Break sized constants into a size token
and a based numeric constant.
This commit is contained in:
parent
3b17456254
commit
561a268c9c
470
lexor.lex
470
lexor.lex
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT) && !defined(macintosh)
|
#if !defined(WINNT) && !defined(macintosh)
|
||||||
#ident "$Id: lexor.lex,v 1.77 2003/03/18 01:36:14 steve Exp $"
|
#ident "$Id: lexor.lex,v 1.78 2003/04/14 03:37:47 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
@ -80,10 +80,6 @@ void reset_lexor();
|
||||||
static void line_directive();
|
static void line_directive();
|
||||||
static void line_directive2();
|
static void line_directive2();
|
||||||
|
|
||||||
static verinum*make_sized_binary(const char*txt);
|
|
||||||
static verinum*make_sized_dec(const char*txt);
|
|
||||||
static verinum*make_sized_octal(const char*txt);
|
|
||||||
static verinum*make_sized_hex(const char*txt);
|
|
||||||
static verinum*make_unsized_binary(const char*txt);
|
static verinum*make_unsized_binary(const char*txt);
|
||||||
static verinum*make_unsized_dec(const char*txt);
|
static verinum*make_unsized_dec(const char*txt);
|
||||||
static verinum*make_unsized_octal(const char*txt);
|
static verinum*make_unsized_octal(const char*txt);
|
||||||
|
|
@ -228,67 +224,19 @@ W [ \t\b\f\r]+
|
||||||
yylval.text = strdup(yytext);
|
yylval.text = strdup(yytext);
|
||||||
return SYSTEM_IDENTIFIER; }
|
return SYSTEM_IDENTIFIER; }
|
||||||
|
|
||||||
[0-9][0-9_]*[ \t]*\'[sS]?[dD][ \t]*[0-9][0-9_]* {
|
|
||||||
yylval.number = make_sized_dec(yytext);
|
|
||||||
return NUMBER; }
|
|
||||||
[0-9][0-9_]*[ \t]*\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ {
|
|
||||||
yylval.number = make_sized_binary(yytext);
|
|
||||||
return NUMBER; }
|
|
||||||
[0-9][0-9_]*[ \t]*\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ {
|
|
||||||
yylval.number = make_sized_octal(yytext);
|
|
||||||
return NUMBER; }
|
|
||||||
[0-9][0-9_]*[ \t]*\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ {
|
|
||||||
yylval.number = make_sized_hex(yytext);
|
|
||||||
return NUMBER; }
|
|
||||||
|
|
||||||
\'[sS]?[dD][ \t]*[0-9][0-9_]* { yylval.number = make_unsized_dec(yytext);
|
\'[sS]?[dD][ \t]*[0-9][0-9_]* { yylval.number = make_unsized_dec(yytext);
|
||||||
return NUMBER; }
|
return BASED_NUMBER; }
|
||||||
\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ { yylval.number = make_unsized_binary(yytext);
|
\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ { yylval.number = make_unsized_binary(yytext);
|
||||||
return NUMBER; }
|
return BASED_NUMBER; }
|
||||||
\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ { yylval.number = make_unsized_octal(yytext);
|
\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ { yylval.number = make_unsized_octal(yytext);
|
||||||
return NUMBER; }
|
return BASED_NUMBER; }
|
||||||
\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
|
\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
|
||||||
return NUMBER; }
|
return BASED_NUMBER; }
|
||||||
|
|
||||||
[0-9][0-9_]* {
|
[0-9][0-9_]* {
|
||||||
char buf[4096];
|
yylval.number = make_unsized_dec(yytext);
|
||||||
|
return DEC_NUMBER; }
|
||||||
if (strlen(yytext) >= sizeof(buf)-2){
|
|
||||||
fprintf(stderr, "Ridicilously long decimal constant will be truncated!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(buf, yytext, sizeof(buf)-2);
|
|
||||||
buf[sizeof(buf)-1] = 0;
|
|
||||||
|
|
||||||
/* Convert the decimal number to a binary value, one digit at
|
|
||||||
a time. Watch out for overflow. */
|
|
||||||
verinum::V*bits = new verinum::V[INTEGER_WIDTH];
|
|
||||||
unsigned idx=0;
|
|
||||||
unsigned nbits=INTEGER_WIDTH;
|
|
||||||
|
|
||||||
while(idx<nbits){
|
|
||||||
int rem = dec_buf_div2(buf);
|
|
||||||
|
|
||||||
bits[idx] = (rem==1) ? verinum::V1 : verinum::V0;
|
|
||||||
++idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(; idx<nbits; ++idx){
|
|
||||||
bits[idx] = verinum::V0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we run out of bits to hold the value, but there are
|
|
||||||
still valueable bits in the number, print a warning. */
|
|
||||||
if (strcmp(buf, "0") != 0){
|
|
||||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
|
||||||
": warning: Numeric decimal constant ``" << yytext <<
|
|
||||||
"'' truncated to " << nbits << " bits." << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
yylval.number = new verinum(bits, nbits, false);
|
|
||||||
yylval.number->has_sign(true);
|
|
||||||
delete[]bits;
|
|
||||||
return NUMBER; }
|
|
||||||
|
|
||||||
[0-9][0-9_]*\.[0-9][0-9_]*([Ee][+-]?[0-9][0-9_]*)? {
|
[0-9][0-9_]*\.[0-9][0-9_]*([Ee][+-]?[0-9][0-9_]*)? {
|
||||||
yylval.realtime = new verireal(yytext);
|
yylval.realtime = new verireal(yytext);
|
||||||
|
|
@ -397,96 +345,6 @@ void lex_end_table()
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static verinum*make_binary_with_size(unsigned size, bool fixed, const char*ptr)
|
|
||||||
{
|
|
||||||
bool sign_flag = false;
|
|
||||||
verinum::V*bits = new verinum::V[size];
|
|
||||||
|
|
||||||
if (tolower(ptr[0]) == 's') {
|
|
||||||
ptr += 1;
|
|
||||||
sign_flag = true;
|
|
||||||
}
|
|
||||||
assert(tolower(*ptr) == 'b');
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
unsigned idx = 0;
|
|
||||||
const char*eptr = ptr + strlen(ptr) - 1;
|
|
||||||
|
|
||||||
while ((eptr >= ptr) && (idx < size)) {
|
|
||||||
|
|
||||||
switch (*eptr) {
|
|
||||||
case '_':
|
|
||||||
break;
|
|
||||||
case '0':
|
|
||||||
bits[idx++] = verinum::V0;
|
|
||||||
break;
|
|
||||||
case '1':
|
|
||||||
bits[idx++] = verinum::V1;
|
|
||||||
break;
|
|
||||||
case 'z': case 'Z': case '?':
|
|
||||||
bits[idx++] = verinum::Vz;
|
|
||||||
break;
|
|
||||||
case 'x': case 'X':
|
|
||||||
bits[idx++] = verinum::Vx;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
eptr -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* If we filled up the expected number of bits, but there are
|
|
||||||
still characters of the number part left, then report a
|
|
||||||
warning that we are truncating. */
|
|
||||||
|
|
||||||
if ((idx >= size) && (eptr >= ptr))
|
|
||||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
|
||||||
": warning: Numeric binary constant ``" << ptr <<
|
|
||||||
"'' truncated to " << size << " bits." << endl;
|
|
||||||
|
|
||||||
|
|
||||||
// Zero-extend binary number, except that z or x is extended
|
|
||||||
// if it is the highest supplied digit.
|
|
||||||
while (idx < size) {
|
|
||||||
switch (ptr[0]) {
|
|
||||||
case '0':
|
|
||||||
case '1':
|
|
||||||
bits[idx++] = verinum::V0;
|
|
||||||
break;
|
|
||||||
case 'z': case 'Z': case '?':
|
|
||||||
bits[idx++] = verinum::Vz;
|
|
||||||
break;
|
|
||||||
case 'x': case 'X':
|
|
||||||
bits[idx++] = verinum::Vx;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
verinum*out = new verinum(bits, size, fixed);
|
|
||||||
delete[]bits;
|
|
||||||
out->has_sign(sign_flag);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static verinum*make_sized_binary(const char*txt)
|
|
||||||
{
|
|
||||||
char*ptr;
|
|
||||||
unsigned size = strtoul(txt,&ptr,10);
|
|
||||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
|
||||||
ptr += 1;
|
|
||||||
assert(*ptr == '\'');
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
return make_binary_with_size(size, true, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static verinum*make_unsized_binary(const char*txt)
|
static verinum*make_unsized_binary(const char*txt)
|
||||||
{
|
{
|
||||||
bool sign_flag = false;
|
bool sign_flag = false;
|
||||||
|
|
@ -538,95 +396,6 @@ static verinum*make_unsized_binary(const char*txt)
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static verinum*make_sized_octal(const char*txt)
|
|
||||||
{
|
|
||||||
bool sign_flag = false;
|
|
||||||
char*ptr;
|
|
||||||
|
|
||||||
unsigned size = strtoul(txt,&ptr,10);
|
|
||||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
|
||||||
ptr += 1;
|
|
||||||
assert(*ptr == '\'');
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
if (tolower(*ptr) == 's') {
|
|
||||||
sign_flag = true;
|
|
||||||
ptr += 1;
|
|
||||||
}
|
|
||||||
assert(tolower(*ptr) == 'o');
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
/* We know from the size number how bit to make the verinum
|
|
||||||
array, so make it now. */
|
|
||||||
verinum::V*bits = new verinum::V[(size+2)/3 * 3];
|
|
||||||
|
|
||||||
/* skip white space between size and the base token. */
|
|
||||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
/* Get a pointer to the last character of the number string,
|
|
||||||
then work back from there (the least significant digit)
|
|
||||||
forward until I run out of digits or space to put them. */
|
|
||||||
char*eptr = ptr + strlen(ptr) - 1;
|
|
||||||
unsigned idx = 0;
|
|
||||||
|
|
||||||
while ((eptr >= ptr) && (idx < size)) {
|
|
||||||
switch (*eptr) {
|
|
||||||
case 'x': case 'X':
|
|
||||||
bits[idx++] = verinum::Vx;
|
|
||||||
bits[idx++] = verinum::Vx;
|
|
||||||
bits[idx++] = verinum::Vx;
|
|
||||||
break;
|
|
||||||
case 'z': case 'Z': case '?':
|
|
||||||
bits[idx++] = verinum::Vz;
|
|
||||||
bits[idx++] = verinum::Vz;
|
|
||||||
bits[idx++] = verinum::Vz;
|
|
||||||
break;
|
|
||||||
case '0': case '1': case '2': case '3':
|
|
||||||
case '4': case '5': case '6': case '7':
|
|
||||||
{
|
|
||||||
unsigned val = *eptr - '0';
|
|
||||||
bits[idx++] = (val&1)? verinum::V1 : verinum::V0;
|
|
||||||
bits[idx++] = (val&2)? verinum::V1 : verinum::V0;
|
|
||||||
bits[idx++] = (val&4)? verinum::V1 : verinum::V0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case '_':
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
eptr -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we filled up all the bits and there are still characters
|
|
||||||
in the number string, then we overflowed. Report a warning
|
|
||||||
that we are truncating. */
|
|
||||||
if ((idx >= size) && (eptr >= ptr))
|
|
||||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
|
||||||
": warning: Numeric octal constant ``" << ptr <<
|
|
||||||
"'' truncated to " << size << " bits." << endl;
|
|
||||||
|
|
||||||
|
|
||||||
/* If we did not fill up all the bits from the string, then
|
|
||||||
zero-extend the number. */
|
|
||||||
while (idx < size) switch (ptr[1]) {
|
|
||||||
case 'x': case 'X':
|
|
||||||
bits[idx++] = verinum::Vx;
|
|
||||||
break;
|
|
||||||
case 'z': case 'Z': case '?':
|
|
||||||
bits[idx++] = verinum::Vz;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
bits[idx++] = verinum::V0;
|
|
||||||
}
|
|
||||||
|
|
||||||
verinum*out = new verinum(bits, size, true);
|
|
||||||
delete[]bits;
|
|
||||||
out->has_sign(sign_flag);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static verinum*make_unsized_octal(const char*txt)
|
static verinum*make_unsized_octal(const char*txt)
|
||||||
{
|
{
|
||||||
|
|
@ -687,102 +456,6 @@ static verinum*make_unsized_octal(const char*txt)
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static verinum*make_sized_hex(const char*txt)
|
|
||||||
{
|
|
||||||
bool sign_flag = false;
|
|
||||||
char*ptr;
|
|
||||||
unsigned size = strtoul(txt,&ptr,10);
|
|
||||||
|
|
||||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
assert(*ptr == '\'');
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
if (tolower(*ptr) == 's') {
|
|
||||||
sign_flag = true;
|
|
||||||
ptr += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(tolower(*ptr) == 'h');
|
|
||||||
|
|
||||||
ptr += 1;
|
|
||||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
verinum::V*bits = new verinum::V[(size+3)&~3];
|
|
||||||
|
|
||||||
unsigned idx = 0;
|
|
||||||
char*eptr = ptr + strlen(ptr) - 1;
|
|
||||||
|
|
||||||
while ((eptr >= ptr) && (idx < size)) {
|
|
||||||
switch (*eptr) {
|
|
||||||
case 'x': case 'X':
|
|
||||||
bits[idx++] = verinum::Vx;
|
|
||||||
bits[idx++] = verinum::Vx;
|
|
||||||
bits[idx++] = verinum::Vx;
|
|
||||||
bits[idx++] = verinum::Vx;
|
|
||||||
break;
|
|
||||||
case 'z': case 'Z': case '?':
|
|
||||||
bits[idx++] = verinum::Vz;
|
|
||||||
bits[idx++] = verinum::Vz;
|
|
||||||
bits[idx++] = verinum::Vz;
|
|
||||||
bits[idx++] = verinum::Vz;
|
|
||||||
break;
|
|
||||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
|
||||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
|
||||||
{
|
|
||||||
unsigned val = tolower(*eptr) - 'a' + 10;
|
|
||||||
bits[idx++] = (val&1)? verinum::V1 : verinum::V0;
|
|
||||||
bits[idx++] = (val&2)? verinum::V1 : verinum::V0;
|
|
||||||
bits[idx++] = (val&4)? verinum::V1 : verinum::V0;
|
|
||||||
bits[idx++] = (val&8)? verinum::V1 : verinum::V0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
|
||||||
{
|
|
||||||
unsigned val = *eptr - '0';
|
|
||||||
bits[idx++] = (val&1)? verinum::V1 : verinum::V0;
|
|
||||||
bits[idx++] = (val&2)? verinum::V1 : verinum::V0;
|
|
||||||
bits[idx++] = (val&4)? verinum::V1 : verinum::V0;
|
|
||||||
bits[idx++] = (val&8)? verinum::V1 : verinum::V0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case '_':
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
eptr -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we filled up the expected number of bits, but there are
|
|
||||||
still characters of the number part left, then report a
|
|
||||||
warning that we are truncating. */
|
|
||||||
if ((idx >= size) && (eptr >= ptr))
|
|
||||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
|
||||||
": warning: Numeric hex constant ``" << ptr <<
|
|
||||||
"'' truncated to " << size << " bits." << endl;
|
|
||||||
|
|
||||||
// zero extend hex numbers
|
|
||||||
while (idx < size) switch (ptr[0]) {
|
|
||||||
case 'x': case 'X':
|
|
||||||
bits[idx++] = verinum::Vx;
|
|
||||||
break;
|
|
||||||
case 'z': case 'Z': case '?':
|
|
||||||
bits[idx++] = verinum::Vz;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
bits[idx++] = verinum::V0;
|
|
||||||
}
|
|
||||||
|
|
||||||
verinum*out = new verinum(bits, size, true);
|
|
||||||
out->has_sign(sign_flag);
|
|
||||||
delete[]bits;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static verinum*make_unsized_hex(const char*txt)
|
static verinum*make_unsized_hex(const char*txt)
|
||||||
{
|
{
|
||||||
|
|
@ -905,80 +578,93 @@ static int dec_buf_div2(char *buf)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Making a decimal number is much easier then the other base numbers
|
* Making a decimal number is much easier then the other base numbers
|
||||||
* because there are no z or x values to worry about.
|
* because there are no z or x values to worry about. It is much
|
||||||
|
* harder then other base numbers because the width needed in bits is
|
||||||
|
* hard to calculate.
|
||||||
*/
|
*/
|
||||||
static verinum*make_dec_with_size(unsigned size, bool fixed, const char*ptr)
|
|
||||||
|
static verinum*make_unsized_dec(const char*ptr)
|
||||||
{
|
{
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
bool signed_flag = false;
|
bool signed_flag = false;
|
||||||
|
unsigned idx;
|
||||||
|
|
||||||
if (tolower(*ptr) == 's') {
|
if (ptr[0] == '\'') {
|
||||||
|
/* The number has decorations of the form 'sd<digits>,
|
||||||
|
possibly with space between the d and the <digits>.
|
||||||
|
Also, the 's' is optional, and markes the number as
|
||||||
|
signed. */
|
||||||
|
ptr += 1;
|
||||||
|
|
||||||
|
if (tolower(*ptr) == 's') {
|
||||||
|
signed_flag = true;
|
||||||
|
ptr += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(tolower(*ptr) == 'd');
|
||||||
|
ptr += 1;
|
||||||
|
|
||||||
|
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
||||||
|
ptr += 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* ... or an undecorated decimal number is passed
|
||||||
|
it. These numbers are treated as signed decimal. */
|
||||||
|
assert(isdigit(*ptr));
|
||||||
signed_flag = true;
|
signed_flag = true;
|
||||||
ptr += 1;
|
|
||||||
}
|
|
||||||
assert(tolower(*ptr) == 'd');
|
|
||||||
|
|
||||||
ptr += 1;
|
|
||||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
if (strlen(ptr) >= sizeof(buf)-2){
|
|
||||||
fprintf(stderr, "Ridicilously long decimal constant will be truncated!\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(buf, ptr, sizeof(buf)-2);
|
|
||||||
buf[sizeof(buf)-1] = 0;
|
|
||||||
|
|
||||||
/* Convert the decimal number to a binary value, one digit at
|
/* Copy the digits into a buffer that I can use to do in-place
|
||||||
a time. Watch out for overflow. */
|
decimal divides. */
|
||||||
verinum::V*bits = new verinum::V[size];
|
idx = 0;
|
||||||
unsigned idx=0;
|
while ((idx < sizeof buf) && (*ptr != 0)) {
|
||||||
|
if (*ptr == '_') {
|
||||||
|
ptr += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
while(idx<size){
|
buf[idx++] = *ptr++;
|
||||||
int rem = dec_buf_div2(buf);
|
|
||||||
|
|
||||||
bits[idx] = (rem==1) ? verinum::V1 : verinum::V0;
|
|
||||||
++idx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(; idx<size; ++idx){
|
if (idx == sizeof buf) {
|
||||||
bits[idx] = verinum::V0;
|
fprintf(stderr, "Ridiculously long"
|
||||||
}
|
" decimal constant will be truncated!\n");
|
||||||
|
idx -= 1;
|
||||||
/* If we run out of bits to hold the value, but there are
|
|
||||||
still valueable bits in the number, print a warning. */
|
|
||||||
if (strcmp(buf, "0") != 0){
|
|
||||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
|
||||||
": warning: Numeric decimal constant ``" << ptr <<
|
|
||||||
"'' truncated to " << size << " bits." << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
verinum*out = new verinum(bits, size, fixed);
|
buf[idx] = 0;
|
||||||
out->has_sign(signed_flag);
|
unsigned tmp_size = idx * 4 + 1;
|
||||||
|
verinum::V *bits = new verinum::V[tmp_size];
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
while (idx < tmp_size) {
|
||||||
|
int rem = dec_buf_div2(buf);
|
||||||
|
bits[idx++] = (rem == 1) ? verinum::V1 : verinum::V0;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(strcmp(buf, "0") == 0);
|
||||||
|
|
||||||
|
/* Now calculate the minimum number of bits needed to
|
||||||
|
represent this unsigned number. */
|
||||||
|
unsigned size = tmp_size;
|
||||||
|
while ((size > 1) && (bits[size-1] == verinum::V0))
|
||||||
|
size -= 1;
|
||||||
|
|
||||||
|
/* Now account for the signedness. Don't leave a 1 in the high
|
||||||
|
bit if this is a signed number. */
|
||||||
|
if (signed_flag && (bits[size-1] == verinum::V1)) {
|
||||||
|
size += 1;
|
||||||
|
assert(size <= tmp_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
verinum*res = new verinum(bits, size, false);
|
||||||
|
res->has_sign(signed_flag);
|
||||||
|
|
||||||
delete[]bits;
|
delete[]bits;
|
||||||
return out;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static verinum*make_sized_dec(const char*txt)
|
|
||||||
{
|
|
||||||
char*ptr;
|
|
||||||
unsigned size = strtoul(txt,&ptr,10);
|
|
||||||
|
|
||||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
assert(*ptr == '\'');
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
return make_dec_with_size(size, true, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static verinum*make_unsized_dec(const char*txt)
|
|
||||||
{
|
|
||||||
verinum*tmp = make_dec_with_size(INTEGER_WIDTH, false, txt+1);
|
|
||||||
tmp->has_sign(true);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The timescale parameter has the form:
|
* The timescale parameter has the form:
|
||||||
|
|
|
||||||
21
parse.y
21
parse.y
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if HAVE_CVS_IDENT
|
#if HAVE_CVS_IDENT
|
||||||
#ident "$Id: parse.y,v 1.174 2003/03/18 01:36:14 steve Exp $"
|
#ident "$Id: parse.y,v 1.175 2003/04/14 03:37:47 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
@ -117,7 +117,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
||||||
|
|
||||||
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING
|
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING
|
||||||
%token <text> PATHPULSE_IDENTIFIER
|
%token <text> PATHPULSE_IDENTIFIER
|
||||||
%token <number> NUMBER
|
%token <number> BASED_NUMBER DEC_NUMBER
|
||||||
%token <realtime> REALTIME
|
%token <realtime> REALTIME
|
||||||
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LS K_RS K_SG
|
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LS K_RS K_SG
|
||||||
%token K_PO_POS K_PO_NEG
|
%token K_PO_POS K_PO_NEG
|
||||||
|
|
@ -145,6 +145,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
||||||
|
|
||||||
%token KK_attribute
|
%token KK_attribute
|
||||||
|
|
||||||
|
%type <number> number
|
||||||
%type <flag> signed_opt
|
%type <flag> signed_opt
|
||||||
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||||
%type <letter> udp_input_sym udp_output_sym
|
%type <letter> udp_input_sym udp_output_sym
|
||||||
|
|
@ -232,6 +233,14 @@ source_file
|
||||||
| source_file description
|
| source_file description
|
||||||
;
|
;
|
||||||
|
|
||||||
|
number : BASED_NUMBER
|
||||||
|
{ $$ = $1; }
|
||||||
|
| DEC_NUMBER
|
||||||
|
{ $$ = $1; }
|
||||||
|
| DEC_NUMBER BASED_NUMBER
|
||||||
|
{ $$ = pform_verinum_with_size($1,$2, @2.text, @2.first_line); }
|
||||||
|
;
|
||||||
|
|
||||||
/* Verilog-2001 supports attribute lists, which can be attached to a
|
/* Verilog-2001 supports attribute lists, which can be attached to a
|
||||||
variety of different objects. The syntax inside the (* *) is a
|
variety of different objects. The syntax inside the (* *) is a
|
||||||
comma separated list of names or names with assigned values. */
|
comma separated list of names or names with assigned values. */
|
||||||
|
|
@ -478,7 +487,7 @@ delay_value
|
||||||
|
|
||||||
|
|
||||||
delay_value_simple
|
delay_value_simple
|
||||||
: NUMBER
|
: DEC_NUMBER
|
||||||
{ verinum*tmp = $1;
|
{ verinum*tmp = $1;
|
||||||
if (tmp == 0) {
|
if (tmp == 0) {
|
||||||
yyerror(@1, "internal error: delay.");
|
yyerror(@1, "internal error: delay.");
|
||||||
|
|
@ -879,7 +888,7 @@ expression_list
|
||||||
|
|
||||||
|
|
||||||
expr_primary
|
expr_primary
|
||||||
: NUMBER
|
: number
|
||||||
{ assert($1);
|
{ assert($1);
|
||||||
PENumber*tmp = new PENumber($1);
|
PENumber*tmp = new PENumber($1);
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
|
|
@ -1762,7 +1771,7 @@ parameter_value_opt
|
||||||
tmp->by_name = $3;
|
tmp->by_name = $3;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| '#' NUMBER
|
| '#' DEC_NUMBER
|
||||||
{ assert($2);
|
{ assert($2);
|
||||||
PENumber*tmp = new PENumber($2);
|
PENumber*tmp = new PENumber($2);
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
|
|
@ -2763,7 +2772,7 @@ udp_sequ_entry
|
||||||
;
|
;
|
||||||
|
|
||||||
udp_initial
|
udp_initial
|
||||||
: K_initial IDENTIFIER '=' NUMBER ';'
|
: K_initial IDENTIFIER '=' number ';'
|
||||||
{ PExpr*etmp = new PENumber($4);
|
{ PExpr*etmp = new PENumber($4);
|
||||||
PEIdent*itmp = new PEIdent(hname_t($2));
|
PEIdent*itmp = new PEIdent(hname_t($2));
|
||||||
PAssign*atmp = new PAssign(itmp, etmp);
|
PAssign*atmp = new PAssign(itmp, etmp);
|
||||||
|
|
|
||||||
56
pform.cc
56
pform.cc
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
#ifdef HAVE_CVS_IDENT
|
||||||
#ident "$Id: pform.cc,v 1.111 2003/03/06 04:37:12 steve Exp $"
|
#ident "$Id: pform.cc,v 1.112 2003/04/14 03:39:15 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
@ -133,6 +133,56 @@ void pform_set_timescale(int unit, int prec,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
||||||
|
const char*file, unsigned lineno)
|
||||||
|
{
|
||||||
|
assert(siz->is_defined());
|
||||||
|
unsigned long size = siz->as_ulong();
|
||||||
|
|
||||||
|
verinum::V pad;
|
||||||
|
|
||||||
|
switch (val->get(val->len()-1)) {
|
||||||
|
case verinum::Vz:
|
||||||
|
pad = verinum::Vz;
|
||||||
|
break;
|
||||||
|
case verinum::Vx:
|
||||||
|
pad = verinum::Vx;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pad = verinum::V0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
verinum*res = new verinum(pad, size);
|
||||||
|
|
||||||
|
unsigned copy = val->len();
|
||||||
|
if (res->len() < copy)
|
||||||
|
copy = res->len();
|
||||||
|
|
||||||
|
for (unsigned idx = 0 ; idx < copy ; idx += 1) {
|
||||||
|
res->set(idx, val->get(idx));
|
||||||
|
}
|
||||||
|
|
||||||
|
res->has_sign(val->has_sign());
|
||||||
|
|
||||||
|
bool trunc_flag = false;
|
||||||
|
for (unsigned idx = copy ; idx < val->len() ; idx += 1) {
|
||||||
|
if (val->get(idx) != pad) {
|
||||||
|
trunc_flag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trunc_flag) {
|
||||||
|
cerr << file << ":" << lineno << ": warning: Numeric constant "
|
||||||
|
<< "truncated to " << copy << " bits." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete siz;
|
||||||
|
delete val;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function evaluates delay expressions. The result should be a
|
* This function evaluates delay expressions. The result should be a
|
||||||
* simple constant that I can interpret as an unsigned number.
|
* simple constant that I can interpret as an unsigned number.
|
||||||
|
|
@ -1414,6 +1464,10 @@ int pform_parse(const char*path, FILE*file)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: pform.cc,v $
|
* $Log: pform.cc,v $
|
||||||
|
* Revision 1.112 2003/04/14 03:39:15 steve
|
||||||
|
* Break sized constants into a size token
|
||||||
|
* and a based numeric constant.
|
||||||
|
*
|
||||||
* Revision 1.111 2003/03/06 04:37:12 steve
|
* Revision 1.111 2003/03/06 04:37:12 steve
|
||||||
* lex_strings.add module names earlier.
|
* lex_strings.add module names earlier.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
10
pform.h
10
pform.h
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
#ifdef HAVE_CVS_IDENT
|
||||||
#ident "$Id: pform.h,v 1.68 2003/02/27 06:45:11 steve Exp $"
|
#ident "$Id: pform.h,v 1.69 2003/04/14 03:39:15 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
|
|
@ -148,6 +148,10 @@ extern void pform_make_udp(const char*name, list<string>*parms,
|
||||||
extern void pform_push_scope(char*name);
|
extern void pform_push_scope(char*name);
|
||||||
extern void pform_pop_scope();
|
extern void pform_pop_scope();
|
||||||
|
|
||||||
|
|
||||||
|
extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
|
||||||
|
const char*file, unsigned loneno);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The makewire functions announce to the pform code new wires. These
|
* The makewire functions announce to the pform code new wires. These
|
||||||
* go into a module that is currently opened.
|
* go into a module that is currently opened.
|
||||||
|
|
@ -275,6 +279,10 @@ extern void pform_dump(ostream&out, Module*mod);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: pform.h,v $
|
* $Log: pform.h,v $
|
||||||
|
* Revision 1.69 2003/04/14 03:39:15 steve
|
||||||
|
* Break sized constants into a size token
|
||||||
|
* and a based numeric constant.
|
||||||
|
*
|
||||||
* Revision 1.68 2003/02/27 06:45:11 steve
|
* Revision 1.68 2003/02/27 06:45:11 steve
|
||||||
* specparams as far as pform.
|
* specparams as far as pform.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue