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:**
* 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 genvar error with `-O0` (#6165). [Max Wipfli]

View File

@ -2222,6 +2222,9 @@ public:
// ACCESSORS
virtual string name() const VL_MT_STABLE { return ""; }
virtual string origName() const { return ""; }
string prettyOrigOrName() const {
return prettyName(origName().empty() ? name() : origName());
}
virtual void name(const string& name) {
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 (isUsedClock()) str << " [CLK]";
if (isSigPublic()) str << " [P]";
if (isSigUserRdPublic()) str << " [PRD]";
if (isSigUserRWPublic()) str << " [PWR]";
if (isInternal()) str << " [INTERNAL]";
if (isLatched()) str << " [LATCHED]";
if (isUsedLoopIdx()) str << " [LOOP]";

View File

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

View File

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

View File

@ -25,19 +25,18 @@ test.compile(make_top_shell=False,
if test.vlt_all:
test.file_grep(
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(
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(
out_filename,
r'{"type":"VAR","name":"t.sub.fr_a","addr":"[^"]*","loc":"\w,82:[^"]*",.*"origName":"fr_a",.*"dtypeName":"int",.*"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'
r'{"type":"VAR","name":"t.sub.fr_b",.*"origName":"fr_b",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true'
)
test.execute()

View File

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

View File

@ -18,7 +18,7 @@ test.compile(make_top_shell=False,
sim_time=100,
iv_flags2=["-g2005-sv -D USE_VPI_NOT_DPI -DWAVES"],
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(
# run_env = "VPI_TRACE=" . Cwd::getcwd() . "/" + test.obj_dir + "/" + test.name + "_vpi.log",

View File

@ -13,11 +13,12 @@ import "DPI-C" context function int mon_check();
`endif
module \t.has.dots (/*AUTOARG*/
// Outputs
\escaped_normal , double__underscore, \9num , \bra[ket]slash/dash-colon:9backslash\done , \x.y ,
// Inputs
clk, \b.c , a
);
// Outputs
\escaped_normal , double__underscore, double__underscore__vlt, \9num ,
\bra[ket]slash/dash-colon:9backslash\done , \x.y ,
// Inputs
clk, a, \b.c
);
`ifdef VERILATOR
`systemc_header
@ -26,16 +27,18 @@ extern "C" int mon_check();
`endif
input clk;
input [7:0] a;
input \b.c ;
input [7:0] a /*verilator public_flat_rw*/;
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];
output double__underscore ;
output double__underscore /*verilator public_flat_rd*/;
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
output \9num ;
@ -44,14 +47,14 @@ extern "C" int mon_check();
output \bra[ket]slash/dash-colon:9backslash\done ;
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 \wire = cyc[0];
wire \check_alias = cyc[0];
wire \check:alias = cyc[0];
wire \check;alias = !cyc[0];
wire \check_alias /*verilator public_flat_rd*/ = cyc[0];
wire \check:alias /*verilator public_flat_rd*/ = cyc[0];
wire \check;alias /*verilator public_flat_rd*/ = !cyc[0];
// These are *different entities*, bug83
wire [31:0] \a0.cyc = ~a0.cyc;
@ -110,11 +113,11 @@ extern "C" int mon_check();
endmodule
module sub (
input [31:0] cyc
input [31:0] cyc /*verilator public_flat_rd*/
);
reg \b.c ;
reg subsig1;
reg subsig2;
reg \b.c /*verilator public_flat_rw*/;
reg subsig1 /*verilator public_flat_rd*/;
reg subsig2 /*verilator public_flat_rd*/;
`ifdef IVERILOG
// stop icarus optimizing signals away
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"