Support cast operator with expression size, bug865.

This commit is contained in:
Wilson Snyder 2014-12-23 22:11:31 -05:00
parent 9f7c473376
commit 8b0af19351
5 changed files with 40 additions and 3 deletions

View File

@ -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

View File

@ -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:

View File

@ -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 "<<nodep->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()));

View File

@ -2977,8 +2977,7 @@ expr<nodep>: // 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

View File

@ -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;