Skip to content

Commit

Permalink
support for multi-dimensional LogicArrays with no API change
Browse files Browse the repository at this point in the history
  • Loading branch information
desmonddak committed Sep 18, 2024
1 parent adfa5ce commit 027e3d0
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 4 deletions.
13 changes: 11 additions & 2 deletions lib/src/serialization/deserializer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,22 @@ class Deserializer extends Module {
if (enable != null) {
enable = addInput('enable', enable);
}
serialized = addInput('serialized', serialized, width: serialized.width);
serialized = (serialized is LogicArray)
? addInputArray('serialized', serialized,
dimensions: serialized.dimensions,
elementWidth: serialized.elementWidth)
: addInput('serialized', serialized, width: serialized.width);
final cnt = Counter.simple(
clk: clk, reset: reset, enable: enable, maxValue: length - 1);
addOutput('count', width: cnt.width) <= cnt.count;
addOutput('done') <= cnt.overflowed;
addOutputArray('deserialized',
dimensions: [length], elementWidth: serialized.width)
dimensions: (serialized is LogicArray)
? ([length, ...serialized.dimensions])
: [length],
elementWidth: (serialized is LogicArray)
? serialized.elementWidth
: serialized.width)
.elements
.forEachIndexed((i, d) =>
d <=
Expand Down
18 changes: 16 additions & 2 deletions lib/src/serialization/serializer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,20 @@ class Serializer extends Module {
deserialized = addInputArray('deserialized', deserialized,
dimensions: deserialized.dimensions,
elementWidth: deserialized.elementWidth);
addOutput('serialized', width: deserialized.elementWidth);

addOutput('count', width: log2Ceil(deserialized.dimensions[0]));
addOutput('done');

final reducedDimensions = List<int>.from(deserialized.dimensions)
..removeAt(0);
if (deserialized.dimensions.length > 1) {
addOutputArray('serialized',
dimensions: reducedDimensions,
elementWidth: deserialized.elementWidth);
} else {
addOutput('serialized', width: deserialized.elementWidth);
}

final cnt = Counter.simple(
clk: clk,
reset: reset,
Expand All @@ -72,7 +82,11 @@ class Serializer extends Module {
clk, reset: reset, en: latchInput, deserialized.elements[i])
: deserialized.elements[i]);
}
serialized <= dataOutput.elements.selectIndex(count);
if (deserialized.dimensions.length > 1) {
serialized <= dataOutput.elements.selectIndex(count);
} else {
serialized <= dataOutput.elements.selectIndex(count);
}
done <=
(flopInput
? flop(clk, reset: reset, en: enable, cnt.equalsMax)
Expand Down
93 changes: 93 additions & 0 deletions test/serialization_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,97 @@ void main() {
await Simulator.endSimulation();
});

test('serializer for larger structures', () async {
const len = 10;
const width = 8;
final dataIn = LogicArray([len, 2], width);
final clk = SimpleClockGenerator(10).clk;
final start = Logic();
final reset = Logic();
final mod = Serializer(dataIn, clk: clk, reset: reset, enable: start);

await mod.build();
unawaited(Simulator.run());

start.inject(0);
reset.inject(0);
var clkCount = 0;
for (var i = 0; i < len; i++) {
for (var j = 0; j < 2; j++) {
dataIn.elements[i].elements[j].inject(i * 2 + j);
}
}
await clk.nextPosedge;

reset.inject(1);
await clk.nextPosedge;
reset.inject(0);
await clk.nextPosedge;
await clk.nextPosedge;
await clk.nextPosedge;
start.inject(1);
final val = mod.serialized as LogicArray;
var predictedClk = 0;
while (mod.done.value.toInt() != 1) {
expect(val.elements[0].value.toInt(), equals(predictedClk * 2));
expect(val.elements[1].value.toInt(), equals(predictedClk * 2 + 1));
await clk.nextPosedge;
predictedClk = (clkCount + 1) % len;
expect(mod.count.value.toInt(), equals(predictedClk));
clkCount++;
}
expect(val.elements[0].value.toInt(), equals(predictedClk * 2));
expect(val.elements[1].value.toInt(), equals(predictedClk * 2 + 1));
await Simulator.endSimulation();
});

test('serializer to deserializer for larger structures', () async {
const len = 10;
const width = 8;
final dataIn = LogicArray([len, 2], width);
final clk = SimpleClockGenerator(10).clk;
final start = Logic();
final reset = Logic();
final mod = Serializer(dataIn, clk: clk, reset: reset, enable: start);

final mod2 = Deserializer(mod.serialized, len,
clk: clk, reset: reset, enable: start);

await mod.build();
await mod2.build();
unawaited(Simulator.run());

WaveDumper(mod2);

start.inject(0);
reset.inject(0);
for (var i = 0; i < len; i++) {
for (var j = 0; j < 2; j++) {
dataIn.elements[i].elements[j].inject(i * 2 + j);
}
}
await clk.nextPosedge;

reset.inject(1);
await clk.nextPosedge;
reset.inject(0);
await clk.nextPosedge;
start.inject(1);
while (mod2.done.value.toInt() != 1) {
await clk.nextPosedge;
}
await clk.nextPosedge;
final dataOut = mod2.deserialized;

for (var i = 0; i < len; i++) {
for (var j = 0; j < 2; j++) {
expect(dataOut.elements[i].elements[j].value,
equals(dataIn.elements[i].elements[j].value));
}
}
await Simulator.endSimulation();
});

test('deserializer rollover', () async {
const len = 6;
const width = 4;
Expand Down Expand Up @@ -211,6 +302,8 @@ void main() {
enable.inject(1);
}
}
await clk.nextPosedge;
await clk.nextPosedge;
await Simulator.endSimulation();
});

Expand Down

0 comments on commit 027e3d0

Please sign in to comment.