diff --git a/Changes b/Changes index 7e26899a3..d6e49d708 100644 --- a/Changes +++ b/Changes @@ -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] diff --git a/src/V3Ast.h b/src/V3Ast.h index dd350519f..a7161e2a1 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -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"); } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index acdbd9256..3307eedfc 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -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]"; diff --git a/src/V3Control.cpp b/src/V3Control.cpp index ee3f49d33..36402417b 100644 --- a/src/V3Control.cpp +++ b/src/V3Control.cpp @@ -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); } diff --git a/src/verilog.y b/src/verilog.y index f82f79ed3..085182f07 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -8087,8 +8087,10 @@ vltDModule: // --module ; vltDModuleE: // [--module ] - /* empty */ { static string unit = "__024unit"; $$ = &unit; } - | vltDModule { $$ = $1; } + /* empty */ + { static string unit = "$unit"; $$ = &unit; } // .vlt uses prettyName + | vltDModule + { $$ = $1; } ; vltDScope: // --scope diff --git a/test_regress/t/t_dpi_var_vlt.py b/test_regress/t/t_dpi_var_vlt.py index ad82e250d..c43dca9c4 100755 --- a/test_regress/t/t_dpi_var_vlt.py +++ b/test_regress/t/t_dpi_var_vlt.py @@ -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() diff --git a/test_regress/t/t_vpi_escape.cpp b/test_regress/t/t_vpi_escape.cpp index 73b7875fd..0ba0c24bc 100644 --- a/test_regress/t/t_vpi_escape.cpp +++ b/test_regress/t/t_vpi_escape.cpp @@ -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(_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(_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(_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()) { diff --git a/test_regress/t/t_vpi_escape.py b/test_regress/t/t_vpi_escape.py index e216188d9..dcc91956c 100755 --- a/test_regress/t/t_vpi_escape.py +++ b/test_regress/t/t_vpi_escape.py @@ -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", diff --git a/test_regress/t/t_vpi_escape.v b/test_regress/t/t_vpi_escape.v index a912c1096..4ac951067 100644 --- a/test_regress/t/t_vpi_escape.v +++ b/test_regress/t/t_vpi_escape.v @@ -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 ; diff --git a/test_regress/t/t_vpi_escape.vlt b/test_regress/t/t_vpi_escape.vlt new file mode 100644 index 000000000..bced08f31 --- /dev/null +++ b/test_regress/t/t_vpi_escape.vlt @@ -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"