diff --git a/Changes b/Changes index 74f94da5c..0cc7392f2 100644 --- a/Changes +++ b/Changes @@ -102,6 +102,7 @@ Verilator 5.029 devel * Fix struct literal on pattern assignment (#5552) (#5559). [Todd Strader] * Fix build on gcc when using the Spack wrapper (#5555). [Eric Müller] * Fix enum name method (#5563). [Todd Strader] +* Fix `$countbits` in assert with non-tristates (#5566). [Shou-Li Hsu] Verilator 5.028 2024-08-21 diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index b30be761d..6663c879e 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -1433,7 +1433,6 @@ class TristateVisitor final : public TristateBaseVisitor { dropop[1] = VN_IS(nodep->thsp(), Const) && VN_AS(nodep->thsp(), Const)->num().isAnyZ(); dropop[2] = VN_IS(nodep->fhsp(), Const) && VN_AS(nodep->fhsp(), Const)->num().isAnyZ(); UINFO(4, " COUNTBITS(" << dropop[0] << dropop[1] << dropop[2] << " " << nodep << endl); - const AstVarRef* const varrefp = VN_AS(nodep->lhsp(), VarRef); // Input variable if (m_graphing) { iterateAndNextNull(nodep->lhsp()); if (!dropop[0]) iterateAndNextNull(nodep->rhsp()); @@ -1454,7 +1453,8 @@ class TristateVisitor final : public TristateBaseVisitor { // do so at present, we only compare if there is a z in the equation. Otherwise // we'd need to attach an enable to every signal, then optimize them away later // when we determine the signal has no tristate - if (!VN_IS(nodep->lhsp(), VarRef)) { + const AstVarRef* const varrefp = VN_CAST(nodep->lhsp(), VarRef); // Input variable + if (!varrefp) { nodep->v3warn(E_UNSUPPORTED, "Unsupported LHS tristate construct: " << nodep->prettyTypeName()); return; diff --git a/test_regress/t/t_math_countbits_tri.py b/test_regress/t/t_math_countbits_tri.py new file mode 100755 index 000000000..2c4ffdce2 --- /dev/null +++ b/test_regress/t/t_math_countbits_tri.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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('simulator') + +test.compile(verilator_flags2=['--assert']) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_math_countbits_tri.v b/test_regress/t/t_math_countbits_tri.v new file mode 100644 index 000000000..421ce6e5d --- /dev/null +++ b/test_regress/t/t_math_countbits_tri.v @@ -0,0 +1,38 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/ + // Outputs + num_zeros, num_ones, + // Inputs + clk, reset_l, vec + ); + + input logic clk; + input logic reset_l; + input logic [7:0] vec; + output logic [7:0] num_zeros; + output logic [7:0] num_ones; + + always_comb begin + num_zeros = '0; + num_ones = '0; + for (int i = 0; i < 8; i++) begin + if (vec[i] == 0) begin + num_zeros++; + end else begin + num_ones++; + end + end + end + assert property (@(negedge clk) disable iff (~reset_l) (num_ones == $countones(vec))); + assert property (@(negedge clk) disable iff (~reset_l) (num_zeros == $countbits(vec, '0))); + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule