diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index a59bf55fc..5b356f638 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -465,33 +465,32 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - - void visit(AstNodeAssign* nodep) override { - if (AstArraySel* const arrselp = VN_CAST(nodep->rhsp(), ArraySel)) { - // handle single element selection from RHS array - if (const AstUnpackArrayDType* const arrp - = VN_CAST(arrselp->fromp()->dtypep()->skipRefp(), UnpackArrayDType)) { - if (!VN_IS(arrp->subDTypep()->skipRefp(), IfaceRefDType)) return; - if (VN_AS(arrp->subDTypep()->skipRefp(), IfaceRefDType)->isVirtual()) return; - V3Const::constifyParamsEdit(arrselp->bitp()); - const AstConst* const constp = VN_CAST(arrselp->bitp(), Const); - if (!constp) { - arrselp->bitp()->v3warn(E_UNSUPPORTED, - "Non-constant index in RHS interface array selection"); - return; - } - const string index = AstNode::encodeNumber(constp->toSInt()); - const AstVarRef* const varrefp = VN_CAST(arrselp->fromp(), VarRef); - UASSERT_OBJ(varrefp, arrselp, "No interface varref under array"); - AstVarXRef* const newp = new AstVarXRef{ - nodep->fileline(), varrefp->name() + "__BRA__" + index + "__KET__", "", - VAccess::READ}; - newp->dtypep(arrp->subDTypep()); - newp->classOrPackagep(varrefp->classOrPackagep()); - arrselp->addNextHere(newp); - VL_DO_DANGLING(arrselp->unlinkFrBack()->deleteTree(), arrselp); + void visit(AstArraySel* nodep) override { + if (const AstUnpackArrayDType* const arrp + = VN_CAST(nodep->fromp()->dtypep()->skipRefp(), UnpackArrayDType)) { + if (!VN_IS(arrp->subDTypep()->skipRefp(), IfaceRefDType)) return; + if (VN_AS(arrp->subDTypep()->skipRefp(), IfaceRefDType)->isVirtual()) return; + V3Const::constifyParamsEdit(nodep->bitp()); + const AstConst* const constp = VN_CAST(nodep->bitp(), Const); + if (!constp) { + nodep->bitp()->v3warn(E_UNSUPPORTED, + "Non-constant index in RHS interface array selection"); + return; } - } else if (AstSliceSel* const arrslicep = VN_CAST(nodep->rhsp(), SliceSel)) { + const string index = AstNode::encodeNumber(constp->toSInt()); + const AstVarRef* const varrefp = VN_CAST(nodep->fromp(), VarRef); + UASSERT_OBJ(varrefp, nodep, "No interface varref under array"); + AstVarXRef* const newp = new AstVarXRef{ + nodep->fileline(), varrefp->name() + "__BRA__" + index + "__KET__", "", + VAccess::READ}; + newp->dtypep(arrp->subDTypep()); + newp->classOrPackagep(varrefp->classOrPackagep()); + nodep->addNextHere(newp); + VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); + } + } + void visit(AstNodeAssign* nodep) override { + if (AstSliceSel* const arrslicep = VN_CAST(nodep->rhsp(), SliceSel)) { if (const AstUnpackArrayDType* const arrp = VN_CAST(arrslicep->fromp()->dtypep(), UnpackArrayDType)) { if (!VN_IS(arrp->subDTypep(), IfaceRefDType)) return; @@ -500,15 +499,20 @@ private: return; } } else { - if (const AstUnpackArrayDType* const lhsarrp - = VN_CAST(nodep->lhsp()->dtypep()->skipRefp(), UnpackArrayDType)) { - if (const AstUnpackArrayDType* const rhsarrp - = VN_CAST(nodep->rhsp()->dtypep()->skipRefp(), UnpackArrayDType)) { + if (const AstUnpackArrayDType* const rhsarrp + = VN_CAST(nodep->rhsp()->dtypep()->skipRefp(), UnpackArrayDType)) { + if (const AstUnpackArrayDType* const lhsarrp + = VN_CAST(nodep->lhsp()->dtypep()->skipRefp(), UnpackArrayDType)) { // copy between arrays if (!VN_IS(lhsarrp->subDTypep()->skipRefp(), IfaceRefDType)) return; if (!VN_IS(rhsarrp->subDTypep()->skipRefp(), IfaceRefDType)) return; if (VN_AS(rhsarrp->subDTypep()->skipRefp(), IfaceRefDType)->isVirtual()) return; + if (!VN_AS(lhsarrp->subDTypep()->skipRefp(), IfaceRefDType)->isVirtual()) { + nodep->v3warn(E_UNSUPPORTED, "Unexpected target of interface assignment [" + << rhsarrp->prettyDTypeNameQ() << "]"); + return; + } if (lhsarrp->elementsConst() != rhsarrp->elementsConst()) { nodep->v3warn(E_UNSUPPORTED, "Array size mismatch in interface assignment"); @@ -518,30 +522,17 @@ private: const string index = AstNode::encodeNumber(i); AstNodeExpr* lhsp = nullptr; if (AstVarRef* const varrefp = VN_CAST(nodep->lhsp(), VarRef)) { - if (VN_AS(lhsarrp->subDTypep()->skipRefp(), IfaceRefDType) - ->isVirtual()) { - AstVarRef* const newvarp = varrefp->cloneTree(false); - AstArraySel* newarrselp = new AstArraySel( - nodep->fileline(), newvarp, - new AstConst(nodep->fileline(), - V3Number(nodep->fileline(), 32, i))); - lhsp = newarrselp; - } else { - AstVarXRef* const newvarrefp = new AstVarXRef{ - nodep->fileline(), - varrefp->name() + "__BRA__" + index + "__KET__", "", - VAccess::WRITE}; - newvarrefp->dtypep(lhsarrp->subDTypep()->skipRefp()); - newvarrefp->classOrPackagep(varrefp->classOrPackagep()); - lhsp = newvarrefp; - } + AstVarRef* const newvarp = varrefp->cloneTree(false); + AstArraySel* newarrselp = new AstArraySel{ + nodep->fileline(), newvarp, + new AstConst{nodep->fileline(), static_cast(i)}}; + lhsp = newarrselp; } else if (AstMemberSel* const prevselp = VN_CAST(nodep->lhsp(), MemberSel)) { AstMemberSel* membselp = prevselp->cloneTree(false); - AstArraySel* newarrselp = new AstArraySel( + AstArraySel* newarrselp = new AstArraySel{ nodep->fileline(), membselp, - new AstConst(nodep->fileline(), - V3Number(nodep->fileline(), 32, i))); + new AstConst{nodep->fileline(), static_cast(i)}}; lhsp = newarrselp; } else { nodep->v3warn(E_UNSUPPORTED, @@ -557,15 +548,20 @@ private: AstAssign* const assignp = new AstAssign(nodep->fileline(), lhsp, rhsp); nodep->addNextHere(assignp); } - VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); + return; } } } + iterateChildren(nodep); } //-------------------- void visit(AstNodeExpr*) override {} // Accelerate void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNew* nodep) override { iterateChildren(nodep); } + void visit(AstMethodCall* nodep) override { iterateChildren(nodep); } + void visit(AstArg* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS diff --git a/test_regress/t/t_interface_dearray.v b/test_regress/t/t_interface_dearray.v index f3cdc8081..a8bee53b2 100644 --- a/test_regress/t/t_interface_dearray.v +++ b/test_regress/t/t_interface_dearray.v @@ -10,25 +10,34 @@ endinterface typedef virtual A a_t; typedef a_t a_array_t[6]; +class B; + function new(virtual A va); + endfunction +endclass + class C; a_array_t vif; + + function void set(int index, a_t iface); + vif[index] = iface; + endfunction endclass module tb_top(); - A a[6](), b[6](); + A a[6](); C c, d, e; a_array_t g; initial begin static a_t aa = a[0]; - b = a; + B b = new(a[0]); c = new(); c.vif = a; d = new(); - d.vif[0] = a[0]; + d.set(0, a[0]); d.vif[1] = a[1]; g[0] = a[0]; diff --git a/test_regress/t/t_interface_dearray_bad.out b/test_regress/t/t_interface_dearray_bad.out index 39486d611..143493309 100644 --- a/test_regress/t/t_interface_dearray_bad.out +++ b/test_regress/t/t_interface_dearray_bad.out @@ -1,23 +1,27 @@ -%Error-UNSUPPORTED: t/t_interface_dearray_bad.v:25:13: Array size mismatch in interface assignment - : ... note: In instance 'tb_top' - 25 | c.vif = b; - | ^ +%Error-UNSUPPORTED: t/t_interface_dearray_bad.v:23:9: Unexpected target of interface assignment ['IFACEREFDTYPE$[0:5]'] + : ... note: In instance 'tb_top' + 23 | a = f; + | ^ ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest -%Error: t/t_interface_dearray_bad.v:30:23: Expecting expression to be constant, but variable isn't const: 'i' +%Error-UNSUPPORTED: t/t_interface_dearray_bad.v:26:13: Array size mismatch in interface assignment + : ... note: In instance 'tb_top' + 26 | c.vif = b; + | ^ +%Error: t/t_interface_dearray_bad.v:31:23: Expecting expression to be constant, but variable isn't const: 'i' : ... note: In instance 'tb_top' - 30 | d.vif[i] = a[i]; + 31 | d.vif[i] = a[i]; | ^ ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. -%Error-UNSUPPORTED: t/t_interface_dearray_bad.v:30:23: Non-constant index in RHS interface array selection +%Error-UNSUPPORTED: t/t_interface_dearray_bad.v:31:23: Non-constant index in RHS interface array selection : ... note: In instance 'tb_top' - 30 | d.vif[i] = a[i]; + 31 | d.vif[i] = a[i]; | ^ -%Error-UNSUPPORTED: t/t_interface_dearray_bad.v:34:16: Interface slices unsupported +%Error-UNSUPPORTED: t/t_interface_dearray_bad.v:35:16: Interface slices unsupported : ... note: In instance 'tb_top' - 34 | e.vif = b[0:5]; + 35 | e.vif = b[0:5]; | ^ -%Error: Internal Error: t/t_interface_dearray_bad.v:25:15: ../V3Broken.cpp:#: Broken link in node (or something without maybePointedTo): 'm_varp && !m_varp->brokeExists()' @ ./V3Ast__gen_impl.h:# +%Error: Internal Error: t/t_interface_dearray_bad.v:23:11: ../V3Broken.cpp:#: Broken link in node (or something without maybePointedTo): 'm_varp && !m_varp->brokeExists()' @ ./V3Ast__gen_impl.h:# : ... note: In instance 'tb_top' - 25 | c.vif = b; - | ^ + 23 | a = f; + | ^ ... This fatal error may be caused by the earlier error(s); resolve those first. diff --git a/test_regress/t/t_interface_dearray_bad.v b/test_regress/t/t_interface_dearray_bad.v index d90fbc5c4..cde795595 100644 --- a/test_regress/t/t_interface_dearray_bad.v +++ b/test_regress/t/t_interface_dearray_bad.v @@ -15,11 +15,12 @@ class C; endclass module tb_top(); - A a[6](), b[7](); + A a[6](), b[7](), f[6](); C c, d, e; a_array_t g; initial begin + a = f; c = new(); c.vif = b;