FloatingPointAdderSimple constructor

FloatingPointAdderSimple(
  1. FloatingPoint a,
  2. FloatingPoint b, {
  3. ParallelPrefix ppGen(
    1. List<Logic>,
    2. Logic (
      1. Logic,
      2. Logic
      )
    ) = KoggeStone.new,
  4. String name = 'floatingpoint_adder_simple',
})

Add two floating point numbers a and b, returning result in sum

Implementation

FloatingPointAdderSimple(FloatingPoint a, FloatingPoint b,
    {ParallelPrefix Function(List<Logic>, Logic Function(Logic, Logic))
        ppGen = KoggeStone.new,
    super.name = 'floatingpoint_adder_simple'})
    : exponentWidth = a.exponent.width,
      mantissaWidth = a.mantissa.width {
  if (b.exponent.width != exponentWidth ||
      b.mantissa.width != mantissaWidth) {
    throw RohdHclException('FloatingPoint widths must match');
  }
  a = a.clone()..gets(addInput('a', a, width: a.width));
  b = b.clone()..gets(addInput('b', b, width: b.width));
  addOutput('sum', width: _sum.width) <= _sum;

  // Ensure that the larger number is wired as 'a'
  final doSwap = a.exponent.lt(b.exponent) |
      (a.exponent.eq(b.exponent) & a.mantissa.lt(b.mantissa)) |
      ((a.exponent.eq(b.exponent) & a.mantissa.eq(b.mantissa)) & b.sign);

  (a, b) = _swap(doSwap, (a, b));

  final aExp =
      a.exponent + mux(a.isNormal(), a.zeroExponent(), a.oneExponent());
  final bExp =
      b.exponent + mux(b.isNormal(), b.zeroExponent(), b.oneExponent());

  // Align and add mantissas
  final expDiff = aExp - bExp;
  final adder = SignMagnitudeAdder(
      a.sign,
      [a.isNormal(), a.mantissa].swizzle(),
      b.sign,
      [b.isNormal(), b.mantissa].swizzle() >>> expDiff,
      (a, b) => ParallelPrefixAdder(a, b, ppGen: ppGen));

  final sum = adder.sum.slice(adder.sum.width - 2, 0);
  final leadOneE =
      ParallelPrefixPriorityEncoder(sum.reversed, ppGen: ppGen).out;
  final leadOne = leadOneE.zeroExtend(exponentWidth);

  // Assemble the output FloatingPoint
  _sum.sign <= adder.sign;
  Combinational([
    If.block([
      Iff(adder.sum[-1] & a.sign.eq(b.sign), [
        _sum.mantissa < (sum >> 1).slice(mantissaWidth - 1, 0),
        _sum.exponent < a.exponent + 1
      ]),
      ElseIf(a.exponent.gt(leadOne) & sum.or(), [
        _sum.mantissa < (sum << leadOne).slice(mantissaWidth - 1, 0),
        _sum.exponent < a.exponent - leadOne
      ]),
      ElseIf(leadOne.eq(0) & sum.or(), [
        _sum.mantissa < (sum << leadOne).slice(mantissaWidth - 1, 0),
        _sum.exponent < a.exponent - leadOne + 1
      ]),
      Else([
        // subnormal result
        _sum.mantissa < sum.slice(mantissaWidth - 1, 0),
        _sum.exponent < _sum.zeroExponent()
      ])
    ])
  ]);
}