def test_tester_magma_internal_signals_verilator(target): circ = common.SimpleALU tester = SymbolicTester(circ, circ.CLK, num_tests=100) tester.circuit.config_en = 1 tester.circuit.config_data = 0 tester.step(2) # TODO: Handle case with only 1 step in cosa backend, then these would just # become assumptions tester.circuit.config_en = 0 tester.step(2) if target == "verilator": # TODO: We could turn this expect into a CoSA assert tester.circuit.config_reg.Q.expect(0) tester.circuit.a.assume(lambda a: a < BitVector(32768, 16)) tester.circuit.b.assume(lambda b: b < BitVector(32768, 16)) # tester.circuit.b.assume(lambda b: b >= BitVector(32768, 16)) # tester.circuit.a.assume(lambda a: a < ((1 << 16) - 1)) # tester.circuit.b.assume(lambda b: b < ((1 << 16) - 1)) # TODO: Dependent constraints, e.g. # tester.ciruit.assume(lambda a, b: a > 0 and b > a) # tester.circuit.c.guarantee(lambda x: x > 0) tester.circuit.c.guarantee(lambda a, b, c: (c >= a) and (c >= b)) with tempfile.TemporaryDirectory() as _dir: kwargs = {} if target == "verilator": kwargs["flags"] = ["-Wno-fatal"] kwargs["magma_opts"] = {"verilator_debug": True} elif target == "cosa": kwargs["magma_opts"] = { "passes": ["rungenerators", "flatten", "cullgraph"] } tester.compile_and_run(target, directory=_dir, **kwargs)
def test_tester_nested_array_tuple(): tester = PythonTester(TestNestedArrayTupleCircuit) expected = [] val = (BitVector.random(4), BitVector.random(4)) tester.poke(TestNestedArrayTupleCircuit.I, val) tester.eval() tester.expect(TestNestedArrayTupleCircuit.O, val)
def test_print_nested_arrays(capfd, target, simulator): circ = common.TestNestedArraysCircuit actions = [ Poke(circ.I, [BitVector(i, 4) for i in range(3)]), Print(circ.I), Eval(), Expect(circ.O, [BitVector(i, 4) for i in range(3)]), Print(circ.O), Poke(circ.I, [BitVector(4 - i, 4) for i in range(3)]), Eval(), Print(circ.O), ] run(circ, actions, target, simulator, flags=["-Wno-lint"]) out, err = capfd.readouterr() if target == fault.verilator_target.VerilatorTarget: actual = "\n".join(out.splitlines()[-9:]) else: if simulator == "ncsim": actual = "\n".join(out.splitlines()[-9 - 3:-3]) elif simulator == "vcs": actual = "\n".join(out.splitlines()[-9 - 6:-6]) else: raise NotImplementedError(f"Unsupported simulator: {simulator}") assert actual == """\ NestedArraysCircuit.I[0] = 0 NestedArraysCircuit.I[1] = 1 NestedArraysCircuit.I[2] = 2 NestedArraysCircuit.O[0] = 0 NestedArraysCircuit.O[1] = 1 NestedArraysCircuit.O[2] = 2 NestedArraysCircuit.O[0] = 4 NestedArraysCircuit.O[1] = 3 NestedArraysCircuit.O[2] = 2""", out
def advance_clk(self, addr, data): save_stall_reg = self.stall[-1] temp_stall_reg = BitVector(0, self.num_stall_domains) mask = BitVector(addr, self.num_stall_domains) for i in range(self.num_stall_domains): if (mask[i] == 1): temp_stall_reg[i] = 0 self.stall = [temp_stall_reg] * data + [save_stall_reg]
def __init__(self, address_width, data_width): self.address_width = address_width self.data_width = data_width self.data_depth = 1 << address_width self.memory = { BitVector(i, address_width): BitVector(0, data_width) for i in range(self.data_depth) }
def config_write(self, addr, data): rw_delay = self.rw_delay_sel[0] duration = rw_delay.as_uint() self.read = [0] * (duration + 1) self.write = [1] * duration + [0] self.config_addr_out = [BitVector(addr, config_addr_width)] \ * (duration + 1) self.config_data_out = [BitVector(data, config_data_width)] \ * (duration + 1)
def test_simple_alu_sequence(circuit, driver, monitor, clock): """ Reuse the same input/output sequence for core and tile """ sequence = [(BitVector.random(16), BitVector.random(16), BitVector.random(2)) for _ in range(5)] tester = SequenceTester(circuit, driver, monitor, sequence, clock=clock) tester.compile_and_run("verilator")
def test_concat_random(): for _ in range(NTESTS): n1 = random.randint(1, MAX_BITS) n2 = random.randint(1, MAX_BITS) a = BitVector.random(n1) b = BitVector.random(n2) c = a.concat(b) assert c.size == a.size + b.size assert c == BitVector[n1 + n2](a.bits() + b.bits()) assert c.binary_string() == b.binary_string() + a.binary_string()
def test_tester_nested_arrays(): circ = common.TestNestedArraysCircuit builder = VectorBuilder(circ) expected = [] for i in range(3): val = random.randint(0, (1 << 4) - 1) builder.process(Poke(circ.I[i], BitVector(val, 4))) builder.process(Expect(circ.O[i], BitVector(val, 4))) expected.append(val) assert builder.vectors == [[Array(expected, 3), Array(expected, 3)]]
class BrCond_DUT(m.Circuit): _IGNORE_UNUSED_ = True io = m.IO( done=m.Out(m.Bit), out=m.Out(m.Bit), taken=m.Out(m.Bit) ) + m.ClockIO() br_cond = BrCond(x_len)() io.taken @= br_cond.taken control = Control(x_len)() br_cond.br_type @= control.br_type insts = [ B(Funct3.BEQ, 0, 0, 0), B(Funct3.BNE, 0, 0, 0), B(Funct3.BLT, 0, 0, 0), B(Funct3.BGE, 0, 0, 0), B(Funct3.BLTU, 0, 0, 0), B(Funct3.BGEU, 0, 0, 0), ] * 10 n = len(insts) counter = CounterModM(n, n.bit_length()) control.inst @= m.mux(insts, counter.O) io.done @= counter.COUT rs1 = [BV.random(x_len) for _ in range(n)] rs2 = [BV.random(x_len) for _ in range(n)] br_cond.rs1 @= m.mux(rs1, counter.O) br_cond.rs2 @= m.mux(rs2, counter.O) eq = [a == b for a, b in zip(rs1, rs2)] ne = [a != b for a, b in zip(rs1, rs2)] lt = [m.sint(a) < m.sint(b) for a, b in zip(rs1, rs2)] ge = [m.sint(a) >= m.sint(b) for a, b in zip(rs1, rs2)] ltu = [a < b for a, b in zip(rs1, rs2)] geu = [a >= b for a, b in zip(rs1, rs2)] @m.inline_combinational() def logic(): if control.br_type == BR_EQ: io.out @= m.mux(eq, counter.O) elif control.br_type == BR_NE: io.out @= m.mux(ne, counter.O) elif control.br_type == BR_LT: io.out @= m.mux(lt, counter.O) elif control.br_type == BR_GE: io.out @= m.mux(ge, counter.O) elif control.br_type == BR_LTU: io.out @= m.mux(ltu, counter.O) elif control.br_type == BR_GEU: io.out @= m.mux(geu, counter.O) else: io.out @= False
def test_alu_basic(alu): tester = fault.Tester(alu(16)) for i, (alu_op, py_op) in enumerate(OP_MAP.items()): A, B = BitVector.random(16), BitVector.random(16) tester.circuit.A = A tester.circuit.B = B tester.circuit.op = alu_op tester.eval() tester.circuit.O.expect(py_op(A, B)) tester.compile_and_run("verilator", flags=["-Wno-unused"])
def write_bit012(pe, bit0: Bit, bit1: Bit, bit2: Bit, instr=asm.add()): BV1 = BitVector[1] config_addr = Data8(BIT012_ADDR) config_data = BitVector.concat( BitVector.concat(BitVector.concat(BV1(bit0), BV1(bit1)), BV1(bit2)), BitVector[29](0)) config_en = Bit(1) return pe(instr, data0=Data(0), config_addr=config_addr, config_data=config_data, config_en=config_en)
def write_gc_reg(self, addr, data): if (addr == GCRegAddr.TST_ADDR): self.TST = [BitVector(data, config_data_width)] elif (addr == GCRegAddr.STALL_ADDR): self.stall = [BitVector(data, self.num_stall_domains)] elif (addr == GCRegAddr.CLK_SEL_ADDR): self.clk_sel = [BitVector(data, 1)] elif (addr == GCRegAddr.RW_DELAY_SEL_ADDR): self.rw_delay_sel = [BitVector(data, config_data_width)] elif (addr == GCRegAddr.CLK_SWITCH_DELAY_SEL_ADDR): self.clk_switch_delay_sel = [BitVector(data, 1)] else: raise ValueError("Writing to invalid GC_reg address")
def test_register(): width = 16 num_tests = 10 init_value = BitVector.random(width) reg = Register(width, init_value) mod_src = verilog(reg) with tempfile.TemporaryDirectory() as tempdir: filename = os.path.join(tempdir, reg.name + ".sv") with open(filename, "w+") as f: for value in mod_src.values(): f.write(value) f.write("\n") # import it as magma circuit circuit = magma.DefineFromVerilogFile(filename, type_map={ "clk": magma.In(magma.Clock), "reset": magma.In( magma.AsyncReset)}, target_modules=[reg.name], shallow=True)[0] tester = fault.Tester(circuit, circuit.clk) tester.zero_inputs() tester.poke(circuit.clk_en, 1) # test it with clk en signal data = [BitVector.random(width) for _ in range(num_tests)] for i in range(10): tester.poke(circuit.I, data[i]) if i > 0: tester.expect(circuit.O, data[i - 1]) tester.step(2) # test clock gating tester.poke(circuit.clk_en, 0) for i in range(10): tester.poke(circuit.I, BitVector.random(width)) tester.step(2) tester.expect(circuit.O, data[num_tests - 1]) tester.compile_and_run(target="verilator", skip_compile=True, directory=tempdir, flags=["-Wno-fatal"])
def compare(self, a, b, res): eq = a == b eq = eq.as_int() a_msb = msb(a) b_msb = msb(b) c_msb = msb(res) if self.signed: ge = int((~(a_msb ^ b_msb) & ~c_msb) | (~a_msb & b_msb)) & 1 le = int((~(a_msb ^ b_msb) & c_msb) | (a_msb & ~b_msb) | eq) & 1 else: ge = int((~(a_msb ^ b_msb) & ~c_msb) | (a_msb & ~b_msb)) & 1 le = int((~(a_msb ^ b_msb) & c_msb) | (~a_msb & b_msb) | eq) & 1 return BitVector(ge, num_bits=1), \ BitVector(eq, num_bits=1), \ BitVector(le, num_bits=1), \
def test_tester_file_scanf(target, simulator): if simulator == "iverilog": pytest.skip("iverilog does not support scanf") with tempfile.TemporaryDirectory(dir=".") as _dir: # determine absolute paths to file I/O locations test_file_in = (Path(_dir) / 'test_file_in.txt').resolve() # create testbench circ = TestUInt32Circuit tester = fault.Tester(circ) tester.zero_inputs() file_in = tester.file_open(str(test_file_in), "r") config_addr = tester.Var("config_addr", BitVector[32]) config_data = tester.Var("config_data", BitVector[32]) loop = tester.loop(8) loop.file_scanf(file_in, "%x %x", config_addr, config_data) loop.poke(circ.I, config_addr + 1) loop.eval() loop.expect(circ.O, config_addr + 1) loop.poke(circ.I, config_data) loop.eval() loop.expect(circ.O, config_data) tester.file_close(file_in) # write input with open(test_file_in, "w") as file: file.write(hex(int(BitVector.random(32)))[2:]) # run simulation if target == "verilator": tester.compile_and_run(target, directory=_dir, flags=["-Wno-fatal"]) else: tester.compile_and_run(target, directory=_dir, simulator=simulator)
def run(self, actions): simulator = self.backend_cls(self.circuit, self.clock) for action in actions: if isinstance(action, fault.actions.Poke): value = action.value # Python simulator does not support setting Bit with # BitVector(1), so do conversion here if isinstance(action.port, m.BitType) and \ isinstance(value, BitVector): value = value.as_uint() simulator.set_value(action.port, value) elif isinstance(action, fault.actions.Print): got = simulator.get_value(action.port) if isinstance(action.port, m.ArrayType) and \ isinstance(action.port.T, (m._BitType, m._BitKind)): got = BitVector(got).as_uint() elif isinstance(action.port, m.ArrayType): raise NotImplementedError("Printing complex nested arrays") print(f'{action.port.debug_name} = {action.format_str}' % got) elif isinstance(action, fault.actions.Expect): got = simulator.get_value(action.port) expected = action.value if isinstance(expected, fault.actions.Peek): expected = simulator.get_value(expected.port) MagmaSimulatorTarget.check(got, action.port, expected) elif isinstance(action, fault.actions.Eval): simulator.evaluate() elif isinstance(action, fault.actions.Step): if self.clock is not action.clock: raise RuntimeError(f"Using different clocks: {self.clock}, " f"{action.clock}") simulator.advance_cycle(action.steps) else: raise NotImplementedError(action)
def test_tester_file_scanf(target, simulator): if simulator == "iverilog": pytest.skip("iverilog does not support scanf") circ = TestUInt32Circuit tester = fault.Tester(circ) tester.zero_inputs() file_in = tester.file_open("test_file_in.txt", "r") config_addr = tester.Var("config_addr", BitVector[32]) config_data = tester.Var("config_data", BitVector[32]) loop = tester.loop(8) loop.file_scanf(file_in, "%x %x", config_addr, config_data) loop.poke(circ.I, config_addr + 1) loop.eval() loop.expect(circ.O, config_addr + 1) loop.poke(circ.I, config_data) loop.eval() loop.expect(circ.O, config_data) tester.file_close(file_in) with tempfile.TemporaryDirectory(dir=".") as _dir: with open(_dir + "/test_file_in.txt", "w") as file: file.write(hex(int(BitVector.random(32)))[2:]) if target == "verilator": tester.compile_and_run(target, directory=_dir, flags=["-Wno-fatal"]) else: tester.compile_and_run(target, directory=_dir, simulator=simulator)
def test_target_clock(capfd, target, simulator): circ = common.TestBasicClkCircuit actions = [ Poke(circ.I, 0), Print(circ.I), Expect(circ.O, 0), Poke(circ.CLK, 0), Print(circ.O), Step(circ.CLK, 1), Poke(circ.I, BitVector(1, 1)), Eval(), Print(circ.O), ] run(circ, actions, target, simulator, flags=["-Wno-lint"]) out, err = capfd.readouterr() lines = out.splitlines() if target == fault.verilator_target.VerilatorTarget: assert lines[-3] == "BasicClkCircuit.I = 0", out assert lines[-2] == "BasicClkCircuit.O = 0", out assert lines[-1] == "BasicClkCircuit.O = 1", out else: if simulator == "ncsim": assert lines[-6] == "BasicClkCircuit.I = 0", out assert lines[-5] == "BasicClkCircuit.O = 0", out assert lines[-4] == "BasicClkCircuit.O = 1", out elif simulator == "vcs": assert lines[-9] == "BasicClkCircuit.I = 0", out assert lines[-8] == "BasicClkCircuit.O = 0", out assert lines[-7] == "BasicClkCircuit.O = 1", out else: raise NotImplementedError(f"Unsupported simulator: {simulator}")
def add_peak_primitive(self, prim_name, family_closure): c = self.context #Just pass in BitVector to get the class peak_class = family_closure(BitVector.get_family()) peak_fn = peak_class.__call__ #Create the coreIR type for this module inputs = peak_fn._peak_inputs_ outputs = peak_fn._peak_outputs_ isa = peak_fn._peak_isa_[1] record_params = OrderedDict() for (io, bit_dir) in ((inputs, c.BitIn()), (outputs, c.Bit())): for name, bvtype in io.items(): if issubclass(bvtype, AbstractBit): btype = bit_dir elif issubclass(bvtype, AbstractBitVector): btype = self.context.Array(bvtype.size, bit_dir) else: raise ValueError("Bad type") record_params[name] = btype modtype = c.Record(record_params) coreir_prim = self.ns.new_module(prim_name, modtype) self.peak_primitives[prim_name] = (coreir_prim, family_closure, isa) self.add_backend_primitive(coreir_prim) return coreir_prim
def get_constant_instance(self, constant, num_bits, module_definition): if module_definition not in self.__constant_cache: self.__constant_cache[module_definition] = {} bit_type_to_constant_map = {GND: 0, VCC: 1} if constant in bit_type_to_constant_map: value = bit_type_to_constant_map[constant] elif isinstance(constant, ArrayType): value = BitVector([bit_type_to_constant_map[x] for x in constant]) else: raise NotImplementedError(constant) if (value, num_bits) not in self.__constant_cache[module_definition]: self.__unique_constant_id += 1 if num_bits is None: config = self.context.new_values({"value": bool(value)}) name = "bit_const_{}_{}".format(value, num_bits) corebit_const_module = self.libs['corebit'].modules["const"] module_definition.add_module_instance(name, corebit_const_module, config) else: gen_args = self.context.new_values({"width": num_bits}) config = self.context.new_values({"value": value}) # name = "const_{}_{}".format(constant, self.__unique_constant_id) name = "const_{}_{}".format(value, num_bits) const_generator = self.libs['coreir'].generators["const"] module_definition.add_generator_instance( name, const_generator, gen_args, config) # return module_definition.select("{}.out".format(name)) self.__constant_cache[module_definition][( value, num_bits)] = module_definition.select("{}.out".format(name)) return self.__constant_cache[module_definition][(value, num_bits)]
def test_automapper(): IR = gen_SmallIR(8) arch_fc = PE_fc arch_bv = arch_fc(family.PyFamily()) arch_mapper = ArchMapper(arch_fc) expect_found = ('Add', 'Sub', 'And', 'Nand', 'Or', 'Nor', 'Not', 'Neg') expect_not_found = ('Mul', 'Shftr', 'Shftl', 'Not', 'Neg') for ir_name, ir_fc in IR.instructions.items(): ir_mapper = arch_mapper.process_ir_instruction(ir_fc) rewrite_rule = ir_mapper.solve('z3') if rewrite_rule is None: assert ir_name in expect_not_found continue assert ir_name in expect_found #verify the mapping works counter_example = rewrite_rule.verify() assert counter_example is None ir_bv = ir_fc(family.PyFamily()) for _ in range(num_test_vectors): ir_vals = { path: BitVector.random(8) for path in rewrite_rule.ir_bounded } ir_inputs = rewrite_rule.build_ir_input(ir_vals, family.PyFamily()) arch_inputs = rewrite_rule.build_arch_input( ir_vals, family.PyFamily()) assert ir_bv()(**ir_inputs) == arch_bv()(**arch_inputs)
def get_width(isa: ISABuilder): if _issubclass(isa, Enum): width = 0 for e in map(lambda x: x.value, isa): if isinstance(e, int): width = max(width, e.bit_length()) elif isinstance(e, AbstractBitVector): width = max(width, e.size) elif isinstance(e, bool): width = max(width, 1) elif isinstance(e, AbstractBit): width = max(width, 1) else: raise TypeError() return width elif _issubclass(isa, (Tuple, Product)): return sum(map(get_width, isa.fields)) elif _issubclass(isa, Sum): return max(map(get_width, isa.fields)) + len(isa.fields).bit_length() elif _issubclass(isa, AbstractBitVector): return isa.size elif _issubclass(isa, AbstractBit) or isinstance(isa, AbstractBit): return 1 elif isinstance(isa, AbstractBitVector): return isa.size elif isinstance(isa, int): return BitVector(isa).size else: raise TypeError(isa)
def check(circuit, sim, number_of_cycles, inputs_generator=None): simulator = PythonSimulator(circuit, clock=circuit.CLK) failed = False for cycle in range(number_of_cycles): if inputs_generator is None: next(sim) else: inputs = [] for name, port in circuit.interface.ports.items(): if name in ["CLK", "CE"]: continue # Skip clocks, TODO: Check the type if port.isoutput(): # circuit input input_value = getattr(inputs_generator, name) inputs.append(input_value) simulator.set_value(getattr(circuit, name), input_value) next(inputs_generator) if len(inputs) > 1: sim.send(inputs) elif len(inputs) == 1: sim.send(inputs[0]) else: next(sim) simulator.advance(2) # Coroutine has an implicit __next__ call on construction so it already # is in it's initial state for name, port in circuit.interface.ports.items(): if port.isinput(): # circuit output if getattr(sim, name) != BitVector( simulator.get_value(getattr(circuit, name))): print( f"Failed on cycle {cycle}, port {name}, expected {getattr(sim, name)}, got {BitVector(simulator.get_value(getattr(circuit, name)))}" ) failed = True assert not failed, "Failed to pass simulation"
def check_gc_reg(gc_inst, reg: GCRegAddr): if (reg == GCRegAddr.TST_ADDR): rd_op = GCOp.READ_TST wr_op = GCOp.WRITE_TST width = gc_inst.TST[0].num_bits elif (reg == GCRegAddr.STALL_ADDR): rd_op = GCOp.READ_STALL wr_op = GCOp.WRITE_STALL width = gc_inst.stall[0].num_bits elif (reg == GCRegAddr.CLK_SEL_ADDR): rd_op = GCOp.READ_CLK_DOMAIN wr_op = GCOp.SWITCH_CLK width = 1 elif (reg == GCRegAddr.RW_DELAY_SEL_ADDR): rd_op = GCOp.READ_RW_DELAY_SEL wr_op = GCOp.WRITE_RW_DELAY_SEL width = gc_inst.rw_delay_sel[0].num_bits elif (reg == GCRegAddr.CLK_SWITCH_DELAY_SEL_ADDR): rd_op = GCOp.READ_CLK_SWITCH_DELAY_SEL wr_op = GCOp.WRITE_CLK_SWITCH_DELAY_SEL width = 1 random_data = BitVector.random(width) res = gc_inst(op=wr_op, data=random_data) # Now read it back res = gc_inst(op=rd_op) assert len(res.config_data_to_jtag) == 1 jtag = res.config_data_to_jtag[0] assert jtag == BitVector[len(jtag)](random_data)
def test_tester_nested_arrays_bulk(): tester = PythonTester(TestNestedArraysCircuit) expected = [] val = [BitVector.random(4) for _ in range(3)] tester.poke(TestNestedArraysCircuit.I, val) tester.eval() tester.expect(TestNestedArraysCircuit.O, val)
def make_expect(self, i, action): if value_utils.is_any(action.value): return [] if isinstance(action.port, SelectPath): name = f"dut.{action.port.system_verilog_path}" debug_name = action.port[-1].name elif isinstance(action.port, fault.WrappedVerilogInternalPort): name = f"dut.{action.port.path}" debug_name = name else: name = verilog_name(action.port.name) debug_name = action.port.name value = action.value if isinstance(value, actions.Peek): if isinstance(value.port, fault.WrappedVerilogInternalPort): value = f"dut.{value.port.path}" else: value = f"{value.port.name}" elif isinstance(value, PortWrapper): value = f"dut.{value.select_path.system_verilog_path}" elif isinstance(action.port, m.SIntType) and value < 0: # Handle sign extension for verilator since it expects and # unsigned c type port_len = len(action.port) value = BitVector(value, port_len).as_uint() return [ f"if ({name} != {value}) $error(\"Failed on action={i}" f" checking port {debug_name}. Expected %x, got %x\"" f", {value}, {name});" ]
def test_mux_wrapper(height, width): """ Test that the mux wrapper circuit works as expected. Specifically, we initialize a mux with random height and width, and check that the output is as expected for select in range [0, height). Note that we do not check the behavior with sel >= height, because this is undefined behavior. """ mux = MuxWrapper(height, width) assert mux.height == height assert mux.width == width assert mux.name() == f"MuxWrapper_{height}_{width}" mux_circuit = mux.circuit() tester = fault.Tester(mux_circuit) inputs = [fault.random.random_bv(width) for _ in range(height)] for i, input_ in enumerate(inputs): tester.poke(mux_circuit.I[i], input_) for i in range(height): tester.poke(mux_circuit.S, BitVector(i, mux.sel_bits)) tester.eval() tester.expect(mux_circuit.O, inputs[i]) with tempfile.TemporaryDirectory() as tempdir: tester.compile_and_run(directory=tempdir, magma_output="coreir-verilog", flags=["-Wno-fatal"])
def test_print_double_nested_arrays(capfd, target, simulator): circ = common.TestDoubleNestedArraysCircuit actions = [ Poke(circ.I, [[BitVector(i + j * 3, 4) for i in range(3)] for j in range(2)]), Print(circ.I), Eval(), Expect(circ.O, [[BitVector(i + j * 3, 4) for i in range(3)] for j in range(2)]), Print(circ.O), Poke(circ.I, [[BitVector(i + (j + 1) * 3, 4) for i in range(3)] for j in range(2)]), Eval(), Print(circ.O), ] run(circ, actions, target, simulator, flags=["-Wno-lint"]) out, err = capfd.readouterr() print(out) if target == fault.verilator_target.VerilatorTarget: actual = "\n".join(out.splitlines()[-18:]) else: if simulator == "ncsim": actual = "\n".join(out.splitlines()[-18 - 3:-3]) elif simulator == "vcs": actual = "\n".join(out.splitlines()[-18 - 6:-6]) else: raise NotImplementedError(f"Unsupported simulator: {simulator}") assert actual == """\ DoubleNestedArraysCircuit.I[0][0] = 0 DoubleNestedArraysCircuit.I[0][1] = 1 DoubleNestedArraysCircuit.I[0][2] = 2 DoubleNestedArraysCircuit.I[1][0] = 3 DoubleNestedArraysCircuit.I[1][1] = 4 DoubleNestedArraysCircuit.I[1][2] = 5 DoubleNestedArraysCircuit.O[0][0] = 0 DoubleNestedArraysCircuit.O[0][1] = 1 DoubleNestedArraysCircuit.O[0][2] = 2 DoubleNestedArraysCircuit.O[1][0] = 3 DoubleNestedArraysCircuit.O[1][1] = 4 DoubleNestedArraysCircuit.O[1][2] = 5 DoubleNestedArraysCircuit.O[0][0] = 3 DoubleNestedArraysCircuit.O[0][1] = 4 DoubleNestedArraysCircuit.O[0][2] = 5 DoubleNestedArraysCircuit.O[1][0] = 6 DoubleNestedArraysCircuit.O[1][1] = 7 DoubleNestedArraysCircuit.O[1][2] = 8\ """, out
def __call__(self, data0=0, data1=0, c=0, bit0=0, bit1=0, bit2=0, clk=0, clk_en=1): ra = self.RegA(data0, clk, clk_en) rb = self.RegB(data1, clk, clk_en) rc = self.RegC(c, clk, clk_en) rd = self.RegD(bit0, clk, clk_en) re = self.RegE(bit1, clk, clk_en) rf = self.RegF(bit2, clk, clk_en) res = ZERO res_p = BITZERO alu_res_p = BITZERO if self._add: add = self._add(ra, rb, rc, rd) if self._alu: res = self._alu(ra, rb, rc, rd) if isinstance(res, tuple): res, alu_res_p = res[0], res[1] lut_out = BITZERO if self._lut: lut_out = self._lut(rd, re, rf) res_p = self.get_flag(ra, rb, rc, rd, res, alu_res_p, lut_out) if not isinstance(res_p, BitVector): assert res_p in {0, 1}, res_p res_p = BitVector(res_p, 1) # if self._cond: # res_p = self._cond(ra, rb, res) # Set internal flags to determine whether debug trigger should be raised # for both the result and the predicate. self.raise_debug_trig = res != self._debug_trig self.raise_debug_trig_p = res_p != self._debug_trig_p return res.as_uint(), res_p.as_uint(), self.get_irq_trigger()