385743f846fe37cd6d74167d8876ad2fd6d98e84
[ieee754fpu.git] / src / ieee754 / fpdiv / divstages.py
1 """IEEE754 Floating Point pipelined Divider
2
3 Relevant bugreport: http://bugs.libre-riscv.org/show_bug.cgi?id=99
4
5 """
6
7 from nmigen import Module
8 from nmigen.cli import main, verilog
9
10 from nmutil.singlepipe import (StageChain, SimpleHandshake)
11
12 from ieee754.fpcommon.fpbase import FPState
13 from ieee754.fpcommon.denorm import FPSCData
14 from ieee754.fpcommon.postcalc import FPAddStage1Data
15 from ieee754.div_rem_sqrt_rsqrt.div_pipe import (DivPipeInterstageData,
16 DivPipeSetupStage,
17 DivPipeCalculateStage,
18 DivPipeFinalStage,
19 )
20
21 # TODO: write these
22 from .div0 import FPDivStage0Mod
23 from .div2 import FPDivStage2Mod
24
25
26 class FPDivStagesSetup(FPState, SimpleHandshake):
27
28 def __init__(self, pspec, n_stages, stage_offs):
29 FPState.__init__(self, "divsetup")
30 self.pspec = pspec
31 self.n_stages = n_stages # number of combinatorial stages
32 self.stage_offs = stage_offs # each CalcStage needs *absolute* idx
33 SimpleHandshake.__init__(self, self) # pipeline is its own stage
34 self.m1o = self.ospec()
35
36 def ispec(self):
37 # REQUIRED. do NOT change.
38 return FPSCData(self.pspec, False) # from denorm
39
40 def ospec(self):
41 return DivPipeInterstageData(self.pspec) # DIV ospec (loop)
42
43 def setup(self, m, i):
44 """ links module to inputs and outputs.
45
46 note: this is a pure *combinatorial* module (StageChain).
47 therefore each sub-module must also be combinatorial
48 """
49
50 divstages = []
51
52 # Converts from FPSCData into DivPipeInputData
53 divstages.append(FPDivStage0Mod(self.pspec))
54
55 # does 1 "convert" (actual processing) from DivPipeInputData
56 # into "intermediate" output (DivPipeInterstageData)
57 divstages.append(DivPipeSetupStage(self.pspec))
58
59 # here is where the intermediary stages are added.
60 # n_stages is adjusted (by pipeline.py), reduced to take
61 # into account extra processing that FPDivStage0Mod and DivPipeSetup
62 # might add.
63 for count in range(self.n_stages): # number of combinatorial stages
64 idx = count + self.stage_offs
65 divstages.append(DivPipeCalculateStage(self.pspec, idx))
66
67 chain = StageChain(divstages)
68 chain.setup(m, i)
69
70 # output is from the last pipe stage
71 self.o = divstages[-1].o
72
73 def process(self, i):
74 return self.o
75
76 def action(self, m):
77 m.d.sync += self.m1o.eq(self.process(None))
78 m.next = "normalise_1"
79
80
81 class FPDivStagesIntermediate(FPState, SimpleHandshake):
82
83 def __init__(self, pspec, n_stages, stage_offs):
84 FPState.__init__(self, "divintermediate")
85 self.pspec = pspec
86 self.n_stages = n_stages # number of combinatorial stages
87 self.stage_offs = stage_offs # each CalcStage needs *absolute* idx
88 SimpleHandshake.__init__(self, self) # pipeline is its own stage
89 self.m1o = self.ospec()
90
91 def ispec(self):
92 # TODO - this is for FPDivStage1Mod
93 return DivPipeInterstageData(self.pspec) # DIV ispec (loop)
94
95 def ospec(self):
96 # TODO - this is for FPDivStage1Mod
97 return DivPipeInterstageData(self.pspec) # DIV ospec (loop)
98
99 def setup(self, m, i):
100 """ links module to inputs and outputs.
101
102 note: this is a pure *combinatorial* module (StageChain).
103 therefore each sub-module must also be combinatorial
104 """
105
106 divstages = []
107
108 # here is where the intermediary stages are added.
109 # n_stages is adjusted (in pipeline.py), reduced to take
110 # into account the extra processing that self.begin and self.end
111 # will add.
112 for count in range(self.n_stages): # number of combinatorial stages
113 idx = count + self.stage_offs
114 divstages.append(DivPipeCalculateStage(self.pspec, idx))
115
116 chain = StageChain(divstages)
117 chain.setup(m, i)
118
119 # output is from the last pipe stage
120 self.o = divstages[-1].o
121
122 def process(self, i):
123 return self.o
124
125 def action(self, m):
126 m.d.sync += self.m1o.eq(self.process(None))
127 m.next = "normalise_1"
128
129
130 class FPDivStagesFinal(FPState, SimpleHandshake):
131
132 def __init__(self, pspec, n_stages, stage_offs):
133 FPState.__init__(self, "divfinal")
134 self.pspec = pspec
135 self.n_stages = n_stages # number of combinatorial stages
136 self.stage_offs = stage_offs # each CalcStage needs *absolute* idx
137 SimpleHandshake.__init__(self, self) # pipeline is its own stage
138 self.m1o = self.ospec()
139
140 def ispec(self):
141 return DivPipeInterstageData(self.pspec) # DIV ispec (loop)
142
143 def ospec(self):
144 # REQUIRED. do NOT change.
145 return FPAddStage1Data(self.pspec) # to post-norm
146
147 def setup(self, m, i):
148 """ links module to inputs and outputs.
149
150 note: this is a pure *combinatorial* module (StageChain).
151 therefore each sub-module must also be combinatorial
152 """
153
154 # takes the DIV pipeline/chain data and munges it
155 # into the format that the normalisation can accept.
156
157 divstages = []
158
159 # here is where the intermediary stages are added.
160 # n_stages is adjusted (in pipeline.py), reduced to take
161 # into account the extra processing that self.begin and self.end
162 # will add.
163 for count in range(self.n_stages): # number of combinatorial stages
164 idx = count + self.stage_offs
165 divstages.append(DivPipeCalculateStage(pspec, idx))
166
167 # does the final conversion from intermediary to output data
168 divstages.append(DivPipeFinalStage(pspec))
169
170 # does conversion from DivPipeOutputData into
171 # FPAddStage1Data format (bad name, TODO, doesn't matter),
172 # so that post-normalisation and corrections can take over
173 divstages.append(FPDivStage2Mod(self.pspec))
174
175 chain = StageChain(divstages)
176 chain.setup(m, i)
177
178 # output is from the last pipe stage
179 self.o = divstages[-1].o
180
181 def process(self, i):
182 return self.o
183
184 def action(self, m):
185 m.d.sync += self.m1o.eq(self.process(None))
186 m.next = "normalise_1"
187
188