Fix randomize inside module without any classes

This commit is contained in:
Wilson Snyder 2025-09-20 17:13:54 -04:00
parent b237eec801
commit 580a843474
8 changed files with 72 additions and 11 deletions

View File

@ -137,6 +137,7 @@ void V3Global::readFiles() {
void V3Global::removeStd() {
// Delete the std package if unused
if (!usesStdPackage()) {
UINFO(3, "Removing unused std:: package");
if (AstNodeModule* stdp = v3Global.rootp()->stdPackagep()) {
v3Global.rootp()->stdPackagep(nullptr);
VL_DO_DANGLING(stdp->unlinkFrBack()->deleteTree(), stdp);

View File

@ -4314,6 +4314,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|| nodep->name() == "rand_mode" || nodep->name() == "constraint_mode") {
if (AstClass* const classp = VN_CAST(m_modp, Class)) {
nodep->classOrPackagep(classp);
} else if (nodep->name() == "randomize") {
// A std::randomize resolved in V3Width
nodep->classOrPackagep(v3Global.rootp()->stdPackagep());
} else {
nodep->v3error("Calling implicit class method "
<< nodep->prettyNameQ() << " without being under class");

View File

@ -63,7 +63,7 @@ V3ParseImp::~V3ParseImp() {
//######################################################################
// Parser utility methods
void V3ParseImp::importIfInStd(FileLine* fileline, const string& id) {
void V3ParseImp::importIfInStd(FileLine* fileline, const string& id, bool doImport) {
// Keywords that auto-import to require use of verilated_std.vh.
// OK if overly sensitive; will over-import and keep std:: around
// longer than migt otherwise.
@ -76,9 +76,11 @@ void V3ParseImp::importIfInStd(FileLine* fileline, const string& id) {
if (AstPackage* const stdpkgp
= v3Global.rootp()->stdPackagep()) { // else e.g. --no-std-package
UINFO(9, "import and keep std:: for " << fileline);
AstPackageImport* const impp = new AstPackageImport{stdpkgp->fileline(), stdpkgp, "*"};
unitPackage(stdpkgp->fileline())->addStmtsp(impp);
v3Global.setUsesStdPackage();
if (doImport) {
AstPackageImport* const impp = new AstPackageImport{stdpkgp->fileline(), stdpkgp, "*"};
unitPackage(stdpkgp->fileline())->addStmtsp(impp);
}
}
}
@ -730,8 +732,9 @@ void V3ParseImp::tokenPipelineSym() {
// Note above sometimes converts yGLOBAL to a yaID__LEX
tokenPipeline(); // sets yylval
int token = yylval.token;
if (token == yaID__LEX || token == yaID__CC || token == yaID__aTYPE) {
importIfInStd(yylval.fl, *(yylval.strp));
if (token == yRANDOMIZE) importIfInStd(yylval.fl, "randomize", false);
if (token == yaID__ETC || token == yaID__CC || token == yaID__LEX || token == yaID__aTYPE) {
importIfInStd(yylval.fl, *(yylval.strp), true);
if (token == yaID__LEX) {
if (VString::startsWith(*(yylval.strp), "PATHPULSE__024")) {
token = yaID__PATHPULSE;

View File

@ -300,7 +300,7 @@ public:
void dumpInputsFile() VL_MT_DISABLED;
void dumpTokensAhead(int line) VL_MT_DISABLED;
static void candidatePli(VSpellCheck* spellerp) VL_MT_DISABLED;
void importIfInStd(FileLine* fileline, const string& id);
void importIfInStd(FileLine* fileline, const string& id, bool doImport);
private:
void preprocDumps(std::ostream& os);

View File

@ -3571,7 +3571,7 @@ statement_item<nodep>: // IEEE: statement_item
| yDISABLE yFORK ';' { $$ = new AstDisableFork{$1}; }
| yDISABLE idDottedSel ';'
{ $$ = new AstDisable{$1, $2};
PARSEP->importIfInStd($1, "process");
PARSEP->importIfInStd($1, "process", true);
}
// // IEEE: event_trigger
| yP_MINUSGT expr ';'

View File

@ -1,8 +1,5 @@
%Error: t/t_randomize_method_nclass_bad.v:9:7: Calling implicit class method 'randomize' without being under class
9 | randomize(1);
| ^~~~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_randomize_method_nclass_bad.v:10:7: Calling implicit class method 'srandom' without being under class
10 | srandom(1);
| ^~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

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.lint(verilator_flags2=["--binary"])
test.passes()

View File

@ -0,0 +1,41 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by PlanV GmbH.
// SPDX-License-Identifier: CC0-1.0
module t_scope_std_randomize;
bit [7:0] addr;
bit [15:0] data;
function bit run();
int ready;
int success;
bit [7:0] old_addr;
bit [15:0] old_data;
int old_ready;
old_addr = addr;
old_data = data;
old_ready = ready;
success = randomize(addr, ready); // std::randomize
if (success == 0) return 0;
if (addr == old_addr && data != old_data && ready == old_ready) begin
return 0;
end
return 1;
endfunction
initial begin
bit ok = 0;
int success;
ok = 0;
ok = run();
if (!ok) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule