add per-FU PowerDecoders. should now be subsettable
[soc.git] / src / soc / experiment / score6600_multi.py
index 4a932109fb87de332e3e7d2be19e5a2bf60e7426..22d8e2d1a76d93d8b33318db42b18c1e66bce0f2 100644 (file)
@@ -4,7 +4,7 @@ from nmigen.hdl.ast import unsigned
 from nmigen import Module, Const, Signal, Array, Cat, Elaboratable, Memory
 from nmigen.back.pysim import Delay
 
 from nmigen import Module, Const, Signal, Array, Cat, Elaboratable, Memory
 from nmigen.back.pysim import Delay
 
-from soc.regfile.regfile import RegFileArray, treereduce
+from soc.regfile.regfile import RegFileArray, ortreereduce
 from soc.scoremulti.fu_fu_matrix import FUFUDepMatrix
 from soc.scoremulti.fu_reg_matrix import FURegDepMatrix
 from soc.scoreboard.global_pending import GlobalPending
 from soc.scoremulti.fu_fu_matrix import FUFUDepMatrix
 from soc.scoremulti.fu_reg_matrix import FURegDepMatrix
 from soc.scoreboard.global_pending import GlobalPending
@@ -15,14 +15,19 @@ from soc.scoreboard.instruction_q import Instruction, InstructionQ
 from soc.scoreboard.memfu import MemFunctionUnits
 
 from soc.experiment.compalu import ComputationUnitNoDelay
 from soc.scoreboard.memfu import MemFunctionUnits
 
 from soc.experiment.compalu import ComputationUnitNoDelay
-from soc.experiment.compldst import LDSTCompUnit
-from soc.experiment.testmem import TestMemory
+from soc.experiment.compalu_multi import MultiCompUnit, go_record
+from soc.experiment.compldst_multi import LDSTCompUnit
+from soc.experiment.compldst_multi import CompLDSTOpSubset
+from soc.experiment.l0_cache import TstL0CacheBuffer
 
 
-from soc.experiment.alu_hier import ALU, BranchALU, CompALUOpSubset
+from soc.experiment.alu_hier import ALU, BranchALU
+from soc.fu.alu.alu_input_record import CompALUOpSubset
 
 
-from soc.decoder.power_enums import InternalOp, Function
+from soc.decoder.power_enums import MicrOp, Function
 from soc.decoder.power_decoder import (create_pdecode)
 from soc.decoder.power_decoder2 import (PowerDecode2)
 from soc.decoder.power_decoder import (create_pdecode)
 from soc.decoder.power_decoder2 import (PowerDecode2)
+from soc.decoder.power_decoder2 import Decode2ToExecute1Type
+
 from soc.simulator.program import Program
 
 
 from soc.simulator.program import Program
 
 
@@ -84,8 +89,11 @@ class CompUnitsBase(Elaboratable):
 
         # inputs
         self.issue_i = Signal(n_units, reset_less=True)
 
         # inputs
         self.issue_i = Signal(n_units, reset_less=True)
-        self.go_rd_i = Signal(n_units, reset_less=True)
-        self.go_wr_i = Signal(n_units, reset_less=True)
+        self.rd0 = go_record(n_units, "rd0")
+        self.rd1 = go_record(n_units, "rd1")
+        self.go_rd_i = [self.rd0.go, self.rd1.go]  # XXX HACK!
+        self.wr0 = go_record(n_units, "wr0")
+        self.go_wr_i = [self.wr0.go]
         self.shadown_i = Signal(n_units, reset_less=True)
         self.go_die_i = Signal(n_units, reset_less=True)
         if ldstmode:
         self.shadown_i = Signal(n_units, reset_less=True)
         self.go_die_i = Signal(n_units, reset_less=True)
         if ldstmode:
@@ -94,8 +102,8 @@ class CompUnitsBase(Elaboratable):
 
         # outputs
         self.busy_o = Signal(n_units, reset_less=True)
 
         # outputs
         self.busy_o = Signal(n_units, reset_less=True)
-        self.rd_rel_o = Signal(n_units, reset_less=True)
-        self.req_rel_o = Signal(n_units, reset_less=True)
+        self.rd_rel_o = [self.rd0.rel, self.rd1.rel]  # HACK!
+        self.req_rel_o = self.wr0.rel
         self.done_o = Signal(n_units, reset_less=True)
         if ldstmode:
             self.ld_o = Signal(n_units, reset_less=True)  # op is LD
         self.done_o = Signal(n_units, reset_less=True)
         if ldstmode:
             self.ld_o = Signal(n_units, reset_less=True)  # op is LD
@@ -119,43 +127,53 @@ class CompUnitsBase(Elaboratable):
         for i, alu in enumerate(self.units):
             setattr(m.submodules, "comp%d" % i, alu)
 
         for i, alu in enumerate(self.units):
             setattr(m.submodules, "comp%d" % i, alu)
 
-        go_rd_l = []
+        go_rd_l0 = []
+        go_rd_l1 = []
         go_wr_l = []
         issue_l = []
         busy_l = []
         req_rel_l = []
         done_l = []
         go_wr_l = []
         issue_l = []
         busy_l = []
         req_rel_l = []
         done_l = []
-        rd_rel_l = []
+        rd_rel0_l = []
+        rd_rel1_l = []
         shadow_l = []
         godie_l = []
         for alu in self.units:
             req_rel_l.append(alu.req_rel_o)
             done_l.append(alu.done_o)
         shadow_l = []
         godie_l = []
         for alu in self.units:
             req_rel_l.append(alu.req_rel_o)
             done_l.append(alu.done_o)
