196d158a00f63ccf2c919051da1cfca4e2442203
1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
5 from nmigen
import Module
, Signal
, Cat
, Mux
, Elaboratable
6 from nmigen
.cli
import main
, verilog
9 from ieee754
.fpcommon
.fpbase
import (Overflow
, OverflowMod
,
10 FPNumBase
, FPNumBaseRecord
)
11 from ieee754
.fpcommon
.fpbase
import MultiShiftRMerge
12 from ieee754
.fpcommon
.fpbase
import FPState
13 from ieee754
.fpcommon
.getop
import FPPipeContext
14 from ieee754
.fpcommon
.msbhigh
import FPMSBHigh
15 from .postcalc
import FPAddStage1Data
20 def __init__(self
, pspec
):
22 self
.roundz
= Signal(reset_less
=True, name
="norm1_roundz")
23 self
.z
= FPNumBaseRecord(width
, False)
24 self
.out_do_z
= Signal(reset_less
=True)
25 self
.oz
= Signal(width
, reset_less
=True)
26 self
.ctx
= FPPipeContext(pspec
)
27 self
.muxid
= self
.ctx
.muxid
30 ret
= [self
.z
.eq(i
.z
), self
.out_do_z
.eq(i
.out_do_z
), self
.oz
.eq(i
.oz
),
31 self
.roundz
.eq(i
.roundz
), self
.ctx
.eq(i
.ctx
)]
35 class FPNorm1ModSingle(Elaboratable
):
37 def __init__(self
, pspec
, e_extra
=False):
39 self
.e_extra
= e_extra
44 return FPAddStage1Data(self
.pspec
, e_extra
=self
.e_extra
)
47 return FPNorm1Data(self
.pspec
)
49 def setup(self
, m
, i
):
50 """ links module to inputs and outputs
52 m
.submodules
.normalise_1
= self
53 m
.d
.comb
+= self
.i
.eq(i
)
58 def elaborate(self
, platform
):
61 of
= OverflowMod("norm1of_")
63 #m.submodules.norm1_out_z = self.o.z
64 m
.submodules
.norm1_out_overflow
= of
65 #m.submodules.norm1_in_z = self.i.z
66 #m.submodules.norm1_in_overflow = self.i.of
69 i
.of
.guard
.name
= "norm1_i_of_guard"
70 i
.of
.round_bit
.name
= "norm1_i_of_roundbit"
71 i
.of
.sticky
.name
= "norm1_i_of_sticky"
72 i
.of
.m0
.name
= "norm1_i_of_m0"
73 m
.submodules
.norm1_insel_z
= insel_z
= FPNumBase(i
.z
)
74 #m.submodules.norm1_insel_overflow = iof = OverflowMod("iof")
76 espec
= (len(insel_z
.e
), True)
77 mwid
= self
.o
.z
.m_width
+2
79 ediff_n126
= Signal(espec
, reset_less
=True)
80 msr
= MultiShiftRMerge(mwid
+2, espec
)
81 m
.submodules
.multishift_r
= msr
83 msb
= FPMSBHigh(mwid
+1, espec
[0], True)
84 m
.submodules
.norm_msb
= msb
86 m
.d
.comb
+= i
.eq(self
.i
)
87 # initialise out from in (overridden below)
88 m
.d
.comb
+= self
.o
.z
.eq(insel_z
)
89 m
.d
.comb
+= Overflow
.eq(of
, i
.of
)
90 # normalisation increase/decrease conditions
91 decrease
= Signal(reset_less
=True)
92 increase
= Signal(reset_less
=True)
93 m
.d
.comb
+= decrease
.eq(insel_z
.m_msbzero
& insel_z
.exp_gt_n126
)
94 m
.d
.comb
+= increase
.eq(insel_z
.exp_lt_n126
)
96 with m
.If(~self
.i
.out_do_z
):
98 # make sure that the amount to decrease by does NOT
99 # go below the minimum non-INF/NaN exponent
100 m
.d
.comb
+= msb
.limclz
.eq(insel_z
.exp_sub_n126
)
102 # cat round and guard bits back into the mantissa
103 msb
.m_in
.eq(Cat(i
.of
.sticky
, i
.of
.round_bit
, i
.of
.guard
,
105 msb
.e_in
.eq(insel_z
.e
),
106 self
.o
.z
.e
.eq(msb
.e_out
),
107 self
.o
.z
.m
.eq(msb
.m_out
[3:]), # exclude bits 0&1
108 of
.m0
.eq(msb
.m_out
[3]), # copy of mantissa[0]
109 # overflow in bits 0..1: got shifted too (leave sticky)
110 of
.guard
.eq(msb
.m_out
[2]), # guard
111 of
.round_bit
.eq(msb
.m_out
[1]), # round
114 with m
.Elif(increase
):
115 temp_m
= Signal(mwid
+1, reset_less
=True)
117 temp_m
.eq(Cat(i
.of
.sticky
, i
.of
.round_bit
, i
.of
.guard
,
119 ediff_n126
.eq(insel_z
.fp
.N126
- insel_z
.e
),
120 # connect multi-shifter to inp/out mantissa (and ediff)
122 msr
.diff
.eq(ediff_n126
),
123 self
.o
.z
.m
.eq(msr
.m
[3:]),
124 of
.m0
.eq(msr
.m
[3]), # copy of mantissa[0]
125 # overflow in bits 0..1: got shifted too (leave sticky)
126 of
.guard
.eq(msr
.m
[2]), # guard
127 of
.round_bit
.eq(msr
.m
[1]), # round
128 of
.sticky
.eq(msr
.m
[0]), # sticky
129 self
.o
.z
.e
.eq(insel_z
.e
+ ediff_n126
),
132 m
.d
.comb
+= self
.o
.roundz
.eq(of
.roundz_out
)
133 m
.d
.comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)
134 m
.d
.comb
+= self
.o
.out_do_z
.eq(self
.i
.out_do_z
)
135 m
.d
.comb
+= self
.o
.oz
.eq(self
.i
.oz
)
140 class FPNorm1ModMulti
:
142 def __init__(self
, pspec
, single_cycle
=True):
144 self
.in_select
= Signal(reset_less
=True)
145 self
.in_z
= FPNumBase(width
, False)
146 self
.in_of
= Overflow()
147 self
.temp_z
= FPNumBase(width
, False)
148 self
.temp_of
= Overflow()
149 self
.out_z
= FPNumBase(width
, False)
150 self
.out_of
= Overflow()
152 def elaborate(self
, platform
):
155 m
.submodules
.norm1_out_z
= self
.out_z
156 m
.submodules
.norm1_out_overflow
= self
.out_of
157 m
.submodules
.norm1_temp_z
= self
.temp_z
158 m
.submodules
.norm1_temp_of
= self
.temp_of
159 m
.submodules
.norm1_in_z
= self
.in_z
160 m
.submodules
.norm1_in_overflow
= self
.in_of
162 in_z
= FPNumBase(self
.width
, False)
164 m
.submodules
.norm1_insel_z
= in_z
165 m
.submodules
.norm1_insel_overflow
= in_of
167 # select which of temp or in z/of to use
168 with m
.If(self
.in_select
):
169 m
.d
.comb
+= in_z
.eq(self
.in_z
)
170 m
.d
.comb
+= in_of
.eq(self
.in_of
)
172 m
.d
.comb
+= in_z
.eq(self
.temp_z
)
173 m
.d
.comb
+= in_of
.eq(self
.temp_of
)
174 # initialise out from in (overridden below)
175 m
.d
.comb
+= self
.out_z
.eq(in_z
)
176 m
.d
.comb
+= self
.out_of
.eq(in_of
)
177 # normalisation increase/decrease conditions
178 decrease
= Signal(reset_less
=True)
179 increase
= Signal(reset_less
=True)
180 m
.d
.comb
+= decrease
.eq(in_z
.m_msbzero
& in_z
.exp_gt_n126
)
181 m
.d
.comb
+= increase
.eq(in_z
.exp_lt_n126
)
182 m
.d
.comb
+= self
.out_norm
.eq(decrease | increase
) # loop-end
186 self
.out_z
.e
.eq(in_z
.e
- 1), # DECREASE exponent
187 self
.out_z
.m
.eq(in_z
.m
<< 1), # shift mantissa UP
188 self
.out_z
.m
[0].eq(in_of
.guard
), # steal guard (was tot[2])
189 self
.out_of
.guard
.eq(in_of
.round_bit
), # round (was tot[1])
190 self
.out_of
.round_bit
.eq(0), # reset round bit
191 self
.out_of
.m0
.eq(in_of
.guard
),
194 with m
.Elif(increase
):
196 self
.out_z
.e
.eq(in_z
.e
+ 1), # INCREASE exponent
197 self
.out_z
.m
.eq(in_z
.m
>> 1), # shift mantissa DOWN
198 self
.out_of
.guard
.eq(in_z
.m
[0]),
199 self
.out_of
.m0
.eq(in_z
.m
[1]),
200 self
.out_of
.round_bit
.eq(in_of
.guard
),
201 self
.out_of
.sticky
.eq(in_of
.sticky | in_of
.round_bit
)
207 class FPNorm1Single(FPState
):
209 def __init__(self
, width
, id_wid
, single_cycle
=True):
210 FPState
.__init
__(self
, "normalise_1")
211 self
.mod
= FPNorm1ModSingle(width
)
212 self
.o
= self
.ospec()
213 self
.out_z
= FPNumBase(width
, False)
214 self
.out_roundz
= Signal(reset_less
=True)
217 return self
.mod
.ispec()
220 return self
.mod
.ospec()
222 def setup(self
, m
, i
):
223 """ links module to inputs and outputs
231 class FPNorm1Multi(FPState
):
233 def __init__(self
, width
, id_wid
):
234 FPState
.__init
__(self
, "normalise_1")
235 self
.mod
= FPNorm1ModMulti(width
)
236 self
.stb
= Signal(reset_less
=True)
237 self
.ack
= Signal(reset
=0, reset_less
=True)
238 self
.out_norm
= Signal(reset_less
=True)
239 self
.in_accept
= Signal(reset_less
=True)
240 self
.temp_z
= FPNumBase(width
)
241 self
.temp_of
= Overflow()
242 self
.out_z
= FPNumBase(width
)
243 self
.out_roundz
= Signal(reset_less
=True)
245 def setup(self
, m
, in_z
, in_of
, norm_stb
):
246 """ links module to inputs and outputs
248 self
.mod
.setup(m
, in_z
, in_of
, norm_stb
,
249 self
.in_accept
, self
.temp_z
, self
.temp_of
,
250 self
.out_z
, self
.out_norm
)
252 m
.d
.comb
+= self
.stb
.eq(norm_stb
)
253 m
.d
.sync
+= self
.ack
.eq(0) # sets to zero when not in normalise_1 state
256 m
.d
.comb
+= self
.in_accept
.eq((~self
.ack
) & (self
.stb
))
257 m
.d
.sync
+= self
.temp_of
.eq(self
.mod
.out_of
)
258 m
.d
.sync
+= self
.temp_z
.eq(self
.out_z
)
259 with m
.If(self
.out_norm
):
260 with m
.If(self
.in_accept
):
265 m
.d
.sync
+= self
.ack
.eq(0)
267 # normalisation not required (or done).
269 m
.d
.sync
+= self
.ack
.eq(1)
270 m
.d
.sync
+= self
.out_roundz
.eq(self
.mod
.out_of
.roundz
)