3473e4c69842eca874c9381a68aa10dfa94b4a56
1 """IEEE Floating Point Divider Pipeline
3 Relevant bugreport: http://bugs.libre-riscv.org/show_bug.cgi?id=99
7 scnorm - FPDIVSpecialCasesDeNorm ispec FPADDBaseData
10 StageChain: FPDIVSpecialCasesMod,
13 pipediv0 - FPDivStagesSetup ispec FPSCData
14 -------- ospec DivPipeCoreInterstageData
16 StageChain: FPDivStage0Mod,
18 DivPipeCalculateStage,
22 pipediv1 - FPDivStagesIntermediate ispec DivPipeCoreInterstageData
23 -------- ospec DivPipeCoreInterstageData
25 StageChain: DivPipeCalculateStage,
31 pipediv5 - FPDivStageFinal ispec FPDivStage0Data
32 -------- ospec FPAddStage1Data
34 StageChain: DivPipeCalculateStage,
36 DivPipeCalculateStage,
40 normpack - FPNormToPack ispec FPAddStage1Data
41 -------- ospec FPPackData
43 StageChain: Norm1ModSingle,
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.
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.
59 from nmigen
import Module
60 from nmigen
.cli
import main
, verilog
62 from nmutil
.singlepipe
import ControlBase
63 from nmutil
.concurrentunit
import ReservationStations
, num_bits
65 from ieee754
.fpcommon
.getop
import FPADDBaseData
66 from ieee754
.fpcommon
.denorm
import FPSCData
67 from ieee754
.fpcommon
.pack
import FPPackData
68 from ieee754
.fpcommon
.normtopack
import FPNormToPack
69 from ieee754
.fpdiv
.specialcases
import FPDIVSpecialCasesDeNorm
70 from ieee754
.fpdiv
.divstages
import (FPDivStagesSetup
,
71 FPDivStagesIntermediate
,
73 from ieee754
.pipeline
import PipelineSpec
76 class FPDIVBasePipe(ControlBase
):
77 def __init__(self
, pspec
):
78 ControlBase
.__init
__(self
)
81 def elaborate(self
, platform
):
82 m
= ControlBase
.elaborate(self
, platform
)
85 n_stages
= 6 # TODO (depends on width)
86 n_comb_stages
= 3 # TODO (depends on how many RS's we want)
88 # to which the answer: "as few as possible"
89 # is required. too many ReservationStations
90 # means "big problems".
92 for i
in range(n_stages
):
94 # needs to convert input from pipestart ospec
96 kls
= FPDivStagesSetup
97 n_comb_stages
-= 1 # reduce due to work done at start
99 # needs to convert output to pipeend ispec
100 elif i
== n_stages
- 1:
101 kls
= FPDivStagesFinal
102 n_comb_stages
-= 1 # FIXME - reduce due to work done at end?
106 kls
= FPDivStagesIntermediate
108 pipechain
.append(kls(self
.pspec
, n_comb_stages
, stage_idx
))
109 stage_idx
+= n_comb_stages
# increment so that each CalcStage
110 # gets a (correct) unique index
112 # start and end: unpack/specialcases then normalisation/packing
113 pipestart
= FPDIVSpecialCasesDeNorm(self
.pspec
)
114 pipeend
= FPNormToPack(self
.pspec
)
117 m
.submodules
.scnorm
= pipestart
118 for i
, p
in enumerate(pipechain
):
119 setattr(m
.submodules
, "pipediv%d" % i
, p
)
120 m
.submodules
.normpack
= pipeend
122 # ControlBase.connect creates the "eqs" needed to connect each pipe
123 m
.d
.comb
+= self
.connect([pipestart
] + pipechain
+ [pipeend
])
128 class FPDIVMuxInOut(ReservationStations
):
129 """ Reservation-Station version of FPDIV pipeline.
131 * fan-in on inputs (an array of FPADDBaseData: a,b,mid)
132 * N-stage divider pipeline
133 * fan-out on outputs (an array of FPPackData: z,mid)
135 Fan-in and Fan-out are combinatorial.
137 :op_wid: - set this to the width of an operator which can
138 then be used to change the behaviour of the pipeline.
141 def __init__(self
, width
, num_rows
, op_wid
=0):
142 self
.id_wid
= num_bits(width
)
143 self
.pspec
= PipelineSpec(width
, self
.id_wid
, op_wid
)
144 # XXX TODO - a class (or function?) that takes the pspec (right here)
145 # and creates... "something". that "something" MUST have an eq function
146 # new_pspec = deepcopy(self.pspec)
147 # new_pspec.opkls = DivPipeCoreOperation
148 # self.alu = FPDIVBasePipe(new_pspec)
149 self
.alu
= FPDIVBasePipe(self
.pspec
)
150 ReservationStations
.__init
__(self
, num_rows
)
153 return FPADDBaseData(self
.pspec
)
156 return FPPackData(self
.pspec
)