From 0fab82384ae80105885c7adedfd5c6f675c5cce8 Mon Sep 17 00:00:00 2001 From: lyj1201 <1609595919@qq.com> Date: Mon, 14 Aug 2023 12:04:33 -0600 Subject: [PATCH 001/151] add AIG random synthesis based RTL argumentation; command = aigarg --- src/base/abci/abc.c | 167 ++++++++++++++++ src/base/abci/abcOrchestration.c | 321 ++++++++++++++++++++++++++++++- 2 files changed, 484 insertions(+), 4 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 0ff8a6f34..6e99d7481 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -164,6 +164,7 @@ static int Abc_CommandAllExact ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandTestExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMajGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandOrchestrate ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAIGArgumentation ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -917,6 +918,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "faultclasses", Abc_CommandFaultClasses, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "exact", Abc_CommandExact, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "orchestrate", Abc_CommandOrchestrate, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "aigarg", Abc_CommandAIGArgumentation, 1 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_start", Abc_CommandBmsStart, 0 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_stop", Abc_CommandBmsStop, 0 ); @@ -7534,6 +7536,171 @@ usage: } +/**Function************************************************************* + + Synopsis [] + + Description [AIG RTL Argumentation] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAIGArgumentation( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pDup; + int c, RetValue; + int nNodeSizeMax; + int nConeSizeMax; + int fUpdateLevel; + int fUseZeros_rwr; + int fUseZeros_ref; + int fUseDcs; + int fVerbose; + int RS_CUT_MIN = 4; + int RS_CUT_MAX = 16; + + int fPrecompute; + int fPlaceEnable; + int nNodesMax; + int nCutsMax; + int nLevelsOdc; + int fVeryVerbose; + int Rand_Seed; + //int sOpsOrder; + size_t NtkSize; + char *DecisionFile; + //FILE *maskFile; + extern void Rwr_Precompute(); + extern int Abc_NtkOrchRand( Abc_Ntk_t * pNtk, Vec_Int_t **pGain_rwr, Vec_Int_t **pGain_res,Vec_Int_t **pGain_ref, Vec_Int_t **DecisionMask, char *DecisionFile, int Rand_Seed, int fUseZeros_rwr, int fUseZeros_ref, int fPlaceEnable, int nCutsMax, int nNodesMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose, int nNodeSizeMax, int nConeSizeMax, int fUseDcs ); + // set defaults + nNodeSizeMax = 10; + nConeSizeMax = 16; + fUpdateLevel = 1; + fUseZeros_rwr = 0; + fUseZeros_ref = 0; + fUseDcs = 0; + fVerbose = 0; + fVeryVerbose = 0; + fPlaceEnable = 0; + fPrecompute = 0; + nCutsMax = 8; + nNodesMax = 1; + nLevelsOdc = 0; + Rand_Seed = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "zZdsh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + break; + case 'z': + fUseZeros_rwr ^= 1; + break; + case 'Z': + fUseZeros_ref ^= 1; + break; + case 'd': + if ( globalUtilOptind >= argc ) + { + goto usage; + } + DecisionFile = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 's': + if ( globalUtilOptind >= argc ) + { + goto usage; + } + Rand_Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + } + } + if ( fPrecompute ) + { + Rwr_Precompute(); + return 0; + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( nCutsMax < RS_CUT_MIN || nCutsMax > RS_CUT_MAX ) + { + Abc_Print( -1, "Can only compute cuts for %d <= K <= %d.\n", RS_CUT_MIN, RS_CUT_MAX ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + if ( nNodeSizeMax > 15 ) + { + Abc_Print( -1, "The cone size cannot exceed 15.\n" ); + return 1; + } + + if ( fUseDcs && nNodeSizeMax >= nConeSizeMax ) + { + Abc_Print( -1, "For don't-care to work, containing cone should be larger than collapsed node.\n" ); + return 1; + } + NtkSize = Abc_NtkObjNumMax(pNtk); + + + + Vec_Int_t *DecisionMask = Vec_IntAlloc(1); + for (int i=0; inSize, DecisionList->pArray[0]); + if ( RetValue == -1 ) + { + Abc_FrameReplaceCurrentNetwork( pAbc, pDup ); + printf( "An error occurred during computation. The original network is restored.\n" ); + } + else + { + Abc_NtkDelete( pDup ); + if ( RetValue == 0 ) + { + Abc_Print( 0, "Orchestration evaluation for RL has failed.\n" ); + return 1; + } + } + // Vec_IntPrint(pGain_rwr); + return 0; + +usage: + Abc_Print( -2, "usage: aigarg [-s ] [-d ][-zZdsh]\n" ); + Abc_Print( -2, "\t performs technology-independent AIG random synthesis (node level) for RTL argumentation\n" ); + Abc_Print( -2, "\t-z : toggle using zero-cost replacements for rwr for aigarg [default = %s]\n", fUseZeros_rwr? "yes": "no" ); + Abc_Print( -2, "\t-Z : toggle using zero-cost replacements for ref for aigarg [default = %s]\n", fUseZeros_ref? "yes": "no" ); + Abc_Print( -2, "\t-d : record random synthesis decision made during argumentation [required filename; e.g., test.csv]\n"); + Abc_Print( -2, "\t-s : set the random seed for random argumentation\n"); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tExample : read i10.aig;st;aigarg -s 1 -d test.csv;write i10_arg_1.aig;cec i10.aig i10_arg_1.aig\n"); + return 1; +} diff --git a/src/base/abci/abcOrchestration.c b/src/base/abci/abcOrchestration.c index fe83891ec..af36939dd 100644 --- a/src/base/abci/abcOrchestration.c +++ b/src/base/abci/abcOrchestration.c @@ -198,7 +198,7 @@ Rwr_ManAddTimeCuts( pManRwr, Abc_Clock() - clk ); pManRwr->nNodesBeg = Abc_NtkNodeNum(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); - printf("nNodes: %d\n", nNodes); + //printf("nNodes: %d\n", nNodes); if ( pGain_rw ) *pGain_rw = Vec_IntAlloc(1); pProgress = Extra_ProgressBarStart( stdout, nNodes ); @@ -489,7 +489,7 @@ int Abc_NtkRefactor3( Abc_Ntk_t * pNtk, Vec_Int_t **pGain_ref, int nNodeSizeMax, Abc_NtkStartReverseLevels( pNtk, 0 ); pManRef->nNodesBeg = Abc_NtkNodeNum(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); - printf("nNodes: %d\n", nNodes); + //printf("nNodes: %d\n", nNodes); if (pGain_ref) *pGain_ref = Vec_IntAlloc(1); pProgress = Extra_ProgressBarStart( stdout, nNodes ); @@ -605,7 +605,7 @@ int Abc_NtkResubstitute3( Abc_Ntk_t * pNtk, Vec_Int_t **pGain_res, int nCutMax, // resynthesize each node once pManRes->nNodesBeg = Abc_NtkNodeNum(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); - printf("nNodes: %d\n", nNodes); + //printf("nNodes: %d\n", nNodes); if (pGain_res) *pGain_res = Vec_IntAlloc(1); pProgress = Extra_ProgressBarStart( stdout, nNodes ); @@ -2732,7 +2732,7 @@ Rwr_ManAddTimeCuts( pManRwr, Abc_Clock() - clk ); pManRef->nNodesBeg = Abc_NtkNodeNum(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); - printf("nNodes: %d\n", nNodes); + //printf("nNodes: %d\n", nNodes); if (pGain_res) *pGain_res = Vec_IntAlloc(1); if (pGain_ref) *pGain_ref = Vec_IntAlloc(1); if (pGain_rwr) *pGain_rwr = Vec_IntAlloc(1); @@ -5318,6 +5318,319 @@ s_ResubTime = Abc_Clock() - clkStart; return 1; } +// orchestration with sudo random decision list +int Abc_NtkOrchRand( Abc_Ntk_t * pNtk, Vec_Int_t **pGain_rwr, Vec_Int_t **pGain_res,Vec_Int_t **pGain_ref, Vec_Int_t **DecisionMask, char * DecisionFile, int Rand_Seed, int fUseZeros_rwr, int fUseZeros_ref, int fPlaceEnable, int nCutMax, int nStepsMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose, int nNodeSizeMax, int nConeSizeMax, int fUseDcs ) +{ + extern int Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); + ProgressBar * pProgress; + // For resub + Abc_ManRes_t * pManRes; + Abc_ManCut_t * pManCutRes; + Odc_Man_t * pManOdc = NULL; + Dec_Graph_t * pFFormRes; + Vec_Ptr_t * vLeaves; + // For rewrite + Cut_Man_t * pManCutRwr; + Rwr_Man_t * pManRwr; + Dec_Graph_t * pGraph; + // For refactor + Abc_ManRef_t * pManRef; + Abc_ManCut_t * pManCutRef; + Dec_Graph_t * pFFormRef; + Vec_Ptr_t * vFanins; + + Abc_Obj_t * pNode; + FILE *fpt; + abctime clk, clkStart = Abc_Clock(); + int i, nNodes, nNodes_after, nGain, fCompl; + int RetValue = 1; + int ops_rwr = 0; + int ops_res = 0; + int ops_ref = 0; + int ops_null = 0; + int Valid_Len = 0; + //Vec_Int_t *Valid_Ops; + + //clock_t begin= clock(); + assert( Abc_NtkIsStrash(pNtk) ); + + // cleanup the AIG + Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc); + + // start the managers resub + pManCutRes = Abc_NtkManCutStart( nCutMax, 100000, 100000, 100000 ); + pManRes = Abc_ManResubStart( nCutMax, ABC_RS_DIV1_MAX ); + if ( nLevelsOdc > 0 ) + pManOdc = Abc_NtkDontCareAlloc( nCutMax, nLevelsOdc, fVerbose, fVeryVerbose ); + // start the managers refactor + pManCutRef = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, 1000 ); + pManRef = Abc_NtkManRefStart_1( nNodeSizeMax, nConeSizeMax, fUseDcs, fVerbose ); + pManRef->vLeaves = Abc_NtkManCutReadCutLarge( pManCutRef ); + // start the managers rewrite + pManRwr = Rwr_ManStart( 0 ); + if ( pManRwr == NULL ) + return 0; + + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Abc_NtkStartReverseLevels( pNtk, 0 ); + + // 'Resub only' + + if ( Abc_NtkLatchNum(pNtk) ) { + Abc_NtkForEachLatch(pNtk, pNode, i) + pNode->pNext = (Abc_Obj_t *)pNode->pData; + } + + // cut manager for rewrite +clk = Abc_Clock(); + pManCutRwr = Abc_NtkStartCutManForRewrite( pNtk ); +Rwr_ManAddTimeCuts( pManRwr, Abc_Clock() - clk ); + pNtk->pManCut = pManCutRwr; + + if ( fVeryVerbose ) + Rwr_ScoresClean( pManRwr ); + + // resynthesize each node once + // resub + pManRes->nNodesBeg = Abc_NtkNodeNum(pNtk); + // rewrite + pManRwr->nNodesBeg = Abc_NtkNodeNum(pNtk); + // refactor + pManRef->nNodesBeg = Abc_NtkNodeNum(pNtk); + +//clock_t resyn_end=clock(); +//double resyn_time_spent = (double)(resyn_end-begin)/CLOCKS_PER_SEC; +//printf("time %f\n", resyn_time_spent); + nNodes = Abc_NtkObjNumMax(pNtk); + //printf("nNodes: %d\n", nNodes); + //for(int i=0; i < nNodes; i++){printf("mask check: %d\n", (*DecisionMask)->pArray[i]);} + //printf("mask size:%d", (**DecisionMask).nSize); + if (pGain_res) *pGain_res = Vec_IntAlloc(1); + if (pGain_ref) *pGain_ref = Vec_IntAlloc(1); + if (pGain_rwr) *pGain_rwr = Vec_IntAlloc(1); + Vec_Int_t *Valid_Ops = Vec_IntAlloc(1); + + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + fpt = fopen(DecisionFile, "w"); + + Abc_NtkForEachNode( pNtk, pNode, i ) + { + //printf("Ochestration id: %d\n", pNode->Id); + int iterNode = pNode->Id; + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // skip the constant node +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // stop if all nodes have been tried once + if ( i >= nNodes ) + break; + // skip persistant nodes + if ( Abc_NodeIsPersistant(pNode) ) + { + //fprintf(fpt, "%d, %s, %d\n", pNode->Id, "None" , -99); + Vec_IntPush((*pGain_res), -99); + Vec_IntPush((*pGain_ref), -99); + Vec_IntPush((*pGain_rwr), -99); + continue; + } + // skip the nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > 1000 ) + { + //fprintf(fpt, "%d, %s, %d\n", pNode->Id,"None", -99); + Vec_IntPush((*pGain_res), -99); + Vec_IntPush((*pGain_ref), -99); + Vec_IntPush((*pGain_rwr), -99); + continue; + } +clk = Abc_Clock(); + +// Generate random operation +// check transformability of all three operations + Vec_IntPush( (Valid_Ops), -1); + nGain = Rwr_NodeRewrite( pManRwr, pManCutRwr, pNode, fUpdateLevel, fUseZeros_rwr, fPlaceEnable ); + Vec_IntPush( (*pGain_rwr), nGain); + if (nGain > 0 || (nGain == 0 && fUseZeros_rwr)) + { + Vec_IntPush( (Valid_Ops), 0); + } + vLeaves = Abc_NodeFindCut( pManCutRes, pNode, 0 ); + pManRes->timeCut += Abc_Clock() - clk; + if ( pManOdc ) + { +clk = Abc_Clock(); + Abc_NtkDontCareClear( pManOdc ); + Abc_NtkDontCareCompute( pManOdc, pNode, vLeaves, pManRes->pCareSet ); +pManRes->timeTruth += Abc_Clock() - clk; + } +clk = Abc_Clock(); + pFFormRes = Abc_ManResubEval( pManRes, pNode, vLeaves, nStepsMax, fUpdateLevel, fVerbose ); +pManRes->timeRes += Abc_Clock() - clk; + Vec_IntPush((*pGain_res), pManRes->nLastGain); + if (pManRes->nLastGain > 0) + { + if ( pFFormRes != NULL ){ + Vec_IntPush( (Valid_Ops), 1); + } + } + + vFanins = Abc_NodeFindCut( pManCutRef, pNode, fUseDcs ); +pManRef->timeCut += Abc_Clock() - clk; +clk = Abc_Clock(); + pFFormRef = Abc_NodeRefactor_1( pManRef, pNode, vFanins, fUpdateLevel, fUseZeros_ref, fUseDcs, fVerbose ); +pManRef->timeRes += Abc_Clock() - clk; + + Vec_IntPush((*pGain_ref), pManRef->nLastGain); + if (pManRef->nLastGain > 0 || (pManRef->nLastGain ==0 && fUseZeros_ref)) + { + if ( pFFormRef != NULL ){ + Vec_IntPush( (Valid_Ops), 2); + } + } + Valid_Len = (Valid_Ops)->nSize; + //printf("The length of valid operations: %d\n", Valid_Len); + +//Pick a random operations from valid ones +if (Rand_Seed == -1) +{ + srand(time(NULL)); +} +else +{ + srand(Rand_Seed); +} + +int r = rand() % Valid_Len; + + if ((Valid_Ops)->pArray[r] == -1){ + (*DecisionMask)->pArray[iterNode] = -1; + ops_null++; + Vec_IntZero(Valid_Ops); // reset updates + continue; + } + else if ((Valid_Ops->pArray[r]) == 0){ + // apply rewrite + pGraph = (Dec_Graph_t *)Rwr_ManReadDecs(pManRwr); + fCompl = Rwr_ManReadCompl(pManRwr); + if ( fPlaceEnable ) + Abc_AigUpdateReset( (Abc_Aig_t *)pNtk->pManFunc ); + if ( fCompl ) Dec_GraphComplement( pGraph ); +clk = Abc_Clock(); + Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, nGain ); +Rwr_ManAddTimeUpdate( pManRwr, Abc_Clock() - clk ); + if ( fCompl ) Dec_GraphComplement( pGraph ); + (*DecisionMask)->pArray[iterNode] = 0; + ops_rwr++; + Vec_IntZero(Valid_Ops); // reset updates + continue; + } + else if ((Valid_Ops->pArray[r] == 1)){ + // apply res + pManRes->nTotalGain += pManRes->nLastGain; +clk = Abc_Clock(); + Dec_GraphUpdateNetwork( pNode, pFFormRes, fUpdateLevel, pManRes->nLastGain ); +pManRes->timeNtk += Abc_Clock() - clk; + Dec_GraphFree( pFFormRes ); + (*DecisionMask)->pArray[iterNode] = 1; + ops_res++; + Vec_IntZero(Valid_Ops); // reset updates + continue; + } + else if ((Valid_Ops->pArray[r] == 2)){ +clk = Abc_Clock(); + if ( !Dec_GraphUpdateNetwork( pNode, pFFormRef, fUpdateLevel, pManRef->nLastGain ) ) + { + Dec_GraphFree( pFFormRef ); + RetValue = -1; + break; + } +pManRef->timeNtk += Abc_Clock() - clk; + Dec_GraphFree( pFFormRef ); + (*DecisionMask)->pArray[iterNode] = 2; + ops_ref++; + Vec_IntZero(Valid_Ops); // reset updates + continue; + } + } + //fwrite((**DecisionMask).pArray, sizeof(int), sizeof((**DecisionMask).pArray), fpt); + for (int i = 0; i < (nNodes); i++){ + fprintf(fpt, "%d\n", (*DecisionMask)->pArray[i]);} + fclose(fpt); +/* + printf("size of vector %d\n", Valid_Len); + printf("Nodes with rewrite: %d\n", ops_rwr); + printf("Nodes with resub: %d\n", ops_res); + printf("Nodes with refactor: %d\n", ops_ref); + printf("Nodes without updates: %d\n", ops_null); +*/ + Extra_ProgressBarStop( pProgress ); +// Rewrite +Rwr_ManAddTimeTotal( pManRwr, Abc_Clock() - clkStart ); + pManRwr->nNodesEnd = Abc_NtkNodeNum(pNtk); + +// Resub +pManRes->timeTotal = Abc_Clock() - clkStart; + pManRes->nNodesEnd = Abc_NtkNodeNum(pNtk); + +// Refactor +pManRef->timeTotal = Abc_Clock() - clkStart; + pManRef->nNodesEnd = Abc_NtkNodeNum(pNtk); + + // print statistics + if ( fVerbose ){ + Abc_ManResubPrint( pManRes ); + Rwr_ManPrintStats( pManRwr ); + Abc_NtkManRefPrintStats_1( pManRef ); + } + if ( fVeryVerbose ) + Rwr_ScoresReport( pManRwr ); + // delete the managers + // resub + Abc_ManResubStop( pManRes ); + Abc_NtkManCutStop( pManCutRes ); + // rewrite + Rwr_ManStop( pManRwr ); + Cut_ManStop( pManCutRwr ); + pNtk->pManCut = NULL; + // refactor + Abc_NtkManCutStop( pManCutRef ); + Abc_NtkManRefStop_1( pManRef ); + + if ( pManOdc ) Abc_NtkDontCareFree( pManOdc ); + + // clean the data field + Abc_NtkForEachObj( pNtk, pNode, i ) + pNode->pData = NULL; + + if ( Abc_NtkLatchNum(pNtk) ) { + Abc_NtkForEachLatch(pNtk, pNode, i) + pNode->pData = pNode->pNext, pNode->pNext = NULL; + } + + // put the nodes into the DFS order and reassign their IDs + Abc_NtkReassignIds( pNtk ); +// Abc_AigCheckFaninOrder( pNtk->pManFunc ); + + // fix the levels + if ( fUpdateLevel ) + Abc_NtkStopReverseLevels( pNtk ); + else + Abc_NtkLevel( pNtk ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkOchestraction: The network check has failed.\n" ); + return 0; + } + nNodes_after = Abc_NtkObjNumMax(pNtk); + //printf("nNodes after optimization: %d\n", nNodes_after); +//s_ResubTime = Abc_Clock() - clkStart; +//clock_t end=clock(); +//double time_spent = (double)(end-begin)/CLOCKS_PER_SEC; +//printf("time %f\n", time_spent); + return 1; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// From 0fe977a33c422bd0957527efa3ee1cbec384222b Mon Sep 17 00:00:00 2001 From: CUNXI YU Date: Sun, 27 Aug 2023 11:18:35 -0600 Subject: [PATCH 002/151] correct the naming of augmentation --- src/base/abci/abc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 6e99d7481..6b5c4ebca 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -164,7 +164,7 @@ static int Abc_CommandAllExact ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandTestExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMajGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandOrchestrate ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAIGArgumentation ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAIGAugmentation ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -918,7 +918,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "faultclasses", Abc_CommandFaultClasses, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "exact", Abc_CommandExact, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "orchestrate", Abc_CommandOrchestrate, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "aigarg", Abc_CommandAIGArgumentation, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "aigaug", Abc_CommandAIGAugmentation, 1 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_start", Abc_CommandBmsStart, 0 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_stop", Abc_CommandBmsStop, 0 ); @@ -7540,14 +7540,14 @@ usage: Synopsis [] - Description [AIG RTL Argumentation] + Description [AIG RTL Augmentation] SideEffects [] SeeAlso [] ***********************************************************************/ -int Abc_CommandAIGArgumentation( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandAIGAugmentation( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pDup; int c, RetValue; @@ -7690,15 +7690,15 @@ int Abc_CommandAIGArgumentation( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: aigarg [-s ] [-d ][-zZdsh]\n" ); + Abc_Print( -2, "usage: aigaug [-s ] [-d ][-zZdsh]\n" ); Abc_Print( -2, "\t performs technology-independent AIG random synthesis (node level) for RTL argumentation\n" ); - Abc_Print( -2, "\t-z : toggle using zero-cost replacements for rwr for aigarg [default = %s]\n", fUseZeros_rwr? "yes": "no" ); - Abc_Print( -2, "\t-Z : toggle using zero-cost replacements for ref for aigarg [default = %s]\n", fUseZeros_ref? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle using zero-cost replacements for rwr for aigaug [default = %s]\n", fUseZeros_rwr? "yes": "no" ); + Abc_Print( -2, "\t-Z : toggle using zero-cost replacements for ref for aigaug [default = %s]\n", fUseZeros_ref? "yes": "no" ); Abc_Print( -2, "\t-d : record random synthesis decision made during argumentation [required filename; e.g., test.csv]\n"); Abc_Print( -2, "\t-s : set the random seed for random argumentation\n"); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); - Abc_Print( -2, "\tExample : read i10.aig;st;aigarg -s 1 -d test.csv;write i10_arg_1.aig;cec i10.aig i10_arg_1.aig\n"); + Abc_Print( -2, "\tExample : read i10.aig;st;aigaug -s 1 -d test.csv;write i10_arg_1.aig;cec i10.aig i10_arg_1.aig\n"); return 1; } From 855976c61d7eb50b238fb9f6e793d80bff1e8ed7 Mon Sep 17 00:00:00 2001 From: CUNXI YU Date: Sun, 27 Aug 2023 11:19:26 -0600 Subject: [PATCH 003/151] correct the naming of augmentation --- src/base/abci/abc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 6b5c4ebca..94ca326df 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -7691,11 +7691,11 @@ int Abc_CommandAIGAugmentation( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: Abc_Print( -2, "usage: aigaug [-s ] [-d ][-zZdsh]\n" ); - Abc_Print( -2, "\t performs technology-independent AIG random synthesis (node level) for RTL argumentation\n" ); + Abc_Print( -2, "\t performs technology-independent AIG random synthesis (node level) for RTL augmentation\n" ); Abc_Print( -2, "\t-z : toggle using zero-cost replacements for rwr for aigaug [default = %s]\n", fUseZeros_rwr? "yes": "no" ); Abc_Print( -2, "\t-Z : toggle using zero-cost replacements for ref for aigaug [default = %s]\n", fUseZeros_ref? "yes": "no" ); - Abc_Print( -2, "\t-d : record random synthesis decision made during argumentation [required filename; e.g., test.csv]\n"); - Abc_Print( -2, "\t-s : set the random seed for random argumentation\n"); + Abc_Print( -2, "\t-d : record random synthesis decision made during augmentation [required filename; e.g., test.csv]\n"); + Abc_Print( -2, "\t-s : set the random seed for random augmentation\n"); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tExample : read i10.aig;st;aigaug -s 1 -d test.csv;write i10_arg_1.aig;cec i10.aig i10_arg_1.aig\n"); From 7fe744968554a4f52a397b33715c3ca7a27f8b69 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Tue, 12 Sep 2023 10:40:59 +0800 Subject: [PATCH 004/151] Refactor(Typo):Typo update on dnsize --- src/map/scl/scl.c | 4 ++-- src/map/scl/sclDnsize.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/map/scl/scl.c b/src/map/scl/scl.c index 3a82280dc..53785668e 100644 --- a/src/map/scl/scl.c +++ b/src/map/scl/scl.c @@ -1787,9 +1787,9 @@ int Scl_CommandDnsize( Abc_Frame_t * pAbc, int argc, char **argv ) usage: fprintf( pAbc->Err, "usage: dnsize [-IJNDGTX num] [-csdvwh]\n" ); fprintf( pAbc->Err, "\t selectively decreases gate sizes while maintaining delay\n" ); - fprintf( pAbc->Err, "\t-I : the number of upsizing iterations to perform [default = %d]\n", pPars->nIters ); + fprintf( pAbc->Err, "\t-I : the number of downsizing iterations to perform [default = %d]\n", pPars->nIters ); fprintf( pAbc->Err, "\t-J : the number of iterations without improvement to stop [default = %d]\n", pPars->nIterNoChange ); - fprintf( pAbc->Err, "\t-N : limit on discrete upsizing steps at a node [default = %d]\n", pPars->Notches ); + fprintf( pAbc->Err, "\t-N : limit on discrete downsizing steps at a node [default = %d]\n", pPars->Notches ); fprintf( pAbc->Err, "\t-D : delay target set by the user, in picoseconds [default = %d]\n", pPars->DelayUser ); fprintf( pAbc->Err, "\t-G : delay gap during updating, in picoseconds [default = %d]\n", pPars->DelayGap ); fprintf( pAbc->Err, "\t-T : approximate timeout in seconds [default = %d]\n", pPars->TimeOut ); diff --git a/src/map/scl/sclDnsize.c b/src/map/scl/sclDnsize.c index 19e4b30c7..5be9e3a34 100644 --- a/src/map/scl/sclDnsize.c +++ b/src/map/scl/sclDnsize.c @@ -265,7 +265,7 @@ void Abc_SclDnsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPa assert( p->vGatesBest == NULL ); p->vGatesBest = Vec_IntDup( p->pNtk->vGates ); - // perform upsizing + // perform downsizing vNodes = Vec_IntAlloc( 1000 ); vEvals = Vec_IntAlloc( 1000 ); vTryLater = Vec_IntAlloc( 1000 ); From 3a53a950aaea4ba7c87d35c6ca5ff5ae4392bbd5 Mon Sep 17 00:00:00 2001 From: wjrforcyber Date: Tue, 12 Sep 2023 11:57:18 +0800 Subject: [PATCH 005/151] Refactor(Typo): Typo update on buffer --- src/map/scl/scl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/map/scl/scl.c b/src/map/scl/scl.c index 53785668e..8671d958e 100644 --- a/src/map/scl/scl.c +++ b/src/map/scl/scl.c @@ -1136,9 +1136,9 @@ int Scl_CommandBuffer( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: fprintf( pAbc->Err, "usage: buffer [-GSN num] [-sbpcvwh]\n" ); - fprintf( pAbc->Err, "\t performs buffering and sizing and mapped network\n" ); + fprintf( pAbc->Err, "\t performs buffering and sizing on mapped network\n" ); fprintf( pAbc->Err, "\t-G : target gain percentage [default = %d]\n", pPars->GainRatio ); - fprintf( pAbc->Err, "\t-S : target slew in pisoseconds [default = %d]\n", pPars->Slew ); + fprintf( pAbc->Err, "\t-S : target slew in picoseconds [default = %d]\n", pPars->Slew ); fprintf( pAbc->Err, "\t-N : the maximum fanout count [default = %d]\n", pPars->nDegree ); fprintf( pAbc->Err, "\t-s : toggle performing only sizing [default = %s]\n", pPars->fSizeOnly? "yes": "no" ); fprintf( pAbc->Err, "\t-b : toggle using buffers instead of inverters [default = %s]\n", pPars->fAddBufs? "yes": "no" ); From 7d80ea5cf9951fc2b37151a59abc8a71a2c6ed7e Mon Sep 17 00:00:00 2001 From: Ethan Mahintorabi Date: Wed, 13 Sep 2023 18:24:01 +0000 Subject: [PATCH 006/151] Adds unit testing framework to ABC Signed-off-by: Ethan Mahintorabi --- .github/workflows/build-posix-cmake.yml | 4 ++ CMakeLists.txt | 14 +++++++ test/CMakeLists.txt | 1 + test/gia/CMakeLists.txt | 11 +++++ test/gia/gia_test.cc | 55 +++++++++++++++++++++++++ 5 files changed, 85 insertions(+) create mode 100644 test/CMakeLists.txt create mode 100644 test/gia/CMakeLists.txt create mode 100644 test/gia/gia_test.cc diff --git a/.github/workflows/build-posix-cmake.yml b/.github/workflows/build-posix-cmake.yml index def198107..6bbf1976e 100644 --- a/.github/workflows/build-posix-cmake.yml +++ b/.github/workflows/build-posix-cmake.yml @@ -40,6 +40,10 @@ jobs: run: | cmake --build build + - name: Run Unit Tests + run: | + ctest --output-on-failure + - name: Test Executable run: | ./build/abc -c "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec" diff --git a/CMakeLists.txt b/CMakeLists.txt index cee9bc72f..c04c112cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,3 +108,17 @@ add_library(libabc-pic EXCLUDE_FROM_ALL ${ABC_SRC}) abc_properties(libabc-pic PUBLIC) set_property(TARGET libabc-pic PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET libabc-pic PROPERTY OUTPUT_NAME abc-pic) + +if(NOT DEFINED ABC_SKIP_TESTS) + enable_testing() + include(FetchContent) + FetchContent_Declare( + googletest + DOWNLOAD_EXTRACT_TIMESTAMP TRUE + # Specify the commit you depend on and update it regularly. + URL "https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip" + ) + FetchContent_MakeAvailable(googletest) + include(GoogleTest) + add_subdirectory(test) +endif() \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 000000000..5a187fcac --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(gia) \ No newline at end of file diff --git a/test/gia/CMakeLists.txt b/test/gia/CMakeLists.txt new file mode 100644 index 000000000..012aca6db --- /dev/null +++ b/test/gia/CMakeLists.txt @@ -0,0 +1,11 @@ +add_executable(gia_test gia_test.cc) + +target_link_libraries(gia_test + gtest + gtest_main + libabc +) + +gtest_discover_tests(gia_test + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) \ No newline at end of file diff --git a/test/gia/gia_test.cc b/test/gia/gia_test.cc new file mode 100644 index 000000000..c61f72f3e --- /dev/null +++ b/test/gia/gia_test.cc @@ -0,0 +1,55 @@ +#include "gtest/gtest.h" + +#include "aig/gia/gia.h" + +namespace abc { + + +TEST(GiaTest, CanAllocateGiaManager) { + Gia_Man_t* aig_manager = Gia_ManStart(100); + + EXPECT_TRUE(aig_manager != nullptr); + Gia_ManStop(aig_manager); +} + +TEST(GiaTest, CanAddACi) { + Gia_Man_t* aig_manager = Gia_ManStart(100); + Gia_ManAppendCi(aig_manager); + + EXPECT_EQ(Gia_ManCiNum(aig_manager), 1); + Gia_ManStop(aig_manager); +} + +TEST(GiaTest, CanAddACo) { + Gia_Man_t* aig_manager = Gia_ManStart(100); + int input1 = Gia_ManAppendCi(aig_manager); + Gia_ManAppendCo(aig_manager, input1); + + EXPECT_EQ(Gia_ManCiNum(aig_manager), 1); + EXPECT_EQ(Gia_ManCoNum(aig_manager), 1); + Gia_ManStop(aig_manager); +} + +TEST(GiaTest, CanAddAnAndGate) { + Gia_Man_t* aig_manager = Gia_ManStart(100); + + int input1 = Gia_ManAppendCi(aig_manager); + int input2 = Gia_ManAppendCi(aig_manager); + + int and_output = Gia_ManAppendAnd(aig_manager, input1, input2); + Gia_ManAppendCo(aig_manager, and_output); + + Vec_Wrd_t* stimulus = Vec_WrdAlloc(2); + Vec_WrdPush(stimulus, /*A*/1); + Vec_WrdPush(stimulus, /*B*/1); + Vec_Wrd_t* output = Gia_ManSimPatSimOut(aig_manager, stimulus, /*fouts*/1); + + EXPECT_EQ(Gia_ManCiNum(aig_manager), 2); + EXPECT_EQ(Gia_ManCoNum(aig_manager), 1); + // A = 1, B = 1 -> A & B == 1 + EXPECT_EQ(Vec_WrdGetEntry(output, 0), 1); + Vec_WrdFree(output); + Gia_ManStop(aig_manager); +} + +} // namespace dpl \ No newline at end of file From 09013f3a6ea7276f289d790a217ca86b863eaeb9 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 15 Sep 2023 22:44:31 +0800 Subject: [PATCH 007/151] New command &gen_hie to generate hierarchical designs. --- src/aig/gia/gia.h | 2 +- src/aig/gia/giaMan.c | 209 ++++++++++++++++++++++++++++++++++++++++++- src/base/abci/abc.c | 57 +++++++++++- 3 files changed, 260 insertions(+), 8 deletions(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index d4edc1237..68266bb2d 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1527,7 +1527,7 @@ extern void Gia_ManPrintStatsMiter( Gia_Man_t * p, int fVerbose ) extern void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs ); extern void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew ); extern void Gia_ManPrintNpnClasses( Gia_Man_t * p ); -extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ); +extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb ); /*=== giaMem.c ===========================================================*/ extern Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax ); extern void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose ); diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index e8f9bca32..0efb5b29f 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -1291,7 +1291,7 @@ void Gia_ManDumpModuleName( FILE * pFile, char * pName ) else fprintf( pFile, "_" ); } -void Gia_ManDumpInterface( Gia_Man_t * p, FILE * pFile ) +void Gia_ManDumpInterface2( Gia_Man_t * p, FILE * pFile ) { int fPrintClk = 0; fprintf( pFile, "module " ); @@ -1324,7 +1324,6 @@ void Gia_ManDumpInterface( Gia_Man_t * p, FILE * pFile ) fprintf( pFile, "endmodule\n\n" ); } - /**Function************************************************************* Synopsis [Compute arrival/required times.] @@ -1407,7 +1406,7 @@ void Gia_ManWriteNames( FILE * pFile, char c, int n, Vec_Ptr_t * vNames, int Sta fFirst = 0; } } -void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ) +void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb ) { Gia_Obj_t * pObj; Vec_Bit_t * vInvs, * vUsed; @@ -1415,6 +1414,13 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); int i, k, iObj, nRegs = Gia_ManRegNum(p); + if ( fInterComb ) + { + extern void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ); + Gia_ManDumpInterface( p, pFileName ); + return; + } + FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { @@ -1423,7 +1429,7 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int } if ( fInter || nRegs ) - Gia_ManDumpInterface( p, pFile ); + Gia_ManDumpInterface2( p, pFile ); //Gia_ManSetRegNum( p, 0 ); p->nRegs = 0; @@ -1588,6 +1594,201 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int Gia_ManSetRegNum( p, nRegs ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ) +{ + Gia_Obj_t * pObj; + Vec_Bit_t * vInvs, * vUsed; + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + int i; + + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + + vInvs = Gia_ManGenUsed( p, 0 ); + vUsed = Gia_ManGenUsed( p, 1 ); + + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_wrapper" ); + fprintf( pFile, " ( _i_, _o_ );\n\n" ); + fprintf( pFile, " input [%d:0] _i_;\n", Gia_ManCiNum(p)-1 ); + fprintf( pFile, " output [%d:0] _o_;\n\n", Gia_ManCoNum(p)-1 ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " assign { " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL ); + fprintf( pFile, " } = _i_;\n\n" ); + + fprintf( pFile, " assign _o_ = { " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL ); + fprintf( pFile, " };\n\n" ); + + if ( Vec_BitCount(vUsed) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vInvs) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs ); + fprintf( pFile, ";\n\n" ); + } + + // input inverters + Gia_ManForEachCi( p, pObj, i ) + { + if ( Vec_BitEntry(vUsed, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(NULL, 'n', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + if ( Vec_BitEntry(vInvs, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " not ( %s,", Gia_ObjGetDumpName(NULL, 'i', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + } + + // internal nodes and their inverters + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + fprintf( pFile, " and ( %s,", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + fprintf( pFile, " %s,", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0(pObj, i), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC1(pObj)? 'i':'n'), Gia_ObjFaninId1(pObj, i), nDigits) ); + if ( Vec_BitEntry(vInvs, i) ) + { + fprintf( pFile, " not ( %s,", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + } + } + + // output drivers + fprintf( pFile, "\n" ); + Gia_ManForEachCo( p, pObj, i ) + { + fprintf( pFile, " buf ( %s, ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + fprintf( pFile, "1\'b%d );\n", Gia_ObjFaninC0(pObj) ); + else + fprintf( pFile, "%s );\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); + } + + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); + + Vec_BitFree( vInvs ); + Vec_BitFree( vUsed ); +} + + +/**Function************************************************************* + + Synopsis [Generate hierarchical design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_FreeMany( Gia_Man_t ** pGias, int nGias ) +{ + int i; + for ( i = 0; i < nGias; i++ ) + Gia_ManStopP( &pGias[i] ); +} +void Gia_GenSandwich( char ** pFNames, int nFNames ) +{ + FILE * pFile = NULL; + char * pFileName = (char *)"sandwich.v"; + Gia_Man_t * pGias[16] = {0}; + int i, k; + assert( nFNames <= 16 ); + for ( i = 0; i < nFNames; i++ ) + { + FILE * pFile = fopen( pFNames[i], "rb" ); + if ( pFile == NULL ) { + printf( "Cannot open input file \"%s\".\n", pFNames[i] ); + Gia_FreeMany( pGias, nFNames ); + return; + } + fclose( pFile ); + pGias[i] = Gia_AigerRead( pFNames[i], 0, 0, 0 ); + if ( pGias[i] == NULL ) { + printf( "Failed to read an AIG from file \"%s\".\n", pFNames[i] ); + Gia_FreeMany( pGias, nFNames ); + return; + } + } + for ( i = 0; i < nFNames-1; i++ ) + if ( Gia_ManPoNum(pGias[i]) < Gia_ManPiNum(pGias[i+1]) ) { + printf( "AIG in file \"%s\" has fewer outputs than inputs of AIG in file \"%s\".\n", pFNames[i], pFNames[i+1] ); + Gia_FreeMany( pGias, nFNames ); + return; + } + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + Gia_FreeMany( pGias, nFNames ); + return; + } + fprintf( pFile, "\n" ); + for ( i = 0; i < nFNames; i++ ) + fprintf( pFile, "`include \"%s\"\n", Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v") ); + fprintf( pFile, "\n" ); + fprintf( pFile, "module sandwich ( in, out );\n" ); + fprintf( pFile, " input [%3d:0] in;\n", Gia_ManPiNum(pGias[0])-1 ); + fprintf( pFile, " output [%3d:0] out;\n", Gia_ManPoNum(pGias[nFNames-1])-1 ); + fprintf( pFile, " wire [%3d:0] tmp0 = in;\n", Gia_ManPiNum(pGias[0])-1 ); + for ( i = 0; i < nFNames; i++ ) { + fprintf( pFile, " wire [%3d:0] tmp%d; ", Gia_ManPoNum(pGias[i])-1, i+1 ); + Gia_ManDumpModuleName( pFile, pGias[i]->pName ); + fprintf( pFile, "_wrapper" ); + for ( k = strlen(pGias[i]->pName); k < 24; k++ ) + fprintf( pFile, " " ); + fprintf( pFile, " i%d ( tmp%d, tmp%d );\n", i+1, i, i+1 ); + } + fprintf( pFile, " assign out = tmp%d;\n", nFNames ); + fprintf( pFile, "endmodule\n" ); + fclose( pFile ); + for ( i = 0; i < nFNames; i++ ) { + Gia_ManDumpVerilog( pGias[i], Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v"), NULL, 0, 0, 1 ); + printf( "Dumped Verilog file \"%s\"\n", Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v") ); + } + Gia_FreeMany( pGias, nFNames ); + printf( "Dumped hierarchical design into file \"%s\"\n", pFileName ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index e86667882..c8fa8e141 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -595,6 +595,7 @@ static int Abc_CommandAbc9Cfs ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9ProdAdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9AddFlop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9BMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenHie ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1364,6 +1365,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&prodadd", Abc_CommandAbc9ProdAdd, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&addflop", Abc_CommandAbc9AddFlop, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmiter", Abc_CommandAbc9BMiter, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&gen_hie", Abc_CommandAbc9GenHie, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); { @@ -31762,13 +31764,14 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) int fUnique = 0; int fVerilog = 0; int fInter = 0; + int fInterComb = 0; int fVerBufs = 0; int fMiniAig = 0; int fMiniLut = 0; int fWriteNewLine = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "upibmlnvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "upicbmlnvh" ) ) != EOF ) { switch ( c ) { @@ -31781,6 +31784,9 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'i': fInter ^= 1; break; + case 'c': + fInterComb ^= 1; + break; case 'b': fVerBufs ^= 1; break; @@ -31822,7 +31828,7 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_ManStop( pGia ); } else if ( fVerilog ) - Gia_ManDumpVerilog( pAbc->pGia, pFileName, NULL, fVerBufs, fInter ); + Gia_ManDumpVerilog( pAbc->pGia, pFileName, NULL, fVerBufs, fInter, fInterComb ); else if ( fMiniAig ) Gia_ManWriteMiniAig( pAbc->pGia, pFileName ); else if ( fMiniLut ) @@ -31832,11 +31838,12 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &w [-upibmlnvh] \n" ); + Abc_Print( -2, "usage: &w [-upicbmlnvh] \n" ); Abc_Print( -2, "\t writes the current AIG into the AIGER file\n" ); Abc_Print( -2, "\t-u : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" ); Abc_Print( -2, "\t-p : toggle writing Verilog with 'and' and 'not' [default = %s]\n", fVerilog? "yes" : "no" ); Abc_Print( -2, "\t-i : toggle writing the interface module in Verilog [default = %s]\n", fInter? "yes" : "no" ); + Abc_Print( -2, "\t-c : toggle writing the interface module in Verilog [default = %s]\n", fInterComb? "yes" : "no" ); Abc_Print( -2, "\t-b : toggle writing additional buffers in Verilog [default = %s]\n", fVerBufs? "yes" : "no" ); Abc_Print( -2, "\t-m : toggle writing MiniAIG rather than AIGER [default = %s]\n", fMiniAig? "yes" : "no" ); Abc_Print( -2, "\t-l : toggle writing MiniLUT rather than AIGER [default = %s]\n", fMiniLut? "yes" : "no" ); @@ -51569,6 +51576,50 @@ usage: return 1; } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9GenHie( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_GenSandwich( char ** pFNames, int nFNames ); + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + char ** pArgvNew = argv + globalUtilOptind; + int nArgcNew = argc - globalUtilOptind; + Gia_GenSandwich( pArgvNew, nArgcNew ); + return 0; +usage: + Abc_Print( -2, "usage: &gen_hie [-vh] ... \n" ); + Abc_Print( -2, "\t generates a hierarchical design\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the AIG files for the instance modules\n"); + Abc_Print( -2, "\t (the PO count of should not be less than the PI count of )\n"); + return 1;} + + /**Function************************************************************* Synopsis [] From 57cc2bd08985f7d95a49de50f3ba0ed7a1f5ceb9 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 15 Sep 2023 22:51:11 +0800 Subject: [PATCH 008/151] Compiler problem. --- src/base/abci/abc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index c8fa8e141..79012c850 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -51592,6 +51592,8 @@ int Abc_CommandAbc9GenHie( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_GenSandwich( char ** pFNames, int nFNames ); int c, fVerbose = 0; + char ** pArgvNew; + int nArgcNew; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { @@ -51606,8 +51608,8 @@ int Abc_CommandAbc9GenHie( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - char ** pArgvNew = argv + globalUtilOptind; - int nArgcNew = argc - globalUtilOptind; + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; Gia_GenSandwich( pArgvNew, nArgcNew ); return 0; usage: From 318d5cb54bd3c1de807139a34667f4d963ea352c Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 15 Sep 2023 23:10:42 +0800 Subject: [PATCH 009/151] Do not create spec outputs in the boundary miter. --- src/aig/gia/giaDup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 6dee2c26f..db4072d71 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -5708,8 +5708,8 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) } Gia_ManForEachCo( p2, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); - Gia_ManForEachCo( p1, pObj, i ) - Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + //Gia_ManForEachCo( p1, pObj, i ) + // Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Vec_IntForEachEntry( vLits, iLit, i ) Gia_ManAppendCo( pNew, iLit ); Vec_IntFree( vLits ); From 475c8dad8ecbbe3cc1c864fb3462c83438184f6d Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 16 Sep 2023 07:13:10 +0800 Subject: [PATCH 010/151] Compiler problem. --- src/base/abci/abc.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 5a755ea1f..a1ee17305 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -7576,7 +7576,11 @@ int Abc_CommandAIGAugmentation( Abc_Frame_t * pAbc, int argc, char ** argv ) int Rand_Seed; //int sOpsOrder; size_t NtkSize; - char *DecisionFile; + char *DecisionFile = NULL; + Vec_Int_t *DecisionMask; + Vec_Int_t *pGain_rwr; + Vec_Int_t *pGain_res; + Vec_Int_t *pGain_ref; //FILE *maskFile; extern void Rwr_Precompute(); extern int Abc_NtkOrchRand( Abc_Ntk_t * pNtk, Vec_Int_t **pGain_rwr, Vec_Int_t **pGain_res,Vec_Int_t **pGain_ref, Vec_Int_t **DecisionMask, char *DecisionFile, int Rand_Seed, int fUseZeros_rwr, int fUseZeros_ref, int fPlaceEnable, int nCutsMax, int nNodesMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose, int nNodeSizeMax, int nConeSizeMax, int fUseDcs ); @@ -7665,15 +7669,9 @@ int Abc_CommandAIGAugmentation( Abc_Frame_t * pAbc, int argc, char ** argv ) } NtkSize = Abc_NtkObjNumMax(pNtk); - - - Vec_Int_t *DecisionMask = Vec_IntAlloc(1); + DecisionMask = Vec_IntAlloc(1); for (int i=0; i Date: Sun, 17 Sep 2023 11:29:26 +0800 Subject: [PATCH 011/151] Revert "Merge pull request #247 from QuantamHD/abc_unit_tests" This reverts commit d91a2a049adec1797c7fa4aaeaef02a3c168734a, reversing changes made to 475c8dad8ecbbe3cc1c864fb3462c83438184f6d. --- .github/workflows/build-posix-cmake.yml | 4 -- CMakeLists.txt | 14 ------- test/CMakeLists.txt | 1 - test/gia/CMakeLists.txt | 11 ----- test/gia/gia_test.cc | 55 ------------------------- 5 files changed, 85 deletions(-) delete mode 100644 test/CMakeLists.txt delete mode 100644 test/gia/CMakeLists.txt delete mode 100644 test/gia/gia_test.cc diff --git a/.github/workflows/build-posix-cmake.yml b/.github/workflows/build-posix-cmake.yml index 6bbf1976e..def198107 100644 --- a/.github/workflows/build-posix-cmake.yml +++ b/.github/workflows/build-posix-cmake.yml @@ -40,10 +40,6 @@ jobs: run: | cmake --build build - - name: Run Unit Tests - run: | - ctest --output-on-failure - - name: Test Executable run: | ./build/abc -c "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec" diff --git a/CMakeLists.txt b/CMakeLists.txt index c04c112cf..cee9bc72f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,17 +108,3 @@ add_library(libabc-pic EXCLUDE_FROM_ALL ${ABC_SRC}) abc_properties(libabc-pic PUBLIC) set_property(TARGET libabc-pic PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET libabc-pic PROPERTY OUTPUT_NAME abc-pic) - -if(NOT DEFINED ABC_SKIP_TESTS) - enable_testing() - include(FetchContent) - FetchContent_Declare( - googletest - DOWNLOAD_EXTRACT_TIMESTAMP TRUE - # Specify the commit you depend on and update it regularly. - URL "https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip" - ) - FetchContent_MakeAvailable(googletest) - include(GoogleTest) - add_subdirectory(test) -endif() \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt deleted file mode 100644 index 5a187fcac..000000000 --- a/test/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(gia) \ No newline at end of file diff --git a/test/gia/CMakeLists.txt b/test/gia/CMakeLists.txt deleted file mode 100644 index 012aca6db..000000000 --- a/test/gia/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_executable(gia_test gia_test.cc) - -target_link_libraries(gia_test - gtest - gtest_main - libabc -) - -gtest_discover_tests(gia_test - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) \ No newline at end of file diff --git a/test/gia/gia_test.cc b/test/gia/gia_test.cc deleted file mode 100644 index c61f72f3e..000000000 --- a/test/gia/gia_test.cc +++ /dev/null @@ -1,55 +0,0 @@ -#include "gtest/gtest.h" - -#include "aig/gia/gia.h" - -namespace abc { - - -TEST(GiaTest, CanAllocateGiaManager) { - Gia_Man_t* aig_manager = Gia_ManStart(100); - - EXPECT_TRUE(aig_manager != nullptr); - Gia_ManStop(aig_manager); -} - -TEST(GiaTest, CanAddACi) { - Gia_Man_t* aig_manager = Gia_ManStart(100); - Gia_ManAppendCi(aig_manager); - - EXPECT_EQ(Gia_ManCiNum(aig_manager), 1); - Gia_ManStop(aig_manager); -} - -TEST(GiaTest, CanAddACo) { - Gia_Man_t* aig_manager = Gia_ManStart(100); - int input1 = Gia_ManAppendCi(aig_manager); - Gia_ManAppendCo(aig_manager, input1); - - EXPECT_EQ(Gia_ManCiNum(aig_manager), 1); - EXPECT_EQ(Gia_ManCoNum(aig_manager), 1); - Gia_ManStop(aig_manager); -} - -TEST(GiaTest, CanAddAnAndGate) { - Gia_Man_t* aig_manager = Gia_ManStart(100); - - int input1 = Gia_ManAppendCi(aig_manager); - int input2 = Gia_ManAppendCi(aig_manager); - - int and_output = Gia_ManAppendAnd(aig_manager, input1, input2); - Gia_ManAppendCo(aig_manager, and_output); - - Vec_Wrd_t* stimulus = Vec_WrdAlloc(2); - Vec_WrdPush(stimulus, /*A*/1); - Vec_WrdPush(stimulus, /*B*/1); - Vec_Wrd_t* output = Gia_ManSimPatSimOut(aig_manager, stimulus, /*fouts*/1); - - EXPECT_EQ(Gia_ManCiNum(aig_manager), 2); - EXPECT_EQ(Gia_ManCoNum(aig_manager), 1); - // A = 1, B = 1 -> A & B == 1 - EXPECT_EQ(Vec_WrdGetEntry(output, 0), 1); - Vec_WrdFree(output); - Gia_ManStop(aig_manager); -} - -} // namespace dpl \ No newline at end of file From 2f5b81119b1bef37fc7637384157cf7238ab92f9 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 17 Sep 2023 12:17:27 +0800 Subject: [PATCH 012/151] Experiments with retiming. --- src/aig/gia/gia.h | 3 ++ src/aig/gia/giaMan.c | 2 + src/aig/gia/giaMini.c | 92 +++++++++++++++++++++++++++++++++++++++++ src/aig/gia/giaSif.c | 9 +++- src/base/main/abcapis.h | 3 ++ 5 files changed, 108 insertions(+), 1 deletion(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 68266bb2d..dab6770bb 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -241,6 +241,9 @@ struct Gia_Man_t_ Vec_Int_t vSuppVars; // used variables Vec_Int_t vVarMap; // used variables Gia_Dat_t * pUData; + // retiming data + Vec_Str_t * vStopsF; + Vec_Str_t * vStopsB; }; diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index 0efb5b29f..a48da5c29 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -156,6 +156,8 @@ void Gia_ManStop( Gia_Man_t * p ) Vec_IntErase( &p->vHash ); Vec_IntErase( &p->vHTable ); Vec_IntErase( &p->vRefs ); + Vec_StrFreeP( &p->vStopsF ); + Vec_StrFreeP( &p->vStopsB ); ABC_FREE( p->pData2 ); ABC_FREE( p->pTravIds ); ABC_FREE( p->pPlacement ); diff --git a/src/aig/gia/giaMini.c b/src/aig/gia/giaMini.c index c0473fea3..85647eac5 100644 --- a/src/aig/gia/giaMini.c +++ b/src/aig/gia/giaMini.c @@ -1228,6 +1228,98 @@ void Gia_MiniAigGenerateFromFile() Mini_AigStop( p ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Gia_ManRetimableF( Gia_Man_t * p, int * pRst, int * pSet, int * pEna ) +{ + Vec_Str_t * vStops = Vec_StrStart( Gia_ManObjNum(p) ); + Vec_Int_t * vTemps = Vec_IntStartFull( 3*Gia_ManObjNum(p) ); + Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i; + char * pStops = Vec_StrArray(vStops); + assert( Gia_ManRegNum(p) > 0 ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRo) + 0, pRst[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRo) + 1, pSet[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRo) + 2, pEna[i] ); + } + Gia_ManForEachAnd( p, pObj, i ) { + int * pFan0 = Vec_IntEntryP( vTemps, 3*Gia_ObjFaninId0(pObj, i) ); + int * pFan1 = Vec_IntEntryP( vTemps, 3*Gia_ObjFaninId1(pObj, i) ); + int * pNode = Vec_IntEntryP( vTemps, 3*i ); + pStops[i] = (char)1; + if ( pFan0[0] != -1 && pFan0[0] == pFan1[0] && pFan0[1] == pFan1[1] && pFan0[2] == pFan1[2] ) + pStops[i] = (char)0, pNode[0] = pFan0[0], pNode[1] = pFan0[1], pNode[2] = pFan0[2]; + } + Vec_IntFree( vTemps ); + return vStops; +} +Vec_Str_t * Gia_ManRetimableB( Gia_Man_t * p, int * pRst, int * pSet, int * pEna ) +{ + Vec_Str_t * vStops = Vec_StrStart( Gia_ManObjNum(p) ); + Vec_Int_t * vTemps = Vec_IntStartFull( 3*Gia_ManObjNum(p) ); + Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i, n; + char * pStops = Vec_StrArray(vStops); + assert( Gia_ManRegNum(p) > 0 ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { + Vec_IntWriteEntry( vTemps, 3*Gia_ObjFaninId0p(p, pObjRi) + 0, pRst[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjFaninId0p(p, pObjRi) + 1, pSet[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjFaninId0p(p, pObjRi) + 2, pEna[i] ); + } + Gia_ManForEachAndReverse( p, pObj, i ) { + int iFans[2] = { Gia_ObjFaninId0(pObj, i), Gia_ObjFaninId1(pObj, i) }; + int * pFans[2] = { Vec_IntEntryP( vTemps, 3*iFans[0] ), Vec_IntEntryP( vTemps, 3*iFans[1] ) }; + int * pNode = Vec_IntEntryP( vTemps, 3*i ); + if ( pNode[0] == -1 ) + continue; + for ( n = 0; n < 2; n++ ) + if ( pFans[n][0] == -1 ) + pStops[iFans[n]] = (char)1, pFans[n][0] = pNode[0], pFans[n][1] = pNode[1], pFans[n][2] = pNode[2]; + else if ( pFans[n][0] != pNode[0] || pFans[n][1] != pNode[1] || pFans[n][2] != pNode[2] ) + pStops[iFans[n]] = (char)0; + } + pStops[0] = (char)0; + Gia_ManForEachCi( p, pObj, i ) + pStops[Gia_ObjId(p, pObj)] = (char)0; + Gia_ManForEachAnd( p, pObj, i ) + pStops[i] = (char)!pStops[i]; + Vec_IntFree( vTemps ); + return vStops; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameSetRetimingData( Abc_Frame_t * pAbc, int * pRst, int * pSet, int * pEna ) +{ + Gia_Man_t * pGia; + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + pGia = Abc_FrameReadGia( pAbc ); + if ( pGia == NULL ) + printf( "Current network in ABC framework is not defined.\n" ); + assert( pGia->vStopsF == NULL ); + assert( pGia->vStopsB == NULL ); + pGia->vStopsF = Gia_ManRetimableF( pGia, pRst, pSet, pEna ); + pGia->vStopsB = Gia_ManRetimableB( pGia, pRst, pSet, pEna ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaSif.c b/src/aig/gia/giaSif.c index db7629fb3..c52ab4dd9 100644 --- a/src/aig/gia/giaSif.c +++ b/src/aig/gia/giaSif.c @@ -490,13 +490,16 @@ int Gia_ManSifCheckIter( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, i } int Gia_ManSifCheckPeriod( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period, int * pIters ) { - Gia_Obj_t * pObj; int i, Id, nSize = nLutSize+1; + Gia_Obj_t * pObj; int i, Id, Stop, nSize = nLutSize+1; assert( Gia_ManRegNum(p) > 0 ); Gia_ManForEachCiId( p, Id, i ) Vec_IntWriteEntry( vCuts, Id*nSize, 1 ); Gia_ManForEachCiId( p, Id, i ) Vec_IntWriteEntry( vCuts, Id*nSize+1, Id << 8 ); Vec_IntFill( vTimes, Gia_ManObjNum(p), -Period ); + if ( p->vStopsF ) + Vec_StrForEachEntry( p->vStopsF, Stop, i ) + if ( Stop ) Vec_IntWriteEntry( vTimes, i, 0 ); Vec_IntWriteEntry( vTimes, 0, 0 ); Gia_ManForEachPi( p, pObj, i ) Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), 0 ); @@ -510,6 +513,10 @@ int Gia_ManSifCheckPeriod( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, Gia_ManForEachObj( p, pObj, i ) if ( Vec_IntEntry(vTimes, Gia_ObjId(p, pObj)) > 2*Period ) return 0; + if ( p->vStopsB ) + Vec_StrForEachEntry( p->vStopsB, Stop, i ) + if ( Stop && Vec_IntEntry(vTimes, i) > Period ) + return 0; } return 0; } diff --git a/src/base/main/abcapis.h b/src/base/main/abcapis.h index d34306baf..e1e05f4c7 100644 --- a/src/base/main/abcapis.h +++ b/src/base/main/abcapis.h @@ -106,6 +106,9 @@ extern ABC_DLL int * Abc_FrameReadBoxes( Abc_Frame_t * pAbc ); extern ABC_DLL int Abc_FrameReadProbStatus( Abc_Frame_t * pAbc ); extern ABC_DLL void * Abc_FrameReadCex( Abc_Frame_t * pAbc ); +// procedure to set retiming data +extern ABC_DLL void Abc_FrameSetRetimingData( Abc_Frame_t * pAbc, int * pRst, int * pSet, int * pEna ); + // procedure to return sequential equivalences extern ABC_DLL int * Abc_FrameReadMiniAigEquivClasses( Abc_Frame_t * pAbc ); From da635a2995304b03d6ed58e434e333a89a68c70c Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 17 Sep 2023 12:18:12 +0800 Subject: [PATCH 013/151] Updating .gitignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c745dfb57..cbb424152 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,4 @@ tags /cmake /cscope +abc.history From 9399faac485e842f3409892181d2bdab986a7137 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 17 Sep 2023 12:40:33 +0800 Subject: [PATCH 014/151] Improvements to &gen_hie. --- src/aig/gia/giaMan.c | 3 +-- src/base/abci/abc.c | 35 +++++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index a48da5c29..2449b5df7 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -1728,10 +1728,9 @@ void Gia_FreeMany( Gia_Man_t ** pGias, int nGias ) for ( i = 0; i < nGias; i++ ) Gia_ManStopP( &pGias[i] ); } -void Gia_GenSandwich( char ** pFNames, int nFNames ) +void Gia_GenSandwich( char ** pFNames, int nFNames, char * pFileName ) { FILE * pFile = NULL; - char * pFileName = (char *)"sandwich.v"; Gia_Man_t * pGias[16] = {0}; int i, k; assert( nFNames <= 16 ); diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index a1ee17305..4bb3a4344 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -51755,15 +51755,24 @@ usage: ***********************************************************************/ int Abc_CommandAbc9GenHie( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Gia_GenSandwich( char ** pFNames, int nFNames ); + extern void Gia_GenSandwich( char ** pFNames, int nFNames, char * pFileName ); + char * pFileName = (char *)"sandwich.v"; int c, fVerbose = 0; char ** pArgvNew; int nArgcNew; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF ) { switch ( c ) { + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by a file name.\n" ); + goto usage; + } + pFileName = argv[globalUtilOptind++]; + break; case 'v': fVerbose ^= 1; break; @@ -51774,16 +51783,22 @@ int Abc_CommandAbc9GenHie( Abc_Frame_t * pAbc, int argc, char ** argv ) } } pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - Gia_GenSandwich( pArgvNew, nArgcNew ); + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew < 1 ) + { + Abc_Print( -1, "Abc_CommandAbc9GenHie(): At least one AIG file should be given on the command line.\n" ); + return 0; + } + Gia_GenSandwich( pArgvNew, nArgcNew, pFileName ); return 0; usage: - Abc_Print( -2, "usage: &gen_hie [-vh] ... \n" ); - Abc_Print( -2, "\t generates a hierarchical design\n" ); - Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - Abc_Print( -2, "\t : the AIG files for the instance modules\n"); - Abc_Print( -2, "\t (the PO count of should not be less than the PI count of )\n"); + Abc_Print( -2, "usage: &gen_hie [-F ] [-vh] ... \n" ); + Abc_Print( -2, "\t generates a hierarchical design in Verilog\n" ); + Abc_Print( -2, "\t-F : the output file name (optional) [default = \"sandwich.v\"]\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the AIG files for the instance modules\n"); + Abc_Print( -2, "\t (the PO count of should not be less than the PI count of )\n"); return 1;} From 09b0295c1aa288eab59c0041bfd12767949c35c9 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 18 Sep 2023 16:27:54 +0800 Subject: [PATCH 015/151] Adding aliases for some commands. --- src/base/abci/abc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 4bb3a4344..5bc50032c 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -844,14 +844,18 @@ Gia_Man_t * Abc_FrameGetGia( Abc_Frame_t * pAbc ) ***********************************************************************/ void Abc_Init( Abc_Frame_t * pAbc ) { + Cmd_CommandAdd( pAbc, "Printing", "ps", Abc_CommandPrintStats, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_stats", Abc_CommandPrintStats, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_exdc", Abc_CommandPrintExdc, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_io", Abc_CommandPrintIo, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_latch", Abc_CommandPrintLatch, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "pfan", Abc_CommandPrintFanio, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_fanio", Abc_CommandPrintFanio, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_mffc", Abc_CommandPrintMffc, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "pf", Abc_CommandPrintFactor, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_factor", Abc_CommandPrintFactor, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_level", Abc_CommandPrintLevel, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "psu", Abc_CommandPrintSupport, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_supp", Abc_CommandPrintSupport, 0 ); #ifdef ABC_USE_CUDD Cmd_CommandAdd( pAbc, "Printing", "print_mint", Abc_CommandPrintMint, 0 ); @@ -860,6 +864,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Printing", "print_unate", Abc_CommandPrintUnate, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_auto", Abc_CommandPrintAuto, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_kmap", Abc_CommandPrintKMap, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "pg", Abc_CommandPrintGates, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_gates", Abc_CommandPrintGates, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_sharing", Abc_CommandPrintSharing, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_xcut", Abc_CommandPrintXCut, 0 ); @@ -873,9 +878,12 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Printing", "show_bdd", Abc_CommandShowBdd, 0 ); Cmd_CommandAdd( pAbc, "Printing", "show_cut", Abc_CommandShowCut, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "clp", Abc_CommandCollapse, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "collapse", Abc_CommandCollapse, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "satclp", Abc_CommandSatClp, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "st", Abc_CommandStrash, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "strash", Abc_CommandStrash, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "b", Abc_CommandBalance, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "balance", Abc_CommandBalance, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "mux_struct", Abc_CommandMuxStruct, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "multi", Abc_CommandMulti, 1 ); From 7fd4b01fb3e514c9ef2f82ddf7824fb829d84ee1 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 18 Sep 2023 16:30:09 +0800 Subject: [PATCH 016/151] Automatic script file generation. --- src/base/abci/abcPrint.c | 50 +++++++---- src/base/cmd/cmd.c | 173 +++++++++++++++++++++++++++++++++++++-- src/base/io/io.c | 12 +++ 3 files changed, 212 insertions(+), 23 deletions(-) diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index 7b566b79d..e90159d2a 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -224,6 +224,37 @@ float Abc_NtkGetArea( Abc_Ntk_t * pNtk ) return Counter; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Abc_NtkGetAreaSpecial( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; int i, Count = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( !strncmp( Mio_GateReadName((Mio_Gate_t*)pObj->pData), "mm", 2 ) ) + Count++; + return 1.0*Count/Abc_NtkNodeNum(pNtk); +} +float Abc_NtkGetAreaSpecial2( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; int i; + float Count = 0, CountAll = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) { + if ( !strncmp( Mio_GateReadName((Mio_Gate_t*)pObj->pData), "mm", 2 ) ) + Count += Mio_GateReadArea((Mio_Gate_t*)pObj->pData); + CountAll += Mio_GateReadArea((Mio_Gate_t*)pObj->pData); + } + return 1.0*Count/CountAll; +} + /**Function************************************************************* Synopsis [Print the vital stats of the network.] @@ -360,7 +391,7 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum if ( fPrintMem ) Abc_Print( 1," mem =%5.2f MB", Abc_NtkMemory(pNtk)/(1<<20) ); Abc_Print( 1,"\n" ); - +/* // print the statistic into a file if ( fDumpResult ) { @@ -374,6 +405,8 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum fprintf( pTable, "\n" ); fclose( pTable ); } +*/ + /* { FILE * pTable; @@ -389,21 +422,6 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum } */ -/* - // print the statistic into a file - { - FILE * pTable; - pTable = fopen( "ucsb/stats.txt", "a+" ); -// fprintf( pTable, "%s ", pNtk->pSpec ); - fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); -// fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); -// fprintf( pTable, "%.0f ", Abc_NtkGetMappedArea(pNtk) ); -// fprintf( pTable, "%.2f ", Abc_NtkDelayTrace(pNtk) ); - fprintf( pTable, "\n" ); - fclose( pTable ); - } -*/ - /* // print the statistic into a file { diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index 67c02cab8..630355fa5 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -22,6 +22,7 @@ #include #else #include +#include #endif #include "base/abc/abc.h" @@ -54,6 +55,8 @@ static int CmdCommandScanDir ( Abc_Frame_t * pAbc, int argc, char ** argv static int CmdCommandRenameFiles ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandLs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandScrGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#else +static int CmdCommandScrGenLinux ( Abc_Frame_t * pAbc, int argc, char ** argv ); #endif static int CmdCommandVersion ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandSis ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -104,6 +107,8 @@ void Cmd_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Basic", "renamefiles", CmdCommandRenameFiles, 0 ); Cmd_CommandAdd( pAbc, "Basic", "ls", CmdCommandLs, 0 ); Cmd_CommandAdd( pAbc, "Basic", "scrgen", CmdCommandScrGen, 0 ); +#else + Cmd_CommandAdd( pAbc, "Basic", "scrgen", CmdCommandScrGenLinux, 0 ); #endif Cmd_CommandAdd( pAbc, "Basic", "version", CmdCommandVersion, 0 ); @@ -1628,11 +1633,11 @@ int CmdCommandScrGen( Abc_Frame_t * pAbc, int argc, char **argv ) int nFileNameMax, nFileNameCur; int Counter = 0; int fUseCurrent; - char c; + int c; fUseCurrent = 0; Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "FDCWch") ) != EOF ) + while ( (c = Extra_UtilGetopt(argc, argv, "FRCWch") ) != EOF ) { switch (c) { @@ -1645,7 +1650,7 @@ int CmdCommandScrGen( Abc_Frame_t * pAbc, int argc, char **argv ) pFileStr = argv[globalUtilOptind]; globalUtilOptind++; break; - case 'D': + case 'R': if ( globalUtilOptind >= argc ) { fprintf( pAbc->Err, "Command line switch \"-D\" should be followed by a string.\n" ); @@ -1795,7 +1800,7 @@ int CmdCommandScrGen( Abc_Frame_t * pAbc, int argc, char **argv ) Line[c] = '/'; fprintf( pFile, "%s", Line ); } - fprintf( pFile, "\n", Line ); + fprintf( pFile, "\n" ); } while( _findnext( hFile, &c_file ) == 0 ); _findclose( hFile ); @@ -1815,17 +1820,171 @@ int CmdCommandScrGen( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; usage: - fprintf( pAbc->Err, "usage: scrgen -F -D -C -W -ch\n" ); + fprintf( pAbc->Err, "usage: scrgen -F -R -C -W -ch\n" ); fprintf( pAbc->Err, "\t generates script for running ABC\n" ); fprintf( pAbc->Err, "\t-F str : the name of the script file [default = \"test.s\"]\n" ); - fprintf( pAbc->Err, "\t-D str : the directory to read files from [default = current]\n" ); + fprintf( pAbc->Err, "\t-R str : the directory to read files from [default = current]\n" ); fprintf( pAbc->Err, "\t-C str : the sequence of commands to run [default = \"ps\"]\n" ); fprintf( pAbc->Err, "\t-W str : the directory to write the resulting files [default = no writing]\n" ); fprintf( pAbc->Err, "\t-c : toggle placing file in current/target dir [default = %s]\n", fUseCurrent? "current": "target" ); fprintf( pAbc->Err, "\t-h : print the command usage\n\n"); - fprintf( pAbc->Err, "\tExample : scrgen -F test1.s -D a/in -C \"ps; st; ps\" -W a/out\n" ); + fprintf( pAbc->Err, "\tExample : scrgen -F test1.s -R a/in -C \"ps; st; ps\" -W a/out\n" ); return 1; } + +#else + +Vec_Ptr_t * CmdReturnFileNames( char * pDirStr ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( 100 ); + struct dirent **namelist; + int num_files = scandir(pDirStr, &namelist, NULL, alphasort); + if (num_files == -1) { + printf("Error opening directory.\n"); + return NULL; + } + for (int i = 0; i < num_files; i++) { + char * pExt = strstr(namelist[i]->d_name, "."); + if ( !pExt || !strcmp(pExt, ".") || !strcmp(pExt, "..") || !strcmp(pExt, ".s") || !strcmp(pExt, ".txt") ) + continue; + Vec_PtrPush( vRes, Abc_UtilStrsav(namelist[i]->d_name) ); + free(namelist[i]); + } + free(namelist); + return vRes; +} + +int CmdCommandScrGenLinux( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Vec_Ptr_t * vNames = NULL; + FILE * pFile = NULL; + char * pFileStr = (char *)"test.s"; + char * pDirStr = (char *)"."; + char * pComStr = (char *)"ps"; + char * pWriteStr = NULL; + char * pWriteExt = NULL; + char Line[2000], * pName; + int nFileNameMax; + int c, k; + + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "FRCWEh") ) != EOF ) + { + switch (c) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pAbc->Err, "Command line switch \"-F\" should be followed by a string.\n" ); + goto usage; + } + pFileStr = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + fprintf( pAbc->Err, "Command line switch \"-D\" should be followed by a string.\n" ); + goto usage; + } + pDirStr = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pAbc->Err, "Command line switch \"-C\" should be followed by a string.\n" ); + goto usage; + } + pComStr = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'W': + if ( globalUtilOptind >= argc ) + { + fprintf( pAbc->Err, "Command line switch \"-W\" should be followed by a string.\n" ); + goto usage; + } + pWriteStr = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'E': + if ( globalUtilOptind >= argc ) + { + fprintf( pAbc->Err, "Command line switch \"-E\" should be followed by a string.\n" ); + goto usage; + } + pWriteExt = argv[globalUtilOptind]; + globalUtilOptind++; + break; + default: + goto usage; + } + } + pFile = fopen( pFileStr, "w" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file %s.\n", pFileStr ); + return 0; + } + vNames = CmdReturnFileNames( pDirStr ); + if ( !vNames || !Vec_PtrSize(vNames) ) + { + if ( vNames ) + printf( "It looks like the directory \"%s\" does not contain any relevant files.\n", pDirStr ); + Vec_PtrFreeP(&vNames); + return 0; + } + nFileNameMax = 0; + Vec_PtrForEachEntry( char *, vNames, pName, k ) + if ( nFileNameMax < strlen(pName) ) + nFileNameMax = strlen(pName); + { + int fAndSpace = pComStr[0] == '&'; + fprintf( pFile, "# Script file produced by ABC on %s\n", Extra_TimeStamp() ); + fprintf( pFile, "# Command line was: scrgen -F %s -D %s -C \"%s\"%s%s%s%s\n", + pFileStr, pDirStr, pComStr, + pWriteStr?" -W ":"", pWriteStr?pWriteStr:"", + pWriteExt?" -E ":"", pWriteExt?pWriteExt:"" ); + Vec_PtrForEachEntry( char *, vNames, pName, k ) { + char * pExt = strstr(pName, "."); + if ( !pExt || !strcmp(pExt, ".") || !strcmp(pExt, "..") || !strcmp(pExt, ".s") || !strcmp(pExt, ".txt") ) + continue; + sprintf( Line, "%sread %s%s%-*s ; %s", fAndSpace ? "&" : "", pDirStr?pDirStr:"", pDirStr?"/":"", nFileNameMax, pName, pComStr ); + for ( c = (int)strlen(Line)-1; c >= 0; c-- ) + if ( Line[c] == '\\' ) + Line[c] = '/'; + fprintf( pFile, "%s", Line ); + if ( pWriteStr ) + { + char * pFNameOut = pWriteExt ? Extra_FileNameGenericAppend(pName, pWriteExt) : pName; + sprintf( Line, " ; %swrite %s/%-*s", fAndSpace ? "&" : "", pWriteStr, nFileNameMax, pFNameOut ); + for ( c = (int)strlen(Line)-1; c >= 0; c-- ) + if ( Line[c] == '\\' ) + Line[c] = '/'; + fprintf( pFile, "%s", Line ); + } + fprintf( pFile, "\n" ); + } + } + fclose( pFile ); + printf( "Script file \"%s\" with command lines for %d files.\n", pFileStr, Vec_PtrSize(vNames) ); + Vec_PtrFreeFree( vNames ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: scrgen -F -R -C -W -E -h\n" ); + fprintf( pAbc->Err, "\t generates script for running ABC\n" ); + fprintf( pAbc->Err, "\t-F str : the name of the script file [default = \"test.s\"]\n" ); + fprintf( pAbc->Err, "\t-R str : the directory to read files from [default = current]\n" ); + fprintf( pAbc->Err, "\t-C str : the sequence of commands to run [default = \"ps\"]\n" ); + fprintf( pAbc->Err, "\t-W str : the directory to write the resulting files [default = no writing]\n" ); + fprintf( pAbc->Err, "\t-E str : the output files extension (with \".\") [default = the same as input files]\n" ); + fprintf( pAbc->Err, "\t-h : print the command usage\n\n"); + fprintf( pAbc->Err, "\tExample : scrgen -F test1.s -R a/in -C \"ps; st; ps\" -W a/out -E .blif\n" ); + return 1; +} + #endif diff --git a/src/base/io/io.c b/src/base/io/io.c index 7b8ca184e..e808d1d0b 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -276,6 +276,18 @@ int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } // read the file using the corresponding file reader + if ( strstr(pFileName, ".") && !strcmp(strstr(pFileName, "."), ".s") ) + { + char Command[1000]; + assert( strlen(pFileName) < 980 ); + sprintf( Command, "source -x %s", pFileName ); + if ( Cmd_CommandExecute( pAbc, Command ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); + return 1; + } + return 0; + } pNtk = Io_Read( pFileName, Io_ReadFileType(pFileName), fCheck, fBarBufs ); if ( pNtk == NULL ) return 0; From 31ad17fa1acdc90378bb633a02841f23bd5b5364 Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Wed, 20 Sep 2023 14:23:47 +0800 Subject: [PATCH 017/151] add abc9RecoverBoundary --- src/aig/gia/giaDup.c | 133 +++++++++++++++++++++++++++++++++++++++++++ src/base/abci/abc.c | 129 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 262 insertions(+) diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index db4072d71..665164eb2 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -5719,6 +5719,139 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) return pNew; } +/**Function************************************************************* + Synopsis [Duplicates AIG while putting objects in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManImplFromBMiter( Gia_Man_t * p, int nPo, int nBInput ) +{ + Gia_Man_t * pNew, *pTemp; + Gia_Obj_t * pObj, *pObj2; + int i; + int nBoundI = 0, nBoundO = 0; + int nExtra; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + // pNew->pName = Abc_UtilStrsav( p->pName ); + // pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + + // add po of impl + Gia_ManForEachCo( p, pObj, i ) + { + if ( i < nPo ) + { + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + } + } + nExtra = Gia_ManAndNum( pNew ); + + // add boundary as buf + Gia_ManForEachCo( p, pObj, i ) + { + if ( i >= 2 * nPo ) + { + pObj2 = Gia_ObjFanin0(pObj); + if (~pObj2->Value) // visited boundary + { + if ( i >= 2 * nPo + nBInput ) + { + nBoundO ++; + } + else nBoundI ++; + } + + Gia_ManDupOrderDfs_rec( pNew, p, pObj2 ); + Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + } + } + nExtra = Gia_ManAndNum( pNew ) - nExtra - Gia_ManBufNum( pNew ); + + Gia_ManForEachCi( p, pObj, i ) + if ( !~pObj->Value ) + pObj->Value = Gia_ManAppendCi(pNew); + assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); + + Gia_ManDupRemapCis( pNew, p ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + + printf( "synthesized implementation:\n" ); + printf( "\t%d / %d input boundary recovered.\n", nBoundI, nBInput ); + printf( "\t%d / %d output boundary recovered.\n", nBoundO, Gia_ManCoNum(p)-2*nPo-nBInput ); + printf( "\t%d / %d unused nodes in the box.\n", nExtra, Gia_ManAndNum(pNew) - Gia_ManBufNum( pNew ) ); + + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while putting objects in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManMiterFromBMiter( Gia_Man_t * p, int nPo ) +{ + Gia_Man_t * pNew, *pTemp; + Gia_Obj_t * pObj, *pObj2; + int i, iXor, iPo, i1, i2; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( "miter" ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + + // create primary inputs + Gia_ManForEachCi( p, pObj, i ) + if ( !~pObj->Value ) + pObj->Value = Gia_ManAppendCi(pNew); + + Gia_ManForEachCo( p, pObj, i ) + { + if ( i == nPo ) + { + break; + } + else + { + pObj2 = Gia_ManCo( p, i + nPo ); + + i1 = Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + i2 = Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj2) ); + + iXor = Gia_ManAppendXor2( pNew, Gia_ObjFaninC0(pObj) ? i1+1 : i1 , Gia_ObjFaninC0(pObj2 ) ? i2+1 : i2 ); + if ( i > 0 ) + { + iPo = Gia_ManAppendOr2( pNew, iPo, iXor ); + } + else + { + iPo = iXor; + } + } + } + Gia_ManAppendCo( pNew, iPo ); + + + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); + Gia_ManStop( pTemp ); + + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 5bc50032c..906b456ad 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -597,6 +597,7 @@ static int Abc_CommandAbc9ProdAdd ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9AddFlop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9BMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenHie ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9RecoverBoundary ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1376,6 +1377,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&addflop", Abc_CommandAbc9AddFlop, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmiter", Abc_CommandAbc9BMiter, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&gen_hie", Abc_CommandAbc9GenHie, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&rb", Abc_CommandAbc9RecoverBoundary, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); { @@ -51809,6 +51811,133 @@ usage: Abc_Print( -2, "\t (the PO count of should not be less than the PI count of )\n"); return 1;} +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9RecoverBoundary( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDeepSyn( Gia_Man_t * pGia, int nIters, int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fVerbose ); + extern Gia_Man_t * Gia_ManImplFromBMiter( Gia_Man_t * p, int nPo, int nBInput ); + extern Gia_Man_t * Gia_ManMiterFromBMiter( Gia_Man_t * p, int nPo ); + int c, nIters = 1, nNoImpr = ABC_INFINITY, TimeOut = 20, nAnds = 0, Seed = 0, fUseTwo = 0, fVerbose = 0; + + int fKeepBMiter = 0; + Gia_Man_t * pMiter; + Gia_Man_t * pImpl; + Gia_Man_t * pDup; + Gia_Obj_t* pObj; + Gia_Man_t * pSpec = NULL; + char ** pArgvNew; + int i, nArgcNew, nPo; + int nBInput = -1; + char *FileName; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vkhI," ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nBInput = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nBInput < 0 ) + goto usage; + break; + case 'k': + fKeepBMiter ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "There is no file name.\n" ); + return 1; + } + + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9RecoverBoundary(): There is no AIG.\n" ); + return 0; + } + FileName = pArgvNew[0]; + + + // printing + + // Gia_ManForEachCo( pAbc->pGia, pObj, i ){ + // printf("Original node: %s id: %i\n", Gia_ObjCoName(pAbc->pGia, i), i); + // } + + + /* + // perform heavy synthesis + pTemp = Gia_ManDeepSyn( pAbc->pGia, nIters, nNoImpr, TimeOut, nAnds, Seed, fUseTwo, fVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + // print spec/impl and boundary information + Gia_ManForEachCo( pAbc->pGia, pObj, i ){ + printf("Output node: %s id: %i\n", Gia_ObjCoName(pAbc->pGia, i), i); + } + */ + + + + // check boundary recovery status + pSpec = Gia_AigerRead( FileName, false, true, 0 ); + if ( !pSpec ) + { + Abc_Print( -1, "Abc_CommandAbc9RecoverBoundary(): fail to read spec.\n" ); + return 1; + } + nPo = Gia_ManCoNum( pSpec ); + + // duplicate + pDup = Gia_ManDup( pAbc->pGia ); + + // option 1: remove po and keep the buffers + // default nbinput: + if ( nBInput == -1 ) nBInput = (Gia_ManCoNum(pDup)-2*nPo)/2; + pImpl = Gia_ManImplFromBMiter( pDup, nPo, nBInput ); + + // option 2: build miter (with uif?) + if (!fKeepBMiter ) + { + pMiter = Gia_ManMiterFromBMiter( pAbc->pGia, nPo ); + Abc_FrameUpdateGia( pAbc, pMiter ); + } + + return 0; + +usage: + Abc_Print( -2, "usage: &rb [-vkh] \n" ); + Abc_Print( -2, "\t generate an implementation aig with specification boundary\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-k : keep the bmiter and print the boundary status only.\n"); + Abc_Print( -2, "\t-I num : the number of inputs in the boundary\n"); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the specification file\n"); + return 1; +} /**Function************************************************************* From 73dac01c15e55026ef057fcc0d08a8b77799a8bb Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 21 Sep 2023 11:08:16 +0800 Subject: [PATCH 018/151] Warning regarding PathMatchSpec() on Windows. --- src/map/scl/sclLiberty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/map/scl/sclLiberty.c b/src/map/scl/sclLiberty.c index 674f65549..3d62b68e5 100644 --- a/src/map/scl/sclLiberty.c +++ b/src/map/scl/sclLiberty.c @@ -83,7 +83,7 @@ struct Scl_Tree_t_ static inline int Scl_LibertyGlobMatch(const char * pattern, const char * string) { #ifdef _WIN32 - return PathMatchSpec(string, pattern); + return PathMatchSpec(string, pattern); // if the compiler complains, add "-lshlwapi" #else return fnmatch(pattern, string, 0) == 0; #endif From 4d1618f600a82f817ab41141446132d73aacd3c7 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 21 Sep 2023 11:08:43 +0800 Subject: [PATCH 019/151] Enable dumping Verilog with assign-statements. --- src/aig/gia/gia.h | 2 +- src/aig/gia/giaMan.c | 311 +++++++++++++++++++++++++++++++++++++++++-- src/base/abci/abc.c | 13 +- 3 files changed, 312 insertions(+), 14 deletions(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index dab6770bb..654f2faa5 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1530,7 +1530,7 @@ extern void Gia_ManPrintStatsMiter( Gia_Man_t * p, int fVerbose ) extern void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs ); extern void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew ); extern void Gia_ManPrintNpnClasses( Gia_Man_t * p ); -extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb ); +extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb, int fAssign ); /*=== giaMem.c ===========================================================*/ extern Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax ); extern void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose ); diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index 2449b5df7..e771f99cc 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -1408,7 +1408,32 @@ void Gia_ManWriteNames( FILE * pFile, char c, int n, Vec_Ptr_t * vNames, int Sta fFirst = 0; } } -void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb ) +void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb, int fAssign ) +{ + if ( fInterComb ) + { + if ( fAssign ) { + extern void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ); + Gia_ManDumpInterfaceAssign( p, pFileName ); + } + else { + extern void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ); + Gia_ManDumpInterface( p, pFileName ); + } + } + else + { + if ( fAssign ) { + extern void Gia_ManDumpVerilogNoInterAssign( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ); + Gia_ManDumpVerilogNoInterAssign( p, pFileName, vObjs, fVerBufs, fInter ); + } + else { + extern void Gia_ManDumpVerilogNoInter( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ); + Gia_ManDumpVerilogNoInter( p, pFileName, vObjs, fVerBufs, fInter ); + } + } +} +void Gia_ManDumpVerilogNoInter( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ) { Gia_Obj_t * pObj; Vec_Bit_t * vInvs, * vUsed; @@ -1416,13 +1441,6 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); int i, k, iObj, nRegs = Gia_ManRegNum(p); - if ( fInterComb ) - { - extern void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ); - Gia_ManDumpInterface( p, pFileName ); - return; - } - FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { @@ -1595,6 +1613,179 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int Gia_ManSetRegNum( p, nRegs ); } +void Gia_ManDumpVerilogNoInterAssign( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ) +{ + Gia_Obj_t * pObj; + Vec_Bit_t * vInvs, * vUsed; + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + int i, k, iObj, nRegs = Gia_ManRegNum(p); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + + if ( fInter || nRegs ) + Gia_ManDumpInterface2( p, pFile ); + //Gia_ManSetRegNum( p, 0 ); + p->nRegs = 0; + + vInvs = Gia_ManGenUsed( p, 0 ); + vUsed = Gia_ManGenUsed( p, 1 ); + + //fprintf( pFile, "// This Verilog file is written by ABC on %s\n\n", Extra_TimeStamp() ); + + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + + if ( fVerBufs ) + { + fprintf( pFile, " (\n " ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 4, 4, NULL ); + fprintf( pFile, ",\n " ); + + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, " input " ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " output " ); + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + Gia_ManForEachPi( p, pObj, i ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(NULL, 'a', i, nDigitsI) ); + } + fprintf( pFile, "\n" ); + + Gia_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'y', i, nDigitsO) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + } + fprintf( pFile, "\n" ); + } + else + { + fprintf( pFile, " (\n " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 4, 4, NULL ); + fprintf( pFile, ",\n " ); + + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, " input " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " output " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vUsed) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vInvs) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs ); + fprintf( pFile, ";\n\n" ); + } + + if ( vObjs ) + { + fprintf( pFile, " wire " ); + Vec_IntForEachEntry( vObjs, iObj, i ) + fprintf( pFile, " t_%d%s", i, i==Vec_IntSize(vObjs)-1 ? "" : "," ); + fprintf( pFile, ";\n\n" ); + Vec_IntForEachEntry( vObjs, iObj, i ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', iObj, nDigits) ); + fprintf( pFile, " t_%d;\n", i ); + } + fprintf( pFile, "\n" ); + } + + // input inverters + Gia_ManForEachPi( p, pObj, i ) + { + if ( Vec_BitEntry(vUsed, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + if ( Vec_BitEntry(vInvs, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'i', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " ~%s;\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + } + + // internal nodes and their inverters + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + int fSkip = 0; + if ( vObjs ) + { + Vec_IntForEachEntry( vObjs, iObj, k ) + if ( iObj == i ) + break; + if ( k < Vec_IntSize(vObjs) ) + fSkip = 1; + } + if ( !fSkip ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + fprintf( pFile, " %s &", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0(pObj, i), nDigits) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC1(pObj)? 'i':'n'), Gia_ObjFaninId1(pObj, i), nDigits) ); + } + if ( Vec_BitEntry(vInvs, i) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); + fprintf( pFile, " ~%s;\n", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + } + } + + // output drivers + fprintf( pFile, "\n" ); + Gia_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, " assign %s = ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + fprintf( pFile, "1\'b%d;\n", Gia_ObjFaninC0(pObj) ); + else + fprintf( pFile, "%s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); + } + + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); + + Vec_BitFree( vInvs ); + Vec_BitFree( vUsed ); + + Gia_ManSetRegNum( p, nRegs ); +} /**Function************************************************************* @@ -1709,6 +1900,108 @@ void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ) Vec_BitFree( vInvs ); Vec_BitFree( vUsed ); } +void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ) +{ + Gia_Obj_t * pObj; + Vec_Bit_t * vInvs, * vUsed; + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + int i; + + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + + vInvs = Gia_ManGenUsed( p, 0 ); + vUsed = Gia_ManGenUsed( p, 1 ); + + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_wrapper" ); + fprintf( pFile, " ( _i_, _o_ );\n\n" ); + fprintf( pFile, " input [%d:0] _i_;\n", Gia_ManCiNum(p)-1 ); + fprintf( pFile, " output [%d:0] _o_;\n\n", Gia_ManCoNum(p)-1 ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " assign { " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL ); + fprintf( pFile, " } = _i_;\n\n" ); + + fprintf( pFile, " assign _o_ = { " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL ); + fprintf( pFile, " };\n\n" ); + + if ( Vec_BitCount(vUsed) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vInvs) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs ); + fprintf( pFile, ";\n\n" ); + } + + // input inverters + Gia_ManForEachCi( p, pObj, i ) + { + if ( Vec_BitEntry(vUsed, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + if ( Vec_BitEntry(vInvs, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'i', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " ~%s;\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + } + + // internal nodes and their inverters + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + fprintf( pFile, " %s &", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0(pObj, i), nDigits) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC1(pObj)? 'i':'n'), Gia_ObjFaninId1(pObj, i), nDigits) ); + if ( Vec_BitEntry(vInvs, i) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); + fprintf( pFile, " ~%s;\n", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + } + } + + // output drivers + fprintf( pFile, "\n" ); + Gia_ManForEachCo( p, pObj, i ) + { + fprintf( pFile, " assign %s = ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + fprintf( pFile, "1\'b%d;\n", Gia_ObjFaninC0(pObj) ); + else + fprintf( pFile, "%s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); + } + + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); + + Vec_BitFree( vInvs ); + Vec_BitFree( vUsed ); +} /**Function************************************************************* @@ -1783,7 +2076,7 @@ void Gia_GenSandwich( char ** pFNames, int nFNames, char * pFileName ) fprintf( pFile, "endmodule\n" ); fclose( pFile ); for ( i = 0; i < nFNames; i++ ) { - Gia_ManDumpVerilog( pGias[i], Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v"), NULL, 0, 0, 1 ); + Gia_ManDumpVerilog( pGias[i], Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v"), NULL, 0, 0, 1, 0 ); printf( "Dumped Verilog file \"%s\"\n", Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v") ); } Gia_FreeMany( pGias, nFNames ); diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 5bc50032c..4ee12db27 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -31938,13 +31938,14 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) int fVerilog = 0; int fInter = 0; int fInterComb = 0; + int fAssign = 0; int fVerBufs = 0; int fMiniAig = 0; int fMiniLut = 0; int fWriteNewLine = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "upicbmlnvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "upicabmlnvh" ) ) != EOF ) { switch ( c ) { @@ -31959,7 +31960,10 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) break; case 'c': fInterComb ^= 1; - break; + break; + case 'a': + fAssign ^= 1; + break; case 'b': fVerBufs ^= 1; break; @@ -32001,7 +32005,7 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_ManStop( pGia ); } else if ( fVerilog ) - Gia_ManDumpVerilog( pAbc->pGia, pFileName, NULL, fVerBufs, fInter, fInterComb ); + Gia_ManDumpVerilog( pAbc->pGia, pFileName, NULL, fVerBufs, fInter, fInterComb, fAssign ); else if ( fMiniAig ) Gia_ManWriteMiniAig( pAbc->pGia, pFileName ); else if ( fMiniLut ) @@ -32011,12 +32015,13 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &w [-upicbmlnvh] \n" ); + Abc_Print( -2, "usage: &w [-upicabmlnvh] \n" ); Abc_Print( -2, "\t writes the current AIG into the AIGER file\n" ); Abc_Print( -2, "\t-u : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" ); Abc_Print( -2, "\t-p : toggle writing Verilog with 'and' and 'not' [default = %s]\n", fVerilog? "yes" : "no" ); Abc_Print( -2, "\t-i : toggle writing the interface module in Verilog [default = %s]\n", fInter? "yes" : "no" ); Abc_Print( -2, "\t-c : toggle writing the interface module in Verilog [default = %s]\n", fInterComb? "yes" : "no" ); + Abc_Print( -2, "\t-a : toggle writing the interface module with assign-statements [default = %s]\n", fAssign? "yes" : "no" ); Abc_Print( -2, "\t-b : toggle writing additional buffers in Verilog [default = %s]\n", fVerBufs? "yes" : "no" ); Abc_Print( -2, "\t-m : toggle writing MiniAIG rather than AIGER [default = %s]\n", fMiniAig? "yes" : "no" ); Abc_Print( -2, "\t-l : toggle writing MiniLUT rather than AIGER [default = %s]\n", fMiniLut? "yes" : "no" ); From 0f11580fcec78fab2e70960b330faa3bf5e6d1fe Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 24 Sep 2023 22:18:45 +0800 Subject: [PATCH 020/151] Experiments with retiming. --- src/aig/gia/giaMini.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/aig/gia/giaMini.c b/src/aig/gia/giaMini.c index 85647eac5..9b679af90 100644 --- a/src/aig/gia/giaMini.c +++ b/src/aig/gia/giaMini.c @@ -1257,7 +1257,7 @@ Vec_Str_t * Gia_ManRetimableF( Gia_Man_t * p, int * pRst, int * pSet, int * pEna int * pNode = Vec_IntEntryP( vTemps, 3*i ); pStops[i] = (char)1; if ( pFan0[0] != -1 && pFan0[0] == pFan1[0] && pFan0[1] == pFan1[1] && pFan0[2] == pFan1[2] ) - pStops[i] = (char)0, pNode[0] = pFan0[0], pNode[1] = pFan0[1], pNode[2] = pFan0[2]; + pStops[i] = (char)0, pNode[0] = pFan0[0], pNode[1] = pFan0[1], pNode[2] = pFan0[2]; } Vec_IntFree( vTemps ); return vStops; @@ -1266,32 +1266,37 @@ Vec_Str_t * Gia_ManRetimableB( Gia_Man_t * p, int * pRst, int * pSet, int * pEna { Vec_Str_t * vStops = Vec_StrStart( Gia_ManObjNum(p) ); Vec_Int_t * vTemps = Vec_IntStartFull( 3*Gia_ManObjNum(p) ); - Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i, n; + Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i, n, iFanout; char * pStops = Vec_StrArray(vStops); assert( Gia_ManRegNum(p) > 0 ); Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { - Vec_IntWriteEntry( vTemps, 3*Gia_ObjFaninId0p(p, pObjRi) + 0, pRst[i] ); - Vec_IntWriteEntry( vTemps, 3*Gia_ObjFaninId0p(p, pObjRi) + 1, pSet[i] ); - Vec_IntWriteEntry( vTemps, 3*Gia_ObjFaninId0p(p, pObjRi) + 2, pEna[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRi) + 0, pRst[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRi) + 1, pSet[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRi) + 2, pEna[i] ); } + Gia_ManStaticFanoutStart( p ); Gia_ManForEachAndReverse( p, pObj, i ) { - int iFans[2] = { Gia_ObjFaninId0(pObj, i), Gia_ObjFaninId1(pObj, i) }; - int * pFans[2] = { Vec_IntEntryP( vTemps, 3*iFans[0] ), Vec_IntEntryP( vTemps, 3*iFans[1] ) }; + int * pFan0 = Vec_IntEntryP( vTemps, 3*Gia_ObjFanoutId(p, i, 0) ); int * pNode = Vec_IntEntryP( vTemps, 3*i ); - if ( pNode[0] == -1 ) + pStops[i] = (char)1; + if ( pFan0[0] == -1 ) continue; - for ( n = 0; n < 2; n++ ) - if ( pFans[n][0] == -1 ) - pStops[iFans[n]] = (char)1, pFans[n][0] = pNode[0], pFans[n][1] = pNode[1], pFans[n][2] = pNode[2]; - else if ( pFans[n][0] != pNode[0] || pFans[n][1] != pNode[1] || pFans[n][2] != pNode[2] ) - pStops[iFans[n]] = (char)0; + Gia_ObjForEachFanoutStaticId( p, i, iFanout, n ) { + int * pFan1 = Vec_IntEntryP( vTemps, 3*iFanout ); + if ( pFan1[0] == -1 || pFan0[0] != pFan1[0] || pFan0[1] != pFan1[1] || pFan0[2] != pFan1[2] ) + break; + } + if ( n < Gia_ObjFanoutNum(p, pObj) ) + continue; + pStops[i] = (char)0, pNode[0] = pFan0[0], pNode[1] = pFan0[1], pNode[2] = pFan0[2]; } - pStops[0] = (char)0; - Gia_ManForEachCi( p, pObj, i ) - pStops[Gia_ObjId(p, pObj)] = (char)0; - Gia_ManForEachAnd( p, pObj, i ) - pStops[i] = (char)!pStops[i]; - Vec_IntFree( vTemps ); + Gia_ManStaticFanoutStop( p ); + Vec_IntFree( vTemps ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { + if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(pRst[i]))) ) pStops[Abc_Lit2Var(pRst[i])] = 1; + if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(pSet[i]))) ) pStops[Abc_Lit2Var(pSet[i])] = 1; + if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(pEna[i]))) ) pStops[Abc_Lit2Var(pEna[i])] = 1; + } return vStops; } From cc636a0d8390cb54ed2abad393c297d63e1ba52f Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 28 Sep 2023 06:40:57 -0700 Subject: [PATCH 021/151] Experiments with verification. --- src/base/abci/abc.c | 85 ++++++++++++++++ src/proof/cec/cecProve.c | 205 ++++++++++++++++++++++++++++++++++++++ src/proof/cec/module.make | 1 + 3 files changed, 291 insertions(+) create mode 100644 src/proof/cec/cecProve.c diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 4ee12db27..586ac2c57 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -541,6 +541,7 @@ static int Abc_CommandAbc9PoPart ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9GroupProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9MultiProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SplitProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SplitSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Bmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SBmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1314,6 +1315,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&gprove", Abc_CommandAbc9GroupProve, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&mprove", Abc_CommandAbc9MultiProve, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&splitprove", Abc_CommandAbc9SplitProve, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sprove", Abc_CommandAbc9SProve, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&splitsat", Abc_CommandAbc9SplitSat, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmc", Abc_CommandAbc9Bmc, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmcs", Abc_CommandAbc9SBmc, 0 ); @@ -46278,6 +46280,89 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9SProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int fVerbose, int fVeryVerbose, int fSilent ); + int c, nProcs = 5, nTimeOut = 3, fVerbose = 0, fVeryVerbose = 0, fSilent = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "PTsvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by a positive integer.\n" ); + goto usage; + } + nProcs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nProcs <= 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer.\n" ); + goto usage; + } + nTimeOut = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nTimeOut <= 0 ) + goto usage; + break; + case 's': + fSilent ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9SProve(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) == 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9SProve(): The problem is combinational.\n" ); + return 1; + } + pAbc->Status = Cec_GiaProveTest( pAbc->pGia, nProcs, nTimeOut, fVerbose, fVeryVerbose, fSilent ); + Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); + return 0; + +usage: + Abc_Print( -2, "usage: &sprove [-PT num] [-svwh]\n" ); + Abc_Print( -2, "\t proves CEC problem by case-splitting\n" ); + Abc_Print( -2, "\t-P num : the number of concurrent processes [default = %d]\n", nProcs ); + Abc_Print( -2, "\t-T num : runtime limit in seconds per subproblem [default = %d]\n", nTimeOut ); + Abc_Print( -2, "\t-s : enable silent computation (no reporting) [default = %s]\n", fSilent? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing more verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/proof/cec/cecProve.c b/src/proof/cec/cecProve.c new file mode 100644 index 000000000..748f506f9 --- /dev/null +++ b/src/proof/cec/cecProve.c @@ -0,0 +1,205 @@ +/**CFile**************************************************************** + + FileName [cecSplit.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Cofactoring for combinational miters.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecSplit.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "aig/gia/gia.h" +#include "aig/gia/giaAig.h" + + +#ifdef ABC_USE_PTHREADS + +#ifdef _WIN32 +#include "../lib/pthread.h" +#else +#include +#include +#endif + +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifndef ABC_USE_PTHREADS + +int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int fVerbose, int fVeryVerbose, int fSilent ) { return -1; } + +#else // pthreads are used + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_GiaProveOne( Gia_Man_t * p, int iEngine, int nTimeOut, Abc_Cex_t ** ppCex ) +{ + abctime clk = Abc_Clock(); + //abctime clkStop = nTimeOut * CLOCKS_PER_SEC + Abc_Clock(); + printf( "Calling engine %d with timeout %d sec.\n", iEngine, nTimeOut ); + if ( iEngine == 0 ) + { + } + else if ( iEngine == 1 ) + { + } + else if ( iEngine == 2 ) + { + } + else if ( iEngine == 3 ) + { + } + else assert( 0 ); + //while ( Abc_Clock() < clkStop ); + printf( "Engine %d finished. ", iEngine ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +#define PAR_THR_MAX 8 +typedef struct Par_ThData_t_ +{ + Gia_Man_t * p; + Abc_Cex_t * pCex; + int iEngine; + int fWorking; + int nTimeOut; + int Result; +} Par_ThData_t; +void * Cec_GiaProveWorkerThread( void * pArg ) +{ + Par_ThData_t * pThData = (Par_ThData_t *)pArg; + volatile int * pPlace = &pThData->fWorking; + while ( 1 ) + { + while ( *pPlace == 0 ); + assert( pThData->fWorking ); + if ( pThData->p == NULL ) + { + pthread_exit( NULL ); + assert( 0 ); + return NULL; + } + pThData->Result = Cec_GiaProveOne( pThData->p, pThData->iEngine, pThData->nTimeOut, &pThData->pCex ); + pThData->fWorking = 0; + } + assert( 0 ); + return NULL; +} +int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int fVerbose, int fVeryVerbose, int fSilent ) +{ + abctime clkTotal = Abc_Clock(); + Par_ThData_t ThData[PAR_THR_MAX]; + pthread_t WorkerThread[PAR_THR_MAX]; + int i, status, RetValue = -1; + Abc_CexFreeP( &p->pCexComb ); + Abc_CexFreeP( &p->pCexSeq ); + if ( fVerbose ) + printf( "Solving verification problem with the following parameters:\n" ); + if ( fVerbose ) + printf( "Processes = %d TimeOut = %d sec Verbose = %d.\n", nProcs, nTimeOut, fVerbose ); + fflush( stdout ); + if ( nProcs == 1 ) + return -1; + // subtract manager thread + nProcs--; + assert( (nProcs == 4 || nProcs == 8) && nProcs <= PAR_THR_MAX ); + // start threads + for ( i = 0; i < nProcs; i++ ) + { + ThData[i].p = Gia_ManDup(p); + ThData[i].pCex = NULL; + ThData[i].iEngine = i; + ThData[i].nTimeOut = nTimeOut; + ThData[i].fWorking = 0; + ThData[i].Result = -1; + status = pthread_create( WorkerThread + i, NULL,Cec_GiaProveWorkerThread, (void *)(ThData + i) ); assert( status == 0 ); + } + + for ( i = 0; i < nProcs; i++ ) + ThData[i].fWorking = 1; + + // wait till threads finish + for ( i = 0; i < nProcs; i++ ) + if ( ThData[i].fWorking ) + i = -1; + + // stop threads + for ( i = 0; i < nProcs; i++ ) + { + assert( !ThData[i].fWorking ); + // cleanup + Gia_ManStopP( &ThData[i].p ); + if ( !p->pCexSeq && ThData[i].pCex ) + p->pCexSeq = Abc_CexDup( ThData[i].pCex, -1 ); + Abc_CexFreeP( &ThData[i].pCex ); + // stop + ThData[i].p = NULL; + ThData[i].fWorking = 1; + } + if ( !fSilent ) + { + if ( RetValue == 0 ) + printf( "Problem is SAT " ); + else if ( RetValue == 1 ) + printf( "Problem is UNSAT " ); + else if ( RetValue == -1 ) + printf( "Problem is UNDECIDED " ); + else assert( 0 ); + printf( ". " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); + fflush( stdout ); + } + return RetValue; +} + +#endif // pthreads are used + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/module.make b/src/proof/cec/module.make index ed3dac110..ed8deba98 100644 --- a/src/proof/cec/module.make +++ b/src/proof/cec/module.make @@ -6,6 +6,7 @@ SRC += src/proof/cec/cecCec.c \ src/proof/cec/cecIso.c \ src/proof/cec/cecMan.c \ src/proof/cec/cecPat.c \ + src/proof/cec/cecProve.c \ src/proof/cec/cecSat.c \ src/proof/cec/cecSatG.c \ src/proof/cec/cecSatG2.c \ From d971e3ecffd89800b95e82ff22eb294cc421599b Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 28 Sep 2023 07:17:42 -0700 Subject: [PATCH 022/151] Updating windows project file. --- abclib.dsp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/abclib.dsp b/abclib.dsp index 7433c5139..3255424db 100644 --- a/abclib.dsp +++ b/abclib.dsp @@ -5627,6 +5627,10 @@ SOURCE=.\src\proof\cec\cecPat.c # End Source File # Begin Source File +SOURCE=.\src\proof\cec\cecProve.c +# End Source File +# Begin Source File + SOURCE=.\src\proof\cec\cecSat.c # End Source File # Begin Source File From 65ccd3cc692d2a7976d7d57954bc2572ddb9c9c9 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 29 Sep 2023 16:07:29 -0700 Subject: [PATCH 023/151] Enabled literal remapping. --- src/aig/gia/giaMini.c | 30 +++++++++++++++++++++++++++--- src/base/main/abcapis.h | 2 +- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/aig/gia/giaMini.c b/src/aig/gia/giaMini.c index 9b679af90..2fce5d0d4 100644 --- a/src/aig/gia/giaMini.c +++ b/src/aig/gia/giaMini.c @@ -1311,18 +1311,42 @@ Vec_Str_t * Gia_ManRetimableB( Gia_Man_t * p, int * pRst, int * pSet, int * pEna SeeAlso [] ***********************************************************************/ -void Abc_FrameSetRetimingData( Abc_Frame_t * pAbc, int * pRst, int * pSet, int * pEna ) +void Abc_FrameRemapLits( int * pLits, int nLits, Vec_Int_t * vMap ) +{ + for ( int i = 0; i < nLits; i++ ) + pLits[i] = Abc_Lit2LitL( Vec_IntArray(vMap), pLits[i] ); +} +void Abc_FrameSetRetimingData( Abc_Frame_t * pAbc, int * pRst, int * pSet, int * pEna, int nRegs ) { Gia_Man_t * pGia; + int * pRstNew = ABC_CALLOC( int, nRegs ); + int * pSetNew = ABC_CALLOC( int, nRegs ); + int * pEnaNew = ABC_CALLOC( int, nRegs ); if ( pAbc == NULL ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); pGia = Abc_FrameReadGia( pAbc ); if ( pGia == NULL ) printf( "Current network in ABC framework is not defined.\n" ); + else { + assert( nRegs == Gia_ManRegNum(pGia) ); + memmove( pRstNew, pRst, sizeof(int)*nRegs ); + memmove( pSetNew, pSet, sizeof(int)*nRegs ); + memmove( pEnaNew, pEna, sizeof(int)*nRegs ); + } + if ( pAbc->vCopyMiniAig == NULL ) + printf( "Mapping of MiniAig nodes is not available.\n" ); + else { + Abc_FrameRemapLits( pRstNew, nRegs, pAbc->vCopyMiniAig ); + Abc_FrameRemapLits( pSetNew, nRegs, pAbc->vCopyMiniAig ); + Abc_FrameRemapLits( pEnaNew, nRegs, pAbc->vCopyMiniAig ); + } assert( pGia->vStopsF == NULL ); assert( pGia->vStopsB == NULL ); - pGia->vStopsF = Gia_ManRetimableF( pGia, pRst, pSet, pEna ); - pGia->vStopsB = Gia_ManRetimableB( pGia, pRst, pSet, pEna ); + pGia->vStopsF = Gia_ManRetimableF( pGia, pRstNew, pSetNew, pEnaNew ); + pGia->vStopsB = Gia_ManRetimableB( pGia, pRstNew, pSetNew, pEnaNew ); + ABC_FREE( pRstNew ); + ABC_FREE( pSetNew ); + ABC_FREE( pEnaNew ); } //////////////////////////////////////////////////////////////////////// diff --git a/src/base/main/abcapis.h b/src/base/main/abcapis.h index e1e05f4c7..30494f77c 100644 --- a/src/base/main/abcapis.h +++ b/src/base/main/abcapis.h @@ -107,7 +107,7 @@ extern ABC_DLL int Abc_FrameReadProbStatus( Abc_Frame_t * pAbc ); extern ABC_DLL void * Abc_FrameReadCex( Abc_Frame_t * pAbc ); // procedure to set retiming data -extern ABC_DLL void Abc_FrameSetRetimingData( Abc_Frame_t * pAbc, int * pRst, int * pSet, int * pEna ); +extern ABC_DLL void Abc_FrameSetRetimingData( Abc_Frame_t * pAbc, int * pRst, int * pSet, int * pEna, int nRegs ); // procedure to return sequential equivalences extern ABC_DLL int * Abc_FrameReadMiniAigEquivClasses( Abc_Frame_t * pAbc ); From 3c4c558656a35c6947569eb703412380b0f5b22d Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 2 Oct 2023 16:47:37 -0700 Subject: [PATCH 024/151] Experiment with script generation. --- src/base/cmd/cmd.c | 75 +++++++++++++++++++++++++++++++++++++++++ src/base/cmd/cmdUtils.c | 64 +++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index 630355fa5..80ba52612 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -59,6 +59,7 @@ static int CmdCommandScrGen ( Abc_Frame_t * pAbc, int argc, char ** argv static int CmdCommandScrGenLinux ( Abc_Frame_t * pAbc, int argc, char ** argv ); #endif static int CmdCommandVersion ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandSGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandSis ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandMvsis ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandCapo ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -111,6 +112,7 @@ void Cmd_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Basic", "scrgen", CmdCommandScrGenLinux, 0 ); #endif Cmd_CommandAdd( pAbc, "Basic", "version", CmdCommandVersion, 0 ); + Cmd_CommandAdd( pAbc, "Basic", "sgen", CmdCommandSGen, 0 ); Cmd_CommandAdd( pAbc, "Various", "sis", CmdCommandSis, 1 ); Cmd_CommandAdd( pAbc, "Various", "mvsis", CmdCommandMvsis, 1 ); @@ -2761,6 +2763,79 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CmdCommandSGen( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Cmd_CommandSGen( Abc_Frame_t * pAbc, int nParts, int nIters, int fVerbose ); + int c, nParts = 10; + int nIters = 10; + int fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NIvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nParts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nParts < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a string (possibly in quotes).\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( Abc_FrameReadNtk(pAbc) == NULL ) + { + Abc_Print( -2, "There is no current network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(Abc_FrameReadNtk(pAbc)) ) + { + Abc_Print( -2, "The current network is not an AIG.\n" ); + return 1; + } + Cmd_CommandSGen( pAbc, nParts, nIters, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: sgen [-N num] [-I num] [-vh]\n" ); + Abc_Print( -2, "\t experiment with script generation\n" ); + Abc_Print( -2, "\t-N num : the number of commands to use [default = %d]\n", nParts ); + Abc_Print( -2, "\t-I num : the number of iterations to perform [default = %d]\n", nIters ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/base/cmd/cmdUtils.c b/src/base/cmd/cmdUtils.c index 2158f8e97..a5dc6972b 100644 --- a/src/base/cmd/cmdUtils.c +++ b/src/base/cmd/cmdUtils.c @@ -833,6 +833,70 @@ void Gia_ManKissatCall( Abc_Frame_t * pAbc, char * pFileName, char * pArgs, int } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Cmd_GenScript( char ** pComms, int nComms, int nParts ) +{ + static char pScript[1000]; int c; + pScript[0] = 0; + for ( c = 0; c < nParts; c++ ) { + strcat( pScript, pComms[rand() % nComms] ); + strcat( pScript, "; " ); + } + strcat( pScript, "print_stats" ); + return pScript; +} +void Cmd_CommandSGen( Abc_Frame_t * pAbc, int nParts, int nIters, int fVerbose ) +{ + Abc_Ntk_t * pCopy = Abc_NtkDup( Abc_FrameReadNtk(pAbc) ); + Abc_Ntk_t * pBest = Abc_NtkDup( Abc_FrameReadNtk(pAbc) ); + Abc_Ntk_t * pCur = NULL; int i; + char * pComms[6] = { "balance", "rewrite", "rewrite -z", "refactor", "refactor -z", "resub" }; + srand( time(NULL) ); + for ( i = 0; i < nIters; i++ ) + { + char * pScript = Cmd_GenScript( pComms, 6, nParts ); + Abc_FrameSetCurrentNetwork( pAbc, Abc_NtkDup(pCopy) ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(pAbc, pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(pAbc, pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + Abc_FrameSetBatchMode( 0 ); + return; + } + Abc_FrameSetBatchMode( 0 ); + } + pCur = Abc_FrameReadNtk(pAbc); + if ( Abc_NtkNodeNum(pCur) < Abc_NtkNodeNum(pBest) ) { + Abc_Obj_t * pObj; int k; + Abc_NtkForEachObj( pBest, pObj, k ) + pObj->fMarkA = pObj->fMarkB = pObj->fMarkC = 0; + Abc_NtkDelete( pBest ); + pBest = Abc_NtkDup( pCur ); + } + } + Abc_FrameSetCurrentNetwork( pAbc, pBest ); + Abc_NtkDelete( pCopy ); +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// From 72b423ba14e416463a06c66c7c908250f4458f45 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 20 Oct 2023 20:53:43 -0700 Subject: [PATCH 025/151] Experiments with SAT solving. --- src/aig/gia/giaUtil.c | 113 ++++++++++++++++++++++++++++++++++++++++++ src/base/abci/abc.c | 91 +++++++++++++++++++++++++++++++++- src/base/io/io.c | 71 ++++++++++++++++++++++++++ src/base/io/ioUtil.c | 87 ++++++++++++++++++++++++++++++++ 4 files changed, 361 insertions(+), 1 deletion(-) diff --git a/src/aig/gia/giaUtil.c b/src/aig/gia/giaUtil.c index dfddc6931..69a6e7235 100644 --- a/src/aig/gia/giaUtil.c +++ b/src/aig/gia/giaUtil.c @@ -3161,6 +3161,119 @@ void Gia_ManPrintArray( Gia_Man_t * p ) printf( "};\n" ); } + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_GetMValue( int i, int nIns, int Mint, unsigned Truth ) +{ + assert( i >= 0 && i < 16 ); + if ( i < nIns ) + return (Mint >> i) & 1; + if ( i == nIns ) + { + if ( Mint < (1 << nIns) ) + return (Truth >> Mint) & 1; + else + return ((Truth >> (Mint-(1 << nIns))) & 1) == 0; + } + else + return 1; +} +void Gia_ManTestProblem() +{ + unsigned Truth = 0xFE; + int i, j, k, c, nIns = 3, nAux = 3; + int nTotal = nIns + 1 + nAux; + int nPairs = nTotal * (nTotal - 1) / 2; + int nMints = (1 << (nIns+1)); + int M[64][100] = {{0}}; + float Value[64] = {0}; + float Solution[100] = {0}; + assert( nMints <= 64 ); + assert( nPairs <= 100 ); + // 7 nodes: 3 inputs + 1 output + 3 aux + // 7*6/2 = 21 pairs + // 16 minterms + for ( k = 0; k < nMints; k++ ) + { + for ( i = c = 0; i < nTotal; i++ ) + for ( j = i+1; j < nTotal; j++ ) + { + int iVal = Gia_GetMValue( i, nIns, k, Truth ); + int jVal = Gia_GetMValue( j, nIns, k, Truth ); + M[k][c++] = iVal == jVal ? 1 : -1; + } + Value[k] = k < (1 << nIns) ? -1 : 1; + assert( c == nPairs ); + } + + for ( k = 0; k < nMints; k++ ) + { + for ( c = 0; c < nPairs; c++ ) + printf( "%2d ", M[k][c] ); + printf( "%3f\n", Value[k] ); + } + + // solve + float Delta = 0.02; + for ( i = 0; i < 100; i++ ) + { + float Error = 0; + for ( k = 0; k < nMints; k++ ) + Error += Value[k] > 0 ? Value[k] : -Value[k]; + printf( "Round %3d : Error = %5f ", i, Error ); + for ( c = 0; c < nPairs; c++ ) + printf( "%2f ", Solution[c] ); + printf( "\n" ); + + //if ( Error < 1 ) + // Delta /= 10; + + for ( c = 0; c < nPairs; c++ ) + { + int Count = 0; + for ( k = 0; k < nMints; k++ ) + if ( (M[k][c] > 0 && Value[k] > 0) || (M[k][c] < 0 && Value[k] < 0) ) + Count++; + else + Count--; + if ( Count == 0 ) + continue; + printf( "Count = %3d ", Count ); + if ( Count > 0 ) + { + printf( "Increasing %d by %f\n", c, Delta ); + Solution[c] += Delta; + for ( k = 0; k < nMints; k++ ) + if ( M[k][c] > 0 ) + Value[k] -= Delta; + else + Value[k] -= Delta; + } + else + { + printf( "Reducing %d by %f\n", c, Delta ); + Solution[c] -= Delta; + for ( k = 0; k < nMints; k++ ) + if ( M[k][c] > 0 ) + Value[k] += Delta; + else + Value[k] += Delta; + } + } + } +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 586ac2c57..43207c887 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -139,6 +139,7 @@ static int Abc_CommandTestDec ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandTestNpn ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestRPO ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestTruth ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRunSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -914,6 +915,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "testnpn", Abc_CommandTestNpn, 0 ); Cmd_CommandAdd( pAbc, "LogiCS", "testrpo", Abc_CommandTestRPO, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "testtruth", Abc_CommandTestTruth, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "runsat", Abc_CommandRunSat, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "runeco", Abc_CommandRunEco, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "rungen", Abc_CommandRunGen, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "xec", Abc_CommandRunTest, 0 ); @@ -7168,6 +7170,93 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRunSat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pFile = NULL; + char * pFileCnf = NULL; + int c, i, fWalk = 0, fKissat = 0, nIters = 10, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ikwvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'k': + fKissat ^= 1; + break; + case 'w': + fWalk ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( fKissat + fWalk != 1 ) { + printf( "Exactly one SAT solver should be selected.\n" ); + return 1; + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + pFileCnf = argv[globalUtilOptind]; + pFile = fopen( pFileCnf, "rb" ); + if ( pFile == NULL ) { + printf( "The file \"%s\" cannot be found.\n", pFileCnf ); + return 1; + } + fclose( pFile ); + abctime clk = Abc_Clock(); + for ( i = 0; i < nIters; i++ ) { + char pCommand[1000]; + if ( fKissat ) + sprintf( pCommand, "kissat -q --seed=%d %s", i, pFileCnf ); + else if ( fWalk ) + sprintf( pCommand, "walk -s%d %s", i, pFileCnf ); + if (system(pCommand) == -1) { + fprintf(stdout, "Command \"%s\" did not succeed.\n", pCommand); + return 0; + } + } + printf( "Performed %d iterations of SAT solving. ", nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return 0; + +usage: + Abc_Print( -2, "usage: runsat [-I num] [-kwvh] \n" ); + Abc_Print( -2, "\t performs randomized iterations of SAT solving\n" ); + Abc_Print( -2, "\t-I num : the number of iterations [default = %d]\n", nIters ); + Abc_Print( -2, "\t-k : toggle using Kissat (binary name \"kissat\") [default = %s]\n", fKissat? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle using WalkSat (binary name \"walk\") [default = %s]\n", fWalk? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -14622,7 +14711,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } */ - + //Gia_ManTestProblem(); return 0; usage: Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] \n" ); diff --git a/src/base/io/io.c b/src/base/io/io.c index e808d1d0b..f988a0078 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -52,6 +52,7 @@ static int IoCommandReadInit ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadPla ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadPlaMo ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadTruth ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadCnf ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadVerilog ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadStatus ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadGig ( Abc_Frame_t * pAbc, int argc, char **argv ); @@ -124,6 +125,7 @@ void Io_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "I/O", "read_pla", IoCommandReadPla, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_plamo", IoCommandReadPlaMo, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_truth", IoCommandReadTruth, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_cnf", IoCommandReadCnf, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_verilog", IoCommandReadVerilog, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_status", IoCommandReadStatus, 0 ); Cmd_CommandAdd( pAbc, "I/O", "&read_gig", IoCommandReadGig, 0 ); @@ -1209,6 +1211,75 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadCnf( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Vec_Ptr_t * Io_FileReadCnf( char * pFileName ); + FILE * pFile; + Abc_Ntk_t * pNtk; + Vec_Ptr_t * vSops; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + goto usage; + + pFile = fopen( argv[globalUtilOptind], "rb" ); + if ( pFile == NULL ) + { + printf( "The file \"%s\" cannot be found.\n", argv[globalUtilOptind] ); + return 1; + } + else + fclose( pFile ); + vSops = Io_FileReadCnf( argv[globalUtilOptind] ); + if ( Vec_PtrSize(vSops) == 0 ) + { + Vec_PtrFreeFree( vSops ); + fprintf( pAbc->Err, "Reading CNF file has failed.\n" ); + return 1; + } + pNtk = Abc_NtkCreateWithNodes( vSops ); + Vec_PtrFreeFree( vSops ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Deriving the network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + Abc_FrameClearVerifStatus( pAbc ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_cnf [-h] \n" ); + fprintf( pAbc->Err, "\t creates network with one node\n" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : file name with the truth table\n" ); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c index eef80efa3..e57fa9574 100644 --- a/src/base/io/ioUtil.c +++ b/src/base/io/ioUtil.c @@ -920,6 +920,93 @@ void Io_TransformSF2PLA( char * pNameIn, char * pNameOut ) ABC_FREE( pBuffer ); } +/**Function************************************************************* + + Synopsis [Reads CNF from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Io_ConvertNumsToSop( Vec_Wec_t * vNums, int nVars ) +{ + Vec_Int_t * vLevel; int i, k, Num; + int nSize = (nVars + 3)*Vec_WecSize(vNums); + char * pStr = ABC_ALLOC( char, nSize+1 ); + memset( pStr, '-', nSize ); + pStr[nSize] = 0; + Vec_WecForEachLevel( vNums, vLevel, i ) + { + char * pCube = pStr + (nVars + 3)*i; + Vec_IntForEachEntry( vLevel, Num, k ) + pCube[Abc_Lit2Var(Num)] = '0' + Abc_LitIsCompl(Num); + pCube[nVars+0] = ' '; + pCube[nVars+1] = '1'; + pCube[nVars+2] = '\n'; + } + return pStr; +} +Vec_Ptr_t * Io_FileReadCnf( char * pFileName ) +{ + Vec_Ptr_t * vSops = Vec_PtrAlloc( 1 ); + Vec_Wec_t * vNums = Vec_WecAlloc( 100 ); + Vec_Int_t * vLevel; + char * pThis, pLine[10000]; + int nVars = -1, nClas = -1; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + while ( fgets( pLine, 10000, pFile ) ) + { + if ( pLine[0] == 'c' ) + continue; + if ( pLine[0] == 'p' ) + { + pThis = strtok(pLine+1, " \t\n\r"); + if ( strcmp(pThis, "cnf") ) + { + Vec_PtrFree( vSops ); + Vec_WecFree( vNums ); + fclose( pFile ); + printf( "Wrong file format.\n" ); + return NULL; + } + pThis = strtok(NULL, " \t\n\r"); + nVars = atoi(pThis); + pThis = strtok(NULL, " \t\n\r"); + nClas = atoi(pThis); + continue; + } + pThis = strtok(pLine, " \t\n\r"); + if ( pThis == NULL ) + continue; + vLevel = Vec_WecPushLevel( vNums ); + while ( pThis ) { + int fComp, Temp = atoi(pThis); + if ( Temp == 0 ) + break; + fComp = Temp < 0; + Temp = Temp < 0 ? -Temp : Temp; + Temp -= 1; + assert( Temp < nVars ); + Vec_IntPush( vLevel, Abc_Var2Lit(Temp, fComp) ); + pThis = strtok(NULL, " \t\n\r"); + } + } + fclose( pFile ); + if ( nClas != Vec_WecSize(vNums) ) + printf( "Warning: The number of clauses (%d) listed is different from the actual number (%d).\n", nClas, Vec_WecSize(vNums) ); + //Vec_WecPrint( vNums, 0 ); + Vec_PtrPush( vSops, Io_ConvertNumsToSop(vNums, nVars) ); + Vec_WecFree( vNums ); + return vSops; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// From 652a0aaef7804280eb2a9721d7e85dda946543ac Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 20 Oct 2023 22:42:40 -0700 Subject: [PATCH 026/151] Compiler warning. --- src/base/abci/abc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 43207c887..f93d03ff0 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -7186,6 +7186,7 @@ int Abc_CommandRunSat( Abc_Frame_t * pAbc, int argc, char ** argv ) FILE * pFile = NULL; char * pFileCnf = NULL; int c, i, fWalk = 0, fKissat = 0, nIters = 10, fVerbose = 0; + abctime clk; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Ikwvh" ) ) != EOF ) { @@ -7230,7 +7231,7 @@ int Abc_CommandRunSat( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } fclose( pFile ); - abctime clk = Abc_Clock(); + clk = Abc_Clock(); for ( i = 0; i < nIters; i++ ) { char pCommand[1000]; if ( fKissat ) From 8dbf8965fdbbabc1101412272b2ef0ff9140b578 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 23 Oct 2023 09:37:04 -0700 Subject: [PATCH 027/151] Adding batch option to "scrgen". --- src/base/cmd/cmd.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index 80ba52612..d8ba90f58 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -1867,10 +1867,11 @@ int CmdCommandScrGenLinux( Abc_Frame_t * pAbc, int argc, char **argv ) char * pWriteExt = NULL; char Line[2000], * pName; int nFileNameMax; + int fBatch = 0; int c, k; Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "FRCWEh") ) != EOF ) + while ( (c = Extra_UtilGetopt(argc, argv, "FRCWEbh") ) != EOF ) { switch (c) { @@ -1919,6 +1920,9 @@ int CmdCommandScrGenLinux( Abc_Frame_t * pAbc, int argc, char **argv ) pWriteExt = argv[globalUtilOptind]; globalUtilOptind++; break; + case 'b': + fBatch ^= 1; + break; default: goto usage; } @@ -1952,7 +1956,7 @@ int CmdCommandScrGenLinux( Abc_Frame_t * pAbc, int argc, char **argv ) char * pExt = strstr(pName, "."); if ( !pExt || !strcmp(pExt, ".") || !strcmp(pExt, "..") || !strcmp(pExt, ".s") || !strcmp(pExt, ".txt") ) continue; - sprintf( Line, "%sread %s%s%-*s ; %s", fAndSpace ? "&" : "", pDirStr?pDirStr:"", pDirStr?"/":"", nFileNameMax, pName, pComStr ); + sprintf( Line, "%s%sread %s%s%-*s ; %s", fBatch ? "./abc -c \"":"", fAndSpace ? "&" : "", pDirStr?pDirStr:"", pDirStr?"/":"", nFileNameMax, pName, pComStr ); for ( c = (int)strlen(Line)-1; c >= 0; c-- ) if ( Line[c] == '\\' ) Line[c] = '/'; @@ -1966,6 +1970,8 @@ int CmdCommandScrGenLinux( Abc_Frame_t * pAbc, int argc, char **argv ) Line[c] = '/'; fprintf( pFile, "%s", Line ); } + if ( fBatch ) + fprintf( pFile, "\"" ); fprintf( pFile, "\n" ); } } @@ -1975,13 +1981,14 @@ int CmdCommandScrGenLinux( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; usage: - fprintf( pAbc->Err, "usage: scrgen -F -R -C -W -E -h\n" ); + fprintf( pAbc->Err, "usage: scrgen -F -R -C -W -E -bh\n" ); fprintf( pAbc->Err, "\t generates script for running ABC\n" ); fprintf( pAbc->Err, "\t-F str : the name of the script file [default = \"test.s\"]\n" ); fprintf( pAbc->Err, "\t-R str : the directory to read files from [default = current]\n" ); fprintf( pAbc->Err, "\t-C str : the sequence of commands to run [default = \"ps\"]\n" ); fprintf( pAbc->Err, "\t-W str : the directory to write the resulting files [default = no writing]\n" ); fprintf( pAbc->Err, "\t-E str : the output files extension (with \".\") [default = the same as input files]\n" ); + fprintf( pAbc->Err, "\t-b : toggles adding batch mode support [default = %s]\n", fBatch? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the command usage\n\n"); fprintf( pAbc->Err, "\tExample : scrgen -F test1.s -R a/in -C \"ps; st; ps\" -W a/out -E .blif\n" ); return 1; From 01ad71b26f983b61ea0faae7eacb2cc60a285793 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 23 Oct 2023 09:38:08 -0700 Subject: [PATCH 028/151] Experiments with verification. --- src/base/abci/abc.c | 34 +++++- src/base/io/ioUtil.c | 2 +- src/proof/cec/cecProve.c | 216 +++++++++++++++++++++++++++++++-------- 3 files changed, 204 insertions(+), 48 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index f93d03ff0..0558eefa4 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -46383,10 +46383,10 @@ usage: ***********************************************************************/ int Abc_CommandAbc9SProve( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int fVerbose, int fVeryVerbose, int fSilent ); - int c, nProcs = 5, nTimeOut = 3, fVerbose = 0, fVeryVerbose = 0, fSilent = 0; + extern int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fVerbose, int fVeryVerbose, int fSilent ); + int c, nProcs = 5, nTimeOut = 3, nTimeOut2 = 10, nTimeOut3 = 100, fVerbose = 0, fVeryVerbose = 0, fSilent = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PTsvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PTUWsvwh" ) ) != EOF ) { switch ( c ) { @@ -46412,6 +46412,28 @@ int Abc_CommandAbc9SProve( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nTimeOut <= 0 ) goto usage; break; + case 'U': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-U\" should be followed by a positive integer.\n" ); + goto usage; + } + nTimeOut2 = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nTimeOut2 <= 0 ) + goto usage; + break; + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" ); + goto usage; + } + nTimeOut3 = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nTimeOut3 <= 0 ) + goto usage; + break; case 's': fSilent ^= 1; break; @@ -46437,15 +46459,17 @@ int Abc_CommandAbc9SProve( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9SProve(): The problem is combinational.\n" ); return 1; } - pAbc->Status = Cec_GiaProveTest( pAbc->pGia, nProcs, nTimeOut, fVerbose, fVeryVerbose, fSilent ); + pAbc->Status = Cec_GiaProveTest( pAbc->pGia, nProcs, nTimeOut, nTimeOut2, nTimeOut3, fVerbose, fVeryVerbose, fSilent ); Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); return 0; usage: - Abc_Print( -2, "usage: &sprove [-PT num] [-svwh]\n" ); + Abc_Print( -2, "usage: &sprove [-PTUW num] [-svwh]\n" ); Abc_Print( -2, "\t proves CEC problem by case-splitting\n" ); Abc_Print( -2, "\t-P num : the number of concurrent processes [default = %d]\n", nProcs ); Abc_Print( -2, "\t-T num : runtime limit in seconds per subproblem [default = %d]\n", nTimeOut ); + Abc_Print( -2, "\t-U num : runtime limit in seconds per subproblem [default = %d]\n", nTimeOut2 ); + Abc_Print( -2, "\t-W num : runtime limit in seconds per subproblem [default = %d]\n", nTimeOut3 ); Abc_Print( -2, "\t-s : enable silent computation (no reporting) [default = %s]\n", fSilent? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing more verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c index e57fa9574..d11ee7408 100644 --- a/src/base/io/ioUtil.c +++ b/src/base/io/ioUtil.c @@ -944,7 +944,7 @@ char * Io_ConvertNumsToSop( Vec_Wec_t * vNums, int nVars ) Vec_IntForEachEntry( vLevel, Num, k ) pCube[Abc_Lit2Var(Num)] = '0' + Abc_LitIsCompl(Num); pCube[nVars+0] = ' '; - pCube[nVars+1] = '1'; + pCube[nVars+1] = '0'; pCube[nVars+2] = '\n'; } return pStr; diff --git a/src/proof/cec/cecProve.c b/src/proof/cec/cecProve.c index 748f506f9..b3ddcd8a1 100644 --- a/src/proof/cec/cecProve.c +++ b/src/proof/cec/cecProve.c @@ -22,6 +22,11 @@ #include "aig/gia/gia.h" #include "aig/gia/giaAig.h" +#include "sat/bmc/bmc.h" +#include "proof/pdr/pdr.h" +#include "proof/cec/cec.h" +#include "proof/ssw/ssw.h" + #ifdef ABC_USE_PTHREADS @@ -41,9 +46,12 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +extern int Ssw_RarSimulateGia( Gia_Man_t * p, Ssw_RarPars_t * pPars ); +extern int Bmcg_ManPerform( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ); + #ifndef ABC_USE_PTHREADS -int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int fVerbose, int fVeryVerbose, int fSilent ) { return -1; } +int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fVerbose, int fVeryVerbose, int fSilent ) { return -1; } #else // pthreads are used @@ -62,28 +70,106 @@ int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int fVerbose, int SeeAlso [] ***********************************************************************/ -int Cec_GiaProveOne( Gia_Man_t * p, int iEngine, int nTimeOut, Abc_Cex_t ** ppCex ) +int Cec_GiaProveOne( Gia_Man_t * p, int iEngine, int nTimeOut, int fVerbose ) { - abctime clk = Abc_Clock(); + abctime clk = Abc_Clock(); + int RetValue = -1; //abctime clkStop = nTimeOut * CLOCKS_PER_SEC + Abc_Clock(); + if ( fVerbose ) printf( "Calling engine %d with timeout %d sec.\n", iEngine, nTimeOut ); + Abc_CexFreeP( &p->pCexSeq ); if ( iEngine == 0 ) { + Ssw_RarPars_t Pars, * pPars = &Pars; + Ssw_RarSetDefaultParams( pPars ); + pPars->TimeOut = nTimeOut; + pPars->fSilent = 1; + RetValue = Ssw_RarSimulateGia( p, pPars ); } else if ( iEngine == 1 ) { - } + Saig_ParBmc_t Pars, * pPars = &Pars; + Saig_ParBmcSetDefaultParams( pPars ); + pPars->nTimeOut = nTimeOut; + pPars->fSilent = 1; + Aig_Man_t * pAig = Gia_ManToAigSimple( p ); + RetValue = Saig_ManBmcScalable( pAig, pPars ); + p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + } else if ( iEngine == 2 ) { - } + Pdr_Par_t Pars, * pPars = &Pars; + Pdr_ManSetDefaultParams( pPars ); + pPars->nTimeOut = nTimeOut; + pPars->fSilent = 1; + Aig_Man_t * pAig = Gia_ManToAigSimple( p ); + RetValue = Pdr_ManSolve( pAig, pPars ); + p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + } else if ( iEngine == 3 ) { + Saig_ParBmc_t Pars, * pPars = &Pars; + Saig_ParBmcSetDefaultParams( pPars ); + pPars->fUseGlucose = 1; + pPars->nTimeOut = nTimeOut; + pPars->fSilent = 1; + Aig_Man_t * pAig = Gia_ManToAigSimple( p ); + RetValue = Saig_ManBmcScalable( pAig, pPars ); + p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + } + else if ( iEngine == 4 ) + { + Pdr_Par_t Pars, * pPars = &Pars; + Pdr_ManSetDefaultParams( pPars ); + pPars->fUseAbs = 1; + pPars->nTimeOut = nTimeOut; + pPars->fSilent = 1; + Aig_Man_t * pAig = Gia_ManToAigSimple( p ); + RetValue = Pdr_ManSolve( pAig, pPars ); + p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + } + else if ( iEngine == 5 ) + { + Bmc_AndPar_t Pars, * pPars = &Pars; + memset( pPars, 0, sizeof(Bmc_AndPar_t) ); + pPars->nProcs = 1; // the number of parallel solvers + pPars->nFramesAdd = 1; // the number of additional frames + pPars->fNotVerbose = 1; // silent + pPars->nTimeOut = nTimeOut; // timeout in seconds + RetValue = Bmcg_ManPerform( p, pPars ); } else assert( 0 ); //while ( Abc_Clock() < clkStop ); - printf( "Engine %d finished. ", iEngine ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - return 0; + if ( fVerbose ) { + printf( "Engine %d finished and %ssolved the problem. ", iEngine, RetValue != -1 ? " " : "not " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + return RetValue; +} +Gia_Man_t * Cec_GiaScorrOld( Gia_Man_t * p ) +{ + Ssw_Pars_t Pars, * pPars = &Pars; + Ssw_ManSetDefaultParams( pPars ); + Aig_Man_t * pAig = Gia_ManToAigSimple( p ); + Aig_Man_t * pAig2 = Ssw_SignalCorrespondence( pAig, pPars ); + Gia_Man_t * pGia2 = Gia_ManFromAigSimple( pAig2 ); + Aig_ManStop( pAig2 ); + Aig_ManStop( pAig ); + return pGia2; +} +Gia_Man_t * Cec_GiaScorrNew( Gia_Man_t * p ) +{ + Cec_ParCor_t Pars, * pPars = &Pars; + Cec_ManCorSetDefaultParams( pPars ); + pPars->nBTLimit = 100; + pPars->nLevelMax = 100; + pPars->fVerbose = 0; + pPars->fUseCSat = 1; + return Cec_ManLSCorrespondence( p, pPars ); } /**Function************************************************************* @@ -101,11 +187,11 @@ int Cec_GiaProveOne( Gia_Man_t * p, int iEngine, int nTimeOut, Abc_Cex_t ** ppCe typedef struct Par_ThData_t_ { Gia_Man_t * p; - Abc_Cex_t * pCex; int iEngine; int fWorking; int nTimeOut; int Result; + int fVerbose; } Par_ThData_t; void * Cec_GiaProveWorkerThread( void * pArg ) { @@ -121,73 +207,119 @@ void * Cec_GiaProveWorkerThread( void * pArg ) assert( 0 ); return NULL; } - pThData->Result = Cec_GiaProveOne( pThData->p, pThData->iEngine, pThData->nTimeOut, &pThData->pCex ); + pThData->Result = Cec_GiaProveOne( pThData->p, pThData->iEngine, pThData->nTimeOut, pThData->fVerbose ); pThData->fWorking = 0; } assert( 0 ); return NULL; } -int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int fVerbose, int fVeryVerbose, int fSilent ) +void Cec_GiaInitThreads( Par_ThData_t * ThData, int nProcs, Gia_Man_t * p, int nTimeOut, int fVerbose, pthread_t * WorkerThread ) { - abctime clkTotal = Abc_Clock(); - Par_ThData_t ThData[PAR_THR_MAX]; - pthread_t WorkerThread[PAR_THR_MAX]; - int i, status, RetValue = -1; - Abc_CexFreeP( &p->pCexComb ); - Abc_CexFreeP( &p->pCexSeq ); - if ( fVerbose ) - printf( "Solving verification problem with the following parameters:\n" ); - if ( fVerbose ) - printf( "Processes = %d TimeOut = %d sec Verbose = %d.\n", nProcs, nTimeOut, fVerbose ); - fflush( stdout ); - if ( nProcs == 1 ) - return -1; - // subtract manager thread - nProcs--; - assert( (nProcs == 4 || nProcs == 8) && nProcs <= PAR_THR_MAX ); - // start threads + int i, status; + assert( nProcs <= PAR_THR_MAX ); for ( i = 0; i < nProcs; i++ ) { ThData[i].p = Gia_ManDup(p); - ThData[i].pCex = NULL; ThData[i].iEngine = i; ThData[i].nTimeOut = nTimeOut; ThData[i].fWorking = 0; ThData[i].Result = -1; + ThData[i].fVerbose = fVerbose; + if ( !WorkerThread ) + continue; status = pthread_create( WorkerThread + i, NULL,Cec_GiaProveWorkerThread, (void *)(ThData + i) ); assert( status == 0 ); } - for ( i = 0; i < nProcs; i++ ) ThData[i].fWorking = 1; - - // wait till threads finish +} +int Cec_GiaWaitThreads( Par_ThData_t * ThData, int nProcs, Gia_Man_t * p, int RetValue, int * pRetEngine ) +{ + int i; for ( i = 0; i < nProcs; i++ ) + { + if ( RetValue == -1 && !ThData[i].fWorking && ThData[i].Result != -1 ) { + RetValue = ThData[i].Result; + *pRetEngine = i; + if ( !p->pCexSeq && ThData[i].p->pCexSeq ) + p->pCexSeq = Abc_CexDup( ThData[i].p->pCexSeq, -1 ); + } if ( ThData[i].fWorking ) i = -1; + } + return RetValue; +} + +int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fVerbose, int fVeryVerbose, int fSilent ) +{ + abctime clkScorr = 0, clkTotal = Abc_Clock(); + Par_ThData_t ThData[PAR_THR_MAX]; + pthread_t WorkerThread[PAR_THR_MAX]; + int i, RetValue = -1, RetEngine = -2; + Abc_CexFreeP( &p->pCexComb ); + Abc_CexFreeP( &p->pCexSeq ); + if ( !fSilent && fVerbose ) + printf( "Solving verification problem with the following parameters:\n" ); + if ( !fSilent && fVerbose ) + printf( "Processes = %d TimeOut = %d sec Verbose = %d.\n", nProcs, nTimeOut, fVerbose ); + fflush( stdout ); + + assert( nProcs == 3 || nProcs == 5 ); + Cec_GiaInitThreads( ThData, nProcs, p, nTimeOut, fVerbose, WorkerThread ); + + // meanwhile, perform scorr + Gia_Man_t * pScorr = Cec_GiaScorrNew( p ); + clkScorr = Abc_Clock() - clkTotal; + if ( Gia_ManAndNum(pScorr) == 0 ) + RetValue = 1, RetEngine = -1; + + RetValue = Cec_GiaWaitThreads( ThData, nProcs, p, RetValue, &RetEngine ); + if ( RetValue == -1 ) + { + abctime clkScorr2, clkStart = Abc_Clock(); + if ( !fSilent && fVerbose ) { + printf( "Reduced the miter from %d to %d nodes. ", Gia_ManAndNum(p), Gia_ManAndNum(pScorr) ); + Abc_PrintTime( 1, "Time", clkScorr ); + } + Cec_GiaInitThreads( ThData, nProcs, pScorr, nTimeOut2, fVerbose, NULL ); + + // meanwhile, perform scorr + Gia_Man_t * pScorr2 = Cec_GiaScorrOld( pScorr ); + clkScorr2 = Abc_Clock() - clkStart; + if ( Gia_ManAndNum(pScorr2) == 0 ) + RetValue = 1; + + RetValue = Cec_GiaWaitThreads( ThData, nProcs, p, RetValue, &RetEngine ); + if ( RetValue == -1 ) + { + if ( !fSilent && fVerbose ) { + printf( "Reduced the miter from %d to %d nodes. ", Gia_ManAndNum(pScorr), Gia_ManAndNum(pScorr2) ); + Abc_PrintTime( 1, "Time", clkScorr2 ); + } + Cec_GiaInitThreads( ThData, nProcs, pScorr2, nTimeOut3, fVerbose, NULL ); + + RetValue = Cec_GiaWaitThreads( ThData, nProcs, p, RetValue, &RetEngine ); + // do something else + } + Gia_ManStop( pScorr2 ); + } + Gia_ManStop( pScorr ); // stop threads for ( i = 0; i < nProcs; i++ ) { - assert( !ThData[i].fWorking ); - // cleanup - Gia_ManStopP( &ThData[i].p ); - if ( !p->pCexSeq && ThData[i].pCex ) - p->pCexSeq = Abc_CexDup( ThData[i].pCex, -1 ); - Abc_CexFreeP( &ThData[i].pCex ); - // stop ThData[i].p = NULL; ThData[i].fWorking = 1; } if ( !fSilent ) { if ( RetValue == 0 ) - printf( "Problem is SAT " ); + printf( "Problem is SAT (solved by %d) ", RetEngine ); else if ( RetValue == 1 ) - printf( "Problem is UNSAT " ); + printf( "Problem is UNSAT (solved by %d) ", RetEngine ); else if ( RetValue == -1 ) printf( "Problem is UNDECIDED " ); else assert( 0 ); - printf( ". " ); + printf( " " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); fflush( stdout ); } From 538ecb4515a932816b3fa242b547c5cff599bb86 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 23 Oct 2023 09:38:24 -0700 Subject: [PATCH 029/151] Updating printouts. --- src/proof/pdr/pdrCore.c | 4 ++-- src/sat/bmc/bmcBmcG.c | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/proof/pdr/pdrCore.c b/src/proof/pdr/pdrCore.c index d77fd4e17..b98a4bbe3 100644 --- a/src/proof/pdr/pdrCore.c +++ b/src/proof/pdr/pdrCore.c @@ -1149,7 +1149,7 @@ int Pdr_ManSolveInt( Pdr_Man_t * p ) { if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); - if ( p->timeToStop && Abc_Clock() > p->timeToStop ) + if ( p->timeToStop && Abc_Clock() > p->timeToStop && !p->pPars->fSilent ) Abc_Print( 1, "Reached timeout (%d seconds) in frame %d.\n", p->pPars->nTimeOut, iFrame ); else if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC ) Abc_Print( 1, "Reached gap timeout (%d seconds) in frame %d.\n", p->pPars->nTimeOutGap, iFrame ); @@ -1173,7 +1173,7 @@ int Pdr_ManSolveInt( Pdr_Man_t * p ) { if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); - if ( p->timeToStop && Abc_Clock() > p->timeToStop ) + if ( p->timeToStop && Abc_Clock() > p->timeToStop && !p->pPars->fSilent ) Abc_Print( 1, "Reached timeout (%d seconds) in frame %d.\n", p->pPars->nTimeOut, iFrame ); else if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC ) Abc_Print( 1, "Reached gap timeout (%d seconds) in frame %d.\n", p->pPars->nTimeOutGap, iFrame ); diff --git a/src/sat/bmc/bmcBmcG.c b/src/sat/bmc/bmcBmcG.c index af141d303..e6205b19c 100644 --- a/src/sat/bmc/bmcBmcG.c +++ b/src/sat/bmc/bmcBmcG.c @@ -421,9 +421,11 @@ int Bmcg_ManPerformOne( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ) break; } p->timeOth = Abc_Clock() - clkStart - p->timeUnf - p->timeCnf - p->timeSmp - p->timeSat; - if ( RetValue == -1 && !pPars->fNotVerbose ) - printf( "No output failed in %d frames. ", f + (k < pPars->nFramesAdd ? k+1 : 0) ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + if ( !pPars->fNotVerbose ) { + if ( RetValue == -1 && !pPars->fNotVerbose ) + printf( "No output failed in %d frames. ", f + (k < pPars->nFramesAdd ? k+1 : 0) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + } Bmcg_ManPrintTime( p ); Bmcg_ManStop( p ); return RetValue; From 76e8d21aafe3a5ae31d7516e33fbac5569384181 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 23 Oct 2023 10:48:43 -0700 Subject: [PATCH 030/151] Printout changes. --- src/base/cmd/cmd.c | 14 +++++++------- src/base/cmd/cmdStarter.c | 10 ++++++---- src/proof/cec/cecProve.c | 40 +++++++++++++++++++++------------------ src/proof/ssw/sswRarity.c | 6 ++++-- 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index d8ba90f58..708fc3f5b 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -1956,7 +1956,7 @@ int CmdCommandScrGenLinux( Abc_Frame_t * pAbc, int argc, char **argv ) char * pExt = strstr(pName, "."); if ( !pExt || !strcmp(pExt, ".") || !strcmp(pExt, "..") || !strcmp(pExt, ".s") || !strcmp(pExt, ".txt") ) continue; - sprintf( Line, "%s%sread %s%s%-*s ; %s", fBatch ? "./abc -c \"":"", fAndSpace ? "&" : "", pDirStr?pDirStr:"", pDirStr?"/":"", nFileNameMax, pName, pComStr ); + sprintf( Line, "%s%sread %s%s%-*s ; %s", fBatch ? "./abc -q \"":"", fAndSpace ? "&" : "", pDirStr?pDirStr:"", pDirStr?"/":"", nFileNameMax, pName, pComStr ); for ( c = (int)strlen(Line)-1; c >= 0; c-- ) if ( Line[c] == '\\' ) Line[c] = '/'; @@ -2549,18 +2549,18 @@ usage: ***********************************************************************/ int CmdCommandStarter( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores ); + extern void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores, int fVerbose ); FILE * pFile; char * pFileName; char * pCommand = NULL; int c, nCores = 3; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NCvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PCvh" ) ) != EOF ) { switch ( c ) { - case 'N': + case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); @@ -2607,13 +2607,13 @@ int CmdCommandStarter( Abc_Frame_t * pAbc, int argc, char ** argv ) } fclose( pFile ); // run commands - Cmd_RunStarter( pFileName, pAbc->sBinary, pCommand, nCores ); + Cmd_RunStarter( pFileName, pAbc->sBinary, pCommand, nCores, fVerbose ); return 0; usage: - Abc_Print( -2, "usage: starter [-N num] [-C cmd] [-vh] \n" ); + Abc_Print( -2, "usage: starter [-P num] [-C cmd] [-vh] \n" ); Abc_Print( -2, "\t runs command lines listed in concurrently on CPUs\n" ); - Abc_Print( -2, "\t-N num : the number of concurrent jobs including the controller [default = %d]\n", nCores ); + Abc_Print( -2, "\t-P num : the number of concurrent jobs including the controller [default = %d]\n", nCores ); Abc_Print( -2, "\t-C cmd : (optional) ABC command line to execute on benchmarks in \n" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); diff --git a/src/base/cmd/cmdStarter.c b/src/base/cmd/cmdStarter.c index ffb2b7522..bfbe5533d 100644 --- a/src/base/cmd/cmdStarter.c +++ b/src/base/cmd/cmdStarter.c @@ -44,7 +44,7 @@ ABC_NAMESPACE_IMPL_START #ifndef ABC_USE_PTHREADS -void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores ) {} +void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores, int fVerbose ) {} #else // pthreads are used @@ -104,7 +104,7 @@ void * Abc_RunThread( void * pCommand ) SeeAlso [] ***********************************************************************/ -void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores ) +void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores, int fVerbose ) { FILE * pFile, * pFileTemp; pthread_t * pThreadIds; @@ -204,8 +204,10 @@ void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCor } else BufferCopy = Abc_UtilStrsav( Buffer ); - fprintf( stdout, "Calling: %s\n", (char *)BufferCopy ); - fflush( stdout ); + if ( fVerbose ) { + fprintf( stdout, "Calling: %s\n", (char *)BufferCopy ); + fflush( stdout ); + } // wait till there is an empty thread while ( 1 ) diff --git a/src/proof/cec/cecProve.c b/src/proof/cec/cecProve.c index b3ddcd8a1..b6325ea2c 100644 --- a/src/proof/cec/cecProve.c +++ b/src/proof/cec/cecProve.c @@ -283,24 +283,27 @@ int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, in Cec_GiaInitThreads( ThData, nProcs, pScorr, nTimeOut2, fVerbose, NULL ); // meanwhile, perform scorr - Gia_Man_t * pScorr2 = Cec_GiaScorrOld( pScorr ); - clkScorr2 = Abc_Clock() - clkStart; - if ( Gia_ManAndNum(pScorr2) == 0 ) - RetValue = 1; - - RetValue = Cec_GiaWaitThreads( ThData, nProcs, p, RetValue, &RetEngine ); - if ( RetValue == -1 ) + if ( Gia_ManAndNum(pScorr) < 100000 ) { - if ( !fSilent && fVerbose ) { - printf( "Reduced the miter from %d to %d nodes. ", Gia_ManAndNum(pScorr), Gia_ManAndNum(pScorr2) ); - Abc_PrintTime( 1, "Time", clkScorr2 ); - } - Cec_GiaInitThreads( ThData, nProcs, pScorr2, nTimeOut3, fVerbose, NULL ); + Gia_Man_t * pScorr2 = Cec_GiaScorrOld( pScorr ); + clkScorr2 = Abc_Clock() - clkStart; + if ( Gia_ManAndNum(pScorr2) == 0 ) + RetValue = 1; + + RetValue = Cec_GiaWaitThreads( ThData, nProcs, p, RetValue, &RetEngine ); + if ( RetValue == -1 ) + { + if ( !fSilent && fVerbose ) { + printf( "Reduced the miter from %d to %d nodes. ", Gia_ManAndNum(pScorr), Gia_ManAndNum(pScorr2) ); + Abc_PrintTime( 1, "Time", clkScorr2 ); + } + Cec_GiaInitThreads( ThData, nProcs, pScorr2, nTimeOut3, fVerbose, NULL ); - RetValue = Cec_GiaWaitThreads( ThData, nProcs, p, RetValue, &RetEngine ); - // do something else + RetValue = Cec_GiaWaitThreads( ThData, nProcs, p, RetValue, &RetEngine ); + // do something else + } + Gia_ManStop( pScorr2 ); } - Gia_ManStop( pScorr2 ); } Gia_ManStop( pScorr ); @@ -312,12 +315,13 @@ int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, in } if ( !fSilent ) { + printf( "Problem \"%s\" is ", p->pSpec ); if ( RetValue == 0 ) - printf( "Problem is SAT (solved by %d) ", RetEngine ); + printf( "SAT (solved by %d).", RetEngine ); else if ( RetValue == 1 ) - printf( "Problem is UNSAT (solved by %d) ", RetEngine ); + printf( "UNSAT (solved by %d).", RetEngine ); else if ( RetValue == -1 ) - printf( "Problem is UNDECIDED " ); + printf( "UNDECIDED." ); else assert( 0 ); printf( " " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); diff --git a/src/proof/ssw/sswRarity.c b/src/proof/ssw/sswRarity.c index 1b7cab23d..679d30666 100644 --- a/src/proof/ssw/sswRarity.c +++ b/src/proof/ssw/sswRarity.c @@ -1040,8 +1040,10 @@ int Ssw_RarSimulate( Aig_Man_t * pAig, Ssw_RarPars_t * pPars ) Abc_Print( 1, "Simulated %d frames for %d rounds with %d restarts.\n", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart ); pAig->pSeqModel = Ssw_RarDeriveCex( p, r * p->pPars->nFrames + f, p->iFailPo, p->iFailPat, pPars->fVerbose ); // print final report - Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", pAig->pSeqModel->iPo, pAig->pName, pAig->pSeqModel->iFrame ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); + if ( !pPars->fSilent ) { + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", pAig->pSeqModel->iPo, pAig->pName, pAig->pSeqModel->iFrame ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); + } goto finish; } timeLastSolved = Abc_Clock(); From 1bf21626c0cca81592fdea2a073c1715b37e17bc Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 23 Oct 2023 11:04:35 -0700 Subject: [PATCH 031/151] Bug fix. --- src/sat/glucose/Glucose.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sat/glucose/Glucose.cpp b/src/sat/glucose/Glucose.cpp index cfb388de6..d878e0d17 100644 --- a/src/sat/glucose/Glucose.cpp +++ b/src/sat/glucose/Glucose.cpp @@ -1124,7 +1124,7 @@ lbool Solver::search(int nof_conflicts) return l_False; } // Perform clause database reduction ! - if(conflicts>=curRestart* nbclausesbeforereduce) + if(conflicts>=curRestart* nbclausesbeforereduce && learnts.size()>0) { assert(learnts.size()>0); From 5de12aa6b3a91850596326954eaca0c997cc499e Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 23 Oct 2023 11:30:44 -0700 Subject: [PATCH 032/151] Experiments with SAT solving. --- src/base/io/io.c | 13 +++++++++---- src/base/io/ioUtil.c | 33 ++++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/base/io/io.c b/src/base/io/io.c index f988a0078..55a02dee2 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -1224,17 +1224,21 @@ usage: ***********************************************************************/ int IoCommandReadCnf( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Vec_Ptr_t * Io_FileReadCnf( char * pFileName ); + extern Vec_Ptr_t * Io_FileReadCnf( char * pFileName, int fMulti ); FILE * pFile; Abc_Ntk_t * pNtk; Vec_Ptr_t * vSops; + int fMulti = 0; int c; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF ) { switch ( c ) { + case 'm': + fMulti ^= 1; + break; case 'h': goto usage; default: @@ -1253,7 +1257,7 @@ int IoCommandReadCnf( Abc_Frame_t * pAbc, int argc, char ** argv ) } else fclose( pFile ); - vSops = Io_FileReadCnf( argv[globalUtilOptind] ); + vSops = Io_FileReadCnf( argv[globalUtilOptind], fMulti ); if ( Vec_PtrSize(vSops) == 0 ) { Vec_PtrFreeFree( vSops ); @@ -1273,8 +1277,9 @@ int IoCommandReadCnf( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pAbc->Err, "usage: read_cnf [-h] \n" ); + fprintf( pAbc->Err, "usage: read_cnf [-mh] \n" ); fprintf( pAbc->Err, "\t creates network with one node\n" ); + fprintf( pAbc->Err, "\t-m : toggles generating multi-output network [default = %s]\n", fMulti? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : file name with the truth table\n" ); return 1; diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c index d11ee7408..eee2dda53 100644 --- a/src/base/io/ioUtil.c +++ b/src/base/io/ioUtil.c @@ -931,8 +931,9 @@ void Io_TransformSF2PLA( char * pNameIn, char * pNameOut ) SeeAlso [] ***********************************************************************/ -char * Io_ConvertNumsToSop( Vec_Wec_t * vNums, int nVars ) +Vec_Ptr_t * Io_ConvertNumsToSop( Vec_Wec_t * vNums, int nVars ) { + Vec_Ptr_t * vSops = Vec_PtrAlloc(1); Vec_Int_t * vLevel; int i, k, Num; int nSize = (nVars + 3)*Vec_WecSize(vNums); char * pStr = ABC_ALLOC( char, nSize+1 ); @@ -947,11 +948,30 @@ char * Io_ConvertNumsToSop( Vec_Wec_t * vNums, int nVars ) pCube[nVars+1] = '0'; pCube[nVars+2] = '\n'; } - return pStr; + Vec_PtrPush( vSops, pStr ); + return vSops; } -Vec_Ptr_t * Io_FileReadCnf( char * pFileName ) +Vec_Ptr_t * Io_ConvertNumsToSopMulti( Vec_Wec_t * vNums, int nVars ) { - Vec_Ptr_t * vSops = Vec_PtrAlloc( 1 ); + Vec_Ptr_t * vSops = Vec_PtrAlloc( Vec_WecSize(vNums) ); + Vec_Int_t * vLevel; int i, k, Num; + Vec_WecForEachLevel( vNums, vLevel, i ) + { + char * pCube = ABC_ALLOC( char, nVars + 4 ); + memset( pCube, '-', nVars ); + Vec_IntForEachEntry( vLevel, Num, k ) + pCube[Abc_Lit2Var(Num)] = '0' + Abc_LitIsCompl(Num); + pCube[nVars+0] = ' '; + pCube[nVars+1] = '0'; + pCube[nVars+2] = '\n'; + pCube[nVars+3] = '\0'; + Vec_PtrPush( vSops, pCube ); + } + return vSops; +} +Vec_Ptr_t * Io_FileReadCnf( char * pFileName, int fMulti ) +{ + Vec_Ptr_t * vSops = NULL; Vec_Wec_t * vNums = Vec_WecAlloc( 100 ); Vec_Int_t * vLevel; char * pThis, pLine[10000]; @@ -1002,7 +1022,10 @@ Vec_Ptr_t * Io_FileReadCnf( char * pFileName ) if ( nClas != Vec_WecSize(vNums) ) printf( "Warning: The number of clauses (%d) listed is different from the actual number (%d).\n", nClas, Vec_WecSize(vNums) ); //Vec_WecPrint( vNums, 0 ); - Vec_PtrPush( vSops, Io_ConvertNumsToSop(vNums, nVars) ); + if ( fMulti ) + vSops = Io_ConvertNumsToSopMulti(vNums, nVars); + else + vSops = Io_ConvertNumsToSop(vNums, nVars); Vec_WecFree( vNums ); return vSops; } From ba64d6118b16f4f405b65affb0b04797e5b665e1 Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Mon, 30 Oct 2023 15:09:01 -0700 Subject: [PATCH 033/151] out-side box matching --- Makefile | 3 +- src/aig/gia/giaDup.c | 96 ++++++++++++++++++++++++++++++++++++++++ src/proof/cec/cecSatG2.c | 57 ++++++++++++++++++++++++ 3 files changed, 155 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3976cf7b1..e6c0f4453 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,8 @@ MODULES := \ src/proof/pdr src/proof/abs src/proof/live src/proof/ssc src/proof/int \ src/proof/cec src/proof/acec src/proof/dch src/proof/fraig src/proof/fra src/proof/ssw \ src/aig/aig src/aig/saig src/aig/gia src/aig/ioa src/aig/ivy src/aig/hop \ - src/aig/miniaig + src/aig/miniaig \ + src/sat/bsat2 all: $(PROG) default: $(PROG) diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 665164eb2..4efbe90dc 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -30,6 +30,8 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +Vec_Int_t* vLitBmiter; + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -5699,13 +5701,107 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) Gia_ManConst0(p2)->Value = 0; Gia_ManForEachCi( p1, pObj, i ) pObj->Value = Gia_ManCi(p2, i)->Value = Gia_ManAppendCi( pNew ); + + // TODO: record the corresponding impl node of each lit + vLitBmiter = Vec_IntAlloc( Gia_ManObjNum(p2) ); + Vec_IntFill( vLitBmiter, Gia_ManObjNum(p2) + Gia_ManObjNum(p1), 0 ); + Gia_ManForEachAnd( p2, pObj, i ) + { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Vec_IntUpdateEntry( vLitBmiter, pObj->Value, 3 ); + } + + // TODO: find nodes in spec + + Vec_Int_t * vTypeSpec = Vec_IntAlloc( 16 ); + Vec_IntFill( vTypeSpec, Gia_ManObjNum(p1), 0 ); + int n = Gia_ManBufNum(p1) / 2; + + Gia_ManStaticFanoutStart( p1 ); + Vec_Ptr_t * vQ = Vec_PtrAlloc(16); + Gia_Obj_t * pObj2; + int c1 = 0; + int c2 = 0; + int count; + Gia_ManForEachBuf( p1, pObj, i ) + { + if ( count < n ) + { + Vec_IntSetEntry( vTypeSpec, Gia_ObjId( p1, pObj ), 1 ); + c1++; + count ++; + + Vec_PtrPush( vQ, Gia_ObjFanin0(pObj) ); + Vec_PtrPush( vQ, Gia_ObjFanin1(pObj) ); + while ( Vec_PtrSize(vQ) != 0 ) + { + pObj2 = Vec_PtrPop(vQ); + if ( Vec_IntEntry( vTypeSpec, Gia_ObjId(p1, pObj2) ) != 0 ) continue; + c1 ++; + Vec_IntSetEntry( vTypeSpec, Gia_ObjId(p1, pObj2), 1 ); + if ( Gia_ObjFaninNum(p1, pObj2) > 0 ) Vec_PtrPush( vQ, Gia_ObjFanin0(pObj2) ); + if ( Gia_ObjFaninNum(p1, pObj2) > 1 ) Vec_PtrPush( vQ, Gia_ObjFanin1(pObj2) ); + } + + } + else + { + Vec_IntSetEntry( vTypeSpec, Gia_ObjId( p1, pObj ), 2 ); + c2 ++; + + int j; + // pObj = Gia_ObjFanin0(pObj); + Gia_ObjForEachFanoutStatic(p1, pObj, pObj2, j) + { + Vec_PtrPush( vQ, pObj2 ); + } + while ( Vec_PtrSize(vQ) != 0 ) + { + pObj2 = Vec_PtrPop(vQ); + if ( Vec_IntEntry( vTypeSpec, Gia_ObjId(p1, pObj2) ) != 0 ) continue; + Vec_IntSetEntry( vTypeSpec, Gia_ObjId(p1, pObj2), 2 ); + c2 ++; + for( int j = 0; j < Gia_ObjFanoutNum(p1, pObj2); j++ ) + { + Vec_PtrPush( vQ, Gia_ObjFanout(p1, pObj2, j) ); + } + } + + } + } + + Gia_ManStaticFanoutStop( p1 ); + + printf( "category %d %d %d\n", c1, c2, Gia_ManObjNum(p1) ); + + + // TODO: record hashed equivalent nodes + Gia_ManForEachAnd( p1, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( Vec_IntEntry( vTypeSpec, Gia_ObjId( p1, pObj) ) > 0 ) + { + if ( Vec_IntGetEntry( vLitBmiter, pObj->Value ) == 3 ) // eq node in impl + { + Vec_IntUpdateEntry( vLitBmiter, pObj->Value, 3 + Vec_IntEntry( vTypeSpec, Gia_ObjId( p1, pObj) ) ); + } + else + { + Vec_IntUpdateEntry( vLitBmiter, pObj->Value, Vec_IntEntry( vTypeSpec, Gia_ObjId( p1, pObj) ) ); + } + } if ( Gia_ObjIsBuf(pObj) ) Vec_IntPush( vLits, pObj->Value ); } + + // int e; + // Vec_IntForEachEntry( vLitBmiter, e, i ) + // { + // printf( "%d ", e ); + // } + // printf("\n"); + Gia_ManForEachCo( p2, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); //Gia_ManForEachCo( p1, pObj, i ) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 281deb0e9..d641704f7 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -143,6 +143,9 @@ static inline int Cec4_ObjSatId( Gia_Man_t * p, Gia_Obj_t * pObj ) static inline int Cec4_ObjSetSatId( Gia_Man_t * p, Gia_Obj_t * pObj, int Num ) { assert(Cec4_ObjSatId(p, pObj) == -1); Gia_ObjSetCopy2Array(p, Gia_ObjId(p, pObj), Num); Vec_IntPush(&p->vSuppVars, Gia_ObjId(p, pObj)); if ( Gia_ObjIsCi(pObj) ) Vec_IntPushTwo(&p->vCopiesTwo, Gia_ObjId(p, pObj), Num); assert(Vec_IntSize(&p->vVarMap) == Num); Vec_IntPush(&p->vVarMap, Gia_ObjId(p, pObj)); return Num; } static inline void Cec4_ObjCleanSatId( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert(Cec4_ObjSatId(p, pObj) != -1); Gia_ObjSetCopy2Array(p, Gia_ObjId(p, pObj), -1); } + +extern Vec_Int_t* vLitBmiter; + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -1887,7 +1890,43 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p continue; } if ( Cec4_ManSweepNode(pMan, i, Gia_ObjId(p, pRepr)) && Gia_ObjProved(p, i) ) + { + if ( Vec_IntEntry( vLitBmiter, pRepr->Value ) == 3 ) + { + switch ( Vec_IntEntry( vLitBmiter, pObj -> Value ) ) + { + case 1: + case 4: + Vec_IntUpdateEntry( vLitBmiter, pRepr->Value, 4 ); + break; + case 2: + case 5: + Vec_IntUpdateEntry( vLitBmiter, pRepr->Value, 5 ); + break; + default: + break; + } + } + else + { + if ( Vec_IntEntry(vLitBmiter, pObj->Value ) == 3 ) + switch ( Vec_IntEntry( vLitBmiter, pRepr -> Value ) ) + { + case 1: + case 4: + Vec_IntUpdateEntry( vLitBmiter, pObj->Value, 4 ); + break; + case 2: + case 5: + Vec_IntUpdateEntry( vLitBmiter, pObj->Value, 5 ); + break; + default: + break; + + } + } pObj->Value = Abc_LitNotCond( pRepr->Value, pObj->fPhase ^ pRepr->fPhase ); + } } if ( p->iPatsPi > 0 ) { @@ -1933,10 +1972,28 @@ finalize: Gia_ManRemoveWrongChoices( p ); return p->pCexSeq ? 0 : 1; } +extern Vec_Int_t * vLitBmiter; Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ) { Gia_Man_t * pNew = NULL; Cec4_ManPerformSweeping( p, pPars, &pNew, 0 ); + + int e, i, c1=0, c2=0, c3=0, c4=0, c5=0; + Vec_IntForEachEntry( vLitBmiter, e, i ) + { + if ( i%2 ) continue; + switch (e) + { + case 1: c1++; break; + case 2: c2++; break; + case 3: c3++; break; + case 4: c4++; break; + case 5: c5++; break; + default: + break; + } + } + printf("category %d %d %d %d %d\n", c1, c2, c3+c4+c5, c4, c5); return pNew; } void Cec4_ManSimulateTest2( Gia_Man_t * p, int nConfs, int fVerbose ) From 50010139ef9b41040d902bad898458c59424771f Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Mon, 6 Nov 2023 18:37:40 +0800 Subject: [PATCH 034/151] why --- src/proof/cec/cecSatG2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index d641704f7..1a6309ebe 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -1978,6 +1978,7 @@ Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ) Gia_Man_t * pNew = NULL; Cec4_ManPerformSweeping( p, pPars, &pNew, 0 ); + // TODO int e, i, c1=0, c2=0, c3=0, c4=0, c5=0; Vec_IntForEachEntry( vLitBmiter, e, i ) { From 04dba9eed9eed7702ddcea4862cc4dc8818d1db8 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 6 Nov 2023 17:35:41 -0800 Subject: [PATCH 035/151] Adding callback for wire caps during sizing. --- src/map/scl/scl.c | 4 ++-- src/map/scl/sclDnsize.c | 7 ++++--- src/map/scl/sclSize.c | 14 +++++++++----- src/map/scl/sclSize.h | 7 ++++--- src/map/scl/sclUpsize.c | 7 ++++--- 5 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/map/scl/scl.c b/src/map/scl/scl.c index 8671d958e..29798f8fa 100644 --- a/src/map/scl/scl.c +++ b/src/map/scl/scl.c @@ -1604,7 +1604,7 @@ int Scl_CommandUpsize( Abc_Frame_t * pAbc, int argc, char **argv ) return 1; } - Abc_SclUpsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, pPars ); + Abc_SclUpsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, pPars, NULL ); return 0; usage: @@ -1781,7 +1781,7 @@ int Scl_CommandDnsize( Abc_Frame_t * pAbc, int argc, char **argv ) return 1; } - Abc_SclDnsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, pPars ); + Abc_SclDnsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, pPars, NULL ); return 0; usage: diff --git a/src/map/scl/sclDnsize.c b/src/map/scl/sclDnsize.c index 5be9e3a34..35f2c8247 100644 --- a/src/map/scl/sclDnsize.c +++ b/src/map/scl/sclDnsize.c @@ -239,7 +239,7 @@ void Abc_SclDnsizePrint( SC_Man * p, int Iter, int nAttempts, int nOverlaps, int SeeAlso [] ***********************************************************************/ -void Abc_SclDnsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ) +void Abc_SclDnsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, void * pFuncFanin ) { SC_Man * p; Abc_Obj_t * pObj; @@ -261,6 +261,7 @@ void Abc_SclDnsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPa // prepare the manager; collect init stats p = Abc_SclManStart( pLib, pNtk, pPars->fUseWireLoads, pPars->fUseDept, pPars->DelayUser, pPars->BuffTreeEst ); + p->pFuncFanin = (float (*)(void *, Abc_Obj_t *, Abc_Obj_t *, int, int))pFuncFanin; p->timeTotal = Abc_Clock(); assert( p->vGatesBest == NULL ); p->vGatesBest = Vec_IntDup( p->pNtk->vGates ); @@ -357,12 +358,12 @@ void Abc_SclDnsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPa SeeAlso [] ***********************************************************************/ -void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ) +void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, void * pFuncFanin ) { Abc_Ntk_t * pNtkNew = pNtk; if ( pNtk->nBarBufs2 > 0 ) pNtkNew = Abc_NtkDupDfsNoBarBufs( pNtk ); - Abc_SclDnsizePerformInt( pLib, pNtkNew, pPars ); + Abc_SclDnsizePerformInt( pLib, pNtkNew, pPars, pFuncFanin ); if ( pNtk->nBarBufs2 > 0 ) Abc_SclTransferGates( pNtk, pNtkNew ); if ( pNtk->nBarBufs2 > 0 ) diff --git a/src/map/scl/sclSize.c b/src/map/scl/sclSize.c index e09c56e67..b3bc2828d 100644 --- a/src/map/scl/sclSize.c +++ b/src/map/scl/sclSize.c @@ -270,21 +270,25 @@ void Abc_SclTimeNtkPrint( SC_Man * p, int fShowAll, int fPrintPath ) SeeAlso [] ***********************************************************************/ -static inline void Abc_SclTimeFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +static inline void Abc_SclTimeFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin, int k ) { SC_Pair * pArrIn = Abc_SclObjTime( p, pFanin ); SC_Pair * pSlewIn = Abc_SclObjSlew( p, pFanin ); SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); SC_Pair * pArrOut = Abc_SclObjTime( p, pObj ); // modified SC_Pair * pSlewOut = Abc_SclObjSlew( p, pObj ); // modified + if ( p->pFuncFanin ) pLoad->fall += p->pFuncFanin(p, pObj, pFanin, k, 0); + if ( p->pFuncFanin ) pLoad->rise += p->pFuncFanin(p, pObj, pFanin, k, 1); Scl_LibPinArrival( pTime, pArrIn, pSlewIn, pLoad, pArrOut, pSlewOut ); } -static inline void Abc_SclDeptFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +static inline void Abc_SclDeptFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin, int k ) { SC_Pair * pDepIn = Abc_SclObjDept( p, pFanin ); // modified SC_Pair * pSlewIn = Abc_SclObjSlew( p, pFanin ); SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); SC_Pair * pDepOut = Abc_SclObjDept( p, pObj ); + if ( p->pFuncFanin ) pLoad->fall += p->pFuncFanin(p, pObj, pFanin, k, 0); + if ( p->pFuncFanin ) pLoad->rise += p->pFuncFanin(p, pObj, pFanin, k, 1); Scl_LibPinDeparture( pTime, pDepIn, pSlewIn, pLoad, pDepOut ); } static inline void Abc_SclDeptObj( SC_Man * p, Abc_Obj_t * pObj ) @@ -298,7 +302,7 @@ static inline void Abc_SclDeptObj( SC_Man * p, Abc_Obj_t * pObj ) if ( Abc_ObjIsCo(pFanout) || Abc_ObjIsLatch(pFanout) ) continue; pTime = Scl_CellPinTime( Abc_SclObjCell(pFanout), Abc_NodeFindFanin(pFanout, pObj) ); - Abc_SclDeptFanin( p, pTime, pFanout, pObj ); + Abc_SclDeptFanin( p, pTime, pFanout, pObj, Abc_NodeFindFanin(pFanout, pObj) ); } } static inline float Abc_SclObjLoadValue( SC_Man * p, Abc_Obj_t * pObj ) @@ -368,9 +372,9 @@ void Abc_SclTimeNode( SC_Man * p, Abc_Obj_t * pObj, int fDept ) { pTime = Scl_CellPinTime( pCell, k ); if ( fDept ) - Abc_SclDeptFanin( p, pTime, pObj, pFanin ); + Abc_SclDeptFanin( p, pTime, pObj, pFanin, k ); else - Abc_SclTimeFanin( p, pTime, pObj, pFanin ); + Abc_SclTimeFanin( p, pTime, pObj, pFanin, k ); } if ( p->EstLoadMax && Value > 1 ) { diff --git a/src/map/scl/sclSize.h b/src/map/scl/sclSize.h index 3ec0d83e3..133ae6647 100644 --- a/src/map/scl/sclSize.h +++ b/src/map/scl/sclSize.h @@ -95,6 +95,7 @@ struct SC_Man_ abctime timeSize; // incremental sizing abctime timeTime; // timing update abctime timeOther; // everything else + float (*pFuncFanin)(void * p, Abc_Obj_t * pObj, Abc_Obj_t * pFanin, int iFanin, int fRise); // called to get info about the node's fanin }; //////////////////////////////////////////////////////////////////////// @@ -127,7 +128,7 @@ static inline double Abc_SclObjSlackMax( SC_Man * p, Abc_Obj_t * pObj, float static inline void Abc_SclObjDupFanin( SC_Man * p, Abc_Obj_t * pObj ) { assert( Abc_ObjIsCo(pObj) ); *Abc_SclObjTime(p, pObj) = *Abc_SclObjTime(p, Abc_ObjFanin0(pObj)); } static inline float Abc_SclObjInDrive( SC_Man * p, Abc_Obj_t * pObj ) { return Vec_FltEntry( p->vInDrive, pObj->iData ); } static inline void Abc_SclObjSetInDrive( SC_Man * p, Abc_Obj_t * pObj, float c){ Vec_FltWriteEntry( p->vInDrive, pObj->iData, c ); } - +static inline void Abc_SclManSetFaninCallBack( SC_Man * p, void * pCallBack ) { p->pFuncFanin = (float (*)(void *, Abc_Obj_t *, Abc_Obj_t *, int, int))pCallBack; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -551,7 +552,7 @@ extern int Abc_SclCheckNtk( Abc_Ntk_t * p, int fVerbose ); extern Abc_Ntk_t * Abc_SclPerformBuffering( Abc_Ntk_t * p, int DegreeR, int Degree, int fUseInvs, int fVerbose ); extern Abc_Ntk_t * Abc_SclBufPerform( Abc_Ntk_t * pNtk, int FanMin, int FanMax, int fBufPis, int fSkipDup, int fVerbose ); /*=== sclDnsize.c ===============================================================*/ -extern void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ); +extern void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, void * pFuncFanin ); /*=== sclLoad.c ===============================================================*/ extern Vec_Flt_t * Abc_SclFindWireCaps( SC_WireLoad * pWL, int nFanoutMax ); extern float Abc_SclFindWireLoad( Vec_Flt_t * vWireCaps, int nFans ); @@ -573,7 +574,7 @@ extern void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nT extern void Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose ); /*=== sclUpsize.c ===============================================================*/ extern int Abc_SclCountNearCriticalNodes( SC_Man * p ); -extern void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ); +extern void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, void * pFuncFanin ); /*=== sclUtil.c ===============================================================*/ extern void Abc_SclMioGates2SclGates( SC_Lib * pLib, Abc_Ntk_t * p ); extern void Abc_SclSclGates2MioGates( SC_Lib * pLib, Abc_Ntk_t * p ); diff --git a/src/map/scl/sclUpsize.c b/src/map/scl/sclUpsize.c index 5c6307352..822278a33 100644 --- a/src/map/scl/sclUpsize.c +++ b/src/map/scl/sclUpsize.c @@ -865,7 +865,7 @@ void Abc_SclUpsizeRemoveDangling( SC_Man * p, Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -void Abc_SclUpsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ) +void Abc_SclUpsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, void * pFuncFanin ) { SC_Man * p; Vec_Int_t * vPathPos = NULL; // critical POs @@ -891,6 +891,7 @@ void Abc_SclUpsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPa pPars->Window += (Abc_NtkNodeNum(pNtk) > 40000); // prepare the manager; collect init stats p = Abc_SclManStart( pLib, pNtk, pPars->fUseWireLoads, pPars->fUseDept, 0, pPars->BuffTreeEst ); + p->pFuncFanin = (float (*)(void *, Abc_Obj_t *, Abc_Obj_t *, int, int))pFuncFanin; p->timeTotal = Abc_Clock(); assert( p->vGatesBest == NULL ); p->vGatesBest = Vec_IntDup( p->pNtk->vGates ); @@ -1024,12 +1025,12 @@ void Abc_SclUpsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPa SeeAlso [] ***********************************************************************/ -void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ) +void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, void * pFuncFanin ) { Abc_Ntk_t * pNtkNew = pNtk; if ( pNtk->nBarBufs2 > 0 ) pNtkNew = Abc_NtkDupDfsNoBarBufs( pNtk ); - Abc_SclUpsizePerformInt( pLib, pNtkNew, pPars ); + Abc_SclUpsizePerformInt( pLib, pNtkNew, pPars, pFuncFanin ); if ( pNtk->nBarBufs2 > 0 ) Abc_SclTransferGates( pNtk, pNtkNew ); if ( pNtk->nBarBufs2 > 0 ) From 67a2b97cf0f5437198f01cea2d99b54d77a6491e Mon Sep 17 00:00:00 2001 From: WWFUG Date: Wed, 8 Nov 2023 19:00:03 +0800 Subject: [PATCH 036/151] added -I options in &bmiter --- .gitignore | 6 ++++ src/aig/gia/giaDup.c | 5 ++- src/base/abci/abc.c | 24 ++++++++++--- src/base/abci/abcMiter.c | 1 + src/proof/cec/cec.h | 1 + src/proof/cec/cecSatG2.c | 75 +++++++++++++++++++++------------------- 6 files changed, 71 insertions(+), 41 deletions(-) diff --git a/.gitignore b/.gitignore index cbb424152..f0c5201c6 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,12 @@ ReleaseExt/ _/ _TEST/ +_sandwich/ +_scripts/ +*.aig +*.vcproj +*.sh +*.v lib/abc* lib/m114* lib/bip* diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 4efbe90dc..24c1d3b0e 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -5669,7 +5669,7 @@ Gia_Man_t * Gia_ManDupAddFlop( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) +Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int biNum) { Vec_Int_t * vLits; Gia_Man_t * pNew, * pTemp; @@ -5717,6 +5717,9 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) Vec_Int_t * vTypeSpec = Vec_IntAlloc( 16 ); Vec_IntFill( vTypeSpec, Gia_ManObjNum(p1), 0 ); int n = Gia_ManBufNum(p1) / 2; + if(biNum > 0){ + n = biNum; + } Gia_ManStaticFanoutStart( p1 ); Vec_Ptr_t * vQ = Vec_PtrAlloc(16); diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 906b456ad..dab809c25 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -37921,7 +37921,7 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) int fCbs = 1, approxLim = 600, subBatchSz = 1, adaRecycle = 500, nMaxNodes = 0; Cec4_ManSetParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "JWRILDCNPMrmdckngxysopwvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "JWRILDCNPMrmdckngxysopwqvh" ) ) != EOF ) { switch ( c ) { @@ -38074,6 +38074,9 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'w': pPars->fVeryVerbose ^= 1; break; + case 'q': + pPars->fBMiterInfo ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -38138,6 +38141,7 @@ usage: Abc_Print( -2, "\t-o : toggle using the old SAT sweeper [default = %s]\n", fUseIvy? "yes": "no" ); Abc_Print( -2, "\t-p : toggle trying to prove when running the old SAT sweeper [default = %s]\n", fUseProve? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing even more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-q : toggle printing additional information for boundary miters [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -51689,16 +51693,25 @@ usage: ***********************************************************************/ int Abc_CommandAbc9BMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ); + extern Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int biNum); Gia_Man_t * pTemp, * pSecond; char * FileName = NULL; FILE * pFile = NULL; int c, fVerbose = 0; + int bi = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) { switch ( c ) { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + bi = atoi(argv[globalUtilOptind++]); + break; case 'v': fVerbose ^= 1; break; @@ -51737,14 +51750,15 @@ int Abc_CommandAbc9BMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9BMiter(): Cannot read the file name on the command line.\n" ); return 0; } - pTemp = Gia_ManBoundaryMiter( pAbc->pGia, pSecond, fVerbose ); + pTemp = Gia_ManBoundaryMiter( pAbc->pGia, pSecond, fVerbose, bi); Gia_ManStop( pSecond ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &bmiter [-vh] \n" ); + Abc_Print( -2, "usage: &bmiter -I [-vh] \n" ); Abc_Print( -2, "\t creates the boundary miter\n" ); + Abc_Print( -2, "\t-I : number of boundary inputs\n" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the implementation file\n"); diff --git a/src/base/abci/abcMiter.c b/src/base/abci/abcMiter.c index 6086fc616..6077a20c2 100644 --- a/src/base/abci/abcMiter.c +++ b/src/base/abci/abcMiter.c @@ -789,6 +789,7 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial, int fVer pNtkFrames->pName = Extra_UtilStrsav(Buffer); // map the constant nodes Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkFrames); + // create new latches (or their initial values) and remember them in the new latches if ( !fInitial ) { diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index d11bca3c3..ca4ac9aba 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -120,6 +120,7 @@ struct Cec_ParFra_t_ int fVeryVerbose; // verbose stats int fVerbose; // verbose stats int iOutFail; // the failed output + int fBMiterInfo; // printing BMiter information }; // combinational equivalence checking parameters diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 1a6309ebe..424369b8c 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -222,6 +222,7 @@ void Cec4_ManSetParams( Cec_ParFra_t * pPars ) pPars->nSatVarMax = 1000; // the max number of SAT variables before recycling SAT solver pPars->nCallsRecycle = 500; // calls to perform before recycling SAT solver pPars->nGenIters = 100; // pattern generation iterations + pPars->fBMiterInfo = 0; // printing BMiter information } /**Function************************************************************* @@ -1891,39 +1892,41 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p } if ( Cec4_ManSweepNode(pMan, i, Gia_ObjId(p, pRepr)) && Gia_ObjProved(p, i) ) { - if ( Vec_IntEntry( vLitBmiter, pRepr->Value ) == 3 ) - { - switch ( Vec_IntEntry( vLitBmiter, pObj -> Value ) ) + if (pPars->fBMiterInfo){ + if ( Vec_IntEntry( vLitBmiter, pRepr->Value ) == 3 ) { - case 1: - case 4: - Vec_IntUpdateEntry( vLitBmiter, pRepr->Value, 4 ); - break; - case 2: - case 5: - Vec_IntUpdateEntry( vLitBmiter, pRepr->Value, 5 ); - break; - default: - break; - } - } - else - { - if ( Vec_IntEntry(vLitBmiter, pObj->Value ) == 3 ) - switch ( Vec_IntEntry( vLitBmiter, pRepr -> Value ) ) + switch ( Vec_IntEntry( vLitBmiter, pObj -> Value ) ) { case 1: case 4: - Vec_IntUpdateEntry( vLitBmiter, pObj->Value, 4 ); + Vec_IntUpdateEntry( vLitBmiter, pRepr->Value, 4 ); break; case 2: case 5: - Vec_IntUpdateEntry( vLitBmiter, pObj->Value, 5 ); + Vec_IntUpdateEntry( vLitBmiter, pRepr->Value, 5 ); break; default: break; - } + } + else + { + if ( Vec_IntEntry(vLitBmiter, pObj->Value ) == 3 ) + switch ( Vec_IntEntry( vLitBmiter, pRepr -> Value ) ) + { + case 1: + case 4: + Vec_IntUpdateEntry( vLitBmiter, pObj->Value, 4 ); + break; + case 2: + case 5: + Vec_IntUpdateEntry( vLitBmiter, pObj->Value, 5 ); + break; + default: + break; + + } + } } pObj->Value = Abc_LitNotCond( pRepr->Value, pObj->fPhase ^ pRepr->fPhase ); } @@ -1979,22 +1982,24 @@ Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ) Cec4_ManPerformSweeping( p, pPars, &pNew, 0 ); // TODO - int e, i, c1=0, c2=0, c3=0, c4=0, c5=0; - Vec_IntForEachEntry( vLitBmiter, e, i ) - { - if ( i%2 ) continue; - switch (e) + if (pPars -> fBMiterInfo){ + int e, i, c1=0, c2=0, c3=0, c4=0, c5=0; + Vec_IntForEachEntry( vLitBmiter, e, i ) { - case 1: c1++; break; - case 2: c2++; break; - case 3: c3++; break; - case 4: c4++; break; - case 5: c5++; break; - default: - break; + if ( i%2 ) continue; + switch (e) + { + case 1: c1++; break; + case 2: c2++; break; + case 3: c3++; break; + case 4: c4++; break; + case 5: c5++; break; + default: + break; + } } + printf("category %d %d %d %d %d\n", c1, c2, c3+c4+c5, c4, c5); } - printf("category %d %d %d %d %d\n", c1, c2, c3+c4+c5, c4, c5); return pNew; } void Cec4_ManSimulateTest2( Gia_Man_t * p, int nConfs, int fVerbose ) From eb264c5d22533fdc7315c1565d8ed286e0237087 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 13 Nov 2023 17:19:54 -0800 Subject: [PATCH 037/151] Suggested fixes. --- src/aig/aig/aigOper.c | 2 +- src/base/abci/abcNtbdd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/aig/aig/aigOper.c b/src/aig/aig/aigOper.c index 4fe2cd8c4..d6f02a6e0 100644 --- a/src/aig/aig/aigOper.c +++ b/src/aig/aig/aigOper.c @@ -453,7 +453,7 @@ Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ) Aig_Obj_t * Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 ) { int i; - assert( vNodes1->nSize > 0 && vNodes1->nSize > 0 ); + assert( vNodes1->nSize > 0 && vNodes2->nSize > 0 ); assert( vNodes1->nSize == vNodes2->nSize ); for ( i = 0; i < vNodes1->nSize; i++ ) vNodes1->pArray[i] = Aig_Not( Aig_Exor( p, (Aig_Obj_t *)vNodes1->pArray[i], (Aig_Obj_t *)vNodes2->pArray[i] ) ); diff --git a/src/base/abci/abcNtbdd.c b/src/base/abci/abcNtbdd.c index 9de88980d..0676a7d0e 100644 --- a/src/base/abci/abcNtbdd.c +++ b/src/base/abci/abcNtbdd.c @@ -237,7 +237,7 @@ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * { Abc_Obj_t * pNodeNew, * pNodeNew0, * pNodeNew1, * pNodeNewC; assert( !Cudd_IsComplement(bFunc) ); - assert( b1 == a1 ); + //assert( b1 == a1 ); if ( bFunc == a1 ) return Abc_NtkCreateNodeConst1(pNtkNew); if ( bFunc == a0 ) From 6ca7eab466342ba8187c188328736d6a44d52199 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 14 Nov 2023 12:58:03 -0800 Subject: [PATCH 038/151] Prototype of integrating decomposition into "if". --- src/base/abci/abc.c | 10 +++++++--- src/base/abci/abcIf.c | 33 +++++++++++++++++++++++++++++++-- src/map/if/if.h | 1 + src/map/if/ifCut.c | 2 +- src/map/if/ifMap.c | 34 ++++++++++++++++++++++++++++++++-- 5 files changed, 72 insertions(+), 8 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 0558eefa4..c8e2b1ef8 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -19447,7 +19447,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) If_ManSetDefaultPars( pPars ); pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyuojiktncvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyzuojiktncvh" ) ) != EOF ) { switch ( c ) { @@ -19652,6 +19652,9 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'y': pPars->fUserRecLib ^= 1; break; + case 'z': + pPars->fUserLutDec ^= 1; + break; case 'u': pPars->fUserSesLib ^= 1; break; @@ -19807,7 +19810,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pLutLib = NULL; } // modify for delay optimization - if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut ) + if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fUserLutDec ) { pPars->fTruth = 1; pPars->fCutMin = 1; @@ -19953,7 +19956,7 @@ usage: sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyuojiktncvh]\n" ); + Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyzuojiktncvh]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -19982,6 +19985,7 @@ usage: Abc_Print( -2, "\t-g : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" ); Abc_Print( -2, "\t-x : toggles delay optimization by DSD balancing [default = %s]\n", pPars->fDsdBalance? "yes": "no" ); Abc_Print( -2, "\t-y : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" ); + Abc_Print( -2, "\t-z : toggles delay optimization with LUT decomposition [default = %s]\n", pPars->fUserLutDec? "yes": "no" ); Abc_Print( -2, "\t-u : toggles delay optimization with SAT-based library [default = %s]\n", pPars->fUserSesLib? "yes": "no" ); Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" ); Abc_Print( -2, "\t-j : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" ); diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index 491e2c140..e92a2282e 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -116,7 +116,7 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk); // update timing info to reflect logic level - if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib) && pNtk->pManTime ) + if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fUserLutDec) && pNtk->pManTime ) { int c; if ( pNtk->AndGateDelay == 0.0 ) @@ -426,6 +426,30 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC return Abc_NodeBuildFromMiniInt( pMan, p->vArray, If_CutLeaveNum(pCut) ); } +/**Function************************************************************* + + Synopsis [Implements decomposed LUT-structure of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_DecRecordToHop( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCutBest, If_Obj_t * pIfObj, Vec_Int_t * vCover ) +{ + // get the truth table + // perform LUT-decomposition and return the LUT-structure + // convert the LUT-structure into a set of logic nodes in Abc_Ntk_t + + // this is a placeholder, which takes the truth table and converts it into an AIG without LUT-decomposition + extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); + word * pTruth = If_CutTruthW(pIfMan, pCutBest); + assert( !pIfMan->pPars->fUseTtPerm ); + return Kit_TruthToHop( (Hop_Man_t *)pMan, (unsigned *)pTruth, If_CutLeaveNum(pCutBest), vCover ); +} + /**Function************************************************************* Synopsis [Derive one node after FPGA mapping.] @@ -464,7 +488,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t pNodeNew = Abc_NtkCreateNode( pNtkNew ); // if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays ) if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm && - !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize ) + !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->fUserLutDec && !pIfMan->pPars->nGateSize ) If_CutRotatePins( pIfMan, pCutBest ); if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) { @@ -524,6 +548,11 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj ); } + else if ( pIfMan->pPars->fUserLutDec ) + { + extern Hop_Obj_t * Abc_DecRecordToHop( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vMemory ); + pNodeNew->pData = Abc_DecRecordToHop( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj, vCover ); + } else { extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); diff --git a/src/map/if/if.h b/src/map/if/if.h index a72da9b95..93cb0f6ca 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -126,6 +126,7 @@ struct If_Par_t_ int fDsdBalance; // special delay optimization int fUserRecLib; // use recorded library int fUserSesLib; // use SAT-based synthesis + int fUserLutDec; // use LUT-based decomposition int fBidec; // use bi-decomposition int fUse34Spec; // use specialized matching int fUseBat; // use one specialized feature diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c index e3d47f1c6..f4f72d1c8 100644 --- a/src/map/if/ifCut.c +++ b/src/map/if/ifCut.c @@ -765,7 +765,7 @@ void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut ) if ( !pCut->fUseless && (p->pPars->fUseDsd || p->pPars->pFuncCell2 || p->pPars->fUseBat || - p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || + p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fEnableCheck07 || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->fUseDsdTune || p->pPars->fEnableCheck75 || p->pPars->fEnableCheck75u || p->pPars->fUseCheck1 || p->pPars->fUseCheck2) ) { diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index b3a4caf66..4a5210e92 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -148,6 +148,32 @@ int * If_CutArrTimeProfile( If_Man_t * p, If_Cut_t * pCut ) return p->pArrTimeProfile; } + +/**Function************************************************************* + + Synopsis [Returns the node's delay if its cut it LUT-decomposed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_CutDelayLutDec( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj ) +{ + // get the truth table + // get the cut leaves' arrival times + // run LUT-decomposition in the evaluation mode + // return expected arrival time at the output + + // this is a placeholder code, which is assume the cut has unit delay + int i, ArrTimes = 0; + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + ArrTimes = Abc_MaxInt( ArrTimes, (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay ); + return ArrTimes + 1; +} + /**Function************************************************************* Synopsis [Finds the best cut for the given node.] @@ -166,7 +192,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep If_Cut_t * pCut0R, * pCut1R; int fFunc0R, fFunc1R; int i, k, v, iCutDsd, fChange; - int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || + int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fUseDsdTune || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->pLutStruct || p->pPars->pFuncCell2 || p->pPars->fUseCheck1 || p->pPars->fUseCheck2; int fUseAndCut = (p->pPars->nAndDelay > 0) || (p->pPars->nAndArea > 0); assert( !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 0 ); @@ -208,6 +234,8 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->fUseless = 1; } } + else if ( p->pPars->fUserLutDec ) + pCut->Delay = If_CutDelayLutDec( p, pCut, pObj ); else if ( p->pPars->fDelayOptLut ) pCut->Delay = If_CutLutBalanceEval( p, pCut ); else if( p->pPars->nGateSize > 0 ) @@ -436,6 +464,8 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->fUseless = 1; } } + else if ( p->pPars->fUserLutDec ) + pCut->Delay = If_CutDelayLutDec( p, pCut, pObj ); else if ( p->pPars->fDelayOptLut ) pCut->Delay = If_CutLutBalanceEval( p, pCut ); else if( p->pPars->nGateSize > 0 ) @@ -507,7 +537,7 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP If_Set_t * pCutSet; If_Obj_t * pTemp; If_Cut_t * pCutTemp, * pCut; - int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec; + int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fUse34Spec; assert( pObj->pEquiv != NULL ); // prepare From 1632dc0d4ec9c917a44ce02965d83a4d6f948f37 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Wed, 15 Nov 2023 18:38:00 +0100 Subject: [PATCH 039/151] First version of ACD --- Makefile | 5 +- src/acd/ac_decomposition.hpp | 1500 ++++++++++++++++++++++++++++++++ src/acd/ac_wrapper.cpp | 69 ++ src/acd/ac_wrapper.h | 23 + src/acd/kitty_algorithm.hpp | 119 +++ src/acd/kitty_constants.hpp | 91 ++ src/acd/kitty_constructors.hpp | 92 ++ src/acd/kitty_dynamic_tt.hpp | 147 ++++ src/acd/kitty_operations.hpp | 333 +++++++ src/acd/kitty_operators.hpp | 86 ++ src/acd/kitty_static_tt.hpp | 131 +++ src/acd/module.make | 1 + src/base/abci/abc.c | 14 +- src/base/abci/abcIf.c | 162 +++- src/map/if/if.h | 11 +- src/map/if/ifCore.c | 18 + src/map/if/ifCut.c | 6 +- src/map/if/ifDelay.c | 126 +++ src/map/if/ifMap.c | 47 +- src/map/if/ifTime.c | 6 + 20 files changed, 2918 insertions(+), 69 deletions(-) create mode 100644 src/acd/ac_decomposition.hpp create mode 100644 src/acd/ac_wrapper.cpp create mode 100644 src/acd/ac_wrapper.h create mode 100644 src/acd/kitty_algorithm.hpp create mode 100644 src/acd/kitty_constants.hpp create mode 100644 src/acd/kitty_constructors.hpp create mode 100644 src/acd/kitty_dynamic_tt.hpp create mode 100644 src/acd/kitty_operations.hpp create mode 100644 src/acd/kitty_operators.hpp create mode 100644 src/acd/kitty_static_tt.hpp create mode 100644 src/acd/module.make diff --git a/Makefile b/Makefile index 3976cf7b1..d770c3faf 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ OS := $(shell uname -s) MODULES := \ $(wildcard src/ext*) \ + src/acd \ src/base/abc src/base/abci src/base/cmd src/base/io src/base/main src/base/exor \ src/base/ver src/base/wlc src/base/wln src/base/acb src/base/bac src/base/cba src/base/pla src/base/test \ src/map/mapper src/map/mio src/map/super src/map/if \ @@ -56,7 +57,7 @@ ARCHFLAGS := $(ARCHFLAGS) OPTFLAGS ?= -g -O -CFLAGS += -Wall -Wno-unused-function -Wno-write-strings -Wno-sign-compare $(ARCHFLAGS) +CFLAGS += -std=c17 -Wall -Wno-unused-function -Wno-write-strings -Wno-sign-compare $(ARCHFLAGS) ifneq ($(findstring arm,$(shell uname -m)),) CFLAGS += -DABC_MEMALIGN=4 endif @@ -151,7 +152,7 @@ ifdef ABC_USE_LIBSTDCXX endif $(info $(MSG_PREFIX)Using CFLAGS=$(CFLAGS)) -CXXFLAGS += $(CFLAGS) +CXXFLAGS += $(CFLAGS) -std=c++17 SRC := GARBAGE := core core.* *.stackdump ./tags $(PROG) arch_flags diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp new file mode 100644 index 000000000..4f94bcba4 --- /dev/null +++ b/src/acd/ac_decomposition.hpp @@ -0,0 +1,1500 @@ +/* mockturtle: C++ logic network library + * Copyright (C) 2018-2023 EPFL + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/*! + \file ac_decomposition.hpp + \brief Ashenhurst-Curtis decomposition + + \author Alessandro Tempia Calvino +*/ + +#ifndef _ACD_H_ +#define _ACD_H_ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "kitty_constants.hpp" +#include "kitty_constructors.hpp" +#include "kitty_static_tt.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_operations.hpp" +#include "kitty_operators.hpp" + +namespace mockturtle +{ + +/*! \brief Parameters for ac_decomposition */ +struct ac_decomposition_params +{ + /*! \brief LUT size for decomposition. */ + uint32_t lut_size{ 6 }; + + /*! \brief Maximum number of iterations for covering. */ + uint32_t max_iter{ 5000 }; +}; + +/*! \brief Statistics for ac_decomposition */ +struct ac_decomposition_stats +{ + uint32_t num_luts{ 0 }; + uint32_t num_edges{ 0 }; + uint32_t num_levels{ 0 }; +}; + +struct ac_decomposition_result +{ + kitty::dynamic_truth_table tt; + std::vector support; +}; + +template +class ac_decomposition_impl +{ +private: + struct encoding_matrix + { + uint64_t column{ 0 }; + uint32_t cost{ 0 }; + uint32_t index{ 0 }; + uint32_t sort_cost{ 0 }; + }; + +private: + static constexpr uint32_t max_num_vars = 8; + using STT = kitty::static_truth_table; + +public: + explicit ac_decomposition_impl( TT const& tt, uint32_t num_vars, ac_decomposition_params const& ps, ac_decomposition_stats* pst = nullptr ) + : num_vars( num_vars ), ps( ps ), pst( pst ), permutations( num_vars ) + { + tt_start = tt; + std::iota( permutations.begin(), permutations.end(), 0 ); + } + + /*! \brief Runs ACD using late arriving variables */ + int run( unsigned delay_profile ) + { + /* truth table is too large for the settings */ + if ( num_vars > max_num_vars ) + { + return -1; + } + + uint32_t late_arriving = __builtin_popcount( delay_profile ); + + /* return a high cost if too many late arriving variables */ + if ( late_arriving > ps.lut_size / 2 || late_arriving > 3 ) + { + return -1; + } + + /* convert to static TT */ + best_tt = kitty::extend_to( tt_start ); + best_multiplicity = UINT32_MAX; + uint32_t best_cost = UINT32_MAX; + + /* permute late arriving variables to be the least significant */ + reposition_late_arriving_variables( delay_profile, late_arriving ); + + /* run ACD trying different bound sets and free sets */ + uint32_t free_set_size = late_arriving; + uint32_t offset = std::max( static_cast( late_arriving ), 1u ); + for ( uint32_t i = offset; i <= ps.lut_size / 2 && i <= 3; ++i ) + { + auto evaluate_fn = [&]( STT const& tt ) { return column_multiplicity( tt, i ); }; + auto [tt_p, perm, cost] = enumerate_iset_combinations_offset( i, offset, evaluate_fn, false ); + + /* add cost if not support reducing */ + uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; + /* check for feasible solution that improves the cost */ + if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost ) + { + best_tt = tt_p; + permutations = perm; + best_multiplicity = cost; + best_cost = cost + additional_cost; + free_set_size = i; + } + } + + if ( best_multiplicity == UINT32_MAX ) + return -1; + + /* compute isets */ + // std::vector isets = compute_isets( free_set_size ); + + // generate_support_minimization_encodings(); + // solve_min_support_exact( isets, free_set_size ); + + /* unfeasible decomposition */ + // if ( best_bound_sets.empty() ) + // { + // return -1; + // } + + pst->num_luts = ps.lut_size - free_set_size; + best_free_set = free_set_size; + + /* TODO generate decomposition only when returning the result */ + // dec_result = generate_decomposition( free_set_size ); + + /* TODO: change return value */ + return 0; + } + + int compute_decomposition() + { + if ( best_multiplicity == UINT32_MAX ) + return -1; + + /* compute isets */ + std::vector isets = compute_isets( best_free_set ); + + generate_support_minimization_encodings(); + solve_min_support_exact( isets, best_free_set ); + + /* unfeasible decomposition */ + if ( best_bound_sets.empty() ) + { + return -1; + } + + return 0; + } + + unsigned get_profile() + { + unsigned profile = 0; + + if ( best_free_set > num_vars ) + return -1; + + for ( uint32_t i = 0; i < best_free_set; ++i ) + { + profile |= 1 << permutations[i]; + } + + return profile; + } + + std::vector get_result() + { + return dec_result; + } + + void get_decomposition( unsigned char *decompArray ) + { + if ( best_free_set > num_vars ) + return; + + dec_result = generate_decomposition( best_free_set ); + return get_decomposition_abc( decompArray ); + } + +private: + uint32_t column_multiplicity( STT tt, uint32_t free_set_size ) + { + uint64_t multiplicity_set[4] = { 0u, 0u, 0u, 0u }; + uint32_t multiplicity = 0; + uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + + /* supports up to 64 values of free set (256 for |FS| == 3)*/ + assert( free_set_size <= 3 ); + + /* extract iset functions */ + if ( free_set_size == 1 ) + { + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < 32; ++j ) + { + multiplicity_set[0] |= UINT64_C( 1 ) << ( *it & 0x3 ); + *it >>= 2; + } + ++it; + } + } + else if ( free_set_size == 2 ) + { + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < 16; ++j ) + { + multiplicity_set[0] |= UINT64_C( 1 ) << ( *it & 0xF ); + *it >>= 4; + } + ++it; + } + } + else /* free set size 3 */ + { + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < 8; ++j ) + { + multiplicity_set[( *it >> 6 ) & 0x3] |= UINT64_C( 1 ) << ( *it & 0x3F ); + *it >>= 8; + } + ++it; + } + } + + multiplicity = __builtin_popcountl( multiplicity_set[0] ); + + if ( free_set_size == 3 ) + { + multiplicity += __builtin_popcountl( multiplicity_set[1] ); + multiplicity += __builtin_popcountl( multiplicity_set[2] ); + multiplicity += __builtin_popcountl( multiplicity_set[3] ); + } + + return multiplicity; + } + + template + std::tuple, uint32_t> enumerate_iset_combinations( uint32_t free_set_size, Fn&& fn, bool verbose = false ) + { + /* works up to 16 input truth tables */ + assert( num_vars <= 16 ); + + /* special case */ + STT tt = best_tt; + if ( num_vars <= free_set_size || free_set_size == 0 ) + { + return { tt, permutations, UINT32_MAX }; + } + + /* select k */ + // free_set_size = std::min( free_set_size, num_vars - free_set_size ); + + /* init permutation array */ + std::array perm, best_perm; + std::copy( permutations.begin(), permutations.begin() + num_vars, perm.begin() ); + best_perm = perm; + + /* TT with best cost */ + STT best = tt; + uint32_t best_cost = UINT32_MAX; + + /* enumerate combinations */ + if ( free_set_size == 1 ) + { + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + best = tt; + best_cost = cost; + best_perm = perm; + } + + if ( verbose ) + { + kitty::print_hex( tt ); + std::cout << " " << cost << " "; + print_perm( perm.begin(), free_set_size ); + } + + for ( uint32_t i = 1; i < num_vars; ++i ) + { + std::swap( perm[0], perm[i] ); + kitty::swap_inplace( tt, 0, i ); + + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + best = tt; + best_cost = cost; + best_perm = perm; + } + + if ( verbose ) + { + kitty::print_hex( tt ); + std::cout << " " << cost << " "; + print_perm( perm.begin(), free_set_size ); + } + } + } + else if ( free_set_size == 2 ) + { + for ( uint32_t i = 0; i < num_vars - 1; ++i ) + { + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + best = tt; + best_cost = cost; + best_perm = perm; + } + + if ( verbose ) + { + kitty::print_hex( tt ); + std::cout << " " << cost << " "; + print_perm( perm.begin(), free_set_size ); + } + + for ( uint32_t j = 2; j < num_vars - i; ++j ) + { + std::swap( perm[1], perm[j] ); + kitty::swap_inplace( tt, 1, j ); + + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + best = tt; + best_cost = cost; + best_perm = perm; + } + + if ( verbose ) + { + kitty::print_hex( tt ); + std::cout << " " << cost << " "; + print_perm( perm.begin(), free_set_size ); + } + } + + std::swap( perm[0], perm[num_vars - i - 1] ); + kitty::swap_inplace( tt, 0, num_vars - i - 1 ); + } + } + else if ( free_set_size == 3 ) + { + for ( uint32_t i = 0; i < num_vars - 2; ++i ) + { + for ( uint32_t j = i; j < num_vars - 2; ++j ) + { + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + best = tt; + best_cost = cost; + best_perm = perm; + } + + if ( verbose ) + { + kitty::print_hex( tt ); + std::cout << " " << cost << " "; + print_perm( perm.begin(), free_set_size ); + } + + for ( uint32_t k = 3; k < num_vars - j; ++k ) + { + std::swap( perm[2], perm[k] ); + kitty::swap_inplace( tt, 2, k ); + + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + best = tt; + best_cost = cost; + best_perm = perm; + } + + if ( verbose ) + { + kitty::print_hex( tt ); + std::cout << " " << cost << " "; + print_perm( perm.begin(), free_set_size ); + } + } + + std::swap( perm[1], perm[num_vars - j - 1] ); + kitty::swap_inplace( tt, 1, num_vars - j - 1 ); + } + + std::swap( perm[0], perm[num_vars - i - 1] ); + kitty::swap_inplace( tt, 0, num_vars - i - 1 ); + } + } + + std::vector res_perm( num_vars ); + std::copy( best_perm.begin(), best_perm.begin() + num_vars, res_perm.begin() ); + + return std::make_tuple( best, res_perm, best_cost ); + } + + template + std::tuple, uint32_t> enumerate_iset_combinations_offset( uint32_t free_set_size, uint32_t offset, Fn&& fn, bool verbose = false ) + { + STT tt = best_tt; + + /* TT with best cost */ + STT best_tt = tt; + uint32_t best_cost = UINT32_MAX; + + /* works up to 16 input truth tables */ + assert( num_vars <= 16 ); + + /* select k */ + free_set_size = std::min( free_set_size, num_vars - free_set_size ); + + /* special case */ + if ( num_vars <= free_set_size || free_set_size <= offset ) + { + if ( offset == free_set_size ) + { + best_cost = fn( tt ); + if ( verbose ) + { + kitty::print_hex( tt ); + std::cout << " " << best_cost << " "; + print_perm( permutations.begin(), free_set_size ); + } + + return { tt, permutations, best_cost }; + } + else + { + return { tt, permutations, UINT32_MAX }; + } + } + + /* decrease combinations */ + free_set_size -= offset; + + /* init permutation array */ + std::array perm, best_perm; + std::copy( permutations.begin(), permutations.begin() + num_vars, perm.begin() ); + best_perm = perm; + + /* enumerate combinations */ + if ( free_set_size == 1 ) + { + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + best_tt = tt; + best_cost = cost; + best_perm = perm; + } + + if ( verbose ) + { + kitty::print_hex( tt ); + std::cout << " " << cost << " "; + print_perm( perm.begin(), free_set_size + offset ); + } + + for ( uint32_t i = offset + 1; i < num_vars; ++i ) + { + std::swap( perm[offset], perm[i] ); + kitty::swap_inplace( tt, offset, i ); + + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + best_tt = tt; + best_cost = cost; + best_perm = perm; + } + + if ( verbose ) + { + kitty::print_hex( tt ); + std::cout << " " << cost << " "; + print_perm( perm.begin(), free_set_size + offset ); + } + } + } + else if ( free_set_size == 2 ) + { + for ( uint32_t i = 0; i < num_vars - 1 - offset; ++i ) + { + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + best_tt = tt; + best_cost = cost; + best_perm = perm; + } + + if ( verbose ) + { + kitty::print_hex( tt ); + std::cout << " " << cost << " "; + print_perm( perm.begin(), free_set_size + offset ); + } + + for ( uint32_t j = offset + 2; j < num_vars - i; ++j ) + { + std::swap( perm[offset + 1], perm[j] ); + kitty::swap_inplace( tt, offset + 1, j ); + + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + best_tt = tt; + best_cost = cost; + best_perm = perm; + } + + if ( verbose ) + { + kitty::print_hex( tt ); + std::cout << " " << cost << " "; + print_perm( perm.begin(), free_set_size + offset ); + } + } + + std::swap( perm[offset], perm[num_vars - i - 1] ); + kitty::swap_inplace( tt, offset, num_vars - i - 1 ); + } + } + else if ( free_set_size == 3 ) + { + for ( uint32_t i = 0; i < num_vars - 2 - offset; ++i ) + { + for ( uint32_t j = i; j < num_vars - 2 - offset; ++j ) + { + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + best_tt = tt; + best_cost = cost; + best_perm = perm; + } + + if ( verbose ) + { + kitty::print_hex( tt ); + std::cout << " " << cost << " "; + print_perm( perm.begin(), free_set_size + offset ); + } + + for ( uint32_t k = offset + 3; k < num_vars - j; ++k ) + { + std::swap( perm[offset + 2], perm[k] ); + kitty::swap_inplace( tt, offset + 2, k ); + + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + best_tt = tt; + best_cost = cost; + best_perm = perm; + } + + if ( verbose ) + { + kitty::print_hex( tt ); + std::cout << " " << cost << " "; + print_perm( perm.begin(), free_set_size + offset ); + } + } + + std::swap( perm[offset + 1], perm[num_vars - j - 1] ); + kitty::swap_inplace( tt, offset + 1, num_vars - j - 1 ); + } + + std::swap( perm[offset], perm[num_vars - i - 1] ); + kitty::swap_inplace( tt, offset, num_vars - i - 1 ); + } + } + + std::vector res_perm( num_vars ); + std::copy( best_perm.begin(), best_perm.begin() + num_vars, res_perm.begin() ); + + return std::make_tuple( best_tt, res_perm, best_cost ); + } + + std::vector compute_isets( uint32_t free_set_size, bool verbose = false ) + { + /* construct isets involved in multiplicity */ + uint32_t isets_support = num_vars - free_set_size; + std::vector isets( best_multiplicity ); + + /* construct isets */ + std::unordered_map column_to_iset; + STT tt = best_tt; + uint32_t offset = 0; + uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + + if ( free_set_size == 1 ) + { + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < 32; ++j ) + { + uint64_t val = *it & 0x3; + + if ( auto el = column_to_iset.find( val ); el != column_to_iset.end() ) + { + isets[el->second]._bits[i / 2] |= UINT64_C( 1 ) << ( j + offset ); + } + else + { + isets[column_to_iset.size()]._bits[i / 2] |= UINT64_C( 1 ) << ( j + offset ); + column_to_iset[val] = column_to_iset.size(); + } + + *it >>= 2; + } + + offset ^= 32; + ++it; + } + } + else if ( free_set_size == 2 ) + { + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < 16; ++j ) + { + uint64_t val = *it & 0xF; + + if ( auto el = column_to_iset.find( val ); el != column_to_iset.end() ) + { + isets[el->second]._bits[i / 4] |= UINT64_C( 1 ) << ( j + offset ); + } + else + { + isets[column_to_iset.size()]._bits[i / 4] |= UINT64_C( 1 ) << ( j + offset ); + column_to_iset[val] = column_to_iset.size(); + } + + *it >>= 4; + } + + offset = ( offset + 16 ) % 64; + ++it; + } + } + else /* free set size 3 */ + { + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < 8; ++j ) + { + uint64_t val = *it & 0xFF; + + if ( auto el = column_to_iset.find( val ); el != column_to_iset.end() ) + { + isets[el->second]._bits[i / 8] |= UINT64_C( 1 ) << ( j + offset ); + } + else + { + isets[column_to_iset.size()]._bits[i / 8] |= UINT64_C( 1 ) << ( j + offset ); + column_to_iset[val] = column_to_iset.size(); + } + + *it >>= 8; + } + + offset = ( offset + 8 ) % 64; + ++it; + } + } + + /* extend isets to cover the whole truth table */ + for ( STT& iset : isets ) + { + local_extend_to( iset, isets_support ); + } + + /* save free_set functions */ + std::vector free_set_tts( best_multiplicity ); + + /* TODO: possible conflict */ + for ( auto const& pair : column_to_iset ) + { + free_set_tts[pair.second]._bits[0] = pair.first; + local_extend_to( free_set_tts[pair.second], free_set_size ); + } + + /* print isets and free set*/ + if ( verbose ) + { + std::cout << "iSets\n"; + uint32_t i = 0; + for ( auto iset : isets ) + { + kitty::print_hex( iset ); + std::cout << " of func "; + kitty::print_hex( free_set_tts[i++] ); + std::cout << "\n"; + } + } + + best_free_set_tts = std::move( free_set_tts ); + + return isets; + } + + std::vector generate_decomposition( uint32_t free_set_size ) + { + std::vector res; + + for ( uint32_t i = 0; i < best_bound_sets.size(); ++i ) + { + ac_decomposition_result dec; + auto tt = best_bound_sets[i]; + auto care = best_care_sets[i]; + + /* compute and minimize support for bound set variables */ + uint32_t k = 0; + for ( uint32_t j = 0; j < num_vars - free_set_size; ++j ) + { + if ( !kitty::has_var( tt, j ) ) + continue; + + if ( !kitty::has_var( tt, care, j ) ) + { + /* fix truth table */ + adjust_truth_table_on_dc( tt, care, j ); + continue; + } + + if ( k < j ) + { + kitty::swap_inplace( tt, k, j ); + kitty::swap_inplace( care, k, j ); + } + dec.support.push_back( permutations[free_set_size + j] ); + ++k; + } + + dec.tt = kitty::shrink_to( tt, dec.support.size() ); + res.push_back( dec ); + } + + /* compute the decomposition for the top-level LUT */ + compute_top_lut_decomposition( res, free_set_size ); + + return res; + } + + void compute_top_lut_decomposition( std::vector& res, uint32_t free_set_size ) + { + uint32_t top_vars = best_bound_sets.size() + free_set_size; + assert( top_vars <= ps.lut_size ); + + /* extend bound set functions with free_set_size LSB vars */ + kitty::dynamic_truth_table tt( top_vars ); + + /* compute support */ + res.emplace_back(); + for ( uint32_t i = 0; i < free_set_size; ++i ) + { + res.back().support.push_back( permutations[i] ); + } + + /* create functions for bound set */ + std::vector bound_set_vars; + auto res_it = res.begin(); + uint32_t offset = 0; + for ( uint32_t i = 0; i < best_bound_sets.size(); ++i ) + { + bound_set_vars.emplace_back( top_vars ); + kitty::create_nth_var( bound_set_vars[i], free_set_size + i ); + + /* add bound-set variables to the support, remove buffers */ + if ( res_it->support.size() == 1 ) + { + res.back().support.push_back( res_it->support.front() ); + /* it is a NOT */ + if ( ( res_it->tt._bits[0] & 1 ) == 1 ) + { + bound_set_vars[i] = ~bound_set_vars[i]; + } + res.erase( res_it ); + ++offset; + } + else + { + res.back().support.push_back( num_vars + i - offset ); + ++res_it; + } + } + + /* create composition function */ + for ( uint32_t i = 0; i < best_free_set_tts.size(); ++i ) + { + kitty::dynamic_truth_table free_set_tt = kitty::shrink_to( best_free_set_tts[i], top_vars ); + + /* find MUX assignments */ + for ( uint32_t j = 0; j < bound_set_vars.size(); ++j ) + { + /* AND with ONSET or OFFSET */ + if ( ( ( best_iset_onset[j] >> i ) & 1 ) ) + { + free_set_tt &= bound_set_vars[j]; + } + else if ( ( ( best_iset_offset[j] >> i ) & 1 ) ) + { + free_set_tt &= ~bound_set_vars[j]; + } + } + + tt |= free_set_tt; + } + + /* add top-level LUT to result */ + res.back().tt = tt; + } + + inline void reposition_late_arriving_variables( unsigned delay_profile, uint32_t late_arriving ) + { + uint32_t k = 0; + for ( uint32_t i = 0; i < late_arriving; ++i ) + { + while ( ( ( delay_profile >> k ) & 1 ) == 0 ) + ++k; + + if ( permutations[i] == k ) + { + ++k; + continue; + } + + std::swap( permutations[i], permutations[k] ); + kitty::swap_inplace( best_tt, i, k ); + ++k; + } + } + + template + void print_perm( Iterator begin, uint32_t free_set ) + { + std::cout << "["; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + if ( i == free_set ) + { + std::cout << ", "; + } + std::cout << *begin << " "; + ++begin; + } + std::cout << "]\n"; + } + + void generate_support_minimization_encodings() + { + uint32_t count = 0; + uint32_t num_combs_exact[4] = { 2, 6, 70, 12870 }; + + /* enable don't cares only if not a power of 2 */ + uint32_t num_combs = 3; + if ( __builtin_popcount( best_multiplicity ) == 1 ) + { + for ( uint32_t i = 0; i < 4; ++i ) + { + if ( ( best_multiplicity >> i ) == 2u ) + { + num_combs = num_combs_exact[i]; + } + } + support_minimization_encodings = std::vector>( num_combs ); + generate_support_minimization_encodings_rec( 0, 0, 0, count ); + } + else + { + for ( uint32_t i = 1; i < best_multiplicity; ++i ) + { + num_combs = ( num_combs << 1 ) + num_combs; + } + support_minimization_encodings = std::vector>( num_combs ); + generate_support_minimization_encodings_rec( 0, 0, 0, count ); + } + + assert( count == num_combs ); + + /* print combinations */ + // std::cout << "{ "; + // for ( auto const& entry : support_minimization_encodings ) + // { + // std::cout << "{ " << entry[0] << ", " << entry[1] << " }, "; + // } + // std::cout << "}\n"; + } + + template + void generate_support_minimization_encodings_rec( uint64_t onset, uint64_t offset, uint32_t var, uint32_t& count ) + { + if ( var == best_multiplicity ) + { + if constexpr ( !enable_dcset ) + { + /* sets must be equally populated */ + if ( __builtin_popcountl( onset ) != __builtin_popcountl( offset ) ) + { + return; + } + } + + support_minimization_encodings[count][0] = onset; + support_minimization_encodings[count][1] = offset; + ++count; + return; + } + + /* move var in DCSET */ + if constexpr ( enable_dcset ) + { + generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + } + + /* move var in ONSET */ + onset |= 1 << var; + generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + onset &= ~( 1 << var ); + + /* move var in OFFSET */ + offset |= 1 << var; + generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + offset &= ~( 1 << var ); + } + + void solve_min_support_exact( std::vector const& isets, uint32_t free_set_size ) + { + std::vector matrix; + matrix.reserve( support_minimization_encodings.size() ); + best_bound_sets.clear(); + + /* create covering matrix */ + if ( !create_covering_matrix( isets, matrix, free_set_size, best_multiplicity > 4 ) ) + { + return; + } + + /* solve the covering problem */ + std::array solution = covering_solve_exact( matrix, 100, ps.max_iter ); + + /* check for failed decomposition */ + if ( solution[0] == UINT32_MAX ) + { + return; + } + + /* compute best bound sets */ + uint32_t num_luts = 1 + solution[4]; + uint32_t num_levels = 2; + uint32_t num_edges = free_set_size + solution[4]; + uint32_t isets_support = num_vars - free_set_size; + best_care_sets.clear(); + best_iset_onset.clear(); + best_iset_offset.clear(); + for ( uint32_t i = 0; i < solution[4]; ++i ) + { + STT tt; + STT care; + + const uint32_t onset = support_minimization_encodings[matrix[solution[i]].index][0]; + const uint32_t offset = support_minimization_encodings[matrix[solution[i]].index][1]; + for ( uint32_t j = 0; j < best_multiplicity; ++j ) + { + if ( ( ( onset >> j ) & 1 ) ) + { + tt |= isets[j]; + } + if ( ( ( offset >> j ) & 1 ) ) + { + care |= isets[j]; + } + } + + care |= tt; + num_edges += matrix[solution[i]].cost & ( ( 1 << isets_support ) - 1 ); + + best_bound_sets.push_back( tt ); + best_care_sets.push_back( care ); + best_iset_onset.push_back( onset ); + best_iset_offset.push_back( offset ); + } + + if ( pst != nullptr ) + { + pst->num_luts = num_luts; + pst->num_levels = num_levels; + pst->num_edges = num_edges; + } + } + + bool create_covering_matrix( std::vector const& isets, std::vector& matrix, uint32_t free_set_size, bool sort ) + { + assert( best_multiplicity < 12 ); + uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; + uint64_t sol_existance = 0; + uint32_t iset_support = num_vars - free_set_size; + + /* insert dichotomies */ + for ( uint32_t i = 0; i < support_minimization_encodings.size(); ++i ) + { + uint32_t const onset = support_minimization_encodings[i][0]; + uint32_t const offset = support_minimization_encodings[i][1]; + + uint32_t ones_onset = __builtin_popcount( onset ); + uint32_t ones_offset = __builtin_popcount( offset ); + + /* filter columns that do not distinguish pairs */ + if ( ones_onset == 0 || ones_offset == 0 || ones_onset == best_multiplicity || ones_offset == best_multiplicity ) + { + continue; + } + + /* compute function and distinguishable seed dichotomies */ + uint64_t column = 0; + STT tt; + STT care; + uint32_t pair_pointer = 0; + for ( uint32_t j = 0; j < best_multiplicity; ++j ) + { + auto onset_shift = ( onset >> j ); + auto offset_shift = ( offset >> j ); + if ( ( onset_shift & 1 ) ) + { + tt |= isets[j]; + } + + if ( ( offset_shift & 1 ) ) + { + care |= isets[j]; + } + + /* compute included seed dichotomies */ + for ( uint32_t k = j + 1; k < best_multiplicity; ++k ) + { + /* if is are in diffent sets */ + if ( ( ( ( onset_shift & ( offset >> k ) ) | ( ( onset >> k ) & offset_shift ) ) & 1 ) ) + { + column |= UINT64_C( 1 ) << ( pair_pointer ); + } + + ++pair_pointer; + } + } + + care |= tt; + + /* compute cost */ + uint32_t cost = 0; + for ( uint32_t j = 0; j < iset_support; ++j ) + { + cost += has_var_support( tt, care, iset_support, j ) ? 1 : 0; + } + + /* discard solutions with support over LUT size */ + if ( cost > ps.lut_size ) + continue; + + if ( cost > 1 ) + { + cost |= 1 << iset_support; + } + + uint32_t sort_cost = cost + ( ( combinations - __builtin_popcountl( column ) ) << num_vars ); + + /* insert */ + matrix.emplace_back( encoding_matrix{ column, cost, i, sort_cost } ); + + sol_existance |= column; + } + + /* necessary condition for the existance of a solution */ + if ( __builtin_popcountl( sol_existance ) != combinations ) + { + return false; + } + + if ( !sort ) + { + return true; + } + + std::sort( matrix.begin(), matrix.end(), [&]( auto const& a, auto const& b ) { + return a.sort_cost < b.sort_cost; + } ); + + /* print */ + // if ( best_multiplicity < 6 ) + // { + // for ( uint32_t i = 0; i < columns.size(); ++i ) + // { + // std::cout << indexes[i] << " " << costs[i] << " \t" << columns[i] << "\n"; + // } + // } + + return true; + } + + template + std::array covering_solve_exact( std::vector& matrix, uint32_t max_iter = 100, int32_t limit = 2000 ) + { + /* last value of res contains the size of the bound set */ + std::array res = { UINT32_MAX }; + uint32_t best_cost = UINT32_MAX; + uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; + bool looping = true; + + assert( best_multiplicity <= 16 ); + + /* determine the number of needed loops*/ + if ( best_multiplicity <= 4 ) + { + res[4] = 2; + for ( uint32_t i = 0; i < matrix.size() - 1; ++i ) + { + for ( uint32_t j = 1; j < matrix.size(); ++j ) + { + /* filter by cost */ + if ( matrix[i].cost + matrix[j].cost >= best_cost ) + continue; + + /* check validity */ + if ( __builtin_popcountl( matrix[i].column | matrix[j].column ) == combinations ) + { + res[0] = i; + res[1] = j; + best_cost = matrix[i].cost + matrix[j].cost; + } + } + } + } + else if ( best_multiplicity <= 8 ) + { + res[4] = 3; + for ( uint32_t i = 0; i < matrix.size() - 2 && looping; ++i ) + { + /* limit */ + if constexpr ( limit_iter ) + { + if ( limit <= 0 || ( best_cost < UINT32_MAX && max_iter == 0 ) ) + { + looping = false; + } + } + + for ( uint32_t j = 1; j < matrix.size() - 1 && looping; ++j ) + { + uint64_t current_columns = matrix[i].column | matrix[j].column; + uint32_t current_cost = matrix[i].cost + matrix[j].cost; + + /* limit */ + if constexpr ( limit_iter ) + { + if ( limit <= 0 || ( best_cost < UINT32_MAX && max_iter == 0 ) ) + { + looping = false; + } + } + + /* bound */ + if ( current_cost >= best_cost ) + { + continue; + } + + for ( uint32_t k = 2; k < matrix.size() && looping; ++k ) + { + /* limit */ + if constexpr ( limit_iter ) + { + if ( limit-- <= 0 || ( best_cost < UINT32_MAX && max_iter-- == 0 ) ) + { + looping = false; + } + } + + /* filter by cost */ + if ( current_cost + matrix[k].cost >= best_cost ) + continue; + + /* check validity */ + if ( __builtin_popcountl( current_columns | matrix[k].column ) == combinations ) + { + res[0] = i; + res[1] = j; + res[2] = k; + best_cost = current_cost + matrix[k].cost; + } + } + } + } + } + else + { + res[4] = 4; + for ( uint32_t i = 0; i < matrix.size() - 3 && looping; ++i ) + { + /* limit */ + if constexpr ( limit_iter ) + { + if ( limit <= 0 || ( best_cost < UINT32_MAX && max_iter == 0 ) ) + { + looping = false; + } + } + + for ( uint32_t j = 1; j < matrix.size() - 2 && looping; ++j ) + { + uint64_t current_columns0 = matrix[i].column | matrix[j].column; + uint32_t current_cost0 = matrix[i].cost + matrix[j].cost; + + /* limit */ + if constexpr ( limit_iter ) + { + if ( limit <= 0 || ( best_cost < UINT32_MAX && max_iter == 0 ) ) + { + looping = false; + } + } + + /* bound */ + if ( current_cost0 >= best_cost ) + { + continue; + } + + for ( uint32_t k = 2; k < matrix.size() - 1 && looping; ++k ) + { + uint64_t current_columns1 = current_columns0 | matrix[k].column; + uint32_t current_cost1 = current_cost0 + matrix[k].cost; + + /* limit */ + if constexpr ( limit_iter ) + { + if ( limit <= 0 || ( best_cost < UINT32_MAX && max_iter == 0 ) ) + { + looping = false; + } + } + + /* bound */ + if ( current_cost1 >= best_cost ) + { + continue; + } + + for ( uint32_t t = 3; t < matrix.size() && looping; ++t ) + { + /* limit */ + if constexpr ( limit_iter ) + { + if ( limit-- <= 0 || ( best_cost < UINT32_MAX && max_iter-- == 0 ) ) + { + looping = false; + } + } + + /* filter by cost */ + if ( current_cost1 + matrix[t].cost >= best_cost ) + continue; + + /* check validity */ + if ( __builtin_popcountl( current_columns1 | matrix[t].column ) == combinations ) + { + res[0] = i; + res[1] = j; + res[2] = k; + res[3] = t; + best_cost = current_cost1 + matrix[t].cost; + } + } + } + } + } + } + + return res; + } + + void adjust_truth_table_on_dc( STT& tt, STT& care, uint32_t var_index ) + { + assert( var_index < tt.num_vars() ); + assert( tt.num_vars() == care.num_vars() ); + + if ( tt.num_vars() <= 6 || var_index < 6 ) + { + auto it_tt = std::begin( tt._bits ); + auto it_care = std::begin( care._bits ); + while ( it_tt != std::end( tt._bits ) ) + { + uint64_t new_bits = *it_tt & *it_care; + *it_tt = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) | + ( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] ); + *it_care = *it_care | ( *it_care >> ( uint64_t( 1 ) << var_index ) ); + + ++it_tt; + ++it_care; + } + return; + } + + const auto step = 1 << ( var_index - 6 ); + for ( auto i = 0u; i < static_cast( tt.num_blocks() ); i += 2 * step ) + { + for ( auto j = 0; j < step; ++j ) + { + tt._bits[i + j] = ( tt._bits[i + j] & care._bits[i + j] ) | ( tt._bits[i + j + step] & care._bits[i + j + step] ); + tt._bits[i + j + step] = tt._bits[i + j]; + care._bits[i + j] = care._bits[i + j] | care._bits[i + j + step]; + care._bits[i + j + step] = care._bits[i + j]; + } + } + } + + void local_extend_to( STT& tt, uint32_t real_num_vars ) + { + if ( real_num_vars < 6 ) + { + auto mask = *tt.begin(); + + for ( auto i = real_num_vars; i < num_vars; ++i ) + { + mask |= ( mask << ( 1 << i ) ); + } + + std::fill( tt.begin(), tt.end(), mask ); + } + else + { + uint32_t num_blocks = ( 1u << ( real_num_vars - 6 ) ); + auto it = tt.begin(); + while ( it != tt.end() ) + { + it = std::copy( tt.cbegin(), tt.cbegin() + num_blocks, it ); + } + } + } + + bool has_var_support( const STT& tt, const STT& care, uint32_t real_num_vars, uint8_t var_index ) + { + assert( var_index < real_num_vars ); + assert( real_num_vars <= tt.num_vars() ); + assert( tt.num_vars() == care.num_vars() ); + + const uint32_t num_blocks = real_num_vars <= 6 ? 1 : ( 1 << ( real_num_vars - 6 ) ); + if ( real_num_vars <= 6 || var_index < 6 ) + { + auto it_tt = std::begin( tt._bits ); + auto it_care = std::begin( care._bits ); + while ( it_tt != std::begin( tt._bits ) + num_blocks ) + { + if ( ( ( ( *it_tt >> ( uint64_t( 1 ) << var_index ) ) ^ *it_tt ) & kitty::detail::projections_neg[var_index] + & ( *it_care >> ( uint64_t( 1 ) << var_index ) ) & *it_care ) != 0 ) + { + return true; + } + ++it_tt; + ++it_care; + } + + return false; + } + + const auto step = 1 << ( var_index - 6 ); + for ( auto i = 0u; i < num_blocks; i += 2 * step ) + { + for ( auto j = 0; j < step; ++j ) + { + if ( ( ( tt._bits[i + j] ^ tt._bits[i + j + step] ) & care._bits[i + j] & care._bits[i + j + step] ) != 0 ) + { + return true; + } + } + } + + return false; + } + + void get_decomposition_abc( unsigned char *decompArray ) + { + unsigned char *pArray = decompArray; + unsigned char bytes = 2; + + /* write number of LUTs */ + pArray++; + *pArray = dec_result.size(); + pArray++; + + /* write LUTs */ + for ( ac_decomposition_result const& lut : dec_result ) + { + /* write fanin size*/ + *pArray = lut.support.size(); + pArray++; ++bytes; + + /* write support */ + for ( uint32_t i : lut.support ) + { + *pArray = (unsigned char) i; + pArray++; ++bytes; + } + + /* write truth table */ + uint32_t tt_num_bytes = ( lut.tt.num_vars() <= 3 ) ? 1 : ( 1 << ( lut.tt.num_vars() - 3 ) ); + tt_num_bytes = std::min( tt_num_bytes, 8u ); + for ( uint32_t i = 0; i < lut.tt.num_blocks(); ++i ) + { + for ( uint32_t j = 0; j < tt_num_bytes; ++j ) + { + *pArray = (unsigned char) ( ( lut.tt._bits[i] >> ( 8 * j ) ) & 0xFF ); + pArray++; ++bytes; + } + } + } + + /* write numBytes */ + *decompArray = bytes; + } + +private: + uint32_t best_multiplicity{ UINT32_MAX }; + uint32_t best_free_set{ UINT32_MAX }; + STT best_tt; + std::vector best_bound_sets; + std::vector best_care_sets; + std::vector best_free_set_tts; + std::vector best_iset_onset; + std::vector best_iset_offset; + std::vector dec_result; + + std::vector> support_minimization_encodings; + + TT tt_start; + uint32_t num_vars; + ac_decomposition_params const& ps; + ac_decomposition_stats* pst; + std::vector permutations; +}; + +} // namespace mockturtle + +#endif // _ACD_H_ \ No newline at end of file diff --git a/src/acd/ac_wrapper.cpp b/src/acd/ac_wrapper.cpp new file mode 100644 index 000000000..b7cee0dd7 --- /dev/null +++ b/src/acd/ac_wrapper.cpp @@ -0,0 +1,69 @@ +// #include "base/main/main.h" +#include "ac_wrapper.h" +#include "ac_decomposition.hpp" + +// ABC_NAMESPACE_IMPL_START + +int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost ) +{ + using namespace mockturtle; + + int num_blocks = ( nVars <= 6 ) ? 1 : ( 1 << ( nVars - 6 ) ); + + /* translate truth table into static table */ + kitty::dynamic_truth_table tt( nVars ); + for ( int i = 0; i < num_blocks; ++i ) + tt._bits[i] = pTruth[i]; + + ac_decomposition_params ps; + ps.lut_size = lutSize; + ac_decomposition_stats st; + + ac_decomposition_impl acd( tt, nVars, ps, &st ); + acd.run( *pdelay ); + int val = acd.compute_decomposition(); + + if ( val < 0 ) + { + *pdelay = 0; + return -1; + } + + *pdelay = acd.get_profile(); + *cost = st.num_luts; + + return 0; +} + +int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ) +{ + using namespace mockturtle; + + int num_blocks = ( nVars <= 6 ) ? 1 : ( 1 << ( nVars - 6 ) ); + + /* translate truth table into static table */ + kitty::dynamic_truth_table tt( nVars ); + for ( int i = 0; i < num_blocks; ++i ) + tt._bits[i] = pTruth[i]; + + ac_decomposition_params ps; + ps.lut_size = lutSize; + ac_decomposition_stats st; + + ac_decomposition_impl acd( tt, nVars, ps, &st ); + acd.run( *pdelay ); + int val = acd.compute_decomposition(); + + if ( val < 0 ) + { + *pdelay = 0; + return -1; + } + + *pdelay = acd.get_profile(); + + acd.get_decomposition( decomposition ); + return 0; +} + +// ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/acd/ac_wrapper.h b/src/acd/ac_wrapper.h new file mode 100644 index 000000000..522a60b86 --- /dev/null +++ b/src/acd/ac_wrapper.h @@ -0,0 +1,23 @@ +// #pragma once +#ifndef __ACD_WRAPPER_H_ +#define __ACD_WRAPPER_H_ + +// #include "base/main/main.h" +#include "misc/util/abc_global.h" + +// ABC_NAMESPACE_HEADER_START + +#ifdef __cplusplus +extern "C" { +#endif + +int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost ); +int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); + +#ifdef __cplusplus +} +#endif + +// ABC_NAMESPACE_HEADER_END + +#endif \ No newline at end of file diff --git a/src/acd/kitty_algorithm.hpp b/src/acd/kitty_algorithm.hpp new file mode 100644 index 000000000..6460a802c --- /dev/null +++ b/src/acd/kitty_algorithm.hpp @@ -0,0 +1,119 @@ +#ifndef _KITTY_ALGORITHM_H_ +#define _KITTY_ALGORITHM_H_ +#pragma once + +#include +#include + +#include "kitty_constants.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_static_tt.hpp" + +namespace kitty +{ + +/*! \brief Perform bitwise unary operation on truth table + + \param tt Truth table + \param op Unary operation that takes as input a word (`uint64_t`) and returns a word + + \return new constructed truth table of same type and dimensions + */ +template +auto unary_operation( const TT& tt, Fn&& op ) +{ + auto result = tt.construct(); + std::transform( tt.cbegin(), tt.cend(), result.begin(), op ); + result.mask_bits(); + return result; +} + +/*! \brief Perform bitwise binary operation on two truth tables + + The dimensions of `first` and `second` must match. This is ensured + at compile-time for static truth tables, but at run-time for dynamic + truth tables. + + \param first First truth table + \param second Second truth table + \param op Binary operation that takes as input two words (`uint64_t`) and returns a word + + \return new constructed truth table of same type and dimensions + */ +template +auto binary_operation( const TT& first, const TT& second, Fn&& op ) +{ + assert( first.num_vars() == second.num_vars() ); + + auto result = first.construct(); + std::transform( first.cbegin(), first.cend(), second.cbegin(), result.begin(), op ); + result.mask_bits(); + return result; +} + +/*! \brief Computes a predicate based on two truth tables + + The dimensions of `first` and `second` must match. This is ensured + at compile-time for static truth tables, but at run-time for dynamic + truth tables. + + \param first First truth table + \param second Second truth table + \param op Binary operation that takes as input two words (`uint64_t`) and returns a Boolean + + \return true or false based on the predicate + */ +template +bool binary_predicate( const TT& first, const TT& second, Fn&& op ) +{ + assert( first.num_vars() == second.num_vars() ); + + return std::equal( first.begin(), first.end(), second.begin(), op ); +} + +/*! \brief Assign computed values to bits + + The functor `op` computes bits which are assigned to the bits of the + truth table. + + \param tt Truth table + \param op Unary operation that takes no input and returns a word (`uint64_t`) +*/ +template +void assign_operation( TT& tt, Fn&& op ) +{ + std::generate( tt.begin(), tt.end(), op ); + tt.mask_bits(); +} + +/*! \brief Iterates through each block of a truth table + + The functor `op` is called for every block of the truth table. + + \param tt Truth table + \param op Unary operation that takes as input a word (`uint64_t`) and returns void +*/ +template +void for_each_block( const TT& tt, Fn&& op ) +{ + std::for_each( tt.cbegin(), tt.cend(), op ); +} + +/*! \brief Iterates through each block of a truth table in reverse + order + + The functor `op` is called for every block of the truth table in + reverse order. + + \param tt Truth table + \param op Unary operation that takes as input a word (`uint64_t`) and returns void +*/ +template +void for_each_block_reversed( const TT& tt, Fn&& op ) +{ + std::for_each( tt.crbegin(), tt.crend(), op ); +} + +} // namespace kitty + +#endif // _KITTY_ALGORITHM_H_ \ No newline at end of file diff --git a/src/acd/kitty_constants.hpp b/src/acd/kitty_constants.hpp new file mode 100644 index 000000000..55cfcd650 --- /dev/null +++ b/src/acd/kitty_constants.hpp @@ -0,0 +1,91 @@ +#ifndef _KITTY_CONSTANTS_H_ +#define _KITTY_CONSTANTS_H_ +#pragma once + +#include +#include + +namespace kitty +{ + +namespace detail +{ + +static constexpr uint64_t projections[] = { + UINT64_C( 0xaaaaaaaaaaaaaaaa ), + UINT64_C( 0xcccccccccccccccc ), + UINT64_C( 0xf0f0f0f0f0f0f0f0 ), + UINT64_C( 0xff00ff00ff00ff00 ), + UINT64_C( 0xffff0000ffff0000 ), + UINT64_C( 0xffffffff00000000 ) }; + +static constexpr uint64_t projections_neg[] = { + UINT64_C( 0x5555555555555555 ), + UINT64_C( 0x3333333333333333 ), + UINT64_C( 0x0f0f0f0f0f0f0f0f ), + UINT64_C( 0x00ff00ff00ff00ff ), + UINT64_C( 0x0000ffff0000ffff ), + UINT64_C( 0x00000000ffffffff ) }; + +static constexpr uint64_t masks[] = { + UINT64_C( 0x0000000000000001 ), + UINT64_C( 0x0000000000000003 ), + UINT64_C( 0x000000000000000f ), + UINT64_C( 0x00000000000000ff ), + UINT64_C( 0x000000000000ffff ), + UINT64_C( 0x00000000ffffffff ), + UINT64_C( 0xffffffffffffffff ) }; + +static constexpr uint64_t permutation_masks[][3] = { + { UINT64_C( 0x9999999999999999 ), UINT64_C( 0x2222222222222222 ), UINT64_C( 0x4444444444444444 ) }, + { UINT64_C( 0xc3c3c3c3c3c3c3c3 ), UINT64_C( 0x0c0c0c0c0c0c0c0c ), UINT64_C( 0x3030303030303030 ) }, + { UINT64_C( 0xf00ff00ff00ff00f ), UINT64_C( 0x00f000f000f000f0 ), UINT64_C( 0x0f000f000f000f00 ) }, + { UINT64_C( 0xff0000ffff0000ff ), UINT64_C( 0x0000ff000000ff00 ), UINT64_C( 0x00ff000000ff0000 ) }, + { UINT64_C( 0xffff00000000ffff ), UINT64_C( 0x00000000ffff0000 ), UINT64_C( 0x0000ffff00000000 ) } }; + +static constexpr uint64_t ppermutation_masks[][6][3] = { + { { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x9999999999999999 ), UINT64_C( 0x2222222222222222 ), UINT64_C( 0x4444444444444444 ) }, + { UINT64_C( 0xa5a5a5a5a5a5a5a5 ), UINT64_C( 0x0a0a0a0a0a0a0a0a ), UINT64_C( 0x5050505050505050 ) }, + { UINT64_C( 0xaa55aa55aa55aa55 ), UINT64_C( 0x00aa00aa00aa00aa ), UINT64_C( 0x5500550055005500 ) }, + { UINT64_C( 0xaaaa5555aaaa5555 ), UINT64_C( 0x0000aaaa0000aaaa ), UINT64_C( 0x5555000055550000 ) }, + { UINT64_C( 0xaaaaaaaa55555555 ), UINT64_C( 0x00000000aaaaaaaa ), UINT64_C( 0x5555555500000000 ) } }, + { { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0xc3c3c3c3c3c3c3c3 ), UINT64_C( 0x0c0c0c0c0c0c0c0c ), UINT64_C( 0x3030303030303030 ) }, + { UINT64_C( 0xcc33cc33cc33cc33 ), UINT64_C( 0x00cc00cc00cc00cc ), UINT64_C( 0x3300330033003300 ) }, + { UINT64_C( 0xcccc3333cccc3333 ), UINT64_C( 0x0000cccc0000cccc ), UINT64_C( 0x3333000033330000 ) }, + { UINT64_C( 0xcccccccc33333333 ), UINT64_C( 0x00000000cccccccc ), UINT64_C( 0x3333333300000000 ) } }, + { { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0xf00ff00ff00ff00f ), UINT64_C( 0x00f000f000f000f0 ), UINT64_C( 0x0f000f000f000f00 ) }, + { UINT64_C( 0xf0f00f0ff0f00f0f ), UINT64_C( 0x0000f0f00000f0f0 ), UINT64_C( 0x0f0f00000f0f0000 ) }, + { UINT64_C( 0xf0f0f0f00f0f0f0f ), UINT64_C( 0x00000000f0f0f0f0 ), UINT64_C( 0x0f0f0f0f00000000 ) } }, + { { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0xff0000ffff0000ff ), UINT64_C( 0x0000ff000000ff00 ), UINT64_C( 0x00ff000000ff0000 ) }, + { UINT64_C( 0xff00ff0000ff00ff ), UINT64_C( 0x00000000ff00ff00 ), UINT64_C( 0x00ff00ff00000000 ) } }, + { { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0xffff00000000ffff ), UINT64_C( 0x00000000ffff0000 ), UINT64_C( 0x0000ffff00000000 ) } } }; + +static constexpr int32_t hex_to_int[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; + +} // namespace detail + +} // namespace kitty + +#endif //_KITTY_CONSTANTS_H_ \ No newline at end of file diff --git a/src/acd/kitty_constructors.hpp b/src/acd/kitty_constructors.hpp new file mode 100644 index 000000000..43408b8cc --- /dev/null +++ b/src/acd/kitty_constructors.hpp @@ -0,0 +1,92 @@ +#ifndef _KITTY_CONSTRUCT_TT_H_ +#define _KITTY_CONSTRUCT_TT_H_ +#pragma once + +#include +#include +#include +#include +#include + +#include "kitty_constants.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_static_tt.hpp" + +namespace kitty +{ + +/*! \brief Creates truth table with number of variables + + If some truth table instance is given, one can create a truth table with the + same type by calling the `construct()` method on it. This function helps if + only the number of variables is known and the base type and uniforms the + creation of static and dynamic truth tables. Note, however, that for static + truth tables `num_vars` must be consistent to the number of variables in the + truth table type. + + \param num_vars Number of variables +*/ +template +inline TT create( unsigned num_vars ) +{ + (void)num_vars; + TT tt; + assert( tt.num_vars() == num_vars ); + return tt; +} + +/*! \cond PRIVATE */ +template<> +inline dynamic_truth_table create( unsigned num_vars ) +{ + return dynamic_truth_table( num_vars ); +} +/*! \endcond */ + +/*! \brief Constructs projections (single-variable functions) + + \param tt Truth table + \param var_index Index of the variable, must be smaller than the truth table's number of variables + \param complement If true, realize inverse projection +*/ +template +void create_nth_var( TT& tt, uint8_t var_index, bool complement = false ) +{ + if ( tt.num_vars() <= 6 ) + { + /* assign from precomputed table */ + tt._bits[0] = complement ? ~detail::projections[var_index] : detail::projections[var_index]; + + /* mask if truth table does not require all bits */ + tt.mask_bits(); + return; + } + + if ( var_index < 6 ) + { + std::fill( std::begin( tt._bits ), std::end( tt._bits ), complement ? ~detail::projections[var_index] : detail::projections[var_index] ); + } + else + { + const auto c = 1 << ( var_index - 6 ); + const auto zero = uint64_t( 0 ); + const auto one = ~zero; + auto block = uint64_t( 0u ); + + while ( block < tt.num_blocks() ) + { + for ( auto i = 0; i < c; ++i ) + { + tt._bits[block++] = complement ? one : zero; + } + for ( auto i = 0; i < c; ++i ) + { + tt._bits[block++] = complement ? zero : one; + } + } + } +} + +} // namespace kitty + +#endif // _KITTY_CONSTRUCT_TT_H_ \ No newline at end of file diff --git a/src/acd/kitty_dynamic_tt.hpp b/src/acd/kitty_dynamic_tt.hpp new file mode 100644 index 000000000..f3ef0c7d9 --- /dev/null +++ b/src/acd/kitty_dynamic_tt.hpp @@ -0,0 +1,147 @@ +#ifndef _KITTY_DYNAMIC_TT_H_ +#define _KITTY_DYNAMIC_TT_H_ +#pragma once + +#include +#include +#include + +#include "kitty_constants.hpp" + +namespace kitty +{ + +/*! Truth table in which number of variables is known at runtime. + */ +struct dynamic_truth_table +{ + /*! Standard constructor. + + The number of variables provided to the truth table can be + computed at runtime. However, once the truth table is constructed + its number of variables cannot change anymore. + + The constructor computes the number of blocks and resizes the + vector accordingly. + + \param num_vars Number of variables + */ + explicit dynamic_truth_table( uint32_t num_vars ) + : _bits( ( num_vars <= 6 ) ? 1u : ( 1u << ( num_vars - 6 ) ) ), + _num_vars( num_vars ) + { + } + + /*! Empty constructor. + + Creates an empty truth table. It has 0 variables, but no bits, i.e., it is + different from a truth table for the constant function. This constructor is + only used for convenience, if algorithms require the existence of default + constructable classes. + */ + dynamic_truth_table() : _num_vars( 0 ) {} + + /*! Constructs a new dynamic truth table instance with the same number of variables. */ + inline dynamic_truth_table construct() const + { + return dynamic_truth_table( _num_vars ); + } + + /*! Returns number of variables. + */ + inline auto num_vars() const noexcept { return _num_vars; } + + /*! Returns number of blocks. + */ + inline auto num_blocks() const noexcept { return _bits.size(); } + + /*! Returns number of bits. + */ + inline auto num_bits() const noexcept { return uint64_t( 1 ) << _num_vars; } + + /*! \brief Begin iterator to bits. + */ + inline auto begin() noexcept { return _bits.begin(); } + + /*! \brief End iterator to bits. + */ + inline auto end() noexcept { return _bits.end(); } + + /*! \brief Begin iterator to bits. + */ + inline auto begin() const noexcept { return _bits.begin(); } + + /*! \brief End iterator to bits. + */ + inline auto end() const noexcept { return _bits.end(); } + + /*! \brief Reverse begin iterator to bits. + */ + inline auto rbegin() noexcept { return _bits.rbegin(); } + + /*! \brief Reverse end iterator to bits. + */ + inline auto rend() noexcept { return _bits.rend(); } + + /*! \brief Constant begin iterator to bits. + */ + inline auto cbegin() const noexcept { return _bits.cbegin(); } + + /*! \brief Constant end iterator to bits. + */ + inline auto cend() const noexcept { return _bits.cend(); } + + /*! \brief Constant reverse begin iterator to bits. + */ + inline auto crbegin() const noexcept { return _bits.crbegin(); } + + /*! \brief Constant teverse end iterator to bits. + */ + inline auto crend() const noexcept { return _bits.crend(); } + + /*! \brief Assign other truth table. + + This replaces the current truth table with another truth table. The truth + table type has to be complete. The vector of bits is resized accordingly. + + \param other Other truth table + */ + template + dynamic_truth_table& operator=( const TT& other ) + { + _bits.resize( other.num_blocks() ); + std::copy( other.begin(), other.end(), begin() ); + _num_vars = other.num_vars(); + + if ( _num_vars < 6 ) + { + mask_bits(); + } + + return *this; + } + + /*! Masks the number of valid truth table bits. + + If the truth table has less than 6 variables, it may not use all + the bits. This operation makes sure to zero out all non-valid + bits. + */ + inline void mask_bits() noexcept + { + if ( _num_vars < 6 ) + { + _bits[0u] &= detail::masks[_num_vars]; + } + } + + /*! \cond PRIVATE */ +public: /* fields */ + std::vector _bits; + uint32_t _num_vars; + /*! \endcond */ +}; + +} //namespace kitty + +#endif // _KITTY_DYNAMIC_TT_H_ \ No newline at end of file diff --git a/src/acd/kitty_operations.hpp b/src/acd/kitty_operations.hpp new file mode 100644 index 000000000..fb504489a --- /dev/null +++ b/src/acd/kitty_operations.hpp @@ -0,0 +1,333 @@ +#ifndef _KITTY_OPERATIONS_TT_H_ +#define _KITTY_OPERATIONS_TT_H_ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "kitty_algorithm.hpp" +#include "kitty_constants.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_static_tt.hpp" + +namespace kitty +{ + +/*! Inverts all bits in a truth table, based on a condition */ +template +inline TT unary_not_if( const TT& tt, bool cond ) +{ +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + const auto mask = -static_cast( cond ); +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + return unary_operation( tt, [mask]( auto a ) + { return a ^ mask; } ); +} + +/*! \brief Inverts all bits in a truth table */ +template +inline TT unary_not( const TT& tt ) +{ + return unary_operation( tt, []( auto a ) + { return ~a; } ); +} + +/*! \brief Bitwise AND of two truth tables */ +template + +inline TT binary_and( const TT& first, const TT& second ) +{ + return binary_operation( first, second, std::bit_and<>() ); +} + +/*! \brief Bitwise OR of two truth tables */ +template +inline TT binary_or( const TT& first, const TT& second ) +{ + return binary_operation( first, second, std::bit_or<>() ); +} + +/*! \brief Swaps two variables in a truth table + + The function swaps variable `var_index1` with `var_index2`. The + function will change `tt` in-place. If `tt` should not be changed, + one can use `swap` instead. + + \param tt Truth table + \param var_index1 First variable + \param var_index2 Second variable +*/ +template +void swap_inplace( TT& tt, uint8_t var_index1, uint8_t var_index2 ) +{ + if ( var_index1 == var_index2 ) + { + return; + } + + if ( var_index1 > var_index2 ) + { + std::swap( var_index1, var_index2 ); + } + + if ( tt.num_vars() <= 6 ) + { + const auto& pmask = detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + tt._bits[0] = ( tt._bits[0] & pmask[0] ) | ( ( tt._bits[0] & pmask[1] ) << shift ) | ( ( tt._bits[0] & pmask[2] ) >> shift ); + } + else if ( var_index2 <= 5 ) + { + const auto& pmask = detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + std::transform( std::begin( tt._bits ), std::end( tt._bits ), std::begin( tt._bits ), + [shift, &pmask]( uint64_t word ) + { + return ( word & pmask[0] ) | ( ( word & pmask[1] ) << shift ) | ( ( word & pmask[2] ) >> shift ); + } ); + } + else if ( var_index1 <= 5 ) /* in this case, var_index2 > 5 */ + { + const auto step = 1 << ( var_index2 - 6 ); + const auto shift = 1 << var_index1; + auto it = std::begin( tt._bits ); + while ( it != std::end( tt._bits ) ) + { + for ( auto i = decltype( step ){ 0 }; i < step; ++i ) + { + const auto low_to_high = ( *( it + i ) & detail::projections[var_index1] ) >> shift; + const auto high_to_low = ( *( it + i + step ) << shift ) & detail::projections[var_index1]; + *( it + i ) = ( *( it + i ) & ~detail::projections[var_index1] ) | high_to_low; + *( it + i + step ) = ( *( it + i + step ) & detail::projections[var_index1] ) | low_to_high; + } + it += 2 * step; + } + } + else + { + const auto step1 = 1 << ( var_index1 - 6 ); + const auto step2 = 1 << ( var_index2 - 6 ); + auto it = std::begin( tt._bits ); + while ( it != std::end( tt._bits ) ) + { + for ( auto i = 0; i < step2; i += 2 * step1 ) + { + for ( auto j = 0; j < step1; ++j ) + { + std::swap( *( it + i + j + step1 ), *( it + i + j + step2 ) ); + } + } + it += 2 * step2; + } + } +} + +/*! \brief Extends smaller truth table to larger one + + The most significant variables will not be in the functional support of the + resulting truth table, but the method is helpful to align a truth table when + being used with another one. + + \param tt Larger truth table to create + \param from Smaller truth table to copy from +*/ +template +void extend_to_inplace( TT& tt, const TTFrom& from ) +{ + assert( tt.num_vars() >= from.num_vars() ); + + if ( from.num_vars() < 6 ) + { + auto mask = *from.begin(); + + for ( auto i = from.num_vars(); i < std::min( 6, tt.num_vars() ); ++i ) + { + mask |= ( mask << ( 1 << i ) ); + } + + std::fill( tt.begin(), tt.end(), mask ); + } + else + { + auto it = tt.begin(); + while ( it != tt.end() ) + { + it = std::copy( from.cbegin(), from.cend(), it ); + } + } +} + +/*! \brief Extends smaller truth table to larger static one + + This is an out-of-place version of `extend_to_inplace` that has the truth + table as a return value. It only works for creating static truth tables. The + template parameter `NumVars` must be equal or larger to the number of + variables in `from`. + + \param from Smaller truth table to copy from +*/ +template +inline static_truth_table extend_to( const TTFrom& from ) +{ + static_truth_table tt; + extend_to_inplace( tt, from ); + return tt; +} + +/*! \brief Checks whether truth table depends on given variable index + + \param tt Truth table + \param var_index Variable index +*/ +template +bool has_var( const TT& tt, uint8_t var_index ) +{ + assert( var_index < tt.num_vars() ); + + if ( tt.num_vars() <= 6 || var_index < 6 ) + { + return std::any_of( std::begin( tt._bits ), std::end( tt._bits ), + [var_index]( uint64_t word ) + { return ( ( word >> ( uint64_t( 1 ) << var_index ) ) & detail::projections_neg[var_index] ) != + ( word & detail::projections_neg[var_index] ); } ); + } + + const auto step = 1 << ( var_index - 6 ); + for ( auto i = 0u; i < static_cast( tt.num_blocks() ); i += 2 * step ) + { + for ( auto j = 0; j < step; ++j ) + { + if ( tt._bits[i + j] != tt._bits[i + j + step] ) + { + return true; + } + } + } + return false; +} + +/*! \brief Checks whether truth table depends on given variable index + + \param tt Truth table + \param care Care set + \param var_index Variable index +*/ +template +bool has_var( const TT& tt, const TT& care, uint8_t var_index ) +{ + assert( var_index < tt.num_vars() ); + assert( tt.num_vars() == care.num_vars() ); + + if ( tt.num_vars() <= 6 || var_index < 6 ) + { + auto it_tt = std::begin( tt._bits ); + auto it_care = std::begin( care._bits ); + while ( it_tt != std::end( tt._bits ) ) + { + if ( ( ( ( *it_tt >> ( uint64_t( 1 ) << var_index ) ) ^ *it_tt ) & detail::projections_neg[var_index] + & ( *it_care >> ( uint64_t( 1 ) << var_index ) ) & *it_care ) != 0 ) + { + return true; + } + ++it_tt; + ++it_care; + } + + return false; + } + + const auto step = 1 << ( var_index - 6 ); + for ( auto i = 0u; i < static_cast( tt.num_blocks() ); i += 2 * step ) + { + for ( auto j = 0; j < step; ++j ) + { + if ( ( ( tt._bits[i + j] ^ tt._bits[i + j + step] ) & care._bits[i + j] & care._bits[i + j + step] ) != 0 ) + { + return true; + } + } + } + return false; +} + +/*! \brief Shrinks larger truth table to smaller one + + The function expects that the most significant bits, which are cut off, are + not in the functional support of the original function. Only then it is + ensured that the resulting function is equivalent. + + \param tt Smaller truth table to create + \param from Larger truth table to copy from +*/ +template +void shrink_to_inplace( TT& tt, const TTFrom& from ) +{ + assert( tt.num_vars() <= from.num_vars() ); + + std::copy( from.begin(), from.begin() + tt.num_blocks(), tt.begin() ); + + if ( tt.num_vars() < 6 ) + { + tt.mask_bits(); + } +} + +/*! \brief Shrinks larger truth table to smaller dynamic one + + This is an out-of-place version of `shrink_to` that has the truth table as a + return value. It only works for creating dynamic tables. The parameter + `num_vars` must be equal or smaller to the number of variables in `from`. + + \param from Smaller truth table to copy from +*/ +template +inline dynamic_truth_table shrink_to( const TTFrom& from, unsigned num_vars ) +{ + auto tt = create( num_vars ); + shrink_to_inplace( tt, from ); + return tt; +} + +/*! \brief Prints truth table in hexadecimal representation + + The most-significant bit will be the first character of the string. + + \param tt Truth table + \param os Output stream +*/ +template +void print_hex( const TT& tt, std::ostream& os = std::cout ) +{ + auto const chunk_size = + std::min( tt.num_vars() <= 1 ? 1 : ( tt.num_bits() >> 2 ), 16 ); + + for_each_block_reversed( tt, [&os, chunk_size]( auto word ) + { + std::string chunk( chunk_size, '0' ); + + auto it = chunk.rbegin(); + while (word && it != chunk.rend()) { + auto hex = word & 0xf; + if (hex < 10) { + *it = '0' + static_cast(hex); + } else { + *it = 'a' + static_cast(hex - 10); + } + ++it; + word >>= 4; + } + os << chunk; } ); +} + +} //namespace kitty + +#endif // _KITTY_OPERATIONS_TT_H_ \ No newline at end of file diff --git a/src/acd/kitty_operators.hpp b/src/acd/kitty_operators.hpp new file mode 100644 index 000000000..cf973ebe0 --- /dev/null +++ b/src/acd/kitty_operators.hpp @@ -0,0 +1,86 @@ +#ifndef _KITTY_OPERATORS_TT_H_ +#define _KITTY_OPERATORS_TT_H_ +#pragma once + +#include +#include +#include +#include +#include + +#include "kitty_constants.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_static_tt.hpp" +#include "kitty_operations.hpp" + +namespace kitty +{ + +/*! \brief Operator for unary_not */ +inline dynamic_truth_table operator~( const dynamic_truth_table& tt ) +{ + return unary_not( tt ); +} + +/*! \brief Operator for unary_not */ +template +inline static_truth_table operator~( const static_truth_table& tt ) +{ + return unary_not( tt ); +} + +/*! \brief Operator for binary_and */ +inline dynamic_truth_table operator&( const dynamic_truth_table& first, const dynamic_truth_table& second ) +{ + return binary_and( first, second ); +} + +/*! \brief Operator for binary_and */ +template +inline static_truth_table operator&( const static_truth_table& first, const static_truth_table& second ) +{ + return binary_and( first, second ); +} + +/*! \brief Operator for binary_and and assign */ +inline void operator&=( dynamic_truth_table& first, const dynamic_truth_table& second ) +{ + first = binary_and( first, second ); +} + +/*! \brief Operator for binary_and and assign */ +template +inline void operator&=( static_truth_table& first, const static_truth_table& second ) +{ + first = binary_and( first, second ); +} + +/*! \brief Operator for binary_or */ +inline dynamic_truth_table operator|( const dynamic_truth_table& first, const dynamic_truth_table& second ) +{ + return binary_or( first, second ); +} + +/*! \brief Operator for binary_or */ +template +inline static_truth_table operator|( const static_truth_table& first, const static_truth_table& second ) +{ + return binary_or( first, second ); +} + +/*! \brief Operator for binary_or and assign */ +inline void operator|=( dynamic_truth_table& first, const dynamic_truth_table& second ) +{ + first = binary_or( first, second ); +} + +/*! \brief Operator for binary_or and assign */ +template +inline void operator|=( static_truth_table& first, const static_truth_table& second ) +{ + first = binary_or( first, second ); +} + +} // namespace kitty + +#endif // _KITTY_OPERATORS_TT_H_ \ No newline at end of file diff --git a/src/acd/kitty_static_tt.hpp b/src/acd/kitty_static_tt.hpp new file mode 100644 index 000000000..61593f3ff --- /dev/null +++ b/src/acd/kitty_static_tt.hpp @@ -0,0 +1,131 @@ +#ifndef _KITTY_STATIC_TT_H_ +#define _KITTY_STATIC_TT_H_ +#pragma once + +#include +#include + +#include "kitty_constants.hpp" + +namespace kitty +{ + +template +struct static_truth_table +{ + /*! \cond PRIVATE */ + enum + { + NumBlocks = ( NumVars <= 6 ) ? 1u : ( 1u << ( NumVars - 6 ) ) + }; + + enum + { + NumBits = uint64_t( 1 ) << NumVars + }; + /*! \endcond */ + + /*! Standard constructor. + + The number of variables provided to the truth table must be known + at runtime. The number of blocks will be computed as a compile + time constant. + */ + static_truth_table() + { + _bits.fill( 0 ); + } + + /*! Constructs a new static truth table instance with the same number of variables. */ + inline static_truth_table construct() const + { + return static_truth_table(); + } + + /*! Returns number of variables. + */ + inline auto num_vars() const noexcept { return NumVars; } + + /*! Returns number of blocks. + */ + inline auto num_blocks() const noexcept { return NumBlocks; } + + /*! Returns number of bits. + */ + inline auto num_bits() const noexcept { return NumBits; } + + /*! \brief Begin iterator to bits. + */ + inline auto begin() noexcept { return _bits.begin(); } + + /*! \brief End iterator to bits. + */ + inline auto end() noexcept { return _bits.end(); } + + /*! \brief Begin iterator to bits. + */ + inline auto begin() const noexcept { return _bits.begin(); } + + /*! \brief End iterator to bits. + */ + inline auto end() const noexcept { return _bits.end(); } + + /*! \brief Reverse begin iterator to bits. + */ + inline auto rbegin() noexcept { return _bits.rbegin(); } + + /*! \brief Reverse end iterator to bits. + */ + inline auto rend() noexcept { return _bits.rend(); } + + /*! \brief Constant begin iterator to bits. + */ + inline auto cbegin() const noexcept { return _bits.cbegin(); } + + /*! \brief Constant end iterator to bits. + */ + inline auto cend() const noexcept { return _bits.cend(); } + + /*! \brief Constant reverse begin iterator to bits. + */ + inline auto crbegin() const noexcept { return _bits.crbegin(); } + + /*! \brief Constant teverse end iterator to bits. + */ + inline auto crend() const noexcept { return _bits.crend(); } + + /*! \brief Assign other truth table if number of variables match. + + This replaces the current truth table with another truth table, if `other` + has the same number of variables. Otherwise, the truth table is not + changed. + + \param other Other truth table + */ + template + static_truth_table& operator=( const TT& other ) + { + if ( other.num_bits() == num_bits() ) + { + std::copy( other.begin(), other.end(), begin() ); + } + + return *this; + } + + /*! Masks the number of valid truth table bits. + + We know that we will have at least 7 variables in this data + structure. + */ + inline void mask_bits() noexcept {} + + /*! \cond PRIVATE */ +public: /* fields */ + std::array _bits; + /*! \endcond */ +}; + +} //namespace kitty + +#endif // _KITTY_STATIC_TT_H_ \ No newline at end of file diff --git a/src/acd/module.make b/src/acd/module.make new file mode 100644 index 000000000..b245d2c42 --- /dev/null +++ b/src/acd/module.make @@ -0,0 +1 @@ +SRC += src/acd/ac_wrapper.cpp diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index c8e2b1ef8..33b85e0bf 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -19447,7 +19447,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) If_ManSetDefaultPars( pPars ); pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyzuojiktncvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyuojiktnczvh" ) ) != EOF ) { switch ( c ) { @@ -19652,9 +19652,6 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'y': pPars->fUserRecLib ^= 1; break; - case 'z': - pPars->fUserLutDec ^= 1; - break; case 'u': pPars->fUserSesLib ^= 1; break; @@ -19679,6 +19676,9 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'c': pPars->fUseTtPerm ^= 1; break; + case 'z': + pPars->fAcd ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -19810,7 +19810,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pLutLib = NULL; } // modify for delay optimization - if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fUserLutDec ) + if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fAcd ) { pPars->fTruth = 1; pPars->fCutMin = 1; @@ -19956,7 +19956,7 @@ usage: sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyzuojiktncvh]\n" ); + Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyuojiktncvh]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -19985,7 +19985,6 @@ usage: Abc_Print( -2, "\t-g : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" ); Abc_Print( -2, "\t-x : toggles delay optimization by DSD balancing [default = %s]\n", pPars->fDsdBalance? "yes": "no" ); Abc_Print( -2, "\t-y : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" ); - Abc_Print( -2, "\t-z : toggles delay optimization with LUT decomposition [default = %s]\n", pPars->fUserLutDec? "yes": "no" ); Abc_Print( -2, "\t-u : toggles delay optimization with SAT-based library [default = %s]\n", pPars->fUserSesLib? "yes": "no" ); Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" ); Abc_Print( -2, "\t-j : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" ); @@ -19994,6 +19993,7 @@ usage: Abc_Print( -2, "\t-t : toggles optimizing average rather than maximum level [default = %s]\n", pPars->fDoAverage? "yes": "no" ); Abc_Print( -2, "\t-n : toggles computing DSDs of the cut functions [default = %s]\n", pPars->fUseDsd? "yes": "no" ); Abc_Print( -2, "\t-c : toggles computing truth tables in a new way [default = %s]\n", pPars->fUseTtPerm? "yes": "no" ); + Abc_Print( -2, "\t-z : toggles using ACD decomposition [default = %s]\n", pPars->fAcd? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index e92a2282e..079cd0066 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -116,7 +116,7 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk); // update timing info to reflect logic level - if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fUserLutDec) && pNtk->pManTime ) + if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fAcd) && pNtk->pManTime ) { int c; if ( pNtk->AndGateDelay == 0.0 ) @@ -427,28 +427,143 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC } /**Function************************************************************* + Synopsis [Implements decomposed LUT-structure of the cut.] + Description [] + + SideEffects [] + SeeAlso [] + ***********************************************************************/ + void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, If_Obj_t * pIfObj, Vec_Int_t * vCover, Abc_Obj_t * pNodeTop ) + { + extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); + assert( !pIfMan->pPars->fUseTtPerm ); - Synopsis [Implements decomposed LUT-structure of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Abc_DecRecordToHop( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCutBest, If_Obj_t * pIfObj, Vec_Int_t * vCover ) -{ // get the truth table + word * pTruth = If_CutTruthW(pIfMan, pCutBest); + int v; + If_Obj_t * pIfLeaf; + + if ( pCutBest->nLeaves <= 6 ) + { + /* add fanins */ + If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, v ) + Abc_ObjAddFanin( pNodeTop, (Abc_Obj_t *)If_ObjCopy( pIfLeaf ) ); + + pNodeTop->Level = Abc_ObjLevelNew( pNodeTop ); + + pNodeTop->pData = Kit_TruthToHop( (Hop_Man_t *)pNtkNew->pManFunc, (unsigned *)pTruth, If_CutLeaveNum(pCutBest), vCover ); + return; + } + + // get the delay profile + unsigned delayProfile = pCutBest->acdDelay; + + // If_Obj_t * pLeaf; + // int i, leafDelay; + // int DelayMax = -1, nLeafMax = 0; + // unsigned uLeafMask = 0; + + // If_CutForEachLeaf( pIfMan, pCutBest, pLeaf, i ) + // { + // leafDelay = If_ObjCutBest(pLeaf)->Delay; + + // if ( DelayMax < leafDelay ) + // { + // DelayMax = leafDelay; + // nLeafMax = 1; + // uLeafMask = (1 << i); + // } + // else if ( DelayMax == leafDelay ) + // { + // nLeafMax++; + // uLeafMask |= (1 << i); + // } + // } + // perform LUT-decomposition and return the LUT-structure + unsigned char decompArray[92]; + int val = acd_decompose( pTruth, pCutBest->nLeaves, 6, &(delayProfile), decompArray ); + + assert( val == 0 ); + // assert( DelayMax + 2 >= pCutBest->Delay ); + // convert the LUT-structure into a set of logic nodes in Abc_Ntk_t + unsigned char bytes_check = decompArray[0]; + assert( bytes_check <= 92 ); + + int byte_p = 2; + unsigned char i, j, k, num_fanins, num_words, num_bytes; + int level, fanin; + word *tt; + Abc_Obj_t *pNewNodes[5]; + + /* create intermediate LUTs*/ + assert( decompArray[1] - 1 <= 5 ); + Abc_Obj_t * pFanin; + for ( i = 0; i < decompArray[1]; ++i ) + { + if ( i < decompArray[1] - 1 ) + { + pNewNodes[i] = Abc_NtkCreateNode( pNtkNew ); + } + else + { + pNewNodes[i] = pNodeTop; + } + num_fanins = decompArray[byte_p++]; + level = 0; + for ( j = 0; j < num_fanins; ++j ) + { + fanin = (int)decompArray[byte_p++]; + if ( fanin < If_CutLeaveNum(pCutBest) ) + { + pFanin = (Abc_Obj_t *)If_ObjCopy( If_CutLeaf(pIfMan, pCutBest, fanin) ); + } + else + { + assert( fanin - If_CutLeaveNum(pCutBest) < i ); + pFanin = pNewNodes[fanin - If_CutLeaveNum(pCutBest)]; + } + Abc_ObjAddFanin( pNewNodes[i], pFanin ); + level = Abc_MaxInt( level, Abc_ObjLevel(pFanin) ); + } + + pNewNodes[i]->Level = level + (int)(Abc_ObjFaninNum(pNewNodes[i]) > 0); + + /* extract the truth table */ + tt = pIfMan->puTempW; + num_words = ( num_fanins <= 6 ) ? 1 : ( 1 << ( num_fanins - 6 ) ); + num_bytes = ( num_fanins <= 3 ) ? 1 : ( 1 << ( Abc_MinInt( (int)num_fanins, 6 ) - 3 ) ); + for ( j = 0; j < num_words; ++j ) + { + tt[j] = 0; + for ( k = 0; k < num_bytes; ++k ) + { + tt[j] |= ( (word)(decompArray[byte_p++]) ) << ( k << 3 ); + } + } + + /* extend truth table if size < 5 */ + assert( num_fanins != 1 ); + if ( num_fanins == 2 ) + { + tt[0] |= tt[0] << 4; + } + while ( num_bytes < 4 ) + { + tt[0] |= tt[0] << ( num_bytes << 3 ); + num_bytes <<= 1; + } + + /* add node data */ + pNewNodes[i]->pData = Kit_TruthToHop( (Hop_Man_t *)pNtkNew->pManFunc, (unsigned *)tt, (int) num_fanins, vCover ); + } + + /* check correct read */ + assert( byte_p == decompArray[0] ); // this is a placeholder, which takes the truth table and converts it into an AIG without LUT-decomposition - extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); - word * pTruth = If_CutTruthW(pIfMan, pCutBest); - assert( !pIfMan->pPars->fUseTtPerm ); - return Kit_TruthToHop( (Hop_Man_t *)pMan, (unsigned *)pTruth, If_CutLeaveNum(pCutBest), vCover ); -} + } /**Function************************************************************* @@ -488,13 +603,18 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t pNodeNew = Abc_NtkCreateNode( pNtkNew ); // if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays ) if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm && - !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->fUserLutDec && !pIfMan->pPars->nGateSize ) + !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fAcd && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize ) If_CutRotatePins( pIfMan, pCutBest ); if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) { If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i ) Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); } + else if ( pIfMan->pPars->fAcd ) + { + If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) + Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover); + } else { If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) @@ -548,10 +668,10 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj ); } - else if ( pIfMan->pPars->fUserLutDec ) + else if ( pIfMan->pPars->fAcd ) { - extern Hop_Obj_t * Abc_DecRecordToHop( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vMemory ); - pNodeNew->pData = Abc_DecRecordToHop( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj, vCover ); + extern void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vMemory, Abc_Obj_t * pNodeTop ); + Abc_DecRecordToHop( pNtkNew, pIfMan, pCutBest, pIfObj, vCover, pNodeNew ); } else { diff --git a/src/map/if/if.h b/src/map/if/if.h index 93cb0f6ca..156e8679f 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -40,6 +40,7 @@ #include "opt/dau/dau.h" #include "misc/vec/vecHash.h" #include "misc/vec/vecWec.h" +#include "ACD/ac_wrapper.h" ABC_NAMESPACE_HEADER_START @@ -126,7 +127,6 @@ struct If_Par_t_ int fDsdBalance; // special delay optimization int fUserRecLib; // use recorded library int fUserSesLib; // use SAT-based synthesis - int fUserLutDec; // use LUT-based decomposition int fBidec; // use bi-decomposition int fUse34Spec; // use specialized matching int fUseBat; // use one specialized feature @@ -146,6 +146,7 @@ struct If_Par_t_ int fDeriveLuts; // enables deriving LUT structures int fDoAverage; // optimize average rather than maximum level int fHashMapping; // perform AIG hashing after mapping + int fAcd; // perform AIG hashing after mapping int fVerbose; // the verbosity flag int fVerboseTrace; // the verbosity flag char * pLutStruct; // LUT structure @@ -280,6 +281,7 @@ struct If_Man_t_ int pDumpIns[16]; Vec_Str_t * vMarks; Vec_Int_t * vVisited2; + int useLimitAdc; // timing manager Tim_Man_t * pManTim; @@ -303,6 +305,7 @@ struct If_Cut_t_ int iCutFunc; // TT ID of the cut int uMaskFunc; // polarity bitmask unsigned uSign; // cut signature + unsigned acdDelay; // Computed pin delay during ACD unsigned Cost : 12; // the user's cost of the cut (related to IF_COST_MAX) unsigned fCompl : 1; // the complemented attribute unsigned fUser : 1; // using the user's area and delay @@ -552,6 +555,7 @@ extern int If_CutPerformCheck45( If_Man_t * p, unsigned * pTruth, in extern int If_CutPerformCheck54( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck75( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern float If_CutDelayLutStruct( If_Man_t * p, If_Cut_t * pCut, char * pStr, float WireDelay ); +// extern int If_CutPerformAcd( If_Man_t * p, unsigned nVars, int lutSize, unsigned * pdelay, int use_late_arrival, unsigned * cost ); extern int If_CluCheckExt( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutRoot, char * pLut0, char * pLut1, word * pFunc0, word * pFunc1 ); extern int If_CluCheckExt3( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutLeaf2, int nLutRoot, @@ -566,6 +570,9 @@ extern int If_CutSopBalancePinDelaysInt( Vec_Int_t * vCover, int * p extern int If_CutSopBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); extern int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ); extern int If_CutLutBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); +extern int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, int best_delay ); +extern int If_AcdReEval( If_Man_t * p, If_Cut_t * pCut ); +extern float If_AcdLeafProp( If_Man_t * p, If_Cut_t * pCut, int i, float required ); /*=== ifDsd.c =============================================================*/ extern If_DsdMan_t * If_DsdManAlloc( int nVars, int nLutSize ); extern void If_DsdManAllocIsops( If_DsdMan_t * p, int nLutSize ); @@ -693,6 +700,8 @@ extern int If_ManCountSpecialPos( If_Man_t * p ); extern void If_CutTraverse( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes ); extern void If_ObjPrint( If_Obj_t * pObj ); +extern int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost ); +extern int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); ABC_NAMESPACE_HEADER_END diff --git a/src/map/if/ifCore.c b/src/map/if/ifCore.c index c03061af2..a8e482912 100644 --- a/src/map/if/ifCore.c +++ b/src/map/if/ifCore.c @@ -62,6 +62,7 @@ void If_ManSetDefaultPars( If_Par_t * pPars ) pPars->fPower = 0; pPars->fCutMin = 0; pPars->fBidec = 0; + pPars->fAcd = 0; pPars->fVerbose = 0; } @@ -106,9 +107,16 @@ int If_ManPerformMappingComb( If_Man_t * p ) If_Obj_t * pObj; abctime clkTotal = Abc_Clock(); int i; + p->useLimitAdc = 1; + //p->vVisited2 = Vec_IntAlloc( 100 ); //p->vMarks = Vec_StrStart( If_ManObjNum(p) ); + // if ( p->pPars->fAcd ) + // { + // p->pPars->nLutSize = 6; + // } + // set arrival times and fanout estimates If_ManForEachCi( p, pObj, i ) { @@ -121,6 +129,16 @@ int If_ManPerformMappingComb( If_Man_t * p ) { // map for delay If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 1, "Delay" ); + + if ( p->pPars->fAcd ) + { + // p->pPars->nLutSize = oldLutSize; + p->useLimitAdc = 0; + If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 0, "Delay" ); + p->useLimitAdc = 1; + // p->pPars->nLutSize = 6; + } + // map for delay second option p->pPars->fFancy = 1; If_ManResetOriginalRefs( p ); diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c index f4f72d1c8..8d1cccba0 100644 --- a/src/map/if/ifCut.c +++ b/src/map/if/ifCut.c @@ -604,10 +604,6 @@ static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; - if ( pC0->Delay < pC1->Delay - p->fEpsilon ) - return -1; - if ( pC0->Delay > pC1->Delay + p->fEpsilon ) - return 1; if ( pC0->fUseless < pC1->fUseless ) return -1; if ( pC0->fUseless > pC1->fUseless ) @@ -765,7 +761,7 @@ void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut ) if ( !pCut->fUseless && (p->pPars->fUseDsd || p->pPars->pFuncCell2 || p->pPars->fUseBat || - p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || + p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fAcd || p->pPars->fEnableCheck07 || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->fUseDsdTune || p->pPars->fEnableCheck75 || p->pPars->fEnableCheck75u || p->pPars->fUseCheck1 || p->pPars->fUseCheck2) ) { diff --git a/src/map/if/ifDelay.c b/src/map/if/ifDelay.c index cb25e767e..fcd53e348 100644 --- a/src/map/if/ifDelay.c +++ b/src/map/if/ifDelay.c @@ -411,6 +411,132 @@ int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ) return DelayMax + 2; } } + +int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, int best_delay ) +{ + pCut->fUser = 1; + pCut->Cost = pCut->nLeaves > 1 ? 1 : 0; + pCut->acdDelay = 0; + if ( pCut->nLeaves == 0 ) // const + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 ); + return 0; + } + if ( pCut->nLeaves == 1 ) // variable + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 ); + return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; + } + + // int LutSize = p->pPars->pLutStruct[0] - '0'; + int LutSize = 6; + int i, leaf_delay; + int DelayMax = -1, nLeafMax = 0; + unsigned uLeafMask = 0; + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + { + leaf_delay = If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; + + if ( DelayMax < leaf_delay ) + { + DelayMax = leaf_delay; + nLeafMax = 1; + uLeafMask = (1 << i); + } + else if ( DelayMax == leaf_delay ) + { + nLeafMax++; + uLeafMask |= (1 << i); + } + } + if ( If_CutLeaveNum(pCut) <= LutSize ) + { + pCut->acdDelay = ( 1 << LutSize ) - 1; + return DelayMax + 1; + } + // else if ( DelayMax + 1 >= best_delay ) + // { + // return DelayMax + 2; + // } + + /* compute the decomposition */ + int use_late_arrival = DelayMax + 2 >= best_delay; + unsigned cost = 1; + + /* TODO: have checks based on delay */ + if ( use_late_arrival && nLeafMax > LutSize / 2 ) + { + pCut->Cost = IF_COST_MAX; + return ABC_INFINITY; + } + + /* remove from critical set */ + if ( !use_late_arrival ) + uLeafMask = 0; + + + word *pTruth = If_CutTruthW( p, pCut ); + int val = acd_evaluate( pTruth, pCut->nLeaves, LutSize, &uLeafMask, &cost ); + + /* not feasible decomposition */ + pCut->acdDelay = uLeafMask; + if ( val < 0 ) + { + pCut->Cost = IF_COST_MAX; + return ABC_INFINITY; + } + + pCut->Cost = cost; + + return DelayMax + ( use_late_arrival ? 1 : 2 ); +} + +int If_AcdReEval( If_Man_t * p, If_Cut_t * pCut ) +{ + // pCut->fUser = 1; + + if ( pCut->nLeaves == 0 ) // const + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 ); + return 0; + } + if ( pCut->nLeaves == 1 ) // variable + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 ); + return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; + } + + // int LutSize = p->pPars->pLutStruct[0] - '0'; + int LutSize = 6; + int i, leaf_delay; + int DelayMax = -1, nLeafMax = 0; + unsigned uLeafMask = 0; + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + { + leaf_delay = If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; + leaf_delay += ( ( pCut->acdDelay >> i ) & 1 ) == 0 ? 2 : 1; + DelayMax = Abc_MaxInt( leaf_delay, DelayMax ); + } + + return DelayMax; +} + +float If_AcdLeafProp( If_Man_t * p, If_Cut_t * pCut, int i, float required ) +{ + if ( pCut->nLeaves == 0 ) // const + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 ); + return required; + } + if ( pCut->nLeaves == 1 ) // variable + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 ); + return 0; + } + + return ( ( pCut->acdDelay >> i ) & 1 ) == 0 ? 2 : 1; +} + /* int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ) { diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index 4a5210e92..da83b5525 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -148,32 +148,6 @@ int * If_CutArrTimeProfile( If_Man_t * p, If_Cut_t * pCut ) return p->pArrTimeProfile; } - -/**Function************************************************************* - - Synopsis [Returns the node's delay if its cut it LUT-decomposed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_CutDelayLutDec( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj ) -{ - // get the truth table - // get the cut leaves' arrival times - // run LUT-decomposition in the evaluation mode - // return expected arrival time at the output - - // this is a placeholder code, which is assume the cut has unit delay - int i, ArrTimes = 0; - for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) - ArrTimes = Abc_MaxInt( ArrTimes, (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay ); - return ArrTimes + 1; -} - /**Function************************************************************* Synopsis [Finds the best cut for the given node.] @@ -192,7 +166,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep If_Cut_t * pCut0R, * pCut1R; int fFunc0R, fFunc1R; int i, k, v, iCutDsd, fChange; - int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || + int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fAcd || p->pPars->fUseDsdTune || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->pLutStruct || p->pPars->pFuncCell2 || p->pPars->fUseCheck1 || p->pPars->fUseCheck2; int fUseAndCut = (p->pPars->nAndDelay > 0) || (p->pPars->nAndArea > 0); assert( !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 0 ); @@ -234,8 +208,10 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->fUseless = 1; } } - else if ( p->pPars->fUserLutDec ) - pCut->Delay = If_CutDelayLutDec( p, pCut, pObj ); + else if ( p->pPars->fAcd ) + { + pCut->Delay = If_AcdReEval( p, pCut ); + } else if ( p->pPars->fDelayOptLut ) pCut->Delay = If_CutLutBalanceEval( p, pCut ); else if( p->pPars->nGateSize > 0 ) @@ -292,6 +268,8 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep if ( !If_CutMergeOrdered( p, pCut0, pCut1, pCut ) ) continue; } + if ( p->pPars->fAcd && p->useLimitAdc && pCut->nLeaves > 6 ) + continue; if ( pObj->fSpec && pCut->nLeaves == (unsigned)p->pPars->nLutSize ) continue; p->nCutsMerged++; @@ -450,7 +428,12 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep else if ( p->pPars->fDsdBalance ) pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL ); else if ( p->pPars->fUserRecLib ) - pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj ); + pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj ); + else if ( p->pPars->fAcd ) + { + pCut->Delay = If_AcdEval( p, pCut, fFirst ? ABC_INFINITY : (int) If_ObjCutBest(pObj)->Delay ); + pCut->fUseless = pCut->Delay == ABC_INFINITY; + } else if ( p->pPars->fUserSesLib ) { int Cost = 0; @@ -464,8 +447,6 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->fUseless = 1; } } - else if ( p->pPars->fUserLutDec ) - pCut->Delay = If_CutDelayLutDec( p, pCut, pObj ); else if ( p->pPars->fDelayOptLut ) pCut->Delay = If_CutLutBalanceEval( p, pCut ); else if( p->pPars->nGateSize > 0 ) @@ -537,7 +518,7 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP If_Set_t * pCutSet; If_Obj_t * pTemp; If_Cut_t * pCutTemp, * pCut; - int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fUse34Spec; + int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec || p->pPars->fAcd; assert( pObj->pEquiv != NULL ); // prepare diff --git a/src/map/if/ifTime.c b/src/map/if/ifTime.c index 9ceef1475..9bce5bc43 100644 --- a/src/map/if/ifTime.c +++ b/src/map/if/ifTime.c @@ -211,6 +211,12 @@ void If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, fl pLeaf->Required = IF_MIN( pLeaf->Required, Required - pLutDelays[0] ); } } + else if ( p->pPars->fAcd ) + { + Required = ObjRequired; + If_CutForEachLeaf( p, pCut, pLeaf, i ) + pLeaf->Required = IF_MIN( pLeaf->Required, Required - If_AcdLeafProp( p, pCut, i, ObjRequired ) ); + } else { if ( pCut->fUser ) From 66cdd36d20afea221ac9af47866569a9bf038f30 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Wed, 15 Nov 2023 19:03:29 +0100 Subject: [PATCH 040/151] Runtime improvements in decomposition --- src/acd/ac_decomposition.hpp | 4 ++-- src/acd/ac_wrapper.cpp | 4 ++-- src/acd/ac_wrapper.h | 1 + src/acd/kitty_operators.hpp | 38 +++++++++++++++++++++++++++++++++++- src/map/if/if.h | 2 +- 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 4f94bcba4..59fd00ada 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -134,8 +134,8 @@ public: /* add cost if not support reducing */ uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; - /* check for feasible solution that improves the cost */ - if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost ) + /* check for feasible solution that improves the cost */ /* TODO: remove limit on cost */ + if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost && cost < 12 ) { best_tt = tt_p; permutations = perm; diff --git a/src/acd/ac_wrapper.cpp b/src/acd/ac_wrapper.cpp index b7cee0dd7..aabe8e86f 100644 --- a/src/acd/ac_wrapper.cpp +++ b/src/acd/ac_wrapper.cpp @@ -20,8 +20,8 @@ int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, ac_decomposition_stats st; ac_decomposition_impl acd( tt, nVars, ps, &st ); - acd.run( *pdelay ); - int val = acd.compute_decomposition(); + int val = acd.run( *pdelay ); + // int val = acd.compute_decomposition(); if ( val < 0 ) { diff --git a/src/acd/ac_wrapper.h b/src/acd/ac_wrapper.h index 522a60b86..cb22acf80 100644 --- a/src/acd/ac_wrapper.h +++ b/src/acd/ac_wrapper.h @@ -4,6 +4,7 @@ // #include "base/main/main.h" #include "misc/util/abc_global.h" +#include "map/if/if.h" // ABC_NAMESPACE_HEADER_START diff --git a/src/acd/kitty_operators.hpp b/src/acd/kitty_operators.hpp index cf973ebe0..68a24cf2e 100644 --- a/src/acd/kitty_operators.hpp +++ b/src/acd/kitty_operators.hpp @@ -78,7 +78,43 @@ inline void operator|=( dynamic_truth_table& first, const dynamic_truth_table& s template inline void operator|=( static_truth_table& first, const static_truth_table& second ) { - first = binary_or( first, second ); + // first = binary_or( first, second ); + /* runtime improved version */ + if constexpr ( NumVars <= 6 ) + { + first._bits |= second._bits; + first.mask_bits(); + } + else if constexpr ( NumVars == 7 ) + { + first._bits[0] |= second._bits[0]; + first._bits[1] |= second._bits[1]; + } + else if constexpr ( NumVars == 8 ) + { + first._bits[0] |= second._bits[0]; + first._bits[1] |= second._bits[1]; + first._bits[2] |= second._bits[2]; + first._bits[3] |= second._bits[3]; + } + else if constexpr ( NumVars == 9 ) + { + first._bits[0] |= second._bits[0]; + first._bits[1] |= second._bits[1]; + first._bits[2] |= second._bits[2]; + first._bits[3] |= second._bits[3]; + first._bits[4] |= second._bits[4]; + first._bits[5] |= second._bits[5]; + first._bits[6] |= second._bits[6]; + first._bits[7] |= second._bits[7]; + } + else + { + for ( uint32_t i = 0; i < first.num_blocks(); ++i ) + { + first._bits[i] |= second._bits[i]; + } + } } } // namespace kitty diff --git a/src/map/if/if.h b/src/map/if/if.h index 156e8679f..56f0bb7ed 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -40,7 +40,7 @@ #include "opt/dau/dau.h" #include "misc/vec/vecHash.h" #include "misc/vec/vecWec.h" -#include "ACD/ac_wrapper.h" +#include "acd/ac_wrapper.h" ABC_NAMESPACE_HEADER_START From c07080f818a8982d68aa428ebd81bb490c89ed02 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Wed, 15 Nov 2023 21:32:34 +0100 Subject: [PATCH 041/151] Adding heuristic set covering solver --- src/acd/ac_decomposition.hpp | 225 ++++++++++++++++++++++++++++++++--- 1 file changed, 208 insertions(+), 17 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 59fd00ada..5a93c5f35 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -84,7 +84,7 @@ private: uint64_t column{ 0 }; uint32_t cost{ 0 }; uint32_t index{ 0 }; - uint32_t sort_cost{ 0 }; + float sort_cost{ 0 }; }; private: @@ -129,6 +129,7 @@ public: uint32_t offset = std::max( static_cast( late_arriving ), 1u ); for ( uint32_t i = offset; i <= ps.lut_size / 2 && i <= 3; ++i ) { + /* TODO: add shared set */ auto evaluate_fn = [&]( STT const& tt ) { return column_multiplicity( tt, i ); }; auto [tt_p, perm, cost] = enumerate_iset_combinations_offset( i, offset, evaluate_fn, false ); @@ -179,12 +180,22 @@ public: std::vector isets = compute_isets( best_free_set ); generate_support_minimization_encodings(); - solve_min_support_exact( isets, best_free_set ); + + /* always solves exactly for power of 2 */ + if ( __builtin_popcount( best_multiplicity ) == 1 ) + solve_min_support_exact( isets, best_free_set ); + else + solve_min_support_heuristic( isets, best_free_set ); /* unfeasible decomposition */ if ( best_bound_sets.empty() ) { - return -1; + solve_min_support_exact( isets, best_free_set ); + + if ( best_bound_sets.empty() ) + { + return -1; + } } return 0; @@ -995,7 +1006,7 @@ private: } /* solve the covering problem */ - std::array solution = covering_solve_exact( matrix, 100, ps.max_iter ); + std::array solution = covering_solve_exact( matrix, 100, ps.max_iter ); /* check for failed decomposition */ if ( solution[0] == UINT32_MAX ) @@ -1047,6 +1058,72 @@ private: } } + void solve_min_support_heuristic( std::vector const& isets, uint32_t free_set_size ) + { + std::vector matrix; + matrix.reserve( support_minimization_encodings.size() ); + best_bound_sets.clear(); + + /* create covering matrix */ + if ( !create_covering_matrix( isets, matrix, free_set_size, false ) ) + { + return; + } + + /* solve the covering problem: heuristic pass + local search */ + std::array solution = covering_solve_heuristic( matrix ); + + /* check for failed decomposition */ + if ( solution[0] == UINT32_MAX ) + { + return; + } + + /* compute best bound sets */ + uint32_t num_luts = 1 + solution[4]; + uint32_t num_levels = 2; + uint32_t num_edges = free_set_size + solution[4]; + uint32_t isets_support = num_vars - free_set_size; + best_care_sets.clear(); + best_iset_onset.clear(); + best_iset_offset.clear(); + for ( uint32_t i = 0; i < solution[4]; ++i ) + { + STT tt; + STT care; + + const uint32_t onset = support_minimization_encodings[matrix[solution[i]].index][0]; + const uint32_t offset = support_minimization_encodings[matrix[solution[i]].index][1]; + for ( uint32_t j = 0; j < best_multiplicity; ++j ) + { + if ( ( ( onset >> j ) & 1 ) ) + { + tt |= isets[j]; + } + if ( ( ( offset >> j ) & 1 ) ) + { + care |= isets[j]; + } + } + + care |= tt; + num_edges += matrix[solution[i]].cost & ( ( 1 << isets_support ) - 1 ); + + best_bound_sets.push_back( tt ); + best_care_sets.push_back( care ); + best_iset_onset.push_back( onset ); + best_iset_offset.push_back( offset ); + } + + if ( pst != nullptr ) + { + pst->num_luts = num_luts; + pst->num_levels = num_levels; + pst->num_edges = num_edges; + } + } + + template bool create_covering_matrix( std::vector const& isets, std::vector& matrix, uint32_t free_set_size, bool sort ) { assert( best_multiplicity < 12 ); @@ -1119,7 +1196,15 @@ private: cost |= 1 << iset_support; } - uint32_t sort_cost = cost + ( ( combinations - __builtin_popcountl( column ) ) << num_vars ); + float sort_cost = 0; + if constexpr ( UseHeuristic ) + { + sort_cost = ( (float) cost ) / ( __builtin_popcountl( column ) ); + } + else + { + sort_cost = cost + ( ( combinations - __builtin_popcountl( column ) ) << num_vars ); + } /* insert */ matrix.emplace_back( encoding_matrix{ column, cost, i, sort_cost } ); @@ -1128,10 +1213,10 @@ private: } /* necessary condition for the existance of a solution */ - if ( __builtin_popcountl( sol_existance ) != combinations ) - { - return false; - } + // if ( __builtin_popcountl( sol_existance ) != combinations ) + // { + // return false; + // } if ( !sort ) { @@ -1154,7 +1239,7 @@ private: return true; } - template + template std::array covering_solve_exact( std::vector& matrix, uint32_t max_iter = 100, int32_t limit = 2000 ) { /* last value of res contains the size of the bound set */ @@ -1195,7 +1280,14 @@ private: /* limit */ if constexpr ( limit_iter ) { - if ( limit <= 0 || ( best_cost < UINT32_MAX && max_iter == 0 ) ) + if ( limit <= 0 ) + { + looping = false; + } + } + if constexpr ( limit_sol ) + { + if ( best_cost < UINT32_MAX && max_iter == 0 ) { looping = false; } @@ -1209,7 +1301,14 @@ private: /* limit */ if constexpr ( limit_iter ) { - if ( limit <= 0 || ( best_cost < UINT32_MAX && max_iter == 0 ) ) + if ( limit <= 0 ) + { + looping = false; + } + } + if constexpr ( limit_sol ) + { + if ( best_cost < UINT32_MAX && max_iter == 0 ) { looping = false; } @@ -1226,7 +1325,14 @@ private: /* limit */ if constexpr ( limit_iter ) { - if ( limit-- <= 0 || ( best_cost < UINT32_MAX && max_iter-- == 0 ) ) + if ( limit-- <= 0 ) + { + looping = false; + } + } + if constexpr ( limit_sol ) + { + if ( best_cost < UINT32_MAX && max_iter-- == 0 ) { looping = false; } @@ -1256,7 +1362,14 @@ private: /* limit */ if constexpr ( limit_iter ) { - if ( limit <= 0 || ( best_cost < UINT32_MAX && max_iter == 0 ) ) + if ( limit <= 0 ) + { + looping = false; + } + } + if constexpr ( limit_sol ) + { + if ( best_cost < UINT32_MAX && max_iter == 0 ) { looping = false; } @@ -1270,7 +1383,14 @@ private: /* limit */ if constexpr ( limit_iter ) { - if ( limit <= 0 || ( best_cost < UINT32_MAX && max_iter == 0 ) ) + if ( limit <= 0 ) + { + looping = false; + } + } + if constexpr ( limit_sol ) + { + if ( best_cost < UINT32_MAX && max_iter == 0 ) { looping = false; } @@ -1290,7 +1410,14 @@ private: /* limit */ if constexpr ( limit_iter ) { - if ( limit <= 0 || ( best_cost < UINT32_MAX && max_iter == 0 ) ) + if ( limit <= 0 ) + { + looping = false; + } + } + if constexpr ( limit_sol ) + { + if ( best_cost < UINT32_MAX && max_iter == 0 ) { looping = false; } @@ -1307,7 +1434,14 @@ private: /* limit */ if constexpr ( limit_iter ) { - if ( limit-- <= 0 || ( best_cost < UINT32_MAX && max_iter-- == 0 ) ) + if ( limit-- <= 0 ) + { + looping = false; + } + } + if constexpr ( limit_sol ) + { + if ( best_cost-- < UINT32_MAX && max_iter == 0 ) { looping = false; } @@ -1335,6 +1469,63 @@ private: return res; } + std::array covering_solve_heuristic( std::vector& matrix ) + { + /* last value of res contains the size of the bound set */ + std::array res = { UINT32_MAX }; + uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; + uint64_t column = 0; + + uint32_t best = 0; + float best_cost = std::numeric_limits::max(); + for ( uint32_t i = 0; i < matrix.size(); ++i ) + { + if ( matrix[i].sort_cost < best_cost ) + { + best = i; + best_cost = matrix[i].sort_cost; + } + } + + /* select */ + column = matrix[best].column; + std::swap( matrix[0], matrix[best] ); + + /* get max number of BS's */ + uint32_t iter = 1; + + while ( iter < ps.lut_size - best_free_set && __builtin_popcountl( column ) != combinations ) + { + /* select column that minimizes the cost */ + best = 0; + best_cost = std::numeric_limits::max(); + for ( uint32_t i = iter; i < matrix.size(); ++i ) + { + float local_cost = ( (float) matrix[i].cost ) / __builtin_popcountl( matrix[i].column & ~column ); + if ( local_cost < best_cost ) + { + best = i; + best_cost = local_cost; + } + } + + column |= matrix[best].column; + std::swap( matrix[iter], matrix[best] ); + ++iter; + } + + if ( __builtin_popcountl( column ) != combinations ) + { + for ( uint32_t i = 0; i < iter; ++i ) + { + res[i] = i; + } + res[4] = iter; + } + + return res; + } + void adjust_truth_table_on_dc( STT& tt, STT& care, uint32_t var_index ) { assert( var_index < tt.num_vars() ); From dcc960bebad3253226dffb7b724d5ea5c076adc5 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Wed, 15 Nov 2023 21:57:29 +0100 Subject: [PATCH 042/151] Adding local search for covering --- src/acd/ac_decomposition.hpp | 48 ++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 5a93c5f35..de409b649 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -1079,6 +1079,9 @@ private: return; } + /* improve solution with local search */ + covering_improve( matrix, solution ); + /* compute best bound sets */ uint32_t num_luts = 1 + solution[4]; uint32_t num_levels = 2; @@ -1526,6 +1529,51 @@ private: return res; } + bool covering_improve( std::vector& matrix, std::array& solution ) + { + /* performs one iteration of local search */ + uint32_t best_cost = 0, local_cost = 0; + uint32_t num_elements = solution[4]; + uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; + bool improved = false; + + /* compute current cost */ + for ( uint32_t i = 0; i < num_elements; ++i ) + { + best_cost += matrix[solution[i]].cost; + } + + uint64_t column; + for ( uint32_t i = 0; i < num_elements; ++i ) + { + /* remove element i */ + local_cost = 0; + column = 0; + for ( uint32_t j = 0; j < num_elements; ++j ) + { + if ( j == i ) + continue; + local_cost += matrix[solution[j]].cost; + column |= matrix[solution[j]].column; + } + + /* search for a better replecemnts */ + for ( uint32_t j = 0; j < matrix.size(); ++j ) + { + if ( __builtin_popcount( column | matrix[j].column ) != combinations ) + continue; + if ( local_cost + matrix[j].cost < best_cost ) + { + solution[i] = j; + best_cost = local_cost + matrix[j].cost; + improved = true; + } + } + } + + return improved; + } + void adjust_truth_table_on_dc( STT& tt, STT& care, uint32_t var_index ) { assert( var_index < tt.num_vars() ); From b32bbdfef31bdfef9790823da480bc55d693a45f Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 16 Nov 2023 15:33:19 +0100 Subject: [PATCH 043/151] Improving set covering using unitary cost --- src/acd/ac_decomposition.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index de409b649..193ef9698 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -1080,7 +1080,8 @@ private: } /* improve solution with local search */ - covering_improve( matrix, solution ); + while ( covering_improve( matrix, solution ) ) + ; /* compute best bound sets */ uint32_t num_luts = 1 + solution[4]; @@ -1202,7 +1203,7 @@ private: float sort_cost = 0; if constexpr ( UseHeuristic ) { - sort_cost = ( (float) cost ) / ( __builtin_popcountl( column ) ); + sort_cost = 1.0f / ( __builtin_popcountl( column ) ); } else { @@ -1504,7 +1505,7 @@ private: best_cost = std::numeric_limits::max(); for ( uint32_t i = iter; i < matrix.size(); ++i ) { - float local_cost = ( (float) matrix[i].cost ) / __builtin_popcountl( matrix[i].column & ~column ); + float local_cost = 1.0f / __builtin_popcountl( matrix[i].column & ~column ); if ( local_cost < best_cost ) { best = i; @@ -1517,7 +1518,7 @@ private: ++iter; } - if ( __builtin_popcountl( column ) != combinations ) + if ( __builtin_popcountl( column ) == combinations ) { for ( uint32_t i = 0; i < iter; ++i ) { From 548fd6afb2d227df4eadf1c0d8d63ac350d0e9aa Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 16 Nov 2023 18:20:05 +0100 Subject: [PATCH 044/151] New version of enumeration of combinations --- src/acd/ac_decomposition.hpp | 228 +++++++++++------------------------ 1 file changed, 68 insertions(+), 160 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 193ef9698..d59bf3d87 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -59,6 +59,9 @@ struct ac_decomposition_params /*! \brief Maximum number of iterations for covering. */ uint32_t max_iter{ 5000 }; + + /*! \brief Perform decomposition if support reducing. */ + bool support_reducing_only{ true }; }; /*! \brief Statistics for ac_decomposition */ @@ -88,7 +91,7 @@ private: }; private: - static constexpr uint32_t max_num_vars = 8; + static constexpr uint32_t max_num_vars = 9; using STT = kitty::static_truth_table; public: @@ -126,17 +129,25 @@ public: /* run ACD trying different bound sets and free sets */ uint32_t free_set_size = late_arriving; - uint32_t offset = std::max( static_cast( late_arriving ), 1u ); - for ( uint32_t i = offset; i <= ps.lut_size / 2 && i <= 3; ++i ) + uint32_t offset = static_cast( late_arriving ); + uint32_t start = std::max( offset, 1u ); + + /* perform only support reducing decomposition */ + if ( ps.support_reducing_only ) + { + start = std::max( start, num_vars - ps.lut_size ); + } + + for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= 3; ++i ) { /* TODO: add shared set */ auto evaluate_fn = [&]( STT const& tt ) { return column_multiplicity( tt, i ); }; - auto [tt_p, perm, cost] = enumerate_iset_combinations_offset( i, offset, evaluate_fn, false ); + auto [tt_p, perm, cost] = enumerate_iset_combinations_offset( i, offset, evaluate_fn ); - /* add cost if not support reducing */ + /* additional cost if not support reducing */ uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; /* check for feasible solution that improves the cost */ /* TODO: remove limit on cost */ - if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost && cost < 12 ) + if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost && cost < 10 ) { best_tt = tt_p; permutations = perm; @@ -458,8 +469,37 @@ private: return std::make_tuple( best, res_perm, best_cost ); } + inline bool combinations_offset_next( uint32_t k, uint32_t offset, uint32_t *pComb, uint32_t *pInvPerm, STT& tt ) + { + uint32_t i; + + for ( i = k - 1; pComb[i] == num_vars - k + i; --i ) + { + if ( i == offset ) + return false; + } + + /* move vars */ + uint32_t var_old = pComb[i]; + uint32_t pos_new = pInvPerm[var_old + 1]; + std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] ); + std::swap( pComb[i], pComb[pos_new] ); + kitty::swap_inplace( tt, i, pos_new ); + + for ( uint32_t j = i + 1; j < k; j++ ) + { + var_old = pComb[j]; + pos_new = pInvPerm[pComb[j - 1] + 1]; + std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] ); + std::swap( pComb[j], pComb[pos_new] ); + kitty::swap_inplace( tt, j, pos_new ); + } + + return true; + } + template - std::tuple, uint32_t> enumerate_iset_combinations_offset( uint32_t free_set_size, uint32_t offset, Fn&& fn, bool verbose = false ) + std::tuple, uint32_t> enumerate_iset_combinations_offset( uint32_t free_set_size, uint32_t offset, Fn&& fn ) { STT tt = best_tt; @@ -467,177 +507,45 @@ private: STT best_tt = tt; uint32_t best_cost = UINT32_MAX; + assert( free_set_size >= offset ); + + /* special case */ + if ( free_set_size == offset ) + { + best_cost = fn( tt ); + return { tt, permutations, best_cost }; + } + /* works up to 16 input truth tables */ assert( num_vars <= 16 ); - /* select k */ - free_set_size = std::min( free_set_size, num_vars - free_set_size ); - - /* special case */ - if ( num_vars <= free_set_size || free_set_size <= offset ) + /* init combinations */ + uint32_t pComb[16], pInvPerm[16], bestPerm[16]; + for ( uint32_t i = 0; i < num_vars; ++i ) { - if ( offset == free_set_size ) - { - best_cost = fn( tt ); - if ( verbose ) - { - kitty::print_hex( tt ); - std::cout << " " << best_cost << " "; - print_perm( permutations.begin(), free_set_size ); - } - - return { tt, permutations, best_cost }; - } - else - { - return { tt, permutations, UINT32_MAX }; - } + pComb[i] = pInvPerm[i] = i; } - /* decrease combinations */ - free_set_size -= offset; - - /* init permutation array */ - std::array perm, best_perm; - std::copy( permutations.begin(), permutations.begin() + num_vars, perm.begin() ); - best_perm = perm; - /* enumerate combinations */ - if ( free_set_size == 1 ) + do { uint32_t cost = fn( tt ); if ( cost < best_cost ) { best_tt = tt; best_cost = cost; - best_perm = perm; - } - - if ( verbose ) - { - kitty::print_hex( tt ); - std::cout << " " << cost << " "; - print_perm( perm.begin(), free_set_size + offset ); - } - - for ( uint32_t i = offset + 1; i < num_vars; ++i ) - { - std::swap( perm[offset], perm[i] ); - kitty::swap_inplace( tt, offset, i ); - - uint32_t cost = fn( tt ); - if ( cost < best_cost ) + for ( uint32_t i = 0; i < num_vars; ++i ) { - best_tt = tt; - best_cost = cost; - best_perm = perm; - } - - if ( verbose ) - { - kitty::print_hex( tt ); - std::cout << " " << cost << " "; - print_perm( perm.begin(), free_set_size + offset ); + bestPerm[i] = pComb[i]; } } - } - else if ( free_set_size == 2 ) - { - for ( uint32_t i = 0; i < num_vars - 1 - offset; ++i ) - { - uint32_t cost = fn( tt ); - if ( cost < best_cost ) - { - best_tt = tt; - best_cost = cost; - best_perm = perm; - } - - if ( verbose ) - { - kitty::print_hex( tt ); - std::cout << " " << cost << " "; - print_perm( perm.begin(), free_set_size + offset ); - } - - for ( uint32_t j = offset + 2; j < num_vars - i; ++j ) - { - std::swap( perm[offset + 1], perm[j] ); - kitty::swap_inplace( tt, offset + 1, j ); - - uint32_t cost = fn( tt ); - if ( cost < best_cost ) - { - best_tt = tt; - best_cost = cost; - best_perm = perm; - } - - if ( verbose ) - { - kitty::print_hex( tt ); - std::cout << " " << cost << " "; - print_perm( perm.begin(), free_set_size + offset ); - } - } - - std::swap( perm[offset], perm[num_vars - i - 1] ); - kitty::swap_inplace( tt, offset, num_vars - i - 1 ); - } - } - else if ( free_set_size == 3 ) - { - for ( uint32_t i = 0; i < num_vars - 2 - offset; ++i ) - { - for ( uint32_t j = i; j < num_vars - 2 - offset; ++j ) - { - uint32_t cost = fn( tt ); - if ( cost < best_cost ) - { - best_tt = tt; - best_cost = cost; - best_perm = perm; - } - - if ( verbose ) - { - kitty::print_hex( tt ); - std::cout << " " << cost << " "; - print_perm( perm.begin(), free_set_size + offset ); - } - - for ( uint32_t k = offset + 3; k < num_vars - j; ++k ) - { - std::swap( perm[offset + 2], perm[k] ); - kitty::swap_inplace( tt, offset + 2, k ); - - uint32_t cost = fn( tt ); - if ( cost < best_cost ) - { - best_tt = tt; - best_cost = cost; - best_perm = perm; - } - - if ( verbose ) - { - kitty::print_hex( tt ); - std::cout << " " << cost << " "; - print_perm( perm.begin(), free_set_size + offset ); - } - } - - std::swap( perm[offset + 1], perm[num_vars - j - 1] ); - kitty::swap_inplace( tt, offset + 1, num_vars - j - 1 ); - } - - std::swap( perm[offset], perm[num_vars - i - 1] ); - kitty::swap_inplace( tt, offset, num_vars - i - 1 ); - } - } + } while( combinations_offset_next( free_set_size, offset, pComb, pInvPerm, tt ) ); std::vector res_perm( num_vars ); - std::copy( best_perm.begin(), best_perm.begin() + num_vars, res_perm.begin() ); + for ( uint32_t i = 0; i < num_vars; ++i ) + { + res_perm[i] = permutations[bestPerm[i]]; + } return std::make_tuple( best_tt, res_perm, best_cost ); } From 8aa57c5d54bf7307c823d39fb9cc03a5e140dafb Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 16 Nov 2023 18:53:02 +0100 Subject: [PATCH 045/151] Decisions on late arrival --- src/acd/ac_decomposition.hpp | 46 +++++++++++++++++++++++++----------- src/acd/ac_wrapper.cpp | 3 ++- src/acd/ac_wrapper.h | 2 +- src/map/if/if.h | 2 +- src/map/if/ifDelay.c | 11 ++++----- 5 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index d59bf3d87..71caccff2 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -62,6 +62,9 @@ struct ac_decomposition_params /*! \brief Perform decomposition if support reducing. */ bool support_reducing_only{ true }; + + /*! \brief If decomposition with delay profile fails, ignore it. */ + bool try_no_late_arrival{ false }; }; /*! \brief Statistics for ac_decomposition */ @@ -157,28 +160,43 @@ public: } } - if ( best_multiplicity == UINT32_MAX ) + if ( best_multiplicity == UINT32_MAX && ( !ps.try_no_late_arrival || late_arriving == 0 ) ) return -1; - /* compute isets */ - // std::vector isets = compute_isets( free_set_size ); + /* try without the delay profile */ + if ( best_multiplicity == UINT32_MAX && ps.try_no_late_arrival ) + { + if ( ps.support_reducing_only ) + { + start = std::max( 1u, num_vars - ps.lut_size ); + } - // generate_support_minimization_encodings(); - // solve_min_support_exact( isets, free_set_size ); + for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= 3; ++i ) + { + /* TODO: add shared set */ + auto evaluate_fn = [&]( STT const& tt ) { return column_multiplicity( tt, i ); }; + auto [tt_p, perm, cost] = enumerate_iset_combinations_offset( i, 0, evaluate_fn ); - /* unfeasible decomposition */ - // if ( best_bound_sets.empty() ) - // { - // return -1; - // } + /* additional cost if not support reducing */ + uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; + /* check for feasible solution that improves the cost */ /* TODO: remove limit on cost */ + if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost && cost < 10 ) + { + best_tt = tt_p; + permutations = perm; + best_multiplicity = cost; + best_cost = cost + additional_cost; + free_set_size = i; + } + } + } + + if ( best_multiplicity == UINT32_MAX ) + return -1; pst->num_luts = ps.lut_size - free_set_size; best_free_set = free_set_size; - /* TODO generate decomposition only when returning the result */ - // dec_result = generate_decomposition( free_set_size ); - - /* TODO: change return value */ return 0; } diff --git a/src/acd/ac_wrapper.cpp b/src/acd/ac_wrapper.cpp index aabe8e86f..821ab3f98 100644 --- a/src/acd/ac_wrapper.cpp +++ b/src/acd/ac_wrapper.cpp @@ -4,7 +4,7 @@ // ABC_NAMESPACE_IMPL_START -int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost ) +int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ) { using namespace mockturtle; @@ -17,6 +17,7 @@ int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, ac_decomposition_params ps; ps.lut_size = lutSize; + ps.try_no_late_arrival = static_cast( try_no_late_arrival ); ac_decomposition_stats st; ac_decomposition_impl acd( tt, nVars, ps, &st ); diff --git a/src/acd/ac_wrapper.h b/src/acd/ac_wrapper.h index cb22acf80..5e0af3787 100644 --- a/src/acd/ac_wrapper.h +++ b/src/acd/ac_wrapper.h @@ -12,7 +12,7 @@ extern "C" { #endif -int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost ); +int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); #ifdef __cplusplus diff --git a/src/map/if/if.h b/src/map/if/if.h index 56f0bb7ed..05dc33949 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -700,7 +700,7 @@ extern int If_ManCountSpecialPos( If_Man_t * p ); extern void If_CutTraverse( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes ); extern void If_ObjPrint( If_Obj_t * pObj ); -extern int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost ); +extern int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); extern int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); ABC_NAMESPACE_HEADER_END diff --git a/src/map/if/ifDelay.c b/src/map/if/ifDelay.c index fcd53e348..c1ecd7c08 100644 --- a/src/map/if/ifDelay.c +++ b/src/map/if/ifDelay.c @@ -471,12 +471,13 @@ int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, int best_delay ) } /* remove from critical set */ - if ( !use_late_arrival ) + if ( !use_late_arrival && nLeafMax > LutSize / 2 ) + { uLeafMask = 0; + } - word *pTruth = If_CutTruthW( p, pCut ); - int val = acd_evaluate( pTruth, pCut->nLeaves, LutSize, &uLeafMask, &cost ); + int val = acd_evaluate( pTruth, pCut->nLeaves, LutSize, &uLeafMask, &cost, !use_late_arrival ); /* not feasible decomposition */ pCut->acdDelay = uLeafMask; @@ -507,10 +508,8 @@ int If_AcdReEval( If_Man_t * p, If_Cut_t * pCut ) } // int LutSize = p->pPars->pLutStruct[0] - '0'; - int LutSize = 6; int i, leaf_delay; - int DelayMax = -1, nLeafMax = 0; - unsigned uLeafMask = 0; + int DelayMax = -1; for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) { leaf_delay = If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; From b77bdeeb173ef7799dc7a2b406ef7f1155ae3b5a Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 16 Nov 2023 19:21:29 +0100 Subject: [PATCH 046/151] Enabling ACD for area --- src/map/if/if.h | 2 +- src/map/if/ifDelay.c | 36 +++++++++++++++++++++++++----------- src/map/if/ifMap.c | 2 +- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/map/if/if.h b/src/map/if/if.h index 05dc33949..b4d06edca 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -570,7 +570,7 @@ extern int If_CutSopBalancePinDelaysInt( Vec_Int_t * vCover, int * p extern int If_CutSopBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); extern int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ); extern int If_CutLutBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); -extern int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, int best_delay ); +extern int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay ); extern int If_AcdReEval( If_Man_t * p, If_Cut_t * pCut ); extern float If_AcdLeafProp( If_Man_t * p, If_Cut_t * pCut, int i, float required ); /*=== ifDsd.c =============================================================*/ diff --git a/src/map/if/ifDelay.c b/src/map/if/ifDelay.c index c1ecd7c08..75a0a0a66 100644 --- a/src/map/if/ifDelay.c +++ b/src/map/if/ifDelay.c @@ -412,7 +412,7 @@ int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ) } } -int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, int best_delay ) +int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay ) { pCut->fUser = 1; pCut->Cost = pCut->nLeaves > 1 ? 1 : 0; @@ -460,20 +460,34 @@ int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, int best_delay ) // } /* compute the decomposition */ - int use_late_arrival = DelayMax + 2 >= best_delay; + int use_late_arrival; unsigned cost = 1; - - /* TODO: have checks based on delay */ - if ( use_late_arrival && nLeafMax > LutSize / 2 ) + + if ( optDelay ) { - pCut->Cost = IF_COST_MAX; - return ABC_INFINITY; + /* checks based on delay: must be better than the previous best cut */ + use_late_arrival = DelayMax + 2 >= If_ObjCutBest(pObj)->Delay; } - - /* remove from critical set */ - if ( !use_late_arrival && nLeafMax > LutSize / 2 ) + else { - uLeafMask = 0; + /* checks based on delay: look at the required time */ + use_late_arrival = DelayMax + 2 > pObj->Required + p->fEpsilon; + } + + /* Too many late-arriving signals */ + if ( nLeafMax > LutSize / 2 ) + { + if ( use_late_arrival ) + { + /* unfeasible decomposition */ + pCut->Cost = IF_COST_MAX; + return ABC_INFINITY; + } + else + { + /* remove critical signals as not needed */ + uLeafMask = 0; + } } word *pTruth = If_CutTruthW( p, pCut ); diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index da83b5525..1455846f6 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -431,7 +431,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj ); else if ( p->pPars->fAcd ) { - pCut->Delay = If_AcdEval( p, pCut, fFirst ? ABC_INFINITY : (int) If_ObjCutBest(pObj)->Delay ); + pCut->Delay = If_AcdEval( p, pCut, pObj, Mode == 0 ); pCut->fUseless = pCut->Delay == ABC_INFINITY; } else if ( p->pPars->fUserSesLib ) From 1ca7a3a353dfce495a71d2f9d7abf3b3ffdddd71 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Fri, 17 Nov 2023 15:49:29 +0100 Subject: [PATCH 047/151] Remove symmetries in covering table --- src/acd/ac_decomposition.hpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 71caccff2..0faf46b91 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -150,7 +150,7 @@ public: /* additional cost if not support reducing */ uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; /* check for feasible solution that improves the cost */ /* TODO: remove limit on cost */ - if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost && cost < 10 ) + if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost && cost < 12 ) { best_tt = tt_p; permutations = perm; @@ -194,7 +194,7 @@ public: if ( best_multiplicity == UINT32_MAX ) return -1; - pst->num_luts = ps.lut_size - free_set_size; + pst->num_luts = best_multiplicity <= 2 ? 2 : best_multiplicity <= 4 ? 3 : best_multiplicity <= 8 ? 4 : 5; best_free_set = free_set_size; return 0; @@ -845,10 +845,10 @@ private: void generate_support_minimization_encodings() { uint32_t count = 0; - uint32_t num_combs_exact[4] = { 2, 6, 70, 12870 }; + uint32_t num_combs_exact[4] = { 1, 3, 35, 6435 }; /* enable don't cares only if not a power of 2 */ - uint32_t num_combs = 3; + uint32_t num_combs = 2; if ( __builtin_popcount( best_multiplicity ) == 1 ) { for ( uint32_t i = 0; i < 4; ++i ) @@ -913,6 +913,12 @@ private: generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); onset &= ~( 1 << var ); + /* remove symmetries */ + if ( var == 0 ) + { + return; + } + /* move var in OFFSET */ offset |= 1 << var; generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); @@ -1181,7 +1187,12 @@ private: assert( best_multiplicity <= 16 ); /* determine the number of needed loops*/ - if ( best_multiplicity <= 4 ) + if ( best_multiplicity <= 2 ) + { + res[4] = 1; + res[0] = 0; + } + else if ( best_multiplicity <= 4 ) { res[4] = 2; for ( uint32_t i = 0; i < matrix.size() - 1; ++i ) From 3d602e2f00fb2fa1ea06f61c6ff1e0391232d439 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Fri, 17 Nov 2023 15:55:10 +0100 Subject: [PATCH 048/151] Adding sorting of columns in heuristic covering --- src/acd/ac_decomposition.hpp | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 0faf46b91..9fb17c764 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -997,7 +997,7 @@ private: best_bound_sets.clear(); /* create covering matrix */ - if ( !create_covering_matrix( isets, matrix, free_set_size, false ) ) + if ( !create_covering_matrix( isets, matrix, free_set_size, true ) ) { return; } @@ -1148,29 +1148,24 @@ private: sol_existance |= column; } - /* necessary condition for the existance of a solution */ - // if ( __builtin_popcountl( sol_existance ) != combinations ) - // { - // return false; - // } - if ( !sort ) { return true; } - std::sort( matrix.begin(), matrix.end(), [&]( auto const& a, auto const& b ) { - return a.sort_cost < b.sort_cost; - } ); - - /* print */ - // if ( best_multiplicity < 6 ) - // { - // for ( uint32_t i = 0; i < columns.size(); ++i ) - // { - // std::cout << indexes[i] << " " << costs[i] << " \t" << columns[i] << "\n"; - // } - // } + if constexpr ( UseHeuristic ) + { + std::sort( matrix.begin(), matrix.end(), [&]( auto const& a, auto const& b ) { + return a.cost < b.cost; + } ); + return true; + } + else + { + std::sort( matrix.begin(), matrix.end(), [&]( auto const& a, auto const& b ) { + return a.sort_cost < b.sort_cost; + } ); + } return true; } From 1d7dfd25c6d346e5e0849b8084250a1596160e38 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Fri, 17 Nov 2023 16:58:17 +0100 Subject: [PATCH 049/151] Improving ACD mapping --- src/acd/ac_decomposition.hpp | 4 +++- src/acd/ac_wrapper.cpp | 3 +-- src/base/abci/abcIf.c | 26 -------------------------- src/map/if/if.h | 2 +- src/map/if/ifCore.c | 25 ++++++++++++++++++------- src/map/if/ifDelay.c | 31 +++++++++++++++---------------- src/map/if/ifMap.c | 2 +- 7 files changed, 39 insertions(+), 54 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 9fb17c764..bfcbf06e1 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -166,6 +166,7 @@ public: /* try without the delay profile */ if ( best_multiplicity == UINT32_MAX && ps.try_no_late_arrival ) { + delay_profile = 0; if ( ps.support_reducing_only ) { start = std::max( 1u, num_vars - ps.lut_size ); @@ -197,7 +198,8 @@ public: pst->num_luts = best_multiplicity <= 2 ? 2 : best_multiplicity <= 4 ? 3 : best_multiplicity <= 8 ? 4 : 5; best_free_set = free_set_size; - return 0; + /* return number of levels */ + return delay_profile == 0 ? 2 : 1; } int compute_decomposition() diff --git a/src/acd/ac_wrapper.cpp b/src/acd/ac_wrapper.cpp index 821ab3f98..6bb41ca37 100644 --- a/src/acd/ac_wrapper.cpp +++ b/src/acd/ac_wrapper.cpp @@ -22,7 +22,6 @@ int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, ac_decomposition_impl acd( tt, nVars, ps, &st ); int val = acd.run( *pdelay ); - // int val = acd.compute_decomposition(); if ( val < 0 ) { @@ -33,7 +32,7 @@ int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, *pdelay = acd.get_profile(); *cost = st.num_luts; - return 0; + return val; } int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ) diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index 079cd0066..b7d796273 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -458,34 +458,10 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC // get the delay profile unsigned delayProfile = pCutBest->acdDelay; - // If_Obj_t * pLeaf; - // int i, leafDelay; - // int DelayMax = -1, nLeafMax = 0; - // unsigned uLeafMask = 0; - - // If_CutForEachLeaf( pIfMan, pCutBest, pLeaf, i ) - // { - // leafDelay = If_ObjCutBest(pLeaf)->Delay; - - // if ( DelayMax < leafDelay ) - // { - // DelayMax = leafDelay; - // nLeafMax = 1; - // uLeafMask = (1 << i); - // } - // else if ( DelayMax == leafDelay ) - // { - // nLeafMax++; - // uLeafMask |= (1 << i); - // } - // } - // perform LUT-decomposition and return the LUT-structure unsigned char decompArray[92]; int val = acd_decompose( pTruth, pCutBest->nLeaves, 6, &(delayProfile), decompArray ); - assert( val == 0 ); - // assert( DelayMax + 2 >= pCutBest->Delay ); // convert the LUT-structure into a set of logic nodes in Abc_Ntk_t unsigned char bytes_check = decompArray[0]; @@ -561,8 +537,6 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC /* check correct read */ assert( byte_p == decompArray[0] ); - - // this is a placeholder, which takes the truth table and converts it into an AIG without LUT-decomposition } /**Function************************************************************* diff --git a/src/map/if/if.h b/src/map/if/if.h index b4d06edca..c3ba59be4 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -570,7 +570,7 @@ extern int If_CutSopBalancePinDelaysInt( Vec_Int_t * vCover, int * p extern int If_CutSopBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); extern int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ); extern int If_CutLutBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); -extern int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay ); +extern int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ); extern int If_AcdReEval( If_Man_t * p, If_Cut_t * pCut ); extern float If_AcdLeafProp( If_Man_t * p, If_Cut_t * pCut, int i, float required ); /*=== ifDsd.c =============================================================*/ diff --git a/src/map/if/ifCore.c b/src/map/if/ifCore.c index a8e482912..ad3c85179 100644 --- a/src/map/if/ifCore.c +++ b/src/map/if/ifCore.c @@ -128,16 +128,11 @@ int If_ManPerformMappingComb( If_Man_t * p ) if ( p->pPars->fPreprocess && !p->pPars->fArea ) { // map for delay - If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 1, "Delay" ); - if ( p->pPars->fAcd ) - { - // p->pPars->nLutSize = oldLutSize; p->useLimitAdc = 0; - If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 0, "Delay" ); + If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 1, "Delay" ); + if ( p->pPars->fAcd ) p->useLimitAdc = 1; - // p->pPars->nLutSize = 6; - } // map for delay second option p->pPars->fFancy = 1; @@ -160,17 +155,33 @@ int If_ManPerformMappingComb( If_Man_t * p ) // area flow oriented mapping for ( i = 0; i < p->pPars->nFlowIters; i++ ) { + // if ( p->pPars->fAcd && i == 0 ) + // { + // p->useLimitAdc = 0; + // } If_ManPerformMappingRound( p, p->pPars->nCutsMax, 1, 0, 0, "Flow" ); if ( p->pPars->fExpRed ) If_ManImproveMapping( p ); + // if ( p->pPars->fAcd && i == 0 ) + // { + // p->useLimitAdc = 1; + // } } // area oriented mapping for ( i = 0; i < p->pPars->nAreaIters; i++ ) { + // if ( p->pPars->fAcd && i == 0 ) + // { + // p->useLimitAdc = 0; + // } If_ManPerformMappingRound( p, p->pPars->nCutsMax, 2, 0, 0, "Area" ); if ( p->pPars->fExpRed ) If_ManImproveMapping( p ); + // if ( p->pPars->fAcd && i == 0 ) + // { + // p->useLimitAdc = 1; + // } } if ( p->pPars->fVerbose ) diff --git a/src/map/if/ifDelay.c b/src/map/if/ifDelay.c index 75a0a0a66..90fab6b00 100644 --- a/src/map/if/ifDelay.c +++ b/src/map/if/ifDelay.c @@ -412,7 +412,7 @@ int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ) } } -int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay ) +int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ) { pCut->fUser = 1; pCut->Cost = pCut->nLeaves > 1 ? 1 : 0; @@ -428,7 +428,6 @@ int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay ) return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; } - // int LutSize = p->pPars->pLutStruct[0] - '0'; int LutSize = 6; int i, leaf_delay; int DelayMax = -1, nLeafMax = 0; @@ -454,24 +453,23 @@ int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay ) pCut->acdDelay = ( 1 << LutSize ) - 1; return DelayMax + 1; } - // else if ( DelayMax + 1 >= best_delay ) - // { - // return DelayMax + 2; - // } /* compute the decomposition */ - int use_late_arrival; + int use_late_arrival = 0; unsigned cost = 1; - if ( optDelay ) + if ( !fFirst ) { - /* checks based on delay: must be better than the previous best cut */ - use_late_arrival = DelayMax + 2 >= If_ObjCutBest(pObj)->Delay; - } - else - { - /* checks based on delay: look at the required time */ - use_late_arrival = DelayMax + 2 > pObj->Required + p->fEpsilon; + if ( optDelay ) + { + /* checks based on delay: must be better than the previous best cut */ + use_late_arrival = DelayMax + 2 >= If_ObjCutBest(pObj)->Delay; + } + else + { + /* checks based on delay: look at the required time */ + use_late_arrival = DelayMax + 2 > pObj->Required + p->fEpsilon; + } } /* Too many late-arriving signals */ @@ -490,6 +488,7 @@ int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay ) } } + /* returns the delay of the decomposition */ word *pTruth = If_CutTruthW( p, pCut ); int val = acd_evaluate( pTruth, pCut->nLeaves, LutSize, &uLeafMask, &cost, !use_late_arrival ); @@ -503,7 +502,7 @@ int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay ) pCut->Cost = cost; - return DelayMax + ( use_late_arrival ? 1 : 2 ); + return DelayMax + val; } int If_AcdReEval( If_Man_t * p, If_Cut_t * pCut ) diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index 1455846f6..69f2ead81 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -431,7 +431,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj ); else if ( p->pPars->fAcd ) { - pCut->Delay = If_AcdEval( p, pCut, pObj, Mode == 0 ); + pCut->Delay = If_AcdEval( p, pCut, pObj, Mode == 0, fFirst ); pCut->fUseless = pCut->Delay == ABC_INFINITY; } else if ( p->pPars->fUserSesLib ) From f7a520b9571aab110781b9fdf4093da60fe16b6d Mon Sep 17 00:00:00 2001 From: aletempiac Date: Sun, 19 Nov 2023 18:51:50 +0100 Subject: [PATCH 050/151] restructuring code --- src/acd/ac_decomposition.hpp | 125 +++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 41 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index bfcbf06e1..c9b1b2453 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "kitty_constants.hpp" @@ -141,11 +142,16 @@ public: start = std::max( start, num_vars - ps.lut_size ); } + std::function column_multiplicity_fn[3] = { + [this]( STT const& tt ) { return column_multiplicity<1u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity<2u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity<3u>( tt ); } + }; + for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= 3; ++i ) { /* TODO: add shared set */ - auto evaluate_fn = [&]( STT const& tt ) { return column_multiplicity( tt, i ); }; - auto [tt_p, perm, cost] = enumerate_iset_combinations_offset( i, offset, evaluate_fn ); + auto [tt_p, perm, cost] = enumerate_iset_combinations_offset( i, offset, column_multiplicity_fn[i - 1] ); /* additional cost if not support reducing */ uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; @@ -175,8 +181,7 @@ public: for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= 3; ++i ) { /* TODO: add shared set */ - auto evaluate_fn = [&]( STT const& tt ) { return column_multiplicity( tt, i ); }; - auto [tt_p, perm, cost] = enumerate_iset_combinations_offset( i, 0, evaluate_fn ); + auto [tt_p, perm, cost] = enumerate_iset_combinations_offset( i, 0, column_multiplicity_fn[i - 1] ); /* additional cost if not support reducing */ uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; @@ -262,59 +267,33 @@ public: } private: - uint32_t column_multiplicity( STT tt, uint32_t free_set_size ) + template + uint32_t column_multiplicity( STT tt ) { uint64_t multiplicity_set[4] = { 0u, 0u, 0u, 0u }; uint32_t multiplicity = 0; uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t constexpr masks_bits[] = { 0x0, 0x3, 0xF, 0x3F }; + uint64_t constexpr masks_idx[] = { 0x0, 0x0, 0x0, 0x3 }; /* supports up to 64 values of free set (256 for |FS| == 3)*/ assert( free_set_size <= 3 ); /* extract iset functions */ - if ( free_set_size == 1 ) + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) { - auto it = std::begin( tt ); - for ( auto i = 0u; i < num_blocks; ++i ) + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) { - for ( auto j = 0; j < 32; ++j ) - { - multiplicity_set[0] |= UINT64_C( 1 ) << ( *it & 0x3 ); - *it >>= 2; - } - ++it; - } - } - else if ( free_set_size == 2 ) - { - auto it = std::begin( tt ); - for ( auto i = 0u; i < num_blocks; ++i ) - { - for ( auto j = 0; j < 16; ++j ) - { - multiplicity_set[0] |= UINT64_C( 1 ) << ( *it & 0xF ); - *it >>= 4; - } - ++it; - } - } - else /* free set size 3 */ - { - auto it = std::begin( tt ); - for ( auto i = 0u; i < num_blocks; ++i ) - { - for ( auto j = 0; j < 8; ++j ) - { - multiplicity_set[( *it >> 6 ) & 0x3] |= UINT64_C( 1 ) << ( *it & 0x3F ); - *it >>= 8; - } - ++it; + multiplicity_set[( *it >> 6 ) & masks_idx[free_set_size]] |= UINT64_C( 1 ) << ( *it & masks_bits[free_set_size] ); + *it >>= ( 1u << free_set_size ); } + ++it; } multiplicity = __builtin_popcountl( multiplicity_set[0] ); - if ( free_set_size == 3 ) + if constexpr ( free_set_size == 3 ) { multiplicity += __builtin_popcountl( multiplicity_set[1] ); multiplicity += __builtin_popcountl( multiplicity_set[2] ); @@ -324,6 +303,70 @@ private: return multiplicity; } + // uint32_t column_multiplicity2( STT tt, uint32_t free_set_size ) + // { + // uint64_t multiplicity_set[4] = { 0u, 0u, 0u, 0u }; + // uint32_t multiplicity = 0; + // uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + + // /* supports up to 64 values of free set (256 for |FS| == 3)*/ + // assert( free_set_size <= 5 ); + + // std::unordered_set column_to_iset; + + // /* extract iset functions */ + // if ( free_set_size == 1 ) + // { + // auto it = std::begin( tt ); + // for ( auto i = 0u; i < num_blocks; ++i ) + // { + // for ( auto j = 0; j < 32; ++j ) + // { + // multiplicity_set[0] |= UINT64_C( 1 ) << ( *it & 0x3 ); + // *it >>= 2; + // } + // ++it; + // } + // } + // else if ( free_set_size == 2 ) + // { + // auto it = std::begin( tt ); + // for ( auto i = 0u; i < num_blocks; ++i ) + // { + // for ( auto j = 0; j < 16; ++j ) + // { + // multiplicity_set[0] |= UINT64_C( 1 ) << ( *it & 0xF ); + // *it >>= 4; + // } + // ++it; + // } + // } + // else /* free set size 3 */ + // { + // auto it = std::begin( tt ); + // for ( auto i = 0u; i < num_blocks; ++i ) + // { + // for ( auto j = 0; j < 8; ++j ) + // { + // multiplicity_set[( *it >> 6 ) & 0x3] |= UINT64_C( 1 ) << ( *it & 0x3F ); + // *it >>= 8; + // } + // ++it; + // } + // } + + // multiplicity = __builtin_popcountl( multiplicity_set[0] ); + + // if ( free_set_size == 3 ) + // { + // multiplicity += __builtin_popcountl( multiplicity_set[1] ); + // multiplicity += __builtin_popcountl( multiplicity_set[2] ); + // multiplicity += __builtin_popcountl( multiplicity_set[3] ); + // } + + // return multiplicity; + // } + template std::tuple, uint32_t> enumerate_iset_combinations( uint32_t free_set_size, Fn&& fn, bool verbose = false ) { From 672fd1b629ede5d67484f73ca9f0f1830fd92322 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Sun, 19 Nov 2023 18:53:54 +0100 Subject: [PATCH 051/151] removing not used methods --- src/acd/ac_decomposition.hpp | 165 ----------------------------------- 1 file changed, 165 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index c9b1b2453..2714f7a8e 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -367,171 +367,6 @@ private: // return multiplicity; // } - template - std::tuple, uint32_t> enumerate_iset_combinations( uint32_t free_set_size, Fn&& fn, bool verbose = false ) - { - /* works up to 16 input truth tables */ - assert( num_vars <= 16 ); - - /* special case */ - STT tt = best_tt; - if ( num_vars <= free_set_size || free_set_size == 0 ) - { - return { tt, permutations, UINT32_MAX }; - } - - /* select k */ - // free_set_size = std::min( free_set_size, num_vars - free_set_size ); - - /* init permutation array */ - std::array perm, best_perm; - std::copy( permutations.begin(), permutations.begin() + num_vars, perm.begin() ); - best_perm = perm; - - /* TT with best cost */ - STT best = tt; - uint32_t best_cost = UINT32_MAX; - - /* enumerate combinations */ - if ( free_set_size == 1 ) - { - uint32_t cost = fn( tt ); - if ( cost < best_cost ) - { - best = tt; - best_cost = cost; - best_perm = perm; - } - - if ( verbose ) - { - kitty::print_hex( tt ); - std::cout << " " << cost << " "; - print_perm( perm.begin(), free_set_size ); - } - - for ( uint32_t i = 1; i < num_vars; ++i ) - { - std::swap( perm[0], perm[i] ); - kitty::swap_inplace( tt, 0, i ); - - uint32_t cost = fn( tt ); - if ( cost < best_cost ) - { - best = tt; - best_cost = cost; - best_perm = perm; - } - - if ( verbose ) - { - kitty::print_hex( tt ); - std::cout << " " << cost << " "; - print_perm( perm.begin(), free_set_size ); - } - } - } - else if ( free_set_size == 2 ) - { - for ( uint32_t i = 0; i < num_vars - 1; ++i ) - { - uint32_t cost = fn( tt ); - if ( cost < best_cost ) - { - best = tt; - best_cost = cost; - best_perm = perm; - } - - if ( verbose ) - { - kitty::print_hex( tt ); - std::cout << " " << cost << " "; - print_perm( perm.begin(), free_set_size ); - } - - for ( uint32_t j = 2; j < num_vars - i; ++j ) - { - std::swap( perm[1], perm[j] ); - kitty::swap_inplace( tt, 1, j ); - - uint32_t cost = fn( tt ); - if ( cost < best_cost ) - { - best = tt; - best_cost = cost; - best_perm = perm; - } - - if ( verbose ) - { - kitty::print_hex( tt ); - std::cout << " " << cost << " "; - print_perm( perm.begin(), free_set_size ); - } - } - - std::swap( perm[0], perm[num_vars - i - 1] ); - kitty::swap_inplace( tt, 0, num_vars - i - 1 ); - } - } - else if ( free_set_size == 3 ) - { - for ( uint32_t i = 0; i < num_vars - 2; ++i ) - { - for ( uint32_t j = i; j < num_vars - 2; ++j ) - { - uint32_t cost = fn( tt ); - if ( cost < best_cost ) - { - best = tt; - best_cost = cost; - best_perm = perm; - } - - if ( verbose ) - { - kitty::print_hex( tt ); - std::cout << " " << cost << " "; - print_perm( perm.begin(), free_set_size ); - } - - for ( uint32_t k = 3; k < num_vars - j; ++k ) - { - std::swap( perm[2], perm[k] ); - kitty::swap_inplace( tt, 2, k ); - - uint32_t cost = fn( tt ); - if ( cost < best_cost ) - { - best = tt; - best_cost = cost; - best_perm = perm; - } - - if ( verbose ) - { - kitty::print_hex( tt ); - std::cout << " " << cost << " "; - print_perm( perm.begin(), free_set_size ); - } - } - - std::swap( perm[1], perm[num_vars - j - 1] ); - kitty::swap_inplace( tt, 1, num_vars - j - 1 ); - } - - std::swap( perm[0], perm[num_vars - i - 1] ); - kitty::swap_inplace( tt, 0, num_vars - i - 1 ); - } - } - - std::vector res_perm( num_vars ); - std::copy( best_perm.begin(), best_perm.begin() + num_vars, res_perm.begin() ); - - return std::make_tuple( best, res_perm, best_cost ); - } - inline bool combinations_offset_next( uint32_t k, uint32_t offset, uint32_t *pComb, uint32_t *pInvPerm, STT& tt ) { uint32_t i; From 219d6d86d6dd2e6115048d5266a8da008ac57fd9 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Sun, 19 Nov 2023 19:33:19 +0100 Subject: [PATCH 052/151] Simplifying code --- src/acd/ac_decomposition.hpp | 196 ++++++++++++----------------------- 1 file changed, 65 insertions(+), 131 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 2714f7a8e..6a7a90a8d 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -88,7 +88,7 @@ class ac_decomposition_impl private: struct encoding_matrix { - uint64_t column{ 0 }; + uint64_t column; uint32_t cost{ 0 }; uint32_t index{ 0 }; float sort_cost{ 0 }; @@ -142,10 +142,12 @@ public: start = std::max( start, num_vars - ps.lut_size ); } - std::function column_multiplicity_fn[3] = { + std::function column_multiplicity_fn[5] = { [this]( STT const& tt ) { return column_multiplicity<1u>( tt ); }, [this]( STT const& tt ) { return column_multiplicity<2u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity<3u>( tt ); } + [this]( STT const& tt ) { return column_multiplicity<3u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity4<4u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } }; for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= 3; ++i ) @@ -277,7 +279,7 @@ private: uint64_t constexpr masks_idx[] = { 0x0, 0x0, 0x0, 0x3 }; /* supports up to 64 values of free set (256 for |FS| == 3)*/ - assert( free_set_size <= 3 ); + static_assert( free_set_size <= 3 ); /* extract iset functions */ auto it = std::begin( tt ); @@ -303,69 +305,55 @@ private: return multiplicity; } - // uint32_t column_multiplicity2( STT tt, uint32_t free_set_size ) - // { - // uint64_t multiplicity_set[4] = { 0u, 0u, 0u, 0u }; - // uint32_t multiplicity = 0; - // uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + template + uint32_t column_multiplicity4( STT tt ) + { + unsigned char multiplicity_set[1 << 16] = { 0 }; + uint32_t multiplicity = 0; + uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF }; - // /* supports up to 64 values of free set (256 for |FS| == 3)*/ - // assert( free_set_size <= 5 ); + static_assert( free_set_size <= 4 ); - // std::unordered_set column_to_iset; + /* extract iset functions */ + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + multiplicity += multiplicity_set[*it & masks[free_set_size]]++ == 0 ? 1 : 0; + *it >>= ( 1u << free_set_size ); + } + ++it; + } - // /* extract iset functions */ - // if ( free_set_size == 1 ) - // { - // auto it = std::begin( tt ); - // for ( auto i = 0u; i < num_blocks; ++i ) - // { - // for ( auto j = 0; j < 32; ++j ) - // { - // multiplicity_set[0] |= UINT64_C( 1 ) << ( *it & 0x3 ); - // *it >>= 2; - // } - // ++it; - // } - // } - // else if ( free_set_size == 2 ) - // { - // auto it = std::begin( tt ); - // for ( auto i = 0u; i < num_blocks; ++i ) - // { - // for ( auto j = 0; j < 16; ++j ) - // { - // multiplicity_set[0] |= UINT64_C( 1 ) << ( *it & 0xF ); - // *it >>= 4; - // } - // ++it; - // } - // } - // else /* free set size 3 */ - // { - // auto it = std::begin( tt ); - // for ( auto i = 0u; i < num_blocks; ++i ) - // { - // for ( auto j = 0; j < 8; ++j ) - // { - // multiplicity_set[( *it >> 6 ) & 0x3] |= UINT64_C( 1 ) << ( *it & 0x3F ); - // *it >>= 8; - // } - // ++it; - // } - // } + return multiplicity; + } - // multiplicity = __builtin_popcountl( multiplicity_set[0] ); + template + uint32_t column_multiplicity5( STT tt ) + { + uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; - // if ( free_set_size == 3 ) - // { - // multiplicity += __builtin_popcountl( multiplicity_set[1] ); - // multiplicity += __builtin_popcountl( multiplicity_set[2] ); - // multiplicity += __builtin_popcountl( multiplicity_set[3] ); - // } + std::unordered_set multiplicity_set; - // return multiplicity; - // } + static_assert( free_set_size <= 5 ); + + /* extract iset functions */ + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + multiplicity_set.insert( *it & masks[free_set_size] ); + *it >>= ( 1u << free_set_size ); + } + ++it; + } + + return static_cast( multiplicity_set.size() ); + } inline bool combinations_offset_next( uint32_t k, uint32_t offset, uint32_t *pComb, uint32_t *pInvPerm, STT& tt ) { @@ -459,84 +447,30 @@ private: STT tt = best_tt; uint32_t offset = 0; uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; - if ( free_set_size == 1 ) + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) { - auto it = std::begin( tt ); - for ( auto i = 0u; i < num_blocks; ++i ) + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) { - for ( auto j = 0; j < 32; ++j ) + uint64_t val = *it & masks[free_set_size]; + + if ( auto el = column_to_iset.find( val ); el != column_to_iset.end() ) { - uint64_t val = *it & 0x3; - - if ( auto el = column_to_iset.find( val ); el != column_to_iset.end() ) - { - isets[el->second]._bits[i / 2] |= UINT64_C( 1 ) << ( j + offset ); - } - else - { - isets[column_to_iset.size()]._bits[i / 2] |= UINT64_C( 1 ) << ( j + offset ); - column_to_iset[val] = column_to_iset.size(); - } - - *it >>= 2; + isets[el->second]._bits[i / ( 1u << free_set_size )] |= UINT64_C( 1 ) << ( j + offset ); + } + else + { + isets[column_to_iset.size()]._bits[i / ( 1u << free_set_size )] |= UINT64_C( 1 ) << ( j + offset ); + column_to_iset[val] = column_to_iset.size(); } - offset ^= 32; - ++it; + *it >>= ( 1u << free_set_size ); } - } - else if ( free_set_size == 2 ) - { - auto it = std::begin( tt ); - for ( auto i = 0u; i < num_blocks; ++i ) - { - for ( auto j = 0; j < 16; ++j ) - { - uint64_t val = *it & 0xF; - if ( auto el = column_to_iset.find( val ); el != column_to_iset.end() ) - { - isets[el->second]._bits[i / 4] |= UINT64_C( 1 ) << ( j + offset ); - } - else - { - isets[column_to_iset.size()]._bits[i / 4] |= UINT64_C( 1 ) << ( j + offset ); - column_to_iset[val] = column_to_iset.size(); - } - - *it >>= 4; - } - - offset = ( offset + 16 ) % 64; - ++it; - } - } - else /* free set size 3 */ - { - auto it = std::begin( tt ); - for ( auto i = 0u; i < num_blocks; ++i ) - { - for ( auto j = 0; j < 8; ++j ) - { - uint64_t val = *it & 0xFF; - - if ( auto el = column_to_iset.find( val ); el != column_to_iset.end() ) - { - isets[el->second]._bits[i / 8] |= UINT64_C( 1 ) << ( j + offset ); - } - else - { - isets[column_to_iset.size()]._bits[i / 8] |= UINT64_C( 1 ) << ( j + offset ); - column_to_iset[val] = column_to_iset.size(); - } - - *it >>= 8; - } - - offset = ( offset + 8 ) % 64; - ++it; - } + offset = ( offset + ( 64 >> free_set_size ) ) % 64; + ++it; } /* extend isets to cover the whole truth table */ From d10d450f38fa1a4e01b4343fd5afba006aea5963 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Sun, 19 Nov 2023 21:59:40 +0100 Subject: [PATCH 053/151] Final implementation --- src/acd/ac_decomposition.hpp | 77 ++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 6a7a90a8d..0a05552e2 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -58,6 +58,9 @@ struct ac_decomposition_params /*! \brief LUT size for decomposition. */ uint32_t lut_size{ 6 }; + /*! \brief Perform decomposition if support reducing. */ + uint32_t max_free_set_vars{ 4 }; + /*! \brief Maximum number of iterations for covering. */ uint32_t max_iter{ 5000 }; @@ -88,14 +91,14 @@ class ac_decomposition_impl private: struct encoding_matrix { - uint64_t column; + uint64_t column[2]; uint32_t cost{ 0 }; uint32_t index{ 0 }; float sort_cost{ 0 }; }; private: - static constexpr uint32_t max_num_vars = 9; + static constexpr uint32_t max_num_vars = 10; using STT = kitty::static_truth_table; public: @@ -118,7 +121,7 @@ public: uint32_t late_arriving = __builtin_popcount( delay_profile ); /* return a high cost if too many late arriving variables */ - if ( late_arriving > ps.lut_size / 2 || late_arriving > 3 ) + if ( late_arriving > ps.lut_size - 1 || late_arriving > ps.max_free_set_vars ) { return -1; } @@ -150,15 +153,15 @@ public: [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } }; - for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= 3; ++i ) + for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) { /* TODO: add shared set */ auto [tt_p, perm, cost] = enumerate_iset_combinations_offset( i, offset, column_multiplicity_fn[i - 1] ); /* additional cost if not support reducing */ uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; - /* check for feasible solution that improves the cost */ /* TODO: remove limit on cost */ - if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost && cost < 12 ) + /* check for feasible solution that improves the cost */ + if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost && cost <= 16 ) { best_tt = tt_p; permutations = perm; @@ -180,15 +183,15 @@ public: start = std::max( 1u, num_vars - ps.lut_size ); } - for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= 3; ++i ) + for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) { /* TODO: add shared set */ auto [tt_p, perm, cost] = enumerate_iset_combinations_offset( i, 0, column_multiplicity_fn[i - 1] ); /* additional cost if not support reducing */ uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; - /* check for feasible solution that improves the cost */ /* TODO: remove limit on cost */ - if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost && cost < 10 ) + /* check for feasible solution that improves the cost */ + if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost && cost <= 16 ) { best_tt = tt_p; permutations = perm; @@ -220,7 +223,7 @@ public: generate_support_minimization_encodings(); /* always solves exactly for power of 2 */ - if ( __builtin_popcount( best_multiplicity ) == 1 ) + if ( __builtin_popcount( best_multiplicity ) == 1 && best_multiplicity <= 8 ) solve_min_support_exact( isets, best_free_set ); else solve_min_support_heuristic( isets, best_free_set ); @@ -876,9 +879,8 @@ private: template bool create_covering_matrix( std::vector const& isets, std::vector& matrix, uint32_t free_set_size, bool sort ) { - assert( best_multiplicity < 12 ); + assert( best_multiplicity <= 16 ); uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; - uint64_t sol_existance = 0; uint32_t iset_support = num_vars - free_set_size; /* insert dichotomies */ @@ -897,7 +899,7 @@ private: } /* compute function and distinguishable seed dichotomies */ - uint64_t column = 0; + uint64_t column[2] = { 0, 0 }; STT tt; STT care; uint32_t pair_pointer = 0; @@ -921,7 +923,7 @@ private: /* if is are in diffent sets */ if ( ( ( ( onset_shift & ( offset >> k ) ) | ( ( onset >> k ) & offset_shift ) ) & 1 ) ) { - column |= UINT64_C( 1 ) << ( pair_pointer ); + column[pair_pointer >> 6u] |= UINT64_C( 1 ) << ( pair_pointer & 0x3F ); } ++pair_pointer; @@ -949,17 +951,15 @@ private: float sort_cost = 0; if constexpr ( UseHeuristic ) { - sort_cost = 1.0f / ( __builtin_popcountl( column ) ); + sort_cost = 1.0f / ( __builtin_popcountl( column[0] ) + __builtin_popcountl( column[1] ) ); } else { - sort_cost = cost + ( ( combinations - __builtin_popcountl( column ) ) << num_vars ); + sort_cost = cost + ( ( combinations - __builtin_popcountl( column[0] + __builtin_popcountl( column[1] ) ) ) << num_vars ); } /* insert */ - matrix.emplace_back( encoding_matrix{ column, cost, i, sort_cost } ); - - sol_existance |= column; + matrix.emplace_back( encoding_matrix{ { column[0], column[1] }, cost, i, sort_cost } ); } if ( !sort ) @@ -1013,7 +1013,7 @@ private: continue; /* check validity */ - if ( __builtin_popcountl( matrix[i].column | matrix[j].column ) == combinations ) + if ( __builtin_popcountl( matrix[i].column[0] | matrix[j].column[0] ) + __builtin_popcountl( matrix[i].column[1] | matrix[j].column[1] ) == combinations ) { res[0] = i; res[1] = j; @@ -1045,7 +1045,8 @@ private: for ( uint32_t j = 1; j < matrix.size() - 1 && looping; ++j ) { - uint64_t current_columns = matrix[i].column | matrix[j].column; + uint64_t current_columns0 = matrix[i].column[0] | matrix[j].column[0]; + uint64_t current_columns1 = matrix[i].column[1] | matrix[j].column[1]; uint32_t current_cost = matrix[i].cost + matrix[j].cost; /* limit */ @@ -1093,7 +1094,7 @@ private: continue; /* check validity */ - if ( __builtin_popcountl( current_columns | matrix[k].column ) == combinations ) + if ( __builtin_popcountl( current_columns0 | matrix[k].column[0] ) + __builtin_popcountl( current_columns1 | matrix[k].column[1] ) == combinations ) { res[0] = i; res[1] = j; @@ -1127,7 +1128,8 @@ private: for ( uint32_t j = 1; j < matrix.size() - 2 && looping; ++j ) { - uint64_t current_columns0 = matrix[i].column | matrix[j].column; + uint64_t current_columns0 = matrix[i].column[0] | matrix[j].column[0]; + uint64_t current_columns1 = matrix[i].column[1] | matrix[j].column[1]; uint32_t current_cost0 = matrix[i].cost + matrix[j].cost; /* limit */ @@ -1154,7 +1156,8 @@ private: for ( uint32_t k = 2; k < matrix.size() - 1 && looping; ++k ) { - uint64_t current_columns1 = current_columns0 | matrix[k].column; + uint64_t current_columns00 = current_columns0 | matrix[k].column[0]; + uint64_t current_columns11 = current_columns1 | matrix[k].column[1]; uint32_t current_cost1 = current_cost0 + matrix[k].cost; /* limit */ @@ -1202,7 +1205,7 @@ private: continue; /* check validity */ - if ( __builtin_popcountl( current_columns1 | matrix[t].column ) == combinations ) + if ( __builtin_popcountl( current_columns00 | matrix[t].column[0] ) + __builtin_popcountl( current_columns11 | matrix[t].column[1] ) == combinations ) { res[0] = i; res[1] = j; @@ -1224,7 +1227,7 @@ private: /* last value of res contains the size of the bound set */ std::array res = { UINT32_MAX }; uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; - uint64_t column = 0; + uint64_t column0 = 0, column1 = 0; uint32_t best = 0; float best_cost = std::numeric_limits::max(); @@ -1238,20 +1241,21 @@ private: } /* select */ - column = matrix[best].column; + column0 = matrix[best].column[0]; + column1 = matrix[best].column[1]; std::swap( matrix[0], matrix[best] ); /* get max number of BS's */ uint32_t iter = 1; - while ( iter < ps.lut_size - best_free_set && __builtin_popcountl( column ) != combinations ) + while ( iter < ps.lut_size - best_free_set && __builtin_popcountl( column0 ) + __builtin_popcountl( column1 ) != combinations ) { /* select column that minimizes the cost */ best = 0; best_cost = std::numeric_limits::max(); for ( uint32_t i = iter; i < matrix.size(); ++i ) { - float local_cost = 1.0f / __builtin_popcountl( matrix[i].column & ~column ); + float local_cost = 1.0f / ( __builtin_popcountl( matrix[i].column[0] & ~column0 ) + __builtin_popcountl( matrix[i].column[1] & ~column1 ) ); if ( local_cost < best_cost ) { best = i; @@ -1259,12 +1263,13 @@ private: } } - column |= matrix[best].column; + column0 |= matrix[best].column[0]; + column1 |= matrix[best].column[1]; std::swap( matrix[iter], matrix[best] ); ++iter; } - if ( __builtin_popcountl( column ) == combinations ) + if ( __builtin_popcountl( column0 ) + __builtin_popcountl( column1 ) == combinations ) { for ( uint32_t i = 0; i < iter; ++i ) { @@ -1290,24 +1295,26 @@ private: best_cost += matrix[solution[i]].cost; } - uint64_t column; + uint64_t column0, column1; for ( uint32_t i = 0; i < num_elements; ++i ) { /* remove element i */ local_cost = 0; - column = 0; + column0 = 0; + column1 = 0; for ( uint32_t j = 0; j < num_elements; ++j ) { if ( j == i ) continue; local_cost += matrix[solution[j]].cost; - column |= matrix[solution[j]].column; + column0 |= matrix[solution[j]].column[0]; + column1 |= matrix[solution[j]].column[1]; } /* search for a better replecemnts */ for ( uint32_t j = 0; j < matrix.size(); ++j ) { - if ( __builtin_popcount( column | matrix[j].column ) != combinations ) + if ( __builtin_popcount( column0 | matrix[j].column[0] ) + __builtin_popcount( column1 | matrix[j].column[1] ) != combinations ) continue; if ( local_cost + matrix[j].cost < best_cost ) { From acdd08fd9bc6792831fa67a2df9e8e1cfaf15d98 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 21 Nov 2023 11:47:56 +0100 Subject: [PATCH 054/151] Performance improvements --- src/acd/ac_decomposition.hpp | 39 ++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 0a05552e2..3112e4c20 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -59,7 +59,7 @@ struct ac_decomposition_params uint32_t lut_size{ 6 }; /*! \brief Perform decomposition if support reducing. */ - uint32_t max_free_set_vars{ 4 }; + uint32_t max_free_set_vars{ 5 }; /*! \brief Maximum number of iterations for covering. */ uint32_t max_iter{ 5000 }; @@ -67,6 +67,9 @@ struct ac_decomposition_params /*! \brief Perform decomposition if support reducing. */ bool support_reducing_only{ true }; + /*! \brief Commits the first feasible decomposition. */ + bool exit_of_feasible_decomposition{ true }; + /*! \brief If decomposition with delay profile fails, ignore it. */ bool try_no_late_arrival{ false }; }; @@ -98,7 +101,7 @@ private: }; private: - static constexpr uint32_t max_num_vars = 10; + static constexpr uint32_t max_num_vars = 8; using STT = kitty::static_truth_table; public: @@ -149,8 +152,8 @@ public: [this]( STT const& tt ) { return column_multiplicity<1u>( tt ); }, [this]( STT const& tt ) { return column_multiplicity<2u>( tt ); }, [this]( STT const& tt ) { return column_multiplicity<3u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity4<4u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } + [this]( STT const& tt ) { return column_multiplicity5<4u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } // slow, do not use }; for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) @@ -168,6 +171,11 @@ public: best_multiplicity = cost; best_cost = cost + additional_cost; free_set_size = i; + + if ( ps.exit_of_feasible_decomposition ) + { + break; + } } } @@ -198,6 +206,11 @@ public: best_multiplicity = cost; best_cost = cost + additional_cost; free_set_size = i; + + if ( ps.exit_of_feasible_decomposition ) + { + break; + } } } } @@ -339,9 +352,10 @@ private: uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; - std::unordered_set multiplicity_set; + static_assert( free_set_size == 5 || free_set_size == 4 ); - static_assert( free_set_size <= 5 ); + uint32_t size = 0; + std::array multiplicity_set; /* extract iset functions */ auto it = std::begin( tt ); @@ -349,13 +363,22 @@ private: { for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) { - multiplicity_set.insert( *it & masks[free_set_size] ); + multiplicity_set[size++] = static_cast( *it & masks[free_set_size] ); *it >>= ( 1u << free_set_size ); } ++it; } - return static_cast( multiplicity_set.size() ); + std::sort( multiplicity_set.begin(), multiplicity_set.begin() + size ); + + /* count unique */ + uint32_t multiplicity = 1; + for ( auto i = 1u; i < size; ++i ) + { + multiplicity += multiplicity_set[i] != multiplicity_set[i - 1] ? 1 : 0; + } + + return multiplicity; } inline bool combinations_offset_next( uint32_t k, uint32_t offset, uint32_t *pComb, uint32_t *pInvPerm, STT& tt ) From a31684734192df82d5a135e2e0d263e83dfdf54e Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Thu, 23 Nov 2023 19:33:05 +0800 Subject: [PATCH 055/151] correct fanout count --- src/aig/gia/giaDup.c | 36 +++++++++++++++++-------- src/proof/cec/cecSatG2.c | 57 +++++++++++++++++++++++++++++++++------- 2 files changed, 73 insertions(+), 20 deletions(-) diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 24c1d3b0e..9d9b56a1c 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -5703,8 +5703,9 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, pObj->Value = Gia_ManCi(p2, i)->Value = Gia_ManAppendCi( pNew ); // TODO: record the corresponding impl node of each lit - vLitBmiter = Vec_IntAlloc( Gia_ManObjNum(p2) ); - Vec_IntFill( vLitBmiter, Gia_ManObjNum(p2) + Gia_ManObjNum(p1), 0 ); + vLitBmiter = Vec_IntAlloc( (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)) * 2 ); + Vec_IntFill( vLitBmiter, (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)) * 2, 0 ); + printf( "allocated size: %d\n", Vec_IntSize(vLitBmiter) ); Gia_ManForEachAnd( p2, pObj, i ) { @@ -5776,7 +5777,7 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, Gia_ManStaticFanoutStop( p1 ); - printf( "category %d %d %d\n", c1, c2, Gia_ManObjNum(p1) ); + printf( "spec: fanin: %d / fanout: %d / total %d\n", c1, c2, Gia_ManObjNum(p1) ); // TODO: record hashed equivalent nodes @@ -5798,17 +5799,30 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, Vec_IntPush( vLits, pObj->Value ); } - // int e; - // Vec_IntForEachEntry( vLitBmiter, e, i ) - // { - // printf( "%d ", e ); - // } - // printf("\n"); + + int e, c3=0, c4=0, c5=0; + c1 = 0; c2 = 0; + + Vec_IntForEachEntry( vLitBmiter, e, i ) + { + if ( i%2 ) continue; + switch (e) + { + case 1: c1++; break; + case 2: c2++; break; + case 3: c3++; break; + case 4: c4++; break; + case 5: c5++; break; + default: + break; + } + } + printf("(strash) impl: eq_fanin: %d / eq_fanout: %d / total: %d\n", c4, c5, c3+c4+c5); Gia_ManForEachCo( p2, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); - //Gia_ManForEachCo( p1, pObj, i ) - // Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachCo( p1, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Vec_IntForEachEntry( vLits, iLit, i ) Gia_ManAppendCo( pNew, iLit ); Vec_IntFree( vLits ); diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 424369b8c..4a39e95d3 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -1882,8 +1882,46 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p if ( pRepr == NULL ) continue; } + int lit_obj = Gia_ObjId( p, pObj ) << 1; + int lit_repr = Gia_ObjId( p, pRepr ) << 1; + if ( Abc_Lit2Var(pObj->Value) == Abc_Lit2Var(pRepr->Value) ) { + // printf( "*node %d (%d) merged into node %d (%d)\n", lit_obj >> 1, Vec_IntEntry( vLitBmiter, lit_obj ), lit_repr >> 1, Vec_IntEntry( vLitBmiter, lit_repr) ); + if ( Vec_IntEntry( vLitBmiter, lit_repr ) == 3 ) + { + switch ( Vec_IntEntry( vLitBmiter, lit_obj ) ) + { + case 1: + case 4: + Vec_IntUpdateEntry( vLitBmiter, lit_repr, 4 ); + break; + case 2: + case 5: + Vec_IntUpdateEntry( vLitBmiter, lit_repr, 5 ); + break; + default: + break; + } + } + else + { + if ( Vec_IntEntry(vLitBmiter, lit_obj ) == 3 ) + switch ( Vec_IntEntry( vLitBmiter, lit_repr ) ) + { + case 1: + case 4: + Vec_IntUpdateEntry( vLitBmiter, lit_obj, 4 ); + break; + case 2: + case 5: + Vec_IntUpdateEntry( vLitBmiter, lit_obj, 5 ); + break; + default: + break; + + } + } assert( (pObj->Value ^ pRepr->Value) == (pObj->fPhase ^ pRepr->fPhase) ); Gia_ObjSetProved( p, i ); if ( Gia_ObjId(p, pRepr) == 0 ) @@ -1893,17 +1931,18 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p if ( Cec4_ManSweepNode(pMan, i, Gia_ObjId(p, pRepr)) && Gia_ObjProved(p, i) ) { if (pPars->fBMiterInfo){ - if ( Vec_IntEntry( vLitBmiter, pRepr->Value ) == 3 ) + // printf( "node %d (%d) merged into node %d (%d)\n", lit_obj, Vec_IntEntry( vLitBmiter, lit_obj ), lit_repr, Vec_IntEntry( vLitBmiter, lit_repr ) ); + if ( Vec_IntEntry( vLitBmiter, lit_repr ) == 3 ) { - switch ( Vec_IntEntry( vLitBmiter, pObj -> Value ) ) + switch ( Vec_IntEntry( vLitBmiter, lit_obj ) ) { case 1: case 4: - Vec_IntUpdateEntry( vLitBmiter, pRepr->Value, 4 ); + Vec_IntUpdateEntry( vLitBmiter, lit_repr, 4 ); break; case 2: case 5: - Vec_IntUpdateEntry( vLitBmiter, pRepr->Value, 5 ); + Vec_IntUpdateEntry( vLitBmiter, lit_repr, 5 ); break; default: break; @@ -1911,16 +1950,16 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p } else { - if ( Vec_IntEntry(vLitBmiter, pObj->Value ) == 3 ) - switch ( Vec_IntEntry( vLitBmiter, pRepr -> Value ) ) + if ( Vec_IntEntry(vLitBmiter, lit_obj ) == 3 ) + switch ( Vec_IntEntry( vLitBmiter, lit_repr ) ) { case 1: case 4: - Vec_IntUpdateEntry( vLitBmiter, pObj->Value, 4 ); + Vec_IntUpdateEntry( vLitBmiter, lit_obj, 4 ); break; case 2: case 5: - Vec_IntUpdateEntry( vLitBmiter, pObj->Value, 5 ); + Vec_IntUpdateEntry( vLitBmiter, lit_obj, 5 ); break; default: break; @@ -1998,7 +2037,7 @@ Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ) break; } } - printf("category %d %d %d %d %d\n", c1, c2, c3+c4+c5, c4, c5); + printf("(fraig) impl: eq_fanin: %d / eq_fanout: %d / total: %d\n", c4, c5, c3+c4+c5); } return pNew; } From 43f4dccb4f1c6a8ad7d591d5bf511ab7e94bec92 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 23 Nov 2023 16:29:33 +0100 Subject: [PATCH 056/151] run time improvements in computing the column multiplicity --- src/acd/ac_decomposition.hpp | 41 ++++++++++-------------------------- 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 3112e4c20..0b6101e53 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -101,7 +101,7 @@ private: }; private: - static constexpr uint32_t max_num_vars = 8; + static constexpr uint32_t max_num_vars = 10; using STT = kitty::static_truth_table; public: @@ -153,7 +153,7 @@ public: [this]( STT const& tt ) { return column_multiplicity<2u>( tt ); }, [this]( STT const& tt ) { return column_multiplicity<3u>( tt ); }, [this]( STT const& tt ) { return column_multiplicity5<4u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } // slow, do not use + [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } }; for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) @@ -290,7 +290,7 @@ private: { uint64_t multiplicity_set[4] = { 0u, 0u, 0u, 0u }; uint32_t multiplicity = 0; - uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; uint64_t constexpr masks_bits[] = { 0x0, 0x3, 0xF, 0x3F }; uint64_t constexpr masks_idx[] = { 0x0, 0x0, 0x0, 0x3 }; @@ -321,40 +321,16 @@ private: return multiplicity; } - template - uint32_t column_multiplicity4( STT tt ) - { - unsigned char multiplicity_set[1 << 16] = { 0 }; - uint32_t multiplicity = 0; - uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; - uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF }; - - static_assert( free_set_size <= 4 ); - - /* extract iset functions */ - auto it = std::begin( tt ); - for ( auto i = 0u; i < num_blocks; ++i ) - { - for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) - { - multiplicity += multiplicity_set[*it & masks[free_set_size]]++ == 0 ? 1 : 0; - *it >>= ( 1u << free_set_size ); - } - ++it; - } - - return multiplicity; - } - template uint32_t column_multiplicity5( STT tt ) { - uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; static_assert( free_set_size == 5 || free_set_size == 4 ); uint32_t size = 0; + uint64_t prev = -1; std::array multiplicity_set; /* extract iset functions */ @@ -363,7 +339,12 @@ private: { for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) { - multiplicity_set[size++] = static_cast( *it & masks[free_set_size] ); + uint32_t fs_fn = static_cast( *it & masks[free_set_size] ); + if ( fs_fn != prev ) + { + multiplicity_set[size++] = fs_fn; + prev = fs_fn; + } *it >>= ( 1u << free_set_size ); } ++it; From 23cfcc1e1f5e7d4b5624a4c29d41e7479cc54ecc Mon Sep 17 00:00:00 2001 From: aletempiac Date: Fri, 24 Nov 2023 12:18:49 +0100 Subject: [PATCH 057/151] Improving efficiency and removing useless code --- src/acd/ac_decomposition.hpp | 521 ++++++++++++----------------------- src/acd/ac_wrapper.cpp | 27 +- src/acd/ac_wrapper.h | 7 +- 3 files changed, 175 insertions(+), 380 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 0b6101e53..d63d6685d 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -61,14 +61,11 @@ struct ac_decomposition_params /*! \brief Perform decomposition if support reducing. */ uint32_t max_free_set_vars{ 5 }; - /*! \brief Maximum number of iterations for covering. */ - uint32_t max_iter{ 5000 }; - /*! \brief Perform decomposition if support reducing. */ bool support_reducing_only{ true }; /*! \brief Commits the first feasible decomposition. */ - bool exit_of_feasible_decomposition{ true }; + bool exit_on_feasible_decomposition{ true }; /*! \brief If decomposition with delay profile fails, ignore it. */ bool try_no_late_arrival{ false }; @@ -88,16 +85,15 @@ struct ac_decomposition_result std::vector support; }; -template class ac_decomposition_impl { private: - struct encoding_matrix + struct encoding_column { uint64_t column[2]; - uint32_t cost{ 0 }; - uint32_t index{ 0 }; - float sort_cost{ 0 }; + uint32_t cost; + uint32_t index; + float sort_cost; }; private: @@ -105,15 +101,14 @@ private: using STT = kitty::static_truth_table; public: - explicit ac_decomposition_impl( TT const& tt, uint32_t num_vars, ac_decomposition_params const& ps, ac_decomposition_stats* pst = nullptr ) - : num_vars( num_vars ), ps( ps ), pst( pst ), permutations( num_vars ) + explicit ac_decomposition_impl( uint32_t num_vars, ac_decomposition_params const& ps, ac_decomposition_stats* pst = nullptr ) + : num_vars( num_vars ), ps( ps ), pst( pst ) { - tt_start = tt; std::iota( permutations.begin(), permutations.end(), 0 ); } /*! \brief Runs ACD using late arriving variables */ - int run( unsigned delay_profile ) + int run( word *tt, unsigned delay_profile ) { /* truth table is too large for the settings */ if ( num_vars > max_num_vars ) @@ -130,97 +125,17 @@ public: } /* convert to static TT */ - best_tt = kitty::extend_to( tt_start ); - best_multiplicity = UINT32_MAX; - uint32_t best_cost = UINT32_MAX; + init_truth_table( tt ); /* permute late arriving variables to be the least significant */ reposition_late_arriving_variables( delay_profile, late_arriving ); /* run ACD trying different bound sets and free sets */ - uint32_t free_set_size = late_arriving; - uint32_t offset = static_cast( late_arriving ); - uint32_t start = std::max( offset, 1u ); - - /* perform only support reducing decomposition */ - if ( ps.support_reducing_only ) + if ( !find_decomposition( delay_profile, late_arriving ) ) { - start = std::max( start, num_vars - ps.lut_size ); - } - - std::function column_multiplicity_fn[5] = { - [this]( STT const& tt ) { return column_multiplicity<1u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity<2u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity<3u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity5<4u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } - }; - - for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) - { - /* TODO: add shared set */ - auto [tt_p, perm, cost] = enumerate_iset_combinations_offset( i, offset, column_multiplicity_fn[i - 1] ); - - /* additional cost if not support reducing */ - uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; - /* check for feasible solution that improves the cost */ - if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost && cost <= 16 ) - { - best_tt = tt_p; - permutations = perm; - best_multiplicity = cost; - best_cost = cost + additional_cost; - free_set_size = i; - - if ( ps.exit_of_feasible_decomposition ) - { - break; - } - } - } - - if ( best_multiplicity == UINT32_MAX && ( !ps.try_no_late_arrival || late_arriving == 0 ) ) return -1; - - /* try without the delay profile */ - if ( best_multiplicity == UINT32_MAX && ps.try_no_late_arrival ) - { - delay_profile = 0; - if ( ps.support_reducing_only ) - { - start = std::max( 1u, num_vars - ps.lut_size ); - } - - for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) - { - /* TODO: add shared set */ - auto [tt_p, perm, cost] = enumerate_iset_combinations_offset( i, 0, column_multiplicity_fn[i - 1] ); - - /* additional cost if not support reducing */ - uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; - /* check for feasible solution that improves the cost */ - if ( cost <= ( 1 << ( ps.lut_size - i ) ) && cost + additional_cost < best_cost && cost <= 16 ) - { - best_tt = tt_p; - permutations = perm; - best_multiplicity = cost; - best_cost = cost + additional_cost; - free_set_size = i; - - if ( ps.exit_of_feasible_decomposition ) - { - break; - } - } - } } - if ( best_multiplicity == UINT32_MAX ) - return -1; - - pst->num_luts = best_multiplicity <= 2 ? 2 : best_multiplicity <= 4 ? 3 : best_multiplicity <= 8 ? 4 : 5; - best_free_set = free_set_size; - /* return number of levels */ return delay_profile == 0 ? 2 : 1; } @@ -231,26 +146,18 @@ public: return -1; /* compute isets */ - std::vector isets = compute_isets( best_free_set ); + std::vector isets = compute_isets(); generate_support_minimization_encodings(); - /* always solves exactly for power of 2 */ - if ( __builtin_popcount( best_multiplicity ) == 1 && best_multiplicity <= 8 ) - solve_min_support_exact( isets, best_free_set ); + /* solves exactly only for small multiplicities */ + if ( best_multiplicity <= 4u ) + solve_min_support_exact( isets ); else - solve_min_support_heuristic( isets, best_free_set ); + solve_min_support_heuristic( isets ); /* unfeasible decomposition */ - if ( best_bound_sets.empty() ) - { - solve_min_support_exact( isets, best_free_set ); - - if ( best_bound_sets.empty() ) - { - return -1; - } - } + assert( !best_bound_sets.empty() ); return 0; } @@ -285,6 +192,110 @@ public: } private: + bool find_decomposition( unsigned& delay_profile, uint32_t late_arriving ) + { + best_multiplicity = UINT32_MAX; + best_free_set = UINT32_MAX; + uint32_t best_cost = UINT32_MAX; + uint32_t offset = static_cast( late_arriving ); + uint32_t start = std::max( offset, 1u ); + + /* perform only support reducing decomposition */ + if ( ps.support_reducing_only ) + { + start = std::max( start, num_vars - ps.lut_size ); + } + + /* array of functions to compute the column multiplicity */ + std::function column_multiplicity_fn[5] = { + [this]( STT const& tt ) { return column_multiplicity<1u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity<2u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity<3u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity5<4u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } + }; + + /* find a feasible AC decomposition */ + for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) + { + auto [tt_p, perm, multiplicity] = enumerate_iset_combinations_offset( i, offset, column_multiplicity_fn[i - 1] ); + + /* additional cost if not support reducing */ + uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; + + /* check for feasible solution that improves the cost */ + if ( multiplicity <= ( 1 << ( ps.lut_size - i ) ) && multiplicity + additional_cost < best_cost && multiplicity <= 16 ) + { + best_tt = tt_p; + permutations = perm; + best_multiplicity = multiplicity; + best_cost = multiplicity + additional_cost; + best_free_set = i; + + if ( ps.exit_on_feasible_decomposition ) + { + break; + } + } + } + + if ( best_multiplicity == UINT32_MAX && ( !ps.try_no_late_arrival || late_arriving == 0 ) ) + return false; + + /* try without the delay profile */ + if ( best_multiplicity == UINT32_MAX && ps.try_no_late_arrival ) + { + delay_profile = 0; + if ( ps.support_reducing_only ) + { + start = std::max( 1u, num_vars - ps.lut_size ); + } + + for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) + { + auto [tt_p, perm, multiplicity] = enumerate_iset_combinations_offset( i, 0, column_multiplicity_fn[i - 1] ); + + /* additional cost if not support reducing */ + uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; + + /* check for feasible solution that improves the cost */ + if ( multiplicity <= ( 1 << ( ps.lut_size - i ) ) && multiplicity + additional_cost < best_cost && multiplicity <= 16 ) + { + best_tt = tt_p; + permutations = perm; + best_multiplicity = multiplicity; + best_cost = multiplicity + additional_cost; + best_free_set = i; + + if ( ps.exit_on_feasible_decomposition ) + { + break; + } + } + } + } + + if ( best_multiplicity == UINT32_MAX ) + return false; + + /* estimation on number of LUTs */ + pst->num_luts = best_multiplicity <= 2 ? 2 : best_multiplicity <= 4 ? 3 : best_multiplicity <= 8 ? 4 : 5; + + return true; + } + + void init_truth_table( word *tt_start ) + { + uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) ); + + for ( uint32_t i = 0; i < num_blocks; ++i ) + { + best_tt._bits[i] = tt_start[i]; + } + + local_extend_to( best_tt, num_vars ); + } + template uint32_t column_multiplicity( STT tt ) { @@ -392,7 +403,7 @@ private: } template - std::tuple, uint32_t> enumerate_iset_combinations_offset( uint32_t free_set_size, uint32_t offset, Fn&& fn ) + std::tuple, uint32_t> enumerate_iset_combinations_offset( uint32_t free_set_size, uint32_t offset, Fn&& fn ) { STT tt = best_tt; @@ -434,7 +445,7 @@ private: } } while( combinations_offset_next( free_set_size, offset, pComb, pInvPerm, tt ) ); - std::vector res_perm( num_vars ); + std::array res_perm; for ( uint32_t i = 0; i < num_vars; ++i ) { res_perm[i] = permutations[bestPerm[i]]; @@ -443,10 +454,10 @@ private: return std::make_tuple( best_tt, res_perm, best_cost ); } - std::vector compute_isets( uint32_t free_set_size, bool verbose = false ) + std::vector compute_isets( bool verbose = false ) { /* construct isets involved in multiplicity */ - uint32_t isets_support = num_vars - free_set_size; + uint32_t isets_support = num_vars - best_free_set; std::vector isets( best_multiplicity ); /* construct isets */ @@ -459,24 +470,24 @@ private: auto it = std::begin( tt ); for ( auto i = 0u; i < num_blocks; ++i ) { - for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) { - uint64_t val = *it & masks[free_set_size]; + uint64_t val = *it & masks[best_free_set]; if ( auto el = column_to_iset.find( val ); el != column_to_iset.end() ) { - isets[el->second]._bits[i / ( 1u << free_set_size )] |= UINT64_C( 1 ) << ( j + offset ); + isets[el->second]._bits[i / ( 1u << best_free_set )] |= UINT64_C( 1 ) << ( j + offset ); } else { - isets[column_to_iset.size()]._bits[i / ( 1u << free_set_size )] |= UINT64_C( 1 ) << ( j + offset ); + isets[column_to_iset.size()]._bits[i / ( 1u << best_free_set )] |= UINT64_C( 1 ) << ( j + offset ); column_to_iset[val] = column_to_iset.size(); } - *it >>= ( 1u << free_set_size ); + *it >>= ( 1u << best_free_set ); } - offset = ( offset + ( 64 >> free_set_size ) ) % 64; + offset = ( offset + ( 64 >> best_free_set ) ) % 64; ++it; } @@ -489,11 +500,10 @@ private: /* save free_set functions */ std::vector free_set_tts( best_multiplicity ); - /* TODO: possible conflict */ for ( auto const& pair : column_to_iset ) { free_set_tts[pair.second]._bits[0] = pair.first; - local_extend_to( free_set_tts[pair.second], free_set_size ); + local_extend_to( free_set_tts[pair.second], best_free_set ); } /* print isets and free set*/ @@ -666,12 +676,12 @@ private: void generate_support_minimization_encodings() { uint32_t count = 0; - uint32_t num_combs_exact[4] = { 1, 3, 35, 6435 }; /* enable don't cares only if not a power of 2 */ uint32_t num_combs = 2; if ( __builtin_popcount( best_multiplicity ) == 1 ) { + uint32_t num_combs_exact[4] = { 1, 3, 35, 6435 }; for ( uint32_t i = 0; i < 4; ++i ) { if ( ( best_multiplicity >> i ) == 2u ) @@ -684,6 +694,7 @@ private: } else { + /* combinations are 2*3^(mu - 1) */ for ( uint32_t i = 1; i < best_multiplicity; ++i ) { num_combs = ( num_combs << 1 ) + num_combs; @@ -704,14 +715,14 @@ private: } template - void generate_support_minimization_encodings_rec( uint64_t onset, uint64_t offset, uint32_t var, uint32_t& count ) + void generate_support_minimization_encodings_rec( uint32_t onset, uint32_t offset, uint32_t var, uint32_t& count ) { if ( var == best_multiplicity ) { if constexpr ( !enable_dcset ) { /* sets must be equally populated */ - if ( __builtin_popcountl( onset ) != __builtin_popcountl( offset ) ) + if ( __builtin_popcount( onset ) != __builtin_popcount( offset ) ) { return; } @@ -723,7 +734,7 @@ private: return; } - /* move var in DCSET */ + /* var in DCSET */ if constexpr ( enable_dcset ) { generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); @@ -746,20 +757,20 @@ private: offset &= ~( 1 << var ); } - void solve_min_support_exact( std::vector const& isets, uint32_t free_set_size ) + void solve_min_support_exact( std::vector const& isets ) { - std::vector matrix; + std::vector matrix; matrix.reserve( support_minimization_encodings.size() ); best_bound_sets.clear(); /* create covering matrix */ - if ( !create_covering_matrix( isets, matrix, free_set_size, best_multiplicity > 4 ) ) + if ( !create_covering_matrix( isets, matrix, false ) ) { return; } /* solve the covering problem */ - std::array solution = covering_solve_exact( matrix, 100, ps.max_iter ); + std::array solution = covering_solve_exact( matrix ); /* check for failed decomposition */ if ( solution[0] == UINT32_MAX ) @@ -770,8 +781,8 @@ private: /* compute best bound sets */ uint32_t num_luts = 1 + solution[4]; uint32_t num_levels = 2; - uint32_t num_edges = free_set_size + solution[4]; - uint32_t isets_support = num_vars - free_set_size; + uint32_t num_edges = best_free_set + solution[4]; + uint32_t isets_support = num_vars - best_free_set; best_care_sets.clear(); best_iset_onset.clear(); best_iset_offset.clear(); @@ -811,14 +822,14 @@ private: } } - void solve_min_support_heuristic( std::vector const& isets, uint32_t free_set_size ) + void solve_min_support_heuristic( std::vector const& isets ) { - std::vector matrix; + std::vector matrix; matrix.reserve( support_minimization_encodings.size() ); best_bound_sets.clear(); /* create covering matrix */ - if ( !create_covering_matrix( isets, matrix, free_set_size, true ) ) + if ( !create_covering_matrix( isets, matrix, true ) ) { return; } @@ -839,8 +850,8 @@ private: /* compute best bound sets */ uint32_t num_luts = 1 + solution[4]; uint32_t num_levels = 2; - uint32_t num_edges = free_set_size + solution[4]; - uint32_t isets_support = num_vars - free_set_size; + uint32_t num_edges = best_free_set + solution[4]; + uint32_t isets_support = num_vars - best_free_set; best_care_sets.clear(); best_iset_onset.clear(); best_iset_offset.clear(); @@ -880,12 +891,12 @@ private: } } - template - bool create_covering_matrix( std::vector const& isets, std::vector& matrix, uint32_t free_set_size, bool sort ) + template + bool create_covering_matrix( std::vector const& isets, std::vector& matrix, bool sort ) { assert( best_multiplicity <= 16 ); uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; - uint32_t iset_support = num_vars - free_set_size; + uint32_t iset_support = num_vars - best_free_set; /* insert dichotomies */ for ( uint32_t i = 0; i < support_minimization_encodings.size(); ++i ) @@ -924,7 +935,7 @@ private: /* compute included seed dichotomies */ for ( uint32_t k = j + 1; k < best_multiplicity; ++k ) { - /* if is are in diffent sets */ + /* if are in diffent sets */ if ( ( ( ( onset_shift & ( offset >> k ) ) | ( ( onset >> k ) & offset_shift ) ) & 1 ) ) { column[pair_pointer >> 6u] |= UINT64_C( 1 ) << ( pair_pointer & 0x3F ); @@ -947,11 +958,6 @@ private: if ( cost > ps.lut_size ) continue; - if ( cost > 1 ) - { - cost |= 1 << iset_support; - } - float sort_cost = 0; if constexpr ( UseHeuristic ) { @@ -963,7 +969,7 @@ private: } /* insert */ - matrix.emplace_back( encoding_matrix{ { column[0], column[1] }, cost, i, sort_cost } ); + matrix.emplace_back( encoding_column{ { column[0], column[1] }, cost, i, sort_cost } ); } if ( !sort ) @@ -976,7 +982,6 @@ private: std::sort( matrix.begin(), matrix.end(), [&]( auto const& a, auto const& b ) { return a.cost < b.cost; } ); - return true; } else { @@ -988,16 +993,14 @@ private: return true; } - template - std::array covering_solve_exact( std::vector& matrix, uint32_t max_iter = 100, int32_t limit = 2000 ) + std::array covering_solve_exact( std::vector& matrix ) { /* last value of res contains the size of the bound set */ std::array res = { UINT32_MAX }; uint32_t best_cost = UINT32_MAX; uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; - bool looping = true; - assert( best_multiplicity <= 16 ); + assert( best_multiplicity <= 4 ); /* determine the number of needed loops*/ if ( best_multiplicity <= 2 ) @@ -1026,207 +1029,11 @@ private: } } } - else if ( best_multiplicity <= 8 ) - { - res[4] = 3; - for ( uint32_t i = 0; i < matrix.size() - 2 && looping; ++i ) - { - /* limit */ - if constexpr ( limit_iter ) - { - if ( limit <= 0 ) - { - looping = false; - } - } - if constexpr ( limit_sol ) - { - if ( best_cost < UINT32_MAX && max_iter == 0 ) - { - looping = false; - } - } - - for ( uint32_t j = 1; j < matrix.size() - 1 && looping; ++j ) - { - uint64_t current_columns0 = matrix[i].column[0] | matrix[j].column[0]; - uint64_t current_columns1 = matrix[i].column[1] | matrix[j].column[1]; - uint32_t current_cost = matrix[i].cost + matrix[j].cost; - - /* limit */ - if constexpr ( limit_iter ) - { - if ( limit <= 0 ) - { - looping = false; - } - } - if constexpr ( limit_sol ) - { - if ( best_cost < UINT32_MAX && max_iter == 0 ) - { - looping = false; - } - } - - /* bound */ - if ( current_cost >= best_cost ) - { - continue; - } - - for ( uint32_t k = 2; k < matrix.size() && looping; ++k ) - { - /* limit */ - if constexpr ( limit_iter ) - { - if ( limit-- <= 0 ) - { - looping = false; - } - } - if constexpr ( limit_sol ) - { - if ( best_cost < UINT32_MAX && max_iter-- == 0 ) - { - looping = false; - } - } - - /* filter by cost */ - if ( current_cost + matrix[k].cost >= best_cost ) - continue; - - /* check validity */ - if ( __builtin_popcountl( current_columns0 | matrix[k].column[0] ) + __builtin_popcountl( current_columns1 | matrix[k].column[1] ) == combinations ) - { - res[0] = i; - res[1] = j; - res[2] = k; - best_cost = current_cost + matrix[k].cost; - } - } - } - } - } - else - { - res[4] = 4; - for ( uint32_t i = 0; i < matrix.size() - 3 && looping; ++i ) - { - /* limit */ - if constexpr ( limit_iter ) - { - if ( limit <= 0 ) - { - looping = false; - } - } - if constexpr ( limit_sol ) - { - if ( best_cost < UINT32_MAX && max_iter == 0 ) - { - looping = false; - } - } - - for ( uint32_t j = 1; j < matrix.size() - 2 && looping; ++j ) - { - uint64_t current_columns0 = matrix[i].column[0] | matrix[j].column[0]; - uint64_t current_columns1 = matrix[i].column[1] | matrix[j].column[1]; - uint32_t current_cost0 = matrix[i].cost + matrix[j].cost; - - /* limit */ - if constexpr ( limit_iter ) - { - if ( limit <= 0 ) - { - looping = false; - } - } - if constexpr ( limit_sol ) - { - if ( best_cost < UINT32_MAX && max_iter == 0 ) - { - looping = false; - } - } - - /* bound */ - if ( current_cost0 >= best_cost ) - { - continue; - } - - for ( uint32_t k = 2; k < matrix.size() - 1 && looping; ++k ) - { - uint64_t current_columns00 = current_columns0 | matrix[k].column[0]; - uint64_t current_columns11 = current_columns1 | matrix[k].column[1]; - uint32_t current_cost1 = current_cost0 + matrix[k].cost; - - /* limit */ - if constexpr ( limit_iter ) - { - if ( limit <= 0 ) - { - looping = false; - } - } - if constexpr ( limit_sol ) - { - if ( best_cost < UINT32_MAX && max_iter == 0 ) - { - looping = false; - } - } - - /* bound */ - if ( current_cost1 >= best_cost ) - { - continue; - } - - for ( uint32_t t = 3; t < matrix.size() && looping; ++t ) - { - /* limit */ - if constexpr ( limit_iter ) - { - if ( limit-- <= 0 ) - { - looping = false; - } - } - if constexpr ( limit_sol ) - { - if ( best_cost-- < UINT32_MAX && max_iter == 0 ) - { - looping = false; - } - } - - /* filter by cost */ - if ( current_cost1 + matrix[t].cost >= best_cost ) - continue; - - /* check validity */ - if ( __builtin_popcountl( current_columns00 | matrix[t].column[0] ) + __builtin_popcountl( current_columns11 | matrix[t].column[1] ) == combinations ) - { - res[0] = i; - res[1] = j; - res[2] = k; - res[3] = t; - best_cost = current_cost1 + matrix[t].cost; - } - } - } - } - } - } return res; } - std::array covering_solve_heuristic( std::vector& matrix ) + std::array covering_solve_heuristic( std::vector& matrix ) { /* last value of res contains the size of the bound set */ std::array res = { UINT32_MAX }; @@ -1285,7 +1092,7 @@ private: return res; } - bool covering_improve( std::vector& matrix, std::array& solution ) + bool covering_improve( std::vector& matrix, std::array& solution ) { /* performs one iteration of local search */ uint32_t best_cost = 0, local_cost = 0; @@ -1431,6 +1238,19 @@ private: return false; } + /* Decomposition format for ABC + * + * The record is an array of unsigned chars where: + * - the first unsigned char entry stores the number of unsigned chars in the record + * - the second entry stores the number of LUTs + * After this, several sub-records follow, each representing one LUT as follows: + * - an unsigned char entry listing the number of fanins + * - a list of fanins, from the LSB to the MSB of the truth table. The N inputs of the original function + * have indexes from 0 to N-1, followed by the internal signals in a topological order + * - the LUT truth table occupying 2^(M-3) bytes, where M is the fanin count of the LUT, from the LSB to the MSB. + * A 2-input LUT, which takes 4 bits, should be stretched to occupy 8 bits (one unsigned char) + * A 0- or 1-input LUT can be represented similarly but it is not expected that such LUTs will be represented + */ void get_decomposition_abc( unsigned char *decompArray ) { unsigned char *pArray = decompArray; @@ -1485,11 +1305,10 @@ private: std::vector> support_minimization_encodings; - TT tt_start; uint32_t num_vars; ac_decomposition_params const& ps; ac_decomposition_stats* pst; - std::vector permutations; + std::array permutations; }; } // namespace mockturtle diff --git a/src/acd/ac_wrapper.cpp b/src/acd/ac_wrapper.cpp index 6bb41ca37..99e5747f2 100644 --- a/src/acd/ac_wrapper.cpp +++ b/src/acd/ac_wrapper.cpp @@ -1,27 +1,17 @@ -// #include "base/main/main.h" #include "ac_wrapper.h" #include "ac_decomposition.hpp" -// ABC_NAMESPACE_IMPL_START - int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ) { using namespace mockturtle; - int num_blocks = ( nVars <= 6 ) ? 1 : ( 1 << ( nVars - 6 ) ); - - /* translate truth table into static table */ - kitty::dynamic_truth_table tt( nVars ); - for ( int i = 0; i < num_blocks; ++i ) - tt._bits[i] = pTruth[i]; - ac_decomposition_params ps; ps.lut_size = lutSize; ps.try_no_late_arrival = static_cast( try_no_late_arrival ); ac_decomposition_stats st; - ac_decomposition_impl acd( tt, nVars, ps, &st ); - int val = acd.run( *pdelay ); + ac_decomposition_impl acd( nVars, ps, &st ); + int val = acd.run( pTruth, *pdelay ); if ( val < 0 ) { @@ -39,19 +29,12 @@ int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, { using namespace mockturtle; - int num_blocks = ( nVars <= 6 ) ? 1 : ( 1 << ( nVars - 6 ) ); - - /* translate truth table into static table */ - kitty::dynamic_truth_table tt( nVars ); - for ( int i = 0; i < num_blocks; ++i ) - tt._bits[i] = pTruth[i]; - ac_decomposition_params ps; ps.lut_size = lutSize; ac_decomposition_stats st; - ac_decomposition_impl acd( tt, nVars, ps, &st ); - acd.run( *pdelay ); + ac_decomposition_impl acd( nVars, ps, &st ); + acd.run( pTruth, *pdelay ); int val = acd.compute_decomposition(); if ( val < 0 ) @@ -65,5 +48,3 @@ int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, acd.get_decomposition( decomposition ); return 0; } - -// ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/acd/ac_wrapper.h b/src/acd/ac_wrapper.h index 5e0af3787..c41b4aec7 100644 --- a/src/acd/ac_wrapper.h +++ b/src/acd/ac_wrapper.h @@ -1,13 +1,10 @@ -// #pragma once +#pragma once #ifndef __ACD_WRAPPER_H_ #define __ACD_WRAPPER_H_ -// #include "base/main/main.h" #include "misc/util/abc_global.h" #include "map/if/if.h" -// ABC_NAMESPACE_HEADER_START - #ifdef __cplusplus extern "C" { #endif @@ -19,6 +16,4 @@ int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, } #endif -// ABC_NAMESPACE_HEADER_END - #endif \ No newline at end of file From 6097fd43495b62bec793fa8ca4fbc429bc9130ae Mon Sep 17 00:00:00 2001 From: aletempiac Date: Fri, 24 Nov 2023 14:24:20 +0100 Subject: [PATCH 058/151] Code formatting --- src/acd/ac_decomposition.hpp | 170 +++++++++++++++++------------------ src/acd/ac_wrapper.cpp | 2 +- 2 files changed, 82 insertions(+), 90 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index d63d6685d..829ea5855 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -44,10 +44,10 @@ #include "kitty_constants.hpp" #include "kitty_constructors.hpp" -#include "kitty_static_tt.hpp" #include "kitty_dynamic_tt.hpp" #include "kitty_operations.hpp" #include "kitty_operators.hpp" +#include "kitty_static_tt.hpp" namespace mockturtle { @@ -55,19 +55,19 @@ namespace mockturtle /*! \brief Parameters for ac_decomposition */ struct ac_decomposition_params { - /*! \brief LUT size for decomposition. */ + /*! \brief LUT size for decomposition (3 < num < 7). */ uint32_t lut_size{ 6 }; - /*! \brief Perform decomposition if support reducing. */ - uint32_t max_free_set_vars{ 5 }; + /*! \brief Maximum size of the free set (1 < num < 6). */ + uint32_t max_free_set_vars{ 4 }; - /*! \brief Perform decomposition if support reducing. */ + /*! \brief Perform only support reducing (2-level) decompositions. */ bool support_reducing_only{ true }; - /*! \brief Commits the first feasible decomposition. */ - bool exit_on_feasible_decomposition{ true }; + /*! \brief Use the first feasible decomposition found. */ + bool use_first{ true }; - /*! \brief If decomposition with delay profile fails, ignore it. */ + /*! \brief If decomposition with delay profile fails, try without. */ bool try_no_late_arrival{ false }; }; @@ -108,7 +108,7 @@ public: } /*! \brief Runs ACD using late arriving variables */ - int run( word *tt, unsigned delay_profile ) + int run( word* ptt, unsigned delay_profile ) { /* truth table is too large for the settings */ if ( num_vars > max_num_vars ) @@ -125,7 +125,7 @@ public: } /* convert to static TT */ - init_truth_table( tt ); + init_truth_table( ptt ); /* permute late arriving variables to be the least significant */ reposition_late_arriving_variables( delay_profile, late_arriving ); @@ -142,7 +142,7 @@ public: int compute_decomposition() { - if ( best_multiplicity == UINT32_MAX ) + if ( best_multiplicity == UINT32_MAX ) return -1; /* compute isets */ @@ -168,7 +168,7 @@ public: if ( best_free_set > num_vars ) return -1; - + for ( uint32_t i = 0; i < best_free_set; ++i ) { profile |= 1 << permutations[i]; @@ -177,17 +177,12 @@ public: return profile; } - std::vector get_result() - { - return dec_result; - } - - void get_decomposition( unsigned char *decompArray ) + void get_decomposition( unsigned char* decompArray ) { if ( best_free_set > num_vars ) return; - dec_result = generate_decomposition( best_free_set ); + generate_decomposition(); return get_decomposition_abc( decompArray ); } @@ -208,12 +203,11 @@ private: /* array of functions to compute the column multiplicity */ std::function column_multiplicity_fn[5] = { - [this]( STT const& tt ) { return column_multiplicity<1u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity<2u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity<3u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity5<4u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } - }; + [this]( STT const& tt ) { return column_multiplicity<1u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity<2u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity<3u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity5<4u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } }; /* find a feasible AC decomposition */ for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) @@ -232,7 +226,7 @@ private: best_cost = multiplicity + additional_cost; best_free_set = i; - if ( ps.exit_on_feasible_decomposition ) + if ( ps.use_first ) { break; } @@ -267,7 +261,7 @@ private: best_cost = multiplicity + additional_cost; best_free_set = i; - if ( ps.exit_on_feasible_decomposition ) + if ( ps.use_first ) { break; } @@ -279,18 +273,20 @@ private: return false; /* estimation on number of LUTs */ - pst->num_luts = best_multiplicity <= 2 ? 2 : best_multiplicity <= 4 ? 3 : best_multiplicity <= 8 ? 4 : 5; + pst->num_luts = best_multiplicity <= 2 ? 2 : best_multiplicity <= 4 ? 3 + : best_multiplicity <= 8 ? 4 + : 5; return true; } - void init_truth_table( word *tt_start ) + void init_truth_table( word* ptt ) { uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) ); for ( uint32_t i = 0; i < num_blocks; ++i ) { - best_tt._bits[i] = tt_start[i]; + best_tt._bits[i] = ptt[i]; } local_extend_to( best_tt, num_vars ); @@ -362,7 +358,7 @@ private: } std::sort( multiplicity_set.begin(), multiplicity_set.begin() + size ); - + /* count unique */ uint32_t multiplicity = 1; for ( auto i = 1u; i < size; ++i ) @@ -373,7 +369,7 @@ private: return multiplicity; } - inline bool combinations_offset_next( uint32_t k, uint32_t offset, uint32_t *pComb, uint32_t *pInvPerm, STT& tt ) + inline bool combinations_offset_next( uint32_t k, uint32_t offset, uint32_t* pComb, uint32_t* pInvPerm, STT& tt ) { uint32_t i; @@ -443,7 +439,7 @@ private: bestPerm[i] = pComb[i]; } } - } while( combinations_offset_next( free_set_size, offset, pComb, pInvPerm, tt ) ); + } while ( combinations_offset_next( free_set_size, offset, pComb, pInvPerm, tt ) ); std::array res_perm; for ( uint32_t i = 0; i < num_vars; ++i ) @@ -525,10 +521,11 @@ private: return isets; } - std::vector generate_decomposition( uint32_t free_set_size ) + void generate_decomposition() { - std::vector res; + dec_result.clear(); + uint32_t num_edges = 0; for ( uint32_t i = 0; i < best_bound_sets.size(); ++i ) { ac_decomposition_result dec; @@ -537,7 +534,7 @@ private: /* compute and minimize support for bound set variables */ uint32_t k = 0; - for ( uint32_t j = 0; j < num_vars - free_set_size; ++j ) + for ( uint32_t j = 0; j < num_vars - best_free_set; ++j ) { if ( !kitty::has_var( tt, j ) ) continue; @@ -554,59 +551,64 @@ private: kitty::swap_inplace( tt, k, j ); kitty::swap_inplace( care, k, j ); } - dec.support.push_back( permutations[free_set_size + j] ); + dec.support.push_back( permutations[best_free_set + j] ); ++k; } dec.tt = kitty::shrink_to( tt, dec.support.size() ); - res.push_back( dec ); + dec_result.push_back( dec ); + num_edges += dec.support.size() > 1 ? dec.support.size() : 0; } /* compute the decomposition for the top-level LUT */ - compute_top_lut_decomposition( res, free_set_size ); + compute_top_lut_decomposition(); - return res; + if ( pst ) + { + pst->num_luts = dec_result.size(); + pst->num_edges = num_edges + dec_result.back().support.size(); + } } - void compute_top_lut_decomposition( std::vector& res, uint32_t free_set_size ) + void compute_top_lut_decomposition() { - uint32_t top_vars = best_bound_sets.size() + free_set_size; + uint32_t top_vars = best_bound_sets.size() + best_free_set; assert( top_vars <= ps.lut_size ); /* extend bound set functions with free_set_size LSB vars */ kitty::dynamic_truth_table tt( top_vars ); /* compute support */ - res.emplace_back(); - for ( uint32_t i = 0; i < free_set_size; ++i ) + dec_result.emplace_back(); + for ( uint32_t i = 0; i < best_free_set; ++i ) { - res.back().support.push_back( permutations[i] ); + dec_result.back().support.push_back( permutations[i] ); } /* create functions for bound set */ std::vector bound_set_vars; - auto res_it = res.begin(); + auto res_it = dec_result.begin(); uint32_t offset = 0; for ( uint32_t i = 0; i < best_bound_sets.size(); ++i ) { bound_set_vars.emplace_back( top_vars ); - kitty::create_nth_var( bound_set_vars[i], free_set_size + i ); + kitty::create_nth_var( bound_set_vars[i], best_free_set + i ); - /* add bound-set variables to the support, remove buffers */ + /* add bound-set variables to the support, remove buffers (shared set) */ if ( res_it->support.size() == 1 ) { - res.back().support.push_back( res_it->support.front() ); + dec_result.back().support.push_back( res_it->support.front() ); /* it is a NOT */ if ( ( res_it->tt._bits[0] & 1 ) == 1 ) { bound_set_vars[i] = ~bound_set_vars[i]; } - res.erase( res_it ); + dec_result.erase( res_it ); ++offset; } else { - res.back().support.push_back( num_vars + i - offset ); + dec_result.back().support.push_back( num_vars + i - offset ); ++res_it; } } @@ -634,7 +636,7 @@ private: } /* add top-level LUT to result */ - res.back().tt = tt; + dec_result.back().tt = tt; } inline void reposition_late_arriving_variables( unsigned delay_profile, uint32_t late_arriving ) @@ -704,14 +706,6 @@ private: } assert( count == num_combs ); - - /* print combinations */ - // std::cout << "{ "; - // for ( auto const& entry : support_minimization_encodings ) - // { - // std::cout << "{ " << entry[0] << ", " << entry[1] << " }, "; - // } - // std::cout << "}\n"; } template @@ -770,7 +764,7 @@ private: } /* solve the covering problem */ - std::array solution = covering_solve_exact( matrix ); + std::array solution = covering_solve_exact( matrix ); /* check for failed decomposition */ if ( solution[0] == UINT32_MAX ) @@ -779,14 +773,14 @@ private: } /* compute best bound sets */ - uint32_t num_luts = 1 + solution[4]; + uint32_t num_luts = 1 + solution[5]; uint32_t num_levels = 2; - uint32_t num_edges = best_free_set + solution[4]; + uint32_t num_edges = best_free_set + solution[5]; uint32_t isets_support = num_vars - best_free_set; best_care_sets.clear(); best_iset_onset.clear(); best_iset_offset.clear(); - for ( uint32_t i = 0; i < solution[4]; ++i ) + for ( uint32_t i = 0; i < solution[5]; ++i ) { STT tt; STT care; @@ -835,7 +829,7 @@ private: } /* solve the covering problem: heuristic pass + local search */ - std::array solution = covering_solve_heuristic( matrix ); + std::array solution = covering_solve_heuristic( matrix ); /* check for failed decomposition */ if ( solution[0] == UINT32_MAX ) @@ -848,14 +842,14 @@ private: ; /* compute best bound sets */ - uint32_t num_luts = 1 + solution[4]; + uint32_t num_luts = 1 + solution[5]; uint32_t num_levels = 2; - uint32_t num_edges = best_free_set + solution[4]; + uint32_t num_edges = best_free_set + solution[5]; uint32_t isets_support = num_vars - best_free_set; best_care_sets.clear(); best_iset_onset.clear(); best_iset_offset.clear(); - for ( uint32_t i = 0; i < solution[4]; ++i ) + for ( uint32_t i = 0; i < solution[5]; ++i ) { STT tt; STT care; @@ -993,10 +987,10 @@ private: return true; } - std::array covering_solve_exact( std::vector& matrix ) + std::array covering_solve_exact( std::vector& matrix ) { /* last value of res contains the size of the bound set */ - std::array res = { UINT32_MAX }; + std::array res = { UINT32_MAX }; uint32_t best_cost = UINT32_MAX; uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; @@ -1005,12 +999,12 @@ private: /* determine the number of needed loops*/ if ( best_multiplicity <= 2 ) { - res[4] = 1; + res[5] = 1; res[0] = 0; } else if ( best_multiplicity <= 4 ) { - res[4] = 2; + res[5] = 2; for ( uint32_t i = 0; i < matrix.size() - 1; ++i ) { for ( uint32_t j = 1; j < matrix.size(); ++j ) @@ -1033,10 +1027,10 @@ private: return res; } - std::array covering_solve_heuristic( std::vector& matrix ) + std::array covering_solve_heuristic( std::vector& matrix ) { /* last value of res contains the size of the bound set */ - std::array res = { UINT32_MAX }; + std::array res = { UINT32_MAX }; uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; uint64_t column0 = 0, column1 = 0; @@ -1086,17 +1080,17 @@ private: { res[i] = i; } - res[4] = iter; + res[5] = iter; } return res; } - bool covering_improve( std::vector& matrix, std::array& solution ) + bool covering_improve( std::vector& matrix, std::array& solution ) { /* performs one iteration of local search */ uint32_t best_cost = 0, local_cost = 0; - uint32_t num_elements = solution[4]; + uint32_t num_elements = solution[5]; uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; bool improved = false; @@ -1211,8 +1205,7 @@ private: auto it_care = std::begin( care._bits ); while ( it_tt != std::begin( tt._bits ) + num_blocks ) { - if ( ( ( ( *it_tt >> ( uint64_t( 1 ) << var_index ) ) ^ *it_tt ) & kitty::detail::projections_neg[var_index] - & ( *it_care >> ( uint64_t( 1 ) << var_index ) ) & *it_care ) != 0 ) + if ( ( ( ( *it_tt >> ( uint64_t( 1 ) << var_index ) ) ^ *it_tt ) & kitty::detail::projections_neg[var_index] & ( *it_care >> ( uint64_t( 1 ) << var_index ) ) & *it_care ) != 0 ) { return true; } @@ -1251,28 +1244,27 @@ private: * A 2-input LUT, which takes 4 bits, should be stretched to occupy 8 bits (one unsigned char) * A 0- or 1-input LUT can be represented similarly but it is not expected that such LUTs will be represented */ - void get_decomposition_abc( unsigned char *decompArray ) + void get_decomposition_abc( unsigned char* decompArray ) { - unsigned char *pArray = decompArray; + unsigned char* pArray = decompArray; unsigned char bytes = 2; /* write number of LUTs */ pArray++; - *pArray = dec_result.size(); - pArray++; + *pArray++ = dec_result.size(); /* write LUTs */ for ( ac_decomposition_result const& lut : dec_result ) { /* write fanin size*/ - *pArray = lut.support.size(); - pArray++; ++bytes; + *pArray++ = lut.support.size(); + ++bytes; /* write support */ for ( uint32_t i : lut.support ) { - *pArray = (unsigned char) i; - pArray++; ++bytes; + *pArray++ = (unsigned char)i; + ++bytes; } /* write truth table */ @@ -1282,8 +1274,8 @@ private: { for ( uint32_t j = 0; j < tt_num_bytes; ++j ) { - *pArray = (unsigned char) ( ( lut.tt._bits[i] >> ( 8 * j ) ) & 0xFF ); - pArray++; ++bytes; + *pArray++ = (unsigned char)( ( lut.tt._bits[i] >> ( 8 * j ) ) & 0xFF ); + ++bytes; } } } diff --git a/src/acd/ac_wrapper.cpp b/src/acd/ac_wrapper.cpp index 99e5747f2..27259b67a 100644 --- a/src/acd/ac_wrapper.cpp +++ b/src/acd/ac_wrapper.cpp @@ -7,7 +7,7 @@ int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, ac_decomposition_params ps; ps.lut_size = lutSize; - ps.try_no_late_arrival = static_cast( try_no_late_arrival ); + ps.try_no_late_arrival = static_cast( try_no_late_arrival ); /* TODO: additional tests */ ac_decomposition_stats st; ac_decomposition_impl acd( nVars, ps, &st ); From b3d2419d9a0175bfbfb7478a7131bd706a16126a Mon Sep 17 00:00:00 2001 From: aletempiac Date: Mon, 27 Nov 2023 13:38:36 +0100 Subject: [PATCH 059/151] Formatting, renaming, and cleaning code --- src/acd/ac_decomposition.hpp | 49 +++++++++++++++--------------------- src/acd/ac_wrapper.cpp | 22 ++++++++++++++-- src/acd/ac_wrapper.h | 18 +++++++++++++ src/base/abci/abc.c | 45 +++++++++++++++++++++++++++------ src/base/abci/abcIf.c | 16 ++++++------ src/map/if/if.h | 12 ++++----- src/map/if/ifCore.c | 28 +-------------------- src/map/if/ifCut.c | 2 +- src/map/if/ifDelay.c | 20 +++++++-------- src/map/if/ifMap.c | 14 +++++------ src/map/if/ifTime.c | 4 +-- 11 files changed, 131 insertions(+), 99 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 829ea5855..2b3161476 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -1,28 +1,20 @@ -/* mockturtle: C++ logic network library - * Copyright (C) 2018-2023 EPFL - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ +/**C++File************************************************************** + FileName [ac_decomposition.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Ashenhurst-Curtis decomposition.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alessandro Tempia Calvino] + + Affiliation [EPFL] + + Date [Ver. 1.0. Started - November 20, 2023.] + +***********************************************************************/ /*! \file ac_decomposition.hpp \brief Ashenhurst-Curtis decomposition @@ -39,7 +31,6 @@ #include #include #include -#include #include #include "kitty_constants.hpp" @@ -49,7 +40,7 @@ #include "kitty_operators.hpp" #include "kitty_static_tt.hpp" -namespace mockturtle +namespace acd { /*! \brief Parameters for ac_decomposition */ @@ -346,10 +337,10 @@ private: { for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) { - uint32_t fs_fn = static_cast( *it & masks[free_set_size] ); + uint64_t fs_fn = *it & masks[free_set_size]; if ( fs_fn != prev ) { - multiplicity_set[size++] = fs_fn; + multiplicity_set[size++] = static_cast( fs_fn ); prev = fs_fn; } *it >>= ( 1u << free_set_size ); @@ -1303,6 +1294,6 @@ private: std::array permutations; }; -} // namespace mockturtle +} // namespace acd #endif // _ACD_H_ \ No newline at end of file diff --git a/src/acd/ac_wrapper.cpp b/src/acd/ac_wrapper.cpp index 27259b67a..baeee2fd6 100644 --- a/src/acd/ac_wrapper.cpp +++ b/src/acd/ac_wrapper.cpp @@ -1,9 +1,27 @@ +/**C++File************************************************************** + + FileName [ac_wrapper.cpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Ashenhurst-Curtis decomposition.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alessandro Tempia Calvino] + + Affiliation [EPFL] + + Date [Ver. 1.0. Started - November 20, 2023.] + +***********************************************************************/ + #include "ac_wrapper.h" #include "ac_decomposition.hpp" int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ) { - using namespace mockturtle; + using namespace acd; ac_decomposition_params ps; ps.lut_size = lutSize; @@ -27,7 +45,7 @@ int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ) { - using namespace mockturtle; + using namespace acd; ac_decomposition_params ps; ps.lut_size = lutSize; diff --git a/src/acd/ac_wrapper.h b/src/acd/ac_wrapper.h index c41b4aec7..ce39949fb 100644 --- a/src/acd/ac_wrapper.h +++ b/src/acd/ac_wrapper.h @@ -1,3 +1,21 @@ +/**C++File************************************************************** + + FileName [ac_wrapper.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Ashenhurst-Curtis decomposition.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alessandro Tempia Calvino] + + Affiliation [EPFL] + + Date [Ver. 1.0. Started - November 20, 2023.] + +***********************************************************************/ + #pragma once #ifndef __ACD_WRAPPER_H_ #define __ACD_WRAPPER_H_ diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 33b85e0bf..89785887d 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -19447,7 +19447,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) If_ManSetDefaultPars( pPars ); pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyuojiktnczvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYZDEWSqaflepmrsdbgxyzuojiktncvh" ) ) != EOF ) { switch ( c ) { @@ -19563,6 +19563,17 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nAndDelay < 0 ) goto usage; break; + case 'Z': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Z\" should be followed by a positive integer 3, 4, 5, or 6.\n" ); + goto usage; + } + pPars->nLutDecSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLutDecSize < 3 || pPars->nLutDecSize > 6 ) + goto usage; + break; case 'D': if ( globalUtilOptind >= argc ) { @@ -19652,6 +19663,9 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'y': pPars->fUserRecLib ^= 1; break; + case 'z': + pPars->fUserLutDec ^= 1; + break; case 'u': pPars->fUserSesLib ^= 1; break; @@ -19676,9 +19690,6 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'c': pPars->fUseTtPerm ^= 1; break; - case 'z': - pPars->fAcd ^= 1; - break; case 'v': pPars->fVerbose ^= 1; break; @@ -19794,6 +19805,25 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fCutMin = 1; } + if ( pPars->fUserLutDec ) + { + if ( pPars->nLutDecSize == 0 ) + { + Abc_Print( -1, "LUT decomposition size (%d) must be set.\n", pPars->nLutDecSize ); + return 1; + } + if ( pPars->nLutDecSize >= pPars->nLutSize ) + { + Abc_Print( -1, "LUT size (%d) must be greater than the LUT decomposition size (%d).\n", pPars->nLutSize, pPars->nLutDecSize ); + return 1; + } + if ( pPars->nLutSize < 4 || pPars->nLutSize > 10 ) + { + Abc_Print( -1, "This feature only works for [4;10]-LUTs.\n" ); + return 1; + } + } + // enable truth table computation if cut minimization is selected if ( pPars->fCutMin ) { @@ -19810,7 +19840,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pLutLib = NULL; } // modify for delay optimization - if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fAcd ) + if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fUserLutDec ) { pPars->fTruth = 1; pPars->fCutMin = 1; @@ -19956,7 +19986,7 @@ usage: sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyuojiktncvh]\n" ); + Abc_Print( -2, "usage: if [-KCFAGRNTXYZ num] [-DEW float] [-S str] [-qarlepmsdbgxyzuojiktncvh]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -19968,6 +19998,7 @@ usage: Abc_Print( -2, "\t-T num : the type of LUT structures [default = any]\n" ); Abc_Print( -2, "\t-X num : delay of AND-gate in LUT library units [default = %d]\n", pPars->nAndDelay ); Abc_Print( -2, "\t-Y num : area of AND-gate in LUT library units [default = %d]\n", pPars->nAndArea ); + Abc_Print( -2, "\t-Z num : the number of LUT inputs for LUT decomposition [default = %d]\n", pPars->nLutDecSize ); Abc_Print( -2, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); Abc_Print( -2, "\t-W float : sets wire delay between adjects LUTs [default = %f]\n", pPars->WireDelay ); @@ -19985,6 +20016,7 @@ usage: Abc_Print( -2, "\t-g : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" ); Abc_Print( -2, "\t-x : toggles delay optimization by DSD balancing [default = %s]\n", pPars->fDsdBalance? "yes": "no" ); Abc_Print( -2, "\t-y : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" ); + Abc_Print( -2, "\t-z : toggles delay optimization with LUT decomposition [default = %s]\n", pPars->fUserLutDec? "yes": "no" ); Abc_Print( -2, "\t-u : toggles delay optimization with SAT-based library [default = %s]\n", pPars->fUserSesLib? "yes": "no" ); Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" ); Abc_Print( -2, "\t-j : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" ); @@ -19993,7 +20025,6 @@ usage: Abc_Print( -2, "\t-t : toggles optimizing average rather than maximum level [default = %s]\n", pPars->fDoAverage? "yes": "no" ); Abc_Print( -2, "\t-n : toggles computing DSDs of the cut functions [default = %s]\n", pPars->fUseDsd? "yes": "no" ); Abc_Print( -2, "\t-c : toggles computing truth tables in a new way [default = %s]\n", pPars->fUseTtPerm? "yes": "no" ); - Abc_Print( -2, "\t-z : toggles using ACD decomposition [default = %s]\n", pPars->fAcd? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index b7d796273..357d7d83f 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -116,7 +116,7 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk); // update timing info to reflect logic level - if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fAcd) && pNtk->pManTime ) + if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fUserLutDec) && pNtk->pManTime ) { int c; if ( pNtk->AndGateDelay == 0.0 ) @@ -443,7 +443,7 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC int v; If_Obj_t * pIfLeaf; - if ( pCutBest->nLeaves <= 6 ) + if ( pCutBest->nLeaves <= pIfMan->pPars->nLutDecSize ) { /* add fanins */ If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, v ) @@ -456,11 +456,11 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC } // get the delay profile - unsigned delayProfile = pCutBest->acdDelay; + unsigned delayProfile = pCutBest->decDelay; // perform LUT-decomposition and return the LUT-structure unsigned char decompArray[92]; - int val = acd_decompose( pTruth, pCutBest->nLeaves, 6, &(delayProfile), decompArray ); + int val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); assert( val == 0 ); // convert the LUT-structure into a set of logic nodes in Abc_Ntk_t @@ -474,7 +474,7 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC Abc_Obj_t *pNewNodes[5]; /* create intermediate LUTs*/ - assert( decompArray[1] - 1 <= 5 ); + assert( decompArray[1] <= 6 ); Abc_Obj_t * pFanin; for ( i = 0; i < decompArray[1]; ++i ) { @@ -577,14 +577,14 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t pNodeNew = Abc_NtkCreateNode( pNtkNew ); // if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays ) if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm && - !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fAcd && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize ) + !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserLutDec && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize ) If_CutRotatePins( pIfMan, pCutBest ); if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) { If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i ) Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); } - else if ( pIfMan->pPars->fAcd ) + else if ( pIfMan->pPars->fUserLutDec ) { If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover); @@ -642,7 +642,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj ); } - else if ( pIfMan->pPars->fAcd ) + else if ( pIfMan->pPars->fUserLutDec ) { extern void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vMemory, Abc_Obj_t * pNodeTop ); Abc_DecRecordToHop( pNtkNew, pIfMan, pCutBest, pIfObj, vCover, pNodeNew ); diff --git a/src/map/if/if.h b/src/map/if/if.h index c3ba59be4..cc4d2926b 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -113,6 +113,7 @@ struct If_Par_t_ int nStructType; // type of the structure int nAndDelay; // delay of AND-gate in LUT library units int nAndArea; // area of AND-gate in LUT library units + int nLutDecSize; // the LUT size for decomposition int fPreprocess; // preprossing int fArea; // area-oriented mapping int fFancy; // a fancy feature @@ -146,7 +147,7 @@ struct If_Par_t_ int fDeriveLuts; // enables deriving LUT structures int fDoAverage; // optimize average rather than maximum level int fHashMapping; // perform AIG hashing after mapping - int fAcd; // perform AIG hashing after mapping + int fUserLutDec; // perform AIG hashing after mapping int fVerbose; // the verbosity flag int fVerboseTrace; // the verbosity flag char * pLutStruct; // LUT structure @@ -281,7 +282,6 @@ struct If_Man_t_ int pDumpIns[16]; Vec_Str_t * vMarks; Vec_Int_t * vVisited2; - int useLimitAdc; // timing manager Tim_Man_t * pManTim; @@ -305,7 +305,6 @@ struct If_Cut_t_ int iCutFunc; // TT ID of the cut int uMaskFunc; // polarity bitmask unsigned uSign; // cut signature - unsigned acdDelay; // Computed pin delay during ACD unsigned Cost : 12; // the user's cost of the cut (related to IF_COST_MAX) unsigned fCompl : 1; // the complemented attribute unsigned fUser : 1; // using the user's area and delay @@ -313,6 +312,7 @@ struct If_Cut_t_ unsigned fAndCut : 1; // matched with AND gate unsigned nLimit : 8; // the maximum number of leaves unsigned nLeaves : 8; // the number of leaves + unsigned decDelay: 16; // pin-to-pin decomposition delay int pLeaves[0]; }; @@ -570,9 +570,9 @@ extern int If_CutSopBalancePinDelaysInt( Vec_Int_t * vCover, int * p extern int If_CutSopBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); extern int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ); extern int If_CutLutBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); -extern int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ); -extern int If_AcdReEval( If_Man_t * p, If_Cut_t * pCut ); -extern float If_AcdLeafProp( If_Man_t * p, If_Cut_t * pCut, int i, float required ); +extern int If_LutDecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ); +extern int If_LutDecReEval( If_Man_t * p, If_Cut_t * pCut ); +extern float If_LutDecPinRequired( If_Man_t * p, If_Cut_t * pCut, int i, float required ); /*=== ifDsd.c =============================================================*/ extern If_DsdMan_t * If_DsdManAlloc( int nVars, int nLutSize ); extern void If_DsdManAllocIsops( If_DsdMan_t * p, int nLutSize ); diff --git a/src/map/if/ifCore.c b/src/map/if/ifCore.c index ad3c85179..f7fcbca66 100644 --- a/src/map/if/ifCore.c +++ b/src/map/if/ifCore.c @@ -62,7 +62,7 @@ void If_ManSetDefaultPars( If_Par_t * pPars ) pPars->fPower = 0; pPars->fCutMin = 0; pPars->fBidec = 0; - pPars->fAcd = 0; + pPars->fUserLutDec = 0; pPars->fVerbose = 0; } @@ -107,16 +107,10 @@ int If_ManPerformMappingComb( If_Man_t * p ) If_Obj_t * pObj; abctime clkTotal = Abc_Clock(); int i; - p->useLimitAdc = 1; //p->vVisited2 = Vec_IntAlloc( 100 ); //p->vMarks = Vec_StrStart( If_ManObjNum(p) ); - // if ( p->pPars->fAcd ) - // { - // p->pPars->nLutSize = 6; - // } - // set arrival times and fanout estimates If_ManForEachCi( p, pObj, i ) { @@ -128,11 +122,7 @@ int If_ManPerformMappingComb( If_Man_t * p ) if ( p->pPars->fPreprocess && !p->pPars->fArea ) { // map for delay - if ( p->pPars->fAcd ) - p->useLimitAdc = 0; If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 1, "Delay" ); - if ( p->pPars->fAcd ) - p->useLimitAdc = 1; // map for delay second option p->pPars->fFancy = 1; @@ -155,33 +145,17 @@ int If_ManPerformMappingComb( If_Man_t * p ) // area flow oriented mapping for ( i = 0; i < p->pPars->nFlowIters; i++ ) { - // if ( p->pPars->fAcd && i == 0 ) - // { - // p->useLimitAdc = 0; - // } If_ManPerformMappingRound( p, p->pPars->nCutsMax, 1, 0, 0, "Flow" ); if ( p->pPars->fExpRed ) If_ManImproveMapping( p ); - // if ( p->pPars->fAcd && i == 0 ) - // { - // p->useLimitAdc = 1; - // } } // area oriented mapping for ( i = 0; i < p->pPars->nAreaIters; i++ ) { - // if ( p->pPars->fAcd && i == 0 ) - // { - // p->useLimitAdc = 0; - // } If_ManPerformMappingRound( p, p->pPars->nCutsMax, 2, 0, 0, "Area" ); if ( p->pPars->fExpRed ) If_ManImproveMapping( p ); - // if ( p->pPars->fAcd && i == 0 ) - // { - // p->useLimitAdc = 1; - // } } if ( p->pPars->fVerbose ) diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c index 8d1cccba0..49850d313 100644 --- a/src/map/if/ifCut.c +++ b/src/map/if/ifCut.c @@ -761,7 +761,7 @@ void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut ) if ( !pCut->fUseless && (p->pPars->fUseDsd || p->pPars->pFuncCell2 || p->pPars->fUseBat || - p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fAcd || + p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fEnableCheck07 || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->fUseDsdTune || p->pPars->fEnableCheck75 || p->pPars->fEnableCheck75u || p->pPars->fUseCheck1 || p->pPars->fUseCheck2) ) { diff --git a/src/map/if/ifDelay.c b/src/map/if/ifDelay.c index 90fab6b00..3514327c1 100644 --- a/src/map/if/ifDelay.c +++ b/src/map/if/ifDelay.c @@ -412,11 +412,11 @@ int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ) } } -int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ) +int If_LutDecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ) { pCut->fUser = 1; pCut->Cost = pCut->nLeaves > 1 ? 1 : 0; - pCut->acdDelay = 0; + pCut->decDelay = 0; if ( pCut->nLeaves == 0 ) // const { assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 ); @@ -428,7 +428,7 @@ int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, in return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; } - int LutSize = 6; + int LutSize = p->pPars->nLutDecSize; int i, leaf_delay; int DelayMax = -1, nLeafMax = 0; unsigned uLeafMask = 0; @@ -450,7 +450,7 @@ int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, in } if ( If_CutLeaveNum(pCut) <= LutSize ) { - pCut->acdDelay = ( 1 << LutSize ) - 1; + pCut->decDelay = ( 1 << LutSize ) - 1; return DelayMax + 1; } @@ -473,7 +473,7 @@ int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, in } /* Too many late-arriving signals */ - if ( nLeafMax > LutSize / 2 ) + if ( nLeafMax == LutSize ) { if ( use_late_arrival ) { @@ -493,7 +493,7 @@ int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, in int val = acd_evaluate( pTruth, pCut->nLeaves, LutSize, &uLeafMask, &cost, !use_late_arrival ); /* not feasible decomposition */ - pCut->acdDelay = uLeafMask; + pCut->decDelay = uLeafMask; if ( val < 0 ) { pCut->Cost = IF_COST_MAX; @@ -505,7 +505,7 @@ int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, in return DelayMax + val; } -int If_AcdReEval( If_Man_t * p, If_Cut_t * pCut ) +int If_LutDecReEval( If_Man_t * p, If_Cut_t * pCut ) { // pCut->fUser = 1; @@ -526,14 +526,14 @@ int If_AcdReEval( If_Man_t * p, If_Cut_t * pCut ) for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) { leaf_delay = If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; - leaf_delay += ( ( pCut->acdDelay >> i ) & 1 ) == 0 ? 2 : 1; + leaf_delay += ( ( pCut->decDelay >> i ) & 1 ) == 0 ? 2 : 1; DelayMax = Abc_MaxInt( leaf_delay, DelayMax ); } return DelayMax; } -float If_AcdLeafProp( If_Man_t * p, If_Cut_t * pCut, int i, float required ) +float If_LutDecPinRequired( If_Man_t * p, If_Cut_t * pCut, int i, float required ) { if ( pCut->nLeaves == 0 ) // const { @@ -546,7 +546,7 @@ float If_AcdLeafProp( If_Man_t * p, If_Cut_t * pCut, int i, float required ) return 0; } - return ( ( pCut->acdDelay >> i ) & 1 ) == 0 ? 2 : 1; + return ( ( pCut->decDelay >> i ) & 1 ) == 0 ? 2 : 1; } /* diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index 69f2ead81..bdd3ae439 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -166,7 +166,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep If_Cut_t * pCut0R, * pCut1R; int fFunc0R, fFunc1R; int i, k, v, iCutDsd, fChange; - int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fAcd || + int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fUseDsdTune || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->pLutStruct || p->pPars->pFuncCell2 || p->pPars->fUseCheck1 || p->pPars->fUseCheck2; int fUseAndCut = (p->pPars->nAndDelay > 0) || (p->pPars->nAndArea > 0); assert( !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 0 ); @@ -208,9 +208,9 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->fUseless = 1; } } - else if ( p->pPars->fAcd ) + else if ( p->pPars->fUserLutDec ) { - pCut->Delay = If_AcdReEval( p, pCut ); + pCut->Delay = If_LutDecReEval( p, pCut ); } else if ( p->pPars->fDelayOptLut ) pCut->Delay = If_CutLutBalanceEval( p, pCut ); @@ -268,7 +268,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep if ( !If_CutMergeOrdered( p, pCut0, pCut1, pCut ) ) continue; } - if ( p->pPars->fAcd && p->useLimitAdc && pCut->nLeaves > 6 ) + if ( p->pPars->fUserLutDec && !fFirst && pCut->nLeaves > p->pPars->nLutDecSize ) continue; if ( pObj->fSpec && pCut->nLeaves == (unsigned)p->pPars->nLutSize ) continue; @@ -429,9 +429,9 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL ); else if ( p->pPars->fUserRecLib ) pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj ); - else if ( p->pPars->fAcd ) + else if ( p->pPars->fUserLutDec ) { - pCut->Delay = If_AcdEval( p, pCut, pObj, Mode == 0, fFirst ); + pCut->Delay = If_LutDecEval( p, pCut, pObj, Mode == 0, fFirst ); pCut->fUseless = pCut->Delay == ABC_INFINITY; } else if ( p->pPars->fUserSesLib ) @@ -518,7 +518,7 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP If_Set_t * pCutSet; If_Obj_t * pTemp; If_Cut_t * pCutTemp, * pCut; - int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec || p->pPars->fAcd; + int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec || p->pPars->fUserLutDec; assert( pObj->pEquiv != NULL ); // prepare diff --git a/src/map/if/ifTime.c b/src/map/if/ifTime.c index 9bce5bc43..f20842384 100644 --- a/src/map/if/ifTime.c +++ b/src/map/if/ifTime.c @@ -211,11 +211,11 @@ void If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, fl pLeaf->Required = IF_MIN( pLeaf->Required, Required - pLutDelays[0] ); } } - else if ( p->pPars->fAcd ) + else if ( p->pPars->fUserLutDec ) { Required = ObjRequired; If_CutForEachLeaf( p, pCut, pLeaf, i ) - pLeaf->Required = IF_MIN( pLeaf->Required, Required - If_AcdLeafProp( p, pCut, i, ObjRequired ) ); + pLeaf->Required = IF_MIN( pLeaf->Required, Required - If_LutDecPinRequired( p, pCut, i, ObjRequired ) ); } else { From 9bb5333f6210a49d7e0895139ef30386585b2594 Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Thu, 7 Dec 2023 19:07:52 +0800 Subject: [PATCH 060/151] extend bo --- abc.rc | 148 ---------------------------------- src/aig/gia/giaDup.c | 19 +++++ src/base/abci/abc.c | 14 +++- src/proof/cec/cec.h | 1 + src/proof/cec/cecSatG2.c | 168 +++++++++++++++++++++++++++++---------- 5 files changed, 157 insertions(+), 193 deletions(-) delete mode 100644 abc.rc diff --git a/abc.rc b/abc.rc deleted file mode 100644 index a3efc0b09..000000000 --- a/abc.rc +++ /dev/null @@ -1,148 +0,0 @@ -# global parameters -set check # checks intermediate networks -#set checkfio # prints warnings when fanins/fanouts are duplicated -#unset checkread # does not check new networks after reading from file -#set backup # saves backup networks retrived by "undo" and "recall" -#set savesteps 1 # sets the maximum number of backup networks to save -#set progressbar # display the progress bar - -# program names for internal calls -set dotwin dot.exe -set dotunix dot -set gsviewwin gsview32.exe -set gsviewunix gv -set siswin sis.exe -set sisunix sis -set mvsiswin mvsis.exe -set mvsisunix mvsis -set capowin MetaPl-Capo10.1-Win32.exe -set capounix MetaPl-Capo10.1 -set gnuplotwin wgnuplot.exe -set gnuplotunix gnuplot - -# Niklas Een's commands -#load_plugin C:\_projects\abc\lib\bip_win.exe "BIP" - -# standard aliases -alias hi history -alias b balance -alias cg clockgate -alias cl cleanup -alias clp collapse -alias cs care_set -alias el eliminate -alias esd ext_seq_dcs -alias f fraig -alias fs fraig_sweep -alias fsto fraig_store -alias fres fraig_restore -alias fr fretime -alias ft fraig_trust -alias ic indcut -alias lp lutpack -alias pcon print_cone -alias pd print_dsd -alias pex print_exdc -d -alias pf print_factor -alias pfan print_fanio -alias pg print_gates -alias pl print_level -alias plat print_latch -alias pio print_io -alias pk print_kmap -alias pm print_miter -alias ps print_stats -alias psb print_stats -b -alias psu print_supp -alias psy print_symm -alias pun print_unate -alias q quit -alias r read -alias ra read_aiger -alias r3 retime -M 3 -alias r3f retime -M 3 -f -alias r3b retime -M 3 -b -alias ren renode -alias rh read_hie -alias ri read_init -alias rl read_blif -alias rb read_bench -alias ret retime -alias dret dretime -alias rp read_pla -alias rt read_truth -alias rv read_verilog -alias rvl read_verlib -alias rsup read_super mcnc5_old.super -alias rlib read_library -alias rlibc read_library cadence.genlib -alias rty read_liberty -alias rlut read_lut -alias rw rewrite -alias rwz rewrite -z -alias rf refactor -alias rfz refactor -z -alias re restructure -alias rez restructure -z -alias rs resub -alias rsz resub -z -alias sa set autoexec ps -alias scl scleanup -alias sif if -s -alias so source -x -alias st strash -alias sw sweep -alias ssw ssweep -alias tr0 trace_start -alias tr1 trace_check -alias trt "r c.blif; st; tr0; b; tr1" -alias u undo -alias w write -alias wa write_aiger -alias wb write_bench -alias wc write_cnf -alias wh write_hie -alias wl write_blif -alias wp write_pla -alias wv write_verilog - -# standard scripts -alias resyn "b; rw; rwz; b; rwz; b" -alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" -alias resyn2a "b; rw; b; rw; rwz; b; rwz; b" -alias resyn3 "b; rs; rs -K 6; b; rsz; rsz -K 6; b; rsz -K 5; b" -alias compress "b -l; rw -l; rwz -l; b -l; rwz -l; b -l" -alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l" -alias choice "fraig_store; resyn; fraig_store; resyn2; fraig_store; fraig_restore" -alias choice2 "fraig_store; balance; fraig_store; resyn; fraig_store; resyn2; fraig_store; resyn2; fraig_store; fraig_restore" -alias rwsat "st; rw -l; b -l; rw -l; rf -l" -alias drwsat2 "st; drw; b -l; drw; drf; ifraig -C 20; drw; b -l; drw; drf" -alias share "st; multi -m; sop; fx; resyn2" -alias addinit "read_init; undc; strash; zero" -alias blif2aig "undc; strash; zero" -alias v2p "&vta_gla; &ps; &gla_derive; &put; w 1.aig; pdr -v" -alias g2p "&ps; &gla_derive; &put; w 2.aig; pdr -v" -alias &sw_ "&put; sweep; st; &get" -alias &fx_ "&put; sweep; sop; fx; st; &get" -alias &dc3 "&b; &jf -K 6; &b; &jf -K 4; &b" -alias &dc4 "&b; &jf -K 7; &fx; &b; &jf -K 5; &fx; &b" - -# resubstitution scripts for the IWLS paper -alias src_rw "st; rw -l; rwz -l; rwz -l" -alias src_rs "st; rs -K 6 -N 2 -l; rs -K 9 -N 2 -l; rs -K 12 -N 2 -l" -alias src_rws "st; rw -l; rs -K 6 -N 2 -l; rwz -l; rs -K 9 -N 2 -l; rwz -l; rs -K 12 -N 2 -l" -alias resyn2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b" -alias r2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b" -alias compress2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l" -alias c2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l" - -# use this script to convert 1-valued and DC-valued flops for an AIG -alias fix_aig "logic; undc; strash; zero" - -# use this script to convert 1-valued and DC-valued flops for a logic network coming from BLIF -alias fix_blif "undc; strash; zero" - -# lazy man's synthesis -alias recadd3 "st; rec_add3; b; rec_add3; dc2; rec_add3; if -K 8; bidec; st; rec_add3; dc2; rec_add3; if -g -K 6; st; rec_add3" - - diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 9d9b56a1c..ffd776cc4 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -31,6 +31,8 @@ ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// Vec_Int_t* vLitBmiter; +Vec_Int_t* vIdBI; +Vec_Int_t* vIdBO; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -5728,6 +5730,11 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int c1 = 0; int c2 = 0; int count; + int val; + + vIdBI = Vec_IntAlloc(16); + vIdBO = Vec_IntAlloc(16); + Gia_ManForEachBuf( p1, pObj, i ) { if ( count < n ) @@ -5782,6 +5789,7 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, // TODO: record hashed equivalent nodes + count = 0; Gia_ManForEachAnd( p1, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( Vec_IntEntry( vTypeSpec, Gia_ObjId( p1, pObj) ) > 0 ) @@ -5796,7 +5804,18 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, } } if ( Gia_ObjIsBuf(pObj) ) + { Vec_IntPush( vLits, pObj->Value ); + if ( count < n ) + { + Vec_IntPush( vIdBI, (pObj->Value) >> 1 ); + } + else + { + Vec_IntPush( vIdBO, (pObj->Value) >> 1 ); + } + count ++; + } } diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index dab809c25..755aeaea0 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -37921,7 +37921,7 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) int fCbs = 1, approxLim = 600, subBatchSz = 1, adaRecycle = 500, nMaxNodes = 0; Cec4_ManSetParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "JWRILDCNPMrmdckngxysopwqvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "OJWRILDCNPMrmdckngxysopwqvh" ) ) != EOF ) { switch ( c ) { @@ -37969,6 +37969,18 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nItersMax < 0 ) goto usage; break; + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nPO = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nPO < 1 ) + goto usage; + break; + case 'L': if ( globalUtilOptind >= argc ) { diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index ca4ac9aba..c9aa96658 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -121,6 +121,7 @@ struct Cec_ParFra_t_ int fVerbose; // verbose stats int iOutFail; // the failed output int fBMiterInfo; // printing BMiter information + int nPO; // number of po in original design given a bmiter }; // combinational equivalence checking parameters diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 4a39e95d3..a01cc7445 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -145,6 +145,9 @@ static inline void Cec4_ObjCleanSatId( Gia_Man_t * p, Gia_Obj_t * pObj ) extern Vec_Int_t* vLitBmiter; +extern Vec_Int_t* vIdBI; +extern Vec_Int_t* vIdBO; + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -1887,51 +1890,9 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p if ( Abc_Lit2Var(pObj->Value) == Abc_Lit2Var(pRepr->Value) ) { - // printf( "*node %d (%d) merged into node %d (%d)\n", lit_obj >> 1, Vec_IntEntry( vLitBmiter, lit_obj ), lit_repr >> 1, Vec_IntEntry( vLitBmiter, lit_repr) ); - if ( Vec_IntEntry( vLitBmiter, lit_repr ) == 3 ) + printf( "*node %d (%d) merged into node %d (%d)\n", lit_obj >> 1, Vec_IntEntry( vLitBmiter, lit_obj ), lit_repr >> 1, Vec_IntEntry( vLitBmiter, lit_repr) ); + if ( pPars->fBMiterInfo ) { - switch ( Vec_IntEntry( vLitBmiter, lit_obj ) ) - { - case 1: - case 4: - Vec_IntUpdateEntry( vLitBmiter, lit_repr, 4 ); - break; - case 2: - case 5: - Vec_IntUpdateEntry( vLitBmiter, lit_repr, 5 ); - break; - default: - break; - } - } - else - { - if ( Vec_IntEntry(vLitBmiter, lit_obj ) == 3 ) - switch ( Vec_IntEntry( vLitBmiter, lit_repr ) ) - { - case 1: - case 4: - Vec_IntUpdateEntry( vLitBmiter, lit_obj, 4 ); - break; - case 2: - case 5: - Vec_IntUpdateEntry( vLitBmiter, lit_obj, 5 ); - break; - default: - break; - - } - } - assert( (pObj->Value ^ pRepr->Value) == (pObj->fPhase ^ pRepr->fPhase) ); - Gia_ObjSetProved( p, i ); - if ( Gia_ObjId(p, pRepr) == 0 ) - pMan->iLastConst = i; - continue; - } - if ( Cec4_ManSweepNode(pMan, i, Gia_ObjId(p, pRepr)) && Gia_ObjProved(p, i) ) - { - if (pPars->fBMiterInfo){ - // printf( "node %d (%d) merged into node %d (%d)\n", lit_obj, Vec_IntEntry( vLitBmiter, lit_obj ), lit_repr, Vec_IntEntry( vLitBmiter, lit_repr ) ); if ( Vec_IntEntry( vLitBmiter, lit_repr ) == 3 ) { switch ( Vec_IntEntry( vLitBmiter, lit_obj ) ) @@ -1966,10 +1927,129 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p } } + // TODO + Vec_IntSetEntry( vLitBmiter, lit_obj, Vec_IntEntry( vLitBmiter, lit_repr) ); + } + assert( (pObj->Value ^ pRepr->Value) == (pObj->fPhase ^ pRepr->fPhase) ); + Gia_ObjSetProved( p, i ); + if ( Gia_ObjId(p, pRepr) == 0 ) + pMan->iLastConst = i; + continue; + } + if ( Cec4_ManSweepNode(pMan, i, Gia_ObjId(p, pRepr)) && Gia_ObjProved(p, i) ) + { + if (pPars->fBMiterInfo){ + printf( "node %d (%d) merged into node %d (%d)\n", lit_obj >> 1, Vec_IntEntry( vLitBmiter, lit_obj ), lit_repr >> 1, Vec_IntEntry( vLitBmiter, lit_repr ) ); + if ( Vec_IntEntry( vLitBmiter, lit_repr ) == 3 ) + { + switch ( Vec_IntEntry( vLitBmiter, lit_obj ) ) + { + case 1: + case 4: + Vec_IntUpdateEntry( vLitBmiter, lit_repr, 4 ); + break; + case 2: + case 5: + Vec_IntUpdateEntry( vLitBmiter, lit_repr, 5 ); + break; + default: + break; + } + } + else + { + if ( Vec_IntEntry(vLitBmiter, lit_obj ) == 3 ) + switch ( Vec_IntEntry( vLitBmiter, lit_repr ) ) + { + case 1: + case 4: + Vec_IntUpdateEntry( vLitBmiter, lit_obj, 4 ); + break; + case 2: + case 5: + Vec_IntUpdateEntry( vLitBmiter, lit_obj, 5 ); + break; + default: + break; + + } + } + // TODO + Vec_IntSetEntry( vLitBmiter, lit_obj, Vec_IntEntry( vLitBmiter, lit_repr) ); } pObj->Value = Abc_LitNotCond( pRepr->Value, pObj->fPhase ^ pRepr->fPhase ); } } + + + if ( pPars->fBMiterInfo ) + { + + // check bi, bo + Vec_Ptr_t* vBO = Vec_PtrAlloc( 16 ); + Vec_Ptr_t * vQ = Vec_PtrAlloc(16); + + int val; + printf("BI:"); + Vec_IntForEachEntry( vIdBI, val, i ) + { + printf( " %d (%d)", val, Vec_IntEntry( vLitBmiter, val << 1) ); + } + printf("\nBO:"); + Vec_IntForEachEntry( vIdBO, val, i ) + { + printf( " %d (%d)", val, Vec_IntEntry( vLitBmiter, val << 1) ); + if ( Vec_IntEntry( vLitBmiter, val << 1) != 5 ) + { + Vec_PtrPush(vQ, &((p->pObjs)[val]) ); + } + } + printf("\n"); + + // find bound + + Gia_ManStaticFanoutStart( p ); + + Vec_Int_t* vFlag = Vec_IntAlloc( p->nObjs ); + Vec_IntFill( vFlag, p->nObjs, 0 ); + Gia_Obj_t * pObj2; + int cnt_node = 0; + int cnt_newBo = 0; + + while ( Vec_PtrSize(vQ) != 0 ) + { + pObj2 = Vec_PtrPop(vQ); + if ( Vec_IntEntry( vFlag, Gia_ObjId(p, pObj2) ) != 0 ) continue; + cnt_node ++; + Vec_IntSetEntry( vFlag, Gia_ObjId(p, pObj2), 1 ); + + val = Vec_IntEntry(vLitBmiter, Gia_ObjId(p, pObj2) << 1); + if ( val == 5 || Gia_ObjIsCo( pObj2 ) ) // boundary found + { + cnt_newBo ++; + Vec_PtrPush( vBO, pObj2 ); + continue; + } + + for( int j = 0; j < Gia_ObjFanoutNum(p, pObj2); j++ ) + { + Vec_PtrPush( vQ, Gia_ObjFanout(p, pObj2, j) ); + printf( "add fanout\n"); + } + } + + Gia_ManStaticFanoutStop(p); + + + printf("extended BO with %d extra nodes:", cnt_node); + Vec_PtrForEachEntry( Gia_Obj_t*, vBO, pObj, i ) + { + printf( " %d", Gia_ObjId(p, pObj) ); + } + printf("\n"); + } + + if ( p->iPatsPi > 0 ) { abctime clk2 = Abc_Clock(); From 16a3c5fc30dddd3dfeb8c815fda22b608a0bf8ce Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 9 Dec 2023 21:53:48 +0800 Subject: [PATCH 061/151] Add copying names in &saveaig and &loadaig. --- src/aig/gia/giaDup.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index db4072d71..dbedca099 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -788,6 +788,11 @@ Gia_Man_t * Gia_ManDupWithAttributes( Gia_Man_t * p ) pNew->vConfigs = Vec_IntDup( p->vConfigs ); if ( p->pCellStr ) pNew->pCellStr = Abc_UtilStrsav( p->pCellStr ); + // copy names if present + if ( p->vNamesIn ) + pNew->vNamesIn = Vec_PtrDupStr( p->vNamesIn ); + if ( p->vNamesOut ) + pNew->vNamesOut = Vec_PtrDupStr( p->vNamesOut ); return pNew; } Gia_Man_t * Gia_ManDupRemovePis( Gia_Man_t * p, int nRemPis ) From 284b9d6a9c01c7df0636a696fc35a47d10f10f0a Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Sun, 10 Dec 2023 21:30:46 +0800 Subject: [PATCH 062/151] extended box report; --- src/aig/gia/giaDup.c | 68 ++++++++++++++---- src/base/abci/abc.c | 14 +--- src/proof/cec/cecSatG2.c | 150 +++++++++++++++++++++++++++------------ 3 files changed, 160 insertions(+), 72 deletions(-) diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index ffd776cc4..aa8f1c053 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -30,7 +30,7 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -Vec_Int_t* vLitBmiter; +Vec_Int_t* vMarkBmiter; Vec_Int_t* vIdBI; Vec_Int_t* vIdBO; @@ -5701,18 +5701,24 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, Gia_ManHashStart( pNew ); Gia_ManConst0(p1)->Value = 0; Gia_ManConst0(p2)->Value = 0; + + // allocate vMarkBmiter + vMarkBmiter = Vec_IntAlloc( (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)) ); + Vec_IntFill( vMarkBmiter, (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)), 0 ); + printf( "allocated size: %d\n", Vec_IntSize(vMarkBmiter) ); + Gia_ManForEachCi( p1, pObj, i ) - pObj->Value = Gia_ManCi(p2, i)->Value = Gia_ManAppendCi( pNew ); + { + int id = pObj->Value = Gia_ManCi(p2, i)->Value = Gia_ManAppendCi( pNew ); + Vec_IntSetEntry( vMarkBmiter, id >> 1, 4 ); + } // TODO: record the corresponding impl node of each lit - vLitBmiter = Vec_IntAlloc( (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)) * 2 ); - Vec_IntFill( vLitBmiter, (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)) * 2, 0 ); - printf( "allocated size: %d\n", Vec_IntSize(vLitBmiter) ); Gia_ManForEachAnd( p2, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - Vec_IntUpdateEntry( vLitBmiter, pObj->Value, 3 ); + Vec_IntUpdateEntry( vMarkBmiter, pObj->Value >> 1, 3 ); } // TODO: find nodes in spec @@ -5726,11 +5732,11 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, Gia_ManStaticFanoutStart( p1 ); Vec_Ptr_t * vQ = Vec_PtrAlloc(16); + Vec_Ptr_t * vBO = Vec_PtrAlloc(16); Gia_Obj_t * pObj2; int c1 = 0; int c2 = 0; - int count; - int val; + int count = 0; vIdBI = Vec_IntAlloc(16); vIdBO = Vec_IntAlloc(16); @@ -5759,6 +5765,7 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, else { Vec_IntSetEntry( vTypeSpec, Gia_ObjId( p1, pObj ), 2 ); + Vec_PtrPush( vBO, pObj ); c2 ++; int j; @@ -5782,6 +5789,37 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, } } + Vec_Int_t* vFlag = Vec_IntAlloc( Gia_ManObjNum(p1) ); + Vec_IntFill( vFlag, Gia_ManObjNum(p1), 0 ); + int id; + int count_node = 0; + + // count nodes + Vec_PtrForEachEntry( Gia_Obj_t*, vBO, pObj, i ) + { + Vec_PtrPush( vQ, pObj ); + } + while( Vec_PtrSize(vQ) > 0 ) + { + pObj = Vec_PtrPop(vQ); + id = Gia_ObjId( p1, pObj ); + if ( Vec_IntEntry( vFlag, Gia_ObjId(p1, pObj) ) != 0 ) continue; + Vec_IntSetEntry( vFlag, Gia_ObjId(p1, pObj), 1 ); + count_node ++; + + if ( Vec_IntEntry( vTypeSpec, id ) == 1 ) + { + continue; + } + else + { + if ( Gia_ObjFaninNum(p1, pObj) > 0 ) Vec_PtrPush( vQ, Gia_ObjFanin0(pObj) ); + if ( Gia_ObjFaninNum(p1, pObj) > 1 ) Vec_PtrPush( vQ, Gia_ObjFanin1(pObj) ); + } + } + printf( "BI: %d, BO: %d, Box Size: %d\n", n, Gia_ManBufNum(p1)-n, count_node ); + + Gia_ManStaticFanoutStop( p1 ); printf( "spec: fanin: %d / fanout: %d / total %d\n", c1, c2, Gia_ManObjNum(p1) ); @@ -5794,13 +5832,13 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( Vec_IntEntry( vTypeSpec, Gia_ObjId( p1, pObj) ) > 0 ) { - if ( Vec_IntGetEntry( vLitBmiter, pObj->Value ) == 3 ) // eq node in impl + if ( Vec_IntGetEntry( vMarkBmiter, pObj->Value >> 1 ) == 3 ) // eq node in impl { - Vec_IntUpdateEntry( vLitBmiter, pObj->Value, 3 + Vec_IntEntry( vTypeSpec, Gia_ObjId( p1, pObj) ) ); + Vec_IntUpdateEntry( vMarkBmiter, pObj->Value >> 1, 3 + Vec_IntEntry( vTypeSpec, Gia_ObjId( p1, pObj) ) ); } else { - Vec_IntUpdateEntry( vLitBmiter, pObj->Value, Vec_IntEntry( vTypeSpec, Gia_ObjId( p1, pObj) ) ); + Vec_IntUpdateEntry( vMarkBmiter, pObj->Value >> 1, Vec_IntEntry( vTypeSpec, Gia_ObjId( p1, pObj) ) ); } } if ( Gia_ObjIsBuf(pObj) ) @@ -5822,9 +5860,8 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int e, c3=0, c4=0, c5=0; c1 = 0; c2 = 0; - Vec_IntForEachEntry( vLitBmiter, e, i ) + Vec_IntForEachEntry( vMarkBmiter, e, i ) { - if ( i%2 ) continue; switch (e) { case 1: c1++; break; @@ -5839,7 +5876,10 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, printf("(strash) impl: eq_fanin: %d / eq_fanout: %d / total: %d\n", c4, c5, c3+c4+c5); Gia_ManForEachCo( p2, pObj, i ) - Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + { + int id = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ) << 1; + Vec_IntSetEntry( vMarkBmiter, id, 5 ); + } Gia_ManForEachCo( p1, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Vec_IntForEachEntry( vLits, iLit, i ) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 755aeaea0..dab809c25 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -37921,7 +37921,7 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) int fCbs = 1, approxLim = 600, subBatchSz = 1, adaRecycle = 500, nMaxNodes = 0; Cec4_ManSetParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "OJWRILDCNPMrmdckngxysopwqvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "JWRILDCNPMrmdckngxysopwqvh" ) ) != EOF ) { switch ( c ) { @@ -37969,18 +37969,6 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nItersMax < 0 ) goto usage; break; - case 'O': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nPO = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nPO < 1 ) - goto usage; - break; - case 'L': if ( globalUtilOptind >= argc ) { diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index a01cc7445..7377367e2 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -144,7 +144,7 @@ static inline int Cec4_ObjSetSatId( Gia_Man_t * p, Gia_Obj_t * pObj, int Num static inline void Cec4_ObjCleanSatId( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert(Cec4_ObjSatId(p, pObj) != -1); Gia_ObjSetCopy2Array(p, Gia_ObjId(p, pObj), -1); } -extern Vec_Int_t* vLitBmiter; +extern Vec_Int_t* vMarkBmiter; extern Vec_Int_t* vIdBI; extern Vec_Int_t* vIdBO; @@ -1885,25 +1885,25 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p if ( pRepr == NULL ) continue; } - int lit_obj = Gia_ObjId( p, pObj ) << 1; - int lit_repr = Gia_ObjId( p, pRepr ) << 1; + int id_obj = Gia_ObjId( p, pObj ); + int id_repr = Gia_ObjId( p, pRepr ); if ( Abc_Lit2Var(pObj->Value) == Abc_Lit2Var(pRepr->Value) ) { - printf( "*node %d (%d) merged into node %d (%d)\n", lit_obj >> 1, Vec_IntEntry( vLitBmiter, lit_obj ), lit_repr >> 1, Vec_IntEntry( vLitBmiter, lit_repr) ); + // printf( "*node %d (%d) merged into node %d (%d)\n", id_obj, Vec_IntEntry( vMarkBmiter, id_obj ), id_repr, Vec_IntEntry( vMarkBmiter, id_repr) ); if ( pPars->fBMiterInfo ) { - if ( Vec_IntEntry( vLitBmiter, lit_repr ) == 3 ) + if ( Vec_IntEntry( vMarkBmiter, id_repr ) == 3 ) { - switch ( Vec_IntEntry( vLitBmiter, lit_obj ) ) + switch ( Vec_IntEntry( vMarkBmiter, id_obj ) ) { case 1: case 4: - Vec_IntUpdateEntry( vLitBmiter, lit_repr, 4 ); + Vec_IntUpdateEntry( vMarkBmiter, id_repr, 4 ); break; case 2: case 5: - Vec_IntUpdateEntry( vLitBmiter, lit_repr, 5 ); + Vec_IntUpdateEntry( vMarkBmiter, id_repr, 5 ); break; default: break; @@ -1911,16 +1911,16 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p } else { - if ( Vec_IntEntry(vLitBmiter, lit_obj ) == 3 ) - switch ( Vec_IntEntry( vLitBmiter, lit_repr ) ) + if ( Vec_IntEntry(vMarkBmiter, id_obj ) == 3 ) + switch ( Vec_IntEntry( vMarkBmiter, id_repr ) ) { case 1: case 4: - Vec_IntUpdateEntry( vLitBmiter, lit_obj, 4 ); + Vec_IntUpdateEntry( vMarkBmiter, id_obj, 4 ); break; case 2: case 5: - Vec_IntUpdateEntry( vLitBmiter, lit_obj, 5 ); + Vec_IntUpdateEntry( vMarkBmiter, id_obj, 5 ); break; default: break; @@ -1928,7 +1928,7 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p } } // TODO - Vec_IntSetEntry( vLitBmiter, lit_obj, Vec_IntEntry( vLitBmiter, lit_repr) ); + Vec_IntSetEntry( vMarkBmiter, id_obj, Vec_IntEntry( vMarkBmiter, id_repr) ); } assert( (pObj->Value ^ pRepr->Value) == (pObj->fPhase ^ pRepr->fPhase) ); Gia_ObjSetProved( p, i ); @@ -1939,18 +1939,18 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p if ( Cec4_ManSweepNode(pMan, i, Gia_ObjId(p, pRepr)) && Gia_ObjProved(p, i) ) { if (pPars->fBMiterInfo){ - printf( "node %d (%d) merged into node %d (%d)\n", lit_obj >> 1, Vec_IntEntry( vLitBmiter, lit_obj ), lit_repr >> 1, Vec_IntEntry( vLitBmiter, lit_repr ) ); - if ( Vec_IntEntry( vLitBmiter, lit_repr ) == 3 ) + // printf( "node %d (%d) merged into node %d (%d)\n", id_obj, Vec_IntEntry( vMarkBmiter, id_obj ), id_repr, Vec_IntEntry( vMarkBmiter, id_repr ) ); + if ( Vec_IntEntry( vMarkBmiter, id_repr ) == 3 ) { - switch ( Vec_IntEntry( vLitBmiter, lit_obj ) ) + switch ( Vec_IntEntry( vMarkBmiter, id_obj ) ) { case 1: case 4: - Vec_IntUpdateEntry( vLitBmiter, lit_repr, 4 ); + Vec_IntUpdateEntry( vMarkBmiter, id_repr, 4 ); break; case 2: case 5: - Vec_IntUpdateEntry( vLitBmiter, lit_repr, 5 ); + Vec_IntUpdateEntry( vMarkBmiter, id_repr, 5 ); break; default: break; @@ -1958,16 +1958,16 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p } else { - if ( Vec_IntEntry(vLitBmiter, lit_obj ) == 3 ) - switch ( Vec_IntEntry( vLitBmiter, lit_repr ) ) + if ( Vec_IntEntry(vMarkBmiter, id_obj ) == 3 ) + switch ( Vec_IntEntry( vMarkBmiter, id_repr ) ) { case 1: case 4: - Vec_IntUpdateEntry( vLitBmiter, lit_obj, 4 ); + Vec_IntUpdateEntry( vMarkBmiter, id_obj, 4 ); break; case 2: case 5: - Vec_IntUpdateEntry( vLitBmiter, lit_obj, 5 ); + Vec_IntUpdateEntry( vMarkBmiter, id_obj, 5 ); break; default: break; @@ -1975,7 +1975,7 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p } } // TODO - Vec_IntSetEntry( vLitBmiter, lit_obj, Vec_IntEntry( vLitBmiter, lit_repr) ); + Vec_IntSetEntry( vMarkBmiter, id_obj, Vec_IntEntry( vMarkBmiter, id_repr) ); } pObj->Value = Abc_LitNotCond( pRepr->Value, pObj->fPhase ^ pRepr->fPhase ); } @@ -1986,67 +1986,128 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p { // check bi, bo - Vec_Ptr_t* vBO = Vec_PtrAlloc( 16 ); - Vec_Ptr_t * vQ = Vec_PtrAlloc(16); - + Vec_Ptr_t* vAO = Vec_PtrAlloc( 16 ); // additioal output boundary + Vec_Ptr_t* vAI = Vec_PtrAlloc( 16 ); // additional input boundary + Vec_Ptr_t* vMI = Vec_PtrAlloc(16); // missing input boundary + Vec_Ptr_t* vMO = Vec_PtrAlloc(16); // missing input boundary + Vec_Ptr_t* vQ = Vec_PtrAlloc(16); // queue for fanout traversal int val; + int cnt_TO = 0; + int cnt_TI = 0; + int cnt_SIDE = 0; + int cnt_MI = 0; + int cnt_MO = 0; + Vec_Int_t* vFlag = Vec_IntAlloc( p->nObjs ); + Vec_IntFill( vFlag, p->nObjs, 0 ); + printf("BI:"); Vec_IntForEachEntry( vIdBI, val, i ) { - printf( " %d (%d)", val, Vec_IntEntry( vLitBmiter, val << 1) ); + printf( " %d (%d)", val, Vec_IntEntry( vMarkBmiter, val) ); + if ( Vec_IntEntry( vMarkBmiter, val) <= 3 ) + { + Vec_PtrPush(vMI, &((p->pObjs)[val]) ); + } + else cnt_MI ++; } printf("\nBO:"); Vec_IntForEachEntry( vIdBO, val, i ) { - printf( " %d (%d)", val, Vec_IntEntry( vLitBmiter, val << 1) ); - if ( Vec_IntEntry( vLitBmiter, val << 1) != 5 ) + printf( " %d (%d)", val, Vec_IntEntry( vMarkBmiter, val) ); + if ( Vec_IntEntry( vMarkBmiter, val) <= 3 ) { Vec_PtrPush(vQ, &((p->pObjs)[val]) ); + Vec_PtrPush(vMO, &((p->pObjs)[val]) ); + Vec_IntSetEntry( vFlag, val, 2 ); } + else cnt_MO ++; } printf("\n"); - // find bound + // find extended output boundary Gia_ManStaticFanoutStart( p ); - Vec_Int_t* vFlag = Vec_IntAlloc( p->nObjs ); - Vec_IntFill( vFlag, p->nObjs, 0 ); Gia_Obj_t * pObj2; - int cnt_node = 0; - int cnt_newBo = 0; + cnt_TO -= Vec_PtrSize(vQ); while ( Vec_PtrSize(vQ) != 0 ) { pObj2 = Vec_PtrPop(vQ); - if ( Vec_IntEntry( vFlag, Gia_ObjId(p, pObj2) ) != 0 ) continue; - cnt_node ++; + if ( Vec_IntEntry( vFlag, Gia_ObjId(p, pObj2) ) == 1 ) continue; Vec_IntSetEntry( vFlag, Gia_ObjId(p, pObj2), 1 ); + cnt_TO ++; - val = Vec_IntEntry(vLitBmiter, Gia_ObjId(p, pObj2) << 1); + val = Vec_IntEntry(vMarkBmiter, Gia_ObjId(p, pObj2)); if ( val == 5 || Gia_ObjIsCo( pObj2 ) ) // boundary found { - cnt_newBo ++; - Vec_PtrPush( vBO, pObj2 ); + Vec_PtrPush( vAO, pObj2 ); continue; } for( int j = 0; j < Gia_ObjFanoutNum(p, pObj2); j++ ) { Vec_PtrPush( vQ, Gia_ObjFanout(p, pObj2, j) ); - printf( "add fanout\n"); } } Gia_ManStaticFanoutStop(p); - printf("extended BO with %d extra nodes:", cnt_node); - Vec_PtrForEachEntry( Gia_Obj_t*, vBO, pObj, i ) + // find extneded input boundary + + Vec_PtrForEachEntry( Gia_Obj_t*, vMO, pObj, i ) + { + Vec_IntSetEntry( vFlag, Gia_ObjId(p, pObj), 2 ); + } + + int id; + Vec_PtrForEachEntry( Gia_Obj_t*, vMI, pObj, i ) Vec_PtrPush( vQ, pObj ); + Vec_PtrForEachEntry( Gia_Obj_t*, vAO, pObj, i ) Vec_PtrPush( vQ, pObj ); + cnt_TI -= Vec_PtrSize(vQ); + while ( Vec_PtrSize(vQ) > 0 ) + { + pObj = Vec_PtrPop(vQ); + id = Gia_ObjId( p, pObj ); + if ( Vec_IntEntry( vFlag, id ) == 2 ) continue; + printf( "backtrace to node %d\n", id ); + if ( Vec_IntEntry(vMarkBmiter, id ) != 2 ) cnt_TI ++; + Vec_IntSetEntry( vFlag, id, 2 ); + + + if ( Vec_IntEntry( vMarkBmiter, id ) >= 3 || Gia_ObjIsCi( pObj ) ) // matched + { + if ( Vec_IntEntry( vMarkBmiter, id ) < 5 || Gia_ObjIsCi( pObj ) ) + { + Vec_PtrPush( vAI, pObj ); + } + continue; + } + else + { + if ( Gia_ObjFaninNum(p, pObj) > 0 ) Vec_PtrPush( vQ, Gia_ObjFanin0(pObj) ); + if ( Gia_ObjFaninNum(p, pObj) > 1 ) Vec_PtrPush( vQ, Gia_ObjFanin1(pObj) ); + } + } + + + // print result + printf("extended BO with %d extra nodes:", cnt_TO); + Vec_PtrForEachEntry( Gia_Obj_t*, vAO, pObj, i ) { printf( " %d", Gia_ObjId(p, pObj) ); } printf("\n"); + + printf("extended BI with %d extra nodes:", cnt_TI); + Vec_PtrForEachEntry( Gia_Obj_t*, vAI, pObj, i ) + { + printf( " %d", Gia_ObjId(p, pObj) ); + } + printf("\n"); + + printf("matched BI: %d / matched BO: %d / AI: %d / AO: %d / Extra nodes: %d\n", cnt_MI, cnt_MO, Vec_PtrSize(vAI), Vec_PtrSize(vAO), cnt_TO + cnt_TI ); + } @@ -2094,7 +2155,7 @@ finalize: Gia_ManRemoveWrongChoices( p ); return p->pCexSeq ? 0 : 1; } -extern Vec_Int_t * vLitBmiter; +extern Vec_Int_t * vMarkBmiter; Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ) { Gia_Man_t * pNew = NULL; @@ -2103,9 +2164,8 @@ Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ) // TODO if (pPars -> fBMiterInfo){ int e, i, c1=0, c2=0, c3=0, c4=0, c5=0; - Vec_IntForEachEntry( vLitBmiter, e, i ) + Vec_IntForEachEntry( vMarkBmiter, e, i ) { - if ( i%2 ) continue; switch (e) { case 1: c1++; break; From 7fe92148ccddd86431b438d25afc0740e71de525 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 18 Dec 2023 21:04:31 +0900 Subject: [PATCH 063/151] New command to put computation to sleep. --- src/base/cmd/cmd.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index 708fc3f5b..5a752a5d4 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -37,6 +37,7 @@ ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// static int CmdCommandTime ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandSleep ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandEcho ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandQuit ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandAbcrc ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -90,6 +91,7 @@ void Cmd_Init( Abc_Frame_t * pAbc ) Cmd_HistoryRead( pAbc ); Cmd_CommandAdd( pAbc, "Basic", "time", CmdCommandTime, 0 ); + Cmd_CommandAdd( pAbc, "Basic", "sleep", CmdCommandSleep, 0 ); Cmd_CommandAdd( pAbc, "Basic", "echo", CmdCommandEcho, 0 ); Cmd_CommandAdd( pAbc, "Basic", "quit", CmdCommandQuit, 0 ); Cmd_CommandAdd( pAbc, "Basic", "abcrc", CmdCommandAbcrc, 0 ); @@ -228,6 +230,54 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv ) return 1; } +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandSleep( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + abctime clkStop; + int c, nSecs = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nSecs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSecs < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + clkStop = Abc_Clock() + nSecs * CLOCKS_PER_SEC; + while ( Abc_Clock() < clkStop ); + return 0; + + usage: + fprintf( pAbc->Err, "usage: sleep [-N ] [-h]\n" ); + fprintf( pAbc->Err, " puts ABC to sleep for the given time\n" ); + fprintf( pAbc->Err, "-N num time in seconds [default = %d]\n", nSecs ); + fprintf( pAbc->Err, "-h print the command usage\n" ); + return 1; +} /**Function******************************************************************** Synopsis [] From 706112ebd8d84c7bd2e5fa7b589eb88319cb2636 Mon Sep 17 00:00:00 2001 From: Rasmus Munk Larsen Date: Tue, 19 Dec 2023 16:13:52 -0800 Subject: [PATCH 064/151] Micro-optimizations to speed up the Liberty parser by ~1.67x. Signed-off-by: Rasmus Munk Larsen --- src/map/scl/sclLiberty.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/map/scl/sclLiberty.c b/src/map/scl/sclLiberty.c index 3d62b68e5..d853f557b 100644 --- a/src/map/scl/sclLiberty.c +++ b/src/map/scl/sclLiberty.c @@ -281,26 +281,38 @@ static inline char * Scl_LibertyFindMatch( char * pPos, char * pEnd ) assert( *pPos == '(' || *pPos == '{' ); if ( *pPos == '(' ) { - for ( ; pPos < pEnd; pPos++ ) - { - if ( *pPos == '(' ) + ++Counter; + ++pPos; + for ( ; pPos < pEnd; pPos++ ) + { + // Invariant: Counter > 0. + if ( *pPos == '(' ) { Counter++; - if ( *pPos == ')' ) + continue; + } + else if ( *pPos == ')' ) { Counter--; - if ( Counter == 0 ) - break; + if ( Counter == 0 ) + break; + } } } else { + ++Counter; + ++pPos; for ( ; pPos < pEnd; pPos++ ) { - if ( *pPos == '{' ) + // Invariant: Counter > 0. + if ( *pPos == '{' ) { Counter++; - if ( *pPos == '}' ) + continue; + } + else if ( *pPos == '}' ) { Counter--; - if ( Counter == 0 ) - break; + if ( Counter == 0 ) + break; + } } } assert( *pPos == ')' || *pPos == '}' ); @@ -317,10 +329,14 @@ static inline Scl_Pair_t Scl_LibertyUpdateHead( Scl_Tree_t * p, Scl_Pair_t Head char * pChar; for ( pChar = pBeg; pChar < pEnd; pChar++ ) { - if ( *pChar == '\n' ) + if ( *pChar == '\n' ) { p->nLines++; - if ( Scl_LibertyCharIsSpace(*pChar) ) + // Note: Scl_LibertyCharIsSpace returns true for '\n', so we can + // continue here and save the call to Scl_LibertyCharIsSpace. continue; + } else if ( Scl_LibertyCharIsSpace(*pChar) ) { + continue; + } pLastNonSpace = pChar; if ( pFirstNonSpace == NULL ) pFirstNonSpace = pChar; From 5978ccdb52394f2e92df41a895335eced0c4fe7a Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 21 Dec 2023 12:16:33 +0900 Subject: [PATCH 065/151] Updating sleep command to wait for file. --- src/base/cmd/cmd.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index 5a752a5d4..a18387acd 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -244,6 +244,7 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv ) int CmdCommandSleep( Abc_Frame_t * pAbc, int argc, char **argv ) { abctime clkStop; + char * pFileName = NULL; int c, nSecs = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) @@ -267,15 +268,25 @@ int CmdCommandSleep( Abc_Frame_t * pAbc, int argc, char **argv ) goto usage; } } + + if ( argc == globalUtilOptind + 1 ) { + FILE * pFile = NULL; + pFileName = argv[globalUtilOptind]; + while ( (pFile = fopen(pFileName, "rb")) == NULL ); + if ( pFile != NULL ) + fclose( pFile ); + } + clkStop = Abc_Clock() + nSecs * CLOCKS_PER_SEC; while ( Abc_Clock() < clkStop ); return 0; usage: - fprintf( pAbc->Err, "usage: sleep [-N ] [-h]\n" ); - fprintf( pAbc->Err, " puts ABC to sleep for the given time\n" ); - fprintf( pAbc->Err, "-N num time in seconds [default = %d]\n", nSecs ); - fprintf( pAbc->Err, "-h print the command usage\n" ); + fprintf( pAbc->Err, "usage: sleep [-N ] [-h] \n" ); + fprintf( pAbc->Err, "\t puts ABC to sleep for some time\n" ); + fprintf( pAbc->Err, "\t-N num : time duration in seconds [default = %d]\n", nSecs ); + fprintf( pAbc->Err, "\t-h : toggle printing the command usage\n" ); + fprintf( pAbc->Err, "\t : (optional) waiting begins after the file is created\n" ); return 1; } /**Function******************************************************************** From 7dcc10a254e780ca7c8e6047f0cc03b7717a148a Mon Sep 17 00:00:00 2001 From: aletempiac Date: Wed, 10 Jan 2024 15:18:39 +0100 Subject: [PATCH 066/151] Minor fixes --- src/acd/ac_decomposition.hpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 2b3161476..64155b713 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -174,7 +174,7 @@ public: return; generate_decomposition(); - return get_decomposition_abc( decompArray ); + get_decomposition_abc( decompArray ); } private: @@ -264,9 +264,12 @@ private: return false; /* estimation on number of LUTs */ - pst->num_luts = best_multiplicity <= 2 ? 2 : best_multiplicity <= 4 ? 3 - : best_multiplicity <= 8 ? 4 - : 5; + if ( pst ) + { + pst->num_luts = best_multiplicity <= 2 ? 2 : best_multiplicity <= 4 ? 3 + : best_multiplicity <= 8 ? 4 + : 5; + } return true; } @@ -799,7 +802,7 @@ private: best_iset_offset.push_back( offset ); } - if ( pst != nullptr ) + if ( pst ) { pst->num_luts = num_luts; pst->num_levels = num_levels; @@ -868,7 +871,7 @@ private: best_iset_offset.push_back( offset ); } - if ( pst != nullptr ) + if ( pst ) { pst->num_luts = num_luts; pst->num_levels = num_levels; From dc68fe27f904ccd14932256db4d2579095021c0d Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 11 Jan 2024 19:45:42 -0800 Subject: [PATCH 067/151] Saving module interface. --- src/base/wlc/wlc.h | 2 +- src/base/wlc/wlcBlast.c | 65 +++++++++++++++++++++++++++++++++++++++ src/base/wlc/wlcCom.c | 18 ++++++++--- src/base/wlc/wlcReadVer.c | 31 ++++++++++++++++--- 4 files changed, 107 insertions(+), 9 deletions(-) diff --git a/src/base/wlc/wlc.h b/src/base/wlc/wlc.h index 0b3bed6c0..ac4743338 100644 --- a/src/base/wlc/wlc.h +++ b/src/base/wlc/wlc.h @@ -448,7 +448,7 @@ extern void Wlc_NtkDeleteSim( Vec_Ptr_t * p ); extern int Wlc_StdinProcessSmt( Abc_Frame_t * pAbc, char * pCmd ); /*=== wlcReadVer.c ========================================================*/ extern char * Wlc_PrsConvertInitValues( Wlc_Ntk_t * p ); -extern Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr ); +extern Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr, int fInter ); /*=== wlcUif.c ========================================================*/ extern Vec_Int_t * Wlc_NtkCollectAddMult( Wlc_Ntk_t * p, Wlc_BstPar_t * pPar, int * pCountA, int * CountM ); extern int Wlc_NtkPairIsUifable( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Wlc_Obj_t * pObj2 ); diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c index 4ec1a4902..47d08da62 100644 --- a/src/base/wlc/wlcBlast.c +++ b/src/base/wlc/wlcBlast.c @@ -2667,6 +2667,71 @@ Vec_Int_t * Wlc_ComputePerm( Wlc_Ntk_t * pNtk, int nPis ) return vPerm; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wlc_TransferPioNames( Wlc_Ntk_t * p, Gia_Man_t * pNew ) +{ + int fSkipBitRange = 0; + Wlc_Obj_t * pObj; int i, k; + Vec_PtrFreeP( &pNew->vNamesIn ); + Vec_PtrFreeP( &pNew->vNamesOut ); + pNew->vNamesIn = Vec_PtrAlloc( Gia_ManPiNum(pNew) ); + pNew->vNamesOut = Vec_PtrAlloc( Gia_ManPoNum(pNew) ); + // create input names + Wlc_NtkForEachCi( p, pObj, i ) + if ( Wlc_ObjIsPi(pObj) ) + { + char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); + int nRange = Wlc_ObjRange( pObj ); + if ( fSkipBitRange && nRange == 1 ) + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(pName) ); + else + for ( k = 0; k < nRange; k++ ) + { + char Buffer[1000]; + sprintf( Buffer, "%s[%d]", pName, pObj->Beg < pObj->End ? pObj->Beg+k : pObj->Beg-k ); + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) ); + //printf( "Writing %s\n", Buffer ); + } + } + // add real primary outputs + Wlc_NtkForEachCo( p, pObj, i ) + if ( Wlc_ObjIsPo(pObj) ) + { + char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); + int nRange = Wlc_ObjRange( pObj ); + if ( fSkipBitRange && nRange == 1 ) + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(pName) ); + else + for ( k = 0; k < nRange; k++ ) + { + char Buffer[1000]; + sprintf( Buffer, "%s[%d]", pName, pObj->Beg < pObj->End ? pObj->Beg+k : pObj->Beg-k ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } + } + if ( Vec_PtrSize(pNew->vNamesIn) != Gia_ManPiNum(pNew) ) + printf( "The number of input bits (%d) does not match the number of primary inputs (%d) in the current AIG.\n", Vec_PtrSize(pNew->vNamesIn), Gia_ManPiNum(pNew) ); + if ( Vec_PtrSize(pNew->vNamesOut) != Gia_ManPoNum(pNew) ) + printf( "The number of output bits (%d) does not match the number of primary inputs (%d) in the current AIG.\n", Vec_PtrSize(pNew->vNamesOut), Gia_ManPoNum(pNew) ); + if ( Vec_PtrSize(pNew->vNamesIn) != Gia_ManPiNum(pNew) || Vec_PtrSize(pNew->vNamesOut) != Gia_ManPoNum(pNew) ) + { + Vec_PtrFreeP( &pNew->vNamesIn ); + Vec_PtrFreeP( &pNew->vNamesOut ); + } + else + printf( "Successfully transferred the primary input/output names from the word-level design to the current AIG.\n" ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/wlc/wlcCom.c b/src/base/wlc/wlcCom.c index 13192a1eb..d15a7723b 100644 --- a/src/base/wlc/wlcCom.c +++ b/src/base/wlc/wlcCom.c @@ -149,14 +149,16 @@ void Wlc_SetNtk( Abc_Frame_t * pAbc, Wlc_Ntk_t * pNtk ) ******************************************************************************/ int Abc_CommandReadWlc( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void Wlc_TransferPioNames( Wlc_Ntk_t * p, Gia_Man_t * pNew ); FILE * pFile; Wlc_Ntk_t * pNtk = NULL; char * pFileName = NULL; int fOldParser = 0; int fPrintTree = 0; + int fInter = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "opvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "opivh" ) ) != EOF ) { switch ( c ) { @@ -166,6 +168,9 @@ int Abc_CommandReadWlc( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'p': fPrintTree ^= 1; break; + case 'i': + fInter ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -193,8 +198,12 @@ int Abc_CommandReadWlc( Abc_Frame_t * pAbc, int argc, char ** argv ) fclose( pFile ); // perform reading - if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) - pNtk = Wlc_ReadVer( pFileName, NULL ); + if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) + { + pNtk = Wlc_ReadVer( pFileName, NULL, fInter ); + if ( fInter && pAbc->pGia ) + Wlc_TransferPioNames( pNtk, pAbc->pGia ); + } else if ( !strcmp( Extra_FileNameExtension(pFileName), "smt" ) || !strcmp( Extra_FileNameExtension(pFileName), "smt2" ) ) pNtk = Wlc_ReadSmt( pFileName, fOldParser, fPrintTree ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "ndr" ) ) @@ -207,10 +216,11 @@ int Abc_CommandReadWlc( Abc_Frame_t * pAbc, int argc, char ** argv ) Wlc_AbcUpdateNtk( pAbc, pNtk ); return 0; usage: - Abc_Print( -2, "usage: %%read [-opvh] \n" ); + Abc_Print( -2, "usage: %%read [-opivh] \n" ); Abc_Print( -2, "\t reads word-level design from Verilog file\n" ); Abc_Print( -2, "\t-o : toggle using old SMT-LIB parser [default = %s]\n", fOldParser? "yes": "no" ); Abc_Print( -2, "\t-p : toggle printing parse SMT-LIB tree [default = %s]\n", fPrintTree? "yes": "no" ); + Abc_Print( -2, "\t-i : toggle reading interface only [default = %s]\n", fInter? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; diff --git a/src/base/wlc/wlcReadVer.c b/src/base/wlc/wlcReadVer.c index aff3eae8a..f31528ea6 100644 --- a/src/base/wlc/wlcReadVer.c +++ b/src/base/wlc/wlcReadVer.c @@ -951,7 +951,7 @@ int Wlc_PrsReadDeclaration( Wlc_Prs_t * p, char * pStart ) } return 1; } -int Wlc_PrsDerive( Wlc_Prs_t * p ) +int Wlc_PrsDerive( Wlc_Prs_t * p, int fInter ) { Wlc_Obj_t * pObj; char * pStart, * pName; @@ -1031,6 +1031,8 @@ startword: while ( (pName = Wlc_PrsStrtok( NULL, "(,)" )) ) { pName = Wlc_PrsSkipSpaces( pName ); + if ( fInter && Wlc_PrsStrCmp( pName, "wire" ) ) + return 0; if ( Wlc_PrsStrCmp( pName, "input" ) || Wlc_PrsStrCmp( pName, "output" ) || Wlc_PrsStrCmp( pName, "wire" ) ) { if ( !Wlc_PrsReadDeclaration( p, pName ) ) @@ -1095,12 +1097,16 @@ startword: // these are read as part of the interface else if ( Wlc_PrsStrCmp( pStart, "input" ) || Wlc_PrsStrCmp( pStart, "output" ) || Wlc_PrsStrCmp( pStart, "wire" ) || Wlc_PrsStrCmp( pStart, "reg" ) ) { + if ( fInter && (Wlc_PrsStrCmp( pStart, "wire" ) || Wlc_PrsStrCmp( pStart, "reg" )) ) + return 0; if ( !Wlc_PrsReadDeclaration( p, pStart ) ) return 0; } else if ( Wlc_PrsStrCmp( pStart, "assign" ) ) { int Type, NameId, fFound, XValue = 0; + if ( fInter ) + return 0; pStart += strlen("assign"); // read name pStart = Wlc_PrsFindName( pStart, &pName ); @@ -1159,6 +1165,8 @@ startword: { // THIS IS A HACK to detect always statement representing combinational MUX int NameId, NameIdOut = -1, fFound, nValues, fDefaultFound = 0; + if ( fInter ) + return 0; // find control pStart = Wlc_PrsFindWord( pStart, "case", &fFound ); if ( pStart == NULL ) @@ -1682,7 +1690,7 @@ startword: } return 1; } -Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr ) +Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr, int fInter ) { Wlc_Prs_t * p; Wlc_Ntk_t * pNtk = NULL; @@ -1696,8 +1704,23 @@ Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr ) if ( !Wlc_PrsPrepare( p ) ) goto finish; // parse models - if ( !Wlc_PrsDerive( p ) ) + if ( !Wlc_PrsDerive( p, fInter ) ) + { + if ( fInter ) + { + printf( "Finished deriving interface for module \"%s\".\n", p->pNtk->pName ); + pNtk = p->pNtk; p->pNtk = NULL; + pNtk->pSpec = Abc_UtilStrsav( pFileName ); + if ( Vec_IntSize(&pNtk->vNameIds) == 0 ) + { + Vec_Int_t * vTemp = Vec_IntStartNatural( Wlc_NtkObjNumMax(pNtk) ); + pNtk->vNameIds = *vTemp, Vec_IntZero(vTemp); + Vec_IntFree( vTemp ); + } + return pNtk; + } goto finish; + } // derive topological order if ( p->pNtk ) { @@ -1728,7 +1751,7 @@ finish: void Io_ReadWordTest( char * pFileName ) { Gia_Man_t * pNew; - Wlc_Ntk_t * pNtk = Wlc_ReadVer( pFileName, NULL ); + Wlc_Ntk_t * pNtk = Wlc_ReadVer( pFileName, NULL, 0 ); if ( pNtk == NULL ) return; Wlc_WriteVer( pNtk, "test.v", 0, 0 ); From 8c7327b8df411654b7d38ccb678c500049fc2b5b Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 11 Jan 2024 22:19:50 -0800 Subject: [PATCH 068/151] Recognizing interface of the module when writing Verilog. --- src/aig/gia/giaMan.c | 133 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 123 insertions(+), 10 deletions(-) diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index e771f99cc..e8fd9f1d8 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -1787,6 +1787,101 @@ void Gia_ManDumpVerilogNoInterAssign( Gia_Man_t * p, char * pFileName, Vec_Int_t Gia_ManSetRegNum( p, nRegs ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintOneName( FILE * pFile, char * pName, int Size ) +{ + int i; + for ( i = 0; i < Size; i++ ) + fprintf( pFile, "%c", pName[i] ); +} +int Gia_ManCountSymbs( char * pName ) +{ + int i; + for ( i = 0; pName[i]; i++ ) + if ( pName[i] == '[' ) + break; + return i; +} +int Gia_ManReadRangeNum( char * pName, int Size ) +{ + if ( pName[Size] == 0 ) + return -1; + assert( pName[Size] == '[' ); + return atoi(pName+Size+1); +} +Vec_Int_t * Gia_ManCountSymbsAll( Vec_Ptr_t * vNames ) +{ + char * pNameLast = (char *)Vec_PtrEntry(vNames, 0), * pName; + int i, nSymbsLast = Gia_ManCountSymbs(pNameLast); + Vec_Int_t * vArray = Vec_IntAlloc( Vec_PtrSize(vNames) * 2 ); + Vec_IntPush( vArray, 0 ); + Vec_IntPush( vArray, nSymbsLast ); + Vec_PtrForEachEntryStart( char *, vNames, pName, i, 1 ) + { + int nSymbs = Gia_ManCountSymbs(pName); + if ( nSymbs == nSymbsLast && !strncmp(pName, pNameLast, nSymbsLast) ) + continue; + Vec_IntPush( vArray, i ); + Vec_IntPush( vArray, nSymbs ); + pNameLast = pName; + nSymbsLast = nSymbs; + } + return vArray; +} +void Gia_ManDumpIoList( Gia_Man_t * p, FILE * pFile, int fOuts ) +{ + Vec_Ptr_t * vNames = fOuts ? p->vNamesOut : p->vNamesIn; + if ( vNames == NULL ) + fprintf( pFile, "_%c_", fOuts ? 'o' : 'i' ); + else + { + Vec_Int_t * vArray = Gia_ManCountSymbsAll( vNames ); + int iName, Size, i; + Vec_IntForEachEntryDouble( vArray, iName, Size, i ) + { + if ( i ) fprintf( pFile, ", " ); + Gia_ManPrintOneName( pFile, (char *)Vec_PtrEntry(vNames, iName), Size ); + } + Vec_IntFree( vArray ); + } +} +void Gia_ManDumpIoRanges( Gia_Man_t * p, FILE * pFile, int fOuts ) +{ + Vec_Ptr_t * vNames = fOuts ? p->vNamesOut : p->vNamesIn; + if ( p->vNamesOut == NULL ) + fprintf( pFile, "%s [%d:0] _%c_;\n", fOuts ? "output" : "input", fOuts ? Gia_ManPoNum(p)-1 : Gia_ManPiNum(p)-1, fOuts ? 'o' : 'i' ); + else + { + Vec_Int_t * vArray = Gia_ManCountSymbsAll( vNames ); + int iName, Size, i; + Vec_IntForEachEntryDouble( vArray, iName, Size, i ) + { + int iNameNext = Vec_IntSize(vArray) > i+2 ? Vec_IntEntry(vArray, i+2) : Vec_PtrSize(vNames); + char * pName = (char *)Vec_PtrEntry(vNames, iName); + char * pNameLast = (char *)Vec_PtrEntry(vNames, iNameNext-1); + assert( !strncmp(pName, pNameLast, Size) ); + int NumBeg = Gia_ManReadRangeNum( pName, Size ); + int NumEnd = Gia_ManReadRangeNum( pNameLast, Size ); + fprintf( pFile, " %s ", fOuts ? "output" : "input" ); + if ( NumBeg != -1 && iName < iNameNext-1 ) + fprintf( pFile, "[%d:%d] ", NumEnd, NumBeg ); + Gia_ManPrintOneName( pFile, pName, Size ); + fprintf( pFile, ";\n" ); + } + Vec_IntFree( vArray ); + } +} + /**Function************************************************************* Synopsis [] @@ -1820,9 +1915,14 @@ void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ) fprintf( pFile, "module " ); Gia_ManDumpModuleName( pFile, p->pName ); fprintf( pFile, "_wrapper" ); - fprintf( pFile, " ( _i_, _o_ );\n\n" ); - fprintf( pFile, " input [%d:0] _i_;\n", Gia_ManCiNum(p)-1 ); - fprintf( pFile, " output [%d:0] _o_;\n\n", Gia_ManCoNum(p)-1 ); + fprintf( pFile, " ( " ); + Gia_ManDumpIoList( p, pFile, 0 ); + fprintf( pFile, ", " ); + Gia_ManDumpIoList( p, pFile, 1 ); + fprintf( pFile, " );\n\n" ); + Gia_ManDumpIoRanges( p, pFile, 0 ); + Gia_ManDumpIoRanges( p, pFile, 1 ); + fprintf( pFile, "\n" ); fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); @@ -1834,9 +1934,13 @@ void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ) fprintf( pFile, " assign { " ); Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL ); - fprintf( pFile, " } = _i_;\n\n" ); + fprintf( pFile, " } = { " ); + Gia_ManDumpIoList( p, pFile, 0 ); + fprintf( pFile, " };\n\n" ); - fprintf( pFile, " assign _o_ = { " ); + fprintf( pFile, " assign { " ); + Gia_ManDumpIoList( p, pFile, 1 ); + fprintf( pFile, " } = { " ); Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL ); fprintf( pFile, " };\n\n" ); @@ -1922,9 +2026,14 @@ void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ) fprintf( pFile, "module " ); Gia_ManDumpModuleName( pFile, p->pName ); fprintf( pFile, "_wrapper" ); - fprintf( pFile, " ( _i_, _o_ );\n\n" ); - fprintf( pFile, " input [%d:0] _i_;\n", Gia_ManCiNum(p)-1 ); - fprintf( pFile, " output [%d:0] _o_;\n\n", Gia_ManCoNum(p)-1 ); + fprintf( pFile, " ( " ); + Gia_ManDumpIoList( p, pFile, 0 ); + fprintf( pFile, ", " ); + Gia_ManDumpIoList( p, pFile, 1 ); + fprintf( pFile, " );\n\n" ); + Gia_ManDumpIoRanges( p, pFile, 0 ); + Gia_ManDumpIoRanges( p, pFile, 1 ); + fprintf( pFile, "\n" ); fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); @@ -1936,9 +2045,13 @@ void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ) fprintf( pFile, " assign { " ); Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL ); - fprintf( pFile, " } = _i_;\n\n" ); + fprintf( pFile, " } = { " ); + Gia_ManDumpIoList( p, pFile, 0 ); + fprintf( pFile, " };\n\n" ); - fprintf( pFile, " assign _o_ = { " ); + fprintf( pFile, " assign { " ); + Gia_ManDumpIoList( p, pFile, 1 ); + fprintf( pFile, " } = { " ); Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL ); fprintf( pFile, " };\n\n" ); From 38e632a954a61e02e3397e02d42142ef86fdd9cb Mon Sep 17 00:00:00 2001 From: aletempiac Date: Fri, 12 Jan 2024 14:50:34 +0100 Subject: [PATCH 069/151] Consider buffers in matrix covering as free --- src/acd/ac_decomposition.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/acd/ac_decomposition.hpp b/src/acd/ac_decomposition.hpp index 64155b713..8ba2fb20e 100644 --- a/src/acd/ac_decomposition.hpp +++ b/src/acd/ac_decomposition.hpp @@ -945,6 +945,10 @@ private: /* discard solutions with support over LUT size */ if ( cost > ps.lut_size ) continue; + + /* buffers have zero cost */ + if ( cost == 1 ) + cost = 0; float sort_cost = 0; if constexpr ( UseHeuristic ) From 5bc99574fc63d4bc97b2e6342f1d3e16d5466cc5 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 12 Jan 2024 22:54:44 -0800 Subject: [PATCH 070/151] Eliminating dependency on "abc.rc" in "&deepsyn". --- src/aig/gia/giaDeep.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/aig/gia/giaDeep.c b/src/aig/gia/giaDeep.c index b58169f42..8d563726f 100644 --- a/src/aig/gia/giaDeep.c +++ b/src/aig/gia/giaDeep.c @@ -55,6 +55,7 @@ Gia_Man_t * Gia_ManDeepSynOne( int nNoImpr, int TimeOut, int nAnds, int Seed, in Abc_Random(0); for ( i = 0; i < IterMax; i++ ) { + char * pCompress2rs = "balance -l; resub -K 6 -l; rewrite -l; resub -K 6 -N 2 -l; refactor -l; resub -K 8 -l; balance -l; resub -K 8 -N 2 -l; rewrite -l; resub -K 10 -l; rewrite -z -l; resub -K 10 -N 2 -l; balance -l; resub -K 12 -l; refactor -z -l; resub -K 12 -N 2 -l; rewrite -z -l; balance -l"; unsigned Rand = Abc_Random(0); int fDch = Rand & 1; //int fCom = (Rand >> 1) & 3; @@ -62,16 +63,16 @@ Gia_Man_t * Gia_ManDeepSynOne( int nNoImpr, int TimeOut, int nAnds, int Seed, in int fFx = (Rand >> 2) & 1; int KLut = fUseTwo ? 2 + (i % 5) : 3 + (i % 4); int fChange = 0; - char Command[1000]; - char * pComp = NULL; + char Command[2000]; + char pComp[1000]; if ( fCom == 3 ) - pComp = "; &put; compress2rs; compress2rs; compress2rs; &get"; + sprintf( pComp, "; &put; %s; %s; %s; &get", pCompress2rs, pCompress2rs, pCompress2rs ); else if ( fCom == 2 ) - pComp = "; &put; compress2rs; compress2rs; &get"; + sprintf( pComp, "; &put; %s; %s; &get", pCompress2rs, pCompress2rs ); else if ( fCom == 1 ) - pComp = "; &put; compress2rs; &get"; + sprintf( pComp, "; &put; %s; &get", pCompress2rs ); else if ( fCom == 0 ) - pComp = "; &dc2"; + sprintf( pComp, "; &dc2" ); sprintf( Command, "&dch%s; &if -a -K %d; &mfs -e -W 20 -L 20%s%s", fDch ? " -f" : "", KLut, fFx ? "; &fx; &st" : "", pComp ); if ( Abc_FrameIsBatchMode() ) From 67aab70cff96346e825ad351e26c69ff88948f50 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 16 Jan 2024 17:42:43 +0100 Subject: [PATCH 071/151] Moving ACD package to if folder --- Makefile | 5 ++--- src/acd/module.make | 1 - src/{ => map/if}/acd/ac_decomposition.hpp | 0 src/{ => map/if}/acd/ac_wrapper.cpp | 0 src/{ => map/if}/acd/ac_wrapper.h | 0 src/{ => map/if}/acd/kitty_algorithm.hpp | 0 src/{ => map/if}/acd/kitty_constants.hpp | 0 src/{ => map/if}/acd/kitty_constructors.hpp | 0 src/{ => map/if}/acd/kitty_dynamic_tt.hpp | 0 src/{ => map/if}/acd/kitty_operations.hpp | 0 src/{ => map/if}/acd/kitty_operators.hpp | 0 src/{ => map/if}/acd/kitty_static_tt.hpp | 0 src/map/if/acd/module.make | 1 + src/map/if/if.h | 2 +- 14 files changed, 4 insertions(+), 5 deletions(-) delete mode 100644 src/acd/module.make rename src/{ => map/if}/acd/ac_decomposition.hpp (100%) rename src/{ => map/if}/acd/ac_wrapper.cpp (100%) rename src/{ => map/if}/acd/ac_wrapper.h (100%) rename src/{ => map/if}/acd/kitty_algorithm.hpp (100%) rename src/{ => map/if}/acd/kitty_constants.hpp (100%) rename src/{ => map/if}/acd/kitty_constructors.hpp (100%) rename src/{ => map/if}/acd/kitty_dynamic_tt.hpp (100%) rename src/{ => map/if}/acd/kitty_operations.hpp (100%) rename src/{ => map/if}/acd/kitty_operators.hpp (100%) rename src/{ => map/if}/acd/kitty_static_tt.hpp (100%) create mode 100644 src/map/if/acd/module.make diff --git a/Makefile b/Makefile index d770c3faf..f7f4fda6f 100644 --- a/Makefile +++ b/Makefile @@ -17,10 +17,9 @@ OS := $(shell uname -s) MODULES := \ $(wildcard src/ext*) \ - src/acd \ src/base/abc src/base/abci src/base/cmd src/base/io src/base/main src/base/exor \ src/base/ver src/base/wlc src/base/wln src/base/acb src/base/bac src/base/cba src/base/pla src/base/test \ - src/map/mapper src/map/mio src/map/super src/map/if \ + src/map/mapper src/map/mio src/map/super src/map/if src/map/if/acd \ src/map/amap src/map/cov src/map/scl src/map/mpm \ src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/nm \ src/misc/vec src/misc/hash src/misc/tim src/misc/bzlib src/misc/zlib \ @@ -55,7 +54,7 @@ endif ARCHFLAGS := $(ARCHFLAGS) -OPTFLAGS ?= -g -O +OPTFLAGS ?= -g -O3 CFLAGS += -std=c17 -Wall -Wno-unused-function -Wno-write-strings -Wno-sign-compare $(ARCHFLAGS) ifneq ($(findstring arm,$(shell uname -m)),) diff --git a/src/acd/module.make b/src/acd/module.make deleted file mode 100644 index b245d2c42..000000000 --- a/src/acd/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += src/acd/ac_wrapper.cpp diff --git a/src/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp similarity index 100% rename from src/acd/ac_decomposition.hpp rename to src/map/if/acd/ac_decomposition.hpp diff --git a/src/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp similarity index 100% rename from src/acd/ac_wrapper.cpp rename to src/map/if/acd/ac_wrapper.cpp diff --git a/src/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h similarity index 100% rename from src/acd/ac_wrapper.h rename to src/map/if/acd/ac_wrapper.h diff --git a/src/acd/kitty_algorithm.hpp b/src/map/if/acd/kitty_algorithm.hpp similarity index 100% rename from src/acd/kitty_algorithm.hpp rename to src/map/if/acd/kitty_algorithm.hpp diff --git a/src/acd/kitty_constants.hpp b/src/map/if/acd/kitty_constants.hpp similarity index 100% rename from src/acd/kitty_constants.hpp rename to src/map/if/acd/kitty_constants.hpp diff --git a/src/acd/kitty_constructors.hpp b/src/map/if/acd/kitty_constructors.hpp similarity index 100% rename from src/acd/kitty_constructors.hpp rename to src/map/if/acd/kitty_constructors.hpp diff --git a/src/acd/kitty_dynamic_tt.hpp b/src/map/if/acd/kitty_dynamic_tt.hpp similarity index 100% rename from src/acd/kitty_dynamic_tt.hpp rename to src/map/if/acd/kitty_dynamic_tt.hpp diff --git a/src/acd/kitty_operations.hpp b/src/map/if/acd/kitty_operations.hpp similarity index 100% rename from src/acd/kitty_operations.hpp rename to src/map/if/acd/kitty_operations.hpp diff --git a/src/acd/kitty_operators.hpp b/src/map/if/acd/kitty_operators.hpp similarity index 100% rename from src/acd/kitty_operators.hpp rename to src/map/if/acd/kitty_operators.hpp diff --git a/src/acd/kitty_static_tt.hpp b/src/map/if/acd/kitty_static_tt.hpp similarity index 100% rename from src/acd/kitty_static_tt.hpp rename to src/map/if/acd/kitty_static_tt.hpp diff --git a/src/map/if/acd/module.make b/src/map/if/acd/module.make new file mode 100644 index 000000000..33c59e830 --- /dev/null +++ b/src/map/if/acd/module.make @@ -0,0 +1 @@ +SRC += src/map/if/acd/ac_wrapper.cpp diff --git a/src/map/if/if.h b/src/map/if/if.h index cc4d2926b..f8c99fdf1 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -40,7 +40,7 @@ #include "opt/dau/dau.h" #include "misc/vec/vecHash.h" #include "misc/vec/vecWec.h" -#include "acd/ac_wrapper.h" +#include "map/if/acd/ac_wrapper.h" ABC_NAMESPACE_HEADER_START From 5a00bbaa8f930f9653fd24fabd948e78bb5784fb Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 16 Jan 2024 18:13:30 +0100 Subject: [PATCH 072/151] Cleaning Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f7f4fda6f..0cc979b75 100644 --- a/Makefile +++ b/Makefile @@ -54,9 +54,9 @@ endif ARCHFLAGS := $(ARCHFLAGS) -OPTFLAGS ?= -g -O3 +OPTFLAGS ?= -g -O -CFLAGS += -std=c17 -Wall -Wno-unused-function -Wno-write-strings -Wno-sign-compare $(ARCHFLAGS) +CFLAGS += -Wall -Wno-unused-function -Wno-write-strings -Wno-sign-compare $(ARCHFLAGS) ifneq ($(findstring arm,$(shell uname -m)),) CFLAGS += -DABC_MEMALIGN=4 endif From d140535d645cd948d2ebae6bc42677dac181f968 Mon Sep 17 00:00:00 2001 From: Baruch Sterin Date: Wed, 17 Jan 2024 15:04:31 -0800 Subject: [PATCH 073/151] Adapt previous merge by @aletempiac to compile with ABC namespaces. --- src/map/if/acd/ac_decomposition.hpp | 4 ++++ src/map/if/acd/ac_wrapper.cpp | 4 ++++ src/map/if/acd/ac_wrapper.h | 8 ++------ src/map/if/acd/kitty_algorithm.hpp | 4 ++++ src/map/if/acd/kitty_constants.hpp | 4 ++++ src/map/if/acd/kitty_constructors.hpp | 4 ++++ src/map/if/acd/kitty_dynamic_tt.hpp | 4 ++++ src/map/if/acd/kitty_operations.hpp | 4 ++++ src/map/if/acd/kitty_operators.hpp | 4 ++++ src/map/if/acd/kitty_static_tt.hpp | 4 ++++ 10 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index 8ba2fb20e..8aee0266d 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -40,6 +40,8 @@ #include "kitty_operators.hpp" #include "kitty_static_tt.hpp" +ABC_NAMESPACE_CXX_HEADER_START + namespace acd { @@ -1303,4 +1305,6 @@ private: } // namespace acd +ABC_NAMESPACE_CXX_HEADER_END + #endif // _ACD_H_ \ No newline at end of file diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index baeee2fd6..fd8015f95 100644 --- a/src/map/if/acd/ac_wrapper.cpp +++ b/src/map/if/acd/ac_wrapper.cpp @@ -19,6 +19,8 @@ #include "ac_wrapper.h" #include "ac_decomposition.hpp" +ABC_NAMESPACE_IMPL_START + int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ) { using namespace acd; @@ -66,3 +68,5 @@ int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, acd.get_decomposition( decomposition ); return 0; } + +ABC_NAMESPACE_IMPL_END diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h index ce39949fb..a384b4404 100644 --- a/src/map/if/acd/ac_wrapper.h +++ b/src/map/if/acd/ac_wrapper.h @@ -23,15 +23,11 @@ #include "misc/util/abc_global.h" #include "map/if/if.h" -#ifdef __cplusplus -extern "C" { -#endif +ABC_NAMESPACE_HEADER_START int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); -#ifdef __cplusplus -} -#endif +ABC_NAMESPACE_HEADER_END #endif \ No newline at end of file diff --git a/src/map/if/acd/kitty_algorithm.hpp b/src/map/if/acd/kitty_algorithm.hpp index 6460a802c..78eead08a 100644 --- a/src/map/if/acd/kitty_algorithm.hpp +++ b/src/map/if/acd/kitty_algorithm.hpp @@ -9,6 +9,8 @@ #include "kitty_dynamic_tt.hpp" #include "kitty_static_tt.hpp" +ABC_NAMESPACE_CXX_HEADER_START + namespace kitty { @@ -116,4 +118,6 @@ void for_each_block_reversed( const TT& tt, Fn&& op ) } // namespace kitty +ABC_NAMESPACE_CXX_HEADER_END + #endif // _KITTY_ALGORITHM_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_constants.hpp b/src/map/if/acd/kitty_constants.hpp index 55cfcd650..35ff489e9 100644 --- a/src/map/if/acd/kitty_constants.hpp +++ b/src/map/if/acd/kitty_constants.hpp @@ -5,6 +5,8 @@ #include #include +ABC_NAMESPACE_CXX_HEADER_START + namespace kitty { @@ -88,4 +90,6 @@ static constexpr int32_t hex_to_int[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } // namespace kitty +ABC_NAMESPACE_CXX_HEADER_END + #endif //_KITTY_CONSTANTS_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_constructors.hpp b/src/map/if/acd/kitty_constructors.hpp index 43408b8cc..26ec6e483 100644 --- a/src/map/if/acd/kitty_constructors.hpp +++ b/src/map/if/acd/kitty_constructors.hpp @@ -12,6 +12,8 @@ #include "kitty_dynamic_tt.hpp" #include "kitty_static_tt.hpp" +ABC_NAMESPACE_CXX_HEADER_START + namespace kitty { @@ -89,4 +91,6 @@ void create_nth_var( TT& tt, uint8_t var_index, bool complement = false ) } // namespace kitty +ABC_NAMESPACE_CXX_HEADER_END + #endif // _KITTY_CONSTRUCT_TT_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_dynamic_tt.hpp b/src/map/if/acd/kitty_dynamic_tt.hpp index f3ef0c7d9..880943dfa 100644 --- a/src/map/if/acd/kitty_dynamic_tt.hpp +++ b/src/map/if/acd/kitty_dynamic_tt.hpp @@ -8,6 +8,8 @@ #include "kitty_constants.hpp" +ABC_NAMESPACE_CXX_HEADER_START + namespace kitty { @@ -144,4 +146,6 @@ public: /* fields */ } //namespace kitty +ABC_NAMESPACE_CXX_HEADER_END + #endif // _KITTY_DYNAMIC_TT_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_operations.hpp b/src/map/if/acd/kitty_operations.hpp index fb504489a..bf8e38007 100644 --- a/src/map/if/acd/kitty_operations.hpp +++ b/src/map/if/acd/kitty_operations.hpp @@ -14,6 +14,8 @@ #include "kitty_dynamic_tt.hpp" #include "kitty_static_tt.hpp" +ABC_NAMESPACE_CXX_HEADER_START + namespace kitty { @@ -330,4 +332,6 @@ void print_hex( const TT& tt, std::ostream& os = std::cout ) } //namespace kitty +ABC_NAMESPACE_CXX_HEADER_END + #endif // _KITTY_OPERATIONS_TT_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_operators.hpp b/src/map/if/acd/kitty_operators.hpp index 68a24cf2e..b5f4688c2 100644 --- a/src/map/if/acd/kitty_operators.hpp +++ b/src/map/if/acd/kitty_operators.hpp @@ -13,6 +13,8 @@ #include "kitty_static_tt.hpp" #include "kitty_operations.hpp" +ABC_NAMESPACE_CXX_HEADER_START + namespace kitty { @@ -119,4 +121,6 @@ inline void operator|=( static_truth_table& first, const static_truth_t } // namespace kitty +ABC_NAMESPACE_CXX_HEADER_END + #endif // _KITTY_OPERATORS_TT_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_static_tt.hpp b/src/map/if/acd/kitty_static_tt.hpp index 61593f3ff..ab5a5d1c9 100644 --- a/src/map/if/acd/kitty_static_tt.hpp +++ b/src/map/if/acd/kitty_static_tt.hpp @@ -7,6 +7,8 @@ #include "kitty_constants.hpp" +ABC_NAMESPACE_CXX_HEADER_START + namespace kitty { @@ -128,4 +130,6 @@ public: /* fields */ } //namespace kitty +ABC_NAMESPACE_CXX_HEADER_END + #endif // _KITTY_STATIC_TT_H_ \ No newline at end of file From 234af64a8cf0b027671320e0378d0da2be2da91a Mon Sep 17 00:00:00 2001 From: Baruch Sterin Date: Thu, 18 Jan 2024 09:58:18 -0800 Subject: [PATCH 074/151] Workaround for C++17 compilation (on clang) --- src/aig/gia/giaIso3.c | 2 +- src/base/acb/acbTest.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/aig/gia/giaIso3.c b/src/aig/gia/giaIso3.c index 8bea4bbfa..b526676d3 100644 --- a/src/aig/gia/giaIso3.c +++ b/src/aig/gia/giaIso3.c @@ -177,7 +177,7 @@ Vec_Wec_t * Gia_Iso4Gia( Gia_Man_t * p ) Vec_WecForEachLevel( vLevs, vLevel, l ) { Gia_Obj_t * pObj; int i; - int RandC[2] = { Abc_Random(0), Abc_Random(0) }; + unsigned RandC[2] = { Abc_Random(0), Abc_Random(0) }; if ( l == 0 ) { Gia_ManForEachObjVec( vLevel, p, pObj, i ) diff --git a/src/base/acb/acbTest.c b/src/base/acb/acbTest.c index 6290b88ea..c22d4b55b 100644 --- a/src/base/acb/acbTest.c +++ b/src/base/acb/acbTest.c @@ -421,8 +421,8 @@ Gia_Man_t * Acb_NtkGiaDeriveMiter( Gia_Man_t * pOne, Gia_Man_t * pTwo, int Type { for ( i = 0; i < Gia_ManCoNum(pOne); i += 2 ) { - int pLitsF[2] = { Gia_ManCo(pOne, i)->Value, Gia_ManCo(pOne, i+1)->Value }; - int pLitsS[2] = { Gia_ManCo(pTwo, i)->Value, Gia_ManCo(pTwo, i+1)->Value }; + unsigned pLitsF[2] = { Gia_ManCo(pOne, i)->Value, Gia_ManCo(pOne, i+1)->Value }; + unsigned pLitsS[2] = { Gia_ManCo(pTwo, i)->Value, Gia_ManCo(pTwo, i+1)->Value }; Gia_ManAppendCo( pNew, pLitsF[0] ); Gia_ManAppendCo( pNew, pLitsS[0] ); } @@ -431,8 +431,8 @@ Gia_Man_t * Acb_NtkGiaDeriveMiter( Gia_Man_t * pOne, Gia_Man_t * pTwo, int Type { for ( i = 0; i < Gia_ManCoNum(pOne); i += 2 ) { - int pLitsF[2] = { Gia_ManCo(pOne, i)->Value, Gia_ManCo(pOne, i+1)->Value }; - int pLitsS[2] = { Gia_ManCo(pTwo, i)->Value, Gia_ManCo(pTwo, i+1)->Value }; + unsigned pLitsF[2] = { Gia_ManCo(pOne, i)->Value, Gia_ManCo(pOne, i+1)->Value }; + unsigned pLitsS[2] = { Gia_ManCo(pTwo, i)->Value, Gia_ManCo(pTwo, i+1)->Value }; Gia_ManAppendCo( pNew, pLitsF[1] ); Gia_ManAppendCo( pNew, pLitsS[1] ); } @@ -441,8 +441,8 @@ Gia_Man_t * Acb_NtkGiaDeriveMiter( Gia_Man_t * pOne, Gia_Man_t * pTwo, int Type { for ( i = 0; i < Gia_ManCoNum(pOne); i += 2 ) { - int pLitsF[2] = { Gia_ManCo(pOne, i)->Value, Gia_ManCo(pOne, i+1)->Value }; - int pLitsS[2] = { Gia_ManCo(pTwo, i)->Value, Gia_ManCo(pTwo, i+1)->Value }; + int pLitsF[2] = { (int)Gia_ManCo(pOne, i)->Value, (int)Gia_ManCo(pOne, i+1)->Value }; + int pLitsS[2] = { (int)Gia_ManCo(pTwo, i)->Value, (int)Gia_ManCo(pTwo, i+1)->Value }; Gia_ManAppendCo( pNew, Gia_ManDualCompare( pNew, pLitsF, pLitsS ) ); } } From 8da884de85b09467eff6f0f813beeb28a4e77c2f Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 18 Jan 2024 18:23:11 -0800 Subject: [PATCH 075/151] Switch to reverse the order of bits. --- src/aig/gia/gia.h | 2 +- src/aig/gia/giaMan.c | 28 ++++++++++++++-------------- src/base/abci/abc.c | 11 ++++++++--- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 654f2faa5..76c8fcb97 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1530,7 +1530,7 @@ extern void Gia_ManPrintStatsMiter( Gia_Man_t * p, int fVerbose ) extern void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs ); extern void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew ); extern void Gia_ManPrintNpnClasses( Gia_Man_t * p ); -extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb, int fAssign ); +extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb, int fAssign, int fReverse ); /*=== giaMem.c ===========================================================*/ extern Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax ); extern void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose ); diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index e8fd9f1d8..7498630a8 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -1408,17 +1408,17 @@ void Gia_ManWriteNames( FILE * pFile, char c, int n, Vec_Ptr_t * vNames, int Sta fFirst = 0; } } -void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb, int fAssign ) +void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb, int fAssign, int fReverse ) { if ( fInterComb ) { if ( fAssign ) { - extern void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ); - Gia_ManDumpInterfaceAssign( p, pFileName ); + extern void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName, int fReverse ); + Gia_ManDumpInterfaceAssign( p, pFileName, fReverse ); } else { - extern void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ); - Gia_ManDumpInterface( p, pFileName ); + extern void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName, int fReverse ); + Gia_ManDumpInterface( p, pFileName, fReverse ); } } else @@ -1855,7 +1855,7 @@ void Gia_ManDumpIoList( Gia_Man_t * p, FILE * pFile, int fOuts ) Vec_IntFree( vArray ); } } -void Gia_ManDumpIoRanges( Gia_Man_t * p, FILE * pFile, int fOuts ) +void Gia_ManDumpIoRanges( Gia_Man_t * p, FILE * pFile, int fOuts, int fReverse ) { Vec_Ptr_t * vNames = fOuts ? p->vNamesOut : p->vNamesIn; if ( p->vNamesOut == NULL ) @@ -1874,7 +1874,7 @@ void Gia_ManDumpIoRanges( Gia_Man_t * p, FILE * pFile, int fOuts ) int NumEnd = Gia_ManReadRangeNum( pNameLast, Size ); fprintf( pFile, " %s ", fOuts ? "output" : "input" ); if ( NumBeg != -1 && iName < iNameNext-1 ) - fprintf( pFile, "[%d:%d] ", NumEnd, NumBeg ); + fprintf( pFile, "[%d:%d] ", fReverse ? NumBeg : NumEnd, fReverse ? NumEnd : NumBeg ); Gia_ManPrintOneName( pFile, pName, Size ); fprintf( pFile, ";\n" ); } @@ -1893,7 +1893,7 @@ void Gia_ManDumpIoRanges( Gia_Man_t * p, FILE * pFile, int fOuts ) SeeAlso [] ***********************************************************************/ -void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ) +void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName, int fReverse ) { Gia_Obj_t * pObj; Vec_Bit_t * vInvs, * vUsed; @@ -1920,8 +1920,8 @@ void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ) fprintf( pFile, ", " ); Gia_ManDumpIoList( p, pFile, 1 ); fprintf( pFile, " );\n\n" ); - Gia_ManDumpIoRanges( p, pFile, 0 ); - Gia_ManDumpIoRanges( p, pFile, 1 ); + Gia_ManDumpIoRanges( p, pFile, 0, fReverse ); + Gia_ManDumpIoRanges( p, pFile, 1, fReverse ); fprintf( pFile, "\n" ); fprintf( pFile, " wire " ); @@ -2004,7 +2004,7 @@ void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ) Vec_BitFree( vInvs ); Vec_BitFree( vUsed ); } -void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ) +void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName, int fReverse ) { Gia_Obj_t * pObj; Vec_Bit_t * vInvs, * vUsed; @@ -2031,8 +2031,8 @@ void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ) fprintf( pFile, ", " ); Gia_ManDumpIoList( p, pFile, 1 ); fprintf( pFile, " );\n\n" ); - Gia_ManDumpIoRanges( p, pFile, 0 ); - Gia_ManDumpIoRanges( p, pFile, 1 ); + Gia_ManDumpIoRanges( p, pFile, 0, fReverse ); + Gia_ManDumpIoRanges( p, pFile, 1, fReverse ); fprintf( pFile, "\n" ); fprintf( pFile, " wire " ); @@ -2189,7 +2189,7 @@ void Gia_GenSandwich( char ** pFNames, int nFNames, char * pFileName ) fprintf( pFile, "endmodule\n" ); fclose( pFile ); for ( i = 0; i < nFNames; i++ ) { - Gia_ManDumpVerilog( pGias[i], Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v"), NULL, 0, 0, 1, 0 ); + Gia_ManDumpVerilog( pGias[i], Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v"), NULL, 0, 0, 1, 0, 0 ); printf( "Dumped Verilog file \"%s\"\n", Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v") ); } Gia_FreeMany( pGias, nFNames ); diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 89785887d..bd0dd74cf 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -32070,9 +32070,10 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) int fMiniAig = 0; int fMiniLut = 0; int fWriteNewLine = 0; + int fReverse = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "upicabmlnvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "upicabmlnrvh" ) ) != EOF ) { switch ( c ) { @@ -32103,6 +32104,9 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'n': fWriteNewLine ^= 1; break; + case 'r': + fReverse ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -32132,7 +32136,7 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_ManStop( pGia ); } else if ( fVerilog ) - Gia_ManDumpVerilog( pAbc->pGia, pFileName, NULL, fVerBufs, fInter, fInterComb, fAssign ); + Gia_ManDumpVerilog( pAbc->pGia, pFileName, NULL, fVerBufs, fInter, fInterComb, fAssign, fReverse ); else if ( fMiniAig ) Gia_ManWriteMiniAig( pAbc->pGia, pFileName ); else if ( fMiniLut ) @@ -32142,7 +32146,7 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &w [-upicabmlnvh] \n" ); + Abc_Print( -2, "usage: &w [-upicabmlnrvh] \n" ); Abc_Print( -2, "\t writes the current AIG into the AIGER file\n" ); Abc_Print( -2, "\t-u : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" ); Abc_Print( -2, "\t-p : toggle writing Verilog with 'and' and 'not' [default = %s]\n", fVerilog? "yes" : "no" ); @@ -32153,6 +32157,7 @@ usage: Abc_Print( -2, "\t-m : toggle writing MiniAIG rather than AIGER [default = %s]\n", fMiniAig? "yes" : "no" ); Abc_Print( -2, "\t-l : toggle writing MiniLUT rather than AIGER [default = %s]\n", fMiniLut? "yes" : "no" ); Abc_Print( -2, "\t-n : toggle writing \'\\n\' after \'c\' in the AIGER file [default = %s]\n", fWriteNewLine? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle reversing the order of input/output bits [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); From 5fa9192412042b3db37cae4059555767994ab267 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 18 Jan 2024 18:34:50 -0800 Subject: [PATCH 076/151] Change how &stochsyn runs on a single core. --- src/aig/gia/giaStoch.c | 73 ++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 21 deletions(-) diff --git a/src/aig/gia/giaStoch.c b/src/aig/gia/giaStoch.c index 78fe2cb67..fc65c80bb 100644 --- a/src/aig/gia/giaStoch.c +++ b/src/aig/gia/giaStoch.c @@ -60,28 +60,35 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ -Gia_Man_t * Gia_StochProcessOne( Gia_Man_t * p, char * pScript, int Rand, int TimeSecs ) +Gia_Man_t * Gia_StochProcessSingle( Gia_Man_t * p, char * pScript, int Rand, int TimeSecs ) { - Gia_Man_t * pNew; - char FileName[100], Command[1000]; - sprintf( FileName, "%06x.aig", Rand ); - Gia_AigerWrite( p, FileName, 0, 0, 0 ); - sprintf( Command, "./abc -q \"&read %s; %s; &write %s\"", FileName, pScript, FileName ); - if ( system( (char *)Command ) ) + Gia_Man_t * pTemp, * pNew = Gia_ManDup( p ); + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), Gia_ManDup(p) ); + if ( Abc_FrameIsBatchMode() ) { - fprintf( stderr, "The following command has returned non-zero exit status:\n" ); - fprintf( stderr, "\"%s\"\n", (char *)Command ); - fprintf( stderr, "Sorry for the inconvenience.\n" ); - fflush( stdout ); - unlink( FileName ); - return Gia_ManDup(p); - } - pNew = Gia_AigerRead( FileName, 0, 0, 0 ); - unlink( FileName ); - if ( pNew && Gia_ManAndNum(pNew) < Gia_ManAndNum(p) ) - return pNew; - Gia_ManStopP( &pNew ); - return Gia_ManDup(p); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return NULL; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return NULL; + } + Abc_FrameSetBatchMode( 0 ); + } + pTemp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + if ( Gia_ManAndNum(pNew) > Gia_ManAndNum(pTemp) ) + { + Gia_ManStop( pNew ); + pNew = Gia_ManDup( pTemp ); + } + return pNew; } void Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int fVerbose ) { @@ -92,7 +99,7 @@ void Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int Vec_IntPush( vRands, Abc_Random(0) % 0x1000000 ); Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) { - pNew = Gia_StochProcessOne( pGia, pScript, Vec_IntEntry(vRands, i), TimeSecs ); + pNew = Gia_StochProcessSingle( pGia, pScript, Vec_IntEntry(vRands, i), TimeSecs ); Gia_ManStop( pGia ); Vec_PtrWriteEntry( vGias, i, pNew ); } @@ -131,6 +138,30 @@ typedef struct Gia_StochThData_t_ int fWorking; } Gia_StochThData_t; +Gia_Man_t * Gia_StochProcessOne( Gia_Man_t * p, char * pScript, int Rand, int TimeSecs ) +{ + Gia_Man_t * pNew; + char FileName[100], Command[1000]; + sprintf( FileName, "%06x.aig", Rand ); + Gia_AigerWrite( p, FileName, 0, 0, 0 ); + sprintf( Command, "./abc -q \"&read %s; %s; &write %s\"", FileName, pScript, FileName ); + if ( system( (char *)Command ) ) + { + fprintf( stderr, "The following command has returned non-zero exit status:\n" ); + fprintf( stderr, "\"%s\"\n", (char *)Command ); + fprintf( stderr, "Sorry for the inconvenience.\n" ); + fflush( stdout ); + unlink( FileName ); + return Gia_ManDup(p); + } + pNew = Gia_AigerRead( FileName, 0, 0, 0 ); + unlink( FileName ); + if ( pNew && Gia_ManAndNum(pNew) < Gia_ManAndNum(p) ) + return pNew; + Gia_ManStopP( &pNew ); + return Gia_ManDup(p); +} + void * Gia_StochWorkerThread( void * pArg ) { Gia_StochThData_t * pThData = (Gia_StochThData_t *)pArg; From d6555f48dd3b2cd6c5a93dc0e373f67f927b9848 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 26 Jan 2024 07:31:20 -0800 Subject: [PATCH 077/151] Adding a switch to not write the timestamp in the AIGER file. --- src/aig/gia/gia.h | 1 + src/aig/gia/giaAiger.c | 24 +++++++++++++++++++++--- src/base/abci/abc.c | 11 ++++++++--- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 76c8fcb97..25a3758eb 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1253,6 +1253,7 @@ extern int Gia_FileSize( char * pFileName ); extern Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSimple, int fSkipStrash, int fCheck ); extern Gia_Man_t * Gia_AigerRead( char * pFileName, int fGiaSimple, int fSkipStrash, int fCheck ); extern void Gia_AigerWrite( Gia_Man_t * p, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine ); +extern void Gia_AigerWriteS( Gia_Man_t * p, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine, int fSkipComment ); extern void Gia_DumpAiger( Gia_Man_t * p, char * pFilePrefix, int iFileNum, int nFileNumDigits ); extern Vec_Str_t * Gia_AigerWriteIntoMemoryStr( Gia_Man_t * p ); extern Vec_Str_t * Gia_AigerWriteIntoMemoryStrPart( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs ); diff --git a/src/aig/gia/giaAiger.c b/src/aig/gia/giaAiger.c index e3967e0ed..de94c4602 100644 --- a/src/aig/gia/giaAiger.c +++ b/src/aig/gia/giaAiger.c @@ -1217,7 +1217,7 @@ Vec_Str_t * Gia_AigerWriteIntoMemoryStrPart( Gia_Man_t * p, Vec_Int_t * vCis, Ve SeeAlso [] ***********************************************************************/ -void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine ) +void Gia_AigerWriteS( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine, int fSkipComment ) { int fVerbose = XAIG_VERBOSE; FILE * pFile; @@ -1557,8 +1557,10 @@ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int // write comments if ( fWriteNewLine ) fprintf( pFile, "c\n" ); - fprintf( pFile, "\nThis file was produced by the GIA package in ABC on %s\n", Gia_TimeStamp() ); - fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); + if ( !fSkipComment ) { + fprintf( pFile, "\nThis file was produced by the GIA package in ABC on %s\n", Gia_TimeStamp() ); + fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); + } fclose( pFile ); if ( p != pInit ) { @@ -1567,6 +1569,22 @@ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int } } +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine ) +{ + Gia_AigerWriteS( pInit, pFileName, fWriteSymbols, fCompact, fWriteNewLine, 0 ); +} + /**Function************************************************************* Synopsis [Writes the AIG in the binary AIGER format.] diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index bd0dd74cf..e0ca6e948 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -32071,9 +32071,10 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) int fMiniLut = 0; int fWriteNewLine = 0; int fReverse = 0; + int fSkipComment = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "upicabmlnrvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "upicabmlnrsvh" ) ) != EOF ) { switch ( c ) { @@ -32107,6 +32108,9 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'r': fReverse ^= 1; break; + case 's': + fSkipComment ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -32142,11 +32146,11 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) else if ( fMiniLut ) Gia_ManWriteMiniLut( pAbc->pGia, pFileName ); else - Gia_AigerWrite( pAbc->pGia, pFileName, 0, 0, fWriteNewLine ); + Gia_AigerWriteS( pAbc->pGia, pFileName, 0, 0, fWriteNewLine, fSkipComment ); return 0; usage: - Abc_Print( -2, "usage: &w [-upicabmlnrvh] \n" ); + Abc_Print( -2, "usage: &w [-upicabmlnrsvh] \n" ); Abc_Print( -2, "\t writes the current AIG into the AIGER file\n" ); Abc_Print( -2, "\t-u : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" ); Abc_Print( -2, "\t-p : toggle writing Verilog with 'and' and 'not' [default = %s]\n", fVerilog? "yes" : "no" ); @@ -32158,6 +32162,7 @@ usage: Abc_Print( -2, "\t-l : toggle writing MiniLUT rather than AIGER [default = %s]\n", fMiniLut? "yes" : "no" ); Abc_Print( -2, "\t-n : toggle writing \'\\n\' after \'c\' in the AIGER file [default = %s]\n", fWriteNewLine? "yes": "no" ); Abc_Print( -2, "\t-r : toggle reversing the order of input/output bits [default = %s]\n", fReverse? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle skipping the timestamp in the output file [default = %s]\n", fSkipComment? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); From 6d1d52deaaa60c5bbe9c74c97a4cd7b6ff91babe Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 30 Jan 2024 20:22:55 -0800 Subject: [PATCH 078/151] Adding an option to read the RTL elaboration library from the current directory. --- src/base/wln/wlnCom.c | 17 +++++++++++------ src/base/wln/wlnRtl.c | 4 ++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/base/wln/wlnCom.c b/src/base/wln/wlnCom.c index 06e4392c9..d24fec48c 100644 --- a/src/base/wln/wlnCom.c +++ b/src/base/wln/wlnCom.c @@ -92,7 +92,7 @@ void Wln_End( Abc_Frame_t * pAbc ) ******************************************************************************/ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fVerbose ); + extern Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fVerbose ); extern Rtl_Lib_t * Wln_ReadSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fCollapse, int fVerbose ); FILE * pFile; @@ -102,11 +102,12 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv ) int fBlast = 0; int fInvert = 0; int fTechMap = 1; + int fLibInDir = 0; int fSkipStrash = 0; int fCollapse = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "TDbismcvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "TDbismlcvh" ) ) != EOF ) { switch ( c ) { @@ -140,6 +141,9 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': fTechMap ^= 1; break; + case 'l': + fLibInDir ^= 1; + break; case 'c': fCollapse ^= 1; break; @@ -174,11 +178,11 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pNew = NULL; if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) - pNew = Wln_BlastSystemVerilog( pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fVerbose ); + pNew = Wln_BlastSystemVerilog( pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fVerbose ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "sv" ) ) - pNew = Wln_BlastSystemVerilog( pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fVerbose ); + pNew = Wln_BlastSystemVerilog( pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fVerbose ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "rtlil" ) ) - pNew = Wln_BlastSystemVerilog( pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fVerbose ); + pNew = Wln_BlastSystemVerilog( pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fVerbose ); else { printf( "Abc_CommandYosys(): Unknown file extension.\n" ); @@ -204,7 +208,7 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv ) } return 0; usage: - Abc_Print( -2, "usage: %%yosys [-T ] [-D ] [-bismcvh] \n" ); + Abc_Print( -2, "usage: %%yosys [-T ] [-D ] [-bismlcvh] \n" ); Abc_Print( -2, "\t reads Verilog or SystemVerilog using Yosys\n" ); Abc_Print( -2, "\t-T : specify the top module name (default uses \"-auto-top\")\n" ); Abc_Print( -2, "\t-D : specify defines to be used by Yosys (default \"not used\")\n" ); @@ -212,6 +216,7 @@ usage: Abc_Print( -2, "\t-i : toggle inverting the outputs (useful for miters) [default = %s]\n", fInvert? "yes": "no" ); Abc_Print( -2, "\t-s : toggle no structural hashing during bit-blasting [default = %s]\n", fSkipStrash? "no strash": "strash" ); Abc_Print( -2, "\t-m : toggle using \"techmap\" to blast operators [default = %s]\n", fTechMap? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle looking for \"techmap.v\" in the current directory [default = %s]\n", fLibInDir? "yes": "no" ); Abc_Print( -2, "\t-c : toggle collapsing design hierarchy using Yosys [default = %s]\n", fCollapse? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); diff --git a/src/base/wln/wlnRtl.c b/src/base/wln/wlnRtl.c index 7ed80edae..36801c862 100644 --- a/src/base/wln/wlnRtl.c +++ b/src/base/wln/wlnRtl.c @@ -167,7 +167,7 @@ Rtl_Lib_t * Wln_ReadSystemVerilog( char * pFileName, char * pTopModule, char * p unlink( pFileTemp ); return pNtk; } -Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fVerbose ) +Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fVerbose ) { Gia_Man_t * pGia = NULL; char Command[1000]; @@ -183,7 +183,7 @@ Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pTopModule, char * pFileName, pTopModule ? "-top " : "-auto-top", pTopModule ? pTopModule : "", - fTechMap ? "techmap; setundef -zero; " : "", pFileTemp ); + fTechMap ? (fLibInDir ? "techmap -map techmap.v; setundef -zero; " : "techmap; setundef -zero; ") : "", pFileTemp ); if ( fVerbose ) printf( "%s\n", Command ); if ( !Wln_ConvertToRtl(Command, pFileTemp) ) From c74144c6eb75095bfd280022f1e7a3ddca28f7f3 Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Thu, 1 Feb 2024 07:25:46 +0800 Subject: [PATCH 079/151] str_eco ver1 --- src/aig/gia/giaDup.c | 730 ++++++++++++++++++++++++++++++--------- src/base/abci/abc.c | 107 ++++++ src/proof/cec/cecSatG2.c | 295 +++++----------- 3 files changed, 767 insertions(+), 365 deletions(-) diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index aa8f1c053..37b3e8e3b 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -30,9 +30,12 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -Vec_Int_t* vMarkBmiter; -Vec_Int_t* vIdBI; -Vec_Int_t* vIdBO; +Vec_Ptr_t* vBmiter2Spec; +Vec_Ptr_t* vBmiter2Impl; +Vec_Int_t* vPatch2Impl; +Vec_Bit_t* vImpl2Spec_phase; +Vec_Int_t* vBI_patch; +Vec_Int_t* vBO_patch; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -5702,186 +5705,55 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, Gia_ManConst0(p1)->Value = 0; Gia_ManConst0(p2)->Value = 0; - // allocate vMarkBmiter - vMarkBmiter = Vec_IntAlloc( (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)) ); - Vec_IntFill( vMarkBmiter, (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)), 0 ); - printf( "allocated size: %d\n", Vec_IntSize(vMarkBmiter) ); + // allocate vImpl2Spec_phase; + vImpl2Spec_phase = Vec_BitAlloc( Gia_ManObjNum(p2) ); + Vec_BitFill( vImpl2Spec_phase, Gia_ManObjNum(p2), 0 ); + + // allocate vBmiter2Impl and vBmiter2Spec + Vec_Int_t* pVec_Int; + vBmiter2Impl = Vec_PtrAlloc( (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)) ); + Vec_PtrFill( vBmiter2Impl, (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)), 0 ); + Vec_PtrForEachEntry( Vec_Int_t*, vBmiter2Impl, pVec_Int, i) + { + Vec_PtrSetEntry(vBmiter2Impl, i, Vec_IntAlloc(2) ); + } + vBmiter2Spec = Vec_PtrAlloc( (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)) ); + Vec_PtrFill( vBmiter2Spec, (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)), 0 ); + Vec_PtrForEachEntry( Vec_Int_t*, vBmiter2Spec, pVec_Int, i) + { + Vec_PtrSetEntry(vBmiter2Spec, i, Vec_IntAlloc(2) ); + } Gia_ManForEachCi( p1, pObj, i ) { - int id = pObj->Value = Gia_ManCi(p2, i)->Value = Gia_ManAppendCi( pNew ); - Vec_IntSetEntry( vMarkBmiter, id >> 1, 4 ); + pObj->Value = Gia_ManCi(p2, i)->Value = Gia_ManAppendCi( pNew ); + Vec_IntPush( Vec_PtrEntry(vBmiter2Spec, pObj->Value >> 1), Gia_ObjId(p1, pObj) ); + Vec_IntPush( Vec_PtrEntry(vBmiter2Impl, pObj->Value >> 1), Gia_ObjId(p1, pObj) ); // same pi id in impl and spec } // TODO: record the corresponding impl node of each lit - Gia_ManForEachAnd( p2, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - Vec_IntUpdateEntry( vMarkBmiter, pObj->Value >> 1, 3 ); + Vec_IntPush( Vec_PtrEntry(vBmiter2Impl, pObj->Value >> 1), Gia_ObjId(p2, pObj) ); } - // TODO: find nodes in spec - - Vec_Int_t * vTypeSpec = Vec_IntAlloc( 16 ); - Vec_IntFill( vTypeSpec, Gia_ManObjNum(p1), 0 ); - int n = Gia_ManBufNum(p1) / 2; - if(biNum > 0){ - n = biNum; - } - - Gia_ManStaticFanoutStart( p1 ); - Vec_Ptr_t * vQ = Vec_PtrAlloc(16); - Vec_Ptr_t * vBO = Vec_PtrAlloc(16); - Gia_Obj_t * pObj2; - int c1 = 0; - int c2 = 0; - int count = 0; - - vIdBI = Vec_IntAlloc(16); - vIdBO = Vec_IntAlloc(16); - - Gia_ManForEachBuf( p1, pObj, i ) - { - if ( count < n ) - { - Vec_IntSetEntry( vTypeSpec, Gia_ObjId( p1, pObj ), 1 ); - c1++; - count ++; - - Vec_PtrPush( vQ, Gia_ObjFanin0(pObj) ); - Vec_PtrPush( vQ, Gia_ObjFanin1(pObj) ); - while ( Vec_PtrSize(vQ) != 0 ) - { - pObj2 = Vec_PtrPop(vQ); - if ( Vec_IntEntry( vTypeSpec, Gia_ObjId(p1, pObj2) ) != 0 ) continue; - c1 ++; - Vec_IntSetEntry( vTypeSpec, Gia_ObjId(p1, pObj2), 1 ); - if ( Gia_ObjFaninNum(p1, pObj2) > 0 ) Vec_PtrPush( vQ, Gia_ObjFanin0(pObj2) ); - if ( Gia_ObjFaninNum(p1, pObj2) > 1 ) Vec_PtrPush( vQ, Gia_ObjFanin1(pObj2) ); - } - - } - else - { - Vec_IntSetEntry( vTypeSpec, Gia_ObjId( p1, pObj ), 2 ); - Vec_PtrPush( vBO, pObj ); - c2 ++; - - int j; - // pObj = Gia_ObjFanin0(pObj); - Gia_ObjForEachFanoutStatic(p1, pObj, pObj2, j) - { - Vec_PtrPush( vQ, pObj2 ); - } - while ( Vec_PtrSize(vQ) != 0 ) - { - pObj2 = Vec_PtrPop(vQ); - if ( Vec_IntEntry( vTypeSpec, Gia_ObjId(p1, pObj2) ) != 0 ) continue; - Vec_IntSetEntry( vTypeSpec, Gia_ObjId(p1, pObj2), 2 ); - c2 ++; - for( int j = 0; j < Gia_ObjFanoutNum(p1, pObj2); j++ ) - { - Vec_PtrPush( vQ, Gia_ObjFanout(p1, pObj2, j) ); - } - } - - } - } - - Vec_Int_t* vFlag = Vec_IntAlloc( Gia_ManObjNum(p1) ); - Vec_IntFill( vFlag, Gia_ManObjNum(p1), 0 ); - int id; - int count_node = 0; - - // count nodes - Vec_PtrForEachEntry( Gia_Obj_t*, vBO, pObj, i ) - { - Vec_PtrPush( vQ, pObj ); - } - while( Vec_PtrSize(vQ) > 0 ) - { - pObj = Vec_PtrPop(vQ); - id = Gia_ObjId( p1, pObj ); - if ( Vec_IntEntry( vFlag, Gia_ObjId(p1, pObj) ) != 0 ) continue; - Vec_IntSetEntry( vFlag, Gia_ObjId(p1, pObj), 1 ); - count_node ++; - - if ( Vec_IntEntry( vTypeSpec, id ) == 1 ) - { - continue; - } - else - { - if ( Gia_ObjFaninNum(p1, pObj) > 0 ) Vec_PtrPush( vQ, Gia_ObjFanin0(pObj) ); - if ( Gia_ObjFaninNum(p1, pObj) > 1 ) Vec_PtrPush( vQ, Gia_ObjFanin1(pObj) ); - } - } - printf( "BI: %d, BO: %d, Box Size: %d\n", n, Gia_ManBufNum(p1)-n, count_node ); - - - Gia_ManStaticFanoutStop( p1 ); - - printf( "spec: fanin: %d / fanout: %d / total %d\n", c1, c2, Gia_ManObjNum(p1) ); - - // TODO: record hashed equivalent nodes - - count = 0; Gia_ManForEachAnd( p1, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - if ( Vec_IntEntry( vTypeSpec, Gia_ObjId( p1, pObj) ) > 0 ) - { - if ( Vec_IntGetEntry( vMarkBmiter, pObj->Value >> 1 ) == 3 ) // eq node in impl - { - Vec_IntUpdateEntry( vMarkBmiter, pObj->Value >> 1, 3 + Vec_IntEntry( vTypeSpec, Gia_ObjId( p1, pObj) ) ); - } - else - { - Vec_IntUpdateEntry( vMarkBmiter, pObj->Value >> 1, Vec_IntEntry( vTypeSpec, Gia_ObjId( p1, pObj) ) ); - } - } - if ( Gia_ObjIsBuf(pObj) ) - { - Vec_IntPush( vLits, pObj->Value ); - if ( count < n ) - { - Vec_IntPush( vIdBI, (pObj->Value) >> 1 ); - } - else - { - Vec_IntPush( vIdBO, (pObj->Value) >> 1 ); - } - count ++; - } + Vec_IntPush( Vec_PtrEntry(vBmiter2Spec, pObj->Value >> 1), Gia_ObjId(p1, pObj) ); } - - int e, c3=0, c4=0, c5=0; - c1 = 0; c2 = 0; - - Vec_IntForEachEntry( vMarkBmiter, e, i ) - { - switch (e) - { - case 1: c1++; break; - case 2: c2++; break; - case 3: c3++; break; - case 4: c4++; break; - case 5: c5++; break; - default: - break; - } - } - printf("(strash) impl: eq_fanin: %d / eq_fanout: %d / total: %d\n", c4, c5, c3+c4+c5); - Gia_ManForEachCo( p2, pObj, i ) { - int id = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ) << 1; - Vec_IntSetEntry( vMarkBmiter, id, 5 ); + int id = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ) >> 1; + Vec_IntPush( Vec_PtrEntry(vBmiter2Impl, id), Gia_ObjId(p2, pObj) ); } Gia_ManForEachCo( p1, pObj, i ) - Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + { + int id = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ) >> 1; + Vec_IntPush( Vec_PtrEntry(vBmiter2Spec, id), Gia_ObjId(p1, pObj) ); + } Vec_IntForEachEntry( vLits, iLit, i ) Gia_ManAppendCo( pNew, iLit ); Vec_IntFree( vLits ); @@ -6024,6 +5896,538 @@ Gia_Man_t * Gia_ManMiterFromBMiter( Gia_Man_t * p, int nPo ) return pNew; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPatch( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int biNum) +{ + Vec_Int_t * vLits; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iLit; + if ( Gia_ManBufNum(p1) == 0 ) { + printf( "The first AIG should have a boundary.\n" ); + return NULL; + } + if ( Gia_ManBufNum(p2) == 0 ) { + printf( "The second AIG should have a boundary.\n" ); + return NULL; + } + assert( Gia_ManBufNum(p1) > 0 ); + assert( Gia_ManBufNum(p2) > 0 ); + assert( Gia_ManBufNum(p1) == Gia_ManBufNum(p2) ); + assert( Gia_ManRegNum(p1) == 0 ); + assert( Gia_ManRegNum(p2) == 0 ); + assert( Gia_ManCiNum(p1) == Gia_ManCiNum(p2) ); + assert( Gia_ManCoNum(p1) == Gia_ManCoNum(p2) ); + if ( fVerbose ) + printf( "Mapping spec to patch with %d inputs, %d outputs, and %d buffers.\n", + Gia_ManCiNum(p1), Gia_ManCoNum(p1), Gia_ManBufNum(p1) ); + pNew = Gia_ManStart( Gia_ManObjNum(p2) ); + pNew->pName = ABC_ALLOC( char, strlen(p1->pName) + 10 ); + sprintf( pNew->pName, "%s_patch", p1->pName ); + Gia_ManHashStart( pNew ); + Gia_ManConst0(p1)->Value = 0; + Gia_ManConst0(p2)->Value = 0; + + // add patch aig first + // record lit -> patch id + Vec_Int_t* vVar2Patch = Vec_IntAlloc( Gia_ManObjNum(p2) ); + Vec_IntFill( vVar2Patch, Gia_ManObjNum(p2), -1 ); + + Gia_ManForEachCi( p2, pObj, i ) + { + pObj->Value = Gia_ManCi(p1, i)->Value = Gia_ManAppendCi( pNew ); + Vec_IntSetEntry( vVar2Patch, pObj->Value >> 1, Gia_ObjId( p2, pObj ) ); + } + Gia_ManForEachAnd( p2, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + printf( "\t%d: %d %d\n", Gia_ObjId( p2, pObj), Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Vec_IntSetEntry( vVar2Patch, pObj->Value >> 1, Gia_ObjId( p2, pObj ) ); + } + + + // alloc vCompl; + Vec_Bit_t * vComplBuf = Vec_BitAlloc(Gia_ManBufNum(p1)); + Vec_Bit_t * vCompl = Vec_BitAlloc(Gia_ManObjNum(p1)); + Vec_BitFill( vCompl, Gia_ManObjNum(p1), 0 ); + Gia_ManForEachBuf( p2, pObj, i ) + { + printf("\tbuf compl %d: %d\n", Gia_ObjId(p2, pObj), Gia_ObjFaninC0(pObj)); + Vec_BitPush( vComplBuf, Gia_ObjFaninC0(pObj) ); + } + int cnt = 0; + Gia_ManForEachBuf( p1, pObj, i ) + { + printf("\tbuf compl %d: %d\n", Gia_ObjId(p1, pObj), Gia_ObjFaninC0(pObj)); + if ( Vec_BitEntry( vComplBuf, cnt ) || Gia_ObjFaninC0(pObj) ) + { + Vec_BitSetEntry( vCompl, Gia_ObjId( p1, pObj ), 1 ); + printf("\tset\n"); + } + cnt++; + } + + + + // mark the box in spec + Vec_Int_t* vFlagSpec = Vec_IntAlloc( Gia_ManObjNum(p1) ); // 1: bi, 2: inside the box, 3: bo + Vec_IntFill( vFlagSpec, Gia_ManObjNum(p1), 0 ); + int cnt_buf = 0; + Gia_ManForEachBuf( p1, pObj, i ) + { + if ( cnt_buf < biNum ) + { + Vec_IntSetEntry( vFlagSpec, Gia_ObjId(p1, Gia_ObjFanin0(pObj) ), 1 ); + } + else + { + Vec_IntSetEntry( vFlagSpec, Gia_ObjId(p1, Gia_ObjFanin0(pObj) ), 3 ); + } + cnt_buf ++; + } + + int fanin0, fanin1; + Gia_ManForEachAnd( p1, pObj, i ) + { + if ( Vec_IntEntry( vFlagSpec, Gia_ObjId(p1, pObj) ) != 0 ) continue ; + fanin0 = Vec_IntEntry( vFlagSpec, Gia_ObjId(p1, Gia_ObjFanin0(pObj) ) ); + fanin1 = Vec_IntEntry( vFlagSpec, Gia_ObjId(p1, Gia_ObjFanin1(pObj) ) ); + if ( fanin0 == 1 || fanin0 == 2 || fanin1 == 1 || fanin1 == 2 ) + Vec_IntSetEntry( vFlagSpec, Gia_ObjId(p1, pObj ), 2 ); + } + + + // compute spec2impl + Vec_Int_t* vSpec2Impl = Vec_IntAlloc( Gia_ManObjNum(p1) ); + Vec_IntFill( vSpec2Impl, Gia_ManObjNum(p1), -1 ); + Vec_Int_t* vSpec, *vImpl; + int j, id; + for ( i = 0; i < Vec_PtrSize( vBmiter2Spec ); i++ ) + { + vSpec = Vec_PtrEntry( vBmiter2Spec, i ); + vImpl = Vec_PtrEntry( vBmiter2Impl, i ); + Vec_IntForEachEntry( vSpec, id, j ) + { + if ( Vec_IntEntry( vSpec2Impl, id ) == -1 && Vec_IntSize( vImpl ) > 0 ) + { + Vec_IntSetEntry( vSpec2Impl, id, Vec_IntEntry( vImpl, 0 ) ); + } + } + } + + // print + // printf("spec 2 impl:\n"); + // Vec_IntForEachEntry( vSpec2Impl, id, i ) + // { + // printf( "\t%d:\t %d\n", i, id ); + // } + + // alloc patch2impl + vPatch2Impl = Vec_IntAlloc( Gia_ManObjNum(p2) ); + Vec_IntFill( vPatch2Impl, Gia_ManObjNum(p2), -1 ); + Vec_IntSetEntry( vPatch2Impl, 0, 0 ); + + Gia_ManForEachCi( p2, pObj, i ) + { + Vec_IntSetEntry( vVar2Patch, pObj->Value >> 1, pObj->Value >> 1); + Vec_IntSetEntry( vPatch2Impl, pObj->Value>>1, Vec_IntEntry( vSpec2Impl, pObj->Value>>1) ); + } + + // set the litral on the boundary of spec as in patch and record patch2impl + Vec_Int_t* vBufLit = Vec_IntAlloc( Gia_ManBufNum( p2 ) ); + vBI_patch = Vec_IntAlloc( Gia_ManBufNum(p2) ); + vBO_patch = Vec_IntAlloc( Gia_ManBufNum(p2) ); + cnt_buf = 0; + Gia_ManForEachBuf( p2, pObj, i ) + { + // TODO: check compl + Vec_IntPush( vBufLit, Gia_ObjFanin0( pObj ) -> Value ); + if ( cnt_buf < biNum ) + { + Vec_IntPush( vBI_patch, Gia_ObjFanin0( pObj) -> Value >> 1 ); + } + else + { + Vec_IntPush( vBO_patch, Gia_ObjFanin0( pObj) -> Value >> 1 ); + } + cnt_buf++; + } + Vec_Int_t* vSpec2Patch = Vec_IntAlloc( Gia_ManObjNum(p1) ); + Vec_IntFill( vSpec2Patch, Gia_ManObjNum(p1), -1 ); + + cnt_buf = 0; + Gia_Obj_t * pObj2; + + Gia_ManForEachBuf( p1, pObj, i ) + { + // TODO: compl? + pObj2 = Gia_ObjFanin0(pObj); + pObj2 -> Value = Vec_IntEntry( vBufLit, cnt_buf ); + Vec_IntSetEntry( vSpec2Patch, Gia_ObjId( p1, pObj2 ), Vec_IntEntry( vVar2Patch, pObj2->Value>>1 ) ); + // printf( "spec node %d -> patch node %d\n", Gia_ObjId( p1, pObj2 ), Vec_IntEntry( vVar2Patch, pObj2->Value>>1 ) ); + + Vec_IntSetEntry( vPatch2Impl, pObj2 -> Value>>1, Vec_IntEntry( vSpec2Impl, Gia_ObjId(p1, pObj2) ) ); + pObj->Value = pObj2->Value; + cnt_buf++; + } + + + // hash the area outside the box in spec and record patch2impl + int lit0, lit1; + Gia_ManForEachAnd( p1, pObj, i ) { + printf( "spec node %d(%d) = %d %d\n", Gia_ObjId( p1, pObj ), Vec_IntEntry( vFlagSpec, Gia_ObjId(p1, pObj)), Gia_ObjId( p1, Gia_ObjFanin0(pObj) ), Gia_ObjId( p1, Gia_ObjFanin1(pObj) ) ); + if ( Vec_IntEntry( vFlagSpec, Gia_ObjId(p1, pObj) ) > 1 ) continue; + if ( Gia_ObjIsBuf(pObj) ) continue; + + lit0 = Gia_ObjFanin0Copy(pObj); + lit1 = Gia_ObjFanin1Copy(pObj); + if ( Vec_BitEntry( vCompl, Gia_ObjId(p1, Gia_ObjFanin0(pObj) ) ) ) lit0 ^= 1; + if ( Vec_BitEntry( vCompl, Gia_ObjId(p1, Gia_ObjFanin1(pObj) ) ) ) lit1 ^= 1; + pObj->Value = Gia_ManHashAnd( pNew, lit0, lit1 ); + + + assert( (pObj->Value>>1) < Vec_IntSize( vVar2Patch) ); + assert( Vec_IntEntry( vVar2Patch, pObj->Value>>1 ) != -1 ); + + Vec_IntSetEntry( vSpec2Patch, Gia_ObjId( p1, pObj ), Vec_IntEntry( vVar2Patch, pObj->Value>>1 ) ); + printf( "spec node %d -> patch node %d\n", Gia_ObjId( p1, pObj ), Vec_IntEntry( vVar2Patch, pObj->Value>>1 ) ); + + Vec_IntSetEntry( vPatch2Impl, pObj->Value >> 1, Vec_IntEntry( vSpec2Impl, Gia_ObjId(p1, pObj) ) ); + } + + + // print + printf("patch 2 impl:\n"); + Vec_IntForEachEntry( vPatch2Impl, id, i ) + { + printf( "\t%d:\t %d\n", i, id ); + } + + // handle co + Gia_ManForEachCo( p2, pObj, i ) + { + int id = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ) >> 1; + } + // TODO: also check spec CO + // Gia_ManForEachCo( p1, pObj, i ) + // { + // int id = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ) >> 1; + // Vec_IntPush( Vec_PtrEntry(vBmiter2Spec, id), Gia_ObjId(p1, pObj) ); + // } + + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +Gia_Man_t * Gia_ManPatchImpl( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int biNum) +{ + Vec_Int_t * vLits; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, *pObj2; + int i, j, iLit, id, id2; + assert( Gia_ManRegNum(p1) == 0 ); + assert( Gia_ManRegNum(p2) == 0 ); + assert( Gia_ManCiNum(p1) == Gia_ManCiNum(p2) ); + assert( Gia_ManCoNum(p1) == Gia_ManCoNum(p2) ); + if ( fVerbose ) + printf( "Mapping spec to patch with %d inputs, %d outputs, and %d buffers.\n", + Gia_ManCiNum(p1), Gia_ManCoNum(p1), Gia_ManBufNum(p1) ); + pNew = Gia_ManStart( Gia_ManObjNum(p2) ); + pNew->pName = ABC_ALLOC( char, strlen(p1->pName) + 10 ); + sprintf( pNew->pName, "%s_patch", p1->pName ); + Gia_ManHashStart( pNew ); + Gia_ManConst0(p1)->Value = 0; + Gia_ManConst0(p2)->Value = 0; + + + // p1: patch + // p2: impl + + // compute extended box + + Gia_ManStaticFanoutStart( p1 ); + Vec_Ptr_t* vBO = Vec_PtrAlloc(16); + Vec_Ptr_t* vBI = Vec_PtrAlloc(16); + Vec_Ptr_t* vAO = Vec_PtrAlloc(16); + Vec_Ptr_t* vAI = Vec_PtrAlloc(16); + + + + Vec_Ptr_t* vQ = Vec_PtrAlloc(16); + Vec_Int_t* vFlag = Vec_IntAlloc( Gia_ManObjNum(p1) ); + Vec_IntFill( vFlag, Gia_ManObjNum(p1), 0 ); + Vec_IntForEachEntry( vBO_patch, id, i ) + { + if ( Vec_IntEntry( vPatch2Impl, id ) == -1 ) // if no match on the boundary + Vec_PtrPush( vQ, p1->pObjs+id ); + else + Vec_PtrPush( vBO, p1->pObjs+id ); + } + + while( Vec_PtrSize(vQ) > 0 ) + { + pObj = Vec_PtrPop(vQ); + id = Gia_ObjId( p1, pObj ); + + if ( Vec_IntEntry( vFlag, id ) == 1 ) continue; + Vec_IntSetEntry( vFlag, id, 1 ); + + printf("%d\n", id); + + if ( Vec_IntEntry( vPatch2Impl, id ) != -1 ) // matched + { + Vec_PtrPush( vAO, pObj ); + } + else + { + for( j = 0; j < Gia_ObjFanoutNum(p1, pObj); j++ ) + { + Vec_PtrPush( vQ, Gia_ObjFanout(p1, pObj, j) ); + printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanout(p1, pObj, j) ) ); + } + + } + } + + // set flag 2 for FOC + Vec_IntForEachEntry( vBO_patch, id, i ) + { + Vec_PtrPush( vQ, p1->pObjs+id ); + } + while( Vec_PtrSize(vQ) > 0 ) + { + pObj = Vec_PtrPop(vQ); + id = Gia_ObjId( p1, pObj ); + + if ( Vec_IntEntry( vFlag, Gia_ObjId(p1, pObj) ) == 2 ) continue; + Vec_IntSetEntry( vFlag, Gia_ObjId(p1, pObj), 2 ); + + for( j = 0; j < Gia_ObjFanoutNum(p1, pObj); j++ ) + { + Vec_PtrPush( vQ, Gia_ObjFanout(p1, pObj, j) ); + } + } + + // set flag 3 for BO + Vec_IntForEachEntry( vBO_patch, id, i ) + { + Vec_IntSetEntry( vFlag, id, 3 ); + } + + // traverse down from unmated BI and AO + Vec_IntForEachEntry( vBI_patch, id, i ) + { + if ( Vec_IntEntry( vPatch2Impl, id ) == -1 ) // if no match on the boundary + Vec_PtrPush( vQ, p1->pObjs+id ); + else + Vec_PtrPush( vBI, p1->pObjs+id ); + } + Vec_PtrForEachEntry( Gia_Obj_t*, vAO, pObj, i ) + { + Vec_PtrPush( vQ, pObj ); + } + + // traverse down + printf("traverse down\n"); + while ( Vec_PtrSize(vQ) != 0 ) + { + pObj = Vec_PtrPop(vQ); + id = Gia_ObjId( p1, pObj ); + if ( Vec_IntEntry( vFlag, id ) == 4 ) continue; + + printf("%d\n", id); + + if ( Vec_IntEntry( vPatch2Impl, id ) != -1 && Vec_IntEntry( vFlag, id ) < 2 ) // matched + { + Vec_PtrPush( vAI, pObj ); + printf("matched\n"); + } + else if ( Vec_IntEntry( vFlag, id ) < 3 ) + { + if ( Gia_ObjFaninNum(p1, pObj) > 0 ) + { + Vec_PtrPush( vQ, Gia_ObjFanin0(pObj) ); + printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanin0(pObj) ) ); + } + + if ( Gia_ObjFaninNum(p1, pObj) > 1 ) + { + Vec_PtrPush( vQ, Gia_ObjFanin1(pObj) ); + printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanin1(pObj) ) ); + } + } + printf("2impl / flag: %d / %d\n", Vec_IntEntry( vPatch2Impl, id ), Vec_IntEntry( vFlag, id ) ); + + Vec_IntSetEntry( vFlag, id, 4 ); + } + + + // print + printf( "matched BI:"); + Vec_PtrForEachEntry( Gia_Obj_t*, vBI, pObj, i ) printf( " %d(%d)", Gia_ObjId( p1, pObj ), Vec_IntEntry( vPatch2Impl, Gia_ObjId(p1, pObj)) ); + printf("\nAI:"); + Vec_PtrForEachEntry( Gia_Obj_t*, vAI, pObj, i ) printf( " %d(%d)", Gia_ObjId( p1, pObj ), Vec_IntEntry( vPatch2Impl, Gia_ObjId(p1, pObj)) ); + printf("\nmateched BO:"); + Vec_PtrForEachEntry( Gia_Obj_t*, vBO, pObj, i ) printf( " %d(%d)", Gia_ObjId( p1, pObj ), Vec_IntEntry( vPatch2Impl, Gia_ObjId(p1, pObj)) ); + printf("\nAO:"); + Vec_PtrForEachEntry( Gia_Obj_t*, vAO, pObj, i ) printf( " %d(%d)", Gia_ObjId( p1, pObj ), Vec_IntEntry( vPatch2Impl, Gia_ObjId(p1, pObj)) ); + printf("\n"); + + // create patched impl + + // mark fanin cone of Extended Input in impl + Vec_Int_t* vFlag_impl = Vec_IntAlloc( Gia_ManObjNum(p2) ); + Vec_IntFill( vFlag_impl, Gia_ManObjNum(p2), 0 ); + + Vec_PtrForEachEntry( Gia_Obj_t*, vBI, pObj, i ) + { + Vec_PtrPush( vQ, p2->pObjs + Vec_IntEntry( vPatch2Impl, Gia_ObjId(p1, pObj) ) ); + } + Vec_PtrForEachEntry( Gia_Obj_t*, vAI, pObj, i ) + { + Vec_PtrPush( vQ, p2->pObjs + Vec_IntEntry( vPatch2Impl, Gia_ObjId(p1, pObj) ) ); + } + + while ( Vec_PtrSize(vQ) != 0 ) + { + pObj = Vec_PtrPop(vQ); + id = Gia_ObjId( p2, pObj ); + if ( Vec_IntEntry( vFlag_impl, id ) == 1 ) continue; + Vec_IntSetEntry( vFlag_impl, id, 1 ); + + if ( Gia_ObjFaninNum(p2, pObj) > 0 ) Vec_PtrPush( vQ, Gia_ObjFanin0(pObj) ); + if ( Gia_ObjFaninNum(p2, pObj) > 1 ) Vec_PtrPush( vQ, Gia_ObjFanin1(pObj) ); + } + + // add pi + Gia_ManForEachCi( p2, pObj, i ) + { + pObj->Value = Gia_ManCi(p1, i)->Value = Gia_ManAppendCi( pNew ); + } + // add fanin cone of EI in impl + int cnt = 0; + Gia_ManForEachAnd( p2, pObj, i ) + { + if ( Vec_IntEntry( vFlag_impl, Gia_ObjId(p2, pObj) ) == 0 ) continue; + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + printf( "%d\n", pObj->Value>>1 ); + cnt ++; + } + printf( "%d node added in the fanin cone of EI\n", cnt ); + // set literal and flag of EI in patch + // TODO: input phase + Vec_PtrForEachEntry( Gia_Obj_t*, vBI, pObj, i ) + { + id = Gia_ObjId( p1, pObj ); + pObj -> Value = ( p2 -> pObjs + Vec_IntEntry( vPatch2Impl, id ) ) -> Value; + Vec_IntSetEntry( vFlag, id, 5 ); + } + Vec_PtrForEachEntry( Gia_Obj_t*, vAI, pObj, i ) + { + id = Gia_ObjId( p1, pObj ); + pObj -> Value = ( p2 -> pObjs + Vec_IntEntry( vPatch2Impl, id ) ) -> Value; + Vec_IntSetEntry( vFlag, id, 5 ); + } + // mark fanin cone of EO in patch (to flag 5) + Vec_PtrForEachEntry( Gia_Obj_t*, vBO, pObj, i ) + Vec_PtrPush( vQ, pObj ); + Vec_PtrForEachEntry( Gia_Obj_t*, vAO, pObj, i ) + Vec_PtrPush( vQ, pObj ); + while ( Vec_PtrSize(vQ) != 0 ) + { + pObj = Vec_PtrPop(vQ); + id = Gia_ObjId( p1, pObj ); + if ( Vec_IntEntry( vFlag, id ) >= 5 ) continue; + Vec_IntSetEntry( vFlag, id, 6 ); + + if ( Gia_ObjFaninNum(p1, pObj) > 0 ) Vec_PtrPush( vQ, Gia_ObjFanin0(pObj) ); + if ( Gia_ObjFaninNum(p1, pObj) > 1 ) Vec_PtrPush( vQ, Gia_ObjFanin1(pObj) ); + } + // add fanin cone of EO to EI in patch + cnt = 0; + Gia_ManForEachAnd( p1, pObj, i ) + { + if ( Vec_IntEntry( vFlag, Gia_ObjId(p1, pObj) ) != 6 ) continue; + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + printf( "%d\n", pObj->Value>>1 ); + cnt ++; + } + printf( "%d node added in the extended boundary\n", cnt ); + + // set literal and flag(1) of EO in impl + Vec_PtrForEachEntry( Gia_Obj_t*, vBO, pObj, i ) + { + id = Gia_ObjId( p1, pObj ); + id2 = Vec_IntEntry( vPatch2Impl, id ); + pObj2 = p2 -> pObjs + id2; + pObj2 -> Value = pObj -> Value; + if ( Vec_BitEntry( vImpl2Spec_phase, id2 ) ) pObj2 -> Value ^= 1; + Vec_IntSetEntry( vFlag_impl, id2, 1 ); + } + Vec_PtrForEachEntry( Gia_Obj_t*, vAO, pObj, i ) + { + id = Gia_ObjId( p1, pObj ); + id2 = Vec_IntEntry( vPatch2Impl, id ); + pObj2 = p2 -> pObjs + id2; + pObj2 -> Value = pObj -> Value; + printf( "id %d matched to id %d in impl, phase %d\n", id, id2, Vec_BitEntry( vImpl2Spec_phase, id2 ) ); + if ( Vec_BitEntry( vImpl2Spec_phase, id2 ) ) pObj2 -> Value ^= 1; + Vec_IntSetEntry( vFlag_impl, id2, 1 ); + } + + // add flag 0 in impl + cnt = 0; + Gia_ManForEachAnd( p2, pObj, i ) + { + if ( Vec_IntEntry( vFlag_impl, Gia_ObjId(p2, pObj) ) != 0 ) continue; + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + printf( "%d\n", pObj->Value>>1 ); + cnt++; + } + printf( "%d node added in the fanout cone\n", cnt ); + + // handle co + cnt = 0; + Gia_ManForEachCo( p2, pObj, i ) + { + id = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ) >> 1; + printf( "%d\n", id ); + cnt ++; + } + + Gia_ManStaticFanoutStop( p1 ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index dab809c25..1a837d030 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -598,6 +598,7 @@ static int Abc_CommandAbc9AddFlop ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9BMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenHie ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9RecoverBoundary ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9StrEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1378,6 +1379,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&bmiter", Abc_CommandAbc9BMiter, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&gen_hie", Abc_CommandAbc9GenHie, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&rb", Abc_CommandAbc9RecoverBoundary, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&str_eco", Abc_CommandAbc9StrEco, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); { @@ -51953,6 +51955,111 @@ usage: return 1; } +int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManPatch( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int biNum); + extern Gia_Man_t * Gia_ManPatchImpl( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int biNum); + Gia_Man_t * pTemp, * pSecond, *pImpl, *pPatched; + char * FileName = NULL; + char * FileName2 = NULL; + FILE * pFile = NULL; + int c, fVerbose = 0; + int bi = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + bi = atoi(argv[globalUtilOptind++]); + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9StrEco(): There is no AIG.\n" ); + return 0; + } + if ( argc != globalUtilOptind + 2 ) + { + printf("%d\n", argc-globalUtilOptind); + Abc_Print( -1, "Abc_CommandAbc9StrEco(): AIG should be given on the command line.\n" ); + return 0; + } + + // get the input file name + FileName = argv[globalUtilOptind]; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", ".blif", ".pla", ".eqn", ".bench" )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + + // get the input file name 2 + FileName2 = argv[globalUtilOptind+1]; + if ( (pFile = fopen( FileName2, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName2 ); + if ( (FileName2 = Extra_FileGetSimilarName( FileName2, ".aig", ".blif", ".pla", ".eqn", ".bench" )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName2 ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + + // map spec to patch + pSecond = Gia_AigerRead( FileName, 0, 1, 0 ); + if ( pSecond == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9StrEco(): Cannot read the file name on the command line.\n" ); + return 0; + } + pTemp = Gia_ManPatch( pAbc->pGia, pSecond, fVerbose, bi); + // Gia_ManStop( pSecond ); + // Abc_FrameUpdateGia( pAbc, pTemp ); + // return 0; + + // generated patched impl + pImpl = Gia_AigerRead( FileName2, 0, 0, 0 ); + if ( pImpl == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9StrEco(): Cannot read the file name on the command line.\n" ); + return 0; + } + pPatched = Gia_ManPatchImpl( pTemp, pImpl, fVerbose, bi); + + Gia_ManStop( pSecond ); + Gia_ManStop( pImpl ); + Gia_ManStop( pTemp ); + Abc_FrameUpdateGia( pAbc, pPatched ); + return 0; + +usage: + Abc_Print( -2, "usage: &str_eco -I [-vh] \n" ); + Abc_Print( -2, "\t creates the boundary miter\n" ); + Abc_Print( -2, "\t-I : number of boundary inputs\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the implementation file\n"); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 7377367e2..0659b3f60 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -147,6 +147,8 @@ static inline void Cec4_ObjCleanSatId( Gia_Man_t * p, Gia_Obj_t * pObj ) extern Vec_Int_t* vMarkBmiter; extern Vec_Int_t* vIdBI; extern Vec_Int_t* vIdBO; +extern Vec_Ptr_t* vBmiter2Spec; +extern Vec_Ptr_t* vBmiter2Impl; //////////////////////////////////////////////////////////////////////// @@ -1788,6 +1790,8 @@ void Gia_ManRemoveWrongChoices( Gia_Man_t * p ) } //Abc_Print( 1, "Removed %d wrong choices.\n", Counter ); } + +extern Vec_Bit_t* vImpl2Spec_phase; int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** ppNew, int fSimOnly ) { Cec4_Man_t * pMan = Cec4_ManCreate( p, pPars ); @@ -1890,45 +1894,24 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p if ( Abc_Lit2Var(pObj->Value) == Abc_Lit2Var(pRepr->Value) ) { - // printf( "*node %d (%d) merged into node %d (%d)\n", id_obj, Vec_IntEntry( vMarkBmiter, id_obj ), id_repr, Vec_IntEntry( vMarkBmiter, id_repr) ); if ( pPars->fBMiterInfo ) { - if ( Vec_IntEntry( vMarkBmiter, id_repr ) == 3 ) + int eId, j; + Vec_Int_t *vIds_spec_repr, *vIds_impl_repr, *vIds_spec_obj, *vIds_impl_obj; + vIds_spec_repr = Vec_PtrEntry( vBmiter2Spec, id_repr ); + vIds_impl_repr = Vec_PtrEntry( vBmiter2Impl, id_repr ); + vIds_spec_obj = Vec_PtrEntry( vBmiter2Spec, id_obj ); + vIds_impl_obj = Vec_PtrEntry( vBmiter2Impl, id_obj ); + Vec_IntForEachEntry( vIds_spec_obj, eId, j) { - switch ( Vec_IntEntry( vMarkBmiter, id_obj ) ) - { - case 1: - case 4: - Vec_IntUpdateEntry( vMarkBmiter, id_repr, 4 ); - break; - case 2: - case 5: - Vec_IntUpdateEntry( vMarkBmiter, id_repr, 5 ); - break; - default: - break; - } + Vec_IntPush(vIds_spec_repr, eId); } - else + Vec_IntForEachEntry( vIds_impl_obj, eId, j) { - if ( Vec_IntEntry(vMarkBmiter, id_obj ) == 3 ) - switch ( Vec_IntEntry( vMarkBmiter, id_repr ) ) - { - case 1: - case 4: - Vec_IntUpdateEntry( vMarkBmiter, id_obj, 4 ); - break; - case 2: - case 5: - Vec_IntUpdateEntry( vMarkBmiter, id_obj, 5 ); - break; - default: - break; - - } + Vec_IntPush(vIds_impl_repr, eId); } - // TODO - Vec_IntSetEntry( vMarkBmiter, id_obj, Vec_IntEntry( vMarkBmiter, id_repr) ); + Vec_IntClear(vIds_spec_obj); + Vec_IntClear(vIds_impl_obj); } assert( (pObj->Value ^ pRepr->Value) == (pObj->fPhase ^ pRepr->fPhase) ); Gia_ObjSetProved( p, i ); @@ -1939,178 +1922,101 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p if ( Cec4_ManSweepNode(pMan, i, Gia_ObjId(p, pRepr)) && Gia_ObjProved(p, i) ) { if (pPars->fBMiterInfo){ - // printf( "node %d (%d) merged into node %d (%d)\n", id_obj, Vec_IntEntry( vMarkBmiter, id_obj ), id_repr, Vec_IntEntry( vMarkBmiter, id_repr ) ); - if ( Vec_IntEntry( vMarkBmiter, id_repr ) == 3 ) + + int eId, j; + Vec_Int_t *vIds_spec_repr, *vIds_impl_repr, *vIds_spec_obj, *vIds_impl_obj; + vIds_spec_repr = Vec_PtrEntry( vBmiter2Spec, id_repr ); + vIds_impl_repr = Vec_PtrEntry( vBmiter2Impl, id_repr ); + vIds_spec_obj = Vec_PtrEntry( vBmiter2Spec, id_obj ); + vIds_impl_obj = Vec_PtrEntry( vBmiter2Impl, id_obj ); + + Vec_IntForEachEntry( vIds_spec_obj, eId, j) { - switch ( Vec_IntEntry( vMarkBmiter, id_obj ) ) + Vec_IntPush(vIds_spec_repr, eId); + } + Vec_IntForEachEntry( vIds_impl_obj, eId, j) + { + Vec_IntPush(vIds_impl_repr, eId); + } + + // handle phase before cleaning + printf( "proven %d merged into %d (phase : %d)\n", Gia_ObjId(p, pObj), Gia_ObjId(p,pRepr), pObj->fPhase ^ pRepr -> fPhase ); + if ( Vec_IntSize(vIds_spec_repr) == 0 ) // no match + { + if ( pObj->fPhase ^ pRepr -> fPhase ) { - case 1: - case 4: - Vec_IntUpdateEntry( vMarkBmiter, id_repr, 4 ); - break; - case 2: - case 5: - Vec_IntUpdateEntry( vMarkBmiter, id_repr, 5 ); - break; - default: - break; + Vec_IntForEachEntry( vIds_impl_obj, eId, j ) + { + Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); + printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); + } } } - else + else if ( Vec_IntSize( vIds_spec_repr ) == Vec_IntSize( vIds_spec_obj) && Vec_IntSize( vIds_impl_obj ) == 0 ) // new match { - if ( Vec_IntEntry(vMarkBmiter, id_obj ) == 3 ) - switch ( Vec_IntEntry( vMarkBmiter, id_repr ) ) + if ( pObj->fPhase ^ pRepr -> fPhase ) + { + Vec_IntForEachEntry( vIds_impl_repr, eId, j ) { - case 1: - case 4: - Vec_IntUpdateEntry( vMarkBmiter, id_obj, 4 ); - break; - case 2: - case 5: - Vec_IntUpdateEntry( vMarkBmiter, id_obj, 5 ); - break; - default: - break; - + Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); + printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); } + printf("new match flip\n"); + } } - // TODO - Vec_IntSetEntry( vMarkBmiter, id_obj, Vec_IntEntry( vMarkBmiter, id_repr) ); + else if ( Vec_IntSize( vIds_spec_repr ) > 0 && Vec_IntSize( vIds_impl_obj ) > 0 ) // matched, merge impl + { + if ( ( pObj->fPhase ^ pRepr -> fPhase) ^ ( Vec_BitEntry( vImpl2Spec_phase, Vec_IntEntry(vIds_impl_repr, 0)) ^ Vec_BitEntry( vImpl2Spec_phase, Vec_IntEntry(vIds_impl_obj, 0)) ) ) + { + if ( Vec_IntSize( vIds_spec_repr ) == Vec_IntSize( vIds_spec_obj) ) // unmatched repr, matched obj, set repr bits + { + Vec_IntForEachEntry( vIds_impl_repr, eId, j ) + { + if ( j >= Vec_IntSize( vIds_impl_repr)-Vec_IntSize(vIds_impl_obj) ) break; + Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); + printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); + } + } + else // set obj bits + { + Vec_IntForEachEntry( vIds_impl_obj, eId, j ) + { + Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); + printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); + } + } + } + } + + Vec_IntClear(vIds_spec_obj); + Vec_IntClear(vIds_impl_obj); + } pObj->Value = Abc_LitNotCond( pRepr->Value, pObj->fPhase ^ pRepr->fPhase ); + + } } - if ( pPars->fBMiterInfo ) { - - // check bi, bo - Vec_Ptr_t* vAO = Vec_PtrAlloc( 16 ); // additioal output boundary - Vec_Ptr_t* vAI = Vec_PtrAlloc( 16 ); // additional input boundary - Vec_Ptr_t* vMI = Vec_PtrAlloc(16); // missing input boundary - Vec_Ptr_t* vMO = Vec_PtrAlloc(16); // missing input boundary - Vec_Ptr_t* vQ = Vec_PtrAlloc(16); // queue for fanout traversal - int val; - int cnt_TO = 0; - int cnt_TI = 0; - int cnt_SIDE = 0; - int cnt_MI = 0; - int cnt_MO = 0; - Vec_Int_t* vFlag = Vec_IntAlloc( p->nObjs ); - Vec_IntFill( vFlag, p->nObjs, 0 ); - - printf("BI:"); - Vec_IntForEachEntry( vIdBI, val, i ) + // print + Vec_Int_t* vIds_spec, *vIds_impl; + int k, id; + for( int j=0; j < Vec_PtrSize(vBmiter2Spec); j++ ) { - printf( " %d (%d)", val, Vec_IntEntry( vMarkBmiter, val) ); - if ( Vec_IntEntry( vMarkBmiter, val) <= 3 ) - { - Vec_PtrPush(vMI, &((p->pObjs)[val]) ); - } - else cnt_MI ++; + printf("node %d: ", j); + vIds_spec = Vec_PtrEntry( vBmiter2Spec, j); + vIds_impl = Vec_PtrEntry( vBmiter2Impl, j); + Vec_IntForEachEntry(vIds_spec, id, k) + printf("%d ", id); + printf("| "); + Vec_IntForEachEntry(vIds_impl, id, k) + printf("%d ", id); + printf("\n"); } - printf("\nBO:"); - Vec_IntForEachEntry( vIdBO, val, i ) - { - printf( " %d (%d)", val, Vec_IntEntry( vMarkBmiter, val) ); - if ( Vec_IntEntry( vMarkBmiter, val) <= 3 ) - { - Vec_PtrPush(vQ, &((p->pObjs)[val]) ); - Vec_PtrPush(vMO, &((p->pObjs)[val]) ); - Vec_IntSetEntry( vFlag, val, 2 ); - } - else cnt_MO ++; - } - printf("\n"); - - // find extended output boundary - - Gia_ManStaticFanoutStart( p ); - - Gia_Obj_t * pObj2; - cnt_TO -= Vec_PtrSize(vQ); - - while ( Vec_PtrSize(vQ) != 0 ) - { - pObj2 = Vec_PtrPop(vQ); - if ( Vec_IntEntry( vFlag, Gia_ObjId(p, pObj2) ) == 1 ) continue; - Vec_IntSetEntry( vFlag, Gia_ObjId(p, pObj2), 1 ); - cnt_TO ++; - - val = Vec_IntEntry(vMarkBmiter, Gia_ObjId(p, pObj2)); - if ( val == 5 || Gia_ObjIsCo( pObj2 ) ) // boundary found - { - Vec_PtrPush( vAO, pObj2 ); - continue; - } - - for( int j = 0; j < Gia_ObjFanoutNum(p, pObj2); j++ ) - { - Vec_PtrPush( vQ, Gia_ObjFanout(p, pObj2, j) ); - } - } - - Gia_ManStaticFanoutStop(p); - - - // find extneded input boundary - - Vec_PtrForEachEntry( Gia_Obj_t*, vMO, pObj, i ) - { - Vec_IntSetEntry( vFlag, Gia_ObjId(p, pObj), 2 ); - } - - int id; - Vec_PtrForEachEntry( Gia_Obj_t*, vMI, pObj, i ) Vec_PtrPush( vQ, pObj ); - Vec_PtrForEachEntry( Gia_Obj_t*, vAO, pObj, i ) Vec_PtrPush( vQ, pObj ); - cnt_TI -= Vec_PtrSize(vQ); - while ( Vec_PtrSize(vQ) > 0 ) - { - pObj = Vec_PtrPop(vQ); - id = Gia_ObjId( p, pObj ); - if ( Vec_IntEntry( vFlag, id ) == 2 ) continue; - printf( "backtrace to node %d\n", id ); - if ( Vec_IntEntry(vMarkBmiter, id ) != 2 ) cnt_TI ++; - Vec_IntSetEntry( vFlag, id, 2 ); - - - if ( Vec_IntEntry( vMarkBmiter, id ) >= 3 || Gia_ObjIsCi( pObj ) ) // matched - { - if ( Vec_IntEntry( vMarkBmiter, id ) < 5 || Gia_ObjIsCi( pObj ) ) - { - Vec_PtrPush( vAI, pObj ); - } - continue; - } - else - { - if ( Gia_ObjFaninNum(p, pObj) > 0 ) Vec_PtrPush( vQ, Gia_ObjFanin0(pObj) ); - if ( Gia_ObjFaninNum(p, pObj) > 1 ) Vec_PtrPush( vQ, Gia_ObjFanin1(pObj) ); - } - } - - - // print result - printf("extended BO with %d extra nodes:", cnt_TO); - Vec_PtrForEachEntry( Gia_Obj_t*, vAO, pObj, i ) - { - printf( " %d", Gia_ObjId(p, pObj) ); - } - printf("\n"); - - printf("extended BI with %d extra nodes:", cnt_TI); - Vec_PtrForEachEntry( Gia_Obj_t*, vAI, pObj, i ) - { - printf( " %d", Gia_ObjId(p, pObj) ); - } - printf("\n"); - - printf("matched BI: %d / matched BO: %d / AI: %d / AO: %d / Extra nodes: %d\n", cnt_MI, cnt_MO, Vec_PtrSize(vAI), Vec_PtrSize(vAO), cnt_TO + cnt_TI ); - } - if ( p->iPatsPi > 0 ) { abctime clk2 = Abc_Clock(); @@ -2155,7 +2061,6 @@ finalize: Gia_ManRemoveWrongChoices( p ); return p->pCexSeq ? 0 : 1; } -extern Vec_Int_t * vMarkBmiter; Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ) { Gia_Man_t * pNew = NULL; @@ -2163,22 +2068,8 @@ Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ) // TODO if (pPars -> fBMiterInfo){ - int e, i, c1=0, c2=0, c3=0, c4=0, c5=0; - Vec_IntForEachEntry( vMarkBmiter, e, i ) - { - switch (e) - { - case 1: c1++; break; - case 2: c2++; break; - case 3: c3++; break; - case 4: c4++; break; - case 5: c5++; break; - default: - break; - } - } - printf("(fraig) impl: eq_fanin: %d / eq_fanout: %d / total: %d\n", c4, c5, c3+c4+c5); } + return pNew; } void Cec4_ManSimulateTest2( Gia_Man_t * p, int nConfs, int fVerbose ) From 62a22c757454a0bf40cccb07987fdd43aad26b40 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 5 Feb 2024 19:26:36 -0800 Subject: [PATCH 080/151] Bug fix in blasting multipliers with different argument bit-width. --- src/base/wlc/wlcBlast.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c index 47d08da62..d3b2b3a05 100644 --- a/src/base/wlc/wlcBlast.c +++ b/src/base/wlc/wlcBlast.c @@ -1050,7 +1050,7 @@ void Wlc_BlastReduceMatrix2( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Int_t * v } -void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ) +void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds, int fVerbose ) { Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB ); Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB ); @@ -1064,13 +1064,17 @@ void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA } if ( fSigned ) { - Vec_WecPush( vProds, nArgA, 1 ); - Vec_WecPush( vLevels, nArgA, 0 ); + Vec_WecPush( vProds, nArgB-1, 1 ); + Vec_WecPush( vLevels, nArgB-1, 0 ); + + Vec_WecPush( vProds, nArgA-1, 1 ); + Vec_WecPush( vLevels, nArgA-1, 0 ); Vec_WecPush( vProds, nArgA+nArgB-1, 1 ); Vec_WecPush( vLevels, nArgA+nArgB-1, 0 ); } - + if ( fVerbose ) + Vec_WecPrint( vProds, 0 ); if ( pvProds ) *pvProds = Vec_WecDup(vProds); else @@ -1117,7 +1121,7 @@ void Wlc_BlastDecoder( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp, Vec_IntPush( vRes, iMint ); } } -void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ) +void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds, int fVerbose ) { Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB + 3 ); Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB + 3 ); @@ -1194,7 +1198,10 @@ void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int Vec_WecPush( vProds, k, Neg ); Vec_WecPush( vLevels, k, 0 ); } - //Vec_WecPrint( vProds, 0 ); + //Vec_WecShrink( vProds, nArgA + nArgB ); + //Vec_WecShrink( vLevels, nArgA + nArgB ); + if ( fVerbose ) + Vec_WecPrint( vProds, 0 ); //Wlc_BlastPrintMatrix( pNew, vProds, 1 ); //printf( "Cutoff ID for partial products = %d.\n", Gia_ManObjNum(pNew) ); if ( pvProds ) @@ -1832,9 +1839,9 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) if ( Wlc_NtkCountConstBits(pArg0, nRangeMax) < Wlc_NtkCountConstBits(pArg1, nRangeMax) ) ABC_SWAP( int *, pArg0, pArg1 ); if ( pPar->fBooth ) - Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned, pPar->fCla, NULL ); + Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned, pPar->fCla, NULL, pParIn->fVerbose ); else if ( pPar->fCla ) - Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes, Wlc_ObjIsSignedFanin01(p, pObj), pPar->fCla, NULL ); + Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes, Wlc_ObjIsSignedFanin01(p, pObj), pPar->fCla, NULL, pParIn->fVerbose ); else Wlc_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned ); //Wlc_BlastMultiplierC( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned ); From d7ef3cc030bcc9da0806069a0f9a25613917c6fb Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 5 Feb 2024 19:29:50 -0800 Subject: [PATCH 081/151] Bug fix in &fx. --- src/aig/gia/giaFx.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/aig/gia/giaFx.c b/src/aig/gia/giaFx.c index 032ae5fc4..c20241ed1 100644 --- a/src/aig/gia/giaFx.c +++ b/src/aig/gia/giaFx.c @@ -150,6 +150,13 @@ Vec_Wrd_t * Gia_ManComputeTruths( Gia_Man_t * p, int nCutSize, int nLutNum, int // collect and sort fanins vLeaves.nCap = vLeaves.nSize = Gia_ObjLutSize( p, i ); vLeaves.pArray = Gia_ObjLutFanins( p, i ); + if( !Vec_IntCheckUniqueSmall(&vLeaves) ) + { + Vec_IntUniqify(&vLeaves); + Vec_IntWriteEntry(p->vMapping, Vec_IntEntry(p->vMapping, i), vLeaves.nSize); + for ( k = 0; k < vLeaves.nSize; k++ ) + Vec_IntWriteEntry(p->vMapping, Vec_IntEntry(p->vMapping, i) + 1 + k, vLeaves.pArray[k]); + } assert( Vec_IntCheckUniqueSmall(&vLeaves) ); Vec_IntSelectSort( Vec_IntArray(&vLeaves), Vec_IntSize(&vLeaves) ); if ( !fReverse ) From e9a0bf6bf9989d6d140cf64e938116a3fd168e82 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 5 Feb 2024 20:32:11 -0800 Subject: [PATCH 082/151] Adding reversing of simulation bits in &sim_read. --- src/base/abci/abc.c | 12 ++++++++---- src/misc/vec/vecWrd.h | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index e0ca6e948..809d62aa5 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -34403,11 +34403,11 @@ usage: ***********************************************************************/ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) { - int c, fOutputs = 0, nWords = 4, fTruth = 0, fVerbose = 0; + int c, fOutputs = 0, nWords = 4, fTruth = 0, fReverse = 0, fVerbose = 0; char ** pArgvNew; int nArgcNew; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Wtovh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Wtrovh" ) ) != EOF ) { switch ( c ) { @@ -34425,6 +34425,9 @@ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) case 't': fTruth ^= 1; break; + case 'r': + fReverse ^= 1; + break; case 'o': fOutputs ^= 1; break; @@ -34455,7 +34458,7 @@ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } Vec_WrdFreeP( &pAbc->pGia->vSimsPi ); - pAbc->pGia->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(pAbc->pGia) ); + pAbc->pGia->vSimsPi = fReverse ? Vec_WrdStartTruthTablesRev( Gia_ManCiNum(pAbc->pGia) ) : Vec_WrdStartTruthTables( Gia_ManCiNum(pAbc->pGia) ); Vec_WrdFreeP( &pAbc->pGia->vSimsPo ); pAbc->pGia->vSimsPo = Gia_ManSimPatSimOut( pAbc->pGia, pAbc->pGia->vSimsPi, 1 ); return 0; @@ -34498,10 +34501,11 @@ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &sim_read [-W num] [-tovh] \n" ); + Abc_Print( -2, "usage: &sim_read [-W num] [-trovh] \n" ); Abc_Print( -2, "\t reads simulation patterns from file\n" ); Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", nWords ); Abc_Print( -2, "\t-t : toggle creating exhaustive simulation info [default = %s]\n", fTruth? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle reversing MSB and LSB input variables [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-o : toggle reading output information [default = %s]\n", fOutputs? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); diff --git a/src/misc/vec/vecWrd.h b/src/misc/vec/vecWrd.h index aa16771ef..b0d16efe6 100644 --- a/src/misc/vec/vecWrd.h +++ b/src/misc/vec/vecWrd.h @@ -195,6 +195,32 @@ static inline Vec_Wrd_t * Vec_WrdStartTruthTables( int nVars ) } return p; } +static inline Vec_Wrd_t * Vec_WrdStartTruthTablesRev( int nVars ) +{ + Vec_Wrd_t * p; + unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + int i, k, nWords; + nWords = nVars <= 6 ? 1 : (1 << (nVars - 6)); + p = Vec_WrdStart( nWords * nVars ); + for ( i = 0; i < nVars; i++ ) + { + unsigned * pTruth = (unsigned *)(p->pArray + nWords * (nVars-1-i)); + if ( i < 5 ) + { + for ( k = 0; k < 2*nWords; k++ ) + pTruth[k] = Masks[i]; + } + else + { + for ( k = 0; k < 2*nWords; k++ ) + if ( k & (1 << (i-5)) ) + pTruth[k] = ~(unsigned)0; + else + pTruth[k] = 0; + } + } + return p; +} static inline int Vec_WrdShiftOne( Vec_Wrd_t * p, int nWords ) { int i, nObjs = p->nSize/nWords; From 52e0a10bf75475ab97dc2474fff537e4c8cf6c86 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 5 Feb 2024 20:49:36 -0800 Subject: [PATCH 083/151] Fixing a compiler problem. --- src/base/wlc/wlc.c | 4 ++-- src/base/wln/wlnBlast.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/base/wlc/wlc.c b/src/base/wlc/wlc.c index 3ba9be96d..91656efc8 100644 --- a/src/base/wlc/wlc.c +++ b/src/base/wlc/wlc.c @@ -677,7 +677,7 @@ Gia_Man_t * Wlc_ManGenTree( int nInputs, int Value, int nBits, int fVerbose ) ***********************************************************************/ Gia_Man_t * Wlc_ManGenProd( int nInputs, int fVerbose ) { - extern void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); + extern void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds, int fVerbose ); extern void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); Vec_Int_t * vIns = Vec_IntAlloc( 2*nInputs ); Gia_Man_t * pTemp, * pNew; @@ -693,7 +693,7 @@ Gia_Man_t * Wlc_ManGenProd( int nInputs, int fVerbose ) // Vec_IntPush( vIns, Vec_IntEntry(vIns, i) ); Gia_ManHashAlloc( pNew ); - Wlc_BlastBooth( pNew, Vec_IntArray(vIns), Vec_IntArray(vIns)+nInputs, nInputs, nInputs, NULL, 0, 0, &vProds ); + Wlc_BlastBooth( pNew, Vec_IntArray(vIns), Vec_IntArray(vIns)+nInputs, nInputs, nInputs, NULL, 0, 0, &vProds, 0 ); //Wlc_BlastMultiplier3( pNew, Vec_IntArray(vIns), Vec_IntArray(vIns)+nInputs, nInputs, nInputs, NULL, 0, 0, &vProds ); //Vec_WecPrint( vProds, 0 ); Wlc_ManGenTreeOne( pNew, vProds, 1, fVerbose ); diff --git a/src/base/wln/wlnBlast.c b/src/base/wln/wlnBlast.c index 776cdd902..c3281a2e0 100644 --- a/src/base/wln/wlnBlast.c +++ b/src/base/wln/wlnBlast.c @@ -69,7 +69,7 @@ void Rtl_NtkBlastNode( Gia_Man_t * pNew, int Type, int nIns, Vec_Int_t * vDatas, extern int Wlc_BlastAdder( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int Carry ); // result is in pAdd0 extern void Wlc_BlastSubtract( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int Carry ); // result is in pAdd0 extern int Wlc_NtkCountConstBits( int * pArray, int nSize ); - extern void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); + extern void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds, int fVerbose ); extern void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); extern void Wlc_BlastZeroCondition( Gia_Man_t * pNew, int * pDiv, int nDiv, Vec_Int_t * vRes ); extern void Wlc_BlastDividerTop( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes, int fNonRest ); @@ -303,7 +303,7 @@ void Rtl_NtkBlastNode( Gia_Man_t * pNew, int Type, int nIns, Vec_Int_t * vDatas, if ( Wlc_NtkCountConstBits(Vec_IntArray(vArg0), Vec_IntSize(vArg0)) < Wlc_NtkCountConstBits(Vec_IntArray(vArg1), Vec_IntSize(vArg1)) ) ABC_SWAP( Vec_Int_t, *vArg0, *vArg1 ) if ( fBooth ) - Wlc_BlastBooth( pNew, Vec_IntArray(vArg0), Vec_IntArray(vArg1), Vec_IntSize(vArg0), Vec_IntSize(vArg1), vRes, fSigned, fCla, NULL ); + Wlc_BlastBooth( pNew, Vec_IntArray(vArg0), Vec_IntArray(vArg1), Vec_IntSize(vArg0), Vec_IntSize(vArg1), vRes, fSigned, fCla, NULL, 0 ); else Wlc_BlastMultiplier3( pNew, Vec_IntArray(vArg0), Vec_IntArray(vArg1), Vec_IntSize(vArg0), Vec_IntSize(vArg1), vRes, fSigned, fCla, NULL ); if ( nRange > Vec_IntSize(vRes) ) From 2d9af6c9a41850622f06691a0152295463efb115 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 8 Feb 2024 09:36:58 +0100 Subject: [PATCH 084/151] Adding ACD for 66 LUT structure using a new method --- src/base/abci/abc.c | 27 +- src/map/if/acd/ac_wrapper.cpp | 42 + src/map/if/acd/ac_wrapper.h | 3 + src/map/if/acd/acd66.hpp | 1093 +++++++++++++++++++++++++++ src/map/if/acd/kitty_operations.hpp | 18 + src/map/if/acd/kitty_static_tt.hpp | 110 ++- src/map/if/if.h | 2 + src/map/if/ifDec66.c | 90 +++ src/map/if/module.make | 1 + 9 files changed, 1383 insertions(+), 3 deletions(-) create mode 100644 src/map/if/acd/acd66.hpp create mode 100644 src/map/if/ifDec66.c diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index e0ca6e948..3c5d3cbb8 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -19447,7 +19447,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) If_ManSetDefaultPars( pPars ); pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYZDEWSqaflepmrsdbgxyzuojiktncvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYZDEWSJqaflepmrsdbgxyzuojiktncvh" ) ) != EOF ) { switch ( c ) { @@ -19621,6 +19621,21 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } break; + case 'J': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-J\" should be followed by string.\n" ); + goto usage; + } + pPars->pLutStruct = argv[globalUtilOptind]; + pPars->fEnableStructN = 1; + globalUtilOptind++; + if ( strlen(pPars->pLutStruct) != 2 ) + { + Abc_Print( -1, "Command line switch \"-J\" should be followed by a 2-char string (e.g. \"66\").\n" ); + goto usage; + } + break; case 'q': pPars->fPreprocess ^= 1; break; @@ -19801,7 +19816,14 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "This feature only works for [6;16]-LUTs.\n" ); return 1; } - pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16; + if ( pPars->fEnableStructN ) + { + pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck66; + } + else + { + pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16; + } pPars->fCutMin = 1; } @@ -20003,6 +20025,7 @@ usage: Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); Abc_Print( -2, "\t-W float : sets wire delay between adjects LUTs [default = %f]\n", pPars->WireDelay ); Abc_Print( -2, "\t-S str : string representing the LUT structure [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" ); + Abc_Print( -2, "\t-J str : string representing the LUT structure (new method) [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" ); Abc_Print( -2, "\t-q : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" ); Abc_Print( -2, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" ); diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index fd8015f95..7268fcad4 100644 --- a/src/map/if/acd/ac_wrapper.cpp +++ b/src/map/if/acd/ac_wrapper.cpp @@ -18,6 +18,7 @@ #include "ac_wrapper.h" #include "ac_decomposition.hpp" +#include "acd66.hpp" ABC_NAMESPACE_IMPL_START @@ -69,4 +70,45 @@ int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, return 0; } +int acd66_evaluate( word * pTruth, unsigned nVars, int verify ) +{ + using namespace acd; + + acd66_params ps; + ps.verify = static_cast( verify ); + acd66_impl acd( nVars, ps ); + + if ( acd.run( pTruth ) == 0 ) + return 0; + + if ( !verify ) + return 1; + + int val = acd.compute_decomposition(); + if ( val != 0 ) + { + return 0; + } + + return 1; +} + +int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition ) +{ + using namespace acd; + + acd66_params ps; + acd66_impl acd( nVars, ps ); + acd.run( pTruth ); + + int val = acd.compute_decomposition(); + if ( val != 0 ) + { + return -1; + } + + acd.get_decomposition( decomposition ); + return 0; +} + ABC_NAMESPACE_IMPL_END diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h index a384b4404..2b832c287 100644 --- a/src/map/if/acd/ac_wrapper.h +++ b/src/map/if/acd/ac_wrapper.h @@ -28,6 +28,9 @@ ABC_NAMESPACE_HEADER_START int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); +int acd66_evaluate( word * pTruth, unsigned nVars, int verify ); +int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition ); + ABC_NAMESPACE_HEADER_END #endif \ No newline at end of file diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp new file mode 100644 index 000000000..a1369db83 --- /dev/null +++ b/src/map/if/acd/acd66.hpp @@ -0,0 +1,1093 @@ +/**C++File************************************************************** + + FileName [acd66.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Ashenhurst-Curtis decomposition.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alessandro Tempia Calvino] + + Affiliation [EPFL] + + Date [Ver. 1.0. Started - Feb 8, 2024.] + +***********************************************************************/ +/*! + \file acd66.hpp + \brief Ashenhurst-Curtis decomposition for "66" cascade + + \author Alessandro Tempia Calvino +*/ + +#ifndef _ACD66_H_ +#define _ACD66_H_ +#pragma once + +#include +#include +#include +#include +#include + +#include "kitty_constants.hpp" +#include "kitty_constructors.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_operations.hpp" +#include "kitty_operators.hpp" +#include "kitty_static_tt.hpp" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace acd +{ + +/*! \brief Parameters for acd66 */ +struct acd66_params +{ + /*! \brief Maximum size of the free set (1 < num < 6). */ + uint32_t max_free_set_vars{ 5 }; + + /*! \brief Number of configurations to test for decomposition. */ + uint32_t max_evaluations{ 3 }; + + /*! \brief Run verification before returning. */ + bool verify{ true }; +}; + +/*! \brief Statistics for acd66 */ +struct acd66_stats +{ + uint32_t num_edges{ 0 }; +}; + +class acd66_impl +{ +private: + static constexpr uint32_t max_num_vars = 11; + using STT = kitty::static_truth_table; + using LTT = kitty::static_truth_table<6>; + +public: + explicit acd66_impl( uint32_t num_vars, acd66_params const& ps, acd66_stats* pst = nullptr ) + : num_vars( num_vars ), ps( ps ), pst( pst ) + { + std::iota( permutations.begin(), permutations.end(), 0 ); + } + + /*! \brief Runs ACD 66 */ + int run( word* ptt ) + { + assert( num_vars > 6 ); + + /* truth table is too large for the settings */ + if ( num_vars > max_num_vars || num_vars > 11 ) + { + return -1; + } + + /* convert to static TT */ + init_truth_table( ptt ); + + /* run ACD trying different bound sets and free sets */ + return find_decomposition() ? 1 : 0; + } + + int compute_decomposition() + { + if ( best_multiplicity == UINT32_MAX ) + return -1; + + compute_decomposition_impl(); + + if ( ps.verify && !verify_impl() ) + { + return 1; + } + + if ( pst ) + { + pst->num_edges = bs_support_size + best_free_set + 1 + ( best_multiplicity > 2 ? 1 : 0 ); + } + + return 0; + } + + /* contains a 1 for BS variables */ + unsigned get_profile() + { + unsigned profile = 0; + + if ( bs_support_size == UINT32_MAX ) + return -1; + + for ( uint32_t i = 0; i < bs_support_size; ++i ) + { + profile |= 1 << permutations[best_free_set + bs_support[i]]; + } + + return profile; + } + + void get_decomposition( unsigned char* decompArray ) + { + if ( bs_support_size == UINT32_MAX ) + return; + + get_decomposition_abc( decompArray ); + } + +private: + bool find_decomposition() + { + best_multiplicity = UINT32_MAX; + best_free_set = UINT32_MAX; + + /* array of functions to compute the column multiplicity */ + std::function column_multiplicity_fn[5] = { + [this]( STT const& tt ) { return column_multiplicity<1u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity<2u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity<3u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity5<4u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } }; + + /* find AC decompositions with minimal multiplicity */ + for ( uint32_t i = num_vars - 6; i <= 5 && i <= ps.max_free_set_vars; ++i ) + { + auto [tt_p, perm, multiplicity] = enumerate_iset_combinations( i, column_multiplicity_fn[i - 1] ); + + /* check for feasible solution into "66" with one possible shared variable */ + if ( multiplicity <= 2 || ( multiplicity <= 4 && i < 5 ) ) + { + best_tt = tt_p; + permutations = perm; + best_multiplicity = multiplicity; + best_free_set = i; + + if ( multiplicity <= 2 || check_shared_set() ) + return true; + } + } + + best_multiplicity = UINT32_MAX; + return false; + } + + void init_truth_table( word* ptt ) + { + uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) ); + + for ( uint32_t i = 0; i < num_blocks; ++i ) + { + start_tt._bits[i] = ptt[i]; + } + + local_extend_to( start_tt, num_vars ); + } + + template + uint32_t column_multiplicity( STT tt ) + { + uint64_t multiplicity_set[4] = { 0u, 0u, 0u, 0u }; + uint32_t multiplicity = 0; + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t constexpr masks_bits[] = { 0x0, 0x3, 0xF, 0x3F }; + uint64_t constexpr masks_idx[] = { 0x0, 0x0, 0x0, 0x3 }; + + /* supports up to 64 values of free set (256 for |FS| == 3)*/ + static_assert( free_set_size <= 3 ); + + /* extract iset functions */ + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + multiplicity_set[( *it >> 6 ) & masks_idx[free_set_size]] |= UINT64_C( 1 ) << ( *it & masks_bits[free_set_size] ); + *it >>= ( 1u << free_set_size ); + } + ++it; + } + + multiplicity = __builtin_popcountl( multiplicity_set[0] ); + + if constexpr ( free_set_size == 3 ) + { + multiplicity += __builtin_popcountl( multiplicity_set[1] ); + multiplicity += __builtin_popcountl( multiplicity_set[2] ); + multiplicity += __builtin_popcountl( multiplicity_set[3] ); + } + + return multiplicity; + } + + template + uint32_t column_multiplicity5( STT tt ) + { + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; + + static_assert( free_set_size == 5 || free_set_size == 4 ); + + uint32_t size = 0; + uint64_t prev = -1; + std::array multiplicity_set; + + /* extract iset functions */ + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + uint32_t fs_fn = static_cast( *it & masks[free_set_size] ); + if ( fs_fn != prev ) + { + multiplicity_set[size++] = fs_fn; + prev = fs_fn; + } + *it >>= ( 1u << free_set_size ); + } + ++it; + } + + std::sort( multiplicity_set.begin(), multiplicity_set.begin() + size ); + + /* count unique */ + uint32_t multiplicity = 1; + for ( auto i = 1u; i < size; ++i ) + { + multiplicity += multiplicity_set[i] != multiplicity_set[i - 1] ? 1 : 0; + } + + return multiplicity; + } + + inline bool combinations_next( uint32_t k, uint32_t* pComb, uint32_t* pInvPerm, STT& tt ) + { + uint32_t i; + + for ( i = k - 1; pComb[i] == num_vars - k + i; --i ) + { + if ( i == 0 ) + return false; + } + + /* move vars */ + uint32_t var_old = pComb[i]; + uint32_t pos_new = pInvPerm[var_old + 1]; + std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] ); + std::swap( pComb[i], pComb[pos_new] ); + swap_inplace_local( tt, i, pos_new ); + + for ( uint32_t j = i + 1; j < k; j++ ) + { + var_old = pComb[j]; + pos_new = pInvPerm[pComb[j - 1] + 1]; + std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] ); + std::swap( pComb[j], pComb[pos_new] ); + swap_inplace_local( tt, j, pos_new ); + } + + return true; + } + + template + std::tuple, uint32_t> enumerate_iset_combinations( uint32_t free_set_size, Fn&& fn ) + { + STT tt = start_tt; + + /* TT with best cost */ + STT best_tt = tt; + uint32_t best_cost = UINT32_MAX; + + /* works up to 16 input truth tables */ + assert( num_vars <= 16 ); + + /* init combinations */ + uint32_t pComb[16], pInvPerm[16], bestPerm[16]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + do + { + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + best_tt = tt; + best_cost = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + bestPerm[i] = pComb[i]; + } + } + } while ( combinations_next( free_set_size, pComb, pInvPerm, tt ) ); + + std::array res_perm; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + res_perm[i] = bestPerm[i]; + } + + return std::make_tuple( best_tt, res_perm, best_cost ); + } + + bool check_shared_var( STT tt, uint32_t free_set_size, uint32_t shared_var, uint32_t multiplicity_limit ) + { + uint64_t multiplicity_set[2][4] = { { 0u, 0u, 0u, 0u }, { 0u, 0u, 0u, 0u } }; + uint32_t multiplicity0 = 0, multiplicity1 = 0; + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t constexpr masks_bits[] = { 0x0, 0x3, 0xF, 0x3F }; + uint64_t constexpr masks_idx[] = { 0x0, 0x0, 0x0, 0x3 }; + + /* supports up to 64 values of free set (256 for |FS| == 3)*/ + assert( free_set_size <= 3 ); + + uint32_t shared_var_shift = shared_var - free_set_size; + + /* extract iset functions */ + uint64_t iteration_counter = 0; + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + multiplicity_set[( iteration_counter >> shared_var_shift ) & 1][( *it >> 6 ) & masks_idx[free_set_size]] |= UINT64_C( 1 ) << ( *it & masks_bits[free_set_size] ); + *it >>= ( 1u << free_set_size ); + ++iteration_counter; + } + ++it; + } + + multiplicity0 = __builtin_popcountl( multiplicity_set[0][0] ); + multiplicity1 = __builtin_popcountl( multiplicity_set[1][0] ); + + if ( free_set_size == 3 ) + { + multiplicity0 += __builtin_popcountl( multiplicity_set[0][1] ); + multiplicity0 += __builtin_popcountl( multiplicity_set[0][2] ); + multiplicity0 += __builtin_popcountl( multiplicity_set[0][3] ); + + multiplicity1 += __builtin_popcountl( multiplicity_set[1][1] ); + multiplicity1 += __builtin_popcountl( multiplicity_set[1][2] ); + multiplicity1 += __builtin_popcountl( multiplicity_set[1][3] ); + } + + if ( multiplicity0 > multiplicity_limit || multiplicity1 > multiplicity_limit ) + return false; + + best_multiplicity0 = multiplicity0; + best_multiplicity1 = multiplicity1; + + return true; + } + + bool check_shared_var5( STT tt, uint32_t free_set_size, uint32_t shared_var, uint32_t multiplicity_limit ) + { + uint32_t const num_blocks = 1u << ( num_vars - 6 ); + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; + + assert( free_set_size == 5 || free_set_size == 4 ); + + uint32_t size[2] = { 0, 0 }; + uint64_t prev[2] = { UINT64_MAX, UINT64_MAX }; + std::array multiplicity_set[2]; + + uint32_t shared_var_shift = shared_var - free_set_size; + + /* extract iset functions */ + uint64_t iteration_counter = 0; + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + uint32_t fs_fn = static_cast( *it & masks[free_set_size] ); + uint32_t cofactor = ( iteration_counter >> shared_var_shift ) & 1; + if ( fs_fn != prev[cofactor] ) + { + multiplicity_set[cofactor][size[cofactor]++] = fs_fn; + prev[cofactor] = fs_fn; + } + *it >>= ( 1u << free_set_size ); + ++iteration_counter; + } + ++it; + } + + std::sort( multiplicity_set[0].begin(), multiplicity_set[0].begin() + size[0] ); + + /* count unique in 0 cofactor */ + uint32_t multiplicity = 1; + for ( auto i = 1u; i < size[0]; ++i ) + { + multiplicity += multiplicity_set[0][i] != multiplicity_set[0][i - 1] ? 1 : 0; + } + + if ( multiplicity > multiplicity_limit ) + return false; + + best_multiplicity0 = multiplicity; + + std::sort( multiplicity_set[1].begin(), multiplicity_set[1].begin() + size[1] ); + + /* count unique in 1 cofactor */ + multiplicity = 1; + for ( auto i = 1u; i < size[1]; ++i ) + { + multiplicity += multiplicity_set[1][i] != multiplicity_set[1][i - 1] ? 1 : 0; + } + + best_multiplicity1 = multiplicity; + + return multiplicity <= multiplicity_limit; + } + + bool check_shared_set() + { + /* find one shared set variable */ + for ( uint32_t i = best_free_set; i < num_vars; ++i ) + { + /* check the multiplicity of cofactors */ + if ( best_free_set < 4 ) + { + if ( check_shared_var( best_tt, best_free_set, i, 2 ) ) + { + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, i, num_vars - 1 ); + std::swap( permutations[i], permutations[num_vars - 1] ); + return true; + } + } + else + { + if ( check_shared_var5( best_tt, best_free_set, i, 2 ) ) + { + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, i, num_vars - 1 ); + std::swap( permutations[i], permutations[num_vars - 1] ); + return true; + } + } + } + + return false; + } + + void compute_decomposition_impl( bool verbose = false ) + { + bool has_shared_set = best_multiplicity > 2; + + /* construct isets involved in multiplicity */ + LTT isets0[2]; + LTT isets1[2]; + + /* construct isets */ + STT tt = best_tt; + uint32_t offset = 0; + uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; + + /* limit analysis on 0 cofactor of the shared variable */ + if ( has_shared_set ) + num_blocks >>= 1; + + auto it = std::begin( tt ); + uint64_t fs_fun[4] = { *it & masks[best_free_set], 0, 0, 0 }; + + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) + { + uint64_t val = *it & masks[best_free_set]; + + if ( val == fs_fun[0] ) + { + isets0[0]._bits |= UINT64_C( 1 ) << ( j + offset ); + } + else + { + isets0[1]._bits |= UINT64_C( 1 ) << ( j + offset ); + fs_fun[1] = val; + } + + *it >>= ( 1u << best_free_set ); + } + + offset = ( offset + ( 64 >> best_free_set ) ) % 64; + ++it; + } + + /* continue on the 1 cofactor if shared set */ + if ( has_shared_set ) + { + fs_fun[2] = *it & masks[best_free_set]; + for ( auto i = num_blocks; i < ( num_blocks << 1 ); ++i ) + { + for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) + { + uint64_t val = *it & masks[best_free_set]; + + if ( val == fs_fun[2] ) + { + isets1[0]._bits |= UINT64_C( 1 ) << ( j + offset ); + } + else + { + isets1[1]._bits |= UINT64_C( 1 ) << ( j + offset ); + fs_fun[3] = val; + } + + *it >>= ( 1u << best_free_set ); + } + + offset = ( offset + ( 64 >> best_free_set ) ) % 64; + ++it; + } + } + + /* find the support minimizing combination with shared set */ + compute_functions( isets0, isets1, fs_fun ); + + /* print functions */ + if ( verbose ) + { + LTT f; + f._bits = dec_funcs[0]; + std::cout << "BS function : "; + kitty::print_hex( f ); + std::cout << "\n"; + f._bits = dec_funcs[1]; + std::cout << "Composition function: "; + kitty::print_hex( f ); + std::cout << "\n"; + } + } + + inline void compute_functions( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4] ) + { + /* u = 2 no support minimization */ + if ( best_multiplicity < 3 ) + { + dec_funcs[0] = isets0[0]._bits; + bs_support_size = num_vars - best_free_set; + for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) + { + bs_support[i] = i; + } + compute_composition( fs_fun ); + return; + } + + /* u = 4 two possibilities */ + if ( best_multiplicity == 4 ) + { + compute_functions4( isets0, isets1, fs_fun ); + return; + } + + /* u = 3 if both sets have multiplicity 2 there are no don't cares */ + if ( best_multiplicity0 == best_multiplicity1 ) + { + compute_functions4( isets0, isets1, fs_fun ); + return; + } + + /* u = 3 one set has multiplicity 1, use don't cares */ + compute_functions3( isets0, isets1, fs_fun ); + compute_composition( fs_fun ); + } + + inline void compute_functions4( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4] ) + { + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX }; + LTT f = isets0[0] | isets1[1]; + LTT care; + care._bits = masks[num_vars - best_free_set]; + + /* count the number of support variables */ + uint32_t support_vars1 = 0; + for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) + { + support_vars1 += has_var6( f, care, i ) ? 1 : 0; + bs_support[i] = i; + } + + /* use a different set */ + f = isets0[0] | isets1[0]; + + uint32_t support_vars2 = 0; + for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) + { + support_vars2 += has_var6( f, care, i ) ? 1 : 0; + } + + bs_support_size = support_vars2; + if ( support_vars2 > support_vars1 ) + { + f = isets0[0] | isets1[1]; + std::swap( fs_fun[3], fs_fun[4] ); + bs_support_size = support_vars1; + } + + /* move variables */ + if ( bs_support_size < num_vars - best_free_set ) + { + support_vars1 = 0; + for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) + { + if ( !has_var6( f, care, i ) ) + { + adjust_truth_table_on_dc( f, care, i ); + continue; + } + + if ( support_vars1 < i ) + { + kitty::swap_inplace( f, support_vars1, i ); + } + + bs_support[support_vars1] = i; + ++support_vars1; + } + } + + dec_funcs[0] = f._bits; + compute_composition( fs_fun ); + } + + inline void compute_functions3( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4] ) + { + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX }; + LTT f = isets0[0] | isets1[0]; + LTT care; + + /* init the care set */ + if ( best_multiplicity0 == 1 ) + { + care._bits = masks[num_vars - best_free_set] & ( ~isets0[0]._bits ); + fs_fun[1] = fs_fun[0]; + } + else + { + care._bits = masks[num_vars - best_free_set] & ( ~isets1[0]._bits ); + fs_fun[3] = fs_fun[2]; + } + + /* count the number of support variables */ + uint32_t support_vars = 0; + for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) + { + if ( !has_var6( f, care, i ) ) + { + adjust_truth_table_on_dc( f, care, i ); + continue; + } + + if ( support_vars < i ) + { + kitty::swap_inplace( f, support_vars, i ); + } + + bs_support[support_vars] = i; + ++support_vars; + } + + bs_support_size = support_vars; + dec_funcs[0] = f._bits; + compute_composition( fs_fun ); + } + + void compute_composition( uint64_t fs_fun[4] ) + { + dec_funcs[1] = fs_fun[0] << ( 1 << best_free_set ); + dec_funcs[1] |= fs_fun[1]; + + if ( best_multiplicity > 2 ) + { + dec_funcs[1] |= fs_fun[2] << ( ( 2 << best_free_set ) + ( 1 << best_free_set ) ); + dec_funcs[1] |= fs_fun[3] << ( 2 << best_free_set ); + } + } + + template + void local_extend_to( TT_type& tt, uint32_t real_num_vars ) + { + if ( real_num_vars < 6 ) + { + auto mask = *tt.begin(); + + for ( auto i = real_num_vars; i < num_vars; ++i ) + { + mask |= ( mask << ( 1 << i ) ); + } + + std::fill( tt.begin(), tt.end(), mask ); + } + else + { + uint32_t num_blocks = ( 1u << ( real_num_vars - 6 ) ); + auto it = tt.begin(); + while ( it != tt.end() ) + { + it = std::copy( tt.cbegin(), tt.cbegin() + num_blocks, it ); + } + } + } + + void swap_inplace_local( STT& tt, uint8_t var_index1, uint8_t var_index2 ) + { + if ( var_index1 == var_index2 ) + { + return; + } + + if ( var_index1 > var_index2 ) + { + std::swap( var_index1, var_index2 ); + } + + assert( num_vars > 6 ); + const uint32_t num_blocks = 1 << ( num_vars - 6 ); + + if ( var_index2 <= 5 ) + { + const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + std::transform( std::begin( tt._bits ), std::begin( tt._bits ) + num_blocks, std::begin( tt._bits ), + [shift, &pmask]( uint64_t word ) { + return ( word & pmask[0] ) | ( ( word & pmask[1] ) << shift ) | ( ( word & pmask[2] ) >> shift ); + } ); + } + else if ( var_index1 <= 5 ) /* in this case, var_index2 > 5 */ + { + const auto step = 1 << ( var_index2 - 6 ); + const auto shift = 1 << var_index1; + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = decltype( step ){ 0 }; i < step; ++i ) + { + const auto low_to_high = ( *( it + i ) & kitty::detail::projections[var_index1] ) >> shift; + const auto high_to_low = ( *( it + i + step ) << shift ) & kitty::detail::projections[var_index1]; + *( it + i ) = ( *( it + i ) & ~kitty::detail::projections[var_index1] ) | high_to_low; + *( it + i + step ) = ( *( it + i + step ) & kitty::detail::projections[var_index1] ) | low_to_high; + } + it += 2 * step; + } + } + else + { + const auto step1 = 1 << ( var_index1 - 6 ); + const auto step2 = 1 << ( var_index2 - 6 ); + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = 0; i < step2; i += 2 * step1 ) + { + for ( auto j = 0; j < step1; ++j ) + { + std::swap( *( it + i + j + step1 ), *( it + i + j + step2 ) ); + } + } + it += 2 * step2; + } + } + } + + inline bool has_var6( const LTT& tt, const LTT& care, uint8_t var_index ) + { + if ( ( ( ( tt._bits >> ( uint64_t( 1 ) << var_index ) ) ^ tt._bits ) & kitty::detail::projections_neg[var_index] & ( care._bits >> ( uint64_t( 1 ) << var_index ) ) & care._bits ) != 0 ) + { + return true; + } + + return false; + } + + bool has_var_support( const STT& tt, const STT& care, uint32_t real_num_vars, uint8_t var_index ) + { + assert( var_index < real_num_vars ); + assert( real_num_vars <= tt.num_vars() ); + assert( tt.num_vars() == care.num_vars() ); + + const uint32_t num_blocks = real_num_vars <= 6 ? 1 : ( 1 << ( real_num_vars - 6 ) ); + if ( real_num_vars <= 6 || var_index < 6 ) + { + auto it_tt = std::begin( tt._bits ); + auto it_care = std::begin( care._bits ); + while ( it_tt != std::begin( tt._bits ) + num_blocks ) + { + if ( ( ( ( *it_tt >> ( uint64_t( 1 ) << var_index ) ) ^ *it_tt ) & kitty::detail::projections_neg[var_index] & ( *it_care >> ( uint64_t( 1 ) << var_index ) ) & *it_care ) != 0 ) + { + return true; + } + ++it_tt; + ++it_care; + } + + return false; + } + + const auto step = 1 << ( var_index - 6 ); + for ( auto i = 0u; i < num_blocks; i += 2 * step ) + { + for ( auto j = 0; j < step; ++j ) + { + if ( ( ( tt._bits[i + j] ^ tt._bits[i + j + step] ) & care._bits[i + j] & care._bits[i + j + step] ) != 0 ) + { + return true; + } + } + } + + return false; + } + + template + bool has_var_support( const TT_type& tt, const TT_type& care, uint32_t real_num_vars, uint8_t var_index ) + { + assert( var_index < real_num_vars ); + assert( real_num_vars <= tt.num_vars() ); + assert( tt.num_vars() == care.num_vars() ); + + const uint32_t num_blocks = real_num_vars <= 6 ? 1 : ( 1 << ( real_num_vars - 6 ) ); + if ( real_num_vars <= 6 || var_index < 6 ) + { + auto it_tt = std::begin( tt._bits ); + auto it_care = std::begin( care._bits ); + while ( it_tt != std::begin( tt._bits ) + num_blocks ) + { + if ( ( ( ( *it_tt >> ( uint64_t( 1 ) << var_index ) ) ^ *it_tt ) & kitty::detail::projections_neg[var_index] & ( *it_care >> ( uint64_t( 1 ) << var_index ) ) & *it_care ) != 0 ) + { + return true; + } + ++it_tt; + ++it_care; + } + + return false; + } + + const auto step = 1 << ( var_index - 6 ); + for ( auto i = 0u; i < num_blocks; i += 2 * step ) + { + for ( auto j = 0; j < step; ++j ) + { + if ( ( ( tt._bits[i + j] ^ tt._bits[i + j + step] ) & care._bits[i + j] & care._bits[i + j + step] ) != 0 ) + { + return true; + } + } + } + + return false; + } + + void adjust_truth_table_on_dc( LTT& tt, LTT& care, uint32_t var_index ) + { + uint64_t new_bits = tt._bits & care._bits; + tt._bits = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) | + ( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] ); + care._bits = care._bits | ( care._bits >> ( uint64_t( 1 ) << var_index ) ); + } + + /* Decomposition format for ABC + * + * The record is an array of unsigned chars where: + * - the first unsigned char entry stores the number of unsigned chars in the record + * - the second entry stores the number of LUTs + * After this, several sub-records follow, each representing one LUT as follows: + * - an unsigned char entry listing the number of fanins + * - a list of fanins, from the LSB to the MSB of the truth table. The N inputs of the original function + * have indexes from 0 to N-1, followed by the internal signals in a topological order + * - the LUT truth table occupying 2^(M-3) bytes, where M is the fanin count of the LUT, from the LSB to the MSB. + * A 2-input LUT, which takes 4 bits, should be stretched to occupy 8 bits (one unsigned char) + * A 0- or 1-input LUT can be represented similarly but it is not expected that such LUTs will be represented + */ + void get_decomposition_abc( unsigned char* decompArray ) + { + unsigned char* pArray = decompArray; + unsigned char bytes = 2; + + /* write number of LUTs */ + pArray++; + *pArray = 2; + pArray++; + + /* write BS LUT */ + /* write fanin size */ + *pArray = bs_support_size; + pArray++; + ++bytes; + + /* write support */ + for ( uint32_t i = 0; i < bs_support_size; ++i ) + { + *pArray = (unsigned char)permutations[bs_support[i] + best_free_set]; + pArray++; + ++bytes; + } + + /* write truth table */ + uint32_t tt_num_bytes = ( bs_support_size <= 3 ) ? 1 : ( 1 << ( bs_support_size - 3 ) ); + for ( uint32_t i = 0; i < tt_num_bytes; ++i ) + { + *pArray = (unsigned char)( ( dec_funcs[0] >> ( 8 * i ) ) & 0xFF ); + pArray++; + ++bytes; + } + + /* write top LUT */ + /* write fanin size */ + uint32_t support_size = best_free_set + 1 + ( best_multiplicity > 2 ? 1 : 0 ); + *pArray = support_size; + pArray++; + ++bytes; + + /* write support */ + for ( uint32_t i = best_free_set; i < best_free_set; ++i ) + { + *pArray = (unsigned char)permutations[i]; + pArray++; + ++bytes; + } + + *pArray = (unsigned char)num_vars; + pArray++; + ++bytes; + + if ( best_multiplicity > 2 ) + { + *pArray = (unsigned char)permutations[num_vars - 1]; + pArray++; + ++bytes; + } + + /* write truth table */ + tt_num_bytes = ( support_size <= 3 ) ? 1 : ( 1 << ( support_size - 3 ) ); + for ( uint32_t i = 0; i < tt_num_bytes; ++i ) + { + *pArray = (unsigned char)( ( dec_funcs[1] >> ( 8 * i ) ) & 0xFF ); + pArray++; + ++bytes; + } + + /* write numBytes */ + *decompArray = bytes; + } + + bool verify_impl() + { + /* create PIs */ + STT pis[max_num_vars]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + kitty::create_nth_var( pis[i], permutations[i] ); + } + + /* BS function patterns */ + STT bsi[6]; + for ( uint32_t i = 0; i < bs_support_size; ++i ) + { + bsi[i] = pis[best_free_set + bs_support[i]]; + } + + /* compute first function */ + STT bsf_sim; + for ( uint32_t i = 0u; i < ( 1 << num_vars ); ++i ) + { + uint32_t pattern = 0u; + for ( auto j = 0; j < bs_support_size; ++j ) + { + pattern |= get_bit( bsi[j], i ) << j; + } + if ( ( dec_funcs[0] >> pattern ) & 1 ) + { + set_bit( bsf_sim, i ); + } + } + + /* compute first function */ + STT top_sim; + for ( uint32_t i = 0u; i < ( 1 << num_vars ); ++i ) + { + uint32_t pattern = 0u; + for ( auto j = 0; j < best_free_set; ++j ) + { + pattern |= get_bit( pis[j], i ) << j; + } + pattern |= get_bit( bsf_sim, i ) << best_free_set; + if ( best_multiplicity > 2 ) + { + pattern |= get_bit( pis[num_vars - 1], i ) << ( best_free_set + 1 ); + } + + if ( ( dec_funcs[1] >> pattern ) & 1 ) + { + set_bit( top_sim, i ); + } + } + + for ( uint32_t i = 0; i < ( 1 << ( num_vars - 6 ) ); ++i ) + { + if ( top_sim._bits[i] != start_tt._bits[i] ) + { + /* convert to dynamic_truth_table */ + // report_tt( bsf_sim ); + std::cout << "Found incorrect decomposition\n"; + report_tt( top_sim ); + std::cout << " instead_of\n"; + report_tt( start_tt ); + return false; + } + } + + return true; + } + + uint32_t get_bit( const STT& tt, uint64_t index ) + { + return ( tt._bits[index >> 6] >> ( index & 0x3f ) ) & 0x1; + } + + void set_bit( STT& tt, uint64_t index ) + { + tt._bits[index >> 6] |= uint64_t( 1 ) << ( index & 0x3f ); + } + + void report_tt( STT const& stt ) + { + kitty::dynamic_truth_table tt( num_vars ); + + std::copy( std::begin( stt._bits ), std::begin( stt._bits ) + ( 1 << ( num_vars - 6 ) ), std::begin( tt ) ); + kitty::print_hex( tt ); + std::cout << "\n"; + } + +private: + uint32_t best_multiplicity{ UINT32_MAX }; + uint32_t best_free_set{ UINT32_MAX }; + uint32_t best_multiplicity0{ UINT32_MAX }; + uint32_t best_multiplicity1{ UINT32_MAX }; + uint32_t bs_support_size{ UINT32_MAX }; + STT best_tt; + STT start_tt; + uint64_t dec_funcs[2]; + uint32_t bs_support[6]; + + uint32_t num_vars; + acd66_params const& ps; + acd66_stats* pst; + std::array permutations; +}; + +} // namespace acd + +ABC_NAMESPACE_CXX_HEADER_END + +#endif // _ACD66_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_operations.hpp b/src/map/if/acd/kitty_operations.hpp index bf8e38007..48a4b7c67 100644 --- a/src/map/if/acd/kitty_operations.hpp +++ b/src/map/if/acd/kitty_operations.hpp @@ -133,6 +133,24 @@ void swap_inplace( TT& tt, uint8_t var_index1, uint8_t var_index2 ) } } +template +inline void swap_inplace( static_truth_table& tt, uint8_t var_index1, uint8_t var_index2 ) +{ + if ( var_index1 == var_index2 ) + { + return; + } + + if ( var_index1 > var_index2 ) + { + std::swap( var_index1, var_index2 ); + } + + const auto& pmask = detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + tt._bits = ( tt._bits & pmask[0] ) | ( ( tt._bits & pmask[1] ) << shift ) | ( ( tt._bits & pmask[2] ) >> shift ); +} + /*! \brief Extends smaller truth table to larger one The most significant variables will not be in the functional support of the diff --git a/src/map/if/acd/kitty_static_tt.hpp b/src/map/if/acd/kitty_static_tt.hpp index ab5a5d1c9..2b1613a6a 100644 --- a/src/map/if/acd/kitty_static_tt.hpp +++ b/src/map/if/acd/kitty_static_tt.hpp @@ -12,8 +12,116 @@ ABC_NAMESPACE_CXX_HEADER_START namespace kitty { +template +struct static_truth_table; + +/*! Truth table (for up to 6 variables) in which number of variables is known at compile time. + */ template -struct static_truth_table +struct static_truth_table +{ + /*! \cond PRIVATE */ + enum + { + NumBits = uint64_t( 1 ) << NumVars + }; + /*! \endcond */ + + /*! Constructs a new static truth table instance with the same number of variables. */ + inline static_truth_table construct() const + { + return static_truth_table(); + } + + /*! Returns number of variables. + */ + inline auto num_vars() const noexcept { return NumVars; } + + /*! Returns number of blocks. + */ + inline auto num_blocks() const noexcept { return 1u; } + + /*! Returns number of bits. + */ + inline auto num_bits() const noexcept { return NumBits; } + + /*! \brief Begin iterator to bits. + */ + inline auto begin() noexcept { return &_bits; } + + /*! \brief End iterator to bits. + */ + inline auto end() noexcept { return ( &_bits ) + 1; } + + /*! \brief Begin iterator to bits. + */ + inline auto begin() const noexcept { return &_bits; } + + /*! \brief End iterator to bits. + */ + inline auto end() const noexcept { return ( &_bits ) + 1; } + + /*! \brief Reverse begin iterator to bits. + */ + inline auto rbegin() noexcept { return &_bits; } + + /*! \brief Reverse end iterator to bits. + */ + inline auto rend() noexcept { return ( &_bits ) + 1; } + + /*! \brief Constant begin iterator to bits. + */ + inline auto cbegin() const noexcept { return &_bits; } + + /*! \brief Constant end iterator to bits. + */ + inline auto cend() const noexcept { return ( &_bits ) + 1; } + + /*! \brief Constant reverse begin iterator to bits. + */ + inline auto crbegin() const noexcept { return &_bits; } + + /*! \brief Constant everse end iterator to bits. + */ + inline auto crend() const noexcept { return ( &_bits ) + 1; } + + /*! \brief Assign other truth table if number of variables match. + + This replaces the current truth table with another truth table, if `other` + has the same number of variables. Otherwise, the truth table is not + changed. + + \param other Other truth table + */ + template + static_truth_table& operator=( const TT& other ) + { + if ( other.num_vars() == num_vars() ) + { + std::copy( other.begin(), other.end(), begin() ); + } + + return *this; + } + + /*! Masks the number of valid truth table bits. + + If the truth table has less than 6 variables, it may not use all + the bits. This operation makes sure to zero out all non-valid + bits. + */ + inline void mask_bits() noexcept { _bits &= detail::masks[NumVars]; } + + /*! \cond PRIVATE */ +public: /* fields */ + uint64_t _bits = 0; + /*! \endcond */ +}; + +/*! Truth table (more than 6 variables) in which number of variables is known at compile time. + */ +template +struct static_truth_table { /*! \cond PRIVATE */ enum diff --git a/src/map/if/if.h b/src/map/if/if.h index f8c99fdf1..33621ac92 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -151,6 +151,7 @@ struct If_Par_t_ int fVerbose; // the verbosity flag int fVerboseTrace; // the verbosity flag char * pLutStruct; // LUT structure + int fEnableStructN;// LUT structure using a new method float WireDelay; // wire delay // internal parameters int fSkipCutFilter;// skip cut filter @@ -551,6 +552,7 @@ extern int If_CutPerformCheck07( If_Man_t * p, unsigned * pTruth, in extern int If_CutPerformCheck08( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck10( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck16( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); +extern int If_CutPerformCheck66( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck45( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck54( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck75( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); diff --git a/src/map/if/ifDec66.c b/src/map/if/ifDec66.c new file mode 100644 index 000000000..932f5feb2 --- /dev/null +++ b/src/map/if/ifDec66.c @@ -0,0 +1,90 @@ +/**CFile**************************************************************** + + FileName [ifDec16.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Fast checking procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifDec16.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" +#include "bool/kit/kit.h" +#include "misc/vec/vecMem.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs ACD into 66 cascade.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_CutPerformCheck66( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeaves, char * pStr ) +{ + unsigned pTruth[IF_MAX_FUNC_LUTSIZE > 5 ? 1 << (IF_MAX_FUNC_LUTSIZE - 5) : 1]; + int i, Length; + // stretch the truth table + assert( nVars >= 6 ); + memcpy( pTruth, pTruth0, sizeof(word) * Abc_TtWordNum(nVars) ); + Abc_TtStretch6( (word *)pTruth, nLeaves, p->pPars->nLutSize ); + + // if cutmin is disabled, minimize the function + if ( !p->pPars->fCutMin ) + nLeaves = Abc_TtMinBase( (word *)pTruth, NULL, nLeaves, nVars ); + + // quit if parameters are wrong + Length = strlen(pStr); + if ( Length != 2 ) + { + printf( "Wrong LUT struct (%s)\n", pStr ); + return 0; + } + for ( i = 0; i < Length; i++ ) + { + if ( pStr[i] != '6' ) + { + printf( "The LUT size (%d) should belong to {6}.\n", pStr[i] - '0' ); + return 0; + } + } + + if ( nLeaves > 11 ) + { + printf( "The cut size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr ); + return 0; + } + + // consider easy case + if ( nLeaves <= 6 ) + return 1; + + // derive the decomposition + return (int)(acd66_evaluate( (word *)pTruth, nVars, 1 ) > 0 ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/map/if/module.make b/src/map/if/module.make index 6651d465b..bd652f35b 100644 --- a/src/map/if/module.make +++ b/src/map/if/module.make @@ -7,6 +7,7 @@ SRC += src/map/if/ifCom.c \ src/map/if/ifDec08.c \ src/map/if/ifDec10.c \ src/map/if/ifDec16.c \ + src/map/if/ifDec66.c \ src/map/if/ifDec75.c \ src/map/if/ifDelay.c \ src/map/if/ifDsd.c \ From 2afaeac8234196ec427cda99cbbe5df82a6f51df Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 8 Feb 2024 11:20:19 +0100 Subject: [PATCH 085/151] Adding hash table to reduce computations --- src/map/if/acd/ac_wrapper.cpp | 6 +- src/map/if/acd/ac_wrapper.h | 2 +- src/map/if/acd/acd66.hpp | 2 +- src/map/if/ifDec66.c | 260 +++++++++++++++++++++++++++++++++- 4 files changed, 259 insertions(+), 11 deletions(-) diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index 7268fcad4..441cb7008 100644 --- a/src/map/if/acd/ac_wrapper.cpp +++ b/src/map/if/acd/ac_wrapper.cpp @@ -70,18 +70,18 @@ int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, return 0; } -int acd66_evaluate( word * pTruth, unsigned nVars, int verify ) +int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition ) { using namespace acd; acd66_params ps; - ps.verify = static_cast( verify ); + ps.verify = false; acd66_impl acd( nVars, ps ); if ( acd.run( pTruth ) == 0 ) return 0; - if ( !verify ) + if ( !compute_decomposition ) return 1; int val = acd.compute_decomposition(); diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h index 2b832c287..2e052c563 100644 --- a/src/map/if/acd/ac_wrapper.h +++ b/src/map/if/acd/ac_wrapper.h @@ -28,7 +28,7 @@ ABC_NAMESPACE_HEADER_START int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); -int acd66_evaluate( word * pTruth, unsigned nVars, int verify ); +int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition ); int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition ); ABC_NAMESPACE_HEADER_END diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index a1369db83..166402ca0 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -54,7 +54,7 @@ struct acd66_params uint32_t max_evaluations{ 3 }; /*! \brief Run verification before returning. */ - bool verify{ true }; + bool verify{ false }; }; /*! \brief Statistics for acd66 */ diff --git a/src/map/if/ifDec66.c b/src/map/if/ifDec66.c index 932f5feb2..3a836363d 100644 --- a/src/map/if/ifDec66.c +++ b/src/map/if/ifDec66.c @@ -1,6 +1,6 @@ /**CFile**************************************************************** - FileName [ifDec16.c] + FileName [ifDec66.c] SystemName [ABC: Logic synthesis and verification system.] @@ -8,13 +8,13 @@ Synopsis [Fast checking procedures.] - Author [Alan Mishchenko] + Author [Alessandro Tempia Calvino] - Affiliation [UC Berkeley] + Affiliation [EPFL] - Date [Ver. 1.0. Started - November 21, 2006.] + Date [Ver. 1.0. Started - Feb 8, 2024.] - Revision [$Id: ifDec16.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + Revision [$Id: ifDec66.c,v 1.00 2008/02/08 00:00:00 tempia Exp $] ***********************************************************************/ @@ -24,10 +24,258 @@ ABC_NAMESPACE_IMPL_START +#define CLU_VAR_MAX 16 +#define CLU_MEM_MAX 1000 // 1 GB +#define CLU_UNUSED 0xff + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// decomposition +typedef struct If_Grp_t_ If_Grp_t; +struct If_Grp_t_ +{ + char nVars; + char nMyu; + char pVars[CLU_VAR_MAX]; +}; + +// hash table entry +typedef struct If_Hte_t_ If_Hte_t; +struct If_Hte_t_ +{ + If_Hte_t * pNext; + unsigned Group; + unsigned Counter; + word pTruth[1]; +}; + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// +static inline unsigned If_CluGrp2Uns2( If_Grp_t * pG ) +{ + char * pChar = (char *)pG; + unsigned Res = 0; + int i; + for ( i = 0; i < 8; i++ ) + Res |= ((pChar[i] & 15) << (i << 2)); + return Res; +} + +static inline void If_CluUns2Grp2( unsigned Group, If_Grp_t * pG ) +{ + char * pChar = (char *)pG; + int i; + for ( i = 0; i < 8; i++ ) + pChar[i] = ((Group >> (i << 2)) & 15); +} + +unsigned int If_CluPrimeCudd2( unsigned int p ) +{ + int i,pn; + + p--; + do { + p++; + if (p&1) { + pn = 1; + i = 3; + while ((unsigned) (i * i) <= p) { + if (p % i == 0) { + pn = 0; + break; + } + i += 2; + } + } else { + pn = 0; + } + } while (!pn); + return(p); + +} /* end of Cudd_Prime */ + +// hash table +static inline int If_CluWordNum2( int nVars ) +{ + return nVars <= 6 ? 1 : 1 << (nVars-6); +} + +int If_CluHashFindMedian2( If_Man_t * p, int t ) +{ + If_Hte_t * pEntry; + Vec_Int_t * vCounters; + int i, Max = 0, Total = 0, Half = 0; + vCounters = Vec_IntStart( 1000 ); + for ( i = 0; i < p->nTableSize[t]; i++ ) + { + for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; pEntry = pEntry->pNext ) + { + if ( Max < (int)pEntry->Counter ) + { + Max = pEntry->Counter; + Vec_IntSetEntry( vCounters, pEntry->Counter, 0 ); + } + Vec_IntAddToEntry( vCounters, pEntry->Counter, 1 ); + Total++; + } + } + for ( i = Max; i > 0; i-- ) + { + Half += Vec_IntEntry( vCounters, i ); + if ( Half > Total/2 ) + break; + } +/* + printf( "total = %d ", Total ); + printf( "half = %d ", Half ); + printf( "i = %d ", i ); + printf( "Max = %d.\n", Max ); +*/ + Vec_IntFree( vCounters ); + return Abc_MaxInt( i, 1 ); +} + +int If_CluHashKey2( word * pTruth, int nWords, int Size ) +{ + static unsigned BigPrimes[8] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; + unsigned Value = 0; + int i; + if ( nWords < 4 ) + { + unsigned char * s = (unsigned char *)pTruth; + for ( i = 0; i < 8 * nWords; i++ ) + Value ^= BigPrimes[i % 7] * s[i]; + } + else + { + unsigned * s = (unsigned *)pTruth; + for ( i = 0; i < 2 * nWords; i++ ) + Value ^= BigPrimes[i % 7] * s[i]; + } + return Value % Size; +} + +unsigned * If_CluHashLookup2( If_Man_t * p, word * pTruth, int t ) +{ + If_Hte_t * pEntry, * pPrev; + int nWords, HashKey; + if ( p == NULL ) + return NULL; + nWords = If_CluWordNum2(p->pPars->nLutSize); + if ( p->pMemEntries == NULL ) + p->pMemEntries = Mem_FixedStart( sizeof(If_Hte_t) + sizeof(word) * (If_CluWordNum2(p->pPars->nLutSize) - 1) ); + if ( p->pHashTable[t] == NULL ) + { + // decide how large should be the table + int nEntriesMax1 = 4 * If_CluPrimeCudd2( Vec_PtrSize(p->vObjs) * p->pPars->nCutsMax ); + int nEntriesMax2 = (int)(((double)CLU_MEM_MAX * (1 << 20)) / If_CluWordNum2(p->pPars->nLutSize) / 8); +// int nEntriesMax2 = 10000; + // create table + p->nTableSize[t] = If_CluPrimeCudd2( Abc_MinInt(nEntriesMax1, nEntriesMax2)/2 ); + p->pHashTable[t] = ABC_CALLOC( void *, p->nTableSize[t] ); + } + // check if this entry exists + HashKey = If_CluHashKey2( pTruth, nWords, p->nTableSize[t] ); + for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[HashKey]; pEntry; pEntry = pEntry->pNext ) + if ( memcmp(pEntry->pTruth, pTruth, sizeof(word) * nWords) == 0 ) + { + pEntry->Counter++; + return &pEntry->Group; + } + // resize the hash table + if ( p->nTableEntries[t] >= 2 * p->nTableSize[t] ) + { + // collect useful entries + If_Hte_t * pPrev; + Vec_Ptr_t * vUseful = Vec_PtrAlloc( p->nTableEntries[t] ); + int i, Median = If_CluHashFindMedian2( p, t ); + for ( i = 0; i < p->nTableSize[t]; i++ ) + { + for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; ) + { + if ( (int)pEntry->Counter > Median ) + { + Vec_PtrPush( vUseful, pEntry ); + pEntry = pEntry->pNext; + } + else + { + pPrev = pEntry->pNext; + Mem_FixedEntryRecycle( p->pMemEntries, (char *)pEntry ); + pEntry = pPrev; + } + } + } + // add useful entries + memset( p->pHashTable[t], 0, sizeof(void *) * p->nTableSize[t] ); + Vec_PtrForEachEntry( If_Hte_t *, vUseful, pEntry, i ) + { + HashKey = If_CluHashKey2( pEntry->pTruth, nWords, p->nTableSize[t] ); + pPrev = ((If_Hte_t **)p->pHashTable[t])[HashKey]; + if ( pPrev == NULL || pEntry->Counter >= pPrev->Counter ) + { + pEntry->pNext = pPrev; + ((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry; + } + else + { + while ( pPrev->pNext && pEntry->Counter < pPrev->pNext->Counter ) + pPrev = pPrev->pNext; + pEntry->pNext = pPrev->pNext; + pPrev->pNext = pEntry; + } + } + p->nTableEntries[t] = Vec_PtrSize( vUseful ); + Vec_PtrFree( vUseful ); + } + // create entry + p->nTableEntries[t]++; + pEntry = (If_Hte_t *)Mem_FixedEntryFetch( p->pMemEntries ); + memcpy( pEntry->pTruth, pTruth, sizeof(word) * nWords ); + pEntry->Group = CLU_UNUSED; + pEntry->Counter = 1; + // insert at the beginning +// pEntry->pNext = ((If_Hte_t **)p->pHashTable[t])[HashKey]; +// ((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry; + // insert at the end + pEntry->pNext = NULL; + for ( pPrev = ((If_Hte_t **)p->pHashTable[t])[HashKey]; pPrev && pPrev->pNext; pPrev = pPrev->pNext ); + if ( pPrev == NULL ) + ((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry; + else + pPrev->pNext = pEntry; + return &pEntry->Group; +} + +// returns if successful +int If_CluCheck66( If_Man_t * p, word * pTruth0, int nVars, int fHashing ) +{ + If_Grp_t G1 = {0}; + unsigned * pHashed = NULL; + + if ( p && fHashing ) + { + pHashed = If_CluHashLookup2( p, pTruth0, 0 ); + if ( pHashed && *pHashed != CLU_UNUSED ) + If_CluUns2Grp2( *pHashed, &G1 ); + } + + /* new entry */ + if ( G1.nVars == 0 ) + { + G1.nVars = acd66_evaluate( pTruth0, nVars, 0 ); + } + + if ( pHashed ) + *pHashed = If_CluGrp2Uns2( &G1 ); + + return G1.nVars; +} + /**Function************************************************************* Synopsis [Performs ACD into 66 cascade.] @@ -79,7 +327,7 @@ int If_CutPerformCheck66( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeav return 1; // derive the decomposition - return (int)(acd66_evaluate( (word *)pTruth, nVars, 1 ) > 0 ); + return If_CluCheck66(p, (word*)pTruth, nVars, 1); } //////////////////////////////////////////////////////////////////////// From 3f80b202cd91b1966378333d6fccf07a7c94fd07 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 8 Feb 2024 14:57:42 +0100 Subject: [PATCH 086/151] C++11 compatible code --- src/map/if/acd/ac_decomposition.hpp | 35 ++++++++++--------- src/map/if/acd/acd66.hpp | 13 ++++---- src/map/if/acd/kitty_algorithm.hpp | 8 ++--- src/map/if/acd/kitty_dynamic_tt.hpp | 26 +++++++-------- src/map/if/acd/kitty_operations.hpp | 10 +++--- src/map/if/acd/kitty_operators.hpp | 23 ++++++++----- src/map/if/acd/kitty_static_tt.hpp | 52 ++++++++++++++--------------- 7 files changed, 88 insertions(+), 79 deletions(-) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index 8aee0266d..d55941995 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -205,7 +205,8 @@ private: /* find a feasible AC decomposition */ for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) { - auto [tt_p, perm, multiplicity] = enumerate_iset_combinations_offset( i, offset, column_multiplicity_fn[i - 1] ); + auto ret_tuple = enumerate_iset_combinations_offset( i, offset, column_multiplicity_fn[i - 1] ); + uint32_t multiplicity = std::get<2>( ret_tuple ); /* additional cost if not support reducing */ uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; @@ -213,8 +214,8 @@ private: /* check for feasible solution that improves the cost */ if ( multiplicity <= ( 1 << ( ps.lut_size - i ) ) && multiplicity + additional_cost < best_cost && multiplicity <= 16 ) { - best_tt = tt_p; - permutations = perm; + best_tt = std::get<0>( ret_tuple ); + permutations = std::get<1>( ret_tuple ); best_multiplicity = multiplicity; best_cost = multiplicity + additional_cost; best_free_set = i; @@ -240,7 +241,8 @@ private: for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) { - auto [tt_p, perm, multiplicity] = enumerate_iset_combinations_offset( i, 0, column_multiplicity_fn[i - 1] ); + auto ret_tuple = enumerate_iset_combinations_offset( i, 0, column_multiplicity_fn[i - 1] ); + uint32_t multiplicity = std::get<2>( ret_tuple ); /* additional cost if not support reducing */ uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; @@ -248,8 +250,8 @@ private: /* check for feasible solution that improves the cost */ if ( multiplicity <= ( 1 << ( ps.lut_size - i ) ) && multiplicity + additional_cost < best_cost && multiplicity <= 16 ) { - best_tt = tt_p; - permutations = perm; + best_tt = std::get<0>( ret_tuple ); + permutations = std::get<1>( ret_tuple ); best_multiplicity = multiplicity; best_cost = multiplicity + additional_cost; best_free_set = i; @@ -298,7 +300,7 @@ private: uint64_t constexpr masks_idx[] = { 0x0, 0x0, 0x0, 0x3 }; /* supports up to 64 values of free set (256 for |FS| == 3)*/ - static_assert( free_set_size <= 3 ); + static_assert( free_set_size <= 3, "Wrong free set size for method used, expected le 3" ); /* extract iset functions */ auto it = std::begin( tt ); @@ -314,7 +316,7 @@ private: multiplicity = __builtin_popcountl( multiplicity_set[0] ); - if constexpr ( free_set_size == 3 ) + if ( free_set_size == 3 ) { multiplicity += __builtin_popcountl( multiplicity_set[1] ); multiplicity += __builtin_popcountl( multiplicity_set[2] ); @@ -330,7 +332,7 @@ private: uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; - static_assert( free_set_size == 5 || free_set_size == 4 ); + static_assert( free_set_size == 5 || free_set_size == 4, "Wrong free set size for method used, expected of 4 or 5" ); uint32_t size = 0; uint64_t prev = -1; @@ -466,7 +468,8 @@ private: { uint64_t val = *it & masks[best_free_set]; - if ( auto el = column_to_iset.find( val ); el != column_to_iset.end() ) + auto el = column_to_iset.find( val ); + if ( el != column_to_iset.end() ) { isets[el->second]._bits[i / ( 1u << best_free_set )] |= UINT64_C( 1 ) << ( j + offset ); } @@ -709,7 +712,7 @@ private: { if ( var == best_multiplicity ) { - if constexpr ( !enable_dcset ) + if ( !enable_dcset ) { /* sets must be equally populated */ if ( __builtin_popcount( onset ) != __builtin_popcount( offset ) ) @@ -725,7 +728,7 @@ private: } /* var in DCSET */ - if constexpr ( enable_dcset ) + if ( enable_dcset ) { generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); } @@ -953,7 +956,7 @@ private: cost = 0; float sort_cost = 0; - if constexpr ( UseHeuristic ) + if ( UseHeuristic ) { sort_cost = 1.0f / ( __builtin_popcountl( column[0] ) + __builtin_popcountl( column[1] ) ); } @@ -971,15 +974,15 @@ private: return true; } - if constexpr ( UseHeuristic ) + if ( UseHeuristic ) { - std::sort( matrix.begin(), matrix.end(), [&]( auto const& a, auto const& b ) { + std::sort( matrix.begin(), matrix.end(), [&]( encoding_column const& a, encoding_column const& b ) { return a.cost < b.cost; } ); } else { - std::sort( matrix.begin(), matrix.end(), [&]( auto const& a, auto const& b ) { + std::sort( matrix.begin(), matrix.end(), [&]( encoding_column const& a, encoding_column const& b ) { return a.sort_cost < b.sort_cost; } ); } diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 166402ca0..67d460157 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -156,13 +156,14 @@ private: /* find AC decompositions with minimal multiplicity */ for ( uint32_t i = num_vars - 6; i <= 5 && i <= ps.max_free_set_vars; ++i ) { - auto [tt_p, perm, multiplicity] = enumerate_iset_combinations( i, column_multiplicity_fn[i - 1] ); + auto ret_tuple = enumerate_iset_combinations( i, column_multiplicity_fn[i - 1] ); + uint32_t multiplicity = std::get<2>( ret_tuple ); /* check for feasible solution into "66" with one possible shared variable */ if ( multiplicity <= 2 || ( multiplicity <= 4 && i < 5 ) ) { - best_tt = tt_p; - permutations = perm; + best_tt = std::get<0>( ret_tuple ); + permutations = std::get<1>( ret_tuple ); best_multiplicity = multiplicity; best_free_set = i; @@ -197,7 +198,7 @@ private: uint64_t constexpr masks_idx[] = { 0x0, 0x0, 0x0, 0x3 }; /* supports up to 64 values of free set (256 for |FS| == 3)*/ - static_assert( free_set_size <= 3 ); + static_assert( free_set_size <= 3, "Wrong free set size for method used, expected le 3" ); /* extract iset functions */ auto it = std::begin( tt ); @@ -213,7 +214,7 @@ private: multiplicity = __builtin_popcountl( multiplicity_set[0] ); - if constexpr ( free_set_size == 3 ) + if ( free_set_size == 3 ) { multiplicity += __builtin_popcountl( multiplicity_set[1] ); multiplicity += __builtin_popcountl( multiplicity_set[2] ); @@ -229,7 +230,7 @@ private: uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; - static_assert( free_set_size == 5 || free_set_size == 4 ); + static_assert( free_set_size == 5 || free_set_size == 4, "Wrong free set size for method used, expected of 4 or 5" ); uint32_t size = 0; uint64_t prev = -1; diff --git a/src/map/if/acd/kitty_algorithm.hpp b/src/map/if/acd/kitty_algorithm.hpp index 78eead08a..a8c71dc07 100644 --- a/src/map/if/acd/kitty_algorithm.hpp +++ b/src/map/if/acd/kitty_algorithm.hpp @@ -22,9 +22,9 @@ namespace kitty \return new constructed truth table of same type and dimensions */ template -auto unary_operation( const TT& tt, Fn&& op ) +TT unary_operation( const TT& tt, Fn&& op ) { - auto result = tt.construct(); + TT result = tt.construct(); std::transform( tt.cbegin(), tt.cend(), result.begin(), op ); result.mask_bits(); return result; @@ -43,11 +43,11 @@ auto unary_operation( const TT& tt, Fn&& op ) \return new constructed truth table of same type and dimensions */ template -auto binary_operation( const TT& first, const TT& second, Fn&& op ) +TT binary_operation( const TT& first, const TT& second, Fn&& op ) { assert( first.num_vars() == second.num_vars() ); - auto result = first.construct(); + TT result = first.construct(); std::transform( first.cbegin(), first.cend(), second.cbegin(), result.begin(), op ); result.mask_bits(); return result; diff --git a/src/map/if/acd/kitty_dynamic_tt.hpp b/src/map/if/acd/kitty_dynamic_tt.hpp index 880943dfa..2913b6674 100644 --- a/src/map/if/acd/kitty_dynamic_tt.hpp +++ b/src/map/if/acd/kitty_dynamic_tt.hpp @@ -51,55 +51,55 @@ struct dynamic_truth_table /*! Returns number of variables. */ - inline auto num_vars() const noexcept { return _num_vars; } + inline uint32_t num_vars() const noexcept { return _num_vars; } /*! Returns number of blocks. */ - inline auto num_blocks() const noexcept { return _bits.size(); } + inline uint32_t num_blocks() const noexcept { return _bits.size(); } /*! Returns number of bits. */ - inline auto num_bits() const noexcept { return uint64_t( 1 ) << _num_vars; } + inline uint32_t num_bits() const noexcept { return uint64_t( 1 ) << _num_vars; } /*! \brief Begin iterator to bits. */ - inline auto begin() noexcept { return _bits.begin(); } + inline std::vector::iterator begin() noexcept { return _bits.begin(); } /*! \brief End iterator to bits. */ - inline auto end() noexcept { return _bits.end(); } + inline std::vector::iterator end() noexcept { return _bits.end(); } /*! \brief Begin iterator to bits. */ - inline auto begin() const noexcept { return _bits.begin(); } + inline std::vector::const_iterator begin() const noexcept { return _bits.begin(); } /*! \brief End iterator to bits. */ - inline auto end() const noexcept { return _bits.end(); } + inline std::vector::const_iterator end() const noexcept { return _bits.end(); } /*! \brief Reverse begin iterator to bits. */ - inline auto rbegin() noexcept { return _bits.rbegin(); } + inline std::vector::reverse_iterator rbegin() noexcept { return _bits.rbegin(); } /*! \brief Reverse end iterator to bits. */ - inline auto rend() noexcept { return _bits.rend(); } + inline std::vector::reverse_iterator rend() noexcept { return _bits.rend(); } /*! \brief Constant begin iterator to bits. */ - inline auto cbegin() const noexcept { return _bits.cbegin(); } + inline std::vector::const_iterator cbegin() const noexcept { return _bits.cbegin(); } /*! \brief Constant end iterator to bits. */ - inline auto cend() const noexcept { return _bits.cend(); } + inline std::vector::const_iterator cend() const noexcept { return _bits.cend(); } /*! \brief Constant reverse begin iterator to bits. */ - inline auto crbegin() const noexcept { return _bits.crbegin(); } + inline std::vector::const_reverse_iterator crbegin() const noexcept { return _bits.crbegin(); } /*! \brief Constant teverse end iterator to bits. */ - inline auto crend() const noexcept { return _bits.crend(); } + inline std::vector::const_reverse_iterator crend() const noexcept { return _bits.crend(); } /*! \brief Assign other truth table. diff --git a/src/map/if/acd/kitty_operations.hpp b/src/map/if/acd/kitty_operations.hpp index 48a4b7c67..e0292bc05 100644 --- a/src/map/if/acd/kitty_operations.hpp +++ b/src/map/if/acd/kitty_operations.hpp @@ -31,7 +31,7 @@ inline TT unary_not_if( const TT& tt, bool cond ) #ifdef _MSC_VER #pragma warning( pop ) #endif - return unary_operation( tt, [mask]( auto a ) + return unary_operation( tt, [mask]( uint64_t a ) { return a ^ mask; } ); } @@ -39,7 +39,7 @@ inline TT unary_not_if( const TT& tt, bool cond ) template inline TT unary_not( const TT& tt ) { - return unary_operation( tt, []( auto a ) + return unary_operation( tt, []( uint64_t a ) { return ~a; } ); } @@ -48,14 +48,14 @@ template inline TT binary_and( const TT& first, const TT& second ) { - return binary_operation( first, second, std::bit_and<>() ); + return binary_operation( first, second, std::bit_and() ); } /*! \brief Bitwise OR of two truth tables */ template inline TT binary_or( const TT& first, const TT& second ) { - return binary_operation( first, second, std::bit_or<>() ); + return binary_operation( first, second, std::bit_or() ); } /*! \brief Swaps two variables in a truth table @@ -330,7 +330,7 @@ void print_hex( const TT& tt, std::ostream& os = std::cout ) auto const chunk_size = std::min( tt.num_vars() <= 1 ? 1 : ( tt.num_bits() >> 2 ), 16 ); - for_each_block_reversed( tt, [&os, chunk_size]( auto word ) + for_each_block_reversed( tt, [&os, chunk_size]( uint64_t word ) { std::string chunk( chunk_size, '0' ); diff --git a/src/map/if/acd/kitty_operators.hpp b/src/map/if/acd/kitty_operators.hpp index b5f4688c2..7ccab7ca1 100644 --- a/src/map/if/acd/kitty_operators.hpp +++ b/src/map/if/acd/kitty_operators.hpp @@ -78,28 +78,33 @@ inline void operator|=( dynamic_truth_table& first, const dynamic_truth_table& s /*! \brief Operator for binary_or and assign */ template -inline void operator|=( static_truth_table& first, const static_truth_table& second ) +inline void operator|=( static_truth_table& first, const static_truth_table& second ) { // first = binary_or( first, second ); /* runtime improved version */ - if constexpr ( NumVars <= 6 ) - { - first._bits |= second._bits; - first.mask_bits(); - } - else if constexpr ( NumVars == 7 ) + first._bits |= second._bits; + first.mask_bits(); +} + +/*! \brief Operator for binary_or and assign */ +template +inline void operator|=( static_truth_table& first, const static_truth_table& second ) +{ + // first = binary_or( first, second ); + /* runtime improved version */ + if ( NumVars == 7 ) { first._bits[0] |= second._bits[0]; first._bits[1] |= second._bits[1]; } - else if constexpr ( NumVars == 8 ) + else if ( NumVars == 8 ) { first._bits[0] |= second._bits[0]; first._bits[1] |= second._bits[1]; first._bits[2] |= second._bits[2]; first._bits[3] |= second._bits[3]; } - else if constexpr ( NumVars == 9 ) + else if ( NumVars == 9 ) { first._bits[0] |= second._bits[0]; first._bits[1] |= second._bits[1]; diff --git a/src/map/if/acd/kitty_static_tt.hpp b/src/map/if/acd/kitty_static_tt.hpp index 2b1613a6a..5bb4bdac1 100644 --- a/src/map/if/acd/kitty_static_tt.hpp +++ b/src/map/if/acd/kitty_static_tt.hpp @@ -35,55 +35,55 @@ struct static_truth_table /*! Returns number of variables. */ - inline auto num_vars() const noexcept { return NumVars; } + inline uint32_t num_vars() const noexcept { return NumVars; } /*! Returns number of blocks. */ - inline auto num_blocks() const noexcept { return 1u; } + inline uint32_t num_blocks() const noexcept { return 1u; } /*! Returns number of bits. */ - inline auto num_bits() const noexcept { return NumBits; } + inline uint32_t num_bits() const noexcept { return NumBits; } /*! \brief Begin iterator to bits. */ - inline auto begin() noexcept { return &_bits; } + inline uint64_t * begin() noexcept { return &_bits; } /*! \brief End iterator to bits. */ - inline auto end() noexcept { return ( &_bits ) + 1; } + inline uint64_t * end() noexcept { return ( &_bits ) + 1; } /*! \brief Begin iterator to bits. */ - inline auto begin() const noexcept { return &_bits; } + inline const uint64_t * begin() const noexcept { return &_bits; } /*! \brief End iterator to bits. */ - inline auto end() const noexcept { return ( &_bits ) + 1; } + inline const uint64_t * end() const noexcept { return ( &_bits ) + 1; } /*! \brief Reverse begin iterator to bits. */ - inline auto rbegin() noexcept { return &_bits; } + inline uint64_t * rbegin() noexcept { return &_bits; } /*! \brief Reverse end iterator to bits. */ - inline auto rend() noexcept { return ( &_bits ) + 1; } + inline uint64_t * rend() noexcept { return ( &_bits ) + 1; } /*! \brief Constant begin iterator to bits. */ - inline auto cbegin() const noexcept { return &_bits; } + inline const uint64_t * cbegin() const noexcept { return &_bits; } /*! \brief Constant end iterator to bits. */ - inline auto cend() const noexcept { return ( &_bits ) + 1; } + inline const uint64_t * cend() const noexcept { return ( &_bits ) + 1; } /*! \brief Constant reverse begin iterator to bits. */ - inline auto crbegin() const noexcept { return &_bits; } + inline const uint64_t * crbegin() const noexcept { return &_bits; } /*! \brief Constant everse end iterator to bits. */ - inline auto crend() const noexcept { return ( &_bits ) + 1; } + inline const uint64_t * crend() const noexcept { return ( &_bits ) + 1; } /*! \brief Assign other truth table if number of variables match. @@ -154,55 +154,55 @@ struct static_truth_table /*! Returns number of variables. */ - inline auto num_vars() const noexcept { return NumVars; } + inline uint32_t num_vars() const noexcept { return NumVars; } /*! Returns number of blocks. */ - inline auto num_blocks() const noexcept { return NumBlocks; } + inline uint32_t num_blocks() const noexcept { return NumBlocks; } /*! Returns number of bits. */ - inline auto num_bits() const noexcept { return NumBits; } + inline uint32_t num_bits() const noexcept { return NumBits; } /*! \brief Begin iterator to bits. */ - inline auto begin() noexcept { return _bits.begin(); } + inline typename std::array::iterator begin() noexcept { return _bits.begin(); } /*! \brief End iterator to bits. */ - inline auto end() noexcept { return _bits.end(); } + inline typename std::array::iterator end() noexcept { return _bits.end(); } /*! \brief Begin iterator to bits. */ - inline auto begin() const noexcept { return _bits.begin(); } + inline typename std::array::const_iterator begin() const noexcept { return _bits.begin(); } /*! \brief End iterator to bits. */ - inline auto end() const noexcept { return _bits.end(); } + inline typename std::array::const_iterator end() const noexcept { return _bits.end(); } /*! \brief Reverse begin iterator to bits. */ - inline auto rbegin() noexcept { return _bits.rbegin(); } + inline typename std::array::reverse_iterator rbegin() noexcept { return _bits.rbegin(); } /*! \brief Reverse end iterator to bits. */ - inline auto rend() noexcept { return _bits.rend(); } + inline typename std::array::reverse_iterator rend() noexcept { return _bits.rend(); } /*! \brief Constant begin iterator to bits. */ - inline auto cbegin() const noexcept { return _bits.cbegin(); } + inline typename std::array::const_iterator cbegin() const noexcept { return _bits.cbegin(); } /*! \brief Constant end iterator to bits. */ - inline auto cend() const noexcept { return _bits.cend(); } + inline typename std::array::const_iterator cend() const noexcept { return _bits.cend(); } /*! \brief Constant reverse begin iterator to bits. */ - inline auto crbegin() const noexcept { return _bits.crbegin(); } + inline typename std::array::const_reverse_iterator crbegin() const noexcept { return _bits.crbegin(); } /*! \brief Constant teverse end iterator to bits. */ - inline auto crend() const noexcept { return _bits.crend(); } + inline typename std::array::const_reverse_iterator crend() const noexcept { return _bits.crend(); } /*! \brief Assign other truth table if number of variables match. From 9eb32f0766969b78dd34d3d5ef11e670a24d03e1 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 8 Feb 2024 15:11:58 +0100 Subject: [PATCH 087/151] Changing compilation flag for c++11 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0cc979b75..3c81251cf 100644 --- a/Makefile +++ b/Makefile @@ -151,7 +151,7 @@ ifdef ABC_USE_LIBSTDCXX endif $(info $(MSG_PREFIX)Using CFLAGS=$(CFLAGS)) -CXXFLAGS += $(CFLAGS) -std=c++17 +CXXFLAGS += $(CFLAGS) -std=c++11 SRC := GARBAGE := core core.* *.stackdump ./tags $(PROG) arch_flags From 17afd93c78f13b3f903b78292cb0f5163e8831f0 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 8 Feb 2024 15:36:09 +0100 Subject: [PATCH 088/151] Extending ACD to work up to 11 variables --- src/base/abci/abc.c | 4 +- src/map/if/acd/ac_decomposition.hpp | 70 ++++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 3c5d3cbb8..2f6d6d545 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -19839,9 +19839,9 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "LUT size (%d) must be greater than the LUT decomposition size (%d).\n", pPars->nLutSize, pPars->nLutDecSize ); return 1; } - if ( pPars->nLutSize < 4 || pPars->nLutSize > 10 ) + if ( pPars->nLutSize < 4 || pPars->nLutSize > 11 ) { - Abc_Print( -1, "This feature only works for [4;10]-LUTs.\n" ); + Abc_Print( -1, "This feature only works for [4;11]-LUTs.\n" ); return 1; } } diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index d55941995..7791ba9d7 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -90,7 +90,7 @@ private: }; private: - static constexpr uint32_t max_num_vars = 10; + static constexpr uint32_t max_num_vars = 11; using STT = kitty::static_truth_table; public: @@ -287,7 +287,7 @@ private: best_tt._bits[i] = ptt[i]; } - local_extend_to( best_tt, num_vars ); + // local_extend_to( best_tt, num_vars ); } template @@ -382,7 +382,7 @@ private: uint32_t pos_new = pInvPerm[var_old + 1]; std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] ); std::swap( pComb[i], pComb[pos_new] ); - kitty::swap_inplace( tt, i, pos_new ); + swap_inplace_local( tt, i, pos_new ); for ( uint32_t j = i + 1; j < k; j++ ) { @@ -390,7 +390,7 @@ private: pos_new = pInvPerm[pComb[j - 1] + 1]; std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] ); std::swap( pComb[j], pComb[pos_new] ); - kitty::swap_inplace( tt, j, pos_new ); + swap_inplace_local( tt, j, pos_new ); } return true; @@ -653,7 +653,7 @@ private: } std::swap( permutations[i], permutations[k] ); - kitty::swap_inplace( best_tt, i, k ); + swap_inplace_local( best_tt, i, k ); ++k; } } @@ -1234,6 +1234,66 @@ private: return false; } + void swap_inplace_local( STT& tt, uint8_t var_index1, uint8_t var_index2 ) + { + if ( var_index1 == var_index2 ) + { + return; + } + + if ( var_index1 > var_index2 ) + { + std::swap( var_index1, var_index2 ); + } + + assert( num_vars > 6 ); + const uint32_t num_blocks = 1 << ( num_vars - 6 ); + + if ( var_index2 <= 5 ) + { + const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + std::transform( std::begin( tt._bits ), std::begin( tt._bits ) + num_blocks, std::begin( tt._bits ), + [shift, &pmask]( uint64_t word ) { + return ( word & pmask[0] ) | ( ( word & pmask[1] ) << shift ) | ( ( word & pmask[2] ) >> shift ); + } ); + } + else if ( var_index1 <= 5 ) /* in this case, var_index2 > 5 */ + { + const auto step = 1 << ( var_index2 - 6 ); + const auto shift = 1 << var_index1; + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = decltype( step ){ 0 }; i < step; ++i ) + { + const auto low_to_high = ( *( it + i ) & kitty::detail::projections[var_index1] ) >> shift; + const auto high_to_low = ( *( it + i + step ) << shift ) & kitty::detail::projections[var_index1]; + *( it + i ) = ( *( it + i ) & ~kitty::detail::projections[var_index1] ) | high_to_low; + *( it + i + step ) = ( *( it + i + step ) & kitty::detail::projections[var_index1] ) | low_to_high; + } + it += 2 * step; + } + } + else + { + const auto step1 = 1 << ( var_index1 - 6 ); + const auto step2 = 1 << ( var_index2 - 6 ); + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = 0; i < step2; i += 2 * step1 ) + { + for ( auto j = 0; j < step1; ++j ) + { + std::swap( *( it + i + j + step1 ), *( it + i + j + step2 ) ); + } + } + it += 2 * step2; + } + } + } + /* Decomposition format for ABC * * The record is an array of unsigned chars where: From 7b74810047cd34ff4e0a37a984bc4eb60ae3412a Mon Sep 17 00:00:00 2001 From: aletempiac Date: Fri, 16 Feb 2024 16:43:24 +0100 Subject: [PATCH 089/151] Changing policy of finding ACD 66 decomposition (faster and 100 percent coverage) --- src/map/if/acd/acd66.hpp | 77 ++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 67d460157..5f925387e 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -156,20 +156,8 @@ private: /* find AC decompositions with minimal multiplicity */ for ( uint32_t i = num_vars - 6; i <= 5 && i <= ps.max_free_set_vars; ++i ) { - auto ret_tuple = enumerate_iset_combinations( i, column_multiplicity_fn[i - 1] ); - uint32_t multiplicity = std::get<2>( ret_tuple ); - - /* check for feasible solution into "66" with one possible shared variable */ - if ( multiplicity <= 2 || ( multiplicity <= 4 && i < 5 ) ) - { - best_tt = std::get<0>( ret_tuple ); - permutations = std::get<1>( ret_tuple ); - best_multiplicity = multiplicity; - best_free_set = i; - - if ( multiplicity <= 2 || check_shared_set() ) - return true; - } + if ( find_decomposition_bs( i, column_multiplicity_fn[i - 1] ) ) + return true; } best_multiplicity = UINT32_MAX; @@ -295,46 +283,57 @@ private: } template - std::tuple, uint32_t> enumerate_iset_combinations( uint32_t free_set_size, Fn&& fn ) + bool find_decomposition_bs( uint32_t free_set_size, Fn&& fn ) { STT tt = start_tt; - /* TT with best cost */ - STT best_tt = tt; - uint32_t best_cost = UINT32_MAX; - /* works up to 16 input truth tables */ assert( num_vars <= 16 ); /* init combinations */ - uint32_t pComb[16], pInvPerm[16], bestPerm[16]; + uint32_t pComb[16], pInvPerm[16]; for ( uint32_t i = 0; i < num_vars; ++i ) { pComb[i] = pInvPerm[i] = i; } /* enumerate combinations */ + best_free_set = free_set_size; do { uint32_t cost = fn( tt ); - if ( cost < best_cost ) + if ( cost == 2 ) { best_tt = tt; - best_cost = cost; + best_multiplicity = cost; for ( uint32_t i = 0; i < num_vars; ++i ) { - bestPerm[i] = pComb[i]; + permutations[i] = pComb[i]; + } + return true; + } + else if ( cost <= 4 && free_set_size < 5 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set2( tt ); + + if ( res > 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, res, num_vars - 1 ); + std::swap( permutations[res], permutations[num_vars - 1] ); + return true; } } } while ( combinations_next( free_set_size, pComb, pInvPerm, tt ) ); - std::array res_perm; - for ( uint32_t i = 0; i < num_vars; ++i ) - { - res_perm[i] = bestPerm[i]; - } - - return std::make_tuple( best_tt, res_perm, best_cost ); + return false; } bool check_shared_var( STT tt, uint32_t free_set_size, uint32_t shared_var, uint32_t multiplicity_limit ) @@ -448,7 +447,7 @@ private: return multiplicity <= multiplicity_limit; } - bool check_shared_set() + int check_shared_set2( STT const& tt ) { /* find one shared set variable */ for ( uint32_t i = best_free_set; i < num_vars; ++i ) @@ -456,27 +455,21 @@ private: /* check the multiplicity of cofactors */ if ( best_free_set < 4 ) { - if ( check_shared_var( best_tt, best_free_set, i, 2 ) ) + if ( check_shared_var( tt, best_free_set, i, 2 ) ) { - /* move shared variable as the most significative one */ - swap_inplace_local( best_tt, i, num_vars - 1 ); - std::swap( permutations[i], permutations[num_vars - 1] ); - return true; + return i; } } else { - if ( check_shared_var5( best_tt, best_free_set, i, 2 ) ) + if ( check_shared_var5( tt, best_free_set, i, 2 ) ) { - /* move shared variable as the most significative one */ - swap_inplace_local( best_tt, i, num_vars - 1 ); - std::swap( permutations[i], permutations[num_vars - 1] ); - return true; + return i; } } } - return false; + return -1; } void compute_decomposition_impl( bool verbose = false ) From 0e471e3ff8ca350fe550af6fb1c92a316db53378 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 20 Feb 2024 14:41:52 +0100 Subject: [PATCH 090/151] Performance improvements of ACD 66 --- src/map/if/acd/acd66.hpp | 225 ++++++++------------------------------- 1 file changed, 47 insertions(+), 178 deletions(-) diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 5f925387e..9377db5ec 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -145,18 +145,10 @@ private: best_multiplicity = UINT32_MAX; best_free_set = UINT32_MAX; - /* array of functions to compute the column multiplicity */ - std::function column_multiplicity_fn[5] = { - [this]( STT const& tt ) { return column_multiplicity<1u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity<2u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity<3u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity5<4u>( tt ); }, - [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } }; - /* find AC decompositions with minimal multiplicity */ for ( uint32_t i = num_vars - 6; i <= 5 && i <= ps.max_free_set_vars; ++i ) { - if ( find_decomposition_bs( i, column_multiplicity_fn[i - 1] ) ) + if ( find_decomposition_bs( i ) ) return true; } @@ -176,81 +168,40 @@ private: local_extend_to( start_tt, num_vars ); } - template - uint32_t column_multiplicity( STT tt ) + uint32_t column_multiplicity( STT const& tt, uint32_t free_set_size ) { - uint64_t multiplicity_set[4] = { 0u, 0u, 0u, 0u }; - uint32_t multiplicity = 0; + assert( free_set_size <= 5 ); + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; - uint64_t constexpr masks_bits[] = { 0x0, 0x3, 0xF, 0x3F }; - uint64_t constexpr masks_idx[] = { 0x0, 0x0, 0x0, 0x3 }; - - /* supports up to 64 values of free set (256 for |FS| == 3)*/ - static_assert( free_set_size <= 3, "Wrong free set size for method used, expected le 3" ); - - /* extract iset functions */ - auto it = std::begin( tt ); - for ( auto i = 0u; i < num_blocks; ++i ) - { - for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) - { - multiplicity_set[( *it >> 6 ) & masks_idx[free_set_size]] |= UINT64_C( 1 ) << ( *it & masks_bits[free_set_size] ); - *it >>= ( 1u << free_set_size ); - } - ++it; - } - - multiplicity = __builtin_popcountl( multiplicity_set[0] ); - - if ( free_set_size == 3 ) - { - multiplicity += __builtin_popcountl( multiplicity_set[1] ); - multiplicity += __builtin_popcountl( multiplicity_set[2] ); - multiplicity += __builtin_popcountl( multiplicity_set[3] ); - } - - return multiplicity; - } - - template - uint32_t column_multiplicity5( STT tt ) - { - uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; - uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; - - static_assert( free_set_size == 5 || free_set_size == 4, "Wrong free set size for method used, expected of 4 or 5" ); - + uint64_t shift = UINT64_C( 1 ) << free_set_size; + uint64_t mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t cofactors[4]; uint32_t size = 0; - uint64_t prev = -1; - std::array multiplicity_set; /* extract iset functions */ auto it = std::begin( tt ); for ( auto i = 0u; i < num_blocks; ++i ) { + uint64_t sub = *it; for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) { - uint32_t fs_fn = static_cast( *it & masks[free_set_size] ); - if ( fs_fn != prev ) + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t k; + for ( k = 0; k < size; ++k ) { - multiplicity_set[size++] = fs_fn; - prev = fs_fn; + if ( fs_fn == cofactors[k] ) + break; } - *it >>= ( 1u << free_set_size ); + if ( k == 4 ) + return 5; + if ( k == size ) + cofactors[size++] = fs_fn; + sub >>= shift; } ++it; } - std::sort( multiplicity_set.begin(), multiplicity_set.begin() + size ); - - /* count unique */ - uint32_t multiplicity = 1; - for ( auto i = 1u; i < size; ++i ) - { - multiplicity += multiplicity_set[i] != multiplicity_set[i - 1] ? 1 : 0; - } - - return multiplicity; + return size; } inline bool combinations_next( uint32_t k, uint32_t* pComb, uint32_t* pInvPerm, STT& tt ) @@ -282,8 +233,7 @@ private: return true; } - template - bool find_decomposition_bs( uint32_t free_set_size, Fn&& fn ) + bool find_decomposition_bs( uint32_t free_set_size ) { STT tt = start_tt; @@ -301,7 +251,7 @@ private: best_free_set = free_set_size; do { - uint32_t cost = fn( tt ); + uint32_t cost = column_multiplicity( tt, free_set_size ); if ( cost == 2 ) { best_tt = tt; @@ -316,7 +266,7 @@ private: { /* look for a shared variable */ best_multiplicity = cost; - int res = check_shared_set2( tt ); + int res = check_shared_set( tt ); if ( res > 0 ) { @@ -336,136 +286,55 @@ private: return false; } - bool check_shared_var( STT tt, uint32_t free_set_size, uint32_t shared_var, uint32_t multiplicity_limit ) + bool check_shared_var( STT const& tt, uint32_t free_set_size, uint32_t shared_var ) { - uint64_t multiplicity_set[2][4] = { { 0u, 0u, 0u, 0u }, { 0u, 0u, 0u, 0u } }; - uint32_t multiplicity0 = 0, multiplicity1 = 0; + assert( free_set_size <= 5 ); + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; - uint64_t constexpr masks_bits[] = { 0x0, 0x3, 0xF, 0x3F }; - uint64_t constexpr masks_idx[] = { 0x0, 0x0, 0x0, 0x3 }; - - /* supports up to 64 values of free set (256 for |FS| == 3)*/ - assert( free_set_size <= 3 ); - + uint64_t shift = UINT64_C( 1 ) << free_set_size; + uint64_t mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t cofactors[2][4]; + uint32_t size[2] = { 0, 0 }; uint32_t shared_var_shift = shared_var - free_set_size; /* extract iset functions */ - uint64_t iteration_counter = 0; + uint32_t iteration_counter = 0; auto it = std::begin( tt ); for ( auto i = 0u; i < num_blocks; ++i ) { + uint64_t sub = *it; for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) { - multiplicity_set[( iteration_counter >> shared_var_shift ) & 1][( *it >> 6 ) & masks_idx[free_set_size]] |= UINT64_C( 1 ) << ( *it & masks_bits[free_set_size] ); - *it >>= ( 1u << free_set_size ); + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t p = ( iteration_counter >> shared_var_shift ) & 1; + uint32_t k; + for ( k = 0; k < size[p]; ++k ) + { + if ( fs_fn == cofactors[p][k] ) + break; + } + if ( k == 2 ) + return false; + if ( k == size[p] ) + cofactors[p][size[p]++] = fs_fn; + sub >>= shift; ++iteration_counter; } ++it; } - multiplicity0 = __builtin_popcountl( multiplicity_set[0][0] ); - multiplicity1 = __builtin_popcountl( multiplicity_set[1][0] ); - - if ( free_set_size == 3 ) - { - multiplicity0 += __builtin_popcountl( multiplicity_set[0][1] ); - multiplicity0 += __builtin_popcountl( multiplicity_set[0][2] ); - multiplicity0 += __builtin_popcountl( multiplicity_set[0][3] ); - - multiplicity1 += __builtin_popcountl( multiplicity_set[1][1] ); - multiplicity1 += __builtin_popcountl( multiplicity_set[1][2] ); - multiplicity1 += __builtin_popcountl( multiplicity_set[1][3] ); - } - - if ( multiplicity0 > multiplicity_limit || multiplicity1 > multiplicity_limit ) - return false; - - best_multiplicity0 = multiplicity0; - best_multiplicity1 = multiplicity1; - return true; } - bool check_shared_var5( STT tt, uint32_t free_set_size, uint32_t shared_var, uint32_t multiplicity_limit ) - { - uint32_t const num_blocks = 1u << ( num_vars - 6 ); - uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; - - assert( free_set_size == 5 || free_set_size == 4 ); - - uint32_t size[2] = { 0, 0 }; - uint64_t prev[2] = { UINT64_MAX, UINT64_MAX }; - std::array multiplicity_set[2]; - - uint32_t shared_var_shift = shared_var - free_set_size; - - /* extract iset functions */ - uint64_t iteration_counter = 0; - auto it = std::begin( tt ); - for ( auto i = 0u; i < num_blocks; ++i ) - { - for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) - { - uint32_t fs_fn = static_cast( *it & masks[free_set_size] ); - uint32_t cofactor = ( iteration_counter >> shared_var_shift ) & 1; - if ( fs_fn != prev[cofactor] ) - { - multiplicity_set[cofactor][size[cofactor]++] = fs_fn; - prev[cofactor] = fs_fn; - } - *it >>= ( 1u << free_set_size ); - ++iteration_counter; - } - ++it; - } - - std::sort( multiplicity_set[0].begin(), multiplicity_set[0].begin() + size[0] ); - - /* count unique in 0 cofactor */ - uint32_t multiplicity = 1; - for ( auto i = 1u; i < size[0]; ++i ) - { - multiplicity += multiplicity_set[0][i] != multiplicity_set[0][i - 1] ? 1 : 0; - } - - if ( multiplicity > multiplicity_limit ) - return false; - - best_multiplicity0 = multiplicity; - - std::sort( multiplicity_set[1].begin(), multiplicity_set[1].begin() + size[1] ); - - /* count unique in 1 cofactor */ - multiplicity = 1; - for ( auto i = 1u; i < size[1]; ++i ) - { - multiplicity += multiplicity_set[1][i] != multiplicity_set[1][i - 1] ? 1 : 0; - } - - best_multiplicity1 = multiplicity; - - return multiplicity <= multiplicity_limit; - } - - int check_shared_set2( STT const& tt ) + inline int check_shared_set( STT const& tt ) { /* find one shared set variable */ for ( uint32_t i = best_free_set; i < num_vars; ++i ) { /* check the multiplicity of cofactors */ - if ( best_free_set < 4 ) + if ( check_shared_var( tt, best_free_set, i ) ) { - if ( check_shared_var( tt, best_free_set, i, 2 ) ) - { - return i; - } - } - else - { - if ( check_shared_var5( tt, best_free_set, i, 2 ) ) - { - return i; - } + return i; } } From 0cd548f1cb771c195004157290e700d673d41a10 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 20 Feb 2024 17:28:50 +0100 Subject: [PATCH 091/151] Performance improvements to ACD --- src/map/if/acd/ac_decomposition.hpp | 35 ++++++++++++++++------------- src/map/if/acd/acd66.hpp | 8 ++----- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index 7791ba9d7..cc50eb8fd 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -203,9 +203,10 @@ private: [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } }; /* find a feasible AC decomposition */ + // for ( uint32_t i = std::min( ps.lut_size - 1, ps.max_free_set_vars); i >= start; --i ) for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) { - auto ret_tuple = enumerate_iset_combinations_offset( i, offset, column_multiplicity_fn[i - 1] ); + auto ret_tuple = enumerate_iset_combinations( i, offset, column_multiplicity_fn[i - 1] ); uint32_t multiplicity = std::get<2>( ret_tuple ); /* additional cost if not support reducing */ @@ -231,7 +232,7 @@ private: return false; /* try without the delay profile */ - if ( best_multiplicity == UINT32_MAX && ps.try_no_late_arrival ) + if ( best_multiplicity == UINT32_MAX ) { delay_profile = 0; if ( ps.support_reducing_only ) @@ -241,7 +242,7 @@ private: for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) { - auto ret_tuple = enumerate_iset_combinations_offset( i, 0, column_multiplicity_fn[i - 1] ); + auto ret_tuple = enumerate_iset_combinations( i, 0, column_multiplicity_fn[i - 1] ); uint32_t multiplicity = std::get<2>( ret_tuple ); /* additional cost if not support reducing */ @@ -291,7 +292,7 @@ private: } template - uint32_t column_multiplicity( STT tt ) + uint32_t column_multiplicity( STT const& tt ) { uint64_t multiplicity_set[4] = { 0u, 0u, 0u, 0u }; uint32_t multiplicity = 0; @@ -303,15 +304,14 @@ private: static_assert( free_set_size <= 3, "Wrong free set size for method used, expected le 3" ); /* extract iset functions */ - auto it = std::begin( tt ); for ( auto i = 0u; i < num_blocks; ++i ) { + uint64_t cof = tt._bits[i]; for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) { - multiplicity_set[( *it >> 6 ) & masks_idx[free_set_size]] |= UINT64_C( 1 ) << ( *it & masks_bits[free_set_size] ); - *it >>= ( 1u << free_set_size ); + multiplicity_set[( cof >> 6 ) & masks_idx[free_set_size]] |= UINT64_C( 1 ) << ( cof & masks_bits[free_set_size] ); + cof >>= ( 1u << free_set_size ); } - ++it; } multiplicity = __builtin_popcountl( multiplicity_set[0] ); @@ -327,7 +327,7 @@ private: } template - uint32_t column_multiplicity5( STT tt ) + uint32_t column_multiplicity5( STT const& tt ) { uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; @@ -339,20 +339,19 @@ private: std::array multiplicity_set; /* extract iset functions */ - auto it = std::begin( tt ); for ( auto i = 0u; i < num_blocks; ++i ) { + uint64_t cof = tt._bits[i]; for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) { - uint64_t fs_fn = *it & masks[free_set_size]; + uint64_t fs_fn = cof & masks[free_set_size]; if ( fs_fn != prev ) { multiplicity_set[size++] = static_cast( fs_fn ); prev = fs_fn; } - *it >>= ( 1u << free_set_size ); + cof >>= ( 1u << free_set_size ); } - ++it; } std::sort( multiplicity_set.begin(), multiplicity_set.begin() + size ); @@ -397,13 +396,13 @@ private: } template - std::tuple, uint32_t> enumerate_iset_combinations_offset( uint32_t free_set_size, uint32_t offset, Fn&& fn ) + std::tuple, uint32_t> enumerate_iset_combinations( uint32_t free_set_size, uint32_t offset, Fn&& fn ) { STT tt = best_tt; /* TT with best cost */ STT best_tt = tt; - uint32_t best_cost = UINT32_MAX; + uint32_t best_cost = ( 1 << ( ps.lut_size - free_set_size ) ) + 1; assert( free_set_size >= offset ); @@ -440,6 +439,12 @@ private: } while ( combinations_offset_next( free_set_size, offset, pComb, pInvPerm, tt ) ); std::array res_perm; + + if ( best_cost > ( 1 << ( ps.lut_size - free_set_size ) ) ) + { + return std::make_tuple( best_tt, res_perm, UINT32_MAX ); + } + for ( uint32_t i = 0; i < num_vars; ++i ) { res_perm[i] = permutations[bestPerm[i]]; diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 9377db5ec..976c1e353 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -179,10 +179,9 @@ private: uint32_t size = 0; /* extract iset functions */ - auto it = std::begin( tt ); for ( auto i = 0u; i < num_blocks; ++i ) { - uint64_t sub = *it; + uint64_t sub = tt._bits[i]; for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) { uint32_t fs_fn = static_cast( sub & mask ); @@ -198,7 +197,6 @@ private: cofactors[size++] = fs_fn; sub >>= shift; } - ++it; } return size; @@ -299,10 +297,9 @@ private: /* extract iset functions */ uint32_t iteration_counter = 0; - auto it = std::begin( tt ); for ( auto i = 0u; i < num_blocks; ++i ) { - uint64_t sub = *it; + uint64_t sub = tt._bits[i]; for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) { uint32_t fs_fn = static_cast( sub & mask ); @@ -320,7 +317,6 @@ private: sub >>= shift; ++iteration_counter; } - ++it; } return true; From 13fd0d55c7b7e54cf0a7fc70ade6ffeae7397d5b Mon Sep 17 00:00:00 2001 From: aletempiac Date: Wed, 21 Feb 2024 09:47:16 +0100 Subject: [PATCH 092/151] Removing unnecessary structs --- src/map/if/acd/ac_wrapper.cpp | 7 ++---- src/map/if/acd/acd66.hpp | 42 ++++++++++++----------------------- 2 files changed, 16 insertions(+), 33 deletions(-) diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index 441cb7008..f2e2f1015 100644 --- a/src/map/if/acd/ac_wrapper.cpp +++ b/src/map/if/acd/ac_wrapper.cpp @@ -74,9 +74,7 @@ int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition ) { using namespace acd; - acd66_params ps; - ps.verify = false; - acd66_impl acd( nVars, ps ); + acd66_impl acd( nVars, false ); if ( acd.run( pTruth ) == 0 ) return 0; @@ -97,8 +95,7 @@ int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition { using namespace acd; - acd66_params ps; - acd66_impl acd( nVars, ps ); + acd66_impl acd( nVars, false ); acd.run( pTruth ); int val = acd.compute_decomposition(); diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 976c1e353..7c8c7a821 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -44,25 +44,6 @@ ABC_NAMESPACE_CXX_HEADER_START namespace acd { -/*! \brief Parameters for acd66 */ -struct acd66_params -{ - /*! \brief Maximum size of the free set (1 < num < 6). */ - uint32_t max_free_set_vars{ 5 }; - - /*! \brief Number of configurations to test for decomposition. */ - uint32_t max_evaluations{ 3 }; - - /*! \brief Run verification before returning. */ - bool verify{ false }; -}; - -/*! \brief Statistics for acd66 */ -struct acd66_stats -{ - uint32_t num_edges{ 0 }; -}; - class acd66_impl { private: @@ -71,8 +52,8 @@ private: using LTT = kitty::static_truth_table<6>; public: - explicit acd66_impl( uint32_t num_vars, acd66_params const& ps, acd66_stats* pst = nullptr ) - : num_vars( num_vars ), ps( ps ), pst( pst ) + explicit acd66_impl( uint32_t num_vars, bool verify = false ) + : num_vars( num_vars ), verify( verify ) { std::iota( permutations.begin(), permutations.end(), 0 ); } @@ -102,17 +83,23 @@ public: compute_decomposition_impl(); - if ( ps.verify && !verify_impl() ) + if ( verify && !verify_impl() ) { return 1; } - if ( pst ) + return 0; + } + + uint32_t get_num_edges() + { + if ( bs_support_size == UINT32_MAX ) { - pst->num_edges = bs_support_size + best_free_set + 1 + ( best_multiplicity > 2 ? 1 : 0 ); + return num_vars + 1 + ( best_multiplicity > 2 ? 1 : 0 ); } - return 0; + /* real value after support minimization */ + return bs_support_size + best_free_set + 1 + ( best_multiplicity > 2 ? 1 : 0 ); } /* contains a 1 for BS variables */ @@ -146,7 +133,7 @@ private: best_free_set = UINT32_MAX; /* find AC decompositions with minimal multiplicity */ - for ( uint32_t i = num_vars - 6; i <= 5 && i <= ps.max_free_set_vars; ++i ) + for ( uint32_t i = num_vars - 6; i <= 5; ++i ) { if ( find_decomposition_bs( i ) ) return true; @@ -940,8 +927,7 @@ private: uint32_t bs_support[6]; uint32_t num_vars; - acd66_params const& ps; - acd66_stats* pst; + bool verify; std::array permutations; }; From eba56b088fe3c4b80e858cd7cc5d75193f4a0fb2 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Wed, 21 Feb 2024 17:13:29 +0100 Subject: [PATCH 093/151] Cleaning code and performance improvements --- src/map/if/acd/ac_decomposition.hpp | 2 +- src/map/if/acd/acd66.hpp | 126 +++++----------------------- 2 files changed, 20 insertions(+), 108 deletions(-) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index cc50eb8fd..8e1fc31b5 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -487,7 +487,7 @@ private: *it >>= ( 1u << best_free_set ); } - offset = ( offset + ( 64 >> best_free_set ) ) % 64; + offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F; ++it; } diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 7c8c7a821..5645f9341 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -66,7 +66,7 @@ public: /* truth table is too large for the settings */ if ( num_vars > max_num_vars || num_vars > 11 ) { - return -1; + return false; } /* convert to static TT */ @@ -132,7 +132,7 @@ private: best_multiplicity = UINT32_MAX; best_free_set = UINT32_MAX; - /* find AC decompositions with minimal multiplicity */ + /* find ACD "66" for different number of variables in the free set */ for ( uint32_t i = num_vars - 6; i <= 5; ++i ) { if ( find_decomposition_bs( i ) ) @@ -160,8 +160,8 @@ private: assert( free_set_size <= 5 ); uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; - uint64_t shift = UINT64_C( 1 ) << free_set_size; - uint64_t mask = ( UINT64_C( 1 ) << shift ) - 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; uint32_t cofactors[4]; uint32_t size = 0; @@ -276,8 +276,8 @@ private: assert( free_set_size <= 5 ); uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; - uint64_t shift = UINT64_C( 1 ) << free_set_size; - uint64_t mask = ( UINT64_C( 1 ) << shift ) - 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; uint32_t cofactors[2][4]; uint32_t size[2] = { 0, 0 }; uint32_t shared_var_shift = shared_var - free_set_size; @@ -333,24 +333,23 @@ private: LTT isets1[2]; /* construct isets */ - STT tt = best_tt; uint32_t offset = 0; uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; - uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; + uint64_t const shift = UINT64_C( 1 ) << best_free_set; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; /* limit analysis on 0 cofactor of the shared variable */ if ( has_shared_set ) num_blocks >>= 1; - auto it = std::begin( tt ); - uint64_t fs_fun[4] = { *it & masks[best_free_set], 0, 0, 0 }; + uint64_t fs_fun[4] = { best_tt._bits[0] & mask, 0, 0, 0 }; for ( auto i = 0u; i < num_blocks; ++i ) { + uint64_t cof = best_tt._bits[i]; for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) { - uint64_t val = *it & masks[best_free_set]; - + uint64_t val = cof & mask; if ( val == fs_fun[0] ) { isets0[0]._bits |= UINT64_C( 1 ) << ( j + offset ); @@ -360,24 +359,21 @@ private: isets0[1]._bits |= UINT64_C( 1 ) << ( j + offset ); fs_fun[1] = val; } - - *it >>= ( 1u << best_free_set ); + cof >>= shift; } - - offset = ( offset + ( 64 >> best_free_set ) ) % 64; - ++it; + offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F; } /* continue on the 1 cofactor if shared set */ if ( has_shared_set ) { - fs_fun[2] = *it & masks[best_free_set]; + fs_fun[2] = best_tt._bits[num_blocks] & mask; for ( auto i = num_blocks; i < ( num_blocks << 1 ); ++i ) { + uint64_t cof = best_tt._bits[i]; for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) { - uint64_t val = *it & masks[best_free_set]; - + uint64_t val = cof & mask; if ( val == fs_fun[2] ) { isets1[0]._bits |= UINT64_C( 1 ) << ( j + offset ); @@ -387,12 +383,9 @@ private: isets1[1]._bits |= UINT64_C( 1 ) << ( j + offset ); fs_fun[3] = val; } - - *it >>= ( 1u << best_free_set ); + cof >>= shift; } - - offset = ( offset + ( 64 >> best_free_set ) ) % 64; - ++it; + offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F; } } @@ -445,7 +438,6 @@ private: /* u = 3 one set has multiplicity 1, use don't cares */ compute_functions3( isets0, isets1, fs_fun ); - compute_composition( fs_fun ); } inline void compute_functions4( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4] ) @@ -488,7 +480,6 @@ private: { if ( !has_var6( f, care, i ) ) { - adjust_truth_table_on_dc( f, care, i ); continue; } @@ -655,85 +646,6 @@ private: return false; } - bool has_var_support( const STT& tt, const STT& care, uint32_t real_num_vars, uint8_t var_index ) - { - assert( var_index < real_num_vars ); - assert( real_num_vars <= tt.num_vars() ); - assert( tt.num_vars() == care.num_vars() ); - - const uint32_t num_blocks = real_num_vars <= 6 ? 1 : ( 1 << ( real_num_vars - 6 ) ); - if ( real_num_vars <= 6 || var_index < 6 ) - { - auto it_tt = std::begin( tt._bits ); - auto it_care = std::begin( care._bits ); - while ( it_tt != std::begin( tt._bits ) + num_blocks ) - { - if ( ( ( ( *it_tt >> ( uint64_t( 1 ) << var_index ) ) ^ *it_tt ) & kitty::detail::projections_neg[var_index] & ( *it_care >> ( uint64_t( 1 ) << var_index ) ) & *it_care ) != 0 ) - { - return true; - } - ++it_tt; - ++it_care; - } - - return false; - } - - const auto step = 1 << ( var_index - 6 ); - for ( auto i = 0u; i < num_blocks; i += 2 * step ) - { - for ( auto j = 0; j < step; ++j ) - { - if ( ( ( tt._bits[i + j] ^ tt._bits[i + j + step] ) & care._bits[i + j] & care._bits[i + j + step] ) != 0 ) - { - return true; - } - } - } - - return false; - } - - template - bool has_var_support( const TT_type& tt, const TT_type& care, uint32_t real_num_vars, uint8_t var_index ) - { - assert( var_index < real_num_vars ); - assert( real_num_vars <= tt.num_vars() ); - assert( tt.num_vars() == care.num_vars() ); - - const uint32_t num_blocks = real_num_vars <= 6 ? 1 : ( 1 << ( real_num_vars - 6 ) ); - if ( real_num_vars <= 6 || var_index < 6 ) - { - auto it_tt = std::begin( tt._bits ); - auto it_care = std::begin( care._bits ); - while ( it_tt != std::begin( tt._bits ) + num_blocks ) - { - if ( ( ( ( *it_tt >> ( uint64_t( 1 ) << var_index ) ) ^ *it_tt ) & kitty::detail::projections_neg[var_index] & ( *it_care >> ( uint64_t( 1 ) << var_index ) ) & *it_care ) != 0 ) - { - return true; - } - ++it_tt; - ++it_care; - } - - return false; - } - - const auto step = 1 << ( var_index - 6 ); - for ( auto i = 0u; i < num_blocks; i += 2 * step ) - { - for ( auto j = 0; j < step; ++j ) - { - if ( ( ( tt._bits[i + j] ^ tt._bits[i + j + step] ) & care._bits[i + j] & care._bits[i + j + step] ) != 0 ) - { - return true; - } - } - } - - return false; - } - void adjust_truth_table_on_dc( LTT& tt, LTT& care, uint32_t var_index ) { uint64_t new_bits = tt._bits & care._bits; @@ -796,7 +708,7 @@ private: ++bytes; /* write support */ - for ( uint32_t i = best_free_set; i < best_free_set; ++i ) + for ( uint32_t i = 0; i < best_free_set; ++i ) { *pArray = (unsigned char)permutations[i]; pArray++; From f72000f5aebd1a222f8357ddc87ae3c3a471c3ff Mon Sep 17 00:00:00 2001 From: aletempiac Date: Wed, 21 Feb 2024 18:25:48 +0100 Subject: [PATCH 094/151] Adding ACD cascade 666, performance improvements --- src/base/abci/abc.c | 4 +- src/map/if/acd/ac_wrapper.cpp | 22 + src/map/if/acd/ac_wrapper.h | 2 + src/map/if/acd/acd66.hpp | 6 +- src/map/if/acd/acd666.hpp | 1256 +++++++++++++++++++++++++++++++++ src/map/if/ifDec66.c | 34 +- 6 files changed, 1316 insertions(+), 8 deletions(-) create mode 100644 src/map/if/acd/acd666.hpp diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 2f6d6d545..f79e8de77 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -19630,9 +19630,9 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pLutStruct = argv[globalUtilOptind]; pPars->fEnableStructN = 1; globalUtilOptind++; - if ( strlen(pPars->pLutStruct) != 2 ) + if ( strlen(pPars->pLutStruct) != 2 && strlen(pPars->pLutStruct) != 3 ) { - Abc_Print( -1, "Command line switch \"-J\" should be followed by a 2-char string (e.g. \"66\").\n" ); + Abc_Print( -1, "Command line switch \"-J\" should be followed by a 2- or 3-char string (e.g. \"66\" or \"666\").\n" ); goto usage; } break; diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index f2e2f1015..be1e8783a 100644 --- a/src/map/if/acd/ac_wrapper.cpp +++ b/src/map/if/acd/ac_wrapper.cpp @@ -19,6 +19,7 @@ #include "ac_wrapper.h" #include "ac_decomposition.hpp" #include "acd66.hpp" +#include "acd666.hpp" ABC_NAMESPACE_IMPL_START @@ -108,4 +109,25 @@ int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition return 0; } +int acd666_evaluate( word * pTruth, unsigned nVars, int compute_decomposition ) +{ + using namespace acd; + + acd666_impl acd( nVars, false ); + + if ( acd.run( pTruth ) == 0 ) + return 0; + + if ( !compute_decomposition ) + return 1; + + int val = acd.compute_decomposition(); + if ( val != 0 ) + { + return 0; + } + + return 1; +} + ABC_NAMESPACE_IMPL_END diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h index 2e052c563..03f17ed40 100644 --- a/src/map/if/acd/ac_wrapper.h +++ b/src/map/if/acd/ac_wrapper.h @@ -31,6 +31,8 @@ int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition ); int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition ); +int acd666_evaluate( word * pTruth, unsigned nVars, int compute_decomposition ); + ABC_NAMESPACE_HEADER_END #endif \ No newline at end of file diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 5645f9341..807181a7a 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -52,7 +52,7 @@ private: using LTT = kitty::static_truth_table<6>; public: - explicit acd66_impl( uint32_t num_vars, bool verify = false ) + explicit acd66_impl( uint32_t const num_vars, bool const verify = false ) : num_vars( num_vars ), verify( verify ) { std::iota( permutations.begin(), permutations.end(), 0 ); @@ -838,8 +838,8 @@ private: uint64_t dec_funcs[2]; uint32_t bs_support[6]; - uint32_t num_vars; - bool verify; + uint32_t const num_vars; + bool const verify; std::array permutations; }; diff --git a/src/map/if/acd/acd666.hpp b/src/map/if/acd/acd666.hpp new file mode 100644 index 000000000..a1287f72c --- /dev/null +++ b/src/map/if/acd/acd666.hpp @@ -0,0 +1,1256 @@ +/**C++File************************************************************** + + FileName [acd666.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Ashenhurst-Curtis decomposition.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alessandro Tempia Calvino] + + Affiliation [EPFL] + + Date [Ver. 1.0. Started - Feb 8, 2024.] + +***********************************************************************/ +/*! + \file acd666.hpp + \brief Ashenhurst-Curtis decomposition for "666" cascade + + \author Alessandro Tempia Calvino +*/ + +#ifndef _ACD666_H_ +#define _ACD666_H_ +#pragma once + +#include +#include +#include +#include +#include + +#include "kitty_constants.hpp" +#include "kitty_constructors.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_operations.hpp" +#include "kitty_operators.hpp" +#include "kitty_static_tt.hpp" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace acd +{ + +class acd666_impl +{ +private: + static constexpr uint32_t max_num_vars = 16; + using STT = kitty::static_truth_table; + using LTT = kitty::static_truth_table<6>; + +public: + explicit acd666_impl( uint32_t const num_vars, bool const verify = false ) + : num_vars( num_vars ), verify( verify ) + { + std::iota( permutations.begin(), permutations.end(), 0 ); + } + + /*! \brief Runs ACD 666 */ + bool run( word* ptt ) + { + assert( num_vars > 6 ); + + /* truth table is too large for the settings */ + if ( num_vars > max_num_vars || num_vars > 16 ) + { + return false; + } + + /* convert to static TT */ + init_truth_table( ptt ); + + /* run ACD trying different bound sets and free sets */ + return find_decomposition(); + } + + int compute_decomposition() + { + if ( best_multiplicity == UINT32_MAX ) + return -1; + + uint32_t n = num_luts == 3 ? rm_support_size : num_vars; + compute_decomposition_impl( n ); + + if ( verify && !verify_impl() ) + { + return 1; + } + + return 0; + } + + uint32_t get_num_edges() + { + if ( support_sizes[0] == UINT32_MAX ) + { + return UINT32_MAX; + } + + uint32_t num_edges = support_sizes[0] + support_sizes[1] + 1 + ( shared_vars[0] < UINT32_MAX ? 1 : 0 ); + + if ( num_luts = 2 ) + return num_edges; + + /* real value after support minimization */ + return num_edges + support_sizes[2] + 1 + ( shared_vars[1] < UINT32_MAX ? 1 : 0 ); + } + + /* contains a 1 for BS variables */ + // unsigned get_profile() + // { + // unsigned profile = 0; + + // if ( support_sizes[0] == UINT32_MAX ) + // return -1; + + // for ( uint32_t i = 0; i < bs_support_size; ++i ) + // { + // profile |= 1 << permutations[best_free_set + bs_support[i]]; + // } + + // return profile; + // } + + // void get_decomposition( unsigned char* decompArray ) + // { + // if ( support_sizes[0] == UINT32_MAX ) + // return; + + // get_decomposition_abc( decompArray ); + // } + +private: + bool find_decomposition() + { + best_multiplicity = UINT32_MAX; + best_free_set = UINT32_MAX; + + /* find ACD "66" for different number of variables in the free set */ + for ( uint32_t i = num_vars - 6; i <= 5; ++i ) + { + if ( find_decomposition_bs( start_tt, num_vars, i ) ) + { + num_luts = 2; + return true; + } + } + + /* find ACD "666" for different number of variables in the free set */ + bool dec_found = false; + uint32_t min_vars_free_set = num_vars <= 11 ? 1 : num_vars - 11; + uint32_t max_vars_free_set = num_vars <= 11 ? num_vars - 7 : 5; + for ( uint32_t i = max_vars_free_set; i >= min_vars_free_set; --i ) + // for ( uint32_t i = min_vars_free_set; i <= max_vars_free_set; ++i ) + { + dec_found = find_decomposition_bs( start_tt, num_vars, i ); + if ( dec_found ) + break; + } + + if ( !dec_found ) + { + best_multiplicity = UINT32_MAX; + return false; + } + + /* compute functions for the top and reminder LUT */ + compute_decomposition_impl_top( num_vars ); + + /* find ACD "66" for the remainder function */ + for ( uint32_t i = rm_support_size - 6; i <= 5; ++i ) + { + if ( find_decomposition_bs( remainder, rm_support_size, i ) ) + { + num_luts = 3; + fix_permutations_remainder( rm_support_size ); + return true; + } + } + + best_multiplicity = UINT32_MAX; + return false; + } + + void init_truth_table( word* ptt ) + { + uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) ); + + for ( uint32_t i = 0; i < num_blocks; ++i ) + { + start_tt._bits[i] = ptt[i]; + } + + local_extend_to( start_tt, num_vars ); + } + + uint32_t column_multiplicity( STT const& tt, uint32_t n, uint32_t free_set_size ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( n > 6 ) ? ( 1u << ( n - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t cofactors[4]; + uint32_t size = 0; + + /* extract iset functions */ + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t k; + for ( k = 0; k < size; ++k ) + { + if ( fs_fn == cofactors[k] ) + break; + } + if ( k == 4 ) + return 5; + if ( k == size ) + cofactors[size++] = fs_fn; + sub >>= shift; + } + } + + return size; + } + + inline bool combinations_next( uint32_t n, uint32_t k, uint32_t* pComb, uint32_t* pInvPerm, STT& tt ) + { + uint32_t i; + + for ( i = k - 1; pComb[i] == n - k + i; --i ) + { + if ( i == 0 ) + return false; + } + + /* move vars */ + uint32_t var_old = pComb[i]; + uint32_t pos_new = pInvPerm[var_old + 1]; + std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] ); + std::swap( pComb[i], pComb[pos_new] ); + swap_inplace_local( tt, n, i, pos_new ); + + for ( uint32_t j = i + 1; j < k; j++ ) + { + var_old = pComb[j]; + pos_new = pInvPerm[pComb[j - 1] + 1]; + std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] ); + std::swap( pComb[j], pComb[pos_new] ); + swap_inplace_local( tt, n, j, pos_new ); + } + + return true; + } + + bool find_decomposition_bs( STT tt, uint32_t n, uint32_t free_set_size ) + { + /* works up to 16 input truth tables */ + assert( n <= 16 ); + + /* init combinations */ + uint32_t pComb[16], pInvPerm[16]; + for ( uint32_t i = 0; i < n; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + best_free_set = free_set_size; + do + { + uint32_t cost = column_multiplicity( tt, n, free_set_size ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < n; ++i ) + { + permutations[i] = pComb[i]; + } + return true; + } + else if ( cost <= 4 && free_set_size < 5 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set( tt, n ); + + if ( res > 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < n; ++i ) + { + permutations[i] = pComb[i]; + } + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, n, res, n - 1 ); + std::swap( permutations[res], permutations[n - 1] ); + return true; + } + } + } while ( combinations_next( n, free_set_size, pComb, pInvPerm, tt ) ); + + return false; + } + + inline bool check_shared_var( STT const& tt, uint32_t n, uint32_t free_set_size, uint32_t shared_var ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( n > 6 ) ? ( 1u << ( n - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t cofactors[2][4]; + uint32_t size[2] = { 0, 0 }; + uint32_t shared_var_shift = shared_var - free_set_size; + + /* extract iset functions */ + uint32_t iteration_counter = 0; + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t p = ( iteration_counter >> shared_var_shift ) & 1; + uint32_t k; + for ( k = 0; k < size[p]; ++k ) + { + if ( fs_fn == cofactors[p][k] ) + break; + } + if ( k == 2 ) + return false; + if ( k == size[p] ) + cofactors[p][size[p]++] = fs_fn; + sub >>= shift; + ++iteration_counter; + } + } + + return true; + } + + inline int check_shared_set( STT const& tt, uint32_t n ) + { + /* find one shared set variable */ + for ( uint32_t i = best_free_set; i < n; ++i ) + { + /* check the multiplicity of cofactors */ + if ( check_shared_var( tt, n, best_free_set, i ) ) + { + return i; + } + } + + return -1; + } + + void compute_decomposition_impl_top( uint32_t n, bool verbose = false ) + { + bool has_shared_set = best_multiplicity > 2; + + /* construct isets involved in multiplicity */ + STT isets0[2]; + STT isets1[2]; + + /* construct isets */ + uint32_t offset = 0; + uint32_t num_blocks = ( n > 6 ) ? ( 1u << ( n - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << best_free_set; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + + /* limit analysis on 0 cofactor of the shared variable */ + if ( has_shared_set ) + num_blocks >>= 1; + + uint64_t fs_fun[4] = { best_tt._bits[0] & mask, 0, 0, 0 }; + + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t cof = best_tt._bits[i]; + for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) + { + uint64_t val = cof & mask; + if ( val == fs_fun[0] ) + { + isets0[0]._bits[i / shift] |= UINT64_C( 1 ) << ( j + offset ); + } + else + { + isets0[1]._bits[i / shift] |= UINT64_C( 1 ) << ( j + offset ); + fs_fun[1] = val; + } + cof >>= shift; + } + offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F; + } + + /* continue on the 1 cofactor if shared set */ + if ( has_shared_set ) + { + fs_fun[2] = best_tt._bits[num_blocks] & mask; + for ( auto i = num_blocks; i < ( num_blocks << 1 ); ++i ) + { + uint64_t cof = best_tt._bits[i]; + for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) + { + uint64_t val = cof & mask; + if ( val == fs_fun[2] ) + { + isets1[0]._bits[i / shift] |= UINT64_C( 1 ) << ( j + offset ); + } + else + { + isets1[1]._bits[i / shift] |= UINT64_C( 1 ) << ( j + offset ); + fs_fun[3] = val; + } + cof >>= shift; + } + offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F; + } + } + + /* find the support minimizing combination with shared set */ + compute_functions_top( isets0, isets1, fs_fun, n ); + + /* print functions */ + if ( verbose ) + { + std::cout << "RM function : "; + kitty::print_hex( remainder ); + std::cout << "\n"; + LTT f; + f._bits = dec_funcs[2]; + std::cout << "Composition function: "; + kitty::print_hex( f ); + std::cout << "\n"; + } + } + + void compute_decomposition_impl( uint32_t n, bool verbose = false ) + { + bool has_shared_set = best_multiplicity > 2; + + /* construct isets involved in multiplicity */ + LTT isets0[2]; + LTT isets1[2]; + + /* construct isets */ + uint32_t offset = 0; + uint32_t num_blocks = ( n > 6 ) ? ( 1u << ( n - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << best_free_set; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + + /* limit analysis on 0 cofactor of the shared variable */ + if ( has_shared_set ) + num_blocks >>= 1; + + uint64_t fs_fun[4] = { best_tt._bits[0] & mask, 0, 0, 0 }; + + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t cof = best_tt._bits[i]; + for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) + { + uint64_t val = cof & mask; + + if ( val == fs_fun[0] ) + { + isets0[0]._bits |= UINT64_C( 1 ) << ( j + offset ); + } + else + { + isets0[1]._bits |= UINT64_C( 1 ) << ( j + offset ); + fs_fun[1] = val; + } + + cof >>= shift; + } + + offset = ( offset + ( 64 >> best_free_set ) ) % 64; + } + + /* continue on the 1 cofactor if shared set */ + if ( has_shared_set ) + { + fs_fun[2] = best_tt._bits[num_blocks] & mask; + for ( auto i = num_blocks; i < ( num_blocks << 1 ); ++i ) + { + uint64_t cof = best_tt._bits[i]; + for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) + { + uint64_t val = cof & mask; + + if ( val == fs_fun[2] ) + { + isets1[0]._bits |= UINT64_C( 1 ) << ( j + offset ); + } + else + { + isets1[1]._bits |= UINT64_C( 1 ) << ( j + offset ); + fs_fun[3] = val; + } + + cof >>= shift; + } + + offset = ( offset + ( 64 >> best_free_set ) ) % 64; + } + } + + /* find the support minimizing combination with shared set */ + compute_functions( isets0, isets1, fs_fun, n ); + + /* print functions */ + if ( verbose ) + { + LTT f; + f._bits = dec_funcs[0]; + std::cout << "BS function : "; + kitty::print_hex( f ); + std::cout << "\n"; + f._bits = dec_funcs[1]; + std::cout << "Composition function: "; + kitty::print_hex( f ); + std::cout << "\n"; + } + } + + inline void compute_functions_top( STT isets0[2], STT isets1[2], uint64_t fs_fun[4], uint32_t n ) + { + /* u = 2 no support minimization */ + if ( best_multiplicity < 3 ) + { + shared_vars[1] = UINT32_MAX; + remainder = isets0[0]; + rm_support_size = n - best_free_set; + for ( uint32_t i = 0; i < n - best_free_set; ++i ) + { + rm_support[i] = permutations[i + best_free_set]; + } + compute_composition( fs_fun, 2 ); + return; + } + + shared_vars[1] = permutations[n - 1]; + + /* u = 4 two possibilities */ + if ( best_multiplicity == 4 ) + { + compute_functions4_top( isets0, isets1, fs_fun, n ); + return; + } + + /* u = 3 if both sets have multiplicity 2 there are no don't cares */ + if ( best_multiplicity0 == best_multiplicity1 ) + { + compute_functions4_top( isets0, isets1, fs_fun, n ); + return; + } + + /* u = 3 one set has multiplicity 1, use don't cares */ + compute_functions3_top( isets0, isets1, fs_fun, n ); + } + + inline void compute_functions( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4], uint32_t n ) + { + /* u = 2 no support minimization */ + if ( best_multiplicity < 3 ) + { + shared_vars[0] = UINT32_MAX; + dec_funcs[0] = isets0[0]._bits; + support_sizes[0] = n - best_free_set; + for ( uint32_t i = 0; i < n - best_free_set; ++i ) + { + supports[0][i] = permutations[i + best_free_set]; + } + compute_composition( fs_fun, 1 ); + return; + } + + shared_vars[0] = permutations[n - 1]; + + /* u = 4 two possibilities */ + if ( best_multiplicity == 4 ) + { + compute_functions4( isets0, isets1, fs_fun, n ); + return; + } + + /* u = 3 if both sets have multiplicity 2 there are no don't cares */ + if ( best_multiplicity0 == best_multiplicity1 ) + { + compute_functions4( isets0, isets1, fs_fun, n ); + return; + } + + /* u = 3 one set has multiplicity 1, use don't cares */ + compute_functions3( isets0, isets1, fs_fun, n ); + } + + inline void compute_functions4_top( STT isets0[2], STT isets1[2], uint64_t fs_fun[4], uint32_t n ) + { + STT f; + uint32_t const num_iset_vars = n - best_free_set; + uint32_t const num_blocks = 1u << ( num_iset_vars - 6 ); + + assert( num_iset_vars > 6 ); + for ( uint32_t i = 0; i < num_blocks; ++i ) + { + f._bits[i] = isets0[0]._bits[i] | isets1[1]._bits[i]; + } + + /* count the number of support variables */ + uint32_t support_vars1 = 0; + for ( uint32_t i = 0; i < num_iset_vars; ++i ) + { + support_vars1 += has_var( f, num_iset_vars, i ) ? 1 : 0; + rm_support[i] = permutations[i + best_free_set]; + } + + /* use a different set */ + for ( uint32_t i = 0; i < num_blocks; ++i ) + { + f._bits[i] = isets0[0]._bits[i] | isets1[0]._bits[i]; + } + + uint32_t support_vars2 = 0; + for ( uint32_t i = 0; i < n - best_free_set; ++i ) + { + support_vars2 += has_var( f, num_iset_vars, i ) ? 1 : 0; + } + + rm_support_size = support_vars2; + if ( support_vars2 > support_vars1 ) + { + for ( uint32_t i = 0; i < num_blocks; ++i ) + { + f._bits[i] = isets0[0]._bits[i] | isets1[1]._bits[i]; + } + std::swap( fs_fun[3], fs_fun[4] ); + rm_support_size = support_vars1; + } + + /* move variables */ + if ( rm_support_size < num_iset_vars ) + { + support_vars1 = 0; + for ( uint32_t i = 0; i < num_iset_vars; ++i ) + { + if ( !has_var( f, num_iset_vars, i ) ) + { + continue; + } + + if ( support_vars1 < i ) + { + swap_inplace_local( f, num_iset_vars, support_vars1, i ); + } + + rm_support[support_vars1] = permutations[i + best_free_set]; + ++support_vars1; + } + } + + remainder = f; + compute_composition( fs_fun, 2 ); + } + + inline void compute_functions4( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4], uint32_t n ) + { + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX }; + LTT f = isets0[0] | isets1[1]; + LTT care; + + assert( n - best_free_set <= 6 ); + care._bits = masks[n - best_free_set]; + + /* count the number of support variables */ + uint32_t support_vars1 = 0; + for ( uint32_t i = 0; i < n - best_free_set; ++i ) + { + support_vars1 += has_var6( f, care, i ) ? 1 : 0; + supports[0][i] = permutations[i + best_free_set]; + } + + /* use a different set */ + f = isets0[0] | isets1[0]; + + uint32_t support_vars2 = 0; + for ( uint32_t i = 0; i < n - best_free_set; ++i ) + { + support_vars2 += has_var6( f, care, i ) ? 1 : 0; + } + + support_sizes[0] = support_vars2; + if ( support_vars2 > support_vars1 ) + { + f = isets0[0] | isets1[1]; + std::swap( fs_fun[3], fs_fun[4] ); + support_sizes[0] = support_vars1; + } + + /* move variables */ + if ( support_sizes[0] < n - best_free_set ) + { + support_vars1 = 0; + for ( uint32_t i = 0; i < n - best_free_set; ++i ) + { + if ( !has_var6( f, care, i ) ) + { + continue; + } + + if ( support_vars1 < i ) + { + kitty::swap_inplace( f, support_vars1, i ); + } + + supports[0][support_vars1] = permutations[i + best_free_set]; + ++support_vars1; + } + } + + dec_funcs[0] = f._bits; + compute_composition( fs_fun, 1 ); + } + + inline void compute_functions3_top( STT isets0[2], STT isets1[2], uint64_t fs_fun[4], uint32_t n ) + { + STT f, care; + uint32_t const num_iset_vars = n - best_free_set; + uint32_t const num_blocks = 1u << ( num_iset_vars - 6 ); + + assert( num_iset_vars > 6 ); + for ( uint32_t i = 0; i < num_blocks; ++i ) + { + f._bits[i] = isets0[0]._bits[i] | isets1[0]._bits[i]; + } + + assert( n - best_free_set <= 6 ); + + /* init the care set */ + if ( best_multiplicity0 == 1 ) + { + for ( uint32_t i = 0; i < num_blocks; ++i ) + { + care._bits[i] = ~( isets0[0]._bits[i] ); + } + fs_fun[1] = fs_fun[0]; + } + else + { + for ( uint32_t i = 0; i < num_blocks; ++i ) + { + care._bits[i] = ~( isets1[0]._bits[i] ); + } + fs_fun[3] = fs_fun[2]; + } + + /* count the number of support variables */ + uint32_t support_vars = 0; + for ( uint32_t i = 0; i < num_iset_vars; ++i ) + { + if ( !has_var_support( f, care, num_iset_vars, i ) ) + { + adjust_truth_table_on_dc( f, care, n, i ); + continue; + } + + if ( support_vars < i ) + { + kitty::swap_inplace( f, support_vars, i ); + } + + rm_support[support_vars] = permutations[i + best_free_set]; + ++support_vars; + } + + rm_support_size = support_vars; + remainder = f; + compute_composition( fs_fun, 2 ); + } + + inline void compute_functions3( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4], uint32_t n ) + { + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX }; + LTT f = isets0[0] | isets1[0]; + LTT care; + + assert( n - best_free_set <= 6 ); + + /* init the care set */ + if ( best_multiplicity0 == 1 ) + { + care._bits = masks[n - best_free_set] & ( ~isets0[0]._bits ); + fs_fun[1] = fs_fun[0]; + } + else + { + care._bits = masks[n - best_free_set] & ( ~isets1[0]._bits ); + fs_fun[3] = fs_fun[2]; + } + + /* count the number of support variables */ + uint32_t support_vars = 0; + for ( uint32_t i = 0; i < n - best_free_set; ++i ) + { + if ( !has_var6( f, care, i ) ) + { + adjust_truth_table_on_dc6( f, care, i ); + continue; + } + + if ( support_vars < i ) + { + kitty::swap_inplace( f, support_vars, i ); + } + + supports[0][support_vars] = i; + ++support_vars; + } + + support_sizes[0] = support_vars; + dec_funcs[0] = f._bits; + compute_composition( fs_fun, 1 ); + } + + void compute_composition( uint64_t fs_fun[4], uint32_t index ) + { + dec_funcs[index] = fs_fun[0] << ( 1 << best_free_set ); + dec_funcs[index] |= fs_fun[1]; + + if ( best_multiplicity > 2 ) + { + dec_funcs[index] |= fs_fun[2] << ( ( 2 << best_free_set ) + ( 1 << best_free_set ) ); + dec_funcs[index] |= fs_fun[3] << ( 2 << best_free_set ); + } + + for ( uint32_t i = 0; i < best_free_set; ++i ) + { + supports[index][i] = permutations[i]; + } + support_sizes[index] = best_free_set; + } + + void fix_permutations_remainder( uint32_t n ) + { + for ( uint32_t i = 0; i < n; ++i ) + { + permutations[i] = rm_support[permutations[i]]; + } + } + + template + void local_extend_to( TT_type& tt, uint32_t real_num_vars ) + { + if ( real_num_vars < 6 ) + { + auto mask = *tt.begin(); + + for ( auto i = real_num_vars; i < num_vars; ++i ) + { + mask |= ( mask << ( 1 << i ) ); + } + + std::fill( tt.begin(), tt.end(), mask ); + } + else + { + uint32_t num_blocks = ( 1u << ( real_num_vars - 6 ) ); + auto it = tt.begin(); + while ( it != tt.end() ) + { + it = std::copy( tt.cbegin(), tt.cbegin() + num_blocks, it ); + } + } + } + + void swap_inplace_local( STT& tt, uint32_t n, uint8_t var_index1, uint8_t var_index2 ) + { + if ( var_index1 == var_index2 ) + { + return; + } + + if ( var_index1 > var_index2 ) + { + std::swap( var_index1, var_index2 ); + } + + assert( n > 6 ); + const uint32_t num_blocks = 1 << ( n - 6 ); + + if ( var_index2 <= 5 ) + { + const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + std::transform( std::begin( tt._bits ), std::begin( tt._bits ) + num_blocks, std::begin( tt._bits ), + [shift, &pmask]( uint64_t word ) { + return ( word & pmask[0] ) | ( ( word & pmask[1] ) << shift ) | ( ( word & pmask[2] ) >> shift ); + } ); + } + else if ( var_index1 <= 5 ) /* in this case, var_index2 > 5 */ + { + const auto step = 1 << ( var_index2 - 6 ); + const auto shift = 1 << var_index1; + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = decltype( step ){ 0 }; i < step; ++i ) + { + const auto low_to_high = ( *( it + i ) & kitty::detail::projections[var_index1] ) >> shift; + const auto high_to_low = ( *( it + i + step ) << shift ) & kitty::detail::projections[var_index1]; + *( it + i ) = ( *( it + i ) & ~kitty::detail::projections[var_index1] ) | high_to_low; + *( it + i + step ) = ( *( it + i + step ) & kitty::detail::projections[var_index1] ) | low_to_high; + } + it += 2 * step; + } + } + else + { + const auto step1 = 1 << ( var_index1 - 6 ); + const auto step2 = 1 << ( var_index2 - 6 ); + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = 0; i < step2; i += 2 * step1 ) + { + for ( auto j = 0; j < step1; ++j ) + { + std::swap( *( it + i + j + step1 ), *( it + i + j + step2 ) ); + } + } + it += 2 * step2; + } + } + } + + inline bool has_var6( const LTT& tt, const LTT& care, uint8_t var_index ) + { + if ( ( ( ( tt._bits >> ( uint64_t( 1 ) << var_index ) ) ^ tt._bits ) & kitty::detail::projections_neg[var_index] & ( care._bits >> ( uint64_t( 1 ) << var_index ) ) & care._bits ) != 0 ) + { + return true; + } + + return false; + } + + inline bool has_var( const STT& tt, uint32_t n, uint8_t var_index ) + { + uint32_t const num_blocks = 1u << ( n - 6 ); + + if ( var_index < 6 ) + { + return std::any_of( std::begin( tt._bits ), std::begin( tt._bits ) + num_blocks, + [var_index]( uint64_t word ) { return ( ( word >> ( uint64_t( 1 ) << var_index ) ) & kitty::detail::projections_neg[var_index] ) != + ( word & kitty::detail::projections_neg[var_index] ); } ); + } + + const auto step = 1 << ( var_index - 6 ); + for ( auto i = 0u; i < num_blocks; i += 2 * step ) + { + for ( auto j = 0; j < step; ++j ) + { + if ( tt._bits[i + j] != tt._bits[i + j + step] ) + { + return true; + } + } + } + return false; + } + + bool has_var_support( const STT& tt, const STT& care, uint32_t real_num_vars, uint8_t var_index ) + { + assert( var_index < real_num_vars ); + assert( real_num_vars <= tt.num_vars() ); + assert( tt.num_vars() == care.num_vars() ); + + const uint32_t num_blocks = real_num_vars <= 6 ? 1 : ( 1 << ( real_num_vars - 6 ) ); + if ( real_num_vars <= 6 || var_index < 6 ) + { + auto it_tt = std::begin( tt._bits ); + auto it_care = std::begin( care._bits ); + while ( it_tt != std::begin( tt._bits ) + num_blocks ) + { + if ( ( ( ( *it_tt >> ( uint64_t( 1 ) << var_index ) ) ^ *it_tt ) & kitty::detail::projections_neg[var_index] & ( *it_care >> ( uint64_t( 1 ) << var_index ) ) & *it_care ) != 0 ) + { + return true; + } + ++it_tt; + ++it_care; + } + + return false; + } + + const auto step = 1 << ( var_index - 6 ); + for ( auto i = 0u; i < num_blocks; i += 2 * step ) + { + for ( auto j = 0; j < step; ++j ) + { + if ( ( ( tt._bits[i + j] ^ tt._bits[i + j + step] ) & care._bits[i + j] & care._bits[i + j + step] ) != 0 ) + { + return true; + } + } + } + + return false; + } + + void adjust_truth_table_on_dc6( LTT& tt, LTT& care, uint32_t var_index ) + { + uint64_t new_bits = tt._bits & care._bits; + tt._bits = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) | + ( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] ); + care._bits = care._bits | ( care._bits >> ( uint64_t( 1 ) << var_index ) ); + } + + void adjust_truth_table_on_dc( STT& tt, STT& care, uint32_t n, uint32_t var_index ) + { + assert( var_index < n ); + const uint32_t num_blocks = n <= 6 ? 1 : ( 1 << ( n - 6 ) ); + + if ( n <= 6 || var_index < 6 ) + { + auto it_tt = std::begin( tt._bits ); + auto it_care = std::begin( care._bits ); + while ( it_tt != std::begin( tt._bits ) + num_blocks ) + { + uint64_t new_bits = *it_tt & *it_care; + *it_tt = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) | + ( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] ); + *it_care = *it_care | ( *it_care >> ( uint64_t( 1 ) << var_index ) ); + + ++it_tt; + ++it_care; + } + return; + } + + const auto step = 1 << ( var_index - 6 ); + for ( auto i = 0u; i < num_blocks; i += 2 * step ) + { + for ( auto j = 0; j < step; ++j ) + { + tt._bits[i + j] = ( tt._bits[i + j] & care._bits[i + j] ) | ( tt._bits[i + j + step] & care._bits[i + j + step] ); + tt._bits[i + j + step] = tt._bits[i + j]; + care._bits[i + j] = care._bits[i + j] | care._bits[i + j + step]; + care._bits[i + j + step] = care._bits[i + j]; + } + } + } + + /* Decomposition format for ABC + * + * The record is an array of unsigned chars where: + * - the first unsigned char entry stores the number of unsigned chars in the record + * - the second entry stores the number of LUTs + * After this, several sub-records follow, each representing one LUT as follows: + * - an unsigned char entry listing the number of fanins + * - a list of fanins, from the LSB to the MSB of the truth table. The N inputs of the original function + * have indexes from 0 to N-1, followed by the internal signals in a topological order + * - the LUT truth table occupying 2^(M-3) bytes, where M is the fanin count of the LUT, from the LSB to the MSB. + * A 2-input LUT, which takes 4 bits, should be stretched to occupy 8 bits (one unsigned char) + * A 0- or 1-input LUT can be represented similarly but it is not expected that such LUTs will be represented + */ + // void get_decomposition_abc( unsigned char* decompArray ) + // { + // unsigned char* pArray = decompArray; + // unsigned char bytes = 2; + + // /* write number of LUTs */ + // pArray++; + // *pArray = 2; + // pArray++; + + // /* write BS LUT */ + // /* write fanin size */ + // *pArray = bs_support_size; + // pArray++; + // ++bytes; + + // /* write support */ + // for ( uint32_t i = 0; i < bs_support_size; ++i ) + // { + // *pArray = (unsigned char)permutations[bs_support[i] + best_free_set]; + // pArray++; + // ++bytes; + // } + + // /* write truth table */ + // uint32_t tt_num_bytes = ( bs_support_size <= 3 ) ? 1 : ( 1 << ( bs_support_size - 3 ) ); + // for ( uint32_t i = 0; i < tt_num_bytes; ++i ) + // { + // *pArray = (unsigned char)( ( dec_funcs[0] >> ( 8 * i ) ) & 0xFF ); + // pArray++; + // ++bytes; + // } + + // /* write top LUT */ + // /* write fanin size */ + // uint32_t support_size = best_free_set + 1 + ( best_multiplicity > 2 ? 1 : 0 ); + // *pArray = support_size; + // pArray++; + // ++bytes; + + // /* write support */ + // for ( uint32_t i = 0; i < best_free_set; ++i ) + // { + // *pArray = (unsigned char)permutations[i]; + // pArray++; + // ++bytes; + // } + + // *pArray = (unsigned char)num_vars; + // pArray++; + // ++bytes; + + // if ( best_multiplicity > 2 ) + // { + // *pArray = (unsigned char)permutations[num_vars - 1]; + // pArray++; + // ++bytes; + // } + + // /* write truth table */ + // tt_num_bytes = ( support_size <= 3 ) ? 1 : ( 1 << ( support_size - 3 ) ); + // for ( uint32_t i = 0; i < tt_num_bytes; ++i ) + // { + // *pArray = (unsigned char)( ( dec_funcs[1] >> ( 8 * i ) ) & 0xFF ); + // pArray++; + // ++bytes; + // } + + // /* write numBytes */ + // *decompArray = bytes; + // } + + bool verify_impl() + { + /* create PIs */ + STT pis[max_num_vars]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + kitty::create_nth_var( pis[i], i ); + } + + STT bsi[6]; + STT bsf_sim; + for ( uint32_t lut_i = 0; lut_i < num_luts; ++lut_i ) + { + for ( uint32_t i = 0; i < support_sizes[lut_i]; ++i ) + { + bsi[i] = pis[supports[lut_i][i]]; + } + + STT top_sim; + for ( uint32_t i = 0u; i < ( 1 << num_vars ); ++i ) + { + uint32_t pattern = 0u; + for ( auto j = 0; j < support_sizes[lut_i]; ++j ) + { + pattern |= get_bit( bsi[j], i ) << j; + } + if ( lut_i != 0 ) + { + pattern |= get_bit( bsf_sim, i ) << support_sizes[lut_i]; + if ( shared_vars[lut_i - 1] < UINT32_MAX ) + { + pattern |= get_bit( pis[shared_vars[lut_i - 1]], i ) << ( support_sizes[lut_i] + 1 ); + } + } + if ( ( dec_funcs[lut_i] >> pattern ) & 1 ) + { + set_bit( top_sim, i ); + } + } + + bsf_sim = top_sim; + } + + /* extend function */ + local_extend_to( bsf_sim, num_vars ); + + for ( uint32_t i = 0; i < ( 1 << ( num_vars - 6 ) ); ++i ) + { + if ( bsf_sim._bits[i] != start_tt._bits[i] ) + { + std::cout << "Found incorrect decomposition\n"; + report_tt( bsf_sim ); + std::cout << " instead_of\n"; + report_tt( start_tt ); + return false; + } + } + + return true; + } + + uint32_t get_bit( const STT& tt, uint64_t index ) + { + return ( tt._bits[index >> 6] >> ( index & 0x3f ) ) & 0x1; + } + + void set_bit( STT& tt, uint64_t index ) + { + tt._bits[index >> 6] |= uint64_t( 1 ) << ( index & 0x3f ); + } + + void report_tt( STT const& stt ) + { + kitty::dynamic_truth_table tt( num_vars ); + + std::copy( std::begin( stt._bits ), std::begin( stt._bits ) + ( 1 << ( num_vars - 6 ) ), std::begin( tt ) ); + kitty::print_hex( tt ); + std::cout << "\n"; + } + +private: + uint32_t best_multiplicity{ UINT32_MAX }; + uint32_t best_free_set{ UINT32_MAX }; + uint32_t best_multiplicity0{ UINT32_MAX }; + uint32_t best_multiplicity1{ UINT32_MAX }; + uint32_t rm_support_size{ UINT32_MAX }; + uint32_t num_luts{ 0 }; + + STT start_tt; + STT best_tt; + STT remainder; + + uint64_t dec_funcs[3]; + uint32_t supports[3][6]; + uint32_t support_sizes[3] = { UINT32_MAX, UINT32_MAX, UINT32_MAX }; + uint32_t rm_support[15]; + uint32_t shared_vars[2]; + + uint32_t const num_vars; + bool const verify; + std::array permutations; +}; + +} // namespace acd + +ABC_NAMESPACE_CXX_HEADER_END + +#endif // _ACD666_H_ \ No newline at end of file diff --git a/src/map/if/ifDec66.c b/src/map/if/ifDec66.c index 3a836363d..5c2dce53b 100644 --- a/src/map/if/ifDec66.c +++ b/src/map/if/ifDec66.c @@ -276,6 +276,31 @@ int If_CluCheck66( If_Man_t * p, word * pTruth0, int nVars, int fHashing ) return G1.nVars; } +// returns if successful +int If_CluCheck666( If_Man_t * p, word * pTruth0, int nVars, int fHashing ) +{ + If_Grp_t G1 = {0}; + unsigned * pHashed = NULL; + + if ( p && fHashing ) + { + pHashed = If_CluHashLookup2( p, pTruth0, 0 ); + if ( pHashed && *pHashed != CLU_UNUSED ) + If_CluUns2Grp2( *pHashed, &G1 ); + } + + /* new entry */ + if ( G1.nVars == 0 ) + { + G1.nVars = acd666_evaluate( pTruth0, nVars, 0 ); + } + + if ( pHashed ) + *pHashed = If_CluGrp2Uns2( &G1 ); + + return G1.nVars; +} + /**Function************************************************************* Synopsis [Performs ACD into 66 cascade.] @@ -302,7 +327,7 @@ int If_CutPerformCheck66( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeav // quit if parameters are wrong Length = strlen(pStr); - if ( Length != 2 ) + if ( Length != 2 && Length != 3 ) { printf( "Wrong LUT struct (%s)\n", pStr ); return 0; @@ -316,7 +341,7 @@ int If_CutPerformCheck66( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeav } } - if ( nLeaves > 11 ) + if ( ( Length == 2 && nLeaves > 11 ) || ( Length == 3 && nLeaves > 16 ) ) { printf( "The cut size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr ); return 0; @@ -327,7 +352,10 @@ int If_CutPerformCheck66( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeav return 1; // derive the decomposition - return If_CluCheck66(p, (word*)pTruth, nVars, 1); + if ( Length == 2 ) + return If_CluCheck66(p, (word*)pTruth, nVars, 1); + else + return If_CluCheck666(p, (word*)pTruth, nVars, 1); } //////////////////////////////////////////////////////////////////////// From d3f140f1dfca176e7d79777217bef4dd25210be4 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 27 Feb 2024 17:36:24 +0100 Subject: [PATCH 095/151] Performance improvements --- src/map/if/acd/ac_decomposition.hpp | 86 +++++++++++++++++++++++++++-- src/map/if/acd/acd66.hpp | 3 +- src/map/if/acd/acd666.hpp | 5 +- 3 files changed, 87 insertions(+), 7 deletions(-) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index 8e1fc31b5..3c72b792f 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -366,6 +366,40 @@ private: return multiplicity; } + uint32_t column_multiplicity2( STT const& tt, uint32_t free_set_size ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t cofactors[4]; + uint32_t size = 0; + + /* extract iset functions */ + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t k; + for ( k = 0; k < size; ++k ) + { + if ( fs_fn == cofactors[k] ) + break; + } + if ( k == 2 ) + return 3; + if ( k == size ) + cofactors[size++] = fs_fn; + sub >>= shift; + } + } + + return size; + } + inline bool combinations_offset_next( uint32_t k, uint32_t offset, uint32_t* pComb, uint32_t* pInvPerm, STT& tt ) { uint32_t i; @@ -401,7 +435,7 @@ private: STT tt = best_tt; /* TT with best cost */ - STT best_tt = tt; + STT local_best_tt = tt; uint32_t best_cost = ( 1 << ( ps.lut_size - free_set_size ) ) + 1; assert( free_set_size >= offset ); @@ -416,6 +450,12 @@ private: /* works up to 16 input truth tables */ assert( num_vars <= 16 ); + /* Search for column multiplicity of 2 */ + if ( free_set_size == ps.lut_size - 1 ) + { + return enumerate_iset_combinations2( free_set_size, offset ); + } + /* init combinations */ uint32_t pComb[16], pInvPerm[16], bestPerm[16]; for ( uint32_t i = 0; i < num_vars; ++i ) @@ -429,7 +469,7 @@ private: uint32_t cost = fn( tt ); if ( cost < best_cost ) { - best_tt = tt; + local_best_tt = tt; best_cost = cost; for ( uint32_t i = 0; i < num_vars; ++i ) { @@ -442,7 +482,7 @@ private: if ( best_cost > ( 1 << ( ps.lut_size - free_set_size ) ) ) { - return std::make_tuple( best_tt, res_perm, UINT32_MAX ); + return std::make_tuple( local_best_tt, res_perm, UINT32_MAX ); } for ( uint32_t i = 0; i < num_vars; ++i ) @@ -450,7 +490,45 @@ private: res_perm[i] = permutations[bestPerm[i]]; } - return std::make_tuple( best_tt, res_perm, best_cost ); + return std::make_tuple( local_best_tt, res_perm, best_cost ); + } + + inline std::tuple, uint32_t> enumerate_iset_combinations2( uint32_t free_set_size, uint32_t offset ) + { + STT tt = best_tt; + + /* TT with best cost */ + STT local_best_tt = tt; + uint32_t best_cost = ( 1 << ( ps.lut_size - free_set_size ) ) + 1; + + assert( free_set_size >= offset ); + + /* init combinations */ + uint32_t pComb[16], pInvPerm[16]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + std::array res_perm; + + do + { + uint32_t cost = column_multiplicity2( tt, free_set_size ); + if ( cost <= 2 ) + { + local_best_tt = tt; + best_cost = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + res_perm[i] = permutations[pComb[i]]; + } + return std::make_tuple( local_best_tt, res_perm, best_cost ); + } + } while ( combinations_offset_next( free_set_size, offset, pComb, pInvPerm, tt ) ); + + return std::make_tuple( local_best_tt, res_perm, UINT32_MAX ); } std::vector compute_isets( bool verbose = false ) diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 807181a7a..52de4581b 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -162,6 +162,7 @@ private: uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; uint64_t const shift = UINT64_C( 1 ) << free_set_size; uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const limit = free_set_size < 5 ? 4 : 2; uint32_t cofactors[4]; uint32_t size = 0; @@ -178,7 +179,7 @@ private: if ( fs_fn == cofactors[k] ) break; } - if ( k == 4 ) + if ( k == limit ) return 5; if ( k == size ) cofactors[size++] = fs_fn; diff --git a/src/map/if/acd/acd666.hpp b/src/map/if/acd/acd666.hpp index a1287f72c..72ae68ec4 100644 --- a/src/map/if/acd/acd666.hpp +++ b/src/map/if/acd/acd666.hpp @@ -101,7 +101,7 @@ public: uint32_t num_edges = support_sizes[0] + support_sizes[1] + 1 + ( shared_vars[0] < UINT32_MAX ? 1 : 0 ); - if ( num_luts = 2 ) + if ( num_luts == 2 ) return num_edges; /* real value after support minimization */ @@ -203,6 +203,7 @@ private: uint32_t const num_blocks = ( n > 6 ) ? ( 1u << ( n - 6 ) ) : 1; uint64_t const shift = UINT64_C( 1 ) << free_set_size; uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const limit = free_set_size < 5 ? 4 : 2; uint32_t cofactors[4]; uint32_t size = 0; @@ -219,7 +220,7 @@ private: if ( fs_fn == cofactors[k] ) break; } - if ( k == 4 ) + if ( k == limit ) return 5; if ( k == size ) cofactors[size++] = fs_fn; From 44a65c23ed1604f4605a227b97ee6a14b08ed2bb Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 27 Feb 2024 17:47:43 +0100 Subject: [PATCH 096/151] Adding relaxation on the maximum free set constraint --- src/map/if/acd/ac_decomposition.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index 3c72b792f..7cd6d9613 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -111,6 +111,12 @@ public: uint32_t late_arriving = __builtin_popcount( delay_profile ); + /* relax maximum number of free set variables if a function has more variables */ + if ( num_vars > ps.max_free_set_vars + ps.lut_size ) + { + ps.max_free_set_vars = num_vars - ps.lut_size; + } + /* return a high cost if too many late arriving variables */ if ( late_arriving > ps.lut_size - 1 || late_arriving > ps.max_free_set_vars ) { @@ -1444,7 +1450,7 @@ private: std::vector> support_minimization_encodings; uint32_t num_vars; - ac_decomposition_params const& ps; + ac_decomposition_params ps; ac_decomposition_stats* pst; std::array permutations; }; From 75abcd376beb39ee163b5db9ec9d87802a4ead33 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Wed, 28 Feb 2024 09:51:32 +0100 Subject: [PATCH 097/151] Adding bindings to use ACD66 instead of generic ACD --- src/map/if/acd/ac_wrapper.cpp | 96 +++++++++++++------ src/map/if/acd/acd66.hpp | 169 ++++++++++++++++++++++++++++++++-- 2 files changed, 229 insertions(+), 36 deletions(-) diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index be1e8783a..7786f0e72 100644 --- a/src/map/if/acd/ac_wrapper.cpp +++ b/src/map/if/acd/ac_wrapper.cpp @@ -23,52 +23,92 @@ ABC_NAMESPACE_IMPL_START +static constexpr bool use_generic_acd = true; + int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ) { using namespace acd; - ac_decomposition_params ps; - ps.lut_size = lutSize; - ps.try_no_late_arrival = static_cast( try_no_late_arrival ); /* TODO: additional tests */ - ac_decomposition_stats st; - - ac_decomposition_impl acd( nVars, ps, &st ); - int val = acd.run( pTruth, *pdelay ); - - if ( val < 0 ) + if ( use_generic_acd ) { - *pdelay = 0; - return -1; + ac_decomposition_params ps; + ps.lut_size = lutSize; + ps.try_no_late_arrival = static_cast( try_no_late_arrival ); /* TODO: additional tests */ + ac_decomposition_stats st; + + ac_decomposition_impl acd( nVars, ps, &st ); + int val = acd.run( pTruth, *pdelay ); + + if ( val < 0 ) + { + *pdelay = 0; + return -1; + } + + *pdelay = acd.get_profile(); + *cost = 2; + + return val; } + else + { + acd66_impl acd( nVars ); + int val = acd.run( pTruth, *pdelay ); - *pdelay = acd.get_profile(); - *cost = st.num_luts; + if ( val == 0 ) + { + *pdelay = 0; + return -1; + } - return val; + *pdelay = acd.get_profile(); + *cost = 2; + + return val; + } } int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ) { using namespace acd; - ac_decomposition_params ps; - ps.lut_size = lutSize; - ac_decomposition_stats st; - - ac_decomposition_impl acd( nVars, ps, &st ); - acd.run( pTruth, *pdelay ); - int val = acd.compute_decomposition(); - - if ( val < 0 ) + if ( use_generic_acd ) { - *pdelay = 0; - return -1; + ac_decomposition_params ps; + ps.lut_size = lutSize; + ac_decomposition_stats st; + + ac_decomposition_impl acd( nVars, ps, &st ); + acd.run( pTruth, *pdelay ); + int val = acd.compute_decomposition(); + + if ( val < 0 ) + { + *pdelay = 0; + return -1; + } + + *pdelay = acd.get_profile(); + acd.get_decomposition( decomposition ); + return 0; } + else + { + acd66_impl acd( nVars ); + acd.run( pTruth, *pdelay ); + int val = acd.compute_decomposition(); - *pdelay = acd.get_profile(); + if ( val != 0 ) + { + *pdelay = 0; + return -1; + } - acd.get_decomposition( decomposition ); - return 0; + *pdelay = acd.get_profile(); + + acd.get_decomposition( decomposition ); + return 0; + } } int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition ) diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 52de4581b..92caf3b57 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -76,6 +76,34 @@ public: return find_decomposition() ? 1 : 0; } + /*! \brief Runs ACD 66 */ + int run( word* ptt, unsigned delay_profile ) + { + assert( num_vars > 6 ); + + /* truth table is too large for the settings */ + if ( num_vars > max_num_vars || num_vars > 11 ) + { + return false; + } + + uint32_t late_arriving = __builtin_popcount( delay_profile ); + + /* too many late arriving variables */ + if ( late_arriving > 5 ) + return 0; + + /* convert to static TT */ + init_truth_table( ptt ); + best_tt = start_tt; + + /* permute late arriving variables to be the least significant */ + reposition_late_arriving_variables( delay_profile, late_arriving ); + + /* run ACD trying different bound sets and free sets */ + return find_decomposition_offset( late_arriving ) ? ( delay_profile == 0 ? 2 : 1 ) : 0; + } + int compute_decomposition() { if ( best_multiplicity == UINT32_MAX ) @@ -102,17 +130,17 @@ public: return bs_support_size + best_free_set + 1 + ( best_multiplicity > 2 ? 1 : 0 ); } - /* contains a 1 for BS variables */ + /* contains a 1 for FS variables */ unsigned get_profile() { unsigned profile = 0; - if ( bs_support_size == UINT32_MAX ) + if ( best_multiplicity == UINT32_MAX ) return -1; - for ( uint32_t i = 0; i < bs_support_size; ++i ) + for ( uint32_t i = 0; i < best_free_set; ++i ) { - profile |= 1 << permutations[best_free_set + bs_support[i]]; + profile |= 1 << permutations[i]; } return profile; @@ -143,6 +171,22 @@ private: return false; } + bool find_decomposition_offset( uint32_t offset ) + { + best_multiplicity = UINT32_MAX; + best_free_set = UINT32_MAX; + + /* find ACD "66" for different number of variables in the free set */ + for ( uint32_t i = std::max( num_vars - 6, offset ); i <= 5; ++i ) + { + if ( find_decomposition_bs_offset( i, offset ) ) + return true; + } + + best_multiplicity = UINT32_MAX; + return false; + } + void init_truth_table( word* ptt ) { uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) ); @@ -190,13 +234,13 @@ private: return size; } - inline bool combinations_next( uint32_t k, uint32_t* pComb, uint32_t* pInvPerm, STT& tt ) + inline bool combinations_next( uint32_t k, uint32_t offset, uint32_t* pComb, uint32_t* pInvPerm, STT& tt ) { uint32_t i; for ( i = k - 1; pComb[i] == num_vars - k + i; --i ) { - if ( i == 0 ) + if ( i == offset ) return false; } @@ -254,7 +298,7 @@ private: best_multiplicity = cost; int res = check_shared_set( tt ); - if ( res > 0 ) + if ( res >= 0 ) { best_tt = tt; for ( uint32_t i = 0; i < num_vars; ++i ) @@ -267,7 +311,96 @@ private: return true; } } - } while ( combinations_next( free_set_size, pComb, pInvPerm, tt ) ); + } while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) ); + + return false; + } + + bool find_decomposition_bs_offset( uint32_t free_set_size, uint32_t offset ) + { + STT tt = best_tt; + + /* works up to 16 input truth tables */ + assert( num_vars <= 16 ); + best_free_set = free_set_size; + + /* special case */ + if ( free_set_size == offset ) + { + uint32_t cost = column_multiplicity( tt, free_set_size ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + return true; + } + else if ( cost <= 4 && free_set_size < 5 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set( tt ); + + if ( res >= 0 ) + { + best_tt = tt; + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, res, num_vars - 1 ); + std::swap( permutations[res], permutations[num_vars - 1] ); + return true; + } + } + return false; + } + + /* init combinations */ + uint32_t pComb[16], pInvPerm[16]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + do + { + uint32_t cost = column_multiplicity( tt, free_set_size ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + return true; + } + else if ( cost <= 4 && free_set_size < 5 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set( tt ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, res, num_vars - 1 ); + std::swap( permutations[res], permutations[num_vars - 1] ); + return true; + } + } + } while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) ); return false; } @@ -552,6 +685,26 @@ private: } } + inline void reposition_late_arriving_variables( unsigned delay_profile, uint32_t late_arriving ) + { + uint32_t k = 0; + for ( uint32_t i = 0; i < late_arriving; ++i ) + { + while ( ( ( delay_profile >> k ) & 1 ) == 0 ) + ++k; + + if ( permutations[i] == k ) + { + ++k; + continue; + } + + std::swap( permutations[i], permutations[k] ); + swap_inplace_local( best_tt, i, k ); + ++k; + } + } + template void local_extend_to( TT_type& tt, uint32_t real_num_vars ) { From 48b5f3b399a51b96bc379ea18052374e64e5fec2 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 29 Feb 2024 17:15:29 +0100 Subject: [PATCH 098/151] ACD66 performance improvements by avoiding unnecessary computation --- src/map/if/acd/acd66.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 92caf3b57..7d7a14faa 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -160,8 +160,10 @@ private: best_multiplicity = UINT32_MAX; best_free_set = UINT32_MAX; + uint32_t max_free_set = num_vars == 11 ? 5 : 4; + /* find ACD "66" for different number of variables in the free set */ - for ( uint32_t i = num_vars - 6; i <= 5; ++i ) + for ( uint32_t i = num_vars - 6; i <= max_free_set; ++i ) { if ( find_decomposition_bs( i ) ) return true; @@ -176,8 +178,10 @@ private: best_multiplicity = UINT32_MAX; best_free_set = UINT32_MAX; + uint32_t max_free_set = ( num_vars == 11 || offset == 5 ) ? 5 : 4; + /* find ACD "66" for different number of variables in the free set */ - for ( uint32_t i = std::max( num_vars - 6, offset ); i <= 5; ++i ) + for ( uint32_t i = std::max( num_vars - 6, offset ); i <= max_free_set; ++i ) { if ( find_decomposition_bs_offset( i, offset ) ) return true; From fa8a2777659aa8c229b451ff494b5b639d73ec14 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 29 Feb 2024 17:16:49 +0100 Subject: [PATCH 099/151] Changing search space exploration of ACD to search for better implementation and prune unnecessary computations based on theoretical properties --- src/map/if/acd/ac_decomposition.hpp | 18 +++++++++++++----- src/map/if/acd/ac_wrapper.cpp | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index 7cd6d9613..d573da2cd 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -58,7 +58,7 @@ struct ac_decomposition_params bool support_reducing_only{ true }; /*! \brief Use the first feasible decomposition found. */ - bool use_first{ true }; + bool use_first{ false }; /*! \brief If decomposition with delay profile fails, try without. */ bool try_no_late_arrival{ false }; @@ -116,6 +116,10 @@ public: { ps.max_free_set_vars = num_vars - ps.lut_size; } + if ( late_arriving > ps.max_free_set_vars ) + { + ps.max_free_set_vars = late_arriving; + } /* return a high cost if too many late arriving variables */ if ( late_arriving > ps.lut_size - 1 || late_arriving > ps.max_free_set_vars ) @@ -227,11 +231,13 @@ private: best_cost = multiplicity + additional_cost; best_free_set = i; - if ( ps.use_first ) + if ( !ps.use_first ) { - break; + continue; } } + + break; } if ( best_multiplicity == UINT32_MAX && ( !ps.try_no_late_arrival || late_arriving == 0 ) ) @@ -263,11 +269,13 @@ private: best_cost = multiplicity + additional_cost; best_free_set = i; - if ( ps.use_first ) + if ( !ps.use_first ) { - break; + continue; } } + + break; } } diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index 7786f0e72..7551335f8 100644 --- a/src/map/if/acd/ac_wrapper.cpp +++ b/src/map/if/acd/ac_wrapper.cpp @@ -46,7 +46,7 @@ int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, } *pdelay = acd.get_profile(); - *cost = 2; + *cost = st.num_luts; return val; } From 1fd79c84302c641173e999b56b915651ff141b55 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 29 Feb 2024 15:19:47 -0800 Subject: [PATCH 100/151] Fixing a bug in input/output name ordering. --- src/aig/gia/giaMan.c | 120 +++++++++++++++++++++++-------------------- src/base/abci/abc.c | 4 +- 2 files changed, 65 insertions(+), 59 deletions(-) diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index 7498630a8..5d8c86b31 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -1254,7 +1254,7 @@ void Gia_ManDfsSlacksPrint( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -void Gia_ManWriteNamesInter( FILE * pFile, char c, int n, int Start, int Skip, int nRegs ) +void Gia_ManWriteNamesInter( FILE * pFile, char c, int n, int Start, int Skip, int nRegs, int fReverse ) { int Length = Start, i, fFirst = 1; char pName[100]; @@ -1318,9 +1318,9 @@ void Gia_ManDumpInterface2( Gia_Man_t * p, FILE * pFile ) fprintf( pFile, "_inst" ); fprintf( pFile, " (\n " ); - Gia_ManWriteNamesInter( pFile, 'i', Gia_ManCiNum(p), 4, 4, Gia_ManRegNum(p) ); + Gia_ManWriteNamesInter( pFile, 'i', Gia_ManCiNum(p), 4, 4, Gia_ManRegNum(p), 0 ); fprintf( pFile, ",\n " ); - Gia_ManWriteNamesInter( pFile, 'o', Gia_ManCoNum(p), 4, 4, Gia_ManRegNum(p) ); + Gia_ManWriteNamesInter( pFile, 'o', Gia_ManCoNum(p), 4, 4, Gia_ManRegNum(p), 0 ); fprintf( pFile, "\n );\n\n" ); fprintf( pFile, "endmodule\n\n" ); @@ -1387,16 +1387,17 @@ char * Gia_ObjGetDumpName( Vec_Ptr_t * vNames, char c, int i, int d ) sprintf( pBuffer, "%c%0*d%c", c, d, i, c ); return pBuffer; } -void Gia_ManWriteNames( FILE * pFile, char c, int n, Vec_Ptr_t * vNames, int Start, int Skip, Vec_Bit_t * vObjs ) +void Gia_ManWriteNames( FILE * pFile, char c, int n, Vec_Ptr_t * vNames, int Start, int Skip, Vec_Bit_t * vObjs, int fReverse ) { int Digits = Abc_Base10Log( n ); int Length = Start, i, fFirst = 1; char * pName; for ( i = 0; i < n; i++ ) { - if ( vObjs && !Vec_BitEntry(vObjs, i) ) + int k = fReverse ? n-1-i : i; + if ( vObjs && !Vec_BitEntry(vObjs, k) ) continue; - pName = Gia_ObjGetDumpName( vNames, c, i, Digits ); + pName = Gia_ObjGetDumpName( vNames, c, k, Digits ); Length += strlen(pName) + 2; if ( Length > 60 ) { @@ -1464,26 +1465,26 @@ void Gia_ManDumpVerilogNoInter( Gia_Man_t * p, char * pFileName, Vec_Int_t * vOb if ( fVerBufs ) { fprintf( pFile, " (\n " ); - Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 4, 4, NULL ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 4, 4, NULL, 0 ); fprintf( pFile, ",\n " ); - Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL ); + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL, 0 ); fprintf( pFile, "\n );\n\n" ); fprintf( pFile, " input " ); - Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " output " ); - Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL ); + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); Gia_ManForEachPi( p, pObj, i ) @@ -1503,32 +1504,32 @@ void Gia_ManDumpVerilogNoInter( Gia_Man_t * p, char * pFileName, Vec_Int_t * vOb else { fprintf( pFile, " (\n " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 4, 4, NULL ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 4, 4, NULL, 0 ); fprintf( pFile, ",\n " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL, 0 ); fprintf( pFile, "\n );\n\n" ); fprintf( pFile, " input " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " output " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vUsed) ) { fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vInvs) ) { fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); fprintf( pFile, ";\n\n" ); } @@ -1644,26 +1645,26 @@ void Gia_ManDumpVerilogNoInterAssign( Gia_Man_t * p, char * pFileName, Vec_Int_t if ( fVerBufs ) { fprintf( pFile, " (\n " ); - Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 4, 4, NULL ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 4, 4, NULL, 0 ); fprintf( pFile, ",\n " ); - Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL ); + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL, 0 ); fprintf( pFile, "\n );\n\n" ); fprintf( pFile, " input " ); - Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " output " ); - Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL ); + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); Gia_ManForEachPi( p, pObj, i ) @@ -1683,32 +1684,32 @@ void Gia_ManDumpVerilogNoInterAssign( Gia_Man_t * p, char * pFileName, Vec_Int_t else { fprintf( pFile, " (\n " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 4, 4, NULL ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 4, 4, NULL, 0 ); fprintf( pFile, ",\n " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL, 0 ); fprintf( pFile, "\n );\n\n" ); fprintf( pFile, " input " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " output " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vUsed) ) { fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vInvs) ) { fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); fprintf( pFile, ";\n\n" ); } @@ -1838,7 +1839,7 @@ Vec_Int_t * Gia_ManCountSymbsAll( Vec_Ptr_t * vNames ) } return vArray; } -void Gia_ManDumpIoList( Gia_Man_t * p, FILE * pFile, int fOuts ) +void Gia_ManDumpIoList( Gia_Man_t * p, FILE * pFile, int fOuts, int fReverse ) { Vec_Ptr_t * vNames = fOuts ? p->vNamesOut : p->vNamesIn; if ( vNames == NULL ) @@ -1849,13 +1850,18 @@ void Gia_ManDumpIoList( Gia_Man_t * p, FILE * pFile, int fOuts ) int iName, Size, i; Vec_IntForEachEntryDouble( vArray, iName, Size, i ) { + if ( fReverse ) + { + iName = Vec_IntEntry(vArray, Vec_IntSize(vArray)-2-i); + Size = Vec_IntEntry(vArray, Vec_IntSize(vArray)-1-i); + } if ( i ) fprintf( pFile, ", " ); Gia_ManPrintOneName( pFile, (char *)Vec_PtrEntry(vNames, iName), Size ); } Vec_IntFree( vArray ); } } -void Gia_ManDumpIoRanges( Gia_Man_t * p, FILE * pFile, int fOuts, int fReverse ) +void Gia_ManDumpIoRanges( Gia_Man_t * p, FILE * pFile, int fOuts ) { Vec_Ptr_t * vNames = fOuts ? p->vNamesOut : p->vNamesIn; if ( p->vNamesOut == NULL ) @@ -1874,7 +1880,7 @@ void Gia_ManDumpIoRanges( Gia_Man_t * p, FILE * pFile, int fOuts, int fReverse ) int NumEnd = Gia_ManReadRangeNum( pNameLast, Size ); fprintf( pFile, " %s ", fOuts ? "output" : "input" ); if ( NumBeg != -1 && iName < iNameNext-1 ) - fprintf( pFile, "[%d:%d] ", fReverse ? NumBeg : NumEnd, fReverse ? NumEnd : NumBeg ); + fprintf( pFile, "[%d:%d] ", NumEnd, NumBeg ); Gia_ManPrintOneName( pFile, pName, Size ); fprintf( pFile, ";\n" ); } @@ -1916,45 +1922,45 @@ void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName, int fReverse ) Gia_ManDumpModuleName( pFile, p->pName ); fprintf( pFile, "_wrapper" ); fprintf( pFile, " ( " ); - Gia_ManDumpIoList( p, pFile, 0 ); + Gia_ManDumpIoList( p, pFile, 0, 0 ); fprintf( pFile, ", " ); - Gia_ManDumpIoList( p, pFile, 1 ); + Gia_ManDumpIoList( p, pFile, 1, 0 ); fprintf( pFile, " );\n\n" ); - Gia_ManDumpIoRanges( p, pFile, 0, fReverse ); - Gia_ManDumpIoRanges( p, pFile, 1, fReverse ); + Gia_ManDumpIoRanges( p, pFile, 0 ); + Gia_ManDumpIoRanges( p, pFile, 1 ); fprintf( pFile, "\n" ); fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " assign { " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL ); + Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL, 1 ); fprintf( pFile, " } = { " ); - Gia_ManDumpIoList( p, pFile, 0 ); + Gia_ManDumpIoList( p, pFile, 0, 1 ); fprintf( pFile, " };\n\n" ); fprintf( pFile, " assign { " ); - Gia_ManDumpIoList( p, pFile, 1 ); + Gia_ManDumpIoList( p, pFile, 1, 1 ); fprintf( pFile, " } = { " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL ); + Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL, 1 ); fprintf( pFile, " };\n\n" ); if ( Vec_BitCount(vUsed) ) { fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vInvs) ) { fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); fprintf( pFile, ";\n\n" ); } @@ -2027,45 +2033,45 @@ void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName, int fReverse ) Gia_ManDumpModuleName( pFile, p->pName ); fprintf( pFile, "_wrapper" ); fprintf( pFile, " ( " ); - Gia_ManDumpIoList( p, pFile, 0 ); + Gia_ManDumpIoList( p, pFile, 0, 0 ); fprintf( pFile, ", " ); - Gia_ManDumpIoList( p, pFile, 1 ); + Gia_ManDumpIoList( p, pFile, 1, 0 ); fprintf( pFile, " );\n\n" ); - Gia_ManDumpIoRanges( p, pFile, 0, fReverse ); - Gia_ManDumpIoRanges( p, pFile, 1, fReverse ); + Gia_ManDumpIoRanges( p, pFile, 0 ); + Gia_ManDumpIoRanges( p, pFile, 1 ); fprintf( pFile, "\n" ); fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " assign { " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL ); + Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL, 1 ); fprintf( pFile, " } = { " ); - Gia_ManDumpIoList( p, pFile, 0 ); + Gia_ManDumpIoList( p, pFile, 0, 1 ); fprintf( pFile, " };\n\n" ); fprintf( pFile, " assign { " ); - Gia_ManDumpIoList( p, pFile, 1 ); + Gia_ManDumpIoList( p, pFile, 1, 1 ); fprintf( pFile, " } = { " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL ); + Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL, 1 ); fprintf( pFile, " };\n\n" ); if ( Vec_BitCount(vUsed) ) { fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vInvs) ) { fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); fprintf( pFile, ";\n\n" ); } diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 809d62aa5..89683acf7 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -32150,7 +32150,7 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &w [-upicabmlnrsvh] \n" ); + Abc_Print( -2, "usage: &w [-upicabmlnsvh] \n" ); Abc_Print( -2, "\t writes the current AIG into the AIGER file\n" ); Abc_Print( -2, "\t-u : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" ); Abc_Print( -2, "\t-p : toggle writing Verilog with 'and' and 'not' [default = %s]\n", fVerilog? "yes" : "no" ); @@ -32161,7 +32161,7 @@ usage: Abc_Print( -2, "\t-m : toggle writing MiniAIG rather than AIGER [default = %s]\n", fMiniAig? "yes" : "no" ); Abc_Print( -2, "\t-l : toggle writing MiniLUT rather than AIGER [default = %s]\n", fMiniLut? "yes" : "no" ); Abc_Print( -2, "\t-n : toggle writing \'\\n\' after \'c\' in the AIGER file [default = %s]\n", fWriteNewLine? "yes": "no" ); - Abc_Print( -2, "\t-r : toggle reversing the order of input/output bits [default = %s]\n", fReverse? "yes": "no" ); + //Abc_Print( -2, "\t-r : toggle reversing the order of input/output bits [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-s : toggle skipping the timestamp in the output file [default = %s]\n", fSkipComment? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); From 6f5656c18837f86f2a9e18fe35046fb7ee306c9f Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Fri, 1 Mar 2024 16:05:41 +0800 Subject: [PATCH 101/151] shared EI/EO not handled yet --- src/aig/gia/gia.h | 23 + src/aig/gia/giaBound.c | 1043 ++++++++++++++++++++++++++++++++++++++ src/aig/gia/giaDup.c | 600 +--------------------- src/aig/gia/module.make | 3 +- src/base/abci/abc.c | 168 ++++-- src/misc/vec/vecBit.h | 21 + src/proof/cec/cecSatG2.c | 119 +---- 7 files changed, 1240 insertions(+), 737 deletions(-) create mode 100644 src/aig/gia/giaBound.c diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index dab6770bb..cbd2b9484 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1789,6 +1789,29 @@ extern void Tas_ManSatPrintStats( Tas_Man_t * p ); extern int Tas_ManSolve( Tas_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ); extern int Tas_ManSolveArray( Tas_Man_t * p, Vec_Ptr_t * vObjs ); +/*=== giaBound.c ===========================================================*/ +typedef struct Bnd_Man_t_ Bnd_Man_t; + +extern Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl ); +extern void Bnd_ManStop(); +//for fraig +extern void Bnd_ManMap( int iLit, int id, int spec ); +extern void Bnd_ManMerge( int id1, int id2, int phaseDiff ); +extern void Bnd_ManFinalizeMappings(); +extern void Bnd_ManPrintMappings(); +// for eco +extern int Bnd_ManCheckBound( Gia_Man_t *p ); +extern void Bnd_ManFindBound( Gia_Man_t *p ); +extern Gia_Man_t* Bnd_ManGenSpecOut( Gia_Man_t *p ); +extern Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t *p ); +extern Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPatch ); +extern void Bnd_ManSetEqOut( int eq ); +extern void Bnd_ManSetEqRes( int eq ); +extern void Bnd_ManPrintStats(); + +// util +extern Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec_Bit_t* vEI_phase, Vec_Bit_t* vEO_phase ); + ABC_NAMESPACE_HEADER_END diff --git a/src/aig/gia/giaBound.c b/src/aig/gia/giaBound.c new file mode 100644 index 000000000..63b2c389b --- /dev/null +++ b/src/aig/gia/giaBound.c @@ -0,0 +1,1043 @@ +#include "gia.h" +#include "misc/tim/tim.h" +#include "misc/vec/vecWec.h" +#include "proof/cec/cec.h" + + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Bnd_Man_t_ Bnd_Man_t; + +struct Bnd_Man_t_ +{ + int nBI; + int nBO; + int nBI_miss; + int nBO_miss; + int nInternal; + int nExtra; + int nMerged_spec; + int nMerged_impl; + + int nNode_spec; + int nNode_impl; + int nNode_patch; + int nNode_patched; + + int status; // 0: init 1: boundary found 2: out generated 3: patched generated + + int combLoop_spec; + int combLoop_impl; + int eq_out; + int eq_res; + int nChoice; + + Vec_Ptr_t* vBmiter2Spec; + Vec_Ptr_t* vBmiter2Impl; + Vec_Int_t* vSpec2Impl; + Vec_Bit_t* vSpec2Impl_phase; + + Vec_Int_t* vBI; + Vec_Int_t* vBO; + Vec_Int_t* vEI_spec; + Vec_Int_t* vEO_spec; + Vec_Int_t* vEI_impl; + Vec_Int_t* vEO_impl; + Vec_Bit_t* vEI_phase; + Vec_Bit_t* vEO_phase; + + Vec_Int_t* vSpec2Impl_diff; + +}; + +Bnd_Man_t* pBnd; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +void Bnd_ManSetEqOut( int eq ) { pBnd -> eq_out = eq;} +void Bnd_ManSetEqRes( int eq ) { pBnd -> eq_res = eq;} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl ) +{ + int i; + Bnd_Man_t* p = ABC_CALLOC( Bnd_Man_t, 1 ); + + p -> vBmiter2Spec = Vec_PtrAlloc( Gia_ManObjNum(pSpec) + Gia_ManObjNum(pImpl) ); + p -> vBmiter2Impl = Vec_PtrAlloc( Gia_ManObjNum(pSpec) + Gia_ManObjNum(pImpl) ); + Vec_PtrFill( p -> vBmiter2Spec, (Gia_ManObjNum(pSpec) + Gia_ManObjNum(pImpl)), 0 ); + Vec_PtrFill( p -> vBmiter2Impl, (Gia_ManObjNum(pSpec) + Gia_ManObjNum(pImpl)), 0 ); + for( i = 0; i < Vec_PtrSize( p -> vBmiter2Impl ); i ++ ) + { + Vec_PtrSetEntry( p -> vBmiter2Spec, i, Vec_IntAlloc(1) ); + Vec_PtrSetEntry( p -> vBmiter2Impl, i, Vec_IntAlloc(1) ); + } + + p -> vSpec2Impl = Vec_IntAlloc( Gia_ManObjNum(pSpec) ); + p -> vSpec2Impl_phase = Vec_BitAlloc( Gia_ManObjNum(pSpec) ); + Vec_IntFill( p -> vSpec2Impl, Gia_ManObjNum(pSpec), -1 ); + Vec_BitFill( p -> vSpec2Impl_phase, Gia_ManObjNum(pSpec), 0 ); + + p -> vBI = Vec_IntAlloc(16); + p -> vBO = Vec_IntAlloc(16); + p -> vEI_spec = Vec_IntAlloc(16); + p -> vEO_spec = Vec_IntAlloc(16); + p -> vEI_impl = Vec_IntAlloc(16); + p -> vEO_impl = Vec_IntAlloc(16); + p -> vEI_phase = Vec_BitAlloc(16); + p -> vEO_phase = Vec_BitAlloc(16); + + p -> nNode_spec = Gia_ManAndNum(pSpec) - Gia_ManBufNum(pSpec); + p -> nNode_impl = Gia_ManAndNum(pImpl); + p -> nNode_patch = 0; + p -> nNode_patched = 0; + + p -> status = 0; + p -> combLoop_spec = 0; + p -> combLoop_impl = 0; + p -> eq_out = 0; + p -> eq_res = 0; + + p -> nChoice = 0; + + p -> vSpec2Impl_diff = Vec_IntAlloc( Gia_ManObjNum(pSpec) ); + Vec_IntFill( p -> vSpec2Impl_diff, Gia_ManObjNum(pSpec), 0 ); + + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bnd_ManStop() +{ + assert(pBnd); + + Vec_PtrFree( pBnd-> vBmiter2Spec ); + Vec_PtrFree( pBnd-> vBmiter2Impl ); + Vec_IntFree( pBnd-> vSpec2Impl ); + Vec_BitFree( pBnd-> vSpec2Impl_phase ); + + Vec_IntFree( pBnd->vBI ); + Vec_IntFree( pBnd->vBO ); + Vec_IntFree( pBnd->vEI_spec ); + Vec_IntFree( pBnd->vEO_spec ); + Vec_IntFree( pBnd->vEI_impl ); + Vec_IntFree( pBnd->vEO_impl ); + Vec_BitFree( pBnd->vEI_phase ); + Vec_BitFree( pBnd->vEO_phase ); + + Vec_IntFree( pBnd-> vSpec2Impl_diff ); + + ABC_FREE( pBnd ); +} + + +void Bnd_ManMap( int iLit, int id, int spec ) +{ + + if ( spec ) + { + Vec_IntPush( Vec_PtrEntry( pBnd -> vBmiter2Spec, iLit >> 1), id ); + Vec_BitSetEntry( pBnd -> vSpec2Impl_phase, id, iLit & 1 ); + } + else + { + assert( (iLit & 1) == 0 ); + Vec_IntPush( Vec_PtrEntry( pBnd -> vBmiter2Impl, iLit >> 1), id ); + } +} + +void Bnd_ManMerge( int id_repr, int id_obj, int phaseDiff ) +{ + + + Vec_Ptr_t* vBmiter2Spec = pBnd -> vBmiter2Spec; + Vec_Ptr_t* vBmiter2Impl = pBnd -> vBmiter2Impl; + Vec_Bit_t* vSpec2Impl_phase = pBnd -> vSpec2Impl_phase; + int id, i; + + Vec_Int_t *vIds_spec_repr, *vIds_impl_repr, *vIds_spec_obj, *vIds_impl_obj; + + vIds_spec_repr = Vec_PtrEntry( vBmiter2Spec, id_repr ); + vIds_impl_repr = Vec_PtrEntry( vBmiter2Impl, id_repr ); + vIds_spec_obj = Vec_PtrEntry( vBmiter2Spec, id_obj ); + vIds_impl_obj = Vec_PtrEntry( vBmiter2Impl, id_obj ); + + Vec_IntForEachEntry( vIds_spec_obj, id, i ) + { + Vec_IntPush(vIds_spec_repr, id); + } + Vec_IntForEachEntry( vIds_impl_obj, id, i ) + { + Vec_IntPush(vIds_impl_repr, id); + } + + // handle spec2impl phase + if ( phaseDiff ) + { + Vec_IntForEachEntry( vIds_spec_obj, id, i ) + { + Vec_BitSetEntry( vSpec2Impl_phase, id, !Vec_BitEntry(vSpec2Impl_phase, id) ); + // printf( "spec id %d's phase set to %d\n", id, Vec_BitEntry(vSpec2Impl_phase, id) ); + } + } + + // handle impl2spec phase + /* + if ( Vec_IntSize(vIds_spec_repr) == 0 ) // no match + { + if ( pObj->fPhase ^ pRepr -> fPhase ) + { + Vec_IntForEachEntry( vIds_impl_obj, eId, j ) + { + Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); + printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); + } + } + } + else if ( Vec_IntSize( vIds_spec_repr ) == Vec_IntSize( vIds_spec_obj) && Vec_IntSize( vIds_impl_obj ) == 0 ) // new match + { + if ( pObj->fPhase ^ pRepr -> fPhase ) + { + Vec_IntForEachEntry( vIds_impl_repr, eId, j ) + { + Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); + printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); + } + printf("new match flip\n"); + } + } + else if ( Vec_IntSize( vIds_spec_repr ) > 0 && Vec_IntSize( vIds_impl_obj ) > 0 ) // matched, merge impl + { + if ( ( pObj->fPhase ^ pRepr -> fPhase) ^ ( Vec_BitEntry( vImpl2Spec_phase, Vec_IntEntry(vIds_impl_repr, 0)) ^ Vec_BitEntry( vImpl2Spec_phase, Vec_IntEntry(vIds_impl_obj, 0)) ) ) + { + if ( Vec_IntSize( vIds_spec_repr ) == Vec_IntSize( vIds_spec_obj) ) // unmatched repr, matched obj, set repr bits + { + Vec_IntForEachEntry( vIds_impl_repr, eId, j ) + { + if ( j >= Vec_IntSize( vIds_impl_repr)-Vec_IntSize(vIds_impl_obj) ) break; + Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); + printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); + } + } + else // set obj bits + { + Vec_IntForEachEntry( vIds_impl_obj, eId, j ) + { + Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); + printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); + } + } + } + } + */ + + Vec_IntClear(vIds_spec_obj); + Vec_IntClear(vIds_impl_obj); + +} +void Bnd_ManFinalizeMappings() +{ + + Vec_Ptr_t* vBmiter2Spec = pBnd -> vBmiter2Spec; + Vec_Ptr_t* vBmiter2Impl = pBnd -> vBmiter2Impl; + Vec_Int_t* vSpec2Impl = pBnd -> vSpec2Impl; + + Vec_Int_t *vSpec, *vImpl; + int i, j, id; + + pBnd -> nMerged_impl = 0; + pBnd -> nMerged_spec = 0; + + + for( i = 0; i < Vec_PtrSize(vBmiter2Spec); i++ ) + { + vSpec = Vec_PtrEntry( vBmiter2Spec, i ); + vImpl = Vec_PtrEntry( vBmiter2Impl, i ); + + // create spec2impl + if ( Vec_IntSize(vSpec) != 0 && Vec_IntSize(vImpl) != 0 ) + { + Vec_IntForEachEntry( vSpec, id, j ) + { + Vec_IntSetEntry( vSpec2Impl, id, Vec_IntEntry(vImpl, 0) ); + + // record the number of different choice of vEI_impl, vEO_impl + Vec_IntSetEntry( pBnd->vSpec2Impl_diff, id, Vec_IntSize(vImpl)-1 ); + } + + + } + + // count number of nodes merged into the same circuit + if ( Vec_IntSize(vSpec) != 0 ) + { + pBnd->nMerged_spec += Vec_IntSize(vSpec) - 1; + } + if ( Vec_IntSize(vImpl) != 0 ) + { + pBnd->nMerged_impl += Vec_IntSize(vImpl) - 1; + } + + + + + } + + +} +void Bnd_ManPrintMappings() +{ + Vec_Ptr_t* vBmiter2Spec = pBnd -> vBmiter2Spec; + Vec_Ptr_t* vBmiter2Impl = pBnd -> vBmiter2Impl; + Vec_Int_t* vIds_spec, *vIds_impl; + int k, id; + for( int j=0; j < Vec_PtrSize(vBmiter2Spec); j++ ) + { + printf("node %d: ", j); + vIds_spec = Vec_PtrEntry( vBmiter2Spec, j); + vIds_impl = Vec_PtrEntry( vBmiter2Impl, j); + Vec_IntForEachEntry(vIds_spec, id, k) + printf("%d ", id); + printf("| "); + Vec_IntForEachEntry(vIds_impl, id, k) + printf("%d ", id); + printf("\n"); + } + +} + +void Bnd_ManPrintBound() +{ + + printf("%d nodes merged in spec\n", pBnd ->nMerged_spec - Vec_IntSize(pBnd->vBI) - Vec_IntSize(pBnd->vBO) ); + printf("%d nodes merged in impl\n", pBnd ->nMerged_impl ); + + printf("BI spec:"); Vec_IntPrint(pBnd -> vBI); + printf("BO spec:"); Vec_IntPrint(pBnd -> vBO); + printf("\nEI spec:"); Vec_IntPrint(pBnd -> vEI_spec); + printf("EI impl:"); Vec_IntPrint(pBnd -> vEI_impl); + printf("EI phase:"); Vec_BitPrint(pBnd -> vEI_phase); + printf("\nEO spec:"); Vec_IntPrint(pBnd -> vEO_spec); + printf("EO impl:"); Vec_IntPrint(pBnd -> vEO_impl); + printf("EO phase:"); Vec_BitPrint(pBnd -> vEO_phase); +} + +void Bnd_ManPrintStats() +{ + Bnd_Man_t* p = pBnd; + + // #internal + // nBI, nBO + // nBI_miss, nBO_miss + // nAI, nAO, nExtra + // #spec, #impl, #patched + + // combLoop_spec, combLoop_impl + + // eq_out, eq_res + // status + + // #different choice of impl on boundary + + printf("\nRESULT\n"); + printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + p->nInternal, + p->nBI, p->nBO, + p->nBI_miss, p->nBO_miss, + Vec_IntSize(p->vEI_spec), Vec_IntSize(p->vEO_spec), p->nExtra, + p->nNode_spec, p->nNode_impl, p->nNode_patched, + p->combLoop_spec, p->combLoop_impl, + p->eq_out, p->eq_res, + p->status, + p->nChoice + ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [check if the given boundary is valid. Return 0 if + the boundary is invalid. Return k if the boundary is valid and + there're k boundary inputs. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bnd_ManCheckBound( Gia_Man_t * p ) +{ + int i; + Gia_Obj_t *pObj; + int valid = 1; + pBnd -> nBI = 0; + pBnd -> nBO = 0; + pBnd -> nInternal = 0; + + printf( "Checking boundary... \n"); + + Vec_Int_t *vPath; + vPath = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( vPath, Gia_ManObjNum(p), 0 ); + int path; + + Gia_ManForEachObjReverse1( p , pObj, i ) + { + if ( Gia_ObjIsCo( pObj ) ) + { + Vec_IntSetEntry( vPath, Gia_ObjId( p, pObj ), 1 ); + } + + path = Vec_IntEntry( vPath, Gia_ObjId(p, pObj) ); + // printf("path = %d\n", path); + + if ( path >= 8 ) + { + valid = 0; + printf("there're more than 2 bufs in a path\n"); + break; + } + + + if( Gia_ObjIsBuf( pObj ) ) + { + Vec_IntSetEntry( vPath, Gia_ObjId( p, Gia_ObjFanin0( pObj ) ), Vec_IntEntry( vPath, Gia_ObjId(p, Gia_ObjFanin0( pObj ) ) ) | path << 1 ); + if ( path == 1 ) // boundary input + { + // TODO: record BIs here since they may not be in the first n buffers + pBnd -> nBO ++; + } + } + else if ( Gia_ObjFaninNum( p, pObj ) >= 1 ) + { + Vec_IntSetEntry( vPath, Gia_ObjId( p, Gia_ObjFanin0( pObj ) ), Vec_IntEntry( vPath, Gia_ObjId(p, Gia_ObjFanin0( pObj ) ) ) | path ); + if ( Gia_ObjFaninNum( p, pObj ) >= 2 ) + { + assert( Gia_ObjFaninNum( p, pObj ) <= 2 ); + Vec_IntSetEntry( vPath, Gia_ObjId( p, Gia_ObjFanin1( pObj ) ), Vec_IntEntry( vPath, Gia_ObjId(p, Gia_ObjFanin1( pObj ) ) ) | path ); + } + if ( path == 2 ) // inside boundary + { + // TODO: record BIs here since they may not be in the first n buffers + pBnd -> nInternal ++; + } + } + else // PI or const, check validity + { + if ( (Vec_IntEntry( vPath, Gia_ObjId(p, pObj) ) | 5) != 5 ) + { + valid = 0; + printf("incorrect buf number at pi %d\n", Vec_IntEntry(vPath, Gia_ObjId(p, pObj)) ); + break; + } + } + } + + pBnd -> nBI = Gia_ManBufNum(p) - pBnd -> nBO; + + if ( !valid ) + { + printf("invalid boundary\n"); + return 0; + } + else + { + printf("valid boundary ("); + printf("#BI = %d\t#BO = %d\t", pBnd -> nBI, Gia_ManBufNum(p)- pBnd -> nBI); + printf("#Internal = %d)\n", pBnd -> nInternal ); + assert( pBnd -> nBI > 0 ); + return pBnd -> nBI; + } +} + + +int Bnd_CheckFlagRec( Gia_Man_t *p, Gia_Obj_t *pObj, Vec_Int_t* vFlag ) +{ + int id = Gia_ObjId(p, pObj); + if ( Vec_IntEntry(vFlag, id) == 1 ) return 1; + if ( Vec_IntEntry(vFlag, id) == 2 ) return 0; + + Vec_IntSetEntry(vFlag, id, 1); + + int ret = 1; + for( int i = 0; i < Gia_ObjFaninNum(p, pObj); i++ ) + { + if ( !Bnd_CheckFlagRec( p, Gia_ObjFanin(pObj, i), vFlag ) ) + { + ret = 0; + break; + } + } + return ret; + +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bnd_ManCheckExtBound( Gia_Man_t * p, Vec_Int_t *vEI, Vec_Int_t *vEO ) +{ + Vec_Int_t *vFlag = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( vFlag, Gia_ManObjNum(p), 0 ); + int success = 1; + int i, id; + + Vec_IntForEachEntry( vEO, id, i ) + { + Vec_IntSetEntry( vFlag, id, 2 ); + } + + Vec_IntForEachEntry( vEI, id, i ) + { + if ( Vec_IntEntry(vFlag, id) == 2 ) continue; // BI connected to BO directly + + if ( !Bnd_CheckFlagRec( p, Gia_ManObj(p, id), vFlag ) ) + { + success = 0; + break; + } + } + + + Vec_IntFree(vFlag); + return success; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void Bnd_ManFindBound( Gia_Man_t * p ) +{ + Vec_Int_t *vFlag; + Vec_Ptr_t *vQ; + Gia_Obj_t *pObj; + int i, j, id, cnt; + + Vec_Int_t *vAI = Vec_IntAlloc(16); + Vec_Int_t *vAO = Vec_IntAlloc(16); + + Vec_Int_t *vSpec2Impl = pBnd -> vSpec2Impl; + Vec_Bit_t *vSpec2Impl_phase = pBnd -> vSpec2Impl_phase; + Vec_Int_t *vBI = pBnd -> vBI; + Vec_Int_t *vBO = pBnd -> vBO; + Vec_Int_t *vEI_spec = pBnd -> vEI_spec; + Vec_Int_t *vEO_spec = pBnd -> vEO_spec; + Vec_Int_t *vEI_impl = pBnd -> vEI_impl; + Vec_Int_t *vEO_impl = pBnd -> vEO_impl; + Vec_Bit_t *vEI_phase = pBnd -> vEI_phase; + Vec_Bit_t *vEO_phase = pBnd -> vEO_phase; + + + // prepare to compute extended boundary + vQ = Vec_PtrAlloc(16); + vFlag = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( vFlag, Gia_ManObjNum(p), 0 ); + + Gia_ManStaticFanoutStart(p); + + // save bo, bi + cnt = 0; + Gia_ManForEachBuf(p, pObj, i) + { + if ( cnt < pBnd -> nBI ) + { + Vec_IntPush( vBI, Gia_ObjId(p, pObj) ); + } + else + { + Vec_IntPush( vBO, Gia_ObjId(p, pObj) ); + } + cnt++; + } + printf("#BI = %d #BO = %d\n", Vec_IntSize(vBI), Vec_IntSize(vBO) ); + + // compute EO, travse with flag 1 + Vec_IntForEachEntry( vBO, id, i ) + { + if ( Vec_IntEntry( vSpec2Impl, id ) == -1 ) // BO not matched + { + Vec_PtrPush( vQ, Gia_ManObj(p, id) ); + } + else + { + Vec_IntPush(vEO_spec, id); + } + } + printf("%d BO doesn't match\n", Vec_PtrSize(vQ) ); + pBnd -> nBO_miss = Vec_PtrSize(vQ); + + int cnt_extra = - Vec_PtrSize(vQ); + while( Vec_PtrSize(vQ) > 0 ) + { + pObj = Vec_PtrPop(vQ); + id = Gia_ObjId( p, pObj ); + + if ( Vec_IntEntry( vFlag, id ) == 1 ) continue; + Vec_IntSetEntry( vFlag, id, 1 ); + + // printf("%d\n", id); + + if ( Vec_IntEntry( vSpec2Impl, id ) != -1 ) // matched + { + Vec_IntPush( vEO_spec, id ); + Vec_IntPush( vAO, id ); + } + else + { + for( j = 0; j < Gia_ObjFanoutNum(p, pObj); j++ ) + { + Vec_PtrPush( vQ, Gia_ObjFanout(p, pObj, j) ); + // printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanout(p1, pObj, j) ) ); + } + } + } + // printf("%d AO found with %d extra nodes\n", Vec_IntSize(vAO) , cnt_extra ); + printf("%d AO found\n", Vec_IntSize(vAO) ); + + + // mark TFOC of BO with flag 1 to prevent them from being selected into EI + // stop at CO + Vec_IntForEachEntry( pBnd -> vBO, id, i ) + { + Vec_PtrPush( vQ, Gia_ManObj(p, id) ); + } + Vec_IntForEachEntry( vFlag, id, i ) + { + Vec_IntSetEntry( vFlag, id, 0 ); + } + while( Vec_PtrSize(vQ) > 0 ) + { + pObj = Vec_PtrPop(vQ); + id = Gia_ObjId( p, pObj ); + + if ( Vec_IntEntry( vFlag, id ) == 1 ) continue; + Vec_IntSetEntry( vFlag, id, 1 ); + + for( j = 0; j < Gia_ObjFanoutNum(p, pObj); j++ ) + { + Vec_PtrPush( vQ, Gia_ObjFanout(p, pObj, j) ); + } + } + + + + // compute EI, traverse with flag 2 + + // add unmatched BI to queue + Vec_IntForEachEntry( vBI, id, i ) + { + if ( Vec_IntEntry( vSpec2Impl, id ) == -1 ) // BO not matched + { + Vec_PtrPush( vQ, Gia_ManObj(p, id) ); + } + else + { + Vec_IntPush(vEI_spec, id); + } + } + printf("%d BI doesn't match\n", Vec_PtrSize(vQ) ); + pBnd -> nBI_miss = Vec_PtrSize(vQ); + cnt_extra -= Vec_PtrSize(vQ); + + // add AO to queue + Vec_IntForEachEntry( vAO, id, i ) + { + Vec_PtrPush( vQ, Gia_ManObj(p, id) ); + } + + // set flag 2 for BO + Vec_IntForEachEntry( vBO, id, i ) + { + Vec_IntSetEntry( vFlag, id, 2 ); + } + + // traverse down from AI and unmatched BI + while( Vec_PtrSize(vQ) > 0 ) + { + pObj = Vec_PtrPop(vQ); + id = Gia_ObjId( p, pObj ); + + if ( Vec_IntEntry( vFlag, id ) == 2 ) continue; + cnt_extra ++; + + // printf("%d\n", id); + + if ( Vec_IntEntry(vFlag, id) != 1 && Vec_IntEntry( vSpec2Impl, id ) != -1 ) // matched + { + Vec_IntPush( vEI_spec, id ); + Vec_IntPush( vAI, id ); + } + else + { + for( j = 0; j < Gia_ObjFaninNum(p, pObj); j++ ) + { + Vec_PtrPush( vQ, Gia_ObjFanin(pObj, j) ); + // printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanout(p1, pObj, j) ) ); + } + } + + Vec_IntSetEntry( vFlag, id, 2 ); + } + printf("%d AI found with %d extra nodes in total\n", Vec_IntSize(vAI) , cnt_extra ); + pBnd -> nExtra = cnt_extra; + + + // gen vEI_impl, vEO_impl, vEI_phase, vEO_phase + Vec_IntForEachEntry( vEI_spec, id, i ) + { + Vec_IntPush( vEI_impl, Vec_IntEntry( vSpec2Impl, id ) ); + Vec_BitPush( vEI_phase, Vec_BitEntry( vSpec2Impl_phase, id ) ); + } + Vec_IntForEachEntry( vEO_spec, id, i ) + { + Vec_IntPush( vEO_impl, Vec_IntEntry( vSpec2Impl, id ) ); + Vec_BitPush( vEO_phase, Vec_BitEntry( vSpec2Impl_phase, id ) ); + } + + + // count number of choice of boundary in impl + Vec_IntForEachEntry( vEI_spec, id, i ) + { + pBnd -> nChoice += Vec_IntEntry( pBnd -> vSpec2Impl_diff, id ); + } + Vec_IntForEachEntry( vEO_spec, id, i ) + { + pBnd -> nChoice += Vec_IntEntry( pBnd -> vSpec2Impl_diff, id ); + } + + + // print + pBnd -> status = 1; + printf("#EI = %d\t#EO = %d\t#Extra Node = %d\n", Vec_IntSize(vEI_spec) , Vec_IntSize(vEO_spec), cnt_extra ); + Bnd_ManPrintBound(); + + // check boundary has comb loop + if ( !Bnd_ManCheckExtBound( p, vEI_spec, vEO_spec ) ) + { + printf("Combinational loop exist\n"); + pBnd -> combLoop_spec = 1; + } + + + // clean up + Vec_IntFree(vAI); + Vec_IntFree(vAO); +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [create circuit with the boundary changed to CI/CO] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec_Bit_t* vEI_phase, Vec_Bit_t* vEO_phase ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, id, lit; + + // check if the boundary has loop (EO cannot be in the TFC of EI ) + if ( !Bnd_ManCheckExtBound( p, vEI, vEO ) ) + { + printf("Combinational loop exist\n"); + pBnd -> combLoop_impl = 1; + return 0; + } + + + // initialize + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew -> pName = ABC_ALLOC( char, strlen(p->pName)+10); + sprintf( pNew -> pName, "%s_out", p -> pName ); + Gia_ManHashStart( pNew ); + Gia_ManConst0(p) -> Value = 0; + Gia_ManCleanValue(p); + + + // create ci for ci and eo + Gia_ManForEachCi( p, pObj, i ) + { + pObj -> Value = Gia_ManAppendCi( pNew ); + } + Vec_IntForEachEntry( vEO, id, i ) + { + Gia_ManObj( p, id ) -> Value = Gia_ManAppendCi(pNew); + if ( vEO_phase && Vec_BitEntry( vEO_phase, i ) ) + { + Gia_ManObj( p, id ) -> Value ^= 1; + } + } + + // TODO: consider where EI and EO share the same node + + // add aig nodes + Gia_ManForEachAnd(p, pObj, i) + { + if ( pObj -> Value ) continue; + pObj -> Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + + // create co for co and ei + Gia_ManForEachCo(p, pObj, i) + { + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Vec_IntForEachEntry( vEI, id, i ) + { + lit = Gia_ManObj(p, id)->Value; + // lit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( vEI_phase && Vec_BitEntry( vEI_phase, i ) ) lit ^= 1; + Gia_ManAppendCo( pNew, lit ); + } + + // clean up + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; + +} + +Gia_Man_t* Bnd_ManGenSpecOut( Gia_Man_t* p ) +{ + printf("Generating spec_out with given boundary.\n"); + Gia_Man_t *pNew = Bnd_ManCutBoundary( p, pBnd->vEI_spec, pBnd->vEO_spec, 0, 0 ); + return pNew; +} +Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t* p ) +{ + printf("Generating impl_out with given boundary.\n"); + Gia_Man_t *pNew = Bnd_ManCutBoundary( p, pBnd->vEI_impl, pBnd->vEO_impl, pBnd->vEI_phase, pBnd->vEO_phase ); + if ( pNew ) pBnd -> status = 2; + else pBnd -> combLoop_impl = 1; + return pNew; +} + +void Bnd_AddNodeRec( Gia_Man_t *p, Gia_Man_t *pNew, Gia_Obj_t *pObj ) +{ + // TODO does this mean constant zero node? + if ( pObj -> Value != 0 || Gia_ObjIsConst0(pObj) ) return; + + for( int i = 0; i < Gia_ObjFaninNum(p, pObj); i++ ) + { + Bnd_AddNodeRec( p, pNew, Gia_ObjFanin(pObj, i) ); + } + + if ( Gia_ObjIsAnd(pObj) ) + { + pObj -> Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + else + { + if ( Gia_ObjIsCi(pObj) ) + { + printf("Ci with value 0 encountered (id = %d)\n", Gia_ObjId(p, pObj) ); + } + assert( Gia_ObjIsCo(pObj) ); + pObj -> Value = Gia_ObjFanin0Copy(pObj); + } +} + +Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPatch ) +{ + + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, id, cnt; + Vec_Int_t *vBI_patch, *vBO_patch; + + printf("Generating patched implementation\n"); + pBnd -> nNode_patch = Gia_ManAndNotBufNum( pPatch ); + + pNew = Gia_ManStart( Gia_ManObjNum(pOut) + Gia_ManObjNum( pSpec ) + Gia_ManObjNum(pPatch) ); + pNew -> pName = ABC_ALLOC( char, strlen(pOut->pName)+3); + sprintf( pNew -> pName, "%s_p", pOut -> pName ); + Gia_ManHashStart( pNew ); + Gia_ManCleanValue(pOut); + Gia_ManCleanValue(pSpec); + Gia_ManCleanValue(pPatch); + + // get bi and bo in patch + cnt = 0; + vBI_patch = Vec_IntAlloc(16); + vBO_patch = Vec_IntAlloc(16); + Gia_ManForEachBuf( pPatch, pObj, i ) + { + if ( cnt < pBnd -> nBI ) + { + Vec_IntPush( vBI_patch, Gia_ObjId( pPatch, pObj ) ); + } + else + { + + Vec_IntPush( vBO_patch, Gia_ObjId( pPatch, pObj ) ); + } + cnt ++; + } + assert( Vec_IntSize( vBI_patch ) == Vec_IntSize(pBnd->vBI) ); + assert( Vec_IntSize( vBO_patch ) == Vec_IntSize(pBnd->vBO) ); + assert( Bnd_ManCheckBound(pPatch) != 0 ); + + + // add Impl (real) PI + for ( i = 0; i < Gia_ManCiNum(pSpec); i++ ) + { + pObj = Gia_ManCi(pOut, i); + pObj -> Value = Gia_ManAppendCi( pNew ); + } + + // add Impl EI to CI + printf("adding EI to CI in Impl\n"); + for ( i = 0; i < Vec_IntSize( pBnd -> vEI_spec ); i++ ) + { + pObj = Gia_ManCo(pOut, i + Gia_ManCoNum(pSpec) ); + Bnd_AddNodeRec( pOut, pNew, pObj ); + + // set Spec EI + Gia_ManObj( pSpec, Vec_IntEntry(pBnd -> vEI_spec, i) ) -> Value = pObj -> Value; + printf("%d ", pObj->Value); + } + printf("\n"); + + // add Spec BI to EI + printf("adding BI to EI in Spec\n"); + Vec_IntForEachEntry( pBnd -> vBI, id, i ) + { + pObj = Gia_ManObj( pSpec, id ); + Bnd_AddNodeRec( pSpec, pNew, pObj ); + + // set patch bi + Gia_ManObj( pPatch, Vec_IntEntry( vBI_patch, i) ) -> Value = pObj -> Value; + printf("%d ", pObj->Value); + } + printf("\n"); + + // check + // cnt = 0; + // Gia_ManForEachBuf( pPatch, pObj, i ) + // { + // if ( cnt < pBnd -> nBI ) + // { + // assert(pObj -> Value != 0); + // } + // cnt++; + // } + + // add Patch BO to BI + printf("adding BO to BI in Patch\n"); + Vec_IntForEachEntry( vBO_patch, id, i ) + { + pObj = Gia_ManObj( pPatch, id ); + Bnd_AddNodeRec( pPatch, pNew, pObj ); + + // set spec bo + Gia_ManObj( pSpec, Vec_IntEntry( pBnd -> vBO, i) ) -> Value = pObj -> Value; + printf("%d ", pObj->Value); + } + printf("\n"); + + // add Spec EO to BO + printf("adding EO to BO in Spec\n"); + Vec_IntForEachEntry( pBnd -> vEO_spec, id, i ) + { + pObj = Gia_ManObj( pSpec, id ); + Bnd_AddNodeRec( pSpec, pNew, pObj ); + + // set impl EO (PI) + Gia_ManCi( pOut, i + Gia_ManCiNum(pSpec) ) -> Value = pObj -> Value; + printf("%d ", pObj->Value); + } + printf("\n"); + + // add Impl (real) PO to EO + printf("adding CO to EO in Impl\n"); + for ( i = 0; i < Gia_ManCoNum(pSpec); i++ ) + { + pObj = Gia_ManCo( pOut, i ); + Bnd_AddNodeRec( pOut, pNew, pObj ); + Gia_ManAppendCo( pNew, pObj->Value ); + printf("%d ", pObj->Value); + } + printf("\n"); + + + // clean up + Vec_IntFree( vBI_patch ); + Vec_IntFree( vBO_patch ); + Gia_ManHashStop( pNew ); + + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + pBnd -> nNode_patched = Gia_ManAndNum( pNew ); + pBnd -> status = 3; + + return pNew; +} + + + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 37b3e8e3b..bdcbb970e 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -30,12 +30,8 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -Vec_Ptr_t* vBmiter2Spec; -Vec_Ptr_t* vBmiter2Impl; -Vec_Int_t* vPatch2Impl; -Vec_Bit_t* vImpl2Spec_phase; -Vec_Int_t* vBI_patch; -Vec_Int_t* vBO_patch; + +extern Bnd_Man_t* pBnd; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -5674,9 +5670,9 @@ Gia_Man_t * Gia_ManDupAddFlop( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int biNum) +Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) { - Vec_Int_t * vLits; + // Vec_Int_t * vLits; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iLit; @@ -5694,7 +5690,7 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, assert( Gia_ManRegNum(p2) == 0 ); assert( Gia_ManCiNum(p1) == Gia_ManCiNum(p2) ); assert( Gia_ManCoNum(p1) == Gia_ManCoNum(p2) ); - vLits = Vec_IntAlloc( Gia_ManBufNum(p1) ); + // vLits = Vec_IntAlloc( Gia_ManBufNum(p1) ); if ( fVerbose ) printf( "Creating a boundary miter with %d inputs, %d outputs, and %d buffers.\n", Gia_ManCiNum(p1), Gia_ManCoNum(p1), Gia_ManBufNum(p1) ); @@ -5705,58 +5701,44 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, Gia_ManConst0(p1)->Value = 0; Gia_ManConst0(p2)->Value = 0; - // allocate vImpl2Spec_phase; - vImpl2Spec_phase = Vec_BitAlloc( Gia_ManObjNum(p2) ); - Vec_BitFill( vImpl2Spec_phase, Gia_ManObjNum(p2), 0 ); - // allocate vBmiter2Impl and vBmiter2Spec - Vec_Int_t* pVec_Int; - vBmiter2Impl = Vec_PtrAlloc( (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)) ); - Vec_PtrFill( vBmiter2Impl, (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)), 0 ); - Vec_PtrForEachEntry( Vec_Int_t*, vBmiter2Impl, pVec_Int, i) + for( int i = 0; i < Gia_ManCiNum(p1); i++ ) { - Vec_PtrSetEntry(vBmiter2Impl, i, Vec_IntAlloc(2) ); - } - vBmiter2Spec = Vec_PtrAlloc( (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)) ); - Vec_PtrFill( vBmiter2Spec, (Gia_ManObjNum(p2) + Gia_ManObjNum(p1)), 0 ); - Vec_PtrForEachEntry( Vec_Int_t*, vBmiter2Spec, pVec_Int, i) - { - Vec_PtrSetEntry(vBmiter2Spec, i, Vec_IntAlloc(2) ); + int iLit = Gia_ManCi(p1, i)->Value = Gia_ManCi(p2, i) -> Value = Gia_ManAppendCi(pNew); + + pObj = Gia_ManCi(p1, i); + Bnd_ManMap( iLit, Gia_ObjId( p1, pObj ), 1 ); + + pObj = Gia_ManCi(p2, i); + Bnd_ManMap( iLit, Gia_ObjId( p2, pObj) , 0 ); + } - Gia_ManForEachCi( p1, pObj, i ) - { - pObj->Value = Gia_ManCi(p2, i)->Value = Gia_ManAppendCi( pNew ); - Vec_IntPush( Vec_PtrEntry(vBmiter2Spec, pObj->Value >> 1), Gia_ObjId(p1, pObj) ); - Vec_IntPush( Vec_PtrEntry(vBmiter2Impl, pObj->Value >> 1), Gia_ObjId(p1, pObj) ); // same pi id in impl and spec - } - - // TODO: record the corresponding impl node of each lit + // record the corresponding impl node of each lit Gia_ManForEachAnd( p2, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - Vec_IntPush( Vec_PtrEntry(vBmiter2Impl, pObj->Value >> 1), Gia_ObjId(p2, pObj) ); + Bnd_ManMap( pObj -> Value, Gia_ObjId(p2, pObj), 0 ); } - // TODO: record hashed equivalent nodes - Gia_ManForEachAnd( p1, pObj, i ) { + // record hashed equivalent nodes + Gia_ManForEachAnd( p1, pObj, i ) + { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - Vec_IntPush( Vec_PtrEntry(vBmiter2Spec, pObj->Value >> 1), Gia_ObjId(p1, pObj) ); + Bnd_ManMap( pObj -> Value, Gia_ObjId(p1, pObj), 1 ); } Gia_ManForEachCo( p2, pObj, i ) { - int id = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ) >> 1; - Vec_IntPush( Vec_PtrEntry(vBmiter2Impl, id), Gia_ObjId(p2, pObj) ); + iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManForEachCo( p1, pObj, i ) { - int id = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ) >> 1; - Vec_IntPush( Vec_PtrEntry(vBmiter2Spec, id), Gia_ObjId(p1, pObj) ); + iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } - Vec_IntForEachEntry( vLits, iLit, i ) - Gia_ManAppendCo( pNew, iLit ); - Vec_IntFree( vLits ); + // Vec_IntForEachEntry( vLits, iLit, i ) + // Gia_ManAppendCo( pNew, iLit ); + // Vec_IntFree( vLits ); Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); @@ -5896,538 +5878,6 @@ Gia_Man_t * Gia_ManMiterFromBMiter( Gia_Man_t * p, int nPo ) return pNew; } -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Gia_ManPatch( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int biNum) -{ - Vec_Int_t * vLits; - Gia_Man_t * pNew, * pTemp; - Gia_Obj_t * pObj; - int i, iLit; - if ( Gia_ManBufNum(p1) == 0 ) { - printf( "The first AIG should have a boundary.\n" ); - return NULL; - } - if ( Gia_ManBufNum(p2) == 0 ) { - printf( "The second AIG should have a boundary.\n" ); - return NULL; - } - assert( Gia_ManBufNum(p1) > 0 ); - assert( Gia_ManBufNum(p2) > 0 ); - assert( Gia_ManBufNum(p1) == Gia_ManBufNum(p2) ); - assert( Gia_ManRegNum(p1) == 0 ); - assert( Gia_ManRegNum(p2) == 0 ); - assert( Gia_ManCiNum(p1) == Gia_ManCiNum(p2) ); - assert( Gia_ManCoNum(p1) == Gia_ManCoNum(p2) ); - if ( fVerbose ) - printf( "Mapping spec to patch with %d inputs, %d outputs, and %d buffers.\n", - Gia_ManCiNum(p1), Gia_ManCoNum(p1), Gia_ManBufNum(p1) ); - pNew = Gia_ManStart( Gia_ManObjNum(p2) ); - pNew->pName = ABC_ALLOC( char, strlen(p1->pName) + 10 ); - sprintf( pNew->pName, "%s_patch", p1->pName ); - Gia_ManHashStart( pNew ); - Gia_ManConst0(p1)->Value = 0; - Gia_ManConst0(p2)->Value = 0; - - // add patch aig first - // record lit -> patch id - Vec_Int_t* vVar2Patch = Vec_IntAlloc( Gia_ManObjNum(p2) ); - Vec_IntFill( vVar2Patch, Gia_ManObjNum(p2), -1 ); - - Gia_ManForEachCi( p2, pObj, i ) - { - pObj->Value = Gia_ManCi(p1, i)->Value = Gia_ManAppendCi( pNew ); - Vec_IntSetEntry( vVar2Patch, pObj->Value >> 1, Gia_ObjId( p2, pObj ) ); - } - Gia_ManForEachAnd( p2, pObj, i ) - { - pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - printf( "\t%d: %d %d\n", Gia_ObjId( p2, pObj), Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - Vec_IntSetEntry( vVar2Patch, pObj->Value >> 1, Gia_ObjId( p2, pObj ) ); - } - - - // alloc vCompl; - Vec_Bit_t * vComplBuf = Vec_BitAlloc(Gia_ManBufNum(p1)); - Vec_Bit_t * vCompl = Vec_BitAlloc(Gia_ManObjNum(p1)); - Vec_BitFill( vCompl, Gia_ManObjNum(p1), 0 ); - Gia_ManForEachBuf( p2, pObj, i ) - { - printf("\tbuf compl %d: %d\n", Gia_ObjId(p2, pObj), Gia_ObjFaninC0(pObj)); - Vec_BitPush( vComplBuf, Gia_ObjFaninC0(pObj) ); - } - int cnt = 0; - Gia_ManForEachBuf( p1, pObj, i ) - { - printf("\tbuf compl %d: %d\n", Gia_ObjId(p1, pObj), Gia_ObjFaninC0(pObj)); - if ( Vec_BitEntry( vComplBuf, cnt ) || Gia_ObjFaninC0(pObj) ) - { - Vec_BitSetEntry( vCompl, Gia_ObjId( p1, pObj ), 1 ); - printf("\tset\n"); - } - cnt++; - } - - - - // mark the box in spec - Vec_Int_t* vFlagSpec = Vec_IntAlloc( Gia_ManObjNum(p1) ); // 1: bi, 2: inside the box, 3: bo - Vec_IntFill( vFlagSpec, Gia_ManObjNum(p1), 0 ); - int cnt_buf = 0; - Gia_ManForEachBuf( p1, pObj, i ) - { - if ( cnt_buf < biNum ) - { - Vec_IntSetEntry( vFlagSpec, Gia_ObjId(p1, Gia_ObjFanin0(pObj) ), 1 ); - } - else - { - Vec_IntSetEntry( vFlagSpec, Gia_ObjId(p1, Gia_ObjFanin0(pObj) ), 3 ); - } - cnt_buf ++; - } - - int fanin0, fanin1; - Gia_ManForEachAnd( p1, pObj, i ) - { - if ( Vec_IntEntry( vFlagSpec, Gia_ObjId(p1, pObj) ) != 0 ) continue ; - fanin0 = Vec_IntEntry( vFlagSpec, Gia_ObjId(p1, Gia_ObjFanin0(pObj) ) ); - fanin1 = Vec_IntEntry( vFlagSpec, Gia_ObjId(p1, Gia_ObjFanin1(pObj) ) ); - if ( fanin0 == 1 || fanin0 == 2 || fanin1 == 1 || fanin1 == 2 ) - Vec_IntSetEntry( vFlagSpec, Gia_ObjId(p1, pObj ), 2 ); - } - - - // compute spec2impl - Vec_Int_t* vSpec2Impl = Vec_IntAlloc( Gia_ManObjNum(p1) ); - Vec_IntFill( vSpec2Impl, Gia_ManObjNum(p1), -1 ); - Vec_Int_t* vSpec, *vImpl; - int j, id; - for ( i = 0; i < Vec_PtrSize( vBmiter2Spec ); i++ ) - { - vSpec = Vec_PtrEntry( vBmiter2Spec, i ); - vImpl = Vec_PtrEntry( vBmiter2Impl, i ); - Vec_IntForEachEntry( vSpec, id, j ) - { - if ( Vec_IntEntry( vSpec2Impl, id ) == -1 && Vec_IntSize( vImpl ) > 0 ) - { - Vec_IntSetEntry( vSpec2Impl, id, Vec_IntEntry( vImpl, 0 ) ); - } - } - } - - // print - // printf("spec 2 impl:\n"); - // Vec_IntForEachEntry( vSpec2Impl, id, i ) - // { - // printf( "\t%d:\t %d\n", i, id ); - // } - - // alloc patch2impl - vPatch2Impl = Vec_IntAlloc( Gia_ManObjNum(p2) ); - Vec_IntFill( vPatch2Impl, Gia_ManObjNum(p2), -1 ); - Vec_IntSetEntry( vPatch2Impl, 0, 0 ); - - Gia_ManForEachCi( p2, pObj, i ) - { - Vec_IntSetEntry( vVar2Patch, pObj->Value >> 1, pObj->Value >> 1); - Vec_IntSetEntry( vPatch2Impl, pObj->Value>>1, Vec_IntEntry( vSpec2Impl, pObj->Value>>1) ); - } - - // set the litral on the boundary of spec as in patch and record patch2impl - Vec_Int_t* vBufLit = Vec_IntAlloc( Gia_ManBufNum( p2 ) ); - vBI_patch = Vec_IntAlloc( Gia_ManBufNum(p2) ); - vBO_patch = Vec_IntAlloc( Gia_ManBufNum(p2) ); - cnt_buf = 0; - Gia_ManForEachBuf( p2, pObj, i ) - { - // TODO: check compl - Vec_IntPush( vBufLit, Gia_ObjFanin0( pObj ) -> Value ); - if ( cnt_buf < biNum ) - { - Vec_IntPush( vBI_patch, Gia_ObjFanin0( pObj) -> Value >> 1 ); - } - else - { - Vec_IntPush( vBO_patch, Gia_ObjFanin0( pObj) -> Value >> 1 ); - } - cnt_buf++; - } - Vec_Int_t* vSpec2Patch = Vec_IntAlloc( Gia_ManObjNum(p1) ); - Vec_IntFill( vSpec2Patch, Gia_ManObjNum(p1), -1 ); - - cnt_buf = 0; - Gia_Obj_t * pObj2; - - Gia_ManForEachBuf( p1, pObj, i ) - { - // TODO: compl? - pObj2 = Gia_ObjFanin0(pObj); - pObj2 -> Value = Vec_IntEntry( vBufLit, cnt_buf ); - Vec_IntSetEntry( vSpec2Patch, Gia_ObjId( p1, pObj2 ), Vec_IntEntry( vVar2Patch, pObj2->Value>>1 ) ); - // printf( "spec node %d -> patch node %d\n", Gia_ObjId( p1, pObj2 ), Vec_IntEntry( vVar2Patch, pObj2->Value>>1 ) ); - - Vec_IntSetEntry( vPatch2Impl, pObj2 -> Value>>1, Vec_IntEntry( vSpec2Impl, Gia_ObjId(p1, pObj2) ) ); - pObj->Value = pObj2->Value; - cnt_buf++; - } - - - // hash the area outside the box in spec and record patch2impl - int lit0, lit1; - Gia_ManForEachAnd( p1, pObj, i ) { - printf( "spec node %d(%d) = %d %d\n", Gia_ObjId( p1, pObj ), Vec_IntEntry( vFlagSpec, Gia_ObjId(p1, pObj)), Gia_ObjId( p1, Gia_ObjFanin0(pObj) ), Gia_ObjId( p1, Gia_ObjFanin1(pObj) ) ); - if ( Vec_IntEntry( vFlagSpec, Gia_ObjId(p1, pObj) ) > 1 ) continue; - if ( Gia_ObjIsBuf(pObj) ) continue; - - lit0 = Gia_ObjFanin0Copy(pObj); - lit1 = Gia_ObjFanin1Copy(pObj); - if ( Vec_BitEntry( vCompl, Gia_ObjId(p1, Gia_ObjFanin0(pObj) ) ) ) lit0 ^= 1; - if ( Vec_BitEntry( vCompl, Gia_ObjId(p1, Gia_ObjFanin1(pObj) ) ) ) lit1 ^= 1; - pObj->Value = Gia_ManHashAnd( pNew, lit0, lit1 ); - - - assert( (pObj->Value>>1) < Vec_IntSize( vVar2Patch) ); - assert( Vec_IntEntry( vVar2Patch, pObj->Value>>1 ) != -1 ); - - Vec_IntSetEntry( vSpec2Patch, Gia_ObjId( p1, pObj ), Vec_IntEntry( vVar2Patch, pObj->Value>>1 ) ); - printf( "spec node %d -> patch node %d\n", Gia_ObjId( p1, pObj ), Vec_IntEntry( vVar2Patch, pObj->Value>>1 ) ); - - Vec_IntSetEntry( vPatch2Impl, pObj->Value >> 1, Vec_IntEntry( vSpec2Impl, Gia_ObjId(p1, pObj) ) ); - } - - - // print - printf("patch 2 impl:\n"); - Vec_IntForEachEntry( vPatch2Impl, id, i ) - { - printf( "\t%d:\t %d\n", i, id ); - } - - // handle co - Gia_ManForEachCo( p2, pObj, i ) - { - int id = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ) >> 1; - } - // TODO: also check spec CO - // Gia_ManForEachCo( p1, pObj, i ) - // { - // int id = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ) >> 1; - // Vec_IntPush( Vec_PtrEntry(vBmiter2Spec, id), Gia_ObjId(p1, pObj) ); - // } - - Gia_ManHashStop( pNew ); - pNew = Gia_ManCleanup( pTemp = pNew ); - Gia_ManStop( pTemp ); - return pNew; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -Gia_Man_t * Gia_ManPatchImpl( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int biNum) -{ - Vec_Int_t * vLits; - Gia_Man_t * pNew, * pTemp; - Gia_Obj_t * pObj, *pObj2; - int i, j, iLit, id, id2; - assert( Gia_ManRegNum(p1) == 0 ); - assert( Gia_ManRegNum(p2) == 0 ); - assert( Gia_ManCiNum(p1) == Gia_ManCiNum(p2) ); - assert( Gia_ManCoNum(p1) == Gia_ManCoNum(p2) ); - if ( fVerbose ) - printf( "Mapping spec to patch with %d inputs, %d outputs, and %d buffers.\n", - Gia_ManCiNum(p1), Gia_ManCoNum(p1), Gia_ManBufNum(p1) ); - pNew = Gia_ManStart( Gia_ManObjNum(p2) ); - pNew->pName = ABC_ALLOC( char, strlen(p1->pName) + 10 ); - sprintf( pNew->pName, "%s_patch", p1->pName ); - Gia_ManHashStart( pNew ); - Gia_ManConst0(p1)->Value = 0; - Gia_ManConst0(p2)->Value = 0; - - - // p1: patch - // p2: impl - - // compute extended box - - Gia_ManStaticFanoutStart( p1 ); - Vec_Ptr_t* vBO = Vec_PtrAlloc(16); - Vec_Ptr_t* vBI = Vec_PtrAlloc(16); - Vec_Ptr_t* vAO = Vec_PtrAlloc(16); - Vec_Ptr_t* vAI = Vec_PtrAlloc(16); - - - - Vec_Ptr_t* vQ = Vec_PtrAlloc(16); - Vec_Int_t* vFlag = Vec_IntAlloc( Gia_ManObjNum(p1) ); - Vec_IntFill( vFlag, Gia_ManObjNum(p1), 0 ); - Vec_IntForEachEntry( vBO_patch, id, i ) - { - if ( Vec_IntEntry( vPatch2Impl, id ) == -1 ) // if no match on the boundary - Vec_PtrPush( vQ, p1->pObjs+id ); - else - Vec_PtrPush( vBO, p1->pObjs+id ); - } - - while( Vec_PtrSize(vQ) > 0 ) - { - pObj = Vec_PtrPop(vQ); - id = Gia_ObjId( p1, pObj ); - - if ( Vec_IntEntry( vFlag, id ) == 1 ) continue; - Vec_IntSetEntry( vFlag, id, 1 ); - - printf("%d\n", id); - - if ( Vec_IntEntry( vPatch2Impl, id ) != -1 ) // matched - { - Vec_PtrPush( vAO, pObj ); - } - else - { - for( j = 0; j < Gia_ObjFanoutNum(p1, pObj); j++ ) - { - Vec_PtrPush( vQ, Gia_ObjFanout(p1, pObj, j) ); - printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanout(p1, pObj, j) ) ); - } - - } - } - - // set flag 2 for FOC - Vec_IntForEachEntry( vBO_patch, id, i ) - { - Vec_PtrPush( vQ, p1->pObjs+id ); - } - while( Vec_PtrSize(vQ) > 0 ) - { - pObj = Vec_PtrPop(vQ); - id = Gia_ObjId( p1, pObj ); - - if ( Vec_IntEntry( vFlag, Gia_ObjId(p1, pObj) ) == 2 ) continue; - Vec_IntSetEntry( vFlag, Gia_ObjId(p1, pObj), 2 ); - - for( j = 0; j < Gia_ObjFanoutNum(p1, pObj); j++ ) - { - Vec_PtrPush( vQ, Gia_ObjFanout(p1, pObj, j) ); - } - } - - // set flag 3 for BO - Vec_IntForEachEntry( vBO_patch, id, i ) - { - Vec_IntSetEntry( vFlag, id, 3 ); - } - - // traverse down from unmated BI and AO - Vec_IntForEachEntry( vBI_patch, id, i ) - { - if ( Vec_IntEntry( vPatch2Impl, id ) == -1 ) // if no match on the boundary - Vec_PtrPush( vQ, p1->pObjs+id ); - else - Vec_PtrPush( vBI, p1->pObjs+id ); - } - Vec_PtrForEachEntry( Gia_Obj_t*, vAO, pObj, i ) - { - Vec_PtrPush( vQ, pObj ); - } - - // traverse down - printf("traverse down\n"); - while ( Vec_PtrSize(vQ) != 0 ) - { - pObj = Vec_PtrPop(vQ); - id = Gia_ObjId( p1, pObj ); - if ( Vec_IntEntry( vFlag, id ) == 4 ) continue; - - printf("%d\n", id); - - if ( Vec_IntEntry( vPatch2Impl, id ) != -1 && Vec_IntEntry( vFlag, id ) < 2 ) // matched - { - Vec_PtrPush( vAI, pObj ); - printf("matched\n"); - } - else if ( Vec_IntEntry( vFlag, id ) < 3 ) - { - if ( Gia_ObjFaninNum(p1, pObj) > 0 ) - { - Vec_PtrPush( vQ, Gia_ObjFanin0(pObj) ); - printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanin0(pObj) ) ); - } - - if ( Gia_ObjFaninNum(p1, pObj) > 1 ) - { - Vec_PtrPush( vQ, Gia_ObjFanin1(pObj) ); - printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanin1(pObj) ) ); - } - } - printf("2impl / flag: %d / %d\n", Vec_IntEntry( vPatch2Impl, id ), Vec_IntEntry( vFlag, id ) ); - - Vec_IntSetEntry( vFlag, id, 4 ); - } - - - // print - printf( "matched BI:"); - Vec_PtrForEachEntry( Gia_Obj_t*, vBI, pObj, i ) printf( " %d(%d)", Gia_ObjId( p1, pObj ), Vec_IntEntry( vPatch2Impl, Gia_ObjId(p1, pObj)) ); - printf("\nAI:"); - Vec_PtrForEachEntry( Gia_Obj_t*, vAI, pObj, i ) printf( " %d(%d)", Gia_ObjId( p1, pObj ), Vec_IntEntry( vPatch2Impl, Gia_ObjId(p1, pObj)) ); - printf("\nmateched BO:"); - Vec_PtrForEachEntry( Gia_Obj_t*, vBO, pObj, i ) printf( " %d(%d)", Gia_ObjId( p1, pObj ), Vec_IntEntry( vPatch2Impl, Gia_ObjId(p1, pObj)) ); - printf("\nAO:"); - Vec_PtrForEachEntry( Gia_Obj_t*, vAO, pObj, i ) printf( " %d(%d)", Gia_ObjId( p1, pObj ), Vec_IntEntry( vPatch2Impl, Gia_ObjId(p1, pObj)) ); - printf("\n"); - - // create patched impl - - // mark fanin cone of Extended Input in impl - Vec_Int_t* vFlag_impl = Vec_IntAlloc( Gia_ManObjNum(p2) ); - Vec_IntFill( vFlag_impl, Gia_ManObjNum(p2), 0 ); - - Vec_PtrForEachEntry( Gia_Obj_t*, vBI, pObj, i ) - { - Vec_PtrPush( vQ, p2->pObjs + Vec_IntEntry( vPatch2Impl, Gia_ObjId(p1, pObj) ) ); - } - Vec_PtrForEachEntry( Gia_Obj_t*, vAI, pObj, i ) - { - Vec_PtrPush( vQ, p2->pObjs + Vec_IntEntry( vPatch2Impl, Gia_ObjId(p1, pObj) ) ); - } - - while ( Vec_PtrSize(vQ) != 0 ) - { - pObj = Vec_PtrPop(vQ); - id = Gia_ObjId( p2, pObj ); - if ( Vec_IntEntry( vFlag_impl, id ) == 1 ) continue; - Vec_IntSetEntry( vFlag_impl, id, 1 ); - - if ( Gia_ObjFaninNum(p2, pObj) > 0 ) Vec_PtrPush( vQ, Gia_ObjFanin0(pObj) ); - if ( Gia_ObjFaninNum(p2, pObj) > 1 ) Vec_PtrPush( vQ, Gia_ObjFanin1(pObj) ); - } - - // add pi - Gia_ManForEachCi( p2, pObj, i ) - { - pObj->Value = Gia_ManCi(p1, i)->Value = Gia_ManAppendCi( pNew ); - } - // add fanin cone of EI in impl - int cnt = 0; - Gia_ManForEachAnd( p2, pObj, i ) - { - if ( Vec_IntEntry( vFlag_impl, Gia_ObjId(p2, pObj) ) == 0 ) continue; - pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - printf( "%d\n", pObj->Value>>1 ); - cnt ++; - } - printf( "%d node added in the fanin cone of EI\n", cnt ); - // set literal and flag of EI in patch - // TODO: input phase - Vec_PtrForEachEntry( Gia_Obj_t*, vBI, pObj, i ) - { - id = Gia_ObjId( p1, pObj ); - pObj -> Value = ( p2 -> pObjs + Vec_IntEntry( vPatch2Impl, id ) ) -> Value; - Vec_IntSetEntry( vFlag, id, 5 ); - } - Vec_PtrForEachEntry( Gia_Obj_t*, vAI, pObj, i ) - { - id = Gia_ObjId( p1, pObj ); - pObj -> Value = ( p2 -> pObjs + Vec_IntEntry( vPatch2Impl, id ) ) -> Value; - Vec_IntSetEntry( vFlag, id, 5 ); - } - // mark fanin cone of EO in patch (to flag 5) - Vec_PtrForEachEntry( Gia_Obj_t*, vBO, pObj, i ) - Vec_PtrPush( vQ, pObj ); - Vec_PtrForEachEntry( Gia_Obj_t*, vAO, pObj, i ) - Vec_PtrPush( vQ, pObj ); - while ( Vec_PtrSize(vQ) != 0 ) - { - pObj = Vec_PtrPop(vQ); - id = Gia_ObjId( p1, pObj ); - if ( Vec_IntEntry( vFlag, id ) >= 5 ) continue; - Vec_IntSetEntry( vFlag, id, 6 ); - - if ( Gia_ObjFaninNum(p1, pObj) > 0 ) Vec_PtrPush( vQ, Gia_ObjFanin0(pObj) ); - if ( Gia_ObjFaninNum(p1, pObj) > 1 ) Vec_PtrPush( vQ, Gia_ObjFanin1(pObj) ); - } - // add fanin cone of EO to EI in patch - cnt = 0; - Gia_ManForEachAnd( p1, pObj, i ) - { - if ( Vec_IntEntry( vFlag, Gia_ObjId(p1, pObj) ) != 6 ) continue; - pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - printf( "%d\n", pObj->Value>>1 ); - cnt ++; - } - printf( "%d node added in the extended boundary\n", cnt ); - - // set literal and flag(1) of EO in impl - Vec_PtrForEachEntry( Gia_Obj_t*, vBO, pObj, i ) - { - id = Gia_ObjId( p1, pObj ); - id2 = Vec_IntEntry( vPatch2Impl, id ); - pObj2 = p2 -> pObjs + id2; - pObj2 -> Value = pObj -> Value; - if ( Vec_BitEntry( vImpl2Spec_phase, id2 ) ) pObj2 -> Value ^= 1; - Vec_IntSetEntry( vFlag_impl, id2, 1 ); - } - Vec_PtrForEachEntry( Gia_Obj_t*, vAO, pObj, i ) - { - id = Gia_ObjId( p1, pObj ); - id2 = Vec_IntEntry( vPatch2Impl, id ); - pObj2 = p2 -> pObjs + id2; - pObj2 -> Value = pObj -> Value; - printf( "id %d matched to id %d in impl, phase %d\n", id, id2, Vec_BitEntry( vImpl2Spec_phase, id2 ) ); - if ( Vec_BitEntry( vImpl2Spec_phase, id2 ) ) pObj2 -> Value ^= 1; - Vec_IntSetEntry( vFlag_impl, id2, 1 ); - } - - // add flag 0 in impl - cnt = 0; - Gia_ManForEachAnd( p2, pObj, i ) - { - if ( Vec_IntEntry( vFlag_impl, Gia_ObjId(p2, pObj) ) != 0 ) continue; - pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - printf( "%d\n", pObj->Value>>1 ); - cnt++; - } - printf( "%d node added in the fanout cone\n", cnt ); - - // handle co - cnt = 0; - Gia_ManForEachCo( p2, pObj, i ) - { - id = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ) >> 1; - printf( "%d\n", id ); - cnt ++; - } - - Gia_ManStaticFanoutStop( p1 ); - Gia_ManHashStop( pNew ); - pNew = Gia_ManCleanup( pTemp = pNew ); - Gia_ManStop( pTemp ); - return pNew; -} - - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/module.make b/src/aig/gia/module.make index 236d43b32..9e5ae3a57 100644 --- a/src/aig/gia/module.make +++ b/src/aig/gia/module.make @@ -109,4 +109,5 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaTsim.c \ src/aig/gia/giaTtopt.cpp \ src/aig/gia/giaUnate.c \ - src/aig/gia/giaUtil.c + src/aig/gia/giaUtil.c \ + src/aig/gia/giaBound.c \ No newline at end of file diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 1a837d030..537e78c24 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -51695,13 +51695,14 @@ usage: ***********************************************************************/ int Abc_CommandAbc9BMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int biNum); + extern Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ); Gia_Man_t * pTemp, * pSecond; char * FileName = NULL; FILE * pFile = NULL; int c, fVerbose = 0; int bi = 0; Extra_UtilGetoptReset(); + // TODO: use a flag to block Bnd_Man while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) { switch ( c ) @@ -51752,7 +51753,7 @@ int Abc_CommandAbc9BMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9BMiter(): Cannot read the file name on the command line.\n" ); return 0; } - pTemp = Gia_ManBoundaryMiter( pAbc->pGia, pSecond, fVerbose, bi); + pTemp = Gia_ManBoundaryMiter( pAbc->pGia, pSecond, fVerbose ); Gia_ManStop( pSecond ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; @@ -51852,7 +51853,7 @@ int Abc_CommandAbc9RecoverBoundary( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_Obj_t* pObj; Gia_Man_t * pSpec = NULL; char ** pArgvNew; - int i, nArgcNew, nPo; + int nArgcNew, nPo; int nBInput = -1; char *FileName; Extra_UtilGetoptReset(); @@ -51955,29 +51956,34 @@ usage: return 1; } +extern Bnd_Man_t* pBnd; int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Gia_ManPatch( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int biNum); - extern Gia_Man_t * Gia_ManPatchImpl( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose, int biNum); - Gia_Man_t * pTemp, * pSecond, *pImpl, *pPatched; + extern Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); + extern void Cec4_ManSetParams( Cec_ParFra_t * pPars ); + extern Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ); + Gia_Man_t *pImpl, *pImpl_out = 0, *pSpec_out = 0, *pMiter, *pPatch, *pPatched, *pTemp, *pBmiter;; char * FileName = NULL; - char * FileName2 = NULL; FILE * pFile = NULL; - int c, fVerbose = 0; - int bi = 0; + int c, fVerbose = 0, success = 1; + + // params + Gps_Par_t Pars, * pPars = &Pars; + memset( pPars, 0, sizeof(Gps_Par_t) ); + Cec_ParCec_t ParsCec, *pParsCec = &ParsCec; + Cec_ManCecSetDefaultParams( pParsCec ); + Cec_ParFra_t ParsFra, *pParsFra = &ParsFra; + Cec4_ManSetParams( pParsFra ); + pParsFra -> fBMiterInfo = 1; + + // TODO: save return value and return at the end of the function + + // parse options Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { - case 'I': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); - goto usage; - } - bi = atoi(argv[globalUtilOptind++]); - break; case 'v': fVerbose ^= 1; break; @@ -51999,7 +52005,10 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } - // get the input file name + // params + + + // read impl FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { @@ -52010,44 +52019,103 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } fclose( pFile ); - - // get the input file name 2 - FileName2 = argv[globalUtilOptind+1]; - if ( (pFile = fopen( FileName2, "r" )) == NULL ) - { - Abc_Print( -1, "Cannot open input file \"%s\". ", FileName2 ); - if ( (FileName2 = Extra_FileGetSimilarName( FileName2, ".aig", ".blif", ".pla", ".eqn", ".bench" )) ) - Abc_Print( 1, "Did you mean \"%s\"?", FileName2 ); - Abc_Print( 1, "\n" ); - return 1; - } - fclose( pFile ); - - // map spec to patch - pSecond = Gia_AigerRead( FileName, 0, 1, 0 ); - if ( pSecond == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc9StrEco(): Cannot read the file name on the command line.\n" ); - return 0; - } - pTemp = Gia_ManPatch( pAbc->pGia, pSecond, fVerbose, bi); - // Gia_ManStop( pSecond ); - // Abc_FrameUpdateGia( pAbc, pTemp ); - // return 0; - - // generated patched impl - pImpl = Gia_AigerRead( FileName2, 0, 0, 0 ); + pImpl = Gia_AigerRead( FileName, 0, 0, 0 ); if ( pImpl == NULL ) { Abc_Print( -1, "Abc_CommandAbc9StrEco(): Cannot read the file name on the command line.\n" ); return 0; } - pPatched = Gia_ManPatchImpl( pTemp, pImpl, fVerbose, bi); - Gia_ManStop( pSecond ); + // read patch + FileName = argv[globalUtilOptind+1]; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", ".blif", ".pla", ".eqn", ".bench" )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pPatch = Gia_AigerRead( FileName, 0, 1, 0 ); + if ( pPatch == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9StrEco(): Cannot read the file name on the command line.\n" ); + return 0; + } + + + // verify if spec eq impl + pMiter = Gia_ManMiter( pAbc->pGia, pImpl, 0, 1, 0, 0, 0 ); + assert( Cec_ManVerify( pMiter, pParsCec ) ); + Gia_ManStop(pMiter); + + // start boundary manager + pBnd = Bnd_ManStart( pAbc->pGia, pImpl ); + + // check boundary + if ( 0 == Bnd_ManCheckBound( pAbc -> pGia ) ) + { + Abc_Print( -1, "Abc_CommandAbc9StrEco(): The given boundary is invalid.\n" ); + success = 0; + } + + if ( success ) + { + // create bmiter, run fraig + pBmiter = Gia_ManBoundaryMiter( pAbc -> pGia, pImpl, 0 ); + pTemp = Cec4_ManSimulateTest( pBmiter, pParsFra ); + Gia_ManStop(pBmiter); + Gia_ManStop(pTemp); + + // find + Bnd_ManFindBound( pAbc -> pGia ); + + // create spec_out and + pSpec_out = Bnd_ManGenSpecOut( pAbc -> pGia ); + if ( !pSpec_out ) success = 0; + pImpl_out = Bnd_ManGenImplOut( pImpl ); + if ( !pImpl_out ) success = 0; + + Gia_AigerWrite( pSpec_out, "spec_out.aig", 0, 0, 0 ); + Gia_AigerWrite( pImpl_out, "impl_out.aig", 0, 0, 0 ); + Gia_ManPrintStats( pSpec_out, pPars ); + Gia_ManPrintStats( pImpl_out, pPars ); + + } + + if ( success ) + { + + // check if spec_out and imnpl_out are equivalent + printf("Checking the equivalence of spec_out and impl_out\n"); + pMiter = Gia_ManMiter( pSpec_out, pImpl_out, 0, 1, 0, 0, 0 ); + Bnd_ManSetEqOut( Cec_ManVerify( pMiter, pParsCec ) ); + Gia_ManStop( pMiter ); + + // generate patched + pPatched = Bnd_ManGenPatched( pImpl_out, pAbc->pGia, pPatch ); + + // check if patched is equiv to patch + printf("Checking the equivalence of patch and patched\n"); + pMiter = Gia_ManMiter( pPatch, pPatched, 0, 1, 0, 0, 0 ); + Bnd_ManSetEqRes( Cec_ManVerify( pMiter, pParsCec ) ); + Gia_ManStop( pMiter ); + + } + + Bnd_ManPrintStats(); + Gia_ManStop( pImpl ); - Gia_ManStop( pTemp ); - Abc_FrameUpdateGia( pAbc, pPatched ); + Gia_ManStop( pPatch ); + if ( pSpec_out ) Gia_ManStop( pSpec_out ); + if ( pImpl_out ) Gia_ManStop( pImpl_out ); + if ( success ) + { + Abc_FrameUpdateGia( pAbc, pPatched ); + } + Bnd_ManStop(); + return 0; usage: diff --git a/src/misc/vec/vecBit.h b/src/misc/vec/vecBit.h index e41d95aa9..9b0af9d94 100644 --- a/src/misc/vec/vecBit.h +++ b/src/misc/vec/vecBit.h @@ -626,6 +626,27 @@ static inline void Vec_BitReset( Vec_Bit_t * p ) p->pArray[i] = 0; } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_BitPrint( Vec_Bit_t * p ) +{ + int i, Entry; + printf( "Vector has %d entries: {", Vec_BitSize(p) ); + Vec_BitForEachEntry( p, Entry, i ) + printf( " %d", Entry ); + printf( " }\n" ); +} + ABC_NAMESPACE_HEADER_END #endif diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 0659b3f60..b198c7ffe 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -143,14 +143,6 @@ static inline int Cec4_ObjSatId( Gia_Man_t * p, Gia_Obj_t * pObj ) static inline int Cec4_ObjSetSatId( Gia_Man_t * p, Gia_Obj_t * pObj, int Num ) { assert(Cec4_ObjSatId(p, pObj) == -1); Gia_ObjSetCopy2Array(p, Gia_ObjId(p, pObj), Num); Vec_IntPush(&p->vSuppVars, Gia_ObjId(p, pObj)); if ( Gia_ObjIsCi(pObj) ) Vec_IntPushTwo(&p->vCopiesTwo, Gia_ObjId(p, pObj), Num); assert(Vec_IntSize(&p->vVarMap) == Num); Vec_IntPush(&p->vVarMap, Gia_ObjId(p, pObj)); return Num; } static inline void Cec4_ObjCleanSatId( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert(Cec4_ObjSatId(p, pObj) != -1); Gia_ObjSetCopy2Array(p, Gia_ObjId(p, pObj), -1); } - -extern Vec_Int_t* vMarkBmiter; -extern Vec_Int_t* vIdBI; -extern Vec_Int_t* vIdBO; -extern Vec_Ptr_t* vBmiter2Spec; -extern Vec_Ptr_t* vBmiter2Impl; - - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -1791,9 +1783,9 @@ void Gia_ManRemoveWrongChoices( Gia_Man_t * p ) //Abc_Print( 1, "Removed %d wrong choices.\n", Counter ); } -extern Vec_Bit_t* vImpl2Spec_phase; int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** ppNew, int fSimOnly ) { + Cec4_Man_t * pMan = Cec4_ManCreate( p, pPars ); Gia_Obj_t * pObj, * pRepr; int i, fSimulate = 1; @@ -1894,25 +1886,11 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p if ( Abc_Lit2Var(pObj->Value) == Abc_Lit2Var(pRepr->Value) ) { - if ( pPars->fBMiterInfo ) + if ( pPars->fBMiterInfo ) { - int eId, j; - Vec_Int_t *vIds_spec_repr, *vIds_impl_repr, *vIds_spec_obj, *vIds_impl_obj; - vIds_spec_repr = Vec_PtrEntry( vBmiter2Spec, id_repr ); - vIds_impl_repr = Vec_PtrEntry( vBmiter2Impl, id_repr ); - vIds_spec_obj = Vec_PtrEntry( vBmiter2Spec, id_obj ); - vIds_impl_obj = Vec_PtrEntry( vBmiter2Impl, id_obj ); - Vec_IntForEachEntry( vIds_spec_obj, eId, j) - { - Vec_IntPush(vIds_spec_repr, eId); - } - Vec_IntForEachEntry( vIds_impl_obj, eId, j) - { - Vec_IntPush(vIds_impl_repr, eId); - } - Vec_IntClear(vIds_spec_obj); - Vec_IntClear(vIds_impl_obj); + Bnd_ManMerge( id_repr, id_obj, pObj->fPhase ^ pRepr->fPhase ); } + assert( (pObj->Value ^ pRepr->Value) == (pObj->fPhase ^ pRepr->fPhase) ); Gia_ObjSetProved( p, i ); if ( Gia_ObjId(p, pRepr) == 0 ) @@ -1923,73 +1901,8 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p { if (pPars->fBMiterInfo){ - int eId, j; - Vec_Int_t *vIds_spec_repr, *vIds_impl_repr, *vIds_spec_obj, *vIds_impl_obj; - vIds_spec_repr = Vec_PtrEntry( vBmiter2Spec, id_repr ); - vIds_impl_repr = Vec_PtrEntry( vBmiter2Impl, id_repr ); - vIds_spec_obj = Vec_PtrEntry( vBmiter2Spec, id_obj ); - vIds_impl_obj = Vec_PtrEntry( vBmiter2Impl, id_obj ); - - Vec_IntForEachEntry( vIds_spec_obj, eId, j) - { - Vec_IntPush(vIds_spec_repr, eId); - } - Vec_IntForEachEntry( vIds_impl_obj, eId, j) - { - Vec_IntPush(vIds_impl_repr, eId); - } - - // handle phase before cleaning - printf( "proven %d merged into %d (phase : %d)\n", Gia_ObjId(p, pObj), Gia_ObjId(p,pRepr), pObj->fPhase ^ pRepr -> fPhase ); - if ( Vec_IntSize(vIds_spec_repr) == 0 ) // no match - { - if ( pObj->fPhase ^ pRepr -> fPhase ) - { - Vec_IntForEachEntry( vIds_impl_obj, eId, j ) - { - Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); - printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); - } - } - } - else if ( Vec_IntSize( vIds_spec_repr ) == Vec_IntSize( vIds_spec_obj) && Vec_IntSize( vIds_impl_obj ) == 0 ) // new match - { - if ( pObj->fPhase ^ pRepr -> fPhase ) - { - Vec_IntForEachEntry( vIds_impl_repr, eId, j ) - { - Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); - printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); - } - printf("new match flip\n"); - } - } - else if ( Vec_IntSize( vIds_spec_repr ) > 0 && Vec_IntSize( vIds_impl_obj ) > 0 ) // matched, merge impl - { - if ( ( pObj->fPhase ^ pRepr -> fPhase) ^ ( Vec_BitEntry( vImpl2Spec_phase, Vec_IntEntry(vIds_impl_repr, 0)) ^ Vec_BitEntry( vImpl2Spec_phase, Vec_IntEntry(vIds_impl_obj, 0)) ) ) - { - if ( Vec_IntSize( vIds_spec_repr ) == Vec_IntSize( vIds_spec_obj) ) // unmatched repr, matched obj, set repr bits - { - Vec_IntForEachEntry( vIds_impl_repr, eId, j ) - { - if ( j >= Vec_IntSize( vIds_impl_repr)-Vec_IntSize(vIds_impl_obj) ) break; - Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); - printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); - } - } - else // set obj bits - { - Vec_IntForEachEntry( vIds_impl_obj, eId, j ) - { - Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); - printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); - } - } - } - } - - Vec_IntClear(vIds_spec_obj); - Vec_IntClear(vIds_impl_obj); + Bnd_ManMerge( id_repr, id_obj, pObj->fPhase ^ pRepr->fPhase ); + // printf( "proven %d merged into %d (phase : %d)\n", Gia_ObjId(p, pObj), Gia_ObjId(p,pRepr), pObj->fPhase ^ pRepr -> fPhase ); } pObj->Value = Abc_LitNotCond( pRepr->Value, pObj->fPhase ^ pRepr->fPhase ); @@ -2001,20 +1914,8 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p if ( pPars->fBMiterInfo ) { // print - Vec_Int_t* vIds_spec, *vIds_impl; - int k, id; - for( int j=0; j < Vec_PtrSize(vBmiter2Spec); j++ ) - { - printf("node %d: ", j); - vIds_spec = Vec_PtrEntry( vBmiter2Spec, j); - vIds_impl = Vec_PtrEntry( vBmiter2Impl, j); - Vec_IntForEachEntry(vIds_spec, id, k) - printf("%d ", id); - printf("| "); - Vec_IntForEachEntry(vIds_impl, id, k) - printf("%d ", id); - printf("\n"); - } + Bnd_ManFinalizeMappings(); + // Bnd_ManPrintMappings(); } if ( p->iPatsPi > 0 ) @@ -2066,10 +1967,6 @@ Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ) Gia_Man_t * pNew = NULL; Cec4_ManPerformSweeping( p, pPars, &pNew, 0 ); - // TODO - if (pPars -> fBMiterInfo){ - } - return pNew; } void Cec4_ManSimulateTest2( Gia_Man_t * p, int nConfs, int fVerbose ) From 9bec2afd601082757c87229beb26ed320922f5ce Mon Sep 17 00:00:00 2001 From: aletempiac Date: Fri, 1 Mar 2024 10:04:48 +0100 Subject: [PATCH 102/151] Removing -z flag to execute delay-driven ACD --- src/base/abci/abc.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index f79e8de77..a14a3a8bc 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -19447,7 +19447,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) If_ManSetDefaultPars( pPars ); pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYZDEWSJqaflepmrsdbgxyzuojiktncvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYZDEWSJqaflepmrsdbgxyuojiktncvh" ) ) != EOF ) { switch ( c ) { @@ -19570,6 +19570,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } pPars->nLutDecSize = atoi(argv[globalUtilOptind]); + pPars->fUserLutDec = 1; globalUtilOptind++; if ( pPars->nLutDecSize < 3 || pPars->nLutDecSize > 6 ) goto usage; @@ -19678,9 +19679,6 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'y': pPars->fUserRecLib ^= 1; break; - case 'z': - pPars->fUserLutDec ^= 1; - break; case 'u': pPars->fUserSesLib ^= 1; break; @@ -20008,7 +20006,7 @@ usage: sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: if [-KCFAGRNTXYZ num] [-DEW float] [-S str] [-qarlepmsdbgxyzuojiktncvh]\n" ); + Abc_Print( -2, "usage: if [-KCFAGRNTXYZ num] [-DEW float] [-S str] [-qarlepmsdbgxyuojiktncvh]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -20020,7 +20018,7 @@ usage: Abc_Print( -2, "\t-T num : the type of LUT structures [default = any]\n" ); Abc_Print( -2, "\t-X num : delay of AND-gate in LUT library units [default = %d]\n", pPars->nAndDelay ); Abc_Print( -2, "\t-Y num : area of AND-gate in LUT library units [default = %d]\n", pPars->nAndArea ); - Abc_Print( -2, "\t-Z num : the number of LUT inputs for LUT decomposition [default = %d]\n", pPars->nLutDecSize ); + Abc_Print( -2, "\t-Z num : the number of LUT inputs for delay-driven LUT decomposition [default = not used]\n" ); Abc_Print( -2, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); Abc_Print( -2, "\t-W float : sets wire delay between adjects LUTs [default = %f]\n", pPars->WireDelay ); @@ -20039,7 +20037,6 @@ usage: Abc_Print( -2, "\t-g : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" ); Abc_Print( -2, "\t-x : toggles delay optimization by DSD balancing [default = %s]\n", pPars->fDsdBalance? "yes": "no" ); Abc_Print( -2, "\t-y : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" ); - Abc_Print( -2, "\t-z : toggles delay optimization with LUT decomposition [default = %s]\n", pPars->fUserLutDec? "yes": "no" ); Abc_Print( -2, "\t-u : toggles delay optimization with SAT-based library [default = %s]\n", pPars->fUserSesLib? "yes": "no" ); Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" ); Abc_Print( -2, "\t-j : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" ); From cd407e2ba3bc0455501e4586a21a1acba1f0a3d6 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Fri, 1 Mar 2024 10:05:30 +0100 Subject: [PATCH 103/151] Activate use_first flag in acd_decompose --- src/map/if/acd/ac_wrapper.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index 7551335f8..e47847f10 100644 --- a/src/map/if/acd/ac_wrapper.cpp +++ b/src/map/if/acd/ac_wrapper.cpp @@ -33,7 +33,8 @@ int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, { ac_decomposition_params ps; ps.lut_size = lutSize; - ps.try_no_late_arrival = static_cast( try_no_late_arrival ); /* TODO: additional tests */ + ps.use_first = false; + ps.try_no_late_arrival = static_cast( try_no_late_arrival ); ac_decomposition_stats st; ac_decomposition_impl acd( nVars, ps, &st ); @@ -76,6 +77,7 @@ int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, { ac_decomposition_params ps; ps.lut_size = lutSize; + ps.use_first = true; ac_decomposition_stats st; ac_decomposition_impl acd( nVars, ps, &st ); From f5f4dca013bdcf62282d88ac9d7fa2238a9c0dcd Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Sat, 2 Mar 2024 21:08:10 +0800 Subject: [PATCH 104/151] clean up --- src/aig/gia/giaBound.c | 214 ++++++++++++++++++++--------------------- src/aig/gia/giaDup.c | 61 ------------ src/base/abci/abc.c | 180 ++++++++-------------------------- 3 files changed, 144 insertions(+), 311 deletions(-) diff --git a/src/aig/gia/giaBound.c b/src/aig/gia/giaBound.c index 63b2c389b..9fad955d7 100644 --- a/src/aig/gia/giaBound.c +++ b/src/aig/gia/giaBound.c @@ -34,7 +34,9 @@ struct Bnd_Man_t_ int combLoop_impl; int eq_out; int eq_res; - int nChoice; + int nChoice_spec; + int nChoice_impl; + int feedthrough; Vec_Ptr_t* vBmiter2Spec; Vec_Ptr_t* vBmiter2Impl; @@ -51,6 +53,7 @@ struct Bnd_Man_t_ Vec_Bit_t* vEO_phase; Vec_Int_t* vSpec2Impl_diff; + Vec_Int_t* vImpl2Spec_diff; // note that this include bufs, which should merge into their fanins }; @@ -115,11 +118,16 @@ Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl ) p -> eq_out = 0; p -> eq_res = 0; - p -> nChoice = 0; + p -> nChoice_spec = 0; + p -> nChoice_impl = 0; + p -> feedthrough = 0; p -> vSpec2Impl_diff = Vec_IntAlloc( Gia_ManObjNum(pSpec) ); Vec_IntFill( p -> vSpec2Impl_diff, Gia_ManObjNum(pSpec), 0 ); + p -> vImpl2Spec_diff = Vec_IntAlloc( Gia_ManObjNum(pImpl) ); + Vec_IntFill( p -> vImpl2Spec_diff, Gia_ManObjNum(pImpl), 0 ); + return p; } @@ -153,6 +161,7 @@ void Bnd_ManStop() Vec_BitFree( pBnd->vEO_phase ); Vec_IntFree( pBnd-> vSpec2Impl_diff ); + Vec_IntFree( pBnd-> vImpl2Spec_diff ); ABC_FREE( pBnd ); } @@ -208,56 +217,6 @@ void Bnd_ManMerge( int id_repr, int id_obj, int phaseDiff ) } } - // handle impl2spec phase - /* - if ( Vec_IntSize(vIds_spec_repr) == 0 ) // no match - { - if ( pObj->fPhase ^ pRepr -> fPhase ) - { - Vec_IntForEachEntry( vIds_impl_obj, eId, j ) - { - Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); - printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); - } - } - } - else if ( Vec_IntSize( vIds_spec_repr ) == Vec_IntSize( vIds_spec_obj) && Vec_IntSize( vIds_impl_obj ) == 0 ) // new match - { - if ( pObj->fPhase ^ pRepr -> fPhase ) - { - Vec_IntForEachEntry( vIds_impl_repr, eId, j ) - { - Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); - printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); - } - printf("new match flip\n"); - } - } - else if ( Vec_IntSize( vIds_spec_repr ) > 0 && Vec_IntSize( vIds_impl_obj ) > 0 ) // matched, merge impl - { - if ( ( pObj->fPhase ^ pRepr -> fPhase) ^ ( Vec_BitEntry( vImpl2Spec_phase, Vec_IntEntry(vIds_impl_repr, 0)) ^ Vec_BitEntry( vImpl2Spec_phase, Vec_IntEntry(vIds_impl_obj, 0)) ) ) - { - if ( Vec_IntSize( vIds_spec_repr ) == Vec_IntSize( vIds_spec_obj) ) // unmatched repr, matched obj, set repr bits - { - Vec_IntForEachEntry( vIds_impl_repr, eId, j ) - { - if ( j >= Vec_IntSize( vIds_impl_repr)-Vec_IntSize(vIds_impl_obj) ) break; - Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); - printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); - } - } - else // set obj bits - { - Vec_IntForEachEntry( vIds_impl_obj, eId, j ) - { - Vec_BitSetEntry( vImpl2Spec_phase, eId, !Vec_BitEntry(vImpl2Spec_phase, eId) ); - printf( "impl id %d's phase set to %d\n", eId, Vec_BitEntry(vImpl2Spec_phase, eId) ); - } - } - } - } - */ - Vec_IntClear(vIds_spec_obj); Vec_IntClear(vIds_impl_obj); @@ -292,6 +251,12 @@ void Bnd_ManFinalizeMappings() Vec_IntSetEntry( pBnd->vSpec2Impl_diff, id, Vec_IntSize(vImpl)-1 ); } + Vec_IntForEachEntry( vImpl, id, j ) + { + // record the number of different choice of vEI_impl, vEO_impl + Vec_IntSetEntry( pBnd->vImpl2Spec_diff, id, Vec_IntSize(vSpec)-1 ); + } + } @@ -304,10 +269,6 @@ void Bnd_ManFinalizeMappings() { pBnd->nMerged_impl += Vec_IntSize(vImpl) - 1; } - - - - } @@ -336,15 +297,14 @@ void Bnd_ManPrintMappings() void Bnd_ManPrintBound() { - printf("%d nodes merged in spec\n", pBnd ->nMerged_spec - Vec_IntSize(pBnd->vBI) - Vec_IntSize(pBnd->vBO) ); - printf("%d nodes merged in impl\n", pBnd ->nMerged_impl ); - + // printf("%d nodes merged in spec\n", pBnd ->nMerged_spec - Vec_IntSize(pBnd->vBI) - Vec_IntSize(pBnd->vBO) ); + // printf("%d nodes merged in impl\n", pBnd ->nMerged_impl ); printf("BI spec:"); Vec_IntPrint(pBnd -> vBI); printf("BO spec:"); Vec_IntPrint(pBnd -> vBO); - printf("\nEI spec:"); Vec_IntPrint(pBnd -> vEI_spec); + printf("EI spec:"); Vec_IntPrint(pBnd -> vEI_spec); printf("EI impl:"); Vec_IntPrint(pBnd -> vEI_impl); printf("EI phase:"); Vec_BitPrint(pBnd -> vEI_phase); - printf("\nEO spec:"); Vec_IntPrint(pBnd -> vEO_spec); + printf("EO spec:"); Vec_IntPrint(pBnd -> vEO_spec); printf("EO impl:"); Vec_IntPrint(pBnd -> vEO_impl); printf("EO phase:"); Vec_BitPrint(pBnd -> vEO_phase); } @@ -353,30 +313,54 @@ void Bnd_ManPrintStats() { Bnd_Man_t* p = pBnd; + + printf("\nSTATS\n"); + + int warning = 0; + if ( p->nChoice_spec > 0 ) + { + warning = 1; + printf("WARNING: multiple equiv nodes on the boundary of spec\n"); + } + if ( p->nChoice_impl > 0 ) + { + warning = 1; + printf("WARNING: multiple equiv nodes on the boundary of impl\n"); + } + if ( p->feedthrough ) + { + warning = 1; + printf("WARNING: feedthrough inside patch\n"); + } + + printf("The outsides of spec and impl are %sEQ.\n", p->eq_out ? "" : "NOT " ); + printf("The patched impl and patch are %sEQ.\n", p->eq_res ? "" : "NOT " ); + // #internal // nBI, nBO // nBI_miss, nBO_miss // nAI, nAO, nExtra // #spec, #impl, #patched - // combLoop_spec, combLoop_impl - - // eq_out, eq_res // status - // #different choice of impl on boundary + // warning (may be neq) + // eq_out, eq_res printf("\nRESULT\n"); - printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", p->nInternal, p->nBI, p->nBO, p->nBI_miss, p->nBO_miss, Vec_IntSize(p->vEI_spec), Vec_IntSize(p->vEO_spec), p->nExtra, p->nNode_spec, p->nNode_impl, p->nNode_patched, p->combLoop_spec, p->combLoop_impl, - p->eq_out, p->eq_res, p->status, - p->nChoice + p->nChoice_impl, + p->nChoice_spec, + p->feedthrough, + warning, + p->eq_out, p->eq_res ); } @@ -610,7 +594,7 @@ void Bnd_ManFindBound( Gia_Man_t * p ) Vec_IntPush(vEO_spec, id); } } - printf("%d BO doesn't match\n", Vec_PtrSize(vQ) ); + printf("%d BO doesn't match. ", Vec_PtrSize(vQ) ); pBnd -> nBO_miss = Vec_PtrSize(vQ); int cnt_extra = - Vec_PtrSize(vQ); @@ -682,7 +666,7 @@ void Bnd_ManFindBound( Gia_Man_t * p ) Vec_IntPush(vEI_spec, id); } } - printf("%d BI doesn't match\n", Vec_PtrSize(vQ) ); + printf("%d BI doesn't match. ", Vec_PtrSize(vQ) ); pBnd -> nBI_miss = Vec_PtrSize(vQ); cnt_extra -= Vec_PtrSize(vQ); @@ -742,16 +726,16 @@ void Bnd_ManFindBound( Gia_Man_t * p ) } - // count number of choice of boundary in impl + // count number of choice of boundary Vec_IntForEachEntry( vEI_spec, id, i ) - { - pBnd -> nChoice += Vec_IntEntry( pBnd -> vSpec2Impl_diff, id ); - } + pBnd -> nChoice_impl += Vec_IntEntry( pBnd -> vSpec2Impl_diff, id ); Vec_IntForEachEntry( vEO_spec, id, i ) - { - pBnd -> nChoice += Vec_IntEntry( pBnd -> vSpec2Impl_diff, id ); - } - + pBnd -> nChoice_impl += Vec_IntEntry( pBnd -> vSpec2Impl_diff, id ); + Vec_IntForEachEntry( vEI_impl, id, i ) + pBnd -> nChoice_spec += Vec_IntEntry( pBnd -> vImpl2Spec_diff, id ); + Vec_IntForEachEntry( vEO_impl, id, i ) + pBnd -> nChoice_spec += Vec_IntEntry( pBnd -> vImpl2Spec_diff, id ); + pBnd -> nChoice_spec -= ( pBnd->nBI + pBnd ->nBO - pBnd->nBI_miss - pBnd->nBO_miss); // print pBnd -> status = 1; @@ -790,6 +774,7 @@ Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; + Vec_Int_t * vValue; int i, id, lit; // check if the boundary has loop (EO cannot be in the TFC of EI ) @@ -809,6 +794,9 @@ Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec Gia_ManConst0(p) -> Value = 0; Gia_ManCleanValue(p); + // record the original value for eo + vValue = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( vValue, Gia_ManObjNum(p), -1 ); // create ci for ci and eo Gia_ManForEachCi( p, pObj, i ) @@ -817,6 +805,10 @@ Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec } Vec_IntForEachEntry( vEO, id, i ) { + if( Gia_ManObj(p, id) -> Value != 0 ) + { + Vec_IntSetEntry( vValue, id, Gia_ManObj(p, id) -> Value ); + } Gia_ManObj( p, id ) -> Value = Gia_ManAppendCi(pNew); if ( vEO_phase && Vec_BitEntry( vEO_phase, i ) ) { @@ -824,7 +816,14 @@ Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec } } - // TODO: consider where EI and EO share the same node + + // record where EI and EO share the same node + // this may cause non-equivalent + Vec_IntForEachEntry( vEI, id, i ) + { + if ( Gia_ManObj(p, id) -> Value != 0 ) + pBnd -> feedthrough = 1; + } // add aig nodes Gia_ManForEachAnd(p, pObj, i) @@ -840,13 +839,26 @@ Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec } Vec_IntForEachEntry( vEI, id, i ) { - lit = Gia_ManObj(p, id)->Value; - // lit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pObj = Gia_ManObj(p, id); + // lit = Gia_ManObj(p, id)->Value; + if ( Gia_ObjIsAnd(pObj) ) lit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + { + assert(Gia_ObjIsCi(pObj) || Gia_ObjIsConst0(pObj)); + if ( Vec_IntEntry(vValue, id) != -1 ) + { + lit = Vec_IntEntry( vValue, id ); // EI at PI and EI merged with EO + } + else { + lit = pObj -> Value; // EI at PI + } + } if ( vEI_phase && Vec_BitEntry( vEI_phase, i ) ) lit ^= 1; Gia_ManAppendCo( pNew, lit ); } // clean up + Vec_IntFree( vValue ); Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); @@ -872,7 +884,12 @@ Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t* p ) void Bnd_AddNodeRec( Gia_Man_t *p, Gia_Man_t *pNew, Gia_Obj_t *pObj ) { // TODO does this mean constant zero node? - if ( pObj -> Value != 0 || Gia_ObjIsConst0(pObj) ) return; + if ( pObj -> Value != 0 ) return; + if ( Gia_ObjIsConst0(pObj) ) + { + printf( "contant zero encountered\n"); + return; + } for( int i = 0; i < Gia_ObjFaninNum(p, pObj); i++ ) { @@ -902,7 +919,6 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat int i, id, cnt; Vec_Int_t *vBI_patch, *vBO_patch; - printf("Generating patched implementation\n"); pBnd -> nNode_patch = Gia_ManAndNotBufNum( pPatch ); pNew = Gia_ManStart( Gia_ManObjNum(pOut) + Gia_ManObjNum( pSpec ) + Gia_ManObjNum(pPatch) ); @@ -932,7 +948,6 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat } assert( Vec_IntSize( vBI_patch ) == Vec_IntSize(pBnd->vBI) ); assert( Vec_IntSize( vBO_patch ) == Vec_IntSize(pBnd->vBO) ); - assert( Bnd_ManCheckBound(pPatch) != 0 ); // add Impl (real) PI @@ -943,7 +958,7 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat } // add Impl EI to CI - printf("adding EI to CI in Impl\n"); + // printf("adding EI to CI in Impl\n"); for ( i = 0; i < Vec_IntSize( pBnd -> vEI_spec ); i++ ) { pObj = Gia_ManCo(pOut, i + Gia_ManCoNum(pSpec) ); @@ -951,12 +966,10 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat // set Spec EI Gia_ManObj( pSpec, Vec_IntEntry(pBnd -> vEI_spec, i) ) -> Value = pObj -> Value; - printf("%d ", pObj->Value); } - printf("\n"); // add Spec BI to EI - printf("adding BI to EI in Spec\n"); + // printf("adding BI to EI in Spec\n"); Vec_IntForEachEntry( pBnd -> vBI, id, i ) { pObj = Gia_ManObj( pSpec, id ); @@ -964,23 +977,10 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat // set patch bi Gia_ManObj( pPatch, Vec_IntEntry( vBI_patch, i) ) -> Value = pObj -> Value; - printf("%d ", pObj->Value); } - printf("\n"); - - // check - // cnt = 0; - // Gia_ManForEachBuf( pPatch, pObj, i ) - // { - // if ( cnt < pBnd -> nBI ) - // { - // assert(pObj -> Value != 0); - // } - // cnt++; - // } // add Patch BO to BI - printf("adding BO to BI in Patch\n"); + // printf("adding BO to BI in Patch\n"); Vec_IntForEachEntry( vBO_patch, id, i ) { pObj = Gia_ManObj( pPatch, id ); @@ -988,12 +988,10 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat // set spec bo Gia_ManObj( pSpec, Vec_IntEntry( pBnd -> vBO, i) ) -> Value = pObj -> Value; - printf("%d ", pObj->Value); } - printf("\n"); // add Spec EO to BO - printf("adding EO to BO in Spec\n"); + // printf("adding EO to BO in Spec\n"); Vec_IntForEachEntry( pBnd -> vEO_spec, id, i ) { pObj = Gia_ManObj( pSpec, id ); @@ -1001,20 +999,16 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat // set impl EO (PI) Gia_ManCi( pOut, i + Gia_ManCiNum(pSpec) ) -> Value = pObj -> Value; - printf("%d ", pObj->Value); } - printf("\n"); // add Impl (real) PO to EO - printf("adding CO to EO in Impl\n"); + // printf("adding CO to EO in Impl\n"); for ( i = 0; i < Gia_ManCoNum(pSpec); i++ ) { pObj = Gia_ManCo( pOut, i ); Bnd_AddNodeRec( pOut, pNew, pObj ); Gia_ManAppendCo( pNew, pObj->Value ); - printf("%d ", pObj->Value); } - printf("\n"); // clean up diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index bdcbb970e..61acab995 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -5817,67 +5817,6 @@ Gia_Man_t * Gia_ManImplFromBMiter( Gia_Man_t * p, int nPo, int nBInput ) return pNew; } -/**Function************************************************************* - - Synopsis [Duplicates AIG while putting objects in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Gia_ManMiterFromBMiter( Gia_Man_t * p, int nPo ) -{ - Gia_Man_t * pNew, *pTemp; - Gia_Obj_t * pObj, *pObj2; - int i, iXor, iPo, i1, i2; - pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Abc_UtilStrsav( "miter" ); - Gia_ManFillValue( p ); - Gia_ManConst0(p)->Value = 0; - - // create primary inputs - Gia_ManForEachCi( p, pObj, i ) - if ( !~pObj->Value ) - pObj->Value = Gia_ManAppendCi(pNew); - - Gia_ManForEachCo( p, pObj, i ) - { - if ( i == nPo ) - { - break; - } - else - { - pObj2 = Gia_ManCo( p, i + nPo ); - - i1 = Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); - i2 = Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj2) ); - - iXor = Gia_ManAppendXor2( pNew, Gia_ObjFaninC0(pObj) ? i1+1 : i1 , Gia_ObjFaninC0(pObj2 ) ? i2+1 : i2 ); - if ( i > 0 ) - { - iPo = Gia_ManAppendOr2( pNew, iPo, iXor ); - } - else - { - iPo = iXor; - } - } - } - Gia_ManAppendCo( pNew, iPo ); - - - pNew = Gia_ManCleanup( pTemp = pNew ); - Gia_ManStop( pTemp ); - pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); - Gia_ManStop( pTemp ); - - return pNew; -} - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 537e78c24..ed930636b 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -597,7 +597,6 @@ static int Abc_CommandAbc9ProdAdd ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9AddFlop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9BMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenHie ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc9RecoverBoundary ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9StrEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1378,7 +1377,6 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&addflop", Abc_CommandAbc9AddFlop, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmiter", Abc_CommandAbc9BMiter, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&gen_hie", Abc_CommandAbc9GenHie, 0 ); - Cmd_CommandAdd( pAbc, "ABC9", "&rb", Abc_CommandAbc9RecoverBoundary, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&str_eco", Abc_CommandAbc9StrEco, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); @@ -51839,122 +51837,6 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandAbc9RecoverBoundary( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - extern Gia_Man_t * Gia_ManDeepSyn( Gia_Man_t * pGia, int nIters, int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fVerbose ); - extern Gia_Man_t * Gia_ManImplFromBMiter( Gia_Man_t * p, int nPo, int nBInput ); - extern Gia_Man_t * Gia_ManMiterFromBMiter( Gia_Man_t * p, int nPo ); - int c, nIters = 1, nNoImpr = ABC_INFINITY, TimeOut = 20, nAnds = 0, Seed = 0, fUseTwo = 0, fVerbose = 0; - - int fKeepBMiter = 0; - Gia_Man_t * pMiter; - Gia_Man_t * pImpl; - Gia_Man_t * pDup; - Gia_Obj_t* pObj; - Gia_Man_t * pSpec = NULL; - char ** pArgvNew; - int nArgcNew, nPo; - int nBInput = -1; - char *FileName; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vkhI," ) ) != EOF ) - { - switch ( c ) - { - case 'I': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); - goto usage; - } - nBInput = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nBInput < 0 ) - goto usage; - break; - case 'k': - fKeepBMiter ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( nArgcNew != 1 ) - { - Abc_Print( -1, "There is no file name.\n" ); - return 1; - } - - if ( pAbc->pGia == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc9RecoverBoundary(): There is no AIG.\n" ); - return 0; - } - FileName = pArgvNew[0]; - - - // printing - - // Gia_ManForEachCo( pAbc->pGia, pObj, i ){ - // printf("Original node: %s id: %i\n", Gia_ObjCoName(pAbc->pGia, i), i); - // } - - - /* - // perform heavy synthesis - pTemp = Gia_ManDeepSyn( pAbc->pGia, nIters, nNoImpr, TimeOut, nAnds, Seed, fUseTwo, fVerbose ); - Abc_FrameUpdateGia( pAbc, pTemp ); - // print spec/impl and boundary information - Gia_ManForEachCo( pAbc->pGia, pObj, i ){ - printf("Output node: %s id: %i\n", Gia_ObjCoName(pAbc->pGia, i), i); - } - */ - - - - // check boundary recovery status - pSpec = Gia_AigerRead( FileName, false, true, 0 ); - if ( !pSpec ) - { - Abc_Print( -1, "Abc_CommandAbc9RecoverBoundary(): fail to read spec.\n" ); - return 1; - } - nPo = Gia_ManCoNum( pSpec ); - - // duplicate - pDup = Gia_ManDup( pAbc->pGia ); - - // option 1: remove po and keep the buffers - // default nbinput: - if ( nBInput == -1 ) nBInput = (Gia_ManCoNum(pDup)-2*nPo)/2; - pImpl = Gia_ManImplFromBMiter( pDup, nPo, nBInput ); - - // option 2: build miter (with uif?) - if (!fKeepBMiter ) - { - pMiter = Gia_ManMiterFromBMiter( pAbc->pGia, nPo ); - Abc_FrameUpdateGia( pAbc, pMiter ); - } - - return 0; - -usage: - Abc_Print( -2, "usage: &rb [-vkh] \n" ); - Abc_Print( -2, "\t generate an implementation aig with specification boundary\n" ); - Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-k : keep the bmiter and print the boundary status only.\n"); - Abc_Print( -2, "\t-I num : the number of inputs in the boundary\n"); - Abc_Print( -2, "\t-h : print the command usage\n"); - Abc_Print( -2, "\t : the specification file\n"); - return 1; -} extern Bnd_Man_t* pBnd; int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) @@ -52005,9 +51887,6 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } - // params - - // read impl FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) @@ -52044,21 +51923,27 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } - - // verify if spec eq impl - pMiter = Gia_ManMiter( pAbc->pGia, pImpl, 0, 1, 0, 0, 0 ); - assert( Cec_ManVerify( pMiter, pParsCec ) ); - Gia_ManStop(pMiter); - // start boundary manager pBnd = Bnd_ManStart( pAbc->pGia, pImpl ); - // check boundary - if ( 0 == Bnd_ManCheckBound( pAbc -> pGia ) ) + // verify if spec eq impl + pMiter = Gia_ManMiter( pAbc->pGia, pImpl, 0, 1, 0, 0, 0 ); + if ( !Cec_ManVerify( pMiter, pParsCec ) ) { - Abc_Print( -1, "Abc_CommandAbc9StrEco(): The given boundary is invalid.\n" ); + Abc_Print( -1, "Abc_CommandAbc9StrEco(): The given impl is not equivalent to spec.\n" ); success = 0; } + Gia_ManStop(pMiter); + + // check boundary + if ( success ) + { + if ( 0 == Bnd_ManCheckBound( pPatch ) || 0 == Bnd_ManCheckBound( pAbc -> pGia ) ) + { + Abc_Print( -1, "Abc_CommandAbc9StrEco(): The given boundary is invalid.\n" ); + success = 0; + } + } if ( success ) { @@ -52077,10 +51962,10 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) pImpl_out = Bnd_ManGenImplOut( pImpl ); if ( !pImpl_out ) success = 0; - Gia_AigerWrite( pSpec_out, "spec_out.aig", 0, 0, 0 ); - Gia_AigerWrite( pImpl_out, "impl_out.aig", 0, 0, 0 ); - Gia_ManPrintStats( pSpec_out, pPars ); - Gia_ManPrintStats( pImpl_out, pPars ); + // Gia_AigerWrite( pSpec_out, "spec_out.aig", 0, 0, 0 ); + // Gia_AigerWrite( pImpl_out, "impl_out.aig", 0, 0, 0 ); + // Gia_ManPrintStats( pSpec_out, pPars ); + // Gia_ManPrintStats( pImpl_out, pPars ); } @@ -52093,11 +51978,26 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) Bnd_ManSetEqOut( Cec_ManVerify( pMiter, pParsCec ) ); Gia_ManStop( pMiter ); - // generate patched + // generate patched impl + printf("Generating patched impl\n"); pPatched = Bnd_ManGenPatched( pImpl_out, pAbc->pGia, pPatch ); + // generate patched spec just for debugging + printf("Generating patched spec\n"); + pTemp = Bnd_ManGenPatched( pSpec_out, pAbc->pGia, pPatch ); + printf("Checking the equivalence of patched spec and patched impl\n"); + pMiter = Gia_ManMiter( pTemp, pPatched, 0, 1, 0, 0, 0 ); + Cec_ManVerify( pMiter, pParsCec ); + Gia_ManStop( pMiter ); + printf("Checking the equivalence of patched spec and patch\n"); + pMiter = Gia_ManMiter( pTemp, pPatch, 0, 1, 0, 0, 0 ); + Cec_ManVerify( pMiter, pParsCec ); + Gia_ManStop( pMiter ); + + Gia_ManStop( pTemp ); + // check if patched is equiv to patch - printf("Checking the equivalence of patch and patched\n"); + printf("Checking the equivalence of patch and patched impl\n"); pMiter = Gia_ManMiter( pPatch, pPatched, 0, 1, 0, 0, 0 ); Bnd_ManSetEqRes( Cec_ManVerify( pMiter, pParsCec ) ); Gia_ManStop( pMiter ); @@ -52119,12 +52019,12 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &str_eco -I [-vh] \n" ); - Abc_Print( -2, "\t creates the boundary miter\n" ); - Abc_Print( -2, "\t-I : number of boundary inputs\n" ); + Abc_Print( -2, "usage: &str_eco -I [-vh] \n" ); + Abc_Print( -2, "\t SAT-sweeping-based ECO\n" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); - Abc_Print( -2, "\t : the implementation file\n"); + Abc_Print( -2, "\t : the implementation aig. (should be equivalent to spec)\n"); + Abc_Print( -2, "\t : the modified spec. (should be a hierarchical AIG)\n"); return 1; } From 23654254e1e6f8965454504892fe68698e32990c Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Sun, 3 Mar 2024 03:06:13 +0800 Subject: [PATCH 105/151] clean up --- src/aig/gia/giaBound.c | 99 +++++++++++++++++++++++------------------- src/base/abci/abc.c | 2 +- 2 files changed, 56 insertions(+), 45 deletions(-) diff --git a/src/aig/gia/giaBound.c b/src/aig/gia/giaBound.c index 9fad955d7..7988d8655 100644 --- a/src/aig/gia/giaBound.c +++ b/src/aig/gia/giaBound.c @@ -299,14 +299,14 @@ void Bnd_ManPrintBound() // printf("%d nodes merged in spec\n", pBnd ->nMerged_spec - Vec_IntSize(pBnd->vBI) - Vec_IntSize(pBnd->vBO) ); // printf("%d nodes merged in impl\n", pBnd ->nMerged_impl ); - printf("BI spec:"); Vec_IntPrint(pBnd -> vBI); - printf("BO spec:"); Vec_IntPrint(pBnd -> vBO); - printf("EI spec:"); Vec_IntPrint(pBnd -> vEI_spec); - printf("EI impl:"); Vec_IntPrint(pBnd -> vEI_impl); - printf("EI phase:"); Vec_BitPrint(pBnd -> vEI_phase); - printf("EO spec:"); Vec_IntPrint(pBnd -> vEO_spec); - printf("EO impl:"); Vec_IntPrint(pBnd -> vEO_impl); - printf("EO phase:"); Vec_BitPrint(pBnd -> vEO_phase); + printf("BI spec:\t"); Vec_IntPrint(pBnd -> vBI); + printf("BO spec:\t"); Vec_IntPrint(pBnd -> vBO); + printf("EI spec:\t"); Vec_IntPrint(pBnd -> vEI_spec); + printf("EI impl:\t"); Vec_IntPrint(pBnd -> vEI_impl); + printf("EI phase:\t"); Vec_BitPrint(pBnd -> vEI_phase); + printf("EO spec:\t"); Vec_IntPrint(pBnd -> vEO_spec); + printf("EO impl:\t"); Vec_IntPrint(pBnd -> vEO_impl); + printf("EO phase:\t"); Vec_BitPrint(pBnd -> vEO_phase); } void Bnd_ManPrintStats() @@ -347,21 +347,21 @@ void Bnd_ManPrintStats() // warning (may be neq) // eq_out, eq_res - printf("\nRESULT\n"); - printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", - p->nInternal, - p->nBI, p->nBO, - p->nBI_miss, p->nBO_miss, - Vec_IntSize(p->vEI_spec), Vec_IntSize(p->vEO_spec), p->nExtra, - p->nNode_spec, p->nNode_impl, p->nNode_patched, - p->combLoop_spec, p->combLoop_impl, - p->status, - p->nChoice_impl, - p->nChoice_spec, - p->feedthrough, - warning, - p->eq_out, p->eq_res - ); + // printf("\nRESULT\n"); + // printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + // p->nInternal, + // p->nBI, p->nBO, + // p->nBI_miss, p->nBO_miss, + // Vec_IntSize(p->vEI_spec), Vec_IntSize(p->vEO_spec), p->nExtra, + // p->nNode_spec, p->nNode_impl, p->nNode_patched, + // p->combLoop_spec, p->combLoop_impl, + // p->status, + // p->nChoice_impl, + // p->nChoice_spec, + // p->feedthrough, + // warning, + // p->eq_out, p->eq_res + // ); } /**Function************************************************************* @@ -580,7 +580,6 @@ void Bnd_ManFindBound( Gia_Man_t * p ) } cnt++; } - printf("#BI = %d #BO = %d\n", Vec_IntSize(vBI), Vec_IntSize(vBO) ); // compute EO, travse with flag 1 Vec_IntForEachEntry( vBO, id, i ) @@ -785,14 +784,26 @@ Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec return 0; } + // detect feedthrough + Gia_ManFillValue(p); + Vec_IntForEachEntry(vEO, id, i) + { + Gia_ManObj(p, id) -> Value = 1; + } + Vec_IntForEachEntry(vEI, id, i) + { + if ( Gia_ManObj(p, id) -> Value == 1 ) + pBnd -> feedthrough = 1; + } // initialize pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew -> pName = ABC_ALLOC( char, strlen(p->pName)+10); sprintf( pNew -> pName, "%s_out", p -> pName ); Gia_ManHashStart( pNew ); + Gia_ManFillValue(p); Gia_ManConst0(p) -> Value = 0; - Gia_ManCleanValue(p); + // record the original value for eo vValue = Vec_IntAlloc( Gia_ManObjNum(p) ); @@ -805,7 +816,7 @@ Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec } Vec_IntForEachEntry( vEO, id, i ) { - if( Gia_ManObj(p, id) -> Value != 0 ) + if( Gia_ManObj(p, id) -> Value != ~0 ) { Vec_IntSetEntry( vValue, id, Gia_ManObj(p, id) -> Value ); } @@ -817,18 +828,10 @@ Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec } - // record where EI and EO share the same node - // this may cause non-equivalent - Vec_IntForEachEntry( vEI, id, i ) - { - if ( Gia_ManObj(p, id) -> Value != 0 ) - pBnd -> feedthrough = 1; - } - // add aig nodes Gia_ManForEachAnd(p, pObj, i) { - if ( pObj -> Value ) continue; + if ( pObj -> Value != ~0 ) continue; pObj -> Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } @@ -884,12 +887,7 @@ Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t* p ) void Bnd_AddNodeRec( Gia_Man_t *p, Gia_Man_t *pNew, Gia_Obj_t *pObj ) { // TODO does this mean constant zero node? - if ( pObj -> Value != 0 ) return; - if ( Gia_ObjIsConst0(pObj) ) - { - printf( "contant zero encountered\n"); - return; - } + if ( pObj -> Value != ~0 ) return; for( int i = 0; i < Gia_ObjFaninNum(p, pObj); i++ ) { @@ -925,9 +923,12 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat pNew -> pName = ABC_ALLOC( char, strlen(pOut->pName)+3); sprintf( pNew -> pName, "%s_p", pOut -> pName ); Gia_ManHashStart( pNew ); - Gia_ManCleanValue(pOut); - Gia_ManCleanValue(pSpec); - Gia_ManCleanValue(pPatch); + Gia_ManFillValue(pOut); + Gia_ManFillValue(pSpec); + Gia_ManFillValue(pPatch); + Gia_ManConst0(pOut)->Value = 0; + Gia_ManConst0(pSpec)->Value = 0; + Gia_ManConst0(pPatch)->Value = 0; // get bi and bo in patch cnt = 0; @@ -966,7 +967,9 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat // set Spec EI Gia_ManObj( pSpec, Vec_IntEntry(pBnd -> vEI_spec, i) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); } + // printf("\n"); // add Spec BI to EI // printf("adding BI to EI in Spec\n"); @@ -977,7 +980,9 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat // set patch bi Gia_ManObj( pPatch, Vec_IntEntry( vBI_patch, i) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); } + // printf("\n"); // add Patch BO to BI // printf("adding BO to BI in Patch\n"); @@ -988,7 +993,9 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat // set spec bo Gia_ManObj( pSpec, Vec_IntEntry( pBnd -> vBO, i) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); } + // printf("\n"); // add Spec EO to BO // printf("adding EO to BO in Spec\n"); @@ -999,7 +1006,9 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat // set impl EO (PI) Gia_ManCi( pOut, i + Gia_ManCiNum(pSpec) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); } + // printf("\n"); // add Impl (real) PO to EO // printf("adding CO to EO in Impl\n"); @@ -1008,7 +1017,9 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat pObj = Gia_ManCo( pOut, i ); Bnd_AddNodeRec( pOut, pNew, pObj ); Gia_ManAppendCo( pNew, pObj->Value ); + // printf(" %d",pObj -> Value); } + // printf("\n"); // clean up diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index ed930636b..4f53096f8 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -51997,7 +51997,7 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_ManStop( pTemp ); // check if patched is equiv to patch - printf("Checking the equivalence of patch and patched impl\n"); + printf("Checking the equivalence of patched impl and patch\n"); pMiter = Gia_ManMiter( pPatch, pPatched, 0, 1, 0, 0, 0 ); Bnd_ManSetEqRes( Cec_ManVerify( pMiter, pParsCec ) ); Gia_ManStop( pMiter ); From a1159d98dff6af1d59dba6cc3309d174c9d065d6 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 2 Mar 2024 16:10:37 -0800 Subject: [PATCH 106/151] Fixing a compiler problem with namespaces. --- src/sat/bsat2/ParseUtils.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sat/bsat2/ParseUtils.h b/src/sat/bsat2/ParseUtils.h index 8e0f9c890..b7325f174 100644 --- a/src/sat/bsat2/ParseUtils.h +++ b/src/sat/bsat2/ParseUtils.h @@ -26,6 +26,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "misc/zlib/zlib.h" +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { //------------------------------------------------------------------------------------------------- @@ -119,4 +121,6 @@ static bool eagerMatch(B& in, const char* str) { //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif From 4de4605836f6bea796ced63b27b7eb6c252d6880 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 2 Mar 2024 16:31:41 -0800 Subject: [PATCH 107/151] More changees to compile new code with namespaces. --- src/sat/bsat2/Alg.h | 4 ++++ src/sat/bsat2/Alloc.h | 4 ++++ src/sat/bsat2/Dimacs.h | 4 ++++ src/sat/bsat2/Heap.h | 4 ++++ src/sat/bsat2/MainSat.cpp | 5 +++++ src/sat/bsat2/MainSimp.cpp | 5 +++++ src/sat/bsat2/Map.h | 4 ++++ src/sat/bsat2/Options.cpp | 4 ++++ src/sat/bsat2/Options.h | 4 ++++ src/sat/bsat2/Queue.h | 4 ++++ src/sat/bsat2/SimpSolver.cpp | 4 ++++ src/sat/bsat2/SimpSolver.h | 3 +++ src/sat/bsat2/Solver.cpp | 4 ++++ src/sat/bsat2/Solver.h | 3 +++ src/sat/bsat2/SolverTypes.h | 4 ++++ src/sat/bsat2/Sort.h | 3 +++ src/sat/bsat2/System.cpp | 18 ++++++++++++++++++ src/sat/bsat2/System.h | 4 ++++ src/sat/bsat2/Vec.h | 4 ++++ src/sat/bsat2/XAlloc.h | 4 ++++ 20 files changed, 93 insertions(+) diff --git a/src/sat/bsat2/Alg.h b/src/sat/bsat2/Alg.h index 3e0745f1d..2a5af3eff 100644 --- a/src/sat/bsat2/Alg.h +++ b/src/sat/bsat2/Alg.h @@ -23,6 +23,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "Vec.h" +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { //================================================================================================= @@ -81,4 +83,6 @@ static inline void append(const vec& from, vec& to){ copy(from, to, true); //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Alloc.h b/src/sat/bsat2/Alloc.h index 7f506cb5a..c583bf3b6 100644 --- a/src/sat/bsat2/Alloc.h +++ b/src/sat/bsat2/Alloc.h @@ -24,6 +24,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "XAlloc.h" #include "Vec.h" +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { //================================================================================================= @@ -128,4 +130,6 @@ RegionAllocator::alloc(int size) //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Dimacs.h b/src/sat/bsat2/Dimacs.h index f26f152be..806b86942 100644 --- a/src/sat/bsat2/Dimacs.h +++ b/src/sat/bsat2/Dimacs.h @@ -26,6 +26,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "ParseUtils.h" #include "SolverTypes.h" +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { //================================================================================================= @@ -86,4 +88,6 @@ static void parse_DIMACS(gzFile input_stream, Solver& S) { //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Heap.h b/src/sat/bsat2/Heap.h index e5b4ddb56..bdaa7edfd 100644 --- a/src/sat/bsat2/Heap.h +++ b/src/sat/bsat2/Heap.h @@ -23,6 +23,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "Vec.h" +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { //================================================================================================= @@ -146,4 +148,6 @@ class Heap { //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/MainSat.cpp b/src/sat/bsat2/MainSat.cpp index 1f61f9eec..e988ac3ac 100644 --- a/src/sat/bsat2/MainSat.cpp +++ b/src/sat/bsat2/MainSat.cpp @@ -29,6 +29,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "Dimacs.h" #include "Solver.h" +ABC_NAMESPACE_IMPL_START + using namespace Minisat; //================================================================================================= @@ -195,3 +197,6 @@ extern "C" int MainSat(int argc, char** argv) exit(0); } } + + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/bsat2/MainSimp.cpp b/src/sat/bsat2/MainSimp.cpp index 4a8909210..c959e606f 100644 --- a/src/sat/bsat2/MainSimp.cpp +++ b/src/sat/bsat2/MainSimp.cpp @@ -33,6 +33,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "Dimacs.h" #include "SimpSolver.h" +ABC_NAMESPACE_IMPL_START + using namespace Minisat; //================================================================================================= @@ -204,3 +206,6 @@ extern "C" int MainSimp(int argc, char** argv) exit(0); } } + + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/bsat2/Map.h b/src/sat/bsat2/Map.h index 1dd22a06d..d9a4c5631 100644 --- a/src/sat/bsat2/Map.h +++ b/src/sat/bsat2/Map.h @@ -23,6 +23,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "IntTypes.h" #include "Vec.h" +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { //================================================================================================= @@ -190,4 +192,6 @@ class Map { //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Options.cpp b/src/sat/bsat2/Options.cpp index b30cff0e5..1f700dc0f 100644 --- a/src/sat/bsat2/Options.cpp +++ b/src/sat/bsat2/Options.cpp @@ -21,6 +21,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "Options.h" #include "ParseUtils.h" +ABC_NAMESPACE_IMPL_START + using namespace Minisat; int Minisat::parseOptions(int& argc, char** argv, bool strict) @@ -91,3 +93,5 @@ int Minisat::printUsageAndExit (int argc, char** argv, bool verbose) return 0; } + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/bsat2/Options.h b/src/sat/bsat2/Options.h index 439cb8f21..42bc45126 100644 --- a/src/sat/bsat2/Options.h +++ b/src/sat/bsat2/Options.h @@ -29,6 +29,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "Vec.h" #include "ParseUtils.h" +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { //================================================================================================== @@ -384,4 +386,6 @@ class BoolOption : public Option //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Queue.h b/src/sat/bsat2/Queue.h index 11b429115..dd40e2c91 100644 --- a/src/sat/bsat2/Queue.h +++ b/src/sat/bsat2/Queue.h @@ -25,6 +25,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA namespace Minisat { +ABC_NAMESPACE_CXX_HEADER_START + //================================================================================================= template @@ -66,4 +68,6 @@ public: //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/SimpSolver.cpp b/src/sat/bsat2/SimpSolver.cpp index 5a7a006c2..59820a47b 100644 --- a/src/sat/bsat2/SimpSolver.cpp +++ b/src/sat/bsat2/SimpSolver.cpp @@ -22,6 +22,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "SimpSolver.h" #include "System.h" +ABC_NAMESPACE_IMPL_START + using namespace Minisat; //================================================================================================= @@ -718,3 +720,5 @@ void SimpSolver::garbageCollect() ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size); to.moveTo(ca); } + +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/sat/bsat2/SimpSolver.h b/src/sat/bsat2/SimpSolver.h index e24b0e430..098254a12 100644 --- a/src/sat/bsat2/SimpSolver.h +++ b/src/sat/bsat2/SimpSolver.h @@ -24,6 +24,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "Queue.h" #include "Solver.h" +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -194,4 +195,6 @@ inline lbool SimpSolver::solveLimited (const vec& assumps, bool do_simp, bo //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Solver.cpp b/src/sat/bsat2/Solver.cpp index 0f8b415a9..2a0642407 100644 --- a/src/sat/bsat2/Solver.cpp +++ b/src/sat/bsat2/Solver.cpp @@ -23,6 +23,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "Sort.h" #include "Solver.h" +ABC_NAMESPACE_IMPL_START + using namespace Minisat; //================================================================================================= @@ -922,3 +924,5 @@ void Solver::garbageCollect() ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size); to.moveTo(ca); } + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/bsat2/Solver.h b/src/sat/bsat2/Solver.h index fc0bb4ba2..d14b2fec8 100644 --- a/src/sat/bsat2/Solver.h +++ b/src/sat/bsat2/Solver.h @@ -27,6 +27,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "Options.h" #include "SolverTypes.h" +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -370,4 +371,6 @@ inline void Solver::toDimacs (const char* file, Lit p, Lit q, Lit r){ ve //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/SolverTypes.h b/src/sat/bsat2/SolverTypes.h index f34deca1c..6401a2a0c 100644 --- a/src/sat/bsat2/SolverTypes.h +++ b/src/sat/bsat2/SolverTypes.h @@ -30,6 +30,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "Map.h" #include "Alloc.h" +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { //================================================================================================= @@ -404,4 +406,6 @@ inline void Clause::strengthen(Lit p) //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Sort.h b/src/sat/bsat2/Sort.h index cc96486d8..15b6b7d07 100644 --- a/src/sat/bsat2/Sort.h +++ b/src/sat/bsat2/Sort.h @@ -26,6 +26,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA //================================================================================================= // Some sorting algorithms for vec's +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -95,4 +96,6 @@ template void sort(vec& v) { //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/System.cpp b/src/sat/bsat2/System.cpp index c2d6259e2..e617500c2 100644 --- a/src/sat/bsat2/System.cpp +++ b/src/sat/bsat2/System.cpp @@ -25,6 +25,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include +ABC_NAMESPACE_IMPL_START + using namespace Minisat; // TODO: split the memory reading functions into two: one for reading high-watermark of RSS, and @@ -72,24 +74,40 @@ double Minisat::memUsedPeak() { double peak = memReadPeak() / 1024; return peak == 0 ? memUsed() : peak; } +ABC_NAMESPACE_IMPL_END + #elif defined(__FreeBSD__) +ABC_NAMESPACE_IMPL_START + double Minisat::memUsed(void) { struct rusage ru; getrusage(RUSAGE_SELF, &ru); return (double)ru.ru_maxrss / 1024; } double MiniSat::memUsedPeak(void) { return memUsed(); } +ABC_NAMESPACE_IMPL_END #elif defined(__APPLE__) #include +ABC_NAMESPACE_IMPL_START + double Minisat::memUsed(void) { malloc_statistics_t t; malloc_zone_statistics(NULL, &t); return (double)t.max_size_in_use / (1024*1024); } +ABC_NAMESPACE_IMPL_END + #else + +ABC_NAMESPACE_IMPL_START + double Minisat::memUsed() { return 0; } double Minisat::memUsedPeak() { return 0; } + +ABC_NAMESPACE_IMPL_END + #endif + diff --git a/src/sat/bsat2/System.h b/src/sat/bsat2/System.h index d776c880c..2952d4117 100644 --- a/src/sat/bsat2/System.h +++ b/src/sat/bsat2/System.h @@ -29,6 +29,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA //------------------------------------------------------------------------------------------------- +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { static inline double cpuTime(void); // CPU-time in seconds. @@ -57,4 +59,6 @@ static inline double Minisat::cpuTime(void) { #endif +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Vec.h b/src/sat/bsat2/Vec.h index f0e07d016..59b5583a8 100644 --- a/src/sat/bsat2/Vec.h +++ b/src/sat/bsat2/Vec.h @@ -27,6 +27,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "IntTypes.h" #include "XAlloc.h" +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { //================================================================================================= @@ -127,4 +129,6 @@ void vec::clear(bool dealloc) { //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/XAlloc.h b/src/sat/bsat2/XAlloc.h index 1da176028..9533b6b90 100644 --- a/src/sat/bsat2/XAlloc.h +++ b/src/sat/bsat2/XAlloc.h @@ -24,6 +24,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { //================================================================================================= @@ -42,4 +44,6 @@ static inline void* xrealloc(void *ptr, size_t size) //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif From f6f542c87330e15386952b12fda4ba1c7b971c30 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 2 Mar 2024 16:38:16 -0800 Subject: [PATCH 108/151] More changes to compile with namespaces. --- src/sat/bsat2/IntTypes.h | 2 ++ src/sat/bsat2/XAlloc.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/sat/bsat2/IntTypes.h b/src/sat/bsat2/IntTypes.h index 1c011e83a..fdcd3d9f7 100644 --- a/src/sat/bsat2/IntTypes.h +++ b/src/sat/bsat2/IntTypes.h @@ -44,4 +44,6 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA //================================================================================================= +#include + #endif diff --git a/src/sat/bsat2/XAlloc.h b/src/sat/bsat2/XAlloc.h index 9533b6b90..fdebe502a 100644 --- a/src/sat/bsat2/XAlloc.h +++ b/src/sat/bsat2/XAlloc.h @@ -24,6 +24,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include +#include + ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { From ce44eda85afef96e8fb1ba4fefedad9c72358a19 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 2 Mar 2024 16:46:09 -0800 Subject: [PATCH 109/151] More changes. --- src/sat/bsat2/Alg.h | 2 +- src/sat/bsat2/Alloc.h | 4 ++-- src/sat/bsat2/Dimacs.h | 4 ++-- src/sat/bsat2/Heap.h | 2 +- src/sat/bsat2/MainSat.cpp | 10 +++++----- src/sat/bsat2/MainSimp.cpp | 10 +++++----- src/sat/bsat2/Map.h | 4 ++-- src/sat/bsat2/Options.cpp | 6 +++--- src/sat/bsat2/Options.h | 6 +++--- src/sat/bsat2/Queue.h | 2 +- src/sat/bsat2/SimpSolver.cpp | 6 +++--- src/sat/bsat2/SimpSolver.h | 4 ++-- src/sat/bsat2/Solver.cpp | 4 ++-- src/sat/bsat2/Solver.h | 10 +++++----- src/sat/bsat2/SolverTypes.h | 10 +++++----- src/sat/bsat2/Sort.h | 2 +- src/sat/bsat2/System.cpp | 2 +- src/sat/bsat2/System.h | 2 +- src/sat/bsat2/Vec.h | 4 ++-- 19 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/sat/bsat2/Alg.h b/src/sat/bsat2/Alg.h index 2a5af3eff..87004fce8 100644 --- a/src/sat/bsat2/Alg.h +++ b/src/sat/bsat2/Alg.h @@ -21,7 +21,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Alg_h #define Minisat_Alg_h -#include "Vec.h" +#include "sat/bsat2/Vec.h" ABC_NAMESPACE_CXX_HEADER_START diff --git a/src/sat/bsat2/Alloc.h b/src/sat/bsat2/Alloc.h index c583bf3b6..a9786a9a8 100644 --- a/src/sat/bsat2/Alloc.h +++ b/src/sat/bsat2/Alloc.h @@ -21,8 +21,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Alloc_h #define Minisat_Alloc_h -#include "XAlloc.h" -#include "Vec.h" +#include "sat/bsat2/XAlloc.h" +#include "sat/bsat2/Vec.h" ABC_NAMESPACE_CXX_HEADER_START diff --git a/src/sat/bsat2/Dimacs.h b/src/sat/bsat2/Dimacs.h index 806b86942..0e7ad925a 100644 --- a/src/sat/bsat2/Dimacs.h +++ b/src/sat/bsat2/Dimacs.h @@ -23,8 +23,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include -#include "ParseUtils.h" -#include "SolverTypes.h" +#include "sat/bsat2/ParseUtils.h" +#include "sat/bsat2/SolverTypes.h" ABC_NAMESPACE_CXX_HEADER_START diff --git a/src/sat/bsat2/Heap.h b/src/sat/bsat2/Heap.h index bdaa7edfd..ae50c4b57 100644 --- a/src/sat/bsat2/Heap.h +++ b/src/sat/bsat2/Heap.h @@ -21,7 +21,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Heap_h #define Minisat_Heap_h -#include "Vec.h" +#include "sat/bsat2/Vec.h" ABC_NAMESPACE_CXX_HEADER_START diff --git a/src/sat/bsat2/MainSat.cpp b/src/sat/bsat2/MainSat.cpp index e988ac3ac..855466263 100644 --- a/src/sat/bsat2/MainSat.cpp +++ b/src/sat/bsat2/MainSat.cpp @@ -23,11 +23,11 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include "misc/zlib/zlib.h" -#include "System.h" -#include "ParseUtils.h" -#include "Options.h" -#include "Dimacs.h" -#include "Solver.h" +#include "sat/bsat2/System.h" +#include "sat/bsat2/ParseUtils.h" +#include "sat/bsat2/Options.h" +#include "sat/bsat2/Dimacs.h" +#include "sat/bsat2/Solver.h" ABC_NAMESPACE_IMPL_START diff --git a/src/sat/bsat2/MainSimp.cpp b/src/sat/bsat2/MainSimp.cpp index c959e606f..2d0ad109e 100644 --- a/src/sat/bsat2/MainSimp.cpp +++ b/src/sat/bsat2/MainSimp.cpp @@ -27,11 +27,11 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #endif -#include "System.h" -#include "ParseUtils.h" -#include "Options.h" -#include "Dimacs.h" -#include "SimpSolver.h" +#include "sat/bsat2/System.h" +#include "sat/bsat2/ParseUtils.h" +#include "sat/bsat2/Options.h" +#include "sat/bsat2/Dimacs.h" +#include "sat/bsat2/SimpSolver.h" ABC_NAMESPACE_IMPL_START diff --git a/src/sat/bsat2/Map.h b/src/sat/bsat2/Map.h index d9a4c5631..374e76c9b 100644 --- a/src/sat/bsat2/Map.h +++ b/src/sat/bsat2/Map.h @@ -20,8 +20,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Map_h #define Minisat_Map_h -#include "IntTypes.h" -#include "Vec.h" +#include "sat/bsat2/IntTypes.h" +#include "sat/bsat2/Vec.h" ABC_NAMESPACE_CXX_HEADER_START diff --git a/src/sat/bsat2/Options.cpp b/src/sat/bsat2/Options.cpp index 1f700dc0f..f14059f67 100644 --- a/src/sat/bsat2/Options.cpp +++ b/src/sat/bsat2/Options.cpp @@ -17,9 +17,9 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************************************/ -#include "Sort.h" -#include "Options.h" -#include "ParseUtils.h" +#include "sat/bsat2/Sort.h" +#include "sat/bsat2/Options.h" +#include "sat/bsat2/ParseUtils.h" ABC_NAMESPACE_IMPL_START diff --git a/src/sat/bsat2/Options.h b/src/sat/bsat2/Options.h index 42bc45126..137b5a45e 100644 --- a/src/sat/bsat2/Options.h +++ b/src/sat/bsat2/Options.h @@ -25,9 +25,9 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include -#include "IntTypes.h" -#include "Vec.h" -#include "ParseUtils.h" +#include "sat/bsat2/IntTypes.h" +#include "sat/bsat2/Vec.h" +#include "sat/bsat2/ParseUtils.h" ABC_NAMESPACE_CXX_HEADER_START diff --git a/src/sat/bsat2/Queue.h b/src/sat/bsat2/Queue.h index dd40e2c91..c2b3c64ad 100644 --- a/src/sat/bsat2/Queue.h +++ b/src/sat/bsat2/Queue.h @@ -21,7 +21,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Queue_h #define Minisat_Queue_h -#include "Vec.h" +#include "sat/bsat2/Vec.h" namespace Minisat { diff --git a/src/sat/bsat2/SimpSolver.cpp b/src/sat/bsat2/SimpSolver.cpp index 59820a47b..59952d154 100644 --- a/src/sat/bsat2/SimpSolver.cpp +++ b/src/sat/bsat2/SimpSolver.cpp @@ -18,9 +18,9 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************************************/ -#include "Sort.h" -#include "SimpSolver.h" -#include "System.h" +#include "sat/bsat2/Sort.h" +#include "sat/bsat2/SimpSolver.h" +#include "sat/bsat2/System.h" ABC_NAMESPACE_IMPL_START diff --git a/src/sat/bsat2/SimpSolver.h b/src/sat/bsat2/SimpSolver.h index 098254a12..ad02c6dff 100644 --- a/src/sat/bsat2/SimpSolver.h +++ b/src/sat/bsat2/SimpSolver.h @@ -21,8 +21,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_SimpSolver_h #define Minisat_SimpSolver_h -#include "Queue.h" -#include "Solver.h" +#include "sat/bsat2/Queue.h" +#include "sat/bsat2/Solver.h" ABC_NAMESPACE_CXX_HEADER_START diff --git a/src/sat/bsat2/Solver.cpp b/src/sat/bsat2/Solver.cpp index 2a0642407..1c45a4538 100644 --- a/src/sat/bsat2/Solver.cpp +++ b/src/sat/bsat2/Solver.cpp @@ -20,8 +20,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include -#include "Sort.h" -#include "Solver.h" +#include "sat/bsat2/Sort.h" +#include "sat/bsat2/Solver.h" ABC_NAMESPACE_IMPL_START diff --git a/src/sat/bsat2/Solver.h b/src/sat/bsat2/Solver.h index d14b2fec8..9c9a30ee3 100644 --- a/src/sat/bsat2/Solver.h +++ b/src/sat/bsat2/Solver.h @@ -21,11 +21,11 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Solver_h #define Minisat_Solver_h -#include "Vec.h" -#include "Heap.h" -#include "Alg.h" -#include "Options.h" -#include "SolverTypes.h" +#include "sat/bsat2/Vec.h" +#include "sat/bsat2/Heap.h" +#include "sat/bsat2/Alg.h" +#include "sat/bsat2/Options.h" +#include "sat/bsat2/SolverTypes.h" ABC_NAMESPACE_CXX_HEADER_START diff --git a/src/sat/bsat2/SolverTypes.h b/src/sat/bsat2/SolverTypes.h index 6401a2a0c..64fbe980e 100644 --- a/src/sat/bsat2/SolverTypes.h +++ b/src/sat/bsat2/SolverTypes.h @@ -24,11 +24,11 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include -#include "IntTypes.h" -#include "Alg.h" -#include "Vec.h" -#include "Map.h" -#include "Alloc.h" +#include "sat/bsat2/IntTypes.h" +#include "sat/bsat2/Alg.h" +#include "sat/bsat2/Vec.h" +#include "sat/bsat2/Map.h" +#include "sat/bsat2/Alloc.h" ABC_NAMESPACE_CXX_HEADER_START diff --git a/src/sat/bsat2/Sort.h b/src/sat/bsat2/Sort.h index 15b6b7d07..7ce99ea46 100644 --- a/src/sat/bsat2/Sort.h +++ b/src/sat/bsat2/Sort.h @@ -21,7 +21,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Sort_h #define Minisat_Sort_h -#include "Vec.h" +#include "sat/bsat2/Vec.h" //================================================================================================= // Some sorting algorithms for vec's diff --git a/src/sat/bsat2/System.cpp b/src/sat/bsat2/System.cpp index e617500c2..2c64e7fea 100644 --- a/src/sat/bsat2/System.cpp +++ b/src/sat/bsat2/System.cpp @@ -18,7 +18,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************************************/ -#include "System.h" +#include "sat/bsat2/System.h" #if defined(__linux__) diff --git a/src/sat/bsat2/System.h b/src/sat/bsat2/System.h index 2952d4117..e3d8afba2 100644 --- a/src/sat/bsat2/System.h +++ b/src/sat/bsat2/System.h @@ -25,7 +25,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #endif -#include "IntTypes.h" +#include "sat/bsat2/IntTypes.h" //------------------------------------------------------------------------------------------------- diff --git a/src/sat/bsat2/Vec.h b/src/sat/bsat2/Vec.h index 59b5583a8..aade19f13 100644 --- a/src/sat/bsat2/Vec.h +++ b/src/sat/bsat2/Vec.h @@ -24,8 +24,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include -#include "IntTypes.h" -#include "XAlloc.h" +#include "sat/bsat2/IntTypes.h" +#include "sat/bsat2/XAlloc.h" ABC_NAMESPACE_CXX_HEADER_START From b627aa7cb586b714cd109dad077d78ed0f433ffc Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 2 Mar 2024 16:57:00 -0800 Subject: [PATCH 110/151] More changes. --- src/sat/bsat2/System.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/sat/bsat2/System.h b/src/sat/bsat2/System.h index e3d8afba2..f5ed5fa13 100644 --- a/src/sat/bsat2/System.h +++ b/src/sat/bsat2/System.h @@ -22,7 +22,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #define Minisat_System_h #if defined(__linux__) -#include +//#include #endif #include "sat/bsat2/IntTypes.h" @@ -39,26 +39,35 @@ extern double memUsedPeak(); // Peak-memory in mega bytes (returns 0 for } +ABC_NAMESPACE_CXX_HEADER_END + //------------------------------------------------------------------------------------------------- // Implementation of inline functions: #if defined(_MSC_VER) || defined(__MINGW32__) #include +ABC_NAMESPACE_CXX_HEADER_START + static inline double Minisat::cpuTime(void) { return (double)clock() / CLOCKS_PER_SEC; } +ABC_NAMESPACE_CXX_HEADER_END + #else #include #include #include +ABC_NAMESPACE_CXX_HEADER_START + static inline double Minisat::cpuTime(void) { struct rusage ru; getrusage(RUSAGE_SELF, &ru); return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; } -#endif - ABC_NAMESPACE_CXX_HEADER_END #endif + + +#endif From b73f1030a654b0db551d08145ba097044e90106d Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 2 Mar 2024 17:03:42 -0800 Subject: [PATCH 111/151] More changes. --- src/sat/bsat2/module.make | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sat/bsat2/module.make b/src/sat/bsat2/module.make index ddd11b1b9..87cdc11ca 100644 --- a/src/sat/bsat2/module.make +++ b/src/sat/bsat2/module.make @@ -1,6 +1,4 @@ SRC += src/sat/bsat2/AbcApi.cpp \ - src/sat/bsat2/MainSat.cpp \ - src/sat/bsat2/MainSimp.cpp \ src/sat/bsat2/Options.cpp \ src/sat/bsat2/SimpSolver.cpp \ src/sat/bsat2/Solver.cpp \ From eb24d29777dcc01a726cc065445ef638e2d04264 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 2 Mar 2024 17:10:30 -0800 Subject: [PATCH 112/151] More changes. --- src/sat/bsat2/Queue.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sat/bsat2/Queue.h b/src/sat/bsat2/Queue.h index c2b3c64ad..8ff65b87b 100644 --- a/src/sat/bsat2/Queue.h +++ b/src/sat/bsat2/Queue.h @@ -23,10 +23,10 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "sat/bsat2/Vec.h" -namespace Minisat { - ABC_NAMESPACE_CXX_HEADER_START +namespace Minisat { + //================================================================================================= template From a747f46292ec06278d02fbb6bc785dbefba54d8c Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 2 Mar 2024 17:21:05 -0800 Subject: [PATCH 113/151] More changes to compile with g++. --- src/aig/gia/giaBound.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/aig/gia/giaBound.c b/src/aig/gia/giaBound.c index 7988d8655..916ed8e1f 100644 --- a/src/aig/gia/giaBound.c +++ b/src/aig/gia/giaBound.c @@ -172,13 +172,13 @@ void Bnd_ManMap( int iLit, int id, int spec ) if ( spec ) { - Vec_IntPush( Vec_PtrEntry( pBnd -> vBmiter2Spec, iLit >> 1), id ); + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry( pBnd -> vBmiter2Spec, iLit >> 1), id ); Vec_BitSetEntry( pBnd -> vSpec2Impl_phase, id, iLit & 1 ); } else { assert( (iLit & 1) == 0 ); - Vec_IntPush( Vec_PtrEntry( pBnd -> vBmiter2Impl, iLit >> 1), id ); + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry( pBnd -> vBmiter2Impl, iLit >> 1), id ); } } @@ -193,10 +193,10 @@ void Bnd_ManMerge( int id_repr, int id_obj, int phaseDiff ) Vec_Int_t *vIds_spec_repr, *vIds_impl_repr, *vIds_spec_obj, *vIds_impl_obj; - vIds_spec_repr = Vec_PtrEntry( vBmiter2Spec, id_repr ); - vIds_impl_repr = Vec_PtrEntry( vBmiter2Impl, id_repr ); - vIds_spec_obj = Vec_PtrEntry( vBmiter2Spec, id_obj ); - vIds_impl_obj = Vec_PtrEntry( vBmiter2Impl, id_obj ); + vIds_spec_repr = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, id_repr ); + vIds_impl_repr = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, id_repr ); + vIds_spec_obj = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, id_obj ); + vIds_impl_obj = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, id_obj ); Vec_IntForEachEntry( vIds_spec_obj, id, i ) { @@ -237,8 +237,8 @@ void Bnd_ManFinalizeMappings() for( i = 0; i < Vec_PtrSize(vBmiter2Spec); i++ ) { - vSpec = Vec_PtrEntry( vBmiter2Spec, i ); - vImpl = Vec_PtrEntry( vBmiter2Impl, i ); + vSpec = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, i ); + vImpl = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, i ); // create spec2impl if ( Vec_IntSize(vSpec) != 0 && Vec_IntSize(vImpl) != 0 ) @@ -282,8 +282,8 @@ void Bnd_ManPrintMappings() for( int j=0; j < Vec_PtrSize(vBmiter2Spec); j++ ) { printf("node %d: ", j); - vIds_spec = Vec_PtrEntry( vBmiter2Spec, j); - vIds_impl = Vec_PtrEntry( vBmiter2Impl, j); + vIds_spec = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, j); + vIds_impl = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, j); Vec_IntForEachEntry(vIds_spec, id, k) printf("%d ", id); printf("| "); @@ -599,7 +599,7 @@ void Bnd_ManFindBound( Gia_Man_t * p ) int cnt_extra = - Vec_PtrSize(vQ); while( Vec_PtrSize(vQ) > 0 ) { - pObj = Vec_PtrPop(vQ); + pObj = (Gia_Obj_t *)Vec_PtrPop(vQ); id = Gia_ObjId( p, pObj ); if ( Vec_IntEntry( vFlag, id ) == 1 ) continue; @@ -637,7 +637,7 @@ void Bnd_ManFindBound( Gia_Man_t * p ) } while( Vec_PtrSize(vQ) > 0 ) { - pObj = Vec_PtrPop(vQ); + pObj = (Gia_Obj_t *)Vec_PtrPop(vQ); id = Gia_ObjId( p, pObj ); if ( Vec_IntEntry( vFlag, id ) == 1 ) continue; @@ -684,7 +684,7 @@ void Bnd_ManFindBound( Gia_Man_t * p ) // traverse down from AI and unmatched BI while( Vec_PtrSize(vQ) > 0 ) { - pObj = Vec_PtrPop(vQ); + pObj = (Gia_Obj_t *)Vec_PtrPop(vQ); id = Gia_ObjId( p, pObj ); if ( Vec_IntEntry( vFlag, id ) == 2 ) continue; From bcf04fadb6f50755b7844cc36fe19e57eca47fd7 Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Mon, 4 Mar 2024 00:54:23 +0800 Subject: [PATCH 114/151] &brecover done --- src/aig/gia/gia.h | 2 + src/aig/gia/giaBound.c | 111 +++++++++++++++++++++--- src/base/abci/abc.c | 189 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 287 insertions(+), 15 deletions(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index e0654afda..5e8f5f36d 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1806,6 +1806,8 @@ extern void Bnd_ManFindBound( Gia_Man_t *p ); extern Gia_Man_t* Bnd_ManGenSpecOut( Gia_Man_t *p ); extern Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t *p ); extern Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPatch ); +extern Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ); +extern Gia_Man_t* Bnd_ManGenPatched2( Gia_Man_t *p, Gia_Man_t *pPatch ); extern void Bnd_ManSetEqOut( int eq ); extern void Bnd_ManSetEqRes( int eq ); extern void Bnd_ManPrintStats(); diff --git a/src/aig/gia/giaBound.c b/src/aig/gia/giaBound.c index 916ed8e1f..a3a298e35 100644 --- a/src/aig/gia/giaBound.c +++ b/src/aig/gia/giaBound.c @@ -572,7 +572,7 @@ void Bnd_ManFindBound( Gia_Man_t * p ) { if ( cnt < pBnd -> nBI ) { - Vec_IntPush( vBI, Gia_ObjId(p, pObj) ); + Vec_IntPush( vBI, Gia_ObjId(p, Gia_ObjFanin0(pObj) ) ); } else { @@ -884,27 +884,32 @@ Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t* p ) return pNew; } -void Bnd_AddNodeRec( Gia_Man_t *p, Gia_Man_t *pNew, Gia_Obj_t *pObj ) +void Bnd_AddNodeRec( Gia_Man_t *p, Gia_Man_t *pNew, Gia_Obj_t *pObj, int fSkipStrash ) { // TODO does this mean constant zero node? if ( pObj -> Value != ~0 ) return; for( int i = 0; i < Gia_ObjFaninNum(p, pObj); i++ ) { - Bnd_AddNodeRec( p, pNew, Gia_ObjFanin(pObj, i) ); + Bnd_AddNodeRec( p, pNew, Gia_ObjFanin(pObj, i), fSkipStrash ); } if ( Gia_ObjIsAnd(pObj) ) { - pObj -> Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( fSkipStrash ) + { + if ( Gia_ObjIsBuf(pObj) ) pObj -> Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else pObj -> Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + else + { + pObj -> Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } } else { - if ( Gia_ObjIsCi(pObj) ) - { - printf("Ci with value 0 encountered (id = %d)\n", Gia_ObjId(p, pObj) ); - } assert( Gia_ObjIsCo(pObj) ); + // if ( Gia_ObjIsCi(pObj) ) printf("Ci with value ~0 encountered (id = %d)\n", Gia_ObjId(p, pObj) ); pObj -> Value = Gia_ObjFanin0Copy(pObj); } } @@ -963,7 +968,7 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat for ( i = 0; i < Vec_IntSize( pBnd -> vEI_spec ); i++ ) { pObj = Gia_ManCo(pOut, i + Gia_ManCoNum(pSpec) ); - Bnd_AddNodeRec( pOut, pNew, pObj ); + Bnd_AddNodeRec( pOut, pNew, pObj, 0 ); // set Spec EI Gia_ManObj( pSpec, Vec_IntEntry(pBnd -> vEI_spec, i) ) -> Value = pObj -> Value; @@ -976,7 +981,7 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat Vec_IntForEachEntry( pBnd -> vBI, id, i ) { pObj = Gia_ManObj( pSpec, id ); - Bnd_AddNodeRec( pSpec, pNew, pObj ); + Bnd_AddNodeRec( pSpec, pNew, pObj, 0 ); // set patch bi Gia_ManObj( pPatch, Vec_IntEntry( vBI_patch, i) ) -> Value = pObj -> Value; @@ -989,7 +994,7 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat Vec_IntForEachEntry( vBO_patch, id, i ) { pObj = Gia_ManObj( pPatch, id ); - Bnd_AddNodeRec( pPatch, pNew, pObj ); + Bnd_AddNodeRec( pPatch, pNew, pObj, 0 ); // set spec bo Gia_ManObj( pSpec, Vec_IntEntry( pBnd -> vBO, i) ) -> Value = pObj -> Value; @@ -1002,7 +1007,7 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat Vec_IntForEachEntry( pBnd -> vEO_spec, id, i ) { pObj = Gia_ManObj( pSpec, id ); - Bnd_AddNodeRec( pSpec, pNew, pObj ); + Bnd_AddNodeRec( pSpec, pNew, pObj, 0 ); // set impl EO (PI) Gia_ManCi( pOut, i + Gia_ManCiNum(pSpec) ) -> Value = pObj -> Value; @@ -1015,7 +1020,7 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat for ( i = 0; i < Gia_ManCoNum(pSpec); i++ ) { pObj = Gia_ManCo( pOut, i ); - Bnd_AddNodeRec( pOut, pNew, pObj ); + Bnd_AddNodeRec( pOut, pNew, pObj, 0 ); Gia_ManAppendCo( pNew, pObj->Value ); // printf(" %d",pObj -> Value); } @@ -1036,7 +1041,87 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat return pNew; } +Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, id; + + pNew = Gia_ManStart( Gia_ManObjNum(pOut) + Gia_ManObjNum( pSpec ) ); + pNew -> pName = ABC_ALLOC( char, strlen(pOut->pName)+3); + sprintf( pNew -> pName, "%s_p", pOut -> pName ); + + Gia_ManFillValue(pOut); + Gia_ManFillValue(pSpec); + Gia_ManConst0(pOut)->Value = 0; + Gia_ManConst0(pSpec)->Value = 0; + + + // add Impl (real) PI + for ( i = 0; i < Gia_ManCiNum(pSpec); i++ ) + { + pObj = Gia_ManCi(pOut, i); + pObj -> Value = Gia_ManAppendCi( pNew ); + } + + // add Impl EI to CI + printf("adding EI to CI in Impl\n"); + for ( i = 0; i < Vec_IntSize( pBnd -> vEI_spec ); i++ ) + { + pObj = Gia_ManCo(pOut, i + Gia_ManCoNum(pSpec) ); + Bnd_AddNodeRec( pOut, pNew, pObj, 1 ); + + // set Spec EI + Gia_ManObj( pSpec, Vec_IntEntry(pBnd -> vEI_spec, i) ) -> Value = pObj -> Value; + printf(" %d",pObj -> Value); + } + printf("\n"); + + // add Spec EO to EI + // add BI -> BO -> EO to maintain the order of bufs + Vec_IntForEachEntry( pBnd -> vBI, id, i ) + { + pObj = Gia_ManObj( pSpec, id ); + Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); + } + Vec_IntForEachEntry( pBnd -> vBO, id, i ) + { + pObj = Gia_ManObj( pSpec, id ); + Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); + } + Vec_IntForEachEntry( pBnd -> vEO_spec, id, i ) + { + pObj = Gia_ManObj( pSpec, id ); + Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); + + // set impl EO (PI) + Gia_ManCi( pOut, i + Gia_ManCiNum(pSpec) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + // add Impl (real) PO to EO + // printf("adding CO to EO in Impl\n"); + for ( i = 0; i < Gia_ManCoNum(pSpec); i++ ) + { + pObj = Gia_ManCo( pOut, i ); + Bnd_AddNodeRec( pOut, pNew, pObj, 1 ); + Gia_ManAppendCo( pNew, pObj->Value ); + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + + // clean up + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + pBnd -> nNode_patched = Gia_ManAndNum( pNew ); + pBnd -> status = 3; + + return pNew; +} diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 9a558c2da..60aa58c08 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -599,6 +599,7 @@ static int Abc_CommandAbc9ProdAdd ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9AddFlop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9BMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenHie ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9BRecover ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9StrEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1381,6 +1382,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&addflop", Abc_CommandAbc9AddFlop, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmiter", Abc_CommandAbc9BMiter, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&gen_hie", Abc_CommandAbc9GenHie, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&brecover", Abc_CommandAbc9BRecover, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&str_eco", Abc_CommandAbc9StrEco, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); @@ -52092,6 +52094,191 @@ usage: ***********************************************************************/ extern Bnd_Man_t* pBnd; +int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); + extern void Cec4_ManSetParams( Cec_ParFra_t * pPars ); + extern Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ); + Gia_Man_t *pSpec, *pImpl_out = 0, *pSpec_out = 0, *pMiter, *pPatched, *pTemp, *pBmiter; + char * FileName = NULL; + FILE * pFile = NULL; + int c, fVerbose = 0, success = 1; + + // params + Gps_Par_t Pars, * pPars = &Pars; + memset( pPars, 0, sizeof(Gps_Par_t) ); + Cec_ParCec_t ParsCec, *pParsCec = &ParsCec; + Cec_ManCecSetDefaultParams( pParsCec ); + Cec_ParFra_t ParsFra, *pParsFra = &ParsFra; + Cec4_ManSetParams( pParsFra ); + pParsFra -> fBMiterInfo = 1; + + // parse options + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9BRecover(): There is no AIG.\n" ); + return 0; + } + if ( argc != globalUtilOptind + 1 ) + { + printf("%d\n", argc-globalUtilOptind); + Abc_Print( -1, "Abc_CommandAbc9BRecover(): AIG should be given on the command line.\n" ); + return 0; + } + + // read spec + FileName = argv[globalUtilOptind]; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", ".blif", ".pla", ".eqn", ".bench" )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pSpec = Gia_AigerRead( FileName, 0, 1, 0 ); + if ( pSpec == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9BRecover(): Cannot read the file name on the command line.\n" ); + return 0; + } + if ( Gia_ManBufNum(pSpec) == 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9BRecover(): The given spec should be hierarchical.\n" ); + Gia_ManStop(pSpec); + return 0; + } + + // start boundary manager + pBnd = Bnd_ManStart( pSpec, pAbc->pGia ); + + // verify if spec eq impl + pMiter = Gia_ManMiter( pAbc->pGia, pSpec, 0, 1, 0, 0, 0 ); + if ( !Cec_ManVerify( pMiter, pParsCec ) ) + { + Abc_Print( -1, "Abc_CommandAbc9BRecover(): The given spec is not equivalent to current impl.\n" ); + success = 0; + } + Gia_ManStop(pMiter); + + // check boundary + if ( success ) + { + if ( 0 == Bnd_ManCheckBound( pSpec ) ) + { + Abc_Print( -1, "Abc_CommandAbc9BRecover(): The given spec has invalid boundary.\n" ); + success = 0; + } + } + + if ( success ) + { + // create bmiter, run fraig, record mapping + pBmiter = Gia_ManBoundaryMiter( pSpec, pAbc->pGia, 0 ); + pTemp = Cec4_ManSimulateTest( pBmiter, pParsFra ); + Gia_ManStop(pBmiter); + Gia_ManStop(pTemp); + + // find + Bnd_ManFindBound( pSpec ); + + // create spec_out and + pSpec_out = Bnd_ManGenSpecOut( pSpec ); + if ( !pSpec_out ) success = 0; + pImpl_out = Bnd_ManGenImplOut( pAbc->pGia ); + if ( !pImpl_out ) success = 0; + + // Gia_AigerWrite( pSpec_out, "spec_out.aig", 0, 0, 0 ); + // Gia_AigerWrite( pImpl_out, "impl_out.aig", 0, 0, 0 ); + // Gia_ManPrintStats( pSpec_out, pPars ); + // Gia_ManPrintStats( pImpl_out, pPars ); + } + + if ( success ) + { + + // check if spec_out and imnpl_out are equivalent + printf("Checking the equivalence of spec_out and impl_out\n"); + pMiter = Gia_ManMiter( pSpec_out, pImpl_out, 0, 1, 0, 0, 0 ); + Bnd_ManSetEqOut( Cec_ManVerify( pMiter, pParsCec ) ); + Gia_ManStop( pMiter ); + + // generate patched impl + printf("Generating patched impl\n"); + pPatched = Bnd_ManGenPatched1( pImpl_out, pSpec ); + + // // generate patched spec just for debugging + // printf("Generating patched spec\n"); + // pTemp = Bnd_ManGenPatched( pSpec_out, pAbc->pGia, pPatch ); + // printf("Checking the equivalence of patched spec and patched impl\n"); + // pMiter = Gia_ManMiter( pTemp, pPatched, 0, 1, 0, 0, 0 ); + // Cec_ManVerify( pMiter, pParsCec ); + // Gia_ManStop( pMiter ); + // printf("Checking the equivalence of patched spec and patch\n"); + // pMiter = Gia_ManMiter( pTemp, pPatch, 0, 1, 0, 0, 0 ); + // Cec_ManVerify( pMiter, pParsCec ); + // Gia_ManStop( pMiter ); + + // Gia_ManStop( pTemp ); + + // check if patched is equiv to spec + printf("Checking the equivalence of patched impl and patch\n"); + pMiter = Gia_ManMiter( pSpec, pPatched, 0, 1, 0, 0, 0 ); + Bnd_ManSetEqRes( Cec_ManVerify( pMiter, pParsCec ) ); + Gia_ManStop( pMiter ); + + } + + Bnd_ManPrintStats(); + + Gia_ManStop( pSpec ); + if ( pSpec_out ) Gia_ManStop( pSpec_out ); + if ( pImpl_out ) Gia_ManStop( pImpl_out ); + if ( success ) + { + Abc_FrameUpdateGia( pAbc, pPatched ); + } + Bnd_ManStop(); + + return 0; + +usage: + Abc_Print( -2, "usage: &str_eco -I [-vh] \n" ); + Abc_Print( -2, "\t SAT-sweeping-based ECO\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the implementation aig. (should be equivalent to spec)\n"); + Abc_Print( -2, "\t : the modified spec. (should be a hierarchical AIG)\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); @@ -52111,8 +52298,6 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) Cec4_ManSetParams( pParsFra ); pParsFra -> fBMiterInfo = 1; - // TODO: save return value and return at the end of the function - // parse options Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) From bfbec7121121577924273574643800d8d94bcb5f Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Mon, 4 Mar 2024 09:36:35 +0800 Subject: [PATCH 115/151] &stc_eco and &brecover done --- src/aig/gia/gia.h | 11 ++- src/aig/gia/giaBound.c | 190 +++++++++++++++++++++++++++++++++-------- src/base/abci/abc.c | 178 ++++++++++++-------------------------- 3 files changed, 216 insertions(+), 163 deletions(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 5e8f5f36d..f12ab35df 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1793,21 +1793,26 @@ extern int Tas_ManSolveArray( Tas_Man_t * p, Vec_Ptr_t * vObjs ) /*=== giaBound.c ===========================================================*/ typedef struct Bnd_Man_t_ Bnd_Man_t; -extern Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl ); +extern Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl, int fVerbose ); extern void Bnd_ManStop(); + +// getter +extern int Bnd_ManGetNInternal(); +extern int Bnd_ManGetNExtra(); + //for fraig extern void Bnd_ManMap( int iLit, int id, int spec ); extern void Bnd_ManMerge( int id1, int id2, int phaseDiff ); extern void Bnd_ManFinalizeMappings(); extern void Bnd_ManPrintMappings(); // for eco -extern int Bnd_ManCheckBound( Gia_Man_t *p ); +extern int Bnd_ManCheckBound( Gia_Man_t *p, int fVerbose ); extern void Bnd_ManFindBound( Gia_Man_t *p ); extern Gia_Man_t* Bnd_ManGenSpecOut( Gia_Man_t *p ); extern Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t *p ); extern Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPatch ); extern Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ); -extern Gia_Man_t* Bnd_ManGenPatched2( Gia_Man_t *p, Gia_Man_t *pPatch ); +extern Gia_Man_t* Bnd_ManGenPatched2( Gia_Man_t *pImpl, Gia_Man_t *pPatch, int fSkiptStrash, int fVerbose ); extern void Bnd_ManSetEqOut( int eq ); extern void Bnd_ManSetEqRes( int eq ); extern void Bnd_ManPrintStats(); diff --git a/src/aig/gia/giaBound.c b/src/aig/gia/giaBound.c index a3a298e35..a420b818d 100644 --- a/src/aig/gia/giaBound.c +++ b/src/aig/gia/giaBound.c @@ -29,6 +29,7 @@ struct Bnd_Man_t_ int nNode_patched; int status; // 0: init 1: boundary found 2: out generated 3: patched generated + int fVerbose; int combLoop_spec; int combLoop_impl; @@ -57,7 +58,7 @@ struct Bnd_Man_t_ }; -Bnd_Man_t* pBnd; +Bnd_Man_t* pBnd = 0; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -78,7 +79,7 @@ void Bnd_ManSetEqRes( int eq ) { pBnd -> eq_res = eq;} ***********************************************************************/ -Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl ) +Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl, int fVerbose ) { int i; Bnd_Man_t* p = ABC_CALLOC( Bnd_Man_t, 1 ); @@ -113,6 +114,8 @@ Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl ) p -> nNode_patched = 0; p -> status = 0; + p -> fVerbose = fVerbose; + p -> combLoop_spec = 0; p -> combLoop_impl = 0; p -> eq_out = 0; @@ -166,6 +169,8 @@ void Bnd_ManStop() ABC_FREE( pBnd ); } +int Bnd_ManGetNInternal() { assert(pBnd); return pBnd -> nInternal; } +int Bnd_ManGetNExtra() { assert(pBnd); return pBnd -> nExtra; } void Bnd_ManMap( int iLit, int id, int spec ) { @@ -370,23 +375,22 @@ void Bnd_ManPrintStats() Description [check if the given boundary is valid. Return 0 if the boundary is invalid. Return k if the boundary is valid and - there're k boundary inputs. ] + there're k boundary inputs. + Can be called even if Bnd_Man_t is not created] SideEffects [] SeeAlso [] ***********************************************************************/ -int Bnd_ManCheckBound( Gia_Man_t * p ) +int Bnd_ManCheckBound( Gia_Man_t * p, int fVerbose ) { int i; Gia_Obj_t *pObj; int valid = 1; - pBnd -> nBI = 0; - pBnd -> nBO = 0; - pBnd -> nInternal = 0; + int nBI = 0, nBO = 0, nInternal = 0; - printf( "Checking boundary... \n"); + if ( fVerbose ) printf( "Checking boundary... \n"); Vec_Int_t *vPath; vPath = Vec_IntAlloc( Gia_ManObjNum(p) ); @@ -417,7 +421,7 @@ int Bnd_ManCheckBound( Gia_Man_t * p ) if ( path == 1 ) // boundary input { // TODO: record BIs here since they may not be in the first n buffers - pBnd -> nBO ++; + nBO ++; } } else if ( Gia_ObjFaninNum( p, pObj ) >= 1 ) @@ -431,7 +435,7 @@ int Bnd_ManCheckBound( Gia_Man_t * p ) if ( path == 2 ) // inside boundary { // TODO: record BIs here since they may not be in the first n buffers - pBnd -> nInternal ++; + nInternal ++; } } else // PI or const, check validity @@ -445,20 +449,33 @@ int Bnd_ManCheckBound( Gia_Man_t * p ) } } - pBnd -> nBI = Gia_ManBufNum(p) - pBnd -> nBO; + nBI = Gia_ManBufNum(p) - nBO; if ( !valid ) { printf("invalid boundary\n"); return 0; } + else if ( nBI == 0 ) + { + printf("no boundary\n"); + return 0; + } else { - printf("valid boundary ("); - printf("#BI = %d\t#BO = %d\t", pBnd -> nBI, Gia_ManBufNum(p)- pBnd -> nBI); - printf("#Internal = %d)\n", pBnd -> nInternal ); - assert( pBnd -> nBI > 0 ); - return pBnd -> nBI; + if ( fVerbose ) + { + printf("valid boundary ("); + printf("#BI = %d\t#BO = %d\t", nBI, Gia_ManBufNum(p)- nBI); + printf("#Internal = %d)\n", nInternal ); + } + if ( pBnd ) + { + pBnd -> nBI = nBI; + pBnd -> nBO = nBO; + pBnd -> nInternal = nInternal; + } + return nBI; } } @@ -593,7 +610,7 @@ void Bnd_ManFindBound( Gia_Man_t * p ) Vec_IntPush(vEO_spec, id); } } - printf("%d BO doesn't match. ", Vec_PtrSize(vQ) ); + if ( pBnd -> fVerbose ) printf("%d BO doesn't match. ", Vec_PtrSize(vQ) ); pBnd -> nBO_miss = Vec_PtrSize(vQ); int cnt_extra = - Vec_PtrSize(vQ); @@ -622,7 +639,7 @@ void Bnd_ManFindBound( Gia_Man_t * p ) } } // printf("%d AO found with %d extra nodes\n", Vec_IntSize(vAO) , cnt_extra ); - printf("%d AO found\n", Vec_IntSize(vAO) ); + if ( pBnd -> fVerbose ) printf("%d AO found\n", Vec_IntSize(vAO) ); // mark TFOC of BO with flag 1 to prevent them from being selected into EI @@ -665,7 +682,7 @@ void Bnd_ManFindBound( Gia_Man_t * p ) Vec_IntPush(vEI_spec, id); } } - printf("%d BI doesn't match. ", Vec_PtrSize(vQ) ); + if ( pBnd -> fVerbose ) printf("%d BI doesn't match. ", Vec_PtrSize(vQ) ); pBnd -> nBI_miss = Vec_PtrSize(vQ); cnt_extra -= Vec_PtrSize(vQ); @@ -708,7 +725,7 @@ void Bnd_ManFindBound( Gia_Man_t * p ) Vec_IntSetEntry( vFlag, id, 2 ); } - printf("%d AI found with %d extra nodes in total\n", Vec_IntSize(vAI) , cnt_extra ); + if ( pBnd -> fVerbose ) printf("%d AI found with %d extra nodes in total\n", Vec_IntSize(vAI) , cnt_extra ); pBnd -> nExtra = cnt_extra; @@ -738,8 +755,11 @@ void Bnd_ManFindBound( Gia_Man_t * p ) // print pBnd -> status = 1; - printf("#EI = %d\t#EO = %d\t#Extra Node = %d\n", Vec_IntSize(vEI_spec) , Vec_IntSize(vEO_spec), cnt_extra ); - Bnd_ManPrintBound(); + if ( pBnd -> fVerbose ) + { + printf("#EI = %d\t#EO = %d\t#Extra Node = %d\n", Vec_IntSize(vEI_spec) , Vec_IntSize(vEO_spec), cnt_extra ); + Bnd_ManPrintBound(); + } // check boundary has comb loop if ( !Bnd_ManCheckExtBound( p, vEI_spec, vEO_spec ) ) @@ -869,15 +889,15 @@ Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec } -Gia_Man_t* Bnd_ManGenSpecOut( Gia_Man_t* p ) +Gia_Man_t* Bnd_ManGenSpecOut( Gia_Man_t* p ) { - printf("Generating spec_out with given boundary.\n"); + if ( pBnd -> fVerbose ) printf("Generating spec_out with given boundary.\n"); Gia_Man_t *pNew = Bnd_ManCutBoundary( p, pBnd->vEI_spec, pBnd->vEO_spec, 0, 0 ); return pNew; } -Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t* p ) +Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t* p) { - printf("Generating impl_out with given boundary.\n"); + if ( pBnd -> fVerbose ) printf("Generating impl_out with given boundary.\n"); Gia_Man_t *pNew = Bnd_ManCutBoundary( p, pBnd->vEI_impl, pBnd->vEO_impl, pBnd->vEI_phase, pBnd->vEO_phase ); if ( pNew ) pBnd -> status = 2; else pBnd -> combLoop_impl = 1; @@ -1066,7 +1086,7 @@ Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ) } // add Impl EI to CI - printf("adding EI to CI in Impl\n"); + // printf("adding EI to CI in Impl\n"); for ( i = 0; i < Vec_IntSize( pBnd -> vEI_spec ); i++ ) { pObj = Gia_ManCo(pOut, i + Gia_ManCoNum(pSpec) ); @@ -1074,20 +1094,24 @@ Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ) // set Spec EI Gia_ManObj( pSpec, Vec_IntEntry(pBnd -> vEI_spec, i) ) -> Value = pObj -> Value; - printf(" %d",pObj -> Value); + // printf(" %d",pObj -> Value); } - printf("\n"); + // printf("\n"); // add Spec EO to EI // add BI -> BO -> EO to maintain the order of bufs - Vec_IntForEachEntry( pBnd -> vBI, id, i ) + // Vec_IntForEachEntry( pBnd -> vBI, id, i ) + // { + // pObj = Gia_ManObj( pSpec, id ); + // Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); + // } + // Vec_IntForEachEntry( pBnd -> vBO, id, i ) + // { + // pObj = Gia_ManObj( pSpec, id ); + // Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); + // } + Gia_ManForEachBuf( pSpec, pObj, i ) { - pObj = Gia_ManObj( pSpec, id ); - Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); - } - Vec_IntForEachEntry( pBnd -> vBO, id, i ) - { - pObj = Gia_ManObj( pSpec, id ); Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); } Vec_IntForEachEntry( pBnd -> vEO_spec, id, i ) @@ -1123,6 +1147,100 @@ Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ) return pNew; } +Gia_Man_t* Bnd_ManGenPatched2( Gia_Man_t *pImpl, Gia_Man_t *pPatch, int fSkipStrash, int fVerbose ) +{ + + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, nBI, nBI_patch, cnt; + Vec_Int_t* vLit; + + + // check boundary first + nBI = Bnd_ManCheckBound( pImpl, fVerbose ); + nBI_patch = Bnd_ManCheckBound( pPatch, fVerbose ); + if ( 0 == nBI_patch || Gia_ManBufNum(pImpl) != Gia_ManBufNum(pPatch) || nBI != nBI_patch ) + { + Abc_Print( -1, "Abc_CommandAbc9StrEco(): The given boundary is invalid.\n" ); + return 0; + } + + // prepare new network + pNew = Gia_ManStart( Gia_ManObjNum(pImpl) + Gia_ManObjNum( pPatch ) ); + pNew -> pName = ABC_ALLOC( char, strlen(pImpl->pName)+3); + sprintf( pNew -> pName, "%s_p", pImpl -> pName ); + if ( !fSkipStrash ) + { + Gia_ManHashAlloc( pNew ); + } + Gia_ManFillValue(pImpl); + Gia_ManFillValue(pPatch); + Gia_ManConst0(pImpl)->Value = 0; + Gia_ManConst0(pPatch)->Value = 0; + + vLit = Vec_IntAlloc( Gia_ManBufNum(pImpl) ); + + // add Impl (real) CI + Gia_ManForEachCi( pImpl, pObj, i ) + { + pObj -> Value = Gia_ManAppendCi( pNew ); + } + + // add Impl BI to CI + cnt = 0; + Gia_ManForEachBuf( pImpl, pObj, i ) + { + Bnd_AddNodeRec( pImpl, pNew, pObj, fSkipStrash ); + Vec_IntPush( vLit, pObj -> Value ); + cnt ++; + if ( cnt >= nBI ) break; + } + + // set BI in patch + // add patch BO to BI + cnt = 0; + Gia_ManForEachBuf( pPatch, pObj, i ) + { + if ( cnt < nBI ) + { + pObj -> Value = Vec_IntEntry( vLit, cnt ); + } + else + { + Bnd_AddNodeRec( pPatch, pNew, pObj, fSkipStrash ); + Vec_IntPush( vLit, pObj -> Value ); + } + cnt ++; + if ( cnt == nBI ) Vec_IntClear( vLit ); + } + + // set BO in impl + cnt = 0; + Gia_ManForEachBuf( pImpl, pObj, i ) + { + cnt ++; + if ( cnt <= nBI) continue; + pObj -> Value = Vec_IntEntry( vLit, cnt-nBI-1 ); + } + + // add impl CO to BO + Gia_ManForEachCo( pImpl, pObj, i ) + { + Bnd_AddNodeRec( pImpl, pNew, pObj, fSkipStrash ); + Gia_ManAppendCo( pNew, pObj -> Value ); + } + + // clean up + if ( !fSkipStrash ) + { + Gia_ManHashStop( pNew ); + } + Vec_IntFree( vLit ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + return pNew; +} //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 60aa58c08..d6363a0cc 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -52099,7 +52099,7 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) extern Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); extern void Cec4_ManSetParams( Cec_ParFra_t * pPars ); extern Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ); - Gia_Man_t *pSpec, *pImpl_out = 0, *pSpec_out = 0, *pMiter, *pPatched, *pTemp, *pBmiter; + Gia_Man_t *pSpec, *pImpl_out = 0, *pSpec_out = 0, *pMiter, *pPatched = 0, *pTemp, *pBmiter; char * FileName = NULL; FILE * pFile = NULL; int c, fVerbose = 0, success = 1; @@ -52165,7 +52165,7 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) } // start boundary manager - pBnd = Bnd_ManStart( pSpec, pAbc->pGia ); + pBnd = Bnd_ManStart( pSpec, pAbc->pGia, fVerbose ); // verify if spec eq impl pMiter = Gia_ManMiter( pAbc->pGia, pSpec, 0, 1, 0, 0, 0 ); @@ -52179,7 +52179,7 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) // check boundary if ( success ) { - if ( 0 == Bnd_ManCheckBound( pSpec ) ) + if ( 0 == Bnd_ManCheckBound( pSpec, fVerbose ) ) { Abc_Print( -1, "Abc_CommandAbc9BRecover(): The given spec has invalid boundary.\n" ); success = 0; @@ -52209,17 +52209,24 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) // Gia_ManPrintStats( pImpl_out, pPars ); } - if ( success ) + if ( !success ) + { + printf("Abc_CommandAbc9BRecover(): The generated boundary is invalid. The circuit is not changed.\n"); + } + else { // check if spec_out and imnpl_out are equivalent - printf("Checking the equivalence of spec_out and impl_out\n"); - pMiter = Gia_ManMiter( pSpec_out, pImpl_out, 0, 1, 0, 0, 0 ); - Bnd_ManSetEqOut( Cec_ManVerify( pMiter, pParsCec ) ); - Gia_ManStop( pMiter ); + if ( fVerbose ) + { + printf("Checking the equivalence of spec_out and impl_out\n"); + pMiter = Gia_ManMiter( pSpec_out, pImpl_out, 0, 1, 0, 0, 0 ); + Bnd_ManSetEqOut( Cec_ManVerify( pMiter, pParsCec ) ); + Gia_ManStop( pMiter ); + } // generate patched impl - printf("Generating patched impl\n"); + if ( fVerbose ) printf("Generating patched impl\n"); pPatched = Bnd_ManGenPatched1( pImpl_out, pSpec ); // // generate patched spec just for debugging @@ -52237,29 +52244,35 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) // Gia_ManStop( pTemp ); // check if patched is equiv to spec - printf("Checking the equivalence of patched impl and patch\n"); + if ( fVerbose ) printf("Checking the equivalence of patched impl and spec\n"); pMiter = Gia_ManMiter( pSpec, pPatched, 0, 1, 0, 0, 0 ); - Bnd_ManSetEqRes( Cec_ManVerify( pMiter, pParsCec ) ); + success = Cec_ManVerify( pMiter, pParsCec ); + Bnd_ManSetEqRes( success ); + if ( !success ) + { + printf("Failed. The generated AIG is not equivalent.\n"); + } Gia_ManStop( pMiter ); } - Bnd_ManPrintStats(); + if ( fVerbose ) Bnd_ManPrintStats(); Gia_ManStop( pSpec ); if ( pSpec_out ) Gia_ManStop( pSpec_out ); if ( pImpl_out ) Gia_ManStop( pImpl_out ); if ( success ) { - Abc_FrameUpdateGia( pAbc, pPatched ); + printf("Success. The generated hierarchical impl is equivalent. (box size: %d -> %d)\n", Bnd_ManGetNInternal(), Bnd_ManGetNInternal() + Bnd_ManGetNExtra() ); } + if (pPatched) Abc_FrameUpdateGia( pAbc, pPatched ); Bnd_ManStop(); return 0; usage: - Abc_Print( -2, "usage: &str_eco -I [-vh] \n" ); - Abc_Print( -2, "\t SAT-sweeping-based ECO\n" ); + Abc_Print( -2, "usage: &brecover -I [-vh] \n" ); + Abc_Print( -2, "\t recover boundary using SAT-Sweeping\n" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the implementation aig. (should be equivalent to spec)\n"); @@ -52283,11 +52296,11 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); extern void Cec4_ManSetParams( Cec_ParFra_t * pPars ); - extern Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ); - Gia_Man_t *pImpl, *pImpl_out = 0, *pSpec_out = 0, *pMiter, *pPatch, *pPatched, *pTemp, *pBmiter;; + Gia_Man_t *pMiter, *pPatch, *pPatched; char * FileName = NULL; FILE * pFile = NULL; - int c, fVerbose = 0, success = 1; + int c, success = 1; + int fVerbose = 0, fSkipStrash = 0; // params Gps_Par_t Pars, * pPars = &Pars; @@ -52300,13 +52313,16 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) // parse options Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "vsh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; + case 's': + fSkipStrash ^= 1; + break; case 'h': goto usage; default: @@ -52318,33 +52334,15 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9StrEco(): There is no AIG.\n" ); return 0; } - if ( argc != globalUtilOptind + 2 ) + if ( argc != globalUtilOptind + 1 ) { printf("%d\n", argc-globalUtilOptind); Abc_Print( -1, "Abc_CommandAbc9StrEco(): AIG should be given on the command line.\n" ); return 0; } - // read impl - FileName = argv[globalUtilOptind]; - if ( (pFile = fopen( FileName, "r" )) == NULL ) - { - Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); - if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", ".blif", ".pla", ".eqn", ".bench" )) ) - Abc_Print( 1, "Did you mean \"%s\"?", FileName ); - Abc_Print( 1, "\n" ); - return 1; - } - fclose( pFile ); - pImpl = Gia_AigerRead( FileName, 0, 0, 0 ); - if ( pImpl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc9StrEco(): Cannot read the file name on the command line.\n" ); - return 0; - } - // read patch - FileName = argv[globalUtilOptind+1]; + FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); @@ -52361,98 +52359,29 @@ int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } - // start boundary manager - pBnd = Bnd_ManStart( pAbc->pGia, pImpl ); + // generate patched impl + if ( fVerbose ) printf("Generating patched impl\n"); + pPatched = Bnd_ManGenPatched2( pAbc->pGia, pPatch, fSkipStrash, fVerbose ); - // verify if spec eq impl - pMiter = Gia_ManMiter( pAbc->pGia, pImpl, 0, 1, 0, 0, 0 ); - if ( !Cec_ManVerify( pMiter, pParsCec ) ) + if ( pPatched ) { - Abc_Print( -1, "Abc_CommandAbc9StrEco(): The given impl is not equivalent to spec.\n" ); - success = 0; - } - Gia_ManStop(pMiter); - - // check boundary - if ( success ) - { - if ( 0 == Bnd_ManCheckBound( pPatch ) || 0 == Bnd_ManCheckBound( pAbc -> pGia ) ) - { - Abc_Print( -1, "Abc_CommandAbc9StrEco(): The given boundary is invalid.\n" ); - success = 0; - } - } - - if ( success ) - { - // create bmiter, run fraig - pBmiter = Gia_ManBoundaryMiter( pAbc -> pGia, pImpl, 0 ); - pTemp = Cec4_ManSimulateTest( pBmiter, pParsFra ); - Gia_ManStop(pBmiter); - Gia_ManStop(pTemp); - - // find - Bnd_ManFindBound( pAbc -> pGia ); - - // create spec_out and - pSpec_out = Bnd_ManGenSpecOut( pAbc -> pGia ); - if ( !pSpec_out ) success = 0; - pImpl_out = Bnd_ManGenImplOut( pImpl ); - if ( !pImpl_out ) success = 0; - - // Gia_AigerWrite( pSpec_out, "spec_out.aig", 0, 0, 0 ); - // Gia_AigerWrite( pImpl_out, "impl_out.aig", 0, 0, 0 ); - // Gia_ManPrintStats( pSpec_out, pPars ); - // Gia_ManPrintStats( pImpl_out, pPars ); - - } - - if ( success ) - { - - // check if spec_out and imnpl_out are equivalent - printf("Checking the equivalence of spec_out and impl_out\n"); - pMiter = Gia_ManMiter( pSpec_out, pImpl_out, 0, 1, 0, 0, 0 ); - Bnd_ManSetEqOut( Cec_ManVerify( pMiter, pParsCec ) ); - Gia_ManStop( pMiter ); - - // generate patched impl - printf("Generating patched impl\n"); - pPatched = Bnd_ManGenPatched( pImpl_out, pAbc->pGia, pPatch ); - - // generate patched spec just for debugging - printf("Generating patched spec\n"); - pTemp = Bnd_ManGenPatched( pSpec_out, pAbc->pGia, pPatch ); - printf("Checking the equivalence of patched spec and patched impl\n"); - pMiter = Gia_ManMiter( pTemp, pPatched, 0, 1, 0, 0, 0 ); - Cec_ManVerify( pMiter, pParsCec ); - Gia_ManStop( pMiter ); - printf("Checking the equivalence of patched spec and patch\n"); - pMiter = Gia_ManMiter( pTemp, pPatch, 0, 1, 0, 0, 0 ); - Cec_ManVerify( pMiter, pParsCec ); - Gia_ManStop( pMiter ); - - Gia_ManStop( pTemp ); - // check if patched is equiv to patch - printf("Checking the equivalence of patched impl and patch\n"); + if ( fVerbose ) printf("Checking the equivalence of patched impl and patch\n"); pMiter = Gia_ManMiter( pPatch, pPatched, 0, 1, 0, 0, 0 ); - Bnd_ManSetEqRes( Cec_ManVerify( pMiter, pParsCec ) ); + success = Cec_ManVerify( pMiter, pParsCec ); + if( !success ) + { + printf("Failed. The patched circuit is not equivalent.\n"); + } Gia_ManStop( pMiter ); - - } - - Bnd_ManPrintStats(); - - Gia_ManStop( pImpl ); - Gia_ManStop( pPatch ); - if ( pSpec_out ) Gia_ManStop( pSpec_out ); - if ( pImpl_out ) Gia_ManStop( pImpl_out ); - if ( success ) - { Abc_FrameUpdateGia( pAbc, pPatched ); } - Bnd_ManStop(); + + Gia_ManStop( pPatch ); + if ( success ) + { + printf("Success. The patched circuit is equivalent.\n"); + } return 0; @@ -52460,6 +52389,7 @@ usage: Abc_Print( -2, "usage: &str_eco -I [-vh] \n" ); Abc_Print( -2, "\t SAT-sweeping-based ECO\n" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles skipping structural hash [default = %s]\n", fSkipStrash? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the implementation aig. (should be equivalent to spec)\n"); Abc_Print( -2, "\t : the modified spec. (should be a hierarchical AIG)\n"); From d87b1cd543efaf724255da2ab74ca959bc75f920 Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Mon, 4 Mar 2024 10:16:14 +0800 Subject: [PATCH 116/151] fixed some warnings in bsat2 --- src/sat/bsat2/Options.cpp | 2 ++ src/sat/bsat2/Options.h | 2 +- src/sat/bsat2/SimpSolver.cpp | 4 ++++ src/sat/bsat2/Solver.cpp | 4 ++-- src/sat/bsat2/Vec.h | 1 - 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/sat/bsat2/Options.cpp b/src/sat/bsat2/Options.cpp index f14059f67..a0a3817d8 100644 --- a/src/sat/bsat2/Options.cpp +++ b/src/sat/bsat2/Options.cpp @@ -45,10 +45,12 @@ int Minisat::parseOptions(int& argc, char** argv, bool strict) } if (!parsed_ok) + { if (strict && match(argv[i], "-")) { fprintf(stderr, "ERROR! Unknown flag \"%s\". Use '--%shelp' for help.\n", argv[i], Option::getHelpPrefixString()); return 0; } // exit(0); else argv[j++] = argv[i]; + } } } diff --git a/src/sat/bsat2/Options.h b/src/sat/bsat2/Options.h index 137b5a45e..00d46d352 100644 --- a/src/sat/bsat2/Options.h +++ b/src/sat/bsat2/Options.h @@ -62,7 +62,7 @@ class Option struct OptionLt { bool operator()(const Option* x, const Option* y) { int test1 = strcmp(x->category, y->category); - return test1 < 0 || test1 == 0 && strcmp(x->type_name, y->type_name) < 0; + return test1 < 0 || ( test1 == 0 && strcmp(x->type_name, y->type_name) < 0 ); } }; diff --git a/src/sat/bsat2/SimpSolver.cpp b/src/sat/bsat2/SimpSolver.cpp index 59952d154..c07ec5b97 100644 --- a/src/sat/bsat2/SimpSolver.cpp +++ b/src/sat/bsat2/SimpSolver.cpp @@ -230,10 +230,12 @@ bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, vec& ou if (var(qs[i]) != v){ for (j = 0; j < ps.size(); j++) if (var(ps[j]) == var(qs[i])) + { if (ps[j] == ~qs[i]) return false; else goto next; + } out_clause.push(qs[i]); } next:; @@ -264,10 +266,12 @@ bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, int& size) if (var(__qs[i]) != v){ for (int j = 0; j < ps.size(); j++) if (var(__ps[j]) == var(__qs[i])) + { if (__ps[j] == ~__qs[i]) return false; else goto next; + } size++; } next:; diff --git a/src/sat/bsat2/Solver.cpp b/src/sat/bsat2/Solver.cpp index 1c45a4538..602692a8b 100644 --- a/src/sat/bsat2/Solver.cpp +++ b/src/sat/bsat2/Solver.cpp @@ -211,7 +211,7 @@ void Solver::cancelUntil(int level) { for (int c = trail.size()-1; c >= trail_lim[level]; c--){ Var x = var(trail[c]); assigns [x] = l_Undef; - if (phase_saving > 1 || (phase_saving == 1) && c > trail_lim.last()) + if (phase_saving > 1 || ((phase_saving == 1) && c > trail_lim.last())) polarity[x] = sign(trail[c]); insertVarOrder(x); } qhead = trail_lim[level]; @@ -659,7 +659,7 @@ lbool Solver::search(int nof_conflicts) }else{ // NO CONFLICT - if (nof_conflicts >= 0 && conflictC >= nof_conflicts || !withinBudget()){ + if ( (nof_conflicts >= 0 && conflictC >= nof_conflicts) || !withinBudget()){ // Reached bound on number of conflicts: progress_estimate = progressEstimate(); cancelUntil(0); diff --git a/src/sat/bsat2/Vec.h b/src/sat/bsat2/Vec.h index aade19f13..f5f5499ea 100644 --- a/src/sat/bsat2/Vec.h +++ b/src/sat/bsat2/Vec.h @@ -93,7 +93,6 @@ public: void moveTo(vec& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; } }; - template void vec::capacity(int min_cap) { if (cap >= min_cap) return; From 524699d6ab7e62ec85e19a118f1f3b02a3b99040 Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Mon, 4 Mar 2024 11:19:46 +0800 Subject: [PATCH 117/151] restore .gitignore, Makefile, and abc.rc --- .gitignore | 4 -- Makefile | 3 +- abc.rc | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 abc.rc diff --git a/.gitignore b/.gitignore index f0c5201c6..3fa906fef 100644 --- a/.gitignore +++ b/.gitignore @@ -10,10 +10,6 @@ _/ _TEST/ _sandwich/ _scripts/ -*.aig -*.vcproj -*.sh -*.v lib/abc* lib/m114* lib/bip* diff --git a/Makefile b/Makefile index 9a9f7abd5..0cc979b75 100644 --- a/Makefile +++ b/Makefile @@ -33,8 +33,7 @@ MODULES := \ src/proof/pdr src/proof/abs src/proof/live src/proof/ssc src/proof/int \ src/proof/cec src/proof/acec src/proof/dch src/proof/fraig src/proof/fra src/proof/ssw \ src/aig/aig src/aig/saig src/aig/gia src/aig/ioa src/aig/ivy src/aig/hop \ - src/aig/miniaig \ - src/sat/bsat2 + src/aig/miniaig all: $(PROG) default: $(PROG) diff --git a/abc.rc b/abc.rc new file mode 100644 index 000000000..a3efc0b09 --- /dev/null +++ b/abc.rc @@ -0,0 +1,148 @@ +# global parameters +set check # checks intermediate networks +#set checkfio # prints warnings when fanins/fanouts are duplicated +#unset checkread # does not check new networks after reading from file +#set backup # saves backup networks retrived by "undo" and "recall" +#set savesteps 1 # sets the maximum number of backup networks to save +#set progressbar # display the progress bar + +# program names for internal calls +set dotwin dot.exe +set dotunix dot +set gsviewwin gsview32.exe +set gsviewunix gv +set siswin sis.exe +set sisunix sis +set mvsiswin mvsis.exe +set mvsisunix mvsis +set capowin MetaPl-Capo10.1-Win32.exe +set capounix MetaPl-Capo10.1 +set gnuplotwin wgnuplot.exe +set gnuplotunix gnuplot + +# Niklas Een's commands +#load_plugin C:\_projects\abc\lib\bip_win.exe "BIP" + +# standard aliases +alias hi history +alias b balance +alias cg clockgate +alias cl cleanup +alias clp collapse +alias cs care_set +alias el eliminate +alias esd ext_seq_dcs +alias f fraig +alias fs fraig_sweep +alias fsto fraig_store +alias fres fraig_restore +alias fr fretime +alias ft fraig_trust +alias ic indcut +alias lp lutpack +alias pcon print_cone +alias pd print_dsd +alias pex print_exdc -d +alias pf print_factor +alias pfan print_fanio +alias pg print_gates +alias pl print_level +alias plat print_latch +alias pio print_io +alias pk print_kmap +alias pm print_miter +alias ps print_stats +alias psb print_stats -b +alias psu print_supp +alias psy print_symm +alias pun print_unate +alias q quit +alias r read +alias ra read_aiger +alias r3 retime -M 3 +alias r3f retime -M 3 -f +alias r3b retime -M 3 -b +alias ren renode +alias rh read_hie +alias ri read_init +alias rl read_blif +alias rb read_bench +alias ret retime +alias dret dretime +alias rp read_pla +alias rt read_truth +alias rv read_verilog +alias rvl read_verlib +alias rsup read_super mcnc5_old.super +alias rlib read_library +alias rlibc read_library cadence.genlib +alias rty read_liberty +alias rlut read_lut +alias rw rewrite +alias rwz rewrite -z +alias rf refactor +alias rfz refactor -z +alias re restructure +alias rez restructure -z +alias rs resub +alias rsz resub -z +alias sa set autoexec ps +alias scl scleanup +alias sif if -s +alias so source -x +alias st strash +alias sw sweep +alias ssw ssweep +alias tr0 trace_start +alias tr1 trace_check +alias trt "r c.blif; st; tr0; b; tr1" +alias u undo +alias w write +alias wa write_aiger +alias wb write_bench +alias wc write_cnf +alias wh write_hie +alias wl write_blif +alias wp write_pla +alias wv write_verilog + +# standard scripts +alias resyn "b; rw; rwz; b; rwz; b" +alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" +alias resyn2a "b; rw; b; rw; rwz; b; rwz; b" +alias resyn3 "b; rs; rs -K 6; b; rsz; rsz -K 6; b; rsz -K 5; b" +alias compress "b -l; rw -l; rwz -l; b -l; rwz -l; b -l" +alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l" +alias choice "fraig_store; resyn; fraig_store; resyn2; fraig_store; fraig_restore" +alias choice2 "fraig_store; balance; fraig_store; resyn; fraig_store; resyn2; fraig_store; resyn2; fraig_store; fraig_restore" +alias rwsat "st; rw -l; b -l; rw -l; rf -l" +alias drwsat2 "st; drw; b -l; drw; drf; ifraig -C 20; drw; b -l; drw; drf" +alias share "st; multi -m; sop; fx; resyn2" +alias addinit "read_init; undc; strash; zero" +alias blif2aig "undc; strash; zero" +alias v2p "&vta_gla; &ps; &gla_derive; &put; w 1.aig; pdr -v" +alias g2p "&ps; &gla_derive; &put; w 2.aig; pdr -v" +alias &sw_ "&put; sweep; st; &get" +alias &fx_ "&put; sweep; sop; fx; st; &get" +alias &dc3 "&b; &jf -K 6; &b; &jf -K 4; &b" +alias &dc4 "&b; &jf -K 7; &fx; &b; &jf -K 5; &fx; &b" + +# resubstitution scripts for the IWLS paper +alias src_rw "st; rw -l; rwz -l; rwz -l" +alias src_rs "st; rs -K 6 -N 2 -l; rs -K 9 -N 2 -l; rs -K 12 -N 2 -l" +alias src_rws "st; rw -l; rs -K 6 -N 2 -l; rwz -l; rs -K 9 -N 2 -l; rwz -l; rs -K 12 -N 2 -l" +alias resyn2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b" +alias r2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b" +alias compress2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l" +alias c2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l" + +# use this script to convert 1-valued and DC-valued flops for an AIG +alias fix_aig "logic; undc; strash; zero" + +# use this script to convert 1-valued and DC-valued flops for a logic network coming from BLIF +alias fix_blif "undc; strash; zero" + +# lazy man's synthesis +alias recadd3 "st; rec_add3; b; rec_add3; dc2; rec_add3; if -K 8; bidec; st; rec_add3; dc2; rec_add3; if -g -K 6; st; rec_add3" + + From c607fc3101608e655760a56cfa4ec5dfb79fed6b Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Mon, 4 Mar 2024 11:20:27 +0800 Subject: [PATCH 118/151] restore --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index 3fa906fef..cbb424152 100644 --- a/.gitignore +++ b/.gitignore @@ -8,8 +8,6 @@ ReleaseExt/ _/ _TEST/ -_sandwich/ -_scripts/ lib/abc* lib/m114* lib/bip* From a16a0f102785468bf1b0bf4c48fbd84b179d7b5c Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 6 Mar 2024 01:40:48 -0800 Subject: [PATCH 119/151] Writing Verilog for AIG using NAND gates. --- src/aig/gia/gia.h | 1 + src/aig/gia/giaMan.c | 99 +++++++++++++++++++++++++++++++++++++++++--- src/base/abci/abc.c | 76 ++++++++++++++++++++++++++++++++-- 3 files changed, 167 insertions(+), 9 deletions(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index f12ab35df..704cd728b 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1532,6 +1532,7 @@ extern void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs ); extern void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew ); extern void Gia_ManPrintNpnClasses( Gia_Man_t * p ); extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb, int fAssign, int fReverse ); +extern void Gia_ManDumpVerilogNand( Gia_Man_t * p, char * pFileName ); /*=== giaMem.c ===========================================================*/ extern Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax ); extern void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose ); diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index 5d8c86b31..288c06536 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -1414,12 +1414,12 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int if ( fInterComb ) { if ( fAssign ) { - extern void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName, int fReverse ); - Gia_ManDumpInterfaceAssign( p, pFileName, fReverse ); + extern void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ); + Gia_ManDumpInterfaceAssign( p, pFileName ); } else { - extern void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName, int fReverse ); - Gia_ManDumpInterface( p, pFileName, fReverse ); + extern void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ); + Gia_ManDumpInterface( p, pFileName ); } } else @@ -1899,7 +1899,7 @@ void Gia_ManDumpIoRanges( Gia_Man_t * p, FILE * pFile, int fOuts ) SeeAlso [] ***********************************************************************/ -void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName, int fReverse ) +void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ) { Gia_Obj_t * pObj; Vec_Bit_t * vInvs, * vUsed; @@ -2010,7 +2010,7 @@ void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName, int fReverse ) Vec_BitFree( vInvs ); Vec_BitFree( vUsed ); } -void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName, int fReverse ) +void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ) { Gia_Obj_t * pObj; Vec_Bit_t * vInvs, * vUsed; @@ -2123,6 +2123,93 @@ void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName, int fReverse ) } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDumpNandLit( FILE * pFile, int nIns, int Lit, int nDigits ) +{ + if ( Lit == 0 ) + fprintf( pFile, "1\'b0" ); + else if ( Lit == 1 ) + fprintf( pFile, "1\'b1" ); + else if ( Abc_Lit2Var(Lit) <= nIns ) + fprintf( pFile, "%cn%0*d", (char)(Abc_LitIsCompl(Lit)? '~':' '), nDigits, Abc_Lit2Var(Lit) ); + else + fprintf( pFile, "%cn%0*d", (char)(Abc_LitIsCompl(Lit)? ' ':'~'), nDigits, Abc_Lit2Var(Lit) ); +} +void Gia_ManDumpVerilogNand( Gia_Man_t * p, char * pFileName ) +{ + Gia_Obj_t * pObj; int i, nPis = Gia_ManPiNum(p); + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + assert( Gia_ManRegNum(p) == 0 ); + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_wrapper" ); + fprintf( pFile, " ( " ); + if ( p->vNamesIn ) { + Gia_ManDumpIoList( p, pFile, 0, 0 ); + fprintf( pFile, ", " ); + Gia_ManDumpIoList( p, pFile, 1, 0 ); + fprintf( pFile, " );\n\n" ); + Gia_ManDumpIoRanges( p, pFile, 0 ); + Gia_ManDumpIoRanges( p, pFile, 1 ); + } + else { + fprintf( pFile, "\n " ); + Gia_ManForEachPi( p, pObj, i ) + fprintf( pFile, "%s, ", Gia_ObjGetDumpName(NULL, 'x', i, nDigitsI) ); + fprintf( pFile, "\n " ); + Gia_ManForEachPo( p, pObj, i ) + fprintf( pFile, "%s%s ", Gia_ObjGetDumpName(NULL, 'z', i, nDigitsO), i < Gia_ManPoNum(p)-1 ? ",":"" ); + fprintf( pFile, "\n);\n\n" ); + fprintf( pFile, " input" ); + Gia_ManForEachPi( p, pObj, i ) + fprintf( pFile, " %s%s", Gia_ObjGetDumpName(NULL, 'x', i, nDigitsI), i < Gia_ManPiNum(p)-1 ? ",":"" ); + fprintf( pFile, ";\n" ); + fprintf( pFile, " output" ); + Gia_ManForEachPo( p, pObj, i ) + fprintf( pFile, " %s%s", Gia_ObjGetDumpName(NULL, 'z', i, nDigitsO), i < Gia_ManPoNum(p)-1 ? ",":"" ); + fprintf( pFile, ";\n" ); + } + fprintf( pFile, "\n" ); + Gia_ManForEachPi( p, pObj, i ) + fprintf( pFile, " wire n%0*d = %s;\n", nDigits, i+1, p->vNamesIn ? (char *)Vec_PtrEntry(p->vNamesIn, i) : Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + fprintf( pFile, " wire n%0*d = ~(", nDigits, i ); + Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit0(pObj, i), nDigits ); + fprintf( pFile, " & " ); + Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit1(pObj, i), nDigits ); + fprintf( pFile, ");\n" ); + } + fprintf( pFile, "\n" ); + Gia_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, " assign %s = ", p->vNamesOut ? (char *)Vec_PtrEntry(p->vNamesOut, i) : Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit0p(p, pObj), nDigits ); + fprintf( pFile, ";\n" ); + } + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); +} + /**Function************************************************************* Synopsis [Generate hierarchical design.] diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index d6363a0cc..9547c4a79 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -219,6 +219,7 @@ static int Abc_CommandInter ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandBb2Wb ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandOutdec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandNodeDup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandWrap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestColor ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -998,6 +999,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "bb2wb", Abc_CommandBb2Wb, 0 ); Cmd_CommandAdd( pAbc, "Various", "outdec", Abc_CommandOutdec, 1 ); Cmd_CommandAdd( pAbc, "Various", "nodedup", Abc_CommandNodeDup, 1 ); + Cmd_CommandAdd( pAbc, "Various", "wrap", Abc_CommandWrap, 0 ); Cmd_CommandAdd( pAbc, "Various", "testcolor", Abc_CommandTestColor, 0 ); Cmd_CommandAdd( pAbc, "Various", "test", Abc_CommandTest, 0 ); // Cmd_CommandAdd( pAbc, "Various", "qbf_solve", Abc_CommandTest, 0 ); @@ -14463,6 +14465,67 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandWrap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char * pFileName = NULL, * pFileName2 = NULL; + FILE * pFile = NULL, * pFile2 = NULL; + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 2 ) + { + Abc_Print( 1,"Two file names are expected on the command line.\n" ); + return 0; + } + pFileName = argv[globalUtilOptind]; + pFileName2 = argv[globalUtilOptind+1]; + pFile = fopen( pFileName, "rb" ); + pFile2 = fopen( pFileName2, "wb" ); + if ( pFile && pFile2 ) + { + char Buffer[1000]; + while ( fgets( Buffer, 1000, pFile ) != NULL ) + { + if ( Buffer[strlen(Buffer)-1] == '\n' ) + Buffer[strlen(Buffer)-1] = 0; + if ( Buffer[strlen(Buffer)-1] == '\r' ) + Buffer[strlen(Buffer)-1] = 0; + fprintf( pFile2, " printf(\"%s\\n\");\n", Buffer ); + } + } + if ( pFile ) fclose(pFile); + if ( pFile2 ) fclose(pFile2); + return 0; + +usage: + Abc_Print( -2, "usage: wrap [-h] \n" ); + Abc_Print( -2, "\t wrapping lines\n" ); + Abc_Print( -2, "\t : input text file\n"); + Abc_Print( -2, "\t : output text file\n"); + return 1; + +} + /**Function************************************************************* Synopsis [] @@ -32065,8 +32128,9 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) char * pFileName; char ** pArgvNew; int c, nArgcNew; - int fUnique = 0; + int fUnique = 0; int fVerilog = 0; + int fVerNand = 0; int fInter = 0; int fInterComb = 0; int fAssign = 0; @@ -32078,7 +32142,7 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) int fSkipComment = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "upicabmlnrsvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "upqicabmlnrsvh" ) ) != EOF ) { switch ( c ) { @@ -32088,6 +32152,9 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'p': fVerilog ^= 1; break; + case 'q': + fVerNand ^= 1; + break; case 'i': fInter ^= 1; break; @@ -32143,6 +32210,8 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_AigerWriteSimple( pGia, pFileName ); Gia_ManStop( pGia ); } + else if ( fVerNand ) + Gia_ManDumpVerilogNand( pAbc->pGia, pFileName ); else if ( fVerilog ) Gia_ManDumpVerilog( pAbc->pGia, pFileName, NULL, fVerBufs, fInter, fInterComb, fAssign, fReverse ); else if ( fMiniAig ) @@ -32154,10 +32223,11 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &w [-upicabmlnsvh] \n" ); + Abc_Print( -2, "usage: &w [-upqicabmlnsvh] \n" ); Abc_Print( -2, "\t writes the current AIG into the AIGER file\n" ); Abc_Print( -2, "\t-u : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" ); Abc_Print( -2, "\t-p : toggle writing Verilog with 'and' and 'not' [default = %s]\n", fVerilog? "yes" : "no" ); + Abc_Print( -2, "\t-q : toggle writing Verilog with NAND-gates [default = %s]\n", fVerNand? "yes" : "no" ); Abc_Print( -2, "\t-i : toggle writing the interface module in Verilog [default = %s]\n", fInter? "yes" : "no" ); Abc_Print( -2, "\t-c : toggle writing the interface module in Verilog [default = %s]\n", fInterComb? "yes" : "no" ); Abc_Print( -2, "\t-a : toggle writing the interface module with assign-statements [default = %s]\n", fAssign? "yes" : "no" ); From 015dd2a367326facf2b582b5786f7b4c0e50b1fd Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Fri, 15 Mar 2024 16:56:10 +0800 Subject: [PATCH 120/151] use speculative in &brecover --- src/aig/gia/gia.h | 3 +- src/aig/gia/giaBound.c | 186 +++++++++++++++++++++++++++++------------ src/aig/gia/giaDup.c | 9 +- src/base/abci/abc.c | 22 ++++- 4 files changed, 160 insertions(+), 60 deletions(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index f12ab35df..3e90ba0e6 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1805,9 +1805,10 @@ extern void Bnd_ManMap( int iLit, int id, int spec ); extern void Bnd_ManMerge( int id1, int id2, int phaseDiff ); extern void Bnd_ManFinalizeMappings(); extern void Bnd_ManPrintMappings(); +extern Gia_Man_t* Bnd_ManStackGias( Gia_Man_t *pSpec, Gia_Man_t *pImpl ); // for eco extern int Bnd_ManCheckBound( Gia_Man_t *p, int fVerbose ); -extern void Bnd_ManFindBound( Gia_Man_t *p ); +extern void Bnd_ManFindBound( Gia_Man_t *p, Gia_Man_t *pImpl ); extern Gia_Man_t* Bnd_ManGenSpecOut( Gia_Man_t *p ); extern Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t *p ); extern Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPatch ); diff --git a/src/aig/gia/giaBound.c b/src/aig/gia/giaBound.c index a420b818d..9ae21b459 100644 --- a/src/aig/gia/giaBound.c +++ b/src/aig/gia/giaBound.c @@ -28,7 +28,6 @@ struct Bnd_Man_t_ int nNode_patch; int nNode_patched; - int status; // 0: init 1: boundary found 2: out generated 3: patched generated int fVerbose; int combLoop_spec; @@ -43,6 +42,8 @@ struct Bnd_Man_t_ Vec_Ptr_t* vBmiter2Impl; Vec_Int_t* vSpec2Impl; Vec_Bit_t* vSpec2Impl_phase; + + Vec_Int_t* vImpl2Bmiter; Vec_Int_t* vBI; Vec_Int_t* vBO; @@ -98,6 +99,9 @@ Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl, int fVerbose ) p -> vSpec2Impl_phase = Vec_BitAlloc( Gia_ManObjNum(pSpec) ); Vec_IntFill( p -> vSpec2Impl, Gia_ManObjNum(pSpec), -1 ); Vec_BitFill( p -> vSpec2Impl_phase, Gia_ManObjNum(pSpec), 0 ); + + p -> vImpl2Bmiter = Vec_IntAlloc( Gia_ManObjNum(pImpl) ); + Vec_IntFill( p -> vImpl2Bmiter, Gia_ManObjNum(pImpl), -1 ); p -> vBI = Vec_IntAlloc(16); p -> vBO = Vec_IntAlloc(16); @@ -113,7 +117,6 @@ Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl, int fVerbose ) p -> nNode_patch = 0; p -> nNode_patched = 0; - p -> status = 0; p -> fVerbose = fVerbose; p -> combLoop_spec = 0; @@ -153,6 +156,7 @@ void Bnd_ManStop() Vec_PtrFree( pBnd-> vBmiter2Impl ); Vec_IntFree( pBnd-> vSpec2Impl ); Vec_BitFree( pBnd-> vSpec2Impl_phase ); + Vec_IntFree( pBnd-> vImpl2Bmiter ); Vec_IntFree( pBnd->vBI ); Vec_IntFree( pBnd->vBO ); @@ -260,6 +264,9 @@ void Bnd_ManFinalizeMappings() { // record the number of different choice of vEI_impl, vEO_impl Vec_IntSetEntry( pBnd->vImpl2Spec_diff, id, Vec_IntSize(vSpec)-1 ); + + // vImpl2Bmiter + Vec_IntSetEntry( pBnd->vImpl2Bmiter, id, i ); } @@ -332,41 +339,41 @@ void Bnd_ManPrintStats() warning = 1; printf("WARNING: multiple equiv nodes on the boundary of impl\n"); } - if ( p->feedthrough ) - { - warning = 1; - printf("WARNING: feedthrough inside patch\n"); - } printf("The outsides of spec and impl are %sEQ.\n", p->eq_out ? "" : "NOT " ); - printf("The patched impl and patch are %sEQ.\n", p->eq_res ? "" : "NOT " ); + printf("The patched impl is %sEQ. to spec (and impl)\n", p->eq_res ? "" : "NOT " ); // #internal // nBI, nBO // nBI_miss, nBO_miss - // nAI, nAO, nExtra + // nEI, nEO, nExtra // #spec, #impl, #patched // combLoop_spec, combLoop_impl - // status - // #different choice of impl on boundary + // #choice_impl + // #choice_spec + // #feedthrough // warning (may be neq) // eq_out, eq_res - // printf("\nRESULT\n"); - // printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", - // p->nInternal, - // p->nBI, p->nBO, - // p->nBI_miss, p->nBO_miss, - // Vec_IntSize(p->vEI_spec), Vec_IntSize(p->vEO_spec), p->nExtra, - // p->nNode_spec, p->nNode_impl, p->nNode_patched, - // p->combLoop_spec, p->combLoop_impl, - // p->status, - // p->nChoice_impl, - // p->nChoice_spec, - // p->feedthrough, - // warning, - // p->eq_out, p->eq_res - // ); + printf("\nRESULT\n"); + printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + p->nInternal, + p->nBI, p->nBO, + p->nBI_miss, p->nBO_miss, + Vec_IntSize(p->vEI_spec), Vec_IntSize(p->vEO_spec), p->nExtra, + p->nNode_spec, p->nNode_impl, p->nNode_patched, + p->combLoop_spec, p->combLoop_impl, + p->nChoice_impl, + p->nChoice_spec, + warning, + p->eq_out, p->eq_res + ); + + printf("#Choice Spec\t%d\n", p->nChoice_spec); + printf("#Choice Impl\t%d\n", p->nChoice_impl); + + + } /**Function************************************************************* @@ -541,7 +548,6 @@ int Bnd_ManCheckExtBound( Gia_Man_t * p, Vec_Int_t *vEI, Vec_Int_t *vEO ) } - /**Function************************************************************* Synopsis [] @@ -554,7 +560,7 @@ int Bnd_ManCheckExtBound( Gia_Man_t * p, Vec_Int_t *vEI, Vec_Int_t *vEO ) ***********************************************************************/ -void Bnd_ManFindBound( Gia_Man_t * p ) +void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) { Vec_Int_t *vFlag; Vec_Ptr_t *vQ; @@ -743,18 +749,16 @@ void Bnd_ManFindBound( Gia_Man_t * p ) // count number of choice of boundary - Vec_IntForEachEntry( vEI_spec, id, i ) - pBnd -> nChoice_impl += Vec_IntEntry( pBnd -> vSpec2Impl_diff, id ); Vec_IntForEachEntry( vEO_spec, id, i ) + { pBnd -> nChoice_impl += Vec_IntEntry( pBnd -> vSpec2Impl_diff, id ); - Vec_IntForEachEntry( vEI_impl, id, i ) - pBnd -> nChoice_spec += Vec_IntEntry( pBnd -> vImpl2Spec_diff, id ); + } Vec_IntForEachEntry( vEO_impl, id, i ) + { pBnd -> nChoice_spec += Vec_IntEntry( pBnd -> vImpl2Spec_diff, id ); - pBnd -> nChoice_spec -= ( pBnd->nBI + pBnd ->nBO - pBnd->nBI_miss - pBnd->nBO_miss); + } // print - pBnd -> status = 1; if ( pBnd -> fVerbose ) { printf("#EI = %d\t#EO = %d\t#Extra Node = %d\n", Vec_IntSize(vEI_spec) , Vec_IntSize(vEO_spec), cnt_extra ); @@ -764,8 +768,10 @@ void Bnd_ManFindBound( Gia_Man_t * p ) // check boundary has comb loop if ( !Bnd_ManCheckExtBound( p, vEI_spec, vEO_spec ) ) { + printf("Combinational loop exist\n"); pBnd -> combLoop_spec = 1; + } @@ -776,7 +782,6 @@ void Bnd_ManFindBound( Gia_Man_t * p ) - /**Function************************************************************* Synopsis [] @@ -804,18 +809,6 @@ Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec return 0; } - // detect feedthrough - Gia_ManFillValue(p); - Vec_IntForEachEntry(vEO, id, i) - { - Gia_ManObj(p, id) -> Value = 1; - } - Vec_IntForEachEntry(vEI, id, i) - { - if ( Gia_ManObj(p, id) -> Value == 1 ) - pBnd -> feedthrough = 1; - } - // initialize pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew -> pName = ABC_ALLOC( char, strlen(p->pName)+10); @@ -847,7 +840,6 @@ Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec } } - // add aig nodes Gia_ManForEachAnd(p, pObj, i) { @@ -899,8 +891,7 @@ Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t* p) { if ( pBnd -> fVerbose ) printf("Generating impl_out with given boundary.\n"); Gia_Man_t *pNew = Bnd_ManCutBoundary( p, pBnd->vEI_impl, pBnd->vEO_impl, pBnd->vEI_phase, pBnd->vEO_phase ); - if ( pNew ) pBnd -> status = 2; - else pBnd -> combLoop_impl = 1; + if (!pNew) pBnd -> combLoop_impl = 1; return pNew; } @@ -1056,7 +1047,6 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat Gia_ManStop( pTemp ); pBnd -> nNode_patched = Gia_ManAndNum( pNew ); - pBnd -> status = 3; return pNew; } @@ -1142,7 +1132,6 @@ Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ) Gia_ManStop( pTemp ); pBnd -> nNode_patched = Gia_ManAndNum( pNew ); - pBnd -> status = 3; return pNew; } @@ -1243,6 +1232,99 @@ Gia_Man_t* Bnd_ManGenPatched2( Gia_Man_t *pImpl, Gia_Man_t *pPatch, int fSkipStr } +Gia_Man_t* Bnd_ManStackGias( Gia_Man_t *pSpec, Gia_Man_t *pImpl ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + + int i, iLit; + if ( Gia_ManBufNum(pSpec) == 0 ) { + printf( "The spec AIG should have a boundary.\n" ); + return NULL; + } + if ( Gia_ManBufNum(pImpl) != 0 ) { + printf( "The impl AIG should have no boundary.\n" ); + return NULL; + } + + assert( Gia_ManBufNum(pSpec) > 0 ); + assert( Gia_ManBufNum(pImpl) == 0 ); + assert( Gia_ManRegNum(pSpec) == 0 ); + assert( Gia_ManRegNum(pImpl) == 0 ); + assert( Gia_ManCiNum(pSpec) == Gia_ManCiNum(pImpl) ); + assert( Gia_ManCoNum(pSpec) == Gia_ManCoNum(pImpl) ); + + pNew = Gia_ManStart( Gia_ManObjNum(pSpec) + Gia_ManObjNum(pImpl) ); + pNew->pName = ABC_ALLOC( char, strlen(pSpec->pName) + 10 ); + sprintf( pNew->pName, "%s_stack", pSpec->pName ); + + Gia_ManHashStart( pNew ); + Gia_ManConst0(pSpec)->Value = 0; + Gia_ManConst0(pImpl)->Value = 0; + + for( int i = 0; i < Gia_ManCiNum(pSpec); i++ ) + { + int iLit = Gia_ManCi(pSpec, i)->Value = Gia_ManCi(pImpl, i) -> Value = Gia_ManAppendCi(pNew); + + pObj = Gia_ManCi(pSpec, i); + Bnd_ManMap( iLit, Gia_ObjId( pSpec, pObj ), 1 ); + + pObj = Gia_ManCi(pImpl, i); + Bnd_ManMap( iLit, Gia_ObjId( pImpl, pObj) , 0 ); + } + + // record the corresponding impl node of each lit + Gia_ManForEachAnd( pImpl, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( pBnd ) Bnd_ManMap( pObj -> Value, Gia_ObjId(pImpl, pObj), 0 ); + } + + Vec_Int_t* vFlag = Vec_IntAlloc( Gia_ManObjNum( pSpec ) ); + Vec_IntFill( vFlag, Gia_ManObjNum(pSpec), 0 ); + int count = 0; + Gia_ManForEachBuf( pSpec, pObj, i ) + { + if ( count < pBnd -> nBI ) + { + // it's BI, don't record buf + Vec_IntSetEntry( vFlag, Gia_ObjId( pSpec, pObj ), 1 ); + } + else + { + // it's BO, don't record buf's fanin + Vec_IntSetEntry( vFlag, Gia_ObjId( pSpec, Gia_ObjFanin0( pObj ) ), 1 ); + } + count++; + } + + // record hashed equivalent nodes + Gia_ManForEachAnd( pSpec, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( Vec_IntEntry( vFlag, Gia_ObjId( pSpec, pObj ) ) == 0 ) + { + Bnd_ManMap( pObj -> Value, Gia_ObjId(pSpec, pObj), 1 ); + } + } + Vec_IntFree( vFlag ); + + Gia_ManForEachCo( pImpl, pObj, i ) + { + iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManForEachCo( pSpec, pObj, i ) + { + iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 46c6f4da0..92eb2ac89 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -5712,10 +5712,10 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) int iLit = Gia_ManCi(p1, i)->Value = Gia_ManCi(p2, i) -> Value = Gia_ManAppendCi(pNew); pObj = Gia_ManCi(p1, i); - Bnd_ManMap( iLit, Gia_ObjId( p1, pObj ), 1 ); + if ( pBnd ) Bnd_ManMap( iLit, Gia_ObjId( p1, pObj ), 1 ); pObj = Gia_ManCi(p2, i); - Bnd_ManMap( iLit, Gia_ObjId( p2, pObj) , 0 ); + if ( pBnd ) Bnd_ManMap( iLit, Gia_ObjId( p2, pObj) , 0 ); } @@ -5723,14 +5723,14 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) Gia_ManForEachAnd( p2, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - Bnd_ManMap( pObj -> Value, Gia_ObjId(p2, pObj), 0 ); + if ( pBnd ) Bnd_ManMap( pObj -> Value, Gia_ObjId(p2, pObj), 0 ); } // record hashed equivalent nodes Gia_ManForEachAnd( p1, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - Bnd_ManMap( pObj -> Value, Gia_ObjId(p1, pObj), 1 ); + if ( pBnd ) Bnd_ManMap( pObj -> Value, Gia_ObjId(p1, pObj), 1 ); } Gia_ManForEachCo( p2, pObj, i ) @@ -5741,6 +5741,7 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) { iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } + // Vec_IntForEachEntry( vLits, iLit, i ) // Gia_ManAppendCo( pNew, iLit ); // Vec_IntFree( vLits ); diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index d6363a0cc..7084b5897 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -52115,12 +52115,27 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) // parse options Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "vhCk" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; + pParsFra->fVerbose ^= 1; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pParsFra->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParsFra->nBTLimit < 0 ) + goto usage; + break; + case 'k': + pParsFra ->fUseCones ^= 1; break; case 'h': goto usage; @@ -52189,13 +52204,14 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( success ) { // create bmiter, run fraig, record mapping - pBmiter = Gia_ManBoundaryMiter( pSpec, pAbc->pGia, 0 ); + // pBmiter = Gia_ManBoundaryMiter( pSpec, pAbc->pGia, 0 ); + pBmiter = Bnd_ManStackGias( pSpec, pAbc->pGia ); pTemp = Cec4_ManSimulateTest( pBmiter, pParsFra ); Gia_ManStop(pBmiter); Gia_ManStop(pTemp); // find - Bnd_ManFindBound( pSpec ); + Bnd_ManFindBound( pSpec, pAbc->pGia ); // create spec_out and pSpec_out = Bnd_ManGenSpecOut( pSpec ); From b7884aaf2b8a9715360e31ff6dc8c45d0db31d9b Mon Sep 17 00:00:00 2001 From: Allen Ho Date: Sat, 16 Mar 2024 01:40:11 +0800 Subject: [PATCH 121/151] clean up & add options for &brecover --- src/aig/gia/gia.h | 2 + src/aig/gia/giaBound.c | 155 ++++++++++++++++++++++++++--------------- src/base/abci/abc.c | 98 ++++++++++++++++---------- 3 files changed, 161 insertions(+), 94 deletions(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 3e90ba0e6..a850935eb 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1806,6 +1806,8 @@ extern void Bnd_ManMerge( int id1, int id2, int phaseDiff ); extern void Bnd_ManFinalizeMappings(); extern void Bnd_ManPrintMappings(); extern Gia_Man_t* Bnd_ManStackGias( Gia_Man_t *pSpec, Gia_Man_t *pImpl ); +extern int Bnd_ManCheckCoMerged( Gia_Man_t *p ); + // for eco extern int Bnd_ManCheckBound( Gia_Man_t *p, int fVerbose ); extern void Bnd_ManFindBound( Gia_Man_t *p, Gia_Man_t *pImpl ); diff --git a/src/aig/gia/giaBound.c b/src/aig/gia/giaBound.c index 9ae21b459..f7811967d 100644 --- a/src/aig/gia/giaBound.c +++ b/src/aig/gia/giaBound.c @@ -38,12 +38,14 @@ struct Bnd_Man_t_ int nChoice_impl; int feedthrough; + int maxNumClass; + Vec_Ptr_t* vBmiter2Spec; Vec_Ptr_t* vBmiter2Impl; - Vec_Int_t* vSpec2Impl; - Vec_Bit_t* vSpec2Impl_phase; + Vec_Bit_t* vSpec2Impl_phase; // TODO: record all phases Vec_Int_t* vImpl2Bmiter; + Vec_Int_t* vSpec2Bmiter; Vec_Int_t* vBI; Vec_Int_t* vBO; @@ -54,9 +56,6 @@ struct Bnd_Man_t_ Vec_Bit_t* vEI_phase; Vec_Bit_t* vEO_phase; - Vec_Int_t* vSpec2Impl_diff; - Vec_Int_t* vImpl2Spec_diff; // note that this include bufs, which should merge into their fanins - }; Bnd_Man_t* pBnd = 0; @@ -68,6 +67,12 @@ Bnd_Man_t* pBnd = 0; void Bnd_ManSetEqOut( int eq ) { pBnd -> eq_out = eq;} void Bnd_ManSetEqRes( int eq ) { pBnd -> eq_res = eq;} +Vec_Int_t* Bnd_ManSpec2Impl( int id ) { return (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Impl, Vec_IntEntry( pBnd->vSpec2Bmiter, id ) ); } +int Bnd_ManSpec2ImplNum( int id ) { return Vec_IntSize( (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Impl, Vec_IntEntry( pBnd->vSpec2Bmiter, id ) ) ); } + +Vec_Int_t* Bnd_ManImpl2Spec( int id ) { return (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Spec, Vec_IntEntry( pBnd->vImpl2Bmiter, id ) ); } +int Bnd_ManImpl2SpecNum( int id ) { return Vec_IntSize( (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Spec, Vec_IntEntry( pBnd->vImpl2Bmiter, id ) ) ); } + /**Function************************************************************* Synopsis [] @@ -85,23 +90,26 @@ Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl, int fVerbose ) int i; Bnd_Man_t* p = ABC_CALLOC( Bnd_Man_t, 1 ); - p -> vBmiter2Spec = Vec_PtrAlloc( Gia_ManObjNum(pSpec) + Gia_ManObjNum(pImpl) ); - p -> vBmiter2Impl = Vec_PtrAlloc( Gia_ManObjNum(pSpec) + Gia_ManObjNum(pImpl) ); - Vec_PtrFill( p -> vBmiter2Spec, (Gia_ManObjNum(pSpec) + Gia_ManObjNum(pImpl)), 0 ); - Vec_PtrFill( p -> vBmiter2Impl, (Gia_ManObjNum(pSpec) + Gia_ManObjNum(pImpl)), 0 ); + p -> maxNumClass = Gia_ManCiNum( pSpec ) + Gia_ManAndNotBufNum(pSpec) + Gia_ManAndNum(pImpl) + 2 + Gia_ManCoNum(pSpec) * 2; + // one for constant node and one for dummy + + p -> vBmiter2Spec = Vec_PtrAlloc( p -> maxNumClass ); + p -> vBmiter2Impl = Vec_PtrAlloc( p -> maxNumClass ); + Vec_PtrFill( p -> vBmiter2Spec, p -> maxNumClass, 0 ); + Vec_PtrFill( p -> vBmiter2Impl, p -> maxNumClass, 0 ); for( i = 0; i < Vec_PtrSize( p -> vBmiter2Impl ); i ++ ) { Vec_PtrSetEntry( p -> vBmiter2Spec, i, Vec_IntAlloc(1) ); Vec_PtrSetEntry( p -> vBmiter2Impl, i, Vec_IntAlloc(1) ); } - p -> vSpec2Impl = Vec_IntAlloc( Gia_ManObjNum(pSpec) ); p -> vSpec2Impl_phase = Vec_BitAlloc( Gia_ManObjNum(pSpec) ); - Vec_IntFill( p -> vSpec2Impl, Gia_ManObjNum(pSpec), -1 ); Vec_BitFill( p -> vSpec2Impl_phase, Gia_ManObjNum(pSpec), 0 ); p -> vImpl2Bmiter = Vec_IntAlloc( Gia_ManObjNum(pImpl) ); - Vec_IntFill( p -> vImpl2Bmiter, Gia_ManObjNum(pImpl), -1 ); + Vec_IntFill( p -> vImpl2Bmiter, Gia_ManObjNum(pImpl), p -> maxNumClass - 1 ); + p -> vSpec2Bmiter = Vec_IntAlloc( Gia_ManObjNum(pSpec) ); + Vec_IntFill( p -> vSpec2Bmiter, Gia_ManObjNum(pSpec), p -> maxNumClass - 1); p -> vBI = Vec_IntAlloc(16); p -> vBO = Vec_IntAlloc(16); @@ -128,12 +136,6 @@ Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl, int fVerbose ) p -> nChoice_impl = 0; p -> feedthrough = 0; - p -> vSpec2Impl_diff = Vec_IntAlloc( Gia_ManObjNum(pSpec) ); - Vec_IntFill( p -> vSpec2Impl_diff, Gia_ManObjNum(pSpec), 0 ); - - p -> vImpl2Spec_diff = Vec_IntAlloc( Gia_ManObjNum(pImpl) ); - Vec_IntFill( p -> vImpl2Spec_diff, Gia_ManObjNum(pImpl), 0 ); - return p; } @@ -154,9 +156,9 @@ void Bnd_ManStop() Vec_PtrFree( pBnd-> vBmiter2Spec ); Vec_PtrFree( pBnd-> vBmiter2Impl ); - Vec_IntFree( pBnd-> vSpec2Impl ); Vec_BitFree( pBnd-> vSpec2Impl_phase ); Vec_IntFree( pBnd-> vImpl2Bmiter ); + Vec_IntFree( pBnd-> vSpec2Bmiter ); Vec_IntFree( pBnd->vBI ); Vec_IntFree( pBnd->vBO ); @@ -167,9 +169,6 @@ void Bnd_ManStop() Vec_BitFree( pBnd->vEI_phase ); Vec_BitFree( pBnd->vEO_phase ); - Vec_IntFree( pBnd-> vSpec2Impl_diff ); - Vec_IntFree( pBnd-> vImpl2Spec_diff ); - ABC_FREE( pBnd ); } @@ -235,7 +234,6 @@ void Bnd_ManFinalizeMappings() Vec_Ptr_t* vBmiter2Spec = pBnd -> vBmiter2Spec; Vec_Ptr_t* vBmiter2Impl = pBnd -> vBmiter2Impl; - Vec_Int_t* vSpec2Impl = pBnd -> vSpec2Impl; Vec_Int_t *vSpec, *vImpl; int i, j, id; @@ -249,27 +247,16 @@ void Bnd_ManFinalizeMappings() vSpec = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, i ); vImpl = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, i ); - // create spec2impl - if ( Vec_IntSize(vSpec) != 0 && Vec_IntSize(vImpl) != 0 ) + Vec_IntForEachEntry( vSpec, id, j ) { - Vec_IntForEachEntry( vSpec, id, j ) - { - Vec_IntSetEntry( vSpec2Impl, id, Vec_IntEntry(vImpl, 0) ); - - // record the number of different choice of vEI_impl, vEO_impl - Vec_IntSetEntry( pBnd->vSpec2Impl_diff, id, Vec_IntSize(vImpl)-1 ); - } - - Vec_IntForEachEntry( vImpl, id, j ) - { - // record the number of different choice of vEI_impl, vEO_impl - Vec_IntSetEntry( pBnd->vImpl2Spec_diff, id, Vec_IntSize(vSpec)-1 ); - - // vImpl2Bmiter - Vec_IntSetEntry( pBnd->vImpl2Bmiter, id, i ); - } - + // vSpec2Bmiter + Vec_IntSetEntry( pBnd->vSpec2Bmiter, id, i ); + } + Vec_IntForEachEntry( vImpl, id, j ) + { + // vImpl2Bmiter + Vec_IntSetEntry( pBnd->vImpl2Bmiter, id, i ); } // count number of nodes merged into the same circuit @@ -283,7 +270,6 @@ void Bnd_ManFinalizeMappings() } } - } void Bnd_ManPrintMappings() { @@ -512,7 +498,7 @@ int Bnd_CheckFlagRec( Gia_Man_t *p, Gia_Obj_t *pObj, Vec_Int_t* vFlag ) Synopsis [] - Description [] + Description [check if combnational loop exist in the extended boundary] SideEffects [] @@ -552,14 +538,14 @@ int Bnd_ManCheckExtBound( Gia_Man_t * p, Vec_Int_t *vEI, Vec_Int_t *vEO ) Synopsis [] - Description [] + Description [find the extended boundary in spec + and compute the corresponding boundary in impl] SideEffects [] SeeAlso [] ***********************************************************************/ - void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) { Vec_Int_t *vFlag; @@ -570,7 +556,6 @@ void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) Vec_Int_t *vAI = Vec_IntAlloc(16); Vec_Int_t *vAO = Vec_IntAlloc(16); - Vec_Int_t *vSpec2Impl = pBnd -> vSpec2Impl; Vec_Bit_t *vSpec2Impl_phase = pBnd -> vSpec2Impl_phase; Vec_Int_t *vBI = pBnd -> vBI; Vec_Int_t *vBO = pBnd -> vBO; @@ -607,7 +592,7 @@ void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) // compute EO, travse with flag 1 Vec_IntForEachEntry( vBO, id, i ) { - if ( Vec_IntEntry( vSpec2Impl, id ) == -1 ) // BO not matched + if ( Bnd_ManSpec2ImplNum(id) == 0 ) // BO not matched { Vec_PtrPush( vQ, Gia_ManObj(p, id) ); } @@ -630,7 +615,7 @@ void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) // printf("%d\n", id); - if ( Vec_IntEntry( vSpec2Impl, id ) != -1 ) // matched + if ( Bnd_ManSpec2ImplNum(id) != 0 ) // matched { Vec_IntPush( vEO_spec, id ); Vec_IntPush( vAO, id ); @@ -679,7 +664,7 @@ void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) // add unmatched BI to queue Vec_IntForEachEntry( vBI, id, i ) { - if ( Vec_IntEntry( vSpec2Impl, id ) == -1 ) // BO not matched + if ( Bnd_ManSpec2ImplNum(id) == 0 ) // BO not matched { Vec_PtrPush( vQ, Gia_ManObj(p, id) ); } @@ -715,7 +700,7 @@ void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) // printf("%d\n", id); - if ( Vec_IntEntry(vFlag, id) != 1 && Vec_IntEntry( vSpec2Impl, id ) != -1 ) // matched + if ( Vec_IntEntry(vFlag, id) != 1 && Bnd_ManSpec2ImplNum(id) != 0 ) // matched { Vec_IntPush( vEI_spec, id ); Vec_IntPush( vAI, id ); @@ -738,12 +723,12 @@ void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) // gen vEI_impl, vEO_impl, vEI_phase, vEO_phase Vec_IntForEachEntry( vEI_spec, id, i ) { - Vec_IntPush( vEI_impl, Vec_IntEntry( vSpec2Impl, id ) ); + Vec_IntPush( vEI_impl, Vec_IntEntry( Bnd_ManSpec2Impl(id) , 0 ) ); Vec_BitPush( vEI_phase, Vec_BitEntry( vSpec2Impl_phase, id ) ); } Vec_IntForEachEntry( vEO_spec, id, i ) { - Vec_IntPush( vEO_impl, Vec_IntEntry( vSpec2Impl, id ) ); + Vec_IntPush( vEO_impl, Vec_IntEntry( Bnd_ManSpec2Impl(id), 0 ) ); Vec_BitPush( vEO_phase, Vec_BitEntry( vSpec2Impl_phase, id ) ); } @@ -751,11 +736,11 @@ void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) // count number of choice of boundary Vec_IntForEachEntry( vEO_spec, id, i ) { - pBnd -> nChoice_impl += Vec_IntEntry( pBnd -> vSpec2Impl_diff, id ); + pBnd -> nChoice_impl += Bnd_ManSpec2ImplNum( id ) - 1; } Vec_IntForEachEntry( vEO_impl, id, i ) { - pBnd -> nChoice_spec += Vec_IntEntry( pBnd -> vImpl2Spec_diff, id ); + pBnd -> nChoice_spec += Bnd_ManImpl2SpecNum( id ) - 1; } // print @@ -781,7 +766,6 @@ void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) } - /**Function************************************************************* Synopsis [] @@ -793,7 +777,6 @@ void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) SeeAlso [] ***********************************************************************/ - Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec_Bit_t* vEI_phase, Vec_Bit_t* vEO_phase ) { Gia_Man_t * pNew, * pTemp; @@ -925,6 +908,17 @@ void Bnd_AddNodeRec( Gia_Man_t *p, Gia_Man_t *pNew, Gia_Obj_t *pObj, int fSkipSt } } +/**Function************************************************************* + + Synopsis [] + + Description [perform ECO directly (not used)] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPatch ) { @@ -1051,6 +1045,17 @@ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPat return pNew; } +/**Function************************************************************* + + Synopsis [] + + Description [recover bounadry] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ) { @@ -1136,6 +1141,18 @@ Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ) return pNew; } +/**Function************************************************************* + + Synopsis [] + + Description [perform eco with recovered boundary. + bnd_man is not used] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ Gia_Man_t* Bnd_ManGenPatched2( Gia_Man_t *pImpl, Gia_Man_t *pPatch, int fSkipStrash, int fVerbose ) { @@ -1318,12 +1335,36 @@ Gia_Man_t* Bnd_ManStackGias( Gia_Man_t *pSpec, Gia_Man_t *pImpl ) iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } + // miter + // Gia_ManForEachCo( pImpl, pObj, i ) + // { + // iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(Gia_ManCo(pSpec,i)) ); + // Gia_ManAppendCo( pNew, iLit ); + // } + + Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } +int Bnd_ManCheckCoMerged( Gia_Man_t* p ) +{ + int nCO = Gia_ManCoNum(p)/2; + + Gia_Obj_t* pObj1; + Gia_Obj_t* pObj2; + + for ( int i = 0; i < nCO; i++ ) + { + pObj1 = Gia_ManCo(p, i); + pObj2 = Gia_ManCo(p, i + nCO); + if ( Gia_ObjFaninLit0p(p, pObj1) != Gia_ObjFaninLit0p(p, pObj2) ) return 0; + } + return 1; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 7084b5897..70b392b3c 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -52081,6 +52081,7 @@ usage: Abc_Print( -2, "\t (the PO count of should not be less than the PI count of )\n"); return 1;} +extern Bnd_Man_t* pBnd; /**Function************************************************************* Synopsis [] @@ -52092,8 +52093,6 @@ usage: SeeAlso [] ***********************************************************************/ - -extern Bnd_Man_t* pBnd; int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); @@ -52102,7 +52101,7 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_Man_t *pSpec, *pImpl_out = 0, *pSpec_out = 0, *pMiter, *pPatched = 0, *pTemp, *pBmiter; char * FileName = NULL; FILE * pFile = NULL; - int c, fVerbose = 0, success = 1; + int c, fVerbose = 0, success = 1, fEq = 1, fEqOut = 1; // params Gps_Par_t Pars, * pPars = &Pars; @@ -52115,7 +52114,7 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) // parse options Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vhCk" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "vhCkeo" ) ) != EOF ) { switch ( c ) { @@ -52137,6 +52136,12 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'k': pParsFra ->fUseCones ^= 1; break; + case 'e': + fEq ^= 1; + break; + case 'o': + fEqOut ^= 1; + break; case 'h': goto usage; default: @@ -52182,34 +52187,33 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) // start boundary manager pBnd = Bnd_ManStart( pSpec, pAbc->pGia, fVerbose ); - // verify if spec eq impl - pMiter = Gia_ManMiter( pAbc->pGia, pSpec, 0, 1, 0, 0, 0 ); - if ( !Cec_ManVerify( pMiter, pParsCec ) ) - { - Abc_Print( -1, "Abc_CommandAbc9BRecover(): The given spec is not equivalent to current impl.\n" ); - success = 0; - } - Gia_ManStop(pMiter); - // check boundary - if ( success ) + if ( 0 == Bnd_ManCheckBound( pSpec, fVerbose ) ) { - if ( 0 == Bnd_ManCheckBound( pSpec, fVerbose ) ) - { - Abc_Print( -1, "Abc_CommandAbc9BRecover(): The given spec has invalid boundary.\n" ); - success = 0; - } + Abc_Print( -1, "Abc_CommandAbc9BRecover(): The given spec has invalid boundary.\n" ); + success = 0; } if ( success ) { // create bmiter, run fraig, record mapping - // pBmiter = Gia_ManBoundaryMiter( pSpec, pAbc->pGia, 0 ); pBmiter = Bnd_ManStackGias( pSpec, pAbc->pGia ); pTemp = Cec4_ManSimulateTest( pBmiter, pParsFra ); + + // every output should be equivalent + // else, terminate the command (TODO?) + if ( !Bnd_ManCheckCoMerged( pTemp ) ) + { + Abc_Print( -1, "Abc_CommandAbc9BRecover(): The given spec and impl cannot be proved equivalent.\n" ); + success = 0; + } + Gia_ManStop(pBmiter); Gia_ManStop(pTemp); + } + if ( success ) + { // find Bnd_ManFindBound( pSpec, pAbc->pGia ); @@ -52223,22 +52227,30 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) // Gia_AigerWrite( pImpl_out, "impl_out.aig", 0, 0, 0 ); // Gia_ManPrintStats( pSpec_out, pPars ); // Gia_ManPrintStats( pImpl_out, pPars ); + + if ( !success ) + { + printf("Abc_CommandAbc9BRecover(): The generated boundary is invalid. The circuit is not changed.\n"); + } } - if ( !success ) - { - printf("Abc_CommandAbc9BRecover(): The generated boundary is invalid. The circuit is not changed.\n"); - } - else + if ( success ) { // check if spec_out and imnpl_out are equivalent if ( fVerbose ) { - printf("Checking the equivalence of spec_out and impl_out\n"); - pMiter = Gia_ManMiter( pSpec_out, pImpl_out, 0, 1, 0, 0, 0 ); - Bnd_ManSetEqOut( Cec_ManVerify( pMiter, pParsCec ) ); - Gia_ManStop( pMiter ); + if ( fEqOut ) + { + printf("Checking the equivalence of spec_out and impl_out\n"); + pMiter = Gia_ManMiter( pSpec_out, pImpl_out, 0, 1, 0, 0, 0 ); + Bnd_ManSetEqOut( Cec_ManVerify( pMiter, pParsCec ) ); + Gia_ManStop( pMiter ); + } + else + { + printf("Skip checking the equivalence of spec_out and impl_out\n"); + } } // generate patched impl @@ -52260,15 +52272,22 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) // Gia_ManStop( pTemp ); // check if patched is equiv to spec - if ( fVerbose ) printf("Checking the equivalence of patched impl and spec\n"); - pMiter = Gia_ManMiter( pSpec, pPatched, 0, 1, 0, 0, 0 ); - success = Cec_ManVerify( pMiter, pParsCec ); - Bnd_ManSetEqRes( success ); - if ( !success ) + if ( fVerbose ) { - printf("Failed. The generated AIG is not equivalent.\n"); + if ( fEq ) printf("Checking the equivalence of patched impl and spec\n"); + else printf("Skip checking the equivalence of patched impl and spec\n"); + } + if ( fEq ) + { + pMiter = Gia_ManMiter( pSpec, pPatched, 0, 1, 0, 0, 0 ); + success = Cec_ManVerify( pMiter, pParsCec ); + Bnd_ManSetEqRes( success ); + if ( !success ) + { + printf("Failed. The generated AIG is not equivalent.\n"); + } + Gia_ManStop( pMiter ); } - Gia_ManStop( pMiter ); } @@ -52279,7 +52298,8 @@ int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pImpl_out ) Gia_ManStop( pImpl_out ); if ( success ) { - printf("Success. The generated hierarchical impl is equivalent. (box size: %d -> %d)\n", Bnd_ManGetNInternal(), Bnd_ManGetNInternal() + Bnd_ManGetNExtra() ); + if ( fEq ) printf("Success. The generated hierarchical impl is equivalent. (box size: %d -> %d)\n", Bnd_ManGetNInternal(), Bnd_ManGetNInternal() + Bnd_ManGetNExtra() ); + else printf("Success. But the equivalence in unknown (box size: %d -> %d)\n", Bnd_ManGetNInternal(), Bnd_ManGetNInternal() + Bnd_ManGetNExtra() ); } if (pPatched) Abc_FrameUpdateGia( pAbc, pPatched ); Bnd_ManStop(); @@ -52291,6 +52311,10 @@ usage: Abc_Print( -2, "\t recover boundary using SAT-Sweeping\n" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t-k : toggle using logic cones in the SAT solver [default = %s]\n", pParsFra->fUseCones? "yes": "no" ); + Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pParsFra->nBTLimit ); + Abc_Print( -2, "\t-e : toggle checking the equivalence of the result [default = %s]\n", fEq? "yes": "no" ); + Abc_Print( -2, "\t-o : toggle checking the equivalence of the outsides in verbose [default = %s]\n", fEqOut? "yes": "no" ); Abc_Print( -2, "\t : the implementation aig. (should be equivalent to spec)\n"); Abc_Print( -2, "\t : the modified spec. (should be a hierarchical AIG)\n"); return 1; From 210474b08c3e018606f49eef2ae31434937ef78c Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 18 Mar 2024 07:49:35 +0900 Subject: [PATCH 122/151] Bug fix in &gen_hie. --- src/aig/gia/giaMan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index 288c06536..f2d403ded 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -2282,6 +2282,8 @@ void Gia_GenSandwich( char ** pFNames, int nFNames, char * pFileName ) fprintf( pFile, "endmodule\n" ); fclose( pFile ); for ( i = 0; i < nFNames; i++ ) { + Vec_PtrFreeFree( pGias[i]->vNamesIn ); pGias[i]->vNamesIn = NULL; + Vec_PtrFreeFree( pGias[i]->vNamesOut ); pGias[i]->vNamesOut = NULL; Gia_ManDumpVerilog( pGias[i], Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v"), NULL, 0, 0, 1, 0, 0 ); printf( "Dumped Verilog file \"%s\"\n", Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v") ); } From 3737a69d8d64cdbfafbfc0727bd291343d3ec25f Mon Sep 17 00:00:00 2001 From: aletempiac Date: Mon, 18 Mar 2024 10:01:59 +0100 Subject: [PATCH 123/151] Adding new ACD66 with support for multiple shared-set variables --- src/map/if/acd/ac_wrapper.cpp | 4 +- src/map/if/acd/acd66.hpp | 488 +++++++++++++++++++++++++++++++--- 2 files changed, 457 insertions(+), 35 deletions(-) diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index e47847f10..6ee265318 100644 --- a/src/map/if/acd/ac_wrapper.cpp +++ b/src/map/if/acd/ac_wrapper.cpp @@ -117,7 +117,7 @@ int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition ) { using namespace acd; - acd66_impl acd( nVars, false ); + acd66_impl acd( nVars, true, false ); if ( acd.run( pTruth ) == 0 ) return 0; @@ -138,7 +138,7 @@ int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition { using namespace acd; - acd66_impl acd( nVars, false ); + acd66_impl acd( nVars, true, false ); acd.run( pTruth ); int val = acd.compute_decomposition(); diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 7d7a14faa..5891f7b90 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -52,14 +52,14 @@ private: using LTT = kitty::static_truth_table<6>; public: - explicit acd66_impl( uint32_t const num_vars, bool const verify = false ) - : num_vars( num_vars ), verify( verify ) + explicit acd66_impl( uint32_t const num_vars, bool multiple_shared_set = false, bool const verify = false ) + : num_vars( num_vars ), multiple_ss( multiple_shared_set ), verify( verify ) { std::iota( permutations.begin(), permutations.end(), 0 ); } /*! \brief Runs ACD 66 */ - int run( word* ptt ) + bool run( word* ptt ) { assert( num_vars > 6 ); @@ -73,7 +73,7 @@ public: init_truth_table( ptt ); /* run ACD trying different bound sets and free sets */ - return find_decomposition() ? 1 : 0; + return find_decomposition(); } /*! \brief Runs ACD 66 */ @@ -123,11 +123,11 @@ public: { if ( bs_support_size == UINT32_MAX ) { - return num_vars + 1 + ( best_multiplicity > 2 ? 1 : 0 ); + return num_vars + 1 + num_shared_vars; } /* real value after support minimization */ - return bs_support_size + best_free_set + 1 + ( best_multiplicity > 2 ? 1 : 0 ); + return bs_support_size + best_free_set + 1 + num_shared_vars; } /* contains a 1 for FS variables */ @@ -160,6 +160,12 @@ private: best_multiplicity = UINT32_MAX; best_free_set = UINT32_MAX; + /* use multiple shared set variables */ + if ( multiple_ss ) + { + return find_decomposition_bs_multi_ss( num_vars - 6 ); + } + uint32_t max_free_set = num_vars == 11 ? 5 : 4; /* find ACD "66" for different number of variables in the free set */ @@ -178,6 +184,12 @@ private: best_multiplicity = UINT32_MAX; best_free_set = UINT32_MAX; + /* use multiple shared set variables */ + if ( multiple_ss ) + { + return find_decomposition_bs_offset_multi_ss( std::max( num_vars - 6, offset ), offset ); + } + uint32_t max_free_set = ( num_vars == 11 || offset == 5 ) ? 5 : 4; /* find ACD "66" for different number of variables in the free set */ @@ -238,6 +250,40 @@ private: return size; } + uint32_t column_multiplicity2( STT const& tt, uint32_t free_set_size, uint32_t const limit ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t cofactors[32]; + uint32_t size = 0; + + /* extract iset functions */ + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t k; + for ( k = 0; k < size; ++k ) + { + if ( fs_fn == cofactors[k] ) + break; + } + if ( k == limit ) + return limit + 1; + if ( k == size ) + cofactors[size++] = fs_fn; + sub >>= shift; + } + } + + return size; + } + inline bool combinations_next( uint32_t k, uint32_t offset, uint32_t* pComb, uint32_t* pInvPerm, STT& tt ) { uint32_t i; @@ -267,6 +313,33 @@ private: return true; } + inline bool combinations_next_simple( uint32_t k, uint32_t* pComb, uint32_t* pInvPerm, uint32_t size ) + { + uint32_t i; + + for ( i = k - 1; pComb[i] == size - k + i; --i ) + { + if ( i == 0 ) + return false; + } + + /* move vars */ + uint32_t var_old = pComb[i]; + uint32_t pos_new = pInvPerm[var_old + 1]; + std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] ); + std::swap( pComb[i], pComb[pos_new] ); + + for ( uint32_t j = i + 1; j < k; j++ ) + { + var_old = pComb[j]; + pos_new = pInvPerm[pComb[j - 1] + 1]; + std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] ); + std::swap( pComb[j], pComb[pos_new] ); + } + + return true; + } + bool find_decomposition_bs( uint32_t free_set_size ) { STT tt = start_tt; @@ -312,6 +385,7 @@ private: /* move shared variable as the most significative one */ swap_inplace_local( best_tt, res, num_vars - 1 ); std::swap( permutations[res], permutations[num_vars - 1] ); + num_shared_vars = 1; return true; } } @@ -350,6 +424,7 @@ private: /* move shared variable as the most significative one */ swap_inplace_local( best_tt, res, num_vars - 1 ); std::swap( permutations[res], permutations[num_vars - 1] ); + num_shared_vars = 1; return true; } } @@ -401,6 +476,179 @@ private: /* move shared variable as the most significative one */ swap_inplace_local( best_tt, res, num_vars - 1 ); std::swap( permutations[res], permutations[num_vars - 1] ); + num_shared_vars = 1; + return true; + } + } + } while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) ); + + return false; + } + + bool find_decomposition_bs_multi_ss( uint32_t free_set_size ) + { + STT tt = start_tt; + + /* works up to 16 input truth tables */ + assert( num_vars <= 16 ); + + /* init combinations */ + uint32_t pComb[16], pInvPerm[16], shared_set[4]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + best_free_set = free_set_size; + do + { + uint32_t cost = column_multiplicity2( tt, free_set_size, 1 << ( 6 - free_set_size ) ); + if ( cost <= 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + return true; + } + + uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2 + : cost <= 16 ? 3 + : cost <= 32 ? 4 + : 5; + if ( ss_vars_needed + free_set_size < 6 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set_multi( tt, ss_vars_needed, shared_set ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + /* move shared variables as the most significative ones */ + for ( int32_t i = res - 1; i >= 0; --i ) + { + swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i ); + std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] ); + } + num_shared_vars = res; + return true; + } + } + } while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) ); + + return false; + } + + bool find_decomposition_bs_offset_multi_ss( uint32_t free_set_size, uint32_t offset ) + { + STT tt = best_tt; + + /* works up to 16 input truth tables */ + assert( num_vars <= 16 ); + best_free_set = free_set_size; + uint32_t shared_set[4]; + + /* special case */ + if ( free_set_size == offset ) + { + uint32_t cost = column_multiplicity2( tt, free_set_size, 1 << ( 6 - free_set_size ) ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + return true; + } + + uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2 + : cost <= 16 ? 3 + : cost <= 32 ? 4 + : 5; + + if ( ss_vars_needed + free_set_size < 6 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set_multi( tt, ss_vars_needed, shared_set ); + + if ( res >= 0 ) + { + best_tt = tt; + /* move shared variables as the most significative ones */ + for ( int32_t i = res - 1; i >= 0; --i ) + { + swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i ); + std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] ); + } + num_shared_vars = res; + return true; + } + } + return false; + } + + /* init combinations */ + uint32_t pComb[16], pInvPerm[16]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + do + { + uint32_t cost = column_multiplicity2( tt, free_set_size, 1 << ( 6 - free_set_size ) ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + return true; + } + + uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2 + : cost <= 16 ? 3 + : cost <= 32 ? 4 + : 5; + + if ( ss_vars_needed + free_set_size < 6 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set_multi( tt, ss_vars_needed, shared_set ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + /* move shared variables as the most significative ones */ + for ( int32_t i = res - 1; i >= 0; --i ) + { + swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i ); + std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] ); + } + num_shared_vars = res; return true; } } @@ -462,9 +710,87 @@ private: return -1; } + bool check_shared_var_combined( STT const& tt, uint32_t free_set_size, uint32_t shared_vars[6], uint32_t num_shared_vars ) + { + assert( free_set_size <= 5 ); + assert( num_shared_vars <= 4 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t cofactors[16][2]; + uint32_t size[16] = { 0 }; + + /* extract iset functions */ + uint32_t iteration_counter = 0; + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t p = 0; + for ( uint32_t k = 0; k < num_shared_vars; ++k ) + { + p += ( ( iteration_counter >> shared_vars[k] ) & 1 ) << k; + } + + uint32_t k; + for ( k = 0; k < size[p]; ++k ) + { + if ( fs_fn == cofactors[p][k] ) + break; + } + if ( k == 2 ) + return false; + if ( k == size[p] ) + cofactors[p][size[p]++] = fs_fn; + sub >>= shift; + ++iteration_counter; + } + } + + return true; + } + + inline int check_shared_set_multi( STT const& tt, uint32_t target_num_ss, uint32_t* res_shared ) + { + /* init combinations */ + uint32_t pComb[6], pInvPerm[6]; + + /* search for a feasible shared set */ + for ( uint32_t i = target_num_ss; i < 6 - best_free_set; ++i ) + { + for ( uint32_t i = 0; i < 6; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + do + { + /* check for combined shared set */ + if ( check_shared_var_combined( tt, best_free_set, pComb, i ) ) + { + for ( uint32_t j = 0; j < i; ++j ) + { + res_shared[j] = pComb[j]; + } + /* sort vars */ + std::sort( res_shared, res_shared + i ); + return i; + } + } while ( combinations_next_simple( i, pComb, pInvPerm, num_vars - best_free_set ) ); + } + + return -1; + } + void compute_decomposition_impl( bool verbose = false ) { - bool has_shared_set = best_multiplicity > 2; + if ( num_shared_vars > 1 ) + return compute_decomposition_impl_multi_ss( verbose ); + + bool has_shared_set = num_shared_vars > 0; /* construct isets involved in multiplicity */ LTT isets0[2]; @@ -545,6 +871,98 @@ private: } } + void compute_decomposition_impl_multi_ss( bool verbose = false ) + { + /* due to the high multiplicity value this method does not perform support minimization */ + + /* construct isets involved in multiplicity */ + LTT composition; + LTT bs; + + /* construct isets */ + uint32_t offset = 0; + uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << best_free_set; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const num_groups = 1 << num_shared_vars; + uint32_t const next_group = 1 << ( num_vars - best_free_set - num_shared_vars ); + + uint64_t fs_fun[32] = { 0 }; + + uint32_t group_index = 0; + uint32_t set_index = 0; + fs_fun[0] = best_tt._bits[0] & mask; + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t cof = best_tt._bits[i]; + for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) + { + uint64_t val = cof & mask; + /* move to next block */ + if ( set_index == next_group ) + { + group_index += 2; + set_index = 0; + fs_fun[group_index] = val; + } + /* gather encoding */ + if ( val != fs_fun[group_index] ) + { + bs._bits |= UINT64_C( 1 ) << ( j + offset ); + fs_fun[group_index + 1] = val; + } + cof >>= shift; + ++set_index; + } + offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F; + } + + /* create composition function */ + for ( uint32_t i = 0; i < 2 * num_groups; ++i ) + { + composition._bits |= fs_fun[i] << ( i * shift ); + } + + /* minimize support BS */ + LTT care; + bs_support_size = 0; + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX }; + care._bits = masks[num_vars - best_free_set]; + for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) + { + if ( !has_var6( bs, care, i ) ) + { + continue; + } + + if ( bs_support_size < i ) + { + kitty::swap_inplace( bs, bs_support_size, i ); + } + + bs_support[bs_support_size] = i; + ++bs_support_size; + } + + /* assign functions */ + dec_funcs[0] = bs._bits; + dec_funcs[1] = composition._bits; + + /* print functions */ + if ( verbose ) + { + LTT f; + f._bits = dec_funcs[0]; + std::cout << "BS function : "; + kitty::print_hex( f ); + std::cout << "\n"; + f._bits = dec_funcs[1]; + std::cout << "Composition function: "; + kitty::print_hex( f ); + std::cout << "\n"; + } + } + inline void compute_functions( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4] ) { /* u = 2 no support minimization */ @@ -689,26 +1107,6 @@ private: } } - inline void reposition_late_arriving_variables( unsigned delay_profile, uint32_t late_arriving ) - { - uint32_t k = 0; - for ( uint32_t i = 0; i < late_arriving; ++i ) - { - while ( ( ( delay_profile >> k ) & 1 ) == 0 ) - ++k; - - if ( permutations[i] == k ) - { - ++k; - continue; - } - - std::swap( permutations[i], permutations[k] ); - swap_inplace_local( best_tt, i, k ); - ++k; - } - } - template void local_extend_to( TT_type& tt, uint32_t real_num_vars ) { @@ -734,6 +1132,26 @@ private: } } + inline void reposition_late_arriving_variables( unsigned delay_profile, uint32_t late_arriving ) + { + uint32_t k = 0; + for ( uint32_t i = 0; i < late_arriving; ++i ) + { + while ( ( ( delay_profile >> k ) & 1 ) == 0 ) + ++k; + + if ( permutations[i] == k ) + { + ++k; + continue; + } + + std::swap( permutations[i], permutations[k] ); + swap_inplace_local( best_tt, i, k ); + ++k; + } + } + void swap_inplace_local( STT& tt, uint8_t var_index1, uint8_t var_index2 ) { if ( var_index1 == var_index2 ) @@ -860,13 +1278,13 @@ private: /* write top LUT */ /* write fanin size */ - uint32_t support_size = best_free_set + 1 + ( best_multiplicity > 2 ? 1 : 0 ); + uint32_t support_size = best_free_set + 1 + num_shared_vars; *pArray = support_size; pArray++; ++bytes; /* write support */ - for ( uint32_t i = 0; i < best_free_set; ++i ) + for ( uint32_t i = best_free_set; i < best_free_set; ++i ) { *pArray = (unsigned char)permutations[i]; pArray++; @@ -877,9 +1295,9 @@ private: pArray++; ++bytes; - if ( best_multiplicity > 2 ) + for ( uint32_t i = 0; i < num_shared_vars; ++i ) { - *pArray = (unsigned char)permutations[num_vars - 1]; + *pArray = (unsigned char)permutations[num_vars - num_shared_vars + i]; pArray++; ++bytes; } @@ -938,9 +1356,11 @@ private: pattern |= get_bit( pis[j], i ) << j; } pattern |= get_bit( bsf_sim, i ) << best_free_set; - if ( best_multiplicity > 2 ) + + /* shared variables */ + for ( auto j = 0u; j < num_shared_vars; ++j ) { - pattern |= get_bit( pis[num_vars - 1], i ) << ( best_free_set + 1 ); + pattern |= get_bit( pis[num_vars - num_shared_vars + j], i ) << ( best_free_set + 1 + j ); } if ( ( dec_funcs[1] >> pattern ) & 1 ) @@ -991,12 +1411,14 @@ private: uint32_t best_multiplicity0{ UINT32_MAX }; uint32_t best_multiplicity1{ UINT32_MAX }; uint32_t bs_support_size{ UINT32_MAX }; + uint32_t num_shared_vars{ 0 }; STT best_tt; STT start_tt; uint64_t dec_funcs[2]; uint32_t bs_support[6]; uint32_t const num_vars; + bool const multiple_ss; bool const verify; std::array permutations; }; From 914b3e980f3cbd27398b4e03787817c9cdc54f13 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 18 Mar 2024 19:50:00 +0900 Subject: [PATCH 124/151] FIxing Windows makefile. --- abclib.dsp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/abclib.dsp b/abclib.dsp index 3255424db..5a45dafa4 100644 --- a/abclib.dsp +++ b/abclib.dsp @@ -4903,6 +4903,10 @@ SOURCE=.\src\aig\gia\giaBidec.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaBound.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaCCof.c # End Source File # Begin Source File From c0989e93f015761f6fe1fffb0a15fa289965baac Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 18 Mar 2024 20:37:46 +0900 Subject: [PATCH 125/151] Fixing Makefile on Windows. --- abclib.dsp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/abclib.dsp b/abclib.dsp index 5a45dafa4..a1c22f6c0 100644 --- a/abclib.dsp +++ b/abclib.dsp @@ -3591,6 +3591,10 @@ SOURCE=.\src\map\if\ifTune.c # End Source File # Begin Source File +SOURCE=.\src\map\if\acd\ac_wrapper.cpp +# End Source File +# Begin Source File + SOURCE=.\src\map\if\ifUtil.c # End Source File # End Group From b31ab1960b321ad30179ef113ab8bb024e58a67a Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 18 Mar 2024 21:30:46 +0900 Subject: [PATCH 126/151] Fixing compilation issues on Windows. --- src/map/if/acd/ac_wrapper.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h index 03f17ed40..4dbb1dee7 100644 --- a/src/map/if/acd/ac_wrapper.h +++ b/src/map/if/acd/ac_wrapper.h @@ -20,6 +20,12 @@ #ifndef __ACD_WRAPPER_H_ #define __ACD_WRAPPER_H_ +#ifdef _MSC_VER +# include // std::iota +# include +# define __builtin_popcount __popcnt +#endif + #include "misc/util/abc_global.h" #include "map/if/if.h" From c32f36af0884a2b91f1b115745466b8505d871f5 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 19 Mar 2024 08:13:07 +0900 Subject: [PATCH 127/151] Fixing c vs c++ header file issue. --- src/map/if/acd/ac_wrapper.h | 1 - src/map/if/acd/kitty_constants.hpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h index 4dbb1dee7..34226b10c 100644 --- a/src/map/if/acd/ac_wrapper.h +++ b/src/map/if/acd/ac_wrapper.h @@ -21,7 +21,6 @@ #define __ACD_WRAPPER_H_ #ifdef _MSC_VER -# include // std::iota # include # define __builtin_popcount __popcnt #endif diff --git a/src/map/if/acd/kitty_constants.hpp b/src/map/if/acd/kitty_constants.hpp index 35ff489e9..180180c42 100644 --- a/src/map/if/acd/kitty_constants.hpp +++ b/src/map/if/acd/kitty_constants.hpp @@ -4,6 +4,7 @@ #include #include +#include // std::iota ABC_NAMESPACE_CXX_HEADER_START From 5d3d77fcfe6e1d14a5e337da24f6d3cacec42a17 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 19 Mar 2024 08:54:32 +0900 Subject: [PATCH 128/151] Fixing Windows compiler problem. --- src/map/if/acd/ac_wrapper.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h index 34226b10c..a39e9145d 100644 --- a/src/map/if/acd/ac_wrapper.h +++ b/src/map/if/acd/ac_wrapper.h @@ -23,6 +23,7 @@ #ifdef _MSC_VER # include # define __builtin_popcount __popcnt +# define __builtin_popcountl __popcnt64 #endif #include "misc/util/abc_global.h" From 2c0943ff623d5deb7a3278357ec40c1a9765cc11 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 19 Mar 2024 09:34:20 +0900 Subject: [PATCH 129/151] Fixiing compiler problem on Windows. --- src/map/if/acd/ac_wrapper.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h index a39e9145d..a6e54b0a9 100644 --- a/src/map/if/acd/ac_wrapper.h +++ b/src/map/if/acd/ac_wrapper.h @@ -23,7 +23,8 @@ #ifdef _MSC_VER # include # define __builtin_popcount __popcnt -# define __builtin_popcountl __popcnt64 +//# define __builtin_popcountl __popcnt64 // the compiler does not find __popcnt64 +# define __builtin_popcountl __popcnt #endif #include "misc/util/abc_global.h" From 783a5404a2ba08d3a1d0b55796212c194c3d6646 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 19 Mar 2024 09:57:52 +0900 Subject: [PATCH 130/151] Fixing Windows makefile. --- abclib.dsp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/abclib.dsp b/abclib.dsp index a1c22f6c0..06802171f 100644 --- a/abclib.dsp +++ b/abclib.dsp @@ -3527,6 +3527,10 @@ SOURCE=.\src\map\if\ifDec16.c # End Source File # Begin Source File +SOURCE=.\src\map\if\ifDec66.c +# End Source File +# Begin Source File + SOURCE=.\src\map\if\ifDec75.c # End Source File # Begin Source File From 8a314db8dc9db2c617226cd3fafd2944749a1c93 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Fri, 22 Mar 2024 15:39:52 +0100 Subject: [PATCH 131/151] Bug fix --- src/map/if/acd/acd66.hpp | 2 +- src/map/if/acd/acd666.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 5891f7b90..aea9752e6 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -1024,7 +1024,7 @@ private: if ( support_vars2 > support_vars1 ) { f = isets0[0] | isets1[1]; - std::swap( fs_fun[3], fs_fun[4] ); + std::swap( fs_fun[2], fs_fun[3] ); bs_support_size = support_vars1; } diff --git a/src/map/if/acd/acd666.hpp b/src/map/if/acd/acd666.hpp index 72ae68ec4..1086af0a3 100644 --- a/src/map/if/acd/acd666.hpp +++ b/src/map/if/acd/acd666.hpp @@ -646,7 +646,7 @@ private: { f._bits[i] = isets0[0]._bits[i] | isets1[1]._bits[i]; } - std::swap( fs_fun[3], fs_fun[4] ); + std::swap( fs_fun[2], fs_fun[3] ); rm_support_size = support_vars1; } @@ -705,7 +705,7 @@ private: if ( support_vars2 > support_vars1 ) { f = isets0[0] | isets1[1]; - std::swap( fs_fun[3], fs_fun[4] ); + std::swap( fs_fun[2], fs_fun[3] ); support_sizes[0] = support_vars1; } From 6aacf524aa1fbb1fa010cdf07fa0fbea97b1137b Mon Sep 17 00:00:00 2001 From: aletempiac Date: Fri, 22 Mar 2024 19:19:35 +0100 Subject: [PATCH 132/151] Performance improvement and fixes --- src/map/if/acd/ac_decomposition.hpp | 54 ++++++++++++++++++----------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index d573da2cd..0ad1e34c2 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -118,11 +118,12 @@ public: } if ( late_arriving > ps.max_free_set_vars ) { - ps.max_free_set_vars = late_arriving; + return -1; /* on average avoiding this computation leads to better quality */ + // ps.max_free_set_vars = late_arriving; } /* return a high cost if too many late arriving variables */ - if ( late_arriving > ps.lut_size - 1 || late_arriving > ps.max_free_set_vars ) + if ( late_arriving > ps.lut_size - 1 ) { return -1; } @@ -632,13 +633,10 @@ private: uint32_t k = 0; for ( uint32_t j = 0; j < num_vars - best_free_set; ++j ) { - if ( !kitty::has_var( tt, j ) ) - continue; - if ( !kitty::has_var( tt, care, j ) ) { /* fix truth table */ - adjust_truth_table_on_dc( tt, care, j ); + adjust_truth_table_on_dc( tt, care, tt.num_vars(), j ); continue; } @@ -788,7 +786,14 @@ private: } } support_minimization_encodings = std::vector>( num_combs ); - generate_support_minimization_encodings_rec( 0, 0, 0, count ); + generate_support_minimization_encodings_rec( 0, 0, 0, count ); + } + else if ( best_multiplicity > 8 ) + { + /* combinations are 2^(mu - 1) */ + num_combs = 1u << ( best_multiplicity - 1 ); + support_minimization_encodings = std::vector>( num_combs ); + generate_support_minimization_encodings_rec( 0, 0, 0, count ); } else { @@ -798,18 +803,18 @@ private: num_combs = ( num_combs << 1 ) + num_combs; } support_minimization_encodings = std::vector>( num_combs ); - generate_support_minimization_encodings_rec( 0, 0, 0, count ); + generate_support_minimization_encodings_rec( 0, 0, 0, count ); } assert( count == num_combs ); } - template + template void generate_support_minimization_encodings_rec( uint32_t onset, uint32_t offset, uint32_t var, uint32_t& count ) { if ( var == best_multiplicity ) { - if ( !enable_dcset ) + if ( equal_size_partition ) { /* sets must be equally populated */ if ( __builtin_popcount( onset ) != __builtin_popcount( offset ) ) @@ -827,12 +832,12 @@ private: /* var in DCSET */ if ( enable_dcset ) { - generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); } /* move var in ONSET */ onset |= 1 << var; - generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); onset &= ~( 1 << var ); /* remove symmetries */ @@ -843,7 +848,7 @@ private: /* move var in OFFSET */ offset |= 1 << var; - generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); offset &= ~( 1 << var ); } @@ -1042,6 +1047,13 @@ private: for ( uint32_t j = 0; j < iset_support; ++j ) { cost += has_var_support( tt, care, iset_support, j ) ? 1 : 0; + // if ( !has_var_support( tt, care, iset_support, j ) ) + // { + // /* adjust truth table and care set */ + // adjust_truth_table_on_dc( tt, care, iset_support, j ); + // continue; + // } + // ++cost; } /* discard solutions with support over LUT size */ @@ -1186,7 +1198,7 @@ private: return res; } - bool covering_improve( std::vector& matrix, std::array& solution ) + bool covering_improve( std::vector const& matrix, std::array& solution ) { /* performs one iteration of local search */ uint32_t best_cost = 0, local_cost = 0; @@ -1233,21 +1245,23 @@ private: return improved; } - void adjust_truth_table_on_dc( STT& tt, STT& care, uint32_t var_index ) + void adjust_truth_table_on_dc( STT& tt, STT& care, uint32_t real_num_vars, uint32_t var_index ) { - assert( var_index < tt.num_vars() ); + assert( var_index < real_num_vars ); assert( tt.num_vars() == care.num_vars() ); - if ( tt.num_vars() <= 6 || var_index < 6 ) + const uint32_t num_blocks = real_num_vars <= 6 ? 1 : ( 1 << ( real_num_vars - 6 ) ); + if ( real_num_vars <= 6 || var_index < 6 ) { auto it_tt = std::begin( tt._bits ); auto it_care = std::begin( care._bits ); - while ( it_tt != std::end( tt._bits ) ) + while ( it_tt != std::begin( tt._bits ) + num_blocks ) { uint64_t new_bits = *it_tt & *it_care; *it_tt = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) | ( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] ); - *it_care = *it_care | ( *it_care >> ( uint64_t( 1 ) << var_index ) ); + *it_care = ( *it_care | ( *it_care >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index]; + *it_care = *it_care | ( *it_care << ( uint64_t( 1 ) << var_index ) ); ++it_tt; ++it_care; @@ -1256,7 +1270,7 @@ private: } const auto step = 1 << ( var_index - 6 ); - for ( auto i = 0u; i < static_cast( tt.num_blocks() ); i += 2 * step ) + for ( auto i = 0u; i < static_cast( num_blocks ); i += 2 * step ) { for ( auto j = 0; j < step; ++j ) { From b0d2ff1c63106626246adea908511a8c94c4a280 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 24 Mar 2024 00:10:08 +0900 Subject: [PATCH 133/151] Exact synthesis using NAND-gates. --- src/base/abc/abc.h | 2 +- src/base/abci/abc.c | 41 ++++++++-- src/base/abci/abcPrint.c | 12 ++- src/sat/bmc/bmcMaj.c | 162 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 205 insertions(+), 12 deletions(-) diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 5cf7a0f59..58131f185 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -841,7 +841,7 @@ extern ABC_DLL void Abc_NtkPrintFanioNew( FILE * pFile, Abc_Ntk_t extern ABC_DLL void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode ); extern ABC_DLL void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ); extern ABC_DLL void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ); -extern ABC_DLL void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fVerbose ); +extern ABC_DLL void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fOutputs, int fVerbose ); extern ABC_DLL void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ); extern ABC_DLL void Abc_NtkPrintSkews( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintAll ); extern ABC_DLL void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj ); diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index b9535f423..66af8713a 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -2022,14 +2022,16 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; int fListNodes; int fProfile; + int fOutputs; int fVerbose; // set defaults fListNodes = 0; fProfile = 1; + fOutputs = 0; fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "npvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "npovh" ) ) != EOF ) { switch ( c ) { @@ -2039,6 +2041,9 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'p': fProfile ^= 1; break; + case 'o': + fOutputs ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -2079,14 +2084,15 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } // process all COs - Abc_NtkPrintLevel( stdout, pNtk, fProfile, fListNodes, fVerbose ); + Abc_NtkPrintLevel( stdout, pNtk, fProfile, fListNodes, fOutputs, fVerbose ); return 0; usage: - Abc_Print( -2, "usage: print_level [-npvh] \n" ); + Abc_Print( -2, "usage: print_level [-npovh] \n" ); Abc_Print( -2, "\t prints information about node level and cone size\n" ); Abc_Print( -2, "\t-n : toggles printing nodes by levels [default = %s]\n", fListNodes? "yes": "no" ); Abc_Print( -2, "\t-p : toggles printing level profile [default = %s]\n", fProfile? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles printing output levels [default = %s]\n", fOutputs? "yes": "no" ); Abc_Print( -2, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tnode : (optional) one node to consider\n"); @@ -9310,11 +9316,12 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) extern void Exa_ManExactSynthesis4( Bmc_EsPar_t * pPars ); extern void Exa_ManExactSynthesis5( Bmc_EsPar_t * pPars ); extern void Exa_ManExactSynthesis6( Bmc_EsPar_t * pPars, char * pFileName ); - int c, fKissat = 0, fKissat2 = 0; + extern void Exa_ManExactSynthesis7( Bmc_EsPar_t * pPars, int GateSize ); + int c, fKissat = 0, fKissat2 = 0, fUseNands = 0, GateSize = 0; Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INTadconugklvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INTGabdconugklvh" ) ) != EOF ) { switch ( c ) { @@ -9351,9 +9358,23 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->RuntimeLim < 0 ) goto usage; break; + case 'G': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" ); + goto usage; + } + GateSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( GateSize < 0 ) + goto usage; + break; case 'a': pPars->fOnlyAnd ^= 1; break; + case 'b': + fUseNands ^= 1; + break; case 'd': pPars->fDynConstr ^= 1; break; @@ -9401,7 +9422,7 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Truth table should be given on the command line.\n" ); return 1; } - if ( (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) + if ( pPars->nVars >= 2 && (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) { Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (pPars->nVars-2)), strlen(pPars->pTtStr) ); return 1; @@ -9416,7 +9437,9 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Function should not have more than 10 inputs.\n" ); return 1; } - if ( fKissat ) + if ( fUseNands ) + Exa_ManExactSynthesis7( pPars, GateSize ); + else if ( fKissat ) Exa_ManExactSynthesis4( pPars ); else if ( fKissat2 ) Exa_ManExactSynthesis5( pPars ); @@ -9427,12 +9450,14 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: twoexact [-INT ] [-adconugklvh] \n" ); + Abc_Print( -2, "usage: twoexact [-INTG ] [-abdconugklvh] \n" ); Abc_Print( -2, "\t exact synthesis of multi-input function using two-input gates\n" ); Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", pPars->nVars ); Abc_Print( -2, "\t-N : the number of two-input nodes [default = %d]\n", pPars->nNodes ); Abc_Print( -2, "\t-T : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); + Abc_Print( -2, "\t-G : the largest allowed gate size (NANDs only) [default = %d]\n", GateSize ); Abc_Print( -2, "\t-a : toggle using only AND-gates (without XOR-gates) [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); + Abc_Print( -2, "\t-b : toggle using only NAND-gates [default = %s]\n", fUseNands ? "yes" : "no" ); Abc_Print( -2, "\t-d : toggle using dynamic constraint addition [default = %s]\n", pPars->fDynConstr ? "yes" : "no" ); Abc_Print( -2, "\t-c : toggle dumping CNF into a file [default = %s]\n", pPars->fDumpCnf ? "yes" : "no" ); Abc_Print( -2, "\t-o : toggle using additional optimizations [default = %s]\n", pPars->fFewerVars ? "yes" : "no" ); diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index e90159d2a..636665249 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -1228,11 +1228,19 @@ char * Abc_NodeGetPrintName( Abc_Obj_t * pObj ) } return Abc_ObjName(nPos == 1 ? pFanout : pObj); } -void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fVerbose ) +void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fOutputs, int fVerbose ) { Abc_Obj_t * pNode; int i, k, Length; - + if ( fOutputs ) + { + Abc_NtkLevel(pNtk); + printf( "Outputs by level: " ); + Abc_NtkForEachCo( pNtk, pNode, k ) + printf( "%d=%d ", k, Abc_ObjFanin0(pNode)->Level ); + printf( "\n" ); + return; + } if ( fListNodes ) { int nLevels; diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index d3a3ac18d..40ecd4a5e 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -3724,10 +3724,170 @@ void Exa_ManExactSynthesis6( Bmc_EsPar_t * pPars, char * pFileName ) if ( pMini ) Mini_AigStop( pMini ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Exa7_AddClause( FILE * pFile, int * pLits, int nLits ) +{ + int i, k = 0; + for ( i = 0; i < nLits; i++ ) { + if ( pLits[i] == 1 ) + return 0; + else if ( pLits[i] == 0 ) + continue; + else + pLits[k++] = pLits[i]; + } + nLits = k; + assert( nLits > 0 ); + if ( pFile ) + { + for ( i = 0; i < nLits; i++ ) + fprintf( pFile, "%s%d ", Abc_LitIsCompl(pLits[i]) ? "-" : "", Abc_Lit2Var(pLits[i]) ); + fprintf( pFile, "0\n" ); + } + if ( 0 ) + { + for ( i = 0; i < nLits; i++ ) + fprintf( stdout, "%s%d ", Abc_LitIsCompl(pLits[i]) ? "-" : "", Abc_Lit2Var(pLits[i])-1 ); + fprintf( stdout, "\n" ); + } + return 1; +} +static inline int Exa7_AddClause4( FILE * pFile, int Lit0, int Lit1, int Lit2, int Lit3 ) +{ + int pLits[4] = { Lit0, Lit1, Lit2, Lit3 }; + return Exa7_AddClause( pFile, pLits, 4 ); +} +int Exa7_GetVar( int n, int i, int j, int m ) +{ + return 1 + n*n*m + n*i + j; +} +int Exa7_ManGenCnf( char * pFileName, word * pTruth, int nVars, int nNodes, int GateSize ) +{ + int m, n, v, k, nV = nVars + nNodes, nMints = 1 << nVars, nClas = 0; + int pVars[32] = {0}; assert( nVars + nNodes + 1 < 32 ); + FILE * pFile = fopen( pFileName, "wb" ); + fputs( "p cnf \n", pFile ); + for ( m = 0; m < nMints; m++ ) + { + for ( v = 0; v < nVars; v++ ) + nClas += Exa7_AddClause4( pFile, Abc_Var2Lit(Exa7_GetVar(nV, v, v, m), ((m >> v)&1)==0), 0, 0, 0 ); + nClas += Exa7_AddClause4( pFile, Abc_Var2Lit(Exa7_GetVar(nV, nV-1, nV-1, m), ((pTruth[0] >> m)&1)==0), 0, 0, 0 ); + for ( n = nVars; n < nV; n++ ) + { + int iValNode = Exa7_GetVar(nV, n, n, m); + for ( v = 0; v < n; v++ ) + { + int iParVar = Exa7_GetVar(nV, v, n, 0); // v < n + int iFanVar = Exa7_GetVar(nV, n, v, m); + int iValFan = Exa7_GetVar(nV, v, v, m); + // iFanVar = ~iParVar | iValFan + nClas += Exa7_AddClause4( pFile, Abc_Var2Lit(iFanVar, 1), Abc_Var2Lit(iParVar, 1), Abc_Var2Lit(iValFan, 0), 0 ); + nClas += Exa7_AddClause4( pFile, Abc_Var2Lit(iFanVar, 0), Abc_Var2Lit(iParVar, 0), 0, 0 ); + nClas += Exa7_AddClause4( pFile, Abc_Var2Lit(iFanVar, 0), Abc_Var2Lit(iValFan, 1), 0, 0 ); + // iParVar & ~iValFan => iValNode + nClas += Exa7_AddClause4( pFile, Abc_Var2Lit(iParVar, 1), Abc_Var2Lit(iValFan, 0), Abc_Var2Lit(iValNode, 0), 0 ); + pVars[v] = Abc_Var2Lit(iFanVar, 1); + } + pVars[v] = Abc_Var2Lit(iValNode, 1); + // (iFanVar0 & iFanVar1 & iFanVar2) => ~iValNode + nClas += Exa7_AddClause( pFile, pVars, n+1 ); + } + } + for ( n = nVars; n < nV; n++ ) { + for ( v = 0; v < n; v++ ) + pVars[v] = Abc_Var2Lit(Exa7_GetVar(nV, v, n, 0), 0); // v < n + nClas += Exa7_AddClause( pFile, pVars, n ); + if ( GateSize ) { + int Total = 1 << n, Limit = GateSize + 1; + for ( m = 0; m < Total; m++ ) + { + if ( Abc_TtCountOnes((word)m) != Limit ) + continue; + for ( k = v = 0; v < n; v++ ) + if ( (m >> v) & 1 ) + pVars[k++] = Abc_Var2Lit(Exa7_GetVar(nV, v, n, 0), 1); + assert( k == Limit ); + nClas += Exa7_AddClause( pFile, pVars, Limit ); + } + } + } + rewind( pFile ); + fprintf( pFile, "p cnf %d %d", nMints * nV * nV, nClas ); + fclose( pFile ); + return nClas; +} +void Exa_ManDumpVerilog( Vec_Int_t * vValues, int nVars, int nNodes, int GateSize, word * pTruth ) +{ + FILE * pFile; + char Buffer[1000]; + char FileName[1100]; + int v, n, k, nV = nVars+nNodes; + Extra_PrintHexadecimalString( Buffer, (unsigned *)pTruth, nVars ); + sprintf( FileName, "func%s_%d_%d.v", Buffer, GateSize, nNodes ); + pFile = fopen( FileName, "wb" ); + fprintf( pFile, "// Realization of the %d-input function %s using %d NAND gates:\n", nVars, Buffer, nNodes ); + fprintf( pFile, "module func%s_%d_%d ( input", Buffer, GateSize, nNodes ); + for ( v = 0; v < nVars; v++ ) + fprintf( pFile, " %c,", 'a'+v ); + fprintf( pFile, " output out );\n" ); + for ( n = nVars; n < nV; n++ ) { + int nFans = 0; + for ( v = 0; v < n; v++ ) + nFans += Vec_IntEntry(vValues, Exa7_GetVar(nV, v, n, 0)); + fprintf( pFile, " wire %c = ~(", 'a'+n ); + for ( k = v = 0; v < n; v++ ) + if ( Vec_IntEntry(vValues, Exa7_GetVar(nV, v, n, 0)) ) + fprintf( pFile, "%c%s", 'a'+v, ++k < nFans ? " & ":"" ); + fprintf( pFile, ");\n" ); + } + fprintf( pFile, " assign out = %c;\n", 'a'+nV-1 ); + fprintf( pFile, "endmodule\n\n" ); + fclose( pFile ); + printf( "Solution was dumped into file \"%s\".\n", FileName ); +} +void Exa_ManExactSynthesis7( Bmc_EsPar_t * pPars, int GateSize ) +{ + abctime clkTotal = Abc_Clock(); + int v, n, nMints = 1 << pPars->nVars; + int nV = pPars->nVars + pPars->nNodes; + word pTruth[16]; Abc_TtReadHex( pTruth, pPars->pTtStr ); + Vec_Int_t * vValues = NULL; + char * pFileNameIn = "_temp_.cnf"; + char * pFileNameOut = "_temp_out.cnf"; + int nClas = Exa7_ManGenCnf( pFileNameIn, pTruth, pPars->nVars, pPars->nNodes, GateSize ); + if ( pPars->fVerbose ) + printf( "CNF with %d variables and %d clauses was dumped into file \"%s\".\n", nMints * nV * nV, nClas, pFileNameIn ); + vValues = Exa4_ManSolve( pFileNameIn, pFileNameOut, pPars->RuntimeLim, pPars->fVerbose ); + if ( pPars->fVerbose && vValues ) { + printf( " " ); + for ( n = 0; n < nV; n++ ) + printf( "%2d ", n ); + printf( "\n" ); + for ( n = pPars->nVars; n < nV; n++, printf("\n") ) { + printf( "%2d : ", n ); + for ( v = 0; v < n; v++ ) + printf( " %c ", Vec_IntEntry(vValues, Exa7_GetVar(nV, v, n, 0)) ? '1':'.' ); // v < n + } + } + if ( vValues ) + Exa_ManDumpVerilog( vValues, pPars->nVars, pPars->nNodes, GateSize, pTruth ); + Vec_IntFreeP( &vValues ); + Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// - ABC_NAMESPACE_IMPL_END From 1f72ffce79413c617840f9a4ca1a33e4f81d974e Mon Sep 17 00:00:00 2001 From: aletempiac Date: Mon, 25 Mar 2024 14:23:43 +0100 Subject: [PATCH 134/151] Improving ACD performance with bail-out conditions --- src/map/if/acd/ac_decomposition.hpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index 0ad1e34c2..a384cc2e1 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -232,7 +232,7 @@ private: best_cost = multiplicity + additional_cost; best_free_set = i; - if ( !ps.use_first ) + if ( !ps.use_first && multiplicity > 2 ) { continue; } @@ -270,7 +270,7 @@ private: best_cost = multiplicity + additional_cost; best_free_set = i; - if ( !ps.use_first ) + if ( !ps.use_first && multiplicity > 2 ) { continue; } @@ -478,6 +478,13 @@ private: pComb[i] = pInvPerm[i] = i; } + /* early bail-out conditions */ + uint32_t bail_multiplicity = 2; + if ( best_multiplicity < UINT32_MAX ) + { + bail_multiplicity = ( best_multiplicity >> 1 ) + ( best_multiplicity & 1 ); + } + /* enumerate combinations */ do { @@ -490,6 +497,11 @@ private: { bestPerm[i] = pComb[i]; } + + if ( best_cost <= bail_multiplicity ) + { + break; + } } } while ( combinations_offset_next( free_set_size, offset, pComb, pInvPerm, tt ) ); From a2cb5eb4e3abb0002f88dd18b0aaa22da91e0ac1 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 25 Mar 2024 23:39:03 +0800 Subject: [PATCH 135/151] Adding command &pms to print miter status. --- src/base/abci/abc.c | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 66af8713a..c1e90a4ed 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -405,6 +405,7 @@ static int Abc_CommandAbc9Write ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9WriteLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Ps ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9PFan ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Pms ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9PSig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Status ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9MuxProfile ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1183,6 +1184,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&wlut", Abc_CommandAbc9WriteLut, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&ps", Abc_CommandAbc9Ps, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&pfan", Abc_CommandAbc9PFan, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&pms", Abc_CommandAbc9Pms, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&psig", Abc_CommandAbc9PSig, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&status", Abc_CommandAbc9Status, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&profile", Abc_CommandAbc9MuxProfile, 0 ); @@ -32511,6 +32513,57 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Pms( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Gia_Obj_t * pObj; + int c, nSat = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9PFan(): There is no AIG.\n" ); + return 1; + } + printf( "Status of %d outputs of the miter: ", Gia_ManPoNum(pAbc->pGia) ); + Gia_ManForEachPo( pAbc->pGia, pObj, c ) + { + printf( "%d", c ); + if ( pAbc->pGia->vNamesOut ) + printf( "(%s)", (char *)Vec_PtrEntry(pAbc->pGia->vNamesOut, c) ); + printf( "=%s ", Gia_ObjFaninLit0p(pAbc->pGia, pObj) == 0 ? "unsat":"sat" ); + nSat += Gia_ObjFaninLit0p(pAbc->pGia, pObj) != 0; + } + printf( "\n" ); + printf( "Total sat = %d. Total unsat = %d.\n", nSat, Gia_ManPoNum(pAbc->pGia)-nSat ); + return 0; + +usage: + Abc_Print( -2, "usage: &pms [-h]\n" ); + Abc_Print( -2, "\t prints miter status after SAT sweeping\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] From 6e1653426f41529cd3d42bbe39d322750387205e Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 28 Mar 2024 16:22:06 +0800 Subject: [PATCH 136/151] Switch to randomly select one choice. --- src/aig/gia/giaEquiv.c | 33 +++++++++++++++++++++++++++++---- src/base/abci/abc.c | 18 +++++++++++------- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/aig/gia/giaEquiv.c b/src/aig/gia/giaEquiv.c index 1c3aa4311..aec9d39ca 100644 --- a/src/aig/gia/giaEquiv.c +++ b/src/aig/gia/giaEquiv.c @@ -715,6 +715,30 @@ Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fS return pNew; } +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Obj_t * Gia_MakeRandomChoice( Gia_Man_t * p, int iRepr ) +{ + int iTemp, Rand, Count = 0; + Gia_ClassForEachObj( p, iRepr, iTemp ) + Count++; + Rand = rand() % Count; + Count = 0; + Gia_ClassForEachObj( p, iRepr, iTemp ) + if ( Count++ == Rand ) + break; + return Gia_ManObj(p, iTemp); +} + /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] @@ -735,7 +759,7 @@ void Gia_ManEquivReduce2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, if ( fDiveIn && (pRepr = Gia_ManEquivRepr(p, pObj, 1, 0)) ) { int iTemp, iRepr = Gia_ObjId(p, pRepr); - Gia_Obj_t * pRepr2 = Gia_ManObj( p, Vec_IntEntry(vMap, iRepr) ); + Gia_Obj_t * pRepr2 = vMap ? Gia_ManObj( p, Vec_IntEntry(vMap, iRepr) ) : Gia_MakeRandomChoice(p, iRepr); Gia_ManEquivReduce2_rec( pNew, p, pRepr2, vMap, 0 ); Gia_ClassForEachObj( p, iRepr, iTemp ) { @@ -751,12 +775,13 @@ void Gia_ManEquivReduce2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Gia_ManEquivReduce2_rec( pNew, p, Gia_ObjFanin1(pObj), vMap, 1 ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } -Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p ) +Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p, int fRandom ) { Vec_Int_t * vMap; Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; + if ( fRandom ) srand(time(NULL)); if ( !p->pReprs && p->pSibls ) { int * pMap = ABC_FALLOC( int, Gia_ManObjNum(p) ); @@ -789,7 +814,7 @@ Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p ) break; if ( i == Gia_ManObjNum(p) ) return Gia_ManDup( p ); - vMap = Gia_ManChoiceMinLevel( p ); + vMap = fRandom ? NULL : Gia_ManChoiceMinLevel( p ); Gia_ManSetPhase( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); @@ -805,7 +830,7 @@ Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); - Vec_IntFree( vMap ); + Vec_IntFreeP( &vMap ); return pNew; } diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index c1e90a4ed..4c540b383 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -44103,14 +44103,14 @@ usage: ***********************************************************************/ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p ); + extern Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p, int fRandom ); Gia_Man_t * pTemp; Dch_Pars_t Pars, * pPars = &Pars; - int c, fMinLevel = 0, fEquiv = 0; + int c, fMinLevel = 0, fEquiv = 0, fRandom = 0; // set defaults Dch_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfremgcxyvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfremngcxyvh" ) ) != EOF ) { switch ( c ) { @@ -44168,6 +44168,9 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': fMinLevel ^= 1; break; + case 'n': + fRandom ^= 1; + break; case 'g': pPars->fUseGia ^= 1; break; @@ -44212,14 +44215,14 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) { pTemp = Gia_ManPerformDch( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); - if ( fMinLevel ) - pTemp = Gia_ManEquivReduce2( pAbc->pGia ); + if ( fMinLevel || fRandom ) + pTemp = Gia_ManEquivReduce2( pAbc->pGia, fRandom ); } Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &dch [-WCS num] [-sptfremgcxyvh]\n" ); + Abc_Print( -2, "usage: &dch [-WCS num] [-sptfremngcxyvh]\n" ); Abc_Print( -2, "\t computes structural choices using a new approach\n" ); Abc_Print( -2, "\t-W num : the max number of simulation words [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); @@ -44230,7 +44233,8 @@ usage: Abc_Print( -2, "\t-f : toggle using lighter logic synthesis [default = %s]\n", pPars->fLightSynth? "yes": "no" ); Abc_Print( -2, "\t-r : toggle skipping choices with redundant support [default = %s]\n", pPars->fSkipRedSupp? "yes": "no" ); Abc_Print( -2, "\t-e : toggle computing and merging equivalences [default = %s]\n", fEquiv? "yes": "no" ); - Abc_Print( -2, "\t-m : toggle minimizing logic level after merging equivalences [default = %s]\n", fMinLevel? "yes": "no" ); + Abc_Print( -2, "\t-m : toggle minimizing logic level after merging equivalences [default = %s]\n", fRandom? "yes": "no" ); + Abc_Print( -2, "\t-n : toggle selecting random choices while merging equivalences [default = %s]\n", fMinLevel? "yes": "no" ); Abc_Print( -2, "\t-g : toggle using GIA to prove equivalences [default = %s]\n", pPars->fUseGia? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using circuit-based SAT vs. MiniSat [default = %s]\n", pPars->fUseCSat? "yes": "no" ); Abc_Print( -2, "\t-x : toggle using new choice computation [default = %s]\n", pPars->fUseNew? "yes": "no" ); From 8f3447800cc93f891cc84bb4bbc88e76bb5d6ef7 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Tue, 2 Apr 2024 11:25:03 +0200 Subject: [PATCH 137/151] Support again decompositions into luts smaller than 6 --- src/map/if/acd/ac_decomposition.hpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index a384cc2e1..a7321d0d5 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -1369,10 +1369,15 @@ private: std::swap( var_index1, var_index2 ); } - assert( num_vars > 6 ); const uint32_t num_blocks = 1 << ( num_vars - 6 ); - if ( var_index2 <= 5 ) + if ( num_vars <= 6 ) + { + const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + tt._bits[0] = ( tt._bits[0] & pmask[0] ) | ( ( tt._bits[0] & pmask[1] ) << shift ) | ( ( tt._bits[0] & pmask[2] ) >> shift ); + } + else if ( var_index2 <= 5 ) { const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2]; const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); From 6b5ebb3e76802a01e78c2a36e0327a270884e909 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Wed, 10 Apr 2024 18:42:52 +0200 Subject: [PATCH 138/151] Removing assertion when decomposing into LUTs smaller than 6 --- src/map/if/acd/ac_decomposition.hpp | 2 +- src/map/if/acd/ac_wrapper.h | 4 +- src/map/if/acd/acdXX.hpp | 1246 +++++++++++++++++++++++++++ 3 files changed, 1249 insertions(+), 3 deletions(-) create mode 100644 src/map/if/acd/acdXX.hpp diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp index a7321d0d5..d8a44b1d5 100644 --- a/src/map/if/acd/ac_decomposition.hpp +++ b/src/map/if/acd/ac_decomposition.hpp @@ -1369,7 +1369,7 @@ private: std::swap( var_index1, var_index2 ); } - const uint32_t num_blocks = 1 << ( num_vars - 6 ); + const uint32_t num_blocks = num_vars <= 6 ? 1 : 1 << ( num_vars - 6 ); if ( num_vars <= 6 ) { diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h index a6e54b0a9..6bde657c0 100644 --- a/src/map/if/acd/ac_wrapper.h +++ b/src/map/if/acd/ac_wrapper.h @@ -35,8 +35,8 @@ ABC_NAMESPACE_HEADER_START int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); -int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition ); -int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition ); +int acdXX_evaluate( word * pTruth, unsigned lutSize, unsigned nVars, int compute_decomposition ); +int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition ); int acd666_evaluate( word * pTruth, unsigned nVars, int compute_decomposition ); diff --git a/src/map/if/acd/acdXX.hpp b/src/map/if/acd/acdXX.hpp new file mode 100644 index 000000000..5ee6abcd6 --- /dev/null +++ b/src/map/if/acd/acdXX.hpp @@ -0,0 +1,1246 @@ +/**C++File************************************************************** + + FileName [acd66.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Ashenhurst-Curtis decomposition.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alessandro Tempia Calvino] + + Affiliation [EPFL] + + Date [Ver. 1.0. Started - Apr 10, 2024.] + +***********************************************************************/ +/*! + \file acdXX.hpp + \brief Ashenhurst-Curtis decomposition for "XX" cascade + + \author Alessandro Tempia Calvino +*/ + +#ifndef _ACDXX_H_ +#define _ACDXX_H_ +#pragma once + +#include +#include +#include +#include +#include + +#include "kitty_constants.hpp" +#include "kitty_constructors.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_operations.hpp" +#include "kitty_operators.hpp" +#include "kitty_static_tt.hpp" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace acd +{ + +struct acdXX_params +{ + uint32_t lut_size{ 6 }; + uint32_t max_shared_vars{ 4 }; + bool verify{ false }; +}; + +class acdXX_impl +{ +private: + static constexpr uint32_t max_num_vars = 11; + using STT = kitty::static_truth_table; + using LTT = kitty::static_truth_table<6>; + +public: + explicit acdXX_impl( uint32_t const num_vars, acdXX_params const& ps = {} ) + : num_vars( num_vars ), ps( ps ) + { + std::iota( permutations.begin(), permutations.end(), 0 ); + } + + /*! \brief Runs ACD XX */ + bool run( word* ptt ) + { + assert( num_vars > 4 ); + + /* truth table is too large for the settings */ + if ( num_vars > max_num_vars || num_vars >= 2 * ps.lut_size ) + { + return false; + } + + /* saturate the maximum number of shared variables */ + ps.max_shared_vars = std::min( ps.max_shared_vars, ps.lut_size - 2 ); + + /* convert to static TT */ + init_truth_table( ptt ); + + /* run ACD trying different bound sets and free sets */ + return find_decomposition(); + } + + /*! \brief Runs ACD XX */ + int run( word* ptt, unsigned delay_profile ) + { + assert( num_vars > 4 ); + + /* truth table is too large for the settings */ + if ( num_vars > max_num_vars || num_vars >= 2 * ps.lut_size ) + { + return 0; + } + + uint32_t late_arriving = __builtin_popcount( delay_profile ); + + /* too many late arriving variables */ + if ( late_arriving >= ps.lut_size ) + return 0; + + /* saturate the maximum number of shared variables */ + ps.max_shared_vars = std::min( ps.max_shared_vars, ps.lut_size - 2 ); + + /* convert to static TT */ + init_truth_table( ptt ); + best_tt = start_tt; + + /* permute late arriving variables to be the least significant */ + reposition_late_arriving_variables( delay_profile, late_arriving ); + + /* run ACD trying different bound sets and free sets */ + return find_decomposition_offset( late_arriving ) ? ( delay_profile == 0 ? 2 : 1 ) : 0; + } + + int compute_decomposition() + { + if ( best_multiplicity == UINT32_MAX ) + return -1; + + compute_decomposition_impl(); + + if ( ps.verify && !verify_impl() ) + { + return 1; + } + + return 0; + } + + uint32_t get_num_edges() + { + if ( bs_support_size == UINT32_MAX ) + { + return num_vars + 1 + num_shared_vars; + } + + /* real value after support minimization */ + return bs_support_size + best_free_set + 1 + num_shared_vars; + } + + /* contains a 1 for FS variables */ + unsigned get_profile() + { + unsigned profile = 0; + + if ( best_multiplicity == UINT32_MAX ) + return -1; + + for ( uint32_t i = 0; i < best_free_set; ++i ) + { + profile |= 1 << permutations[i]; + } + + return profile; + } + + void get_decomposition( unsigned char* decompArray ) + { + if ( bs_support_size == UINT32_MAX ) + return; + + get_decomposition_abc( decompArray ); + } + +private: + bool find_decomposition() + { + best_multiplicity = UINT32_MAX; + best_free_set = UINT32_MAX; + + /* use multiple shared set variables */ + if ( ps.max_shared_vars > 1 ) + { + return find_decomposition_bs_multi_ss( num_vars - ps.lut_size ); + } + + uint32_t max_free_set = num_vars == ( 2 * ps.lut_size - 1 ) ? ps.lut_size - 1 : ps.lut_size - 1 - ps.max_shared_vars; + + /* find ACD "XX" for different number of variables in the free set */ + for ( uint32_t i = num_vars - ps.lut_size; i <= max_free_set; ++i ) + { + if ( find_decomposition_bs( i ) ) + return true; + } + + best_multiplicity = UINT32_MAX; + return false; + } + + bool find_decomposition_offset( uint32_t offset ) + { + best_multiplicity = UINT32_MAX; + best_free_set = UINT32_MAX; + + /* use multiple shared set variables */ + if ( ps.max_shared_vars > 1 ) + { + return find_decomposition_bs_offset_multi_ss( std::max( num_vars - ps.lut_size, offset ), offset ); + } + + uint32_t max_free_set = ( num_vars == ( 2 * ps.lut_size - 1 ) || ( offset == ps.lut_size - 1 ) ) ? ps.lut_size - 1 : ps.lut_size - 1 - ps.max_shared_vars; + + /* find ACD "66" for different number of variables in the free set */ + for ( uint32_t i = std::max( num_vars - 6, offset ); i <= max_free_set; ++i ) + { + if ( find_decomposition_bs_offset( i, offset ) ) + return true; + } + + best_multiplicity = UINT32_MAX; + return false; + } + + void init_truth_table( word* ptt ) + { + uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) ); + + for ( uint32_t i = 0; i < num_blocks; ++i ) + { + start_tt._bits[i] = ptt[i]; + } + + local_extend_to( start_tt, num_vars ); + } + + uint32_t column_multiplicity( STT const& tt, uint32_t free_set_size ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const limit = ( ps.max_shared_vars == 0 || free_set_size == ( ps.lut_size - 1 ) ) ? 2 : 4; + uint32_t const inner_loop_max = ( num_vars < 6 ? ( 1 << num_vars ) : 64 ) >> free_set_size; + uint32_t cofactors[4]; + uint32_t size = 0; + + /* extract iset functions */ + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < inner_loop_max; ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t k; + for ( k = 0; k < size; ++k ) + { + if ( fs_fn == cofactors[k] ) + break; + } + if ( k == limit ) + return 5; + if ( k == size ) + cofactors[size++] = fs_fn; + sub >>= shift; + } + } + + return size; + } + + uint32_t column_multiplicity2( STT const& tt, uint32_t free_set_size, uint32_t const limit ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const inner_loop_max = ( num_vars < 6 ? ( 1 << num_vars ) : 64 ) >> free_set_size; + uint32_t cofactors[32]; + uint32_t size = 0; + + /* extract iset functions */ + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < inner_loop_max; ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t k; + for ( k = 0; k < size; ++k ) + { + if ( fs_fn == cofactors[k] ) + break; + } + if ( k == limit ) + return 64; + if ( k == size ) + cofactors[size++] = fs_fn; + sub >>= shift; + } + } + + return size; + } + + inline bool combinations_next( uint32_t k, uint32_t offset, uint32_t* pComb, uint32_t* pInvPerm, STT& tt ) + { + uint32_t i; + + for ( i = k - 1; pComb[i] == num_vars - k + i; --i ) + { + if ( i == offset ) + return false; + } + + /* move vars */ + uint32_t var_old = pComb[i]; + uint32_t pos_new = pInvPerm[var_old + 1]; + std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] ); + std::swap( pComb[i], pComb[pos_new] ); + swap_inplace_local( tt, i, pos_new ); + + for ( uint32_t j = i + 1; j < k; j++ ) + { + var_old = pComb[j]; + pos_new = pInvPerm[pComb[j - 1] + 1]; + std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] ); + std::swap( pComb[j], pComb[pos_new] ); + swap_inplace_local( tt, j, pos_new ); + } + + return true; + } + + inline bool combinations_next_simple( uint32_t k, uint32_t* pComb, uint32_t* pInvPerm, uint32_t size ) + { + uint32_t i; + + for ( i = k - 1; pComb[i] == size - k + i; --i ) + { + if ( i == 0 ) + return false; + } + + /* move vars */ + uint32_t var_old = pComb[i]; + uint32_t pos_new = pInvPerm[var_old + 1]; + std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] ); + std::swap( pComb[i], pComb[pos_new] ); + + for ( uint32_t j = i + 1; j < k; j++ ) + { + var_old = pComb[j]; + pos_new = pInvPerm[pComb[j - 1] + 1]; + std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] ); + std::swap( pComb[j], pComb[pos_new] ); + } + + return true; + } + + bool find_decomposition_bs( uint32_t free_set_size ) + { + STT tt = start_tt; + + /* works up to 11 input truth tables */ + assert( num_vars <= 11 ); + + /* init combinations */ + uint32_t pComb[11], pInvPerm[11]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + best_free_set = free_set_size; + do + { + uint32_t cost = column_multiplicity( tt, free_set_size ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + return true; + } + else if ( ps.max_shared_vars > 0 && cost <= 4 && free_set_size < 5 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set( tt ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, res, num_vars - 1 ); + std::swap( permutations[res], permutations[num_vars - 1] ); + num_shared_vars = 1; + return true; + } + } + } while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) ); + + return false; + } + + bool find_decomposition_bs_offset( uint32_t free_set_size, uint32_t offset ) + { + STT tt = best_tt; + + /* works up to 11 input truth tables */ + assert( num_vars <= 11 ); + best_free_set = free_set_size; + + /* special case */ + if ( free_set_size == offset ) + { + uint32_t cost = column_multiplicity( tt, free_set_size ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + return true; + } + else if ( ps.max_shared_vars > 0 && cost <= 4 && free_set_size < 5 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set( tt ); + + if ( res >= 0 ) + { + best_tt = tt; + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, res, num_vars - 1 ); + std::swap( permutations[res], permutations[num_vars - 1] ); + num_shared_vars = 1; + return true; + } + } + return false; + } + + /* init combinations */ + uint32_t pComb[11], pInvPerm[11]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + do + { + uint32_t cost = column_multiplicity( tt, free_set_size ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + return true; + } + else if ( ps.max_shared_vars > 0 && cost <= 4 && free_set_size < 5 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set( tt ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, res, num_vars - 1 ); + std::swap( permutations[res], permutations[num_vars - 1] ); + num_shared_vars = 1; + return true; + } + } + } while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) ); + + return false; + } + + bool find_decomposition_bs_multi_ss( uint32_t free_set_size ) + { + STT tt = start_tt; + + /* works up to 11 input truth tables */ + assert( num_vars <= 11 ); + + /* init combinations */ + uint32_t pComb[11], pInvPerm[11], shared_set[4]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + uint32_t limit = std::min( 1 << ( ps.lut_size - free_set_size ), 1 << ( ps.max_shared_vars + 1 ) ); + + /* enumerate combinations */ + best_free_set = free_set_size; + do + { + uint32_t cost = column_multiplicity2( tt, free_set_size, limit ); + if ( cost <= 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + return true; + } + + uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2 + : cost <= 16 ? 3 + : cost <= 32 ? 4 + : 5; + if ( ss_vars_needed + free_set_size < ps.lut_size ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set_multi( tt, ss_vars_needed, shared_set ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + /* move shared variables as the most significative ones */ + for ( int32_t i = res - 1; i >= 0; --i ) + { + swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i ); + std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] ); + } + num_shared_vars = res; + return true; + } + } + } while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) ); + + return false; + } + + bool find_decomposition_bs_offset_multi_ss( uint32_t free_set_size, uint32_t offset ) + { + STT tt = best_tt; + + /* works up to 11 input truth tables */ + assert( num_vars <= 11 ); + best_free_set = free_set_size; + uint32_t shared_set[4]; + + uint32_t limit = std::min( 1 << ( ps.lut_size - free_set_size ), 1 << ( ps.max_shared_vars + 1 ) ); + + /* special case */ + if ( free_set_size == offset ) + { + uint32_t cost = column_multiplicity2( tt, free_set_size, limit ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + return true; + } + + uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2 + : cost <= 16 ? 3 + : cost <= 32 ? 4 + : 5; + + if ( ss_vars_needed + free_set_size < 6 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set_multi( tt, ss_vars_needed, shared_set ); + + if ( res >= 0 ) + { + best_tt = tt; + /* move shared variables as the most significative ones */ + for ( int32_t i = res - 1; i >= 0; --i ) + { + swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i ); + std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] ); + } + num_shared_vars = res; + return true; + } + } + return false; + } + + /* init combinations */ + uint32_t pComb[11], pInvPerm[11]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + do + { + uint32_t cost = column_multiplicity2( tt, free_set_size, limit ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + return true; + } + + uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2 + : cost <= 16 ? 3 + : cost <= 32 ? 4 + : 5; + + if ( ss_vars_needed + free_set_size < 6 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set_multi( tt, ss_vars_needed, shared_set ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + /* move shared variables as the most significative ones */ + for ( int32_t i = res - 1; i >= 0; --i ) + { + swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i ); + std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] ); + } + num_shared_vars = res; + return true; + } + } + } while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) ); + + return false; + } + + bool check_shared_var( STT const& tt, uint32_t free_set_size, uint32_t shared_var ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const inner_loop_max = ( num_vars < 6 ? ( 1 << num_vars ) : 64 ) >> free_set_size; + uint32_t cofactors[2][4]; + uint32_t size[2] = { 0, 0 }; + uint32_t shared_var_shift = shared_var - free_set_size; + + /* extract iset functions */ + uint32_t iteration_counter = 0; + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < inner_loop_max; ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t p = ( iteration_counter >> shared_var_shift ) & 1; + uint32_t k; + for ( k = 0; k < size[p]; ++k ) + { + if ( fs_fn == cofactors[p][k] ) + break; + } + if ( k == 2 ) + return false; + if ( k == size[p] ) + cofactors[p][size[p]++] = fs_fn; + sub >>= shift; + ++iteration_counter; + } + } + + return true; + } + + inline int check_shared_set( STT const& tt ) + { + /* find one shared set variable */ + for ( uint32_t i = best_free_set; i < num_vars; ++i ) + { + /* check the multiplicity of cofactors */ + if ( check_shared_var( tt, best_free_set, i ) ) + { + return i; + } + } + + return -1; + } + + bool check_shared_var_combined( STT const& tt, uint32_t free_set_size, uint32_t shared_vars[6], uint32_t num_shared_vars ) + { + assert( free_set_size <= 5 ); + assert( num_shared_vars <= 4 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const inner_loop_max = ( num_vars < 6 ? ( 1 << num_vars ) : 64 ) >> free_set_size; + uint32_t cofactors[16][2]; + uint32_t size[16] = { 0 }; + + /* extract iset functions */ + uint32_t iteration_counter = 0; + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < inner_loop_max; ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t p = 0; + for ( uint32_t k = 0; k < num_shared_vars; ++k ) + { + p |= ( ( iteration_counter >> shared_vars[k] ) & 1 ) << k; + } + + uint32_t k; + for ( k = 0; k < size[p]; ++k ) + { + if ( fs_fn == cofactors[p][k] ) + break; + } + if ( k == 2 ) + return false; + if ( k == size[p] ) + cofactors[p][size[p]++] = fs_fn; + sub >>= shift; + ++iteration_counter; + } + } + + return true; + } + + inline int check_shared_set_multi( STT const& tt, uint32_t target_num_ss, uint32_t* res_shared ) + { + /* init combinations */ + uint32_t pComb[6], pInvPerm[6]; + uint32_t max_shared_vars = std::min( ps.lut_size - best_free_set - 1, ps.max_shared_vars ); + + /* search for a feasible shared set */ + for ( uint32_t i = target_num_ss; i <= max_shared_vars; ++i ) + { + for ( uint32_t i = 0; i < 6; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + do + { + /* check for combined shared set */ + if ( check_shared_var_combined( tt, best_free_set, pComb, i ) ) + { + for ( uint32_t j = 0; j < i; ++j ) + { + res_shared[j] = pComb[j]; + } + /* sort vars */ + std::sort( res_shared, res_shared + i ); + return i; + } + } while ( combinations_next_simple( i, pComb, pInvPerm, num_vars - best_free_set ) ); + } + + return -1; + } + + void compute_decomposition_impl( bool verbose = false ) + { + /* construct isets involved in multiplicity */ + LTT composition; + LTT bs; + LTT bs_dc; + + /* construct isets */ + uint32_t offset = 0; + uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << best_free_set; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const num_groups = 1 << num_shared_vars; + uint32_t const next_group = 1 << ( num_vars - best_free_set - num_shared_vars ); + uint32_t const inner_loop_max = ( num_vars < 6 ? ( 1 << num_vars ) : 64 ) >> best_free_set; + + uint64_t fs_fun[32] = { 0 }; + uint64_t dc_mask = ( ( UINT64_C( 1 ) << next_group ) - 1 ); + + uint32_t group_index = 0; + uint32_t set_index = 0; + fs_fun[0] = best_tt._bits[0] & mask; + bool set_dc = true; + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t cof = best_tt._bits[i]; + for ( auto j = 0; j < inner_loop_max; ++j ) + { + uint64_t val = cof & mask; + /* move to next block */ + if ( set_index == next_group ) + { + if ( set_dc ) + { + /* only one cofactor can be found in the group --> encoding can be 0 or 1 */ + fs_fun[group_index + 1] = fs_fun[group_index]; + bs_dc._bits |= dc_mask; + } + /* set don't care */ + set_dc = true; + group_index += 2; + set_index = 0; + fs_fun[group_index] = val; + dc_mask <<= next_group; + } + /* gather encoding */ + if ( val != fs_fun[group_index] ) + { + bs._bits |= UINT64_C( 1 ) << ( j + offset ); + fs_fun[group_index + 1] = val; + set_dc = false; // two cofactors are present + } + cof >>= shift; + ++set_index; + } + offset = ( offset + inner_loop_max ) & 0x3F; + } + + if ( set_dc ) + { + /* only one cofactor can be found in the group --> encoding can be 0 or 1 */ + fs_fun[group_index + 1] = fs_fun[group_index]; + bs_dc._bits |= dc_mask; + } + + /* create composition function */ + for ( uint32_t i = 0; i < 2 * num_groups; ++i ) + { + composition._bits |= fs_fun[i] << ( i * shift ); + } + + /* minimize support BS */ + LTT care; + bs_support_size = 0; + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX }; + care._bits = masks[num_vars - best_free_set] & ~bs_dc._bits; + for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) + { + if ( !has_var6( bs, care, i ) ) + { + adjust_truth_table_on_dc( bs, care, i ); + continue; + } + + if ( bs_support_size < i ) + { + kitty::swap_inplace( bs, bs_support_size, i ); + } + + bs_support[bs_support_size] = i; + ++bs_support_size; + } + + /* assign functions */ + dec_funcs[0] = bs._bits; + dec_funcs[1] = composition._bits; + + /* print functions */ + if ( verbose ) + { + LTT f; + f._bits = dec_funcs[0]; + std::cout << "BS function : "; + kitty::print_hex( f ); + std::cout << "\n"; + f._bits = dec_funcs[1]; + std::cout << "Composition function: "; + kitty::print_hex( f ); + std::cout << "\n"; + } + } + + template + void local_extend_to( TT_type& tt, uint32_t real_num_vars ) + { + if ( real_num_vars < 6 ) + { + auto mask = *tt.begin(); + + for ( auto i = real_num_vars; i < num_vars; ++i ) + { + mask |= ( mask << ( 1 << i ) ); + } + + std::fill( tt.begin(), tt.end(), mask ); + } + else + { + uint32_t num_blocks = ( 1u << ( real_num_vars - 6 ) ); + auto it = tt.begin(); + while ( it != tt.end() ) + { + it = std::copy( tt.cbegin(), tt.cbegin() + num_blocks, it ); + } + } + } + + inline void reposition_late_arriving_variables( unsigned delay_profile, uint32_t late_arriving ) + { + uint32_t k = 0; + for ( uint32_t i = 0; i < late_arriving; ++i ) + { + while ( ( ( delay_profile >> k ) & 1 ) == 0 ) + ++k; + + if ( permutations[i] == k ) + { + ++k; + continue; + } + + std::swap( permutations[i], permutations[k] ); + swap_inplace_local( best_tt, i, k ); + ++k; + } + } + + void swap_inplace_local( STT& tt, uint8_t var_index1, uint8_t var_index2 ) + { + if ( var_index1 == var_index2 ) + { + return; + } + + if ( var_index1 > var_index2 ) + { + std::swap( var_index1, var_index2 ); + } + + const uint32_t num_blocks = num_vars <= 6 ? 1 : 1 << ( num_vars - 6 ); + + if ( num_vars <= 6 ) + { + const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + tt._bits[0] = ( tt._bits[0] & pmask[0] ) | ( ( tt._bits[0] & pmask[1] ) << shift ) | ( ( tt._bits[0] & pmask[2] ) >> shift ); + } + else if ( var_index2 <= 5 ) + { + const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + std::transform( std::begin( tt._bits ), std::begin( tt._bits ) + num_blocks, std::begin( tt._bits ), + [shift, &pmask]( uint64_t word ) { + return ( word & pmask[0] ) | ( ( word & pmask[1] ) << shift ) | ( ( word & pmask[2] ) >> shift ); + } ); + } + else if ( var_index1 <= 5 ) /* in this case, var_index2 > 5 */ + { + const auto step = 1 << ( var_index2 - 6 ); + const auto shift = 1 << var_index1; + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = decltype( step ){ 0 }; i < step; ++i ) + { + const auto low_to_high = ( *( it + i ) & kitty::detail::projections[var_index1] ) >> shift; + const auto high_to_low = ( *( it + i + step ) << shift ) & kitty::detail::projections[var_index1]; + *( it + i ) = ( *( it + i ) & ~kitty::detail::projections[var_index1] ) | high_to_low; + *( it + i + step ) = ( *( it + i + step ) & kitty::detail::projections[var_index1] ) | low_to_high; + } + it += 2 * step; + } + } + else + { + const auto step1 = 1 << ( var_index1 - 6 ); + const auto step2 = 1 << ( var_index2 - 6 ); + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = 0; i < step2; i += 2 * step1 ) + { + for ( auto j = 0; j < step1; ++j ) + { + std::swap( *( it + i + j + step1 ), *( it + i + j + step2 ) ); + } + } + it += 2 * step2; + } + } + } + + inline bool has_var6( const LTT& tt, const LTT& care, uint8_t var_index ) + { + if ( ( ( ( tt._bits >> ( uint64_t( 1 ) << var_index ) ) ^ tt._bits ) & kitty::detail::projections_neg[var_index] & ( care._bits >> ( uint64_t( 1 ) << var_index ) ) & care._bits ) != 0 ) + { + return true; + } + + return false; + } + + void adjust_truth_table_on_dc( LTT& tt, LTT& care, uint32_t var_index ) + { + uint64_t new_bits = tt._bits & care._bits; + tt._bits = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) | + ( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] ); + care._bits = ( care._bits | ( care._bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index]; + care._bits = care._bits | ( care._bits << ( uint64_t( 1 ) << var_index ) ); + } + + /* Decomposition format for ABC + * + * The record is an array of unsigned chars where: + * - the first unsigned char entry stores the number of unsigned chars in the record + * - the second entry stores the number of LUTs + * After this, several sub-records follow, each representing one LUT as follows: + * - an unsigned char entry listing the number of fanins + * - a list of fanins, from the LSB to the MSB of the truth table. The N inputs of the original function + * have indexes from 0 to N-1, followed by the internal signals in a topological order + * - the LUT truth table occupying 2^(M-3) bytes, where M is the fanin count of the LUT, from the LSB to the MSB. + * A 2-input LUT, which takes 4 bits, should be stretched to occupy 8 bits (one unsigned char) + * A 0- or 1-input LUT can be represented similarly but it is not expected that such LUTs will be represented + */ + void get_decomposition_abc( unsigned char* decompArray ) + { + unsigned char* pArray = decompArray; + unsigned char bytes = 2; + + /* write number of LUTs */ + pArray++; + *pArray = 2; + pArray++; + + /* write BS LUT */ + /* write fanin size */ + *pArray = bs_support_size; + pArray++; + ++bytes; + + /* write support */ + for ( uint32_t i = 0; i < bs_support_size; ++i ) + { + *pArray = (unsigned char)permutations[bs_support[i] + best_free_set]; + pArray++; + ++bytes; + } + + /* write truth table */ + uint32_t tt_num_bytes = ( bs_support_size <= 3 ) ? 1 : ( 1 << ( bs_support_size - 3 ) ); + for ( uint32_t i = 0; i < tt_num_bytes; ++i ) + { + *pArray = (unsigned char)( ( dec_funcs[0] >> ( 8 * i ) ) & 0xFF ); + pArray++; + ++bytes; + } + + /* write top LUT */ + /* write fanin size */ + uint32_t support_size = best_free_set + 1 + num_shared_vars; + *pArray = support_size; + pArray++; + ++bytes; + + /* write support */ + for ( uint32_t i = best_free_set; i < best_free_set; ++i ) + { + *pArray = (unsigned char)permutations[i]; + pArray++; + ++bytes; + } + + *pArray = (unsigned char)num_vars; + pArray++; + ++bytes; + + for ( uint32_t i = 0; i < num_shared_vars; ++i ) + { + *pArray = (unsigned char)permutations[num_vars - num_shared_vars + i]; + pArray++; + ++bytes; + } + + /* write truth table */ + tt_num_bytes = ( support_size <= 3 ) ? 1 : ( 1 << ( support_size - 3 ) ); + for ( uint32_t i = 0; i < tt_num_bytes; ++i ) + { + *pArray = (unsigned char)( ( dec_funcs[1] >> ( 8 * i ) ) & 0xFF ); + pArray++; + ++bytes; + } + + /* write numBytes */ + *decompArray = bytes; + } + + bool verify_impl() + { + /* create PIs */ + STT pis[max_num_vars]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + kitty::create_nth_var( pis[i], permutations[i] ); + } + + /* BS function patterns */ + STT bsi[6]; + for ( uint32_t i = 0; i < bs_support_size; ++i ) + { + bsi[i] = pis[best_free_set + bs_support[i]]; + } + + /* compute first function */ + STT bsf_sim; + for ( uint32_t i = 0u; i < ( 1 << num_vars ); ++i ) + { + uint32_t pattern = 0u; + for ( auto j = 0; j < bs_support_size; ++j ) + { + pattern |= get_bit( bsi[j], i ) << j; + } + if ( ( dec_funcs[0] >> pattern ) & 1 ) + { + set_bit( bsf_sim, i ); + } + } + + /* compute first function */ + STT top_sim; + for ( uint32_t i = 0u; i < ( 1 << num_vars ); ++i ) + { + uint32_t pattern = 0u; + for ( auto j = 0; j < best_free_set; ++j ) + { + pattern |= get_bit( pis[j], i ) << j; + } + pattern |= get_bit( bsf_sim, i ) << best_free_set; + + /* shared variables */ + for ( auto j = 0u; j < num_shared_vars; ++j ) + { + pattern |= get_bit( pis[num_vars - num_shared_vars + j], i ) << ( best_free_set + 1 + j ); + } + + if ( ( dec_funcs[1] >> pattern ) & 1 ) + { + set_bit( top_sim, i ); + } + } + + /* extend function */ + for ( uint32_t i = 0; i < ( 1 << ( num_vars > 6 ? num_vars - 6 : 1 ) ); ++i ) + { + if ( top_sim._bits[i] != start_tt._bits[i] ) + { + std::cout << "Found incorrect decomposition\n"; + report_tt( top_sim ); + std::cout << " instead_of\n"; + report_tt( start_tt ); + return false; + } + } + + return true; + } + + uint32_t get_bit( const STT& tt, uint64_t index ) + { + return ( tt._bits[index >> 6] >> ( index & 0x3f ) ) & 0x1; + } + + void set_bit( STT& tt, uint64_t index ) + { + tt._bits[index >> 6] |= uint64_t( 1 ) << ( index & 0x3f ); + } + + void report_tt( STT const& stt ) + { + kitty::dynamic_truth_table tt( num_vars ); + + std::copy( std::begin( stt._bits ), std::begin( stt._bits ) + ( 1 << ( num_vars > 6 ? num_vars - 6 : 0 ) ), std::begin( tt ) ); + kitty::print_hex( tt ); + std::cout << "\n"; + } + +private: + uint32_t best_multiplicity{ UINT32_MAX }; + uint32_t best_free_set{ UINT32_MAX }; + uint32_t best_multiplicity0{ UINT32_MAX }; + uint32_t best_multiplicity1{ UINT32_MAX }; + uint32_t bs_support_size{ UINT32_MAX }; + uint32_t num_shared_vars{ 0 }; + STT best_tt; + STT start_tt; + uint64_t dec_funcs[2]; + uint32_t bs_support[6]; + + uint32_t const num_vars; + acdXX_params ps; + std::array permutations; +}; + +} // namespace acd + +ABC_NAMESPACE_CXX_HEADER_END + +#endif // _ACDXX_H_ \ No newline at end of file From 64fea5c4c246ba7bc05f58c4ab26f9fab808f7ed Mon Sep 17 00:00:00 2001 From: aletempiac Date: Wed, 10 Apr 2024 18:43:52 +0200 Subject: [PATCH 139/151] Improving the performance and quality of acd66 --- src/map/if/acd/acd66.hpp | 260 ++++----------------------------------- 1 file changed, 25 insertions(+), 235 deletions(-) diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index aea9752e6..e9dec8a3e 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -732,7 +732,7 @@ private: uint32_t p = 0; for ( uint32_t k = 0; k < num_shared_vars; ++k ) { - p += ( ( iteration_counter >> shared_vars[k] ) & 1 ) << k; + p |= ( ( iteration_counter >> shared_vars[k] ) & 1 ) << k; } uint32_t k; @@ -787,97 +787,10 @@ private: void compute_decomposition_impl( bool verbose = false ) { - if ( num_shared_vars > 1 ) - return compute_decomposition_impl_multi_ss( verbose ); - - bool has_shared_set = num_shared_vars > 0; - - /* construct isets involved in multiplicity */ - LTT isets0[2]; - LTT isets1[2]; - - /* construct isets */ - uint32_t offset = 0; - uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; - uint64_t const shift = UINT64_C( 1 ) << best_free_set; - uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; - - /* limit analysis on 0 cofactor of the shared variable */ - if ( has_shared_set ) - num_blocks >>= 1; - - uint64_t fs_fun[4] = { best_tt._bits[0] & mask, 0, 0, 0 }; - - for ( auto i = 0u; i < num_blocks; ++i ) - { - uint64_t cof = best_tt._bits[i]; - for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) - { - uint64_t val = cof & mask; - if ( val == fs_fun[0] ) - { - isets0[0]._bits |= UINT64_C( 1 ) << ( j + offset ); - } - else - { - isets0[1]._bits |= UINT64_C( 1 ) << ( j + offset ); - fs_fun[1] = val; - } - cof >>= shift; - } - offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F; - } - - /* continue on the 1 cofactor if shared set */ - if ( has_shared_set ) - { - fs_fun[2] = best_tt._bits[num_blocks] & mask; - for ( auto i = num_blocks; i < ( num_blocks << 1 ); ++i ) - { - uint64_t cof = best_tt._bits[i]; - for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) - { - uint64_t val = cof & mask; - if ( val == fs_fun[2] ) - { - isets1[0]._bits |= UINT64_C( 1 ) << ( j + offset ); - } - else - { - isets1[1]._bits |= UINT64_C( 1 ) << ( j + offset ); - fs_fun[3] = val; - } - cof >>= shift; - } - offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F; - } - } - - /* find the support minimizing combination with shared set */ - compute_functions( isets0, isets1, fs_fun ); - - /* print functions */ - if ( verbose ) - { - LTT f; - f._bits = dec_funcs[0]; - std::cout << "BS function : "; - kitty::print_hex( f ); - std::cout << "\n"; - f._bits = dec_funcs[1]; - std::cout << "Composition function: "; - kitty::print_hex( f ); - std::cout << "\n"; - } - } - - void compute_decomposition_impl_multi_ss( bool verbose = false ) - { - /* due to the high multiplicity value this method does not perform support minimization */ - /* construct isets involved in multiplicity */ LTT composition; LTT bs; + LTT bs_dc; /* construct isets */ uint32_t offset = 0; @@ -888,10 +801,12 @@ private: uint32_t const next_group = 1 << ( num_vars - best_free_set - num_shared_vars ); uint64_t fs_fun[32] = { 0 }; + uint64_t dc_mask = ( ( UINT64_C( 1 ) << next_group ) - 1 ); uint32_t group_index = 0; uint32_t set_index = 0; fs_fun[0] = best_tt._bits[0] & mask; + bool set_dc = true; for ( auto i = 0u; i < num_blocks; ++i ) { uint64_t cof = best_tt._bits[i]; @@ -901,15 +816,25 @@ private: /* move to next block */ if ( set_index == next_group ) { + if ( set_dc ) + { + /* only one cofactor can be found in the group --> encoding can be 0 or 1 */ + fs_fun[group_index + 1] = fs_fun[group_index]; + bs_dc._bits |= dc_mask; + } + /* set don't care */ + set_dc = true; group_index += 2; set_index = 0; fs_fun[group_index] = val; + dc_mask <<= next_group; } /* gather encoding */ if ( val != fs_fun[group_index] ) { bs._bits |= UINT64_C( 1 ) << ( j + offset ); fs_fun[group_index + 1] = val; + set_dc = false; // two cofactors are present } cof >>= shift; ++set_index; @@ -917,6 +842,13 @@ private: offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F; } + if ( set_dc ) + { + /* only one cofactor can be found in the group --> encoding can be 0 or 1 */ + fs_fun[group_index + 1] = fs_fun[group_index]; + bs_dc._bits |= dc_mask; + } + /* create composition function */ for ( uint32_t i = 0; i < 2 * num_groups; ++i ) { @@ -927,11 +859,12 @@ private: LTT care; bs_support_size = 0; uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX }; - care._bits = masks[num_vars - best_free_set]; + care._bits = masks[num_vars - best_free_set] & ~bs_dc._bits; for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) { if ( !has_var6( bs, care, i ) ) { + adjust_truth_table_on_dc( bs, care, i ); continue; } @@ -963,150 +896,6 @@ private: } } - inline void compute_functions( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4] ) - { - /* u = 2 no support minimization */ - if ( best_multiplicity < 3 ) - { - dec_funcs[0] = isets0[0]._bits; - bs_support_size = num_vars - best_free_set; - for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) - { - bs_support[i] = i; - } - compute_composition( fs_fun ); - return; - } - - /* u = 4 two possibilities */ - if ( best_multiplicity == 4 ) - { - compute_functions4( isets0, isets1, fs_fun ); - return; - } - - /* u = 3 if both sets have multiplicity 2 there are no don't cares */ - if ( best_multiplicity0 == best_multiplicity1 ) - { - compute_functions4( isets0, isets1, fs_fun ); - return; - } - - /* u = 3 one set has multiplicity 1, use don't cares */ - compute_functions3( isets0, isets1, fs_fun ); - } - - inline void compute_functions4( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4] ) - { - uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX }; - LTT f = isets0[0] | isets1[1]; - LTT care; - care._bits = masks[num_vars - best_free_set]; - - /* count the number of support variables */ - uint32_t support_vars1 = 0; - for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) - { - support_vars1 += has_var6( f, care, i ) ? 1 : 0; - bs_support[i] = i; - } - - /* use a different set */ - f = isets0[0] | isets1[0]; - - uint32_t support_vars2 = 0; - for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) - { - support_vars2 += has_var6( f, care, i ) ? 1 : 0; - } - - bs_support_size = support_vars2; - if ( support_vars2 > support_vars1 ) - { - f = isets0[0] | isets1[1]; - std::swap( fs_fun[2], fs_fun[3] ); - bs_support_size = support_vars1; - } - - /* move variables */ - if ( bs_support_size < num_vars - best_free_set ) - { - support_vars1 = 0; - for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) - { - if ( !has_var6( f, care, i ) ) - { - continue; - } - - if ( support_vars1 < i ) - { - kitty::swap_inplace( f, support_vars1, i ); - } - - bs_support[support_vars1] = i; - ++support_vars1; - } - } - - dec_funcs[0] = f._bits; - compute_composition( fs_fun ); - } - - inline void compute_functions3( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4] ) - { - uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX }; - LTT f = isets0[0] | isets1[0]; - LTT care; - - /* init the care set */ - if ( best_multiplicity0 == 1 ) - { - care._bits = masks[num_vars - best_free_set] & ( ~isets0[0]._bits ); - fs_fun[1] = fs_fun[0]; - } - else - { - care._bits = masks[num_vars - best_free_set] & ( ~isets1[0]._bits ); - fs_fun[3] = fs_fun[2]; - } - - /* count the number of support variables */ - uint32_t support_vars = 0; - for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) - { - if ( !has_var6( f, care, i ) ) - { - adjust_truth_table_on_dc( f, care, i ); - continue; - } - - if ( support_vars < i ) - { - kitty::swap_inplace( f, support_vars, i ); - } - - bs_support[support_vars] = i; - ++support_vars; - } - - bs_support_size = support_vars; - dec_funcs[0] = f._bits; - compute_composition( fs_fun ); - } - - void compute_composition( uint64_t fs_fun[4] ) - { - dec_funcs[1] = fs_fun[0] << ( 1 << best_free_set ); - dec_funcs[1] |= fs_fun[1]; - - if ( best_multiplicity > 2 ) - { - dec_funcs[1] |= fs_fun[2] << ( ( 2 << best_free_set ) + ( 1 << best_free_set ) ); - dec_funcs[1] |= fs_fun[3] << ( 2 << best_free_set ); - } - } - template void local_extend_to( TT_type& tt, uint32_t real_num_vars ) { @@ -1227,7 +1016,8 @@ private: uint64_t new_bits = tt._bits & care._bits; tt._bits = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) | ( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] ); - care._bits = care._bits | ( care._bits >> ( uint64_t( 1 ) << var_index ) ); + care._bits = ( care._bits | ( care._bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index]; + care._bits = care._bits | ( care._bits << ( uint64_t( 1 ) << var_index ) ); } /* Decomposition format for ABC From 32bc1d4ab245a03820de8fdee82c5621fa08e14c Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 11 Apr 2024 11:31:28 +0200 Subject: [PATCH 140/151] Cleaning and generalizing code --- src/base/abci/abc.c | 4 +-- src/map/if/acd/ac_wrapper.cpp | 40 ++++++++--------------- src/map/if/acd/ac_wrapper.h | 4 +-- src/map/if/acd/acd66.hpp | 6 ++-- src/map/if/acd/acdXX.hpp | 17 ++++------ src/map/if/if.h | 2 +- src/map/if/ifDec66.c | 61 +++++++++-------------------------- 7 files changed, 42 insertions(+), 92 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index b9535f423..36c8f698b 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -19700,7 +19700,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) globalUtilOptind++; if ( strlen(pPars->pLutStruct) != 2 && strlen(pPars->pLutStruct) != 3 ) { - Abc_Print( -1, "Command line switch \"-J\" should be followed by a 2- or 3-char string (e.g. \"66\" or \"666\").\n" ); + Abc_Print( -1, "Command line switch \"-J\" should be followed by a 2-char string (e.g. \"44\" or \"66\" \").\n" ); goto usage; } break; @@ -19883,7 +19883,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( pPars->fEnableStructN ) { - pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck66; + pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheckXX; } else { diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index 6ee265318..7914bbd42 100644 --- a/src/map/if/acd/ac_wrapper.cpp +++ b/src/map/if/acd/ac_wrapper.cpp @@ -19,7 +19,7 @@ #include "ac_wrapper.h" #include "ac_decomposition.hpp" #include "acd66.hpp" -#include "acd666.hpp" +#include "acdXX.hpp" ABC_NAMESPACE_IMPL_START @@ -113,61 +113,49 @@ int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, } } -int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition ) +inline int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition ) { using namespace acd; - acd66_impl acd( nVars, true, false ); if ( acd.run( pTruth ) == 0 ) return 0; - - if ( !compute_decomposition ) + if ( decomposition == NULL ) return 1; - int val = acd.compute_decomposition(); if ( val != 0 ) { return 0; } + acd.get_decomposition( decomposition ); return 1; } -int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition ) +int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition ) { using namespace acd; - acd66_impl acd( nVars, true, false ); - acd.run( pTruth ); - - int val = acd.compute_decomposition(); - if ( val != 0 ) + if ( lutSize == 6 ) { - return -1; + return acd66_decompose( pTruth, nVars, decomposition ); } - - acd.get_decomposition( decomposition ); - return 0; -} - -int acd666_evaluate( word * pTruth, unsigned nVars, int compute_decomposition ) -{ - using namespace acd; - - acd666_impl acd( nVars, false ); + + acdXX_params ps; + ps.lut_size = lutSize; + ps.max_shared_vars = lutSize - 2; + acdXX_impl acd( nVars, ps ); if ( acd.run( pTruth ) == 0 ) return 0; - - if ( !compute_decomposition ) + if ( decomposition == NULL ) return 1; - int val = acd.compute_decomposition(); if ( val != 0 ) { return 0; } + acd.get_decomposition( decomposition ); return 1; } diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h index 6bde657c0..a4c4bff9b 100644 --- a/src/map/if/acd/ac_wrapper.h +++ b/src/map/if/acd/ac_wrapper.h @@ -35,11 +35,9 @@ ABC_NAMESPACE_HEADER_START int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); -int acdXX_evaluate( word * pTruth, unsigned lutSize, unsigned nVars, int compute_decomposition ); +int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition ); int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition ); -int acd666_evaluate( word * pTruth, unsigned nVars, int compute_decomposition ); - ABC_NAMESPACE_HEADER_END #endif \ No newline at end of file diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index e9dec8a3e..500dab361 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -215,7 +215,7 @@ private: local_extend_to( start_tt, num_vars ); } - uint32_t column_multiplicity( STT const& tt, uint32_t free_set_size ) + uint32_t column_multiplicity( STT const& tt, uint32_t const free_set_size ) { assert( free_set_size <= 5 ); @@ -250,7 +250,7 @@ private: return size; } - uint32_t column_multiplicity2( STT const& tt, uint32_t free_set_size, uint32_t const limit ) + uint32_t column_multiplicity2( STT const& tt, uint32_t const free_set_size, uint32_t const limit ) { assert( free_set_size <= 5 ); @@ -1198,8 +1198,6 @@ private: private: uint32_t best_multiplicity{ UINT32_MAX }; uint32_t best_free_set{ UINT32_MAX }; - uint32_t best_multiplicity0{ UINT32_MAX }; - uint32_t best_multiplicity1{ UINT32_MAX }; uint32_t bs_support_size{ UINT32_MAX }; uint32_t num_shared_vars{ 0 }; STT best_tt; diff --git a/src/map/if/acd/acdXX.hpp b/src/map/if/acd/acdXX.hpp index 5ee6abcd6..74d5df8d9 100644 --- a/src/map/if/acd/acdXX.hpp +++ b/src/map/if/acd/acdXX.hpp @@ -46,8 +46,13 @@ namespace acd struct acdXX_params { + /* Nymber of inputs of the LUT */ uint32_t lut_size{ 6 }; + + /* Maximum number of variables in the shared set */ uint32_t max_shared_vars{ 4 }; + + /* Run verification */ bool verify{ false }; }; @@ -228,7 +233,7 @@ private: local_extend_to( start_tt, num_vars ); } - uint32_t column_multiplicity( STT const& tt, uint32_t free_set_size ) + uint32_t column_multiplicity( STT const& tt, uint32_t const free_set_size ) { assert( free_set_size <= 5 ); @@ -264,7 +269,7 @@ private: return size; } - uint32_t column_multiplicity2( STT const& tt, uint32_t free_set_size, uint32_t const limit ) + uint32_t column_multiplicity2( STT const& tt, uint32_t const free_set_size, uint32_t const limit ) { assert( free_set_size <= 5 ); @@ -412,9 +417,6 @@ private: bool find_decomposition_bs_offset( uint32_t free_set_size, uint32_t offset ) { STT tt = best_tt; - - /* works up to 11 input truth tables */ - assert( num_vars <= 11 ); best_free_set = free_set_size; /* special case */ @@ -504,9 +506,6 @@ private: { STT tt = start_tt; - /* works up to 11 input truth tables */ - assert( num_vars <= 11 ); - /* init combinations */ uint32_t pComb[11], pInvPerm[11], shared_set[4]; for ( uint32_t i = 0; i < num_vars; ++i ) @@ -1225,8 +1224,6 @@ private: private: uint32_t best_multiplicity{ UINT32_MAX }; uint32_t best_free_set{ UINT32_MAX }; - uint32_t best_multiplicity0{ UINT32_MAX }; - uint32_t best_multiplicity1{ UINT32_MAX }; uint32_t bs_support_size{ UINT32_MAX }; uint32_t num_shared_vars{ 0 }; STT best_tt; diff --git a/src/map/if/if.h b/src/map/if/if.h index 33621ac92..47fe109ca 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -552,7 +552,7 @@ extern int If_CutPerformCheck07( If_Man_t * p, unsigned * pTruth, in extern int If_CutPerformCheck08( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck10( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck16( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); -extern int If_CutPerformCheck66( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); +extern int If_CutPerformCheckXX( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck45( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck54( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck75( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); diff --git a/src/map/if/ifDec66.c b/src/map/if/ifDec66.c index 5c2dce53b..9c486685c 100644 --- a/src/map/if/ifDec66.c +++ b/src/map/if/ifDec66.c @@ -24,7 +24,7 @@ ABC_NAMESPACE_IMPL_START -#define CLU_VAR_MAX 16 +#define CLU_VAR_MAX 11 #define CLU_MEM_MAX 1000 // 1 GB #define CLU_UNUSED 0xff @@ -252,7 +252,7 @@ unsigned * If_CluHashLookup2( If_Man_t * p, word * pTruth, int t ) } // returns if successful -int If_CluCheck66( If_Man_t * p, word * pTruth0, int nVars, int fHashing ) +int If_CluCheckXX( If_Man_t * p, word * pTruth0, int lutSize, int nVars, int fHashing ) { If_Grp_t G1 = {0}; unsigned * pHashed = NULL; @@ -267,32 +267,7 @@ int If_CluCheck66( If_Man_t * p, word * pTruth0, int nVars, int fHashing ) /* new entry */ if ( G1.nVars == 0 ) { - G1.nVars = acd66_evaluate( pTruth0, nVars, 0 ); - } - - if ( pHashed ) - *pHashed = If_CluGrp2Uns2( &G1 ); - - return G1.nVars; -} - -// returns if successful -int If_CluCheck666( If_Man_t * p, word * pTruth0, int nVars, int fHashing ) -{ - If_Grp_t G1 = {0}; - unsigned * pHashed = NULL; - - if ( p && fHashing ) - { - pHashed = If_CluHashLookup2( p, pTruth0, 0 ); - if ( pHashed && *pHashed != CLU_UNUSED ) - If_CluUns2Grp2( *pHashed, &G1 ); - } - - /* new entry */ - if ( G1.nVars == 0 ) - { - G1.nVars = acd666_evaluate( pTruth0, nVars, 0 ); + G1.nVars = acdXX_decompose( pTruth0, lutSize, nVars, NULL ); } if ( pHashed ) @@ -312,12 +287,11 @@ int If_CluCheck666( If_Man_t * p, word * pTruth0, int nVars, int fHashing ) SeeAlso [] ***********************************************************************/ -int If_CutPerformCheck66( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeaves, char * pStr ) +int If_CutPerformCheckXX( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeaves, char * pStr ) { unsigned pTruth[IF_MAX_FUNC_LUTSIZE > 5 ? 1 << (IF_MAX_FUNC_LUTSIZE - 5) : 1]; - int i, Length; + int Length; // stretch the truth table - assert( nVars >= 6 ); memcpy( pTruth, pTruth0, sizeof(word) * Abc_TtWordNum(nVars) ); Abc_TtStretch6( (word *)pTruth, nLeaves, p->pPars->nLutSize ); @@ -327,35 +301,30 @@ int If_CutPerformCheck66( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeav // quit if parameters are wrong Length = strlen(pStr); - if ( Length != 2 && Length != 3 ) + if ( Length != 2 ) { printf( "Wrong LUT struct (%s)\n", pStr ); return 0; } - for ( i = 0; i < Length; i++ ) + + int lutSize = pStr[0] - '0'; + if ( lutSize < 3 || lutSize > 6 ) { - if ( pStr[i] != '6' ) - { - printf( "The LUT size (%d) should belong to {6}.\n", pStr[i] - '0' ); - return 0; - } + printf( "The LUT size (%d) should belong to {3,4,5,6}.\n", lutSize ); + return 0; } - if ( ( Length == 2 && nLeaves > 11 ) || ( Length == 3 && nLeaves > 16 ) ) + if ( nLeaves >= 2 * lutSize ) { printf( "The cut size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr ); return 0; } - // consider easy case - if ( nLeaves <= 6 ) + // consider trivial case + if ( nLeaves <= lutSize ) return 1; - // derive the decomposition - if ( Length == 2 ) - return If_CluCheck66(p, (word*)pTruth, nVars, 1); - else - return If_CluCheck666(p, (word*)pTruth, nVars, 1); + return If_CluCheckXX(p, (word*)pTruth, lutSize, nVars, 1); } //////////////////////////////////////////////////////////////////////// From ca78f5e6e5308df420ffc5c709e6d37caf97e40b Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 11 Apr 2024 05:05:52 -0700 Subject: [PATCH 141/151] Bug fix in the resub engine. --- src/aig/gia/giaSupps.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/aig/gia/giaSupps.c b/src/aig/gia/giaSupps.c index 96721d66b..894e26b7d 100644 --- a/src/aig/gia/giaSupps.c +++ b/src/aig/gia/giaSupps.c @@ -572,6 +572,10 @@ int Supp_FindNextDiv( Supp_Man_t * p, int Pair ) iDiv1 = iDiv1 == -1 ? ABC_INFINITY : iDiv1; iDiv2 = iDiv2 == -1 ? ABC_INFINITY : iDiv2; iDiv = Abc_MinInt( iDiv1, iDiv2 ); + // return -1 if the pair cannot be distinguished by any divisor + // in this case the original resub problem has no solution + if ( iDiv == ABC_INFINITY ) + return -1; assert( iDiv >= 0 && iDiv < Vec_IntSize(p->vCands) ); return iDiv; } @@ -582,6 +586,8 @@ int Supp_ManRandomSolution( Supp_Man_t * p, int iSet, int fVerbose ) { int Pair = Supp_ComputePair( p, iSet ); int iDiv = Supp_FindNextDiv( p, Pair ); + if ( iDiv == -1 ) + return -1; iSet = Supp_ManSubsetAdd( p, iSet, iDiv, fVerbose ); if ( Supp_SetFuncNum(p, iSet) > 0 ) Vec_IntPush( p->vTempSets, iSet ); @@ -883,6 +889,10 @@ Vec_Int_t * Supp_ManCompute( Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * { Supp_ManAddPatternsFunc( p, i ); iSet = Supp_ManRandomSolution( p, 0, fVeryVerbose ); + if ( iSet == -1 ) { + Supp_ManDelete( p ); + return NULL; + } for ( r = 0; r < p->nRounds; r++ ) { if ( fVeryVerbose ) @@ -898,6 +908,10 @@ Vec_Int_t * Supp_ManCompute( Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * iBest = iSet; } iSet = Supp_ManReconstruct( p, fVeryVerbose ); + if ( iSet == -1 ) { + Supp_ManDelete( p ); + return NULL; + } } if ( fVeryVerbose ) printf( "Matrix size %d.\n", Vec_PtrSize(p->vMatrix) ); From 5b49724fcc209124b3f26e6e7807d1356b89ce21 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 11 Apr 2024 15:43:22 +0200 Subject: [PATCH 142/151] removing acd666 --- src/map/if/acd/acd666.hpp | 1257 ------------------------------------- 1 file changed, 1257 deletions(-) delete mode 100644 src/map/if/acd/acd666.hpp diff --git a/src/map/if/acd/acd666.hpp b/src/map/if/acd/acd666.hpp deleted file mode 100644 index 1086af0a3..000000000 --- a/src/map/if/acd/acd666.hpp +++ /dev/null @@ -1,1257 +0,0 @@ -/**C++File************************************************************** - - FileName [acd666.hpp] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Ashenhurst-Curtis decomposition.] - - Synopsis [Interface with the FPGA mapping package.] - - Author [Alessandro Tempia Calvino] - - Affiliation [EPFL] - - Date [Ver. 1.0. Started - Feb 8, 2024.] - -***********************************************************************/ -/*! - \file acd666.hpp - \brief Ashenhurst-Curtis decomposition for "666" cascade - - \author Alessandro Tempia Calvino -*/ - -#ifndef _ACD666_H_ -#define _ACD666_H_ -#pragma once - -#include -#include -#include -#include -#include - -#include "kitty_constants.hpp" -#include "kitty_constructors.hpp" -#include "kitty_dynamic_tt.hpp" -#include "kitty_operations.hpp" -#include "kitty_operators.hpp" -#include "kitty_static_tt.hpp" - -ABC_NAMESPACE_CXX_HEADER_START - -namespace acd -{ - -class acd666_impl -{ -private: - static constexpr uint32_t max_num_vars = 16; - using STT = kitty::static_truth_table; - using LTT = kitty::static_truth_table<6>; - -public: - explicit acd666_impl( uint32_t const num_vars, bool const verify = false ) - : num_vars( num_vars ), verify( verify ) - { - std::iota( permutations.begin(), permutations.end(), 0 ); - } - - /*! \brief Runs ACD 666 */ - bool run( word* ptt ) - { - assert( num_vars > 6 ); - - /* truth table is too large for the settings */ - if ( num_vars > max_num_vars || num_vars > 16 ) - { - return false; - } - - /* convert to static TT */ - init_truth_table( ptt ); - - /* run ACD trying different bound sets and free sets */ - return find_decomposition(); - } - - int compute_decomposition() - { - if ( best_multiplicity == UINT32_MAX ) - return -1; - - uint32_t n = num_luts == 3 ? rm_support_size : num_vars; - compute_decomposition_impl( n ); - - if ( verify && !verify_impl() ) - { - return 1; - } - - return 0; - } - - uint32_t get_num_edges() - { - if ( support_sizes[0] == UINT32_MAX ) - { - return UINT32_MAX; - } - - uint32_t num_edges = support_sizes[0] + support_sizes[1] + 1 + ( shared_vars[0] < UINT32_MAX ? 1 : 0 ); - - if ( num_luts == 2 ) - return num_edges; - - /* real value after support minimization */ - return num_edges + support_sizes[2] + 1 + ( shared_vars[1] < UINT32_MAX ? 1 : 0 ); - } - - /* contains a 1 for BS variables */ - // unsigned get_profile() - // { - // unsigned profile = 0; - - // if ( support_sizes[0] == UINT32_MAX ) - // return -1; - - // for ( uint32_t i = 0; i < bs_support_size; ++i ) - // { - // profile |= 1 << permutations[best_free_set + bs_support[i]]; - // } - - // return profile; - // } - - // void get_decomposition( unsigned char* decompArray ) - // { - // if ( support_sizes[0] == UINT32_MAX ) - // return; - - // get_decomposition_abc( decompArray ); - // } - -private: - bool find_decomposition() - { - best_multiplicity = UINT32_MAX; - best_free_set = UINT32_MAX; - - /* find ACD "66" for different number of variables in the free set */ - for ( uint32_t i = num_vars - 6; i <= 5; ++i ) - { - if ( find_decomposition_bs( start_tt, num_vars, i ) ) - { - num_luts = 2; - return true; - } - } - - /* find ACD "666" for different number of variables in the free set */ - bool dec_found = false; - uint32_t min_vars_free_set = num_vars <= 11 ? 1 : num_vars - 11; - uint32_t max_vars_free_set = num_vars <= 11 ? num_vars - 7 : 5; - for ( uint32_t i = max_vars_free_set; i >= min_vars_free_set; --i ) - // for ( uint32_t i = min_vars_free_set; i <= max_vars_free_set; ++i ) - { - dec_found = find_decomposition_bs( start_tt, num_vars, i ); - if ( dec_found ) - break; - } - - if ( !dec_found ) - { - best_multiplicity = UINT32_MAX; - return false; - } - - /* compute functions for the top and reminder LUT */ - compute_decomposition_impl_top( num_vars ); - - /* find ACD "66" for the remainder function */ - for ( uint32_t i = rm_support_size - 6; i <= 5; ++i ) - { - if ( find_decomposition_bs( remainder, rm_support_size, i ) ) - { - num_luts = 3; - fix_permutations_remainder( rm_support_size ); - return true; - } - } - - best_multiplicity = UINT32_MAX; - return false; - } - - void init_truth_table( word* ptt ) - { - uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) ); - - for ( uint32_t i = 0; i < num_blocks; ++i ) - { - start_tt._bits[i] = ptt[i]; - } - - local_extend_to( start_tt, num_vars ); - } - - uint32_t column_multiplicity( STT const& tt, uint32_t n, uint32_t free_set_size ) - { - assert( free_set_size <= 5 ); - - uint32_t const num_blocks = ( n > 6 ) ? ( 1u << ( n - 6 ) ) : 1; - uint64_t const shift = UINT64_C( 1 ) << free_set_size; - uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; - uint32_t const limit = free_set_size < 5 ? 4 : 2; - uint32_t cofactors[4]; - uint32_t size = 0; - - /* extract iset functions */ - for ( auto i = 0u; i < num_blocks; ++i ) - { - uint64_t sub = tt._bits[i]; - for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) - { - uint32_t fs_fn = static_cast( sub & mask ); - uint32_t k; - for ( k = 0; k < size; ++k ) - { - if ( fs_fn == cofactors[k] ) - break; - } - if ( k == limit ) - return 5; - if ( k == size ) - cofactors[size++] = fs_fn; - sub >>= shift; - } - } - - return size; - } - - inline bool combinations_next( uint32_t n, uint32_t k, uint32_t* pComb, uint32_t* pInvPerm, STT& tt ) - { - uint32_t i; - - for ( i = k - 1; pComb[i] == n - k + i; --i ) - { - if ( i == 0 ) - return false; - } - - /* move vars */ - uint32_t var_old = pComb[i]; - uint32_t pos_new = pInvPerm[var_old + 1]; - std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] ); - std::swap( pComb[i], pComb[pos_new] ); - swap_inplace_local( tt, n, i, pos_new ); - - for ( uint32_t j = i + 1; j < k; j++ ) - { - var_old = pComb[j]; - pos_new = pInvPerm[pComb[j - 1] + 1]; - std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] ); - std::swap( pComb[j], pComb[pos_new] ); - swap_inplace_local( tt, n, j, pos_new ); - } - - return true; - } - - bool find_decomposition_bs( STT tt, uint32_t n, uint32_t free_set_size ) - { - /* works up to 16 input truth tables */ - assert( n <= 16 ); - - /* init combinations */ - uint32_t pComb[16], pInvPerm[16]; - for ( uint32_t i = 0; i < n; ++i ) - { - pComb[i] = pInvPerm[i] = i; - } - - /* enumerate combinations */ - best_free_set = free_set_size; - do - { - uint32_t cost = column_multiplicity( tt, n, free_set_size ); - if ( cost == 2 ) - { - best_tt = tt; - best_multiplicity = cost; - for ( uint32_t i = 0; i < n; ++i ) - { - permutations[i] = pComb[i]; - } - return true; - } - else if ( cost <= 4 && free_set_size < 5 ) - { - /* look for a shared variable */ - best_multiplicity = cost; - int res = check_shared_set( tt, n ); - - if ( res > 0 ) - { - best_tt = tt; - for ( uint32_t i = 0; i < n; ++i ) - { - permutations[i] = pComb[i]; - } - /* move shared variable as the most significative one */ - swap_inplace_local( best_tt, n, res, n - 1 ); - std::swap( permutations[res], permutations[n - 1] ); - return true; - } - } - } while ( combinations_next( n, free_set_size, pComb, pInvPerm, tt ) ); - - return false; - } - - inline bool check_shared_var( STT const& tt, uint32_t n, uint32_t free_set_size, uint32_t shared_var ) - { - assert( free_set_size <= 5 ); - - uint32_t const num_blocks = ( n > 6 ) ? ( 1u << ( n - 6 ) ) : 1; - uint64_t const shift = UINT64_C( 1 ) << free_set_size; - uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; - uint32_t cofactors[2][4]; - uint32_t size[2] = { 0, 0 }; - uint32_t shared_var_shift = shared_var - free_set_size; - - /* extract iset functions */ - uint32_t iteration_counter = 0; - for ( auto i = 0u; i < num_blocks; ++i ) - { - uint64_t sub = tt._bits[i]; - for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) - { - uint32_t fs_fn = static_cast( sub & mask ); - uint32_t p = ( iteration_counter >> shared_var_shift ) & 1; - uint32_t k; - for ( k = 0; k < size[p]; ++k ) - { - if ( fs_fn == cofactors[p][k] ) - break; - } - if ( k == 2 ) - return false; - if ( k == size[p] ) - cofactors[p][size[p]++] = fs_fn; - sub >>= shift; - ++iteration_counter; - } - } - - return true; - } - - inline int check_shared_set( STT const& tt, uint32_t n ) - { - /* find one shared set variable */ - for ( uint32_t i = best_free_set; i < n; ++i ) - { - /* check the multiplicity of cofactors */ - if ( check_shared_var( tt, n, best_free_set, i ) ) - { - return i; - } - } - - return -1; - } - - void compute_decomposition_impl_top( uint32_t n, bool verbose = false ) - { - bool has_shared_set = best_multiplicity > 2; - - /* construct isets involved in multiplicity */ - STT isets0[2]; - STT isets1[2]; - - /* construct isets */ - uint32_t offset = 0; - uint32_t num_blocks = ( n > 6 ) ? ( 1u << ( n - 6 ) ) : 1; - uint64_t const shift = UINT64_C( 1 ) << best_free_set; - uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; - - /* limit analysis on 0 cofactor of the shared variable */ - if ( has_shared_set ) - num_blocks >>= 1; - - uint64_t fs_fun[4] = { best_tt._bits[0] & mask, 0, 0, 0 }; - - for ( auto i = 0u; i < num_blocks; ++i ) - { - uint64_t cof = best_tt._bits[i]; - for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) - { - uint64_t val = cof & mask; - if ( val == fs_fun[0] ) - { - isets0[0]._bits[i / shift] |= UINT64_C( 1 ) << ( j + offset ); - } - else - { - isets0[1]._bits[i / shift] |= UINT64_C( 1 ) << ( j + offset ); - fs_fun[1] = val; - } - cof >>= shift; - } - offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F; - } - - /* continue on the 1 cofactor if shared set */ - if ( has_shared_set ) - { - fs_fun[2] = best_tt._bits[num_blocks] & mask; - for ( auto i = num_blocks; i < ( num_blocks << 1 ); ++i ) - { - uint64_t cof = best_tt._bits[i]; - for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) - { - uint64_t val = cof & mask; - if ( val == fs_fun[2] ) - { - isets1[0]._bits[i / shift] |= UINT64_C( 1 ) << ( j + offset ); - } - else - { - isets1[1]._bits[i / shift] |= UINT64_C( 1 ) << ( j + offset ); - fs_fun[3] = val; - } - cof >>= shift; - } - offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F; - } - } - - /* find the support minimizing combination with shared set */ - compute_functions_top( isets0, isets1, fs_fun, n ); - - /* print functions */ - if ( verbose ) - { - std::cout << "RM function : "; - kitty::print_hex( remainder ); - std::cout << "\n"; - LTT f; - f._bits = dec_funcs[2]; - std::cout << "Composition function: "; - kitty::print_hex( f ); - std::cout << "\n"; - } - } - - void compute_decomposition_impl( uint32_t n, bool verbose = false ) - { - bool has_shared_set = best_multiplicity > 2; - - /* construct isets involved in multiplicity */ - LTT isets0[2]; - LTT isets1[2]; - - /* construct isets */ - uint32_t offset = 0; - uint32_t num_blocks = ( n > 6 ) ? ( 1u << ( n - 6 ) ) : 1; - uint64_t const shift = UINT64_C( 1 ) << best_free_set; - uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; - - /* limit analysis on 0 cofactor of the shared variable */ - if ( has_shared_set ) - num_blocks >>= 1; - - uint64_t fs_fun[4] = { best_tt._bits[0] & mask, 0, 0, 0 }; - - for ( auto i = 0u; i < num_blocks; ++i ) - { - uint64_t cof = best_tt._bits[i]; - for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) - { - uint64_t val = cof & mask; - - if ( val == fs_fun[0] ) - { - isets0[0]._bits |= UINT64_C( 1 ) << ( j + offset ); - } - else - { - isets0[1]._bits |= UINT64_C( 1 ) << ( j + offset ); - fs_fun[1] = val; - } - - cof >>= shift; - } - - offset = ( offset + ( 64 >> best_free_set ) ) % 64; - } - - /* continue on the 1 cofactor if shared set */ - if ( has_shared_set ) - { - fs_fun[2] = best_tt._bits[num_blocks] & mask; - for ( auto i = num_blocks; i < ( num_blocks << 1 ); ++i ) - { - uint64_t cof = best_tt._bits[i]; - for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) - { - uint64_t val = cof & mask; - - if ( val == fs_fun[2] ) - { - isets1[0]._bits |= UINT64_C( 1 ) << ( j + offset ); - } - else - { - isets1[1]._bits |= UINT64_C( 1 ) << ( j + offset ); - fs_fun[3] = val; - } - - cof >>= shift; - } - - offset = ( offset + ( 64 >> best_free_set ) ) % 64; - } - } - - /* find the support minimizing combination with shared set */ - compute_functions( isets0, isets1, fs_fun, n ); - - /* print functions */ - if ( verbose ) - { - LTT f; - f._bits = dec_funcs[0]; - std::cout << "BS function : "; - kitty::print_hex( f ); - std::cout << "\n"; - f._bits = dec_funcs[1]; - std::cout << "Composition function: "; - kitty::print_hex( f ); - std::cout << "\n"; - } - } - - inline void compute_functions_top( STT isets0[2], STT isets1[2], uint64_t fs_fun[4], uint32_t n ) - { - /* u = 2 no support minimization */ - if ( best_multiplicity < 3 ) - { - shared_vars[1] = UINT32_MAX; - remainder = isets0[0]; - rm_support_size = n - best_free_set; - for ( uint32_t i = 0; i < n - best_free_set; ++i ) - { - rm_support[i] = permutations[i + best_free_set]; - } - compute_composition( fs_fun, 2 ); - return; - } - - shared_vars[1] = permutations[n - 1]; - - /* u = 4 two possibilities */ - if ( best_multiplicity == 4 ) - { - compute_functions4_top( isets0, isets1, fs_fun, n ); - return; - } - - /* u = 3 if both sets have multiplicity 2 there are no don't cares */ - if ( best_multiplicity0 == best_multiplicity1 ) - { - compute_functions4_top( isets0, isets1, fs_fun, n ); - return; - } - - /* u = 3 one set has multiplicity 1, use don't cares */ - compute_functions3_top( isets0, isets1, fs_fun, n ); - } - - inline void compute_functions( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4], uint32_t n ) - { - /* u = 2 no support minimization */ - if ( best_multiplicity < 3 ) - { - shared_vars[0] = UINT32_MAX; - dec_funcs[0] = isets0[0]._bits; - support_sizes[0] = n - best_free_set; - for ( uint32_t i = 0; i < n - best_free_set; ++i ) - { - supports[0][i] = permutations[i + best_free_set]; - } - compute_composition( fs_fun, 1 ); - return; - } - - shared_vars[0] = permutations[n - 1]; - - /* u = 4 two possibilities */ - if ( best_multiplicity == 4 ) - { - compute_functions4( isets0, isets1, fs_fun, n ); - return; - } - - /* u = 3 if both sets have multiplicity 2 there are no don't cares */ - if ( best_multiplicity0 == best_multiplicity1 ) - { - compute_functions4( isets0, isets1, fs_fun, n ); - return; - } - - /* u = 3 one set has multiplicity 1, use don't cares */ - compute_functions3( isets0, isets1, fs_fun, n ); - } - - inline void compute_functions4_top( STT isets0[2], STT isets1[2], uint64_t fs_fun[4], uint32_t n ) - { - STT f; - uint32_t const num_iset_vars = n - best_free_set; - uint32_t const num_blocks = 1u << ( num_iset_vars - 6 ); - - assert( num_iset_vars > 6 ); - for ( uint32_t i = 0; i < num_blocks; ++i ) - { - f._bits[i] = isets0[0]._bits[i] | isets1[1]._bits[i]; - } - - /* count the number of support variables */ - uint32_t support_vars1 = 0; - for ( uint32_t i = 0; i < num_iset_vars; ++i ) - { - support_vars1 += has_var( f, num_iset_vars, i ) ? 1 : 0; - rm_support[i] = permutations[i + best_free_set]; - } - - /* use a different set */ - for ( uint32_t i = 0; i < num_blocks; ++i ) - { - f._bits[i] = isets0[0]._bits[i] | isets1[0]._bits[i]; - } - - uint32_t support_vars2 = 0; - for ( uint32_t i = 0; i < n - best_free_set; ++i ) - { - support_vars2 += has_var( f, num_iset_vars, i ) ? 1 : 0; - } - - rm_support_size = support_vars2; - if ( support_vars2 > support_vars1 ) - { - for ( uint32_t i = 0; i < num_blocks; ++i ) - { - f._bits[i] = isets0[0]._bits[i] | isets1[1]._bits[i]; - } - std::swap( fs_fun[2], fs_fun[3] ); - rm_support_size = support_vars1; - } - - /* move variables */ - if ( rm_support_size < num_iset_vars ) - { - support_vars1 = 0; - for ( uint32_t i = 0; i < num_iset_vars; ++i ) - { - if ( !has_var( f, num_iset_vars, i ) ) - { - continue; - } - - if ( support_vars1 < i ) - { - swap_inplace_local( f, num_iset_vars, support_vars1, i ); - } - - rm_support[support_vars1] = permutations[i + best_free_set]; - ++support_vars1; - } - } - - remainder = f; - compute_composition( fs_fun, 2 ); - } - - inline void compute_functions4( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4], uint32_t n ) - { - uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX }; - LTT f = isets0[0] | isets1[1]; - LTT care; - - assert( n - best_free_set <= 6 ); - care._bits = masks[n - best_free_set]; - - /* count the number of support variables */ - uint32_t support_vars1 = 0; - for ( uint32_t i = 0; i < n - best_free_set; ++i ) - { - support_vars1 += has_var6( f, care, i ) ? 1 : 0; - supports[0][i] = permutations[i + best_free_set]; - } - - /* use a different set */ - f = isets0[0] | isets1[0]; - - uint32_t support_vars2 = 0; - for ( uint32_t i = 0; i < n - best_free_set; ++i ) - { - support_vars2 += has_var6( f, care, i ) ? 1 : 0; - } - - support_sizes[0] = support_vars2; - if ( support_vars2 > support_vars1 ) - { - f = isets0[0] | isets1[1]; - std::swap( fs_fun[2], fs_fun[3] ); - support_sizes[0] = support_vars1; - } - - /* move variables */ - if ( support_sizes[0] < n - best_free_set ) - { - support_vars1 = 0; - for ( uint32_t i = 0; i < n - best_free_set; ++i ) - { - if ( !has_var6( f, care, i ) ) - { - continue; - } - - if ( support_vars1 < i ) - { - kitty::swap_inplace( f, support_vars1, i ); - } - - supports[0][support_vars1] = permutations[i + best_free_set]; - ++support_vars1; - } - } - - dec_funcs[0] = f._bits; - compute_composition( fs_fun, 1 ); - } - - inline void compute_functions3_top( STT isets0[2], STT isets1[2], uint64_t fs_fun[4], uint32_t n ) - { - STT f, care; - uint32_t const num_iset_vars = n - best_free_set; - uint32_t const num_blocks = 1u << ( num_iset_vars - 6 ); - - assert( num_iset_vars > 6 ); - for ( uint32_t i = 0; i < num_blocks; ++i ) - { - f._bits[i] = isets0[0]._bits[i] | isets1[0]._bits[i]; - } - - assert( n - best_free_set <= 6 ); - - /* init the care set */ - if ( best_multiplicity0 == 1 ) - { - for ( uint32_t i = 0; i < num_blocks; ++i ) - { - care._bits[i] = ~( isets0[0]._bits[i] ); - } - fs_fun[1] = fs_fun[0]; - } - else - { - for ( uint32_t i = 0; i < num_blocks; ++i ) - { - care._bits[i] = ~( isets1[0]._bits[i] ); - } - fs_fun[3] = fs_fun[2]; - } - - /* count the number of support variables */ - uint32_t support_vars = 0; - for ( uint32_t i = 0; i < num_iset_vars; ++i ) - { - if ( !has_var_support( f, care, num_iset_vars, i ) ) - { - adjust_truth_table_on_dc( f, care, n, i ); - continue; - } - - if ( support_vars < i ) - { - kitty::swap_inplace( f, support_vars, i ); - } - - rm_support[support_vars] = permutations[i + best_free_set]; - ++support_vars; - } - - rm_support_size = support_vars; - remainder = f; - compute_composition( fs_fun, 2 ); - } - - inline void compute_functions3( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4], uint32_t n ) - { - uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX }; - LTT f = isets0[0] | isets1[0]; - LTT care; - - assert( n - best_free_set <= 6 ); - - /* init the care set */ - if ( best_multiplicity0 == 1 ) - { - care._bits = masks[n - best_free_set] & ( ~isets0[0]._bits ); - fs_fun[1] = fs_fun[0]; - } - else - { - care._bits = masks[n - best_free_set] & ( ~isets1[0]._bits ); - fs_fun[3] = fs_fun[2]; - } - - /* count the number of support variables */ - uint32_t support_vars = 0; - for ( uint32_t i = 0; i < n - best_free_set; ++i ) - { - if ( !has_var6( f, care, i ) ) - { - adjust_truth_table_on_dc6( f, care, i ); - continue; - } - - if ( support_vars < i ) - { - kitty::swap_inplace( f, support_vars, i ); - } - - supports[0][support_vars] = i; - ++support_vars; - } - - support_sizes[0] = support_vars; - dec_funcs[0] = f._bits; - compute_composition( fs_fun, 1 ); - } - - void compute_composition( uint64_t fs_fun[4], uint32_t index ) - { - dec_funcs[index] = fs_fun[0] << ( 1 << best_free_set ); - dec_funcs[index] |= fs_fun[1]; - - if ( best_multiplicity > 2 ) - { - dec_funcs[index] |= fs_fun[2] << ( ( 2 << best_free_set ) + ( 1 << best_free_set ) ); - dec_funcs[index] |= fs_fun[3] << ( 2 << best_free_set ); - } - - for ( uint32_t i = 0; i < best_free_set; ++i ) - { - supports[index][i] = permutations[i]; - } - support_sizes[index] = best_free_set; - } - - void fix_permutations_remainder( uint32_t n ) - { - for ( uint32_t i = 0; i < n; ++i ) - { - permutations[i] = rm_support[permutations[i]]; - } - } - - template - void local_extend_to( TT_type& tt, uint32_t real_num_vars ) - { - if ( real_num_vars < 6 ) - { - auto mask = *tt.begin(); - - for ( auto i = real_num_vars; i < num_vars; ++i ) - { - mask |= ( mask << ( 1 << i ) ); - } - - std::fill( tt.begin(), tt.end(), mask ); - } - else - { - uint32_t num_blocks = ( 1u << ( real_num_vars - 6 ) ); - auto it = tt.begin(); - while ( it != tt.end() ) - { - it = std::copy( tt.cbegin(), tt.cbegin() + num_blocks, it ); - } - } - } - - void swap_inplace_local( STT& tt, uint32_t n, uint8_t var_index1, uint8_t var_index2 ) - { - if ( var_index1 == var_index2 ) - { - return; - } - - if ( var_index1 > var_index2 ) - { - std::swap( var_index1, var_index2 ); - } - - assert( n > 6 ); - const uint32_t num_blocks = 1 << ( n - 6 ); - - if ( var_index2 <= 5 ) - { - const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2]; - const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); - std::transform( std::begin( tt._bits ), std::begin( tt._bits ) + num_blocks, std::begin( tt._bits ), - [shift, &pmask]( uint64_t word ) { - return ( word & pmask[0] ) | ( ( word & pmask[1] ) << shift ) | ( ( word & pmask[2] ) >> shift ); - } ); - } - else if ( var_index1 <= 5 ) /* in this case, var_index2 > 5 */ - { - const auto step = 1 << ( var_index2 - 6 ); - const auto shift = 1 << var_index1; - auto it = std::begin( tt._bits ); - while ( it != std::begin( tt._bits ) + num_blocks ) - { - for ( auto i = decltype( step ){ 0 }; i < step; ++i ) - { - const auto low_to_high = ( *( it + i ) & kitty::detail::projections[var_index1] ) >> shift; - const auto high_to_low = ( *( it + i + step ) << shift ) & kitty::detail::projections[var_index1]; - *( it + i ) = ( *( it + i ) & ~kitty::detail::projections[var_index1] ) | high_to_low; - *( it + i + step ) = ( *( it + i + step ) & kitty::detail::projections[var_index1] ) | low_to_high; - } - it += 2 * step; - } - } - else - { - const auto step1 = 1 << ( var_index1 - 6 ); - const auto step2 = 1 << ( var_index2 - 6 ); - auto it = std::begin( tt._bits ); - while ( it != std::begin( tt._bits ) + num_blocks ) - { - for ( auto i = 0; i < step2; i += 2 * step1 ) - { - for ( auto j = 0; j < step1; ++j ) - { - std::swap( *( it + i + j + step1 ), *( it + i + j + step2 ) ); - } - } - it += 2 * step2; - } - } - } - - inline bool has_var6( const LTT& tt, const LTT& care, uint8_t var_index ) - { - if ( ( ( ( tt._bits >> ( uint64_t( 1 ) << var_index ) ) ^ tt._bits ) & kitty::detail::projections_neg[var_index] & ( care._bits >> ( uint64_t( 1 ) << var_index ) ) & care._bits ) != 0 ) - { - return true; - } - - return false; - } - - inline bool has_var( const STT& tt, uint32_t n, uint8_t var_index ) - { - uint32_t const num_blocks = 1u << ( n - 6 ); - - if ( var_index < 6 ) - { - return std::any_of( std::begin( tt._bits ), std::begin( tt._bits ) + num_blocks, - [var_index]( uint64_t word ) { return ( ( word >> ( uint64_t( 1 ) << var_index ) ) & kitty::detail::projections_neg[var_index] ) != - ( word & kitty::detail::projections_neg[var_index] ); } ); - } - - const auto step = 1 << ( var_index - 6 ); - for ( auto i = 0u; i < num_blocks; i += 2 * step ) - { - for ( auto j = 0; j < step; ++j ) - { - if ( tt._bits[i + j] != tt._bits[i + j + step] ) - { - return true; - } - } - } - return false; - } - - bool has_var_support( const STT& tt, const STT& care, uint32_t real_num_vars, uint8_t var_index ) - { - assert( var_index < real_num_vars ); - assert( real_num_vars <= tt.num_vars() ); - assert( tt.num_vars() == care.num_vars() ); - - const uint32_t num_blocks = real_num_vars <= 6 ? 1 : ( 1 << ( real_num_vars - 6 ) ); - if ( real_num_vars <= 6 || var_index < 6 ) - { - auto it_tt = std::begin( tt._bits ); - auto it_care = std::begin( care._bits ); - while ( it_tt != std::begin( tt._bits ) + num_blocks ) - { - if ( ( ( ( *it_tt >> ( uint64_t( 1 ) << var_index ) ) ^ *it_tt ) & kitty::detail::projections_neg[var_index] & ( *it_care >> ( uint64_t( 1 ) << var_index ) ) & *it_care ) != 0 ) - { - return true; - } - ++it_tt; - ++it_care; - } - - return false; - } - - const auto step = 1 << ( var_index - 6 ); - for ( auto i = 0u; i < num_blocks; i += 2 * step ) - { - for ( auto j = 0; j < step; ++j ) - { - if ( ( ( tt._bits[i + j] ^ tt._bits[i + j + step] ) & care._bits[i + j] & care._bits[i + j + step] ) != 0 ) - { - return true; - } - } - } - - return false; - } - - void adjust_truth_table_on_dc6( LTT& tt, LTT& care, uint32_t var_index ) - { - uint64_t new_bits = tt._bits & care._bits; - tt._bits = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) | - ( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] ); - care._bits = care._bits | ( care._bits >> ( uint64_t( 1 ) << var_index ) ); - } - - void adjust_truth_table_on_dc( STT& tt, STT& care, uint32_t n, uint32_t var_index ) - { - assert( var_index < n ); - const uint32_t num_blocks = n <= 6 ? 1 : ( 1 << ( n - 6 ) ); - - if ( n <= 6 || var_index < 6 ) - { - auto it_tt = std::begin( tt._bits ); - auto it_care = std::begin( care._bits ); - while ( it_tt != std::begin( tt._bits ) + num_blocks ) - { - uint64_t new_bits = *it_tt & *it_care; - *it_tt = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) | - ( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] ); - *it_care = *it_care | ( *it_care >> ( uint64_t( 1 ) << var_index ) ); - - ++it_tt; - ++it_care; - } - return; - } - - const auto step = 1 << ( var_index - 6 ); - for ( auto i = 0u; i < num_blocks; i += 2 * step ) - { - for ( auto j = 0; j < step; ++j ) - { - tt._bits[i + j] = ( tt._bits[i + j] & care._bits[i + j] ) | ( tt._bits[i + j + step] & care._bits[i + j + step] ); - tt._bits[i + j + step] = tt._bits[i + j]; - care._bits[i + j] = care._bits[i + j] | care._bits[i + j + step]; - care._bits[i + j + step] = care._bits[i + j]; - } - } - } - - /* Decomposition format for ABC - * - * The record is an array of unsigned chars where: - * - the first unsigned char entry stores the number of unsigned chars in the record - * - the second entry stores the number of LUTs - * After this, several sub-records follow, each representing one LUT as follows: - * - an unsigned char entry listing the number of fanins - * - a list of fanins, from the LSB to the MSB of the truth table. The N inputs of the original function - * have indexes from 0 to N-1, followed by the internal signals in a topological order - * - the LUT truth table occupying 2^(M-3) bytes, where M is the fanin count of the LUT, from the LSB to the MSB. - * A 2-input LUT, which takes 4 bits, should be stretched to occupy 8 bits (one unsigned char) - * A 0- or 1-input LUT can be represented similarly but it is not expected that such LUTs will be represented - */ - // void get_decomposition_abc( unsigned char* decompArray ) - // { - // unsigned char* pArray = decompArray; - // unsigned char bytes = 2; - - // /* write number of LUTs */ - // pArray++; - // *pArray = 2; - // pArray++; - - // /* write BS LUT */ - // /* write fanin size */ - // *pArray = bs_support_size; - // pArray++; - // ++bytes; - - // /* write support */ - // for ( uint32_t i = 0; i < bs_support_size; ++i ) - // { - // *pArray = (unsigned char)permutations[bs_support[i] + best_free_set]; - // pArray++; - // ++bytes; - // } - - // /* write truth table */ - // uint32_t tt_num_bytes = ( bs_support_size <= 3 ) ? 1 : ( 1 << ( bs_support_size - 3 ) ); - // for ( uint32_t i = 0; i < tt_num_bytes; ++i ) - // { - // *pArray = (unsigned char)( ( dec_funcs[0] >> ( 8 * i ) ) & 0xFF ); - // pArray++; - // ++bytes; - // } - - // /* write top LUT */ - // /* write fanin size */ - // uint32_t support_size = best_free_set + 1 + ( best_multiplicity > 2 ? 1 : 0 ); - // *pArray = support_size; - // pArray++; - // ++bytes; - - // /* write support */ - // for ( uint32_t i = 0; i < best_free_set; ++i ) - // { - // *pArray = (unsigned char)permutations[i]; - // pArray++; - // ++bytes; - // } - - // *pArray = (unsigned char)num_vars; - // pArray++; - // ++bytes; - - // if ( best_multiplicity > 2 ) - // { - // *pArray = (unsigned char)permutations[num_vars - 1]; - // pArray++; - // ++bytes; - // } - - // /* write truth table */ - // tt_num_bytes = ( support_size <= 3 ) ? 1 : ( 1 << ( support_size - 3 ) ); - // for ( uint32_t i = 0; i < tt_num_bytes; ++i ) - // { - // *pArray = (unsigned char)( ( dec_funcs[1] >> ( 8 * i ) ) & 0xFF ); - // pArray++; - // ++bytes; - // } - - // /* write numBytes */ - // *decompArray = bytes; - // } - - bool verify_impl() - { - /* create PIs */ - STT pis[max_num_vars]; - for ( uint32_t i = 0; i < num_vars; ++i ) - { - kitty::create_nth_var( pis[i], i ); - } - - STT bsi[6]; - STT bsf_sim; - for ( uint32_t lut_i = 0; lut_i < num_luts; ++lut_i ) - { - for ( uint32_t i = 0; i < support_sizes[lut_i]; ++i ) - { - bsi[i] = pis[supports[lut_i][i]]; - } - - STT top_sim; - for ( uint32_t i = 0u; i < ( 1 << num_vars ); ++i ) - { - uint32_t pattern = 0u; - for ( auto j = 0; j < support_sizes[lut_i]; ++j ) - { - pattern |= get_bit( bsi[j], i ) << j; - } - if ( lut_i != 0 ) - { - pattern |= get_bit( bsf_sim, i ) << support_sizes[lut_i]; - if ( shared_vars[lut_i - 1] < UINT32_MAX ) - { - pattern |= get_bit( pis[shared_vars[lut_i - 1]], i ) << ( support_sizes[lut_i] + 1 ); - } - } - if ( ( dec_funcs[lut_i] >> pattern ) & 1 ) - { - set_bit( top_sim, i ); - } - } - - bsf_sim = top_sim; - } - - /* extend function */ - local_extend_to( bsf_sim, num_vars ); - - for ( uint32_t i = 0; i < ( 1 << ( num_vars - 6 ) ); ++i ) - { - if ( bsf_sim._bits[i] != start_tt._bits[i] ) - { - std::cout << "Found incorrect decomposition\n"; - report_tt( bsf_sim ); - std::cout << " instead_of\n"; - report_tt( start_tt ); - return false; - } - } - - return true; - } - - uint32_t get_bit( const STT& tt, uint64_t index ) - { - return ( tt._bits[index >> 6] >> ( index & 0x3f ) ) & 0x1; - } - - void set_bit( STT& tt, uint64_t index ) - { - tt._bits[index >> 6] |= uint64_t( 1 ) << ( index & 0x3f ); - } - - void report_tt( STT const& stt ) - { - kitty::dynamic_truth_table tt( num_vars ); - - std::copy( std::begin( stt._bits ), std::begin( stt._bits ) + ( 1 << ( num_vars - 6 ) ), std::begin( tt ) ); - kitty::print_hex( tt ); - std::cout << "\n"; - } - -private: - uint32_t best_multiplicity{ UINT32_MAX }; - uint32_t best_free_set{ UINT32_MAX }; - uint32_t best_multiplicity0{ UINT32_MAX }; - uint32_t best_multiplicity1{ UINT32_MAX }; - uint32_t rm_support_size{ UINT32_MAX }; - uint32_t num_luts{ 0 }; - - STT start_tt; - STT best_tt; - STT remainder; - - uint64_t dec_funcs[3]; - uint32_t supports[3][6]; - uint32_t support_sizes[3] = { UINT32_MAX, UINT32_MAX, UINT32_MAX }; - uint32_t rm_support[15]; - uint32_t shared_vars[2]; - - uint32_t const num_vars; - bool const verify; - std::array permutations; -}; - -} // namespace acd - -ABC_NAMESPACE_CXX_HEADER_END - -#endif // _ACD666_H_ \ No newline at end of file From e8924e5534878acddb0f6005d20fbf45c85a0077 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 11 Apr 2024 15:44:52 +0200 Subject: [PATCH 143/151] Fixes and improvements --- src/map/if/acd/ac_wrapper.cpp | 145 ++++++++++++++++++---------------- src/map/if/acd/ac_wrapper.h | 3 +- src/map/if/acd/acd66.hpp | 17 +++- src/map/if/acd/acdXX.hpp | 19 ++++- 4 files changed, 106 insertions(+), 78 deletions(-) diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp index 7914bbd42..ad923edd2 100644 --- a/src/map/if/acd/ac_wrapper.cpp +++ b/src/map/if/acd/ac_wrapper.cpp @@ -23,94 +23,99 @@ ABC_NAMESPACE_IMPL_START -static constexpr bool use_generic_acd = true; - int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ) { using namespace acd; - if ( use_generic_acd ) + ac_decomposition_params ps; + ps.lut_size = lutSize; + ps.use_first = false; + ps.try_no_late_arrival = static_cast( try_no_late_arrival ); + ac_decomposition_stats st; + + ac_decomposition_impl acd( nVars, ps, &st ); + int val = acd.run( pTruth, *pdelay ); + + if ( val < 0 ) { - ac_decomposition_params ps; - ps.lut_size = lutSize; - ps.use_first = false; - ps.try_no_late_arrival = static_cast( try_no_late_arrival ); - ac_decomposition_stats st; - - ac_decomposition_impl acd( nVars, ps, &st ); - int val = acd.run( pTruth, *pdelay ); - - if ( val < 0 ) - { - *pdelay = 0; - return -1; - } - - *pdelay = acd.get_profile(); - *cost = st.num_luts; - - return val; + *pdelay = 0; + return -1; } - else - { - acd66_impl acd( nVars ); - int val = acd.run( pTruth, *pdelay ); - if ( val == 0 ) - { - *pdelay = 0; - return -1; - } + *pdelay = acd.get_profile(); + *cost = st.num_luts; - *pdelay = acd.get_profile(); - *cost = 2; - - return val; - } + return val; } int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ) { using namespace acd; - if ( use_generic_acd ) + ac_decomposition_params ps; + ps.lut_size = lutSize; + ps.use_first = true; + ac_decomposition_stats st; + + ac_decomposition_impl acd( nVars, ps, &st ); + acd.run( pTruth, *pdelay ); + int val = acd.compute_decomposition(); + + if ( val < 0 ) { - ac_decomposition_params ps; - ps.lut_size = lutSize; - ps.use_first = true; - ac_decomposition_stats st; - - ac_decomposition_impl acd( nVars, ps, &st ); - acd.run( pTruth, *pdelay ); - int val = acd.compute_decomposition(); - - if ( val < 0 ) - { - *pdelay = 0; - return -1; - } - - *pdelay = acd.get_profile(); - acd.get_decomposition( decomposition ); - return 0; + *pdelay = 0; + return -1; } - else + + *pdelay = acd.get_profile(); + acd.get_decomposition( decomposition ); + return 0; +} + +int acd2_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ) +{ + using namespace acd; + + acdXX_params ps; + ps.lut_size = lutSize; + ps.max_shared_vars = lutSize - 2; + acdXX_impl acd( nVars, ps ); + int val = acd.run( pTruth, *pdelay ); + + if ( val == 0 ) { - acd66_impl acd( nVars ); - acd.run( pTruth, *pdelay ); - int val = acd.compute_decomposition(); - - if ( val != 0 ) - { - *pdelay = 0; - return -1; - } - - *pdelay = acd.get_profile(); - - acd.get_decomposition( decomposition ); - return 0; + *pdelay = 0; + return -1; } + + acd.compute_decomposition(); + *pdelay = acd.get_profile(); + *cost = 2; + + return val; +} + +int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ) +{ + using namespace acd; + + acdXX_params ps; + ps.lut_size = lutSize; + ps.max_shared_vars = lutSize - 2; + acdXX_impl acd( nVars, ps ); + acd.run( pTruth, *pdelay ); + int val = acd.compute_decomposition(); + + if ( val != 0 ) + { + *pdelay = 0; + return -1; + } + + *pdelay = acd.get_profile(); + + acd.get_decomposition( decomposition ); + return 0; } inline int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition ) diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h index a4c4bff9b..edb45ca7f 100644 --- a/src/map/if/acd/ac_wrapper.h +++ b/src/map/if/acd/ac_wrapper.h @@ -34,8 +34,9 @@ ABC_NAMESPACE_HEADER_START int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); +int acd2_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); +int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); -int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition ); int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition ); ABC_NAMESPACE_HEADER_END diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index 500dab361..ea7bfe951 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -138,9 +138,20 @@ public: if ( best_multiplicity == UINT32_MAX ) return -1; - for ( uint32_t i = 0; i < best_free_set; ++i ) + if ( bs_support_size == UINT32_MAX ) { - profile |= 1 << permutations[i]; + for ( uint32_t i = 0; i < best_free_set; ++i ) + { + profile |= 1 << permutations[i]; + } + } + else + { + for ( uint32_t i = 0; i < bs_support_size; ++i ) + { + profile |= 1 << permutations[bs_support[i] + best_free_set]; + } + profile = ~profile & ( ( 1u << num_vars ) - 1 ); } return profile; @@ -1074,7 +1085,7 @@ private: ++bytes; /* write support */ - for ( uint32_t i = best_free_set; i < best_free_set; ++i ) + for ( uint32_t i = 0; i < best_free_set; ++i ) { *pArray = (unsigned char)permutations[i]; pArray++; diff --git a/src/map/if/acd/acdXX.hpp b/src/map/if/acd/acdXX.hpp index 74d5df8d9..8dabc725e 100644 --- a/src/map/if/acd/acdXX.hpp +++ b/src/map/if/acd/acdXX.hpp @@ -155,10 +155,21 @@ public: if ( best_multiplicity == UINT32_MAX ) return -1; - - for ( uint32_t i = 0; i < best_free_set; ++i ) + + if ( bs_support_size == UINT32_MAX ) { - profile |= 1 << permutations[i]; + for ( uint32_t i = 0; i < best_free_set; ++i ) + { + profile |= 1 << permutations[i]; + } + } + else + { + for ( uint32_t i = 0; i < bs_support_size; ++i ) + { + profile |= 1 << permutations[bs_support[i] + best_free_set]; + } + profile = ~profile & ( ( 1u << num_vars ) - 1 ); } return profile; @@ -1101,7 +1112,7 @@ private: ++bytes; /* write support */ - for ( uint32_t i = best_free_set; i < best_free_set; ++i ) + for ( uint32_t i = 0; i < best_free_set; ++i ) { *pArray = (unsigned char)permutations[i]; pArray++; From 6052d10fdec4884d5bfdb134a874264185ce0d94 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 11 Apr 2024 15:45:37 +0200 Subject: [PATCH 144/151] Adding new command if -U for 2-LUT decompositions under delay profile --- src/base/abci/abc.c | 21 ++++++++-- src/base/abci/abcIf.c | 27 ++++++++----- src/map/if/if.h | 6 ++- src/map/if/ifCore.c | 1 + src/map/if/ifCut.c | 2 +- src/map/if/ifDelay.c | 89 +++++++++++++++++++++++++++++++++++++++++++ src/map/if/ifMap.c | 11 ++++-- src/map/if/ifTime.c | 2 +- 8 files changed, 140 insertions(+), 19 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 36c8f698b..778e7f319 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -19514,7 +19514,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) If_ManSetDefaultPars( pPars ); pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYZDEWSJqaflepmrsdbgxyuojiktncvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYUZDEWSJqaflepmrsdbgxyuojiktncvh" ) ) != EOF ) { switch ( c ) { @@ -19630,6 +19630,18 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nAndDelay < 0 ) goto usage; break; + case 'U': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-U\" should be followed by a positive integer 3, 4, 5, or 6.\n" ); + goto usage; + } + pPars->nLutDecSize = atoi(argv[globalUtilOptind]); + pPars->fUserLut2D = 1; + globalUtilOptind++; + if ( pPars->nLutDecSize < 3 || pPars->nLutDecSize > 6 ) + goto usage; + break; case 'Z': if ( globalUtilOptind >= argc ) { @@ -19892,7 +19904,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fCutMin = 1; } - if ( pPars->fUserLutDec ) + if ( pPars->fUserLutDec || pPars->fUserLut2D ) { if ( pPars->nLutDecSize == 0 ) { @@ -19927,7 +19939,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pLutLib = NULL; } // modify for delay optimization - if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fUserLutDec ) + if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fUserLutDec || pPars->fUserLut2D ) { pPars->fTruth = 1; pPars->fCutMin = 1; @@ -20073,7 +20085,7 @@ usage: sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: if [-KCFAGRNTXYZ num] [-DEW float] [-S str] [-qarlepmsdbgxyuojiktncvh]\n" ); + Abc_Print( -2, "usage: if [-KCFAGRNTXYUZ num] [-DEW float] [-SJ str] [-qarlepmsdbgxyuojiktncvh]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -20085,6 +20097,7 @@ usage: Abc_Print( -2, "\t-T num : the type of LUT structures [default = any]\n" ); Abc_Print( -2, "\t-X num : delay of AND-gate in LUT library units [default = %d]\n", pPars->nAndDelay ); Abc_Print( -2, "\t-Y num : area of AND-gate in LUT library units [default = %d]\n", pPars->nAndArea ); + Abc_Print( -2, "\t-U num : the number of LUT inputs for delay-driven LUT decomposition [default = not used]\n" ); Abc_Print( -2, "\t-Z num : the number of LUT inputs for delay-driven LUT decomposition [default = not used]\n" ); Abc_Print( -2, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index 357d7d83f..8c4ac1448 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -116,7 +116,7 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk); // update timing info to reflect logic level - if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fUserLutDec) && pNtk->pManTime ) + if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fUserLutDec || pPars->fUserLut2D ) && pNtk->pManTime ) { int c; if ( pNtk->AndGateDelay == 0.0 ) @@ -433,8 +433,8 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC SideEffects [] SeeAlso [] ***********************************************************************/ - void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, If_Obj_t * pIfObj, Vec_Int_t * vCover, Abc_Obj_t * pNodeTop ) - { +void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, If_Obj_t * pIfObj, Vec_Int_t * vCover, Abc_Obj_t * pNodeTop ) +{ extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); assert( !pIfMan->pPars->fUseTtPerm ); @@ -460,7 +460,15 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC // perform LUT-decomposition and return the LUT-structure unsigned char decompArray[92]; - int val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); + int val; + if ( pIfMan->pPars->fUserLutDec ) + { + val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); + } + else + { + val = acd2_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); + } assert( val == 0 ); // convert the LUT-structure into a set of logic nodes in Abc_Ntk_t @@ -473,7 +481,7 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC word *tt; Abc_Obj_t *pNewNodes[5]; - /* create intermediate LUTs*/ + /* create intermediate LUTs */ assert( decompArray[1] <= 6 ); Abc_Obj_t * pFanin; for ( i = 0; i < decompArray[1]; ++i ) @@ -537,7 +545,7 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC /* check correct read */ assert( byte_p == decompArray[0] ); - } +} /**Function************************************************************* @@ -577,14 +585,15 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t pNodeNew = Abc_NtkCreateNode( pNtkNew ); // if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays ) if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm && - !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserLutDec && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize ) + !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserLutDec && !pIfMan->pPars->fUserLut2D && !pIfMan->pPars->fUserRecLib && + !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize ) If_CutRotatePins( pIfMan, pCutBest ); if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) { If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i ) Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); } - else if ( pIfMan->pPars->fUserLutDec ) + else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D ) { If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover); @@ -642,7 +651,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj ); } - else if ( pIfMan->pPars->fUserLutDec ) + else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D ) { extern void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vMemory, Abc_Obj_t * pNodeTop ); Abc_DecRecordToHop( pNtkNew, pIfMan, pCutBest, pIfObj, vCover, pNodeNew ); diff --git a/src/map/if/if.h b/src/map/if/if.h index 47fe109ca..723fda780 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -147,7 +147,8 @@ struct If_Par_t_ int fDeriveLuts; // enables deriving LUT structures int fDoAverage; // optimize average rather than maximum level int fHashMapping; // perform AIG hashing after mapping - int fUserLutDec; // perform AIG hashing after mapping + int fUserLutDec; // perform Boolean decomposition during mapping + int fUserLut2D; // perform Boolean decomposition during mapping int fVerbose; // the verbosity flag int fVerboseTrace; // the verbosity flag char * pLutStruct; // LUT structure @@ -573,6 +574,7 @@ extern int If_CutSopBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, extern int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ); extern int If_CutLutBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); extern int If_LutDecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ); +extern int If_Lut2DecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ); extern int If_LutDecReEval( If_Man_t * p, If_Cut_t * pCut ); extern float If_LutDecPinRequired( If_Man_t * p, If_Cut_t * pCut, int i, float required ); /*=== ifDsd.c =============================================================*/ @@ -704,6 +706,8 @@ extern void If_ObjPrint( If_Obj_t * pObj ); extern int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); extern int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); +extern int acd2_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); +extern int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); ABC_NAMESPACE_HEADER_END diff --git a/src/map/if/ifCore.c b/src/map/if/ifCore.c index f7fcbca66..eed6a55e8 100644 --- a/src/map/if/ifCore.c +++ b/src/map/if/ifCore.c @@ -63,6 +63,7 @@ void If_ManSetDefaultPars( If_Par_t * pPars ) pPars->fCutMin = 0; pPars->fBidec = 0; pPars->fUserLutDec = 0; + pPars->fUserLut2D = 0; pPars->fVerbose = 0; } diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c index 49850d313..c9354b339 100644 --- a/src/map/if/ifCut.c +++ b/src/map/if/ifCut.c @@ -761,7 +761,7 @@ void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut ) if ( !pCut->fUseless && (p->pPars->fUseDsd || p->pPars->pFuncCell2 || p->pPars->fUseBat || - p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || + p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fUserLut2D || p->pPars->fEnableCheck07 || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->fUseDsdTune || p->pPars->fEnableCheck75 || p->pPars->fEnableCheck75u || p->pPars->fUseCheck1 || p->pPars->fUseCheck2) ) { diff --git a/src/map/if/ifDelay.c b/src/map/if/ifDelay.c index 3514327c1..0f94de49a 100644 --- a/src/map/if/ifDelay.c +++ b/src/map/if/ifDelay.c @@ -505,6 +505,95 @@ int If_LutDecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, return DelayMax + val; } +int If_Lut2DecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ) +{ + pCut->fUser = 1; + pCut->Cost = pCut->nLeaves > 1 ? 1 : 0; + pCut->decDelay = 0; + if ( pCut->nLeaves == 0 ) // const + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 ); + return 0; + } + if ( pCut->nLeaves == 1 ) // variable + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 ); + return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; + } + + int LutSize = p->pPars->nLutDecSize; + int i, leaf_delay; + int DelayMax = -1, nLeafMax = 0; + unsigned uLeafMask = 0; + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + { + leaf_delay = If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; + + if ( DelayMax < leaf_delay ) + { + DelayMax = leaf_delay; + nLeafMax = 1; + uLeafMask = (1 << i); + } + else if ( DelayMax == leaf_delay ) + { + nLeafMax++; + uLeafMask |= (1 << i); + } + } + if ( If_CutLeaveNum(pCut) <= LutSize ) + { + pCut->decDelay = ( 1 << LutSize ) - 1; + return DelayMax + 1; + } + + /* compute the decomposition */ + int use_late_arrival = 0; + unsigned cost = 1; + + if ( !fFirst ) + { + if ( optDelay ) + { + /* checks based on delay: must be better than the previous best cut */ + use_late_arrival = DelayMax + 2 >= If_ObjCutBest(pObj)->Delay; + } + else + { + /* checks based on delay: look at the required time */ + use_late_arrival = DelayMax + 2 > pObj->Required + p->fEpsilon; + } + } + + /* Too many late-arriving signals */ + if ( nLeafMax == LutSize && use_late_arrival ) + { + /* unfeasible decomposition */ + pCut->Cost = IF_COST_MAX; + return ABC_INFINITY; + } + + if ( !use_late_arrival ) + { + uLeafMask = 0; + } + + /* returns the delay of the decomposition */ + word *pTruth = If_CutTruthW( p, pCut ); + int val = acd2_evaluate( pTruth, pCut->nLeaves, LutSize, &uLeafMask, &cost, !use_late_arrival ); + + /* not feasible decomposition */ + pCut->decDelay = uLeafMask; + if ( val < 0 ) + { + pCut->Cost = IF_COST_MAX; + return ABC_INFINITY; + } + + pCut->Cost = 2; + return DelayMax + val; +} + int If_LutDecReEval( If_Man_t * p, If_Cut_t * pCut ) { // pCut->fUser = 1; diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index bdd3ae439..0ad63f050 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -166,7 +166,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep If_Cut_t * pCut0R, * pCut1R; int fFunc0R, fFunc1R; int i, k, v, iCutDsd, fChange; - int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || + int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fUserLut2D || p->pPars->fUseDsdTune || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->pLutStruct || p->pPars->pFuncCell2 || p->pPars->fUseCheck1 || p->pPars->fUseCheck2; int fUseAndCut = (p->pPars->nAndDelay > 0) || (p->pPars->nAndArea > 0); assert( !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 0 ); @@ -208,7 +208,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->fUseless = 1; } } - else if ( p->pPars->fUserLutDec ) + else if ( p->pPars->fUserLutDec || p->pPars->fUserLut2D ) { pCut->Delay = If_LutDecReEval( p, pCut ); } @@ -434,6 +434,11 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->Delay = If_LutDecEval( p, pCut, pObj, Mode == 0, fFirst ); pCut->fUseless = pCut->Delay == ABC_INFINITY; } + else if ( p->pPars->fUserLut2D ) + { + pCut->Delay = If_Lut2DecEval( p, pCut, pObj, Mode == 0, fFirst ); + pCut->fUseless = pCut->Delay == ABC_INFINITY; + } else if ( p->pPars->fUserSesLib ) { int Cost = 0; @@ -518,7 +523,7 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP If_Set_t * pCutSet; If_Obj_t * pTemp; If_Cut_t * pCutTemp, * pCut; - int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec || p->pPars->fUserLutDec; + int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec || p->pPars->fUserLutDec || p->pPars->fUserLut2D; assert( pObj->pEquiv != NULL ); // prepare diff --git a/src/map/if/ifTime.c b/src/map/if/ifTime.c index f20842384..a1b51d6ad 100644 --- a/src/map/if/ifTime.c +++ b/src/map/if/ifTime.c @@ -211,7 +211,7 @@ void If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, fl pLeaf->Required = IF_MIN( pLeaf->Required, Required - pLutDelays[0] ); } } - else if ( p->pPars->fUserLutDec ) + else if ( p->pPars->fUserLutDec || p->pPars->fUserLut2D ) { Required = ObjRequired; If_CutForEachLeaf( p, pCut, pLeaf, i ) From 0c905f873b57fa3e6e6744cd49301f51bfd57f48 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Thu, 11 Apr 2024 19:01:05 +0200 Subject: [PATCH 145/151] Fixes --- src/map/if/acd/acd66.hpp | 4 ++++ src/map/if/acd/acdXX.hpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp index ea7bfe951..109512986 100644 --- a/src/map/if/acd/acd66.hpp +++ b/src/map/if/acd/acd66.hpp @@ -555,6 +555,7 @@ private: } } while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) ); + best_multiplicity = UINT32_MAX; return false; } @@ -602,6 +603,8 @@ private: return true; } } + + best_multiplicity = UINT32_MAX; return false; } @@ -665,6 +668,7 @@ private: } } while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) ); + best_multiplicity = UINT32_MAX; return false; } diff --git a/src/map/if/acd/acdXX.hpp b/src/map/if/acd/acdXX.hpp index 8dabc725e..e43404ea9 100644 --- a/src/map/if/acd/acdXX.hpp +++ b/src/map/if/acd/acdXX.hpp @@ -571,6 +571,7 @@ private: } } while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) ); + best_multiplicity = UINT32_MAX; return false; } @@ -620,6 +621,8 @@ private: return true; } } + + best_multiplicity = UINT32_MAX; return false; } @@ -683,6 +686,7 @@ private: } } while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) ); + best_multiplicity = UINT32_MAX; return false; } From 1d90cafd5402f92e88f2a6e15e8c09eb42ea8517 Mon Sep 17 00:00:00 2001 From: Peter Gadfort Date: Fri, 12 Apr 2024 13:27:58 -0400 Subject: [PATCH 146/151] add library merging flag to read_lib Signed-off-by: Peter Gadfort --- src/map/scl/scl.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/map/scl/scl.c b/src/map/scl/scl.c index 29798f8fa..7fab98134 100644 --- a/src/map/scl/scl.c +++ b/src/map/scl/scl.c @@ -183,13 +183,14 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) int fUnit = 0; int fVerbose = 1; int fVeryVerbose = 0; + int fMerge = 0; SC_DontUse dont_use = {0}; dont_use.dont_use_list = ABC_ALLOC(char *, argc); dont_use.size = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "SGMXdnuvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "SGMXdnuvwmh" ) ) != EOF ) { switch ( c ) { @@ -251,6 +252,9 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'w': fVeryVerbose ^= 1; break; + case 'm': + fMerge ^= 1; + break; case 'h': goto usage; default: @@ -271,7 +275,15 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_SclLibFree(pLib2); } else if ( argc == globalUtilOptind + 1 ) { // expecting one file - pLib = Scl_ReadLibraryFile( pAbc, argv[globalUtilOptind], fVerbose, fVeryVerbose, dont_use ); + SC_Lib * pLib1 = Scl_ReadLibraryFile( pAbc, argv[globalUtilOptind], fVerbose, fVeryVerbose, dont_use ); + + SC_Lib * pLib_ext = (SC_Lib *)pAbc->pLibScl; + if ( fMerge && pLib_ext != NULL && pLib1 != NULL ) { + pLib = Abc_SclMergeLibraries( pLib_ext, pLib1 ); + if (pLib1) Abc_SclLibFree(pLib1); + } else { + pLib = pLib1; + } ABC_FREE(dont_use.dont_use_list); } else { @@ -319,6 +331,7 @@ usage: fprintf( pAbc->Err, "\t-u : toggle setting unit area for all cells [default = %s]\n", fUnit? "yes": "no" ); fprintf( pAbc->Err, "\t-v : toggle writing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-w : toggle writing information about skipped gates [default = %s]\n", fVeryVerbose? "yes": "no" ); + fprintf( pAbc->Err, "\t-m : toggle merging library with exisiting library [default = %s]\n", fMerge? "yes": "no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\t : the name of a file to read\n" ); fprintf( pAbc->Err, "\t : the name of a file to read (optional)\n" ); From 935c6a875d3c916c0726feb64c493ec99e2b77be Mon Sep 17 00:00:00 2001 From: Peter Gadfort Date: Fri, 12 Apr 2024 13:49:44 -0400 Subject: [PATCH 147/151] add missing flag to read_lib help --- src/map/scl/scl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/map/scl/scl.c b/src/map/scl/scl.c index 7fab98134..abb64b1af 100644 --- a/src/map/scl/scl.c +++ b/src/map/scl/scl.c @@ -320,7 +320,7 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dnuvwh] [-X cell_name] \n" ); + fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dnuvwmh] [-X cell_name] \n" ); fprintf( pAbc->Err, "\t reads Liberty library from file\n" ); fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew ); fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain ); From 99e0e37da6eeef211b728e9035a89141c1be046b Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 14 Apr 2024 09:51:00 -0700 Subject: [PATCH 148/151] Added switch -p in "read_lib" to skip writing cell prefix. --- src/map/scl/scl.c | 13 +++++++++---- src/map/scl/sclLib.h | 2 +- src/map/scl/sclLibScl.c | 4 ++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/map/scl/scl.c b/src/map/scl/scl.c index abb64b1af..6ddd60944 100644 --- a/src/map/scl/scl.c +++ b/src/map/scl/scl.c @@ -184,13 +184,14 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) int fVerbose = 1; int fVeryVerbose = 0; int fMerge = 0; + int fUsePrefix = 0; SC_DontUse dont_use = {0}; dont_use.dont_use_list = ABC_ALLOC(char *, argc); dont_use.size = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "SGMXdnuvwmh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "SGMXdnuvwmph" ) ) != EOF ) { switch ( c ) { @@ -255,6 +256,9 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': fMerge ^= 1; break; + case 'p': + fUsePrefix ^= 1; + break; case 'h': goto usage; default: @@ -270,7 +274,7 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) if (pLib2) Abc_SclLibFree(pLib2); return 1; } - pLib = Abc_SclMergeLibraries( pLib1, pLib2 ); + pLib = Abc_SclMergeLibraries( pLib1, pLib2, fUsePrefix ); Abc_SclLibFree(pLib1); Abc_SclLibFree(pLib2); } @@ -279,7 +283,7 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) SC_Lib * pLib_ext = (SC_Lib *)pAbc->pLibScl; if ( fMerge && pLib_ext != NULL && pLib1 != NULL ) { - pLib = Abc_SclMergeLibraries( pLib_ext, pLib1 ); + pLib = Abc_SclMergeLibraries( pLib_ext, pLib1, fUsePrefix ); if (pLib1) Abc_SclLibFree(pLib1); } else { pLib = pLib1; @@ -320,7 +324,7 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dnuvwmh] [-X cell_name] \n" ); + fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dnuvwmph] [-X cell_name] \n" ); fprintf( pAbc->Err, "\t reads Liberty library from file\n" ); fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew ); fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain ); @@ -332,6 +336,7 @@ usage: fprintf( pAbc->Err, "\t-v : toggle writing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-w : toggle writing information about skipped gates [default = %s]\n", fVeryVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-m : toggle merging library with exisiting library [default = %s]\n", fMerge? "yes": "no" ); + fprintf( pAbc->Err, "\t-p : toggle using prefix for the cell names [default = %s]\n", fUsePrefix? "yes": "no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\t : the name of a file to read\n" ); fprintf( pAbc->Err, "\t : the name of a file to read (optional)\n" ); diff --git a/src/map/scl/sclLib.h b/src/map/scl/sclLib.h index 08a9066a5..c08f30c09 100644 --- a/src/map/scl/sclLib.h +++ b/src/map/scl/sclLib.h @@ -748,7 +748,7 @@ extern SC_Lib * Abc_SclReadFromStr( Vec_Str_t * vOut ); extern SC_Lib * Abc_SclReadFromFile( char * pFileName ); extern void Abc_SclWriteScl( char * pFileName, SC_Lib * p ); extern void Abc_SclWriteLiberty( char * pFileName, SC_Lib * p ); -extern SC_Lib * Abc_SclMergeLibraries( SC_Lib * pLib1, SC_Lib * pLib2 ); +extern SC_Lib * Abc_SclMergeLibraries( SC_Lib * pLib1, SC_Lib * pLib2, int fUsePrefix ); /*=== sclLibUtil.c ===============================================================*/ extern void Abc_SclHashCells( SC_Lib * p ); extern int Abc_SclCellFind( SC_Lib * p, char * pName ); diff --git a/src/map/scl/sclLibScl.c b/src/map/scl/sclLibScl.c index e13a746e6..1dc57e483 100644 --- a/src/map/scl/sclLibScl.c +++ b/src/map/scl/sclLibScl.c @@ -866,12 +866,12 @@ void Abc_SclWriteLiberty( char * pFileName, SC_Lib * p ) SeeAlso [] ***********************************************************************/ -SC_Lib * Abc_SclMergeLibraries( SC_Lib * pLib1, SC_Lib * pLib2 ) +SC_Lib * Abc_SclMergeLibraries( SC_Lib * pLib1, SC_Lib * pLib2, int fUsePrefix ) { Vec_Str_t * vOut = Vec_StrAlloc( 10000 ); int n_valid_cells2 = Abc_SclCountValidCells( pLib2 ); Abc_SclWriteLibrary( vOut, pLib1, n_valid_cells2 ); - Abc_SclWriteLibraryCellsOnly( vOut, pLib2, 2 ); + Abc_SclWriteLibraryCellsOnly( vOut, pLib2, fUsePrefix ? 2 : 0 ); SC_Lib * p = Abc_SclReadFromStr( vOut ); p->pFileName = Abc_UtilStrsav( pLib1->pFileName ); p->pName = ABC_ALLOC( char, strlen(pLib1->pName) + strlen(pLib2->pName) + 10 ); From 2d6b5c9adc5f9f5a202f143c516e9b3a801bf496 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 15 Apr 2024 20:25:43 -0700 Subject: [PATCH 149/151] Bug fix in CNF generation for &glucose. --- src/sat/glucose/AbcGlucose.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sat/glucose/AbcGlucose.cpp b/src/sat/glucose/AbcGlucose.cpp index cbaedbe62..bc22ff5d2 100644 --- a/src/sat/glucose/AbcGlucose.cpp +++ b/src/sat/glucose/AbcGlucose.cpp @@ -885,7 +885,7 @@ Vec_Int_t * Glucose_SolverFromAig( Gia_Man_t * p, SimpSolver& s ) lits->push( toLit(*pLit) ), s.addVar( *pLit >> 1 ); s.addClause(*lits); } - Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums,pCnf->nVars); + Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums, Gia_ManObjNum(p)); printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Cnf_DataFree(pCnf); From bc725b85deb2d2df135833daa590b2ac1417d3c4 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 15 Apr 2024 20:29:38 -0700 Subject: [PATCH 150/151] Bug fix in CNF generation for &glucose (three more places). --- src/sat/glucose/AbcGlucose.cpp | 2 +- src/sat/glucose2/AbcGlucose2.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sat/glucose/AbcGlucose.cpp b/src/sat/glucose/AbcGlucose.cpp index bc22ff5d2..d6f4c454d 100644 --- a/src/sat/glucose/AbcGlucose.cpp +++ b/src/sat/glucose/AbcGlucose.cpp @@ -899,7 +899,7 @@ Vec_Int_t * Glucose_SolverFromAig2( Gia_Man_t * p, SimpSolver& S ) for ( int i = 0; i < pCnf->nClauses; i++ ) if ( !glucose_solver_addclause( &S, pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) ) assert( 0 ); - Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums,pCnf->nVars); + Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums, Gia_ManObjNum(p)); //printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); //Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Cnf_DataFree(pCnf); diff --git a/src/sat/glucose2/AbcGlucose2.cpp b/src/sat/glucose2/AbcGlucose2.cpp index 0e4871187..6201779cb 100644 --- a/src/sat/glucose2/AbcGlucose2.cpp +++ b/src/sat/glucose2/AbcGlucose2.cpp @@ -903,7 +903,7 @@ Vec_Int_t * Glucose_SolverFromAig( Gia_Man_t * p, SimpSolver& s ) lits->push( toLit(*pLit) ), s.addVar( *pLit >> 1 ); s.addClause(*lits); } - Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums,pCnf->nVars); + Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums, Gia_ManObjNum(p)); printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Cnf_DataFree(pCnf); @@ -917,7 +917,7 @@ Vec_Int_t * Glucose_SolverFromAig2( Gia_Man_t * p, SimpSolver& S ) for ( int i = 0; i < pCnf->nClauses; i++ ) if ( !glucose2_solver_addclause( &S, pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) ) assert( 0 ); - Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums,pCnf->nVars); + Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums, Gia_ManObjNum(p)); //printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); //Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Cnf_DataFree(pCnf); From de060a26adc7f3da91fe35857c9e054089a2c210 Mon Sep 17 00:00:00 2001 From: Peter Gadfort Date: Tue, 16 Apr 2024 08:54:59 -0400 Subject: [PATCH 151/151] ensure initial library writing also honors prefix --- src/map/scl/sclLibScl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/map/scl/sclLibScl.c b/src/map/scl/sclLibScl.c index 1dc57e483..144ec7f55 100644 --- a/src/map/scl/sclLibScl.c +++ b/src/map/scl/sclLibScl.c @@ -570,7 +570,7 @@ int Abc_SclCountValidCells( SC_Lib * p ) n_valid_cells++; return n_valid_cells; } -static void Abc_SclWriteLibrary( Vec_Str_t * vOut, SC_Lib * p, int nExtra ) +static void Abc_SclWriteLibrary( Vec_Str_t * vOut, SC_Lib * p, int nExtra, int fUsePrefix ) { SC_WireLoad * pWL; SC_WireLoadSel * pWLS; @@ -624,13 +624,13 @@ static void Abc_SclWriteLibrary( Vec_Str_t * vOut, SC_Lib * p, int nExtra ) // Write 'cells' vector: n_valid_cells = Abc_SclCountValidCells( p ); Vec_StrPutI( vOut, n_valid_cells + nExtra ); - Abc_SclWriteLibraryCellsOnly( vOut, p, (int)(nExtra > 0) ); + Abc_SclWriteLibraryCellsOnly( vOut, p, fUsePrefix ? 1 : 0 ); } void Abc_SclWriteScl( char * pFileName, SC_Lib * p ) { Vec_Str_t * vOut; vOut = Vec_StrAlloc( 10000 ); - Abc_SclWriteLibrary( vOut, p, 0 ); + Abc_SclWriteLibrary( vOut, p, 0, 0 ); if ( Vec_StrSize(vOut) > 0 ) { FILE * pFile = fopen( pFileName, "wb" ); @@ -870,7 +870,7 @@ SC_Lib * Abc_SclMergeLibraries( SC_Lib * pLib1, SC_Lib * pLib2, int fUsePrefix ) { Vec_Str_t * vOut = Vec_StrAlloc( 10000 ); int n_valid_cells2 = Abc_SclCountValidCells( pLib2 ); - Abc_SclWriteLibrary( vOut, pLib1, n_valid_cells2 ); + Abc_SclWriteLibrary( vOut, pLib1, n_valid_cells2, fUsePrefix ); Abc_SclWriteLibraryCellsOnly( vOut, pLib2, fUsePrefix ? 2 : 0 ); SC_Lib * p = Abc_SclReadFromStr( vOut ); p->pFileName = Abc_UtilStrsav( pLib1->pFileName );