Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
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.
Loading branch information
@@ -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+\fI value \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
@@ -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 ;
@@ -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,15 +765,24 @@ 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 () << " : "
<< " pruned to width=" << expr_width << endl;
}
}
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 ;
Toggle all file notes