set up DivPipeCoreConfig back in FPDIVMuxInOut, syntax errors
[ieee754fpu.git] / src / ieee754 / fpdiv / pipeline.py
1 """IEEE Floating Point Divider Pipeline
2
3 Relevant bugreport: http://bugs.libre-riscv.org/show_bug.cgi?id=99
4
5 Stack looks like this:
6
7 scnorm - FPDIVSpecialCasesDeNorm ispec FPADDBaseData
8 ------ ospec FPSCData
9
10 StageChain: FPDIVSpecialCasesMod,
11 FPAddDeNormMod
12
13 pipediv0 - FPDivStagesSetup ispec FPSCData
14 -------- ospec DivPipeCoreInterstageData
15
16 StageChain: FPDivStage0Mod,
17 DivPipeSetupStage,
18 DivPipeCalculateStage,
19 ...
20 DivPipeCalculateStage
21
22 pipediv1 - FPDivStagesIntermediate ispec DivPipeCoreInterstageData
23 -------- ospec DivPipeCoreInterstageData
24
25 StageChain: DivPipeCalculateStage,
26 ...
27 DivPipeCalculateStage
28 ...
29 ...
30
31 pipediv5 - FPDivStageFinal ispec FPDivStage0Data
32 -------- ospec FPAddStage1Data
33
34 StageChain: DivPipeCalculateStage,
35 ...
36 DivPipeCalculateStage,
37 DivPipeFinalStage,
38 FPDivStage2Mod
39
40 normpack - FPNormToPack ispec FPAddStage1Data
41 -------- ospec FPPackData
42
43 StageChain: Norm1ModSingle,
44 RoundMod,
45 CorrectionsMod,
46 PackMod
47
48 the number of combinatorial StageChains (n_comb_stages) in
49 FPDivStages is an argument arranged to get the length of the whole
50 pipeline down to sane numbers.
51
52 the reason for keeping the number of stages down is that for every
53 pipeline clock delay, a corresponding ReservationStation is needed.
54 if there are 24 pipeline stages, we need a whopping TWENTY FOUR
55 RS's. that's far too many. 6 is just about an acceptable number.
56 even 8 is starting to get alarmingly high.
57 """
58
59 from nmigen import Module
60 from nmigen.cli import main, verilog
61
62 from nmutil.singlepipe import ControlBase
63 from nmutil.concurrentunit import ReservationStations, num_bits
64
65 from ieee754.fpcommon.getop import FPADDBaseData
66 from ieee754.fpcommon.denorm import FPSCData
67 from ieee754.fpcommon.fpbase import FPFormat
68 from ieee754.fpcommon.pack import FPPackData
69 from ieee754.fpcommon.normtopack import FPNormToPack
70 from ieee754.fpdiv.specialcases import FPDIVSpecialCasesDeNorm
71 from ieee754.fpdiv.divstages import (FPDivStagesSetup,
72 FPDivStagesIntermediate,
73 FPDivStagesFinal)
74 from ieee754.pipeline import PipelineSpec
75 from ieee754.div_rem_sqrt_rsqrt.core import DivPipeCoreConfig
76
77
78 class FPDIVBasePipe(ControlBase):
79 def __init__(self, pspec):
80 self.pspec = pspec
81 ControlBase.__init__(self)
82
83 pipechain = []
84 n_stages = 6 # TODO (depends on width)
85 n_comb_stages = 3 # TODO (depends on how many RS's we want)
86 stage_idx = 0
87 # to which the answer: "as few as possible"
88 # is required. too many ReservationStations
89 # means "big problems".
90
91 for i in range(n_stages):
92
93 # needs to convert input from pipestart ospec
94 if i == 0:
95 kls = FPDivStagesSetup
96 n_comb_stages -= 1 # reduce due to work done at start
97
98 # needs to convert output to pipeend ispec
99 elif i == n_stages - 1:
100 kls = FPDivStagesFinal
101 n_comb_stages -= 1 # FIXME - reduce due to work done at end?
102
103 # intermediary stage
104 else:
105 kls = FPDivStagesIntermediate
106
107 pipechain.append(kls(self.pspec, n_comb_stages, stage_idx))
108 stage_idx += n_comb_stages # increment so that each CalcStage
109 # gets a (correct) unique index
110
111 self.pipechain = pipechain
112
113 # start and end: unpack/specialcases then normalisation/packing
114 self.pipestart = pipestart = FPDIVSpecialCasesDeNorm(self.pspec)
115 self.pipeend = pipeend = FPNormToPack(self.pspec)
116
117 self._eqs = self.connect([pipestart] + pipechain + [pipeend])
118
119 def elaborate(self, platform):
120 m = ControlBase.elaborate(self, platform)
121
122 # add submodules
123 m.submodules.scnorm = self.pipestart
124 for i, p in enumerate(self.pipechain):
125 setattr(m.submodules, "pipediv%d" % i, p)
126 m.submodules.normpack = self.pipeend
127
128 # ControlBase.connect creates the "eqs" needed to connect each pipe
129 m.d.comb += self._eqs
130
131 return m
132
133
134 class FPDIVMuxInOut(ReservationStations):
135 """ Reservation-Station version of FPDIV pipeline.
136
137 * fan-in on inputs (an array of FPADDBaseData: a,b,mid)
138 * N-stage divider pipeline
139 * fan-out on outputs (an array of FPPackData: z,mid)
140
141 Fan-in and Fan-out are combinatorial.
142
143 :op_wid: - set this to the width of an operator which can
144 then be used to change the behaviour of the pipeline.
145 """
146
147 def __init__(self, width, num_rows, op_wid=0):
148 self.id_wid = num_bits(width)
149 self.pspec = PipelineSpec(width, self.id_wid, op_wid)
150 # get the standard mantissa width, store in the pspec
151 # (used in DivPipeBaseStage.get_core_config)
152 fpformat = FPFormat.standard(width)
153 log2_radix = 2
154 cfg = DivPipeCoreConfig(width, fpformat.fraction_width, log2_radix)
155 self.pspec.fpformat = fpformat
156 self.pspec.log2_radix = log2_radix
157 self.pspec.core_config = cfg
158
159 # XXX TODO - a class (or function?) that takes the pspec (right here)
160 # and creates... "something". that "something" MUST have an eq function
161 # new_pspec = deepcopy(self.pspec)
162 # new_pspec.opkls = DivPipeCoreOperation
163 # self.alu = FPDIVBasePipe(new_pspec)
164 self.alu = FPDIVBasePipe(self.pspec)
165 ReservationStations.__init__(self, num_rows)
166
167 def i_specfn(self):
168 return FPADDBaseData(self.pspec)
169
170 def o_specfn(self):
171 return FPPackData(self.pspec)