mirror of
https://github.com/verilator/verilator.git
synced 2025-01-22 14:24:18 +00:00
Fix multiple declarations on one enum, bug199
This commit is contained in:
parent
cdcb94751e
commit
eb63c8dcb8
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user