/**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_ManPiNum(p1) == Aig_ManPiNum(p2) ); assert( Aig_ManPoNum(p1) == Aig_ManPoNum(p2) ); pNew = Aig_ManStart( Aig_ManObjNumMax(p1) + Aig_ManObjNumMax(p2) ); // add first AIG Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew); Aig_ManForEachPi( p1, pObj, i ) pObj->pData = Aig_ObjCreatePi( 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_ManForEachPi( p2, pObj, i ) pObj->pData = Aig_ManPi( 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_ManPoNum(p1); i++ ) { Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(Aig_ManPo(p1, i)) ); Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(Aig_ManPo(p2, i)) ); } Aig_ManCleanup( pNew ); return pNew; }
/**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; }
static inline int Saig_ManGetMap2( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, int * pf2 ) { Vec_Int_t * vMap = (Vec_Int_t *)p->pData2; int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id; *pf2 = Vec_IntEntry( vMap, 2*nOffset + 1 ); return Vec_IntEntry( vMap, 2*nOffset ); }
/**Function************************************************************* Synopsis [Performs ternary simulation of one frame.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Saig_ManBmcTerSimOne( Aig_Man_t * p, unsigned * pPrev ) { Aig_Obj_t * pObj, * pObjLi; unsigned * pInfo; int i, Val0, Val1; pInfo = ABC_CALLOC( unsigned, Aig_BitWordNum(2 * Aig_ManObjNumMax(p)) ); Saig_ManBmcSimInfoSet( pInfo, Aig_ManConst1(p), SAIG_TER_ONE ); Saig_ManForEachPi( p, pObj, i ) Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_UND ); if ( pPrev == NULL ) { Saig_ManForEachLo( p, pObj, i ) Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_ZER ); } else { Saig_ManForEachLiLo( p, pObjLi, pObj, i ) Saig_ManBmcSimInfoSet( pInfo, pObj, Saig_ManBmcSimInfoGet(pPrev, pObjLi) ); } Aig_ManForEachNode( p, pObj, i ) { Val0 = Saig_ManBmcSimInfoGet( pInfo, Aig_ObjFanin0(pObj) ); Val1 = Saig_ManBmcSimInfoGet( pInfo, Aig_ObjFanin1(pObj) ); if ( Aig_ObjFaninC0(pObj) ) Val0 = Saig_ManBmcSimInfoNot( Val0 ); if ( Aig_ObjFaninC1(pObj) ) Val1 = Saig_ManBmcSimInfoNot( Val1 ); Saig_ManBmcSimInfoSet( pInfo, pObj, Saig_ManBmcSimInfoAnd(Val0, Val1) ); }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [Orders nodes as follows: PIs, ANDs, POs.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupSimple( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew; int i; assert( p->pManTime == NULL ); assert( p->pManHaig == NULL || Aig_ManBufNum(p) == 0 ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Aig_UtilStrsav( p->pName ); pNew->pSpec = Aig_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; <<<<<<< HEAD
/**Function************************************************************* Synopsis [Creates fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Saig_SimObj_t * Saig_ManCreateMan( Aig_Man_t * p ) { Saig_SimObj_t * pAig, * pEntry; Aig_Obj_t * pObj; int i; pAig = ABC_CALLOC( Saig_SimObj_t, Aig_ManObjNumMax(p)+1 ); // printf( "Allocating %7.2f Mb.\n", 1.0 * sizeof(Saig_SimObj_t) * (Aig_ManObjNumMax(p)+1)/(1<<20) ); Aig_ManForEachObj( p, pObj, i ) { pEntry = pAig + i; pEntry->Type = pObj->Type; if ( Aig_ObjIsPi(pObj) || i == 0 ) { if ( Saig_ObjIsLo(p, pObj) ) { pEntry->iFan0 = (Saig_ObjLoToLi(p, pObj)->Id << 1); pEntry->iFan1 = -1; } continue; } pEntry->iFan0 = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj); if ( Aig_ObjIsPo(pObj) ) continue; assert( Aig_ObjIsNode(pObj) ); pEntry->iFan1 = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj); }
/**Function************************************************************* Synopsis [Returns the probability of POs being 1 under rand seq sim.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManProfileConstraints( Aig_Man_t * p, int nWords, int nFrames, int fVerbose ) { Vec_Ptr_t * vInfo; Vec_Int_t * vProbs, * vProbs2; Aig_Obj_t * pObj, * pObjLi; unsigned * pInfo, * pInfo0, * pInfo1, * pInfoMask, * pInfoMask2; int i, w, f, RetValue = 1, clk = clock(); if ( fVerbose ) printf( "Simulating %d nodes and %d flops for %d frames with %d words... ", Aig_ManNodeNum(p), Aig_ManRegNum(p), nFrames, nWords ); Aig_ManRandom( 1 ); vInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p)+2, nWords ); Vec_PtrCleanSimInfo( vInfo, 0, nWords ); vProbs = Vec_IntStart( Saig_ManPoNum(p) ); vProbs2 = Vec_IntStart( Saig_ManPoNum(p) ); // start the constant pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(Aig_ManConst1(p)) ); for ( w = 0; w < nWords; w++ ) pInfo[w] = ~0; // start the flop inputs Saig_ManForEachLi( p, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); for ( w = 0; w < nWords; w++ ) pInfo[w] = 0; }
/**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDup( Aig_Man_t * p, int fOrdered ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Aig_UtilStrsav( p->pName ); pNew->nRegs = p->nRegs; pNew->nAsserts = p->nAsserts; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachPi( p, pObj, i ) pObj->pData = Aig_ObjCreatePi(pNew); // duplicate internal nodes if ( fOrdered ) { Aig_ManForEachObj( p, pObj, i ) if ( Aig_ObjIsBuf(pObj) ) pObj->pData = Aig_ObjChild0Copy(pObj); else if ( Aig_ObjIsNode(pObj) ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } else {
static inline void Saig_ManSetMap1( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, Aig_Obj_t * pNew ) { Vec_Int_t * vMap = (Vec_Int_t *)p->pData; int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id; assert( !Aig_IsComplement(pOld) ); assert( !Aig_IsComplement(pNew) ); Vec_IntWriteEntry( vMap, nOffset, pNew->Id ); }
/**Function************************************************************* Synopsis [Maps a node/frame into a node/frame of a different manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Saig_ManStartMap2( Aig_Man_t * p, int nFrames ) { Vec_Int_t * vMap; int i; assert( p->pData2 == NULL ); vMap = Vec_IntAlloc( Aig_ManObjNumMax(p) * nFrames * 2 ); for ( i = 0; i < vMap->nCap; i++ ) vMap->pArray[i] = -1; vMap->nSize = vMap->nCap; p->pData2 = vMap; }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates initialized timeframes for temporal decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManTemporFrames( Aig_Man_t * pAig, int nFrames ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f; // start the frames package Aig_ManCleanData( pAig ); pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); pFrames->pName = Aig_UtilStrsav( pAig->pName ); // initiliaze the flops Saig_ManForEachLo( pAig, pObj, i ) pObj->pData = Aig_ManConst0(pFrames); // for each timeframe for ( f = 0; f < nFrames; f++ ) { Aig_ManConst1(pAig)->pData = Aig_ManConst1(pFrames); Saig_ManForEachPi( pAig, pObj, i ) pObj->pData = Aig_ObjCreatePi(pFrames); Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); Aig_ManForEachPo( pAig, pObj, i ) pObj->pData = Aig_ObjChild0Copy(pObj); Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) pObjLo->pData = pObjLi->pData; } // create POs for the flop inputs Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreatePo( pFrames, (Aig_Obj_t *)pObj->pData ); Aig_ManCleanup( pFrames ); return pFrames; }
/**Function************************************************************* Synopsis [Duplicate the AIG w/o POs and transforms to transit into init state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Inter_ManStartOneOutput( Aig_Man_t * p, int fAddFirstPo ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjLi, * pObjLo; Aig_Obj_t * pCtrl = NULL; // Suppress "might be used uninitialized" int i; assert( Aig_ManRegNum(p) > 0 ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) { if ( i == Saig_ManPiNum(p) ) pCtrl = Aig_ObjCreateCi( pNew ); pObj->pData = Aig_ObjCreateCi( pNew ); } // set registers pNew->nRegs = fAddFirstPo? 0 : p->nRegs; pNew->nTruePis = fAddFirstPo? Aig_ManCiNum(p) + 1 : p->nTruePis + 1; pNew->nTruePos = fAddFirstPo + Saig_ManConstrNum(p); // duplicate internal nodes Aig_ManForEachNode( p, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create constraint outputs Saig_ManForEachPo( p, pObj, i ) { if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) ) continue; Aig_ObjCreateCo( pNew, Aig_Not( Aig_ObjChild0Copy(pObj) ) ); } // add the PO if ( fAddFirstPo ) { pObj = Aig_ManCo( p, 0 ); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } else { // create register inputs with MUXes Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) { pObj = Aig_Mux( pNew, pCtrl, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); // pObj = Aig_Mux( pNew, pCtrl, Aig_ManConst0(pNew), Aig_ObjChild0Copy(pObjLi) ); Aig_ObjCreateCo( pNew, pObj ); } }
/**Function************************************************************* Synopsis [Partitioning using levelized order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Aig_ManPartitionLevelized( Aig_Man_t * p, int nPartSize ) { Vec_Int_t * vId2Part; Vec_Vec_t * vNodes; Aig_Obj_t * pObj; int i, k, Counter = 0; vNodes = Aig_ManLevelize( p ); vId2Part = Vec_IntStart( Aig_ManObjNumMax(p) ); Vec_VecForEachEntryReverseReverse( Aig_Obj_t *, vNodes, pObj, i, k ) Vec_IntWriteEntry( vId2Part, Aig_ObjId(pObj), Counter++/nPartSize ); Vec_VecFree( vNodes ); return vId2Part; }
/**Function************************************************************* Synopsis [Returns the array of constraint candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManComputeIndCase( Aig_Man_t * p, DdManager * dd, Vec_Int_t * vNodes ) { Vec_Ptr_t * vBdds; Aig_Obj_t * pObj; DdNode * bFunc; int i, Entry; vBdds = Vec_PtrStart( Aig_ManObjNumMax(p) ); bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Aig_ObjId(Aig_ManConst1(p)), bFunc ); Saig_ManForEachPi( p, pObj, i ) { bFunc = Cudd_bddIthVar( dd, Aig_ManPiNum(p) + i ); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); }
/**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Aig_UtilStrsav( p->pName ); // create the PIs Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachPi( p, pObj, i ) pObj->pData = Aig_ObjCreatePi(pNew); return pNew; }
/**Function************************************************************* Synopsis [Starts representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dch_Cla_t * Dch_ClassesStart( Aig_Man_t * pAig ) { Dch_Cla_t * p; p = ABC_ALLOC( Dch_Cla_t, 1 ); memset( p, 0, sizeof(Dch_Cla_t) ); p->pAig = pAig; p->pId2Class = ABC_CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) ); p->pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); p->vClassOld = Vec_PtrAlloc( 100 ); p->vClassNew = Vec_PtrAlloc( 100 ); assert( pAig->pReprs == NULL ); Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); return p; }
/**Function************************************************************* Synopsis [Partitioning using DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Aig_ManPartitionDfs( Aig_Man_t * p, int nPartSize, int fPreorder ) { Vec_Int_t * vId2Part; Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i, Counter = 0; vId2Part = Vec_IntStart( Aig_ManObjNumMax(p) ); if ( fPreorder ) { vNodes = Aig_ManDfsPreorder( p, 1 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) Vec_IntWriteEntry( vId2Part, Aig_ObjId(pObj), Counter++/nPartSize ); } else {
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManDumpBlif( Aig_Man_t * p, char * pFileName ) { FILE * pFile; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i; if ( Aig_ManPoNum(p) == 0 ) { printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" ); return; } Aig_ManSetPioNumbers( p ); // write input file pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Saig_ManDumpBlif(): Cannot open file for writing.\n" ); return; } fprintf( pFile, "# BLIF file written by procedure Saig_ManDumpBlif()\n" ); fprintf( pFile, "# If unedited, this file can be read by Saig_ManReadBlif()\n" ); fprintf( pFile, "# AIG stats: pi=%d po=%d reg=%d and=%d obj=%d maxid=%d\n", Saig_ManPiNum(p), Saig_ManPoNum(p), Saig_ManRegNum(p), Aig_ManNodeNum(p), Aig_ManObjNum(p), Aig_ManObjNumMax(p) ); fprintf( pFile, ".model %s\n", p->pName ); // write primary inputs fprintf( pFile, ".inputs" ); Aig_ManForEachPiSeq( p, pObj, i ) fprintf( pFile, " %s", Saig_ObjName(p, pObj) ); fprintf( pFile, "\n" ); // write primary outputs fprintf( pFile, ".outputs" ); Aig_ManForEachPoSeq( p, pObj, i ) fprintf( pFile, " %s", Saig_ObjName(p, pObj) ); fprintf( pFile, "\n" ); // write registers if ( Aig_ManRegNum(p) ) { Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) { fprintf( pFile, ".latch" ); fprintf( pFile, " %s", Saig_ObjName(p, pObjLi) ); fprintf( pFile, " %s", Saig_ObjName(p, pObjLo) ); fprintf( pFile, " 0\n" ); } }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // driver issue:arises when creating // - driver ref-counter array // - Ns2Glo maps // - final partition // - change-phase cube // LI variable is used when // - driver drives more than one LI // - driver is a PI // - driver is a constant //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the array of times each flop driver is referenced.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p ) { Vec_Int_t * vCounts; Aig_Obj_t * pObj; int i; vCounts = Vec_IntStart( Aig_ManObjNumMax(p) ); Saig_ManForEachLi( p, pObj, i ) Vec_IntAddToEntry( vCounts, Aig_ObjFaninId0(pObj), 1 ); return vCounts; }
Aig_Man_t * Saig_ManCreateIndMiter2( Aig_Man_t * pAig, Vec_Vec_t * vCands ) { int nFrames = 3; Vec_Ptr_t * vNodes; Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; Aig_Obj_t ** pObjMap; int i, f, k; // create mapping for the frames nodes pObjMap = ABC_CALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) ); // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); pFrames->pName = Abc_UtilStrsav( pAig->pName ); pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // map constant nodes for ( f = 0; f < nFrames; f++ ) Aig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); // create PI nodes for the frames for ( f = 0; f < nFrames; f++ ) Aig_ManForEachPiSeq( pAig, pObj, i ) Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) ); // set initial state for the latches Aig_ManForEachLoSeq( pAig, pObj, i ) Aig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) ); // add timeframes for ( f = 0; f < nFrames; f++ ) { // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) { pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Aig_ObjChild1Frames(pObjMap,nFrames,pObj,f) ); Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); } // set the latch inputs and copy them into the latch outputs of the next frame Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i ) { pObjNew = Aig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f); if ( f < nFrames - 1 ) Aig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew ); }
ABC_NAMESPACE_IMPL_START /* A similar approach is presented in the his paper: A. Kuehlmann. Dynamic transition relation simplification for bounded property checking. ICCAD'04, pp. 50-57. */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Maps a node/frame into a node of a different manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Saig_ManStartMap1( Aig_Man_t * p, int nFrames ) { Vec_Int_t * vMap; int i; assert( p->pData == NULL ); vMap = Vec_IntAlloc( Aig_ManObjNumMax(p) * nFrames ); for ( i = 0; i < vMap->nCap; i++ ) vMap->pArray[i] = -1; vMap->nSize = vMap->nCap; p->pData = vMap; }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Saig_ObjName( Aig_Man_t * p, Aig_Obj_t * pObj ) { static char Buffer[16]; if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) ) sprintf( Buffer, "n%0*d", Aig_Base10Log(Aig_ManObjNumMax(p)), Aig_ObjId(pObj) ); else if ( Saig_ObjIsPi(p, pObj) ) sprintf( Buffer, "pi%0*d", Aig_Base10Log(Saig_ManPiNum(p)), Aig_ObjPioNum(pObj) ); else if ( Saig_ObjIsPo(p, pObj) ) sprintf( Buffer, "po%0*d", Aig_Base10Log(Saig_ManPoNum(p)), Aig_ObjPioNum(pObj) ); else if ( Saig_ObjIsLo(p, pObj) ) sprintf( Buffer, "lo%0*d", Aig_Base10Log(Saig_ManRegNum(p)), Aig_ObjPioNum(pObj) - Saig_ManPiNum(p) ); else if ( Saig_ObjIsLi(p, pObj) ) sprintf( Buffer, "li%0*d", Aig_Base10Log(Saig_ManRegNum(p)), Aig_ObjPioNum(pObj) - Saig_ManPoNum(p) ); else assert( 0 ); return Buffer; }
/**Function************************************************************* Synopsis [Duplicate the AIG w/o POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Inter_ManStartDuplicated( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; assert( Aig_ManRegNum(p) > 0 ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); // set registers pNew->nTruePis = p->nTruePis; pNew->nTruePos = Saig_ManConstrNum(p); pNew->nRegs = p->nRegs; // duplicate internal nodes Aig_ManForEachNode( p, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create constraint outputs Saig_ManForEachPo( p, pObj, i ) { if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) ) continue; Aig_ObjCreateCo( pNew, Aig_Not( Aig_ObjChild0Copy(pObj) ) ); } // create register inputs with MUXes Saig_ManForEachLi( p, pObj, i ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); Aig_ManCleanup( pNew ); return pNew; }
/**Function************************************************************* Synopsis [For each cut, returns PIs that can be quantified.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManCutMap( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Ptr_t * vSupps ) { int fShowMatrix = 1; Vec_Ptr_t * vMaps, * vOne; Vec_Int_t * vMap, * vPrev, * vNext; Aig_Obj_t * pObj; int * piFirst, * piLast; int i, k, CounterPlus, CounterMinus, Counter; vMaps = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Vec_Ptr_t *, vResult, vOne, i ) { vMap = Vec_IntStart( Aig_ManObjNumMax(p) ); Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k ) { if ( !Saig_ObjIsPi(p, pObj) ) Vec_IntWriteEntry( vMap, pObj->Id, 1 ); // else //printf( "*" ); //printf( "%d ", pObj->Id ); } Vec_PtrPush( vMaps, vMap ); //printf( "\n" ); }
/**Function************************************************************* Synopsis [Load the network into FPGA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Man_t * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf ) { extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); Vec_Int_t * vSwitching = NULL, * vSwitching2 = NULL; float * pSwitching = NULL, * pSwitching2 = NULL; If_Man_t * pIfMan; If_Obj_t * pIfObj; Aig_Obj_t * pNode, * pFanin, * pPrev; int i; abctime clk = Abc_Clock(); // set the number of registers (switch activity will be combinational) Aig_ManSetRegNum( p, 0 ); if ( pPars->fPower ) { vSwitching = Saig_ManComputeSwitchProbs( p, 48, 16, 0 ); if ( pPars->fVerbose ) { ABC_PRT( "Computing switching activity", Abc_Clock() - clk ); } pSwitching = (float *)vSwitching->pArray; vSwitching2 = Vec_IntStart( Aig_ManObjNumMax(p) ); pSwitching2 = (float *)vSwitching2->pArray; } // start the mapping manager and set its parameters pIfMan = If_ManStart( pPars ); pIfMan->vSwitching = vSwitching2; // load the AIG into the mapper Aig_ManForEachObj( p, pNode, i ) { if ( Aig_ObjIsAnd(pNode) ) { pIfObj = If_ManCreateAnd( pIfMan, If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ), If_NotCond( (If_Obj_t *)Aig_ObjFanin1(pNode)->pData, Aig_ObjFaninC1(pNode) ) ); // printf( "no%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); } else if ( Aig_ObjIsCi(pNode) ) { pIfObj = If_ManCreateCi( pIfMan ); If_ObjSetLevel( pIfObj, Aig_ObjLevel(pNode) ); // printf( "pi%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); if ( pIfMan->nLevelMax < (int)pIfObj->Level ) pIfMan->nLevelMax = (int)pIfObj->Level; } else if ( Aig_ObjIsCo(pNode) ) { pIfObj = If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ) ); // printf( "po%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); } else if ( Aig_ObjIsConst1(pNode) ) pIfObj = If_ManConst1( pIfMan ); else // add the node to the mapper assert( 0 ); // save the result assert( Vec_PtrEntry(vAigToIf, i) == NULL ); Vec_PtrWriteEntry( vAigToIf, i, pIfObj ); pNode->pData = pIfObj; if ( vSwitching2 ) pSwitching2[pIfObj->Id] = pSwitching[pNode->Id]; // set up the choice node if ( Aig_ObjIsChoice( p, pNode ) ) { for ( pPrev = pNode, pFanin = Aig_ObjEquiv(p, pNode); pFanin; pPrev = pFanin, pFanin = Aig_ObjEquiv(p, pFanin) ) If_ObjSetChoice( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData ); If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pData ); } // assert( If_ObjLevel(pIfObj) == Aig_ObjLevel(pNode) ); } if ( vSwitching ) Vec_IntFree( vSwitching ); return pIfMan; }
Vec_PtrCleanSimInfo( vInfo, 0, nWords ); vProbs = Vec_IntStart( Saig_ManPoNum(p) ); vProbs2 = Vec_IntStart( Saig_ManPoNum(p) ); // start the constant pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(Aig_ManConst1(p)) ); for ( w = 0; w < nWords; w++ ) pInfo[w] = ~0; // start the flop inputs Saig_ManForEachLi( p, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); for ( w = 0; w < nWords; w++ ) pInfo[w] = 0; } // get the info mask pInfoMask = (unsigned *)Vec_PtrEntry( vInfo, Aig_ManObjNumMax(p) ); // PO failed pInfoMask2 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ManObjNumMax(p)+1 ); // constr failed for ( f = 0; f < nFrames; f++ ) { // assign primary inputs Saig_ManForEachPi( p, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); for ( w = 0; w < nWords; w++ ) pInfo[w] = Aig_ManRandom( 0 ); } // move the flop values Saig_ManForEachLiLo( p, pObjLi, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObjLi) );
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Constructs initialized timeframes with constraints as POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ssw_FramesWithConstraints( Aig_Man_t * p, int nFrames ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f; // assert( Saig_ManConstrNum(p) > 0 ); assert( Aig_ManRegNum(p) > 0 ); assert( Aig_ManRegNum(p) < Aig_ManCiNum(p) ); // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(p) * nFrames ); // create latches for the first frame Saig_ManForEachLo( p, pObj, i ) Aig_ObjSetCopy( pObj, Aig_ManConst0(pFrames) ); // add timeframes for ( f = 0; f < nFrames; f++ ) { // map constants and PIs Aig_ObjSetCopy( Aig_ManConst1(p), Aig_ManConst1(pFrames) ); Saig_ManForEachPi( p, pObj, i ) Aig_ObjSetCopy( pObj, Aig_ObjCreateCi(pFrames) ); // add internal nodes of this frame Aig_ManForEachNode( p, pObj, i ) Aig_ObjSetCopy( pObj, Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ) ); // transfer to the primary output Aig_ManForEachCo( p, pObj, i ) Aig_ObjSetCopy( pObj, Aig_ObjChild0Copy(pObj) ); // create constraint outputs Saig_ManForEachPo( p, pObj, i ) { if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) ) continue; Aig_ObjCreateCo( pFrames, Aig_Not( Aig_ObjCopy(pObj) ) ); } // transfer latch inputs to the latch outputs Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) Aig_ObjSetCopy( pObjLo, Aig_ObjCopy(pObjLi) ); } // remove dangling nodes Aig_ManCleanup( pFrames ); return pFrames; }
/**Function************************************************************* Synopsis [Takes the AIG with the single output to be checked.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cla_Man_t * Fra_ClauStart( Aig_Man_t * pMan ) { Cla_Man_t * p; Cnf_Dat_t * pCnfMain; Cnf_Dat_t * pCnfTest; Cnf_Dat_t * pCnfBmc; Aig_Man_t * pFramesMain; Aig_Man_t * pFramesTest; Aig_Man_t * pFramesBmc; assert( Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) == 1 ); // start the manager p = ABC_ALLOC( Cla_Man_t, 1 ); memset( p, 0, sizeof(Cla_Man_t) ); p->vCexMain0 = Vec_IntAlloc( Aig_ManRegNum(pMan) ); p->vCexMain = Vec_IntAlloc( Aig_ManRegNum(pMan) ); p->vCexTest = Vec_IntAlloc( Aig_ManRegNum(pMan) ); p->vCexBase = Vec_IntAlloc( Aig_ManRegNum(pMan) ); p->vCexAssm = Vec_IntAlloc( Aig_ManRegNum(pMan) ); p->vCexBmc = Vec_IntAlloc( Aig_ManRegNum(pMan) ); // derive two timeframes to be checked pFramesMain = Aig_ManFrames( pMan, 2, 0, 1, 0, 0, NULL ); // nFrames, fInit, fOuts, fRegs //Aig_ManShow( pFramesMain, 0, NULL ); assert( Aig_ManCoNum(pFramesMain) == 2 ); Aig_ObjChild0Flip( Aig_ManCo(pFramesMain, 0) ); // complement the first output pCnfMain = Cnf_DeriveSimple( pFramesMain, 0 ); //Cnf_DataWriteIntoFile( pCnfMain, "temp.cnf", 1 ); p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( pCnfMain, 1, 0 ); /* { int i; Aig_Obj_t * pObj; Aig_ManForEachObj( pFramesMain, pObj, i ) printf( "%d -> %d \n", pObj->Id, pCnfMain->pVarNums[pObj->Id] ); printf( "\n" ); } */ // derive one timeframe to be checked pFramesTest = Aig_ManFrames( pMan, 1, 0, 0, 1, 0, NULL ); assert( Aig_ManCoNum(pFramesTest) == Aig_ManRegNum(pMan) ); pCnfTest = Cnf_DeriveSimple( pFramesTest, Aig_ManRegNum(pMan) ); p->pSatTest = (sat_solver *)Cnf_DataWriteIntoSolver( pCnfTest, 1, 0 ); p->nSatVarsTestBeg = p->nSatVarsTestCur = sat_solver_nvars( p->pSatTest ); // derive one timeframe to be checked for BMC pFramesBmc = Aig_ManFrames( pMan, 1, 1, 0, 1, 0, NULL ); //Aig_ManShow( pFramesBmc, 0, NULL ); assert( Aig_ManCoNum(pFramesBmc) == Aig_ManRegNum(pMan) ); pCnfBmc = Cnf_DeriveSimple( pFramesBmc, Aig_ManRegNum(pMan) ); p->pSatBmc = (sat_solver *)Cnf_DataWriteIntoSolver( pCnfBmc, 1, 0 ); // create variable sets p->vSatVarsMainCs = Fra_ClauSaveInputVars( pFramesMain, pCnfMain, 2 * (Aig_ManCiNum(pMan)-Aig_ManRegNum(pMan)) ); p->vSatVarsTestCs = Fra_ClauSaveLatchVars( pFramesTest, pCnfTest, 1 ); p->vSatVarsTestNs = Fra_ClauSaveLatchVars( pFramesTest, pCnfTest, 0 ); p->vSatVarsBmcNs = Fra_ClauSaveOutputVars( pFramesBmc, pCnfBmc ); assert( Vec_IntSize(p->vSatVarsTestCs) == Vec_IntSize(p->vSatVarsMainCs) ); assert( Vec_IntSize(p->vSatVarsTestCs) == Vec_IntSize(p->vSatVarsBmcNs) ); // create mapping of CS into NS vars p->pMapCsMainToCsTest = Fra_ClauCreateMapping( p->vSatVarsMainCs, p->vSatVarsTestCs, Aig_ManObjNumMax(pFramesMain) ); p->pMapCsTestToCsMain = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsMainCs, Aig_ManObjNumMax(pFramesTest) ); p->pMapCsTestToNsTest = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsTestNs, Aig_ManObjNumMax(pFramesTest) ); p->pMapCsTestToNsBmc = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsBmcNs, Aig_ManObjNumMax(pFramesTest) ); // cleanup Cnf_DataFree( pCnfMain ); Cnf_DataFree( pCnfTest ); Cnf_DataFree( pCnfBmc ); Aig_ManStop( pFramesMain ); Aig_ManStop( pFramesTest ); Aig_ManStop( pFramesBmc ); if ( p->pSatMain == NULL || p->pSatTest == NULL || p->pSatBmc == NULL ) { Fra_ClauStop( p ); return NULL; } return p; }
static inline int Saig_ManGetMap1( Aig_Man_t * p, Aig_Obj_t * pOld, int f1 ) { Vec_Int_t * vMap = (Vec_Int_t *)p->pData; int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id; return Vec_IntEntry( vMap, nOffset ); }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Inserts the given mapping into the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ntl_Man_t * Ntl_ManInsertMapping( Ntl_Man_t * p, Vec_Ptr_t * vMapping, Aig_Man_t * pAig ) { char Buffer[1000]; Vec_Ptr_t * vCopies; Vec_Int_t * vCover; Ntl_Mod_t * pRoot; Ntl_Obj_t * pNode; Ntl_Net_t * pNet, * pNetCo; Ntl_Lut_t * pLut; int i, k, nDigits; assert( Vec_PtrSize(p->vCis) == Aig_ManPiNum(pAig) ); assert( Vec_PtrSize(p->vCos) == Aig_ManPoNum(pAig) ); p = Ntl_ManStartFrom( p ); pRoot = Ntl_ManRootModel( p ); assert( Ntl_ModelNodeNum(pRoot) == 0 ); // map the AIG back onto the design Ntl_ManForEachCiNet( p, pNet, i ) pNet->pCopy = Aig_ManPi( pAig, i ); // start mapping of AIG nodes into their copies vCopies = Vec_PtrStart( Aig_ManObjNumMax(pAig) ); Ntl_ManForEachCiNet( p, pNet, i ) Vec_PtrWriteEntry( vCopies, ((Aig_Obj_t *)pNet->pCopy)->Id, pNet ); // create a new node for each LUT vCover = Vec_IntAlloc( 1 << 16 ); nDigits = Aig_Base10Log( Vec_PtrSize(vMapping) ); Vec_PtrForEachEntry( Ntl_Lut_t *, vMapping, pLut, i ) { pNode = Ntl_ModelCreateNode( pRoot, pLut->nFanins ); pNode->pSop = Kit_PlaFromTruth( p->pMemSops, pLut->pTruth, pLut->nFanins, vCover ); if ( !Kit_TruthIsConst0(pLut->pTruth, pLut->nFanins) && !Kit_TruthIsConst1(pLut->pTruth, pLut->nFanins) ) { for ( k = 0; k < pLut->nFanins; k++ ) { pNet = (Ntl_Net_t *)Vec_PtrEntry( vCopies, pLut->pFanins[k] ); if ( pNet == NULL ) { printf( "Ntl_ManInsert(): Internal error: Net not found.\n" ); return 0; } Ntl_ObjSetFanin( pNode, pNet, k ); } } else pNode->nFanins = 0; sprintf( Buffer, "lut%0*d", nDigits, i ); if ( (pNet = Ntl_ModelFindNet( pRoot, Buffer )) ) { printf( "Ntl_ManInsert(): Internal error: Intermediate net name is not unique.\n" ); return 0; } pNet = Ntl_ModelFindOrCreateNet( pRoot, Buffer ); if ( !Ntl_ModelSetNetDriver( pNode, pNet ) ) { printf( "Ntl_ManInsert(): Internal error: Net has more than one fanin.\n" ); return 0; } Vec_PtrWriteEntry( vCopies, pLut->Id, pNet ); }