-            rd_rel_l.append(alu.rd_rel_o)
             shadow_l.append(alu.shadown_i)
             godie_l.append(alu.go_die_i)
             shadow_l.append(alu.shadown_i)
             godie_l.append(alu.go_die_i)
+            print(alu, "rel", alu.req_rel_o, alu.rd_rel_o)
+            rd_rel0_l.append(alu.rd_rel_o[0])
+            rd_rel1_l.append(alu.rd_rel_o[1])
             go_wr_l.append(alu.go_wr_i)
             go_wr_l.append(alu.go_wr_i)
-            go_rd_l.append(alu.go_rd_i)
+            go_rd_l0.append(alu.go_rd_i[0])
+            go_rd_l1.append(alu.go_rd_i[1])
             issue_l.append(alu.issue_i)
             busy_l.append(alu.busy_o)
             issue_l.append(alu.issue_i)
             busy_l.append(alu.busy_o)
-        comb += self.rd_rel_o.eq(Cat(*rd_rel_l))
+        comb += self.rd0.rel.eq(Cat(*rd_rel0_l))
+        comb += self.rd1.rel.eq(Cat(*rd_rel1_l))
         comb += self.req_rel_o.eq(Cat(*req_rel_l))
         comb += self.done_o.eq(Cat(*done_l))
         comb += self.busy_o.eq(Cat(*busy_l))
         comb += Cat(*godie_l).eq(self.go_die_i)
         comb += Cat(*shadow_l).eq(self.shadown_i)
         comb += self.req_rel_o.eq(Cat(*req_rel_l))
         comb += self.done_o.eq(Cat(*done_l))
         comb += self.busy_o.eq(Cat(*busy_l))
         comb += Cat(*godie_l).eq(self.go_die_i)
         comb += Cat(*shadow_l).eq(self.shadown_i)
-        comb += Cat(*go_wr_l).eq(self.go_wr_i)
-        comb += Cat(*go_rd_l).eq(self.go_rd_i)
+        comb += Cat(*go_wr_l).eq(self.wr0.go)  # XXX TODO
+        comb += Cat(*go_rd_l0).eq(self.rd0.go)
+        comb += Cat(*go_rd_l1).eq(self.rd1.go)
         comb += Cat(*issue_l).eq(self.issue_i)
 
         # connect data register input/output
 
         # merge (OR) all integer FU / ALU outputs to a single value
         comb += Cat(*issue_l).eq(self.issue_i)
 
         # connect data register input/output
 
         # merge (OR) all integer FU / ALU outputs to a single value
+        # XXX NOTE: this only works because there is a single "port"
+        # protected by a single go_wr.  multi-issue requires a bus
+        # to be inserted here.
         if self.units:
         if self.units:
-            data_o = treereduce(self.units, "data_o")
+            data_o = ortreereduce(self.units, "data_o")
             comb += self.data_o.eq(data_o)
             if self.ldstmode:
             comb += self.data_o.eq(data_o)
             if self.ldstmode:
-                addr_o = treereduce(self.units, "addr_o")
+                addr_o = ortreereduce(self.units, "addr_o")
                 comb += self.addr_o.eq(addr_o)
 
         for i, alu in enumerate(self.units):
                 comb += self.addr_o.eq(addr_o)
 
         for i, alu in enumerate(self.units):
@@ -196,7 +214,7 @@ class CompUnitsBase(Elaboratable):
 
 class CompUnitLDSTs(CompUnitsBase):
 
 
 class CompUnitLDSTs(CompUnitsBase):
 
-    def __init__(self, rwid, opwid, n_ldsts, mem):
+    def __init__(self, rwid, opwid, n_ldsts, l0):
         """ Inputs:
 
             * :rwid:   bit width of register file(s) - both FP and INT
         """ Inputs:
 
             * :rwid:   bit width of register file(s) - both FP and INT
@@ -205,18 +223,13 @@ class CompUnitLDSTs(CompUnitsBase):
         self.opwid = opwid
 
         # inputs
         self.opwid = opwid
 
         # inputs
-        self.oper_i = Signal(opwid, reset_less=True)
-        self.imm_i = Signal(rwid, reset_less=True)
-
-        # Int ALUs
-        self.alus = []
-        for i in range(n_ldsts):
-            self.alus.append(ALU(rwid))
+        self.op = CompLDSTOpSubset("cul_i")
 
 
+        # LD/ST Units
         units = []
         units = []
-        for alu in self.alus:
-            aluopwid = 4  # see compldst.py for "internal" opcode
-            units.append(LDSTCompUnit(rwid, aluopwid, alu, mem))
+        for i in range(n_ldsts):
+            pi = l0.l0.dports[i].pi
+            units.append(LDSTCompUnit(pi, rwid, awid=48))
 
         CompUnitsBase.__init__(self, rwid, units, ldstmode=True)
 
 
         CompUnitsBase.__init__(self, rwid, units, ldstmode=True)
 
@@ -224,11 +237,9 @@ class CompUnitLDSTs(CompUnitsBase):
         m = CompUnitsBase.elaborate(self, platform)
         comb = m.d.comb
 
         m = CompUnitsBase.elaborate(self, platform)
         comb = m.d.comb
 
-        # hand the same operation to all units, 4 lower bits though
-        for alu in self.units:
-            comb += alu.oper_i[0:4].eq(self.oper_i)
-            comb += alu.imm_i.eq(self.imm_i)
-            comb += alu.isalu_i.eq(0)
+        # hand the same operation to all units
+        for ldst in self.units:
+            comb += ldst.oper_i.eq(self.op)
 
         return m
 
 
         return m
 
@@ -245,8 +256,6 @@ class CompUnitALUs(CompUnitsBase):
 
         # inputs
         self.op = CompALUOpSubset("cua_i")
 
         # inputs
         self.op = CompALUOpSubset("cua_i")
-        self.oper_i = Signal(opwid, reset_less=True)
-        self.imm_i = Signal(rwid, reset_less=True)
 
         # Int ALUs
         alus = []
 
         # Int ALUs
         alus = []
@@ -256,7 +265,7 @@ class CompUnitALUs(CompUnitsBase):
         units = []
         for alu in alus:
             aluopwid = 3  # extra bit for immediate mode
         units = []
         for alu in alus:
             aluopwid = 3  # extra bit for immediate mode
-            units.append(ComputationUnitNoDelay(rwid, alu))
+            units.append(MultiCompUnit(rwid, alu, CompALUOpSubset))
 
         CompUnitsBase.__init__(self, rwid, units)
 
 
         CompUnitsBase.__init__(self, rwid, units)
 
@@ -267,8 +276,6 @@ class CompUnitALUs(CompUnitsBase):
         # hand the subset of operation to ALUs
         for alu in self.units:
             comb += alu.oper_i.eq(self.op)
         # hand the subset of operation to ALUs
         for alu in self.units:
             comb += alu.oper_i.eq(self.op)
-            #comb += alu.oper_i[0:3].eq(self.oper_i)
-            #comb += alu.imm_i.eq(self.imm_i)
 
         return m
 
 
         return m
 
@@ -287,13 +294,14 @@ class CompUnitBR(CompUnitsBase):
         self.opwid = opwid
 
         # inputs
         self.opwid = opwid
 
         # inputs
+        self.op = CompALUOpSubset("cua_i")  # TODO - CompALUBranchSubset
         self.oper_i = Signal(opwid, reset_less=True)
         self.imm_i = Signal(rwid, reset_less=True)
 
         # Branch ALU and CU
         self.bgt = BranchALU(rwid)
         aluopwid = 3  # extra bit for immediate mode
         self.oper_i = Signal(opwid, reset_less=True)
         self.imm_i = Signal(rwid, reset_less=True)
 
         # Branch ALU and CU
         self.bgt = BranchALU(rwid)
         aluopwid = 3  # extra bit for immediate mode
-        self.br1 = ComputationUnitNoDelay(rwid, self.bgt)
+        self.br1 = MultiCompUnit(rwid, self.bgt, CompALUOpSubset)
         CompUnitsBase.__init__(self, rwid, [self.br1])
 
     def elaborate(self, platform):
         CompUnitsBase.__init__(self, rwid, [self.br1])
 
     def elaborate(self, platform):
@@ -302,6 +310,7 @@ class CompUnitBR(CompUnitsBase):
 
         # hand the same operation to all units
         for alu in self.units:
 
         # hand the same operation to all units
         for alu in self.units:
+            # comb += alu.oper_i.eq(self.op) # TODO
             comb += alu.oper_i.eq(self.oper_i)
             #comb += alu.imm_i.eq(self.imm_i)
 
             comb += alu.oper_i.eq(self.oper_i)
             #comb += alu.imm_i.eq(self.imm_i)
 
@@ -310,26 +319,55 @@ class CompUnitBR(CompUnitsBase):
 
 class FunctionUnits(Elaboratable):
 
 
 class FunctionUnits(Elaboratable):
 
-    def __init__(self, n_regs, n_int_alus):
-        self.n_regs = n_regs
-        self.n_int_alus = n_int_alus
-
-        self.dest_i = Signal(n_regs, reset_less=True)  # Dest R# in
-        self.src1_i = Signal(n_regs, reset_less=True)  # oper1 R# in
-        self.src2_i = Signal(n_regs, reset_less=True)  # oper2 R# in
-
-        self.g_int_rd_pend_o = Signal(n_regs, reset_less=True)
-        self.g_int_wr_pend_o = Signal(n_regs, reset_less=True)
+    def __init__(self, n_reg, n_int_alus, n_src, n_dst):
+        self.n_src, self.n_dst = n_src, n_dst
+        self.n_reg = n_reg
+        self.n_int_alus = nf = n_int_alus
 
 
-        self.dest_rsel_o = Signal(n_regs, reset_less=True)  # dest reg (bot)
-        self.src1_rsel_o = Signal(n_regs, reset_less=True)  # src1 reg (bot)
-        self.src2_rsel_o = Signal(n_regs, reset_less=True)  # src2 reg (bot)
+        self.g_int_rd_pend_o = Signal(n_reg, reset_less=True)
+        self.g_int_wr_pend_o = Signal(n_reg, reset_less=True)
 
         self.readable_o = Signal(n_int_alus, reset_less=True)
         self.writable_o = Signal(n_int_alus, reset_less=True)
 
 
         self.readable_o = Signal(n_int_alus, reset_less=True)
         self.writable_o = Signal(n_int_alus, reset_less=True)
 
-        self.go_rd_i = Signal(n_int_alus, reset_less=True)
-        self.go_wr_i = Signal(n_int_alus, reset_less=True)
+        # 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_dst):
+            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)
+
+        # for Register File Select Lines (horizontal), per-reg
+        self.dst_rsel_o = Array(dsel)  # dest reg (bot)
+        self.src_rsel_o = Array(rsel)  # src reg (bot)
+
+        self.go_rd_i = Array(rd)
+        self.go_wr_i = Array(wr)
+
         self.go_die_i = Signal(n_int_alus, reset_less=True)
         self.fn_issue_i = Signal(n_int_alus, reset_less=True)
 
         self.go_die_i = Signal(n_int_alus, reset_less=True)
         self.fn_issue_i = Signal(n_int_alus, reset_less=True)
 
@@ -343,10 +381,10 @@ class FunctionUnits(Elaboratable):
         n_intfus = self.n_int_alus
 
         # Integer FU-FU Dep Matrix
         n_intfus = self.n_int_alus
 
         # Integer FU-FU Dep Matrix
-        intfudeps = FUFUDepMatrix(n_intfus, n_intfus, 1, 1)
+        intfudeps = FUFUDepMatrix(n_intfus, n_intfus, 2, 1)
         m.submodules.intfudeps = intfudeps
         # Integer FU-Reg Dep Matrix
         m.submodules.intfudeps = intfudeps
         # Integer FU-Reg Dep Matrix
-        intregdeps = FURegDepMatrix(n_intfus, self.n_regs, 2, 1)
+        intregdeps = FURegDepMatrix(n_intfus, self.n_reg, 2, 1)
         m.submodules.intregdeps = intregdeps
 
         comb += self.g_int_rd_pend_o.eq(intregdeps.v_rd_rsel_o)
         m.submodules.intregdeps = intregdeps
 
         comb += self.g_int_rd_pend_o.eq(intregdeps.v_rd_rsel_o)
@@ -360,27 +398,26 @@ class FunctionUnits(Elaboratable):
         self.wr_pend_o = intregdeps.wr_pend_o  # also output for use in WaWGrid
 
         comb += intfudeps.issue_i.eq(self.fn_issue_i)
         self.wr_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_rd_i)
-        comb += intfudeps.go_wr_i[0].eq(self.go_wr_i)
         comb += intfudeps.go_die_i.eq(self.go_die_i)
         comb += self.readable_o.eq(intfudeps.readable_o)
         comb += self.writable_o.eq(intfudeps.writable_o)
 
         # Connect function issue / arrays, and dest/src1/src2
         comb += intfudeps.go_die_i.eq(self.go_die_i)
         comb += self.readable_o.eq(intfudeps.readable_o)
         comb += self.writable_o.eq(intfudeps.writable_o)
 
         # Connect function issue / arrays, and dest/src1/src2
-        comb += intregdeps.dest_i[0].eq(self.dest_i)
-        comb += intregdeps.src_i[0].eq(self.src1_i)
-        comb += intregdeps.src_i[1].eq(self.src2_i)
-
-        comb += intregdeps.go_rd_i[0].eq(self.go_rd_i)
-        comb += intregdeps.go_rd_i[1].eq(self.go_rd_i)
-        comb += intregdeps.go_wr_i[0].eq(self.go_wr_i)
+        for i in range(self.n_src):
+            print(i, self.go_rd_i, intfudeps.go_rd_i)
+            comb += intfudeps.go_rd_i[i].eq(self.go_rd_i[i])
+            comb += intregdeps.src_i[i].eq(self.src_i[i])
+            comb += intregdeps.go_rd_i[i].eq(self.go_rd_i[i])
+            comb += self.src_rsel_o[i].eq(intregdeps.src_rsel_o[i])
+        for i in range(self.n_dst):
+            print(i, self.go_wr_i, intfudeps.go_wr_i)
+            comb += intfudeps.go_wr_i[i].eq(self.go_wr_i[i])
+            comb += intregdeps.dest_i[i].eq(self.dest_i[i])
+            comb += intregdeps.go_wr_i[i].eq(self.go_wr_i[i])
+            comb += self.dst_rsel_o[i].eq(intregdeps.dest_rsel_o[i])
         comb += intregdeps.go_die_i.eq(self.go_die_i)
         comb += intregdeps.issue_i.eq(self.fn_issue_i)
 
         comb += intregdeps.go_die_i.eq(self.go_die_i)
         comb += intregdeps.issue_i.eq(self.fn_issue_i)
 
-        comb += self.dest_rsel_o.eq(intregdeps.dest_rsel_o[0])
-        comb += self.src1_rsel_o.eq(intregdeps.src_rsel_o[0])
-        comb += self.src2_rsel_o.eq(intregdeps.src_rsel_o[1])
-
         return m
 
 
         return m
 
 
@@ -399,18 +436,17 @@ class Scoreboard(Elaboratable):
         self.fpregs = RegFileArray(rwid, n_regs)
 
         # Memory (test for now)
         self.fpregs = RegFileArray(rwid, n_regs)
 
         # Memory (test for now)
-        self.mem = TestMemory(self.rwid, 8)  # not too big, takes too long
+        self.l0 = TstL0CacheBuffer()
 
         # issue q needs to get at these
         self.aluissue = IssueUnitGroup(2)
         self.lsissue = IssueUnitGroup(2)
         self.brissue = IssueUnitGroup(1)
         # and these
 
         # issue q needs to get at these
         self.aluissue = IssueUnitGroup(2)
         self.lsissue = IssueUnitGroup(2)
         self.brissue = IssueUnitGroup(1)
         # and these
-        self.alu_op = CompALUOpSubset("alu")
+        self.instr = Decode2ToExecute1Type("sc_instr")
         self.br_oper_i = Signal(4, reset_less=True)
         self.br_imm_i = Signal(rwid, reset_less=True)
         self.ls_oper_i = Signal(4, reset_less=True)
         self.br_oper_i = Signal(4, reset_less=True)
         self.br_imm_i = Signal(rwid, reset_less=True)
         self.ls_oper_i = Signal(4, reset_less=True)
-        self.ls_imm_i = Signal(rwid, reset_less=True)
 
         # inputs
         self.int_dest_i = Signal(range(n_regs), reset_less=True)  # Dest R# in
 
         # inputs
         self.int_dest_i = Signal(range(n_regs), reset_less=True)  # Dest R# in
@@ -437,7 +473,7 @@ class Scoreboard(Elaboratable):
 
         m.submodules.intregs = self.intregs
         m.submodules.fpregs = self.fpregs
 
         m.submodules.intregs = self.intregs
         m.submodules.fpregs = self.fpregs
-        m.submodules.mem = mem = self.mem
+        m.submodules.l0 = l0 = self.l0
 
         # register ports
         int_dest = self.intregs.write_port("dest")
 
         # register ports
         int_dest = self.intregs.write_port("dest")
@@ -455,7 +491,7 @@ class Scoreboard(Elaboratable):
 
         # LDST Comp Units
         n_ldsts = 2
 
         # LDST Comp Units
         n_ldsts = 2
-        cul = CompUnitLDSTs(self.rwid, 4, self.lsissue.n_insns, self.mem)
+        cul = CompUnitLDSTs(self.rwid, 4, self.lsissue.n_insns, l0)
 
         # Comp Units
         m.submodules.cu = cu = CompUnitsBase(self.rwid, [cua, cul, cub])
 
         # Comp Units
         m.submodules.cu = cu = CompUnitsBase(self.rwid, [cua, cul, cub])
@@ -463,14 +499,17 @@ class Scoreboard(Elaboratable):
         br1 = cub.br1
 
         # Int FUs
         br1 = cub.br1
 
         # Int FUs
-        m.submodules.intfus = intfus = FunctionUnits(self.n_regs, n_int_alus)
+        fu_n_src = 2
+        fu_n_dst = 1
+        m.submodules.intfus = intfus = FunctionUnits(self.n_regs, n_int_alus,
+                                                     fu_n_src, fu_n_dst)
 
         # Memory FUs
         m.submodules.memfus = memfus = MemFunctionUnits(n_ldsts, 5)
 
         # Memory Priority Picker 1: one gateway per memory port
         # picks 1 reader and 1 writer to intreg
 
         # Memory FUs
         m.submodules.memfus = memfus = MemFunctionUnits(n_ldsts, 5)
 
         # Memory Priority Picker 1: one gateway per memory port
         # picks 1 reader and 1 writer to intreg
-        mempick1 = GroupPicker(n_ldsts)
+        mempick1 = GroupPicker(n_ldsts, 1, 1)
         m.submodules.mempick1 = mempick1
 
         # Count of number of FUs
         m.submodules.mempick1 = mempick1
 
         # Count of number of FUs
@@ -479,8 +518,8 @@ class Scoreboard(Elaboratable):
 
         # Integer Priority Picker 1: Adder + Subtractor (and LD/ST)
         # picks 1 reader and 1 writer to intreg
 
         # Integer Priority Picker 1: Adder + Subtractor (and LD/ST)
         # picks 1 reader and 1 writer to intreg
-        intpick1 = GroupPicker(n_intfus)
-        m.submodules.intpick1 = intpick1
+        ipick1 = GroupPicker(n_intfus, fu_n_src, fu_n_dst)
+        m.submodules.intpick1 = ipick1
 
         # INT/FP Issue Unit
         regdecode = RegDecode(self.n_regs)
 
         # INT/FP Issue Unit
         regdecode = RegDecode(self.n_regs)
@@ -519,18 +558,17 @@ class Scoreboard(Elaboratable):
                  ]
 
         # take these to outside (issue needs them)
                  ]
 
         # take these to outside (issue needs them)
-        comb += cua.op.eq(self.alu_op)
+        comb += cua.op.eq_from_execute1(self.instr)
         comb += cub.oper_i.eq(self.br_oper_i)
         comb += cub.imm_i.eq(self.br_imm_i)
         comb += cub.oper_i.eq(self.br_oper_i)
         comb += cub.imm_i.eq(self.br_imm_i)
-        comb += cul.oper_i.eq(self.ls_oper_i)
-        comb += cul.imm_i.eq(self.ls_imm_i)
+        comb += cul.op.eq_from_execute1(self.instr)
 
         # TODO: issueunit.f (FP)
 
         # and int function issue / busy arrays, and dest/src1/src2
 
         # TODO: issueunit.f (FP)
 
         # and int function issue / busy arrays, and dest/src1/src2
-        comb += intfus.dest_i.eq(regdecode.dest_o)
-        comb += intfus.src1_i.eq(regdecode.src1_o)
-        comb += intfus.src2_i.eq(regdecode.src2_o)
+        comb += intfus.dest_i[0].eq(regdecode.dest_o)
+        comb += intfus.src_i[0].eq(regdecode.src1_o)
+        comb += intfus.src_i[1].eq(regdecode.src2_o)
 
         fn_issue_o = issueunit.fn_issue_o
 
 
         fn_issue_o = issueunit.fn_issue_o
 
@@ -542,7 +580,9 @@ class Scoreboard(Elaboratable):
         # Memory Function Unit
         # ---------
         reset_b = Signal(cul.n_units, reset_less=True)
         # Memory Function Unit
         # ---------
         reset_b = Signal(cul.n_units, reset_less=True)
-        sync += reset_b.eq(cul.go_st_i | cul.go_wr_i | cul.go_die_i)
+        # XXX was cul.go_wr_i not done.o
+        # sync += reset_b.eq(cul.go_st_i | cul.done_o | cul.go_die_i)
+        sync += reset_b.eq(cul.go_st_i | cul.done_o | cul.go_die_i)
 
         comb += memfus.fn_issue_i.eq(cul.issue_i)  # Comp Unit Issue -> Mem FUs
         comb += memfus.addr_en_i.eq(cul.adr_rel_o)  # Match enable on adr rel
 
         comb += memfus.fn_issue_i.eq(cul.issue_i)  # Comp Unit Issue -> Mem FUs
         comb += memfus.addr_en_i.eq(cul.adr_rel_o)  # Match enable on adr rel
@@ -560,7 +600,7 @@ class Scoreboard(Elaboratable):
 
         # TODO: adr_rel_o needs to go into L1 Cache.  for now,
         # just immediately activate go_adr
 
         # TODO: adr_rel_o needs to go into L1 Cache.  for now,
         # just immediately activate go_adr
-        comb += cul.go_ad_i.eq(cul.adr_rel_o)
+        sync += cul.go_ad_i.eq(cul.adr_rel_o)
 
         # connect up address data
         comb += memfus.addrs_i[0].eq(cul.units[0].addr_o)
 
         # connect up address data
         comb += memfus.addrs_i[0].eq(cul.units[0].addr_o)
@@ -601,24 +641,31 @@ class Scoreboard(Elaboratable):
         # ---------
 
         # Group Picker... done manually for now.
         # ---------
 
         # Group Picker... done manually for now.
-        go_rd_o = intpick1.go_rd_o
-        go_wr_o = intpick1.go_wr_o
+        go_rd_o = ipick1.go_rd_o
+        go_wr_o = ipick1.go_wr_o
         go_rd_i = intfus.go_rd_i
         go_wr_i = intfus.go_wr_i
         go_die_i = intfus.go_die_i
         # NOTE: connect to the shadowed versions so that they can "die" (reset)
         go_rd_i = intfus.go_rd_i
         go_wr_i = intfus.go_wr_i
         go_die_i = intfus.go_die_i
         # NOTE: connect to the shadowed versions so that they can "die" (reset)
-        comb += go_rd_i[0:n_intfus].eq(go_rd_o[0:n_intfus])  # rd
-        comb += go_wr_i[0:n_intfus].eq(go_wr_o[0:n_intfus])  # wr
+        for i in range(fu_n_src):
+            comb += go_rd_i[i][0:n_intfus].eq(go_rd_o[i][0:n_intfus])  # rd
+        for i in range(fu_n_dst):
+            comb += go_wr_i[i][0:n_intfus].eq(go_wr_o[i][0:n_intfus])  # wr
         comb += go_die_i[0:n_intfus].eq(anydie[0:n_intfus])  # die
 
         # Connect Picker
         # ---------
         comb += go_die_i[0:n_intfus].eq(anydie[0:n_intfus])  # die
 
         # Connect Picker
         # ---------
-        comb += intpick1.rd_rel_i[0:n_intfus].eq(cu.rd_rel_o[0:n_intfus])
-        comb += intpick1.req_rel_i[0:n_intfus].eq(cu.done_o[0:n_intfus])
         int_rd_o = intfus.readable_o
         int_rd_o = intfus.readable_o
+        rrel_o = cu.rd_rel_o
+        rqrl_o = cu.req_rel_o
+        for i in range(fu_n_src):
+            comb += ipick1.rd_rel_i[i][0:n_intfus].eq(rrel_o[i][0:n_intfus])
+            comb += ipick1.readable_i[i][0:n_intfus].eq(int_rd_o[0:n_intfus])
         int_wr_o = intfus.writable_o
         int_wr_o = intfus.writable_o
-        comb += intpick1.readable_i[0:n_intfus].eq(int_rd_o[0:n_intfus])
-        comb += intpick1.writable_i[0:n_intfus].eq(int_wr_o[0:n_intfus])
+        for i in range(fu_n_dst):
+            # XXX FIXME: rqrl_o[i] here
+            comb += ipick1.req_rel_i[i][0:n_intfus].eq(rqrl_o[0:n_intfus])
+            comb += ipick1.writable_i[i][0:n_intfus].eq(int_wr_o[0:n_intfus])
 
         # ---------
         # Shadow Matrix
 
         # ---------
         # Shadow Matrix
@@ -640,7 +687,10 @@ class Scoreboard(Elaboratable):
 
         # when written, the shadow can be cancelled (and was good)
         for i in range(n_intfus):
 
         # when written, the shadow can be cancelled (and was good)
         for i in range(n_intfus):
-            comb += shadows.s_good_i[i][0:n_intfus].eq(go_wr_o[0:n_intfus])
+            #comb += shadows.s_good_i[i][0:n_intfus].eq(go_wr_o[0:n_intfus])
+            # XXX experiment: use ~cu.busy_o instead.  *should* be good
+            # because the comp unit is only free once completed
+            comb += shadows.s_good_i[i][0:n_intfus].eq(~cu.busy_o[0:n_intfus])
 
         # *previous* instruction shadows *current* instruction, and, obviously,
         # if the previous is completed (!busy) don't cast the shadow!
 
         # *previous* instruction shadows *current* instruction, and, obviously,
         # if the previous is completed (!busy) don't cast the shadow!
@@ -694,9 +744,9 @@ class Scoreboard(Elaboratable):
         # ---------
         # Connect Register File(s)
         # ---------
         # ---------
         # Connect Register File(s)
         # ---------
-        comb += int_dest.wen.eq(intfus.dest_rsel_o)
-        comb += int_src1.ren.eq(intfus.src1_rsel_o)
-        comb += int_src2.ren.eq(intfus.src2_rsel_o)
+        comb += int_dest.wen.eq(intfus.dst_rsel_o[0])
+        comb += int_src1.ren.eq(intfus.src_rsel_o[0])
+        comb += int_src2.ren.eq(intfus.src_rsel_o[1])
 
         # connect ALUs to regfile
         comb += int_dest.data_i.eq(cu.data_o)
 
         # connect ALUs to regfile
         comb += int_dest.data_i.eq(cu.data_o)
@@ -704,8 +754,10 @@ class Scoreboard(Elaboratable):
         comb += cu.src2_i.eq(int_src2.data_o)
 
         # connect ALU Computation Units
         comb += cu.src2_i.eq(int_src2.data_o)
 
         # connect ALU Computation Units
-        comb += cu.go_rd_i[0:n_intfus].eq(go_rd_o[0:n_intfus])
-        comb += cu.go_wr_i[0:n_intfus].eq(go_wr_o[0:n_intfus])
+        for i in range(fu_n_src):
+            comb += cu.go_rd_i[i][0:n_intfus].eq(go_rd_o[i][0:n_intfus])
+        for i in range(fu_n_dst):
+            comb += cu.go_wr_i[i][0:n_intfus].eq(go_wr_o[i][0:n_intfus])
         comb += cu.issue_i[0:n_intfus].eq(fn_issue_o[0:n_intfus])
 
         return m
         comb += cu.issue_i[0:n_intfus].eq(fn_issue_o[0:n_intfus])
 
         return m
@@ -808,28 +860,21 @@ class IssueToScoreboard(Elaboratable):
             comb += sc.int_src1_i.eq(src1)
             comb += sc.int_src2_i.eq(src2)
             comb += sc.reg_enable_i.eq(1)  # enable the regfile
             comb += sc.int_src1_i.eq(src1)
             comb += sc.int_src2_i.eq(src2)
             comb += sc.reg_enable_i.eq(1)  # enable the regfile
+            comb += sc.instr.eq(instr)
 
             # choose a Function-Unit-Group
             with m.If(fu == Function.ALU):  # alu
 
             # choose a Function-Unit-Group
             with m.If(fu == Function.ALU):  # alu
-                comb += sc.alu_op.eq_from_execute1(instr)
-                comb += sc.aluissue.insn_i.eq(1)
+                comb += sc.aluissue.insn_i.eq(1)  # enable alu issue
                 comb += wait_issue_alu.eq(1)
                 comb += wait_issue_alu.eq(1)
+            with m.Elif(fu == Function.LDST):  # ld/st
+                comb += sc.lsissue.insn_i.eq(1)  # enable ldst issue
+                comb += wait_issue_ls.eq(1)
+
             with m.Elif((op & (0x3 << 2)) != 0):  # branch
                 comb += sc.br_oper_i.eq(Cat(op[0:2], opi))
                 comb += sc.br_imm_i.eq(imm)
                 comb += sc.brissue.insn_i.eq(1)
                 comb += wait_issue_br.eq(1)
             with m.Elif((op & (0x3 << 2)) != 0):  # branch
                 comb += sc.br_oper_i.eq(Cat(op[0:2], opi))
                 comb += sc.br_imm_i.eq(imm)
                 comb += sc.brissue.insn_i.eq(1)
                 comb += wait_issue_br.eq(1)
-            with m.Elif((op & (0x3 << 4)) != 0):  # ld/st
-                # see compldst.py
-                # bit 0: ADD/SUB
-                # bit 1: immed
-                # bit 4: LD
-                # bit 5: ST
-                comb += sc.ls_oper_i.eq(Cat(op[0], opi[0], op[4:6]))
-                comb += sc.ls_imm_i.eq(imm)
-                comb += sc.lsissue.insn_i.eq(1)
-                comb += wait_issue_ls.eq(1)
-
             # XXX TODO
             # these indicate that the instruction is to be made
             # shadow-dependent on
             # XXX TODO
             # these indicate that the instruction is to be made
             # shadow-dependent on
@@ -871,7 +916,7 @@ def power_instr_q(dut, pdecode2, ins, code):
 def instr_q(dut, op, funit, op_imm, imm, src1, src2, dest,
             branch_success, branch_fail):
     instrs = [{'insn_type': op, 'fn_unit': funit, 'write_reg': dest,
 def instr_q(dut, op, funit, op_imm, imm, src1, src2, dest,
             branch_success, branch_fail):
     instrs = [{'insn_type': op, 'fn_unit': funit, 'write_reg': dest,
-                'imm_data': (imm, op_imm),
+               'imm_data': (imm, op_imm),
                'read_reg1': src1, 'read_reg2': src2}]
 
     sendlen = 1
                'read_reg1': src1, 'read_reg2': src2}]
 
     sendlen = 1
