Concatenation can evaluate sub-expressions in place.

This commit is contained in:
steve 2002-11-06 05:41:37 +00:00
parent bc6a958a50
commit 46ee38b466
1 changed files with 78 additions and 29 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: eval_expr.c,v 1.82 2002/10/20 02:55:37 steve Exp $" #ident "$Id: eval_expr.c,v 1.83 2002/11/06 05:41:37 steve Exp $"
#endif #endif
# include "vvp_priv.h" # include "vvp_priv.h"
@ -28,6 +28,8 @@
# include <stdlib.h> # include <stdlib.h>
# include <assert.h> # include <assert.h>
static void draw_eval_expr_dest(ivl_expr_t exp, struct vector_info dest,
int ok_flags);
int number_is_unknown(ivl_expr_t ex) int number_is_unknown(ivl_expr_t ex)
{ {
@ -990,22 +992,26 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
avec.base = allocate_vector_exp(arg, awid); avec.base = allocate_vector_exp(arg, awid);
avec.wid = awid; avec.wid = awid;
/* If it's not in the lookaside map, then
evaluate the expression here. */
if (avec.base == 0) {
/* Evaluate this sub expression. */
avec = draw_eval_expr_wid(arg, awid, 0);
}
trans = awid; trans = awid;
if ((off + awid) > wid) if ((off + awid) > wid)
trans = wid - off; trans = wid - off;
assert(awid == avec.wid); if (avec.base != 0) {
assert(awid == avec.wid);
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
res.base+off,
avec.base, trans);
clr_vector(avec);
} else {
struct vector_info dest;
dest.base = res.base+off;
dest.wid = trans;
draw_eval_expr_dest(arg, dest, 0);
}
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base+off,
avec.base, trans);
clr_vector(avec);
idx -= 1; idx -= 1;
off += trans; off += trans;
@ -1171,36 +1177,41 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
* offsetting the read from the lsi (least significant index) of the * offsetting the read from the lsi (least significant index) of the
* signal. * signal.
*/ */
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid) static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
{ {
unsigned idx; unsigned idx;
unsigned lsi = ivl_expr_lsi(exp); unsigned lsi = ivl_expr_lsi(exp);
unsigned swid = ivl_expr_width(exp); unsigned swid = ivl_expr_width(exp);
ivl_signal_t sig = ivl_expr_signal(exp); ivl_signal_t sig = ivl_expr_signal(exp);
struct vector_info res;
if (swid > wid) if (swid > res.wid)
swid = wid; swid = res.wid;
res.base = allocate_vector_exp(exp, wid);
res.wid = wid;
if (res.base != 0)
return res;
if (res.base == 0) {
res.base = allocate_vector(wid);
res.wid = wid;
save_expression_lookaside(res.base, exp, wid);
}
for (idx = 0 ; idx < swid ; idx += 1) for (idx = 0 ; idx < swid ; idx += 1)
fprintf(vvp_out, " %%load %u, V_%s[%u];\n", fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
res.base+idx, vvp_signal_label(sig), idx+lsi); res.base+idx, vvp_signal_label(sig), idx+lsi);
/* Pad the signal value with zeros. */ /* Pad the signal value with zeros. */
if (swid < wid) if (swid < res.wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n", fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+swid, wid-swid); res.base+swid, res.wid-swid);
}
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
{
struct vector_info res;
/* Already in the vector lookaside? */
res.base = allocate_vector_exp(exp, wid);
res.wid = wid;
if (res.base != 0)
return res;
res.base = allocate_vector(wid);
res.wid = wid;
save_expression_lookaside(res.base, exp, wid);
draw_signal_dest(exp, res);
return res; return res;
} }
@ -1794,6 +1805,41 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
return res; return res;
} }
/*
* Sometimes we know ahead of time where we want the expression value
* to go. In that case, call this function. It will check to see if
* the expression can be preplaced, and if so it will evaluate it in
* place.
*/
static void draw_eval_expr_dest(ivl_expr_t exp, struct vector_info dest,
int stuff_ok_flag)
{
struct vector_info tmp;
switch (ivl_expr_type(exp)) {
case IVL_EX_SIGNAL:
draw_signal_dest(exp, dest);
return;
default:
break;
}
/* Fallback, is to draw the expression by width, and mov it to
the required dest. */
tmp = draw_eval_expr_wid(exp, dest.wid, stuff_ok_flag);
assert(tmp.wid == dest.wid);
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
dest.base, tmp.base, dest.wid);
if (tmp.base >= 8)
save_expression_lookaside(tmp.base, exp, tmp.wid);
clr_vector(tmp);
}
struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid, struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
int stuff_ok_flag) int stuff_ok_flag)
{ {
@ -1868,6 +1914,9 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
/* /*
* $Log: eval_expr.c,v $ * $Log: eval_expr.c,v $
* Revision 1.83 2002/11/06 05:41:37 steve
* Concatenation can evaluate sub-expressions in place.
*
* Revision 1.82 2002/10/20 02:55:37 steve * Revision 1.82 2002/10/20 02:55:37 steve
* Properly set or clear expression lookaside for binary expressions. * Properly set or clear expression lookaside for binary expressions.
* *