diff --git a/Changes b/Changes index 10eab753d..332753d5c 100644 --- a/Changes +++ b/Changes @@ -5,7 +5,9 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.869 devel -**** Suppress COMBDLY when inside always_latch, bug854. [Iztok Jeras] +**** Suppress COMBDLY when inside always_latch, bug864. [Iztok Jeras] + +**** Support cast operator with expression size, bug865. [Iztok Jeras] * Verilator 3.868 2014-12-20 diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index a33d7aef7..b6761847a 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -3485,6 +3485,21 @@ public: AstNodeDType* childDTypep() const { return op2p()->castNodeDType(); } }; +class AstCastParse : public AstNode { + // Cast to appropriate type, where we haven't determined yet what the data type is +public: + AstCastParse(FileLine* fl, AstNode* lhsp, AstNode* dtp) : AstNode(fl) { + setOp1p(lhsp); setOp2p(dtp); + } + ASTNODE_NODE_FUNCS(CastParse, CASTPARSE) + virtual string emitVerilog() { return "((%d)'(%l))"; } + virtual string emitC() { V3ERROR_NA; return ""; } + virtual bool cleanOut() { V3ERROR_NA; return true;} virtual bool cleanLhs() {return true;} + virtual bool sizeMattersLhs() {return false;} + AstNode* lhsp() const { return op1p(); } + AstNode* dtp() const { return op2p(); } +}; + class AstCastSize : public AstNode { // Cast to specific size; signed/twostate inherited from lower element per IEEE public: diff --git a/src/V3Width.cpp b/src/V3Width.cpp index bb77134a7..3cba1036f 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -945,6 +945,21 @@ private: nodep->iterateChildren(*this); nodep->dtypep(iterateEditDTypep(nodep, nodep->subDTypep())); } + virtual void visit(AstCastParse* nodep, AstNUser* vup) { + // nodep->dtp could be data type, or a primary_constant + // Don't iterate lhsp, will deal with that once convert the type + V3Const::constifyParamsEdit(nodep->dtp()); // itemp may change + if (AstConst* constp = nodep->dtp()->castConst()) { + constp->unlinkFrBack(); + AstNode* newp = new AstCastSize(nodep->fileline(), nodep->lhsp()->unlinkFrBack(), constp); + nodep->replaceWith(newp); + pushDeletep(nodep); nodep=NULL; + newp->accept(*this,vup); + } else { + nodep->v3error("Unsupported: Cast to "<dtp()->prettyTypeName()); + nodep->replaceWith(nodep->lhsp()->unlinkFrBack()); + } + } virtual void visit(AstCast* nodep, AstNUser* vup) { if (nodep->childDTypep()) nodep->dtypep(moveChildDTypeEdit(nodep)); nodep->dtypep(iterateEditDTypep(nodep, nodep->dtypep())); diff --git a/src/verilog.y b/src/verilog.y index d77a53d6c..c3329e8d3 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2977,8 +2977,7 @@ expr: // IEEE: part of expression/constant_expression/primary | yUNSIGNED yP_TICK '(' expr ')' { $$ = new AstUnsigned($1,$4); } // // Spec only allows primary with addition of a type reference // // We'll be more general, and later assert LHS was a type. - //UNSUP ~l~expr yP_TICK '(' expr ')' { UNSUP } - | yaINTNUM yP_TICK '(' expr ')' { $$ = new AstCastSize($2,$4,new AstConst($1->fileline(),*$1)); } + | ~l~expr yP_TICK '(' expr ')' { $$ = new AstCastParse($2,$4,$1); } // // // IEEE: assignment_pattern_expression // // IEEE: streaming_concatenation diff --git a/test_regress/t/t_cast.v b/test_regress/t/t_cast.v index cda5ed171..5f23ff48b 100644 --- a/test_regress/t/t_cast.v +++ b/test_regress/t/t_cast.v @@ -11,6 +11,7 @@ module t; mc_t o; logic [15:0] allones = 16'hffff; + parameter FOUR = 4; initial begin if (4'shf > 4'sh0) $stop; @@ -18,6 +19,11 @@ module t; if (4'hf < 4'h0) $stop; if (unsigned'(4'shf) < 4'h0) $stop; if (4'(allones) !== 4'hf) $stop; + if (6'(allones) !== 6'h3f) $stop; + if ((4)'(allones) !== 4'hf) $stop; + if ((4+2)'(allones) !== 6'h3f) $stop; + if ((4-2)'(allones) !== 2'h3) $stop; + if ((FOUR+2)'(allones) !== 6'h3f) $stop; o = tocast_t'(4'b1); if (o != 4'b1) $stop;