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