diff --git a/docs/guide/extensions.rst b/docs/guide/extensions.rst index ca6a36ddc..d18987055 100644 --- a/docs/guide/extensions.rst +++ b/docs/guide/extensions.rst @@ -111,6 +111,15 @@ or "`ifdef`"'s may break other tools. class/endclass pair. Despite the name of this macro, this also works in pure C++ code. +.. option:: `systemc_header_post + + Take the remaining text up to the next :option:`\`verilog` or + :option:`\`systemc_... <\`systemc_header>` mode switch and place it + verbatim into the output .h file's header after the class definition. + Must be placed as a module or class item, e.g., directly inside a + module/endmodule or class/endclass pair. Despite the name of this macro, + this also works in pure C++ code. + .. option:: `systemc_class_name Inside one of the :option:`\`systemc_... <\`systemc_header>` text diff --git a/docs/guide/languages.rst b/docs/guide/languages.rst index abf4e6862..4c8d3a022 100644 --- a/docs/guide/languages.rst +++ b/docs/guide/languages.rst @@ -396,8 +396,8 @@ This section describes specific limitations for each language keyword. \`begin_keywords, \`begin_keywords, \`begin_keywords, \`begin_keywords, \`define, \`else, \`elsif, \`end_keywords, \`endif, \`error, \`ifdef, \`ifndef, \`include, \`line, \`systemc_ctor, \`systemc_dtor, - \`systemc_header, \`systemc_imp_header, \`systemc_implementation, - \`systemc_interface, \`undef, \`verilog + \`systemc_header, \`systemc_header_post, \`systemc_imp_header, + \`systemc_implementation, \`systemc_interface, \`undef, \`verilog |cmdslong1| Fully supported. diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index dd56e2ce7..26c895c29 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -3898,6 +3898,14 @@ public: bool isPure() override { return false; } // SPECIAL: User may order w/other sigs bool isOutputter() override { return true; } }; +class AstScHdrPost final : public AstNodeText { +public: + AstScHdrPost(FileLine* fl, const string& textp) + : ASTGEN_SUPER_ScHdrPost(fl, textp) {} + ASTGEN_MEMBERS_AstScHdrPost; + bool isPure() override { return false; } // SPECIAL: User may order w/other sigs + bool isOutputter() override { return true; } +}; class AstScImp final : public AstNodeText { public: AstScImp(FileLine* fl, const string& textp) diff --git a/src/V3EmitCHeaders.cpp b/src/V3EmitCHeaders.cpp index b4acd5d48..7aedb9855 100644 --- a/src/V3EmitCHeaders.cpp +++ b/src/V3EmitCHeaders.cpp @@ -595,6 +595,7 @@ class EmitCHeader final : public EmitCConstInit { // Emit out of class function declarations puts("\n"); emitFuncDecls(modp, /* inClassBody: */ false); + emitTextSection(modp, VNType::atScHdrPost); } explicit EmitCHeader(const AstNodeModule* modp) { diff --git a/src/V3LanguageWords.h b/src/V3LanguageWords.h index c04603efa..ad7acdaad 100644 --- a/src/V3LanguageWords.h +++ b/src/V3LanguageWords.h @@ -238,6 +238,7 @@ inline void V3LanguageWords::Singleton::init() { addKwd("`systemc_ctor", "Verilator preprocessor directive"); addKwd("`systemc_dtor", "Verilator preprocessor directive"); addKwd("`systemc_header", "Verilator preprocessor directive"); + addKwd("`systemc_header_post", "Verilator preprocessor directive"); addKwd("`systemc_imp_header", "Verilator preprocessor directive"); addKwd("`systemc_implementation", "Verilator preprocessor directive"); addKwd("`systemc_interface", "Verilator preprocessor directive"); diff --git a/src/verilog.l b/src/verilog.l index 11b606307..eb13dbaf8 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -81,7 +81,7 @@ static double lexParseDouble(FileLine* fl, const char* textp, size_t length) { %s V95 V01NC V01C V05 S05 S09 S12 S17 S23 %s ATTRMODE QQQ STRING TABLE %s VA5 SAX VLT -%s SYSCHDR SYSCINT SYSCIMP SYSCIMPH SYSCCTOR SYSCDTOR +%s SYSCHDR SYSCHDRP SYSCINT SYSCIMP SYSCIMPH SYSCCTOR SYSCDTOR ws [ \t\f\r]+ wsnr [ \t\f]+ @@ -1028,7 +1028,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} /* Common for all SYSC header states */ /* OPTIMIZE: we return one per line, make it one for the entire block */ /* If add to this list also add to V3LanguageWords.h */ -{ +{ "`accelerate" { FL_FWD; FL_BRK; } // Verilog-XL compatibility "`autoexpand_vectornets" { FL_FWD; FL_BRK; } // Verilog-XL compatibility "`celldefine" { FL_FWD; PARSEP->lexFileline()->celldefineOn(true); FL_BRK; } @@ -1100,6 +1100,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "`systemc_ctor" { FL_FWD; BEGIN SYSCCTOR; FL_BRK; } "`systemc_dtor" { FL_FWD; BEGIN SYSCDTOR; FL_BRK; } "`systemc_header" { FL_FWD; BEGIN SYSCHDR; FL_BRK; } + "`systemc_header_post" { FL_FWD; BEGIN SYSCHDRP; FL_BRK; } "`systemc_imp_header" { FL_FWD; BEGIN SYSCIMPH; FL_BRK; } "`systemc_implementation" { FL_FWD; BEGIN SYSCIMP; FL_BRK; } "`systemc_interface" { FL_FWD; BEGIN SYSCINT; FL_BRK; } @@ -1115,6 +1116,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} } [ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; yylval.strp = PARSEP->newString(yytext); return yaSCHDR; } +[ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; yylval.strp = PARSEP->newString(yytext); return yaSCHDRP; } [ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; yylval.strp = PARSEP->newString(yytext); return yaSCINT; } [ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; yylval.strp = PARSEP->newString(yytext); return yaSCIMP; } [ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; yylval.strp = PARSEP->newString(yytext); return yaSCIMPH; } @@ -1122,7 +1124,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} [ \t]*[^` \t\n\r][^\n\r]*{crnl} { FL; yylval.strp = PARSEP->newString(yytext); return yaSCDTOR; } /* Pick up text-type data */ -{ +{ {wsnr}* { yymore(); } {crnl} { yymore(); } } diff --git a/src/verilog.y b/src/verilog.y index 5885da7f0..c75848d4e 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -453,6 +453,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yaSCCTOR "`systemc_ctor block" %token yaSCDTOR "`systemc_dtor block" %token yaSCHDR "`systemc_header block" +%token yaSCHDRP "`systemc_header_post block" %token yaSCIMP "`systemc_implementation block" %token yaSCIMPH "`systemc_imp_header block" %token yaSCINT "`systemc_interface block" @@ -2738,6 +2739,7 @@ non_port_module_item: // ==IEEE: non_port_module_item vlScBlock: // Verilator-specific `systemc_* blocks yaSCHDR { $$ = new AstScHdr{$1, *$1}; v3Global.setHasSCTextSections(); } + | yaSCHDRP { $$ = new AstScHdrPost{$1, *$1}; v3Global.setHasSCTextSections(); } | yaSCINT { $$ = new AstScInt{$1, *$1}; v3Global.setHasSCTextSections(); } | yaSCIMP { $$ = new AstScImp{$1, *$1}; v3Global.setHasSCTextSections(); } | yaSCIMPH { $$ = new AstScImpHdr{$1, *$1}; v3Global.setHasSCTextSections(); } diff --git a/test_regress/t/t_extend_class.v b/test_regress/t/t_extend_class.v index d5bd34405..fc00e295b 100644 --- a/test_regress/t/t_extend_class.v +++ b/test_regress/t/t_extend_class.v @@ -12,6 +12,8 @@ class Cls; `ifdef verilator `systemc_header #define DID_INT_HEADER 1 + `systemc_header_post +inline void `systemc_class_name::my_inline_function() {} `systemc_interface #ifndef DID_INT_HEADER #error "`systemc_header didn't work" @@ -22,6 +24,7 @@ class Cls; return 1; } static void my_imp_function(); + static void my_inline_function(); `systemc_imp_header #define DID_IMP_HEADER 1 @@ -49,6 +52,7 @@ module t (/*AUTOARG*/); c = new; i = $c(c, "->my_function()"); $c(c, "->my_imp_function();"); + $c(c, "->my_inline_function();"); c = null; // Causes destruction and All Finished $finish; end