From 68633814d1fc5b9517b6842e39df80fbca63968f Mon Sep 17 00:00:00 2001 From: Andrew Pullin Date: Fri, 23 Jan 2026 14:27:46 -0800 Subject: [PATCH] Fix #1268: Allow variables to be driven by primitive gate outputs Per IEEE 1800-2017 6.5, variables can be written by one port, including primitive gate outputs. The code incorrectly disallowed this with the comment "Gates can never have variable output ports." Changed elaborate_lnet/elaborate_bi_net calls for gate outputs to pass true for var_allowed_in_sv, allowing variables as single-driver outputs. Co-Authored-By: Claude Opus 4.5 --- elaborate.cc | 8 +++++--- ivtest/gold/br_gh1222.gold | 6 +----- ivtest/ivltests/br_gh1222.v | 4 ++-- ivtest/ivltests/br_gh1268.v | 23 +++++++++++++++++++++++ ivtest/regress-sv.list | 1 + 5 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 ivtest/ivltests/br_gh1268.v diff --git a/elaborate.cc b/elaborate.cc index 6839156da..3b1ac3fb0 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -774,11 +774,13 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const des->errors += 1; return; } - // Gates can never have variable output ports. + // In SystemVerilog, variables can be driven by a single + // primitive/gate output (IEEE 1800-2017 6.5). Primitives always + // use default (strong) drive strength. if (lval_count > gate_count) - lval_sigs[idx] = pin(idx)->elaborate_bi_net(des, scope, false); + lval_sigs[idx] = pin(idx)->elaborate_bi_net(des, scope, gn_system_verilog()); else - lval_sigs[idx] = pin(idx)->elaborate_lnet(des, scope, false); + lval_sigs[idx] = pin(idx)->elaborate_lnet(des, scope, gn_system_verilog()); // The only way this should return zero is if an error // happened, so for that case just return. diff --git a/ivtest/gold/br_gh1222.gold b/ivtest/gold/br_gh1222.gold index 92ec72be1..f8e18ba50 100644 --- a/ivtest/gold/br_gh1222.gold +++ b/ivtest/gold/br_gh1222.gold @@ -2,8 +2,4 @@ ./ivltests/br_gh1222.v:6: error: Variable 'rout_ca2' cannot be driven by a primitive or continuous assignment with non-default strength. ./ivltests/br_gh1222.v:7: error: Variable 'lout_ca1' cannot be driven by a primitive or continuous assignment with non-default strength. ./ivltests/br_gh1222.v:7: error: Variable 'lout_ca2' cannot be driven by a primitive or continuous assignment with non-default strength. -./ivltests/br_gh1222.v:12: error: Variable 'rout_gt' cannot be driven by a primitive or continuous assignment with non-default strength. -./ivltests/br_gh1222.v:12: error: Failed to elaborate primitive output expression top.rout_gt. -./ivltests/br_gh1222.v:13: error: Variable 'lout_gt' cannot be driven by a primitive or continuous assignment with non-default strength. -./ivltests/br_gh1222.v:13: error: Failed to elaborate primitive output expression top.lout_gt. -12 error(s) during elaboration. +8 error(s) during elaboration. diff --git a/ivtest/ivltests/br_gh1222.v b/ivtest/ivltests/br_gh1222.v index b5e1d0e9c..1c5873a1c 100644 --- a/ivtest/ivltests/br_gh1222.v +++ b/ivtest/ivltests/br_gh1222.v @@ -9,8 +9,8 @@ module top; assign (strong1, strong0) rout_valid = in; // Ok, real cannot be in a concatenation assign (strong1, strong0) {lout_valid1, lout_valid2} = in; // Ok, default strength - and (rout_gt, in, in); // Gates must drive a net - and (lout_gt, in, in); // Gates must drive a net + and (rout_gt, in, in); // Ok in SV, variables can be driven by primitives (IEEE 1800-2017 6.5) + and (lout_gt, in, in); // Ok in SV, variables can be driven by primitives (IEEE 1800-2017 6.5) // When strength is added it should only be for the default strength! udp_inv (rout_udp, in); // A UDP is like a module and can drive a variable diff --git a/ivtest/ivltests/br_gh1268.v b/ivtest/ivltests/br_gh1268.v new file mode 100644 index 000000000..9c72f7277 --- /dev/null +++ b/ivtest/ivltests/br_gh1268.v @@ -0,0 +1,23 @@ +// Test for GitHub issue #1268 +// Variable (output logic) should be allowed to be driven by primitive gate +// Per IEEE 1800-2017 6.5: variables can be written by one port (primitive output) + +module driver(output logic c, input wire d); + not b(c, d); +endmodule + +module test; + wire d = 1'b0; + wire c; + + driver dut(.c(c), .d(d)); + + initial begin + #1; + if (c !== 1'b1) begin + $display("FAILED: c = %b, expected 1", c); + $finish; + end + $display("PASSED"); + end +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 89e4d7666..ded8b92a1 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -992,3 +992,4 @@ 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 +br_gh1268 normal,-g2012 ivltests