Fix power calculation; setAllOnes should not set hidden state bits in V3Number.

This commit is contained in:
Wilson Snyder 2014-04-08 20:28:16 -04:00
parent 5c39420d91
commit fb4928b2f5
5 changed files with 105 additions and 5 deletions

View File

@ -27,7 +27,7 @@ indicates the contributor was also the author of the fix; Thanks!
**** Fix signed extension problems with -Wno-WIDTH, bug729. [Clifford Wolf]
**** Fix power operator calculation, bug730. [Clifford Wolf]
**** Fix power operator calculation, bug730, bug735. [Clifford Wolf]
**** Fix Mac OS-X test issues. [Holger Waechtler]

View File

@ -47,6 +47,7 @@ V3Number::V3Number(VerilogString, FileLine* fileline, const string& str) {
}
}
}
opCleanThis();
}
V3Number::V3Number (FileLine* fileline, const char* sourcep) {
@ -252,6 +253,7 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
setBit(obit, bitIs(obit-1));
obit++;
}
opCleanThis();
//printf("Dump \"%s\" CP \"%s\" B '%c' %d W %d\n", sourcep, value_startp, base, width(), m_value[0]);
}
@ -276,11 +278,13 @@ V3Number& V3Number::setQuad(vluint64_t value) {
for (int i=0; i<words(); i++) m_value[i]=m_valueX[i] = 0;
m_value[0] = value & VL_ULL(0xffffffff);
m_value[1] = (value>>VL_ULL(32)) & VL_ULL(0xffffffff);
opCleanThis();
return *this;
}
V3Number& V3Number::setLong(uint32_t value) {
for (int i=0; i<words(); i++) m_value[i]=m_valueX[i] = 0;
m_value[0] = value;
opCleanThis();
return *this;
}
V3Number& V3Number::setLongS(vlsint32_t value) {
@ -288,6 +292,7 @@ V3Number& V3Number::setLongS(vlsint32_t value) {
union { uint32_t u; vlsint32_t s; } u;
u.s = value;
m_value[0] = u.u;
opCleanThis();
return *this;
}
V3Number& V3Number::setDouble(double value) {
@ -314,14 +319,17 @@ V3Number& V3Number::setAllBits0() {
}
V3Number& V3Number::setAllBits1() {
for (int i=0; i<words(); i++) { m_value[i]= ~0; m_valueX[i] = 0; }
opCleanThis();
return *this;
}
V3Number& V3Number::setAllBitsX() {
for (int i=0; i<words(); i++) { m_value[i]=m_valueX[i] = ~0; }
opCleanThis();
return *this;
}
V3Number& V3Number::setAllBitsZ() {
for (int i=0; i<words(); i++) { m_value[i]=0; m_valueX[i] = ~0; }
opCleanThis();
return *this;
}
V3Number& V3Number::setMask(int nbits) {
@ -341,6 +349,8 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
if (width()!=64) out<<"%E-bad-width-double";
else out<<toDouble();
return out.str();
} else {
if ((m_value[words()-1] | m_valueX[words()-1]) & ~hiWordMask()) out<<"%E-hidden-bits";
}
if (prefixed) {
if (sized()) {
@ -751,6 +761,7 @@ V3Number& V3Number::opCountOnes (const V3Number& lhs) {
if (lhs.isFourState()) return setAllBitsX();
setZero();
m_value[0] = lhs.countOnes();
opCleanThis();
return *this;
}
V3Number& V3Number::opIsUnknown (const V3Number& lhs) {
@ -1291,6 +1302,7 @@ V3Number& V3Number::opModDivGuts(const V3Number& lhs, const V3Number& rhs, bool
}
UINFO(9, " opmoddiv-1w "<<lhs<<" "<<rhs<<" q="<<*this<<" rem=0x"<<hex<<k<<dec<<endl);
if (is_modulus) { setZero(); m_value[0] = k; }
opCleanThis();
return *this;
}
@ -1373,9 +1385,11 @@ V3Number& V3Number::opModDivGuts(const V3Number& lhs, const V3Number& rhs, bool
m_value[i] = (un[i] >> s) | (shift_mask & (un[i+1] << (32-s)));
}
for (int i=vw; i<words; i++) m_value[i] = 0;
opCleanThis();
UINFO(9, " opmoddiv-mod "<<lhs<<" "<<rhs<<" now="<<*this<<endl);
return *this;
} else { // division
opCleanThis();
UINFO(9, " opmoddiv-div "<<lhs<<" "<<rhs<<" now="<<*this<<endl);
return *this;
}
@ -1457,9 +1471,8 @@ V3Number& V3Number::opClean (const V3Number& lhs, uint32_t bits) {
void V3Number::opCleanThis() {
// Clean in place number
if (uint32_t okbits = (width() & 31)) {
m_value[words()-1] &= ((1UL<<okbits)-1);
}
m_value[words()-1] &= hiWordMask();
m_valueX[words()-1] &= hiWordMask();
}
V3Number& V3Number::opSel (const V3Number& lhs, const V3Number& msb, const V3Number& lsb) {

View File

@ -103,6 +103,7 @@ private:
}
int words() const { return ((width()+31)/32); }
uint32_t hiWordMask() const { return VL_MASK_I(width()); }
V3Number& opModDivGuts(const V3Number& lhs, const V3Number& rhs, bool is_modulus);
@ -111,7 +112,7 @@ public:
// CONSTRUCTORS
V3Number(FileLine* fileline) { init(fileline, 1); }
V3Number(FileLine* fileline, int width) { init(fileline, width); } // 0=unsized
V3Number(FileLine* fileline, int width, uint32_t value) { init(fileline, width); m_value[0]=value; }
V3Number(FileLine* fileline, int width, uint32_t value) { init(fileline, width); m_value[0]=value; opCleanThis(); }
V3Number(FileLine* fileline, const char* source); // Create from a verilog 32'hxxxx number.
V3Number(VerilogString, FileLine* fileline, const string& vvalue);

18
test_regress/t/t_math_pow4.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 (
);
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -0,0 +1,68 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2014 by Clifford Wolf.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
wire [31:0] y;
reg a;
test004 sub (/*AUTOINST*/
// Outputs
.y (y[31:0]),
// Inputs
.a (a));
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d a=%x y=%x\n",$time, cyc, a, y);
`endif
cyc <= cyc + 1;
if (cyc==0) begin
a <= 0;
end
else if (cyc==1) begin
a <= 1;
if (y != 32'h0) $stop;
end
else if (cyc==2) begin
if (y != 32'h010000ff) $stop;
end
else if (cyc==99) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module test004(a, y);
input a;
output [31:0] y;
wire [7:0] y0;
wire [7:0] y1;
wire [7:0] y2;
wire [7:0] y3;
assign y = {y0,y1,y2,y3};
localparam [7:0] v0 = +8'sd1 ** -8'sd2; //'h01
localparam [7:0] v1 = +8'sd2 ** -8'sd2; //'h00
localparam [7:0] v2 = -8'sd2 ** -8'sd3; //'h00
localparam [7:0] v3 = -8'sd1 ** -8'sd3; //'hff
localparam [7:0] zero = 0;
initial $display("v0=%x v1=%x v2=%x v3=%x", v0,v1,v2,v3);
assign y0 = a ? v0 : zero;
assign y1 = a ? v1 : zero;
assign y2 = a ? v2 : zero;
assign y3 = a ? v3 : zero;
endmodule