remove m.If/Elif from fpdiv specialcases
[ieee754fpu.git] / src / ieee754 / fpdiv / mulAddRecFN.py
1 """
2 /*============================================================================
3
4 This Verilog source file is part of the Berkeley HardFloat IEEE Floating-Point
5 Arithmetic Package, Release 1, by John R. Hauser.
6
7 Copyright 2019 The Regents of the University of California. All rights
8 reserved.
9
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35 =============================================================================*/
36
37 `include "HardFloat_consts.vi"
38 `include "HardFloat_specialize.vi"
39
40 """
41
42 from nmigen import Elaboratable, Cat, Const, Mux, Module, Signal, Repl
43 from nmutil.concurrentunit import num_bits
44
45 #/*----------------------------------------------------------------------------
46 #*----------------------------------------------------------------------------*/
47
48 class mulAddRecFNToRaw_preMul(Elaboratable):
49 def __init__(self, expWidth=3, sigWidth=3):
50 # inputs
51 self.control = Signal(floatControlWidth, reset_less=True)
52 self.op = Signal(2, reset_less=True)
53 self.a = Signal(expWidth + sigWidth + 1, reset_less=True)
54 self.b = Signal(expWidth + sigWidth + 1, reset_less=True)
55 self.c = Signal(expWidth + sigWidth + 1, reset_less=True)
56 self.roundingMode = Signal(3, reset_less=True)
57
58 # outputs
59 self.mulAddA = Signal(sigWidth, reset_less=True)
60 self.mulAddB = Signal(sigWidth, reset_less=True)
61 self.mulAddC = Signal(sigWidth*2, reset_less=True)
62 self.intermed_compactState = Signal(6, reset_less=True)
63 self.intermed_sExp = Signal(expWidth + 2, reset_less=True)
64 wid = num_bits(sigWidth + 1)
65 self.intermed_CDom_CAlignDist = Signal(wid, reset_less=True)
66 self.intermed_highAlignedSigC = Signal((sigWidth + 2), reset_less=True)
67
68 def elaborate(self, platform):
69 m = Module()
70 comb = m.d.comb
71
72 #/*-------------------------------------------------------------------
73 #*--------------------------------------------------------------------*/
74 prodWidth = sigWidth*2;
75 sigSumWidth = sigWidth + prodWidth + 3;
76 #/*-------------------------------------------------------------------
77 #*-------------------------------------------------------------------*/
78 isNaNA = Signal(reset_less=True)
79 isInfA = Signal(reset_less=True)
80 isZeroA = Signal(reset_less=True)
81 signA = Signal(reset_less=True)
82
83 sExpA = Signal((expWidth + 2, True), reset_less=True)
84 sigA = Signal(sigWidth+1, reset_less=True)
85 m.submodules.recFNToRawFN_a = rf = recFNToRawFN(expWidth, sigWidth)
86 comb += [(a, isNaNA, isInfA, isZeroA, signA, sExpA, sigA)]
87
88 isSigNaNA = Signal(reset_less=True)
89 m.submodules.isSigNaN_a = nan_a = isSigNaNRecFN(expWidth, sigWidth)
90 comb += [(a, isSigNaNA)]
91
92 isNaNB = Signal(reset_less=True)
93 isInfB = Signal(reset_less=True)
94 isZeroB = Signal(reset_less=True)
95 signB = Signal(reset_less=True)
96
97 sExpB = Signal((expWidth + 2, True), reset_less=True)
98 sigB = Signal(sigWidth+1, reset_less=True)
99 m.submodules.recFNToRawFN_b = rf = recFNToRawFN(expWidth, sigWidth)
100 comb += [(b, isNaNB, isInfB, isZeroB, signB, sExpB, sigB)]
101
102 isSigNaNB = Signal(reset_less=True)
103 m.submodules.isSigNaN_b = nan_b = isSigNaNRecFN(expWidth, sigWidth)
104 comb += [(b, isSigNaNB)]
105
106 isNaNC = Signal(reset_less=True)
107 isInfC = Signal(reset_less=True)
108 isZeroC = Signal(reset_less=True)
109 signC = Signal(reset_less=True)
110
111 sExpC = Signal((expWidth + 2, True), reset_less=True)
112 sigC = Signal(sigWidth+1, reset_less=True)
113 m.submodules.recFNToRawFN_c = rf = recFNToRawFN(expWidth, sigWidth)
114 comb += [(c, isNaNC, isInfC, isZeroC, signC, sExpC, sigC)]
115
116 isSigNaNC = Signal(reset_less=True)
117 m.submodules.isSigNaN_c = nan_c = isSigNaNRecFN(expWidth, sigWidth)
118 comb += [(c, isSigNaNC)]
119
120 #/*-------------------------------------------------------------------
121 #*-------------------------------------------------------------------*/
122 signProd = Signal(reset_less=True)
123 sExpAlignedProd = Signal((expWidth + 3, True), reset_less=True)
124 doSubMags = Signal(reset_less=True)
125 opSignC = Signal(reset_less=True)
126 roundingMode_min = Signal(reset_less=True)
127
128 comb += signProd.eq(signA ^ signB ^ op[1])
129 comb += sExpAlignedProd.eq(sExpA + sExpB + \
130 (-(1<<expWidth) + sigWidth + 3))
131 comb += doSubMags.eq(signProd ^ signC ^ op[0])
132 comb += opSignC.eq(signProd ^ doSubMags)
133 comb += roundingMode_min.eq(roundingMode == ROUND_MIN)
134
135 #/*-------------------------------------------------------------------
136 #*-------------------------------------------------------------------*/
137 sNatCAlignDist = Signal((expWidth + 3, True), reset_less=True)
138 posNatCAlignDist = Signal(expWidth + 2, reset_less=True)
139 isMinCAlign = Signal(reset_less=True)
140 CIsDominant = Signal(reset_less=True)
141 sExpSum = Signal((expWidth + 2, True), reset_less=True)
142 CAlignDist = Signal(num_bits(sigSumWidth), reset_less=True)
143 extComplSigC = Signal((sigSumWidth + 3, True), reset_less=True)
144 mainAlignedSigC = Signal(sigSumWidth + 2, reset_less=True)
145
146 CGrainAlign = (sigSumWidth - sigWidth - 1) & 3;
147 grainAlignedSigC = Signal(sigWidth+CGrainAlign + 1, reset_less=True)
148 reduced4SigC = Signal((sigWidth+CGrainAlign)/4 + 1, reset_less=True)
149 m.submodules.compressBy4_sigC = compressBy4(sigWidth + 1 + CGrainAlign)
150 comb += (grainAlignedSigC, reduced4SigC)
151 CExtraMaskHiBound = (sigSumWidth - 1)/4;
152 CExtraMaskLoBound = (sigSumWidth - sigWidth - 1)/4;
153 CExtraMask = Signal(CExtraMaskHiBound - CExtraMaskLoBound,
154 reset_less=True)
155 m.submodules.lowMask_CExtraMask = lowMaskHiLo(clog2(sigSumWidth) - 2,
156 CExtraMaskHiBound,
157 CExtraMaskLoBound)
158 comb += (CAlignDist[(clog2(sigSumWidth) - 1):2], CExtraMask)
159 reduced4CExtra = Signal(reset_less=True)
160 alignedSigC = Signal(sigSumWidth, reset_less=True)
161
162 sc = [Repl(doSubMags, sigSumWidth - sigWidth + 2)] + \
163 [Mux(doSubMags, ~sigC, sigC)]
164
165 comb += [\
166 sNatCAlignDist.eq(sExpAlignedProd - sExpC),
167 posNatCAlignDist.eq(sNatCAlignDist[:expWidth + 2]),
168 isMinCAlign.eq(isZeroA | isZeroB | (sNatCAlignDist < 0)),
169 CIsDominant.eq(~isZeroC & \
170 (isMinCAlign | (posNatCAlignDist <= sigWidth))),
171 sExpSum.eq(Mux(CIsDominant, sExpC, sExpAlignedProd - sigWidth)),
172 CAlignDist.eq(Mux(isMinCAlign, 0,
173 Mux((posNatCAlignDist < sigSumWidth - 1),
174 posNatCAlignDist[:num_bits(sigSumWidth)],
175 sigSumWidth - 1))),
176 extComplSigC.eq(Cat(*sc)),
177 mainAlignedSigC.eq(extComplSigC >> CAlignDist),
178 grainAlignedSigC.eq(sigC<<CGrainAlign),
179 compressBy4_sigC.inp.eq(grainAlignedSigC),
180 reduced4SigC.eq(compressBy4_sigC.out),
181 lowMaskHiLo.inp.eq(CAlignDist[2:clog2(sigSumWidth)]),
182 CExtraMask.eq(lowMaskHiLo.out),
183 reduced4CExtra.eq((reduced4SigC & CExtraMask).bool()),
184 alignedSigC.eq(Cat(\
185 Mux(doSubMags, (mainAlignedSigC[:3]&0b111) & ~reduced4CExtra,
186 (mainAlignedSigC[:3].bool()) | reduced4CExtra),
187 mainAlignedSigC>>3)),
188 ]
189
190 #/*-------------------------------------------------------------------
191 #*-------------------------------------------------------------------*/
192 isNaNAOrB = Signal(reset_less=True)
193 isNaNAny = Signal(reset_less=True)
194 isInfAOrB = Signal(reset_less=True)
195 invalidProd = Signal(reset_less=True)
196 notSigNaN_invalidExc = Signal(reset_less=True)
197 invalidExc = Signal(reset_less=True)
198 notNaN_addZeros = Signal(reset_less=True)
199 specialCase = Signal(reset_less=True)
200 specialNotNaN_signOut = Signal(reset_less=True)
201 comb += [
202 isNaNAOrB.eq(isNaNA | isNaNB),
203 isNaNAny.eq(isNaNAOrB | isNaNC),
204 isInfAOrB.eq(isInfA | isInfB),
205 invalidProd.eq((isInfA & isZeroB) | (isZeroA & isInfB)),
206 notSigNaN_invalidExc.eq(
207 invalidProd | (~isNaNAOrB & isInfAOrB & isInfC & doSubMags)),
208 invalidExc.eq(
209 isSigNaNA | isSigNaNB | isSigNaNC | notSigNaN_invalidExc),
210 notNaN_addZeros.eq((isZeroA | isZeroB) & isZeroC),
211 specialCase.eq(isNaNAny | isInfAOrB | isInfC | notNaN_addZeros),
212 specialNotNaN_signOut.eq(
213 (isInfAOrB & signProd) | (isInfC & opSignC)
214 | (notNaN_addZeros & ~roundingMode_min & signProd & opSignC)
215 | (notNaN_addZeros & roundingMode_min & (signProd | opSignC)))
216 ]
217
218 special_signOut = specialNotNaN_signOut;
219 #/*-------------------------------------------------------------------
220 # *-------------------------------------------------------------------*/
221 comb += self.mulAddA.eq(sigA)
222 comb += self.mulAddB.eq(sigB)
223 comb += self.mulAddC.eq(alignedSigC[1:prodWidth+1])
224 comb += self.intermed_compactState.eq(Cat(
225 special_signOut,
226 notNaN_addZeros | (~specialCase & alignedSigC[0]),
227 isInfAOrB | isInfC | (~specialCase & CIsDominant ),
228 isNaNAny | (~specialCase & doSubMags ),
229 invalidExc | (~specialCase & signProd ),
230 specialCase,))
231 comb += self.intermed_sExp.eq(sExpSum)
232 comb += self.intermed_CDom_CAlignDist(
233 CAlignDist[:clog2(sigWidth + 1)])
234 comb += self.intermed_highAlignedSigC.eq(
235 alignedSigC[(sigSumWidth - 1):(prodWidth + 1)])
236
237 return m
238
239 #/*------------------------------------------------------------------------
240 #*------------------------------------------------------------------------*/
241
242 class mulAddRecFNToRaw_postMul(Elaboratable):
243
244 def __init__(self, expWidth=3, sigWidth=3):
245 # inputs
246 self.intermed_compactState = Signal(6, reset_less=True)
247 self.intermed_sExp = Signal(expWidth + 2, reset_less=True)
248 wid = num_bits(sigWidth + 1)
249 self.intermed_CDom_CAlignDist = Signal(wid, reset_less=True)
250 self.intermed_highAlignedSigC = Signal((sigWidth + 2), reset_less=True)
251 self.mulAddResult = Signal(sigWidth*2, reset_less=True)
252 self.roundingMode = Signal(3, reset_less=True)
253
254 # outputs
255 self.invalidExc = Signal(reset_less=True)
256 self.out_isNaN = Signal(reset_less=True)
257 self.out_isInf = Signal(reset_less=True)
258 self.out_isZero = Signal(reset_less=True)
259 self.out_sign = Signal(reset_less=True)
260 self.out_sExp = Signal((expWidth + 2, True), reset_less=True)
261 self.out_sig = Signal(sigWidth + 3, reset_less=True)
262
263 def elaborate(self, platform):
264 m = Module()
265 comb = m.d.comb
266
267 #/*-------------------------------------------------------------------
268 #*-------------------------------------------------------------------*/
269 prodWidth = sigWidth*2;
270 sigSumWidth = sigWidth + prodWidth + 3;
271
272 #/*-------------------------------------------------------------------
273 #*-------------------------------------------------------------------*/
274 specialCase = Signal(reset_less=True)
275 invalidExc = Signal(reset_less=True)
276 out_isNaN = Signal(reset_less=True)
277 out_isInf = Signal(reset_less=True)
278 notNaN_addZeros = Signal(reset_less=True)
279 signProd = Signal(reset_less=True)
280 doSubMags = Signal(reset_less=True)
281 CIsDominant = Signal(reset_less=True)
282 bit0AlignedSigC = Signal(reset_less=True)
283 special_signOut = Signal(reset_less=True)
284 comb += [
285 specialCase .eq( intermed_compactState[5] ),
286 invalidExc .eq( specialCase & intermed_compactState[4] ),
287 out_isNaN .eq( specialCase & intermed_compactState[3] ),
288 out_isInf .eq( specialCase & intermed_compactState[2] ),
289 notNaN_addZeros .eq( specialCase & intermed_compactState[1] ),
290 signProd .eq( intermed_compactState[4] ),
291 doSubMags .eq( intermed_compactState[3] ),
292 CIsDominant .eq( intermed_compactState[2] ),
293 bit0AlignedSigC .eq( intermed_compactState[1] ),
294 special_signOut .eq( intermed_compactState[0] ),
295 ]
296
297 #/*-------------------------------------------------------------------
298 #*-------------------------------------------------------------------*/
299 opSignC = Signal(reset_less=True)
300 incHighAlignedSigC = Signal(sigWidth + 3, reset_less=True)
301 sigSum = Signal(sigSumWidth, reset_less=True)
302 roundingMode_min = Signal(reset_less=True)
303
304 comb += [\
305 opSignC.eq(signProd ^ doSubMags),
306 incHighAlignedSigC.eq(intermed_highAlignedSigC + 1),
307 sigSum.eq(Cat(bit0AlignedSigC,
308 mulAddResult[(prodWidth - 1):0],
309 Mux(mulAddResult[prodWidth],
310 incHighAlignedSigC,
311 intermed_highAlignedSigC))),
312 roundingMode_min.eq(roundingMode == ROUND_MIN),
313 ]
314
315 #/*-------------------------------------------------------------------
316 #*-------------------------------------------------------------------*/
317 CDom_sign = Signal(reset_less=True)
318 CDom_sExp = Signal((expWidth + 2, True), reset_less=True)
319 CDom_absSigSum = Signal(prodWidth+2, reset_less=True)
320 CDom_absSigSumExtra = Signal(reset_less=True)
321 CDom_mainSig = Signal(sigWidth+5, reset_less=True)
322 CDom_grainAlignedLowSig = Signal(sigWidth | 3, reset_less=True)
323 CDom_reduced4LowSig = Signal(sigWidth/4+1, reset_less=True)
324 CDom_sigExtraMask = Signal(sigWidth/4, reset_less=True)
325
326 lowMask_CDom_sigExtraMask = lm
327 m.submodules.lm = lm = lowMaskLoHi(clog2(sigWidth + 1) - 2, 0,
328 sigWidth/4)
329 CDom_reduced4SigExtra = Signal(reset_less=True)
330 CDom_sig = Signal(sigWidth+3, reset_less=True)
331
332 comb += [\
333 CDom_sign.eq(opSignC),
334 CDom_sExp.eq(intermed_sExp - doSubMags),
335 CDom_absSigSum.eq(Mux(doSubMags,
336 ~sigSum[sigWidth+1:sigSumWidth],
337 Cat(sigSum[sigWidth+2 : sigSumWidth - 2],
338 intermed_highAlignedSigC[(sigWidth + 1):sigWidth],
339 0b0))),
340 CDom_absSigSumExtra.eq(Mux(doSubMags,
341 (~sigSum[1:sigWidth+1]).bool(),
342 sigSum[1:sigWidth + 2].bool())),
343 CDom_mainSig.eq(
344 (CDom_absSigSum<<intermed_CDom_CAlignDist)>>(sigWidth - 3)),
345 CDom_grainAlignedLowSig.eq(
346 CDom_absSigSum[(sigWidth - 1):0]<<(~sigWidth & 3)),
347 CDom_reduced4LowSig.eq(compressBy4_CDom_absSigSum.out),
348 compressBy4_CDom_absSigSum.inp.eq(CDom_grainAlignedLowSig),
349 lowMask_CDom_sigExtraMask.inp.eq(
350 intermed_CDom_CAlignDist[2:clog2(sigWidth + 1)]),
351 CDom_sigExtraMask.eq(lowMask_CDom_sigExtraMask.out),
352 CDom_reduced4SigExtra.eq(
353 (CDom_reduced4LowSig & CDom_sigExtraMask).bool()),
354 CDom_sig.eq(Cat((CDom_mainSig[:3]).bool() |
355 CDom_reduced4SigExtra |
356 CDom_absSigSumExtra,
357 CDom_mainSig>>3)),
358 ]
359
360 #/*-------------------------------------------------------------------
361 #*-------------------------------------------------------------------*/
362 notCDom_signSigSum = Signal(reset_less=True)
363 notCDom_absSigSum = Signal(prodWidth + 3, reset_less=True)
364 notCDom_reduced2AbsSigSum = Signal((prodWidth+2)//2+1, reset_less=True)
365 m.submodules.cb2 = compressBy2_notCDom_absSigSum = \
366 compressBy2(prodWidth + 3)
367 notCDom_normDistReduced2 = Signal(clog2(prodWidth+4) - 1,
368 reset_less=True)
369 m.submodules.clz = countLeadingZeros_notCDom = \
370 countLeadingZeros((prodWidth + 2)/2 + 1,
371 clog2(prodWidth + 4) - 1)
372 notCDom_nearNormDist = Signal(clog2(prodWidth + 4), reset_less=True)
373 notCDom_sExp = Signal((expWidth + 2, True), reset_less=True)
374 notCDom_mainSig = Signal(sigWidth + 5, reset_less=True)
375 sw = (sigWidth/2 + 1) | 1
376 CDom_grainAlignedLowReduced2Sig = Signal(sw, reset_less=True)
377 notCDom_reduced4AbsSigSum = Signal((sigWidth + 2)//4+1, reset_less=True)
378 m.submodules.cb2r = compressBy2_notCDom_reduced2AbsSigSum = \
379 compressBy2(sw)
380 sw = (sigWidth + 2)//4
381 notCDom_sigExtraMask = Signal(sw, reset_less=True)
382 m.submodules.lms = lowMask_notCDom_sigExtraMask = \
383 lowMaskLoHi(clog2(prodWidth + 4) - 2, 0, sw)
384 notCDom_reduced4SigExtra = Signal(reset_less=True)
385 notCDom_sig = Signal(sigWidth+3, reset_less=True)
386 notCDom_completeCancellation = Signal(reset_less=True)
387 notCDom_sign = Signal(reset_less=True)
388
389 comb += [\
390 notCDom_signSigSum.eq(sigSum[prodWidth + 3]),
391 notCDom_absSigSum.eq(Mux(notCDom_signSigSum,
392 ~sigSum[:prodWidth + 3],
393 sigSum[:prodWidth + 3] + doSubMags)),
394 compressBy2_notCDom_absSigSum.inp.eq(notCDom_absSigSum),
395 notCDom_reduced2AbsSigSum.eq(compressBy2_notCDom_absSigSum.out),
396 countLeadingZeros_notCDom.inp.eq(notCDom_reduced2AbsSigSum),
397 notCDom_normDistReduced2.out.eq(countLeadingZeros_notCDom),
398 notCDom_nearNormDist.eq(notCDom_normDistReduced2<<1),
399 notCDom_sExp.eq(intermed_sExp - notCDom_nearNormDist),
400 notCDom_mainSig.eq((Cat(notCDom_absSigSum, 0)<<
401 notCDom_nearNormDist)>>(sigWidth - 1)),
402 CDom_grainAlignedLowReduced2Sig.eq(
403 notCDom_reduced2AbsSigSum[sigWidth/2:0]<<((sigWidth/2) & 1)),
404 compressBy2_notCDom_reduced2AbsSigSum.inp.eq(
405 CDom_grainAlignedLowReduced2Sig),
406 compressBy2_notCDom_reduced2AbsSigSum.eq(
407 notCDom_reduced4AbsSigSum.out),
408 lowMask_notCDom_sigExtraMask.inp.eq(
409 notCDom_normDistReduced2[1:clog2(prodWidth + 4) - 1]),
410 notCDom_sigExtraMask.eq(lowMask_notCDom_sigExtraMask.out),
411 notCDom_reduced4SigExtra.eq(
412 (notCDom_reduced4AbsSigSum & notCDom_sigExtraMask).bool()),
413 notCDom_sig.eq(Cat(
414 notCDom_mainSig[:3].bool() | notCDom_reduced4SigExtra,
415 notCDom_mainSig>>3)),
416 notCDom_completeCancellation.eq(
417 notCDom_sig[(sigWidth + 1):(sigWidth + 3)] == 0),
418 notCDom_sign.eq(Mux(notCDom_completeCancellation,
419 roundingMode_min,
420 signProd ^ notCDom_signSigSum)),
421 ]
422
423 #/*-------------------------------------------------------------------
424 #*-------------------------------------------------------------------*/
425 comb += [\
426 self.out_isZero.eq( notNaN_addZeros | \
427 (~CIsDominant & notCDom_completeCancellation)),
428 out_sign.eq((specialCase & special_signOut) \
429 | (~specialCase & CIsDominant & CDom_sign ) \
430 | (~specialCase & ~CIsDominant & notCDom_sign )),
431 out_sExp.eq(Mux(CIsDominant, CDom_sExp, notCDom_sExp)),
432 out_sig.eq(Mux(CIsDominant, CDom_sig, notCDom_sig)),
433 ]
434
435 return m
436
437 #/*------------------------------------------------------------------------
438 #*------------------------------------------------------------------------*/
439
440 class mulAddRecFNToRaw(Elaboratable):
441 def __init__(expWidth=3, sigWidth=3):
442 self.control = Signal(floatControlWidth, reset_less=True)
443 self.op = Signal(2, reset_less=True)
444 self.a = Signal(expWidth + sigWidth + 1, reset_less=True)
445 self.b = Signal(expWidth + sigWidth + 1, reset_less=True)
446 self.c = Signal(expWidth + sigWidth + 1, reset_less=True)
447 self.roundingMode = Signal(3, reset_less=True)
448
449 # output
450 self.invalidExc = Signal(reset_less=True)
451 self.out_isNaN = Signal(reset_less=True)
452 self.out_isInf = Signal(reset_less=True)
453 self.out_isZero = Signal(reset_less=True)
454 self.out_sign = Signal(reset_less=True)
455 self.out_sExp = Signal((expWidth + 2, True), reset_less=True)
456 self.out_sig = Signal(sigWidth + 3, reset_less=True)
457
458 def elaborate(self, platform):
459 m = Module()
460 comb = m.d.comb
461
462 mulAddA = Signal(sigWidth, reset_less=True)
463 mulAddB = Signal(sigWidth, reset_less=True)
464 mulAddC = Signal(sigWidth*2, reset_less=True)
465 intermed_compactState = Signal(6, reset_less=True)
466 intermed_sExp = Signal(expWidth + 2, reset_less=True)
467 wid = num_bits(sigWidth + 1)
468 intermed_CDom_CAlignDist = Signal(wid, reset_less=True)
469 intermed_highAlignedSigC = Signal((sigWidth + 2), reset_less=True)
470
471 m.submodules.mar = mulAddToRaw_preMul = \
472 mulAddRecFNToRaw_preMul(expWidth, sigWidth)
473
474 comb += [\
475 mulAddToRaw_preMul.control.eq(self.control),
476 mulAddToRaw_preMul.op.eq(self.op),
477 mulAddToRaw_preMul.a.eq(self.a),
478 mulAddToRaw_preMul.b.eq(self.b),
479 mulAddToRaw_preMul.roundingMode.eq(self.roundingMode),
480 mulAddA.eq(mulAddToRaw_preMul.mulAddA),
481 mulAddB.eq(mulAddToRaw_preMul.mulAddB),
482 mulAddC.eq(mulAddToRaw_preMul.mulAddC),
483 intermed_compactState.eq(mulAddToRaw_preMul.intermed_compactState),
484 intermed_sExp.eq(mulAddToRaw_preMul.intermed_sExp),
485 intermed_CDom_CAlignDist.eq(
486 mulAddToRaw_preMul.intermed_CDom_CAlignDist),
487 intermed_highAlignedSigC.eq(
488 mulAddToRaw_preMul.intermed_highAlignedSigC),
489 ]
490
491 mulAddResult = Signal(sigWidth*2+1, reset_less=True)
492 comb += mulAddResult.eq(mulAddA * mulAddB + mulAddC)
493
494 m.submodules.marp = mulAddToRaw_postMul = \
495 mulAddRecFNToRaw_postMul(expWidth, sigWidth)
496
497 comb += [\
498 mulAddRecFNToRaw_postMul.intermed_compactState.eq(
499 intermed_compactState),
500 mulAddRecFNToRaw_postMul.intermed_sExp.eq(intermed_sExp),
501 mulAddRecFNToRaw_postMul.intermed_CDom_CAlignDist.eq(
502 intermed_CDom_CAlignDist),
503 mulAddRecFNToRaw_postMul.intermed_highAlignedSigC.eq(
504 intermed_highAlignedSigC),
505 mulAddRecFNToRaw_postMul.mulAddResult.eq(mulAddResult),
506 mulAddRecFNToRaw_postMul.roundingMode.eq(roundingMode),
507
508 invalidExc.eq(mulAddRecFNToRaw_postMul.invalidExc),
509 out_isNaN.eq(mulAddRecFNToRaw_postMul.out_isNaN),
510 out_isInf.eq(mulAddRecFNToRaw_postMul.out_isInf),
511 out_isZero.eq(mulAddRecFNToRaw_postMul.out_isZero),
512 out_sign.eq(mulAddRecFNToRaw_postMul.out_sign),
513 out_sExp.eq(mulAddRecFNToRaw_postMul.out_sExp),
514 out_sig.eq(mulAddRecFNToRaw_postMul.out_sig),
515 ]
516
517 return m
518
519 """
520 XXX TODO?
521
522 /*----------------------------------------------------------------------------
523 *----------------------------------------------------------------------------*/
524
525 module
526 mulAddRecFN#(parameter expWidth = 3, parameter sigWidth = 3) (
527 input [(`floatControlWidth - 1):0] control,
528 input [1:0] op,
529 input [(expWidth + sigWidth):0] a,
530 input [(expWidth + sigWidth):0] b,
531 input [(expWidth + sigWidth):0] c,
532 input [2:0] roundingMode,
533 output [(expWidth + sigWidth):0] out,
534 output [4:0] exceptionFlags
535 );
536
537 wire invalidExc, out_isNaN, out_isInf, out_isZero, out_sign;
538 wire signed [(expWidth + 1):0] out_sExp;
539 wire [(sigWidth + 2):0] out_sig;
540 mulAddRecFNToRaw#(expWidth, sigWidth)
541 mulAddRecFNToRaw(
542 control,
543 op,
544 a,
545 b,
546 c,
547 roundingMode,
548 invalidExc,
549 out_isNaN,
550 out_isInf,
551 out_isZero,
552 out_sign,
553 out_sExp,
554 out_sig
555 );
556 roundRawFNToRecFN#(expWidth, sigWidth, 0)
557 roundRawOut(
558 control,
559 invalidExc,
560 1'b0,
561 out_isNaN,
562 out_isInf,
563 out_isZero,
564 out_sign,
565 out_sExp,
566 out_sig,
567 roundingMode,
568 out,
569 exceptionFlags
570 );
571
572 endmodule
573 """
574