diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index f7508e71a..b233e66f6 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -72,9 +72,14 @@ static void draw_vpi_taskfunc_args(const char*call_string, unsigned parm_count = tnet ? ivl_stmt_parm_count(tnet) : ivl_expr_parms(fnet); - struct vector_info *vec = 0x0; - unsigned int vecs= 0; - unsigned int veci= 0; + + struct args_info { + char*text; + int vec_flag; /* True if the vec must be released. */ + struct vector_info vec; + } *args = calloc(parm_count, sizeof(struct args_info)); + + char buffer[4096]; ivl_parameter_t par; @@ -92,17 +97,56 @@ static void draw_vpi_taskfunc_args(const char*call_string, with VPI handles of their own. Therefore, skip them in the process of evaluating expressions. */ case IVL_EX_NONE: + args[idx].text = strdup("\" \""); + continue; + case IVL_EX_ARRAY: - case IVL_EX_NUMBER: + snprintf(buffer, sizeof buffer, + "v%p", ivl_expr_signal(expr)); + args[idx].text = strdup(buffer); + continue; + + case IVL_EX_NUMBER: { + unsigned bit, wid = ivl_expr_width(expr); + const char*bits = ivl_expr_bits(expr); + char*dp; + + snprintf(buffer, sizeof buffer, + "%u'%sb", wid, ivl_expr_signed(expr)? "s" : ""); + dp = buffer + strlen(buffer); + for (bit = wid ; bit > 0 ; bit -= 1) + *dp++ = bits[bit-1]; + *dp++ = 0; + assert(dp - buffer <= sizeof buffer); + args[idx].text = strdup(buffer); + continue; + } + case IVL_EX_STRING: + if (( par = ivl_expr_parameter(expr) )) { + snprintf(buffer, sizeof buffer, "P_%p", par); + + } else { + snprintf(buffer, sizeof buffer, "\"%s\"", ivl_expr_string(expr)); + } + args[idx].text = strdup(buffer); + continue; + case IVL_EX_EVENT: + snprintf(buffer, sizeof buffer, "E_%p", ivl_expr_event(expr)); + args[idx].text = strdup(buffer); + continue; case IVL_EX_SCOPE: + snprintf(buffer, sizeof buffer, "S_%p", ivl_expr_scope(expr)); + args[idx].text = strdup(buffer); continue; case IVL_EX_SFUNC: - if (is_magic_sfunc(ivl_expr_name(expr))) + if (is_magic_sfunc(ivl_expr_name(expr))) { + snprintf(buffer, sizeof buffer, "%s", ivl_expr_name(expr)); + args[idx].text = strdup(buffer); continue; - + } break; case IVL_EX_SIGNAL: @@ -125,21 +169,47 @@ static void draw_vpi_taskfunc_args(const char*call_string, } else if (ivl_expr_signed(expr) != ivl_signal_signed(ivl_expr_signal(expr))) { break; - } else if (! is_fixed_memory_word(expr)){ - break; - } else { - /* Some array selects need to be evaluated. */ + } else if (is_fixed_memory_word(expr)) { + /* This is a word of a non-array, or a word + of a net array, so we can address the + word directly. */ + ivl_signal_t sig = ivl_expr_signal(expr); + unsigned use_word = 0; ivl_expr_t word_ex = ivl_expr_oper1(expr); - if (word_ex && !number_is_immediate(word_ex, - 8*sizeof(unsigned))) { - break; + if (word_ex) { + /* Some array select have been evaluated. */ + if (number_is_immediate(word_ex, 8*sizeof(unsigned))) { + use_word = get_number_immediate(word_ex); + word_ex = 0; + } } + if (word_ex) + break; + + assert(word_ex == 0); + snprintf(buffer, sizeof buffer, "v%p_%u", sig, use_word); + args[idx].text = strdup(buffer); continue; - } + } else { + /* What's left, this is the work of a var + array. Create the right code to handle + it. */ + ivl_signal_t sig = ivl_expr_signal(expr); + unsigned use_word = 0; + ivl_expr_t word_ex = ivl_expr_oper1(expr); + if (word_ex) { + /* Some array select have been evaluated. */ + if (number_is_immediate(word_ex, 8*sizeof(unsigned))) { + use_word = get_number_immediate(word_ex); + word_ex = 0; + } + } + if (word_ex) + break; - case IVL_EX_MEMORY: - if (!ivl_expr_oper1(expr)) { + snprintf(buffer, sizeof buffer, "&A", sig, use_word); + args[idx].text = strdup(buffer); continue; } @@ -149,143 +219,43 @@ static void draw_vpi_taskfunc_args(const char*call_string, break; } - vec = (struct vector_info *) - realloc(vec, (vecs+1)*sizeof(struct vector_info)); - switch (ivl_expr_value(expr)) { case IVL_VT_LOGIC: case IVL_VT_BOOL: - vec[vecs] = draw_eval_expr(expr, 0); + args[idx].vec_flag = 1; + args[idx].vec = draw_eval_expr(expr, 0); + snprintf(buffer, sizeof buffer, + "T<%u,%u,%s>", args[idx].vec.base, args[idx].vec.wid, + ivl_expr_signed(expr)? "s" : "u"); break; case IVL_VT_REAL: - vec[vecs].base = draw_eval_real(expr); - vec[vecs].wid = 0; + args[idx].vec_flag = 1; + args[idx].vec.base = draw_eval_real(expr); + args[idx].vec.wid = 0; + snprintf(buffer, sizeof buffer, + "W<%u,r>", args[idx].vec.base); break; default: assert(0); } - vecs++; + args[idx].text = strdup(buffer); } fprintf(vvp_out, "%s", call_string); for (idx = 0 ; idx < parm_count ; idx += 1) { - ivl_expr_t expr = tnet - ? ivl_stmt_parm(tnet, idx) - : ivl_expr_parm(fnet, idx); - switch (ivl_expr_type(expr)) { - case IVL_EX_NONE: - fprintf(vvp_out, ", \" \""); - continue; - - case IVL_EX_ARRAY: - fprintf(vvp_out, ", v%p", ivl_expr_signal(expr)); - continue; - - case IVL_EX_NUMBER: { - unsigned bit, wid = ivl_expr_width(expr); - const char*bits = ivl_expr_bits(expr); - - fprintf(vvp_out, ", %u'%sb", wid, - ivl_expr_signed(expr)? "s" : ""); - for (bit = wid ; bit > 0 ; bit -= 1) - fputc(bits[bit-1], vvp_out); - continue; - } - - case IVL_EX_SIGNAL: - /* If this is a part select, then the value was - calculated above. Otherwise, just pass the - signal. */ - if (ivl_expr_width(expr) != - ivl_signal_width(ivl_expr_signal(expr))) { - break; - - } else if (ivl_expr_signed(expr) != - ivl_signal_signed(ivl_expr_signal(expr))) { - break; - - } else if (! is_fixed_memory_word(expr)){ - break; - - } else { - ivl_signal_t sig = ivl_expr_signal(expr); - unsigned use_word = 0; - ivl_expr_t word_ex = ivl_expr_oper1(expr); - if (word_ex) { - /* Some array select have been evaluated. */ - if (!number_is_immediate(word_ex, - 8*sizeof(unsigned))) { - break; - } - use_word = get_number_immediate(word_ex); - } - fprintf(vvp_out, ", v%p_%u", sig, use_word); - continue; - } - assert(0); - continue; - - case IVL_EX_STRING: - if (( par = ivl_expr_parameter(expr) )) { - fprintf(vvp_out, ", P_%p", par); - - } else { - fprintf(vvp_out, ", \"%s\"", - ivl_expr_string(expr)); - } - continue; - - case IVL_EX_EVENT: - fprintf(vvp_out, ", E_%p", ivl_expr_event(expr)); - continue; - - case IVL_EX_SCOPE: - fprintf(vvp_out, ", S_%p", ivl_expr_scope(expr)); - continue; - - case IVL_EX_SFUNC: - if (is_magic_sfunc(ivl_expr_name(expr))) { - fprintf(vvp_out, ", %s", ivl_expr_name(expr)); - continue; - } - break; - - default: - break; + fprintf(vvp_out, ", %s", args[idx].text); + free(args[idx].text); + if (args[idx].vec_flag) { + if (args[idx].vec.wid > 0) + clr_vector(args[idx].vec); + else + clr_word(args[idx].vec.base); } - assert(veci < vecs); - - switch (ivl_expr_value(expr)) { - - case IVL_VT_LOGIC: - case IVL_VT_BOOL: - fprintf(vvp_out, ", T<%u,%u,%s>", vec[veci].base, - vec[veci].wid, ivl_expr_signed(expr)? "s" : "u"); - break; - - case IVL_VT_REAL: - fprintf(vvp_out, ", W<%u,r>", vec[veci].base); - break; - - default: - assert(0); - } - veci++; } - assert(veci == vecs); - - if (vecs) { - for (idx = 0; idx < vecs; idx++) { - if (vec[idx].wid > 0) - clr_vector(vec[idx]); - else if (vec[idx].wid == 0) - clr_word(vec[idx].base); - } - free(vec); - } + free(args); fprintf(vvp_out, ";\n"); } diff --git a/vvp/array.cc b/vvp/array.cc index e644c8904..8341c218c 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -77,6 +77,12 @@ struct __vpiArrayIndex { unsigned done; }; +struct __vpiArrayVthrA { + struct __vpiHandle base; + struct __vpiArray*array; + unsigned address; +}; + /* * The vpiArrayWord is magic. It is used as the handle to return when * vpi code tries to index or scan an array of variable words. The @@ -117,6 +123,10 @@ static int vpi_array_var_word_get(int code, vpiHandle); static void vpi_array_var_word_get_value(vpiHandle, p_vpi_value); static vpiHandle vpi_array_var_word_put_value(vpiHandle, p_vpi_value, int); +static int vpi_array_vthr_A_get(int code, vpiHandle); +static void vpi_array_vthr_A_get_value(vpiHandle, p_vpi_value); +static vpiHandle vpi_array_vthr_A_put_value(vpiHandle, p_vpi_value, int); + static const struct __vpirt vpip_arraymem_rt = { vpiMemory, vpi_array_get, @@ -167,12 +177,27 @@ static const struct __vpirt vpip_array_var_word_rt = { 0 }; +static const struct __vpirt vpip_array_vthr_A_rt = { + vpiMemoryWord, + &vpi_array_vthr_A_get, + 0, + &vpi_array_vthr_A_get_value, + &vpi_array_vthr_A_put_value, + 0, + 0, + 0, + 0 +}; + # define ARRAY_HANDLE(ref) (assert(ref->vpi_type->type_code==vpiMemory), \ (struct __vpiArray*)ref) # define ARRAY_VAR_WORD(ref) (assert(ref->vpi_type->type_code==vpiMemoryWord), \ (struct __vpiArrayWord*)ref) +# define ARRAY_VTHR_A_HANDLE(ref) (assert(ref->vpi_type->type_code==vpiMemoryWord), \ + (struct __vpiArrayVthrA*)ref) + static void array_make_vals_words(struct __vpiArray*parent) { assert(parent->vals_words == 0); @@ -399,6 +424,53 @@ static int array_index_free_object(vpiHandle ref) return 1; } +static int vpi_array_vthr_A_get(int code, vpiHandle ref) +{ + struct __vpiArrayVthrA*obj = ARRAY_VTHR_A_HANDLE(ref); + struct __vpiArray*parent = obj->array; + + switch (code) { + case vpiLineNo: + return 0; // Not implemented for now! + + case vpiSize: + assert(parent->vals); + return parent->vals_width; + + default: + return 0; + } +} +static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value value) +{ + struct __vpiArrayVthrA*obj = ARRAY_VTHR_A_HANDLE(ref); + struct __vpiArray*parent = obj->array; + + assert(parent); + assert(parent->vals); + assert(obj->address < parent->array_count); + + vpip_vec4_get_value(parent->vals[obj->address], + parent->vals_width, false, value); +} + +static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int) +{ + struct __vpiArrayVthrA*obj = ARRAY_VTHR_A_HANDLE(ref); + struct __vpiArray*parent = obj->array; + + unsigned index = obj->address; + + assert(parent); + assert(obj->address < parent->array_count); + + vvp_vector4_t val = vec4_from_vpi_value(vp, parent->vals_width); + array_set_word(parent, index, 0, val); + + return ref; +} + + void array_set_word(vvp_array_t arr, unsigned address, unsigned part_off, @@ -773,3 +845,19 @@ void compile_array_alias(char*label, char*name, char*src) free(name); free(src); } + +vpiHandle vpip_make_vthr_A(char*label, unsigned addr) +{ + struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*) + malloc(sizeof (struct __vpiArrayVthrA)); + + obj->base.vpi_type = &vpip_array_vthr_A_rt; + + obj->array = array_find(label); + assert(obj->array); + + obj->address = addr; + assert(addr < obj->array->array_count); + + return &(obj->base); +} diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 46032abc5..fb0d919be 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -190,6 +190,7 @@ return T_NUMBER; } +"&A" { return K_A; } /* Handle some specialized constant/literals as symbols. */ diff --git a/vvp/parse.y b/vvp/parse.y index 8e577fd01..28e75b296 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -65,7 +65,7 @@ static struct __vpiModPath*modpath_dst = 0; vvp_delay_t*cdelay; }; -%token K_ALIAS K_ALIAS_S K_ALIAS_R +%token K_A K_ALIAS K_ALIAS_S K_ALIAS_R %token K_ARITH_ABS K_ARITH_DIV K_ARITH_DIV_R K_ARITH_DIV_S K_ARITH_MOD %token K_ARITH_MOD_R %token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R @@ -766,38 +766,40 @@ argument_opt ; argument_list - : argument - { struct argv_s tmp; - argv_init(&tmp); - argv_add(&tmp, $1); - $$ = tmp; - } - | argument_list ',' argument - { struct argv_s tmp = $1; - argv_add(&tmp, $3); - $$ = tmp; - } - | T_SYMBOL - { struct argv_s tmp; - argv_init(&tmp); - argv_sym_add(&tmp, $1); - $$ = tmp; - } - | argument_list ',' T_SYMBOL - { struct argv_s tmp = $1; - argv_sym_add(&tmp, $3); - $$ = tmp; - } - ; + : argument + { struct argv_s tmp; + argv_init(&tmp); + argv_add(&tmp, $1); + $$ = tmp; + } + | argument_list ',' argument + { struct argv_s tmp = $1; + argv_add(&tmp, $3); + $$ = tmp; + } + | T_SYMBOL + { struct argv_s tmp; + argv_init(&tmp); + argv_sym_add(&tmp, $1); + $$ = tmp; + } + | argument_list ',' T_SYMBOL + { struct argv_s tmp = $1; + argv_sym_add(&tmp, $3); + $$ = tmp; + } + ; argument - : T_STRING - { $$ = vpip_make_string_const($1); } - | T_VECTOR - { $$ = vpip_make_binary_const($1.idx, $1.text); - free($1.text); - } - ; + : T_STRING + { $$ = vpip_make_string_const($1); } + | T_VECTOR + { $$ = vpip_make_binary_const($1.idx, $1.text); + free($1.text); + } + | K_A '<' T_SYMBOL ',' T_NUMBER '>' + { $$ = vpip_make_vthr_A($3, $5); } + ; /* functor operands can only be a list of symbols. */ diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 8c95673e0..8da38a0c4 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -433,6 +433,8 @@ vpiHandle vpip_make_vthr_vector(unsigned base, unsigned wid, bool signed_flag); vpiHandle vpip_make_vthr_word(unsigned base, const char*type); +vpiHandle vpip_make_vthr_A(char*symbol, unsigned index); + /* * This function is called before any compilation to load VPI * modules. This gives the modules a chance to announce their