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_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_port_single(do_test): class A(Component): def construct(s): s.in_ = InPort(Bits32) a = A() a._ref_ports = [('clk', rt.Port('input', rdt.Vector(1))), ('in_', rt.Port('input', rdt.Vector(32))), ('reset', rt.Port('input', rdt.Vector(1)))] a._ref_ports_yosys = a._ref_ports 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 local_do_test(m): m.elaborate() rtype = rt.RTLIRGetter(cache=False).get_component_ifc_rtlir(m) ipass = VerilogVerilatorImportPass() symbols, decls = ipass.gen_signal_decl_py(rtype) assert symbols == m._ref_symbols assert decls == m._ref_decls
def local_do_test(m): m.elaborate() rtype = rt.get_component_ifc_rtlir(m) ipass = ImportPass() symbols, decls, conns = ipass.gen_signal_decl_py(rtype) assert symbols == m._ref_symbols assert decls == m._ref_decls assert conns == m._ref_conns
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 test_interface(do_test): class Ifc(Interface): def construct(s): s.msg = InPort(Bits32) s.val = InPort(Bits1) s.rdy = OutPort(Bits1) class A(Component): def construct(s): s.ifc = Ifc() a = A() a._ref_ports = [('clk', rt.Port('input', rdt.Vector(1))), ('reset', rt.Port('input', rdt.Vector(1))), ('ifc__msg', rt.Port('input', rdt.Vector(32))), ('ifc__rdy', rt.Port('output', rdt.Vector(1))), ('ifc__val', rt.Port('input', rdt.Vector(1)))] a._ref_ports_yosys = a._ref_ports do_test(a)
def rtlir_tr_subcomp_port_decl(s, m, c_id, c_rtype, c_array_type, port_id, port_rtype, port_dtype, port_array_type): port_def_rtype = rt.Wire(port_dtype["raw_dtype"]) return { 'def': s.rtlir_tr_wire_decl('{c_id}__' + port_id, port_def_rtype, port_array_type, port_dtype), 'decl': '.{port_id}( {{c_id}}__{port_id} )'.format(**locals()) }
def translate_behavioral(s, m): """Translate behavioral part of `m`.""" # Get upblk metadata s.behavioral.accessed[ m] = m._pass_behavioral_rtlir_type_check.rtlir_accessed # Translate upblks upblk_decls = [] upblk_srcs = [] upblk_py_srcs = [] upblks = { 'CombUpblk': get_ordered_upblks(m), 'SeqUpblk': get_ordered_update_ff(m), } # Sort the upblks by their name upblks['CombUpblk'].sort(key=lambda x: x.__name__) upblks['SeqUpblk'].sort(key=lambda x: x.__name__) for upblk_type in ('CombUpblk', 'SeqUpblk'): for blk in upblks[upblk_type]: upblk_ir = s.behavioral.rtlir[m][blk] upblk_srcs.append(s.rtlir_tr_upblk_src(blk, upblk_ir)) upblk_py_srcs.append( s.rtlir_tr_upblk_py_src(blk, upblk_ir.is_lambda, upblk_ir.src, upblk_ir.lino, upblk_ir.filename)) upblk_decls.append( s.rtlir_tr_upblk_decl(blk, upblk_srcs[-1], upblk_py_srcs[-1])) s.behavioral.upblk_srcs[m] = s.rtlir_tr_upblk_srcs(upblk_srcs) s.behavioral.upblk_py_srcs[m] = s.rtlir_tr_upblk_decls(upblk_py_srcs) s.behavioral.upblk_decls[m] = s.rtlir_tr_upblk_decls(upblk_decls) # Generate free variable declarations freevars = [] for name, fvar in s.behavioral.freevars[m].items(): rtype = rt.get_rtlir(fvar) if isinstance(rtype, rt.Array): fvar_rtype = rtype.get_sub_type() array_rtype = rtype else: fvar_rtype = rtype array_rtype = None dtype = fvar_rtype.get_dtype() assert isinstance( dtype, rdt.Vector ), \ f'{name} freevar should be an integer or a list of integers!' freevars.append( s.rtlir_tr_behavioral_freevar( name, fvar_rtype, s.rtlir_tr_unpacked_array_type(array_rtype), s.rtlir_tr_vector_dtype(dtype), fvar)) s.behavioral.decl_freevars[m] = s.rtlir_tr_behavioral_freevars( freevars)
def test_struct_port_array(do_test): @bitstruct class struct: bar: Bits32 foo: Bits32 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)}) 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 rtlir_tr_subcomp_ifc_port_decl(s, m, c_id, c_rtype, c_array_type, ifc_id, ifc_rtype, ifc_array_type, port_id, port_rtype, port_array_type): assert isinstance( port_rtype, rt.Port ), \ "SystemVerilog backend does not support nested interface {} yet!".format( port_id ) port_dtype = s.rtlir_data_type_translation(m, port_rtype.get_dtype()) port_def_rtype = rt.Wire(port_dtype["raw_dtype"]) return { 'def' : s.rtlir_tr_wire_decl('{c_id}__{ifc_id}__'+port_id, port_def_rtype, port_array_type, port_dtype), 'decl' : '.{{ifc_id}}__{port_id}( {{c_id}}__{{ifc_id}}__{port_id} )'. \ format(**locals()) }
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_struct_port_single(do_test): @bitstruct class struct: bar: Bits32 foo: Bits32 class A(Component): def construct(s): s.in_ = InPort(struct) a = A() st = rdt.Struct(struct, {'bar': rdt.Vector(32), 'foo': rdt.Vector(32)}) a._ref_ports = [ (['clk'], 'clk', rt.Port('input', rdt.Vector(1)), 0), (['in_'], 'in_', 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_.bar'], 'in___bar', rt.Port('input', rdt.Vector(32)), 0), (['in_.foo'], 'in___foo', 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))]
def rtlir_tr_behavioral_tmpvar( s, id_, upblk_id, dtype ): return s.rtlir_tr_wire_decl( "__tmpvar__"+upblk_id+'_'+id_, rt.Wire(dtype['raw_dtype']), s.rtlir_tr_unpacked_array_type(None), dtype )
def mangle_vector(s, d, id_, dtype): return [(id_, rt.Port(d, dtype))]
def DataStrategy(draw, dut): """Return a strategy that generates input vector for component `dut`.""" max_cycles = 10 ret = [] dut.elaborate() rifc = rt.RTLIRGetter(cache=False).get_component_ifc_rtlir(dut) ports = rifc.get_ports_packed() ifcs = rifc.get_ifc_views_packed() # Add reset cycle at the beginning reset1, reset2 = {}, {} for id_, port in ports: if id_ == "clk": reset1.update({id_: Bits1(0)}) reset2.update({id_: Bits1(1)}) elif id_ == "reset": reset1.update({id_: Bits1(1)}) reset2.update({id_: Bits1(1)}) else: n_dim, port_rtype = flatten(port) if port_rtype.get_direction() == "input": if n_dim: reset1.update(ArrayInitData(id_, n_dim, port_rtype)) reset2.update(ArrayInitData(id_, n_dim, port_rtype)) else: reset1.update(InPortInitData(id_, port_rtype)) reset2.update(InPortInitData(id_, port_rtype)) for id_, ifc in ifcs: n_dim, ifc_rtype = flatten(ifc) if n_dim: reset1.update(ArrayDataStrategy(id_, n_dim, ifc_rtype)) reset2.update(ArrayDataStrategy(id_, n_dim, ifc_rtype)) else: reset1.update(InterfaceInitData(id_, n_dim, ifc_rtype)) reset2.update(InterfaceInitData(id_, n_dim, ifc_rtype)) ret.append(reset1) ret.append(reset2) for i in range(max_cycles): data = {} for id_, port in ports: if id_ in ["clk", "reset"]: data.update({id_: Bits1(0)}) else: n_dim, port_rtype = flatten(port) if n_dim: if port_rtype.get_direction() == "input": data.update( draw(ArrayDataStrategy(id_, n_dim, port_rtype))) elif port_rtype.get_direction() == "input": data.update(draw(InPortDataStrategy(id_, port_rtype))) for id_, ifc in ifcs: n_dim, ifc_rtype = flatten(ifc) if n_dim: data.update(draw(ArrayDataStrategy(id_, n_dim, ifc_rtype))) else: data.update(draw(InterfaceDataStrategy(id_, ifc_rtype))) # Toggle clock signal toggle_data = {} for id_, signal in data.items(): if id_ == "clk": toggle_data.update({id_: Bits1(1)}) else: toggle_data.update({id_: copy.deepcopy(signal)}) ret.append(data) ret.append(toggle_data) return ret
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'], '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].foo[0][0]'], 'in___0__foo__0__0', rt.Port('input', rdt.Vector(32)), 0), (['in_[0].foo[0][1]'], 'in___0__foo__0__1', rt.Port('input', rdt.Vector(32)), 0), (['in_[0].foo[1][0]'], 'in___0__foo__1__0', rt.Port('input', rdt.Vector(32)), 0), (['in_[0].foo[1][1]'], 'in___0__foo__1__1', rt.Port('input', rdt.Vector(32)), 0), (['in_[0].foo[2][0]'], 'in___0__foo__2__0', rt.Port('input', rdt.Vector(32)), 0), (['in_[0].foo[2][1]'], 'in___0__foo__2__1', rt.Port('input', rdt.Vector(32)), 0), (['in_[1].bar'], 'in___1__bar', rt.Port('input', rdt.Vector(32)), 0), (['in_[1].foo[0][0]'], 'in___1__foo__0__0', rt.Port('input', rdt.Vector(32)), 0), (['in_[1].foo[0][1]'], 'in___1__foo__0__1', rt.Port('input', rdt.Vector(32)), 0), (['in_[1].foo[1][0]'], 'in___1__foo__1__0', rt.Port('input', rdt.Vector(32)), 0), (['in_[1].foo[1][1]'], 'in___1__foo__1__1', rt.Port('input', rdt.Vector(32)), 0), (['in_[1].foo[2][0]'], 'in___1__foo__2__0', rt.Port('input', rdt.Vector(32)), 0), (['in_[1].foo[2][1]'], 'in___1__foo__2__1', rt.Port('input', rdt.Vector(32)), 0), (['reset'], 'reset', rt.Port('input', rdt.Vector(1)), 0), ] do_test(a)
def test_interface_array(do_test): class Ifc(Interface): def construct(s): s.msg = InPort(Bits32) s.val = InPort(Bits1) s.rdy = OutPort(Bits1) 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].msg', 'ifc[1].msg'], 'ifc__msg', rt.Array([2], rt.Port('input', rdt.Vector(32))), 1), (['ifc[0].rdy', 'ifc[1].rdy'], 'ifc__rdy', rt.Array([2], rt.Port('output', rdt.Vector(1))), 1), (['ifc[0].val', 'ifc[1].val'], '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].msg'], 'ifc__0__msg', rt.Port('input', rdt.Vector(32)), 1), (['ifc[0].rdy'], 'ifc__0__rdy', rt.Port('output', rdt.Vector(1)), 1), (['ifc[0].val'], 'ifc__0__val', rt.Port('input', rdt.Vector(1)), 1), (['ifc[1].msg'], 'ifc__1__msg', rt.Port('input', rdt.Vector(32)), 1), (['ifc[1].rdy'], 'ifc__1__rdy', rt.Port('output', rdt.Vector(1)), 1), (['ifc[1].val'], 'ifc__1__val', rt.Port('input', rdt.Vector(1)), 1), ] do_test(a)
def test_nested_interface_port_array(do_test): class InnerIfc(Interface): def construct(s): s.msg = [InPort(Bits32) for _ in range(2)] 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', rt.Port('input', rdt.Vector(1))), ('reset', rt.Port('input', rdt.Vector(1))), ('ifc__0__ctrl_bar', rt.Port('input', rdt.Vector(32))), ('ifc__0__ctrl_foo', rt.Port('output', rdt.Vector(32))), ('ifc__0__valrdy_ifc__msg', rt.Array([2], rt.Port('input', rdt.Vector(32)))), ('ifc__0__valrdy_ifc__rdy', rt.Port('output', rdt.Vector(1))), ('ifc__0__valrdy_ifc__val', rt.Port('input', rdt.Vector(1))), ('ifc__1__ctrl_bar', rt.Port('input', rdt.Vector(32))), ('ifc__1__ctrl_foo', rt.Port('output', rdt.Vector(32))), ('ifc__1__valrdy_ifc__msg', rt.Array([2], rt.Port('input', rdt.Vector(32)))), ('ifc__1__valrdy_ifc__rdy', rt.Port('output', rdt.Vector(1))), ('ifc__1__valrdy_ifc__val', rt.Port('input', rdt.Vector(1))) ] a._ref_ports_yosys = [ ('clk', rt.Port('input', rdt.Vector(1))), ('reset', rt.Port('input', rdt.Vector(1))), ('ifc__0__ctrl_bar', rt.Port('input', rdt.Vector(32))), ('ifc__0__ctrl_foo', rt.Port('output', rdt.Vector(32))), ('ifc__0__valrdy_ifc__msg__0', rt.Port('input', rdt.Vector(32))), ('ifc__0__valrdy_ifc__msg__1', rt.Port('input', rdt.Vector(32))), ('ifc__0__valrdy_ifc__rdy', rt.Port('output', rdt.Vector(1))), ('ifc__0__valrdy_ifc__val', rt.Port('input', rdt.Vector(1))), ('ifc__1__ctrl_bar', rt.Port('input', rdt.Vector(32))), ('ifc__1__ctrl_foo', rt.Port('output', rdt.Vector(32))), ('ifc__1__valrdy_ifc__msg__0', rt.Port('input', rdt.Vector(32))), ('ifc__1__valrdy_ifc__msg__1', rt.Port('input', rdt.Vector(32))), ('ifc__1__valrdy_ifc__rdy', rt.Port('output', rdt.Vector(1))), ('ifc__1__valrdy_ifc__val', rt.Port('input', rdt.Vector(1))) ] do_test(a)
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 local_do_test(m): m.elaborate() rtype = rt.get_component_ifc_rtlir(m) ipass = ImportPass() result = ipass.gen_packed_ports(rtype) assert result == m._ref_ports
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)]