diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index b707a1b4c..6e593c339 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -326,6 +326,10 @@ private: } nodep->replaceWith(inp); } + virtual void visit(AstSampled* nodep) VL_OVERRIDE { + nodep->replaceWith(nodep->exprp()->unlinkFrBack()); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } //========== Statements virtual void visit(AstDisplay* nodep) VL_OVERRIDE { diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 11f9541cf..31ff34e37 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -6265,6 +6265,24 @@ public: virtual bool same(const AstNode* samep) const { return true; } }; +class AstSampled : public AstNodeMath { + // Verilog $sampled + // Parents: math + // Children: expression +public: + AstSampled(FileLine* fl, AstNode* exprp) + : ASTGEN_SUPER(fl) { addOp1p(exprp); } + ASTNODE_NODE_FUNCS(Sampled) + virtual string emitVerilog() { return "$sampled(%l)"; } + virtual string emitC() { V3ERROR_NA; return "";} + virtual string emitSimpleOperator() { V3ERROR_NA; return ""; } + virtual bool cleanOut() const { V3ERROR_NA; return ""; } + virtual int instrCount() const { return 0; } + AstNode* exprp() const { return op1p(); } // op1 = expression + virtual V3Hash sameHash() const { return V3Hash(); } + virtual bool same(const AstNode* samep) const { return true; } +}; + class AstPattern : public AstNodeMath { // Verilog '{a,b,c,d...} // Parents: AstNodeAssign, AstPattern, ... diff --git a/src/V3Width.cpp b/src/V3Width.cpp index eed6e7536..bb8602c57 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -947,6 +947,12 @@ private: } } } + virtual void visit(AstSampled* nodep) VL_OVERRIDE { + if (m_vup->prelim()) { + iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); + nodep->dtypeFrom(nodep->exprp()); + } + } virtual void visit(AstRand* nodep) VL_OVERRIDE { if (m_vup->prelim()) { nodep->dtypeSetSigned32(); // Says the spec diff --git a/src/verilog.l b/src/verilog.l index e9082d34c..a442fe34e 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -234,6 +234,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$rtoi" { FL; return yD_RTOI; } "$setup" { FL; return yaTIMINGSPEC; } "$setuphold" { FL; return yaTIMINGSPEC; } + "$sampled" { FL; return yD_SAMPLED; } "$sformat" { FL; return yD_SFORMAT; } "$sformatf" { FL; return yD_SFORMATF; } "$shortrealtobits" { FL; return yD_SHORTREALTOBITS; } diff --git a/src/verilog.y b/src/verilog.y index 85957bb89..6503dc0e4 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -591,6 +591,7 @@ class AstSenTree; %token yD_REWIND "$rewind" %token yD_RIGHT "$right" %token yD_RTOI "$rtoi" +%token yD_SAMPLED "$sampled" %token yD_SFORMAT "$sformat" %token yD_SFORMATF "$sformatf" %token yD_SHORTREALTOBITS "$shortrealtobits" @@ -3264,6 +3265,7 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func) | yD_RIGHT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,NULL); } | yD_RIGHT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,$5); } | yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); } + | yD_SAMPLED '(' expr ')' { $$ = new AstSampled($1, $3); } | yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } | yD_SHORTREALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); UNSUPREAL($1); } | yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); } diff --git a/test_regress/t/t_past.v b/test_regress/t/t_past.v index 610e0fb5e..ed7f0add8 100644 --- a/test_regress/t/t_past.v +++ b/test_regress/t/t_past.v @@ -75,6 +75,8 @@ module Test (/*AUTOARG*/ if (dly0 != $past(in)) $stop; if (dly0 != $past(in,1)) $stop; if (dly1 != $past(in,2)) $stop; + // $sampled(expression) -> expression + if (in != $sampled(in)) $stop; end assert property (@(posedge clk) dly0 == $past(in));