return res # enumerate(res)
+# a hazard bitvector "remap" function which returns an AST expression
+# that remaps read/write hazard regfile port numbers to either a full
+# bitvector or a reduced subset one. SPR for example is reduced to a
+# single bit.
+# CRITICALLY-IMPORTANT NOTE: these bitvectors *have* to match up per
+# regfile! therefore the remapping is per regfile, *NOT* per regfile
+# port and certainly not based on whether it is a read port or write port.
+# note that any reductions here will result in degraded performance due
+# to conflicts, but at least it keeps the hazard matrix sizes down to "sane"
+def bitvector_remap(regfile, rfile, port):
+ # 8-bits (at the moment, no SVP64), CR is unary: no remap
+ if regfile == 'CR':
+ return port
+ # 3 bits, unary alrady: return the port
+ if regfile == 'XER':
+ return port
+ # 3 bits, unary: return the port
+ if regfile == 'XER':
+ return port
+ # 5 bits, unary: return the port
+ if regfile == 'STATE':
+ return port
+ # 9 bits (9 entries), might be unary already
+ if regfile == 'FAST':
+ if rfile.unary: # FAST might be unary already
+ return port
+ else:
+ return 1 << port
+ # 10 bits (!!) - reduce to one
+ if regfile == 'SPR':
+ if rfile.unary: # FAST might be unary already
+ return port
+ else:
+ return 1 << port
+ if regfile == 'INT':
+ if rfile.unary: # INT, check if unary/binary
+ return port
+ else:
+ return 1 << port
+
+
# derive from ControlBase rather than have a separate Stage instance,
# this is simpler to do
class NonProductionCore(ControlBase):
# link LoadStore1 into MMU
mmu = self.fus.get_fu('mmu0')
+ ldst0 = self.fus.get_fu('ldst0')
print ("core pspec", pspec.ldst_ifacetype)
print ("core mmu", mmu)
if mmu is not None:
- print ("core lsmem.lsi", l0.cmpi.lsmem.lsi)
- mmu.alu.set_ldst_interface(l0.cmpi.lsmem.lsi)
+ lsi = l0.cmpi.lsmem.lsi # a LoadStore1 Interface object
+ print ("core lsmem.lsi", lsi)
+ mmu.alu.set_ldst_interface(lsi)
+ # urr store I-Cache in core so it is easier to get at
+ self.icache = lsi.icache
+
+ # alternative reset values for STATE regs. these probably shouldn't
+ # be set, here, instead have them done by Issuer. which they are.
+ # as well. because core.state overrides them. sigh.
+ self.msr_at_reset = 0x0
+ self.pc_at_reset = 0x0
+ if hasattr(pspec, "msr_reset") and isinstance(pspec.msr_reset, int):
+ self.msr_at_reset = pspec.msr_reset
+ if hasattr(pspec, "pc_reset") and isinstance(pspec.pc_reset, int):
+ self.pc_at_reset = pspec.pc_reset
+ state_resets = [self.pc_at_reset, # PC at reset
+ self.msr_at_reset, # MSR at reset
+ 0x0, # SVSTATE at reset
+ 0x0, # DEC at reset
+ 0x0] # TB at reset
# register files (yes plural)
- self.regs = RegFiles(pspec, make_hazard_vecs=self.make_hazard_vecs)
+ self.regs = RegFiles(pspec, make_hazard_vecs=self.make_hazard_vecs,
+ state_resets=state_resets)
# set up input and output: unusual requirement to set data directly
# (due to the way that the core is set up in a different domain,
svp64_en=self.svp64_en,
regreduce_en=self.regreduce_en)
self.des[funame] = self.decoders[funame].do
+ print ("create decoder subset", funame, opkls, self.des[funame])
# create per-Function Unit write-after-write hazard signals
# yes, really, this should have been added in ReservationStations
if "mmu0" in self.decoders:
self.decoders["mmu0"].mmu0_spr_dec = self.decoders["spr0"]
+ # allow pausing of the DEC/TB FSM back in Issuer, by spotting
+ # if there is an MTSPR instruction
+ self.pause_dec_tb = Signal()
+
# next 3 functions are Stage API Compliance
def setup(self, m, i):
pass
# is a waw hazard. decoder has to still
# be asserted in order to detect that, tho
comb += fu.oper_i.eq_from(do)
+ if funame == 'mmu0':
+ # URRR this is truly dreadful.
+ # OP_FETCH_FAILED is a "fake" op.
+ # no instruction creates it. OP_TRAP
+ # uses the *main* decoder: this is
+ # a *Satellite* decoder that reacts
+ # on *insn_in*... not fake ops. gaah.
+ main_op = self.ireg.e.do
+ with m.If(main_op.insn_type ==
+ MicrOp.OP_FETCH_FAILED):
+ comb += fu.oper_i.insn_type.eq(
+ MicrOp.OP_FETCH_FAILED)
+ comb += fu.oper_i.fn_unit.eq(
+ Function.MMU)
# issue when valid (and no write-hazard)
comb += fu.issue_i.eq(~self.waw_hazard)
# instruction ok, indicate ready
funame.lower().startswith('trap')):
with m.If(fu.busy_o):
comb += busy_o.eq(1)
+ # for SPR pipeline pause dec/tb FSM to avoid race condition
+ # TODO: really this should be much more sophisticated,
+ # spot MTSPR, spot that DEC/TB is what is to be updated.
+ # a job for PowerDecoder2, there
+ if funame.lower().startswith('spr'):
+ with m.If(fu.busy_o #& fu.oper_i.insn_type == OP_MTSPR
+ ):
+ comb += self.pause_dec_tb.eq(1)
# return both the function unit "enable" dict as well as the "busy".
# the "busy-or-issued" can be passed in to the Read/Write port
# the PowerDecoder2 (main one, not the satellites) contains
# the decoded regfile numbers. obtain these now
- okflag, regport = regspec_decode(m, readmode, e,
- regfile, regname)
+ decinfo = regspec_decode(m, readmode, e, regfile, regname)
+ okflag, regport = decinfo.okflag, decinfo.regport
# construct the dictionary of regspec information by regfile
if regname not in byregfiles_spec[regfile]:
if __name__ == '__main__':
pspec = TestMemPspec(ldst_ifacetype='testpi',
imem_ifacetype='',
- addr_wid=48,
+ addr_wid=64,
allow_overlap=True,
mask_wid=8,
reg_wid=64)