/**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_DetectFanoutFreeCone_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst ) { // make the pointer regular pNode = Fraig_Regular(pNode); // if the new node is complemented or a PI, another gate begins if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) ) { Fraig_NodeVecPushUnique( vSuper, pNode ); return; } // go through the branches Fraig_DetectFanoutFreeCone_rec( pNode->p1, vSuper, vInside, 0 ); Fraig_DetectFanoutFreeCone_rec( pNode->p2, vSuper, vInside, 0 ); // add the node Fraig_NodeVecPushUnique( vInside, pNode ); }
/**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_CollectSupergate_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, int fFirst, int fStopAtMux ) { // if the new node is complemented or a PI, another gate begins // if ( Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || Fraig_NodeIsMuxType(pNode) ) if ( (!fFirst && Fraig_Regular(pNode)->nRefs > 1) || Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || (fStopAtMux && Fraig_NodeIsMuxType(pNode)) ) { Fraig_NodeVecPushUnique( vSuper, pNode ); return; } // go through the branches Fraig_CollectSupergate_rec( pNode->p1, vSuper, 0, fStopAtMux ); Fraig_CollectSupergate_rec( pNode->p2, vSuper, 0, fStopAtMux ); }
/**Function************************************************************* Synopsis [Collect variables using their proximity from the nodes.] Description [This procedure creates a variable order based on collecting first the nodes that are the closest to the given two target nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) { Fraig_Node_t * pNode, * pFanin; int i, k, Number, fUseMuxes = 1; int nVarsAlloc; assert( pOld != pNew ); assert( !Fraig_IsComplement(pOld) ); assert( !Fraig_IsComplement(pNew) ); pMan->nTravIds++; // clean the variables nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed); Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 ); Msat_IntVecClear( pMan->vVarsInt ); // add the first node Msat_IntVecPush( pMan->vVarsInt, pOld->Num ); Msat_IntVecWriteEntry( pMan->vVarsUsed, pOld->Num, 1 ); pOld->TravId = pMan->nTravIds; // add the second node Msat_IntVecPush( pMan->vVarsInt, pNew->Num ); Msat_IntVecWriteEntry( pMan->vVarsUsed, pNew->Num, 1 ); pNew->TravId = pMan->nTravIds; // create the variable order for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ ) { // get the new node on the frontier Number = Msat_IntVecReadEntry(pMan->vVarsInt, i); pNode = pMan->vNodes->pArray[Number]; if ( !Fraig_NodeIsAnd(pNode) ) continue; // if the node does not have fanins, create them if ( pNode->vFanins == NULL ) { // create the fanins of the supergate assert( pNode->fClauses == 0 ); // detecting a fanout-free cone (experiment only) // Fraig_DetectFanoutFreeCone( pMan, pNode ); if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) { pNode->vFanins = Fraig_NodeVecAlloc( 4 ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); Fraig_SupergateAddClausesMux( pMan, pNode ); // Fraig_DetectFanoutFreeConeMux( pMan, pNode ); nMuxes++; } else { pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); } assert( pNode->vFanins->nSize > 1 ); pNode->fClauses = 1; pMan->nVarsClauses++; pNode->fMark2 = 1; // goes together with Fraig_SetupAdjacentMark() } // explore the implication fanins of pNode for ( k = 0; k < pNode->vFanins->nSize; k++ ) { pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); if ( pFanin->TravId == pMan->nTravIds ) // already collected continue; // collect and mark Msat_IntVecPush( pMan->vVarsInt, pFanin->Num ); Msat_IntVecWriteEntry( pMan->vVarsUsed, pFanin->Num, 1 ); pFanin->TravId = pMan->nTravIds; } } // set up the adjacent variable information // Fraig_SetupAdjacent( pMan, pMan->vVarsInt ); Fraig_SetupAdjacentMark( pMan, pMan->vVarsInt ); }
/**Function************************************************************* Synopsis [Traverses the cone, collects the numbers and adds the clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { Fraig_Node_t * pFanin; Msat_IntVec_t * vAdjs; int fUseMuxes = 1, i; int fItIsTime; // skip if the node is aleady visited assert( !Fraig_IsComplement(pNode) ); if ( pNode->TravId == pMan->nTravIds ) return; pNode->TravId = pMan->nTravIds; // collect the node's number (closer to reverse topological order) Msat_IntVecPush( pMan->vVarsInt, pNode->Num ); Msat_IntVecWriteEntry( pMan->vVarsUsed, pNode->Num, 1 ); if ( !Fraig_NodeIsAnd( pNode ) ) return; // if the node does not have fanins, create them fItIsTime = 0; if ( pNode->vFanins == NULL ) { fItIsTime = 1; // create the fanins of the supergate assert( pNode->fClauses == 0 ); if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) { pNode->vFanins = Fraig_NodeVecAlloc( 4 ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); Fraig_SupergateAddClausesMux( pMan, pNode ); } else { pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); } assert( pNode->vFanins->nSize > 1 ); pNode->fClauses = 1; pMan->nVarsClauses++; // add fanins vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pNode->Num ); assert( Msat_IntVecReadSize( vAdjs ) == 0 ); for ( i = 0; i < pNode->vFanins->nSize; i++ ) { pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); Msat_IntVecPush( vAdjs, pFanin->Num ); } } // recursively visit the fanins for ( i = 0; i < pNode->vFanins->nSize; i++ ) Fraig_PrepareCones_rec( pMan, Fraig_Regular(pNode->vFanins->pArray[i]) ); if ( fItIsTime ) { // recursively visit the fanins for ( i = 0; i < pNode->vFanins->nSize; i++ ) { pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); Msat_IntVecPush( vAdjs, pNode->Num ); } } }