abcDress2.c 16.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/**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 $]

***********************************************************************/

21 22 23
#include "base/abc/abc.h"
#include "aig/aig/aig.h"
#include "proof/dch/dch.h"
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72

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*************************************************************

73
  Synopsis    [Creates the dual-output miter.]
74 75 76 77 78 79 80 81 82 83 84 85 86

  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;
87 88
    assert( Aig_ManCiNum(p1) == Aig_ManCiNum(p2) );
    assert( Aig_ManCoNum(p1) == Aig_ManCoNum(p2) );
89 90 91
    pNew = Aig_ManStart( Aig_ManObjNumMax(p1) + Aig_ManObjNumMax(p2) );
    // add first AIG
    Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew);
92 93
    Aig_ManForEachCi( p1, pObj, i )
        pObj->pData = Aig_ObjCreateCi( pNew );
94 95 96 97
    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);
98
    Aig_ManForEachCi( p2, pObj, i )
99
        pObj->pData = Aig_ManCi( pNew, i );
100 101 102
    Aig_ManForEachNode( p2, pObj, i )
        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
    // add the outputs
103
    for ( i = 0; i < Aig_ManCoNum(p1); i++ )
104
    {
105 106
        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1, i)) );
        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(Aig_ManCo(p2, i)) );
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
    }
    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     []

***********************************************************************/
361
void Abc_NtkDressPrintStats( Vec_Ptr_t * vRes, int nNodes0, int nNodes1, abctime Time )
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
{
    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
395 396
        PairsAll += Abc_MinInt(Neg[0] + Pos[0], Neg[1] + Pos[1]);
        PairsOne += Abc_MinInt(Neg[0], Neg[1]) + Abc_MinInt(Pos[0], Pos[1]);
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
    }
    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;
422
    abctime clk = Abc_Clock();
423 424
    vRes = Abc_NtkDressComputeEquivs( pNtk1, pNtk2, nConflictLimit, fVerbose );
//    Abc_NtkDressPrintEquivs( vRes );
425
    Abc_NtkDressPrintStats( vRes, Abc_NtkNodeNum(pNtk1), Abc_NtkNodeNum(pNtk1), Abc_Clock() - clk );
426 427 428 429 430 431 432 433 434 435
    Vec_VecFree( (Vec_Vec_t *)vRes );
}

////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END