Support decimal constants of arbitrary widths.

This commit is contained in:
Wilson Snyder 2009-06-12 08:27:48 -04:00
parent ea78520220
commit 3c395c26be
7 changed files with 99 additions and 12 deletions

View File

@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.71***
**** Support decimal constants of arbitrary widths. [Mark Marshall]
**** Fix segfault on unrolling for's with bad inits, bug90. [Andreas Olofsson]
**** Fix tristates causing "Assigned pin is neither...". [by Lane Brooks]

View File

@ -131,31 +131,43 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
// Convert decimal number to hex
int olen = 0;
uint32_t val = 0;
for (const char* cp=value_startp;
*cp; cp++) {
int got_x = 0;
int got_z = 0;
int got_01 = 0;
for (const char* cp=value_startp; *cp; cp++) {
switch (tolower(*cp)) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
val = val*10 + (*cp-'0');
m_value[0] = val;
if (width()>32 && olen>7/*10000000 fits in 32 bits, so ok*/) {
m_fileline->v3error("Unsupported: Conversion of decimal number over 32 bits, use hex\n");
olen=0;
if (olen<=7) { // 10000000 fits in 32 bits, so ok
// Constants are common, so for speed avoid wide math until we need it
val = val*10 + (*cp-'0');
m_value[0] = val;
} else { // Wide; all previous digits are already in m_value[0]
// this = (this * 10)/*product*/ + (*cp-'0')/*addend*/
// Assumed rare; lots of optimizations are possible here
V3Number product (fileline, width()+4); // +4 for overflow detection
V3Number ten (fileline, width()+4, 10);
V3Number addend (fileline, width(), (*cp-'0'));
product.opMul(*this,ten);
this->opAdd(product,addend);
if (product.bitsValue(width(), 4)) { // Overflowed
m_fileline->v3error("Too many digits for "<<width()<<" bit number: "<<sourcep);
while (*(cp+1)) cp++; // Skip ahead so don't get multiple warnings
}
}
olen++;
got_01 = 1;
break;
}
case 'z': case '?': {
if (olen) m_fileline->v3error("Multi-digit X/Z/? not legal in decimal constant: "<<*cp);
if (!m_sized) m_fileline->v3error("Unsized X/Z/? not legal in decimal constant: "<<*cp);
olen++;
setAllBitsZ();
got_z = 1;
break;
}
case 'x': {
if (olen) m_fileline->v3error("Multi-digit X/Z/? not legal in decimal constant: "<<*cp);
if (!m_sized) m_fileline->v3error("Unsized X/Z/? not legal in decimal constant: "<<*cp);
olen++;
got_x = 1;
setAllBitsX();
break;
}
@ -167,6 +179,7 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
}
}
obit = width();
if ((got_01+got_x+got_z)>1) m_fileline->v3error("Mixing X/Z/? with digits not legal in decimal constant: "<<value_startp);
}
else {
// Convert bin/octal number to hex
@ -174,7 +187,7 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
(cp>=value_startp
&& obit<=width());
cp--) {
if (*cp!='_' && obit>=width()) {
if (*cp!='_' && *cp!='0' && obit>=width()) {
m_fileline->v3error("Too many digits for "<<width()<<" bit number: "<<sourcep);
break;
}

View File

@ -0,0 +1,19 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 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 (
v_flags2 => ["--lint-only"],
fails=>1,
expect=>
'%Error: t/t_const_dec_mixed_bad.v:\d+: Mixing X/Z/\? with digits not legal in decimal constant: x_1
%Error: Exiting due to.*',
);
ok(1);
1;

View File

@ -0,0 +1,10 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2005-2007 by Wilson Snyder.
module t (/*AUTOARG*/);
parameter [200:0] MIXED = 32'dx_1;
endmodule

View File

@ -0,0 +1,22 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 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 (
v_flags2 => ["--lint-only"],
fails=>1,
expect=>
'%Error: t/t_const_overflow_bad.v:\d+: Too many digits for 94 bit number: 94\'d123456789012345678901234567890
%Error: t/t_const_overflow_bad.v:\d+: Too many digits for 8 bit number: 8\'habc
%Error: t/t_const_overflow_bad.v:\d+: Too many digits for 6 bit number: 6\'o1234
%Error: t/t_const_overflow_bad.v:\d+: Too many digits for 3 bit number: 3\'b1111
%Error: Exiting due to.*',
);
ok(1);
1;

View File

@ -0,0 +1,17 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2005-2007 by Wilson Snyder.
module t (/*AUTOARG*/);
parameter [200:0] TOO_SMALL = 94'd123456789012345678901234567890; // One to many digits
parameter [200:0] SMALLH = 8'habc; // One to many digits
parameter [200:0] SMALLO = 6'o1234; // One to many digits
parameter [200:0] SMALLB = 3'b1111; // One to many digits
// We'll allow this though; no reason to be cruel
parameter [200:0] OKH = 8'h000000001;
endmodule

View File

@ -84,6 +84,10 @@ module t (/*AUTOARG*/
if ( con__ascii !== {"abcd","efgh","ijkl","mnop"}) $stop;
if ( 3'dx !== 3'hx) $stop;
// Wide decimal
if ( 94'd12345678901234567890123456789 != 94'h27e41b3246bec9b16e398115) $stop;
if (-94'sd123456789012345678901234567 != 94'h3f99e1020ea70d57d360b479) $stop;
end
if (cyc==2) begin
win <= 32'h123123;