Make some CVTREAL fatal where IEEE requires it.
This commit is contained in:
parent
7a32771c7e
commit
7f1011e5f7
|
|
@ -629,8 +629,8 @@ class WidthVisitor final : public VNVisitor {
|
||||||
iterateCheckString(nodep, "RHS", nodep->rhsp(), BOTH);
|
iterateCheckString(nodep, "RHS", nodep->rhsp(), BOTH);
|
||||||
nodep->dtypeSetString();
|
nodep->dtypeSetString();
|
||||||
} else {
|
} else {
|
||||||
iterateCheckSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
|
iterateCheckIntegralSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
|
||||||
iterateCheckSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
|
iterateCheckIntegralSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
|
||||||
|
|
||||||
if (m_streamConcat) {
|
if (m_streamConcat) {
|
||||||
packIfUnpacked(nodep->lhsp());
|
packIfUnpacked(nodep->lhsp());
|
||||||
|
|
@ -837,7 +837,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
if (vdtypep && vdtypep->isString()) {
|
if (vdtypep && vdtypep->isString()) {
|
||||||
iterateCheckString(nodep, "LHS", nodep->srcp(), BOTH);
|
iterateCheckString(nodep, "LHS", nodep->srcp(), BOTH);
|
||||||
} else {
|
} else {
|
||||||
iterateCheckSelf(nodep, "LHS", nodep->srcp(), SELF, BOTH);
|
iterateCheckIntegralSelf(nodep, "LHS", nodep->srcp(), SELF, BOTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((vdtypep && vdtypep->isString()) || nodep->srcp()->isString()) {
|
if ((vdtypep && vdtypep->isString()) || nodep->srcp()->isString()) {
|
||||||
|
|
@ -971,7 +971,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
if (debug() >= 9) nodep->dumpTree("- selWidth: ");
|
if (debug() >= 9) nodep->dumpTree("- selWidth: ");
|
||||||
userIterateAndNext(nodep->fromp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
userIterateAndNext(nodep->fromp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
||||||
userIterateAndNext(nodep->lsbp(), WidthVP{SELF, PRELIM}.p());
|
userIterateAndNext(nodep->lsbp(), WidthVP{SELF, PRELIM}.p());
|
||||||
checkCvtUS(nodep->fromp());
|
checkCvtUS(nodep->fromp(), false);
|
||||||
iterateCheckSizedSelf(nodep, "Select LHS", nodep->fromp(), SELF, BOTH);
|
iterateCheckSizedSelf(nodep, "Select LHS", nodep->fromp(), SELF, BOTH);
|
||||||
int width = nodep->widthConst();
|
int width = nodep->widthConst();
|
||||||
if (width <= 0) {
|
if (width <= 0) {
|
||||||
|
|
@ -1510,7 +1510,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkCvtUS(nodep->lhsp());
|
checkCvtUS(nodep->lhsp(), false);
|
||||||
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
|
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
|
||||||
nodep->dtypeFrom(nodep->lhsp());
|
nodep->dtypeFrom(nodep->lhsp());
|
||||||
}
|
}
|
||||||
|
|
@ -6826,7 +6826,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
UASSERT_OBJ(!nodep->op2p(), nodep, "For unary ops only!");
|
UASSERT_OBJ(!nodep->op2p(), nodep, "For unary ops only!");
|
||||||
if (m_vup->prelim()) {
|
if (m_vup->prelim()) {
|
||||||
userIterateAndNext(nodep->lhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
userIterateAndNext(nodep->lhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
||||||
if (!real_ok) checkCvtUS(nodep->lhsp());
|
if (!real_ok) checkCvtUS(nodep->lhsp(), false);
|
||||||
}
|
}
|
||||||
if (real_ok && nodep->lhsp()->isDouble()) {
|
if (real_ok && nodep->lhsp()->isDouble()) {
|
||||||
spliceCvtD(nodep->lhsp());
|
spliceCvtD(nodep->lhsp());
|
||||||
|
|
@ -6867,7 +6867,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
UASSERT_OBJ(!nodep->op2p(), nodep, "For unary ops only!");
|
UASSERT_OBJ(!nodep->op2p(), nodep, "For unary ops only!");
|
||||||
if (m_vup->prelim()) {
|
if (m_vup->prelim()) {
|
||||||
userIterateAndNext(nodep->lhsp(), WidthVP{SELF, PRELIM}.p());
|
userIterateAndNext(nodep->lhsp(), WidthVP{SELF, PRELIM}.p());
|
||||||
checkCvtUS(nodep->lhsp());
|
checkCvtUS(nodep->lhsp(), true);
|
||||||
const int width = nodep->lhsp()->width();
|
const int width = nodep->lhsp()->width();
|
||||||
AstNodeDType* const expDTypep = nodep->findLogicDType(width, width, rs_out);
|
AstNodeDType* const expDTypep = nodep->findLogicDType(width, width, rs_out);
|
||||||
nodep->dtypep(expDTypep);
|
nodep->dtypep(expDTypep);
|
||||||
|
|
@ -6895,7 +6895,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
// RHS is self-determined. RHS is always treated as unsigned, has no effect on result.
|
// RHS is self-determined. RHS is always treated as unsigned, has no effect on result.
|
||||||
if (m_vup->prelim()) {
|
if (m_vup->prelim()) {
|
||||||
userIterateAndNext(nodep->lhsp(), WidthVP{SELF, PRELIM}.p());
|
userIterateAndNext(nodep->lhsp(), WidthVP{SELF, PRELIM}.p());
|
||||||
checkCvtUS(nodep->lhsp());
|
checkCvtUS(nodep->lhsp(), false);
|
||||||
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
|
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
|
||||||
nodep->dtypeFrom(nodep->lhsp());
|
nodep->dtypeFrom(nodep->lhsp());
|
||||||
}
|
}
|
||||||
|
|
@ -6955,8 +6955,8 @@ class WidthVisitor final : public VNVisitor {
|
||||||
// Determine expression widths only relying on what's in the subops
|
// Determine expression widths only relying on what's in the subops
|
||||||
userIterateAndNext(nodep->lhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
userIterateAndNext(nodep->lhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
||||||
userIterateAndNext(nodep->rhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
userIterateAndNext(nodep->rhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
||||||
checkCvtUS(nodep->lhsp());
|
checkCvtUS(nodep->lhsp(), false);
|
||||||
checkCvtUS(nodep->rhsp());
|
checkCvtUS(nodep->rhsp(), false);
|
||||||
const int width = std::max(nodep->lhsp()->width(), nodep->rhsp()->width());
|
const int width = std::max(nodep->lhsp()->width(), nodep->rhsp()->width());
|
||||||
const int mwidth = std::max(nodep->lhsp()->widthMin(), nodep->rhsp()->widthMin());
|
const int mwidth = std::max(nodep->lhsp()->widthMin(), nodep->rhsp()->widthMin());
|
||||||
const bool expSigned = (nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
|
const bool expSigned = (nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
|
||||||
|
|
@ -6990,8 +6990,8 @@ class WidthVisitor final : public VNVisitor {
|
||||||
userIterateAndNext(nodep->lhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
userIterateAndNext(nodep->lhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
||||||
userIterateAndNext(nodep->rhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
userIterateAndNext(nodep->rhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
||||||
if (!real_ok) {
|
if (!real_ok) {
|
||||||
checkCvtUS(nodep->lhsp());
|
checkCvtUS(nodep->lhsp(), false);
|
||||||
checkCvtUS(nodep->rhsp());
|
checkCvtUS(nodep->rhsp(), false);
|
||||||
}
|
}
|
||||||
if (nodep->lhsp()->isDouble() || nodep->rhsp()->isDouble()) {
|
if (nodep->lhsp()->isDouble() || nodep->rhsp()->isDouble()) {
|
||||||
spliceCvtD(nodep->lhsp());
|
spliceCvtD(nodep->lhsp());
|
||||||
|
|
@ -7330,8 +7330,12 @@ class WidthVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
(void)underp; // cppcheck
|
(void)underp; // cppcheck
|
||||||
}
|
}
|
||||||
void iterateCheckSelf(AstNode* nodep, const char* side, AstNode* underp, Determ determ,
|
void iterateCheckIntegralSelf(AstNode* nodep, const char* side, AstNode* underp, Determ determ,
|
||||||
Stage stage) {
|
Stage stage) {
|
||||||
|
iterateCheckSelf(nodep, side, underp, determ, stage, true);
|
||||||
|
}
|
||||||
|
void iterateCheckSelf(AstNode* nodep, const char* side, AstNode* underp, Determ determ,
|
||||||
|
Stage stage, bool integralOnly = false) {
|
||||||
// Coerce child to any data type; child is self-determined
|
// Coerce child to any data type; child is self-determined
|
||||||
// i.e. isolated from expected type.
|
// i.e. isolated from expected type.
|
||||||
// e.g. nodep=CONCAT, underp=lhs in CONCAT(lhs,rhs)
|
// e.g. nodep=CONCAT, underp=lhs in CONCAT(lhs,rhs)
|
||||||
|
|
@ -7341,7 +7345,8 @@ class WidthVisitor final : public VNVisitor {
|
||||||
if (stage & PRELIM) {
|
if (stage & PRELIM) {
|
||||||
underp = userIterateSubtreeReturnEdits(underp, WidthVP{SELF, PRELIM}.p());
|
underp = userIterateSubtreeReturnEdits(underp, WidthVP{SELF, PRELIM}.p());
|
||||||
}
|
}
|
||||||
underp = VN_IS(underp, NodeExpr) ? checkCvtUS(VN_AS(underp, NodeExpr)) : underp;
|
underp
|
||||||
|
= VN_IS(underp, NodeExpr) ? checkCvtUS(VN_AS(underp, NodeExpr), integralOnly) : underp;
|
||||||
AstNodeDType* const expDTypep = underp->dtypep();
|
AstNodeDType* const expDTypep = underp->dtypep();
|
||||||
underp = iterateCheck(nodep, side, underp, SELF, FINAL, expDTypep, EXTEND_EXP);
|
underp = iterateCheck(nodep, side, underp, SELF, FINAL, expDTypep, EXTEND_EXP);
|
||||||
(void)underp; // cppcheck
|
(void)underp; // cppcheck
|
||||||
|
|
@ -7357,7 +7362,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
if (stage & PRELIM) {
|
if (stage & PRELIM) {
|
||||||
underp = userIterateSubtreeReturnEdits(underp, WidthVP{SELF, PRELIM}.p());
|
underp = userIterateSubtreeReturnEdits(underp, WidthVP{SELF, PRELIM}.p());
|
||||||
}
|
}
|
||||||
underp = VN_IS(underp, NodeExpr) ? checkCvtUS(VN_AS(underp, NodeExpr)) : underp;
|
underp = VN_IS(underp, NodeExpr) ? checkCvtUS(VN_AS(underp, NodeExpr), false) : underp;
|
||||||
AstNodeDType* const expDTypep = underp->dtypep();
|
AstNodeDType* const expDTypep = underp->dtypep();
|
||||||
underp = iterateCheck(nodep, side, underp, SELF, FINAL, expDTypep, EXTEND_EXP);
|
underp = iterateCheck(nodep, side, underp, SELF, FINAL, expDTypep, EXTEND_EXP);
|
||||||
AstNodeDType* const checkDtp = expDTypep->skipRefToEnump();
|
AstNodeDType* const checkDtp = expDTypep->skipRefToEnump();
|
||||||
|
|
@ -7674,11 +7679,15 @@ class WidthVisitor final : public VNVisitor {
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// SIGNED/DOUBLE METHODS
|
// SIGNED/DOUBLE METHODS
|
||||||
|
|
||||||
AstNodeExpr* checkCvtUS(AstNodeExpr* nodep) {
|
AstNodeExpr* checkCvtUS(AstNodeExpr* nodep, bool fatal) {
|
||||||
if (nodep && nodep->dtypep()->skipRefp()->isDouble()) {
|
if (nodep && nodep->dtypep()->skipRefp()->isDouble()) {
|
||||||
|
if (fatal) {
|
||||||
|
nodep->v3error("Expected integral input to " << nodep->backp()->prettyTypeName());
|
||||||
|
} else {
|
||||||
nodep->v3warn(REALCVT,
|
nodep->v3warn(REALCVT,
|
||||||
"Implicit conversion of real to integer; expected integral input to "
|
"Implicit conversion of real to integer; expected integral input to "
|
||||||
<< nodep->backp()->prettyTypeName());
|
<< nodep->backp()->prettyTypeName());
|
||||||
|
}
|
||||||
nodep = spliceCvtS(nodep, false, 32);
|
nodep = spliceCvtS(nodep, false, 32);
|
||||||
}
|
}
|
||||||
return nodep;
|
return nodep;
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,46 @@
|
||||||
%Warning-REALCVT: t/t_lint_realcvt_bad.v:12:18: Implicit conversion of real to integer
|
%Warning-REALCVT: t/t_lint_realcvt_bad.v:12:17: Implicit conversion of real to integer
|
||||||
12 | time t_bad1 = 9.001ns;
|
12 | time t_bad1 = 9.001ns;
|
||||||
| ^~~~~~~
|
| ^~~~~~~
|
||||||
... For warning description see https://verilator.org/warn/REALCVT?v=latest
|
... For warning description see https://verilator.org/warn/REALCVT?v=latest
|
||||||
... Use "/* verilator lint_off REALCVT */" and lint_on around source to disable this message.
|
... Use "/* verilator lint_off REALCVT */" and lint_on around source to disable this message.
|
||||||
%Warning-REALCVT: t/t_lint_realcvt_bad.v:13:18: Implicit conversion of real to integer
|
%Warning-REALCVT: t/t_lint_realcvt_bad.v:13:17: Implicit conversion of real to integer
|
||||||
13 | time t_bad2 = 9.999ns;
|
13 | time t_bad2 = 9.999ns;
|
||||||
| ^~~~~~~
|
| ^~~~~~~
|
||||||
%Warning-REALCVT: t/t_lint_realcvt_bad.v:17:18: Implicit conversion of real to integer
|
%Warning-REALCVT: t/t_lint_realcvt_bad.v:17:17: Implicit conversion of real to integer
|
||||||
17 | time t_bad3 = 9ps;
|
17 | time t_bad3 = 9ps;
|
||||||
| ^~~
|
| ^~~
|
||||||
%Warning-REALCVT: t/t_lint_realcvt_bad.v:23:22: Implicit conversion of real to integer
|
%Warning-REALCVT: t/t_lint_realcvt_bad.v:23:21: Implicit conversion of real to integer
|
||||||
23 | integer i_bad21 = 23.1;
|
23 | integer i_bad21 = 23.1;
|
||||||
| ^~~~
|
| ^~~~
|
||||||
|
%Error: t/t_lint_realcvt_bad.v:27:17: Expected integral input to SIGNED
|
||||||
|
: ... note: In instance 'sub'
|
||||||
|
27 | i = $signed(1.0);
|
||||||
|
| ^~~
|
||||||
|
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||||
|
%Error: t/t_lint_realcvt_bad.v:28:19: Expected integral input to UNSIGNED
|
||||||
|
: ... note: In instance 'sub'
|
||||||
|
28 | i = $unsigned(1.0);
|
||||||
|
| ^~~
|
||||||
|
%Error: t/t_lint_realcvt_bad.v:29:10: Expected integral input to CONCAT
|
||||||
|
: ... note: In instance 'sub'
|
||||||
|
29 | i = {1.2, 1.3};
|
||||||
|
| ^~~
|
||||||
|
%Error: t/t_lint_realcvt_bad.v:29:15: Expected integral input to CONCAT
|
||||||
|
: ... note: In instance 'sub'
|
||||||
|
29 | i = {1.2, 1.3};
|
||||||
|
| ^~~
|
||||||
|
%Warning-WIDTHTRUNC: t/t_lint_realcvt_bad.v:29:7: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's REPLICATE generates 64 bits.
|
||||||
|
: ... note: In instance 'sub'
|
||||||
|
29 | i = {1.2, 1.3};
|
||||||
|
| ^
|
||||||
|
... For warning description see https://verilator.org/warn/WIDTHTRUNC?v=latest
|
||||||
|
... Use "/* verilator lint_off WIDTHTRUNC */" and lint_on around source to disable this message.
|
||||||
|
%Error: t/t_lint_realcvt_bad.v:30:12: Expected integral input to REPLICATE
|
||||||
|
: ... note: In instance 'sub'
|
||||||
|
30 | i = {6{1.2}};
|
||||||
|
| ^~~
|
||||||
|
%Warning-WIDTHTRUNC: t/t_lint_realcvt_bad.v:30:7: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's REPLICATE generates 192 bits.
|
||||||
|
: ... note: In instance 'sub'
|
||||||
|
30 | i = {6{1.2}};
|
||||||
|
| ^
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
|
|
@ -22,4 +22,12 @@ module sub;
|
||||||
integer i_ok20 = 23.0; // No warning
|
integer i_ok20 = 23.0; // No warning
|
||||||
integer i_bad21 = 23.1;
|
integer i_bad21 = 23.1;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
int i;
|
||||||
|
i = $signed(1.0); // Error, doesn't support real, not just warning
|
||||||
|
i = $unsigned(1.0); // Error, doesn't support real, not just warning
|
||||||
|
i = {1.2, 1.3}; // Error, doesn't support real, not just warning
|
||||||
|
i = {6{1.2}}; // Error, doesn't support real, not just warning
|
||||||
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue