Support decimal constants of arbitrary widths.
This commit is contained in:
parent
ea78520220
commit
3c395c26be
2
Changes
2
Changes
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue