Compare commits

...
16 Commits
Author SHA1 Message Date
Wilson Snyder ed2fbd8f25 Version bump 2010-09-20 15:46:17 -04:00
Wilson Snyder 42199bc8e5 Fix preprocessor `` of existing base define, bug283. 2010-09-20 15:20:16 -04:00
Wilson Snyder 7c5318768c Reduce debug verbosity (match Verilog-Perl) 2010-09-20 13:13:31 -04:00
Wilson Snyder aba25aab19 On core dump, print debug suggestions. 2010-09-20 09:21:29 -04:00
Wilson Snyder f99bd33f91 Support tracing/coverage of underscore signals, bug280. 2010-08-29 19:28:46 -04:00
Wilson Snyder a6a6ce83f0 Internals: Use branch prediction in asserts 2010-08-10 11:19:45 -04:00
Wilson Snyder f4908a9758 Increase define recursions before error 2010-08-10 11:18:53 -04:00
Wilson Snyder 5e4ca4b76a Version bump 2010-07-10 18:41:23 -04:00
Wilson Snyder 1e938d0e90 Update preprocessor to match next Verilog-Perl version.
Fix preprocessor preservation of newlines across macro substitutions.
Fix preprocessor stringification of nested macros.
Fix preprocessor whitespace on define arguments
2010-07-10 18:30:16 -04:00
Wilson Snyder f3704f4c05 Tests: Rename includes to .vh extensions 2010-07-08 20:51:54 -04:00
Wilson Snyder 8800efe953 Internals: Rename incLineno to match Verilog-Perl, no functional change. 2010-07-08 20:31:41 -04:00
Wilson Snyder a320c4584e Fix do {...} while() not requiring final semicolon. 2010-07-07 19:15:51 -04:00
Wilson Snyder 3841850168 Preproc: fix pass-through of `line enter-exit codes.
Internals: Merge Verilog-Perl preproc changes through d450722.
2010-07-06 20:29:12 -04:00
Wilson Snyder beb3885840 Add t_clk_2in test 2010-06-21 20:40:34 -04:00
Wilson Snyder 06967c0c46 Fix some constant parameter functions causing crash, bug253. 2010-05-25 19:37:45 -04:00
Wilson Snyder 9a382c572c Commentary, bug251 2010-05-02 06:29:02 -04:00
44 changed files with 1910 additions and 438 deletions
+20
View File
@@ -3,6 +3,26 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...] The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks! indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.804 2010/09/20
*** Support tracing/coverage of underscore signals, bug280. [by Jason McMullan]
**** Fix preprocessor `` of existing base define, bug283. [Usha Priyadharshini]
**** Increase define recursions before error. [Paul Liu]
**** On core dump, print debug suggestions.
* Verilator 3.803 2010/07/10
*** Fix preprocessor preservation of newlines across macro substitutions.
**** Fix preprocessor stringification of nested macros.
**** Fix some constant parameter functions causing crash, bug253. [Nick Bowler]
**** Fix do {...} while() not requiring final semicolon.
* Verilator 3.802 2010/05/01 * Verilator 3.802 2010/05/01
*** Support runtime access to public signal names. *** Support runtime access to public signal names.
+1 -1
View File
@@ -118,7 +118,7 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
src/.*ignore src/*.in src/*.cpp src/*.[chly] src/astgen src/bisonpre src/*fix \ src/.*ignore src/*.in src/*.cpp src/*.[chly] src/astgen src/bisonpre src/*fix \
src/*.pl src/*.pod \ src/*.pl src/*.pod \
test_*/.*ignore test_*/Makefile* test_*/*.cpp \ test_*/.*ignore test_*/Makefile* test_*/*.cpp \
test_*/*.pl test_*/*.v test_*/*.vc test_*/vlint \ test_*/*.pl test_*/*.v test_*/*.vc test_*/*.vh \
test_verilated/vgen*.pl \ test_verilated/vgen*.pl \
test_regress/t/*.cpp \ test_regress/t/*.cpp \
test_regress/t/*.h \ test_regress/t/*.h \
+23 -2
View File
@@ -137,6 +137,15 @@ sub run {
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n"; warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
warn "%Error: $command\n"; warn "%Error: $command\n";
} }
if ($status & 255) {
if (($status & 255) == 8 || ($status & 255) == 11) { # SIGFPA or SIGSEGV
warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
} elsif (($status & 255) == 6) { # SIGABRT
warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
} else {
warn "%Error: Verilator threw signal $status. Consider trying --debug --gdbbt\n" if !$Debug;
}
}
die "%Error: Command Failed $command\n"; die "%Error: Command Failed $command\n";
} }
} }
@@ -207,6 +216,7 @@ descriptions in the next sections for more information.
--coverage-line Enable line coverage --coverage-line Enable line coverage
--coverage-toggle Enable toggle coverage --coverage-toggle Enable toggle coverage
--coverage-user Enable PSL/SVL user coverage --coverage-user Enable PSL/SVL user coverage
--coverage-underscore Enable covarge of _signals
-D<var>[=<value>] Set preprocessor define -D<var>[=<value>] Set preprocessor define
--debug Enable debugging --debug Enable debugging
--debug-check Enable debugging assertions --debug-check Enable debugging assertions
@@ -256,6 +266,7 @@ descriptions in the next sections for more information.
--top-module <topname> Name of top level input module --top-module <topname> Name of top level input module
--trace Enable waveform creation --trace Enable waveform creation
--trace-depth <levels> Depth of tracing --trace-depth <levels> Depth of tracing
--trace-underscore Enable tracing of _signals
-U<var> Undefine preprocessor define -U<var> Undefine preprocessor define
--unroll-count <loops> Tune maximum loop iterations --unroll-count <loops> Tune maximum loop iterations
--unroll-stmts <stmts> Tune maximum loop body size --unroll-stmts <stmts> Tune maximum loop body size
@@ -426,6 +437,11 @@ counting such behavior.
A /*verilator coverage_off/on */ comment pair can be used around signals A /*verilator coverage_off/on */ comment pair can be used around signals
that do not need toggle analysis, such as RAMs and register files. that do not need toggle analysis, such as RAMs and register files.
=item --coverage-underscore
Enable coverage of signals that start with an underscore. Normally, these
signals are not covered. See also --trace-underscore.
=item --coverage-user =item --coverage-user
Enables user inserted functional coverage. Currently, all functional Enables user inserted functional coverage. Currently, all functional
@@ -750,6 +766,11 @@ Specify the number of levels deep to enable tracing, for example
entire model. Using a small number will decrease visibility, but greatly entire model. Using a small number will decrease visibility, but greatly
improve runtime and trace file size. improve runtime and trace file size.
=item --trace-underscore
Enable tracing of signals that start with an underscore. Normally, these
signals are not output during tracing. See also --coverage-underscore.
=item -UI<var> =item -UI<var>
Undefines the given preprocessor symbol. Undefines the given preprocessor symbol.
@@ -2636,7 +2657,7 @@ finally call "trace_object->close()". For an example, see below and the
test_c/sim_main.cpp file of the distribution. test_c/sim_main.cpp file of the distribution.
You also need to compile verilated_vcd_c.cpp and add it to your link, You also need to compile verilated_vcd_c.cpp and add it to your link,
preferably by adding the dependancies in $(VK_GLOBAL_OBJS) to your preferably by adding the dependencies in $(VK_GLOBAL_OBJS) to your
Makefile's link rule. This is done for you if using the Verilator --exe Makefile's link rule. This is done for you if using the Verilator --exe
flag. flag.
@@ -2676,7 +2697,7 @@ question, however the timescale and timeprecision will not inherited from
your SystemC settings. your SystemC settings.
You also need to compile verilated_vcd_sc.cpp and verilated_vcd_c.cpp and You also need to compile verilated_vcd_sc.cpp and verilated_vcd_c.cpp and
add them to your link, preferably by adding the dependancies in add them to your link, preferably by adding the dependencies in
$(VK_GLOBAL_OBJS) to your Makefile's link rule. This is done for you if $(VK_GLOBAL_OBJS) to your Makefile's link rule. This is done for you if
using the Verilator --exe flag. using the Verilator --exe flag.
+6 -4
View File
@@ -81,10 +81,12 @@ private:
string prettyName = nodep->prettyName(); string prettyName = nodep->prettyName();
if (!nodep->isToggleCoverable()) if (!nodep->isToggleCoverable())
return "Not relevant signal type"; return "Not relevant signal type";
if (prettyName.c_str()[0] == '_') if (!v3Global.opt.coverageUnderscore()) {
return "Leading underscore"; if (prettyName.c_str()[0] == '_')
if (prettyName.find("._") != string::npos) return "Leading underscore";
return "Inlined leading underscore"; if (prettyName.find("._") != string::npos)
return "Inlined leading underscore";
}
if ((nodep->width()*nodep->arrayElements()) > 256) return "Wide bus/array > 256 bits"; if ((nodep->width()*nodep->arrayElements()) > 256) return "Wide bus/array > 256 bits";
// We allow this, though tracing doesn't // We allow this, though tracing doesn't
// if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array"; // if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array";
+13 -1
View File
@@ -79,7 +79,13 @@ FileLine::FileLine(FileLine::EmptySecret) {
} }
} }
void FileLine::lineDirective(const char* textp) { string FileLine::lineDirectiveStrg(int enterExit) const {
char numbuf[20]; sprintf(numbuf, "%d", lineno());
char levelbuf[20]; sprintf(levelbuf, "%d", enterExit);
return ((string)"`line "+numbuf+" \""+filename()+"\" "+levelbuf+"\n");
}
void FileLine::lineDirective(const char* textp, int& enterExitRef) {
// Handle `line directive // Handle `line directive
// Skip `line // Skip `line
while (*textp && isspace(*textp)) textp++; while (*textp && isspace(*textp)) textp++;
@@ -102,6 +108,12 @@ void FileLine::lineDirective(const char* textp) {
strfn = strfn.substr(0, textp-fn); strfn = strfn.substr(0, textp-fn);
this->filename(strfn); this->filename(strfn);
} }
// Grab level
while (*textp && (isspace(*textp) || *textp=='"')) textp++;
if (isdigit(*textp)) enterExitRef = atoi(textp);
else enterExitRef = 0;
//printf ("PPLINE %d '%s'\n", s_lineno, s_filename.c_str()); //printf ("PPLINE %d '%s'\n", s_lineno, s_filename.c_str());
} }
+12 -6
View File
@@ -196,13 +196,13 @@ inline void v3errorEnd(ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
// Use this instead of fatal() to mention the source code line. // Use this instead of fatal() to mention the source code line.
#define v3fatalSrc(msg) v3warn(EC_FATALSRC,__FILE__<<":"<<dec<<__LINE__<<": "<<msg) #define v3fatalSrc(msg) v3warn(EC_FATALSRC,__FILE__<<":"<<dec<<__LINE__<<": "<<msg)
#define UINFO(level,stmsg) {if(debug()>=(level)) { cout<<"- "<<V3Error::lineStr(__FILE__,__LINE__)<<stmsg; }} #define UINFO(level,stmsg) {if(VL_UNLIKELY(debug()>=(level))) { cout<<"- "<<V3Error::lineStr(__FILE__,__LINE__)<<stmsg; }}
#define UINFONL(level,stmsg) {if(debug()>=(level)) { cout<<stmsg; } } #define UINFONL(level,stmsg) {if(VL_UNLIKELY(debug()>=(level))) { cout<<stmsg; } }
#define UDEBUGONLY(stmts) {stmts} #define UDEBUGONLY(stmts) {stmts}
#define UASSERT(condition,stmsg) { if (!(condition)) { v3fatalSrc(stmsg); }} #define UASSERT(condition,stmsg) { if (VL_UNLIKELY(!(condition))) { v3fatalSrc(stmsg); }}
// For use in V3Ast static functions only // For use in V3Ast static functions only
#define UASSERT_STATIC(condition,stmsg) { if (!(condition)) { cerr<<"Internal Error: "<<__FILE__<<":"<<dec<<__LINE__<<":"<<(stmsg)<<endl; abort(); } } #define UASSERT_STATIC(condition,stmsg) { if (VL_UNLIKELY(!(condition))) { cerr<<"Internal Error: "<<__FILE__<<":"<<dec<<__LINE__<<":"<<(stmsg)<<endl; abort(); } }
#define V3ERROR_NA { v3error("Internal: Unexpected Call"); v3fatalSrc("Unexpected Call"); } #define V3ERROR_NA { v3error("Internal: Unexpected Call"); v3fatalSrc("Unexpected Call"); }
@@ -234,26 +234,32 @@ protected:
// We are storing pointers, so we CAN'T change them after initial reading. // We are storing pointers, so we CAN'T change them after initial reading.
friend class V3ParseImp; friend class V3ParseImp;
friend class V3PreLex; friend class V3PreLex;
friend class V3PreProcImp;
void lineno(int num) { m_lineno = num; } void lineno(int num) { m_lineno = num; }
void filename(const string& name) { m_filename = name; } void filename(const string& name) { m_filename = name; }
void lineDirective(const char* textp); void lineDirective(const char* textp, int& enterExitRef);
void incLineno() { m_lineno++; } void linenoInc() { m_lineno++; }
void linenoIncInPlace() { m_lineno++; }
FileLine* copyOrSameFileLine(); FileLine* copyOrSameFileLine();
public: public:
FileLine (const string& filename, int lineno) { m_lineno=lineno; m_filename = filename; m_warnOn=s_defaultFileLine.m_warnOn; } FileLine (const string& filename, int lineno) { m_lineno=lineno; m_filename = filename; m_warnOn=s_defaultFileLine.m_warnOn; }
FileLine (FileLine* fromp) { m_lineno=fromp->lineno(); m_filename = fromp->filename(); m_warnOn=fromp->m_warnOn; } FileLine (FileLine* fromp) { m_lineno=fromp->lineno(); m_filename = fromp->filename(); m_warnOn=fromp->m_warnOn; }
FileLine (EmptySecret); FileLine (EmptySecret);
~FileLine() { } ~FileLine() { }
FileLine* create(const string& filename, int lineno) { return new FileLine(filename,lineno); }
FileLine* create(int lineno) { return create(filename(), lineno); }
static void deleteAllRemaining(); static void deleteAllRemaining();
#ifdef VL_LEAK_CHECKS #ifdef VL_LEAK_CHECKS
static void* operator new(size_t size); static void* operator new(size_t size);
static void operator delete(void* obj, size_t size); static void operator delete(void* obj, size_t size);
#endif #endif
int lineno () const { return m_lineno; } int lineno () const { return m_lineno; }
string ascii() const; string ascii() const;
const string filename () const { return m_filename; } const string filename () const { return m_filename; }
const string filebasename () const; const string filebasename () const;
const string profileFuncname() const; const string profileFuncname() const;
string lineDirectiveStrg(int enter_exit_level) const;
void warnOn(V3ErrorCode code, bool flag) { m_warnOn.set(code,flag); } // Turn on/off warning messages on this line. void warnOn(V3ErrorCode code, bool flag) { m_warnOn.set(code,flag); } // Turn on/off warning messages on this line.
void warnOff(V3ErrorCode code, bool flag) { warnOn(code,!flag); } void warnOff(V3ErrorCode code, bool flag) { warnOn(code,!flag); }
bool warnOff(const string& code, bool flag); // Returns 1 if ok bool warnOff(const string& code, bool flag); // Returns 1 if ok
+6
View File
@@ -611,9 +611,12 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
else if ( onoff (sw, "-coverage", flag/*ref*/) ) { coverage(flag); } else if ( onoff (sw, "-coverage", flag/*ref*/) ) { coverage(flag); }
else if ( onoff (sw, "-coverage-line", flag/*ref*/) ){ m_coverageLine = flag; } else if ( onoff (sw, "-coverage-line", flag/*ref*/) ){ m_coverageLine = flag; }
else if ( onoff (sw, "-coverage-toggle", flag/*ref*/) ){ m_coverageToggle = flag; } else if ( onoff (sw, "-coverage-toggle", flag/*ref*/) ){ m_coverageToggle = flag; }
else if ( onoff (sw, "-coverage-underscore", flag/*ref*/) ){ m_coverageUnderscore = flag; }
else if ( onoff (sw, "-coverage-user", flag/*ref*/) ){ m_coverageUser = flag; } else if ( onoff (sw, "-coverage-user", flag/*ref*/) ){ m_coverageUser = flag; }
else if ( onoff (sw, "-covsp", flag/*ref*/) ) { } // TBD else if ( onoff (sw, "-covsp", flag/*ref*/) ) { } // TBD
else if ( !strcmp (sw, "-debug-abort") ) { abort(); } // Undocumented, see also --debug-core-dump
else if ( onoff (sw, "-debug-check", flag/*ref*/) ){ m_debugCheck = flag; } else if ( onoff (sw, "-debug-check", flag/*ref*/) ){ m_debugCheck = flag; }
else if ( !strcmp (sw, "-debug-core-dump") ) { char* zp=NULL; *zp=0; } // Undocumented, see also --debug-abort
else if ( onoff (sw, "-dump-tree", flag/*ref*/) ) { m_dumpTree = flag; } else if ( onoff (sw, "-dump-tree", flag/*ref*/) ) { m_dumpTree = flag; }
else if ( onoff (sw, "-exe", flag/*ref*/) ) { m_exe = flag; } else if ( onoff (sw, "-exe", flag/*ref*/) ) { m_exe = flag; }
else if ( onoff (sw, "-ignc", flag/*ref*/) ) { m_ignc = flag; } else if ( onoff (sw, "-ignc", flag/*ref*/) ) { m_ignc = flag; }
@@ -634,6 +637,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
else if ( !strcmp (sw, "-sv") ) { m_language = V3LangCode::L1800_2005; } else if ( !strcmp (sw, "-sv") ) { m_language = V3LangCode::L1800_2005; }
else if ( onoff (sw, "-trace", flag/*ref*/) ) { m_trace = flag; } else if ( onoff (sw, "-trace", flag/*ref*/) ) { m_trace = flag; }
else if ( onoff (sw, "-trace-dups", flag/*ref*/) ) { m_traceDups = flag; } else if ( onoff (sw, "-trace-dups", flag/*ref*/) ) { m_traceDups = flag; }
else if ( onoff (sw, "-trace-underscore", flag/*ref*/) ) { m_traceUnderscore = flag; }
else if ( onoff (sw, "-underline-zero", flag/*ref*/) ) { m_underlineZero = flag; } // Undocumented, old Verilator-2 else if ( onoff (sw, "-underline-zero", flag/*ref*/) ) { m_underlineZero = flag; } // Undocumented, old Verilator-2
// Optimization // Optimization
else if ( !strncmp (sw, "-O", 2) ) { else if ( !strncmp (sw, "-O", 2) ) {
@@ -993,6 +997,7 @@ V3Options::V3Options() {
m_autoflush = false; m_autoflush = false;
m_coverageLine = false; m_coverageLine = false;
m_coverageToggle = false; m_coverageToggle = false;
m_coverageUnderscore = false;
m_coverageUser = false; m_coverageUser = false;
m_debugCheck = false; m_debugCheck = false;
m_dumpTree = false; m_dumpTree = false;
@@ -1014,6 +1019,7 @@ V3Options::V3Options() {
m_systemPerl = false; m_systemPerl = false;
m_trace = false; m_trace = false;
m_traceDups = false; m_traceDups = false;
m_traceUnderscore = false;
m_underlineZero = false; m_underlineZero = false;
m_errorLimit = 50; m_errorLimit = 50;
+4
View File
@@ -103,6 +103,7 @@ class V3Options {
bool m_cdc; // main switch: --cdc bool m_cdc; // main switch: --cdc
bool m_coverageLine; // main switch: --coverage-block bool m_coverageLine; // main switch: --coverage-block
bool m_coverageToggle;// main switch: --coverage-toggle bool m_coverageToggle;// main switch: --coverage-toggle
bool m_coverageUnderscore;// main switch: --coverage-underscore
bool m_coverageUser; // main switch: --coverage-func bool m_coverageUser; // main switch: --coverage-func
bool m_debugCheck; // main switch: --debug-check bool m_debugCheck; // main switch: --debug-check
bool m_dumpTree; // main switch: --dump-tree bool m_dumpTree; // main switch: --dump-tree
@@ -122,6 +123,7 @@ class V3Options {
bool m_stats; // main switch: --stats bool m_stats; // main switch: --stats
bool m_trace; // main switch: --trace bool m_trace; // main switch: --trace
bool m_traceDups; // main switch: --trace-dups bool m_traceDups; // main switch: --trace-dups
bool m_traceUnderscore;// main switch: --trace-underscore
bool m_underlineZero;// main switch: --underline-zero; undocumented old Verilator 2 bool m_underlineZero;// main switch: --underline-zero; undocumented old Verilator 2
int m_errorLimit; // main switch: --error-limit int m_errorLimit; // main switch: --error-limit
@@ -222,12 +224,14 @@ class V3Options {
bool coverage() const { return m_coverageLine || m_coverageToggle || m_coverageUser; } bool coverage() const { return m_coverageLine || m_coverageToggle || m_coverageUser; }
bool coverageLine() const { return m_coverageLine; } bool coverageLine() const { return m_coverageLine; }
bool coverageToggle() const { return m_coverageToggle; } bool coverageToggle() const { return m_coverageToggle; }
bool coverageUnderscore() const { return m_coverageUnderscore; }
bool coverageUser() const { return m_coverageUser; } bool coverageUser() const { return m_coverageUser; }
bool debugCheck() const { return m_debugCheck; } bool debugCheck() const { return m_debugCheck; }
bool dumpTree() const { return m_dumpTree; } bool dumpTree() const { return m_dumpTree; }
bool exe() const { return m_exe; } bool exe() const { return m_exe; }
bool trace() const { return m_trace; } bool trace() const { return m_trace; }
bool traceDups() const { return m_traceDups; } bool traceDups() const { return m_traceDups; }
bool traceUnderscore() const { return m_traceUnderscore; }
bool outFormatOk() const { return m_outFormatOk; } bool outFormatOk() const { return m_outFormatOk; }
bool keepTempFiles() const { return (V3Error::debugDefault()!=0); } bool keepTempFiles() const { return (V3Error::debugDefault()!=0); }
bool pinsUint8() const { return m_pinsUint8; } bool pinsUint8() const { return m_pinsUint8; }
+4 -3
View File
@@ -52,10 +52,11 @@
class ParamVisitor : public AstNVisitor { class ParamVisitor : public AstNVisitor {
private: private:
// NODE STATE // NODE STATE
// AstNodeModule::user4() // bool True if parameters numbered // AstNodeModule::user5() // bool True if parameters numbered
// AstVar::user4() // int Global parameter number (for naming new module) // AstVar::user4() // int Global parameter number (for naming new module)
// // (0=not processed, 1=iterated, but no number, 65+ parameter numbered) // // (0=not processed, 1=iterated, but no number, 65+ parameter numbered)
AstUser4InUse m_inuser4; AstUser4InUse m_inuser4;
AstUser5InUse m_inuser5;
// User1/2/3 used by constant function simulations // User1/2/3 used by constant function simulations
// STATE // STATE
@@ -130,8 +131,8 @@ private:
// Make sure all parameters are constantified // Make sure all parameters are constantified
virtual void visit(AstVar* nodep, AstNUser*) { virtual void visit(AstVar* nodep, AstNUser*) {
if (!nodep->user4()) { if (!nodep->user5()) {
nodep->user4(1); // Mark done - Note values >1 used for letter numbering nodep->user5(1); // Mark done
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (nodep->isParam()) { if (nodep->isParam()) {
if (!nodep->hasSimpleInit()) { nodep->v3fatalSrc("Parameter without initial value"); } if (!nodep->hasSimpleInit()) { nodep->v3fatalSrc("Parameter without initial value"); }
+1 -1
View File
@@ -249,7 +249,7 @@ public:
static bool optFuture(const string& flag) { return v3Global.opt.isFuture(flag); } static bool optFuture(const string& flag) { return v3Global.opt.isFuture(flag); }
void ppline (const char* text); void ppline (const char* text);
void incLineno() { fileline()->incLineno(); } void linenoInc() { fileline()->linenoInc(); }
void verilatorCmtLint(const char* text, bool on); void verilatorCmtLint(const char* text, bool on);
void verilatorCmtLintSave(); void verilatorCmtLintSave();
void verilatorCmtLintRestore(); void verilatorCmtLintRestore();
+67 -19
View File
@@ -32,8 +32,12 @@
#include "V3Error.h" #include "V3Error.h"
//======================================================================
class V3PreProcImp;
// Token codes // Token codes
// If changing, see V3Pre.cpp's V3PreImp::tokenName() // If changing, see V3PreProc.cpp's V3PreProcImp::tokenName()
#define VP_EOF 0 #define VP_EOF 0
#define VP_INCLUDE 256 #define VP_INCLUDE 256
@@ -57,10 +61,13 @@
#define VP_DEFARG 307 #define VP_DEFARG 307
#define VP_ERROR 308 #define VP_ERROR 308
#define VP_DEFFORM 309 #define VP_DEFFORM 309
#define VP_STRIFY 310
#define VP_BACKQUOTE 311
#define VP_SYMBOL_JOIN 312
#define VP_DEFREF_JOIN 313
#define VP_PSL 350 #define VP_PSL 350
//====================================================================== //======================================================================
// Externs created by flex // Externs created by flex
// We add a prefix so that other lexers/flexers in the same program won't collide. // We add a prefix so that other lexers/flexers in the same program won't collide.
@@ -111,22 +118,41 @@ void yy_delete_buffer( YY_BUFFER_STATE b );
//====================================================================== //======================================================================
#define KEEPCMT_SUB 2 #define KEEPCMT_SUB 2
#define KEEPCMT_EXP 3
//======================================================================
// Entry for each file processed; a stack of entries included
class VPreStream {
public:
FileLine* m_curFilelinep; // Current processing point (see also m_tokFilelinep)
deque<string> m_buffers; // Buffer of characters to process
int m_ignNewlines; // Ignore multiline newlines
bool m_eof; // "EOF" buffer
bool m_file; // Buffer is start of new file
int m_termState; // Termination fsm
VPreStream(FileLine* fl)
: m_curFilelinep(fl), m_ignNewlines(0),
m_eof(false), m_file(false), m_termState(0) {
}
~VPreStream() {}
};
//====================================================================== //======================================================================
// Class entry for each per-lexer state // Class entry for each per-lexer state
class V3PreLex { class V3PreLex {
public: // Used only by V3PreLex.cpp and V3PreProc.cpp public: // Used only by V3PreLex.cpp and V3PreProc.cpp
FileLine* m_curFilelinep; // Current processing point V3PreProcImp* m_preimpp; // Preprocessor lexor belongs to
stack<VPreStream*> m_streampStack; // Stack of processing files
// Parse state YY_BUFFER_STATE m_bufferState; // Flex state
stack<YY_BUFFER_STATE> m_bufferStack; // Stack of inserted text above current point FileLine* m_tokFilelinep; // Starting position of current token
deque<string> m_buffers; ///< Buffer of characters to process
// State to lexer // State to lexer
static V3PreLex* s_currentLexp; // Current lexing point static V3PreLex* s_currentLexp; ///< Current lexing point
int m_keepComments; // Emit comments in output text int m_keepComments; ///< Emit comments in output text
bool m_pedantic; // Obey standard; don't Substitute `error int m_keepWhitespace; ///< Emit all whitespace in output text
bool m_pedantic; ///< Obey standard; don't Substitute `error
// State from lexer // State from lexer
int m_formalLevel; // Parenthesis counting inside def formals int m_formalLevel; // Parenthesis counting inside def formals
@@ -135,40 +161,62 @@ class V3PreLex {
bool m_pslMoreNeeded;// Next // comment is really psl bool m_pslMoreNeeded;// Next // comment is really psl
bool m_defCmtSlash; // /*...*/ comment in define had \ ending bool m_defCmtSlash; // /*...*/ comment in define had \ ending
string m_defValue; // Definition value being built. string m_defValue; // Definition value being built.
int m_enterExit; // For VL_LINE, the enter/exit level
// CONSTRUCTORS // CONSTRUCTORS
V3PreLex() { V3PreLex(V3PreProcImp* preimpp, FileLine* filelinep) {
m_preimpp = preimpp;
m_keepComments = 0; m_keepComments = 0;
m_keepWhitespace = 1;
m_pedantic = false; m_pedantic = false;
m_formalLevel = 0; m_formalLevel = 0;
m_parenLevel = 0; m_parenLevel = 0;
m_defCmtSlash = false; m_defCmtSlash = false;
m_tokFilelinep = filelinep;
m_enterExit = 0;
m_pslParenLevel = 0; m_pslParenLevel = 0;
m_pslMoreNeeded = false; m_pslMoreNeeded = false;
initFirstBuffer(); initFirstBuffer(filelinep);
} }
~V3PreLex() { ~V3PreLex() {
while (!m_bufferStack.empty()) { yy_delete_buffer(m_bufferStack.top()); m_bufferStack.pop(); } while (!m_streampStack.empty()) { delete m_streampStack.top(); m_streampStack.pop(); }
yy_delete_buffer(m_bufferState); m_bufferState=NULL;
} }
void initFirstBuffer();
// Called by V3PreLex.l from lexer // Called by V3PreLex.l from lexer
void appendDefValue(const char* text, size_t len); VPreStream* curStreamp() { return m_streampStack.top(); } // Can't be empty, "EOF" is on top
void lineDirective(const char* text); FileLine* curFilelinep() { return curStreamp()->m_curFilelinep; }
void incLineno() { m_curFilelinep->incLineno(); } void curFilelinep(FileLine* fl) { curStreamp()->m_curFilelinep = fl; }
void appendDefValue(const char* textp, size_t len) { m_defValue.append(textp,len); }
void lineDirective(const char* textp);
void linenoInc() { if (curStreamp()->m_ignNewlines) curStreamp()->m_ignNewlines--;
else curFilelinep()->linenoInc(); }
// Called by V3PreProc.cpp to inform lexer // Called by V3PreProc.cpp to inform lexer
void pushStateDefArg(int level); void pushStateDefArg(int level);
void pushStateDefForm(); void pushStateDefForm();
void pushStateDefValue(); void pushStateDefValue();
void pushStateIncFilename(); void pushStateIncFilename();
void scanBytes(const char* strp, size_t len); void scanNewFile(FileLine* filelinep);
void scanBytes(const string& str);
void scanBytesBack(const string& str); void scanBytesBack(const string& str);
size_t inputToLex(char* buf, size_t max_size); size_t inputToLex(char* buf, size_t max_size);
/// Called by VPreproc.cpp to get data from lexer /// Called by V3PreProc.cpp to get data from lexer
YY_BUFFER_STATE currentBuffer(); YY_BUFFER_STATE currentBuffer();
int lex();
int currentStartState(); int currentStartState();
void dumpSummary(); void dumpSummary();
void dumpStack(); void dumpStack();
void unused();
/// Utility
static int debug();
static void debug(int level);
static string cleanDbgStrg(const string& in);
private:
string currentUnreadChars();
string endOfStream(bool& againr);
void initFirstBuffer(FileLine* filelinep);
void scanSwitchStream(VPreStream* streamp);
}; };
#endif // Guard #endif // Guard
+210 -53
View File
@@ -1,3 +1,8 @@
%option noyywrap align interactive
%option stack
%option noc++
%option prefix="V3PreLex"
%{
/************************************************************************** /**************************************************************************
* DESCRIPTION: Verilator: Flex verilog preprocessor * DESCRIPTION: Verilator: Flex verilog preprocessor
* *
@@ -20,12 +25,6 @@
* lost characters. * lost characters.
**************************************************************************/ **************************************************************************/
%option noyywrap align interactive
%option stack
%option noc++
%option prefix="V3PreLex"
%{
#include "V3PreProc.h" #include "V3PreProc.h"
#include "V3PreLex.h" #include "V3PreLex.h"
@@ -42,11 +41,11 @@ size_t yyourleng() { return yyleng; }
void yyourtext(const char* textp, size_t size) { yytext=(char*)textp; yyleng=size; } void yyourtext(const char* textp, size_t size) { yytext=(char*)textp; yyleng=size; }
// Prevent conflicts from perl version // Prevent conflicts from perl version
static void linenoInc() {LEXP->incLineno();} static void linenoInc() {LEXP->linenoInc();}
static bool optPsl() { return V3PreProc::optPsl(); } static bool optPsl() { return V3PreProc::optPsl(); }
static bool pedantic() { return LEXP->m_pedantic; } static bool pedantic() { return LEXP->m_pedantic; }
static void yyerror(char* msg) { LEXP->m_curFilelinep->v3error(msg); } static void yyerror(char* msg) { LEXP->curFilelinep()->v3error(msg); }
static void yyerrorf(const char* msg) { LEXP->m_curFilelinep->v3error(msg); } static void yyerrorf(const char* msg) { LEXP->curFilelinep()->v3error(msg); }
static void appendDefValue(const char* t, size_t l) { LEXP->appendDefValue(t,l); } static void appendDefValue(const char* t, size_t l) { LEXP->appendDefValue(t,l); }
static int pslParenLevel() { return LEXP->m_pslParenLevel; } static int pslParenLevel() { return LEXP->m_pslParenLevel; }
static void pslParenLevelInc() { LEXP->m_pslParenLevel++; } static void pslParenLevelInc() { LEXP->m_pslParenLevel++; }
@@ -79,8 +78,11 @@ ws [ \t\f\r]
wsn [ \t\f] wsn [ \t\f]
crnl [\r]*[\n] crnl [\r]*[\n]
quote [\"] quote [\"]
tickquote [`][\"]
backslash [\\] backslash [\\]
/* Where we use symb/symbdef, we must also look for a `` join */
symb ([a-zA-Z_][a-zA-Z0-9_$]*|\\[^ \t\f\r\n]+) symb ([a-zA-Z_][a-zA-Z0-9_$]*|\\[^ \t\f\r\n]+)
symbdef ([a-zA-Z_][a-zA-Z0-9_$]*|\\[^ \t\f\r\n`]+)
word [a-zA-Z0-9_]+ word [a-zA-Z0-9_]+
drop [\032] drop [\032]
psl [p]sl psl [p]sl
@@ -104,11 +106,11 @@ psl [p]sl
/* Optional directives we recognize */ /* Optional directives we recognize */
<INITIAL>"`__FILE__" { static string rtnfile; <INITIAL>"`__FILE__" { static string rtnfile;
rtnfile = '"'; rtnfile += LEXP->m_curFilelinep->filename().c_str(); rtnfile = '"'; rtnfile += LEXP->curFilelinep()->filename().c_str();
rtnfile += '"'; yytext=(char*)rtnfile.c_str(); yyleng = rtnfile.length(); rtnfile += '"'; yytext=(char*)rtnfile.c_str(); yyleng = rtnfile.length();
return (VP_STRING); } return (VP_STRING); }
<INITIAL>"`__LINE__" { static char buf[10]; <INITIAL>"`__LINE__" { static char buf[10];
sprintf(buf, "%d",LEXP->m_curFilelinep->lineno()); sprintf(buf, "%d",LEXP->curFilelinep()->lineno());
yytext = buf; yyleng = strlen(yytext); yytext = buf; yyleng = strlen(yytext);
return (VP_TEXT); } return (VP_TEXT); }
<INITIAL>"`error" { if (!pedantic()) return (VP_ERROR); else return(VP_DEFREF); } <INITIAL>"`error" { if (!pedantic()) return (VP_ERROR); else return(VP_DEFREF); }
@@ -125,6 +127,10 @@ psl [p]sl
if (LEXP->m_parenLevel || LEXP->m_formalLevel) { appendDefValue(yytext,yyleng); yyleng=0; } if (LEXP->m_parenLevel || LEXP->m_formalLevel) { appendDefValue(yytext,yyleng); yyleng=0; }
else return (VP_STRING); } else return (VP_STRING); }
/* Stringification */
<INITIAL>{tickquote} { return VP_STRIFY; }
<INITIAL>"`\\`\"" { return VP_BACKQUOTE; }
/* Protected blocks */ /* Protected blocks */
<INITIAL>"`protected" { yy_push_state(PRTMODE); yymore(); } <INITIAL>"`protected" { yy_push_state(PRTMODE); yymore(); }
<PRTMODE><<EOF>> { linenoInc(); yyerrorf("EOF in `protected"); yyleng=0; yyterminate(); } <PRTMODE><<EOF>> { linenoInc(); yyerrorf("EOF in `protected"); yyleng=0; yyterminate(); }
@@ -146,7 +152,7 @@ psl [p]sl
<DEFFPAR><<EOF>> { yy_pop_state(); return VP_DEFFORM; } /* empty formals */ <DEFFPAR><<EOF>> { yy_pop_state(); return VP_DEFFORM; } /* empty formals */
<DEFFPAR>. { yy_pop_state(); unput(yytext[yyleng-1]); yyleng=0; return VP_DEFFORM; } /* empty formals */ <DEFFPAR>. { yy_pop_state(); unput(yytext[yyleng-1]); yyleng=0; return VP_DEFFORM; } /* empty formals */
/* Reading definition formals */ /* Reading definition formals (declaration of a define) */
<DEFFORM>[(] { appendDefValue(yytext,yyleng); yyleng=0; ++LEXP->m_formalLevel; } <DEFFORM>[(] { appendDefValue(yytext,yyleng); yyleng=0; ++LEXP->m_formalLevel; }
<DEFFORM>[)] { appendDefValue(yytext,yyleng); yyleng=0; if ((--LEXP->m_formalLevel)==0) { yy_pop_state(); return VP_DEFFORM; } } <DEFFORM>[)] { appendDefValue(yytext,yyleng); yyleng=0; if ((--LEXP->m_formalLevel)==0) { yy_pop_state(); return VP_DEFFORM; } }
<DEFFORM>"/*" { yy_push_state(CMTMODE); yymore(); } <DEFFORM>"/*" { yy_push_state(CMTMODE); yymore(); }
@@ -154,22 +160,24 @@ psl [p]sl
<DEFFORM>{drop} { } <DEFFORM>{drop} { }
<DEFFORM><<EOF>> { linenoInc(); yy_pop_state(); yyerrorf("Unterminated ( in define formal arguments."); yyleng=0; return VP_DEFFORM; } <DEFFORM><<EOF>> { linenoInc(); yy_pop_state(); yyerrorf("Unterminated ( in define formal arguments."); yyleng=0; return VP_DEFFORM; }
<DEFFORM>{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */ <DEFFORM>{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */
<DEFFORM>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */ <DEFFORM>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\\\n",2); } /* Include return so can maintain output line count */
<DEFFORM>{quote} { yy_push_state(STRMODE); yymore(); } <DEFFORM>{quote} { yy_push_state(STRMODE); yymore(); } /* Legal only in default values */
<DEFFORM>"`\\`\"" { appendDefValue(yytext,yyleng); } /* Maybe illegal, otherwise in default value */
<DEFFORM>{tickquote} { appendDefValue(yytext,yyleng); } /* Maybe illegal, otherwise in default value */
<DEFFORM>[{\[] { LEXP->m_formalLevel++; appendDefValue(yytext,yyleng); } <DEFFORM>[{\[] { LEXP->m_formalLevel++; appendDefValue(yytext,yyleng); }
<DEFFORM>[}\]] { LEXP->m_formalLevel--; appendDefValue(yytext,yyleng); } <DEFFORM>[}\]] { LEXP->m_formalLevel--; appendDefValue(yytext,yyleng); }
<DEFFORM>[^\/\*\n\r\\(){}\[\]\"]+ | <DEFFORM>[^\/\*\n\r\\(){}\[\]\"]+ |
<DEFFORM>[\\][^\n\r] | <DEFFORM>[\\][^\n\r] |
<DEFFORM>. { appendDefValue(yytext,yyleng); } <DEFFORM>. { appendDefValue(yytext,yyleng); }
/* Reading definition value */ /* Reading definition value (declaration of a define's text) */
<DEFVAL>"/*" { LEXP->m_defCmtSlash=false; yy_push_state(DEFCMT); yymore(); } /* Special comment parser */ <DEFVAL>"/*" { LEXP->m_defCmtSlash=false; yy_push_state(DEFCMT); yymore(); } /* Special comment parser */
<DEFVAL>"//"[^\n\r]*[\\]{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Spec says // not part of define value */ <DEFVAL>"//"[^\n\r]*[\\]{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Spec says // not part of define value */
<DEFVAL>"//"[^\n\r]* { return (VP_COMMENT);} <DEFVAL>"//"[^\n\r]* { return (VP_COMMENT);}
<DEFVAL>{drop} { } <DEFVAL>{drop} { }
<DEFVAL><<EOF>> { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } /* Technically illegal, but people complained */ <DEFVAL><<EOF>> { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } /* Technically illegal, but people complained */
<DEFVAL>{crnl} { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } <DEFVAL>{crnl} { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); }
<DEFVAL>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Return, but not \ is part of define value */ <DEFVAL>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\\\n",2); } /* Return, AND \ is part of define value */
<DEFVAL>[^\/\*\n\r\\]+ | <DEFVAL>[^\/\*\n\r\\]+ |
<DEFVAL>[\\][^\n\r] | <DEFVAL>[\\][^\n\r] |
<DEFVAL>. { appendDefValue(yytext,yyleng); } <DEFVAL>. { appendDefValue(yytext,yyleng); }
@@ -186,13 +194,15 @@ psl [p]sl
<DEFCMT>. { yymore(); } <DEFCMT>. { yymore(); }
<DEFCMT><<EOF>> { yyerrorf("EOF in '/* ... */' block comment\n"); yyleng=0; yyterminate(); } <DEFCMT><<EOF>> { yyerrorf("EOF in '/* ... */' block comment\n"); yyleng=0; yyterminate(); }
/* Define arguments */ /* Define arguments (use of a define) */
<ARGMODE>"/*" { yy_push_state(CMTMODE); yymore(); } <ARGMODE>"/*" { yy_push_state(CMTMODE); yymore(); }
<ARGMODE>"//"[^\n\r]* { return (VP_COMMENT);} <ARGMODE>"//"[^\n\r]* { return (VP_COMMENT);}
<ARGMODE>{drop} { } <ARGMODE>{drop} { }
<ARGMODE><<EOF>> { yyerrorf("EOF in define argument list\n"); yyleng = 0; yyterminate(); } <ARGMODE><<EOF>> { yyerrorf("EOF in define argument list\n"); yyleng = 0; yyterminate(); }
<ARGMODE>{crnl} { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); } <ARGMODE>{crnl} { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); }
<ARGMODE>{quote} { yy_push_state(STRMODE); yymore(); } <ARGMODE>{quote} { yy_push_state(STRMODE); yymore(); }
<ARGMODE>"`\\`\"" { appendDefValue(yytext,yyleng); } /* Literal text */
<ARGMODE>{tickquote} { return(VP_STRIFY); }
<ARGMODE>[{\[] { LEXP->m_parenLevel++; appendDefValue(yytext,yyleng); } <ARGMODE>[{\[] { LEXP->m_parenLevel++; appendDefValue(yytext,yyleng); }
<ARGMODE>[}\]] { LEXP->m_parenLevel--; appendDefValue(yytext,yyleng); } <ARGMODE>[}\]] { LEXP->m_parenLevel--; appendDefValue(yytext,yyleng); }
<ARGMODE>[(] { LEXP->m_parenLevel++; <ARGMODE>[(] { LEXP->m_parenLevel++;
@@ -215,7 +225,8 @@ psl [p]sl
} else { } else {
yy_pop_state(); return (VP_DEFARG); yy_pop_state(); return (VP_DEFARG);
}} }}
<ARGMODE>"`"{symb} { return (VP_DEFREF); } /* defref in defref */ <ARGMODE>"`"{symbdef} { appendDefValue(yytext,yyleng); } /* defref in defref - outer macro expands first */
<ARGMODE>"`"{symbdef}`` { appendDefValue(yytext,yyleng); } /* defref in defref - outer macro expands first */
<ARGMODE>[^\/\*\n\r\\(,){}\[\]\"`]+ | <ARGMODE>[^\/\*\n\r\\(,){}\[\]\"`]+ |
<ARGMODE>. { appendDefValue(yytext,yyleng); } <ARGMODE>. { appendDefValue(yytext,yyleng); }
@@ -258,12 +269,15 @@ psl [p]sl
<PSLMULM>"//"[^\n\r]* { return (VP_COMMENT); } /* Comments inside block comments get literal inclusion (later removal) */ <PSLMULM>"//"[^\n\r]* { return (VP_COMMENT); } /* Comments inside block comments get literal inclusion (later removal) */
/* Define calls */ /* Define calls */
<INITIAL,PSLMULM,PSLONEM>"`"{symb} { return (VP_DEFREF); } /* symbdef prevents normal lex rules from making `\`"foo a symbol {`"foo} instead of a BACKQUOTE */
<INITIAL,PSLMULM,PSLONEM>"`"{symbdef} { return (VP_DEFREF); }
<INITIAL,PSLMULM,PSLONEM>"`"{symbdef}`` { yyleng-=2; return (VP_DEFREF_JOIN); }
/* Generics */ /* Generics */
<INITIAL,PSLMULM>{crnl} { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); } <INITIAL,PSLMULM>{crnl} { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); }
<INITIAL,PSLMULM,PSLONEM><<EOF>> { yyterminate(); } /* A "normal" EOF */ <INITIAL,PSLMULM,PSLONEM><<EOF>> { yyterminate(); } /* A "normal" EOF */
<INITIAL,PSLMULM,PSLONEM>{symb} { return (VP_SYMBOL); } <INITIAL,PSLMULM,PSLONEM>{symb} { return (VP_SYMBOL); }
<INITIAL,PSLMULM,PSLONEM>{symb}`` { yyleng-=2; return (VP_SYMBOL_JOIN); }
<INITIAL,PSLMULM,PSLONEM>{wsn}+ { return (VP_WHITE); } <INITIAL,PSLMULM,PSLONEM>{wsn}+ { return (VP_WHITE); }
<INITIAL,PSLMULM,PSLONEM>{drop} { } <INITIAL,PSLMULM,PSLONEM>{drop} { }
<INITIAL,PSLMULM,PSLONEM>[\r] { } <INITIAL,PSLMULM,PSLONEM>[\r] { }
@@ -297,59 +311,177 @@ void V3PreLex::pushStateIncFilename() {
yymore(); yymore();
} }
void V3PreLex::initFirstBuffer() { void V3PreLex::debug(int level) { yy_flex_debug=level; }
// Called from constructor to make first buffer int V3PreLex::debug() { return yy_flex_debug; }
// yy_create_buffer also sets yy_fill_buffer=1 so reads from YY_INPUT
yy_switch_to_buffer(yy_create_buffer(NULL, YY_BUF_SIZE)); int V3PreLex::lex() {
m_bufferStack.push(currentBuffer()); V3PreLex::s_currentLexp = this; // Tell parser where to get/put data
yyrestart(NULL); m_tokFilelinep = curFilelinep(); // Remember token start location, may be updated by the lexer later
return yylex();
} }
size_t V3PreLex::inputToLex(char* buf, size_t max_size) { size_t V3PreLex::inputToLex(char* buf, size_t max_size) {
// We need a custom YY_INPUT because we can't use flex buffers. // We need a custom YY_INPUT because we can't use flex buffers.
// Flex buffers are limited to 2GB, and we can't chop into 2G pieces // Flex buffers are limited to 2GB, and we can't chop into 2G pieces
// because buffers can't end in the middle of tokens. // because buffers can't end in the middle of tokens.
// m_buffers only applies to the "base" buffer when there's no scanBytes outstanding // Note if we switched streams here (which we don't) "buf" would be
// It won't be called on scan_buffers as they don't have yy_fill_buffer set. // become a stale invalid pointer.
// //
//if (debug()) { cout<<"- pp:inputToLex ITL s="<<max_size<<" bs="<<m_bufferStack.size()<<endl; dumpSummary(); } VPreStream* streamp = curStreamp();
if (debug()>=10) { cout<<"- pp:inputToLex ITL s="<<max_size<<" bs="<<streamp->m_buffers.size()<<endl; dumpStack(); }
// For testing, use really small chunks // For testing, use really small chunks
//if (max_size > 13) max_size=13; //if (max_size > 13) max_size=13;
again:
size_t got = 0; size_t got = 0;
// Get from this stream
while (got < max_size // Haven't got enough while (got < max_size // Haven't got enough
&& !m_buffers.empty()) { // And something buffered && !streamp->m_buffers.empty()) { // And something buffered
string front = m_buffers.front(); m_buffers.pop_front(); string front = curStreamp()->m_buffers.front(); streamp->m_buffers.pop_front();
size_t len = front.length(); size_t len = front.length();
if (len > (max_size-got)) { // Front string too big if (len > (max_size-got)) { // Front string too big
string remainder = front.substr(max_size-got);
front = front.substr(0, max_size-got);
m_buffers.push_front(remainder); // Put back remainder for next time
len = (max_size-got); len = (max_size-got);
string remainder = front.substr(len);
front = front.substr(0, len);
streamp->m_buffers.push_front(remainder); // Put back remainder for next time
} }
strncpy(buf+got, front.c_str(), len); strncpy(buf+got, front.c_str(), len);
got += len; got += len;
} }
//if (debug()) { cout<<"- pp::inputToLex got="<<got<<" '"<<string(buf,got)<<"'"<<endl; } if (!got) { // end of stream; try "above" file
bool again=false;
string forceOut = endOfStream(again/*ref*/);
streamp = curStreamp(); // May have been updated
if (forceOut != "") {
if (forceOut.length() > max_size) {
yyerrorf("Output buffer too small for a `line");
} else {
got = forceOut.length();
strncpy(buf, forceOut.c_str(), got);
}
} else {
if (streamp->m_eof) {
if (yy_flex_debug) cout<<"- EOF\n";
}
got = 0; // 0=EOF/EOS - although got was already 0.
if (again) goto again;
}
}
if (debug()>=10) { cout<<"- pp::inputToLex got="<<got<<" '"<<string(buf,got)<<"'"<<endl; }
return got; return got;
} }
void V3PreLex::scanBytes(const char* strp, size_t len) { string V3PreLex::endOfStream(bool& againr) {
// Switch to file or next unputString
againr = false;
if (yy_flex_debug) cout<<"-EOS state="<<curStreamp()->m_termState<<" at "<<curFilelinep()<<endl;
if (curStreamp()->m_eof) return ""; // Don't delete the final "EOF" stream
bool exited_file = curStreamp()->m_file;
if (!exited_file) {
// Midpoint of stream, just change buffers
delete curStreamp();
m_streampStack.pop(); // Must work as size>1; EOF is entry 0
againr = true;
return "";
}
// Multiple steps because we need FLEX to see ending \n and EOS to end
// any illegal states, like an unterminated `protected region
else if (!curStreamp()->m_termState) {
// First shutdown phase for a file
// Terminate all files with a newline. This prevents problems if
// the user had a define without a terminating newline,
// otherwise the resumed file's next line would get tacked on.
// Also makes it likely the `line that changes files comes out
// immediately.
curStreamp()->m_termState = 1;
return "\n"; // Exit old file
}
else if (curStreamp()->m_termState == 1) {
// Now the EOF - can't be sent with other characters
curStreamp()->m_termState = 2;
return ""; // End of file
}
else if (curStreamp()->m_termState == 2) {
// Now ending `line
curStreamp()->m_termState = 3;
return curFilelinep()->lineDirectiveStrg(2); // Exit old file
}
else {
// Final shutdown phase for a stream, we can finally change the
// current fileline to the new stream
curStreamp()->m_termState = 0;
FileLine* filelinep = curFilelinep();
delete curStreamp();
m_streampStack.pop(); // Must work as size>1; EOF is entry 0
if (curStreamp()->m_eof) {
// EOF doesn't have a "real" fileline, but a linenumber of 0 from init time
// Inherit whatever we last parsed so it's more obvious.
curFilelinep(filelinep);
}
// The caller parser remembered the start location for the text we are parsing,
// but we've discovered there was a file switch along the way, so update it.
m_tokFilelinep = curFilelinep();
//
if (curStreamp()->m_eof) {
return "";
} else {
return curFilelinep()->lineDirectiveStrg(0); // Reenter resumed file
}
}
}
void V3PreLex::initFirstBuffer(FileLine* filelinep) {
// Called from constructor to make first buffer
// yy_create_buffer also sets yy_fill_buffer=1 so reads from YY_INPUT
VPreStream* streamp = new VPreStream(filelinep);
streamp->m_eof = true;
m_streampStack.push(streamp);
//
m_bufferState = yy_create_buffer(NULL, YY_BUF_SIZE);
yy_switch_to_buffer(m_bufferState);
yyrestart(NULL);
}
void V3PreLex::scanNewFile(FileLine* filelinep) {
// Called on new open file. scanBytesBack will be called next.
VPreStream* streamp = new VPreStream(filelinep);
m_tokFilelinep = curFilelinep();
streamp->m_file = true;
scanSwitchStream(streamp);
}
void V3PreLex::scanBytes(const string& str) {
// Note buffers also appended in ::scanBytesBack // Note buffers also appended in ::scanBytesBack
// Not "m_buffers.push_front(string(strp,len))" as we need a `define // Not "m_buffers.push_front(string(strp,len))" as we need a `define
// to take effect immediately, in the middle of the current buffer // to take effect immediately, in the middle of the current buffer
yy_scan_bytes(strp, len); // Also we don't use scan_bytes that would set yy_fill_buffer
m_bufferStack.push(currentBuffer()); // yy_scan_bytes makes new buffer // which would force Flex to bypass our YY_INPUT routine.
VPreStream* streamp = new VPreStream(curFilelinep());
streamp->m_buffers.push_front(str);
scanSwitchStream(streamp);
}
void V3PreLex::scanSwitchStream(VPreStream* streamp) {
curStreamp()->m_buffers.push_front(currentUnreadChars());
m_streampStack.push(streamp);
yyrestart(NULL);
} }
void V3PreLex::scanBytesBack(const string& str) { void V3PreLex::scanBytesBack(const string& str) {
// Initial creation, that will pull from YY_INPUT==inputToLex // Initial creation, that will pull from YY_INPUT==inputToLex
// Note buffers also appended in ::scanBytes // Note buffers also appended in ::scanBytes
m_buffers.push_back(str); if (curStreamp()->m_eof) yyerrorf("scanBytesBack without being under scanNewFile");
curStreamp()->m_buffers.push_back(str);
} }
void V3PreLex::appendDefValue(const char* textp, size_t len) { string V3PreLex::currentUnreadChars() {
// Append given text to current definition value being formed // WARNING - Peeking at internals
m_defValue.append(textp,len); ssize_t left = (yy_n_chars - (yy_c_buf_p -currentBuffer()->yy_ch_buf));
if (left > 0) { // left may be -1 at EOS
*(yy_c_buf_p) = (yy_hold_char);
return string(yy_c_buf_p, left);
} else {
return "";
}
} }
YY_BUFFER_STATE V3PreLex::currentBuffer() { YY_BUFFER_STATE V3PreLex::currentBuffer() {
@@ -361,29 +493,54 @@ int V3PreLex::currentStartState() {
} }
void V3PreLex::lineDirective(const char* textp) { void V3PreLex::lineDirective(const char* textp) {
m_curFilelinep->lineDirective(textp); curFilelinep()->lineDirective(textp, m_enterExit/*ref*/);
// Make sure we have a dependency on whatever file was specified // Make sure we have a dependency on whatever file was specified
V3File::addSrcDepend(m_curFilelinep->filename()); V3File::addSrcDepend(curFilelinep()->filename());
} }
void V3PreLex::dumpSummary() { void V3PreLex::dumpSummary() {
cout<<"- pp::dumpSummary curBuf="<<(void*)(currentBuffer()) cout<<"- pp::dumpSummary curBuf="<<(void*)(currentBuffer());
<<" nBuf="<<m_bufferStack.size() #ifdef FLEX_DEBUG // Else peeking at internals may cause portability issues
<<" yyfill="<<currentBuffer()->yy_fill_buffer<<endl; ssize_t left = (yy_n_chars
- (yy_c_buf_p
-currentBuffer()->yy_ch_buf));
cout<<" left="<<dec<<left;
#endif
cout<<endl;
} }
void V3PreLex::dumpStack() { void V3PreLex::dumpStack() {
// For debug use // For debug use
dumpSummary(); dumpSummary();
stack<YY_BUFFER_STATE> tmpstack = m_bufferStack; stack<VPreStream*> tmpstack = LEXP->m_streampStack;
printf(" bufferStack[%p]:",this);
while (!tmpstack.empty()) { while (!tmpstack.empty()) {
printf(" %p",tmpstack.top()); VPreStream* streamp = tmpstack.top();
cout<<"- bufferStack["<<(void*)(streamp)<<"]: "
<<" at="<<streamp->m_curFilelinep
<<" nBuf="<<streamp->m_buffers.size()
<<" size0="<<(streamp->m_buffers.empty() ? 0 : streamp->m_buffers.front().length())
<<(streamp->m_eof?" [EOF]":"")
<<(streamp->m_file?" [FILE]":"");
cout<<endl;
tmpstack.pop(); tmpstack.pop();
} }
printf("\n");
} }
string V3PreLex::cleanDbgStrg(const string& in) {
string out = in;
string::size_type pos;
while ((pos=out.find("\n")) != string::npos) { out.replace(pos, 1, "\\n"); }
while ((pos=out.find("\r")) != string::npos) { out.replace(pos, 1, "\\r"); }
return out;
}
void V3PreLex::unused() {
if (0) {
// Prevent unused warnings
yy_top_state();
}
}
/*################################################################### /*###################################################################
* Local Variables: * Local Variables:
* mode: C++ * mode: C++
+469 -220
View File
File diff suppressed because it is too large Load Diff
+14 -6
View File
@@ -32,6 +32,9 @@
#include <list> #include <list>
#include <iostream> #include <iostream>
// Compatibility with Verilog-Perl's preprocessor
#define fatalSrc(msg) v3fatalSrc(msg)
class V3InFilter; class V3InFilter;
class V3PreProc { class V3PreProc {
@@ -40,14 +43,14 @@ class V3PreProc {
protected: protected:
// STATE // STATE
FileLine* m_fileline; // Last token's starting point
int m_debug; // Debugging int m_debug; // Debugging
public: public:
// CONSTANTS // CONSTANTS
enum MiscConsts { enum MiscConsts {
DEFINE_RECURSION_LEVEL_MAX = 50, // How many `def substitutions before an error DEFINE_RECURSION_LEVEL_MAX = 1000, // How many `def substitutions before an error
INCLUDE_DEPTH_MAX = 500 // How many `includes deep before an error INCLUDE_DEPTH_MAX = 500, // How many `includes deep before an error
NEWLINES_VS_TICKLINE = 20 // Use `line in place of this many newlines
}; };
// ACCESSORS // ACCESSORS
@@ -60,11 +63,12 @@ public:
int debug() const { return m_debug; } int debug() const { return m_debug; }
void debug(int level) { m_debug = level; } void debug(int level) { m_debug = level; }
FileLine* fileline() { return m_fileline; } // File/Line number for last getline call FileLine* fileline(); ///< File/Line number for last getline call
// CONTROL METHODS // CONTROL METHODS
// These options control how the parsing proceeds // These options control how the parsing proceeds
int keepComments() { return 2; } // Return comments, 0=no, 1=yes, 2=callback int keepComments() { return 2; } // Return comments, 0=no, 1=yes, 2=callback
bool keepWhitespace() { return false; }
bool lineDirectives() { return true; } // Insert `line directives bool lineDirectives() { return true; } // Insert `line directives
bool pedantic() { return false; } // Obey standard; Don't substitute `error bool pedantic() { return false; } // Obey standard; Don't substitute `error
static bool optPsl(); static bool optPsl();
@@ -83,12 +87,16 @@ public:
} }
virtual string removeDefines(const string& text)=0; // Remove defines in a text string virtual string removeDefines(const string& text)=0; // Remove defines in a text string
// UTILITIES
void error(string msg) { fileline()->v3error(msg); } ///< Report a error
void fatal(string msg) { fileline()->v3fatalSrc(msg); } ///< Report a fatal error
protected: protected:
// CONSTUCTORS // CONSTUCTORS
V3PreProc(FileLine* fl) { V3PreProc() {
m_fileline=fl;
m_debug=0; m_debug=0;
}; };
void configure(FileLine* fl);
public: public:
static V3PreProc* createPreProc(FileLine* fileline); static V3PreProc* createPreProc(FileLine* fileline);
virtual ~V3PreProc() {} virtual ~V3PreProc() {}
+1
View File
@@ -1034,6 +1034,7 @@ private:
AstNodeFTask* funcp = nodep->taskp(); AstNodeFTask* funcp = nodep->taskp();
if (!funcp) nodep->v3fatalSrc("unlinked"); if (!funcp) nodep->v3fatalSrc("unlinked");
if (!funcp->isFunction()) nodep->v3fatalSrc("func reference to non-function"); if (!funcp->isFunction()) nodep->v3fatalSrc("func reference to non-function");
if (!m_scopep) nodep->v3fatalSrc("func ref not under scope");
// Inline func refs in the function // Inline func refs in the function
iterateIntoFTask(funcp); iterateIntoFTask(funcp);
// Create output variable // Create output variable
+6 -4
View File
@@ -69,10 +69,12 @@ private:
string prettyName = nodep->prettyName(); string prettyName = nodep->prettyName();
if (!nodep->isTrace()) if (!nodep->isTrace())
return "Verilator trace_off"; return "Verilator trace_off";
if (prettyName.c_str()[0] == '_') if (!v3Global.opt.traceUnderscore()) {
return "Leading underscore"; if (prettyName.c_str()[0] == '_')
if (prettyName.find("._") != string::npos) return "Leading underscore";
return "Inlined leading underscore"; if (prettyName.find("._") != string::npos)
return "Inlined leading underscore";
}
if (nodep->width() > 256) return "Wide bus > 256 bits"; if (nodep->width() > 256) return "Wide bus > 256 bits";
if (nodep->arrayElements() > 32) return "Wide memory > 32 ents"; if (nodep->arrayElements() > 32) return "Wide memory > 32 ents";
if (!(nodep->dtypeSkipRefp()->castBasicDType() if (!(nodep->dtypeSkipRefp()->castBasicDType()
+1 -1
View File
@@ -25,7 +25,7 @@
//********************************************************************** //**********************************************************************
//**** Version and host name //**** Version and host name
#define DTVERSION "Verilator 3.802 2010/05/01" #define DTVERSION "Verilator 3.804 2010/07/10"
//********************************************************************** //**********************************************************************
//**** Functions //**** Functions
+3 -2
View File
@@ -42,7 +42,7 @@ extern void yyerrorf(const char* format, ...);
//====================================================================== //======================================================================
#define NEXTLINE() {PARSEP->incLineno();} #define NEXTLINE() {PARSEP->linenoInc();}
#define CRELINE() (PARSEP->copyOrSameFileLine()) #define CRELINE() (PARSEP->copyOrSameFileLine())
#define FL { yylval.fl = CRELINE(); } #define FL { yylval.fl = CRELINE(); }
@@ -53,7 +53,8 @@ extern void yyerrorf(const char* format, ...);
void V3ParseImp::ppline (const char* textp) { void V3ParseImp::ppline (const char* textp) {
// Handle `line directive // Handle `line directive
fileline()->lineDirective(textp); int enterExit;
fileline()->lineDirective(textp, enterExit/*ref*/);
} }
void V3ParseImp::verilatorCmtLint(const char* textp, bool warnOff) { void V3ParseImp::verilatorCmtLint(const char* textp, bool warnOff) {
+1 -1
View File
@@ -1864,7 +1864,7 @@ statement_item<nodep>: // IEEE: statement_item
// // for's first ';' is in for_initalization // // for's first ';' is in for_initalization
| yFOR '(' for_initialization expr ';' for_stepE ')' stmtBlock | yFOR '(' for_initialization expr ';' for_stepE ')' stmtBlock
{ $$ = new AstBegin($1,"",$3); $3->addNext(new AstWhile($1, $4,$8,$6)); } { $$ = new AstBegin($1,"",$3); $3->addNext(new AstWhile($1, $4,$8,$6)); }
| yDO stmtBlock yWHILE '(' expr ')' { $$ = $2->cloneTree(true); $$->addNext(new AstWhile($1,$5,$2));} | yDO stmtBlock yWHILE '(' expr ')' ';' { $$ = $2->cloneTree(true); $$->addNext(new AstWhile($1,$5,$2));}
//UNSUP yFOREACH '(' idClassForeach/*array_id[loop_variables]*/ ')' stmt { UNSUP } //UNSUP yFOREACH '(' idClassForeach/*array_id[loop_variables]*/ ')' stmt { UNSUP }
// //
// // IEEE: jump_statement // // IEEE: jump_statement
+53
View File
@@ -0,0 +1,53 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2010 by Wilson Snyder.
#include <verilated.h>
#ifdef T_CLK_2IN_VEC
# include "Vt_clk_2in_vec.h"
#else
# include "Vt_clk_2in.h"
#endif
unsigned int main_time = false;
double sc_time_stamp () {
return main_time;
}
VM_PREFIX* topp = NULL;
void clockit(int clk1, int clk0) {
#ifdef T_CLK_2IN_VEC
topp->clks = clk1<<1 | clk0;
#else
topp->c1 = clk1;
topp->c0 = clk0;
#endif
#ifdef TEST_VERBOSE
printf("[%d] c1=%d c0=%d\n", main_time, clk1, clk0);
#endif
topp->eval();
main_time++;
}
int main (int argc, char *argv[]) {
topp = new VM_PREFIX;
topp->check = 0;
clockit(0,0);
Verilated::debug(0);
for (int i = 0; i < 2; i++) {
clockit(0, 0);
clockit(0, 1);
clockit(1, 1);
clockit(0, 0);
clockit(1, 1);
clockit(1, 0);
clockit(0, 0);
}
topp->check = 1;
clockit(0,0);
}
+20
View File
@@ -0,0 +1,20 @@
#!/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 (
make_top_shell => 0,
make_main => 0,
v_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp"],
) if $Self->{v3};
execute (
check_finished=>1,
) if $Self->{v3};
ok(1);
1;
+70
View File
@@ -0,0 +1,70 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2010 by Wilson Snyder.
module t (
`ifdef T_CLK_2IN_VEC
input [1:0] clks,
`else
input c0,
input c1,
`endif
input check
);
`ifdef T_CLK_2IN_VEC
wire c0 = clks[0];
wire c1 = clks[1];
`endif
integer p0 = 0;
integer p1 = 0;
integer p01 = 0;
integer n0 = 0;
integer n1 = 0;
integer n01 = 0;
`define display_counts(text) begin \
$write("[%0t] ",$time); \
`ifdef T_CLK_2IN_VEC $write(" 2v "); `endif \
$write(text); \
$write(": %0d %0d %0d %0d %0d %0d\n", p0, p1, p01, n0, n1, n01); \
end
always @ (posedge c0) begin
p0 = p0 + 1; // Want blocking, so don't miss clock counts
`ifdef TEST_VERBOSE `display_counts("posedge 0"); `endif
end
always @ (posedge c1) begin
p1 = p1 + 1;
`ifdef TEST_VERBOSE `display_counts("posedge 1"); `endif
end
always @ (posedge c0 or posedge c1) begin
p01 = p01 + 1;
`ifdef TEST_VERBOSE `display_counts("posedge *"); `endif
end
always @ (negedge c0) begin
n0 = n0 + 1;
`ifdef TEST_VERBOSE `display_counts("negedge 0"); `endif
end
always @ (negedge c1) begin
n1 = n1 + 1;
`ifdef TEST_VERBOSE `display_counts("negedge 1"); `endif
end
always @ (negedge c0 or negedge c1) begin
n01 = n01 + 1;
`ifdef TEST_VERBOSE `display_counts("negedge *"); `endif
end
always @ (posedge check) begin
if (p0!=4) $stop;
if (p1!=4) $stop;
if (p01!=6) $stop;
if (n0!=4) $stop;
if (n1!=4) $stop;
if (n01!=6) $stop;
$write("*-* All Finished *-*\n");
end
endmodule
+22
View File
@@ -0,0 +1,22 @@
#!/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.
top_filename("t/t_clk_2in.v");
compile (
make_top_shell => 0,
make_main => 0,
v_flags2 => ["+define+T_CLK_2IN_VEC=1 --exe $Self->{t_dir}/t_clk_2in.cpp"],
) if $Self->{v3};
execute (
check_finished=>1,
) if $Self->{v3};
ok(1);
1;
+21
View File
@@ -0,0 +1,21 @@
#!/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.
$Self->{vlt} or $Self->skip("Verilator only test");
compile (
v_flags2 => ["--debug-core-dump"],
fails=>$Self->{v3},
expect=>
'%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt
%Error: Command Failed.*',
);
ok(1);
1;
+1 -1
View File
@@ -10,7 +10,7 @@ module t (/*AUTOARG*/
input clk; input clk;
reg _ranit; reg _ranit;
`include "t_initial_inc.v" `include "t_initial_inc.vh"
// surefire lint_off STMINI // surefire lint_off STMINI
initial assign user_loaded_value = 1; initial assign user_loaded_value = 1;
+18
View File
@@ -0,0 +1,18 @@
#!/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 (
);
execute (
check_finished=>1,
);
ok(1);
1;
+55
View File
@@ -0,0 +1,55 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2010 by Wilson Snyder.
module t (/*AUTOARG*/);
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [31:0] O_out; // From test of Test.v
// End of automatics
Test test (/*AUTOINST*/
// Outputs
.O_out (O_out[31:0]));
initial begin
if (O_out != 32'h4) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
module Test
(
output [31:0] O_out
);
test
#(
.pFOO(5),
.pBAR(2)
) U_test
(
.O_out(O_out)
);
endmodule
module test
#(parameter pFOO = 7,
parameter pBAR = 3,
parameter pBAZ = ceiling(pFOO, pBAR)
)
(
output [31:0] O_out
);
assign O_out = pBAZ;
function integer ceiling;
input [31:0] x, y;
ceiling = ((x%y == 0) ? x/y : (x/y)+1) + 1;
endfunction
endmodule
+16 -5
View File
@@ -8,45 +8,56 @@
`line 10 "t/t_pipe_filter.v" 0
example line 10; example line 10;
example line 11; example line 11;
`line 13 "t/t_pipe_filter.v" 0
`line 13 "t/t_pipe_filter.v" 0 `line 13 "t/t_pipe_filter.v" 0
`line 1 "t/t_pipe_filter_inc.v" 1 `line 1 "t/t_pipe_filter_inc.vh" 1
int lint_off_line_7 = 1; int lint_off_line_7 = 1;
`line 2 "t/t_pipe_filter.v" 0
int lint_off_line_8 = 1; int lint_off_line_8 = 1;
`line 8 "t/t_pipe_filter.v" 0
inc line 6; inc line 6;
inc line 7; inc line 7;
inc line 8; inc line 8;
inc line 9; inc line 9;
`line 12 "t/t_pipe_filter_inc.v" 2
`line 13 "t/t_pipe_filter_inc.vh" 2
`line 13 "t/t_pipe_filter.v" 0 `line 13 "t/t_pipe_filter.v" 0
`line 15 "t/t_pipe_filter.v" 0
`line 15 "t/t_pipe_filter.v" 0 `line 15 "t/t_pipe_filter.v" 0
`line 1 "t/t_pipe_filter_inc.v" 1 `line 1 "t/t_pipe_filter_inc.vh" 1
int lint_off_line_7 = 1; int lint_off_line_7 = 1;
`line 2 "t/t_pipe_filter.v" 0
int lint_off_line_8 = 1; int lint_off_line_8 = 1;
`line 8 "t/t_pipe_filter.v" 0
inc line 6; inc line 6;
inc line 7; inc line 7;
inc line 8; inc line 8;
inc line 9; inc line 9;
`line 12 "t/t_pipe_filter_inc.v" 2
`line 13 "t/t_pipe_filter_inc.vh" 2
`line 15 "t/t_pipe_filter.v" 0 `line 15 "t/t_pipe_filter.v" 0
`line 17 "t/t_pipe_filter.v" 0
example line 15; example line 15;
example line 16; example line 16;
`line 19 "t/t_pipe_filter.v" 2
`line 20 "t/t_pipe_filter.v" 2
+2 -2
View File
@@ -10,9 +10,9 @@
example line 10; example line 10;
example line 11; example line 11;
`include "t_pipe_filter_inc.v" `include "t_pipe_filter_inc.vh"
// Twice to check caching of includes // Twice to check caching of includes
`include "t_pipe_filter_inc.v" `include "t_pipe_filter_inc.vh"
example line 15; example line 15;
example line 16; example line 16;
+11 -9
View File
@@ -13,21 +13,23 @@ compile (
execute ( execute (
check_finished=>1, check_finished=>1,
expect=>quotemeta( expect=>quotemeta(
'pre thrupre thrumid thrupost post: "right side" qq{pre thrupre thrumid thrupost post: "right side"
left side: "right side" left side: "right side"
left side : "right side " left side: "right side"
left_side : "right_side " left_side: "right_side"
na : "right_side " na: "right_side"
prep ( midp1 left_side midp2 ( outp ) ) : "right_side " prep ( midp1 left_side midp2 ( outp ) ): "right_side"
na: "nana" na: "nana"
`ls `rs : "`ls `rs " left_side right_side: "left_side right_side"
left side: "right side"
: "" : ""
left side: "right side" left side: "right side"
left side : "right side " left side: "right side"
standalone
twoline: "first second" twoline: "first second"
Line 38 File "t/t_pp_display.v" Line 49 File "t/t_pp_display.v"
*-* All Finished *-* *-* All Finished *-*
')); }));
ok(1); ok(1);
1; 1;
+11
View File
@@ -17,6 +17,7 @@ module t;
`define thru(x) x `define thru(x) x
`define thruthru `ls `rs // Doesn't expand `define thruthru `ls `rs // Doesn't expand
`define msg(x,y) `"x: `\`"y`\`"`" `define msg(x,y) `"x: `\`"y`\`"`"
`define left(m,left) m // The 'left' as the variable name shouldn't match the "left" in the `" string
initial begin initial begin
//$display(`msg( \`, \`)); // Illegal //$display(`msg( \`, \`)); // Illegal
$display(`msg(pre `thru(thrupre `thru(thrumid) thrupost) post,right side)); $display(`msg(pre `thru(thrupre `thru(thrumid) thrupost) post,right side));
@@ -27,13 +28,23 @@ module t;
$display(`msg( prep ( midp1 `ls midp2 ( outp ) ) , `rs )); $display(`msg( prep ( midp1 `ls midp2 ( outp ) ) , `rs ));
$display(`msg(`noarg,`noarg`noarg)); $display(`msg(`noarg,`noarg`noarg));
$display(`msg( `thruthru , `thruthru )); // Results vary between simulators $display(`msg( `thruthru , `thruthru )); // Results vary between simulators
$display(`left(`msg( left side , right side ), left_replaced));
//$display(`msg( `"tickquoted_left`", `"tickquoted_right`" )); // Syntax error
`ifndef VCS // Sim bug - wrong number of arguments, but we're right
$display(`msg(`thru(),)); // Empty $display(`msg(`thru(),)); // Empty
`endif
$display(`msg(`thru(left side),`thru(right side))); $display(`msg(`thru(left side),`thru(right side)));
$display(`msg( `thru( left side ) , `thru( right side ) )); $display(`msg( `thru( left side ) , `thru( right side ) ));
`ifndef NC
$display(`"standalone`");
`endif
`ifdef VERILATOR
// Illegal on some simulators, as the "..." crosses two lines
`define twoline first \ `define twoline first \
second second
$display(`msg(twoline, `twoline)); $display(`msg(twoline, `twoline));
`endif
$display("Line %0d File \"%s\"",`__LINE__,`__FILE__); $display("Line %0d File \"%s\"",`__LINE__,`__FILE__);
+1 -1
View File
@@ -3,7 +3,7 @@
// This file ONLY is placed into the Public Domain, for any use, // This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2008 by Wilson Snyder. // without warranty, 2008 by Wilson Snyder.
`include "t_pp_lib_inc.v" `include "t_pp_lib_inc.vh"
module t(); module t();
wire [`WIDTH-1:0] a; wire [`WIDTH-1:0] a;
library_cell n1(a); library_cell n1(a);
+461 -63
View File
@@ -5,142 +5,230 @@
`line 7 "t/t_preproc.v" 0
`line 9 "t/t_preproc.v" 0 `line 7 "t/t_preproc.v" 0
`line 1 "t/t_preproc_inc2.v" 1 `line 1 "t/t_preproc_inc2.vh" 1
`line 3 "t/t_preproc.v" 0
`line 4 "t/t_preproc.v" 0
At file "t/t_preproc_inc2.v" line 4 At file "t/t_preproc_inc2.vh" line 4
`line 6 "t/t_preproc_inc2.v" 0 `line 6 "t/t_preproc_inc2.vh" 0
`line 1 "t/t_preproc_inc3.v" 1 `line 1 "t/t_preproc_inc3.vh" 1
`line 2 "inc3_a_filename_from_line_directive" 0 `line 2 "inc3_a_filename_from_line_directive" 0
`line 6 "inc3_a_filename_from_line_directive" 0
At file "inc3_a_filename_from_line_directive" line 10 At file "inc3_a_filename_from_line_directive" line 10
`line 12 "inc3_a_filename_from_line_directive" 0
`line 13 "inc3_a_filename_from_line_directive" 0
`line 15 "inc3_a_filename_from_line_directive" 0
`line 17 "inc3_a_filename_from_line_directive" 0
`line 18 "inc3_a_filename_from_line_directive" 2 `line 19 "inc3_a_filename_from_line_directive" 2
`line 6 "t/t_preproc_inc2.v" 0 `line 6 "t/t_preproc_inc2.vh" 0
`line 7 "t/t_preproc_inc2.v" 2
`line 9 "t/t_preproc.v" 0 `line 8 "t/t_preproc_inc2.vh" 2
`line 7 "t/t_preproc.v" 0
`line 12 "t/t_preproc.v" 0
/*verilator pass_thru comment*/ /*verilator pass_thru comment*/
`line 14 "t/t_preproc.v" 0
/*verilator pass_thru_comment2*/ /*verilator pass_thru_comment2*/
`line 19 "t/t_preproc.v" 0
`line 22 "t/t_preproc.v" 0
wire [3:0] q = { wire [3:0] q = {
1'b1 ,
1'b0 ,
1'b1 ,
1'b1 1'b1
`line 25 "t/t_preproc.v" 0
,
`line 26 "t/t_preproc.v" 0
1'b0 ,
1'b1
`line 27 "t/t_preproc.v" 0
,
1'b1
`line 28 "t/t_preproc.v" 0
}; };
`line 29 "t/t_preproc.v" 0
text. text.
`line 31 "t/t_preproc.v" 0
foo bar foo bar
foobar2 foobar2
`line 36 "t/t_preproc.v" 0
`line 40 "t/t_preproc.v" 0
first part second part third part `line 46 "t/t_preproc.v" 0
Line_Preproc_Check 49 first part
`line 46 "t/t_preproc.v" 0
second part
`line 46 "t/t_preproc.v" 0
third part
{
`line 47 "t/t_preproc.v" 0
a,
`line 47 "t/t_preproc.v" 0
b,
`line 47 "t/t_preproc.v" 0
c}
Line_Preproc_Check 48
`line 52 "t/t_preproc.v" 0
`line 54 "t/t_preproc.v" 0
deep deep deep deep
`line 58 "t/t_preproc.v" 0
"Inside: `nosubst" "Inside: `nosubst"
"`nosubst" "`nosubst"
`line 63 "t/t_preproc.v" 0
x y LLZZ x y x y LLZZ x y
p q LLZZ p q r s LLZZ r s LLZZ p q LLZZ p q r s LLZZ r s p q LLZZ p q r s LLZZ r s LLZZ p q LLZZ p q r s LLZZ r s
firstline comma","line LLZZ firstline comma","line `line 69 "t/t_preproc.v" 0
firstline comma","line LLZZ firstline comma","line
`line 71 "t/t_preproc.v" 0
x y LLZZ "a" y x y LLZZ "a" y
`line 74 "t/t_preproc.v" 0
(a,b)(a,b) (a,b)(a,b)
`line 77 "t/t_preproc.v" 0
$display("left side: \"right side\"") $display("left side: \"right side\"")
`line 80 "t/t_preproc.v" 0
bar_suffix bar_suffix more
`line 83 "t/t_preproc.v" 0
$c("Zap(\"",bug1,"\");");;
$c("Zap(\"","bug2","\");");; `line 85 "t/t_preproc.v" 0
$c("Zap(\"",bug1,"\");");;
`line 86 "t/t_preproc.v" 0
$c("Zap(\"","bug2","\");");;
`line 94 "t/t_preproc.v" 0
initial begin
$display("pre thrupre thrumid thrupost post: \"right side\"");
$display("left side: \"right side\"");
$display("left side: \"right side\"");
$display("left_side: \"right_side\"");
$display("na: \"right_side\"");
$display("prep ( midp1 left_side midp2 ( outp ) ): \"right_side\"");
$display("na: \"nana\"");
$display("left_side right_side: \"left_side right_side\"");
$display(": \"\"");
$display("left side: \"right side\"");
$display("left side: \"right side\"");
$display("standalone");
`line 115 "t/t_preproc.v" 0
$display("twoline: \"first second\"");
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
`line 128 "t/t_preproc.v" 0
wire tmp_d1 = d1; wire tmp_o1 = tmp_d1 + 1; assign o1 = tmp_o1 ; `line 133 "t/t_preproc.v" 0
wire tmp_d2 = d2 ; wire tmp_o2 = tmp_d2 + 1; assign o2 = tmp_o2 ; module add1 ( input wire d1, output wire o1);
`line 134 "t/t_preproc.v" 0
wire tmp_d1 = d1;
`line 134 "t/t_preproc.v" 0
wire tmp_o1 = tmp_d1 + 1;
`line 134 "t/t_preproc.v" 0
assign o1 = tmp_o1 ;
endmodule
module add2 ( input wire d2, output wire o2);
`line 137 "t/t_preproc.v" 0
wire tmp_d2 = d2;
`line 137 "t/t_preproc.v" 0
wire tmp_o2 = tmp_d2 + 1;
`line 137 "t/t_preproc.v" 0
assign o2 = tmp_o2 ;
endmodule
`line 140 "t/t_preproc.v" 0
@@ -148,13 +236,37 @@ wire tmp_d2 = d2 ; wire tmp_o2 = tmp_d2 + 1; assign o2 = tmp_o2 ;
`line 147 "t/t_preproc.v" 0
generate for (i=0; i<(3); i=i+1) begin psl cover { m5k.f .ctl._ctl_mvldx_m1.d[i] & ~m5k.f .ctl._ctl_mvldx_m1.q[i] & !m5k.f .ctl._ctl_mvldx_m1.cond & ((m5k.f .ctl.alive & m5k.f .ctl.alive_m1))} report "fondNoRise: m5kc_fcl._ctl_mvldx_m1"; psl cover { ~m5k.f .ctl._ctl_mvldx_m1.d[i] & m5k.f .ctl._ctl_mvldx_m1.q[i] & !m5k.f .ctl._ctl_mvldx_m1.cond & ((m5k.f .ctl.alive & m5k.f .ctl.alive_m1))} report "fondNoFall: m5kc_fcl._ctl_mvldx_m1"; end endgenerate `line 151 "t/t_preproc.v" 0
`line 151 "t/t_preproc.v" 0
generate for (i=0; i<(3); i=i+1) begin
`line 151 "t/t_preproc.v" 0
psl cover { m5k.f .ctl._ctl_mvldx_m1.d[i] & ~m5k.f .ctl._ctl_mvldx_m1.q[i] & !m5k.f .ctl._ctl_mvldx_m1.cond & ((m5k.f .ctl.alive & m5k.f .ctl.alive_m1))} report "fondNoRise: m5kc_fcl._ctl_mvldx_m1";
`line 151 "t/t_preproc.v" 0
psl cover { ~m5k.f .ctl._ctl_mvldx_m1.d[i] & m5k.f .ctl._ctl_mvldx_m1.q[i] & !m5k.f .ctl._ctl_mvldx_m1.cond & ((m5k.f .ctl.alive & m5k.f .ctl.alive_m1))} report "fondNoFall: m5kc_fcl._ctl_mvldx_m1";
`line 151 "t/t_preproc.v" 0
end endgenerate
`line 155 "t/t_preproc.v" 0
module prot();
`protected
I!#r#e6<_Q{{E2+]I3<[3s)1@D|'E''i!O?]jD>Jo_![Cl)
#nj1]p,3^1~,="E@QZB\T)eU\pC#C|7=\$J$##A[@-@{Qk]
`endprotected
`line 160 "t/t_preproc.v" 0
endmodule
`line 165 "t/t_preproc.v" 0
@@ -163,24 +275,74 @@ wire tmp_d2 = d2 ; wire tmp_o2 = tmp_d2 + 1; assign o2 = tmp_o2 ;
`line 173 "t/t_preproc.v" 0
begin addr <= (({regs[6], regs[7]} + 1)); rd <= 1; end and begin addr <= (({regs[6], regs[7]})); wdata <= (rdata); wr <= 1; end begin addr <= (({regs[6], regs[7]} + 1)); rd <= 1; end and begin addr <= (({regs[6], regs[7]})); wdata <= (rdata); wr <= 1; end
begin addr <= ({regs[6], regs[7]} + 1); rd <= 1; end begin addr <= ({regs[6], regs[7]} + 1); rd <= 1; end
begin addr <= ({regs[6], regs[7]}); wdata <= (rdata); wr <= 1; end begin addr <= ({regs[6], regs[7]}); wdata <= (rdata); wr <= 1; end more
`line 179 "t/t_preproc.v" 0
`line 180 "t/t_preproc.v" 0
`line 1 "t/t_preproc_inc4.vh" 1
`line 3 "t/t_preproc.v" 0
`line 5 "t/t_preproc.v" 0
`line 7 "t/t_preproc_inc4.vh" 2
`line 180 "t/t_preproc.v" 0
`line 181 "t/t_preproc.v" 0
`line 184 "t/t_preproc.v" 0
`line 186 "t/t_preproc.v" 0
`line 193 "t/t_preproc.v" 0
$blah("ab,cd","e,f");
$blah(this.logfile,vec);
$blah(this.logfile,vec[1,2,3]);
$blah(this.logfile,{blah.name(), " is not foo"});
`line 202 "t/t_preproc.v" 0
`pragma foo = 1
`default_nettype none
`default_nettype uwire
`line 209 "t/t_preproc.v" 0
`line 130 "t/t_preproc.v" 0 `line 213 "t/t_preproc.v" 0
Line_Preproc_Check 213
Line_Preproc_Check 131
`line 218 "t/t_preproc.v" 0
@@ -188,11 +350,35 @@ Line_Preproc_Check 131
(x,y ) `line 225 "t/t_preproc.v" 0
Line_Preproc_Check 144 (x,y)
Line_Preproc_Check 226
`line 231 "t/t_preproc.v" 0
beginend
beginend
"beginend"
`line 241 "t/t_preproc.v" 0
`\esc`def
`line 245 "t/t_preproc.v" 0
Not a \`define
`line 249 "t/t_preproc.v" 0
@@ -201,11 +387,23 @@ x,y)--bee submacro has comma paren
`line 257 "t/t_preproc.v" 0
$display("bits %d %d", $bits(foo), `10); $display("bits %d %d", $bits(foo), `10);
`line 262 "t/t_preproc.v" 0
`line 265 "t/t_preproc.v" 0
`line 270 "t/t_preproc.v" 0
@@ -218,12 +416,30 @@ $display("bits %d %d", $bits(foo), `10);
`line 282 "t/t_preproc.v" 0
`line 173 "t/t_preproc.v" 0
`line 173 "t/t_preproc.v" 0
assign a3 = ~b3 ;
`line 282 "t/t_preproc.v" 0
`line 282 "t/t_preproc.v" 0
`line 282 "t/t_preproc.v" 0
`line 282 "t/t_preproc.v" 0
`line 282 "t/t_preproc.v" 0
`line 282 "t/t_preproc.v" 0
`line 282 "t/t_preproc.v" 0
`line 282 "t/t_preproc.v" 0
`line 282 "t/t_preproc.v" 0
assign a3 = ~b3 ;
`line 282 "t/t_preproc.v" 0
`line 284 "t/t_preproc.v" 0
\ \
@@ -233,32 +449,56 @@ $display("bits %d %d", $bits(foo), `10);
def foo `line 293 "t/t_preproc.v" 0
`line 293 "t/t_preproc.v" 0
`line 293 "t/t_preproc.v" 0
`line 293 "t/t_preproc.v" 0
def i
`line 297 "t/t_preproc.v" 0
`line 301 "t/t_preproc.v" 0
`line 307 "t/t_preproc.v" 0
1 /*verilator NOT IN DEFINE*/ (nodef) 1 /*verilator NOT IN DEFINE*/ (nodef)
2 /*verilator PART OF DEFINE*/ (hasdef) 2 /*verilator PART OF DEFINE*/ (hasdef)
3 /*verilator NOT PART OF DEFINE*/ (nodef) 3
4 /*verilator PART OF DEFINE*/ (nodef) `line 309 "t/t_preproc.v" 0
5 also in also3 (nodef) /*verilator NOT PART
OF DEFINE*/ (nodef)
`line 310 "t/t_preproc.v" 0
4
`line 310 "t/t_preproc.v" 0
/*verilator PART
OF DEFINE*/ (nodef)
`line 311 "t/t_preproc.v" 0
5 also in
`line 311 "t/t_preproc.v" 0
also3 (nodef)
HAS a NEW LINE HAS a NEW
`line 314 "t/t_preproc.v" 0
LINE
`line 318 "t/t_preproc.v" 0
@@ -272,36 +512,194 @@ HAS a NEW LINE
`line 331 "t/t_preproc.v" 0
`line 334 "t/t_preproc.v" 0
EXP: clxx_scen EXP: clxx_scen
clxx_scen clxx_scen
EXP: clxx_scen EXP: clxx_scen
"clxx_scen" "clxx_scen"
EXP: do if (start("verilog/inc1.v", 25)) begin message({"Blah-", "clx_scen", " end"}); end while(0); EXP: do if (start("verilog/inc1.v", 25)) begin message({"Blah-", "clx_scen", " end"}); end while(0);
do
`line 231 "t/t_preproc.v" 0 `line 340 "t/t_preproc.v" 0
if (start("t/t_preproc.v", 231)) begin message({"Blah-", "clx_scen", " end"}); end while(0); do
`line 340 "t/t_preproc.v" 0
`line 340 "t/t_preproc.v" 0
`line 340 "t/t_preproc.v" 0
`line 340 "t/t_preproc.v" 0
`line 340 "t/t_preproc.v" 0
if (start("t/t_preproc.v", 340)) begin
`line 340 "t/t_preproc.v" 0
`line 340 "t/t_preproc.v" 0
message({"Blah-", "clx_scen", " end"});
`line 340 "t/t_preproc.v" 0
end
`line 340 "t/t_preproc.v" 0
`line 340 "t/t_preproc.v" 0
while(0);
`line 344 "t/t_preproc.v" 0
`line 348 "t/t_preproc.v" 0
`line 348 "t/t_preproc.v" 0
`line 349 "t/t_preproc.v" 0
`line 241 "t/t_preproc.v" 0
`line 351 "t/t_preproc.v" 0
EXP: This is fooed EXP: This is fooed
This is fooed This is fooed
EXP: This is fooed_2 EXP: This is fooed_2
This is fooed_2 This is fooed_2
`line 250 "t/t_preproc.v" 2 `line 357 "t/t_preproc.v" 0
np
np
`line 362 "t/t_preproc.v" 0
`line 367 "t/t_preproc.v" 0
`line 372 "t/t_preproc.v" 0
`line 378 "t/t_preproc.v" 0
`line 382 "t/t_preproc.v" 0
hello3hello3hello3
hello4hello4hello4hello4
`line 386 "t/t_preproc.v" 0
`line 388 "t/t_preproc.v" 0
`line 1 "t/t_preproc_inc4.vh" 1
`line 3 "t/t_preproc.v" 0
`line 5 "t/t_preproc.v" 0
`line 7 "t/t_preproc_inc4.vh" 2
`line 388 "t/t_preproc.v" 0
`line 389 "t/t_preproc.v" 0
`line 393 "t/t_preproc.v" 0
`line 397 "t/t_preproc.v" 0
Line_Preproc_Check 401
`line 404 "t/t_preproc.v" 0
Line_Preproc_Check 407
"FOO \
BAR " "arg_line1 \
arg_line2" "FOO \
BAR "
`line 410 "t/t_preproc.v" 0
Line_Preproc_Check 410
`line 414 "t/t_preproc.v" 0
`line 418 "t/t_preproc.v" 0
abc
`line 424 "t/t_preproc.v" 0
EXP: sonet_frame
sonet_frame
`line 430 "t/t_preproc.v" 0
EXP: sonet_frame
sonet_frame
`line 435 "t/t_preproc.v" 0
EXP: sonet_frame
sonet_frame
`line 441 "t/t_preproc.v" 0
EXP: module zzz ; endmodule
module zzz ; endmodule
module zzz ; endmodule
`line 447 "t/t_preproc.v" 0
EXP: module a_b ; endmodule
module a_b ; endmodule
module a_b ; endmodule
`line 454 "t/t_preproc.v" 2
+1 -1
View File
@@ -14,7 +14,7 @@ if (!$Self->{v3}) {
ok(1); ok(1);
} else { } else {
compile ( compile (
v_flags2 => ['-DDEF_A0 -E'], v_flags2 => ['-DDEF_A0 -DPREDEF_COMMAND_LINE -E'],
verilator_make_gcc=>0, verilator_make_gcc=>0,
stdout_filename => $stdout_filename, stdout_filename => $stdout_filename,
); );
+216 -11
View File
@@ -1,12 +1,10 @@
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
//
//
// This file ONLY is placed into the Public Domain, for any use, // This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2004-2007 by Wilson Snyder. // without warranty, 2000-2010 by Wilson Snyder.
//=========================================================================== //===========================================================================
// Includes // Includes
`include "t_preproc_inc2.v" `include "t_preproc_inc2.vh"
//=========================================================================== //===========================================================================
// Comments // Comments
@@ -46,6 +44,7 @@ text.
/*******COMMENT*****/ /*******COMMENT*****/
`MULTILINE `MULTILINE
`MOREMULTILINE
Line_Preproc_Check `__LINE__ Line_Preproc_Check `__LINE__
//=========================================================================== //===========================================================================
@@ -59,7 +58,7 @@ Line_Preproc_Check `__LINE__
`define nosubst NOT_SUBSTITUTED `define nosubst NOT_SUBSTITUTED
`define WITHTICK "`nosubst" `define WITHTICK "`nosubst"
"Inside: `nosubst" "Inside: `nosubst"
`WITHTICK `WITHTICK
`define withparam(a, b) a b LLZZ a b `define withparam(a, b) a b LLZZ a b
`withparam(x,y) `withparam(x,y)
@@ -79,21 +78,64 @@ Line_Preproc_Check `__LINE__
$display(`msg(left side, right side)) $display(`msg(left side, right side))
`define foo(f) f``_suffix `define foo(f) f``_suffix
`foo(bar) `foo(bar) more
`define zap(which) \ `define zap(which) \
$c("Zap(\"",which,"\");"); $c("Zap(\"",which,"\");");
`zap(bug1); `zap(bug1);
`zap("bug2"); `zap("bug2");
/* Define inside comment: `DEEPER and `WITHTICK */
// More commentary: `zap(bug1); `zap("bug2");
//======================================================================
// display passthru
`define ls left_side
`define rs right_side
`define noarg na
`define thru(x) x
`define thruthru `ls `rs // Doesn't expand
`define msg(x,y) `"x: `\`"y`\`"`"
initial begin
//$display(`msg( \`, \`)); // Illegal
$display(`msg(pre `thru(thrupre `thru(thrumid) thrupost) post,right side));
$display(`msg(left side,right side));
$display(`msg( left side , right side ));
$display(`msg( `ls , `rs ));
$display(`msg( `noarg , `rs ));
$display(`msg( prep ( midp1 `ls midp2 ( outp ) ) , `rs ));
$display(`msg(`noarg,`noarg`noarg));
$display(`msg( `thruthru , `thruthru )); // Results vary between simulators
$display(`msg(`thru(),)); // Empty
$display(`msg(`thru(left side),`thru(right side)));
$display(`msg( `thru( left side ) , `thru( right side ) ));
$display(`"standalone`");
// Unspecified when the stringification has multiple lines
`define twoline first \
second
$display(`msg(twoline, `twoline));
//$display(`msg(left side, \ right side \ )); // Not sure \{space} is legal.
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
//======================================================================
// rt.cpan.org bug34429 // rt.cpan.org bug34429
`define ADD_UP(a,c) \ `define ADD_UP(a,c) \
wire tmp_``a = a; \ wire tmp_``a = a; \
wire tmp_``c = tmp_``a + 1; \ wire tmp_``c = tmp_``a + 1; \
assign c = tmp_``c ; assign c = tmp_``c ;
`ADD_UP(d1,o1) // expansion is OK module add1 ( input wire d1, output wire o1);
`ADD_UP( d2 , o2 ) // expansion is bad `ADD_UP(d1,o1) // expansion is OK
endmodule
module add2 ( input wire d2, output wire o2);
`ADD_UP( d2 , o2 ) // expansion is bad
endmodule
`define check(mod, width, flopname, gate, path) \ `define check(mod, width, flopname, gate, path) \
generate for (i=0; i<(width); i=i+1) begin \ generate for (i=0; i<(width); i=i+1) begin \
@@ -108,6 +150,17 @@ assign c = tmp_``c ;
`check(m5kc_fcl, 3, _ctl_mvldx_m1, `CK_fr, `MF._ctl_mvldx_m1) // ignorecmt `check(m5kc_fcl, 3, _ctl_mvldx_m1, `CK_fr, `MF._ctl_mvldx_m1) // ignorecmt
//======================================================================
// Quotes are legal in protected blocks. Grr.
module prot();
`protected
I!#r#e6<_Q{{E2+]I3<[3s)1@D|'E''i!O?]jD>Jo_![Cl)
#nj1]p,3^1~,="E@QZB\T)eU\pC#C|7=\$J$##A[@-@{Qk]
`endprotected
endmodule
//"
//======================================================================
// macro call with define that has comma // macro call with define that has comma
`define REG_H 6 `define REG_H 6
`define REG_L 7 `define REG_L 7
@@ -119,9 +172,38 @@ assign c = tmp_``c ;
`EX_READ((`_HL + 1)) and `EX_WRITE((`_HL), rdata) `EX_READ((`_HL + 1)) and `EX_WRITE((`_HL), rdata)
`EX_READ(`_HL + 1) `EX_READ(`_HL + 1)
`EX_WRITE(`_HL, rdata) `EX_WRITE(`_HL, rdata) more
//=========================================================================== //======================================================================
// include of parameterized file
`define INCNAME "t_preproc_inc4.vh"
`include `INCNAME
`ifndef T_PREPROC_INC4
`error "No Inc4"
`endif
`undef T_PREPROC_INC4
`ifdef NOT_DEFINED_INC
`include NOT_DEFINED_INC
`endif
//======================================================================
// macro call with , in {}
`define xxerror(logfile, msg) $blah(logfile,msg)
`xxerror("ab,cd","e,f");
`xxerror(this.logfile, vec);
`xxerror(this.logfile, vec[1,2,3]);
`xxerror(this.logfile, {blah.name(), " is not foo"});
//======================================================================
// pragma/default net type
`pragma foo = 1
`default_nettype none
`default_nettype uwire
//======================================================================
// Ifdef // Ifdef
`define EMPTY_TRUE `define EMPTY_TRUE
@@ -143,6 +225,25 @@ Line_Preproc_Check `__LINE__
) )
Line_Preproc_Check `__LINE__ Line_Preproc_Check `__LINE__
//======================================================================
// defines split arguments
`define BEGIN begin
`define END end
`define BEGINEND `BEGIN`END
`define quoteit(x) `"x`"
`BEGIN`END // 2001 spec doesn't require two tokens, so "beginend" ok
`BEGINEND // 2001 spec doesn't require two tokens, so "beginend" ok
`quoteit(`BEGIN`END) // No space "beginend"
//======================================================================
// bug106
`define \esc`def got_escaped
`ifdef \esc`def
`\esc`def
`endif
Not a \`define
//====================================================================== //======================================================================
// misparsed comma in submacro // misparsed comma in submacro
`define sb bee `define sb bee
@@ -156,6 +257,14 @@ Line_Preproc_Check `__LINE__
`define bug191(bits) $display("bits %d %d", $bits(foo), `bits); `define bug191(bits) $display("bits %d %d", $bits(foo), `bits);
`bug191(10) `bug191(10)
//======================================================================
// 1800-2009
`define UDALL
`ifndef PREDEF_COMMAND_LINE `error "Test setup error, PREDEF_COMMAND_LINE pre-missing" `endif
`undefineall
`ifdef UDALL `error "undefineall failed" `endif
`ifndef PREDEF_COMMAND_LINE `error "Deleted too much, no PREDEF_COMMAND_LINE" `endif
//====================================================================== //======================================================================
// bug202 // bug202
`define FC_INV3(out, in) \ `define FC_INV3(out, in) \
@@ -245,3 +354,99 @@ EXP: This is fooed_2
`def_fooed_2 `def_fooed_2
//====================================================================== //======================================================================
`define NOPARAM() np
`NOPARAM()
`NOPARAM( )
//======================================================================
// It's unclear if the spec allows this; is text_macro_idenitfier before or after substitution?
`define NODS_DEFINED
`define NODS_INDIRECT(x) x
`ifndef `NODS_INDIRECT(NODS_DEFINED)
`error "Indirect failed"
`endif
`ifdef `NODS_INDIRECT(NODS_UNDEFINED)
`error "Indirect2 failed"
`endif
//======================================================================
// Metaprogramming
`define REPEAT_0(d)
`define REPEAT_1(d) d
`define REPEAT_2(d) `REPEAT_1(d)d
`define REPEAT_3(d) `REPEAT_2(d)d
`define REPEAT_4(d) `REPEAT_3(d)d
`define CONCAT(a, b) a``b
`define REPEATC(n, d) `CONCAT(`REPEAT_, n)(d)
`define REPEATT(n, d) `REPEAT_``n(d)
`REPEATC(3, hello3 )
`REPEATT(4, hello4 )
//======================================================================
// Include from stringification
`undef T_PREPROC_INC4
`define NODS_CONC_VH(m) `"m.vh`"
`include `NODS_CONC_VH(t_preproc_inc4)
`ifndef T_PREPROC_INC4 `error_here `endif
//======================================================================
// Defines doing defines
// Note the newline on the end - required to form the end of a define
`define DEFINEIT(d) d \
`define _DEFIF_Z_0 1
`define DEFIF_NZ(d,n) `undef d `ifndef _DEFIF_Z_``n `DEFINEIT(`define d 1) `endif
`DEFIF_NZ(TEMP,1)
`ifndef TEMP `error "bad" `endif
`DEFIF_NZ(TEMP,0)
`ifdef TEMP `error "bad0" `endif
Line_Preproc_Check `__LINE__
//======================================================================
// Quoted multiline - track line numbers, and insure \\n gets propagated
`define MULQUOTE "FOO \
BAR "
`define MULQUOTE2(mq) `MULQUOTE mq `MULQUOTE
Line_Preproc_Check `__LINE__
`MULQUOTE2("arg_line1 \
arg_line2")
Line_Preproc_Check `__LINE__
//======================================================================
// bug283
`define A a
`define B b
`define C c
// EXP: abc
`define C5 `A``b```C
`C5
`undef A
`undef B
`undef C
`define XTYPE sonet
`define XJOIN(__arg1, __arg2) __arg1``__arg2
`define XACTION `XJOIN(`XTYPE, _frame)
EXP: sonet_frame
`XACTION
//
`define XFRAME frame
`define XACTION2 `XJOIN(sonet_, `XFRAME)
EXP: sonet_frame
`XACTION2
// This result varies between simulators
`define sonet_frame other_frame
`define XACTION3 `XTYPE``_frame
EXP: sonet_frame
`XACTION3
// The existance of non-existance of a base define can make a difference
`define QA_b zzz
`define Q1 `QA``_b
EXP: module zzz ; endmodule
module `Q1 ; endmodule
module `Q1 ; endmodule
`define QA a
EXP: module a_b ; endmodule
module `Q1 ; endmodule
module `Q1 ; endmodule
//======================================================================
+15 -6
View File
@@ -8,8 +8,9 @@
`line 10 "t/t_preproc_def09.v" 0
'initial $display("start", "msg1" , "msg2" , "end");' 'initial $display("start", "msg1" , "msg2", "end");'
'initial $display("start", "msg1" , "msg2" , "end");' 'initial $display("start", "msg1" , "msg2" , "end");'
'initial $display("start", " msg1" , , "end");' 'initial $display("start", " msg1" , , "end");'
'initial $display("start", " msg1" , , "end");' 'initial $display("start", " msg1" , , "end");'
@@ -24,15 +25,17 @@
`line 26 "t/t_preproc_def09.v" 0
'$display(5,,2,,3 );'
'$display(5,,2,,3);' '$display(5,,2,,3);'
'$display(1 ,,"B",,3 );' '$display(5,,2,,3);'
'$display(1,,"B",,3);'
'$display(1 ,,"B",,3 );' '$display(1 ,,"B",,3 );'
'$display(5,,2,,);' '$display(5,,2,,);'
'$display(5,,2,,);' '$display(5,,2,,);'
`line 35 "t/t_preproc_def09.v" 0
'$display(1,,,,3);' '$display(1,,,,3);'
'$display(5,,,,"C");' '$display(5,,,,"C");'
@@ -41,23 +44,27 @@
'$display(5,,2,,"C");' '$display(5,,2,,"C");'
'$display(5,,2,,"C");' '$display(5,,2,,"C");'
`line 43 "t/t_preproc_def09.v" 0
'$display(1 ,,0,,"C");' '$display(1,,0,,"C");'
'$display(1 ,,0,,"C");' '$display(1 ,,0,,"C");'
'$display(5,,0,,"C");' '$display(5,,0,,"C");'
'$display(5,,0,,"C");' '$display(5,,0,,"C");'
`line 50 "t/t_preproc_def09.v" 0
'b + 1 + 42 + a ' 'b + 1 + 42 + a'
'b + 1 + 42 + a' 'b + 1 + 42 + a'
`line 55 "t/t_preproc_def09.v" 0
'"==)" "((((" () '; '"==)" "((((" () ';
'"==)" "((((" () '; '"==)" "((((" () ';
`line 60 "t/t_preproc_def09.v" 0
@@ -68,8 +75,10 @@
`line 70 "t/t_preproc_def09.v" 0
'(6) (eq=al) ZOT' '(6) (eq=al) ZOT'
HERE-71 - Line71 HERE-71 - Line71
`line 74 "t/t_preproc_def09.v" 2
`line 75 "t/t_preproc_def09.v" 2
@@ -2,5 +2,5 @@
// This file ONLY is placed into the Public Domain, for any use, // This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2000-2007 by Wilson Snyder. // without warranty, 2000-2007 by Wilson Snyder.
At file `__FILE__ line `__LINE__ At file `__FILE__ line `__LINE__
`define INCFILE <t_preproc_inc3.v> `define INCFILE <t_preproc_inc3.vh>
`include `INCFILE `include `INCFILE
@@ -13,5 +13,5 @@
`endif // guard `endif // guard
`ifdef not_defined `ifdef not_defined
`include "NotToBeInced.v" `include "NotToBeInced.vh"
`endif `endif
+5
View File
@@ -0,0 +1,5 @@
// DESCRIPTION: Verilog::Preproc: Example source code
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2000-2010 by Wilson Snyder.
`define T_PREPROC_INC4
+32 -10
View File
@@ -5,16 +5,20 @@
`line 7 "t/t_preproc_psl.v" 0
/*verilator metacomment preserved*/ /*verilator metacomment preserved*/
`line 9 "t/t_preproc_psl.v" 0
/*verilator metacomment also_preserved*/ /*verilator metacomment also_preserved*/
`line 11 "t/t_preproc_psl.v" 0
Hello in t_preproc_psl.v Hello in t_preproc_psl.v
`line 17 "t/t_preproc_psl.v" 0
@@ -22,32 +26,47 @@ Hello in t_preproc_psl.v
`line 28 "t/t_preproc_psl.v" 0
`line 28 "t/t_preproc_psl.v" 0
`line 28 "t/t_preproc_psl.v" 0
`line 28 "t/t_preproc_psl.v" 0
`line 29 "t/t_preproc_psl.v" 0
29 29
`line 31 "t/t_preproc_psl.v" 0
`line 40 "t/t_preproc_psl.v" 0
`line 40 "t/t_preproc_psl.v" 0
`line 40 "t/t_preproc_psl.v" 0
`line 40 "t/t_preproc_psl.v" 0
`line 40 "t/t_preproc_psl.v" 0
`line 41 "t/t_preproc_psl.v" 0
41 41
`line 43 "t/t_preproc_psl.v" 0
`line 45 "t/t_preproc_psl.v" 0
`line 50 "t/t_preproc_psl.v" 0
@@ -55,16 +74,17 @@ Hello in t_preproc_psl.v
`line 57 "t/t_preproc_psl.v" 0
`line 59 "t/t_preproc_psl.v" 0
`line 62 "t/t_preproc_psl.v" 0
`line 65 "t/t_preproc_psl.v" 0
`psl `psl
psl assert always sig!=90; psl assert always sig!=90;
@@ -72,5 +92,7 @@ psl assert always sig!=90;
`line 72 "t/t_preproc_psl.v" 0
72 72
`line 73 "t/t_preproc_psl.v" 2
`line 74 "t/t_preproc_psl.v" 2
+15 -3
View File
@@ -5,16 +5,20 @@
`line 7 "t/t_preproc_psl.v" 0
/*verilator metacomment preserved*/ /*verilator metacomment preserved*/
`line 9 "t/t_preproc_psl.v" 0
/*verilator metacomment also_preserved*/ /*verilator metacomment also_preserved*/
`line 11 "t/t_preproc_psl.v" 0
Hello in t_preproc_psl.v Hello in t_preproc_psl.v
`line 17 "t/t_preproc_psl.v" 0
psl default clock = (posedge clk); psl default clock = (posedge clk);
psl fails1: cover {cyc==10}; psl fails1: cover {cyc==10};
psl assert always cyc!=10; psl assert always cyc!=10;
@@ -29,10 +33,12 @@ Hello in t_preproc_psl.v
29 29
`line 31 "t/t_preproc_psl.v" 0
psl psl
`line 35 "t/t_preproc_psl.v" 0
fails_ml: fails_ml:
assert always assert always
cyc==3 -> mask==8'h21; cyc==3 -> mask==8'h21;
@@ -41,13 +47,16 @@ Hello in t_preproc_psl.v
41 41
`line 43 "t/t_preproc_psl.v" 0
psl assert never (cyc==1 && reset_l); psl assert never (cyc==1 && reset_l);
`line 45 "t/t_preproc_psl.v" 0
psl fails3: assert always psl fails3: assert always
psl cyc==3 -> mask==8'h21; psl cyc==3 -> mask==8'h21;
`line 50 "t/t_preproc_psl.v" 0
psl assert always psl assert always
psl {[*]; cyc==3; psl {[*]; cyc==3;
psl cyc==4; cyc==6}; psl cyc==4; cyc==6};
@@ -55,16 +64,17 @@ Hello in t_preproc_psl.v
`line 57 "t/t_preproc_psl.v" 0
`line 59 "t/t_preproc_psl.v" 0
`line 62 "t/t_preproc_psl.v" 0
psl assert always cyc!=10; psl assert always cyc!=10;
`line 65 "t/t_preproc_psl.v" 0
`psl `psl
psl assert always sig!=90; psl assert always sig!=90;
@@ -72,5 +82,7 @@ psl assert always sig!=90;
`line 72 "t/t_preproc_psl.v" 0
72 72
`line 73 "t/t_preproc_psl.v" 2
`line 74 "t/t_preproc_psl.v" 2