diff --git a/Makefile.in b/Makefile.in index 20e23af2b..2beb72a0f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -18,7 +18,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.65 2000/09/09 15:21:26 steve Exp $" +#ident "$Id: Makefile.in,v 1.66 2000/09/17 21:26:15 steve Exp $" # # SHELL = /bin/sh @@ -76,8 +76,8 @@ O = main.o cprop.o design_dump.o dup_expr.o elaborate.o elab_expr.o \ elab_lval.o elab_net.o elab_pexpr.o elab_scope.o elab_sig.o emit.o eval.o \ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \ mangle.o netlist.o net_assign.o \ -net_design.o net_event.o net_force.o net_link.o net_proc.o net_scope.o \ -net_udp.o \ +net_design.o net_event.o net_force.o net_link.o net_modulo.o net_proc.o \ +net_scope.o net_udp.o \ pad_to_width.o \ parse.o parse_misc.o pform.o pform_dump.o \ set_width.o \ diff --git a/PExpr.h b/PExpr.h index 5417a3b11..1dd88a7b0 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.43 2000/09/09 15:21:26 steve Exp $" +#ident "$Id: PExpr.h,v 1.44 2000/09/17 21:26:15 steve Exp $" #endif # include @@ -146,7 +146,7 @@ class PEEvent : public PExpr { edge_t type() const; PExpr* expr() const; - + virtual void dump(ostream&) const; private: @@ -324,6 +324,11 @@ class PEBinary : public PExpr { unsigned long rise, unsigned long fall, unsigned long decay) const; + NetNet* elaborate_net_mod_(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, @@ -392,6 +397,9 @@ class PECallFunction : public PExpr { /* * $Log: PExpr.h,v $ + * Revision 1.44 2000/09/17 21:26:15 steve + * Add support for modulus (Eric Aardoom) + * * Revision 1.43 2000/09/09 15:21:26 steve * move lval elaboration to PExpr virtual methods. * diff --git a/design_dump.cc b/design_dump.cc index 29b2986e7..95806bc92 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.96 2000/09/10 02:18:16 steve Exp $" +#ident "$Id: design_dump.cc,v 1.97 2000/09/17 21:26:15 steve Exp $" #endif /* @@ -297,6 +297,13 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const dump_obj_attr(o, ind+4); } +void NetModulo::dump_node(ostream&o, unsigned ind) const +{ + o << setw(ind) << "" << "NET_MODULO (NetModulo): " << name() << endl; + dump_node_pins(o, ind+4); + dump_obj_attr(o, ind+4); +} + void NetRamDq::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): " @@ -969,6 +976,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.97 2000/09/17 21:26:15 steve + * Add support for modulus (Eric Aardoom) + * * Revision 1.96 2000/09/10 02:18:16 steve * elaborate complex l-values * diff --git a/elab_net.cc b/elab_net.cc index 80586e413..70cca7e6d 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.46 2000/09/07 21:28:51 steve Exp $" +#ident "$Id: elab_net.cc,v 1.47 2000/09/17 21:26:15 steve Exp $" #endif # include "PExpr.h" @@ -41,7 +41,8 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path, switch (op_) { case '*': return elaborate_net_mul_(des, path, width, rise, fall, decay); - //case '%': + case '%': + return elaborate_net_mod_(des, path, width, rise, fall, decay); case '/': return elaborate_net_div_(des, path, width, rise, fall, decay); case '+': @@ -584,6 +585,58 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, const string&path, return osig; } +/* + * Elaborate a modulo gate. + */ +NetNet* PEBinary::elaborate_net_mod_(Design*des, const string&path, + unsigned lwidth, + unsigned long rise, + unsigned long fall, + unsigned long decay) const +{ + NetScope*scope = des->find_scope(path); + assert(scope); + 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(); + NetModulo*mod = new NetModulo(des->local_symbol(path), rwidth, + lsig->pin_count(), + rsig->pin_count()); + des->add_node(mod); + + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) + connect(mod->pin_DataA(idx), lsig->pin(idx)); + for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1) + connect(mod->pin_DataB(idx), rsig->pin(idx)); + + if (lwidth == 0) lwidth = rwidth; + NetNet*osig = new NetNet(scope, des->local_symbol(path), + NetNet::IMPLICIT, lwidth); + osig->local_flag(true); + + unsigned cnt = osig->pin_count(); + if (cnt > rwidth) cnt = rwidth; + + for (unsigned idx = 0 ; idx < cnt ; idx += 1) + connect(mod->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, @@ -1693,6 +1746,9 @@ NetNet* PEUnary::elaborate_net(Design*des, const string&path, /* * $Log: elab_net.cc,v $ + * Revision 1.47 2000/09/17 21:26:15 steve + * Add support for modulus (Eric Aardoom) + * * Revision 1.46 2000/09/07 21:28:51 steve * more robust abut ternary bit widths. * diff --git a/emit.cc b/emit.cc index 5453575b4..418ab7071 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.52 2000/09/02 20:54:20 steve Exp $" +#ident "$Id: emit.cc,v 1.53 2000/09/17 21:26:15 steve Exp $" #endif /* @@ -112,6 +112,12 @@ bool NetForce::emit_node(struct target_t*tgt) const return true; } +bool NetModulo::emit_node(struct target_t*tgt) const +{ + tgt->lpm_modulo(this); + return true; +} + bool NetMult::emit_node(struct target_t*tgt) const { tgt->lpm_mult(this); @@ -475,6 +481,9 @@ bool emit(const Design*des, const char*type) /* * $Log: emit.cc,v $ + * Revision 1.53 2000/09/17 21:26:15 steve + * Add support for modulus (Eric Aardoom) + * * Revision 1.52 2000/09/02 20:54:20 steve * Rearrange NetAssign to make NetAssign_ separate. * diff --git a/functor.cc b/functor.cc index 2f805f61a..e05cc8d28 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.21 2000/08/01 02:48:41 steve Exp $" +#ident "$Id: functor.cc,v 1.22 2000/09/17 21:26:15 steve Exp $" #endif # include "functor.h" @@ -55,6 +55,10 @@ void functor_t::lpm_divide(class Design*, class NetDivide*) { } +void functor_t::lpm_modulo(class Design*, class NetModulo*) +{ +} + void functor_t::lpm_ff(class Design*, class NetFF*) { } @@ -172,6 +176,11 @@ void NetLogic::functor_node(Design*des, functor_t*fun) fun->lpm_logic(des, this); } +void NetModulo::functor_node(Design*des, functor_t*fun) +{ + fun->lpm_modulo(des, this); +} + void NetMult::functor_node(Design*des, functor_t*fun) { fun->lpm_mult(des, this); @@ -265,6 +274,9 @@ int proc_match_t::event_wait(NetEvWait*) /* * $Log: functor.cc,v $ + * Revision 1.22 2000/09/17 21:26:15 steve + * Add support for modulus (Eric Aardoom) + * * Revision 1.21 2000/08/01 02:48:41 steve * Support <= in synthesis of DFF and ram devices. * diff --git a/functor.h b/functor.h index cc89ab1e7..15202eb52 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.16 2000/08/01 02:48:42 steve Exp $" +#ident "$Id: functor.h,v 1.17 2000/09/17 21:26:15 steve Exp $" #endif /* @@ -63,6 +63,9 @@ struct functor_t { /* This method is called for each structural constant. */ virtual void lpm_divide(class Design*des, class NetDivide*); + /* This method is called for each structural constant. */ + virtual void lpm_modulo(class Design*des, class NetModulo*); + /* This method is called for each FF in the design. */ virtual void lpm_ff(class Design*des, class NetFF*); @@ -91,6 +94,9 @@ struct proc_match_t { /* * $Log: functor.h,v $ + * Revision 1.17 2000/09/17 21:26:15 steve + * Add support for modulus (Eric Aardoom) + * * Revision 1.16 2000/08/01 02:48:42 steve * Support <= in synthesis of DFF and ram devices. * diff --git a/net_modulo.cc b/net_modulo.cc new file mode 100644 index 000000000..4892fe150 --- /dev/null +++ b/net_modulo.cc @@ -0,0 +1,105 @@ +/* + * 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: net_modulo.cc,v 1.1 2000/09/17 21:26:15 steve Exp $" +#endif + +# include +# include +# include +# include + +# include "netlist.h" + + +NetModulo::NetModulo(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(Link::OUTPUT); + pin(p).set_name("Result", idx); + } + for (unsigned idx = 0 ; idx < width_a_ ; idx += 1, p += 1) { + pin(p).set_dir(Link::INPUT); + pin(p).set_name("DataA", idx); + } + for (unsigned idx = 0 ; idx < width_b_ ; idx += 1, p += 1) { + pin(p).set_dir(Link::INPUT); + pin(p).set_name("DataB", idx); + } +} + +NetModulo::~NetModulo() +{ +} + +unsigned NetModulo::width_r() const +{ + return width_r_; +} + +unsigned NetModulo::width_a() const +{ + return width_a_; +} + +unsigned NetModulo::width_b() const +{ + return width_b_; +} + +Link& NetModulo::pin_Result(unsigned idx) +{ + assert(idx < width_r_); + return pin(idx); +} + +const Link& NetModulo::pin_Result(unsigned idx) const +{ + assert(idx < width_r_); + return pin(idx); +} + +Link& NetModulo::pin_DataA(unsigned idx) +{ + assert(idx < width_a_); + return pin(idx+width_r_); +} + +const Link& NetModulo::pin_DataA(unsigned idx) const +{ + assert(idx < width_a_); + return pin(idx+width_r_); +} + +Link& NetModulo::pin_DataB(unsigned idx) +{ + assert(idx < width_b_); + return pin(idx+width_r_+width_a_); +} + +const Link& NetModulo::pin_DataB(unsigned idx) const +{ + assert(idx < width_b_); + return pin(idx+width_r_+width_a_); +} + + diff --git a/netlist.h b/netlist.h index 48850dad1..f3034ac1d 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.162 2000/09/10 02:18:16 steve Exp $" +#ident "$Id: netlist.h,v 1.163 2000/09/17 21:26:15 steve Exp $" #endif /* @@ -513,6 +513,44 @@ class NetDivide : public NetNode { unsigned width_b_; }; +/* + * This class represents a theoretical (though not necessarily + * practical) integer modulo 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 NetModulo : public NetNode { + + public: + NetModulo(const string&n, unsigned width, unsigned wa, unsigned wb); + ~NetModulo(); + + unsigned width_r() const; + unsigned width_a() const; + unsigned width_b() const; + + Link& pin_DataA(unsigned idx); + Link& pin_DataB(unsigned idx); + Link& pin_Result(unsigned idx); + + const Link& pin_DataA(unsigned idx) const; + const Link& pin_DataB(unsigned idx) const; + const Link& pin_Result(unsigned idx) const; + + virtual void dump_node(ostream&, unsigned ind) const; + virtual bool emit_node(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. @@ -2762,6 +2800,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.163 2000/09/17 21:26:15 steve + * Add support for modulus (Eric Aardoom) + * * Revision 1.162 2000/09/10 02:18:16 steve * elaborate complex l-values * diff --git a/t-vvm.cc b/t-vvm.cc index bbef3c5ee..8a64448ae 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.174 2000/09/16 21:28:14 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.175 2000/09/17 21:26:15 steve Exp $" #endif # include @@ -156,6 +156,7 @@ class target_vvm : public target_t { virtual void lpm_clshift(const NetCLShift*); virtual void lpm_compare(const NetCompare*); virtual void lpm_divide(const NetDivide*); + virtual void lpm_modulo(const NetModulo*); virtual void lpm_ff(const NetFF*); virtual void lpm_mult(const NetMult*); virtual void lpm_mux(const NetMux*); @@ -1535,6 +1536,44 @@ void target_vvm::lpm_divide(const NetDivide*mul) } } +void target_vvm::lpm_modulo(const NetModulo*mul) +{ + string mname = mangle(mul->name()); + + out << "static vvm_imod " << 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 = mul->pin_DataA(idx).nexus()->name(); + unsigned ncode = nexus_wire_map[nexus]; + + init_code << " nexus_wire_table["<width_b() ; idx += 1) { + string nexus = mul->pin_DataB(idx).nexus()->name(); + unsigned ncode = nexus_wire_map[nexus]; + + init_code << " nexus_wire_table["<width_r() ; idx += 1) { + string nexus = mul->pin_Result(idx).nexus()->name(); + unsigned ncode = nexus_wire_map[nexus]; + + init_code << " nexus_wire_table["<