FixedToFloat constructor
- FixedPoint fixed, {
- required int exponentWidth,
- required int mantissaWidth,
- String name = 'FixedToFloat',
Constructor
Implementation
FixedToFloat(FixedPoint fixed,
{required this.exponentWidth,
required this.mantissaWidth,
super.name = 'FixedToFloat'}) {
fixed = fixed.clone()..gets(addInput('fixed', fixed, width: fixed.width));
addOutput('float', width: _float.width) <= _float;
final bias = FloatingPointValue.computeBias(exponentWidth);
final eMax = pow(2, exponentWidth) - 2;
final iWidth =
(2 + max(fixed.n, max(log2Ceil(fixed.width), exponentWidth))).toInt();
// Special handling needed for E4M3 as it does not support inf
if ((exponentWidth == 4) && (mantissaWidth == 3)) {
UnimplementedError('E4M3 is not supported.');
}
// Extract sign bit
if (fixed.signed) {
_float.sign <= fixed[-1];
} else {
_float.sign <= Const(0);
}
final absValue = Logic(name: 'absValue', width: fixed.width)
..gets(mux(_float.sign, ~(fixed - 1), fixed));
final jBit =
ParallelPrefixPriorityEncoder(absValue.reversed).out.zeroExtend(iWidth);
// Extract mantissa
final mantissa = Logic(name: 'mantissa', width: mantissaWidth);
final guard = Logic(name: 'guardBit');
final sticky = Logic(name: 'stickBit');
final j = Logic(name: 'j', width: iWidth);
final maxShift = fixed.width - fixed.n + bias - 2;
// Limit to minimum exponent
if (maxShift > 0) {
j <= mux(jBit.gt(maxShift), Const(maxShift, width: iWidth), jBit);
} else {
j <= jBit;
}
// Align mantissa
final absValueShifted =
Logic(width: max(absValue.width, mantissaWidth + 2));
if (absValue.width < mantissaWidth + 2) {
final zeros = Const(0, width: mantissaWidth + 2 - absValue.width);
absValueShifted <= [absValue, zeros].swizzle() << j;
} else {
absValueShifted <= absValue << j;
}
mantissa <= absValueShifted.getRange(-mantissaWidth - 1, -1);
guard <= absValueShifted.getRange(-mantissaWidth - 2, -mantissaWidth - 1);
sticky <= absValueShifted.getRange(0, -mantissaWidth - 2).or();
/// Round to nearest even: mantissa | guard sticky
final roundUp = guard & (sticky | mantissa[0]);
final mantissaRounded = mux(roundUp, mantissa + 1, mantissa);
// Calculate biased exponent
final eRaw = mux(
absValueShifted[-1],
Const(bias + fixed.width - fixed.n - 1, width: iWidth) - j,
Const(0, width: iWidth));
final eRawRne = mux(roundUp & ~mantissaRounded.or(), eRaw + 1, eRaw);
// Select output handling corner cases
final expoLessThanOne = eRawRne[-1] | ~eRawRne.or();
final expoMoreThanMax = ~eRawRne[-1] & (eRawRne.gt(eMax));
Combinational([
If.block([
Iff(~absValue.or(), [
// Zero
_float.exponent < Const(0, width: exponentWidth),
_float.mantissa < Const(0, width: mantissaWidth),
]),
ElseIf(expoMoreThanMax, [
// Infinity
_float.exponent < LogicValue.filled(exponentWidth, LogicValue.one),
_float.mantissa < Const(0, width: mantissaWidth),
]),
ElseIf(expoLessThanOne, [
// Subnormal
_float.exponent < Const(0, width: exponentWidth),
_float.mantissa < mantissaRounded
]),
Else([
// Normal
_float.exponent < eRawRne.slice(exponentWidth - 1, 0),
_float.mantissa < mantissaRounded
])
])
]);
}