mirror of
https://github.com/verilator/verilator.git
synced 2025-04-05 04:02:37 +00:00
Internals: Split V3Error into V3FileLine. No functional change.
This commit is contained in:
parent
87a47a5ca0
commit
6da13c6486
@ -186,6 +186,7 @@ RAW_OBJS = \
|
|||||||
V3Error.o \
|
V3Error.o \
|
||||||
V3Expand.o \
|
V3Expand.o \
|
||||||
V3File.o \
|
V3File.o \
|
||||||
|
V3FileLine.o \
|
||||||
V3Gate.o \
|
V3Gate.o \
|
||||||
V3GenClk.o \
|
V3GenClk.o \
|
||||||
V3Graph.o \
|
V3Graph.o \
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
|
#include "V3FileLine.h"
|
||||||
#include "V3Number.h"
|
#include "V3Number.h"
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
|
#include "V3FileLine.h"
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
|
273
src/V3Error.cpp
273
src/V3Error.cpp
@ -27,7 +27,6 @@
|
|||||||
# include "V3Ast.h"
|
# include "V3Ast.h"
|
||||||
# include "V3Global.h"
|
# include "V3Global.h"
|
||||||
# include "V3Stats.h"
|
# include "V3Stats.h"
|
||||||
# include "V3Config.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
@ -36,6 +35,8 @@
|
|||||||
int V3Error::s_errCount = 0;
|
int V3Error::s_errCount = 0;
|
||||||
int V3Error::s_warnCount = 0;
|
int V3Error::s_warnCount = 0;
|
||||||
int V3Error::s_debugDefault = 0;
|
int V3Error::s_debugDefault = 0;
|
||||||
|
int V3Error::s_errorLimit = V3Error::MAX_ERRORS;
|
||||||
|
bool V3Error::s_warnFatal = true;
|
||||||
int V3Error::s_tellManual = 0;
|
int V3Error::s_tellManual = 0;
|
||||||
ostringstream V3Error::s_errorStr; // Error string being formed
|
ostringstream V3Error::s_errorStr; // Error string being formed
|
||||||
V3ErrorCode V3Error::s_errorCode = V3ErrorCode::EC_FATAL;
|
V3ErrorCode V3Error::s_errorCode = V3ErrorCode::EC_FATAL;
|
||||||
@ -65,270 +66,6 @@ V3ErrorCode::V3ErrorCode(const char* msgp) {
|
|||||||
m_e = V3ErrorCode::EC_ERROR;
|
m_e = V3ErrorCode::EC_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
//######################################################################
|
|
||||||
// FileLineSingleton class functions
|
|
||||||
|
|
||||||
const string FileLineSingleton::filenameLetters(int no) {
|
|
||||||
const int size = 1 + (64 / 4); // Each letter retires more than 4 bits of a > 64 bit number
|
|
||||||
char out[size];
|
|
||||||
char* op = out+size-1;
|
|
||||||
*--op = '\0'; // We build backwards
|
|
||||||
int num = no;
|
|
||||||
do {
|
|
||||||
*--op = 'a'+num%26;
|
|
||||||
num /= 26;
|
|
||||||
} while (num);
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Convert filenames to a filenameno
|
|
||||||
|
|
||||||
//! This lets us assign a nice small identifier for debug messages, but more
|
|
||||||
//! importantly lets us use a 4 byte int instead of 8 byte pointer in every
|
|
||||||
//! FileLine.
|
|
||||||
|
|
||||||
//! We associate a language with each source file, so we also set the default
|
|
||||||
//! for this.
|
|
||||||
int FileLineSingleton::nameToNumber(const string& filename) {
|
|
||||||
FileNameNumMap::const_iterator it = m_namemap.find(filename);
|
|
||||||
if (VL_LIKELY(it != m_namemap.end())) return it->second;
|
|
||||||
int num = m_names.size();
|
|
||||||
m_names.push_back(filename);
|
|
||||||
m_languages.push_back(V3LangCode::mostRecent());
|
|
||||||
m_namemap.insert(make_pair(filename,num));
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Support XML output
|
|
||||||
|
|
||||||
//! Experimental. Updated to also put out the language.
|
|
||||||
void FileLineSingleton::fileNameNumMapDumpXml(ostream& os) {
|
|
||||||
os<<"<files>\n";
|
|
||||||
for (FileNameNumMap::const_iterator it = m_namemap.begin(); it != m_namemap.end(); ++it) {
|
|
||||||
os<<"<file id=\""<<filenameLetters(it->second)
|
|
||||||
<<"\" filename=\""<<it->first
|
|
||||||
<<"\" language=\""<<numberToLang(it->second).ascii()<<"\"/>\n";
|
|
||||||
}
|
|
||||||
os<<"</files>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
//######################################################################
|
|
||||||
// FileLine class functions
|
|
||||||
|
|
||||||
FileLine::FileLine(FileLine::EmptySecret) {
|
|
||||||
// Sort of a singleton
|
|
||||||
m_lineno=0;
|
|
||||||
m_filenameno=singleton().nameToNumber("AstRoot");
|
|
||||||
|
|
||||||
m_warnOn=0;
|
|
||||||
for (int codei=V3ErrorCode::EC_MIN; codei<V3ErrorCode::_ENUM_MAX; codei++) {
|
|
||||||
V3ErrorCode code = (V3ErrorCode)codei;
|
|
||||||
warnOff(code, code.defaultsOff());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string FileLine::lineDirectiveStrg(int enterExit) const {
|
|
||||||
char numbuf[20]; sprintf(numbuf, "%d", lineno());
|
|
||||||
char levelbuf[20]; sprintf(levelbuf, "%d", enterExit);
|
|
||||||
return ((string)"`line "+numbuf+" \""+filename()+"\" "+levelbuf+"\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileLine::lineDirective(const char* textp, int& enterExitRef) {
|
|
||||||
// Handle `line directive
|
|
||||||
// Skip `line
|
|
||||||
while (*textp && isspace(*textp)) textp++;
|
|
||||||
while (*textp && !isspace(*textp)) textp++;
|
|
||||||
while (*textp && (isspace(*textp) || *textp=='"')) textp++;
|
|
||||||
|
|
||||||
// Grab linenumber
|
|
||||||
const char *ln = textp;
|
|
||||||
while (*textp && !isspace(*textp)) textp++;
|
|
||||||
if (isdigit(*ln)) {
|
|
||||||
this->lineno(atoi(ln));
|
|
||||||
}
|
|
||||||
while (*textp && (isspace(*textp) || *textp=='"')) textp++;
|
|
||||||
|
|
||||||
// Grab filename
|
|
||||||
const char *fn = textp;
|
|
||||||
while (*textp && !(isspace(*textp) || *textp=='"')) textp++;
|
|
||||||
if (textp != fn) {
|
|
||||||
string strfn = fn;
|
|
||||||
strfn = strfn.substr(0, textp-fn);
|
|
||||||
this->filename(strfn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Grab level
|
|
||||||
while (*textp && (isspace(*textp) || *textp=='"')) textp++;
|
|
||||||
if (isdigit(*textp)) enterExitRef = atoi(textp);
|
|
||||||
else enterExitRef = 0;
|
|
||||||
|
|
||||||
//printf ("PPLINE %d '%s'\n", s_lineno, s_filename.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
FileLine* FileLine::copyOrSameFileLine() {
|
|
||||||
// When a fileline is "used" to produce a node, calls this function.
|
|
||||||
// Return this, or a copy of this
|
|
||||||
// There are often more than one token per line, thus we use the
|
|
||||||
// same pointer as long as we're on the same line, file & warn state.
|
|
||||||
#ifndef _V3ERROR_NO_GLOBAL_
|
|
||||||
V3Config::applyIgnores(this); // Toggle warnings based on global config file
|
|
||||||
#endif
|
|
||||||
static FileLine* lastNewp = NULL;
|
|
||||||
if (lastNewp && *lastNewp == *this) { // Compares lineno, filename, etc
|
|
||||||
return lastNewp;
|
|
||||||
}
|
|
||||||
FileLine* newp = new FileLine(this);
|
|
||||||
lastNewp = newp;
|
|
||||||
return newp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileLine::updateLanguage () {
|
|
||||||
language(v3Global.opt.fileLanguage(filename()));
|
|
||||||
}
|
|
||||||
|
|
||||||
const string FileLine::filebasename() const {
|
|
||||||
string name = filename();
|
|
||||||
string::size_type pos;
|
|
||||||
if ((pos = name.rfind("/")) != string::npos) {
|
|
||||||
name.erase(0,pos+1);
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
const string FileLine::filebasenameNoExt() const {
|
|
||||||
string name = filebasename();
|
|
||||||
string::size_type pos;
|
|
||||||
if ((pos = name.find(".")) != string::npos) {
|
|
||||||
name = name.substr(0,pos);
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
const string FileLine::profileFuncname() const {
|
|
||||||
// Return string that is OK as a function name - for profiling
|
|
||||||
string name = filebasenameNoExt();
|
|
||||||
string::size_type pos;
|
|
||||||
while ((pos = name.find_first_not_of("abcdefghijlkmnopqrstuvwxyzABCDEFGHIJLKMNOPQRSTUVWXYZ0123456789_"))
|
|
||||||
!= string::npos) {
|
|
||||||
name.replace(pos, 1, "_");
|
|
||||||
}
|
|
||||||
name += "__l"+cvtToStr(lineno());
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
string FileLine::ascii() const {
|
|
||||||
return filename()+":"+cvtToStr(lineno());
|
|
||||||
}
|
|
||||||
ostream& operator<<(ostream& os, FileLine* fileline) {
|
|
||||||
os <<fileline->ascii()<<": "<<hex;
|
|
||||||
return(os);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileLine::warnOff(const string& msg, bool flag) {
|
|
||||||
V3ErrorCode code (msg.c_str());
|
|
||||||
if (code < V3ErrorCode::EC_FIRST_WARN) {
|
|
||||||
return false;
|
|
||||||
} else if (v3Global.opt.lintOnly() // Lint mode is allowed to suppress some errors
|
|
||||||
&& code < V3ErrorCode::EC_MIN) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
warnOff(code, flag);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileLine::warnLintOff(bool flag) {
|
|
||||||
for (int codei=V3ErrorCode::EC_MIN; codei<V3ErrorCode::_ENUM_MAX; codei++) {
|
|
||||||
V3ErrorCode code = (V3ErrorCode)codei;
|
|
||||||
if (code.lintError()) warnOff(code, flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileLine::warnStyleOff(bool flag) {
|
|
||||||
for (int codei=V3ErrorCode::EC_MIN; codei<V3ErrorCode::_ENUM_MAX; codei++) {
|
|
||||||
V3ErrorCode code = (V3ErrorCode)codei;
|
|
||||||
if (code.styleError()) warnOff(code, flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileLine::warnIsOff(V3ErrorCode code) const {
|
|
||||||
if (!m_warnOn.test(code)) return true;
|
|
||||||
if (!defaultFileLine().m_warnOn.test(code)) return true; // Global overrides local
|
|
||||||
// UNOPTFLAT implies UNOPT
|
|
||||||
if (code==V3ErrorCode::UNOPT && !m_warnOn.test(V3ErrorCode::UNOPTFLAT)) return true;
|
|
||||||
if ((code.lintError() || code.styleError()) && !m_warnOn.test(V3ErrorCode::I_LINT)) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileLine::modifyStateInherit(const FileLine* fromp) {
|
|
||||||
// Any warnings that are off in "from", become off in "this".
|
|
||||||
for (int codei=V3ErrorCode::EC_MIN; codei<V3ErrorCode::_ENUM_MAX; codei++) {
|
|
||||||
V3ErrorCode code = (V3ErrorCode)codei;
|
|
||||||
if (fromp->warnIsOff(code)) {
|
|
||||||
this->warnOff(code, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileLine::v3errorEnd(ostringstream& str) {
|
|
||||||
if (this && m_lineno) {
|
|
||||||
ostringstream nsstr;
|
|
||||||
nsstr<<this<<str.str();
|
|
||||||
if (warnIsOff(V3Error::errorCode())) V3Error::suppressThisWarning();
|
|
||||||
V3Error::v3errorEnd(nsstr);
|
|
||||||
} else {
|
|
||||||
V3Error::v3errorEnd(str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string FileLine::warnMore() const {
|
|
||||||
if (this && m_lineno) {
|
|
||||||
return V3Error::warnMore()+ascii()+": ";
|
|
||||||
} else {
|
|
||||||
return V3Error::warnMore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef VL_LEAK_CHECKS
|
|
||||||
typedef set<FileLine*> FileLineCheckSet;
|
|
||||||
FileLineCheckSet fileLineLeakChecks;
|
|
||||||
|
|
||||||
void* FileLine::operator new(size_t size) {
|
|
||||||
FileLine* objp = static_cast<FileLine*>(::operator new(size));
|
|
||||||
fileLineLeakChecks.insert(objp);
|
|
||||||
return objp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileLine::operator delete(void* objp, size_t size) {
|
|
||||||
if (!objp) return;
|
|
||||||
FileLine* flp = static_cast<FileLine*>(objp);
|
|
||||||
FileLineCheckSet::iterator it = fileLineLeakChecks.find(flp);
|
|
||||||
if (it != fileLineLeakChecks.end()) {
|
|
||||||
fileLineLeakChecks.erase(it);
|
|
||||||
} else {
|
|
||||||
flp->v3fatalSrc("Deleting FileLine object that was never tracked\n");
|
|
||||||
}
|
|
||||||
::operator delete(objp);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void FileLine::deleteAllRemaining() {
|
|
||||||
#ifdef VL_LEAK_CHECKS
|
|
||||||
// FileLines are allocated, but never nicely freed, as it's much faster
|
|
||||||
// that way. Unfortunately this makes our leak checking a big mess, so
|
|
||||||
// only when leak checking we'll track them all and cleanup.
|
|
||||||
while (1) {
|
|
||||||
FileLineCheckSet::iterator it=fileLineLeakChecks.begin();
|
|
||||||
if (it==fileLineLeakChecks.end()) break;
|
|
||||||
delete *it;
|
|
||||||
// Operator delete will remove the iterated object from the list.
|
|
||||||
// Eventually the list will be empty and terminate the loop.
|
|
||||||
}
|
|
||||||
fileLineLeakChecks.clear();
|
|
||||||
singleton().clear();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// V3Error class functions
|
// V3Error class functions
|
||||||
|
|
||||||
@ -356,13 +93,13 @@ string V3Error::lineStr (const char* filename, int lineno) {
|
|||||||
|
|
||||||
void V3Error::incErrors() {
|
void V3Error::incErrors() {
|
||||||
s_errCount++;
|
s_errCount++;
|
||||||
if (errorCount() == v3Global.opt.errorLimit()) { // Not >= as would otherwise recurse
|
if (errorCount() == errorLimit()) { // Not >= as would otherwise recurse
|
||||||
v3fatal ("Exiting due to too many errors encountered; --error-limit="<<errorCount()<<endl);
|
v3fatal ("Exiting due to too many errors encountered; --error-limit="<<errorCount()<<endl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Error::abortIfWarnings() {
|
void V3Error::abortIfWarnings() {
|
||||||
bool exwarn = v3Global.opt.warnFatal() && warnCount();
|
bool exwarn = warnFatal() && warnCount();
|
||||||
if (errorCount() && exwarn) {
|
if (errorCount() && exwarn) {
|
||||||
v3fatal ("Exiting due to "<<dec<<errorCount()<<" error(s), "<<warnCount()<<" warning(s)\n");
|
v3fatal ("Exiting due to "<<dec<<errorCount()<<" error(s), "<<warnCount()<<" warning(s)\n");
|
||||||
} else if (errorCount()) {
|
} else if (errorCount()) {
|
||||||
@ -412,7 +149,9 @@ void V3Error::vlAbort () {
|
|||||||
|
|
||||||
void V3Error::suppressThisWarning() {
|
void V3Error::suppressThisWarning() {
|
||||||
if (s_errorCode>=V3ErrorCode::EC_MIN) {
|
if (s_errorCode>=V3ErrorCode::EC_MIN) {
|
||||||
|
#ifndef _V3ERROR_NO_GLOBAL_
|
||||||
V3Stats::addStatSum(string("Warnings, Suppressed ")+s_errorCode.ascii(), 1);
|
V3Stats::addStatSum(string("Warnings, Suppressed ")+s_errorCode.ascii(), 1);
|
||||||
|
#endif
|
||||||
s_errorSuppressed = true;
|
s_errorSuppressed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
150
src/V3Error.h
150
src/V3Error.h
@ -30,8 +30,6 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
#include "V3LangCode.h"
|
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
class V3ErrorCode {
|
class V3ErrorCode {
|
||||||
@ -191,9 +189,11 @@ class V3Error {
|
|||||||
static bool s_describedWarnings; // Told user how to disable warns
|
static bool s_describedWarnings; // Told user how to disable warns
|
||||||
static bool s_describedEachWarn[V3ErrorCode::_ENUM_MAX]; // Told user specifics about this warning
|
static bool s_describedEachWarn[V3ErrorCode::_ENUM_MAX]; // Told user specifics about this warning
|
||||||
static bool s_pretendError[V3ErrorCode::_ENUM_MAX]; // Pretend this warning is an error
|
static bool s_pretendError[V3ErrorCode::_ENUM_MAX]; // Pretend this warning is an error
|
||||||
static int s_debugDefault; // Default debugging level
|
static int s_debugDefault; // Option: --debugi Default debugging level
|
||||||
|
static int s_errorLimit; // Option: --error-limit Number of errors before exit
|
||||||
|
static bool s_warnFatal; // Option: --warnFatal Warnings are fatal
|
||||||
static int s_errCount; // Error count
|
static int s_errCount; // Error count
|
||||||
static int s_warnCount; // Error count
|
static int s_warnCount; // Warning count
|
||||||
static int s_tellManual; // Tell user to see manual, 0=not yet, 1=doit, 2=disable
|
static int s_tellManual; // Tell user to see manual, 0=not yet, 1=doit, 2=disable
|
||||||
static ostringstream s_errorStr; // Error string being formed
|
static ostringstream s_errorStr; // Error string being formed
|
||||||
static V3ErrorCode s_errorCode; // Error string being formed will abort
|
static V3ErrorCode s_errorCode; // Error string being formed will abort
|
||||||
@ -210,6 +210,10 @@ class V3Error {
|
|||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
static void debugDefault(int level) { s_debugDefault = level; }
|
static void debugDefault(int level) { s_debugDefault = level; }
|
||||||
static int debugDefault() { return s_debugDefault; }
|
static int debugDefault() { return s_debugDefault; }
|
||||||
|
static void errorLimit(int level) { s_errorLimit = level; }
|
||||||
|
static int errorLimit() { return s_errorLimit; }
|
||||||
|
static void warnFatal(bool flag) { s_warnFatal = flag; }
|
||||||
|
static bool warnFatal() { return s_warnFatal; }
|
||||||
static string msgPrefix(); // returns %Error/%Warn
|
static string msgPrefix(); // returns %Error/%Warn
|
||||||
static int errorCount() { return s_errCount; }
|
static int errorCount() { return s_errCount; }
|
||||||
static int warnCount() { return s_warnCount; }
|
static int warnCount() { return s_warnCount; }
|
||||||
@ -243,7 +247,7 @@ class V3Error {
|
|||||||
inline int debug() { return V3Error::debugDefault(); }
|
inline int debug() { return V3Error::debugDefault(); }
|
||||||
inline void v3errorEnd(ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
|
inline void v3errorEnd(ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
|
||||||
|
|
||||||
// These allow errors using << operators: v3error("foo"<<"bar");
|
// Theses allow errors using << operators: v3error("foo"<<"bar");
|
||||||
// Careful, you can't put () around msg, as you would in most macro definitions
|
// Careful, you can't put () around msg, as you would in most macro definitions
|
||||||
// Note the commas are the comma operator, not separating arguments. These are needed to insure
|
// Note the commas are the comma operator, not separating arguments. These are needed to insure
|
||||||
// evaluation order as otherwise we couldn't insure v3errorPrep is called first.
|
// evaluation order as otherwise we couldn't insure v3errorPrep is called first.
|
||||||
@ -285,140 +289,4 @@ inline string ucfirst(const string& text) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
//######################################################################
|
|
||||||
|
|
||||||
class FileLine;
|
|
||||||
|
|
||||||
//! Singleton class with tables of per-file data.
|
|
||||||
|
|
||||||
//! This singleton class contains tables of data that are unchanging in each
|
|
||||||
//! source file (each with its own unique filename number).
|
|
||||||
class FileLineSingleton {
|
|
||||||
// TYPES
|
|
||||||
typedef map<string,int> FileNameNumMap;
|
|
||||||
typedef map<string,V3LangCode> FileLangNumMap;
|
|
||||||
// MEMBERS
|
|
||||||
FileNameNumMap m_namemap; // filenameno for each filename
|
|
||||||
deque<string> m_names; // filename text for each filenameno
|
|
||||||
deque<V3LangCode> m_languages; // language for each filenameno
|
|
||||||
// COSNTRUCTORS
|
|
||||||
FileLineSingleton() { }
|
|
||||||
~FileLineSingleton() { }
|
|
||||||
protected:
|
|
||||||
friend class FileLine;
|
|
||||||
// METHODS
|
|
||||||
int nameToNumber(const string& filename);
|
|
||||||
const string numberToName(int filenameno) const { return m_names[filenameno]; }
|
|
||||||
const V3LangCode numberToLang(int filenameno) const { return m_languages[filenameno]; }
|
|
||||||
void numberToLang(int filenameno, const V3LangCode& l) { m_languages[filenameno] = l; }
|
|
||||||
void clear() { m_namemap.clear(); m_names.clear(); m_languages.clear(); }
|
|
||||||
void fileNameNumMapDumpXml(ostream& os);
|
|
||||||
static const string filenameLetters(int fileno);
|
|
||||||
};
|
|
||||||
|
|
||||||
//! File and line number of an object, mostly for error reporting
|
|
||||||
|
|
||||||
//! This class is instantiated for every source code line (potentially
|
|
||||||
//! millions). To save space, per-file information (e.g. filename, source
|
|
||||||
//! language is held in tables in the FileLineSingleton class.
|
|
||||||
class FileLine {
|
|
||||||
int m_lineno;
|
|
||||||
int m_filenameno;
|
|
||||||
bitset<V3ErrorCode::_ENUM_MAX> m_warnOn;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct EmptySecret {};
|
|
||||||
inline static FileLineSingleton& singleton() {
|
|
||||||
static FileLineSingleton s;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
inline static FileLine& defaultFileLine() {
|
|
||||||
static FileLine* defFilelinep = new FileLine(FileLine::EmptySecret());
|
|
||||||
return *defFilelinep;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
// User routines should never need to change line numbers
|
|
||||||
// We are storing pointers, so we CAN'T change them after initial reading.
|
|
||||||
friend class FileLineSingleton;
|
|
||||||
friend class V3ParseImp;
|
|
||||||
friend class V3PreLex;
|
|
||||||
friend class V3PreProcImp;
|
|
||||||
void lineno(int num) { m_lineno = num; }
|
|
||||||
void language (V3LangCode lang) { singleton().numberToLang(m_filenameno, lang); }
|
|
||||||
void filename(const string& name) { m_filenameno = singleton().nameToNumber(name); }
|
|
||||||
void lineDirective(const char* textp, int& enterExitRef);
|
|
||||||
void linenoInc() { m_lineno++; }
|
|
||||||
void linenoIncInPlace() { m_lineno++; }
|
|
||||||
FileLine* copyOrSameFileLine();
|
|
||||||
public:
|
|
||||||
FileLine (const string& filename, int lineno) {
|
|
||||||
m_lineno=lineno; m_filenameno = singleton().nameToNumber(filename);
|
|
||||||
m_warnOn=defaultFileLine().m_warnOn; }
|
|
||||||
FileLine (FileLine* fromp) {
|
|
||||||
m_lineno=fromp->m_lineno; m_filenameno = fromp->m_filenameno; m_warnOn=fromp->m_warnOn; }
|
|
||||||
FileLine (EmptySecret);
|
|
||||||
~FileLine() { }
|
|
||||||
FileLine* create(const string& filename, int lineno) { return new FileLine(filename,lineno); }
|
|
||||||
FileLine* create(int lineno) { return create(filename(), lineno); }
|
|
||||||
static void deleteAllRemaining();
|
|
||||||
#ifdef VL_LEAK_CHECKS
|
|
||||||
static void* operator new(size_t size);
|
|
||||||
static void operator delete(void* obj, size_t size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int lineno () const { return m_lineno; }
|
|
||||||
V3LangCode language () const { return singleton().numberToLang(m_filenameno); }
|
|
||||||
void updateLanguage ();
|
|
||||||
string ascii() const;
|
|
||||||
const string filename () const { return singleton().numberToName(m_filenameno); }
|
|
||||||
const string filenameLetters() const { return singleton().filenameLetters(m_filenameno); }
|
|
||||||
const string filebasename () const;
|
|
||||||
const string filebasenameNoExt () const;
|
|
||||||
const string profileFuncname() const;
|
|
||||||
const string xml() const { return "fl=\""+filenameLetters()+cvtToStr(lineno())+"\""; }
|
|
||||||
string lineDirectiveStrg(int enter_exit_level) const;
|
|
||||||
void warnOn(V3ErrorCode code, bool flag) { m_warnOn.set(code,flag); } // Turn on/off warning messages on this line.
|
|
||||||
void warnOff(V3ErrorCode code, bool flag) { warnOn(code,!flag); }
|
|
||||||
bool warnOff(const string& code, bool flag); // Returns 1 if ok
|
|
||||||
bool warnIsOff(V3ErrorCode code) const;
|
|
||||||
void warnLintOff(bool flag);
|
|
||||||
void warnStyleOff(bool flag);
|
|
||||||
void warnStateFrom(const FileLine& from) { m_warnOn=from.m_warnOn; }
|
|
||||||
void warnResetDefault() { warnStateFrom(defaultFileLine()); }
|
|
||||||
|
|
||||||
// Specific flag ACCESSORS/METHODS
|
|
||||||
bool coverageOn() const { return m_warnOn.test(V3ErrorCode::I_COVERAGE); }
|
|
||||||
void coverageOn(bool flag) { warnOn(V3ErrorCode::I_COVERAGE,flag); }
|
|
||||||
bool tracingOn() const { return m_warnOn.test(V3ErrorCode::I_TRACING); }
|
|
||||||
void tracingOn(bool flag) { warnOn(V3ErrorCode::I_TRACING,flag); }
|
|
||||||
|
|
||||||
// METHODS - Global
|
|
||||||
static void globalWarnLintOff(bool flag) {
|
|
||||||
defaultFileLine().warnLintOff(flag); }
|
|
||||||
static void globalWarnStyleOff(bool flag) {
|
|
||||||
defaultFileLine().warnStyleOff(flag); }
|
|
||||||
static void globalWarnOff(V3ErrorCode code, bool flag) {
|
|
||||||
defaultFileLine().warnOff(code, flag); }
|
|
||||||
static bool globalWarnOff(const string& code, bool flag) {
|
|
||||||
return defaultFileLine().warnOff(code, flag); }
|
|
||||||
static void fileNameNumMapDumpXml(ostream& os) {
|
|
||||||
singleton().fileNameNumMapDumpXml(os); }
|
|
||||||
|
|
||||||
// METHODS - Called from netlist
|
|
||||||
// Merge warning disables from another fileline
|
|
||||||
void modifyStateInherit(const FileLine* fromp);
|
|
||||||
// Change the current fileline due to actions discovered after parsing
|
|
||||||
// and may have side effects on other nodes sharing this FileLine.
|
|
||||||
// Use only when this is intended
|
|
||||||
void modifyWarnOff(V3ErrorCode code, bool flag) { warnOff(code,flag); }
|
|
||||||
|
|
||||||
// OPERATORS
|
|
||||||
void v3errorEnd(ostringstream& str);
|
|
||||||
string warnMore() const;
|
|
||||||
inline bool operator==(FileLine rhs) const {
|
|
||||||
return (m_lineno==rhs.m_lineno && m_filenameno==rhs.m_filenameno && m_warnOn==rhs.m_warnOn);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ostream& operator<<(ostream& os, FileLine* fileline);
|
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
|
#include "V3FileLine.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
294
src/V3FileLine.cpp
Normal file
294
src/V3FileLine.cpp
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Error handling
|
||||||
|
//
|
||||||
|
// Code available from: http://www.veripool.org/verilator
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2014 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.
|
||||||
|
//
|
||||||
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <cstring>
|
||||||
|
#include <set>
|
||||||
|
#include "V3Error.h"
|
||||||
|
#include "V3FileLine.h"
|
||||||
|
#ifndef _V3ERROR_NO_GLOBAL_
|
||||||
|
# include "V3Ast.h"
|
||||||
|
# include "V3Global.h"
|
||||||
|
# include "V3Stats.h"
|
||||||
|
# include "V3Config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// FileLineSingleton class functions
|
||||||
|
|
||||||
|
const string FileLineSingleton::filenameLetters(int no) {
|
||||||
|
const int size = 1 + (64 / 4); // Each letter retires more than 4 bits of a > 64 bit number
|
||||||
|
char out[size];
|
||||||
|
char* op = out+size-1;
|
||||||
|
*--op = '\0'; // We build backwards
|
||||||
|
int num = no;
|
||||||
|
do {
|
||||||
|
*--op = 'a'+num%26;
|
||||||
|
num /= 26;
|
||||||
|
} while (num);
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Convert filenames to a filenameno
|
||||||
|
|
||||||
|
//! This lets us assign a nice small identifier for debug messages, but more
|
||||||
|
//! importantly lets us use a 4 byte int instead of 8 byte pointer in every
|
||||||
|
//! FileLine.
|
||||||
|
|
||||||
|
//! We associate a language with each source file, so we also set the default
|
||||||
|
//! for this.
|
||||||
|
int FileLineSingleton::nameToNumber(const string& filename) {
|
||||||
|
FileNameNumMap::const_iterator it = m_namemap.find(filename);
|
||||||
|
if (VL_LIKELY(it != m_namemap.end())) return it->second;
|
||||||
|
int num = m_names.size();
|
||||||
|
m_names.push_back(filename);
|
||||||
|
m_languages.push_back(V3LangCode::mostRecent());
|
||||||
|
m_namemap.insert(make_pair(filename,num));
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Support XML output
|
||||||
|
|
||||||
|
//! Experimental. Updated to also put out the language.
|
||||||
|
void FileLineSingleton::fileNameNumMapDumpXml(ostream& os) {
|
||||||
|
os<<"<files>\n";
|
||||||
|
for (FileNameNumMap::const_iterator it = m_namemap.begin(); it != m_namemap.end(); ++it) {
|
||||||
|
os<<"<file id=\""<<filenameLetters(it->second)
|
||||||
|
<<"\" filename=\""<<it->first
|
||||||
|
<<"\" language=\""<<numberToLang(it->second).ascii()<<"\"/>\n";
|
||||||
|
}
|
||||||
|
os<<"</files>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// FileLine class functions
|
||||||
|
|
||||||
|
FileLine::FileLine(FileLine::EmptySecret) {
|
||||||
|
// Sort of a singleton
|
||||||
|
m_lineno=0;
|
||||||
|
m_filenameno=singleton().nameToNumber("AstRoot");
|
||||||
|
|
||||||
|
m_warnOn=0;
|
||||||
|
for (int codei=V3ErrorCode::EC_MIN; codei<V3ErrorCode::_ENUM_MAX; codei++) {
|
||||||
|
V3ErrorCode code = (V3ErrorCode)codei;
|
||||||
|
warnOff(code, code.defaultsOff());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string FileLine::lineDirectiveStrg(int enterExit) const {
|
||||||
|
char numbuf[20]; sprintf(numbuf, "%d", lineno());
|
||||||
|
char levelbuf[20]; sprintf(levelbuf, "%d", enterExit);
|
||||||
|
return ((string)"`line "+numbuf+" \""+filename()+"\" "+levelbuf+"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLine::lineDirective(const char* textp, int& enterExitRef) {
|
||||||
|
// Handle `line directive
|
||||||
|
// Skip `line
|
||||||
|
while (*textp && isspace(*textp)) textp++;
|
||||||
|
while (*textp && !isspace(*textp)) textp++;
|
||||||
|
while (*textp && (isspace(*textp) || *textp=='"')) textp++;
|
||||||
|
|
||||||
|
// Grab linenumber
|
||||||
|
const char *ln = textp;
|
||||||
|
while (*textp && !isspace(*textp)) textp++;
|
||||||
|
if (isdigit(*ln)) {
|
||||||
|
this->lineno(atoi(ln));
|
||||||
|
}
|
||||||
|
while (*textp && (isspace(*textp) || *textp=='"')) textp++;
|
||||||
|
|
||||||
|
// Grab filename
|
||||||
|
const char *fn = textp;
|
||||||
|
while (*textp && !(isspace(*textp) || *textp=='"')) textp++;
|
||||||
|
if (textp != fn) {
|
||||||
|
string strfn = fn;
|
||||||
|
strfn = strfn.substr(0, textp-fn);
|
||||||
|
this->filename(strfn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab level
|
||||||
|
while (*textp && (isspace(*textp) || *textp=='"')) textp++;
|
||||||
|
if (isdigit(*textp)) enterExitRef = atoi(textp);
|
||||||
|
else enterExitRef = 0;
|
||||||
|
|
||||||
|
//printf ("PPLINE %d '%s'\n", s_lineno, s_filename.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
FileLine* FileLine::copyOrSameFileLine() {
|
||||||
|
// When a fileline is "used" to produce a node, calls this function.
|
||||||
|
// Return this, or a copy of this
|
||||||
|
// There are often more than one token per line, thus we use the
|
||||||
|
// same pointer as long as we're on the same line, file & warn state.
|
||||||
|
#ifndef _V3ERROR_NO_GLOBAL_
|
||||||
|
V3Config::applyIgnores(this); // Toggle warnings based on global config file
|
||||||
|
#endif
|
||||||
|
static FileLine* lastNewp = NULL;
|
||||||
|
if (lastNewp && *lastNewp == *this) { // Compares lineno, filename, etc
|
||||||
|
return lastNewp;
|
||||||
|
}
|
||||||
|
FileLine* newp = new FileLine(this);
|
||||||
|
lastNewp = newp;
|
||||||
|
return newp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string FileLine::filebasename() const {
|
||||||
|
string name = filename();
|
||||||
|
string::size_type pos;
|
||||||
|
if ((pos = name.rfind("/")) != string::npos) {
|
||||||
|
name.erase(0,pos+1);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string FileLine::filebasenameNoExt() const {
|
||||||
|
string name = filebasename();
|
||||||
|
string::size_type pos;
|
||||||
|
if ((pos = name.find(".")) != string::npos) {
|
||||||
|
name = name.substr(0,pos);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string FileLine::profileFuncname() const {
|
||||||
|
// Return string that is OK as a function name - for profiling
|
||||||
|
string name = filebasenameNoExt();
|
||||||
|
string::size_type pos;
|
||||||
|
while ((pos = name.find_first_not_of("abcdefghijlkmnopqrstuvwxyzABCDEFGHIJLKMNOPQRSTUVWXYZ0123456789_"))
|
||||||
|
!= string::npos) {
|
||||||
|
name.replace(pos, 1, "_");
|
||||||
|
}
|
||||||
|
name += "__l"+cvtToStr(lineno());
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
string FileLine::ascii() const {
|
||||||
|
return filename()+":"+cvtToStr(lineno());
|
||||||
|
}
|
||||||
|
ostream& operator<<(ostream& os, FileLine* fileline) {
|
||||||
|
os <<fileline->ascii()<<": "<<hex;
|
||||||
|
return(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileLine::warnOff(const string& msg, bool flag) {
|
||||||
|
V3ErrorCode code (msg.c_str());
|
||||||
|
if (code < V3ErrorCode::EC_FIRST_WARN) {
|
||||||
|
return false;
|
||||||
|
#ifndef _V3ERROR_NO_GLOBAL_
|
||||||
|
} else if (v3Global.opt.lintOnly() // Lint mode is allowed to suppress some errors
|
||||||
|
&& code < V3ErrorCode::EC_MIN) {
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
warnOff(code, flag);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLine::warnLintOff(bool flag) {
|
||||||
|
for (int codei=V3ErrorCode::EC_MIN; codei<V3ErrorCode::_ENUM_MAX; codei++) {
|
||||||
|
V3ErrorCode code = (V3ErrorCode)codei;
|
||||||
|
if (code.lintError()) warnOff(code, flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLine::warnStyleOff(bool flag) {
|
||||||
|
for (int codei=V3ErrorCode::EC_MIN; codei<V3ErrorCode::_ENUM_MAX; codei++) {
|
||||||
|
V3ErrorCode code = (V3ErrorCode)codei;
|
||||||
|
if (code.styleError()) warnOff(code, flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileLine::warnIsOff(V3ErrorCode code) const {
|
||||||
|
if (!m_warnOn.test(code)) return true;
|
||||||
|
if (!defaultFileLine().m_warnOn.test(code)) return true; // Global overrides local
|
||||||
|
// UNOPTFLAT implies UNOPT
|
||||||
|
if (code==V3ErrorCode::UNOPT && !m_warnOn.test(V3ErrorCode::UNOPTFLAT)) return true;
|
||||||
|
if ((code.lintError() || code.styleError()) && !m_warnOn.test(V3ErrorCode::I_LINT)) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLine::modifyStateInherit(const FileLine* fromp) {
|
||||||
|
// Any warnings that are off in "from", become off in "this".
|
||||||
|
for (int codei=V3ErrorCode::EC_MIN; codei<V3ErrorCode::_ENUM_MAX; codei++) {
|
||||||
|
V3ErrorCode code = (V3ErrorCode)codei;
|
||||||
|
if (fromp->warnIsOff(code)) {
|
||||||
|
this->warnOff(code, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLine::v3errorEnd(ostringstream& str) {
|
||||||
|
if (this && m_lineno) {
|
||||||
|
ostringstream nsstr;
|
||||||
|
nsstr<<this<<str.str();
|
||||||
|
if (warnIsOff(V3Error::errorCode())) V3Error::suppressThisWarning();
|
||||||
|
V3Error::v3errorEnd(nsstr);
|
||||||
|
} else {
|
||||||
|
V3Error::v3errorEnd(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string FileLine::warnMore() const {
|
||||||
|
if (this && m_lineno) {
|
||||||
|
return V3Error::warnMore()+ascii()+": ";
|
||||||
|
} else {
|
||||||
|
return V3Error::warnMore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef VL_LEAK_CHECKS
|
||||||
|
typedef set<FileLine*> FileLineCheckSet;
|
||||||
|
FileLineCheckSet fileLineLeakChecks;
|
||||||
|
|
||||||
|
void* FileLine::operator new(size_t size) {
|
||||||
|
FileLine* objp = static_cast<FileLine*>(::operator new(size));
|
||||||
|
fileLineLeakChecks.insert(objp);
|
||||||
|
return objp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLine::operator delete(void* objp, size_t size) {
|
||||||
|
if (!objp) return;
|
||||||
|
FileLine* flp = static_cast<FileLine*>(objp);
|
||||||
|
FileLineCheckSet::iterator it = fileLineLeakChecks.find(flp);
|
||||||
|
if (it != fileLineLeakChecks.end()) {
|
||||||
|
fileLineLeakChecks.erase(it);
|
||||||
|
} else {
|
||||||
|
flp->v3fatalSrc("Deleting FileLine object that was never tracked\n");
|
||||||
|
}
|
||||||
|
::operator delete(objp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void FileLine::deleteAllRemaining() {
|
||||||
|
#ifdef VL_LEAK_CHECKS
|
||||||
|
// FileLines are allocated, but never nicely freed, as it's much faster
|
||||||
|
// that way. Unfortunately this makes our leak checking a big mess, so
|
||||||
|
// only when leak checking we'll track them all and cleanup.
|
||||||
|
while (1) {
|
||||||
|
FileLineCheckSet::iterator it=fileLineLeakChecks.begin();
|
||||||
|
if (it==fileLineLeakChecks.end()) break;
|
||||||
|
delete *it;
|
||||||
|
// Operator delete will remove the iterated object from the list.
|
||||||
|
// Eventually the list will be empty and terminate the loop.
|
||||||
|
}
|
||||||
|
fileLineLeakChecks.clear();
|
||||||
|
singleton().clear();
|
||||||
|
#endif
|
||||||
|
}
|
171
src/V3FileLine.h
Normal file
171
src/V3FileLine.h
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Error handling
|
||||||
|
//
|
||||||
|
// Code available from: http://www.veripool.org/verilator
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2014 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.
|
||||||
|
//
|
||||||
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#ifndef _V3FileLine_H_
|
||||||
|
#define _V3FileLine_H_ 1
|
||||||
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <bitset>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
#include "V3Error.h"
|
||||||
|
#include "V3LangCode.h"
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
|
||||||
|
class FileLine;
|
||||||
|
|
||||||
|
//! Singleton class with tables of per-file data.
|
||||||
|
|
||||||
|
//! This singleton class contains tables of data that are unchanging in each
|
||||||
|
//! source file (each with its own unique filename number).
|
||||||
|
class FileLineSingleton {
|
||||||
|
// TYPES
|
||||||
|
typedef map<string,int> FileNameNumMap;
|
||||||
|
typedef map<string,V3LangCode> FileLangNumMap;
|
||||||
|
// MEMBERS
|
||||||
|
FileNameNumMap m_namemap; // filenameno for each filename
|
||||||
|
deque<string> m_names; // filename text for each filenameno
|
||||||
|
deque<V3LangCode> m_languages; // language for each filenameno
|
||||||
|
// COSNTRUCTORS
|
||||||
|
FileLineSingleton() { }
|
||||||
|
~FileLineSingleton() { }
|
||||||
|
protected:
|
||||||
|
friend class FileLine;
|
||||||
|
// METHODS
|
||||||
|
int nameToNumber(const string& filename);
|
||||||
|
const string numberToName(int filenameno) const { return m_names[filenameno]; }
|
||||||
|
const V3LangCode numberToLang(int filenameno) const { return m_languages[filenameno]; }
|
||||||
|
void numberToLang(int filenameno, const V3LangCode& l) { m_languages[filenameno] = l; }
|
||||||
|
void clear() { m_namemap.clear(); m_names.clear(); m_languages.clear(); }
|
||||||
|
void fileNameNumMapDumpXml(ostream& os);
|
||||||
|
static const string filenameLetters(int fileno);
|
||||||
|
};
|
||||||
|
|
||||||
|
//! File and line number of an object, mostly for error reporting
|
||||||
|
|
||||||
|
//! This class is instantiated for every source code line (potentially
|
||||||
|
//! millions). To save space, per-file information (e.g. filename, source
|
||||||
|
//! language is held in tables in the FileLineSingleton class.
|
||||||
|
class FileLine {
|
||||||
|
int m_lineno;
|
||||||
|
int m_filenameno;
|
||||||
|
bitset<V3ErrorCode::_ENUM_MAX> m_warnOn;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct EmptySecret {};
|
||||||
|
inline static FileLineSingleton& singleton() {
|
||||||
|
static FileLineSingleton s;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
inline static FileLine& defaultFileLine() {
|
||||||
|
static FileLine* defFilelinep = new FileLine(FileLine::EmptySecret());
|
||||||
|
return *defFilelinep;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
// User routines should never need to change line numbers
|
||||||
|
// We are storing pointers, so we CAN'T change them after initial reading.
|
||||||
|
friend class FileLineSingleton;
|
||||||
|
friend class V3ParseImp;
|
||||||
|
friend class V3PreLex;
|
||||||
|
friend class V3PreProcImp;
|
||||||
|
void lineno(int num) { m_lineno = num; }
|
||||||
|
void language (V3LangCode lang) { singleton().numberToLang(m_filenameno, lang); }
|
||||||
|
void filename(const string& name) { m_filenameno = singleton().nameToNumber(name); }
|
||||||
|
void lineDirective(const char* textp, int& enterExitRef);
|
||||||
|
void linenoInc() { m_lineno++; }
|
||||||
|
void linenoIncInPlace() { m_lineno++; }
|
||||||
|
FileLine* copyOrSameFileLine();
|
||||||
|
public:
|
||||||
|
FileLine (const string& filename, int lineno) {
|
||||||
|
m_lineno=lineno; m_filenameno = singleton().nameToNumber(filename);
|
||||||
|
m_warnOn=defaultFileLine().m_warnOn; }
|
||||||
|
FileLine (FileLine* fromp) {
|
||||||
|
m_lineno=fromp->m_lineno; m_filenameno = fromp->m_filenameno; m_warnOn=fromp->m_warnOn; }
|
||||||
|
FileLine (EmptySecret);
|
||||||
|
~FileLine() { }
|
||||||
|
FileLine* create(const string& filename, int lineno) { return new FileLine(filename,lineno); }
|
||||||
|
FileLine* create(int lineno) { return create(filename(), lineno); }
|
||||||
|
static void deleteAllRemaining();
|
||||||
|
#ifdef VL_LEAK_CHECKS
|
||||||
|
static void* operator new(size_t size);
|
||||||
|
static void operator delete(void* obj, size_t size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int lineno () const { return m_lineno; }
|
||||||
|
V3LangCode language () const { return singleton().numberToLang(m_filenameno); }
|
||||||
|
string ascii() const;
|
||||||
|
const string filename () const { return singleton().numberToName(m_filenameno); }
|
||||||
|
const string filenameLetters() const { return singleton().filenameLetters(m_filenameno); }
|
||||||
|
const string filebasename () const;
|
||||||
|
const string filebasenameNoExt () const;
|
||||||
|
const string profileFuncname() const;
|
||||||
|
const string xml() const { return "fl=\""+filenameLetters()+cvtToStr(lineno())+"\""; }
|
||||||
|
string lineDirectiveStrg(int enter_exit_level) const;
|
||||||
|
void warnOn(V3ErrorCode code, bool flag) { m_warnOn.set(code,flag); } // Turn on/off warning messages on this line.
|
||||||
|
void warnOff(V3ErrorCode code, bool flag) { warnOn(code,!flag); }
|
||||||
|
bool warnOff(const string& code, bool flag); // Returns 1 if ok
|
||||||
|
bool warnIsOff(V3ErrorCode code) const;
|
||||||
|
void warnLintOff(bool flag);
|
||||||
|
void warnStyleOff(bool flag);
|
||||||
|
void warnStateFrom(const FileLine& from) { m_warnOn=from.m_warnOn; }
|
||||||
|
void warnResetDefault() { warnStateFrom(defaultFileLine()); }
|
||||||
|
|
||||||
|
// Specific flag ACCESSORS/METHODS
|
||||||
|
bool coverageOn() const { return m_warnOn.test(V3ErrorCode::I_COVERAGE); }
|
||||||
|
void coverageOn(bool flag) { warnOn(V3ErrorCode::I_COVERAGE,flag); }
|
||||||
|
bool tracingOn() const { return m_warnOn.test(V3ErrorCode::I_TRACING); }
|
||||||
|
void tracingOn(bool flag) { warnOn(V3ErrorCode::I_TRACING,flag); }
|
||||||
|
|
||||||
|
// METHODS - Global
|
||||||
|
static void globalWarnLintOff(bool flag) {
|
||||||
|
defaultFileLine().warnLintOff(flag); }
|
||||||
|
static void globalWarnStyleOff(bool flag) {
|
||||||
|
defaultFileLine().warnStyleOff(flag); }
|
||||||
|
static void globalWarnOff(V3ErrorCode code, bool flag) {
|
||||||
|
defaultFileLine().warnOff(code, flag); }
|
||||||
|
static bool globalWarnOff(const string& code, bool flag) {
|
||||||
|
return defaultFileLine().warnOff(code, flag); }
|
||||||
|
static void fileNameNumMapDumpXml(ostream& os) {
|
||||||
|
singleton().fileNameNumMapDumpXml(os); }
|
||||||
|
|
||||||
|
// METHODS - Called from netlist
|
||||||
|
// Merge warning disables from another fileline
|
||||||
|
void modifyStateInherit(const FileLine* fromp);
|
||||||
|
// Change the current fileline due to actions discovered after parsing
|
||||||
|
// and may have side effects on other nodes sharing this FileLine.
|
||||||
|
// Use only when this is intended
|
||||||
|
void modifyWarnOff(V3ErrorCode code, bool flag) { warnOff(code,flag); }
|
||||||
|
|
||||||
|
// OPERATORS
|
||||||
|
void v3errorEnd(ostringstream& str);
|
||||||
|
string warnMore() const;
|
||||||
|
inline bool operator==(FileLine rhs) const {
|
||||||
|
return (m_lineno==rhs.m_lineno && m_filenameno==rhs.m_filenameno && m_warnOn==rhs.m_warnOn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ostream& operator<<(ostream& os, FileLine* fileline);
|
||||||
|
|
||||||
|
#endif // Guard
|
@ -26,6 +26,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
|
#include "V3FileLine.h"
|
||||||
#include "V3Options.h"
|
#include "V3Options.h"
|
||||||
|
|
||||||
class AstNetlist;
|
class AstNetlist;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
|
#include "V3FileLine.h"
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#define V3NUMBER_ASCII_BINARY
|
#define V3NUMBER_ASCII_BINARY
|
||||||
#define _V3ERROR_NO_GLOBAL_ 1
|
#define _V3ERROR_NO_GLOBAL_ 1
|
||||||
#include "V3Error.cpp"
|
#include "V3Error.cpp"
|
||||||
|
#include "V3FileLine.cpp"
|
||||||
#include "V3Number.cpp"
|
#include "V3Number.cpp"
|
||||||
|
|
||||||
#include <config_build.h>
|
#include <config_build.h>
|
||||||
|
@ -832,7 +832,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
|||||||
}
|
}
|
||||||
else if ( !strcmp (sw, "-error-limit") && (i+1)<argc ) {
|
else if ( !strcmp (sw, "-error-limit") && (i+1)<argc ) {
|
||||||
shift;
|
shift;
|
||||||
m_errorLimit = atoi(argv[i]);
|
V3Error::errorLimit(atoi(argv[i]));
|
||||||
}
|
}
|
||||||
else if ( !strncmp (sw, "-I", 2)) {
|
else if ( !strncmp (sw, "-I", 2)) {
|
||||||
addIncDirUser (parseFileArg(optdir, string (sw+strlen("-I"))));
|
addIncDirUser (parseFileArg(optdir, string (sw+strlen("-I"))));
|
||||||
@ -946,7 +946,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
|||||||
FileLine::globalWarnStyleOff(true);
|
FileLine::globalWarnStyleOff(true);
|
||||||
}
|
}
|
||||||
else if (!strcmp (sw, "-Wno-fatal")) {
|
else if (!strcmp (sw, "-Wno-fatal")) {
|
||||||
m_warnFatal = false;
|
V3Error::warnFatal(false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
string msg = sw+strlen("-Wno-");
|
string msg = sw+strlen("-Wno-");
|
||||||
@ -1220,7 +1220,6 @@ V3Options::V3Options() {
|
|||||||
m_makePhony = false;
|
m_makePhony = false;
|
||||||
m_orderClockDly = true;
|
m_orderClockDly = true;
|
||||||
m_outFormatOk = false;
|
m_outFormatOk = false;
|
||||||
m_warnFatal = true;
|
|
||||||
m_pinsBv = 65;
|
m_pinsBv = 65;
|
||||||
m_profileCFuncs = false;
|
m_profileCFuncs = false;
|
||||||
m_preprocOnly = false;
|
m_preprocOnly = false;
|
||||||
@ -1243,7 +1242,6 @@ V3Options::V3Options() {
|
|||||||
|
|
||||||
m_convergeLimit = 100;
|
m_convergeLimit = 100;
|
||||||
m_dumpTree = 0;
|
m_dumpTree = 0;
|
||||||
m_errorLimit = 50;
|
|
||||||
m_ifDepth = 0;
|
m_ifDepth = 0;
|
||||||
m_inlineMult = 2000;
|
m_inlineMult = 2000;
|
||||||
m_outputSplit = 0;
|
m_outputSplit = 0;
|
||||||
|
@ -77,7 +77,6 @@ class V3Options {
|
|||||||
bool m_lintOnly; // main switch: --lint-only
|
bool m_lintOnly; // main switch: --lint-only
|
||||||
bool m_orderClockDly;// main switch: --order-clock-delay
|
bool m_orderClockDly;// main switch: --order-clock-delay
|
||||||
bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified
|
bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified
|
||||||
bool m_warnFatal; // main switch: --warnFatal
|
|
||||||
bool m_pinsScUint; // main switch: --pins-sc-uint
|
bool m_pinsScUint; // main switch: --pins-sc-uint
|
||||||
bool m_pinsScBigUint;// main switch: --pins-sc-biguint
|
bool m_pinsScBigUint;// main switch: --pins-sc-biguint
|
||||||
bool m_pinsUint8; // main switch: --pins-uint8
|
bool m_pinsUint8; // main switch: --pins-uint8
|
||||||
@ -100,7 +99,6 @@ class V3Options {
|
|||||||
|
|
||||||
int m_convergeLimit;// main switch: --converge-limit
|
int m_convergeLimit;// main switch: --converge-limit
|
||||||
int m_dumpTree; // main switch: --dump-tree
|
int m_dumpTree; // main switch: --dump-tree
|
||||||
int m_errorLimit; // main switch: --error-limit
|
|
||||||
int m_ifDepth; // main switch: --if-depth
|
int m_ifDepth; // main switch: --if-depth
|
||||||
int m_inlineMult; // main switch: --inline-mult
|
int m_inlineMult; // main switch: --inline-mult
|
||||||
int m_outputSplit; // main switch: --output-split
|
int m_outputSplit; // main switch: --output-split
|
||||||
@ -224,7 +222,6 @@ class V3Options {
|
|||||||
bool orderClockDly() const { return m_orderClockDly; }
|
bool orderClockDly() const { return m_orderClockDly; }
|
||||||
bool outFormatOk() const { return m_outFormatOk; }
|
bool outFormatOk() const { return m_outFormatOk; }
|
||||||
bool keepTempFiles() const { return (V3Error::debugDefault()!=0); }
|
bool keepTempFiles() const { return (V3Error::debugDefault()!=0); }
|
||||||
bool warnFatal() const { return m_warnFatal; }
|
|
||||||
bool pinsScUint() const { return m_pinsScUint; }
|
bool pinsScUint() const { return m_pinsScUint; }
|
||||||
bool pinsScBigUint() const { return m_pinsScBigUint; }
|
bool pinsScBigUint() const { return m_pinsScBigUint; }
|
||||||
bool pinsUint8() const { return m_pinsUint8; }
|
bool pinsUint8() const { return m_pinsUint8; }
|
||||||
@ -240,7 +237,6 @@ class V3Options {
|
|||||||
|
|
||||||
int convergeLimit() const { return m_convergeLimit; }
|
int convergeLimit() const { return m_convergeLimit; }
|
||||||
int dumpTree() const { return m_dumpTree; }
|
int dumpTree() const { return m_dumpTree; }
|
||||||
int errorLimit() const { return m_errorLimit; }
|
|
||||||
int ifDepth() const { return m_ifDepth; }
|
int ifDepth() const { return m_ifDepth; }
|
||||||
int inlineMult() const { return m_inlineMult; }
|
int inlineMult() const { return m_inlineMult; }
|
||||||
int outputSplit() const { return m_outputSplit; }
|
int outputSplit() const { return m_outputSplit; }
|
||||||
|
@ -104,7 +104,7 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
|
|||||||
// of this source file is updated here, in case there have been any
|
// of this source file is updated here, in case there have been any
|
||||||
// intervening +<lang>ext+ options since it was first ecountered.
|
// intervening +<lang>ext+ options since it was first ecountered.
|
||||||
FileLine *modfileline = new FileLine (modfilename, 0);
|
FileLine *modfileline = new FileLine (modfilename, 0);
|
||||||
modfileline->updateLanguage();
|
modfileline->language(v3Global.opt.fileLanguage(modfilename));
|
||||||
ppPushText((string)"`begin_keywords \""+modfileline->language().ascii()+"\"\n");
|
ppPushText((string)"`begin_keywords \""+modfileline->language().ascii()+"\"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
|
#include "V3FileLine.h"
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
#include "V3Parse.h"
|
#include "V3Parse.h"
|
||||||
#include "V3ParseSym.h"
|
#include "V3ParseSym.h"
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
|
#include "V3FileLine.h"
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
#include "V3SymTable.h"
|
#include "V3SymTable.h"
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
|
#include "V3FileLine.h"
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
|
#include "V3FileLine.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
|
#include "V3FileLine.h"
|
||||||
|
|
||||||
class V3ParseImp;
|
class V3ParseImp;
|
||||||
class V3InFilter;
|
class V3InFilter;
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
|
||||||
|
class AstNetlist;
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user