Ejemplo n.º 1
0
    def get_imported_object(s, m):
        ph_cfg = s.get_placeholder_config(m)
        ip_cfg = s.get_config(m)
        ip_cfg.setup_configs(m, s.get_translation_namespace(m))

        rtype = RTLIRGetter(cache=False).get_component_ifc_rtlir(m)

        # Now we selectively unpack array of ports if they are referred to in
        # port_map
        ports = s.get_gen_mapped_port()(m, ph_cfg.port_map, ph_cfg.has_clk,
                                        ph_cfg.has_reset)

        cached, config_file, cfg_d = s.is_cached(m, ip_cfg)

        s.create_verilator_model(m, ph_cfg, ip_cfg, cached)

        port_cdefs = s.create_verilator_c_wrapper(m, ph_cfg, ip_cfg, ports,
                                                  cached)

        s.create_shared_lib(m, ph_cfg, ip_cfg, cached)

        symbols = s.create_py_wrapper(m, ph_cfg, ip_cfg, rtype, ports,
                                      port_cdefs, cached)

        imp = s.import_component(m, ph_cfg, ip_cfg, symbols)

        imp._ip_cfg = ip_cfg
        imp._ph_cfg = ph_cfg
        imp._ports = ports

        # Dump configuration dict to config_file
        with open(config_file, 'w') as fd:
            json.dump(cfg_d, fd, indent=4)

        return imp
Ejemplo n.º 2
0
    def visit_placeholder(s, m):
        c = s.__class__
        super().visit_placeholder(m)
        irepr = RTLIRGetter(cache=False).get_component_ifc_rtlir(m)

        s.setup_default_configs(m, irepr)
        cfg = m.get_metadata(c.placeholder_config)

        if cfg.enable:
            s.check_valid(m, cfg, irepr)
            s.pickle(m, cfg, irepr)
Ejemplo n.º 3
0
def gen_mapped_ports(m, raw_port_map, has_clk=True, has_reset=True, sep='__'):
    """Return a list of (pname, vname, rt.Port/rt.Array ) that has all ports
  of `rtype`. This method performs SystemVerilog backend-specific name
  mangling and returns all ports that appear in the interface of component
  `rtype`. Each tuple contains a port or an array of port that has any data type
  allowed in RTLIRDataType.
  Shunning: Now we also take port_map into account. Two points to note:
  1. If a port's pname appears as a key in port_map, we need to use the
     corresponding value as vname
  2. For an n-D array of ports, we enforce the rule that assumes either no
     element is mapped in port_map, or _all_ of the elements are mapped.
  """

    # Shunning: this handles the case where the port is in interface since
    # we need to actually extract 'minion.req.en' from 's.x.y.minion.req.en'
    port_map = {}
    l = len(repr(m))
    for p, mapped_name in raw_port_map.items():
        assert p.get_host_component() is m
        port_map[repr(p)[l + 1:]] = mapped_name

    # [pnames], vname, rtype, port_idx

    def _mangle_port(pname, vname, port, n_dim):

        # Normal port
        if not n_dim:
            return [([pname], port_map[pname] if pname in port_map else vname,
                     port, 0)]

        # Handle port array. We just assume if one element of the port array
        # is mapped, we need the user to map every element in the array.
        found = tot = 0
        all_ports = []
        Q = deque([(pname, vname, port, n_dim)])
        while Q:
            _pname, _vname, _port, _n_dim = Q.popleft()
            if not _n_dim:
                if _pname in port_map:
                    found += 1
                    _vname = port_map[_pname]
                all_ports.append(([_pname], _vname, _port, 0))
            else:
                for i in range(_n_dim[0]):
                    Q.append((f"{_pname}[{i}]", f"{_vname}{sep}{i}", _port,
                              _n_dim[1:]))

        assert found == len(all_ports) or found == 0, \
            f"{pname} is an {len(n_dim)}-D array of ports with {len(all_ports)} ports in total, " \
            f" but only {found} of them is mapped. Please either map all of them or none of them."

        if not found:
            return [([pname], vname, rt.Array(n_dim, port), 0)]
        else:
            return all_ports

    def _is_ifc_mapped(pname, vname, rtype, n_dim):
        found, tot, flatten_ports = 0, 0, []
        # pname, vname, rtype, n_dim
        Q = deque([(pname, vname, rtype, n_dim, 0)])

        while Q:
            _pname, _vname, _rtype, _n_dim, _prev_dims = Q.popleft()
            if _n_dim:
                for i in range(_n_dim[0]):
                    Q.append((f"{_pname}[{i}]", f"{_vname}{sep}{i}", _rtype,
                              _n_dim[1:], _prev_dims + 1))
            else:
                if isinstance(_rtype, rt.Port):
                    # Port inside the interface
                    tot += 1
                    if _pname in port_map:
                        found += 1
                        flatten_ports.append(
                            ([_pname], port_map[_pname], _rtype, _prev_dims))
                    else:
                        flatten_ports.append(
                            ([_pname], _vname, _rtype, _prev_dims))
                elif isinstance(_rtype, rt.InterfaceView):
                    # Interface (nested)
                    for sub_name, sub_rtype in _rtype.get_all_properties_packed(
                    ):
                        sub_n_dim, sub_rtype = get_rtype(sub_rtype)
                        Q.append((f"{_pname}.{sub_name}",
                                  f"{_vname}{sep}{sub_name}", sub_rtype,
                                  sub_n_dim, _prev_dims))
                else:
                    assert False, f"{_pname} is not interface(s) or port(s)!"

        assert (found == 0) or (found == tot), \
            f"{name} is an interface that has {tot} ports in total, " \
            f" but only {found} of them is mapped. Please either map all of them or none of them."
        return (found == tot), flatten_ports

    def _gen_packed_ifc(pname, vname, ifc, n_dim):
        packed_ifc, ret = [], []
        Q = deque([(pname, vname, ifc, n_dim, [], 0)])
        while Q:
            _pname, _vname, _rtype, _n_dim, _prev_n_dim, _port_idx = Q.popleft(
            )

            if isinstance(_rtype, rt.Port):
                if not (_prev_n_dim + _n_dim):
                    new_rtype = _rtype
                else:
                    new_rtype = rt.Array(_prev_n_dim + _n_dim, _rtype)
                packed_ifc.append((_pname, _vname, new_rtype, _port_idx))

            elif isinstance(_rtype, rt.InterfaceView):
                if _n_dim:
                    new_prev_n_dim = _prev_n_dim + [_n_dim[0]]
                    for i in range(_n_dim[0]):
                        Q.append((f"{_pname}[{i}]", _vname, _rtype, _n_dim[1:],
                                  new_prev_n_dim, _port_idx + 1))
                else:
                    new_prev_n_dim = _prev_n_dim
                    for sub_name, sub_rtype in _rtype.get_all_properties_packed(
                    ):
                        sub_n_dim, sub_rtype = get_rtype(sub_rtype)
                        Q.append((f"{_pname}.{sub_name}",
                                  f"{_vname}{sep}{sub_name}", sub_rtype,
                                  sub_n_dim, new_prev_n_dim, _port_idx))
            else:
                assert False, f"{_pname} is not interface(s) or port(s)!"

        # Merge entries whose vnames are the same. The result will have a list for
        # the pnames.
        names = set()
        for _, vname, rtype, port_idx in packed_ifc:
            if vname not in names:
                names.add(vname)
                ret.append(([], vname, rtype, port_idx))
                for _pname, _vname, _, _port_idx in packed_ifc:
                    if vname == _vname:
                        assert _port_idx == port_idx
                        ret[-1][0].append(_pname)

        return ret

    def _mangle_ifc(pname, vname, ifc, n_dim):
        is_mapped, flatten_ifc = _is_ifc_mapped(pname, vname, ifc, n_dim)
        if is_mapped:
            return flatten_ifc
        else:
            return _gen_packed_ifc(pname, vname, ifc, n_dim)

    # We start from all packed ports/interfaces, and unpack arrays if
    # it is found in a port.
    rtype = RTLIRGetter(cache=False).get_component_ifc_rtlir(m)
    ret = []

    for name, port in rtype.get_ports_packed():
        if not has_clk and name == 'clk': continue
        if not has_reset and name == 'reset': continue
        p_n_dim, p_rtype = get_rtype(port)
        ret += _mangle_port(name, name, p_rtype, p_n_dim)

    for name, ifc in rtype.get_ifc_views_packed():
        i_n_dim, i_rtype = get_rtype(ifc)
        ret += _mangle_ifc(name, name, i_rtype, i_n_dim)

    return ret
Ejemplo n.º 4
0
def gen_mapped_ports(m, port_map, has_clk=True, has_reset=True, sep='__'):
    """Return a list of (pname, vname, rt.Port/rt.Array ) that has all ports
  of `rtype`. This method performs SystemVerilog backend-specific name
  mangling and returns all ports that appear in the interface of component
  `rtype`. Each tuple contains a port or an array of port that has any data type
  allowed in RTLIRDataType.
  Shunning: Now we also take port_map into account. Two points to note:
  1. If a port's pname appears as a key in port_map, we need to use the
     corresponding value as vname
  2. For an n-D array of ports, we enforce the rule that assumes either no
     element is mapped in port_map, or _all_ of the elements are mapped.
  """

    port_map = {p._dsl._my_name: n for p, n in port_map.items()}

    def _mangle_vector(pname, vname, port, dtype, port_idx):
        return [([pname], port_map[pname] if pname in port_map else vname,
                 rt.Port(port.direction, dtype), port_idx)]

    def _mangle_struct(pname, vname, port, dtype, port_idx):
        ret = []
        for field_name, field_dtype in dtype.get_all_properties().items():
            ret += _mangle_dtype(f"{pname}.{field_name}",
                                 f"{vname}{sep}{field_name}", port,
                                 field_dtype, port_idx)
        return ret

    def _mangle_packed(pname, vname, port, dtype, n_dim, port_idx):
        if not n_dim:
            return _mangle_dtype(pname, vname, port, dtype, port_idx)
        else:
            ret = []
            for i in range(n_dim[0]):
                ret += _mangle_packed(f"{pname}[{i}]", f"{vname}{sep}{i}",
                                      port, dtype, n_dim[1:], port_idx)
            return ret

    def _mangle_dtype(pname, vname, port, dtype, port_idx):
        if isinstance(dtype, rdt.Vector):
            return _mangle_vector(pname, vname, port, dtype, port_idx)
        elif isinstance(dtype, rdt.Struct):
            return _mangle_struct(pname, vname, port, dtype, port_idx)
        elif isinstance(dtype, rdt.PackedArray):
            return _mangle_packed(pname, vname, port, dtype.get_sub_dtype(),
                                  dtype.get_dim_sizes(), port_idx)
        else:
            assert False, f'unrecognized data type {dtype}!'

    def _mangle_port(pname, vname, port, n_dim, port_idx):
        # Normal port
        if not n_dim:
            return _mangle_dtype(pname, vname, port, port.get_dtype(),
                                 port_idx)

        # Handle port array. We just assume if one element of the port array
        # is mapped, we need the user to map every element in the array.
        else:
            ret = []
            for i in range(n_dim[0]):
                ret += _mangle_port(f"{pname}[{i}]", f"{vname}{sep}{i}", port,
                                    n_dim[1:], port_idx)
            return ret

    def _mangle_ifc(pname, vname, ifc, n_dim, port_idx):
        ret = []
        if not n_dim:
            for port_name, port_rtype in ifc.get_all_properties_packed():
                port_n_dim, port_rtype = get_rtype(port_rtype)
                if isinstance(port_rtype, rt.InterfaceView):
                    ret += _mangle_ifc(f"{pname}.{port_name}",
                                       f"{vname}{sep}{port_name}", port_rtype,
                                       port_n_dim, port_idx)
                elif isinstance(port_rtype, rt.Port):
                    ret += _mangle_port(f"{pname}.{port_name}",
                                        f"{vname}{sep}{port_name}", port_rtype,
                                        port_n_dim, port_idx)
                else:
                    assert False, "unrecognized interface/port {port_rtype}!"
        else:
            for i in range(n_dim[0]):
                ret += _mangle_ifc(f"{pname}[{i}]", f"{vname}{sep}{i}", ifc,
                                   n_dim[1:], port_idx + 1)
        return ret

    # We start from all packed ports/interfaces, and unpack arrays if
    # it is found in a port.
    rtype = RTLIRGetter(cache=False).get_component_ifc_rtlir(m)
    ret = []

    for name, port in rtype.get_ports_packed():
        if not has_clk and name == 'clk': continue
        if not has_reset and name == 'reset': continue
        p_n_dim, p_rtype = get_rtype(port)
        ret += _mangle_port(name, name, p_rtype, p_n_dim, 0)

    for name, ifc in rtype.get_ifc_views_packed():
        i_n_dim, i_rtype = get_rtype(ifc)
        ret += _mangle_ifc(name, name, i_rtype, i_n_dim, 0)

    return ret