Cleanup vec4 handling of suppressed store/assign due to bad offset/index math.

This commit is contained in:
Stephen Williams 2014-01-14 12:00:39 -08:00
parent c6c697bdb7
commit d8533104b0
6 changed files with 93 additions and 11 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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} },

View File

@ -199,6 +199,10 @@ contains the word address.
The <off-index> and <delay-index> 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 <var-label>, <off-index>, <delay-index>
This is for writing parts to the target variable. The <var-label> 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 <vpi-label>, <delay>
* %assign/wr/d <vpi-label>, <delayx>
* %assign/wr/e <vpi-label>
@ -543,6 +550,15 @@ the format of the output is:
<description> is a string, if string is 0 then the following default
message is used: "Procedural tracing.".
* %flag_mov <flag1>, <flag2>
This instruction copies the flag bit from <flag2> to <flag1>.
* %flag_or <flag1>, <flag2>
This instruction calculates the verilog OR of the flag bits in <flag1>
and <flag2>, and leaves the result in <flag1>.
* %flag_set/imm <flag>, <value>
This instruction sets an immediate value into a flag bit. This is a
@ -625,7 +641,7 @@ bits.
* %ix/getv <idx>, <functor-label>
* %ix/getv/s <idx>, <functor-label>
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 <offset> is a
non-zero index register. A 0 index is a fixed constant and cannot
fail.
NOTE: The <wid> is not necessary, and should be removed.
* %sub <bit-l>, <bit-r>, <wid> (XXXX Old version)

View File

@ -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<vvp_signal_value*> (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 <flag1>, <flag2)
*/
bool of_FLAG_MOV(vthread_t thr, vvp_code_t cp)
{
int flag1 = cp->bit_idx[0];
int flag2 = cp->bit_idx[1];
thr->flags[flag1] = thr->flags[flag2];
return true;
}
/*
* %flag_or <flag1>, <flag2>
*/
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;