Merge branch 'master' of steve-icarus@icarus.com:git/verilog
This commit is contained in:
commit
0ac36dc5af
10
elab_net.cc
10
elab_net.cc
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
31
vvp/arith.cc
31
vvp/arith.cc
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue