diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 85f9c7075..85300588d 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -1751,7 +1751,7 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res, if (!number_is_immediate(ix, 8*sizeof(unsigned long))) { draw_eval_expr_into_integer(ix, 3); if (add_index < 0) { - fprintf(vvp_out, " %%load/av %u, v%p, %u;\n", + fprintf(vvp_out, " %%load/av %u, v%p, %u;\n", res.base, sig, swid); } else { assert(add_index == 0); diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index fea75a840..cac098fd3 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -184,22 +184,44 @@ static void set_to_lvariable(ivl_lval_t lval, } static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix, - unsigned bit, unsigned delay, unsigned width) + unsigned bit, unsigned delay, ivl_expr_t dexp, + unsigned width) { unsigned skip_assign = transient_id++; - /* Calculate array word index into index register 3 */ - draw_eval_expr_into_integer(word_ix, 3); - /* Skip assignment if word expression is not defined. */ - fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign); + if (dexp == 0) { + /* Constant delay... */ + /* Calculate array word index into index register 3 */ + draw_eval_expr_into_integer(word_ix, 3); + /* Skip assignment if word expression is not defined. */ + fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign); - /* Store expression width into index word 0 */ - fprintf(vvp_out, " %%ix/load 0, %u; // word width\n", width); - /* Store constant (0) word part select into index 1 */ - fprintf(vvp_out, " %%ix/load 1, 0;\n"); + /* Store expression width into index word 0 */ + fprintf(vvp_out, " %%ix/load 0, %u; // word width\n", width); + /* Store constant (0) word part select into index 1 */ + fprintf(vvp_out, " %%ix/load 1, 0;\n"); - fprintf(vvp_out, " %%assign/av v%p, %u, %u;\n", lsig, delay, bit); - fprintf(vvp_out, "t_%u ;\n", skip_assign); + fprintf(vvp_out, " %%assign/av v%p, %u, %u;\n", lsig, + delay, bit); + fprintf(vvp_out, "t_%u ;\n", skip_assign); + } else { + /* Calculated delay... */ + int delay_index = allocate_word(); + draw_eval_expr_into_integer(dexp, delay_index); + /* Calculate array word index into index register 3 */ + draw_eval_expr_into_integer(word_ix, 3); + /* Skip assignment if word expression is not defined. */ + fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign); + + /* Store expression width into index word 0 */ + fprintf(vvp_out, " %%ix/load 0, %u; // word width\n", width); + /* Store constant (0) word part select into index 1 */ + fprintf(vvp_out, " %%ix/load 1, 0;\n"); + + fprintf(vvp_out, " %%assign/av/d v%p, %d, %u;\n", lsig, + delay_index, bit); + fprintf(vvp_out, "t_%u ;\n", skip_assign); + } clear_expression_lookaside(); } @@ -218,8 +240,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit, if (ivl_signal_array_count(sig) > 1) { assert(word_ix); if (! number_is_immediate(word_ix, 8*sizeof(use_word))) { - assert(!dexp); - assign_to_array_word(sig, word_ix, bit, delay, width); + assign_to_array_word(sig, word_ix, bit, delay, dexp, width); return; } @@ -280,7 +301,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit, draw_eval_expr_into_integer(dexp, delay_index); fprintf(vvp_out, " %%ix/load 0, %u;\n", width); fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off); - fprintf(vvp_out, " %%assign/v0/x1/d v%p_%lu, %u, %u;\n", + fprintf(vvp_out, " %%assign/v0/x1/d v%p_%lu, %d, %u;\n", sig, use_word, delay_index, bit); clr_word(delay_index); } diff --git a/vvp/codes.h b/vvp/codes.h index 40113f895..0b0f7dad7 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -38,6 +38,7 @@ extern bool of_ADDI(vthread_t thr, vvp_code_t code); extern bool of_AND(vthread_t thr, vvp_code_t code); extern bool of_ANDR(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_D(vthread_t thr, vvp_code_t code); extern bool of_ASSIGN_MV(vthread_t thr, vvp_code_t code); extern bool of_ASSIGN_V0(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index 601086385..ff073ab2f 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -88,6 +88,7 @@ const static struct opcode_table_s opcode_table[] = { { "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%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/mv",of_ASSIGN_MV,3,{OA_MEM_PTR,OA_BIT1, OA_BIT2} }, { "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, { "%assign/v0/d",of_ASSIGN_V0D,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index d5679909a..05156a6ae 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -57,6 +57,7 @@ means the following: otherwise x * %assign/av , , +* %assign/av/d , , The %assign/av instruction assigns a vector value to a word in the labeled array. The is the delay in simulation time to the @@ -70,6 +71,11 @@ The base of a part select is retrieved from index register 1. The address of the word in the memory is from index register 3. The address is canonical form. +The %assign/av/d variation reads the delay from an integer register that +is given by the value. This should not be 0, 1 or 3, of course, +since these registers contain the vector width, base part select and +word address. + * %assign/mv , , (DEPRECATED) the %assign/mv instruction assigns a vector value to a word in the diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 5c91f3ce2..b59d94979 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -564,6 +564,29 @@ bool of_ASSIGN_AV(vthread_t thr, vvp_code_t cp) return true; } +/* %assign/av/d , , + * This generates an assignment event to an array. Index register 0 + * contains the width of the vector (and the word) and index register + * 3 contains the canonical address of the word in memory. The named + * index register contains the delay. + */ +bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t cp) +{ + unsigned wid = thr->words[0].w_int; + unsigned off = thr->words[1].w_int; + unsigned adr = thr->words[3].w_int; + + assert(wid > 0); + + unsigned long delay = thr->words[cp->bit_idx[0]].w_int; + unsigned bit = cp->bit_idx[1]; + + vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid); + + schedule_assign_array_word(cp->array, adr, off, value, delay); + return true; +} + /* * This is %assign/v0