/**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 [cnfMap.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: cnfMap.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cnf.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes area flow of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cnf_CutAssignAreaFlow( Cnf_Man_t * p, Dar_Cut_t * pCut, int * pAreaFlows ) { Aig_Obj_t * pLeaf; int i; pCut->Value = 0; pCut->uSign = 100 * Cnf_CutSopCost( p, pCut ); Dar_CutForEachLeaf( p->pManAig, pCut, pLeaf, i ) { pCut->Value += pLeaf->nRefs; if ( !Aig_ObjIsNode(pLeaf) ) continue; assert( pLeaf->nRefs > 0 ); pCut->uSign += pAreaFlows[pLeaf->Id] / (pLeaf->nRefs? pLeaf->nRefs : 1); } } /**Function************************************************************* Synopsis [Computes area flow of the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cnf_CutSuperAreaFlow( Vec_Ptr_t * vSuper, int * pAreaFlows ) { Aig_Obj_t * pLeaf; int i, nAreaFlow; nAreaFlow = 100 * (Vec_PtrSize(vSuper) + 1); Vec_PtrForEachEntry( vSuper, pLeaf, i ) { pLeaf = Aig_Regular(pLeaf); if ( !Aig_ObjIsNode(pLeaf) ) continue; assert( pLeaf->nRefs > 0 ); nAreaFlow += pAreaFlows[pLeaf->Id] / (pLeaf->nRefs? pLeaf->nRefs : 1); } return nAreaFlow; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cnf_DeriveMapping( Cnf_Man_t * p ) { Vec_Ptr_t * vSuper; Aig_Obj_t * pObj; Dar_Cut_t * pCut, * pCutBest; int i, k, AreaFlow, * pAreaFlows; // allocate area flows pAreaFlows = ALLOC( int, Aig_ManObjNumMax(p->pManAig) ); memset( pAreaFlows, 0, sizeof(int) * Aig_ManObjNumMax(p->pManAig) ); // visit the nodes in the topological order and update their best cuts vSuper = Vec_PtrAlloc( 100 ); Aig_ManForEachNode( p->pManAig, pObj, i ) { // go through the cuts pCutBest = NULL; Dar_ObjForEachCut( pObj, pCut, k ) { pCut->fBest = 0; if ( k == 0 ) continue; Cnf_CutAssignAreaFlow( p, pCut, pAreaFlows ); if ( pCutBest == NULL || pCutBest->uSign > pCut->uSign || (pCutBest->uSign == pCut->uSign && pCutBest->Value < pCut->Value) ) pCutBest = pCut; } // check the big cut // Aig_ObjCollectSuper( pObj, vSuper ); // get the area flow of this cut // AreaFlow = Cnf_CutSuperAreaFlow( vSuper, pAreaFlows ); // Trevor: Always set the best one with fBest. // otherwise CNF generation fails. Wrote to Alan // seeking confirmation this was not dangerous. AreaFlow = AIG_INFINITY; if (1 || AreaFlow >= (int)pCutBest->uSign ) { pAreaFlows[pObj->Id] = pCutBest->uSign; pCutBest->fBest = 1; } else { pAreaFlows[pObj->Id] = AreaFlow; pObj->fMarkB = 1; // mark the special node } } Vec_PtrFree( vSuper ); free( pAreaFlows ); /* // compute the area of mapping AreaFlow = 0; Aig_ManForEachPo( p->pManAig, pObj, i ) AreaFlow += Dar_ObjBestCut(Aig_ObjFanin0(pObj))->uSign / 100 / Aig_ObjFanin0(pObj)->nRefs; printf( "Area of the network = %d.\n", AreaFlow ); */ } #if 0 /**Function************************************************************* Synopsis [Computes area of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_CutDeref( Aig_Man_t * p, Dar_Cut_t * pCut ) { Aig_Obj_t * pLeaf; int i; Dar_CutForEachLeaf( p, pCut, pLeaf, i ) { assert( pLeaf->nRefs > 0 ); if ( --pLeaf->nRefs > 0 || !Aig_ObjIsAnd(pLeaf) ) continue; Aig_CutDeref( p, Aig_ObjBestCut(pLeaf) ); } } /**Function************************************************************* Synopsis [Computes area of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_CutRef( Aig_Man_t * p, Dar_Cut_t * pCut ) { Aig_Obj_t * pLeaf; int i, Area = pCut->Value; Dar_CutForEachLeaf( p, pCut, pLeaf, i ) { assert( pLeaf->nRefs >= 0 ); if ( pLeaf->nRefs++ > 0 || !Aig_ObjIsAnd(pLeaf) ) continue; Area += Aig_CutRef( p, Aig_ObjBestCut(pLeaf) ); } return Area; } /**Function************************************************************* Synopsis [Computes exact area of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cnf_CutArea( Aig_Man_t * p, Dar_Cut_t * pCut ) { int Area; Area = Aig_CutRef( p, pCut ); Aig_CutDeref( p, pCut ); return Area; } /**Function************************************************************* Synopsis [Returns 1 if the second cut is better.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cnf_CutCompare( Dar_Cut_t * pC0, Dar_Cut_t * pC1 ) { if ( pC0->Area < pC1->Area - 0.0001 ) return -1; if ( pC0->Area > pC1->Area + 0.0001 ) // smaller area flow is better return 1; // if ( pC0->NoRefs < pC1->NoRefs ) // return -1; // if ( pC0->NoRefs > pC1->NoRefs ) // fewer non-referenced fanins is better // return 1; // if ( pC0->FanRefs / pC0->nLeaves > pC1->FanRefs / pC1->nLeaves ) // return -1; // if ( pC0->FanRefs / pC0->nLeaves < pC1->FanRefs / pC1->nLeaves ) // return 1; // larger average fanin ref-counter is better // return 0; return 1; } /**Function************************************************************* Synopsis [Returns the cut with the smallest area flow.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dar_Cut_t * Cnf_ObjFindBestCut( Aig_Obj_t * pObj ) { Dar_Cut_t * pCut, * pCutBest; int i; pCutBest = NULL; Dar_ObjForEachCut( pObj, pCut, i ) if ( pCutBest == NULL || Cnf_CutCompare(pCutBest, pCut) == 1 ) pCutBest = pCut; return pCutBest; } /**Function************************************************************* Synopsis [Computes area flow of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cnf_CutAssignArea( Cnf_Man_t * p, Dar_Cut_t * pCut ) { Aig_Obj_t * pLeaf; int i; pCut->Area = (float)pCut->Cost; pCut->NoRefs = 0; pCut->FanRefs = 0; Dar_CutForEachLeaf( p->pManAig, pCut, pLeaf, i ) { if ( !Aig_ObjIsNode(pLeaf) ) continue; if ( pLeaf->nRefs == 0 ) { pCut->Area += Aig_ObjBestCut(pLeaf)->Cost; pCut->NoRefs++; } else { if ( pCut->FanRefs + pLeaf->nRefs > 15 ) pCut->FanRefs = 15; else pCut->FanRefs += pLeaf->nRefs; } } } /**Function************************************************************* Synopsis [Performs one round of "area recovery" using exact local area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cnf_ManMapForCnf( Cnf_Man_t * p ) { Aig_Obj_t * pObj; Dar_Cut_t * pCut, * pCutBest; int i, k; // visit the nodes in the topological order and update their best cuts Aig_ManForEachNode( p->pManAig, pObj, i ) { // find the old best cut pCutBest = Aig_ObjBestCut(pObj); Dar_ObjClearBestCut(pCutBest); // if the node is used, dereference its cut if ( pObj->nRefs ) Aig_CutDeref( p->pManAig, pCutBest ); // evaluate the cuts of this node Dar_ObjForEachCut( pObj, pCut, k ) // Cnf_CutAssignAreaFlow( p, pCut ); pCut->Area = (float)Cnf_CutArea( p->pManAig, pCut ); // find the new best cut pCutBest = Cnf_ObjFindBestCut(pObj); Dar_ObjSetBestCut( pCutBest ); // if the node is used, reference its cut if ( pObj->nRefs ) Aig_CutRef( p->pManAig, pCutBest ); } return 1; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// ////////////////////////////////////////////////////////////////////////