start new version of Pi2LSUI based on PortInterfaceBase
[soc.git] / src / soc / experiment / pi2ls.py
index 548ac5e5a8333744ce003e4b6b9af63a5f1b04ee..f9059f05c1b6edd48c082381a06b342728b48a7c 100644 (file)
 from soc.minerva.units.loadstore import LoadStoreUnitInterface
 from soc.experiment.pimem import PortInterface
 from soc.scoreboard.addr_match import LenExpand
+from soc.experiment.pimem import PortInterfaceBase
+from nmigen.utils import log2_int
 
 from nmigen import Elaboratable, Module, Signal
 
 
-class Pi2LSUI(Elaboratable):
+class Pi2LSUI(PortInterfaceBase):
+
+    def __init__(self, name, lsui=None,
+                             data_wid=64, mask_wid=8, addr_wid=48):
+        print ("pi2lsui reg mask addr", data_wid, mask_wid, addr_wid)
+        super().__init__(data_wid, addr_wid)
+        if lsui is None:
+            lsui = LoadStoreUnitInterface(addr_wid, self.addrbits, data_wid)
+        self.lsui = lsui
+
+    def set_wr_addr(self, m, addr, mask):
+        m.d.comb += self.lsui.x_mask_i.eq(mask)
+        m.d.comb += self.lsui.x_addr_i.eq(addr)
+
+    def set_rd_addr(self, m, addr, mask):
+        m.d.comb += self.lsui.x_mask_i.eq(mask)
+        m.d.comb += self.lsui.x_addr_i.eq(addr)
+
+    def set_wr_data(self, m, data, wen): # mask already done in addr setup
+        m.d.comb += self.lsui.x_st_data_i.eq(data)
+        return ~self.lsui.x_busy_o
+
+    def get_rd_data(self, m):
+        return self.lsui.m_ld_data_o, ~self.lsui.x_busy_o
+
+    def elaborate(self, platform):
+        m = super().elaborate(platform)
+
+        return m
+
+
+class Pi2LSUI1(Elaboratable):
 
     def __init__(self, name, pi=None, lsui=None,
-                             regwid=64, mask_wid=8, addrwid=48):
+                             data_wid=64, mask_wid=8, addr_wid=48):
+        print ("pi2lsui reg mask addr", data_wid, mask_wid, addr_wid)
         self.addrbits = mask_wid
         if pi is None:
-            pi = PortInterface(name="%s_pi", regwid=regwid, addrwid=addrwid)
+            piname = "%s_pi" % name
+            pi = PortInterface(piname, regwid=data_wid, addrwid=addr_wid)
         self.pi = pi
         if lsui is None:
-            lsui = LoadStoreUnitInterface(addrwid, self.addrbits, regwid)
+            lsui = LoadStoreUnitInterface(addr_wid, self.addrbits, data_wid)
         self.lsui = lsui
 
     def splitaddr(self, addr):
@@ -46,32 +81,44 @@ class Pi2LSUI(Elaboratable):
         """
         return addr[:self.addrbits], addr[self.addrbits:]
 
+    def connect_port(self, inport):
+        return self.pi.connect_port(inport)
+
     def elaborate(self, platform):
         m = Module()
         pi, lsui, addrbits = self.pi, self.lsui, self.addrbits
-        m.submodules.lenexp = lenexp = LenExpand(self.addrbits, 8)
+        m.submodules.lenexp = lenexp = LenExpand(log2_int(self.addrbits), 8)
 
         ld_in_progress = Signal(reset=0)
+        st_in_progress = Signal(reset=0)
 
         m.d.comb += lsui.x_ld_i.eq(pi.is_ld_i)
         m.d.comb += lsui.x_st_i.eq(pi.is_st_i)
-        m.d.comb += pi.busy_o.eq(lsui.x_busy_o)
+        m.d.comb += pi.busy_o.eq(pi.is_ld_i | pi.is_st_i)#lsui.x_busy_o)
+
+        lsbaddr, msbaddr = self.splitaddr(pi.addr.data)
+        m.d.comb += lenexp.len_i.eq(pi.data_len)
+        m.d.comb += lenexp.addr_i.eq(lsbaddr) # LSBs of addr
+        m.d.comb += lsui.x_addr_i.eq(pi.addr.data) # XXX hmmm...
 
         with m.If(pi.addr.ok):
             # expand the LSBs of address plus LD/ST len into 16-bit mask
-            m.d.comb += lenexp.len_i.eq(pi.data_len)
-            m.d.comb += lenexp.addr_i.eq(pi.addr.data[addrbits]) # LSBs of addr
             m.d.comb += lsui.x_mask_i.eq(lenexp.lexp_o)
             # pass through the address, indicate "valid"
-            m.d.comb += lsui.x_addr_i.eq(pi.addr.data) # full address
             m.d.comb += lsui.x_valid_i.eq(1)
             # indicate "OK" - XXX should be checking address valid
             m.d.comb += pi.addr_ok_o.eq(1)
 
+        with m.If(~lsui.x_busy_o & pi.is_st_i & pi.addr.ok):
+                m.d.sync += st_in_progress.eq(1)
+
         with m.If(pi.is_ld_i):
-            m.d.comb += pi.ld.data.eq(lsui.m_ld_data_o)
+            # shift/mask out the loaded data
+            m.d.comb += pi.ld.data.eq((lsui.m_ld_data_o & lenexp.rexp_o) >>
+                                      (lenexp.addr_i*8))
             # remember we're in the process of loading
-            m.d.sync += ld_in_progress.eq(1)
+            with m.If(pi.addr.ok):
+                m.d.sync += ld_in_progress.eq(1)
 
         # If a load happened on the previous cycle and the memory is
         # not busy, that means it returned the data from the load. In
@@ -84,6 +131,10 @@ class Pi2LSUI(Elaboratable):
             m.d.comb += pi.ld.ok.eq(0)
 
         with m.If(pi.is_st_i & pi.st.ok):
-            m.d.comb += lsui.x_st_data_i.eq(pi.st.data)
+            m.d.comb += lsui.x_st_data_i.eq(pi.st.data << (lenexp.addr_i*8))
+            with m.If(st_in_progress):
+                m.d.sync += st_in_progress.eq(0)
+            with m.Else():
+                m.d.comb += pi.busy_o.eq(0)
 
         return m