From b6d1bb1fa7e92e70c37be29b4b6f428a5c1b0121 Mon Sep 17 00:00:00 2001 From: steve Date: Thu, 30 Dec 1999 04:19:12 +0000 Subject: [PATCH] Propogate constant 0 in low bits of adders. --- cprop.cc | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++- functor.cc | 14 ++++- functor.h | 8 ++- netlist.cc | 7 ++- netlist.h | 6 ++- 5 files changed, 181 insertions(+), 7 deletions(-) diff --git a/cprop.cc b/cprop.cc index f25c9b84c..6aea7beee 100644 --- a/cprop.cc +++ b/cprop.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: cprop.cc,v 1.4 1999/12/17 06:18:15 steve Exp $" +#ident "$Id: cprop.cc,v 1.5 1999/12/30 04:19:12 steve Exp $" #endif # include "netlist.h" @@ -72,9 +72,147 @@ static verinum::V driven_value(const NetObj::Link&lnk) struct cprop_functor : public functor_t { + unsigned count; + + virtual void lpm_add_sub(Design*des, NetAddSub*obj); + virtual void lpm_ff(Design*des, NetFF*obj); virtual void lpm_logic(Design*des, NetLogic*obj); }; +void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj) +{ + // For now, only additions are handled. + if (obj->attribute("LPM_Direction") != "ADD") + return; + + // If the low bit on the A side is 0, then eliminate it from + // the adder, and pass the B side directly to the + // result. Don't reduce the adder smaller then a 1-bit + // adder. These will be eliminated later. + while ((obj->width() > 1) + && all_drivers_constant(obj->pin_DataA(0)) + && (driven_value(obj->pin_DataA(0)) == verinum::V0)) { + + NetAddSub*tmp = 0; + tmp = new NetAddSub(obj->name(), obj->width()-1); + //connect(tmp->pin_Aclr(), obj->pin_Aclr()); + //connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub()); + //connect(tmp->pin_Clock(), obj->pin_Clock()); + //connect(tmp->pin_Cin(), obj->pin_Cin()); + connect(tmp->pin_Cout(), obj->pin_Cout()); + //connect(tmp->pin_Overflow(), obj->pin_Overflow()); + for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) { + connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1)); + connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1)); + connect(tmp->pin_Result(idx), obj->pin_Result(idx+1)); + } + connect(obj->pin_Result(0), obj->pin_DataB(0)); + delete obj; + des->add_node(tmp); + obj = tmp; + count += 1; + } + + // Now do the same thing on the B side. + while ((obj->width() > 1) + && all_drivers_constant(obj->pin_DataB(0)) + && (driven_value(obj->pin_DataB(0)) == verinum::V0)) { + + NetAddSub*tmp = 0; + tmp = new NetAddSub(obj->name(), obj->width()-1); + //connect(tmp->pin_Aclr(), obj->pin_Aclr()); + //connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub()); + //connect(tmp->pin_Clock(), obj->pin_Clock()); + //connect(tmp->pin_Cin(), obj->pin_Cin()); + connect(tmp->pin_Cout(), obj->pin_Cout()); + //connect(tmp->pin_Overflow(), obj->pin_Overflow()); + for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) { + connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1)); + connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1)); + connect(tmp->pin_Result(idx), obj->pin_Result(idx+1)); + } + connect(obj->pin_Result(0), obj->pin_DataA(0)); + delete obj; + des->add_node(tmp); + obj = tmp; + count += 1; + } + + // If the adder is only 1 bit wide, then replace it with the + // simple logic gate. + if (obj->width() == 1) { + NetLogic*tmp; + if (obj->pin_Cout().is_linked()) { + tmp = new NetLogic(des->local_symbol(obj->name()), 3, + NetLogic::AND); + connect(tmp->pin(0), obj->pin_Cout()); + connect(tmp->pin(1), obj->pin_DataA(0)); + connect(tmp->pin(2), obj->pin_DataB(0)); + des->add_node(tmp); + } + tmp = new NetLogic(obj->name(), 3, NetLogic::XOR); + connect(tmp->pin(0), obj->pin_Result(0)); + connect(tmp->pin(1), obj->pin_DataA(0)); + connect(tmp->pin(2), obj->pin_DataB(0)); + delete obj; + des->add_node(tmp); + count += 1; + return; + } + +} + +void cprop_functor::lpm_ff(Design*des, NetFF*obj) +{ + // Look for and count unlinked FF outputs. Note that if the + // Data and Q pins are connected together, they can be removed + // from the circuit. + unsigned unlinked_count = 0; + for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) { + if (connected(obj->pin_Data(idx), obj->pin_Q(idx))) { + obj->pin_Data(idx).unlink(); + obj->pin_Q(idx).unlink(); + } + if (! obj->pin_Q(idx).is_linked()) + unlinked_count += 1; + } + + // If the entire FF is unlinked, remove the whole thing. + if (unlinked_count == obj->width()) { + delete obj; + count += 1; + return; + } + + // If some of the FFs are unconnected, make a new FF array + // that does not include the useless FF devices. + if (unlinked_count > 0) { + NetFF*tmp = new NetFF(obj->name(), obj->width()-unlinked_count); + connect(tmp->pin_Clock(), obj->pin_Clock()); + connect(tmp->pin_Enable(), obj->pin_Enable()); + connect(tmp->pin_Aload(), obj->pin_Aload()); + connect(tmp->pin_Aset(), obj->pin_Aset()); + connect(tmp->pin_Aclr(), obj->pin_Aclr()); + connect(tmp->pin_Sload(), obj->pin_Sload()); + connect(tmp->pin_Sset(), obj->pin_Sset()); + connect(tmp->pin_Sclr(), obj->pin_Sclr()); + + unsigned tidx = 0; + for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) + if (obj->pin_Q(idx).is_linked()) { + connect(tmp->pin_Data(tidx), obj->pin_Data(idx)); + connect(tmp->pin_Q(tidx), obj->pin_Q(idx)); + tidx += 1; + } + + assert(tidx == obj->width() - unlinked_count); + delete obj; + des->add_node(tmp); + count += 1; + return; + } +} + void cprop_functor::lpm_logic(Design*des, NetLogic*obj) { switch (obj->type()) { @@ -89,6 +227,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj) if (driven_value(obj->pin(idx)) == verinum::V0) { connect(obj->pin(0), obj->pin(idx)); delete obj; + count += 1; return; } } @@ -106,6 +245,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj) if (driven_value(obj->pin(idx)) != verinum::V1) { connect(obj->pin(0), obj->pin(idx)); delete obj; + count += 1; return; } } @@ -114,6 +254,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj) // input as the output value and remove the gate. connect(obj->pin(0), obj->pin(1)); delete obj; + count += 1; return; default: @@ -163,8 +304,13 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj) void cprop(Design*des) { + // Continually propogate constants until a scan finds nothing + // to do. cprop_functor prop; - des->functor(&prop); + do { + prop.count = 0; + des->functor(&prop); + } while (prop.count > 0); cprop_dc_functor dc; des->functor(&dc); @@ -172,6 +318,9 @@ void cprop(Design*des) /* * $Log: cprop.cc,v $ + * Revision 1.5 1999/12/30 04:19:12 steve + * Propogate constant 0 in low bits of adders. + * * Revision 1.4 1999/12/17 06:18:15 steve * Rewrite the cprop functor to use the functor_t interface. * diff --git a/functor.cc b/functor.cc index 93e2b3faa..36011c675 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) -#ident "$Id: functor.cc,v 1.7 1999/12/17 06:18:16 steve Exp $" +#ident "$Id: functor.cc,v 1.8 1999/12/30 04:19:12 steve Exp $" #endif # include "functor.h" @@ -35,6 +35,10 @@ void functor_t::process(class Design*, class NetProcTop*) { } +void functor_t::lpm_add_sub(class Design*, class NetAddSub*) +{ +} + void functor_t::lpm_const(class Design*, class NetConst*) { } @@ -83,6 +87,11 @@ void NetNode::functor_node(Design*, functor_t*) { } +void NetAddSub::functor_node(Design*des, functor_t*fun) +{ + fun->lpm_add_sub(des, this); +} + void NetConst::functor_node(Design*des, functor_t*fun) { fun->lpm_const(des, this); @@ -149,6 +158,9 @@ int NetPEvent::match_proc(proc_match_t*that) /* * $Log: functor.cc,v $ + * Revision 1.8 1999/12/30 04:19:12 steve + * Propogate constant 0 in low bits of adders. + * * Revision 1.7 1999/12/17 06:18:16 steve * Rewrite the cprop functor to use the functor_t interface. * diff --git a/functor.h b/functor.h index c3082a0e6..1029aff05 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) -#ident "$Id: functor.h,v 1.5 1999/12/17 06:18:16 steve Exp $" +#ident "$Id: functor.h,v 1.6 1999/12/30 04:19:12 steve Exp $" #endif /* @@ -42,6 +42,9 @@ struct functor_t { /* This method is called for each process in the design. */ virtual void process(class Design*des, class NetProcTop*); + /* This method is called for each structural adder. */ + virtual void lpm_add_sub(class Design*des, class NetAddSub*); + /* This method is called for each structural constant. */ virtual void lpm_const(class Design*des, class NetConst*); @@ -64,6 +67,9 @@ struct proc_match_t { /* * $Log: functor.h,v $ + * Revision 1.6 1999/12/30 04:19:12 steve + * Propogate constant 0 in low bits of adders. + * * Revision 1.5 1999/12/17 06:18:16 steve * Rewrite the cprop functor to use the functor_t interface. * diff --git a/netlist.cc b/netlist.cc index 2d81be5db..910b8215b 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) -#ident "$Id: netlist.cc,v 1.101 1999/12/17 03:38:46 steve Exp $" +#ident "$Id: netlist.cc,v 1.102 1999/12/30 04:19:12 steve Exp $" #endif # include @@ -145,7 +145,7 @@ bool NetObj::Link::is_linked(const NetObj&that) const bool NetObj::Link::is_linked(const NetObj::Link&that) const { for (const Link*idx = next_ ; this != idx ; idx = idx->next_) - if (idx == &that) + if (idx->is_equal(that)) return true; return false; @@ -2764,6 +2764,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) /* * $Log: netlist.cc,v $ + * Revision 1.102 1999/12/30 04:19:12 steve + * Propogate constant 0 in low bits of adders. + * * Revision 1.101 1999/12/17 03:38:46 steve * NetConst can now hold wide constants. * diff --git a/netlist.h b/netlist.h index e41a7c47c..0528d09fa 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) -#ident "$Id: netlist.h,v 1.104 1999/12/17 06:18:16 steve Exp $" +#ident "$Id: netlist.h,v 1.105 1999/12/30 04:19:12 steve Exp $" #endif /* @@ -328,6 +328,7 @@ class NetAddSub : public NetNode { 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); }; /* @@ -2080,6 +2081,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.105 1999/12/30 04:19:12 steve + * Propogate constant 0 in low bits of adders. + * * Revision 1.104 1999/12/17 06:18:16 steve * Rewrite the cprop functor to use the functor_t interface. *