diff --git a/tgt-vvp/draw_ufunc.c b/tgt-vvp/draw_ufunc.c index db5ee7dcd..6860b8531 100644 --- a/tgt-vvp/draw_ufunc.c +++ b/tgt-vvp/draw_ufunc.c @@ -112,6 +112,15 @@ struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid) res.base = allocate_vector(wid); res.wid = wid; + if (res.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits for function result.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + return res; + } + + assert(res.base != 0); unsigned load_wid = swid; if (load_wid > ivl_signal_width(retval)) diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index 4a0ded932..43821385f 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -303,6 +303,13 @@ struct vector_info draw_vpi_func_call(ivl_expr_t fnet, unsigned wid) res.base = allocate_vector(wid); res.wid = wid; + if (res.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits for system function result.\n", + ivl_expr_file(fnet), ivl_expr_lineno(fnet), wid); + vvp_errors += 1; + } + sprintf(call_string, " %%vpi_func %u %u \"%s\", %u, %u", ivl_file_table_index(ivl_expr_file(fnet)), ivl_expr_lineno(fnet), ivl_expr_name(fnet), res.base, res.wid); diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 85300588d..63dabb04a 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -277,6 +277,14 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid, expressions. */ if (lv.base < 8) { unsigned base = allocate_vector(ewid); + if (base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of equality compare.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%mov %u, %u, 1;\n", base, lv.base); lv.base = base; lv.wid = ewid; @@ -285,6 +293,14 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid, } else if (lv.wid < ewid) { unsigned base = allocate_vector(ewid); + if (base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of equality compare.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } + if (lv.base >= 8) clr_vector(lv); fprintf(vvp_out, " %%mov %u, %u, %u;\n", base, @@ -309,6 +325,7 @@ static struct vector_info draw_binary_expr_eq_real(ivl_expr_t exp) res.base = allocate_vector(1); res.wid = 1; + assert(res.base); lword = draw_eval_real(ivl_expr_oper1(exp)); rword = draw_eval_real(ivl_expr_oper2(exp)); @@ -441,6 +458,14 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, uses. This is because that bit may be clobbered by other expressions. */ { unsigned base = allocate_vector(ewid); + if (base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of equality compare.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%mov %u, %u, 1;\n", base, lv.base); lv.base = base; lv.wid = ewid; @@ -467,6 +492,7 @@ static struct vector_info draw_binary_expr_land(ivl_expr_t exp, unsigned wid) clr_vector(lv); tmp.base = allocate_vector(1); tmp.wid = 1; + assert(tmp.base); fprintf(vvp_out, " %%or/r %u, %u, %u;\n", tmp.base, lv.base, lv.wid); lv = tmp; @@ -478,6 +504,7 @@ static struct vector_info draw_binary_expr_land(ivl_expr_t exp, unsigned wid) clr_vector(rv); tmp.base = allocate_vector(1); tmp.wid = 1; + assert(tmp.base); fprintf(vvp_out, " %%or/r %u, %u, %u;\n", tmp.base, rv.base, rv.wid); rv = tmp; @@ -514,6 +541,14 @@ static struct vector_info draw_binary_expr_land(ivl_expr_t exp, unsigned wid) /* Write the result into a zero-padded result. */ { unsigned base = allocate_vector(wid); + if (base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of padded logical AND.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%mov %u, %u, 1;\n", base, lv.base); clr_vector(lv); lv.base = base; @@ -541,6 +576,7 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid) clr_vector(lv); tmp.base = allocate_vector(1); tmp.wid = 1; + assert(tmp.base); fprintf(vvp_out, " %%or/r %u, %u, %u;\n", tmp.base, lv.base, lv.wid); lv = tmp; @@ -555,6 +591,7 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid) clr_vector(rv); tmp.base = allocate_vector(1); tmp.wid = 1; + assert(tmp.base); fprintf(vvp_out, " %%or/r %u, %u, %u;\n", tmp.base, rv.base, rv.wid); rv = tmp; @@ -592,6 +629,14 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid) /* Write the result into a zero-padded result. */ { unsigned base = allocate_vector(wid); + if (base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of padded logical OR.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%mov %u, %u, 1;\n", base, lv.base); clr_vector(lv); lv.base = base; @@ -615,6 +660,8 @@ static struct vector_info draw_binary_expr_le_real(ivl_expr_t exp) res.base = allocate_vector(1); res.wid = 1; + assert(res.base); + clr_word(lword); clr_word(rword); @@ -695,6 +742,14 @@ static struct vector_info draw_binary_expr_le_bool(ivl_expr_t exp, uses. This is because that bit may be clobbered by other expressions. */ { unsigned base = allocate_vector(wid); + if (base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of padded inequality compare.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%mov %u, 5, 1;\n", base); tmp.base = base; tmp.wid = wid; @@ -822,6 +877,14 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp, uses. This is because that bit may be clobbered by other expressions. */ { unsigned base = allocate_vector(wid); + if (base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of padded inequality compare.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%mov %u, 5, 1;\n", base); lv.base = base; lv.wid = wid; @@ -858,6 +921,14 @@ static struct vector_info draw_binary_expr_logic(ivl_expr_t exp, struct vector_info tmp; tmp.base = allocate_vector(lv.wid); tmp.wid = lv.wid; + if (tmp.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of binary logic.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp.base, lv.base, tmp.wid); lv = tmp; @@ -933,6 +1004,14 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid) struct vector_info tmp; tmp.base = allocate_vector(lv.wid); tmp.wid = lv.wid; + if (tmp.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of left shift (<<).\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp.base, lv.base, lv.wid); lv = tmp; @@ -960,6 +1039,14 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid) struct vector_info tmp; tmp.base = allocate_vector(lv.wid); tmp.wid = lv.wid; + if (tmp.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of right shift (>>).\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), lv.wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp.base, lv.base, lv.wid); lv = tmp; @@ -992,6 +1079,14 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid) struct vector_info tmp; tmp.base = allocate_vector(lv.wid); tmp.wid = lv.wid; + if (tmp.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of right shift (>>>).\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), lv.wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp.base, lv.base, lv.wid); lv = tmp; @@ -1030,6 +1125,13 @@ static struct vector_info draw_load_add_immediate(ivl_expr_t le, imm = get_number_immediate(re); lv.base = allocate_vector(wid); lv.wid = wid; + if (lv.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of addition.\n", + ivl_expr_file(le), ivl_expr_lineno(le), wid); + vvp_errors += 1; + } /* Load the signal value with a %load that adds the index register to the value being loaded. */ @@ -1093,6 +1195,14 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le, case 0: case 1: tmp = allocate_vector(wid); + if (tmp == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of subtraction.\n", + ivl_expr_file(le), ivl_expr_lineno(le), wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp, lv.base, wid); lv.base = tmp; fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid); @@ -1205,6 +1315,14 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid) tmp.base = allocate_vector(wid); tmp.wid = wid; + if (tmp.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of arithmetic expression.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp.base, lv.base, wid); lv = tmp; @@ -1343,6 +1461,14 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid, /* Allocate a vector to hold the result. */ res.base = allocate_vector(wid); res.wid = wid; + if (res.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for result of concatenation.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } + /* Get the repeat count. This must be a constant that has been evaluated at compile time. The operands will be repeated to @@ -1464,6 +1590,13 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid) vector. Allocate the vector and use %mov instructions to load the constant bit values. */ res.base = allocate_vector(wid); + if (res.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for number value.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } if ((!number_is_unknown(exp)) && number_is_immediate(exp, 16)) { int val = get_number_immediate(exp); @@ -1546,6 +1679,13 @@ static struct vector_info draw_pad_expr(ivl_expr_t exp, unsigned wid) res.base = allocate_vector(wid); res.wid = wid; + if (res.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "to pad expression.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, subv.base, subv.wid); @@ -1580,6 +1720,7 @@ static struct vector_info draw_realnum_expr(ivl_expr_t exp, unsigned wid) res.base = allocate_vector(wid); res.wid = wid; + assert(res.base); addr = res.base; run = 1; @@ -1666,6 +1807,13 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid) vector. Allocate the vector and use %mov instructions to load the constant bit values. */ res.base = allocate_vector(wid); + if (res.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "for string value.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } /* Since this is a string, we know that all the bits are defined and each character represents exactly 8 bits. Use @@ -1819,6 +1967,14 @@ static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid, res.base = allocate_vector(wid); res.wid = wid; + if (res.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "to load variable/wire.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } + save_expression_lookaside(res.base, exp, wid); draw_signal_dest(exp, res, -1, 0L); @@ -1846,6 +2002,13 @@ static struct vector_info draw_select_array(ivl_expr_t sube, res.base = allocate_vector(wid); res.wid = wid; + if (res.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "to hold selected value.\n", + ivl_expr_file(sube), ivl_expr_lineno(sube), wid); + vvp_errors += 1; + } for (idx = 0 ; idx < wid ; idx += 1) { fprintf(vvp_out, " %%load/avx.p %u, v%p, 0;\n", res.base+idx, sig); @@ -1891,6 +2054,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube, res.base = allocate_vector(wid); res.wid = wid; + assert(res.base); fprintf(vvp_out, " %%load/v %u, v%p_%u, %u; Only need %u of %u bits\n", res.base, sig, use_word, bit_wid, bit_wid, ivl_expr_width(sube)); @@ -1907,6 +2071,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube, /* Alas, do it the hard way. */ res.base = allocate_vector(wid); res.wid = wid; + assert(res.base); for (idx = 0 ; idx < res.wid ; idx += 1) { if (idx >= bit_wid) { @@ -1981,6 +2146,7 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid, if (subv.base < 4) { res.base = allocate_vector(subv.wid); res.wid = subv.wid; + assert(res.base); fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, subv.base, res.wid); subv = res; @@ -2051,6 +2217,7 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid) struct vector_info tmp; tmp.base = allocate_vector(wid); tmp.wid = wid; + assert(tmp.base); fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp.base, tru.base, wid); tru = tmp; @@ -2108,6 +2275,7 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid) || ivl_expr_value(exp) == IVL_VT_BOOL); res.base = allocate_vector(wid); res.wid = wid; + assert(res.base); fprintf(vvp_out, " %%vpi_func %u %u \"%s\", %u, %u;\n", ivl_file_table_index(ivl_expr_file(exp)), ivl_expr_lineno(exp), ivl_expr_name(exp), @@ -2221,6 +2389,14 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid) struct vector_info tmp; tmp.base = allocate_vector(wid); tmp.wid = wid; + if (tmp.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits " + "to pad unary expression result.\n", + ivl_expr_file(exp), ivl_expr_lineno(exp), wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp.base, res.base, res.wid); fprintf(vvp_out, " %%mov %u, 0, %u;\n", @@ -2246,6 +2422,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid) if (res.base < 4) { tmp.base = allocate_vector(res.wid); tmp.wid = res.wid; + assert(res.base); fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp.base, res.base, res.wid); res = tmp; @@ -2269,6 +2446,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid) struct vector_info tmp; tmp.base = allocate_vector(wid); tmp.wid = wid; + assert(res.base); fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp.base, res.base, res.wid); fprintf(vvp_out, " %%mov %u, 0, %u;\n", diff --git a/tgt-vvp/vector.c b/tgt-vvp/vector.c index 2c1d5012d..77f08ec96 100644 --- a/tgt-vvp/vector.c +++ b/tgt-vvp/vector.c @@ -91,6 +91,9 @@ static unsigned allocate_vector_no_lookaside(unsigned wid, int skip_lookaside) unsigned idx = 0; while (idx < wid) { + if (base+idx >= MAX_VEC) + return 0; + assert((base + idx) < MAX_VEC); if ((allocation_map[base+idx].alloc > 0) || (skip_lookaside && peek_exp(base+idx))) { @@ -121,6 +124,9 @@ static unsigned allocate_vector_no_lookaside(unsigned wid, int skip_lookaside) * again without worrying about trashing lookaside results. This * should lead to preferentially allocating new bits instead of * constantly overwriting intermediate results. + * + * If there is no space for a vector of the given width, then give up + * and return 0. */ unsigned allocate_vector(unsigned wid) { diff --git a/tgt-vvp/vvp.c b/tgt-vvp/vvp.c index 37aab78f6..e1cb632f3 100644 --- a/tgt-vvp/vvp.c +++ b/tgt-vvp/vvp.c @@ -27,6 +27,7 @@ # include FILE*vvp_out = 0; +int vvp_errors = 0; inline static void draw_execute_header(ivl_design_t des) { @@ -79,6 +80,8 @@ int target_design(ivl_design_t des) return -1; } + vvp_errors = 0; + draw_execute_header(des); { int pre = ivl_design_time_precision(des); @@ -113,6 +116,6 @@ int target_design(ivl_design_t des) fclose(vvp_out); - return rc; + return rc + vvp_errors; } diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index f96099961..53c31618e 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -29,6 +29,11 @@ */ extern FILE* vvp_out; +/* + * Keep a count of errors that would render the output unusable. + */ +extern int vvp_errors; + struct vector_info { unsigned base; unsigned wid; diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 8fa8830dc..572dc48ab 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -374,6 +374,14 @@ static int show_stmt_assign_vector(ivl_statement_t net) vec.base = allocate_vector(wid); vec.wid = wid; + if (vec.base == 0) { + fprintf(stderr, "%s:%u: vvp.tgt error: " + "Unable to allocate %u thread bits for " + "r-value expression.\n", ivl_expr_file(rval), + ivl_expr_lineno(rval), wid); + vvp_errors += 1; + } + fprintf(vvp_out, " %%cvt/vr %u, %d, %u;\n", vec.base, word, vec.wid); @@ -604,6 +612,7 @@ static int show_stmt_block_named(ivl_statement_t net, ivl_scope_t scope) static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope) { + int rc = 0; ivl_expr_t exp = ivl_stmt_cond_expr(net); struct vector_info cond = draw_eval_expr(exp, 0); unsigned count = ivl_stmt_case_count(net); @@ -688,7 +697,7 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope) /* Emit code for the default case. */ if (default_case < count) { ivl_statement_t cst = ivl_stmt_case_stmt(net, default_case); - show_statement(cst, sscope); + rc += show_statement(cst, sscope); } /* Jump to the out of the case. */ @@ -703,7 +712,7 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope) fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+idx); clear_expression_lookaside(); - show_statement(cst, sscope); + rc += show_statement(cst, sscope); fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, local_base+count); @@ -715,11 +724,12 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope) fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+count); clear_expression_lookaside(); - return 0; + return rc; } static int show_stmt_case_r(ivl_statement_t net, ivl_scope_t sscope) { + int rc = 0; ivl_expr_t exp = ivl_stmt_cond_expr(net); int cond = draw_eval_real(exp); unsigned count = ivl_stmt_case_count(net); @@ -762,7 +772,7 @@ static int show_stmt_case_r(ivl_statement_t net, ivl_scope_t sscope) fall through to this statement. */ if (default_case < count) { ivl_statement_t cst = ivl_stmt_case_stmt(net, default_case); - show_statement(cst, sscope); + rc += show_statement(cst, sscope); } /* Jump to the out of the case. */ @@ -777,7 +787,7 @@ static int show_stmt_case_r(ivl_statement_t net, ivl_scope_t sscope) fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+idx); clear_expression_lookaside(); - show_statement(cst, sscope); + rc += show_statement(cst, sscope); fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, local_base+count); @@ -1344,6 +1354,7 @@ static struct vector_info reduction_or(struct vector_info cvec) clr_vector(cvec); result.base = allocate_vector(1); result.wid = 1; + assert(result.base); fprintf(vvp_out, " %%or/r %u, %u, %u;\n", result.base, cvec.base, cvec.wid); break;