2e38cd929fcddb38c9e30bcbe1864b4c127a3d9e
[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 return DivPipeInterstageData(self.pspec) # DIV ispec (loop)
102
103 def ospec(self):
104 # TODO - this is for FPDivStage1Mod
105 return DivPipeInterstageData(self.pspec) # DIV ospec (loop)
106
107 def setup(self, m, i):
108 """ links module to inputs and outputs.
109
110 note: this is a pure *combinatorial* module (StageChain).
111 therefore each sub-module must also be combinatorial
112 (and not do too much)
113 """
114
115 divstages = []
116
117 # here is where the intermediary stages are added.
118 # n_stages is adjusted (in pipeline.py), reduced to take
119 # into account the extra processing that self.begin and self.end
120 # will add.
121 for count in range(self.n_stages): # number of combinatorial stages
122 # XXX: this can actually be entirely dropped...
123 divstages.append(FPDivStage1Mod(self.pspec))
124
125 # ... and replaced with this.
126 # vvvvvvv
127 #divstages.append(DivPipeCalculateStage(core_config, count))
128 # ^^^^^^^
129
130 chain = StageChain(divstages)
131 chain.setup(m, i)
132
133 # output is from the last pipe stage
134 self.o = divstages[-1].o
135
136 def process(self, i):
137 return self.o
138
139 def action(self, m):
140 m.d.sync += self.m1o.eq(self.process(None))
141 m.next = "normalise_1"
142
143
144 class FPDivStagesFinal(FPState, SimpleHandshake):
145
146 def __init__(self, pspec, n_stages):
147 FPState.__init__(self, "divfinal")
148 self.pspec = pspec
149 self.n_stages = n_stages # number of combinatorial stages
150 SimpleHandshake.__init__(self, self) # pipeline is its own stage
151 self.m1o = self.ospec()
152
153 def ispec(self):
154 # XXX TODO: replace with "intermediary" (DivPipeInterstageData?)
155 return FPDivStage0Data(self.pspec) # DIV ispec (loop)
156
157 def ospec(self):
158 # REQUIRED. do NOT change.
159 return FPAddStage1Data(self.pspec) # to post-norm
160
161 def setup(self, m, i):
162 """ links module to inputs and outputs.
163
164 note: this is a pure *combinatorial* module (StageChain).
165 therefore each sub-module must also be combinatorial
166 (and not do too much)
167 """
168
169 # takes the DIV pipeline/chain data and munges it
170 # into the format that the normalisation can accept.
171
172 divstages = []
173
174 # here is where the intermediary stages are added.
175 # n_stages is adjusted (in pipeline.py), reduced to take
176 # into account the extra processing that self.begin and self.end
177 # will add.
178 for count in range(self.n_stages): # number of combinatorial stages
179 # XXX: this can actually be entirely dropped...
180 divstages.append(FPDivStage1Mod(self.pspec))
181
182 # ... and replaced with this.
183 # vvvvvvv
184 #divstages.append(DivPipeCalculateStage(core_config, count))
185 # ^^^^^^^
186
187 # does the final conversion from intermediary to output data
188 # vvvvvvv
189 # FIXME divstages.append(DivPipeFinalStage(something))
190 # ^^^^^^^
191
192 # does conversion from DivPipeOutputData into
193 # FPAddStage1Data format (bad name, TODO, doesn't matter),
194 # so that post-normalisation and corrections can take over
195 divstages.append(FPDivStage2Mod(self.pspec))
196
197 chain = StageChain(divstages)
198 chain.setup(m, i)
199
200 # output is from the last pipe stage
201 self.o = divstages[-1].o
202
203 def process(self, i):
204 return self.o
205
206 def action(self, m):
207 m.d.sync += self.m1o.eq(self.process(None))
208 m.next = "normalise_1"
209
210