def check(self, m: Module): push_a = self.instr[0] == 0 self.assert_cycles(m, 4) self.assert_cycle_signals(m, 1, address=self.data.pre_pc + 1, vma=1, rw=1, ba=0) data = self.assert_cycle_signals(m, 2, address=self.data.pre_sp, vma=1, rw=0, ba=0) self.assert_cycle_signals(m, 3, vma=0, ba=0) with m.If(push_a): m.d.comb += Assert(data == self.data.pre_a) with m.Else(): m.d.comb += Assert(data == self.data.pre_b) self.assert_registers(m, SP=self.data.pre_sp - 1, PC=self.data.pre_pc + 1) self.assert_flags(m)
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the NextDay module.""" m = Module() m.submodules.nd = nd = cls() # We don't have to create a signal here. Using is_zero is like just copying the logic. is_zero = ((nd.next_year == 0) & (nd.next_month == 0) & (nd.next_day == 0)) m.d.comb += Assert(nd.invalid == is_zero) all_nonzero = ((nd.next_year != 0) & (nd.next_month != 0) & (nd.next_day != 0)) m.d.comb += Assert(all_nonzero | is_zero) with m.If(~nd.invalid): with m.If(nd.day == 31): m.d.comb += Assert(nd.next_day == 1) with m.If((nd.month == 12) & (nd.day == 31)): m.d.comb += Assert(nd.next_month == 1) with m.If(((nd.year % 2) == 1) & (nd.month == 2) & (nd.day == 29)): m.d.comb += Assert(nd.invalid) m.d.comb += Cover((nd.next_month == 2) & (nd.next_day == 29)) return m, [nd.year, nd.month, nd.day]
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the shifter.""" m = Module() m.submodules.shifter = shifter = ShiftCard() shamt = Signal(5) m.d.comb += shamt.eq(shifter.data_y[:5]) with m.If(shamt > 0): m.d.comb += Cover(shifter.data_z == 0xFFFFAAA0) with m.Switch(shifter.alu_op): with m.Case(AluOp.SLL): m.d.comb += Assert( shifter.data_z == (shifter.data_x << shamt)[:32]) with m.Case(AluOp.SRL): m.d.comb += Assert(shifter.data_z == (shifter.data_x >> shamt)) with m.Case(AluOp.SRA): m.d.comb += Assert( shifter.data_z == (shifter.data_x.as_signed() >> shamt)) with m.Default(): m.d.comb += Assert(shifter.data_z == 0) return m, [ shifter.alu_op, shifter.data_x, shifter.data_y, shifter.data_z ]
def check(self, m: Module, instr: Value, data: FormalData): b = instr[6] pre_input = Mux(b, data.pre_b, data.pre_a) m.d.comb += [ Assert(data.post_a == data.pre_a), Assert(data.post_b == data.pre_b), Assert(data.post_x == data.pre_x), Assert(data.post_sp == data.pre_sp), Assert(data.addresses_written == 0), ] m.d.comb += [ Assert(data.post_pc == data.plus16(data.pre_pc, 3)), Assert(data.addresses_read == 3), Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)), Assert(data.read_addr[1] == data.plus16(data.pre_pc, 2)), Assert(data.read_addr[2] == Cat(data.read_data[1], data.read_data[0])), ] input1 = pre_input input2 = data.read_data[2] output = input1 & input2 z = output == 0 n = output[7] v = 0 self.assertFlags(m, data.post_ccs, data.pre_ccs, Z=z, N=n, V=v)
def elaborate(self, platform): m = Module() MAX_AMOUNT = Const(22) with m.If(self.i_reset): m.d.sync += self.counter.eq(0) with m.Elif(self.i_start_signal & (self.counter == 0)): m.d.sync += self.counter.eq(MAX_AMOUNT - 1) with m.Elif(self.counter != 0): m.d.sync += self.counter.eq(self.counter - 1) m.d.sync += self.o_busy.eq((~self.i_reset) & \ ((self.i_start_signal & (self.counter == 0)) | \ (self.counter > 1))) if self.fv_mode: f_past_valid = Signal(1, reset=0) m.d.sync += f_past_valid.eq(1) m.d.comb += Assert(self.counter < MAX_AMOUNT) with m.If(f_past_valid & Past(self.i_start_signal) & Past(self.o_busy)): m.d.comb += Assume(self.i_start_signal) with m.Elif(f_past_valid & Past(self.i_start_signal) & ~Past(self.o_busy)): m.d.comb += Assume(~self.i_start_signal) m.d.comb += Assert(self.o_busy == (self.counter != 0)) with m.If(f_past_valid & Past(self.counter) != 0): m.d.comb += Assert(self.counter < Past(self.counter)) return m
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the ToPennies module.""" m = Module() m.submodules.to_pennies = to_pennies = cls() m.d.comb += Cover((to_pennies.pennies == 37) & (to_pennies.nickels == 3) & (to_pennies.dimes == 10) & (to_pennies.quarters == 5) & (to_pennies.dollars == 2)) m.d.comb += Cover(to_pennies.pennies_out == 548) m.d.comb += Cover((to_pennies.pennies_out == 64) & (to_pennies.nickels == 2 * to_pennies.dimes) & (to_pennies.dimes > 0)) m.d.comb += Assert((to_pennies.pennies_out % 5) == (to_pennies.pennies % 5)) with m.If(to_pennies.pennies == 0): m.d.comb += Assert((to_pennies.pennies % 5) == 0) return m, [to_pennies.pennies, to_pennies.nickels, to_pennies.dimes, to_pennies.quarters, to_pennies.dollars]
def assert_registers( self, m: Module, A=None, B: Value = None, X: Value = None, SP: Value = None, PC: Value = None, ): if A is not None: m.d.comb += self.want_a.eq(A[:8]) else: m.d.comb += self.want_a.eq(self.data.pre_a) if B is not None: m.d.comb += self.want_b.eq(B[:8]) else: m.d.comb += self.want_b.eq(self.data.pre_b) if X is not None: m.d.comb += self.want_x.eq(X[:16]) else: m.d.comb += self.want_x.eq(self.data.pre_x) if SP is not None: m.d.comb += self.want_sp.eq(SP[:16]) else: m.d.comb += self.want_sp.eq(self.data.pre_sp) if PC is not None: m.d.comb += self.want_pc.eq(PC[:16]) else: m.d.comb += self.want_pc.eq(self.data.pre_pc) m.d.comb += Assert(self.data.post_a == self.want_a) m.d.comb += Assert(self.data.post_b == self.want_b) m.d.comb += Assert(self.data.post_x == self.want_x) m.d.comb += Assert(self.data.post_sp == self.want_sp) m.d.comb += Assert(self.data.post_pc == self.want_pc)
def __main(): m = top = Module() clock = ClockInfo("i") m.domains.i = clock.domain top.submodules.regs = regs = RegisterFileModule(32) regs.aux_ports.append(clock.clk) regs.aux_ports.append(clock.rst) comb = m.d.comb with m.If(regs.rs1_in == 0): comb += Assert(regs.rs1_out == 0) with m.If(regs.rs2_in == 0): comb += Assert(regs.rs2_out == 0) with m.If(regs.rs2_in == regs.rs1_in): comb += Assert(regs.rs2_out == regs.rs2_out) with m.If((Past(regs.rd) == regs.rs1_in) & (~Past(clock.rst) & (~clock.rst))): with m.If(regs.rs1_in != 0): comb += Assert(regs.rs1_out == Past(regs.rd_value)) nmigen_main(top, ports=regs.ports())
def run_general(self): """ General proof """ m = self.module core: Core = self.uut comb = m.d.comb last = self.time[1] now = self.time[0] with m.If(self.additional_check() & last.at_instruction_start()): with m.If( last.itype.match(opcode=Opcode.OpImm, funct3=self.funct3())): with m.If(last.itype.rd == 0): comb += Assert(now.r[0] == 0) now.assert_same_gpr(m, last.r) with m.Else(): expected = Signal( core.xlen, name=f"{self.__class__.__name__}_expected") actual = Signal(core.xlen, name=f"{self.__class__.__name__}_got") comb += actual.eq(now.r[last.itype.rd]) comb += expected.eq( self.general_proof_expr(last.r[last.itype.rs1], last.itype.imm)) comb += Assert(expected == actual) now.assert_pc_advanced(m, last.r) now.assert_same_gpr_but_one(m, last.r, last.itype.rd)
def formal(cls) -> Tuple[Module, List[Signal]]: m = Module() ph = ClockDomain("ph") clk = ClockSignal("ph") m.domains += ph m.d.sync += clk.eq(~clk) s = IC_7416374(clk="ph") m.submodules += s with m.If(s.n_oe): m.d.comb += Assert(s.q == 0) with m.If(~s.n_oe & Rose(clk)): m.d.comb += Assert(s.q == Past(s.d)) with m.If(~s.n_oe & Fell(clk) & ~Past(s.n_oe)): m.d.comb += Assert(s.q == Past(s.q)) sync_clk = ClockSignal("sync") sync_rst = ResetSignal("sync") # Make sure the clock is clocking m.d.comb += Assume(sync_clk == ~Past(sync_clk)) # Don't want to test what happens when we reset. m.d.comb += Assume(~sync_rst) m.d.comb += Assume(~ResetSignal("ph")) return m, [sync_clk, sync_rst, s.n_oe, s.q, s.d]
def match(self, rv, input): m : Module = self.module comb = m.d.comb comb += Assert(rv[0:8] == input[0:8]) with m.If(input[7]): comb += Assert(rv[8:32] == -1) with m.Else(): comb += Assert(rv[8:32] == 0)
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the Negate module.""" m = Module() m.submodules.c = c = cls() m.d.comb += Assert(c.output1 == c.output2) m.d.comb += Assert(c.output2 == c.output3) m.d.comb += Assert(c.output1[63] == (c.output1.as_signed() < 0)) return m, [c.input]
def verification_statements(m): #Create Local Reference to the LDPC_Decoder LDPC_Decoder = m.submodules.LDPC_Decoder #Ensure that done and output signals are reset when start is toggled. with m.If((LDPC_Decoder.start == 0) & Past(LDPC_Decoder.start)): m.d.sync += Assert((LDPC_Decoder.done == 0)) m.d.sync += Assert((LDPC_Decoder.data_output == 0)) return
def assert_gpr_value(self, m: Module, idx: Value, expected_value: Value, src_loc_at=1): """ Assert GPR value (ignored for idx = 0 and zeri is checked instead) """ comb = m.d.comb with m.If(idx == 0): comb += Assert(self.r[0] == 0, src_loc_at=src_loc_at) with m.Else(): comb += Assert(self.r[idx] == expected_value, src_loc_at=src_loc_at)
def __verify_left(m): m.submodules.shl = shl = Shifter(32, Shifter.LEFT, "shl") comb = m.d.comb expect = Signal(32) comb += expect.eq(shl.input << shl.shamt) comb += Assert(shl.output == expect) with m.If(shl.input == 0): comb += Assert(shl.output == shl.input) with m.If(shl.shamt == 31): comb += Assert(shl.output[31] == shl.input[0]) comb += Assert(shl.output[31] == shl.input.bit_select(31 - shl.shamt, 1)) return shl.ports()
def run_general(self): last = self.time[1] now = self.time[0] m = self.module comb = m.d.comb with m.If(last.jtype.match(opcode=Opcode.Jal)): with m.If(last.jtype.rd == 0): now.assert_same_gpr(m, last.r) with m.Else(): now.assert_same_gpr_but_one(m, last.r, last.jtype.rd) comb += Assert(now.r[last.jtype.rd] == (last.r.pc+4)[0:32]) comb += Assert(now.r.pc == (last.r.pc+last.jtype.imm)[0:32])
def prove(self, m: Module): last = 0 sum_of_bits = self.add_output_signal(self.input_width, name="sum") for i in range(self.input_width): next_value = Signal(self.input_width) m.d.comb += next_value.eq(last + self.a[i]) last = next_value m.d.comb += sum_of_bits.eq(next_value) with m.If((sum_of_bits % 2) == 0): #even m.d.comb += Assert(self.parity == Const(1, 1)) with m.If((sum_of_bits % 2) == 1): #odd m.d.comb += Assert(self.parity == Const(0, 1))
def verify_stype(self, m): sig = self.build_signal(m, "S", [(0, 6, "1001011"), (7, 11, "10000"), (12, 14, "001"), (15, 19, "00010"), (20, 24, "00011"), (25, 31, "0111111")]) s = SType("stype") s.elaborate(m.d.comb, sig) m.d.comb += Assert(s.opcode == Const(0b1001011, 7)) m.d.comb += Assert(s.funct3 == Const(1, 3)) m.d.comb += Assert(s.rs1 == Const(2, 5)) m.d.comb += Assert(s.rs2 == Const(3, 5)) m.d.comb += Assert(s.imm == Const(0b011111110000, 12)) return []
def run_general(self): last = self.time[1] now = self.time[0] m = self.module comb = m.d.comb with m.If(last.utype.match(opcode=Opcode.Lui)): with m.If(last.jtype.rd == 0): now.assert_same_gpr(m, last.r) with m.Else(): now.assert_same_gpr_but_one(m, last.r, last.utype.rd) comb += Assert(now.r[last.utype.rd] == last.utype.imm) comb += Assert(now.r[last.utype.rd][0:12] == 0) now.assert_pc_advanced(m, last.r)
def elaborate(self, platform): m = Module() m.submodules.executer = executer = RefreshExecuter(self._abits, self._babits, self._trp, self._trfc) m.d.comb += [ self.a.eq(executer.a), self.ba.eq(executer.ba), self.cas.eq(executer.cas), self.ras.eq(executer.ras), self.we.eq(executer.we), ] countEqZero = Signal(reset=(self._postponing <= 1)) countDiffZero = Signal(reset=(self._postponing > 1)) count = Signal(range(self._postponing), reset=self._postponing-1) with m.If(self.start): m.d.sync += [ count.eq(count.reset), countEqZero.eq(self._postponing <= 1), countDiffZero.eq(self._postponing > 1), ] with m.Elif(executer.done): with m.If(count != 0): m.d.sync += count.eq(count-1) with m.If(count == 1): m.d.sync += [ countEqZero.eq(1), countDiffZero.eq(0), ] with m.Else(): m.d.sync += [ countEqZero.eq(0), countDiffZero.eq(1), ] m.d.comb += [ executer.start.eq(self.start | countDiffZero), self.done.eq(executer.done & countEqZero), ] if platform == "formal": m.d.comb += [ Assert(countEqZero == (count == 0)), Assert(countDiffZero == (count != 0)), ] return m
def run_example(self): """ Concrete example """ m = self.module comb = m.d.comb last = self.time[1] now = self.time[0] with m.If(last.jtype.match(opcode=Opcode.Jal, rd=1, imm=-4)): comb += Assert(now.r.pc == (last.r.pc-4)[0:32]) comb += Assert(now.r[1] == (last.r.pc+4)[0:32]) with m.If(last.jtype.match(opcode=Opcode.Jal, imm=0)): comb += Assert(now.r.pc == (last.r.pc)[0:32]) with m.If(last.jtype.match(opcode=Opcode.Jal, imm=4)): comb += Assert(now.r.pc == (last.r.pc+4)[0:32])
def assert_pc_advanced(self, m: Module, previous: RegisterFile, src_loc_at=1): comb = m.d.comb comb += Assert(self.r.pc == (previous.pc + 4)[:self.r.pc.width], src_loc_at=src_loc_at)
def run_example(self): """ Concrete example """ m = self.module comb = m.d.comb last = self.time[1] now = self.time[0] with m.If(last.utype.match(rd=1, imm=0x80000) & last.r[1] == 1): comb += Assert(now.r[1] == 0x80000) with m.If(last.utype.match(rd=1, imm=0xFFFFF000)): comb += Assert(now.r[1] == 0xFFFFF000) with m.If(last.utype.match(rd=1, imm=0xFF1FF000)): comb += Assert(now.r[1] == 0xFF1FF000)
def elaborate(self, platform): m = Module() if self._txxd is not None: count = Signal(range(max(self._txxd, 2))) with m.If(self.valid): m.d.sync += [ count.eq(self._txxd - 1), self.ready.eq((self._txxd - 1) == 0), ] with m.Elif(~self.ready): m.d.sync += count.eq(count - 1) with m.If(count == 1): m.d.sync += self.ready.eq(1) if platform == "formal": if self._txxd is not None and self._txxd > 0: hasSeenValid = Signal() with m.If(self.valid): m.d.sync += hasSeenValid.eq(1) m.d.sync += Assert( (hasSeenValid & (count == 0)).implies(self.ready == 1)) return m
def check(self, m: Module, instr: Value, data: FormalData): input1, input2, actual_output = self.common_check(m, instr, data) carry_in = Signal() sum9 = Signal(9) sum8 = Signal(8) sum5 = Signal(5) with_carry = (instr[1] == 0) h = sum5[4] n = sum9[7] c = sum9[8] z = (sum9[:8] == 0) v = (sum8[7] ^ c) with m.If(with_carry): m.d.comb += carry_in.eq(data.pre_ccs[Flags.C]) with m.Else(): m.d.comb += carry_in.eq(0) m.d.comb += [ sum9.eq(input1 + input2 + carry_in), sum8.eq(input1[:7] + input2[:7] + carry_in), sum5.eq(input1[:4] + input2[:4] + carry_in), Assert(actual_output == sum9[:8]), ] self.assertFlags(m, data.post_ccs, data.pre_ccs, Z=z, N=n, V=v, C=c, H=h)
def run_main_proof(self): first = self.time[ProofLoadBase.MAX_DELAY] m : Module = self.module comb = m.d.comb with m.If(first.at_instruction_start() & first.itype.match(opcode=Opcode.Load, funct3=self.op_load())): check_only = None #check_only = 3 source_address = (first.r[first.itype.rs1] + first.itype.imm)[:32] for i in range(ProofLoadBase.MAX_DELAY-1, 0,-1): if check_only is not None and i != check_only: continue now = self.time[i] next = self.time[i-1] with m.If(self.previously_no_data_arrived(i)): now.assert_loading_from(m, source_address) now.assert_same_gpr(m, first.r) now.assert_same_pc(m, first.r) with m.If(~now.input_ready): pass with m.Else(): next.assert_same_gpr_but_one(m, first.r, first.itype.rd) next.assert_pc_advanced(m, now.r) with m.If(first.itype.rd == 0): comb += Assert(next.r[0] == 0) with m.Else(): self.match(next.r[first.itype.rd], now.input_data[0])
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the Cell3x3 module.""" m = Module() m.submodules.c = c = cls() s = 0 for n in range(9): if n != 4: s += c.input[n] with m.If(s == 3): m.d.comb += Assert(c.output) with m.If(s == 2): m.d.comb += Assert(c.output == c.input[4]) return m, [c.input]
def check(self, m: Module): ret_addr = (self.data.pre_pc + 2)[:16] offset = Signal(signed(8)) self.assert_cycles(m, 8) data = self.assert_cycle_signals(m, 1, address=self.data.pre_pc + 1, vma=1, rw=1, ba=0) self.assert_cycle_signals(m, 2, vma=0, ba=0) ret_addr_lo = self.assert_cycle_signals(m, 3, address=self.data.pre_sp, vma=1, rw=0, ba=0) ret_addr_hi = self.assert_cycle_signals(m, 4, address=self.data.pre_sp - 1, vma=1, rw=0, ba=0) self.assert_cycle_signals(m, 5, vma=0, ba=0) self.assert_cycle_signals(m, 6, vma=0, ba=0) self.assert_cycle_signals(m, 7, vma=0, ba=0) m.d.comb += offset.eq(data) m.d.comb += Assert(LCat(ret_addr_hi, ret_addr_lo) == ret_addr) self.assert_registers(m, PC=ret_addr + offset, SP=self.data.pre_sp - 2) self.assert_flags(m)
def validate(self): with self.is_running(): with self.is_instruction(0xDD, 1): self.assert_equals(self.cycle, 1) self.assert_inc16(self.Addr, self.NOW) self.m.d.ph1 += Assert( self.cycle == 1 ) # Note, this is not the end of the instruction, this is the next memory address
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the SignedComparator module.""" m = Module() m.submodules.c = c = cls() m.d.comb += Assert(c.lt == (c.a.as_signed() < c.b.as_signed())) return m, [c.a, c.b]