Add `systemc_dtor option

git-svn-id: file://localhost/svn/verilator/trunk/verilator@767 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
Wilson Snyder 2006-08-30 17:27:53 +00:00
parent 6358b7f1a3
commit c82235a2de
12 changed files with 128 additions and 67 deletions

View File

@ -7,6 +7,8 @@ indicates the contributor was also the author of the fix; Thanks!
*** Added --inhibit-sim flag for environments using old __Vm_inhibitSim. *** Added --inhibit-sim flag for environments using old __Vm_inhibitSim.
*** Added `systemc_dtor for destructor extentions. [Allan Cochrane]
**** Declare tables static, to reduce D-Cache miss rate. **** Declare tables static, to reduce D-Cache miss rate.
**** Fix $display %m name not matching Verilog name inside SystemC modules. **** Fix $display %m name not matching Verilog name inside SystemC modules.

2
TODO
View File

@ -22,6 +22,8 @@ Features:
Selectable SystemC types based on widths (see notes below) Selectable SystemC types based on widths (see notes below)
Compile time Compile time
Inline first level trace routines Inline first level trace routines
Coverage
Points should be per-scope like everything else rather then per-module
Expression coverage (see notes) Expression coverage (see notes)
More Verilog 2001 Support More Verilog 2001 Support
C-style function and task arguments. [Wim Michiels] C-style function and task arguments. [Wim Michiels]

View File

@ -357,8 +357,8 @@ C++ file exceeds the specified number of operations, a new file will be
created. In addition, any slow routines will be placed into __Slow files. created. In addition, any slow routines will be placed into __Slow files.
This accelerates compilation by as optimization can be disabled on the slow This accelerates compilation by as optimization can be disabled on the slow
routines, and the remaining files can be compiled on parallel machines. routines, and the remaining files can be compiled on parallel machines.
With GCC 3.3 on Opteron, --output-split 20000 will result in splitting into With GCC 3.3 on a 2GHz Opteron, --output-split 20000 will result in
approximately one-minute-compile chunks. splitting into approximately one-minute-compile chunks.
=item --pins64 =item --pins64
@ -963,6 +963,12 @@ Take remaining text up to the next `verilog or `systemc_... mode switch and
place it verbatim into the C++ class constructor. Despite the name of this place it verbatim into the C++ class constructor. Despite the name of this
macro, this also works in pure C++ code. macro, this also works in pure C++ code.
=item `systemc_dtor
Take remaining text up to the next `verilog or `systemc_... mode switch and
place it verbatim into the C++ class destructor. Despite the name of this
macro, this also works in pure C++ code.
=item `systemc_interface =item `systemc_interface
Take remaining text up to the next `verilog or `systemc_... mode switch and Take remaining text up to the next `verilog or `systemc_... mode switch and

View File

@ -2647,6 +2647,17 @@ struct AstScCtor : public AstNodeText {
virtual bool isOutputter() const { return true; } virtual bool isOutputter() const { return true; }
}; };
struct AstScDtor : public AstNodeText {
AstScDtor(FileLine* fl, const string& textp)
: AstNodeText(fl, textp) {}
virtual ~AstScDtor() {}
virtual AstType type() const { return AstType::SCDTOR;}
virtual AstNode* clone() { return new AstScDtor(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual bool isSplittable() const { return false; } // SPECIAL: User may order w/other sigs
virtual bool isOutputter() const { return true; }
};
struct AstScHdr : public AstNodeText { struct AstScHdr : public AstNodeText {
AstScHdr(FileLine* fl, const string& textp) AstScHdr(FileLine* fl, const string& textp)
: AstNodeText(fl, textp) {} : AstNodeText(fl, textp) {}

View File

@ -660,9 +660,11 @@ class EmitCImp : EmitCStmts {
void emitCellCtors(AstModule* modp); void emitCellCtors(AstModule* modp);
void emitSensitives(); void emitSensitives();
// Medium level // Medium level
void emitCoverageCtor(AstModule* modp); void emitCtorImp(AstModule* modp);
void emitConfigureImp(AstModule* modp);
void emitCoverageDecl(AstModule* modp); void emitCoverageDecl(AstModule* modp);
void emitCoverageImp(AstModule* modp); void emitCoverageImp(AstModule* modp);
void emitDestructorImp(AstModule* modp);
void emitTextSection(AstType type); void emitTextSection(AstType type);
void emitIntFuncDecls(AstModule* modp); void emitIntFuncDecls(AstModule* modp);
// High level // High level
@ -1087,19 +1089,6 @@ void EmitCImp::emitVarResets(AstModule* modp) {
} }
} }
void EmitCImp::emitCoverageCtor(AstModule* modp) {
bool first=true;
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (nodep->castCoverDecl()) {
if (first) {
first = false;
puts("// Coverage Declarations\n");
}
nodep->accept(*this);
}
}
}
void EmitCImp::emitCoverageDecl(AstModule* modp) { void EmitCImp::emitCoverageDecl(AstModule* modp) {
m_coverIds.clear(); m_coverIds.clear();
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) { for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
@ -1117,6 +1106,42 @@ void EmitCImp::emitCoverageDecl(AstModule* modp) {
} }
} }
void EmitCImp::emitCtorImp(AstModule* modp) {
puts("\n");
if (optSystemPerl() && modp->isTop()) {
puts("SP_CTOR_IMP("+modClassName(modp)+")");
} else if (optSystemC() && modp->isTop()) {
puts("VL_SC_CTOR_IMP("+modClassName(modp)+")");
} else {
puts("VL_CTOR_IMP("+modClassName(modp)+")");
}
emitVarCtors();
puts(" {\n");
emitCellCtors(modp);
emitSensitives();
emitVarResets(modp);
emitTextSection(AstType::SCCTOR);
if (optSystemPerl()) puts("SP_AUTO_CTOR;\n");
puts("}\n");
}
void EmitCImp::emitConfigureImp(AstModule* modp) {
puts("\nvoid "+modClassName(modp)+"::__Vconfigure("+symClassName()+"* symsp) {\n");
puts( "__VlSymsp = symsp;\n"); // First, as later stuff needs it.
bool first=true;
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (nodep->castCoverDecl()) {
if (first) {
first = false;
puts("// Coverage Declarations\n");
}
nodep->accept(*this);
}
}
puts("}\n");
}
void EmitCImp::emitCoverageImp(AstModule* modp) { void EmitCImp::emitCoverageImp(AstModule* modp) {
if (m_coverIds.size()) { if (m_coverIds.size()) {
puts("\n// Coverage\n"); puts("\n// Coverage\n");
@ -1136,6 +1161,14 @@ void EmitCImp::emitCoverageImp(AstModule* modp) {
} }
} }
void EmitCImp::emitDestructorImp(AstModule* modp) {
puts("\n");
puts(modClassName(modp)+"::~"+modClassName(modp)+"() {\n");
emitTextSection(AstType::SCDTOR);
if (modp->isTop()) puts("delete __VlSymsp; __VlSymsp=NULL;\n");
puts("}\n");
}
void EmitCImp::emitStaticDecl(AstModule* modp) { void EmitCImp::emitStaticDecl(AstModule* modp) {
// Need implementation here. Be careful of alignment code; needs to be uniquified // Need implementation here. Be careful of alignment code; needs to be uniquified
// with module name to avoid multiple symbols. // with module name to avoid multiple symbols.
@ -1419,10 +1452,13 @@ void EmitCImp::emitInt(AstModule* modp) {
ofp()->putsPrivate(false); // public: ofp()->putsPrivate(false); // public:
if (optSystemC() && modp->isTop()) { if (optSystemC() && modp->isTop()) {
puts("SC_CTOR("+modClassName(modp)+");\n"); puts("SC_CTOR("+modClassName(modp)+");\n");
puts("virtual ~"+modClassName(modp)+"();\n");
} else if (optSystemC()) { } else if (optSystemC()) {
puts("VL_CTOR("+modClassName(modp)+");\n"); puts("VL_CTOR("+modClassName(modp)+");\n");
puts("~"+modClassName(modp)+"();\n");
} else { } else {
puts(modClassName(modp)+"(const char* name=\"TOP\");\n"); puts(modClassName(modp)+"(const char* name=\"TOP\");\n");
puts("~"+modClassName(modp)+"();\n");
if (v3Global.opt.trace()) { if (v3Global.opt.trace()) {
puts("void\ttrace (SpTraceVcdCFile* tfp, int levels, int options=0);\n"); puts("void\ttrace (SpTraceVcdCFile* tfp, int levels, int options=0);\n");
} }
@ -1511,34 +1547,14 @@ void EmitCImp::emitImp(AstModule* modp) {
emitStaticDecl(modp); emitStaticDecl(modp);
} }
// Constructor
if (m_slow && m_splitFilenum==0) { if (m_slow && m_splitFilenum==0) {
puts("\n//--------------------\n"); puts("\n//--------------------\n");
puts("\n"); emitCtorImp(modp);
if (optSystemPerl() && modp->isTop()) { emitConfigureImp(modp);
puts("SP_CTOR_IMP("+modClassName(modp)+")"); emitDestructorImp(modp);
} else if (optSystemC() && modp->isTop()) {
puts("VL_SC_CTOR_IMP("+modClassName(modp)+")");
} else {
puts("VL_CTOR_IMP("+modClassName(modp)+")");
}
emitVarCtors();
puts(" {\n");
emitCellCtors(modp);
emitSensitives();
emitVarResets(modp);
emitTextSection(AstType::SCCTOR);
if (optSystemPerl()) puts("SP_AUTO_CTOR;\n");
puts("}\n");
puts("\nvoid "+modClassName(m_modp)+"::__Vconfigure("+symClassName()+"* symsp) {\n");
puts( "__VlSymsp = symsp;\n"); // First, as later stuff needs it.
emitCoverageCtor(modp);
puts("}\n");
emitCoverageImp(modp); emitCoverageImp(modp);
} }
if (m_fast && m_splitFilenum==0) { if (m_fast && m_splitFilenum==0) {
if (modp->isTop()) { if (modp->isTop()) {
emitStaticDecl(modp); emitStaticDecl(modp);

View File

@ -366,6 +366,11 @@ private:
m_modp->modPublic(true); m_modp->modPublic(true);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstScDtor* nodep, AstNUser*) {
// Destructor info means the module must remain public
m_modp->modPublic(true);
nodep->iterateChildren(*this);
}
virtual void visit(AstScInt* nodep, AstNUser*) { virtual void visit(AstScInt* nodep, AstNUser*) {
// Special class info means the module must remain public // Special class info means the module must remain public
m_modp->modPublic(true); m_modp->modPublic(true);

View File

@ -88,7 +88,7 @@ void yyerrorf(const char* format, ...) {
%a 15000 %a 15000
%o 25000 %o 25000
%s VLG PSL STRING SYSCHDR SYSCINT SYSCIMP SYSCIMPH SYSCCTOR IGNORE %s VLG PSL STRING SYSCHDR SYSCINT SYSCIMP SYSCIMPH SYSCCTOR SYSCDTOR IGNORE
ws [ \t\f\r]+ ws [ \t\f\r]+
/* identifier */ /* identifier */
@ -537,24 +537,28 @@ escid \\[^ \t\f\r\n]+
/************************************************************************/ /************************************************************************/
/* Common for all SYSC header states */ /* Common for all SYSC header states */
/* OPTIMIZE: we return one per line, make it one for the entire block */ /* OPTIMIZE: we return one per line, make it one for the entire block */
<VLG,PSL,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,IGNORE>[ \t]*"`verilog" { BEGIN VLG; } <VLG,PSL,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>{
<VLG,PSL,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,IGNORE>[ \t]*"`psl" { if (V3Read::optPsl()) { BEGIN PSL; } else { BEGIN IGNORE; } } [ \t]*"`verilog" { BEGIN VLG; }
<VLG,PSL,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,IGNORE>[ \t]*"`systemc_header" { BEGIN SYSCHDR; } [ \t]*"`psl" { if (V3Read::optPsl()) { BEGIN PSL; } else { BEGIN IGNORE; } }
<VLG,PSL,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,IGNORE>[ \t]*"`systemc_ctor" { BEGIN SYSCCTOR; } [ \t]*"`systemc_header" { BEGIN SYSCHDR; }
<VLG,PSL,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,IGNORE>[ \t]*"`systemc_interface" { BEGIN SYSCINT; } [ \t]*"`systemc_ctor" { BEGIN SYSCCTOR; }
<VLG,PSL,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,IGNORE>[ \t]*"`systemc_implementation" { BEGIN SYSCIMP; } [ \t]*"`systemc_dtor" { BEGIN SYSCDTOR; }
<VLG,PSL,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,IGNORE>[ \t]*"`systemc_imp_header" { BEGIN SYSCIMPH; } [ \t]*"`systemc_interface" { BEGIN SYSCINT; }
<VLG,PSL,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,IGNORE>"`line"[ \t][^\n]*\n {V3Read::ppline(yytext);} [ \t]*"`systemc_implementation" { BEGIN SYSCIMP; }
[ \t]*"`systemc_imp_header" { BEGIN SYSCIMPH; }
"`line"[ \t][^\n]*\n {V3Read::ppline(yytext);}
}
<SYSCHDR>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCHDR;} <SYSCHDR>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCHDR;}
<SYSCINT>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCINT;} <SYSCINT>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCINT;}
<SYSCIMP>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCIMP;} <SYSCIMP>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCIMP;}
<SYSCIMPH>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCIMPH;} <SYSCIMPH>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCIMPH;}
<SYSCCTOR>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCCTOR;} <SYSCCTOR>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCCTOR;}
<SYSCDTOR>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCDTOR;}
<IGNORE>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); } <IGNORE>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); }
<SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,IGNORE>[ \t]*\n { NEXTLINE(); yymore();} <SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>[ \t]*\n { NEXTLINE(); yymore();}
<SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,IGNORE>\r ; <SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>\r ;
/************************************************************************/ /************************************************************************/
/* Default rules - leave last */ /* Default rules - leave last */