@@ -885,11 +930,11 @@ def instr_q(dut, op, funit, op_imm, imm, src1, src2, dest,
         yield dut.data_i[idx].insn_type.eq(insn_type)
         yield dut.data_i[idx].fn_unit.eq(fn_unit)
         yield dut.data_i[idx].read_reg1.data.eq(reg1)
         yield dut.data_i[idx].insn_type.eq(insn_type)
         yield dut.data_i[idx].fn_unit.eq(fn_unit)
         yield dut.data_i[idx].read_reg1.data.eq(reg1)
-        yield dut.data_i[idx].read_reg1.ok.eq(1) # XXX TODO
+        yield dut.data_i[idx].read_reg1.ok.eq(1)  # XXX TODO
         yield dut.data_i[idx].read_reg2.data.eq(reg2)
         yield dut.data_i[idx].read_reg2.data.eq(reg2)
-        yield dut.data_i[idx].read_reg2.ok.eq(1) # XXX TODO
+        yield dut.data_i[idx].read_reg2.ok.eq(1)  # XXX TODO
         yield dut.data_i[idx].write_reg.data.eq(dest)
         yield dut.data_i[idx].write_reg.data.eq(dest)
-        yield dut.data_i[idx].write_reg.ok.eq(1) # XXX TODO
+        yield dut.data_i[idx].write_reg.ok.eq(1)  # XXX TODO
         yield dut.data_i[idx].imm_data.data.eq(imm)
         yield dut.data_i[idx].imm_data.ok.eq(op_imm)
         di = yield dut.data_i[idx]
         yield dut.data_i[idx].imm_data.data.eq(imm)
         yield dut.data_i[idx].imm_data.ok.eq(op_imm)
         di = yield dut.data_i[idx]
@@ -1108,21 +1153,30 @@ def power_sim(m, dut, pdecode2, instruction, alusim):
         for i in range(1, dut.n_regs):
             #val = randint(0, (1<<alusim.rwidth)-1)
             #val = 31+i*3
         for i in range(1, dut.n_regs):
             #val = randint(0, (1<<alusim.rwidth)-1)
             #val = 31+i*3
-            val = i # XXX actually, not random at all
+            val = i  # XXX actually, not random at all
             yield dut.intregs.regs[i].reg.eq(val)
             alusim.setval(i, val)
 
         # create some instructions
             yield dut.intregs.regs[i].reg.eq(val)
             alusim.setval(i, val)
 
         # create some instructions
-        lst = [#"addi 3, 0, 0x1234",
-               #"addi 2, 0, 0x4321",
-               "add  1, 3, 2"]
+        lst = []
+        if False:
+            lst += ["addi 2, 0, 0x4321",
+                    "addi 3, 0, 0x1234",
+                    "add  1, 3, 2",
+                    "add  4, 3, 5"
+                    ]
+        if True:
+            lst += ["lbzu 6, 7(2)",
+
+                    ]
+
         with Program(lst) as program:
             gen = program.generate_instructions()
 
             # issue instruction(s), wait for issue to be free before proceeding
             for ins, code in zip(gen, program.assembly.splitlines()):
                 yield instruction.eq(ins)          # raw binary instr.
         with Program(lst) as program:
             gen = program.generate_instructions()
 
             # issue instruction(s), wait for issue to be free before proceeding
             for ins, code in zip(gen, program.assembly.splitlines()):
                 yield instruction.eq(ins)          # raw binary instr.
-                yield Delay(1e-6)
+                yield  # Delay(1e-6)
 
                 print("binary 0x{:X}".format(ins & 0xffffffff))
                 print("assembly", code)
 
                 print("binary 0x{:X}".format(ins & 0xffffffff))
                 print("assembly", code)
@@ -1179,15 +1233,15 @@ def scoreboard_sim(dut, alusim):
             instrs.append((1, 7, 2, 2, 0, 0, (0, 0)))
 
         if True:
             instrs.append((1, 7, 2, 2, 0, 0, (0, 0)))
 
         if True:
-            instrs.append((2, 3, 3, InternalOp.OP_ADD, Function.ALU,
+            instrs.append((2, 3, 3, MicrOp.OP_ADD, Function.ALU,
                            0, 0, (0, 0)))
                            0, 0, (0, 0)))
-            instrs.append((5, 3, 3, InternalOp.OP_ADD, Function.ALU,
+            instrs.append((5, 3, 3, MicrOp.OP_ADD, Function.ALU,
                            0, 0, (0, 0)))
         if False:
                            0, 0, (0, 0)))
         if False:
-            instrs.append((3, 5, 5, InternalOp.OP_MUL_L64, Function.ALU,
+            instrs.append((3, 5, 5, MicrOp.OP_MUL_L64, Function.ALU,
                            1, 7, (0, 0)))
         if False:
                            1, 7, (0, 0)))
         if False:
-            instrs.append((2, 3, 3, InternalOp.OP_ADD, Function.ALU,
+            instrs.append((2, 3, 3, MicrOp.OP_ADD, Function.ALU,
                            0, 0, (0, 0)))
 
         if False:
                            0, 0, (0, 0)))
 
         if False:
@@ -1282,7 +1336,7 @@ def scoreboard_sim(dut, alusim):
 
         # issue instruction(s), wait for issue to be free before proceeding
         for i, instr in enumerate(instrs):
 
         # issue instruction(s), wait for issue to be free before proceeding
         for i, instr in enumerate(instrs):
-            print (i, instr)
+            print(i, instr)
             src1, src2, dest, op, fn_unit, opi, imm, (br_ok, br_fail) = instr
 
             print("instr %d: (%d, %d, %d, %s, %s, %d, %d)" %
             src1, src2, dest, op, fn_unit, opi, imm, (br_ok, br_fail) = instr
 
             print("instr %d: (%d, %d, %d, %s, %s, %d, %d)" %
@@ -1335,7 +1389,7 @@ def test_scoreboard():
     run_simulation(m, power_sim(m, dut, pdecode2, instruction, alusim),
                    vcd_name='test_powerboard6600.vcd')
 
     run_simulation(m, power_sim(m, dut, pdecode2, instruction, alusim),
                    vcd_name='test_powerboard6600.vcd')
 
-    #run_simulation(dut, scoreboard_sim(dut, alusim),
+    # run_simulation(dut, scoreboard_sim(dut, alusim),
     #               vcd_name='test_scoreboard6600.vcd')
 
     # run_simulation(dut, scoreboard_branch_sim(dut, alusim),
     #               vcd_name='test_scoreboard6600.vcd')
 
     # run_simulation(dut, scoreboard_branch_sim(dut, alusim),