- CR: not so many needed (perhaps)
- Branch: one or two of these (depending on speculation run-ahead)
- Trap: yeah really only one of these
+ - SPR: again, only one.
- ShiftRot (perhaps not too many of these)
* Multi-cycle (and FSM) Function Units. these are FUs that can only
"""
+# imports
+
+from nmigen import Elaboratable, Module
from nmigen.cli import rtlil
from soc.experiment.compalu_multi import MultiCompUnit
+from soc.decoder.power_enums import Function
# pipeline / spec imports
from soc.fu.alu.pipeline import ALUBasePipe
from soc.fu.alu.pipe_data import ALUPipeSpec
+from soc.fu.logical.pipeline import LogicalBasePipe
+from soc.fu.logical.pipe_data import LogicalPipeSpec
+
from soc.fu.cr.pipeline import CRBasePipe
from soc.fu.cr.pipe_data import CRPipeSpec
from soc.fu.shift_rot.pipeline import ShiftRotBasePipe
from soc.fu.shift_rot.pipe_data import ShiftRotPipeSpec
+from soc.fu.spr.pipeline import SPRBasePipe
+from soc.fu.spr.pipe_data import SPRPipeSpec
+
+from soc.fu.trap.pipeline import TrapBasePipe
+from soc.fu.trap.pipe_data import TrapPipeSpec
+
+from soc.fu.div.pipeline import DivBasePipe
+from soc.fu.div.pipe_data import DivPipeSpecDivPipeCore
+
+from soc.fu.mul.pipeline import MulBasePipe
+from soc.fu.mul.pipe_data import MulPipeSpec
+
+from soc.fu.ldst.pipe_data import LDSTPipeSpec
+from soc.experiment.compldst_multi import LDSTCompUnit # special-case
+
###################################################################
###### FunctionUnitBaseSingle - use to make single-stge pipes #####
note that it is through MultiCompUnit.get_in/out that we *actually*
connect up the association between regspec variable names (defined
in the pipe_data).
+
+ note that the rdflags function obtains (dynamically, from instruction
+ decoding) which read-register ports are to be requested. this is not
+ ideal (it could be a lot neater) but works for now.
"""
- def __init__(self, speckls, pipekls):
+
+ def __init__(self, speckls, pipekls, idx):
+ alu_name = "alu_%s%d" % (self.fnunit.name.lower(), idx)
pspec = speckls(id_wid=2) # spec (NNNPipeSpec instance)
opsubset = pspec.opsubsetkls # get the operand subset class
regspec = pspec.regspec # get the regspec
alu = pipekls(pspec) # create actual NNNBasePipe
- super().__init__(regspec, alu, opsubset) # pass to MultiCompUnit
+ super().__init__(regspec, alu, opsubset, name=alu_name) # MultiCompUnit
##############################################################
###### actual Function Units: these are "single" stage pipelines #####
class ALUFunctionUnit(FunctionUnitBaseSingle):
- def __init__(self): super().__init__(ALUPipeSpec, ALUBasePipe)
+ fnunit = Function.ALU
+
+ def __init__(self, idx):
+ super().__init__(ALUPipeSpec, ALUBasePipe, idx)
+
+
+class LogicalFunctionUnit(FunctionUnitBaseSingle):
+ fnunit = Function.LOGICAL
+
+ def __init__(self, idx):
+ super().__init__(LogicalPipeSpec, LogicalBasePipe, idx)
+
class CRFunctionUnit(FunctionUnitBaseSingle):
- def __init__(self): super().__init__(CRPipeSpec, CRBasePipe)
+ fnunit = Function.CR
+
+ def __init__(self, idx):
+ super().__init__(CRPipeSpec, CRBasePipe, idx)
+
class BranchFunctionUnit(FunctionUnitBaseSingle):
- def __init__(self): super().__init__(BranchPipeSpec, BranchBasePipe)
+ fnunit = Function.BRANCH
+
+ def __init__(self, idx):
+ super().__init__(BranchPipeSpec, BranchBasePipe, idx)
+
class ShiftRotFunctionUnit(FunctionUnitBaseSingle):
- def __init__(self): super().__init__(ShiftRotPipeSpec, ShiftRotBasePipe)
+ fnunit = Function.SHIFT_ROT
+
+ def __init__(self, idx):
+ super().__init__(ShiftRotPipeSpec, ShiftRotBasePipe, idx)
+
+
+class DivFunctionUnit(FunctionUnitBaseSingle):
+ fnunit = Function.DIV
+
+ def __init__(self, idx):
+ super().__init__(DivPipeSpecDivPipeCore, DivBasePipe, idx)
+
+
+class MulFunctionUnit(FunctionUnitBaseSingle):
+ fnunit = Function.MUL
+
+ def __init__(self, idx):
+ super().__init__(MulPipeSpec, MulBasePipe, idx)
+
+
+class TrapFunctionUnit(FunctionUnitBaseSingle):
+ fnunit = Function.TRAP
+
+ def __init__(self, idx):
+ super().__init__(TrapPipeSpec, TrapBasePipe, idx)
+
+
+class SPRFunctionUnit(FunctionUnitBaseSingle):
+ fnunit = Function.SPR
+
+ def __init__(self, idx):
+ super().__init__(SPRPipeSpec, SPRBasePipe, idx)
+
+
+# special-case: LD/ST conforms to the CompUnit API but is not a pipeline
+
+class LDSTFunctionUnit(LDSTCompUnit):
+ fnunit = Function.LDST
+
+ def __init__(self, pi, awid, idx):
+ alu_name = "ldst_%s%d" % (self.fnunit.name.lower(), idx)
+ pspec = LDSTPipeSpec(id_wid=2) # spec (NNNPipeSpec instance)
+ opsubset = pspec.opsubsetkls # get the operand subset class
+ regspec = pspec.regspec # get the regspec
+ super().__init__(pi, regspec, awid, opsubset, name=alu_name)
+
#####################################################################
###### actual Function Units: these are "multi" stage pipelines #####
# TODO: ReservationStations-based.
+# simple one-only function unit class, for test purposes
+class AllFunctionUnits(Elaboratable):
+ """AllFunctionUnits
+
+ creates a dictionary of Function Units according to required spec.
+ tuple is of:
+
+ * name of ALU,
+ * quantity of FUs required
+ * type of FU required
+
+ """
+
+ def __init__(self, pspec, pilist=None):
+ addrwid = pspec.addr_wid
+ units = pspec.units
+ if not isinstance(units, dict):
+ units = {'alu': 1, 'cr': 1, 'branch': 1, 'trap': 1,
+ 'spr': 1,
+ 'logical': 1,
+ 'mul': 1,
+ 'div': 1, 'shiftrot': 1}
+ alus = {'alu': ALUFunctionUnit,
+ 'cr': CRFunctionUnit,
+ 'branch': BranchFunctionUnit,
+ 'trap': TrapFunctionUnit,
+ 'spr': SPRFunctionUnit,
+ 'div': DivFunctionUnit,
+ 'mul': MulFunctionUnit,
+ 'logical': LogicalFunctionUnit,
+ 'shiftrot': ShiftRotFunctionUnit,
+ }
+ self.fus = {}
+ for name, qty in units.items():
+ kls = alus[name]
+ for i in range(qty):
+ self.fus["%s%d" % (name, i)] = kls(i)
+ if pilist is None:
+ return
+ for i, pi in enumerate(pilist):
+ self.fus["ldst%d" % (i)] = LDSTFunctionUnit(pi, addrwid, i)
+
+ def elaborate(self, platform):
+ m = Module()
+ for (name, fu) in self.fus.items():
+ setattr(m.submodules, name, fu)
+ return m
+
+ def __iter__(self):
+ for (name, fu) in self.fus.items():
+ yield from fu.ports()
+
+ def ports(self):
+ return list(self)
+
+
def tst_single_fus_il():
for (name, kls) in (('alu', ALUFunctionUnit),
('cr', CRFunctionUnit),
('branch', BranchFunctionUnit),
+ ('trap', TrapFunctionUnit),
+ ('spr', SPRFunctionUnit),
+ ('mul', MulFunctionUnit),
+ ('logical', LogicalFunctionUnit),
('shiftrot', ShiftRotFunctionUnit)):
- fu = kls()
+ fu = kls(0)
vl = rtlil.convert(fu, ports=fu.ports())
with open("fu_%s.il" % name, "w") as f:
f.write(vl)
+
+def tst_all_fus():
+ dut = AllFunctionUnits()
+ vl = rtlil.convert(dut, ports=dut.ports())
+ with open("all_fus.il", "w") as f:
+ f.write(vl)
+
+
if __name__ == '__main__':
tst_single_fus_il()
+ tst_all_fus()