diff --git a/Changes b/Changes index 204fbbc9c..4be0ac478 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,8 @@ indicates the contributor was also the author of the fix; Thanks! *** Support SystemVerilog "logic", bug101. [by Alex Duller] +*** Name SYMRSVDWORD error, and allow disabling it, bug103. [Gary Thomas] + * Verilator 3.712 2009/07/14 ** Patching SystemC is no longer required to trace sc_bvs. diff --git a/bin/verilator b/bin/verilator index 1abb57bad..5c9e366a3 100755 --- a/bin/verilator +++ b/bin/verilator @@ -1965,6 +1965,13 @@ example: Ignoring this warning may make Verilator simulations differ from other simulators. +=item SYMRSVDWORD + +Error that a symbol matches a C++ reserved word and using this as a symbol +name would result in odd C compiler errors. You may disable this error +message as you would disable warnings, but the symbol will be renamed by +Verilator to avoid the conflict. + =item TASKNSVAR Error when a call to a task or function has a output from that task tied to diff --git a/src/V3Ast.h b/src/V3Ast.h index dc136e9b1..5f3b48961 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -669,6 +669,7 @@ public: // ACCESSORS virtual string name() const { return ""; } + virtual void name(const string& name) { this->v3fatalSrc("name() called on object without name() method"); } virtual string verilogKwd() const { return ""; } string shortName() const; // Name with __PVT__ removed for concatenating scopes static string dedotName(const string& namein); // Name with dots removed @@ -1058,7 +1059,7 @@ public: virtual int instrCount() const { return widthInstrs(); } virtual void cloneRelink(); virtual string name() const { return m_name; } // * = Var name - void name(const string& name) { m_name = name; } + virtual void name(const string& name) { m_name = name; } bool lvalue() const { return m_lvalue; } void lvalue(bool lval) { m_lvalue=lval; } // Avoid using this; Set in constructor AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable @@ -1135,7 +1136,7 @@ public: virtual bool maybePointedTo() const { return true; } // {AstFunc only} op1 = Range output variable // op3 = Statements/Ports/Vars - void name(const string& name) { m_name = name; } + virtual void name(const string& name) { m_name = name; } AstNode* stmtsp() const { return op3p()->castNode(); } // op1 = List of statements void addStmtsp(AstNode* nodep) { addOp3p(nodep); } void taskPublic(bool flag) { m_taskPublic=flag; } @@ -1168,7 +1169,7 @@ public: void inlinedDots(const string& flag) { m_inlinedDots = flag; } AstNodeFTask* taskp() const { return m_taskp; } // [After Link] Pointer to variable void taskp(AstNodeFTask* taskp) { m_taskp=taskp; } - void name(const string& name) { m_name = name; } + virtual void name(const string& name) { m_name = name; } void dotted(const string& name) { m_dotted = name; } // op1 = namep AstNode* namep() const { return op1p(); } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index b45d92554..b223242e3 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -308,7 +308,7 @@ public: void funcReturn(bool flag) { m_funcReturn = flag; } void trace(bool flag) { m_trace=flag; } // METHODS - void name(const string& name) { m_name = name; } + virtual void name(const string& name) { m_name = name; } bool isInput() const { return m_input; } bool isOutput() const { return m_output; } bool isInOnly() const { return m_input && !m_output; } @@ -425,7 +425,7 @@ public: virtual bool broken() const; virtual bool maybePointedTo() const { return true; } virtual string name() const { return m_name; } // * = Scope name - void name(const string& name) { m_name = name; } + virtual void name(const string& name) { m_name = name; } string nameDotless() const; string nameVlSym() const { return (((string)"vlSymsp->") + nameDotless()); } AstModule* modp() const { return m_modp; } @@ -565,7 +565,7 @@ public: virtual void dump(ostream& str); virtual bool broken() const { return (m_modVarp && !m_modVarp->brokeExists()); } virtual string name() const { return m_name; } // * = Pin name, ""=go by number - void name(const string& name) { m_name = name; } + virtual void name(const string& name) { m_name = name; } bool dotStar() const { return name() == ".*"; } // Special fake name for .* connections until linked int pinNum() const { return m_pinNum; } void exprp(AstNode* nodep) { addOp1p(nodep); } @@ -605,7 +605,7 @@ public: void addStmtp(AstNode* nodep) { addOp2p(nodep); } void addActivep(AstNode* nodep) { addOp3p(nodep); } // ACCESSORS - void name(const string& name) { m_name = name; } + virtual void name(const string& name) { m_name = name; } string origName() const { return m_origName; } bool inLibrary() const { return m_inLibrary; } void inLibrary(bool flag) { m_inLibrary = flag; } @@ -642,7 +642,7 @@ public: virtual bool maybePointedTo() const { return true; } // ACCESSORS virtual string name() const { return m_name; } // * = Cell name - void name(const string& name) { m_name = name; } + virtual void name(const string& name) { m_name = name; } string origName() const { return m_origName; } // * = Original name void origName(const string& name) { m_origName = name; } string modName() const { return m_modName; } // * = Instance name @@ -672,7 +672,7 @@ public: // ACCESSORS virtual string name() const { return m_name; } // * = Cell name string origModName() const { return m_origModName; } // * = modp()->origName() before inlining - void name(const string& name) { m_name = name; } + virtual void name(const string& name) { m_name = name; } }; struct AstPort : public AstNode { @@ -707,7 +707,7 @@ public: } ASTNODE_NODE_FUNCS(Begin, BEGIN) virtual string name() const { return m_name; } // * = Block name - void name(const string& flag) { m_name=flag; } + virtual void name(const string& name) { m_name = name; } // op1 = Statements AstNode* stmtsp() const { return op1p()->castNode(); } // op1 = List of statements void addStmtp(AstNode* nodep) { addOp1p(nodep); } @@ -2627,7 +2627,7 @@ public: virtual string name() const { return m_name; } // * = Var name virtual V3Hash sameHash() const { return V3Hash(name()); } virtual bool same(AstNode* samep) const { return samep->name() == name(); } - void name(const string& flag) { m_name = flag; } + virtual void name(const string& name) { m_name = name; } AstNode* propp() const { return op1p(); } // op1 = property AstSenTree* sentreep() const { return op2p()->castSenTree(); } // op2 = clock domain void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain @@ -2809,7 +2809,7 @@ public: && (rtnTypeVoid()==samep->castCFunc()->rtnTypeVoid()) && (argTypes()==samep->castCFunc()->argTypes())); } // - void name(const string& flag) { m_name = flag; } + virtual void name(const string& name) { m_name = name; } AstScope* scopep() const { return m_scopep; } void scopep(AstScope* nodep) { m_scopep = nodep; } string rtnTypeVoid() const { return ((m_rtnType=="") ? "void" : m_rtnType); } diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 093225fc6..3a41e79ae 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -65,7 +65,9 @@ class EmitCSyms : EmitCBaseVisitor { if (nodep->name() != "") { string rsvd = m_words.isKeyword(nodep->name()); if (rsvd != "") { - nodep->v3error("Unsupported: "+rsvd+": "<name()); + // Generally V3Name should find all of these and throw SYMRSVDWORD. + // We'll still check here because the compiler errors resulting if we miss this warning are SO nasty + nodep->v3error("Symbol matching "+rsvd+" reserved word reached emitter, should have hit SYMRSVDWORD: '"<name()<<"'"); } } } diff --git a/src/V3Error.h b/src/V3Error.h index 4bdbec10e..4c883fd09 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -59,6 +59,7 @@ public: CMPCONST, // Comparison is constant due to limited range COMBDLY, // Combinatorial delayed assignment STMTDLY, // Delayed statement + SYMRSVDWORD, // Symbol is Reserved Word GENCLK, // Generated Clock IMPERFECTSCH, // Imperfect schedule (disabled by default) IMPLICIT, // Implicit wire @@ -94,7 +95,7 @@ public: " FIRST_WARN", "BLKANDNBLK", "CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CMPCONST", - "COMBDLY", "STMTDLY", "GENCLK", "IMPERFECTSCH", "IMPLICIT", "IMPURE", + "COMBDLY", "STMTDLY", "SYMRSVDWORD", "GENCLK", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "MULTIDRIVEN", "REDEFMACRO", "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED", "VARHIDDEN", "WIDTH", "WIDTHCONCAT", @@ -108,7 +109,7 @@ public: bool dangerous() const { return ( m_e==COMBDLY ); } // Warnings we'll present to the user as errors // Later -Werror- options may make more of these. - bool pretendError() const { return ( m_e==BLKANDNBLK || m_e==IMPURE ); } + bool pretendError() const { return ( m_e==BLKANDNBLK || m_e==IMPURE || m_e==SYMRSVDWORD); } // Warnings to mention manual bool mentionManual() const { return ( m_e==FATALSRC || pretendError() ); } diff --git a/src/V3Name.cpp b/src/V3Name.cpp index c51ccbb6e..fd953eceb 100644 --- a/src/V3Name.cpp +++ b/src/V3Name.cpp @@ -34,6 +34,7 @@ #include "V3Global.h" #include "V3Name.h" #include "V3Ast.h" +#include "V3LanguageWords.h" //###################################################################### // Name state, as a visitor of each AstNode @@ -45,14 +46,11 @@ private: // AstCell::user1() -> bool. Set true if already processed // AstScope::user1() -> bool. Set true if already processed // AstVar::user1() -> bool. Set true if already processed - // - // AstCell::user2() -> bool. Set true if was privitized - // AstVar::user2() -> bool. Set true if was privitized AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; // STATE AstModule* m_modp; + V3LanguageWords m_words; // Reserved word detector // METHODS static int debug() { @@ -61,6 +59,23 @@ private: return level; } + void rename(AstNode* nodep, bool addPvt) { + if (!nodep->user1()) { // Not already done + if (addPvt) { + string newname = (string)"__PVT__"+nodep->name(); + nodep->name(newname); + } else { + string rsvd = m_words.isKeyword(nodep->name()); + if (rsvd != "") { + nodep->v3warn(SYMRSVDWORD,"Symbol matches "+rsvd+": '"<name()<<"'"); + string newname = (string)"__SYM__"+nodep->name(); + nodep->name(newname); + } + } + nodep->user1(1); + } + } + // VISITORS virtual void visit(AstModule* nodep, AstNUser*) { m_modp = nodep; @@ -70,16 +85,13 @@ private: // Add __PVT__ to names of local signals virtual void visit(AstVar* nodep, AstNUser*) { // Don't iterate... Don't need temps for RANGES under the Var. - if (!nodep->user1() - && !m_modp->isTop() - && !nodep->isSigPublic() - && !nodep->isTemp()) { // Don't bother to rename internal signals - // Change the name to something private... - string newname = (string)"__PVT__"+nodep->name(); - nodep->name(newname); - nodep->user1(1); - nodep->user2(1); - } + rename(nodep, (!m_modp->isTop() + && !nodep->isSigPublic() + && !nodep->isTemp())); // Don't bother to rename internal signals + } + virtual void visit(AstCFunc* nodep, AstNUser*) { + nodep->iterateChildren(*this); + rename(nodep, false); } virtual void visit(AstVarRef* nodep, AstNUser*) { if (nodep->varp()) { @@ -88,14 +100,7 @@ private: } } virtual void visit(AstCell* nodep, AstNUser*) { - if (!nodep->user1() - && !nodep->modp()->modPublic()) { - // Change the name to something private... - string newname = (string)"__PVT__"+nodep->name(); - nodep->name(newname); - nodep->user1(1); - nodep->user2(1); - } + rename(nodep, !nodep->modp()->modPublic()); nodep->iterateChildren(*this); } virtual void visit(AstScope* nodep, AstNUser*) { diff --git a/test_regress/t/t_var_bad_rsvd.pl b/test_regress/t/t_var_bad_rsvd.pl deleted file mode 100755 index fea0a7e64..000000000 --- a/test_regress/t/t_var_bad_rsvd.pl +++ /dev/null @@ -1,19 +0,0 @@ -#!/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 ( - fails=>$Self->{v3}, - expect=> -'%Error: t/t_var_bad_rsvd.v:\d+: Unsupported: C\+\+ common word: bool -%Error: t/t_var_bad_rsvd.v:\d+: Unsupported: C\+\+ reserved word: switch -%Error: Exiting due to.*', - ); - -ok(1); -1; diff --git a/test_regress/t/t_var_bad_rsvd.v b/test_regress/t/t_var_bad_rsvd.v deleted file mode 100644 index 48492614b..000000000 --- a/test_regress/t/t_var_bad_rsvd.v +++ /dev/null @@ -1,18 +0,0 @@ -// DESCRIPTION: Verilator: Verilog Test module -// -// This file ONLY is placed into the Public Domain, for any use, -// without warranty, 2005 by Wilson Snyder. - -module t (/*AUTOARG*/ - // Inputs - bool - ); - - input bool; // BAD - - reg vector; // OK, as not public - reg switch /*verilator public*/; // Bad - - initial $stop; - -endmodule