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
// vector, then do not bother with it. Return the
// signal itself.
if (sb_lsb == 0 && wid == net->vector_width())
// signal itself, casting to unsigned if necessary.
if (sb_lsb == 0 && wid == net->vector_width()) {
net->cast_signed(false);
return net;
}
// If the part select covers NONE of the vector, then return a
// constant X.
@ -1580,61 +1582,10 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
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));
NetESelect*ss = new NetESelect(net, ex, wid);
ss->set_line(*this);
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;
NetExpr*ex = new NetEConst(verinum(sb_lsb));
NetESelect*ss = new NetESelect(net, ex, wid);
ss->set_line(*this);
return ss;
}
/*

View File

@ -75,9 +75,9 @@ int number_is_immediate(ivl_expr_t ex, unsigned lim_wid)
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;
switch (ivl_expr_type(ex)) {
@ -93,11 +93,13 @@ unsigned long get_number_immediate(ivl_expr_t ex)
break;
case '1':
assert(idx < 8*sizeof(imm));
imm |= 1UL << idx;
imm |= 1L << idx;
break;
default:
assert(0);
}
if (ivl_expr_signed(ex) && bits[nbits-1]=='1' && nbits < 8*sizeof(imm))
imm |= -1L << nbits;
break;
}
@ -112,30 +114,18 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
{
switch (ivl_expr_type(expr)) {
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_NUMBER:
case IVL_EX_ULONG:
fprintf(vvp_out, " %%ix/load %u, %lu;\n", ix, ivl_expr_uvalue(expr));
break;
{
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;
case IVL_EX_SIGNAL: {
ivl_signal_t sig = ivl_expr_signal(expr);

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_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

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
number. The idx value selects the index register. This is different
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>
@ -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
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
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
provide a basic auto-increment behavior.