Skip to content

Commit

Permalink
Fix a bug where array port element naming collisions with port names …
Browse files Browse the repository at this point in the history
…caused misconnections (#473)
  • Loading branch information
mkorbel1 authored Mar 7, 2024
1 parent 05f6cba commit 6d54c25
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 12 deletions.
63 changes: 51 additions & 12 deletions lib/src/synthesizers/systemverilog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,41 @@ class _SynthSubModuleInstantiation {
}

/// A mapping of input port name to [_SynthLogic].
final Map<String, _SynthLogic> inputMapping = {};
late final Map<String, _SynthLogic> inputMapping =
UnmodifiableMapView(_inputMapping);
final Map<String, _SynthLogic> _inputMapping = {};

/// Adds an input mapping from [name] to [synthLogic].
void setInputMapping(String name, _SynthLogic synthLogic,
{bool replace = false}) {
// ignore: invalid_use_of_protected_member
assert(module.inputs.containsKey(name),
'Input $name not found in module ${module.name}.');
assert(
(replace && _inputMapping.containsKey(name)) ||
!_inputMapping.containsKey(name),
'A mapping already exists to this input: $name.');

_inputMapping[name] = synthLogic;
}

/// A mapping of output port name to [_SynthLogic].
final Map<String, _SynthLogic> outputMapping = {};
late final Map<String, _SynthLogic> outputMapping =
UnmodifiableMapView(_outputMapping);
final Map<String, _SynthLogic> _outputMapping = {};

/// Adds an output mapping from [name] to [synthLogic].
void setOutputMapping(String name, _SynthLogic synthLogic,
{bool replace = false}) {
assert(module.outputs.containsKey(name),
'Output $name not found in module ${module.name}.');
assert(
(replace && _outputMapping.containsKey(name)) ||
!_outputMapping.containsKey(name),
'A mapping already exists to this output: $name.');

_outputMapping[name] = synthLogic;
}

/// Indicates whether this module should be declared.
bool get needsDeclaration => _needsDeclaration;
Expand Down Expand Up @@ -500,9 +531,12 @@ class _SynthModuleDefinition {
receiver.isOutput && (receiver.parentModule?.parent == module);
if (receiverIsSubModuleOutput) {
final subModule = receiver.parentModule!;
final subModuleInstantiation =
_getSynthSubModuleInstantiation(subModule);
subModuleInstantiation.outputMapping[receiver.name] = synthReceiver;

// array elements are not named ports, just contained in array
if (synthReceiver is! _SynthLogicArrayElement) {
_getSynthSubModuleInstantiation(subModule)
.setOutputMapping(receiver.name, synthReceiver);
}

// ignore: invalid_use_of_protected_member
logicsToTraverse.addAll(subModule.inputs.values);
Expand All @@ -527,9 +561,12 @@ class _SynthModuleDefinition {
receiver.isInput && (receiver.parentModule?.parent == module);
if (receiverIsSubModuleInput) {
final subModule = receiver.parentModule!;
final subModuleInstantiation =
_getSynthSubModuleInstantiation(subModule);
subModuleInstantiation.inputMapping[receiver.name] = synthReceiver;

// array elements are not named ports, just contained in array
if (synthReceiver is! _SynthLogicArrayElement) {
_getSynthSubModuleInstantiation(subModule)
.setInputMapping(receiver.name, synthReceiver);
}
}
}

Expand All @@ -548,14 +585,16 @@ class _SynthModuleDefinition {
// ignore: invalid_use_of_protected_member
for (final inputName in submoduleInstantiation.module.inputs.keys) {
final orig = submoduleInstantiation.inputMapping[inputName]!;
submoduleInstantiation.inputMapping[inputName] =
orig.replacement ?? orig;
submoduleInstantiation.setInputMapping(
inputName, orig.replacement ?? orig,
replace: true);
}

for (final outputName in submoduleInstantiation.module.outputs.keys) {
final orig = submoduleInstantiation.outputMapping[outputName]!;
submoduleInstantiation.outputMapping[outputName] =
orig.replacement ?? orig;
submoduleInstantiation.setOutputMapping(
outputName, orig.replacement ?? orig,
replace: true);
}
}
}
Expand Down
31 changes: 31 additions & 0 deletions test/logic_name_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,26 @@ class DrivenOutputModule extends Module {
}
}

class ModWithNameCollisionArrayPorts extends Module {
Logic get o => output('o');
ModWithNameCollisionArrayPorts(LogicArray portA, Logic portA2)
: super(name: 'submod') {
portA2 = addInput('portA_2', portA2);
portA = addInputArray('portA', portA, dimensions: [3, 1]);
addOutput('o') <= portA2;

addOutput('portB_1');
addOutputArray('portB', dimensions: [2, 1]);
}
}

class NameCollisionArrayTop extends Module {
NameCollisionArrayTop() {
addOutput('o') <=
ModWithNameCollisionArrayPorts(LogicArray([3, 1], 1), Logic()).o;
}
}

void main() {
test(
'GIVEN logic name is valid '
Expand Down Expand Up @@ -180,4 +200,15 @@ void main() {
expect(sv, contains('z'));
});
});

test('array port and simple port with _num name conflict', () async {
final mod = NameCollisionArrayTop();
await mod.build();
final sv = mod.generateSynth();
expect(
sv,
contains('submod(.portA_2(portA_2),.portA(portA),'
'.o(o),'
'.portB_1(portB_1),.portB(portB))'));
});
}

0 comments on commit 6d54c25

Please sign in to comment.