fix imports
[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 """
45
46 divstages = []
47
48 # Converts from FPSCData into DivPipeInputData
49 divstages.append(FPDivStage0Mod(self.pspec))
50
51 # does 1 "convert" (actual processing) from DivPipeInputData
52 # into "intermediate" output (DivPipeInterstageData)
53 divstages.append(DivPipeSetupStage(self.pspec))
54
55 # here is where the intermediary stages are added.
56 # n_stages is adjusted (by pipeline.py), reduced to take
57 # into account extra processing that FPDivStage0Mod and DivPipeSetup
58 # might add.
59 for count in range(self.n_stages): # number of combinatorial stages
60 idx = count + self.stage_offs
61 divstages.append(DivPipeCalculateStage(self.pspec, idx))
62
63 chain = StageChain(divstages)
64 chain.setup(m, i)
65
66 # output is from the last pipe stage
67 self.o = divstages[-1].o
68
69 def process(self, i):
70 return self.o
71
72 def action(self, m):
73 m.d.sync += self.m1o.eq(self.process(None))
74 m.next = "normalise_1"
75
76
77 class FPDivStagesIntermediate(FPState, SimpleHandshake):
78
79 def __init__(self, pspec, n_stages, stage_offs):
80 FPState.__init__(self, "divintermediate")
81 self.pspec = pspec
82 self.n_stages = n_stages # number of combinatorial stages
83 self.stage_offs = stage_offs # each CalcStage needs *absolute* idx
84 SimpleHandshake.__init__(self, self) # pipeline is its own stage
85 self.m1o = self.ospec()
86
87 def ispec(self):
88 # TODO - this is for FPDivStage1Mod
89 return DivPipeInterstageData(self.pspec) # DIV ispec (loop)
90
91 def ospec(self):
92 # TODO - this is for FPDivStage1Mod
93 return DivPipeInterstageData(self.pspec) # DIV ospec (loop)
94
95 def setup(self, m, i):
96 """ links module to inputs and outputs.
97
98 note: this is a pure *combinatorial* module (StageChain).
99 therefore each sub-module must also be combinatorial
100 """
101
102 divstages = []
103
104 # here is where the intermediary stages are added.
105 # n_stages is adjusted (in pipeline.py), reduced to take
106 # into account the extra processing that self.begin and self.end
107 # will add.
108 for count in range(self.n_stages): # number of combinatorial stages
109 idx = count + self.stage_offs
110 divstages.append(DivPipeCalculateStage(self.pspec, idx))
111
112 chain = StageChain(divstages)
113 chain.setup(m, i)
114
115 # output is from the last pipe stage
116 self.o = divstages[-1].o
117
118 def process(self, i):
119 return self.o
120
121 def action(self, m):
122 m.d.sync += self.m1o.eq(self.process(None))
123 m.next = "normalise_1"
124
125
126 class FPDivStagesFinal(FPState, SimpleHandshake):
127
128 def __init__(self, pspec, n_stages, stage_offs):
129 FPState.__init__(self, "divfinal")
130 self.pspec = pspec
131 self.n_stages = n_stages # number of combinatorial stages
132 self.stage_offs = stage_offs # each CalcStage needs *absolute* idx
133 SimpleHandshake.__init__(self, self) # pipeline is its own stage
134 self.m1o = self.ospec()
135
136 def ispec(self):
137 return DivPipeInterstageData(self.pspec) # DIV ispec (loop)
138
139 def ospec(self):
140 # REQUIRED. do NOT change.
141 return FPAddStage1Data(self.pspec) # to post-norm
142
143 def setup(self, m, i):
144 """ links module to inputs and outputs.
145
146 note: this is a pure *combinatorial* module (StageChain).
147 therefore each sub-module must also be combinatorial
148 """
149
150 # takes the DIV pipeline/chain data and munges it
151 # into the format that the normalisation can accept.
152
153 divstages = []
154
155 # here is where the intermediary stages are added.
156 # n_stages is adjusted (in pipeline.py), reduced to take
157 # into account the extra processing that self.begin and self.end
158 # will add.
159 for count in range(self.n_stages): # number of combinatorial stages
160 idx = count + self.stage_offs
161 divstages.append(DivPipeCalculateStage(pspec, idx))
162
163 # does the final conversion from intermediary to output data
164 divstages.append(DivPipeFinalStage(pspec))
165
166 # does conversion from DivPipeOutputData into
167 # FPAddStage1Data format (bad name, TODO, doesn't matter),
168 # so that post-normalisation and corrections can take over
169 divstages.append(FPDivStage2Mod(self.pspec))
170
171 chain = StageChain(divstages)
172 chain.setup(m, i)
173
174 # output is from the last pipe stage
175 self.o = divstages[-1].o
176
177 def process(self, i):
178 return self.o
179
180 def action(self, m):
181 m.d.sync += self.m1o.eq(self.process(None))
182 m.next = "normalise_1"
183
184