Handle constant propagation through XOR gates,
including reducing the gate to a constant, a buffer or an inverter if possible.
This commit is contained in:
parent
11e6440162
commit
fc6978e4de
106
cprop.cc
106
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.18 2000/11/11 00:03:36 steve Exp $"
|
#ident "$Id: cprop.cc,v 1.19 2000/11/18 04:10:37 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
|
|
@ -228,6 +228,9 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||||
unsigned top = obj->pin_count();
|
unsigned top = obj->pin_count();
|
||||||
unsigned idx = 1;
|
unsigned idx = 1;
|
||||||
|
|
||||||
|
/* Eliminate all the 0 inputs. They have no effect
|
||||||
|
on the output of an XOR gate. Don't remove the
|
||||||
|
last input, though. */
|
||||||
while (idx < top) {
|
while (idx < top) {
|
||||||
if (! link_drivers_constant(obj->pin(idx))) {
|
if (! link_drivers_constant(obj->pin(idx))) {
|
||||||
idx += 1;
|
idx += 1;
|
||||||
|
|
@ -247,9 +250,100 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Look for pairs of constant 1 inputs. If I find a
|
||||||
|
pair, then eliminate both. Each iteration through
|
||||||
|
the loop, the `one' variable holds the index to
|
||||||
|
the previous V1, or 0 if there is none.
|
||||||
|
|
||||||
|
The `ones' variable counts the number of V1
|
||||||
|
inputs. After this loop completes, `ones' will be
|
||||||
|
0 or 1. */
|
||||||
|
|
||||||
|
unsigned one = 0, ones = 0;
|
||||||
|
idx = 1;
|
||||||
|
while (idx < top) {
|
||||||
|
if (! link_drivers_constant(obj->pin(idx))) {
|
||||||
|
idx += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (driven_value(obj->pin(idx)) == verinum::V1) {
|
||||||
|
if (one == 0) {
|
||||||
|
one = idx;
|
||||||
|
ones += 1;
|
||||||
|
idx += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->pin(idx).unlink();
|
||||||
|
top -= 1;
|
||||||
|
if (idx < top) {
|
||||||
|
connect(obj->pin(idx), obj->pin(top));
|
||||||
|
obj->pin(top).unlink();
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->pin(one).unlink();
|
||||||
|
top -= 1;
|
||||||
|
if (one < top) {
|
||||||
|
connect(obj->pin(one), obj->pin(top));
|
||||||
|
obj->pin(top).unlink();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(ones == 1);
|
||||||
|
ones = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If all the inputs were eliminated, then replace
|
||||||
|
the gate with a constant 0 and I am done. */
|
||||||
|
if (top == 1) {
|
||||||
|
NetConst*tmp = new NetConst(obj->name(), verinum::V0);
|
||||||
|
|
||||||
|
des->add_node(tmp);
|
||||||
|
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||||
|
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||||
|
connect(obj->pin(0), tmp->pin(0));
|
||||||
|
|
||||||
|
delete obj;
|
||||||
|
count += 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there is a stray V1 input and only one other
|
||||||
|
input, then replace the gate with an inverter and
|
||||||
|
we are done. */
|
||||||
|
|
||||||
|
if ((top == 3) && (ones == 1)) {
|
||||||
|
unsigned save;
|
||||||
|
if (! link_drivers_constant(obj->pin(1)))
|
||||||
|
save = 1;
|
||||||
|
else if (driven_value(obj->pin(1)) != verinum::V1)
|
||||||
|
save = 1;
|
||||||
|
else
|
||||||
|
save = 2;
|
||||||
|
|
||||||
|
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||||
|
obj->name(), 2,
|
||||||
|
NetLogic::NOT);
|
||||||
|
des->add_node(tmp);
|
||||||
|
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||||
|
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||||
|
connect(obj->pin(0), tmp->pin(0));
|
||||||
|
connect(obj->pin(save), tmp->pin(1));
|
||||||
|
|
||||||
|
delete obj;
|
||||||
|
count += 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we are down to only one input, then replace
|
||||||
|
the XOR with a BUF and exit now. */
|
||||||
if (top == 2) {
|
if (top == 2) {
|
||||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||||
obj->name(), top,
|
obj->name(), 2,
|
||||||
NetLogic::BUF);
|
NetLogic::BUF);
|
||||||
des->add_node(tmp);
|
des->add_node(tmp);
|
||||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||||
|
|
@ -261,6 +355,9 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Finally, this cleans up the gate by creating a
|
||||||
|
new XOR gate that has the right number of
|
||||||
|
inputs, connected in the right place. */
|
||||||
if (top < obj->pin_count()) {
|
if (top < obj->pin_count()) {
|
||||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||||
obj->name(), top,
|
obj->name(), top,
|
||||||
|
|
@ -434,6 +531,11 @@ void cprop(Design*des)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: cprop.cc,v $
|
* $Log: cprop.cc,v $
|
||||||
|
* Revision 1.19 2000/11/18 04:10:37 steve
|
||||||
|
* Handle constant propagation through XOR gates,
|
||||||
|
* including reducing the gate to a constant,
|
||||||
|
* a buffer or an inverter if possible.
|
||||||
|
*
|
||||||
* Revision 1.18 2000/11/11 00:03:36 steve
|
* Revision 1.18 2000/11/11 00:03:36 steve
|
||||||
* Add support for the t-dll backend grabing flip-flops.
|
* Add support for the t-dll backend grabing flip-flops.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue