diff --git a/Changes b/Changes index 418720645..2e765de1e 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,8 @@ indicates the contributor was also the author of the fix; Thanks! ** Add --vpi flag, and fix VPI linkage, bug969. [Arthur Kahlich] +** Support genvar indexes into arrayed cells, bug517. [Todd Strader] + ** Support $sformatf, bug977. [Johan Bjork] **** Add VerilatedScopeNameMap for introspection, bug966. [Todd Strader] diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 05916c980..39105e715 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1311,6 +1311,7 @@ public: ASTNODE_NODE_FUNCS(VarXRef, VARXREF) virtual void dump(ostream& str); string dotted() const { return m_dotted; } + void dotted(const string& dotted) { m_dotted = dotted; } string prettyDotted() const { return prettyName(dotted()); } string inlinedDots() const { return m_inlinedDots; } void inlinedDots(const string& flag) { m_inlinedDots = flag; } @@ -1570,6 +1571,56 @@ public: virtual void name(const string& name) { m_name = name; } }; +class AstCellRef : public AstNode { + // As-of-yet unlinkable reference into a cell +private: + string m_name; // Cell name +public: + AstCellRef(FileLine* fl, + string name, AstNode* cellp, AstNode* exprp) + : AstNode(fl) + , m_name(name) { + addNOp1p(cellp); addNOp2p(exprp); } + ASTNODE_NODE_FUNCS(CellRef, CELLREF) + // ACCESSORS + virtual string name() const { return m_name; } // * = Array name + AstNode* cellp() const { return op1p(); } // op1 = Cell + AstNode* exprp() const { return op2p(); } // op2 = Expression +}; + +class AstCellArrayRef : public AstNode { + // As-of-yet unlinkable reference into an array of cells +private: + string m_name; // Array name +public: + AstCellArrayRef(FileLine* fl, + string name, AstNode* selectExprp) + : AstNode(fl) + , m_name(name) { + addNOp1p(selectExprp); } + ASTNODE_NODE_FUNCS(CellArrayRef, CELLARRAYREF) + // ACCESSORS + virtual string name() const { return m_name; } // * = Array name + AstNode* selp() const { return op1p(); } // op1 = Select expression +}; + +class AstUnlinkedVarXRef : public AstNode { + // As-of-yet unlinkable VarXRef +private: + string m_name; // Var name +public: + AstUnlinkedVarXRef(FileLine* fl, + AstVarXRef* vxrp, string name, AstNode* crp) + : AstNode(fl) + , m_name(name) { + addNOp1p(vxrp); addNOp2p(crp); } + ASTNODE_NODE_FUNCS(UnlinkedVarXRef, UNLINKEDVARXREF) + // ACCESSORS + virtual string name() const { return m_name; } // * = Var name + AstVarXRef* varxrefp() const { return op1p()->castVarXRef(); } // op1 = VarXRef + AstNode* cellrefp() const { return op2p(); } // op1 = CellArrayRef or CellRef +}; + class AstBind : public AstNode { // Parents: MODULE // Children: CELL diff --git a/src/V3Const.cpp b/src/V3Const.cpp index f434d49ca..ed757d855 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1446,7 +1446,7 @@ private: } m_selp = NULL; } - virtual void visit(AstVarRef* nodep, AstNUser*) { + virtual void visit(AstNodeVarRef* nodep, AstNUser*) { nodep->iterateChildren(*this); if (!nodep->varp()) nodep->v3fatalSrc("Not linked"); bool did=false; diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 9276b874c..cc85ee7ad 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -348,14 +348,18 @@ private: // This is quite similar to how classes work; when unpacked classes are better supported // may remap interfaces to be more like a class. if (!nodep->hasIfaceVar()) { - string varName = nodep->name()+"__Viftop"; // V3LinkDot looks for this naming - AstIfaceRefDType* idtypep = new AstIfaceRefDType(nodep->fileline(), nodep->name(), nodep->modp()->name()); - idtypep->cellp(nodep); // Only set when real parent cell known - idtypep->ifacep(NULL); // cellp overrides - AstVar* varp = new AstVar(nodep->fileline(), AstVarType::IFACEREF, varName, VFlagChildDType(), idtypep); - varp->isIfaceParent(true); - nodep->addNextHere(varp); - nodep->hasIfaceVar(true); + if (!nodep->rangep()) { + string varName = nodep->name() + "__Viftop"; // V3LinkDot looks for this naming + AstIfaceRefDType *idtypep = new AstIfaceRefDType(nodep->fileline(), nodep->name(), + nodep->modp()->name()); + idtypep->cellp(nodep); // Only set when real parent cell known + idtypep->ifacep(NULL); // cellp overrides + AstVar *varp = new AstVar(nodep->fileline(), AstVarType::IFACEREF, varName, + VFlagChildDType(), idtypep); + varp->isIfaceParent(true); + nodep->addNextHere(varp); + nodep->hasIfaceVar(true); + } } } if (nodep->modp()) { diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 935634749..b1d36ebfc 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1322,12 +1322,15 @@ private: DotPosition m_dotPos; // Scope part of dotted resolution VSymEnt* m_dotSymp; // SymEnt for dotted AstParse lookup AstDot* m_dotp; // Current dot + bool m_unresolved; // Unresolved, needs help from V3Param + AstNode* m_unlinkedScope;// Unresolved scope, needs corresponding VarXRef bool m_dotErr; // Error found in dotted resolution, ignore upwards string m_dotText; // String of dotted names found in below parseref DotStates() { init(NULL); } ~DotStates() {} void init(VSymEnt* curSymp) { m_dotPos = DP_NONE; m_dotSymp = curSymp; m_dotp = NULL; m_dotErr = false; m_dotText = ""; + m_unresolved = false; m_unlinkedScope = NULL; } string ascii() const { static const char* names[] = { "NONE","PACKAGE","SCOPE","FINAL","MEMBER" }; @@ -1335,6 +1338,7 @@ private: sstr<<"ds="<lhsp()->castCellRef() || nodep->lhsp()->castCellArrayRef())) { + m_ds.m_unlinkedScope = nodep->lhsp(); + } if (!m_ds.m_dotErr) { // Once something wrong, give up if (start && m_ds.m_dotPos==DP_SCOPE) m_ds.m_dotPos = DP_FINAL; // Top 'final' dot RHS is final RHS, else it's a DOT(DOT(x,*here*),real-rhs) which we consider a RHS nodep->rhsp()->iterateAndNext(*this); @@ -1523,6 +1530,10 @@ private: pushDeletep(nodep); VL_DANGLING(nodep); } else { // Dot midpoint AstNode* newp = nodep->rhsp()->unlinkFrBack(); + if (m_ds.m_unresolved) { + AstCellRef* crp = new AstCellRef(nodep->fileline(), nodep->name(), nodep->lhsp()->unlinkFrBack(), newp); + newp = crp; + } nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } @@ -1641,17 +1652,24 @@ private: nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } else if (allowVar) { - AstNodeVarRef* newp; + AstNode* newp; if (m_ds.m_dotText != "") { - newp = new AstVarXRef(nodep->fileline(), nodep->name(), m_ds.m_dotText, false); // lvalue'ness computed later - newp->varp(varp); + AstVarXRef* refp = new AstVarXRef(nodep->fileline(), nodep->name(), m_ds.m_dotText, false); // lvalue'ness computed later + refp->varp(varp); m_ds.m_dotText = ""; + if (m_ds.m_unresolved && m_ds.m_unlinkedScope) { + newp = new AstUnlinkedVarXRef(nodep->fileline(), refp->castVarXRef(), refp->name(), m_ds.m_unlinkedScope->unlinkFrBack()); + m_ds.m_unlinkedScope = NULL; + m_ds.m_unresolved = false; + } else { + newp = refp; + } } else { - newp = new AstVarRef(nodep->fileline(), nodep->name(), false); // lvalue'ness computed later - newp->varp(varp); - newp->packagep(foundp->packagep()); - UINFO(9," new "<fileline(), varp, false); // lvalue'ness computed later + refp->packagep(foundp->packagep()); + newp = refp; } + UINFO(9," new "<replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); m_ds.m_dotPos = DP_MEMBER; ok = true; @@ -1906,12 +1924,9 @@ private: if (nodep->user3SetOnce()) return; nodep->lhsp()->iterateAndNext(*this); if (m_ds.m_dotPos == DP_SCOPE) { // Already under dot, so this is {modulepart} DOT {modulepart} - if (AstConst* constp = nodep->rhsp()->castConst()) { - string index = AstNode::encodeNumber(constp->toSInt()); - m_ds.m_dotText += "__BRA__"+index+"__KET__"; - } else { - nodep->v3error("Unsupported: Non-constant inside []'s in the cell part of a dotted reference"); - } + UINFO(9," deferring until after a V3Param pass: "<attrp()->iterateAndNext(*this); } m_ds = lastStates; + if (m_ds.m_unresolved && m_ds.m_dotPos == DP_SCOPE) { + AstNode* exprp = nodep->bitp()->unlinkFrBack(); + AstCellArrayRef* newp = new AstCellArrayRef(nodep->fileline(), nodep->fromp()->name(), exprp); + nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); + } } virtual void visit(AstNodePreSel* nodep, AstNUser*) { // Excludes simple AstSelBit, see above @@ -2018,6 +2038,18 @@ private: checkNoDot(nodep); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); } + virtual void visit(AstCellRef* nodep, AstNUser*) { + UINFO(5," AstCellRef: "<iterateChildren(*this); + } + virtual void visit(AstCellArrayRef* nodep, AstNUser*) { + UINFO(5," AstCellArrayRef: "<selp()->iterateAndNext(*this); + } + m_setRefLvalue = last_setRefLvalue; + } virtual void visit(AstNodePreSel* nodep, AstNUser*) { bool last_setRefLvalue = m_setRefLvalue; { // Only set lvalues on the from diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index 11dc9df35..7667c30c9 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -204,6 +204,9 @@ private: if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { // Maybe varxref - so need to clone nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::VAR_BASE, varrefp->cloneTree(false))); + } else if (AstUnlinkedVarXRef* uvxrp = basefromp->castUnlinkedVarXRef()) { // Maybe varxref - so need to clone + nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::VAR_BASE, + uvxrp->cloneTree(false))); } else if (AstMemberSel* fromp = basefromp->castMemberSel()) { nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::MEMBER_BASE, fromp->cloneTree(false))); diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 35a035a37..6c293bf78 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -108,6 +108,8 @@ private: typedef deque CellList; CellList m_cellps; // Cells left to process (in this module) + string m_unlinkedTxt; // Text for AstUnlinkedVarXRef + // METHODS static int debug() { static int level = -1; @@ -251,6 +253,41 @@ private: virtual void visit(AstVarXRef* nodep, AstNUser*) { nodep->varp(NULL); // Needs relink, as may remove pointed-to var } + virtual void visit(AstUnlinkedVarXRef* nodep, AstNUser*) { + m_unlinkedTxt.clear(); + nodep->cellrefp()->iterate(*this); + nodep->varxrefp()->dotted(m_unlinkedTxt); + nodep->replaceWith(nodep->varxrefp()->unlinkFrBack()); + pushDeletep(nodep); VL_DANGLING(nodep); + } + virtual void visit(AstCellArrayRef* nodep, AstNUser*) { + V3Const::constifyParamsEdit(nodep->selp()); + if (AstConst* constp = nodep->selp()->castConst()) { + string index = AstNode::encodeNumber(constp->toSInt()); + m_unlinkedTxt += nodep->name() + "__BRA__"+index+"__KET__"; + } else { + nodep->v3error("Could not expand constant selection inside dotted reference: "<selp()->prettyName()); + return; + } + } + virtual void visit(AstCellRef* nodep, AstNUser*) { + // Children must be CellArrayRef, CellRef or ParseRef + if (nodep->cellp()->castCellArrayRef() || nodep->cellp()->castCellRef()) { + nodep->cellp()->iterate(*this); + } else if (nodep->cellp()->castParseRef()) { + m_unlinkedTxt += nodep->cellp()->name(); + } else { + nodep->v3error("Could not elaborate dotted reference (LHS): "<cellp()->prettyName()); + } + m_unlinkedTxt += "."; + if (nodep->exprp()->castCellArrayRef() || nodep->exprp()->castCellRef()) { + nodep->exprp()->iterate(*this); + } else if (nodep->exprp()->castParseRef()) { + m_unlinkedTxt += nodep->exprp()->name(); + } else { + nodep->v3error("Could not elaborate dotted reference (RHS): "<exprp()->prettyName()); + } + } // Generate Statements virtual void visit(AstGenerate* nodep, AstNUser*) { diff --git a/test_regress/t/t_crazy_sel.pl b/test_regress/t/t_crazy_sel.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_crazy_sel.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_crazy_sel.v b/test_regress/t/t_crazy_sel.v new file mode 100644 index 000000000..027d9884d --- /dev/null +++ b/test_regress/t/t_crazy_sel.v @@ -0,0 +1,42 @@ +// DESCRIPTION: Verilator: Dotted reference that uses another dotted reference +// as the select expression +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2015 by Todd Strader. + +interface foo_intf; + logic a; +endinterface + +function integer the_other_func (input integer val); + return val; +endfunction + +module t (/*AUTOARG*/); + genvar the_genvar; + generate + for (the_genvar = 0; the_genvar < 4; the_genvar++) begin: foo_loop + foo foo_inst(); + end + endgenerate + + bar bar_inst(); + + logic x; + assign x = foo_loop[bar_inst.THE_LP].foo_inst.y; + //localparam N = 2; + //assign x = foo_loop[N].foo_inst.y; + + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule + +module foo(); + logic y; +endmodule + +module bar(); + localparam THE_LP = 2; +endmodule diff --git a/test_regress/t/t_gen_index.pl b/test_regress/t/t_gen_index.pl index 4d9e70f55..8e68549ed 100755 --- a/test_regress/t/t_gen_index.pl +++ b/test_regress/t/t_gen_index.pl @@ -7,8 +7,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. -$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug517"); - # Compile time only test compile ( ); diff --git a/test_regress/t/t_genfor_hier.pl b/test_regress/t/t_genfor_hier.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_genfor_hier.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_genfor_hier.v b/test_regress/t/t_genfor_hier.v new file mode 100644 index 000000000..cf69e3f0d --- /dev/null +++ b/test_regress/t/t_genfor_hier.v @@ -0,0 +1,23 @@ +// DESCRIPTION: Verilator: Demonstrate deferred linking across module +// bondaries +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2015 by Todd Strader. + +module m1(); + logic v1; +endmodule + +module t (/*AUTOARG*/); + for (genvar the_genvar = 0; the_genvar < 4; the_genvar++) begin : m1_b + m1 m1_inst(); + end + for (genvar the_other_genvar = 0; the_other_genvar < 4; the_other_genvar++) begin + always_comb m1_b[the_other_genvar].m1_inst.v1 = 1'b0; + end + + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_interface_array.pl b/test_regress/t/t_interface_array.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_interface_array.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_array.v b/test_regress/t/t_interface_array.v new file mode 100644 index 000000000..820b7f3c8 --- /dev/null +++ b/test_regress/t/t_interface_array.v @@ -0,0 +1,79 @@ +// DESCRIPTION: Verilator: Functionally demonstrate an array of interfaces +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2015 by Todd Strader. + +interface foo_intf; + logic a; + + modport source ( + output a + ); + + modport sink ( + input a + ); +endinterface + +function integer identity (input integer val); + return val; +endfunction + +module t (/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + + localparam N = 5; + + logic [N-1:0] a_in; + logic [N-1:0] a_out; + logic [N-1:0] ack_out; + + foo_intf foos [N-1:0] (); + + // Deferred link dotting with genvars + generate + genvar i; + for (i = 0; i < N-4; i++) begin : someLoop + assign ack_out[i] = a_in[i]; + assign foos[i].a = a_in[i]; + assign a_out[i] = foos[i].a; + end + endgenerate + + // Defferred link dotting with localparam + localparam THE_LP = N-3; + assign ack_out[THE_LP] = a_in[THE_LP]; + assign foos[THE_LP].a = a_in[THE_LP]; + assign a_out[THE_LP] = foos[THE_LP].a; + + // Defferred link dotting with arithmetic expression + assign ack_out[N-2] = a_in[N-2]; + assign foos[N-2].a = a_in[N-2]; + assign a_out[N-2] = foos[N-2].a; + + // Defferred link dotting with funcrefs + assign ack_out[identity(N-1)] = a_in[identity(N-1)]; + assign foos[identity(N-1)].a = a_in[identity(N-1)]; + assign a_out[identity(N-1)] = foos[identity(N-1)].a; + + initial a_in = '0; + always @(posedge clk) begin + a_in <= a_in + { {N-1 {1'b0}}, 1'b1 }; + + if (ack_out != a_out) begin + $display("%%Error: Interface and non-interface paths do not match: 0b%b 0b%b", + ack_out, a_out); + $stop; + end + + if (& a_in) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule diff --git a/test_regress/t/t_interface_array_bad.pl b/test_regress/t/t_interface_array_bad.pl new file mode 100755 index 000000000..6cd6a6d0d --- /dev/null +++ b/test_regress/t/t_interface_array_bad.pl @@ -0,0 +1,21 @@ +#!/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 ( + fails=>1, + expect=> +'%Error: t/t_interface_array_bad.v:\d+: Expecting expression to be constant, but variable isn\'t const: bar +%Error: t/t_interface_array_bad.v:\d+: Could not expand constant selection inside dotted reference: bar +%Error: t/t_interface_array_bad.v:\d+: Can\'t find definition of \'a\' in dotted signal: .a +%Error: Known scopes under \'a\':.* +%Error: Exiting due to.*', + ); + +ok(1); +1; diff --git a/test_regress/t/t_interface_array_bad.v b/test_regress/t/t_interface_array_bad.v new file mode 100644 index 000000000..2f550845b --- /dev/null +++ b/test_regress/t/t_interface_array_bad.v @@ -0,0 +1,53 @@ +// DESCRIPTION: Verilator: Demonstrate deferred linking error messages +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2015 by Todd Strader. + +interface foo_intf; + logic a; +endinterface + +function integer the_other_func (input integer val); + return val; +endfunction + +module t (/*AUTOARG*/); + + localparam N = 4; + + foo_intf foos [N-1:0] (); + logic [ 7 : 0 ] bar; + + // Non-constant dotted select is not allowed + assign foos[bar].a = 1'b1; + + baz baz_inst (); + + // Unsure how to produce V3Param AstCellRef visitor errors + //assign baz_inst.x = 1'b1; + //assign baz_inst.N = 1'b1; + //assign baz_inst.7 = 1'b1; + //assign baz_inst.qux_t = 1'b1; + //assign baz_inst.the_func = 1'b1; + //assign baz_inst.the_lp = 1'b1; + + //assign bar.x = 1'b1; + //assign fake_inst.x = 1'b1; + //assign the_other_func.x = 1'b1; + + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule + +module baz; + typedef integer qux_t; + + function integer the_func (input integer val); + return val; + endfunction + + localparam the_lp = 5; +endmodule diff --git a/test_regress/t/t_interface_array_modport.pl b/test_regress/t/t_interface_array_modport.pl new file mode 100755 index 000000000..c14f759cd --- /dev/null +++ b/test_regress/t/t_interface_array_modport.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 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. + +$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug978"); + +compile ( + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_interface_array_modport.v b/test_regress/t/t_interface_array_modport.v new file mode 100644 index 000000000..4ed075278 --- /dev/null +++ b/test_regress/t/t_interface_array_modport.v @@ -0,0 +1,35 @@ +// DESCRIPTION: Verilator: Connecting an interface array slice to a module's portmap +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2015 by Todd Strader. + +interface foo_intf; + logic a; +endinterface + +module foo_mod + ( + foo_intf foo + ); +endmodule + +module t (/*AUTOARG*/); + + localparam N = 4; + + foo_intf foos [N-1:0] (); + //foo_intf foos (); + + foo_mod + foo_mod + ( + .foo (foos[2]) + //.foo (foos) + ); + + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule