Implement assign/vec4/off/e

This commit is contained in:
Stephen Williams 2014-01-23 18:39:29 -08:00
parent 8bebe59e20
commit 9cfb15a302
4 changed files with 150 additions and 28 deletions

View File

@ -117,7 +117,7 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
{
unsigned skip_assign = transient_id++;
int word_ix_reg = 3;
int part_off_reg = 1;
int part_off_reg = 0;
int delay_index;
unsigned long part_off = 0;
@ -138,7 +138,6 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
if (dexp != 0) {
word_ix_reg = allocate_word();
part_off_reg = allocate_word();
} else if (part_off_ex) {
word_ix_reg = allocate_word();
}
@ -148,11 +147,13 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
fprintf(vvp_out, " %%flag_or %d, 4;\n", error_flag);
if (part_off_ex) {
part_off_reg = allocate_word();
draw_eval_expr_into_integer(part_off_ex, part_off_reg);
fprintf(vvp_out, " %%flag_or %d, 4;\n", error_flag);
} else {
} else if (part_off != 0) {
/* Store word part select into part_off_reg */
part_off_reg = allocate_word();
fprintf(vvp_out, " %%ix/load %d, %lu, 0; part off\n",
part_off_reg, part_off);
}
@ -161,19 +162,18 @@ 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);
fprintf(vvp_out, " %%flag_mov 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);
}
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %d;\n",
lsig, part_off_reg, delay_index);
clr_word(part_off_reg);
clr_word(delay_index);
} else if (nevents != 0) {
/* Event control delay... */
fprintf(vvp_out, " %%assign/vec4/a/e v%p, 0;\n", lsig);
fprintf(vvp_out, " %%assign/vec4/a/e v%p, %d;\n", lsig, part_off_reg);
} else {
/* Constant delay... */
@ -196,6 +196,8 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
if (nevents != 0) fprintf(vvp_out, " %%evctl/c;\n");
clr_flag(error_flag);
if (part_off_reg)
clr_word(part_off_reg);
clear_expression_lookaside();
}
@ -240,7 +242,6 @@ static void assign_to_lvector(ivl_lval_t lval,
// so in these cases we'll need to use
// %assign/vec4/off/... variants.
unsigned skip_assign = transient_id++;
if (dexp != 0) {
/* Calculated offset... */
int offset_index = allocate_word();
@ -260,19 +261,15 @@ static void assign_to_lvector(ivl_lval_t lval,
clr_word(delay_index);
} else if (nevents != 0) {
int offset_index = allocate_word();
/* Event control delay... */
draw_eval_expr_into_integer(part_off_ex, 1);
/* If the index expression has XZ bits, skip the assign. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
#if 0
fprintf(vvp_out, " %%ix/load 0, %u, 0;\n", width);
fprintf(vvp_out, " %%assign/v0/x1/e v%p_%lu, %u;\n",
sig, use_word, bit);
#else
assert(0); // XXXX
#endif
fprintf(vvp_out, "t_%u ;\n", skip_assign);
draw_eval_expr_into_integer(part_off_ex, offset_index);
fprintf(vvp_out, " %%assign/vec4/off/e v%p_%lu, %d;\n",
sig, use_word, offset_index);
fprintf(vvp_out, " %%evctl/c;\n");
clr_word(offset_index);
} else {
int offset_index = allocate_word();
int delay_index = allocate_word();
@ -338,7 +335,15 @@ static void assign_to_lvector(ivl_lval_t lval,
}
#else
if (nevents != 0) {
assert(0); // XXXX
assert(dexp==0);
int offset_index = allocate_word();
fprintf(vvp_out, " %%ix/load %d, %lu, 0;\n",
offset_index, part_off);
fprintf(vvp_out, " %%flag_set/imm 4, 0;\n");
fprintf(vvp_out, " %%assign/vec4/off/e v%p_%lu, %d;\n",
sig, use_word, offset_index);
fprintf(vvp_out, " %%evctl/c;\n");
clr_word(offset_index);
} else {
// Constant part offset, non-constant (calculated)
@ -372,6 +377,8 @@ static void assign_to_lvector(ivl_lval_t lval,
/* Event control delay... */
fprintf(vvp_out, " %%assign/vec4/e v%p_%lu;\n",
sig, use_word);
fprintf(vvp_out, " %%evctl/c;\n");
} else {
/*
* The %assign can only take a 32 bit delay. For a larger

View File

@ -44,14 +44,15 @@ extern bool of_ASSIGN_ARD(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_ARE(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_AV(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_AVE(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_D(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_MV(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_VEC4(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_VEC4D(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_VEC4E(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_VEC4_A_D(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_VEC4_A_E(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_VEC4_OFF_D(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_VEC4_OFF_E(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_V0X1(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_V0X1E(vthread_t thr, vvp_code_t code);

View File

@ -97,15 +97,16 @@ static const struct opcode_table_s opcode_table[] = {
{ "%assign/ar/e",of_ASSIGN_ARE,1,{OA_ARR_PTR,OA_NONE, OA_NONE} },
{ "%assign/av",of_ASSIGN_AV,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/av/d",of_ASSIGN_AVD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/av/e",of_ASSIGN_AVE,2,{OA_ARR_PTR,OA_BIT1, OA_NONE} },
{ "%assign/v0/x1",of_ASSIGN_V0X1,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
{ "%assign/v0/x1/d",of_ASSIGN_V0X1D,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
{ "%assign/v0/x1/e",of_ASSIGN_V0X1E,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
{ "%assign/vec4", of_ASSIGN_VEC4, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%assign/vec4/a/d", of_ASSIGN_VEC4_A_D, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
{ "%assign/vec4/a/e", of_ASSIGN_VEC4_A_E, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%assign/vec4/d", of_ASSIGN_VEC4D, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%assign/vec4/e", of_ASSIGN_VEC4E, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%assign/vec4/off/d",of_ASSIGN_VEC4_OFF_D, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%assign/vec4/off/e",of_ASSIGN_VEC4_OFF_E, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%assign/wr", of_ASSIGN_WR, 2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
{ "%assign/wr/d",of_ASSIGN_WRD,2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
{ "%assign/wr/e",of_ASSIGN_WRE,1,{OA_VPI_PTR, OA_NONE, OA_NONE} },

View File

@ -1168,6 +1168,7 @@ bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t cp)
return true;
}
#if 0
bool of_ASSIGN_AVE(vthread_t thr, vvp_code_t cp)
{
unsigned wid = thr->words[0].w_int;
@ -1194,7 +1195,6 @@ bool of_ASSIGN_AVE(vthread_t thr, vvp_code_t cp)
assert(wid > 0);
#if 0
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
// If the count is zero then just put the value.
if (thr->ecount == 0) {
@ -1202,12 +1202,10 @@ bool of_ASSIGN_AVE(vthread_t thr, vvp_code_t cp)
} else {
schedule_evctl(cp->array, adr, value, off, thr->event, thr->ecount);
}
#else
fprintf(stderr, "XXXX NOT IMPLEMENTED: %%assign/av/e ...\n");
assert(0);
#endif
return true;
}
#endif
#if 0
/*
@ -1261,14 +1259,82 @@ bool of_ASSIGN_VEC4_A_D(vthread_t thr, vvp_code_t cp)
vvp_time64_t del = del_idx? thr->words[del_idx].w_uint : 0;
long adr = thr->words[adr_idx].w_int;
vvp_vector4_t value = thr->pop_vec4();
vvp_vector4_t val = thr->pop_vec4();
unsigned wid = val.size();
const unsigned array_wid = get_array_word_size(cp->array);
// 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);
if (off >= (long)array_wid)
return true;
if (off < 0) {
if ((unsigned)-off >= array_wid)
return true;
int use_off = -off;
assert(wid > use_off);
unsigned use_wid = wid - use_off;
val = val.subvalue(use_off, use_wid);
off = 0;
wid = use_wid;
}
if (off+wid > array_wid) {
val = val.subvalue(0, array_wid-off);
wid = val.size();
}
schedule_assign_array_word(cp->array, adr, off, val, del);
return true;
}
/*
* %assign/vec4/a/e <arr>, <offx>
*/
bool of_ASSIGN_VEC4_A_E(vthread_t thr, vvp_code_t cp)
{
int off_idx = cp->bit_idx[0];
int adr_idx = 3;
long off = off_idx? thr->words[off_idx].w_int : 0;
long adr = thr->words[adr_idx].w_int;
vvp_vector4_t val = thr->pop_vec4();
unsigned wid = val.size();
const unsigned array_wid = get_array_word_size(cp->array);
// 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;
if (off >= (long)array_wid)
return true;
if (off < 0) {
if ((unsigned)-off >= array_wid)
return true;
int use_off = -off;
assert(wid > (unsigned)use_off);
unsigned use_wid = wid - use_off;
val = val.subvalue(use_off, use_wid);
off = 0;
wid = use_wid;
}
if (off+wid > array_wid) {
val = val.subvalue(0, array_wid-off);
wid = val.size();
}
if (thr->ecount == 0) {
schedule_assign_array_word(cp->array, adr, off, val, 0);
} else {
schedule_evctl(cp->array, adr, val, off, thr->event, thr->ecount);
}
return true;
}
@ -1309,6 +1375,53 @@ bool of_ASSIGN_VEC4_OFF_D(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* %assign/vec4/off/e <var>, <off>
*/
bool of_ASSIGN_VEC4_OFF_E(vthread_t thr, vvp_code_t cp)
{
vvp_net_ptr_t ptr (cp->net, 0);
unsigned off_index = cp->bit_idx[0];
vvp_vector4_t val = thr->pop_vec4();
unsigned wid = val.size();
int off = thr->words[off_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);
if (off >= (long)sig->value_size())
return true;
if (off < 0) {
if ((unsigned)-off >= sig->value_size())
return true;
int use_off = -off;
assert(wid > use_off);
unsigned use_wid = wid - use_off;
val = val.subvalue(use_off, use_wid);
off = 0;
wid = use_wid;
}
if (off+wid > sig->value_size()) {
val = val.subvalue(0, sig->value_size()-off);
wid = val.size();
}
if (thr->ecount == 0) {
schedule_assign_vector(ptr, off, sig->value_size(), val, 0);
} else {
schedule_evctl(ptr, val, off, sig->value_size(), thr->event, thr->ecount);
}
return true;
}
#if 0
/*
* This is %assign/v0/d <label>, <delay_idx>, <bit>