PLRUs were selecting an output index, only one selected
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 6 Dec 2021 17:00:29 +0000 (17:00 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 6 Dec 2021 17:00:29 +0000 (17:00 +0000)
therefore move the selection from the PLRUs into the module.
simplified

src/soc/experiment/dcache.py
src/soc/experiment/icache.py
src/soc/experiment/plru.py

index bf14e18dda596fff2c4638a281396f35362e4968..a32456c8848bf4d2dcec0b1aba20ca265f9da050 100644 (file)
@@ -688,7 +688,7 @@ class DCache(Elaboratable):
         with m.If(~r0_stall):
             sync += tlb_way.eq(dtlb[index])
 
-    def maybe_tlb_plrus(self, m, r1, tlb_plru_victim):
+    def maybe_tlb_plrus(self, m, r1, tlb_plru_victim, tlb_req_index):
         """Generate TLB PLRUs
         """
         comb = m.d.comb
@@ -698,11 +698,13 @@ class DCache(Elaboratable):
             return
 
         # Binary-to-Unary one-hot, enabled by tlb_hit valid
-        tlb_plrus = PLRUs(TLB_SET_SIZE, TLB_WAY_BITS, tlb_plru_victim)
+        tlb_plrus = PLRUs(TLB_SET_SIZE, TLB_WAY_BITS)
         m.submodules.tlb_plrus = tlb_plrus
         comb += tlb_plrus.way.eq(r1.tlb_hit.way)
         comb += tlb_plrus.valid.eq(r1.tlb_hit.valid)
         comb += tlb_plrus.index.eq(r1.tlb_hit_index)
+        comb += tlb_plrus.isel.eq(tlb_req_index) # select victim
+        comb += tlb_plru_victim.eq(tlb_plrus.o_index) # selected victim
 
     def tlb_search(self, m, tlb_req_index, r0, r0_valid,
                    tlb_way,
@@ -800,7 +802,7 @@ class DCache(Elaboratable):
         with m.If(tlb_hit.valid):
             comb += d.repl_way.eq(tlb_hit.way)
         with m.Else():
-            comb += d.repl_way.eq(tlb_plru_victim[tlb_req_index])
+            comb += d.repl_way.eq(tlb_plru_victim)
         comb += d.eatag.eq(r0.req.addr[TLB_LG_PGSZ + TLB_SET_BITS:64])
         comb += d.pte_data.eq(r0.req.data)
 
@@ -813,10 +815,12 @@ class DCache(Elaboratable):
         if TLB_NUM_WAYS == 0:
             return
 
-        m.submodules.plrus = plrus = PLRUs(NUM_LINES, WAY_BITS, plru_victim)
+        m.submodules.plrus = plrus = PLRUs(NUM_LINES, WAY_BITS)
         comb += plrus.way.eq(r1.hit_way)
         comb += plrus.valid.eq(r1.cache_hit)
         comb += plrus.index.eq(r1.hit_index)
+        comb += plrus.isel.eq(r1.store_index) # select victim
+        comb += plru_victim.eq(plrus.o_index) # selected victim
 
     def cache_tag_read(self, m, r0_stall, req_index, cache_tag_set, cache_tags):
         """Cache tag RAM read port
@@ -916,7 +920,7 @@ class DCache(Elaboratable):
 
         # The way to replace on a miss
         with m.If(r1.write_tag):
-            comb += replace_way.eq(plru_victim[r1.store_index])
+            comb += replace_way.eq(plru_victim)
         with m.Else():
             comb += replace_way.eq(r1.store_way)
 
@@ -1636,7 +1640,7 @@ class DCache(Elaboratable):
 
         cache_out_row     = Signal(WB_DATA_BITS)
 
-        plru_victim       = PLRUOut()
+        plru_victim       = Signal(WAY_BITS)
         replace_way       = Signal(WAY_BITS)
 
         # Wishbone read/write/cache write formatting signals
@@ -1654,7 +1658,7 @@ class DCache(Elaboratable):
         perm_ok       = Signal()
         access_ok     = Signal()
 
-        tlb_plru_victim = TLBPLRUOut()
+        tlb_plru_victim = Signal(TLB_WAY_BITS)
 
         # we don't yet handle collisions between loadstore1 requests
         # and MMU requests
@@ -1689,7 +1693,7 @@ class DCache(Elaboratable):
                         tlb_hit, tlb_plru_victim,
                         tlb_way)
         self.maybe_plrus(m, r1, plru_victim)
-        self.maybe_tlb_plrus(m, r1, tlb_plru_victim)
+        self.maybe_tlb_plrus(m, r1, tlb_plru_victim, tlb_req_index)
         self.cache_tag_read(m, r0_stall, req_index, cache_tag_set, cache_tags)
         self.dcache_request(m, r0, ra, req_index, req_row, req_tag,
                            r0_valid, r1, cache_tags, replace_way,
index 56f69c39eae6d46938857d89feef4bf05128d2ac..845ed5ec39ab955d661f8646ea35f9d1cd8336eb 100644 (file)
@@ -384,10 +384,13 @@ class ICache(Elaboratable):
         if NUM_WAYS == 0:
             return
 
-        m.submodules.plrus = plru = PLRUs(NUM_LINES, WAY_BITS, plru_victim)
+
+        m.submodules.plrus = plru = PLRUs(NUM_LINES, WAY_BITS)
         comb += plru.way.eq(r.hit_way)
         comb += plru.valid.eq(r.hit_valid)
         comb += plru.index.eq(get_index(r.hit_nia))
+        comb += plru.isel.eq(r.store_index) # select victim
+        comb += plru_victim.eq(plru.o_index) # selected victim
 
     # TLB hit detection and real address generation
     def itlb_lookup(self, m, tlb_req_index, itlb,
@@ -519,7 +522,7 @@ class ICache(Elaboratable):
 
         # The way to replace on a miss
         with m.If(r.state == State.CLR_TAG):
-            comb += replace_way.eq(plru_victim[r.store_index])
+            comb += replace_way.eq(plru_victim)
         with m.Else():
             comb += replace_way.eq(r.store_way)
 
@@ -815,7 +818,7 @@ class ICache(Elaboratable):
 
         cache_out_row    = Signal(ROW_SIZE_BITS)
 
-        plru_victim      = PLRUOut()
+        plru_victim      = Signal(WAY_BITS)
         replace_way      = Signal(WAY_BITS)
 
         # fake-up the wishbone stall signal to comply with pipeline mode
index 1812af6e41425ec7dffc547af483d612bf80f90d..92b8fc1480b23b04d72686726e51bbea7d62341c 100644 (file)
@@ -55,16 +55,14 @@ class PLRU(Elaboratable):
 
 
 class PLRUs(Elaboratable):
-    def __init__(self, n_plrus, n_bits, out=None):
+    def __init__(self, n_plrus, n_bits):
         self.n_plrus = n_plrus
         self.n_bits = n_bits
         self.valid = Signal()
         self.way = Signal(n_bits)
         self.index = Signal(n_plrus.bit_length())
-        if out is None:
-            out = Array(Signal(n_bits, name="plru_out%d" % x) \
-                             for x in range(n_plrus))
-        self.out = out
+        self.isel = Signal(n_plrus.bit_length())
+        self.o_index = Signal(n_bits)
 
     def elaborate(self, platform):
         """Generate TLB PLRUs
@@ -80,18 +78,24 @@ class PLRUs(Elaboratable):
         comb += te.n.eq(~self.valid)
         comb += te.i.eq(self.index)
 
+        out = Array(Signal(self.n_bits, name="plru_out%d" % x) \
+                             for x in range(self.n_plrus))
+
         for i in range(self.n_plrus):
             # PLRU interface
             m.submodules["plru_%d" % i] = plru = PLRU(self.n_bits)
 
             comb += plru.acc_en.eq(te.o[i])
             comb += plru.acc_i.eq(self.way)
-            comb += self.out[i].eq(plru.lru_o)
+            comb += out[i].eq(plru.lru_o)
+
+        # select output based on index
+        comb += self.o_index.eq(out[self.isel])
 
         return m
 
     def ports(self):
-        return [self.valid, self.way, self.index] + list(self.out)
+        return [self.valid, self.way, self.index, self.isel, self.o_index]
 
 
 if __name__ == '__main__':