test_ldst_pi.py: first version of test_dcache_random()
[soc.git] / src / soc / experiment / l0_cache.py
index 42d4ddc7144ff549bf69ca79b561fd57b8618f76..8414f77f75631691df9c358646fac454de950040 100644 (file)
@@ -23,12 +23,12 @@ from nmigen.utils import log2_int
 from nmigen.hdl.rec import Record, Layout
 
 from nmutil.latch import SRLatch, latchregister
-from soc.decoder.power_decoder2 import Data
-from soc.decoder.power_enums import MicrOp
+from openpower.decoder.power_decoder2 import Data
+from openpower.decoder.power_enums import MicrOp
 from soc.regfile.regfile import ortreereduce
 from nmutil.util import treereduce
 
-from soc.decoder.power_decoder2 import Data
+from openpower.decoder.power_decoder2 import Data
 #from nmutil.picker import PriorityPicker
 from nmigen.lib.coding import PriorityEncoder
 from soc.scoreboard.addr_split import LDSTSplitter
@@ -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}
@@ -198,20 +177,35 @@ class TstDataMerger2(Elaboratable):
             ul.append(CacheRecord())
         self.input_array = Array(ul)
 
+    def addr_match(self,j,addr):
+        ret = []
+        for k in range(self.n_units):
+            ret += [(addr[j] == addr[k])]
+        return Cat(*ret)
+
     def elaborate(self, platform):
         m = Module()
         m.submodules.dm_odd = dm_odd = DataMerger(self.n_units)
         m.submodules.dm_even = dm_even = DataMerger(self.n_units)
 
-        #TODO assign data and address match
-        #m.d.comb += dm_even.addr_array_i.eq(TODO)
-        #m.d.comb += dm_odd.addr_array_i.eq(TODO)
-        #m.d.comb += dm_even.data_i.eq(TODO)
-        #m.d.comb += dm_odd.data_i.eq(TODO)
+        addr_even = []
+        addr_odd = []
+        for j in range(self.n_units):
+            inp = self.input_array[j]
+            addr_even += [Cat(inp.addr,inp.a_even)]
+            addr_odd +=  [Cat(inp.addr,inp.a_odd)]
+
+        for j in range(self.n_units):
+            inp = self.input_array[j]
+            m.d.comb += dm_even.data_i[j].en.eq(inp.bytemask_even)
+            m.d.comb += dm_odd.data_i[j].en.eq(inp.bytemask_odd)
+            m.d.comb += dm_even.data_i[j].data.eq(inp.data_even)
+            m.d.comb += dm_odd.data_i[j].data.eq(inp.data_odd)
+            m.d.comb += dm_even.addr_array_i[j].eq(self.addr_match(j,addr_even))
+            m.d.comb += dm_odd.addr_array_i[j].eq(self.addr_match(j,addr_odd))
 
         m.d.comb += self.data_odd.eq(dm_odd.data_o.data)
         m.d.comb += self.data_even.eq(dm_even.data_o.data)
-        self.data
         return m
 
 
@@ -315,6 +309,7 @@ class L0CacheBuffer(Elaboratable):
 
 class TstL0CacheBuffer(Elaboratable):
     def __init__(self, pspec, n_units=3):
+        self.pspec = pspec
         regwid = pspec.reg_wid
         addrwid = pspec.addr_wid
         self.cmpi = ConfigMemoryPortInterface(pspec)
@@ -325,8 +320,18 @@ class TstL0CacheBuffer(Elaboratable):
         m = Module()
         m.submodules.pimem = self.pimem
         m.submodules.l0 = self.l0
-        if hasattr(self.cmpi, 'lsmem'):  # hmmm not happy about this
-            m.submodules.lsmem = self.cmpi.lsmem.lsi
+
+        if not hasattr(self.cmpi, 'lsmem'):
+            return m
+
+        # really bad hack, the LoadStore1 classes already have the
+        # lsi (LoadStoreInterface) as a submodule.
+        if self.pspec.ldst_ifacetype in ['mmu_cache_wb', 'test_mmu_cache_wb']:
+            return m
+
+        # hmmm not happy about this - should not be digging down and
+        # putting modules in
+        m.submodules.lsmem = self.cmpi.lsmem.lsi
 
         return m
 
@@ -377,7 +382,6 @@ def l0_cache_ldst(arg, dut):
 
 
 def data_merger_merge(dut):
-    print("data_merger")
     # starting with all inputs zero
     yield Settle()
     en = yield dut.data_o.en
@@ -398,6 +402,12 @@ def data_merger_merge(dut):
     assert en == 0xff
     yield
 
+def data_merger_test2(dut):
+    # starting with all inputs zero
+    yield Settle()
+    yield
+    yield
+
 
 class TestL0Cache(unittest.TestCase):
 
@@ -434,15 +444,16 @@ class TestDataMerger(unittest.TestCase):
 
     def test_data_merger(self):
 
-        dut = DataMerger(8)
+        dut = TstDataMerger2()
         #vl = rtlil.convert(dut, ports=dut.ports())
         # with open("test_data_merger.il", "w") as f:
         #    f.write(vl)
 
-        run_simulation(dut, data_merger_merge(dut),
+        run_simulation(dut, data_merger_test2(dut),
                        vcd_name='test_data_merger.vcd')
 
 
+
 class TestDualPortSplitter(unittest.TestCase):
 
     def test_dual_port_splitter(self):