mirror of
https://github.com/verilator/verilator.git
synced 2025-07-31 07:56:10 +00:00
Support std::semaphore
and typed std::mailbox
(#3708)
Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
This commit is contained in:
parent
4452a9b10f
commit
68e1b473e2
106
include/std.sv
Normal file
106
include/std.sv
Normal file
@ -0,0 +1,106 @@
|
||||
// DESCRIPTION: Verilator: built-in packages and classes
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2022 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
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
// verilator lint_off DECLFILENAME
|
||||
// verilator lint_off TIMESCALEMOD
|
||||
// verilator lint_off UNUSEDSIGNAL
|
||||
package std;
|
||||
class mailbox #(type T);
|
||||
protected int m_bound;
|
||||
protected T m_queue[$];
|
||||
|
||||
function new(int bound = 0);
|
||||
m_bound = bound;
|
||||
endfunction
|
||||
|
||||
function int num();
|
||||
return m_queue.size();
|
||||
endfunction
|
||||
|
||||
task put(T message);
|
||||
`ifdef VERILATOR_TIMING
|
||||
if (m_bound != 0)
|
||||
wait (m_queue.size() < m_bound);
|
||||
m_queue.push_back(message);
|
||||
`endif
|
||||
endtask
|
||||
|
||||
function int try_put(T message);
|
||||
if (num() < m_bound) begin
|
||||
m_queue.push_back(message);
|
||||
return 1;
|
||||
end
|
||||
return 0;
|
||||
endfunction
|
||||
|
||||
task get(ref T message);
|
||||
`ifdef VERILATOR_TIMING
|
||||
wait (m_queue.size() > 0);
|
||||
message = m_queue.pop_front();
|
||||
`endif
|
||||
endtask
|
||||
|
||||
function int try_get(ref T message);
|
||||
if (num() > 0) begin
|
||||
message = m_queue.pop_front();
|
||||
return 1;
|
||||
end
|
||||
return 0;
|
||||
endfunction
|
||||
|
||||
task peek(ref T message);
|
||||
`ifdef VERILATOR_TIMING
|
||||
wait (m_queue.size() > 0);
|
||||
message = m_queue[0];
|
||||
`endif
|
||||
endtask
|
||||
|
||||
function int try_peek(ref T message);
|
||||
if (num() > 0) begin
|
||||
message = m_queue[0];
|
||||
return 1;
|
||||
end
|
||||
return 0;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class semaphore;
|
||||
protected int m_keyCount;
|
||||
|
||||
function new(int keyCount = 0);
|
||||
m_keyCount = keyCount;
|
||||
endfunction
|
||||
|
||||
function void put(int keyCount = 1);
|
||||
m_keyCount += keyCount;
|
||||
endfunction
|
||||
|
||||
task get(int keyCount = 1);
|
||||
`ifdef VERILATOR_TIMING
|
||||
wait (m_keyCount >= keyCount);
|
||||
m_keyCount -= keyCount;
|
||||
`endif
|
||||
endtask
|
||||
|
||||
function int try_get(int keyCount = 1);
|
||||
if (m_keyCount >= keyCount) begin
|
||||
m_keyCount -= keyCount;
|
||||
return 1;
|
||||
end
|
||||
return 0;
|
||||
endfunction
|
||||
endclass
|
||||
endpackage
|
||||
|
||||
// verilator lint_off IMPORTSTAR
|
||||
import std::*;
|
@ -1086,6 +1086,7 @@ class AstNetlist final : public AstNode {
|
||||
AstTypeTable* const m_typeTablep; // Reference to top type table, for faster lookup
|
||||
AstConstPool* const m_constPoolp; // Reference to constant pool, for faster lookup
|
||||
AstPackage* m_dollarUnitPkgp = nullptr; // $unit
|
||||
AstPackage* m_stdPackagep = nullptr; // SystemVerilog std package
|
||||
AstCFunc* m_evalp = nullptr; // The '_eval' function
|
||||
AstCFunc* m_evalNbap = nullptr; // The '_eval__nba' function
|
||||
AstVarScope* m_dpiExportTriggerp = nullptr; // The DPI export trigger variable
|
||||
@ -1119,6 +1120,8 @@ public:
|
||||
void dpiExportTriggerp(AstVarScope* varScopep) { m_dpiExportTriggerp = varScopep; }
|
||||
AstVar* delaySchedulerp() const { return m_delaySchedulerp; }
|
||||
void delaySchedulerp(AstVar* const varScopep) { m_delaySchedulerp = varScopep; }
|
||||
void stdPackagep(AstPackage* const packagep) { m_stdPackagep = packagep; }
|
||||
AstPackage* stdPackagep() const { return m_stdPackagep; }
|
||||
AstTopScope* topScopep() const { return m_topScopep; }
|
||||
void createTopScope(AstScope* scopep);
|
||||
VTimescale timeunit() const { return m_timeunit; }
|
||||
|
@ -63,6 +63,13 @@ void V3Global::readFiles() {
|
||||
"Cannot find file containing module: ");
|
||||
}
|
||||
|
||||
if (usesStdPackage()) {
|
||||
// Parse the std package
|
||||
parser.parseFile(new FileLine{FileLine::commandLineFilename()},
|
||||
V3Options::getStdPackagePath(), false,
|
||||
"Cannot find std.sv containing built-in std:: definitions: ");
|
||||
}
|
||||
|
||||
// Read libraries
|
||||
// To be compatible with other simulators,
|
||||
// this needs to be done after the top file is read
|
||||
|
@ -107,6 +107,7 @@ class V3Global final {
|
||||
bool m_dpi = false; // Need __Dpi include files
|
||||
bool m_hasEvents = false; // Design uses SystemVerilog named events
|
||||
bool m_hasClasses = false; // Design uses SystemVerilog classes
|
||||
bool m_usesStdPackage = false; // Design uses the std package
|
||||
bool m_usesTiming = false; // Design uses timing constructs
|
||||
bool m_hasForceableSignals = false; // Need to apply V3Force pass
|
||||
bool m_hasSCTextSections = false; // Has `systemc_* sections that need to be emitted
|
||||
@ -152,6 +153,8 @@ public:
|
||||
void setHasEvents() { m_hasEvents = true; }
|
||||
bool hasClasses() const { return m_hasClasses; }
|
||||
void setHasClasses() { m_hasClasses = true; }
|
||||
bool usesStdPackage() const { return m_usesStdPackage; }
|
||||
void setUsesStdPackage() { m_usesStdPackage = true; }
|
||||
bool usesTiming() const { return m_usesTiming; }
|
||||
void setUsesTiming() { m_usesTiming = true; }
|
||||
bool hasForceableSignals() const { return m_hasForceableSignals; }
|
||||
|
@ -50,6 +50,7 @@ private:
|
||||
using ImplTypedefMap = std::map<const std::pair<void*, std::string>, AstTypedef*>;
|
||||
|
||||
// STATE
|
||||
AstPackage* const m_stdPackagep; // SystemVerilog std package
|
||||
AstVar* m_varp = nullptr; // Variable we're under
|
||||
ImplTypedefMap m_implTypedef; // Created typedefs for each <container,name>
|
||||
std::unordered_set<FileLine*> m_filelines; // Filelines that have been seen
|
||||
@ -600,6 +601,11 @@ private:
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
}
|
||||
}
|
||||
void visit(AstClassOrPackageRef* nodep) override {
|
||||
if (nodep->name() == "std" && !nodep->classOrPackagep()) {
|
||||
nodep->classOrPackagep(m_stdPackagep);
|
||||
}
|
||||
}
|
||||
|
||||
void visit(AstNode* nodep) override {
|
||||
// Default: Just iterate
|
||||
@ -609,7 +615,10 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit LinkParseVisitor(AstNetlist* rootp) { iterate(rootp); }
|
||||
explicit LinkParseVisitor(AstNetlist* rootp)
|
||||
: m_stdPackagep{rootp->stdPackagep()} {
|
||||
iterate(rootp);
|
||||
}
|
||||
~LinkParseVisitor() override = default;
|
||||
};
|
||||
|
||||
|
@ -706,6 +706,8 @@ string V3Options::getenvVERILATOR_ROOT() {
|
||||
return var;
|
||||
}
|
||||
|
||||
string V3Options::getStdPackagePath() { return getenvVERILATOR_ROOT() + "/include/std.sv"; }
|
||||
|
||||
string V3Options::getSupported(const string& var) {
|
||||
// If update below, also update V3Options::showVersion()
|
||||
if (var == "COROUTINES" && coroutineSupport()) {
|
||||
|
@ -666,6 +666,7 @@ public:
|
||||
static string getenvSYSTEMC_INCLUDE();
|
||||
static string getenvSYSTEMC_LIBDIR();
|
||||
static string getenvVERILATOR_ROOT();
|
||||
static string getStdPackagePath();
|
||||
static string getSupported(const string& var);
|
||||
static bool systemCSystemWide();
|
||||
static bool systemCFound(); // SystemC installed, or environment points to it
|
||||
|
@ -532,14 +532,17 @@ void V3ParseImp::tokenPipelineSym() {
|
||||
&& (*(yylval.strp) == "mailbox" // IEEE-standard class
|
||||
|| *(yylval.strp) == "process" // IEEE-standard class
|
||||
|| *(yylval.strp) == "semaphore")) { // IEEE-standard class
|
||||
v3Global.setUsesStdPackage();
|
||||
yylval.scp = nullptr;
|
||||
if (token == yaID__LEX) token = yaID__aTYPE;
|
||||
} else { // Not found
|
||||
yylval.scp = nullptr;
|
||||
if (token == yaID__CC) {
|
||||
// IEEE does require this, but we may relax this as UVM breaks it, so allow bbox
|
||||
// for today
|
||||
if (!v3Global.opt.bboxUnsup()) {
|
||||
if (!m_afterColonColon && *(yylval.strp) == "std") {
|
||||
v3Global.setUsesStdPackage();
|
||||
} else if (!v3Global.opt.bboxUnsup()) {
|
||||
// IEEE does require this, but we may relax this as UVM breaks it, so allow
|
||||
// bbox for today
|
||||
// We'll get a parser error eventually but might not be obvious
|
||||
// is missing package, and this confuses people
|
||||
static int warned = false;
|
||||
@ -554,6 +557,7 @@ void V3ParseImp::tokenPipelineSym() {
|
||||
}
|
||||
}
|
||||
}
|
||||
m_afterColonColon = token == yP_COLONCOLON;
|
||||
yylval.token = token;
|
||||
// effectively returns yylval
|
||||
}
|
||||
|
@ -150,6 +150,7 @@ class V3ParseImp final {
|
||||
VOptionBool m_unconnectedDrive; // Last unconnected drive
|
||||
|
||||
int m_lexPrevToken = 0; // previous parsed token (for lexer)
|
||||
bool m_afterColonColon = false; // The previous token was '::'
|
||||
std::deque<V3ParseBisonYYSType> m_tokensAhead; // Tokens we parsed ahead of parser
|
||||
|
||||
std::deque<string*> m_stringps; // Created strings for later cleanup
|
||||
|
@ -3291,6 +3291,16 @@ private:
|
||||
VL_DANGLING(index_exprp); // May have been edited
|
||||
return VN_AS(nodep->pinsp(), Arg)->exprp();
|
||||
}
|
||||
void methodCallWarnTiming(AstMethodCall* const nodep, const std::string& className) {
|
||||
if (v3Global.opt.timing().isSetFalse()) {
|
||||
nodep->v3warn(E_NOTIMING,
|
||||
className << "::" << nodep->name() << "() requires --timing");
|
||||
} else if (!v3Global.opt.timing().isSetTrue()) {
|
||||
nodep->v3warn(E_NEEDTIMINGOPT, "Use --timing or --no-timing to specify how "
|
||||
<< className << "::" << nodep->name()
|
||||
<< "() should be handled");
|
||||
}
|
||||
}
|
||||
void methodCallClass(AstMethodCall* nodep, AstClassRefDType* adtypep) {
|
||||
// No need to width-resolve the class, as it was done when we did the child
|
||||
AstClass* const first_classp = adtypep->classp();
|
||||
@ -3300,6 +3310,26 @@ private:
|
||||
}
|
||||
UASSERT_OBJ(first_classp, nodep, "Unlinked");
|
||||
for (AstClass* classp = first_classp; classp;) {
|
||||
if (nodep->fileline()->timingOn()) {
|
||||
if (classp->name() == "semaphore"
|
||||
|| VString::startsWith(classp->name(), "mailbox")) {
|
||||
// Find the package the class is in
|
||||
AstNode* pkgItemp = classp;
|
||||
while (pkgItemp->backp() && pkgItemp->backp()->nextp() == pkgItemp) {
|
||||
pkgItemp = pkgItemp->backp();
|
||||
}
|
||||
AstPackage* const packagep = VN_CAST(pkgItemp->backp(), Package);
|
||||
// Check if it's std
|
||||
if (packagep && packagep->name() == "std") {
|
||||
if (classp->name() == "semaphore" && nodep->name() == "get") {
|
||||
methodCallWarnTiming(nodep, "semaphore");
|
||||
} else if (nodep->name() == "put" || nodep->name() == "get"
|
||||
|| nodep->name() == "peek") {
|
||||
methodCallWarnTiming(nodep, "mailbox");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (AstNodeFTask* const ftaskp
|
||||
= VN_CAST(classp->findMember(nodep->name()), NodeFTask)) {
|
||||
userIterate(ftaskp, nullptr);
|
||||
|
@ -1162,6 +1162,13 @@ package_declaration: // ==IEEE: package_declaration
|
||||
packageFront<nodeModulep>:
|
||||
yPACKAGE lifetimeE idAny ';'
|
||||
{ $$ = new AstPackage{$<fl>3, *$3};
|
||||
if ($$->name() == "std") {
|
||||
if ($$->fileline()->filename() != V3Options::getStdPackagePath()) {
|
||||
$$->v3error("Redeclaring the 'std' package is not allowed");
|
||||
} else {
|
||||
PARSEP->rootp()->stdPackagep(VN_AS($$, Package));
|
||||
}
|
||||
}
|
||||
$$->inLibrary(true); // packages are always libraries; don't want to make them a "top"
|
||||
$$->lifetime($2);
|
||||
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
|
||||
|
@ -1,6 +0,0 @@
|
||||
%Error: t/t_mailbox.v:24:4: Can't find typedef: 'mailbox'
|
||||
24 | mailbox #(int) m;
|
||||
| ^~~~~~~
|
||||
%Error: Internal Error: t/t_mailbox.v:24:14: ../V3LinkDot.cpp:#: Pin not under instance?
|
||||
24 | mailbox #(int) m;
|
||||
| ^~~
|
@ -10,14 +10,19 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
fails => $Self->{vlt_all},
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
if (!$Self->have_coroutines) {
|
||||
skip("No coroutine support");
|
||||
}
|
||||
else {
|
||||
compile(
|
||||
verilator_flags2 => ["--exe --main --timing -Wall"],
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
) if !$Self->{vlt_all};
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
}
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
@ -20,6 +20,7 @@
|
||||
`define MAILBOX_T mailbox
|
||||
`endif
|
||||
|
||||
// verilator lint_off DECLFILENAME
|
||||
module t(/*AUTOARG*/);
|
||||
`MAILBOX_T #(int) m;
|
||||
int msg;
|
||||
|
@ -1,6 +1,5 @@
|
||||
%Error: t/t_mailbox_bad.v:8:4: Can't find typedef: 'mailbox'
|
||||
8 | mailbox #(int) m;
|
||||
| ^~~~~~~
|
||||
%Error: Internal Error: t/t_mailbox_bad.v:8:14: ../V3LinkDot.cpp:#: Pin not under instance?
|
||||
8 | mailbox #(int) m;
|
||||
| ^~~
|
||||
%Error: t/t_mailbox_bad.v:12:13: Class method 'bad_method' not found in class 'mailbox__Tz1'
|
||||
: ... In instance t
|
||||
12 | if (m.bad_method() != 0) $stop;
|
||||
| ^~~~~~~~~~
|
||||
%Error: Exiting due to
|
||||
|
@ -1,6 +0,0 @@
|
||||
%Error: t/t_mailbox.v:24:4: Can't find typedef: 'mailbox'
|
||||
24 | mailbox #(int) m;
|
||||
| ^~~~~~~
|
||||
%Error: Internal Error: t/t_mailbox.v:24:14: ../V3LinkDot.cpp:#: Pin not under instance?
|
||||
24 | mailbox #(int) m;
|
||||
| ^~~
|
@ -10,17 +10,21 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
top_filename("t/t_mailbox.v");
|
||||
if (!$Self->have_coroutines) {
|
||||
skip("No coroutine support");
|
||||
}
|
||||
else {
|
||||
top_filename("t/t_mailbox.v");
|
||||
|
||||
compile(
|
||||
v_flags2 => ["+define+T_MAILBOX+std::mailbox"],
|
||||
fails => $Self->{vlt_all},
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
compile(
|
||||
verilator_flags2 => ["--exe --main --timing -Wall -DMAILBOX_T=std::mailbox"],
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
) if !$Self->{vlt_all};
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
}
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
@ -30,4 +30,20 @@
|
||||
: ... In instance t
|
||||
27 | initial #2 $stop;
|
||||
| ^
|
||||
%Error-NOTIMING: t/t_notiming.v:33:10: mailbox::put() requires --timing
|
||||
: ... In instance t
|
||||
33 | m.put(i);
|
||||
| ^~~
|
||||
%Error-NOTIMING: t/t_notiming.v:34:10: mailbox::get() requires --timing
|
||||
: ... In instance t
|
||||
34 | m.get(i);
|
||||
| ^~~
|
||||
%Error-NOTIMING: t/t_notiming.v:35:10: mailbox::peek() requires --timing
|
||||
: ... In instance t
|
||||
35 | m.peek(i);
|
||||
| ^~~~
|
||||
%Error-NOTIMING: t/t_notiming.v:36:10: semaphore::get() requires --timing
|
||||
: ... In instance t
|
||||
36 | s.get();
|
||||
| ^~~
|
||||
%Error: Exiting due to
|
||||
|
@ -25,6 +25,16 @@ module t;
|
||||
|
||||
initial #1 ->e;
|
||||
initial #2 $stop; // timeout
|
||||
|
||||
mailbox#(int) m = new;
|
||||
semaphore s = new;
|
||||
initial begin
|
||||
int i;
|
||||
m.put(i);
|
||||
m.get(i);
|
||||
m.peek(i);
|
||||
s.get();
|
||||
end
|
||||
endmodule
|
||||
|
||||
`ifdef VERILATOR_TIMING
|
||||
|
@ -1,7 +0,0 @@
|
||||
%Error: t/t_semaphore.v:21:4: Can't find typedef: 'semaphore'
|
||||
21 | semaphore s;
|
||||
| ^~~~~~~~~
|
||||
%Error: t/t_semaphore.v:22:4: Can't find typedef: 'semaphore'
|
||||
22 | semaphore s2;
|
||||
| ^~~~~~~~~
|
||||
%Error: Exiting due to
|
@ -10,14 +10,19 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
fails => $Self->{vlt_all},
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
if (!$Self->have_coroutines) {
|
||||
skip("No coroutine support");
|
||||
}
|
||||
else {
|
||||
compile(
|
||||
verilator_flags2 => ["--exe --main --timing -Wall"],
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
) if !$Self->{vlt_all};
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
}
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
@ -16,11 +16,11 @@
|
||||
`define SEMAPHORE_T semaphore
|
||||
`endif
|
||||
|
||||
// verilator lint_off DECLFILENAME
|
||||
module t(/*AUTOARG*/);
|
||||
// From UVM:
|
||||
`SEMAPHORE_T s;
|
||||
`SEMAPHORE_T s2;
|
||||
int msg;
|
||||
|
||||
initial begin
|
||||
s = new(1);
|
||||
|
@ -1,4 +1,5 @@
|
||||
%Error: t/t_semaphore_bad.v:8:4: Can't find typedef: 'semaphore'
|
||||
8 | semaphore s;
|
||||
| ^~~~~~~~~
|
||||
%Error: t/t_semaphore_bad.v:12:13: Class method 'bad_method' not found in class 'semaphore'
|
||||
: ... In instance t
|
||||
12 | if (s.bad_method() != 0) $stop;
|
||||
| ^~~~~~~~~~
|
||||
%Error: Exiting due to
|
||||
|
@ -1,7 +0,0 @@
|
||||
%Error: t/t_semaphore.v:21:4: Can't find typedef: 'semaphore'
|
||||
21 | semaphore s;
|
||||
| ^~~~~~~~~
|
||||
%Error: t/t_semaphore.v:22:4: Can't find typedef: 'semaphore'
|
||||
22 | semaphore s2;
|
||||
| ^~~~~~~~~
|
||||
%Error: Exiting due to
|
@ -10,17 +10,21 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
top_filename("t/t_semaphore.v");
|
||||
if (!$Self->have_coroutines) {
|
||||
skip("No coroutine support");
|
||||
}
|
||||
else {
|
||||
top_filename("t/t_semaphore.v");
|
||||
|
||||
compile(
|
||||
v_flags2 => ["+define+T_SEMAPHORE+std::semaphore"],
|
||||
fails => $Self->{vlt_all},
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
compile(
|
||||
verilator_flags2 => ["--exe --main --timing -Wall -DSEMAPHORE_T=std::semaphore"],
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
) if !$Self->{vlt_all};
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
}
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
5
test_regress/t/t_std_identifier.out
Normal file
5
test_regress/t/t_std_identifier.out
Normal file
@ -0,0 +1,5 @@
|
||||
%Error-PKGNODECL: t/t_std_identifier.v:16:20: Package/class 'std' not found, and needs to be predeclared (IEEE 1800-2017 26.3)
|
||||
16 | int baz = foo::std::bar;
|
||||
| ^~~
|
||||
... For error description see https://verilator.org/warn/PKGNODECL?v=latest
|
||||
%Error: Exiting due to
|
@ -2,18 +2,21 @@
|
||||
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
|
||||
# Copyright 2022 by Antmicro Ltd. 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_semaphore.v");
|
||||
scenarios(linter => 1);
|
||||
|
||||
lint(
|
||||
verilator_flags2 => ["--debug-exit-uvm"],
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
lint(
|
||||
verilator_flags2 => ["-DTEST_DECLARE_STD"],
|
||||
);
|
||||
|
||||
ok(1);
|
17
test_regress/t/t_std_identifier.v
Normal file
17
test_regress/t/t_std_identifier.v
Normal file
@ -0,0 +1,17 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2022 by Antmicro Ltd.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
package foo;
|
||||
`ifdef TEST_DECLARE_STD
|
||||
class std;
|
||||
static int bar;
|
||||
endclass
|
||||
`endif
|
||||
endpackage
|
||||
|
||||
module t;
|
||||
int baz = foo::std::bar;
|
||||
endmodule
|
4
test_regress/t/t_std_pkg_bad.out
Normal file
4
test_regress/t/t_std_pkg_bad.out
Normal file
@ -0,0 +1,4 @@
|
||||
%Error: t/t_std_pkg_bad.v:7:9: Redeclaring the 'std' package is not allowed
|
||||
7 | package std;
|
||||
| ^~~
|
||||
%Error: Exiting due to
|
@ -2,18 +2,17 @@
|
||||
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
|
||||
# Copyright 2022 by Antmicro Ltd. 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_mailbox.v");
|
||||
scenarios(linter => 1);
|
||||
|
||||
lint(
|
||||
verilator_flags2 => ["--debug-exit-uvm"],
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
11
test_regress/t/t_std_pkg_bad.v
Normal file
11
test_regress/t/t_std_pkg_bad.v
Normal file
@ -0,0 +1,11 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2022 by Antmicro Ltd.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
package std;
|
||||
endpackage
|
||||
|
||||
module t;
|
||||
endmodule
|
@ -31,4 +31,20 @@
|
||||
: ... In instance t
|
||||
27 | initial #2 $stop;
|
||||
| ^
|
||||
%Error-NEEDTIMINGOPT: t/t_notiming.v:33:10: Use --timing or --no-timing to specify how mailbox::put() should be handled
|
||||
: ... In instance t
|
||||
33 | m.put(i);
|
||||
| ^~~
|
||||
%Error-NEEDTIMINGOPT: t/t_notiming.v:34:10: Use --timing or --no-timing to specify how mailbox::get() should be handled
|
||||
: ... In instance t
|
||||
34 | m.get(i);
|
||||
| ^~~
|
||||
%Error-NEEDTIMINGOPT: t/t_notiming.v:35:10: Use --timing or --no-timing to specify how mailbox::peek() should be handled
|
||||
: ... In instance t
|
||||
35 | m.peek(i);
|
||||
| ^~~~
|
||||
%Error-NEEDTIMINGOPT: t/t_notiming.v:36:10: Use --timing or --no-timing to specify how semaphore::get() should be handled
|
||||
: ... In instance t
|
||||
36 | s.get();
|
||||
| ^~~
|
||||
%Error: Exiting due to
|
||||
|
Loading…
Reference in New Issue
Block a user