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