-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* compressor with flopped output * cleaned up addend_compressor tests, added random testing
- Loading branch information
1 parent
5bf9681
commit b6f7059
Showing
4 changed files
with
156 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
// 2024 June 04 | ||
// Author: Desmond Kirkpatrick <[email protected]> | ||
|
||
import 'dart:async'; | ||
import 'dart:io'; | ||
import 'dart:math'; | ||
import 'package:rohd/rohd.dart'; | ||
|
@@ -16,12 +17,42 @@ import 'package:rohd_hcl/src/arithmetic/evaluate_partial_product.dart'; | |
import 'package:rohd_hcl/src/arithmetic/partial_product_sign_extend.dart'; | ||
import 'package:test/test.dart'; | ||
|
||
/// A simple module to test partial product generation and compression | ||
class CompressorTestMod extends Module { | ||
late final PartialProductGenerator pp; | ||
|
||
late final ColumnCompressor compressor; | ||
|
||
Logic get r0 => output('r0'); | ||
|
||
Logic get r1 => output('r1'); | ||
|
||
CompressorTestMod(Logic ia, Logic ib, RadixEncoder encoder, Logic? iclk, | ||
{bool signed = true}) | ||
: super(name: 'compressor_test_mod') { | ||
final a = addInput('a', ia, width: ia.width); | ||
final b = addInput('b', ib, width: ib.width); | ||
Logic? clk; | ||
if (iclk != null) { | ||
clk = addInput('clk', iclk); | ||
} | ||
|
||
pp = PartialProductGeneratorCompactRectSignExtension(a, b, encoder, | ||
signed: signed); | ||
compressor = ColumnCompressor(pp, clk: clk); | ||
compressor.compress(); | ||
final r0 = addOutput('r0', width: compressor.columns.length); | ||
final r1 = addOutput('r1', width: compressor.columns.length); | ||
|
||
r0 <= compressor.extractRow(0); | ||
r1 <= compressor.extractRow(1); | ||
} | ||
} | ||
|
||
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++) { | ||
|
@@ -32,51 +63,79 @@ 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'); | ||
|
||
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: $i($X)[$widthX] * $j($Y)[$widthY]: ' | ||
'$adderValue vs expected $product' | ||
'\n$pp'); | ||
|
||
checkCompressor(pp, X, Y); | ||
} | ||
} | ||
} | ||
|
||
void testCompressionRandom(PartialProductGenerator pp, int iterations) { | ||
final widthX = pp.selector.multiplicand.width; | ||
final widthY = pp.encoder.multiplier.width; | ||
|
||
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() { | ||
test('exhaustive compression evaluate: square radix-4, just CompactRect', | ||
tearDown(() async { | ||
await Simulator.reset(); | ||
}); | ||
test('ColumnCompressor: random evaluate: square radix-4, just CompactRect', | ||
() async { | ||
stdout.write('\n'); | ||
|
||
|
@@ -95,13 +154,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); | ||
|
@@ -131,65 +190,37 @@ void main() { | |
expect(compressor.evaluate().$1, equals(BigInt.from(av * bv))); | ||
} | ||
}); | ||
test('single compressor evaluate', () async { | ||
|
||
test('Column Compressor: evaluate flopped', () async { | ||
final clk = SimpleClockGenerator(10).clk; | ||
const widthX = 6; | ||
const widthY = 6; | ||
final a = Logic(name: 'a', width: widthX); | ||
final b = Logic(name: 'b', width: widthY); | ||
|
||
const av = 3; | ||
var av = 3; | ||
const bv = 6; | ||
for (final signed in [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('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 [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))); | ||
} | ||
const radix = 2; | ||
final encoder = RadixEncoder(radix); | ||
final compressorTestMod = CompressorTestMod(a, b, encoder, clk); | ||
await compressorTestMod.build(); | ||
unawaited(Simulator.run()); | ||
var bA = BigInt.from(av).toSigned(widthX); | ||
final bB = BigInt.from(bv).toSigned(widthY); | ||
|
||
// Set these so that printing inside module build will have Logic values | ||
a.put(bA); | ||
b.put(bB); | ||
|
||
await clk.nextNegedge; | ||
expect(compressorTestMod.compressor.evaluate().$1, | ||
equals(BigInt.from(av * bv))); | ||
av = 4; | ||
bA = BigInt.from(av).toSigned(widthX); | ||
a.put(bA); | ||
await clk.nextNegedge; | ||
expect(compressorTestMod.compressor.evaluate().$1, | ||
equals(BigInt.from(av * bv))); | ||
await Simulator.endSimulation(); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters