Change control file `public_flat_*` and other signal attributes to support __ in names (#6140).

This commit is contained in:
Wilson Snyder 2025-07-09 20:48:00 -04:00
parent d1462f3120
commit d89df33fcd
10 changed files with 90 additions and 50 deletions

View File

@ -14,6 +14,7 @@ Verilator 5.039 devel
**Other:** **Other:**
* Support disable dotted references (#6154). [Ryszard Rozak, Antmicro Ltd.] * Support disable dotted references (#6154). [Ryszard Rozak, Antmicro Ltd.]
* Change control file `public_flat_*` and other signal attributes to support __ in names (#6140).
* Fix class extends dotted error (#6162). [Igor Zaworski] * Fix class extends dotted error (#6162). [Igor Zaworski]
* Fix genvar error with `-O0` (#6165). [Max Wipfli] * Fix genvar error with `-O0` (#6165). [Max Wipfli]

View File

@ -2222,6 +2222,9 @@ public:
// ACCESSORS // ACCESSORS
virtual string name() const VL_MT_STABLE { return ""; } virtual string name() const VL_MT_STABLE { return ""; }
virtual string origName() const { return ""; } virtual string origName() const { return ""; }
string prettyOrigOrName() const {
return prettyName(origName().empty() ? name() : origName());
}
virtual void name(const string& name) { virtual void name(const string& name) {
this->v3fatalSrc("name() called on object without name() method"); this->v3fatalSrc("name() called on object without name() method");
} }

View File

@ -2604,6 +2604,8 @@ void AstVar::dump(std::ostream& str) const {
if (isPulldown()) str << " [PULLDOWN]"; if (isPulldown()) str << " [PULLDOWN]";
if (isUsedClock()) str << " [CLK]"; if (isUsedClock()) str << " [CLK]";
if (isSigPublic()) str << " [P]"; if (isSigPublic()) str << " [P]";
if (isSigUserRdPublic()) str << " [PRD]";
if (isSigUserRWPublic()) str << " [PWR]";
if (isInternal()) str << " [INTERNAL]"; if (isInternal()) str << " [INTERNAL]";
if (isLatched()) str << " [LATCHED]"; if (isLatched()) str << " [LATCHED]";
if (isUsedLoopIdx()) str << " [LOOP]"; if (isUsedLoopIdx()) str << " [LOOP]";

View File

@ -276,7 +276,7 @@ public:
const VPragmaType pragma = VPragmaType::COVERAGE_BLOCK_OFF; const VPragmaType pragma = VPragmaType::COVERAGE_BLOCK_OFF;
if (!nodep->unnamed()) { if (!nodep->unnamed()) {
for (const string& i : m_coverageOffBlocks) { for (const string& i : m_coverageOffBlocks) {
if (VString::wildmatch(nodep->name(), i)) { if (VString::wildmatch(nodep->prettyOrigOrName(), i)) {
nodep->addStmtsp(new AstPragma{nodep->fileline(), pragma}); nodep->addStmtsp(new AstPragma{nodep->fileline(), pragma});
} }
} }
@ -732,7 +732,7 @@ void V3Control::applyCoverageBlock(AstNodeModule* modulep, AstBegin* nodep) {
const string& filename = nodep->fileline()->filename(); const string& filename = nodep->fileline()->filename();
V3ControlFile* const filep = V3ControlResolver::s().files().resolve(filename); V3ControlFile* const filep = V3ControlResolver::s().files().resolve(filename);
if (filep) filep->applyBlock(nodep); if (filep) filep->applyBlock(nodep);
const string& modname = modulep->name(); const string& modname = modulep->prettyOrigOrName();
V3ControlModule* const modp = V3ControlResolver::s().modules().resolve(modname); V3ControlModule* const modp = V3ControlResolver::s().modules().resolve(modname);
if (modp) modp->applyBlock(nodep); if (modp) modp->applyBlock(nodep);
} }
@ -744,29 +744,30 @@ void V3Control::applyIgnores(FileLine* filelinep) {
} }
void V3Control::applyModule(AstNodeModule* modulep) { void V3Control::applyModule(AstNodeModule* modulep) {
const string& modname = modulep->origName(); const string& modname = modulep->prettyOrigOrName();
V3ControlModule* const modp = V3ControlResolver::s().modules().resolve(modname); V3ControlModule* const modp = V3ControlResolver::s().modules().resolve(modname);
if (modp) modp->apply(modulep); if (modp) modp->apply(modulep);
} }
void V3Control::applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp) { void V3Control::applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp) {
const string& modname = modulep->name(); const string& modname = modulep->prettyOrigOrName();
V3ControlModule* const modp = V3ControlResolver::s().modules().resolve(modname); V3ControlModule* const modp = V3ControlResolver::s().modules().resolve(modname);
if (!modp) return; if (!modp) return;
const V3ControlFTask* const ftp = modp->ftasks().resolve(ftaskp->name()); const V3ControlFTask* const ftp = modp->ftasks().resolve(ftaskp->prettyOrigOrName());
if (ftp) ftp->apply(ftaskp); if (ftp) ftp->apply(ftaskp);
} }
void V3Control::applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar* varp) { void V3Control::applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar* varp) {
V3ControlVar* vp; V3ControlVar* vp;
V3ControlModule* const modp = V3ControlResolver::s().modules().resolve(modulep->name()); V3ControlModule* const modp
= V3ControlResolver::s().modules().resolve(modulep->prettyOrigOrName());
if (!modp) return; if (!modp) return;
if (ftaskp) { if (ftaskp) {
V3ControlFTask* const ftp = modp->ftasks().resolve(ftaskp->name()); V3ControlFTask* const ftp = modp->ftasks().resolve(ftaskp->prettyOrigOrName());
if (!ftp) return; if (!ftp) return;
vp = ftp->vars().resolve(varp->name()); vp = ftp->vars().resolve(varp->prettyOrigOrName());
} else { } else {
vp = modp->vars().resolve(varp->name()); vp = modp->vars().resolve(varp->prettyOrigOrName());
} }
if (vp) vp->apply(varp); if (vp) vp->apply(varp);
} }

View File

@ -8087,8 +8087,10 @@ vltDModule<strp>: // --module <arg>
; ;
vltDModuleE<strp>: // [--module <arg>] vltDModuleE<strp>: // [--module <arg>]
/* empty */ { static string unit = "__024unit"; $$ = &unit; } /* empty */
| vltDModule { $$ = $1; } { static string unit = "$unit"; $$ = &unit; } // .vlt uses prettyName
| vltDModule
{ $$ = $1; }
; ;
vltDScope<strp>: // --scope <arg> vltDScope<strp>: // --scope <arg>

View File

@ -25,19 +25,18 @@ test.compile(make_top_shell=False,
if test.vlt_all: if test.vlt_all:
test.file_grep( test.file_grep(
out_filename, out_filename,
r'{"type":"VAR","name":"formatted","addr":"[^"]*","loc":"\w,58:[^"]*",.*"origName":"formatted",.*"direction":"INPUT",.*"dtypeName":"string",.*"attrSFormat":true' r'{"type":"VAR","name":"formatted",.*"origName":"formatted",.*"direction":"INPUT",.*"attrSFormat":true'
) )
test.file_grep( test.file_grep(
out_filename, out_filename,
r'{"type":"VAR","name":"t.sub.in","addr":"[^"]*","loc":"\w,81:[^"]*",.*"origName":"in",.*"dtypeName":"int",.*"isSigUserRdPublic":true' r'{"type":"VAR","name":"t.sub.in",.*"origName":"in",.*"isSigUserRdPublic":true')
test.file_grep(
out_filename,
r'{"type":"VAR","name":"t.sub.fr_a",.*"origName":"fr_a",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true'
) )
test.file_grep( test.file_grep(
out_filename, out_filename,
r'{"type":"VAR","name":"t.sub.fr_a","addr":"[^"]*","loc":"\w,82:[^"]*",.*"origName":"fr_a",.*"dtypeName":"int",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true' r'{"type":"VAR","name":"t.sub.fr_b",.*"origName":"fr_b",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true'
)
test.file_grep(
out_filename,
r'{"type":"VAR","name":"t.sub.fr_b","addr":"[^"]*","loc":"\w,83:[^"]*",.*"origName":"fr_b",.*"dtypeName":"int",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true'
) )
test.execute() test.execute()

View File

@ -58,7 +58,13 @@ const char* _my_rooted(const char* obj) {
return buf.c_str(); return buf.c_str();
} }
#define MY_VPI_HANDLE(signal) vpi_handle_by_name(const_cast<PLI_BYTE8*>(_my_rooted(signal)), NULL); TestVpiHandle my_vpi_handle(const char* signal) {
#ifdef TEST_VERBOSE
printf("-my_vpi_handle(\"%s\")\n", _my_rooted(signal));
#endif
TestVpiHandle vh = vpi_handle_by_name(const_cast<PLI_BYTE8*>(_my_rooted(signal)), NULL);
return vh;
}
int _mon_check_var() { int _mon_check_var() {
#ifdef TEST_VERBOSE #ifdef TEST_VERBOSE
@ -67,7 +73,7 @@ int _mon_check_var() {
TestVpiHandle vh1 = vpi_handle_by_name(const_cast<PLI_BYTE8*>(_sim_top()), NULL); TestVpiHandle vh1 = vpi_handle_by_name(const_cast<PLI_BYTE8*>(_sim_top()), NULL);
TEST_CHECK_NZ(vh1); TEST_CHECK_NZ(vh1);
TestVpiHandle vh2 = MY_VPI_HANDLE("\\check;alias "); TestVpiHandle vh2 = my_vpi_handle("\\check;alias ");
TEST_CHECK_NZ(vh2); TEST_CHECK_NZ(vh2);
// scope attributes // scope attributes
@ -107,15 +113,29 @@ int _mon_check_var() {
TEST_CHECK_CSTR(p, "vpiNet"); TEST_CHECK_CSTR(p, "vpiNet");
} }
TestVpiHandle vh4 = MY_VPI_HANDLE("\\x.y "); TestVpiHandle vh4 = my_vpi_handle("\\x.y ");
TEST_CHECK_NZ(vh4); TEST_CHECK_NZ(vh4);
// Test that the toplevel TOP.xxxxx search is skipped // Test that the toplevel TOP.xxxxx search is skipped
// when the path to the scope has more than one level. // when the path to the scope has more than one level.
TestVpiHandle vh5 = MY_VPI_HANDLE("\\mod.with_dot .\\b.c "); {
TestVpiHandle vh5 = my_vpi_handle("\\mod.with_dot .\\b.c ");
TEST_CHECK_NZ(vh5); TEST_CHECK_NZ(vh5);
p = vpi_get_str(vpiFullName, vh5); p = vpi_get_str(vpiFullName, vh5);
TEST_CHECK_CSTR(p, "\\t.has.dots .\\mod.with_dot .\\b.c "); TEST_CHECK_CSTR(p, "\\t.has.dots .\\mod.with_dot .\\b.c ");
}
{
TestVpiHandle vh5 = my_vpi_handle("double__underscore");
TEST_CHECK_NZ(vh5);
p = vpi_get_str(vpiFullName, vh5);
TEST_CHECK_CSTR(p, "TOP.double__underscore");
}
{
TestVpiHandle vh5 = my_vpi_handle("double__underscore__vlt");
TEST_CHECK_NZ(vh5);
p = vpi_get_str(vpiFullName, vh5);
TEST_CHECK_CSTR(p, "TOP.double__underscore__vlt");
}
return errors; return errors;
} }
@ -126,7 +146,7 @@ int _mon_check_iter() {
#endif #endif
const char* p; const char* p;
TestVpiHandle vh2 = MY_VPI_HANDLE("\\mod.with_dot "); TestVpiHandle vh2 = my_vpi_handle("\\mod.with_dot ");
TEST_CHECK_NZ(vh2); TEST_CHECK_NZ(vh2);
p = vpi_get_str(vpiName, vh2); p = vpi_get_str(vpiName, vh2);
TEST_CHECK_CSTR(p, "\\mod.with_dot "); TEST_CHECK_CSTR(p, "\\mod.with_dot ");
@ -135,12 +155,12 @@ int _mon_check_iter() {
TEST_CHECK_CSTR(p, "sub"); TEST_CHECK_CSTR(p, "sub");
} }
TestVpiHandle vh_null_name = MY_VPI_HANDLE("___0_"); TestVpiHandle vh_null_name = my_vpi_handle("___0_");
TEST_CHECK_NZ(vh_null_name); TEST_CHECK_NZ(vh_null_name);
p = vpi_get_str(vpiName, vh_null_name); p = vpi_get_str(vpiName, vh_null_name);
TEST_CHECK_CSTR(p, "___0_"); TEST_CHECK_CSTR(p, "___0_");
TestVpiHandle vh_hex_name = MY_VPI_HANDLE("___0F_"); TestVpiHandle vh_hex_name = my_vpi_handle("___0F_");
TEST_CHECK_NZ(vh_hex_name); TEST_CHECK_NZ(vh_hex_name);
p = vpi_get_str(vpiName, vh_hex_name); p = vpi_get_str(vpiName, vh_hex_name);
TEST_CHECK_CSTR(p, "___0F_"); TEST_CHECK_CSTR(p, "___0F_");
@ -198,7 +218,7 @@ int _mon_check_ports() {
printf("-mon_check_ports()\n"); printf("-mon_check_ports()\n");
#endif #endif
// test writing to input port // test writing to input port
TestVpiHandle vh1 = MY_VPI_HANDLE("a"); TestVpiHandle vh1 = my_vpi_handle("a");
TEST_CHECK_NZ(vh1); TEST_CHECK_NZ(vh1);
PLI_INT32 d; PLI_INT32 d;
@ -236,7 +256,7 @@ int _mon_check_ports() {
TEST_CHECK_EQ(v.value.integer, 2); TEST_CHECK_EQ(v.value.integer, 2);
// get handle of toplevel module // get handle of toplevel module
TestVpiHandle vht = MY_VPI_HANDLE(""); TestVpiHandle vht = my_vpi_handle("");
TEST_CHECK_NZ(vht); TEST_CHECK_NZ(vht);
d = vpi_get(vpiType, vht); d = vpi_get(vpiType, vht);
@ -263,7 +283,7 @@ int _mon_check_ports() {
TEST_CHECK_EQ(handleName1, handleName2); TEST_CHECK_EQ(handleName1, handleName2);
TestVpiHandle vh2 = MY_VPI_HANDLE("\\b.c "); TestVpiHandle vh2 = my_vpi_handle("\\b.c ");
TEST_CHECK_NZ(vh2); TEST_CHECK_NZ(vh2);
if (TestSimulator::is_verilator()) { if (TestSimulator::is_verilator()) {

View File

@ -18,7 +18,7 @@ test.compile(make_top_shell=False,
sim_time=100, sim_time=100,
iv_flags2=["-g2005-sv -D USE_VPI_NOT_DPI -DWAVES"], iv_flags2=["-g2005-sv -D USE_VPI_NOT_DPI -DWAVES"],
v_flags2=["+define+USE_VPI_NOT_DPI"], v_flags2=["+define+USE_VPI_NOT_DPI"],
verilator_flags2=["--exe --vpi --no-l2name --public-flat-rw", test.pli_filename]) verilator_flags2=["--exe --vpi --no-l2name t/t_vpi_escape.vlt", test.pli_filename])
test.execute( test.execute(
# run_env = "VPI_TRACE=" . Cwd::getcwd() . "/" + test.obj_dir + "/" + test.name + "_vpi.log", # run_env = "VPI_TRACE=" . Cwd::getcwd() . "/" + test.obj_dir + "/" + test.name + "_vpi.log",

View File

@ -14,9 +14,10 @@ import "DPI-C" context function int mon_check();
module \t.has.dots (/*AUTOARG*/ module \t.has.dots (/*AUTOARG*/
// Outputs // Outputs
\escaped_normal , double__underscore, \9num , \bra[ket]slash/dash-colon:9backslash\done , \x.y , \escaped_normal , double__underscore, double__underscore__vlt, \9num ,
\bra[ket]slash/dash-colon:9backslash\done , \x.y ,
// Inputs // Inputs
clk, \b.c , a clk, a, \b.c
); );
`ifdef VERILATOR `ifdef VERILATOR
@ -26,16 +27,18 @@ extern "C" int mon_check();
`endif `endif
input clk; input clk;
input [7:0] a; input [7:0] a /*verilator public_flat_rw*/;
input \b.c ; input \b.c /*verilator public_flat_rw*/;
integer cyc; initial cyc=1; int cyc /*verilator public_flat_rd*/;
output \escaped_normal ; output \escaped_normal /*verilator public_flat_rd*/;
wire \escaped_normal = cyc[0]; wire \escaped_normal = cyc[0];
output double__underscore ; output double__underscore /*verilator public_flat_rd*/;
wire double__underscore = cyc[0]; wire double__underscore = cyc[0];
output double__underscore__vlt; // public in .vlt
wire double__underscore__vlt = cyc[0];
// C doesn't allow leading non-alpha, so must escape // C doesn't allow leading non-alpha, so must escape
output \9num ; output \9num ;
@ -44,14 +47,14 @@ extern "C" int mon_check();
output \bra[ket]slash/dash-colon:9backslash\done ; output \bra[ket]slash/dash-colon:9backslash\done ;
wire \bra[ket]slash/dash-colon:9backslash\done = cyc[0]; wire \bra[ket]slash/dash-colon:9backslash\done = cyc[0];
output \x.y ; output \x.y /*verilator public_flat_rd*/;
wire \x.y = cyc[0]; wire \x.y = cyc[0];
wire \wire = cyc[0]; wire \wire = cyc[0];
wire \check_alias = cyc[0]; wire \check_alias /*verilator public_flat_rd*/ = cyc[0];
wire \check:alias = cyc[0]; wire \check:alias /*verilator public_flat_rd*/ = cyc[0];
wire \check;alias = !cyc[0]; wire \check;alias /*verilator public_flat_rd*/ = !cyc[0];
// These are *different entities*, bug83 // These are *different entities*, bug83
wire [31:0] \a0.cyc = ~a0.cyc; wire [31:0] \a0.cyc = ~a0.cyc;
@ -110,11 +113,11 @@ extern "C" int mon_check();
endmodule endmodule
module sub ( module sub (
input [31:0] cyc input [31:0] cyc /*verilator public_flat_rd*/
); );
reg \b.c ; reg \b.c /*verilator public_flat_rw*/;
reg subsig1; reg subsig1 /*verilator public_flat_rd*/;
reg subsig2; reg subsig2 /*verilator public_flat_rd*/;
`ifdef IVERILOG `ifdef IVERILOG
// stop icarus optimizing signals away // stop icarus optimizing signals away
wire redundant = subsig1 | subsig2 | \b.c ; wire redundant = subsig1 | subsig2 | \b.c ;

View File

@ -0,0 +1,9 @@
// 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_config
public_flat_rd -module "*" -var "double__underscore__vlt"