# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

import logging as log
import random
import re
from collections import OrderedDict
from copy import deepcopy
from math import ceil, log2
from typing import Dict, List

from topgen import c, lib
from .clocks import Clocks
from .resets import Resets
from reggen.ip_block import IpBlock
from reggen.params import LocalParam, Parameter, RandParameter, MemSizeParameter


def _get_random_data_hex_literal(width):
    """ Fetch 'width' random bits and return them as hex literal"""
    width = int(width)
    literal_str = hex(random.getrandbits(width))
    return literal_str


def _get_random_perm_hex_literal(numel):
    """ Compute a random permutation of 'numel' elements and
    return as packed hex literal"""
    num_elements = int(numel)
    width = int(ceil(log2(num_elements)))
    idx = [x for x in range(num_elements)]
    random.shuffle(idx)
    literal_str = ""
    for k in idx:
        literal_str += format(k, '0' + str(width) + 'b')
    # convert to hex for space efficiency
    literal_str = hex(int(literal_str, 2))
    return literal_str


def elaborate_instances(top, name_to_block: Dict[str, IpBlock]):
    '''Add additional fields to the elements of top['module']

    These elements represent instantiations of IP blocks. This function adds
    extra fields to them to carry across information from the IpBlock objects
    that represent the blocks being instantiated. See elaborate_instance for
    more details of what gets added.

    '''
    # Initialize RNG for compile-time netlist constants.
    random.seed(int(top['rnd_cnst_seed']))

    for instance in top['module']:
        block = name_to_block[instance['type']]
        elaborate_instance(instance, block)


def elaborate_instance(instance, block: IpBlock):
    """Add additional fields to a single instance of a module.

    instance is the instance to be filled in. block is the block that it's
    instantiating.

    Altered fields:
        - param_list (list of parameters for the instance)
        - inter_signal_list (list of inter-module signals)
        - base_addrs (a map from interface name to its base address)

    Removed fields:
        - base_addr (this is reflected in base_addrs)

    """

    # create an empty dict if nothing is there
    if "param_decl" not in instance:
        instance["param_decl"] = {}

    mod_name = instance["name"]
    cc_mod_name = c.Name.from_snake_case(mod_name).as_camel_case()

    # Check to see if all declared parameters exist
    param_decl_accounting = [decl for decl in instance["param_decl"].keys()]

    # param_list
    new_params = []
    for param in block.params.by_name.values():
        if isinstance(param, LocalParam):
            # Remove local parameters.
            continue

        new_param = param.as_dict()

        param_expose = param.expose if isinstance(param, Parameter) else False

        # assign an empty entry if this is not present
        if "memory" not in instance:
            instance["memory"] = {}

        # Check for security-relevant parameters that are not exposed,
        # adding a top-level name.
        if param.name.lower().startswith("sec") and not param_expose:
            log.warning("{} has security-critical parameter {} "
                        "not exposed to top".format(
                            mod_name, param.name))

        # Move special prefixes to the beginnining of the parameter name.
        param_prefixes = ["Sec", "RndCnst", "MemSize"]
        name_top = cc_mod_name + param.name
        for prefix in param_prefixes:
            if not param.name.startswith(prefix):
                continue
            else:
                if param.name == prefix:
                    raise ValueError(f'Module instance {mod_name} has a '
                                     f'parameter {param.name} that is equal '
                                     f'to prefix {prefix}.')

                if re.match(prefix + '[A-Z].+$', param.name):
                    name_top = (prefix + cc_mod_name +
                                param.name[len(prefix):])
                break

        new_param['name_top'] = name_top

        # Generate random bits or permutation, if needed
        if isinstance(param, RandParameter):
            if param.randtype == 'data':
                new_default = _get_random_data_hex_literal(param.randcount)
                # Effective width of the random vector
                randwidth = param.randcount
            else:
                assert param.randtype == 'perm'
                new_default = _get_random_perm_hex_literal(param.randcount)
                # Effective width of the random vector
                randwidth = param.randcount * ceil(log2(param.randcount))

            new_param['default'] = new_default
            new_param['randwidth'] = randwidth

        elif isinstance(param, MemSizeParameter):
            key = param.name[7:].lower()
            # Set the parameter to the specified memory size.
            if key in instance["memory"]:
                new_default = int(instance["memory"][key]["size"], 0)
                new_param['default'] = new_default
            else:
                log.error("Missing memory configuration for "
                          "memory {} in instance {}"
                          .format(key, instance["name"]))

        # if this exposed parameter is listed in the `param_decl` dict,
        # override its default value.
        elif param.name in instance["param_decl"].keys():
            new_param['default'] = instance["param_decl"][param.name]
            # remove the parameter from the accounting dict
            param_decl_accounting.remove(param.name)

        new_params.append(new_param)

    instance["param_list"] = new_params

    # for each module declaration, check to see that the parameter actually exists
    # and can be set
    for decl in param_decl_accounting:
        log.error("{} is not a valid parameter of {} that can be "
                  "set from top level".format(decl, block.name))

    # These objects get added-to in place by code in intermodule.py, so we have
    # to convert and copy them here.
    instance["inter_signal_list"] = [s.as_dict() for s in block.inter_signals]

    # An instance must either have a 'base_addr' address or a 'base_addrs'
    # address, but can't have both.
    base_addrs = instance.get('base_addrs')
    if base_addrs is None:
        if 'base_addr' not in instance:
            log.error('Instance {!r} has neither a base_addr '
                      'nor a base_addrs field.'
                      .format(instance['name']))
        else:
            # If the instance has a base_addr field, make sure that the block
            # has just one device interface.
            if len(block.reg_blocks) != 1:
                log.error('Instance {!r} has a base_addr field but it '
                          'instantiates the block {!r}, which has {} '
                          'device interfaces.'
                          .format(instance['name'],
                                  block.name, len(block.reg_blocks)))
            else:
                if_name = next(iter(block.reg_blocks))
                base_addrs = {if_name: instance['base_addr']}

        # Fill in a bogus base address (we don't have proper error handling, so
        # have to do *something*)
        if base_addrs is None:
            base_addrs = {None: 0}

        instance['base_addrs'] = base_addrs
    else:
        if 'base_addr' in instance:
            log.error('Instance {!r} has both a base_addr '
                      'and a base_addrs field.'
                      .format(instance['name']))

        # Since the instance already has a base_addrs field, make sure that
        # it's got the same set of keys as the name of the interfaces in the
        # block.
        inst_if_names = set(base_addrs.keys())
        block_if_names = set(block.reg_blocks.keys())
        if block_if_names != inst_if_names:
            log.error('Instance {!r} has a base_addrs field with keys {} '
                      'but the block it instantiates ({!r}) has device '
                      'interfaces {}.'
                      .format(instance['name'], inst_if_names,
                              block.name, block_if_names))

    if 'base_addr' in instance:
        del instance['base_addr']


# TODO: Replace this part to be configurable from Hjson or template
predefined_modules = {
    "corei": "rv_core_ibex",
    "cored": "rv_core_ibex"
}


def is_xbar(top, name):
    """Check if the given name is crossbar
    """
    xbars = list(filter(lambda node: node["name"] == name, top["xbar"]))
    if len(xbars) == 0:
        return False, None

    if len(xbars) > 1:
        log.error("Matching crossbar {} is more than one.".format(name))
        raise SystemExit()

    return True, xbars[0]


def xbar_addhost(top, xbar, host):
    """Add host nodes information

    - xbar: bool, true if the host port is from another Xbar
    """
    # Check and fetch host if exists in nodes
    obj = list(filter(lambda node: node["name"] == host, xbar["nodes"]))
    if len(obj) == 0:
        log.warning(
            "host %s doesn't exist in the node list. Using default values" %
            host)
        obj = OrderedDict([
            ("name", host),
            ("clock", xbar['clock']),
            ("reset", xbar['reset']),
            ("type", "host"),
            ("inst_type", ""),
            ("stub", False),
            # The default matches RTL default
            # pipeline_byp is don't care if pipeline is false
            ("pipeline", "true"),
            ("pipeline_byp", "true")
        ])
        xbar["nodes"].append(obj)
        return

    xbar_bool, xbar_h = is_xbar(top, host)
    if xbar_bool:
        log.info("host {} is a crossbar. Nothing to deal with.".format(host))

    obj[0]["xbar"] = xbar_bool

    if 'clock' not in obj[0]:
        obj[0]["clock"] = xbar['clock']

    if 'reset' not in obj[0]:
        obj[0]["reset"] = xbar["reset"]

    obj[0]["stub"] = False
    obj[0]["inst_type"] = predefined_modules[
        host] if host in predefined_modules else ""
    obj[0]["pipeline"] = obj[0]["pipeline"] if "pipeline" in obj[0] else "true"
    obj[0]["pipeline_byp"] = obj[0]["pipeline_byp"] if obj[0][
        "pipeline"] == "true" and "pipeline_byp" in obj[0] else "true"


def process_pipeline_var(node):
    """Add device nodes pipeline / pipeline_byp information

    - Supply a default of true / true if not defined by xbar
    """
    node["pipeline"] = node["pipeline"] if "pipeline" in node else "true"
    node["pipeline_byp"] = node[
        "pipeline_byp"] if "pipeline_byp" in node else "true"


