Constant propagation for compare ==.
This commit is contained in:
parent
d3bff8a451
commit
59b69c6dd1
111
cprop.cc
111
cprop.cc
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT) && !defined(macintosh)
|
#if !defined(WINNT) && !defined(macintosh)
|
||||||
#ident "$Id: cprop.cc,v 1.24 2001/02/10 04:50:54 steve Exp $"
|
#ident "$Id: cprop.cc,v 1.25 2001/02/16 03:27:31 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
|
|
@ -39,6 +39,8 @@ struct cprop_functor : public functor_t {
|
||||||
unsigned count;
|
unsigned count;
|
||||||
|
|
||||||
virtual void lpm_add_sub(Design*des, NetAddSub*obj);
|
virtual void lpm_add_sub(Design*des, NetAddSub*obj);
|
||||||
|
virtual void lpm_compare(Design*des, NetCompare*obj);
|
||||||
|
virtual void lpm_compare_eq_(Design*des, NetCompare*obj);
|
||||||
virtual void lpm_ff(Design*des, NetFF*obj);
|
virtual void lpm_ff(Design*des, NetFF*obj);
|
||||||
virtual void lpm_logic(Design*des, NetLogic*obj);
|
virtual void lpm_logic(Design*des, NetLogic*obj);
|
||||||
virtual void lpm_mux(Design*des, NetMux*obj);
|
virtual void lpm_mux(Design*des, NetMux*obj);
|
||||||
|
|
@ -128,6 +130,110 @@ void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
|
||||||
|
{
|
||||||
|
if (obj->pin_AEB().is_linked()) {
|
||||||
|
assert( ! obj->pin_AGB().is_linked() );
|
||||||
|
assert( ! obj->pin_AGEB().is_linked() );
|
||||||
|
assert( ! obj->pin_ALB().is_linked() );
|
||||||
|
assert( ! obj->pin_ALEB().is_linked() );
|
||||||
|
assert( ! obj->pin_AGB().is_linked() );
|
||||||
|
assert( ! obj->pin_ANEB().is_linked() );
|
||||||
|
lpm_compare_eq_(des, obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* First, look for the case where constant bits on matching A
|
||||||
|
and B inputs are different. This this is so, the device can
|
||||||
|
be completely eliminated and replaced with a constant 0. */
|
||||||
|
|
||||||
|
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||||
|
if (! link_drivers_constant(obj->pin_DataA(idx)))
|
||||||
|
continue;
|
||||||
|
if (! link_drivers_constant(obj->pin_DataB(idx)))
|
||||||
|
continue;
|
||||||
|
if (driven_value(obj->pin_DataA(idx)) ==
|
||||||
|
driven_value(obj->pin_DataB(idx)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
NetConst*zero = new NetConst(obj->name(), verinum::V0);
|
||||||
|
connect(zero->pin(0), obj->pin_AEB());
|
||||||
|
delete obj;
|
||||||
|
des->add_node(zero);
|
||||||
|
count += 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Still may need the gate. Run through the inputs again, and
|
||||||
|
look for pairs of constants. Those inputs can be removed. */
|
||||||
|
|
||||||
|
unsigned top = obj->width();
|
||||||
|
for (unsigned idx = 0 ; idx < top ; ) {
|
||||||
|
if (! link_drivers_constant(obj->pin_DataA(idx))) {
|
||||||
|
idx += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (! link_drivers_constant(obj->pin_DataB(idx))) {
|
||||||
|
idx += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->pin_DataA(idx).unlink();
|
||||||
|
obj->pin_DataB(idx).unlink();
|
||||||
|
|
||||||
|
top -= 1;
|
||||||
|
for (unsigned jj = idx ; jj < top ; jj += 1) {
|
||||||
|
connect(obj->pin_DataA(jj), obj->pin_DataA(jj+1));
|
||||||
|
connect(obj->pin_DataB(jj), obj->pin_DataB(jj+1));
|
||||||
|
obj->pin_DataA(jj+1).unlink();
|
||||||
|
obj->pin_DataB(jj+1).unlink();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we wound up disconnecting all the inputs, then remove
|
||||||
|
the device and replace it with a constant. */
|
||||||
|
if (top == 0) {
|
||||||
|
NetConst*one = new NetConst(obj->name(), verinum::V1);
|
||||||
|
connect(one->pin(0), obj->pin_AEB());
|
||||||
|
delete obj;
|
||||||
|
des->add_node(one);
|
||||||
|
count += 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there is only one bit left, then replace the comparator
|
||||||
|
with a simple XOR gate. */
|
||||||
|
if (top == 1) {
|
||||||
|
NetLogic*tmp = new NetLogic(obj->scope(), obj->name(), 3,
|
||||||
|
NetLogic::XOR);
|
||||||
|
connect(tmp->pin(0), obj->pin_AEB());
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (top == obj->width())
|
||||||
|
return;
|
||||||
|
|
||||||
|
NetCompare*tmp = new NetCompare(obj->name(), top);
|
||||||
|
connect(tmp->pin_AEB(), obj->pin_AEB());
|
||||||
|
for (unsigned idx = 0 ; idx < top ; idx += 1) {
|
||||||
|
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx));
|
||||||
|
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx));
|
||||||
|
}
|
||||||
|
delete obj;
|
||||||
|
des->add_node(tmp);
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
void cprop_functor::lpm_ff(Design*des, NetFF*obj)
|
void cprop_functor::lpm_ff(Design*des, NetFF*obj)
|
||||||
{
|
{
|
||||||
// Look for and count unlinked FF outputs. Note that if the
|
// Look for and count unlinked FF outputs. Note that if the
|
||||||
|
|
@ -826,6 +932,9 @@ void cprop(Design*des)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: cprop.cc,v $
|
* $Log: cprop.cc,v $
|
||||||
|
* Revision 1.25 2001/02/16 03:27:31 steve
|
||||||
|
* Constant propagation for compare ==.
|
||||||
|
*
|
||||||
* Revision 1.24 2001/02/10 04:50:54 steve
|
* Revision 1.24 2001/02/10 04:50:54 steve
|
||||||
* Catch constants driving root module ports. (PR#130)
|
* Catch constants driving root module ports. (PR#130)
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue