From c82235a2de335ab1d4d18d7a386eeae62f54adf1 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 30 Aug 2006 17:27:53 +0000 Subject: [PATCH] Add `systemc_dtor option git-svn-id: file://localhost/svn/verilator/trunk/verilator@767 77ca24e4-aefa-0310-84f0-b9a241c72d87 --- Changes | 2 + TODO | 4 +- bin/verilator | 10 ++- src/V3AstNodes.h | 11 ++++ src/V3EmitC.cpp | 92 ++++++++++++++++----------- src/V3LinkResolve.cpp | 5 ++ src/verilog.l | 26 ++++---- src/verilog.y | 3 +- test_regress/driver.pl | 1 + test_regress/t/t_extend.pl | 18 ++++++ {test_v => test_regress/t}/t_extend.v | 13 ++-- test_v/t.v | 10 +-- 12 files changed, 128 insertions(+), 67 deletions(-) create mode 100755 test_regress/t/t_extend.pl rename {test_v => test_regress/t}/t_extend.v (88%) diff --git a/Changes b/Changes index 6903af515..b977e01e0 100644 --- a/Changes +++ b/Changes @@ -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 `systemc_dtor for destructor extentions. [Allan Cochrane] + **** Declare tables static, to reduce D-Cache miss rate. **** Fix $display %m name not matching Verilog name inside SystemC modules. diff --git a/TODO b/TODO index 2dd701eee..1b5da6d7e 100644 --- a/TODO +++ b/TODO @@ -22,7 +22,9 @@ Features: Selectable SystemC types based on widths (see notes below) Compile time Inline first level trace routines - Expression coverage (see notes) + Coverage + Points should be per-scope like everything else rather then per-module + Expression coverage (see notes) More Verilog 2001 Support C-style function and task arguments. [Wim Michiels] (* *) Attributes (just ignore -- preprocessor?) diff --git a/bin/verilator b/bin/verilator index 4a04c3a36..98d3268b0 100755 --- a/bin/verilator +++ b/bin/verilator @@ -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. This accelerates compilation by as optimization can be disabled on the slow 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 -approximately one-minute-compile chunks. +With GCC 3.3 on a 2GHz Opteron, --output-split 20000 will result in +splitting into approximately one-minute-compile chunks. =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 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 Take remaining text up to the next `verilog or `systemc_... mode switch and diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 7a971846f..7dc1bd23d 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -2647,6 +2647,17 @@ struct AstScCtor : public AstNodeText { 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 { AstScHdr(FileLine* fl, const string& textp) : AstNodeText(fl, textp) {} diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index a552b3bd9..0152d2539 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -660,9 +660,11 @@ class EmitCImp : EmitCStmts { void emitCellCtors(AstModule* modp); void emitSensitives(); // Medium level - void emitCoverageCtor(AstModule* modp); + void emitCtorImp(AstModule* modp); + void emitConfigureImp(AstModule* modp); void emitCoverageDecl(AstModule* modp); void emitCoverageImp(AstModule* modp); + void emitDestructorImp(AstModule* modp); void emitTextSection(AstType type); void emitIntFuncDecls(AstModule* modp); // 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) { m_coverIds.clear(); 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) { if (m_coverIds.size()) { 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) { // Need implementation here. Be careful of alignment code; needs to be uniquified // with module name to avoid multiple symbols. @@ -1419,10 +1452,13 @@ void EmitCImp::emitInt(AstModule* modp) { ofp()->putsPrivate(false); // public: if (optSystemC() && modp->isTop()) { puts("SC_CTOR("+modClassName(modp)+");\n"); + puts("virtual ~"+modClassName(modp)+"();\n"); } else if (optSystemC()) { puts("VL_CTOR("+modClassName(modp)+");\n"); + puts("~"+modClassName(modp)+"();\n"); } else { puts(modClassName(modp)+"(const char* name=\"TOP\");\n"); + puts("~"+modClassName(modp)+"();\n"); if (v3Global.opt.trace()) { puts("void\ttrace (SpTraceVcdCFile* tfp, int levels, int options=0);\n"); } @@ -1511,34 +1547,14 @@ void EmitCImp::emitImp(AstModule* modp) { emitStaticDecl(modp); } - // Constructor if (m_slow && m_splitFilenum==0) { puts("\n//--------------------\n"); - 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"); - - puts("\nvoid "+modClassName(m_modp)+"::__Vconfigure("+symClassName()+"* symsp) {\n"); - puts( "__VlSymsp = symsp;\n"); // First, as later stuff needs it. - emitCoverageCtor(modp); - puts("}\n"); - + emitCtorImp(modp); + emitConfigureImp(modp); + emitDestructorImp(modp); emitCoverageImp(modp); } + if (m_fast && m_splitFilenum==0) { if (modp->isTop()) { emitStaticDecl(modp); diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index f108f2e87..77d4ee0e1 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -366,6 +366,11 @@ private: m_modp->modPublic(true); 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*) { // Special class info means the module must remain public m_modp->modPublic(true); diff --git a/src/verilog.l b/src/verilog.l index 9560de1dd..3670af8d2 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -88,7 +88,7 @@ void yyerrorf(const char* format, ...) { %a 15000 %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]+ /* identifier */ @@ -537,24 +537,28 @@ escid \\[^ \t\f\r\n]+ /************************************************************************/ /* Common for all SYSC header states */ /* OPTIMIZE: we return one per line, make it one for the entire block */ -[ \t]*"`verilog" { BEGIN VLG; } -[ \t]*"`psl" { if (V3Read::optPsl()) { BEGIN PSL; } else { BEGIN IGNORE; } } -[ \t]*"`systemc_header" { BEGIN SYSCHDR; } -[ \t]*"`systemc_ctor" { BEGIN SYSCCTOR; } -[ \t]*"`systemc_interface" { BEGIN SYSCINT; } -[ \t]*"`systemc_implementation" { BEGIN SYSCIMP; } -[ \t]*"`systemc_imp_header" { BEGIN SYSCIMPH; } -"`line"[ \t][^\n]*\n {V3Read::ppline(yytext);} +{ + [ \t]*"`verilog" { BEGIN VLG; } + [ \t]*"`psl" { if (V3Read::optPsl()) { BEGIN PSL; } else { BEGIN IGNORE; } } + [ \t]*"`systemc_header" { BEGIN SYSCHDR; } + [ \t]*"`systemc_ctor" { BEGIN SYSCCTOR; } + [ \t]*"`systemc_dtor" { BEGIN SYSCDTOR; } + [ \t]*"`systemc_interface" { BEGIN SYSCINT; } + [ \t]*"`systemc_implementation" { BEGIN SYSCIMP; } + [ \t]*"`systemc_imp_header" { BEGIN SYSCIMPH; } + "`line"[ \t][^\n]*\n {V3Read::ppline(yytext);} +} [ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCHDR;} [ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCINT;} [ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCIMP;} [ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCIMPH;} [ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCCTOR;} +[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return ySCDTOR;} [ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); } -[ \t]*\n { NEXTLINE(); yymore();} -\r ; +[ \t]*\n { NEXTLINE(); yymore();} +\r ; /************************************************************************/ /* Default rules - leave last */ diff --git a/src/verilog.y b/src/verilog.y index 827b29065..bd107d947 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -125,7 +125,7 @@ class AstSenTree; %token yINTNUM %token yFLOATNUM %token yID ySTRING -%token ySCHDR ySCINT ySCIMP ySCIMPH ySCCTOR +%token ySCHDR ySCINT ySCIMP ySCIMPH ySCCTOR ySCDTOR %token yMODULE yENDMODULE yALWAYS yINITIAL yPOSEDGE yNEGEDGE yBBEGIN yBEND yOR %token yINPUT yOUTPUT yINOUT yWIRE yTRI yREG yPARAM yLOCALPARAM yDEFPARAM %token yFUNCTION yENDFUNCTION yTASK yENDTASK @@ -405,6 +405,7 @@ modItem: modOrGenItem { $$ = $1; } | ySCIMP { $$ = new AstScImp(CRELINE(),*$1); } | ySCIMPH { $$ = new AstScImpHdr(CRELINE(),*$1); } | ySCCTOR { $$ = new AstScCtor(CRELINE(),*$1); } + | ySCDTOR { $$ = new AstScDtor(CRELINE(),*$1); } | yVL_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::INLINE_MODULE); } | yVL_NO_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::NO_INLINE_MODULE); } | yVL_PUBLIC_MODULE { $$ = new AstPragma($1,AstPragmaType::PUBLIC_MODULE); } diff --git a/test_regress/driver.pl b/test_regress/driver.pl index 922b7249d..d2206430b 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -572,6 +572,7 @@ sub _make_main { print $fh " }\n"; print $fh " top->final();\n"; print $fh " SpCoverage::write(\"",$self->{coverage_filename},"\");\n" if $self->{coverage}; + print $fh " delete top;\n"; print $fh " exit(0L);\n"; print $fh "}\n"; $fh->close(); diff --git a/test_regress/t/t_extend.pl b/test_regress/t/t_extend.pl new file mode 100755 index 000000000..66168354c --- /dev/null +++ b/test_regress/t/t_extend.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-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; diff --git a/test_v/t_extend.v b/test_regress/t/t_extend.v similarity index 88% rename from test_v/t_extend.v rename to test_regress/t/t_extend.v index 5e2c8c1a1..a6a967f86 100644 --- a/test_v/t_extend.v +++ b/test_regress/t/t_extend.v @@ -2,11 +2,9 @@ // DESCRIPTION: Verilator: Verilog Test module // // 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*/ - // Outputs - passed, +module t (/*AUTOARG*/ // Inputs clk ); @@ -14,7 +12,6 @@ module t_extend (/*AUTOARG*/ /*verilator public_module*/ input clk; - output passed; reg passed; initial passed = 0; // No verilator_public needed, because it's outside the "" in the $c statement reg [7:0] cyc; initial cyc=0; reg c_worked; @@ -47,8 +44,7 @@ module t_extend (/*AUTOARG*/ if (cyc == 8'd3) begin if (c_worked !== 1'b1) $stop; if (c_wider !== 9'h10) $stop; - $write("[%0t] t_extend: Passed\n",$time); - passed <= 1'b1; + $finish; end end @@ -72,6 +68,9 @@ module t_extend (/*AUTOARG*/ #endif `systemc_ctor m_did_ctor = 1; + `systemc_dtor + printf("In systemc_dtor\n"); + printf("*-* All Finished *-*\n"); `verilog `endif diff --git a/test_v/t.v b/test_v/t.v index b172e00fb..f10647352 100644 --- a/test_v/t.v +++ b/test_v/t.v @@ -1,4 +1,4 @@ -// $Id:$ +// $Id$ // DESCRIPTION: Verilator: Verilog Test module // // This file ONLY is placed into the Public Domain, for any use, @@ -90,16 +90,12 @@ module t (/*AUTOARG*/ // Inputs .clk (clk), .fastclk (fastclk)); - t_extend textend + t_loop tloop (.passed (passedv[15]), /*AUTOINST*/ // Inputs .clk (clk)); - t_loop tloop - (.passed (passedv[16]), - /*AUTOINST*/ - // Inputs - .clk (clk)); + assign passedv[16] = 1'b1; assign passedv[17] = 1'b1; assign passedv[18] = 1'b1; t_task ttask