mirror of
https://github.com/verilator/verilator.git
synced 2024-12-29 10:47:34 +00:00
Merge branch 'master' into develop-v5
This commit is contained in:
commit
880cac2fdd
8
.github/workflows/coverage.yml
vendored
8
.github/workflows/coverage.yml
vendored
@ -24,10 +24,10 @@ jobs:
|
||||
|
||||
|
||||
Build:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
CI_BUILD_STAGE_NAME: build
|
||||
CI_RUNS_ON: ubuntu-20.04
|
||||
CI_RUNS_ON: ubuntu-22.04
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
@ -73,11 +73,11 @@ jobs:
|
||||
- 9
|
||||
include:
|
||||
- { test: dist, num: '' }
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
name: test-${{ matrix.test }}${{ matrix.num }}
|
||||
env:
|
||||
CI_BUILD_STAGE_NAME: test
|
||||
CI_RUNS_ON: ubuntu-20.04
|
||||
CI_RUNS_ON: ubuntu-22.04
|
||||
steps:
|
||||
|
||||
- name: Download tar archive
|
||||
|
11
Changes
11
Changes
@ -13,7 +13,7 @@ Verilator 5.001 devel
|
||||
|
||||
**Major:**
|
||||
|
||||
* This is a major new release, currently only in alpha testing.
|
||||
* This is a major new release.
|
||||
* Fully support the Active and NBA scheduling regions as defined by the
|
||||
SystemVerilog standard (IEEE 1800-2017 chapter 4). This means all generated
|
||||
clocks are now simulated correctly (#3278, #3384). [Geza Lore, Shunyao CAD]
|
||||
@ -22,7 +22,7 @@ Verilator 5.001 devel
|
||||
* Add --binary option as alias of --main --exe --build --timing (#3625).
|
||||
|
||||
|
||||
Verilator 4.227 devel
|
||||
Verilator 4.228 2022-10-01
|
||||
==========================
|
||||
|
||||
**Announcement:**
|
||||
@ -33,14 +33,18 @@ Verilator 4.227 devel
|
||||
|
||||
**Minor:**
|
||||
|
||||
* Support IEEE constant signal strengths (#3601). [Ryszard Rozak/Antmicro]
|
||||
* Support some IEEE signal strengths (#3601) (#3629). [Ryszard Rozak/Antmicro]
|
||||
* Add --main to generate main() C++ (previously was experimental only).
|
||||
* Add --build-jobs, and rework arguments for -j (#3623). [Kamil Rakoczy]
|
||||
* Rename --bin to --build-dep-bin.
|
||||
* Rename debug flags --dumpi-tree, --dumpi-graph, etc. [Geza Lore]
|
||||
* Fix thread saftey in SystemC VL_ASSIGN_SBW/WSB (#3494) (#3513). [Mladen Slijepcevic]
|
||||
* Fix crash in gate optimization of circular logic (#3543). [Bill Flynn]
|
||||
* Fix arguments in non-static method call (#3547) (#3582). [Gustav Svensk]
|
||||
* Fix default --mod-prefix when --prefix is repeated (#3603). [Geza Lore]
|
||||
* Fix calling trace() after open() segfault (#3610) (#3627). [Yu-Sheng Lin]
|
||||
* Fix typedef'ed class conversion to boolean (#3616). [Aleksander Kiryk]
|
||||
* Fix Verilation speed when disabled warnings (#3632). [Kamil Rakoczy/Antmicro]
|
||||
|
||||
|
||||
Verilator 4.226 2022-08-31
|
||||
@ -55,6 +59,7 @@ Verilator 4.226 2022-08-31
|
||||
* Support $test$plusargs(expr) (#3489).
|
||||
* Rename trace rolloverSize() (#3570).
|
||||
* Improve Verilation speed with --threads on large designs. [Geza Lore]
|
||||
* Improve Verilation memory by reducing V3Number (#3521). [Mariusz Glebocki/Antmicro]
|
||||
* Fix struct pattern assignment (#2328) (#3517). [Mostafa Gamal]
|
||||
* Fix public combo propagation issues (#2905). [Todd Strader]
|
||||
* Fix incorrect tristate logic (#3399) [shareefj, Vighnesh Iyer]
|
||||
|
@ -71,6 +71,7 @@ Ludwig Rogiers
|
||||
Lukasz Dalek
|
||||
Maarten De Braekeleer
|
||||
Maciej Sobkowski
|
||||
Marcel Chang
|
||||
Marco Widmer
|
||||
Mariusz Glebocki
|
||||
Markus Krause
|
||||
|
@ -382,6 +382,12 @@ Summary:
|
||||
<--dump-tree>` may be useful if the dump files are large and not
|
||||
desired.
|
||||
|
||||
.. option:: --dump-tree-dot
|
||||
|
||||
Rarely needed. Enable dumping Ast .tree.dot debug files in Graphviz
|
||||
Dot format. This option implies :vlopt:`--dump-tree`, unless
|
||||
:vlopt:`--dumpi-tree` was passed explicitly.
|
||||
|
||||
.. option:: --dump-tree-addrids
|
||||
|
||||
Rarely needed - for developer use. Replace AST node addresses with
|
||||
|
@ -1677,6 +1677,16 @@ Similarly the ``NETLIST`` has a list of modules referred to by its
|
||||
``op1p()`` pointer.
|
||||
|
||||
|
||||
.tree.dot Output
|
||||
----------------
|
||||
|
||||
``*.tree.dot`` files are dumps of the AST Tree in `Graphviz
|
||||
<https://www.graphviz.org>`__ dot format. This can be used to
|
||||
visualize the AST Tree. The vertices correspond to ``AstNode``
|
||||
instances, and the edges represent the pointers (``op1p``,
|
||||
``op2p``, etc) between the nodes.
|
||||
|
||||
|
||||
Debugging with GDB
|
||||
------------------
|
||||
|
||||
|
@ -82,7 +82,7 @@ int sc_main(int argc, char* argv[]) {
|
||||
|
||||
// You must do one evaluation before enabling waves, in order to allow
|
||||
// SystemC to interconnect everything for testing.
|
||||
sc_start(1, SC_NS);
|
||||
sc_start(SC_ZERO_TIME);
|
||||
|
||||
#if VM_TRACE
|
||||
// If verilator was invoked with --trace argument,
|
||||
|
@ -551,15 +551,15 @@ template <>
|
||||
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::runOffloadedCallbacks(
|
||||
const std::vector<CallbackRecord>& cbVec) {
|
||||
// Fall back on sequential execution
|
||||
for (const CallbackRecord& cbr : cbVec) {
|
||||
#ifdef VL_THREADED
|
||||
for (const CallbackRecord& cbr : cbVec) {
|
||||
Buffer* traceBufferp = getTraceBuffer();
|
||||
cbr.m_dumpOffloadCb(cbr.m_userp, static_cast<OffloadBuffer*>(traceBufferp));
|
||||
commitTraceBuffer(traceBufferp);
|
||||
#else
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", "Unreachable");
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
if (!cbVec.empty()) VL_FATAL_MT(__FILE__, __LINE__, "", "Unreachable");
|
||||
#endif
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -586,7 +586,9 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::dump(uint64_t timeui) VL_MT_SAFE_EXCLUD
|
||||
if (!preChangeDump()) return;
|
||||
}
|
||||
|
||||
#ifdef VL_THREADED
|
||||
uint32_t* bufferp = nullptr;
|
||||
#endif
|
||||
if (offload()) {
|
||||
#ifdef VL_THREADED
|
||||
// Currently only incremental dumps run on the worker thread
|
||||
|
@ -1141,6 +1141,49 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump, boo
|
||||
}
|
||||
}
|
||||
|
||||
static void drawChildren(std::ostream& os, const AstNode* thisp, const AstNode* childp,
|
||||
const std::string& childName) {
|
||||
if (childp) {
|
||||
os << "\tn" << cvtToHex(thisp) << " -> n" << cvtToHex(childp) << " ["
|
||||
<< "label=\"" << childName << "\" color=red];\n";
|
||||
for (const AstNode* nodep = childp; nodep; nodep = nodep->nextp()) {
|
||||
nodep->dumpTreeDot(os);
|
||||
if (nodep->nextp()) {
|
||||
os << "\tn" << cvtToHex(nodep) << " -> n" << cvtToHex(nodep->nextp()) << " ["
|
||||
<< "label=\"next\" color=red];\n";
|
||||
os << "\t{rank=same; n" << cvtToHex(nodep) << ", n" << cvtToHex(nodep->nextp())
|
||||
<< "}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AstNode::dumpTreeDot(std::ostream& os) const {
|
||||
os << "\tn" << cvtToHex(this) << "\t["
|
||||
<< "label=\"" << typeName() << "\\n"
|
||||
<< name() << "\"];\n";
|
||||
drawChildren(os, this, m_op1p, "op1");
|
||||
drawChildren(os, this, m_op2p, "op2");
|
||||
drawChildren(os, this, m_op3p, "op3");
|
||||
drawChildren(os, this, m_op4p, "op4");
|
||||
}
|
||||
|
||||
void AstNode::dumpTreeDotFile(const string& filename, bool append, bool doDump) {
|
||||
if (doDump) {
|
||||
UINFO(2, "Dumping " << filename << endl);
|
||||
const std::unique_ptr<std::ofstream> treedotp{V3File::new_ofstream(filename, append)};
|
||||
if (treedotp->fail()) v3fatal("Can't write " << filename);
|
||||
*treedotp << "digraph vTree{\n";
|
||||
*treedotp << "\tgraph\t[label=\"" << filename + ".dot"
|
||||
<< "\",\n";
|
||||
*treedotp << "\t\t labelloc=t, labeljust=l,\n";
|
||||
*treedotp << "\t\t //size=\"7.5,10\",\n"
|
||||
<< "];\n";
|
||||
dumpTreeDot(*treedotp);
|
||||
*treedotp << "}\n";
|
||||
}
|
||||
}
|
||||
|
||||
void AstNode::v3errorEndFatal(std::ostringstream& str) const {
|
||||
v3errorEnd(str);
|
||||
assert(0); // LCOV_EXCL_LINE
|
||||
|
@ -1916,6 +1916,8 @@ public:
|
||||
void dumpTreeFile(const string& filename, bool append = false, bool doDump = true,
|
||||
bool doCheck = true);
|
||||
static void dumpTreeFileGdb(const AstNode* nodep, const char* filenamep = nullptr);
|
||||
void dumpTreeDot(std::ostream& os = std::cout) const;
|
||||
void dumpTreeDotFile(const string& filename, bool append = false, bool doDump = true);
|
||||
|
||||
// METHODS - queries
|
||||
// Changes control flow, disable some optimizations
|
||||
|
@ -424,10 +424,46 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void preserveTopIfaces(AstNetlist* rootp) {
|
||||
for (AstNodeModule* modp = rootp->modulesp(); modp && modp->level() <= 2;
|
||||
modp = VN_AS(modp->nextp(), NodeModule)) {
|
||||
for (AstNode* subnodep = modp->stmtsp(); subnodep; subnodep = subnodep->nextp()) {
|
||||
if (AstVar* const varp = VN_CAST(subnodep, Var)) {
|
||||
if (varp->isIfaceRef()) {
|
||||
const AstNodeDType* const subtypep = varp->subDTypep();
|
||||
const AstIfaceRefDType* ifacerefp = nullptr;
|
||||
if (VN_IS(subtypep, IfaceRefDType)) {
|
||||
ifacerefp = VN_AS(varp->subDTypep(), IfaceRefDType);
|
||||
} else if (VN_IS(subtypep, BracketArrayDType)) {
|
||||
const AstBracketArrayDType* const arrp
|
||||
= VN_AS(subtypep, BracketArrayDType);
|
||||
const AstNodeDType* const arrsubtypep = arrp->subDTypep();
|
||||
if (VN_IS(arrsubtypep, IfaceRefDType)) {
|
||||
ifacerefp = VN_AS(arrsubtypep, IfaceRefDType);
|
||||
}
|
||||
} else if (VN_IS(subtypep, UnpackArrayDType)) {
|
||||
const AstUnpackArrayDType* const arrp
|
||||
= VN_AS(subtypep, UnpackArrayDType);
|
||||
const AstNodeDType* const arrsubtypep = arrp->subDTypep();
|
||||
if (VN_IS(arrsubtypep, IfaceRefDType)) {
|
||||
ifacerefp = VN_AS(arrsubtypep, IfaceRefDType);
|
||||
}
|
||||
}
|
||||
|
||||
if (ifacerefp && !ifacerefp->cellp()
|
||||
&& (ifacerefp->ifacep()->user1() == 0)) {
|
||||
ifacerefp->ifacep()->user1(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes, bool elimScopes,
|
||||
bool elimCells)
|
||||
bool elimCells, bool elimTopIfaces)
|
||||
: m_elimUserVars{elimUserVars}
|
||||
, m_elimDTypes{elimDTypes}
|
||||
, m_elimCells{elimCells} {
|
||||
@ -448,6 +484,7 @@ public:
|
||||
if (elimCells) deadCheckCells();
|
||||
deadCheckClasses();
|
||||
// Modules after vars, because might be vars we delete inside a mod we delete
|
||||
if (!elimTopIfaces) preserveTopIfaces(nodep);
|
||||
deadCheckMod();
|
||||
|
||||
// We may have removed some datatypes, cleanup
|
||||
@ -461,30 +498,32 @@ public:
|
||||
|
||||
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DeadVisitor{nodep, false, false, false, false}; } // Destruct before checking
|
||||
{
|
||||
DeadVisitor{nodep, false, false, false, false, !v3Global.opt.topIfacesSupported()};
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("deadModules", 0, dumpTree() >= 6);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DeadVisitor{nodep, false, true, false, false}; } // Destruct before checking
|
||||
{ DeadVisitor{nodep, false, true, false, false, false}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("deadDtypes", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DeadVisitor{nodep, false, true, true, false}; } // Destruct before checking
|
||||
{ DeadVisitor{nodep, false, true, true, false, false}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("deadDtypesScoped", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DeadVisitor{nodep, true, true, false, true}; } // Destruct before checking
|
||||
{ DeadVisitor{nodep, true, true, false, true, false}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("deadAll", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DeadVisitor{nodep, true, true, true, true}; } // Destruct before checking
|
||||
{ DeadVisitor{nodep, true, true, true, true, false}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("deadAllScoped", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
@ -93,8 +93,11 @@ string V3Global::digitsFilename(int number) {
|
||||
}
|
||||
|
||||
void V3Global::dumpCheckGlobalTree(const string& stagename, int newNumber, bool doDump) {
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename(stagename + ".tree", newNumber), false,
|
||||
doDump);
|
||||
const string treeFilename = v3Global.debugFilename(stagename + ".tree", newNumber);
|
||||
v3Global.rootp()->dumpTreeFile(treeFilename, false, doDump);
|
||||
if (v3Global.opt.dumpTreeDot()) {
|
||||
v3Global.rootp()->dumpTreeDotFile(treeFilename + ".dot", false, doDump);
|
||||
}
|
||||
if (v3Global.opt.stats()) V3Stats::statsStage(stagename);
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,10 @@ private:
|
||||
std::vector<V3GraphVertex*> m_callTrace; // List of everything we hit processing so far
|
||||
|
||||
void main() {
|
||||
// Use Tarjan's algorithm to find the strongly connected subgraphs.
|
||||
// Use Pearce's algorithm to color the strongly connected components. For reference see
|
||||
// "An Improved Algorithm for Finding the Strongly Connected Components of a Directed
|
||||
// Graph", David J.Pearce, 2005
|
||||
//
|
||||
// Node State:
|
||||
// Vertex::user // DFS number indicating possible root of subtree, 0=not iterated
|
||||
// Vertex::color // Output subtree number (fully processed)
|
||||
|
@ -308,6 +308,19 @@ public:
|
||||
if (forScopeCreation()) m_nameScopeSymMap.emplace(scopename, symp);
|
||||
return symp;
|
||||
}
|
||||
VSymEnt* insertTopIface(AstCell* nodep, const string& scopename) {
|
||||
VSymEnt* const symp = new VSymEnt{&m_syms, nodep};
|
||||
UINFO(9, " INSERTtopiface se" << cvtToHex(symp) << " " << scopename << " " << nodep
|
||||
<< endl);
|
||||
symp->parentp(rootEntp()); // Needed so backward search can find name of top module
|
||||
symp->fallbackp(dunitEntp()); // Needed so can find $unit stuff
|
||||
nodep->user1p(symp);
|
||||
if (nodep->modp()) nodep->modp()->user1p(symp);
|
||||
checkDuplicate(rootEntp(), nodep, nodep->origName());
|
||||
rootEntp()->insert(nodep->origName(), symp);
|
||||
if (forScopeCreation()) m_nameScopeSymMap.emplace(scopename, symp);
|
||||
return symp;
|
||||
}
|
||||
VSymEnt* insertCell(VSymEnt* abovep, VSymEnt* modSymp, AstCell* nodep,
|
||||
const string& scopename) {
|
||||
UASSERT_OBJ(abovep, nodep, "Null symbol table inserting node");
|
||||
@ -764,8 +777,55 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||
modp = VN_AS(modp->nextp(), NodeModule)) {
|
||||
UINFO(8, "Top Module: " << modp << endl);
|
||||
m_scope = "TOP";
|
||||
|
||||
if (m_statep->forPrearray() && v3Global.opt.topIfacesSupported()) {
|
||||
for (AstNode* subnodep = modp->stmtsp(); subnodep; subnodep = subnodep->nextp()) {
|
||||
if (AstVar* const varp = VN_CAST(subnodep, Var)) {
|
||||
if (varp->isIfaceRef()) {
|
||||
const AstNodeDType* const subtypep = varp->subDTypep();
|
||||
const AstIfaceRefDType* ifacerefp = nullptr;
|
||||
if (VN_IS(subtypep, IfaceRefDType)) {
|
||||
ifacerefp = VN_AS(varp->subDTypep(), IfaceRefDType);
|
||||
} else if (VN_IS(subtypep, BracketArrayDType)) {
|
||||
const AstBracketArrayDType* const arrp
|
||||
= VN_AS(subtypep, BracketArrayDType);
|
||||
const AstNodeDType* const arrsubtypep = arrp->subDTypep();
|
||||
if (VN_IS(arrsubtypep, IfaceRefDType)) {
|
||||
ifacerefp = VN_AS(arrsubtypep, IfaceRefDType);
|
||||
}
|
||||
} else if (VN_IS(subtypep, UnpackArrayDType)) {
|
||||
const AstUnpackArrayDType* const arrp
|
||||
= VN_AS(subtypep, UnpackArrayDType);
|
||||
const AstNodeDType* const arrsubtypep = arrp->subDTypep();
|
||||
if (VN_IS(arrsubtypep, IfaceRefDType)) {
|
||||
ifacerefp = VN_AS(arrsubtypep, IfaceRefDType);
|
||||
}
|
||||
}
|
||||
|
||||
if (ifacerefp && !ifacerefp->cellp()) {
|
||||
// A dummy cell to keep the top level interface alive and correctly
|
||||
// optimized for default parameter values
|
||||
AstCell* ifacecellp
|
||||
= new AstCell{nodep->fileline(),
|
||||
nodep->fileline(),
|
||||
modp->name() + "__02E" + varp->name(),
|
||||
ifacerefp->ifaceName(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr};
|
||||
ifacecellp->modp(ifacerefp->ifacep());
|
||||
m_curSymp = m_modSymp
|
||||
= m_statep->insertTopIface(ifacecellp, m_scope);
|
||||
{ iterate(ifacecellp); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_curSymp = m_modSymp = m_statep->insertTopCell(modp, m_scope);
|
||||
{ iterate(modp); }
|
||||
|
||||
m_scope = "";
|
||||
m_curSymp = m_modSymp = nullptr;
|
||||
}
|
||||
|
@ -199,6 +199,36 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
|
||||
} else {
|
||||
ioNames.insert(oldvarp->name());
|
||||
}
|
||||
} else if (v3Global.opt.topIfacesSupported() && oldvarp->isIfaceRef()) {
|
||||
const AstNodeDType* const subtypep = oldvarp->subDTypep();
|
||||
if (VN_IS(subtypep, IfaceRefDType)) {
|
||||
const AstIfaceRefDType* const ifacerefp = VN_AS(subtypep, IfaceRefDType);
|
||||
if (!ifacerefp->cellp()) {
|
||||
if (ioNames.find(oldvarp->name()) != ioNames.end()) {
|
||||
// UINFO(8, "Multitop dup interface found: " << oldvarp << endl);
|
||||
dupNames.insert(oldvarp->name());
|
||||
} else {
|
||||
ioNames.insert(oldvarp->name());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (VN_IS(subtypep, UnpackArrayDType)) {
|
||||
const AstUnpackArrayDType* const arrp = VN_AS(subtypep, UnpackArrayDType);
|
||||
const AstNodeDType* const arrsubtypep = arrp->subDTypep();
|
||||
if (VN_IS(arrsubtypep, IfaceRefDType)) {
|
||||
const AstIfaceRefDType* const ifacerefp
|
||||
= VN_AS(arrsubtypep, IfaceRefDType);
|
||||
if (!ifacerefp->cellp()) {
|
||||
if (ioNames.find(oldvarp->name()) != ioNames.end()) {
|
||||
// UINFO(8, "Multitop dup interface array found: " << oldvarp
|
||||
// << endl);
|
||||
dupNames.insert(oldvarp->name());
|
||||
} else {
|
||||
ioNames.insert(oldvarp->name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -256,6 +286,104 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
|
||||
// Skip length and width comp; we know it's a direct assignment
|
||||
pinp->modVarp(oldvarp);
|
||||
cellp->addPinsp(pinp);
|
||||
} else if (v3Global.opt.topIfacesSupported() && oldvarp->isIfaceRef()) {
|
||||
// for each interface port on oldmodp instantiate a corresponding interface
|
||||
// cell in $root
|
||||
const AstNodeDType* const subtypep = oldvarp->subDTypep();
|
||||
if (VN_IS(subtypep, IfaceRefDType)) {
|
||||
const AstIfaceRefDType* const ifacerefp = VN_AS(subtypep, IfaceRefDType);
|
||||
if (!ifacerefp->cellp()) {
|
||||
string name = oldvarp->name();
|
||||
if (dupNames.find(name) != dupNames.end()) {
|
||||
// __02E=. while __DOT__ looks nicer but will break V3LinkDot
|
||||
name = oldmodp->name() + "__02E" + name;
|
||||
}
|
||||
|
||||
AstCell* ifacecellp = new AstCell{newmodp->fileline(),
|
||||
newmodp->fileline(),
|
||||
name,
|
||||
ifacerefp->ifaceName(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr};
|
||||
ifacecellp->modp(ifacerefp->ifacep());
|
||||
newmodp->addStmtsp(ifacecellp);
|
||||
|
||||
AstIfaceRefDType* const idtypep = new AstIfaceRefDType{
|
||||
newmodp->fileline(), name, ifacerefp->ifaceName()};
|
||||
idtypep->ifacep(nullptr);
|
||||
idtypep->dtypep(idtypep);
|
||||
idtypep->cellp(ifacecellp);
|
||||
rootp->typeTablep()->addTypesp(idtypep);
|
||||
|
||||
AstVar* varp = new AstVar{newmodp->fileline(), VVarType::IFACEREF,
|
||||
name + "__Viftop", idtypep};
|
||||
varp->isIfaceParent(true);
|
||||
ifacecellp->addNextHere(varp);
|
||||
ifacecellp->hasIfaceVar(true);
|
||||
|
||||
AstPin* const pinp
|
||||
= new AstPin{oldvarp->fileline(), 0, varp->name(),
|
||||
new AstVarRef{varp->fileline(), varp,
|
||||
oldvarp->isWritable() ? VAccess::WRITE
|
||||
: VAccess::READ}};
|
||||
pinp->modVarp(oldvarp);
|
||||
cellp->addPinsp(pinp);
|
||||
}
|
||||
} else if (VN_IS(subtypep, UnpackArrayDType)) {
|
||||
const AstUnpackArrayDType* const oldarrp
|
||||
= VN_AS(subtypep, UnpackArrayDType);
|
||||
const AstNodeDType* const arrsubtypep = oldarrp->subDTypep();
|
||||
if (VN_IS(arrsubtypep, IfaceRefDType)) {
|
||||
const AstIfaceRefDType* const ifacerefp
|
||||
= VN_AS(arrsubtypep, IfaceRefDType);
|
||||
if (!ifacerefp->cellp()) {
|
||||
string name = oldvarp->name();
|
||||
if (dupNames.find(name) != dupNames.end()) {
|
||||
// __02E=. while __DOT__ looks nicer but will break V3LinkDot
|
||||
name = oldmodp->name() + "__02E" + name;
|
||||
}
|
||||
|
||||
AstUnpackArrayDType* arraydtypep
|
||||
= VN_AS(oldvarp->dtypep(), UnpackArrayDType);
|
||||
AstCell* ifacearraycellp
|
||||
= new AstCell{newmodp->fileline(),
|
||||
newmodp->fileline(),
|
||||
name,
|
||||
ifacerefp->ifaceName(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
arraydtypep->rangep()->cloneTree(true)};
|
||||
ifacearraycellp->modp(ifacerefp->ifacep());
|
||||
newmodp->addStmtsp(ifacearraycellp);
|
||||
|
||||
AstIfaceRefDType* const idtypep = new AstIfaceRefDType{
|
||||
newmodp->fileline(), name, ifacerefp->ifaceName()};
|
||||
idtypep->ifacep(nullptr);
|
||||
idtypep->dtypep(idtypep);
|
||||
idtypep->cellp(ifacearraycellp);
|
||||
rootp->typeTablep()->addTypesp(idtypep);
|
||||
|
||||
AstNodeArrayDType* const arrp = new AstUnpackArrayDType{
|
||||
newmodp->fileline(), idtypep,
|
||||
arraydtypep->rangep()->cloneTree(true)};
|
||||
AstVar* varp = new AstVar{newmodp->fileline(), VVarType::IFACEREF,
|
||||
name + "__Viftop", arrp};
|
||||
varp->isIfaceParent(true);
|
||||
ifacearraycellp->addNextHere(varp);
|
||||
ifacearraycellp->hasIfaceVar(true);
|
||||
rootp->typeTablep()->addTypesp(arrp);
|
||||
|
||||
AstPin* const pinp = new AstPin{
|
||||
oldvarp->fileline(), 0, varp->name(),
|
||||
new AstVarRef{varp->fileline(), varp,
|
||||
oldvarp->isWritable() ? VAccess::WRITE
|
||||
: VAccess::READ}};
|
||||
pinp->modVarp(oldvarp);
|
||||
cellp->addPinsp(pinp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ private:
|
||||
nodep->valuep()->unlinkFrBack()));
|
||||
}
|
||||
}
|
||||
if (nodep->isIfaceRef() && !nodep->isIfaceParent()) {
|
||||
if (nodep->isIfaceRef() && !nodep->isIfaceParent() && !v3Global.opt.topIfacesSupported()) {
|
||||
// Only AstIfaceRefDType's at this point correspond to ports;
|
||||
// haven't made additional ones for interconnect yet, so assert is simple
|
||||
// What breaks later is we don't have a Scope/Cell representing
|
||||
|
@ -828,6 +828,11 @@ void V3Options::notify() {
|
||||
|
||||
// Mark options as available
|
||||
m_available = true;
|
||||
|
||||
// --dump-tree-dot will turn on tree dumping.
|
||||
if (!m_dumpLevel.count("tree") && m_dumpLevel.count("tree-dot")) {
|
||||
m_dumpLevel["tree"] = m_dumpLevel["tree-dot"];
|
||||
}
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
@ -458,6 +458,9 @@ public:
|
||||
bool decoration() const { return m_decoration; }
|
||||
bool dpiHdrOnly() const { return m_dpiHdrOnly; }
|
||||
bool dumpDefines() const { return m_dumpLevel.count("defines") && m_dumpLevel.at("defines"); }
|
||||
bool dumpTreeDot() const {
|
||||
return m_dumpLevel.count("tree-dot") && m_dumpLevel.at("tree-dot");
|
||||
}
|
||||
bool exe() const { return m_exe; }
|
||||
bool flatten() const { return m_flatten; }
|
||||
bool gmake() const { return m_gmake; }
|
||||
@ -494,6 +497,7 @@ public:
|
||||
bool vpi() const { return m_vpi; }
|
||||
bool xInitialEdge() const { return m_xInitialEdge; }
|
||||
bool xmlOnly() const { return m_xmlOnly; }
|
||||
bool topIfacesSupported() const { return lintOnly() && !hierarchical(); }
|
||||
|
||||
int buildJobs() const { return m_buildJobs; }
|
||||
int convergeLimit() const { return m_convergeLimit; }
|
||||
|
@ -493,6 +493,47 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||
}
|
||||
return VN_AS(invarp->user1p(), Var);
|
||||
}
|
||||
AstConst* getNonZConstp(AstConst* const constp) {
|
||||
FileLine* const fl = constp->fileline();
|
||||
V3Number numz{constp, constp->width()};
|
||||
numz.opBitsZ(constp->num()); // Z->1, else 0
|
||||
V3Number numz0{constp, constp->width()};
|
||||
numz0.opNot(numz); // Z->0, else 1
|
||||
return new AstConst{fl, numz0};
|
||||
}
|
||||
AstNode* getEnExprBasedOnOriginalp(AstNode* const nodep) {
|
||||
if (AstVarRef* const varrefp = VN_CAST(nodep, VarRef)) {
|
||||
return new AstVarRef{varrefp->fileline(), getCreateEnVarp(varrefp->varp()),
|
||||
VAccess::READ};
|
||||
} else if (AstConst* const constp = VN_CAST(nodep, Const)) {
|
||||
return getNonZConstp(constp);
|
||||
} else if (AstExtend* const extendp = VN_CAST(nodep, Extend)) {
|
||||
// Extend inserts 0 at the beginning. 0 in __en variable means that this bit equals z,
|
||||
// so in order to preserve the value of the original AstExtend node we should insert 1
|
||||
// instead of 0. To extend __en expression we have to negate its lhsp() and then negate
|
||||
// whole extend.
|
||||
|
||||
// Unlink lhsp before copying to save unnecessary copy of lhsp
|
||||
AstNode* const lhsp = extendp->lhsp()->unlinkFrBack();
|
||||
AstExtend* const enExtendp = extendp->cloneTree(false);
|
||||
extendp->lhsp(lhsp);
|
||||
AstNode* const enLhsp = getEnExprBasedOnOriginalp(lhsp);
|
||||
enExtendp->lhsp(new AstNot{enLhsp->fileline(), enLhsp});
|
||||
return new AstNot{enExtendp->fileline(), enExtendp};
|
||||
} else if (AstSel* const selp = VN_CAST(nodep, Sel)) {
|
||||
AstNode* const fromp = selp->fromp()->unlinkFrBack();
|
||||
AstSel* const enSelp = selp->cloneTree(false);
|
||||
selp->fromp(fromp);
|
||||
AstNode* const enFromp = getEnExprBasedOnOriginalp(fromp);
|
||||
enSelp->fromp(enFromp);
|
||||
return enSelp;
|
||||
} else {
|
||||
nodep->v3warn(E_UNSUPPORTED,
|
||||
"Unsupported tristate construct: " << nodep->prettyTypeName()
|
||||
<< " in function " << __func__);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
AstVar* getCreateOutVarp(AstVar* invarp) {
|
||||
// Return the master __out for the specified input variable
|
||||
if (!invarp->user4p()) {
|
||||
@ -959,14 +1000,10 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||
} else if (m_tgraph.isTristate(nodep)) {
|
||||
m_tgraph.didProcess(nodep);
|
||||
FileLine* const fl = nodep->fileline();
|
||||
V3Number numz(nodep, nodep->width());
|
||||
numz.opBitsZ(nodep->num()); // Z->1, else 0
|
||||
V3Number numz0(nodep, nodep->width());
|
||||
numz0.opNot(numz); // Z->0, else 1
|
||||
V3Number num1(nodep, nodep->width());
|
||||
num1.opAnd(nodep->num(), numz0); // 01X->01X, Z->0
|
||||
AstConst* const newconstp = new AstConst(fl, num1);
|
||||
AstConst* const enp = new AstConst(fl, numz0);
|
||||
AstConst* const enp = getNonZConstp(nodep);
|
||||
V3Number num1{nodep, nodep->width()};
|
||||
num1.opAnd(nodep->num(), enp->num()); // 01X->01X, Z->0
|
||||
AstConst* const newconstp = new AstConst{fl, num1};
|
||||
nodep->replaceWith(newconstp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
newconstp->user1p(enp); // Propagate up constant with non-Z bits as 1
|
||||
@ -1263,23 +1300,27 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||
UINFO(9, dbgState() << nodep << endl);
|
||||
// Constification always moves const to LHS
|
||||
AstConst* const constp = VN_CAST(nodep->lhsp(), Const);
|
||||
AstVarRef* const varrefp = VN_CAST(nodep->rhsp(), VarRef); // Input variable
|
||||
if (constp && constp->user1p() && varrefp) {
|
||||
if (constp && constp->user1p()) {
|
||||
// 3'b1z0 -> ((3'b101 == in__en) && (3'b100 == in))
|
||||
varrefp->unlinkFrBack();
|
||||
AstNode* const rhsp = nodep->rhsp();
|
||||
rhsp->unlinkFrBack();
|
||||
FileLine* const fl = nodep->fileline();
|
||||
AstNode* enRhsp;
|
||||
if (rhsp->user1p()) {
|
||||
enRhsp = rhsp->user1p();
|
||||
rhsp->user1p(nullptr);
|
||||
} else {
|
||||
enRhsp = getEnExprBasedOnOriginalp(rhsp);
|
||||
}
|
||||
const V3Number oneIfEn
|
||||
= VN_AS(constp->user1p(), Const)
|
||||
->num(); // visit(AstConst) already split into en/ones
|
||||
const V3Number& oneIfEnOne = constp->num();
|
||||
AstVar* const envarp = getCreateEnVarp(varrefp->varp());
|
||||
AstNode* newp
|
||||
= new AstLogAnd(fl,
|
||||
new AstEq(fl, new AstConst(fl, oneIfEn),
|
||||
new AstVarRef(fl, envarp, VAccess::READ)),
|
||||
= new AstLogAnd{fl, new AstEq{fl, new AstConst{fl, oneIfEn}, enRhsp},
|
||||
// Keep the caseeq if there are X's present
|
||||
new AstEqCase(fl, new AstConst(fl, oneIfEnOne), varrefp));
|
||||
if (neq) newp = new AstLogNot(fl, newp);
|
||||
new AstEqCase{fl, new AstConst{fl, oneIfEnOne}, rhsp}};
|
||||
if (neq) newp = new AstLogNot{fl, newp};
|
||||
UINFO(9, " newceq " << newp << endl);
|
||||
if (debug() >= 9) nodep->dumpTree(cout, "-caseeq-old: ");
|
||||
if (debug() >= 9) newp->dumpTree(cout, "-caseeq-new: ");
|
||||
|
20
test_regress/t/t_dump_tree_dot.pl
Executable file
20
test_regress/t/t_dump_tree_dot.pl
Executable file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(vlt => 1);
|
||||
|
||||
top_filename("t/t_EXAMPLE.v");
|
||||
|
||||
lint(
|
||||
v_flags => ["--lint-only --dump-tree-dot"],
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
@ -10,7 +10,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
|
||||
scenarios(vlt => 1);
|
||||
|
||||
lint(
|
||||
compile(
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
16
test_regress/t/t_lint_iface_array_topmodule1.pl
Executable file
16
test_regress/t/t_lint_iface_array_topmodule1.pl
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2008 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(linter => 1);
|
||||
|
||||
lint();
|
||||
|
||||
ok(1);
|
||||
1;
|
48
test_regress/t/t_lint_iface_array_topmodule1.v
Normal file
48
test_regress/t/t_lint_iface_array_topmodule1.v
Normal file
@ -0,0 +1,48 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Josh Redford.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
interface my_if;
|
||||
|
||||
logic valid;
|
||||
logic [7:0] data ;
|
||||
|
||||
modport slave_mp (
|
||||
input valid,
|
||||
input data
|
||||
);
|
||||
|
||||
modport master_mp (
|
||||
output valid,
|
||||
output data
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
||||
module t
|
||||
(
|
||||
input wire clk,
|
||||
my_if.slave_mp in_if [2],
|
||||
my_if.master_mp out_if [2]
|
||||
);
|
||||
|
||||
my_if my_i [2] ();
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
my_i[0].valid <= in_if[0].valid;
|
||||
my_i[0].data <= in_if[0].data;
|
||||
|
||||
my_i[1].valid <= in_if[1].valid;
|
||||
my_i[1].data <= in_if[1].data;
|
||||
end
|
||||
|
||||
assign out_if[0].valid = my_i[0].valid;
|
||||
assign out_if[0].data = my_i[0].data;
|
||||
|
||||
assign out_if[1].valid = my_i[1].valid;
|
||||
assign out_if[1].data = my_i[1].data;
|
||||
|
||||
endmodule
|
16
test_regress/t/t_lint_iface_array_topmodule2.pl
Executable file
16
test_regress/t/t_lint_iface_array_topmodule2.pl
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2008 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(linter => 1);
|
||||
|
||||
lint();
|
||||
|
||||
ok(1);
|
||||
1;
|
39
test_regress/t/t_lint_iface_array_topmodule2.v
Normal file
39
test_regress/t/t_lint_iface_array_topmodule2.v
Normal file
@ -0,0 +1,39 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Josh Redford.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
interface my_if #(
|
||||
parameter DW = 8
|
||||
) ();
|
||||
|
||||
logic valid;
|
||||
logic [DW-1:0] data ;
|
||||
|
||||
modport slave_mp (
|
||||
input valid,
|
||||
input data
|
||||
);
|
||||
|
||||
modport master_mp (
|
||||
output valid,
|
||||
output data
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
||||
module t
|
||||
(
|
||||
input wire clk,
|
||||
my_if.slave_mp in_if [2],
|
||||
my_if.master_mp out_if [2]
|
||||
);
|
||||
|
||||
assign out_if[0].valid = in_if[0].valid;
|
||||
assign out_if[0].data = in_if[0].data;
|
||||
|
||||
assign out_if[1].valid = in_if[1].valid;
|
||||
assign out_if[1].data = in_if[1].data;
|
||||
|
||||
endmodule
|
16
test_regress/t/t_lint_iface_array_topmodule3.pl
Executable file
16
test_regress/t/t_lint_iface_array_topmodule3.pl
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2008 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(linter => 1);
|
||||
|
||||
lint();
|
||||
|
||||
ok(1);
|
||||
1;
|
77
test_regress/t/t_lint_iface_array_topmodule3.v
Normal file
77
test_regress/t/t_lint_iface_array_topmodule3.v
Normal file
@ -0,0 +1,77 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Josh Redford.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
interface my_if #( parameter integer DW = 8 ) (input clk);
|
||||
|
||||
localparam DW_LOCAL = DW;
|
||||
|
||||
logic valid;
|
||||
logic [DW-1:0] data;
|
||||
|
||||
modport slave_mp (
|
||||
input valid,
|
||||
input data
|
||||
);
|
||||
|
||||
modport master_mp (
|
||||
output valid,
|
||||
output data
|
||||
);
|
||||
|
||||
function automatic integer width();
|
||||
return $bits(data);
|
||||
endfunction
|
||||
|
||||
generate
|
||||
if (DW < 4)
|
||||
begin: dw_lt_4_G
|
||||
function automatic integer min_width();
|
||||
return 4;
|
||||
endfunction
|
||||
end
|
||||
else
|
||||
begin: dw_ge_4_G
|
||||
function automatic integer min_width();
|
||||
return 8;
|
||||
endfunction
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endinterface
|
||||
|
||||
module t
|
||||
(
|
||||
input wire clk,
|
||||
my_if in_if [2],
|
||||
my_if out_if [2]
|
||||
);
|
||||
|
||||
assign out_if[0].valid = in_if[0].valid;
|
||||
assign out_if[0].data = in_if[0].data;
|
||||
|
||||
assign out_if[1].valid = in_if[1].valid;
|
||||
assign out_if[1].data = in_if[1].data;
|
||||
|
||||
my_if my_i (.clk(clk));
|
||||
|
||||
initial
|
||||
begin
|
||||
$display(in_if[0].DW_LOCAL);
|
||||
$display(in_if[0].width());
|
||||
$display(in_if[0].dw_ge_4_G.min_width());
|
||||
$display(out_if[0].DW_LOCAL);
|
||||
$display(out_if[0].width());
|
||||
$display(out_if[0].dw_ge_4_G.min_width());
|
||||
|
||||
$display(in_if[1].DW_LOCAL);
|
||||
$display(in_if[1].width());
|
||||
$display(in_if[1].dw_ge_4_G.min_width());
|
||||
$display(out_if[1].DW_LOCAL);
|
||||
$display(out_if[1].width());
|
||||
$display(out_if[1].dw_ge_4_G.min_width());
|
||||
end
|
||||
|
||||
endmodule
|
5
test_regress/t/t_lint_iface_array_topmodule_bad.out
Normal file
5
test_regress/t/t_lint_iface_array_topmodule_bad.out
Normal file
@ -0,0 +1,5 @@
|
||||
%Error: t/t_lint_iface_array_topmodule_bad.v:8:24: Parameter without initial value is never given value (IEEE 1800-2017 6.20.1): 'DW'
|
||||
: ... In instance t
|
||||
8 | parameter integer DW
|
||||
| ^~
|
||||
%Error: Exiting due to
|
19
test_regress/t/t_lint_iface_array_topmodule_bad.pl
Executable file
19
test_regress/t/t_lint_iface_array_topmodule_bad.pl
Executable file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2008 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(linter => 1);
|
||||
|
||||
lint(
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
50
test_regress/t/t_lint_iface_array_topmodule_bad.v
Normal file
50
test_regress/t/t_lint_iface_array_topmodule_bad.v
Normal file
@ -0,0 +1,50 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Josh Redford.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
interface my_if #(
|
||||
parameter integer DW
|
||||
) ();
|
||||
|
||||
logic valid;
|
||||
logic [7:0] data ;
|
||||
|
||||
modport slave_mp (
|
||||
input valid,
|
||||
input data
|
||||
);
|
||||
|
||||
modport master_mp (
|
||||
output valid,
|
||||
output data
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
||||
module t
|
||||
(
|
||||
input wire clk,
|
||||
my_if.slave_mp in_if [2],
|
||||
my_if.master_mp out_if [2]
|
||||
);
|
||||
|
||||
my_if my_i [2] ();
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
my_i[0].valid <= in_if[0].valid;
|
||||
my_i[0].data <= in_if[0].data;
|
||||
|
||||
my_i[1].valid <= in_if[1].valid;
|
||||
my_i[1].data <= in_if[1].data;
|
||||
end
|
||||
|
||||
assign out_if[0].valid = my_i[0].valid;
|
||||
assign out_if[0].data = my_i[0].data;
|
||||
|
||||
assign out_if[1].valid = my_i[1].valid;
|
||||
assign out_if[1].data = my_i[1].data;
|
||||
|
||||
endmodule
|
16
test_regress/t/t_lint_iface_topmodule1.pl
Executable file
16
test_regress/t/t_lint_iface_topmodule1.pl
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2008 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(linter => 1);
|
||||
|
||||
lint();
|
||||
|
||||
ok(1);
|
||||
1;
|
42
test_regress/t/t_lint_iface_topmodule1.v
Normal file
42
test_regress/t/t_lint_iface_topmodule1.v
Normal file
@ -0,0 +1,42 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Josh Redford.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
interface my_if;
|
||||
|
||||
logic valid;
|
||||
logic [7:0] data ;
|
||||
|
||||
modport slave_mp (
|
||||
input valid,
|
||||
input data
|
||||
);
|
||||
|
||||
modport master_mp (
|
||||
output valid,
|
||||
output data
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
||||
module t
|
||||
(
|
||||
input wire clk,
|
||||
my_if.slave_mp in_if,
|
||||
my_if.master_mp out_if
|
||||
);
|
||||
|
||||
my_if my_i ();
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
my_i.valid <= in_if.valid;
|
||||
my_i.data <= in_if.data;
|
||||
end
|
||||
|
||||
assign out_if.valid = my_i.valid;
|
||||
assign out_if.data = my_i.data;
|
||||
|
||||
endmodule
|
16
test_regress/t/t_lint_iface_topmodule2.pl
Executable file
16
test_regress/t/t_lint_iface_topmodule2.pl
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2008 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(linter => 1);
|
||||
|
||||
lint();
|
||||
|
||||
ok(1);
|
||||
1;
|
35
test_regress/t/t_lint_iface_topmodule2.v
Normal file
35
test_regress/t/t_lint_iface_topmodule2.v
Normal file
@ -0,0 +1,35 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Josh Redford.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
interface my_if #(
|
||||
parameter integer DW = 8
|
||||
) ();
|
||||
logic valid;
|
||||
logic [DW-1:0] data;
|
||||
|
||||
modport slave_mp (
|
||||
input valid,
|
||||
input data
|
||||
);
|
||||
|
||||
modport master_mp (
|
||||
output valid,
|
||||
output data
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
||||
module t
|
||||
(
|
||||
input wire clk,
|
||||
my_if.slave_mp in_if,
|
||||
my_if.master_mp out_if
|
||||
);
|
||||
|
||||
assign out_if.valid = in_if.valid;
|
||||
assign out_if.data = in_if.data;
|
||||
|
||||
endmodule
|
16
test_regress/t/t_lint_iface_topmodule3.pl
Executable file
16
test_regress/t/t_lint_iface_topmodule3.pl
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2008 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(linter => 1);
|
||||
|
||||
lint();
|
||||
|
||||
ok(1);
|
||||
1;
|
67
test_regress/t/t_lint_iface_topmodule3.v
Normal file
67
test_regress/t/t_lint_iface_topmodule3.v
Normal file
@ -0,0 +1,67 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Josh Redford.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
interface my_if #( parameter integer DW = 8 ) (input clk);
|
||||
|
||||
localparam DW_LOCAL = DW;
|
||||
|
||||
logic valid;
|
||||
logic [DW-1:0] data;
|
||||
|
||||
modport slave_mp (
|
||||
input valid,
|
||||
input data
|
||||
);
|
||||
|
||||
modport master_mp (
|
||||
output valid,
|
||||
output data
|
||||
);
|
||||
|
||||
function automatic integer width();
|
||||
return $bits(data);
|
||||
endfunction
|
||||
|
||||
generate
|
||||
if (DW < 4)
|
||||
begin: dw_lt_4_G
|
||||
function automatic integer min_width();
|
||||
return 4;
|
||||
endfunction
|
||||
end
|
||||
else
|
||||
begin: dw_ge_4_G
|
||||
function automatic integer min_width();
|
||||
return 8;
|
||||
endfunction
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endinterface
|
||||
|
||||
module t
|
||||
(
|
||||
input wire clk,
|
||||
my_if in_if,
|
||||
my_if out_if
|
||||
);
|
||||
|
||||
assign out_if.valid = in_if.valid;
|
||||
assign out_if.data = in_if.data;
|
||||
|
||||
my_if my_i (.clk(clk));
|
||||
|
||||
initial
|
||||
begin
|
||||
$display(in_if.DW_LOCAL);
|
||||
$display(in_if.width());
|
||||
$display(in_if.dw_ge_4_G.min_width());
|
||||
$display(out_if.DW_LOCAL);
|
||||
$display(out_if.width());
|
||||
$display(out_if.dw_ge_4_G.min_width());
|
||||
end
|
||||
|
||||
endmodule
|
5
test_regress/t/t_lint_iface_topmodule_bad.out
Normal file
5
test_regress/t/t_lint_iface_topmodule_bad.out
Normal file
@ -0,0 +1,5 @@
|
||||
%Error: t/t_lint_iface_topmodule_bad.v:8:23: Parameter without initial value is never given value (IEEE 1800-2017 6.20.1): 'DW'
|
||||
: ... In instance t
|
||||
8 | parameter integer DW
|
||||
| ^~
|
||||
%Error: Exiting due to
|
19
test_regress/t/t_lint_iface_topmodule_bad.pl
Executable file
19
test_regress/t/t_lint_iface_topmodule_bad.pl
Executable file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2008 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(linter => 1);
|
||||
|
||||
lint(
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
44
test_regress/t/t_lint_iface_topmodule_bad.v
Normal file
44
test_regress/t/t_lint_iface_topmodule_bad.v
Normal file
@ -0,0 +1,44 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Josh Redford.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
interface my_if #(
|
||||
parameter integer DW
|
||||
) ();
|
||||
|
||||
logic valid;
|
||||
logic [DW-1:0] data ;
|
||||
|
||||
modport slave_mp (
|
||||
input valid,
|
||||
input data
|
||||
);
|
||||
|
||||
modport master_mp (
|
||||
output valid,
|
||||
output data
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
||||
module t
|
||||
(
|
||||
input wire clk,
|
||||
my_if.slave_mp in_if,
|
||||
my_if.master_mp out_if
|
||||
);
|
||||
|
||||
my_if my_i ();
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
my_i.valid <= in_if.valid;
|
||||
my_i.data <= in_if.data;
|
||||
end
|
||||
|
||||
assign out_if.valid = my_i.valid;
|
||||
assign out_if.data = my_i.data;
|
||||
|
||||
endmodule
|
8
test_regress/t/t_tri_and_eqcase.out
Normal file
8
test_regress/t/t_tri_and_eqcase.out
Normal file
@ -0,0 +1,8 @@
|
||||
%Error-UNSUPPORTED: t/t_tri_and_eqcase.v:9:28: Unsupported tristate construct: AND in function getEnExprBasedOnOriginalp
|
||||
9 | logic b = 1'z === (clk1 & clk2);
|
||||
| ^
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error: Internal Error: t/t_tri_and_eqcase.v:9:18: ../V3Ast.cpp:#: Null item passed to setOp2p
|
||||
9 | logic b = 1'z === (clk1 & clk2);
|
||||
| ^~~
|
||||
... See the manual at https://verilator.org/verilator_doc.html for more assistance.
|
19
test_regress/t/t_tri_and_eqcase.pl
Executable file
19
test_regress/t/t_tri_and_eqcase.pl
Executable file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(vlt => 1);
|
||||
|
||||
lint(
|
||||
fails => $Self->{vlt_all},
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
17
test_regress/t/t_tri_and_eqcase.v
Normal file
17
test_regress/t/t_tri_and_eqcase.v
Normal file
@ -0,0 +1,17 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2022 by Antmicro Ltd.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (clk1, clk2);
|
||||
input wire clk1, clk2;
|
||||
logic b = 1'z === (clk1 & clk2);
|
||||
|
||||
always begin
|
||||
if (!b) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
endmodule
|
21
test_regress/t/t_tri_select_eqcase.pl
Executable file
21
test_regress/t/t_tri_select_eqcase.pl
Executable file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2022 by Antmicro Ltd. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
26
test_regress/t/t_tri_select_eqcase.v
Normal file
26
test_regress/t/t_tri_select_eqcase.v
Normal file
@ -0,0 +1,26 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2022 by Antmicro Ltd.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
wire [3:0] a = 4'b11z1;
|
||||
logic b = 1'bz === a[1];
|
||||
logic c = 1'bz === a[2];
|
||||
logic d = 2'bzz === 2'(a[1]);
|
||||
logic e = 2'b0z === 2'(a[1]);
|
||||
|
||||
|
||||
always begin
|
||||
if (b && !c && !d && e) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
else begin
|
||||
$write("Error: b = %b, c = %b, d = %b, e = %b ", b, c, d, e);
|
||||
$write("expected: b = 1, c = 0, d = 0, e = 1\n");
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user