c5756fbae0daa46d97d3bdece800e1132c3af591
1 ###################################################################
2 """Function Units Construction
4 This module pulls all of the pipelines together (soc.fu.*) and, using
5 the regspec and Computation Unit APIs, constructs Scoreboard-aware
6 Function Units that may systematically and automatically be wired up
7 to appropriate Register Files.
11 * Single-cycle Function Units. these are FUs that will only block for
12 one cycle. it is expected that multiple of these be instantiated,
13 because they are simple and trivial, and not many gates.
15 - ALU, Logical: definitely several
16 - CR: not so many needed (perhaps)
17 - Branch: one or two of these (depending on speculation run-ahead)
18 - Trap: yeah really only one of these
19 - SPR: again, only one.
20 - ShiftRot (perhaps not too many of these)
22 * Multi-cycle (and FSM) Function Units. these are FUs that can only
23 handle a limited number of values, and take several cycles to complete.
24 Given that under Scoreboard Management, start and completion must be
25 fully managed, a "Reservation Station" style approach is required:
26 *one* multiple-stage (N stage) pipelines need a minimum of N (plural)
27 "CompUnit" front-ends. this includes:
29 - MUL (all versions including MAC)
30 - DIV (including modulo)
32 In either case, there will be multiple MultiCompUnits: it's just that
33 single-cycle ones are instantiated individually (one single-cycle pipeline
34 per MultiCompUnit, and multi-cycle ones need to be instantiated en-masse,
35 where *only one* actual pipeline (or FSM) has *multiple* Reservation
40 * https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
46 from nmigen
import Elaboratable
, Module
47 from nmigen
.cli
import rtlil
48 from soc
.experiment
.compalu_multi
import MultiCompUnit
49 from soc
.decoder
.power_enums
import Function
51 # pipeline / spec imports
53 from soc
.fu
.alu
.pipeline
import ALUBasePipe
54 from soc
.fu
.alu
.pipe_data
import ALUPipeSpec
56 from soc
.fu
.logical
.pipeline
import LogicalBasePipe
57 from soc
.fu
.logical
.pipe_data
import LogicalPipeSpec
59 from soc
.fu
.cr
.pipeline
import CRBasePipe
60 from soc
.fu
.cr
.pipe_data
import CRPipeSpec
62 from soc
.fu
.branch
.pipeline
import BranchBasePipe
63 from soc
.fu
.branch
.pipe_data
import BranchPipeSpec
65 from soc
.fu
.shift_rot
.pipeline
import ShiftRotBasePipe
66 from soc
.fu
.shift_rot
.pipe_data
import ShiftRotPipeSpec
68 from soc
.fu
.spr
.pipeline
import SPRBasePipe
69 from soc
.fu
.spr
.pipe_data
import SPRPipeSpec
71 from soc
.fu
.trap
.pipeline
import TrapBasePipe
72 from soc
.fu
.trap
.pipe_data
import TrapPipeSpec
74 from soc
.fu
.div
.pipeline
import DivBasePipe
75 from soc
.fu
.div
.pipe_data
import DivPipeSpecFSMDivCore
76 from soc
.fu
.div
.pipe_data
import DivPipeSpecDivPipeCore
78 from soc
.fu
.mul
.pipeline
import MulBasePipe
79 from soc
.fu
.mul
.pipe_data
import MulPipeSpec
81 from soc
.fu
.ldst
.pipe_data
import LDSTPipeSpec
82 from soc
.experiment
.compldst_multi
import LDSTCompUnit
# special-case
85 ###################################################################
86 ###### FunctionUnitBaseSingle - use to make single-stge pipes #####
88 class FunctionUnitBaseSingle(MultiCompUnit
):
89 """FunctionUnitBaseSingle
91 main "glue" class that brings everything together.
92 ONLY use this class for single-stage pipelines.
94 * :speckls: - the specification. contains regspec and op subset info,
95 and contains common "stuff" like the pipeline ctx,
96 what type of nmutil pipeline base is to be used (etc)
97 * :pipekls: - the type of pipeline. actually connects things together
99 note that it is through MultiCompUnit.get_in/out that we *actually*
100 connect up the association between regspec variable names (defined
103 note that the rdflags function obtains (dynamically, from instruction
104 decoding) which read-register ports are to be requested. this is not
105 ideal (it could be a lot neater) but works for now.
108 def __init__(self
, speckls
, pipekls
, idx
):
109 alu_name
= "alu_%s%d" % (self
.fnunit
.name
.lower(), idx
)
110 pspec
= speckls(id_wid
=2) # spec (NNNPipeSpec instance)
111 opsubset
= pspec
.opsubsetkls
# get the operand subset class
112 regspec
= pspec
.regspec
# get the regspec
113 alu
= pipekls(pspec
) # create actual NNNBasePipe
114 super().__init
__(regspec
, alu
, opsubset
, name
=alu_name
) # MultiCompUnit
117 ##############################################################
118 # TODO: ReservationStations-based (FunctionUnitBaseConcurrent)
120 class FunctionUnitBaseMulti
:
124 ######################################################################
125 ###### actual Function Units: these are "single" stage pipelines #####
127 class ALUFunctionUnit(FunctionUnitBaseSingle
):
128 fnunit
= Function
.ALU
130 def __init__(self
, idx
):
131 super().__init
__(ALUPipeSpec
, ALUBasePipe
, idx
)
134 class LogicalFunctionUnit(FunctionUnitBaseSingle
):
135 fnunit
= Function
.LOGICAL
137 def __init__(self
, idx
):
138 super().__init
__(LogicalPipeSpec
, LogicalBasePipe
, idx
)
141 class CRFunctionUnit(FunctionUnitBaseSingle
):
144 def __init__(self
, idx
):
145 super().__init
__(CRPipeSpec
, CRBasePipe
, idx
)
148 class BranchFunctionUnit(FunctionUnitBaseSingle
):
149 fnunit
= Function
.BRANCH
151 def __init__(self
, idx
):
152 super().__init
__(BranchPipeSpec
, BranchBasePipe
, idx
)
155 class ShiftRotFunctionUnit(FunctionUnitBaseSingle
):
156 fnunit
= Function
.SHIFT_ROT
158 def __init__(self
, idx
):
159 super().__init
__(ShiftRotPipeSpec
, ShiftRotBasePipe
, idx
)
162 class DivFunctionUnit(FunctionUnitBaseSingle
):
163 fnunit
= Function
.DIV
165 def __init__(self
, idx
):
166 #super().__init__(DivPipeSpecFSMDivCore, DivBasePipe, idx)
167 super().__init
__(DivPipeSpecDivPipeCore
, DivBasePipe
, idx
)
170 class MulFunctionUnit(FunctionUnitBaseSingle
):
171 fnunit
= Function
.MUL
173 def __init__(self
, idx
):
174 super().__init
__(MulPipeSpec
, MulBasePipe
, idx
)
177 class TrapFunctionUnit(FunctionUnitBaseSingle
):
178 fnunit
= Function
.TRAP
180 def __init__(self
, idx
):
181 super().__init
__(TrapPipeSpec
, TrapBasePipe
, idx
)
184 class SPRFunctionUnit(FunctionUnitBaseSingle
):
185 fnunit
= Function
.SPR
187 def __init__(self
, idx
):
188 super().__init
__(SPRPipeSpec
, SPRBasePipe
, idx
)
191 # special-case: LD/ST conforms to the CompUnit API but is not a pipeline
193 class LDSTFunctionUnit(LDSTCompUnit
):
194 fnunit
= Function
.LDST
196 def __init__(self
, pi
, awid
, idx
):
197 alu_name
= "ldst_%s%d" % (self
.fnunit
.name
.lower(), idx
)
198 pspec
= LDSTPipeSpec(id_wid
=2) # spec (NNNPipeSpec instance)
199 opsubset
= pspec
.opsubsetkls
# get the operand subset class
200 regspec
= pspec
.regspec
# get the regspec
201 super().__init
__(pi
, regspec
, awid
, opsubset
, name
=alu_name
)
204 #####################################################################
205 ###### actual Function Units: these are "multi" stage pipelines #####
207 # TODO: ReservationStations-based.
210 # simple one-only function unit class, for test purposes
211 class AllFunctionUnits(Elaboratable
):
214 creates a dictionary of Function Units according to required spec.
218 * quantity of FUs required
219 * type of FU required
223 def __init__(self
, pspec
, pilist
=None):
224 addrwid
= pspec
.addr_wid
226 if not isinstance(units
, dict):
227 units
= {'alu': 1, 'cr': 1, 'branch': 1, 'trap': 1,
231 'div': 1, 'shiftrot': 1}
232 alus
= {'alu': ALUFunctionUnit
,
233 'cr': CRFunctionUnit
,
234 'branch': BranchFunctionUnit
,
235 'trap': TrapFunctionUnit
,
236 'spr': SPRFunctionUnit
,
237 'div': DivFunctionUnit
,
238 'mul': MulFunctionUnit
,
239 'logical': LogicalFunctionUnit
,
240 'shiftrot': ShiftRotFunctionUnit
,
243 for name
, qty
in units
.items():
246 self
.fus
["%s%d" % (name
, i
)] = kls(i
)
249 for i
, pi
in enumerate(pilist
):
250 self
.fus
["ldst%d" % (i
)] = LDSTFunctionUnit(pi
, addrwid
, i
)
252 def elaborate(self
, platform
):
254 for (name
, fu
) in self
.fus
.items():
255 setattr(m
.submodules
, name
, fu
)
259 for (name
, fu
) in self
.fus
.items():
260 yield from fu
.ports()
266 def tst_single_fus_il():
267 for (name
, kls
) in (('alu', ALUFunctionUnit
),
268 ('cr', CRFunctionUnit
),
269 ('branch', BranchFunctionUnit
),
270 ('trap', TrapFunctionUnit
),
271 ('spr', SPRFunctionUnit
),
272 ('mul', MulFunctionUnit
),
273 ('logical', LogicalFunctionUnit
),
274 ('shiftrot', ShiftRotFunctionUnit
)):
276 vl
= rtlil
.convert(fu
, ports
=fu
.ports())
277 with
open("fu_%s.il" % name
, "w") as f
:
282 dut
= AllFunctionUnits()
283 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
284 with
open("all_fus.il", "w") as f
:
288 if __name__
== '__main__':