Internals: Move PLI errors into linker, and better test.

This commit is contained in:
Wilson Snyder 2020-05-23 11:55:34 -04:00
parent 6a882f9dc6
commit 57621a93ad
9 changed files with 125 additions and 31 deletions

View File

@ -2731,6 +2731,7 @@ private:
string m_dotted; // Dotted part of scope the name()ed task/func is under or ""
string m_inlinedDots; // Dotted hierarchy flattened out
AstNodeModule* m_packagep; // Package hierarchy
bool m_pli; // Pli system call ($name)
public:
AstNodeFTaskRef(AstType t, FileLine* fl, bool statement, AstNode* namep, AstNode* pinsp)
: AstNodeStmt(t, fl, statement)
@ -2767,6 +2768,8 @@ public:
void dotted(const string& name) { m_dotted = name; }
AstNodeModule* packagep() const { return m_packagep; }
void packagep(AstNodeModule* nodep) { m_packagep = nodep; }
bool pli() const { return m_pli; }
void pli(bool flag) { m_pli = flag; }
// op1 = namep
AstNode* namep() const { return op1p(); }
// op2 = reserved for AstMethodCall

View File

@ -2491,11 +2491,39 @@ private:
} else if (VN_IS(nodep, New) && m_statep->forPrearray()) {
// Resolved in V3Width
} else if (nodep->dotted() == "") {
string suggest = m_statep->suggestSymFallback(dotSymp, nodep->name(),
LinkNodeMatcherFTask());
nodep->v3error("Can't find definition of task/function: "
<< nodep->prettyNameQ() << endl
<< (suggest.empty() ? "" : nodep->warnMore() + suggest));
if (nodep->pli()) {
if (v3Global.opt.bboxSys()) {
AstNode* newp;
if (VN_IS(nodep, FuncRef)) {
newp = new AstConst(nodep->fileline(), AstConst::StringToParse(),
"'0");
} else {
AstNode* outp = NULL;
while (nodep->pinsp()) {
AstNode* pinp = nodep->pinsp()->unlinkFrBack();
AstNode* addp = pinp;
if (AstArg* argp = VN_CAST(pinp, Arg)) {
addp = argp->exprp()->unlinkFrBack();
VL_DO_DANGLING(pinp->deleteTree(), pinp);
}
outp = AstNode::addNext(outp, addp);
}
newp = new AstSysIgnore(nodep->fileline(), outp);
}
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
return;
} else {
nodep->v3error("Unsupported or unknown PLI call: "
<< nodep->prettyNameQ() << endl);
}
} else {
string suggest = m_statep->suggestSymFallback(dotSymp, nodep->name(),
LinkNodeMatcherFTask());
nodep->v3error("Can't find definition of task/function: "
<< nodep->prettyNameQ() << endl
<< (suggest.empty() ? "" : nodep->warnMore() + suggest));
}
} else {
string suggest = m_statep->suggestSymFallback(dotSymp, nodep->name(),
LinkNodeMatcherFTask());

View File

@ -65,15 +65,20 @@ void V3ParseImp::parserClear() {
//======================================================================
// V3ParseGrammar functions requiring bison state
void V3ParseGrammar::argWrapList(AstNodeFTaskRef* nodep) {
AstNode* V3ParseGrammar::argWrapList(AstNode* nodep) {
// Convert list of expressions to list of arguments
if (!nodep) return NULL;
AstNode* outp = NULL;
while (nodep->pinsp()) {
AstNode* exprp = nodep->pinsp()->unlinkFrBack();
AstBegin* tempp = new AstBegin(nodep->fileline(), "[EditWrapper]", nodep);
while (nodep) {
AstNode* nextp = nodep->nextp();
AstNode* exprp = nodep->unlinkFrBack();
nodep = nextp;
// addNext can handle nulls:
outp = AstNode::addNext(outp, new AstArg(exprp->fileline(), "", exprp));
}
if (outp) nodep->addPinsp(outp);
VL_DO_DANGLING(tempp->deleteTree(), tempp);
return outp;
}
AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, const string& name, int value) {

View File

@ -44,10 +44,6 @@ extern void yyerrorf(const char* format, ...);
#define FL { FL_FWD; yylval.fl = CRELINE(); }
#define RETURN_BBOX_SYS_OR_MSG(msg,yytext) { \
if (!v3Global.opt.bboxSys()) { yyerrorf(msg, yytext); FL_BRK; } \
return yaD_IGNORE; }
#define ERROR_RSVD_WORD(language) \
do { FL_FWD; \
yyerrorf("Unsupported: " language " reserved word not implemented: '%s'", yytext); \
@ -601,10 +597,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX>{
"$"[a-zA-Z_$][a-zA-Z0-9_$]* { string str (yytext, yyleng);
yylval.strp = PARSEP->newString(AstNode::encodeName(str));
// Lookup unencoded name including the $, to avoid hitting normal signals
if (SYMP->symCurrentp()->findIdFallback(str)) {
FL; return yaD_DPI;
} else { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported or unknown PLI call: %s", yytext); }
FL; return yaD_PLI;
}
}

View File

@ -91,7 +91,7 @@ public:
}
// METHODS
void argWrapList(AstNodeFTaskRef* nodep);
AstNode* argWrapList(AstNode* nodep);
bool allTracingOn(FileLine* fl) {
return v3Global.opt.trace() && m_tracingParse && fl->tracingOn();
}
@ -311,8 +311,7 @@ class AstSenTree;
%token<fl> yVLT_D_TASK "--task"
%token<fl> yVLT_D_VAR "--var"
%token<strp> yaD_IGNORE "${ignored-bbox-sys}"
%token<strp> yaD_DPI "${dpi-sys}"
%token<strp> yaD_PLI "${pli-system}"
%token<fl> yaT_RESETALL "`resetall"
@ -3264,12 +3263,7 @@ function_subroutine_callNoMethod<nodep>: // IEEE: function_subroutine_call (as f
system_t_call<nodep>: // IEEE: system_tf_call (as task)
//
yaD_IGNORE parenE { $$ = new AstSysIgnore($<fl>1,NULL); }
| yaD_IGNORE '(' exprList ')' { $$ = new AstSysIgnore($<fl>1,$3); }
//
| yaD_DPI parenE { $$ = new AstTaskRef($<fl>1,*$1,NULL); }
| yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($<fl>1, *$1, $3);
GRAMMARP->argWrapList(VN_CAST($$, TaskRef)); }
yaD_PLI systemDpiArgsE { $$ = new AstTaskRef($<fl>1, *$1, $2); VN_CAST($$, TaskRef)->pli(true); }
//
| yD_DUMPPORTS '(' idDotted ',' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::FILE, $5); DEL($3);
$$->addNext(new AstDumpCtl($<fl>1, VDumpCtlType::VARS,
@ -3369,11 +3363,7 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
;
system_f_call<nodep>: // IEEE: system_tf_call (as func)
yaD_IGNORE parenE { $$ = new AstConst($<fl>1, AstConst::StringToParse(), "'b0"); } // Unsized 0
| yaD_IGNORE '(' exprList ')' { $$ = new AstConst($<fl>1, AstConst::StringToParse(), "'b0"); } // Unsized 0
//
| yaD_DPI parenE { $$ = new AstFuncRef($<fl>1,*$1,NULL); }
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($<fl>1,*$1,$3); GRAMMARP->argWrapList(VN_CAST($$, FuncRef)); }
yaD_PLI systemDpiArgsE { $$ = new AstFuncRef($<fl>1, *$1, $2); VN_CAST($$, FuncRef)->pli(true); }
//
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
@ -3381,6 +3371,11 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| system_f_call_or_t { $$ = $1; }
;
systemDpiArgsE<nodep>: // IEEE: part of system_if_call for aruments of $dpi call
parenE { $$ = NULL; }
| '(' exprList ')' { $$ = GRAMMARP->argWrapList($2); }
;
system_f_call_or_t<nodep>: // IEEE: part of system_tf_call (can be task or func)
yD_ACOS '(' expr ')' { $$ = new AstAcosD($1,$3); }
| yD_ACOSH '(' expr ')' { $$ = new AstAcoshD($1,$3); }

View File

@ -0,0 +1,13 @@
%Error: t/t_pli_bad.v:10:7: Unsupported or unknown PLI call: '$unknown_pli_task'
10 | $unknown_pli_task;
| ^~~~~~~~~~~~~~~~~
%Error: t/t_pli_bad.v:11:7: Unsupported or unknown PLI call: '$unknown_pli_task'
11 | $unknown_pli_task("arg", i);
| ^~~~~~~~~~~~~~~~~
%Error: t/t_pli_bad.v:12:11: Unsupported or unknown PLI call: '$unknown_pli_function'
12 | i = $unknown_pli_function;
| ^~~~~~~~~~~~~~~~~~~~~
%Error: t/t_pli_bad.v:13:11: Unsupported or unknown PLI call: '$unknown_pli_function'
13 | i = $unknown_pli_function("arg", i);
| ^~~~~~~~~~~~~~~~~~~~~
%Error: Exiting due to

20
test_regress/t/t_pli_bad.pl Executable file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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
scenarios(linter => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,16 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2019 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t;
integer i;
initial begin
$unknown_pli_task;
$unknown_pli_task("arg", i);
i = $unknown_pli_function;
i = $unknown_pli_function("arg", i);
$stop;
end
endmodule

21
test_regress/t/t_pli_bbox.pl Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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
scenarios(vlt => 1);
top_filename("t/t_pli_bad.v");
lint(
verilator_flags2 => ["--bbox-sys"],
);
ok(1);
1;