Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

42compress #142

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 15 additions & 12 deletions lib/src/arithmetic/addend_compressor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ abstract class BitCompressor extends Module {
late final List<List<double>> _delays;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you think it may be useful to expose a @protected API for setting these delays rather than private, so that if someone has a technology-specific delay they want to set, they could just extend one of the compressors and change the delay numbers? this also leads to another question: should there be an argument to generate compressors in ColumnCompressor (even the smaller ones) rather than just a flag on whether to use 4:2 or not?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bare minimum is to use 2:2 and 3:2 compressors (half and full-adders). But you have a point -- people have invented even wider compressors.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you want to include changes to support arbitrary delays and user-defined compressors in this PR? one consideration is this flag to "use 4:2 compressors" is an API that wouldn't really make sense if we later replace it with a list of compressor types that can be used, for example


/// Construct a column compressor.
BitCompressor(this.terms) {
BitCompressor(this.terms, {super.name = 'bitcompressor'}) {
compressBits = [
for (var pos = 0; pos < terms.length; pos++)
addInput('t_$pos', terms[pos].logic)
Expand All @@ -171,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.terms) {
Compressor2(super.terms, {super.name = 'bitcompressor2'}) {
sum <= compressBits.xor();
carry <= compressBits.and();
_delays[CompressTermType.sum.index][CompressTermType.pp.index] = 1.0;
Expand All @@ -182,7 +182,7 @@ class Compressor2 extends BitCompressor {
/// 3-input column compressor (full-adder)
class Compressor3 extends BitCompressor {
/// Construct a 3-input column compressor (full-adder).
Compressor3(super.terms) {
Compressor3(super.terms, {super.name = 'bitcompressor3'}) {
sum <= compressBits.xor();
carry <=
mux(compressBits[0], compressBits.slice(2, 1).or(),
Expand All @@ -200,7 +200,8 @@ class Compressor4 extends BitCompressor {
Logic get cout => output('cout');

/// Construct a 4-input column compressor using two 3-input compressors.
Compressor4(List<CompressTerm> terms, List<CompressTerm> cinL)
Compressor4(List<CompressTerm> terms, List<CompressTerm> cinL,
{super.name = 'bitcompressor4'})
: super(terms) {
// We need to use internal Logic and regenerate Term lists inside
cinL = [
Expand Down Expand Up @@ -270,9 +271,9 @@ class ColumnCompressor {
ColumnCompressor(this.pp,
{this.use42Compressors = false, this.clk, this.reset, this.enable}) {
columns = List.generate(pp.maxWidth(), (i) => ColumnQueue());
if (use42Compressors) {
carryColumns = List.generate(pp.maxWidth(), (i) => ColumnQueue());
}
// if (use42Compressors) {
carryColumns = List.generate(pp.maxWidth(), (i) => ColumnQueue());
// }
for (var row = 0; row < pp.rows; row++) {
for (var col = 0; col < pp.partialProducts[row].length; col++) {
final trueColumn = pp.rowShift[row] + col;
Expand All @@ -285,23 +286,26 @@ class ColumnCompressor {

/// Return the longest column length
int longestColumn() =>
columns.reduce((a, b) => a.length > b.length ? a : b).length;
columns.reduce((a, b) => a.length > b.length ? a : b).length +
carryColumns.reduce((a, b) => a.length > b.length ? a : b).length;

/// Convert a row to a Logic bitvector
Logic extractRow(int row) {
final width = pp.maxWidth();

final rowBits = <Logic>[];
for (var col = columns.length - 1; col >= 0; col--) {
final colList = columns[col].toList();
final colList = carryColumns[col].toList() + columns[col].toList();
if (row < colList.length) {
final value = colList[row].logic;

rowBits.add(
clk != null ? flop(clk!, value, reset: reset, en: enable) : value);
} else {
rowBits.add(Const(0));
}
}
rowBits.addAll(List.filled(pp.rowShift[row], Const(0)));
// rowBits.addAll(List.filled(pp.rowShift[row], Const(0)));
if (width > rowBits.length) {
return rowBits.swizzle().zeroExtend(width);
}
Expand All @@ -319,7 +323,7 @@ class ColumnCompressor {
} else {
carryQueue = PriorityQueue<CompressTerm>();
}
final depth = queue.length;
final depth = queue.length + carryQueue.length;
if (depth > iteration) {
if (depth > 2) {
final first = queue.removeFirst();
Expand All @@ -333,7 +337,6 @@ class ColumnCompressor {
inputs
..add(queue.removeFirst())
..add(queue.removeFirst());

compressor = Compressor4(inputs, [cin]);
if (col < columns.length - 1) {
final t = CompressTerm(compressor, CompressTermType.carry,
Expand Down
35 changes: 25 additions & 10 deletions lib/src/arithmetic/evaluate_compressor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,30 @@ extension EvaluateLiveColumnCompressor on ColumnCompressor {
bool logic = false,
bool header = true,
int prefix = 1,
int extraSpace = 5}) {
int extraSpace = 0}) {
final ts = StringBuffer();
final rows = longestColumn();
final width = pp.maxWidth();
var accum = BigInt.zero;

for (var row = 0; row < rows; row++) {
final int shift;
if (row >= pp.rows) {
shift = pp.rowShift[pp.rows - 1];
} else {
shift = pp.rowShift[row];
}
final rowLogic = <Logic>[];
for (var col = columns.length - 1; col >= 0; col--) {
final colList = columns[col].toList();
final colList = carryColumns[col].toList() + columns[col].toList();
if (row < colList.length) {
rowLogic.insert(0, colList[row].logic);
} else if (col >= shift) {
// rowLogic.insert(0, Const(0));
}
}
final rowBits = [for (final c in rowLogic) c.value].reversed.toList();
// ignore: cascade_invocations
rowBits.addAll(List.filled(pp.rowShift[row], LogicValue.zero));
final rowBits = [for (final c in rowLogic) c.value].reversed.toList()
..addAll(List.filled(shift, LogicValue.zero));
final rowBitsExtend = rowBits.length < width
? rowBits.swizzle().zeroExtend(width)
: rowBits.swizzle();
Expand All @@ -53,7 +60,7 @@ extension EvaluateLiveColumnCompressor on ColumnCompressor {
prefix: prefix,
extraSpace: extraSpace,
intValue: true,
shift: pp.rowShift[row]))
shift: shift))
..write('\n');
}

Expand All @@ -67,15 +74,23 @@ extension EvaluateLiveColumnCompressor on ColumnCompressor {
}

/// Return a string representing the compression tree in its current state
String representation() {
String representation({bool evalLogic = false, bool useTabs = true}) {
final ts = StringBuffer();

final sep = useTabs ? '\t' : ' ';

for (var row = 0; row < longestColumn(); row++) {
ts.write(useTabs ? '' : ' ');
for (var col = columns.length - 1; col >= 0; col--) {
final colList = columns[col].toList();
final colList = columns[col].toList() + carryColumns[col].toList();
if (row < colList.length) {
ts.write('\t${colList[row]}');
if (evalLogic) {
ts.write('$sep${colList[row].logic.value.toInt()}');
} else {
ts.write('$sep${colList[row]}');
}
} else {
ts.write('\t');
ts.write(useTabs ? sep : '$sep ');
}
}
ts.write('\n');
Expand Down
15 changes: 7 additions & 8 deletions lib/src/arithmetic/multiplier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,6 @@ class CompressionTreeMultiplier extends Multiplier {
Logic? selectSignedMultiplicand})
ppGen = PartialProductGeneratorCompactRectSignExtension.new,
bool use42Compressors = false,
super.signed = false,
super.name = 'compression_tree_multiplier'}) {
clk = (clk != null) ? addInput('clk', clk!) : null;
reset = (reset != null) ? addInput('reset', reset!) : null;
Expand All @@ -266,17 +265,17 @@ class CompressionTreeMultiplier extends Multiplier {
selectSignedMultiplier: selectSignedMultiplier,
signedMultiplier: signedMultiplier,
);

final compressor = ColumnCompressor(
clk: iClk,
reset: iReset,
enable: iEnable,
clk: clk,
reset: reset,
enable: enable,
pp,
use42Compressors: use42Compressors)
..compress();
final adder = ParallelPrefixAdder(
compressor.extractRow(0), compressor.extractRow(1),
ppGen: ppTree);

product <= adder.sum.slice(a.width + b.width - 1, 0);
}
}
Expand Down Expand Up @@ -394,9 +393,9 @@ class CompressionTreeMultiplyAccumulate extends MultiplyAccumulate {
pp.rowShift.insert(0, 0);

final compressor = ColumnCompressor(
clk: iClk,
reset: iReset,
enable: iEnable,
clk: clk,
reset: reset,
enable: enable,
pp,
use42Compressors: use42Compressors)
..compress();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class CompressionTreeMultiplierConfigurator extends Configurator {
/// Map from Type to Function for Parallel Prefix generator
static Map<Type,
ParallelPrefix Function(List<Logic>, Logic Function(Logic, Logic))>
generatorMap = {
ppGeneratorMap = {
Ripple: Ripple.new,
Sklansky: Sklansky.new,
KoggeStone: KoggeStone.new,
Expand All @@ -26,7 +26,7 @@ class CompressionTreeMultiplierConfigurator extends Configurator {

/// Controls the type of [ParallelPrefix] tree used in the adder.
final prefixTreeKnob =
ChoiceConfigKnob(generatorMap.keys.toList(), value: KoggeStone);
ChoiceConfigKnob(ppGeneratorMap.keys.toList(), value: KoggeStone);

/// Controls the Booth encoding radix of the multiplier.!
final radixKnob = ChoiceConfigKnob<int>(
Expand Down Expand Up @@ -60,7 +60,13 @@ class CompressionTreeMultiplierConfigurator extends Configurator {
Logic(name: 'a', width: multiplicandWidthKnob.value),
Logic(name: 'b', width: multiplierWidthKnob.value),
radixKnob.value,
ppTree: generatorMap[prefixTreeKnob.value]!,
signedMultiplicand: signMultiplicandValueKnob.value == 'signed',
signedMultiplier: signMultiplierValueKnob.value == 'signed',
selectSignedMultiplicand:
signMultiplicandValueKnob.value == 'selected' ? Logic() : null,
selectSignedMultiplier:
signMultiplierValueKnob.value == 'selected' ? Logic() : null,
ppTree: ppGeneratorMap[prefixTreeKnob.value]!,
use42Compressors: use42CompressorsKnob.value);

@override
Expand Down
Loading