Exemplo n.º 1
0
def autoconnect_xbar(topcfg: OrderedDict, xbar: OrderedDict):
    ports = [x for x in xbar["nodes"] if x["type"] in ["host", "device"]]
    for port in ports:
        if port["xbar"]:
            if port["type"] == "host":
                # Skip as device will add connection
                continue

            # Device port adds signal
            add_intermodule_connection(obj=topcfg,
                                       req_m=xbar["name"],
                                       req_s="tl_%s" % port["name"],
                                       rsp_m=port["name"],
                                       rsp_s="tl_%s" % xbar["name"])
            continue  # xbar port case

        # check if name exists in ["module", "memory"]
        ips = [
            x for x in topcfg["module"] + topcfg["memory"]
            if x["name"] == port["name"] and lib.is_inst(x)
        ]

        assert len(ips) <= 1

        if len(ips) == 0:
            # if not in module, memory, should be existed in top or ext field
            module_key = "{}.tl_{}".format(xbar["name"], port["name"])
            if module_key not in topcfg["inter_module"]["top"] + list(
                    topcfg["inter_module"]["external"].keys()):
                log.error("Inter-module key {} cannot be found in module, "
                          "memory, top, or external lists.".format(module_key))
            continue

        ip = ips[0]
        inter_signal_list = ip['inter_signal_list']

        # get the port name
        def get_signame(act: str) -> OrderedDict:
            ims = [
                x for x in inter_signal_list
                if (x.get('package') == 'tlul_pkg' and
                    x['struct'] == 'tl' and
                    x['act'] == act)
            ]
            return ims

        if port["type"] == "device":
            ims = get_signame("rsp")
        else:  # host type
            ims = get_signame("req")

        assert len(ims) == 1
        sig_name = ims[0]["name"]

        add_intermodule_connection(obj=topcfg,
                                   req_m=port["name"],
                                   req_s=sig_name,
                                   rsp_m=xbar["name"],
                                   rsp_s="tl_%s" % port["name"])
        continue  # len() == 1
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
def xbar_adddevice(top, xbar, device):
    """Add device nodes information

    - 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
    """
    deviceobj = list(
        filter(lambda node: node["name"] == device,
               top["module"] + top["memory"]))
    nodeobj = list(filter(lambda node: node["name"] == device, xbar["nodes"]))

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

    # case 1: another xbar --> check in xbar list
    log.info("Handling xbar device {}, devlen {}, nodelen {}".format(
        device, len(deviceobj), len(nodeobj)))
    if device in xbar_list and len(nodeobj) == 0:
        log.error(
            "Another crossbar %s needs to be specified in the 'nodes' list" %
            device)
        return

    if len(deviceobj) == 0:
        # doesn't exist,

        # case 1: Crossbar handling
        if device in xbar_list:
            log.info(
                "device {} in Xbar {} is connected to another Xbar".format(
                    device, xbar["name"]))
            assert len(nodeobj) == 1
            nodeobj[0]["xbar"] = True
            nodeobj[0]["stub"] = False
            process_pipeline_var(nodeobj[0])
            return

        # case 2: predefined_modules (debug_mem, rv_plic)
        # TODO: Find configurable solution not from predefined but from object?
        if device in predefined_modules:
            if device == "debug_mem":
                if len(nodeobj) == 0:
                    # Add new debug_mem
                    xbar["nodes"].append({
                        "name": "debug_mem",
                        "type": "device",
                        "clock": xbar['clock'],
                        "reset": xbar['reset'],
                        "inst_type": predefined_modules["debug_mem"],
                        "addr_range": [OrderedDict([
                            ("base_addr", top["debug_mem_base_addr"]),
                            ("size_byte", "0x1000"),
                        ])],
                        "xbar": False,
                        "stub": False,
                        "pipeline": "true",
                        "pipeline_byp": "true"
                    })  # yapf: disable
                else:
                    # Update if exists
                    node = nodeobj[0]
                    node["inst_type"] = predefined_modules["debug_mem"]
                    node["addr_range"] = [
                        OrderedDict([("base_addr", top["debug_mem_base_addr"]),
                                     ("size_byte", "0x1000")])
                    ]
                    node["xbar"] = False
                    node["stub"] = False
                    process_pipeline_var(node)
            else:
                log.error("device %s shouldn't be host type" % device)
                return
        # case 3: not defined
        else:
            # Crossbar check
            log.error("""
            Device %s doesn't exist in 'module', 'memory', predefined,
            or as a node object
            """ % device)

            return

    # Search object from module or memory
    elif len(nodeobj) == 0:
        # found in module or memory but node object doesn't exist.
        xbar["nodes"].append({
            "name": device,
            "type": "device",
            "clock": deviceobj[0]["clock"],
            "reset": deviceobj[0]["reset"],
            "inst_type": deviceobj[0]["type"],
            "addr_range": [OrderedDict([
                ("base_addr", deviceobj[0]["base_addr"]),
                ("size_byte", deviceobj[0]["size"])])],
            "pipeline": "true",
            "pipeline_byp": "true",
            "xbar": True if device in xbar_list else False,
            "stub": not lib.is_inst(deviceobj[0])
        })  # yapf: disable

    else:
        # found and exist in the nodes too
        node = nodeobj[0]
        node["inst_type"] = deviceobj[0]["type"]
        node["addr_range"] = [
            OrderedDict([("base_addr", deviceobj[0]["base_addr"]),
                         ("size_byte", deviceobj[0]["size"])])
        ]
        node["xbar"] = True if device in xbar_list else False
        node["stub"] = not lib.is_inst(deviceobj[0])
        process_pipeline_var(node)
Exemplo n.º 4
0
def autoconnect_xbar(topcfg: OrderedDict, name_to_block: Dict[str, IpBlock],
                     xbar: OrderedDict) -> None:
    # The crossbar is connecting to modules and memories in topcfg, plus
    # possible external connections. Make indices for the modules and memories
    # for quick lookup and add some assertions to make sure no name appears in
    # multiple places.
    name_to_module = {}
    for mod in topcfg['module']:
        assert mod['name'] not in name_to_module
        if lib.is_inst(mod):
            name_to_module[mod['name']] = mod

    name_to_memory = {}
    for mem in topcfg['memory']:
        assert mem['name'] not in name_to_memory
        if lib.is_inst(mem):
            name_to_memory[mem['name']] = mem

    # The names of modules and memories should be disjoint
    assert not (set(name_to_module.keys()) & set(name_to_memory.keys()))

    external_names = (set(topcfg['inter_module']['top'])
                      | set(topcfg["inter_module"]["external"].keys()))

    ports = [x for x in xbar["nodes"] if x["type"] in ["host", "device"]]
    for port in ports:
        # Here, we expect port_name to either be a single identifier (in which
        # case, it's taken as the name of some module or memory) to be a dotted
        # pair MOD.INAME where MOD is the name of some module and INAME is the
        # associated interface name.
        name_parts = port['name'].split('.', 1)
        port_base = name_parts[0]
        port_iname = name_parts[1] if len(name_parts) > 1 else None
        esc_name = port['name'].replace('.', '__')

        if port["xbar"]:
            if port_iname is not None:
                log.error(
                    'A crossbar connection may not '
                    'have a target of the form MOD.INAME (saw {!r})'.format(
                        port['name']))
                continue

            if port["type"] == "host":
                # Skip as device will add connection
                continue

            # Device port adds signal
            add_intermodule_connection(obj=topcfg,
                                       req_m=xbar["name"],
                                       req_s="tl_" + esc_name,
                                       rsp_m=esc_name,
                                       rsp_s="tl_" + xbar["name"])
            continue  # xbar port case

        port_mod = name_to_module.get(port_base)
        port_mem = name_to_memory.get(port_base)
        assert port_mod is None or port_mem is None

        if not (port_mod or port_mem):
            # if not in module, memory, should be existed in top or ext field
            module_key = "{}.tl_{}".format(xbar["name"], esc_name)
            if module_key not in external_names:
                log.error("Inter-module key {} cannot be found in module, "
                          "memory, top, or external lists.".format(module_key))

            continue

        if port_iname is not None and port_mem is not None:
            log.error('Cannot make connection for {!r}: the base of the name '
                      'points to a memory but memories do not support '
                      'interface names.'.format(port['name']))

        is_host = port['type'] == 'host'

        # If the hit is a module, it originally came from reggen (via
        # merge.py's amend_ip() function). In this case, we should have a
        # BusInterfaces object as well as a list of InterSignal objects.
        #
        # If not, this is a memory that will just have a dictionary of inter
        # signals.
        if port_mod is not None:
            block = name_to_block[port_mod['type']]
            try:
                sig_name = block.bus_interfaces.find_port_name(
                    is_host, port_iname)
            except KeyError:
                log.error(
                    'Cannot make {} connection for {!r}: the base of '
                    'the target module has no matching bus interface.'.format(
                        'host' if is_host else 'device', port['name']))
                continue
        else:
            inter_signal_list = port_mem['inter_signal_list']
            act = 'req' if is_host else 'rsp'
            matches = [
                x for x in inter_signal_list
                if (x.get('package') == 'tlul_pkg' and x['struct'] == 'tl'
                    and x['act'] == act)
            ]
            if not matches:
                log.error('Cannot make {} connection for {!r}: the memory '
                          'has no signal with an action of {}.'.format(
                              'host' if is_host else 'device', port['name'],
                              act))
                continue

            assert len(matches) == 1
            sig_name = matches[0]['name']

        if is_host:
            add_intermodule_connection(obj=topcfg,
                                       req_m=xbar["name"],
                                       req_s="tl_" + esc_name,
                                       rsp_m=port_base,
                                       rsp_s=sig_name)
        else:
            add_intermodule_connection(obj=topcfg,
                                       req_m=port_base,
                                       req_s=sig_name,
                                       rsp_m=xbar["name"],
                                       rsp_s="tl_" + esc_name)
Exemplo n.º 5
0
def autoconnect_xbar(topcfg: OrderedDict, xbar: OrderedDict):
    ports = [x for x in xbar["nodes"] if x["type"] in ["host", "device"]]
    for port in ports:
        if port["xbar"]:
            if port["type"] == "host":
                # Skip as device will add connection
                continue

            # Device port adds signal
            add_intermodule_connection(obj=topcfg,
                                       req_m=xbar["name"],
                                       req_s="tl_%s" % port["name"],
                                       rsp_m=port["name"],
                                       rsp_s="tl_%s" % xbar["name"])
            continue  # xbar port case

        # check if name exists in ["module", "memory"]
        ips = [
            x for x in topcfg["module"] + topcfg["memory"]
            if x["name"] == port["name"] and lib.is_inst(x)
        ]

        assert len(ips) <= 1

        if len(ips) == 0:
            # if not in module, memory, should be existed in top or ext field
            module_key = "{}.tl_{}".format(xbar["name"], port["name"])
            if module_key not in topcfg["inter_module"]["top"] + list(
                    topcfg["inter_module"]["external"].keys()):
                log.error("Inter-module key {} cannot be found in module, "
                          "memory, top, or external lists.".format(module_key))
            continue

        ip = ips[0]

        # Depending on whether ip came from reggen or topgen, it might be an
        # InterSignal object or it might be a dict. Extract the fields we need
        # so that the code below can treat it as a dict.
        isl = ip['inter_signal_list']
        if not isl or isinstance(isl[0], InterSignal):
            inter_signal_list = [signal.as_dict() for signal in isl]
        else:
            inter_signal_list = isl

        # get the port name
        def get_signame(act: str) -> OrderedDict:
            ims = [
                x for x in inter_signal_list
                if (x.get('package') == 'tlul_pkg' and x['struct'] == 'tl'
                    and x['act'] == act)
            ]
            return ims

        if port["type"] == "device":
            ims = get_signame("rsp")
        else:  # host type
            ims = get_signame("req")

        assert len(ims) == 1
        sig_name = ims[0]["name"]

        add_intermodule_connection(obj=topcfg,
                                   req_m=port["name"],
                                   req_s=sig_name,
                                   rsp_m=xbar["name"],
                                   rsp_s="tl_%s" % port["name"])
        continue  # len() == 1