diff --git a/PExpr.h b/PExpr.h index ca6b6869c..2d693876d 100644 --- a/PExpr.h +++ b/PExpr.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: PExpr.h,v 1.33 2000/04/01 19:31:57 steve Exp $" +#ident "$Id: PExpr.h,v 1.34 2000/04/01 21:40:22 steve Exp $" #endif # include @@ -289,6 +289,11 @@ class PEBinary : public PExpr { unsigned long rise, unsigned long fall, unsigned long decay) const; + NetNet* elaborate_net_div_(Design*des, const string&path, + unsigned lwidth, + unsigned long rise, + unsigned long fall, + unsigned long decay) const; NetNet* elaborate_net_log_(Design*des, const string&path, unsigned lwidth, unsigned long rise, @@ -353,6 +358,9 @@ class PECallFunction : public PExpr { /* * $Log: PExpr.h,v $ + * Revision 1.34 2000/04/01 21:40:22 steve + * Add support for integer division. + * * Revision 1.33 2000/04/01 19:31:57 steve * Named events as far as the pform. * diff --git a/design_dump.cc b/design_dump.cc index 2ae65b1fc..66056b172 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: design_dump.cc,v 1.70 2000/03/29 04:37:10 steve Exp $" +#ident "$Id: design_dump.cc,v 1.71 2000/04/01 21:40:22 steve Exp $" #endif /* @@ -147,6 +147,13 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const dump_obj_attr(o, ind+4); } +void NetDivide::dump_node(ostream&o, unsigned ind) const +{ + o << setw(ind) << "" << "NET_DIVIDE (NetDivide): " << name() << endl; + dump_node_pins(o, ind+4); + dump_obj_attr(o, ind+4); +} + void NetMult::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "LPM_MULT (NetMult): " << name() << endl; @@ -897,6 +904,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.71 2000/04/01 21:40:22 steve + * Add support for integer division. + * * Revision 1.70 2000/03/29 04:37:10 steve * New and improved combinational primitives. * diff --git a/elab_net.cc b/elab_net.cc index d60b7c0c7..333e0fb6c 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 */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elab_net.cc,v 1.28 2000/03/27 04:38:15 steve Exp $" +#ident "$Id: elab_net.cc,v 1.29 2000/04/01 21:40:22 steve Exp $" #endif # include "PExpr.h" @@ -38,9 +38,10 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path, { switch (op_) { case '*': - //case '/': - //case '%': return elaborate_net_mul_(des, path, width, rise, fall, decay); + //case '%': + case '/': + return elaborate_net_div_(des, path, width, rise, fall, decay); case '+': case '-': return elaborate_net_add_(des, path, width, rise, fall, decay); @@ -500,6 +501,57 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, const string&path, return osig; } +/* + * Elaborate a divider gate. + */ +NetNet* PEBinary::elaborate_net_div_(Design*des, const string&path, + unsigned lwidth, + unsigned long rise, + unsigned long fall, + unsigned long decay) const +{ + NetNet*lsig = left_->elaborate_net(des, path, 0, 0, 0, 0); + if (lsig == 0) return 0; + NetNet*rsig = right_->elaborate_net(des, path, 0, 0, 0, 0); + if (rsig == 0) return 0; + + unsigned rwidth = lsig->pin_count(); + if (rsig->pin_count() > rwidth) + rwidth = rsig->pin_count(); + NetDivide*div = new NetDivide(des->local_symbol(path), rwidth, + lsig->pin_count(), + rsig->pin_count()); + 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)); + + if (lwidth == 0) lwidth = rwidth; + NetNet*osig = new NetNet(0, des->local_symbol(path), + NetNet::IMPLICIT, lwidth); + osig->local_flag(true); + des->add_signal(osig); + + unsigned cnt = osig->pin_count(); + if (cnt > rwidth) cnt = rwidth; + + for (unsigned idx = 0 ; idx < cnt ; idx += 1) + connect(div->pin_Result(idx), osig->pin(idx)); + + /* If the lvalue is larger then the result, then pad the + output with constant 0. */ + if (cnt < osig->pin_count()) { + NetConst*tmp = new NetConst(des->local_symbol(path), verinum::V0); + des->add_node(tmp); + for (unsigned idx = cnt ; idx < osig->pin_count() ; idx += 1) + connect(osig->pin(idx), tmp->pin(0)); + } + + return osig; +} + NetNet* PEBinary::elaborate_net_log_(Design*des, const string&path, unsigned lwidth, unsigned long rise, @@ -1356,6 +1408,9 @@ NetNet* PEUnary::elaborate_net(Design*des, const string&path, /* * $Log: elab_net.cc,v $ + * Revision 1.29 2000/04/01 21:40:22 steve + * Add support for integer division. + * * Revision 1.28 2000/03/27 04:38:15 steve * Speling error. * diff --git a/emit.cc b/emit.cc index 409db2982..3bcede6d2 100644 --- a/emit.cc +++ b/emit.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: emit.cc,v 1.35 2000/03/29 04:37:11 steve Exp $" +#ident "$Id: emit.cc,v 1.36 2000/04/01 21:40:22 steve Exp $" #endif /* @@ -85,6 +85,11 @@ void NetConst::emit_node(ostream&o, struct target_t*tgt) const tgt->net_const(o, this); } +void NetDivide::emit_node(ostream&o, struct target_t*tgt) const +{ + tgt->lpm_divide(o, this); +} + void NetFF::emit_node(ostream&o, struct target_t*tgt) const { tgt->lpm_ff(o, this); @@ -402,6 +407,9 @@ bool emit(ostream&o, const Design*des, const char*type) /* * $Log: emit.cc,v $ + * Revision 1.36 2000/04/01 21:40:22 steve + * Add support for integer division. + * * Revision 1.35 2000/03/29 04:37:11 steve * New and improved combinational primitives. * diff --git a/functor.cc b/functor.cc index 8b2103997..3c3fca1e9 100644 --- a/functor.cc +++ b/functor.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: functor.cc,v 1.12 2000/02/23 02:56:54 steve Exp $" +#ident "$Id: functor.cc,v 1.13 2000/04/01 21:40:22 steve Exp $" #endif # include "functor.h" @@ -43,6 +43,10 @@ void functor_t::lpm_const(class Design*, class NetConst*) { } +void functor_t::lpm_divide(class Design*, class NetDivide*) +{ +} + void functor_t::lpm_ff(class Design*, class NetFF*) { } @@ -101,6 +105,11 @@ void NetConst::functor_node(Design*des, functor_t*fun) fun->lpm_const(des, this); } +void NetDivide::functor_node(Design*des, functor_t*fun) +{ + fun->lpm_divide(des, this); +} + void NetFF::functor_node(Design*des, functor_t*fun) { fun->lpm_ff(des, this); @@ -180,6 +189,9 @@ int NetPEvent::match_proc(proc_match_t*that) /* * $Log: functor.cc,v $ + * Revision 1.13 2000/04/01 21:40:22 steve + * Add support for integer division. + * * Revision 1.12 2000/02/23 02:56:54 steve * Macintosh compilers do not support ident. * diff --git a/functor.h b/functor.h index bc1f561ad..56ac6dd62 100644 --- a/functor.h +++ b/functor.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: functor.h,v 1.9 2000/02/23 02:56:54 steve Exp $" +#ident "$Id: functor.h,v 1.10 2000/04/01 21:40:22 steve Exp $" #endif /* @@ -48,6 +48,9 @@ struct functor_t { /* This method is called for each structural constant. */ virtual void lpm_const(class Design*des, class NetConst*); + /* This method is called for each structural constant. */ + virtual void lpm_divide(class Design*des, class NetDivide*); + /* This method is called for each FF in the design. */ virtual void lpm_ff(class Design*des, class NetFF*); @@ -71,6 +74,9 @@ struct proc_match_t { /* * $Log: functor.h,v $ + * Revision 1.10 2000/04/01 21:40:22 steve + * Add support for integer division. + * * Revision 1.9 2000/02/23 02:56:54 steve * Macintosh compilers do not support ident. * @@ -85,20 +91,5 @@ struct proc_match_t { * * Revision 1.5 1999/12/17 06:18:16 steve * Rewrite the cprop functor to use the functor_t interface. - * - * Revision 1.4 1999/12/05 02:24:08 steve - * Synthesize LPM_RAM_DQ for writes into memories. - * - * Revision 1.3 1999/12/01 06:06:16 steve - * Redo synth to use match_proc_t scanner. - * - * Revision 1.2 1999/11/01 02:07:40 steve - * Add the synth functor to do generic synthesis - * and add the LPM_FF device to handle rows of - * flip-flops. - * - * Revision 1.1 1999/07/17 22:01:13 steve - * Add the functor interface for functor transforms. - * */ #endif diff --git a/netlist.cc b/netlist.cc index d0d98ef85..2ac924cec 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.cc,v 1.109 2000/03/29 04:37:11 steve Exp $" +#ident "$Id: netlist.cc,v 1.110 2000/04/01 21:40:22 steve Exp $" #endif # include @@ -932,6 +932,80 @@ const NetObj::Link& NetCompare::pin_DataB(unsigned idx) const return pin(8+width_+idx); } +NetDivide::NetDivide(const string&n, unsigned wr, + unsigned wa, unsigned wb) +: NetNode(n, wr+wa+wb), width_r_(wr), width_a_(wa), width_b_(wb) +{ + unsigned p = 0; + for (unsigned idx = 0 ; idx < width_r_ ; idx += 1, p += 1) { + pin(p).set_dir(NetObj::Link::OUTPUT); + pin(p).set_name("Result", idx); + } + for (unsigned idx = 0 ; idx < width_a_ ; idx += 1, p += 1) { + pin(p).set_dir(NetObj::Link::INPUT); + pin(p).set_name("DataA", idx); + } + for (unsigned idx = 0 ; idx < width_b_ ; idx += 1, p += 1) { + pin(p).set_dir(NetObj::Link::INPUT); + pin(p).set_name("DataB", idx); + } +} + +NetDivide::~NetDivide() +{ +} + +unsigned NetDivide::width_r() const +{ + return width_r_; +} + +unsigned NetDivide::width_a() const +{ + return width_a_; +} + +unsigned NetDivide::width_b() const +{ + return width_b_; +} + +NetObj::Link& NetDivide::pin_Result(unsigned idx) +{ + assert(idx < width_r_); + return pin(idx); +} + +const NetObj::Link& NetDivide::pin_Result(unsigned idx) const +{ + assert(idx < width_r_); + return pin(idx); +} + +NetObj::Link& NetDivide::pin_DataA(unsigned idx) +{ + assert(idx < width_a_); + return pin(idx+width_r_); +} + +const NetObj::Link& NetDivide::pin_DataA(unsigned idx) const +{ + assert(idx < width_a_); + return pin(idx+width_r_); +} + +NetObj::Link& NetDivide::pin_DataB(unsigned idx) +{ + assert(idx < width_b_); + return pin(idx+width_r_+width_a_); +} + +const NetObj::Link& NetDivide::pin_DataB(unsigned idx) const +{ + assert(idx < width_b_); + return pin(idx+width_r_+width_a_); +} + NetMult::NetMult(const string&n, unsigned wr, unsigned wa, unsigned wb, unsigned ws) : NetNode(n, 2+wr+wa+wb+ws), width_r_(wr), width_a_(wa), width_b_(wb), @@ -2523,6 +2597,9 @@ bool NetUDP::sequ_glob_(string input, char output) /* * $Log: netlist.cc,v $ + * Revision 1.110 2000/04/01 21:40:22 steve + * Add support for integer division. + * * Revision 1.109 2000/03/29 04:37:11 steve * New and improved combinational primitives. * diff --git a/netlist.h b/netlist.h index e0170fc60..1c5371e1e 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.h,v 1.115 2000/03/29 04:37:11 steve Exp $" +#ident "$Id: netlist.h,v 1.116 2000/04/01 21:40:22 steve Exp $" #endif /* @@ -411,6 +411,44 @@ class NetCompare : public NetNode { unsigned width_; }; +/* + * This class represents a theoretical (though not necessarily + * practical) integer divider gate. This is not to represent any real + * hardware, but to support the / operator in Verilog, when it shows + * up in structural contexts. + * + * The operands of the operation are the DataA and DataB inputs, + * and the Result output reflects the value DataA/DataB. + */ + +class NetDivide : public NetNode { + + public: + NetDivide(const string&n, unsigned width, unsigned wa, unsigned wb); + ~NetDivide(); + + unsigned width_r() const; + unsigned width_a() const; + unsigned width_b() const; + + NetObj::Link& pin_DataA(unsigned idx); + NetObj::Link& pin_DataB(unsigned idx); + NetObj::Link& pin_Result(unsigned idx); + + const NetObj::Link& pin_DataA(unsigned idx) const; + const NetObj::Link& pin_DataB(unsigned idx) const; + const NetObj::Link& pin_Result(unsigned idx) const; + + virtual void dump_node(ostream&, unsigned ind) const; + virtual void emit_node(ostream&, struct target_t*) const; + virtual void functor_node(Design*des, functor_t*fun); + + private: + unsigned width_r_; + unsigned width_a_; + unsigned width_b_; +}; + /* * This class represents an LPM_FF device. There is no literal gate * type in Verilog that maps, but gates of this type can be inferred. @@ -2228,6 +2266,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.116 2000/04/01 21:40:22 steve + * Add support for integer division. + * * Revision 1.115 2000/03/29 04:37:11 steve * New and improved combinational primitives. * diff --git a/t-vvm.cc b/t-vvm.cc index d407b5042..0899ee467 100644 --- a/t-vvm.cc +++ b/t-vvm.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-vvm.cc,v 1.127 2000/03/29 04:37:11 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.128 2000/04/01 21:40:23 steve Exp $" #endif # include @@ -65,6 +65,7 @@ class target_vvm : public target_t { virtual void lpm_add_sub(ostream&os, const NetAddSub*); virtual void lpm_clshift(ostream&os, const NetCLShift*); virtual void lpm_compare(ostream&os, const NetCompare*); + virtual void lpm_divide(ostream&os, const NetDivide*); virtual void lpm_ff(ostream&os, const NetFF*); virtual void lpm_mult(ostream&os, const NetMult*); virtual void lpm_mux(ostream&os, const NetMux*); @@ -553,12 +554,12 @@ void vvm_proc_rval::expr_binary(const NetEBinary*expr) << "," << lres << "," << rres << ");" << endl; break; case '/': - os_ << setw(indent_) << "" << result << " = vvm_binop_idiv(" - << lres << "," << rres << ");" << endl; + os_ << setw(indent_) << "" << "vvm_binop_idiv(" << result + << "," << lres << "," << rres << ");" << endl; break; case '%': - os_ << setw(indent_) << "" << result << " = vvm_binop_imod(" - << lres << "," << rres << ");" << endl; + os_ << setw(indent_) << "" << "vvm_binop_imod(" << result + << "," << lres << "," << rres << ");" << endl; break; default: cerr << "vvm: Unhandled binary op `" << expr->op() << "': " @@ -1246,6 +1247,44 @@ void target_vvm::lpm_compare(ostream&os, const NetCompare*gate) } } +void target_vvm::lpm_divide(ostream&os, const NetDivide*mul) +{ + string mname = mangle(mul->name()); + + os << "static vvm_idiv " << mname << "(" << mul->width_r() << + "," << mul->width_a() << "," << mul->width_b() << ");" << endl; + + + /* Connect the DataA inputs... */ + for (unsigned idx = 0 ; idx < mul->width_a() ; idx += 1) { + string nexus = nexus_from_link(&mul->pin_DataA(idx)); + unsigned ncode = nexus_wire_map[nexus]; + + init_code << " nexus_wire_table["<width_b() ; idx += 1) { + string nexus = nexus_from_link(&mul->pin_DataB(idx)); + unsigned ncode = nexus_wire_map[nexus]; + + init_code << " nexus_wire_table["<width_r() ; idx += 1) { + string nexus = nexus_from_link(&mul->pin_Result(idx)); + unsigned ncode = nexus_wire_map[nexus]; + + init_code << " nexus_wire_table["< with an svector version, - * Add integer support. - * - * Revision 1.9 1999/05/12 04:03:20 steve - * emit NetAssignMem objects in vvm target. - * - * Revision 1.8 1999/05/01 02:57:53 steve - * Handle much more complex event expressions. - * - * Revision 1.7 1999/04/25 00:44:10 steve - * Core handles subsignal expressions. - * - * Revision 1.6 1999/04/19 01:59:37 steve - * Add memories to the parse and elaboration phases. - * - * Revision 1.5 1999/02/08 02:49:56 steve - * Turn the NetESignal into a NetNode so - * that it can connect to the netlist. - * Implement the case statement. - * Convince t-vvm to output code for - * the case statement. - * - * Revision 1.4 1998/12/01 00:42:15 steve - * Elaborate UDP devices, - * Support UDP type attributes, and - * pass those attributes to nodes that - * are instantiated by elaboration, - * Put modules into a map instead of - * a simple list. - * - * Revision 1.3 1998/11/09 18:55:35 steve - * Add procedural while loops, - * Parse procedural for loops, - * Add procedural wait statements, - * Add constant nodes, - * Add XNOR logic gate, - * Make vvm output look a bit prettier. - * - * Revision 1.2 1998/11/07 17:05:06 steve - * Handle procedural conditional, and some - * of the conditional expressions. - * - * Elaborate signals and identifiers differently, - * allowing the netlist to hold signal information. - * - * Revision 1.1 1998/11/03 23:29:06 steve - * Introduce verilog to CVS. - * */ #endif diff --git a/vvm/Makefile.in b/vvm/Makefile.in index 938a6d147..42d43d6da 100644 --- a/vvm/Makefile.in +++ b/vvm/Makefile.in @@ -18,7 +18,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.27 2000/03/29 04:37:11 steve Exp $" +#ident "$Id: Makefile.in,v 1.28 2000/04/01 21:40:23 steve Exp $" # # SHELL = /bin/sh @@ -60,7 +60,7 @@ all: libvvm.a O = vvm_add_sub.o vvm_bit.o vvm_calltf.o vvm_clshift.o vvm_compare.o \ vvm_event.o vvm_ff.o \ -vvm_func.o vvm_gates.o vvm_mult.o vvm_mux.o \ +vvm_func.o vvm_gates.o vvm_idiv.o vvm_mult.o vvm_mux.o \ vvm_nexus.o vvm_pevent.o vvm_signal.o vvm_thread.o vvm_udp.o vpip.o P = vpi_bit.o vpi_callback.o \ diff --git a/vvm/vvm_func.h b/vvm/vvm_func.h index 439b22d61..17445e7f1 100644 --- a/vvm/vvm_func.h +++ b/vvm/vvm_func.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vvm_func.h,v 1.27 2000/03/26 16:55:41 steve Exp $" +#ident "$Id: vvm_func.h,v 1.28 2000/04/01 21:40:23 steve Exp $" #endif # include "vvm.h" @@ -86,6 +86,13 @@ extern void vvm_binop_plus(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r); +/* + * Integer division. + */ +extern void vvm_binop_idiv(vvm_bitset_t&v, + const vvm_bitset_t&l, + const vvm_bitset_t&r); + /* * The binary - operator is turned into + by doing 2's complement * arithmetic. l-r == l+~r+1. The "+1" is accomplished by adding in a @@ -196,6 +203,9 @@ extern void vvm_ternary(vvm_bitset_t&v, vpip_bit_t c, /* * $Log: vvm_func.h,v $ + * Revision 1.28 2000/04/01 21:40:23 steve + * Add support for integer division. + * * Revision 1.27 2000/03/26 16:55:41 steve * Remove the vvm_bits_t abstract class. * diff --git a/vvm/vvm_gates.h b/vvm/vvm_gates.h index ad46df9d9..81d70ff4d 100644 --- a/vvm/vvm_gates.h +++ b/vvm/vvm_gates.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vvm_gates.h,v 1.53 2000/03/29 04:37:11 steve Exp $" +#ident "$Id: vvm_gates.h,v 1.54 2000/04/01 21:40:23 steve Exp $" #endif # include "vvm.h" @@ -279,6 +279,34 @@ class vvm_ff : public vvm_nexus::recvr_t { vvm_ff& operator= (const vvm_ff&); }; +/* + * This class behaves like a combinational divider. There isn't really + * such a practical device, but this is useful for simulating code + * that includes a / operator in structural contexts. + */ +class vvm_idiv : public vvm_nexus::recvr_t { + + public: + explicit vvm_idiv(unsigned rwid, unsigned awid, unsigned bwid); + ~vvm_idiv(); + + void init_DataA(unsigned idx, vpip_bit_t val); + void init_DataB(unsigned idx, vpip_bit_t val); + + vvm_nexus::drive_t* config_rout(unsigned idx); + unsigned key_DataA(unsigned idx) const; + unsigned key_DataB(unsigned idx) const; + + private: + void take_value(unsigned key, vpip_bit_t val); + + unsigned rwid_; + unsigned awid_; + unsigned bwid_; + vpip_bit_t*bits_; + vvm_nexus::drive_t*out_; +}; + /* * This class behaves like a combinational multiplier. The device * behaves like the LPM_MULT device. @@ -839,6 +867,9 @@ template class vvm_pevent : public vvm_nexus::recvr_t { /* * $Log: vvm_gates.h,v $ + * Revision 1.54 2000/04/01 21:40:23 steve + * Add support for integer division. + * * Revision 1.53 2000/03/29 04:37:11 steve * New and improved combinational primitives. * diff --git a/vvm/vvm_idiv.cc b/vvm/vvm_idiv.cc new file mode 100644 index 000000000..7349ae8ab --- /dev/null +++ b/vvm/vvm_idiv.cc @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2000 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(WINNT) && !defined(macintosh) +#ident "$Id: vvm_idiv.cc,v 1.1 2000/04/01 21:40:23 steve Exp $" +#endif + +# include "vvm_func.h" +# include "vvm_gates.h" +# include + +void vvm_binop_idiv(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r) +{ + assert(v.get_width() <= 8*sizeof(unsigned long)); + assert(l.get_width() <= 8*sizeof(unsigned long)); + assert(r.get_width() <= 8*sizeof(unsigned long)); + + unsigned long lv = 0, rv = 0; + unsigned long vv; + + for (unsigned idx = 0 ; idx < l.get_width() ; idx += 1) { + + if (B_ISXZ(l[idx])) + goto unknown_result; + + if (B_IS1(l[idx])) + lv |= 1 << idx; + } + + for (unsigned idx = 0 ; idx < r.get_width() ; idx += 1) { + + if (B_ISXZ(r[idx])) + goto unknown_result; + + if (B_IS1(r[idx])) + rv |= 1 << idx; + } + + if (rv == 0) + goto unknown_result; + + vv = lv / rv; + + for (unsigned idx = 0 ; idx < v.get_width() ; idx += 1) { + + if (vv & 1) + v[idx] = St1; + else + v[idx] = St0; + + vv >>= 1; + } + + return; + + unknown_result: + for (unsigned idx= 0 ; idx < v.get_width() ; idx += 1) + v[idx] = StX; +} + + +vvm_idiv::vvm_idiv(unsigned rwid, unsigned awid, unsigned bwid) +: rwid_(rwid), awid_(awid), bwid_(bwid) +{ + bits_ = new vpip_bit_t[rwid_+awid_+bwid_]; + for (unsigned idx = 0 ; idx < rwid_+awid_+bwid_ ; idx += 1) + bits_[idx] = StX; + + out_ = new vvm_nexus::drive_t[rwid]; +} + +vvm_idiv::~vvm_idiv() +{ + delete[]out_; + delete[]bits_; +} + +void vvm_idiv::init_DataA(unsigned idx, vpip_bit_t val) +{ + assert(idx < awid_); + bits_[rwid_+idx] = val; +} + +void vvm_idiv::init_DataB(unsigned idx, vpip_bit_t val) +{ + assert(idx < bwid_); + bits_[rwid_+awid_+idx] = val; +} + +vvm_nexus::drive_t* vvm_idiv::config_rout(unsigned idx) +{ + assert(idx < rwid_); + return out_+idx; +} + +unsigned vvm_idiv::key_DataA(unsigned idx) const +{ + assert(idx < awid_); + return rwid_+idx; +} + +unsigned vvm_idiv::key_DataB(unsigned idx) const +{ + assert(idx < bwid_); + return rwid_+awid_+idx; +} + +void vvm_idiv::take_value(unsigned key, vpip_bit_t val) +{ + if (B_EQ(bits_[key], val)) { + bits_[key] = val; + return; + } + + bits_[key] = val; + + vvm_bitset_t r (bits_, rwid_); + vvm_bitset_t a (bits_+rwid_, awid_); + vvm_bitset_t b (bits_+rwid_+awid_, bwid_); + vvm_binop_idiv(r, a, b); + + for (unsigned idx = 0 ; idx < rwid_ ; idx += 1) + out_[idx].set_value(bits_[idx]); + +} + +/* + * $Log: vvm_idiv.cc,v $ + * Revision 1.1 2000/04/01 21:40:23 steve + * Add support for integer division. + * + */ +