Support parameter type, bug376.

This commit is contained in:
Wilson Snyder 2016-03-14 21:51:31 -04:00
parent cef097b7b7
commit 9ae40d64f0
17 changed files with 388 additions and 17 deletions

View File

@ -6,6 +6,8 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.883 devel * Verilator 3.883 devel
** Support parameter type, bug376. [Alan Hunter, et al]
* Verilator 3.882 2016-03-01 * Verilator 3.882 2016-03-01
@ -2715,5 +2717,5 @@ Version 2.0.
Local variables: Local variables:
mode: outline mode: outline
paragraph-separate: "[ \f\n]*$" paragraph-separate: "[ \f\n]*$"
end: end:

View File

@ -158,6 +158,39 @@ public:
//###################################################################### //######################################################################
//==== Data Types //==== Data Types
class AstParamTypeDType : public AstNodeDType {
// Parents: MODULE
// A parameter type statement; much like a var or typedef
private:
AstVarType m_varType; // Type of variable (for localparam vs. param)
string m_name; // Name of variable
public:
AstParamTypeDType(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp)
: AstNodeDType(fl), m_varType(type), m_name(name) {
childDTypep(dtp); // Only for parser
dtypep(NULL); // V3Width will resolve
}
ASTNODE_NODE_FUNCS(ParamTypeDType, PARAMTYPEDTYPE)
AstNodeDType* getChildDTypep() const { return childDTypep(); }
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Type assigning to
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); }
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
// METHODS
virtual string name() const { return m_name; }
virtual bool maybePointedTo() const { return true; }
virtual bool hasDType() const { return true; }
void name(const string& flag) { m_name = flag; }
AstVarType varType() const { return m_varType; } // * = Type of variable
bool isParam() const { return true; }
bool isGParam() const { return (varType()==AstVarType::GPARAM); }
};
class AstTypedef : public AstNode { class AstTypedef : public AstNode {
private: private:
string m_name; string m_name;
@ -689,6 +722,23 @@ public:
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
}; };
struct AstParseTypeDType : public AstNodeDType {
// Parents: VAR
// During parsing, this indicates the type of a parameter is a "parameter type"
// e.g. the data type is a container of any data type
AstParseTypeDType(FileLine* fl)
: AstNodeDType(fl) {}
ASTNODE_NODE_FUNCS(ParseTypeDType, PARSETYPEDTYPE)
AstNodeDType* dtypep() const { return NULL; }
// METHODS
virtual AstBasicDType* basicp() const { return NULL; }
virtual AstNodeDType* skipRefp() const { return NULL; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return 0; }
virtual int widthTotalBytes() const { return 0; }
};
//###################################################################### //######################################################################
class AstArraySel : public AstNodeSel { class AstArraySel : public AstNodeSel {
@ -1333,6 +1383,7 @@ private:
int m_pinNum; // Pin number int m_pinNum; // Pin number
string m_name; // Pin name, or "" for number based interconnect string m_name; // Pin name, or "" for number based interconnect
AstVar* m_modVarp; // Input/output this pin connects to on submodule. AstVar* m_modVarp; // Input/output this pin connects to on submodule.
AstParamTypeDType* m_modPTypep; // Param type this pin connects to on submodule.
bool m_param; // Pin connects to parameter bool m_param; // Pin connects to parameter
bool m_svImplicit; // Pin is SystemVerilog .name'ed bool m_svImplicit; // Pin is SystemVerilog .name'ed
public: public:
@ -1341,6 +1392,7 @@ public:
,m_name(name), m_param(false), m_svImplicit(false) { ,m_name(name), m_param(false), m_svImplicit(false) {
m_pinNum = pinNum; m_pinNum = pinNum;
m_modVarp = NULL; m_modVarp = NULL;
m_modPTypep = NULL;
setNOp1p(exprp); setNOp1p(exprp);
} }
AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp) AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp)
@ -1348,11 +1400,15 @@ public:
m_name = varname->name(); m_name = varname->name();
m_pinNum = pinNum; m_pinNum = pinNum;
m_modVarp = NULL; m_modVarp = NULL;
m_modPTypep = NULL;
setNOp1p(exprp); setNOp1p(exprp);
} }
ASTNODE_NODE_FUNCS(Pin, PIN) ASTNODE_NODE_FUNCS(Pin, PIN)
virtual void dump(ostream& str); virtual void dump(ostream& str);
virtual const char* broken() const { BROKEN_RTN(m_modVarp && !m_modVarp->brokeExists()); return NULL; } virtual const char* broken() const {
BROKEN_RTN(m_modVarp && !m_modVarp->brokeExists());
BROKEN_RTN(m_modPTypep && !m_modPTypep->brokeExists());
return NULL; }
virtual string name() const { return m_name; } // * = Pin name, ""=go by number virtual string name() const { return m_name; } // * = Pin name, ""=go by number
virtual void name(const string& name) { m_name = name; } virtual void name(const string& name) { m_name = name; }
virtual string prettyOperatorName() const { return modVarp() virtual string prettyOperatorName() const { return modVarp()
@ -1363,7 +1419,9 @@ public:
void exprp(AstNode* nodep) { addOp1p(nodep); } void exprp(AstNode* nodep) { addOp1p(nodep); }
AstNode* exprp() const { return op1p()->castNode(); } // op1 = Expression connected to pin, NULL if unconnected AstNode* exprp() const { return op1p()->castNode(); } // op1 = Expression connected to pin, NULL if unconnected
AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable
void modVarp(AstVar* varp) { m_modVarp=varp; } void modVarp(AstVar* nodep) { m_modVarp=nodep; }
AstParamTypeDType* modPTypep() const { return m_modPTypep; } // [After Link] Pointer to variable
void modPTypep(AstParamTypeDType* nodep) { m_modPTypep=nodep; }
bool param() const { return m_param; } bool param() const { return m_param; }
void param(bool flag) { m_param=flag; } void param(bool flag) { m_param=flag; }
bool svImplicit() const { return m_svImplicit; } bool svImplicit() const { return m_svImplicit; }

View File

@ -242,6 +242,10 @@ private:
// No cleaning, or would loose pointer to enum // No cleaning, or would loose pointer to enum
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstParamTypeDType* nodep, AstNUser*) {
// No cleaning, or would loose pointer to enum
nodep->iterateChildren(*this);
}
// Control flow operators // Control flow operators
virtual void visit(AstNodeCond* nodep, AstNUser*) { virtual void visit(AstNodeCond* nodep, AstNUser*) {

View File

@ -2260,8 +2260,12 @@ private:
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
// Default: Just iterate // Default: Just iterate
if (m_required) { if (m_required) {
nodep->v3error("Expecting expression to be constant, but can't convert a " if (nodep->castNodeDType() || nodep->castRange()) {
<<nodep->prettyTypeName()<<" to constant."); // Ignore dtypes for parameter type pins
} else {
nodep->v3error("Expecting expression to be constant, but can't convert a "
<<nodep->prettyTypeName()<<" to constant.");
}
} else { } else {
// Calculate the width of this operation // Calculate the width of this operation
if (m_params && !nodep->width()) { if (m_params && !nodep->width()) {

View File

@ -90,6 +90,7 @@ private:
// Default: Just iterate // Default: Just iterate
virtual void visit(AstVar*, AstNUser*) {} virtual void visit(AstVar*, AstNUser*) {}
virtual void visit(AstTypedef*, AstNUser*) {} virtual void visit(AstTypedef*, AstNUser*) {}
virtual void visit(AstParamTypeDType*, AstNUser*) {}
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
nodeHashIterate(nodep); nodeHashIterate(nodep);
} }

View File

@ -194,6 +194,7 @@ public:
else if (nodep->castFunc()) return "function"; else if (nodep->castFunc()) return "function";
else if (nodep->castBegin()) return "block"; else if (nodep->castBegin()) return "block";
else if (nodep->castIface()) return "interface"; else if (nodep->castIface()) return "interface";
else if (nodep->castParamTypeDType()) return "parameter type";
else return nodep->prettyTypeName(); else return nodep->prettyTypeName();
} }
@ -893,6 +894,11 @@ class LinkDotFindVisitor : public AstNVisitor {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
} }
virtual void visit(AstParamTypeDType* nodep, AstNUser*) {
if (!m_curSymp) nodep->v3fatalSrc("Parameter type not under module??\n");
nodep->iterateChildren(*this);
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
}
virtual void visit(AstCFunc* nodep, AstNUser*) { virtual void visit(AstCFunc* nodep, AstNUser*) {
// For dotted resolution, ignore all AstVars under functions, otherwise shouldn't exist // For dotted resolution, ignore all AstVars under functions, otherwise shouldn't exist
if (m_statep->forScopeCreation()) nodep->v3fatalSrc("No CFuncs expected in tree yet"); if (m_statep->forScopeCreation()) nodep->v3fatalSrc("No CFuncs expected in tree yet");
@ -1539,6 +1545,10 @@ private:
markAndCheckPinDup(nodep, refp, whatp); markAndCheckPinDup(nodep, refp, whatp);
} }
} }
else if (AstParamTypeDType* refp = foundp->nodep()->castParamTypeDType()) {
nodep->modPTypep(refp);
markAndCheckPinDup(nodep, refp, whatp);
}
else { else {
nodep->v3error(ucfirst(whatp)<<" not found: "<<nodep->prettyName()); nodep->v3error(ucfirst(whatp)<<" not found: "<<nodep->prettyName());
} }
@ -2099,7 +2109,12 @@ private:
if (AstTypedef* defp = foundp ? foundp->nodep()->castTypedef() : NULL) { if (AstTypedef* defp = foundp ? foundp->nodep()->castTypedef() : NULL) {
nodep->refDTypep(defp->subDTypep()); nodep->refDTypep(defp->subDTypep());
nodep->packagep(foundp->packagep()); nodep->packagep(foundp->packagep());
} else { }
else if (AstParamTypeDType* defp = foundp ? foundp->nodep()->castParamTypeDType() : NULL) {
nodep->refDTypep(defp);
nodep->packagep(foundp->packagep());
}
else {
nodep->v3error("Can't find typedef: "<<nodep->prettyName()); nodep->v3error("Can't find typedef: "<<nodep->prettyName());
} }
} }

View File

@ -140,6 +140,21 @@ private:
virtual void visit(AstVar* nodep, AstNUser*) { virtual void visit(AstVar* nodep, AstNUser*) {
cleanFileline(nodep); cleanFileline(nodep);
if (nodep->subDTypep()->castParseTypeDType()) {
// It's a parameter type. Use a different node type for this.
AstNodeDType* dtypep = nodep->valuep()->castNodeDType();
if (!dtypep) {
nodep->v3error("Parameter type's initial value isn't a type: "<<nodep->prettyName());
nodep->unlinkFrBack();
} else {
dtypep->unlinkFrBack();
AstNode* newp = new AstParamTypeDType(nodep->fileline(), nodep->varType(), nodep->name(),
VFlagChildDType(), dtypep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
}
return;
}
// We used modTrace before leveling, and we may now // We used modTrace before leveling, and we may now
// want to turn it off now that we know the levelizations // want to turn it off now that we know the levelizations
if (v3Global.opt.traceDepth() if (v3Global.opt.traceDepth()

View File

@ -177,6 +177,12 @@ private:
clonemapp->insert(make_pair(oldvarp, varp)); clonemapp->insert(make_pair(oldvarp, varp));
} }
} }
else if (AstParamTypeDType* ptp = stmtp->castParamTypeDType()) {
if (ptp->isGParam()) {
AstParamTypeDType* oldptp = ptp->clonep()->castParamTypeDType();
clonemapp->insert(make_pair(oldptp, ptp));
}
}
} }
} }
void relinkPins(CloneMap* clonemapp, AstPin* startpinp) { void relinkPins(CloneMap* clonemapp, AstPin* startpinp) {
@ -188,6 +194,11 @@ private:
UASSERT(cloneiter != clonemapp->end(), "Couldn't find pin in clone list"); UASSERT(cloneiter != clonemapp->end(), "Couldn't find pin in clone list");
pinp->modVarp(cloneiter->second->castVar()); pinp->modVarp(cloneiter->second->castVar());
} }
else if (pinp->modPTypep()) {
CloneMap::iterator cloneiter = clonemapp->find(pinp->modPTypep());
UASSERT(cloneiter != clonemapp->end(), "Couldn't find pin in clone list");
pinp->modPTypep(cloneiter->second->castParamTypeDType());
}
else { else {
pinp->v3fatalSrc("Not linked?\n"); pinp->v3fatalSrc("Not linked?\n");
} }
@ -499,6 +510,24 @@ void ParamVisitor::visitCell(AstCell* nodep) {
any_overrides = true; any_overrides = true;
} }
} }
} else if (AstParamTypeDType* modvarp = pinp->modPTypep()) {
AstNodeDType* exprp = pinp->exprp()->castNodeDType();
AstNodeDType* origp = modvarp->subDTypep();
if (!exprp) {
pinp->v3error("Parameter type pin value isn't a type: Param "<<pinp->prettyName()<<" of "<<nodep->prettyName());
} else if (!origp) {
pinp->v3error("Parameter type variable isn't a type: Param "<<modvarp->prettyName());
} else {
UINFO(9,"Parameter type assignment expr="<<exprp<<" to "<<origp<<endl);
if (origp && exprp->sameTree(origp)) {
// Setting parameter to its default value. Just ignore it.
// This prevents making additional modules, and makes coverage more
// obvious as it won't show up under a unique module page name.
} else {
longname += "_" + paramSmallName(nodep->modp(),modvarp)+paramValueNumber(exprp);
any_overrides = true;
}
}
} else { } else {
pinp->v3error("Parameter not found in sub-module: Param "<<pinp->prettyName()<<" of "<<nodep->prettyName()); pinp->v3error("Parameter not found in sub-module: Param "<<pinp->prettyName()<<" of "<<nodep->prettyName());
} }
@ -624,6 +653,15 @@ void ParamVisitor::visitCell(AstCell* nodep) {
// Set this parameter to value requested by cell // Set this parameter to value requested by cell
modvarp->valuep(constp->cloneTree(false)); modvarp->valuep(constp->cloneTree(false));
} }
else if (AstParamTypeDType* modptp = pinp->modPTypep()) {
AstNodeDType* dtypep = pinp->exprp()->castNodeDType();
if (!dtypep) pinp->v3fatalSrc("unlinked param dtype");
if (modptp->childDTypep()) pushDeletep(modptp->childDTypep()->unlinkFrBack());
// Set this parameter to value requested by cell
modptp->childDTypep(dtypep->cloneTree(false));
// Later V3LinkDot will convert the ParamDType to a Typedef
// Not done here as may be localparams, etc, that also need conversion
}
} }
} }

View File

@ -151,6 +151,26 @@ ostream& operator<<(ostream& str, const WidthVP* vup) {
//###################################################################### //######################################################################
class WidthClearVisitor {
// Rather than a AstNVisitor, can just quickly touch every node
void clearWidthRecurse(AstNode* nodep) {
nodep->didWidth(false);
if (nodep->op1p()) clearWidthRecurse(nodep->op1p());
if (nodep->op2p()) clearWidthRecurse(nodep->op2p());
if (nodep->op3p()) clearWidthRecurse(nodep->op3p());
if (nodep->op4p()) clearWidthRecurse(nodep->op4p());
if (nodep->nextp()) clearWidthRecurse(nodep->nextp());
}
public:
// CONSTUCTORS
explicit WidthClearVisitor(AstNetlist* nodep) {
clearWidthRecurse(nodep);
}
virtual ~WidthClearVisitor() {}
};
//######################################################################
class WidthVisitor : public AstNVisitor { class WidthVisitor : public AstNVisitor {
private: private:
// TYPES // TYPES
@ -913,6 +933,9 @@ private:
// calculation would return identical values. Therefore we can directly replace the width // calculation would return identical values. Therefore we can directly replace the width
nodep->widthForce(nodep->rangep()->elementsConst(), nodep->rangep()->elementsConst()); nodep->widthForce(nodep->rangep()->elementsConst(), nodep->rangep()->elementsConst());
} }
else if (nodep->isRanged()) {
nodep->widthForce(nodep->nrange().elements(), nodep->nrange().elements());
}
else if (nodep->implicit()) { else if (nodep->implicit()) {
// Parameters may notice implicitness and change to different dtype // Parameters may notice implicitness and change to different dtype
nodep->widthForce(1,1); nodep->widthForce(1,1);
@ -951,6 +974,13 @@ private:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
nodep->dtypep(iterateEditDTypep(nodep, nodep->subDTypep())); nodep->dtypep(iterateEditDTypep(nodep, nodep->subDTypep()));
} }
virtual void visit(AstParamTypeDType* nodep, AstNUser*) {
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
if (nodep->childDTypep()) nodep->dtypep(moveChildDTypeEdit(nodep));
nodep->iterateChildren(*this);
nodep->dtypep(iterateEditDTypep(nodep, nodep->subDTypep()));
nodep->widthFromSub(nodep->subDTypep());
}
virtual void visit(AstCastParse* nodep, AstNUser* vup) { virtual void visit(AstCastParse* nodep, AstNUser* vup) {
// nodep->dtp could be data type, or a primary_constant // nodep->dtp could be data type, or a primary_constant
// Don't iterate lhsp, will deal with that once convert the type // Don't iterate lhsp, will deal with that once convert the type
@ -2724,6 +2754,7 @@ private:
if (nodep->width()==0) nodep->v3fatalSrc("Under node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?"); if (nodep->width()==0) nodep->v3fatalSrc("Under node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?");
if (expWidth==0) nodep->v3fatalSrc("Node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?"); if (expWidth==0) nodep->v3fatalSrc("Node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?");
if (expWidthMin==0) expWidthMin = expWidth; if (expWidthMin==0) expWidthMin = expWidth;
if (nodep->dtypep()->width() == expWidth) return false;
if (nodep->dtypep()->widthSized() && nodep->width() != expWidthMin) return true; if (nodep->dtypep()->widthSized() && nodep->width() != expWidthMin) return true;
if (!nodep->dtypep()->widthSized() && nodep->widthMin() > expWidthMin) return true; if (!nodep->dtypep()->widthSized() && nodep->widthMin() > expWidthMin) return true;
return false; return false;
@ -3528,6 +3559,7 @@ int V3Width::debug() {
void V3Width::width(AstNetlist* nodep) { void V3Width::width(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
// We should do it in bottom-up module order, but it works in any order. // We should do it in bottom-up module order, but it works in any order.
WidthClearVisitor cvisitor (nodep);
WidthVisitor visitor (false, false); WidthVisitor visitor (false, false);
(void)visitor.mainAcceptEdit(nodep); (void)visitor.mainAcceptEdit(nodep);
WidthRemoveVisitor rvisitor; WidthRemoveVisitor rvisitor;

View File

@ -128,9 +128,17 @@ private:
visitIterateNodeDType(nodep); visitIterateNodeDType(nodep);
} }
virtual void visit(AstNodeClassDType* nodep, AstNUser*) { virtual void visit(AstNodeClassDType* nodep, AstNUser*) {
if (nodep->user1SetOnce()) return; // Process once
visitIterateNodeDType(nodep); visitIterateNodeDType(nodep);
nodep->clearCache(); nodep->clearCache();
} }
virtual void visit(AstParamTypeDType* nodep, AstNUser*) {
if (nodep->user1SetOnce()) return; // Process once
visitIterateNodeDType(nodep);
// Move to type table as all dtype pointers must resolve there
nodep->unlinkFrBack(); // Make non-child
v3Global.rootp()->typeTablep()->addTypesp(nodep);
}
void visitIterateNodeDType(AstNodeDType* nodep) { void visitIterateNodeDType(AstNodeDType* nodep) {
// Rather than use dtypeChg which may make new nodes, we simply edit in place, // Rather than use dtypeChg which may make new nodes, we simply edit in place,
// as we don't need to preserve any widthMin's, and every dtype with the same width // as we don't need to preserve any widthMin's, and every dtype with the same width

View File

@ -459,6 +459,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"struct" { FL; return ySTRUCT; } "struct" { FL; return ySTRUCT; }
"timeprecision" { FL; return yTIMEPRECISION; } "timeprecision" { FL; return yTIMEPRECISION; }
"timeunit" { FL; return yTIMEUNIT; } "timeunit" { FL; return yTIMEUNIT; }
"type" { FL; return yTYPE; }
"typedef" { FL; return yTYPEDEF; } "typedef" { FL; return yTYPEDEF; }
"union" { FL; return yUNION; } "union" { FL; return yUNION; }
"unique" { FL; return yUNIQUE; } "unique" { FL; return yUNIQUE; }
@ -508,7 +509,6 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"tagged" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); } "tagged" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"this" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); } "this" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"throughout" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); } "throughout" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"type" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"virtual" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); } "virtual" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"wait_order" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); } "wait_order" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
"wildcard" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); } "wildcard" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }

View File

@ -421,6 +421,7 @@ class AstSenTree;
%token<fl> yTRI0 "tri0" %token<fl> yTRI0 "tri0"
%token<fl> yTRI1 "tri1" %token<fl> yTRI1 "tri1"
%token<fl> yTRUE "true" %token<fl> yTRUE "true"
%token<fl> yTYPE "type"
%token<fl> yTYPEDEF "typedef" %token<fl> yTYPEDEF "typedef"
%token<fl> yUNION "union" %token<fl> yUNION "union"
%token<fl> yUNIQUE "unique" %token<fl> yUNIQUE "unique"
@ -1140,14 +1141,14 @@ local_parameter_declarationFront: // IEEE: local_parameter_declaration w/o assig
// // Front must execute first so VARDTYPE is ready before list of vars // // Front must execute first so VARDTYPE is ready before list of vars
varLParamReset implicit_typeE { /*VARRESET-in-varLParam*/ VARDTYPE($2); } varLParamReset implicit_typeE { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
| varLParamReset data_type { /*VARRESET-in-varLParam*/ VARDTYPE($2); } | varLParamReset data_type { /*VARRESET-in-varLParam*/ VARDTYPE($2); }
//UNSUP varLParamReset yTYPE { /*VARRESET-in-varLParam*/ VARDTYPE(new AstParseTypeDType($2)); } | varLParamReset yTYPE { /*VARRESET-in-varLParam*/ VARDTYPE(new AstParseTypeDType($2)); }
; ;
parameter_declarationFront: // IEEE: parameter_declaration w/o assignment parameter_declarationFront: // IEEE: parameter_declaration w/o assignment
// // Front must execute first so VARDTYPE is ready before list of vars // // Front must execute first so VARDTYPE is ready before list of vars
varGParamReset implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($2); } varGParamReset implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
| varGParamReset data_type { /*VARRESET-in-varGParam*/ VARDTYPE($2); } | varGParamReset data_type { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
//UNSUP varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE(new AstParseTypeDType($2)); } | varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE(new AstParseTypeDType($2)); }
; ;
parameter_port_declarationFrontE: // IEEE: parameter_port_declaration w/o assignment parameter_port_declarationFrontE: // IEEE: parameter_port_declaration w/o assignment
@ -1155,10 +1156,10 @@ parameter_port_declarationFrontE: // IEEE: parameter_port_declaration w/o assign
// // Front must execute first so VARDTYPE is ready before list of vars // // Front must execute first so VARDTYPE is ready before list of vars
varGParamReset implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($2); } varGParamReset implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
| varGParamReset data_type { /*VARRESET-in-varGParam*/ VARDTYPE($2); } | varGParamReset data_type { /*VARRESET-in-varGParam*/ VARDTYPE($2); }
//UNSUP varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE(new AstParseTypeDType($2)); } | varGParamReset yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE(new AstParseTypeDType($2)); }
| implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($1); } | implicit_typeE { /*VARRESET-in-varGParam*/ VARDTYPE($1); }
| data_type { /*VARRESET-in-varGParam*/ VARDTYPE($1); } | data_type { /*VARRESET-in-varGParam*/ VARDTYPE($1); }
//UNSUP yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE(new AstParseTypeDType($1)); } | yTYPE { /*VARRESET-in-varGParam*/ VARDTYPE(new AstParseTypeDType($1)); }
; ;
net_declaration<nodep>: // IEEE: net_declaration - excluding implict net_declaration<nodep>: // IEEE: net_declaration - excluding implict
@ -1993,7 +1994,7 @@ param_assignment<varp>: // ==IEEE: param_assignment
// // IEEE: constant_param_expression // // IEEE: constant_param_expression
// // constant_param_expression: '$' is in expr // // constant_param_expression: '$' is in expr
// // note exptOrDataType being a data_type is only for yPARAMETER yTYPE // // note exptOrDataType being a data_type is only for yPARAMETER yTYPE
id/*new-parameter*/ variable_dimensionListE sigAttrListE '=' expr id/*new-parameter*/ variable_dimensionListE sigAttrListE '=' exprOrDataType
/**/ { $$ = VARDONEA($<fl>1,*$1, $2, $3); $$->valuep($5); } /**/ { $$ = VARDONEA($<fl>1,*$1, $2, $3); $$->valuep($5); }
; ;
@ -2704,6 +2705,12 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yD_VALUEPLUSARGS '(' str ',' expr ')' { $$ = new AstValuePlusArgs($1,*$3,$5); } | yD_VALUEPLUSARGS '(' str ',' expr ')' { $$ = new AstValuePlusArgs($1,*$3,$5); }
; ;
exprOrDataType<nodep>: // expr | data_type: combined to prevent conflicts
expr { $$ = $1; }
// // data_type includes id that overlaps expr, so special flavor
| data_type { $$ = $1; }
;
list_of_argumentsE<nodep>: // IEEE: [list_of_arguments] list_of_argumentsE<nodep>: // IEEE: [list_of_arguments]
argsDottedList { $$ = $1; } argsDottedList { $$ = $1; }
| argsExprListE { if ($1->castArg() && $1->castArg()->emptyConnectNoNext()) { $1->deleteTree(); $$ = NULL; } // Mis-created when have 'func()' | argsExprListE { if ($1->castArg() && $1->castArg()->emptyConnectNoNext()) { $1->deleteTree(); $$ = NULL; } // Mis-created when have 'func()'
@ -3795,6 +3802,12 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstRange
if (GRAMMARP->m_varDecl == AstVarType::SUPPLY1) { if (GRAMMARP->m_varDecl == AstVarType::SUPPLY1) {
nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 1)); nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 1));
} }
if (dtypep->castParseTypeDType()) {
// Parser needs to know what is a type
AstNode* newp = new AstTypedefFwd(fileline, name);
nodep->addNext(newp);
SYMP->reinsert(newp);
}
// Don't set dtypep in the ranging; // Don't set dtypep in the ranging;
// We need to autosize parameters and integers separately // We need to autosize parameters and integers separately
// //

View File

@ -7,14 +7,12 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug376");
compile ( compile (
); );
execute ( execute (
check_finished=>1, check_finished=>1,
); );
ok(1); ok(1);
1; 1;

18
test_regress/t/t_param_type2.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,40 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2012 by Iztok Jeras.
package tt_pkg;
typedef enum logic [1:0] {L0, L1, L2, L3} test_t;
endpackage
module t (/*AUTOARG*/
// Outputs
ob
);
output [1:0] ob;
import tt_pkg::*;
test_t a;
test_t b;
assign a = L0;
assign ob = b;
tt_buf #(.T_t(test_t))
u_test
(.i(a), .o(b));
endmodule
module tt_buf
#(
parameter type T_t = logic [0:0]
)
(
input T_t i,
output T_t o
);
assign o = i;
endmodule

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,107 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2009 by Wilson Snyder.
typedef reg [2:0] threeansi_t;
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
reg [63:0] crc;
reg [63:0] sum;
// Take CRC data and apply to testblock inputs
wire [2:0] in = crc[2:0];
localparam type three_t = reg [2:0];
three_t outna;
three_t outa;
TestNonAnsi #( .p_t (reg [2:0]) )
test (// Outputs
.out (outna),
/*AUTOINST*/
// Inputs
.clk (clk),
.in (in[2:0]));
TestAnsi #( .p_t (reg [2:0]))
testa (// Outputs
.out (outa),
/*AUTOINST*/
// Inputs
.clk (clk),
.in (in[2:0]));
// Aggregate outputs into a single result vector
wire [63:0] result = {57'h0, outna, 1'b0, outa};
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
`endif
cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
if (cyc==0) begin
// Setup
crc <= 64'h5aef0c8d_d70a4497;
sum <= 64'h0;
end
else if (cyc<10) begin
sum <= 64'h0;
end
else if (cyc<90) begin
end
else if (cyc==99) begin
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
if (crc !== 64'hc77bb9b3784ea091) $stop;
// What checksum will we end up with (above print should match)
`define EXPECTED_SUM 64'h018decfea0a8828a
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module TestNonAnsi (/*AUTOARG*/
// Outputs
out,
// Inputs
clk, in
);
parameter type p_t = shortint;
input clk;
input p_t in;
output p_t out;
always @(posedge clk) begin
out <= ~in;
end
endmodule
module TestAnsi
#( parameter type p_t = shortint )
(
input clk,
input p_t in,
output p_t out
);
always @(posedge clk) begin
out <= ~in;
end
endmodule
// Local Variables:
// verilog-typedef-regexp: "_t$"
// End: