fix imports
[ieee754fpu.git] / src / ieee754 / div_rem_sqrt_rsqrt / div_pipe.py
1 # SPDX-License-Identifier: LGPL-2.1-or-later
2 # See Notices.txt for copyright information
3 """ div/rem/sqrt/rsqrt pipeline. """
4
5 from ieee754.div_rem_sqrt_rsqrt.core import (DivPipeCoreConfig,
6 DivPipeCoreInputData,
7 DivPipeCoreInterstageData,
8 DivPipeCoreOutputData,
9 DivPipeCoreSetupStage,
10 DivPipeCoreCalculateStage,
11 DivPipeCoreFinalStage,
12 )
13 from ieee754.fpcommon.getop import FPPipeContext
14 from ieee754.fpcommon.fpbase import FPFormat, FPNumBaseRecord
15
16
17 class DivPipeConfig:
18 """ Configuration for the div/rem/sqrt/rsqrt pipeline.
19
20 :attribute pspec: ``PipelineSpec`` instance
21 :attribute core_config: the ``DivPipeCoreConfig`` instance.
22 """
23
24 def __init__(self, pspec, log2_radix=3):
25 """ Create a ``DivPipeConfig`` instance. """
26 self.pspec = pspec
27 bit_width = pspec.width
28 fract_width = FPFormat.standard(bit_width).fraction_width
29 self.core_config = DivPipeCoreConfig(bit_width,
30 fract_width,
31 log2_radix)
32
33
34 class DivPipeBaseData:
35 """ input data base type for ``DivPipe``.
36
37 :attribute z: a convenient way to carry the sign and exponent through
38 the pipeline from when they were computed right at the
39 start.
40 :attribute out_do_z: FIXME: document
41 :attribute oz: FIXME: document
42 :attribute ctx: FIXME: document
43 :attribute muxid:
44 FIXME: document
45 Alias of ``ctx.muxid``.
46 :attribute config: the ``DivPipeConfig`` instance.
47 """
48
49 def __init__(self, config):
50 """ Create a ``DivPipeBaseData`` instance. """
51 self.config = config
52 width = config.pspec.width
53 self.z = FPNumBaseRecord(width, False) # s and e carried: m ignored
54 self.out_do_z = Signal(reset_less=True)
55 self.oz = Signal(width, reset_less=True)
56
57 self.ctx = FPPipeContext(config.pspec) # context: muxid, operator etc.
58 # FIXME: add proper muxid explanation somewhere and refer to it here
59 self.muxid = self.ctx.muxid # annoying. complicated.
60
61 def __iter__(self):
62 """ Get member signals. """
63 yield from self.z
64 yield self.out_do_z
65 yield self.oz
66 yield from self.ctx
67
68 def eq(self, rhs):
69 """ Assign member signals. """
70 return [self.z.eq(rhs.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz),
71 self.ctx.eq(i.ctx)]
72
73
74 class DivPipeInputData(DivPipeCoreInputData, DivPipeBaseData):
75 """ input data type for ``DivPipe``. """
76
77 def __init__(self, config):
78 """ Create a ``DivPipeInputData`` instance. """
79 DivPipeCoreInputData.__init__(self, config.core_config)
80 DivPipeBaseData.__init__(self, config)
81
82 def __iter__(self):
83 """ Get member signals. """
84 yield from DivPipeCoreInputData.__iter__(self)
85 yield from DivPipeBaseData.__iter__(self)
86
87 def eq(self, rhs):
88 """ Assign member signals. """
89 return DivPipeCoreInputData.eq(self, rhs) + \
90 DivPipeBaseData.eq(self, rhs)
91
92
93 class DivPipeInterstageData(DivPipeCoreInterstageData, DivPipeBaseData):
94 """ interstage data type for ``DivPipe``. """
95
96 def __init__(self, config):
97 """ Create a ``DivPipeInterstageData`` instance. """
98 DivPipeCoreInterstageData.__init__(self, config.core_config)
99 DivPipeBaseData.__init__(self, config)
100
101 def __iter__(self):
102 """ Get member signals. """
103 yield from DivPipeCoreInterstageData.__iter__(self)
104 yield from DivPipeBaseData.__iter__(self)
105
106 def eq(self, rhs):
107 """ Assign member signals. """
108 return DivPipeCoreInterstageData.eq(self, rhs) + \
109 DivPipeBaseData.eq(self, rhs)
110
111
112 class DivPipeOutputData(DivPipeCoreOutputData, DivPipeBaseData):
113 """ output data type for ``DivPipe``. """
114
115 def __init__(self, config):
116 """ Create a ``DivPipeOutputData`` instance. """
117 DivPipeCoreOutputData.__init__(self, config.core_config)
118 DivPipeBaseData.__init__(self, config)
119
120 def __iter__(self):
121 """ Get member signals. """
122 yield from DivPipeCoreOutputData.__iter__(self)
123 yield from DivPipeBaseData.__iter__(self)
124
125 def eq(self, rhs):
126 """ Assign member signals. """
127 return DivPipeCoreOutputData.eq(self, rhs) + \
128 DivPipeBaseData.eq(self, rhs)
129
130
131 class DivPipeBaseStage:
132 """ Base Mix-in for DivPipe*Stage. """
133
134 def _elaborate(self, m, platform):
135 m.d.comb += self.o.z.eq(self.i.z)
136 m.d.comb += self.o.oz.eq(self.i.oz)
137 m.d.comb += self.o.out_do_z.eq(self.i.out_do_z)
138 m.d.comb += self.o.ctx.eq(self.i.ctx)
139
140 def get_core_config(self):
141 m_width = self.pspec.m_width # mantissa width
142 # 4 extra bits on the mantissa: MSB is zero, MSB-1 is 1
143 # then there is guard and round at the LSB end
144 return DivPipeCoreConfig(m_width+4, 0, log_radix=2)
145
146
147 class DivPipeSetupStage(DivPipeBaseStage, DivPipeCoreSetupStage):
148
149 def __init__(self, pspec):
150 DivPipeCoreSetupStage.__init__(self.get_core_config())
151 self.pspec = pspec
152
153 def elaborate(self, platform):
154 m = DivPipeCoreSetupStage(platform) # XXX TODO: out_do_z logic!
155 self._elaborate(m, platform)
156 return m
157
158
159 class DivPipeCalculateStage(DivPipeBaseStage, DivPipeCoreCalculateStage):
160
161 def __init__(self, pspec, stage_index):
162 DivPipeCoreCalculateStage.__init__(self.get_core_config(), stage_index)
163 self.pspec = pspec
164
165 def elaborate(self, platform):
166 m = DivPipeCoreCalculateStage(platform) # XXX TODO: out_do_z logic!
167 self._elaborate(m, platform)
168 return m
169
170
171 class DivPipeFinalStage(DivPipeBaseStage, DivPipeCoreFinalStage):
172
173 def __init__(self, pspec, stage_index):
174 DivPipeCoreFinalStage.__init__(self.get_core_config(), stage_index)
175 self.pspec = pspec
176
177 def elaborate(self, platform):
178 m = DivPipeCoreCalculateStage(platform) # XXX TODO: out_do_z logic!
179 self._elaborate(m, platform)
180 return m
181