Fix elaboration displays with some `%p` (#6451).

This commit is contained in:
Wilson Snyder 2025-09-18 08:34:29 -04:00
parent 92f30dd28f
commit 46e56ca6fc
6 changed files with 77 additions and 3 deletions

View File

@ -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]

View File

@ -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)");

View File

@ -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);

View File

@ -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

View File

@ -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()

View File

@ -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