def xbar_adddevice(top: Dict[str, object],
                   name_to_block: Dict[str, IpBlock],
                   xbar: Dict[str, object],
                   other_xbars: List[str],
                   device: str) -> None:
    """Add or amend an entry in xbar['nodes'] to represent the device interface

    - clock: comes from module if exist, use xbar default otherwise
    - reset: comes from module if exist, use xbar default otherwise
    - inst_type: comes from module or memory if exist.
    - base_addr: comes from module or memory, or assume rv_plic?
    - size_byte: comes from module or memory
    - xbar: bool, true if the device port is another xbar
    - stub: There is no backing module / memory, instead a tlul port
            is created and forwarded above the current hierarchy
    """
    device_parts = device.split('.', 1)
    device_base = device_parts[0]
    device_ifname = device_parts[1] if len(device_parts) > 1 else None

    # Try to find a block or memory instance with name device_base. Object
    # names should be unique, so there should never be more than one hit.
    instances = [
        node for node in top["module"] + top["memory"]
        if node['name'] == device_base
    ]
    assert len(instances) <= 1
    inst = instances[0] if instances else None

    # Try to find a node in the crossbar called device. Node names should be
    # unique, so there should never be more than one hit.
    nodes = [
        node for node in xbar['nodes']
        if node['name'] == device
    ]
    assert len(nodes) <= 1
    node = nodes[0] if nodes else None

    log.info("Handling xbar device {} (matches instance? {}; matches node? {})"
             .format(device, inst is not None, node is not None))

    # case 1: another xbar --> check in xbar list
    if node is None and device in other_xbars:
        log.error(
            "Another crossbar %s needs to be specified in the 'nodes' list" %
            device)
        return

    # If there is no module or memory with the right name, this might still be
    # ok: we might be connecting to another crossbar or to a predefined module.
    if inst is None:
        # case 1: Crossbar handling
        if device in other_xbars:
            log.info(
                "device {} in Xbar {} is connected to another Xbar".format(
                    device, xbar["name"]))
            assert node is not None
            node["xbar"] = True
            node["stub"] = False
            process_pipeline_var(node)
            return

        # case 2: predefined_modules (debug_mem, rv_plic)
        # TODO: Find configurable solution not from predefined but from object?
        if device in predefined_modules:
            log.error("device %s shouldn't be host type" % device)

            return

        # case 3: not defined
        # Crossbar check
        log.error("Device %s doesn't exist in 'module', 'memory', predefined, "
                  "or as a node object" % device)
        return

    # If we get here, inst points an instance of some block or memory. It
    # shouldn't point at a crossbar (because that would imply a naming clash)
    assert device_base not in other_xbars
    base_addr, size_byte = lib.get_base_and_size(name_to_block,
                                                 inst, device_ifname)
    addr_range = {"base_addr": hex(base_addr), "size_byte": hex(size_byte)}

    stub = not lib.is_inst(inst)

    if node is None:
        log.error('Cannot connect to {!r} because '
                  'the crossbar defines no node for {!r}.'
                  .format(device, device_base))
        return

    node["inst_type"] = inst["type"]
    node["addr_range"] = [addr_range]
    node["xbar"] = False
    node["stub"] = stub
    process_pipeline_var(node)


def amend_xbar(top: Dict[str, object],
               name_to_block: Dict[str, IpBlock],
               xbar: Dict[str, object]):
    """Amend crossbar informations to the top list

    Amended fields
    - clock: Adopt from module clock if exists
    - inst_type: Module instance some module will be hard-coded
                 the tool searches module list and memory list then put here
    - base_addr: from top["module"]
    - size: from top["module"]
    """
    xbar_list = [x["name"] for x in top["xbar"]]
    if not xbar["name"] in xbar_list:
        log.info(
            "Xbar %s doesn't belong to the top %s. Check if the xbar doesn't need"
            % (xbar["name"], top["name"]))
        return

    topxbar = list(
        filter(lambda node: node["name"] == xbar["name"], top["xbar"]))[0]

    topxbar["connections"] = deepcopy(xbar["connections"])
    if "nodes" in xbar:
        topxbar["nodes"] = deepcopy(xbar["nodes"])
    else:
        topxbar["nodes"] = []

    # xbar primary clock and reset
    topxbar["clock"] = xbar["clock_primary"]
    topxbar["reset"] = xbar["reset_primary"]

    # Build nodes from 'connections'
    device_nodes = set()
    for host, devices in xbar["connections"].items():
        # add host first
        xbar_addhost(top, topxbar, host)

        # add device if doesn't exist
        device_nodes.update(devices)

    other_xbars = [x["name"]
                   for x in top["xbar"]
                   if x["name"] != xbar["name"]]

    log.info(device_nodes)
    for device in device_nodes:
        xbar_adddevice(top, name_to_block, topxbar, other_xbars, device)


def xbar_cross(xbar, xbars):
    """Check if cyclic dependency among xbars

    And gather the address range for device port (to another Xbar)

    @param node_name if not "", the function only search downstream
                     devices starting from the node_name
    @param visited   The nodes it visited to reach this port. If any
                     downstream port from node_name in visited, it means
                     circular path exists. It should be fatal error.
    """
    # Step 1: Visit devices (gather the address range)
    log.info("Processing circular path check for {}".format(xbar["name"]))
    addr = []
    for node in [
            x for x in xbar["nodes"]
            if x["type"] == "device" and "xbar" in x and x["xbar"] is False
    ]:
        addr.extend(node["addr_range"])

    # Step 2: visit xbar device ports
    xbar_nodes = [
        x for x in xbar["nodes"]
        if x["type"] == "device" and "xbar" in x and x["xbar"] is True
    ]

    # Now call function to get the device range
    # the node["name"] is used to find the host_xbar and its connection. The
    # assumption here is that there's only one connection from crossbar A to
    # crossbar B.
    #
    # device_xbar is the crossbar has a device port with name as node["name"].
    # host_xbar is the crossbar has a host port with name as node["name"].
    for node in xbar_nodes:
        xbar_addr = xbar_cross_node(node["name"], xbar, xbars, visited=[])
        node["addr_range"] = xbar_addr


def xbar_cross_node(node_name, device_xbar, xbars, visited=[]):
    # 1. Get the connected xbar
    host_xbars = [x for x in xbars if x["name"] == node_name]
    assert len(host_xbars) == 1
    host_xbar = host_xbars[0]

    log.info("Processing node {} in Xbar {}.".format(node_name,
                                                     device_xbar["name"]))
    result = []  # [(base_addr, size), .. ]
    # Sweep the devices using connections and gather the address.
    # If the device is another xbar, call recursive
    visited.append(host_xbar["name"])
    devices = host_xbar["connections"][device_xbar["name"]]

    for node in host_xbar["nodes"]:
        if not node["name"] in devices:
            continue
        if "xbar" in node and node["xbar"] is True:
            if "addr_range" not in node:
                # Deeper dive into another crossbar
                xbar_addr = xbar_cross_node(node["name"], host_xbar, xbars,
                                            visited)
                node["addr_range"] = xbar_addr

        result.extend(deepcopy(node["addr_range"]))

    visited.pop()

    return result


# find the first instance name of a given type
def _find_module_name(modules, module_type):
    for m in modules:
        if m['type'] == module_type:
            return m['name']

    return None


def extract_clocks(top: OrderedDict):
    '''Add clock exports to top and connections to endpoints

    This function sets up all the clock-related machinery that is needed to
    generate the (templated) clkmgr code. This runs before we load up IP blocks
    with reggen, so can only see top-level configuration.

    '''
    clocks = top['clocks']
    assert isinstance(clocks, Clocks)

    exported_clks = OrderedDict()

    for ep in top['module'] + top['memory'] + top['xbar']:
        clock_connections = OrderedDict()

        # Ensure each module has a default case
        export_if = ep.get('clock_reset_export', [])

        # if no clock group assigned, default is unique
        ep['clock_group'] = 'secure' if 'clock_group' not in ep else ep[
            'clock_group']
        ep_grp = ep['clock_group']

        # end point names and clocks
        ep_name = ep['name']
        ep_clks = []

        group = clocks.groups[ep_grp]

        for port, clk in ep['clock_srcs'].items():
            ep_clks.append(clk)

            name = ''
            hier_name = clocks.hier_paths[group.src]

            if group.src == 'ext':
                # clock comes from top ports
                if clk == 'main':
                    name = "i"
                else:
                    name = "{}_i".format(clk)

            elif group.unique:
                # new unqiue clock name
                name = "{}_{}".format(clk, ep_name)

            else:
                # new group clock name
                name = "{}_{}".format(clk, ep_grp)

            clk_name = "clk_" + name

            # add clock to a particular group
            clk_sig = clocks.add_clock_to_group(group, clk_name, clk)
            clk_sig.add_endpoint(ep_name, port)

            # add clock connections
            clock_connections[port] = hier_name + clk_name

            # clocks for this module are exported
            for intf in export_if:
                log.info("{} export clock name is {}".format(ep_name, name))

                # create dict entry if it does not exit
                if intf not in exported_clks:
                    exported_clks[intf] = OrderedDict()

                # if first time encounter end point, declare
                if ep_name not in exported_clks[intf]:
                    exported_clks[intf][ep_name] = []

                # append clocks
                exported_clks[intf][ep_name].append(name)

        # Add to endpoint structure
        ep['clock_connections'] = clock_connections

    # add entry to top level json
    top['exported_clks'] = exported_clks


def connect_clocks(top, name_to_block: Dict[str, IpBlock]):
    clocks = top['clocks']
    assert isinstance(clocks, Clocks)

    # add entry to inter_module automatically
    clkmgr_name = _find_module_name(top['module'], 'clkmgr')
    external = top['inter_module']['external']
    for intf in top['exported_clks']:
        external[f'{clkmgr_name}.clocks_{intf}'] = f"clks_{intf}"

    typed_clocks = clocks.typed_clocks()

    # Set up intermodule connections for idle clocks. Iterating over
    # hint_names() here ensures that we visit the clocks in the same order as
    # the code that generates the enumeration in clkmgr_pkg.sv: important,
    # since the order that we add entries to clkmgr_idle below gives the index
    # of each hint in the "idle" signal bundle. These *must* match, or we'll
    # have hard-to-debug mis-connections.
    clkmgr_idle = []
    for clk_name in typed_clocks.hint_names().keys():
        sig = typed_clocks.hint_clks[clk_name]
        ep_names = list(set(ep_name for ep_name, ep_port in sig.endpoints))
        if len(ep_names) != 1:
            raise ValueError(f'There are {len(ep_names)} end-points connected '
                             f'to the {sig.name} clock: {ep_names}. Where '
                             f'should the idle signal come from?')
        ep_name = ep_names[0]

        # We've got the name of the endpoint, but that's not enough: we need to
        # find the corresponding IpBlock. To do this, we have to do a (linear)
        # search through top['module'] to find the instance that matches the
        # endpoint, then use that instance's type as a key in name_to_block.
        ep_inst = None
        for inst in top['module']:
            if inst['name'] == ep_name:
                ep_inst = inst
                break
        if ep_inst is None:
            raise ValueError(f'No module instance with name {ep_name}: only '
                             f'modules can have hint clocks. Is this a '
                             f'crossbar or a memory?')

        ip_block = name_to_block[ep_inst['type']]

        # Walk through the clocking items for the block to find the one that
        # defines each of the ports.
        idle_signal = None
        for ep_name, ep_port in sig.endpoints:
            ep_idle = None
            for item in ip_block.clocking.items:
                if item.clock != ep_port:
                    continue
                if item.idle is None:
                    raise ValueError(f'Cannot connect the {sig.name} clock to '
                                     f'port {ep_port} of {ep_name}. This is a '
                                     f'hint clock, but the clocking item on '
                                     f'the module defines no idle signal.')
                if idle_signal is not None and item.idle != idle_signal:
                    raise ValueError(f'Cannot connect the {sig.name} clock to '
                                     f'port {ep_port} of {ep_name}. We '
                                     f'already have a connection to another '
                                     f'clock signal which has an assocated '
                                     f'idle signal called {idle_signal}, but '
                                     f'this clocking item has an idle signal '
                                     f'called {item.idle}.')
                ep_idle = item.idle
                break
            if ep_idle is None:
                raise ValueError(f'Cannot connect the {sig.name} clock to '
                                 f'port {ep_port} of {ep_name}: no such '
                                 f'clocking item.')
            idle_signal = ep_idle
        assert idle_signal is not None

        # At this point, there's a slight problem: we use names like "idle_o"
        # for signals in the hjson, but the inter-module list expects names
        # like "idle". Drop the trailing "_o".
        if not idle_signal.endswith('_o'):
            raise ValueError(f'Idle signal for {ep_port} of {ep_name} is '
                             f'{idle_signal}, which is missing the expected '
                             f'"_o" suffix.')
        idle_signal = idle_signal[:-2]

        clkmgr_idle.append(ep_name + '.' + idle_signal)

    top['inter_module']['connect']['{}.idle'.format(clkmgr_name)] = clkmgr_idle


def amend_resets(top, name_to_block):
    """Generate exported reset structure and automatically connect to
       intermodule.

       Also iterate through and determine need for shadowed reset and
       domains.
    """

    top_resets = Resets(top['resets'], top['clocks'])
    rstmgr_name = _find_module_name(top['module'], 'rstmgr')

    # Generate exported reset list
    exported_rsts = OrderedDict()
    for module in top["module"]:

        block = name_to_block[module['type']]
        block_clock = block.get_primary_clock()
        primary_reset = module['reset_connections'][block_clock.reset]

        # shadowed determination
        if block.has_shadowed_reg():
            top_resets.mark_reset_shadowed(primary_reset)

        # domain determination
        if module['domain']:
            for r in block.clocking.items:
                if r.reset:
                    reset = module['reset_connections'][r.reset]
                    top_resets.add_reset_domain(reset, module['domain'])

        # This code is here to ensure if amend_clocks/resets switched order
        # everything would still work
        export_if = module.get('clock_reset_export', [])

        # There may be multiple export interfaces
        for intf in export_if:
            # create dict entry if it does not exit
            if intf not in exported_rsts:
                exported_rsts[intf] = OrderedDict()

            # grab directly from reset_connections definition
            rsts = [rst for rst in module['reset_connections'].values()]
            exported_rsts[intf][module['name']] = rsts

    # add entry to top level json
    top['exported_rsts'] = exported_rsts

    # add entry to inter_module automatically
    for intf in top['exported_rsts']:
        top['inter_module']['external']['{}.resets_{}'.format(
            rstmgr_name, intf)] = "rsts_{}".format(intf)

    # reset class objects
    top["resets"] = top_resets


def ensure_interrupt_modules(top: OrderedDict, name_to_block: Dict[str, IpBlock]):
    '''Populate top['interrupt_module'] if necessary

    Do this by adding each module in top['modules'] that defines at least one
    interrupt.

    '''
    if 'interrupt_module' in top:
        return

    modules = []
    for module in top['module']:
        block = name_to_block[module['type']]
        if block.interrupts:
            modules.append(module['name'])

    top['interrupt_module'] = modules


def amend_interrupt(top: OrderedDict, name_to_block: Dict[str, IpBlock]):
    """Check interrupt_module if exists, or just use all modules
    """
    ensure_interrupt_modules(top, name_to_block)

    if "interrupt" not in top or top["interrupt"] == "":
        top["interrupt"] = []

    for m in top["interrupt_module"]:
        ips = list(filter(lambda module: module["name"] == m, top["module"]))
        if len(ips) == 0:
            log.warning(
                "Cannot find IP %s which is used in the interrupt_module" % m)
            continue

        ip = ips[0]
        block = name_to_block[ip['type']]

        log.info("Adding interrupts from module %s" % ip["name"])
        for signal in block.interrupts:
            sig_dict = signal.as_nwt_dict('interrupt')
            qual = lib.add_module_prefix_to_signal(sig_dict,
                                                   module=m.lower())
            top["interrupt"].append(qual)


def ensure_alert_modules(top: OrderedDict, name_to_block: Dict[str, IpBlock]):
    '''Populate top['alert_module'] if necessary

    Do this by adding each module in top['modules'] that defines at least one
    alert.

    '''
    if 'alert_module' in top:
        return

    modules = []
    for module in top['module']:
        block = name_to_block[module['type']]
        if block.alerts:
            modules.append(module['name'])

    top['alert_module'] = modules


def amend_alert(top: OrderedDict, name_to_block: Dict[str, IpBlock]):
    """Check interrupt_module if exists, or just use all modules
    """
    ensure_alert_modules(top, name_to_block)

    if "alert" not in top or top["alert"] == "":
        top["alert"] = []

    for m in top["alert_module"]:
        ips = list(filter(lambda module: module["name"] == m, top["module"]))
        if len(ips) == 0:
            log.warning("Cannot find IP %s which is used in the alert_module" %
                        m)
            continue

        ip = ips[0]
        block = name_to_block[ip['type']]

        log.info("Adding alert from module %s" % ip["name"])
        # Note: we assume that all alerts are asynchronous in order to make the
        # design homogeneous and more amenable to DV automation and synthesis
        # constraint scripting.
        for alert in block.alerts:
            alert_dict = alert.as_nwt_dict('alert')
            alert_dict['async'] = '1'
            qual_sig = lib.add_module_prefix_to_signal(alert_dict,
                                                       module=m.lower())
            top["alert"].append(qual_sig)


def amend_wkup(topcfg: OrderedDict, name_to_block: Dict[str, IpBlock]):

    pwrmgr_name = _find_module_name(topcfg['module'], 'pwrmgr')

    if "wakeups" not in topcfg or topcfg["wakeups"] == "":
        topcfg["wakeups"] = []

    # create list of wakeup signals
    for m in topcfg["module"]:
        log.info("Adding wakeup from module %s" % m["name"])
        block = name_to_block[m['type']]
        for signal in block.wakeups:
            log.info("Adding signal %s" % signal.name)
            topcfg["wakeups"].append({
                'name': signal.name,
                'width': str(signal.bits.width()),
                'module': m["name"]
            })

    # add wakeup signals to pwrmgr connections
    signal_names = [
        "{}.{}".format(s["module"].lower(), s["name"].lower())
        for s in topcfg["wakeups"]
    ]

    topcfg["inter_module"]["connect"]["{}.wakeups".format(pwrmgr_name)] = signal_names
    log.info("Intermodule signals: {}".format(
        topcfg["inter_module"]["connect"]))


