From a5fd5363b312eafda7e7530304852e4da24f8ae8 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 22 Oct 2012 17:20:43 -0700 Subject: [PATCH] Rewire real value expressions to use a stack instead of register space. This will hopefully improve performance slightly, but also this intended as a model for what to do when I get around to doing the same thing to other data types. --- tgt-vvp/draw_ufunc.c | 13 +- tgt-vvp/draw_vpi.c | 44 +++-- tgt-vvp/eval_expr.c | 61 +++---- tgt-vvp/eval_real.c | 372 +++++++++++++------------------------- tgt-vvp/stmt_assign.c | 16 +- tgt-vvp/vvp_priv.h | 11 +- tgt-vvp/vvp_process.c | 98 +++++----- vvp/codes.h | 13 +- vvp/compile.cc | 88 ++++----- vvp/compile.h | 8 +- vvp/opcodes.txt | 165 ++++++++++------- vvp/parse.y | 37 ++-- vvp/sfunc.cc | 3 + vvp/stop.cc | 1 + vvp/vpi_priv.h | 11 +- vvp/vpi_tasks.cc | 65 ++++--- vvp/vpi_vthr_vector.cc | 2 +- vvp/vthread.cc | 395 ++++++++++++++++++++++++----------------- vvp/vthread.h | 8 +- 19 files changed, 711 insertions(+), 700 deletions(-) diff --git a/tgt-vvp/draw_ufunc.c b/tgt-vvp/draw_ufunc.c index 998d90f77..66942988f 100644 --- a/tgt-vvp/draw_ufunc.c +++ b/tgt-vvp/draw_ufunc.c @@ -46,13 +46,11 @@ static void function_argument_logic(ivl_signal_t port, ivl_expr_t expr) static void function_argument_real(ivl_signal_t port, ivl_expr_t expr) { - int res = draw_eval_real(expr); - /* ports cannot be arrays. */ assert(ivl_signal_dimensions(port) == 0); - fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", port, res); - clr_word(res); + draw_eval_real(expr); + fprintf(vvp_out, " %%store/real v%p_0;\n", port); } static void function_argument_bool(ivl_signal_t port, ivl_expr_t expr) @@ -160,11 +158,10 @@ struct vector_info draw_ufunc_expr(ivl_expr_t expr, unsigned wid) return res; } -int draw_ufunc_real(ivl_expr_t expr) +void draw_ufunc_real(ivl_expr_t expr) { ivl_scope_t def = ivl_expr_def(expr); ivl_signal_t retval = ivl_scope_port(def, 0); - int res = 0; unsigned idx; /* If this is an automatic function, allocate the local storage. */ @@ -188,13 +185,11 @@ int draw_ufunc_real(ivl_expr_t expr) assert(ivl_signal_dimensions(retval) == 0); /* Load the result into a word. */ - res = allocate_word(); - fprintf(vvp_out, " %%load/wr %d, v%p_0;\n", res, retval); + fprintf(vvp_out, " %%load/real v%p_0;\n", retval); /* If this is an automatic function, free the local storage. */ if (ivl_scope_is_auto(def)) { fprintf(vvp_out, " %%free S_%p;\n", def); } - return res; } diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index 1133c8c42..799b43746 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -31,9 +31,12 @@ struct args_info { char*text; int vec_flag; /* True if the vec must be released. */ struct vector_info vec; - /* String Stack position if this argument is a calculated string. */ - int str_flag; - unsigned str_stack; + /* True if this argument is a calculated string. */ + char str_flag; + /* True if this argument is a calculated real. */ + char real_flag; + /* Stack position if this argument is a calculated string. */ + unsigned stack; struct args_info *child; /* Arguments can be nested. */ }; @@ -284,6 +287,7 @@ static void draw_vpi_taskfunc_args(const char*call_string, going to need. We'll need this for making stack references, and also to clean out the stack when done. */ unsigned str_stack_need = 0; + unsigned real_stack_need = 0; /* Figure out how many expressions are going to be evaluated for this task call. I won't need to evaluate expressions @@ -392,11 +396,14 @@ static void draw_vpi_taskfunc_args(const char*call_string, ivl_expr_signed(expr)? "s" : "u"); break; case IVL_VT_REAL: - args[idx].vec_flag = 1; - args[idx].vec.base = draw_eval_real(expr); + draw_eval_real(expr); + args[idx].vec_flag = 0; + args[idx].vec.base = 0; args[idx].vec.wid = 0; - snprintf(buffer, sizeof buffer, - "W<%u,r>", args[idx].vec.base); + args[idx].str_flag = 0; + args[idx].real_flag = 1; + args[idx].stack = real_stack_need; + real_stack_need += 1; break; case IVL_VT_STRING: /* Eval the string into the stack, and tell VPI @@ -406,7 +413,8 @@ static void draw_vpi_taskfunc_args(const char*call_string, args[idx].vec.base = 0; args[idx].vec.wid = 0; args[idx].str_flag = 1; - args[idx].str_stack = str_stack_need; + args[idx].stack = str_stack_need; + args[idx].real_flag = 0; str_stack_need += 1; buffer[0] = 0; break; @@ -425,8 +433,11 @@ static void draw_vpi_taskfunc_args(const char*call_string, /* If this is a string stack reference, then calculate the stack depth and use that to generate the completed string. */ - unsigned pos = str_stack_need - args[idx].str_stack - 1; + unsigned pos = str_stack_need - args[idx].stack - 1; fprintf(vvp_out, ", S<%u,str>",pos); + } else if (args[idx].real_flag) { + unsigned pos = real_stack_need - args[idx].stack - 1; + fprintf(vvp_out, ", W<%u,r>",pos); } else { fprintf(vvp_out, ", %s", args[idx].text); } @@ -450,10 +461,8 @@ static void draw_vpi_taskfunc_args(const char*call_string, free(args); + fprintf(vvp_out, " {%u %u}", real_stack_need, str_stack_need); fprintf(vvp_out, ";\n"); - - if (str_stack_need > 0) - fprintf(vvp_out, " %%pop/str %u;\n", str_stack_need); } void draw_vpi_task_call(ivl_statement_t tnet) @@ -474,7 +483,7 @@ void draw_vpi_task_call(ivl_statement_t tnet) } if (parm_count == 0) { - fprintf(vvp_out, " %s %u %u \"%s\";\n", command, + fprintf(vvp_out, " %s %u %u \"%s\" {0 0};\n", command, ivl_file_table_index(ivl_stmt_file(tnet)), ivl_stmt_lineno(tnet), ivl_stmt_name(tnet)); } else { @@ -509,16 +518,13 @@ struct vector_info draw_vpi_func_call(ivl_expr_t fnet, unsigned wid) return res; } -int draw_vpi_rfunc_call(ivl_expr_t fnet) +void draw_vpi_rfunc_call(ivl_expr_t fnet) { char call_string[1024]; - int res = allocate_word(); - sprintf(call_string, " %%vpi_func/r %u %u \"%s\", %d", + sprintf(call_string, " %%vpi_func/r %u %u \"%s\"", ivl_file_table_index(ivl_expr_file(fnet)), - ivl_expr_lineno(fnet), ivl_expr_name(fnet), res); + ivl_expr_lineno(fnet), ivl_expr_name(fnet)); draw_vpi_taskfunc_args(call_string, 0, fnet); - - return res; } diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 303db2438..4c59512d7 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -277,8 +277,6 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix) */ void draw_eval_expr_into_integer(ivl_expr_t expr, unsigned ix) { - int word; - switch (ivl_expr_value(expr)) { case IVL_VT_BOOL: @@ -287,9 +285,8 @@ void draw_eval_expr_into_integer(ivl_expr_t expr, unsigned ix) break; case IVL_VT_REAL: - word = draw_eval_real(expr); - fprintf(vvp_out, " %%cvt/sr %u, %d;\n", ix, word); - clr_word(word); + draw_eval_real(expr); + fprintf(vvp_out, " %%cvt/sr %u;\n", ix); break; default: @@ -428,19 +425,15 @@ static struct vector_info draw_eq_immediate(ivl_expr_t expr, unsigned ewid, static struct vector_info draw_binary_expr_eq_real(ivl_expr_t expr) { struct vector_info res; - int lword, rword; res.base = allocate_vector(1); res.wid = 1; assert(res.base); - lword = draw_eval_real(ivl_expr_oper1(expr)); - rword = draw_eval_real(ivl_expr_oper2(expr)); + draw_eval_real(ivl_expr_oper1(expr)); + draw_eval_real(ivl_expr_oper2(expr)); - clr_word(lword); - clr_word(rword); - - fprintf(vvp_out, " %%cmp/wr %d, %d;\n", lword, rword); + fprintf(vvp_out, " %%cmp/wr;\n"); switch (ivl_expr_opcode(expr)) { case 'e': @@ -834,36 +827,39 @@ static struct vector_info draw_binary_expr_le_real(ivl_expr_t expr) ivl_expr_t le = ivl_expr_oper1(expr); ivl_expr_t re = ivl_expr_oper2(expr); - int lword = draw_eval_real(le); - int rword = draw_eval_real(re); res.base = allocate_vector(1); res.wid = 1; assert(res.base); - clr_word(lword); - clr_word(rword); - switch (ivl_expr_opcode(expr)) { case '<': - fprintf(vvp_out, " %%cmp/wr %d, %d;\n", lword, rword); + draw_eval_real(le); + draw_eval_real(re); + fprintf(vvp_out, " %%cmp/wr;\n"); fprintf(vvp_out, " %%mov %u, 5, 1;\n", res.base); break; case 'L': /* <= */ - fprintf(vvp_out, " %%cmp/wr %d, %d;\n", lword, rword); + draw_eval_real(le); + draw_eval_real(re); + fprintf(vvp_out, " %%cmp/wr;\n"); fprintf(vvp_out, " %%or 5, 4, 1;\n"); fprintf(vvp_out, " %%mov %u, 5, 1;\n", res.base); break; case '>': - fprintf(vvp_out, " %%cmp/wr %d, %d;\n", rword, lword); + draw_eval_real(re); + draw_eval_real(le); + fprintf(vvp_out, " %%cmp/wr;\n"); fprintf(vvp_out, " %%mov %u, 5, 1;\n", res.base); break; case 'G': /* >= */ - fprintf(vvp_out, " %%cmp/wr %d, %d;\n", rword, lword); + draw_eval_real(re); + draw_eval_real(le); + fprintf(vvp_out, " %%cmp/wr;\n"); fprintf(vvp_out, " %%or 5, 4, 1;\n"); fprintf(vvp_out, " %%mov %u, 5, 1;\n", res.base); break; @@ -2353,13 +2349,9 @@ static void draw_signal_dest(ivl_expr_t expr, struct vector_info res, if (ivl_signal_data_type(sig) == IVL_VT_REAL) { - int tmp; - assert(add_index < 0); - tmp = allocate_word(); - fprintf(vvp_out, " %%load/wr %d, v%p_%u;\n", tmp, sig, word); - fprintf(vvp_out, " %%cvt/vr %u, %d, %u;\n", res.base, tmp, res.wid); - clr_word(tmp); + fprintf(vvp_out, " %%load/real v%p_%u;\n", sig, word); + fprintf(vvp_out, " %%cvt/vr %u, %u;\n", res.base, res.wid); } else if (add_index >= 0) { @@ -3069,7 +3061,7 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t expr, unsigned wid) res.base = allocate_vector(wid); res.wid = wid; assert(res.base); - fprintf(vvp_out, " %%vpi_func %u %u \"%s\", %u, %u;\n", + fprintf(vvp_out, " %%vpi_func %u %u \"%s\", %u, %u {0 0};\n", ivl_file_table_index(ivl_expr_file(expr)), ivl_expr_lineno(expr), ivl_expr_name(expr), res.base, res.wid); @@ -3242,7 +3234,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t expr, unsigned wid) struct vector_info res; ivl_expr_t sub = ivl_expr_oper1(expr); const char *rop = 0; - int word, inv = 0; + int inv = 0; switch (ivl_expr_opcode(expr)) { case '&': rop = "and"; break; @@ -3471,11 +3463,10 @@ static struct vector_info draw_unary_expr(ivl_expr_t expr, unsigned wid) break; case IVL_VT_REAL: - word = draw_eval_real(sub); + draw_eval_real(sub); res.base = allocate_vector(wid); res.wid = wid; - fprintf(vvp_out, " %%cvt/vr %d, %d, %u;\n", res.base, word, wid); - clr_word(word); + fprintf(vvp_out, " %%cvt/vr %d, %u;\n", res.base, wid); break; default: @@ -3485,12 +3476,10 @@ static struct vector_info draw_unary_expr(ivl_expr_t expr, unsigned wid) case 'v': /* Cast a real value to an integer. */ assert(ivl_expr_value(sub) == IVL_VT_REAL); - word = draw_eval_real(sub); + draw_eval_real(sub); res.base = allocate_vector(wid); res.wid = wid; - fprintf(vvp_out, " %%cvt/vr %u, %d, %u;\n", res.base, word, - res.wid); - clr_word(word); + fprintf(vvp_out, " %%cvt/vr %u, %u;\n", res.base, res.wid); break; case 'r': /* Handled in eval_real.c. */ diff --git a/tgt-vvp/eval_real.c b/tgt-vvp/eval_real.c index 6c1c4176e..20b6d5710 100644 --- a/tgt-vvp/eval_real.c +++ b/tgt-vvp/eval_real.c @@ -52,10 +52,8 @@ void clr_word(int res) word_alloc_mask &= ~ (1U << res); } -static int draw_binary_real(ivl_expr_t expr) +static void draw_binary_real(ivl_expr_t expr) { - int l, r = -1; - switch (ivl_expr_opcode(expr)) { case 'E': case 'N': @@ -72,93 +70,52 @@ static int draw_binary_real(ivl_expr_t expr) assert(0); } - l = draw_eval_real(ivl_expr_oper1(expr)); - r = draw_eval_real(ivl_expr_oper2(expr)); + draw_eval_real(ivl_expr_oper1(expr)); + draw_eval_real(ivl_expr_oper2(expr)); switch (ivl_expr_opcode(expr)) { case '+': - fprintf(vvp_out, " %%add/wr %d, %d;\n", l, r); + fprintf(vvp_out, " %%add/wr;\n"); break; case '-': - fprintf(vvp_out, " %%sub/wr %d, %d;\n", l, r); + fprintf(vvp_out, " %%sub/wr;\n"); break; case '*': - fprintf(vvp_out, " %%mul/wr %d, %d;\n", l, r); + fprintf(vvp_out, " %%mul/wr;\n"); break; case '/': - fprintf(vvp_out, " %%div/wr %d, %d;\n", l, r); + fprintf(vvp_out, " %%div/wr;\n"); break; case '%': - fprintf(vvp_out, " %%mod/wr %d, %d;\n", l, r); + fprintf(vvp_out, " %%mod/wr;\n"); break; case 'p': - fprintf(vvp_out, " %%pow/wr %d, %d;\n", l, r); + fprintf(vvp_out, " %%pow/wr;\n"); break; - case 'm': { /* min(l,r) */ - unsigned lab_out = local_count++; - unsigned lab_r = local_count++; - /* If r is NaN, the go out and accept l as result. */ - fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r); - fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 4;\n", thread_count, - lab_out); - /* If l is NaN, the go out and accept r as result. */ - fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l); - fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 4;\n", thread_count, - lab_r); - /* If l <= r then go out. */ - fprintf(vvp_out, " %%cmp/wr %d, %d;\n", r, l); - fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 5;\n", thread_count, - lab_out); - /* At this point we know we want r as the result. */ - fprintf(vvp_out, "T_%u.%u %%mov/wr %d, %d;\n", thread_count, - lab_r, l, r); - fprintf(vvp_out, "T_%u.%u ;\n", thread_count, lab_out); - break; - } + case 'm': + fprintf(vvp_out, " %%min/wr;\n"); + break; - case 'M': { /* max(l,r) */ - unsigned lab_out = local_count++; - unsigned lab_r = local_count++; - /* If r is NaN, the go out and accept l as result. */ - fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r); - fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 4;\n", thread_count, - lab_out); - /* If l is NaN, the go out and accept r as result. */ - fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l); - fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 4;\n", thread_count, - lab_r); - /* if l >= r then go out. */ - fprintf(vvp_out, " %%cmp/wr %d, %d;\n", l, r); - fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 5;\n", thread_count, - lab_out); - - fprintf(vvp_out, "T_%u.%u %%mov/wr %d, %d;\n", thread_count, - lab_r, l, r); - fprintf(vvp_out, "T_%u.%u ;\n", thread_count, lab_out); - break; - } + case 'M': + fprintf(vvp_out, " %%max/wr;\n"); + break; default: fprintf(stderr, "XXXX draw_binary_real(%c)\n", ivl_expr_opcode(expr)); assert(0); } - - if (r >= 0) clr_word(r); - - return l; } -static int draw_number_real(ivl_expr_t expr) +static void draw_number_real(ivl_expr_t expr) { unsigned int idx; - int res = allocate_word(); const char*bits = ivl_expr_bits(expr); unsigned wid = ivl_expr_width(expr); unsigned long mant = 0; @@ -204,14 +161,12 @@ static int draw_number_real(ivl_expr_t expr) if (negate) vexp |= 0x4000; - fprintf(vvp_out, " %%loadi/wr %d, %lu, %d; load(num)= %c%lu (wid=%u)\n", - res, mant, vexp, (vexp&0x4000)? '-' : '+', mant, wid); - return res; + fprintf(vvp_out, " %%pushi/real %lu, %d; load(num)= %c%lu (wid=%u)\n", + mant, vexp, (vexp&0x4000)? '-' : '+', mant, wid); } -static int draw_realnum_real(ivl_expr_t expr) +static void draw_realnum_real(ivl_expr_t expr) { - int res = allocate_word(); double value = ivl_expr_dvalue(expr); double fract; @@ -222,18 +177,18 @@ static int draw_realnum_real(ivl_expr_t expr) /* Handle the special case that the value is +-inf. */ if (isinf(value)) { if (value > 0) - fprintf(vvp_out, " %%loadi/wr %d, 0, %d; load=+inf\n", - res, 0x3fff); + fprintf(vvp_out, " %%pushi/real 0, %d; load=+inf\n", + 0x3fff); else - fprintf(vvp_out, " %%loadi/wr %d, 0, %d; load=-inf\n", - res, 0x7fff); - return res; + fprintf(vvp_out, " %%pushi/real 0, %d; load=-inf\n", + 0x7fff); + return; } /* Handle the special case that the value is NaN. */ if (value != value) { - fprintf(vvp_out, " %%loadi/wr %d, 1, %d; load=NaN\n", - res, 0x3fff); - return res; + fprintf(vvp_out, " %%pushi/real 1, %d; load=NaN\n", + 0x3fff); + return; } if (value < 0) { @@ -251,8 +206,8 @@ static int draw_realnum_real(ivl_expr_t expr) assert(vexp < 0x2000); vexp += sign; - fprintf(vvp_out, " %%loadi/wr %d, %lu, %d; load=%#g\n", - res, mant, vexp, ivl_expr_dvalue(expr)); + fprintf(vvp_out, " %%pushi/real %lu, %d; load=%#g\n", + mant, vexp, ivl_expr_dvalue(expr)); /* Capture the residual bits, if there are any. Note that an IEEE754 mantissa has 52 bits, 31 of which were accounted @@ -268,59 +223,51 @@ static int draw_realnum_real(ivl_expr_t expr) vexp += sign; if (mant != 0) { - int tmp_word = allocate_word(); - fprintf(vvp_out, " %%loadi/wr %d, %lu, %d; load=%#g\n", - tmp_word, mant, vexp, ivl_expr_dvalue(expr)); - fprintf(vvp_out, " %%add/wr %d, %d;\n", res, tmp_word); - clr_word(tmp_word); + fprintf(vvp_out, " %%pushi/real %lu, %d; load=%#g\n", + mant, vexp, ivl_expr_dvalue(expr)); + fprintf(vvp_out, " %%add/wr;\n"); } - - return res; } /* * The real value of a logic expression is the integer value of the * expression converted to real. */ -static int draw_real_logic_expr(ivl_expr_t expr, int stuff_ok_flag) +static void draw_real_logic_expr(ivl_expr_t expr, int stuff_ok_flag) { - int res = allocate_word(); struct vector_info sv = draw_eval_expr(expr, stuff_ok_flag); const char*sign_flag = ivl_expr_signed(expr)? "/s" : ""; if (sv.wid > 64) { - fprintf(vvp_out, " %%cvt/rv%s %d, %u, %u;\n", - sign_flag, res, sv.base, sv.wid); + fprintf(vvp_out, " %%cvt/rv%s %u, %u;\n", + sign_flag, sv.base, sv.wid); } else { + int res = allocate_word(); fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n", sign_flag, res, sv.base, sv.wid); if (ivl_expr_signed(expr)) - fprintf(vvp_out, " %%cvt/rs %d, %d;\n", res, res); + fprintf(vvp_out, " %%cvt/rs %d;\n", res); else - fprintf(vvp_out, " %%cvt/ru %d, %d;\n", res, res); + fprintf(vvp_out, " %%cvt/ru %d;\n", res); + clr_word(res); } clr_vector(sv); - - return res; } -static int draw_sfunc_real(ivl_expr_t expr) +static void draw_sfunc_real(ivl_expr_t expr) { - int res; - switch (ivl_expr_value(expr)) { case IVL_VT_REAL: if (ivl_expr_parms(expr) == 0) { - res = allocate_word(); - fprintf(vvp_out, " %%vpi_func/r %u %u \"%s\", %d;\n", + fprintf(vvp_out, " %%vpi_func/r %u %u \"%s\" {0 0};\n", ivl_file_table_index(ivl_expr_file(expr)), - ivl_expr_lineno(expr), ivl_expr_name(expr), res); + ivl_expr_lineno(expr), ivl_expr_name(expr)); } else { - res = draw_vpi_rfunc_call(expr); + draw_vpi_rfunc_call(expr); } break; @@ -328,55 +275,53 @@ static int draw_sfunc_real(ivl_expr_t expr) /* If the value of the sfunc is a vector, then evaluate it as a vector, then convert the result to a real (via an index register) for the result. */ - res = draw_real_logic_expr(expr, 0); + draw_real_logic_expr(expr, 0); break; default: assert(0); - res = -1; } - return res; } -static int draw_signal_real_real(ivl_expr_t expr) +static void draw_signal_real_real(ivl_expr_t expr) { ivl_signal_t sig = ivl_expr_signal(expr); - int res = allocate_word(); if (ivl_signal_dimensions(sig) == 0) { - fprintf(vvp_out, " %%load/wr %d, v%p_0;\n", res, sig); - return res; + fprintf(vvp_out, " %%load/real v%p_0;\n", sig); + return; } ivl_expr_t word_ex = ivl_expr_oper1(expr); int word_ix = allocate_word(); draw_eval_expr_into_integer(word_ex, word_ix); - fprintf(vvp_out, " %%load/ar %d, v%p, %d;\n", res, sig, word_ix); + fprintf(vvp_out, " %%load/ar v%p, %d;\n", sig, word_ix); clr_word(word_ix); - return res; } -static int draw_signal_real(ivl_expr_t expr) +static void draw_signal_real(ivl_expr_t expr) { ivl_signal_t sig = ivl_expr_signal(expr); switch (ivl_signal_data_type(sig)) { case IVL_VT_LOGIC: - return draw_real_logic_expr(expr, 0); + draw_real_logic_expr(expr, 0); + return; case IVL_VT_REAL: - return draw_signal_real_real(expr); + draw_signal_real_real(expr); + return; default: fprintf(stderr, "vvp.tgt error: signal_data_type=%d\n", ivl_signal_data_type(sig)); assert(0); - return -1; + return; } } /* If we have nested ternary operators they are likely tail recursive. * This code is structured to allow this recursion without overflowing * the available thread words. */ -static int draw_ternary_real(ivl_expr_t expr) +static void draw_ternary_real(ivl_expr_t expr) { ivl_expr_t cond = ivl_expr_oper1(expr); ivl_expr_t true_ex = ivl_expr_oper2(expr); @@ -385,11 +330,8 @@ static int draw_ternary_real(ivl_expr_t expr) struct vector_info tst; unsigned lab_true = local_count++; - unsigned lab_move = local_count++; unsigned lab_out = local_count++; - int tru, fal, res; - /* Evaluate the ternary condition. */ tst = draw_eval_expr(cond, STUFF_OK_XZ|STUFF_OK_RO); if ((tst.base >= 4) && (tst.wid > 1)) { @@ -410,127 +352,59 @@ static int draw_ternary_real(ivl_expr_t expr) fprintf(vvp_out, " %%jmp/1 T_%u.%u, %u;\n", thread_count, lab_true, tst.base); - /* Evaluate the false expression and copy it to the result word. */ - fal = draw_eval_real(false_ex); - res = allocate_word(); - fprintf(vvp_out, " %%mov/wr %d, %d;\n", res, fal); - clr_word(fal); + /* Evaluate the false expression. */ + draw_eval_real(false_ex); fprintf(vvp_out, " %%jmp/0 T_%u.%u, %u; End of false expr.\n", thread_count, lab_out, tst.base); - /* Evaluate the true expression. */ - fprintf(vvp_out, "T_%u.%u ;\n", thread_count, lab_true); - tru = draw_eval_real(true_ex); - fprintf(vvp_out, " %%jmp/1 T_%u.%u, %u; End of true expr.\n", - thread_count, lab_move, tst.base); - /* If the conditional is undefined then blend the real words. */ - fprintf(vvp_out, " %%blend/wr %d, %d;\n", res, tru); + draw_eval_real(true_ex); + fprintf(vvp_out, " %%blend/wr;\n"); fprintf(vvp_out, " %%jmp T_%u.%u; End of blend\n", thread_count, lab_out); - /* If we only need the true result then copy it to the result word. */ - fprintf(vvp_out, "T_%u.%u ; Move true result.\n", - thread_count, lab_move); - fprintf(vvp_out, " %%mov/wr %d, %d;\n", res, tru); - clr_word(tru); + /* Evaluate the true expression. */ + fprintf(vvp_out, "T_%u.%u ;\n", thread_count, lab_true); + draw_eval_real(true_ex); /* This is the out label. */ fprintf(vvp_out, "T_%u.%u ;\n", thread_count, lab_out); clr_vector(tst); - - return res; } -static int increment(ivl_expr_t e, int s, bool pre) +static void increment(ivl_expr_t e, bool pre) { - ivl_signal_t sig; - int r; - int one; - - sig = ivl_expr_signal(e); - r = s; - - /* create a temporary word to hold value 1.0 */ - one = allocate_word(); - fprintf(vvp_out, " %%loadi/wr %d, 1, 0x1000; load 1.0\n", one); - - if (!pre) { - /* - * post-increment must return the non-incremented value. - * Therefore, copy the current value in a new word and return - * it. - */ - r = allocate_word(); - fprintf(vvp_out, " %%mov/wr %d, %d;\n", r, s); - } - - fprintf(vvp_out, " %%add/wr %d, %d;\n", s, one); - fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", sig, s); - - return r; + ivl_signal_t sig = ivl_expr_signal(e); + fprintf(vvp_out, " %%load/real v%p_0;\n", sig); + if (!pre) fprintf(vvp_out, " %%dup/real;\n"); + fprintf(vvp_out, " %%pushi/real 1, 0x1000;\n"); + fprintf(vvp_out, " %%add/wr;\n"); + if ( pre) fprintf(vvp_out, " %%dup/real;\n"); + fprintf(vvp_out, " %%store/real v%p_0;\n", sig); } -static inline int pre_increment(ivl_expr_t e, int s) +static void decrement(ivl_expr_t e, bool pre) { - return increment(e, s, true); + ivl_signal_t sig = ivl_expr_signal(e); + fprintf(vvp_out, " %%load/real v%p_0;\n", sig); + if (!pre) fprintf(vvp_out, " %%dup/real;\n"); + fprintf(vvp_out, " %%pushi/real 1, 0x1000;\n"); + fprintf(vvp_out, " %%sub/wr;\n"); + if ( pre) fprintf(vvp_out, " %%dup/real;\n"); + fprintf(vvp_out, " %%store/real v%p_0;\n", sig); } -static inline int post_increment(ivl_expr_t e, int s) -{ - return increment(e, s, false); -} - -static int decrement(ivl_expr_t e, int s, bool pre) -{ - ivl_signal_t sig; - int r; - int one; - - sig = ivl_expr_signal(e); - r = s; - - /* create a temporary word to hold value 1.0 */ - one = allocate_word(); - fprintf(vvp_out, " %%loadi/wr %d, 1, 0x1000; load 1.0\n", one); - - if (!pre) { - /* - * post-decrement must return the non-incremented value. - * Therefore, copy the current value in a new word and return - * it. - */ - r = allocate_word(); - fprintf(vvp_out, " %%mov/wr %d, %d;\n", r, s); - } - - fprintf(vvp_out, " %%sub/wr %d, %d;\n", s, one); - fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", sig, s); - - return r; -} - -static inline int pre_decrement(ivl_expr_t e, int s) -{ - return decrement(e, s, true); -} - -static inline int post_decrement(ivl_expr_t e, int s) -{ - return decrement(e, s, false); -} - -static int draw_unary_real(ivl_expr_t expr) +static void draw_unary_real(ivl_expr_t expr) { ivl_expr_t sube; - int sub; /* If the opcode is a ~ or a ! then the sub expression must not be * a real expression, so use vector evaluation and then convert * that result to a real value. */ if ((ivl_expr_opcode(expr) == '~') || (ivl_expr_opcode(expr) == '!')) { - return draw_real_logic_expr(expr, STUFF_OK_XZ); + draw_real_logic_expr(expr, STUFF_OK_XZ); + return; } sube = ivl_expr_oper1(expr); @@ -541,30 +415,28 @@ static int draw_unary_real(ivl_expr_t expr) assert(ivl_expr_value(sube) != IVL_VT_REAL); res = draw_eval_expr(sube, 1); if (ivl_expr_signed(sube)) suffix = "/s"; - sub = allocate_word(); - fprintf(vvp_out, " %%cvt/rv%s %d, %u, %u;\n", suffix, sub, - res.base, res.wid); + fprintf(vvp_out, " %%cvt/rv%s %u, %u;\n", suffix, res.base, res.wid); clr_vector(res); - return sub; + return; } - sub = draw_eval_real(sube); - if (ivl_expr_opcode(expr) == '+') - return sub; + if (ivl_expr_opcode(expr) == '+') { + draw_eval_real(sube); + return; + } if (ivl_expr_opcode(expr) == '-') { - int res = allocate_word(); - fprintf(vvp_out, " %%loadi/wr %d, 0, 0; load 0.0\n", res); - fprintf(vvp_out, " %%sub/wr %d, %d;\n", res, sub); - - clr_word(sub); - return res; + fprintf(vvp_out, " %%pushi/real 0, 0; load 0.0\n"); + draw_eval_real(sube); + fprintf(vvp_out, " %%sub/wr;\n"); + return; } if (ivl_expr_opcode(expr) == 'm') { /* abs() */ - fprintf(vvp_out, " %%abs/wr %d, %d;\n", sub, sub); - return sub; + draw_eval_real(sube); + fprintf(vvp_out, " %%abs/wr;\n"); + return; } if (ivl_expr_opcode(expr) == 'v') { /* Handled in eval_expr.c. */ @@ -573,70 +445,71 @@ static int draw_unary_real(ivl_expr_t expr) assert(0); } - switch (ivl_expr_opcode(expr)) { - case 'I': - return pre_increment(sube, sub); + switch (ivl_expr_opcode(expr)) { + case 'I': + increment(sube, true); + return; + case 'i': + increment(sube, false); + return; - case 'i': - return post_increment(sube, sub); - - case 'D': - return pre_decrement(sube, sub); - - case 'd': - return post_decrement(sube, sub); + case 'D': + decrement(sube, true); + return; + case 'd': + decrement(sube, false); + return; } fprintf(stderr, "vvp.tgt error: unhandled real unary operator: %c.\n", ivl_expr_opcode(expr)); assert(0); - return 0; } -int draw_eval_real(ivl_expr_t expr) +void draw_eval_real(ivl_expr_t expr) { - int res = 0; /* If this expression/sub-expression is not real then we need * to evaluate it as a bit value and then convert the bit based * result to a real value. This is required to get integer * division to work correctly. */ if (ivl_expr_value(expr) != IVL_VT_REAL) { - return draw_real_logic_expr(expr, STUFF_OK_XZ); + draw_real_logic_expr(expr, STUFF_OK_XZ); + return; } switch (ivl_expr_type(expr)) { case IVL_EX_BINARY: - res = draw_binary_real(expr); + draw_binary_real(expr); break; case IVL_EX_NUMBER: - res = draw_number_real(expr); + draw_number_real(expr); break; case IVL_EX_REALNUM: - res = draw_realnum_real(expr); + draw_realnum_real(expr); break; case IVL_EX_SFUNC: - res = draw_sfunc_real(expr); + draw_sfunc_real(expr); break; case IVL_EX_SIGNAL: - res = draw_signal_real(expr); + draw_signal_real(expr); break; case IVL_EX_TERNARY: - res = draw_ternary_real(expr); + draw_ternary_real(expr); break; case IVL_EX_UFUNC: - res = draw_ufunc_real(expr); + draw_ufunc_real(expr); break; case IVL_EX_UNARY: - res = draw_unary_real(expr); + draw_unary_real(expr); break; default: @@ -645,22 +518,23 @@ int draw_eval_real(ivl_expr_t expr) const char*sign_flag = ivl_expr_signed(expr)? "/s" : ""; clr_vector(sv); - res = allocate_word(); + int res = allocate_word(); fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n", sign_flag, res, sv.base, sv.wid); - fprintf(vvp_out, " %%cvt/rs %d, %d;\n", res, res); + fprintf(vvp_out, " %%cvt/rs %d;\n", res); + + clr_word(res); } else { fprintf(stderr, "XXXX Evaluate real expression (%d)\n", ivl_expr_type(expr)); fprintf(vvp_out, " ; XXXX Evaluate real expression (%d)\n", ivl_expr_type(expr)); - return 0; + return; } break; } - return res; } diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 3badf40d7..0a771311c 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -530,7 +530,7 @@ static int show_stmt_assign_vector(ivl_statement_t net) result to a vector. Then store that vector into the l-value. */ if (ivl_expr_value(rval) == IVL_VT_REAL) { - int word = draw_eval_real(rval); + draw_eval_real(rval); /* This is the accumulated with of the l-value of the assignment. */ unsigned wid = ivl_stmt_lwidth(net); @@ -546,10 +546,7 @@ static int show_stmt_assign_vector(ivl_statement_t net) vvp_errors += 1; } - fprintf(vvp_out, " %%cvt/vr %u, %d, %u;\n", - res.base, word, res.wid); - - clr_word(word); + fprintf(vvp_out, " %%cvt/vr %u, %u;\n", res.base, res.wid); } else { res = draw_eval_expr(rval, 0); @@ -696,13 +693,12 @@ static int show_stmt_assign_vector(ivl_statement_t net) */ static int show_stmt_assign_sig_real(ivl_statement_t net) { - int res; ivl_lval_t lval; ivl_signal_t var; assert(ivl_stmt_opcode(net) == 0); - res = draw_eval_real(ivl_stmt_rval(net)); + draw_eval_real(ivl_stmt_rval(net)); assert(ivl_stmt_lvals(net) == 1); lval = ivl_stmt_lval(net, 0); @@ -710,8 +706,7 @@ static int show_stmt_assign_sig_real(ivl_statement_t net) assert(var != 0); if (ivl_signal_dimensions(var) == 0) { - clr_word(res); - fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", var, res); + fprintf(vvp_out, " %%store/real v%p_0;\n", var); return 0; } @@ -723,9 +718,8 @@ static int show_stmt_assign_sig_real(ivl_statement_t net) int word_ix = allocate_word(); draw_eval_expr_into_integer(word_ex, word_ix); // Generate an assignment to write to the array. - fprintf(vvp_out, " %%set/ar v%p, %d, %d;\n", var, word_ix, res); + fprintf(vvp_out, " %%store/reala v%p, %d;\n", var, word_ix); - clr_word(res); clr_word(word_ix); return 0; diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index c0dff49cc..01752a110 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -100,7 +100,7 @@ extern int draw_scope(ivl_scope_t scope, ivl_scope_t parent); extern void draw_lpm_mux(ivl_lpm_t net); extern struct vector_info draw_ufunc_expr(ivl_expr_t expr, unsigned wid); -extern int draw_ufunc_real(ivl_expr_t expr); +extern void draw_ufunc_real(ivl_expr_t expr); extern void pad_expr_in_place(ivl_expr_t expr, struct vector_info res, unsigned swid); @@ -129,7 +129,7 @@ extern void draw_vpi_task_call(ivl_statement_t net); extern struct vector_info draw_vpi_func_call(ivl_expr_t expr, unsigned wid); -extern int draw_vpi_rfunc_call(ivl_expr_t expr); +extern void draw_vpi_rfunc_call(ivl_expr_t expr); /* * Enumeration draw routine. @@ -298,11 +298,10 @@ extern long get_number_immediate(ivl_expr_t ex); extern uint64_t get_number_immediate64(ivl_expr_t ex); /* - * draw_eval_real evaluates real value expressions. The return code - * from the function is the index of the word register that contains - * the result. + * draw_eval_real evaluates real value expressions. The result of the + * evaluation is the real result in the top of the real expression stack. */ -extern int draw_eval_real(ivl_expr_t ex); +extern void draw_eval_real(ivl_expr_t ex); /* * draw_eval_bool64 evaluates a bool expression. The return code from diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 88ffa9482..e352fcccf 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -39,9 +39,10 @@ unsigned transient_id = 0; * executable code for the processes. */ -/* Support a non-blocking assignment to a real array word. */ +/* Support a non-blocking assignment to a real array word. The real + value to be written is already in the top of the stack. */ static void assign_to_array_r_word(ivl_signal_t lsig, ivl_expr_t word_ix, - unsigned bit, uint64_t delay, + uint64_t delay, ivl_expr_t dexp, unsigned nevents) { unsigned skip_assign = transient_id++; @@ -62,12 +63,12 @@ static void assign_to_array_r_word(ivl_signal_t lsig, ivl_expr_t word_ix, /* Calculated delay... */ int delay_index = allocate_word(); draw_eval_expr_into_integer(dexp, delay_index); - fprintf(vvp_out, " %%assign/ar/d v%p, %d, %u;\n", lsig, - delay_index, bit); + fprintf(vvp_out, " %%assign/ar/d v%p, %d;\n", lsig, + delay_index); clr_word(delay_index); } else if (nevents != 0) { /* Event control delay... */ - fprintf(vvp_out, " %%assign/ar/e v%p, %u;\n", lsig, bit); + fprintf(vvp_out, " %%assign/ar/e v%p;\n", lsig); } else { /* Constant delay... */ unsigned long low_d = delay % UINT64_C(0x100000000); @@ -81,12 +82,12 @@ static void assign_to_array_r_word(ivl_signal_t lsig, ivl_expr_t word_ix, int delay_index = allocate_word(); fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n", delay_index, low_d, hig_d); - fprintf(vvp_out, " %%assign/ar/d v%p, %d, %u;\n", lsig, - delay_index, bit); + fprintf(vvp_out, " %%assign/ar/d v%p, %d;\n", lsig, + delay_index); clr_word(delay_index); } else { - fprintf(vvp_out, " %%assign/ar v%p, %lu, %u;\n", - lsig, low_d, bit); + fprintf(vvp_out, " %%assign/ar v%p, %lu;\n", + lsig, low_d); } } @@ -376,8 +377,6 @@ static int show_stmt_assign_nb_real(ivl_statement_t net) ivl_expr_t del = ivl_stmt_delay_expr(net); /* variables for the selection of word from an array. */ unsigned long use_word = 0; - /* thread address for a word value. */ - int word; uint64_t delay = 0; unsigned nevents = ivl_stmt_nevent(net); @@ -395,13 +394,12 @@ static int show_stmt_assign_nb_real(ivl_statement_t net) } /* Evaluate the r-value */ - word = draw_eval_real(rval); + draw_eval_real(rval); if (ivl_signal_dimensions(sig) > 0) { ivl_expr_t word_ix = ivl_lval_idx(lval); assert(word_ix); - assign_to_array_r_word(sig, word_ix, word, delay, del, nevents); - clr_word(word); + assign_to_array_r_word(sig, word_ix, delay, del, nevents); return 0; } @@ -410,12 +408,12 @@ static int show_stmt_assign_nb_real(ivl_statement_t net) assert(nevents == 0); int delay_index = allocate_word(); draw_eval_expr_into_integer(del, delay_index); - fprintf(vvp_out, " %%assign/wr/d v%p_%lu, %d, %d;\n", - sig, use_word, delay_index, word); + fprintf(vvp_out, " %%assign/wr/d v%p_%lu, %d;\n", + sig, use_word, delay_index); clr_word(delay_index); } else if (nevents) { - fprintf(vvp_out, " %%assign/wr/e v%p_%lu, %d;\n", - sig, use_word, word); + fprintf(vvp_out, " %%assign/wr/e v%p_%lu;\n", + sig, use_word); } else { unsigned long low_d = delay % UINT64_C(0x100000000); unsigned long hig_d = delay / UINT64_C(0x100000000); @@ -428,17 +426,15 @@ static int show_stmt_assign_nb_real(ivl_statement_t net) int delay_index = allocate_word(); fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n", delay_index, low_d, hig_d); - fprintf(vvp_out, " %%assign/wr/d v%p_%lu, %d, %d;\n", - sig, use_word, delay_index, word); + fprintf(vvp_out, " %%assign/wr/d v%p_%lu, %d;\n", + sig, use_word, delay_index); clr_word(delay_index); } else { - fprintf(vvp_out, " %%assign/wr v%p_%lu, %lu, %d;\n", - sig, use_word, low_d, word); + fprintf(vvp_out, " %%assign/wr v%p_%lu, %lu;\n", + sig, use_word, low_d); } } - clr_word(word); - return 0; } @@ -525,7 +521,7 @@ static int show_stmt_assign_nb(ivl_statement_t net) value. Evaluate the real expression, then convert the result to a vector. */ if (ivl_expr_value(rval) == IVL_VT_REAL) { - int word = draw_eval_real(rval); + draw_eval_real(rval); /* This is the accumulated with of the l-value of the assignment. */ wid = ivl_stmt_lwidth(net); @@ -541,10 +537,8 @@ static int show_stmt_assign_nb(ivl_statement_t net) vvp_errors += 1; } - fprintf(vvp_out, " %%cvt/vr %u, %d, %u;\n", - res.base, word, res.wid); - - clr_word(word); + fprintf(vvp_out, " %%cvt/vr %u, %u;\n", + res.base, res.wid); } else { res = draw_eval_expr(rval, 0); @@ -747,7 +741,6 @@ static int show_stmt_case_r(ivl_statement_t net, ivl_scope_t sscope) { int rc = 0; ivl_expr_t expr = ivl_stmt_cond_expr(net); - int cond = draw_eval_real(expr); unsigned count = ivl_stmt_case_count(net); unsigned local_base = local_count; @@ -756,6 +749,11 @@ static int show_stmt_case_r(ivl_statement_t net, ivl_scope_t sscope) show_stmt_file_line(net, "Case statement."); + /* Build the reference value into the top of the stack. All + the case comparisons will make duplicates of this value in + order to do their tests. */ + draw_eval_real(expr); + local_count += count + 1; /* First draw the branch table. All the non-default cases @@ -765,26 +763,23 @@ static int show_stmt_case_r(ivl_statement_t net, ivl_scope_t sscope) for (idx = 0 ; idx < count ; idx += 1) { ivl_expr_t cex = ivl_stmt_case_expr(net, idx); - int cvec; if (cex == 0) { default_case = idx; continue; } - cvec = draw_eval_real(cex); - - fprintf(vvp_out, " %%cmp/wr %d, %d;\n", cond, cvec); + /* The referene value... */ + fprintf(vvp_out, " %%dup/real;\n"); + /* The guard value... */ + draw_eval_real(cex); + /* The comparison. */ + fprintf(vvp_out, " %%cmp/wr;\n"); fprintf(vvp_out, " %%jmp/1 T_%u.%u, 4;\n", thread_count, local_base+idx); - /* Done with the guard expression value. */ - clr_word(cvec); } - /* Done with the case expression. */ - clr_word(cond); - /* Emit code for the case default. The above jump table will fall through to this statement. */ if (default_case < count) { @@ -812,11 +807,15 @@ static int show_stmt_case_r(ivl_statement_t net, ivl_scope_t sscope) /* The out of the case. */ fprintf(vvp_out, "T_%u.%u ;\n", thread_count, local_base+count); + fprintf(vvp_out, " %%pop/real 1;\n"); return rc; } -static void force_real_to_lval(ivl_statement_t net, int res) +/* + * The real value is already pushed to the top of the real value stack. + */ +static void force_real_to_lval(ivl_statement_t net) { const char*command_name; ivl_lval_t lval; @@ -845,7 +844,7 @@ static void force_real_to_lval(ivl_statement_t net, int res) /* L-Value must be a signal: reg or wire */ assert(lsig != 0); - fprintf(vvp_out, " %s v%p_0, %d;\n", command_name, lsig, res); + fprintf(vvp_out, " %s v%p_0;\n", command_name, lsig); } @@ -1049,12 +1048,10 @@ static int show_stmt_cassign(ivl_statement_t net) sig = ivl_lval_sig(ivl_stmt_lval(net, 0)); if (sig && ivl_signal_data_type(sig) == IVL_VT_REAL) { - int res; - res = draw_eval_real(ivl_stmt_rval(net)); - clr_word(res); + draw_eval_real(ivl_stmt_rval(net)); + force_real_to_lval(net); - force_real_to_lval(net, res); } else { struct vector_info rvec; @@ -1230,9 +1227,8 @@ static int show_stmt_delayx(ivl_statement_t net, ivl_scope_t sscope) } case IVL_VT_REAL: { - int word = draw_eval_real(expr); - fprintf(vvp_out, " %%cvt/ur 0, %d;\n", word); - clr_word(word); + draw_eval_real(expr); + fprintf(vvp_out, " %%cvt/ur 0;\n"); break; } @@ -1272,12 +1268,10 @@ static int show_stmt_force(ivl_statement_t net) sig = ivl_lval_sig(ivl_stmt_lval(net, 0)); if (sig && ivl_signal_data_type(sig) == IVL_VT_REAL) { - int res; - res = draw_eval_real(ivl_stmt_rval(net)); - clr_word(res); + draw_eval_real(ivl_stmt_rval(net)); + force_real_to_lval(net); - force_real_to_lval(net, res); } else { struct vector_info rvec; diff --git a/vvp/codes.h b/vvp/codes.h index f34b48c31..9cc38f20a 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -93,6 +93,7 @@ extern bool of_DISABLE(vthread_t thr, vvp_code_t code); extern bool of_DIV(vthread_t thr, vvp_code_t code); extern bool of_DIV_S(vthread_t thr, vvp_code_t code); extern bool of_DIV_WR(vthread_t thr, vvp_code_t code); +extern bool of_DUP_REAL(vthread_t thr, vvp_code_t code); extern bool of_END(vthread_t thr, vvp_code_t code); extern bool of_EVCTL(vthread_t thr, vvp_code_t code); extern bool of_EVCTLC(vthread_t thr, vvp_code_t code); @@ -126,18 +127,18 @@ extern bool of_LOAD_AVP0(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t code); extern bool of_LOAD_DAR(vthread_t thr, vvp_code_t code); +extern bool of_LOAD_REAL(vthread_t thr, vvp_code_t code); extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VP0_S(vthread_t thr, vvp_code_t code); -extern bool of_LOAD_WR(vthread_t thr, vvp_code_t code); extern bool of_LOAD_X1P(vthread_t thr, vvp_code_t code); -extern bool of_LOADI_WR(vthread_t thr, vvp_code_t code); +extern bool of_MAX_WR(vthread_t thr, vvp_code_t code); +extern bool of_MIN_WR(vthread_t thr, vvp_code_t code); extern bool of_MOD(vthread_t thr, vvp_code_t code); extern bool of_MOD_S(vthread_t thr, vvp_code_t code); extern bool of_MOD_WR(vthread_t thr, vvp_code_t code); extern bool of_MOV(vthread_t thr, vvp_code_t code); -extern bool of_MOV_WR(vthread_t thr, vvp_code_t code); extern bool of_MOV_WU(vthread_t thr, vvp_code_t code); extern bool of_MOVI(vthread_t thr, vvp_code_t code); extern bool of_MUL(vthread_t thr, vvp_code_t code); @@ -152,27 +153,29 @@ extern bool of_NORR(vthread_t thr, vvp_code_t code); extern bool of_OR(vthread_t thr, vvp_code_t code); extern bool of_ORR(vthread_t thr, vvp_code_t code); extern bool of_PAD(vthread_t thr, vvp_code_t code); +extern bool of_POP_REAL(vthread_t thr, vvp_code_t code); extern bool of_POP_STR(vthread_t thr, vvp_code_t code); extern bool of_POW(vthread_t thr, vvp_code_t code); extern bool of_POW_S(vthread_t thr, vvp_code_t code); extern bool of_POW_WR(vthread_t thr, vvp_code_t code); extern bool of_PUSHI_STR(vthread_t thr, vvp_code_t code); +extern bool of_PUSHI_REAL(vthread_t thr, vvp_code_t code); extern bool of_PUSHV_STR(vthread_t thr, vvp_code_t code); extern bool of_PUTC_STR_V(vthread_t thr, vvp_code_t code); extern bool of_RELEASE_NET(vthread_t thr, vvp_code_t code); extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code); extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code); -extern bool of_SET_AR(vthread_t thr, vvp_code_t code); extern bool of_SET_AV(vthread_t thr, vvp_code_t code); extern bool of_SET_DAR(vthread_t thr, vvp_code_t code); extern bool of_SET_VEC(vthread_t thr, vvp_code_t code); -extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code); extern bool of_SET_X0(vthread_t thr, vvp_code_t code); extern bool of_SET_X0_X(vthread_t thr, vvp_code_t code); extern bool of_SHIFTL_I0(vthread_t thr, vvp_code_t code); extern bool of_SHIFTR_I0(vthread_t thr, vvp_code_t code); extern bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t code); extern bool of_STORE_OBJ(vthread_t thr, vvp_code_t code); +extern bool of_STORE_REAL(vthread_t thr, vvp_code_t code); +extern bool of_STORE_REALA(vthread_t thr, vvp_code_t code); extern bool of_STORE_STR(vthread_t thr, vvp_code_t code); extern bool of_SUB(vthread_t thr, vvp_code_t code); extern bool of_SUB_WR(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index 6dd05a13f..78ff817d5 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -84,17 +84,17 @@ struct opcode_table_s { }; static const struct opcode_table_s opcode_table[] = { - { "%abs/wr", of_ABS_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%abs/wr", of_ABS_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%add", of_ADD, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%add/wr", of_ADD_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%add/wr", of_ADD_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%addi", of_ADDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%alloc", of_ALLOC, 1, {OA_VPI_PTR, OA_NONE, OA_NONE} }, { "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%andi", of_ANDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%assign/ar",of_ASSIGN_AR,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} }, - { "%assign/ar/d",of_ASSIGN_ARD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} }, - { "%assign/ar/e",of_ASSIGN_ARE,2,{OA_ARR_PTR,OA_BIT1, OA_NONE} }, + { "%assign/ar",of_ASSIGN_AR,2,{OA_ARR_PTR,OA_BIT1, OA_NONE} }, + { "%assign/ar/d",of_ASSIGN_ARD,2,{OA_ARR_PTR,OA_BIT1, OA_NONE} }, + { "%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} }, @@ -104,22 +104,22 @@ static const struct opcode_table_s opcode_table[] = { { "%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/wr", of_ASSIGN_WR, 3,{OA_VPI_PTR, OA_BIT1, OA_BIT2} }, - { "%assign/wr/d",of_ASSIGN_WRD,3,{OA_VPI_PTR, OA_BIT1, OA_BIT2} }, - { "%assign/wr/e",of_ASSIGN_WRE,2,{OA_VPI_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} }, { "%assign/x0",of_ASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, - { "%blend", of_BLEND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%blend/wr", of_BLEND_WR,2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%blend", of_BLEND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%blend/wr", of_BLEND_WR,0, {OA_NONE, OA_NONE, OA_NONE} }, { "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%cassign/link",of_CASSIGN_LINK,2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} }, { "%cassign/v",of_CASSIGN_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, - { "%cassign/wr",of_CASSIGN_WR,2,{OA_FUNC_PTR,OA_BIT1, OA_NONE} }, + { "%cassign/wr",of_CASSIGN_WR,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%cassign/x0",of_CASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, { "%cast2", of_CAST2, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cmp/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cmp/str",of_CMPSTR, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%cmp/wr", of_CMPWR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%cmp/wr", of_CMPWR, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%cmp/ws", of_CMPWS, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%cmp/wu", of_CMPWU, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%cmp/x", of_CMPX, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, @@ -128,13 +128,13 @@ static const struct opcode_table_s opcode_table[] = { { "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%concat/str",of_CONCAT_STR,0,{OA_NONE, OA_NONE, OA_NONE} }, { "%concati/str",of_CONCATI_STR,1,{OA_STRING,OA_NONE, OA_NONE} }, - { "%cvt/rs", of_CVT_RS, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, - { "%cvt/ru", of_CVT_RU, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, - { "%cvt/rv", of_CVT_RV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%cvt/rv/s", of_CVT_RV_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%cvt/sr", of_CVT_SR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, - { "%cvt/ur", of_CVT_UR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, - { "%cvt/vr", of_CVT_VR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%cvt/rs", of_CVT_RS, 1, {OA_BIT1, OA_NONE, OA_NONE} }, + { "%cvt/ru", of_CVT_RU, 1, {OA_BIT1, OA_NONE, OA_NONE} }, + { "%cvt/rv", of_CVT_RV, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%cvt/rv/s", of_CVT_RV_S,2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%cvt/sr", of_CVT_SR, 1, {OA_BIT1, OA_NONE, OA_NONE} }, + { "%cvt/ur", of_CVT_UR, 1, {OA_BIT1, OA_NONE, OA_NONE} }, + { "%cvt/vr", of_CVT_VR, 2, {OA_BIT1, OA_NUMBER, OA_NONE} }, { "%deassign",of_DEASSIGN,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%deassign/wr",of_DEASSIGN_WR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, @@ -142,7 +142,8 @@ static const struct opcode_table_s opcode_table[] = { { "%delete/obj",of_DELETE_OBJ,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%div/s", of_DIV_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%div/wr", of_DIV_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%div/wr", of_DIV_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%dup/real", of_DUP_REAL,0, {OA_NONE, OA_NONE, OA_NONE} }, { "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%evctl", of_EVCTL, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} }, { "%evctl/c",of_EVCTLC, 0, {OA_NONE, OA_NONE, OA_NONE} }, @@ -150,7 +151,7 @@ static const struct opcode_table_s opcode_table[] = { { "%evctl/s",of_EVCTLS, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} }, { "%force/link",of_FORCE_LINK,2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} }, { "%force/v",of_FORCE_V,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, - { "%force/wr",of_FORCE_WR,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} }, + { "%force/wr",of_FORCE_WR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%force/x0",of_FORCE_X0,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%free", of_FREE, 1, {OA_VPI_PTR, OA_NONE, OA_NONE} }, { "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, @@ -168,28 +169,28 @@ static const struct opcode_table_s opcode_table[] = { { "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} }, { "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%join/detach",of_JOIN_DETACH,1,{OA_NUMBER,OA_NONE, OA_NONE} }, - { "%load/ar",of_LOAD_AR,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, + { "%load/ar",of_LOAD_AR,2, {OA_ARR_PTR, OA_BIT1, OA_NONE} }, { "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/avx.p",of_LOAD_AVX_P,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/dar",of_LOAD_DAR,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, - { "%load/str",of_LOAD_STR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} }, + { "%load/real", of_LOAD_REAL,1,{OA_VPI_PTR, OA_NONE, OA_NONE} }, + { "%load/str", of_LOAD_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/vp0/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, - { "%load/wr",of_LOAD_WR,2, {OA_BIT1, OA_VPI_PTR, OA_BIT2} }, { "%load/x1p",of_LOAD_X1P,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, - { "%loadi/wr",of_LOADI_WR,3,{OA_BIT1, OA_NUMBER, OA_BIT2} }, + { "%max/wr", of_MAX_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%min/wr", of_MIN_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%mod", of_MOD, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%mod/s", of_MOD_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%mod/wr", of_MOD_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%mod/wr", of_MOD_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%mov/wr", of_MOV_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%mov/wu", of_MOV_WU, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%movi", of_MOVI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%mul", of_MUL, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%mul/wr", of_MUL_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%mul/wr", of_MUL_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nand", of_NAND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nand/r", of_NANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, @@ -200,29 +201,31 @@ static const struct opcode_table_s opcode_table[] = { { "%or", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%pad", of_PAD, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%pop/str",of_POP_STR,1, {OA_NUMBER, OA_NONE, OA_NONE} }, + { "%pop/real",of_POP_REAL,1, {OA_NUMBER, OA_NONE, OA_NONE} }, + { "%pop/str", of_POP_STR, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%pow/s", of_POW_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%pow/wr", of_POW_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, - { "%pushi/str",of_PUSHI_STR,1,{OA_STRING, OA_NONE, OA_NONE} }, + { "%pow/wr", of_POW_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%pushi/real",of_PUSHI_REAL,2,{OA_BIT1, OA_BIT2, OA_NONE} }, + { "%pushi/str", of_PUSHI_STR, 1,{OA_STRING, OA_NONE, OA_NONE} }, { "%pushv/str", of_PUSHV_STR, 2, {OA_BIT1,OA_BIT2, OA_NONE} }, { "%putc/str/v",of_PUTC_STR_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, { "%release/net",of_RELEASE_NET,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} }, { "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} }, { "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} }, - { "%set/ar", of_SET_AR, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} }, { "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} }, { "%set/dar",of_SET_DAR,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, - { "%set/wr", of_SET_WORDR,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} }, { "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} }, { "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} }, { "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} }, - { "%store/obj",of_STORE_OBJ,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, - { "%store/str",of_STORE_STR,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, + { "%store/obj", of_STORE_OBJ, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, + { "%store/real", of_STORE_REAL, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, + { "%store/reala",of_STORE_REALA,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} }, + { "%store/str", of_STORE_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%sub", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%sub/wr", of_SUB_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%substr/v",of_SUBSTR_V,3,{OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%wait", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, @@ -1788,7 +1791,8 @@ void compile_file_line(char*label, long file_idx, long lineno, void compile_vpi_call(char*label, char*name, bool func_as_task_err, bool func_as_task_warn, long file_idx, long lineno, - unsigned argc, vpiHandle*argv) + unsigned argc, vpiHandle*argv, + unsigned real_stack, unsigned string_stack) { if (label) compile_codelabel(label); @@ -1801,7 +1805,8 @@ void compile_vpi_call(char*label, char*name, store that handle in the instruction. */ code->handle = vpip_build_vpi_call(name, 0, 0, 0, func_as_task_err, func_as_task_warn, - argc, argv, file_idx, lineno); + argc, argv, real_stack, string_stack, + file_idx, lineno); if (code->handle == 0) compile_errors += 1; @@ -1812,7 +1817,9 @@ void compile_vpi_call(char*label, char*name, void compile_vpi_func_call(char*label, char*name, unsigned vbit, int vwid, long file_idx, long lineno, - unsigned argc, vpiHandle*argv) + unsigned argc, vpiHandle*argv, + unsigned real_stack, + unsigned string_stack) { if (label) compile_codelabel(label); @@ -1824,7 +1831,8 @@ void compile_vpi_func_call(char*label, char*name, /* Create a vpiHandle that bundles the call information, and store that handle in the instruction. */ code->handle = vpip_build_vpi_call(name, vbit, vwid, 0, true, false, - argc, argv, file_idx, lineno); + argc, argv, real_stack, string_stack, + file_idx, lineno); if (code->handle == 0) compile_errors += 1; diff --git a/vvp/compile.h b/vvp/compile.h index 6d54730ac..bb4c60e80 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -413,7 +413,9 @@ extern void compile_file_line(char*label, long file_idx, long lineno, extern void compile_vpi_call(char*label, char*name, bool func_as_task_err, bool func_as_task_warn, long file_idx, long lineno, - unsigned argc, vpiHandle*argv); + unsigned argc, vpiHandle*argv, + unsigned real_stack, + unsigned string_stack); /* Compile a function call. The vbit and vwid encode the return type. If the vwid >0, the return type is a vector. If the vwid is @@ -422,7 +424,9 @@ extern void compile_vpi_call(char*label, char*name, extern void compile_vpi_func_call(char*label, char*name, unsigned vbit, int vwid, long file_idx, long lineno, - unsigned argc, vpiHandle*argv); + unsigned argc, vpiHandle*argv, + unsigned real_stack, + unsigned string_stack); extern void print_vpi_call_errors(); extern void compile_fork(char*label, struct symb_s targ_s, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 1884f7b38..8637555a9 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -50,8 +50,8 @@ See also the %sub instruction. * %add/wr , This is the real valued version of the %add instruction. The arguments -are word indices of the operands. The right operand is added into the -left operand. +are popped from the stack, right operand then left, and the result +pushed in place See also the %sub/wr instruction. @@ -78,14 +78,14 @@ means the following: 1 and 1 --> 1 otherwise x -* %assign/ar , , -* %assign/ar/d , , -* %assign/ar/e , +* %assign/ar , +* %assign/ar/d , +* %assign/ar/e The %assign/ar instruction assigns a real value to a word in the labeled real array. The is the delay in simulation time to -the assignment (0 for non-blocking assignment) and is the -index register that contains the value to write. +the assignment (0 for non-blocking assignment) and the value is popped +from the real value stack. The memory word address is read from index register 3. The address is in canonical form. @@ -152,13 +152,13 @@ This is similar to the %assign/v0 instruction, but adds the index-1 index register with the canonical index of the destination where the vector is to be written. This allows for part writes into the vector. -* %assign/wr , , -* %assign/wr/d , , -* %assign/wr/e , +* %assign/wr , +* %assign/wr/d , +* %assign/wr/e This instruction provides a non-blocking assign of the real value given in to the real object addressed by the -label after the given . +label after the given . The real value is popped from the stack. The %assign/wr/d variation gets the delay from integer register . @@ -194,10 +194,11 @@ manner like the expression (x ? : ). The truth table is: In other words, if the bits are identical, then take that value. Otherwise, the value is x. -* %blend/wr , +* %blend/wr This instruction blends real values for the ternary operator. If the -values match return that otherwise return 0.0. +values match return that otherwise return 0.0. Two values are popped +from the stack, one is pushed back. * %breakpoint @@ -217,10 +218,11 @@ variable. This is similar to %set, but it uses the cassign port signal responds differently. See "VARIABLE STATEMENTS" in the README.txt file. -* %cassign/wr , +* %cassign/wr Perform a continuous assign of a constant real value to the target -variable. See %cassign/v above. +variable. See %cassign/v above. The value is popped from the real +value stack. * %cassign/x0