Support linting for top module interfaces (#3635)
This commit is contained in:
parent
46b8dca360
commit
159cf0429c
|
|
@ -423,10 +423,45 @@ 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:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes, bool elimScopes,
|
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes, bool elimScopes,
|
||||||
bool elimCells)
|
bool elimCells, bool elimTopIfaces)
|
||||||
: m_elimUserVars{elimUserVars}
|
: m_elimUserVars{elimUserVars}
|
||||||
, m_elimDTypes{elimDTypes}
|
, m_elimDTypes{elimDTypes}
|
||||||
, m_elimCells{elimCells} {
|
, m_elimCells{elimCells} {
|
||||||
|
|
@ -442,6 +477,7 @@ public:
|
||||||
if (elimCells) deadCheckCells();
|
if (elimCells) deadCheckCells();
|
||||||
deadCheckClasses();
|
deadCheckClasses();
|
||||||
// Modules after vars, because might be vars we delete inside a mod we delete
|
// Modules after vars, because might be vars we delete inside a mod we delete
|
||||||
|
if (!elimTopIfaces) preserveTopIfaces(nodep);
|
||||||
deadCheckMod();
|
deadCheckMod();
|
||||||
|
|
||||||
// We may have removed some datatypes, cleanup
|
// We may have removed some datatypes, cleanup
|
||||||
|
|
@ -455,30 +491,30 @@ public:
|
||||||
|
|
||||||
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
||||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
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);
|
V3Global::dumpCheckGlobalTree("deadModules", 0, dumpTree() >= 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
|
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
|
||||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
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);
|
V3Global::dumpCheckGlobalTree("deadDtypes", 0, dumpTree() >= 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) {
|
void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) {
|
||||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
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);
|
V3Global::dumpCheckGlobalTree("deadDtypesScoped", 0, dumpTree() >= 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
||||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
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);
|
V3Global::dumpCheckGlobalTree("deadAll", 0, dumpTree() >= 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
|
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
|
||||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
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);
|
V3Global::dumpCheckGlobalTree("deadAllScoped", 0, dumpTree() >= 3);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -308,6 +308,19 @@ public:
|
||||||
if (forScopeCreation()) m_nameScopeSymMap.emplace(scopename, symp);
|
if (forScopeCreation()) m_nameScopeSymMap.emplace(scopename, symp);
|
||||||
return 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,
|
VSymEnt* insertCell(VSymEnt* abovep, VSymEnt* modSymp, AstCell* nodep,
|
||||||
const string& scopename) {
|
const string& scopename) {
|
||||||
UASSERT_OBJ(abovep, nodep, "Null symbol table inserting node");
|
UASSERT_OBJ(abovep, nodep, "Null symbol table inserting node");
|
||||||
|
|
@ -764,8 +777,46 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||||
modp = VN_AS(modp->nextp(), NodeModule)) {
|
modp = VN_AS(modp->nextp(), NodeModule)) {
|
||||||
UINFO(8, "Top Module: " << modp << endl);
|
UINFO(8, "Top Module: " << modp << endl);
|
||||||
m_scope = "TOP";
|
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);
|
m_curSymp = m_modSymp = m_statep->insertTopCell(modp, m_scope);
|
||||||
{ iterate(modp); }
|
{ iterate(modp); }
|
||||||
|
|
||||||
m_scope = "";
|
m_scope = "";
|
||||||
m_curSymp = m_modSymp = nullptr;
|
m_curSymp = m_modSymp = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -200,6 +200,35 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
|
||||||
ioNames.insert(oldvarp->name());
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -257,6 +286,81 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
|
||||||
pinp->modVarp(oldvarp);
|
pinp->modVarp(oldvarp);
|
||||||
cellp->addPinsp(pinp);
|
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()));
|
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;
|
// Only AstIfaceRefDType's at this point correspond to ports;
|
||||||
// haven't made additional ones for interconnect yet, so assert is simple
|
// haven't made additional ones for interconnect yet, so assert is simple
|
||||||
// What breaks later is we don't have a Scope/Cell representing
|
// What breaks later is we don't have a Scope/Cell representing
|
||||||
|
|
|
||||||
|
|
@ -490,6 +490,7 @@ public:
|
||||||
bool vpi() const { return m_vpi; }
|
bool vpi() const { return m_vpi; }
|
||||||
bool xInitialEdge() const { return m_xInitialEdge; }
|
bool xInitialEdge() const { return m_xInitialEdge; }
|
||||||
bool xmlOnly() const { return m_xmlOnly; }
|
bool xmlOnly() const { return m_xmlOnly; }
|
||||||
|
bool topIfacesSupported() const { return lintOnly() && !hierarchical(); }
|
||||||
|
|
||||||
int buildJobs() const { return m_buildJobs; }
|
int buildJobs() const { return m_buildJobs; }
|
||||||
int convergeLimit() const { return m_convergeLimit; }
|
int convergeLimit() const { return m_convergeLimit; }
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||||
|
|
||||||
scenarios(vlt => 1);
|
scenarios(vlt => 1);
|
||||||
|
|
||||||
lint(
|
compile(
|
||||||
fails => 1,
|
fails => 1,
|
||||||
expect_filename => $Self->{golden_filename},
|
expect_filename => $Self->{golden_filename},
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue