From f7efae93d57f90447e4a2476ab899b381f27591d Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 31 Oct 2009 10:08:38 -0400 Subject: [PATCH] Internals: Clean up the main flex/bison files to have some sanity. (Hopefully) no functional change. . V3Parse.h External consumer interface to V3ParseImp . V3ParseImp Internals to parser, common to across flex & bison ... V3ParseGrammar Wrapper that includes V3ParseBison ..... V3ParseBison Bison output ... V3ParseLex Wrapper that includes lex output ..... V3Lexer.yy.cpp Flex output --- src/Makefile_obj.in | 12 +- src/V3Ast.h | 2 +- src/V3AstNodes.h | 4 +- src/V3Const.cpp | 1 - src/V3Error.h | 2 +- src/V3LinkCells.cpp | 9 +- src/V3Param.cpp | 1 - src/V3Parse.h | 53 ++ src/{V3Parse.cpp => V3ParseGrammar.cpp} | 0 src/{V3Read.cpp => V3ParseImp.cpp} | 97 +--- src/V3ParseImp.h | 198 +++++++ src/V3ParseLex.cpp | 78 +++ src/V3PreShell.cpp | 10 +- src/V3PreShell.h | 4 +- src/V3Read.h | 139 ----- src/V3Simulate.h | 2 + src/Verilator.cpp | 18 +- src/verilog.l | 139 +++-- src/verilog.y | 738 ++++++++++++------------ 19 files changed, 852 insertions(+), 655 deletions(-) create mode 100644 src/V3Parse.h rename src/{V3Parse.cpp => V3ParseGrammar.cpp} (100%) rename src/{V3Read.cpp => V3ParseImp.cpp} (63%) create mode 100644 src/V3ParseImp.h create mode 100644 src/V3ParseLex.cpp delete mode 100644 src/V3Read.h diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index 716232a2c..111fc6c96 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -208,9 +208,10 @@ RAW_OBJS = \ # Non-concatable OBJS += \ - V3Parse.o \ + V3ParseImp.o \ + V3ParseGrammar.o \ + V3ParseLex.o \ V3PreProc.o \ - V3Read.o \ #### Linking @@ -245,10 +246,13 @@ V3Number_test: V3Number_test.o %.o: %.c $(OBJCACHE) ${CC} ${CPPFLAGS} -c $< -V3Read.o: V3Read.cpp V3Lexer.yy.cpp V3ParseBison.c +V3ParseLex.o: V3ParseLex.cpp V3Lexer.yy.cpp V3ParseBison.c $(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $< -V3Parse.o: V3Parse.cpp V3ParseBison.c +V3ParseGrammar.o: V3ParseGrammar.cpp V3ParseBison.c + $(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $< + +V3ParseImp.o: V3ParseImp.cpp V3ParseBison.c $(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $< V3PreProc.o: V3PreProc.cpp V3PreLex.yy.cpp diff --git a/src/V3Ast.h b/src/V3Ast.h index c4ab329ce..56ffa86b3 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1152,7 +1152,7 @@ public: // op3 = Statements/Ports/Vars 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 addStmtsp(AstNode* nodep) { addNOp3p(nodep); } void taskPublic(bool flag) { m_taskPublic=flag; } bool taskPublic() const { return m_taskPublic; } }; diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 8c2b002f4..b137e98e2 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -731,7 +731,7 @@ public: 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); } + void addStmtp(AstNode* nodep) { addNOp1p(nodep); } bool unnamed() const { return m_unnamed; } }; @@ -804,7 +804,7 @@ public: ASTNODE_NODE_FUNCS(Func, FUNC) // op1 = Range output variable (functions only) AstNode* fvarp() const { return op1p()->castNode(); } - void addFvarp(AstNode* nodep) { addOp1p(nodep); } + void addFvarp(AstNode* nodep) { addNOp1p(nodep); } void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; } bool attrIsolateAssign() const { return m_attrIsolateAssign; } }; diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 1aafa9253..4e19c327a 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -35,7 +35,6 @@ #include "V3Global.h" #include "V3Const.h" -#include "V3Read.h" #include "V3Ast.h" #include "V3Width.h" #include "V3Signed.h" diff --git a/src/V3Error.h b/src/V3Error.h index 0b3e7a596..3845e8a0c 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -228,7 +228,7 @@ class FileLine { protected: // User routines should never need to change line numbers // We are storing pointers, so we CAN'T change them after initial reading. - friend class V3Read; + friend class V3ParseImp; friend class V3PreLex; void lineno(int num) { m_lineno = num; } void filename(const string& name) { m_filename = name; } diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 3b546dda2..c7a2274c7 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -37,7 +37,7 @@ #include "V3Global.h" #include "V3LinkCells.h" #include "V3SymTable.h" -#include "V3Read.h" +#include "V3Parse.h" #include "V3Ast.h" #include "V3Graph.h" @@ -169,8 +169,8 @@ private: AstModule* modp = m_mods.findIdUpward(nodep->modName())->castModule(); if (!modp) { // Read-subfile - V3Read reader (v3Global.rootp()); - reader.readFile(nodep->fileline(), nodep->modName(), false); + V3Parse parser (v3Global.rootp()); + parser.parseFile(nodep->fileline(), nodep->modName(), false); V3Error::abortIfErrors(); // We've read new modules, grab new pointers to their names readModNames(); @@ -200,7 +200,7 @@ private: if (nodep->modp() && pinStar) { // Note what pins exist UINFO(9," CELL .* connect "<pinsp(); pinp; pinp=pinp->nextp()->castPin()) { if (pinp->name()=="") pinp->v3error("Connect by position is illegal in .* connected cells"); if (!ports.findIdFlat(pinp->name())) { @@ -254,6 +254,7 @@ private: m_mods.insert(nodep->name(), nodep); } } + //if (debug()>=9) m_mods.dump(cout, "-syms: "); } public: diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 1b5d83ca0..0e89b2c76 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -39,7 +39,6 @@ #include "V3Global.h" #include "V3Param.h" -#include "V3Read.h" #include "V3Ast.h" #include "V3Case.h" #include "V3Const.h" diff --git a/src/V3Parse.h b/src/V3Parse.h new file mode 100644 index 000000000..658b32176 --- /dev/null +++ b/src/V3Parse.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +//************************************************************************* +// DESCRIPTION: Verilator: Reading of Verilog files +// +// Code available from: http://www.veripool.org/verilator +// +// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli +// +//************************************************************************* +// +// Copyright 2003-2009 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. +// +// Verilator is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +//************************************************************************* + +#ifndef _V3PARSE_H_ +#define _V3PARSE_H_ 1 +#include "config_build.h" +#include "verilatedos.h" +#include "V3Error.h" +#include "V3Global.h" + +class AstNetlist; +class V3ParseImp; + +//============================================================================ + +class V3Parse { +private: + V3ParseImp* m_impp; + +public: + // CONSTRUCTORS + // We must allow reading multiple files into one parser + V3Parse(AstNetlist* rootp); + ~V3Parse(); + + // METHODS + // Preprocess and read the Verilog file specified into the netlist database + void parseFile(FileLine* fileline, const string& modname, bool inLibrary); + + // Push preprocessed text to the lexer + static void ppPushText(V3ParseImp* impp, const string& text); +}; + +#endif // Guard diff --git a/src/V3Parse.cpp b/src/V3ParseGrammar.cpp similarity index 100% rename from src/V3Parse.cpp rename to src/V3ParseGrammar.cpp diff --git a/src/V3Read.cpp b/src/V3ParseImp.cpp similarity index 63% rename from src/V3Read.cpp rename to src/V3ParseImp.cpp index 97199c577..a0bcbe93b 100644 --- a/src/V3Read.cpp +++ b/src/V3ParseImp.cpp @@ -18,6 +18,14 @@ // GNU General Public License for more details. // //************************************************************************* +// Overview of files involved in parsing +// V3Parse.h External consumer interface to V3ParseImp +// V3ParseImp Internals to parser, common to across flex & bison +// V3ParseGrammar Wrapper that includes V3ParseBison +// V3ParseBison Bison output +// V3ParseLex Wrapper that includes lex output +// V3Lexer.yy.cpp Flex output +//************************************************************************* #include "config_build.h" #include "verilatedos.h" @@ -30,55 +38,18 @@ #include "V3Global.h" #include "V3Ast.h" #include "V3File.h" -#include "V3Read.h" +#include "V3ParseImp.h" #include "V3PreShell.h" -//====================================================================== -// Build in LEX script - -#define yyFlexLexer V3LexerBase -#include "V3Lexer.yy.cpp" -#undef yyFlexLexer - -//YYSTYPE yylval; - //====================================================================== // Globals -V3Read* V3Read::s_readp = NULL; - -extern bool yyparse(); -extern int yydebug; - -//###################################################################### -// Lex-derived class - -/// Override the base lexer class so we can add some access functions -class V3Lexer : public V3LexerBase { -public: - // CONSTRUCTORS - V3Lexer() : V3LexerBase(NULL) {} - ~V3Lexer() {} - // METHODS - void stateExitPsl() { - if (YY_START != PSL) yyerrorf("Internal error: Exiting PSL state when not in PSL state"); - yy_pop_state(); - } - void statePushVlg() { - yy_push_state(STATE_VERILOG_RECENT); - } - void statePop() { - yy_pop_state(); - } -}; -void V3Read::stateExitPsl() { s_readp->m_lexerp->stateExitPsl(); } -void V3Read::statePushVlg() { s_readp->m_lexerp->stateExitPsl(); } -void V3Read::statePop() { s_readp->m_lexerp->statePop(); } +V3ParseImp* V3ParseImp::s_parsep = NULL; //###################################################################### // Read class functions -V3Read::~V3Read() { +V3ParseImp::~V3ParseImp() { for (deque::iterator it = m_stringps.begin(); it != m_stringps.end(); ++it) { delete (*it); } @@ -87,11 +58,11 @@ V3Read::~V3Read() { delete (*it); } m_numberps.clear(); - if (m_lexerp) { delete m_lexerp; m_lexerp = NULL; } + lexDestroy(); parserClear(); } -int V3Read::ppInputToLex(char* buf, int max_size) { +int V3ParseImp::ppInputToLex(char* buf, int max_size) { int got = 0; while (got < max_size // Haven't got enough && !m_ppBuffers.empty()) { // And something buffered @@ -114,7 +85,7 @@ int V3Read::ppInputToLex(char* buf, int max_size) { return got; } -void V3Read::readFile(FileLine* fileline, const string& modfilename, bool inLibrary) { +void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool inLibrary) { string modname = V3Options::filenameNonExt(modfilename); UINFO(2,__FUNCTION__<<": "<warnResetDefault(); // Reenable warnings on each file - if (m_lexerp) delete m_lexerp; // Restart from clean slate. - m_lexerp = new V3Lexer(); - // if (debug()) { m_lexerp->set_debug(~0); } - // if (debug()) yydebug = 1; - UINFO(4,"Lexing Done "<warnResetDefault(); // Reenable warnings on each file + lexDestroy(); // Restart from clean slate. + lexNew(debugFlex()>=9); // Lex it - if (yyparse()) v3fatal("Cannot continue\n"); + if (bisonParse()) v3fatal("Cannot continue\n"); } //====================================================================== -// Lex accessors +// V3Parse functions -bool V3Read::optPsl() { - return v3Global.opt.psl(); +V3Parse::V3Parse(AstNetlist* rootp) { + m_impp = new V3ParseImp (rootp); } -bool V3Read::optFuture(const string& flag) { - return v3Global.opt.isFuture(flag); +V3Parse::~V3Parse() { + delete m_impp; m_impp = NULL; } - -//====================================================================== -// Lex internal functions - -int V3Read::yylexThis() { - int token = m_lexerp->yylex(); - // Match verilog-perl names - if (token == yaID__LEX) { token = yaID__ETC; } - UINFO(5,m_fileline<<" TOKEN="<parseFile(fileline, modname, inLibrary); +} +void V3Parse::ppPushText(V3ParseImp* impp, const string& text) { + impp->ppPushText(text); } diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h new file mode 100644 index 000000000..32598df8d --- /dev/null +++ b/src/V3ParseImp.h @@ -0,0 +1,198 @@ +// -*- C++ -*- +//************************************************************************* +// DESCRIPTION: Verilator: Common header between parser and lex +// +// Code available from: http://www.veripool.org/verilator +// +// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli +// +//************************************************************************* +// +// Copyright 2009-2009 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. +// +// Verilator is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +//************************************************************************* + +#ifndef _V3PARSEIMP_H_ +#define _V3PARSEIMP_H_ 1 +#include "config_build.h" +#include "verilatedos.h" +#include "V3Error.h" +#include "V3Global.h" +#include "V3Parse.h" +#include "V3SymTable.h" +#include + +class V3Lexer; + +// IMPORTANT: Don't include this file other than in the bison and flex, +// as it's definitions will confuse other parsers + +//====================================================================== +// Types (between parser & lexer) + +typedef enum { uniq_NONE, uniq_UNIQUE, uniq_PRIORITY } V3UniqState; + +//============================================================================ +// We can't use bison's %union as we want to pass the fileline with all tokens + +struct V3ParseBisonYYSType { + FileLine* fl; + union { + V3Number* nump; + string* strp; + int cint; + double cdouble; + V3UniqState uniqstate; + + AstNode* nodep; + + AstBegin* beginp; + AstCase* casep; + AstCaseItem* caseitemp; + AstConst* constp; + AstFunc* funcp; + AstModule* modulep; + AstNodeSenItem* senitemp; + AstNodeVarRef* varnodep; + AstParseRef* parserefp; + AstPin* pinp; + AstRange* rangep; + AstSenTree* sentreep; + AstTask* taskp; + AstVar* varp; + }; +}; + +#define YYSTYPE V3ParseBisonYYSType + +//###################################################################### + +class V3ParseImp { + // MEMBERS + AstNetlist* m_rootp; // Root of the design + V3Lexer* m_lexerp; // Current FlexLexer + static V3ParseImp* s_parsep; // Current THIS, bison() isn't class based + FileLine* m_fileline; // Filename/linenumber currently active + + bool m_inCellDefine; // Inside a `celldefine + bool m_inLibrary; // Currently reading a library vs. regular file + int m_inBeginKwd; // Inside a `begin_keywords + int m_lastVerilogState; // Last LEX state in `begin_keywords + + deque m_stringps; // Created strings for later cleanup + deque m_numberps; // Created numbers for later cleanup + deque m_lintState; // Current lint state for save/restore + deque m_ppBuffers; // Preprocessor->lex buffer of characters to process + +public: + // Note these are an exception to using the filename as the debug type + static int debugBison() { + static int level = -1; + if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel("bison"); + return level; + } + static int debugFlex() { + static int level = -1; + if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel("flex"); + return level; + } + static int debug() { return debugBison() ? debugFlex() : 0; } + + // Functions called by lex rules: + int yylexThis(); + static bool optPsl() { return v3Global.opt.psl(); } + static bool optFuture(const string& flag) { return v3Global.opt.isFuture(flag); } + + void ppline (const char* text); + void incLineno() { fileline()->incLineno(); } + void verilatorCmtLint(const char* text, bool on); + void verilatorCmtLintSave(); + void verilatorCmtLintRestore(); + void verilatorCmtBad(const char* text); + void pushBeginKeywords(int state) { m_inBeginKwd++; m_lastVerilogState=state; } + bool popBeginKeywords() { if (m_inBeginKwd) { m_inBeginKwd--; return true; } else return false; } + int lastVerilogState() { return m_lastVerilogState; } + static const char* tokenName(int tok); + + void ppPushText(const string& text) { m_ppBuffers.push_back(text); } + int ppInputToLex(char* buf, int max_size); + + static V3ParseImp* parsep() { return s_parsep; } + + // TODO: Many of these functions are the old interface; they'd be better as non-static + // and called as READP->newString(...) etc. + string* newString(const string& text) { + // Allocate a string, remembering it so we can reclaim storage at lex end + string* strp = new string (text); + m_stringps.push_back(strp); + return strp; + } + string* newString(const char* text) { + // Allocate a string, remembering it so we can reclaim storage at lex end + string* strp = new string (text); + m_stringps.push_back(strp); + return strp; + } + string* newString(const char* text, int length) { + string* strp = new string (text, length); + m_stringps.push_back(strp); + return strp; + } + V3Number* newNumber(FileLine* fl, const char* text) { + V3Number* nump = new V3Number (fl, text); + m_numberps.push_back(nump); + return nump; + } + + // Return next token, for bison, since bison isn't class based, use a global THIS + FileLine* fileline() { return m_fileline; } + AstNetlist* rootp() { return m_rootp; } + FileLine* copyOrSameFileLine() { return fileline()->copyOrSameFileLine(); } + bool inCellDefine() { return m_inCellDefine; } + void inCellDefine(bool flag) { m_inCellDefine = flag; } + bool inLibrary() { return m_inLibrary; } + + // Interactions with parser + int bisonParse(); + + // Interactions with lexer + void lexNew(int debug); + void lexDestroy(); + void stateExitPsl(); // Parser -> lexer communication + void statePushVlg(); // Parser -> lexer communication + void statePop(); // Parser -> lexer communication + int stateVerilogRecent(); // Parser -> lexer communication + int flexPpInputToLex(char* buf, int max_size) { return ppInputToLex(buf,max_size); } + +public: + // CREATORS + V3ParseImp(AstNetlist* rootp) { + m_rootp = rootp; m_lexerp = NULL; + m_inCellDefine = false; + m_inLibrary = false; + m_inBeginKwd = 0; + m_lastVerilogState = stateVerilogRecent(); + } + ~V3ParseImp(); + void parserClear(); + + // METHODS + // Preprocess and read the Verilog file specified into the netlist database + int lexToBison(); // Pass token to bison + + void parseFile(FileLine* fileline, const string& modfilename, bool inLibrary); + +private: + void lexFile(const string& modname); + int lexToken(); // Internal; called from lexToBison +}; + +#endif // Guard diff --git a/src/V3ParseLex.cpp b/src/V3ParseLex.cpp new file mode 100644 index 000000000..859c59c7d --- /dev/null +++ b/src/V3ParseLex.cpp @@ -0,0 +1,78 @@ +//************************************************************************* +// DESCRIPTION: Verilator: Netlist (top level) functions +// +// Code available from: http://www.veripool.org/verilator +// +// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli +// +//************************************************************************* +// +// Copyright 2003-2009 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. +// +// Verilator is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +//************************************************************************* + +#include "config_build.h" +#include "verilatedos.h" +#include +#include +#include +#include + +#include "V3Error.h" +#include "V3Global.h" +#include "V3File.h" +#include "V3ParseImp.h" + +//====================================================================== +// Build in LEX script + +#define yyFlexLexer V3LexerBase +#include "V3Lexer.yy.cpp" +#undef yyFlexLexer + +//###################################################################### +// Lex-derived class + +/// Override the base lexer class so we can add some access functions +class V3Lexer : public V3LexerBase { +public: + // CONSTRUCTORS + V3Lexer() : V3LexerBase(NULL) {} + ~V3Lexer() {} + // METHODS + void stateExitPsl() { + if (YY_START != PSL) yyerrorf("Internal error: Exiting PSL state when not in PSL state"); + yy_pop_state(); + } + void statePushVlg() { + yy_push_state(STATE_VERILOG_RECENT); + } + void statePop() { + yy_pop_state(); + } +}; +void V3ParseImp::stateExitPsl() { parsep()->m_lexerp->stateExitPsl(); } +void V3ParseImp::statePushVlg() { parsep()->m_lexerp->stateExitPsl(); } +void V3ParseImp::statePop() { parsep()->m_lexerp->statePop(); } +int V3ParseImp::yylexThis() { parsep()->m_lexerp->yylex(); } + +//###################################################################### +// Read class functions + +void V3ParseImp::lexNew(int debug) { + if (m_lexerp) delete m_lexerp; // Restart from clean slate. + m_lexerp = new V3Lexer(); + if (debugFlex()>=9) { m_lexerp->set_debug(~0); } +} + +void V3ParseImp::lexDestroy() { + if (m_lexerp) { delete m_lexerp; m_lexerp = NULL; } +} diff --git a/src/V3PreShell.cpp b/src/V3PreShell.cpp index 082f315a4..3db6acaf5 100644 --- a/src/V3PreShell.cpp +++ b/src/V3PreShell.cpp @@ -33,7 +33,7 @@ #include "V3PreShell.h" #include "V3PreProc.h" #include "V3File.h" -#include "V3Read.h" +#include "V3Parse.h" //###################################################################### @@ -69,7 +69,7 @@ protected: } } - void preproc (FileLine* fl, const string& modname, V3Read* readerp) { + void preproc (FileLine* fl, const string& modname, V3ParseImp* parsep) { // Preprocess the given module, putting output in vppFilename UINFONL(1," Preprocessing "<isEof()) { string line = s_preprocp->getline(); - readerp->ppPushText(line); + V3Parse::ppPushText(parsep, line); } } @@ -111,8 +111,8 @@ V3PreProc* V3PreShellImp::s_preprocp = NULL; void V3PreShell::boot(char** env) { V3PreShellImp::s_preImp.boot(env); } -void V3PreShell::preproc(FileLine* fl, const string& modname, V3Read* readerp) { - V3PreShellImp::s_preImp.preproc(fl, modname, readerp); +void V3PreShell::preproc(FileLine* fl, const string& modname, V3ParseImp* parsep) { + V3PreShellImp::s_preImp.preproc(fl, modname, parsep); } void V3PreShell::preprocInclude(FileLine* fl, const string& modname) { V3PreShellImp::s_preImp.preprocInclude(fl, modname); diff --git a/src/V3PreShell.h b/src/V3PreShell.h index 726fd3d54..14bdd4279 100644 --- a/src/V3PreShell.h +++ b/src/V3PreShell.h @@ -27,7 +27,7 @@ #include "verilatedos.h" #include "V3Error.h" -class V3Read; +class V3ParseImp; //============================================================================ @@ -35,7 +35,7 @@ class V3PreShell { // Static class for calling preprocessor public: static void boot(char** env); - static void preproc(FileLine* fileline, const string& module, V3Read* readerp); + static void preproc(FileLine* fileline, const string& module, V3ParseImp* parsep); static void preprocInclude(FileLine* fileline, const string& module); static string dependFiles() { return ""; } // Perl only static void define(const string& name, const string& value); diff --git a/src/V3Read.h b/src/V3Read.h deleted file mode 100644 index 98f2c89fe..000000000 --- a/src/V3Read.h +++ /dev/null @@ -1,139 +0,0 @@ -// -*- C++ -*- -//************************************************************************* -// DESCRIPTION: Verilator: Reading of Verilog files -// -// Code available from: http://www.veripool.org/verilator -// -// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli -// -//************************************************************************* -// -// Copyright 2003-2009 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. -// -// Verilator is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -//************************************************************************* - -#ifndef _V3READ_H_ -#define _V3READ_H_ 1 -#include "config_build.h" -#include "verilatedos.h" -#include "V3Error.h" -#include - -class AstNetlist; -class V3Lexer; -class V3Number; -class AstNode; - -//====================================================================== -// Types (between parser & lexer) - -typedef enum { uniq_NONE, uniq_UNIQUE, uniq_PRIORITY } V3UniqState; - -//============================================================================ - -class V3Read { - AstNetlist* m_rootp; // Root of the design - V3Lexer* m_lexerp; // Current FlexLexer - static V3Read* s_readp; // Current THIS, bison() isn't class based - FileLine* m_fileline; // Filename/linenumber currently active - bool m_inCellDefine; // Inside a `celldefine - bool m_inLibrary; // Currently reading a library vs. regular file - int m_inBeginKwd; // Inside a `begin_keywords - int m_lastVerilogState; // Last LEX state in `begin_keywords - deque m_stringps; // Created strings for later cleanup - deque m_numberps; // Created numbers for later cleanup - deque m_lintState; // Current lint state for save/restore - deque m_ppBuffers; // Preprocessor->lex buffer of characters to process - - // Options isn't visible, so not using debugSrcLevel - //int debug() { return 9; } - -protected: - // Functions called by lex rules: - friend class V3Lexer; - friend class V3LexerBase; - friend class FileLine; - friend class V3PreShellImp; - int yylexThis(); - static bool optPsl(); - static bool optFuture(const string& flag); - static void ppline (const char* text); - static void incLineno() { s_readp->fileline()->incLineno(); } - static void verilatorCmtLint(const char* text, bool on); - static void verilatorCmtLintSave(); - static void verilatorCmtLintRestore(); - static void verilatorCmtBad(const char* text); - static void pushBeginKeywords(int state) { s_readp->m_inBeginKwd++; s_readp->m_lastVerilogState=state; } - static bool popBeginKeywords() { if (s_readp->m_inBeginKwd) { s_readp->m_inBeginKwd--; return true; } else return false; } - static int lastVerilogState() { return s_readp->m_lastVerilogState; } - - void ppPushText(const string& text) { m_ppBuffers.push_back(text); } - int ppInputToLex(char* buf, int max_size); - -public: // But for internal use only - static string* newString(const string& text) { - // Allocate a string, remembering it so we can reclaim storage at lex end - string* strp = new string (text); - s_readp->m_stringps.push_back(strp); - return strp; - } - static string* newString(const char* text) { - // Allocate a string, remembering it so we can reclaim storage at lex end - string* strp = new string (text); - s_readp->m_stringps.push_back(strp); - return strp; - } - static string* newString(const char* text, int length) { - string* strp = new string (text, length); - s_readp->m_stringps.push_back(strp); - return strp; - } - static V3Number* newNumber(FileLine* fl, const char* text) { - V3Number* nump = new V3Number (fl, text); - s_readp->m_numberps.push_back(nump); - return nump; - } - - // Return next token, for bison, since bison isn't class based, use a global THIS - static int yylex() { return s_readp->yylexThis(); } - static FileLine* fileline() { return s_readp->m_fileline; } - static AstNetlist* rootp() { return s_readp->m_rootp; } - static FileLine* copyOrSameFileLine() { return s_readp->fileline()->copyOrSameFileLine(); } - static bool inCellDefine() { return s_readp->m_inCellDefine; } - static void inCellDefine(bool flag) { s_readp->m_inCellDefine = flag; } - static bool inLibrary() { return s_readp->m_inLibrary; } - static void stateExitPsl(); // Parser -> lexer communication - static void statePushVlg(); // Parser -> lexer communication - static void statePop(); // Parser -> lexer communication - static int stateVerilogRecent(); // Parser -> lexer communication - static int flexPpInputToLex(char* buf, int max_size) { return s_readp->ppInputToLex(buf,max_size); } - -public: - // CREATORS - V3Read(AstNetlist* rootp) { - m_rootp = rootp; m_lexerp = NULL; - m_inCellDefine = false; - m_inLibrary = false; - m_inBeginKwd = 0; - m_lastVerilogState = stateVerilogRecent(); - } - ~V3Read(); - void parserClear(); - - // METHODS - // Preprocess and read the Verilog file specified into the netlist database - void readFile(FileLine* fileline, const string& modname, bool inLibrary); - -private: - void lexFile(const string& modname); -}; - -#endif // Guard diff --git a/src/V3Simulate.h b/src/V3Simulate.h index 8cbed7e39..97e5eae88 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -44,6 +44,8 @@ #include "V3Ast.h" #include "V3Width.h" +#include + //============================================================================ //###################################################################### diff --git a/src/Verilator.cpp b/src/Verilator.cpp index e1c46a38d..2aa8c7657 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -68,9 +68,9 @@ #include "V3Name.h" #include "V3Order.h" #include "V3Param.h" +#include "V3Parse.h" #include "V3PreShell.h" #include "V3Premit.h" -#include "V3Read.h" #include "V3Scope.h" #include "V3Signed.h" #include "V3Split.h" @@ -92,12 +92,12 @@ V3Global v3Global; // V3 Class -- top level void V3Global::readFiles() { - V3Read reader (m_rootp); + V3Parse parser (v3Global.rootp()); // Read top module for (V3StringList::const_iterator it = v3Global.opt.vFiles().begin(); it != v3Global.opt.vFiles().end(); ++it) { string filename = *it; - reader.readFile(new FileLine("CommandLine",0), filename, false); + parser.parseFile(new FileLine("CommandLine",0), filename, false); } // Read libraries @@ -106,16 +106,21 @@ void V3Global::readFiles() { for (V3StringSet::const_iterator it = v3Global.opt.libraryFiles().begin(); it != v3Global.opt.libraryFiles().end(); ++it) { string filename = *it; - reader.readFile(new FileLine("CommandLine",0), filename, true); + parser.parseFile(new FileLine("CommandLine",0), filename, true); } + //v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("parse.tree")); V3Error::abortIfErrors(); + + if (!v3Global.opt.preprocOnly()) { + // Resolve all modules cells refer to + V3LinkCells::link(v3Global.rootp()); + } } //###################################################################### void process () { - // Resolve all modules cells refer to - V3LinkCells::link(v3Global.rootp()); + // Sort modules by level so later algorithms don't need to care V3LinkLevel::modSortByLevel(); v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("cells.tree")); V3Error::abortIfErrors(); @@ -566,7 +571,6 @@ int main(int argc, char** argv, char** env) { // Read first filename v3Global.readFiles(); - //v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("parse.tree")); // Link, etc, if needed if (!v3Global.opt.preprocOnly()) { diff --git a/src/verilog.l b/src/verilog.l index c94273e6a..9acf119fe 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -25,8 +25,8 @@ #include #include #include -#include "V3Read.h" #include "V3Number.h" +#include "V3ParseImp.h" // Defines YYTYPE; before including bison header #include "V3ParseBison.h" // Generated by bison extern void yyerror(const char*); @@ -34,52 +34,55 @@ extern void yyerrorf(const char* format, ...); #define STATE_VERILOG_RECENT S05 // State name for most recent Verilog Version +#define PARSEP V3ParseImp::parsep() + + #define YY_INPUT(buf,result,max_size) \ - result = V3Read::flexPpInputToLex(buf,max_size); + result = PARSEP->flexPpInputToLex(buf,max_size); //====================================================================== -#define NEXTLINE() {V3Read::incLineno();} -#define CRELINE() (V3Read::copyOrSameFileLine()) +#define NEXTLINE() {PARSEP->incLineno();} +#define CRELINE() (PARSEP->copyOrSameFileLine()) -#define FL { yylval.fileline = CRELINE(); } +#define FL { yylval.fl = CRELINE(); } #define RETURN_BBOX_SYS_OR_MSG(msg,yytext) { \ if (v3Global.opt.bboxSys()) return yD_aIGNORE; \ else yyerrorf(msg,yytext); } -void V3Read::ppline (const char* textp) { +void V3ParseImp::ppline (const char* textp) { // Handle `line directive fileline()->lineDirective(textp); } -void V3Read::verilatorCmtLint(const char* textp, bool warnOff) { +void V3ParseImp::verilatorCmtLint(const char* textp, bool warnOff) { const char* sp = textp; while (*sp && !isspace(*sp)) sp++; while (*sp && isspace(*sp)) sp++; while (*sp && !isspace(*sp)) sp++; while (*sp && isspace(*sp)) sp++; string msg = sp; string::size_type pos; if ((pos=msg.find("*")) != string::npos) { msg.erase(pos); } - if (!(V3Read::fileline()->warnOff(msg, warnOff))) { - if (!V3Read::optFuture(msg)) { + if (!(PARSEP->fileline()->warnOff(msg, warnOff))) { + if (!PARSEP->optFuture(msg)) { yyerrorf("Unknown verilator lint message code: %s, in %s",msg.c_str(), textp); } } } -void V3Read::verilatorCmtLintSave() { - s_readp->m_lintState.push_back(*V3Read::fileline()); +void V3ParseImp::verilatorCmtLintSave() { + m_lintState.push_back(*PARSEP->fileline()); } -void V3Read::verilatorCmtLintRestore() { - if (s_readp->m_lintState.empty()) { +void V3ParseImp::verilatorCmtLintRestore() { + if (m_lintState.empty()) { yyerrorf("/*verilator lint_restore*/ without matching save."); return; } - V3Read::fileline()->warnStateFrom(s_readp->m_lintState.back()); - s_readp->m_lintState.pop_back(); + PARSEP->fileline()->warnStateFrom(m_lintState.back()); + m_lintState.pop_back(); } -void V3Read::verilatorCmtBad(const char* textp) { +void V3ParseImp::verilatorCmtBad(const char* textp) { string cmtparse = textp; if (cmtparse.substr(0,strlen("/*verilator")) == "/*verilator") { cmtparse.replace(0,strlen("/*verilator"), ""); @@ -91,20 +94,20 @@ void V3Read::verilatorCmtBad(const char* textp) { for (int i=0; isalnum(cmtparse[i]); i++) { cmtname += cmtparse[i]; } - if (!V3Read::optFuture(cmtname)) { + if (!PARSEP->optFuture(cmtname)) { yyerrorf("Unknown verilator comment: %s",textp); } } // See V3Read.cpp -//void V3Read::stateExitPsl() { BEGIN VLG; } -//void V3Read::statePushVlg() { yy_push_state(VLG); } -//void V3Read::statePop() { yy_pop_state(); } +//void V3ParseImp::stateExitPsl() { BEGIN VLG; } +//void V3ParseImp::statePushVlg() { yy_push_state(VLG); } +//void V3ParseImp::statePop() { yy_pop_state(); } //====================================================================== void yyerror(const char* errmsg) { - V3Read::fileline()->v3error(errmsg); + PARSEP->fileline()->v3error(errmsg); } void yyerrorf(const char* format, ...) { @@ -577,16 +580,16 @@ escid \\[^ \t\f\r\n]+ "/*verilator public_module*/" { FL; return yVL_PUBLIC_MODULE; } "/*verilator sc_clock*/" { FL; return yVL_CLOCK; } "/*verilator systemc_clock*/" { FL; return yVL_CLOCK; } - "/*verilator tracing_off*/" {V3Read::fileline()->tracingOn(false); } - "/*verilator tracing_on*/" {V3Read::fileline()->tracingOn(true); } - "/*verilator coverage_off*/" {V3Read::fileline()->coverageOn(false); } - "/*verilator coverage_on*/" {V3Read::fileline()->coverageOn(true); } - "/*verilator lint_off"[^*]*"*/" {V3Read::verilatorCmtLint(yytext, true); } - "/*verilator lint_on"[^*]*"*/" {V3Read::verilatorCmtLint(yytext, false); } - "/*verilator lint_restore*/" {V3Read::verilatorCmtLintRestore(); } - "/*verilator lint_save*/" {V3Read::verilatorCmtLintSave(); } + "/*verilator tracing_off*/" {PARSEP->fileline()->tracingOn(false); } + "/*verilator tracing_on*/" {PARSEP->fileline()->tracingOn(true); } + "/*verilator coverage_off*/" {PARSEP->fileline()->coverageOn(false); } + "/*verilator coverage_on*/" {PARSEP->fileline()->coverageOn(true); } + "/*verilator lint_off"[^*]*"*/" {PARSEP->verilatorCmtLint(yytext, true); } + "/*verilator lint_on"[^*]*"*/" {PARSEP->verilatorCmtLint(yytext, false); } + "/*verilator lint_restore*/" {PARSEP->verilatorCmtLintRestore(); } + "/*verilator lint_save*/" {PARSEP->verilatorCmtLintSave(); } - "/*"[^*]*"*/" {V3Read::verilatorCmtBad(yytext); } + "/*"[^*]*"*/" {PARSEP->verilatorCmtBad(yytext); } } /************************************************************************/ @@ -710,41 +713,41 @@ escid \\[^ \t\f\r\n]+ /* Identifiers and numbers */ { - {escid} { FL; yylval.strp = V3Read::newString + {escid} { FL; yylval.strp = PARSEP->newString (AstNode::encodeName(string(yytext+1))); // +1 to skip the backslash return yaID__LEX; } - {id} { FL; yylval.strp = V3Read::newString(AstNode::encodeName(string(yytext))); + {id} { FL; yylval.strp = PARSEP->newString(AstNode::encodeName(string(yytext))); return yaID__LEX; } - \"[^\"\\]*\" { FL; yylval.strp = V3Read::newString(yytext+1,yyleng-2); + \"[^\"\\]*\" { FL; yylval.strp = PARSEP->newString(yytext+1,yyleng-2); return yaSTRING; } \" { yy_push_state(STRING); yymore(); } [0-9]*?['']s?[bcodhBCODH][ \t]*[A-Fa-f0-9xXzZ_?]* { - FL; yylval.nump = V3Read::newNumber(V3Read::fileline(),(char*)yytext); + FL; yylval.nump = PARSEP->newNumber(PARSEP->fileline(),(char*)yytext); return yaINTNUM; } [0-9]*?['']s?[01xXzZ] { /* SystemVerilog */ - FL; yylval.nump = V3Read::newNumber(V3Read::fileline(),(char*)yytext); + FL; yylval.nump = PARSEP->newNumber(PARSEP->fileline(),(char*)yytext); return yaINTNUM; } /* Note below is constructed to not match the ' that begins a '( or '{ */ [0-9][_0-9]*[ \t]*['']s?[bcodhBCODH]?[ \t]*[A-Fa-f0-9xXzZ_?]+ { - FL; yylval.nump = V3Read::newNumber(V3Read::fileline(),(char*)yytext); + FL; yylval.nump = PARSEP->newNumber(PARSEP->fileline(),(char*)yytext); return yaINTNUM; } [0-9][_0-9]*[ \t]*['']s?[bcodhBCODH] { - FL; yylval.nump = V3Read::newNumber(V3Read::fileline(),(char*)yytext); + FL; yylval.nump = PARSEP->newNumber(PARSEP->fileline(),(char*)yytext); return yaINTNUM; } [0-9][_0-9]*[ \t]*['']s { - FL; yylval.nump = V3Read::newNumber(V3Read::fileline(),(char*)yytext); + FL; yylval.nump = PARSEP->newNumber(PARSEP->fileline(),(char*)yytext); return yaINTNUM; } [0-9][_0-9]* { - FL; yylval.nump = V3Read::newNumber(V3Read::fileline(),(char*)yytext); + FL; yylval.nump = PARSEP->newNumber(PARSEP->fileline(),(char*)yytext); return yaINTNUM; } [0-9][_0-9]*(\.[_0-9]+)([eE][-+]?[_0-9]+)? { @@ -768,7 +771,7 @@ escid \\[^ \t\f\r\n]+ \\{crnl} { yymore(); NEXTLINE(); } \\. { yymore(); } \" { yy_pop_state(); - FL; yylval.strp = V3Read::newString(yytext+1,yyleng-2); + FL; yylval.strp = PARSEP->newString(yytext+1,yyleng-2); return yaSTRING; } . { yymore(); } @@ -793,7 +796,7 @@ escid \\[^ \t\f\r\n]+ { "`accelerate" { } // Verilog-XL compatibility "`autoexpand_vectornets" { } // Verilog-XL compatibility - "`celldefine" { V3Read::inCellDefine(true); } + "`celldefine" { PARSEP->inCellDefine(true); } "`default_decay_time"{ws}+[^\n\r]* { } // Verilog spec - delays only "`default_nettype"{ws}+[a-zA-Z0-9]* { yyerrorf("Unsupported: Verilog 2001 directive not implemented: %s",yytext); } // Verilog 2001 "`delay_mode_distributed" { } // Verilog spec - delays only @@ -802,11 +805,11 @@ escid \\[^ \t\f\r\n]+ "`delay_mode_zero" { } // Verilog spec - delays only "`disable_portfaults" { } // Verilog-XL compatibility "`enable_portfaults" { } // Verilog-XL compatibility - "`endcelldefine" { V3Read::inCellDefine(false); } + "`endcelldefine" { PARSEP->inCellDefine(false); } "`endprotect" { } "`expand_vectornets" { } // Verilog-XL compatibility "`inline" { } - "`line"{ws}+[^\n\r]*{crnl} { V3Read::ppline(yytext); } + "`line"{ws}+[^\n\r]*{crnl} { PARSEP->ppline(yytext); } "`noaccelerate" { } // Verilog-XL compatibility "`noexpand_vectornets" { } // Verilog-XL compatibility "`noremove_gatenames" { } // Verilog-XL compatibility @@ -816,7 +819,7 @@ escid \\[^ \t\f\r\n]+ "`portcoerce" { } "`pragma"{ws}+[^\n\r]* { } // Verilog 2005 "`protect" { } - "`psl" { if (V3Read::optPsl()) { BEGIN PSL; } else { BEGIN IGNORE; } } + "`psl" { if (PARSEP->optPsl()) { BEGIN PSL; } else { BEGIN IGNORE; } } "`remove_gatenames" { } // Verilog-XL compatibility "`remove_netnames" { } // Verilog-XL compatibility "`resetall" { } @@ -824,12 +827,12 @@ escid \\[^ \t\f\r\n]+ "`timescale"{ws}+[^\n\r]* { } // Verilog spec - not supported /* See also setLanguage below */ - "`begin_keywords"[ \t]*\"1364-1995\" { yy_push_state(V95); V3Read::pushBeginKeywords(YY_START); } - "`begin_keywords"[ \t]*\"1364-2001\" { yy_push_state(V01); V3Read::pushBeginKeywords(YY_START); } - "`begin_keywords"[ \t]*\"1364-2001-noconfig\" { yy_push_state(V01); V3Read::pushBeginKeywords(YY_START); } - "`begin_keywords"[ \t]*\"1364-2005\" { yy_push_state(V05); V3Read::pushBeginKeywords(YY_START); } - "`begin_keywords"[ \t]*\"1800-2005\" { yy_push_state(S05); V3Read::pushBeginKeywords(YY_START); } - "`end_keywords" { yy_pop_state(); if (!V3Read::popBeginKeywords()) yyerrorf("`end_keywords when not inside `begin_keywords block"); } + "`begin_keywords"[ \t]*\"1364-1995\" { yy_push_state(V95); PARSEP->pushBeginKeywords(YY_START); } + "`begin_keywords"[ \t]*\"1364-2001\" { yy_push_state(V01); PARSEP->pushBeginKeywords(YY_START); } + "`begin_keywords"[ \t]*\"1364-2001-noconfig\" { yy_push_state(V01); PARSEP->pushBeginKeywords(YY_START); } + "`begin_keywords"[ \t]*\"1364-2005\" { yy_push_state(V05); PARSEP->pushBeginKeywords(YY_START); } + "`begin_keywords"[ \t]*\"1800-2005\" { yy_push_state(S05); PARSEP->pushBeginKeywords(YY_START); } + "`end_keywords" { yy_pop_state(); if (!PARSEP->popBeginKeywords()) yyerrorf("`end_keywords when not inside `begin_keywords block"); } /* Verilator */ "`systemc_ctor" { BEGIN SYSCCTOR; } @@ -838,15 +841,15 @@ escid \\[^ \t\f\r\n]+ "`systemc_imp_header" { BEGIN SYSCIMPH; } "`systemc_implementation" { BEGIN SYSCIMP; } "`systemc_interface" { BEGIN SYSCINT; } - "`verilog" { BEGIN V3Read::lastVerilogState(); } + "`verilog" { BEGIN PARSEP->lastVerilogState(); } } -[ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; NEXTLINE(); yylval.strp = V3Read::newString(yytext); return yaSCHDR; } -[ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; NEXTLINE(); yylval.strp = V3Read::newString(yytext); return yaSCINT; } -[ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; NEXTLINE(); yylval.strp = V3Read::newString(yytext); return yaSCIMP; } -[ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; NEXTLINE(); yylval.strp = V3Read::newString(yytext); return yaSCIMPH; } -[ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; NEXTLINE(); yylval.strp = V3Read::newString(yytext); return yaSCCTOR; } -[ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; NEXTLINE(); yylval.strp = V3Read::newString(yytext); return yaSCDTOR; } +[ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; NEXTLINE(); yylval.strp = PARSEP->newString(yytext); return yaSCHDR; } +[ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; NEXTLINE(); yylval.strp = PARSEP->newString(yytext); return yaSCINT; } +[ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; NEXTLINE(); yylval.strp = PARSEP->newString(yytext); return yaSCIMP; } +[ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; NEXTLINE(); yylval.strp = PARSEP->newString(yytext); return yaSCIMPH; } +[ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; NEXTLINE(); yylval.strp = PARSEP->newString(yytext); return yaSCCTOR; } +[ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; NEXTLINE(); yylval.strp = PARSEP->newString(yytext); return yaSCDTOR; } [ \t]*[^` \t\n\r][^\n\r]*{crnl} { NEXTLINE(); } /* Pick up text-type data */ @@ -867,4 +870,24 @@ escid \\[^ \t\f\r\n]+ /* Catch all - absolutely last */ <*>.|\n { yyerrorf("Missing verilog.l rule: Default rule invoked in state %d: %s", YY_START, yytext); } %% -int V3Read::stateVerilogRecent() { return STATE_VERILOG_RECENT; } +int V3ParseImp::stateVerilogRecent() { return STATE_VERILOG_RECENT; } + +int V3ParseImp::lexToken() { + // called from lexToBison, has a "this" + // yylvalp is global + int token = yylexThis(); + if (token == yaID__LEX) { token = yaID__ETC; } + return token; +} + +int V3ParseImp::lexToBison() { + // Called as global since bison doesn't have our pointer + int tok = lexToken(); + //yylval.scp = NULL; // Symbol table not yet needed - no packages + if (debugFlex()>=6 || debugBison()>=6) { + cout<<" lexToBison TOKEN="< #include -#include "V3Read.h" #include "V3Ast.h" #include "V3Global.h" +#include "V3ParseImp.h" // Defines YYTYPE; before including bison header #define YYERROR_VERBOSE 1 #define YYINITDEPTH 10000 // Older bisons ignore YYMAXDEPTH #define YYMAXDEPTH 10000 // Pick up new lexer -#define yylex V3Read::yylex +#define yylex PARSEP->lexToBison #define PSLUNSUP(what) NULL; yyerrorf("Unsupported: PSL language feature not implemented"); extern void yyerror(const char* errmsg); @@ -44,74 +44,84 @@ extern void yyerrorf(const char* format, ...); //====================================================================== // Statics (for here only) -class V3Parse { +class V3ParseGrammar { public: - static bool s_impliedDecl; // Allow implied wire declarations - static AstVarType s_varDecl; // Type for next signal declaration (reg/wire/etc) - static AstVarType s_varIO; // Type for next signal declaration (input/output/etc) - static bool s_varSigned; // Signed state for next signal declaration - static AstVar* s_varAttrp; // Current variable for attribute adding - static AstCase* s_caseAttrp; // Current case statement for attribute adding - static AstRange* s_varRangep; // Pointer to range for next signal declaration - static int s_pinNum; // Pin number currently parsing - static string s_instModule; // Name of module referenced for instantiations - static AstPin* s_instParamp; // Parameters for instantiations - static int s_uniqueAttr; // Bitmask of unique/priority keywords + bool m_impliedDecl; // Allow implied wire declarations + AstVarType m_varDecl; // Type for next signal declaration (reg/wire/etc) + AstVarType m_varIO; // Type for next signal declaration (input/output/etc) + bool m_varSigned; // Signed state for next signal declaration + AstVar* m_varAttrp; // Current variable for attribute adding + AstCase* m_caseAttrp; // Current case statement for attribute adding + AstRange* m_varRangep; // Pointer to range for next signal declaration + int m_pinNum; // Pin number currently parsing + string m_instModule; // Name of module referenced for instantiations + AstPin* m_instParamp; // Parameters for instantiations + int m_uniqueAttr; // Bitmask of unique/priority keywords - static AstVar* createVariable(FileLine* fileline, string name, AstRange* arrayp, AstNode* attrsp); - static AstNode* createSupplyExpr(FileLine* fileline, string name, int value); - static AstText* createTextQuoted(FileLine* fileline, string text); - static AstDisplay* createDisplayError(FileLine* fileline) { + // CONSTRUCTORS + V3ParseGrammar() { + m_impliedDecl = false; + m_varDecl = AstVarType::UNKNOWN; + m_varIO = AstVarType::UNKNOWN; + m_varSigned = false; + m_varRangep = NULL; + m_pinNum = -1; + m_instModule; + m_instParamp = NULL; + m_varAttrp = NULL; + m_caseAttrp = NULL; + } + static V3ParseGrammar* singletonp() { + static V3ParseGrammar singleton; + return &singleton; + } + + // METHODS + AstVar* createVariable(FileLine* fileline, string name, AstRange* arrayp, AstNode* attrsp); + AstNode* createSupplyExpr(FileLine* fileline, string name, int value); + AstText* createTextQuoted(FileLine* fileline, string text) { + string newtext = deQuote(fileline, text); + return new AstText(fileline, newtext); + } + AstDisplay* createDisplayError(FileLine* fileline) { AstDisplay* nodep = new AstDisplay(fileline,AstDisplayType::ERROR, "", NULL,NULL); nodep->addNext(new AstStop(fileline)); return nodep; } - static void setRange(AstRange* rangep) { - if (s_varRangep) { s_varRangep->deleteTree(); s_varRangep=NULL; } // It was cloned, so this is safe. - s_varRangep = rangep; - } - static string deQuote(FileLine* fileline, string text); -}; - -bool V3Parse::s_impliedDecl = false; -AstVarType V3Parse::s_varDecl = AstVarType::UNKNOWN; -AstVarType V3Parse::s_varIO = AstVarType::UNKNOWN; -bool V3Parse::s_varSigned = false; -AstRange* V3Parse::s_varRangep = NULL; -int V3Parse::s_pinNum = -1; -string V3Parse::s_instModule; -AstPin* V3Parse::s_instParamp = NULL; -AstVar* V3Parse::s_varAttrp = NULL; -AstCase* V3Parse::s_caseAttrp = NULL; - -//====================================================================== -// Utility functions - -static AstNode* newVarInit(FileLine* fileline, AstNode* varp, AstNode* initp) { + AstNode* newVarInit(FileLine* fileline, AstNode* varp, AstNode* initp) { return new AstInitial(fileline, new AstAssign(fileline, new AstVarRef(fileline, varp->name(),true), initp)); -} + } + void setRange(AstRange* rangep) { + if (m_varRangep) { m_varRangep->deleteTree(); m_varRangep=NULL; } // It was cloned, so this is safe. + m_varRangep = rangep; + } + string deQuote(FileLine* fileline, string text); +}; + +#define PARSEP V3ParseImp::parsep() +#define GRAMMARP V3ParseGrammar::singletonp() //====================================================================== // Macro functions -#define CRELINE() (V3Read::copyOrSameFileLine()) +#define CRELINE() (PARSEP->copyOrSameFileLine()) -#define VARRESET_LIST(decl) { V3Parse::s_pinNum=1; VARRESET(); VARDECL(decl); } // Start of pinlist -#define VARRESET_NONLIST(decl) { V3Parse::s_pinNum=0; VARRESET(); VARDECL(decl); } // Not in a pinlist +#define VARRESET_LIST(decl) { GRAMMARP->m_pinNum=1; VARRESET(); VARDECL(decl); } // Start of pinlist +#define VARRESET_NONLIST(decl) { GRAMMARP->m_pinNum=0; VARRESET(); VARDECL(decl); } // Not in a pinlist #define VARRESET() { VARDECL(UNKNOWN); VARIO(UNKNOWN); VARSIGNED(false); VARRANGE(NULL); } -#define VARDECL(type) { V3Parse::s_varDecl = AstVarType::type; } -#define VARIO(type) { V3Parse::s_varIO = AstVarType::type; } -#define VARSIGNED(value) { V3Parse::s_varSigned = value; } -#define VARRANGE(rangep) { V3Parse::setRange(rangep); } +#define VARDECL(type) { GRAMMARP->m_varDecl = AstVarType::type; } +#define VARIO(type) { GRAMMARP->m_varIO = AstVarType::type; } +#define VARSIGNED(value) { GRAMMARP->m_varSigned = value; } +#define VARRANGE(rangep) { GRAMMARP->setRange(rangep); } #define VARTYPE(typep) { VARRANGE(typep); } // Temp until other data types supported -#define VARDONEA(name,array,attrs) V3Parse::createVariable(CRELINE(),(name),(array),(attrs)) -#define VARDONEP(portp,array,attrs) V3Parse::createVariable((portp)->fileline(),(portp)->name(),(array),(attrs)) -#define PINNUMINC() (V3Parse::s_pinNum++) +#define VARDONEA(name,array,attrs) GRAMMARP->createVariable(CRELINE(),(name),(array),(attrs)) +#define VARDONEP(portp,array,attrs) GRAMMARP->createVariable((portp)->fileline(),(portp)->name(),(array),(attrs)) +#define PINNUMINC() (GRAMMARP->m_pinNum++) -#define INSTPREP(modname,paramsp) { V3Parse::s_impliedDecl = true; V3Parse::s_instModule = modname; V3Parse::s_instParamp = paramsp; } +#define INSTPREP(modname,paramsp) { GRAMMARP->m_impliedDecl = true; GRAMMARP->m_instModule = modname; GRAMMARP->m_instParamp = paramsp; } static void ERRSVKWD(FileLine* fileline, const string& tokname) { static int toldonce = 0; @@ -124,30 +134,6 @@ static void ERRSVKWD(FileLine* fileline, const string& tokname) { class AstSenTree; %} -%union { - FileLine* fileline; - V3Number* nump; - string* strp; - int cint; - double cdouble; - V3UniqState uniqstate; - - AstNode* nodep; - - AstCase* casep; - AstCaseItem* caseitemp; - AstConst* constp; - AstFunc* funcp; - AstModule* modulep; - AstNodeVarRef* varnodep; - AstParseRef* parserefp; - AstPin* pinp; - AstRange* rangep; - AstNodeSenItem* senitemp; - AstSenTree* sentreep; - AstVar* varp; -} - // When writing Bison patterns we use yTOKEN instead of "token", // so Bison will error out on unknown "token"s. @@ -170,7 +156,7 @@ class AstSenTree; %token yaSTRING "STRING" %token yaSTRING__IGNORE "STRING-ignored" // Used when expr:string not allowed -%token yaTIMINGSPEC "TIMING SPEC ELEMENT" +%token yaTIMINGSPEC "TIMING SPEC ELEMENT" %token yaSCHDR "`systemc_header BLOCK" %token yaSCINT "`systemc_ctor BLOCK" @@ -179,32 +165,33 @@ class AstSenTree; %token yaSCCTOR "`systemc_implementation BLOCK" %token yaSCDTOR "`systemc_imp_header BLOCK" -%token '!' -%token '#' -%token '%' -%token '&' -%token '(' -%token ')' -%token '*' -%token '+' -%token ',' -%token '-' -%token '.' -%token '/' -%token ':' -%token ';' -%token '<' -%token '=' -%token '>' -%token '?' -%token '@' -%token '[' -%token ']' -%token '^' -%token '{' -%token '|' -%token '}' -%token '~' +// is the fileline, abbreviated to shorten "$1" references +%token '!' +%token '#' +%token '%' +%token '&' +%token '(' +%token ')' +%token '*' +%token '+' +%token ',' +%token '-' +%token '.' +%token '/' +%token ':' +%token ';' +%token '<' +%token '=' +%token '>' +%token '?' +%token '@' +%token '[' +%token ']' +%token '^' +%token '{' +%token '|' +%token '}' +%token '~' // Specific keywords // yKEYWORD means match "keyword" @@ -212,195 +199,195 @@ class AstSenTree; // for example yP_ for punctuation based operators. // Double underscores "yX__Y" means token X followed by Y, // and "yX__ETC" means X folled by everything but Y(s). -%token yALWAYS "always" -%token yAND "and" -%token yASSERT "assert" -%token yASSIGN "assign" -%token yAUTOMATIC "automatic" -%token yBEGIN "begin" -%token yBUF "buf" -%token yBUFIF0 "bufif0" -%token yBUFIF1 "bufif1" -%token yCASE "case" -%token yCASEX "casex" -%token yCASEZ "casez" -%token yCLOCKING "clocking" -%token yCOVER "cover" -%token yDEFAULT "default" -%token yDEFPARAM "defparam" -%token yDISABLE "disable" -%token yDO "do" -%token yELSE "else" -%token yEND "end" -%token yENDCASE "endcase" -%token yENDCLOCKING "endclocking" -%token yENDFUNCTION "endfunction" -%token yENDGENERATE "endgenerate" -%token yENDMODULE "endmodule" -%token yENDPROPERTY "endproperty" -%token yENDSPECIFY "endspecify" -%token yENDTASK "endtask" -%token yFINAL "final" -%token yFOR "for" -%token yFOREVER "forever" -%token yFUNCTION "function" -%token yGENERATE "generate" -%token yGENVAR "genvar" -%token yIF "if" -%token yIFF "iff" -%token yLOGIC "logic" -%token yINITIAL "initial" -%token yINOUT "inout" -%token yINPUT "input" -%token yINTEGER "integer" -%token yLOCALPARAM "localparam" -%token yMODULE "module" -%token yNAND "nand" -%token yNEGEDGE "negedge" -%token yNOR "nor" -%token yNOT "not" -%token yNOTIF0 "notif0" -%token yNOTIF1 "notif1" -%token yOR "or" -%token yOUTPUT "output" -%token yPARAMETER "parameter" -%token yPOSEDGE "posedge" -%token yPRIORITY "priority" -%token yPROPERTY "property" -%token yPULLDOWN "pulldown" -%token yPULLUP "pullup" -%token yREG "reg" -%token yREPEAT "repeat" -%token ySCALARED "scalared" -%token ySIGNED "signed" -%token ySPECIFY "specify" -%token ySPECPARAM "specparam" -%token ySTATIC "static" -%token ySUPPLY0 "supply0" -%token ySUPPLY1 "supply1" -%token yTASK "task" -%token yTIMEPRECISION "timeprecision" -%token yTIMEUNIT "timeunit" -%token yTRI "tri" -%token yTRUE "true" -%token yUNIQUE "unique" -%token yUNSIGNED "unsigned" -%token yVECTORED "vectored" -%token yWHILE "while" -%token yWIRE "wire" -%token yXNOR "xnor" -%token yXOR "xor" +%token yALWAYS "always" +%token yAND "and" +%token yASSERT "assert" +%token yASSIGN "assign" +%token yAUTOMATIC "automatic" +%token yBEGIN "begin" +%token yBUF "buf" +%token yBUFIF0 "bufif0" +%token yBUFIF1 "bufif1" +%token yCASE "case" +%token yCASEX "casex" +%token yCASEZ "casez" +%token yCLOCKING "clocking" +%token yCOVER "cover" +%token yDEFAULT "default" +%token yDEFPARAM "defparam" +%token yDISABLE "disable" +%token yDO "do" +%token yELSE "else" +%token yEND "end" +%token yENDCASE "endcase" +%token yENDCLOCKING "endclocking" +%token yENDFUNCTION "endfunction" +%token yENDGENERATE "endgenerate" +%token yENDMODULE "endmodule" +%token yENDPROPERTY "endproperty" +%token yENDSPECIFY "endspecify" +%token yENDTASK "endtask" +%token yFINAL "final" +%token yFOR "for" +%token yFOREVER "forever" +%token yFUNCTION "function" +%token yGENERATE "generate" +%token yGENVAR "genvar" +%token yIF "if" +%token yIFF "iff" +%token yLOGIC "logic" +%token yINITIAL "initial" +%token yINOUT "inout" +%token yINPUT "input" +%token yINTEGER "integer" +%token yLOCALPARAM "localparam" +%token yMODULE "module" +%token yNAND "nand" +%token yNEGEDGE "negedge" +%token yNOR "nor" +%token yNOT "not" +%token yNOTIF0 "notif0" +%token yNOTIF1 "notif1" +%token yOR "or" +%token yOUTPUT "output" +%token yPARAMETER "parameter" +%token yPOSEDGE "posedge" +%token yPRIORITY "priority" +%token yPROPERTY "property" +%token yPULLDOWN "pulldown" +%token yPULLUP "pullup" +%token yREG "reg" +%token yREPEAT "repeat" +%token ySCALARED "scalared" +%token ySIGNED "signed" +%token ySPECIFY "specify" +%token ySPECPARAM "specparam" +%token ySTATIC "static" +%token ySUPPLY0 "supply0" +%token ySUPPLY1 "supply1" +%token yTASK "task" +%token yTIMEPRECISION "timeprecision" +%token yTIMEUNIT "timeunit" +%token yTRI "tri" +%token yTRUE "true" +%token yUNIQUE "unique" +%token yUNSIGNED "unsigned" +%token yVECTORED "vectored" +%token yWHILE "while" +%token yWIRE "wire" +%token yXNOR "xnor" +%token yXOR "xor" -%token yD_BITS "$bits" -%token yD_C "$c" -%token yD_CLOG2 "$clog2" -%token yD_COUNTONES "$countones" -%token yD_DISPLAY "$display" -%token yD_ERROR "$error" -%token yD_FATAL "$fatal" -%token yD_FCLOSE "$fclose" -%token yD_FDISPLAY "$fdisplay" -%token yD_FEOF "$feof" -%token yD_FFLUSH "$fflush" -%token yD_FGETC "$fgetc" -%token yD_FGETS "$fgets" -%token yD_FINISH "$finish" -%token yD_FOPEN "$fopen" -%token yD_FSCANF "$fscanf" -%token yD_FWRITE "$fwrite" -%token yD_INFO "$info" -%token yD_ISUNKNOWN "$isunknown" -%token yD_ONEHOT "$onehot" -%token yD_ONEHOT0 "$onehot0" -%token yD_RANDOM "$random" -%token yD_READMEMB "$readmemb" -%token yD_READMEMH "$readmemh" -%token yD_SIGNED "$signed" -%token yD_SSCANF "$sscanf" -%token yD_STIME "$stime" -%token yD_STOP "$stop" -%token yD_TIME "$time" -%token yD_UNSIGNED "$unsigned" -%token yD_WARNING "$warning" -%token yD_WRITE "$write" -%token yD_aIGNORE "${ignored-bbox-sys}" +%token yD_BITS "$bits" +%token yD_C "$c" +%token yD_CLOG2 "$clog2" +%token yD_COUNTONES "$countones" +%token yD_DISPLAY "$display" +%token yD_ERROR "$error" +%token yD_FATAL "$fatal" +%token yD_FCLOSE "$fclose" +%token yD_FDISPLAY "$fdisplay" +%token yD_FEOF "$feof" +%token yD_FFLUSH "$fflush" +%token yD_FGETC "$fgetc" +%token yD_FGETS "$fgets" +%token yD_FINISH "$finish" +%token yD_FOPEN "$fopen" +%token yD_FSCANF "$fscanf" +%token yD_FWRITE "$fwrite" +%token yD_INFO "$info" +%token yD_ISUNKNOWN "$isunknown" +%token yD_ONEHOT "$onehot" +%token yD_ONEHOT0 "$onehot0" +%token yD_RANDOM "$random" +%token yD_READMEMB "$readmemb" +%token yD_READMEMH "$readmemh" +%token yD_SIGNED "$signed" +%token yD_SSCANF "$sscanf" +%token yD_STIME "$stime" +%token yD_STOP "$stop" +%token yD_TIME "$time" +%token yD_UNSIGNED "$unsigned" +%token yD_WARNING "$warning" +%token yD_WRITE "$write" +%token yD_aIGNORE "${ignored-bbox-sys}" -%token yPSL "psl" -%token yPSL_ASSERT "PSL assert" -%token yPSL_CLOCK "PSL clock" -%token yPSL_COVER "PSL cover" -%token yPSL_REPORT "PSL report" +%token yPSL "psl" +%token yPSL_ASSERT "PSL assert" +%token yPSL_CLOCK "PSL clock" +%token yPSL_COVER "PSL cover" +%token yPSL_REPORT "PSL report" -%token yVL_CLOCK "/*verilator sc_clock*/" -%token yVL_CLOCK_ENABLE "/*verilator clock_enable*/" -%token yVL_COVERAGE_BLOCK_OFF "/*verilator coverage_block_off*/" -%token yVL_FULL_CASE "/*verilator full_case*/" -%token yVL_INLINE_MODULE "/*verilator inline_module*/" -%token yVL_ISOLATE_ASSIGNMENTS "/*verilator isolate_assignments*/" -%token yVL_NO_INLINE_MODULE "/*verilator no_inline_module*/" -%token yVL_NO_INLINE_TASK "/*verilator no_inline_task*/" -%token yVL_PARALLEL_CASE "/*verilator parallel_case*/" -%token yVL_PUBLIC "/*verilator public*/" -%token yVL_PUBLIC_FLAT "/*verilator public_flat*/" -%token yVL_PUBLIC_MODULE "/*verilator public_module*/" +%token yVL_CLOCK "/*verilator sc_clock*/" +%token yVL_CLOCK_ENABLE "/*verilator clock_enable*/" +%token yVL_COVERAGE_BLOCK_OFF "/*verilator coverage_block_off*/" +%token yVL_FULL_CASE "/*verilator full_case*/" +%token yVL_INLINE_MODULE "/*verilator inline_module*/" +%token yVL_ISOLATE_ASSIGNMENTS "/*verilator isolate_assignments*/" +%token yVL_NO_INLINE_MODULE "/*verilator no_inline_module*/" +%token yVL_NO_INLINE_TASK "/*verilator no_inline_task*/" +%token yVL_PARALLEL_CASE "/*verilator parallel_case*/" +%token yVL_PUBLIC "/*verilator public*/" +%token yVL_PUBLIC_FLAT "/*verilator public_flat*/" +%token yVL_PUBLIC_MODULE "/*verilator public_module*/" -%token yP_TICK "'" -%token yP_TICKBRA "'{" -%token yP_OROR "||" -%token yP_ANDAND "&&" -%token yP_NOR "~|" -%token yP_XNOR "^~" -%token yP_NAND "~&" -%token yP_EQUAL "==" -%token yP_NOTEQUAL "!=" -%token yP_CASEEQUAL "===" -%token yP_CASENOTEQUAL "!==" -%token yP_WILDEQUAL "==?" -%token yP_WILDNOTEQUAL "!=?" -%token yP_GTE ">=" -%token yP_LTE "<=" -%token yP_SLEFT "<<" -%token yP_SRIGHT ">>" -%token yP_SSRIGHT ">>>" -%token yP_POW "**" +%token yP_TICK "'" +%token yP_TICKBRA "'{" +%token yP_OROR "||" +%token yP_ANDAND "&&" +%token yP_NOR "~|" +%token yP_XNOR "^~" +%token yP_NAND "~&" +%token yP_EQUAL "==" +%token yP_NOTEQUAL "!=" +%token yP_CASEEQUAL "===" +%token yP_CASENOTEQUAL "!==" +%token yP_WILDEQUAL "==?" +%token yP_WILDNOTEQUAL "!=?" +%token yP_GTE ">=" +%token yP_LTE "<=" +%token yP_SLEFT "<<" +%token yP_SRIGHT ">>" +%token yP_SSRIGHT ">>>" +%token yP_POW "**" -%token yP_PLUSCOLON "+:" -%token yP_MINUSCOLON "-:" -%token yP_MINUSGT "->" -%token yP_MINUSGTGT "->>" -%token yP_EQGT "=>" -%token yP_ASTGT "*>" -%token yP_ANDANDAND "&&&" -%token yP_POUNDPOUND "##" -%token yP_DOTSTAR ".*" +%token yP_PLUSCOLON "+:" +%token yP_MINUSCOLON "-:" +%token yP_MINUSGT "->" +%token yP_MINUSGTGT "->>" +%token yP_EQGT "=>" +%token yP_ASTGT "*>" +%token yP_ANDANDAND "&&&" +%token yP_POUNDPOUND "##" +%token yP_DOTSTAR ".*" -%token yP_ATAT "@@" -%token yP_COLONCOLON "::" -%token yP_COLONEQ ":=" -%token yP_COLONDIV ":/" -%token yP_ORMINUSGT "|->" -%token yP_OREQGT "|=>" -%token yP_BRASTAR "[*" -%token yP_BRAEQ "[=" -%token yP_BRAMINUSGT "[->" +%token yP_ATAT "@@" +%token yP_COLONCOLON "::" +%token yP_COLONEQ ":=" +%token yP_COLONDIV ":/" +%token yP_ORMINUSGT "|->" +%token yP_OREQGT "|=>" +%token yP_BRASTAR "[*" +%token yP_BRAEQ "[=" +%token yP_BRAMINUSGT "[->" -%token yP_PLUSPLUS "++" -%token yP_MINUSMINUS "--" -%token yP_PLUSEQ "+=" -%token yP_MINUSEQ "-=" -%token yP_TIMESEQ "*=" -%token yP_DIVEQ "/=" -%token yP_MODEQ "%=" -%token yP_ANDEQ "&=" -%token yP_OREQ "|=" -%token yP_XOREQ "^=" -%token yP_SLEFTEQ "<<=" -%token yP_SRIGHTEQ ">>=" -%token yP_SSRIGHTEQ ">>>=" +%token yP_PLUSPLUS "++" +%token yP_MINUSMINUS "--" +%token yP_PLUSEQ "+=" +%token yP_MINUSEQ "-=" +%token yP_TIMESEQ "*=" +%token yP_DIVEQ "/=" +%token yP_MODEQ "%=" +%token yP_ANDEQ "&=" +%token yP_OREQ "|=" +%token yP_XOREQ "^=" +%token yP_SLEFTEQ "<<=" +%token yP_SRIGHTEQ ">>=" +%token yP_SSRIGHTEQ ">>>=" -%token yPSL_BRA "{" -%token yPSL_KET "}" -%token yP_LOGIFF +%token yPSL_BRA "{" +%token yPSL_KET "}" +%token yP_LOGIFF // [* is not a operator, as "[ * ]" is legal // [= and [-> could be repitition operators, but to match [* we don't add them. @@ -410,7 +397,7 @@ class AstSenTree; // PSL op precedence %right yP_MINUSGT yP_LOGIFF %right yP_ORMINUSGT yP_OREQGT -%left prPSLCLK +%left prPSLCLK // Verilog op precedence %right '?' ':' @@ -464,13 +451,13 @@ class AstSenTree; // Note we read a parenthesis ahead, so this may not change the lexer at the right point. stateExitPsl: // For PSL lexing, return from PSL state - /* empty */ { V3Read::stateExitPsl(); } + /* empty */ { PARSEP->stateExitPsl(); } ; statePushVlg: // For PSL lexing, escape current state into Verilog state - /* empty */ { V3Read::statePushVlg(); } + /* empty */ { PARSEP->statePushVlg(); } ; statePop: // Return to previous lexing state - /* empty */ { V3Read::statePop(); } + /* empty */ { PARSEP->statePop(); } ; //********************************************************************** @@ -533,17 +520,21 @@ module_declaration: // ==IEEE: module_declaration module_itemListE yENDMODULE endLabelE { $1->modTrace(v3Global.opt.trace() && $1->fileline()->tracingOn()); // Stash for implicit wires, etc if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); - if ($5) $1->addStmtp($5); } + if ($5) $1->addStmtp($5); + } // //UNSUP yEXTERN modFront parameter_port_listE portsStarE ';' //UNSUP { UNSUP } ; modFront: + // // General note: all *Front functions must call symPushNew before + // // any formal arguments, as the arguments must land in the new scope. yMODULE lifetimeE idAny - { $$ = new AstModule($1,*$3); $$->inLibrary(V3Read::inLibrary()||V3Read::inCellDefine()); + { $$ = new AstModule($1,*$3); $$->inLibrary(PARSEP->inLibrary()||PARSEP->inCellDefine()); $$->modTrace(v3Global.opt.trace()); - V3Read::rootp()->addModulep($$); } + PARSEP->rootp()->addModulep($$); + } ; parameter_value_assignmentE: // IEEE: [ parameter_value_assignment ] @@ -638,10 +629,10 @@ port: // ==IEEE: port | portDirNetE signingE rangeList portSig variable_dimensionListE sigAttrListE { $$=$4; VARTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); } | portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE { $$=$2; /*VARTYPE-same*/ $$->addNextNull(VARDONEP($$,$3,$4)); } // - | portDirNetE data_type portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$3; VARTYPE($2); $$->addNextNull(VARDONEP($$,$4,$5)); $$->addNextNull(newVarInit($6,$$,$7)); } - //UNSUP portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$3; VARTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); $$->addNextNull(newVarInit($7,$$,$8)); } - //UNSUP portDirNetE yVAR implicit_type portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$3; VARTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); $$->addNextNull(newVarInit($7,$$,$8)); } - | portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$3; /*VARTYPE-same*/ $$->addNextNull(VARDONEP($$,$3,$4)); $$->addNextNull(newVarInit($5,$$,$6)); } + | portDirNetE data_type portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$3; VARTYPE($2); $$->addNextNull(VARDONEP($$,$4,$5)); $$->addNextNull(GRAMMARP->newVarInit($6,$$,$7)); } + //UNSUP portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$3; VARTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); $$->addNextNull(GRAMMARP->newVarInit($7,$$,$8)); } + //UNSUP portDirNetE yVAR implicit_type portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$3; VARTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); $$->addNextNull(GRAMMARP->newVarInit($7,$$,$8)); } + | portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$3; /*VARTYPE-same*/ $$->addNextNull(VARDONEP($$,$3,$4)); $$->addNextNull(GRAMMARP->newVarInit($5,$$,$6)); } ; portDirNetE: // IEEE: part of port, optional net type and/or direction @@ -981,12 +972,12 @@ non_port_module_item: // ==IEEE: non_port_module_item //UNSUP interface_declaration { $$ = $1; } | timeunits_declaration { $$ = NULL; } // // Verilator specific - | yaSCHDR { $$ = new AstScHdr(CRELINE(),*$1); } - | yaSCINT { $$ = new AstScInt(CRELINE(),*$1); } - | yaSCIMP { $$ = new AstScImp(CRELINE(),*$1); } - | yaSCIMPH { $$ = new AstScImpHdr(CRELINE(),*$1); } - | yaSCCTOR { $$ = new AstScCtor(CRELINE(),*$1); } - | yaSCDTOR { $$ = new AstScDtor(CRELINE(),*$1); } + | yaSCHDR { $$ = new AstScHdr($1,*$1); } + | yaSCINT { $$ = new AstScInt($1,*$1); } + | yaSCIMP { $$ = new AstScImp($1,*$1); } + | yaSCIMPH { $$ = new AstScImpHdr($1,*$1); } + | yaSCCTOR { $$ = new AstScCtor($1,*$1); } + | yaSCDTOR { $$ = new AstScDtor($1,*$1); } | yVL_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::INLINE_MODULE); } | yVL_NO_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::NO_INLINE_MODULE); } | yVL_PUBLIC_MODULE { $$ = new AstPragma($1,AstPragmaType::PUBLIC_MODULE); } @@ -1153,7 +1144,7 @@ delayE: | delay_control { } /* ignored */ ; -delay_control: //== IEEE: delay_control +delay_control: //== IEEE: delay_control '#' delay_value { $$ = $1; } /* ignored */ | '#' '(' minTypMax ')' { $$ = $1; } /* ignored */ | '#' '(' minTypMax ',' minTypMax ')' { $$ = $1; } /* ignored */ @@ -1287,7 +1278,7 @@ etcInst: // IEEE: module_instantiation + gate_instantiation + udp_insta instDecl: id parameter_value_assignmentE {INSTPREP(*$1,$2);} instnameList ';' - { $$ = $4; V3Parse::s_impliedDecl=false;} + { $$ = $4; GRAMMARP->m_impliedDecl=false;} //UNSUP: strengthSpecE for udp_instantiations ; @@ -1297,8 +1288,8 @@ instnameList: ; instnameParen: - id instRangeE '(' cellpinList ')' { $$ = new AstCell($3, *$1,V3Parse::s_instModule,$4, V3Parse::s_instParamp,$2); } - | id instRangeE { $$ = new AstCell(CRELINE(),*$1,V3Parse::s_instModule,NULL,V3Parse::s_instParamp,$2); } + id instRangeE '(' cellpinList ')' { $$ = new AstCell($3, *$1,GRAMMARP->m_instModule,$4, GRAMMARP->m_instParamp,$2); } + | id instRangeE { $$ = new AstCell(CRELINE(),*$1,GRAMMARP->m_instModule,NULL,GRAMMARP->m_instParamp,$2); } //UNSUP instRangeE '(' cellpinList ')' { UNSUP } // UDP ; @@ -1392,14 +1383,13 @@ stmtBlock: // IEEE: statement + seq_block + par_block seq_block: // ==IEEE: seq_block // // IEEE doesn't allow declarations in unnamed blocks, but several simulators do. // // So need begin's even if unnamed to scope variables down - yBEGIN blockDeclStmtList yEND { $$ = new AstBegin($1,"",$2); } - | yBEGIN /**/ yEND { $$ = NULL; } - | yBEGIN ':' seq_blockId blockDeclStmtList yEND endLabelE { $$ = new AstBegin($2,*$3,$4); } - | yBEGIN ':' seq_blockId /**/ yEND endLabelE { $$ = new AstBegin($2,*$3,NULL); } + seq_blockFront blockDeclStmtList yEND endLabelE { $$=$1; $1->addStmtp($2); } + | seq_blockFront /**/ yEND endLabelE { $$=$1; } ; -seq_blockId: // IEEE: part of seq_block - idAny/*new-block_identifier*/ { $$ = $1; } +seq_blockFront: // IEEE: part of par_block + yBEGIN { $$ = new AstBegin($1,"",NULL); } + | yBEGIN ':' idAny/*new-block_identifier*/ { $$ = new AstBegin($1,*$3,NULL); } ; blockDeclStmtList: // IEEE: { block_item_declaration } { statement or null } @@ -1581,15 +1571,15 @@ unique_priorityE: // IEEE: unique_priority + empty ; caseStart: // IEEE: part of case_statement - yCASE '(' expr ')' { $$ = V3Parse::s_caseAttrp = new AstCase($1,AstCaseType::CASE,$3,NULL); } - | yCASEX '(' expr ')' { $$ = V3Parse::s_caseAttrp = new AstCase($1,AstCaseType::CASEX,$3,NULL); $1->v3warn(CASEX,"Suggest casez (with ?'s) in place of casex (with X's)\n"); } - | yCASEZ '(' expr ')' { $$ = V3Parse::s_caseAttrp = new AstCase($1,AstCaseType::CASEZ,$3,NULL); } + yCASE '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,AstCaseType::CASE,$3,NULL); } + | yCASEX '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,AstCaseType::CASEX,$3,NULL); $1->v3warn(CASEX,"Suggest casez (with ?'s) in place of casex (with X's)\n"); } + | yCASEZ '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,AstCaseType::CASEZ,$3,NULL); } ; caseAttrE: /*empty*/ { } - | caseAttrE yVL_FULL_CASE { V3Parse::s_caseAttrp->fullPragma(true); } - | caseAttrE yVL_PARALLEL_CASE { V3Parse::s_caseAttrp->parallelPragma(true); } + | caseAttrE yVL_FULL_CASE { GRAMMARP->m_caseAttrp->fullPragma(true); } + | caseAttrE yVL_PARALLEL_CASE { GRAMMARP->m_caseAttrp->parallelPragma(true); } ; case_itemListE: // IEEE: [ { case_item } ] @@ -1682,7 +1672,7 @@ system_t_call: // IEEE: system_tf_call (as task) | yD_INFO '(' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::INFO, *$3,NULL,$4); } | yD_WARNING parenE { $$ = new AstDisplay($1,AstDisplayType::WARNING,"", NULL,NULL); } | yD_WARNING '(' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::WARNING,*$3,NULL,$4); } - | yD_ERROR parenE { $$ = V3Parse::createDisplayError($1); } + | yD_ERROR parenE { $$ = GRAMMARP->createDisplayError($1); } | yD_ERROR '(' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::ERROR, *$3,NULL,$4); $$->addNext(new AstStop($1)); } | yD_FATAL parenE { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); } | yD_FATAL '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); if ($3) $3->deleteTree(); } @@ -1727,14 +1717,18 @@ list_of_argumentsE: // IEEE: [list_of_arguments] //UNSUP empty arguments with just ,, ; -task_declaration: // ==IEEE: task_declaration +task_declaration: // ==IEEE: task_declaration yTASK lifetimeE taskId tfGuts yENDTASK endLabelE - { $$ = new AstTask ($1,*$3,$4);} + { $$ = $3; $$->addStmtsp($4); } ; function_declaration: // IEEE: function_declaration + function_body_declaration - yFUNCTION lifetimeE funcTypeE tfIdScoped tfGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$4,$5,$3); if ($3) $$->isSigned($3->isSigned()); } - | yFUNCTION lifetimeE funcTypeE tfIdScoped yVL_ISOLATE_ASSIGNMENTS tfGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$4,$6,$3); $$->attrIsolateAssign(true); if ($3) $$->isSigned($3->isSigned()); } + yFUNCTION lifetimeE funcTypeE funcId tfGuts yENDFUNCTION endLabelE + { $$ = $4; $$->addFvarp($3); $$->addStmtsp($5); if ($3) $$->isSigned($3->isSigned()); + } + | yFUNCTION lifetimeE funcTypeE funcId yVL_ISOLATE_ASSIGNMENTS tfGuts yENDFUNCTION endLabelE + { $$ = $4; $$->addFvarp($3); $$->addStmtsp($6); $$->attrIsolateAssign(true); if ($3) $$->isSigned($3->isSigned()); + } //UNSUP: Generic function return types ; @@ -1749,13 +1743,18 @@ lifetime: // ==IEEE: lifetime | yAUTOMATIC { } ; -taskId: - tfIdScoped { $$ = $1; } +taskId: + id + { $$ = new AstTask($1, *$1, NULL); + } ; -tfIdScoped: // IEEE: part of function_body_declaration/task_body_declaration - // // IEEE: [ interface_identifier '.' | class_scope ] function_identifier - id { $$ = $1; } +funcId: // IEEE: function_data_type_or_implicit + part of function_body_declaration + // // IEEE: function_data_type_or_implicit must be expanded here to prevent conflict + // // function_data_type expanded here to prevent conflicts with implicit_type:empty vs data_type:ID + id + { $$ = new AstFunc ($1,*$1,NULL,NULL); + } //UNSUP id/*interface_identifier*/ '.' id { UNSUP } //UNSUP class_scope_id { UNSUP } ; @@ -1949,7 +1948,7 @@ expr: // IEEE: part of expression/constant_expression/primary //======================// IEEE: primary/constant_primary // // // IEEE: primary_literal (minus string, which is handled specially) - | yaINTNUM { $$ = new AstConst(CRELINE(),*$1); } + | yaINTNUM { $$ = new AstConst($1,*$1); } //UNSUP yaFLOATNUM { UNSUP } //UNSUP yaTIMENUM { UNSUP } | strAsInt~noStr__IGNORE~ { $$ = $1; } @@ -2288,15 +2287,15 @@ junkToSemi: // IDs id: - yaID__ETC { $$ = $1; } + yaID__ETC { $$ = $1; $$=$1; } ; idAny: // Any kind of identifier - //UNSUP yaID__aCLASS { $$ = $1; } - //UNSUP yaID__aCOVERGROUP { $$ = $1; } - //UNSUP yaID__aPACKAGE { $$ = $1; } - //UNSUP yaID__aTYPE { $$ = $1; } - yaID__ETC { $$ = $1; } + //UNSUP yaID__aCLASS { $$ = $1; $$=$1; } + //UNSUP yaID__aCOVERGROUP { $$ = $1; $$=$1; } + //UNSUP yaID__aPACKAGE { $$ = $1; $$=$1; } + //UNSUP yaID__aTYPE { $$ = $1; $$=$1; } + yaID__ETC { $$ = $1; $$=$1; } ; idSVKwd: // Warn about non-forward compatible Verilog 2001 code @@ -2370,11 +2369,11 @@ varRefBase: // yaSTRING shouldn't be used directly, instead via an abstraction below str: // yaSTRING but with \{escapes} need decoded - yaSTRING { $$ = V3Read::newString(V3Parse::deQuote(CRELINE(),*$1)); } + yaSTRING { $$ = PARSEP->newString(GRAMMARP->deQuote($1,*$1)); } ; strAsInt: - yaSTRING { $$ = new AstConst(CRELINE(),V3Number(V3Number::VerilogString(),CRELINE(),V3Parse::deQuote(CRELINE(),*$1)));} + yaSTRING { $$ = new AstConst($1,V3Number(V3Number::VerilogString(),$1,GRAMMARP->deQuote($1,*$1)));} ; strAsIntIgnore: // strAsInt, but never matches for when expr shouldn't parse strings @@ -2382,7 +2381,7 @@ strAsIntIgnore: // strAsInt, but never matches for when expr shouldn't p ; strAsText: - yaSTRING { $$ = V3Parse::createTextQuoted(CRELINE(),*$1);} + yaSTRING { $$ = GRAMMARP->createTextQuoted($1,*$1);} ; endLabelE: @@ -2432,7 +2431,7 @@ property_specDisable: // IEEE: part of property_spec immediate_assert_statement: // ==IEEE: immediate_assert_statement // // action_block expanded here, for compatibility with AstVAssert - yASSERT '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstVAssert($1,$3,$5, V3Parse::createDisplayError($1)); } + yASSERT '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstVAssert($1,$3,$5, GRAMMARP->createDisplayError($1)); } | yASSERT '(' expr ')' yELSE stmtBlock { $$ = new AstVAssert($1,$3,NULL,$6); } | yASSERT '(' expr ')' stmtBlock yELSE stmtBlock { $$ = new AstVAssert($1,$3,$5,$7); } ; @@ -2516,12 +2515,30 @@ pslExpr: //********************************************************************** %% -void V3Read::parserClear() { - // Clear up any dynamic memory V3Parser required - V3Parse::setRange(NULL); +int V3ParseImp::bisonParse() { + if (PARSEP->debugBison()>=9) yydebug = 1; + return yyparse(); } -AstNode* V3Parse::createSupplyExpr(FileLine* fileline, string name, int value) { +const char* V3ParseImp::tokenName(int token) { +#if YYDEBUG || YYERROR_VERBOSE + if (token >= 255) + return yytname[token-255]; + else { + static char ch[2]; ch[0]=token; ch[1]='\0'; + return ch; + } +#else + return ""; +#endif +} + +void V3ParseImp::parserClear() { + // Clear up any dynamic memory V3Parser required + GRAMMARP->setRange(NULL); +} + +AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, string name, int value) { FileLine* newfl = new FileLine (fileline); newfl->warnOff(V3ErrorCode::WIDTH, true); AstNode* nodep = new AstConst(newfl, V3Number(fileline)); @@ -2532,12 +2549,12 @@ AstNode* V3Parse::createSupplyExpr(FileLine* fileline, string name, int value) { return nodep; } -AstVar* V3Parse::createVariable(FileLine* fileline, string name, AstRange* arrayp, AstNode* attrsp) { - AstVarType type = V3Parse::s_varIO; - AstRange* rangep = V3Parse::s_varRangep; +AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstRange* arrayp, AstNode* attrsp) { + AstVarType type = GRAMMARP->m_varIO; + AstRange* rangep = GRAMMARP->m_varRangep; AstRange* cleanup_rangep = NULL; - //UINFO(0,"CREVAR "<ascii()<<" decl="<ascii()<<" decl="<m_varDecl.ascii()<<" io="<m_varIO.ascii()<m_varDecl; if (type == AstVarType::PORT) { // Just wanted port decl; we've already made it. if (rangep) fileline->v3error("Unsupported: Ranges ignored in port-lists"); @@ -2545,12 +2562,12 @@ AstVar* V3Parse::createVariable(FileLine* fileline, string name, AstRange* array } if (type == AstVarType::UNKNOWN) fileline->v3fatalSrc("Unknown signal type declared"); // Linting, because we allow parsing of a superset of the language - if (type == AstVarType::INTEGER || V3Parse::s_varDecl == AstVarType::INTEGER + if (type == AstVarType::INTEGER || GRAMMARP->m_varDecl == AstVarType::INTEGER || type == AstVarType::GENVAR) { if (rangep) { if (rangep->msbConst()==31 && rangep->lsbConst()==0) { // For backward compatibility with functions some INTEGERS are internally made as [31:0] - rangep->deleteTree(); rangep=NULL; V3Parse::s_varRangep=NULL; + rangep->deleteTree(); rangep=NULL; GRAMMARP->m_varRangep=NULL; } else { fileline->v3error("Integers may not be ranged: "<cloneTree(false), arrayp); nodep->addAttrsp(attrsp); - nodep->isSigned(V3Parse::s_varSigned); - if (type == AstVarType::INTEGER || V3Parse::s_varDecl == AstVarType::INTEGER + nodep->isSigned(GRAMMARP->m_varSigned); + if (type == AstVarType::INTEGER || GRAMMARP->m_varDecl == AstVarType::INTEGER || type == AstVarType::GENVAR) { nodep->isSigned(true); } - if (V3Parse::s_varDecl != AstVarType::UNKNOWN) nodep->combineType(V3Parse::s_varDecl); - if (V3Parse::s_varIO != AstVarType::UNKNOWN) nodep->combineType(V3Parse::s_varIO); + if (GRAMMARP->m_varDecl != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varDecl); + if (GRAMMARP->m_varIO != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varIO); - if (V3Parse::s_varDecl == AstVarType::SUPPLY0) { - nodep->addNext(V3Parse::createSupplyExpr(fileline, nodep->name(), 0)); + if (GRAMMARP->m_varDecl == AstVarType::SUPPLY0) { + nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 0)); } - if (V3Parse::s_varDecl == AstVarType::SUPPLY1) { - nodep->addNext(V3Parse::createSupplyExpr(fileline, nodep->name(), 1)); + if (GRAMMARP->m_varDecl == AstVarType::SUPPLY1) { + nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 1)); } // Clear any widths that got presumed by the ranging; // We need to autosize parameters and integers separately @@ -2587,12 +2604,12 @@ AstVar* V3Parse::createVariable(FileLine* fileline, string name, AstRange* array else nodep->trace(v3Global.opt.trace() && nodep->fileline()->tracingOn()); // Remember the last variable created, so we can attach attributes to it in later parsing - V3Parse::s_varAttrp = nodep; + GRAMMARP->m_varAttrp = nodep; if (cleanup_rangep) { cleanup_rangep->deleteTree(); cleanup_rangep=NULL; } return nodep; } -string V3Parse::deQuote(FileLine* fileline, string text) { +string V3ParseGrammar::deQuote(FileLine* fileline, string text) { // Fix up the quoted strings the user put in, for example "\"" becomes " // Reverse is AstNode::quoteName(...) bool quoted = false; @@ -2647,11 +2664,6 @@ string V3Parse::deQuote(FileLine* fileline, string text) { return newtext; } -AstText* V3Parse::createTextQuoted(FileLine* fileline, string text) { - string newtext = deQuote(fileline, text); - return new AstText(fileline, newtext); -} - //YACC = /kits/sources/bison-2.4.1/src/bison --report=lookahead // --report=lookahead // --report=itemset