From c2dc3fe5c3cc771fd3dd892633a1c5903e9fee23 Mon Sep 17 00:00:00 2001 From: steve Date: Fri, 23 Mar 2001 01:10:24 +0000 Subject: [PATCH] Assure that operands are the correct width. --- tgt-vvp/eval_expr.c | 128 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 107 insertions(+), 21 deletions(-) diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 919f68eed..04cbf4191 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -17,12 +17,14 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: eval_expr.c,v 1.1 2001/03/22 05:06:21 steve Exp $" +#ident "$Id: eval_expr.c,v 1.2 2001/03/23 01:10:24 steve Exp $" #endif # include "vvp_priv.h" # include +struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid); + static unsigned char allocation_map[0x10000/8]; static inline int peek_bit(unsigned addr) @@ -75,15 +77,21 @@ static unsigned short allocate_vector(unsigned short wid) return base; } -/* - * The draw_eval_expr() function draws code to evaluate the passed - * expression, then returns the location and width of the result. - */ -static struct vector_info draw_binary_expr(ivl_expr_t exp) +static struct vector_info draw_binary_expr_eq(ivl_expr_t exp) { - struct vector_info lv = draw_eval_expr(ivl_expr_oper1(exp)); - struct vector_info rv = draw_eval_expr(ivl_expr_oper2(exp)); + ivl_expr_t le = ivl_expr_oper1(exp); + ivl_expr_t re = ivl_expr_oper2(exp); + + struct vector_info lv; + struct vector_info rv; + + unsigned wid = ivl_expr_width(le); + if (ivl_expr_width(re) > wid) + wid = ivl_expr_width(re); + + lv = draw_eval_expr_wid(le, wid); + rv = draw_eval_expr_wid(re, wid); switch (ivl_expr_opcode(exp)) { case 'e': /* == */ @@ -115,17 +123,73 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp) return lv; } -static struct vector_info draw_number_expr(ivl_expr_t exp) +static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid) +{ + struct vector_info rv; + + switch (ivl_expr_opcode(exp)) { + case 'e': /* == */ + case 'n': /* != */ + assert(wid == 1); + rv = draw_binary_expr_eq(exp); + break; + + default: + assert(0); + } + + return rv; +} + +/* + * A number in an expression is made up by copying constant bits into + * the allocated vector. + */ +static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid) { unsigned idx; - unsigned wid = ivl_expr_width(exp); + struct vector_info res; const char*bits = ivl_expr_bits(exp); - struct vector_info res; - res.base = allocate_vector(wid); res.wid = wid; - for (idx = 0 ; idx < wid ; idx += 1) { + assert(ivl_expr_width(exp) >= wid); + + /* If all the bits of the number have the same value, then we + can use a constant bit. There is no need to allocate wr + bits, and there is no need to generate any code. */ + + for (idx = 1 ; idx < res.wid ; idx += 1) { + if (bits[idx] != bits[0]) + break; + } + + if (idx == res.wid) { + switch (bits[0]) { + case '0': + res.base = 0; + break; + case '1': + res.base = 1; + break; + case 'x': + res.base = 2; + break; + case 'z': + res.base = 3; + break; + } + return res; + } + + /* The number value needs to be represented as an allocated + vector. Allocate the vector and use %mov instructions to + load the constant bit values. */ + res.base = allocate_vector(wid); + + idx = 0; + while (idx < wid) { + unsigned cnt; char src = '?'; switch (bits[idx]) { case '0': @@ -142,30 +206,44 @@ static struct vector_info draw_number_expr(ivl_expr_t exp) break; } - fprintf(vvp_out, " %%mov %u, %c, 1;\n", res.base+idx, src); + for (cnt = 1 ; idx+cnt < wid ; cnt += 1) + if (bits[idx+cnt] != bits[idx]) + break; + + fprintf(vvp_out, " %%mov %u, %c, %u;\n", + res.base+idx, src, cnt); + + idx += cnt; } return res; } -static struct vector_info draw_signal_expr(ivl_expr_t exp) +static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid) { unsigned idx; - unsigned wid = ivl_expr_width(exp); + unsigned swid = ivl_expr_width(exp); const char*name = ivl_expr_name(exp); struct vector_info res; + if (swid > wid) + swid = wid; + res.base = allocate_vector(wid); res.wid = wid; - for (idx = 0 ; idx < wid ; idx += 1) + for (idx = 0 ; idx < swid ; idx += 1) fprintf(vvp_out, " %%load %u, V_%s[%u];\n", res.base+idx, name, idx); + /* Pad the signal value with zeros. */ + if (swid < wid) + fprintf(vvp_out, " %%mov %u, 0, %u;\n", + res.base+swid, wid-swid); return res; } -struct vector_info draw_eval_expr(ivl_expr_t exp) +struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid) { struct vector_info res; @@ -178,23 +256,31 @@ struct vector_info draw_eval_expr(ivl_expr_t exp) break; case IVL_EX_BINARY: - res = draw_binary_expr(exp); + res = draw_binary_expr(exp, wid); break; case IVL_EX_NUMBER: - res = draw_number_expr(exp); + res = draw_number_expr(exp, wid); break; case IVL_EX_SIGNAL: - res = draw_signal_expr(exp); + res = draw_signal_expr(exp, wid); break; } return res; } +struct vector_info draw_eval_expr(ivl_expr_t exp) +{ + return draw_eval_expr_wid(exp, ivl_expr_width(exp)); +} + /* * $Log: eval_expr.c,v $ + * Revision 1.2 2001/03/23 01:10:24 steve + * Assure that operands are the correct width. + * * Revision 1.1 2001/03/22 05:06:21 steve * Geneate code for conditional statements. *