Merge branch 'master' into verilog-ams

This commit is contained in:
Stephen Williams 2008-11-07 20:14:43 -08:00
commit 988fc70368
13 changed files with 105 additions and 42 deletions

View File

@ -484,6 +484,7 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
lsig->vector_width(),
rsig->vector_width());
div->set_line(*this);
div->set_signed(has_sign());
des->add_node(div);
connect(div->pin_DataA(), lsig->pin(0));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2005 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-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
@ -16,9 +16,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_modulo.cc,v 1.9 2005/09/15 22:54:47 steve Exp $"
#endif
# include "config.h"
@ -69,6 +66,16 @@ Link& NetModulo::pin_Result()
return pin(0);
}
void NetModulo::set_signed(bool flag)
{
signed_flag_ = flag;
}
bool NetModulo::get_signed() const
{
return signed_flag_;
}
const Link& NetModulo::pin_Result() const
{
return pin(0);
@ -93,25 +100,3 @@ const Link& NetModulo::pin_DataB() const
{
return pin(2);
}
/*
* $Log: net_modulo.cc,v $
* Revision 1.9 2005/09/15 22:54:47 steve
* Fix bug configuring NetModulo pins.
*
* Revision 1.8 2005/03/12 06:43:35 steve
* Update support for LPM_MOD.
*
* Revision 1.7 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
* Revision 1.6 2003/03/06 00:28:41 steve
* All NetObj objects have lex_string base names.
*
* Revision 1.5 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2002/08/11 23:47:04 steve
* Add missing Log and Ident strings.
*
*/

View File

@ -1176,6 +1176,9 @@ class NetModulo : public NetNode {
unsigned width_a() const;
unsigned width_b() const;
void set_signed(bool);
bool get_signed() const;
Link& pin_DataA();
Link& pin_DataB();
Link& pin_Result();
@ -1192,6 +1195,8 @@ class NetModulo : public NetNode {
unsigned width_r_;
unsigned width_a_;
unsigned width_b_;
bool signed_flag_;
};
/*

View File

@ -1782,7 +1782,7 @@ void dll_target::lpm_modulo(const NetModulo*net)
unsigned wid = net->width_r();
obj->width = wid;
obj->u_.arith.signed_flag = 0;
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
const Nexus*nex;

View File

@ -1170,6 +1170,8 @@ static void draw_lpm_add(ivl_lpm_t net)
case IVL_LPM_MOD:
if (dto == IVL_VT_REAL)
type = "mod.r";
else if (ivl_lpm_signed(net))
type = "mod.s";
else
type = "mod";
break;

View File

@ -144,13 +144,25 @@ void vvp_arith_div::wide4_(vvp_net_ptr_t ptr)
}
vvp_vector2_t b2 (op_b_);
if (b2.is_NaN()) {
if (b2.is_NaN() || b2.is_zero()) {
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
return;
}
vvp_vector2_t res2 = a2 / b2;
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res2, wid_), 0);
bool negate = false;
if (signed_flag_) {
if (a2.value(a2.size()-1)) {
a2 = -a2;
negate = true;
}
if (b2.value(b2.size()-1)) {
b2 = -b2;
negate = !negate;
}
}
vvp_vector2_t res = a2 / b2;
if (negate) res = -res;
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res, wid_), 0);
}
void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
@ -180,17 +192,34 @@ void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
the operands for now, and remember to put the sign back
later. */
if (signed_flag_) {
unsigned long sign_mask = 0;
if (op_a_.size() != 8 * sizeof(unsigned long)) {
sign_mask = -1UL << op_a_.size();
}
if (op_a_.value(op_a_.size()-1)) {
a = (-a) & ~ (-1UL << op_a_.size());
a = (-a) & ~sign_mask;
negate = !negate;
}
sign_mask = 0;
if (op_b_.size() != 8 * sizeof(unsigned long)) {
sign_mask = -1UL << op_b_.size();
}
if (op_b_.value(op_b_.size()-1)) {
b = (-b) & ~ (-1UL << op_b_.size());
b = (-b) & ~sign_mask;
negate = ! negate;
}
}
if (b == 0) {
vvp_vector4_t xval (wid_);
for (unsigned idx = 0 ; idx < wid_ ; idx += 1)
xval.set_bit(idx, BIT4_X);
vvp_send_vec4(ptr.ptr()->out, xval, 0);
return;
}
unsigned long val = a / b;
if (negate)
val = -val;
@ -229,12 +258,23 @@ void vvp_arith_mod::wide_(vvp_net_ptr_t ptr)
}
vvp_vector2_t b2 (op_b_);
if (b2.is_NaN()) {
if (b2.is_NaN() || b2.is_zero()) {
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
return;
}
bool negate = false;
if (signed_flag_) {
if (a2.value(a2.size()-1)) {
a2 = -a2;
negate = true;
}
if (b2.value(b2.size()-1)) {
b2 = -b2;
}
}
vvp_vector2_t res = a2 % b2;
if (negate) res = -res;
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res, res.size()), 0);
}
@ -265,14 +305,21 @@ void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
the operands for now, and remember to put the sign back
later. */
if (signed_flag_) {
unsigned long sign_mask = 0;
if (op_a_.size() != 8 * sizeof(unsigned long)) {
sign_mask = -1UL << op_a_.size();
}
if (op_a_.value(op_a_.size()-1)) {
a = (-a) & ~ (-1UL << op_a_.size());
a = (-a) & ~sign_mask;
negate = !negate;
}
sign_mask = 0;
if (op_b_.size() != 8 * sizeof(unsigned long)) {
sign_mask = -1UL << op_b_.size();
}
if (op_b_.value(op_b_.size()-1)) {
b = (-b) & ~ (-1UL << op_b_.size());
negate = ! negate;
b = (-b) & ~sign_mask;
}
}

View File

@ -979,7 +979,7 @@ void compile_arith_div_r(char*label, unsigned argc, struct symb_s*argv)
make_arith(arith, label, argc, argv);
}
void compile_arith_mod(char*label, long wid,
void compile_arith_mod(char*label, long wid, bool signed_flag,
unsigned argc, struct symb_s*argv)
{
assert( wid > 0 );
@ -990,7 +990,7 @@ void compile_arith_mod(char*label, long wid,
return;
}
vvp_arith_ *arith = new vvp_arith_mod(wid, false);
vvp_arith_ *arith = new vvp_arith_mod(wid, signed_flag);
make_arith(arith, label, argc, argv);
}

View File

@ -157,7 +157,7 @@ extern void compile_arith_cast_real(char*label, bool signed_flag,
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,
extern void compile_arith_mod(char*label, long width, bool signed_flag,
unsigned argc, struct symb_s*argv);
extern void compile_arith_mult(char*label, long width,
unsigned argc, struct symb_s*argv);

View File

@ -93,6 +93,7 @@
".arith/div.s" { return K_ARITH_DIV_S; }
".arith/mod" { return K_ARITH_MOD; }
".arith/mod.r" { return K_ARITH_MOD_R; }
".arith/mod.s" { return K_ARITH_MOD_S; }
".arith/mult" { return K_ARITH_MULT; }
".arith/mult.r" { return K_ARITH_MULT_R; }
".arith/pow" { return K_ARITH_POW; }

View File

@ -67,7 +67,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_A K_ALIAS K_ALIAS_S K_ALIAS_R
%token K_ARITH_ABS K_ARITH_DIV K_ARITH_DIV_R K_ARITH_DIV_S K_ARITH_MOD
%token K_ARITH_MOD_R
%token K_ARITH_MOD_R K_ARITH_MOD_S
%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 K_ARITH_POW_R K_ARITH_POW_S
%token K_ARRAY K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT
@ -288,7 +288,7 @@ statement
| T_LABEL K_ARITH_MOD T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_arith_mod($1, $3, obj.cnt, obj.vect);
compile_arith_mod($1, $3, false, obj.cnt, obj.vect);
}
| T_LABEL K_ARITH_MOD_R T_NUMBER ',' symbols ';'
@ -296,6 +296,11 @@ statement
compile_arith_mod_r($1, obj.cnt, obj.vect);
}
| T_LABEL K_ARITH_MOD_S T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_arith_mod($1, $3, true, obj.cnt, obj.vect);
}
| T_LABEL K_ARITH_MULT T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_arith_mult($1, $3, obj.cnt, obj.vect);

View File

@ -3085,7 +3085,7 @@ bool of_LOADI_WR(vthread_t thr, vvp_code_t cp)
static void do_verylong_mod(vthread_t thr, vvp_code_t cp,
bool left_is_neg, bool right_is_neg)
{
bool out_is_neg = left_is_neg != right_is_neg;
bool out_is_neg = left_is_neg;
int len=cp->number;
unsigned char *a, *z, *t;
a = new unsigned char[len+1];

View File

@ -2020,6 +2020,21 @@ static void div_mod (vvp_vector2_t dividend, vvp_vector2_t divisor,
remainder = vvp_vector2_t(dividend, mask.size());
}
vvp_vector2_t operator - (const vvp_vector2_t&that)
{
vvp_vector2_t neg(that);
if (neg.wid_ == 0) return neg;
const unsigned words = (neg.wid_ + neg.BITS_PER_WORD-1) /
neg.BITS_PER_WORD;
for (unsigned idx = 0 ; idx < words ; idx += 1) {
neg.vec_[idx] = ~neg.vec_[idx];
}
neg += vvp_vector2_t(1, neg.wid_);
return neg;
}
vvp_vector2_t operator / (const vvp_vector2_t&dividend,
const vvp_vector2_t&divisor)
{

View File

@ -564,6 +564,7 @@ class vvp_vector4array_aa : public vvp_vector4array_t, public automatic_hooks_s
*/
class vvp_vector2_t {
friend vvp_vector2_t operator - (const vvp_vector2_t&);
friend vvp_vector2_t operator + (const vvp_vector2_t&,
const vvp_vector2_t&);
friend vvp_vector2_t operator * (const vvp_vector2_t&,
@ -619,6 +620,7 @@ extern bool operator >= (const vvp_vector2_t&, const vvp_vector2_t&);
extern bool operator < (const vvp_vector2_t&, const vvp_vector2_t&);
extern bool operator <= (const vvp_vector2_t&, const vvp_vector2_t&);
extern bool operator == (const vvp_vector2_t&, const vvp_vector2_t&);
extern vvp_vector2_t operator - (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&);