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