def test_nested_interface(do_test): class InnerIfc(Interface): def construct(s): s.msg = InPort(Bits32) s.val = InPort(Bits1) s.rdy = OutPort(Bits1) class Ifc(Interface): def construct(s): s.valrdy_ifc = InnerIfc() s.ctrl_bar = InPort(Bits32) s.ctrl_foo = OutPort(Bits32) class A(Component): def construct(s): s.ifc = [Ifc() for _ in range(2)] a = A() a._ref_ports = [ (['clk'], 'clk', rt.Port('input', rdt.Vector(1)), 0), (['reset'], 'reset', rt.Port('input', rdt.Vector(1)), 0), (['ifc[0].ctrl_bar', 'ifc[1].ctrl_bar'], 'ifc__ctrl_bar', rt.Array([2], rt.Port('input', rdt.Vector(32))), 1), (['ifc[0].ctrl_foo', 'ifc[1].ctrl_foo'], 'ifc__ctrl_foo', rt.Array([2], rt.Port('output', rdt.Vector(32))), 1), (['ifc[0].valrdy_ifc.msg', 'ifc[1].valrdy_ifc.msg'], 'ifc__valrdy_ifc__msg', rt.Array([2], rt.Port('input', rdt.Vector(32))), 1), (['ifc[0].valrdy_ifc.rdy', 'ifc[1].valrdy_ifc.rdy'], 'ifc__valrdy_ifc__rdy', rt.Array([2], rt.Port('output', rdt.Vector(1))), 1), (['ifc[0].valrdy_ifc.val', 'ifc[1].valrdy_ifc.val'], 'ifc__valrdy_ifc__val', rt.Array([2], rt.Port('input', rdt.Vector(1))), 1), ] a._ref_ports_yosys = [ (['clk'], 'clk', rt.Port('input', rdt.Vector(1)), 0), (['reset'], 'reset', rt.Port('input', rdt.Vector(1)), 0), (['ifc[0].ctrl_bar'], 'ifc__0__ctrl_bar', rt.Port('input', rdt.Vector(32)), 1), (['ifc[0].ctrl_foo'], 'ifc__0__ctrl_foo', rt.Port('output', rdt.Vector(32)), 1), (['ifc[0].valrdy_ifc.msg'], 'ifc__0__valrdy_ifc__msg', rt.Port('input', rdt.Vector(32)), 1), (['ifc[0].valrdy_ifc.rdy'], 'ifc__0__valrdy_ifc__rdy', rt.Port('output', rdt.Vector(1)), 1), (['ifc[0].valrdy_ifc.val'], 'ifc__0__valrdy_ifc__val', rt.Port('input', rdt.Vector(1)), 1), (['ifc[1].ctrl_bar'], 'ifc__1__ctrl_bar', rt.Port('input', rdt.Vector(32)), 1), (['ifc[1].ctrl_foo'], 'ifc__1__ctrl_foo', rt.Port('output', rdt.Vector(32)), 1), (['ifc[1].valrdy_ifc.msg'], 'ifc__1__valrdy_ifc__msg', rt.Port('input', rdt.Vector(32)), 1), (['ifc[1].valrdy_ifc.rdy'], 'ifc__1__valrdy_ifc__rdy', rt.Port('output', rdt.Vector(1)), 1), (['ifc[1].valrdy_ifc.val'], 'ifc__1__valrdy_ifc__val', rt.Port('input', rdt.Vector(1)), 1), ] do_test(a)
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 test_struct_port_array(do_test): class struct(BitStruct): def __init__(s, bar=1, foo=42): s.bar = Bits32(bar) s.foo = Bits32(foo) class A(Component): def construct(s): s.in_ = [InPort(struct) for _ in range(2)] a = A() st = rdt.Struct('struct', { 'bar': rdt.Vector(32), 'foo': rdt.Vector(32) }, ['bar', 'foo']) a._ref_ports = [('clk', rt.Port('input', rdt.Vector(1))), ('in_', rt.Array([2], rt.Port('input', st))), ('reset', rt.Port('input', rdt.Vector(1)))] a._ref_ports_yosys = [('clk', rt.Port('input', rdt.Vector(1))), ('in___0__bar', rt.Port('input', rdt.Vector(32))), ('in___0__foo', rt.Port('input', rdt.Vector(32))), ('in___1__bar', rt.Port('input', rdt.Vector(32))), ('in___1__foo', rt.Port('input', rdt.Vector(32))), ('reset', rt.Port('input', rdt.Vector(1)))] do_test(a)
def test_nested_struct(do_test): @bitstruct class inner_struct: foo: Bits32 @bitstruct class struct: bar: Bits32 inner: inner_struct class A(Component): def construct(s): s.in_ = [InPort(struct) for _ in range(2)] a = A() inner = rdt.Struct(inner_struct, {'foo': rdt.Vector(32)}) st = rdt.Struct(struct, {'bar': rdt.Vector(32), 'inner': inner}) a._ref_ports = [ (['clk'], 'clk', rt.Port('input', rdt.Vector(1)), 0), (['in_'], 'in_', rt.Array([2], rt.Port('input', st)), 0), (['reset'], 'reset', rt.Port('input', rdt.Vector(1)), 0), ] a._ref_ports_yosys = [ (['clk'], 'clk', rt.Port('input', rdt.Vector(1)), 0), (['in_[0].bar'], 'in___0__bar', rt.Port('input', rdt.Vector(32)), 0), (['in_[0].inner.foo'], 'in___0__inner__foo', rt.Port('input', rdt.Vector(32)), 0), (['in_[1].bar'], 'in___1__bar', rt.Port('input', rdt.Vector(32)), 0), (['in_[1].inner.foo'], 'in___1__inner__foo', rt.Port('input', rdt.Vector(32)), 0), (['reset'], 'reset', rt.Port('input', rdt.Vector(1)), 0), ] do_test(a)
def test_packed_array_port_array(do_test): @bitstruct class struct: bar: Bits32 foo: [[Bits32] * 2] * 3 class A(Component): def construct(s): s.in_ = [InPort(struct) for _ in range(2)] a = A() foo = rdt.PackedArray([3, 2], rdt.Vector(32)) st = rdt.Struct('struct', {'bar': rdt.Vector(32), 'foo': foo}) a._ref_ports = [('clk', rt.Port('input', rdt.Vector(1))), ('in_', rt.Array([2], rt.Port('input', st))), ('reset', rt.Port('input', rdt.Vector(1)))] a._ref_ports_yosys = [ ('clk', rt.Port('input', rdt.Vector(1))), ('in___0__bar', rt.Port('input', rdt.Vector(32))), ('in___0__foo__0__0', rt.Port('input', rdt.Vector(32))), ('in___0__foo__0__1', rt.Port('input', rdt.Vector(32))), ('in___0__foo__1__0', rt.Port('input', rdt.Vector(32))), ('in___0__foo__1__1', rt.Port('input', rdt.Vector(32))), ('in___0__foo__2__0', rt.Port('input', rdt.Vector(32))), ('in___0__foo__2__1', rt.Port('input', rdt.Vector(32))), ('in___1__bar', rt.Port('input', rdt.Vector(32))), ('in___1__foo__0__0', rt.Port('input', rdt.Vector(32))), ('in___1__foo__0__1', rt.Port('input', rdt.Vector(32))), ('in___1__foo__1__0', rt.Port('input', rdt.Vector(32))), ('in___1__foo__1__1', rt.Port('input', rdt.Vector(32))), ('in___1__foo__2__0', rt.Port('input', rdt.Vector(32))), ('in___1__foo__2__1', rt.Port('input', rdt.Vector(32))), ('reset', rt.Port('input', rdt.Vector(1))) ] do_test(a)
def test_port_array(do_test): class A(Component): def construct(s): s.in_ = [InPort(Bits32) for _ in range(3)] a = A() a._ref_ports = [('clk', rt.Port('input', rdt.Vector(1))), ('in_', rt.Array([3], rt.Port('input', rdt.Vector(32)))), ('reset', rt.Port('input', rdt.Vector(1)))] a._ref_ports_yosys = [('clk', rt.Port('input', rdt.Vector(1))), ('in___0', rt.Port('input', rdt.Vector(32))), ('in___1', rt.Port('input', rdt.Vector(32))), ('in___2', rt.Port('input', rdt.Vector(32))), ('reset', rt.Port('input', rdt.Vector(1)))] do_test(a)
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 test_port_2d_array(do_test): class A(Component): def construct(s): s.in_ = [[InPort(Bits32) for _ in range(2)] for _ in range(3)] a = A() a._ref_ports = [ (['clk'], 'clk', rt.Port('input', rdt.Vector(1)), 0), (['in_'], 'in_', rt.Array([3, 2], rt.Port('input', rdt.Vector(32))), 0), (['reset'], 'reset', rt.Port('input', rdt.Vector(1)), 0), ] a._ref_ports_yosys = [ (['clk'], 'clk', rt.Port('input', rdt.Vector(1)), 0), (['in_[0][0]'], 'in___0__0', rt.Port('input', rdt.Vector(32)), 0), (['in_[0][1]'], 'in___0__1', rt.Port('input', rdt.Vector(32)), 0), (['in_[1][0]'], 'in___1__0', rt.Port('input', rdt.Vector(32)), 0), (['in_[1][1]'], 'in___1__1', rt.Port('input', rdt.Vector(32)), 0), (['in_[2][0]'], 'in___2__0', rt.Port('input', rdt.Vector(32)), 0), (['in_[2][1]'], 'in___2__1', rt.Port('input', rdt.Vector(32)), 0), (['reset'], 'reset', rt.Port('input', rdt.Vector(1)), 0), ] do_test(a)
def mangle_port(s, id_, port, n_dim): if not n_dim: return [(id_, port)] else: return [(id_, rt.Array(n_dim, port))]