forgot to pass cix (cache-inhibited) through to LD/ST which was
[soc.git] / src / soc / fu / ldst / loadstore.py
index 6af17736944c4bacaa879f82dafc7c69aa86e851..6e868b1eebdd7eeffbc6f1812c29e508a0a0ad9c 100644 (file)
@@ -19,7 +19,7 @@ Links:
 
 from nmigen import (Elaboratable, Module, Signal, Shape, unsigned, Cat, Mux,
                     Record, Memory,
-                    Const)
+                    Const, C)
 from nmutil.iocontrol import RecordObject
 from nmutil.util import rising_edge, Display
 from enum import Enum, unique
@@ -118,6 +118,7 @@ class LoadStore1(PortInterfaceBase):
         self.load_data_delay = Signal(128) # perform 2 LD/STs
         self.byte_sel      = Signal(16)    # also for misaligned, 16-bit
         self.alignstate    = Signal(Misalign) # progress of alignment request
+        self.next_addr      = Signal(64)      # 2nd (aligned) read/write addr
         #self.xerc         : xer_common_t;
         #self.rc            = Signal()
         self.nc            = Signal()              # non-cacheable access
@@ -148,7 +149,8 @@ class LoadStore1(PortInterfaceBase):
     def external_busy(self, m):
         return self.instr_fault | self.r_instr_fault
 
-    def set_wr_addr(self, m, addr, mask, misalign, msr, is_dcbz):
+    def set_wr_addr(self, m, addr, mask, misalign, msr, is_dcbz, is_nc):
+        m.d.comb += self.req.nc.eq(is_nc)
         m.d.comb += self.req.load.eq(0) # store operation
         m.d.comb += self.req.byte_sel.eq(mask)
         m.d.comb += self.req.raddr.eq(addr)
@@ -158,6 +160,7 @@ class LoadStore1(PortInterfaceBase):
         m.d.comb += self.req.dcbz.eq(is_dcbz)
         with m.If(misalign):
             m.d.comb += self.req.alignstate.eq(Misalign.NEED2WORDS)
+            m.d.sync += self.next_addr.eq(Cat(C(0, 3), addr[3:]+1))
 
         # m.d.comb += Display("set_wr_addr %i dcbz %i",addr,is_dcbz)
 
@@ -177,7 +180,7 @@ class LoadStore1(PortInterfaceBase):
 
         return None
 
-    def set_rd_addr(self, m, addr, mask, misalign, msr):
+    def set_rd_addr(self, m, addr, mask, misalign, msr, is_nc):
         m.d.comb += self.d_valid.eq(1)
         m.d.comb += self.req.load.eq(1) # load operation
         m.d.comb += self.req.byte_sel.eq(mask)
@@ -185,6 +188,7 @@ class LoadStore1(PortInterfaceBase):
         m.d.comb += self.req.priv_mode.eq(~msr.pr) # not-problem  ==> priv
         m.d.comb += self.req.virt_mode.eq(msr.dr) # DR ==> virt
         m.d.comb += self.req.mode_32bit.eq(~msr.sf) # not-sixty-four ==> 32bit
+        m.d.comb += self.req.nc.eq(is_nc)
         # BAD HACK! disable cacheing on LD when address is 0xCxxx_xxxx
         # this is for peripherals. same thing done in Microwatt loadstore1.vhdl
         with m.If(addr[28:] == Const(0xc, 4)):
@@ -193,7 +197,9 @@ class LoadStore1(PortInterfaceBase):
         if self.disable_cache:
             m.d.comb += self.req.nc.eq(1)
         with m.If(misalign):
+            # need two reads: prepare next address in advance
             m.d.comb += self.req.alignstate.eq(Misalign.NEED2WORDS)
+            m.d.sync += self.next_addr.eq(Cat(C(0, 3), addr[3:]+1))
 
         # hmm, rather than add yet another argument to set_rd_addr
         # read direct from PortInterface
@@ -328,14 +334,12 @@ class LoadStore1(PortInterfaceBase):
                             m.d.sync += d_out.data.eq(self.store_data2)
                         # mmm kinda cheating, make a 2nd blip.
                         # use an aligned version of the address
-                        addr_aligned, z3 = Signal(64), Const(0, 3)
-                        comb += addr_aligned.eq(Cat(z3, ldst_r.raddr[3:]+1))
                         m.d.comb += self.d_validblip.eq(1)
                         comb += self.req.eq(ldst_r) # from copy of request
-                        comb += self.req.raddr.eq(addr_aligned)
+                        comb += self.req.raddr.eq(self.next_addr)
                         comb += self.req.byte_sel.eq(ldst_r.byte_sel[8:])
                         comb += self.req.alignstate.eq(Misalign.WAITSECOND)
-                        sync += ldst_r.raddr.eq(addr_aligned)
+                        sync += ldst_r.raddr.eq(self.next_addr)
                         sync += ldst_r.byte_sel.eq(ldst_r.byte_sel[8:])
                         sync += ldst_r.alignstate.eq(Misalign.WAITSECOND)
                         sync += Display("    second req %x", self.req.raddr)