Allow that sum immediate values can be signed.

Actually, the immediate value handling is a little chaotic and should
be cleaned up. This patch opens the door for allowing signed immediate
values, and uses them in a few places where they are explicitly handled.
We must go through the opcodes that can take immediate values and make
explicit whether they are signed/unsigned/etc, and what their size
limits are.
This commit is contained in:
Stephen Williams 2008-06-13 13:32:06 -07:00
parent 99a46fd5af
commit 7afb280990
8 changed files with 63 additions and 134 deletions

View File

@ -47,9 +47,9 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
const char*dly = "";
if (d_rise != 0) {
assert(number_is_immediate(d_rise, 64));
assert(number_is_immediate(d_fall, 64));
assert(number_is_immediate(d_decay, 64));
assert(number_is_immediate(d_rise, 64, 0));
assert(number_is_immediate(d_fall, 64, 0));
assert(number_is_immediate(d_decay, 64, 0));
dly = "/d";
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
net, get_number_immediate(d_rise),

View File

@ -359,9 +359,9 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
/* We have a delayed constant, so we need to build some code. */
if (d_rise != 0) {
assert(number_is_immediate(d_rise, 64));
assert(number_is_immediate(d_fall, 64));
assert(number_is_immediate(d_decay, 64));
assert(number_is_immediate(d_rise, 64, 0));
assert(number_is_immediate(d_fall, 64, 0));
assert(number_is_immediate(d_decay, 64, 0));
fprintf(vvp_out, "L_%p/d .functor BUFZ 1, %s, "
"C4<0>, C4<0>, C4<0>;\n", cptr, result);

View File

@ -29,82 +29,6 @@
#define snprintf _snprintf
#endif
/*
* Check to see if the expression (number) can be correctly represented
* with a long variable.
*/
static int is_constant_number(ivl_expr_t ex)
{
/* Make sure this matches the return type of constant_number(). */
unsigned lim_wid = 8*sizeof(long);
const char*bits;
char pad_bit = '0';
unsigned idx;
unsigned nbits = ivl_expr_width(ex);
if (ivl_expr_type(ex) != IVL_EX_NUMBER
&& ivl_expr_type(ex) != IVL_EX_ULONG)
return 0;
bits = ivl_expr_bits(ex);
/* For unsigned values the effective MSB and on must be '0'. */
if (!ivl_expr_signed(ex)) lim_wid -= 1;
/* For negative values the pad bit is '1'. */
if (ivl_expr_signed(ex) && bits[nbits-1]=='1') {
pad_bit = '1';
}
/* For the number to fit in the variable all the upper bits must
* match the pad bits. */
for (idx = lim_wid ; idx < nbits ; idx += 1) {
if (bits[idx] != pad_bit) return 0;
}
return 1;
}
/*
* Convert the expression (number) to a long value.
*/
static long get_constant_number(ivl_expr_t ex)
{
long rtn = 0;
switch (ivl_expr_type(ex)) {
case IVL_EX_ULONG:
rtn = (signed)ivl_expr_value(ex);
break;
case IVL_EX_NUMBER: {
unsigned idx;
const char*bits = ivl_expr_bits(ex);
unsigned nbits = ivl_expr_width(ex);
char pad_bit = bits[nbits-1];
/* Define all the bits in the long (negative numbers). */
for (idx = 0 ; idx < 8*sizeof(long) ; idx += 1) {
char bit;
if (idx < nbits) bit = bits[idx];
else bit = pad_bit;
switch (bit) {
case '0':
break;
case '1':
rtn |= 1 << idx;
break;
default:
assert(0);
}
}
break;
}
default:
assert(0);
}
return rtn;
}
static const char* magic_sfuncs[] = {
"$time",
"$stime",
@ -138,7 +62,7 @@ static int is_fixed_memory_word(ivl_expr_t net)
if (ivl_signal_type(sig) == IVL_SIT_REG)
return 0;
if (number_is_immediate(ivl_expr_oper1(net), 8*sizeof(unsigned)))
if (number_is_immediate(ivl_expr_oper1(net), 8*sizeof(unsigned), 0))
return 1;
return 0;
@ -258,7 +182,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
ivl_expr_t word_ex = ivl_expr_oper1(expr);
if (word_ex) {
/* Some array select have been evaluated. */
if (number_is_immediate(word_ex, 8*sizeof(unsigned))) {
if (number_is_immediate(word_ex, 8*sizeof(unsigned), 0)) {
use_word = get_number_immediate(word_ex);
word_ex = 0;
}
@ -280,7 +204,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
ivl_expr_t word_ex = ivl_expr_oper1(expr);
if (word_ex) {
/* Some array select have been evaluated. */
if (number_is_immediate(word_ex, 8*sizeof(unsigned))) {
if (number_is_immediate(word_ex, 8*sizeof(unsigned), 0)) {
use_word = get_number_immediate(word_ex);
word_ex = 0;
}
@ -320,10 +244,10 @@ static void draw_vpi_taskfunc_args(const char*call_string,
assert(bexpr);
/* This is a constant bit/part select. */
if (is_constant_number(bexpr)) {
if (number_is_immediate(bexpr, 64, 1)) {
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>",
ivl_expr_signal(vexpr),
get_constant_number(bexpr),
get_number_immediate(bexpr),
ivl_expr_width(expr));
/* This is an indexed bit/part select. */
} else {

View File

@ -54,9 +54,11 @@ int number_is_unknown(ivl_expr_t ex)
* above bitX. The maximum size of the immediate may vary, so use
* lim_wid at the width limit to use.
*/
int number_is_immediate(ivl_expr_t ex, unsigned lim_wid)
int number_is_immediate(ivl_expr_t ex, unsigned lim_wid, int negative_ok_flag)
{
const char*bits;
unsigned nbits = ivl_expr_width(ex);
char pad_bit = '0';
unsigned idx;
if (ivl_expr_type(ex) != IVL_EX_NUMBER
@ -64,14 +66,17 @@ int number_is_immediate(ivl_expr_t ex, unsigned lim_wid)
return 0;
bits = ivl_expr_bits(ex);
for (idx = lim_wid ; idx < ivl_expr_width(ex) ; idx += 1)
if (bits[idx] != '0')
return 0;
/* Negative numbers are not "immediate". */
if (ivl_expr_signed(ex) && bits[ivl_expr_width(ex)-1]=='1')
if (ivl_expr_signed(ex) && bits[nbits-1]=='1')
pad_bit = '1';
if (pad_bit == '1' && !negative_ok_flag)
return 0;
for (idx = lim_wid ; idx < nbits ; idx += 1)
if (bits[idx] != pad_bit)
return 0;
return 1;
}
@ -146,7 +151,7 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
}
ivl_expr_t ixe = ivl_expr_oper1(expr);
if (number_is_immediate(ixe, 8*sizeof(unsigned long)))
if (number_is_immediate(ixe, 8*sizeof(unsigned long), 0))
word = get_number_immediate(ixe);
else {
struct vector_info rv;
@ -374,7 +379,7 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
return draw_binary_expr_eq_real(exp);
}
if (number_is_immediate(re,16) && !number_is_unknown(re))
if (number_is_immediate(re,16,0) && !number_is_unknown(re))
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
assert(ivl_expr_value(le) == IVL_VT_LOGIC
@ -805,7 +810,7 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
switch (ivl_expr_opcode(exp)) {
case 'G':
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
if (number_is_immediate(le,16) && !number_is_unknown(le)) {
if (number_is_immediate(le,16,0) && !number_is_unknown(le)) {
unsigned imm = get_number_immediate(le);
assert(imm >= 0);
fprintf(vvp_out, " %%cmpi/%c %u, %u, %u;\n", s_flag,
@ -821,7 +826,7 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
case 'L':
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
if (number_is_immediate(re,16) && !number_is_unknown(re)) {
if (number_is_immediate(re,16,0) && !number_is_unknown(re)) {
unsigned imm = get_number_immediate(re);
assert(imm >= 0);
fprintf(vvp_out, " %%cmpi/%c %u, %u, %u;\n", s_flag,
@ -837,7 +842,7 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
case '<':
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
if (number_is_immediate(re,16) && !number_is_unknown(re)) {
if (number_is_immediate(re,16,0) && !number_is_unknown(re)) {
unsigned imm = get_number_immediate(re);
assert(imm >= 0);
fprintf(vvp_out, " %%cmpi/%c %u, %u, %u;\n", s_flag,
@ -852,7 +857,7 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
case '>':
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
if (number_is_immediate(le,16) && !number_is_unknown(le)) {
if (number_is_immediate(le,16,0) && !number_is_unknown(le)) {
unsigned imm = get_number_immediate(le);
assert(imm >= 0);
fprintf(vvp_out, " %%cmpi/%c %u, %u, %u;\n", s_flag,
@ -931,9 +936,9 @@ static struct vector_info draw_binary_expr_logic(ivl_expr_t exp,
ivl_expr_t re = ivl_expr_oper2(exp);
if (ivl_expr_opcode(exp) == '&') {
if (number_is_immediate(re, IMM_WID) && !number_is_unknown(re))
if (number_is_immediate(re, IMM_WID, 0) && !number_is_unknown(re))
return draw_logic_immediate(exp, le, re, wid);
if (number_is_immediate(le, IMM_WID) && !number_is_unknown(le))
if (number_is_immediate(le, IMM_WID, 0) && !number_is_unknown(le))
return draw_logic_immediate(exp, re, le, wid);
}
@ -1341,7 +1346,7 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
if ((ivl_expr_opcode(exp) == '+')
&& (ivl_expr_type(re) == IVL_EX_NUMBER)
&& (! number_is_unknown(re))
&& number_is_immediate(re, 8*sizeof(unsigned long)))
&& number_is_immediate(re, 8*sizeof(unsigned long), 0))
return draw_add_immediate(le, re, wid);
if ((ivl_expr_opcode(exp) == '-')
@ -1351,13 +1356,13 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
if ((ivl_expr_opcode(exp) == '-')
&& (ivl_expr_type(re) == IVL_EX_NUMBER)
&& (! number_is_unknown(re))
&& number_is_immediate(re, IMM_WID))
&& number_is_immediate(re, IMM_WID, 0))
return draw_sub_immediate(le, re, wid);
if ((ivl_expr_opcode(exp) == '*')
&& (ivl_expr_type(re) == IVL_EX_NUMBER)
&& (! number_is_unknown(re))
&& number_is_immediate(re, IMM_WID))
&& number_is_immediate(re, IMM_WID, 0))
return draw_mul_immediate(le, re, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
@ -1664,7 +1669,7 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
vvp_errors += 1;
}
if ((!number_is_unknown(exp)) && number_is_immediate(exp, IMM_WID)) {
if ((!number_is_unknown(exp)) && number_is_immediate(exp, IMM_WID,0)) {
unsigned long val = get_number_immediate(exp);
fprintf(vvp_out, " %%movi %u, %lu, %u;\n", res.base, val, wid);
return res;
@ -2113,7 +2118,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
ivl_expr_t ix = ivl_expr_oper1(sube);
if (ivl_signal_type(sig)==IVL_SIT_REG
|| !number_is_immediate(ix, 8*sizeof(unsigned long)))
|| !number_is_immediate(ix, 8*sizeof(unsigned long),0))
return draw_select_array(sube, bit_idx, bit_wid, wid);
/* The index is constant, so we can return to direct
@ -2124,7 +2129,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
/* Try the special case that the part is at the beginning of
the signal (or the entire width). Just load the early bits
in one go. */
if (number_is_immediate(bit_idx, 32)
if (number_is_immediate(bit_idx, 32, 0)
&& get_number_immediate(bit_idx) == 0
&& (ivl_expr_width(sube) >= bit_wid)) {

View File

@ -328,7 +328,7 @@ static int draw_signal_real_real(ivl_expr_t exp)
if (ivl_signal_array_count(sig) > 1) {
ivl_expr_t ix = ivl_expr_oper1(exp);
if (!number_is_immediate(ix, 8*sizeof(word))) {
if (!number_is_immediate(ix, 8*sizeof(word), 0)) {
/* XXXX Need to generate a %load/ar instruction. */
assert(0);
return res;

View File

@ -269,7 +269,7 @@ extern unsigned allocate_vector_exp(ivl_expr_t exp, unsigned wid,
int exclusive_flag);
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, int negative_is_ok);
extern long get_number_immediate(ivl_expr_t ex);
/*

View File

@ -83,7 +83,7 @@ static void set_to_lvariable(ivl_lval_t lval,
if (part_off_ex == 0) {
part_off = 0;
} else if (number_is_immediate(part_off_ex, 64)) {
} else if (number_is_immediate(part_off_ex, 64, 0)) {
part_off = get_number_immediate(part_off_ex);
part_off_ex = 0;
}
@ -91,7 +91,7 @@ static void set_to_lvariable(ivl_lval_t lval,
/* If the word index is a constant expression, then evaluate
it to select the word, and pay no further heed to the
expression itself. */
if (word_ix && number_is_immediate(word_ix, 8*sizeof(use_word))) {
if (word_ix && number_is_immediate(word_ix, 8*sizeof(use_word), 0)) {
use_word = get_number_immediate(word_ix);
word_ix = 0;
}
@ -227,14 +227,14 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
unsigned part_off = 0;
if (part_off_ex == 0) {
part_off = 0;
} else if (number_is_immediate(part_off_ex, 64)) {
} else if (number_is_immediate(part_off_ex, 64, 0)) {
part_off = get_number_immediate(part_off_ex);
part_off_ex = 0;
}
if (dexp == 0) {
/* Constant delay... */
if (number_is_immediate(word_ix, 64)) {
if (number_is_immediate(word_ix, 64, 0)) {
fprintf(vvp_out, " %%ix/load 3, %lu; address\n",
get_number_immediate(word_ix));
} else {
@ -259,7 +259,7 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
/* Calculated delay... */
int delay_index = allocate_word();
draw_eval_expr_into_integer(dexp, delay_index);
if (number_is_immediate(word_ix, 64)) {
if (number_is_immediate(word_ix, 64, 0)) {
fprintf(vvp_out, " %%ix/load 3, %lu; address\n",
get_number_immediate(word_ix));
} else {
@ -306,7 +306,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
if (part_off_ex == 0) {
part_off = 0;
} else if (number_is_immediate(part_off_ex, 64)) {
} else if (number_is_immediate(part_off_ex, 64, 0)) {
part_off = get_number_immediate(part_off_ex);
part_off_ex = 0;
}
@ -543,7 +543,7 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
if (ivl_signal_array_count(sig) > 1) {
word_ix = ivl_lval_idx(lval);
assert(word_ix);
assert(number_is_immediate(word_ix, 8*sizeof(use_word)));
assert(number_is_immediate(word_ix, 8*sizeof(use_word), 0));
use_word = get_number_immediate(word_ix);
}
@ -700,7 +700,7 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
if ((ivl_statement_type(net) == IVL_ST_CASE)
&& (ivl_expr_type(cex) == IVL_EX_NUMBER)
&& (! number_is_unknown(cex))
&& number_is_immediate(cex, 16)) {
&& number_is_immediate(cex, 16, 0)) {
unsigned long imm = get_number_immediate(cex);
@ -926,12 +926,12 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
if (part_off_ex == 0) {
part_off = 0;
} else {
assert(number_is_immediate(part_off_ex, 64));
assert(number_is_immediate(part_off_ex, 64, 0));
part_off = get_number_immediate(part_off_ex);
}
if (word_idx != 0) {
assert(number_is_immediate(word_idx, 8*sizeof(unsigned long)));
assert(number_is_immediate(word_idx, 8*sizeof(unsigned long), 0));
use_word = get_number_immediate(word_idx);
}
@ -1004,12 +1004,12 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
/* At least for now, only handle force to fixed words of an array. */
if ((lword_idx = ivl_lval_idx(lval)) != 0) {
assert(number_is_immediate(lword_idx, 8*sizeof(unsigned long)));
assert(number_is_immediate(lword_idx, 8*sizeof(unsigned long), 0));
use_lword = get_number_immediate(lword_idx);
}
if ((rword_idx = ivl_expr_oper1(rval)) != 0) {
assert(number_is_immediate(rword_idx, 8*sizeof(unsigned long)));
assert(number_is_immediate(rword_idx, 8*sizeof(unsigned long), 0));
use_rword = get_number_immediate(rword_idx);
}
@ -1087,12 +1087,12 @@ static int show_stmt_deassign(ivl_statement_t net)
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
unsigned part_off = 0;
if (part_off_ex != 0) {
assert(number_is_immediate(part_off_ex, 64));
assert(number_is_immediate(part_off_ex, 64, 0));
part_off = get_number_immediate(part_off_ex);
}
if (word_idx != 0) {
assert(number_is_immediate(word_idx, 8*sizeof(use_word)));
assert(number_is_immediate(word_idx, 8*sizeof(use_word), 0));
use_word = get_number_immediate(word_idx);
}
@ -1369,7 +1369,7 @@ static int show_stmt_release(ivl_statement_t net)
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
unsigned part_off = 0;
if (part_off_ex != 0) {
assert(number_is_immediate(part_off_ex, 64));
assert(number_is_immediate(part_off_ex, 64, 0));
part_off = get_number_immediate(part_off_ex);
}
@ -1383,7 +1383,7 @@ static int show_stmt_release(ivl_statement_t net)
}
if (word_idx != 0) {
assert(number_is_immediate(word_idx, 8*sizeof(use_word)));
assert(number_is_immediate(word_idx, 8*sizeof(use_word), 0));
use_word = get_number_immediate(word_idx);
}

View File

@ -546,9 +546,9 @@ static void draw_delay(ivl_net_logic_t lptr)
return;
/* FIXME: Assume that the expression is a constant */
assert(number_is_immediate(d0, 64));
assert(number_is_immediate(d1, 64));
assert(number_is_immediate(d2, 64));
assert(number_is_immediate(d0, 64, 0));
assert(number_is_immediate(d1, 64, 0));
assert(number_is_immediate(d2, 64, 0));
if (d0 == d1 && d1 == d2)
fprintf(vvp_out, " (%lu)", get_number_immediate(d0));
@ -862,9 +862,9 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
ivl_expr_t fall_exp = ivl_logic_delay(lptr,1);
ivl_expr_t decay_exp = ivl_logic_delay(lptr,2);
if (number_is_immediate(rise_exp,64)
&& number_is_immediate(fall_exp,64)
&& number_is_immediate(decay_exp,64)) {
if (number_is_immediate(rise_exp,64,0)
&& number_is_immediate(fall_exp,64,0)
&& number_is_immediate(decay_exp,64,0)) {
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
lptr, get_number_immediate(rise_exp),
@ -1055,9 +1055,9 @@ static const char* draw_lpm_output_delay(ivl_lpm_t net)
const char*dly = "";
if (d_rise != 0) {
assert(number_is_immediate(d_rise, 64));
assert(number_is_immediate(d_fall, 64));
assert(number_is_immediate(d_decay, 64));
assert(number_is_immediate(d_rise, 64, 0));
assert(number_is_immediate(d_fall, 64, 0));
assert(number_is_immediate(d_decay, 64, 0));
dly = "/d";
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
net, get_number_immediate(d_rise),