Added width cap for unsized expressions.
Unsized expressions can expand to extremely large widths. Usually this is actually a mistake in the source code, but it can lead to the compiler temporarily using extremely large amounts of memory, or in the worst case, crashing. This adds a cap on the width of unsized expressions (by default 65536 bits, but overridable by the user), and causes a warning message to be output when the cap is reached.
This commit is contained in:
parent
1f81d4c081
commit
5dcd2e8957
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __compiler_H
|
#ifndef __compiler_H
|
||||||
#define __compiler_H
|
#define __compiler_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2013 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -36,6 +36,11 @@
|
||||||
*/
|
*/
|
||||||
extern unsigned integer_width;
|
extern unsigned integer_width;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The width_cap is the width limit for unsized expressions.
|
||||||
|
*/
|
||||||
|
extern unsigned width_cap;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the maximum number of recursive module loops allowed within
|
* This is the maximum number of recursive module loops allowed within
|
||||||
* a generate block.
|
* a generate block.
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
%{
|
%{
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -92,6 +92,8 @@ int cmdfile_stack_ptr = 0;
|
||||||
|
|
||||||
"+vhdl-libdir+" { BEGIN(PLUS_ARGS); return TOK_VHDL_LIBDIR; }
|
"+vhdl-libdir+" { BEGIN(PLUS_ARGS); return TOK_VHDL_LIBDIR; }
|
||||||
|
|
||||||
|
"+width-cap+" { BEGIN(PLUS_ARGS); return TOK_WIDTH_CAP; }
|
||||||
|
|
||||||
/* If it is not any known plus-flag, return the generic form. */
|
/* If it is not any known plus-flag, return the generic form. */
|
||||||
"+"[^\n \t\b\f\r+]* {
|
"+"[^\n \t\b\f\r+]* {
|
||||||
cflval.text = strdup(yytext);
|
cflval.text = strdup(yytext);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
%{
|
%{
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -61,6 +61,7 @@ static void translate_file_name(char*text)
|
||||||
%token TOK_Da TOK_Dc TOK_Dv TOK_Dy
|
%token TOK_Da TOK_Dc TOK_Dv TOK_Dy
|
||||||
%token TOK_DEFINE TOK_INCDIR TOK_INTEGER_WIDTH TOK_LIBDIR TOK_LIBDIR_NOCASE
|
%token TOK_DEFINE TOK_INCDIR TOK_INTEGER_WIDTH TOK_LIBDIR TOK_LIBDIR_NOCASE
|
||||||
%token TOK_LIBEXT TOK_PARAMETER TOK_TIMESCALE TOK_VHDL_WORK TOK_VHDL_LIBDIR
|
%token TOK_LIBEXT TOK_PARAMETER TOK_TIMESCALE TOK_VHDL_WORK TOK_VHDL_LIBDIR
|
||||||
|
%token TOK_WIDTH_CAP
|
||||||
%token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING
|
%token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
@ -191,6 +192,13 @@ item
|
||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| TOK_WIDTH_CAP TOK_PLUSARG
|
||||||
|
{ char*tmp = substitutions($2);
|
||||||
|
free($2);
|
||||||
|
width_cap = strtoul(tmp,0,10);
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
/* The +<word> tokens that are not otherwise matched, are
|
/* The +<word> tokens that are not otherwise matched, are
|
||||||
ignored. The skip_args rule arranges for all the argument words
|
ignored. The skip_args rule arranges for all the argument words
|
||||||
to be consumed. */
|
to be consumed. */
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __globals_H
|
#ifndef __globals_H
|
||||||
#define __globals_H
|
#define __globals_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -24,6 +24,9 @@
|
||||||
/* This is the integer-width argument that will be passed to ivl. */
|
/* This is the integer-width argument that will be passed to ivl. */
|
||||||
extern unsigned integer_width;
|
extern unsigned integer_width;
|
||||||
|
|
||||||
|
/* This is the width-cap argument that will be passed to ivl. */
|
||||||
|
extern unsigned width_cap;
|
||||||
|
|
||||||
extern const char*vhdlpp_work;
|
extern const char*vhdlpp_work;
|
||||||
extern const char**vhdlpp_libdir;
|
extern const char**vhdlpp_libdir;
|
||||||
extern unsigned vhdlpp_libdir_cnt;
|
extern unsigned vhdlpp_libdir_cnt;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
.TH iverilog 1 "April 2nd, 2013" "" "Version %M.%m.%n %E"
|
.TH iverilog 1 "February 26th, 2014" "" "Version %M.%m.%n %E"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
iverilog - Icarus Verilog compiler
|
iverilog - Icarus Verilog compiler
|
||||||
|
|
||||||
|
|
@ -462,6 +462,12 @@ This allows the programmer to select the width for integer variables
|
||||||
in the Verilog source. The default is 32, the value can be any desired
|
in the Verilog source. The default is 32, the value can be any desired
|
||||||
integer value.
|
integer value.
|
||||||
|
|
||||||
|
.TP 8
|
||||||
|
.B +width-cap+\fIvalue\fP
|
||||||
|
This allows the programmer to select the width cap for unsized expressions.
|
||||||
|
If the calculated width for an unsized expression exceeds this value, the
|
||||||
|
compiler will issue a warning and limit the expression width to this value.
|
||||||
|
|
||||||
.SH "VARIABLES IN COMMAND FILES"
|
.SH "VARIABLES IN COMMAND FILES"
|
||||||
|
|
||||||
In certain cases, iverilog supports variables in command files. These
|
In certain cases, iverilog supports variables in command files. These
|
||||||
|
|
@ -515,7 +521,7 @@ Tips on using, debugging, and developing the compiler can be found at
|
||||||
|
|
||||||
.SH COPYRIGHT
|
.SH COPYRIGHT
|
||||||
.nf
|
.nf
|
||||||
Copyright \(co 2002\-2011 Stephen Williams
|
Copyright \(co 2002\-2014 Stephen Williams
|
||||||
|
|
||||||
This document can be freely redistributed according to the terms of the
|
This document can be freely redistributed according to the terms of the
|
||||||
GNU General Public License version 2.0
|
GNU General Public License version 2.0
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -141,6 +141,8 @@ char warning_flags[16] = "n";
|
||||||
|
|
||||||
unsigned integer_width = 32;
|
unsigned integer_width = 32;
|
||||||
|
|
||||||
|
unsigned width_cap = 65536;
|
||||||
|
|
||||||
char*mod_list = 0;
|
char*mod_list = 0;
|
||||||
char*command_filename = 0;
|
char*command_filename = 0;
|
||||||
|
|
||||||
|
|
@ -1192,6 +1194,8 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
fprintf(iconfig_file, "iwidth:%u\n", integer_width);
|
fprintf(iconfig_file, "iwidth:%u\n", integer_width);
|
||||||
|
|
||||||
|
fprintf(iconfig_file, "widthcap:%u\n", width_cap);
|
||||||
|
|
||||||
/* Write the preprocessor command needed to preprocess a
|
/* Write the preprocessor command needed to preprocess a
|
||||||
single file. This may be used to preprocess library
|
single file. This may be used to preprocess library
|
||||||
files. */
|
files. */
|
||||||
|
|
|
||||||
|
|
@ -756,12 +756,11 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||||
r_val = rc->value().as_long();
|
r_val = rc->value().as_long();
|
||||||
|
|
||||||
// Clip to a sensible range to avoid underflow/overflow
|
// Clip to a sensible range to avoid underflow/overflow
|
||||||
// in the following calculations. 1024 bits should be
|
// in the following calculations.
|
||||||
// enough for anyone...
|
|
||||||
if (r_val < 0)
|
if (r_val < 0)
|
||||||
r_val = 0;
|
r_val = 0;
|
||||||
if (r_val > 1024)
|
if (r_val > width_cap)
|
||||||
r_val = 1024;
|
r_val = width_cap;
|
||||||
|
|
||||||
// If the left operand is a simple unsized number, we
|
// If the left operand is a simple unsized number, we
|
||||||
// can calculate the actual width required for the power
|
// can calculate the actual width required for the power
|
||||||
|
|
|
||||||
10
main.cc
10
main.cc
|
|
@ -1,5 +1,5 @@
|
||||||
const char COPYRIGHT[] =
|
const char COPYRIGHT[] =
|
||||||
"Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)";
|
"Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -191,6 +191,11 @@ bool verbose_flag = false;
|
||||||
|
|
||||||
unsigned integer_width = 32;
|
unsigned integer_width = 32;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Width limit for unsized expressions.
|
||||||
|
*/
|
||||||
|
unsigned width_cap = 65536;
|
||||||
|
|
||||||
int def_ts_units = 0;
|
int def_ts_units = 0;
|
||||||
int def_ts_prec = 0;
|
int def_ts_prec = 0;
|
||||||
|
|
||||||
|
|
@ -647,6 +652,9 @@ static void read_iconfig_file(const char*ipath)
|
||||||
} else if (strcmp(buf, "iwidth") == 0) {
|
} else if (strcmp(buf, "iwidth") == 0) {
|
||||||
integer_width = strtoul(cp,0,10);
|
integer_width = strtoul(cp,0,10);
|
||||||
|
|
||||||
|
} else if (strcmp(buf, "widthcap") == 0) {
|
||||||
|
width_cap = strtoul(cp,0,10);
|
||||||
|
|
||||||
} else if (strcmp(buf, "library_file") == 0) {
|
} else if (strcmp(buf, "library_file") == 0) {
|
||||||
perm_string path = filename_strings.make(cp);
|
perm_string path = filename_strings.make(cp);
|
||||||
library_file_map[path] = true;
|
library_file_map[path] = true;
|
||||||
|
|
|
||||||
23
netmisc.cc
23
netmisc.cc
|
|
@ -746,9 +746,9 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||||
|
|
||||||
// If context_width is positive, this is the RHS of an assignment,
|
// If context_width is positive, this is the RHS of an assignment,
|
||||||
// so the LHS width must also be included in the width calculation.
|
// so the LHS width must also be included in the width calculation.
|
||||||
if ((context_width > 0) && (pe->expr_type() != IVL_VT_REAL)
|
unsigned pos_context_width = context_width > 0 ? context_width : 0;
|
||||||
&& (expr_width < (unsigned)context_width))
|
if ((pe->expr_type() != IVL_VT_REAL) && (expr_width < pos_context_width))
|
||||||
expr_width = context_width;
|
expr_width = pos_context_width;
|
||||||
|
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << pe->get_fileline() << ": elab_and_eval: test_width of "
|
cerr << pe->get_fileline() << ": elab_and_eval: test_width of "
|
||||||
|
|
@ -765,8 +765,8 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||||
// If we can get the same result using a smaller expression
|
// If we can get the same result using a smaller expression
|
||||||
// width, do so.
|
// width, do so.
|
||||||
if ((context_width > 0) && (pe->expr_type() != IVL_VT_REAL)
|
if ((context_width > 0) && (pe->expr_type() != IVL_VT_REAL)
|
||||||
&& (expr_width > (unsigned)context_width)) {
|
&& (expr_width > pos_context_width)) {
|
||||||
expr_width = max(pe->min_width(), (unsigned)context_width);
|
expr_width = max(pe->min_width(), pos_context_width);
|
||||||
|
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << pe->get_fileline() << ": "
|
cerr << pe->get_fileline() << ": "
|
||||||
|
|
@ -774,6 +774,15 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((mode >= PExpr::LOSSLESS) && (expr_width > width_cap)
|
||||||
|
&& (expr_width > pos_context_width)) {
|
||||||
|
cerr << pe->get_fileline() << ": warning: excessive unsized "
|
||||||
|
<< "expression width detected." << endl;
|
||||||
|
cerr << pe->get_fileline() << ": : The expression width "
|
||||||
|
<< "is capped at " << width_cap << " bits." << endl;
|
||||||
|
expr_width = width_cap;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned flags = PExpr::NO_FLAGS;
|
unsigned flags = PExpr::NO_FLAGS;
|
||||||
if (need_const)
|
if (need_const)
|
||||||
flags |= PExpr::NEED_CONST;
|
flags |= PExpr::NEED_CONST;
|
||||||
|
|
@ -789,10 +798,10 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||||
tmp = cast_to_real(tmp);
|
tmp = cast_to_real(tmp);
|
||||||
break;
|
break;
|
||||||
case IVL_VT_BOOL:
|
case IVL_VT_BOOL:
|
||||||
tmp = cast_to_int2(tmp, context_width > 0 ? context_width : 0);
|
tmp = cast_to_int2(tmp, pos_context_width);
|
||||||
break;
|
break;
|
||||||
case IVL_VT_LOGIC:
|
case IVL_VT_LOGIC:
|
||||||
tmp = cast_to_int4(tmp, context_width > 0 ? context_width : 0);
|
tmp = cast_to_int4(tmp, pos_context_width);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue