/**CFile**************************************************************** Copyright (c) The Regents of the University of California. All rights reserved. Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. FileName [cnfCut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG-to-CNF conversion.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: cnfCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cnf.h" #include "kit.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates cut of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cnf_Cut_t * Cnf_CutAlloc( Cnf_Man_t * p, int nLeaves ) { Cnf_Cut_t * pCut; int nSize = sizeof(Cnf_Cut_t) + sizeof(int) * nLeaves + sizeof(unsigned) * Aig_TruthWordNum(nLeaves); pCut = (Cnf_Cut_t *)Aig_MmFlexEntryFetch( p->pMemCuts, nSize ); pCut->nFanins = nLeaves; pCut->nWords = Aig_TruthWordNum(nLeaves); pCut->vIsop[0] = pCut->vIsop[1] = NULL; return pCut; } /**Function************************************************************* Synopsis [Deallocates cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cnf_CutFree( Cnf_Cut_t * pCut ) { if ( pCut->vIsop[0] ) Vec_IntFree( pCut->vIsop[0] ); if ( pCut->vIsop[1] ) Vec_IntFree( pCut->vIsop[1] ); } /**Function************************************************************* Synopsis [Creates cut for the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cnf_Cut_t * Cnf_CutCreate( Cnf_Man_t * p, Aig_Obj_t * pObj ) { Dar_Cut_t * pCutBest; Cnf_Cut_t * pCut; unsigned * pTruth; assert( Aig_ObjIsNode(pObj) ); pCutBest = Dar_ObjBestCut( pObj ); assert( pCutBest != NULL ); assert( pCutBest->nLeaves <= 4 ); pCut = Cnf_CutAlloc( p, pCutBest->nLeaves ); memcpy( pCut->pFanins, pCutBest->pLeaves, sizeof(int) * pCutBest->nLeaves ); pTruth = Cnf_CutTruth(pCut); *pTruth = (pCutBest->uTruth << 16) | pCutBest->uTruth; pCut->Cost = Cnf_CutSopCost( p, pCutBest ); return pCut; } /**Function************************************************************* Synopsis [Deallocates cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cnf_CutPrint( Cnf_Cut_t * pCut ) { int i; printf( "{" ); for ( i = 0; i < pCut->nFanins; i++ ) printf( "%d ", pCut->pFanins[i] ); printf( " } " ); } /**Function************************************************************* Synopsis [Allocates cut of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cnf_CutDeref( Cnf_Man_t * p, Cnf_Cut_t * pCut ) { Aig_Obj_t * pObj; int i; Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } } /**Function************************************************************* Synopsis [Allocates cut of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cnf_CutRef( Cnf_Man_t * p, Cnf_Cut_t * pCut ) { Aig_Obj_t * pObj; int i; Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i ) { pObj->nRefs++; } } /**Function************************************************************* Synopsis [Allocates cut of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cnf_CutUpdateRefs( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, Cnf_Cut_t * pCutRes ) { Cnf_CutDeref( p, pCut ); Cnf_CutDeref( p, pCutFan ); Cnf_CutRef( p, pCutRes ); } /**Function************************************************************* Synopsis [Merges two arrays of integers.] Description [Returns the number of items.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cnf_CutMergeLeaves( Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int * pFanins ) { int i, k, nFanins = 0; for ( i = k = 0; i < pCut->nFanins && k < pCutFan->nFanins; ) { if ( pCut->pFanins[i] == pCutFan->pFanins[k] ) pFanins[nFanins++] = pCut->pFanins[i], i++, k++; else if ( pCut->pFanins[i] < pCutFan->pFanins[k] ) pFanins[nFanins++] = pCut->pFanins[i], i++; else pFanins[nFanins++] = pCutFan->pFanins[k], k++; } for ( ; i < pCut->nFanins; i++ ) pFanins[nFanins++] = pCut->pFanins[i]; for ( ; k < pCutFan->nFanins; k++ ) pFanins[nFanins++] = pCutFan->pFanins[k]; return nFanins; } /**Function************************************************************* Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Cnf_TruthPhase( Cnf_Cut_t * pCut, Cnf_Cut_t * pCut1 ) { unsigned uPhase = 0; int i, k; for ( i = k = 0; i < pCut->nFanins; i++ ) { if ( k == pCut1->nFanins ) break; if ( pCut->pFanins[i] < pCut1->pFanins[k] ) continue; assert( pCut->pFanins[i] == pCut1->pFanins[k] ); uPhase |= (1 << i); k++; } return uPhase; } /**Function************************************************************* Synopsis [Removes the fanin variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cnf_CutRemoveIthVar( Cnf_Cut_t * pCut, int iVar, int iFan ) { int i; assert( pCut->pFanins[iVar] == iFan ); pCut->nFanins--; for ( i = iVar; i < pCut->nFanins; i++ ) pCut->pFanins[i] = pCut->pFanins[i+1]; } /**Function************************************************************* Synopsis [Inserts the fanin variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cnf_CutInsertIthVar( Cnf_Cut_t * pCut, int iVar, int iFan ) { int i; for ( i = pCut->nFanins; i > iVar; i-- ) pCut->pFanins[i] = pCut->pFanins[i-1]; pCut->pFanins[iVar] = iFan; pCut->nFanins++; } /**Function************************************************************* Synopsis [Merges two cuts.] Description [Returns NULL of the cuts cannot be merged.] SideEffects [] SeeAlso [] ***********************************************************************/ Cnf_Cut_t * Cnf_CutCompose( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int iFan ) { Cnf_Cut_t * pCutRes; static THREAD_LOCAL int pFanins[32]; unsigned * pTruth, * pTruthFan, * pTruthRes; unsigned * pTop = p->pTruths[0], * pFan = p->pTruths[2], * pTemp = p->pTruths[3]; unsigned uPhase, uPhaseFan; int i, iVar, nFanins, RetValue; // make sure the second cut is the fanin of the first for ( iVar = 0; iVar < pCut->nFanins; iVar++ ) if ( pCut->pFanins[iVar] == iFan ) break; assert( iVar < pCut->nFanins ); // remove this variable Cnf_CutRemoveIthVar( pCut, iVar, iFan ); // merge leaves of the cuts nFanins = Cnf_CutMergeLeaves( pCut, pCutFan, pFanins ); if ( nFanins+1 > p->nMergeLimit ) { Cnf_CutInsertIthVar( pCut, iVar, iFan ); return NULL; } // create new cut pCutRes = Cnf_CutAlloc( p, nFanins ); memcpy( pCutRes->pFanins, pFanins, sizeof(int) * nFanins ); assert( pCutRes->nFanins <= pCut->nFanins + pCutFan->nFanins ); // derive its truth table // get the truth tables in the composition space pTruth = Cnf_CutTruth(pCut); pTruthFan = Cnf_CutTruth(pCutFan); pTruthRes = Cnf_CutTruth(pCutRes); for ( i = 0; i < 2*pCutRes->nWords; i++ ) pTop[i] = pTruth[i % pCut->nWords]; for ( i = 0; i < pCutRes->nWords; i++ ) pFan[i] = pTruthFan[i % pCutFan->nWords]; // move the variable to the end uPhase = Kit_BitMask( pCutRes->nFanins+1 ) & ~(1 << iVar); Kit_TruthShrink( pTemp, pTop, pCutRes->nFanins, pCutRes->nFanins+1, uPhase, 1 ); // compute the phases uPhase = Cnf_TruthPhase( pCutRes, pCut ) | (1 << pCutRes->nFanins); uPhaseFan = Cnf_TruthPhase( pCutRes, pCutFan ); // permute truth-tables to the common support Kit_TruthStretch( pTemp, pTop, pCut->nFanins+1, pCutRes->nFanins+1, uPhase, 1 ); Kit_TruthStretch( pTemp, pFan, pCutFan->nFanins, pCutRes->nFanins, uPhaseFan, 1 ); // perform Boolean operation Kit_TruthMux( pTruthRes, pTop, pTop+pCutRes->nWords, pFan, pCutRes->nFanins ); // return the cut to its original condition Cnf_CutInsertIthVar( pCut, iVar, iFan ); // consider the simple case if ( pCutRes->nFanins < 5 ) { pCutRes->Cost = p->pSopSizes[0xFFFF & *pTruthRes] + p->pSopSizes[0xFFFF & ~*pTruthRes]; return pCutRes; } // derive ISOP for positive phase RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 ); pCutRes->vIsop[1] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory ); // derive ISOP for negative phase Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins ); RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 ); pCutRes->vIsop[0] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory ); Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins ); // compute the cut cost if ( pCutRes->vIsop[0] == NULL || pCutRes->vIsop[1] == NULL ) pCutRes->Cost = 127; else if ( Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]) > 127 ) pCutRes->Cost = 127; else pCutRes->Cost = Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]); return pCutRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// ////////////////////////////////////////////////////////////////////////