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
|
||||
#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
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -36,6 +36,11 @@
|
|||
*/
|
||||
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
|
||||
* 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
|
||||
* 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; }
|
||||
|
||||
"+width-cap+" { BEGIN(PLUS_ARGS); return TOK_WIDTH_CAP; }
|
||||
|
||||
/* If it is not any known plus-flag, return the generic form. */
|
||||
"+"[^\n \t\b\f\r+]* {
|
||||
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
|
||||
* 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_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_WIDTH_CAP
|
||||
%token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING
|
||||
|
||||
%%
|
||||
|
|
@ -191,6 +192,13 @@ item
|
|||
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
|
||||
ignored. The skip_args rule arranges for all the argument words
|
||||
to be consumed. */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __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
|
||||
* 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. */
|
||||
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_libdir;
|
||||
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
|
||||
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
|
||||
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"
|
||||
|
||||
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
|
||||
.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
|
||||
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
|
||||
* 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 width_cap = 65536;
|
||||
|
||||
char*mod_list = 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, "widthcap:%u\n", width_cap);
|
||||
|
||||
/* Write the preprocessor command needed to preprocess a
|
||||
single file. This may be used to preprocess library
|
||||
files. */
|
||||
|
|
|
|||
|
|
@ -756,12 +756,11 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
r_val = rc->value().as_long();
|
||||
|
||||
// Clip to a sensible range to avoid underflow/overflow
|
||||
// in the following calculations. 1024 bits should be
|
||||
// enough for anyone...
|
||||
// in the following calculations.
|
||||
if (r_val < 0)
|
||||
r_val = 0;
|
||||
if (r_val > 1024)
|
||||
r_val = 1024;
|
||||
if (r_val > width_cap)
|
||||
r_val = width_cap;
|
||||
|
||||
// If the left operand is a simple unsized number, we
|
||||
// can calculate the actual width required for the power
|
||||
|
|
|
|||
10
main.cc
10
main.cc
|
|
@ -1,5 +1,5 @@
|
|||
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
|
||||
|
|
@ -191,6 +191,11 @@ bool verbose_flag = false;
|
|||
|
||||
unsigned integer_width = 32;
|
||||
|
||||
/*
|
||||
* Width limit for unsized expressions.
|
||||
*/
|
||||
unsigned width_cap = 65536;
|
||||
|
||||
int def_ts_units = 0;
|
||||
int def_ts_prec = 0;
|
||||
|
||||
|
|
@ -647,6 +652,9 @@ static void read_iconfig_file(const char*ipath)
|
|||
} else if (strcmp(buf, "iwidth") == 0) {
|
||||
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) {
|
||||
perm_string path = filename_strings.make(cp);
|
||||
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,
|
||||
// so the LHS width must also be included in the width calculation.
|
||||
if ((context_width > 0) && (pe->expr_type() != IVL_VT_REAL)
|
||||
&& (expr_width < (unsigned)context_width))
|
||||
expr_width = context_width;
|
||||
unsigned pos_context_width = context_width > 0 ? context_width : 0;
|
||||
if ((pe->expr_type() != IVL_VT_REAL) && (expr_width < pos_context_width))
|
||||
expr_width = pos_context_width;
|
||||
|
||||
if (debug_elaborate) {
|
||||
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
|
||||
// width, do so.
|
||||
if ((context_width > 0) && (pe->expr_type() != IVL_VT_REAL)
|
||||
&& (expr_width > (unsigned)context_width)) {
|
||||
expr_width = max(pe->min_width(), (unsigned)context_width);
|
||||
&& (expr_width > pos_context_width)) {
|
||||
expr_width = max(pe->min_width(), pos_context_width);
|
||||
|
||||
if (debug_elaborate) {
|
||||
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;
|
||||
if (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);
|
||||
break;
|
||||
case IVL_VT_BOOL:
|
||||
tmp = cast_to_int2(tmp, context_width > 0 ? context_width : 0);
|
||||
tmp = cast_to_int2(tmp, pos_context_width);
|
||||
break;
|
||||
case IVL_VT_LOGIC:
|
||||
tmp = cast_to_int4(tmp, context_width > 0 ? context_width : 0);
|
||||
tmp = cast_to_int4(tmp, pos_context_width);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue