GCC Code Coverage Report
Directory: . Exec Total Coverage
File: build-coverage/deps/include/symfpu/core/rounder.h Lines: 148 148 100.0 %
Date: 2021-08-01 Branches: 409 729 56.1 %

Line Exec Source
1
/*
2
** Copyright (C) 2018 Martin Brain
3
**
4
** See the file LICENSE for licensing information.
5
*/
6
7
/*
8
** rounder.h
9
**
10
** Martin Brain
11
** martin.brain@cs.ox.ac.uk
12
** 26/08/14
13
**
14
** Rounding arbitrary length unpacked floats back to their correct length.
15
**
16
*/
17
18
/*
19
 * Rounder Ideas
20
 *
21
 *  - get the rounder to handle things with 1 or 2 possible leading
22
 *    0's rather than normalise before and after rounding.
23
 *    Subnormal rounding should ideally be temporarily denormalised to
24
 *    avoid the expensive variable position rounding.
25
 *
26
 *  1. Take exponent and add a 0 at the start to deal with overflow.
27
 *     (may not be needed if the exponent has already been extended due
28
 *      to subnormals, addition, etc.)
29
 *  2. For each of the possible positions of the binary point, produce
30
 *     an incremented version and round and sticky bits.
31
 *     (given the alignment is known, may be able to just pick how much
32
 *      to increment by and then increment once.)
33
 *  3. The leading zeros of the original exponent pick which set of
34
 *     round and sticky to use.  Thus pick which of the incremented /
35
 *     normal to use and align apart from 1.
36
 *  4. Finally align, most of the information needed for this will be
37
 *     already known.
38
 *  (Catch -- this can introduce diamonds)
39
 *
40
 * - can fold the increment from the rounder into the circuitry /
41
 *   last round of accumulation.
42
 *   In fact, can take this further.  a + b + 1 takes the same
43
 *   circuitry as a + b.  a * b + 1 shares most of the circuit with
44
 *   a * b and neither of them require a sign extension.  Extending
45
 *   this to a + b + k and a * b + k for positional rounding is an
46
 *   open question.
47
 *
48
 * - add a 'non-deterministic rounding' mode for underapproximation.
49
 *
50
 * - add 'round-to-odd' and 'round-away-from-zero' mode
51
 *
52
 * - add 'flush subnormals to zero' option
53
 *
54
 * - Rather than increment and re-align, take all but the top bit of the
55
 *   significand, concatinate on to the exponent and then increment.
56
 *   This is effectively using the ordering trick for packed rounding.
57
 *
58
 * - The sticky bit should be a flag rather than concatinated on to the
59
 *   number to make arithmetic reasoning easier.
60
 *   (Conversely ... having it as bits is better for semi-normalised things)
61
 *
62
 * - Specialised rounders
63
 *    Additive
64
 *     Only one overflow increment is possible, even for a + b + 1
65
 *     When a subnormal number if generated, it is exact and thus you
66
 *      don't need to think about positional rounding for the
67
 *      subnormals.
68
 *     No need to check for underflow to zero for similar reasons.
69
 *     The rounder for the near path can be even more specialised as
70
 *      the sticky bit is always 0 and it can't overflow.
71
 *     Can only overflow if it is an effective add.
72
 *
73
 *    Multiplicative
74
 *     May be able to increment without overflow.
75
 *      It only seems to be possible for subnormals.
76
 *     Don't need to extend the exponent to increment when normalising.
77
 *     Can use injection bits during the multiplication reduction tree,
78
 *      the problem with the carry up can be fixed afterwards with an
79
 *      increment (add for subnormal) or by spotting the carry up during
80
 *      the reduction.
81
 *
82
 *    FMA
83
 *     More like multiply.
84
 */
85
86
87
#include "symfpu/core/operations.h"
88
#include "symfpu/core/unpackedFloat.h"
89
90
#ifndef SYMFPU_ROUNDER
91
#define SYMFPU_ROUNDER
92
93
namespace symfpu {
94
95
  // The final reconstruction of the rounded result
96
  // Handles the overflow and underflow conditions
97
  template <class t>
98
1055
  unpackedFloat<t> rounderSpecialCases (const typename t::fpt &format,
99
					const typename t::rm &roundingMode,
100
					const unpackedFloat<t> &roundedResult,
101
					const typename t::prop &overflow,
102
					const typename t::prop &underflow,
103
					const typename t::prop &isZero)
104
  {
105
    typedef typename t::prop prop;
106
    typedef typename t::ubv ubv;
107
108
    /*** Underflow and overflow ***/
109
110
    // On overflow either return inf or max
111
2529
    prop returnInf(roundingMode == t::RNE() ||
112
656
		   roundingMode == t::RNA() ||
113
2493
		   (roundingMode == t::RTP() && !roundedResult.getSign()) ||
114
467
		   (roundingMode == t::RTN() &&  roundedResult.getSign()));
115
1055
    probabilityAnnotation<t>(returnInf, LIKELY);  // Inf is more likely than max in most application scenarios
116
117
    // On underflow either return 0 or minimum subnormal
118
2529
    prop returnZero(roundingMode == t::RNE() ||
119
656
		    roundingMode == t::RNA() ||
120
524
		    roundingMode == t::RTZ() ||
121
2443
		    (roundingMode == t::RTP() &&  roundedResult.getSign()) ||
122
421
		    (roundingMode == t::RTN() && !roundedResult.getSign()));
123
1055
    probabilityAnnotation<t>(returnZero, LIKELY);   // 0 is more likely than min in most application scenarios
124
125
126
127
    /*** Reconstruct ***/
128
2110
    unpackedFloat<t> inf(unpackedFloat<t>::makeInf(format, roundedResult.getSign()));
129
2110
    unpackedFloat<t> max(roundedResult.getSign(), unpackedFloat<t>::maxNormalExponent(format), ubv::allOnes(unpackedFloat<t>::significandWidth(format)));
130
2110
    unpackedFloat<t> min(roundedResult.getSign(), unpackedFloat<t>::minSubnormalExponent(format), unpackedFloat<t>::leadingOne(unpackedFloat<t>::significandWidth(format)));
131
2110
    unpackedFloat<t> zero(unpackedFloat<t>::makeZero(format, roundedResult.getSign()));
132
133
1055
    unpackedFloat<t> result(ITE(isZero,
134
				zero,
135
				ITE(underflow,
136
				    ITE(returnZero, zero, min),
137
				    ITE(overflow,
138
					ITE(returnInf, inf, max),
139
					roundedResult))));
140
2110
    return result;
141
  }
142
143
144
  // Decide whether to round up or not
145
  template <class t>
146
1338
    typename t::prop roundingDecision (const typename t::rm &roundingMode,
147
				     const typename t::prop &sign,
148
				     const typename t::prop &significandEven,
149
				     const typename t::prop &guardBit,
150
				     const typename t::prop &stickyBit,
151
				     const typename t::prop &knownRoundDown) {
152
    typedef typename t::prop prop;
153
154
1427
    prop roundUpRNE(roundingMode == t::RNE() && guardBit && (stickyBit || !significandEven));
155
1427
    prop roundUpRNA(roundingMode == t::RNA() && guardBit);
156
1427
    prop roundUpRTP(roundingMode == t::RTP() && !sign && (guardBit || stickyBit));
157
1427
    prop roundUpRTN(roundingMode == t::RTN() &&  sign && (guardBit || stickyBit));
158
1427
    prop roundUpRTZ(roundingMode == t::RTZ() && prop(false));
159
1448
    prop roundUp(!knownRoundDown &&
160
905
		 (roundUpRNE || roundUpRNA || roundUpRTP || roundUpRTN || roundUpRTZ));
161
162
1427
    return roundUp;
163
  }
164
165
166
167
  template <class t>
168
164
  struct significandRounderResult{
169
    typename t::ubv significand;
170
    typename t::prop incrementExponent;
171
172
164
    significandRounderResult(const typename t::ubv &sig, const typename t::prop &inc) :
173
164
      significand(sig), incrementExponent(inc) {}
174
175
    significandRounderResult(const significandRounderResult &old) :
176
      significand(old.significand), incrementExponent(old.incrementExponent) {}
177
  };
178
179
  // Handles rounding the significand to a fixed width
180
  // If knownRoundDown is true should simplify to just extract
181
  // Not quite the same as either rounder so can't quite be refactored
182
  template <class t>
183
4
  significandRounderResult<t> fixedPositionRound(const typename t::rm &roundingMode,
184
						 const typename t::prop &sign,
185
						 const typename t::ubv &significand,
186
						 const typename t::bwt &targetWidth,
187
						 const typename t::prop &knownLeadingOne,
188
						 const typename t::prop &knownRoundDown) {
189
    typedef typename t::bwt bwt;
190
    typedef typename t::prop prop;
191
    typedef typename t::ubv ubv;
192
193
4
    bwt sigWidth(significand.getWidth());
194
4
    PRECONDITION(sigWidth >= targetWidth + 2);
195
    // Extract
196
8
    ubv extractedSignificand(significand.extract(sigWidth - 1, sigWidth - targetWidth).extend(1)); // extended to catch the overflow
197
198
8
    prop significandEven(extractedSignificand.extract(0,0).isAllZeros());
199
200
201
    // Normal guard and sticky bits
202
4
    bwt guardBitPosition(sigWidth - (targetWidth + 1));
203
8
    prop guardBit(significand.extract(guardBitPosition, guardBitPosition).isAllOnes());
204
205
8
    prop stickyBit(!significand.extract(guardBitPosition - 1,0).isAllZeros());
206
207
    // Rounding decision
208
8
    prop roundUp(roundingDecision<t>(roundingMode, sign, significandEven,
209
				     guardBit, stickyBit, knownRoundDown));
210
211
    // Conditional increment
212
8
    ubv roundedSignificand(conditionalIncrement<t>(roundUp, extractedSignificand));
213
214
8
    ubv overflowBit(roundedSignificand.extract(targetWidth, targetWidth) & ubv(roundUp));
215
8
    ubv carryUpMask((overflowBit | ubv(knownLeadingOne)).append(ubv::zero(targetWidth - 1)));   // Cheaper than conditional shift
216
217
    // Build result
218
4
    significandRounderResult<t> result(roundedSignificand.extract(targetWidth-1,0) | carryUpMask,
219
				    overflowBit.isAllOnes());
220
221
8
    return result;
222
  }
223
224
225
  // Handles rounding the significand to a fixed width
226
  // If knownRoundDown is true should simplify to just mask
227
  // Not quite the same as either rounder so can't quite be refactored
228
  template <class t>
229
160
  significandRounderResult<t> variablePositionRound(const typename t::rm &roundingMode,
230
						    const typename t::prop &sign,
231
						    const typename t::ubv &significand,
232
						    const typename t::ubv &roundPosition,
233
						    const typename t::prop &knownLeadingOne,
234
						    const typename t::prop &knownRoundDown) {
235
    typedef typename t::bwt bwt;
236
    typedef typename t::prop prop;
237
    typedef typename t::ubv ubv;
238
239
160
    bwt sigWidth(significand.getWidth());
240
241
    // Set up significand
242
    // Round-up-from-sticky bit and overflow bit at MSB, (fall-back) guard and sticky bits at LSB
243
320
    ubv expandedSignificand(significand.extend(2).append(ubv::zero(2)));
244
160
    bwt exsigWidth(expandedSignificand.getWidth());
245
246
247
    // Identify the increment, guard and sticky bits
248
320
    ubv incrementLocation(ubv(exsigWidth, (0x1U << 2U)) << roundPosition.matchWidth(expandedSignificand));
249
320
    ubv guardLocation(incrementLocation >> ubv::one(exsigWidth));
250
320
    ubv stickyLocations(guardLocation.decrement());
251
252
180
    prop significandEven((incrementLocation & expandedSignificand).isAllZeros());
253
180
    prop guardBit(!(guardLocation & expandedSignificand).isAllZeros());
254
180
    prop stickyBit(!(stickyLocations & expandedSignificand).isAllZeros());
255
256
    // Rounding decision
257
180
    prop roundUp(roundingDecision<t>(roundingMode, sign, significandEven,
258
				     guardBit, stickyBit, knownRoundDown));
259
260
    // Conditional increment
261
320
    ubv roundedSignificand(expandedSignificand + ITE(roundUp,
262
						     incrementLocation,
263
						     ubv::zero(exsigWidth)));
264
265
    // Mask out rounded bits and extract
266
320
    ubv maskedRoundedSignificand(roundedSignificand & (~(stickyLocations << ubv::one(exsigWidth)))); // LSB is wrong but gets cut
267
268
320
    ubv roundUpFromSticky(roundedSignificand.extract(exsigWidth - 1, exsigWidth - 1));  // Only true when rounding up and whole significand is sticky
269
320
    ubv overflowBit(roundedSignificand.extract(exsigWidth - 2, exsigWidth - 2));
270
320
    ubv maskTrigger((roundUpFromSticky | overflowBit) & ubv(roundUp));
271
320
    ubv carryUpMask((maskTrigger | ubv(knownLeadingOne)).append(ubv::zero(sigWidth - 1)));   // Cheaper than conditional shift
272
273
    // Build result
274
160
    significandRounderResult<t> result(maskedRoundedSignificand.extract(sigWidth + 1, 2) | carryUpMask,
275
				       maskTrigger.isAllOnes());
276
277
320
    return result;
278
  }
279
280
281
282
  // Allows various of the key branches in the rounder to be fixed / removed
283
  // using information that is known from the operation in which the rounder
284
  // is used. Setting these to false gives the usual rounder.
285
  template <class t>
286
125
  struct customRounderInfo {
287
    typedef typename t::prop prop;
288
289
    prop noOverflow;
290
    prop noUnderflow;
291
    prop exact;                 // Significand does not need to be changed
292
    prop subnormalExact;        // If the value is subnormal then it is exact
293
    prop noSignificandOverflow; // Incrementing the significand will not cause overflow
294
    //prop stickyIsZero;        // Can be fixed in the number directly
295
296
1055
    customRounderInfo (const prop &noO, const prop &noU,
297
		       const prop &e, const prop &sE,
298
		       const prop &nSO) :
299
      noOverflow(noO), noUnderflow(noU), exact(e),
300
1055
      subnormalExact(sE), noSignificandOverflow(nSO) {}
301
  };
302
303
template <class t>
304
1055
  unpackedFloat<t> customRounder (const typename t::fpt &format,
305
				  const typename t::rm &roundingMode,
306
				  const unpackedFloat<t> &uf,
307
				  const customRounderInfo<t> &known) {
308
309
  typedef typename t::bwt bwt;
310
  typedef typename t::prop prop;
311
  typedef typename t::ubv ubv;
312
  typedef typename t::sbv sbv;
313
314
  //PRECONDITION(uf.valid(format));
315
  // Not a precondition because
316
  //  1. Exponent and significand may be extended.
317
  //  2. Their values may also be outside of the correct range.
318
  //
319
  // However some thing do hold:
320
  //  1. Leading bit of the significant is 1   (if you want to get a meaningful answer)
321
  //     (if not, a cancellation on the near path of add can cause
322
  //      this, but the result will not be used, so it can be incorrect)
323
2110
  ubv psig(uf.getSignificand());
324
1055
  bwt sigWidth(psig.getWidth());
325
  //PRECONDITION(psig.extract(sigWidth-1, sigWidth-1).isAllOnes());
326
2110
  ubv sig(psig | unpackedFloat<t>::leadingOne(sigWidth));
327
328
  //  2. Must have round and sticky bits
329
1055
  bwt targetSignificandWidth(unpackedFloat<t>::significandWidth(format));
330
1055
  PRECONDITION(sigWidth >= targetSignificandWidth + 2);
331
332
  //  3. Must have at least enough exponent bits
333
2110
  sbv exp(uf.getExponent());
334
1055
  bwt expWidth(exp.getWidth());
335
1055
  bwt targetExponentWidth(unpackedFloat<t>::exponentWidth(format));
336
1055
  PRECONDITION(expWidth >= targetExponentWidth);
337
338
  // Also, do not round special values.
339
  // Note that this relies on these having default values and
340
  // the code that calls the rounder constructing uf from parts.
341
  //PRECONDITION(!uf.getNaN());
342
  //PRECONDITION(!uf.getInf());
343
  //PRECONDITION(!uf.getZero());
344
  // The safe choice of default values means this should work OK
345
346
347
348
  /*** Early underflow and overflow detection ***/
349
1055
  bwt exponentExtension(expWidth - targetExponentWidth);
350
1110
  prop earlyOverflow(exp > unpackedFloat<t>::maxNormalExponent(format).extend(exponentExtension));
351
1110
  prop earlyUnderflow(exp < unpackedFloat<t>::minSubnormalExponent(format).extend(exponentExtension).decrement());
352
  // Optimisation : if the precondition on sigWidth and targetSignificandWidth is removed
353
  //                then can change to:
354
  //                   exponent >= minSubnormalExponent - 1
355
  //                && sigWidth > targetSignificandBits
356
1055
  probabilityAnnotation<t>(earlyOverflow, UNLIKELY);  // (over,under)flows are generally rare events
357
1055
  probabilityAnnotation<t>(earlyUnderflow, UNLIKELY);
358
359
1110
  prop potentialLateOverflow(exp == unpackedFloat<t>::maxNormalExponent(format).extend(exponentExtension));
360
1110
  prop potentialLateUnderflow(exp == unpackedFloat<t>::minSubnormalExponent(format).extend(exponentExtension).decrement());
361
1055
  probabilityAnnotation<t>(potentialLateOverflow, VERYUNLIKELY);
362
1055
  probabilityAnnotation<t>(potentialLateUnderflow, VERYUNLIKELY);
363
364
365
366
  /*** Normal or subnormal rounding? ***/
367
1110
  prop normalRoundingRange(exp >= unpackedFloat<t>::minNormalExponent(format).extend(exponentExtension));
368
1055
  probabilityAnnotation<t>(normalRoundingRange, LIKELY);
369
1110
  prop normalRounding(normalRoundingRange || known.subnormalExact);
370
371
372
373
  /*** Round to correct significand. ***/
374
2110
  ubv extractedSignificand(sig.extract(sigWidth - 1, sigWidth - targetSignificandWidth).extend(1)); // extended to catch the overflow
375
376
  // Normal guard and sticky bits
377
1055
  bwt guardBitPosition(sigWidth - (targetSignificandWidth + 1));
378
1110
  prop guardBit(sig.extract(guardBitPosition, guardBitPosition).isAllOnes());
379
380
1110
  prop stickyBit(!sig.extract(guardBitPosition - 1,0).isAllZeros());
381
382
383
  // For subnormals, locating the guard and stick bits is a bit more involved
384
  //sbv subnormalAmount(uf.getSubnormalAmount(format)); // Catch is, uf isn't in the given format, so this doesn't work
385
2110
  sbv subnormalAmount(expandingSubtract<t>(unpackedFloat<t>::minNormalExponent(format).matchWidth(exp),exp));
386
1055
  INVARIANT((subnormalAmount < sbv(expWidth + 1, sigWidth - 1)) || earlyUnderflow);
387
  // Note that this is negative if normal, giving a full subnormal mask
388
  // but the result will be ignored (see the next invariant)
389
390
391
  // Care is needed if the exponents are longer than the significands
392
  // In the case when data is lost it is negative and not used
393
1055
  bwt extractedSignificandWidth(extractedSignificand.getWidth());
394
2110
  ubv subnormalShiftPrepared((extractedSignificandWidth >= expWidth + 1) ?
395
			     subnormalAmount.toUnsigned().matchWidth(extractedSignificand) :
396
			     subnormalAmount.toUnsigned().extract(extractedSignificandWidth - 1, 0));
397
398
399
  // Compute masks
400
2110
  ubv subnormalMask(orderEncode<t>(subnormalShiftPrepared)); // Invariant implies this if all ones, it will not be used
401
2110
  ubv subnormalStickyMask(subnormalMask >> ubv::one(targetSignificandWidth + 1)); // +1 as the exponent is extended
402
403
  // Apply
404
2110
  ubv subnormalMaskedSignificand(extractedSignificand & (~subnormalMask));
405
2110
  ubv subnormalMaskRemoved(extractedSignificand & subnormalMask);
406
  // Optimisation : remove the masking with a single orderEncodeBitwise style construct
407
408
1110
  prop subnormalGuardBit(!(subnormalMaskRemoved & (~subnormalStickyMask)).isAllZeros());
409
2838
  prop subnormalStickyBit(guardBit || stickyBit ||
410
2728
			  !((subnormalMaskRemoved & subnormalStickyMask).isAllZeros()));
411
412
413
2110
  ubv subnormalIncrementAmount((subnormalMask.modularLeftShift(ubv::one(targetSignificandWidth + 1))) & ~subnormalMask); // The only case when this looses info is earlyUnderflow
414
1055
  INVARIANT(IMPLIES(subnormalIncrementAmount.isAllZeros(), earlyUnderflow || normalRounding));
415
416
417
  // Have to choose the right one dependent on rounding mode
418
1110
  prop choosenGuardBit(ITE(normalRounding, guardBit, subnormalGuardBit));
419
1110
  prop choosenStickyBit(ITE(normalRounding, stickyBit, subnormalStickyBit));
420
421
1110
  prop significandEven(ITE(normalRounding,
422
			   extractedSignificand.extract(0,0).isAllZeros(),
423
			   ((extractedSignificand & subnormalIncrementAmount).isAllZeros())));
424
1110
  prop roundUp(roundingDecision<t>(roundingMode, uf.getSign(), significandEven,
425
				   choosenGuardBit, choosenStickyBit,
426
2000
				   known.exact || (known.subnormalExact && !normalRoundingRange)));
427
428
429
  // Perform the increment as needed
430
2110
  ubv leadingOne(unpackedFloat<t>::leadingOne(targetSignificandWidth));
431
  // Not actually true, consider minSubnormalExponent - 1 : not an early underfow and empty significand
432
  //INVARIANT(!(subnormalMaskedSignificand & leadingOne).isAllZeros() ||
433
  //          earlyUnderflow); // This one really matters, it means only the early underflow path is wrong
434
435
436
  // Convert the round up flag to a mask
437
2110
  ubv normalRoundUpAmount(ubv(roundUp).matchWidth(extractedSignificand));
438
2110
  ubv subnormalRoundUpMask(ubv(roundUp).append(ubv::zero(targetSignificandWidth)).signExtendRightShift(ubv(targetSignificandWidth + 1, targetSignificandWidth)));
439
2110
  ubv subnormalRoundUpAmount(subnormalRoundUpMask & subnormalIncrementAmount);
440
441
2110
  ubv rawRoundedSignificand((ITE(normalRounding,
442
				 extractedSignificand,
443
				 subnormalMaskedSignificand)
444
			     +
445
			     ITE(normalRounding,
446
				 normalRoundUpAmount,
447
				 subnormalRoundUpAmount)));
448
449
  // We might have lost the leading one, if so, re-add and note that we need to increment the significand
450
1110
  prop significandOverflow(rawRoundedSignificand.extract(targetSignificandWidth, targetSignificandWidth).isAllOnes());
451
1055
  INVARIANT(IMPLIES(significandOverflow, roundUp));
452
453
2110
  ubv extractedRoundedSignificand(rawRoundedSignificand.extract(targetSignificandWidth - 1, 0));
454
2110
  ubv roundedSignificand(extractedRoundedSignificand | leadingOne);
455
1055
  INVARIANT(IMPLIES(significandOverflow, extractedRoundedSignificand.isAllZeros()));
456
457
458
459
460
  /*** Round to correct exponent. ***/
461
462
  // The extend is almost certainly unnecessary (see specialised rounders)
463
2110
  sbv extendedExponent(exp.extend(1));
464
465
1110
  prop incrementExponentNeeded(roundUp && significandOverflow);  // The roundUp is implied but kept for signal forwarding
466
1055
  probabilityAnnotation<t>(incrementExponentNeeded, VERYUNLIKELY);
467
1110
  prop incrementExponent(!known.noSignificandOverflow && incrementExponentNeeded);
468
1055
  INVARIANT(IMPLIES(known.noSignificandOverflow, !incrementExponentNeeded));
469
470
2110
  sbv correctedExponent(conditionalIncrement<t>(incrementExponent, extendedExponent));
471
472
  // Track overflows and underflows
473
2110
  sbv maxNormal(unpackedFloat<t>::maxNormalExponent(format).matchWidth(correctedExponent));
474
2110
  sbv minSubnormal(unpackedFloat<t>::minSubnormalExponent(format).matchWidth(correctedExponent));
475
476
2110
  sbv correctedExponentInRange(collar<t>(correctedExponent, minSubnormal, maxNormal));
477
478
479
  // This can over and underflow but these values will not be used
480
1055
  bwt currentExponentWidth(correctedExponentInRange.getWidth());
481
2110
  sbv roundedExponent(correctedExponentInRange.contract(currentExponentWidth - targetExponentWidth));
482
483
484
485
  /*** Finish ***/
486
487
1110
  prop computedOverflow(potentialLateOverflow && incrementExponentNeeded);
488
1110
  prop computedUnderflow(potentialLateUnderflow && !incrementExponentNeeded);
489
1055
  probabilityAnnotation<t>(computedOverflow, UNLIKELY);
490
1055
  probabilityAnnotation<t>(computedUnderflow, UNLIKELY);
491
492
1110
  prop lateOverflow(!earlyOverflow && computedOverflow);
493
1110
  prop lateUnderflow(!earlyUnderflow && computedUnderflow);
494
1055
  probabilityAnnotation<t>(lateOverflow, VERYUNLIKELY);
495
1055
  probabilityAnnotation<t>(lateUnderflow, VERYUNLIKELY);
496
497
498
  // So that ITE abstraction works...
499
1110
  prop overflow(!known.noOverflow && ITE(lateOverflow, prop(true), earlyOverflow));
500
1110
  prop underflow(!known.noUnderflow && ITE(lateUnderflow, prop(true), earlyUnderflow));
501
502
2110
  unpackedFloat<t> roundedResult(uf.getSign(), roundedExponent, roundedSignificand);
503
1055
  unpackedFloat<t> result(rounderSpecialCases<t>(format, roundingMode, roundedResult,
504
						 overflow, underflow, uf.getZero()));
505
506
1055
  POSTCONDITION(result.valid(format));
507
508
2110
  return result;
509
 }
510
511
template <class t>
512
unpackedFloat<t> originalRounder (const typename t::fpt &format,
513
				  const typename t::rm &roundingMode,
514
				  const unpackedFloat<t> &uf) {
515
516
  typedef typename t::bwt bwt;
517
  typedef typename t::prop prop;
518
  typedef typename t::ubv ubv;
519
  typedef typename t::sbv sbv;
520
521
  //PRECONDITION(uf.valid(format));
522
  // Not a precondition because
523
  //  1. Exponent and significand may be extended.
524
  //  2. Their values may also be outside of the correct range.
525
  //
526
  // However some thing do hold:
527
  //  1. Leading bit of the significant is 1   (if you want to get a meaningful answer)
528
  //     (if not, a cancellation on the near path of add can cause
529
  //      this, but the result will not be used, so it can be incorrect)
530
  ubv psig(uf.getSignificand());
531
  bwt sigWidth(psig.getWidth());
532
  //PRECONDITION(psig.extract(sigWidth-1, sigWidth-1).isAllOnes());
533
  ubv sig(psig | unpackedFloat<t>::leadingOne(sigWidth));
534
535
  //  2. Must have round and sticky bits
536
  bwt targetSignificandWidth(unpackedFloat<t>::significandWidth(format));
537
  PRECONDITION(sigWidth >= targetSignificandWidth + 2);
538
539
  //  3. Must have at least enough exponent bits
540
  sbv exp(uf.getExponent());
541
  bwt expWidth(exp.getWidth());
542
  bwt targetExponentWidth(unpackedFloat<t>::exponentWidth(format));
543
  PRECONDITION(expWidth >= targetExponentWidth);
544
545
  // Also, do not round special values.
546
  // Note that this relies on these having default values and
547
  // the code that calls the rounder constructing uf from parts.
548
  PRECONDITION(!uf.getNaN());
549
  PRECONDITION(!uf.getInf());
550
  //PRECONDITION(!uf.getZero());   // The safe choice of default values means this should work OK
551
552
553
554
  /*** Early underflow and overflow detection ***/
555
  bwt exponentExtension(expWidth - targetExponentWidth);
556
  prop earlyOverflow(exp > unpackedFloat<t>::maxNormalExponent(format).extend(exponentExtension));
557
  prop earlyUnderflow(exp < unpackedFloat<t>::minSubnormalExponent(format).extend(exponentExtension).decrement());
558
  // Optimisation : if the precondition on sigWidth and targetSignificandWidth is removed
559
  //                then can change to:
560
  //                   exponent >= minSubnormalExponent - 1
561
  //                && sigWidth > targetSignificandBits
562
563
564
565
  /*** Normal or subnormal rounding? ***/
566
  prop normalRounding(exp >= unpackedFloat<t>::minNormalExponent(format).extend(exponentExtension));
567
  probabilityAnnotation<t>(normalRounding, LIKELY);
568
569
570
  /*** Round to correct significand. ***/
571
  ubv extractedSignificand(sig.extract(sigWidth - 1, sigWidth - targetSignificandWidth));
572
573
  bwt guardBitPosition(sigWidth - (targetSignificandWidth + 1));
574
  prop guardBit(sig.extract(guardBitPosition, guardBitPosition).isAllOnes());
575
576
  prop stickyBit(!sig.extract(guardBitPosition - 1,0).isAllZeros());
577
578
579
  // For subnormals, locating the guard and stick bits is a bit more involved
580
  sbv subnormalAmount(unpackedFloat<t>::maxSubnormalExponent(format).extend(exponentExtension) - exp);
581
  prop belowLimit(subnormalAmount <= sbv::zero(expWidth));    // Not subnormal
582
  prop aboveLimit(subnormalAmount >= sbv(expWidth, targetSignificandWidth));  // Will underflow
583
  sbv subnormalShift(ITE((belowLimit || aboveLimit), sbv::zero(expWidth), subnormalAmount));
584
  // Optimisation : collar
585
586
  bwt extractedSignificandWidth(extractedSignificand.getWidth());
587
  ubv subnormalShiftPrepared((extractedSignificandWidth >= expWidth + 1) ?
588
			     subnormalAmount.toUnsigned().extend(targetSignificandWidth - expWidth) :
589
			     subnormalAmount.toUnsigned().extract(extractedSignificandWidth - 1, 0));
590
  ubv guardLocation(ubv::one(targetSignificandWidth) << subnormalShiftPrepared);
591
  ubv stickyMask(guardLocation.decrement());
592
593
594
  prop subnormalGuardBit(!(extractedSignificand & guardLocation).isAllZeros());
595
  prop subnormalStickyBit(guardBit || stickyBit ||
596
			  !((extractedSignificand & stickyMask).isAllZeros()));
597
598
599
600
601
  // Can overflow but is handled
602
  ubv incrementedSignificand(extractedSignificand.modularIncrement());
603
  prop incrementedSignificandOverflow(incrementedSignificand.isAllZeros());
604
  // Optimisation : conditional increment
605
  // Optimisation : use top bit of significand to increment the exponent
606
607
  ubv correctedIncrementedSignificand(ITE(!incrementedSignificandOverflow,
608
					  incrementedSignificand,
609
					  unpackedFloat<t>::leadingOne(unpackedFloat<t>::significandWidth(format))));
610
611
612
  ubv incrementAmount(guardLocation.modularLeftShift(ubv::one(guardLocation.getWidth()))); // Overflows (safely) in the case of rounding up to the least subnormal.
613
  ubv mask(guardLocation | stickyMask);
614
  ubv maskedSignificand(extractedSignificand & ~mask);
615
616
  ubv subnormalIncrementedSignificand(maskedSignificand.modularAdd(incrementAmount));
617
  prop subnormalIncrementedSignificandOverflow(subnormalIncrementedSignificand.isAllZeros());
618
  ubv subnomalCorrectedIncrementedSignificand(ITE(!subnormalIncrementedSignificandOverflow,
619
						  subnormalIncrementedSignificand,
620
						  unpackedFloat<t>::leadingOne(unpackedFloat<t>::significandWidth(format))));
621
622
623
624
  // Have to choose the right one dependent on rounding mode
625
  prop choosenGuardBit(ITE(normalRounding, guardBit, subnormalGuardBit));
626
  prop choosenStickyBit(ITE(normalRounding, stickyBit, subnormalStickyBit));
627
628
  prop significandEven(ITE(normalRounding,
629
			   extractedSignificand.extract(0,0).isAllZeros(),
630
			   ((extractedSignificand & incrementAmount).isAllZeros())));
631
  prop roundUp(roundingDecision<t>(roundingMode, uf.getSign(), significandEven,
632
				   choosenGuardBit, choosenStickyBit, prop(false)));
633
634
  ubv roundedSignificand(ITE(normalRounding,
635
			     ITE((!roundUp), extractedSignificand, correctedIncrementedSignificand),
636
			     ITE((!roundUp), maskedSignificand, subnomalCorrectedIncrementedSignificand)));
637
638
639
640
  /*** Round to correct exponent. ***/
641
642
  // The extend is almost certainly unnecessary (see specialised rounders)
643
  sbv extendedExponent(exp.extend(1));
644
645
  prop incrementExponent(ITE(normalRounding,
646
			     incrementedSignificandOverflow,
647
			     subnormalIncrementedSignificandOverflow)
648
			 && roundUp);
649
  probabilityAnnotation<t>(incrementExponent, VERYUNLIKELY);
650
651
  sbv correctedExponent(conditionalIncrement<t>(incrementExponent, extendedExponent));
652
653
  // This can over and underflow but these values will not be used
654
  bwt currentExponentWidth(correctedExponent.getWidth());
655
  sbv roundedExponent(correctedExponent.contract(currentExponentWidth - targetExponentWidth));
656
657
658
  /*** Finish ***/
659
  prop computedOverflow(correctedExponent > unpackedFloat<t>::maxNormalExponent(format).extend(currentExponentWidth - targetExponentWidth));
660
  prop computedUnderflow(correctedExponent < unpackedFloat<t>::minSubnormalExponent(format).extend(currentExponentWidth - targetExponentWidth));
661
662
  // So that ITE abstraction works...
663
  prop overflow(ITE(earlyOverflow, prop(true), computedOverflow));
664
  prop underflow(ITE(earlyUnderflow, prop(true), computedUnderflow));
665
666
  unpackedFloat<t> roundedResult(uf.getSign(), roundedExponent, roundedSignificand);
667
  unpackedFloat<t> result(rounderSpecialCases<t>(format, roundingMode, roundedResult,
668
						 overflow, underflow, uf.getZero()));
669
670
  POSTCONDITION(result.valid(format));
671
672
  return result;
673
 }
674
675
676
template <class t>
677
396
  unpackedFloat<t> rounder (const typename t::fpt &format,
678
			    const typename t::rm &roundingMode,
679
			    const unpackedFloat<t> &uf) {
680
  typedef typename t::prop prop;
681
415
  customRounderInfo<t> cri(prop(false), prop(false), prop(false), prop(false), prop(false));  // Default is to know nothing
682
683
  #ifdef USE_ORIGINAL_ROUNDER
684
  return originalRounder(format, roundingMode, uf);  // Allow old versions to be compared
685
  #else
686
415
  return customRounder(format, roundingMode, uf, cri);
687
  #endif
688
 }
689
690
691
}
692
693
#endif