View File

@ -125,7 +125,7 @@ class AstSenTree;
%token<nump> yINTNUM %token<nump> yINTNUM
%token<cdouble> yFLOATNUM %token<cdouble> yFLOATNUM
%token<strp> yID ySTRING %token<strp> yID ySTRING
%token<strp> ySCHDR ySCINT ySCIMP ySCIMPH ySCCTOR %token<strp> ySCHDR ySCINT ySCIMP ySCIMPH ySCCTOR ySCDTOR
%token<fileline> yMODULE yENDMODULE yALWAYS yINITIAL yPOSEDGE yNEGEDGE yBBEGIN yBEND yOR %token<fileline> yMODULE yENDMODULE yALWAYS yINITIAL yPOSEDGE yNEGEDGE yBBEGIN yBEND yOR
%token<fileline> yINPUT yOUTPUT yINOUT yWIRE yTRI yREG yPARAM yLOCALPARAM yDEFPARAM %token<fileline> yINPUT yOUTPUT yINOUT yWIRE yTRI yREG yPARAM yLOCALPARAM yDEFPARAM
%token<fileline> yFUNCTION yENDFUNCTION yTASK yENDTASK %token<fileline> yFUNCTION yENDFUNCTION yTASK yENDTASK
@ -405,6 +405,7 @@ modItem: modOrGenItem { $$ = $1; }
| ySCIMP { $$ = new AstScImp(CRELINE(),*$1); } | ySCIMP { $$ = new AstScImp(CRELINE(),*$1); }
| ySCIMPH { $$ = new AstScImpHdr(CRELINE(),*$1); } | ySCIMPH { $$ = new AstScImpHdr(CRELINE(),*$1); }
| ySCCTOR { $$ = new AstScCtor(CRELINE(),*$1); } | ySCCTOR { $$ = new AstScCtor(CRELINE(),*$1); }
| ySCDTOR { $$ = new AstScDtor(CRELINE(),*$1); }
| yVL_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::INLINE_MODULE); } | yVL_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::INLINE_MODULE); }
| yVL_NO_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::NO_INLINE_MODULE); } | yVL_NO_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::NO_INLINE_MODULE); }
| yVL_PUBLIC_MODULE { $$ = new AstPragma($1,AstPragmaType::PUBLIC_MODULE); } | yVL_PUBLIC_MODULE { $$ = new AstPragma($1,AstPragmaType::PUBLIC_MODULE); }

View File

@ -572,6 +572,7 @@ sub _make_main {
print $fh " }\n"; print $fh " }\n";
print $fh " top->final();\n"; print $fh " top->final();\n";
print $fh " SpCoverage::write(\"",$self->{coverage_filename},"\");\n" if $self->{coverage}; print $fh " SpCoverage::write(\"",$self->{coverage_filename},"\");\n" if $self->{coverage};
print $fh " delete top;\n";
print $fh " exit(0L);\n"; print $fh " exit(0L);\n";
print $fh "}\n"; print $fh "}\n";
$fh->close(); $fh->close();

18
test_regress/t/t_extend.pl Executable file
View File

@ -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-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.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -2,11 +2,9 @@
// 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, 2003 by Wilson Snyder. // without warranty, 2003-2006 by Wilson Snyder.
module t_extend (/*AUTOARG*/ module t (/*AUTOARG*/
// Outputs
passed,
// Inputs // Inputs
clk clk
); );
@ -14,7 +12,6 @@ module t_extend (/*AUTOARG*/
/*verilator public_module*/ /*verilator public_module*/
input clk; input clk;
output passed; reg passed; initial passed = 0;
// No verilator_public needed, because it's outside the "" in the $c statement // No verilator_public needed, because it's outside the "" in the $c statement
reg [7:0] cyc; initial cyc=0; reg [7:0] cyc; initial cyc=0;
reg c_worked; reg c_worked;
@ -47,8 +44,7 @@ module t_extend (/*AUTOARG*/
if (cyc == 8'd3) begin if (cyc == 8'd3) begin
if (c_worked !== 1'b1) $stop; if (c_worked !== 1'b1) $stop;
if (c_wider !== 9'h10) $stop; if (c_wider !== 9'h10) $stop;
$write("[%0t] t_extend: Passed\n",$time); $finish;
passed <= 1'b1;
end end
end end
@ -72,6 +68,9 @@ module t_extend (/*AUTOARG*/
#endif #endif
`systemc_ctor `systemc_ctor
m_did_ctor = 1; m_did_ctor = 1;
`systemc_dtor
printf("In systemc_dtor\n");
printf("*-* All Finished *-*\n");
`verilog `verilog
`endif `endif

View File

@ -1,4 +1,4 @@
// $Id:$ // $Id$
// 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,
@ -90,16 +90,12 @@ module t (/*AUTOARG*/
// Inputs // Inputs
.clk (clk), .clk (clk),
.fastclk (fastclk)); .fastclk (fastclk));
t_extend textend t_loop tloop
(.passed (passedv[15]), (.passed (passedv[15]),
/*AUTOINST*/ /*AUTOINST*/
// Inputs // Inputs
.clk (clk)); .clk (clk));
t_loop tloop assign passedv[16] = 1'b1;
(.passed (passedv[16]),
/*AUTOINST*/
// Inputs
.clk (clk));
assign passedv[17] = 1'b1; assign passedv[17] = 1'b1;
assign passedv[18] = 1'b1; assign passedv[18] = 1'b1;
t_task ttask t_task ttask