diff --git a/Changes b/Changes index c243887f5..bc7597e37 100644 --- a/Changes +++ b/Changes @@ -50,7 +50,7 @@ Verilator 5.041 devel * Fix external function declarations with class typedef references (#6433). * Fix internal error on out-of-bounds real array access. * Fix pre/post increments in assertions (#6434). -* Fix elaboration displays with `%m` (#6445). [Alex Solomatnikov] +* Fix elaboration displays with `%m` and some `%p` (#6445) (#6451). [Alex Solomatnikov] * Fix false unique assertions on `else ;` (#6450). [Don Owen] diff --git a/src/V3Const.cpp b/src/V3Const.cpp index c00543b0f..b4b0e1308 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -3606,6 +3606,7 @@ class ConstVisitor final : public VNVisitor { // $accessor_name, ... // # .castFoo is the test VN_IS(object,Foo) // # ,, gets replaced with a , rather than && + // DISABLE_BASE # Turnes off checking Ast's base class treeops // }" # bracket not paren // ,"what to call" // @@ -3920,6 +3921,7 @@ class ConstVisitor final : public VNVisitor { TREEOPA("AstPutcN{$lhsp.castConst, $rhsp.castConst, $thsp.castConst}", "replaceConst(nodep)"); TREEOPA("AstSubstrN{$lhsp.castConst, $rhsp.castConst, $thsp.castConst}", "replaceConst(nodep)"); TREEOPA("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, VN_AS(nodep->lhsp(), Const)->num().toString())"); + TREEOP ("AstToStringN{DISABLE_BASE}", "DONE"); // Avoid uniop(const); use matchToStringNConst TREEOP ("AstToStringN{matchToStringNConst(nodep)}", "DONE"); // Custom // Implied by AstIsUnbounded::numberOperate: V("AstIsUnbounded{$lhsp.castConst}", "replaceNum(nodep, 0)"); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index c99024b8c..a8a3691ec 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -4554,7 +4554,7 @@ class WidthVisitor final : public VNVisitor { } else if (nodep->name() == "atoreal") { fmt = AstAtoN::ATOREAL; } else { - V3ERROR_NA; + nodep->v3fatalSrc("Bad case"); fmt = AstAtoN::ATOI; } // dummy assignment to suppress compiler warning methodOkArguments(nodep, 0, 0); diff --git a/src/astgen b/src/astgen index 2f1140d0f..b0f14d728 100755 --- a/src/astgen +++ b/src/astgen @@ -21,6 +21,7 @@ class Node: self._subClasses = [] # Initially list, but tuple after completion self._allSuperClasses = None # Computed on demand after completion self._allSubClasses = None # Computed on demand after completion + self._disableBase = False # Skip base class const checking self._typeId = None # Concrete type identifier number for leaf classes self._typeIdMin = None # Lowest type identifier number for class self._typeIdMax = None # Highest type identifier number for class @@ -47,6 +48,13 @@ class Node: def isCompleted(self): return isinstance(self._subClasses, tuple) + @property + def disableBase(self): + return self._disableBase + + def disableBaseSet(self): + self._disableBase = True + @property def file(self): return self._file @@ -301,11 +309,15 @@ class Cpt: mif = "m_doV" else: self.error("Unknown flag: " + doflag) + subnodes = re.sub(r',,', '__ESCAPEDCOMMA__', subnodes) for subnode in re.split(r'\s*,\s*', subnodes): subnode = re.sub(r'__ESCAPEDCOMMA__', ',', subnode) if re.match(r'^\$([a-zA-Z0-9]+)$', subnode): continue # "$lhs" is just a comment that this op has a lhs + if re.search(r'DISABLE_BASE', subnode): + AstNodes[typen].disableBaseSet() + return subnodeif = subnode subnodeif = re.sub(r'\$([a-zA-Z0-9]+)\.cast([A-Z][A-Za-z0-9]+)$', r'VN_IS(nodep->\1(),\2)', subnodeif) @@ -464,7 +476,12 @@ class Cpt: for node in AstNodeList: out_for_type_sc = [] out_for_type = [] - classes = list(node.allSuperClasses) + if node.disableBase: + classes = [] + out_for_type.extend(" // DISABLE_BASE\n") + else: + classes = list(node.allSuperClasses) + classes.append(node) for base in classes: base = base.name diff --git a/test_regress/t/t_assert_elab_p.py b/test_regress/t/t_assert_elab_p.py new file mode 100755 index 000000000..147fe6faf --- /dev/null +++ b/test_regress/t/t_assert_elab_p.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('simulator') + +test.compile() + +test.passes() diff --git a/test_regress/t/t_assert_elab_p.v b/test_regress/t/t_assert_elab_p.v new file mode 100644 index 000000000..bf1248fdb --- /dev/null +++ b/test_regress/t/t_assert_elab_p.v @@ -0,0 +1,39 @@ +// 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 + +// verilator lint_off WIDTH + +module pipe_id_match #( + parameter type ID_T = logic [4:0], + parameter ID_T STAGE_IDS[3:0][1:0] = '{default: 1} +); + generate + $info("%m %s:%0d: 4=%0d 2=%0d STAGE_IDS=%p", "test.sv", 25, 4, 2, STAGE_IDS); + endgenerate +endmodule + +module t #( + parameter type ID_T = logic [4:0] +); + function automatic ID_T [3:0][1:0] gen_stage_ids(); + for (int unsigned st = 0; st < 4; st++) begin + for (int unsigned id = 0; id < 2; id++) begin + gen_stage_ids[st][id] = 3 + ((st + 1) * 2) + id - (3 + ((st + 1) * 2) + id < 18 ? 0 : 18); + end + end + endfunction + + localparam ID_T STAGE_IDS[3:0][1:0] = gen_stage_ids(); + + pipe_id_match #( + .ID_T(ID_T), + .STAGE_IDS(STAGE_IDS) + ) pipe ( + .*); + + initial $finish; + +endmodule