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 |