This commit is contained in:
parent
e6114b6bbb
commit
4080284e53
2
Changes
2
Changes
|
|
@ -59,6 +59,7 @@ Verilator 5.043 devel
|
|||
* Optimize inlining small C functions and add `-inline-cfuncs` (#6815). [Jose Drowne]
|
||||
* Fix generate function(s) inside of generate blocks (#1011) (#6789). [em2machine]
|
||||
* Fix typedef derived from type defined inside interface (#3441) (#6776). [em2machine]
|
||||
* Fix warning lint directive ordering and consistency (#4185) (#5368) (#5610) (#6876).
|
||||
* Fix extern function that returns parameterized class (#4924).
|
||||
* Fix type deduction for variable parameterized classes (#6281) (#6813). [em2machine]
|
||||
* Fix randomize called within func/task (#6144) (#6753). [Yilou Wang]
|
||||
|
|
@ -128,6 +129,7 @@ Verilator 5.043 devel
|
|||
* Fix `randc` on extended class (#6852).
|
||||
* Fix typedef `::` class reference error (#6862).
|
||||
* Fix missing include on FreeBSD (#6864).
|
||||
* Fix `--Wwarn-lint` to be inverse of `--Wno-lint`.
|
||||
|
||||
|
||||
Verilator 5.042 2025-11-02
|
||||
|
|
|
|||
|
|
@ -2410,14 +2410,8 @@ The grammar of control commands is as follows:
|
|||
(or wildcard with '\*' or '?', or all files if omitted) and range of
|
||||
line numbers (or all lines if omitted).
|
||||
|
||||
If a warning is disabled with lint_off, it will not be printed, even if the
|
||||
source contains a lint_on metacomment. The control file directives and
|
||||
metacomments are interpreted separately and do not interact. A warning is
|
||||
emitted only if not disabled either in a control file or via metacomments.
|
||||
|
||||
If the ``-rule`` is omitted, all lint warnings (see list in
|
||||
:vlopt:`-Wno-lint`) are enabled/disabled. This will override all later
|
||||
lint warning enables for the specified region.
|
||||
:vlopt:`-Wno-lint`) are enabled/disabled.
|
||||
|
||||
If ``-contents`` is provided, the input files must contain the given
|
||||
wildcard (with '\*' or '?'), and are waived in case they match, provided
|
||||
|
|
@ -2435,6 +2429,21 @@ The grammar of control commands is as follows:
|
|||
wildcard is compared across the entire multi-line message; see
|
||||
:vlopt:`--waiver-multiline`.
|
||||
|
||||
When there are overlapping conflicting lint_on/lint_off directives, they
|
||||
are resolved in the following priority order:
|
||||
|
||||
* All lint_on/lint_off without a ``-file``, or with a ``-file "\*"``,
|
||||
are processed in order of parsing.
|
||||
* All lint_on/lint_off with ``-file "non-\*"`` are processed in order of
|
||||
parsing.
|
||||
* All lint_off with ``--match`` in order of parsing.
|
||||
|
||||
If a warning is disabled with lint_off, it will not be printed, even if
|
||||
the source contains a lint_on metacomment. The control file directives
|
||||
and metacomments are interpreted separately and do not interact. A
|
||||
warning is emitted only if not disabled either in a control file or via
|
||||
metacomments.
|
||||
|
||||
Before version 4.026, ``-rule`` was named ``-msg``, and
|
||||
``-msg`` remained a deprecated alias until Version 5.000.
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ public:
|
|||
V3ControlWildcardResolver() = default;
|
||||
~V3ControlWildcardResolver() = default;
|
||||
|
||||
/// Update into maps from other
|
||||
// Update this resolved file's item map by inserting other's (wildcarded filename's) items
|
||||
void update(const V3ControlWildcardResolver& other) VL_MT_SAFE_EXCLUDES(m_mutex)
|
||||
VL_EXCLUDES(other.m_mutex) {
|
||||
V3LockGuard lock{m_mutex};
|
||||
|
|
@ -72,13 +72,15 @@ public:
|
|||
std::unique_ptr<T>& entryr = pair.first->second;
|
||||
// Resolve entry when first requested, cache the result
|
||||
if (pair.second) {
|
||||
// Update the entity with all matches in the patterns
|
||||
// Inserted: update the entity with all matches in the patterns
|
||||
for (const auto& patEnt : m_mapPatterns) {
|
||||
if (VString::wildmatch(name, patEnt.first)) {
|
||||
if (!entryr) entryr.reset(new T{});
|
||||
entryr->update(patEnt.second);
|
||||
}
|
||||
}
|
||||
// Perform final actions that needed all updates completed
|
||||
if (entryr) entryr->updateFinalize();
|
||||
}
|
||||
return entryr.get();
|
||||
}
|
||||
|
|
@ -95,6 +97,7 @@ public:
|
|||
m_attrs.reserve(m_attrs.size() + other.m_attrs.size());
|
||||
m_attrs.insert(m_attrs.end(), other.m_attrs.begin(), other.m_attrs.end());
|
||||
}
|
||||
void updateFinalize() {}
|
||||
// Apply all attributes to the variable
|
||||
void apply(AstVar* varp) const {
|
||||
for (const VAttrType attr : m_attrs) {
|
||||
|
|
@ -194,6 +197,7 @@ public:
|
|||
m_ports.update(f.m_ports);
|
||||
m_vars.update(f.m_vars);
|
||||
}
|
||||
void updateFinalize() {}
|
||||
|
||||
V3ControlVarResolver& params() { return m_params; }
|
||||
V3ControlVarResolver& ports() { return m_ports; }
|
||||
|
|
@ -245,6 +249,7 @@ public:
|
|||
m_modPragmas.insert(*it);
|
||||
}
|
||||
}
|
||||
void updateFinalize() {}
|
||||
|
||||
V3ControlFTaskResolver& ftasks() { return m_tasks; }
|
||||
V3ControlVarResolver& params() { return m_params; }
|
||||
|
|
@ -308,28 +313,220 @@ using V3ControlModuleResolver = V3ControlWildcardResolver<V3ControlModule>;
|
|||
// lint/coverage/tracing on/off
|
||||
class V3ControlIgnoresLine final {
|
||||
public:
|
||||
const int m_lineno; // Line number to make change at
|
||||
const int m_lineMin; // Minimum line number to make change at
|
||||
const int m_lineMax; // Maximum line number to make change at (inclusive)
|
||||
const V3ErrorCode m_code; // Error code
|
||||
const bool m_on; // True to enable message
|
||||
V3ControlIgnoresLine(V3ErrorCode code, int lineno, bool on)
|
||||
: m_lineno{lineno}
|
||||
V3ControlIgnoresLine(V3ErrorCode code, int linemin, int linemax, bool on)
|
||||
: m_lineMin{linemin}
|
||||
, m_lineMax{linemax}
|
||||
, m_code{code}
|
||||
, m_on{on} {}
|
||||
~V3ControlIgnoresLine() = default;
|
||||
bool operator<(const V3ControlIgnoresLine& 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);
|
||||
bool everyLine() const { return m_lineMin == 0 && m_lineMax == 0; }
|
||||
bool inRange(int lineno) const {
|
||||
return (lineno >= m_lineMin && lineno <= m_lineMax) || everyLine();
|
||||
}
|
||||
};
|
||||
std::ostream& operator<<(std::ostream& os, const V3ControlIgnoresLine& rhs) {
|
||||
return os << rhs.m_lineno << ", " << rhs.m_code << ", " << rhs.m_on;
|
||||
return os << rhs.m_lineMin << "-" << rhs.m_lineMax << ", " << rhs.m_code << ", " << rhs.m_on;
|
||||
}
|
||||
|
||||
// Ignore line settings, index is parse order
|
||||
// Single global deque to avoid copying when update()
|
||||
static std::vector<V3ControlIgnoresLine> controlIgnLines;
|
||||
|
||||
using IgnIndices = std::vector<uint32_t>; // List of {s_ignLines indces}
|
||||
|
||||
class VIntervalTree final {
|
||||
struct Entry final {
|
||||
// Classic centered interval tree, referencing an index to controlIgnLines
|
||||
int m_center; // Line number of central point
|
||||
std::unique_ptr<Entry> m_leftp; // Entry with all its rules/entries < this center
|
||||
std::unique_ptr<Entry> m_rightp; // Entry with all its rules/entries > this center
|
||||
IgnIndices m_byMin; // Rules overlapping center sorted by min line number
|
||||
IgnIndices m_byMax; // Rules overlapping center sorted by max line number
|
||||
explicit Entry(int center)
|
||||
: m_center{center} {}
|
||||
};
|
||||
|
||||
std::unique_ptr<Entry> m_rootp; // Root of interval tree
|
||||
IgnIndices m_everyLines; // All-line disables
|
||||
|
||||
private:
|
||||
std::unique_ptr<Entry> buildTree(const IgnIndices& points) {
|
||||
if (points.empty()) return nullptr;
|
||||
|
||||
int minval = std::numeric_limits<int>::max();
|
||||
int maxval = std::numeric_limits<int>::min();
|
||||
for (const auto& it : points) {
|
||||
const V3ControlIgnoresLine& cign = controlIgnLines[it];
|
||||
if (cign.everyLine()) {
|
||||
m_everyLines.emplace_back(it);
|
||||
continue;
|
||||
}
|
||||
minval = std::min(minval, cign.m_lineMin);
|
||||
maxval = std::max(maxval, cign.m_lineMax);
|
||||
}
|
||||
|
||||
int center = minval + (maxval - minval) / 2;
|
||||
auto entp = std::unique_ptr<Entry>(new Entry{center});
|
||||
|
||||
IgnIndices leftPoints, rightPoints;
|
||||
for (const auto& it : points) {
|
||||
const V3ControlIgnoresLine& cign = controlIgnLines[it];
|
||||
if (cign.everyLine()) continue;
|
||||
// UINFO(9, "Inserting for center " << center << " point " << it);
|
||||
if (cign.m_lineMax < center)
|
||||
leftPoints.emplace_back(it);
|
||||
else if (cign.m_lineMin > center)
|
||||
rightPoints.emplace_back(it);
|
||||
else {
|
||||
entp->m_byMin.push_back(it);
|
||||
entp->m_byMax.push_back(it);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(entp->m_byMin.begin(), entp->m_byMin.end(), [](uint32_t a, uint32_t b) {
|
||||
return controlIgnLines[a].m_lineMin < controlIgnLines[b].m_lineMin;
|
||||
});
|
||||
std::sort(entp->m_byMax.begin(), entp->m_byMax.end(), [](uint32_t a, uint32_t b) {
|
||||
return controlIgnLines[a].m_lineMax > controlIgnLines[b].m_lineMax;
|
||||
});
|
||||
|
||||
entp->m_leftp = buildTree(leftPoints);
|
||||
entp->m_rightp = buildTree(rightPoints);
|
||||
return entp;
|
||||
}
|
||||
|
||||
void findTree(int lineno, Entry* entp, IgnIndices& resultsr, int& nextChanger) const {
|
||||
// UINFO(9, "Find " << lineno << " center " << entp->m_center);
|
||||
if (lineno < entp->m_center) {
|
||||
nextChanger = std::min(nextChanger, entp->m_center);
|
||||
for (const auto& it : entp->m_byMin) {
|
||||
const V3ControlIgnoresLine& cign = controlIgnLines[it];
|
||||
if (cign.m_lineMin <= lineno) {
|
||||
resultsr.emplace_back(it);
|
||||
} else {
|
||||
nextChanger = std::min(nextChanger, cign.m_lineMin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (entp->m_leftp) findTree(lineno, entp->m_leftp.get(), resultsr, nextChanger);
|
||||
} else if (lineno > entp->m_center) {
|
||||
for (const auto& it : entp->m_byMax) {
|
||||
const V3ControlIgnoresLine& cign = controlIgnLines[it];
|
||||
if (cign.m_lineMax >= lineno) {
|
||||
nextChanger = std::min(nextChanger, cign.m_lineMax + 1);
|
||||
resultsr.emplace_back(it);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (entp->m_rightp) findTree(lineno, entp->m_rightp.get(), resultsr, nextChanger);
|
||||
} else {
|
||||
for (const auto& it : entp->m_byMin) {
|
||||
const V3ControlIgnoresLine& cign = controlIgnLines[it];
|
||||
resultsr.emplace_back(it);
|
||||
if (cign.m_lineMax >= lineno)
|
||||
nextChanger = std::min(nextChanger, cign.m_lineMax + 1);
|
||||
}
|
||||
if (entp->m_leftp) findTree(lineno, entp->m_leftp.get(), resultsr, nextChanger);
|
||||
if (entp->m_rightp) findTree(lineno, entp->m_rightp.get(), resultsr, nextChanger);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VIntervalTree() {}
|
||||
~VIntervalTree() = default;
|
||||
// METHODS
|
||||
void clear() { m_rootp = nullptr; }
|
||||
void build(const IgnIndices& points) {
|
||||
clear();
|
||||
m_rootp = buildTree(points);
|
||||
}
|
||||
void find(int lineno, IgnIndices& resultsr, int& nextChanger) const {
|
||||
resultsr = m_everyLines;
|
||||
nextChanger = std::numeric_limits<int>::max();
|
||||
|
||||
if (m_rootp) findTree(lineno, m_rootp.get(), resultsr, nextChanger);
|
||||
// Sort indices, so can process in parse order
|
||||
std::sort(resultsr.begin(), resultsr.end());
|
||||
}
|
||||
|
||||
static void selfTest() {
|
||||
// 0 10 20 30 40 50
|
||||
// i0: . 10-10 . . . .
|
||||
// i1: . . 20-20 . . .
|
||||
// i2: . . . . 40-40 .
|
||||
// i3: . 10------------30 . .
|
||||
// i4: . . 20------------40 .
|
||||
// i5:(below) 0---------------------------------------0
|
||||
IgnIndices data;
|
||||
std::vector<std::pair<int, int>> points
|
||||
= {{10, 10}, {20, 20}, {40, 40}, {10, 30}, {20, 40}};
|
||||
for (auto& it : points) {
|
||||
controlIgnLines.emplace_back(
|
||||
V3ControlIgnoresLine{V3ErrorCode::I_LINT, it.first, it.second, true});
|
||||
data.emplace_back(static_cast<uint32_t>(controlIgnLines.size() - 1));
|
||||
}
|
||||
VIntervalTree tree;
|
||||
tree.build(data);
|
||||
|
||||
IgnIndices results;
|
||||
int nextChange = 0;
|
||||
tree.find(0, results, nextChange);
|
||||
UASSERT_SELFTEST(size_t, results.size(), 0);
|
||||
UASSERT_SELFTEST(int, nextChange, 10);
|
||||
tree.find(10, results, nextChange);
|
||||
UASSERT_SELFTEST(size_t, results.size(), 2);
|
||||
UASSERT_SELFTEST(int, results[0], 0);
|
||||
UASSERT_SELFTEST(int, results[1], 3);
|
||||
UASSERT_SELFTEST(int, nextChange, 11);
|
||||
tree.find(11, results, nextChange);
|
||||
UASSERT_SELFTEST(size_t, results.size(), 1);
|
||||
UASSERT_SELFTEST(int, results[0], 3);
|
||||
UASSERT_SELFTEST(int, nextChange, 15); // Center, or would be 20
|
||||
tree.find(20, results, nextChange);
|
||||
UASSERT_SELFTEST(size_t, results.size(), 3);
|
||||
UASSERT_SELFTEST(int, results[0], 1);
|
||||
UASSERT_SELFTEST(int, results[1], 3);
|
||||
UASSERT_SELFTEST(int, results[2], 4);
|
||||
UASSERT_SELFTEST(int, nextChange, 21);
|
||||
tree.find(21, results, nextChange);
|
||||
UASSERT_SELFTEST(size_t, results.size(), 2);
|
||||
UASSERT_SELFTEST(int, results[0], 3);
|
||||
UASSERT_SELFTEST(int, results[1], 4);
|
||||
UASSERT_SELFTEST(int, nextChange, 25); // Center, or would be 30
|
||||
tree.find(30, results, nextChange);
|
||||
UASSERT_SELFTEST(size_t, results.size(), 2);
|
||||
UASSERT_SELFTEST(int, results[0], 3);
|
||||
UASSERT_SELFTEST(int, results[1], 4);
|
||||
UASSERT_SELFTEST(int, nextChange, 31);
|
||||
tree.find(40, results, nextChange);
|
||||
UASSERT_SELFTEST(size_t, results.size(), 2);
|
||||
UASSERT_SELFTEST(int, results[0], 2);
|
||||
UASSERT_SELFTEST(int, results[1], 4);
|
||||
UASSERT_SELFTEST(int, nextChange, 41);
|
||||
tree.find(41, results, nextChange);
|
||||
UASSERT_SELFTEST(size_t, results.size(), 0);
|
||||
UASSERT_SELFTEST(int, nextChange, std::numeric_limits<int>::max());
|
||||
//
|
||||
points = {{0, 0}};
|
||||
for (auto& it : points) {
|
||||
controlIgnLines.emplace_back(
|
||||
V3ControlIgnoresLine{V3ErrorCode::I_LINT, it.first, it.second, true});
|
||||
data.emplace_back(static_cast<uint32_t>(controlIgnLines.size() - 1));
|
||||
}
|
||||
tree.build(data);
|
||||
//
|
||||
tree.find(50, results, nextChange);
|
||||
UASSERT_SELFTEST(size_t, results.size(), 1);
|
||||
UASSERT_SELFTEST(int, results[0], 5);
|
||||
}
|
||||
};
|
||||
|
||||
// Some attributes are attached to entities of the occur on a fileline
|
||||
// and multiple attributes can be attached to a line
|
||||
using V3ControlLineAttribute = std::bitset<VPragmaType::_ENUM_SIZE>;
|
||||
|
|
@ -355,16 +552,17 @@ public:
|
|||
// File entity
|
||||
class V3ControlFile final {
|
||||
using LineAttrMap = std::map<int, V3ControlLineAttribute>; // Map line->bitset of attributes
|
||||
using IgnLines = std::multiset<V3ControlIgnoresLine>; // list of {line,code,on}
|
||||
using Waivers = std::vector<WaiverSetting>; // List of {code,wildcard string}
|
||||
|
||||
LineAttrMap m_lineAttrs; // Attributes to line mapping
|
||||
IgnLines m_ignLines; // Ignore line settings
|
||||
IgnIndices m_ignIndices; // s_ignLines that apply to this specific file
|
||||
Waivers m_waivers; // Waive messages
|
||||
VIntervalTree m_intervalTree; // Tree of indices to IgnLines
|
||||
|
||||
struct {
|
||||
int lineno; // Last line number
|
||||
IgnLines::const_iterator it; // Point with next linenumber > current line number
|
||||
int filenameno = -1; // Last filename
|
||||
int lineno = -1; // Last linenumber
|
||||
int nextChange = -1; // Line number of next change
|
||||
} m_lastIgnore; // Last ignore line run
|
||||
|
||||
// Match a given line and attribute to the map, line 0 is any
|
||||
|
|
@ -375,24 +573,24 @@ class V3ControlFile final {
|
|||
}
|
||||
|
||||
public:
|
||||
V3ControlFile() {
|
||||
m_lastIgnore.lineno = -1;
|
||||
m_lastIgnore.it = m_ignLines.begin();
|
||||
}
|
||||
V3ControlFile() {}
|
||||
void update(const V3ControlFile& file) {
|
||||
// Copy in all Attributes
|
||||
// Copy in all attributes and waivers
|
||||
for (const auto& itr : file.m_lineAttrs) m_lineAttrs[itr.first] |= itr.second;
|
||||
// Copy in all ignores
|
||||
for (const auto& ignLine : file.m_ignLines) m_ignLines.insert(ignLine);
|
||||
// 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());
|
||||
// Copy in all ignore references
|
||||
m_ignIndices.reserve(m_ignIndices.size() + file.m_ignIndices.size());
|
||||
m_ignIndices.insert(m_ignIndices.end(), file.m_ignIndices.begin(),
|
||||
file.m_ignIndices.end());
|
||||
// updateFinalize() will soon build tree
|
||||
}
|
||||
void updateFinalize() { m_intervalTree.build(m_ignIndices); }
|
||||
void addLineAttribute(int lineno, VPragmaType attr) { m_lineAttrs[lineno].set(attr); }
|
||||
void addIgnore(V3ErrorCode code, int lineno, bool on) {
|
||||
m_ignLines.insert(V3ControlIgnoresLine{code, lineno, on});
|
||||
m_lastIgnore.it = m_ignLines.begin();
|
||||
void addIgnore(V3ErrorCode code, int min, int max, bool on) {
|
||||
controlIgnLines.emplace_back(V3ControlIgnoresLine{code, min, max, on});
|
||||
m_ignIndices.emplace_back(static_cast<uint32_t>(controlIgnLines.size() - 1));
|
||||
m_lastIgnore.nextChange = -1;
|
||||
}
|
||||
void addIgnoreMatch(V3ErrorCode code, const string& contents, const string& match) {
|
||||
// Since Verilator 5.031 the error message compared has context, so
|
||||
|
|
@ -425,22 +623,41 @@ public:
|
|||
}
|
||||
void applyIgnores(FileLine* filelinep) {
|
||||
// HOT routine, called each parsed token line of this filename
|
||||
if (m_lastIgnore.lineno != filelinep->lineno()) {
|
||||
// UINFO(9, " ApplyIgnores for " << filelinep->ascii());
|
||||
// Process all on/offs for lines up to and including the current line
|
||||
const int curlineno = filelinep->lastLineno();
|
||||
for (; m_lastIgnore.it != m_ignLines.end(); ++m_lastIgnore.it) {
|
||||
if (m_lastIgnore.it->m_lineno > curlineno) break;
|
||||
// UINFO(9, " Hit " << *m_lastIgnore.it);
|
||||
filelinep->warnOnCtrl(m_lastIgnore.it->m_code, m_lastIgnore.it->m_on);
|
||||
}
|
||||
if (false && debug() >= 9) {
|
||||
for (IgnLines::const_iterator it = m_lastIgnore.it; it != m_ignLines.end(); ++it) {
|
||||
UINFO(9, " NXT " << *it);
|
||||
}
|
||||
}
|
||||
m_lastIgnore.lineno = filelinep->lastLineno();
|
||||
if (filelinep->filenameno() == m_lastIgnore.filenameno
|
||||
&& filelinep->lineno() == m_lastIgnore.lineno)
|
||||
return; // Short circuit, no change, no debug
|
||||
// For speed, compute line number of next potential change, and skip if before then
|
||||
if (filelinep->filenameno() == m_lastIgnore.filenameno
|
||||
&& filelinep->lineno() < m_lastIgnore.nextChange) {
|
||||
m_lastIgnore.lineno = filelinep->lineno();
|
||||
UINFO(9, " ApplyIgnores for " << filelinep->ascii() << " (no change predicted)");
|
||||
return;
|
||||
}
|
||||
UINFO(9, " ApplyIgnores for " << filelinep->ascii());
|
||||
m_lastIgnore.filenameno = filelinep->filenameno();
|
||||
m_lastIgnore.lineno = filelinep->lineno();
|
||||
m_lastIgnore.nextChange = std::numeric_limits<int>::max();
|
||||
|
||||
// Find all on/offs. Unlike lint pragmas we calculate the entire
|
||||
// bitset of errors to enable, instead of individual enable/disable changes.
|
||||
IgnIndices results;
|
||||
m_intervalTree.find(filelinep->lineno(), results /*ref*/, m_lastIgnore.nextChange /*ref*/);
|
||||
// Process all on/offs for lines up to and including the current line
|
||||
VErrorBitSet bitset{VErrorBitSet::AllOnes{}};
|
||||
for (const auto& it : results) {
|
||||
const V3ControlIgnoresLine& cign = controlIgnLines[it];
|
||||
UASSERT(cign.inRange(filelinep->lineno()),
|
||||
"Interval tree returned lines outside range");
|
||||
UINFO(9, " Hit " << cign);
|
||||
cign.m_code.forDelegateCodes(
|
||||
[&](V3ErrorCode subcode) { bitset.set(subcode, cign.m_on); });
|
||||
}
|
||||
|
||||
filelinep->warnSetCtrlBitSet(bitset);
|
||||
m_lastIgnore.nextChange = std::max(m_lastIgnore.nextChange, filelinep->lineno() + 1);
|
||||
UINFO(9, " AppliedIgnores " << filelinep << " next@ln " << std::dec
|
||||
<< m_lastIgnore.nextChange
|
||||
<< " Messages: " << bitset.ascii());
|
||||
}
|
||||
bool waive(V3ErrorCode code, const string& message) {
|
||||
if (code.hardError()) return false;
|
||||
|
|
@ -648,17 +865,14 @@ void V3Control::addCaseFull(const string& filename, int lineno) {
|
|||
V3ControlFile& file = V3ControlResolver::s().files().at(filename);
|
||||
file.addLineAttribute(lineno, VPragmaType::FULL_CASE);
|
||||
}
|
||||
|
||||
void V3Control::addCaseParallel(const string& filename, int lineno) {
|
||||
V3ControlFile& file = V3ControlResolver::s().files().at(filename);
|
||||
file.addLineAttribute(lineno, VPragmaType::PARALLEL_CASE);
|
||||
}
|
||||
|
||||
void V3Control::addCoverageBlockOff(const string& filename, int lineno) {
|
||||
V3ControlFile& file = V3ControlResolver::s().files().at(filename);
|
||||
file.addLineAttribute(lineno, VPragmaType::COVERAGE_BLOCK_OFF);
|
||||
}
|
||||
|
||||
void V3Control::addCoverageBlockOff(const string& module, const string& blockname) {
|
||||
V3ControlResolver::s().modules().at(module).addCoverageBlockOff(blockname);
|
||||
}
|
||||
|
|
@ -668,16 +882,16 @@ void V3Control::addHierWorkers(FileLine* fl, const string& model, int workers) {
|
|||
}
|
||||
|
||||
void V3Control::addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max) {
|
||||
if (filename == "*") {
|
||||
UINFO(9, "addIgnore " << code << " " << min << "-" << max << " fn=" << filename);
|
||||
if (filename == "*") { // For "lint_off/lint_on [--rule x]"
|
||||
FileLine::globalWarnOff(code, !on);
|
||||
} else {
|
||||
V3ControlResolver::s().files().at(filename).addIgnore(code, min, on);
|
||||
if (max) V3ControlResolver::s().files().at(filename).addIgnore(code, max, !on);
|
||||
} else { // For "lint_off/lint_on [--rule x] --file y [-lines min[-max]]"
|
||||
V3ControlResolver::s().files().at(filename).addIgnore(code, min, max, on);
|
||||
}
|
||||
}
|
||||
|
||||
void V3Control::addIgnoreMatch(V3ErrorCode code, const string& filename, const string& contents,
|
||||
const string& match) {
|
||||
// For "lint_off --rule x --file y --match z", no support for lint_on
|
||||
V3ControlResolver::s().files().at(filename).addIgnoreMatch(code, contents, match);
|
||||
}
|
||||
|
||||
|
|
@ -700,7 +914,6 @@ void V3Control::addModulePragma(const string& module, VPragmaType pragma) {
|
|||
void V3Control::addProfileData(FileLine* fl, const string& hierDpi, uint64_t cost) {
|
||||
V3ControlResolver::s().addProfileData(fl, hierDpi, cost);
|
||||
}
|
||||
|
||||
void V3Control::addProfileData(FileLine* fl, const string& model, const string& key,
|
||||
uint64_t cost) {
|
||||
V3ControlResolver::s().addProfileData(fl, model, key, cost);
|
||||
|
|
@ -796,7 +1009,6 @@ void V3Control::applyCoverageBlock(AstNodeModule* modulep, AstBegin* nodep) {
|
|||
V3ControlModule* const modp = V3ControlResolver::s().modules().resolve(modname);
|
||||
if (modp) modp->applyBlock(nodep);
|
||||
}
|
||||
|
||||
void V3Control::applyCoverageBlock(AstNodeModule* modulep, AstGenBlock* nodep) {
|
||||
const string& filename = nodep->fileline()->filename();
|
||||
V3ControlFile* const filep = V3ControlResolver::s().files().resolve(filename);
|
||||
|
|
@ -885,3 +1097,5 @@ bool V3Control::waive(const FileLine* filelinep, V3ErrorCode code, const string&
|
|||
if (!filep) return false;
|
||||
return filep->waive(code, message);
|
||||
}
|
||||
|
||||
void V3Control::selfTest() { VIntervalTree::selfTest(); }
|
||||
|
|
|
|||
|
|
@ -75,6 +75,8 @@ public:
|
|||
static uint64_t getCurrentHierBlockCost();
|
||||
|
||||
static bool waive(const FileLine* filelinep, V3ErrorCode code, const string& message);
|
||||
|
||||
static void selfTest();
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -272,15 +272,15 @@ public:
|
|||
return (pretendError() || m_e == EC_FATALSRC || m_e == SIDEEFFECT || m_e == SYMRSVDWORD
|
||||
|| m_e == ZERODLY);
|
||||
}
|
||||
// Warnings that are lint only
|
||||
// Warnings that are lint only; includes all style warnings
|
||||
bool lintError() const VL_MT_SAFE {
|
||||
return (m_e == ALWCOMBORDER || m_e == ASCRANGE || m_e == ASSIGNEQEXPR || m_e == BSSPACE
|
||||
|| m_e == CASEINCOMPLETE || m_e == CASEOVERLAP || m_e == CASEWITHX || m_e == CASEX
|
||||
|| m_e == CASTCONST || m_e == CMPCONST || m_e == COLONPLUS || m_e == IMPLICIT
|
||||
|| m_e == IMPLICITSTATIC || m_e == LATCH || m_e == MISINDENT || m_e == NEWERSTD
|
||||
|| m_e == PREPROCZERO || m_e == PINMISSING || m_e == REALCVT || m_e == STATICVAR
|
||||
|| m_e == UNSIGNED || m_e == WIDTH || m_e == WIDTHTRUNC || m_e == WIDTHEXPAND
|
||||
|| m_e == WIDTHXZEXPAND);
|
||||
return (styleError() || m_e == ALWCOMBORDER || m_e == ASCRANGE || m_e == ASSIGNEQEXPR
|
||||
|| m_e == BSSPACE || m_e == CASEINCOMPLETE || m_e == CASEOVERLAP
|
||||
|| m_e == CASEWITHX || m_e == CASEX || m_e == CASTCONST || m_e == CMPCONST
|
||||
|| m_e == COLONPLUS || m_e == IMPLICIT || m_e == IMPLICITSTATIC || m_e == LATCH
|
||||
|| m_e == MISINDENT || m_e == NEWERSTD || m_e == PREPROCZERO || m_e == PINMISSING
|
||||
|| m_e == REALCVT || m_e == STATICVAR || m_e == UNSIGNED || m_e == WIDTH
|
||||
|| m_e == WIDTHTRUNC || m_e == WIDTHEXPAND || m_e == WIDTHXZEXPAND);
|
||||
}
|
||||
// Warnings that are style only
|
||||
bool styleError() const VL_MT_SAFE {
|
||||
|
|
@ -313,6 +313,18 @@ public:
|
|||
action(V3ErrorCode{COVERIGN});
|
||||
action(V3ErrorCode{SPECIFYIGN});
|
||||
return;
|
||||
case V3ErrorCode::I_LINT:
|
||||
for (int i = V3ErrorCode::EC_MIN; i < V3ErrorCode::_ENUM_MAX; ++i) {
|
||||
const V3ErrorCode subcode{i};
|
||||
if (subcode.lintError()) action(subcode);
|
||||
}
|
||||
return;
|
||||
case V3ErrorCode::I_STYLE:
|
||||
for (int i = V3ErrorCode::EC_MIN; i < V3ErrorCode::_ENUM_MAX; ++i) {
|
||||
const V3ErrorCode subcode{i};
|
||||
if (subcode.styleError()) action(subcode);
|
||||
}
|
||||
return;
|
||||
case V3ErrorCode::UNUSED:
|
||||
action(V3ErrorCode{UNUSEDGENVAR});
|
||||
action(V3ErrorCode{UNUSEDLOOP});
|
||||
|
|
@ -333,6 +345,8 @@ public:
|
|||
switch (other) {
|
||||
case V3ErrorCode::E_UNSUPPORTED:
|
||||
return m_e == E_UNSUPPORTED || m_e == COVERIGN || m_e == SPECIFYIGN;
|
||||
case V3ErrorCode::I_LINT: return lintError();
|
||||
case V3ErrorCode::I_STYLE: return styleError();
|
||||
case V3ErrorCode::UNUSED:
|
||||
return m_e == UNUSEDGENVAR || m_e == UNUSEDLOOP || m_e == UNUSEDPARAM
|
||||
|| m_e == UNUSEDSIGNAL;
|
||||
|
|
@ -361,7 +375,9 @@ class VErrorBitSet final {
|
|||
: m_bitset{lhs.m_bitset & rhs.m_bitset} {}
|
||||
|
||||
public:
|
||||
class AllOnes {};
|
||||
VErrorBitSet() {}
|
||||
explicit VErrorBitSet(AllOnes) { m_bitset.set(); }
|
||||
~VErrorBitSet() = default;
|
||||
bool test(V3ErrorCode code) const { return m_bitset[code]; }
|
||||
void set(V3ErrorCode code, bool flag) { m_bitset[code] = flag; }
|
||||
|
|
@ -371,6 +387,13 @@ public:
|
|||
}
|
||||
VErrorBitSet operator&(const VErrorBitSet& rhs) const { return VErrorBitSet{*this, rhs}; }
|
||||
bool operator==(const VErrorBitSet& rhs) const { return m_bitset == rhs.m_bitset; }
|
||||
string ascii() const { // LCOV_EXCL_START
|
||||
string result;
|
||||
for (int i = V3ErrorCode::EC_MIN; i < V3ErrorCode::_ENUM_MAX; ++i) {
|
||||
if (!test(V3ErrorCode{i})) result += " !"s + V3ErrorCode{i}.ascii();
|
||||
}
|
||||
return result;
|
||||
} // LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ FileLineSingleton::msgEnSetIdx_t FileLineSingleton::defaultMsgEnIndex() VL_MT_SA
|
|||
// "-Wall" and the like only adjust the code subset, so use default enablement there
|
||||
msgEnBitSet.set(MsgEnBitSet::Subset::CODE, code, !code.defaultsOff());
|
||||
// The control file subset is only adjusted by the control files, everything enabled by
|
||||
// default
|
||||
// default. (V3Control also likewise creates with this)
|
||||
msgEnBitSet.set(MsgEnBitSet::Subset::CTRL, code, true);
|
||||
}
|
||||
return addMsgEnBitSet(msgEnBitSet);
|
||||
|
|
@ -145,12 +145,23 @@ FileLineSingleton::msgEnSetIdx_t FileLineSingleton::msgEnSetBit(msgEnSetIdx_t se
|
|||
if (msgEn(setIdx).test(subset, subcode) != value) same = false;
|
||||
});
|
||||
if (same) return setIdx;
|
||||
// Make new mask of all delegated codes at once (to avoid extra indicies if looped above this)
|
||||
// Make new mask of all delegated codes at once (to avoid extra indices if looped above this)
|
||||
MsgEnBitSet msgEnBitSet{msgEn(setIdx)};
|
||||
code.forDelegateCodes([&](V3ErrorCode subcode) { msgEnBitSet.set(subset, subcode, value); });
|
||||
return addMsgEnBitSet(msgEnBitSet);
|
||||
}
|
||||
|
||||
FileLineSingleton::msgEnSetIdx_t FileLineSingleton::msgSetCtrlBitSet(msgEnSetIdx_t setIdx,
|
||||
const VErrorBitSet& bitset) {
|
||||
const MsgEnBitSet::Subset subset = MsgEnBitSet::Subset::CTRL;
|
||||
// See if state matches existing
|
||||
if (msgEn(setIdx).getAll(subset) == bitset) return setIdx;
|
||||
// Make new mask of all delegated codes at once (to avoid extra indices if looped above this)
|
||||
MsgEnBitSet msgEnBitSet{msgEn(setIdx)};
|
||||
msgEnBitSet.setAll(subset, bitset);
|
||||
return addMsgEnBitSet(msgEnBitSet);
|
||||
}
|
||||
|
||||
FileLineSingleton::msgEnSetIdx_t FileLineSingleton::msgEnAnd(msgEnSetIdx_t lhsIdx,
|
||||
msgEnSetIdx_t rhsIdx) {
|
||||
const MsgEnBitSet& lhs = msgEn(lhsIdx);
|
||||
|
|
@ -395,26 +406,9 @@ string FileLine::warnOffParse(const string& msgs, bool turnOff) {
|
|||
return result;
|
||||
}
|
||||
|
||||
void FileLine::warnLintOff(bool turnOff) {
|
||||
for (int codei = V3ErrorCode::EC_MIN; codei < V3ErrorCode::_ENUM_MAX; codei++) {
|
||||
const V3ErrorCode code{codei};
|
||||
if (code.lintError()) warnOff(code, turnOff);
|
||||
}
|
||||
}
|
||||
|
||||
void FileLine::warnStyleOff(bool turnOff) {
|
||||
for (int codei = V3ErrorCode::EC_MIN; codei < V3ErrorCode::_ENUM_MAX; codei++) {
|
||||
const V3ErrorCode code{codei};
|
||||
if (code.styleError()) warnOff(code, turnOff);
|
||||
}
|
||||
}
|
||||
|
||||
bool FileLine::warnIsOff(V3ErrorCode code) const {
|
||||
if (!msgEn().enabled(code)) return true;
|
||||
if (!defaultFileLine().msgEn().enabled(code)) return true; // Global overrides local
|
||||
if ((code.lintError() || code.styleError()) && !msgEn().enabled(V3ErrorCode::I_LINT)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -81,9 +81,19 @@ class FileLineSingleton final {
|
|||
return m_codeEn == other.m_codeEn && m_ctrlEn == other.m_ctrlEn;
|
||||
}
|
||||
|
||||
const VErrorBitSet& getAll(Subset subset) const {
|
||||
return subset == Subset::CODE ? m_codeEn : m_ctrlEn;
|
||||
}
|
||||
bool test(Subset subset, V3ErrorCode code) const {
|
||||
return subset == Subset::CODE ? m_codeEn.test(code) : m_ctrlEn.test(code);
|
||||
}
|
||||
void setAll(Subset subset, const VErrorBitSet& bitset) {
|
||||
if (subset == Subset::CODE) { // LCOV_EXCL_BR_LINE
|
||||
m_codeEn = bitset; // LCOV_EXCL_LINE
|
||||
} else {
|
||||
m_ctrlEn = bitset;
|
||||
}
|
||||
}
|
||||
void set(Subset subset, V3ErrorCode code, bool value) {
|
||||
if (subset == Subset::CODE) {
|
||||
m_codeEn.set(code, value);
|
||||
|
|
@ -136,6 +146,8 @@ class FileLineSingleton final {
|
|||
// Set code to value in bitset at interned index setIdx, return interned index of result
|
||||
msgEnSetIdx_t msgEnSetBit(msgEnSetIdx_t setIdx, MsgEnBitSet::Subset subset, V3ErrorCode code,
|
||||
bool value);
|
||||
// Bulk-set all control codes to given bitset
|
||||
msgEnSetIdx_t msgSetCtrlBitSet(msgEnSetIdx_t setIdx, const VErrorBitSet& bitset);
|
||||
// Return index to intersection set
|
||||
msgEnSetIdx_t msgEnAnd(msgEnSetIdx_t lhsIdx, msgEnSetIdx_t rhsIdx);
|
||||
// Retrieve interned bitset at given interned index. The returned reference is not persistent.
|
||||
|
|
@ -367,8 +379,8 @@ private:
|
|||
|
||||
public:
|
||||
void warnOn(V3ErrorCode code, bool flag) { warnSet(MsgEnBitSet::Subset::CODE, code, flag); }
|
||||
void warnOnCtrl(V3ErrorCode code, bool flag) {
|
||||
warnSet(MsgEnBitSet::Subset::CTRL, code, flag);
|
||||
void warnSetCtrlBitSet(const VErrorBitSet& bitset) {
|
||||
m_msgEnIdx = singleton().msgSetCtrlBitSet(m_msgEnIdx, bitset);
|
||||
}
|
||||
void warnOff(V3ErrorCode code, bool turnOff) { warnOn(code, !turnOff); }
|
||||
string warnOffParse(const string& msgs, bool turnOff); // Returns "" if ok
|
||||
|
|
@ -392,8 +404,6 @@ public:
|
|||
// <command-line> and <built-in> match what GCC outputs
|
||||
static string commandLineFilename() VL_MT_SAFE { return "<command-line>"; }
|
||||
static string builtInFilename() VL_MT_SAFE { return "<built-in>"; }
|
||||
static void globalWarnLintOff(bool turnOff) { defaultFileLine().warnLintOff(turnOff); }
|
||||
static void globalWarnStyleOff(bool turnOff) { defaultFileLine().warnStyleOff(turnOff); }
|
||||
static void globalWarnOff(V3ErrorCode code, bool turnOff) {
|
||||
defaultFileLine().warnOff(code, turnOff);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1859,10 +1859,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
|
|||
});
|
||||
DECL_OPTION("-vpi", OnOff, &m_vpi);
|
||||
|
||||
DECL_OPTION("-Wall", CbCall, []() {
|
||||
FileLine::globalWarnLintOff(false);
|
||||
FileLine::globalWarnStyleOff(false);
|
||||
});
|
||||
DECL_OPTION("-Wall", CbCall, []() { FileLine::globalWarnOff(V3ErrorCode::I_LINT, false); });
|
||||
DECL_OPTION("-Werror-", CbPartialMatch, [this, fl](const char* optp) {
|
||||
const V3ErrorCode code{optp};
|
||||
if (code == V3ErrorCode::EC_ERROR) {
|
||||
|
|
@ -1890,11 +1887,9 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
|
|||
}
|
||||
DECL_OPTION("-Wno-context", CbCall, [this]() { m_context = false; });
|
||||
DECL_OPTION("-Wno-fatal", CbCall, []() { V3Error::warnFatal(false); });
|
||||
DECL_OPTION("-Wno-lint", CbCall, []() {
|
||||
FileLine::globalWarnLintOff(true);
|
||||
FileLine::globalWarnStyleOff(true);
|
||||
});
|
||||
DECL_OPTION("-Wno-style", CbCall, []() { FileLine::globalWarnStyleOff(true); });
|
||||
DECL_OPTION("-Wno-lint", CbCall, []() { FileLine::globalWarnOff(V3ErrorCode::I_LINT, true); });
|
||||
DECL_OPTION("-Wno-style", CbCall,
|
||||
[]() { FileLine::globalWarnOff(V3ErrorCode::I_STYLE, true); });
|
||||
DECL_OPTION("-work", Set, &m_work);
|
||||
DECL_OPTION("-Wpedantic", CbCall, [this]() {
|
||||
m_pedantic = true;
|
||||
|
|
@ -1913,8 +1908,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
|
|||
V3Error::pretendError(code, false);
|
||||
}
|
||||
});
|
||||
DECL_OPTION("-Wwarn-lint", CbCall, []() { FileLine::globalWarnLintOff(false); });
|
||||
DECL_OPTION("-Wwarn-style", CbCall, []() { FileLine::globalWarnStyleOff(false); });
|
||||
DECL_OPTION("-Wwarn-lint", CbCall,
|
||||
[]() { FileLine::globalWarnOff(V3ErrorCode::I_LINT, false); });
|
||||
DECL_OPTION("-Wwarn-style", CbCall,
|
||||
[]() { FileLine::globalWarnOff(V3ErrorCode::I_STYLE, false); });
|
||||
DECL_OPTION("-waiver-multiline", OnOff, &m_waiverMultiline);
|
||||
DECL_OPTION("-waiver-output", Set, &m_waiverOutput);
|
||||
|
||||
|
|
|
|||
|
|
@ -723,6 +723,7 @@ static bool verilate(const string& argString) {
|
|||
V3ExecGraph::selfTest();
|
||||
V3PreShell::selfTest();
|
||||
V3Broken::selfTest();
|
||||
V3Control::selfTest();
|
||||
V3ThreadPool::selfTest();
|
||||
UINFO(2, "selfTest done");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8036,9 +8036,9 @@ vltItem:
|
|||
| vltOffFront vltDFile
|
||||
{ V3Control::addIgnore($1, false, *$2, 0, 0); }
|
||||
| vltOffFront vltDFile yVLT_D_LINES yaINTNUM
|
||||
{ V3Control::addIgnore($1, false, *$2, $4->toUInt(), $4->toUInt() + 1); }
|
||||
{ V3Control::addIgnore($1, false, *$2, $4->toUInt(), $4->toUInt()); }
|
||||
| vltOffFront vltDFile yVLT_D_LINES yaINTNUM '-' yaINTNUM
|
||||
{ V3Control::addIgnore($1, false, *$2, $4->toUInt(), $6->toUInt() + 1); }
|
||||
{ V3Control::addIgnore($1, false, *$2, $4->toUInt(), $6->toUInt()); }
|
||||
| vltOffFront vltDFile vltDMatch
|
||||
{ if (($1 == V3ErrorCode::I_COVERAGE) || ($1 == V3ErrorCode::I_TRACING)) {
|
||||
$<fl>1->v3error("Argument -match only supported for lint_off");
|
||||
|
|
@ -8074,9 +8074,9 @@ vltItem:
|
|||
| vltOnFront vltDFile
|
||||
{ V3Control::addIgnore($1, true, *$2, 0, 0); }
|
||||
| vltOnFront vltDFile yVLT_D_LINES yaINTNUM
|
||||
{ V3Control::addIgnore($1, true, *$2, $4->toUInt(), $4->toUInt() + 1); }
|
||||
{ V3Control::addIgnore($1, true, *$2, $4->toUInt(), $4->toUInt()); }
|
||||
| vltOnFront vltDFile yVLT_D_LINES yaINTNUM '-' yaINTNUM
|
||||
{ V3Control::addIgnore($1, true, *$2, $4->toUInt(), $6->toUInt() + 1); }
|
||||
{ V3Control::addIgnore($1, true, *$2, $4->toUInt(), $6->toUInt()); }
|
||||
| vltOnFront vltDScope
|
||||
{ if ($1 != V3ErrorCode::I_TRACING) {
|
||||
$<fl>1->v3error("Argument -scope only supported for tracing_on/off");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
%Warning-UNUSEDSIGNAL: t/t_vlt_warn_file2_bad.v:20:7: Signal is not driven, nor used: 'unuse_warn_var_line20'
|
||||
: ... note: In instance 't'
|
||||
20 | reg unuse_warn_var_line20;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~
|
||||
... For warning description see https://verilator.org/warn/UNUSEDSIGNAL?v=latest
|
||||
... Use "/* verilator lint_off UNUSEDSIGNAL */" and lint_on around source to disable this message.
|
||||
%Error: Exiting due to
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
test.lint(verilator_flags2=['--Wall'], fails=True, expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2025 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`ifdef verilator
|
||||
`verilator_config
|
||||
lint_off -rule DECLFILENAME
|
||||
// Test filename matches are in directive parse order
|
||||
lint_off -rule UNUSED -file "*/t_*" // Sorts before t_vlt_*
|
||||
lint_off -rule UNUSED -file "*/t_vlt_warn*" // Sorts after t_vlt_*
|
||||
lint_on -rule UNUSED -file "*/t_vlt_*"
|
||||
lint_off -rule UNUSED -file "*/t_vlt_warn*" -lines 21-22
|
||||
`verilog
|
||||
`endif
|
||||
|
||||
|
||||
module t;
|
||||
reg unuse_warn_var_line20; // Unused warning - must be line 20 (on)
|
||||
reg unuse_warn2_var_line21; // Unused warning - must be line 21 (off)
|
||||
reg unuse_warn3_var_line22; // Unused warning - must be line 22 (off)
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
%Warning-UNUSEDPARAM: t/t_vlt_warn_one_on_bad.v:24:14: Parameter is not used: 'unuse_warn5_var_line24'
|
||||
: ... note: In instance 't'
|
||||
24 | localparam unuse_warn5_var_line24 = 0;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~
|
||||
... For warning description see https://verilator.org/warn/UNUSEDPARAM?v=latest
|
||||
... Use "/* verilator lint_off UNUSEDPARAM */" and lint_on around source to disable this message.
|
||||
%Warning-UNUSEDPARAM: t/t_vlt_warn_one_on_bad.v:25:14: Parameter is not used: 'unuse_warn5_var_line25'
|
||||
: ... note: In instance 't'
|
||||
25 | localparam unuse_warn5_var_line25 = 0;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~
|
||||
%Error: Exiting due to
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
test.lint(verilator_flags2=['--Wall'], fails=True, expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2025 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`ifdef verilator
|
||||
`verilator_config
|
||||
// Issue #4185
|
||||
lint_off
|
||||
lint_on -rule UNUSEDPARAM
|
||||
`verilog
|
||||
`endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module t;
|
||||
reg unuse_warn_var_line20; // Unused warning - must be line 20
|
||||
reg unuse_warn2_var_line21; // Unused warning - must be line 21
|
||||
reg unuse_warn3_var_line22; // Unused warning - must be line 22
|
||||
reg unuse_warn4_var_line23; // Unused warning - must be line 23
|
||||
localparam unuse_warn5_var_line24 = 0; // Unused warning - must be line 24 (not suppressed)
|
||||
localparam unuse_warn5_var_line25 = 0; // Unused warning - must be line 25 (not suppressed)
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
%Warning-UNUSEDSIGNAL: t/t_vlt_warn_range_bad.v:24:7: Signal is not driven, nor used: 'unuse_warn5_var_line24'
|
||||
: ... note: In instance 't'
|
||||
24 | reg unuse_warn5_var_line24;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~
|
||||
... For warning description see https://verilator.org/warn/UNUSEDSIGNAL?v=latest
|
||||
... Use "/* verilator lint_off UNUSEDSIGNAL */" and lint_on around source to disable this message.
|
||||
%Warning-UNUSEDSIGNAL: t/t_vlt_warn_range_bad.v:26:7: Signal is not driven, nor used: 'unuse_warn5_var_line26'
|
||||
: ... note: In instance 't'
|
||||
26 | reg unuse_warn5_var_line26;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~
|
||||
%Error: Exiting due to
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
test.lint(verilator_flags2=['--Wall'], fails=True, expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2025 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`ifdef verilator
|
||||
`verilator_config
|
||||
lint_off -rule DECLFILENAME
|
||||
// Test overlapping ranges work correctly
|
||||
lint_off -rule UNUSED -file "*/t_*" -lines 21-23
|
||||
lint_off -rule UNUSED -file "*/t_*" -lines 20-22 // Intentional overlap with above
|
||||
lint_off -rule UNUSED -file "*/t_*" -lines 25-99
|
||||
lint_on -rule UNUSED -file "*/t_*" -lines 26
|
||||
`verilog
|
||||
`endif
|
||||
|
||||
|
||||
module t;
|
||||
reg unuse_warn_var_line20; // Unused warning - must be line 20
|
||||
reg unuse_warn2_var_line21; // Unused warning - must be line 21
|
||||
reg unuse_warn3_var_line22; // Unused warning - must be line 22
|
||||
reg unuse_warn4_var_line23; // Unused warning - must be line 23
|
||||
reg unuse_warn5_var_line24; // Unused warning - must be line 24 (not suppressed)
|
||||
reg unuse_warn5_var_line25; // Unused warning - must be line 25
|
||||
reg unuse_warn5_var_line26; // Unused warning - must be line 26 (turned on)
|
||||
reg unuse_warn5_var_line27; // Unused warning - must be line 27
|
||||
endmodule
|
||||
Loading…
Reference in New Issue