Support "package" and $unit.

Add VARHIDDEN warning when signal name hides module name.
This commit is contained in:
Wilson Snyder 2009-11-07 21:05:02 -05:00
parent bc2d3a13f4
commit 68567e763c
23 changed files with 413 additions and 120 deletions

View File

@ -16,8 +16,12 @@ indicates the contributor was also the author of the fix; Thanks!
*** Support "program".
*** Support "package" and $unit.
*** Support typedef. [Donal Casey]
*** Add VARHIDDEN warning when signal name hides module name.
* Verilator 3.720 2009/10/26
** Support little endian bit vectors ("reg [0:2] x;").

View File

@ -1122,17 +1122,18 @@ private:
bool m_lvalue; // Left hand side assignment
AstVar* m_varp; // [AfterLink] Pointer to variable itself
AstVarScope* m_varScopep; // Varscope for hierarchy
AstPackage* m_packagep; // Package hierarchy
string m_name; // Name of variable
string m_hiername; // Scope converted into name-> for emitting
bool m_hierThis; // Hiername points to "this" function
public:
AstNodeVarRef(FileLine* fl, const string& name, bool lvalue)
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(NULL), m_varScopep(NULL),
m_name(name), m_hierThis(false) {
m_packagep(NULL), m_name(name), m_hierThis(false) {
}
AstNodeVarRef(FileLine* fl, const string& name, AstVar* varp, bool lvalue)
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(varp), m_varScopep(NULL),
m_name(name), m_hierThis(false) {
m_packagep(NULL), m_name(name), m_hierThis(false) {
// May have varp==NULL
if (m_varp) widthSignedFrom((AstNode*)m_varp);
}
@ -1152,6 +1153,8 @@ public:
void hiername(const string& hn) { m_hiername = hn; }
bool hierThis() const { return m_hierThis; }
void hierThis(bool flag) { m_hierThis = flag; }
AstPackage* packagep() const { return m_packagep; }
void packagep(AstPackage* nodep) { m_packagep=nodep; }
// Know no children, and hot function, so skip iterator for speed
// See checkTreeIter also that asserts no children
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
@ -1251,10 +1254,11 @@ private:
string m_name; // Name of variable
string m_dotted; // Dotted part of scope to task or ""
string m_inlinedDots; // Dotted hierarchy flattened out
AstPackage* m_packagep; // Package hierarchy
public:
AstNodeFTaskRef(FileLine* fl, AstNode* namep, AstNode* pinsp)
:AstNode(fl)
, m_taskp(NULL) {
, m_taskp(NULL), m_packagep(NULL) {
setOp1p(namep); addNOp2p(pinsp);
}
ASTNODE_BASE_FUNCS(NodeFTaskRef)
@ -1272,6 +1276,8 @@ public:
void taskp(AstNodeFTask* taskp) { m_taskp=taskp; }
virtual void name(const string& name) { m_name = name; }
void dotted(const string& name) { m_dotted = name; }
AstPackage* packagep() const { return m_packagep; }
void packagep(AstPackage* nodep) { m_packagep=nodep; }
// op1 = namep
AstNode* namep() const { return op1p(); }
// op2 = Pin interconnection list

View File

@ -230,11 +230,12 @@ public:
struct AstRefDType : public AstNodeDType {
AstTypedef* m_defp;
string m_name;
AstPackage* m_packagep; // Package hierarchy
public:
AstRefDType(FileLine* fl, const string& name)
: AstNodeDType(fl), m_defp(NULL), m_name(name) {}
: AstNodeDType(fl), m_defp(NULL), m_name(name), m_packagep(NULL) {}
AstRefDType(FileLine* fl, AstTypedef* defp)
: AstNodeDType(fl), m_defp(defp), m_name(defp->name()) {
: AstNodeDType(fl), m_defp(defp), m_name(defp->name()), m_packagep(NULL) {
widthSignedFrom(defp);
}
ASTNODE_NODE_FUNCS(RefDType, REFDTYPE)
@ -261,6 +262,8 @@ public:
AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); } // op1 = Range of variable
AstTypedef* defp() const { return m_defp; }
void defp(AstTypedef* nodep) { m_defp=nodep; }
AstPackage* packagep() const { return m_packagep; }
void packagep(AstPackage* nodep) { m_packagep=nodep; }
};
//######################################################################
@ -763,6 +766,15 @@ struct AstModule : public AstNodeModule {
ASTNODE_NODE_FUNCS(Module, MODULE)
};
struct AstPackage : public AstNodeModule {
// A package declaration
AstPackage(FileLine* fl, const string& name)
: AstNodeModule (fl,name) {}
ASTNODE_NODE_FUNCS(Package, PACKAGE)
static string dollarUnitName() { return AstNode::encodeName("$unit"); }
bool isDollarUnit() const { return name() == dollarUnitName(); }
};
struct AstCell : public AstNode {
// A instantiation cell or interface call (don't know which until link)
private:

View File

@ -22,6 +22,8 @@
// Remove any unreferenced modules
// Remove any unreferenced variables
//
// NOTE: If redo this, consider using maybePointedTo()/broken() ish scheme
// instead of needing as many visitors.
//*************************************************************************
#include "config_build.h"
@ -104,6 +106,21 @@ private:
if (nodep->varp()) {
nodep->varp()->user1(nodep->varp()->user1() + 1);
}
if (nodep->packagep()) {
nodep->packagep()->user1(nodep->packagep()->user1() + 1);
}
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->packagep()) {
nodep->packagep()->user1(nodep->packagep()->user1() + 1);
}
}
virtual void visit(AstRefDType* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->packagep()) {
nodep->packagep()->user1(nodep->packagep()->user1() + 1);
}
}
virtual void visit(AstVarScope* nodep, AstNUser*) {
nodep->iterateChildren(*this);

View File

@ -101,7 +101,7 @@ private:
nodep->name(name);
nodep->iterateChildren(*this);
}
if (nodep->modp()->user1p()) { // Marked with inline request
if (nodep->modp()->user1()) { // Marked with inline request
if (m_cellp) nodep->v3error("Cloning should have already been done bottom-up");
UINFO(5," Inline CELL "<<nodep<<endl);
UINFO(5," To MOD "<<m_modp<<endl);
@ -343,6 +343,8 @@ private:
|| m_stmtCnt < INLINE_MODS_SMALLER
|| v3Global.opt.inlineMult() < 1
|| refs*m_stmtCnt < v3Global.opt.inlineMult())));
// Packages aren't really "under" anything so they confuse this algorithm
if (nodep->castPackage()) doit = false;
UINFO(4, " Inline="<<doit<<" Possible="<<allowed<<" Usr="<<userinline<<" Refs="<<refs<<" Stmts="<<m_stmtCnt
<<" "<<nodep<<endl);
if (doit) {
@ -381,7 +383,7 @@ private:
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
// Cleanup link until V3LinkDot can correct it
nodep->taskp(NULL);
if (!nodep->packagep()) nodep->taskp(NULL);
nodep->iterateChildren(*this);
}
// Nop's to speed up the loop
@ -430,7 +432,7 @@ void V3Inline::inlineAll(AstNetlist* nodep) {
AstNodeModule* nextmodp;
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=nextmodp) {
nextmodp = modp->nextp()->castNodeModule();
if (modp->user1p()) { // Was inlined
if (modp->user1()) { // Was inlined
modp->unlinkFrBack()->deleteTree(); modp=NULL;
}
}

View File

@ -48,14 +48,15 @@ class LinkVisitor : public AstNVisitor {
private:
// NODE STATE
// Entire netlist:
// AstNodeModule::user1p() // V3SymTable* Module's Symbol table
// AstNodeFTask::user1p() // V3SymTable* Local Symbol table
// AstBegin::user1p() // V3SymTable* Local Symbol table
// AstVar/Module/Task::user1() // AstPackage* Set if inside a package
// AstVar::user2p() // bool True if port set for this variable
// AstVar/Module::user3p() // V3SymTable* Table used to create this variable
AstUser1InUse m_inuser1;
// AstNodeModule::user4p() // V3SymTable* Module's Symbol table
// AstNodeFTask::user4p() // V3SymTable* Local Symbol table
// AstBegin::user4p() // V3SymTable* Local Symbol table
AstUser2InUse m_inuser2;
AstUser3InUse m_inuser3;
AstUser4InUse m_inuser4;
// ENUMS
enum IdState { // Which loop through the tree
@ -65,7 +66,8 @@ private:
// STATE
// Below state needs to be preserved between each module call.
AstNodeModule* m_modp; // Current module
AstPackage* m_packagep; // Current package
AstNodeModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Current function/task
IdState m_idState; // Id linking mode (find or resolve)
int m_paramNum; // Parameter number, for position based connection
@ -85,37 +87,52 @@ private:
// METHODS
V3SymTable* symsFindNew(AstNode* nodep, V3SymTable* upperVarsp) {
// Find or create symbol table for this node
if (V3SymTable* symsp = nodep->user1p()->castSymTable()) {
if (V3SymTable* symsp = nodep->user4p()->castSymTable()) {
return symsp;
} else {
V3SymTable* symsp = new V3SymTable(nodep, upperVarsp);
m_delSymps.push_back(symsp);
nodep->user1p(symsp);
nodep->user4p(symsp);
return symsp;
}
}
V3SymTable* symsFind(AstNode* nodep) {
// Find or create symbol table for this node
if (V3SymTable* symsp = nodep->user4p()->castSymTable()) {
return symsp;
} else {
nodep->v3fatalSrc("Symbol table not found looking up symbol");
return NULL;
}
}
void symsInsert(const string& name, AstNode* nodep) {
// Insert into symbol table, and remember what table the node is in
m_curVarsp->insert(name, nodep);
nodep->user3p(m_curVarsp);
nodep->user1p(m_packagep);
}
AstPackage* packageFor(AstNode* nodep) {
if (nodep) return nodep->user1p()->castNode()->castPackage(); // Loaded by symsInsert
else return NULL;
}
void linkVarName (AstVarRef* nodep) {
if (!nodep->varp()) {
AstVar* varp = m_curVarsp->findIdUpward(nodep->name())->castVar();
nodep->varp(varp);
nodep->packagep(packageFor(varp));
}
}
const char* nodeTextType(AstNode* nodep) {
const char* what = "node";
if (nodep->castVar()) what = "variable";
else if (nodep->castCell()) what = "cell";
else if (nodep->castTask()) what = "task";
else if (nodep->castFunc()) what = "function";
else if (nodep->castBegin()) what = "block";
return what;
string nodeTextType(AstNode* nodep) {
if (nodep->castVar()) return "variable";
else if (nodep->castCell()) return "cell";
else if (nodep->castTask()) return "task";
else if (nodep->castFunc()) return "function";
else if (nodep->castBegin()) return "block";
else return nodep->prettyTypeName();
}
string ucfirst(const string& text) {
@ -171,13 +188,13 @@ private:
// VISITs
virtual void visit(AstNetlist* nodep, AstNUser*) {
// Look at all modules, and store pointers to all module names
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=modp->nextp()->castNodeModule()) {
symsFindNew(modp, NULL);
}
// Top scope
m_curVarsp = symsFindNew(nodep, NULL);
// And recurse...
// Recurse...
m_idState = ID_FIND;
nodep->iterateChildren(*this);
if (debug()==9) m_curVarsp->dump(cout,"-curvars: ",true/*user4p_is_table*/);
m_idState = ID_PARAM;
nodep->iterateChildren(*this);
m_idState = ID_RESOLVE;
@ -188,18 +205,30 @@ private:
virtual void visit(AstNodeModule* nodep, AstNUser*) {
// Module: Create sim table for entire module and iterate
UINFO(2,"Link Module: "<<nodep<<endl);
m_modp = nodep;
// This state must be save/restored in the cell visitor function
m_curVarsp = symsFindNew(nodep, NULL);
if (!m_curVarsp) nodep->v3fatalSrc("NULL");
m_cellVarsp = NULL;
m_paramNum = 0;
m_beginNum = 0;
m_modBeginNum = 0;
nodep->iterateChildren(*this);
// Prep for next
m_curVarsp = NULL;
m_modp = NULL;
V3SymTable* upperVarsp = m_curVarsp;
{
m_modp = nodep;
if (!m_curVarsp) nodep->v3fatalSrc("NULL");
if (nodep->castPackage()) m_packagep = nodep->castPackage();
if (m_packagep && m_packagep->isDollarUnit()) { // $unit goes on "top"
nodep->user4p(m_curVarsp);
// Don't insert dunit itself, or symtable->dump will loop-recurse
} else {
findAndInsertAndCheck(nodep, nodep->name());
m_curVarsp = symsFindNew(nodep, upperVarsp);
UINFO(9, "New module scope "<<m_curVarsp<<endl);
}
// This state must be save/restored in the cell visitor function
m_cellVarsp = NULL;
m_paramNum = 0;
m_beginNum = 0;
m_modBeginNum = 0;
nodep->iterateChildren(*this);
// Prep for next
m_modp = NULL;
m_packagep = NULL;
}
m_curVarsp = upperVarsp;
}
virtual void visit(AstGenerate* nodep, AstNUser*) {
@ -231,12 +260,12 @@ private:
bool ins=false;
if (!foundp) {
ins=true;
} else if (!findvarp) {
} else if (!findvarp && m_curVarsp->findIdFlat(nodep->name())) {
nodep->v3error("Unsupported in C: Variable has same name as "
<<nodeTextType(foundp)<<": "<<nodep->prettyName());
} else if (findvarp != nodep) {
UINFO(4,"DupVar: "<<nodep<<" ;; "<<findvarp<<endl);
if (findvarp->user3p() == m_curVarsp) { // Only when on same level
UINFO(4,"DupVar: "<<nodep<<" ;; "<<foundp<<endl);
if (findvarp && findvarp->user3p() == m_curVarsp) { // Only when on same level
if ((findvarp->isIO() && nodep->isSignal())
|| (findvarp->isSignal() && nodep->isIO())) {
findvarp->combineType(nodep);
@ -249,9 +278,9 @@ private:
} else {
// User can disable the message at either point
if (!nodep->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)
&& !findvarp->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)) {
&& !foundp->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)) {
nodep->v3warn(VARHIDDEN,"Declaration of signal hides declaration in upper scope: "<<nodep->name());
findvarp->v3warn(VARHIDDEN,"... Location of original declaration");
foundp->v3warn(VARHIDDEN,"... Location of original declaration");
}
ins = true;
}
@ -368,9 +397,15 @@ private:
// NodeFTaskRef: Resolve its reference
if (m_idState==ID_RESOLVE && !nodep->taskp()) {
if (nodep->dotted() == "") {
AstNodeFTask* taskp = m_curVarsp->findIdUpward(nodep->name())->castNodeFTask();
AstNodeFTask* taskp;
if (nodep->packagep()) {
taskp = symsFind(nodep->packagep())->findIdUpward(nodep->name())->castNodeFTask();
} else {
taskp = m_curVarsp->findIdUpward(nodep->name())->castNodeFTask();
}
if (!taskp) { nodep->v3error("Can't find definition of task/function: "<<nodep->prettyName()); }
nodep->taskp(taskp);
nodep->packagep(packageFor(taskp));
}
}
nodep->iterateChildren(*this);
@ -393,9 +428,15 @@ private:
virtual void visit(AstRefDType* nodep, AstNUser*) {
// Resolve its reference
if (m_idState==ID_RESOLVE && !nodep->defp()) {
AstTypedef* defp = m_curVarsp->findIdUpward(nodep->name())->castTypedef();
AstTypedef* defp;
if (nodep->packagep()) {
defp = symsFind(nodep->packagep())->findIdFlat(nodep->name())->castTypedef();
} else {
defp = m_curVarsp->findIdUpward(nodep->name())->castTypedef();
}
if (!defp) { nodep->v3error("Can't find typedef: "<<nodep->prettyName()); }
nodep->defp(defp);
nodep->packagep(packageFor(defp));
}
nodep->iterateChildren(*this);
}
@ -411,12 +452,14 @@ private:
}
else {
// Need to pass the module info to this cell, so we can link up the pin names
m_cellVarsp = nodep->modp()->user1p()->castSymTable();
UINFO(4,"(Backto) Link Cell: "<<nodep<<endl);
//if (debug()) { nodep->dumpTree(cout,"linkcell:"); }
//if (debug()) { nodep->modp()->dumpTree(cout,"linkcemd:"); }
nodep->iterateChildren(*this);
m_cellVarsp = NULL;
if (m_idState==ID_RESOLVE) {
m_cellVarsp = nodep->modp()->user4p()->castSymTable();
UINFO(4,"(Backto) Link Cell: "<<nodep<<endl);
//if (debug()) { nodep->dumpTree(cout,"linkcell:"); }
//if (debug()) { nodep->modp()->dumpTree(cout,"linkcemd:"); }
nodep->iterateChildren(*this);
m_cellVarsp = NULL;
}
}
// Parent module inherits child's publicity
// This is done bottom up in the LinkBotupVisitor stage
@ -460,6 +503,7 @@ private:
virtual void visit(AstPin* nodep, AstNUser*) {
// Pin: Link to submodule's pin
// ONLY CALLED by AstCell during ID_RESOLVE state
if (!m_cellVarsp) nodep->v3fatalSrc("Pin not under cell?\n");
if (m_idState==ID_RESOLVE && !nodep->modVarp()) {
AstVar* refp = m_cellVarsp->findIdFlat(nodep->name())->castVar();
@ -523,6 +567,7 @@ public:
m_cellVarsp = NULL;
m_modp = NULL;
m_ftaskp = NULL;
m_packagep = NULL;
m_paramNum = 0;
m_beginNum = 0;
m_modBeginNum = 0;

View File

@ -210,6 +210,7 @@ public:
// METHODS
LinkDotCellVertex* insertTopCell(AstNodeModule* nodep, const string& scopename) {
// Only called on the module at the very top of the hierarchy
UINFO(9," INSERTcell "<<scopename<<" "<<nodep<<endl);
LinkDotCellVertex* vxp = new LinkDotCellVertex(&m_graph, nodep);
nodep->user1p(vxp);
@ -382,6 +383,11 @@ private:
// VISITs
virtual void visit(AstNetlist* nodep, AstNUser*) {
// Process $unit or other packages
// Not needed - dotted references not allowed from inside packages
//for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nodep->nextp()->castNodeModule()) {
// if (nodep->castPackage()) {}}
// The first module in the list is always the top module (sorted before this is called).
// This may not be the module with isTop() set, as early in the steps,
// wrapTop may have not been created yet.
@ -402,6 +408,8 @@ private:
}
}
virtual void visit(AstNodeModule* nodep, AstNUser*) {
// Called on top module from Netlist, other modules from the cell creating them,
// and packages
UINFO(8," "<<nodep<<endl);
if (!m_cellVxp) {
// Will be optimized away later
@ -667,7 +675,9 @@ private:
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
UINFO(8," "<<nodep<<endl);
if (!m_cellVxp) {
if (nodep->packagep()) {
// References into packages don't care about cell hierarchy.
} else if (!m_cellVxp) {
UINFO(9,"Dead module for "<<nodep<<endl);
nodep->taskp(NULL); // Module that is not in hierarchy. We'll be dead code eliminating it later.
} else {

View File

@ -128,4 +128,23 @@ void V3LinkLevel::wrapTop(AstNetlist* netlistp) {
}
}
}
wrapTopPackages(netlistp, newmodp);
}
void V3LinkLevel::wrapTopPackages(AstNetlist* netlistp, AstNodeModule* newmodp) {
// Instantiate all packages under the top wrapper
// This way all later SCOPE based optimizations can ignore packages
for (AstNodeModule* modp = netlistp->modulesp(); modp; modp=modp->nextp()->castNodeModule()) {
if (modp->castPackage()) {
AstCell* cellp = new AstCell(modp->fileline(),
// Could add __03a__03a="::" to prevent conflict
// with module names/"v"
modp->name(),
modp->name(),
NULL, NULL, NULL);
cellp->modp(modp);
newmodp->addStmtp(cellp);
}
}
}

View File

@ -30,6 +30,8 @@
//============================================================================
class V3LinkLevel {
private:
static void wrapTopPackages(AstNetlist* nodep, AstNodeModule* newmodp);
public:
static void modSortByLevel();
static void wrapTop(AstNetlist* nodep);

View File

@ -45,7 +45,7 @@ typedef enum { uniq_NONE, uniq_UNIQUE, uniq_PRIORITY } V3UniqState;
struct V3ParseBisonYYSType {
FileLine* fl;
//V3SymTable* scp; // Symbol table scope for future lookups
AstNode* scp; // Symbol table scope for future lookups
union {
V3Number* nump;
string* strp;
@ -64,8 +64,10 @@ struct V3ParseBisonYYSType {
AstNodeModule* modulep;
AstNodeDType* dtypep;
AstNodeFTask* ftaskp;
AstNodeFTaskRef* ftaskrefp;
AstNodeSenItem* senitemp;
AstNodeVarRef* varnodep;
AstPackage* packagep;
AstParseRef* parserefp;
AstPin* pinp;
AstRange* rangep;
@ -88,7 +90,8 @@ private:
// MEMBERS
static int s_anonNum; // Number of next anonymous object
V3SymTable* m_symTableNextId; // Symbol table for next lexer lookup
V3SymTable* m_symCurrentp; // Node with active symbol table for additions/lookups
V3SymTable* m_symCurrentp; // Active symbol table for additions/lookups
V3SymTable* m_symRootp; // Root symbol table
SymStack m_sympStack; // Stack of nodes with symbol tables
SymStack m_symsp; // All symbol tables, to cleanup
@ -102,6 +105,7 @@ private:
public:
V3SymTable* nextId() const { return m_symTableNextId; }
V3SymTable* symCurrentp() const { return m_symCurrentp; }
V3SymTable* symRootp() const { return m_symRootp; }
V3SymTable* findNewTable(AstNode* nodep, V3SymTable* parentp) {
if (!nodep->user4p()) {
@ -112,9 +116,14 @@ public:
return getTable(nodep);
}
void nextId(AstNode* entp) {
if (entp) { UINFO(9,"symTableNextId under "<<entp<<"-"<<entp->type().ascii()<<endl); }
else { UINFO(9,"symTableNextId under NULL"<<endl); }
m_symTableNextId = getTable(entp);
if (entp) {
UINFO(9,"symTableNextId under "<<entp<<"-"<<entp->type().ascii()<<endl);
m_symTableNextId = getTable(entp);
}
else {
UINFO(9,"symTableNextId under NULL"<<endl);
m_symTableNextId = NULL;
}
}
void reinsert(AstNode* nodep, V3SymTable* parentp=NULL) {
if (!parentp) parentp = symCurrentp();
@ -179,6 +188,7 @@ public:
pushScope(findNewTable(rootp, NULL));
m_symTableNextId = NULL;
m_symCurrentp = symCurrentp();
m_symRootp = symCurrentp();
}
~V3ParseSym() {
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) {

View File

@ -46,7 +46,7 @@ class ScopeVisitor : public AstNVisitor {
private:
// NODE STATE
// AstVar::user1p -> AstVarScope replacement for this variable
// AstVarRef::user2p -> bool. True indicates already processed
// AstTask::user2p -> AstTask*. Replacement task
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
@ -69,15 +69,15 @@ private:
AstNodeModule* modp = nodep->topModulep();
if (!modp) { nodep->v3error("No root module specified"); return; }
// Operate starting at the top of the hierarchy
AstNode::user2ClearTree();
m_aboveCellp = NULL;
m_aboveScopep = NULL;
modp->accept(*this);
}
virtual void visit(AstNodeModule* nodep, AstNUser*) {
// Create required blocks and add to module
string scopename = (!m_aboveScopep ? "TOP"
: (m_aboveScopep->name()+"."+m_aboveCellp->name()));
string scopename;
if (!m_aboveScopep) scopename = "TOP";
else scopename = m_aboveScopep->name()+"."+m_aboveCellp->name();
UINFO(4," MOD AT "<<scopename<<" "<<nodep<<endl);
AstNode::user1ClearTree();
@ -129,6 +129,7 @@ private:
// Add to list of blocks under this scope
UINFO(4," Move "<<nodep<<endl);
AstInitial* clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
clonep->iterateChildren(*this); // We iterate under the *clone*
}
@ -136,6 +137,7 @@ private:
// Add to list of blocks under this scope
UINFO(4," Move "<<nodep<<endl);
AstFinal* clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
clonep->iterateChildren(*this); // We iterate under the *clone*
}
@ -143,6 +145,7 @@ private:
// Add to list of blocks under this scope
UINFO(4," Move "<<nodep<<endl);
AstNode* clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
clonep->iterateChildren(*this); // We iterate under the *clone*
}
@ -150,6 +153,7 @@ private:
// Add to list of blocks under this scope
UINFO(4," Move "<<nodep<<endl);
AstNode* clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
clonep->iterateChildren(*this); // We iterate under the *clone*
}
@ -157,6 +161,7 @@ private:
// Add to list of blocks under this scope
UINFO(4," Move "<<nodep<<endl);
AstNode* clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
clonep->iterateChildren(*this); // We iterate under the *clone*
}
@ -164,6 +169,7 @@ private:
// Add to list of blocks under this scope
UINFO(4," Move "<<nodep<<endl);
AstNode* clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
clonep->iterateChildren(*this); // We iterate under the *clone*
}
@ -171,8 +177,9 @@ private:
// Add to list of blocks under this scope
UINFO(4," CFUNC "<<nodep<<endl);
AstCFunc* clonep = nodep->cloneTree(false);
clonep->scopep(m_scopep);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
clonep->scopep(m_scopep);
// We iterate under the *clone*
clonep->iterateChildren(*this);
}
@ -180,6 +187,7 @@ private:
// Add to list of blocks under this scope
UINFO(4," FTASK "<<nodep<<endl);
AstNodeFTask* clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
// We iterate under the *clone*
clonep->iterateChildren(*this);
@ -196,21 +204,10 @@ private:
virtual void visit(AstVarRef* nodep, AstNUser*) {
// VarRef needs to point to VarScope
// Make sure variable has made user1p.
if (!nodep->user2()) {
nodep->varp()->accept(*this);
AstVarScope* varscp = (AstVarScope*)nodep->varp()->user1p();
if (!varscp) nodep->v3fatalSrc("Can't locate varref scope");
nodep->varScopep(varscp);
}
}
virtual void visit(AstVarXRef* nodep, AstNUser*) {
// The crossrefs are dealt with in V3LinkDot
nodep->varp(NULL);
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
// The crossrefs are dealt with in V3LinkDot
nodep->taskp(NULL);
nodep->iterateChildren(*this);
nodep->varp()->accept(*this);
AstVarScope* varscp = (AstVarScope*)nodep->varp()->user1p();
if (!varscp) nodep->v3fatalSrc("Can't locate varref scope");
nodep->varScopep(varscp);
}
virtual void visit(AstScopeName* nodep, AstNUser*) {
// If there's a %m in the display text, we add a special node that will contain the name()
@ -306,6 +303,27 @@ private:
movedDeleteOrIterate(nodep);
}
virtual void visit(AstVarXRef* nodep, AstNUser*) {
// The crossrefs are dealt with in V3LinkDot
nodep->varp(NULL);
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
// The crossrefs are dealt with in V3LinkDot
UINFO(9," Old pkg-taskref "<<nodep<<endl);
if (nodep->packagep()) {
// Point to the clone
if (!nodep->taskp()) nodep->v3fatalSrc("Unlinked");
AstNodeFTask* newp = nodep->taskp()->user2p()->castNode()->castNodeFTask();
if (!newp) nodep->v3fatalSrc("No clone for package function");
nodep->taskp(newp);
UINFO(9," New pkg-taskref "<<nodep<<endl);
} else {
nodep->taskp(NULL);
UINFO(9," New pkg-taskref "<<nodep<<endl);
}
nodep->iterateChildren(*this);
}
//--------------------
// Default
virtual void visit(AstNode* nodep, AstNUser*) {

View File

@ -194,6 +194,7 @@ private:
m_assignwp->convertToAlways(); pushDeletep(m_assignwp); m_assignwp=NULL;
}
// We make multiple edges if a task is called multiple times from another task.
if (!nodep->taskp()) nodep->v3fatalSrc("Unlinked task");
new TaskEdge (&m_callGraph, m_curVxp, getFTaskVertex(nodep->taskp()));
}
virtual void visit(AstNodeFTask* nodep, AstNUser*) {

View File

@ -186,6 +186,7 @@ void process () {
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("assert.tree"));
// Add top level wrapper with instance pointing to old top
// Move packages to under new top
// Must do this after we know the width of any parameters
// We also do it after coverage/assertion insertion so we don't 'cover' the top level.
V3LinkLevel::wrapTop(v3Global.rootp());

View File

@ -357,6 +357,7 @@ escid \\[^ \t\f\r\n]+
"$onehot0" { FL; return yD_ONEHOT0; }
"$warning" { FL; return yD_WARNING; }
/* SV2005 Keywords */
"$unit" { FL; return yD_UNIT; } /* Yes, a keyword, not task */
"always_comb" { FL; return yALWAYS; }
"always_ff" { FL; return yALWAYS; }
"always_latch" { FL; return yALWAYS; }
@ -365,6 +366,7 @@ escid \\[^ \t\f\r\n]+
"clocking" { FL; return yCLOCKING; }
"do" { FL; return yDO; }
"endclocking" { FL; return yENDCLOCKING; }
"endpackage" { FL; return yENDPACKAGE; }
"endprogram" { FL; return yENDPROGRAM; }
"endproperty" { FL; return yENDPROPERTY; }
"final" { FL; return yFINAL; }
@ -372,6 +374,7 @@ escid \\[^ \t\f\r\n]+
"int" { FL; return yINT; }
"logic" { FL; return yLOGIC; }
"longint" { FL; return yLONGINT; }
"package" { FL; return yPACKAGE; }
"priority" { FL; return yPRIORITY; }
"program" { FL; return yPROGRAM; }
"shortint" { FL; return ySHORTINT; }
@ -385,7 +388,6 @@ escid \\[^ \t\f\r\n]+
/* Generic unsupported warnings */
/* Note assert_strobe was in SystemVerilog 3.1, but removed for SystemVerilog 2005 */
"$root" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"$unit" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"alias" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"bind" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
@ -403,7 +405,6 @@ escid \\[^ \t\f\r\n]+
"endclass" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"endgroup" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"endinterface" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"endpackage" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"endsequence" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"enum" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"expect" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
@ -426,7 +427,6 @@ escid \\[^ \t\f\r\n]+
"modport" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"new" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"null" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"package" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"packed" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"protected" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"pure" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
@ -888,13 +888,13 @@ int V3ParseImp::lexToken() {
//if (debug()>=9) SYMP->symCurrentp()->dump(cout," -findtree: ",true);
scp = SYMP->symCurrentp()->findIdUpward(*(yylval.strp));
}
yylval.scp = scp;
if (scp) {
UINFO(7," lexToken: Found "<<scp<<endl);
//UNSUP s_yylvalp->scp = scp;
if (scp->castTypedef()) token = yaID__aTYPE;
else if (scp->castTypedefFwd()) token = yaID__aTYPE;
else if (scp->castPackage()) token = yaID__aPACKAGE;
//UNSUP else if (scp->castClass()) token = yaID__aCLASS;
//UNSUP else if (scp->castPackage()) token = yaID__aPACKAGE;
//UNSUP else if (scp->castCoverGroup()) token = yaID__aCOVERGROUP;
else token = yaID__ETC;
} else { // Not found

View File

@ -44,6 +44,10 @@ extern void yyerrorf(const char* format, ...);
//======================================================================
// Statics (for here only)
#define PARSEP V3ParseImp::parsep()
#define SYMP PARSEP->symp()
#define GRAMMARP V3ParseGrammar::singletonp()
class V3ParseGrammar {
public:
bool m_impliedDecl; // Allow implied wire declarations
@ -96,6 +100,18 @@ public:
if (m_varDTypep) { m_varDTypep->deleteTree(); m_varDTypep=NULL; } // It was cloned, so this is safe.
m_varDTypep = dtypep;
}
AstPackage* unitPackage(FileLine* fl) {
// Find one made earlier?
AstPackage* pkgp = SYMP->symRootp()->findIdFlat(AstPackage::dollarUnitName())->castPackage();
if (!pkgp) {
pkgp = new AstPackage(fl, AstPackage::dollarUnitName());
pkgp->inLibrary(true); // packages are always libraries; don't want to make them a "top"
pkgp->modTrace(false); // may reconsider later
PARSEP->rootp()->addModulep(pkgp);
SYMP->reinsert(pkgp, SYMP->symRootp()); // Don't push/pop scope as they're global
}
return pkgp;
}
AstNodeDType* addRange(AstBasicDType* dtypep, AstRange* rangesp) {
if (!rangesp) {
return dtypep;
@ -117,10 +133,6 @@ public:
string deQuote(FileLine* fileline, string text);
};
#define PARSEP V3ParseImp::parsep()
#define SYMP PARSEP->symp()
#define GRAMMARP V3ParseGrammar::singletonp()
const AstBasicDTypeKwd LOGIC = AstBasicDTypeKwd::LOGIC; // Shorthand "LOGIC"
const AstBasicDTypeKwd LOGIC_IMPLICIT = AstBasicDTypeKwd::LOGIC_IMPLICIT;
@ -166,6 +178,7 @@ class AstSenTree;
// package_identifier, type_identifier, variable_identifier,
%token<strp> yaID__ETC "IDENTIFIER"
%token<strp> yaID__LEX "IDENTIFIER-in-lex"
%token<strp> yaID__aPACKAGE "PACKAGE-IDENTIFIER"
%token<strp> yaID__aTYPE "TYPE-IDENTIFIER"
// IEEE: integral_number
@ -246,6 +259,7 @@ class AstSenTree;
%token<fl> yENDFUNCTION "endfunction"
%token<fl> yENDGENERATE "endgenerate"
%token<fl> yENDMODULE "endmodule"
%token<fl> yENDPACKAGE "endpackage"
%token<fl> yENDPROGRAM "endprogram"
%token<fl> yENDPROPERTY "endproperty"
%token<fl> yENDSPECIFY "endspecify"
@ -275,6 +289,7 @@ class AstSenTree;
%token<fl> yNOTIF1 "notif1"
%token<fl> yOR "or"
%token<fl> yOUTPUT "output"
%token<fl> yPACKAGE "package"
%token<fl> yPARAMETER "parameter"
%token<fl> yPOSEDGE "posedge"
%token<fl> yPRIORITY "priority"
@ -337,6 +352,7 @@ class AstSenTree;
%token<fl> yD_STIME "$stime"
%token<fl> yD_STOP "$stop"
%token<fl> yD_TIME "$time"
%token<fl> yD_UNIT "$unit"
%token<fl> yD_UNSIGNED "$unsigned"
%token<fl> yD_WARNING "$warning"
%token<fl> yD_WRITE "$write"
@ -472,6 +488,11 @@ class AstSenTree;
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
%start source_text
@ -508,8 +529,8 @@ description: // ==IEEE: description
module_declaration { }
//UNSUP interface_declaration { }
| program_declaration { }
//UNSUP package_declaration { }
//UNSUP package_item { }
| package_declaration { }
| package_item { if ($1) GRAMMARP->unitPackage($1->fileline())->addStmtp($1); }
//UNSUP bind_directive { }
// unsupported // IEEE: config_declaration
| error { }
@ -523,6 +544,38 @@ timeunits_declaration<nodep>: // ==IEEE: timeunits_declaration
//**********************************************************************
// Packages
package_declaration: // ==IEEE: package_declaration
packageFront package_itemListE yENDPACKAGE endLabelE
{ $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2);
SYMP->popScope($1); }
;
packageFront<modulep>:
yPACKAGE idAny ';'
{ $$ = new AstPackage($1,*$2);
$$->inLibrary(true); // packages are always libraries; don't want to make them a "top"
$$->modTrace(v3Global.opt.trace());
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
;
package_itemListE<nodep>: // IEEE: [{ package_item }]
/* empty */ { $$ = NULL; }
| package_itemList { $$ = $1; }
;
package_itemList<nodep>: // IEEE: { package_item }
package_item { $$ = $1; }
| package_itemList package_item { $$ = $1->addNextNull($2); }
;
package_item<nodep>: // ==IEEE: package_item
package_or_generate_item_declaration { $$ = $1; }
//UNSUP anonymous_program { $$ = $1; }
| timeunits_declaration { $$ = $1; }
;
package_or_generate_item_declaration<nodep>: // ==IEEE: package_or_generate_item_declaration
net_declaration { $$ = $1; }
| data_declaration { $$ = $1; }
@ -1762,14 +1815,17 @@ for_step<nodep>: // IEEE: for_step
//************************************************
// Functions/tasks
taskRef<nodep>: // IEEE: part of tf_call
taskRef<ftaskrefp>: // IEEE: part of tf_call
idDotted { $$ = new AstTaskRef(CRELINE(),new AstParseRef($1->fileline(), AstParseRefExp::TASK, $1),NULL);}
| idDotted '(' list_of_argumentsE ')' { $$ = new AstTaskRef(CRELINE(),new AstParseRef($1->fileline(), AstParseRefExp::TASK, $1),$3);}
//UNSUP: package_scopeIdFollows idDotted { $$ = new AstTaskRef(CRELINE(),new AstParseRef($2->fileline(), AstParseRefExp::TASK, $2),NULL);}
//UNSUP: package_scopeIdFollows idDotted '(' list_of_argumentsE ')' { $$ = new AstTaskRef(CRELINE(),new AstParseRef($2->fileline(), AstParseRefExp::TASK, $2),$4);}
//UNSUP: idDotted is really just id to allow dotted method calls
;
funcRef<nodep>: // IEEE: part of tf_call
funcRef<ftaskrefp>: // IEEE: part of tf_call
idDotted '(' list_of_argumentsE ')' { $$ = new AstFuncRef($2,new AstParseRef($1->fileline(), AstParseRefExp::FUNC, $1), $3); }
| package_scopeIdFollows idDotted '(' list_of_argumentsE ')' { $$ = new AstFuncRef($3,new AstParseRef($2->fileline(), AstParseRefExp::FUNC, $2), $4); $$->packagep($1); }
//UNSUP: idDotted is really just id to allow dotted method calls
;
@ -2448,8 +2504,8 @@ id<strp>:
idAny<strp>: // Any kind of identifier
//UNSUP yaID__aCLASS { $$ = $1; $<fl>$=$<fl>1; }
//UNSUP yaID__aCOVERGROUP { $$ = $1; $<fl>$=$<fl>1; }
//UNSUP yaID__aPACKAGE { $$ = $1; $<fl>$=$<fl>1; }
yaID__aTYPE { $$ = $1; $<fl>$=$<fl>1; }
yaID__aPACKAGE { $$ = $1; $<fl>$=$<fl>1; }
| yaID__aTYPE { $$ = $1; $<fl>$=$<fl>1; }
| yaID__ETC { $$ = $1; $<fl>$=$<fl>1; }
;
@ -2605,22 +2661,31 @@ immediate_assert_statement<nodep>: // ==IEEE: immediate_assert_statement
// must be included in the rules below.
// Each of these must end with {symsPackageDone | symsClassDone}
ps_id_etc<strp>: // package_scope + general id
package_scopeIdFollowsE id { $$ = $2; }
ps_id_etc: // package_scope + general id
package_scopeIdFollowsE id { }
;
ps_type<dtypep>: // IEEE: ps_parameter_identifier | ps_type_identifier
// Even though we looked up the type and have a AstNode* to it,
// we can't fully resolve it because it may have been just a forward definition.
package_scopeIdFollowsE yaID__aTYPE { $$ = new AstRefDType($<fl>1, *$2); }
package_scopeIdFollowsE yaID__aTYPE { $$ = new AstRefDType($<fl>2, *$2); $$->castRefDType()->packagep($1); }
;
//=== Below rules assume special scoping per above
package_scopeIdFollowsE: // IEEE: [package_scope]
package_scopeIdFollowsE<packagep>: // IEEE: [package_scope]
// // IMPORTANT: The lexer will parse the following ID to be in the found package
/* empty */ { }
//UNSUP package_scopeIdFollows { UNSUP }
/* empty */ { $$ = NULL; }
| package_scopeIdFollows { $$ = $1; }
;
package_scopeIdFollows<packagep>: // IEEE: package_scope
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// //vv mid rule action needed otherwise we might not have NextId in time to parse the id token
yD_UNIT { SYMP->nextId(PARSEP->rootp()); }
/*cont*/ yP_COLONCOLON { $$ = GRAMMARP->unitPackage($<fl>1); }
| yaID__aPACKAGE { SYMP->nextId($<scp>1); }
/*cont*/ yP_COLONCOLON { $$ = $<scp>1->castPackage(); }
;
//************************************************

View File

@ -3,7 +3,7 @@
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2008 by Wilson Snyder.
module a;
module t;
reg a;
initial begin
$unknown_sys_task_call_to_be_bbox("blah");

View File

@ -63,9 +63,9 @@ module MxN_pipeline (in, out, clk);
//wire [M*(N-1):1] t;
//dffn #(M) p[N:1] ({out,t},{t,in},clk);
wire [M*(N-1):1] t;
wire [M*(N-1):1] w;
wire [M*N:1] q;
dffn #(M) p[N:1] (q,{t,in},clk);
assign {out,t} = q;
dffn #(M) p[N:1] (q,{w,in},clk);
assign {out,w} = q;
endmodule

View File

@ -87,7 +87,9 @@ module fifo (/*AUTOARG*/
reg [65:0] outData;
// verilator lint_off VARHIDDEN
reg [65:0] fifo[0:fifoDepth-1];
// verilator lint_on VARHIDDEN
reg [`PTRBITSM1:0] wrPtr, rdPtr;
//reg [65:0] temp;

18
test_regress/t/t_package.pl Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/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.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -0,0 +1,36 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2009 by Wilson Snyder.
typedef int unit_type_t;
function [3:0] unit_plusone(input [3:0] i);
unit_plusone = i+1;
endfunction
package p;
typedef int package_type_t;
function [3:0] plusone(input [3:0] i);
plusone = i+1;
endfunction
endpackage
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
unit_type_t vu;
$unit::unit_type_t vdu;
p::package_type_t vp;
initial begin
if (unit_plusone(1) !== 2) $stop;
if ($unit::unit_plusone(1) !== 2) $stop;
if (p::plusone(1) !== 2) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -3,7 +3,7 @@
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2009 by Wilson Snyder.
//UNSUPtypedef reg [2:0] three_t;
typedef reg [2:0] threeansi_t;
module t (/*AUTOARG*/
// Inputs
@ -11,7 +11,7 @@ module t (/*AUTOARG*/
);
input clk;
typedef reg [2:0] three_t; //UNSUP remove
typedef reg [2:0] three_t;
integer cyc=0;
reg [63:0] crc;
@ -22,6 +22,7 @@ module t (/*AUTOARG*/
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
threeansi_t outa; // From testa of TestAnsi.v
three_t outna; // From test of TestNonAnsi.v
// End of automatics
@ -32,14 +33,12 @@ module t (/*AUTOARG*/
.clk (clk),
.in (in));
//UNSUP
// TestAnsi testa (// Outputs
// .out (outa),
// /*AUTOINST*/
// // Inputs
// .clk (clk),
// .in (in));
wire [2:0] outa = outna;
TestAnsi testa (// Outputs
.out (outa),
/*AUTOINST*/
// Inputs
.clk (clk),
.in (in));
// Aggregate outputs into a single result vector
wire [63:0] result = {57'h0, outna, 1'b0, outa};
@ -92,21 +91,16 @@ module TestNonAnsi (/*AUTOARG*/
end
endmodule
`ifndef verilator //UNSUPPORTED
typedef reg [2:0] three_t;
module TestAnsi (
input clk,
input three_t in,
output three_t out
input threeansi_t in,
output threeansi_t out
);
always @(posedge clk) begin
out <= ~in;
end
endmodule
`endif
// Local Variables:
// verilog-typedef-regexp: "_t$"
// End:

View File

@ -0,0 +1,21 @@
#!/usr/bin/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.
compile (
v_flags2 => ["--lint-only"],
fails=>$Self->{v3},
expect=>
'%Warning-VARHIDDEN: t/t_var_bad_hide2.v:\d+: Declaration of signal hides declaration in upper scope: t
.*
%Warning-VARHIDDEN: t/t_var_bad_hide2.v:\d+: ... Location of original declaration
%Error: Exiting due to.*',
);
ok(1);
1;

View File

@ -0,0 +1,10 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2009 by Wilson Snyder.
module t;
integer t;
endmodule