Skip to content

Commit

Permalink
More robust use of precalculated expressions, and
Browse files Browse the repository at this point in the history
 Separate lookaside for written variables that can
 also be reused.
  • Loading branch information
steve committed Sep 17, 2005
1 parent 7235706 commit 672aa61
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 57 deletions.
48 changes: 33 additions & 15 deletions tgt-vvp/eval_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_expr.c,v 1.121 2005/09/15 02:49:47 steve Exp $"
#ident "$Id: eval_expr.c,v 1.122 2005/09/17 01:01:00 steve Exp $"
#endif

# include "vvp_priv.h"
Expand Down Expand Up @@ -274,8 +274,8 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
if (ivl_expr_width(re) > wid)
wid = ivl_expr_width(re);

lv = draw_eval_expr_wid(le, wid, stuff_ok_flag&STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, stuff_ok_flag&STUFF_OK_XZ);
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag&~STUFF_OK_47);
rv = draw_eval_expr_wid(re, wid, stuff_ok_flag&~STUFF_OK_47);

switch (ivl_expr_opcode(exp)) {
case 'E': /* === */
Expand Down Expand Up @@ -1057,7 +1057,7 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
return draw_mul_immediate(le, re, wid);

lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ|STUFF_OK_RO);

if (lv.wid != wid) {
fprintf(stderr, "XXXX ivl_expr_opcode(exp) = %c,"
Expand Down Expand Up @@ -1198,11 +1198,14 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp,
* expression, then copying it into the continguous vector of the
* result. Do this until the result vector is filled.
*/
static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid,
int stuff_ok_flag)
{
unsigned off, rep;
struct vector_info res;

int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO) ? 0 : 1;

/* Allocate a vector to hold the result. */
res.base = allocate_vector(wid);
res.wid = wid;
Expand Down Expand Up @@ -1232,7 +1235,7 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)

/* Try to locate the subexpression in the
lookaside map. */
avec.base = allocate_vector_exp(arg, awid);
avec.base = allocate_vector_exp(arg, awid, alloc_exclusive);
avec.wid = awid;

trans = awid;
Expand Down Expand Up @@ -1517,15 +1520,21 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
}
}

static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid,
int stuff_ok_flag)
{
struct vector_info res;

int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO) ? 0 : 1;

/* Already in the vector lookaside? */
res.base = allocate_vector_exp(exp, wid);
res.base = allocate_vector_exp(exp, wid, alloc_exclusive);
res.wid = wid;
if (res.base != 0)
if (res.base != 0) {
fprintf(vvp_out, "; Reuse signal base=%u wid=%u from lookaside.\n",
res.base, res.wid);
return res;
}

res.base = allocate_vector(wid);
res.wid = wid;
Expand Down Expand Up @@ -1643,16 +1652,19 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
return res;
}

static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
int stuff_ok_flag)
{
struct vector_info subv, shiv, res;
ivl_expr_t sube = ivl_expr_oper1(exp);
ivl_expr_t shift = ivl_expr_oper2(exp);

int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO)? 0 : 1;

/* First look for the self expression in the lookaside, and
allocate that if possible. If I find it, then immediatly
return that. */
if ( (res.base = allocate_vector_exp(exp, wid)) != 0) {
if ( (res.base = allocate_vector_exp(exp, wid, alloc_exclusive)) != 0) {
fprintf(vvp_out, "; Reuse base=%u wid=%u from lookaside.\n",
res.base, wid);
res.wid = wid;
Expand Down Expand Up @@ -1712,6 +1724,7 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
res.wid = wid;

subv.base += wid;
subv.wid -= wid;
clr_vector(subv);

} else if (subv.wid == wid) {
Expand Down Expand Up @@ -1742,7 +1755,7 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)

/* Evaluate the condition expression, and if necessary reduce
it to a single bit. */
tst = draw_eval_expr(cond, STUFF_OK_XZ);
tst = draw_eval_expr(cond, STUFF_OK_XZ|STUFF_OK_RO);
if ((tst.base >= 4) && (tst.wid > 1)) {
struct vector_info tmp;

Expand Down Expand Up @@ -2064,7 +2077,7 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
break;

case IVL_EX_CONCAT:
res = draw_concat_expr(exp, wid);
res = draw_concat_expr(exp, wid, stuff_ok_flag);
break;

case IVL_EX_NUMBER:
Expand All @@ -2079,11 +2092,11 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
if (ivl_expr_oper2(exp) == 0)
res = draw_pad_expr(exp, wid);
else
res = draw_select_expr(exp, wid);
res = draw_select_expr(exp, wid, stuff_ok_flag);
break;

case IVL_EX_SIGNAL:
res = draw_signal_expr(exp, wid);
res = draw_signal_expr(exp, wid, stuff_ok_flag);
break;

case IVL_EX_TERNARY:
Expand Down Expand Up @@ -2117,6 +2130,11 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)

/*
* $Log: eval_expr.c,v $
* Revision 1.122 2005/09/17 01:01:00 steve
* More robust use of precalculated expressions, and
* Separate lookaside for written variables that can
* also be reused.
*
* Revision 1.121 2005/09/15 02:49:47 steve
* Better reuse of IVL_EX_SELECT expressions.
*
Expand Down
132 changes: 95 additions & 37 deletions tgt-vvp/vector.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vector.c,v 1.6 2005/09/15 02:50:13 steve Exp $"
#ident "$Id: vector.c,v 1.7 2005/09/17 01:01:00 steve Exp $"
#endif

# include "vvp_priv.h"
Expand All @@ -31,42 +31,35 @@

static struct allocation_score_s {
ivl_expr_t exp;
unsigned bit;
unsigned alloc : 1;
ivl_signal_t sig;
unsigned exp_bit : 24;
unsigned sig_bit : 24;
unsigned alloc : 8;
} allocation_map[MAX_VEC] = { {0} };

/* This is the largest bit to have lookaside values. */
static unsigned lookaside_top = 0;

static inline int peek_bit(unsigned addr)
{
return allocation_map[addr].alloc;
}

static inline void set_bit(unsigned addr)
{
allocation_map[addr].alloc = 1;
}

static inline void clr_bit(unsigned addr)
{
allocation_map[addr].alloc = 0;
}

static inline ivl_expr_t peek_exp(unsigned addr)
{
return allocation_map[addr].exp;
}

static inline unsigned peek_exp_bit(unsigned addr)
{
return allocation_map[addr].bit;
return allocation_map[addr].exp_bit;
}

static inline void set_exp(unsigned addr, ivl_expr_t exp, unsigned ebit)
{
allocation_map[addr].exp = exp;
allocation_map[addr].bit = ebit;
allocation_map[addr].exp_bit = ebit;
}

static inline void set_sig(unsigned addr, ivl_signal_t exp, unsigned ebit)
{
allocation_map[addr].sig = exp;
allocation_map[addr].sig_bit = ebit;
}

/*
Expand All @@ -84,8 +77,10 @@ void clr_vector(struct vector_info vec)
if (vec.base < 4)
return;
assert(vec.base >= 8);
for (idx = 0 ; idx < vec.wid ; idx += 1)
clr_bit(vec.base + idx);
for (idx = 0 ; idx < vec.wid ; idx += 1) {
assert( allocation_map[vec.base+idx].alloc > 0);
allocation_map[vec.base+idx].alloc -= 1;
}
}

static unsigned allocate_vector_no_lookaside(unsigned wid, int skip_lookaside)
Expand All @@ -95,7 +90,8 @@ static unsigned allocate_vector_no_lookaside(unsigned wid, int skip_lookaside)

while (idx < wid) {
assert((base + idx) < MAX_VEC);
if (peek_bit(base+idx) || (skip_lookaside && peek_exp(base+idx))) {
if ((allocation_map[base+idx].alloc > 0)
|| (skip_lookaside && peek_exp(base+idx))) {
base = base + idx + 1;
idx = 0;

Expand All @@ -105,7 +101,7 @@ static unsigned allocate_vector_no_lookaside(unsigned wid, int skip_lookaside)
}

for (idx = 0 ; idx < wid ; idx += 1) {
set_bit(base+idx);
allocation_map[base+idx].alloc += 1;
set_exp(base+idx, 0, 0);
}

Expand Down Expand Up @@ -140,21 +136,45 @@ unsigned allocate_vector(unsigned wid)
void clear_expression_lookaside(void)
{
unsigned idx;
for (idx = 0 ; idx < lookaside_top ; idx += 1)

for (idx = 0 ; idx < lookaside_top ; idx += 1) {
set_exp(idx, 0, 0);
set_sig(idx, 0, 0);
}

lookaside_top = 0;
}

void save_expression_lookaside(unsigned addr, ivl_expr_t exp,
unsigned wid)
void save_expression_lookaside(unsigned addr, ivl_expr_t exp, unsigned wid)
{
unsigned idx;
assert(addr >= 8);
assert((addr+wid) <= MAX_VEC);

for (idx = 0 ; idx < wid ; idx += 1)
/* When saving an expression to the lookaside, also clear the
signal saved in the lookaside for these bits. The reason is
that an expression calculation will replace any signal
bits. */
for (idx = 0 ; idx < wid ; idx += 1) {
set_exp(addr+idx, exp, idx);
set_sig(addr+idx, 0, 0);
}

if ((addr+wid) > lookaside_top)
lookaside_top = addr+wid;
}

void save_signal_lookaside(unsigned addr, ivl_signal_t sig, unsigned wid)
{
unsigned idx;
/* Don't bind any of hte low bits to a signal. */
if (addr < 8)
return;

assert((addr+wid) <= MAX_VEC);

for (idx = 0 ; idx < wid ; idx += 1)
set_sig(addr+idx, sig, idx);

if ((addr+wid) > lookaside_top)
lookaside_top = addr+wid;
Expand Down Expand Up @@ -213,26 +233,56 @@ static int compare_exp(ivl_expr_t l, ivl_expr_t r)
return 0;
}

static unsigned find_expression_lookaside(ivl_expr_t exp,
unsigned wid)
static unsigned find_expression_lookaside(ivl_expr_t exp, unsigned wid)
{
unsigned top;
unsigned idx, match;
ivl_signal_t sig;

if (lookaside_top <= wid)
return 0;

top = lookaside_top - wid + 1;

/* Look in the expression lookaside for this expression. */
assert(exp);
match = 0;
for (idx = 8 ; idx < top ; idx += 1) {
for (idx = 8 ; idx < lookaside_top ; idx += 1) {
if (! compare_exp(allocation_map[idx].exp, exp)) {
match = 0;
continue;
}

if (allocation_map[idx].bit != match) {
if (allocation_map[idx].exp_bit != match) {
match = 0;
continue;
}

match += 1;
if (match == wid)
return idx-match+1;
}

if (ivl_expr_type(exp) != IVL_EX_SIGNAL)
return 0;

sig = ivl_expr_signal(exp);

/* Only reg signals (variables) will be in the signal
lookaside, because only blocking assigned values are in the
signal lookaside. */
if (ivl_signal_type(sig) != IVL_SIT_REG)
return 0;

/* Now look for signal value matches in the signal lookaside. */
match = 0;
for (idx = 8 ; idx < lookaside_top ; idx += 1) {
if (sig != allocation_map[idx].sig) {
match = 0;
continue;
}

if (allocation_map[idx].sig_bit != match) {
match = 0;
continue;
}
Expand All @@ -251,23 +301,31 @@ static unsigned find_expression_lookaside(ivl_expr_t exp,
* caller will not need to evaluate the expression. If this function
* returns 0, then the expression is not found and nothing is allocated.
*/
unsigned allocate_vector_exp(ivl_expr_t exp, unsigned wid)
unsigned allocate_vector_exp(ivl_expr_t exp, unsigned wid,
int exclusive_flag)
{
unsigned idx;
unsigned la = find_expression_lookaside(exp, wid);

for (idx = 0 ; idx < wid ; idx += 1)
if (allocation_map[la+idx].alloc)
return 0;
if (exclusive_flag) {
for (idx = 0 ; idx < wid ; idx += 1)
if (allocation_map[la+idx].alloc)
return 0;
}

for (idx = 0 ; idx < wid ; idx += 1)
allocation_map[la+idx].alloc = 1;
allocation_map[la+idx].alloc += 1;

return la;
}

/*
* $Log: vector.c,v $
* Revision 1.7 2005/09/17 01:01:00 steve
* More robust use of precalculated expressions, and
* Separate lookaside for written variables that can
* also be reused.
*
* Revision 1.6 2005/09/15 02:50:13 steve
* Preserve precalculated expressions when possible.
*
Expand Down
Loading

0 comments on commit 672aa61

Please sign in to comment.