From a03033e7432cb9130d3a343309f7eb9d5cec9e19 Mon Sep 17 00:00:00 2001 From: Andrew Pullin Date: Fri, 23 Jan 2026 11:28:58 -0800 Subject: [PATCH] Fix #1267: Allow wire logic connected to uwire port to have multiple drivers TODO: Decide how resolved net types (tri0/tri1/triand/trior) should interact with uwire in a shared nexus. --- ivtest/ivltests/br_gh1267.v | 23 +++++++++++++++++++++++ ivtest/regress-sv.list | 1 + tgt-vvp/draw_net_input.c | 21 +++++++++++++++++++-- 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 ivtest/ivltests/br_gh1267.v diff --git a/ivtest/ivltests/br_gh1267.v b/ivtest/ivltests/br_gh1267.v new file mode 100644 index 000000000..aa2ce8a5b --- /dev/null +++ b/ivtest/ivltests/br_gh1267.v @@ -0,0 +1,23 @@ +// Test for GitHub issue #1267 +// Wire logic connected to uwire port should not trigger multi-driver error +// The uwire semantics apply only to the uwire signal, not to wires connected to it. + +module a(input uwire logic a1); +endmodule + +module b(); + wire logic b1; + + a b_inst(.a1(b1)); + not not_inst(b1, b1); + + assign b1 = 'b0; + + initial begin + #1; + // b1 has multiple drivers, which is allowed for wire types + // The value will be X due to conflicting drivers + $display("b1 = %b (expected X due to conflicting drivers)", b1); + $display("PASSED"); + end +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 127f58fa5..89e4d7666 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -991,3 +991,4 @@ ipsupsel_real_idx CE,-g2012 ivltests gold=ipsupsel_real_idx.gold real_edges CE,-g2012 ivltests gold=real_edges.gold br_gh1112 CE,-g2009 ivltests gold=br_gh1112.gold br_gh670 normal,-g2009 ivltests +br_gh1267 normal,-g2012 ivltests diff --git a/tgt-vvp/draw_net_input.c b/tgt-vvp/draw_net_input.c index d50eaaf38..fe0f0fc4d 100644 --- a/tgt-vvp/draw_net_input.c +++ b/tgt-vvp/draw_net_input.c @@ -30,6 +30,8 @@ static ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex) { unsigned idx; ivl_signal_type_t out = IVL_SIT_TRI; + int has_tri = 0; + int has_uwire = 0; for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) { ivl_signal_type_t stype; @@ -41,14 +43,29 @@ static ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex) stype = ivl_signal_type(sig); if (stype == IVL_SIT_REG) continue; - if (stype == IVL_SIT_TRI) + if (stype == IVL_SIT_TRI) { + has_tri = 1; continue; + } if (stype == IVL_SIT_NONE) continue; - if (stype == IVL_SIT_UWIRE) return IVL_SIT_UWIRE; + if (stype == IVL_SIT_UWIRE) { + has_uwire = 1; + continue; + } out = stype; } + /* If both TRI (wire) and UWIRE are in the nexus, return TRI + because wire semantics allow multiple drivers. Only return + UWIRE if no TRI signals are present. This fixes GitHub #1267 + where wire logic connected to uwire ports was incorrectly + treated as requiring single-driver semantics. + TODO: Decide how resolved net types (tri0/tri1/triand/trior) + should interact with uwire in a shared nexus. */ + if (has_uwire && !has_tri) + return IVL_SIT_UWIRE; + return out; }