/**CFile**************************************************************** FileName [bm.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Boolean Matching package.] Synopsis [Check P-equivalence and PP-equivalence of two circuits.] Author [Hadi Katebi] Affiliation [University of Michigan] Date [Ver. 1.0. Started - January, 2009.] Revision [No revisions so far] Comments [This is the cleaned up version of the code I used for DATE 2010 publication.] [If you have any question or if you find a bug, contact me at hadik@umich.edu.] [I don't guarantee that I can fix all the bugs, but I can definitely point you to the right direction so you can fix the bugs yourself]. Debugging [There are some part of the code that are commented out. Those parts mostly print the contents of the data structures to the standard output. Un-comment them if you find them useful for debugging.] ***********************************************************************/ #include "base/abc/abc.h" #include "opt/sim/sim.h" #include "sat/bsat/satSolver.h" #include "misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START int match1by1(Abc_Ntk_t * pNtk1, Vec_Ptr_t ** nodesInLevel1, Vec_Int_t ** iMatch1, Vec_Int_t ** iDep1, Vec_Int_t * matchedInputs1, int * iGroup1, Vec_Int_t ** oMatch1, int * oGroup1, Abc_Ntk_t * pNtk2, Vec_Ptr_t ** nodesInLevel2, Vec_Int_t ** iMatch2, Vec_Int_t ** iDep2, Vec_Int_t * matchedInputs2, int * iGroup2, Vec_Int_t ** oMatch2, int * oGroup2, Vec_Int_t * matchedOutputs1, Vec_Int_t * matchedOutputs2, Vec_Int_t * oMatchedGroups, Vec_Int_t * iNonSingleton, int ii, int idx); int Abc_NtkBmSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Vec_Ptr_t * iMatchPairs, Vec_Ptr_t * oMatchPairs, Vec_Int_t * mismatch, int mode); void getDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep) { Vec_Ptr_t * vSuppFun; int i, j; vSuppFun = Sim_ComputeFunSupp(pNtk, 0); for(i = 0; i < Abc_NtkPoNum(pNtk); i++) { char * seg = (char *)vSuppFun->pArray[i]; for(j = 0; j < Abc_NtkPiNum(pNtk); j+=8) { if(((*seg) & 0x01) == 0x01) Vec_IntPushOrder(oDep[i], j); if(((*seg) & 0x02) == 0x02) Vec_IntPushOrder(oDep[i], j+1); if(((*seg) & 0x04) == 0x04) Vec_IntPushOrder(oDep[i], j+2); if(((*seg) & 0x08) == 0x08) Vec_IntPushOrder(oDep[i], j+3); if(((*seg) & 0x10) == 0x10) Vec_IntPushOrder(oDep[i], j+4); if(((*seg) & 0x20) == 0x20) Vec_IntPushOrder(oDep[i], j+5); if(((*seg) & 0x40) == 0x40) Vec_IntPushOrder(oDep[i], j+6); if(((*seg) & 0x80) == 0x80) Vec_IntPushOrder(oDep[i], j+7); seg++; } } for(i = 0; i < Abc_NtkPoNum(pNtk); i++) for(j = 0; j < Vec_IntSize(oDep[i]); j++) Vec_IntPush(iDep[Vec_IntEntry(oDep[i], j)], i); /*for(i = 0; i < Abc_NtkPoNum(pNtk); i++) { printf("Output %d: ", i); for(j = 0; j < Vec_IntSize(oDep[i]); j++) printf("%d ", Vec_IntEntry(oDep[i], j)); printf("\n"); } printf("\n"); for(i = 0; i < Abc_NtkPiNum(pNtk); i++) { printf("Input %d: ", i); for(j = 0; j < Vec_IntSize(iDep[i]); j++) printf("%d ", Vec_IntEntry(iDep[i], j)); printf("\n"); } printf("\n"); */ } void initMatchList(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep, Vec_Int_t** iMatch, int* iLastItem, Vec_Int_t** oMatch, int* oLastItem, int* iGroup, int* oGroup, int p_equivalence) { int i, j, curr; Vec_Int_t** temp; if(!p_equivalence) { temp = ABC_ALLOC( Vec_Int_t*, Abc_NtkPiNum(pNtk)+1); for(i = 0; i < Abc_NtkPiNum(pNtk)+1; i++) temp[i] = Vec_IntAlloc( 0 ); for(i = 0; i < Abc_NtkPoNum(pNtk); i++) Vec_IntPush(temp[Vec_IntSize(oDep[i])], i); curr = 0; for(i = 0; i < Abc_NtkPiNum(pNtk)+1; i++) { if(Vec_IntSize(temp[i]) == 0) Vec_IntFree( temp[i] ); else { oMatch[curr] = temp[i]; for(j = 0; j < Vec_IntSize(temp[i]); j++) oGroup[Vec_IntEntry(oMatch[curr], j)] = curr; curr++; } } *oLastItem = curr; ABC_FREE( temp ); } else { // the else part fixes the outputs for P-equivalence checking for(i = 0; i < Abc_NtkPoNum(pNtk); i++) { Vec_IntPush(oMatch[i], i); oGroup[i] = i; (*oLastItem) = Abc_NtkPoNum(pNtk); } } /*for(j = 0; j < *oLastItem; j++) { printf("oMatch %d: ", j); for(i = 0; i < Vec_IntSize(oMatch[j]); i++) printf("%d ", Vec_IntEntry(oMatch[j], i)); printf("\n"); } for(i = 0; i < Abc_NtkPoNum(pNtk); i++) printf("%d: %d ", i, oGroup[i]);*/ ////////////////////////////////////////////////////////////////////////////// temp = ABC_ALLOC( Vec_Int_t*, Abc_NtkPoNum(pNtk)+1 ); for(i = 0; i < Abc_NtkPoNum(pNtk)+1; i++) temp[i] = Vec_IntAlloc( 0 ); for(i = 0; i < Abc_NtkPiNum(pNtk); i++) Vec_IntPush(temp[Vec_IntSize(iDep[i])], i); curr = 0; for(i = 0; i < Abc_NtkPoNum(pNtk)+1; i++) { if(Vec_IntSize(temp[i]) == 0) Vec_IntFree( temp[i] ); else { iMatch[curr] = temp[i]; for(j = 0; j < Vec_IntSize(iMatch[curr]); j++) iGroup[Vec_IntEntry(iMatch[curr], j)] = curr; curr++; } } *iLastItem = curr; ABC_FREE( temp ); /*printf("\n"); for(j = 0; j < *iLastItem; j++) { printf("iMatch %d: ", j); for(i = 0; i < Vec_IntSize(iMatch[j]); i++) printf("%d ", Vec_IntEntry(iMatch[j], i)); printf("\n"); } for(i = 0; i < Abc_NtkPiNum(pNtk); i++) printf("%d: %d ", i, iGroup[i]); printf("\n");*/ } void iSortDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, int* oGroup) { int i, j, k; Vec_Int_t * temp; Vec_Int_t * oGroupList; oGroupList = Vec_IntAlloc( 10 ); for(i = 0; i < Abc_NtkPiNum(pNtk); i++) { if(Vec_IntSize(iDep[i]) == 1) continue; temp = Vec_IntAlloc( Vec_IntSize(iDep[i]) ); for(j = 0; j < Vec_IntSize(iDep[i]); j++) Vec_IntPushUniqueOrder(oGroupList, oGroup[Vec_IntEntry(iDep[i], j)]); for(j = 0; j < Vec_IntSize(oGroupList); j++) { for(k = 0; k < Vec_IntSize(iDep[i]); k++) if(oGroup[Vec_IntEntry(iDep[i], k)] == Vec_IntEntry(oGroupList, j)) { Vec_IntPush( temp, Vec_IntEntry(iDep[i], k) ); Vec_IntRemove( iDep[i], Vec_IntEntry(iDep[i], k) ); k--; } } Vec_IntFree( iDep[i] ); iDep[i] = temp; Vec_IntClear( oGroupList ); /*printf("Input %d: ", i); for(j = 0; j < Vec_IntSize(iDep[i]); j++) printf("%d ", Vec_IntEntry(iDep[i], j)); printf("\n");*/ } Vec_IntFree( oGroupList ); } void oSortDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** oDep, int* iGroup) { int i, j, k; Vec_Int_t * temp; Vec_Int_t * iGroupList; iGroupList = Vec_IntAlloc( 10 ); for(i = 0; i < Abc_NtkPoNum(pNtk); i++) { if(Vec_IntSize(oDep[i]) == 1) continue; temp = Vec_IntAlloc( Vec_IntSize(oDep[i]) ); for(j = 0; j < Vec_IntSize(oDep[i]); j++) Vec_IntPushUniqueOrder(iGroupList, iGroup[Vec_IntEntry(oDep[i], j)]); for(j = 0; j < Vec_IntSize(iGroupList); j++) { for(k = 0; k < Vec_IntSize(oDep[i]); k++) if(iGroup[Vec_IntEntry(oDep[i], k)] == Vec_IntEntry(iGroupList, j)) { Vec_IntPush( temp, Vec_IntEntry(oDep[i], k) ); Vec_IntRemove( oDep[i], Vec_IntEntry(oDep[i], k) ); k--; } } Vec_IntFree( oDep[i] ); oDep[i] = temp; Vec_IntClear( iGroupList ); /*printf("Output %d: ", i); for(j = 0; j < Vec_IntSize(oDep[i]); j++) printf("%d ", Vec_IntEntry(oDep[i], j)); printf("\n");*/ } Vec_IntFree( iGroupList ); } int oSplitByDep(Abc_Ntk_t *pNtk, Vec_Int_t** oDep, Vec_Int_t** oMatch, int* oGroup, int* oLastItem, int* iGroup) { int i, j, k; int numOfItemsAdded; Vec_Int_t * array, * sortedArray; numOfItemsAdded = 0; for(i = 0; i < *oLastItem; i++) { if(Vec_IntSize(oMatch[i]) == 1) continue; array = Vec_IntAlloc( Vec_IntSize(oMatch[i]) ); sortedArray = Vec_IntAlloc( Vec_IntSize(oMatch[i]) ); for(j = 0; j < Vec_IntSize(oMatch[i]); j++) { int factor, encode; encode = 0; factor = 1; for(k = 0; k < Vec_IntSize(oDep[Vec_IntEntry(oMatch[i], j)]); k++) encode += iGroup[Vec_IntEntry(oDep[Vec_IntEntry(oMatch[i], j)], k)] * factor; Vec_IntPush(array, encode); Vec_IntPushUniqueOrder(sortedArray, encode); if( encode < 0) printf("WARNING! Integer overflow!"); //printf("%d ", Vec_IntEntry(array, j)); } while( Vec_IntSize(sortedArray) > 1 ) { for(k = 0; k < Vec_IntSize(oMatch[i]); k++) { if(Vec_IntEntry(array, k) == Vec_IntEntryLast(sortedArray)) { Vec_IntPush(oMatch[*oLastItem+numOfItemsAdded], Vec_IntEntry(oMatch[i], k)); oGroup[Vec_IntEntry(oMatch[i], k)] = *oLastItem+numOfItemsAdded; Vec_IntRemove( oMatch[i], Vec_IntEntry(oMatch[i], k) ); Vec_IntRemove( array, Vec_IntEntry(array, k) ); k--; } } numOfItemsAdded++; Vec_IntPop(sortedArray); } Vec_IntFree( array ); Vec_IntFree( sortedArray ); //printf("\n"); } *oLastItem += numOfItemsAdded; /*printf("\n"); for(j = 0; j < *oLastItem ; j++) { printf("oMatch %d: ", j); for(i = 0; i < Vec_IntSize(oMatch[j]); i++) printf("%d ", Vec_IntEntry(oMatch[j], i)); printf("\n"); }*/ return numOfItemsAdded; } int iSplitByDep(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** iMatch, int* iGroup, int* iLastItem, int* oGroup) { int i, j, k; int numOfItemsAdded = 0; Vec_Int_t * array, * sortedArray; for(i = 0; i < *iLastItem; i++) { if(Vec_IntSize(iMatch[i]) == 1) continue; array = Vec_IntAlloc( Vec_IntSize(iMatch[i]) ); sortedArray = Vec_IntAlloc( Vec_IntSize(iMatch[i]) ); for(j = 0; j < Vec_IntSize(iMatch[i]); j++) { int factor, encode; encode = 0; factor = 1; for(k = 0; k < Vec_IntSize(iDep[Vec_IntEntry(iMatch[i], j)]); k++) encode += oGroup[Vec_IntEntry(iDep[Vec_IntEntry(iMatch[i], j)], k)] * factor; Vec_IntPush(array, encode); Vec_IntPushUniqueOrder(sortedArray, encode); //printf("%d ", Vec_IntEntry(array, j)); } while( Vec_IntSize(sortedArray) > 1 ) { for(k = 0; k < Vec_IntSize(iMatch[i]); k++) { if(Vec_IntEntry(array, k) == Vec_IntEntryLast(sortedArray)) { Vec_IntPush(iMatch[*iLastItem+numOfItemsAdded], Vec_IntEntry(iMatch[i], k)); iGroup[Vec_IntEntry(iMatch[i], k)] = *iLastItem+numOfItemsAdded; Vec_IntRemove( iMatch[i], Vec_IntEntry(iMatch[i], k) ); Vec_IntRemove( array, Vec_IntEntry(array, k) ); k--; } } numOfItemsAdded++; Vec_IntPop(sortedArray); } Vec_IntFree( array ); Vec_IntFree( sortedArray ); //printf("\n"); } *iLastItem += numOfItemsAdded; /*printf("\n"); for(j = 0; j < *iLastItem ; j++) { printf("iMatch %d: ", j); for(i = 0; i < Vec_IntSize(iMatch[j]); i++) printf("%d ", Vec_IntEntry(iMatch[j], i)); printf("\n"); }*/ return numOfItemsAdded; } Vec_Ptr_t ** findTopologicalOrder( Abc_Ntk_t * pNtk ) { Vec_Ptr_t ** vNodes; Abc_Obj_t * pObj, * pFanout; int i, k; extern void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); // start the array of nodes vNodes = ABC_ALLOC(Vec_Ptr_t *, Abc_NtkPiNum(pNtk)); for(i = 0; i < Abc_NtkPiNum(pNtk); i++) vNodes[i] = Vec_PtrAlloc(50); Abc_NtkForEachCi( pNtk, pObj, i ) { // set the traversal ID Abc_NtkIncrementTravId( pNtk ); Abc_NodeSetTravIdCurrent( pObj ); pObj = Abc_ObjFanout0Ntk(pObj); Abc_ObjForEachFanout( pObj, pFanout, k ) Abc_NtkDfsReverse_rec( pFanout, vNodes[i] ); } return vNodes; } int * Abc_NtkSimulateOneNode( Abc_Ntk_t * pNtk, int * pModel, int input, Vec_Ptr_t ** topOrder ) { Abc_Obj_t * pNode; Vec_Ptr_t * vNodes; int * pValues, Value0, Value1, i; vNodes = Vec_PtrAlloc( 50 ); /* printf( "Counter example: " ); Abc_NtkForEachCi( pNtk, pNode, i ) printf( " %d", pModel[i] ); printf( "\n" ); */ // increment the trav ID Abc_NtkIncrementTravId( pNtk ); // set the CI values Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)1; pNode = Abc_NtkCi(pNtk, input); pNode->iTemp = pModel[input]; // simulate in the topological order for(i = Vec_PtrSize(topOrder[input])-1; i >= 0; i--) { pNode = (Abc_Obj_t *)Vec_PtrEntry(topOrder[input], i); Value0 = ((int)(ABC_PTRUINT_T)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode); Value1 = ((int)(ABC_PTRUINT_T)Abc_ObjFanin1(pNode)->pCopy) ^ Abc_ObjFaninC1(pNode); if( pNode->iTemp != (Value0 & Value1)) { pNode->iTemp = (Value0 & Value1); Vec_PtrPush(vNodes, pNode); } } // fill the output values pValues = ABC_ALLOC( int, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) pValues[i] = ((int)(ABC_PTRUINT_T)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode); pNode = Abc_NtkCi(pNtk, input); if(pNode->pCopy == (Abc_Obj_t *)1) pNode->pCopy = (Abc_Obj_t *)0; else pNode->pCopy = (Abc_Obj_t *)1; for(i = 0; i < Vec_PtrSize(vNodes); i++) { pNode = (Abc_Obj_t *)Vec_PtrEntry(vNodes, i); if(pNode->pCopy == (Abc_Obj_t *)1) pNode->pCopy = (Abc_Obj_t *)0; else pNode->pCopy = (Abc_Obj_t *)1; } Vec_PtrFree( vNodes ); return pValues; } int refineIOBySimulation(Abc_Ntk_t *pNtk, Vec_Int_t** iMatch, int* iLastItem, int * iGroup, Vec_Int_t** iDep, Vec_Int_t** oMatch, int* oLastItem, int * oGroup, Vec_Int_t** oDep, char * vPiValues, int * observability, Vec_Ptr_t ** topOrder) { Abc_Obj_t * pObj; int * pModel;//, ** pModel2; int * output, * output2; int lastItem; int i, j, k; Vec_Int_t * iComputedNum, * iComputedNumSorted; Vec_Int_t * oComputedNum; // encoding the number of flips int factor; int isRefined = FALSE; pModel = ABC_ALLOC( int, Abc_NtkCiNum(pNtk) ); Abc_NtkForEachPi( pNtk, pObj, i ) pModel[i] = vPiValues[i] - '0'; Abc_NtkForEachLatch( pNtk, pObj, i ) pModel[Abc_NtkPiNum(pNtk)+i] = pObj->iData - 1; output = Abc_NtkVerifySimulatePattern( pNtk, pModel ); oComputedNum = Vec_IntAlloc( Abc_NtkPoNum(pNtk) ); for(i = 0; i < Abc_NtkPoNum(pNtk); i++) Vec_IntPush(oComputedNum, 0); /****************************************************************************************/ /********** group outputs that produce 1 and outputs that produce 0 together ************/ lastItem = *oLastItem; for(i = 0; i < lastItem && (*oLastItem) != Abc_NtkPoNum(pNtk); i++) { int flag = FALSE; if(Vec_IntSize(oMatch[i]) == 1) continue; for(j = 1; j < Vec_IntSize(oMatch[i]); j++) if(output[Vec_IntEntry(oMatch[i], 0)] != output[Vec_IntEntry(oMatch[i], j)]) { flag = TRUE; break; } if(flag) { for(j = 0; j < Vec_IntSize(oMatch[i]); j++) if(output[Vec_IntEntry(oMatch[i], j)]) { Vec_IntPush(oMatch[*oLastItem], Vec_IntEntry(oMatch[i], j)); oGroup[Vec_IntEntry(oMatch[i], j)] = *oLastItem; Vec_IntRemove(oMatch[i], Vec_IntEntry(oMatch[i], j)); j--; } (*oLastItem)++; } } if( (*oLastItem) > lastItem ) { isRefined = TRUE; iSortDependencies(pNtk, iDep, oGroup); } /****************************************************************************************/ /************* group inputs that make the same number of flips in outpus ****************/ lastItem = *iLastItem; for(i = 0; i < lastItem && (*iLastItem) != Abc_NtkPiNum(pNtk); i++) { int num; if(Vec_IntSize(iMatch[i]) == 1) continue; iComputedNum = Vec_IntAlloc( Vec_IntSize(iMatch[i]) ); iComputedNumSorted = Vec_IntAlloc( Vec_IntSize(iMatch[i]) ); for(j = 0; j < Vec_IntSize(iMatch[i]); j++) { if( vPiValues[Vec_IntEntry(iMatch[i], j)] == '0' ) pModel[Vec_IntEntry(iMatch[i], j)] = 1; else pModel[Vec_IntEntry(iMatch[i], j)] = 0; //output2 = Abc_NtkVerifySimulatePattern( pNtk, pModel ); output2 = Abc_NtkSimulateOneNode( pNtk, pModel, Vec_IntEntry(iMatch[i], j), topOrder ); num = 0; factor = 1; for(k = 0; k < Vec_IntSize(iDep[Vec_IntEntry(iMatch[i], j)]); k++) { int outputIndex = Vec_IntEntry(iDep[Vec_IntEntry(iMatch[i], j)], k); if(output2[outputIndex]) num += (oGroup[outputIndex] + 1) * factor; if(output[outputIndex] != output2[outputIndex]) { int temp = Vec_IntEntry(oComputedNum, outputIndex) + i + 1; Vec_IntWriteEntry(oComputedNum, outputIndex, temp); observability[Vec_IntEntry(iMatch[i], j)]++; } } Vec_IntPush(iComputedNum, num); Vec_IntPushUniqueOrder(iComputedNumSorted, num); pModel[Vec_IntEntry(iMatch[i], j)] = vPiValues[Vec_IntEntry(iMatch[i], j)] - '0'; ABC_FREE( output2 ); } while( Vec_IntSize( iComputedNumSorted ) > 1 ) { for(k = 0; k < Vec_IntSize(iMatch[i]); k++) { if(Vec_IntEntry(iComputedNum, k) == Vec_IntEntryLast(iComputedNumSorted) ) { Vec_IntPush(iMatch[*iLastItem], Vec_IntEntry(iMatch[i], k)); iGroup[Vec_IntEntry(iMatch[i], k)] = *iLastItem; Vec_IntRemove( iMatch[i], Vec_IntEntry(iMatch[i], k) ); Vec_IntRemove( iComputedNum, Vec_IntEntry(iComputedNum, k) ); k--; } } (*iLastItem)++; Vec_IntPop( iComputedNumSorted ); } Vec_IntFree( iComputedNum ); Vec_IntFree( iComputedNumSorted ); } if( (*iLastItem) > lastItem ) { isRefined = TRUE; oSortDependencies(pNtk, oDep, iGroup); } /****************************************************************************************/ /********** encode the number of flips in each output by flipping the outputs ***********/ /********** and group all the outputs that have the same encoding ***********/ lastItem = *oLastItem; for(i = 0; i < lastItem && (*oLastItem) != Abc_NtkPoNum(pNtk); i++) { Vec_Int_t * encode, * sortedEncode; // encoding the number of flips if(Vec_IntSize(oMatch[i]) == 1) continue; encode = Vec_IntAlloc( Vec_IntSize(oMatch[i]) ); sortedEncode = Vec_IntAlloc( Vec_IntSize(oMatch[i]) ); for(j = 0; j < Vec_IntSize(oMatch[i]); j++) { Vec_IntPush(encode, Vec_IntEntry(oComputedNum, Vec_IntEntry(oMatch[i], j)) ); Vec_IntPushUniqueOrder( sortedEncode, Vec_IntEntry(encode, j) ); } while( Vec_IntSize(sortedEncode) > 1 ) { for(j = 0; j < Vec_IntSize(oMatch[i]); j++) if(Vec_IntEntry(encode, j) == Vec_IntEntryLast(sortedEncode)) { Vec_IntPush(oMatch[*oLastItem], Vec_IntEntry(oMatch[i], j)); oGroup[Vec_IntEntry(oMatch[i], j)] = *oLastItem; Vec_IntRemove( oMatch[i], Vec_IntEntry(oMatch[i], j) ); Vec_IntRemove( encode, Vec_IntEntry(encode, j) ); j --; } (*oLastItem)++; Vec_IntPop( sortedEncode ); } Vec_IntFree( encode ); Vec_IntFree( sortedEncode ); } if( (*oLastItem) > lastItem ) isRefined = TRUE; ABC_FREE( pModel ); ABC_FREE( output ); Vec_IntFree( oComputedNum ); return isRefined; } Abc_Ntk_t * Abc_NtkMiterBm( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Vec_Ptr_t * iCurrMatch, Vec_Ptr_t * oCurrMatch ) { char Buffer[1000]; Abc_Ntk_t * pNtkMiter; pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); pNtkMiter->pName = Extra_UtilStrsav(Buffer); //Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize ); { Abc_Obj_t * pObj, * pObjNew; int i; Abc_AigConst1(pNtk1)->pCopy = Abc_AigConst1(pNtkMiter); Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtkMiter); // create new PIs and remember them in the old PIs if(iCurrMatch == NULL) { Abc_NtkForEachCi( pNtk1, pObj, i ) { pObjNew = Abc_NtkCreatePi( pNtkMiter ); // remember this PI in the old PIs pObj->pCopy = pObjNew; pObj = Abc_NtkCi(pNtk2, i); pObj->pCopy = pObjNew; // add name Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); } } else { for(i = 0; i < Vec_PtrSize( iCurrMatch ); i += 2) { pObjNew = Abc_NtkCreatePi( pNtkMiter ); pObj = (Abc_Obj_t *)Vec_PtrEntry(iCurrMatch, i); pObj->pCopy = pObjNew; pObj = (Abc_Obj_t *)Vec_PtrEntry(iCurrMatch, i+1); pObj->pCopy = pObjNew; // add name Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); } } // create the only PO pObjNew = Abc_NtkCreatePo( pNtkMiter ); // add the PO name Abc_ObjAssignName( pObjNew, "miter", NULL ); } // Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); { Abc_Obj_t * pNode; int i; assert( Abc_NtkIsDfsOrdered(pNtk1) ); Abc_AigForEachAnd( pNtk1, pNode, i ) pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); } // Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); { Abc_Obj_t * pNode; int i; assert( Abc_NtkIsDfsOrdered(pNtk2) ); Abc_AigForEachAnd( pNtk2, pNode, i ) pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); } // Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize ); { Vec_Ptr_t * vPairs; Abc_Obj_t * pMiter; int i; vPairs = Vec_PtrAlloc( 100 ); // collect the CO nodes for the miter if(oCurrMatch != NULL) { for(i = 0; i < Vec_PtrSize( oCurrMatch ); i += 2) { Vec_PtrPush( vPairs, Abc_ObjChild0Copy((Abc_Obj_t *)Vec_PtrEntry(oCurrMatch, i)) ); Vec_PtrPush( vPairs, Abc_ObjChild0Copy((Abc_Obj_t *)Vec_PtrEntry(oCurrMatch, i+1)) ); } } else { Abc_Obj_t * pNode; Abc_NtkForEachCo( pNtk1, pNode, i ) { Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); pNode = Abc_NtkCo( pNtk2, i ); Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); } } pMiter = Abc_AigMiter( (Abc_Aig_t *)pNtkMiter->pManFunc, vPairs, 0 ); Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); Vec_PtrFree(vPairs); } //Abc_AigCleanup(pNtkMiter->pManFunc); return pNtkMiter; } int * pValues1__, * pValues2__; void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, Vec_Int_t * mismatch ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pNode; int nErrors, nPrinted, i, iNode = -1; assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) ); assert( Abc_NtkCoNum(pNtk1) == Abc_NtkCoNum(pNtk2) ); // get the CO values under this model pValues1__ = Abc_NtkVerifySimulatePattern( pNtk1, pModel ); pValues2__ = Abc_NtkVerifySimulatePattern( pNtk2, pModel ); // count the mismatches nErrors = 0; for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ ) nErrors += (int)( pValues1__[i] != pValues2__[i] ); //printf( "Verification failed for at least %d outputs: ", nErrors ); // print the first 3 outputs nPrinted = 0; for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ ) if ( pValues1__[i] != pValues2__[i] ) { if ( iNode == -1 ) iNode = i; //printf( " %s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) ); if ( ++nPrinted == 3 ) break; } /*if ( nPrinted != nErrors ) printf( " ..." ); printf( "\n" );*/ // report mismatch for the first output if ( iNode >= 0 ) { /*printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n", Abc_ObjName(Abc_NtkCo(pNtk1,iNode)), pValues1[iNode], pValues2[iNode] ); printf( "Input pattern: " );*/ // collect PIs in the cone pNode = Abc_NtkCo(pNtk1,iNode); vNodes = Abc_NtkNodeSupport( pNtk1, &pNode, 1 ); // set the PI numbers Abc_NtkForEachCi( pNtk1, pNode, i ) pNode->iTemp = i; // print the model pNode = (Abc_Obj_t *)Vec_PtrEntry( vNodes, 0 ); if ( Abc_ObjIsCi(pNode) ) { Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { assert( Abc_ObjIsCi(pNode) ); //printf( " %s=%d", Abc_ObjName(pNode), pModel[(int)pNode->pCopy] ); Vec_IntPush(mismatch, Abc_ObjId(pNode)-1); Vec_IntPush(mismatch, pModel[(int)(size_t)pNode->pCopy]); } } //printf( "\n" ); Vec_PtrFree( vNodes ); } free( pValues1__ ); free( pValues2__ ); } int Abc_NtkMiterSatBm( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fVerbose, ABC_INT64_T * pNumConfs, ABC_INT64_T * pNumInspects) { static sat_solver * pSat = NULL; lbool status; int RetValue; abctime clk; extern int Abc_NodeAddClausesTop( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ); extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); if ( pNumConfs ) *pNumConfs = 0; if ( pNumInspects ) *pNumInspects = 0; assert( Abc_NtkLatchNum(pNtk) == 0 ); // if ( Abc_NtkPoNum(pNtk) > 1 ) // fprintf( stdout, "Warning: The miter has %d outputs. SAT will try to prove all of them.\n", Abc_NtkPoNum(pNtk) ); // load clauses into the sat_solver clk = Abc_Clock(); pSat = (sat_solver *)Abc_NtkMiterSatCreate( pNtk, 0 ); if ( pSat == NULL ) return 1; //printf( "%d \n", pSat->clauses.size ); //sat_solver_delete( pSat ); //return 1; // printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); // PRT( "Time", Abc_Clock() - clk ); // simplify the problem clk = Abc_Clock(); status = sat_solver_simplify(pSat); // printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); // PRT( "Time", Abc_Clock() - clk ); if ( status == 0 ) { sat_solver_delete( pSat ); // printf( "The problem is UNSATISFIABLE after simplification.\n" ); return 1; } // solve the miter clk = Abc_Clock(); if ( fVerbose ) pSat->verbosity = 1; status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_Undef ) { // printf( "The problem timed out.\n" ); RetValue = -1; } else if ( status == l_True ) { // printf( "The problem is SATISFIABLE.\n" ); RetValue = 0; } else if ( status == l_False ) { // printf( "The problem is UNSATISFIABLE.\n" ); RetValue = 1; } else assert( 0 ); // PRT( "SAT sat_solver time", Abc_Clock() - clk ); // printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts ); // if the problem is SAT, get the counterexample if ( status == l_True ) { // Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk ); Vec_Int_t * vCiIds = Abc_NtkGetCiSatVarNums( pNtk ); pNtk->pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); Vec_IntFree( vCiIds ); } // free the sat_solver if ( fVerbose ) Sat_SolverPrintStats( stdout, pSat ); if ( pNumConfs ) *pNumConfs = (int)pSat->stats.conflicts; if ( pNumInspects ) *pNumInspects = (int)pSat->stats.inspects; //sat_solver_store_write( pSat, "trace.cnf" ); sat_solver_store_free( pSat ); sat_solver_delete( pSat ); return RetValue; } int Abc_NtkBmSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Vec_Ptr_t * iMatchPairs, Vec_Ptr_t * oMatchPairs, Vec_Int_t * mismatch, int mode) { extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); Abc_Ntk_t * pMiter = NULL; Abc_Ntk_t * pCnf; int RetValue; // get the miter of the two networks if( mode == 0 ) { //Abc_NtkDelete( pMiter ); pMiter = Abc_NtkMiterBm( pNtk1, pNtk2, iMatchPairs, oMatchPairs ); } else if( mode == 1 ) // add new outputs { int i; Abc_Obj_t * pObj; Vec_Ptr_t * vPairs; Abc_Obj_t * pNtkMiter; vPairs = Vec_PtrAlloc( 100 ); Abc_NtkForEachCo( pMiter, pObj, i ) Abc_ObjRemoveFanins( pObj ); for(i = 0; i < Vec_PtrSize( oMatchPairs ); i += 2) { Vec_PtrPush( vPairs, Abc_ObjChild0Copy((Abc_Obj_t *)Vec_PtrEntry(oMatchPairs, i)) ); Vec_PtrPush( vPairs, Abc_ObjChild0Copy((Abc_Obj_t *)Vec_PtrEntry(oMatchPairs, i+1)) ); } pNtkMiter = Abc_AigMiter( (Abc_Aig_t *)pMiter->pManFunc, vPairs, 0 ); Abc_ObjAddFanin( Abc_NtkPo(pMiter,0), pNtkMiter ); Vec_PtrFree( vPairs); } else if( mode == 2 ) // add some outputs { } else if( mode == 3) // remove all outputs { } if ( pMiter == NULL ) { printf("Miter computation has failed."); return -1; } RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0) { /*printf("Networks are NOT EQUIVALENT after structural hashing."); */ // report the error if(mismatch != NULL) { pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel, mismatch ); ABC_FREE( pMiter->pModel ); } Abc_NtkDelete( pMiter ); return RetValue; } if( RetValue == 1 ) { /*printf("Networks are equivalent after structural hashing."); */ Abc_NtkDelete( pMiter ); return RetValue; } // convert the miter into a CNF //if(mode == 0) pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 ); Abc_NtkDelete( pMiter ); if ( pCnf == NULL ) { printf("Renoding for CNF has failed."); return -1; } // solve the CNF using the SAT solver RetValue = Abc_NtkMiterSat( pCnf, (ABC_INT64_T)10000, (ABC_INT64_T)0, 0, NULL, NULL); /*if ( RetValue == -1 ) printf("Networks are undecided (SAT solver timed out)."); else if ( RetValue == 0 ) printf("Networks are NOT EQUIVALENT after SAT."); else printf("Networks are equivalent after SAT."); */ if ( mismatch != NULL && pCnf->pModel ) Abc_NtkVerifyReportError( pNtk1, pNtk2, pCnf->pModel, mismatch ); ABC_FREE( pCnf->pModel ); Abc_NtkDelete( pCnf ); return RetValue; } int checkEquivalence( Abc_Ntk_t * pNtk1, Vec_Int_t* matchedInputs1, Vec_Int_t * matchedOutputs1, Abc_Ntk_t * pNtk2, Vec_Int_t* matchedInputs2, Vec_Int_t * matchedOutputs2) { Vec_Ptr_t * iMatchPairs, * oMatchPairs; int i; int result; iMatchPairs = Vec_PtrAlloc( Abc_NtkPiNum( pNtk1 ) * 2); oMatchPairs = Vec_PtrAlloc( Abc_NtkPoNum( pNtk1 ) * 2); for(i = 0; i < Abc_NtkPiNum(pNtk1); i++) { Vec_PtrPush(iMatchPairs, Abc_NtkPi(pNtk2, Vec_IntEntry(matchedInputs2, i))); Vec_PtrPush(iMatchPairs, Abc_NtkPi(pNtk1, Vec_IntEntry(matchedInputs1, i))); } for(i = 0; i < Abc_NtkPoNum(pNtk1); i++) { Vec_PtrPush(oMatchPairs, Abc_NtkPo(pNtk2, Vec_IntEntry(matchedOutputs2, i))); Vec_PtrPush(oMatchPairs, Abc_NtkPo(pNtk1, Vec_IntEntry(matchedOutputs1, i))); } result = Abc_NtkBmSat(pNtk1, pNtk2, iMatchPairs, oMatchPairs, NULL, 0); if( result ) printf("*** Circuits are equivalent ***\n"); else printf("*** Circuits are NOT equivalent ***\n"); Vec_PtrFree( iMatchPairs ); Vec_PtrFree( oMatchPairs ); return result; } Abc_Ntk_t * computeCofactor(Abc_Ntk_t * pNtk, Vec_Ptr_t ** nodesInLevel, int * bitVector, Vec_Int_t * currInputs) { Abc_Ntk_t * subNtk; Abc_Obj_t * pObj, * pObjNew; int i, j, numOfLevels; numOfLevels = Abc_AigLevel( pNtk ); // number of levels excludes PI/POs // start a new network subNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); subNtk->pName = Extra_UtilStrsav("subNtk"); Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(subNtk); // clean the node copy fields and mark the nodes that need to be copied to the new network Abc_NtkCleanCopy( pNtk ); if(bitVector != NULL) { for(i = 0; i < Abc_NtkPiNum(pNtk); i++) if(bitVector[i]) { pObj = Abc_NtkPi(pNtk, i); pObj->pCopy = (Abc_Obj_t *)(1); } } for(i = 0; i < Vec_IntSize(currInputs); i++) { pObj = Abc_NtkPi(pNtk, Vec_IntEntry(currInputs, i)); pObjNew = Abc_NtkDupObj( subNtk, pObj, 1 ); pObj->pCopy = pObjNew; } // i = 0 are the inputs and the inputs are not added to the 2d array ( nodesInLevel ) for( i = 0; i <= numOfLevels; i++ ) for( j = 0; j < Vec_PtrSize( nodesInLevel[i] ); j++) { pObj = (Abc_Obj_t *)Vec_PtrEntry( nodesInLevel[i], j ); if(Abc_ObjChild0Copy(pObj) == NULL && Abc_ObjChild1Copy(pObj) == NULL) pObj->pCopy = NULL; else if(Abc_ObjChild0Copy(pObj) == NULL && Abc_ObjChild1Copy(pObj) == (void*)(1)) pObj->pCopy = NULL; else if(Abc_ObjChild0Copy(pObj) == NULL && (Abc_ObjChild1Copy(pObj) != (NULL) && Abc_ObjChild1Copy(pObj) != (void*)(1)) ) pObj->pCopy = NULL; else if(Abc_ObjChild0Copy(pObj) == (void*)(1) && Abc_ObjChild1Copy(pObj) == NULL) pObj->pCopy = NULL; else if(Abc_ObjChild0Copy(pObj) == (void*)(1) && Abc_ObjChild1Copy(pObj) == (void*)(1)) pObj->pCopy = (Abc_Obj_t *)(1); else if(Abc_ObjChild0Copy(pObj) == (void*)(1) && (Abc_ObjChild1Copy(pObj) != (NULL) && Abc_ObjChild1Copy(pObj) != (void*)(1)) ) pObj->pCopy = Abc_ObjChild1Copy(pObj); else if( (Abc_ObjChild0Copy(pObj) != (NULL) && Abc_ObjChild0Copy(pObj) != (void*)(1)) && Abc_ObjChild1Copy(pObj) == NULL ) pObj->pCopy = NULL; else if( (Abc_ObjChild0Copy(pObj) != (NULL) && Abc_ObjChild0Copy(pObj) != (void*)(1)) && Abc_ObjChild1Copy(pObj) == (void*)(1) ) pObj->pCopy = Abc_ObjChild0Copy(pObj); else if( (Abc_ObjChild0Copy(pObj) != (NULL) && Abc_ObjChild0Copy(pObj) != (void*)(1)) && (Abc_ObjChild1Copy(pObj) != (NULL) && Abc_ObjChild1Copy(pObj) != (void*)(1)) ) pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)subNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); } for(i = 0; i < Abc_NtkPoNum(pNtk); i++) { pObj = Abc_NtkPo(pNtk, i); pObjNew = Abc_NtkDupObj( subNtk, pObj, 1 ); if( Abc_ObjChild0Copy(pObj) == NULL) { Abc_ObjAddFanin( pObjNew, Abc_AigConst1(subNtk)); pObjNew->fCompl0 = 1; } else if( Abc_ObjChild0Copy(pObj) == (void*)(1) ) { Abc_ObjAddFanin( pObjNew, Abc_AigConst1(subNtk)); pObjNew->fCompl0 = 0; } else Abc_ObjAddFanin( pObjNew, Abc_ObjChild0Copy(pObj) ); } return subNtk; } FILE *matchFile; int matchNonSingletonOutputs(Abc_Ntk_t * pNtk1, Vec_Ptr_t ** nodesInLevel1, Vec_Int_t ** iMatch1, Vec_Int_t ** iDep1, Vec_Int_t * matchedInputs1, int * iGroup1, Vec_Int_t ** oMatch1, int * oGroup1, Abc_Ntk_t * pNtk2, Vec_Ptr_t ** nodesInLevel2, Vec_Int_t ** iMatch2, Vec_Int_t ** iDep2, Vec_Int_t * matchedInputs2, int * iGroup2, Vec_Int_t ** oMatch2, int * oGroup2, Vec_Int_t * matchedOutputs1, Vec_Int_t * matchedOutputs2, Vec_Int_t * oMatchedGroups, Vec_Int_t * iNonSingleton, Abc_Ntk_t * subNtk1, Abc_Ntk_t * subNtk2, Vec_Ptr_t * oMatchPairs, Vec_Int_t * oNonSingleton, int oI, int idx, int ii, int iidx) { static int MATCH_FOUND; int i; int j, temp; Vec_Int_t * mismatch; int * skipList; static int counter = 0; MATCH_FOUND = FALSE; if( oI == Vec_IntSize( oNonSingleton ) ) { if( iNonSingleton != NULL) if( match1by1(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, ii, iidx) ) MATCH_FOUND = TRUE; if( iNonSingleton == NULL) MATCH_FOUND = TRUE; return MATCH_FOUND; } i = Vec_IntEntry(oNonSingleton, oI); mismatch = Vec_IntAlloc(10); skipList = ABC_ALLOC(int, Vec_IntSize(oMatch1[i])); for(j = 0; j < Vec_IntSize(oMatch1[i]); j++) skipList[j] = FALSE; Vec_PtrPush(oMatchPairs, Abc_NtkPo(subNtk1, Vec_IntEntry(oMatch1[i], idx)) ); Vec_IntPush(matchedOutputs1, Vec_IntEntry(oMatch1[i], idx)); for(j = 0; j < Vec_IntSize( oMatch2[i] ) && MATCH_FOUND == FALSE; j++) { if( Vec_IntEntry(oMatch2[i], j) == -1 || skipList[j] == TRUE) continue; Vec_PtrPush(oMatchPairs, Abc_NtkPo(subNtk2, Vec_IntEntry(oMatch2[i], j))); Vec_IntPush(matchedOutputs2, Vec_IntEntry(oMatch2[i], j)); counter++; if( Abc_NtkBmSat( subNtk1, subNtk2, NULL, oMatchPairs, mismatch, 0) ) { /*fprintf(matchFile, "%s matched to %s\n", Abc_ObjName(Abc_NtkPo(pNtk1, Vec_IntEntry(oMatch1[i], idx))), Abc_ObjName(Abc_NtkPo(pNtk2, Vec_IntEntry(oMatch2[i], j)))); */ temp = Vec_IntEntry(oMatch2[i], j); Vec_IntWriteEntry(oMatch2[i], j, -1); if(idx != Vec_IntSize( oMatch1[i] ) - 1) // call the same function with idx+1 matchNonSingletonOutputs(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, subNtk1, subNtk2, oMatchPairs, oNonSingleton, oI, idx+1, ii, iidx); else // call the same function with idx = 0 and oI++ matchNonSingletonOutputs(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, subNtk1, subNtk2, oMatchPairs, oNonSingleton, oI+1, 0, ii, iidx); Vec_IntWriteEntry(oMatch2[i], j, temp); } else { int * output1, * output2; int k; Abc_Obj_t * pObj; int * pModel; char * vPiValues; vPiValues = ABC_ALLOC( char, Abc_NtkPiNum(subNtk1) + 1); vPiValues[Abc_NtkPiNum(subNtk1)] = '\0'; for(k = 0; k < Abc_NtkPiNum(subNtk1); k++) vPiValues[k] = '0'; for(k = 0; k < Vec_IntSize(mismatch); k += 2) vPiValues[Vec_IntEntry(mismatch, k)] = Vec_IntEntry(mismatch, k+1); pModel = ABC_ALLOC( int, Abc_NtkCiNum(subNtk1) ); Abc_NtkForEachPi( subNtk1, pObj, k ) pModel[k] = vPiValues[k] - '0'; Abc_NtkForEachLatch( subNtk1, pObj, k ) pModel[Abc_NtkPiNum(subNtk1)+k] = pObj->iData - 1; output1 = Abc_NtkVerifySimulatePattern( subNtk1, pModel ); Abc_NtkForEachLatch( subNtk2, pObj, k ) pModel[Abc_NtkPiNum(subNtk2)+k] = pObj->iData - 1; output2 = Abc_NtkVerifySimulatePattern( subNtk2, pModel ); for(k = 0; k < Vec_IntSize( oMatch1[i] ); k++) if(output1[Vec_IntEntry(oMatch1[i], idx)] != output2[Vec_IntEntry(oMatch2[i], k)]) { skipList[k] = TRUE; /*printf("Output is SKIPPED");*/ } ABC_FREE( vPiValues ); ABC_FREE( pModel ); ABC_FREE( output1 ); ABC_FREE( output2 ); } if(MATCH_FOUND == FALSE ) { Vec_PtrPop(oMatchPairs); Vec_IntPop(matchedOutputs2); } } if(MATCH_FOUND == FALSE ) { Vec_PtrPop(oMatchPairs); Vec_IntPop(matchedOutputs1); } if(MATCH_FOUND && counter != 0) { /*printf("Number of OUTPUT SAT instances = %d", counter);*/ counter = 0; } ABC_FREE( mismatch ); ABC_FREE( skipList ); return MATCH_FOUND; } int match1by1(Abc_Ntk_t * pNtk1, Vec_Ptr_t ** nodesInLevel1, Vec_Int_t ** iMatch1, Vec_Int_t ** iDep1, Vec_Int_t * matchedInputs1, int * iGroup1, Vec_Int_t ** oMatch1, int * oGroup1, Abc_Ntk_t * pNtk2, Vec_Ptr_t ** nodesInLevel2, Vec_Int_t ** iMatch2, Vec_Int_t ** iDep2, Vec_Int_t * matchedInputs2, int * iGroup2, Vec_Int_t ** oMatch2, int * oGroup2, Vec_Int_t * matchedOutputs1, Vec_Int_t * matchedOutputs2, Vec_Int_t * oMatchedGroups, Vec_Int_t * iNonSingleton, int ii, int idx) { static int MATCH_FOUND = FALSE; Abc_Ntk_t * subNtk1, * subNtk2; Vec_Int_t * oNonSingleton; Vec_Ptr_t * oMatchPairs; int * skipList; int j, m; int i; static int counter = 0; MATCH_FOUND = FALSE; if( ii == Vec_IntSize(iNonSingleton) ) { MATCH_FOUND = TRUE; return TRUE; } i = Vec_IntEntry(iNonSingleton, ii); if( idx == Vec_IntSize(iMatch1[i]) ) { // call again with the next element in iNonSingleton return match1by1(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, ii+1, 0); } oNonSingleton = Vec_IntAlloc(10); oMatchPairs = Vec_PtrAlloc(100); skipList = ABC_ALLOC(int, Vec_IntSize(iMatch1[i])); for(j = 0; j < Vec_IntSize(iMatch1[i]); j++) skipList[j] = FALSE; Vec_IntPush(matchedInputs1, Vec_IntEntry(iMatch1[i], idx)); idx++; if(idx == 1) { for(j = 0; j < Vec_IntSize(iDep1[Vec_IntEntryLast(iMatch1[i])]); j++) { if( Vec_IntSize(oMatch1[oGroup1[Vec_IntEntry(iDep1[Vec_IntEntryLast(iMatch1[i])], j)]]) == 1 ) continue; if( Vec_IntFind( oMatchedGroups, oGroup1[Vec_IntEntry(iDep1[Vec_IntEntryLast(iMatch1[i])], j)]) != -1) continue; Vec_IntPushUnique(oNonSingleton, oGroup1[Vec_IntEntry(iDep1[Vec_IntEntryLast(iMatch1[i])], j)]); Vec_IntPushUnique(oMatchedGroups, oGroup1[Vec_IntEntry(iDep1[Vec_IntEntryLast(iMatch1[i])], j)]); } } subNtk1 = computeCofactor(pNtk1, nodesInLevel1, NULL, matchedInputs1); for(j = idx-1; j < Vec_IntSize(iMatch2[i]) && MATCH_FOUND == FALSE; j++) { int tempJ; Vec_Int_t * mismatch; if( skipList[j] ) continue; mismatch = Vec_IntAlloc(10); Vec_IntPush(matchedInputs2, Vec_IntEntry(iMatch2[i], j)); subNtk2 = computeCofactor(pNtk2, nodesInLevel2, NULL, matchedInputs2); for(m = 0; m < Vec_IntSize(matchedOutputs1); m++) { Vec_PtrPush(oMatchPairs, Abc_NtkPo(subNtk1, Vec_IntEntry(matchedOutputs1, m))); Vec_PtrPush(oMatchPairs, Abc_NtkPo(subNtk2, Vec_IntEntry(matchedOutputs2, m))); } counter++; if( Abc_NtkBmSat( subNtk2, subNtk1, NULL, oMatchPairs, mismatch, 0) ) { if(idx-1 != j) { tempJ = Vec_IntEntry(iMatch2[i], idx-1); Vec_IntWriteEntry(iMatch2[i], idx-1, Vec_IntEntry(iMatch2[i], j)); Vec_IntWriteEntry(iMatch2[i], j, tempJ); } /*fprintf(matchFile, "%s matched to %s\n", Abc_ObjName(Abc_NtkPi(pNtk1, Vec_IntEntry(iMatch1[i], idx-1))), Abc_ObjName(Abc_NtkPi(pNtk2, Vec_IntEntry(iMatch2[i], j))));*/ // we look for a match for outputs in oNonSingleton matchNonSingletonOutputs(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, subNtk1, subNtk2, oMatchPairs, oNonSingleton, 0, 0, ii, idx); if(idx-1 != j) { tempJ = Vec_IntEntry(iMatch2[i], idx-1); Vec_IntWriteEntry(iMatch2[i], idx-1, Vec_IntEntry(iMatch2[i], j)); Vec_IntWriteEntry(iMatch2[i], j, tempJ); } } else { Abc_Ntk_t * FpNtk1, * FpNtk2; int * bitVector1, * bitVector2; Vec_Int_t * currInputs1, * currInputs2; Vec_Ptr_t * vSupp; Abc_Obj_t * pObj; int suppNum1 = 0; int * suppNum2; bitVector1 = ABC_ALLOC( int, Abc_NtkPiNum(pNtk1) ); bitVector2 = ABC_ALLOC( int, Abc_NtkPiNum(pNtk2) ); currInputs1 = Vec_IntAlloc(10); currInputs2 = Vec_IntAlloc(10); suppNum2 = ABC_ALLOC(int, Vec_IntSize(iMatch2[i])-idx+1); for(m = 0; m < Abc_NtkPiNum(pNtk1); m++) { bitVector1[m] = 0; bitVector2[m] = 0; } for(m = 0; m < Vec_IntSize(iMatch2[i])-idx+1; m++) suppNum2[m]= 0; // First of all set the value of the inputs that are already matched and are in mismatch for(m = 0; m < Vec_IntSize(mismatch); m += 2) { int n = Vec_IntEntry(mismatch, m); bitVector1[Vec_IntEntry(matchedInputs1, n)] = Vec_IntEntry(mismatch, m+1); bitVector2[Vec_IntEntry(matchedInputs2, n)] = Vec_IntEntry(mismatch, m+1); } for(m = idx-1; m < Vec_IntSize(iMatch1[i]); m++) { Vec_IntPush(currInputs1, Vec_IntEntry(iMatch1[i], m)); Vec_IntPush(currInputs2, Vec_IntEntry(iMatch2[i], m)); } // Then add all the inputs that are not yet matched to the currInputs for(m = 0; m < Abc_NtkPiNum(pNtk1); m++) { if(Vec_IntFind( matchedInputs1, m ) == -1) Vec_IntPushUnique(currInputs1, m); if(Vec_IntFind( matchedInputs2, m ) == -1) Vec_IntPushUnique(currInputs2, m); } FpNtk1 = computeCofactor(pNtk1, nodesInLevel1, bitVector1, currInputs1); FpNtk2 = computeCofactor(pNtk2, nodesInLevel2, bitVector2, currInputs2); Abc_NtkForEachPo( FpNtk1, pObj, m ) { int n; vSupp = Abc_NtkNodeSupport( FpNtk1, &pObj, 1 ); for(n = 0; n < vSupp->nSize; n++) if( Abc_ObjId((Abc_Obj_t *)vSupp->pArray[n]) == 1 ) suppNum1 += Vec_IntFind( matchedOutputs1, m) + 1; Vec_PtrFree( vSupp ); } Abc_NtkForEachPo( FpNtk2, pObj, m ) { int n; vSupp = Abc_NtkNodeSupport( FpNtk2, &pObj, 1 ); for(n = 0; n < vSupp->nSize; n++) if( (int)Abc_ObjId((Abc_Obj_t *)vSupp->pArray[n])-1 < (Vec_IntSize(iMatch2[i]))-idx+1 && (int)Abc_ObjId((Abc_Obj_t *)vSupp->pArray[n])-1 >= 0) suppNum2[Abc_ObjId((Abc_Obj_t *)vSupp->pArray[n])-1] += Vec_IntFind( matchedOutputs2, m) + 1; Vec_PtrFree( vSupp ); } /*if(suppNum1 != 0) printf("Ntk1 is trigged"); if(suppNum2[0] != 0) printf("Ntk2 is trigged");*/ for(m = 0; m < Vec_IntSize(iMatch2[i])-idx+1; m++) if(suppNum2[m] != suppNum1) { skipList[m+idx-1] = TRUE; /*printf("input is skipped");*/ } Abc_NtkDelete( FpNtk1 ); Abc_NtkDelete( FpNtk2 ); ABC_FREE( bitVector1 ); ABC_FREE( bitVector2 ); Vec_IntFree( currInputs1 ); Vec_IntFree( currInputs2 ); ABC_FREE( suppNum2 ); } Vec_PtrClear(oMatchPairs); Abc_NtkDelete( subNtk2 ); Vec_IntFree(mismatch); //Vec_IntWriteEntry(iMatch2[i], j, tempJ); if( MATCH_FOUND == FALSE ) Vec_IntPop(matchedInputs2); } if( MATCH_FOUND == FALSE ) { Vec_IntPop(matchedInputs1); if(idx == 1) { for(m = 0; m < Vec_IntSize(oNonSingleton); m++) Vec_IntPop( oMatchedGroups ); } } Vec_IntFree( oNonSingleton ); Vec_PtrFree( oMatchPairs ); ABC_FREE( skipList ); Abc_NtkDelete( subNtk1 ); if(MATCH_FOUND && counter != 0) { /*printf("Number of INPUT SAT instances = %d\n", counter);*/ counter = 0; } return MATCH_FOUND; } float refineBySAT(Abc_Ntk_t * pNtk1, Vec_Int_t ** iMatch1, int * iGroup1, Vec_Int_t ** iDep1, int* iLastItem1, Vec_Int_t ** oMatch1, int * oGroup1, Vec_Int_t ** oDep1, int* oLastItem1, int * observability1, Abc_Ntk_t * pNtk2, Vec_Int_t ** iMatch2, int * iGroup2, Vec_Int_t ** iDep2, int* iLastItem2, Vec_Int_t ** oMatch2, int * oGroup2, Vec_Int_t ** oDep2, int* oLastItem2, int * observability2) { int i, j; Abc_Obj_t * pObj; Vec_Int_t * iNonSingleton; Vec_Int_t * matchedInputs1, * matchedInputs2; Vec_Int_t * matchedOutputs1, * matchedOutputs2; Vec_Ptr_t ** nodesInLevel1, ** nodesInLevel2; Vec_Int_t * oMatchedGroups; FILE *result; int matchFound; abctime clk = Abc_Clock(); float satTime = 0.0; /*matchFile = fopen("satmatch.txt", "w");*/ iNonSingleton = Vec_IntAlloc(10); matchedInputs1 = Vec_IntAlloc( Abc_NtkPiNum(pNtk1) ); matchedInputs2 = Vec_IntAlloc( Abc_NtkPiNum(pNtk2) ); matchedOutputs1 = Vec_IntAlloc( Abc_NtkPoNum(pNtk1) ); matchedOutputs2 = Vec_IntAlloc( Abc_NtkPoNum(pNtk2) ); nodesInLevel1 = ABC_ALLOC( Vec_Ptr_t *, Abc_AigLevel( pNtk1 ) + 1); // why numOfLevels+1? because the inputs are in level 0 for(i = 0; i <= Abc_AigLevel( pNtk1 ); i++) nodesInLevel1[i] = Vec_PtrAlloc( 20 ); // bucket sort the objects based on their levels Abc_AigForEachAnd( pNtk1, pObj, i ) Vec_PtrPush(nodesInLevel1[Abc_ObjLevel(pObj)], pObj); nodesInLevel2 = ABC_ALLOC( Vec_Ptr_t *, Abc_AigLevel( pNtk2 ) + 1); // why numOfLevels+1? because the inputs are in level 0 for(i = 0; i <= Abc_AigLevel( pNtk2 ); i++) nodesInLevel2[i] = Vec_PtrAlloc( 20 ); // bucket sort the objects based on their levels Abc_AigForEachAnd( pNtk2, pObj, i ) Vec_PtrPush(nodesInLevel2[Abc_ObjLevel(pObj)], pObj); oMatchedGroups = Vec_IntAlloc( 10 ); for(i = 0; i < *iLastItem1; i++) { if(Vec_IntSize(iMatch1[i]) == 1) { Vec_IntPush(matchedInputs1, Vec_IntEntryLast(iMatch1[i])); Vec_IntPush(matchedInputs2, Vec_IntEntryLast(iMatch2[i])); } else Vec_IntPush(iNonSingleton, i); } for(i = 0; i < *oLastItem1; i++) { if(Vec_IntSize(oMatch1[i]) == 1) { Vec_IntPush(matchedOutputs1, Vec_IntEntryLast(oMatch1[i])); Vec_IntPush(matchedOutputs2, Vec_IntEntryLast(oMatch2[i])); } } for(i = 0; i < Vec_IntSize(iNonSingleton) - 1; i++) { for(j = i + 1; j < Vec_IntSize(iNonSingleton); j++) if( observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, j)], 0)] > observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, i)], 0)] ) { int temp = Vec_IntEntry(iNonSingleton, i); Vec_IntWriteEntry( iNonSingleton, i, Vec_IntEntry(iNonSingleton, j) ); Vec_IntWriteEntry( iNonSingleton, j, temp ); } else if( observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, j)], 0)] == observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, i)], 0)] ) { if( Vec_IntSize(iMatch2[Vec_IntEntry(iNonSingleton, j)]) < Vec_IntSize(iMatch2[Vec_IntEntry(iNonSingleton, i)]) ) { int temp = Vec_IntEntry(iNonSingleton, i); Vec_IntWriteEntry( iNonSingleton, i, Vec_IntEntry(iNonSingleton, j) ); Vec_IntWriteEntry( iNonSingleton, j, temp ); } } } /*for(i = 0; i < Vec_IntSize(iNonSingleton) - 1; i++) { for(j = i + 1; j < Vec_IntSize(iNonSingleton); j++) if( Vec_IntSize(oDep2[oGroup2[Vec_IntEntryLast(iMatch2[Vec_IntEntry(iNonSingleton, j)])]]) > Vec_IntSize(oDep2[oGroup2[Vec_IntEntryLast(iMatch2[Vec_IntEntry(iNonSingleton, i)])]]) ) { int temp = Vec_IntEntry(iNonSingleton, i); Vec_IntWriteEntry( iNonSingleton, i, Vec_IntEntry(iNonSingleton, j) ); Vec_IntWriteEntry( iNonSingleton, j, temp ); } else if( Vec_IntSize(oDep2[oGroup2[Vec_IntEntryLast(iMatch2[Vec_IntEntry(iNonSingleton, j)])]]) == Vec_IntSize(oDep2[oGroup2[Vec_IntEntryLast(iMatch2[Vec_IntEntry(iNonSingleton, i)])]]) ) { if( observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, j)], 0)] > observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, i)], 0)] ) { int temp = Vec_IntEntry(iNonSingleton, i); Vec_IntWriteEntry( iNonSingleton, i, Vec_IntEntry(iNonSingleton, j) ); Vec_IntWriteEntry( iNonSingleton, j, temp ); } } }*/ matchFound = match1by1(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, 0, 0); if( matchFound && Vec_IntSize(matchedOutputs1) != Abc_NtkPoNum(pNtk1) ) { Vec_Int_t * oNonSingleton; Vec_Ptr_t * oMatchPairs; Abc_Ntk_t * subNtk1, * subNtk2; oNonSingleton = Vec_IntAlloc( 10 ); oMatchPairs = Vec_PtrAlloc(Abc_NtkPoNum(pNtk1) * 2); for(i = 0; i < *oLastItem1; i++) if( Vec_IntSize(oMatch1[i]) > 1 && Vec_IntFind( oMatchedGroups, i) == -1 ) Vec_IntPush(oNonSingleton, i); subNtk1 = computeCofactor(pNtk1, nodesInLevel1, NULL, matchedInputs1); subNtk2 = computeCofactor(pNtk2, nodesInLevel2, NULL, matchedInputs2); matchFound = matchNonSingletonOutputs(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup1, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, NULL, subNtk1, subNtk2, oMatchPairs, oNonSingleton, 0, 0, 0, 0); Vec_IntFree( oNonSingleton ); Vec_PtrFree( oMatchPairs ); Abc_NtkDelete(subNtk1); Abc_NtkDelete(subNtk2); } satTime = (float)(Abc_Clock() - clk)/(float)(CLOCKS_PER_SEC); if( matchFound ) { checkEquivalence( pNtk1, matchedInputs1, matchedOutputs1, pNtk2, matchedInputs2, matchedOutputs2); result = fopen("IOmatch.txt", "w"); fprintf(result, "I/O = %d / %d \n\n", Abc_NtkPiNum(pNtk1), Abc_NtkPoNum(pNtk1)); for(i = 0; i < Vec_IntSize(matchedInputs1) ; i++) fprintf(result, "{%s}\t{%s}\n", Abc_ObjName(Abc_NtkPi(pNtk1, Vec_IntEntry(matchedInputs1, i))), Abc_ObjName(Abc_NtkPi(pNtk2, Vec_IntEntry(matchedInputs2, i))) ); fprintf(result, "\n-----------------------------------------\n"); for(i = 0; i < Vec_IntSize(matchedOutputs1) ; i++) fprintf(result, "{%s}\t{%s}\n", Abc_ObjName(Abc_NtkPo(pNtk1, Vec_IntEntry(matchedOutputs1, i))), Abc_ObjName(Abc_NtkPo(pNtk2, Vec_IntEntry(matchedOutputs2, i))) ); fclose( result ); } Vec_IntFree( matchedInputs1 ); Vec_IntFree( matchedInputs2 ); Vec_IntFree( matchedOutputs1 ); Vec_IntFree( matchedOutputs2 ); Vec_IntFree( iNonSingleton ); Vec_IntFree( oMatchedGroups ); for(i = 0; i <= Abc_AigLevel( pNtk1 ); i++) Vec_PtrFree( nodesInLevel1[i] ); for(i = 0; i <= Abc_AigLevel( pNtk2 ); i++) Vec_PtrFree( nodesInLevel2[i] ); ABC_FREE( nodesInLevel1 ); ABC_FREE( nodesInLevel2 ); /*fclose(matchFile);*/ return satTime; } int checkListConsistency(Vec_Int_t ** iMatch1, Vec_Int_t ** oMatch1, Vec_Int_t ** iMatch2, Vec_Int_t ** oMatch2, int iLastItem1, int oLastItem1, int iLastItem2, int oLastItem2) { //int i; if(iLastItem1 != iLastItem2 || oLastItem1 != oLastItem2) return FALSE; /*for(i = 0; i < iLastItem1; i++) { if(Vec_IntSize(iMatch1[i]) != Vec_IntSize(iMatch2[i])) return FALSE; } for(i = 0; i < oLastItem1; i++) { if(Vec_IntSize(oMatch1[i]) != Vec_IntSize(oMatch2[i])) return FALSE; }*/ return TRUE; } void bmGateWay( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int p_equivalence ) { Vec_Int_t ** iDep1, ** oDep1; Vec_Int_t ** iDep2, ** oDep2; Vec_Int_t ** iMatch1, ** oMatch1; Vec_Int_t ** iMatch2, ** oMatch2; int * iGroup1, * oGroup1; int * iGroup2, * oGroup2; int iLastItem1, oLastItem1; int iLastItem2, oLastItem2; int i, j; char * vPiValues1, * vPiValues2; int * observability1, * observability2; abctime clk = Abc_Clock(); float initTime; float simulTime; float satTime; Vec_Ptr_t ** topOrder1 = NULL, ** topOrder2 = NULL; extern void getDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep); extern void initMatchList(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep, Vec_Int_t** iMatch, int* iLastItem, Vec_Int_t** oMatch, int* oLastItem, int* iGroup, int* oGroup, int p_equivalence); extern void iSortDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, int* oGroup); extern void oSortDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** oDep, int* iGroup); extern int iSplitByDep(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** iMatch, int* iGroup, int* iLastItem, int* oGroup); extern int oSplitByDep(Abc_Ntk_t *pNtk, Vec_Int_t** oDep, Vec_Int_t** oMatch, int* oGroup, int* oLastItem, int* iGroup); extern Vec_Ptr_t ** findTopologicalOrder(Abc_Ntk_t * pNtk); extern int refineIOBySimulation(Abc_Ntk_t *pNtk, Vec_Int_t** iMatch, int* iLastItem, int * iGroup, Vec_Int_t** iDep, Vec_Int_t** oMatch, int* oLastItem, int * oGroup, Vec_Int_t** oDep, char * vPiValues, int * observability, Vec_Ptr_t ** topOrder); extern float refineBySAT(Abc_Ntk_t * pNtk1, Vec_Int_t ** iMatch1, int * iGroup1, Vec_Int_t ** iDep1, int* iLastItem1, Vec_Int_t ** oMatch1, int * oGroup1, Vec_Int_t ** oDep1, int* oLastItem1, int * observability1, Abc_Ntk_t * pNtk2, Vec_Int_t ** iMatch2, int * iGroup2, Vec_Int_t ** iDep2, int* iLastItem2, Vec_Int_t ** oMatch2, int * oGroup2, Vec_Int_t ** oDep2, int* oLastItem2, int * observability2); int checkListConsistency(Vec_Int_t ** iMatch1, Vec_Int_t ** oMatch1, Vec_Int_t ** iMatch2, Vec_Int_t ** oMatch2, int iLastItem1, int oLastItem1, int iLastItem2, int oLastItem2); iDep1 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPiNum(pNtk1) ); oDep1 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPoNum(pNtk1) ); iDep2 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPiNum(pNtk2) ); oDep2 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPoNum(pNtk2) ); iMatch1 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPiNum(pNtk1) ); oMatch1 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPoNum(pNtk1) ); iMatch2 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPiNum(pNtk2) ); oMatch2 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPoNum(pNtk2) ); iGroup1 = ABC_ALLOC( int, Abc_NtkPiNum(pNtk1) ); oGroup1 = ABC_ALLOC( int, Abc_NtkPoNum(pNtk1) ); iGroup2 = ABC_ALLOC( int, Abc_NtkPiNum(pNtk2) ); oGroup2 = ABC_ALLOC( int, Abc_NtkPoNum(pNtk2) ); vPiValues1 = ABC_ALLOC( char, Abc_NtkPiNum(pNtk1) + 1); vPiValues1[Abc_NtkPiNum(pNtk1)] = '\0'; vPiValues2 = ABC_ALLOC( char, Abc_NtkPiNum(pNtk2) + 1); vPiValues2[Abc_NtkPiNum(pNtk2)] = '\0'; observability1 = ABC_ALLOC(int, (unsigned)Abc_NtkPiNum(pNtk1)); observability2 = ABC_ALLOC(int, (unsigned)Abc_NtkPiNum(pNtk2)); for(i = 0; i < Abc_NtkPiNum(pNtk1); i++) { iDep1[i] = Vec_IntAlloc( 1 ); iMatch1[i] = Vec_IntAlloc( 1 ); iDep2[i] = Vec_IntAlloc( 1 ); iMatch2[i] = Vec_IntAlloc( 1 ); vPiValues1[i] = '0'; vPiValues2[i] = '0'; observability1[i] = 0; observability2[i] = 0; } for(i = 0; i < Abc_NtkPoNum(pNtk1); i++) { oDep1[i] = Vec_IntAlloc( 1 ); oMatch1[i] = Vec_IntAlloc( 1 ); oDep2[i] = Vec_IntAlloc( 1 ); oMatch2[i] = Vec_IntAlloc( 1 ); } /************* Strashing ************/ pNtk1 = Abc_NtkStrash( pNtk1, 0, 0, 0 ); pNtk2 = Abc_NtkStrash( pNtk2, 0, 0, 0 ); printf("Network strashing is done!\n"); /************************************/ /******* Getting Dependencies *******/ getDependencies(pNtk1, iDep1, oDep1); getDependencies(pNtk2, iDep2, oDep2); printf("Getting dependencies is done!\n"); /************************************/ /***** Intializing match lists ******/ initMatchList(pNtk1, iDep1, oDep1, iMatch1, &iLastItem1, oMatch1, &oLastItem1, iGroup1, oGroup1, p_equivalence); initMatchList(pNtk2, iDep2, oDep2, iMatch2, &iLastItem2, oMatch2, &oLastItem2, iGroup2, oGroup2, p_equivalence); printf("Initializing match lists is done!\n"); /************************************/ if( !checkListConsistency(iMatch1, oMatch1, iMatch2, oMatch2, iLastItem1, oLastItem1, iLastItem2, oLastItem2) ) { fprintf( stdout, "I/O dependencies of two circuits are different.\n"); goto freeAndExit; } printf("Refining IOs by dependencies ..."); // split match lists further by checking dependencies do { int iNumOfItemsAdded = 1, oNumOfItemsAdded = 1; do { if( oNumOfItemsAdded ) { iSortDependencies(pNtk1, iDep1, oGroup1); iSortDependencies(pNtk2, iDep2, oGroup2); } if( iNumOfItemsAdded ) { oSortDependencies(pNtk1, oDep1, iGroup1); oSortDependencies(pNtk2, oDep2, iGroup2); } if( iLastItem1 < Abc_NtkPiNum(pNtk1) ) { iSplitByDep(pNtk1, iDep1, iMatch1, iGroup1, &iLastItem1, oGroup1); if( oLastItem1 < Abc_NtkPoNum(pNtk1) ) oSplitByDep(pNtk1, oDep1, oMatch1, oGroup1, &oLastItem1, iGroup1); } if( iLastItem2 < Abc_NtkPiNum(pNtk2) ) { iNumOfItemsAdded = iSplitByDep(pNtk2, iDep2, iMatch2, iGroup2, &iLastItem2, oGroup2); if( oLastItem2 < Abc_NtkPoNum(pNtk2) ) oNumOfItemsAdded = oSplitByDep(pNtk2, oDep2, oMatch2, oGroup2, &oLastItem2, iGroup2); else oNumOfItemsAdded = 0; } else iNumOfItemsAdded = 0; if(!checkListConsistency(iMatch1, oMatch1, iMatch2, oMatch2, iLastItem1, oLastItem1, iLastItem2, oLastItem2)) { fprintf( stdout, "I/O dependencies of two circuits are different.\n"); goto freeAndExit; } }while(iNumOfItemsAdded != 0 || oNumOfItemsAdded != 0); }while(0); printf(" done!\n"); initTime = ((float)(Abc_Clock() - clk)/(float)(CLOCKS_PER_SEC)); clk = Abc_Clock(); topOrder1 = findTopologicalOrder(pNtk1); topOrder2 = findTopologicalOrder(pNtk2); printf("Refining IOs by simulation ..."); do { int counter = 0; int ioSuccess1, ioSuccess2; do { for(i = 0; i < iLastItem1; i++) { int temp = (int)(SIM_RANDOM_UNSIGNED % 2); if(Vec_IntSize(iMatch1[i]) != Vec_IntSize(iMatch2[i])) { fprintf( stdout, "Input refinement by simulation finds two circuits different.\n"); goto freeAndExit; } for(j = 0; j < Vec_IntSize(iMatch1[i]); j++) { vPiValues1[Vec_IntEntry(iMatch1[i], j)] = temp + '0'; vPiValues2[Vec_IntEntry(iMatch2[i], j)] = temp + '0'; } } ioSuccess1 = refineIOBySimulation(pNtk1, iMatch1, &iLastItem1, iGroup1, iDep1, oMatch1, &oLastItem1, oGroup1, oDep1, vPiValues1, observability1, topOrder1); ioSuccess2 = refineIOBySimulation(pNtk2, iMatch2, &iLastItem2, iGroup2, iDep2, oMatch2, &oLastItem2, oGroup2, oDep2, vPiValues2, observability2, topOrder2); if(ioSuccess1 && ioSuccess2) counter = 0; else counter++; if(ioSuccess1 != ioSuccess2 || !checkListConsistency(iMatch1, oMatch1, iMatch2, oMatch2, iLastItem1, oLastItem1, iLastItem2, oLastItem2)) { fprintf( stdout, "Input refinement by simulation finds two circuits different.\n"); goto freeAndExit; } }while(counter <= 200); }while(0); printf(" done!\n"); simulTime = (float)(Abc_Clock() - clk)/(float)(CLOCKS_PER_SEC); printf("SAT-based search started ...\n"); satTime = refineBySAT(pNtk1, iMatch1, iGroup1, iDep1, &iLastItem1, oMatch1, oGroup1, oDep1, &oLastItem1, observability1, pNtk2, iMatch2, iGroup2, iDep2, &iLastItem2, oMatch2, oGroup2, oDep2, &oLastItem2, observability2); printf( "Init Time = %4.2f\n", initTime ); printf( "Simulation Time = %4.2f\n", simulTime ); printf( "SAT Time = %4.2f\n", satTime ); printf( "Overall Time = %4.2f\n", initTime + simulTime + satTime ); freeAndExit: for(i = 0; i < iLastItem1 ; i++) { Vec_IntFree( iMatch1[i] ); Vec_IntFree( iMatch2[i] ); } for(i = 0; i < oLastItem1 ; i++) { Vec_IntFree( oMatch1[i] ); Vec_IntFree( oMatch2[i] ); } for(i = 0; i < Abc_NtkPiNum(pNtk1); i++) { Vec_IntFree( iDep1[i] ); Vec_IntFree( iDep2[i] ); if(topOrder1 != NULL) { Vec_PtrFree( topOrder1[i] ); Vec_PtrFree( topOrder2[i] ); } } for(i = 0; i < Abc_NtkPoNum(pNtk1); i++) { Vec_IntFree( oDep1[i] ); Vec_IntFree( oDep2[i] ); } ABC_FREE( iMatch1 ); ABC_FREE( iMatch2 ); ABC_FREE( oMatch1 ); ABC_FREE( oMatch2 ); ABC_FREE( iDep1 ); ABC_FREE( iDep2 ); ABC_FREE( oDep1 ); ABC_FREE( oDep2 ); ABC_FREE( iGroup1 ); ABC_FREE( iGroup2 ); ABC_FREE( oGroup1 ); ABC_FREE( oGroup2 ); ABC_FREE( vPiValues1 ); ABC_FREE( vPiValues2 ); ABC_FREE( observability1 ); ABC_FREE( observability2 ); if(topOrder1 != NULL) { ABC_FREE( topOrder1 ); ABC_FREE( topOrder2 ); } }ABC_NAMESPACE_IMPL_END