diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 94209c15c..0f32bf9c6 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -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 diff --git a/vvp/codes.h b/vvp/codes.h index 1f70ee6a2..735ada010 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -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); diff --git a/vvp/compile.cc b/vvp/compile.cc index 81c199f29..5238ddffd 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -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} }, diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 611acbe0f..e8a1f8a44 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -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 , + */ +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 , + */ +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 (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