start converting hardfloat-verilog fmac to nmigen
[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
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 comb += [
163 sNatCAlignDist.eq(sExpAlignedProd - sExpC),
164 posNatCAlignDist.eq(sNatCAlignDist[:expWidth + 2]),
165 isMinCAlign.eq(isZeroA | isZeroB | (sNatCAlignDist < 0))
166 CIsDominant.eq(~isZeroC & \
167 (isMinCAlign | (posNatCAlignDist <= sigWidth)))
168 sExpSum.eq(Mux(CIsDominant, sExpC, sExpAlignedProd - sigWidth)),
169 CAlignDist.eq(Mux(isMinCAlign, 0,
170 Mux((posNatCAlignDist < sigSumWidth - 1),
171 posNatCAlignDist[:num_bits(sigSumWidth)],
172 sigSumWidth - 1)),
173 # XXX check! {doSubMags ? ~sigC : sigC,
174 # {(sigSumWidth - sigWidth + 2){doSubMags}}};
175 sc = [doSubMags] * (sigSumWidth - sigWidth + 2) + \
176 [Mux(doSubMags, ~sigC, sigC)]
177 extComplSigC.eq(Cat(*sc))
178 # XXX check! nmigen doesn't have >>> operator, only >>
179 mainAlignedSigC.eq(extComplSigC >>> CAlignDist),
180 grainAlignedSigC.eq(sigC<<CGrainAlign),
181 compressBy4_sigC.in.eq(grainAlignedSigC),
182 reduced4SigC.eq(compressBy4_sigC.out),
183 lowMaskHiLo.in.eq(CAlignDist[2:(clog2(sigSumWidth)]),
184 CExtraMask.eq(lowMaskHiLo.out),
185 reduced4CExtra.eq((reduced4SigC & CExtraMask).bool()),
186 alignedSigC = Cat(
187 Mux(doSubMags, (mainAlignedSigC[:3]=0b111) & ~reduced4CExtra,
188 (mainAlignedSigC[:3].bool()) | reduced4CExtra),
189 mainAlignedSigC>>3)
190 ]
191 #/*-------------------------------------------------------------------
192 #*-------------------------------------------------------------------*/
193 isNaNAOrB = Signal(reset_less=True)
194 isNaNAny = Signal(reset_less=True)
195 isInfAOrB = Signal(reset_less=True)
196 invalidProd = Signal(reset_less=True)
197 notSigNaN_invalidExc = Signal(reset_less=True)
198 invalidExc = Signal(reset_less=True)
199 notNaN_addZeros = Signal(reset_less=True)
200 specialCase = Signal(reset_less=True)
201 specialNotNaN_signOut = Signal(reset_less=True)
202 comb += [
203 isNaNAOrB.eq(isNaNA | isNaNB),
204 isNaNAny.eq(isNaNAOrB | isNaNC),
205 isInfAOrB.eq(isInfA | isInfB),
206 invalidProd.eq((isInfA & isZeroB) | (isZeroA & isInfB)),
207 notSigNaN_invalidExc.eq(
208 invalidProd | (!isNaNAOrB & isInfAOrB & isInfC & doSubMags)),
209 invalidExc.eq(
210 isSigNaNA | isSigNaNB | isSigNaNC | notSigNaN_invalidExc),
211 notNaN_addZeros.eq((isZeroA | isZeroB) && isZeroC),
212 specialCase.eq(isNaNAny | isInfAOrB | isInfC | notNaN_addZeros),
213 specialNotNaN_signOut.eq(
214 (isInfAOrB & signProd) | (isInfC & opSignC)
215 | (notNaN_addZeros & !roundingMode_min & signProd & opSignC)
216 | (notNaN_addZeros & roundingMode_min & (signProd | opSignC)))
217 ]
218
219 special_signOut = specialNotNaN_signOut;
220 #/*-------------------------------------------------------------------
221 # *-------------------------------------------------------------------*/
222 mulAddA = sigA;
223 mulAddB = sigB;
224 mulAddC = Signal(prodWidth, reset_less=True)
225 intermed_compactState = Signal(6, reset_less=True)
226
227 comb += mulAddC.eq(alignedSigC[1:prodWidth+1])
228 comb += intermed_compactState.eq(Cat(
229 special_signOut,
230 notNaN_addZeros | (~specialCase & alignedSigC[0]),
231 isInfAOrB | isInfC | (~specialCase & CIsDominant ),
232 isNaNAny | (~specialCase & doSubMags ),
233 invalidExc | (~specialCase & signProd ),
234 specialCase,))
235 intermed_sExp = sExpSum;
236 intermed_CDom_CAlignDist = CAlignDist[(clog2(sigWidth + 1) - 1):0];
237 intermed_highAlignedSigC =
238 alignedSigC[(sigSumWidth - 1):(prodWidth + 1)];
239
240 return m
241
242 #/*------------------------------------------------------------------------
243 #*------------------------------------------------------------------------*/
244
245 class mulAddRecFNToRaw_postMul(Elaboratable):
246
247 def __init__(self, expWidth = 3, parameter sigWidth = 3):
248 # inputs
249 self.control = Signal(floatControlWidth, reset_less=True)
250 self.op = Signal(2, reset_less=True)
251 self.a = Signal(expWidth + sigWidth + 1, reset_less=True)
252 self.b = Signal(expWidth + sigWidth + 1, reset_less=True)
253 self.c = Signal(expWidth + sigWidth + 1, reset_less=True)
254 self.roundingMode = Signal(3, reset_less=True)
255
256 # outputs
257 self.mulAddA = Signal(sigWidth, reset_less=True)
258 self.mulAddB = Signal(sigWidth, reset_less=True)
259 self.mulAddC = Signal(sigWidth*2, reset_less=True)
260
261 # inputs
262 self.intermed_compactState = Signal(6, reset_less=True)
263 self.intermed_sExp = Signal(expWidth + 2, reset_less=True)
264 wid = num_bits(sigWidth + 1)
265 self.intermed_CDom_CAlignDist = Signal(wid, reset_less=True)
266 self.intermed_highAlignedSigC = Signal((sigWidth + 2), reset_less=True)
267 self.mulAddResult = Signal(sigWidth*2, reset_less=True)
268 self.roundingMode = Signal(3, reset_less=True)
269
270 # outputs
271 self.invalidExc = Signal(reset_less=True)
272 self.out_isNaN = Signal(reset_less=True)
273 self.out_isInf = Signal(reset_less=True)
274 self.out_isZero = Signal(reset_less=True)
275 self.out_sign = Signal(reset_less=True)
276 self.out_sExp = Signal((expWidth + 2, True), reset_less=True)
277 self.out_sig = Signal(sigWidth + 3, reset_less=True)
278
279 def elaborate(self, platform):
280 m = Module()
281 comb = m.d.comb
282
283 #/*-------------------------------------------------------------------
284 #*-------------------------------------------------------------------*/
285 prodWidth = sigWidth*2;
286 sigSumWidth = sigWidth + prodWidth + 3;
287
288 #/*-------------------------------------------------------------------
289 #*-------------------------------------------------------------------*/
290 wire specialCase = Signal(reset_less=True)
291 assign invalidExc = Signal(reset_less=True)
292 assign out_isNaN = Signal(reset_less=True)
293 assign out_isInf = Signal(reset_less=True)
294 wire notNaN_addZeros = Signal(reset_less=True)
295 wire signProd = Signal(reset_less=True)
296 wire doSubMags = Signal(reset_less=True)
297 wire CIsDominant = Signal(reset_less=True)
298 wire bit0AlignedSigC = Signal(reset_less=True)
299 wire special_signOut = Signal(reset_less=True)
300 comb += [
301 specialCase .eq( intermed_compactState[5] ),
302 invalidExc .eq( specialCase & intermed_compactState[4] ),
303 out_isNaN .eq( specialCase & intermed_compactState[3] ),
304 out_isInf .eq( specialCase & intermed_compactState[2] ),
305 notNaN_addZeros .eq( specialCase & intermed_compactState[1] ),
306 signProd .eq( intermed_compactState[4] ),
307 doSubMags .eq( intermed_compactState[3] ),
308 CIsDominant .eq( intermed_compactState[2] ),
309 bit0AlignedSigC .eq( intermed_compactState[1] ),
310 special_signOut .eq( intermed_compactState[0] ),
311 ]
312
313 #/*-------------------------------------------------------------------
314 #*-------------------------------------------------------------------*/
315 opSignC = Signal(reset_less=True)
316 incHighAlignedSigC = Signal(sigWidth + 3, reset_less=True)
317 sigSum = Signal(sigSumWidth, reset_less=True)
318 roundingMode_min = Signal(reset_less=True)
319
320 comb += [\
321 opSignC.eq(signProd ^ doSubMags),
322 incHighAlignedSigC.eq(intermed_highAlignedSigC + 1),
323 sigSum.eq(Cat(bit0AlignedSigC,
324 mulAddResult[(prodWidth - 1):0],
325 Mux(mulAddResult[prodWidth],
326 incHighAlignedSigC,
327 intermed_highAlignedSigC))),
328 roundingMode_min.eq(roundingMode == `round_min),
329 ]
330
331 #/*-------------------------------------------------------------------
332 #*-------------------------------------------------------------------*/
333 CDom_sign = Signal(reset_less=True)
334 CDom_sExp = Signal((expWidth + 2, True), reset_less=True)
335 CDom_absSigSum = Signal(prodWidth+2, reset_less=True)
336 CDom_absSigSumExtra = Signal(reset_less=True)
337 CDom_mainSig = Signal(sigWidth+5, reset_less=True)
338 CDom_grainAlignedLowSig = Signal(sigWidth | 3, reset_less=True)
339 CDom_reduced4LowSig = Signal(sigWidth/4+1, reset_less=True)
340 CDom_sigExtraMask = Signal(sigWidth/4, reset_less=True)
341
342 lowMask_CDom_sigExtraMask = lm
343 m.submodules.lm = lm = lowMaskLoHi(clog2(sigWidth + 1) - 2, 0,
344 sigWidth/4)
345 CDom_reduced4SigExtra = Signal(reset_less=True)
346 CDom_sig = Signal(sigWidth+3, reset_less=True)
347
348 comb += [\
349 CDom_sign.eq(opSignC),
350 CDom_sExp.eq(intermed_sExp - doSubMags),
351 CDom_absSigSum.eq(Mux(doSubMags,
352 ~sigSum[sigWidth+1:sigSumWidth],
353 Cat(sigSum[sigWidth+2 : sigSumWidth - 2],
354 intermed_highAlignedSigC[(sigWidth + 1):sigWidth],
355 0b0)),
356 CDom_absSigSumExtra.eq(Mux(doSubMags,
357 (~sigSum[1:sigWidth+1]).bool(),
358 sigSum[1:sigWidth + 2].bool())),
359 CDom_mainSig.eq(
360 (CDom_absSigSum<<intermed_CDom_CAlignDist)>>(sigWidth - 3)),
361 CDom_grainAlignedLowSig.eq(
362 CDom_absSigSum[(sigWidth - 1):0]<<(~sigWidth & 3)),
363 CDom_reduced4LowSig.eq(compressBy4_CDom_absSigSum.out),
364 compressBy4_CDom_absSigSum.in.eq(CDom_grainAlignedLowSig),
365 lowMask_CDom_sigExtraMask.in.eq(
366 intermed_CDom_CAlignDist[2:clog2(sigWidth + 1)]),
367 CDom_sigExtraMask.eq(lowMask_CDom_sigExtraMask.out),
368 CDom_reduced4SigExtra.eq(
369 (CDom_reduced4LowSig & CDom_sigExtraMask).bool()),
370 CDom_sig.eq(Cat((CDom_mainSig[:3]).bool() |
371 CDom_reduced4SigExtra |
372 CDom_absSigSumExtra,
373 CDom_mainSig>>3)),
374 ]
375
376 #/*-------------------------------------------------------------------
377 #*-------------------------------------------------------------------*/
378 notCDom_signSigSum = Signal(reset_less=True)
379 notCDom_absSigSum = Signal(prodWidth + 3, reset_less=True)
380 notCDom_reduced2AbsSigSum = Signal(prodWidth+2)//2+1, reset_less=True)
381 m.submodules.cb2 = compressBy2_notCDom_absSigSum = \
382 compressBy2(prodWidth + 3)
383 notCDom_normDistReduced2 = Signal(clog2(prodWidth+4) - 1,
384 reset_less=True)
385 m.submodules.clz = countLeadingZeros_notCDom =
386 countLeadingZeros((prodWidth + 2)/2 + 1,
387 clog2(prodWidth + 4) - 1)
388 notCDom_nearNormDist = Signal((clog2(prodWidth + 4), reset_less=True)
389 notCDom_sExp = Signal((expWidth + 2, True), reset_less=True)
390 notCDom_mainSig = Signal(sigWidth + 5, reset_less=True)
391 sw = (((sigWidth/2 + 1) | 1)
392 CDom_grainAlignedLowReduced2Sig = Signal(sw, reset_less=True)
393 notCDom_reduced4AbsSigSum = Signal((sigWidth + 2)//4+1, reset_less=True)
394 m.submodules.cb2r = compressBy2_notCDom_reduced2AbsSigSum =
395 compressBy2((sigWidth/2 + 1) | 1)
396 sw = ((sigWidth + 2)/4
397 notCDom_sigExtraMask = Signal(sw, reset_less=True)
398 m.submodules.lms = lowMask_notCDom_sigExtraMask =
399 lowMaskLoHi(clog2(prodWidth + 4) - 2, 0, (sigWidth + 2)/4)
400 notCDom_reduced4SigExtra = Signal(reset_less=True)
401 notCDom_sig Signal(sigWidth+3, reset_less=True)
402 notCDom_completeCancellation = Signal(reset_less=True)
403 notCDom_sign = Signal(reset_less=True)
404
405 comb += [\
406 notCDom_signSigSum.eq(sigSum[prodWidth + 3]),
407 notCDom_absSigSum.eq(Mux(notCDom_signSigSum,
408 ~sigSum[:prodWidth + 3],
409 sigSum[:prodWidth + 3] + doSubMags))
410 compressBy2_notCDom_absSigSum.in.eq(notCDom_absSigSum),
411 notCDom_reduced2AbsSigSum.eq(compressBy2_notCDom_absSigSum.out),
412 countLeadingZeros_notCDom.in.eq(notCDom_reduced2AbsSigSum),
413 notCDom_normDistReduced2.out.eq(countLeadingZeros_notCDom),
414 notCDom_nearNormDist.eq(notCDom_normDistReduced2<<1),
415 notCDom_sExp.eq(intermed_sExp - notCDom_nearNormDist),
416 notCDom_mainSig.eq((Cat(notCDom_absSigSum, 0)<<
417 notCDom_nearNormDist)>>(sigWidth - 1)),
418 CDom_grainAlignedLowReduced2Sig.eq(
419 notCDom_reduced2AbsSigSum[sigWidth/2:0]<<((sigWidth/2) & 1)),
420 compressBy2_notCDom_reduced2AbsSigSum.in.eq(
421 CDom_grainAlignedLowReduced2Sig),
422 compressBy2_notCDom_reduced2AbsSigSum.eq(
423 notCDom_reduced4AbsSigSum.out),
424 lowMask_notCDom_sigExtraMask.in.eq(
425 notCDom_normDistReduced2[1:clog2(prodWidth + 4) - 1]),
426 notCDom_sigExtraMask.eq(lowMask_notCDom_sigExtraMask.out),
427 notCDom_reduced4SigExtra.eq(
428 (notCDom_reduced4AbsSigSum & notCDom_sigExtraMask).bool()),
429 notCDom_sig.eq(Cat(
430 notCDom_mainSig[:3].bool() | notCDom_reduced4SigExtra,
431 notCDom_mainSig>>3)),
432 notCDom_completeCancellation.eq(
433 notCDom_sig[(sigWidth + 1):(sigWidth + 3)] == 0),
434 notCDom_sign = Mux(notCDom_completeCancellation,
435 roundingMode_min,
436 signProd ^ notCDom_signSigSum),
437 ]
438
439 #/*-------------------------------------------------------------------
440 #*-------------------------------------------------------------------*/
441 assign out_isZero =
442 notNaN_addZeros | (!CIsDominant && notCDom_completeCancellation);
443 assign out_sign =
444 ( specialCase && special_signOut)
445 | (!specialCase && CIsDominant && CDom_sign )
446 | (!specialCase && !CIsDominant && notCDom_sign );
447 assign out_sExp = CIsDominant ? CDom_sExp : notCDom_sExp;
448 assign out_sig = CIsDominant ? CDom_sig : notCDom_sig;
449
450 /*----------------------------------------------------------------------------
451 *----------------------------------------------------------------------------*/
452
453 module
454 mulAddRecFNToRaw#(parameter expWidth = 3, parameter sigWidth = 3) (
455 input [(`floatControlWidth - 1):0] control,
456 input [1:0] op,
457 input [(expWidth + sigWidth):0] a,
458 input [(expWidth + sigWidth):0] b,
459 input [(expWidth + sigWidth):0] c,
460 input [2:0] roundingMode,
461 output invalidExc,
462 output out_isNaN,
463 output out_isInf,
464 output out_isZero,
465 output out_sign,
466 output signed [(expWidth + 1):0] out_sExp,
467 output [(sigWidth + 2):0] out_sig
468 );
469 `include "HardFloat_localFuncs.vi"
470
471 wire [(sigWidth - 1):0] mulAddA, mulAddB;
472 wire [(sigWidth*2 - 1):0] mulAddC;
473 wire [5:0] intermed_compactState;
474 wire signed [(expWidth + 1):0] intermed_sExp;
475 wire [(clog2(sigWidth + 1) - 1):0] intermed_CDom_CAlignDist;
476 wire [(sigWidth + 1):0] intermed_highAlignedSigC;
477 mulAddRecFNToRaw_preMul#(expWidth, sigWidth)
478 mulAddToRaw_preMul(
479 control,
480 op,
481 a,
482 b,
483 c,
484 roundingMode,
485 mulAddA,
486 mulAddB,
487 mulAddC,
488 intermed_compactState,
489 intermed_sExp,
490 intermed_CDom_CAlignDist,
491 intermed_highAlignedSigC
492 );
493 wire [sigWidth*2:0] mulAddResult = mulAddA * mulAddB + mulAddC;
494 mulAddRecFNToRaw_postMul#(expWidth, sigWidth)
495 mulAddToRaw_postMul(
496 intermed_compactState,
497 intermed_sExp,
498 intermed_CDom_CAlignDist,
499 intermed_highAlignedSigC,
500 mulAddResult,
501 roundingMode,
502 invalidExc,
503 out_isNaN,
504 out_isInf,
505 out_isZero,
506 out_sign,
507 out_sExp,
508 out_sig
509 );
510
511 endmodule
512
513 /*----------------------------------------------------------------------------
514 *----------------------------------------------------------------------------*/
515
516 module
517 mulAddRecFN#(parameter expWidth = 3, parameter sigWidth = 3) (
518 input [(`floatControlWidth - 1):0] control,
519 input [1:0] op,
520 input [(expWidth + sigWidth):0] a,
521 input [(expWidth + sigWidth):0] b,
522 input [(expWidth + sigWidth):0] c,
523 input [2:0] roundingMode,
524 output [(expWidth + sigWidth):0] out,
525 output [4:0] exceptionFlags
526 );
527
528 wire invalidExc, out_isNaN, out_isInf, out_isZero, out_sign;
529 wire signed [(expWidth + 1):0] out_sExp;
530 wire [(sigWidth + 2):0] out_sig;
531 mulAddRecFNToRaw#(expWidth, sigWidth)
532 mulAddRecFNToRaw(
533 control,
534 op,
535 a,
536 b,
537 c,
538 roundingMode,
539 invalidExc,
540 out_isNaN,
541 out_isInf,
542 out_isZero,
543 out_sign,
544 out_sExp,
545 out_sig
546 );
547 roundRawFNToRecFN#(expWidth, sigWidth, 0)
548 roundRawOut(
549 control,
550 invalidExc,
551 1'b0,
552 out_isNaN,
553 out_isInf,
554 out_isZero,
555 out_sign,
556 out_sExp,
557 out_sig,
558 roundingMode,
559 out,
560 exceptionFlags
561 );
562
563 endmodule
564