diff --git a/lib/src/synthesizers/systemverilog.dart b/lib/src/synthesizers/systemverilog.dart index cf38297fd..139efbfab 100644 --- a/lib/src/synthesizers/systemverilog.dart +++ b/lib/src/synthesizers/systemverilog.dart @@ -1218,8 +1218,8 @@ class _SynthModuleDefinition { final srcArray = src.parentArray; final dstArray = dst.parentArray; - assert(srcArray.logics.length == 1, 'should be 1'); - assert(dstArray.logics.length == 1, 'should be 1'); + assert(srcArray.logics.length == 1, 'should be 1 name for the array'); + assert(dstArray.logics.length == 1, 'should be 1 name for the array'); if (srcArray.logics.first.elements.length != dstArray.logics.first.elements.length || @@ -1236,7 +1236,31 @@ class _SynthModuleDefinition { for (final MapEntry(key: (srcArray, dstArray), value: arrAssignments) in groupedAssignments.entries) { - if (arrAssignments.length == srcArray.logics.first.elements.length) { + assert( + srcArray.logics.first.elements.length == + dstArray.logics.first.elements.length, + 'should be equal lengths of elements in both arrays by now'); + + // first requirement is that all elements have been assigned + var shouldMerge = + arrAssignments.length == srcArray.logics.first.elements.length; + + if (shouldMerge) { + // only check each element if the lengths match + for (final arrAssignment in arrAssignments) { + final arrAssignmentSrc = + (arrAssignment.src as _SynthLogicArrayElement).logic; + final arrAssignmentDst = + (arrAssignment.dst as _SynthLogicArrayElement).logic; + + if (arrAssignmentSrc.arrayIndex! != arrAssignmentDst.arrayIndex!) { + shouldMerge = false; + break; + } + } + } + + if (shouldMerge) { reducedAssignments.add(_SynthAssignment(srcArray, dstArray)); } else { reducedAssignments.addAll(arrAssignments); diff --git a/test/array_collapsing_test.dart b/test/array_collapsing_test.dart index 32f51e5fc..adfe61607 100644 --- a/test/array_collapsing_test.dart +++ b/test/array_collapsing_test.dart @@ -22,6 +22,17 @@ class ArrayModule extends Module { } } +class ArrayWithShuffledAssignment extends Module { + ArrayWithShuffledAssignment(LogicArray a) { + final inpA = addInputArray('a', a, dimensions: a.dimensions); + final outB = addOutputArray('b', dimensions: a.dimensions); + + for (var i = 0; i < a.dimensions.first; i++) { + outB.elements[i] <= inpA.elements[a.dimensions.first - i - 1]; + } + } +} + class ArrayModuleWithNetIntermediates extends Module { ArrayModuleWithNetIntermediates(LogicArray a, LogicArray b) { a = addInOutArray('a', a, @@ -69,6 +80,21 @@ void main() { SimCompare.checkIverilogVector(mod, vectors); }); + test('array assignment non-collapsing with shuffled assignment', () async { + final mod = ArrayWithShuffledAssignment(LogicArray([4], 1)); + await mod.build(); + + final sv = mod.generateSynth(); + expect(sv, contains('assign b[0] = a[3];')); + expect(sv, contains('assign b[3] = a[0];')); + + final vectors = [ + Vector({'a': LogicValue.of('01xz')}, {'b': LogicValue.of('zx10')}), + ]; + await SimCompare.checkFunctionalVector(mod, vectors); + SimCompare.checkIverilogVector(mod, vectors); + }); + test('array nets with intermediate collapse with unpacked', () async { final mod = ArrayModuleWithNetIntermediates( LogicArray([3, 3], 1, numUnpackedDimensions: 2),