Support "package" and $unit.
Add VARHIDDEN warning when signal name hides module name.
This commit is contained in:
parent
bc2d3a13f4
commit
68567e763c
4
Changes
4
Changes
|
|
@ -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;").
|
||||
|
|
|
|||
12
src/V3Ast.h
12
src/V3Ast.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
133
src/V3Link.cpp
133
src/V3Link.cpp
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
//============================================================================
|
||||
|
||||
class V3LinkLevel {
|
||||
private:
|
||||
static void wrapTopPackages(AstNetlist* nodep, AstNodeModule* newmodp);
|
||||
public:
|
||||
static void modSortByLevel();
|
||||
static void wrapTop(AstNetlist* nodep);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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*) {
|
||||
|
|
|
|||
|
|
@ -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*) {
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(); }
|
||||
;
|
||||
|
||||
//************************************************
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue