diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 69e448bd8..fdbcc205c 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -5835,6 +5835,10 @@ public: }; class AstCastDynamic : public AstNodeBiop { + // Verilog $cast used as a function + // Task usage of $cast is converted during parse to assert($cast(...)) + // Parents: MATH + // Children: MATH public: AstCastDynamic(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index cdfdd11e8..453747555 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -76,6 +76,15 @@ private: iterateAndNextNull(nodep->rhsp()); } } + virtual void visit(AstCastDynamic* nodep) override { + VL_RESTORER(m_setRefLvalue); + { + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->lhsp()); + m_setRefLvalue = false; + iterateAndNextNull(nodep->rhsp()); + } + } virtual void visit(AstFOpen* nodep) override { VL_RESTORER(m_setRefLvalue); { diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 7e91a0362..a71bb0089 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1599,9 +1599,10 @@ private: nodep->widthFromSub(nodep->subDTypep()); } virtual void visit(AstCastDynamic* nodep) override { + nodep->dtypeChgWidthSigned(32, 1, VSigning::SIGNED); // Spec says integer return nodep->v3warn(E_UNSUPPORTED, "Unsupported: $cast. Suggest try static cast."); AstNode* newp = new AstConst(nodep->fileline(), 1); - newp->dtypeSetSigned32(); // Spec says integer return + newp->dtypeFrom(nodep); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } diff --git a/src/verilog.y b/src/verilog.y index dfbe30a97..72275ccd9 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -3624,6 +3624,9 @@ system_t_call: // IEEE: system_tf_call (as task) | yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstWriteMem($1, true, $3, $5, $7, nullptr); } | yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstWriteMem($1, true, $3, $5, $7, $9); } // + | yD_CAST '(' expr ',' expr ')' + { $$ = new AstAssert($1, new AstCastDynamic($1, $3, $5), nullptr, nullptr, true); } + // // Any system function as a task | system_f_call_or_t { $$ = new AstSysFuncAsTask($1, $1); } ; @@ -3632,6 +3635,7 @@ system_f_call: // IEEE: system_tf_call (as func) yaD_PLI systemDpiArgsE { $$ = new AstFuncRef($1, *$1, $2); VN_CAST($$, FuncRef)->pli(true); } // | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? nullptr : new AstUCFunc($1,$3)); } + | yD_CAST '(' expr ',' expr ')' { $$ = new AstCastDynamic($1, $3, $5); } | yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); } // | system_f_call_or_t { $$ = $1; } @@ -3654,7 +3658,6 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func) | yD_BITS '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); } | yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); } | yD_BITSTOSHORTREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); UNSUPREAL($1); } - | yD_CAST '(' expr ',' expr ')' { $$ = new AstCastDynamic($1, $3, $5); } | yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); } | yD_CHANGED '(' expr ')' { $$ = new AstLogNot($1, new AstStable($1, $3)); } | yD_CHANGED '(' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $changed and clock arguments"); } diff --git a/test_regress/t/t_castdyn.out b/test_regress/t/t_castdyn.out index 14761e02a..2b0ae4bce 100644 --- a/test_regress/t/t_castdyn.out +++ b/test_regress/t/t_castdyn.out @@ -22,8 +22,8 @@ : ... In instance t 51 | i = $cast(bbo, b); | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn.v:57:11: Unsupported: $cast. Suggest try static cast. +%Error-UNSUPPORTED: t/t_castdyn.v:58:11: Unsupported: $cast. Suggest try static cast. : ... In instance t - 57 | i = $cast(bao, b); + 58 | i = $cast(bao, b); | ^~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_castdyn.v b/test_regress/t/t_castdyn.v index 2d788ca51..123268419 100644 --- a/test_regress/t/t_castdyn.v +++ b/test_regress/t/t_castdyn.v @@ -53,9 +53,11 @@ module t (/*AUTOARG*/); if (b != bb) $stop; bb = new; - b = b; + b = bb; + bao = ba; i = $cast(bao, b); if (i != 0) $stop; + if (bao != ba) $stop; // Unchanged $write("*-* All Finished *-*\n"); $finish;