# Copyright (c) 2012-2013,2019 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder.  You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#####################################################################
#
# System visualization using DOT
#
# While config.ini and config.json provide an almost complete listing
# of a system's components and connectivity, they lack a birds-eye
# view. The output generated by do_dot() is a DOT-based figure (as a
# pdf and an editable svg file) and its source dot code. Nodes are
# components, and edges represent the memory hierarchy: the edges are
# directed, from a requestor to responder. Initially all nodes are
# generated, and then all edges are added. do_dot should be called
# with the top-most SimObject (namely root but not necessarily), the
# output folder and the output dot source filename. From the given
# node, both processes (node and edge creation) is performed
# recursivly, traversing all children of the given root.
#
# pydot is required. When missing, no output will be generated.
#
#####################################################################

import m5, os, re
from m5.SimObject import isRoot, isSimObjectVector
from m5.params import PortRef, isNullPointer
from m5.util import warn

try:
    import pydot
except:
    pydot = False


def simnode_children(simNode):
    for child in simNode._children.values():
        if isNullPointer(child):
            continue
        if isSimObjectVector(child):
            for obj in child:
                if not isNullPointer(obj):
                    yield obj
        else:
            yield child


# need to create all nodes (components) before creating edges (memory channels)
def dot_create_nodes(simNode, callgraph):
    if isRoot(simNode):
        label = "root"
    else:
        label = simNode._name
    full_path = re.sub("\.", "_", simNode.path())
    # add class name under the label
    label = '"' + label + " \\n: " + simNode.__class__.__name__ + '"'

    # each component is a sub-graph (cluster)
    cluster = dot_create_cluster(simNode, full_path, label)

    # create nodes per port
    for port_name in simNode._ports.keys():
        port = simNode._port_refs.get(port_name, None)
        if port != None:
            full_port_name = full_path + "_" + port_name
            port_node = dot_create_node(simNode, full_port_name, port_name)
            cluster.add_node(port_node)

    # recurse to children
    for child in simnode_children(simNode):
        dot_create_nodes(child, cluster)

    callgraph.add_subgraph(cluster)


# create all edges according to memory hierarchy
def dot_create_edges(simNode, callgraph):
    for port_name in simNode._ports.keys():
        port = simNode._port_refs.get(port_name, None)
        if port != None:
            full_path = re.sub("\.", "_", simNode.path())
            full_port_name = full_path + "_" + port_name
            port_node = dot_create_node(simNode, full_port_name, port_name)
            # create edges
            if isinstance(port, PortRef):
                if port.peer:
                    dot_add_edge(simNode, callgraph, full_port_name, port)
            else:
                for p in port.elements:
                    if p.peer:
                        dot_add_edge(simNode, callgraph, full_port_name, p)

    # recurse to children
    for child in simnode_children(simNode):
        dot_create_edges(child, callgraph)


def dot_add_edge(simNode, callgraph, full_port_name, port):
    peer = port.peer
    full_peer_path = re.sub("\.", "_", peer.simobj.path())
    full_peer_port_name = full_peer_path + "_" + peer.name

    # Each edge is encountered twice, once for each peer. We only want one
    # edge, so we'll arbitrarily chose which peer "wins" based on their names.
    if full_peer_port_name < full_port_name:
        dir_type = {
            (False, False): "both",
            (True, False): "forward",
            (False, True): "back",
            (True, True): "none",
        }[(port.is_source, peer.is_source)]
        edge = pydot.Edge(full_port_name, full_peer_port_name, dir=dir_type)
        callgraph.add_edge(edge)


def dot_create_cluster(simNode, full_path, label):
    # get the parameter values of the node and use them as a tooltip
    ini_strings = []
    for param in sorted(simNode._params.keys()):
        value = simNode._values.get(param)
        if value != None:
            # parameter name = value in HTML friendly format
            ini_strings.append(
                str(param) + "&#61;" + simNode._values[param].ini_str()
            )
    # join all the parameters with an HTML newline
    # Pydot limit line length to 16384.
    # Account for the quotes added later around the tooltip string
    tooltip = "&#10;\\".join(ini_strings)
    max_tooltip_length = 16384 - 2
    if len(tooltip) > max_tooltip_length:
        truncated = "... (truncated)"
        tooltip = tooltip[: max_tooltip_length - len(truncated)] + truncated

    return pydot.Cluster(
        full_path,
        shape="box",
        label=label,
        tooltip='"' + tooltip + '"',
        style='"rounded, filled"',
        color="#000000",
        fillcolor=dot_gen_colour(simNode),
        fontname="Arial",
        fontsize="14",
        fontcolor="#000000",
    )


def dot_create_node(simNode, full_path, label):
    return pydot.Node(
        full_path,
        shape="box",
        label=label,
        style='"rounded, filled"',
        color="#000000",
        fillcolor=dot_gen_colour(simNode, True),
        fontname="Arial",
        fontsize="14",
        fontcolor="#000000",
    )


# an enumerator for different kinds of node types, at the moment we
# discern the majority of node types, with the caches being the
# notable exception
class NodeType:
    SYS = 0
    CPU = 1
    XBAR = 2
    MEM = 3
    DEV = 4
    OTHER = 5


# based on the sim object, determine the node type
def get_node_type(simNode):
    if isinstance(simNode, m5.objects.System):
        return NodeType.SYS
    # NULL ISA has no BaseCPU or PioDevice, so check if these names
    # exists before using them
    elif "BaseCPU" in dir(m5.objects) and isinstance(
        simNode, m5.objects.BaseCPU
    ):
        return NodeType.CPU
    elif "PioDevice" in dir(m5.objects) and isinstance(
        simNode, m5.objects.PioDevice
    ):
        return NodeType.DEV
    elif isinstance(simNode, m5.objects.BaseXBar):
        return NodeType.XBAR
    elif isinstance(simNode, m5.objects.AbstractMemory):
        return NodeType.MEM
    else:
        return NodeType.OTHER


# based on the node type, determine the colour as an RGB tuple, the
# palette is rather arbitrary at this point (some coherent natural
# tones), and someone that feels artistic should probably have a look
def get_type_colour(nodeType):
    if nodeType == NodeType.SYS:
        return (228, 231, 235)
    elif nodeType == NodeType.CPU:
        return (187, 198, 217)
    elif nodeType == NodeType.XBAR:
        return (111, 121, 140)
    elif nodeType == NodeType.MEM:
        return (94, 89, 88)
    elif nodeType == NodeType.DEV:
        return (199, 167, 147)
    elif nodeType == NodeType.OTHER:
        # use a relatively gray shade
        return (186, 182, 174)


# generate colour for a node, either corresponding to a sim object or a
# port
def dot_gen_colour(simNode, isPort=False):
    # determine the type of the current node, and also its parent, if
    # the node is not the same type as the parent then we use the base
    # colour for its type
    node_type = get_node_type(simNode)
    if simNode._parent:
        parent_type = get_node_type(simNode._parent)
    else:
        parent_type = NodeType.OTHER

    # if this node is the same type as the parent, then scale the
    # colour based on the depth such that the deeper levels in the
    # hierarchy get darker colours
    if node_type == parent_type:
        # start out with a depth of zero
        depth = 0
        parent = simNode._parent
        # find the closes parent that is not the same type
        while parent and get_node_type(parent) == parent_type:
            depth = depth + 1
            parent = parent._parent
        node_colour = get_type_colour(parent_type)
        # slightly arbitrary, but assume that the depth is less than
        # five levels
        r, g, b = map(lambda x: x * max(1 - depth / 7.0, 0.3), node_colour)
    else:
        node_colour = get_type_colour(node_type)
        r, g, b = node_colour

    # if we are colouring a port, then make it a slightly darker shade
    # than the node that encapsulates it, once again use a magic constant
    if isPort:
        r, g, b = map(lambda x: 0.8 * x, (r, g, b))

    return dot_rgb_to_html(r, g, b)


def dot_rgb_to_html(r, g, b):
    return f"#{int(r):02x}{int(g):02x}{int(b):02x}"


# We need to create all of the clock domains. We abuse the alpha channel to get
# the correct domain colouring.
def dot_add_clk_domain(c_dom, v_dom):
    label = '"' + str(c_dom) + "\ :\ " + str(v_dom) + '"'
    label = re.sub("\.", "_", str(label))
    full_path = re.sub("\.", "_", str(c_dom))
    return pydot.Cluster(
        full_path,
        shape="box",
        label=label,
        style='"rounded, filled, dashed"',
        color="#000000",
        fillcolor="#AFC8AF8F",
        fontname="Arial",
        fontsize="14",
        fontcolor="#000000",
    )


def dot_create_dvfs_nodes(simNode, callgraph, domain=None):
    if isRoot(simNode):
        label = "root"
    else:
        label = simNode._name
    full_path = re.sub("\.", "_", simNode.path())
    # add class name under the label
    label = '"' + label + " \\n: " + simNode.__class__.__name__ + '"'

    # each component is a sub-graph (cluster)
    cluster = dot_create_cluster(simNode, full_path, label)

    # create nodes per port
    for port_name in simNode._ports.keys():
        port = simNode._port_refs.get(port_name, None)
        if port != None:
            full_port_name = full_path + "_" + port_name
            port_node = dot_create_node(simNode, full_port_name, port_name)
            cluster.add_node(port_node)

    # Dictionary of DVFS domains
    dvfs_domains = {}

    # recurse to children
    for child in simnode_children(simNode):
        try:
            c_dom = child.__getattr__("clk_domain")
            v_dom = c_dom.__getattr__("voltage_domain")
        except AttributeError:
            # Just re-use the domain from above
            c_dom = domain
            v_dom = c_dom.__getattr__("voltage_domain")
            pass

        if c_dom == domain or c_dom == None:
            dot_create_dvfs_nodes(child, cluster, domain)
        else:
            if c_dom not in dvfs_domains:
                dvfs_cluster = dot_add_clk_domain(c_dom, v_dom)
                dvfs_domains[c_dom] = dvfs_cluster
            else:
                dvfs_cluster = dvfs_domains[c_dom]
            dot_create_dvfs_nodes(child, dvfs_cluster, c_dom)

    for key in dvfs_domains:
        cluster.add_subgraph(dvfs_domains[key])

    callgraph.add_subgraph(cluster)


def do_dot(root, outdir, dotFilename):
    if not pydot:
        warn(
            "No dot file generated. "
            + "Please install pydot to generate the dot file and pdf."
        )
        return
    # * use ranksep > 1.0 for for vertical separation between nodes
    # especially useful if you need to annotate edges using e.g. visio
    # which accepts svg format
    # * no need for hoizontal separation as nothing moves horizonally
    callgraph = pydot.Dot(graph_type="digraph", ranksep="1.3")
    dot_create_nodes(root, callgraph)
    dot_create_edges(root, callgraph)
    dot_filename = os.path.join(outdir, dotFilename)
    callgraph.write(dot_filename)
    try:
        # dot crashes if the figure is extremely wide.
        # So avoid terminating simulation unnecessarily
        callgraph.write_svg(dot_filename + ".svg")
        callgraph.write_pdf(dot_filename + ".pdf")
    except:
        warn("failed to generate dot output from %s", dot_filename)


def do_dvfs_dot(root, outdir, dotFilename):
    if not pydot:
        warn(
            "No dot file generated. "
            + "Please install pydot to generate the dot file and pdf."
        )
        return

    # There is a chance that we are unable to resolve the clock or
    # voltage domains. If so, we fail silently.
    try:
        dvfsgraph = pydot.Dot(graph_type="digraph", ranksep="1.3")
        dot_create_dvfs_nodes(root, dvfsgraph)
        dot_create_edges(root, dvfsgraph)
        dot_filename = os.path.join(outdir, dotFilename)
        dvfsgraph.write(dot_filename)
    except:
        warn("Failed to generate dot graph for DVFS domains")
        return

    try:
        # dot crashes if the figure is extremely wide.
        # So avoid terminating simulation unnecessarily
        dvfsgraph.write_svg(dot_filename + ".svg")
        dvfsgraph.write_pdf(dot_filename + ".pdf")
    except:
        warn("failed to generate dot output from %s", dot_filename)
