diff --git a/Changes b/Changes index 1b7bc3b35..88711eb62 100644 --- a/Changes +++ b/Changes @@ -13,6 +13,8 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Add --no-relative-cfuncs and related default optimization, bug1224. [John Coiner] +*** Add /*verilator tag*/ for XML extraction applications. [Chris Randall] + **** The internal test_verilated test directory is moved to be part of test_regress. **** Fix over-aggressive inlining, bug1223. [John Coiner] diff --git a/bin/verilator b/bin/verilator index d647c032b..847ef3705 100755 --- a/bin/verilator +++ b/bin/verilator @@ -2574,6 +2574,12 @@ indicate the function or task should pass all remaining arguments through $sformatf. This allows creation of DPI functions with $display like behavior. See the test_regress/t/t_dpi_display.v file for an example. +=item /*verilator tag */ + +Attached after a variable or structure member to indicate opaque (to +Verilator) text that should be passed through to the XML output as a tag, +for use by downstream applications. + =item /*verilator tracing_off*/ Disable waveform tracing for all future signals that are declared in this diff --git a/src/V3Ast.h b/src/V3Ast.h index d5bc08457..7336e1674 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1087,6 +1087,8 @@ public: // ACCESSORS virtual string name() const { return ""; } virtual void name(const string& name) { this->v3fatalSrc("name() called on object without name() method"); } + virtual void tag(const string& text) {} + virtual string tag() const { return ""; } virtual string verilogKwd() const { return ""; } string shortName() const; // Name with __PVT__ removed for concatenating scopes static string dedotName(const string& namein); // Name with dots removed diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index cd9232d63..757399064 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -610,6 +610,7 @@ class AstMemberDType : public AstNodeDType { private: AstNodeDType* m_refDTypep; // Elements of this type (after widthing) string m_name; // Name of variable + string m_tag; // Holds the string of the verilator tag -- used in XML output. int m_lsb; // Within this level's packed struct, the LSB of the first bit of the member //UNSUP: int m_randType; // Randomization type (IEEE) public: @@ -650,6 +651,8 @@ public: virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... // METHODS virtual void name(const string& name) { m_name = name; } + virtual void tag(const string& text) { m_tag = text;} + virtual string tag() const { return m_tag; } int lsb() const { return m_lsb; } void lsb(int lsb) { m_lsb=lsb; } }; @@ -978,6 +981,7 @@ class AstVar : public AstNode { private: string m_name; // Name of variable string m_origName; // Original name before dot addition + string m_tag; // Holds the string of the verilator tag -- used in XML output. AstVarType m_varType; // Type of variable bool m_input:1; // Input or inout bool m_output:1; // Output or inout @@ -1118,6 +1122,8 @@ public: void trace(bool flag) { m_trace=flag; } // METHODS virtual void name(const string& name) { m_name = name; } + virtual void tag(const string& text) { m_tag = text;} + virtual string tag() const { return m_tag; } virtual string directionName() const { return (isInout() ? "inout" : isInput() ? "input" : isOutput() ? "output" : varType().ascii()); } bool isInput() const { return m_input; } diff --git a/src/V3EmitXml.cpp b/src/V3EmitXml.cpp index c385a1885..bf488b7ee 100644 --- a/src/V3EmitXml.cpp +++ b/src/V3EmitXml.cpp @@ -68,6 +68,7 @@ class EmitXmlFileVisitor : public AstNVisitor { if (tag=="") tag = VString::downcase(nodep->typeName()); puts("<"+tag+" "+nodep->fileline()->xml()); if (nodep->name()!="") { puts(" name="); putsQuoted(nodep->prettyName()); } + if (nodep->tag()!="") { puts(" tag="); putsQuoted(nodep->tag()); } } void outputChildrenEnd(AstNode* nodep, string tag) { if (tag=="") tag = VString::downcase(nodep->typeName()); diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index 4ba76543a..9ca603356 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -119,6 +119,8 @@ class V3ParseImp { deque m_lintState; // Current lint state for save/restore deque m_ppBuffers; // Preprocessor->lex buffer of characters to process + string m_tag; // Contents (if any) of current verilator tag + AstNode* m_tagNodep; // Points to the node to set to m_tag or NULL to not set. public: // Note these are an exception to using the filename as the debug type static int debugBison() { @@ -143,6 +145,10 @@ public: void verilatorCmtLintSave(); void verilatorCmtLintRestore(); void verilatorCmtBad(const char* text); + void tag(const char* text); + void tagNodep(AstNode* nodep) { m_tagNodep = nodep; } + AstNode* tagNodep() const { return m_tagNodep;} + static double parseDouble(const char* text, size_t length, bool* successp = NULL); void pushBeginKeywords(int state) { m_inBeginKwd++; m_lastVerilogState=state; } bool popBeginKeywords() { if (m_inBeginKwd) { m_inBeginKwd--; return true; } else return false; } @@ -218,6 +224,7 @@ public: m_curBisonVal.token = 0; m_prevBisonVal.token = 0; // m_aheadVal not used as m_ahead = false + m_tagNodep = NULL; } ~V3ParseImp(); void parserClear(); diff --git a/src/verilog.l b/src/verilog.l index decc4b8b0..10f59a744 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -102,6 +102,15 @@ void V3ParseImp::verilatorCmtBad(const char* textp) { } } +void V3ParseImp::tag(const char* text) { + if (m_tagNodep) { + string tmp = text + strlen("/*verilator tag "); + string::size_type pos; + if ((pos=tmp.rfind("*/")) != string::npos) { tmp.erase(pos); } + m_tagNodep->tag(tmp); + } +} + // See V3Read.cpp //void V3ParseImp::statePop() { yy_pop_state(); } @@ -702,6 +711,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "/*verilator lint_on"[^*]*"*/" {PARSEP->verilatorCmtLint(yytext, false); } "/*verilator lint_restore*/" {PARSEP->verilatorCmtLintRestore(); } "/*verilator lint_save*/" {PARSEP->verilatorCmtLintSave(); } + "/*verilator tag"[^*]*"*/" {PARSEP->tag(yytext); } "/**/" { } "/*"[^*]+"*/" {PARSEP->verilatorCmtBad(yytext); } diff --git a/src/verilog.y b/src/verilog.y index 672525bbf..f6ac5aec4 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -1425,7 +1425,9 @@ member_decl_assignment: // Derived from IEEE: variable_decl_assignment // // At present we allow only packed structures/unions. So this is different from variable_decl_assignment id variable_dimensionListE { if ($2) $2->v3error("Unsupported: Unpacked array in packed struct/union"); - $$ = new AstMemberDType($1, *$1, VFlagChildDType(), GRAMMARP->m_memDTypep->cloneTree(true)); } + $$ = new AstMemberDType($1, *$1, VFlagChildDType(), GRAMMARP->m_memDTypep->cloneTree(true)); + PARSEP->tagNodep($$); + } | id variable_dimensionListE '=' variable_declExpr { $4->v3error("Unsupported: Initial values in struct/union members."); } | idSVKwd { $$ = NULL; } @@ -3874,6 +3876,7 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstRange // Remember the last variable created, so we can attach attributes to it in later parsing GRAMMARP->m_varAttrp = nodep; + PARSEP->tagNodep(GRAMMARP->m_varAttrp); return nodep; } diff --git a/test_regress/t/t_xml_tag.out b/test_regress/t/t_xml_tag.out new file mode 100644 index 000000000..dbeb81c69 --- /dev/null +++ b/test_regress/t/t_xml_tag.out @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test_regress/t/t_xml_tag.pl b/test_regress/t/t_xml_tag.pl new file mode 100755 index 000000000..31b7a1d91 --- /dev/null +++ b/test_regress/t/t_xml_tag.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2012 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. + +$Self->{vlt} or $Self->skip("Verilator only test"); + +my $out_filename = "$Self->{obj_dir}/V$Self->{name}.xml"; + +compile ( + verilator_flags2 => ['--xml-only'], + verilator_make_gcc => 0, + ); + +ok(files_identical("$out_filename", "t/$Self->{name}.out")); +1; diff --git a/test_regress/t/t_xml_tag.v b/test_regress/t/t_xml_tag.v new file mode 100644 index 000000000..db8ae3bd9 --- /dev/null +++ b/test_regress/t/t_xml_tag.v @@ -0,0 +1,25 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2017 by Chris Randall. + +module m + ( + input clk_ip, // verilator tag clk_ip + input rst_ip, + output foo_op); // verilator tag foo_op + + // This is a comment + + typedef struct packed { + logic clk; /* verilator tag this is clk */ + logic k; /* verilator lint_off UNUSED */ + logic enable; // verilator tag enable + logic data; // verilator tag data + } my_struct; + + // This is a comment + + my_struct this_struct; + +endmodule