diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index efd6749cc..6089a5eaa 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -10,6 +10,7 @@ Alex Chadwick Aliaksei Chapyzhenka Ameya Vikram Singh Andreas Kuster +Arkadiusz Kozdra Chris Randall Chuxuan Wang Conor McCullough diff --git a/include/verilated.cpp b/include/verilated.cpp index 1f6fe3b4c..da8599a42 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -1606,8 +1606,8 @@ IData VL_SYSTEM_IW(int lhswords, const WDataInP lhsp) VL_MT_SAFE { return code >> 8; // Want exit status } -IData VL_TESTPLUSARGS_I(const char* formatp) VL_MT_SAFE { - const std::string& match = Verilated::threadContextp()->impp()->argPlusMatch(formatp); +IData VL_TESTPLUSARGS_I(const std::string& format) VL_MT_SAFE { + const std::string& match = Verilated::threadContextp()->impp()->argPlusMatch(format.c_str()); return match.empty() ? 0 : 1; } diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h index ab71839b5..c8fb91d3e 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -146,7 +146,7 @@ extern IData VL_SYSTEM_IW(int lhswords, WDataInP const lhsp); extern IData VL_SYSTEM_IQ(QData lhs); inline IData VL_SYSTEM_II(IData lhs) VL_MT_SAFE { return VL_SYSTEM_IQ(lhs); } -extern IData VL_TESTPLUSARGS_I(const char* formatp); +extern IData VL_TESTPLUSARGS_I(const std::string& format); extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish //========================================================================= diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 118666c0b..d9e4b81db 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -4551,26 +4551,21 @@ public: class AstTestPlusArgs final : public AstNodeMath { // Parents: expr // Child: variable to set. If nullptr then this is a $test$plusargs instead of $value$plusargs -private: - string m_text; - public: - AstTestPlusArgs(FileLine* fl, const string& text) - : ASTGEN_SUPER_TestPlusArgs(fl) - , m_text{text} {} + AstTestPlusArgs(FileLine* fl, AstNode* searchp) + : ASTGEN_SUPER_TestPlusArgs(fl) { + setOp1p(searchp); + } ASTNODE_NODE_FUNCS(TestPlusArgs) - virtual string name() const override { return m_text; } virtual string verilogKwd() const override { return "$test$plusargs"; } virtual string emitVerilog() override { return verilogKwd(); } virtual string emitC() override { return "VL_VALUEPLUSARGS_%nq(%lw, %P, nullptr)"; } virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } virtual bool cleanOut() const override { return true; } - virtual bool same(const AstNode* samep) const override { - return text() == static_cast(samep)->text(); - } - string text() const { return m_text; } // * = Text to display - void text(const string& text) { m_text = text; } + virtual bool same(const AstNode* samep) const override { return true; } + AstNode* searchp() const { return op1p(); } // op1 = Search expression + void searchp(AstNode* nodep) { setOp1p(nodep); } }; class AstGenFor final : public AstNodeFor { diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index 4bdfb1c57..305fa47a7 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -581,7 +581,7 @@ public: } virtual void visit(AstTestPlusArgs* nodep) override { puts("VL_TESTPLUSARGS_I("); - putsQuoted(nodep->text()); + emitCvtPackStr(nodep->searchp()); puts(")"); } virtual void visit(AstFError* nodep) override { diff --git a/src/V3Hasher.cpp b/src/V3Hasher.cpp index 7cf3672b6..4b0cbbbba 100644 --- a/src/V3Hasher.cpp +++ b/src/V3Hasher.cpp @@ -225,11 +225,6 @@ private: m_hash += nodep->text(); }); } - virtual void visit(AstTestPlusArgs* nodep) override { - m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // - m_hash += nodep->text(); - }); - } virtual void visit(AstAddrOfCFunc* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // iterateNull(nodep->funcp()); diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index 6ab7eb8e7..1f955e361 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -210,6 +210,13 @@ private: iterateAndNextNull(nodep->msbp()); } } + virtual void visit(AstTestPlusArgs* nodep) override { + VL_RESTORER(m_setRefLvalue); + { + m_setRefLvalue = VAccess::NOCHANGE; + iterateAndNextNull(nodep->searchp()); + } + } virtual void visit(AstValuePlusArgs* nodep) override { VL_RESTORER(m_setRefLvalue); { diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 15bdf6f33..8a833d9f2 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -448,7 +448,6 @@ private: // Widths: Constant, terminal virtual void visit(AstTime* nodep) override { nodep->dtypeSetUInt64(); } virtual void visit(AstTimeD* nodep) override { nodep->dtypeSetDouble(); } - virtual void visit(AstTestPlusArgs* nodep) override { nodep->dtypeSetSigned32(); } virtual void visit(AstScopeName* nodep) override { nodep->dtypeSetUInt64(); // A pointer, but not that it matters } @@ -4350,6 +4349,12 @@ private: userIterateAndNext(nodep->lsbp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->msbp(), WidthVP(SELF, BOTH).p()); } + virtual void visit(AstTestPlusArgs* nodep) override { + if (m_vup->prelim()) { + userIterateAndNext(nodep->searchp(), WidthVP{SELF, BOTH}.p()); + nodep->dtypeChgWidthSigned(32, 1, VSigning::SIGNED); // Spec says integer return + } + } virtual void visit(AstValuePlusArgs* nodep) override { if (m_vup->prelim()) { userIterateAndNext(nodep->searchp(), WidthVP(SELF, BOTH).p()); diff --git a/src/verilog.y b/src/verilog.y index ea4161500..34fbe86b0 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -3917,7 +3917,7 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or | yD_STABLE '(' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $stable and clock arguments"); } | yD_TAN '(' expr ')' { $$ = new AstTanD($1,$3); } | yD_TANH '(' expr ')' { $$ = new AstTanhD($1,$3); } - | yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); } + | yD_TESTPLUSARGS '(' expr ')' { $$ = new AstTestPlusArgs($1, $3); } | yD_TIME parenE { $$ = new AstTime($1, VTimescale(VTimescale::NONE)); } | yD_TYPENAME '(' exprOrDataType ')' { $$ = new AstAttrOf($1, VAttrType::TYPENAME, $3); } | yD_UNGETC '(' expr ',' expr ')' { $$ = new AstFUngetC($1, $5, $3); } // Arg swap to file first diff --git a/test_regress/t/t_sys_plusargs.v b/test_regress/t/t_sys_plusargs.v index 55daf5085..4aef6e33c 100644 --- a/test_regress/t/t_sys_plusargs.v +++ b/test_regress/t/t_sys_plusargs.v @@ -22,6 +22,12 @@ module t; //if ($test$plusargs("")!==1) $stop; // Simulators differ in this answer if ($test$plusargs("NOTTHERE")!==0) $stop; + sv_in = "PLUS"; +`ifdef VERILATOR + if ($c1(0)) sv_in = "NEVER"; // Prevent constant propagation +`endif + if ($test$plusargs(sv_in)!==1) $stop; + p_i = 10; if ($value$plusargs("NOTTHERE%d", p_i) !== 0) $stop; if ($value$plusargs("NOTTHERE%0d", p_i) !== 0) $stop;