+++ /dev/null
-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()
+++ /dev/null
-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<<dummy), n_fu)
- # inputs
- self.rd_pend_i = Signal(n_fu, reset_less=True) # read pend in (left)
- self.wr_pend_i = Signal(n_fu, reset_less=True) # write pend in (left)
- self.issue_i = Signal(n_fu, reset_less=True) # Issue in (top)
-
- # 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, 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, 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)
-
- self.go_die_i = Signal(n_fu, reset_less=True) # Go Die in (left)
-
- # outputs (latched rd/wr wait)
- self.rd_wait_o = Signal(n_fu, reset_less=True) # read wait out (right)
- self.wr_wait_o = Signal(n_fu, reset_less=True) # write wait out (right)
-
- def elaborate(self, platform):
- m = Module()
-
- # set up rd/wr latches
- rd_c = []
- for i in range(self.n_src):
- rd_l = SRLatch(sync=False, name="rd%d_c" % i, llen=self.n_fu)
- setattr(m.submodules, "src%d_c" % (i+1), rd_l)
- rd_c.append(rd_l)
- wr_c = []
- for i in range(self.n_dest):
- wr_l = SRLatch(sync=False, name="wr%d_c" % i, llen=self.n_fu)
- setattr(m.submodules, "dst%d_c" % (i+1), wr_l)
- wr_c.append(wr_l)
-
- # reset on go HI, set on dest and issue
-
- # connect go_wr / pend
- for i in range(self.n_dest):
- m.d.comb += wr_c[i].r.eq(self.go_wr_i[i] | self.go_die_i)
- m.d.comb += wr_c[i].s.eq(self.issue_i & self.wr_pend_i & self.dummy)
-
- # connect go_rd / pend_i
- for i in range(self.n_src):
- m.d.comb += rd_c[i].r.eq(self.go_rd_i[i] | self.go_die_i)
- m.d.comb += rd_c[i].s.eq(self.issue_i & self.rd_pend_i & self.dummy)
-
- # connect output with OR-reduce (DO NOT USE bool()!)
- # read-wait (and write-wait) only go off when all GORD (and GOWR) fire
- rd_q = []
- for i in range(self.n_src):
- rd_q.append(rd_c[i].qlq)
- m.d.comb += self.rd_wait_o.eq(reduce(or_, rd_q) & ~self.issue_i)
- wr_q = []
- for i in range(self.n_dest):
- wr_q.append(wr_c[i].qlq)
- m.d.comb += self.wr_wait_o.eq(reduce(or_, wr_q) & ~self.issue_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.go_die_i
- yield self.rd_wait_o
- yield self.wr_wait_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 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 = FUDependenceCell(dummy=4, n_fu=4, n_src=2, n_dest=2)
- vl = rtlil.convert(dut, ports=dut.ports())
- with open("test_fu_dcell.il", "w") as f:
- f.write(vl)
-
- run_simulation(dut, dcell_sim(dut), vcd_name='test_fu_dcell.vcd')
-
-if __name__ == '__main__':
- test_dcell()
+++ /dev/null
-from nmigen.compat.sim import run_simulation
-from nmigen.cli import verilog, rtlil
-from nmigen import Module, Signal, Elaboratable, Array, Cat, Const
-
-from soc.scoreboard.fu_dep_cell_multi import FUDependenceCell
-from soc.scoreboard.fu_picker_vec import FU_Pick_Vec
-
-"""
-
- 6600 Function Unit Dependency Table Matrix inputs / outputs
- -----------------------------------------------------------
-
-"""
-
-class FUFUDepMatrix(Elaboratable):
- """ implements 11.4.7 mitch alsup FU-to-Reg Dependency Matrix, p26
- """
- def __init__(self, n_fu_row, n_fu_col, n_src, n_dest):
- self.n_fu_row = n_fu_row # Y (FU row#) ^v
- self.n_fu_col = n_fu_col # X (FU col #) <>
- 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()
+++ /dev/null
-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()
+++ /dev/null
-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
-
+++ /dev/null
-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()
+++ /dev/null
-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
-
--- /dev/null
+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()
--- /dev/null
+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<<dummy), n_fu)
+ # inputs
+ self.rd_pend_i = Signal(n_fu, reset_less=True) # read pend in (left)
+ self.wr_pend_i = Signal(n_fu, reset_less=True) # write pend in (left)
+ self.issue_i = Signal(n_fu, reset_less=True) # Issue in (top)
+
+ # 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, 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, 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)
+
+ self.go_die_i = Signal(n_fu, reset_less=True) # Go Die in (left)
+
+ # outputs (latched rd/wr wait)
+ self.rd_wait_o = Signal(n_fu, reset_less=True) # read wait out (right)
+ self.wr_wait_o = Signal(n_fu, reset_less=True) # write wait out (right)
+
+ def elaborate(self, platform):
+ m = Module()
+
+ # set up rd/wr latches
+ rd_c = []
+ for i in range(self.n_src):
+ rd_l = SRLatch(sync=False, name="rd%d_c" % i, llen=self.n_fu)
+ setattr(m.submodules, "src%d_c" % (i+1), rd_l)
+ rd_c.append(rd_l)
+ wr_c = []
+ for i in range(self.n_dest):
+ wr_l = SRLatch(sync=False, name="wr%d_c" % i, llen=self.n_fu)
+ setattr(m.submodules, "dst%d_c" % (i+1), wr_l)
+ wr_c.append(wr_l)
+
+ # reset on go HI, set on dest and issue
+
+ # connect go_wr / pend
+ for i in range(self.n_dest):
+ m.d.comb += wr_c[i].r.eq(self.go_wr_i[i] | self.go_die_i)
+ m.d.comb += wr_c[i].s.eq(self.issue_i & self.wr_pend_i & self.dummy)
+
+ # connect go_rd / pend_i
+ for i in range(self.n_src):
+ m.d.comb += rd_c[i].r.eq(self.go_rd_i[i] | self.go_die_i)
+ m.d.comb += rd_c[i].s.eq(self.issue_i & self.rd_pend_i & self.dummy)
+
+ # connect output with OR-reduce (DO NOT USE bool()!)
+ # read-wait (and write-wait) only go off when all GORD (and GOWR) fire
+ rd_q = []
+ for i in range(self.n_src):
+ rd_q.append(rd_c[i].qlq)
+ m.d.comb += self.rd_wait_o.eq(reduce(or_, rd_q) & ~self.issue_i)
+ wr_q = []
+ for i in range(self.n_dest):
+ wr_q.append(wr_c[i].qlq)
+ m.d.comb += self.wr_wait_o.eq(reduce(or_, wr_q) & ~self.issue_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.go_die_i
+ yield self.rd_wait_o
+ yield self.wr_wait_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 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 = FUDependenceCell(dummy=4, n_fu=4, n_src=2, n_dest=2)
+ vl = rtlil.convert(dut, ports=dut.ports())
+ with open("test_fu_dcell.il", "w") as f:
+ f.write(vl)
+
+ run_simulation(dut, dcell_sim(dut), vcd_name='test_fu_dcell.vcd')
+
+if __name__ == '__main__':
+ test_dcell()
--- /dev/null
+from nmigen.compat.sim import run_simulation
+from nmigen.cli import verilog, rtlil
+from nmigen import Module, Signal, Elaboratable, Array, Cat, Const
+
+from soc.scoremulti.fu_dep_cell_multi import FUDependenceCell
+from soc.scoreboard.fu_picker_vec import FU_Pick_Vec
+
+"""
+
+ 6600 Function Unit Dependency Table Matrix inputs / outputs
+ -----------------------------------------------------------
+
+"""
+
+class FUFUDepMatrix(Elaboratable):
+ """ implements 11.4.7 mitch alsup FU-to-Reg Dependency Matrix, p26
+ """
+ def __init__(self, n_fu_row, n_fu_col, n_src, n_dest):
+ self.n_fu_row = n_fu_row # Y (FU row#) ^v
+ self.n_fu_col = n_fu_col # X (FU col #) <>
+ 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()
--- /dev/null
+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()
--- /dev/null
+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
+
--- /dev/null
+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()
--- /dev/null
+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
+