whoops missing default zero (no idea how)
[soc.git] / src / soc / experiment / compldst_multi.py
index 8e9f4ec35718541824a78e3ab857dfbf8f307378..7dfdb15ecb45a0f41449418db612c3f774cddccc 100644 (file)
@@ -92,9 +92,15 @@ from soc.experiment.l0_cache import PortInterface
 from soc.experiment.pimem import LDSTException
 from soc.fu.regspec import RegSpecAPI
 
-from soc.decoder.power_enums import MicrOp, Function, LDSTMode
+from openpower.decoder.power_enums import MicrOp, Function, LDSTMode
 from soc.fu.ldst.ldst_input_record import CompLDSTOpSubset
-from soc.decoder.power_decoder2 import Data
+from openpower.decoder.power_decoder2 import Data
+from openpower.consts import MSR
+
+
+# TODO: LDSTInputData and LDSTOutputData really should be used
+# here, to make things more like the other CompUnits.  currently,
+# also, RegSpecAPI is used explicitly here
 
 
 class LDSTCompUnitRecord(CompUnitRecord):
@@ -105,7 +111,7 @@ class LDSTCompUnitRecord(CompUnitRecord):
         self.ad = go_record(1, name="cu_ad")  # address go in, req out
         self.st = go_record(1, name="cu_st")  # store go in, req out
 
-        self.exception_o = LDSTException("exc")
+        self.exc_o = LDSTException("exc_o")
 
         self.ld_o = Signal(reset_less=True)  # operation is a LD
         self.st_o = Signal(reset_less=True)  # operation is a ST
@@ -131,11 +137,11 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
 
     Data (outputs)
     --------------
-    * :data_o:     Dest out (LD)          - managed by wr[0] go/req
-    * :addr_o:     Address out (LD or ST) - managed by wr[1] go/req
-    * :exception_o: Address/Data Exception occurred.  LD/ST must terminate
+    * :data_o:  Dest out (LD)          - managed by wr[0] go/req
+    * :addr_o:  Address out (LD or ST) - managed by wr[1] go/req
+    * :exc_o:   Address/Data Exception occurred.  LD/ST must terminate
 
-    TODO: make exception_o a data-type rather than a single-bit signal
+    TODO: make exc_o a data-type rather than a single-bit signal
           (see bug #302)
 
     Control Signals (In)
@@ -228,7 +234,7 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
 
         self.data_o = Data(self.data_wid, name="o")  # Dest1 out: RT
         self.addr_o = Data(self.data_wid, name="ea")  # Addr out: Update => RA
-        self.exception_o = cu.exception_o
+        self.exc_o = cu.exc_o
         self.done_o = cu.done_o
         self.busy_o = cu.busy_o
 
@@ -442,22 +448,26 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
         # address release only if addr ready, but Port must be idle
         comb += self.adr_rel_o.eq(alu_valid & adr_l.q & busy_o)
 
+        # the write/store (etc) all must be cancelled if an exception occurs
+        cancel = Signal(reset_less=True)
+        comb += cancel.eq(self.exc_o.happened | self.shadown_i)
+
         # store release when st ready *and* all operands read (and no shadow)
         comb += self.st.rel_o.eq(sto_l.q & busy_o & rd_done & op_is_st &
-                               self.shadown_i)
+                               cancel)
 
         # request write of LD result.  waits until shadow is dropped.
         comb += self.wr.rel_o[0].eq(rd_done & wri_l.q & busy_o & lod_l.qn &
-                                  op_is_ld & self.shadown_i)
+                                  op_is_ld & cancel)
 
         # request write of EA result only in update mode
         comb += self.wr.rel_o[1].eq(upd_l.q & busy_o & op_is_update &
-                                  alu_valid & self.shadown_i)
+                                  alu_valid & cancel)
 
         # provide "done" signal: select req_rel for non-LD/ST, adr_rel for LD/ST
         comb += wr_any.eq(self.st.go_i | p_st_go |
                           self.wr.go_i[0] | self.wr.go_i[1])
-        comb += wr_reset.eq(rst_l.q & busy_o & self.shadown_i &
+        comb += wr_reset.eq(rst_l.q & busy_o & cancel &
                             ~(self.st.rel_o | self.wr.rel_o[0] |
                               self.wr.rel_o[1]) &
                             (lod_l.qn | op_is_st)
@@ -492,8 +502,10 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
         # address: use sync to avoid long latency
         sync += pi.addr.data.eq(addr_r)           # EA from adder
         sync += pi.addr.ok.eq(alu_ok & lsd_l.q)  # "do address stuff" (once)
-        comb += self.exception_o.eq(pi.exception_o)  # exception occurred
+        comb += self.exc_o.eq(pi.exc_o)  # exception occurred
         comb += addr_ok.eq(self.pi.addr_ok_o)  # no exc, address fine
+        # connect MSR.PR for priv/virt operation
+        comb += pi.msr_pr.eq(oper_r.msr[MSR.PR])
 
         # byte-reverse on LD
         revnorev = Signal(64, reset_less=True)
@@ -533,11 +545,13 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
         return m
 
     def get_out(self, i):
-        """make LDSTCompUnit look like RegSpecALUAPI"""
+        """make LDSTCompUnit look like RegSpecALUAPI.  these correspond
+        to LDSTOutputData o and o1 respectively.
+        """
         if i == 0:
-            return self.data_o
+            return self.data_o # LDSTOutputData.regspec o
         if i == 1:
-            return self.addr_o
+            return self.addr_o # LDSTOutputData.regspec o1
         # return self.dest[i]
 
     def get_fu_out(self, i):