Skip to content

Commit

Permalink
Support drawing some select expressions in place.
Browse files Browse the repository at this point in the history
Select of signals is natural for evaluating in place, if possible.
Doing so can save instructions for certain expressions.
  • Loading branch information
steveicarus committed Nov 23, 2008
1 parent 83a7497 commit 4de891d
Showing 1 changed file with 106 additions and 10 deletions.
116 changes: 106 additions & 10 deletions tgt-vvp/eval_expr.c
Expand Up @@ -1803,6 +1803,25 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
return res;
}

/*
* This little helper function generates the instructions to pad a
* vector in place. It is assumed that the calling functio has set up
* the first sub_sidth bits of the dest vector, and the signed_flag is
* true if the extension is to be signed.
*/
static void pad_in_place(struct vector_info dest, unsigned sub_width, int signed_flag)
{
if (signed_flag) {
unsigned idx;
for (idx = sub_width ; idx < dest.wid ; idx += 1)
fprintf(vvp_out, " %%mov %u, %u, 1;\n",
dest.base+idx, dest.base+sub_width-1);
} else {
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
dest.base+sub_width, dest.wid - sub_width);
}
}

/*
* The PAD expression takes a smaller node and pads it out to a larger
* value. It will zero extend or sign extend depending on the
Expand Down Expand Up @@ -1848,16 +1867,8 @@ static struct vector_info draw_pad_expr(ivl_expr_t exp, unsigned wid)
subv.wid = ivl_expr_width(subexpr);
draw_eval_expr_dest(subexpr, subv, 0);

if (ivl_expr_signed(exp)) {
unsigned idx;
for (idx = subv.wid ; idx < res.wid ; idx += 1)
fprintf(vvp_out, " %%mov %u, %u, 1;\n",
res.base+idx, subv.base+subv.wid-1);
} else {
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+subv.wid, res.wid - subv.wid);
}

pad_in_place(res, subv.wid, ivl_expr_signed(exp));

save_expression_lookaside(res.base, exp, wid);
return res;
}
Expand Down Expand Up @@ -2261,6 +2272,43 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
return res;
}

static void draw_select_signal_dest(ivl_expr_t sube,
ivl_expr_t bit_idx,
struct vector_info dest,
int stuff_ok_flag)
{
struct vector_info tmp;
ivl_signal_t sig = ivl_expr_signal(sube);

/* Special case: If the operand is a signal (not an array) and
the part select is coming from the LSB, and the part select
is no larger then the signal itself, then we can load the
value in place, directly. */
if ((ivl_signal_dimensions(sig) == 0)
&& (ivl_expr_width(sube) >= dest.wid)
&& number_is_immediate(bit_idx, 32, 0)
&& get_number_immediate(bit_idx) == 0) {
unsigned use_word = 0;
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u; Select %u out of %u bits\n",
dest.base, sig, use_word, dest.wid,
dest.wid, ivl_expr_width(sube));
return;
}

/* Fallback, just draw the expression and copy the result into
the destination. */
tmp = draw_select_signal(sube, bit_idx, dest.wid, dest.wid);
assert(tmp.wid == dest.wid);

fprintf(vvp_out, " %%mov %u, %u, %u; Move signal select into place\n",
dest.base, tmp.base, dest.wid);

if (tmp.base >= 8) {
save_expression_lookaside(tmp.base, sube, tmp.wid);
clr_vector(tmp);
}
}

static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
int stuff_ok_flag)
{
Expand Down Expand Up @@ -2350,6 +2398,50 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
return res;
}

static void draw_select_expr_dest(ivl_expr_t exp, struct vector_info dest,
int stuff_ok_flag)
{
struct vector_info tmp;

ivl_expr_t sube = ivl_expr_oper1(exp);
ivl_expr_t shift= ivl_expr_oper2(exp);

/* If the shift expression is not present, then this is really
a pad expression, and that can be handled pretty
easily. Evalutate the subexpression into the destination,
then pad in place. */
if (shift == 0) {
struct vector_info subv;
subv.base = dest.base;
subv.wid = ivl_expr_width(sube);
if (subv.wid > dest.wid)
subv.wid = dest.wid;

draw_eval_expr_dest(sube, subv, stuff_ok_flag);

pad_in_place(dest, subv.wid, ivl_expr_signed(exp));
return;
}

if (ivl_expr_type(sube) == IVL_EX_SIGNAL) {
draw_select_signal_dest(sube, shift, dest, stuff_ok_flag);
return;
}

/* Fallback, is to draw the expression by width, and mov it to
the required dest. */
tmp = draw_select_expr(exp, dest.wid, stuff_ok_flag);
assert(tmp.wid == dest.wid);

fprintf(vvp_out, " %%mov %u, %u, %u; Move select into place\n",
dest.base, tmp.base, dest.wid);

if (tmp.base >= 8) {
save_expression_lookaside(tmp.base, exp, tmp.wid);
clr_vector(tmp);
}
}

static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
{
struct vector_info res, tru, fal, tst;
Expand Down Expand Up @@ -2690,6 +2782,10 @@ static void draw_eval_expr_dest(ivl_expr_t exp, struct vector_info dest,
draw_signal_dest(exp, dest, -1, 0L);
return;

case IVL_EX_SELECT:
draw_select_expr_dest(exp, dest, stuff_ok_flag);
return;

default:
break;
}
Expand Down

0 comments on commit 4de891d

Please sign in to comment.