Merge branch 'master' of steve-icarus@icarus.com:git/verilog

This commit is contained in:
Stephen Williams 2008-02-06 18:38:55 -08:00
commit 0ac36dc5af
11 changed files with 109 additions and 48 deletions

View File

@ -1139,17 +1139,17 @@ NetNet* PEBinary::elaborate_net_pow_(Design*des, NetScope*scope,
return 0;
}
// The power is signed if either its operands are signed.
bool arith_is_signed = lsig->get_signed() || rsig->get_signed();
/* For now we only support real values. */
if (lsig->data_type() != IVL_VT_REAL) {
cerr << get_fileline() << ": sorry: Bit based power (**) is "
if (lsig->data_type() != IVL_VT_REAL && arith_is_signed) {
cerr << get_fileline() << ": sorry: Signed bit based power (**) is "
<< "currently unsupported in continuous assignments." << endl;
des->errors += 1;
return 0;
}
// The power is signed if both its operands are signed.
bool arith_is_signed = lsig->get_signed() && rsig->get_signed();
unsigned rwidth = lwidth;
if (rwidth == 0) {
/* Reals are always 1 wide and lsig/rsig types match here. */

View File

@ -1708,8 +1708,10 @@ static void draw_lpm_add(ivl_lpm_t net)
case IVL_LPM_POW:
if (dto == IVL_VT_REAL)
type = "pow.r";
else if (ivl_lpm_signed(net))
assert(0); /* No support for signed bit based signals. */
else
assert(0); /* No support for bit based signals. */
type = "pow";
break;
default:
assert(0);
@ -2094,7 +2096,7 @@ static void draw_lpm_ufunc(ivl_lpm_t net)
const char*dly = draw_lpm_output_delay(net);
fprintf(vvp_out, "L_%p%s .ufunc TD_%s, %u", net, dly,
ivl_scope_name(def),
vvp_mangle_id(ivl_scope_name(def)),
ivl_lpm_width(net));
/* Print all the net signals that connect to the input of the

View File

@ -397,6 +397,37 @@ void vvp_arith_mult::wide(vvp_ipoint_t base, bool push)
}
#endif
// Power
vvp_arith_pow::vvp_arith_pow(unsigned wid)
: vvp_arith_(wid)
{
}
vvp_arith_pow::~vvp_arith_pow()
{
}
void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
{
dispatch_operand_(ptr, bit);
vvp_vector2_t a2 (op_a_);
vvp_vector2_t b2 (op_b_);
if (a2.is_NaN() || b2.is_NaN()) {
vvp_send_vec4(ptr.ptr()->out, x_val_);
return;
}
vvp_vector2_t result = pow(a2, b2);
vvp_vector4_t res4 = vector2_to_vector4(result, wid_);
vvp_send_vec4(ptr.ptr()->out, res4);
}
// Addition
vvp_arith_sum::vvp_arith_sum(unsigned wid)

View File

@ -159,6 +159,14 @@ class vvp_arith_mult : public vvp_arith_ {
void wide_(vvp_net_ptr_t ptr);
};
class vvp_arith_pow : public vvp_arith_ {
public:
explicit vvp_arith_pow(unsigned wid);
~vvp_arith_pow();
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
};
class vvp_arith_sub : public vvp_arith_ {
public:

View File

@ -997,6 +997,22 @@ void compile_arith_mult_r(char*label, unsigned argc, struct symb_s*argv)
make_arith(arith, label, argc, argv);
}
void compile_arith_pow(char*label, long wid,
unsigned argc, struct symb_s*argv)
{
assert( wid > 0 );
if (argc != 2) {
fprintf(stderr, "%s .arith/pow has wrong number of symbols\n", label);
compile_errors += 1;
return;
}
vvp_arith_ *arith = new vvp_arith_pow(wid);
make_arith(arith, label, argc, argv);
}
void compile_arith_pow_r(char*label, unsigned argc, struct symb_s*argv)
{
if (argc != 2) {

View File

@ -146,6 +146,8 @@ extern void compile_part_select_var(char*label, char*src,
* This is called by the parser to make the various arithmetic and
* comparison functors.
*/
extern void compile_arith_pow(char*label, long width,
unsigned argc, struct symb_s*argv);
extern void compile_arith_div(char*label, long width, bool signed_flag,
unsigned argc, struct symb_s*argv);
extern void compile_arith_mod(char*label, long width,

View File

@ -94,6 +94,7 @@
".arith/mod.r" { return K_ARITH_MOD_R; }
".arith/mult" { return K_ARITH_MULT; }
".arith/mult.r" { return K_ARITH_MULT_R; }
".arith/pow" { return K_ARITH_POW; }
".arith/pow.r" { return K_ARITH_POW_R; }
".arith/sub" { return K_ARITH_SUB; }
".arith/sub.r" { return K_ARITH_SUB_R; }

View File

@ -68,7 +68,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_ALIAS K_ALIAS_S K_ALIAS_R
%token K_ARITH_DIV K_ARITH_DIV_R K_ARITH_DIV_S K_ARITH_MOD K_ARITH_MOD_R
%token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R
%token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW_R
%token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R
%token K_ARRAY K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R
%token K_CMP_GE K_CMP_GE_R K_CMP_GE_S K_CMP_GT K_CMP_GT_R K_CMP_GT_S
@ -286,6 +286,11 @@ statement
compile_arith_mult_r($1, obj.cnt, obj.vect);
}
| T_LABEL K_ARITH_POW T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_arith_pow($1, $3, obj.cnt, obj.vect);
}
| T_LABEL K_ARITH_POW_R T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_arith_pow_r($1, obj.cnt, obj.vect);

View File

@ -3172,33 +3172,6 @@ bool of_NOR(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* Basic idea from "Introduction to Programming using SML" by
* Michael R. Hansen and Hans Rischel page 261 and "Seminumerical
* Algorithms, Third Edition" by Donald E. Knuth section 4.6.3.
*/
static vvp_vector2_t calc_uspow(vvp_vector2_t x, vvp_vector2_t y)
{
/* If we have a zero exponent just return a 1 bit wide 1. */
if (y == vvp_vector2_t(0L, 1)) {
return vvp_vector2_t(1L, 1);
}
/* Is the value odd? */
if (y.value(0) == 1) {
y.set_bit(0, 0); // A quick subtract by 1.
vvp_vector2_t res = x * calc_uspow(x, y);
res.trim(); // To keep the size under control trim extra zeros.
return res;
}
y >>= 1; // A fast divide by two. We know the LSB is zero.
vvp_vector2_t z = calc_uspow(x, y);
vvp_vector2_t res = z * z;
res.trim(); // To keep the size under control trim extra zeros.
return res;
}
bool of_POW(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
@ -3206,27 +3179,21 @@ bool of_POW(vthread_t thr, vvp_code_t cp)
unsigned idx = cp->bit_idx[0];
unsigned idy = cp->bit_idx[1];
unsigned wid = cp->number;
vvp_vector4_t xval = vthread_bits_to_vector(thr, idx, wid);
vvp_vector4_t yval = vthread_bits_to_vector(thr, idy, wid);
vvp_vector2_t xv2 = vvp_vector2_t(vthread_bits_to_vector(thr, idx, wid));
vvp_vector2_t yv2 = vvp_vector2_t(vthread_bits_to_vector(thr, idy, wid));
/* If we have an X or Z in the arguments return X. */
if (xval.has_xz() || yval.has_xz()) {
for (unsigned idx = 0 ; idx < cp->number ; idx += 1)
if (xv2.is_NaN() || yv2.is_NaN()) {
for (unsigned idx = 0 ; idx < wid ; idx += 1)
thr_put_bit(thr, cp->bit_idx[0]+idx, BIT4_X);
return true;
}
/* To make the result more manageable trim off the extra bits. */
unsigned min_x_wid = wid;
while (xval.value(min_x_wid-1) == BIT4_0 && min_x_wid > 0) min_x_wid -= 1;
xval.resize(min_x_wid);
unsigned min_y_wid = wid;
while (yval.value(min_y_wid-1) == BIT4_0 && min_y_wid > 0) min_y_wid -= 1;
yval.resize(min_y_wid);
xv2.trim();
yv2.trim();
vvp_vector2_t result = calc_uspow(vvp_vector2_t(xval),
vvp_vector2_t(yval));
vvp_vector2_t result = pow(xv2, yv2);
/* If the result is too small zero pad it. */
if (result.size() < wid) {

View File

@ -1094,6 +1094,33 @@ bool vvp_vector2_t::is_NaN() const
return wid_ == 0;
}
/*
* Basic idea from "Introduction to Programming using SML" by
* Michael R. Hansen and Hans Rischel page 261 and "Seminumerical
* Algorithms, Third Edition" by Donald E. Knuth section 4.6.3.
*/
vvp_vector2_t pow(const vvp_vector2_t&x, vvp_vector2_t&y)
{
/* If we have a zero exponent just return a 1 bit wide 1. */
if (y == vvp_vector2_t(0L, 1)) {
return vvp_vector2_t(1L, 1);
}
/* Is the value odd? */
if (y.value(0) == 1) {
y.set_bit(0, 0); // A quick subtract by 1.
vvp_vector2_t res = x * pow(x, y);
res.trim(); // To keep the size under control trim extra zeros.
return res;
}
y >>= 1; // A fast divide by two. We know the LSB is zero.
vvp_vector2_t z = pow(x, y);
vvp_vector2_t res = z * z;
res.trim(); // To keep the size under control trim extra zeros.
return res;
}
static void multiply_long(unsigned long a, unsigned long b,
unsigned long&low, unsigned long&high)
{

View File

@ -328,6 +328,8 @@ extern vvp_vector2_t operator + (const vvp_vector2_t&, const vvp_vector2_t&);
extern vvp_vector2_t operator * (const vvp_vector2_t&, const vvp_vector2_t&);
extern vvp_vector2_t operator / (const vvp_vector2_t&, const vvp_vector2_t&);
extern vvp_vector2_t operator % (const vvp_vector2_t&, const vvp_vector2_t&);
vvp_vector2_t pow(const vvp_vector2_t&, vvp_vector2_t&);
extern vvp_vector4_t vector2_to_vector4(const vvp_vector2_t&, unsigned wid);
/* A c4string is of the form C4<...> where ... are bits. */
extern vvp_vector4_t c4string_to_vector4(const char*str);