add an absolute count on the stages
[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 .div2 import FPDivStage2Mod
19 from .div0 import FPDivStage0Data
20
21
22 class FPDivStagesSetup(FPState, SimpleHandshake):
23
24 def __init__(self, pspec, n_stages, stage_offs):
25 FPState.__init__(self, "divsetup")
26 self.pspec = pspec
27 self.n_stages = n_stages # number of combinatorial stages
28 self.stage_offs = stage_offs # each CalcStage needs *absolute* idx
29 SimpleHandshake.__init__(self, self) # pipeline is its own stage
30 self.m1o = self.ospec()
31
32 def ispec(self):
33 # REQUIRED. do NOT change.
34 return FPSCData(self.pspec, False) # from denorm
35
36 def ospec(self):
37 return DivPipeInterstageData(self.pspec) # DIV ospec (loop)
38
39 def setup(self, m, i):
40 """ links module to inputs and outputs.
41
42 note: this is a pure *combinatorial* module (StageChain).
43 therefore each sub-module must also be combinatorial
44 (and not do too much: in particular, n_stages must be
45 reduced slightly when either self.end=True or self.begin=True)
46 """
47
48 divstages = []
49
50 # Converts from FPSCData into DivPipeInputData
51 divstages.append(FPDivStage0Mod(self.pspec))
52
53 # does 1 "convert" (actual processing) from DivPipeInputData
54 # into "intermediate" output (DivPipeInterstageData)
55 divstages.append(DivPipeSetupStage(self.pspec))
56
57 # here is where the intermediary stages are added.
58 # n_stages is adjusted (by pipeline.py), reduced to take
59 # into account extra processing that FPDivStage0Mod and DivPipeSetup
60 # might add.
61 for count in range(self.n_stages): # number of combinatorial stages
62 idx = count + self.stage_offs
63 divstages.append(DivPipeCalculateStage(self.pspec, idx))
64
65 chain = StageChain(divstages)
66 chain.setup(m, i)
67
68 # output is from the last pipe stage
69 self.o = divstages[-1].o
70
71 def process(self, i):
72 return self.o
73
74 def action(self, m):
75 m.d.sync += self.m1o.eq(self.process(None))
76 m.next = "normalise_1"
77
78
79 class FPDivStagesIntermediary(FPState, SimpleHandshake):
80
81 def __init__(self, pspec, n_stages, stage_offs):
82 FPState.__init__(self, "divintermediate")
83 self.pspec = pspec
84 self.n_stages = n_stages # number of combinatorial stages
85 self.stage_offs = stage_offs # each CalcStage needs *absolute* idx
86 SimpleHandshake.__init__(self, self) # pipeline is its own stage
87 self.m1o = self.ospec()
88
89 def ispec(self):
90 # TODO - this is for FPDivStage1Mod
91 return DivPipeInterstageData(self.pspec) # DIV ispec (loop)
92
93 def ospec(self):
94 # TODO - this is for FPDivStage1Mod
95 return DivPipeInterstageData(self.pspec) # DIV ospec (loop)
96
97 def setup(self, m, i):
98 """ links module to inputs and outputs.
99
100 note: this is a pure *combinatorial* module (StageChain).
101 therefore each sub-module must also be combinatorial
102 (and not do too much)
103 """
104
105 divstages = []
106
107 # here is where the intermediary stages are added.
108 # n_stages is adjusted (in pipeline.py), reduced to take
109 # into account the extra processing that self.begin and self.end
110 # will add.
111 for count in range(self.n_stages): # number of combinatorial stages
112 idx = count + self.stage_offs
113 divstages.append(DivPipeCalculateStage(self.pspec, idx))
114
115 chain = StageChain(divstages)
116 chain.setup(m, i)
117
118 # output is from the last pipe stage
119 self.o = divstages[-1].o
120
121 def process(self, i):
122 return self.o
123
124 def action(self, m):
125 m.d.sync += self.m1o.eq(self.process(None))
126 m.next = "normalise_1"
127
128
129 class FPDivStagesFinal(FPState, SimpleHandshake):
130
131 def __init__(self, pspec, n_stages, stage_offs):
132 FPState.__init__(self, "divfinal")
133 self.pspec = pspec
134 self.n_stages = n_stages # number of combinatorial stages
135 self.stage_offs = stage_offs # each CalcStage needs *absolute* idx
136 SimpleHandshake.__init__(self, self) # pipeline is its own stage
137 self.m1o = self.ospec()
138
139 def ispec(self):
140 return DivPipeInterstageData(self.pspec) # DIV ispec (loop)
141
142 def ospec(self):
143 # REQUIRED. do NOT change.
144 return FPAddStage1Data(self.pspec) # to post-norm
145
146 def setup(self, m, i):
147 """ links module to inputs and outputs.
148
149 note: this is a pure *combinatorial* module (StageChain).
150 therefore each sub-module must also be combinatorial
151 (and not do too much)
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