forked from github/verilator
Fix cast width propagation (#2597).
This commit is contained in:
parent
6e7b07c794
commit
d78941885b
2
Changes
2
Changes
@ -16,6 +16,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
**** Fix iteration over mutating list bug in VPI (#2588). [Kaleb Barrett]
|
||||
|
||||
**** Fix cast width propagation (#2597). [flex-liu]
|
||||
|
||||
**** Fix return from callValueCbs (#2589) (#2605). [Marlon James]
|
||||
|
||||
**** Fix WIDTH warnings on comparisons with nullptr (#2602). [Rupert Swarbrick]
|
||||
|
@ -5953,6 +5953,7 @@ public:
|
||||
virtual bool cleanLhs() const { return true; }
|
||||
virtual bool sizeMattersLhs() const { return false; }
|
||||
AstNode* lhsp() const { return op1p(); }
|
||||
void lhsp(AstNode* nodep) { setOp1p(nodep); }
|
||||
virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
|
||||
AstNodeDType* childDTypep() const { return VN_CAST(op2p(), NodeDType); }
|
||||
virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
|
||||
|
@ -1661,41 +1661,47 @@ private:
|
||||
// Note we don't sign lhsp() that would make the algorithm O(n^2) if lots of casting.
|
||||
AstBasicDType* basicp = nodep->dtypep()->basicp();
|
||||
UASSERT_OBJ(basicp, nodep, "Unimplemented: Casting non-simple data type");
|
||||
// When implement more complicated types need to convert childDTypep to
|
||||
// dtypep() not as a child
|
||||
if (!basicp->isDouble() && !nodep->lhsp()->isDouble()) {
|
||||
// Note widthCheckSized might modify nodep->lhsp()
|
||||
AstNodeDType* subDTypep = nodep->findLogicDType(nodep->width(), nodep->width(),
|
||||
nodep->lhsp()->dtypep()->numeric());
|
||||
iterateCheck(nodep, "value", nodep->lhsp(), CONTEXT, FINAL, subDTypep, EXTEND_EXP,
|
||||
false);
|
||||
} else {
|
||||
iterateCheck(nodep, "value", nodep->lhsp(), SELF, FINAL, nodep->lhsp()->dtypep(),
|
||||
EXTEND_EXP, false);
|
||||
}
|
||||
AstNode* newp = nodep->lhsp()->unlinkFrBack();
|
||||
if (basicp->isDouble() && !newp->isDouble()) {
|
||||
if (newp->isSigned()) {
|
||||
newp = new AstISToRD(nodep->fileline(), newp);
|
||||
if (m_vup->prelim()) {
|
||||
userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p());
|
||||
// When implement more complicated types need to convert childDTypep to
|
||||
// dtypep() not as a child
|
||||
if (!basicp->isDouble() && !nodep->lhsp()->isDouble()) {
|
||||
// Note castSized might modify nodep->lhsp()
|
||||
int width = nodep->dtypep()->width();
|
||||
castSized(nodep, nodep->lhsp(), width);
|
||||
} else {
|
||||
newp = new AstIToRD(nodep->fileline(), newp);
|
||||
iterateCheck(nodep, "value", nodep->lhsp(), SELF, FINAL, nodep->lhsp()->dtypep(),
|
||||
EXTEND_EXP, false);
|
||||
}
|
||||
} else if (!basicp->isDouble() && newp->isDouble()) {
|
||||
if (basicp->isSigned()) {
|
||||
newp = new AstRToIRoundS(nodep->fileline(), newp);
|
||||
AstNode* newp = nodep->lhsp()->unlinkFrBack();
|
||||
if (basicp->isDouble() && !newp->isDouble()) {
|
||||
if (newp->isSigned()) {
|
||||
newp = new AstISToRD(nodep->fileline(), newp);
|
||||
} else {
|
||||
newp = new AstIToRD(nodep->fileline(), newp);
|
||||
}
|
||||
} else if (!basicp->isDouble() && newp->isDouble()) {
|
||||
if (basicp->isSigned()) {
|
||||
newp = new AstRToIRoundS(nodep->fileline(), newp);
|
||||
} else {
|
||||
newp = new AstUnsigned(nodep->fileline(),
|
||||
new AstRToIS(nodep->fileline(), newp));
|
||||
}
|
||||
} else if (basicp->isSigned() && !newp->isSigned()) {
|
||||
newp = new AstSigned(nodep->fileline(), newp);
|
||||
} else if (!basicp->isSigned() && newp->isSigned()) {
|
||||
newp = new AstUnsigned(nodep->fileline(), newp);
|
||||
} else {
|
||||
newp = new AstUnsigned(nodep->fileline(), new AstRToIS(nodep->fileline(), newp));
|
||||
// newp = newp; // Can just remove cast
|
||||
}
|
||||
} else if (basicp->isSigned() && !newp->isSigned()) {
|
||||
newp = new AstSigned(nodep->fileline(), newp);
|
||||
} else if (!basicp->isSigned() && newp->isSigned()) {
|
||||
newp = new AstUnsigned(nodep->fileline(), newp);
|
||||
} else {
|
||||
// newp = newp; // Can just remove cast
|
||||
nodep->lhsp(newp);
|
||||
// if (debug()) nodep->dumpTree(cout, " CastOut: ");
|
||||
}
|
||||
if (m_vup->final()) {
|
||||
AstNode* underp = nodep->lhsp()->unlinkFrBack();
|
||||
nodep->replaceWith(underp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
// if (debug()) newp->dumpTree(cout, " CastOut: ");
|
||||
}
|
||||
virtual void visit(AstCastSize* nodep) override {
|
||||
// IEEE: Signedness of result is same as self-determined signedness
|
||||
|
@ -9,9 +9,14 @@ module t (/*AUTOARG*/);
|
||||
logic in1 = 1;
|
||||
logic [1:0] in2 = 2'b11;
|
||||
logic [31:0] out;
|
||||
logic [7:0] ones = 8'b11111111;
|
||||
logic [9:0] ones10 = 10'b1111111111;
|
||||
|
||||
typedef logic [7:0] data_t;
|
||||
|
||||
typedef logic [9:0] ten_t;
|
||||
ten_t out10;
|
||||
|
||||
// verilator lint_off WIDTH
|
||||
initial begin
|
||||
in1 = 1;
|
||||
@ -31,6 +36,28 @@ module t (/*AUTOARG*/);
|
||||
out = data_t'(in1 << in2);
|
||||
if (out != 8'b1000) $stop;
|
||||
|
||||
// Check upper bits get cleared when cast
|
||||
in2 = 3;
|
||||
out = data_t'(ones << in2);
|
||||
if (out != 8'b11111000) $stop;
|
||||
|
||||
in2 = 3;
|
||||
out = data_t'(ones10 << in2);
|
||||
if (out != 8'b11111000) $stop;
|
||||
|
||||
// bug2597
|
||||
out = data_t'(10'h208 >> 2);
|
||||
if (out != 8'h82) $stop;
|
||||
|
||||
out = data_t'(10'h208 >> 2);
|
||||
if (out != 8'h82) $stop;
|
||||
|
||||
out = data_t'('h208 >> 2);
|
||||
if (out != 8'h82) $stop;
|
||||
|
||||
out10 = ten_t'('h404 >> 2);
|
||||
if (out10 != 10'h101) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish();
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user