Add --autoflush option

This commit is contained in:
Wilson Snyder 2008-07-16 14:06:08 -04:00
parent f0a06182ca
commit 4591f35b7c
11 changed files with 82 additions and 9 deletions

View File

@ -8,6 +8,8 @@ indicates the contributor was also the author of the fix; Thanks!
** Add --x-assign=fast option, and make it the default.
This chooses performance over reset debugging. See the manual.
** Add --autoflush, for flushing streams after $display. [Steve Tong]
*** Add $feof, $fgetc, $fgets, $fflush, $fscanf, $sscanf. [Holger Waechtler]
*** Add $stime. [Holger Waechtler]

View File

@ -177,6 +177,7 @@ descriptions in the next sections for more information.
{file.c/cc/cpp} Optional C++ files to link in
--assert Enable all assertions
--autoflush Flush streams after all $displays
--bin <filename> Override Verilator binary
--cc Create C++ output
--compiler <compiler-name> Tune for specified C++ compiler
@ -254,6 +255,12 @@ desired, but other assertions are, use --assert --nopsl.)
See also --x-assign; setting "--x-assign unique" may be desirable.
=item --autoflush
After every $display or $fdisplay, flush the output stream. This insures
that messages will appear immediately but may reduce performance. Defaults
off, which will buffer output as provided by the normal C stdio calls.
=item --bin I<filename>
Rarely needed. Override the default filename for Verilator itself. When a

View File

@ -306,11 +306,15 @@ public:
puts("=0; }\n");
}
virtual void visit(AstFFlush* nodep, AstNUser*) {
puts("if (");
nodep->filep()->iterateAndNext(*this);
puts(") { fflush (VL_CVT_Q_FP(");
nodep->filep()->iterateAndNext(*this);
puts(")); ");
if (!nodep->filep()) {
puts("fflush (stdout);\n");
} else {
puts("if (");
nodep->filep()->iterateAndNext(*this);
puts(") { fflush (VL_CVT_Q_FP(");
nodep->filep()->iterateAndNext(*this);
puts(")); }\n");
}
}
virtual void visit(AstWhile* nodep, AstNUser*) {
nodep->precondsp()->iterateAndNext(*this);

View File

@ -368,7 +368,9 @@ private:
}
virtual void visit(AstFFlush* nodep, AstNUser*) {
nodep->iterateChildren(*this);
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
if (nodep->filep()) {
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
}
}
virtual void visit(AstFGetC* nodep, AstNUser*) {
nodep->iterateChildren(*this);

View File

@ -563,6 +563,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
else if ( onoff (sw, "-MMD", flag/*ref*/) ) { m_makeDepend = flag; }
else if ( onoff (sw, "-MP", flag/*ref*/) ) { m_makePhony = flag; }
else if ( onoff (sw, "-assert", flag/*ref*/) ) { m_assert = flag; m_psl = flag; }
else if ( onoff (sw, "-autoflush", flag/*ref*/) ) { m_autoflush = flag; }
else if ( !strcmp (sw, "-cc") ) { m_outFormatOk = true; m_systemC = false; m_systemPerl = false; }
else if ( onoff (sw, "-coverage", flag/*ref*/) ) { coverage(flag); }
else if ( onoff (sw, "-coverage-line", flag/*ref*/) ){ m_coverageLine = flag; }
@ -793,6 +794,7 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename) {
V3Options::V3Options() {
m_impp = new V3OptionsImp;
m_autoflush = false;
m_coverageLine = false;
m_coverageUser = false;
m_debugCheck = false;

View File

@ -86,6 +86,7 @@ class V3Options {
bool m_makeDepend; // main switch: -MMD
bool m_makePhony; // main switch: -MP
bool m_assert; // main switch: --assert
bool m_autoflush; // main switch: --autoflush
bool m_coverageLine; // main switch: --coverage-block
bool m_coverageUser; // main switch: --coverage-func
bool m_debugCheck; // main switch: --debug-check
@ -182,6 +183,7 @@ class V3Options {
bool skipIdentical() const { return m_skipIdentical; }
bool stats() const { return m_stats; }
bool assertOn() const { return m_assert; } // assertOn as "assert" may be defined
bool autoflush() const { return m_autoflush; }
bool coverage() const { return m_coverageUser || m_coverageLine; }
bool coverageLine() const { return m_coverageLine; }
bool coverageUser() const { return m_coverageUser; }

View File

@ -23,6 +23,9 @@
// For each wide OP, make a a temporary variable with the wide value
// For each deep expression, assign expression to temporary.
//
// Each display (independant transformation; here as Premit is a good point)
// If autoflush, insert a flush
//
//*************************************************************************
#include "config_build.h"
@ -264,6 +267,26 @@ private:
checkNode(nodep);
}
// Autoflush
virtual void visit(AstDisplay* nodep, AstNUser* vup) {
startStatement(nodep);
nodep->iterateChildren(*this);
m_stmtp = NULL;
if (v3Global.opt.autoflush()) {
AstNode* searchp = nodep->nextp();
while (searchp && searchp->castComment()) searchp = searchp->nextp();
if (searchp
&& searchp->castDisplay()
&& nodep->filep()->sameTree(searchp->castDisplay()->filep())) {
// There's another display next; we can just wait to flush
} else {
UINFO(4,"Autoflush "<<nodep<<endl);
nodep->addNextHere(new AstFFlush(nodep->fileline(),
nodep->filep()->cloneTree(true)));
}
}
}
//--------------------
// Default: Just iterate
virtual void visit(AstVar* nodep, AstNUser*) {} // Don't hit varrefs under vars

View File

@ -586,8 +586,10 @@ private:
widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64);
}
virtual void visit(AstFFlush* nodep, AstNUser*) {
nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p());
widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64);
if (nodep->filep()) {
nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p());
widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64);
}
}
virtual void visit(AstFGetC* nodep, AstNUser* vup) {
nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p());

View File

@ -0,0 +1,22 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.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
# General Public License or the Perl Artistic License.
top_filename("t/t_sys_file_basic.v");
compile (
v_flags2 => ['+incdir+../include',
'+define+AUTOFLUSH'],
verilator_flags2 => ['--autoflush'],
);
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -9,6 +9,7 @@ if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
unlink("obj_dir/t_sys_file_basic_test.log");
compile (
v_flags2 => ['+incdir+../include'],
);
execute (

View File

@ -28,7 +28,13 @@ module t;
if (!$feof(file)) $stop;
`endif
file = $fopen("obj_dir/t_sys_file_basic_test.log","w"); // The "w" is required so we get a FD not a MFD
`ifdef AUTOFLUSH
// The "w" is required so we get a FD not a MFD
file = $fopen("obj_dir/t_sys_file_autoflush.log","w");
`else
// The "w" is required so we get a FD not a MFD
file = $fopen("obj_dir/t_sys_file_basic_test.log","w");
`endif
if ($feof(file)) $stop;
$fdisplay(file, "[%0t] hello v=%x", $time, 32'h12345667);