Skip to content

Commit

Permalink
BitCompressors use terms instead of bitvector
Browse files Browse the repository at this point in the history
  • Loading branch information
desmonddak committed Nov 20, 2024
1 parent 5668789 commit 73aac77
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 55 deletions.
51 changes: 25 additions & 26 deletions lib/src/arithmetic/addend_compressor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
import 'package:rohd/rohd.dart';
import 'package:rohd_hcl/src/arithmetic/evaluate_compressor.dart';
import 'package:rohd_hcl/src/arithmetic/multiplier_lib.dart';
import 'package:rohd_hcl/src/exceptions.dart';

Expand Down Expand Up @@ -122,7 +121,7 @@ class CompressTerm implements Comparable<CompressTerm> {
String toString() {
final str = StringBuffer();
final ts = switch (type) {
CompressTermType.pp => 'p',
CompressTermType.pp => 'pp',
CompressTermType.carry => 'c',
CompressTermType.cout => 'o',
CompressTermType.sum => 's',
Expand All @@ -135,8 +134,6 @@ class CompressTerm implements Comparable<CompressTerm> {
}
}

// TODO(desmonddak): Could we use List<CompressTerms> in constructor instead
// PRoblem is we pass BitCOmpressor into CompressTErm constructor for delay
/// Base class for bit-level column compressor function
abstract class BitCompressor extends Module {
/// Input bits to compress
Expand All @@ -155,12 +152,11 @@ abstract class BitCompressor extends Module {
late final List<List<double>> _delays;

/// Construct a column compressor.
BitCompressor(Logic compressBits) {
this.compressBits = addInput(
'compressBits',
compressBits,
width: compressBits.width,
);
BitCompressor(this.terms) {
compressBits = [
for (var pos = 0; pos < terms.length; pos++)
addInput('t_$pos', terms[pos].logic)
].swizzle();
addOutput('sum');
addOutput('carry');
_delays = List.filled(CompressTermType.values.length,
Expand All @@ -175,7 +171,7 @@ abstract class BitCompressor extends Module {
/// 2-input column compressor (half-adder)
class Compressor2 extends BitCompressor {
/// Construct a 2-input compressor (half-adder).
Compressor2(super.compressBits) {
Compressor2(super.terms) {
sum <= compressBits.xor();
carry <= compressBits.and();
_delays[CompressTermType.sum.index][CompressTermType.pp.index] = 1.0;
Expand All @@ -186,12 +182,13 @@ class Compressor2 extends BitCompressor {
/// 3-input column compressor (full-adder)
class Compressor3 extends BitCompressor {
/// Construct a 3-input column compressor (full-adder).
Compressor3(super.compressBits) {
Compressor3(super.terms) {
sum <= compressBits.xor();
carry <=
mux(compressBits[0], compressBits.slice(2, 1).or(),
compressBits.slice(2, 1).and());
// TODO(desmonddak): wiring different inputs for different delays
// means we may need to index by input not just type
_delays[CompressTermType.sum.index][CompressTermType.pp.index] = 1.0;
_delays[CompressTermType.carry.index][CompressTermType.pp.index] = 1.5;
}
Expand All @@ -203,14 +200,17 @@ class Compressor4 extends BitCompressor {
Logic get cout => output('cout');

/// Construct a 4-input column compressor using two 3-input compressors.
Compressor4(super.compressBits, List<Logic> cinL) {
Compressor4(List<CompressTerm> terms, List<CompressTerm> cinL)
: super(terms) {
for (final cin in cinL) {
addInput('cin', cin);
addInput('cin', cin.logic);
}
addOutput('cout');
final c3A = Compressor3(compressBits.slice(2, 0));
final c3A = Compressor3(terms.sublist(1, 4));
cout <= c3A.carry;
final c3B = Compressor3([c3A.sum, compressBits[3], cinL[0]].swizzle());
final t = CompressTerm(
c3A, CompressTermType.sum, c3A.sum, terms.sublist(1, 4), 0, 0);
final c3B = Compressor3([t, terms[0], cinL[0]]);
carry <= c3B.carry;
sum <= c3B.sum;

Expand Down Expand Up @@ -256,6 +256,9 @@ class ColumnCompressor {
/// 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.
///
/// [use42Compressors] will combine 4:2, 3:2, and 2:2 compressors in building
/// a compression tree.
ColumnCompressor(this.pp,
{this.use42Compressors = false, this.clk, this.reset, this.enable}) {
columns = List.generate(pp.maxWidth(), (i) => ColumnQueue());
Expand Down Expand Up @@ -317,25 +320,23 @@ class ColumnCompressor {
BitCompressor compressor;
if (depth > 4 && use42Compressors) {
final cin = carryQueue.isNotEmpty
? [carryQueue.removeFirst().logic]
: <Logic>[Const(0)];
? carryQueue.removeFirst()
: CompressTerm(null, CompressTermType.cin, Const(0), [], 0, 0);
inputs
..add(queue.removeFirst())
..add(queue.removeFirst());
compressor =
Compressor4([for (final i in inputs) i.logic].swizzle(), cin);

compressor = Compressor4(inputs, [cin]);
if (col < columns.length - 1) {
final t = CompressTerm(compressor, CompressTermType.carry,
(compressor as Compressor4).cout, inputs, 0, col);
carryColumns[col + 1].add(t);
}
} else if (depth > 3) {
inputs.add(queue.removeFirst());
compressor =
Compressor3([for (final i in inputs) i.logic].swizzle());
compressor = Compressor3(inputs);
} else {
compressor =
Compressor2([for (final i in inputs) i.logic].swizzle());
compressor = Compressor2(inputs);
}
final t = CompressTerm(
compressor, CompressTermType.sum, compressor.sum, inputs, 0, col);
Expand All @@ -359,8 +360,6 @@ class ColumnCompressor {
var iterations = longestColumn();
while (iterations > 0) {
terms.addAll(_compressIter(iterations--));
// final cc = this;
// print(cc.representation());
if (longestColumn() <= 2) {
break;
}
Expand Down
24 changes: 14 additions & 10 deletions test/arithmetic/addend_compressor_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
// 2024 June 04
// Author: Desmond Kirkpatrick <[email protected]>

// ignore_for_file: avoid_print

import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'package:meta/meta.dart';
import 'package:rohd/rohd.dart';
import 'package:rohd_hcl/rohd_hcl.dart';
import 'package:rohd_hcl/src/arithmetic/evaluate_compressor.dart';
Expand Down Expand Up @@ -146,7 +147,16 @@ void main() {
final bits = Logic(width: 4);
final cin = [Logic()];

final compressor = Compressor4(bits, cin);
final inputs = [
for (var i = 0; i < bits.width; i++)
CompressTerm(null, CompressTermType.pp, bits[i], [], 0, 0)
];
final carryInputs = [
for (var i = 0; i < cin.length; i++)
CompressTerm(null, CompressTermType.pp, cin[i], [], 0, 0)
];

final compressor = Compressor4(inputs, carryInputs);

for (var cVal = 0; cVal < 2; cVal++) {
cin[0].put(cVal);
Expand Down Expand Up @@ -190,8 +200,7 @@ void main() {
Logic(name: 'Y', width: width), encoder,
signed: signed);
}
// testCompressionRandom(pp, 10, use42Compressors: true);
testCompressionExhaustive(pp, use42Compressors: true);
testCompressionRandom(pp, 10, use42Compressors: true);
}
}
}
Expand Down Expand Up @@ -358,15 +367,10 @@ void main() {

final pp = PartialProductGeneratorStopBitsSignExtension(a, b, encoder);

// print(pp.representation());

expect(pp.evaluate(), equals(bA * bB));
final compressor = ColumnCompressor(pp, use42Compressors: true);
// print(compressor.representation());
expect(compressor.evaluate().$1, equals(bA * bB));
compressor.compress();
// print(compressor.representation());

expect(compressor.evaluate().$1, equals(bA * bB));
expect(compressor.evaluate(logic: true).$1, equals(bA * bB));
});
}
45 changes: 26 additions & 19 deletions test/arithmetic/multiplier_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -595,24 +595,31 @@ void main() {
expect(ppG0.getAbsolute(1, 9).value, equals(Const(1).value));
expect(ppG0.getAbsolute(1, 10).value, equals(Const(0).value));

// final cc = ColumnCompressor(ppG0);
// const expectedRep = '''
// pp3,15 pp3,14 pp3,13 pp3,12 pp3,11 pp3,10 pp3,9 pp3,8 pp3,7 pp3,6 pp3,5 pp2,4 pp2,3 pp1,2 pp1,1 pp0,0
// pp2,13 pp2,12 pp1,11 pp2,10 pp2,9 pp2,8 pp2,7 pp2,6 pp2,5 pp0,4 pp0,3 pp0,2 pp0,1
// pp2,11 pp1,10 pp1,9 pp1,8 pp1,7 pp1,6 pp1,5 pp1,4 pp1,3
// pp0,10 pp0,9 pp0,8 pp0,7 pp0,6 pp0,5
// ''';
// expect(cc.representation(), equals(expectedRep));

// final (v, ts) = cc.evaluate(printOut: true);

// const expectedEval = '''
// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// 1 I 0 0 0 0 0 0 1 1 0 0 0 1 1 0 = 49350 (-16186)
// 1 I 1 0 0 0 0 0 0 0 1 0 0 = 14344 (14344)
// 0 i 1 0 0 0 0 1 1 = 536 (536)
// i S S 1 1 0 = 960 (960)
// p 1 1 1 1 1 1 1 0 1 0 1 0 0 1 1 0 = 65190 (-346)''';
// expect(ts.toString(), equals(expectedEval));
final cc = ColumnCompressor(ppG0);
const expectedRep = '''
pp3,15 pp3,14 pp3,13 pp3,12 pp3,11 pp3,10 pp3,9 pp3,8 pp3,7 pp3,6 pp3,5 pp2,4 pp2,3 pp1,2 pp1,1 pp0,0
pp2,13 pp2,12 pp1,11 pp2,10 pp2,9 pp2,8 pp2,7 pp2,6 pp2,5 pp0,4 pp0,3 pp0,2 pp0,1
pp2,11 pp1,10 pp1,9 pp1,8 pp1,7 pp1,6 pp1,5 pp1,4 pp1,3
pp0,10 pp0,9 pp0,8 pp0,7 pp0,6 pp0,5
''';
const expectedRep2 = '''
pp3,15 pp3,14 pp3,13 pp3,12 pp3,11 pp3,10 pp3,9 pp3,8 pp3,7 pp3,6 pp3,5 pp2,4 pp2,3 pp1,2 pp1,1 pp0,0
pp2,13 pp2,12 pp1,11 pp2,10 pp2,9 pp2,8 pp2,7 pp2,6 pp2,5 pp0,4 pp0,3 pp0,2 pp0,1
pp2,11 pp1,10 pp1,9 pp1,8 pp1,7 pp1,6 pp1,5 pp1,4 pp1,3
pp0,10 pp0,9 pp0,8 pp0,7 pp0,6 pp0,5
''';
// print(cc.representation());
expect(cc.representation(), equals(expectedRep2));

final (v, ts) = cc.evaluate(printOut: true);

const expectedEval = '''
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1 I 0 0 0 0 0 0 1 1 0 0 0 1 1 0 = 49350 (-16186)
1 I 1 0 0 0 0 0 0 0 1 0 0 = 14344 (14344)
0 i 1 0 0 0 0 1 1 = 536 (536)
i S S 1 1 0 = 960 (960)
p 1 1 1 1 1 1 1 0 1 0 1 0 0 1 1 0 = 65190 (-346)''';
expect(ts.toString(), equals(expectedEval));
});
}

0 comments on commit 73aac77

Please sign in to comment.