add misalign flag to PortInterfaceBase
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 9 May 2021 12:29:19 +0000 (13:29 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 9 May 2021 12:29:19 +0000 (13:29 +0100)
allows first exception to be generated

src/soc/experiment/pi2ls.py
src/soc/experiment/pimem.py
src/soc/experiment/test/test_l0_cache_buffer2.py
src/soc/experiment/test/test_mmu_dcache_pi.py
src/soc/fu/ldst/loadstore.py

index f07ba33c39add5e05b418dbe69a876e52166cf2b..19278be1da8226df33bc792dbf5abd958e4598d5 100644 (file)
@@ -46,12 +46,12 @@ class Pi2LSUI(PortInterfaceBase):
         self.lsui_busy = Signal()
         self.valid_l = SRLatch(False, name="valid")
 
-    def set_wr_addr(self, m, addr, mask):
+    def set_wr_addr(self, m, addr, mask, misalign):
         m.d.comb += self.valid_l.s.eq(1)
         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):
+    def set_rd_addr(self, m, addr, mask, misalign):
         m.d.comb += self.valid_l.s.eq(1)
         m.d.comb += self.lsui.x_mask_i.eq(mask)
         m.d.comb += self.lsui.x_addr_i.eq(addr)
index e9923ca602b4d6a8aa7520878b9b6f9a65969d2e..b051edd1624c2dbffa0e1dcf371a1a90fe178d4d 100644 (file)
@@ -169,8 +169,8 @@ class PortInterfaceBase(Elaboratable):
     def connect_port(self, inport):
         return self.pi.connect_port(inport)
 
-    def set_wr_addr(self, m, addr, mask): pass
-    def set_rd_addr(self, m, addr, mask): pass
+    def set_wr_addr(self, m, addr, mask, misalign): pass
+    def set_rd_addr(self, m, addr, mask, misalign): pass
     def set_wr_data(self, m, data, wen): pass
     def get_rd_data(self, m): pass
 
@@ -215,6 +215,12 @@ class PortInterfaceBase(Elaboratable):
         sync += busy_delay.eq(pi.busy_o)
         comb += busy_edge.eq(pi.busy_o & ~busy_delay)
 
+        # misalignment detection: bits at end of lenexpand are set.
+        # when using the L0CacheBuffer "data expander" which splits requests
+        # into *two* PortInterfaces, this acts as a "safety check".
+        misalign = Signal()
+        comb += misalign.eq(lenexp.lexp_o[8:].bool())
+
         # activate mode: only on "edge"
         comb += ld_active.s.eq(rising_edge(m, lds))  # activate LD mode
         comb += st_active.s.eq(rising_edge(m, sts))  # activate ST mode
@@ -231,7 +237,7 @@ class PortInterfaceBase(Elaboratable):
             comb += lenexp.len_i.eq(pi.data_len)
             comb += lenexp.addr_i.eq(lsbaddr)
             with m.If(pi.addr.ok & adrok_l.qn):
-                self.set_rd_addr(m, pi.addr.data, lenexp.lexp_o)
+                self.set_rd_addr(m, pi.addr.data, lenexp.lexp_o, misalign)
                 comb += pi.addr_ok_o.eq(1)  # acknowledge addr ok
                 sync += adrok_l.s.eq(1)       # and pull "ack" latch
 
@@ -243,7 +249,7 @@ class PortInterfaceBase(Elaboratable):
             comb += lenexp.len_i.eq(pi.data_len)
             comb += lenexp.addr_i.eq(lsbaddr)
             with m.If(pi.addr.ok):
-                self.set_wr_addr(m, pi.addr.data, lenexp.lexp_o)
+                self.set_wr_addr(m, pi.addr.data, lenexp.lexp_o, misalign)
                 with m.If(adrok_l.qn):
                     comb += pi.addr_ok_o.eq(1)  # acknowledge addr ok
                     sync += adrok_l.s.eq(1)       # and pull "ack" latch
@@ -330,11 +336,11 @@ class TestMemoryPortInterface(PortInterfaceBase):
         # hard-code memory addressing width to 6 bits
         self.mem = TestMemory(regwid, 5, granularity=regwid//8, init=False)
 
-    def set_wr_addr(self, m, addr, mask):
+    def set_wr_addr(self, m, addr, mask, misalign):
         lsbaddr, msbaddr = self.splitaddr(addr)
         m.d.comb += self.mem.wrport.addr.eq(msbaddr)
 
-    def set_rd_addr(self, m, addr, mask):
+    def set_rd_addr(self, m, addr, mask, misalign):
         lsbaddr, msbaddr = self.splitaddr(addr)
         m.d.comb += self.mem.rdport.addr.eq(msbaddr)
 
index 11fa645d39fc55ba7d5e91ec7531cbf08479d7da..e90445496ed670585e19036d6b40e9719b9d595e 100644 (file)
@@ -25,10 +25,10 @@ class TestCachedMemoryPortInterface(PortInterfaceBase):
         super().__init__(regwid, addrwid)
         self.ldst = LDSTSplitter(32, 48, 4)
 
-    def set_wr_addr(self, m, addr, mask):
+    def set_wr_addr(self, m, addr, mask, misalign):
         m.d.comb += self.ldst.addr_i.eq(addr)
 
-    def set_rd_addr(self, m, addr, mask):
+    def set_rd_addr(self, m, addr, mask, misalign):
         m.d.comb += self.ldst.addr_i.eq(addr)
 
     def set_wr_data(self, m, data, wen):
@@ -54,6 +54,7 @@ class TestCachedMemoryPortInterface(PortInterfaceBase):
         yield from super().ports()
         # TODO: memory ports
 
+
 def test_cache_single_run(dut):
     #test single byte
     addr = 0
index 1c74261c3b79334db8f7f6de236a46159c89fe38..0dc182b290bb890757718337853dfe84464bcac9 100644 (file)
@@ -54,14 +54,14 @@ class TestMicrowattMemoryPortInterface(PortInterfaceBase):
         self.mmu = mmu
         self.dcache = dcache
 
-    def set_wr_addr(self, m, addr, mask):
+    def set_wr_addr(self, m, addr, mask, misalign):
         m.d.comb += self.dcache.d_in.addr.eq(addr)
         m.d.comb += self.mmu.l_in.addr.eq(addr)
         m.d.comb += self.mmu.l_in.load.eq(0)
         m.d.comb += self.mmu.l_in.priv.eq(1)
         m.d.comb += self.mmu.l_in.valid.eq(1)
 
-    def set_rd_addr(self, m, addr, mask):
+    def set_rd_addr(self, m, addr, mask, misalign):
         m.d.comb += self.dcache.d_in.addr.eq(addr)
         m.d.comb += self.mmu.l_in.addr.eq(addr)
         m.d.comb += self.mmu.l_in.load.eq(1)
index c622ab21799f4d7458cfb0f7f84e62af258ddc52..18d09509ad27034a2bdf926e1b35994b08b9478b 100644 (file)
@@ -89,7 +89,7 @@ class LoadStore1(PortInterfaceBase):
         #self.nia           = Signal(64)
         #self.srr1          = Signal(16)
 
-    def set_wr_addr(self, m, addr, mask):
+    def set_wr_addr(self, m, addr, mask, misalign):
         m.d.comb += self.load.eq(0) # store operation
 
         m.d.comb += self.d_in.load.eq(0)
@@ -100,7 +100,7 @@ class LoadStore1(PortInterfaceBase):
             m.d.comb += self.nc.eq(1)
         return None
 
-    def set_rd_addr(self, m, addr, mask):
+    def set_rd_addr(self, m, addr, mask, misalign):
         m.d.comb += self.d_valid.eq(1)
         m.d.comb += self.d_in.valid.eq(self.d_validblip)
         m.d.comb += self.load.eq(1) # load operation