From f0cefd43523ba7a57ff28fc8c7a19e5708d61a73 Mon Sep 17 00:00:00 2001 From: Kia <kia@special-circumstanc.es> Date: Wed, 24 Mar 2021 13:21:11 -0600 Subject: [PATCH] BMC showed us a bug! --- rtl_lib/gearbox.py | 102 +++++++++++++++++++++++++++++++++----------- rtl_lib/gearbox.sby | 24 +++++++++++ 2 files changed, 101 insertions(+), 25 deletions(-) create mode 100644 rtl_lib/gearbox.sby diff --git a/rtl_lib/gearbox.py b/rtl_lib/gearbox.py index a450852..5af7a95 100644 --- a/rtl_lib/gearbox.py +++ b/rtl_lib/gearbox.py @@ -55,8 +55,8 @@ class ArbitraryGearbox(Elaboratable): m.d.comb += upstream_transaction.eq( self.bus.upstream_ready_out & self.bus.upstream_valid_in) m.d.comb += downstream_transaction.eq(self.bus.downstream_ready_in & self.bus.downstream_valid_out) - m.d.comb += self.bus.upstream_ready_out.eq( shift_reg_len - valid_bit_count >= upstream_width) - m.d.comb += self.bus.downstream_valid_out.eq(shift_reg_len >= downstream_width) + m.d.comb += self.bus.upstream_ready_out.eq(shift_reg_len - valid_bit_count >= upstream_width) + m.d.comb += self.bus.downstream_valid_out.eq( valid_bit_count >= downstream_width) m.d.comb += self.bus.data_out.eq(shift_reg[0:downstream_width]) @@ -101,7 +101,7 @@ class IdempotentGearbox(Elaboratable): def elaborate(self, platform): m = Module() - m.submodules.pipe = pipe = PipeStage(width=self.width, registered_ready=True) + m.submodules.pipe = pipe = PipeStage(width=self.width, registered_ready=False) m.d.comb += pipe.upstream_valid_in.eq(self.bus.upstream_valid_in) m.d.comb += pipe.downstream_ready_in.eq(self.bus.downstream_ready_in) @@ -135,20 +135,59 @@ class GoldenGearboxModel(Elaboratable): write_ptr = Signal(range(self.sim_memory_size)) read_ptr = Signal(range(self.sim_memory_size)) - with m.If(self.bus.valid_in == 1): - m.d.sync += write_ptr.eq(write_ptr + self.upstream_width) - with m.Switch(write_ptr): - for cand_wptr in range(0, self.sim_memory_size): - with m.Case(cand_wptr): + upstream_width = self.upstream_width + downstream_width = self.downstream_width + + # these are to make fake flow control signals + fake_memory = self.upstream_width + self.downstream_width + fake_occupied = Signal(range(self.upstream_width + self.downstream_width)) + + upstream_transaction = Signal(1) + downstream_transaction = Signal(1) + + m.d.comb += upstream_transaction.eq( self.bus.upstream_ready_out & self.bus.upstream_valid_in) + m.d.comb += downstream_transaction.eq(self.bus.downstream_ready_in & self.bus.downstream_valid_out) + + m.d.comb += self.bus.upstream_ready_out.eq(fake_memory - fake_occupied >= upstream_width) + m.d.comb += self.bus.downstream_valid_out.eq( fake_occupied >= downstream_width) + + with m.If(upstream_transaction == 1): + with m.If(downstream_transaction == 1): # upstream and downstream + # the simultaneous transaction is hard, but updating the valid count isn't + m.d.sync += fake_occupied.eq(fake_occupied + upstream_width - downstream_width) + m.d.sync += read_ptr.eq(read_ptr + self.downstream_width) + m.d.sync += write_ptr.eq(write_ptr + self.upstream_width) - m.d.sync += self.memory.eq( + with m.Switch(write_ptr): + for cand_wptr in range(0, self.sim_memory_size): + with m.Case(cand_wptr): - Cat(self.memory.bit_select(0, cand_wptr), - self.bus.data_in)) + m.d.sync += self.memory.eq( + + Cat(self.memory.bit_select(0, cand_wptr), + self.bus.data_in)) + + + with m.Else(): # upstream, no downstream + m.d.sync += fake_occupied.eq(fake_occupied + upstream_width) + m.d.sync += write_ptr.eq(write_ptr + self.upstream_width) + + with m.Switch(write_ptr): + for cand_wptr in range(0, self.sim_memory_size): + with m.Case(cand_wptr): + + m.d.sync += self.memory.eq( + + Cat(self.memory.bit_select(0, cand_wptr), + self.bus.data_in)) + + with m.Else(): + with m.If(downstream_transaction == 1): # no upstream, downstream + m.d.sync += fake_occupied.eq(fake_occupied - downstream_width) + m.d.sync += read_ptr.eq(read_ptr + self.downstream_width) + + m.d.comb += self.bus.data_out.eq(self.memory.bit_select(read_ptr, self.downstream_width)) - with m.If(self.bus.ready_in == 1): - m.d.comb += self.bus.data_out.eq(self.memory.bit_select(read_ptr,self.downstream_width)) - m.d.sync += read_ptr.eq(read_ptr + self.downstream_width) return m @@ -163,24 +202,37 @@ class DummyPlug(Elaboratable): def elaborate(self, platform): m = Module() - width = 7 + upstream_width = 5 + downstream_width = 9 + sim_memory_size = 32 - m.submodules.gearbox = gearbox = ArbitraryGearbox(upstream_width=width, downstream_width=width) - m.submodules.idempotent = idempotent = IdempotentGearbox(width=width) + expiration_date = int(sim_memory_size/upstream_width)-1 - m.d.comb += gearbox.bus.data_in.eq(AnySeq(width)) + number_of_writes = Signal(range(2*expiration_date)) + wrapped = Signal(1) + + m.submodules.gearbox = gearbox = ArbitraryGearbox(upstream_width=upstream_width, downstream_width=downstream_width) + m.submodules.golden = golden = GoldenGearboxModel(upstream_width=upstream_width, downstream_width=downstream_width, sim_memory_size=sim_memory_size) + + m.d.comb += gearbox.bus.data_in.eq(AnySeq(upstream_width)) m.d.comb += gearbox.bus.downstream_ready_in.eq(AnySeq(1)) m.d.comb += gearbox.bus.upstream_valid_in.eq(AnySeq(1)) - m.d.comb += idempotent.bus.data_in.eq(gearbox.bus.data_in) - m.d.comb += idempotent.bus.downstream_ready_in.eq(gearbox.bus.downstream_ready_in) - m.d.comb += idempotent.bus.upstream_valid_in.eq(gearbox.bus.upstream_valid_in) + m.d.comb += golden.bus.data_in.eq(gearbox.bus.data_in) + m.d.comb += golden.bus.downstream_ready_in.eq(gearbox.bus.downstream_ready_in) + m.d.comb += golden.bus.upstream_valid_in.eq(gearbox.bus.upstream_valid_in) + + with m.If(gearbox.bus.upstream_valid_in & gearbox.bus.upstream_ready_out == 1): + m.d.sync += number_of_writes.eq(number_of_writes + 1) + with m.If(number_of_writes > expiration_date): + m.d.sync += wrapped.eq(1) - m.d.comb += Assert(gearbox.bus.upstream_ready_out == idempotent.bus.upstream_ready_out) - m.d.comb += Assert(gearbox.bus.downstream_valid_out == idempotent.bus.downstream_valid_out) + with m.If(wrapped == 0): + m.d.comb += Assert(gearbox.bus.upstream_ready_out == golden.bus.upstream_ready_out) + m.d.comb += Assert(gearbox.bus.downstream_valid_out == golden.bus.downstream_valid_out) - with m.If(gearbox.bus.downstream_valid_out == 1): - m.d.comb += Assert(gearbox.bus.data_out == idempotent.bus.data_out) + with m.If(gearbox.bus.downstream_valid_out == 1): + m.d.comb += Assert(gearbox.bus.data_out == golden.bus.data_out) return m diff --git a/rtl_lib/gearbox.sby b/rtl_lib/gearbox.sby new file mode 100644 index 0000000..3042f9f --- /dev/null +++ b/rtl_lib/gearbox.sby @@ -0,0 +1,24 @@ +[options] +#mode prove +mode bmc +depth 32 + +multiclock off + +[engines] +smtbmc +#abc pdr +#abc bmc3 + +[script] +read_ilang gearbox.il +prep -top top +proc +opt +fsm +flatten +show -format dot -notitle -prefix ./dotty.dot + + +[files] +gearbox.il \ No newline at end of file -- GitLab