diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 7c1f043f6..715feab24 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -98,6 +98,7 @@ Fan Shupei february cozzocrea Felix Neumärker Felix Yan +Francesco Urbani Frans Skarman Fuad Ismail Furqan Nadir diff --git a/src/V3Width.cpp b/src/V3Width.cpp index cd47febd8..d1ccd3540 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1608,7 +1608,8 @@ class WidthVisitor final : public VNVisitor { } void visit(AstEmptyQueue* nodep) override { nodep->dtypeSetEmptyQueue(); - if (!VN_IS(nodep->backp(), Assign) && !VN_IS(nodep->backp(), Var)) { + if (!VN_IS(nodep->backp(), Assign) && !VN_IS(nodep->backp(), Var) + && !VN_IS(nodep->backp(), Arg)) { nodep->v3warn(E_UNSUPPORTED, "Unsupported/Illegal: empty queue ('{}') in this context"); } @@ -6240,14 +6241,15 @@ class WidthVisitor final : public VNVisitor { nodep->replaceWith(newp); // UINFOTREE(9, newp, "", "apat-out"); } + AstNodeExpr* newConsDynArrayOrQueue(FileLine* fileline, const AstNodeDType* dtypep) { + if (VN_IS(dtypep, DynArrayDType)) return new AstConsDynArray{fileline}; + if (VN_IS(dtypep, QueueDType)) return new AstConsQueue{fileline}; + return nullptr; + } void patternDynArrayOrQueue(AstPattern* nodep, AstNodeDType* arrayp) { - AstNodeExpr* newp = nullptr; + AstNodeExpr* newp = newConsDynArrayOrQueue(nodep->fileline(), arrayp); + UASSERT_OBJ(newp, nodep, "Expected dynamic array or queue data type"); const bool isDynArray = VN_IS(arrayp, DynArrayDType); - if (isDynArray) { - newp = new AstConsDynArray{nodep->fileline()}; - } else { - newp = new AstConsQueue{nodep->fileline()}; - } newp->dtypeFrom(arrayp); for (AstPatMember* patp = VN_AS(nodep->itemsp(), PatMember); patp; patp = VN_AS(patp->nextp(), PatMember)) { @@ -7878,9 +7880,21 @@ class WidthVisitor final : public VNVisitor { for (const auto& tconnect : tconnects) { const AstVar* const portp = tconnect.first; const AstArg* const argp = tconnect.second; - AstNodeExpr* const pinp = argp->exprp(); + AstNodeExpr* pinp = argp->exprp(); if (!pinp) continue; // Argument error we'll find later AstNodeDType* const portDTypep = portp->dtypep()->skipRefToEnump(); + if (VN_IS(pinp, EmptyQueue)) { + AstNodeExpr* newp = newConsDynArrayOrQueue(pinp->fileline(), portDTypep); + if (!newp) { + pinp->v3warn(E_UNSUPPORTED, + "Unsupported/Illegal: empty queue ('{}') in this context"); + newp = new AstConst{pinp->fileline(), AstConst::Unsized32{}, 0}; + } + newp->dtypeFrom(portDTypep); + pinp->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(pinp), pinp); + pinp = newp; + } const AstNodeDType* const pinDTypep = pinp->dtypep()->skipRefToEnump(); const AstIfaceRefDType* const portIfacep = VN_CAST(portDTypep->elemDTypep(true), IfaceRefDType); diff --git a/test_regress/t/t_queue_empty_bad.out b/test_regress/t/t_queue_empty_bad.out index 00130c436..7e3c99e03 100644 --- a/test_regress/t/t_queue_empty_bad.out +++ b/test_regress/t/t_queue_empty_bad.out @@ -1,10 +1,14 @@ -%Error-UNSUPPORTED: t/t_queue_empty_bad.v:11:9: Unsupported/Illegal: empty queue ('{}') in this context +%Error-UNSUPPORTED: t/t_queue_empty_bad.v:14:9: Unsupported/Illegal: empty queue ('{}') in this context : ... note: In instance 't' - 11 | i = {} + 1; + 14 | i = {} + 1; | ^ ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest -%Error-UNSUPPORTED: t/t_queue_empty_bad.v:13:7: Unsupported/Illegal: empty queue ('{}') in this assign context +%Error-UNSUPPORTED: t/t_queue_empty_bad.v:16:7: Unsupported/Illegal: empty queue ('{}') in this assign context : ... note: In instance 't' - 13 | i = {}; + 16 | i = {}; | ^ +%Error-UNSUPPORTED: t/t_queue_empty_bad.v:18:16: Unsupported/Illegal: empty queue ('{}') in this context + : ... note: In instance 't' + 18 | scalar_arg({}); + | ^ %Error: Exiting due to diff --git a/test_regress/t/t_queue_empty_bad.v b/test_regress/t/t_queue_empty_bad.v index 6e094f4e3..d452b2e37 100644 --- a/test_regress/t/t_queue_empty_bad.v +++ b/test_regress/t/t_queue_empty_bad.v @@ -5,6 +5,9 @@ // SPDX-License-Identifier: CC0-1.0 module t; + task scalar_arg(int value); + endtask + initial begin int i; @@ -12,6 +15,8 @@ module t; i = {}; + scalar_arg({}); + $write("*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_queue_empty_pin.v b/test_regress/t/t_queue_empty_pin.v index be0f5a869..c2cc7c33b 100644 --- a/test_regress/t/t_queue_empty_pin.v +++ b/test_regress/t/t_queue_empty_pin.v @@ -9,8 +9,18 @@ module t; if (q.size != 0) $stop; endtask + task qtsk(int q[$]); + if (q.size != 0) $stop; + endtask + + task dtsk(int q[]); + if (q.size != 0) $stop; + endtask + initial begin tsk(); + qtsk({}); + dtsk({}); $write("*-* All Finished *-*\n"); $finish;