Allow renaming C keywords
This commit is contained in:
parent
c44febe85e
commit
59b491e3a8
2
Changes
2
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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(); }
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -65,7 +65,9 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
if (nodep->name() != "") {
|
||||
string rsvd = m_words.isKeyword(nodep->name());
|
||||
if (rsvd != "") {
|
||||
nodep->v3error("Unsupported: "+rsvd+": "<<nodep->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: '"<<nodep->name()<<"'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() ); }
|
||||
|
||||
|
|
|
|||
|
|
@ -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+": '"<<nodep->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*) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue