Add public enums, bug833.

This commit is contained in:
Wilson Snyder 2014-11-07 07:50:11 -05:00
parent e9c46afcf7
commit 3f82fd2f37
13 changed files with 207 additions and 7 deletions

View File

@ -9,6 +9,8 @@ indicates the contributor was also the author of the fix; Thanks!
*** Add optimization of operators between concats, msg1447. [Jie Xu] *** Add optimization of operators between concats, msg1447. [Jie Xu]
*** Add public enums, bug833. [Jonathon Donaldson]
**** Fix public parameters in unused packages, bug804. [Jonathon Donaldson] **** Fix public parameters in unused packages, bug804. [Jonathon Donaldson]
**** Fix generate unrolling with function call, bug830. [Steven Slatter] **** Fix generate unrolling with function call, bug830. [Steven Slatter]

View File

@ -2251,6 +2251,14 @@ reduce the size of the final executable when a task is used a very large
number of times. For this flag to work, the task and tasks below it must number of times. For this flag to work, the task and tasks below it must
be pure; they cannot reference any variables outside the task itself. be pure; they cannot reference any variables outside the task itself.
=item /*verilator public*/ (typedef enum)
Used after an enum typedef declaration to indicate the emitted C code
should have the enum values visible. Due to C++ language restrictions, this
may only be used on 64-bit or narrower integral enumerations.
typedef enum logic [2:0] { ZERO = 3'b0 } pub_t /*verilator public*/;
=item /*verilator public*/ (variable) =item /*verilator public*/ (variable)
Used after an input, output, register, or wire declaration to indicate the Used after an input, output, register, or wire declaration to indicate the

View File

@ -236,6 +236,8 @@ public:
DIM_SIZE, // V3Width processes DIM_SIZE, // V3Width processes
DIM_UNPK_DIMENSIONS, // V3Width converts to constant DIM_UNPK_DIMENSIONS, // V3Width converts to constant
// //
DT_PUBLIC, // V3LinkParse moves to AstTypedef::attrPublic
//
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
// //
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
@ -255,6 +257,7 @@ public:
"%E-AT", "%E-AT",
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT", "DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS", "DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
"DT_PUBLIC",
"MEMBER_BASE", "MEMBER_BASE",
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC", "VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW", "VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
@ -1565,8 +1568,9 @@ public:
virtual void dumpSmall(ostream& str); virtual void dumpSmall(ostream& str);
virtual bool hasDType() const { return true; } virtual bool hasDType() const { return true; }
virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const = 0; // recurses over typedefs to next non-typeref type virtual AstNodeDType* skipRefp() const = 0; // recurses over typedefs/const/enum to next non-typeref type
virtual AstNodeDType* skipRefToConstp() const = 0; // recurses over typedefs to next non-typeref-or-const type virtual AstNodeDType* skipRefToConstp() const = 0; // recurses over typedefs to next non-typeref-or-const type
virtual AstNodeDType* skipRefToEnump() const = 0; // recurses over typedefs/const to next non-typeref-or-enum/struct type
virtual int widthAlignBytes() const = 0; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) virtual int widthAlignBytes() const = 0; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... virtual int widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
virtual bool maybePointedTo() const { return true; } virtual bool maybePointedTo() const { return true; }
@ -1617,6 +1621,7 @@ public:
virtual AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); } virtual AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); }
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
// op1 = members // op1 = members
@ -1673,6 +1678,7 @@ public:
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); } virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); }
int msb() const; int msb() const;

View File

@ -819,6 +819,10 @@ void AstPin::dump(ostream& str) {
else { str<<" ->UNLINKED"; } else { str<<" ->UNLINKED"; }
if (svImplicit()) str<<" [.SV]"; if (svImplicit()) str<<" [.SV]";
} }
void AstTypedef::dump(ostream& str) {
this->AstNode::dump(str);
if (attrPublic()) str<<" [PUBLIC]";
}
void AstRange::dump(ostream& str) { void AstRange::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
if (littleEndian()) str<<" [LITTLE]"; if (littleEndian()) str<<" [LITTLE]";

View File

@ -183,22 +183,30 @@ public:
class AstTypedef : public AstNode { class AstTypedef : public AstNode {
private: private:
string m_name; string m_name;
bool m_attrPublic;
public: public:
AstTypedef(FileLine* fl, const string& name, VFlagChildDType, AstNodeDType* dtp) AstTypedef(FileLine* fl, const string& name, AstNode* attrsp, VFlagChildDType, AstNodeDType* dtp)
: AstNode(fl), m_name(name) { : AstNode(fl), m_name(name) {
childDTypep(dtp); // Only for parser childDTypep(dtp); // Only for parser
addAttrsp(attrsp);
dtypep(NULL); // V3Width will resolve dtypep(NULL); // V3Width will resolve
m_attrPublic = false;
} }
ASTNODE_NODE_FUNCS(Typedef, TYPEDEF) ASTNODE_NODE_FUNCS(Typedef, TYPEDEF)
virtual void dump(ostream& str);
AstNodeDType* getChildDTypep() const { return childDTypep(); } AstNodeDType* getChildDTypep() const { return childDTypep(); }
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Type assigning to AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Type assigning to
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
void addAttrsp(AstNode* nodep) { addNOp4p(nodep); }
AstNode* attrsp() const { return op4p()->castNode(); } // op4 = Attributes during early parse
// METHODS // METHODS
virtual string name() const { return m_name; } virtual string name() const { return m_name; }
virtual bool maybePointedTo() const { return true; } virtual bool maybePointedTo() const { return true; }
virtual bool hasDType() const { return true; } virtual bool hasDType() const { return true; }
void name(const string& flag) { m_name = flag; } void name(const string& flag) { m_name = flag; }
bool attrPublic() const { return m_attrPublic; }
void attrPublic(bool flag) { m_attrPublic = flag; }
}; };
class AstTypedefFwd : public AstNode { class AstTypedefFwd : public AstNode {
@ -242,6 +250,7 @@ public:
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); } virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); } virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
virtual string name() const { return m_name; } virtual string name() const { return m_name; }
@ -384,6 +393,7 @@ public:
virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
AstBasicDTypeKwd keyword() const { return m.m_keyword; } // Avoid using - use isSomething accessors instead AstBasicDTypeKwd keyword() const { return m.m_keyword; } // Avoid using - use isSomething accessors instead
@ -445,6 +455,7 @@ public:
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); } virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
}; };
@ -474,6 +485,7 @@ public:
virtual AstBasicDType* basicp() const { return NULL; } virtual AstBasicDType* basicp() const { return NULL; }
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return 1; } virtual int widthAlignBytes() const { return 1; }
virtual int widthTotalBytes() const { return 1; } virtual int widthTotalBytes() const { return 1; }
string cellName() const { return m_cellName; } string cellName() const { return m_cellName; }
@ -528,6 +540,10 @@ public:
if (defp()) return defp()->skipRefToConstp(); if (defp()) return defp()->skipRefToConstp();
else { v3fatalSrc("Typedef not linked"); return NULL; } else { v3fatalSrc("Typedef not linked"); return NULL; }
} }
virtual AstNodeDType* skipRefToEnump() const {
if (defp()) return defp()->skipRefToEnump();
else { v3fatalSrc("Typedef not linked"); return NULL; }
}
virtual int widthAlignBytes() const { return dtypeSkipRefp()->widthAlignBytes(); } virtual int widthAlignBytes() const { return dtypeSkipRefp()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return dtypeSkipRefp()->widthTotalBytes(); } virtual int widthTotalBytes() const { return dtypeSkipRefp()->widthTotalBytes(); }
void name(const string& flag) { m_name = flag; } void name(const string& flag) { m_name = flag; }
@ -599,6 +615,7 @@ public:
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType) AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); } virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); } virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
// METHODS // METHODS
@ -688,6 +705,7 @@ public:
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); } virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); } virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
}; };

View File

@ -238,6 +238,10 @@ private:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
insureCleanAndNext (nodep->valuep()); insureCleanAndNext (nodep->valuep());
} }
virtual void visit(AstTypedef* 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

@ -165,6 +165,13 @@ private:
nodep->packagep()->user1Inc(); nodep->packagep()->user1Inc();
} }
} }
virtual void visit(AstTypedef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
// Don't let packages with only public variables disappear
// Normal modules may disappear, e.g. if they are parameterized then removed
if (nodep->attrPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
}
virtual void visit(AstVarScope* nodep, AstNUser*) { virtual void visit(AstVarScope* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);

View File

@ -96,6 +96,38 @@ public:
} }
} }
void emitTypedefs(AstNode* firstp) {
bool first = true;
for (AstNode* loopp=firstp; loopp; loopp = loopp->nextp()) {
if (AstTypedef* nodep = loopp->castTypedef()) {
if (nodep->attrPublic()) {
if (first) {
first = false;
puts("\n// TYPEDEFS\n");
puts("// That were declared public\n");
} else {
puts("\n");
}
if (AstEnumDType* adtypep = nodep->dtypep()->skipRefToEnump()->castEnumDType()) {
if (adtypep->width()>64) {
puts("// enum "+nodep->name()+" // Ignored: Too wide for C++\n");
} else {
puts("enum "+nodep->name()+" {\n");
for (AstEnumItem* itemp = adtypep->itemsp(); itemp; itemp=itemp->nextp()->castEnumItem()) {
puts(itemp->name());
puts(" = ");
itemp->valuep()->iterateAndNext(*this);
if (nodep->nextp()) puts(",");
puts("\n");
}
puts("};\n");
}
}
}
}
}
}
// VISITORS // VISITORS
virtual void visit(AstNodeAssign* nodep, AstNUser*) { virtual void visit(AstNodeAssign* nodep, AstNUser*) {
bool paren = true; bool decind = false; bool paren = true; bool decind = false;
@ -663,6 +695,7 @@ public:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
// NOPs // NOPs
virtual void visit(AstTypedef*, AstNUser*) {}
virtual void visit(AstPragma*, AstNUser*) {} virtual void visit(AstPragma*, AstNUser*) {}
virtual void visit(AstCell*, AstNUser*) {} // Handled outside the Visit class virtual void visit(AstCell*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstVar*, AstNUser*) {} // Handled outside the Visit class virtual void visit(AstVar*, AstNUser*) {} // Handled outside the Visit class
@ -670,7 +703,6 @@ public:
virtual void visit(AstTraceDecl*, AstNUser*) {} // Handled outside the Visit class virtual void visit(AstTraceDecl*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstTraceInc*, AstNUser*) {} // Handled outside the Visit class virtual void visit(AstTraceInc*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstCFile*, AstNUser*) {} // Handled outside the Visit class virtual void visit(AstCFile*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstTypedef*, AstNUser*) {} // Nothing needed presently
// Default // Default
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
puts((string)"\n???? // "+nodep->prettyTypeName()+"\n"); puts((string)"\n???? // "+nodep->prettyTypeName()+"\n");
@ -1845,6 +1877,8 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
} }
} }
emitTypedefs(modp->stmtsp());
puts("\n// PORTS\n"); puts("\n// PORTS\n");
if (modp->isTop()) puts("// The application code writes and reads these signals to\n"); if (modp->isTop()) puts("// The application code writes and reads these signals to\n");
if (modp->isTop()) puts("// propagate new values into/out from the Verilated model.\n"); if (modp->isTop()) puts("// propagate new values into/out from the Verilated model.\n");

View File

@ -62,6 +62,7 @@ private:
AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module
AstNodeModule* m_modp; // Current module AstNodeModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Current task AstNodeFTask* m_ftaskp; // Current task
AstNodeDType* m_dtypep; // Current data type
// METHODS // METHODS
static int debug() { static int debug() {
@ -104,6 +105,15 @@ private:
m_valueModp = upperValueModp; m_valueModp = upperValueModp;
} }
} }
virtual void visit(AstNodeDType* nodep, AstNUser*) {
if (!nodep->user1SetOnce()) { // Process only once.
cleanFileline(nodep);
AstNodeDType* upperDtypep = m_dtypep;
m_dtypep = nodep;
nodep->iterateChildren(*this);
m_dtypep = upperDtypep;
}
}
virtual void visit(AstEnumItem* nodep, AstNUser*) { virtual void visit(AstEnumItem* nodep, AstNUser*) {
// Expand ranges // Expand ranges
cleanFileline(nodep); cleanFileline(nodep);
@ -176,7 +186,13 @@ private:
virtual void visit(AstAttrOf* nodep, AstNUser*) { virtual void visit(AstAttrOf* nodep, AstNUser*) {
cleanFileline(nodep); cleanFileline(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (nodep->attrType() == AstAttrType::VAR_CLOCK) { if (nodep->attrType() == AstAttrType::DT_PUBLIC) {
AstTypedef* typep = nodep->backp()->castTypedef();
if (!typep) nodep->v3fatalSrc("Attribute not attached to typedef");
typep->attrPublic(true);
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
}
else if (nodep->attrType() == AstAttrType::VAR_CLOCK) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrScClocked(true); m_varp->attrScClocked(true);
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
@ -265,7 +281,7 @@ private:
nodep->deleteTree(); nodep=NULL; nodep->deleteTree(); nodep=NULL;
return; return;
} else { } else {
defp = new AstTypedef(nodep->fileline(), nodep->name(), VFlagChildDType(), dtypep); defp = new AstTypedef(nodep->fileline(), nodep->name(), NULL, VFlagChildDType(), dtypep);
m_implTypedef.insert(make_pair(make_pair(nodep->containerp(), defp->name()), defp)); m_implTypedef.insert(make_pair(make_pair(nodep->containerp(), defp->name()), defp));
backp->addNextHere(defp); backp->addNextHere(defp);
} }
@ -327,6 +343,7 @@ public:
m_varp = NULL; m_varp = NULL;
m_modp = NULL; m_modp = NULL;
m_ftaskp = NULL; m_ftaskp = NULL;
m_dtypep = NULL;
m_inAlways = false; m_inAlways = false;
m_inGenerate = false; m_inGenerate = false;
m_needStart = false; m_needStart = false;

View File

@ -1600,8 +1600,9 @@ implicit_typeE<dtypep>: // IEEE: part of *data_type_or_implicit
type_declaration<nodep>: // ==IEEE: type_declaration type_declaration<nodep>: // ==IEEE: type_declaration
// // Use idAny, as we can redeclare a typedef on an existing typedef // // Use idAny, as we can redeclare a typedef on an existing typedef
yTYPEDEF data_type idAny variable_dimensionListE ';' { $$ = new AstTypedef($<fl>1, *$3, VFlagChildDType(), GRAMMARP->createArray($2,$4,false)); yTYPEDEF data_type idAny variable_dimensionListE dtypeAttrListE ';'
SYMP->reinsert($$); } /**/ { $$ = new AstTypedef($<fl>1, *$3, $5, VFlagChildDType(), GRAMMARP->createArray($2,$4,false));
SYMP->reinsert($$); }
//UNSUP yTYPEDEF id/*interface*/ '.' idAny/*type*/ idAny/*type*/ ';' { $$ = NULL; $1->v3error("Unsupported: SystemVerilog 2005 typedef in this context"); } //UNSUP //UNSUP yTYPEDEF id/*interface*/ '.' idAny/*type*/ idAny/*type*/ ';' { $$ = NULL; $1->v3error("Unsupported: SystemVerilog 2005 typedef in this context"); } //UNSUP
// // Combines into above "data_type id" rule // // Combines into above "data_type id" rule
// // Verilator: Not important what it is in the AST, just need to make sure the yaID__aTYPE gets returned // // Verilator: Not important what it is in the AST, just need to make sure the yaID__aTYPE gets returned
@ -1612,6 +1613,20 @@ type_declaration<nodep>: // ==IEEE: type_declaration
//UNSUP yTYPEDEF yCLASS idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($<fl>1, *$3); SYMP->reinsert($$); } //UNSUP yTYPEDEF yCLASS idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($<fl>1, *$3); SYMP->reinsert($$); }
; ;
dtypeAttrListE<nodep>:
/* empty */ { $$ = NULL; }
| dtypeAttrList { $$ = $1; }
;
dtypeAttrList<nodep>:
dtypeAttr { $$ = $1; }
| dtypeAttrList dtypeAttr { $$ = $1->addNextNull($2); }
;
dtypeAttr<nodep>:
yVL_PUBLIC { $$ = new AstAttrOf($1,AstAttrType::DT_PUBLIC); }
;
//************************************************ //************************************************
// Module Items // Module Items

View File

@ -0,0 +1,26 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2006 by Wilson Snyder.
#include <verilated.h>
#include "Vt_enum_public.h"
#include "Vt_enum_public_p3.h"
#include "Vt_enum_public_p62.h"
int main (int argc, char *argv[]) {
Vt_enum_public *topp = new Vt_enum_public;
Verilated::debug(0);
// Make sure public tag worked
if (Vt_enum_public_p3::ZERO || Vt_enum_public_p3::ONE) {}
if (Vt_enum_public_p62::ZERO || Vt_enum_public_p62::ALLONE) {}
for (int i = 0; i < 10; i++) {
topp->eval();
}
}

26
test_regress/t/t_enum_public.pl Executable file
View File

@ -0,0 +1,26 @@
#!/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.
if ($Self->{vlt}) {
compile (
verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp"],
make_top_shell => 0,
make_main => 0,
);
} else {
compile (
);
}
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -0,0 +1,33 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2009 by Wilson Snyder.
package p3;
typedef enum logic [2:0] {
ZERO = 3'b0,
ONE = 3'b1 } e3_t /*verilator public*/;
endpackage
package p62;
typedef enum logic [62:0] {
ZERO = '0,
ALLONE = '1 } e62_t /*verilator public*/;
endpackage
module t (/*AUTOARG*/);
enum integer {
EI_A,
EI_B,
EI_C
} m_state;
initial begin
m_state = EI_A;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule