diff --git a/tgt-vvp/draw_net_input.c b/tgt-vvp/draw_net_input.c index 6c792511a..2bd7aedb2 100644 --- a/tgt-vvp/draw_net_input.c +++ b/tgt-vvp/draw_net_input.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -471,7 +471,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) } - fprintf(stderr, "internal error: no input to nexus.\n"); + fprintf(stderr, "vvp.tgt error: no input to nexus.\n"); assert(0); return strdup("C"); } diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 0917626fb..48e703dd5 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -504,7 +504,7 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t expr, case 'e': /* == */ if (lv.wid != rv.wid) { - fprintf(stderr,"internal error: operands of == " + fprintf(stderr,"vvp.tgt error: operands of == " " have different widths: %u vs %u\n", lv.wid, rv.wid); } @@ -519,7 +519,7 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t expr, case 'N': /* !== */ if (lv.wid != rv.wid) { - fprintf(stderr,"internal error: operands of !== " + fprintf(stderr,"vvp.tgt error: operands of !== " " have different widths: %u vs %u\n", lv.wid, rv.wid); } @@ -536,7 +536,7 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t expr, case 'n': /* != */ if (lv.wid != rv.wid) { - fprintf(stderr,"internal error: operands of != " + fprintf(stderr,"vvp.tgt error: operands of != " " have different widths: %u vs %u\n", lv.wid, rv.wid); } @@ -2383,7 +2383,7 @@ static struct vector_info draw_select_signal(ivl_expr_t expr, /* Try the special case that the part is at the beginning of the signal (or the entire width). Just load the early bits in one go. */ - if (number_is_immediate(bit_idx, 32, 0) + if (number_is_immediate(bit_idx, IMM_WID, 0) && !number_is_unknown(bit_idx) && get_number_immediate(bit_idx) == 0 && (ivl_expr_width(sube) >= bit_wid)) { @@ -2448,7 +2448,7 @@ static void draw_select_signal_dest(ivl_expr_t expr, value in place, directly. */ if ((ivl_signal_dimensions(sig) == 0) && (ivl_expr_width(sube) >= dest.wid) - && number_is_immediate(bit_idx, 32, 0) + && number_is_immediate(bit_idx, IMM_WID, 0) && ! number_is_unknown(bit_idx) && get_number_immediate(bit_idx) == 0) { unsigned use_word = 0; @@ -2946,7 +2946,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t expr, unsigned wid) break; default: - fprintf(stderr, "vvp error: unhandled unary: %c\n", + fprintf(stderr, "vvp.tgt error: unhandled unary operator: %c\n", ivl_expr_opcode(expr)); assert(0); } @@ -3005,7 +3005,7 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t expr, unsigned wid, switch (ivl_expr_type(expr)) { default: case IVL_EX_NONE: - fprintf(stderr, "%s:%u: vvp-tgt error: unhandled expr. type: " + fprintf(stderr, "%s:%u: vvp.tgt error: unhandled expr. type: " "%u at %s:%d\n", ivl_expr_file(expr), ivl_expr_lineno(expr), ivl_expr_type(expr), __FILE__, __LINE__); exit(1); @@ -3013,7 +3013,7 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t expr, unsigned wid, res.wid = 0; break; case IVL_EX_EVENT: - fprintf(stderr, "%s:%u: vvp-tgt error: A named event is not " + fprintf(stderr, "%s:%u: vvp.tgt error: A named event is not " "handled in this context (expression).\n", ivl_expr_file(expr), ivl_expr_lineno(expr)); exit(1); diff --git a/tgt-vvp/eval_real.c b/tgt-vvp/eval_real.c index 5e9fd4657..e7bd91b67 100644 --- a/tgt-vvp/eval_real.c +++ b/tgt-vvp/eval_real.c @@ -31,19 +31,22 @@ static unsigned long word_alloc_mask = 0x0f; int allocate_word() { int res = 4; - int max = IMM_WID; + int max = WORD_COUNT; while (res < max && (1U << res) & word_alloc_mask) res += 1; - assert(res < max); + if (res >= max) { + fprintf(stderr, "vvp.tgt error: Thread words exhausted.\n"); + exit(1); + } word_alloc_mask |= 1U << res; return res; } void clr_word(int res) { - int max = IMM_WID; + int max = WORD_COUNT; assert(res < max); word_alloc_mask &= ~ (1U << res); } @@ -213,7 +216,7 @@ static int draw_number_real(ivl_expr_t expr) if (bits[idx] == '0') continue; - fprintf(stderr, "internal error: mantissa doesn't fit!\n"); + fprintf(stderr, "vvp.tgt error: mantissa doesn't fit!\n"); assert(0); } @@ -388,13 +391,16 @@ static int draw_signal_real(ivl_expr_t expr) case IVL_VT_REAL: return draw_signal_real_real(expr); default: - fprintf(stderr, "internal error: signal_data_type=%d\n", + fprintf(stderr, "vvp.tgt error: signal_data_type=%d\n", ivl_signal_data_type(sig)); assert(0); return -1; } } +/* 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) { ivl_expr_t cond = ivl_expr_oper1(expr); @@ -404,12 +410,12 @@ static int draw_ternary_real(ivl_expr_t expr) struct vector_info tst; unsigned lab_true = local_count++; - unsigned lab_false = local_count++; + unsigned lab_move = local_count++; unsigned lab_out = local_count++; - int tru, fal; - int res = allocate_word(); + 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)) { struct vector_info tmp; @@ -425,29 +431,34 @@ static int draw_ternary_real(ivl_expr_t expr) tst.wid = 1; } - fprintf(vvp_out, " %%jmp/0 T_%d.%d, %u;\n", + /* Evaluate the true expression second. */ + fprintf(vvp_out, " %%jmp/1 T_%d.%d, %u;\n", thread_count, lab_true, tst.base); - tru = draw_eval_real(true_ex); - fprintf(vvp_out, " %%mov/wr %d, %d;\n", res, tru); - fprintf(vvp_out, " %%jmp/1 T_%d.%d, %u; End of true expr.\n", - thread_count, lab_out, tst.base); - clr_word(tru); - - fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_true); + /* 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); fprintf(vvp_out, " %%jmp/0 T_%d.%d, %u; End of false expr.\n", - thread_count, lab_false, tst.base); + thread_count, lab_out, tst.base); - fprintf(vvp_out, " %%blend/wr %d, %d;\n", res, fal); + /* Evaluate the true expression. */ + fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_true); + tru = draw_eval_real(true_ex); + fprintf(vvp_out, " %%jmp/1 T_%d.%d, %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); fprintf(vvp_out, " %%jmp T_%d.%d; End of blend\n", thread_count, lab_out); - fprintf(vvp_out, "T_%d.%d ; Move false result.\n", - thread_count, lab_false); - - fprintf(vvp_out, " %%mov/wr %d, %d;\n", res, fal); - clr_word(fal); + /* If we only need the true result then copy it to the result word. */ + fprintf(vvp_out, "T_%d.%d ; Move true result.\n", + thread_count, lab_move); + fprintf(vvp_out, " %%mov/wr %d, %d;\n", res, tru); + clr_word(tru); /* This is the out label. */ fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out); @@ -521,11 +532,9 @@ static int draw_unary_real(ivl_expr_t expr) return sub; } - fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n", - ivl_expr_opcode(expr), sub); - fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n", - ivl_expr_opcode(expr), sub); - return 0; + fprintf(stderr, "vvp.tgt error: unhandled real unary operator: %c.\n", + ivl_expr_opcode(expr)); + assert(0); } int draw_eval_real(ivl_expr_t expr) diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index 174508102..2e304324b 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -45,6 +45,9 @@ struct vector_info { /* Width limit for typical immediate arguments. */ # define IMM_WID 32 + /* The number of words available in a thread. */ +# define WORD_COUNT 16 + /* * Mangle all non-symbol characters in an identifier, quotes in names */