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

Clean serialization #92

Merged
merged 10 commits into from
Sep 19, 2024
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;
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
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) {
desmonddak marked this conversation as resolved.
Show resolved Hide resolved
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
Loading