start also putting in additional DivPipe*Stage usage
[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):
25 FPState.__init__(self, "divsetup")
26 self.pspec = pspec
27 self.n_stages = n_stages # number of combinatorial stages
28 SimpleHandshake.__init__(self, self) # pipeline is its own stage
29 self.m1o = self.ospec()
30
31 def ispec(self):
32 # REQUIRED. do NOT change.
33 return FPSCData(self.pspec, False) # from denorm
34
35 def ospec(self):
36 return DivPipeInterstageData(self.pspec) # DIV ospec (loop)
37
38 def setup(self, m, i):
39 """ links module to inputs and outputs.
40
41 note: this is a pure *combinatorial* module (StageChain).
42 therefore each sub-module must also be combinatorial
43 (and not do too much: in particular, n_stages must be
44 reduced slightly when either self.end=True or self.begin=True)
45 """
46
47 divstages = []
48
49 # Converts from FPSCData into DivPipeInputData
50 divstages.append(FPDivStage0Mod(self.pspec))
51
52 # does 1 "convert" (actual processing) from DivPipeInputData
53 # into "intermediate" output (DivPipeInterstageData)
54 divstages.append(DivPipeSetupStage(self.pspec))
55
56 # here is where the intermediary stages are added.
57 # n_stages is adjusted (in pipeline.py), reduced to take
58 # into account the extra processing that self.begin and self.end
59 # will add.
60 for count in range(self.n_stages): # number of combinatorial stages
61 divstages.append(DivPipeCalculateStage(self.pspec, count))
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 FPDivStagesIntermediary(FPState, SimpleHandshake):
78
79 def __init__(self, pspec, n_stages):
80 FPState.__init__(self, "divintermediate")
81 self.pspec = pspec
82 self.n_stages = n_stages # number of combinatorial stages
83 SimpleHandshake.__init__(self, self) # pipeline is its own stage
84 self.m1o = self.ospec()
85
86 def ispec(self):
87 # TODO - this is for FPDivStage1Mod
88 return DivPipeInterstageData(self.pspec) # DIV ispec (loop)
89
90 def ospec(self):
91 # TODO - this is for FPDivStage1Mod
92 return DivPipeInterstageData(self.pspec) # DIV ospec (loop)
93
94 def setup(self, m, i):
95 """ links module to inputs and outputs.
96
97 note: this is a pure *combinatorial* module (StageChain).
98 therefore each sub-module must also be combinatorial
99 (and not do too much)
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 divstages.append(DivPipeCalculateStage(self.pspec, count))
110
111 chain = StageChain(divstages)
112 chain.setup(m, i)
113
114 # output is from the last pipe stage
115 self.o = divstages[-1].o
116
117 def process(self, i):
118 return self.o
119
120 def action(self, m):
121 m.d.sync += self.m1o.eq(self.process(None))
122 m.next = "normalise_1"
123
124
125 class FPDivStagesFinal(FPState, SimpleHandshake):
126
127 def __init__(self, pspec, n_stages):
128 FPState.__init__(self, "divfinal")
129 self.pspec = pspec
130 self.n_stages = n_stages # number of combinatorial stages
131 SimpleHandshake.__init__(self, self) # pipeline is its own stage
132 self.m1o = self.ospec()
133
134 def ispec(self):
135 # XXX TODO: replace with "intermediary" (?)
136 return DivPipeInterstageData(self.pspec) # DIV ispec (loop)
137
138 def ospec(self):
139 # REQUIRED. do NOT change.
140 return FPAddStage1Data(self.pspec) # to post-norm
141
142 def setup(self, m, i):
143 """ links module to inputs and outputs.
144
145 note: this is a pure *combinatorial* module (StageChain).
146 therefore each sub-module must also be combinatorial
147 (and not do too much)
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 divstages.append(DivPipeCalculateStage(pspec, count))
161
162 # does the final conversion from intermediary to output data
163 divstages.append(DivPipeFinalStage(pspec))
164
165 # does conversion from DivPipeOutputData into
166 # FPAddStage1Data format (bad name, TODO, doesn't matter),
167 # so that post-normalisation and corrections can take over
168 divstages.append(FPDivStage2Mod(self.pspec))
169
170 chain = StageChain(divstages)
171 chain.setup(m, i)
172
173 # output is from the last pipe stage
174 self.o = divstages[-1].o
175
176 def process(self, i):
177 return self.o
178
179 def action(self, m):
180 m.d.sync += self.m1o.eq(self.process(None))
181 m.next = "normalise_1"
182
183