Merge branch 'master' of git://github.com/steveicarus/iverilog into vhdl

This commit is contained in:
Nick Gasson 2008-05-28 17:23:12 +01:00
commit e178baefbd
8 changed files with 566 additions and 575 deletions

View File

@ -92,7 +92,7 @@ unsigned long get_number_immediate(ivl_expr_t ex)
case '0': case '0':
break; break;
case '1': case '1':
imm |= 1 << idx; imm |= 1UL << idx;
break; break;
default: default:
assert(0); assert(0);
@ -909,12 +909,43 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
return lv; return lv;
} }
static struct vector_info draw_logic_immediate(ivl_expr_t exp,
ivl_expr_t le,
ivl_expr_t re,
unsigned wid)
{
struct vector_info lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
unsigned long imm = get_number_immediate(re);
assert(lv.base >= 4);
switch (ivl_expr_opcode(exp)) {
case '&':
fprintf(vvp_out, " %%andi %u, %lu, %u;\n", lv.base, imm, lv.wid);
break;
default:
assert(0);
break;
}
return lv;
}
static struct vector_info draw_binary_expr_logic(ivl_expr_t exp, static struct vector_info draw_binary_expr_logic(ivl_expr_t exp,
unsigned wid) unsigned wid)
{ {
ivl_expr_t le = ivl_expr_oper1(exp); ivl_expr_t le = ivl_expr_oper1(exp);
ivl_expr_t re = ivl_expr_oper2(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))
return draw_logic_immediate(exp, le, re, wid);
if (number_is_immediate(le, IMM_WID) && !number_is_unknown(le))
return draw_logic_immediate(exp, re, le, wid);
}
struct vector_info lv; struct vector_info lv;
struct vector_info rv; struct vector_info rv;
@ -1167,15 +1198,15 @@ static struct vector_info draw_add_immediate(ivl_expr_t le,
imm = get_number_immediate(re); imm = get_number_immediate(re);
/* Now generate enough %addi instructions to add the entire /* Now generate enough %addi instructions to add the entire
immediate value to the destination. The adds are done 16 immediate value to the destination. The adds are done IMM_WID
bits at a time, but 17 bits are done to push the carry into bits at a time, but +1 bits are done to push the carry into
the higher bits if needed. */ the higher bits if needed. */
{ unsigned base; { unsigned base;
for (base = 0 ; base < lv.wid ; base += 16) { for (base = 0 ; base < lv.wid ; base += IMM_WID) {
unsigned long tmp = imm & 0xffffUL; unsigned long tmp = imm & 0xffffffffUL;
unsigned add_wid = lv.wid - base; unsigned add_wid = lv.wid - base;
imm >>= 16; imm >>= IMM_WID;
fprintf(vvp_out, " %%addi %u, %lu, %u;\n", fprintf(vvp_out, " %%addi %u, %lu, %u;\n",
lv.base+base, tmp, add_wid); lv.base+base, tmp, add_wid);
@ -1203,7 +1234,7 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le,
assert(lv.wid == wid); assert(lv.wid == wid);
imm = get_number_immediate(re); imm = get_number_immediate(re);
assert( (imm & ~0xffff) == 0 ); assert( (imm & ~0xffffffffUL) == 0 );
switch (lv.base) { switch (lv.base) {
case 0: case 0:
@ -1299,13 +1330,13 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
if ((ivl_expr_opcode(exp) == '-') if ((ivl_expr_opcode(exp) == '-')
&& (ivl_expr_type(re) == IVL_EX_NUMBER) && (ivl_expr_type(re) == IVL_EX_NUMBER)
&& (! number_is_unknown(re)) && (! number_is_unknown(re))
&& number_is_immediate(re, 16)) && number_is_immediate(re, IMM_WID))
return draw_sub_immediate(le, re, wid); return draw_sub_immediate(le, re, wid);
if ((ivl_expr_opcode(exp) == '*') if ((ivl_expr_opcode(exp) == '*')
&& (ivl_expr_type(re) == IVL_EX_NUMBER) && (ivl_expr_type(re) == IVL_EX_NUMBER)
&& (! number_is_unknown(re)) && (! number_is_unknown(re))
&& number_is_immediate(re, 16)) && number_is_immediate(re, IMM_WID))
return draw_mul_immediate(le, re, wid); return draw_mul_immediate(le, re, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ); lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
@ -1612,9 +1643,9 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
vvp_errors += 1; vvp_errors += 1;
} }
if ((!number_is_unknown(exp)) && number_is_immediate(exp, 16)) { if ((!number_is_unknown(exp)) && number_is_immediate(exp, IMM_WID)) {
int val = get_number_immediate(exp); unsigned long val = get_number_immediate(exp);
fprintf(vvp_out, " %%movi %u, %d, %u;\n", res.base, val, wid); fprintf(vvp_out, " %%movi %u, %lu, %u;\n", res.base, val, wid);
return res; return res;
} }
@ -1836,8 +1867,8 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
idx = 0; idx = 0;
while (idx < nwid) { while (idx < nwid) {
unsigned bits; unsigned bits;
unsigned trans = 16; unsigned trans = IMM_WID;
if (nwid-idx < 16) if (nwid-idx < trans)
trans = nwid-idx; trans = nwid-idx;
bits = *p; bits = *p;
@ -1845,6 +1876,14 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
if (trans > 8) { if (trans > 8) {
bits |= *p << 8; bits |= *p << 8;
p -= 1; p -= 1;
if (trans > 16) {
bits |= *p << 16;
p -= 1;
if (trans > 24) {
bits |= *p << 24;
p -= 1;
}
}
} }
fprintf(vvp_out, " %%movi %u, %u, %u;\n", res.base+idx,bits,trans); fprintf(vvp_out, " %%movi %u, %u, %u;\n", res.base+idx,bits,trans);
@ -1881,8 +1920,14 @@ void pad_expr_in_place(ivl_expr_t exp, struct vector_info res, unsigned swid)
res.base+idx, res.base+swid-1); res.base+idx, res.base+swid-1);
} else { } else {
fprintf(vvp_out, " %%mov %u, 0, %u;\n", unsigned base = res.base+swid;
res.base+swid, res.wid-swid); unsigned count = res.wid-swid;
/* The %movi is faster for larger widths, but for very
small counts, the %mov is faster. */
if (count > 4)
fprintf(vvp_out, " %%movi %u, 0, %u;\n", base, count);
else
fprintf(vvp_out, " %%mov %u, 0, %u;\n", base, count);
} }
} }
@ -2086,7 +2131,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
for (idx = 0 ; idx < res.wid ; idx += 1) { for (idx = 0 ; idx < res.wid ; idx += 1) {
if (idx >= bit_wid) { if (idx >= bit_wid) {
fprintf(vvp_out, " %%mov %u, 0, %u; Pad from %u to %u\n", fprintf(vvp_out, " %%movi %u, 0, %u; Pad from %u to %u\n",
res.base+idx, res.wid-idx, res.base+idx, res.wid-idx,
ivl_expr_width(sube), wid); ivl_expr_width(sube), wid);
break; break;
@ -2410,7 +2455,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
fprintf(vvp_out, " %%mov %u, %u, %u;\n", fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, res.base, res.wid); tmp.base, res.base, res.wid);
fprintf(vvp_out, " %%mov %u, 0, %u;\n", fprintf(vvp_out, " %%movi %u, 0, %u;\n",
tmp.base+res.wid, tmp.wid-res.wid); tmp.base+res.wid, tmp.wid-res.wid);
clr_vector(res); clr_vector(res);
res = tmp; res = tmp;
@ -2460,7 +2505,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
assert(res.base); assert(res.base);
fprintf(vvp_out, " %%mov %u, %u, %u;\n", fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, res.base, res.wid); tmp.base, res.base, res.wid);
fprintf(vvp_out, " %%mov %u, 0, %u;\n", fprintf(vvp_out, " %%movi %u, 0, %u;\n",
tmp.base+res.wid, tmp.wid-res.wid); tmp.base+res.wid, tmp.wid-res.wid);
clr_vector(res); clr_vector(res);
res = tmp; res = tmp;

View File

@ -39,6 +39,12 @@ struct vector_info {
unsigned wid; unsigned wid;
}; };
/*
* Convenient constants...
*/
/* Width limit for typical immediate arguments. */
# define IMM_WID 32
/* /*
* Mangle all non-symbol characters in an identifier, quotes in names * Mangle all non-symbol characters in an identifier, quotes in names
*/ */

View File

@ -37,6 +37,7 @@ extern bool of_ADD(vthread_t thr, vvp_code_t code);
extern bool of_ADD_WR(vthread_t thr, vvp_code_t code); extern bool of_ADD_WR(vthread_t thr, vvp_code_t code);
extern bool of_ADDI(vthread_t thr, vvp_code_t code); extern bool of_ADDI(vthread_t thr, vvp_code_t code);
extern bool of_AND(vthread_t thr, vvp_code_t code); extern bool of_AND(vthread_t thr, vvp_code_t code);
extern bool of_ANDI(vthread_t thr, vvp_code_t code);
extern bool of_ANDR(vthread_t thr, vvp_code_t code); extern bool of_ANDR(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_AV(vthread_t thr, vvp_code_t code); extern bool of_ASSIGN_AV(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t code); extern bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t code);
@ -167,7 +168,7 @@ struct vvp_code_s {
}; };
union { union {
unsigned bit_idx[2]; uint32_t bit_idx[2];
vvp_net_t *net2; vvp_net_t *net2;
vvp_code_t cptr2; vvp_code_t cptr2;
struct ufunc_core*ufunc_core_ptr; struct ufunc_core*ufunc_core_ptr;

View File

@ -85,6 +85,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%addi", of_ADDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%addi", of_ADDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%andi", of_ANDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%assign/av",of_ASSIGN_AV,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} }, { "%assign/av",of_ASSIGN_AV,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/av/d",of_ASSIGN_AVD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} }, { "%assign/av/d",of_ASSIGN_AVD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, { "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },

View File

@ -531,7 +531,8 @@ is one of the 4 constant bits, the effect is to replicate the value
into the destination vector. This is useful for filling a vector. into the destination vector. This is useful for filling a vector.
The %movi variant moves a binary value, LSB first, into the The %movi variant moves a binary value, LSB first, into the
destination vector. destination vector. The immediate value is up to 32bits, padded with
zeros to fillout the width.
* %mul <bit-l>, <bit-r>, <wid> * %mul <bit-l>, <bit-r>, <wid>

File diff suppressed because it is too large Load Diff

View File

@ -61,28 +61,6 @@ vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c)
} }
} }
vvp_bit4_t operator & (vvp_bit4_t a, vvp_bit4_t b)
{
if (a == BIT4_0)
return BIT4_0;
if (b == BIT4_0)
return BIT4_0;
if (bit4_is_xz(a))
return BIT4_X;
if (bit4_is_xz(b))
return BIT4_X;
return BIT4_1;
}
vvp_bit4_t operator | (vvp_bit4_t a, vvp_bit4_t b)
{
if (a == BIT4_1)
return BIT4_1;
if (b == BIT4_1)
return BIT4_1;
return bit4_z2x( (vvp_bit4_t) ((int)a | (int)b) );
}
vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b) vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b)
{ {
if (bit4_is_xz(a)) if (bit4_is_xz(a))

View File

@ -87,8 +87,21 @@ inline vvp_bit4_t bit4_z2x(vvp_bit4_t a)
inline vvp_bit4_t operator ~ (vvp_bit4_t a) inline vvp_bit4_t operator ~ (vvp_bit4_t a)
{ return bit4_z2x((vvp_bit4_t) (((int)a) ^ 1)); } { return bit4_z2x((vvp_bit4_t) (((int)a) ^ 1)); }
extern vvp_bit4_t operator | (vvp_bit4_t a, vvp_bit4_t b); inline vvp_bit4_t operator | (vvp_bit4_t a, vvp_bit4_t b)
extern vvp_bit4_t operator & (vvp_bit4_t a, vvp_bit4_t b); {
if (a==BIT4_1 || b==BIT4_1)
return BIT4_1;
return bit4_z2x( (vvp_bit4_t) ((int)a | (int)b) );
}
inline vvp_bit4_t operator & (vvp_bit4_t a, vvp_bit4_t b)
{
if (a==BIT4_0 || b==BIT4_0)
return BIT4_0;
return bit4_z2x( (vvp_bit4_t) ((int)a | (int)b) );
}
extern vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b); extern vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b);
extern ostream& operator<< (ostream&o, vvp_bit4_t a); extern ostream& operator<< (ostream&o, vvp_bit4_t a);
@ -294,41 +307,47 @@ inline void vvp_vector4_t::set_bit(unsigned idx, vvp_bit4_t val)
assert(idx < size_); assert(idx < size_);
unsigned long off = idx % BITS_PER_WORD; unsigned long off = idx % BITS_PER_WORD;
unsigned long amask = 0, bmask = 0;
switch (val) {
case BIT4_0:
amask = 0;
bmask = 0;
break;
case BIT4_1:
amask = 1;
bmask = 0;
break;
case BIT4_X:
amask = 1;
bmask = 1;
break;
case BIT4_Z:
amask = 0;
bmask = 1;
break;
}
unsigned long mask = 1UL << off; unsigned long mask = 1UL << off;
amask <<= off;
bmask <<= off;
if (size_ > BITS_PER_WORD) { if (size_ > BITS_PER_WORD) {
unsigned wdx = idx / BITS_PER_WORD; unsigned wdx = idx / BITS_PER_WORD;
switch (val) {
case BIT4_0:
abits_ptr_[wdx] &= ~mask; abits_ptr_[wdx] &= ~mask;
abits_ptr_[wdx] |= amask;
bbits_ptr_[wdx] &= ~mask; bbits_ptr_[wdx] &= ~mask;
bbits_ptr_[wdx] |= bmask; break;
case BIT4_1:
abits_ptr_[wdx] |= mask;
bbits_ptr_[wdx] &= ~mask;
break;
case BIT4_X:
abits_ptr_[wdx] |= mask;
bbits_ptr_[wdx] |= mask;
break;
case BIT4_Z:
abits_ptr_[wdx] &= ~mask;
bbits_ptr_[wdx] |= mask;
break;
}
} else { } else {
switch (val) {
case BIT4_0:
abits_val_ &= ~mask; abits_val_ &= ~mask;
abits_val_ |= amask;
bbits_val_ &= ~mask; bbits_val_ &= ~mask;
bbits_val_ |= bmask; break;
case BIT4_1:
abits_val_ |= mask;
bbits_val_ &= ~mask;
break;
case BIT4_X:
abits_val_ |= mask;
bbits_val_ |= mask;
break;
case BIT4_Z:
abits_val_ &= ~mask;
bbits_val_ |= mask;
break;
}
} }
} }