/**CFile**************************************************************** FileName [abcDressw.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Transfers names from one netlist to the other.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcDressw.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "aig/aig/aig.h" #include "proof/dch/dch.h" ABC_NAMESPACE_IMPL_START /* Procedure Abc_NtkDressComputeEquivs() implemented in this file computes equivalence classes of objects of the two networks (pNtk1 and pNtk2). It is possible that pNtk1 is the network before synthesis and pNtk2 is the network after synthesis. The equiv classes of nodes from these networks can be used to transfer the names from pNtk1 to pNtk2, or vice versa. The above procedure returns the array (Vec_Ptr_t) of integer arrays (Vec_Int_t). Each of the integer arrays contains entries of one equivalence class. Each entry (EquivId) contains the following information: (1) object ID, which is a number 'num', such that 0 <= 'num' < MaxId where MaxId is the largest ID of nodes in a network (2) the polarity of the node, which is a binary number, 0 or 1, giving the node's value when pattern (000...0) is applied to the inputs (3) the number of the network, 0 or 1, which stands for pNtk1 and pNtk2, respectively The first array in the array of arrays is empty, or contains nodes that are equivalent to a constant (if such nodes appear in the network). Given EquivID defined above, use the APIs below to get its components. */ // declarations to be added to the application code extern int Abc_ObjEquivId2ObjId( int EquivId ); extern int Abc_ObjEquivId2Polar( int EquivId ); extern int Abc_ObjEquivId2NtkId( int EquivId ); // definition that may remain in this file int Abc_ObjEquivId2ObjId( int EquivId ) { return EquivId >> 2; } int Abc_ObjEquivId2Polar( int EquivId ) { return (EquivId >> 1) & 1; } int Abc_ObjEquivId2NtkId( int EquivId ) { return EquivId & 1; } //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); extern void Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates the dual-output miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManCreateDualOutputMiter( Aig_Man_t * p1, Aig_Man_t * p2 ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; assert( Aig_ManCiNum(p1) == Aig_ManCiNum(p2) ); assert( Aig_ManCoNum(p1) == Aig_ManCoNum(p2) ); pNew = Aig_ManStart( Aig_ManObjNumMax(p1) + Aig_ManObjNumMax(p2) ); // add first AIG Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p1, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); Aig_ManForEachNode( p1, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // add second AIG Aig_ManConst1(p2)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p2, pObj, i ) pObj->pData = Aig_ManCi( pNew, i ); Aig_ManForEachNode( p2, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // add the outputs for ( i = 0; i < Aig_ManCoNum(p1); i++ ) { Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1, i)) ); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(Aig_ManCo(p2, i)) ); } Aig_ManCleanup( pNew ); return pNew; } /**Function************************************************************* Synopsis [Sets polarity attribute of each object in the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDressMapSetPolarity( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pAnd; int i; // each node refers to the the strash copy whose polarity is set Abc_NtkForEachObj( pNtk, pObj, i ) { if ( (pAnd = Abc_ObjRegular(pObj->pCopy)) && Abc_ObjType(pAnd) != ABC_OBJ_NONE ) // strashed object is present and legal pObj->fPhase = pAnd->fPhase ^ Abc_ObjIsComplement(pObj->pCopy); } } /**Function************************************************************* Synopsis [Create mapping of node IDs of pNtk into equiv classes of pMiter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkDressMapClasses( Aig_Man_t * pMiter, Abc_Ntk_t * pNtk ) { Vec_Int_t * vId2Lit; Abc_Obj_t * pObj, * pAnd; Aig_Obj_t * pObjMan, * pObjMiter, * pObjRepr; int i; vId2Lit = Vec_IntAlloc( 0 ); Vec_IntFill( vId2Lit, Abc_NtkObjNumMax(pNtk), -1 ); Abc_NtkForEachNode( pNtk, pObj, i ) { // get the pointer to the miter node corresponding to pObj if ( (pAnd = Abc_ObjRegular(pObj->pCopy)) && Abc_ObjType(pAnd) != ABC_OBJ_NONE && // strashed node is present and legal (pObjMan = Aig_Regular((Aig_Obj_t *)pAnd->pCopy)) && Aig_ObjType(pObjMan) != AIG_OBJ_NONE && // AIG node is present and legal (pObjMiter = Aig_Regular((Aig_Obj_t *)pObjMan->pData)) && Aig_ObjType(pObjMiter) != AIG_OBJ_NONE ) // miter node is present and legal { // get the representative of the miter node pObjRepr = Aig_ObjRepr( pMiter, pObjMiter ); pObjRepr = pObjRepr? pObjRepr : pObjMiter; // map pObj (whose ID is i) into the repr node ID (i.e. equiv class) Vec_IntWriteEntry( vId2Lit, i, Aig_ObjId(pObjRepr) ); } } return vId2Lit; } /**Function************************************************************* Synopsis [Returns the vector of given equivalence class of objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_ObjDressClass( Vec_Ptr_t * vRes, Vec_Int_t * vClass2Num, int Class ) { int ClassNumber; assert( Class > 0 ); ClassNumber = Vec_IntEntry( vClass2Num, Class ); assert( ClassNumber != 0 ); if ( ClassNumber > 0 ) return (Vec_Int_t *)Vec_PtrEntry( vRes, ClassNumber ); // previous class // create new class Vec_IntWriteEntry( vClass2Num, Class, Vec_PtrSize(vRes) ); Vec_PtrPush( vRes, Vec_IntAlloc(4) ); return (Vec_Int_t *)Vec_PtrEntryLast( vRes ); } /**Function************************************************************* Synopsis [Returns the ID of a node in an equivalence class.] Description [The ID is composed of three parts: object ID, followed by one bit telling the phase of this node, followed by one bit telling the network to which this node belongs.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjDressMakeId( Abc_Ntk_t * pNtk, int ObjId, int iNtk ) { return (ObjId << 2) | (Abc_NtkObj(pNtk,ObjId)->fPhase << 1) | iNtk; } /**Function************************************************************* Synopsis [Computes equivalence classes of objects in pNtk1 and pNtk2.] Description [Internal procedure.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDressMapIds( Aig_Man_t * pMiter, Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ) { Vec_Ptr_t * vRes; Vec_Int_t * vId2Lit1, * vId2Lit2, * vCounts0, * vCounts1, * vClassC, * vClass2Num; int i, Class; // start the classes vRes = Vec_PtrAlloc( 1000 ); // set polarity of the nodes Abc_NtkDressMapSetPolarity( pNtk1 ); Abc_NtkDressMapSetPolarity( pNtk2 ); // create mapping of node IDs of pNtk1/pNtk2 into the IDs of equiv classes of pMiter vId2Lit1 = Abc_NtkDressMapClasses( pMiter, pNtk1 ); vId2Lit2 = Abc_NtkDressMapClasses( pMiter, pNtk2 ); // count the number of nodes in each equivalence class vCounts0 = Vec_IntStart( Aig_ManObjNumMax(pMiter) ); Vec_IntForEachEntry( vId2Lit1, Class, i ) if ( Class >= 0 ) Vec_IntAddToEntry( vCounts0, Class, 1 ); vCounts1 = Vec_IntStart( Aig_ManObjNumMax(pMiter) ); Vec_IntForEachEntry( vId2Lit2, Class, i ) if ( Class >= 0 ) Vec_IntAddToEntry( vCounts1, Class, 1 ); // get the costant class vClassC = Vec_IntAlloc( 100 ); Vec_IntForEachEntry( vId2Lit1, Class, i ) if ( Class == 0 ) Vec_IntPush( vClassC, Abc_ObjDressMakeId(pNtk1, i, 0) ); Vec_IntForEachEntry( vId2Lit2, Class, i ) if ( Class == 0 ) Vec_IntPush( vClassC, Abc_ObjDressMakeId(pNtk2, i, 1) ); Vec_PtrPush( vRes, vClassC ); // map repr node IDs into class numbers vClass2Num = Vec_IntAlloc( 0 ); Vec_IntFill( vClass2Num, Aig_ManObjNumMax(pMiter), -1 ); // keep classes having at least one element from pNtk1 and one from pNtk2 Vec_IntForEachEntry( vId2Lit1, Class, i ) if ( Class > 0 && Vec_IntEntry(vCounts0, Class) && Vec_IntEntry(vCounts1, Class) ) Vec_IntPush( Abc_ObjDressClass(vRes, vClass2Num, Class), Abc_ObjDressMakeId(pNtk1, i, 0) ); Vec_IntForEachEntry( vId2Lit2, Class, i ) if ( Class > 0 && Vec_IntEntry(vCounts0, Class) && Vec_IntEntry(vCounts1, Class) ) Vec_IntPush( Abc_ObjDressClass(vRes, vClass2Num, Class), Abc_ObjDressMakeId(pNtk2, i, 1) ); // package them accordingly Vec_IntFree( vClass2Num ); Vec_IntFree( vCounts0 ); Vec_IntFree( vCounts1 ); Vec_IntFree( vId2Lit1 ); Vec_IntFree( vId2Lit2 ); return vRes; } /**Function************************************************************* Synopsis [Computes equivalence classes of objects in pNtk1 and pNtk2.] Description [Returns the array (Vec_Ptr_t) of integer arrays (Vec_Int_t). Each of the integer arrays contains entries of one equivalence class. Each entry contains the following information: the network number (0/1), the polarity (0/1) and the object ID in the the network (0 <= num < MaxId) where MaxId is the largest number of an ID of an object in that network.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDressComputeEquivs( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConflictLimit, int fVerbose ) { Dch_Pars_t Pars, * pPars = &Pars; Abc_Ntk_t * pAig1, * pAig2; Aig_Man_t * pMan1, * pMan2, * pMiter; Vec_Ptr_t * vRes; assert( !Abc_NtkIsStrash(pNtk1) ); assert( !Abc_NtkIsStrash(pNtk2) ); // convert network into AIG pAig1 = Abc_NtkStrash( pNtk1, 1, 1, 0 ); pAig2 = Abc_NtkStrash( pNtk2, 1, 1, 0 ); pMan1 = Abc_NtkToDar( pAig1, 0, 0 ); pMan2 = Abc_NtkToDar( pAig2, 0, 0 ); // derive the miter pMiter = Aig_ManCreateDualOutputMiter( pMan1, pMan2 ); // set up parameters for SAT sweeping Dch_ManSetDefaultParams( pPars ); pPars->nBTLimit = nConflictLimit; pPars->fVerbose = fVerbose; // perform SAT sweeping Dch_ComputeEquivalences( pMiter, pPars ); // now, pMiter is annotated with the equivl class info // convert this info into the resulting array vRes = Abc_NtkDressMapIds( pMiter, pNtk1, pNtk2 ); Aig_ManStop( pMiter ); Aig_ManStop( pMan1 ); Aig_ManStop( pMan2 ); Abc_NtkDelete( pAig1 ); Abc_NtkDelete( pAig2 ); return vRes; } /**Function************************************************************* Synopsis [Prints information about node equivalences.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDressPrintEquivs( Vec_Ptr_t * vRes ) { Vec_Int_t * vClass; int i, k, Entry; Vec_PtrForEachEntry( Vec_Int_t *, vRes, vClass, i ) { printf( "Class %5d : ", i ); printf( "Num =%5d ", Vec_IntSize(vClass) ); Vec_IntForEachEntry( vClass, Entry, k ) printf( "%5d%c%d ", Abc_ObjEquivId2ObjId(Entry), Abc_ObjEquivId2Polar(Entry)? '-':'+', Abc_ObjEquivId2NtkId(Entry) ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Prints information about node equivalences.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDressPrintStats( Vec_Ptr_t * vRes, int nNodes0, int nNodes1, abctime Time ) { Vec_Int_t * vClass; int i, k, Entry; int NegAll[2] = {0}, PosAll[2] = {0}, PairsAll = 0, PairsOne = 0; int Pos[2], Neg[2]; // count the number of equivalences in each class Vec_PtrForEachEntry( Vec_Int_t *, vRes, vClass, i ) { Pos[0] = Pos[1] = 0; Neg[0] = Neg[1] = 0; Vec_IntForEachEntry( vClass, Entry, k ) { if ( Abc_ObjEquivId2NtkId(Entry) ) { if ( Abc_ObjEquivId2Polar(Entry) ) Neg[1]++; // negative polarity in network 1 else Pos[1]++; // positive polarity in network 1 } else { if ( Abc_ObjEquivId2Polar(Entry) ) Neg[0]++; // negative polarity in network 0 else Pos[0]++; // positive polarity in network 0 } } PosAll[0] += Pos[0]; // total positive polarity in network 0 PosAll[1] += Pos[1]; // total positive polarity in network 1 NegAll[0] += Neg[0]; // total negative polarity in network 0 NegAll[1] += Neg[1]; // total negative polarity in network 1 // assuming that the name can be transferred to only one node PairsAll += Abc_MinInt(Neg[0] + Pos[0], Neg[1] + Pos[1]); PairsOne += Abc_MinInt(Neg[0], Neg[1]) + Abc_MinInt(Pos[0], Pos[1]); } printf( "Total number of equiv classes = %7d.\n", Vec_PtrSize(vRes) ); printf( "Participating nodes from both networks = %7d.\n", NegAll[0]+PosAll[0]+NegAll[1]+PosAll[1] ); printf( "Participating nodes from the first network = %7d. (%7.2f %% of nodes)\n", NegAll[0]+PosAll[0], 100.0*(NegAll[0]+PosAll[0])/(nNodes0+1) ); printf( "Participating nodes from the second network = %7d. (%7.2f %% of nodes)\n", NegAll[1]+PosAll[1], 100.0*(NegAll[1]+PosAll[1])/(nNodes1+1) ); printf( "Node pairs (any polarity) = %7d. (%7.2f %% of names can be moved)\n", PairsAll, 100.0*PairsAll/(nNodes0+1) ); printf( "Node pairs (same polarity) = %7d. (%7.2f %% of names can be moved)\n", PairsOne, 100.0*PairsOne/(nNodes0+1) ); ABC_PRT( "Total runtime", Time ); } /**Function************************************************************* Synopsis [Transfers names from pNtk1 to pNtk2.] Description [Internally calls new procedure for mapping node IDs of both networks into the shared equivalence classes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDress2( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConflictLimit, int fVerbose ) { Vec_Ptr_t * vRes; abctime clk = Abc_Clock(); vRes = Abc_NtkDressComputeEquivs( pNtk1, pNtk2, nConflictLimit, fVerbose ); // Abc_NtkDressPrintEquivs( vRes ); Abc_NtkDressPrintStats( vRes, Abc_NtkNodeNum(pNtk1), Abc_NtkNodeNum(pNtk1), Abc_Clock() - clk ); Vec_VecFree( (Vec_Vec_t *)vRes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END