remove rdflags in pipe_data.py (redundant)
[soc.git] / src / soc / fu / compunits / compunits.py
1 ###################################################################
2 """Function Units Construction
3
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.
8
9 Two types exist:
10
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.
14
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 - ShiftRot (perhaps not too many of these)
20
21 * Multi-cycle (and FSM) Function Units. these are FUs that can only
22 handle a limited number of values, and take several cycles to complete.
23 Given that under Scoreboard Management, start and completion must be
24 fully managed, a "Reservation Station" style approach is required:
25 *one* multiple-stage (N stage) pipelines need a minimum of N (plural)
26 "CompUnit" front-ends. this includes:
27
28 - MUL (all versions including MAC)
29 - DIV (including modulo)
30
31 In either case, there will be multiple MultiCompUnits: it's just that
32 single-cycle ones are instantiated individually (one single-cycle pipeline
33 per MultiCompUnit, and multi-cycle ones need to be instantiated en-masse,
34 where *only one* actual pipeline (or FSM) has *multiple* Reservation
35 Stations.
36
37 see:
38
39 * https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
40
41 """
42
43 # imports
44
45 from nmigen import Cat
46 from nmigen.cli import rtlil
47 from soc.experiment.compalu_multi import MultiCompUnit
48
49 # pipeline / spec imports
50
51 from soc.fu.alu.pipeline import ALUBasePipe
52 from soc.fu.alu.pipe_data import ALUPipeSpec
53
54 from soc.fu.logical.pipeline import LogicalBasePipe
55 from soc.fu.logical.pipe_data import LogicalPipeSpec
56
57 from soc.fu.cr.pipeline import CRBasePipe
58 from soc.fu.cr.pipe_data import CRPipeSpec
59
60 from soc.fu.branch.pipeline import BranchBasePipe
61 from soc.fu.branch.pipe_data import BranchPipeSpec
62
63 from soc.fu.shift_rot.pipeline import ShiftRotBasePipe
64 from soc.fu.shift_rot.pipe_data import ShiftRotPipeSpec
65
66
67 ###################################################################
68 ###### FunctionUnitBaseSingle - use to make single-stge pipes #####
69
70 class FunctionUnitBaseSingle(MultiCompUnit):
71 """FunctionUnitBaseSingle
72
73 main "glue" class that brings everything together.
74 ONLY use this class for single-stage pipelines.
75
76 * :speckls: - the specification. contains regspec and op subset info,
77 and contains common "stuff" like the pipeline ctx,
78 what type of nmutil pipeline base is to be used (etc)
79 * :pipekls: - the type of pipeline. actually connects things together
80
81 note that it is through MultiCompUnit.get_in/out that we *actually*
82 connect up the association between regspec variable names (defined
83 in the pipe_data).
84
85 note that the rdflags function obtains (dynamically, from instruction
86 decoding) which read-register ports are to be requested. this is not
87 ideal (it could be a lot neater) but works for now.
88 """
89 def __init__(self, speckls, pipekls):
90 pspec = speckls(id_wid=2) # spec (NNNPipeSpec instance)
91 opsubset = pspec.opsubsetkls # get the operand subset class
92 regspec = pspec.regspec # get the regspec
93 alu = pipekls(pspec) # create actual NNNBasePipe
94 super().__init__(regspec, alu, opsubset) # pass to MultiCompUnit
95
96
97 ##############################################################
98 # TODO: ReservationStations-based (FunctionUnitBaseConcurrent)
99
100 class FunctionUnitBaseMulti:
101 pass
102
103
104 ######################################################################
105 ###### actual Function Units: these are "single" stage pipelines #####
106
107 class ALUFunctionUnit(FunctionUnitBaseSingle):
108 def __init__(self): super().__init__(ALUPipeSpec, ALUBasePipe)
109
110 class LogicalFunctionUnit(FunctionUnitBaseSingle):
111 def __init__(self): super().__init__(LogicalPipeSpec, LogicalBasePipe)
112
113 class CRFunctionUnit(FunctionUnitBaseSingle):
114 def __init__(self): super().__init__(CRPipeSpec, CRBasePipe)
115
116 class BranchFunctionUnit(FunctionUnitBaseSingle):
117 def __init__(self): super().__init__(BranchPipeSpec, BranchBasePipe)
118
119 class ShiftRotFunctionUnit(FunctionUnitBaseSingle):
120 def __init__(self): super().__init__(ShiftRotPipeSpec, ShiftRotBasePipe)
121
122
123 #####################################################################
124 ###### actual Function Units: these are "multi" stage pipelines #####
125
126 # TODO: ReservationStations-based.
127
128
129 def tst_single_fus_il():
130 for (name, kls) in (('alu', ALUFunctionUnit),
131 ('cr', CRFunctionUnit),
132 ('branch', BranchFunctionUnit),
133 ('shiftrot', ShiftRotFunctionUnit)):
134 fu = kls()
135 vl = rtlil.convert(fu, ports=fu.ports())
136 with open("fu_%s.il" % name, "w") as f:
137 f.write(vl)
138
139 if __name__ == '__main__':
140 tst_single_fus_il()