| /**CFile**************************************************************** |
| |
| FileName [rpo.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [RPO] |
| |
| Synopsis [Performs read polarity once factorization.] |
| |
| Author [Mayler G. A. Martins / Vinicius Callegaro] |
| |
| Affiliation [UFRGS] |
| |
| Date [Ver. 1.0. Started - May 08, 2013.] |
| |
| Revision [$Id: rpo.c,v 1.00 2013/05/08 00:00:00 mgamartins Exp $] |
| |
| ***********************************************************************/ |
| |
| #include <stdio.h> |
| |
| #include "literal.h" |
| #include "rpo.h" |
| #include "bool/kit/kit.h" |
| #include "misc/util/abc_global.h" |
| #include "misc/vec/vec.h" |
| |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| typedef struct Rpo_Man_t_ Rpo_Man_t; |
| |
| struct Rpo_Man_t_ { |
| unsigned * target; |
| int nVars; |
| |
| Literal_t ** literals; |
| int nLits; |
| int nLitsMax; |
| |
| Rpo_LCI_Edge_t* lci; |
| int nLCIElems; |
| |
| int thresholdMax; |
| |
| }; |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Check if two literals are AND-grouped] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Rpo_CheckANDGroup(Literal_t* lit1, Literal_t* lit2, int nVars) { |
| unsigned* notLit1Func = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); |
| unsigned* notLit2Func = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); |
| unsigned* and1; |
| unsigned* and2; |
| int isZero; |
| |
| Kit_TruthNot(notLit1Func, lit1->function, nVars); |
| Kit_TruthNot(notLit2Func, lit2->function, nVars); |
| and1 = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); |
| and2 = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); |
| Kit_TruthAnd(and1, lit1->transition, notLit2Func, nVars); |
| isZero = Kit_TruthIsConst0(and1, nVars); |
| if (isZero) { |
| Kit_TruthAnd(and2, lit2->transition, notLit1Func, nVars); |
| isZero = Kit_TruthIsConst0(and2, nVars); |
| } |
| ABC_FREE(notLit1Func); |
| ABC_FREE(notLit2Func); |
| ABC_FREE(and1); |
| ABC_FREE(and2); |
| return isZero; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Check if two literals are AND-grouped] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Rpo_CheckORGroup(Literal_t* lit1, Literal_t* lit2, int nVars) { |
| unsigned* and1 = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); |
| unsigned* and2 = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); |
| int isZero; |
| Kit_TruthAnd(and1, lit1->transition, lit2->function, nVars); |
| isZero = Kit_TruthIsConst0(and1, nVars); |
| if (isZero) { |
| Kit_TruthAnd(and2, lit2->transition, lit1->function, nVars); |
| isZero = Kit_TruthIsConst0(and2, nVars); |
| } |
| ABC_FREE(and1); |
| ABC_FREE(and2); |
| return isZero; |
| } |
| |
| Rpo_LCI_Edge_t* Rpo_CreateEdge(Operator_t op, int i, int j, int* vertexDegree) { |
| Rpo_LCI_Edge_t* edge = ABC_ALLOC(Rpo_LCI_Edge_t, 1); |
| edge->connectionType = op; |
| edge->idx1 = i; |
| edge->idx2 = j; |
| edge->visited = 0; |
| vertexDegree[i]++; |
| vertexDegree[j]++; |
| return edge; |
| } |
| |
| int Rpo_computeMinEdgeCost(Rpo_LCI_Edge_t** edges, int edgeCount, int* vertexDegree) { |
| int minCostIndex = -1; |
| int minVertexIndex = -1; |
| unsigned int minCost = ~0; |
| Rpo_LCI_Edge_t* edge; |
| unsigned int edgeCost; |
| int minVertex; |
| int i; |
| for (i = 0; i < edgeCount; ++i) { |
| edge = edges[i]; |
| if (!edge->visited) { |
| edgeCost = vertexDegree[edge->idx1] + vertexDegree[edge->idx2]; |
| minVertex = (edge->idx1 < edge->idx2) ? edge->idx1 : edge->idx2; |
| if (edgeCost < minCost) { |
| minCost = edgeCost; |
| minCostIndex = i; |
| minVertexIndex = minVertex; |
| } else if ((edgeCost == minCost) && minVertex < minVertexIndex) { |
| minCost = edgeCost; |
| minCostIndex = i; |
| minVertexIndex = minVertex; |
| } |
| } |
| } |
| return minCostIndex; |
| } |
| |
| void Rpo_PrintEdge(Rpo_LCI_Edge_t* edge) { |
| Abc_Print(-2, "Edge (%d,%d)/%d\n", edge->idx1, edge->idx2, edge->connectionType); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Test] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Literal_t* Rpo_Factorize(unsigned* target, int nVars, int nThreshold, int verbose) { |
| |
| int nLitCap = nVars * 2; |
| int nLit = 0; |
| int w; |
| Literal_t** vecLit; |
| Literal_t* lit; |
| Literal_t* result; |
| int thresholdCount = 0; |
| |
| if (Kit_TruthIsConst0(target, nVars)) { |
| return Lit_CreateLiteralConst(target, nVars, 0); |
| } else if (Kit_TruthIsConst1(target, nVars)) { |
| return Lit_CreateLiteralConst(target, nVars, 1); |
| } |
| |
| // if (nThreshold == -1) { |
| // nThreshold = nLitCap + nVars; |
| // } |
| if (verbose) { |
| Abc_Print(-2, "Target: "); |
| Lit_PrintTT(target, nVars); |
| Abc_Print(-2, "\n"); |
| } |
| vecLit = ABC_ALLOC(Literal_t*, nLitCap); |
| |
| for (w = nVars - 1; w >= 0; w--) { |
| lit = Lit_Alloc(target, nVars, w, '+'); |
| if (lit != NULL) { |
| vecLit[nLit] = lit; |
| nLit++; |
| } |
| lit = Lit_Alloc(target, nVars, w, '-'); |
| if (lit != NULL) { |
| vecLit[nLit] = lit; |
| nLit++; |
| } |
| } |
| if (verbose) { |
| Abc_Print(-2, "Allocated %d literal clusters\n", nLit); |
| } |
| |
| result = Rpo_Recursion(target, vecLit, nLit, nLit, nVars, &thresholdCount, nThreshold, verbose); |
| |
| //freeing the memory |
| for (w = 0; w < nLit; ++w) { |
| Lit_Free(vecLit[w]); |
| } |
| ABC_FREE(vecLit); |
| |
| return result; |
| |
| } |
| |
| Literal_t* Rpo_Recursion(unsigned* target, Literal_t** vecLit, int nLit, int nLitCount, int nVars, int* thresholdCount, int thresholdMax, int verbose) { |
| int i, j, k; |
| Literal_t* copyResult; |
| int* vertexDegree; |
| int v; |
| int edgeSize; |
| Rpo_LCI_Edge_t** edges; |
| int edgeCount = 0; |
| int isAnd; |
| int isOr; |
| Rpo_LCI_Edge_t* edge; |
| Literal_t* result = NULL; |
| int edgeIndex; |
| int minLitIndex; |
| int maxLitIndex; |
| Literal_t* oldLit1; |
| Literal_t* oldLit2; |
| Literal_t* newLit; |
| |
| *thresholdCount = *thresholdCount + 1; |
| if (*thresholdCount == thresholdMax) { |
| return NULL; |
| } |
| if (verbose) { |
| Abc_Print(-2, "Entering recursion %d\n", *thresholdCount); |
| } |
| // verify if solution is the target or not |
| if (nLitCount == 1) { |
| if (verbose) { |
| Abc_Print(-2, "Checking solution: "); |
| } |
| for (k = 0; k < nLit; ++k) { |
| if (vecLit[k] != NULL) { |
| if (Kit_TruthIsEqual(target, vecLit[k]->function, nVars)) { |
| copyResult = Lit_Copy(vecLit[k], nVars); |
| if (verbose) { |
| Abc_Print(-2, "FOUND!\n", thresholdCount); |
| } |
| thresholdCount = 0; //?? |
| return copyResult; |
| } |
| } |
| } |
| if (verbose) { |
| Abc_Print(-2, "FAILED!\n", thresholdCount); |
| } |
| return NULL; |
| } |
| |
| vertexDegree = ABC_ALLOC(int, nLit); |
| // if(verbose) { |
| // Abc_Print(-2,"Allocating vertexDegree...\n"); |
| // } |
| for (v = 0; v < nLit; v++) { |
| vertexDegree[v] = 0; |
| } |
| // building edges |
| edgeSize = (nLit * (nLit - 1)) / 2; |
| edges = ABC_ALLOC(Rpo_LCI_Edge_t*, edgeSize); |
| if (verbose) { |
| Abc_Print(-2, "Creating Edges: \n"); |
| } |
| |
| for (i = 0; i < nLit; ++i) { |
| if (vecLit[i] == NULL) { |
| continue; |
| } |
| for (j = i; j < nLit; ++j) { |
| if (vecLit[j] == NULL) { |
| continue; |
| } |
| isAnd = Rpo_CheckANDGroup(vecLit[i], vecLit[j], nVars); |
| isOr = Rpo_CheckORGroup(vecLit[i], vecLit[j], nVars); |
| if (isAnd) { |
| if (verbose) { |
| Abc_Print(-2, "Grouped: "); |
| Lit_PrintExp(vecLit[j]); |
| Abc_Print(-2, " AND "); |
| Lit_PrintExp(vecLit[i]); |
| Abc_Print(-2, "\n"); |
| } |
| // add edge |
| edge = Rpo_CreateEdge(LIT_AND, i, j, vertexDegree); |
| edges[edgeCount++] = edge; |
| } |
| if (isOr) { |
| if (verbose) { |
| Abc_Print(-2, "Grouped: "); |
| Lit_PrintExp(vecLit[j]); |
| Abc_Print(-2, " OR "); |
| Lit_PrintExp(vecLit[i]); |
| Abc_Print(-2, "\n"); |
| } |
| // add edge |
| edge = Rpo_CreateEdge(LIT_OR, i, j, vertexDegree); |
| edges[edgeCount++] = edge; |
| } |
| } |
| } |
| if (verbose) { |
| Abc_Print(-2, "%d edges created.\n", edgeCount); |
| } |
| |
| |
| //traverse the edges, grouping new Literal Clusters |
| do { |
| edgeIndex = Rpo_computeMinEdgeCost(edges, edgeCount, vertexDegree); |
| if (edgeIndex < 0) { |
| if (verbose) { |
| Abc_Print(-2, "There is no edges unvisited... Exiting recursion.\n"); |
| //exit(-1); |
| } |
| break; |
| //return NULL; // the graph does not have unvisited edges |
| } |
| edge = edges[edgeIndex]; |
| edge->visited = 1; |
| //Rpo_PrintEdge(edge); |
| minLitIndex = (edge->idx1 < edge->idx2) ? edge->idx1 : edge->idx2; |
| maxLitIndex = (edge->idx1 > edge->idx2) ? edge->idx1 : edge->idx2; |
| oldLit1 = vecLit[minLitIndex]; |
| oldLit2 = vecLit[maxLitIndex]; |
| newLit = Lit_GroupLiterals(oldLit1, oldLit2, (Operator_t)edge->connectionType, nVars); |
| vecLit[minLitIndex] = newLit; |
| vecLit[maxLitIndex] = NULL; |
| |
| if (verbose) { |
| Abc_Print(-2, "New Literal Cluster found: "); |
| Lit_PrintExp(newLit); |
| Abc_Print(-2, " -> "); |
| Lit_PrintTT(newLit->function, nVars); |
| Abc_Print(-2, "\n"); |
| } |
| result = Rpo_Recursion(target, vecLit, nLit, (nLitCount - 1), nVars, thresholdCount, thresholdMax, verbose); |
| //independent of result, free the newLit and restore the vector of Literal Clusters |
| Lit_Free(newLit); |
| vecLit[minLitIndex] = oldLit1; |
| vecLit[maxLitIndex] = oldLit2; |
| if (*thresholdCount == thresholdMax) { |
| break; |
| } |
| } while (result == NULL); |
| //freeing memory |
| // if(verbose) { |
| // Abc_Print(-2,"Freeing vertexDegree...\n"); |
| // } |
| ABC_FREE(vertexDegree); |
| for (i = 0; i < edgeCount; ++i) { |
| //Abc_Print(-2, "%p ", edges[i]); |
| ABC_FREE(edges[i]); |
| } |
| ABC_FREE(edges); |
| return result; |
| } |
| |
| ABC_NAMESPACE_IMPL_END |