signExtend method
override
Execute the sign extension, overridden to specialize.
Implementation
@override
void signExtend() {
// An implementation of
// Mohanty, B.K., Choubey, A. Efficient Design for Radix-8 Booth Multiplier
// and Its Application in Lifting 2-D DWT. Circuits Syst Signal Process 36,
// 1129–1149 (2017). https://doi.org/10.1007/s00034-016-0349-9
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 lastRow = rows - 1;
final firstAddend = partialProducts[0];
final lastAddend = partialProducts[lastRow];
final firstRowQStart = selector.width - (signedMultiplicand ? 1 : 0);
final lastRowSignPos = shift * lastRow;
final alignRow0Sign = firstRowQStart - lastRowSignPos;
final signs = [
for (var r = 0; r < rows; r++)
encoder
.fetchEncoding(r)
.sign
.named('sign_r$r', naming: Naming.mergeable)
];
final propagate =
List.generate(rows, (i) => List.filled(0, Logic(), growable: true));
for (var row = 0; row < rows; row++) {
propagate[row].add(signs[row]);
for (var col = 0; col < 2 * (shift - 1); col++) {
propagate[row].add(partialProducts[row][col]
.named('propagate_r${row}_c$col', naming: Naming.mergeable));
}
// Last row has extend sign propagation to Q start
if (row == lastRow) {
var col = 2 * (shift - 1);
while (propagate[lastRow].length <= alignRow0Sign) {
propagate[lastRow].add(SignBit(partialProducts[row][col++]));
}
}
for (var col = 1; col < propagate[row].length; col++) {
propagate[row][col] = (propagate[row][col] & propagate[row][col - 1])
.named('propagate_r${row}_c$col', naming: Naming.mergeable);
}
}
final m =
List.generate(rows, (i) => List.filled(0, Logic(), growable: true));
for (var row = 0; row < rows; row++) {
for (var c = 0; c < shift - 1; c++) {
m[row].add((partialProducts[row][c] ^ propagate[row][c])
.named('m_r${row}_c$c', naming: Naming.mergeable));
}
m[row].addAll(List.filled(shift - 1, Logic()));
}
while (m[lastRow].length < alignRow0Sign) {
m[lastRow].add(Logic());
}
// TODO(desmonddak): this seems unused when looking at Verilog output
for (var i = shift - 1; i < m[lastRow].length; i++) {
m[lastRow][i] = (lastAddend[i] ^
(i < alignRow0Sign ? propagate[lastRow][i] : Const(0)))
.named('m_lastr_c$i', naming: Naming.mergeable);
}
final remainders = List.filled(rows, Logic());
for (var row = 0; row < lastRow; row++) {
remainders[row] = propagate[row][shift - 1]
.named('remainders_r$row', naming: Naming.mergeable);
}
remainders[lastRow] <=
propagate[lastRow][max(alignRow0Sign, 0)]
.named('remainders_lastrow', naming: Naming.mergeable);
// Compute Sign extension for row==0
final firstSign = Logic(name: 'firstsign', naming: Naming.mergeable);
if (selectSignedMultiplicand == null) {
firstSign <=
(signedMultiplicand ? SignBit(firstAddend.last) : SignBit(signs[0]));
} else {
firstSign <=
SignBit(mux(selectSignedMultiplicand!, firstAddend.last, signs[0]));
}
final q = [
(firstSign ^ remainders[lastRow])
.named('qfirst', naming: Naming.mergeable),
(~(firstSign & ~remainders[lastRow]))
.named('q_last', naming: Naming.mergeable),
];
q.insertAll(1, List.filled(shift - 1, ~q[1]));
for (var row = 0; row < rows; row++) {
final addend = partialProducts[row];
if (row > 0) {
final mLimit = (row == lastRow) ? alignRow0Sign : shift - 1;
for (var i = 0; i < mLimit; i++) {
addend[i] = m[row][i];
}
addStopSignFlip(addend, SignBit(~signs[row], inverted: true));
addend
..insert(0, remainders[row - 1])
..addAll(List.filled(shift - 1, Const(1)));
rowShift[row] -= 1;
} else {
for (var i = 0; i < shift - 1; i++) {
firstAddend[i] = m[0][i];
}
if (!signedMultiplicand) {
firstAddend.add(q[0]);
} else {
firstAddend.last = q[0];
}
firstAddend.addAll(q.getRange(1, q.length));
}
}
if (shift == 1) {
lastAddend.add(Const(1));
}
}