Merge 70f61664c1 into c7530dbcc1
This commit is contained in:
commit
3d8d5cf800
|
|
@ -342,9 +342,9 @@ These flags affect the general behavior of the compiler.
|
|||
|
||||
* select-range
|
||||
|
||||
This enables warnings for constant out-of-bound selects. This includes
|
||||
partial or fully out-of-bound select as well as a select containing a 'bx
|
||||
or 'bz in the index.
|
||||
This enables warnings for constant and runtime out-of-bound selects. This
|
||||
includes partial or fully out-of-bound select as well as a select containing
|
||||
a 'bx or 'bz in the index.
|
||||
|
||||
* timescale
|
||||
|
||||
|
|
|
|||
|
|
@ -421,8 +421,8 @@ will generate a warning.
|
|||
|
||||
.TP 8
|
||||
.B select-range
|
||||
This enables warnings for constant out of bound selects. This includes
|
||||
partial or fully out of bound selects as well as a select containing
|
||||
This enables warnings for constant and runtime out-of-bound selects. This
|
||||
includes partial or fully out-of-bound select as well as a select containing
|
||||
a 'bx or 'bz in the index.
|
||||
|
||||
.TP 8
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
PASSED
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
ivltests/unpacked_array_oob_write_warn.v:21: Warning: out-of-bounds unpacked array write index 4 for 'a[0:3]'; write ignored.
|
||||
ivltests/unpacked_array_oob_write_warn.v:24: Warning: out-of-bounds unpacked array write index -1 for 'a[0:3]'; write ignored.
|
||||
ivltests/unpacked_array_oob_write_warn.v:27: Warning: out-of-bounds unpacked array write index 5 for 'a[0:3]'; write ignored.
|
||||
ivltests/unpacked_array_oob_write_warn.v:30: Warning: out-of-bounds unpacked array write index 3 for 'r[0:1]'; write ignored.
|
||||
ivltests/unpacked_array_oob_write_warn.v:33: Warning: undefined unpacked array write index for 'a[0:3]'; write ignored.
|
||||
ivltests/unpacked_array_oob_write_warn.v:36: Warning: undefined unpacked array write index for 'a[0:3]'; write ignored.
|
||||
ivltests/unpacked_array_oob_write_warn.v:39: Warning: undefined unpacked array write index for 'r[0:1]'; write ignored.
|
||||
|
|
@ -0,0 +1 @@
|
|||
PASSED
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
module main;
|
||||
logic [7:0] a [0:3];
|
||||
real r [0:1];
|
||||
integer idx;
|
||||
integer errors;
|
||||
|
||||
initial begin
|
||||
errors = 0;
|
||||
|
||||
a[0] = 8'h11;
|
||||
a[1] = 8'h22;
|
||||
a[2] = 8'h33;
|
||||
a[3] = 8'h44;
|
||||
r[0] = 1.25;
|
||||
r[1] = 2.50;
|
||||
|
||||
idx = 2;
|
||||
a[idx] = 8'haa;
|
||||
|
||||
idx = 4;
|
||||
a[idx] = 8'hff;
|
||||
|
||||
idx = -1;
|
||||
a[idx] <= 8'hee;
|
||||
|
||||
idx = 5;
|
||||
repeat (2) a[idx] = 8'h77;
|
||||
|
||||
idx = 3;
|
||||
r[idx] <= 9.50;
|
||||
|
||||
idx = 'bx;
|
||||
a[idx] = 8'h66;
|
||||
|
||||
idx = 'bz;
|
||||
a[idx] <= 8'h55;
|
||||
|
||||
idx = 'bx;
|
||||
r[idx] = 7.25;
|
||||
|
||||
#1;
|
||||
|
||||
if (a[0] !== 8'h11) errors = errors + 1;
|
||||
if (a[1] !== 8'h22) errors = errors + 1;
|
||||
if (a[2] !== 8'haa) errors = errors + 1;
|
||||
if (a[3] !== 8'h44) errors = errors + 1;
|
||||
if (r[0] != 1.25) errors = errors + 1;
|
||||
if (r[1] != 2.50) errors = errors + 1;
|
||||
|
||||
if (errors) begin
|
||||
$display("FAILED");
|
||||
$finish(1);
|
||||
end
|
||||
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -380,6 +380,8 @@ test_va_math vvp_tests/test_va_math.json
|
|||
test_vams_math vvp_tests/test_vams_math.json
|
||||
timing_check_syntax vvp_tests/timing_check_syntax.json
|
||||
timing_check_delayed_signals vvp_tests/timing_check_delayed_signals.json
|
||||
unpacked_array_oob_write_nowarn vvp_tests/unpacked_array_oob_write_nowarn.json
|
||||
unpacked_array_oob_write_warn vvp_tests/unpacked_array_oob_write_warn.json
|
||||
uwire_fail2 vvp_tests/uwire_fail2.json
|
||||
uwire_fail3 vvp_tests/uwire_fail3.json
|
||||
value_range1 vvp_tests/value_range1.json
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "unpacked_array_oob_write_warn.v",
|
||||
"iverilog-args" : [ "-g2005-sv", "-pfileline=1" ],
|
||||
"gold" : "unpacked_array_oob_write_nowarn"
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "unpacked_array_oob_write_warn.v",
|
||||
"iverilog-args" : [ "-g2005-sv", "-Wselect-range", "-pfileline=1" ],
|
||||
"gold" : "unpacked_array_oob_write_warn"
|
||||
}
|
||||
2
main.cc
2
main.cc
|
|
@ -749,6 +749,8 @@ static void read_iconfig_file(const char*ipath)
|
|||
roots.push_back(lex_strings.make(cp));
|
||||
|
||||
} else if (strcmp(buf,"warnings") == 0) {
|
||||
free(reinterpret_cast<void*>(const_cast<char*>(flags["warnings"])));
|
||||
flags["warnings"] = strdup(cp);
|
||||
/* Scan the warnings enable string for warning flags. */
|
||||
for ( ; *cp ; cp += 1) switch (*cp) {
|
||||
case 'f':
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ int target_design(ivl_design_t des)
|
|||
* printed for procedural statements. (e.g. -pfileline=1).
|
||||
* The default is no file/line information will be included. */
|
||||
const char*fileline = ivl_design_flag(des, "fileline");
|
||||
const char*warnings = ivl_design_flag(des, "warnings");
|
||||
|
||||
const char*debug_flags = ivl_design_flag(des, "debug_flags");
|
||||
process_debug_string(debug_flags);
|
||||
|
|
@ -210,6 +211,8 @@ int target_design(ivl_design_t des)
|
|||
|
||||
fprintf(vvp_out, ":ivl_delay_selection \"%s\";\n",
|
||||
ivl_design_delay_sel(des));
|
||||
if (warnings && *warnings)
|
||||
fprintf(vvp_out, ":ivl_warnings \"%s\";\n", warnings);
|
||||
|
||||
{ int pre = ivl_design_time_precision(des);
|
||||
char sign = '+';
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ static void assign_to_array_r_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
|||
uint64_t delay,
|
||||
ivl_expr_t dexp, unsigned nevents)
|
||||
{
|
||||
unsigned end_assign = transient_id++;
|
||||
int word_ix_reg = 3;
|
||||
|
||||
/* if we have to evaluate a delay expression, evaluate word index into
|
||||
|
|
@ -54,24 +53,23 @@ static void assign_to_array_r_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
|||
!number_is_unknown(word_ix)) {
|
||||
fprintf(vvp_out, " %%ix/load %d, %ld, 0; address\n",
|
||||
word_ix_reg, get_number_immediate(word_ix));
|
||||
fprintf(vvp_out, " %%flag_set/imm 4, 0;\n");
|
||||
} else {
|
||||
/* Calculate array word index into index register 3 */
|
||||
draw_eval_expr_into_integer(word_ix, word_ix_reg);
|
||||
/* Skip assignment if word expression is not defined. */
|
||||
unsigned do_assign = transient_id++;
|
||||
fprintf(vvp_out, " %%jmp/0 t_%u, 4;\n", do_assign);
|
||||
fprintf(vvp_out, " %%pop/real 1;\n");
|
||||
fprintf(vvp_out, " %%jmp t_%u;\n", end_assign);
|
||||
fprintf(vvp_out, "t_%u ;\n", do_assign);
|
||||
}
|
||||
|
||||
if (dexp != 0) {
|
||||
/* Calculated delay... */
|
||||
int delay_index = allocate_word();
|
||||
int index_flag = allocate_flag();
|
||||
fprintf(vvp_out, " %%flag_mov %d, 4;\n", index_flag);
|
||||
draw_eval_expr_into_integer(dexp, delay_index);
|
||||
fprintf(vvp_out, " %%ix/mov 3, %d;\n", word_ix_reg);
|
||||
fprintf(vvp_out, " %%flag_mov 4, %d;\n", index_flag);
|
||||
fprintf(vvp_out, " %%assign/ar/d v%p, %d;\n", lsig,
|
||||
delay_index);
|
||||
clr_flag(index_flag);
|
||||
clr_word(word_ix_reg);
|
||||
clr_word(delay_index);
|
||||
} else if (nevents != 0) {
|
||||
|
|
@ -99,7 +97,6 @@ static void assign_to_array_r_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
|||
}
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "t_%u ;\n", end_assign);
|
||||
if (nevents != 0) fprintf(vvp_out, " %%evctl/c;\n");
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ extern void compile_init(void);
|
|||
extern void compile_cleanup(void);
|
||||
|
||||
extern bool verbose_flag;
|
||||
extern bool warn_array_write_oob;
|
||||
|
||||
/*
|
||||
* If this file opened, then write debug information to this
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ inline uint64_t strtouint64(const char*str, char**endptr, int base)
|
|||
/* These are some special header/footer keywords. */
|
||||
^":ivl_version" { return K_ivl_version; }
|
||||
^":ivl_delay_selection" { return K_ivl_delay_selection; }
|
||||
^":ivl_warnings" { return K_ivl_warnings; }
|
||||
^":vpi_module" { return K_vpi_module; }
|
||||
^":vpi_time_precision" { return K_vpi_time_precision; }
|
||||
^":file_names" { return K_file_names; }
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ extern "C" const char*optarg;
|
|||
#endif
|
||||
|
||||
bool verbose_flag = false;
|
||||
bool warn_array_write_oob = false;
|
||||
static int vvp_return_value = 0;
|
||||
static int vvp_used = 0;
|
||||
|
||||
|
|
@ -214,6 +215,12 @@ void set_delay_selection(const char* sel)
|
|||
delete[] sel;
|
||||
}
|
||||
|
||||
void set_warning_flags(const char* sel)
|
||||
{
|
||||
warn_array_write_oob = strchr(sel, 's') != 0;
|
||||
delete[] sel;
|
||||
}
|
||||
|
||||
static void final_cleanup()
|
||||
{
|
||||
vvp_object::cleanup();
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ static struct __vpiModPath*modpath_dst = 0;
|
|||
%token K_VAR_S K_VAR_STR K_VAR_I K_VAR_R K_VAR_2S K_VAR_2U
|
||||
%token K_vpi_call K_vpi_call_w K_vpi_call_i
|
||||
%token K_vpi_func K_vpi_func_r K_vpi_func_s
|
||||
%token K_ivl_version K_ivl_delay_selection
|
||||
%token K_ivl_version K_ivl_delay_selection K_ivl_warnings
|
||||
%token K_vpi_module K_vpi_time_precision K_file_names K_file_line
|
||||
%token K_PORT_INPUT K_PORT_OUTPUT K_PORT_INOUT K_PORT_MIXED K_PORT_NODIR
|
||||
|
||||
|
|
@ -153,6 +153,8 @@ header_line
|
|||
{ verify_version($2, $3); }
|
||||
| K_ivl_delay_selection T_STRING ';'
|
||||
{ set_delay_selection($2); }
|
||||
| K_ivl_warnings T_STRING ';'
|
||||
{ set_warning_flags($2); }
|
||||
| K_vpi_module T_STRING ';'
|
||||
{ compile_load_vpi_module($2); }
|
||||
| K_vpi_time_precision '+' T_NUMBER ';'
|
||||
|
|
|
|||
|
|
@ -38,6 +38,11 @@ extern void verify_version(char *ivl_ver, char* commit);
|
|||
*/
|
||||
extern void set_delay_selection(const char* sel);
|
||||
|
||||
/*
|
||||
* Set runtime warning classes embedded in the VVP input file.
|
||||
*/
|
||||
extern void set_warning_flags(const char* sel);
|
||||
|
||||
/*
|
||||
* various functions shared by the lexor and the parser.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
# include "config.h"
|
||||
# include "vthread.h"
|
||||
# include "codes.h"
|
||||
# include "compile.h"
|
||||
# include "schedule.h"
|
||||
# include "ufunc.h"
|
||||
# include "event.h"
|
||||
|
|
@ -1076,6 +1077,42 @@ bool of_ADD_WR(vthread_t thr, vvp_code_t)
|
|||
return true;
|
||||
}
|
||||
|
||||
static set<vvp_code_t> warned_array_write_oob;
|
||||
|
||||
static void maybe_warn_array_write_oob(vthread_t thr, vvp_code_t cp,
|
||||
int64_t adr)
|
||||
{
|
||||
if (!warn_array_write_oob)
|
||||
return;
|
||||
|
||||
assert(cp->array);
|
||||
|
||||
bool index_undef = thr->flags[4] == BIT4_1;
|
||||
if (!index_undef && adr >= 0 && (uint64_t) adr < cp->array->get_size())
|
||||
return;
|
||||
|
||||
if (!warned_array_write_oob.insert(cp).second)
|
||||
return;
|
||||
|
||||
int left = cp->array->swap_addr ? cp->array->last_addr.get_value()
|
||||
: cp->array->first_addr.get_value();
|
||||
int right = cp->array->swap_addr ? cp->array->first_addr.get_value()
|
||||
: cp->array->last_addr.get_value();
|
||||
|
||||
cerr << thr->get_fileline();
|
||||
if (index_undef) {
|
||||
cerr << "Warning: undefined unpacked array write index for '";
|
||||
} else {
|
||||
int64_t source_index = adr
|
||||
+ (int64_t) cp->array->first_addr.get_value();
|
||||
cerr << "Warning: out-of-bounds unpacked array write index "
|
||||
<< source_index << " for '";
|
||||
}
|
||||
|
||||
cerr << cp->array->name << "[" << left << ":" << right
|
||||
<< "]'; write ignored." << endl;
|
||||
}
|
||||
|
||||
/* %assign/ar <array>, <delay>
|
||||
* Generate an assignment event to a real array. Index register 3
|
||||
* contains the canonical address of the word in the memory. <delay>
|
||||
|
|
@ -1088,6 +1125,11 @@ bool of_ASSIGN_AR(vthread_t thr, vvp_code_t cp)
|
|||
unsigned delay = cp->bit_idx[0];
|
||||
double value = thr->pop_real();
|
||||
|
||||
maybe_warn_array_write_oob(thr, cp, adr);
|
||||
|
||||
if (thr->flags[4] == BIT4_1)
|
||||
return true;
|
||||
|
||||
if (adr >= 0) {
|
||||
schedule_assign_array_word(cp->array, adr, value, delay);
|
||||
}
|
||||
|
|
@ -1105,6 +1147,11 @@ bool of_ASSIGN_ARD(vthread_t thr, vvp_code_t cp)
|
|||
long adr = thr->words[3].w_int;
|
||||
double value = thr->pop_real();
|
||||
|
||||
maybe_warn_array_write_oob(thr, cp, adr);
|
||||
|
||||
if (thr->flags[4] == BIT4_1)
|
||||
return true;
|
||||
|
||||
if (adr >= 0) {
|
||||
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_uint;
|
||||
schedule_assign_array_word(cp->array, adr, value, delay);
|
||||
|
|
@ -1125,6 +1172,11 @@ bool of_ASSIGN_ARE(vthread_t thr, vvp_code_t cp)
|
|||
long adr = thr->words[3].w_int;
|
||||
double value = thr->pop_real();
|
||||
|
||||
maybe_warn_array_write_oob(thr, cp, adr);
|
||||
|
||||
if (thr->flags[4] == BIT4_1)
|
||||
return true;
|
||||
|
||||
if (adr >= 0) {
|
||||
if (thr->ecount == 0) {
|
||||
schedule_assign_array_word(cp->array, adr, value, 0);
|
||||
|
|
@ -1210,6 +1262,8 @@ bool of_ASSIGN_VEC4_A_D(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
vvp_vector4_t val = thr->pop_vec4();
|
||||
|
||||
maybe_warn_array_write_oob(thr, cp, adr);
|
||||
|
||||
// Abort if flags[4] is set. This can happen if the calculation
|
||||
// into an index register failed.
|
||||
if (thr->flags[4] == BIT4_1)
|
||||
|
|
@ -1236,6 +1290,8 @@ bool of_ASSIGN_VEC4_A_E(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
vvp_vector4_t val = thr->pop_vec4();
|
||||
|
||||
maybe_warn_array_write_oob(thr, cp, adr);
|
||||
|
||||
// Abort if flags[4] is set. This can happen if the calculation
|
||||
// into an index register failed.
|
||||
if (thr->flags[4] == BIT4_1)
|
||||
|
|
@ -5770,6 +5826,11 @@ bool of_STORE_OBJA(vthread_t thr, vvp_code_t cp)
|
|||
vvp_object_t val;
|
||||
thr->pop_object(val);
|
||||
|
||||
maybe_warn_array_write_oob(thr, cp, adr);
|
||||
|
||||
if (thr->flags[4] == BIT4_1)
|
||||
return true;
|
||||
|
||||
cp->array->set_word(adr, val);
|
||||
|
||||
return true;
|
||||
|
|
@ -6089,8 +6150,10 @@ static bool storea(vthread_t thr, vvp_code_t cp)
|
|||
ELEM val;
|
||||
pop_value(thr, val, 0);
|
||||
|
||||
unsigned adr = thr->words[idx].w_int;
|
||||
maybe_warn_array_write_oob(thr, cp, adr);
|
||||
|
||||
if (thr->flags[4] != BIT4_1) {
|
||||
unsigned adr = thr->words[idx].w_int;
|
||||
cp->array->set_word(adr, val);
|
||||
}
|
||||
|
||||
|
|
@ -6191,6 +6254,8 @@ bool of_STORE_VEC4A(vthread_t thr, vvp_code_t cp)
|
|||
long adr = adr_index? thr->words[adr_index].w_int : 0;
|
||||
int64_t off = off_index ? thr->words[off_index].w_int : 0;
|
||||
|
||||
maybe_warn_array_write_oob(thr, cp, adr);
|
||||
|
||||
// Suppress action if flags-4 is true.
|
||||
if (thr->flags[4] == BIT4_1) {
|
||||
thr->pop_vec4(1);
|
||||
|
|
|
|||
Loading…
Reference in New Issue