Merge branch 'master' of ssh://steve-icarus@icarus.com/home/u/icarus/steve/git/verilog

This commit is contained in:
Stephen Williams 2008-06-13 08:41:40 -07:00
commit 659714f45d
4 changed files with 32 additions and 86 deletions

View File

@ -1567,9 +1567,11 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
// If the part select covers exactly the entire // If the part select covers exactly the entire
// vector, then do not bother with it. Return the // vector, then do not bother with it. Return the
// signal itself. // signal itself, casting to unsigned if necessary.
if (sb_lsb == 0 && wid == net->vector_width()) if (sb_lsb == 0 && wid == net->vector_width()) {
net->cast_signed(false);
return net; return net;
}
// If the part select covers NONE of the vector, then return a // If the part select covers NONE of the vector, then return a
// constant X. // constant X.
@ -1580,63 +1582,12 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
return tmp; return tmp;
} }
// If the part select is entirely within the vector, then make
// a simple part select.
if (sb_lsb >= 0 && sb_msb < (signed)net->vector_width()) {
NetExpr*ex = new NetEConst(verinum(sb_lsb)); NetExpr*ex = new NetEConst(verinum(sb_lsb));
NetESelect*ss = new NetESelect(net, ex, wid); NetESelect*ss = new NetESelect(net, ex, wid);
ss->set_line(*this); ss->set_line(*this);
return ss; return ss;
} }
// Now the hard stuff. The part select is falling off at least
// one end. We're going to need a NetEConcat to mix the
// selection with overrun.
NetEConst*bot = 0;
if (sb_lsb < 0) {
bot = make_const_x( 0-sb_lsb );
bot->set_line(*this);
sb_lsb = 0;
}
NetEConst*top = 0;
if (sb_msb >= (signed)net->vector_width()) {
top = make_const_x( 1+sb_msb-net->vector_width() );
top->set_line(*this);
sb_msb = net->vector_width()-1;
}
unsigned concat_count = 1;
if (bot) concat_count += 1;
if (top) concat_count += 1;
NetEConcat*concat = new NetEConcat(concat_count);
concat->set_line(*this);
if (bot) {
concat_count -= 1;
concat->set(concat_count, bot);
}
if (sb_lsb == 0 && sb_msb+1 == (signed)net->vector_width()) {
concat_count -= 1;
concat->set(concat_count, net);
} else {
NetExpr*ex = new NetEConst(verinum(sb_lsb));
ex->set_line(*this);
NetESelect*ss = new NetESelect(net, ex, 1+sb_msb-sb_lsb);
ss->set_line(*this);
concat_count -= 1;
concat->set(concat_count, ss);
}
if (top) {
concat_count -= 1;
concat->set(concat_count, top);
}
ivl_assert(*this, concat_count==0);
return concat;
}
/* /*
* Part select indexed up, i.e. net[<m> +: <l>] * Part select indexed up, i.e. net[<m> +: <l>]
*/ */

View File

@ -75,9 +75,9 @@ int number_is_immediate(ivl_expr_t ex, unsigned lim_wid)
return 1; return 1;
} }
unsigned long get_number_immediate(ivl_expr_t ex) long get_number_immediate(ivl_expr_t ex)
{ {
unsigned long imm = 0; long imm = 0;
unsigned idx; unsigned idx;
switch (ivl_expr_type(ex)) { switch (ivl_expr_type(ex)) {
@ -93,11 +93,13 @@ unsigned long get_number_immediate(ivl_expr_t ex)
break; break;
case '1': case '1':
assert(idx < 8*sizeof(imm)); assert(idx < 8*sizeof(imm));
imm |= 1UL << idx; imm |= 1L << idx;
break; break;
default: default:
assert(0); assert(0);
} }
if (ivl_expr_signed(ex) && bits[nbits-1]=='1' && nbits < 8*sizeof(imm))
imm |= -1L << nbits;
break; break;
} }
@ -112,29 +114,17 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
{ {
switch (ivl_expr_type(expr)) { switch (ivl_expr_type(expr)) {
case IVL_EX_NUMBER: { case IVL_EX_NUMBER:
unsigned value = 0;
unsigned idx, nbits = ivl_expr_width(expr);
const char*bits = ivl_expr_bits(expr);
for (idx = 0 ; idx < nbits ; idx += 1) switch (bits[idx]) {
case '0':
break;
case '1':
assert(idx < (8*sizeof value));
value |= 1 << idx;
break;
default:
assert(0);
}
fprintf(vvp_out, " %%ix/load %u, %u;\n", ix, value);
break;
}
case IVL_EX_ULONG: case IVL_EX_ULONG:
fprintf(vvp_out, " %%ix/load %u, %lu;\n", ix, ivl_expr_uvalue(expr)); {
long imm = get_number_immediate(expr);
if (imm >= 0) {
fprintf(vvp_out, " %%ix/load %u, %ld;\n", ix, imm);
} else {
fprintf(vvp_out, " %%ix/load %u, 0; loading %ld\n", ix, imm);
fprintf(vvp_out, " %%ix/sub %u, %ld;\n", ix, -imm);
}
}
break; break;
case IVL_EX_SIGNAL: { case IVL_EX_SIGNAL: {

View File

@ -270,7 +270,7 @@ extern unsigned allocate_vector_exp(ivl_expr_t exp, unsigned wid,
extern int number_is_unknown(ivl_expr_t ex); extern int number_is_unknown(ivl_expr_t ex);
extern int number_is_immediate(ivl_expr_t ex, unsigned lim_wid); extern int number_is_immediate(ivl_expr_t ex, unsigned lim_wid);
extern unsigned long get_number_immediate(ivl_expr_t ex); extern long get_number_immediate(ivl_expr_t ex);
/* /*
* draw_eval_real evaluates real value expressions. The return code * draw_eval_real evaluates real value expressions. The return code

View File

@ -369,7 +369,7 @@ This instruction loads an immediate value into the addressed index
register. The index register holds numeric values, so the <value> is a register. The index register holds numeric values, so the <value> is a
number. The idx value selects the index register. This is different number. The idx value selects the index register. This is different
from %ix/get, which loads the index register from a value in the from %ix/get, which loads the index register from a value in the
thread bit vector. thread bit vector. The value is a signed decimal value >= 0.
* %ix/add <idx>, <value> * %ix/add <idx>, <value>
@ -462,7 +462,12 @@ select a part from a vector functor at <functor-label>. The
part is pulled from the indexed bit of the addressed functor and loaded part is pulled from the indexed bit of the addressed functor and loaded
into the destination thread bit. The <wid> is the width of the into the destination thread bit. The <wid> is the width of the
part. If any bit of the desired value is outside the vector, then that part. If any bit of the desired value is outside the vector, then that
bit is set to X. The index register 1 is interpreted as a signed value. bit is set to X.
The index register 1 is interpreted as a signed value. Even though the
address is cannonical (from 0 to the width of the signal) the value in
index register 1 may be <0 or >=wid. The load instruction handles
filling in the out-of-bounds bits with x.
When the operation is done, the <wid> is added to index register 1, to When the operation is done, the <wid> is added to index register 1, to
provide a basic auto-increment behavior. provide a basic auto-increment behavior.