forked from github/verilator
Fix late constant division by zero giving X error, bug775.
This commit is contained in:
parent
71b2eed32c
commit
475e4207cc
2
Changes
2
Changes
@ -25,6 +25,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
**** Fix C compiler interpreting signing, bug773. [Clifford Wolf]
|
||||
|
||||
**** Fix late constant division by zero giving X error, bug775. [Clifford Wolf]
|
||||
|
||||
**** Fix gate primitives with arrays and non-arrayed pins.
|
||||
|
||||
**** Fix DETECTARRAY error on packed arrays, bug770. [Jie Xu]
|
||||
|
@ -44,6 +44,7 @@ class V3Global {
|
||||
int m_debugFileNumber; // Number to append to debug files created
|
||||
bool m_assertDTypesResolved; // Tree should have dtypep()'s
|
||||
bool m_assertWidthsMatch; // Tree should have width()==widthMin()
|
||||
bool m_constRemoveXs; // Const needs to strip any Xs
|
||||
bool m_needHInlines; // Need __Inlines file
|
||||
bool m_needHeavy; // Need verilated_heavy.h include
|
||||
bool m_dpi; // Need __Dpi include files
|
||||
@ -58,6 +59,7 @@ public:
|
||||
m_debugFileNumber = 0;
|
||||
m_assertDTypesResolved = false;
|
||||
m_assertWidthsMatch = false;
|
||||
m_constRemoveXs = false;
|
||||
m_needHInlines = false;
|
||||
m_needHeavy = false;
|
||||
m_dpi = false;
|
||||
@ -77,6 +79,8 @@ public:
|
||||
static void dumpCheckGlobalTree(const string& filename, int newNumber=0, bool doDump=true);
|
||||
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
|
||||
void assertWidthsMatch(bool flag) { m_assertWidthsMatch = flag; }
|
||||
bool constRemoveXs() const { return m_constRemoveXs; }
|
||||
void constRemoveXs(bool flag) { m_constRemoveXs = flag; }
|
||||
string debugFilename(const string& nameComment, int newNumber=0) {
|
||||
++m_debugFileNumber;
|
||||
if (newNumber) m_debugFileNumber = newNumber;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <cstdarg>
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include "V3Global.h"
|
||||
#include "V3Number.h"
|
||||
|
||||
#define MAX_SPRINTF_DOUBLE_SIZE 100 // Maximum characters with a sprintf %e/%f/%g (probably < 30)
|
||||
@ -323,6 +324,7 @@ V3Number& V3Number::setAllBits1() {
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::setAllBitsX() {
|
||||
// Use setAllBitsXRemoved if calling this based on a non-X/Z input value such as divide by zero
|
||||
for (int i=0; i<words(); i++) { m_value[i]=m_valueX[i] = ~0; }
|
||||
opCleanThis();
|
||||
return *this;
|
||||
@ -332,6 +334,20 @@ V3Number& V3Number::setAllBitsZ() {
|
||||
opCleanThis();
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::setAllBitsXRemoved() {
|
||||
if (!v3Global.constRemoveXs()) {
|
||||
return setAllBitsX();
|
||||
} else {
|
||||
// If we get a divide by zero we get Xs.
|
||||
// But after V3Unknown we have removed Xs, so use --x-assign to direct-insert 0/1
|
||||
if (v3Global.opt.xAssign() == "1") {
|
||||
return setAllBits1();
|
||||
} else {
|
||||
return setAllBits0();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
V3Number& V3Number::setMask(int nbits) {
|
||||
setZero();
|
||||
for (int bit=0; bit<nbits; bit++) { setBit(bit,1); }
|
||||
@ -1248,7 +1264,7 @@ V3Number& V3Number::opDiv (const V3Number& lhs, const V3Number& rhs) {
|
||||
UINFO(9, "opdiv "<<lhs<<" "<<rhs<<endl);
|
||||
// i op j, max(L(lhs),L(rhs)) bit return, if any 4-state, 4-state return
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsXRemoved();
|
||||
if (lhs.width()<=64) {
|
||||
setQuad(lhs.toUQuad() / rhs.toUQuad());
|
||||
return *this;
|
||||
@ -1261,7 +1277,7 @@ V3Number& V3Number::opDivS (const V3Number& lhs, const V3Number& rhs) {
|
||||
// Signed divide
|
||||
//UINFO(9, ">>divs-start "<<lhs<<" "<<rhs<<endl);
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsXRemoved();
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
|
||||
V3Number qNoSign = opDiv(lhsNoSign,rhsNoSign);
|
||||
@ -1278,7 +1294,7 @@ V3Number& V3Number::opDivS (const V3Number& lhs, const V3Number& rhs) {
|
||||
V3Number& V3Number::opModDiv (const V3Number& lhs, const V3Number& rhs) {
|
||||
// i op j, max(L(lhs),L(rhs)) bit return, if any 4-state, 4-state return
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsXRemoved();
|
||||
if (lhs.width()<=64) {
|
||||
setQuad(lhs.toUQuad() % rhs.toUQuad());
|
||||
return *this;
|
||||
@ -1290,7 +1306,7 @@ V3Number& V3Number::opModDiv (const V3Number& lhs, const V3Number& rhs) {
|
||||
V3Number& V3Number::opModDivS (const V3Number& lhs, const V3Number& rhs) {
|
||||
// Signed moddiv
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsXRemoved();
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
|
||||
V3Number qNoSign = opModDiv(lhsNoSign,rhsNoSign);
|
||||
@ -1428,7 +1444,7 @@ V3Number& V3Number::opPow (const V3Number& lhs, const V3Number& rhs, bool lsign,
|
||||
if (lhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large >64bit ** power operator not implemented yet: "<<*this);
|
||||
if (rhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large >64bit ** power operator not implemented yet: "<<*this);
|
||||
if (rsign && rhs.isNegative()) {
|
||||
if (lhs.isEqZero()) return setAllBitsX();
|
||||
if (lhs.isEqZero()) return setAllBitsXRemoved();
|
||||
else if (lhs.isEqOne()) return setQuad(1);
|
||||
else if (lsign && lhs.isEqAllOnes()) {
|
||||
if (rhs.bitIs1(0)) return setAllBits1(); // -1^odd=-1
|
||||
|
@ -145,6 +145,7 @@ public:
|
||||
}
|
||||
|
||||
// SETTERS
|
||||
V3Number& setAllBitsXRemoved();
|
||||
V3Number& setAllBitsX();
|
||||
V3Number& setAllBitsZ();
|
||||
V3Number& setAllBits0();
|
||||
|
@ -256,6 +256,7 @@ void process () {
|
||||
// Move assignments from X into MODULE temps.
|
||||
// (Before flattening, so each new X variable is shared between all scopes of that module.)
|
||||
V3Unknown::unknownAll(v3Global.rootp());
|
||||
v3Global.constRemoveXs(true);
|
||||
V3Global::dumpCheckGlobalTree("unknown.tree");
|
||||
|
||||
// Module inlining
|
||||
|
18
test_regress/t/t_math_div0.pl
Executable file
18
test_regress/t/t_math_div0.pl
Executable file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ['--x-assign 0'],
|
||||
);
|
||||
|
||||
execute (
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
11
test_regress/t/t_math_div0.v
Normal file
11
test_regress/t/t_math_div0.v
Normal file
@ -0,0 +1,11 @@
|
||||
module t(y);
|
||||
output [3:0] y;
|
||||
// bug775
|
||||
// verilator lint_off WIDTH
|
||||
assign y = ((0/0) ? 1 : 2) % 0;
|
||||
|
||||
initial begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
@ -11,7 +11,10 @@
|
||||
`define c(v,vs) (v)
|
||||
`endif
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
ow4_u
|
||||
);
|
||||
|
||||
bit fail;
|
||||
|
||||
@ -157,4 +160,9 @@
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
// bug775
|
||||
output [3:0] ow4_u; // Must be consumed
|
||||
assign ow4_u = ((0/0) ? 1 : 2) % 0;
|
||||
|
||||
endmodule
|
||||
|
Loading…
Reference in New Issue
Block a user