sort out ariane PLRU, rename/clarify
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 13 Sep 2020 11:25:24 +0000 (12:25 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 13 Sep 2020 11:25:24 +0000 (12:25 +0100)
src/soc/experiment/dcache.py
src/soc/experiment/plru.py
src/unused/TLB/ariane/plru.py

index fd90a145678880094f9254b7fbabe68578c8cf36..bc2f3d375c10fc145f64b85b3f59ad5baa515edc 100644 (file)
@@ -1837,5 +1837,5 @@ if __name__ == '__main__':
         mem.append((i*2)| ((i*2+1)<<32))
 
     test_dcache(mem, dcache_sim, "")
-    #test_dcache(None, dcache_random_sim, "random")
+    test_dcache(None, dcache_random_sim, "random")
 
index baa68ce2eb53b34eb82be048f8eabd81b5f92176..c8a59b39ed1ca6dd5f7366739f6f769ccc74200c 100644 (file)
@@ -1,6 +1,8 @@
 # based on microwatt plru.vhdl
 
 from nmigen import Elaboratable, Signal, Array, Module
+from nmigen.cli import rtlil
+
 
 class PLRU(Elaboratable):
 
@@ -14,7 +16,7 @@ class PLRU(Elaboratable):
         m = Module()
         comb, sync = m.d.comb, m.d.sync
 
-        tree = Array(Signal() for i in range(self.BITS))
+        tree = Array(Signal(name="tree%d" % i) for i in range(self.BITS))
 
         # XXX Check if we can turn that into a little ROM instead that
         # takes the tree bit vector and returns the LRU. See if it's better
@@ -52,3 +54,14 @@ class PLRU(Elaboratable):
                     node = node_next
 
         return m
+
+    def ports(self):
+        return [self.acc_en, self.lru_o, self.acc]
+
+if __name__ == '__main__':
+    dut = PLRU(3)
+    vl = rtlil.convert(dut, ports=dut.ports())
+    with open("test_plru.il", "w") as f:
+        f.write(vl)
+
+
index 25d208ae2604c94580df5b4bac18f57378fe05d5..70e212689cb783d24223c6e7f5ae7b640997ec9c 100644 (file)
@@ -1,6 +1,9 @@
-from nmigen import Signal, Module, Cat, Const
+# based on ariane plru, from tlb.sv
+
+from nmigen import Signal, Module, Cat, Const, Repl
 from nmigen.hdl.ir import Elaboratable
-from math import log2
+from nmigen.cli import rtlil
+from nmigen.utils import log2_int
 
 
 class PLRU(Elaboratable):
@@ -17,50 +20,51 @@ class PLRU(Elaboratable):
              ... ... ... ...
     """
 
-    def __init__(self, entries):
-        self.entries = entries
-        self.lu_hit = Signal(entries)
-        self.replace_en_o = Signal(entries)
-        self.lu_access_i = Signal()
-        # Tree (bit per entry)
-        self.TLBSZ = 2*(self.entries-1)
-        self.plru_tree = Signal(self.TLBSZ)
-        self.plru_tree_o = Signal(self.TLBSZ)
+    def __init__(self, BITS):
+        self.BITS = BITS
+        self.acc_en = Signal(BITS)
+        self.lru_o = Signal(BITS)
+        self.acc_i = Signal()
 
     def elaborate(self, platform=None):
         m = Module()
 
+        # Tree (bit per entry)
+        TLBSZ = 2*(self.BITS-1)
+        plru_tree = Signal(TLBSZ)
+
         # Just predefine which nodes will be set/cleared
         # E.g. for a TLB with 8 entries, the for-loop is semantically
         # equivalent to the following pseudo-code:
         # unique case (1'b1)
-        # lu_hit[7]: plru_tree[0, 2, 6] = {1, 1, 1};
-        # lu_hit[6]: plru_tree[0, 2, 6] = {1, 1, 0};
-        # lu_hit[5]: plru_tree[0, 2, 5] = {1, 0, 1};
-        # lu_hit[4]: plru_tree[0, 2, 5] = {1, 0, 0};
-        # lu_hit[3]: plru_tree[0, 1, 4] = {0, 1, 1};
-        # lu_hit[2]: plru_tree[0, 1, 4] = {0, 1, 0};
-        # lu_hit[1]: plru_tree[0, 1, 3] = {0, 0, 1};
-        # lu_hit[0]: plru_tree[0, 1, 3] = {0, 0, 0};
+        # acc_en[7]: plru_tree[0, 2, 6] = {1, 1, 1};
+        # acc_en[6]: plru_tree[0, 2, 6] = {1, 1, 0};
+        # acc_en[5]: plru_tree[0, 2, 5] = {1, 0, 1};
+        # acc_en[4]: plru_tree[0, 2, 5] = {1, 0, 0};
+        # acc_en[3]: plru_tree[0, 1, 4] = {0, 1, 1};
+        # acc_en[2]: plru_tree[0, 1, 4] = {0, 1, 0};
+        # acc_en[1]: plru_tree[0, 1, 3] = {0, 0, 1};
+        # acc_en[0]: plru_tree[0, 1, 3] = {0, 0, 0};
         # default: begin /* No hit */ end
         # endcase
-        LOG_TLB = int(log2(self.entries))
-        print(LOG_TLB)
-        for i in range(self.entries):
+
+        LOG_TLB = log2_int(self.BITS)
+        hit = Signal(self.BITS)
+        m.d.comb += hit.eq(Repl(self.acc_i, self.BITS) & self.acc_en)
+
+        for i in range(self.BITS):
             # we got a hit so update the pointer as it was least recently used
-            hit = Signal(reset_less=True)
-            m.d.comb += hit.eq(self.lu_hit[i] & self.lu_access_i)
-            with m.If(hit):
+            with m.If(hit[i]):
                 # Set the nodes to the values we would expect
                 for lvl in range(LOG_TLB):
                     idx_base = (1 << lvl)-1
                     # lvl0 <=> MSB, lvl1 <=> MSB-1, ...
                     shift = LOG_TLB - lvl
-                    new_idx = Const(~((i >> (shift-1)) & 1), (1, False))
+                    new_idx = Const(~((i >> (shift-1)) & 1), 1)
                     plru_idx = idx_base + (i >> shift)
                     print("plru", i, lvl, hex(idx_base),
                           plru_idx, shift, new_idx)
-                    m.d.comb += self.plru_tree_o[plru_idx].eq(new_idx)
+                    m.d.sync += plru_tree[plru_idx].eq(new_idx)
 
         # Decode tree to write enable signals
         # Next for-loop basically creates the following logic for e.g.
@@ -77,7 +81,7 @@ class PLRU(Elaboratable):
         # the corresponding bit of the entry's index, this is
         # the next entry to replace.
         replace = []
-        for i in range(self.entries):
+        for i in range(self.BITS):
             en = []
             for lvl in range(LOG_TLB):
                 idx_base = (1 << lvl)-1
@@ -87,20 +91,26 @@ class PLRU(Elaboratable):
                 plru_idx = idx_base + (i >> shift)
                 plru = Signal(reset_less=True,
                               name="plru-%d-%d-%d" % (i, lvl, plru_idx))
-                m.d.comb += plru.eq(self.plru_tree[plru_idx])
-                # en &= plru_tree_q[idx_base + (i>>shift)] == new_idx;
+                m.d.comb += plru.eq(plru_tree[plru_idx])
                 if new_idx:
-                    en.append(~plru)  # yes inverted (using bool())
+                    en.append(~plru)  # yes inverted (using bool() below)
                 else:
-                    en.append(plru)  # yes inverted (using bool())
-            print("plru", i, en)
+                    en.append(plru)  # yes inverted (using bool() below)
+            print("plru replace", i, en)
             # boolean logic manipulation:
             # plru0 & plru1 & plru2 == ~(~plru0 | ~plru1 | ~plru2)
             replace.append(~Cat(*en).bool())
-        m.d.comb += self.replace_en_o.eq(Cat(*replace))
+        m.d.comb += self.lru_o.eq(Cat(*replace))
 
         return m
 
     def ports(self):
-        return [self.entries, self.lu_hit, self.replace_en_o,
-                self.lu_access_i, self.plru_tree, self.plru_tree_o]
+        return [self.acc_en, self.lru_o, self.acc_i]
+
+
+if __name__ == '__main__':
+    dut = PLRU(4)
+    vl = rtlil.convert(dut, ports=dut.ports())
+    with open("test_plru.il", "w") as f:
+        f.write(vl)
+