Merge branch 'master' of ssh://steve-icarus@icarus.com/home/u/icarus/steve/git/verilog
This commit is contained in:
commit
659714f45d
65
elab_expr.cc
65
elab_expr.cc
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue