diff --git a/elab_net.cc b/elab_net.cc index 3ba0c72d4..5fcc828e2 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.111 2003/03/29 05:51:25 steve Exp $" +#ident "$Id: elab_net.cc,v 1.112 2003/04/11 05:18:08 steve Exp $" #endif # include "config.h" @@ -421,14 +421,31 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope, unsigned dwidth = lsig->pin_count(); if (rsig->pin_count() > dwidth) dwidth = rsig->pin_count(); - NetNet*zero = 0; + /* Operands of binary compare need to be padded to equal + size. Figure the pad bit needed to extend the narrowest + vector. */ + NetNet*padbit = 0; if (lsig->pin_count() != rsig->pin_count()) { - NetConst*tmp = new NetConst(scope, scope->local_symbol(), - verinum::V0); - des->add_node(tmp); - zero = new NetNet(scope, scope->local_symbol(), NetNet::WIRE); - zero->local_flag(true); - connect(tmp->pin(0), zero->pin(0)); + unsigned lwid = lsig->pin_count(); + unsigned rwid = rsig->pin_count(); + + padbit = new NetNet(scope, scope->local_symbol(), NetNet::WIRE); + padbit->local_flag(true); + + if (lsig->get_signed() && (lwid < rwid)) { + + connect(padbit->pin(0), lsig->pin(lwid-1)); + + } else if (rsig->get_signed() && (rwid < lwid)) { + + connect(padbit->pin(0), rsig->pin(rwid-1)); + + } else { + NetConst*tmp = new NetConst(scope, scope->local_symbol(), + verinum::V0); + des->add_node(tmp); + connect(tmp->pin(0), padbit->pin(0)); + } } NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE); @@ -447,11 +464,11 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope, for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) connect(cmp->pin_DataA(idx), lsig->pin(idx)); for (unsigned idx = lsig->pin_count(); idx < dwidth ; idx += 1) - connect(cmp->pin_DataA(idx), zero->pin(0)); + connect(cmp->pin_DataA(idx), padbit->pin(0)); for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1) connect(cmp->pin_DataB(idx), rsig->pin(idx)); for (unsigned idx = rsig->pin_count(); idx < dwidth ; idx += 1) - connect(cmp->pin_DataB(idx), zero->pin(0)); + connect(cmp->pin_DataB(idx), padbit->pin(0)); switch (op_) { case '<': @@ -467,6 +484,11 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope, connect(cmp->pin_AGEB(), osig->pin(0)); break; } + /* If both operands are signed, then do a signed + compare. */ + if (lsig->get_signed() && rsig->get_signed()) + cmp->set_signed(true); + gate = cmp; break; } @@ -487,12 +509,12 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope, if (idx < lsig->pin_count()) connect(cmp->pin(1), lsig->pin(idx)); else - connect(cmp->pin(1), zero->pin(0)); + connect(cmp->pin(1), padbit->pin(0)); if (idx < rsig->pin_count()) connect(cmp->pin(2), rsig->pin(idx)); else - connect(cmp->pin(2), zero->pin(0)); + connect(cmp->pin(2), padbit->pin(0)); connect(cmp->pin(0), gate->pin(idx+1)); des->add_node(cmp); @@ -527,12 +549,12 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope, if (idx < lsig->pin_count()) connect(cmp->pin_DataA(idx), lsig->pin(idx)); else - connect(cmp->pin_DataA(idx), zero->pin(0)); + connect(cmp->pin_DataA(idx), padbit->pin(0)); if (idx < rsig->pin_count()) connect(cmp->pin_DataB(idx), rsig->pin(idx)); else - connect(cmp->pin_DataB(idx), zero->pin(0)); + connect(cmp->pin_DataB(idx), padbit->pin(0)); } connect(cmp->pin_AEB(), osig->pin(0)); @@ -561,12 +583,12 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope, if (idx < lsig->pin_count()) connect(cmp->pin_DataA(idx), lsig->pin(idx)); else - connect(cmp->pin_DataA(idx), zero->pin(0)); + connect(cmp->pin_DataA(idx), padbit->pin(0)); if (idx < rsig->pin_count()) connect(cmp->pin_DataB(idx), rsig->pin(idx)); else - connect(cmp->pin_DataB(idx), zero->pin(0)); + connect(cmp->pin_DataB(idx), padbit->pin(0)); } connect(cmp->pin_ANEB(), osig->pin(0)); @@ -1014,16 +1036,36 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope, * This method elaborates a call to a function in the context of a * continuous assignment. */ -NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope, unsigned, - unsigned long, - unsigned long, - unsigned long, - Link::strength_t, - Link::strength_t) const +NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope, + unsigned width, + unsigned long rise, + unsigned long fall, + unsigned long decay, + Link::strength_t drive0, + Link::strength_t drive1) const { unsigned errors = 0; unsigned func_pins = 0; + /* Handle the special case that the function call is to + $signed. This takes a single expression argument, and + forces it to be a signed result. Otherwise, it is as if the + $signed did not exist. */ + if (strcmp(path_.peek_name(0), "$signed") == 0) { + if ((parms_.count() != 1) || (parms_[0] == 0)) { + cerr << get_line() << ": error: The $signed() function " + << "takes exactly one(1) argument." << endl; + des->errors += 1; + return 0; + } + + PExpr*expr = parms_[0]; + NetNet*sub = expr->elaborate_net(des, scope, width, rise, + fall, decay, drive0, drive1); + sub->set_signed(true); + return sub; + } + /* Look up the function definition. */ NetFuncDef*def = des->find_function(scope, path_); if (def == 0) { @@ -1276,6 +1318,7 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope, const NetEConst*pc = dynamic_cast(pe); assert(pc); verinum pvalue = pc->value(); + sig = new NetNet(scope, path_.peek_name(0), NetNet::IMPLICIT, pc->expr_width()); NetConst*cp = new NetConst(scope, scope->local_symbol(), @@ -2281,6 +2324,10 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope, /* * $Log: elab_net.cc,v $ + * Revision 1.112 2003/04/11 05:18:08 steve + * Handle signed magnitude compare all the + * way through to the vvp code generator. + * * Revision 1.111 2003/03/29 05:51:25 steve * Sign extend NetMult inputs if result is signed. * diff --git a/ivl.def b/ivl.def index bbf0ed611..b7349a6e8 100644 --- a/ivl.def +++ b/ivl.def @@ -75,6 +75,7 @@ ivl_lpm_q ivl_lpm_scope ivl_lpm_select ivl_lpm_selects +ivl_lpm_signed ivl_lpm_size ivl_lpm_type ivl_lpm_width diff --git a/ivl_target.h b/ivl_target.h index 5f4c86d7f..1a735b47a 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: ivl_target.h,v 1.115 2003/03/10 23:40:53 steve Exp $" +#ident "$Id: ivl_target.h,v 1.116 2003/04/11 05:18:08 steve Exp $" #endif #ifdef __cplusplus @@ -643,6 +643,10 @@ extern const char* ivl_udp_name(ivl_udp_t net); * This is the size of the select input for a LPM_MUX device, or the * address bus width of an LPM_RAM. * + * ivl_lpm_signed + * Arithmetic LPM devices may be signed or unsigned if there is a + * distinction. + * * ivl_lpm_size * In addition to a width, some devices have a size. The size is * often the number of inputs per out, i.e., the number of inputs @@ -652,6 +656,7 @@ extern const char* ivl_udp_name(ivl_udp_t net); extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */ extern const char* ivl_lpm_basename(ivl_lpm_t net); extern ivl_scope_t ivl_lpm_scope(ivl_lpm_t net); +extern int ivl_lpm_signed(ivl_lpm_t net); extern ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net); extern unsigned ivl_lpm_width(ivl_lpm_t net); @@ -1204,6 +1209,10 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.116 2003/04/11 05:18:08 steve + * Handle signed magnitude compare all the + * way through to the vvp code generator. + * * Revision 1.115 2003/03/10 23:40:53 steve * Keep parameter constants for the ivl_target API. * diff --git a/netlist.cc b/netlist.cc index 538a94909..2a472b231 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.210 2003/03/29 05:51:25 steve Exp $" +#ident "$Id: netlist.cc,v 1.211 2003/04/11 05:18:08 steve Exp $" #endif # include "config.h" @@ -849,6 +849,7 @@ const Link& NetCLShift::pin_Distance(unsigned idx) const NetCompare::NetCompare(NetScope*s, const string&n, unsigned wi) : NetNode(s, lex_strings.add(n.c_str()), 8+2*wi), width_(wi) { + signed_flag_ = false; pin(0).set_dir(Link::INPUT); pin(0).set_name("Aclr"); pin(1).set_dir(Link::INPUT); pin(1).set_name("Clock"); pin(2).set_dir(Link::OUTPUT); pin(2).set_name("AGB"); @@ -874,6 +875,16 @@ unsigned NetCompare::width() const return width_; } +bool NetCompare::get_signed() const +{ + return signed_flag_; +} + +void NetCompare::set_signed(bool flag) +{ + signed_flag_ = flag; +} + Link& NetCompare::pin_Aclr() { return pin(0); @@ -2151,6 +2162,10 @@ const NetProc*NetTaskDef::proc() const /* * $Log: netlist.cc,v $ + * Revision 1.211 2003/04/11 05:18:08 steve + * Handle signed magnitude compare all the + * way through to the vvp code generator. + * * Revision 1.210 2003/03/29 05:51:25 steve * Sign extend NetMult inputs if result is signed. * diff --git a/netlist.h b/netlist.h index e5c03229d..564fd1ddb 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.284 2003/04/08 04:33:55 steve Exp $" +#ident "$Id: netlist.h,v 1.285 2003/04/11 05:18:08 steve Exp $" #endif /* @@ -533,6 +533,9 @@ class NetCompare : public NetNode { unsigned width() const; + bool get_signed() const; + void set_signed(bool); + Link& pin_Aclr(); Link& pin_Clock(); Link& pin_AGB(); @@ -563,6 +566,7 @@ class NetCompare : public NetNode { private: unsigned width_; + bool signed_flag_; }; /* @@ -3246,6 +3250,10 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.285 2003/04/11 05:18:08 steve + * Handle signed magnitude compare all the + * way through to the vvp code generator. + * * Revision 1.284 2003/04/08 04:33:55 steve * Synthesize shift expressions. * diff --git a/t-dll-api.cc b/t-dll-api.cc index c0e4f3cc6..a78dd72bc 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.96 2003/03/10 23:40:53 steve Exp $" +#ident "$Id: t-dll-api.cc,v 1.97 2003/04/11 05:18:08 steve Exp $" #endif # include "config.h" @@ -902,6 +902,35 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net) } } +extern "C" int ivl_lpm_signed(ivl_lpm_t net) +{ + assert(net); + switch (net->type) { + case IVL_LPM_FF: + case IVL_LPM_RAM: + case IVL_LPM_MUX: + return 0; + case IVL_LPM_ADD: + case IVL_LPM_CMP_EQ: + case IVL_LPM_CMP_GE: + case IVL_LPM_CMP_GT: + case IVL_LPM_CMP_NE: + case IVL_LPM_DIVIDE: + case IVL_LPM_MOD: + case IVL_LPM_MULT: + case IVL_LPM_SUB: + return net->u_.arith.signed_flag; + case IVL_LPM_SHIFTL: + case IVL_LPM_SHIFTR: + return 0; + case IVL_LPM_UFUNC: + return 0; + default: + assert(0); + return 0; + } +} + extern "C" unsigned ivl_lpm_size(ivl_lpm_t net) { switch (net->type) { @@ -1797,6 +1826,10 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net) /* * $Log: t-dll-api.cc,v $ + * Revision 1.97 2003/04/11 05:18:08 steve + * Handle signed magnitude compare all the + * way through to the vvp code generator. + * * Revision 1.96 2003/03/10 23:40:53 steve * Keep parameter constants for the ivl_target API. * diff --git a/t-dll.cc b/t-dll.cc index 2be71908d..fbef1eefe 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.109 2003/03/29 05:51:25 steve Exp $" +#ident "$Id: t-dll.cc,v 1.110 2003/04/11 05:18:08 steve Exp $" #endif # include "config.h" @@ -1071,6 +1071,8 @@ void dll_target::lpm_add_sub(const NetAddSub*net) obj->scope = find_scope(des_, net->scope()); assert(obj->scope); + obj->u_.arith.signed_flag = 0; + /* Choose the width of the adder. If the carry bit is connected, then widen the adder by one and plan on leaving the fake inputs unconnected. */ @@ -1219,6 +1221,7 @@ void dll_target::lpm_compare(const NetCompare*net) bool swap_operands = false; obj->u_.arith.width = net->width(); + obj->u_.arith.signed_flag = net->get_signed()? 1 : 0; obj->u_.arith.q = new ivl_nexus_t[1 + 2 * obj->u_.arith.width]; obj->u_.arith.a = obj->u_.arith.q + 1; @@ -2117,6 +2120,10 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj }; /* * $Log: t-dll.cc,v $ + * Revision 1.110 2003/04/11 05:18:08 steve + * Handle signed magnitude compare all the + * way through to the vvp code generator. + * * Revision 1.109 2003/03/29 05:51:25 steve * Sign extend NetMult inputs if result is signed. * diff --git a/t-dll.h b/t-dll.h index 83e4cfa30..b3140bc16 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.100 2003/03/10 23:40:54 steve Exp $" +#ident "$Id: t-dll.h,v 1.101 2003/04/11 05:18:08 steve Exp $" #endif # include "target.h" @@ -334,7 +334,8 @@ struct ivl_lpm_s { } shift; struct ivl_lpm_arith_s { - unsigned short width; + unsigned width :16; + unsigned signed_flag :1; ivl_nexus_t*q, *a, *b; } arith; @@ -672,6 +673,10 @@ struct ivl_variable_s { /* * $Log: t-dll.h,v $ + * Revision 1.101 2003/04/11 05:18:08 steve + * Handle signed magnitude compare all the + * way through to the vvp code generator. + * * Revision 1.100 2003/03/10 23:40:54 steve * Keep parameter constants for the ivl_target API. * diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 7a44214af..173355207 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.76 2003/03/29 05:51:26 steve Exp $" +#ident "$Id: stub.c,v 1.77 2003/04/11 05:18:08 steve Exp $" #endif # include "config.h" @@ -304,8 +304,11 @@ static void show_lpm(ivl_lpm_t net) } default: - fprintf(out, " %s: \n", ivl_lpm_basename(net), - ivl_lpm_width(net)); + fprintf(out, " LPM(%d) %s: \n", + ivl_lpm_type(net), + ivl_lpm_basename(net), + ivl_lpm_width(net), + ivl_lpm_signed(net)); } } @@ -837,6 +840,10 @@ int target_design(ivl_design_t des) /* * $Log: stub.c,v $ + * Revision 1.77 2003/04/11 05:18:08 steve + * Handle signed magnitude compare all the + * way through to the vvp code generator. + * * Revision 1.76 2003/03/29 05:51:26 steve * Sign extend NetMult inputs if result is signed. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 51ad2074a..d80d61e9e 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.91 2003/03/25 02:15:48 steve Exp $" +#ident "$Id: vvp_scope.c,v 1.92 2003/04/11 05:18:08 steve Exp $" #endif # include "vvp_priv.h" @@ -1133,6 +1133,7 @@ static void draw_lpm_cmp(ivl_lpm_t net) { unsigned width; const char*type = ""; + const char*signed_string = ivl_lpm_signed(net)? ".s" : ""; width = ivl_lpm_width(net); @@ -1147,9 +1148,10 @@ static void draw_lpm_cmp(ivl_lpm_t net) assert(0); } - fprintf(vvp_out, "L_%s.%s .cmp/%s %u", + fprintf(vvp_out, "L_%s.%s .cmp/%s%s %u", vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), - vvp_mangle_id(ivl_lpm_basename(net)), type, width); + vvp_mangle_id(ivl_lpm_basename(net)), type, + signed_string, width); draw_lpm_arith_a_b_inputs(net); @@ -1627,6 +1629,10 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) /* * $Log: vvp_scope.c,v $ + * Revision 1.92 2003/04/11 05:18:08 steve + * Handle signed magnitude compare all the + * way through to the vvp code generator. + * * Revision 1.91 2003/03/25 02:15:48 steve * Use hash code for scope labels. *