def test_struct_port_array(do_test): class B(BitStruct): def __init__(s, foo=0, bar=42): s.foo = Bits32(foo) s.bar = Bits16(bar) class A(Component): def construct(s): s.struct = [InPort(B) for _ in range(5)] a = A() a._ref_name = "A" a._ref_ports = \ """\ port_decls: port_decl: struct Array[5] of Port """ a._ref_wires = "wire_decls:\n" a._ref_consts = "const_decls:\n" a._ref_conns = "connections:\n" a._ref_structs = [(rdt.Struct('B', { 'foo': rdt.Vector(32), 'bar': rdt.Vector(16) }, ['bar', 'foo']), 'B')] a._ref_src = \ """\ struct B component A ( port_decls: port_decl: struct Array[5] of Port interface_decls: ); const_decls: freevars: wire_decls: component_decls: tmpvars: upblk_srcs: connections: endcomponent """ do_test(a)
def test_multi_ifc_decls(do_test): class InIfc(Interface): def construct(s): s.msg = InPort(Bits32) s.val = InPort(Bits1) s.rdy = OutPort(Bits1) class OutIfc(Interface): def construct(s): s.msg = OutPort(Bits32) s.val = OutPort(Bits1) s.rdy = InPort(Bits1) class A(Component): def construct(s): s.in_ = InIfc() s.out = OutIfc() connect(s.out, s.in_) a = A() a._ref_src = \ """\ module A ( input logic [0:0] clk, input logic [0:0] reset, input logic [31:0] in___msg, output logic [0:0] in___rdy, input logic [0:0] in___val, output logic [31:0] out__msg, input logic [0:0] out__rdy, output logic [0:0] out__val ); assign out__msg = in___msg; assign in___rdy = out__rdy; assign out__val = in___val; endmodule """ a._ref_src_yosys = a._ref_src 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'], 'clk', rt.Port('input', rdt.Vector(1)), 0), (['in_'], 'in_', rt.Array([3], 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]'], 'in___0', rt.Port('input', rdt.Vector(32)), 0), (['in_[1]'], 'in___1', rt.Port('input', rdt.Vector(32)), 0), (['in_[2]'], 'in___2', rt.Port('input', rdt.Vector(32)), 0), (['reset'], 'reset', rt.Port('input', rdt.Vector(1)), 0), ] do_test(a)
def run_test(cls, args, test_vectors): m = cls(*args) T = args[1] Tsel = mk_bits(clog2(args[0])) def tv_in(model, test_vector): n = len(model.in_) for i in range(n): model.in_[i] = T(test_vector[i]) model.sel[i] = Tsel(test_vector[n + i]) def tv_out(model, test_vector): n = len(model.in_) for i in range(n): assert model.out[i] == T(test_vector[n * 2 + i]) m._test_vectors = test_vectors m._tv_in, m._tv_out = tv_in, tv_out do_test(m)
def test_pymtl_multi_upblks( do_test ): class A( Component ): def construct( s ): s.out = [ OutPort( Bits32 ) for _ in range(5) ] @s.update def upblk1(): s.out[0] = Bits32(42) @s.update def upblk2(): s.out[1] = Bits32(42) a = A() a._ref_upblk_repr = \ """\ upblk_srcs: upblk_src: upblk1 upblk_src: upblk2 """ a._ref_freevar_repr = """freevars:\n""" do_test( a )
def test_L2_if_cond_bool(do_test): class B(BitStruct): def __init__(s): s.foo = Bits32(42) class A(Component): def construct(s): s.in_ = InPort(B) s.out = OutPort(Bits1) @s.update def upblk(): if s.in_: s.out = Bits1(1) else: s.out = ~Bits1(1) with expected_failure(PyMTLTypeError, "cannot be converted to bool"): 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 test_expr_port_array_index(do_test): class A(Component): def construct(s): s.foo = [InPort(Bits32) for _ in range(5)] s.bar = OutPort(Bits32) connect(s.bar, s.foo[1]) a = A() a._ref_name = "A" a._ref_ports = \ """\ port_decls: port_decl: bar Port of Vector32 port_decl: foo Array[5] of Port """ a._ref_wires = "wire_decls:\n" a._ref_consts = "const_decls:\n" a._ref_conns = \ """\ connections: connection: PortArrayIdx CurCompAttr foo 1 -> CurCompAttr bar """ a._ref_src = \ """\ component {} ( port_decls: port_decl: bar Port of Vector32 port_decl: foo Array[5] of Port interface_decls: ); const_decls: freevars: wire_decls: component_decls: tmpvars: upblk_srcs: connections: connection: PortArrayIdx CurCompAttr foo 1 -> CurCompAttr bar endcomponent """.format( a._ref_name ) do_test(a)
def test_expr_part_sel(do_test): class A(Component): def construct(s): s.foo = InPort(Bits32) s.bar = OutPort(Bits4) connect(s.bar, s.foo[0:4]) a = A() a._ref_name = "A" a._ref_ports = \ """\ port_decls: port_decl: bar Port of Vector4 port_decl: foo Port of Vector32 """ a._ref_wires = "wire_decls:\n" a._ref_consts = "const_decls:\n" a._ref_conns = \ """\ connections: connection: PartSel CurCompAttr foo 0 4 -> CurCompAttr bar """ a._ref_src = \ """\ component {} ( port_decls: port_decl: bar Port of Vector4 port_decl: foo Port of Vector32 interface_decls: ); const_decls: freevars: wire_decls: component_decls: tmpvars: upblk_srcs: connections: connection: PartSel CurCompAttr foo 0 4 -> CurCompAttr bar endcomponent """.format( a._ref_name ) 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', rt.Port('input', rdt.Vector(1))), ('in_', rt.Array([3, 2], 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__0', rt.Port('input', rdt.Vector(32))), ('in___0__1', rt.Port('input', rdt.Vector(32))), ('in___1__0', rt.Port('input', rdt.Vector(32))), ('in___1__1', rt.Port('input', rdt.Vector(32))), ('in___2__0', rt.Port('input', rdt.Vector(32))), ('in___2__1', rt.Port('input', rdt.Vector(32))), ('reset', rt.Port('input', rdt.Vector(1)))] do_test(a)
def test_interface_array_non_static_index( do_test ): class Ifc( Interface ): def construct( s ): s.foo = InPort( Bits32 ) class A( Component ): def construct( s ): s.in_ = [ Ifc() for _ in range(2) ] s.out = OutPort( Bits32 ) @s.update def upblk(): s.out = s.in_[s.in_[0].foo].foo a = A() a._ref_upblk_srcs_yosys = { 'upblk' : \ """\ always_comb begin : upblk out = in___foo[in___foo[0]]; end\ """ } do_test( a )
def test_pymtl_struct_closure(do_test): @bitstruct class B: foo: Bits32 class A(Component): def construct(s): foo = InPort(B) s._foo = foo s.out = OutPort(Bits32) @s.update def upblk(): s.out = foo.foo a = A() a.elaborate() a._rtlir_freevar_ref = {'foo': a._foo} do_test(a)
def test_reduce(do_test): class v_reduce(Component): def construct(s): s.in_1 = InPort(Bits32) s.in_2 = InPort(Bits32) s.in_3 = InPort(Bits32) s.out = OutPort(Bits1) @s.update def v_reduce(): s.out = reduce_and(s.in_1) & reduce_or(s.in_2) | reduce_xor( s.in_3) a = v_reduce() in_1 = Attribute(Base(a), 'in_1') in_2 = Attribute(Base(a), 'in_2') in_3 = Attribute(Base(a), 'in_3') out = Attribute(Base(a), 'out') a._rtlir_test_ref = { 'v_reduce': CombUpblk('v_reduce', [ Assign( out, BinOp( BinOp(Reduce(BitAnd(), in_1), BitAnd(), Reduce(BitOr(), in_2)), BitOr(), Reduce(BitXor(), in_3), ), True) ]) } a._test_vector = [ ' in_1 in_2 in_3 *out', [Bits32, Bits32, Bits32, Bits1], [0, 1, 2, 1], [b32(-1), 1, b32(-1), 1], [9, 8, 7, 1], ] do_test(a)
def test_normal_queue(do_test): # Test a Placeholder with params in `construct` def tv_in(m, tv): m.enq_en @= tv[0] m.enq_msg @= tv[1] m.deq_en @= tv[3] def tv_out(m, tv): if tv[2] != '*': assert m.enq_rdy == tv[2] if tv[4] != '*': assert m.deq_rdy == tv[5] if tv[5] != '*': assert m.deq_msg == tv[4] class VQueue(Component, Placeholder): def construct(s, data_width, num_entries, count_width): s.count = OutPort(mk_bits(count_width)) s.deq_en = InPort(Bits1) s.deq_rdy = OutPort(Bits1) s.deq_msg = OutPort(mk_bits(data_width)) s.enq_en = InPort(Bits1) s.enq_rdy = OutPort(Bits1) s.enq_msg = InPort(mk_bits(data_width)) s.set_metadata(VerilogTranslationImportPass.enable, True) num_entries = 1 q = VQueue(data_width=32, num_entries=num_entries, count_width=clog2(num_entries + 1)) tv = [ # enq deq # en msg rdy en msg rdy [1, 42, 1, 0, 0, 0], [0, 43, 0, 1, 42, 1], [1, 43, 1, 0, 42, 0], [0, 44, 0, 1, 43, 1], [1, 44, 1, 0, 43, 0], [0, 45, 0, 1, 44, 1], [1, 45, 1, 0, 44, 0], ] q._tv = tv q._tv_in = tv_in q._tv_out = tv_out do_test(q)
def test_multi_components_tmpvars(do_test): class B(Component): def construct(s): s.out = OutPort(Bits16) @s.update def upblk(): u = Bits16(0) s.out = u class A(Component): def construct(s): s.b = B() s.out = OutPort(Bits16) @s.update def upblk(): u = s.b.out s.out = u a = A() a.elaborate() a._ref_upblk_repr = { a : \ """\ upblk_srcs: upblk_src: upblk """, a.b : \ """\ upblk_srcs: upblk_src: upblk """ } a._ref_freevar_repr = {a: "freevars:\n", a.b: "freevars:\n"} a._ref_tmpvar_repr = { a : \ """\ tmpvars: tmpvar: u in upblk of Vector16 """, a.b : \ """\ tmpvars: tmpvar: u in upblk of Vector16 """ } do_test(a)
def test_nested_struct(do_test): class inner_struct(BitStruct): def __init__(s, foo=42): s.foo = Bits32(foo) class struct(BitStruct): def __init__(s, bar=1): s.bar = Bits32(bar) s.inner = inner_struct() class A(Component): def construct(s): s.in_ = [InPort(struct) for _ in range(2)] a = A() # Inner struct will not be added to `symbols` because struct # refers to it! a._ref_symbols = {'struct': struct} a._ref_decls = [ "s.in_ = [ InPort( struct ) for _ in range(2) ]", ] a._ref_conns = [ "connect( s.clk, s.mangled__clk[0:1] )", "@s.update", "def in__LBR_0_RBR_():", " s.mangled__in_[0][0:32] = s.in_[0].inner.foo", " s.mangled__in_[0][32:64] = s.in_[0].bar", "@s.update", "def in__LBR_1_RBR_():", " s.mangled__in_[1][0:32] = s.in_[1].inner.foo", " s.mangled__in_[1][32:64] = s.in_[1].bar", "connect( s.reset, s.mangled__reset[0:1] )" ] a._ref_conns_yosys = [ "connect( s.clk, s.mangled__clk )", "@s.update", "def in__LBR_0_RBR_():", " s.mangled__in___05F_0___05Finner___05Ffoo = s.in_[0].inner.foo", " s.mangled__in___05F_0___05Fbar = s.in_[0].bar", "@s.update", "def in__LBR_1_RBR_():", " s.mangled__in___05F_1___05Finner___05Ffoo = s.in_[1].inner.foo", " s.mangled__in___05F_1___05Fbar = s.in_[1].bar", "connect( s.reset, s.mangled__reset )" ] do_test(a)
def test_subcomp_decl( do_test ): class B( Component ): def construct( s ): s.out_b = OutPort( Bits32 ) @s.update def upblk(): s.out_b = Bits32(0) class A( Component ): def construct( s ): s.out_a = OutPort( Bits32 ) s.b = B() connect( s.b.out_b, s.out_a ) a = A() a._ref_subcomps = { a : \ """\ logic [0:0] b__clk; logic [31:0] b__out_b; logic [0:0] b__reset; B b ( .clk( b__clk ), .out_b( b__out_b ), .reset( b__reset ) );\ """ } a._ref_comps_port_yosys = a._ref_subcomps a._ref_comps_wire_yosys = { a : "" } a._ref_comps_conn_yosys = { a : "" } # TestVectorSimulator properties def tv_in( m, tv ): pass def tv_out( m, tv ): assert m.out_a == Bits32(tv[0]) a._test_vectors = [ [ 0 ], ] a._tv_in, a._tv_out = tv_in, tv_out do_test( a )
def test_fixed_size_slice(do_test): a = CaseConstSizeSlicingComp.DUT() a._rtlir_test_ref = { 'upblk': CombUpblk('upblk', [ For(LoopVarDecl('i'), Number(0), Number(2), Number(1), [ Assign([Index(Attribute(Base(a), 'out'), LoopVar('i'))], Slice( Attribute(Base(a), 'in_'), BinOp(LoopVar('i'), Mult(), Number(8)), BinOp(BinOp(LoopVar('i'), Mult(), Number(8)), Add(), Number(8)), BinOp(LoopVar('i'), Mult(), Number(8)), 8, ), True) ]) ]) } do_test(a)
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', rt.Port('input', rdt.Vector(1))), ('in_', rt.Port('input', st)), ('reset', rt.Port('input', rdt.Vector(1)))] a._ref_ports_yosys = [('clk', rt.Port('input', rdt.Vector(1))), ('in___bar', rt.Port('input', rdt.Vector(32))), ('in___foo', rt.Port('input', rdt.Vector(32))), ('reset', rt.Port('input', rdt.Vector(1)))] do_test(a)
def test_if_basic(do_test): a = CaseIfBasicComp.DUT() a._rtlir_test_ref = { 'if_basic': CombUpblk('if_basic', [ If( Compare(Slice(Attribute(Base(a), 'in_'), Number(0), Number(8)), Eq(), SizeCast(8, Number(255))), [ Assign([Attribute(Base(a), 'out')], Slice(Attribute(Base(a), 'in_'), Number(8), Number(16)), True) ], [ Assign([Attribute(Base(a), 'out')], SizeCast(8, Number(0)), True) ]) ]) } do_test(a)
def test_sub_component_attr(do_test): class B(Component): def construct(s): s.out_b = OutPort(Bits32) @s.update def upblk(): s.out_b = Bit32(0) class A(Component): def construct(s): s.b = B() s.out = OutPort(Bits64) @s.update def upblk(): s.out = zext(s.b.out_b, 64) with expected_failure(SVerilogTranslationError, "sub-components"): do_test(A())
def test_pymtl_list_Bits_freevar( do_test ): freevar = [ Bits32(42) for _ in range(5) ] class A( Component ): def construct( s ): s.out = OutPort( Bits32 ) @s.update def upblk(): s.out = freevar[2] a = A() a._ref_upblk_repr = \ """\ upblk_srcs: upblk_src: upblk """ a._ref_freevar_repr = \ """\ freevars: freevar: freevar """ do_test( a )
def test_port_single(do_test): class A(Component): def construct(s): s.in_ = InPort(mk_bits(322)) a = A() a._ref_symbols = {'Bits322': mk_bits(322)} a._ref_decls = [ "s.in_ = InPort( Bits322 )", ] a._ref_conns = [ "connect( s.clk, s.mangled__clk[0:1] )", "connect( s.in_, s.mangled__in_[0:322] )", "connect( s.reset, s.mangled__reset[0:1] )" ] a._ref_conns_yosys = [ "connect( s.clk, s.mangled__clk )", "connect( s.in_, s.mangled__in_ )", "connect( s.reset, s.mangled__reset )" ] do_test(a)
def test_multi_tmp_wire_struct(do_test): @bitstruct class C: bar: Bits32 @bitstruct class B: foo: Bits32 class A(Component): def construct(s): s.in_b = InPort(B) s.in_c = InPort(C) s.out_b = OutPort(Bits32) s.out_c = OutPort(Bits32) @s.update def upblk1(): u = s.in_b s.out_b = u.foo @s.update def upblk2(): u = s.in_c s.out_c = u.bar a = A() a._ref_upblk_repr = \ """\ upblk_srcs: upblk_src: upblk1 upblk_src: upblk2 """ a._ref_freevar_repr = "freevars:\n" a._ref_tmpvar_repr = \ """\ tmpvars: tmpvar: u in upblk1 of Struct B tmpvar: u in upblk2 of Struct C """ do_test(a)
def test_wire_decls(do_test): class A(Component): def construct(s): s.foo = Wire(Bits32) s.bar = Wire(Bits4) @s.update def upblk(): s.foo = 42 s.bar = Bits4(0) a = A() a._ref_name = "A" a._ref_ports = "port_decls:\n" a._ref_wires = \ """\ wire_decls: wire_decl: bar Wire of Vector4 wire_decl: foo Wire of Vector32 """ a._ref_src = \ """\ component {} ( port_decls: interface_decls: ); const_decls: freevars: wire_decls: wire_decl: bar Wire of Vector4 wire_decl: foo Wire of Vector32 component_decls: tmpvars: upblk_srcs: upblk_src: upblk connections: endcomponent """.format( a._ref_name ) do_test(a)
def test_freevar(do_test): class A(Component): def construct(s): STATE_IDLE = Bits32(42) s.in_ = InPort(Bits32) s.out = OutPort(Bits64) @s.update def upblk(): s.out = concat(s.in_, STATE_IDLE) a = A() a._ref_upblk_srcs = { 'upblk' : \ """\ always_comb begin : upblk out = { in_, __const__STATE_IDLE }; end\ """ } # TestVectorSimulator properties def tv_in(m, tv): m.in_ = Bits32(tv[0]) def tv_out(m, tv): assert m.out == Bits64(tv[1]) a._test_vectors = [ [42, concat(Bits32(42), Bits32(42))], [-1, concat(Bits32(-1), Bits32(42))], [-2, concat(Bits32(-2), Bits32(42))], [2, concat(Bits32(2), Bits32(42))], ] a._tv_in, a._tv_out = tv_in, tv_out a._ref_upblk_srcs_yosys = { 'upblk' : \ """\ always_comb begin : upblk out = { in_, 32'd42 }; end\ """ } do_test(a)
def test_if_basic(do_test): class if_basic(Component): def construct(s): s.in_ = InPort(Bits16) s.out = OutPort(Bits8) @s.update def if_basic(): if s.in_[0:8] == Bits8(255): s.out = s.in_[8:16] else: s.out = Bits8(0) a = if_basic() a._rtlir_test_ref = { 'if_basic': CombUpblk('if_basic', [ If( Compare(Slice(Attribute(Base(a), 'in_'), Number(0), Number(8)), Eq(), SizeCast(8, Number(255))), [ Assign( Attribute(Base(a), 'out'), Slice(Attribute(Base(a), 'in_'), Number(8), Number(16)), True) ], [ Assign(Attribute(Base(a), 'out'), SizeCast(8, Number(0)), True) ]) ]) } a._test_vector = [ 'in_ *out', [Bits16, Bits8], [255, 0], [511, 1], [256, 0], ] do_test(a)
def test_L1_attr_signal(do_test): @bitstruct class B: """Struct class used to trigger certain exception. Struct does not belong to level 1. It is just used for testing purposes. """ foobar: Bits32 class A(Component): def construct(s): s.in_ = InPort(B) s.out = OutPort(Bits32) @s.update def upblk(): s.out = s.in_.foobar with expected_failure(PyMTLTypeError, "base of an attribute must be a component"): do_test(A())
def test_reduce(do_test): a = CaseReducesInx3OutComp.DUT() in_1 = Attribute(Base(a), 'in_1') in_2 = Attribute(Base(a), 'in_2') in_3 = Attribute(Base(a), 'in_3') out = Attribute(Base(a), 'out') a._rtlir_test_ref = { 'v_reduce': CombUpblk('v_reduce', [ Assign([out], BinOp( BinOp(Reduce(BitAnd(), in_1), BitAnd(), Reduce(BitOr(), in_2)), BitOr(), Reduce(BitXor(), in_3), ), True) ]) } do_test(a)
def test_index_static( do_test, Type, data ): class A( Component ): def construct( s, Type ): s.in_ = [InPort ( Type ) for _ in range(2)] s.out = [OutPort( Type ) for _ in range(2)] @s.update def index_upblk(): if s.in_[0] > s.in_[1]: s.out[0] = Type(1) s.out[1] = Type(0) else: s.out[0] = Type(0) s.out[1] = Type(1) def line_trace( s ): return "s.in0 = " + str( s.in_[0] ) +\ "s.in1 = " + str( s.in_[1] ) +\ "s.out0 = " + str( s.out[0] ) +\ "s.out1 = " + str( s.out[1] ) a = A( Type ) a._data = data do_test( a )