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