Skip to content

Commit

Permalink
fixed addend-compressor testing
Browse files Browse the repository at this point in the history
  • Loading branch information
desmonddak committed Nov 5, 2024
1 parent 3dc669b commit d098f94
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 117 deletions.
11 changes: 8 additions & 3 deletions lib/src/arithmetic/addend_compressor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -170,16 +170,21 @@ class ColumnCompressor {
/// The partial product array to be compressed
final PartialProductArray pp;

/// The clk
/// The clk for the pipelined version of column compression.
Logic? clk;

/// Optional reset
/// Optional reset for configurable pipestage
Logic? reset;

/// Optional enable
/// Optional enable for configurable pipestage.
Logic? enable;

/// Initialize a ColumnCompressor for a set of partial products
///
/// If [clk] is not null then a set of flops are used to latch the output
/// after compression (see [extractRow]). [reset] and [enable] are optional
/// inputs to control these flops when [clk] is provided. If [clk] is null,
/// the [ColumnCompressor] is built as a combinational tree of compressors.
ColumnCompressor(this.pp, {this.clk, this.reset, this.enable}) {
columns = List.generate(pp.maxWidth(), (i) => ColumnQueue());

Expand Down
189 changes: 75 additions & 114 deletions test/arithmetic/addend_compressor_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ void testCompressionExhaustive(PartialProductGenerator pp) {
final widthX = pp.selector.multiplicand.width;
final widthY = pp.encoder.multiplier.width;

final compressor = ColumnCompressor(pp);

final limitX = pow(2, widthX);
final limitY = pow(2, widthY);
for (var i = 0; i < limitX; i++) {
Expand All @@ -65,54 +63,80 @@ void testCompressionExhaustive(PartialProductGenerator pp) {
final Y = pp.signed
? BigInt.from(j).toSigned(widthY)
: BigInt.from(j).toUnsigned(widthY);
final product = X * Y;

pp.multiplicand.put(X);
pp.multiplier.put(Y);
final value = pp.evaluate();
expect(value, equals(product),
reason: 'Fail: $i($X) * $j($Y): $value '
'vs expected $product'
'\n$pp');
final evaluateValue = compressor.evaluate();
if (evaluateValue.$1 != product) {
stdout
..write('Fail: $i($X)[$widthX] * $j($Y)[$widthY]: $evaluateValue '
'vs expected $product\n')
..write(pp);
}
compressor.compress();
final compressedValue = compressor.evaluate().$1;
expect(compressedValue, equals(product),
reason: 'Fail: $i($X)[$widthX] * $j($Y)[$widthY]: $compressedValue '
'vs expected $product'
'\n$pp');
final compressedLogicValue = compressor.evaluate(logic: true).$1;
expect(compressedLogicValue, equals(product),
reason:
'Fail: $i($X)[$widthX] * $j($Y)[$widthY]: $compressedLogicValue '
'vs expected $product'
'\n$pp');
checkCompressor(pp, X, Y);
}
}
}

final a = compressor.extractRow(0);
final b = compressor.extractRow(1);
void testCompressionRandom(PartialProductGenerator pp, int iterations) {
final widthX = pp.selector.multiplicand.width;
final widthY = pp.encoder.multiplier.width;

final adder = ParallelPrefixAdder(a, b);
final adderValue =
adder.sum.value.toBigInt().toSigned(compressor.columns.length);
expect(adderValue, equals(product),
reason: 'Fail: $i($X)[$widthX] * $j($Y)[$widthY]: '
'$adderValue vs expected $product'
'\n$pp');
}
final value = Random(47);
for (var i = 0; i < iterations; i++) {
final X = pp.signed
? value.nextLogicValue(width: widthX).toBigInt().toSigned(widthX)
: value.nextLogicValue(width: widthX).toBigInt().toUnsigned(widthX);
;
final Y = pp.signed
? value.nextLogicValue(width: widthY).toBigInt().toSigned(widthY)
: value.nextLogicValue(width: widthY).toBigInt().toUnsigned(widthY);

checkCompressor(pp, X, Y);
}
}

void checkCompressor(PartialProductGenerator pp, BigInt X, BigInt Y) {
final widthX = pp.selector.multiplicand.width;
final widthY = pp.encoder.multiplier.width;
final compressor = ColumnCompressor(pp);

final product = X * Y;

pp.multiplicand.put(X);
pp.multiplier.put(Y);
final value = pp.evaluate();
expect(value, equals(product),
reason: 'Fail: $X * $Y: $value '
'vs expected $product'
'\n$pp');
final evaluateValue = compressor.evaluate();
if (evaluateValue.$1 != product) {
stdout
..write('Fail: $X)$widthX] * $Y[$widthY]: $evaluateValue '
'vs expected $product\n')
..write(pp);
}
compressor.compress();
final compressedValue = compressor.evaluate().$1;
expect(compressedValue, equals(product),
reason: 'Fail: $X[$widthX] * $Y[$widthY]: $compressedValue '
'vs expected $product'
'\n$pp');
final compressedLogicValue = compressor.evaluate(logic: true).$1;
expect(compressedLogicValue, equals(product),
reason: 'Fail: $X[$widthX] * $Y[$widthY]: $compressedLogicValue '
'vs expected $product'
'\n$pp');

final a = compressor.extractRow(0);
final b = compressor.extractRow(1);

final adder = ParallelPrefixAdder(a, b);
final adderValue =
adder.sum.value.toBigInt().toSigned(compressor.columns.length);
expect(adderValue, equals(product),
reason: 'Fail: $X[$widthX] * $Y[$widthY]: '
'$adderValue vs expected $product'
'\n$pp');
}

void main() {
tearDown(() async {
await Simulator.reset();
});
test('exhaustive compression evaluate: square radix-4, just CompactRect',
test('ColumnCompressor: random evaluate: square radix-4, just CompactRect',
() async {
stdout.write('\n');

Expand All @@ -131,13 +155,13 @@ void main() {
Logic(name: 'Y', width: width), encoder,
signed: signed);

testCompressionExhaustive(pp);
testCompressionRandom(pp, 30);
}
}
}
}
});
test('single compressor evaluate multiply', () async {
test('Column Compressor: single compressor evaluate', () async {
const widthX = 6;
const widthY = 9;
final a = Logic(name: 'a', width: widthX);
Expand Down Expand Up @@ -167,39 +191,8 @@ void main() {
expect(compressor.evaluate().$1, equals(BigInt.from(av * bv)));
}
});
test('single compressor evaluate', () async {
const widthX = 6;
const widthY = 6;
final a = Logic(name: 'a', width: widthX);
final b = Logic(name: 'b', width: widthY);

const av = 3;
const bv = 6;
for (final signed in [false, true]) {
final bA = signed
? BigInt.from(av).toSigned(widthX)
: BigInt.from(av).toUnsigned(widthX);
final bB = signed
? BigInt.from(bv).toSigned(widthY)
: BigInt.from(bv).toUnsigned(widthY);

// Set these so that printing inside module build will have Logic values
a.put(bA);
b.put(bB);
const radix = 2;
final encoder = RadixEncoder(radix);

final pp = PartialProductGeneratorCompactRectSignExtension(a, b, encoder,
signed: signed);
expect(pp.evaluate(), equals(BigInt.from(av * bv)));
final compressor = ColumnCompressor(pp);
expect(compressor.evaluate().$1, equals(BigInt.from(av * bv)));
compressor.compress();
expect(compressor.evaluate().$1, equals(BigInt.from(av * bv)));
}
});

test('single compressor evaluate flopped', () async {
test('Column Compressor: evaluate flopped', () async {
final clk = SimpleClockGenerator(10).clk;
const widthX = 6;
const widthY = 6;
Expand All @@ -208,7 +201,13 @@ void main() {

var av = 3;
const bv = 6;
const radix = 2;
final encoder = RadixEncoder(radix);
unawaited(Simulator.run());
for (final signed in [false, true]) {
final compressorTestMod =
CompressorTestMod(a, b, encoder, clk, signed: signed);
await compressorTestMod.build();
var bA = signed
? BigInt.from(av).toSigned(widthX)
: BigInt.from(av).toUnsigned(widthX);
Expand All @@ -219,57 +218,19 @@ void main() {
// Set these so that printing inside module build will have Logic values
a.put(bA);
b.put(bB);
const radix = 2;
final encoder = RadixEncoder(radix);

final compressorTestMod = CompressorTestMod(a, b, encoder, clk);
await compressorTestMod.build();

unawaited(Simulator.run());

await clk.nextNegedge;
expect(compressorTestMod.compressor.evaluate().$1,
equals(BigInt.from(av * bv)));
av = 4;
bA = signed
? BigInt.from(av).toSigned(widthX)
: BigInt.from(bv).toUnsigned(widthX);
: BigInt.from(av).toUnsigned(widthX);
a.put(bA);
await clk.nextNegedge;
expect(compressorTestMod.compressor.evaluate().$1,
equals(BigInt.from(av * bv)));

await Simulator.endSimulation();
}
});

test('example multiplier', () async {
const widthX = 10;
const widthY = 10;
final a = Logic(name: 'a', width: widthX);
final b = Logic(name: 'b', width: widthY);

const av = 37;
const bv = 6;
for (final signed in [false, true]) {
final bA = signed
? BigInt.from(av).toSigned(widthX)
: BigInt.from(av).toUnsigned(widthX);
final bB = signed
? BigInt.from(bv).toSigned(widthY)
: BigInt.from(bv).toUnsigned(widthY);

// Set these so that printing inside module build will have Logic values
a.put(bA);
b.put(bB);
const radix = 8;
final encoder = RadixEncoder(radix);

final pp = PartialProductGeneratorCompactRectSignExtension(a, b, encoder,
signed: signed);
expect(pp.evaluate(), equals(BigInt.from(av * bv)));
final compressor = ColumnCompressor(pp)..compress();
expect(compressor.evaluate().$1, equals(BigInt.from(av * bv)));
}
await Simulator.endSimulation();
});
}

0 comments on commit d098f94

Please sign in to comment.