From 699563c9bd53d2d37e79c0f70db409657f293e11 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 19 Dec 2006 14:09:57 +0000 Subject: [PATCH] Add support. git-svn-id: file://localhost/svn/verilator/trunk/verilator@846 77ca24e4-aefa-0310-84f0-b9a241c72d87 --- Changes | 2 + bin/verilator | 31 ++++-- include/verilated.cpp | 108 +++++++++++++++++++ include/verilated.h | 33 +++++- src/V3AstNodes.h | 28 +++++ src/V3EmitC.cpp | 33 ++++++ src/V3EmitV.cpp | 10 ++ src/V3Width.cpp | 6 ++ src/verilog.l | 2 + src/verilog.y | 68 ++++++------ test_regress/driver.pl | 10 +- test_regress/t/t_clk_latch.v | 4 +- test_regress/t/{t_file.pl => t_sys_file.pl} | 6 +- test_regress/t/{t_file.v => t_sys_file.v} | 7 +- test_regress/t/t_sys_readmem.pl | 18 ++++ test_regress/t/t_sys_readmem.v | 62 +++++++++++ test_regress/t/t_sys_readmem_b.mem | 18 ++++ test_regress/t/t_sys_readmem_b_8.mem | 19 ++++ test_regress/t/t_sys_readmem_bad_addr.mem | 9 ++ test_regress/t/t_sys_readmem_bad_addr.pl | 20 ++++ test_regress/t/t_sys_readmem_bad_addr.v | 15 +++ test_regress/t/t_sys_readmem_bad_digit.mem | 9 ++ test_regress/t/t_sys_readmem_bad_digit.pl | 20 ++++ test_regress/t/t_sys_readmem_bad_digit.v | 16 +++ test_regress/t/t_sys_readmem_bad_end.mem | 11 ++ test_regress/t/t_sys_readmem_bad_end.pl | 20 ++++ test_regress/t/t_sys_readmem_bad_end.v | 18 ++++ test_regress/t/t_sys_readmem_bad_notfound.pl | 20 ++++ test_regress/t/t_sys_readmem_bad_notfound.v | 16 +++ test_regress/t/t_sys_readmem_h.mem | 13 +++ 30 files changed, 603 insertions(+), 49 deletions(-) rename test_regress/t/{t_file.pl => t_sys_file.pl} (85%) mode change 100755 => 100644 rename test_regress/t/{t_file.v => t_sys_file.v} (71%) create mode 100755 test_regress/t/t_sys_readmem.pl create mode 100644 test_regress/t/t_sys_readmem.v create mode 100644 test_regress/t/t_sys_readmem_b.mem create mode 100644 test_regress/t/t_sys_readmem_b_8.mem create mode 100644 test_regress/t/t_sys_readmem_bad_addr.mem create mode 100755 test_regress/t/t_sys_readmem_bad_addr.pl create mode 100644 test_regress/t/t_sys_readmem_bad_addr.v create mode 100644 test_regress/t/t_sys_readmem_bad_digit.mem create mode 100755 test_regress/t/t_sys_readmem_bad_digit.pl create mode 100644 test_regress/t/t_sys_readmem_bad_digit.v create mode 100644 test_regress/t/t_sys_readmem_bad_end.mem create mode 100755 test_regress/t/t_sys_readmem_bad_end.pl create mode 100644 test_regress/t/t_sys_readmem_bad_end.v create mode 100755 test_regress/t/t_sys_readmem_bad_notfound.pl create mode 100644 test_regress/t/t_sys_readmem_bad_notfound.v create mode 100644 test_regress/t/t_sys_readmem_h.mem diff --git a/Changes b/Changes index b8fd3d8d3..a6279d6dd 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.62*** +** Support $readmemb and $readmemh. [Eugene Weber, Arthur Kahlich] + *** Fixed configure and compiling under Solaris. [Bob Farrell] *** When dotted signal lookup fails, help the user by showing known scopes. diff --git a/bin/verilator b/bin/verilator index f3e0f92ca..40d0f026a 100755 --- a/bin/verilator +++ b/bin/verilator @@ -996,16 +996,6 @@ Verilog standard, %x prints a number with the natural width, %0x prints a number with minimum width, however %5x prints 5 digits per the C standard (it's unspecified in Verilog). -=item $fopen, $fclose, $fdisplay, $fwrite - -File descriptors passed to the file PLI calls must be file descriptors, not -MCDs, which includes the mode parameter to $fopen being mandatory. -Verilator will convert the integer used to hold the file descriptor into a -internal FILE*. To prevent core dumps due to mis-use, and because integers -are 32 bits while FILE*s may be 64 bits, the descriptor must be stored in a -reg [63:0] rather then an integer. The define `verilator_file_descriptor in -verilated.v can be used to hide this difference. - =item `coverage_block_off Specifies the entire begin/end block should be ignored for coverage analysis. @@ -1316,6 +1306,27 @@ appropriate width. $display and friends must have a constant format string as the first argument (as with C's printf), you cannot simply list variables standalone. +=item $displayb, $displayh, $displayo, $writeb, $writeh, $writeo, etc + +The sized display functions are rarely used and so not supported. Replace +them with a $write with the appropriate format specifier. + +=item $fopen, $fclose, $fdisplay, $fwrite + +File descriptors passed to the file PLI calls must be file descriptors, not +MCDs, which includes the mode parameter to $fopen being mandatory. +Verilator will convert the integer used to hold the file descriptor into a +internal FILE*. To prevent core dumps due to mis-use, and because integers +are 32 bits while FILE*s may be 64 bits, the descriptor must be stored in a +reg [63:0] rather then an integer. The define `verilator_file_descriptor in +verilated.v can be used to hide this difference. + +=item $readmemb, $readmemh + +Read memory commands should work properly. Note Verilator and the Verilog +specification does not include support for readmem to multi-dimensional +arrays. + =head1 ERRORS AND WARNINGS Warnings may be disabled in two ways. First, when the warning is diff --git a/include/verilated.cpp b/include/verilated.cpp index 1e2851a8a..936aada41 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -24,6 +24,7 @@ #include "verilated.h" #include +#include #define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING @@ -238,6 +239,113 @@ QData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) { return VL_CVT_FP_Q(fopen(filenamez,modez)); } +void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int, + QData ofilename, void* memp, IData start, IData end) { + IData fnw[2]; VL_SET_WQ(fnw, ofilename); + return VL_READMEM_W(hex,2,width,depth,array_lsb, fnw,memp,start,end); +} + +void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords, + WDataInP ofilenamep, void* memp, IData start, IData end) { + char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; + _VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep); + FILE* fp = fopen(ofilenamez, "r"); + if (!fp) { + // We don't report the Verilog source filename as it slow to have to pass it down + vl_fatal (ofilenamez, 0, "", "$readmem file not found"); + return; + } + // Prep for reading + IData addr = start; + int linenum = 0; + bool innum = false; + bool ignore_to_eol = false; + bool ignore_to_cmt = false; + bool needinc = false; + bool reading_addr = false; + int lastc = ' '; + // Read the data + // We process a character at a time, as then we don't need to deal + // with changing buffer sizes dynamically, etc. + while (1) { + int c = fgetc(fp); + if (c==EOF) break; + //printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n", linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc); + if (c=='\n') { linenum++; ignore_to_eol=false; if (innum) reading_addr=false; innum=false; } + else if (c=='\t' || c==' ' || c=='\r' || c=='\f') { if (innum) reading_addr=false; innum=false; } + // Skip // comments and detect /* comments + else if (ignore_to_cmt && lastc=='*' && c=='/') { + ignore_to_cmt = false; if (innum) reading_addr=false; innum=false; + } else if (!ignore_to_eol && !ignore_to_cmt) { + if (lastc=='/' && c=='*') { ignore_to_cmt = true; } + else if (lastc=='/' && c=='/') { ignore_to_eol = true; } + else if (c=='/') {} // Part of /* or // + else if (c=='_') {} + else if (c=='@') { reading_addr = true; innum=false; needinc=false; } + // Check for hex or binary digits as file format requests + else if (isxdigit(c)) { + c = tolower(c); + int value = (c >= 'a' ? (c-'a'+10) : (c-'0')); + if (!innum) { // Prep for next number + if (needinc) { addr++; needinc=false; } + } + if (reading_addr) { + // Decode @ addresses + if (!innum) addr=0; + addr = (addr<<4) + value; + } else { + needinc = true; + //printf(" Value width=%d @%x = %c\n", width, addr, c); + if (addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb)) { + vl_fatal (ofilenamez, linenum, "", "$readmem file address beyond bounds of array"); + } else { + int entry = addr - array_lsb; + QData shift = hex ? VL_ULL(4) : VL_ULL(1); + // Shift value in + if (width<=8) { + CData* datap = &((CData*)(memp))[entry]; + if (!innum) { *datap = 0; } + *datap = ((*datap << shift) + value) & VL_MASK_I(width); + } else if (width<=16) { + SData* datap = &((SData*)(memp))[entry]; + if (!innum) { *datap = 0; } + *datap = ((*datap << shift) + value) & VL_MASK_I(width); + } else if (width<=VL_WORDSIZE) { + IData* datap = &((IData*)(memp))[entry]; + if (!innum) { *datap = 0; } + *datap = ((*datap << shift) + value) & VL_MASK_I(width); + } else if (width<=VL_QUADSIZE) { + QData* datap = &((QData*)(memp))[entry]; + if (!innum) { *datap = 0; } + *datap = ((*datap << (QData)(shift)) + (QData)(value)) & VL_MASK_Q(width); + } else { + WDataOutP datap = &((WDataOutP)(memp))[ entry*VL_WORDS_I(width) ]; + if (!innum) { VL_ZERO_RESET_W(width, datap); } + _VL_SHIFTL_INPLACE_W(width, datap, shift); + datap[0] |= value; + } + if (value>=(1<=0; i--) { printf("%08x ",iwp[i]); } + printf("\n"); +} + //========================================================================= // Pli macros @@ -1035,6 +1050,18 @@ static inline WDataOutP VL_CONCAT_WWW(int obits,int lbits,int rbits,WDataOutP ow //=================================================================== // Shifts +// Static shift, used by internal functions +// The output is the same as the input - it overlaps! +static inline void _VL_SHIFTL_INPLACE_W(int obits,WDataOutP iowp,IData rd/*1 or 4*/) { + int words = VL_WORDS_I(obits); + IData linsmask = VL_MASK_I(rd); + for (int i=words-1; i>=1; i--) { + iowp[i] = ((iowp[i]<> (32-rd)) & linsmask); + } + iowp[0] = ((iowp[0]<castReadMem()->isHex(); } + bool isHex() const { return m_isHex; } + AstNode* filenamep() const { return op1p()->castNode(); } + AstNode* memp() const { return op2p()->castNode(); } + AstNode* lsbp() const { return op3p()->castNode(); } + AstNode* msbp() const { return op4p()->castNode(); } +}; + struct AstGenFor : public AstNodeFor { AstGenFor(FileLine* fileline, AstNode* initsp, AstNode* condp, AstNode* incsp, AstNode* bodysp) diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 424126891..f6e3bfb80 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -249,6 +249,39 @@ public: nodep->modep()->iterateAndNext(*this); puts(");\n"); } + virtual void visit(AstReadMem* nodep, AstNUser*) { + puts("VL_READMEM_"); + emitIQW(nodep->filenamep()); + puts(" ("); // We take a void* rather then emitIQW(nodep->memp()); + puts(nodep->isHex()?"true":"false"); + putbs(","); + puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width + putbs(","); + uint32_t array_lsb = 0; + { + AstVarRef* varrefp = nodep->memp()->castVarRef(); + if (!varrefp || !varrefp->varp()->arrayp(0)) { nodep->v3error("Readmem loading non-arrayed variable"); } + else { + puts(cvtToStr(varrefp->varp()->arrayElements())); + array_lsb = varrefp->varp()->arrayp(0)->lsbConst(); + } + } + putbs(", "); + puts(cvtToStr(array_lsb)); + putbs(","); + puts(cvtToStr(nodep->filenamep()->widthWords())); + if (nodep->filenamep()->widthWords() > VL_TO_STRING_MAX_WORDS) { + nodep->v3error("String of "<filenamep()->width()<<" bits exceeds hardcoded limit VL_TO_STRING_MAX_WORDS in verilatedos.h\n"); + } + putbs(", "); + nodep->filenamep()->iterateAndNext(*this); + putbs(", "); + nodep->memp()->iterateAndNext(*this); + putbs(","); if (nodep->lsbp()) { nodep->lsbp()->iterateAndNext(*this); } + else puts(cvtToStr(array_lsb)); + putbs(","); if (nodep->msbp()) { nodep->msbp()->iterateAndNext(*this); } else puts("~0"); + puts(");\n"); + } virtual void visit(AstFClose* nodep, AstNUser*) { puts("if ("); nodep->filep()->iterateAndNext(*this); diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index efe9b8b61..ad2b4ee22 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -193,6 +193,16 @@ public: if (nodep->filep()) nodep->filep()->iterateChildren(*this); puts(");\n"); } + virtual void visit(AstReadMem* nodep, AstNUser*) { + putbs(nodep->verilogKwd()); + putbs(" ("); + if (nodep->filenamep()) nodep->filenamep()->iterateChildren(*this); + putbs(","); + if (nodep->memp()) nodep->memp()->iterateChildren(*this); + if (nodep->lsbp()) { putbs(","); nodep->lsbp()->iterateChildren(*this); } + if (nodep->msbp()) { putbs(","); nodep->msbp()->iterateChildren(*this); } + puts(");\n"); + } virtual void visit(AstNodeFor* nodep, AstNUser*) { puts("for ("); m_suppressSemi = true; diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 1701045db..820ea0ae9 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -554,6 +554,12 @@ private: virtual void visit(AstFClose* nodep, AstNUser*) { nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p()); } + virtual void visit(AstReadMem* nodep, AstNUser*) { + nodep->filenamep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); + nodep->memp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); + nodep->lsbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); + nodep->msbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); + } virtual void visit(AstUCStmt* nodep, AstNUser*) { // TOP LEVEL NODE // Just let all arguments seek their natural sizes diff --git a/src/verilog.l b/src/verilog.l index 8ded7cd30..fd8cea8cc 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -174,6 +174,8 @@ escid \\[^ \t\f\r\n]+ "$onehot0" {yylval.fileline = CRELINE(); return yD_ONEHOT0;} "$period" {yylval.fileline = CRELINE(); return yTIMINGSPEC;} "$realtime" {yylval.fileline = CRELINE(); return yD_TIME;} +"$readmemb" {yylval.fileline = CRELINE(); return yD_READMEMB;} +"$readmemh" {yylval.fileline = CRELINE(); return yD_READMEMH;} "$recovery" {yylval.fileline = CRELINE(); return yTIMINGSPEC;} "$recrem" {yylval.fileline = CRELINE(); return yTIMINGSPEC;} "$removal" {yylval.fileline = CRELINE(); return yTIMINGSPEC;} diff --git a/src/verilog.y b/src/verilog.y index 1612e9c90..2869cb3ad 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -136,31 +136,33 @@ class AstSenTree; %token yBUF yNOT yAND yNAND yNOR yXOR yXNOR %token ySCALARED yVECTORED -%token yASSERT "assert" -%token yCLOCK "clock" -%token yCOVER "cover" -%token yFINAL "final" -%token yPSL "psl" -%token yREPORT "report" -%token yTRUE "true" +%token yASSERT "assert" +%token yCLOCK "clock" +%token yCOVER "cover" +%token yFINAL "final" +%token yPSL "psl" +%token yREPORT "report" +%token yTRUE "true" -%token yD_BITS "$bits" -%token yD_C "$c" -%token yD_COUNTONES "$countones" -%token yD_DISPLAY "$display" -%token yD_FCLOSE "$fclose" -%token yD_FDISPLAY "$fdisplay" -%token yD_FINISH "$finish" -%token yD_FOPEN "$fopen" -%token yD_FWRITE "$fwrite" -%token yD_ISUNKNOWN "$isunknown" -%token yD_ONEHOT "$onehot" -%token yD_ONEHOT0 "$onehot0" -%token yD_SIGNED "$signed" -%token yD_STOP "$stop" -%token yD_TIME "$time" -%token yD_UNSIGNED "$unsigned" -%token yD_WRITE "$write" +%token yD_BITS "$bits" +%token yD_C "$c" +%token yD_COUNTONES "$countones" +%token yD_DISPLAY "$display" +%token yD_FCLOSE "$fclose" +%token yD_FDISPLAY "$fdisplay" +%token yD_FINISH "$finish" +%token yD_FOPEN "$fopen" +%token yD_FWRITE "$fwrite" +%token yD_ISUNKNOWN "$isunknown" +%token yD_ONEHOT "$onehot" +%token yD_ONEHOT0 "$onehot0" +%token yD_READMEMB "$readmemb" +%token yD_READMEMH "$readmemh" +%token yD_SIGNED "$signed" +%token yD_STOP "$stop" +%token yD_TIME "$time" +%token yD_UNSIGNED "$unsigned" +%token yD_WRITE "$write" %token yVL_CLOCK "/*verilator sc_clock*/" %token yVL_CLOCK_ENABLE "/*verilator clock_enable*/" @@ -670,15 +672,21 @@ stmt: ';' { $$ = NULL; } | stateCaseForIf { $$ = $1; } | taskRef ';' { $$ = $1; } - | yD_DISPLAY ';' { $$ = new AstDisplay($1,'\n',"",NULL,NULL); } - | yD_DISPLAY '(' ySTRING ')' ';' { $$ = new AstDisplay($1,'\n',*$3,NULL,NULL); } - | yD_DISPLAY '(' ySTRING ',' eList ')' ';' { $$ = new AstDisplay($1,'\n',*$3,NULL,$5); } - | yD_WRITE '(' ySTRING ')' ';' { $$ = new AstDisplay($1,'\0',*$3,NULL,NULL); } + | yD_DISPLAY ';' { $$ = new AstDisplay($1,'\n',"",NULL,NULL); } + | yD_DISPLAY '(' ySTRING ')' ';' { $$ = new AstDisplay($1,'\n',*$3,NULL,NULL); } + | yD_DISPLAY '(' ySTRING ',' eList ')' ';' { $$ = new AstDisplay($1,'\n',*$3,NULL,$5); } + | yD_WRITE '(' ySTRING ')' ';' { $$ = new AstDisplay($1,'\0',*$3,NULL,NULL); } | yD_WRITE '(' ySTRING ',' eList ')' ';' { $$ = new AstDisplay($1,'\0',*$3,NULL,$5); } | yD_FDISPLAY '(' idVarXRef ',' ySTRING ')' ';' { $$ = new AstDisplay($1,'\n',*$5,$3,NULL); } - | yD_FDISPLAY '(' idVarXRef ',' ySTRING ',' eList ')' ';' { $$ = new AstDisplay($1,'\n',*$5,$3,$7); } + | yD_FDISPLAY '(' idVarXRef ',' ySTRING ',' eList ')' ';' { $$ = new AstDisplay($1,'\n',*$5,$3,$7); } | yD_FWRITE '(' idVarXRef ',' ySTRING ')' ';' { $$ = new AstDisplay($1,'\0',*$5,$3,NULL); } - | yD_FWRITE '(' idVarXRef ',' ySTRING ',' eList ')' ';' { $$ = new AstDisplay($1,'\0',*$5,$3,$7); } + | yD_FWRITE '(' idVarXRef ',' ySTRING ',' eList ')' ';' { $$ = new AstDisplay($1,'\0',*$5,$3,$7); } + | yD_READMEMB '(' expr ',' lhIdArrayed ')' ';' { $$ = new AstReadMem($1,false,$3,$5,NULL,NULL); } + | yD_READMEMB '(' expr ',' lhIdArrayed ',' expr ')' ';' { $$ = new AstReadMem($1,false,$3,$5,$7,NULL); } + | yD_READMEMB '(' expr ',' lhIdArrayed ',' expr ',' expr ')' ';' { $$ = new AstReadMem($1,false,$3,$5,$7,$9); } + | yD_READMEMH '(' expr ',' lhIdArrayed ')' ';' { $$ = new AstReadMem($1,true, $3,$5,NULL,NULL); } + | yD_READMEMH '(' expr ',' lhIdArrayed ',' expr ')' ';' { $$ = new AstReadMem($1,true, $3,$5,$7,NULL); } + | yD_READMEMH '(' expr ',' lhIdArrayed ',' expr ',' expr ')' ';' { $$ = new AstReadMem($1,true, $3,$5,$7,$9); } ; stateCaseForIf: caseStmt caseAttrE caseList yENDCASE { $$ = $1; $1->addItemsp($3); } diff --git a/test_regress/driver.pl b/test_regress/driver.pl index b430e7a09..3eea46d0f 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -57,6 +57,7 @@ my $opt_stop; my $opt_optimize; my $opt_gdb; my $opt_jobs = 1; +my $opt_verbose; my $Opt_Verilated_Debug; if (! GetOptions ( "help" => \&usage, @@ -69,6 +70,7 @@ if (! GetOptions ( "gdb!" => \$opt_gdb, "stop!" => \$opt_stop, "optimize:s" => \$opt_optimize, + "verbose!" => \$opt_verbose, "<>" => \¶meter, )) { usage(); @@ -187,7 +189,9 @@ sub new { make_top_shell => 1, # Make a default __top.v file make_main => 1, # Make __main.cpp # All compilers - v_flags => [split(/\s+/," -f input.vc --debug-check")], + v_flags => [split(/\s+/,(" -f input.vc --debug-check" + .($opt_verbose ? " +define+TEST_VERBOSE+1":"") + ))], v_flags2 => [], # Overridden in some sim files v_other_filenames => [], # After the filename so we can spec multiple files # VCS @@ -827,6 +831,10 @@ Stop on the first error Run using VCS. +=item --verbose + +Enable test verbose messages. + =item --v3 Run using Verilator. diff --git a/test_regress/t/t_clk_latch.v b/test_regress/t/t_clk_latch.v index 8a6be6619..b7bbd070d 100644 --- a/test_regress/t/t_clk_latch.v +++ b/test_regress/t/t_clk_latch.v @@ -1,4 +1,4 @@ -// $Id:$ +// $Id$ // DESCRIPTION: Verilator: Verilog Test module // // This file ONLY is placed into the Public Domain, for any use, @@ -83,7 +83,9 @@ module t (/*AUTOARG*/ always @ (posedge fastclk) begin cyc <= cyc+1; +`ifdef TEST_VERBOSE $write("%d %x %x %x %x %x %x\n",cyc,data_a,data_a_a,data_b_a,data_b,data_a_b,data_b_b); +`endif if (cyc>=19 && cyc<36) begin if (compare !== check[cyc]) begin $write("[%0t] Mismatch, got=%x, exp=%x\n", $time, compare, check[cyc]); diff --git a/test_regress/t/t_file.pl b/test_regress/t/t_sys_file.pl old mode 100755 new mode 100644 similarity index 85% rename from test_regress/t/t_file.pl rename to test_regress/t/t_sys_file.pl index e0ac01b53..6b72957e6 --- a/test_regress/t/t_file.pl +++ b/test_regress/t/t_sys_file.pl @@ -7,16 +7,16 @@ if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; } # redistribute it and/or modify it under the terms of either the GNU # General Public License or the Perl Artistic License. +unlink("obj_dir/t_sys_file_test.log"); + compile ( ); -unlink("obj_dir/t_file_test.log"); - execute ( check_finished=>1, ); -file_grep ("obj_dir/t_file_test.log", +file_grep ("obj_dir/t_sys_file_test.log", qr/\[0\] hello v=12345667 \[0\] Hello2 /); diff --git a/test_regress/t/t_file.v b/test_regress/t/t_sys_file.v similarity index 71% rename from test_regress/t/t_file.v rename to test_regress/t/t_sys_file.v index 9091d02c5..21439e859 100644 --- a/test_regress/t/t_file.v +++ b/test_regress/t/t_sys_file.v @@ -16,7 +16,7 @@ module t; $fwrite(file, "Never printed, file closed\n"); `endif - file = $fopen("obj_dir/t_file_test.log","w"); // The "w" is required so we get a FD not a MFD + file = $fopen("obj_dir/t_sys_file_test.log","w"); // The "w" is required so we get a FD not a MFD $fdisplay(file, "[%0t] hello v=%x", $time, 32'h12345667); $fwrite(file, "[%0t] %s\n", $time, "Hello2"); @@ -27,6 +27,11 @@ module t; $fwrite(file, "Never printed, file closed\n"); `endif + begin + file = $fopen("obj_dir/DOES_NOT_EXIST","r"); // The "r" is required so we get a FD not a MFD + if (|file) $stop; // Should not exist, IE must return 0 + end + $write("*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_sys_readmem.pl b/test_regress/t/t_sys_readmem.pl new file mode 100755 index 000000000..7bfdbe852 --- /dev/null +++ b/test_regress/t/t_sys_readmem.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; } +# $Id$ +# 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 +# General Public License or the Perl Artistic License. + +compile ( + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_sys_readmem.v b/test_regress/t/t_sys_readmem.v new file mode 100644 index 000000000..a237be134 --- /dev/null +++ b/test_regress/t/t_sys_readmem.v @@ -0,0 +1,62 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2003 by Wilson Snyder. + +module t; + + reg [5:0] binary_nostart [2:15]; + reg [5:0] binary_start [0:15]; + reg [175:0] hex [0:15]; + + integer i; + + initial begin + + begin + $readmemb("t/t_sys_readmem_b.mem", binary_nostart); +`ifdef TEST_VERBOSE + for (i=0; i<16; i=i+1) $write(" @%x = %x\n", i, binary_nostart[i]); +`endif + if (binary_nostart['h2] != 6'h02) $stop; + if (binary_nostart['h3] != 6'h03) $stop; + if (binary_nostart['h4] != 6'h04) $stop; + if (binary_nostart['h5] != 6'h05) $stop; + if (binary_nostart['h6] != 6'h06) $stop; + if (binary_nostart['h7] != 6'h07) $stop; + if (binary_nostart['h8] != 6'h10) $stop; + if (binary_nostart['hc] != 6'h14) $stop; + if (binary_nostart['hd] != 6'h15) $stop; + end + + begin + $readmemb("t/t_sys_readmem_b_8.mem", binary_start, 4, 4+7); +`ifdef TEST_VERBOSE + for (i=0; i<16; i=i+1) $write(" @%x = %x\n", i, binary_start[i]); +`endif + if (binary_start['h04] != 6'h10) $stop; + if (binary_start['h05] != 6'h11) $stop; + if (binary_start['h06] != 6'h12) $stop; + if (binary_start['h07] != 6'h13) $stop; + if (binary_start['h08] != 6'h14) $stop; + if (binary_start['h09] != 6'h15) $stop; + if (binary_start['h0a] != 6'h16) $stop; + if (binary_start['h0b] != 6'h17) $stop; + end + + begin + $readmemh("t/t_sys_readmem_h.mem", hex, 0); +`ifdef TEST_VERBOSE + for (i=0; i<16; i=i+1) $write(" @%x = %x\n", i, hex[i]); +`endif + if (hex['h04] != 176'h400437654321276543211765432107654321abcdef10) $stop; + if (hex['h0a] != 176'h400a37654321276543211765432107654321abcdef11) $stop; + if (hex['h0b] != 176'h400b37654321276543211765432107654321abcdef12) $stop; + if (hex['h0c] != 176'h400c37654321276543211765432107654321abcdef13) $stop; + end + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_sys_readmem_b.mem b/test_regress/t/t_sys_readmem_b.mem new file mode 100644 index 000000000..e5ae5bf92 --- /dev/null +++ b/test_regress/t/t_sys_readmem_b.mem @@ -0,0 +1,18 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test data file +// +// Copyright 2006 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// General Public License or the Perl Artistic License. + +010 +0_1_1 +100/*Space*/101// Space +110 111 + +@00_0_8 +10000 + +@c +10100 +10101 diff --git a/test_regress/t/t_sys_readmem_b_8.mem b/test_regress/t/t_sys_readmem_b_8.mem new file mode 100644 index 000000000..7c811db4b --- /dev/null +++ b/test_regress/t/t_sys_readmem_b_8.mem @@ -0,0 +1,19 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test data file +// +// Copyright 2006 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// General Public License or the Perl Artistic License. + +10000 +10001 +10010 +10011 +/* +multi line +ignored +*/ +10100 +10101 +10110 +10111 diff --git a/test_regress/t/t_sys_readmem_bad_addr.mem b/test_regress/t/t_sys_readmem_bad_addr.mem new file mode 100644 index 000000000..dcba90f53 --- /dev/null +++ b/test_regress/t/t_sys_readmem_bad_addr.mem @@ -0,0 +1,9 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test data file +// +// Copyright 2006 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// General Public License or the Perl Artistic License. + +@121212 +10 diff --git a/test_regress/t/t_sys_readmem_bad_addr.pl b/test_regress/t/t_sys_readmem_bad_addr.pl new file mode 100755 index 000000000..52bc12be9 --- /dev/null +++ b/test_regress/t/t_sys_readmem_bad_addr.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; } +# $Id$ +# 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 +# General Public License or the Perl Artistic License. + +compile ( + ); + +execute ( + fails=>$Last_Self->{v3}, + expect=> +'%Error: t/t_sys_readmem_bad_addr.mem:\d+: \$readmem file address beyond bounds of array', + ); + +ok(1); +1; diff --git a/test_regress/t/t_sys_readmem_bad_addr.v b/test_regress/t/t_sys_readmem_bad_addr.v new file mode 100644 index 000000000..3bde466f3 --- /dev/null +++ b/test_regress/t/t_sys_readmem_bad_addr.v @@ -0,0 +1,15 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2003 by Wilson Snyder. + +module t; + reg [175:0] hex [0:15]; + + initial begin + $readmemh("t/t_sys_readmem_bad_addr.mem", hex); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_sys_readmem_bad_digit.mem b/test_regress/t/t_sys_readmem_bad_digit.mem new file mode 100644 index 000000000..403a1a93e --- /dev/null +++ b/test_regress/t/t_sys_readmem_bad_digit.mem @@ -0,0 +1,9 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test data file +// +// Copyright 2006 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// General Public License or the Perl Artistic License. + +a0 + diff --git a/test_regress/t/t_sys_readmem_bad_digit.pl b/test_regress/t/t_sys_readmem_bad_digit.pl new file mode 100755 index 000000000..720c8d450 --- /dev/null +++ b/test_regress/t/t_sys_readmem_bad_digit.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; } +# $Id$ +# 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 +# General Public License or the Perl Artistic License. + +compile ( + ); + +execute ( + fails=>$Last_Self->{v3}, + expect=> +'%Error: t/t_sys_readmem_bad_digit.mem:\d+: \$readmemb \(binary\) file contains hex characters', + ); + +ok(1); +1; diff --git a/test_regress/t/t_sys_readmem_bad_digit.v b/test_regress/t/t_sys_readmem_bad_digit.v new file mode 100644 index 000000000..f42197a69 --- /dev/null +++ b/test_regress/t/t_sys_readmem_bad_digit.v @@ -0,0 +1,16 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2003 by Wilson Snyder. + +module t; + + reg [175:0] hex [0:15]; + + initial begin + $readmemb("t/t_sys_readmem_bad_digit.mem", hex); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_sys_readmem_bad_end.mem b/test_regress/t/t_sys_readmem_bad_end.mem new file mode 100644 index 000000000..2bc10cf77 --- /dev/null +++ b/test_regress/t/t_sys_readmem_bad_end.mem @@ -0,0 +1,11 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test data file +// +// Copyright 2006 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// General Public License or the Perl Artistic License. + +00 +01 +10 +// Missing additional data diff --git a/test_regress/t/t_sys_readmem_bad_end.pl b/test_regress/t/t_sys_readmem_bad_end.pl new file mode 100755 index 000000000..2913e8fc5 --- /dev/null +++ b/test_regress/t/t_sys_readmem_bad_end.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; } +# $Id$ +# 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 +# General Public License or the Perl Artistic License. + +compile ( + ); + +execute ( + fails=>$Last_Self->{v3}, + expect=> +'%Error: t/t_sys_readmem_bad_end.mem:\d+: \$readmem file ended before specified ending-address', + ); + +ok(1); +1; diff --git a/test_regress/t/t_sys_readmem_bad_end.v b/test_regress/t/t_sys_readmem_bad_end.v new file mode 100644 index 000000000..25c7e847c --- /dev/null +++ b/test_regress/t/t_sys_readmem_bad_end.v @@ -0,0 +1,18 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2003 by Wilson Snyder. + +module t; + + reg [175:0] hex [0:15]; + + integer i; + + initial begin + $readmemh("t/t_sys_readmem_bad_end.mem", hex, 0, 15); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_sys_readmem_bad_notfound.pl b/test_regress/t/t_sys_readmem_bad_notfound.pl new file mode 100755 index 000000000..7ac9031d4 --- /dev/null +++ b/test_regress/t/t_sys_readmem_bad_notfound.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; } +# $Id$ +# 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 +# General Public License or the Perl Artistic License. + +compile ( + ); + +execute ( + fails=>$Last_Self->{v3}, + expect=> +'%Error: t/t_sys_readmem_bad_NOTFOUND.mem:\d+: \$readmem file not found', + ); + +ok(1); +1; diff --git a/test_regress/t/t_sys_readmem_bad_notfound.v b/test_regress/t/t_sys_readmem_bad_notfound.v new file mode 100644 index 000000000..2337d6c8e --- /dev/null +++ b/test_regress/t/t_sys_readmem_bad_notfound.v @@ -0,0 +1,16 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2003 by Wilson Snyder. + +module t; + + reg [175:0] hex [0:15]; + + initial begin + $readmemh("t/t_sys_readmem_bad_NOTFOUND.mem", hex); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_sys_readmem_h.mem b/test_regress/t/t_sys_readmem_h.mem new file mode 100644 index 000000000..d533c565f --- /dev/null +++ b/test_regress/t/t_sys_readmem_h.mem @@ -0,0 +1,13 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test data file +// +// Copyright 2006 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// General Public License or the Perl Artistic License. + +@4 +4004_37654321_27654321_17654321_07654321_abcdef10 +@a +400a_37654321_27654321_17654321_07654321_abcdef11 +400b_37654321_27654321_17654321_07654321_abcdef12 +400c_37654321_27654321_17654321_07654321_abcdef13