diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 897177b0f..637de71a1 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -578,10 +578,14 @@ static void store_vec4_to_lval(ivl_statement_t net) int part_index = 0; /* Calculate the word address into word_index */ draw_eval_expr_into_integer(word_ex, word_index); - /* If there is a part_offset, calcualte it into part_index. */ + /* If there is a part_offset, calculate it into part_index. */ if (part_off_ex) { + int flag_index = allocate_flag(); part_index = allocate_word(); + fprintf(vvp_out, " %%flag_mov %d, 4;\n", flag_index); draw_eval_expr_into_integer(part_off_ex, part_index); + fprintf(vvp_out, " %%flag_or 4, %d;\n", flag_index); + clr_flag(flag_index); } fprintf(vvp_out, " %%store/vec4a v%p, %d, %d;\n", @@ -595,6 +599,7 @@ static void store_vec4_to_lval(ivl_statement_t net) /* Dynamically calculated part offset */ int offset_index = allocate_word(); draw_eval_expr_into_integer(part_off_ex, offset_index); + /* Note that flag4 is set by the eval above. */ fprintf(vvp_out, " %%store/vec4 v%p_0, %d, %u;\n", lsig, offset_index, lwid); clr_word(offset_index); diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 59c51fede..f5e847f86 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -121,6 +121,9 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix, int delay_index; unsigned long part_off = 0; + int error_flag = allocate_flag(); + fprintf(vvp_out, " %%flag_set/imm %d, 0;\n", error_flag); + /* Figure the constant part offset, if possible. If we can do so, then forget about the expression and use the calculated value. After this block, if the part_off_ex!=0, then the @@ -142,13 +145,11 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix, /* Calculate array word index into word index register */ draw_eval_expr_into_integer(word_ix, word_ix_reg); - /* Skip assignment if word expression is not defined. */ - fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign); + fprintf(vvp_out, " %%flag_or %d, 4;\n", error_flag); if (part_off_ex) { draw_eval_expr_into_integer(part_off_ex, part_off_reg); - /* If the index expression has XZ bits, skip the assign. */ - fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign); + fprintf(vvp_out, " %%flag_or %d, 4;\n", error_flag); } else { /* Store word part select into part_off_reg */ @@ -160,6 +161,7 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix, /* Calculated delay... */ delay_index = allocate_word(); draw_eval_expr_into_integer(dexp, delay_index); + fprintf(vvp_out, " %%flag_or 4, %d;\n", error_flag); if (word_ix_reg != 3) { fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg); clr_word(word_ix_reg); @@ -193,6 +195,7 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix, fprintf(vvp_out, "t_%u ;\n", skip_assign); if (nevents != 0) fprintf(vvp_out, " %%evctl/c;\n"); + clr_flag(error_flag); clear_expression_lookaside(); } @@ -275,15 +278,16 @@ static void assign_to_lvector(ivl_lval_t lval, /* Constant delay... */ fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n", delay_index, low_d, hig_d); - /* Calculated part offset... */ + /* Calculated part offset. This will leave flag + bit 4 set to 1 if the copy into the index + detected xz values. The %assign will use that + to know to skip the assign. */ draw_eval_expr_into_integer(part_off_ex, offset_index); /* If the index expression has XZ bits, skip the assign. */ - fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign); fprintf(vvp_out, " %%assign/vec4/off/d v%p_%lu, %d, %d;\n", sig, use_word, offset_index, delay_index); clr_word(offset_index); clr_word(delay_index); - fprintf(vvp_out, "t_%u ;\n", skip_assign); } } else if (part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig)) { @@ -344,11 +348,13 @@ static void assign_to_lvector(ivl_lval_t lval, int offset_index = allocate_word(); int delay_index = allocate_word(); fprintf(vvp_out, " %%ix/load %d, %lu, 0;\n", offset_index, part_off); - if (dexp) + if (dexp) { draw_eval_expr_into_integer(dexp,delay_index); - else + } else { fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n", delay_index, low_d, hig_d); + fprintf(vvp_out, " %%flag_set/imm 4, 0;\n"); + } fprintf(vvp_out, " %%assign/vec4/off/d v%p_%lu, %d, %d;\n", sig, use_word, offset_index, delay_index); clr_word(offset_index); diff --git a/vvp/codes.h b/vvp/codes.h index 65b99184a..1f70ee6a2 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -108,6 +108,8 @@ extern bool of_EVCTLI(vthread_t thr, vvp_code_t code); extern bool of_EVCTLS(vthread_t thr, vvp_code_t code); extern bool of_FILE_LINE(vthread_t thr, vvp_code_t code); extern bool of_FLAG_GET_VEC4(vthread_t thr, vvp_code_t code); +extern bool of_FLAG_MOV(vthread_t thr, vvp_code_t code); +extern bool of_FLAG_OR(vthread_t thr, vvp_code_t code); extern bool of_FLAG_SET_IMM(vthread_t thr, vvp_code_t code); extern bool of_FLAG_SET_VEC4(vthread_t thr, vvp_code_t code); extern bool of_FORCE_LINK(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index 737ac117e..5dfedc31a 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -157,6 +157,8 @@ static const struct opcode_table_s opcode_table[] = { { "%evctl/s",of_EVCTLS, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} }, { "%event", of_EVENT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%flag_get/vec4", of_FLAG_GET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, + { "%flag_mov", of_FLAG_MOV, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%flag_or", of_FLAG_OR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%flag_set/imm", of_FLAG_SET_IMM, 2, {OA_NUMBER, OA_BIT1, OA_NONE} }, { "%flag_set/vec4", of_FLAG_SET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%force/link", of_FORCE_LINK,2,{OA_FUNC_PTR, OA_FUNC_PTR2, OA_NONE} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index ef3202425..8716a4bab 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -199,6 +199,10 @@ contains the word address. The and index registers can be 0, which means a zero value instead of the contents of index register 0. +If flag bit 4 is set, then the value will be popped from the stack, +but it will not be assigned. This handles the case that the index +values is undefined. + * %assign/vec4/off/d , , This is for writing parts to the target variable. The is @@ -208,6 +212,9 @@ register that holds the offset into the target variable, and the offset is in canonical bits. The width that is written is taken from the width of the value on the stack. +The actual assignment is suppressed if flags-4 is 1. This is so that +calculations of offset can set the flag on errors. + * %assign/wr , * %assign/wr/d , * %assign/wr/e @@ -543,6 +550,15 @@ the format of the output is: is a string, if string is 0 then the following default message is used: "Procedural tracing.". +* %flag_mov , + +This instruction copies the flag bit from to . + +* %flag_or , + +This instruction calculates the verilog OR of the flag bits in +and , and leaves the result in . + * %flag_set/imm , This instruction sets an immediate value into a flag bit. This is a @@ -625,7 +641,7 @@ bits. * %ix/getv , * %ix/getv/s , -These instructions are like the %ix/get instructions, except that they +These instructions are like the %ix/vec4 instructions, except that they read directly from a functor label instead of from thread bits. They set bit 4 just like %ix/get. @@ -1245,6 +1261,14 @@ offset. Both index registers can be 0, to mean a zero value instead of a zero register. +The %store/vec4a will check flag bit 4, and if it is true, it will +suppress the actual assignment. This is so that the context can +indicate that the address is invalid. + +The %store/vec4 will check flag bit 4, only if the is a +non-zero index register. A 0 index is a fixed constant and cannot +fail. + NOTE: The is not necessary, and should be removed. * %sub , , (XXXX Old version) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 2d91c53a7..3910ed770 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -1263,6 +1263,11 @@ bool of_ASSIGN_VEC4_A_D(vthread_t thr, vvp_code_t cp) vvp_vector4_t value = thr->pop_vec4(); + // Abort if flags[4] is set. This can happen if the calulation + // into an index register failed. + if (thr->flags[4] == BIT4_1) + return true; + schedule_assign_array_word(cp->array, adr, off, value, del); return true; } @@ -1280,6 +1285,11 @@ bool of_ASSIGN_VEC4_OFF_D(vthread_t thr, vvp_code_t cp) int off = thr->words[off_index].w_int; int del = thr->words[del_index].w_int; + // Abort if flags[4] is set. This can happen if the calulation + // into an index register failed. + if (thr->flags[4] == BIT4_1) + return true; + vvp_signal_value*sig = dynamic_cast (cp->net->fil); assert(sig); @@ -2937,6 +2947,30 @@ bool of_FLAG_GET_VEC4(vthread_t thr, vvp_code_t cp) return true; } +/* + * %flag_mov , bit_idx[0]; + int flag2 = cp->bit_idx[1]; + + thr->flags[flag1] = thr->flags[flag2]; + return true; +} + +/* + * %flag_or , + */ +bool of_FLAG_OR(vthread_t thr, vvp_code_t cp) +{ + int flag1 = cp->bit_idx[0]; + int flag2 = cp->bit_idx[1]; + + thr->flags[flag1] = thr->flags[flag1] | thr->flags[flag2]; + return true; +} + bool of_FLAG_SET_IMM(vthread_t thr, vvp_code_t cp) { int flag = cp->number; @@ -5836,6 +5870,11 @@ bool of_STORE_VEC4(vthread_t thr, vvp_code_t cp) if (val.size() > wid) val.resize(wid); + // If there is a problem loading the index register, flags-4 + // will be set to 1, and we know here to skip the actual assignment. + if (off_index!=0 && thr->flags[4] == BIT4_1) + return true; + if (off==0 && val.size()==sig->value_size()) vvp_send_vec4(ptr, val, thr->wt_context); else @@ -5857,6 +5896,10 @@ bool of_STORE_VEC4A(vthread_t thr, vvp_code_t cp) long adr = adr_index? thr->words[adr_index].w_int : 0; long off = off_index? thr->words[off_index].w_int : 0; + // Suppress action if flags-4 is true. + if (thr->flags[4] == BIT4_1) + return true; + array_set_word(cp->array, adr, off, value); return true;