mirror of https://github.com/YosysHQ/abc.git
234 lines
6.3 KiB
C
234 lines
6.3 KiB
C
/*
|
||
* Revision Control Information
|
||
*
|
||
* $Source$
|
||
* $Author$
|
||
* $Revision$
|
||
* $Date$
|
||
*
|
||
*/
|
||
/*
|
||
module: gasp.c
|
||
|
||
The "last_gasp" heuristic computes the reduction of each cube in
|
||
the cover (without replacement) and then performs an expansion of
|
||
these cubes. The cubes which expand to cover some other cube are
|
||
added to the original cover and irredundant finds a minimal subset.
|
||
|
||
If one of the reduced cubes expands to cover some other reduced
|
||
cube, then the new prime thus generated is a candidate for reducing
|
||
the size of the cover.
|
||
|
||
super_gasp is a variation on this strategy which extracts a minimal
|
||
subset from the set of all prime implicants which cover all
|
||
maximally reduced cubes.
|
||
*/
|
||
|
||
#include "espresso.h"
|
||
|
||
ABC_NAMESPACE_IMPL_START
|
||
|
||
|
||
|
||
/*
|
||
* reduce_gasp -- compute the maximal reduction of each cube of F
|
||
*
|
||
* If a cube does not reduce, it remains prime; otherwise, it is marked
|
||
* as nonprime. If the cube is redundant (should NEVER happen here) we
|
||
* just crap out ...
|
||
*
|
||
* A cover with all of the cubes of F is returned. Those that did
|
||
* reduce are marked "NONPRIME"; those that reduced are marked "PRIME".
|
||
* The cubes are in the same order as in F.
|
||
*/
|
||
static pcover reduce_gasp(F, D)
|
||
pcover F, D;
|
||
{
|
||
pcube p, last, cunder, *FD;
|
||
pcover G;
|
||
|
||
G = new_cover(F->count);
|
||
FD = cube2list(F, D);
|
||
|
||
/* Reduce cubes of F without replacement */
|
||
foreach_set(F, last, p) {
|
||
cunder = reduce_cube(FD, p);
|
||
if (setp_empty(cunder)) {
|
||
fatal("empty reduction in reduce_gasp, shouldn't happen");
|
||
} else if (setp_equal(cunder, p)) {
|
||
SET(cunder, PRIME); /* just to make sure */
|
||
G = sf_addset(G, p); /* it did not reduce ... */
|
||
} else {
|
||
RESET(cunder, PRIME); /* it reduced ... */
|
||
G = sf_addset(G, cunder);
|
||
}
|
||
if (debug & GASP) {
|
||
printf("REDUCE_GASP: %s reduced to %s\n", pc1(p), pc2(cunder));
|
||
}
|
||
free_cube(cunder);
|
||
}
|
||
|
||
free_cubelist(FD);
|
||
return G;
|
||
}
|
||
|
||
/*
|
||
* expand_gasp -- expand each nonprime cube of F into a prime implicant
|
||
*
|
||
* The gasp strategy differs in that only those cubes which expand to
|
||
* cover some other cube are saved; also, all cubes are expanded
|
||
* regardless of whether they become covered or not.
|
||
*/
|
||
|
||
pcover expand_gasp(F, D, R, Foriginal)
|
||
INOUT pcover F;
|
||
IN pcover D;
|
||
IN pcover R;
|
||
IN pcover Foriginal;
|
||
{
|
||
int c1index;
|
||
pcover G;
|
||
|
||
/* Try to expand each nonprime and noncovered cube */
|
||
G = new_cover(10);
|
||
for(c1index = 0; c1index < F->count; c1index++) {
|
||
expand1_gasp(F, D, R, Foriginal, c1index, &G);
|
||
}
|
||
G = sf_dupl(G);
|
||
G = expand(G, R, /*nonsparse*/ FALSE); /* Make them prime ! */
|
||
return G;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* expand1 -- Expand a single cube against the OFF-set, using the gasp strategy
|
||
*/
|
||
void expand1_gasp(F, D, R, Foriginal, c1index, G)
|
||
pcover F; /* reduced cubes of ON-set */
|
||
pcover D; /* DC-set */
|
||
pcover R; /* OFF-set */
|
||
pcover Foriginal; /* ON-set before reduction (same order as F) */
|
||
int c1index; /* which index of F (or Freduced) to be checked */
|
||
pcover *G;
|
||
{
|
||
register int c2index;
|
||
register pcube p, last, c2under;
|
||
pcube RAISE, FREESET, temp, *FD, c2essential;
|
||
pcover F1;
|
||
|
||
if (debug & EXPAND1) {
|
||
printf("\nEXPAND1_GASP: \t%s\n", pc1(GETSET(F, c1index)));
|
||
}
|
||
|
||
RAISE = new_cube();
|
||
FREESET = new_cube();
|
||
temp = new_cube();
|
||
|
||
/* Initialize the OFF-set */
|
||
R->active_count = R->count;
|
||
foreach_set(R, last, p) {
|
||
SET(p, ACTIVE);
|
||
}
|
||
/* Initialize the reduced ON-set, all nonprime cubes become active */
|
||
F->active_count = F->count;
|
||
foreachi_set(F, c2index, c2under) {
|
||
if (c1index == c2index || TESTP(c2under, PRIME)) {
|
||
F->active_count--;
|
||
RESET(c2under, ACTIVE);
|
||
} else {
|
||
SET(c2under, ACTIVE);
|
||
}
|
||
}
|
||
|
||
/* Initialize the raising and unassigned sets */
|
||
(void) set_copy(RAISE, GETSET(F, c1index));
|
||
(void) set_diff(FREESET, cube.fullset, RAISE);
|
||
|
||
/* Determine parts which must be lowered */
|
||
essen_parts(R, F, RAISE, FREESET);
|
||
|
||
/* Determine parts which can always be raised */
|
||
essen_raising(R, RAISE, FREESET);
|
||
|
||
/* See which, if any, of the reduced cubes we can cover */
|
||
foreachi_set(F, c2index, c2under) {
|
||
if (TESTP(c2under, ACTIVE)) {
|
||
/* See if this cube can be covered by an expansion */
|
||
if (setp_implies(c2under, RAISE) ||
|
||
feasibly_covered(R, c2under, RAISE, temp)) {
|
||
|
||
/* See if c1under can expanded to cover c2 reduced against
|
||
* (F - c1) u c1under; if so, c2 can definitely be removed !
|
||
*/
|
||
|
||
/* Copy F and replace c1 with c1under */
|
||
F1 = sf_save(Foriginal);
|
||
(void) set_copy(GETSET(F1, c1index), GETSET(F, c1index));
|
||
|
||
/* Reduce c2 against ((F - c1) u c1under) */
|
||
FD = cube2list(F1, D);
|
||
c2essential = reduce_cube(FD, GETSET(F1, c2index));
|
||
free_cubelist(FD);
|
||
sf_free(F1);
|
||
|
||
/* See if c2essential is covered by an expansion of c1under */
|
||
if (feasibly_covered(R, c2essential, RAISE, temp)) {
|
||
(void) set_or(temp, RAISE, c2essential);
|
||
RESET(temp, PRIME); /* cube not prime */
|
||
*G = sf_addset(*G, temp);
|
||
}
|
||
set_free(c2essential);
|
||
}
|
||
}
|
||
}
|
||
|
||
free_cube(RAISE);
|
||
free_cube(FREESET);
|
||
free_cube(temp);
|
||
}
|
||
|
||
/* irred_gasp -- Add new primes to F and find an irredundant subset */
|
||
pcover irred_gasp(F, D, G)
|
||
pcover F, D, G; /* G is disposed of */
|
||
{
|
||
if (G->count != 0)
|
||
F = irredundant(sf_append(F, G), D);
|
||
else
|
||
free_cover(G);
|
||
return F;
|
||
}
|
||
|
||
|
||
/* last_gasp */
|
||
pcover last_gasp(F, D, R, cost)
|
||
pcover F, D, R;
|
||
cost_t *cost;
|
||
{
|
||
pcover G, G1;
|
||
|
||
EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
|
||
EXECUTE(G1 = expand_gasp(G, D, R, F), GEXPAND_TIME, G1, *cost);
|
||
free_cover(G);
|
||
EXECUTE(F = irred_gasp(F, D, G1), GIRRED_TIME, F, *cost);
|
||
return F;
|
||
}
|
||
|
||
|
||
/* super_gasp */
|
||
pcover super_gasp(F, D, R, cost)
|
||
pcover F, D, R;
|
||
cost_t *cost;
|
||
{
|
||
pcover G, G1;
|
||
|
||
EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
|
||
EXECUTE(G1 = all_primes(G, R), GEXPAND_TIME, G1, *cost);
|
||
free_cover(G);
|
||
EXEC(G = sf_dupl(sf_append(F, G1)), "NEWPRIMES", G);
|
||
EXECUTE(F = irredundant(G, D), IRRED_TIME, F, *cost);
|
||
return F;
|
||
}
|
||
ABC_NAMESPACE_IMPL_END
|
||
|