From: Luke Kenneth Casson Leighton Date: Tue, 14 Apr 2020 18:31:57 +0000 (+0100) Subject: move scoreboard multi rd/wr to new folder X-Git-Tag: div_pipeline~1435^2~8 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=592556d3ef4bf283122f2ff799ff0eaba50b247f;p=soc.git move scoreboard multi rd/wr to new folder --- diff --git a/src/soc/scoreboard/dep_multi_cell.py b/src/soc/scoreboard/dep_multi_cell.py deleted file mode 100644 index 04002c33..00000000 --- a/src/soc/scoreboard/dep_multi_cell.py +++ /dev/null @@ -1,206 +0,0 @@ -from nmigen.compat.sim import run_simulation -from nmigen.cli import verilog, rtlil -from nmigen import Module, Signal, Elaboratable, Array, Cat, Repl -from nmutil.latch import SRLatch -from functools import reduce -from operator import or_ - - -class DependencyRow(Elaboratable): - """ implements 11.4.7 mitch alsup dependence cell, p27 - adjusted to be clock-sync'd on rising edge only. - mitch design (as does 6600) requires alternating rising/falling clock - - * SET mode: issue_i HI, go_i LO, reg_i HI - register is captured - - FWD is DISABLED (~issue_i) - - RSEL DISABLED - * QRY mode: issue_i LO, go_i LO, haz_i HI - FWD is ASSERTED - reg_i HI - ignored - * GO mode : issue_i LO, go_i HI - RSEL is ASSERTED - haz_i HI - FWD still can be ASSERTED - - FWD assertion (hazard protection) therefore still occurs in both - Query and Go Modes, for this cycle, due to the cq register - - GO mode works for one cycle, again due to the cq register capturing - the latch output. Without the cq register, the SR Latch (which is - asynchronous) would be reset at the exact moment that GO was requested, - and the RSEL would be garbage. - - cancel_mode: individual bit-array of cancels rather than a global one - """ - def __init__(self, n_reg, n_src, n_dest, cancel_mode=False): - self.cancel_mode = cancel_mode - self.n_reg = n_reg - self.n_src = n_src - self.n_dest = n_dest - # src arrays - src = [] - rsel = [] - fwd = [] - rd = [] - for i in range(n_src): - j = i + 1 # name numbering to match src1/src2 - src.append(Signal(n_reg, name="src%d" % j, reset_less=True)) - rsel.append(Signal(n_reg, name="src%d_rsel_o" % j, reset_less=True)) - fwd.append(Signal(n_reg, name="src%d_fwd_o" % j, reset_less=True)) - rd.append(Signal(n_reg, name="go_rd%d_i" % j, reset_less=True)) - - # dest arrays - dest = [] - dsel = [] - dfwd = [] - wr = [] - for i in range(n_dest): - j = i + 1 # name numbering to match src1/src2 - dest.append(Signal(n_reg, name="dst%d" % j, reset_less=True)) - dsel.append(Signal(n_reg, name="dst%d_rsel_o" % j, reset_less=True)) - dfwd.append(Signal(n_reg, name="dst%d_fwd_o" % j, reset_less=True)) - wr.append(Signal(n_reg, name="go_wr%d_i" % j, reset_less=True)) - - # inputs - self.dest_i = Array(dest) # Dest in (top) - self.src_i = Array(src) # operands in (top) - self.issue_i = Signal(reset_less=True) # Issue in (top) - - self.rd_pend_i = Signal(n_reg, reset_less=True) # Read pend in (top) - self.wr_pend_i = Signal(n_reg, reset_less=True) # Write pend in (top) - self.v_rd_rsel_o = Signal(n_reg, reset_less=True) # Read pend out (bot) - self.v_wr_rsel_o = Signal(n_reg, reset_less=True) # Write pend out (bot) - - self.go_wr_i = Array(wr) # Go Write in (left) - self.go_rd_i = Array(rd) # Go Read in (left) - if self.cancel_mode: - self.go_die_i = Signal(n_reg, reset_less=True) # Go Die in (left) - else: - self.go_die_i = Signal(reset_less=True) # Go Die in (left) - - # for Register File Select Lines (vertical) - self.dest_rsel_o = Array(dsel) # dest reg sel (bot) - self.src_rsel_o = Array(rsel) # src reg sel (bot) - - # for Function Unit "forward progress" (horizontal) - self.dest_fwd_o = Array(dfwd) # dest FU fw (right) - self.src_fwd_o = Array(fwd) # src FU fw (right) - - def elaborate(self, platform): - m = Module() - - # set up dest latches - dest_c = [] - for i in range(self.n_dest): - dst_l = SRLatch(sync=False, llen=self.n_reg, name="dst%d" % i) - setattr(m.submodules, "dst%d_c" % (i+1), dst_l) - dest_c.append(dst_l) - - # set up src latches - src_c = [] - for i in range(self.n_src): - src_l = SRLatch(sync=False, llen=self.n_reg, name="src%d" % i) - setattr(m.submodules, "src%d_c" % (i+1), src_l) - src_c.append(src_l) - - # connect go_rd / go_wr (dest->wr, src->rd) - if self.cancel_mode: - go_die = self.go_die_i - else: - go_die = Repl(self.go_die_i, self.n_reg) - wr_die = [] - for i in range(self.n_dest): - wrd = Signal(self.n_reg, reset_less=True, name="wdi%d" % i) - wr_die.append(wrd) - m.d.comb += wrd.eq(Repl(self.go_wr_i[i], self.n_reg) | go_die) - rd_die = [] - for i in range(self.n_src): - rdd = Signal(self.n_reg, reset_less=True, name="rdi%d" % i) - rd_die.append(rdd) - m.d.comb += rdd.eq(Repl(self.go_rd_i[i], self.n_reg) | go_die) - for i in range(self.n_src): - m.d.comb += src_c[i].r.eq(rd_die[i]) - for i in range(self.n_dest): - m.d.comb += dest_c[i].r.eq(wr_die[i]) - - # connect input reg bit (unary) - i_ext = Repl(self.issue_i, self.n_reg) - for i in range(self.n_dest): - m.d.comb += dest_c[i].s.eq(i_ext & self.dest_i[i]) - for i in range(self.n_src): - m.d.comb += src_c[i].s.eq(i_ext & self.src_i[i]) - - # connect up hazard checks: read-after-write and write-after-read - for i in range(self.n_dest): - m.d.comb += self.dest_fwd_o[i].eq(dest_c[i].q & self.rd_pend_i) - for i in range(self.n_src): - m.d.comb += self.src_fwd_o[i].eq(src_c[i].q & self.wr_pend_i) - - # connect reg-sel outputs - for i in range(self.n_dest): - wr_ext = Repl(self.go_wr_i[i], self.n_reg) - m.d.comb += self.dest_rsel_o[i].eq(dest_c[i].qlq & wr_ext) - for i in range(self.n_src): - rd_ext = Repl(self.go_rd_i[i], self.n_reg) - m.d.comb += self.src_rsel_o[i].eq(src_c[i].qlq & rd_ext) - - # to be accumulated to indicate if register is in use (globally) - # after ORing, is fed back in to rd_pend_i / wr_pend_i - src_q = [] - for i in range(self.n_src): - src_q.append(src_c[i].qlq) - m.d.comb += self.v_rd_rsel_o.eq(reduce(or_, src_q)) # do not use bool() - dst_q = [] - for i in range(self.n_dest): - dst_q.append(dest_c[i].qlq) - m.d.comb += self.v_wr_rsel_o.eq(reduce(or_, dst_q)) # do not use bool() - - return m - - def __iter__(self): - yield from self.dest_i - yield from self.src_i - yield self.rd_pend_i - yield self.wr_pend_i - yield self.issue_i - yield from self.go_wr_i - yield from self.go_rd_i - yield self.go_die_i - yield from self.dest_rsel_o - yield from self.src_rsel_o - yield from self.dest_fwd_o - yield from self.src_fwd_o - - def ports(self): - return list(self) - - -def dcell_sim(dut): - yield dut.dest_i.eq(1) - yield dut.issue_i.eq(1) - yield - yield dut.issue_i.eq(0) - yield - yield dut.src1_i.eq(1) - yield dut.issue_i.eq(1) - yield - yield - yield - yield dut.issue_i.eq(0) - yield - yield dut.go_rd_i.eq(1) - yield - yield dut.go_rd_i.eq(0) - yield - yield dut.go_wr_i.eq(1) - yield - yield dut.go_wr_i.eq(0) - yield - -def test_dcell(): - dut = DependencyRow(4, 3, 2, True) - vl = rtlil.convert(dut, ports=dut.ports()) - with open("test_drow.il", "w") as f: - f.write(vl) - - run_simulation(dut, dcell_sim(dut), vcd_name='test_dcell.vcd') - -if __name__ == '__main__': - test_dcell() diff --git a/src/soc/scoreboard/fu_dep_cell_multi.py b/src/soc/scoreboard/fu_dep_cell_multi.py deleted file mode 100644 index 4643f3c2..00000000 --- a/src/soc/scoreboard/fu_dep_cell_multi.py +++ /dev/null @@ -1,125 +0,0 @@ -from nmigen.compat.sim import run_simulation -from nmigen.cli import verilog, rtlil -from nmigen import Module, Signal, Const, Elaboratable, Array -from nmutil.latch import SRLatch - -from functools import reduce -from operator import or_ - - -class FUDependenceCell(Elaboratable): - """ implements 11.4.7 mitch alsup dependence cell, p27 - """ - def __init__(self, dummy, n_fu, n_src, n_dest): - self.n_fu = n_fu - self.n_src = n_src - self.n_dest = n_dest - self.dummy = Const(~(1< - self.n_src = n_src - self.n_dest = n_dest - self.rd_pend_i = Signal(n_fu_row, reset_less=True) # Rd pending (left) - self.wr_pend_i = Signal(n_fu_row, reset_less=True) # Wr pending (left) - self.issue_i = Signal(n_fu_col, reset_less=True) # Issue in (top) - - self.go_die_i = Signal(n_fu_row, reset_less=True) # Go Die in (left) - # set up go_wr and go_wr array - rd = [] - for i in range(n_src): - j = i + 1 # name numbering to match src1/src2 - rd.append(Signal(n_fu_row, name="gord%d_i" % j, reset_less=True)) - wr = [] - for i in range(n_src): - j = i + 1 # name numbering to match src1/src2 - wr.append(Signal(n_fu_row, name="gowr%d_i" % j, reset_less=True)) - - self.go_wr_i = Array(wr) # Go Write in (left) - self.go_rd_i = Array(rd) # Go Read in (left) - - # for Function Unit Readable/Writable (horizontal) - self.readable_o = Signal(n_fu_col, reset_less=True) # readable (bot) - self.writable_o = Signal(n_fu_col, reset_less=True) # writable (bot) - - def elaborate(self, platform): - m = Module() - - # --- - # matrix of dependency cells - # --- - dm = Array(FUDependenceCell(f, self.n_fu_col, self.n_src, self.n_dest) \ - for f in range(self.n_fu_row)) - for y in range(self.n_fu_row): - setattr(m.submodules, "dm%d" % y, dm[y]) - - # --- - # array of Function Unit Readable/Writable: row-length, horizontal - # --- - fur = Array(FU_Pick_Vec(self.n_fu_row) for r in range(self.n_fu_col)) - for x in range(self.n_fu_col): - setattr(m.submodules, "fur_x%d" % (x), fur[x]) - - # --- - # connect FU Readable/Writable vector - # --- - readable = [] - writable = [] - for y in range(self.n_fu_row): - fu = fur[y] - # accumulate Readable/Writable Vector outputs - readable.append(fu.readable_o) - writable.append(fu.writable_o) - - # ... and output them from this module (horizontal, width=REGs) - m.d.comb += self.readable_o.eq(Cat(*readable)) - m.d.comb += self.writable_o.eq(Cat(*writable)) - - # --- - # connect FU Pending - # --- - for y in range(self.n_fu_row): - dc = dm[y] - fu = fur[y] - # connect cell reg-select outputs to Reg Vector In - m.d.comb += [fu.rd_pend_i.eq(dc.rd_wait_o), - fu.wr_pend_i.eq(dc.wr_wait_o), - ] - - # --- - # connect Dependency Matrix dest/src1/src2/issue to module d/s/s/i - # --- - for x in range(self.n_fu_col): - issue_i = [] - for y in range(self.n_fu_row): - dc = dm[y] - # accumulate cell inputs issue - issue_i.append(dc.issue_i[x]) - # wire up inputs from module to row cell inputs - m.d.comb += Cat(*issue_i).eq(self.issue_i) - - # --- - # connect Matrix go_rd_i/go_wr_i to module readable/writable - # --- - for y in range(self.n_fu_row): - dc = dm[y] - # wire up inputs from module to row cell inputs - m.d.comb += dc.go_die_i.eq(self.go_die_i) - for i in range(self.n_src): - m.d.comb += dc.go_rd_i[i].eq(self.go_rd_i[i]) - for i in range(self.n_dest): - m.d.comb += dc.go_wr_i[i].eq(self.go_wr_i[i]) - - # --- - # connect Matrix pending - # --- - for y in range(self.n_fu_row): - dc = dm[y] - # wire up inputs from module to row cell inputs - m.d.comb += [dc.rd_pend_i.eq(self.rd_pend_i), - dc.wr_pend_i.eq(self.wr_pend_i), - ] - - return m - - def __iter__(self): - yield self.rd_pend_i - yield self.wr_pend_i - yield self.issue_i - yield from self.go_wr_i - yield from self.go_rd_i - yield self.readable_o - yield self.writable_o - - def ports(self): - return list(self) - -def d_matrix_sim(dut): - """ XXX TODO - """ - yield dut.dest_i.eq(1) - yield dut.issue_i.eq(1) - yield - yield dut.issue_i.eq(0) - yield - yield dut.src1_i.eq(1) - yield dut.issue_i.eq(1) - yield - yield dut.issue_i.eq(0) - yield - yield dut.go_rd_i.eq(1) - yield - yield dut.go_rd_i.eq(0) - yield - yield dut.go_wr_i.eq(1) - yield - yield dut.go_wr_i.eq(0) - yield - -def test_fu_fu_matrix(): - dut = FUFUDepMatrix(n_fu_row=3, n_fu_col=4, n_src=3, n_dest=2) - vl = rtlil.convert(dut, ports=dut.ports()) - with open("test_fu_fu_matrix.il", "w") as f: - f.write(vl) - - run_simulation(dut, d_matrix_sim(dut), vcd_name='test_fu_fu_matrix.vcd') - -if __name__ == '__main__': - test_fu_fu_matrix() diff --git a/src/soc/scoreboard/fu_reg_matrix_multi.py b/src/soc/scoreboard/fu_reg_matrix_multi.py deleted file mode 100644 index 699e5617..00000000 --- a/src/soc/scoreboard/fu_reg_matrix_multi.py +++ /dev/null @@ -1,345 +0,0 @@ -from nmigen.compat.sim import run_simulation -from nmigen.cli import verilog, rtlil -from nmigen import Module, Signal, Elaboratable, Array, Cat, Repl - -from soc.scoreboard.dep_multi_cell import DependencyRow -from soc.scoreboard.fu_wr_pend_multi import FU_RW_Pend -from soc.scoreboard.reg_sel_multi import Reg_Rsv -from soc.scoreboard.global_pending import GlobalPending - -""" - - 6600 Dependency Table Matrix inputs / outputs - --------------------------------------------- - - d s1 s2 i d s1 s2 i d s1 s2 i d s1 s2 i - | | | | | | | | | | | | | | | | - v v v v v v v v v v v v v v v v - go_rd/go_wr -> dm-r0-fu0 dm-r1-fu0 dm-r2-fu0 dm-r3-fu0 -> wr/rd-pend - go_rd/go_wr -> dm-r0-fu1 dm-r1-fu1 dm-r2-fu1 dm-r3-fu1 -> wr/rd-pend - go_rd/go_wr -> dm-r0-fu2 dm-r1-fu2 dm-r2-fu2 dm-r3-fu2 -> wr/rd-pend - | | | | | | | | | | | | - v v v v v v v v v v v v - d s1 s2 d s1 s2 d s1 s2 d s1 s2 - reg sel reg sel reg sel reg sel - -""" - -class FURegDepMatrix(Elaboratable): - """ implements 11.4.7 mitch alsup FU-to-Reg Dependency Matrix, p26 - """ - def __init__(self, n_fu_row, n_reg_col, n_src, n_dest, cancel=None): - self.n_src = n_src - self.n_dest = n_dest - self.n_fu_row = nf = n_fu_row # Y (FUs) ^v - self.n_reg_col = n_reg = n_reg_col # X (Regs) <> - - # arrays - src = [] - rsel = [] - rd = [] - for i in range(n_src): - j = i + 1 # name numbering to match src1/src2 - src.append(Signal(n_reg, name="src%d" % j, reset_less=True)) - rsel.append(Signal(n_reg, name="src%d_rsel_o" % j, reset_less=True)) - rd.append(Signal(nf, name="gord%d_i" % j, reset_less=True)) - dst = [] - dsel = [] - wr = [] - for i in range(n_src): - j = i + 1 # name numbering to match src1/src2 - dst.append(Signal(n_reg, name="dst%d" % j, reset_less=True)) - dsel.append(Signal(n_reg, name="dst%d_rsel_o" % j, reset_less=True)) - wr.append(Signal(nf, name="gowr%d_i" % j, reset_less=True)) - wpnd = [] - pend = [] - for i in range(nf): - j = i + 1 # name numbering to match src1/src2 - pend.append(Signal(nf, name="rd_src%d_pend_o" % j, reset_less=True)) - wpnd.append(Signal(nf, name="wr_dst%d_pend_o" % j, reset_less=True)) - - self.dest_i = Array(dst) # Dest in (top) - self.src_i = Array(src) # oper in (top) - - # cancellation array (from Address Matching), ties in with go_die_i - self.cancel = cancel - - # Register "Global" vectors for determining RaW and WaR hazards - self.wr_pend_i = Signal(n_reg_col, reset_less=True) # wr pending (top) - self.rd_pend_i = Signal(n_reg_col, reset_less=True) # rd pending (top) - self.v_wr_rsel_o = Signal(n_reg_col, reset_less=True) # wr pending (bot) - self.v_rd_rsel_o = Signal(n_reg_col, reset_less=True) # rd pending (bot) - - self.issue_i = Signal(n_fu_row, reset_less=True) # Issue in (top) - self.go_wr_i = Array(wr) # Go Write in (left) - self.go_rd_i = Array(rd) # Go Read in (left) - self.go_die_i = Signal(n_fu_row, reset_less=True) # Go Die in (left) - - # for Register File Select Lines (horizontal), per-reg - self.dest_rsel_o = Array(dsel) # dest reg (bot) - self.src_rsel_o = Array(rsel) # src reg (bot) - - # for Function Unit "forward progress" (vertical), per-FU - self.wr_pend_o = Signal(n_fu_row, reset_less=True) # wr pending (right) - self.wr_dst_pend_o = Array(wpnd) # dest pending - self.rd_pend_o = Signal(n_fu_row, reset_less=True) # rd pending (right) - self.rd_src_pend_o = Array(pend) # src1 pending - - def elaborate(self, platform): - m = Module() - return self._elaborate(m, platform) - - def _elaborate(self, m, platform): - - # --- - # matrix of dependency cells - # --- - cancel_mode = self.cancel is not None - dm = Array(DependencyRow(self.n_reg_col, self.n_src, - self.n_dest, cancel_mode) \ - for r in range(self.n_fu_row)) - for fu in range(self.n_fu_row): - setattr(m.submodules, "dr_fu%d" % fu, dm[fu]) - - # --- - # array of Function Unit Pending vectors - # --- - fupend = Array(FU_RW_Pend(self.n_reg_col, self.n_src, self.n_dest) \ - for f in range(self.n_fu_row)) - for fu in range(self.n_fu_row): - setattr(m.submodules, "fu_fu%d" % (fu), fupend[fu]) - - # --- - # array of Register Reservation vectors - # --- - regrsv = Array(Reg_Rsv(self.n_fu_row, self.n_src, self.n_dest) \ - for r in range(self.n_reg_col)) - for rn in range(self.n_reg_col): - setattr(m.submodules, "rr_r%d" % (rn), regrsv[rn]) - - # --- - # connect Function Unit vector - # --- - wr_pend = [] - rd_pend = [] - for fu in range(self.n_fu_row): - fup = fupend[fu] - # accumulate FU Vector outputs - wr_pend.append(fup.reg_wr_pend_o) - rd_pend.append(fup.reg_rd_pend_o) - - # ... and output them from this module (vertical, width=FUs) - m.d.comb += self.wr_pend_o.eq(Cat(*wr_pend)) - m.d.comb += self.rd_pend_o.eq(Cat(*rd_pend)) - - # same for dest - for i in range(self.n_dest): - wr_dst_pend = [] - for fu in range(self.n_fu_row): - dc = dm[fu] - fup = fupend[fu] - dst_fwd_o = [] - for rn in range(self.n_reg_col): - # accumulate cell fwd outputs for dest/src1/src2 - dst_fwd_o.append(dc.dest_fwd_o[i][rn]) - # connect cell fwd outputs to FU Vector in [Cat is gooood] - m.d.comb += [fup.dest_fwd_i[i].eq(Cat(*dst_fwd_o)), - ] - # accumulate FU Vector outputs - wr_dst_pend.append(fup.reg_wr_dst_pend_o[i]) - # ... and output them from this module (vertical, width=FUs) - m.d.comb += self.wr_dst_pend_o[i].eq(Cat(*wr_dst_pend)) - - # same for src - for i in range(self.n_src): - rd_src_pend = [] - for fu in range(self.n_fu_row): - dc = dm[fu] - fup = fupend[fu] - src_fwd_o = [] - for rn in range(self.n_reg_col): - # accumulate cell fwd outputs for dest/src1/src2 - src_fwd_o.append(dc.src_fwd_o[i][rn]) - # connect cell fwd outputs to FU Vector in [Cat is gooood] - m.d.comb += [fup.src_fwd_i[i].eq(Cat(*src_fwd_o)), - ] - # accumulate FU Vector outputs - rd_src_pend.append(fup.reg_rd_src_pend_o[i]) - # ... and output them from this module (vertical, width=FUs) - m.d.comb += self.rd_src_pend_o[i].eq(Cat(*rd_src_pend)) - - # --- - # connect Reg Selection vector - # --- - for i in range(self.n_dest): - dest_rsel = [] - for rn in range(self.n_reg_col): - rsv = regrsv[rn] - dest_rsel_o = [] - for fu in range(self.n_fu_row): - dc = dm[fu] - # accumulate cell reg-select outputs dest/src1/src2 - dest_rsel_o.append(dc.dest_rsel_o[i][rn]) - # connect cell reg-select outputs to Reg Vector In - m.d.comb += rsv.dest_rsel_i[i].eq(Cat(*dest_rsel_o)), - - # accumulate Reg-Sel Vector outputs - dest_rsel.append(rsv.dest_rsel_o[i]) - - # ... and output them from this module (horizontal, width=REGs) - m.d.comb += self.dest_rsel_o[i].eq(Cat(*dest_rsel)) - - # same for src - for i in range(self.n_src): - src_rsel = [] - for rn in range(self.n_reg_col): - rsv = regrsv[rn] - src_rsel_o = [] - for fu in range(self.n_fu_row): - dc = dm[fu] - # accumulate cell reg-select outputs dest/src1/src2 - src_rsel_o.append(dc.src_rsel_o[i][rn]) - # connect cell reg-select outputs to Reg Vector In - m.d.comb += rsv.src_rsel_i[i].eq(Cat(*src_rsel_o)), - # accumulate Reg-Sel Vector outputs - src_rsel.append(rsv.src_rsel_o[i]) - - # ... and output them from this module (horizontal, width=REGs) - m.d.comb += self.src_rsel_o[i].eq(Cat(*src_rsel)) - - # --- - # connect Dependency Matrix dest/src1/src2/issue to module d/s/s/i - # --- - for fu in range(self.n_fu_row): - dc = dm[fu] - # wire up inputs from module to row cell inputs (Cat is gooood) - m.d.comb += [dc.rd_pend_i.eq(self.rd_pend_i), - dc.wr_pend_i.eq(self.wr_pend_i), - ] - # same for dest - for fu in range(self.n_fu_row): - dc = dm[fu] - # wire up inputs from module to row cell inputs (Cat is gooood) - m.d.comb += dc.dest_i[i].eq(self.dest_i[i]) - - # same for src - for i in range(self.n_src): - for fu in range(self.n_fu_row): - dc = dm[fu] - # wire up inputs from module to row cell inputs (Cat is gooood) - m.d.comb += dc.src_i[i].eq(self.src_i[i]) - - # accumulate rsel bits into read/write pending vectors. - rd_pend_v = [] - wr_pend_v = [] - for fu in range(self.n_fu_row): - dc = dm[fu] - rd_pend_v.append(dc.v_rd_rsel_o) - wr_pend_v.append(dc.v_wr_rsel_o) - rd_v = GlobalPending(self.n_reg_col, rd_pend_v) - wr_v = GlobalPending(self.n_reg_col, wr_pend_v) - m.submodules.rd_v = rd_v - m.submodules.wr_v = wr_v - - m.d.comb += self.v_rd_rsel_o.eq(rd_v.g_pend_o) - m.d.comb += self.v_wr_rsel_o.eq(wr_v.g_pend_o) - - # --- - # connect Dep issue_i/go_rd_i/go_wr_i to module issue_i/go_rd/go_wr - # --- - issue_i = [] - for fu in range(self.n_fu_row): - dc = dm[fu] - issue_i.append(dc.issue_i) - # wire up inputs from module to row cell inputs (Cat is gooood) - m.d.comb += Cat(*issue_i).eq(self.issue_i) - - for i in range(self.n_src): - go_rd_i = [] - for fu in range(self.n_fu_row): - dc = dm[fu] - # accumulate cell fwd outputs for dest/src1/src2 - go_rd_i.append(dc.go_rd_i[i]) - # wire up inputs from module to row cell inputs (Cat is gooood) - m.d.comb += Cat(*go_rd_i).eq(self.go_rd_i[i]) - - for i in range(self.n_dest): - go_wr_i = [] - for fu in range(self.n_fu_row): - dc = dm[fu] - # accumulate cell fwd outputs for dest/src1/src2 - go_wr_i.append(dc.go_wr_i[i]) - # wire up inputs from module to row cell inputs (Cat is gooood) - m.d.comb += Cat(*go_wr_i).eq(self.go_wr_i[i]) - - # --- - # connect Dep go_die_i - # --- - if cancel_mode: - for fu in range(self.n_fu_row): - dc = dm[fu] - go_die = Repl(self.go_die_i[fu], self.n_fu_row) - go_die = go_die | self.cancel[fu] - m.d.comb += dc.go_die_i.eq(go_die) - else: - go_die_i = [] - for fu in range(self.n_fu_row): - dc = dm[fu] - # accumulate cell fwd outputs for dest/src1/src2 - go_die_i.append(dc.go_die_i) - # wire up inputs from module to row cell inputs (Cat is gooood) - m.d.comb += Cat(*go_die_i).eq(self.go_die_i) - return m - - def __iter__(self): - yield from self.dest_i - yield from self.src_i - yield self.issue_i - yield from self.go_wr_i - yield from self.go_rd_i - yield self.go_die_i - yield from self.dest_rsel_o - yield from self.src_rsel_o - yield self.wr_pend_o - yield self.rd_pend_o - yield self.wr_pend_i - yield self.rd_pend_i - yield self.v_wr_rsel_o - yield self.v_rd_rsel_o - yield from self.rd_src_pend_o - - def ports(self): - return list(self) - -def d_matrix_sim(dut): - """ XXX TODO - """ - yield dut.dest_i.eq(1) - yield dut.issue_i.eq(1) - yield - yield dut.issue_i.eq(0) - yield - yield dut.src1_i.eq(1) - yield dut.issue_i.eq(1) - yield - yield dut.issue_i.eq(0) - yield - yield dut.go_rd_i.eq(1) - yield - yield dut.go_rd_i.eq(0) - yield - yield dut.go_wr_i.eq(1) - yield - yield dut.go_wr_i.eq(0) - yield - -def test_d_matrix(): - dut = FURegDepMatrix(n_fu_row=3, n_reg_col=4, n_src=2, n_dest=2) - vl = rtlil.convert(dut, ports=dut.ports()) - with open("test_fu_reg_matrix.il", "w") as f: - f.write(vl) - - run_simulation(dut, d_matrix_sim(dut), vcd_name='test_fu_reg_matrix.vcd') - -if __name__ == '__main__': - test_d_matrix() diff --git a/src/soc/scoreboard/fu_wr_pend_multi.py b/src/soc/scoreboard/fu_wr_pend_multi.py deleted file mode 100644 index d1ce2d06..00000000 --- a/src/soc/scoreboard/fu_wr_pend_multi.py +++ /dev/null @@ -1,43 +0,0 @@ -from nmigen import Elaboratable, Module, Signal, Array - - -class FU_RW_Pend(Elaboratable): - """ these are allocated per-FU (horizontally), - and are of length reg_count - """ - def __init__(self, reg_count, n_src, n_dest): - self.n_src = n_src - self.n_dest = n_dest - self.reg_count = reg_count - self.dest_fwd_i = Signal(reg_count, reset_less=True) - dst = [] - for i in range(n_src): - j = i + 1 # name numbering to match dest1/dest2 - dst.append(Signal(reg_count, name="dst%d" % j, reset_less=True)) - self.dest_fwd_i = Array(dst) - src = [] - for i in range(n_src): - j = i + 1 # name numbering to match src1/src2 - src.append(Signal(reg_count, name="src%d" % j, reset_less=True)) - self.src_fwd_i = Array(src) - - self.reg_wr_pend_o = Signal(reset_less=True) - self.reg_rd_pend_o = Signal(reset_less=True) - self.reg_rd_src_pend_o = Signal(n_src, reset_less=True) - self.reg_wr_dst_pend_o = Signal(n_dest, reset_less=True) - - def elaborate(self, platform): - m = Module() - - # OR forwarding input together to create per-src pending - for i in range(self.n_src): - m.d.comb += self.reg_rd_src_pend_o[i].eq(self.src_fwd_i[i].bool()) - # then OR all src pending together - m.d.comb += self.reg_rd_pend_o.eq(self.reg_rd_src_pend_o.bool()) - - # likewise for per-dest then all-dest - for i in range(self.n_dest): - m.d.comb += self.reg_wr_dst_pend_o[i].eq(self.dest_fwd_i[i].bool()) - m.d.comb += self.reg_wr_pend_o.eq(self.reg_wr_dst_pend_o.bool()) - return m - diff --git a/src/soc/scoreboard/memfu_multi.py b/src/soc/scoreboard/memfu_multi.py deleted file mode 100644 index e40be352..00000000 --- a/src/soc/scoreboard/memfu_multi.py +++ /dev/null @@ -1,131 +0,0 @@ -from nmigen.compat.sim import run_simulation -from nmigen.cli import verilog, rtlil -from nmigen import Module, Signal, Array, Elaboratable - -from soc.scoreboard.fu_fu_matrix_multi import FUFUDepMatrix -from soc.scoreboard.mdm import FUMemMatchMatrix - - -class MemFunctionUnits(Elaboratable): - - def __init__(self, n_ldsts, addrbitwid): - self.n_ldsts = n_ldsts - self.bitwid = addrbitwid - - self.st_i = Signal(n_ldsts, reset_less=True) # Dest R# in - self.ld_i = Signal(n_ldsts, reset_less=True) # oper1 R# in - - self.g_int_ld_pend_o = Signal(n_ldsts, reset_less=True) - self.g_int_st_pend_o = Signal(n_ldsts, reset_less=True) - - self.st_rsel_o = Signal(n_ldsts, reset_less=True) # dest reg (bot) - self.ld_rsel_o = Signal(n_ldsts, reset_less=True) # src1 reg (bot) - - self.loadable_o = Signal(n_ldsts, reset_less=True) - self.storable_o = Signal(n_ldsts, reset_less=True) - self.addr_nomatch_o = Signal(n_ldsts, reset_less=True) - - self.go_ld_i = Signal(n_ldsts, reset_less=True) - self.go_st_i = Signal(n_ldsts, reset_less=True) - self.go_die_i = Signal(n_ldsts, reset_less=True) - self.fn_issue_i = Signal(n_ldsts, reset_less=True) - - # address matching - self.addrs_i = Array(Signal(self.bitwid, name="addrs_i%d" % i) \ - for i in range(n_ldsts)) - #self.addr_we_i = Signal(n_ldsts) # write-enable for incoming address - self.addr_en_i = Signal(n_ldsts) # address latched in - self.addr_rs_i = Signal(n_ldsts) # address deactivated - - # Note: FURegs st_pend_o is also outputted from here, for use in WaWGrid - - def elaborate(self, platform): - m = Module() - comb = m.d.comb - sync = m.d.sync - - n_fus = self.n_ldsts - - # Integer FU-FU Dep Matrix - intfudeps = FUFUDepMatrix(n_fus, n_fus, 1, 1) - m.submodules.intfudeps = intfudeps - # Integer FU-Reg Dep Matrix - intregdeps = FUMemMatchMatrix(n_fus, self.bitwid) - m.submodules.intregdeps = intregdeps - - # ok, because we do not know in advance what the AGEN (address gen) - # is, we have to make a transitive dependency set. i.e. the LD - # (or ST) being requested now must depend on ALL prior LDs *AND* STs. - # these get dropped very rapidly once AGEN is carried out. - # XXX TODO - - # connect fureg matrix as a mem system - comb += self.g_int_ld_pend_o.eq(intregdeps.v_rd_rsel_o) - comb += self.g_int_st_pend_o.eq(intregdeps.v_wr_rsel_o) - - comb += intregdeps.rd_pend_i.eq(intregdeps.v_rd_rsel_o) - comb += intregdeps.wr_pend_i.eq(intregdeps.v_wr_rsel_o) - - comb += intfudeps.rd_pend_i.eq(intregdeps.rd_pend_o) - comb += intfudeps.wr_pend_i.eq(intregdeps.wr_pend_o) - self.st_pend_o = intregdeps.wr_pend_o # also output for use in WaWGrid - - comb += intfudeps.issue_i.eq(self.fn_issue_i) - comb += intfudeps.go_rd_i[0].eq(self.go_ld_i) - comb += intfudeps.go_wr_i[0].eq(self.go_st_i) - comb += intfudeps.go_die_i.eq(self.go_die_i) - comb += self.loadable_o.eq(intfudeps.readable_o) - comb += self.storable_o.eq(intfudeps.writable_o) - comb += self.addr_nomatch_o.eq(intregdeps.addr_nomatch_o) - - # Connect function issue / arrays, and dest/src1/src2 - comb += intregdeps.dest_i.eq(self.st_i) - comb += intregdeps.src_i[0].eq(self.ld_i) - - comb += intregdeps.go_rd_i.eq(self.go_ld_i) - comb += intregdeps.go_wr_i.eq(self.go_st_i) - comb += intregdeps.go_die_i.eq(self.go_die_i) - comb += intregdeps.issue_i.eq(self.fn_issue_i) - - comb += self.st_rsel_o.eq(intregdeps.dest_rsel_o) - comb += self.ld_rsel_o.eq(intregdeps.src_rsel_o[0]) - - # connect address matching: these get connected to the Addr CUs - for i in range(self.n_ldsts): - comb += intregdeps.addrs_i[i].eq(self.addrs_i[i]) - #comb += intregdeps.addr_we_i.eq(self.addr_we_i) - comb += intregdeps.addr_en_i.eq(self.addr_en_i) - comb += intregdeps.addr_rs_i.eq(self.addr_rs_i) - - return m - - def __iter__(self): - yield self.ld_i - yield self.st_i - yield self.g_int_st_pend_o - yield self.g_int_ld_pend_o - yield self.ld_rsel_o - yield self.st_rsel_o - yield self.loadable_o - yield self.storable_o - yield self.go_st_i - yield self.go_ld_i - yield self.go_die_i - yield self.fn_issue_i - yield from self.addrs_i - #yield self.addr_we_i - yield self.addr_en_i - - def ports(self): - return list(self) - -def test_fumem(): - dut = MemFunctionUnits(n_ldsts=4, addrbitwid=5) - vl = rtlil.convert(dut, ports=dut.ports()) - with open("test_memfu_matrix.il", "w") as f: - f.write(vl) - - #run_simulation(dut, dcell_sim(dut), vcd_name='test_fu_dcell.vcd') - -if __name__ == '__main__': - test_fumem() diff --git a/src/soc/scoreboard/reg_sel_multi.py b/src/soc/scoreboard/reg_sel_multi.py deleted file mode 100644 index 9d36f3be..00000000 --- a/src/soc/scoreboard/reg_sel_multi.py +++ /dev/null @@ -1,29 +0,0 @@ -from nmigen import Elaboratable, Module, Signal, Array - - -class Reg_Rsv(Elaboratable): - """ these are allocated per-Register (vertically), - and are each of length fu_count - """ - def __init__(self, fu_count, n_src, n_dest): - self.n_src = n_src - self.n_dest = n_dest - self.fu_count = fu_count - self.dest_rsel_i = Signal(fu_count, reset_less=True) - self.dest_rsel_i = Array(Signal(fu_count, name="dst_rsel_i", - reset_less=True) \ - for i in range(n_dest)) - self.src_rsel_i = Array(Signal(fu_count, name="src_rsel_i", - reset_less=True) \ - for i in range(n_src)) - self.dest_rsel_o = Signal(n_dest, reset_less=True) - self.src_rsel_o = Signal(n_src, reset_less=True) - - def elaborate(self, platform): - m = Module() - for i in range(self.n_dest): - m.d.comb += self.dest_rsel_o[i].eq(self.dest_rsel_i[i].bool()) - for i in range(self.n_src): - m.d.comb += self.src_rsel_o[i].eq(self.src_rsel_i[i].bool()) - return m - diff --git a/src/soc/scoremulti/dep_multi_cell.py b/src/soc/scoremulti/dep_multi_cell.py new file mode 100644 index 00000000..04002c33 --- /dev/null +++ b/src/soc/scoremulti/dep_multi_cell.py @@ -0,0 +1,206 @@ +from nmigen.compat.sim import run_simulation +from nmigen.cli import verilog, rtlil +from nmigen import Module, Signal, Elaboratable, Array, Cat, Repl +from nmutil.latch import SRLatch +from functools import reduce +from operator import or_ + + +class DependencyRow(Elaboratable): + """ implements 11.4.7 mitch alsup dependence cell, p27 + adjusted to be clock-sync'd on rising edge only. + mitch design (as does 6600) requires alternating rising/falling clock + + * SET mode: issue_i HI, go_i LO, reg_i HI - register is captured + - FWD is DISABLED (~issue_i) + - RSEL DISABLED + * QRY mode: issue_i LO, go_i LO, haz_i HI - FWD is ASSERTED + reg_i HI - ignored + * GO mode : issue_i LO, go_i HI - RSEL is ASSERTED + haz_i HI - FWD still can be ASSERTED + + FWD assertion (hazard protection) therefore still occurs in both + Query and Go Modes, for this cycle, due to the cq register + + GO mode works for one cycle, again due to the cq register capturing + the latch output. Without the cq register, the SR Latch (which is + asynchronous) would be reset at the exact moment that GO was requested, + and the RSEL would be garbage. + + cancel_mode: individual bit-array of cancels rather than a global one + """ + def __init__(self, n_reg, n_src, n_dest, cancel_mode=False): + self.cancel_mode = cancel_mode + self.n_reg = n_reg + self.n_src = n_src + self.n_dest = n_dest + # src arrays + src = [] + rsel = [] + fwd = [] + rd = [] + for i in range(n_src): + j = i + 1 # name numbering to match src1/src2 + src.append(Signal(n_reg, name="src%d" % j, reset_less=True)) + rsel.append(Signal(n_reg, name="src%d_rsel_o" % j, reset_less=True)) + fwd.append(Signal(n_reg, name="src%d_fwd_o" % j, reset_less=True)) + rd.append(Signal(n_reg, name="go_rd%d_i" % j, reset_less=True)) + + # dest arrays + dest = [] + dsel = [] + dfwd = [] + wr = [] + for i in range(n_dest): + j = i + 1 # name numbering to match src1/src2 + dest.append(Signal(n_reg, name="dst%d" % j, reset_less=True)) + dsel.append(Signal(n_reg, name="dst%d_rsel_o" % j, reset_less=True)) + dfwd.append(Signal(n_reg, name="dst%d_fwd_o" % j, reset_less=True)) + wr.append(Signal(n_reg, name="go_wr%d_i" % j, reset_less=True)) + + # inputs + self.dest_i = Array(dest) # Dest in (top) + self.src_i = Array(src) # operands in (top) + self.issue_i = Signal(reset_less=True) # Issue in (top) + + self.rd_pend_i = Signal(n_reg, reset_less=True) # Read pend in (top) + self.wr_pend_i = Signal(n_reg, reset_less=True) # Write pend in (top) + self.v_rd_rsel_o = Signal(n_reg, reset_less=True) # Read pend out (bot) + self.v_wr_rsel_o = Signal(n_reg, reset_less=True) # Write pend out (bot) + + self.go_wr_i = Array(wr) # Go Write in (left) + self.go_rd_i = Array(rd) # Go Read in (left) + if self.cancel_mode: + self.go_die_i = Signal(n_reg, reset_less=True) # Go Die in (left) + else: + self.go_die_i = Signal(reset_less=True) # Go Die in (left) + + # for Register File Select Lines (vertical) + self.dest_rsel_o = Array(dsel) # dest reg sel (bot) + self.src_rsel_o = Array(rsel) # src reg sel (bot) + + # for Function Unit "forward progress" (horizontal) + self.dest_fwd_o = Array(dfwd) # dest FU fw (right) + self.src_fwd_o = Array(fwd) # src FU fw (right) + + def elaborate(self, platform): + m = Module() + + # set up dest latches + dest_c = [] + for i in range(self.n_dest): + dst_l = SRLatch(sync=False, llen=self.n_reg, name="dst%d" % i) + setattr(m.submodules, "dst%d_c" % (i+1), dst_l) + dest_c.append(dst_l) + + # set up src latches + src_c = [] + for i in range(self.n_src): + src_l = SRLatch(sync=False, llen=self.n_reg, name="src%d" % i) + setattr(m.submodules, "src%d_c" % (i+1), src_l) + src_c.append(src_l) + + # connect go_rd / go_wr (dest->wr, src->rd) + if self.cancel_mode: + go_die = self.go_die_i + else: + go_die = Repl(self.go_die_i, self.n_reg) + wr_die = [] + for i in range(self.n_dest): + wrd = Signal(self.n_reg, reset_less=True, name="wdi%d" % i) + wr_die.append(wrd) + m.d.comb += wrd.eq(Repl(self.go_wr_i[i], self.n_reg) | go_die) + rd_die = [] + for i in range(self.n_src): + rdd = Signal(self.n_reg, reset_less=True, name="rdi%d" % i) + rd_die.append(rdd) + m.d.comb += rdd.eq(Repl(self.go_rd_i[i], self.n_reg) | go_die) + for i in range(self.n_src): + m.d.comb += src_c[i].r.eq(rd_die[i]) + for i in range(self.n_dest): + m.d.comb += dest_c[i].r.eq(wr_die[i]) + + # connect input reg bit (unary) + i_ext = Repl(self.issue_i, self.n_reg) + for i in range(self.n_dest): + m.d.comb += dest_c[i].s.eq(i_ext & self.dest_i[i]) + for i in range(self.n_src): + m.d.comb += src_c[i].s.eq(i_ext & self.src_i[i]) + + # connect up hazard checks: read-after-write and write-after-read + for i in range(self.n_dest): + m.d.comb += self.dest_fwd_o[i].eq(dest_c[i].q & self.rd_pend_i) + for i in range(self.n_src): + m.d.comb += self.src_fwd_o[i].eq(src_c[i].q & self.wr_pend_i) + + # connect reg-sel outputs + for i in range(self.n_dest): + wr_ext = Repl(self.go_wr_i[i], self.n_reg) + m.d.comb += self.dest_rsel_o[i].eq(dest_c[i].qlq & wr_ext) + for i in range(self.n_src): + rd_ext = Repl(self.go_rd_i[i], self.n_reg) + m.d.comb += self.src_rsel_o[i].eq(src_c[i].qlq & rd_ext) + + # to be accumulated to indicate if register is in use (globally) + # after ORing, is fed back in to rd_pend_i / wr_pend_i + src_q = [] + for i in range(self.n_src): + src_q.append(src_c[i].qlq) + m.d.comb += self.v_rd_rsel_o.eq(reduce(or_, src_q)) # do not use bool() + dst_q = [] + for i in range(self.n_dest): + dst_q.append(dest_c[i].qlq) + m.d.comb += self.v_wr_rsel_o.eq(reduce(or_, dst_q)) # do not use bool() + + return m + + def __iter__(self): + yield from self.dest_i + yield from self.src_i + yield self.rd_pend_i + yield self.wr_pend_i + yield self.issue_i + yield from self.go_wr_i + yield from self.go_rd_i + yield self.go_die_i + yield from self.dest_rsel_o + yield from self.src_rsel_o + yield from self.dest_fwd_o + yield from self.src_fwd_o + + def ports(self): + return list(self) + + +def dcell_sim(dut): + yield dut.dest_i.eq(1) + yield dut.issue_i.eq(1) + yield + yield dut.issue_i.eq(0) + yield + yield dut.src1_i.eq(1) + yield dut.issue_i.eq(1) + yield + yield + yield + yield dut.issue_i.eq(0) + yield + yield dut.go_rd_i.eq(1) + yield + yield dut.go_rd_i.eq(0) + yield + yield dut.go_wr_i.eq(1) + yield + yield dut.go_wr_i.eq(0) + yield + +def test_dcell(): + dut = DependencyRow(4, 3, 2, True) + vl = rtlil.convert(dut, ports=dut.ports()) + with open("test_drow.il", "w") as f: + f.write(vl) + + run_simulation(dut, dcell_sim(dut), vcd_name='test_dcell.vcd') + +if __name__ == '__main__': + test_dcell() diff --git a/src/soc/scoremulti/fu_dep_cell_multi.py b/src/soc/scoremulti/fu_dep_cell_multi.py new file mode 100644 index 00000000..4643f3c2 --- /dev/null +++ b/src/soc/scoremulti/fu_dep_cell_multi.py @@ -0,0 +1,125 @@ +from nmigen.compat.sim import run_simulation +from nmigen.cli import verilog, rtlil +from nmigen import Module, Signal, Const, Elaboratable, Array +from nmutil.latch import SRLatch + +from functools import reduce +from operator import or_ + + +class FUDependenceCell(Elaboratable): + """ implements 11.4.7 mitch alsup dependence cell, p27 + """ + def __init__(self, dummy, n_fu, n_src, n_dest): + self.n_fu = n_fu + self.n_src = n_src + self.n_dest = n_dest + self.dummy = Const(~(1< + self.n_src = n_src + self.n_dest = n_dest + self.rd_pend_i = Signal(n_fu_row, reset_less=True) # Rd pending (left) + self.wr_pend_i = Signal(n_fu_row, reset_less=True) # Wr pending (left) + self.issue_i = Signal(n_fu_col, reset_less=True) # Issue in (top) + + self.go_die_i = Signal(n_fu_row, reset_less=True) # Go Die in (left) + # set up go_wr and go_wr array + rd = [] + for i in range(n_src): + j = i + 1 # name numbering to match src1/src2 + rd.append(Signal(n_fu_row, name="gord%d_i" % j, reset_less=True)) + wr = [] + for i in range(n_src): + j = i + 1 # name numbering to match src1/src2 + wr.append(Signal(n_fu_row, name="gowr%d_i" % j, reset_less=True)) + + self.go_wr_i = Array(wr) # Go Write in (left) + self.go_rd_i = Array(rd) # Go Read in (left) + + # for Function Unit Readable/Writable (horizontal) + self.readable_o = Signal(n_fu_col, reset_less=True) # readable (bot) + self.writable_o = Signal(n_fu_col, reset_less=True) # writable (bot) + + def elaborate(self, platform): + m = Module() + + # --- + # matrix of dependency cells + # --- + dm = Array(FUDependenceCell(f, self.n_fu_col, self.n_src, self.n_dest) \ + for f in range(self.n_fu_row)) + for y in range(self.n_fu_row): + setattr(m.submodules, "dm%d" % y, dm[y]) + + # --- + # array of Function Unit Readable/Writable: row-length, horizontal + # --- + fur = Array(FU_Pick_Vec(self.n_fu_row) for r in range(self.n_fu_col)) + for x in range(self.n_fu_col): + setattr(m.submodules, "fur_x%d" % (x), fur[x]) + + # --- + # connect FU Readable/Writable vector + # --- + readable = [] + writable = [] + for y in range(self.n_fu_row): + fu = fur[y] + # accumulate Readable/Writable Vector outputs + readable.append(fu.readable_o) + writable.append(fu.writable_o) + + # ... and output them from this module (horizontal, width=REGs) + m.d.comb += self.readable_o.eq(Cat(*readable)) + m.d.comb += self.writable_o.eq(Cat(*writable)) + + # --- + # connect FU Pending + # --- + for y in range(self.n_fu_row): + dc = dm[y] + fu = fur[y] + # connect cell reg-select outputs to Reg Vector In + m.d.comb += [fu.rd_pend_i.eq(dc.rd_wait_o), + fu.wr_pend_i.eq(dc.wr_wait_o), + ] + + # --- + # connect Dependency Matrix dest/src1/src2/issue to module d/s/s/i + # --- + for x in range(self.n_fu_col): + issue_i = [] + for y in range(self.n_fu_row): + dc = dm[y] + # accumulate cell inputs issue + issue_i.append(dc.issue_i[x]) + # wire up inputs from module to row cell inputs + m.d.comb += Cat(*issue_i).eq(self.issue_i) + + # --- + # connect Matrix go_rd_i/go_wr_i to module readable/writable + # --- + for y in range(self.n_fu_row): + dc = dm[y] + # wire up inputs from module to row cell inputs + m.d.comb += dc.go_die_i.eq(self.go_die_i) + for i in range(self.n_src): + m.d.comb += dc.go_rd_i[i].eq(self.go_rd_i[i]) + for i in range(self.n_dest): + m.d.comb += dc.go_wr_i[i].eq(self.go_wr_i[i]) + + # --- + # connect Matrix pending + # --- + for y in range(self.n_fu_row): + dc = dm[y] + # wire up inputs from module to row cell inputs + m.d.comb += [dc.rd_pend_i.eq(self.rd_pend_i), + dc.wr_pend_i.eq(self.wr_pend_i), + ] + + return m + + def __iter__(self): + yield self.rd_pend_i + yield self.wr_pend_i + yield self.issue_i + yield from self.go_wr_i + yield from self.go_rd_i + yield self.readable_o + yield self.writable_o + + def ports(self): + return list(self) + +def d_matrix_sim(dut): + """ XXX TODO + """ + yield dut.dest_i.eq(1) + yield dut.issue_i.eq(1) + yield + yield dut.issue_i.eq(0) + yield + yield dut.src1_i.eq(1) + yield dut.issue_i.eq(1) + yield + yield dut.issue_i.eq(0) + yield + yield dut.go_rd_i.eq(1) + yield + yield dut.go_rd_i.eq(0) + yield + yield dut.go_wr_i.eq(1) + yield + yield dut.go_wr_i.eq(0) + yield + +def test_fu_fu_matrix(): + dut = FUFUDepMatrix(n_fu_row=3, n_fu_col=4, n_src=3, n_dest=2) + vl = rtlil.convert(dut, ports=dut.ports()) + with open("test_fu_fu_matrix.il", "w") as f: + f.write(vl) + + run_simulation(dut, d_matrix_sim(dut), vcd_name='test_fu_fu_matrix.vcd') + +if __name__ == '__main__': + test_fu_fu_matrix() diff --git a/src/soc/scoremulti/fu_reg_matrix_multi.py b/src/soc/scoremulti/fu_reg_matrix_multi.py new file mode 100644 index 00000000..04b547bf --- /dev/null +++ b/src/soc/scoremulti/fu_reg_matrix_multi.py @@ -0,0 +1,345 @@ +from nmigen.compat.sim import run_simulation +from nmigen.cli import verilog, rtlil +from nmigen import Module, Signal, Elaboratable, Array, Cat, Repl + +from soc.scoremulti.dep_multi_cell import DependencyRow +from soc.scoremulti.fu_wr_pend_multi import FU_RW_Pend +from soc.scoremulti.reg_sel_multi import Reg_Rsv +from soc.scoreboard.global_pending import GlobalPending + +""" + + 6600 Dependency Table Matrix inputs / outputs + --------------------------------------------- + + d s1 s2 i d s1 s2 i d s1 s2 i d s1 s2 i + | | | | | | | | | | | | | | | | + v v v v v v v v v v v v v v v v + go_rd/go_wr -> dm-r0-fu0 dm-r1-fu0 dm-r2-fu0 dm-r3-fu0 -> wr/rd-pend + go_rd/go_wr -> dm-r0-fu1 dm-r1-fu1 dm-r2-fu1 dm-r3-fu1 -> wr/rd-pend + go_rd/go_wr -> dm-r0-fu2 dm-r1-fu2 dm-r2-fu2 dm-r3-fu2 -> wr/rd-pend + | | | | | | | | | | | | + v v v v v v v v v v v v + d s1 s2 d s1 s2 d s1 s2 d s1 s2 + reg sel reg sel reg sel reg sel + +""" + +class FURegDepMatrix(Elaboratable): + """ implements 11.4.7 mitch alsup FU-to-Reg Dependency Matrix, p26 + """ + def __init__(self, n_fu_row, n_reg_col, n_src, n_dest, cancel=None): + self.n_src = n_src + self.n_dest = n_dest + self.n_fu_row = nf = n_fu_row # Y (FUs) ^v + self.n_reg_col = n_reg = n_reg_col # X (Regs) <> + + # arrays + src = [] + rsel = [] + rd = [] + for i in range(n_src): + j = i + 1 # name numbering to match src1/src2 + src.append(Signal(n_reg, name="src%d" % j, reset_less=True)) + rsel.append(Signal(n_reg, name="src%d_rsel_o" % j, reset_less=True)) + rd.append(Signal(nf, name="gord%d_i" % j, reset_less=True)) + dst = [] + dsel = [] + wr = [] + for i in range(n_src): + j = i + 1 # name numbering to match src1/src2 + dst.append(Signal(n_reg, name="dst%d" % j, reset_less=True)) + dsel.append(Signal(n_reg, name="dst%d_rsel_o" % j, reset_less=True)) + wr.append(Signal(nf, name="gowr%d_i" % j, reset_less=True)) + wpnd = [] + pend = [] + for i in range(nf): + j = i + 1 # name numbering to match src1/src2 + pend.append(Signal(nf, name="rd_src%d_pend_o" % j, reset_less=True)) + wpnd.append(Signal(nf, name="wr_dst%d_pend_o" % j, reset_less=True)) + + self.dest_i = Array(dst) # Dest in (top) + self.src_i = Array(src) # oper in (top) + + # cancellation array (from Address Matching), ties in with go_die_i + self.cancel = cancel + + # Register "Global" vectors for determining RaW and WaR hazards + self.wr_pend_i = Signal(n_reg_col, reset_less=True) # wr pending (top) + self.rd_pend_i = Signal(n_reg_col, reset_less=True) # rd pending (top) + self.v_wr_rsel_o = Signal(n_reg_col, reset_less=True) # wr pending (bot) + self.v_rd_rsel_o = Signal(n_reg_col, reset_less=True) # rd pending (bot) + + self.issue_i = Signal(n_fu_row, reset_less=True) # Issue in (top) + self.go_wr_i = Array(wr) # Go Write in (left) + self.go_rd_i = Array(rd) # Go Read in (left) + self.go_die_i = Signal(n_fu_row, reset_less=True) # Go Die in (left) + + # for Register File Select Lines (horizontal), per-reg + self.dest_rsel_o = Array(dsel) # dest reg (bot) + self.src_rsel_o = Array(rsel) # src reg (bot) + + # for Function Unit "forward progress" (vertical), per-FU + self.wr_pend_o = Signal(n_fu_row, reset_less=True) # wr pending (right) + self.wr_dst_pend_o = Array(wpnd) # dest pending + self.rd_pend_o = Signal(n_fu_row, reset_less=True) # rd pending (right) + self.rd_src_pend_o = Array(pend) # src1 pending + + def elaborate(self, platform): + m = Module() + return self._elaborate(m, platform) + + def _elaborate(self, m, platform): + + # --- + # matrix of dependency cells + # --- + cancel_mode = self.cancel is not None + dm = Array(DependencyRow(self.n_reg_col, self.n_src, + self.n_dest, cancel_mode) \ + for r in range(self.n_fu_row)) + for fu in range(self.n_fu_row): + setattr(m.submodules, "dr_fu%d" % fu, dm[fu]) + + # --- + # array of Function Unit Pending vectors + # --- + fupend = Array(FU_RW_Pend(self.n_reg_col, self.n_src, self.n_dest) \ + for f in range(self.n_fu_row)) + for fu in range(self.n_fu_row): + setattr(m.submodules, "fu_fu%d" % (fu), fupend[fu]) + + # --- + # array of Register Reservation vectors + # --- + regrsv = Array(Reg_Rsv(self.n_fu_row, self.n_src, self.n_dest) \ + for r in range(self.n_reg_col)) + for rn in range(self.n_reg_col): + setattr(m.submodules, "rr_r%d" % (rn), regrsv[rn]) + + # --- + # connect Function Unit vector + # --- + wr_pend = [] + rd_pend = [] + for fu in range(self.n_fu_row): + fup = fupend[fu] + # accumulate FU Vector outputs + wr_pend.append(fup.reg_wr_pend_o) + rd_pend.append(fup.reg_rd_pend_o) + + # ... and output them from this module (vertical, width=FUs) + m.d.comb += self.wr_pend_o.eq(Cat(*wr_pend)) + m.d.comb += self.rd_pend_o.eq(Cat(*rd_pend)) + + # same for dest + for i in range(self.n_dest): + wr_dst_pend = [] + for fu in range(self.n_fu_row): + dc = dm[fu] + fup = fupend[fu] + dst_fwd_o = [] + for rn in range(self.n_reg_col): + # accumulate cell fwd outputs for dest/src1/src2 + dst_fwd_o.append(dc.dest_fwd_o[i][rn]) + # connect cell fwd outputs to FU Vector in [Cat is gooood] + m.d.comb += [fup.dest_fwd_i[i].eq(Cat(*dst_fwd_o)), + ] + # accumulate FU Vector outputs + wr_dst_pend.append(fup.reg_wr_dst_pend_o[i]) + # ... and output them from this module (vertical, width=FUs) + m.d.comb += self.wr_dst_pend_o[i].eq(Cat(*wr_dst_pend)) + + # same for src + for i in range(self.n_src): + rd_src_pend = [] + for fu in range(self.n_fu_row): + dc = dm[fu] + fup = fupend[fu] + src_fwd_o = [] + for rn in range(self.n_reg_col): + # accumulate cell fwd outputs for dest/src1/src2 + src_fwd_o.append(dc.src_fwd_o[i][rn]) + # connect cell fwd outputs to FU Vector in [Cat is gooood] + m.d.comb += [fup.src_fwd_i[i].eq(Cat(*src_fwd_o)), + ] + # accumulate FU Vector outputs + rd_src_pend.append(fup.reg_rd_src_pend_o[i]) + # ... and output them from this module (vertical, width=FUs) + m.d.comb += self.rd_src_pend_o[i].eq(Cat(*rd_src_pend)) + + # --- + # connect Reg Selection vector + # --- + for i in range(self.n_dest): + dest_rsel = [] + for rn in range(self.n_reg_col): + rsv = regrsv[rn] + dest_rsel_o = [] + for fu in range(self.n_fu_row): + dc = dm[fu] + # accumulate cell reg-select outputs dest/src1/src2 + dest_rsel_o.append(dc.dest_rsel_o[i][rn]) + # connect cell reg-select outputs to Reg Vector In + m.d.comb += rsv.dest_rsel_i[i].eq(Cat(*dest_rsel_o)), + + # accumulate Reg-Sel Vector outputs + dest_rsel.append(rsv.dest_rsel_o[i]) + + # ... and output them from this module (horizontal, width=REGs) + m.d.comb += self.dest_rsel_o[i].eq(Cat(*dest_rsel)) + + # same for src + for i in range(self.n_src): + src_rsel = [] + for rn in range(self.n_reg_col): + rsv = regrsv[rn] + src_rsel_o = [] + for fu in range(self.n_fu_row): + dc = dm[fu] + # accumulate cell reg-select outputs dest/src1/src2 + src_rsel_o.append(dc.src_rsel_o[i][rn]) + # connect cell reg-select outputs to Reg Vector In + m.d.comb += rsv.src_rsel_i[i].eq(Cat(*src_rsel_o)), + # accumulate Reg-Sel Vector outputs + src_rsel.append(rsv.src_rsel_o[i]) + + # ... and output them from this module (horizontal, width=REGs) + m.d.comb += self.src_rsel_o[i].eq(Cat(*src_rsel)) + + # --- + # connect Dependency Matrix dest/src1/src2/issue to module d/s/s/i + # --- + for fu in range(self.n_fu_row): + dc = dm[fu] + # wire up inputs from module to row cell inputs (Cat is gooood) + m.d.comb += [dc.rd_pend_i.eq(self.rd_pend_i), + dc.wr_pend_i.eq(self.wr_pend_i), + ] + # same for dest + for fu in range(self.n_fu_row): + dc = dm[fu] + # wire up inputs from module to row cell inputs (Cat is gooood) + m.d.comb += dc.dest_i[i].eq(self.dest_i[i]) + + # same for src + for i in range(self.n_src): + for fu in range(self.n_fu_row): + dc = dm[fu] + # wire up inputs from module to row cell inputs (Cat is gooood) + m.d.comb += dc.src_i[i].eq(self.src_i[i]) + + # accumulate rsel bits into read/write pending vectors. + rd_pend_v = [] + wr_pend_v = [] + for fu in range(self.n_fu_row): + dc = dm[fu] + rd_pend_v.append(dc.v_rd_rsel_o) + wr_pend_v.append(dc.v_wr_rsel_o) + rd_v = GlobalPending(self.n_reg_col, rd_pend_v) + wr_v = GlobalPending(self.n_reg_col, wr_pend_v) + m.submodules.rd_v = rd_v + m.submodules.wr_v = wr_v + + m.d.comb += self.v_rd_rsel_o.eq(rd_v.g_pend_o) + m.d.comb += self.v_wr_rsel_o.eq(wr_v.g_pend_o) + + # --- + # connect Dep issue_i/go_rd_i/go_wr_i to module issue_i/go_rd/go_wr + # --- + issue_i = [] + for fu in range(self.n_fu_row): + dc = dm[fu] + issue_i.append(dc.issue_i) + # wire up inputs from module to row cell inputs (Cat is gooood) + m.d.comb += Cat(*issue_i).eq(self.issue_i) + + for i in range(self.n_src): + go_rd_i = [] + for fu in range(self.n_fu_row): + dc = dm[fu] + # accumulate cell fwd outputs for dest/src1/src2 + go_rd_i.append(dc.go_rd_i[i]) + # wire up inputs from module to row cell inputs (Cat is gooood) + m.d.comb += Cat(*go_rd_i).eq(self.go_rd_i[i]) + + for i in range(self.n_dest): + go_wr_i = [] + for fu in range(self.n_fu_row): + dc = dm[fu] + # accumulate cell fwd outputs for dest/src1/src2 + go_wr_i.append(dc.go_wr_i[i]) + # wire up inputs from module to row cell inputs (Cat is gooood) + m.d.comb += Cat(*go_wr_i).eq(self.go_wr_i[i]) + + # --- + # connect Dep go_die_i + # --- + if cancel_mode: + for fu in range(self.n_fu_row): + dc = dm[fu] + go_die = Repl(self.go_die_i[fu], self.n_fu_row) + go_die = go_die | self.cancel[fu] + m.d.comb += dc.go_die_i.eq(go_die) + else: + go_die_i = [] + for fu in range(self.n_fu_row): + dc = dm[fu] + # accumulate cell fwd outputs for dest/src1/src2 + go_die_i.append(dc.go_die_i) + # wire up inputs from module to row cell inputs (Cat is gooood) + m.d.comb += Cat(*go_die_i).eq(self.go_die_i) + return m + + def __iter__(self): + yield from self.dest_i + yield from self.src_i + yield self.issue_i + yield from self.go_wr_i + yield from self.go_rd_i + yield self.go_die_i + yield from self.dest_rsel_o + yield from self.src_rsel_o + yield self.wr_pend_o + yield self.rd_pend_o + yield self.wr_pend_i + yield self.rd_pend_i + yield self.v_wr_rsel_o + yield self.v_rd_rsel_o + yield from self.rd_src_pend_o + + def ports(self): + return list(self) + +def d_matrix_sim(dut): + """ XXX TODO + """ + yield dut.dest_i.eq(1) + yield dut.issue_i.eq(1) + yield + yield dut.issue_i.eq(0) + yield + yield dut.src1_i.eq(1) + yield dut.issue_i.eq(1) + yield + yield dut.issue_i.eq(0) + yield + yield dut.go_rd_i.eq(1) + yield + yield dut.go_rd_i.eq(0) + yield + yield dut.go_wr_i.eq(1) + yield + yield dut.go_wr_i.eq(0) + yield + +def test_d_matrix(): + dut = FURegDepMatrix(n_fu_row=3, n_reg_col=4, n_src=2, n_dest=2) + vl = rtlil.convert(dut, ports=dut.ports()) + with open("test_fu_reg_matrix.il", "w") as f: + f.write(vl) + + run_simulation(dut, d_matrix_sim(dut), vcd_name='test_fu_reg_matrix.vcd') + +if __name__ == '__main__': + test_d_matrix() diff --git a/src/soc/scoremulti/fu_wr_pend_multi.py b/src/soc/scoremulti/fu_wr_pend_multi.py new file mode 100644 index 00000000..d1ce2d06 --- /dev/null +++ b/src/soc/scoremulti/fu_wr_pend_multi.py @@ -0,0 +1,43 @@ +from nmigen import Elaboratable, Module, Signal, Array + + +class FU_RW_Pend(Elaboratable): + """ these are allocated per-FU (horizontally), + and are of length reg_count + """ + def __init__(self, reg_count, n_src, n_dest): + self.n_src = n_src + self.n_dest = n_dest + self.reg_count = reg_count + self.dest_fwd_i = Signal(reg_count, reset_less=True) + dst = [] + for i in range(n_src): + j = i + 1 # name numbering to match dest1/dest2 + dst.append(Signal(reg_count, name="dst%d" % j, reset_less=True)) + self.dest_fwd_i = Array(dst) + src = [] + for i in range(n_src): + j = i + 1 # name numbering to match src1/src2 + src.append(Signal(reg_count, name="src%d" % j, reset_less=True)) + self.src_fwd_i = Array(src) + + self.reg_wr_pend_o = Signal(reset_less=True) + self.reg_rd_pend_o = Signal(reset_less=True) + self.reg_rd_src_pend_o = Signal(n_src, reset_less=True) + self.reg_wr_dst_pend_o = Signal(n_dest, reset_less=True) + + def elaborate(self, platform): + m = Module() + + # OR forwarding input together to create per-src pending + for i in range(self.n_src): + m.d.comb += self.reg_rd_src_pend_o[i].eq(self.src_fwd_i[i].bool()) + # then OR all src pending together + m.d.comb += self.reg_rd_pend_o.eq(self.reg_rd_src_pend_o.bool()) + + # likewise for per-dest then all-dest + for i in range(self.n_dest): + m.d.comb += self.reg_wr_dst_pend_o[i].eq(self.dest_fwd_i[i].bool()) + m.d.comb += self.reg_wr_pend_o.eq(self.reg_wr_dst_pend_o.bool()) + return m + diff --git a/src/soc/scoremulti/memfu_multi.py b/src/soc/scoremulti/memfu_multi.py new file mode 100644 index 00000000..0c3bc049 --- /dev/null +++ b/src/soc/scoremulti/memfu_multi.py @@ -0,0 +1,131 @@ +from nmigen.compat.sim import run_simulation +from nmigen.cli import verilog, rtlil +from nmigen import Module, Signal, Array, Elaboratable + +from soc.scoremulti.fu_fu_matrix_multi import FUFUDepMatrix +from soc.scoreboard.mdm import FUMemMatchMatrix + + +class MemFunctionUnits(Elaboratable): + + def __init__(self, n_ldsts, addrbitwid): + self.n_ldsts = n_ldsts + self.bitwid = addrbitwid + + self.st_i = Signal(n_ldsts, reset_less=True) # Dest R# in + self.ld_i = Signal(n_ldsts, reset_less=True) # oper1 R# in + + self.g_int_ld_pend_o = Signal(n_ldsts, reset_less=True) + self.g_int_st_pend_o = Signal(n_ldsts, reset_less=True) + + self.st_rsel_o = Signal(n_ldsts, reset_less=True) # dest reg (bot) + self.ld_rsel_o = Signal(n_ldsts, reset_less=True) # src1 reg (bot) + + self.loadable_o = Signal(n_ldsts, reset_less=True) + self.storable_o = Signal(n_ldsts, reset_less=True) + self.addr_nomatch_o = Signal(n_ldsts, reset_less=True) + + self.go_ld_i = Signal(n_ldsts, reset_less=True) + self.go_st_i = Signal(n_ldsts, reset_less=True) + self.go_die_i = Signal(n_ldsts, reset_less=True) + self.fn_issue_i = Signal(n_ldsts, reset_less=True) + + # address matching + self.addrs_i = Array(Signal(self.bitwid, name="addrs_i%d" % i) \ + for i in range(n_ldsts)) + #self.addr_we_i = Signal(n_ldsts) # write-enable for incoming address + self.addr_en_i = Signal(n_ldsts) # address latched in + self.addr_rs_i = Signal(n_ldsts) # address deactivated + + # Note: FURegs st_pend_o is also outputted from here, for use in WaWGrid + + def elaborate(self, platform): + m = Module() + comb = m.d.comb + sync = m.d.sync + + n_fus = self.n_ldsts + + # Integer FU-FU Dep Matrix + intfudeps = FUFUDepMatrix(n_fus, n_fus, 1, 1) + m.submodules.intfudeps = intfudeps + # Integer FU-Reg Dep Matrix + intregdeps = FUMemMatchMatrix(n_fus, self.bitwid) + m.submodules.intregdeps = intregdeps + + # ok, because we do not know in advance what the AGEN (address gen) + # is, we have to make a transitive dependency set. i.e. the LD + # (or ST) being requested now must depend on ALL prior LDs *AND* STs. + # these get dropped very rapidly once AGEN is carried out. + # XXX TODO + + # connect fureg matrix as a mem system + comb += self.g_int_ld_pend_o.eq(intregdeps.v_rd_rsel_o) + comb += self.g_int_st_pend_o.eq(intregdeps.v_wr_rsel_o) + + comb += intregdeps.rd_pend_i.eq(intregdeps.v_rd_rsel_o) + comb += intregdeps.wr_pend_i.eq(intregdeps.v_wr_rsel_o) + + comb += intfudeps.rd_pend_i.eq(intregdeps.rd_pend_o) + comb += intfudeps.wr_pend_i.eq(intregdeps.wr_pend_o) + self.st_pend_o = intregdeps.wr_pend_o # also output for use in WaWGrid + + comb += intfudeps.issue_i.eq(self.fn_issue_i) + comb += intfudeps.go_rd_i[0].eq(self.go_ld_i) + comb += intfudeps.go_wr_i[0].eq(self.go_st_i) + comb += intfudeps.go_die_i.eq(self.go_die_i) + comb += self.loadable_o.eq(intfudeps.readable_o) + comb += self.storable_o.eq(intfudeps.writable_o) + comb += self.addr_nomatch_o.eq(intregdeps.addr_nomatch_o) + + # Connect function issue / arrays, and dest/src1/src2 + comb += intregdeps.dest_i.eq(self.st_i) + comb += intregdeps.src_i[0].eq(self.ld_i) + + comb += intregdeps.go_rd_i.eq(self.go_ld_i) + comb += intregdeps.go_wr_i.eq(self.go_st_i) + comb += intregdeps.go_die_i.eq(self.go_die_i) + comb += intregdeps.issue_i.eq(self.fn_issue_i) + + comb += self.st_rsel_o.eq(intregdeps.dest_rsel_o) + comb += self.ld_rsel_o.eq(intregdeps.src_rsel_o[0]) + + # connect address matching: these get connected to the Addr CUs + for i in range(self.n_ldsts): + comb += intregdeps.addrs_i[i].eq(self.addrs_i[i]) + #comb += intregdeps.addr_we_i.eq(self.addr_we_i) + comb += intregdeps.addr_en_i.eq(self.addr_en_i) + comb += intregdeps.addr_rs_i.eq(self.addr_rs_i) + + return m + + def __iter__(self): + yield self.ld_i + yield self.st_i + yield self.g_int_st_pend_o + yield self.g_int_ld_pend_o + yield self.ld_rsel_o + yield self.st_rsel_o + yield self.loadable_o + yield self.storable_o + yield self.go_st_i + yield self.go_ld_i + yield self.go_die_i + yield self.fn_issue_i + yield from self.addrs_i + #yield self.addr_we_i + yield self.addr_en_i + + def ports(self): + return list(self) + +def test_fumem(): + dut = MemFunctionUnits(n_ldsts=4, addrbitwid=5) + vl = rtlil.convert(dut, ports=dut.ports()) + with open("test_memfu_matrix.il", "w") as f: + f.write(vl) + + #run_simulation(dut, dcell_sim(dut), vcd_name='test_fu_dcell.vcd') + +if __name__ == '__main__': + test_fumem() diff --git a/src/soc/scoremulti/reg_sel_multi.py b/src/soc/scoremulti/reg_sel_multi.py new file mode 100644 index 00000000..9d36f3be --- /dev/null +++ b/src/soc/scoremulti/reg_sel_multi.py @@ -0,0 +1,29 @@ +from nmigen import Elaboratable, Module, Signal, Array + + +class Reg_Rsv(Elaboratable): + """ these are allocated per-Register (vertically), + and are each of length fu_count + """ + def __init__(self, fu_count, n_src, n_dest): + self.n_src = n_src + self.n_dest = n_dest + self.fu_count = fu_count + self.dest_rsel_i = Signal(fu_count, reset_less=True) + self.dest_rsel_i = Array(Signal(fu_count, name="dst_rsel_i", + reset_less=True) \ + for i in range(n_dest)) + self.src_rsel_i = Array(Signal(fu_count, name="src_rsel_i", + reset_less=True) \ + for i in range(n_src)) + self.dest_rsel_o = Signal(n_dest, reset_less=True) + self.src_rsel_o = Signal(n_src, reset_less=True) + + def elaborate(self, platform): + m = Module() + for i in range(self.n_dest): + m.d.comb += self.dest_rsel_o[i].eq(self.dest_rsel_i[i].bool()) + for i in range(self.n_src): + m.d.comb += self.src_rsel_o[i].eq(self.src_rsel_i[i].bool()) + return m +