def test_assemble(): @family_closure def PE_fc(family): Bit = family.Bit @family.assemble(locals(), globals()) class PESimple(Peak, typecheck=True): def __call__(self, in0: Bit, in1: Bit) -> Bit: return in0 & in1 return PESimple #verify BV works PE_bv = PE_fc(family.PyFamily()) vals = [Bit(0), Bit(1)] for i0, i1 in itertools.product(vals, vals): assert PE_bv()(i0, i1) == i0 & i1 #verify SMT works PE_smt = PE_fc(family.SMTFamily()) vals = [SMTBit(0), SMTBit(1), SMTBit(), SMTBit()] for i0, i1 in itertools.product(vals, vals): assert PE_smt()(i0, i1) == i0 & i1 #verify magma works PE_magma = PE_fc(family.MagmaFamily()) tester = fault.Tester(PE_magma) vals = [0, 1] for i0, i1 in itertools.product(vals, vals): tester.circuit.in0 = i0 tester.circuit.in1 = i1 tester.eval() tester.circuit.O.expect(i0 & i1) tester.compile_and_run("verilator", flags=["-Wno-fatal"])
def test_add_peak_instruction(): class Input(Product): a = ABV[16] b = ABV[16] c = ABit class Output(Product): x = ABV[16] y = ABit ir = IR() def fun(family, a, b, c): return c.ite(a, b), c ir.add_peak_instruction("Simple", Input, Output, fun) assert "Simple" in ir.instructions Simple_fc = ir.instructions["Simple"] assert isinstance(Simple_fc, family_closure) Simple = Simple_fc(Bit.get_family()) InputBV = rebind_type(Input, Bit.get_family()) OutputBV = rebind_type(Output, Bit.get_family()) for name, t in InputBV.field_dict.items(): assert Simple.input_t.field_dict[name] is t for name, t in OutputBV.field_dict.items(): assert Simple.output_t.field_dict[name] is t simple = Simple() BV16 = BitVector[16] x, y = simple(BV16(5), BV16(6), Bit(1)) assert x == BV16(5) assert y == Bit(1)
def test_combinational_circuit(): def f(a, b, c): return (a & b) ^ c class main(m.Circuit): io = m.IO(a=m.In(m.Bit), b=m.In(m.Bit), c=m.In(m.Bit), d=m.Out(m.Bit)) m.wire(f(io.a, io.b, io.c), io.d) test_vectors = generate_function_test_vectors(main, f) assert len(test_vectors) == 2**3 + 1 # Check that vectors are as expected. The general pattern that we expect is # that the outputs of the ith vector match f() evaluated on the inputs in # the (i - 1)th vector. Also the order of the inputs matches the canonical # order of the cartesian product. for i, inputs in enumerate(product((0, 1), (0, 1), (0, 1))): vec = test_vectors[i].test_vector expected = [Bit(x) for x in inputs] assert vec[:3] == expected if i == 0: assert vec[3] == AnyValue continue prev_inputs = test_vectors[i - 1].test_vector[:3] expected = Bit(f(*prev_inputs)) assert vec[3] == expected # Checking the pattern above for the last vector. vec = test_vectors[-1].test_vector prev_inputs = test_vectors[-2].test_vector[:3] expected = Bit(f(*prev_inputs)) assert vec[3] == expected
def test_composition(): PE_magma = PE_fc(family.MagmaFamily()) PE_py = PE_fc(family.PyFamily())() tester = fault.Tester(PE_magma) Op = Inst.op0 assert Op is Inst.op1 asm = Assembler(Inst) for op0, op1, choice, in0, in1 in itertools.product( Inst.op0.enumerate(), Inst.op1.enumerate(), (Bit(0), Bit(1)), range(4), range(4), ): in0 = BitVector[16](in0) in1 = BitVector[16](in1) inst = Inst(op0=op0, op1=op1, choice=choice) gold = PE_py(inst=inst, data0=in0, data1=in1) tester.circuit.inst = asm.assemble(inst) tester.circuit.data0 = in0 tester.circuit.data1 = in1 tester.eval() tester.circuit.O.expect(gold) tester.compile_and_run("verilator", flags=["-Wno-fatal"])
def test_lut_ternary(op): pe = PE() inst = getattr(asm, f"lut_{op.name}")() for _ in range(NTESTS): sel = Bit(random.choice([0,1])) d0 = Bit(random.choice([0,1])) d1 = Bit(random.choice([0,1])) data0 = UIntVector.random(DATAWIDTH) _, res_p,_ = pe(inst, data0=data0,bit0=d0,bit1=d1,bit2=sel) assert res_p==op.func(sel,d0,d1)
def test_lut_unary(op): pe = PE() inst = getattr(asm, f"lut_{op.name}")() for _ in range(NTESTS): b0 = Bit(random.choice([0,1])) b1 = Bit(random.choice([0,1])) b2 = Bit(random.choice([0,1])) data0 = UIntVector.random(DATAWIDTH) _, res_p,_ = pe(inst, data0=data0,bit0=b0,bit1=b1,bit2=b2) assert res_p==op.func(b1)
def test_hash(): x = { Bit(0): 0, BitVector[3](0): 1, UIntVector[3](): 2, SIntVector[3](0): 3, } assert x[Bit(0)] == 0 assert x[BitVector[3](0)] == 1 assert x[UIntVector[3](0)] == 2 assert x[SIntVector[3](0)] == 3
def test_enum(): class Op(Enum): And = 1 Or = 2 @family_closure def PE_fc(family): Bit = family.Bit @family.assemble(locals(), globals()) class PE_Enum(Peak): def __call__(self, op: Const(Op), in0: Bit, in1: Bit) -> Bit: if op == Op.And: return in0 & in1 else: #op == Op.Or return in0 | in1 return PE_Enum # verify BV works PE_bv = PE_fc(family.PyFamily()) vals = [Bit(0), Bit(1)] for op in Op.enumerate(): for i0, i1 in itertools.product(vals, vals): res = PE_bv()(op, i0, i1) gold = (i0 & i1) if (op is Op.And) else (i0 | i1) assert res == gold # verify BV works PE_smt = PE_fc(family.SMTFamily()) Op_aadt = AssembledADT[Op, Assembler, SMTBitVector] vals = [SMTBit(0), SMTBit(1), SMTBit(), SMTBit()] for op in Op.enumerate(): op = Op_aadt(op) for i0, i1 in itertools.product(vals, vals): res = PE_smt()(op, i0, i1) gold = (i0 & i1) if (op is Op.And) else (i0 | i1) assert res == gold # verify magma works asm = Assembler(Op) PE_magma = PE_fc(family.MagmaFamily()) tester = fault.Tester(PE_magma) vals = [0, 1] for op in (Op.And, Op.Or): for i0, i1 in itertools.product(vals, vals): gold = (i0 & i1) if (op is Op.And) else (i0 | i1) tester.circuit.op = int(asm.assemble(op)) tester.circuit.in0 = i0 tester.circuit.in1 = i1 tester.eval() tester.circuit.O.expect(gold) tester.compile_and_run("verilator", flags=["-Wno-fatal"])
def test_lut(): pe = PE() for _ in range(NTESTS): lut_val = BitVector.random(8) inst = asm.lut(lut_val) b0 = Bit(random.choice([0,1])) b1 = Bit(random.choice([0,1])) b2 = Bit(random.choice([0,1])) data0 = UIntVector.random(DATAWIDTH) _, res_p,_ = pe(inst, data0=data0,bit0=b0,bit1=b1,bit2=b2) assert res_p== lut_val[int(BitVector[3]([b0,b1,b2]))]
def read(self, address, data): self.io.apb.PADDR = address self.set_psel(Bit(1)) self.io.apb.PWRITE = Bit(0) yield self.io.apb.PENABLE = Bit(1) yield while not self.io.apb.PREADY: # TODO: Insert timeout logic yield self.io.apb.PENABLE = Bit(0) self.set_psel(Bit(0))
def get_random_input(name, port): if issubclass(port, m.Array): return get_random_arr(name, port) elif issubclass(port, m.AsyncReset): return 0 elif issubclass(port, m.Digital): # TODO: Hack, check the name and don't twiddle config ports, we # should add a config type if "config_" in name: return Bit(0) elif "reset" in name: return Bit(0) else: return random_bit() else: raise NotImplementedError(name, port, type(port)) # pragma: nocover
def solved_to_bv(var, solver): smt_var = solver.get_value(var.value) assert smt_var.is_constant() solver_value = smt_var.constant_value() if isinstance(var, SMTBit): return Bit(solver_value) else: return BitVector[var.size](solver_value)
def test_protocol_ite(): Counter, CounterMeta, Word = gen_counter(BitVector) cnt1 = Counter() cnt2 = Counter() cnt1.inc() assert cnt1.val == 1 assert cnt2.val == 0 cnt3 = Bit(0).ite(cnt1, cnt2) assert cnt3.val == cnt2.val cnt4 = Bit(1).ite(cnt1, cnt2) assert cnt4.val == cnt1.val
def process_result(self, type_, result): if issubclass(type_, m.Digital): return Bit(result) if issubclass(type_, m.Bits): return BitVector[len(type_)](result) if is_recursive_type(type_): return BitVector[len(type_)](result) return result
def test_comparison(op, reference, width): for _ in range(NTESTS): I0, I1 = SIntVector.random(width), SIntVector.random(width) if op is operator.floordiv and I1 == 0: # Skip divide by zero continue expected = Bit(reference(int(I0), int(I1))) assert expected == bool(op(I0, I1))
def write_data01(pe, data0: Data, data1: Data, instr=asm.add(), ra=Data(0)): config_addr = Data8(DATA01_ADDR) config_data = BitVector.concat(data0, data1) config_en = Bit(1) return pe(instr, data0=ra, config_addr=config_addr, config_data=config_data, config_en=config_en)
def make_bit(value): # TODO(rsetaluri): Use bit_vector.Bit when implemented. if isinstance(value, BitVector) and len(value) == 1: return value[0] if value == 0 or value == 1: return Bit(value) if value is AnyValue or value is UnknownValue or value is HiZ: return value raise NotImplementedError(value)
def read(bus, io, request, tester, addr, data): #{{{ #36: Poke(RegFile_reg0_reg1.apb.PSEL1, Bit(True)) #37: Poke(RegFile_reg0_reg1.apb.PADDR, 1) #38: Poke(RegFile_reg0_reg1.apb.PPROT, Bit(False)) #39: Poke(RegFile_reg0_reg1.apb.PENABLE, Bit(False)) #40: Poke(RegFile_reg0_reg1.apb.PWRITE, Bit(False)) #41: Poke(RegFile_reg0_reg1.apb.PWDATA, 45) #42: Poke(RegFile_reg0_reg1.apb.PSTRB, 0) #43: Step(RegFile_reg0_reg1.apb.PCLK, steps=2) #44: Poke(RegFile_reg0_reg1.apb.PSEL1, Bit(True)) #45: Poke(RegFile_reg0_reg1.apb.PADDR, 1) #46: Poke(RegFile_reg0_reg1.apb.PPROT, Bit(False)) #47: Poke(RegFile_reg0_reg1.apb.PENABLE, Bit(True)) #48: Poke(RegFile_reg0_reg1.apb.PWRITE, Bit(False)) #49: Poke(RegFile_reg0_reg1.apb.PWDATA, 45) #50: Poke(RegFile_reg0_reg1.apb.PSTRB, 0) #51: Step(RegFile_reg0_reg1.apb.PCLK, steps=2) #52: Expect(apb_PREADY, Bit(True)) #53: Expect(apb_PRDATA, 45) #54: Poke(RegFile_reg0_reg1.apb.PSEL1, Bit(False)) #55: Poke(RegFile_reg0_reg1.apb.PADDR, 1) #56: Poke(RegFile_reg0_reg1.apb.PPROT, Bit(False)) #57: Poke(RegFile_reg0_reg1.apb.PENABLE, Bit(False)) #58: Poke(RegFile_reg0_reg1.apb.PWRITE, Bit(False)) #59: Poke(RegFile_reg0_reg1.apb.PWDATA, 45) #60: Poke(RegFile_reg0_reg1.apb.PSTRB, 0) #61: Step(RegFile_reg0_reg1.apb.PCLK, steps=2) #62: Expect(apb_PREADY, Bit(False)) #63: Step(RegFile_reg0_reg1.apb.PCLK, steps=2) #}}} # Send request #36 到 43 request.command = APB.APBCommand.READ step(bus, io, tester) #44 到 51 request.command = APB.APBCommand.IDLE # No wait state io.apb.PREADY = Bit(1) step(bus, io, tester) #52: Expect(apb_PREADY, Bit(True)) tester.circuit.apb.PREADY.expect(1) #53: Expect(apb_PRDATA, 45) tester.circuit.apb.PRDATA.expect(data) #54 到 61 step(bus, io, tester) #62: Expect(apb_PREADY, Bit(False)) tester.circuit.apb.PREADY.expect(0) tester.step(2)
def _model_to_frozendict(v_map, model): d = {} for k, v in v_map.items(): if isinstance(v, AbstractBitVector): d[k] = BitVector[v.size](model[v.value].as_long()) elif isinstance(v, AbstractBit): d[k] = Bit(bool(model[v.value])) else: raise TypeError() return FrozenDict(d)
def generate_function_test_vectors(circuit, func, input_ranges=None, mode='complete', flatten=True): check(circuit, func) args = [] for i, (name, port) in enumerate(circuit.IO.items()): if port.is_input(): if issubclass(port, m.Bit): args.append([Bit(0), Bit(1)]) elif issubclass(port, Array) and issubclass(port.T, m.Bit): num_bits = port.N if issubclass(port, SInt): if input_ranges is None: input_range = range(-2**(num_bits - 1), 2**(num_bits - 1)) else: input_range = input_ranges[i] args.append([SIntVector[num_bits](x) for x in input_range]) else: if input_ranges is None: input_range = range(1 << num_bits) else: input_range = input_ranges[i] args.append([BitVector[num_bits](x) for x in input_range]) else: raise NotImplementedError(port, type(port)) tests = [] for test in product(*args): result = func(*list(test)) test = [list(test), []] if isinstance(result, tuple): test[-1].extend(result) else: test[-1].append(result) tests.append(test) if flatten: tests = flatten_tests(tests) else: tests = [test[0] + test[1] for test in tests] return tests
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 test_ite(t_constructor, t_size, f_constructor, f_size): pred = Bit(_rand_int(1)) t = t_constructor(t_size) f = f_constructor(f_size) t_is_bv_constructor = t_constructor in {_rand_signed, _rand_bv} f_is_bv_constructor = f_constructor in {_rand_signed, _rand_bv} sizes_equal = t_size == f_size if (t_constructor is f_constructor and t_is_bv_constructor and sizes_equal): # The same bv_constructor res = pred.ite(t, f) assert type(res) is type(t) elif t_is_bv_constructor and f_is_bv_constructor and sizes_equal: # Different bv_constuctor res = pred.ite(t, f) # The bases should be the most specific types that are common # to both branches and PolyBase. assert isinstance(res, PolyBase) assert isinstance(res, BitVector[t_size]) elif t_is_bv_constructor and f_is_bv_constructor and not sizes_equal: # BV with different size with pytest.raises(InconsistentSizeError): res = pred.ite(t, f) else: # Trying to coerce an int with pytest.raises(TypeError): res = pred.ite(t, f)
def read(self, address, data): """ Issue a read as a sequence of output values: * Set the address line based on the input * Set PSEL for the requested slave * Clear PWRITE * Wait one clock cycle * Set PENABLE * Wait one clock cycle * Wait for PREADY to be high (from the slave) * Clear PENABLE and PSEL """ self.io.apb.PADDR = address self.set_psel(Bit(1)) self.io.apb.PWRITE = Bit(0) yield self.io.apb.PENABLE = Bit(1) yield while not self.io.apb.PREADY: # TODO: Insert timeout logic yield self.io.apb.PENABLE = Bit(0) self.set_psel(Bit(0))
def read(bus, io, request, tester, addr, data): # Send request request.command = APBCommand.READ step(bus, io, tester) request.command = APBCommand.IDLE # No wait state io.apb.PREADY = Bit(1) step(bus, io, tester) tester.circuit.apb.PREADY.expect(1) tester.circuit.apb.PRDATA.expect(data) step(bus, io, tester) tester.circuit.apb.PREADY.expect(0) tester.step(2)
def write(bus, io, request, tester, addr, data): # Test idle state step(bus, io, tester) # Send request request.command = APBCommand.WRITE step(bus, io, tester) request.command = APBCommand.IDLE # No wait state io.apb.PREADY = Bit(1) step(bus, io, tester) tester.circuit.apb.PREADY.expect(1) step(bus, io, tester) tester.circuit.apb.PREADY.expect(0) tester.step(2)
def test_random(): assert Bit.random() in [0, 1]
def test_operator_bit2(op, reference, v1, v2): assert reference(v1, v2) == bool(op(Bit(v1), Bit(v2)))
def test_operator_bit1(op, reference, v): assert reference(v) == bool(op(Bit(v)))
def test_value(value, arg): assert bool(Bit(arg)) == value
def test_illegal(): with pytest.raises(TypeError): Bit(object()) with pytest.raises(ValueError): Bit(2)