From 80fd469ae813917c05630d12ef23ff2f966d31dd Mon Sep 17 00:00:00 2001 From: "Korbel, Max" Date: Thu, 8 Jan 2026 12:01:28 -0800 Subject: [PATCH 01/10] got a test reproducing issue seen in rohd bridge tieoffs --- test/sv_gen_test.dart | 73 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/test/sv_gen_test.dart b/test/sv_gen_test.dart index cb6aa9fd6..b51bbbdfd 100644 --- a/test/sv_gen_test.dart +++ b/test/sv_gen_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2023-2025 Intel Corporation +// Copyright (C) 2023-2026 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // sv_gen_test.dart @@ -494,11 +494,82 @@ class ModWithPartialArrayAssignment extends Module { } } +class ModWithConstInlineUnaryOp extends Module { + ModWithConstInlineUnaryOp() { + addOutput('b', width: 8) <= ~Const(0, width: 8); + } +} + +class TieOffSubsetTop extends Module { + TieOffSubsetTop(Logic clk, {required bool withRedirect}) { + clk = addInput('clk', clk); + + Logic tieoffApple = + Const(0, width: 2).named('apple_tieoff', naming: Naming.mergeable); + + final apple = LogicArray([4], 4, name: 'apple'); + + if (withRedirect) { + tieoffApple = Logic(width: 2)..gets(tieoffApple); + } + + apple.elements[1].assignSubset(tieoffApple.elements, start: 1); + + TieOffSubsetSub(clk, apple, withRedirect: withRedirect); + } +} + +class TieOffSubsetSub extends Module { + TieOffSubsetSub(Logic clk, Logic apple, {required bool withRedirect}) + : super(name: 'submod') { + apple = addInputArray('apple', apple, dimensions: [4], elementWidth: 4); + clk = addInput('clk', clk); + + Logic tieoffBanana = + Const(0, width: 2).named('banana_tieoff', naming: Naming.mergeable); + + if (withRedirect) { + tieoffBanana = Logic(width: 2)..gets(tieoffBanana); + } + + final banana = addOutputArray('banana', dimensions: [4], elementWidth: 4); + + banana.elements[1].assignSubset(tieoffBanana.elements, start: 1); + } +} + void main() { tearDown(() async { await Simulator.reset(); }); + test('const unary inline op', () async { + final mod = ModWithConstInlineUnaryOp(); + await mod.build(); + + final vectors = [ + Vector({}, {'b': 0xff}), + ]; + + await SimCompare.checkFunctionalVector(mod, vectors); + SimCompare.checkIverilogVector(mod, vectors); + }); + + group('tieoff subset of array', () { + for (final redirect in [true, false]) { + test('with redirect=$redirect', () async { + final mod = TieOffSubsetTop(Logic(), withRedirect: redirect); + await mod.build(); + + final sv = mod.generateSynth(); + print(sv); + + expect(sv, contains("assign apple_tieoff = 2'h0;")); + expect(sv, contains("assign banana_tieoff = 2'h0;")); + }); + } + }); + group('signal declaration order', () { void checkSignalDeclarationOrder(String sv, List signalNames) { final expected = From 489bf07890107d06bb2996e4352c73127c595669 Mon Sep 17 00:00:00 2001 From: "Korbel, Max" Date: Thu, 8 Jan 2026 15:59:37 -0800 Subject: [PATCH 02/10] fix seems to work --- .../synthesizers/utilities/synth_logic.dart | 23 ++++++++++++++++++- test/sv_gen_test.dart | 6 +++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/src/synthesizers/utilities/synth_logic.dart b/lib/src/synthesizers/utilities/synth_logic.dart index 5dec7300c..436b911da 100644 --- a/lib/src/synthesizers/utilities/synth_logic.dart +++ b/lib/src/synthesizers/utilities/synth_logic.dart @@ -172,7 +172,7 @@ class SynthLogic { .any(parentSynthModuleDefinition.logicHasPresentSynthLogic)); /// Two [SynthLogic]s that are not [mergeable] cannot be merged with each - /// other. If onlyt one of them is not [mergeable], it can adopt the elements + /// other. If only one of them is not [mergeable], it can adopt the elements /// from the other. bool get mergeable => _reservedLogic == null && _constLogic == null && _renameableLogic == null; @@ -292,6 +292,20 @@ class SynthLogic { a.adopt(b); return (removed: b, kept: a); } + // else if ((a.isConstant && b is SynthLogicArrayElement) || + // (b.isConstant && a is SynthLogicArrayElement)) { + // // we don't want to lose any constant assignments when signals aren't + // // guaranteed to be declared + // return null; + // } + + if ((a.isConstant && b.constNameDisallowed) || + (b.isConstant && a.constNameDisallowed)) { + // we cannot merge a constant if the other disallows the constant name + // since we can lose a constant assignment (note: this doesn't guarantee + // we end up with the nicest name) + return null; + } if (!a.mergeable && !b.mergeable) { return null; @@ -332,6 +346,13 @@ class SynthLogic { assert( other != this, 'Suspicious attempt to merge a SynthLogic into itself.'); +//TODO TMP + // print('***\n $this -- is adopting \n $other'); + + // if (this.toString().contains('const_0')) { + // print('here'); + // } + _constNameDisallowed |= other._constNameDisallowed; // only take one of the other's items if we don't have it already diff --git a/test/sv_gen_test.dart b/test/sv_gen_test.dart index b51bbbdfd..b67adbe7a 100644 --- a/test/sv_gen_test.dart +++ b/test/sv_gen_test.dart @@ -564,8 +564,10 @@ void main() { final sv = mod.generateSynth(); print(sv); - expect(sv, contains("assign apple_tieoff = 2'h0;")); - expect(sv, contains("assign banana_tieoff = 2'h0;")); + // expect(sv, contains("assign apple_tieoff = 2'h0;")); + // expect(sv, contains("assign banana_tieoff = 2'h0;")); + + //TODO: do a simcompare to see the actual values in SV sim }); } }); From 8865bee53bece0b30a67eca246362c685f435293 Mon Sep 17 00:00:00 2001 From: "Korbel, Max" Date: Thu, 8 Jan 2026 16:04:56 -0800 Subject: [PATCH 03/10] some cleanup and test improvements --- .../synthesizers/utilities/synth_logic.dart | 7 ----- test/sv_gen_test.dart | 30 ++++++++++++++----- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/lib/src/synthesizers/utilities/synth_logic.dart b/lib/src/synthesizers/utilities/synth_logic.dart index 436b911da..9cd05a6e8 100644 --- a/lib/src/synthesizers/utilities/synth_logic.dart +++ b/lib/src/synthesizers/utilities/synth_logic.dart @@ -346,13 +346,6 @@ class SynthLogic { assert( other != this, 'Suspicious attempt to merge a SynthLogic into itself.'); -//TODO TMP - // print('***\n $this -- is adopting \n $other'); - - // if (this.toString().contains('const_0')) { - // print('here'); - // } - _constNameDisallowed |= other._constNameDisallowed; // only take one of the other's items if we don't have it already diff --git a/test/sv_gen_test.dart b/test/sv_gen_test.dart index b67adbe7a..f503a3ddc 100644 --- a/test/sv_gen_test.dart +++ b/test/sv_gen_test.dart @@ -501,10 +501,13 @@ class ModWithConstInlineUnaryOp extends Module { } class TieOffSubsetTop extends Module { + LogicArray get outApple => output('outApple') as LogicArray; + LogicArray get outBanana => output('outBanana') as LogicArray; + TieOffSubsetTop(Logic clk, {required bool withRedirect}) { clk = addInput('clk', clk); - Logic tieoffApple = + var tieoffApple = Const(0, width: 2).named('apple_tieoff', naming: Naming.mergeable); final apple = LogicArray([4], 4, name: 'apple'); @@ -515,17 +518,23 @@ class TieOffSubsetTop extends Module { apple.elements[1].assignSubset(tieoffApple.elements, start: 1); - TieOffSubsetSub(clk, apple, withRedirect: withRedirect); + final submod = TieOffSubsetSub(clk, apple, withRedirect: withRedirect); + + addOutputArray('outApple', dimensions: [4], elementWidth: 4).gets(apple); + addOutputArray('outBanana', dimensions: [4], elementWidth: 4) + .gets(submod.outBanana); } } class TieOffSubsetSub extends Module { + LogicArray get outBanana => output('banana') as LogicArray; + TieOffSubsetSub(Logic clk, Logic apple, {required bool withRedirect}) : super(name: 'submod') { apple = addInputArray('apple', apple, dimensions: [4], elementWidth: 4); clk = addInput('clk', clk); - Logic tieoffBanana = + var tieoffBanana = Const(0, width: 2).named('banana_tieoff', naming: Naming.mergeable); if (withRedirect) { @@ -562,12 +571,19 @@ void main() { await mod.build(); final sv = mod.generateSynth(); - print(sv); - // expect(sv, contains("assign apple_tieoff = 2'h0;")); - // expect(sv, contains("assign banana_tieoff = 2'h0;")); + expect(sv, contains(RegExp("assign .* = 2'h0;"))); - //TODO: do a simcompare to see the actual values in SV sim + // simcompare to make sure simulation works as expected + final vectors = [ + Vector({}, { + 'outApple': 'zzzzzzzzz00zzzzz', + 'outBanana': 'zzzzzzzzz00zzzzz', + }), + ]; + + await SimCompare.checkFunctionalVector(mod, vectors); + SimCompare.checkIverilogVector(mod, vectors); }); } }); From 2ab1c084a8d422ed8ce68e11709b9cea09bd81d0 Mon Sep 17 00:00:00 2001 From: "Korbel, Max" Date: Thu, 8 Jan 2026 16:34:22 -0800 Subject: [PATCH 04/10] reorder assignment collapsing to make nicer names --- lib/src/synthesizers/utilities/synth_logic.dart | 3 +-- .../synthesizers/utilities/synth_module_definition.dart | 7 ++++++- test/sv_gen_test.dart | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/src/synthesizers/utilities/synth_logic.dart b/lib/src/synthesizers/utilities/synth_logic.dart index 9cd05a6e8..c2d9379b0 100644 --- a/lib/src/synthesizers/utilities/synth_logic.dart +++ b/lib/src/synthesizers/utilities/synth_logic.dart @@ -302,8 +302,7 @@ class SynthLogic { if ((a.isConstant && b.constNameDisallowed) || (b.isConstant && a.constNameDisallowed)) { // we cannot merge a constant if the other disallows the constant name - // since we can lose a constant assignment (note: this doesn't guarantee - // we end up with the nicest name) + // since we can lose a constant assignment return null; } diff --git a/lib/src/synthesizers/utilities/synth_module_definition.dart b/lib/src/synthesizers/utilities/synth_module_definition.dart index 6193b1fc0..b6043fad6 100644 --- a/lib/src/synthesizers/utilities/synth_module_definition.dart +++ b/lib/src/synthesizers/utilities/synth_module_definition.dart @@ -885,7 +885,12 @@ class SynthModuleDefinition { while (prevAssignmentCount != assignments.length) { // keep looping until it stops shrinking final reducedAssignments = []; - for (final assignment in assignments) { + for (final assignment in CombinedIterableView([ + // we look at non-constant assignments first to maximize merging in case + // some constant merge scenario is disallowed by + assignments.where((a) => !a.src.isConstant && !a.dst.isConstant), + assignments.where((a) => a.src.isConstant || a.dst.isConstant), + ])) { assert(assignment is! PartialSynthAssignment, 'Partial assignments should have been removed before this.'); diff --git a/test/sv_gen_test.dart b/test/sv_gen_test.dart index f503a3ddc..317c55e37 100644 --- a/test/sv_gen_test.dart +++ b/test/sv_gen_test.dart @@ -572,7 +572,8 @@ void main() { final sv = mod.generateSynth(); - expect(sv, contains(RegExp("assign .* = 2'h0;"))); + expect(sv, contains("assign banana_tieoff = 2'h0;")); + expect(sv, contains("assign apple_tieoff = 2'h0;")); // simcompare to make sure simulation works as expected final vectors = [ From 9fc98641930fdc14c5eef05f9d6f6b3a50a7f8a3 Mon Sep 17 00:00:00 2001 From: "Korbel, Max" Date: Fri, 9 Jan 2026 12:54:28 -0800 Subject: [PATCH 05/10] cleanup --- lib/src/synthesizers/utilities/synth_logic.dart | 8 +------- .../synthesizers/utilities/synth_module_definition.dart | 4 ++-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/src/synthesizers/utilities/synth_logic.dart b/lib/src/synthesizers/utilities/synth_logic.dart index c2d9379b0..8597ec33e 100644 --- a/lib/src/synthesizers/utilities/synth_logic.dart +++ b/lib/src/synthesizers/utilities/synth_logic.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2025 Intel Corporation +// Copyright (C) 2021-2026 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // synth_logic.dart @@ -292,12 +292,6 @@ class SynthLogic { a.adopt(b); return (removed: b, kept: a); } - // else if ((a.isConstant && b is SynthLogicArrayElement) || - // (b.isConstant && a is SynthLogicArrayElement)) { - // // we don't want to lose any constant assignments when signals aren't - // // guaranteed to be declared - // return null; - // } if ((a.isConstant && b.constNameDisallowed) || (b.isConstant && a.constNameDisallowed)) { diff --git a/lib/src/synthesizers/utilities/synth_module_definition.dart b/lib/src/synthesizers/utilities/synth_module_definition.dart index b6043fad6..d91852545 100644 --- a/lib/src/synthesizers/utilities/synth_module_definition.dart +++ b/lib/src/synthesizers/utilities/synth_module_definition.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2025 Intel Corporation +// Copyright (C) 2021-2026 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // synth_module_definition.dart @@ -887,7 +887,7 @@ class SynthModuleDefinition { final reducedAssignments = []; for (final assignment in CombinedIterableView([ // we look at non-constant assignments first to maximize merging in case - // some constant merge scenario is disallowed by + // some constant merge scenario is disallowed by a module (e.g. subset) assignments.where((a) => !a.src.isConstant && !a.dst.isConstant), assignments.where((a) => a.src.isConstant || a.dst.isConstant), ])) { From c7a40483874c3c31b873349683d9749805a14bff Mon Sep 17 00:00:00 2001 From: "Korbel, Max" Date: Fri, 9 Jan 2026 13:37:14 -0800 Subject: [PATCH 06/10] add another test, failing --- test/sv_gen_test.dart | 96 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 16 deletions(-) diff --git a/test/sv_gen_test.dart b/test/sv_gen_test.dart index 317c55e37..7abb9067b 100644 --- a/test/sv_gen_test.dart +++ b/test/sv_gen_test.dart @@ -547,6 +547,47 @@ class TieOffSubsetSub extends Module { } } +class TieOffPortTop extends Module { + TieOffPortTop(Logic clk, {required bool withRedirect}) { + clk = addInput('clk', clk); + + var tieoffApple = Const(0).named('apple_tieoff', naming: Naming.mergeable); + + final apple = Logic(name: 'apple', naming: Naming.mergeable); + + if (withRedirect) { + tieoffApple = Logic()..gets(tieoffApple); + } + + apple <= tieoffApple; + + final submod = TieOffPortSub(apple, withRedirect: withRedirect); + + addOutput('outApple') <= submod.outApple; + addOutput('outBanana') <= submod.banana; + } +} + +class TieOffPortSub extends Module { + late final Logic banana; + late final Logic outApple; + TieOffPortSub(Logic apple, {required bool withRedirect}) { + apple = addInput('apple', apple); + + var tieoffBanana = + Const(0).named('banana_tieoff', naming: Naming.mergeable); + + if (withRedirect) { + tieoffBanana = Logic()..gets(tieoffBanana); + } + + banana = addOutput('banana'); + outApple = addOutput('outApple')..gets(apple); + + banana <= tieoffBanana; + } +} + void main() { tearDown(() async { await Simulator.reset(); @@ -564,27 +605,50 @@ void main() { SimCompare.checkIverilogVector(mod, vectors); }); - group('tieoff subset of array', () { + group('tieoff ', () { for (final redirect in [true, false]) { - test('with redirect=$redirect', () async { - final mod = TieOffSubsetTop(Logic(), withRedirect: redirect); - await mod.build(); + group('with redirect=$redirect', () { + test('subset of array', () async { + final mod = TieOffSubsetTop(Logic(), withRedirect: redirect); + await mod.build(); - final sv = mod.generateSynth(); + final sv = mod.generateSynth(); - expect(sv, contains("assign banana_tieoff = 2'h0;")); - expect(sv, contains("assign apple_tieoff = 2'h0;")); + expect(sv, contains("assign banana_tieoff = 2'h0;")); + expect(sv, contains("assign apple_tieoff = 2'h0;")); - // simcompare to make sure simulation works as expected - final vectors = [ - Vector({}, { - 'outApple': 'zzzzzzzzz00zzzzz', - 'outBanana': 'zzzzzzzzz00zzzzz', - }), - ]; + // simcompare to make sure simulation works as expected + final vectors = [ + Vector({}, { + 'outApple': 'zzzzzzzzz00zzzzz', + 'outBanana': 'zzzzzzzzz00zzzzz', + }), + ]; - await SimCompare.checkFunctionalVector(mod, vectors); - SimCompare.checkIverilogVector(mod, vectors); + await SimCompare.checkFunctionalVector(mod, vectors); + SimCompare.checkIverilogVector(mod, vectors); + }); + + test('full port', () async { + final mod = TieOffPortTop(Logic(), withRedirect: redirect); + await mod.build(); + + final sv = mod.generateSynth(); + + expect(sv, contains("assign banana = 1'h0;")); + expect(sv, contains(".apple(1'h0)")); + + // simcompare to make sure simulation works as expected + final vectors = [ + Vector({}, { + 'outApple': 0, + 'outBanana': 0, + }), + ]; + + await SimCompare.checkFunctionalVector(mod, vectors); + SimCompare.checkIverilogVector(mod, vectors); + }); }); } }); From e7638971fab2ec4fd2c27127e1c94dca3764c40c Mon Sep 17 00:00:00 2001 From: "Korbel, Max" Date: Fri, 9 Jan 2026 13:41:46 -0800 Subject: [PATCH 07/10] allow const circular assignments to be ignored --- .../synthesizers/utilities/synth_module_definition.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/src/synthesizers/utilities/synth_module_definition.dart b/lib/src/synthesizers/utilities/synth_module_definition.dart index d91852545..570976e7f 100644 --- a/lib/src/synthesizers/utilities/synth_module_definition.dart +++ b/lib/src/synthesizers/utilities/synth_module_definition.dart @@ -897,6 +897,13 @@ class SynthModuleDefinition { final dst = assignment.dst; final src = assignment.src; + if (src == dst && src.isConstant) { + // looks like this assignment does nothing -- some sort of circular + // constant assignment, can just remove it + + continue; + } + assert(dst != src, 'No circular assignment allowed between $dst and $src.'); From 53a948468af2dd006aff5ad0ce62b8233c2a2615 Mon Sep 17 00:00:00 2001 From: "Korbel, Max" Date: Sun, 18 Jan 2026 11:42:46 -0800 Subject: [PATCH 08/10] reproduce issue where output driving inout with unnamed net causes name assertion failure --- test/net_test.dart | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/test/net_test.dart b/test/net_test.dart index c8d15b7d7..56a59220e 100644 --- a/test/net_test.dart +++ b/test/net_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2024-2025 Intel Corporation +// Copyright (C) 2024-2026 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // net_test.dart @@ -341,11 +341,44 @@ class ModArrToNetSub extends Module { } } +class OutToInOutTop extends Module { + OutToInOutTop(Logic clk) { + clk = addInput('clk', clk); + final modWithOut = ModWithOut(clk); + final myNetTop = LogicNet(); + myNetTop <= modWithOut.myOut; + + ModWithInOut(myNetTop); + } +} + +class ModWithOut extends Module { + late final Logic myOut; + + ModWithOut(Logic clk) { + clk = addInput('clk', clk); + myOut = addOutput('myOut')..gets(~clk); + } +} + +class ModWithInOut extends Module { + ModWithInOut(LogicNet myNet) { + myNet = addInOut('myNet', myNet); + } +} + void main() { tearDown(() async { await Simulator.reset(); }); + test('out to inout unnamed connection', () async { + final mod = OutToInOutTop(Logic()); + await mod.build(); + + print(mod.generateSynth()); + }); + test('mod array to net hier', () async { final mod = ModArrToNetTop(LogicArray.net([2], 8)); await mod.build(); From b54cdbe469daed91d35ee2fb0382142bacc15502 Mon Sep 17 00:00:00 2001 From: "Korbel, Max" Date: Sun, 18 Jan 2026 12:22:13 -0800 Subject: [PATCH 09/10] fix and improved test --- .../utilities/synth_module_definition.dart | 5 +- test/net_test.dart | 35 +------------ test/sv_gen_test.dart | 50 +++++++++++++++++++ 3 files changed, 55 insertions(+), 35 deletions(-) diff --git a/lib/src/synthesizers/utilities/synth_module_definition.dart b/lib/src/synthesizers/utilities/synth_module_definition.dart index 570976e7f..b8b78476a 100644 --- a/lib/src/synthesizers/utilities/synth_module_definition.dart +++ b/lib/src/synthesizers/utilities/synth_module_definition.dart @@ -605,7 +605,10 @@ class SynthModuleDefinition { ...internalSignal.dstConnections ] .where((e) => - e.parentModule == module && logicHasPresentSynthLogic(e)) + (e.parentModule == module || + ( // in case of sub-module output driving a net + e.parentModule?.parent == module && e.isOutput)) && + logicHasPresentSynthLogic(e)) .isNotEmpty; if (anyInternalConnections) { diff --git a/test/net_test.dart b/test/net_test.dart index 56a59220e..c8d15b7d7 100644 --- a/test/net_test.dart +++ b/test/net_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2024-2026 Intel Corporation +// Copyright (C) 2024-2025 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // net_test.dart @@ -341,44 +341,11 @@ class ModArrToNetSub extends Module { } } -class OutToInOutTop extends Module { - OutToInOutTop(Logic clk) { - clk = addInput('clk', clk); - final modWithOut = ModWithOut(clk); - final myNetTop = LogicNet(); - myNetTop <= modWithOut.myOut; - - ModWithInOut(myNetTop); - } -} - -class ModWithOut extends Module { - late final Logic myOut; - - ModWithOut(Logic clk) { - clk = addInput('clk', clk); - myOut = addOutput('myOut')..gets(~clk); - } -} - -class ModWithInOut extends Module { - ModWithInOut(LogicNet myNet) { - myNet = addInOut('myNet', myNet); - } -} - void main() { tearDown(() async { await Simulator.reset(); }); - test('out to inout unnamed connection', () async { - final mod = OutToInOutTop(Logic()); - await mod.build(); - - print(mod.generateSynth()); - }); - test('mod array to net hier', () async { final mod = ModArrToNetTop(LogicArray.net([2], 8)); await mod.build(); diff --git a/test/sv_gen_test.dart b/test/sv_gen_test.dart index 7abb9067b..efbb41bf0 100644 --- a/test/sv_gen_test.dart +++ b/test/sv_gen_test.dart @@ -588,6 +588,35 @@ class TieOffPortSub extends Module { } } +class OutToInOutTop extends Module { + OutToInOutTop(Logic clk) : super(name: 'out_to_inout_top') { + clk = addInput('clk', clk); + final modWithOut = ModWithOut(clk); + final myNetTop = LogicNet(); + myNetTop <= modWithOut.myOut; + + addOutput('clkB') <= ModWithInOut(myNetTop).clkB; + } +} + +class ModWithOut extends Module { + late final Logic myOut; + + ModWithOut(Logic clk) : super(name: 'mod_with_out') { + clk = addInput('clk', clk); + myOut = addOutput('myOut')..gets(~clk); + } +} + +class ModWithInOut extends Module { + late final Logic clkB; + ModWithInOut(LogicNet myNet) : super(name: 'mod_with_inout') { + myNet = addInOut('myNet', myNet); + + clkB = addOutput('clkB')..gets(myNet); + } +} + void main() { tearDown(() async { await Simulator.reset(); @@ -947,4 +976,25 @@ endmodule : ModWithUselessWireMods''')); }); } }); + + test('out to inout unnamed connection', () async { + // this test makes sure we don't lose an unnamed connection from an output + // to an inout + + final mod = OutToInOutTop(Logic()); + await mod.build(); + + final sv = mod.generateSynth(); + + print(sv); + + expect(sv, contains('assign myNet = myOut;')); + + final vectors = [ + Vector({'clk': 0}, {'clkB': 1}), + Vector({'clk': 1}, {'clkB': 0}), + ]; + await SimCompare.checkFunctionalVector(mod, vectors); + SimCompare.checkIverilogVector(mod, vectors); + }); } From 6ff3b2c7fabeb857aafc48cf394dfd0053e5a56e Mon Sep 17 00:00:00 2001 From: "Korbel, Max" Date: Sun, 18 Jan 2026 12:26:14 -0800 Subject: [PATCH 10/10] cleanup --- test/sv_gen_test.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/sv_gen_test.dart b/test/sv_gen_test.dart index efbb41bf0..6e3774067 100644 --- a/test/sv_gen_test.dart +++ b/test/sv_gen_test.dart @@ -986,8 +986,6 @@ endmodule : ModWithUselessWireMods''')); final sv = mod.generateSynth(); - print(sv); - expect(sv, contains('assign myNet = myOut;')); final vectors = [