Merge from master

This commit is contained in:
Wilson Snyder 2018-05-13 19:39:30 -04:00
commit 9ba6fc9279
12 changed files with 96 additions and 107 deletions

View File

@ -16,6 +16,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Fix parsing "output signed" in V2K port list, msg2540. [James Jung]
**** Fix parsing error on bad missing #, bug1308. [Dan Kirkham]
* Verilator 3.922 2018-03-17

View File

@ -17,6 +17,7 @@
/obj_dbg/
/obj_opt/
/obj_vlt/
/obj_vltmt/
/obj_dist/
/INCA_libs/
/cov_work/

View File

@ -228,8 +228,8 @@ Verilator - Convert Verilog code to C++/SystemC
=head1 DESCRIPTION
Verilator converts synthesizable (not behavioral) Verilog code, plus some
Synthesis, SystemVerilog and a small subset of Verilog AMS assertions, into
Verilator converts synthesizable (generally not behavioral) Verilog code,
plus some Synthesis, SystemVerilog and a small subset of Verilog AMS into
C++ or SystemC code. It is not a complete simulator, but a compiler.
Verilator is invoked with parameters similar to GCC, Cadence

View File

@ -202,7 +202,7 @@ IData VL_RAND32() VL_MT_SAFE {
t_seeded = true;
long seedval;
{
VerilatedLockGuard guard(s_mutex);
VerilatedLockGuard lock(s_mutex);
seedval = lrand48()<<16 ^ lrand48();
if (!seedval) seedval++;
}
@ -1612,7 +1612,7 @@ Verilated::ThreadLocal::~ThreadLocal() {
}
void Verilated::debug(int val) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_s.s_debug = val;
if (val) {
#ifdef VL_DEBUG
@ -1623,23 +1623,23 @@ void Verilated::debug(int val) VL_MT_SAFE {
}
}
void Verilated::randReset(int val) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_s.s_randReset = val;
}
void Verilated::calcUnusedSigs(bool flag) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_s.s_calcUnusedSigs = flag;
}
void Verilated::gotFinish(bool flag) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_s.s_gotFinish = flag;
}
void Verilated::assertOn(bool flag) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_s.s_assertOn = flag;
}
void Verilated::fatalOnVpiError(bool flag) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_s.s_fatalOnVpiError = flag;
}
@ -1661,7 +1661,7 @@ const char* Verilated::catName(const char* n1, const char* n2) VL_MT_SAFE {
}
void Verilated::flushCb(VerilatedVoidCb cb) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
if (s_flushCb == cb) {} // Ok - don't duplicate
else if (!s_flushCb) { s_flushCb=cb; }
else {
@ -1671,14 +1671,14 @@ void Verilated::flushCb(VerilatedVoidCb cb) VL_MT_SAFE {
}
void Verilated::flushCall() VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
if (s_flushCb) (*s_flushCb)();
fflush(stderr);
fflush(stdout);
}
void Verilated::commandArgs(int argc, const char** argv) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_args.argc = argc;
s_args.argv = argv;
VerilatedImp::commandArgs(argc,argv);
@ -1716,16 +1716,6 @@ void Verilated::scopesDump() VL_MT_SAFE {
VerilatedImp::scopesDump();
}
void Verilated::numThreads(unsigned threads) VL_MT_SAFE {
VerilatedImp::numThreads(threads);
}
unsigned Verilated::numThreads() VL_MT_SAFE {
return VerilatedImp::numThreads();
}
void Verilated::spawnThreads() VL_MT_SAFE {
VerilatedImp::spawnThreads();
}
const VerilatedScope* Verilated::scopeFind(const char* namep) VL_MT_SAFE {
return VerilatedImp::scopeFind(namep);
}
@ -1948,7 +1938,7 @@ void VerilatedScope::scopeDump() const {
//===========================================================================
// VerilatedOneThreaded:: Methods
#ifdef VL_THREADED
#if defined(VL_THREADED) && defined(VL_DEBUG)
void VerilatedAssertOneThread::fatal_different() VL_MT_SAFE {
VL_FATAL_MT(__FILE__, __LINE__, "", "Routine called that is single threaded, but called from"
" a different thread then the expected constructing thread");

View File

@ -437,17 +437,6 @@ public:
/// releases - contact the authors before production use.
static void scopesDump() VL_MT_SAFE;
/// Set the number of threads to execute on.
/// 0x0 = use all available CPU threads, or 1 if no support compiled in
/// Ignored after spawnThreads() has been called
static void numThreads(unsigned threads) VL_MT_SAFE;
static unsigned numThreads() VL_MT_SAFE;
/// Spawn child threads, using numThreads() as # of threads
/// Verilator calls this automatically on the first eval() call
/// User code may call it earlier if desired
/// Once called the first time, later calls are ignored
static void spawnThreads() VL_MT_SAFE;
public:
// METHODS - INTERNAL USE ONLY (but public due to what uses it)
// Internal: Create a new module name by concatenating two strings

View File

@ -233,12 +233,12 @@ public:
// PUBLIC METHODS
void clear() VL_EXCLUDES(m_mutex) {
Verilated::quiesce();
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
clearGuts();
}
void clearNonMatch(const char* matchp) VL_EXCLUDES(m_mutex) {
Verilated::quiesce();
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
if (matchp && matchp[0]) {
ItemList newlist;
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
@ -254,7 +254,7 @@ public:
}
void zero() VL_EXCLUDES(m_mutex) {
Verilated::quiesce();
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
(*it)->zero();
}
@ -262,18 +262,18 @@ public:
// We assume there's always call to i/f/p in that order
void inserti (VerilatedCovImpItem* itemp) VL_EXCLUDES(m_mutex) {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
assert(!m_insertp);
m_insertp = itemp;
}
void insertf (const char* filenamep, int lineno) VL_EXCLUDES(m_mutex) {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
m_insertFilenamep = filenamep;
m_insertLineno = lineno;
}
void insertp (const char* ckeyps[MAX_KEYS],
const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
assert(m_insertp);
// First two key/vals are filename
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
@ -328,7 +328,7 @@ public:
void write(const char* filename) VL_EXCLUDES(m_mutex) {
Verilated::quiesce();
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
#ifndef VM_COVERAGE
VL_FATAL_MT("",0,"","%Error: Called VerilatedCov::write when VM_COVERAGE disabled\n");
#endif

View File

@ -94,7 +94,7 @@ public:
// METHODS
//// Add message to queue (called by producer)
void post(const VerilatedMsg& msg) VL_EXCLUDES(m_mutex) {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
m_queue.insert(msg); // Pass by value to copy the message into queue
++m_depth;
}
@ -199,15 +199,10 @@ class VerilatedImp {
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); ///< File descriptors
std::deque<IData> m_fdFree VL_GUARDED_BY(m_fdMutex); ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
// Threads
VerilatedMutex m_threadMutex; ///< Protect m_numThreads, etc
bool m_spawned VL_GUARDED_BY(m_threadMutex); ///< Already called spawnThreads()
unsigned m_numThreads VL_GUARDED_BY(m_threadMutex); ///< Number of threads user requested, 0x0=all cpus
public: // But only for verilated*.cpp
// CONSTRUCTORS
VerilatedImp()
: m_argVecLoaded(false), m_exportNext(0), m_spawned(false), m_numThreads(0) {
: m_argVecLoaded(false), m_exportNext(0) {
m_fdps.resize(3);
m_fdps[0] = stdin;
m_fdps[1] = stdout;
@ -218,7 +213,7 @@ private:
VL_UNCOPYABLE(VerilatedImp);
public:
static void internalsDump() VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_argMutex);
VerilatedLockGuard lock(s_s.m_argMutex);
VL_PRINTF_MT("internalsDump:\n");
VL_PRINTF_MT(" Argv:");
for (ArgVec::const_iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
@ -234,16 +229,16 @@ public:
// METHODS - arguments
public:
static void commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
VerilatedLockGuard guard(s_s.m_argMutex);
VerilatedLockGuard lock(s_s.m_argMutex);
s_s.m_argVec.clear(); // Always clear
commandArgsAddGuts(argc, argv);
}
static void commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
VerilatedLockGuard guard(s_s.m_argMutex);
VerilatedLockGuard lock(s_s.m_argMutex);
commandArgsAddGuts(argc, argv);
}
static std::string argPlusMatch(const char* prefixp) VL_EXCLUDES(s_s.m_argMutex) {
VerilatedLockGuard guard(s_s.m_argMutex);
VerilatedLockGuard lock(s_s.m_argMutex);
// Note prefixp does not include the leading "+"
size_t len = strlen(prefixp);
if (VL_UNLIKELY(!s_s.m_argVecLoaded)) {
@ -272,14 +267,14 @@ public:
// There's often many more scopes than userdata's and thus having a ~48byte
// per map overhead * N scopes would take much more space and cache thrashing.
static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_userMapMutex);
VerilatedLockGuard lock(s_s.m_userMapMutex);
UserMap::iterator it=s_s.m_userMap.find(std::make_pair(scopep,userKey));
if (it != s_s.m_userMap.end()) it->second = userData;
// When we support VL_THREADs, we need a lock around this insert, as it's runtime
else s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep,userKey),userData));
}
static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_userMapMutex);
VerilatedLockGuard lock(s_s.m_userMapMutex);
UserMap::const_iterator it=s_s.m_userMap.find(std::make_pair(scopep,userKey));
if (VL_LIKELY(it != s_s.m_userMap.end())) return it->second;
else return NULL;
@ -288,7 +283,7 @@ private:
/// Symbol table destruction cleans up the entries for each scope.
static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE {
// Slow ok - called once/scope on destruction, so we simply iterate.
VerilatedLockGuard guard(s_s.m_userMapMutex);
VerilatedLockGuard lock(s_s.m_userMapMutex);
for (UserMap::iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ) {
if (it->first.first == scopep) {
s_s.m_userMap.erase(it++);
@ -298,7 +293,7 @@ private:
}
}
static void userDump() VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_userMapMutex); // Avoid it changing in middle of dump
VerilatedLockGuard lock(s_s.m_userMapMutex); // Avoid it changing in middle of dump
bool first = true;
for (UserMap::const_iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ++it) {
if (first) { VL_PRINTF_MT(" userDump:\n"); first=false; }
@ -311,27 +306,27 @@ public: // But only for verilated*.cpp
// METHODS - scope name
static void scopeInsert(const VerilatedScope* scopep) VL_MT_SAFE {
// Slow ok - called once/scope at construction
VerilatedLockGuard guard(s_s.m_nameMutex);
VerilatedLockGuard lock(s_s.m_nameMutex);
VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
if (it == s_s.m_nameMap.end()) {
s_s.m_nameMap.insert(it, std::make_pair(scopep->name(),scopep));
}
}
static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_nameMutex); // If too slow, can assume this is only VL_MT_SAFE_POSINIT
VerilatedLockGuard lock(s_s.m_nameMutex); // If too slow, can assume this is only VL_MT_SAFE_POSINIT
VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.find(namep);
if (VL_LIKELY(it != s_s.m_nameMap.end())) return it->second;
else return NULL;
}
static void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE {
// Slow ok - called once/scope at destruction
VerilatedLockGuard guard(s_s.m_nameMutex);
VerilatedLockGuard lock(s_s.m_nameMutex);
userEraseScope(scopep);
VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
if (it != s_s.m_nameMap.end()) s_s.m_nameMap.erase(it);
}
static void scopesDump() VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_nameMutex);
VerilatedLockGuard lock(s_s.m_nameMutex);
VL_PRINTF_MT(" scopesDump:\n");
for (VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.begin(); it!=s_s.m_nameMap.end(); ++it) {
const VerilatedScope* scopep = it->second;
@ -355,7 +350,7 @@ public: // But only for verilated*.cpp
// miss at the cost of a multiply, and all lookups move to slowpath.
static int exportInsert(const char* namep) VL_MT_SAFE {
// Slow ok - called once/function at creation
VerilatedLockGuard guard(s_s.m_exportMutex);
VerilatedLockGuard lock(s_s.m_exportMutex);
ExportNameMap::iterator it=s_s.m_exportMap.find(namep);
if (it == s_s.m_exportMap.end()) {
s_s.m_exportMap.insert(it, std::make_pair(namep, s_s.m_exportNext++));
@ -365,7 +360,7 @@ public: // But only for verilated*.cpp
}
}
static int exportFind(const char* namep) VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_exportMutex);
VerilatedLockGuard lock(s_s.m_exportMutex);
ExportNameMap::const_iterator it=s_s.m_exportMap.find(namep);
if (VL_LIKELY(it != s_s.m_exportMap.end())) return it->second;
std::string msg = (std::string("%Error: Testbench C called ")+namep
@ -375,14 +370,14 @@ public: // But only for verilated*.cpp
}
static const char* exportName(int funcnum) VL_MT_SAFE {
// Slowpath; find name for given export; errors only so no map to reverse-map it
VerilatedLockGuard guard(s_s.m_exportMutex);
VerilatedLockGuard lock(s_s.m_exportMutex);
for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) {
if (it->second == funcnum) return it->first;
}
return "*UNKNOWN*";
}
static void exportsDump() VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_exportMutex);
VerilatedLockGuard lock(s_s.m_exportMutex);
bool first = true;
for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) {
if (first) { VL_PRINTF_MT(" exportDump:\n"); first=false; }
@ -397,7 +392,7 @@ public: // But only for verilated*.cpp
static IData fdNew(FILE* fp) VL_MT_SAFE {
if (VL_UNLIKELY(!fp)) return 0;
// Bit 31 indicates it's a descriptor not a MCD
VerilatedLockGuard guard(s_s.m_fdMutex);
VerilatedLockGuard lock(s_s.m_fdMutex);
if (s_s.m_fdFree.empty()) {
// Need to create more space in m_fdps and m_fdFree
size_t start = s_s.m_fdps.size();
@ -410,7 +405,7 @@ public: // But only for verilated*.cpp
}
static void fdDelete(IData fdi) VL_MT_SAFE {
IData idx = VL_MASK_I(31) & fdi;
VerilatedLockGuard guard(s_s.m_fdMutex);
VerilatedLockGuard lock(s_s.m_fdMutex);
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return;
if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free
s_s.m_fdps[idx] = NULL;
@ -418,41 +413,10 @@ public: // But only for verilated*.cpp
}
static inline FILE* fdToFp(IData fdi) VL_MT_SAFE {
IData idx = VL_MASK_I(31) & fdi;
VerilatedLockGuard guard(s_s.m_fdMutex); // This might get slow, if it does we can cache it
VerilatedLockGuard lock(s_s.m_fdMutex); // This might get slow, if it does we can cache it
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL;
return s_s.m_fdps[idx];
}
public: // But only for verilated*.cpp
// METHODS - Threading
static void numThreads(unsigned threads) VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_threadMutex);
if (!s_s.m_spawned) s_s.m_numThreads = threads;
}
static unsigned numThreads() VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_threadMutex);
#ifdef VL_THREADED
unsigned threads = s_s.m_numThreads;
if (threads == 0x0) {
threads = std::thread::hardware_concurrency(); // Or 0=unknown, C++11
}
if (threads<1) threads = 1;
return threads;
#else
return 0;
#endif
}
static void spawnThreads() VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_threadMutex);
if (!s_s.m_spawned) {
// Convert numThreads from 0 to the spawned number
numThreads(numThreads());
s_s.m_spawned = true;
#ifdef VL_THREADED
// THREADED-TODO startup threads
#endif
}
}
};
//======================================================================

View File

@ -61,18 +61,18 @@ private:
static Singleton& singleton() { static Singleton s; return s; }
public:
static void pushVcd(VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) {
VerilatedLockGuard guard(singleton().s_vcdMutex);
VerilatedLockGuard lock(singleton().s_vcdMutex);
singleton().s_vcdVecp.push_back(vcdp);
}
static void removeVcd(const VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) {
VerilatedLockGuard guard(singleton().s_vcdMutex);
VerilatedLockGuard lock(singleton().s_vcdMutex);
VcdVec::iterator pos = find(singleton().s_vcdVecp.begin(), singleton().s_vcdVecp.end(), vcdp);
if (pos != singleton().s_vcdVecp.end()) { singleton().s_vcdVecp.erase(pos); }
}
static void flush_all() VL_EXCLUDES(singleton().s_vcdMutex) VL_MT_UNSAFE_ONE {
// Thread safety: Although this function is protected by a mutex so perhaps
// in the future we can allow tracing in separate threads, vcdp->flush() assumes call from single thread
VerilatedLockGuard guard(singleton().s_vcdMutex);
VerilatedLockGuard lock(singleton().s_vcdMutex);
for (VcdVec::const_iterator it=singleton().s_vcdVecp.begin(); it!=singleton().s_vcdVecp.end(); ++it) {
VerilatedVcd* vcdp = *it;
vcdp->flush();

View File

@ -27,7 +27,7 @@ my $header = ("\\usepackage[left=1.7in,right=1.7in,top=1.3in,bottom=1.3in]{geome
);
foreach my $line (<STDIN>) {
$line =~ s/(\\begin{document})/${header}$1/;
$line =~ s/(\\tableofcontents)/\\begin{titlepage} \\maketitle \\end{titlepage}\n$1/;
$line =~ s/(\\begin\{document\})/${header}$1/;
$line =~ s/(\\tableofcontents)/\\begin\{titlepage\} \\maketitle \\end\{titlepage\}\n$1/;
print "$line";
}

View File

@ -956,13 +956,13 @@ port<nodep>: // ==IEEE: port
{ $$=$2; /*VARDTYPE-same*/ $$->addNextNull(VARDONEP($$,$3,$4)); }
//
| portDirNetE data_type portSig variable_dimensionListE sigAttrListE '=' constExpr
{ $$=$3; VARDTYPE($2); AstVar* vp=VARDONEP($$,$4,$5); $$->addNextNull(vp); vp->valuep($7); }
{ $$=$3; VARDTYPE($2); if (AstVar* vp=VARDONEP($$,$4,$5)) { $$->addNextNull(vp); vp->valuep($7); } }
| portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE '=' constExpr
{ $$=$4; VARDTYPE($3); AstVar* vp=VARDONEP($$,$5,$6); $$->addNextNull(vp); vp->valuep($8); }
{ $$=$4; VARDTYPE($3); if (AstVar* vp=VARDONEP($$,$5,$6)) { $$->addNextNull(vp); vp->valuep($8); } }
| portDirNetE yVAR implicit_typeE portSig variable_dimensionListE sigAttrListE '=' constExpr
{ $$=$4; VARDTYPE($3); AstVar* vp=VARDONEP($$,$5,$6); $$->addNextNull(vp); vp->valuep($8); }
{ $$=$4; VARDTYPE($3); if (AstVar* vp=VARDONEP($$,$5,$6)) { $$->addNextNull(vp); vp->valuep($8); } }
| portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE '=' constExpr
{ $$=$2; /*VARDTYPE-same*/ AstVar* vp=VARDONEP($$,$3,$4); $$->addNextNull(vp); vp->valuep($6); }
{ $$=$2; /*VARDTYPE-same*/ if (AstVar* vp=VARDONEP($$,$3,$4)) { $$->addNextNull(vp); vp->valuep($6); } }
;
portDirNetE: // IEEE: part of port, optional net type and/or direction
@ -3852,6 +3852,7 @@ vltOnFront<errcodeen>:
%%
int V3ParseImp::bisonParse() {
// Use --debugi-bison 9 to enable this
if (PARSEP->debugBison()>=9) yydebug = 1;
return yyparse();
}

View File

@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2008 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.
scenarios(vlt => 1);
compile(
verilator_flags2 => ["--lint-only -Wno-DECLFILENAME"],
fails => 1,
verilator_make_gcc => 0,
make_top_shell => 0,
make_main => 0,
expect =>
q{%Error: t/t_lint_mod_paren_bad.v:\d+: syntax error, unexpected '\(', expecting ';'
%Error: Exiting due to .*},
);
ok(1);
1;

View File

@ -0,0 +1,18 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2018 by Wilson Snyder.
// Should have been:
//module t #(
module t
(
FOO=1
) (
output bar
);
assign bar = FOO;
endmodule