Fix late constant division by zero giving X error, bug775.

This commit is contained in:
Wilson Snyder 2014-06-09 22:27:04 -04:00
parent 71b2eed32c
commit 475e4207cc
8 changed files with 67 additions and 6 deletions

View File

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

View File

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

View File

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

View File

@ -145,6 +145,7 @@ public:
}
// SETTERS
V3Number& setAllBitsXRemoved();
V3Number& setAllBitsX();
V3Number& setAllBitsZ();
V3Number& setAllBits0();

View File

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

View 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

View File

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