convert to DynamicPipe (default class in PipelineSpec: SimpleHandshake)
[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
11
12 from ieee754.pipeline import DynamicPipe
13 from ieee754.fpcommon.denorm import FPSCData
14 from ieee754.fpcommon.postcalc import FPAddStage1Data
15 from ieee754.div_rem_sqrt_rsqrt.div_pipe import (DivPipeInterstageData,
16 DivPipeSetupStage,
17 DivPipeCalculateStage,
18 DivPipeFinalStage,
19 )
20
21 # TODO: write these
22 from .div0 import FPDivStage0Mod
23 from .div2 import FPDivStage2Mod
24
25
26 class FPDivStagesSetup(DynamicPipe):
27
28 def __init__(self, pspec, n_stages, stage_offs):
29 self.pspec = pspec
30 self.n_stages = n_stages # number of combinatorial stages
31 self.stage_offs = stage_offs # each CalcStage needs *absolute* idx
32 super().__init__(pspec)
33
34 def ispec(self):
35 # REQUIRED. do NOT change.
36 return FPSCData(self.pspec, False) # from denorm
37
38 def ospec(self):
39 return DivPipeInterstageData(self.pspec) # DIV ospec (loop)
40
41 def setup(self, m, i):
42 """ links module to inputs and outputs.
43
44 note: this is a pure *combinatorial* module (StageChain).
45 therefore each sub-module must also be combinatorial
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
75 class FPDivStagesIntermediate(DynamicPipe):
76
77 def __init__(self, pspec, n_stages, stage_offs):
78 self.pspec = pspec
79 self.n_stages = n_stages # number of combinatorial stages
80 self.stage_offs = stage_offs # each CalcStage needs *absolute* idx
81 super().__init__(pspec)
82
83 def ispec(self):
84 # TODO - this is for FPDivStage1Mod
85 return DivPipeInterstageData(self.pspec) # DIV ispec (loop)
86
87 def ospec(self):
88 # TODO - this is for FPDivStage1Mod
89 return DivPipeInterstageData(self.pspec) # DIV ospec (loop)
90
91 def setup(self, m, i):
92 """ links module to inputs and outputs.
93
94 note: this is a pure *combinatorial* module (StageChain).
95 therefore each sub-module must also be combinatorial
96 """
97
98 divstages = []
99
100 # here is where the intermediary stages are added.
101 # n_stages is adjusted (in pipeline.py), reduced to take
102 # into account the extra processing that self.begin and self.end
103 # will add.
104 for count in range(self.n_stages): # number of combinatorial stages
105 idx = count + self.stage_offs
106 divstages.append(DivPipeCalculateStage(self.pspec, idx))
107
108 chain = StageChain(divstages)
109 chain.setup(m, i)
110
111 # output is from the last pipe stage
112 self.o = divstages[-1].o
113
114 def process(self, i):
115 return self.o
116
117
118 class FPDivStagesFinal(DynamicPipe):
119
120 def __init__(self, pspec, n_stages, stage_offs):
121 self.pspec = pspec
122 self.n_stages = n_stages # number of combinatorial stages
123 self.stage_offs = stage_offs # each CalcStage needs *absolute* idx
124 super().__init__(pspec)
125
126 def ispec(self):
127 return DivPipeInterstageData(self.pspec) # DIV ispec (loop)
128
129 def ospec(self):
130 # REQUIRED. do NOT change.
131 return FPAddStage1Data(self.pspec) # to post-norm
132
133 def setup(self, m, i):
134 """ links module to inputs and outputs.
135
136 note: this is a pure *combinatorial* module (StageChain).
137 therefore each sub-module must also be combinatorial
138 """
139
140 # takes the DIV pipeline/chain data and munges it
141 # into the format that the normalisation can accept.
142
143 divstages = []
144
145 # here is where the intermediary stages are added.
146 # n_stages is adjusted (in pipeline.py), reduced to take
147 # into account the extra processing that self.begin and self.end
148 # will add.
149 for count in range(self.n_stages): # number of combinatorial stages
150 idx = count + self.stage_offs
151 divstages.append(DivPipeCalculateStage(self.pspec, idx))
152
153 # does the final conversion from intermediary to output data
154 divstages.append(DivPipeFinalStage(self.pspec))
155
156 # does conversion from DivPipeOutputData into
157 # FPAddStage1Data format (bad name, TODO, doesn't matter),
158 # so that post-normalisation and corrections can take over
159 divstages.append(FPDivStage2Mod(self.pspec))
160
161 chain = StageChain(divstages)
162 chain.setup(m, i)
163
164 # output is from the last pipe stage
165 self.o = divstages[-1].o
166
167 def process(self, i):
168 return self.o