Implement signed divide and signed right shift in nets.

This commit is contained in:
steve 2004-06-30 02:16:26 +00:00
parent 57b8ca191f
commit 3dbc07f34d
9 changed files with 165 additions and 51 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_net.cc,v 1.132 2004/06/24 15:22:23 steve Exp $"
#ident "$Id: elab_net.cc,v 1.133 2004/06/30 02:16:26 steve Exp $"
#endif
# include "config.h"
@ -94,6 +94,7 @@ NetNet* PEBinary::elaborate_net(Design*des, NetScope*scope,
return elaborate_net_log_(des, scope, width, rise, fall, decay);
case 'l': // <<
case 'r': // >>
case 'R': // >>>
return elaborate_net_shift_(des, scope, width, rise, fall, decay);
}
@ -138,6 +139,7 @@ NetNet* PEBinary::elaborate_net(Design*des, NetScope*scope,
case 'l':
case 'r':
case 'R':
assert(0);
break;
default:
@ -771,6 +773,7 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
rsig->pin_count());
des->add_node(div);
div->set_signed(lsig->get_signed() && rsig->get_signed());
// Connect the left and right inputs of the divider to the
// nets that are the left and right expressions.
@ -789,6 +792,7 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, lwidth);
osig->local_flag(true);
osig->set_signed(div->get_signed());
for (unsigned idx = 0 ; idx < rwidth ; idx += 1)
connect(div->pin_Result(idx), osig->pin(idx));
@ -1048,6 +1052,9 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
if (lsig->pin_count() > lwidth)
lwidth = lsig->pin_count();
bool right_flag = op_ == 'r' || op_ == 'R';
bool signed_flag = op_ == 'R';
/* Handle the special case of a constant shift amount. There
is no reason in this case to create a gate at all, just
connect the lsig to the osig with the bit positions
@ -1070,6 +1077,8 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
des->add_node(zero);
if (op_ == 'l') {
/* Left shift means put some zeros on the bottom
of the vector. */
unsigned idx;
for (idx = 0 ; idx < dist ; idx += 1)
connect(osig->pin(idx), zero->pin(0));
@ -1079,7 +1088,17 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
for ( ; idx < lwidth ; idx += 1)
connect(osig->pin(idx), zero->pin(0));
} else if (op_ == 'R') {
/* Signed right shift. */
unsigned idx;
unsigned keep = lsig->pin_count()-dist;
for (idx = 0 ; idx < keep ; idx += 1)
connect(osig->pin(idx), lsig->pin(idx+dist));
for (idx = keep ; idx < lwidth ; idx += 1)
connect(osig->pin(idx), lsig->pin(keep+dist-1));
} else {
/* Unsigned right shift. */
assert(op_ == 'r');
unsigned idx;
unsigned keep = lsig->pin_count()-dist;
@ -1104,7 +1123,8 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
// Make the shift device itself, and the output
// NetNet. Connect the Result output pins to the osig signal
NetCLShift*gate = new NetCLShift(scope, scope->local_symbol(),
lwidth, rsig->pin_count());
lwidth, rsig->pin_count(),
right_flag, signed_flag);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, lwidth);
@ -1135,17 +1155,6 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
connect(rsig->pin(idx), gate->pin_Distance(idx));
if (op_ == 'r') {
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
tmp->local_flag(true);
NetConst*dir = new NetConst(scope, scope->local_symbol(),
verinum::V1);
connect(dir->pin(0), gate->pin_Direction());
connect(tmp->pin(0), gate->pin_Direction());
des->add_node(dir);
}
des->add_node(gate);
return osig;
@ -1980,6 +1989,7 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
NetNet*net = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, lwidth);
net->local_flag(true);
net->set_signed(value_->has_sign());
/* when expanding a constant to fit into the net, extend
the Vx or Vz values if they are in the sign position,
@ -2020,6 +2030,7 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
NetNet*net = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, value_->len());
net->local_flag(true);
net->set_signed(value_->has_sign());
NetConst*tmp = new NetConst(scope, scope->local_symbol(),
*value_);
for (unsigned idx = 0 ; idx < value_->len() ; idx += 1)
@ -2462,6 +2473,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/*
* $Log: elab_net.cc,v $
* Revision 1.133 2004/06/30 02:16:26 steve
* Implement signed divide and signed right shift in nets.
*
* Revision 1.132 2004/06/24 15:22:23 steve
* Code cleanup from Larry.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: expr_synth.cc,v 1.58 2004/06/16 16:21:34 steve Exp $"
#ident "$Id: expr_synth.cc,v 1.59 2004/06/30 02:16:26 steve Exp $"
#endif
# include "config.h"
@ -508,6 +508,9 @@ NetNet* NetEBShift::synthesize(Design*des)
if (lsig == 0)
return 0;
bool right_flag = op_ == 'r' || op_ == 'R';
bool signed_flag = op_ == 'R';
NetScope*scope = lsig->scope();
/* Detect the special case where the shift amount is
@ -566,7 +569,8 @@ NetNet* NetEBShift::synthesize(Design*des)
assert(op() == 'l');
NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(),
osig->pin_count(),
rsig->pin_count());
rsig->pin_count(),
right_flag, signed_flag);
des->add_node(dev);
for (unsigned idx = 0 ; idx < dev->width() ; idx += 1)
@ -579,14 +583,6 @@ NetNet* NetEBShift::synthesize(Design*des)
for (unsigned idx = 0 ; idx < dev->width_dist() ; idx += 1)
connect(dev->pin_Distance(idx), rsig->pin(idx));
verinum dir_v = (op() == 'r')? verinum::V1 : verinum::V0;
NetNet*dir_n = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, 1);
NetConst*dir = new NetConst(scope, scope->local_symbol(), dir_v);
des->add_node(dir);
connect(dev->pin_Direction(), dir->pin(0));
connect(dev->pin_Direction(), dir_n->pin(0));
return osig;
}
@ -879,6 +875,9 @@ NetNet* NetESignal::synthesize(Design*des)
/*
* $Log: expr_synth.cc,v $
* Revision 1.59 2004/06/30 02:16:26 steve
* Implement signed divide and signed right shift in nets.
*
* Revision 1.58 2004/06/16 16:21:34 steve
* Connect rsif of multiply to DataB.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.cc,v 1.224 2004/06/13 04:56:54 steve Exp $"
#ident "$Id: netlist.cc,v 1.225 2004/06/30 02:16:26 steve Exp $"
#endif
# include "config.h"
@ -794,9 +794,11 @@ const Link& NetAddSub::pin_Result(unsigned idx) const
* 3+2W -- Distance(0)
*/
NetCLShift::NetCLShift(NetScope*s, perm_string n,
unsigned width, unsigned width_dist)
unsigned width, unsigned width_dist,
bool right_flag, bool signed_flag)
: NetNode(s, n, 3+2*width+width_dist),
width_(width), width_dist_(width_dist)
width_(width), width_dist_(width_dist),
right_flag_(right_flag), signed_flag_(signed_flag)
{
pin(0).set_dir(Link::INPUT); pin(0).set_name(
perm_string::literal("Direction"), 0);
@ -833,6 +835,17 @@ unsigned NetCLShift::width_dist() const
return width_dist_;
}
bool NetCLShift::right_flag() const
{
return right_flag_;
}
bool NetCLShift::signed_flag() const
{
return signed_flag_;
}
#if 0
Link& NetCLShift::pin_Direction()
{
return pin(0);
@ -842,6 +855,7 @@ const Link& NetCLShift::pin_Direction() const
{
return pin(0);
}
#endif
Link& NetCLShift::pin_Underflow()
{
@ -1049,7 +1063,7 @@ const Link& NetCompare::pin_DataB(unsigned idx) const
NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr,
unsigned wa, unsigned wb)
: NetNode(sc, n, wr+wa+wb),
width_r_(wr), width_a_(wa), width_b_(wb)
width_r_(wr), width_a_(wa), width_b_(wb), signed_flag_(false)
{
unsigned p = 0;
for (unsigned idx = 0 ; idx < width_r_ ; idx += 1, p += 1) {
@ -1085,6 +1099,16 @@ unsigned NetDivide::width_b() const
return width_b_;
}
void NetDivide::set_signed(bool flag)
{
signed_flag_ = flag;
}
bool NetDivide::get_signed() const
{
return signed_flag_;
}
Link& NetDivide::pin_Result(unsigned idx)
{
assert(idx < width_r_);
@ -2257,6 +2281,9 @@ const NetProc*NetTaskDef::proc() const
/*
* $Log: netlist.cc,v $
* Revision 1.225 2004/06/30 02:16:26 steve
* Implement signed divide and signed right shift in nets.
*
* Revision 1.224 2004/06/13 04:56:54 steve
* Add support for the default_nettype directive.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.313 2004/06/13 04:56:55 steve Exp $"
#ident "$Id: netlist.h,v 1.314 2004/06/30 02:16:26 steve Exp $"
#endif
/*
@ -493,12 +493,15 @@ class NetCLShift : public NetNode {
public:
NetCLShift(NetScope*s, perm_string n, unsigned width,
unsigned width_dist);
unsigned width_dist, bool right_flag, bool signed_flag);
~NetCLShift();
unsigned width() const;
unsigned width_dist() const;
bool right_flag() const;
bool signed_flag() const;
Link& pin_Direction();
Link& pin_Underflow();
Link& pin_Overflow();
@ -519,6 +522,8 @@ class NetCLShift : public NetNode {
private:
unsigned width_;
unsigned width_dist_;
bool right_flag_;
bool signed_flag_;
};
/*
@ -597,6 +602,9 @@ class NetDivide : public NetNode {
unsigned width_a() const;
unsigned width_b() const;
void set_signed(bool);
bool get_signed() const;
Link& pin_DataA(unsigned idx);
Link& pin_DataB(unsigned idx);
Link& pin_Result(unsigned idx);
@ -613,6 +621,8 @@ class NetDivide : public NetNode {
unsigned width_r_;
unsigned width_a_;
unsigned width_b_;
bool signed_flag_;
};
/*
@ -3331,6 +3341,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.314 2004/06/30 02:16:26 steve
* Implement signed divide and signed right shift in nets.
*
* Revision 1.313 2004/06/13 04:56:55 steve
* Add support for the default_nettype directive.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-api.cc,v 1.106 2003/12/03 02:46:24 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.107 2004/06/30 02:16:27 steve Exp $"
#endif
# include "config.h"
@ -983,6 +983,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
return net->u_.arith.signed_flag;
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
return net->u_.shift.signed_flag;
return 0;
case IVL_LPM_UFUNC:
return 0;
@ -1934,6 +1935,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
/*
* $Log: t-dll-api.cc,v $
* Revision 1.107 2004/06/30 02:16:27 steve
* Implement signed divide and signed right shift in nets.
*
* Revision 1.106 2003/12/03 02:46:24 steve
* Add support for wait on list of named events.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.129 2004/02/20 18:53:35 steve Exp $"
#ident "$Id: t-dll.cc,v 1.130 2004/06/30 02:16:27 steve Exp $"
#endif
# include "config.h"
@ -1182,20 +1182,12 @@ void dll_target::lpm_clshift(const NetCLShift*net)
/* Look at the direction input of the device, and select the
shift direction accordingly. */
if (net->pin_Direction().is_linked()) {
assert( net->pin_Direction().nexus()->drivers_constant() );
verinum::V dir = net->pin_Direction().nexus()->driven_value();
switch (dir) {
case verinum::V0:
break;
case verinum::V1:
obj->type = IVL_LPM_SHIFTR;
break;
default:
assert(0);
}
}
if (net->right_flag())
obj->type = IVL_LPM_SHIFTR;
if (net->signed_flag())
obj->u_.shift.signed_flag = 1;
else
obj->u_.shift.signed_flag = 0;
obj->u_.shift.width = net->width();
obj->u_.shift.select = net->width_dist();
@ -1372,6 +1364,7 @@ void dll_target::lpm_divide(const NetDivide*net)
unsigned wid = net->width_r();
obj->u_.arith.width = wid;
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
obj->u_.arith.q = new ivl_nexus_t[3 * obj->u_.arith.width];
obj->u_.arith.a = obj->u_.arith.q + obj->u_.arith.width;
@ -1396,7 +1389,18 @@ void dll_target::lpm_divide(const NetDivide*net)
nexus_lpm_add(obj->u_.arith.a[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
} else if (obj->u_.arith.signed_flag) {
/* If this is signed divide, sign extend the perand. */
nex = net->pin_DataA(net->width_a()-1).nexus();
assert(nex);
assert(nex->t_cookie());
obj->u_.arith.a[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.a[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
} else {
/* Unsigned divide: pad the operand. */
obj->u_.arith.a[idx] = 0;
}
@ -2176,6 +2180,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.130 2004/06/30 02:16:27 steve
* Implement signed divide and signed right shift in nets.
*
* Revision 1.129 2004/02/20 18:53:35 steve
* Addtrbute keys are perm_strings.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.h,v 1.113 2004/05/31 23:34:39 steve Exp $"
#ident "$Id: t-dll.h,v 1.114 2004/06/30 02:16:27 steve Exp $"
#endif
# include "target.h"
@ -335,6 +335,7 @@ struct ivl_lpm_s {
struct ivl_lpm_shift_s {
unsigned width;
unsigned select;
unsigned signed_flag :1;
ivl_nexus_t*q;
ivl_nexus_t*d;
ivl_nexus_t*s;
@ -683,6 +684,9 @@ struct ivl_variable_s {
/*
* $Log: t-dll.h,v $
* Revision 1.114 2004/06/30 02:16:27 steve
* Implement signed divide and signed right shift in nets.
*
* Revision 1.113 2004/05/31 23:34:39 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.86 2004/06/17 16:06:19 steve Exp $"
#ident "$Id: stub.c,v 1.87 2004/06/30 02:16:27 steve Exp $"
#endif
# include "config.h"
@ -206,6 +206,26 @@ static void show_lpm(ivl_lpm_t net)
break;
}
case IVL_LPM_DIVIDE: {
fprintf(out, " LPM_DIVIDE %s: <width=%u %s>\n",
ivl_lpm_basename(net), width,
ivl_lpm_signed(net)? "signed" : "unsigned");
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Q %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_q(net, idx)));
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_data(net, idx);
fprintf(out, " Data A %u: %s\n", idx,
nex? ivl_nexus_name(nex) : "");
}
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_datab(net, idx);
fprintf(out, " Data B %u: %s\n", idx,
nex? ivl_nexus_name(nex) : "");
}
break;
}
case IVL_LPM_CMP_NE: {
fprintf(out, " LPM_COMPARE(NE) %s: <width=%u>\n",
ivl_lpm_basename(net), width);
@ -224,8 +244,25 @@ static void show_lpm(ivl_lpm_t net)
}
case IVL_LPM_SHIFTL: {
fprintf(out, " LPM_SHIFTL %s: <width=%u, selects=%u>\n",
ivl_lpm_basename(net), width, ivl_lpm_selects(net));
fprintf(out, " LPM_SHIFTL %s: <width=%u, selects=%u %s>\n",
ivl_lpm_basename(net), width, ivl_lpm_selects(net),
ivl_lpm_signed(net)? "signed" : "unsigned");
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Q %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_q(net, idx)));
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Data A %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_data(net, idx)));
for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1)
fprintf(out, " Shift %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_select(net, idx)));
break;
}
case IVL_LPM_SHIFTR: {
fprintf(out, " LPM_SHIFTR %s: <width=%u, selects=%u %s>\n",
ivl_lpm_basename(net), width, ivl_lpm_selects(net),
ivl_lpm_signed(net)? "signed" : "unsigned");
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Q %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_q(net, idx)));
@ -909,6 +946,9 @@ int target_design(ivl_design_t des)
/*
* $Log: stub.c,v $
* Revision 1.87 2004/06/30 02:16:27 steve
* Implement signed divide and signed right shift in nets.
*
* Revision 1.86 2004/06/17 16:06:19 steve
* Help system function signedness survive elaboration.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_scope.c,v 1.99 2004/06/16 23:33:42 steve Exp $"
#ident "$Id: vvp_scope.c,v 1.100 2004/06/30 02:16:27 steve Exp $"
#endif
# include "vvp_priv.h"
@ -1141,7 +1141,10 @@ static void draw_lpm_add(ivl_lpm_t net)
type = "mult";
break;
case IVL_LPM_DIVIDE:
type = "div";
if (ivl_lpm_signed(net))
type = "div.s";
else
type = "div";
break;
case IVL_LPM_MOD:
type = "mod";
@ -1586,6 +1589,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/*
* $Log: vvp_scope.c,v $
* Revision 1.100 2004/06/30 02:16:27 steve
* Implement signed divide and signed right shift in nets.
*
* Revision 1.99 2004/06/16 23:33:42 steve
* Generate .cmp/eq nodes instead of sea of gates.
*