From b30b2a183b2e227cea23c3c282c005309115486c Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 20 Nov 2011 02:01:48 -0500 Subject: [PATCH] Support . --- Changes | 2 ++ include/verilated.cpp | 11 ++++++++++ include/verilated.h | 4 ++++ src/V3AstNodes.h | 39 ++++++++++++++++++++++++++++++++++ src/V3EmitC.cpp | 24 +++++++++++++++++++++ src/V3Width.cpp | 8 +++++++ src/verilog.l | 1 + src/verilog.y | 3 +++ test_regress/t/t_sys_system.pl | 18 ++++++++++++++++ test_regress/t/t_sys_system.v | 31 +++++++++++++++++++++++++++ 10 files changed, 141 insertions(+) create mode 100755 test_regress/t/t_sys_system.pl create mode 100644 test_regress/t/t_sys_system.v diff --git a/Changes b/Changes index e9ebc8537..ac1ac74c6 100644 --- a/Changes +++ b/Changes @@ -12,6 +12,8 @@ indicates the contributor was also the author of the fix; Thanks! **** Support constants in sensitivity lists, bug412. [Jeremy Bennett] +**** Support $system. [Ruben Diez] + **** Support $sscanf with %g. [Holger Wächtler] **** Indicate 'exiting due to errors' if errors, not warnings. [Ruben Diez] diff --git a/include/verilated.cpp b/include/verilated.cpp index 1140865d0..6f21f238b 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -937,6 +937,17 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords, } } +IData VL_SYSTEM_IQ(QData lhs) { + IData lhsw[2]; VL_SET_WQ(lhsw, lhs); + return VL_SYSTEM_IW(2, lhsw); +} +IData VL_SYSTEM_IW(int lhswords, WDataInP filenamep) { + char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; + _VL_VINT_TO_STRING(lhswords*VL_WORDSIZE, filenamez, filenamep); + int code = system(filenamez); + return code >> 8; // Want exit status +} + IData VL_TESTPLUSARGS_I(const char* formatp) { string match = VerilatedImp::argPlusMatch(formatp); if (match == "") return 0; diff --git a/include/verilated.h b/include/verilated.h index fdbb92162..66fbbf81a 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -349,6 +349,10 @@ extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...); extern void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...); +extern IData VL_SYSTEM_IW(int lhsnwords, WDataInP lhs); +extern IData VL_SYSTEM_IQ(QData lhs); +inline IData VL_SYSTEM_II(IData lhs) { return VL_SYSTEM_IQ(lhs); } + extern IData VL_TESTPLUSARGS_I(const char* formatp); extern IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp); extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index c7c0faeae..c50ee09b8 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1895,6 +1895,45 @@ public: AstNode* msbp() const { return op4p()->castNode(); } }; +struct AstSystemT : public AstNodeStmt { + // $system used as task + AstSystemT(FileLine* fileline, AstNode* lhsp) + : AstNodeStmt (fileline) { + setOp1p(lhsp); + } + ASTNODE_NODE_FUNCS(SystemT, SYSTEMT) + virtual string verilogKwd() const { return "$system"; } + virtual bool isGateOptimizable() const { return false; } + virtual bool isPredictOptimizable() const { return false; } + virtual bool isSplittable() const { return false; } + virtual bool isOutputter() const { return true; } + virtual bool isUnlikely() const { return true; } + virtual V3Hash sameHash() const { return V3Hash(); } + virtual bool same(AstNode* samep) const { return true; } + AstNode* lhsp() const { return op1p(); } +}; + +struct AstSystemF : public AstNodeMath { + // $system used as function + AstSystemF(FileLine* fileline, AstNode* lhsp) + : AstNodeMath (fileline) { + setOp1p(lhsp); + } + ASTNODE_NODE_FUNCS(SystemF, SYSTEMF) + virtual string verilogKwd() const { return "$system"; } + virtual string emitVerilog() { return verilogKwd(); } + virtual string emitC() { return "VL_SYSTEM_%nq(%lw, %P)"; } + virtual bool isGateOptimizable() const { return false; } + virtual bool isPredictOptimizable() const { return false; } + virtual bool isSplittable() const { return false; } + virtual bool isOutputter() const { return true; } + virtual bool isUnlikely() const { return true; } + virtual bool cleanOut() { return true; } + virtual V3Hash sameHash() const { return V3Hash(); } + virtual bool same(AstNode* samep) const { return true; } + AstNode* lhsp() const { return op1p(); } +}; + struct AstValuePlusArgs : public AstNodeMath { // Parents: expr // Child: variable to set. If NULL then this is a $test$plusargs instead of $value$plusargs diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index d04e16943..e2b3afa86 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -361,6 +361,30 @@ public: puts(")); }\n"); } } + virtual void visit(AstSystemT* nodep, AstNUser*) { + puts("(void)VL_SYSTEM_I"); + emitIQW(nodep->lhsp()); + puts("("); + if (nodep->lhsp()->isWide()) { + puts(cvtToStr(nodep->lhsp()->widthWords())); + putbs(", "); + } + checkMaxWords(nodep->lhsp()); + nodep->lhsp()->iterateAndNext(*this); + puts(");\n"); + } + virtual void visit(AstSystemF* nodep, AstNUser*) { + puts("VL_SYSTEM_I"); + emitIQW(nodep->lhsp()); + puts("("); + if (nodep->lhsp()->isWide()) { + puts(cvtToStr(nodep->lhsp()->widthWords())); + putbs(", "); + } + checkMaxWords(nodep->lhsp()); + nodep->lhsp()->iterateAndNext(*this); + puts(")"); + } virtual void visit(AstJumpGo* nodep, AstNUser*) { puts("goto __Vlabel"+cvtToStr(nodep->labelp()->labelNum())+";\n"); } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index e3b334b1d..2bd7e06e5 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1041,6 +1041,14 @@ private: virtual void visit(AstSysIgnore* nodep, AstNUser* vup) { nodep->exprsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); } + virtual void visit(AstSystemF* nodep, AstNUser*) { + nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); + nodep->numeric(AstNumeric::UNSIGNED); + nodep->width(32,32); + } + virtual void visit(AstSystemT* nodep, AstNUser*) { + nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,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()); diff --git a/src/verilog.l b/src/verilog.l index 0f9b8da04..e7c9eb190 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -215,6 +215,7 @@ word [a-zA-Z0-9_]+ "$stime" { FL; return yD_STIME; } "$stop" { FL; return yD_STOP; } "$swrite" { FL; return yD_SWRITE; } + "$system" { FL; return yD_SYSTEM; } "$test$plusargs" { FL; return yD_TESTPLUSARGS; } "$time" { FL; return yD_TIME; } "$timeskew" { FL; return yaTIMINGSPEC; } diff --git a/src/verilog.y b/src/verilog.y index ba46dafe7..d11fbcd38 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -425,6 +425,7 @@ class AstSenTree; %token yD_STIME "$stime" %token yD_STOP "$stop" %token yD_SWRITE "$swrite" +%token yD_SYSTEM "$system" %token yD_TESTPLUSARGS "$test$plusargs" %token yD_TIME "$time" %token yD_UNIT "$unit" @@ -2133,6 +2134,7 @@ system_t_call: // IEEE: system_tf_call (as task) // | yD_SFORMAT '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); } | yD_SWRITE '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); } + | yD_SYSTEM '(' expr ')' { $$ = new AstSystemT($1,$3); } // | yD_DISPLAY parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY,"", NULL,NULL); } | yD_DISPLAY '(' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY,*$3,NULL,$4); } @@ -2184,6 +2186,7 @@ system_f_call: // IEEE: system_tf_call (as func) | yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); } | yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); } | yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); } + | yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); } | yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); } | yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); } | yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); } diff --git a/test_regress/t/t_sys_system.pl b/test_regress/t/t_sys_system.pl new file mode 100755 index 000000000..7058e622f --- /dev/null +++ b/test_regress/t/t_sys_system.pl @@ -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; diff --git a/test_regress/t/t_sys_system.v b/test_regress/t/t_sys_system.v new file mode 100644 index 000000000..eda684c94 --- /dev/null +++ b/test_regress/t/t_sys_system.v @@ -0,0 +1,31 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2011 by Wilson Snyder. + +module t; + + integer i; + + initial begin +`ifndef VERILATOR + `ifndef VCS + `ifndef NC + $system(); // Legal per spec, but not supported everywhere and nonsensical + `endif + `endif +`endif + $system("exit 0"); + $system("echo hello"); +`ifndef VCS + i = $system("exit 0"); + if (i!==0) $stop; + i = $system("exit 10"); + if (i!==10) $stop; +`endif + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule