def test_simple_def(target, suffix): m.set_codegen_debug_info(True) And2 = m.DeclareCircuit('And2', "I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)) main = m.DefineCircuit("main", "I", m.In(m.Bits[2]), "O", m.Out(m.Bit)) and2 = And2() m.wire(main.I[0], and2.I0) m.wire(main.I[1], and2.I1) m.wire(and2.O, main.O) m.EndCircuit() m.compile("build/test_simple_def", main, output=target) assert check_files_equal(__file__, f"build/test_simple_def.{suffix}", f"gold/test_simple_def.{suffix}") # Check that the subclassing pattern produces the same annotations class Main(m.Circuit): IO = ["I", m.In(m.Bits[2]), "O", m.Out(m.Bit)] @classmethod def definition(io): and2 = And2() m.wire(io.I[0], and2.I0) m.wire(io.I[1], and2.I1) m.wire(and2.O, io.O) # Create a fresh context for second compilation. m.compile("build/test_simple_def_class", Main, output=target) m.set_codegen_debug_info(False) assert check_files_equal(__file__, f"build/test_simple_def_class.{suffix}", f"gold/test_simple_def_class.{suffix}")
def com(name, main): import magma from magma.testing import check_files_equal name += '_' + magma.mantle_target build = 'build/' + name gold = 'gold/' + name magma.compile(build, main) assert check_files_equal(__file__, build + '.v', gold + '.v') assert check_files_equal(__file__, build + '.pcf', gold + '.pcf')
def com(name, main): from magma.testing import check_files_equal name += '_' + magma.mantle_target build = 'build/' + name gold = 'gold/' + name magma.compile(build, main) assert check_files_equal(__file__, build + '.v', gold + '.v') if magma.mantle_target == 'ice40': assert check_files_equal(__file__, build + '.pcf', gold + '.pcf') elif magma.mantle_target in ['spartan3', 'spartan6']: assert check_files_equal(__file__, build + '.ucf', gold + '.ucf')
def test_coreir_mux_complex(T): class Main(m.Circuit): IO = ["I0", m.In(T), "I1", m.In(T), "S", m.In(m.Bit), "O", m.Out(T)] @classmethod def definition(circuit): MuxT = mantle.DefineMux(2, T=type(circuit.I0)) circuit.O @= MuxT()(circuit.I0, circuit.I1, circuit.S) T_str = str(T).replace("[", "").replace("]", "").replace("(", "")\ .replace(")", "").replace(",", "").replace(" ", "") m.compile(f"build/test_coreir_mux_{T_str}", Main) check_files_equal(__file__, f"build/test_coreir_mux_{T_str}.v", f"gold/test_coreir_mux_{T_str}.v")
def test_bit_term(): CorebitTerm = DefineCorebitTerm() assert repr(CorebitTerm) == """\ corebit_term = DeclareCircuit("corebit_term", "I", In(Bit))""" compile("build/test_bit_term", wrap(CorebitTerm), output="coreir") assert check_files_equal(__file__, "build/test_bit_term.json", "gold/test_bit_term.json")
def test_declare_generator(): DefineSmax = DeclareCoreIRGenerator(lib="commonlib", name="smax") width = 16 class LinkerTest(m.Circuit): name = "LinkerTest0" IO = [ "I0", m.In(m.Bits[width]), "I1", m.In(m.Bits[width]), "O", m.Out(m.Bits[width]) ] @classmethod def definition(self): Smax = DefineSmax(width=width) smax = Smax() m.wire(self.I0, smax.in0) m.wire(self.I1, smax.in1) m.wire(self.O, smax.out) dir_path = os.path.dirname(os.path.realpath(__file__)) m.compile(os.path.join(dir_path, "build/linker_test0"), LinkerTest, output="coreir") assert check_files_equal(__file__, "build/linker_test0.json", "gold/linker_test0.json")
def test_pop_count(): PopCount8 = DefinePopCount(8) m.compile('build/popcount8', PopCount8, output="coreir") assert check_files_equal(__file__, "build/popcount8.json", "gold/popcount8.json") scope = Scope() sim = CoreIRSimulator(PopCount8, None) for I, expected_O in [(1, 1), (2, 1), (3, 2)]: sim.set_value(PopCount8.I, BitVector(I, 8), scope) sim.evaluate() assert BitVector(sim.get_value(PopCount8.O, scope), 8).as_int() == expected_O m.compile('build/popcount8', PopCount8, output="verilog") assert check_files_equal(__file__, "build/popcount8.v", "gold/popcount8.v")
def test_sipo_basic(): class test_sipo_basic(m.Circuit): io = m.IO(I=m.In(m.Bit), O=m.Out(m.Bits[5])) + m.ClockIO() io.O @= SIPO(5, m.Bit)()(io.I) m.compile("build/test_sipo_basic", test_sipo_basic) assert check_files_equal(__file__, f"build/test_sipo_basic.v", f"gold/test_sipo_basic.v") tester = fault.SynchronousTester(test_sipo_basic, test_sipo_basic.CLK) tester.circuit.I = 1 tester.advance_cycle() tester.circuit.O.expect(0b00001) tester.advance_cycle() tester.circuit.O.expect(0b00011) tester.circuit.I = 0 tester.advance_cycle() tester.circuit.O.expect(0b00110) tester.circuit.I = 1 tester.advance_cycle() tester.circuit.O.expect(0b01101) tester.circuit.I = 0 tester.advance_cycle() tester.circuit.O.expect(0b11010) tester.compile_and_run("verilator", skip_compile=True, directory=os.path.join(os.path.dirname(__file__), "build"))
def test_ram(): main = m.DefineCircuit("main", "rdata", m.Out(m.Bit), "CLKIN", m.In(m.Clock)) ram = mantle.RAM(4, 1, name="ram") waddr = mantle.Counter(2, cout=False) wdata = mantle.Counter(1, cout=False) we = 1 raddr = mantle.Counter(2, cout=False) ram(raddr, waddr, wdata, we, CLK=main.CLKIN) m.wire(ram.RDATA[0], main.rdata) m.EndDefine() if m.mantle_target == "coreir": output = "coreir" suffix = "json" else: output = "verilog" suffix = "v" m.compile(f"build/test_common_ram_{m.mantle_target}", main, output) assert check_files_equal( __file__, f"build/test_common_ram_{m.mantle_target}.{suffix}", f"gold/test_common_ram_{m.mantle_target}.{suffix}")
def test_bit_const(): BitConst = DefineCorebitConst(value=1) assert repr(BitConst) == """\ corebit_const1 = DeclareCircuit("corebit_const1", "O", Out(Bit))""" compile("build/test_bit_const", wrap(BitConst), output="coreir") assert check_files_equal(__file__, "build/test_bit_const.json", "gold/test_bit_const.json")
def test_binary_op(op, N, T, TType): """ Tests mantle.operator by using the operator.{op.name} method directly and using the overloaded {op.operator} if it is not None. """ if op.name in ["mul"] and T not in (m.UInt, m.SInt): pytest.skip(f"{op.name} only defined for m.UInt and m.SInt") if op.name in ["udiv", "umod"] and T != m.UInt: pytest.skip(f"{op.name} only defined for m.UInt") elif op.name in ["sdiv", "smod"] and T != m.SInt: pytest.skip(f"{op.name} only defined for m.SInt") def to_str(x): if callable(x): return x.__name__ return str(x) _name = "TestsCircuit_" + \ "_".join(to_str(x) for x in (op.name, N, T, TType)) # List of comparison ops so we can special case them (output type and # wiring 0) comparisons = ["lt", "le", "gt", "ge"] if op.name in comparisons + ["eq", "ne"]: out_T = m.Out(m.Bit) expected_res_type = m.BitType else: out_T = m.Out(T(N)) expected_res_type = TType class TestCircuit(m.Circuit): name = _name IO = [ "I0", m.In(T(N)), "I1", m.In(T(N)), "O0", out_T, "O1", out_T, "O2", out_T ] @classmethod def definition(io): # Test using the method directly res = getattr(mantle, op.name)(io.I0, io.I1) assert isinstance(res, expected_res_type), type(res) m.wire(res, io.O0) # Test using the operator if it exists, otherwise wire 0 to O1 if op.operator is None or (op.name in ["sub", "add"] + comparisons and T == m.Bits): if op.name in comparisons: m.wire(0, io.O1) else: m.wire(m.bits(0, N), io.O1) else: res_operator = eval(f"io.I0 {op.operator} io.I1") m.wire(res_operator, io.O1) # Test integer promotion res = getattr(mantle, op.name)(io.I0, 1) m.wire(res, io.O2) m.compile(f'build/{_name}', TestCircuit, output="coreir") assert check_files_equal(__file__, f"build/{_name}.json", f"gold/{_name}.json")
def test_new_types(output): # TODO: Make it easier to do a type alias like this (for a parametrized type) def Coordinate(num_bits): return m.Bits[num_bits] # Parametrized types should be implemented using a type constructure # TODO: Add suport for isinstance(t, Polygon), need to rework to use class # structure or at least autogenerate a PolygonType (or document how to # subclass and create a new Type/Kind) def Point2D(num_bits): return m.Tuple(x=Coordinate(num_bits), y=Coordinate(num_bits)) def Polygon(num_vertices, num_bits): return m.Array[num_vertices, Point2D(num_bits)] class TestCircuit(m.Circuit): IO = [ "I", m.In(Polygon(12, 3)), "O", m.Out(Polygon(12, 3)) ] @classmethod def definition(io): m.wire(io.I, io.O) suffix = 'v' if output == 'coreir-verilog' else 'json' m.compile('build/test_new_types', TestCircuit, output=output) assert check_files_equal(__file__, f"build/test_new_types.{suffix}", f"gold/test_new_types.{suffix}")
def test_coreir_rom(): addr_width = 2 width = 16 class Mem(Circuit): name = "test_coreir_mem" IO = [ "raddr", In(Bits(addr_width)), "rdata", Out(Bits(width)), "waddr", In(Bits(addr_width)), "wdata", In(Bits(width)), "clk", In(Clock), "wen", In(Bit) ] @classmethod def definition(io): mem = DefineCoreirMem(4, 16)() wire(io.raddr, mem.raddr) wire(io.rdata, mem.rdata) wire(io.waddr, mem.waddr) wire(io.wdata, mem.wdata) wire(io.clk, mem.clk) wire(io.wen, mem.wen) compile("build/test_coreir_mem", Mem, output="coreir") assert check_files_equal(__file__, "build/test_coreir_mem.json", "gold/test_coreir_mem.json")
def com(Test, name): from magma.testing import check_files_equal name = f'test_{name}' build = f'build/{name}' gold = f'gold/{name}' m.compile(build, Test, output="verilog") assert check_files_equal(__file__, build + '.v', gold + '.v')
def test(): main = DefineCircuit("main", "O", Out(Bits[2])) wire(array([0, 1]), main.O) compile("build/out2", main) assert check_files_equal(__file__, "build/out2.v", "gold/out2.v")
def test(): main = DefineCircuit("main", "O", Out(Bit)) wire(1, main.O) compile("build/out1", main) assert check_files_equal(__file__, "build/out1.v", "gold/out1.v")
def test_for_loop_def(target, suffix): m.set_codegen_debug_info(True) And2 = m.DeclareCircuit('And2', "I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)) main = m.DefineCircuit("main", "I", m.In(m.Bits[2]), "O", m.Out(m.Bit)) and2_prev = None for i in range(0, 4): and2 = And2() if i == 0: m.wire(main.I[0], and2.I0) m.wire(main.I[1], and2.I1) else: m.wire(and2_prev.O, and2.I0) m.wire(main.I[1], and2.I1) and2_prev = and2 m.wire(and2.O, main.O) m.EndCircuit() m.compile("build/test_for_loop_def", main, output=target) m.set_codegen_debug_info(False) assert check_files_equal(__file__, f"build/test_for_loop_def.{suffix}", f"gold/test_for_loop_def.{suffix}")
def test_interleaved_instance_wiring(target, suffix): m.set_codegen_debug_info(True) And2 = m.DeclareCircuit('And2', "I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)) main = m.DefineCircuit("main", "I", m.In(m.Bits[2]), "O", m.Out(m.Bit)) and2_0 = And2() and2_1 = And2() m.wire(main.I[0], and2_0.I0) m.wire(main.I[1], and2_0.I1) m.wire(and2_0.O, and2_1.I0) m.wire(main.I[1], and2_1.I1) and2_2 = And2() m.wire(and2_1.O, and2_2.I0) m.wire(main.I[0], and2_2.I1) m.wire(and2_2.O, main.O) m.EndCircuit() m.compile("build/test_interleaved_instance_wiring", main, output=target) m.set_codegen_debug_info(False) assert check_files_equal( __file__, f"build/test_interleaved_instance_wiring.{suffix}", f"gold/test_interleaved_instance_wiring.{suffix}")
def test_bit_term(): assert repr(CorebitTerm) == """\ corebit_term = DefineCircuit("corebit_term", "in", In(Bit)) EndCircuit()""" compile("build/test_bit_term", CorebitTerm, output="coreir") assert check_files_equal(__file__, "build/test_bit_term.json", "gold/test_bit_term.json")
def test(): main = DefineCircuit("main", "I", In(Bits[2]), "O", Out(Bits[2])) wire(main.I, main.O) compile("build/inout2", main) assert check_files_equal(__file__, "build/inout2.v", "gold/inout2.v")
def test_const(): Const8 = DefineCoreirConst(width=4, value=8) assert repr(Const8) == """\ coreir_const48 = DeclareCircuit("coreir_const48", "O", Out(Bits(4)))""" compile("build/test_const", wrap(Const8), output="coreir") assert check_files_equal(__file__, "build/test_const.json", "gold/test_const.json")
def test_two_ports(backend): height = 4 data_width = 4 addr_width = m.bitutils.clog2(height) class _Main(m.Circuit): name = f"test_regfile_two_ports_{backend}" io = m.IO(write_addr0=m.In(m.Bits[addr_width]), write_data0=m.In(m.Bits[data_width]), write_addr1=m.In(m.Bits[addr_width]), write_data1=m.In(m.Bits[data_width]), read_addr0=m.In(m.Bits[addr_width]), read_data0=m.Out(m.Bits[data_width]), read_addr1=m.In(m.Bits[addr_width]), read_data1=m.Out( m.Bits[data_width])) + m.ClockIO(has_async_reset=True) reg_file = mantle.RegFileBuilder("my_regfile", height, data_width, backend=backend) reg_file[io.write_addr0] = io.write_data0 io.read_data0 @= reg_file[io.read_addr0] reg_file[io.write_addr1] = io.write_data1 io.read_data1 @= reg_file[io.read_addr1] m.compile(f"build/test_regfile_two_ports_{backend}", _Main) assert check_files_equal(__file__, f"build/test_regfile_two_ports_{backend}.v", f"gold/test_regfile_two_ports_{backend}.v") tester = fault.Tester(_Main, _Main.CLK) tester.circuit.CLK = 0 for i in range(4): tester.circuit.write_addr0 = i tester.circuit.write_data0 = 3 - i tester.circuit.write_addr1 = 3 - i tester.circuit.write_data1 = i tester.step(2) for i in range(4): tester.circuit.read_addr0 = i tester.circuit.read_addr1 = 3 - i tester.eval() tester.circuit.read_data0.expect(3 - i) tester.circuit.read_data1.expect(i) # Test priority. tester.circuit.write_addr0 = 3 tester.circuit.write_data0 = 3 tester.circuit.write_addr1 = 3 tester.circuit.write_data1 = 4 tester.step(2) tester.circuit.read_addr0 = 3 tester.eval() tester.circuit.read_data0.expect(4) build_dir = os.path.join(os.path.dirname(__file__), "build") tester.compile_and_run(target="verilator", directory=build_dir, skip_compile=True, flags=["-Wno-unused", "-Wno-undriven"])
def test_romb_coreir(): main = DefineCircuit("test_romb_coreir", "RDATAOUT", Out(Bits[16]), "CLK", In(Clock)) romb = ROMB(256, 16, [0b00000001, 0b11111111] + [0] * 254) wire(romb.RADDR, uint(1, 8)) wire(romb.RCLK, main.CLK) wire(romb.RE, enable(1)) wire(romb.RDATA, main.RDATAOUT) EndCircuit() compile("build/test_romb_coreir", main, output="coreir") assert check_files_equal(__file__, "build/test_romb_coreir.json", "gold/test_romb_coreir.json") compile("build/test_romb_coreir", main, output="coreir-verilog") assert check_files_equal(__file__, "build/test_romb_coreir.v", "gold/test_romb_coreir.v")
def test_coreir_mux_2xTuple(): A = Product.from_fields("anon", dict(a=Bit, b=Bits[2])) B = Product.from_fields("anon", dict(a=A, b=Bits[3])) mux = DefineMux(2, T=B) print(repr(mux)) compile("build/test_coreir_mux2xTuple", mux, output="coreir") assert check_files_equal(__file__, "build/test_coreir_mux2xTuple.json", "gold/test_coreir_mux2xTuple.json")
def com(Test, name): from magma import compile from magma.testing import check_files_equal name = 'test_{}'.format(name) build = 'build/' + name gold = 'gold/' + name compile(build, Test) assert check_files_equal(__file__, build + '.v', gold + '.v')
def test_bit_const(): BitConst = DefineCorebitConst(value=1) assert repr(BitConst) == """\ corebit_const1 = DefineCircuit("corebit_const1", "out", Out(Bit)) wire(1, corebit_const1.out) EndCircuit()""" compile("build/test_bit_const", BitConst, output="coreir") assert check_files_equal(__file__, "build/test_bit_const.json", "gold/test_bit_const.json")
def test_pll(): class TestPLL(m.Circuit): io = m.IO(CLKIN=m.In(m.Clock), CLKOUT=m.Out(m.Clock)) clk = SB_PLL(32000000, 16000000)(I=io.CLKIN) m.wire(clk, io.CLKOUT) m.compile("build/test_pll", TestPLL, output="coreir") assert check_files_equal(__file__, "build/test_pll.json", "gold/test_pll.json")
def com(Test, name): import magma from magma import compile from magma.testing import check_files_equal name = f'{name}_{magma.mantle_target}' build = 'build/' + name gold = 'gold/' + name compile(build, Test, output="verilog") assert check_files_equal(__file__, build + '.v', gold + '.v')
def test_no_reg(): m.config.set_debug_mode(True) DFF = DefineDFF(has_reset=True) print(repr(DFF)) compile("build/test_coreir_dff_debug_no_reg", DFF, output="coreir-verilog") assert check_files_equal(__file__, "build/test_coreir_dff_debug_no_reg.json", "gold/test_coreir_dff_debug_no_reg.json") m.config.set_debug_mode(False)
def test_array_nesting(): T = m.Array[10, m.Tuple(I=m.In(m.Bit), O=m.Out(m.Bit))] Foo = m.DefineCircuit("Foo", "IFC", T) for i in range(10): m.wire(Foo.IFC[i].I, Foo.IFC[i].O) m.EndCircuit() m.compile("build/test_array_nesting", Foo, output="coreir") assert check_files_equal(__file__, f"build/test_array_nesting.json", f"gold/test_array_nesting.json")