signExtend method

  1. @override
void signExtend()
override

Sign extend the PP array using stop bits. If possible, fold the final carry into another row (only when rectangular enough that carry bit lands outside another row). This technique can then be combined with a first-row extension technique for folding in the final carry.

Implementation

@override
void signExtend() {
  if (signedMultiplicand && (selectSignedMultiplicand != null)) {
    throw RohdHclException('multiplicand sign reconfiguration requires '
        'signedMultiplicand=false');
  }
  if (isSignExtended) {
    throw RohdHclException('Partial Product array already sign-extended');
  }
  isSignExtended = true;

  final finalCarryPos = shift * (rows - 1);
  final finalCarryRelPos = finalCarryPos - selector.width - shift;
  final finalCarryRow =
      ((encoder.multiplier.width > selector.multiplicand.width) &&
              (finalCarryRelPos > 0))
          ? (finalCarryRelPos / shift).floor()
          : 0;

  final signs = [
    for (var r = 0; r < rows; r++)
      encoder
          .fetchEncoding(r)
          .sign
          .named('sign_r$r', naming: Naming.mergeable)
  ];

  for (var row = 0; row < rows; row++) {
    final addend = partialProducts[row];
    final Logic sign;
    if (selectSignedMultiplicand != null) {
      sign = mux(selectSignedMultiplicand!, addend.last, signs[row]);
    } else {
      sign = signedMultiplicand ? addend.last : signs[row];
    }
    if (row == 0) {
      if (!signedMultiplicand) {
        addend.addAll(List.filled(shift, SignBit(sign)));
      } else {
        // either is signed?
        addend.addAll(List.filled(shift - 1, SignBit(sign))); // signed only?
      }
      addend.add(SignBit(~sign, inverted: true));
    } else {
      addStopSign(addend, SignBit(~sign, inverted: true));
      addend
        ..addAll(List.filled(shift - 1, Const(1)))
        ..insertAll(0, List.filled(shift - 1, Const(0)))
        ..insert(0, SignBit(signs[row - 1]));
      rowShift[row] -= shift;
    }
  }

  if (finalCarryRow > 0) {
    final extensionRow = partialProducts[finalCarryRow];
    extensionRow
      ..addAll(List.filled(
          finalCarryPos - (extensionRow.length + rowShift[finalCarryRow]),
          Const(0)))
      ..add(SignBit(signs[rows - 1]));
  } else if (signedMultiplier | (selectSignedMultiplier != null)) {
    // Create an extra row to hold the final carry bit
    partialProducts
        .add(List.filled(selector.width, Const(0), growable: true));
    partialProducts.last.insert(0, SignBit(signs[rows - 2]));
    rowShift.add((rows - 2) * shift);

    // Hack for radix-2
    if (shift == 1) {
      addStopSignFlip(
          partialProducts.last, SignBit(Const(1), inverted: true));
    }
  }
}