From 027e3d09abba6d59d5ace9ff8862d625a8f9d655 Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Wed, 18 Sep 2024 15:57:15 -0700 Subject: [PATCH] support for multi-dimensional LogicArrays with no API change --- lib/src/serialization/deserializer.dart | 13 +++- lib/src/serialization/serializer.dart | 18 ++++- test/serialization_test.dart | 93 +++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 4 deletions(-) diff --git a/lib/src/serialization/deserializer.dart b/lib/src/serialization/deserializer.dart index 25c56437b..7faa64208 100644 --- a/lib/src/serialization/deserializer.dart +++ b/lib/src/serialization/deserializer.dart @@ -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 <= diff --git a/lib/src/serialization/serializer.dart b/lib/src/serialization/serializer.dart index 7cc6f2e3f..f20680ff8 100644 --- a/lib/src/serialization/serializer.dart +++ b/lib/src/serialization/serializer.dart @@ -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.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, @@ -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) diff --git a/test/serialization_test.dart b/test/serialization_test.dart index 0e5fa389f..0c0ad2077 100644 --- a/test/serialization_test.dart +++ b/test/serialization_test.dart @@ -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; @@ -211,6 +302,8 @@ void main() { enable.inject(1); } } + await clk.nextPosedge; + await clk.nextPosedge; await Simulator.endSimulation(); });