move bank of PLRUs to their own submodule in both dcache.py and icache.py
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 6 Dec 2021 15:45:40 +0000 (15:45 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 6 Dec 2021 15:45:40 +0000 (15:45 +0000)
src/soc/experiment/dcache.py
src/soc/experiment/icache.py
src/soc/experiment/plru.py

index 7fc94be48c7343b0f81423f740e062fdf7d6666e..04c19745b8b59d8b289b19ebac1c411e071d165e 100644 (file)
@@ -50,7 +50,7 @@ from soc.experiment.wb_types import (WB_ADDR_BITS, WB_DATA_BITS, WB_SEL_BITS,
 
 from soc.experiment.cache_ram import CacheRam
 #from soc.experiment.plru import PLRU
-from nmutil.plru import PLRU
+from nmutil.plru import PLRU, PLRUs
 
 # for test
 from soc.bus.sram import SRAM
@@ -698,20 +698,11 @@ class DCache(Elaboratable):
             return
 
         # Binary-to-Unary one-hot, enabled by tlb_hit valid
-        m.submodules.tlb_hit_e = te = Decoder(TLB_SET_SIZE)
-        comb += te.n.eq(~r1.tlb_hit.valid)
-        comb += te.i.eq(r1.tlb_hit_index)
-
-        for i in range(TLB_SET_SIZE):
-            # TLB PLRU interface
-            tlb_plru        = PLRU(TLB_WAY_BITS)
-            setattr(m.submodules, "maybe_plru_%d" % i, tlb_plru)
-            tlb_plru_acc_en = Signal()
-
-            comb += tlb_plru_acc_en.eq(te.o[i])
-            comb += tlb_plru.acc_en.eq(tlb_plru_acc_en)
-            comb += tlb_plru.acc_i.eq(r1.tlb_hit.way)
-            comb += tlb_plru_victim[i].eq(tlb_plru.lru_o)
+        tlb_plrus = PLRUs(TLB_SET_SIZE, TLB_WAY_BITS, tlb_plru_victim)
+        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)
 
     def tlb_search(self, m, tlb_req_index, r0, r0_valid,
                    tlb_way,
@@ -822,22 +813,10 @@ class DCache(Elaboratable):
         if TLB_NUM_WAYS == 0:
             return
 
-        # XXX TODO: use a Binary-to-Unary one-hot here,
-        # enabled by cache_hit
-        m.submodules.hit_e = he = Decoder(NUM_LINES)
-        comb += he.n.eq(~r1.cache_hit)
-        comb += he.i.eq(r1.hit_index)
-
-        for i in range(NUM_LINES):
-            # PLRU interface
-            plru        = PLRU(WAY_BITS)
-            m.submodules["plru%d" % i] = plru
-            plru_acc_en = Signal()
-
-            comb += plru_acc_en.eq(he.o[i])
-            comb += plru.acc_en.eq(plru_acc_en)
-            comb += plru.acc_i.eq(r1.hit_way)
-            comb += plru_victim[i].eq(plru.lru_o)
+        m.submodules.plrus = plrus = PLRUs(NUM_LINES, WAY_BITS, plru_victim)
+        comb += plrus.way.eq(r1.hit_way)
+        comb += plrus.valid.eq(r1.cache_hit)
+        comb += plrus.index.eq(r1.hit_index)
 
     def cache_tag_read(self, m, r0_stall, req_index, cache_tag_set, cache_tags):
         """Cache tag RAM read port
index 226b8da3b68423c143200e7badb3305a44f94829..393bb7122d43398b86faebdfd4be00b6ed91b30a 100644 (file)
@@ -29,8 +29,8 @@ from nmigen.lib.coding import Decoder
 from nmutil.util import Display
 
 #from nmutil.plru import PLRU
+from soc.experiment.plru import PLRU, PLRUs
 from soc.experiment.cache_ram import CacheRam
-from soc.experiment.plru import PLRU
 
 from soc.experiment.mem_types import (Fetch1ToICacheType,
                                       ICacheToDecode1Type,
@@ -380,20 +380,13 @@ class ICache(Elaboratable):
     def maybe_plrus(self, m, r, plru_victim):
         comb = m.d.comb
 
-        with m.If(NUM_WAYS > 1):
-            m.submodules.plru_e = e = Decoder(NUM_LINES)
-            comb += e.i.eq(get_index(r.hit_nia))
+        if NUM_WAYS == 0:
+            return
 
-            for i in range(NUM_LINES):
-                plru        = PLRU(WAY_BITS)
-                m.submodules["plru_%d" % i] = plru
-
-                # PLRU interface
-                with m.If(e.o[i]):
-                    comb += plru.acc_en.eq(r.hit_valid)
-
-                comb += plru.acc_i.eq(r.hit_way)
-                comb += plru_victim[i].eq(plru.lru_o)
+        m.submodules.plrus = plru = PLRUs(NUM_LINES, WAY_BITS, plru_victim)
+        comb += plru.way.eq(r.hit_way)
+        comb += plru.valid.eq(r.hit_valid)
+        comb += plru.index.eq(get_index(r.hit_nia))
 
     # TLB hit detection and real address generation
     def itlb_lookup(self, m, tlb_req_index, itlb,
index 31f84c2033153ff710ca13aafa73445e181eb46f..1812af6e41425ec7dffc547af483d612bf80f90d 100644 (file)
@@ -1,7 +1,8 @@
 # based on microwatt plru.vhdl
 
-from nmigen import Elaboratable, Signal, Array, Module, Mux, Const
+from nmigen import Elaboratable, Signal, Array, Module, Mux, Const, Cat
 from nmigen.cli import rtlil
+from nmigen.lib.coding import Decoder
 
 
 class PLRU(Elaboratable):
@@ -52,6 +53,47 @@ class PLRU(Elaboratable):
     def ports(self):
         return [self.acc_en, self.lru_o, self.acc_i]
 
+
+class PLRUs(Elaboratable):
+    def __init__(self, n_plrus, n_bits, out=None):
+        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
+
+    def elaborate(self, platform):
+        """Generate TLB PLRUs
+        """
+        m = Module()
+        comb = m.d.comb
+
+        if self.n_plrus == 0:
+            return m
+
+        # Binary-to-Unary one-hot, enabled by valid
+        m.submodules.te = te = Decoder(self.n_plrus)
+        comb += te.n.eq(~self.valid)
+        comb += te.i.eq(self.index)
+
+        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)
+
+        return m
+
+    def ports(self):
+        return [self.valid, self.way, self.index] + list(self.out)
+
+
 if __name__ == '__main__':
     dut = PLRU(2)
     vl = rtlil.convert(dut, ports=dut.ports())
@@ -59,3 +101,9 @@ if __name__ == '__main__':
         f.write(vl)
 
 
+    dut = PLRUs(4, 2)
+    vl = rtlil.convert(dut, ports=dut.ports())
+    with open("test_plrus.il", "w") as f:
+        f.write(vl)
+
+