b0c539f9805e94080c0713fd83f76fd6739101cc
[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
16 # TODO: write these
17 from .div0 import FPDivStage0Mod
18 from .div1 import FPDivStage1Mod # can be dropped entirely
19 # (replaced with DivPipeCalculateStage)
20 # note, yes, DivPipeCalculateStage *NOT*
21 # DivPipeCoreCalculateStage
22 from .div2 import FPDivStage2Mod
23 from .div0 import FPDivStage0Data
24
25
26 class FPDivStagesSetup(FPState, SimpleHandshake):
27
28 def __init__(self, width, pspec, n_stages):
29 FPState.__init__(self, "divsetup")
30 self.width = width
31 self.pspec = pspec
32 self.n_stages = n_stages # number of combinatorial stages
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.width, self.pspec, False) # from denorm
39
40 def ospec(self):
41 # XXX TODO: replace with "intermediary" (DivPipeInterstageData)
42 return FPDivStage0Data(self.width, self.pspec) # DIV ospec (loop)
43
44 def setup(self, m, i):
45 """ links module to inputs and outputs.
46
47 note: this is a pure *combinatorial* module (StageChain).
48 therefore each sub-module must also be combinatorial
49 (and not do too much: in particular, n_stages must be
50 reduced slightly when either self.end=True or self.begin=True)
51 """
52
53 divstages = []
54
55 # Converts from FPSCData into DivPipeInputData
56 divstages.append(FPDivStage0Mod(self.width, self.pspec))
57
58 # does 1 "convert" (actual processing) from DivPipeInputData
59 # into "intermediate" output (DivPipeInterstageData)
60 # vvvvvvv
61 # FIXME divstages.append(DivPipeSetupStage(something))
62 # ^^^^^^^
63
64 # here is where the intermediary stages are added.
65 # n_stages is adjusted (in pipeline.py), reduced to take
66 # into account the extra processing that self.begin and self.end
67 # will add.
68 for count in range(self.n_stages): # number of combinatorial stages
69 # XXX: this can actually be entirely dropped...
70 divstages.append(FPDivStage1Mod(self.width, self.pspec))
71
72 # ... and replaced with this.
73 # vvvvvvv
74 #divstages.append(DivPipeCalculateStage(core_config, count))
75 # ^^^^^^^
76
77 chain = StageChain(divstages)
78 chain.setup(m, i)
79
80 # output is from the last pipe stage
81 self.o = divstages[-1].o
82
83 def process(self, i):
84 return self.o
85
86 def action(self, m):
87 m.d.sync += self.m1o.eq(self.process(None))
88 m.next = "normalise_1"
89
90
91 class FPDivStagesIntermediary(FPState, SimpleHandshake):
92
93 def __init__(self, width, pspec, n_stages):
94 FPState.__init__(self, "divintermediate")
95 self.width = width
96 self.pspec = pspec
97 self.n_stages = n_stages # number of combinatorial stages
98 self.begin = begin # "begin" mode
99 self.end = end # "end" mode
100 SimpleHandshake.__init__(self, self) # pipeline is its own stage
101 self.m1o = self.ospec()
102
103 def ispec(self):
104 # TODO - this is for FPDivStage1Mod
105 # XXX TODO: replace with "intermediary" (DivPipeInterstageData)
106 return FPDivStage0Data(self.width, self.pspec) # DIV ispec (loop)
107
108 def ospec(self):
109 # TODO - this is for FPDivStage1Mod
110 # XXX TODO: replace with "intermediary" (DivPipeInterstageData)
111 return FPDivStage0Data(self.width, self.pspec) # DIV ospec (loop)
112
113 def setup(self, m, i):
114 """ links module to inputs and outputs.
115
116 note: this is a pure *combinatorial* module (StageChain).
117 therefore each sub-module must also be combinatorial
118 (and not do too much)
119 """
120
121 divstages = []
122
123 # here is where the intermediary stages are added.
124 # n_stages is adjusted (in pipeline.py), reduced to take
125 # into account the extra processing that self.begin and self.end
126 # will add.
127 for count in range(self.n_stages): # number of combinatorial stages
128 # XXX: this can actually be entirely dropped...
129 divstages.append(FPDivStage1Mod(self.width, self.pspec))
130
131 # ... and replaced with this.
132 # vvvvvvv
133 #divstages.append(DivPipeCalculateStage(core_config, count))
134 # ^^^^^^^
135
136 chain = StageChain(divstages)
137 chain.setup(m, i)
138
139 # output is from the last pipe stage
140 self.o = divstages[-1].o
141
142 def process(self, i):
143 return self.o
144
145 def action(self, m):
146 m.d.sync += self.m1o.eq(self.process(None))
147 m.next = "normalise_1"
148
149
150 class FPDivStagesFinal(FPState, SimpleHandshake):
151
152 def __init__(self, width, pspec, n_stages):
153 FPState.__init__(self, "divfinal")
154 self.width = width
155 self.pspec = pspec
156 self.n_stages = n_stages # number of combinatorial stages
157 SimpleHandshake.__init__(self, self) # pipeline is its own stage
158 self.m1o = self.ospec()
159
160 def ispec(self):
161 # XXX TODO: replace with "intermediary" (DivPipeInterstageData?)
162 return FPDivStage0Data(self.width, self.pspec) # DIV ispec (loop)
163
164 def ospec(self):
165 # REQUIRED. do NOT change.
166 return FPAddStage1Data(self.width, self.pspec) # to post-norm
167
168 def setup(self, m, i):
169 """ links module to inputs and outputs.
170
171 note: this is a pure *combinatorial* module (StageChain).
172 therefore each sub-module must also be combinatorial
173 (and not do too much)
174 """
175
176 # takes the DIV pipeline/chain data and munges it
177 # into the format that the normalisation can accept.
178
179 divstages = []
180
181 # here is where the intermediary stages are added.
182 # n_stages is adjusted (in pipeline.py), reduced to take
183 # into account the extra processing that self.begin and self.end
184 # will add.
185 for count in range(self.n_stages): # number of combinatorial stages
186 # XXX: this can actually be entirely dropped...
187 divstages.append(FPDivStage1Mod(self.width, self.pspec))
188
189 # ... and replaced with this.
190 # vvvvvvv
191 #divstages.append(DivPipeCalculateStage(core_config, count))
192 # ^^^^^^^
193
194 # does the final conversion from intermediary to output data
195 # vvvvvvv
196 # FIXME divstages.append(DivPipeFinalStage(something))
197 # ^^^^^^^
198
199 # does conversion from DivPipeOutputData into
200 # FPAddStage1Data format (bad name, TODO, doesn't matter),
201 # so that post-normalisation and corrections can take over
202 divstages.append(FPDivStage2Mod(self.width, self.pspec))
203
204 chain = StageChain(divstages)
205 chain.setup(m, i)
206
207 # output is from the last pipe stage
208 self.o = divstages[-1].o
209
210 def process(self, i):
211 return self.o
212
213 def action(self, m):
214 m.d.sync += self.m1o.eq(self.process(None))
215 m.next = "normalise_1"
216
217