Support signed integer division.

This commit is contained in:
steve 2002-04-14 18:41:34 +00:00
parent 5cf7355c91
commit eb27dc8db3
6 changed files with 243 additions and 174 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: netlist.cc,v 1.181 2002/02/01 05:09:14 steve Exp $"
#ident "$Id: netlist.cc,v 1.182 2002/04/14 18:41:34 steve Exp $"
#endif
# include "config.h"
@ -1825,6 +1825,8 @@ NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r)
expr_width(r->expr_width());
else
expr_width(l->expr_width());
cast_signed(l->has_sign() && r->has_sign());
}
NetEBAdd::~NetEBAdd()
@ -1923,6 +1925,7 @@ NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
w = r->expr_width();
expr_width(w);
cast_signed(l->has_sign() && r->has_sign());
}
NetEBDiv::~NetEBDiv()
@ -1978,6 +1981,7 @@ NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
expr_width(l->expr_width() + r->expr_width());
cast_signed(l->has_sign() && r->has_sign());
}
NetEBMult::~NetEBMult()
@ -2423,6 +2427,9 @@ const NetProc*NetTaskDef::proc() const
/*
* $Log: netlist.cc,v $
* Revision 1.182 2002/04/14 18:41:34 steve
* Support signed integer division.
*
* Revision 1.181 2002/02/01 05:09:14 steve
* Propagate sign in unary minus.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: eval_expr.c,v 1.56 2002/02/03 05:53:00 steve Exp $"
#ident "$Id: eval_expr.c,v 1.57 2002/04/14 18:41:34 steve Exp $"
#endif
# include "vvp_priv.h"
@ -548,6 +548,8 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
struct vector_info lv;
struct vector_info rv;
const char*sign_string = ivl_expr_signed(exp)? "/s" : "";
lv = draw_eval_expr_wid(le, wid);
rv = draw_eval_expr_wid(re, wid);
@ -582,7 +584,8 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
break;
case '/':
fprintf(vvp_out, " %%div %u, %u, %u;\n", lv.base, rv.base, wid);
fprintf(vvp_out, " %%div%s %u, %u, %u;\n", sign_string,
lv.base, rv.base, wid);
break;
case '%':
@ -1503,6 +1506,9 @@ struct vector_info draw_eval_expr(ivl_expr_t exp)
/*
* $Log: eval_expr.c,v $
* Revision 1.57 2002/04/14 18:41:34 steve
* Support signed integer division.
*
* Revision 1.56 2002/02/03 05:53:00 steve
* Fix parameter bit select check for magic constants.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: codes.h,v 1.38 2002/03/18 00:19:34 steve Exp $"
#ident "$Id: codes.h,v 1.39 2002/04/14 18:41:34 steve Exp $"
#endif
@ -52,6 +52,7 @@ extern bool of_DELAY(vthread_t thr, vvp_code_t code);
extern bool of_DELAYX(vthread_t thr, vvp_code_t code);
extern bool of_DISABLE(vthread_t thr, vvp_code_t code);
extern bool of_DIV(vthread_t thr, vvp_code_t code);
extern bool of_DIV_S(vthread_t thr, vvp_code_t code);
extern bool of_END(vthread_t thr, vvp_code_t code);
extern bool of_FORCE(vthread_t thr, vvp_code_t code);
extern bool of_FORK(vthread_t thr, vvp_code_t code);
@ -151,6 +152,9 @@ extern vvp_code_t codespace_index(vvp_cpoint_t ptr);
/*
* $Log: codes.h,v $
* Revision 1.39 2002/04/14 18:41:34 steve
* Support signed integer division.
*
* Revision 1.38 2002/03/18 00:19:34 steve
* Add the .ufunc statement.
*
@ -165,70 +169,5 @@ extern vvp_code_t codespace_index(vvp_cpoint_t ptr);
*
* Revision 1.34 2001/08/26 22:59:32 steve
* Add the assign/x0 and set/x opcodes.
*
* Revision 1.33 2001/07/22 00:04:50 steve
* Add the load/x instruction for bit selects.
*
* Revision 1.32 2001/07/19 04:40:55 steve
* Add support for the delayx opcode.
*
* Revision 1.31 2001/06/30 21:07:26 steve
* Support non-const right shift (unsigned).
*
* Revision 1.30 2001/06/23 18:26:26 steve
* Add the %shiftl/i0 instruction.
*
* Revision 1.29 2001/06/18 01:09:32 steve
* More behavioral unary reduction operators.
* (Stephan Boettcher)
*
* Revision 1.28 2001/06/16 23:45:05 steve
* Add support for structural multiply in t-dll.
* Add code generators and vvp support for both
* structural and behavioral multiply.
*
* Revision 1.27 2001/05/24 04:20:10 steve
* Add behavioral modulus.
*
* Revision 1.26 2001/05/09 04:23:18 steve
* Now that the interactive debugger exists,
* there is no use for the output dump.
*
* Revision 1.25 2001/05/06 17:42:22 steve
* Add the %ix/get instruction. (Stephan Boettcher)
*
* Revision 1.24 2001/05/05 23:55:46 steve
* Add the beginnings of an interactive debugger.
*
* Revision 1.23 2001/05/02 23:16:50 steve
* Document memory related opcodes,
* parser uses numbv_s structures instead of the
* symbv_s and a mess of unions,
* Add the %is/sub instruction.
* (Stephan Boettcher)
*
* Revision 1.22 2001/05/02 01:57:25 steve
* Support behavioral subtraction.
*
* Revision 1.21 2001/05/01 01:09:39 steve
* Add support for memory objects. (Stephan Boettcher)
*
* Revision 1.20 2001/04/18 04:21:23 steve
* Put threads into scopes.
*
* Revision 1.19 2001/04/15 16:37:48 steve
* add XOR support.
*
* Revision 1.18 2001/04/15 04:07:56 steve
* Add support for behavioral xnor.
*
* Revision 1.17 2001/04/13 03:55:18 steve
* More complete reap of all threads.
*
* Revision 1.16 2001/04/05 01:12:28 steve
* Get signed compares working correctly in vvp.
*
* Revision 1.15 2001/04/01 22:25:33 steve
* Add the reduction nor instruction.
*/
#endif

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: compile.cc,v 1.123 2002/04/14 02:56:19 steve Exp $"
#ident "$Id: compile.cc,v 1.124 2002/04/14 18:41:34 steve Exp $"
#endif
# include "arith.h"
@ -95,6 +95,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%div/s", of_DIV_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%force", of_FORCE, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
@ -1408,6 +1409,9 @@ vvp_ipoint_t debug_lookup_functor(const char*name)
/*
* $Log: compile.cc,v $
* Revision 1.124 2002/04/14 18:41:34 steve
* Support signed integer division.
*
* Revision 1.123 2002/04/14 02:56:19 steve
* Support signed expressions through to VPI.
*
@ -1438,25 +1442,5 @@ vvp_ipoint_t debug_lookup_functor(const char*name)
*
* Revision 1.114 2001/11/07 03:34:42 steve
* Use functor pointers where vvp_ipoint_t is unneeded.
*
* Revision 1.113 2001/11/06 03:07:21 steve
* Code rearrange. (Stephan Boettcher)
*
* Revision 1.112 2001/11/01 04:42:39 steve
* Handle procedural constant functor pointers.
*
* Revision 1.111 2001/11/01 03:00:19 steve
* Add force/cassign/release/deassign support. (Stephan Boettcher)
*
* Revision 1.110 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.109 2001/10/18 17:30:25 steve
* Support rnpmos devices. (Philip Blundell)
*
* Revision 1.108 2001/10/16 02:47:37 steve
* Add arith/div object.
*/

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* $Id: opcodes.txt,v 1.32 2002/01/26 02:08:07 steve Exp $
* $Id: opcodes.txt,v 1.33 2002/04/14 18:41:34 steve Exp $
*/
@ -160,11 +160,14 @@ the threads that are currently within that scope.
* %div <bit-l>, <bit-r>, <wid>
* %div/s <bit-l>, <bit-r>, <wid>
This instruction arithmetically divides the <bit-l> vector by the
<bit-r> vector, and leaves the result in the <bit-l> vector. IF any of
the bits in either vector are x or z, the entire result is x.
The %div/s instruction is the same as %div, but does signed division.
* %force <fofu-label>, <width>

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vthread.cc,v 1.67 2002/03/18 00:19:34 steve Exp $"
#ident "$Id: vthread.cc,v 1.68 2002/04/14 18:41:34 steve Exp $"
#endif
# include "vthread.h"
@ -650,45 +650,9 @@ bool of_DISABLE(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_DIV(vthread_t thr, vvp_code_t cp)
static void divide_bits(unsigned len, unsigned char*lbits,
const unsigned char*rbits)
{
assert(cp->bit_idx[0] >= 4);
if(cp->number <= 8*sizeof(unsigned long)) {
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
unsigned long lv = 0, rv = 0;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned lb = thr_get_bit(thr, idx1);
unsigned rb = thr_get_bit(thr, idx2);
if ((lb | rb) & 2)
goto x_out;
lv |= lb << idx;
rv |= rb << idx;
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
if (rv == 0)
goto x_out;
lv /= rv;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
thr_put_bit(thr, cp->bit_idx[0]+idx, (lv&1) ? 1 : 0);
lv >>= 1;
}
return true;
} else {
int len=cp->number;
unsigned char *a, *b, *z, *t;
a = new unsigned char[len+1];
b = new unsigned char[len+1];
@ -702,32 +666,19 @@ bool of_DIV(vthread_t thr, vvp_code_t cp)
int i;
int current, copylen;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned lb = thr_get_bit(thr, idx1);
unsigned rb = thr_get_bit(thr, idx2);
if ((lb | rb) & 2) {
delete []t;
delete []z;
delete []b;
delete []a;
goto x_out;
}
for (unsigned idx = 0 ; idx < len ; idx += 1) {
unsigned lb = lbits[idx];
unsigned rb = rbits[idx];
z[idx]=lb;
a[idx]=1-rb; // for 2s complement add..
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
z[len]=0;
a[len]=1;
for(i=0;i<len+1;i++) {
for(i=0;i<(int)len+1;i++) {
b[i]=0;
}
@ -776,15 +727,84 @@ bool of_DIV(vthread_t thr, vvp_code_t cp)
}
tally:
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
for (unsigned idx = 0 ; idx < len ; idx += 1) {
// n.b., z[] has the remainder...
thr_put_bit(thr, cp->bit_idx[0]+idx, b[idx]);
lbits[idx] = b[idx];
}
delete []t;
delete []z;
delete []b;
delete []a;
}
bool of_DIV(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
if(cp->number <= 8*sizeof(unsigned long)) {
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
unsigned long lv = 0, rv = 0;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned lb = thr_get_bit(thr, idx1);
unsigned rb = thr_get_bit(thr, idx2);
if ((lb | rb) & 2)
goto x_out;
lv |= lb << idx;
rv |= rb << idx;
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
if (rv == 0)
goto x_out;
lv /= rv;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
thr_put_bit(thr, cp->bit_idx[0]+idx, (lv&1) ? 1 : 0);
lv >>= 1;
}
return true;
} else {
/* Make a string of the bits of the numbers to be
divided. Then divide them, and write the results into
the thread. */
unsigned char*lbits = new unsigned char[cp->number];
unsigned char*rbits = new unsigned char[cp->number];
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
lbits[idx] = thr_get_bit(thr, idx1);
rbits[idx] = thr_get_bit(thr, idx2);
if ((lbits[idx] | rbits[idx]) > 1) {
delete[]lbits;
delete[]rbits;
goto x_out;
}
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
divide_bits(cp->number, lbits, rbits);
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
thr_put_bit(thr, cp->bit_idx[0]+idx, lbits[idx]);
}
delete[]lbits;
delete[]rbits;
return true;
}
@ -795,6 +815,113 @@ bool of_DIV(vthread_t thr, vvp_code_t cp)
return true;
}
static void negate_bits(unsigned len, unsigned char*bits)
{
unsigned char carry = 1;
for (unsigned idx = 0 ; idx < len ; idx += 1) {
carry += bits[idx]? 0 : 1;
bits[idx] = carry & 1;
carry >>= 1;
}
}
bool of_DIV_S(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
if(cp->number <= 8*sizeof(long)) {
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
long lv = 0, rv = 0;
unsigned lb = 0;
unsigned rb = 0;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
lb = thr_get_bit(thr, idx1);
rb = thr_get_bit(thr, idx2);
if ((lb | rb) & 2)
goto x_out;
lv |= (long)lb << idx;
rv |= (long)rb << idx;
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
/* Extend the sign to fill the native long. */
for (unsigned idx = cp->number; idx < (8*sizeof lv); idx += 1) {
lv |= (long)lb << idx;
rv |= (long)rb << idx;
}
if (rv == 0)
goto x_out;
lv /= rv;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
thr_put_bit(thr, cp->bit_idx[0]+idx, (lv&1) ? 1 : 0);
lv >>= 1;
}
} else {
unsigned char*lbits = new unsigned char[cp->number];
unsigned char*rbits = new unsigned char[cp->number];
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
lbits[idx] = thr_get_bit(thr, idx1);
rbits[idx] = thr_get_bit(thr, idx2);
if ((lbits[idx] | rbits[idx]) > 1) {
delete[]lbits;
delete[]rbits;
goto x_out;
}
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
/* Signed division is unsigned division on the absolute
values of the operands, then corrected for the number
of signs. */
unsigned sign_flag = 0;
if (lbits[cp->number-1]) {
sign_flag += 1;
negate_bits(cp->number, lbits);
}
if (rbits[cp->number-1]) {
sign_flag += 1;
negate_bits(cp->number, rbits);
}
divide_bits(cp->number, lbits, rbits);
if (sign_flag & 1) {
negate_bits(cp->number, lbits);
}
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
thr_put_bit(thr, cp->bit_idx[0]+idx, lbits[idx]);
}
delete[]lbits;
delete[]rbits;
}
return true;
x_out:
for (unsigned idx = 0 ; idx < cp->number ; idx += 1)
thr_put_bit(thr, cp->bit_idx[0]+idx, 2);
return true;
}
/*
* This terminates the current thread. If there is a parent who is
* waiting for me to die, then I schedule it. At any rate, I mark
@ -1749,6 +1876,9 @@ bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp)
/*
* $Log: vthread.cc,v $
* Revision 1.68 2002/04/14 18:41:34 steve
* Support signed integer division.
*
* Revision 1.67 2002/03/18 00:19:34 steve
* Add the .ufunc statement.
*