hmm there seems to have been an error in DTLB Read,
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 24 Jan 2022 14:11:07 +0000 (14:11 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 24 Jan 2022 14:11:07 +0000 (14:11 +0000)
where if a write *and* a read occurred at the same time, the old
DTLB-valid entry was given. add similar "forwarding" that is used in
Memory.  DTLB-valid is actually a register not a Memory, where the
DTLB way/tags are a Memory, hence the bug

src/soc/experiment/dcache.py

index f12a736e12872658afe3a17f42834da0f40cdffa..bbb655f01632d39b72f1eddd09d4c7ddf2bede89 100644 (file)
@@ -558,18 +558,24 @@ class DTLBUpdate(Elaboratable):
             #comb += wr_valid.en.eq(1<<self.repl_way)
 
         # select one TLB way, use a register here
-        r_tlb_way        = TLBRecord("r_tlb_way")
         r_delay = Signal()
         sync += r_delay.eq(self.tlb_read)
+        # first deal with the valids, which are not in a Memory.
+        # tlb way valid is output on a 1 clock delay with sync,
+        # but have to explicitly deal with "forwarding" here
         with m.If(self.tlb_read):
-            sync += self.tlb_way.valid.eq(dtlb_valid[self.tlb_read_index])
+            with m.If(v_updated): # write *and* read in same cycle: forward
+                sync += self.tlb_way.valid.eq(db_out)
+            with m.Else():
+                sync += self.tlb_way.valid.eq(dtlb_valid[self.tlb_read_index])
+        # now deal with the Memory-read case. the output must remain
+        # valid (stable) even when a read-request is not made, but stable
+        # on a one-clock delay, hence the register
+        r_tlb_way        = TLBRecord("r_tlb_way")
         with m.If(r_delay):
             # on one clock delay, output the contents of the read port(s)
-            # comb += self.tlb_way.valid.eq(rd_valid.data)
             comb += self.tlb_way.tag.eq(rd_tagway.data)
             comb += self.tlb_way.pte.eq(rd_pteway.data)
-            # and also capture the (delayed) output...
-            #sync += r_tlb_way.valid.eq(rd_valid.data)
             sync += r_tlb_way.tag.eq(rd_tagway.data)
             sync += r_tlb_way.pte.eq(rd_pteway.data)
         with m.Else():