mirror of
https://github.com/verilator/verilator.git
synced 2026-09-08 10:33:20 +02:00
Add lint_off -match waivers (#2102)
* Add more directives to configuration files Allow to set the same directives in configuration files that can also be set by comment attributes (such as /* verilator public */ etc). * Add support for lint messsage waivers Add configuration file switch '-match' for lint_off. It takes a string with wildcards allowed and warnings will be matched against it (if rule and file also match). If it matches, the warning is waived. Fixes #1649 and #1514 Closes #2072
This commit is contained in:
+4
-1
@@ -142,7 +142,10 @@ public:
|
||||
NO_INLINE_MODULE,
|
||||
NO_INLINE_TASK,
|
||||
PUBLIC_MODULE,
|
||||
PUBLIC_TASK
|
||||
PUBLIC_TASK,
|
||||
FULL_CASE,
|
||||
PARALLEL_CASE,
|
||||
ENUM_SIZE
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstPragmaType() : m_e(ILLEGAL) {}
|
||||
|
||||
+451
-93
@@ -30,133 +30,491 @@
|
||||
#include <string>
|
||||
|
||||
//######################################################################
|
||||
// Resolve wildcards in files, modules, ftasks or variables
|
||||
|
||||
class V3ConfigLine {
|
||||
// Template for a class that serves as a map for entities that can be specified
|
||||
// as wildcards and are accessed by a resolved name. It rebuilds a name lookup
|
||||
// cache of resolved entities. Entities stored in this container need an update
|
||||
// function that takes a reference of this type to join multiple entities into one.
|
||||
template <typename T> class V3ConfigWildcardResolver {
|
||||
typedef std::map<string, T> Map;
|
||||
|
||||
Map m_mapWildcard; // Wildcard strings to entities
|
||||
Map m_mapResolved; // Resolved strings to converged entities
|
||||
typename Map::iterator m_last; // Last access, will probably hit again
|
||||
public:
|
||||
int m_lineno; // Line number to make change at
|
||||
V3ErrorCode m_code; // Error code
|
||||
bool m_on; // True to enable message
|
||||
V3ConfigLine(V3ErrorCode code, int lineno, bool on)
|
||||
: m_lineno(lineno), m_code(code), m_on(on) {}
|
||||
~V3ConfigLine() {}
|
||||
inline bool operator< (const V3ConfigLine& rh) const {
|
||||
if (m_lineno<rh.m_lineno) return true;
|
||||
if (m_lineno>rh.m_lineno) return false;
|
||||
if (m_code<rh.m_code) return true;
|
||||
if (m_code>rh.m_code) return false;
|
||||
V3ConfigWildcardResolver() { m_last = m_mapResolved.end(); }
|
||||
|
||||
/// Update into maps from other
|
||||
void update(const V3ConfigWildcardResolver& other) {
|
||||
typename Map::const_iterator it;
|
||||
for (it = other.m_mapResolved.begin(); it != other.m_mapResolved.end(); ++it) {
|
||||
m_mapResolved[it->first].update(it->second);
|
||||
}
|
||||
for (it = other.m_mapWildcard.begin(); it != other.m_mapWildcard.end(); ++it) {
|
||||
m_mapWildcard[it->first].update(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
// Access and create a (wildcard) entity
|
||||
T& at(const string& name) {
|
||||
// Don't store into wildcards if the name is not a wildcard string
|
||||
return m_mapWildcard[name];
|
||||
}
|
||||
// Access an entity and resolve wildcards that match it
|
||||
T* resolve(const string& name) {
|
||||
// Lookup if recently accessed matches
|
||||
if (VL_LIKELY(m_last != m_mapResolved.end()) && VL_LIKELY(m_last->first == name)) {
|
||||
return &m_last->second;
|
||||
}
|
||||
// Lookup if it was resolved before, typically not
|
||||
typename Map::iterator it = m_mapResolved.find(name);
|
||||
if (VL_UNLIKELY(it != m_mapResolved.end())) { return &it->second; }
|
||||
|
||||
T* newp = NULL;
|
||||
// Cannot be resolved, create if matched
|
||||
|
||||
// Update this entity with all matches in the wildcards
|
||||
for (it = m_mapWildcard.begin(); it != m_mapWildcard.end(); ++it) {
|
||||
if (VString::wildmatch(name, it->first)) {
|
||||
if (!newp) {
|
||||
newp = &m_mapResolved[name]; // Emplace and get pointer
|
||||
}
|
||||
newp->update(it->second);
|
||||
}
|
||||
}
|
||||
return newp;
|
||||
}
|
||||
// Flush on update
|
||||
void flush() { m_mapResolved.clear(); }
|
||||
};
|
||||
|
||||
// Only public_flat_rw has the sensitity tree
|
||||
class V3ConfigVarAttr {
|
||||
public:
|
||||
AstAttrType m_type; // Type of attribute
|
||||
AstSenTree* m_sentreep; // Sensitivity tree for public_flat_rw
|
||||
V3ConfigVarAttr(AstAttrType type, AstSenTree* sentreep)
|
||||
: m_type(type)
|
||||
, m_sentreep(sentreep) {}
|
||||
};
|
||||
|
||||
// Overload vector with the required update function and to apply all entries
|
||||
class V3ConfigVar : public std::vector<V3ConfigVarAttr> {
|
||||
public:
|
||||
// Update from other by copying all attributes
|
||||
void update(const V3ConfigVar& node) {
|
||||
reserve(size() + node.size());
|
||||
insert(end(), node.begin(), node.end());
|
||||
}
|
||||
// Apply all attributes to the variable
|
||||
void apply(AstVar* varp) {
|
||||
for (const_iterator it = begin(); it != end(); ++it) {
|
||||
AstNode* newp = new AstAttrOf(varp->fileline(), it->m_type);
|
||||
varp->addAttrsp(newp);
|
||||
if (it->m_type == AstAttrType::VAR_PUBLIC_FLAT_RW && it->m_sentreep) {
|
||||
newp->addNext(new AstAlwaysPublic(varp->fileline(), it->m_sentreep, NULL));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef V3ConfigWildcardResolver<V3ConfigVar> V3ConfigVarResolver;
|
||||
|
||||
//######################################################################
|
||||
// Function or task: Have variables and properties
|
||||
|
||||
class V3ConfigFTask {
|
||||
V3ConfigVarResolver m_vars; // Variables in function/task
|
||||
bool m_isolate; // Isolate function return
|
||||
bool m_noinline; // Don't inline function/task
|
||||
bool m_public; // Public function/task
|
||||
|
||||
public:
|
||||
V3ConfigFTask()
|
||||
: m_isolate(false)
|
||||
, m_noinline(false)
|
||||
, m_public(false) {}
|
||||
void update(const V3ConfigFTask& f) {
|
||||
// Don't overwrite true with false
|
||||
if (f.m_isolate) m_isolate = true;
|
||||
if (f.m_noinline) m_noinline = true;
|
||||
if (f.m_public) m_public = true;
|
||||
m_vars.update(f.m_vars);
|
||||
}
|
||||
|
||||
V3ConfigVarResolver& vars() { return m_vars; }
|
||||
|
||||
void setIsolate(bool set) { m_isolate = set; }
|
||||
void setNoInline(bool set) { m_noinline = set; }
|
||||
void setPublic(bool set) { m_public = set; }
|
||||
|
||||
void apply(AstNodeFTask* ftaskp) {
|
||||
if (m_noinline)
|
||||
ftaskp->addStmtsp(new AstPragma(ftaskp->fileline(), AstPragmaType::NO_INLINE_TASK));
|
||||
if (m_public)
|
||||
ftaskp->addStmtsp(new AstPragma(ftaskp->fileline(), AstPragmaType::PUBLIC_TASK));
|
||||
// Only functions can have isolate (return value)
|
||||
if (VN_IS(ftaskp, Func)) ftaskp->attrIsolateAssign(m_isolate);
|
||||
}
|
||||
};
|
||||
|
||||
typedef V3ConfigWildcardResolver<V3ConfigFTask> V3ConfigFTaskResolver;
|
||||
|
||||
//######################################################################
|
||||
// Modules have tasks, variables, named blocks and properties
|
||||
|
||||
class V3ConfigModule {
|
||||
typedef std::unordered_set<string> StringSet;
|
||||
|
||||
V3ConfigFTaskResolver m_tasks; // Functions/tasks in module
|
||||
V3ConfigVarResolver m_vars; // Variables in module
|
||||
StringSet m_coverageOffBlocks; // List of block names for coverage_off
|
||||
bool m_inline; // Whether to force the inline
|
||||
bool m_inlineValue; // The inline value (on/off)
|
||||
bool m_public; // Public module
|
||||
|
||||
public:
|
||||
V3ConfigModule()
|
||||
: m_inline(false)
|
||||
, m_inlineValue(false)
|
||||
, m_public(false) {}
|
||||
|
||||
void update(const V3ConfigModule& m) {
|
||||
m_tasks.update(m.m_tasks);
|
||||
m_vars.update(m.m_vars);
|
||||
for (StringSet::const_iterator it = m.m_coverageOffBlocks.begin();
|
||||
it != m.m_coverageOffBlocks.end(); ++it) {
|
||||
m_coverageOffBlocks.insert(*it);
|
||||
}
|
||||
if (!m_inline) {
|
||||
m_inline = m.m_inline;
|
||||
m_inlineValue = m.m_inlineValue;
|
||||
}
|
||||
if (!m_public) m_public = m.m_public;
|
||||
}
|
||||
|
||||
V3ConfigFTaskResolver& ftasks() { return m_tasks; }
|
||||
V3ConfigVarResolver& vars() { return m_vars; }
|
||||
|
||||
void addCoverageBlockOff(const string& name) { m_coverageOffBlocks.insert(name); }
|
||||
void setInline(bool set) {
|
||||
m_inline = true;
|
||||
m_inlineValue = set;
|
||||
}
|
||||
void setPublic(bool set) { m_public = set; }
|
||||
|
||||
void apply(AstNodeModule* modp) {
|
||||
if (m_inline) {
|
||||
AstPragmaType type
|
||||
= m_inlineValue ? AstPragmaType::INLINE_MODULE : AstPragmaType::NO_INLINE_MODULE;
|
||||
AstNode* nodep = new AstPragma(modp->fileline(), type);
|
||||
modp->addStmtp(nodep);
|
||||
}
|
||||
if (m_public) {
|
||||
AstNode* nodep = new AstPragma(modp->fileline(), AstPragmaType::PUBLIC_MODULE);
|
||||
modp->addStmtp(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
void applyBlock(AstBegin* nodep) {
|
||||
AstPragmaType pragma = AstPragmaType::COVERAGE_BLOCK_OFF;
|
||||
if (!nodep->unnamed()) {
|
||||
for (StringSet::const_iterator it = m_coverageOffBlocks.begin();
|
||||
it != m_coverageOffBlocks.end(); ++it) {
|
||||
if (VString::wildmatch(nodep->name(), *it)) {
|
||||
nodep->addStmtsp(new AstPragma(nodep->fileline(), pragma));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef V3ConfigWildcardResolver<V3ConfigModule> V3ConfigModuleResolver;
|
||||
|
||||
//######################################################################
|
||||
// Files have:
|
||||
// - Line ignores (lint/coverage/tracing on/off)
|
||||
// - Line attributes: Attributes attached to lines
|
||||
|
||||
// lint/coverage/tracing on/off
|
||||
class V3ConfigIgnoresLine {
|
||||
public:
|
||||
int m_lineno; // Line number to make change at
|
||||
V3ErrorCode m_code; // Error code
|
||||
bool m_on; // True to enable message
|
||||
V3ConfigIgnoresLine(V3ErrorCode code, int lineno, bool on)
|
||||
: m_lineno(lineno)
|
||||
, m_code(code)
|
||||
, m_on(on) {}
|
||||
~V3ConfigIgnoresLine() {}
|
||||
inline bool operator<(const V3ConfigIgnoresLine& rh) const {
|
||||
if (m_lineno < rh.m_lineno) return true;
|
||||
if (m_lineno > rh.m_lineno) return false;
|
||||
if (m_code < rh.m_code) return true;
|
||||
if (m_code > rh.m_code) return false;
|
||||
// Always turn "on" before "off" so that overlapping lines will end
|
||||
// up finally with the error "off"
|
||||
return (m_on>rh.m_on);
|
||||
return (m_on > rh.m_on);
|
||||
}
|
||||
};
|
||||
std::ostream& operator<<(std::ostream& os, V3ConfigLine rhs) {
|
||||
return os<<rhs.m_lineno<<", "<<rhs.m_code<<", "<<rhs.m_on; }
|
||||
std::ostream& operator<<(std::ostream& os, V3ConfigIgnoresLine rhs) {
|
||||
return os << rhs.m_lineno << ", " << rhs.m_code << ", " << rhs.m_on;
|
||||
}
|
||||
|
||||
class V3ConfigIgnores {
|
||||
typedef std::multiset<V3ConfigLine> IgnLines; // list of {line,code,on}
|
||||
typedef std::map<string,IgnLines> IgnFiles; // {filename} => list of {line,code,on}
|
||||
// Some attributes are attached to entities of the occur on a fileline
|
||||
// and multiple attributes can be attached to a line
|
||||
typedef std::bitset<AstPragmaType::ENUM_SIZE> V3ConfigLineAttribute;
|
||||
|
||||
// MEMBERS
|
||||
string m_lastFilename; // Last filename looked up
|
||||
int m_lastLineno; // Last linenumber looked up
|
||||
// File entity
|
||||
class V3ConfigFile {
|
||||
typedef std::map<int, V3ConfigLineAttribute> LineAttrMap; // Map line->bitset of attributes
|
||||
typedef std::multiset<V3ConfigIgnoresLine> IgnLines; // list of {line,code,on}
|
||||
typedef std::pair<V3ErrorCode, string> WaiverSetting; // Waive code if string matches
|
||||
typedef std::vector<WaiverSetting> Waivers; // List of {code,wildcard string}
|
||||
|
||||
IgnLines::const_iterator m_lastIt; // Point with next linenumber > current line number
|
||||
IgnLines::const_iterator m_lastEnd; // Point with end()
|
||||
LineAttrMap m_lineAttrs; // Atributes to line mapping
|
||||
IgnLines m_ignLines; // Ignore line settings
|
||||
Waivers m_waivers; // Waive messages
|
||||
|
||||
IgnFiles m_ignWilds; // Ignores for each wildcarded filename
|
||||
IgnFiles m_ignFiles; // Ignores for each non-wildcarded filename
|
||||
struct {
|
||||
int lineno; // Last line number
|
||||
IgnLines::const_iterator it; // Point with next linenumber > current line number
|
||||
} m_lastIgnore; // Last ignore line run
|
||||
|
||||
static V3ConfigIgnores s_singleton; // Singleton (not via local static, as that's slow)
|
||||
|
||||
V3ConfigIgnores() { m_lastLineno = -1; }
|
||||
~V3ConfigIgnores() {}
|
||||
|
||||
// METHODS
|
||||
inline IgnLines* findWilds(const string& wildname) {
|
||||
IgnFiles::iterator it = m_ignWilds.find(wildname);
|
||||
if (it != m_ignWilds.end()) {
|
||||
return &(it->second);
|
||||
} else {
|
||||
m_ignWilds.insert(make_pair(wildname, IgnLines()));
|
||||
it = m_ignWilds.find(wildname);
|
||||
return &(it->second);
|
||||
}
|
||||
}
|
||||
inline void absBuild(const string& filename) {
|
||||
// Given a filename, find all wildcard matches against it and build
|
||||
// hash with the specific filename. This avoids having to wildmatch
|
||||
// more than once against any filename.
|
||||
IgnFiles::iterator it = m_ignFiles.find(filename);
|
||||
if (it == m_ignFiles.end()) {
|
||||
// Haven't seen this filename before
|
||||
m_ignFiles.insert(make_pair(filename, IgnLines()));
|
||||
it = m_ignFiles.find(filename);
|
||||
// Make new list for this file of all matches
|
||||
for (IgnFiles::iterator fnit = m_ignWilds.begin(); fnit != m_ignWilds.end(); ++fnit) {
|
||||
if (VString::wildmatch(filename.c_str(), fnit->first.c_str())) {
|
||||
for (IgnLines::iterator lit = fnit->second.begin();
|
||||
lit != fnit->second.end(); ++lit) {
|
||||
it->second.insert(*lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_lastIt = it->second.begin();
|
||||
m_lastEnd = it->second.end();
|
||||
// Match a given line and attribute to the map, line 0 is any
|
||||
bool lineMatch(int lineno, AstPragmaType type) {
|
||||
if (m_lineAttrs.find(0) != m_lineAttrs.end() && m_lineAttrs[0][type]) return true;
|
||||
if (m_lineAttrs.find(lineno) == m_lineAttrs.end()) return false;
|
||||
return m_lineAttrs[lineno][type];
|
||||
}
|
||||
|
||||
public:
|
||||
inline static V3ConfigIgnores& singleton() { return s_singleton; }
|
||||
V3ConfigFile() { m_lastIgnore = {-1, m_ignLines.begin()}; }
|
||||
|
||||
void addIgnore(V3ErrorCode code, const string& wildname, int lineno, bool on) {
|
||||
// Insert
|
||||
IgnLines* linesp = findWilds(wildname);
|
||||
UINFO(9,"config addIgnore "<<wildname<<":"<<lineno<<", "<<code<<", "<<on<<endl);
|
||||
linesp->insert(V3ConfigLine(code, lineno, on));
|
||||
// Flush the match cache, due to a change in the rules.
|
||||
m_ignFiles.clear();
|
||||
m_lastFilename = " ";
|
||||
void update(const V3ConfigFile& file) {
|
||||
// Copy in all Attributes
|
||||
for (LineAttrMap::const_iterator it = file.m_lineAttrs.begin();
|
||||
it != file.m_lineAttrs.end(); ++it) {
|
||||
m_lineAttrs[it->first] |= it->second;
|
||||
}
|
||||
// Copy in all ignores
|
||||
for (IgnLines::const_iterator it = file.m_ignLines.begin(); it != file.m_ignLines.end();
|
||||
++it) {
|
||||
m_ignLines.insert(*it);
|
||||
}
|
||||
// Update the iterator after the list has changed
|
||||
m_lastIgnore.it = m_ignLines.begin();
|
||||
m_waivers.reserve(m_waivers.size() + file.m_waivers.size());
|
||||
m_waivers.insert(m_waivers.end(), file.m_waivers.begin(), file.m_waivers.end());
|
||||
}
|
||||
void addLineAttribute(int lineno, AstPragmaType attr) { m_lineAttrs[lineno].set(attr); }
|
||||
void addIgnore(V3ErrorCode code, int lineno, bool on) {
|
||||
m_ignLines.insert(V3ConfigIgnoresLine(code, lineno, on));
|
||||
m_lastIgnore.it = m_ignLines.begin();
|
||||
}
|
||||
void addWaiver(V3ErrorCode code, const string& match) {
|
||||
m_waivers.push_back(make_pair(code, match));
|
||||
}
|
||||
|
||||
void applyBlock(AstBegin* nodep) {
|
||||
// Apply to block at this line
|
||||
AstPragmaType pragma = AstPragmaType::COVERAGE_BLOCK_OFF;
|
||||
if (lineMatch(nodep->fileline()->lineno(), pragma)) {
|
||||
nodep->addStmtsp(new AstPragma(nodep->fileline(), pragma));
|
||||
}
|
||||
}
|
||||
void applyCase(AstCase* nodep) {
|
||||
// Apply to this case at this line
|
||||
int lineno = nodep->fileline()->lineno();
|
||||
if (lineMatch(lineno, AstPragmaType::FULL_CASE)) nodep->fullPragma(true);
|
||||
if (lineMatch(lineno, AstPragmaType::PARALLEL_CASE)) nodep->parallelPragma(true);
|
||||
}
|
||||
inline void applyIgnores(FileLine* filelinep) {
|
||||
// HOT routine, called each parsed token line
|
||||
if (m_lastLineno != filelinep->lastLineno()
|
||||
|| m_lastFilename != filelinep->filename()) {
|
||||
//UINFO(9," ApplyIgnores for "<<filelinep->ascii()<<endl);
|
||||
if (VL_UNLIKELY(m_lastFilename != filelinep->filename())) {
|
||||
absBuild(filelinep->filename());
|
||||
m_lastFilename = filelinep->filename();
|
||||
}
|
||||
// HOT routine, called each parsed token line of this filename
|
||||
if (m_lastIgnore.lineno != filelinep->lineno()) {
|
||||
// UINFO(9," ApplyIgnores for "<<filelinep->ascii()<<endl);
|
||||
// Process all on/offs for lines up to and including the current line
|
||||
int curlineno = filelinep->lastLineno();
|
||||
for (; m_lastIt != m_lastEnd; ++m_lastIt) {
|
||||
if (m_lastIt->m_lineno > curlineno) break;
|
||||
//UINFO(9," Hit "<<*m_lastIt<<endl);
|
||||
filelinep->warnOn(m_lastIt->m_code, m_lastIt->m_on);
|
||||
for (; m_lastIgnore.it != m_ignLines.end(); ++m_lastIgnore.it) {
|
||||
if (m_lastIgnore.it->m_lineno > curlineno) break;
|
||||
// UINFO(9," Hit "<<*m_lastIt<<endl);
|
||||
filelinep->warnOn(m_lastIgnore.it->m_code, m_lastIgnore.it->m_on);
|
||||
}
|
||||
if (0 && debug() >= 9) {
|
||||
for (IgnLines::const_iterator it=m_lastIt; it != m_lastEnd; ++it) {
|
||||
UINFO(9," NXT "<<*it<<endl);
|
||||
for (IgnLines::const_iterator it = m_lastIgnore.it; it != m_ignLines.end(); ++it) {
|
||||
UINFO(9, " NXT " << *it << endl);
|
||||
}
|
||||
}
|
||||
m_lastLineno = filelinep->lastLineno();
|
||||
m_lastIgnore.lineno = filelinep->lastLineno();
|
||||
}
|
||||
}
|
||||
bool waive(V3ErrorCode code, const string& match) {
|
||||
for (Waivers::const_iterator it = m_waivers.begin(); it != m_waivers.end(); ++it) {
|
||||
if (((it->first == code) || (it->first == V3ErrorCode::I_LINT))
|
||||
&& VString::wildmatch(match, it->second)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
V3ConfigIgnores V3ConfigIgnores::s_singleton;
|
||||
typedef V3ConfigWildcardResolver<V3ConfigFile> V3ConfigFileResolver;
|
||||
|
||||
//######################################################################
|
||||
// Resolve modules and files in the design
|
||||
|
||||
class V3ConfigResolver {
|
||||
V3ConfigModuleResolver m_modules; // Access to module names (with wildcards)
|
||||
V3ConfigFileResolver m_files; // Access to file names (with wildcards)
|
||||
|
||||
static V3ConfigResolver s_singleton; // Singleton (not via local static, as that's slow)
|
||||
V3ConfigResolver() {}
|
||||
~V3ConfigResolver() {}
|
||||
|
||||
public:
|
||||
inline static V3ConfigResolver& s() { return s_singleton; }
|
||||
|
||||
V3ConfigModuleResolver& modules() { return m_modules; }
|
||||
V3ConfigFileResolver& files() { return m_files; }
|
||||
};
|
||||
|
||||
V3ConfigResolver V3ConfigResolver::s_singleton;
|
||||
|
||||
//######################################################################
|
||||
// V3Config
|
||||
|
||||
void V3Config::addCaseFull(const string& filename, int lineno) {
|
||||
V3ConfigFile& file = V3ConfigResolver::s().files().at(filename);
|
||||
file.addLineAttribute(lineno, AstPragmaType::FULL_CASE);
|
||||
}
|
||||
|
||||
void V3Config::addCaseParallel(const string& filename, int lineno) {
|
||||
V3ConfigFile& file = V3ConfigResolver::s().files().at(filename);
|
||||
file.addLineAttribute(lineno, AstPragmaType::PARALLEL_CASE);
|
||||
}
|
||||
|
||||
void V3Config::addCoverageBlockOff(const string& filename, int lineno) {
|
||||
V3ConfigFile& file = V3ConfigResolver::s().files().at(filename);
|
||||
file.addLineAttribute(lineno, AstPragmaType::COVERAGE_BLOCK_OFF);
|
||||
}
|
||||
|
||||
void V3Config::addCoverageBlockOff(const string& module, const string& blockname) {
|
||||
V3ConfigResolver::s().modules().at(module).addCoverageBlockOff(blockname);
|
||||
}
|
||||
|
||||
void V3Config::addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max) {
|
||||
if (filename=="*") {
|
||||
FileLine::globalWarnOff(code,!on);
|
||||
if (filename == "*") {
|
||||
FileLine::globalWarnOff(code, !on);
|
||||
} else {
|
||||
V3ConfigIgnores::singleton().addIgnore(code, filename, min, on);
|
||||
if (max) V3ConfigIgnores::singleton().addIgnore(code, filename, max, !on);
|
||||
V3ConfigResolver::s().files().at(filename).addIgnore(code, min, on);
|
||||
if (max) V3ConfigResolver::s().files().at(filename).addIgnore(code, max, !on);
|
||||
V3ConfigResolver::s().files().flush();
|
||||
}
|
||||
}
|
||||
|
||||
void V3Config::applyIgnores(FileLine* filelinep) {
|
||||
V3ConfigIgnores::singleton().applyIgnores(filelinep);
|
||||
void V3Config::addInline(FileLine* fl, const string& module, const string& ftask, bool on) {
|
||||
if (ftask.empty()) {
|
||||
V3ConfigResolver::s().modules().at(module).setInline(on);
|
||||
} else {
|
||||
if (!on) {
|
||||
fl->v3error("no_inline not supported for tasks" << endl);
|
||||
} else {
|
||||
V3ConfigResolver::s().modules().at(module).ftasks().at(ftask).setNoInline(on);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void V3Config::addVarAttr(FileLine* fl, const string& module, const string& ftask,
|
||||
const string& var, AstAttrType attr, AstSenTree* sensep) {
|
||||
// Semantics: sensep only if public_flat_rw
|
||||
if ((attr != AstAttrType::VAR_PUBLIC_FLAT_RW) && sensep) {
|
||||
sensep->v3error("sensitivity not expected for attribute" << endl);
|
||||
return;
|
||||
}
|
||||
// Semantics: Most of the attributes operate on signals
|
||||
if (var.empty()) {
|
||||
if (attr == AstAttrType::VAR_ISOLATE_ASSIGNMENTS) {
|
||||
if (ftask.empty()) {
|
||||
fl->v3error("isolate_assignments only applies to signals or functions/tasks"
|
||||
<< endl);
|
||||
} else {
|
||||
V3ConfigResolver::s().modules().at(module).ftasks().at(ftask).setIsolate(true);
|
||||
}
|
||||
} else if (attr == AstAttrType::VAR_PUBLIC) {
|
||||
if (ftask.empty()) {
|
||||
// public module, this is the only exception from var here
|
||||
V3ConfigResolver::s().modules().at(module).setPublic(true);
|
||||
} else {
|
||||
V3ConfigResolver::s().modules().at(module).ftasks().at(ftask).setPublic(true);
|
||||
}
|
||||
} else {
|
||||
fl->v3error("missing -signal" << endl);
|
||||
}
|
||||
} else {
|
||||
V3ConfigModule& mod = V3ConfigResolver::s().modules().at(module);
|
||||
if (ftask.empty()) {
|
||||
mod.vars().at(var).push_back(V3ConfigVarAttr(attr, sensep));
|
||||
} else {
|
||||
mod.ftasks().at(ftask).vars().at(var).push_back({attr, sensep});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void V3Config::addWaiver(V3ErrorCode code, const string& filename, const string& match) {
|
||||
V3ConfigResolver::s().files().at(filename).addWaiver(code, match);
|
||||
}
|
||||
|
||||
void V3Config::applyCase(AstCase* nodep) {
|
||||
const string& filename = nodep->fileline()->filename();
|
||||
V3ConfigFile* filep = V3ConfigResolver::s().files().resolve(filename);
|
||||
if (filep) filep->applyCase(nodep);
|
||||
}
|
||||
|
||||
void V3Config::applyCoverageBlock(AstNodeModule* modulep, AstBegin* nodep) {
|
||||
const string& filename = nodep->fileline()->filename();
|
||||
V3ConfigFile* filep = V3ConfigResolver::s().files().resolve(filename);
|
||||
if (filep) filep->applyBlock(nodep);
|
||||
const string& modname = modulep->name();
|
||||
V3ConfigModule* modp = V3ConfigResolver::s().modules().resolve(modname);
|
||||
if (modp) modp->applyBlock(nodep);
|
||||
}
|
||||
|
||||
void V3Config::applyIgnores(FileLine* filelinep) {
|
||||
const string& filename = filelinep->filename();
|
||||
V3ConfigFile* filep = V3ConfigResolver::s().files().resolve(filename);
|
||||
if (filep) filep->applyIgnores(filelinep);
|
||||
}
|
||||
|
||||
void V3Config::applyModule(AstNodeModule* modulep) {
|
||||
const string& modname = modulep->name();
|
||||
V3ConfigModule* modp = V3ConfigResolver::s().modules().resolve(modname);
|
||||
if (modp) modp->apply(modulep);
|
||||
}
|
||||
|
||||
void V3Config::applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp) {
|
||||
const string& modname = modulep->name();
|
||||
V3ConfigModule* modp = V3ConfigResolver::s().modules().resolve(modname);
|
||||
if (!modp) return;
|
||||
V3ConfigFTask* ftp = modp->ftasks().resolve(ftaskp->name());
|
||||
if (ftp) ftp->apply(ftaskp);
|
||||
}
|
||||
|
||||
void V3Config::applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar* varp) {
|
||||
V3ConfigVar* vp;
|
||||
V3ConfigModule* modp = V3ConfigResolver::s().modules().resolve(modulep->name());
|
||||
if (!modp) return;
|
||||
if (ftaskp) {
|
||||
V3ConfigFTask* ftp = modp->ftasks().resolve(ftaskp->name());
|
||||
if (!ftp) return;
|
||||
vp = ftp->vars().resolve(varp->name());
|
||||
} else {
|
||||
vp = modp->vars().resolve(varp->name());
|
||||
}
|
||||
if (vp) vp->apply(varp);
|
||||
}
|
||||
|
||||
bool V3Config::waive(FileLine* filelinep, V3ErrorCode code, const string& message) {
|
||||
V3ConfigFile* filep = V3ConfigResolver::s().files().resolve(filelinep->filename());
|
||||
if (!filep) return false;
|
||||
return filep->waive(code, message);
|
||||
}
|
||||
|
||||
@@ -26,13 +26,27 @@
|
||||
|
||||
#include "V3Error.h"
|
||||
#include "V3FileLine.h"
|
||||
#include "V3Ast.h"
|
||||
|
||||
//######################################################################
|
||||
|
||||
class V3Config {
|
||||
public:
|
||||
static void addCaseFull(const string& file, int lineno);
|
||||
static void addCaseParallel(const string& file, int lineno);
|
||||
static void addCoverageBlockOff(const string& file, int lineno);
|
||||
static void addCoverageBlockOff(const string& module, const string& blockname);
|
||||
static void addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max);
|
||||
static void addWaiver(V3ErrorCode code, const string& filename, const string& msg);
|
||||
static void addInline(FileLine* fl, const string& module, const string& ftask, bool on);
|
||||
static void addVarAttr(FileLine* fl, const string& module, const string& ftask, const string& signal, AstAttrType type, AstSenTree* nodep);
|
||||
static void applyCase(AstCase* nodep);
|
||||
static void applyCoverageBlock(AstNodeModule* modulep, AstBegin* nodep);
|
||||
static void applyIgnores(FileLine* filelinep);
|
||||
static void applyModule(AstNodeModule* nodep);
|
||||
static void applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp);
|
||||
static void applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar* varp);
|
||||
static bool waive(FileLine* filelinep, V3ErrorCode code, const string& match);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
||||
+4
-1
@@ -131,7 +131,10 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
||||
}
|
||||
puts(" origName="); putsQuoted(nodep->origName());
|
||||
// Attributes
|
||||
if (nodep->attrClocker()) puts(" clocker=\"true\"");
|
||||
if (nodep->attrClocker() == VVarAttrClocker::CLOCKER_YES)
|
||||
puts(" clocker=\"true\"");
|
||||
else if (nodep->attrClocker() == VVarAttrClocker::CLOCKER_NO)
|
||||
puts(" clocker=\"false\"");
|
||||
if (nodep->attrClockEn()) puts(" clock_enable=\"true\"");
|
||||
if (nodep->attrIsolateAssign()) puts(" isolate_assignments=\"true\"");
|
||||
if (nodep->isSigPublic()) puts(" public=\"true\"");
|
||||
|
||||
+4
-1
@@ -341,7 +341,10 @@ void FileLine::v3errorEnd(std::ostringstream& str, const string& locationStr) {
|
||||
if (!locationStr.empty()) {
|
||||
lstr<<std::setw(ascii().length())<<" "<<": "<<locationStr;
|
||||
}
|
||||
if (warnIsOff(V3Error::errorCode())) V3Error::suppressThisWarning();
|
||||
if (warnIsOff(V3Error::errorCode())
|
||||
|| V3Config::waive(this, V3Error::errorCode(), str.str())) {
|
||||
V3Error::suppressThisWarning();
|
||||
}
|
||||
else if (!V3Error::errorContexted()) nsstr<<warnContextPrimary();
|
||||
V3Error::v3errorEnd(nsstr, lstr.str());
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "V3Global.h"
|
||||
#include "V3LinkParse.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3Config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
@@ -106,6 +107,8 @@ private:
|
||||
|
||||
// VISITs
|
||||
virtual void visit(AstNodeFTask* nodep) {
|
||||
V3Config::applyFTask(m_modp, nodep);
|
||||
|
||||
if (!nodep->user1SetOnce()) { // Process only once.
|
||||
cleanFileline(nodep);
|
||||
m_ftaskp = nodep;
|
||||
@@ -189,6 +192,9 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
// Maybe this variable has a signal attribute
|
||||
V3Config::applyVarAttr(m_modp, m_ftaskp, nodep);
|
||||
|
||||
if (v3Global.opt.publicFlatRW()) {
|
||||
switch (nodep->varType()) {
|
||||
case AstVarType::VAR:
|
||||
@@ -438,6 +444,8 @@ private:
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeModule* nodep) {
|
||||
V3Config::applyModule(nodep);
|
||||
|
||||
// Module: Create sim table for entire module and iterate
|
||||
cleanFileline(nodep);
|
||||
//
|
||||
@@ -474,6 +482,17 @@ private:
|
||||
visitIterateNoValueMod(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstBegin* nodep) {
|
||||
V3Config::applyCoverageBlock(m_modp, nodep);
|
||||
cleanFileline(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCase* nodep) {
|
||||
V3Config::applyCase(nodep);
|
||||
cleanFileline(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstNode* nodep) {
|
||||
// Default: Just iterate
|
||||
cleanFileline(nodep);
|
||||
|
||||
@@ -62,6 +62,7 @@ struct V3ParseBisonYYSType {
|
||||
VSignedState signstate;
|
||||
V3ImportProperty iprop;
|
||||
V3ErrorCode::en errcodeen;
|
||||
AstAttrType::en attrtypeen;
|
||||
|
||||
AstNode* nodep;
|
||||
|
||||
|
||||
@@ -74,6 +74,14 @@ bool VString::wildmatch(const char* s, const char* p) {
|
||||
return (*s == '\0');
|
||||
}
|
||||
|
||||
bool VString::wildmatch(const string& s, const string& p) {
|
||||
return wildmatch(s.c_str(), p.c_str());
|
||||
}
|
||||
|
||||
bool VString::isWildcard(const string &p) {
|
||||
return ((p.find("*") != string::npos) || (p.find("?") != string::npos));
|
||||
}
|
||||
|
||||
string VString::dot(const string& a, const string& dot, const string& b) {
|
||||
if (b=="") return a;
|
||||
if (a=="") return b;
|
||||
|
||||
@@ -63,6 +63,10 @@ public:
|
||||
// METHODS (generic string utilities)
|
||||
// Return true if p with ? or *'s matches s
|
||||
static bool wildmatch(const char* s, const char* p);
|
||||
// Return true if p with ? or *'s matches s
|
||||
static bool wildmatch(const string& s, const string& p);
|
||||
// Return true if this is a wildcard string (contains * or ?)
|
||||
static bool isWildcard(const string &p);
|
||||
// Return {a}{dot}{b}, omitting dot if a or b are empty
|
||||
static string dot(const string& a, const string& dot, const string& b);
|
||||
// Convert string to lowercase (tolower)
|
||||
|
||||
@@ -135,17 +135,45 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
{ws} { FL_FWD; FL_BRK; } /* otherwise ignore white-space */
|
||||
{crnl} { FL_FWD; FL_BRK; } /* Count line numbers */
|
||||
|
||||
"clock_enable" { FL; return yVLT_CLOCK_ENABLE; }
|
||||
"clocker" { FL; return yVLT_CLOCKER; }
|
||||
"coverage_block_off" { FL; return yVLT_COVERAGE_BLOCK_OFF; }
|
||||
"coverage_off" { FL; return yVLT_COVERAGE_OFF; }
|
||||
"coverage_on" { FL; return yVLT_COVERAGE_ON; }
|
||||
"full_case" { FL; return yVLT_FULL_CASE; }
|
||||
"inline" { FL; return yVLT_INLINE; }
|
||||
"isolate_assignments" { FL; return yVLT_ISOLATE_ASSIGNMENTS; }
|
||||
"lint_off" { FL; return yVLT_LINT_OFF; }
|
||||
"lint_on" { FL; return yVLT_LINT_ON; }
|
||||
"no_clocker" { FL; return yVLT_NO_CLOCKER; }
|
||||
"no_inline" { FL; return yVLT_NO_INLINE; }
|
||||
"parallel_case" { FL; return yVLT_PARALLEL_CASE; }
|
||||
"public" { FL; return yVLT_PUBLIC; }
|
||||
"public_flat" { FL; return yVLT_PUBLIC_FLAT; }
|
||||
"public_flat_rd" { FL; return yVLT_PUBLIC_FLAT_RD; }
|
||||
"public_flat_rw" { FL; return yVLT_PUBLIC_FLAT_RW; }
|
||||
"public_module" { FL; return yVLT_PUBLIC_MODULE; }
|
||||
"sc_bv" { FL; return yVLT_SC_BV; }
|
||||
"sformat" { FL; return yVLT_SFORMAT; }
|
||||
"tracing_off" { FL; return yVLT_TRACING_OFF; }
|
||||
"tracing_on" { FL; return yVLT_TRACING_ON; }
|
||||
|
||||
-?"-block" { FL; return yVLT_D_BLOCK; }
|
||||
-?"-file" { FL; return yVLT_D_FILE; }
|
||||
-?"-function" { FL; return yVLT_D_FUNCTION; }
|
||||
-?"-lines" { FL; return yVLT_D_LINES; }
|
||||
-?"-match" { FL; return yVLT_D_MATCH; }
|
||||
-?"-module" { FL; return yVLT_D_MODULE; }
|
||||
-?"-msg" { FL; return yVLT_D_MSG; }
|
||||
-?"-rule" { FL; return yVLT_D_RULE; }
|
||||
-?"-task" { FL; return yVLT_D_TASK; }
|
||||
-?"-var" { FL; return yVLT_D_VAR; }
|
||||
|
||||
/* Reachable by attr_event_control */
|
||||
"edge" { FL; return yEDGE; }
|
||||
"negedge" { FL; return yNEGEDGE; }
|
||||
"or" { FL; return yOR; }
|
||||
"posedge" { FL; return yPOSEDGE; }
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
+111
-18
@@ -273,17 +273,39 @@ class AstSenTree;
|
||||
%token<strp> yaSCCTOR "`systemc_implementation BLOCK"
|
||||
%token<strp> yaSCDTOR "`systemc_imp_header BLOCK"
|
||||
|
||||
%token<fl> yVLT_COVERAGE_OFF "coverage_off"
|
||||
%token<fl> yVLT_COVERAGE_ON "coverage_on"
|
||||
%token<fl> yVLT_LINT_OFF "lint_off"
|
||||
%token<fl> yVLT_LINT_ON "lint_on"
|
||||
%token<fl> yVLT_TRACING_OFF "tracing_off"
|
||||
%token<fl> yVLT_TRACING_ON "tracing_on"
|
||||
%token<fl> yVLT_CLOCKER "clocker"
|
||||
%token<fl> yVLT_CLOCK_ENABLE "clock_enable"
|
||||
%token<fl> yVLT_COVERAGE_BLOCK_OFF "coverage_block_off"
|
||||
%token<fl> yVLT_COVERAGE_OFF "coverage_off"
|
||||
%token<fl> yVLT_COVERAGE_ON "coverage_on"
|
||||
%token<fl> yVLT_FULL_CASE "full_case"
|
||||
%token<fl> yVLT_INLINE "inline"
|
||||
%token<fl> yVLT_ISOLATE_ASSIGNMENTS "isolate_assignments"
|
||||
%token<fl> yVLT_LINT_OFF "lint_off"
|
||||
%token<fl> yVLT_LINT_ON "lint_on"
|
||||
%token<fl> yVLT_NO_CLOCKER "no_clocker"
|
||||
%token<fl> yVLT_NO_INLINE "no_inline"
|
||||
%token<fl> yVLT_PARALLEL_CASE "parallel_case"
|
||||
%token<fl> yVLT_PUBLIC "public"
|
||||
%token<fl> yVLT_PUBLIC_FLAT "public_flat"
|
||||
%token<fl> yVLT_PUBLIC_FLAT_RD "public_flat_rd"
|
||||
%token<fl> yVLT_PUBLIC_FLAT_RW "public_flat_rw"
|
||||
%token<fl> yVLT_PUBLIC_MODULE "public_module"
|
||||
%token<fl> yVLT_SC_BV "sc_bv"
|
||||
%token<fl> yVLT_SFORMAT "sformat"
|
||||
%token<fl> yVLT_TRACING_OFF "tracing_off"
|
||||
%token<fl> yVLT_TRACING_ON "tracing_on"
|
||||
|
||||
%token<fl> yVLT_D_FILE "--file"
|
||||
%token<fl> yVLT_D_LINES "--lines"
|
||||
%token<fl> yVLT_D_MSG "--msg"
|
||||
%token<fl> yVLT_D_RULE "--rule"
|
||||
%token<fl> yVLT_D_BLOCK "--block"
|
||||
%token<fl> yVLT_D_FILE "--file"
|
||||
%token<fl> yVLT_D_FUNCTION "--function"
|
||||
%token<fl> yVLT_D_LINES "--lines"
|
||||
%token<fl> yVLT_D_MODULE "--module"
|
||||
%token<fl> yVLT_D_MATCH "--match"
|
||||
%token<fl> yVLT_D_MSG "--msg"
|
||||
%token<fl> yVLT_D_RULE "--rule"
|
||||
%token<fl> yVLT_D_TASK "--task"
|
||||
%token<fl> yVLT_D_VAR "--var"
|
||||
|
||||
%token<strp> yaD_IGNORE "${ignored-bbox-sys}"
|
||||
%token<strp> yaD_DPI "${dpi-sys}"
|
||||
@@ -737,6 +759,7 @@ class AstSenTree;
|
||||
// Blank lines for type insertion
|
||||
// Blank lines for type insertion
|
||||
// Blank lines for type insertion
|
||||
// Blank lines for type insertion
|
||||
|
||||
%start source_text
|
||||
|
||||
@@ -2460,6 +2483,11 @@ cellpinItemE<pinp>: // IEEE: named_port_connection + empty
|
||||
//************************************************
|
||||
// EventControl lists
|
||||
|
||||
attr_event_controlE<sentreep>:
|
||||
/* empty */ { $$ = NULL; }
|
||||
| attr_event_control { $$ = $1; }
|
||||
;
|
||||
|
||||
attr_event_control<sentreep>: // ==IEEE: event_control
|
||||
'@' '(' event_expression ')' { $$ = new AstSenTree($1,$3); }
|
||||
| '@' '(' '*' ')' { $$ = NULL; }
|
||||
@@ -5582,14 +5610,45 @@ memberQualOne<nodep>: // IEEE: property_qualifier + method_qualifier
|
||||
// VLT Files
|
||||
|
||||
vltItem:
|
||||
vltOffFront { V3Config::addIgnore($1,false,"*",0,0); }
|
||||
| vltOffFront yVLT_D_FILE yaSTRING { V3Config::addIgnore($1,false,*$3,0,0); }
|
||||
| vltOffFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM { V3Config::addIgnore($1,false,*$3,$5->toUInt(),$5->toUInt()+1); }
|
||||
| vltOffFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM '-' yaINTNUM { V3Config::addIgnore($1,false,*$3,$5->toUInt(),$7->toUInt()+1); }
|
||||
| vltOnFront { V3Config::addIgnore($1,true,"*",0,0); }
|
||||
| vltOnFront yVLT_D_FILE yaSTRING { V3Config::addIgnore($1,true,*$3,0,0); }
|
||||
| vltOnFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM { V3Config::addIgnore($1,true,*$3,$5->toUInt(),$5->toUInt()+1); }
|
||||
| vltOnFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM '-' yaINTNUM { V3Config::addIgnore($1,true,*$3,$5->toUInt(),$7->toUInt()+1); }
|
||||
|
||||
vltOffFront { V3Config::addIgnore($1, false, "*", 0, 0); }
|
||||
| vltOffFront yVLT_D_FILE yaSTRING
|
||||
{ V3Config::addIgnore($1, false, *$3, 0, 0); }
|
||||
| vltOffFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM
|
||||
{ V3Config::addIgnore($1, false, *$3, $5->toUInt(), $5->toUInt()+1); }
|
||||
| vltOffFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM '-' yaINTNUM
|
||||
{ V3Config::addIgnore($1, false, *$3, $5->toUInt(), $7->toUInt()+1); }
|
||||
| vltOffFront yVLT_D_FILE yaSTRING yVLT_D_MATCH yaSTRING
|
||||
{ if (($1==V3ErrorCode::I_COVERAGE) || ($1==V3ErrorCode::I_TRACING)) {
|
||||
$<fl>1->v3error("Argument -match only supported for lint_off"<<endl);
|
||||
} else {
|
||||
V3Config::addWaiver($1,*$3,*$5);
|
||||
}}
|
||||
| vltOnFront { V3Config::addIgnore($1, true, "*", 0, 0); }
|
||||
| vltOnFront yVLT_D_FILE yaSTRING
|
||||
{ V3Config::addIgnore($1, true, *$3, 0, 0); }
|
||||
| vltOnFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM
|
||||
{ V3Config::addIgnore($1, true, *$3, $5->toUInt(), $5->toUInt()+1); }
|
||||
| vltOnFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM '-' yaINTNUM
|
||||
{ V3Config::addIgnore($1, true, *$3, $5->toUInt(), $7->toUInt()+1); }
|
||||
| vltVarAttrFront vltDModuleE vltDFTaskE vltVarAttrVarE attr_event_controlE
|
||||
{ V3Config::addVarAttr($<fl>1, *$2, *$3, *$4, $1, $5); }
|
||||
| vltInlineFront vltDModuleE vltDFTaskE
|
||||
{ V3Config::addInline($<fl>1, *$2, *$3, $1); }
|
||||
| yVLT_COVERAGE_BLOCK_OFF yVLT_D_FILE yaSTRING
|
||||
{ V3Config::addCoverageBlockOff(*$3, 0); }
|
||||
| yVLT_COVERAGE_BLOCK_OFF yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM
|
||||
{ V3Config::addCoverageBlockOff(*$3, $5->toUInt()); }
|
||||
| yVLT_COVERAGE_BLOCK_OFF yVLT_D_MODULE yaSTRING yVLT_D_BLOCK yaSTRING
|
||||
{ V3Config::addCoverageBlockOff(*$3, *$5); }
|
||||
| yVLT_FULL_CASE yVLT_D_FILE yaSTRING
|
||||
{ V3Config::addCaseFull(*$3, 0); }
|
||||
| yVLT_FULL_CASE yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM
|
||||
{ V3Config::addCaseFull(*$3, $5->toUInt()); }
|
||||
| yVLT_PARALLEL_CASE yVLT_D_FILE yaSTRING
|
||||
{ V3Config::addCaseParallel(*$3, 0); }
|
||||
| yVLT_PARALLEL_CASE yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM
|
||||
{ V3Config::addCaseParallel(*$3, $5->toUInt()); }
|
||||
;
|
||||
|
||||
vltOffFront<errcodeen>:
|
||||
@@ -5618,6 +5677,40 @@ vltOnFront<errcodeen>:
|
||||
if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown Error Code: "<<*$3<<endl); } }
|
||||
;
|
||||
|
||||
vltDModuleE<strp>:
|
||||
/* empty */ { static string unit = "__024unit"; $$ = &unit; }
|
||||
| yVLT_D_MODULE str { $$ = $2; }
|
||||
;
|
||||
|
||||
vltDFTaskE<strp>:
|
||||
/* empty */ { static string empty = ""; $$ = ∅ }
|
||||
| yVLT_D_FUNCTION str { $$ = $2; }
|
||||
| yVLT_D_TASK str { $$ = $2; }
|
||||
;
|
||||
|
||||
vltInlineFront<cbool>:
|
||||
yVLT_INLINE { $$ = true; }
|
||||
| yVLT_NO_INLINE { $$ = false; }
|
||||
;
|
||||
|
||||
vltVarAttrVarE<strp>:
|
||||
/* empty */ { static string empty = ""; $$ = ∅ }
|
||||
| yVLT_D_VAR str { $$ = $2; }
|
||||
;
|
||||
|
||||
vltVarAttrFront<attrtypeen>:
|
||||
yVLT_CLOCK_ENABLE { $$ = AstAttrType::VAR_CLOCK_ENABLE; }
|
||||
| yVLT_CLOCKER { $$ = AstAttrType::VAR_CLOCKER; }
|
||||
| yVLT_ISOLATE_ASSIGNMENTS { $$ = AstAttrType::VAR_ISOLATE_ASSIGNMENTS; }
|
||||
| yVLT_NO_CLOCKER { $$ = AstAttrType::VAR_NO_CLOCKER; }
|
||||
| yVLT_PUBLIC { $$ = AstAttrType::VAR_PUBLIC; v3Global.dpi(true); }
|
||||
| yVLT_PUBLIC_FLAT { $$ = AstAttrType::VAR_PUBLIC_FLAT; v3Global.dpi(true); }
|
||||
| yVLT_PUBLIC_FLAT_RD { $$ = AstAttrType::VAR_PUBLIC_FLAT_RD; v3Global.dpi(true); }
|
||||
| yVLT_PUBLIC_FLAT_RW { $$ = AstAttrType::VAR_PUBLIC_FLAT_RW; v3Global.dpi(true); }
|
||||
| yVLT_SC_BV { $$ = AstAttrType::VAR_SC_BV; }
|
||||
| yVLT_SFORMAT { $$ = AstAttrType::VAR_SFORMAT; }
|
||||
;
|
||||
|
||||
//**********************************************************************
|
||||
%%
|
||||
// For implementation functions see V3ParseGrammar.cpp
|
||||
|
||||
Reference in New Issue
Block a user