+ def connect_rdport(self, m, fu_bitdict, rdpickers, regfile, regname, fspec):
+ comb, sync = m.d.comb, m.d.sync
+ fus = self.fus.fus
+ regs = self.regs
+
+ rpidx = regname
+
+ # select the required read port. these are pre-defined sizes
+ rfile = regs.rf[regfile.lower()]
+ rport = rfile.r_ports[rpidx]
+ print("read regfile", rpidx, regfile, regs.rf.keys(),
+ rfile, rfile.unary)
+
+ fspecs = fspec
+ if not isinstance(fspecs, list):
+ fspecs = [fspecs]
+
+ rdflags = []
+ pplen = 0
+ reads = []
+ ppoffs = []
+ for i, fspec in enumerate(fspecs):
+ # get the regfile specs for this regfile port
+ (rf, read, write, wid, fuspec) = fspec
+ print ("fpsec", i, fspec, len(fuspec))
+ ppoffs.append(pplen) # record offset for picker
+ pplen += len(fuspec)
+ name = "rdflag_%s_%s_%d" % (regfile, regname, i)
+ rdflag = Signal(name=name, reset_less=True)
+ comb += rdflag.eq(rf)
+ rdflags.append(rdflag)
+ reads.append(read)
+
+ print ("pplen", pplen)
+
+ # create a priority picker to manage this port
+ rdpickers[regfile][rpidx] = rdpick = PriorityPicker(pplen)
+ setattr(m.submodules, "rdpick_%s_%s" % (regfile, rpidx), rdpick)
+
+ rens = []
+ addrs = []
+ for i, fspec in enumerate(fspecs):
+ (rf, read, write, wid, fuspec) = fspec
+ # connect up the FU req/go signals, and the reg-read to the FU
+ # and create a Read Broadcast Bus
+ for pi, (funame, fu, idx) in enumerate(fuspec):
+ pi += ppoffs[i]
+
+ # connect request-read to picker input, and output to go-rd
+ fu_active = fu_bitdict[funame]
+ name = "%s_%s_%s_%i" % (regfile, rpidx, funame, pi)
+ addr_en = Signal.like(reads[i], name="addr_en_"+name)
+ pick = Signal(name="pick_"+name) # picker input
+ rp = Signal(name="rp_"+name) # picker output
+ delay_pick = Signal(name="dp_"+name) # read-enable "underway"
+
+ # exclude any currently-enabled read-request (mask out active)
+ comb += pick.eq(fu.rd_rel_o[idx] & fu_active & rdflags[i] &
+ ~delay_pick)
+ comb += rdpick.i[pi].eq(pick)
+ comb += fu.go_rd_i[idx].eq(delay_pick) # pass in *delayed* pick
+
+ # if picked, select read-port "reg select" number to port
+ comb += rp.eq(rdpick.o[pi] & rdpick.en_o)
+ sync += delay_pick.eq(rp) # delayed "pick"
+ comb += addr_en.eq(Mux(rp, reads[i], 0))
+
+ # the read-enable happens combinatorially (see mux-bus below)
+ # but it results in the data coming out on a one-cycle delay.
+ if rfile.unary:
+ rens.append(addr_en)
+ else:
+ addrs.append(addr_en)
+ rens.append(rp)
+
+ # use the *delayed* pick signal to put requested data onto bus
+ with m.If(delay_pick):
+ # connect regfile port to input, creating fan-out Bus
+ src = fu.src_i[idx]
+ print("reg connect widths",
+ regfile, regname, pi, funame,
+ src.shape(), rport.data_o.shape())
+ # all FUs connect to same port
+ comb += src.eq(rport.data_o)
+
+ # or-reduce the muxed read signals
+ if rfile.unary:
+ # for unary-addressed
+ comb += rport.ren.eq(ortreereduce_sig(rens))
+ else:
+ # for binary-addressed
+ comb += rport.addr.eq(ortreereduce_sig(addrs))
+ comb += rport.ren.eq(Cat(*rens).bool())
+ print ("binary", regfile, rpidx, rport, rport.ren, rens, addrs)
+