Fix multiple declarations on one enum, bug199

This commit is contained in:
Wilson Snyder 2010-01-06 19:04:20 -05:00
parent cdcb94751e
commit eb63c8dcb8
4 changed files with 85 additions and 2 deletions

View File

@ -147,6 +147,33 @@ public:
virtual string name() const { return m_name; }
};
struct AstDefImplicitDType : public AstNodeDType {
// For parsing enum/struct/unions that are declared with a variable rather than typedef
// This allows "var enum {...} a,b" to share the enum definition for both variables
// After link, these become typedefs
private:
string m_name;
void* m_containerp; // In what scope is the name unique, so we can know what are duplicate definitions (arbitrary value)
public:
AstDefImplicitDType(FileLine* fl, const string& name, AstNode* containerp, AstNodeDType* dtypep)
: AstNodeDType(fl), m_name(name), m_containerp(containerp) {
setOp1p(dtypep);
widthSignedFrom(dtypep);
}
ASTNODE_NODE_FUNCS(DefImplicitDType, DEFIMPLICITDTYPE)
AstNodeDType* dtypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); } // op1 = Range of variable
void dtypep(AstNodeDType* nodep) { setOp1p(nodep); }
void* containerp() const { return m_containerp; }
// METHODS
virtual AstBasicDType* basicp() const { return dtypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
virtual string name() const { return m_name; }
void name(const string& flag) { m_name = flag; }
};
struct AstArrayDType : public AstNodeDType {
// Array data type, ie "some_dtype var_name [2:0]"
AstArrayDType(FileLine* fl, AstNodeDType* dtypep, AstRange* rangep)

View File

@ -50,12 +50,16 @@ private:
// AstNode::user() -> bool. True if processed
AstUser1InUse m_inuser1;
// TYPES
typedef map <pair<void*,string>,AstTypedef*> ImplTypedefMap;
// STATE
string m_dotText; // Dotted module text we are building for a dotted node, passed up
bool m_inModDot; // We're inside module part of dotted name
AstParseRefExp m_exp; // Type of data we're looking for
AstText* m_baseTextp; // Lowest TEXT node that needs replacement with varref
AstVar* m_varp; // Variable we're under
ImplTypedefMap m_implTypedef; // Created typedefs for each <container,name>
// METHODS
static int debug() {
@ -285,6 +289,41 @@ private:
}
}
virtual void visit(AstDefImplicitDType* nodep, AstNUser*) {
UINFO(8," DEFIMPLICIT "<<nodep<<endl);
// Must remember what names we've already created, and combine duplicates
// so that for "var enum {...} a,b" a & b will share a common typedef
// Unique name space under each containerp() so that an addition of a new type won't change every verilated module.
AstTypedef* defp = NULL;
ImplTypedefMap::iterator it = m_implTypedef.find(make_pair(nodep->containerp(), nodep->name()));
if (it != m_implTypedef.end()) {
defp = it->second;
} else {
// Definition must be inserted right after the variable (etc) that needed it
// AstVar, AstTypedef, AstNodeFTask are common containers
AstNode* backp = nodep->backp();
for (; backp; backp=nodep->backp()) {
if (backp->castVar()) break;
else if (backp->castTypedef()) break;
else if (backp->castNodeFTask()) break;
}
if (!backp) nodep->v3fatalSrc("Implicit enum/struct type created under unexpected node type");
AstNodeDType* dtypep = nodep->dtypep(); dtypep->unlinkFrBack();
if (backp->castTypedef()) { // A typedef doesn't need us to make yet another level of typedefing
// For typedefs just remove the AstRefDType level of abstraction
nodep->replaceWith(dtypep);
nodep->deleteTree(); nodep=NULL;
return;
} else {
defp = new AstTypedef(nodep->fileline(), nodep->name(), dtypep);
m_implTypedef.insert(make_pair(make_pair(nodep->containerp(), defp->name()), defp));
backp->addNextHere(defp);
}
}
nodep->replaceWith(new AstRefDType(nodep->fileline(), defp->name()));
nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstNode* nodep, AstNUser*) {
// Default: Just iterate
checkExpected(nodep); // So we detect node types we forgot to list here

View File

@ -59,6 +59,8 @@ public:
int m_pinNum; // Pin number currently parsing
string m_instModule; // Name of module referenced for instantiations
AstPin* m_instParamp; // Parameters for instantiations
AstNodeModule* m_modp; // Module
int m_modTypeImpNum; // Implicit type number, incremented each module
int m_uniqueAttr; // Bitmask of unique/priority keywords
// CONSTRUCTORS
@ -70,6 +72,8 @@ public:
m_pinNum = -1;
m_instModule;
m_instParamp = NULL;
m_modp = NULL;
m_modTypeImpNum = 0;
m_varAttrp = NULL;
m_caseAttrp = NULL;
}
@ -107,6 +111,7 @@ public:
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
GRAMMARP->m_modp = pkgp; GRAMMARP->m_modTypeImpNum = 0;
PARSEP->rootp()->addModulep(pkgp);
SYMP->reinsert(pkgp, SYMP->symRootp()); // Don't push/pop scope as they're global
}
@ -583,6 +588,7 @@ packageFront<modulep>:
{ $$ = new AstPackage($1,*$2);
$$->inLibrary(true); // packages are always libraries; don't want to make them a "top"
$$->modTrace(v3Global.opt.trace());
GRAMMARP->m_modp = $$; GRAMMARP->m_modTypeImpNum = 0;
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
;
@ -669,6 +675,7 @@ modFront<modulep>:
yMODULE lifetimeE idAny
{ $$ = new AstModule($1,*$3); $$->inLibrary(PARSEP->inLibrary()||PARSEP->inCellDefine());
$$->modTrace(v3Global.opt.trace());
GRAMMARP->m_modp = $$; GRAMMARP->m_modTypeImpNum = 0;
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
;
@ -679,6 +686,7 @@ udpFront<modulep>:
$$->modTrace(false);
$$->addStmtp(new AstPragma($1,AstPragmaType::INLINE_MODULE));
PARSEP->fileline()->tracingOn(false);
GRAMMARP->m_modp = $$; GRAMMARP->m_modTypeImpNum = 0;
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
;
@ -834,6 +842,7 @@ pgmFront<modulep>:
yPROGRAM lifetimeE idAny/*new_program*/
{ $$ = new AstModule($1,*$3); $$->inLibrary(PARSEP->inLibrary()||PARSEP->inCellDefine());
$$->modTrace(v3Global.opt.trace());
GRAMMARP->m_modp = $$; GRAMMARP->m_modTypeImpNum = 0;
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
;
@ -1060,7 +1069,7 @@ data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc referenc
//UNSUP { UNSUP }
//UNSUP yUNION taggedE packedSigningE '{' struct_union_memberList '}' packed_dimensionListE
//UNSUP { UNSUP }
| enumDecl { $$ = $1; }
| enumDecl { $$ = new AstDefImplicitDType($1->fileline(),"__typeimpenum"+cvtToStr(GRAMMARP->m_modTypeImpNum++),GRAMMARP->m_modp,$1); }
| ySTRING { $$ = new AstBasicDType($1,AstBasicDTypeKwd::STRING); }
| yCHANDLE { $$ = new AstBasicDType($1,AstBasicDTypeKwd::CHANDLE); }
//UNSUP yEVENT { UNSUP }

View File

@ -21,7 +21,7 @@ module t (/*AUTOARG*/
EP_State_DWAIT ,
EP_State_DSHIFT0 ,
EP_State_DSHIFT1 ,
EP_State_DSHIFT15 } m_state_xr;
EP_State_DSHIFT15 } m_state_xr, m_state2_xr;
// Beginning of automatic ASCII enum decoding
reg [79:0] m_stateAscii_xr; // Decode of m_state_xr
@ -49,21 +49,29 @@ module t (/*AUTOARG*/
//$write("%d %x %x %x\n", cyc, data, wrapcheck_a, wrapcheck_b);
if (cyc==1) begin
m_state_xr <= EP_State_IDLE;
m_state2_xr <= EP_State_IDLE;
end
if (cyc==2) begin
if (m_stateAscii_xr != "idle ") $stop;
m_state_xr <= EP_State_CMDSHIFT13;
if (m_state2_xr != EP_State_IDLE) $stop;
m_state2_xr <= EP_State_CMDSHIFT13;
end
if (cyc==3) begin
if (m_stateAscii_xr != "cmdshift13") $stop;
m_state_xr <= EP_State_CMDSHIFT16;
if (m_state2_xr != EP_State_CMDSHIFT13) $stop;
m_state2_xr <= EP_State_CMDSHIFT16;
end
if (cyc==4) begin
if (m_stateAscii_xr != "cmdshift16") $stop;
m_state_xr <= EP_State_DWAIT;
if (m_state2_xr != EP_State_CMDSHIFT16) $stop;
m_state2_xr <= EP_State_DWAIT;
end
if (cyc==9) begin
if (m_stateAscii_xr != "dwait ") $stop;
if (m_state2_xr != EP_State_DWAIT) $stop;
$write("*-* All Finished *-*\n");
$finish;
end