Add unsigned bit based power support to normal expressions.
This patch adds bit based power support to normal expressions. It also pushes the constant unsigned bit based calculation to the runtime until the bit based method can be copied to the compiler. Continuous assignments also need to use this type of calculation.
This commit is contained in:
parent
1b410f0c7d
commit
e82293c981
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -185,12 +185,6 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
|||
case 'p':
|
||||
tmp = new NetEBPow(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
if (tmp->expr_type() == IVL_VT_LOGIC) {
|
||||
cerr << get_fileline() << ": sorry: Power operator is not "
|
||||
"currently supported on unsigned bit based values."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '*':
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -979,7 +979,11 @@ NetExpr* NetEBPow::eval_tree(int prune_to_width)
|
|||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
return new NetEConst( pow(lval,rval) );
|
||||
if (lc->has_sign() || rc->has_sign()) {
|
||||
return new NetEConst( pow(lval,rval) );
|
||||
} else {
|
||||
return 0; // For now force this to the runtime.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1634,4 +1638,3 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
|||
|
||||
return new NetEConst(verinum(res, 1));
|
||||
}
|
||||
|
||||
|
|
|
|||
1
t-dll.cc
1
t-dll.cc
|
|
@ -1783,6 +1783,7 @@ void dll_target::lpm_pow(const NetPow*net)
|
|||
assert(obj->scope);
|
||||
|
||||
unsigned wid = net->width_r();
|
||||
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
|
||||
|
||||
obj->width = wid;
|
||||
|
||||
|
|
|
|||
|
|
@ -1234,7 +1234,8 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
|
|||
break;
|
||||
|
||||
case 'p':
|
||||
assert(0);
|
||||
fprintf(vvp_out, " %%pow%s %u, %u, %u;\n", sign_string,
|
||||
lv.base, rv.base, wid);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -2394,4 +2395,3 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
|
|||
{
|
||||
return draw_eval_expr_wid(exp, ivl_expr_width(exp), stuff_ok_flag);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1709,7 +1709,7 @@ static void draw_lpm_add(ivl_lpm_t net)
|
|||
if (dto == IVL_VT_REAL)
|
||||
type = "pow.r";
|
||||
else
|
||||
assert(0); /* Not supported for bit based signals, */
|
||||
assert(0); /* No support for bit based signals. */
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ extern bool of_NOR(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_NORR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_OR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ORR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_POW(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_POW_WR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_RELEASE_NET(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%or", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%pow/wr", of_POW_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%release/net",of_RELEASE_NET,1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
|
||||
{ "%release/reg",of_RELEASE_REG,1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
|
||||
|
|
|
|||
|
|
@ -570,6 +570,12 @@ and the <dst> is a writable scalar. The <dst> gets the value of the
|
|||
or of all the bits of the src vector.
|
||||
|
||||
|
||||
* %pow <bit-l>, <bit-r>
|
||||
|
||||
This opcode raises <bit-l> (unsigned) to the power of <bit-r> (unsigned).
|
||||
The result replaces the left operand.
|
||||
|
||||
|
||||
* %pow/wr <bit-l>, <bit-r>
|
||||
|
||||
This opcode raises <bit-l> (real) to the power of <bit-r> (real). The
|
||||
|
|
|
|||
|
|
@ -3172,6 +3172,77 @@ 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);
|
||||
|
||||
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);
|
||||
|
||||
/* 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)
|
||||
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);
|
||||
|
||||
|
||||
vvp_vector2_t result = calc_uspow(vvp_vector2_t(xval),
|
||||
vvp_vector2_t(yval));
|
||||
|
||||
/* If the result is too small zero pad it. */
|
||||
if (result.size() < wid) {
|
||||
for (unsigned idx = wid-1; idx >= result.size(); idx -= 1)
|
||||
thr_put_bit(thr, cp->bit_idx[0]+idx, BIT4_0);
|
||||
wid = result.size();
|
||||
}
|
||||
|
||||
/* Copy only what we need of the result. */
|
||||
for (unsigned idx = 0; idx < wid; idx += 1)
|
||||
thr_put_bit(thr, cp->bit_idx[0]+idx,
|
||||
result.value(idx) ? BIT4_1 : BIT4_0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_POW_WR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
double l = thr->words[cp->bit_idx[0]].w_real;
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,11 @@ vvp_vector2_t::~vvp_vector2_t()
|
|||
if (vec_) delete[]vec_;
|
||||
}
|
||||
|
||||
void vvp_vector2_t::trim()
|
||||
{
|
||||
while (value(wid_-1) == 0 && wid_ > 1) wid_ -= 1;
|
||||
}
|
||||
|
||||
unsigned vvp_vector2_t::size() const
|
||||
{
|
||||
return wid_;
|
||||
|
|
@ -2473,4 +2478,3 @@ vvp_bit4_t compare_gtge_signed(const vvp_vector4_t&a,
|
|||
else
|
||||
return BIT4_0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -307,6 +307,8 @@ class vvp_vector2_t {
|
|||
unsigned size() const;
|
||||
int value(unsigned idx) const;
|
||||
void set_bit(unsigned idx, int bit);
|
||||
// Make the size just big enough to hold the first 1 bit.
|
||||
void trim();
|
||||
|
||||
private:
|
||||
enum { BITS_PER_WORD = 8 * sizeof(unsigned long) };
|
||||
|
|
|
|||
Loading…
Reference in New Issue