move scoreboard multi rd/wr to new folder
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 14 Apr 2020 18:31:57 +0000 (19:31 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 14 Apr 2020 18:31:57 +0000 (19:31 +0100)
14 files changed:
src/soc/scoreboard/dep_multi_cell.py [deleted file]
src/soc/scoreboard/fu_dep_cell_multi.py [deleted file]
src/soc/scoreboard/fu_fu_matrix_multi.py [deleted file]
src/soc/scoreboard/fu_reg_matrix_multi.py [deleted file]
src/soc/scoreboard/fu_wr_pend_multi.py [deleted file]
src/soc/scoreboard/memfu_multi.py [deleted file]
src/soc/scoreboard/reg_sel_multi.py [deleted file]
src/soc/scoremulti/dep_multi_cell.py [new file with mode: 0644]
src/soc/scoremulti/fu_dep_cell_multi.py [new file with mode: 0644]
src/soc/scoremulti/fu_fu_matrix_multi.py [new file with mode: 0644]
src/soc/scoremulti/fu_reg_matrix_multi.py [new file with mode: 0644]
src/soc/scoremulti/fu_wr_pend_multi.py [new file with mode: 0644]
src/soc/scoremulti/memfu_multi.py [new file with mode: 0644]
src/soc/scoremulti/reg_sel_multi.py [new file with mode: 0644]

diff --git a/src/soc/scoreboard/dep_multi_cell.py b/src/soc/scoreboard/dep_multi_cell.py
deleted file mode 100644 (file)
index 04002c3..0000000
+++ /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 (file)
index 4643f3c..0000000
+++ /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<<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()
diff --git a/src/soc/scoreboard/fu_fu_matrix_multi.py b/src/soc/scoreboard/fu_fu_matrix_multi.py
deleted file mode 100644 (file)
index 4309858..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-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()
diff --git a/src/soc/scoreboard/fu_reg_matrix_multi.py b/src/soc/scoreboard/fu_reg_matrix_multi.py
deleted file mode 100644 (file)
index 699e561..0000000
+++ /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 (file)
index d1ce2d0..0000000
+++ /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 (file)
index e40be35..0000000
+++ /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 (file)
index 9d36f3b..0000000
+++ /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 (file)
index 0000000..04002c3
--- /dev/null
@@ -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 (file)
index 0000000..4643f3c
--- /dev/null
@@ -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<<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()
diff --git a/src/soc/scoremulti/fu_fu_matrix_multi.py b/src/soc/scoremulti/fu_fu_matrix_multi.py
new file mode 100644 (file)
index 0000000..6fe2048
--- /dev/null
@@ -0,0 +1,168 @@
+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()
diff --git a/src/soc/scoremulti/fu_reg_matrix_multi.py b/src/soc/scoremulti/fu_reg_matrix_multi.py
new file mode 100644 (file)
index 0000000..04b547b
--- /dev/null
@@ -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 (file)
index 0000000..d1ce2d0
--- /dev/null
@@ -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 (file)
index 0000000..0c3bc04
--- /dev/null
@@ -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 (file)
index 0000000..9d36f3b
--- /dev/null
@@ -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
+