diff --git a/elab_net.cc b/elab_net.cc index c9b0a4358..2ca7758fb 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.151 2005/02/12 06:25:40 steve Exp $" +#ident "$Id: elab_net.cc,v 1.152 2005/02/19 02:43:38 steve Exp $" #endif # include "config.h" @@ -723,23 +723,23 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope, unsigned rwidth = lwidth; if (rwidth == 0) { - rwidth = lsig->pin_count(); - if (rsig->pin_count() > rwidth) - rwidth = rsig->pin_count(); + rwidth = lsig->vector_width(); + if (rsig->vector_width() > rwidth) + rwidth = rsig->vector_width(); lwidth = rwidth; } - if ((rwidth > lsig->pin_count()) && (rwidth > rsig->pin_count())) { - rwidth = lsig->pin_count(); - if (rsig->pin_count() > rwidth) - rwidth = rsig->pin_count(); + if ((rwidth > lsig->vector_width()) && (rwidth > rsig->vector_width())) { + rwidth = lsig->vector_width(); + if (rsig->vector_width() > rwidth) + rwidth = rsig->vector_width(); } // Create a device with the calculated dimensions. NetDivide*div = new NetDivide(scope, scope->local_symbol(), rwidth, - lsig->pin_count(), - rsig->pin_count()); + lsig->vector_width(), + rsig->vector_width()); des->add_node(div); div->set_signed(lsig->get_signed() && rsig->get_signed()); @@ -747,10 +747,8 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope, // Connect the left and right inputs of the divider to the // nets that are the left and right expressions. - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) - connect(div->pin_DataA(idx), lsig->pin(idx)); - for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1) - connect(div->pin_DataB(idx), rsig->pin(idx)); + connect(div->pin_DataA(), lsig->pin(0)); + connect(div->pin_DataB(), rsig->pin(0)); // Make an output signal that is the width of the l-value. @@ -763,24 +761,9 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope, 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)); + connect(div->pin_Result(), osig->pin(0)); - // If the lvalue is larger then the result, then pad the - // output with constant 0. This can happen for example in - // cases like this: - // wire [3;0] a, b; - // wire [7:0] r = a / b; - - if (rwidth < osig->pin_count()) { - NetConst*tmp = new NetConst(scope, scope->local_symbol(), - verinum::V0); - des->add_node(tmp); - for (unsigned idx = rwidth ; idx < osig->pin_count() ; idx += 1) - connect(osig->pin(idx), tmp->pin(0)); - } - return osig; } @@ -1004,8 +987,8 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope, NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0); if (lsig == 0) return 0; - if (lsig->pin_count() > lwidth) - lwidth = lsig->pin_count(); + if (lsig->vector_width() > lwidth) + lwidth = lsig->vector_width(); bool right_flag = op_ == 'r' || op_ == 'R'; bool signed_flag = op_ == 'R'; @@ -1013,56 +996,123 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope, /* 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 - shifted. */ + shifted. Use a NetPartSelect to select the parts of the + left expression that survive the shift, and a NetConcat to + concatenate a constant for padding. */ if (verinum*rval = right_->eval_const(des, scope)) { assert(rval->is_defined()); unsigned dist = rval->as_ulong(); - if (dist > lwidth) - dist = lwidth; - /* Very special case, constant 0 shift. */ + /* Very special case: constant 0 shift. Simply return + the left signal again. */ if (dist == 0) return lsig; + /* Another very special case: constant shift the entire + value away. The result is a const. */ + if (dist > lwidth) { + assert(0); + } + + /* The construction that I'm making will ultimately + connect its output to the osig here. This will be the + result that I return from this function. */ NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, lwidth); osig->local_flag(true); - NetConst*zero = new NetConst(scope, scope->local_symbol(), - verinum::V0); - 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)); - for ( ; (idxpin_count()) - ; idx += 1) - connect(osig->pin(idx), lsig->pin(idx-dist)); - for ( ; idx < lwidth ; idx += 1) - connect(osig->pin(idx), zero->pin(0)); + /* Make the constant zero's that I'm going to pad to the + top or bottom of the left expression. Attach a signal + to its output so that I don't have to worry about it + later. If the left expression is less then the + desired width (and we are doing right shifts) then we + can combine the expression padding with the distance + padding to reduce nodes. */ + unsigned pad_width = dist; + unsigned part_width = lwidth - dist; + if (op_ == 'r' || op_ == 'R') { + if (lsig->vector_width() < lwidth) { + pad_width += lwidth - lsig->vector_width(); + part_width -= lwidth - lsig->vector_width(); + } + } else { - } 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)); + /* The left net must be the same width as the + result. The part select that I'm about to make relies + on that. */ + lsig = pad_to_width(des, lsig, lwidth); + + } + + NetNet*zero = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, pad_width); + zero->local_flag(true); + zero->set_line(*this); + + if (op_ == 'R') { + NetPartSelect*sign_bit + = new NetPartSelect(lsig, lsig->vector_width()-1, + 1, NetPartSelect::VP); + des->add_node(sign_bit); + NetReplicate*sign_pad + = new NetReplicate(scope, scope->local_symbol(), + pad_width, pad_width); + des->add_node(sign_pad); + NetNet*tmp = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, 1); + connect(sign_bit->pin(0), tmp->pin(0)); + connect(sign_bit->pin(0), sign_pad->pin(1)); + + connect(zero->pin(0), sign_pad->pin(0)); } else { - /* Unsigned right shift. */ - assert(op_ == 'r'); - 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), zero->pin(0)); + NetConst*zero_c = new NetConst(scope, scope->local_symbol(), + verinum(verinum::V0, pad_width)); + des->add_node(zero_c); + connect(zero->pin(0), zero_c->pin(0)); } + /* Make a concatenation operator that will join the + part-selected right expression at the pad values. */ + NetConcat*cc = new NetConcat(scope, scope->local_symbol(), + lwidth, 2); + cc->set_line(*this); + des->add_node(cc); + connect(cc->pin(0), osig->pin(0)); + + /* Make the part select of the left expression and + connect it to the lsb or msb of the concatenation, + depending on the direction of the shift. */ + NetPartSelect*part; + + switch (op_) { + case 'l': // Left shift === {lsig, zero} + part = new NetPartSelect(lsig, 0, part_width, + NetPartSelect::VP); + connect(cc->pin(1), zero->pin(0)); + connect(cc->pin(2), part->pin(0)); + break; + case 'R': + case 'r': // right-shift === {zero, lsig} + part = new NetPartSelect(lsig, dist, part_width, + NetPartSelect::VP); + connect(cc->pin(1), part->pin(0)); + connect(cc->pin(2), zero->pin(0)); + break; + default: + assert(0); + } + + des->add_node(part); + + /* Attach a signal to the part select output (NetConcat + input) */ + NetNet*tmp = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, part_width); + tmp->local_flag(true); + tmp->set_line(*this); + connect(part->pin(0), tmp->pin(0)); + return osig; } @@ -1078,39 +1128,31 @@ 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->vector_width(), right_flag, signed_flag); + des->add_node(gate); NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, lwidth); osig->local_flag(true); + osig->set_signed(signed_flag); - for (unsigned idx = 0 ; idx < lwidth ; idx += 1) - connect(osig->pin(idx), gate->pin_Result(idx)); + connect(osig->pin(0), gate->pin_Result()); // Connect the lsig (the left expression) to the Data input, // and pad it if necessary with constant zeros. - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) - connect(lsig->pin(idx), gate->pin_Data(idx)); - - if (lsig->pin_count() < lwidth) { - NetConst*zero = new NetConst(scope, scope->local_symbol(), - verinum::V0); - NetNet*tmp = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, 1); - tmp->local_flag(true); - des->add_node(zero); - connect(zero->pin(0), tmp->pin(0)); - for (unsigned idx = lsig->pin_count() ; idx < lwidth ; idx += 1) - connect(zero->pin(0), gate->pin_Data(idx)); - } + assert(lsig->vector_width() == lwidth); + connect(lsig->pin(0), gate->pin_Data()); // Connect the rsig (the shift amount expression) to the // Distance input. - for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1) - connect(rsig->pin(idx), gate->pin_Distance(idx)); + connect(rsig->pin(0), gate->pin_Distance()); - des->add_node(gate); + if (debug_elaborate) { + cerr << get_line() << ": debug: " + << "Elaborate LPM_SHIFT: width="<width() + << ", swidth="<< gate->width_dist() << endl; + } return osig; } @@ -2462,6 +2504,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope, /* * $Log: elab_net.cc,v $ + * Revision 1.152 2005/02/19 02:43:38 steve + * Support shifts and divide. + * * Revision 1.151 2005/02/12 06:25:40 steve * Restructure NetMux devices to pass vectors. * Generate NetMux devices from ternary expressions, diff --git a/elaborate.cc b/elaborate.cc index d13030a97..eca940703 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elaborate.cc,v 1.318 2005/02/10 04:56:58 steve Exp $" +#ident "$Id: elaborate.cc,v 1.319 2005/02/19 02:43:38 steve Exp $" #endif # include "config.h" @@ -94,7 +94,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const assert(lval->pin_count() == 1); if (debug_elaborate) { - cerr << lval->get_line() << ": debug: PGassign: elaborated l-value" + cerr << get_line() << ": debug: PGassign: elaborated l-value" << " width=" << lval->vector_width() << endl; } @@ -2938,6 +2938,9 @@ Design* elaborate(listroots) /* * $Log: elaborate.cc,v $ + * Revision 1.319 2005/02/19 02:43:38 steve + * Support shifts and divide. + * * Revision 1.318 2005/02/10 04:56:58 steve * distinguish between single port namy instances, and single instances many sub-ports. * diff --git a/expr_synth.cc b/expr_synth.cc index d6cfc4012..a62031d75 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.63 2005/02/12 06:25:40 steve Exp $" +#ident "$Id: expr_synth.cc,v 1.64 2005/02/19 02:43:38 steve Exp $" #endif # include "config.h" @@ -371,16 +371,13 @@ NetNet* NetEBDiv::synthesize(Design*des) case '/': { NetDivide*div = new NetDivide(scope, scope->local_symbol(), expr_width(), - lsig->pin_count(), - rsig->pin_count()); + lsig->vector_width(), + rsig->vector_width()); des->add_node(div); - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) - connect(div->pin_DataA(idx), lsig->pin(idx)); - for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1) - connect(div->pin_DataB(idx), rsig->pin(idx)); - for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) - connect(div->pin_Result(idx), osig->pin(idx)); + connect(div->pin_DataA(), lsig->pin(0)); + connect(div->pin_DataB(), rsig->pin(0)); + connect(div->pin_Result(),osig->pin(0)); break; } @@ -562,20 +559,18 @@ NetNet* NetEBShift::synthesize(Design*des) assert(op() == 'l'); NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(), - osig->pin_count(), - rsig->pin_count(), + osig->vector_width(), + rsig->vector_width(), right_flag, signed_flag); + dev->set_line(*this); des->add_node(dev); - for (unsigned idx = 0 ; idx < dev->width() ; idx += 1) - connect(dev->pin_Result(idx), osig->pin(idx)); + connect(dev->pin_Result(), osig->pin(0)); - assert(lsig->pin_count() >= dev->width()); - for (unsigned idx = 0 ; idx < dev->width() ; idx += 1) - connect(dev->pin_Data(idx), lsig->pin(idx)); + assert(lsig->vector_width() == dev->width()); + connect(dev->pin_Data(), lsig->pin(0)); - for (unsigned idx = 0 ; idx < dev->width_dist() ; idx += 1) - connect(dev->pin_Distance(idx), rsig->pin(idx)); + connect(dev->pin_Distance(), rsig->pin(0)); return osig; } @@ -850,6 +845,9 @@ NetNet* NetESignal::synthesize(Design*des) /* * $Log: expr_synth.cc,v $ + * Revision 1.64 2005/02/19 02:43:38 steve + * Support shifts and divide. + * * Revision 1.63 2005/02/12 06:25:40 steve * Restructure NetMux devices to pass vectors. * Generate NetMux devices from ternary expressions, diff --git a/ivl_target.h b/ivl_target.h index 63e156da5..f20e4f2b9 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.142 2005/02/14 01:51:39 steve Exp $" +#ident "$Id: ivl_target.h,v 1.143 2005/02/19 02:43:38 steve Exp $" #endif #ifdef __cplusplus @@ -766,6 +766,11 @@ extern const char* ivl_udp_name(ivl_udp_t net); * the concatentation. The ivl_lpm_size function returns the number of * inputs help by the device. * + * - Divide (IVL_LPM_DIVIDE) + * The divide operators take two inputs and generate an output. The + * ivl_lpm_width returns the width of the result. The width of the + * inputs are their own. + * * - Multiply (IVL_LPM_MULT) * The multiply takes two inputs and generates an output. Unlike other * arithmetic nodes, the width only refers to the output. The inputs @@ -833,6 +838,12 @@ extern const char* ivl_udp_name(ivl_udp_t net); * vector. The ivl_lpm_size() returns the number of times the input is * repeated to get the desired width. The ivl core assures that the * input vector is exactly ivl_lpm_width() / ivl_lpm_size() bits. + * + * - Shifts (IVL_LPM_SHIFTL/SHIFTR) + * This node takes two inputs, a vector and a shift distance. The + * ivl_lpm_data(0) nexus is the vector input, and the ivl_lpm_data(1) + * the shift distance. The vector input is the same width as the + * output, but the distance has its own width. */ extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */ @@ -858,7 +869,7 @@ extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net); /* IVL_LPM_FF IVL_LPM_RAM */ extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net); /* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT - IVL_LPM_MUX IVL_LPM_RAM IVL_LPM_SUB */ + IVL_LPM_MUX IVL_LPM_RAM IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB */ extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx); /* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */ extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx); @@ -1516,6 +1527,9 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.143 2005/02/19 02:43:38 steve + * Support shifts and divide. + * * Revision 1.142 2005/02/14 01:51:39 steve * Handle bit selects in l-values to assignments. * diff --git a/netlist.cc b/netlist.cc index f65cd175a..a7190a67b 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.237 2005/02/12 06:25:40 steve Exp $" +#ident "$Id: netlist.cc,v 1.238 2005/02/19 02:43:38 steve Exp $" #endif # include "config.h" @@ -842,39 +842,23 @@ const Link& NetAddSub::pin_Result() const /* * The pinout for the NetCLShift is: - * 0 -- Direction - * 1 -- Underflow - * 2 -- Overflow - * 3 -- Data(0) - * 3+W -- Result(0) - * 3+2W -- Distance(0) + * 0 -- Result + * 1 -- Data + * 2 -- Distance */ NetCLShift::NetCLShift(NetScope*s, perm_string n, unsigned width, unsigned width_dist, bool right_flag, bool signed_flag) -: NetNode(s, n, 3+2*width+width_dist), +: NetNode(s, n, 3), 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); - pin(1).set_dir(Link::OUTPUT); pin(1).set_name( - perm_string::literal("Underflow"), 0); - pin(2).set_dir(Link::OUTPUT); pin(2).set_name( - perm_string::literal("Overflow"), 0); - - for (unsigned idx = 0 ; idx < width_ ; idx += 1) { - pin(3+idx).set_dir(Link::INPUT); - pin(3+idx).set_name(perm_string::literal("Data"), idx); - - pin(3+width_+idx).set_dir(Link::OUTPUT); - pin(3+width_+idx).set_name(perm_string::literal("Result"), idx); - } - - for (unsigned idx = 0 ; idx < width_dist_ ; idx += 1) { - pin(3+2*width_+idx).set_dir(Link::INPUT); - pin(3+2*width_+idx).set_name(perm_string::literal("Distance"), idx); - } + pin(0).set_dir(Link::OUTPUT); + pin(0).set_name(perm_string::literal("Result"), 0); + pin(1).set_dir(Link::INPUT); + pin(1).set_name(perm_string::literal("Data"), 0); + pin(2).set_dir(Link::INPUT); + pin(2).set_name(perm_string::literal("Distance"), 0); } NetCLShift::~NetCLShift() @@ -901,74 +885,36 @@ bool NetCLShift::signed_flag() const return signed_flag_; } -#if 0 -Link& NetCLShift::pin_Direction() -{ - return pin(0); -} - -const Link& NetCLShift::pin_Direction() const -{ - return pin(0); -} -#endif - -Link& NetCLShift::pin_Underflow() +Link& NetCLShift::pin_Data() { return pin(1); } -const Link& NetCLShift::pin_Underflow() const +const Link& NetCLShift::pin_Data() const { return pin(1); } -Link& NetCLShift::pin_Overflow() +Link& NetCLShift::pin_Result() +{ + return pin(0); +} + +const Link& NetCLShift::pin_Result() const +{ + return pin(0); +} + +Link& NetCLShift::pin_Distance() { return pin(2); } -const Link& NetCLShift::pin_Overflow() const +const Link& NetCLShift::pin_Distance() const { return pin(2); } -Link& NetCLShift::pin_Data(unsigned idx) -{ - assert(idx < width_); - return pin(3+idx); -} - -const Link& NetCLShift::pin_Data(unsigned idx) const -{ - assert(idx < width_); - return pin(3+idx); -} - -Link& NetCLShift::pin_Result(unsigned idx) -{ - assert(idx < width_); - return pin(3+width_+idx); -} - -const Link& NetCLShift::pin_Result(unsigned idx) const -{ - assert(idx < width_); - return pin(3+width_+idx); -} - -Link& NetCLShift::pin_Distance(unsigned idx) -{ - assert(idx < width_dist_); - return pin(3+2*width_+idx); -} - -const Link& NetCLShift::pin_Distance(unsigned idx) const -{ - assert(idx < width_dist_); - return pin(3+2*width_+idx); -} - NetCompare::NetCompare(NetScope*s, perm_string n, unsigned wi) : NetNode(s, n, 10), width_(wi) { @@ -1116,22 +1062,15 @@ const Link& NetCompare::pin_DataB() const NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr, unsigned wa, unsigned wb) -: NetNode(sc, n, wr+wa+wb), +: NetNode(sc, n, 3), 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) { - pin(p).set_dir(Link::OUTPUT); - pin(p).set_name(perm_string::literal("Result"), idx); - } - for (unsigned idx = 0 ; idx < width_a_ ; idx += 1, p += 1) { - pin(p).set_dir(Link::INPUT); - pin(p).set_name(perm_string::literal("DataA"), idx); - } - for (unsigned idx = 0 ; idx < width_b_ ; idx += 1, p += 1) { - pin(p).set_dir(Link::INPUT); - pin(p).set_name(perm_string::literal("DataB"), idx); - } + pin(0).set_dir(Link::OUTPUT); + pin(0).set_name(perm_string::literal("Result"), 0); + pin(1).set_dir(Link::INPUT); + pin(1).set_name(perm_string::literal("DataA"), 0); + pin(2).set_dir(Link::INPUT); + pin(2).set_name(perm_string::literal("DataB"), 0); } NetDivide::~NetDivide() @@ -1163,40 +1102,34 @@ bool NetDivide::get_signed() const return signed_flag_; } -Link& NetDivide::pin_Result(unsigned idx) +Link& NetDivide::pin_Result() { - assert(idx < width_r_); - return pin(idx); + return pin(0); } -const Link& NetDivide::pin_Result(unsigned idx) const +const Link& NetDivide::pin_Result() const { - assert(idx < width_r_); - return pin(idx); + return pin(0); } -Link& NetDivide::pin_DataA(unsigned idx) +Link& NetDivide::pin_DataA() { - assert(idx < width_a_); - return pin(idx+width_r_); + return pin(1); } -const Link& NetDivide::pin_DataA(unsigned idx) const +const Link& NetDivide::pin_DataA() const { - assert(idx < width_a_); - return pin(idx+width_r_); + return pin(1); } -Link& NetDivide::pin_DataB(unsigned idx) +Link& NetDivide::pin_DataB() { - assert(idx < width_b_); - return pin(idx+width_r_+width_a_); + return pin(2); } -const Link& NetDivide::pin_DataB(unsigned idx) const +const Link& NetDivide::pin_DataB() const { - assert(idx < width_b_); - return pin(idx+width_r_+width_a_); + return pin(2); } NetMult::NetMult(NetScope*sc, perm_string n, unsigned wr, @@ -2258,6 +2191,9 @@ const NetProc*NetTaskDef::proc() const /* * $Log: netlist.cc,v $ + * Revision 1.238 2005/02/19 02:43:38 steve + * Support shifts and divide. + * * Revision 1.237 2005/02/12 06:25:40 steve * Restructure NetMux devices to pass vectors. * Generate NetMux devices from ternary expressions, diff --git a/netlist.h b/netlist.h index cbb0a2727..b5add2dec 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.334 2005/02/12 06:25:40 steve Exp $" +#ident "$Id: netlist.h,v 1.335 2005/02/19 02:43:38 steve Exp $" #endif /* @@ -506,19 +506,13 @@ class NetCLShift : public NetNode { bool right_flag() const; bool signed_flag() const; - Link& pin_Direction(); - Link& pin_Underflow(); - Link& pin_Overflow(); - Link& pin_Data(unsigned idx); - Link& pin_Result(unsigned idx); - Link& pin_Distance(unsigned idx); + Link& pin_Data(); + Link& pin_Result(); + Link& pin_Distance(); - const Link& pin_Direction() const; - const Link& pin_Underflow() const; - const Link& pin_Overflow() const; - const Link& pin_Data(unsigned idx) const; - const Link& pin_Result(unsigned idx) const; - const Link& pin_Distance(unsigned idx) const; + const Link& pin_Data() const; + const Link& pin_Result() const; + const Link& pin_Distance() const; virtual void dump_node(ostream&, unsigned ind) const; virtual bool emit_node(struct target_t*) const; @@ -639,13 +633,13 @@ class NetDivide : public NetNode { void set_signed(bool); bool get_signed() const; - Link& pin_DataA(unsigned idx); - Link& pin_DataB(unsigned idx); - Link& pin_Result(unsigned idx); + Link& pin_DataA(); + Link& pin_DataB(); + Link& pin_Result(); - const Link& pin_DataA(unsigned idx) const; - const Link& pin_DataB(unsigned idx) const; - const Link& pin_Result(unsigned idx) const; + const Link& pin_DataA() const; + const Link& pin_DataB() const; + const Link& pin_Result() const; virtual void dump_node(ostream&, unsigned ind) const; virtual bool emit_node(struct target_t*) const; @@ -3420,6 +3414,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.335 2005/02/19 02:43:38 steve + * Support shifts and divide. + * * Revision 1.334 2005/02/12 06:25:40 steve * Restructure NetMux devices to pass vectors. * Generate NetMux devices from ternary expressions, diff --git a/t-dll-api.cc b/t-dll-api.cc index 4e295e8fc..6f6756192 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.118 2005/02/12 06:25:40 steve Exp $" +#ident "$Id: t-dll-api.cc,v 1.119 2005/02/19 02:43:38 steve Exp $" #endif # include "config.h" @@ -770,8 +770,11 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx) case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTR: - assert(idx < net->u_.shift.width); - return net->u_.shift.d[idx]; + assert(idx <= 1); + if (idx == 0) + return net->u_.shift.d; + else + return net->u_.shift.s; case IVL_LPM_FF: case IVL_LPM_RAM: @@ -933,8 +936,8 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx) case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTR: - assert(idx < net->u_.shift.width); - return net->u_.shift.q[idx]; + assert(idx == 0); + return net->u_.shift.q; case IVL_LPM_UFUNC: assert(idx < net->u_.ufunc.port_wid[0]); @@ -978,11 +981,6 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx) assert(idx == 0); return net->u_.mux.s; - case IVL_LPM_SHIFTL: - case IVL_LPM_SHIFTR: - assert(idx < net->u_.shift.select); - return net->u_.shift.s[idx]; - default: assert(0); return 0; @@ -996,9 +994,6 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net) return net->u_.ff.swid; case IVL_LPM_MUX: return net->u_.mux.swid; - case IVL_LPM_SHIFTL: - case IVL_LPM_SHIFTR: - return net->u_.shift.select; case IVL_LPM_CONCAT: return net->u_.concat.inputs; default: @@ -1992,6 +1987,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net) /* * $Log: t-dll-api.cc,v $ + * Revision 1.119 2005/02/19 02:43:38 steve + * Support shifts and divide. + * * Revision 1.118 2005/02/12 06:25:40 steve * Restructure NetMux devices to pass vectors. * Generate NetMux devices from ternary expressions, diff --git a/t-dll.cc b/t-dll.cc index d5e415e9e..7d0106b89 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.141 2005/02/13 01:15:07 steve Exp $" +#ident "$Id: t-dll.cc,v 1.142 2005/02/19 02:43:38 steve Exp $" #endif # include "config.h" @@ -1211,46 +1211,26 @@ void dll_target::lpm_clshift(const NetCLShift*net) obj->u_.shift.width = net->width(); obj->u_.shift.select = net->width_dist(); - unsigned nex_count = obj->u_.shift.width * 2 + obj->u_.shift.select; - obj->u_.shift.q = new ivl_nexus_t[nex_count]; - obj->u_.shift.d = obj->u_.shift.q + obj->u_.shift.width; - obj->u_.shift.s = obj->u_.shift.d + obj->u_.shift.width; - for (unsigned idx = 0 ; idx < nex_count ; idx += 1) - obj->u_.shift.q[idx] = 0; + const Nexus*nex; - for (unsigned idx = 0 ; idx < net->width() ; idx += 1) { - const Nexus*nex; + nex = net->pin_Result().nexus(); + assert(nex->t_cookie()); - nex = net->pin_Result(idx).nexus(); - assert(nex && nex->t_cookie()); + obj->u_.shift.q = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.shift.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG); - obj->u_.shift.q[idx] = (ivl_nexus_t) nex->t_cookie(); - nexus_lpm_add(obj->u_.shift.q[idx], obj, 0, - IVL_DR_STRONG, IVL_DR_STRONG); - } + nex = net->pin_Data().nexus(); + assert(nex->t_cookie()); - for (unsigned idx = 0 ; idx < net->width() ; idx += 1) { - const Nexus*nex; + obj->u_.shift.d = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.shift.d, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ); - nex = net->pin_Data(idx).nexus(); - assert(nex && nex->t_cookie()); + nex = net->pin_Distance().nexus(); + assert(nex->t_cookie()); - obj->u_.shift.d[idx] = (ivl_nexus_t) nex->t_cookie(); - nexus_lpm_add(obj->u_.shift.q[idx], obj, 0, - IVL_DR_HiZ, IVL_DR_HiZ); - } - - for (unsigned idx = 0 ; idx < net->width_dist() ; idx += 1) { - const Nexus*nex; - - nex = net->pin_Distance(idx).nexus(); - assert(nex && nex->t_cookie()); - - obj->u_.shift.s[idx] = (ivl_nexus_t) nex->t_cookie(); - nexus_lpm_add(obj->u_.shift.s[idx], obj, 0, - IVL_DR_HiZ, IVL_DR_HiZ); - } + obj->u_.shift.s = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.shift.s, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ); scope_add_lpm(obj->scope, obj); } @@ -1373,62 +1353,28 @@ void dll_target::lpm_divide(const NetDivide*net) obj->u_.arith.width = wid; obj->u_.arith.signed_flag = net->get_signed()? 1 : 0; -#if 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; - obj->u_.arith.b = obj->u_.arith.a + obj->u_.arith.width; - for (unsigned idx = 0 ; idx < wid ; idx += 1) { - const Nexus*nex; + const Nexus*nex; - nex = net->pin_Result(idx).nexus(); - assert(nex->t_cookie()); + nex = net->pin_Result().nexus(); + assert(nex->t_cookie()); - obj->u_.arith.q[idx] = (ivl_nexus_t) nex->t_cookie(); - nexus_lpm_add(obj->u_.arith.q[idx], obj, 0, - IVL_DR_STRONG, IVL_DR_STRONG); + obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG); - if (idx < net->width_a()) { - nex = net->pin_DataA(idx).nexus(); - assert(nex); - assert(nex->t_cookie()); + nex = net->pin_DataA().nexus(); + 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); + obj->u_.arith.a = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.arith.a, 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()); + nex = net->pin_DataB().nexus(); + 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; - } + obj->u_.arith.b = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.arith.b, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ); - if (idx < net->width_b()) { - nex = net->pin_DataB(idx).nexus(); - assert(nex); - assert(nex->t_cookie()); - - obj->u_.arith.b[idx] = (ivl_nexus_t) nex->t_cookie(); - nexus_lpm_add(obj->u_.arith.b[idx], obj, 0, - IVL_DR_HiZ, IVL_DR_HiZ); - - } else { - obj->u_.arith.b[idx] = 0; - } - } -#else - cerr << "XXXX t-dll.cc: Forgot how to handle lpm_divide." << endl; -#endif scope_add_lpm(obj->scope, obj); } @@ -2222,6 +2168,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj }; /* * $Log: t-dll.cc,v $ + * Revision 1.142 2005/02/19 02:43:38 steve + * Support shifts and divide. + * * Revision 1.141 2005/02/13 01:15:07 steve * Replace supply nets with wires connected to pullup/down supply devices. * diff --git a/t-dll.h b/t-dll.h index efb2d3507..ddab84214 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.121 2005/02/12 06:25:40 steve Exp $" +#ident "$Id: t-dll.h,v 1.122 2005/02/19 02:43:39 steve Exp $" #endif # include "target.h" @@ -325,9 +325,7 @@ struct ivl_lpm_s { unsigned width; unsigned select; unsigned signed_flag :1; - ivl_nexus_t*q; - ivl_nexus_t*d; - ivl_nexus_t*s; + ivl_nexus_t q, d, s; } shift; struct ivl_lpm_arith_s { @@ -687,6 +685,9 @@ struct ivl_variable_s { /* * $Log: t-dll.h,v $ + * Revision 1.122 2005/02/19 02:43:39 steve + * Support shifts and divide. + * * Revision 1.121 2005/02/12 06:25:40 steve * Restructure NetMux devices to pass vectors. * Generate NetMux devices from ternary expressions, diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 01cc65e2a..f72d20f0d 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.110 2005/02/13 01:15:07 steve Exp $" +#ident "$Id: stub.c,v 1.111 2005/02/19 02:43:39 steve Exp $" #endif # include "config.h" @@ -270,6 +270,16 @@ static void show_lpm_add(ivl_lpm_t net) show_lpm_arithmetic_pins(net); } +static void show_lpm_divide(ivl_lpm_t net) +{ + unsigned width = ivl_lpm_width(net); + + fprintf(out, " LPM_DIVIDE %s: \n", + ivl_lpm_basename(net), width); + + show_lpm_arithmetic_pins(net); +} + /* IVL_LPM_CMP_EEQ * This LPM node supports two-input compare. The output width is * actually always 1, the lpm_width is the expected width of the inputs. @@ -430,6 +440,36 @@ static void show_lpm_mux(ivl_lpm_t net) } } +static void show_lpm_part(ivl_lpm_t net) +{ + unsigned width = ivl_lpm_width(net); + unsigned base = ivl_lpm_base(net); + const char*part_type_string = ""; + + switch (ivl_lpm_type(net)) { + case IVL_LPM_PART_VP: + part_type_string = "VP"; + break; + case IVL_LPM_PART_PV: + part_type_string = "PV"; + break; + default: + break; + } + + fprintf(out, " LPM_PART_%s %s: \n", + part_type_string, ivl_lpm_basename(net), + width, base, ivl_lpm_signed(net)); + fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0))); + fprintf(out, " I: %s\n", ivl_nexus_name(ivl_lpm_data(net,0))); + + /* The compiler must assure that the base plus the part select + width fits within the input to the part select. */ + if (width_of_nexus(ivl_lpm_data(net,0)) < (width+base)) { + fprintf(out, " ERROR: Part select is out of range.\n"); + stub_errors += 1; + } +} /* * The reduction operators have similar characteristics and are @@ -524,25 +564,9 @@ static void show_lpm(ivl_lpm_t net) show_lpm_add(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_DIVIDE: + show_lpm_divide(net); + break; case IVL_LPM_CMP_EEQ: show_lpm_cmp_eeq(net); @@ -643,23 +667,10 @@ static void show_lpm(ivl_lpm_t net) show_lpm_mux(net); break; - case IVL_LPM_PART_VP: { - fprintf(out, " LPM_PART_VP %s: \n", - ivl_lpm_basename(net), - width, ivl_lpm_base(net), ivl_lpm_signed(net)); - fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0))); - fprintf(out, " I: %s\n", ivl_nexus_name(ivl_lpm_data(net,0))); - break; - } - - case IVL_LPM_PART_PV: { - fprintf(out, " LPM_PART_PV %s: \n", - ivl_lpm_basename(net), - width, ivl_lpm_base(net), ivl_lpm_signed(net)); - fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0))); - fprintf(out, " I: %s\n", ivl_nexus_name(ivl_lpm_data(net,0))); - break; - } + case IVL_LPM_PART_VP: + case IVL_LPM_PART_PV: + show_lpm_part(net); + break; case IVL_LPM_REPEAT: show_lpm_repeat(net); @@ -1111,6 +1122,9 @@ int target_design(ivl_design_t des) /* * $Log: stub.c,v $ + * Revision 1.111 2005/02/19 02:43:39 steve + * Support shifts and divide. + * * Revision 1.110 2005/02/13 01:15:07 steve * Replace supply nets with wires connected to pullup/down supply devices. *