diff --git a/src/V3Width.cpp b/src/V3Width.cpp index a487ce473..49cf22ba6 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -6085,18 +6085,25 @@ class WidthVisitor final : public VNVisitor { userIterateAndNext(nodep->exprp(), WidthVP{CONTEXT_DET, PRELIM}.p()); nodep->dtypeFrom(nodep->rangep()); // Very much like like an pin - const AstNodeDType* const conDTypep = nodep->exprp()->dtypep(); + const AstNodeDType* const pinDTypep = nodep->exprp()->dtypep(); const int numInsts = nodep->rangep()->elementsConst(); const int modwidth = numInsts; - const int conwidth = conDTypep->width(); - if (conwidth == 1 && modwidth > 1) { // Multiple connections - AstNodeDType* const subDTypep = nodep->findLogicDType(1, 1, conDTypep->numeric()); + const int pinwidth = pinDTypep->width(); + if (pinwidth == 1 && modwidth > 1) { // Multiple connections + AstNodeDType* const subDTypep = nodep->findLogicDType(1, 1, pinDTypep->numeric()); userIterateAndNext(nodep->exprp(), WidthVP{subDTypep, FINAL}.p()); AstNode* const newp = new AstReplicate{nodep->fileline(), nodep->exprp()->unlinkFrBack(), static_cast(numInsts)}; nodep->replaceWith(newp); } else { + if (pinwidth != modwidth) { // && is not generic interconnect (when supported) + nodep->exprp()->v3error("Gate primitive connection expects " + << modwidth << " bits " + << ((modwidth != 1) ? "or 1 bit "s : ""s) + << "on the gate port, but the connection generates " + << pinwidth << " bits (IEEE 1800-2023 28.3.6)"); + } // Eliminating so pass down all of vup userIterateAndNext(nodep->exprp(), m_vup); nodep->replaceWith(nodep->exprp()->unlinkFrBack()); diff --git a/test_regress/t/t_gate_width_bad.out b/test_regress/t/t_gate_width_bad.out new file mode 100644 index 000000000..bdc4cfd0b --- /dev/null +++ b/test_regress/t/t_gate_width_bad.out @@ -0,0 +1,14 @@ +%Error: t/t_gate_width_bad.v:14:26: Gate primitive connection expects 1 bits on the gate port, but the connection generates 2 bits (IEEE 1800-2023 28.3.6) + : ... note: In instance 't' + 14 | buf buf2[0:0] (out[1], 2'b01); + | ^~~~~ + ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. +%Error: t/t_gate_width_bad.v:15:28: Gate primitive connection expects 1 bits on the gate port, but the connection generates 2 bits (IEEE 1800-2023 28.3.6) + : ... note: In instance 't' + 15 | buf buf3[0:0] (out[2], in[1:0]); + | ^ +%Error: t/t_gate_width_bad.v:16:28: Gate primitive connection expects 4 bits or 1 bit on the gate port, but the connection generates 2 bits (IEEE 1800-2023 28.3.6) + : ... note: In instance 't' + 16 | buf buf4[3:0] (out[2], in[1:0]); + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_gate_width_bad.py b/test_regress/t/t_gate_width_bad.py new file mode 100755 index 000000000..55203b6c9 --- /dev/null +++ b/test_regress/t/t_gate_width_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_gate_width_bad.v b/test_regress/t/t_gate_width_bad.v new file mode 100644 index 000000000..2d0d0b424 --- /dev/null +++ b/test_regress/t/t_gate_width_bad.v @@ -0,0 +1,20 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t; + + reg [1:0] in; + wire [2:0] out; + + // verilator lint_off WIDTH + buf buf1 (out[0], 1); // <--- BAD wrong connection width + buf buf2[0:0] (out[1], 2'b01); // <--- BAD wrong connection width + buf buf3[0:0] (out[2], in[1:0]); // <--- BAD wrong connection width + buf buf4[3:0] (out[2], in[1:0]); // <--- BAD wrong connection width + + initial $stop; + +endmodule