initial version of L0CacheBuffer2
authorTobias Platen <tplaten@posteo.de>
Tue, 11 Aug 2020 17:16:47 +0000 (19:16 +0200)
committerTobias Platen <tplaten@posteo.de>
Tue, 11 Aug 2020 17:16:47 +0000 (19:16 +0200)
src/soc/experiment/l0_cache.py
src/soc/experiment/test/test_l0_cache_buffer2.py [new file with mode: 0644]
src/soc/scoreboard/addr_split.py
src/unused/experiment/l0_cache.py [new file with mode: 0644]

index 81ebd9301fefcbf4184782ccd03a1559eef43d54..e2c31096a78269e5d5f55548445524db81f79a71 100644 (file)
@@ -41,51 +41,30 @@ from soc.experiment.pimem import PortInterface
 from soc.config.test.test_pi2ls import pi_ld, pi_st, pi_ldst
 import unittest
 
+class L0CacheBuffer2(Elaboratable):
+    """L0CacheBuffer2"""
+    def __init__(self, n_units=8, regwid=64, addrwid=48):
+        self.n_units = n_units
+        self.regwid = regwid
+        self.addrwid = addrwid
+        ul = []
+        for i in range(self.n_units):
+            ul += [PortInterface()]
+        self.dports = Array(ul)
 
-class DualPortSplitter(Elaboratable):
-    """DualPortSplitter
-
-    * one incoming PortInterface
-    * two *OUTGOING* PortInterfaces
-    * uses LDSTSplitter to do it
-
-    (actually, thinking about it LDSTSplitter could simply be
-     modified to conform to PortInterface: one in, two out)
-
-    once that is done each pair of ports may be wired directly
-    to the dual ports of L0CacheBuffer
-
-    The split is carried out so that, regardless of alignment or
-    mis-alignment, outgoing PortInterface[0] takes bit 4 == 0
-    of the address, whilst outgoing PortInterface[1] takes
-    bit 4 == 1.
+    def elaborate(self, platform):
+        m = Module()
+        comb, sync = m.d.comb, m.d.sync
 
-    PortInterface *may* need to be changed so that the length is
-    a binary number (accepting values 1-16).
-    """
+        # connect the ports as modules
 
-    def __init__(self):
-        self.outp = [PortInterface(name="outp_0"),
-                     PortInterface(name="outp_1")]
-        self.inp = PortInterface(name="inp")
-        print(self.outp)
+        for i in range(self.n_units):
+            d = LDSTSplitter(64, 48, 4, self.dports[i])
+            setattr(m.submodules, "ldst_splitter%d" % i, d)
 
-    def elaborate(self, platform):
-        m = Module()
-        comb = m.d.comb
-        m.submodules.splitter = splitter = LDSTSplitter(64, 48, 4)
-        comb += splitter.addr_i.eq(self.inp.addr)  # XXX
-        #comb += splitter.len_i.eq()
-        #comb += splitter.valid_i.eq()
-        comb += splitter.is_ld_i.eq(self.inp.is_ld_i)
-        comb += splitter.is_st_i.eq(self.inp.is_st_i)
-        #comb += splitter.st_data_i.eq()
-        #comb += splitter.sld_valid_i.eq()
-        #comb += splitter.sld_data_i.eq()
-        #comb += splitter.sst_valid_i.eq()
+        # state-machine latches TODO
         return m
 
-
 class DataMergerRecord(Record):
     """
     {data: 128 bit, byte_enable: 16 bit}
diff --git a/src/soc/experiment/test/test_l0_cache_buffer2.py b/src/soc/experiment/test/test_l0_cache_buffer2.py
new file mode 100644 (file)
index 0000000..33c6355
--- /dev/null
@@ -0,0 +1,30 @@
+"""
+TODO
+"""
+
+from soc.experiment.l0_cache import L0CacheBuffer2
+from nmigen import Module
+from nmigen.cli import rtlil
+#cxxsim = False
+#if cxxsim:
+#    from nmigen.sim.cxxsim import Simulator, Settle
+#else:
+#    from nmigen.back.pysim import Simulator, Settle
+from nmigen.compat.sim import run_simulation, Settle
+
+def test_cache_run(dut):
+    yield
+
+def test_cache():
+    dut = L0CacheBuffer2()
+
+    #vl = rtlil.convert(dut, ports=dut.ports())
+    # with open("test_data_merger.il", "w") as f:
+    #    f.write(vl)
+
+    run_simulation(dut, test_cache_run(dut),
+                   vcd_name='test_cache.vcd')
+
+if __name__ == '__main__':
+    test_cache()
+    #TODO make debug output optional
index b3156595300170a9692837809b2b150301c19360..4a9573382cdcf5bbb280a9450e4591ca8df8c795 100644 (file)
@@ -69,18 +69,21 @@ def byteExpand(signal):
     lst = []
     for i in range(len(signal)):
         bit = signal[i]
-        for j in range(8):
+        for j in range(8): #TODO this can be optimized
             lst += [bit]
     return Cat(*lst)
 
 class LDSTSplitter(Elaboratable):
 
-    def __init__(self, dwidth, awidth, dlen):
+    def __init__(self, dwidth, awidth, dlen, pi=None):
         self.dwidth, self.awidth, self.dlen = dwidth, awidth, dlen
         # cline_wid = 8<<dlen # cache line width: bytes (8) times (2^^dlen)
         cline_wid = dwidth*8  # convert bytes to bits
 
-        self.pi =  PortInterface()
+        if(pi is None):
+            self.pi = PortInterface()
+        else:
+            self.pi = pi
 
         self.addr_i = self.pi.addr.data  #Signal(awidth, reset_less=True)
         # no match in PortInterface
diff --git a/src/unused/experiment/l0_cache.py b/src/unused/experiment/l0_cache.py
new file mode 100644 (file)
index 0000000..3b8a7d9
--- /dev/null
@@ -0,0 +1,42 @@
+class DualPortSplitter(Elaboratable):
+    """DualPortSplitter
+
+    * one incoming PortInterface
+    * two *OUTGOING* PortInterfaces
+    * uses LDSTSplitter to do it
+
+    (actually, thinking about it LDSTSplitter could simply be
+     modified to conform to PortInterface: one in, two out)
+
+    once that is done each pair of ports may be wired directly
+    to the dual ports of L0CacheBuffer
+
+    The split is carried out so that, regardless of alignment or
+    mis-alignment, outgoing PortInterface[0] takes bit 4 == 0
+    of the address, whilst outgoing PortInterface[1] takes
+    bit 4 == 1.
+
+    PortInterface *may* need to be changed so that the length is
+    a binary number (accepting values 1-16).
+    """
+
+    def __init__(self,inp):
+        self.outp = [PortInterface(name="outp_0"),
+                     PortInterface(name="outp_1")]
+        print(self.outp)
+
+    def elaborate(self, platform):
+        m = Module()
+        comb = m.d.comb
+        m.submodules.splitter = splitter = LDSTSplitter(64, 48, 4)
+        self.inp = splitter.pi
+        comb += splitter.addr_i.eq(self.inp.addr)  # XXX
+        #comb += splitter.len_i.eq()
+        #comb += splitter.valid_i.eq()
+        comb += splitter.is_ld_i.eq(self.inp.is_ld_i)
+        comb += splitter.is_st_i.eq(self.inp.is_st_i)
+        #comb += splitter.st_data_i.eq()
+        #comb += splitter.sld_valid_i.eq()
+        #comb += splitter.sld_data_i.eq()
+        #comb += splitter.sst_valid_i.eq()
+        return m