1 |
|
/* |
2 |
|
** Copyright (C) 2018 Martin Brain |
3 |
|
** |
4 |
|
** See the file LICENSE for licensing information. |
5 |
|
*/ |
6 |
|
|
7 |
|
/* |
8 |
|
** packing.h |
9 |
|
** |
10 |
|
** Martin Brain |
11 |
|
** martin.brain@cs.ox.ac.uk |
12 |
|
** 03/06/14 |
13 |
|
** |
14 |
|
** Algorithms for converting from a packed float (a bit vector) into |
15 |
|
** the working, unpacked float format. Should be instantiated with a |
16 |
|
** traits structure from one of the baseTypes/ implementations. |
17 |
|
** |
18 |
|
*/ |
19 |
|
|
20 |
|
#include "symfpu/core/unpackedFloat.h" |
21 |
|
|
22 |
|
#ifndef SYMFPU_PACKING |
23 |
|
#define SYMFPU_PACKING |
24 |
|
|
25 |
|
namespace symfpu { |
26 |
|
|
27 |
|
template<class t> |
28 |
343 |
unpackedFloat<t> unpack (const typename t::fpt format, const typename t::ubv &packedFloat) { |
29 |
|
typedef typename t::bwt bwt; |
30 |
|
typedef typename t::prop prop; |
31 |
|
typedef typename t::ubv ubv; |
32 |
|
typedef typename t::sbv sbv; |
33 |
|
|
34 |
343 |
bwt pWidth = format.packedWidth(); |
35 |
343 |
bwt exWidth = format.packedExponentWidth(); |
36 |
343 |
bwt sigWidth = format.packedSignificandWidth(); |
37 |
|
|
38 |
343 |
PRECONDITION(packedFloat.getWidth() == pWidth); |
39 |
|
|
40 |
|
// Extract |
41 |
686 |
ubv packedSignificand(packedFloat.extract(sigWidth - 1, 0)); |
42 |
686 |
ubv packedExponent(packedFloat.extract(sigWidth + exWidth - 1, sigWidth)); |
43 |
361 |
prop sign(packedFloat.extract(pWidth - 1, sigWidth + exWidth).isAllOnes()); |
44 |
|
|
45 |
|
// Prepare the normal and subnormal cases |
46 |
343 |
bwt unpackedExWidth = unpackedFloat<t>::exponentWidth(format); |
47 |
343 |
bwt unpackedSigWidth = unpackedFloat<t>::significandWidth(format); |
48 |
|
|
49 |
343 |
INVARIANT(unpackedExWidth > exWidth); // To avoid overflow |
50 |
686 |
sbv biasedExponent(packedExponent.extend(unpackedExWidth - exWidth).toSigned() - unpackedFloat<t>::bias(format)); |
51 |
|
// Optimisation : both the normal and subnormal paths subtract a constant |
52 |
|
// from the exponent as the last step (bias and minNormalExponent respectively) |
53 |
|
|
54 |
686 |
ubv significandWithLeadingZero(packedSignificand.extend(unpackedSigWidth - sigWidth)); |
55 |
686 |
ubv significandWithLeadingOne(unpackedFloat<t>::leadingOne(unpackedFloat<t>::significandWidth(format)) | significandWithLeadingZero); |
56 |
|
|
57 |
686 |
unpackedFloat<t> ufNormal(sign, biasedExponent, significandWithLeadingOne); |
58 |
686 |
unpackedFloat<t> ufSubnormalBase(sign, unpackedFloat<t>::minNormalExponent(format), significandWithLeadingZero); |
59 |
|
|
60 |
|
// Optimisation : right shift the significand by one if subnormal |
61 |
|
// and then set the carry in when you add to the exponent. |
62 |
|
// May be sufficient to just assert that it has a leading zero |
63 |
|
|
64 |
|
|
65 |
|
// Analyse |
66 |
361 |
prop zeroExponent(packedExponent.isAllZeros()); |
67 |
361 |
prop onesExponent(packedExponent.isAllOnes()); |
68 |
361 |
prop zeroSignificand(significandWithLeadingZero.isAllZeros()); // Shared with normaliseUp |
69 |
|
|
70 |
|
// Identify the cases |
71 |
361 |
prop isZero(zeroExponent && zeroSignificand); |
72 |
361 |
prop isSubnormal(zeroExponent && !zeroSignificand); |
73 |
361 |
prop isNormal(!zeroExponent && !onesExponent); |
74 |
361 |
prop isInf(onesExponent && zeroSignificand); |
75 |
361 |
prop isNaN(onesExponent && !zeroSignificand); |
76 |
|
|
77 |
343 |
INVARIANT(isZero || isSubnormal || isNormal || isInf || isNaN); |
78 |
|
|
79 |
343 |
probabilityAnnotation<t,prop>(isSubnormal, UNLIKELY); |
80 |
|
|
81 |
|
// Splice together |
82 |
993 |
unpackedFloat<t> uf(ITE(isNaN, |
83 |
|
unpackedFloat<t>::makeNaN(format), |
84 |
|
ITE(isInf, |
85 |
|
unpackedFloat<t>::makeInf(format, sign), |
86 |
|
ITE(isZero, |
87 |
|
unpackedFloat<t>::makeZero(format, sign), |
88 |
650 |
ITE(!isSubnormal, |
89 |
|
ufNormal, |
90 |
|
ufSubnormalBase.normaliseUp(format) ))))); |
91 |
|
|
92 |
343 |
POSTCONDITION(uf.valid(format)); |
93 |
|
|
94 |
686 |
return uf; |
95 |
|
} |
96 |
|
|
97 |
|
|
98 |
|
template<class t> |
99 |
6132 |
typename t::ubv pack (const typename t::fpt &format, const unpackedFloat<t> &uf) { |
100 |
|
typedef typename t::bwt bwt; |
101 |
|
typedef typename t::prop prop; |
102 |
|
typedef typename t::ubv ubv; |
103 |
|
typedef typename t::sbv sbv; |
104 |
|
|
105 |
6132 |
PRECONDITION(uf.valid(format)); |
106 |
|
|
107 |
|
// Sign |
108 |
12264 |
ubv packedSign(uf.getSign()); |
109 |
|
|
110 |
|
// Exponent |
111 |
6132 |
bwt packedExWidth(format.packedExponentWidth()); |
112 |
|
|
113 |
9105 |
prop inNormalRange(uf.inNormalRange(format, prop(true))); |
114 |
6132 |
INVARIANT(inNormalRange || uf.inSubnormalRange(format, prop(true))); // Default values ensure this. |
115 |
|
//prop inSubnormalRange(uf.inSubnormalRange(format)); // Allowing this optimisation |
116 |
9105 |
prop inSubnormalRange(!inNormalRange); |
117 |
|
|
118 |
6132 |
probabilityAnnotation<t,prop>(inNormalRange, LIKELY); |
119 |
6132 |
probabilityAnnotation<t,prop>(inSubnormalRange, UNLIKELY); |
120 |
|
|
121 |
12264 |
sbv biasedExp(uf.getExponent() + unpackedFloat<t>::bias(format)); |
122 |
|
// Will be correct for normal values only, subnormals may still be negative. |
123 |
12264 |
ubv packedBiasedExp(biasedExp.toUnsigned().extract(packedExWidth - 1,0)); |
124 |
|
|
125 |
12264 |
ubv maxExp(ubv::allOnes(packedExWidth)); |
126 |
12264 |
ubv minExp(ubv::zero(packedExWidth)); |
127 |
|
|
128 |
9105 |
prop hasMaxExp(uf.getNaN() || uf.getInf()); |
129 |
9105 |
prop hasMinExp(uf.getZero() || inSubnormalRange); |
130 |
9105 |
prop hasFixedExp(hasMaxExp || hasMinExp); |
131 |
|
|
132 |
12264 |
ubv packedExp(ITE(hasFixedExp, |
133 |
|
ITE(hasMaxExp, maxExp, minExp), |
134 |
|
packedBiasedExp)); |
135 |
|
|
136 |
|
|
137 |
|
// Significand |
138 |
6132 |
bwt packedSigWidth = format.packedSignificandWidth(); |
139 |
12264 |
ubv unpackedSignificand(uf.getSignificand()); |
140 |
6132 |
bwt unpackedSignificandWidth = unpackedSignificand.getWidth(); |
141 |
|
|
142 |
6132 |
INVARIANT(packedSigWidth == unpackedSignificandWidth - 1); |
143 |
12264 |
ubv dropLeadingOne(unpackedSignificand.extract(packedSigWidth - 1,0)); |
144 |
|
|
145 |
12264 |
ubv subnormalShiftAmount(uf.getSubnormalAmount(format).toUnsigned()); |
146 |
12264 |
ubv shiftAmount((subnormalShiftAmount.getWidth() <= unpackedSignificandWidth) ? |
147 |
|
subnormalShiftAmount.matchWidth(unpackedSignificand) : |
148 |
|
subnormalShiftAmount.extract(unpackedSignificandWidth - 1, 0)); |
149 |
|
// The extraction could loose data if exponent is much larger than the significand |
150 |
|
// However getSubnormalAmount is between 0 and packedSigWidth so it should be safe |
151 |
12264 |
ubv correctedSubnormal((unpackedSignificand >> shiftAmount).extract(packedSigWidth - 1,0)); |
152 |
|
|
153 |
9105 |
prop hasFixedSignificand(uf.getNaN() || uf.getInf() || uf.getZero()); |
154 |
|
|
155 |
18396 |
ubv packedSig(ITE(hasFixedSignificand, |
156 |
6132 |
ITE(uf.getNaN(), |
157 |
|
unpackedFloat<t>::nanPattern(packedSigWidth), |
158 |
|
ubv::zero(packedSigWidth)), |
159 |
|
ITE(inNormalRange, |
160 |
|
dropLeadingOne, |
161 |
|
correctedSubnormal))); |
162 |
|
|
163 |
|
|
164 |
|
// Finish up |
165 |
6132 |
ubv packed(packedSign.append(packedExp).append(packedSig)); |
166 |
|
|
167 |
6132 |
POSTCONDITION(packed.getWidth() == format.packedWidth()); |
168 |
|
|
169 |
12264 |
return packed; |
170 |
|
} |
171 |
|
|
172 |
|
} |
173 |
|
|
174 |
|
#endif |