From 475e4207cc5a089f12eff3a5cba22653c5cc5c39 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 9 Jun 2014 22:27:04 -0400 Subject: [PATCH] Fix late constant division by zero giving X error, bug775. --- Changes | 2 ++ src/V3Global.h | 4 ++++ src/V3Number.cpp | 26 +++++++++++++++++++++----- src/V3Number.h | 1 + src/Verilator.cpp | 1 + test_regress/t/t_math_div0.pl | 18 ++++++++++++++++++ test_regress/t/t_math_div0.v | 11 +++++++++++ test_regress/t/t_math_signed5.v | 10 +++++++++- 8 files changed, 67 insertions(+), 6 deletions(-) create mode 100755 test_regress/t/t_math_div0.pl create mode 100644 test_regress/t/t_math_div0.v diff --git a/Changes b/Changes index 425f4e699..e261897e5 100644 --- a/Changes +++ b/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] diff --git a/src/V3Global.h b/src/V3Global.h index 29c2f7ac3..af9832773 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -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; diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 99321c589..79c68146b 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -25,6 +25,7 @@ #include #include #include +#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>divs-start "<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 diff --git a/src/V3Number.h b/src/V3Number.h index 1ef58c6f5..706c31f10 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -145,6 +145,7 @@ public: } // SETTERS + V3Number& setAllBitsXRemoved(); V3Number& setAllBitsX(); V3Number& setAllBitsZ(); V3Number& setAllBits0(); diff --git a/src/Verilator.cpp b/src/Verilator.cpp index 33625e6d7..44c30bdee 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -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 diff --git a/test_regress/t/t_math_div0.pl b/test_regress/t/t_math_div0.pl new file mode 100755 index 000000000..566b77252 --- /dev/null +++ b/test_regress/t/t_math_div0.pl @@ -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; diff --git a/test_regress/t/t_math_div0.v b/test_regress/t/t_math_div0.v new file mode 100644 index 000000000..2d6fb09c3 --- /dev/null +++ b/test_regress/t/t_math_div0.v @@ -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 diff --git a/test_regress/t/t_math_signed5.v b/test_regress/t/t_math_signed5.v index 72e4f95ad..0f4585066 100644 --- a/test_regress/t/t_math_signed5.v +++ b/test_regress/t/t_math_signed5.v @@ -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