diff --git a/elab_net.cc b/elab_net.cc index a9bd205d7..bfeba7585 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -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. * diff --git a/expr_synth.cc b/expr_synth.cc index 9b0a1c38a..1e9938580 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -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. * diff --git a/netlist.cc b/netlist.cc index 3bedaae6f..9069219fe 100644 --- a/netlist.cc +++ b/netlist.cc @@ -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. * diff --git a/netlist.h b/netlist.h index 608202a4d..fa5f82c6f 100644 --- a/netlist.h +++ b/netlist.h @@ -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. * diff --git a/t-dll-api.cc b/t-dll-api.cc index 219ab0141..7e1d3e4ce 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -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. * diff --git a/t-dll.cc b/t-dll.cc index b6bc9d6be..f71e10cdf 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -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. * diff --git a/t-dll.h b/t-dll.h index d4c37121f..f5c19dc85 100644 --- a/t-dll.h +++ b/t-dll.h @@ -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 diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index a2384d0c3..902c8abc2 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -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: \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: \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: \n", - ivl_lpm_basename(net), width, ivl_lpm_selects(net)); + fprintf(out, " LPM_SHIFTL %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: \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. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index bc986b057..80fe4e08e 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -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. *