# connect each satellite decoder and give it the instruction.
# as subset decoders this massively reduces wire fanout given
# the large number of ALUs
- setattr(m.submodules, "dec_%s" % v.fn_name, v)
+ m.submodules["dec_%s" % v.fn_name] = v
comb += v.dec.raw_opcode_in.eq(self.ireg.raw_insn_i)
comb += v.dec.bigendian.eq(self.ireg.bigendian_i)
# sigh due to SVP64 RA_OR_ZERO detection connect these too
# and resolved
with m.If(self.issue_conflict):
comb += busy_o.eq(1)
+ # make sure that LDST, SPR, MMU, Branch and Trap all say "busy"
+ # and do not allow overlap. these are all the ones that
+ # are non-forward-progressing: exceptions etc. that otherwise
+ # change CoreState for some reason (MSR, PC, SVSTATE)
+ for funame, fu in fus.items():
+ if (funame.lower().startswith('ldst') or
+ funame.lower().startswith('branch') or
+ funame.lower().startswith('mmu') or
+ funame.lower().startswith('spr') or
+ funame.lower().startswith('trap')):
+ with m.If(fu.busy_o):
+ comb += busy_o.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
# create a priority picker to manage this port
rdpickers[regfile][rpidx] = rdpick = PriorityPicker(pplen)
- setattr(m.submodules, "rdpick_%s_%s" % (regfile, rpidx), rdpick)
+ m.submodules["rdpick_%s_%s" % (regfile, rpidx)] = rdpick
rens = []
addrs = []
# the detection of what shall be written to is based
# on *issue*. it is delayed by 1 cycle so that instructions
# "addi 5,5,0x2" do not cause combinatorial loops due to
- # fake-dependency on *themselves*
+ # fake-dependency on *themselves*. this will totally fail
+ # spectacularly when doing multi-issue
print ("write vector (for regread)", regfile, wvset)
wviaddr_en = Signal(len(wvset), name="wv_issue_addr_en_"+name)
issue_active = Signal(name="iactive_"+name)
wvset = wv.s # write-vec bit-level hazard ctrl
wvclr = wv.r # write-vec bit-level hazard ctrl
wvchk = wv.q # write-after-write hazard check
- wvchk_qint = wv.q_int # write-after-write hazard check, delayed
+ wvchk_qint = wv.q # write-after-write hazard check, NOT delayed
fspecs = fspec
if not isinstance(fspecs, list):
# create a priority picker to manage this port
wrpickers[regfile][rpidx] = wrpick = PriorityPicker(pplen)
- setattr(m.submodules, "wrpick_%s_%s" % (regfile, rpidx), wrpick)
+ m.submodules["wrpick_%s_%s" % (regfile, rpidx)] = wrpick
wsigs = []
wens = []
comb += wport.wen.eq(ortreereduce_sig(wens))
if not self.make_hazard_vecs:
- return
-
- # for write-vectors
- comb += wvclr.eq(ortreereduce_sig(wvclren)) # clear (regfile write)
- comb += wvset.eq(ortreereduce_sig(wvseten)) # set (issue time)
+ return [], []
+
+ # return these here rather than set wvclr/wvset directly,
+ # because there may be more than one write-port to a given
+ # regfile. example: XER has a write-port for SO, CA, and OV
+ # and the *last one added* of those would overwrite the other
+ # two. solution: have connect_wrports collate all the
+ # or-tree-reduced bitvector set/clear requests and drop them
+ # in as a single "thing". this can only be done because the
+ # set/get is an unary bitvector.
+ print ("make write-vecs", regfile, regname, wvset, wvclr)
+ return (ortreereduce_sig(wvclren), # clear (regfile write)
+ ortreereduce_sig(wvseten)) # set (issue time)
def connect_wrports(self, m, fu_bitdict, fu_selected):
"""connect write ports
# same for write ports.
# BLECH! complex code-duplication! BLECH!
wrpickers = {}
+ wvclrers = defaultdict(list)
+ wvseters = defaultdict(list)
for regfile, spec in byregfiles_wr.items():
fuspecs = byregfiles_wrspec[regfile]
wrpickers[regfile] = {}
if 'fast3' in fuspecs:
fuspecs['fast1'].append(fuspecs.pop('fast3'))
+ # collate these and record them by regfile because there
+ # are sometimes more write-ports per regfile
for (regname, fspec) in sort_fuspecs(fuspecs):
- self.connect_wrport(m, fu_bitdict, fu_selected, wrpickers,
+ wvclren, wvseten = self.connect_wrport(m,
+ fu_bitdict, fu_selected,
+ wrpickers,
regfile, regname, fspec)
+ wvclrers[regfile.lower()].append(wvclren)
+ wvseters[regfile.lower()].append(wvseten)
+
+ if not self.make_hazard_vecs:
+ return
+
+ # for write-vectors: reduce the clr-ers and set-ers down to
+ # a single set of bits. otherwise if there are two write
+ # ports (on some regfiles), the last one doing comb += on
+ # the reg.wv[regfile] instance "wins" (and all others are ignored,
+ # whoops). if there was only one write-port per wv regfile this would
+ # not be an issue.
+ for regfile in wvclrers.keys():
+ wv = regs.wv[regfile]
+ wvset = wv.s # write-vec bit-level hazard ctrl
+ wvclr = wv.r # write-vec bit-level hazard ctrl
+ wvclren = wvclrers[regfile]
+ wvseten = wvseters[regfile]
+ comb += wvclr.eq(ortreereduce_sig(wvclren)) # clear (regfile write)
+ comb += wvset.eq(ortreereduce_sig(wvseten)) # set (issue time)
def get_byregfiles(self, readmode):
pspec = TestMemPspec(ldst_ifacetype='testpi',
imem_ifacetype='',
addr_wid=48,
+ allow_overlap=True,
mask_wid=8,
reg_wid=64)
dut = NonProductionCore(pspec)