# Handle reset requests from modules
def amend_reset_request(topcfg: OrderedDict,
                        name_to_block: Dict[str, IpBlock]):

    pwrmgr_name = _find_module_name(topcfg['module'], 'pwrmgr')

    if "reset_requests" not in topcfg or topcfg["reset_requests"] == "":
        topcfg["reset_requests"] = []

    # create list of reset signals
    for m in topcfg["module"]:
        log.info("Adding reset requests from module %s" % m["name"])
        block = name_to_block[m['type']]
        for signal in block.reset_requests:
            log.info("Adding signal %s" % signal.name)
            topcfg["reset_requests"].append({
                'name': signal.name,
                'width': str(signal.bits.width()),
                'module': m["name"]
            })

    # add reset requests to pwrmgr connections
    signal_names = [
        "{}.{}".format(s["module"].lower(), s["name"].lower())
        for s in topcfg["reset_requests"]
    ]

    topcfg["inter_module"]["connect"]["{}.rstreqs".format(pwrmgr_name)] = signal_names
    log.info("Intermodule signals: {}".format(
        topcfg["inter_module"]["connect"]))


def append_io_signal(temp: Dict, sig_inst: Dict) -> None:
    '''Appends the signal to the correct list'''
    if sig_inst['type'] == 'inout':
        temp['inouts'].append(sig_inst)
    if sig_inst['type'] == 'input':
        temp['inputs'].append(sig_inst)
    if sig_inst['type'] == 'output':
        temp['outputs'].append(sig_inst)


def get_index_and_incr(ctrs: Dict, connection: str, io_dir: str) -> Dict:
    '''Get correct index counter and increment'''

    if connection != 'muxed':
        connection = 'dedicated'

    if io_dir in 'inout':
        result = ctrs[connection]['inouts']
        ctrs[connection]['inouts'] += 1
    elif connection == 'muxed':
        # For MIOs, the input/output arrays differ in RTL
        # I.e., the input array contains {inputs, inouts}, whereas
        # the output array contains {outputs, inouts}.
        if io_dir == 'input':
            result = ctrs[connection]['inputs'] + ctrs[connection]['inouts']
            ctrs[connection]['inputs'] += 1
        elif io_dir == 'output':
            result = ctrs[connection]['outputs'] + ctrs[connection]['inouts']
            ctrs[connection]['outputs'] += 1
        else:
            assert(0)  # should not happen
    else:
        # For DIOs, the input/output arrays are identical in terms of index layout.
        # Unused inputs are left unconnected and unused outputs are tied off.
        if io_dir == 'input':
            result = ctrs[connection]['inputs'] + ctrs[connection]['inouts']
            ctrs[connection]['inputs'] += 1
        elif io_dir == 'output':
            result = (ctrs[connection]['outputs'] +
                      ctrs[connection]['inouts'] +
                      ctrs[connection]['inputs'])
            ctrs[connection]['outputs'] += 1
        else:
            assert(0)  # should not happen

    return result


def amend_pinmux_io(top: Dict, name_to_block: Dict[str, IpBlock]):
    """ Process pinmux/pinout configuration and assign available IOs
    """
    pinmux = top['pinmux']
    pinout = top['pinout']
    targets = top['targets']

    temp = {}
    temp['inouts'] = []
    temp['inputs'] = []
    temp['outputs'] = []

    for sig in pinmux['signals']:
        # Get the signal information from the IP block type of this instance/
        mod_name = sig['instance']
        m = lib.get_module_by_name(top, mod_name)

        if m is None:
            raise SystemExit("Module {} is not searchable.".format(mod_name))

        block = name_to_block[m['type']]

        # If the signal is explicitly named.
        if sig['port'] != '':

            # If this is a bus signal with explicit indexes.
            if '[' in sig['port']:
                name_split = sig['port'].split('[')
                sig_name = name_split[0]
                idx = int(name_split[1][:-1])
            else:
                idx = -1
                sig_name = sig['port']

            sig_inst = deepcopy(block.get_signal_by_name_as_dict(sig_name))

            if idx >= 0 and idx >= sig_inst['width']:
                raise SystemExit("Index {} is out of bounds for signal {}"
                                 " with width {}.".format(idx, sig_name, sig_inst['width']))
            if idx == -1 and sig_inst['width'] != 1:
                raise SystemExit("Bus signal {} requires an index.".format(sig_name))

            # If we got this far we know that the signal is valid and exists.
            # Augment this signal instance with additional information.
            sig_inst.update({'idx': idx,
                             'pad': sig['pad'],
                             'attr': sig['attr'],
                             'connection': sig['connection'],
                             'desc': sig['desc']})
            sig_inst['name'] = mod_name + '_' + sig_inst['name']
            append_io_signal(temp, sig_inst)

        # Otherwise the name is a wildcard for selecting all available IO signals
        # of this block and we need to extract them here one by one signals here.
        else:
            sig_list = deepcopy(block.get_signals_as_list_of_dicts())

            for sig_inst in sig_list:
                # If this is a multibit signal, unroll the bus and
                # generate a single bit IO signal entry for each one.
                if sig_inst['width'] > 1:
                    for idx in range(sig_inst['width']):
                        sig_inst_copy = deepcopy(sig_inst)
                        sig_inst_copy.update({'idx': idx,
                                              'pad': sig['pad'],
                                              'attr': sig['attr'],
                                              'connection': sig['connection'],
                                              'desc': sig['desc']})
                        sig_inst_copy['name'] = sig['instance'] + '_' + sig_inst_copy['name']
                        append_io_signal(temp, sig_inst_copy)
                else:
                    sig_inst.update({'idx': -1,
                                     'pad': sig['pad'],
                                     'attr': sig['attr'],
                                     'connection': sig['connection'],
                                     'desc': sig['desc']})
                    sig_inst['name'] = sig['instance'] + '_' + sig_inst['name']
                    append_io_signal(temp, sig_inst)

    # Now that we've collected all input and output signals,
    # we can go through once again and stack them into one unified
    # list, and calculate MIO/DIO global indices.
    pinmux['ios'] = (temp['inouts'] +
                     temp['inputs'] +
                     temp['outputs'])

    # Remember these counts to facilitate the RTL generation
    pinmux['io_counts'] = {'dedicated': {'inouts': 0, 'inputs': 0, 'outputs': 0, 'pads': 0},
                           'muxed': {'inouts': 0, 'inputs': 0, 'outputs': 0, 'pads': 0}}

    for sig in pinmux['ios']:
        glob_idx = get_index_and_incr(pinmux['io_counts'], sig['connection'], sig['type'])
        sig['glob_idx'] = glob_idx

    # Calculate global indices for pads.
    j = k = 0
    for pad in pinout['pads']:
        if pad['connection'] == 'muxed':
            pad['idx'] = j
            j += 1
        else:
            pad['idx'] = k
            k += 1
    pinmux['io_counts']['muxed']['pads'] = j
    pinmux['io_counts']['dedicated']['pads'] = k

    # For each target configuration, calculate the special signal indices.
    known_muxed_pads = {}
    for pad in pinout['pads']:
        if pad['connection'] == 'muxed':
            known_muxed_pads[pad['name']] = pad

    known_mapped_dio_pads = {}
    for sig in pinmux['ios']:
        if sig['connection'] in ['muxed', 'manual']:
            continue
        if sig['pad'] in known_mapped_dio_pads:
            raise SystemExit('Cannot have multiple IOs mapped to the same DIO pad {}'
                             .format(sig['pad']))
        known_mapped_dio_pads[sig['pad']] = sig

    for target in targets:
        for entry in target['pinmux']['special_signals']:
            # If this is a muxed pad, the resolution is
            # straightforward. I.e., we just assign the MIO index.
            if entry['pad'] in known_muxed_pads:
                entry['idx'] = known_muxed_pads[entry['pad']]['idx']
            # Otherwise we need to find out which DIO this pad is mapped to.
            # Note that we can't have special_signals that are manual, since
            # there needs to exist a DIO connection.
            elif entry['pad'] in known_mapped_dio_pads:
                # This index refers to the stacked {dio, mio} array
                # on the chip-level, hence we have to add the amount of MIO pads.
                idx = (known_mapped_dio_pads[entry['pad']]['glob_idx'] +
                       pinmux['io_counts']['muxed']['pads'])
                entry['idx'] = idx
            else:
                assert(0)  # Entry should be guaranteed to exist at this point


def merge_top(topcfg: OrderedDict,
              name_to_block: Dict[str, IpBlock],
              xbarobjs: OrderedDict) -> OrderedDict:

    # Combine ip cfg into topcfg
    elaborate_instances(topcfg, name_to_block)

    # Create clock connections for each block
    # Assign clocks into appropriate groups
    # Note, elaborate_instances references clock information to establish async handling
    # as part of alerts.
    # amend_clocks(topcfg)

    # Combine the wakeups
    amend_wkup(topcfg, name_to_block)
    amend_reset_request(topcfg, name_to_block)

    # Combine the interrupt (should be processed prior to xbar)
    amend_interrupt(topcfg, name_to_block)

    # Combine the alert (should be processed prior to xbar)
    amend_alert(topcfg, name_to_block)

    # Creates input/output list in the pinmux
    log.info("Processing PINMUX")
    amend_pinmux_io(topcfg, name_to_block)

    # Combine xbar into topcfg
    for xbar in xbarobjs:
        amend_xbar(topcfg, name_to_block, xbar)

    # 2nd phase of xbar (gathering the devices address range)
    for xbar in topcfg["xbar"]:
        xbar_cross(xbar, topcfg["xbar"])

    # Add path names to declared resets.
    # Declare structure for exported resets.
    amend_resets(topcfg, name_to_block)

    # remove unwanted fields 'debug_mem_base_addr'
    topcfg.pop('debug_mem_base_addr', None)

    return topcfg
