diff --git a/Changes b/Changes index 968e3f05c..e57f4970d 100644 --- a/Changes +++ b/Changes @@ -11,12 +11,14 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Support arrayed parameter overrides, bug1153. [John Stevenson] -**** Fix non-arrayed cells with interface arrays, bug1153. [John Stevenson] +**** Support modport access to un-modport objects, bug1161. [Todd Strader] **** Add stack trace when can't optimize function, bug1158. [Todd Strader] **** Add warning on mis-sized literal, bug1156. [Todd Strader] +**** Fix non-arrayed cells with interface arrays, bug1153. [John Stevenson] + * Verilator 3.902 2017-04-02 diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 1e3edf65b..41147fe0c 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -445,6 +445,10 @@ public: <<") <- se"<nodep()<importFromIface(symsp(), srcp); + // Allow access to objects not permissible to be listed in a modport + if (srcp->nodep()->castModport()) { + lhsp->importFromIface(symsp(), srcp->parentp(), true); + } } //m_scopeAliasMap[samn].clear(); // Done with it, but put into debug file } diff --git a/src/V3SymTable.h b/src/V3SymTable.h index 4014697fd..55c233ce4 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -183,16 +183,19 @@ public: } return any; } - void importFromIface(VSymGraph* graphp, const VSymEnt* srcp) { + void importFromIface(VSymGraph* graphp, const VSymEnt* srcp, bool onlyUnmodportable = false) { // Import interface tokens from source symbol table into this symbol table, recursively UINFO(9, " importIf se"<<(void*)this<<" from se"<<(void*)srcp<m_idNameMap.begin(); it!=srcp->m_idNameMap.end(); ++it) { const string& name = it->first; VSymEnt* subSrcp = it->second; - VSymEnt* subSymp = new VSymEnt(graphp, subSrcp); - reinsert(name, subSymp); - // And recurse to create children - subSymp->importFromIface(graphp, subSrcp); + AstVar* varp = subSrcp->nodep()->castVar(); + if (!onlyUnmodportable || (varp && varp->varType() == AstVarType::GPARAM)) { + VSymEnt* subSymp = new VSymEnt(graphp, subSrcp); + reinsert(name, subSymp); + // And recurse to create children + subSymp->importFromIface(graphp, subSrcp); + } } } void cellErrorScopes(AstNode* lookp, string prettyName="") { diff --git a/test_regress/t/t_interface_parameter_access.pl b/test_regress/t/t_interface_parameter_access.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_interface_parameter_access.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.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 +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +compile ( + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_interface_parameter_access.v b/test_regress/t/t_interface_parameter_access.v new file mode 100644 index 000000000..efe60b86b --- /dev/null +++ b/test_regress/t/t_interface_parameter_access.v @@ -0,0 +1,80 @@ +// DESCRIPTION: Verilator: Interface parameter getter +// +// A test of the import parameter used with modport +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2015 by Todd Strader + +interface test_if #(parameter integer FOO = 1); + + // Interface variable + logic data; + + // Modport + modport mp( + import getFoo, + output data + ); + + function integer getFoo (); + return FOO; + endfunction + +endinterface // test_if + + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + test_if #( .FOO (5) ) the_interface (); + + testmod testmod_i (.clk (clk), + .intf (the_interface), + .intf_no_mp (the_interface) + ); + +endmodule + + +module testmod + ( + input clk, + test_if.mp intf, + test_if intf_no_mp + ); + +`ifdef ELAB_TIME + localparam THE_FOO = intf.FOO; + // localparam THE_OTHER_FOO = intf_no_mp.FOO; +`endif + + always @(posedge clk) begin +`ifdef ELAB_TIME + if (THE_FOO != 5) begin + $display("%%Error: THE_FOO = %0d", THE_FOO); + $stop; + end + // if (THE_OTHER_FOO != 5) begin + // $display("%%Error: THE_OTHER_FOO = %0d", THE_OTHER_FOO); + // $stop; + // end +`endif + if (intf.FOO != 5) begin + $display("%%Error: intf.FOO = %0d", intf.FOO); + $stop; + end + // if (intf_no_mp.FOO != 5) begin + // $display("%%Error: intf_no_mp.FOO = %0d", intf_no_mp.FOO); + // $stop; + // end + // if (i.getFoo() != 5) begin + // $display("%%Error: i.getFoo() = %0d", i.getFoo()); + // $stop; + // end + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule