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):
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
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)
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
# 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)
# 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)
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):