diff options
Diffstat (limited to 'src/base')
41 files changed, 3956 insertions, 140 deletions
diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 8ac5040d..dd189c6d 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -600,7 +600,7 @@ extern ABC_DLL int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk ); /*=== abcCollapse.c ==========================================================*/ -extern ABC_DLL Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fReverse, int fVerbose ); extern ABC_DLL Abc_Ntk_t * Abc_NtkCollapseSat( Abc_Ntk_t * pNtk, int nCubeLim, int nBTLimit, int nCostMax, int fCanon, int fReverse, int fCnfShared, int fVerbose ); extern ABC_DLL Gia_Man_t * Abc_NtkClpGia( Abc_Ntk_t * pNtk ); /*=== abcCut.c ==========================================================*/ @@ -657,6 +657,7 @@ extern ABC_DLL void Abc_ObjPatchFanoutFanin( Abc_Obj_t * pObj, int extern ABC_DLL Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type ); extern ABC_DLL void Abc_ObjTransferFanout( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); extern ABC_DLL void Abc_ObjReplace( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); +extern ABC_DLL void Abc_ObjReplaceByConstant( Abc_Obj_t * pNode, int fConst1 ); extern ABC_DLL int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin ); /*=== abcFanOrder.c ==========================================================*/ extern ABC_DLL int Abc_NtkMakeLegit( Abc_Ntk_t * pNtk ); @@ -761,7 +762,7 @@ extern ABC_DLL Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ); /*=== abcNtbdd.c ==========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_NtkDeriveFromBdd( void * dd, void * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ); extern ABC_DLL Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ); -extern ABC_DLL void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDropInternal, int fReorder, int fVerbose ); +extern ABC_DLL void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDropInternal, int fReorder, int fReverse, int fVerbose ); extern ABC_DLL void * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ); extern ABC_DLL int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk ); /*=== abcNtk.c ==========================================================*/ diff --git a/src/base/abc/abcFanio.c b/src/base/abc/abcFanio.c index caa57a4e..519debb1 100644 --- a/src/base/abc/abcFanio.c +++ b/src/base/abc/abcFanio.c @@ -337,6 +337,30 @@ void Abc_ObjReplace( Abc_Obj_t * pNodeOld, Abc_Obj_t * pNodeNew ) /**Function************************************************************* + Synopsis [Replaces a node by a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjReplaceByConstant( Abc_Obj_t * pNode, int fConst1 ) +{ + Abc_Obj_t * pNodeNew; + assert( Abc_NtkIsLogic(pNode->pNtk) ); + assert( !Abc_ObjIsCo(pNode) ); + pNodeNew = fConst1 ? Abc_NtkCreateNodeConst1(pNode->pNtk) : Abc_NtkCreateNodeConst0(pNode->pNtk); + // transfer the fanouts to the old node + Abc_ObjTransferFanout( pNode, pNodeNew ); + // remove the old node + if ( Abc_ObjIsNode(pNode) ) + Abc_NtkDeleteObj_rec( pNode, 1 ); +} + +/**Function************************************************************* + Synopsis [Returns the index of the fanin in the fanin list of the fanout.] Description [] diff --git a/src/base/abc/abcShow.c b/src/base/abc/abcShow.c index 13dd9346..f91397df 100644 --- a/src/base/abc/abcShow.c +++ b/src/base/abc/abcShow.c @@ -85,12 +85,13 @@ void Abc_NodeShowBddOne( DdManager * dd, DdNode * bFunc ) SeeAlso [] ***********************************************************************/ -void Abc_NodeShowBdd( Abc_Obj_t * pNode ) +void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ) { FILE * pFile; Vec_Ptr_t * vNamesIn; char FileNameDot[200]; char * pNameOut; + DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; assert( Abc_NtkIsBddLogic(pNode->pNtk) ); // create the file name @@ -105,7 +106,14 @@ void Abc_NodeShowBdd( Abc_Obj_t * pNode ) // set the node names vNamesIn = Abc_NodeGetFaninNames( pNode ); pNameOut = Abc_ObjName(pNode); - Cudd_DumpDot( (DdManager *)pNode->pNtk->pManFunc, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); + if ( fCompl ) + Cudd_DumpDot( dd, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); + else + { + DdNode * bAdd = Cudd_BddToAdd( dd, (DdNode *)pNode->pData ); Cudd_Ref( bAdd ); + Cudd_DumpDot( dd, 1, (DdNode **)&bAdd, (char **)vNamesIn->pArray, &pNameOut, pFile ); + Cudd_RecursiveDeref( dd, bAdd ); + } Abc_NodeFreeNames( vNamesIn ); Abc_NtkCleanCopy( pNode->pNtk ); fclose( pFile ); @@ -113,9 +121,72 @@ void Abc_NodeShowBdd( Abc_Obj_t * pNode ) // visualize the file Abc_ShowFile( FileNameDot ); } +void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl ) +{ + char FileNameDot[200]; + char ** ppNamesIn, ** ppNamesOut; + DdManager * dd; DdNode * bFunc; + Vec_Ptr_t * vFuncsGlob; + Abc_Obj_t * pObj; int i; + FILE * pFile; + + assert( Abc_NtkIsStrash(pNtk) ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, 0, 0 ); + if ( dd == NULL ) + { + printf( "Construction of global BDDs has failed.\n" ); + return; + } + //printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); + + // create the file name + Abc_ShowGetFileName( pNtk->pName, FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + + // set the node names + ppNamesIn = Abc_NtkCollectCioNames( pNtk, 0 ); + ppNamesOut = Abc_NtkCollectCioNames( pNtk, 1 ); + if ( fCompl ) + Cudd_DumpDot( dd, Abc_NtkCoNum(pNtk), (DdNode **)Vec_PtrArray(vFuncsGlob), ppNamesIn, ppNamesOut, pFile ); + else + { + DdNode ** pbAdds = ABC_ALLOC( DdNode *, Vec_PtrSize(vFuncsGlob) ); + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + { pbAdds[i] = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( pbAdds[i] ); } + Cudd_DumpDot( dd, Abc_NtkCoNum(pNtk), pbAdds, ppNamesIn, ppNamesOut, pFile ); + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + Cudd_RecursiveDeref( dd, pbAdds[i] ); + ABC_FREE( pbAdds ); + } + ABC_FREE( ppNamesIn ); + ABC_FREE( ppNamesOut ); + fclose( pFile ); + + // cleanup + Abc_NtkFreeGlobalBdds( pNtk, 0 ); + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vFuncsGlob ); + Extra_StopManager( dd ); + Abc_NtkCleanCopy( pNtk ); + + // visualize the file + Abc_ShowFile( FileNameDot ); +} #else -void Abc_NodeShowBdd( Abc_Obj_t * pNode ) {} +void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ) {} +void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl ) {} #endif /**Function************************************************************* diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 0e527058..181ca54a 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -86,6 +86,7 @@ static int Abc_CommandPrintMffc ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandPrintFactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintLevel ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintSupport ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintMint ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintSymms ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintUnate ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintAuto ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -154,6 +155,7 @@ static int Abc_CommandTwoExact ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandLutExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAllExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -184,6 +186,7 @@ static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandReach ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCone ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandNode ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCof ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTopmost ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTopAnd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTrim ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -314,6 +317,8 @@ static int Abc_CommandInsWin ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandPermute ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandUnpermute ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCubeEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPathEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFunEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -775,6 +780,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Printing", "print_factor", Abc_CommandPrintFactor, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_level", Abc_CommandPrintLevel, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_supp", Abc_CommandPrintSupport, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_mint", Abc_CommandPrintMint, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_symm", Abc_CommandPrintSymms, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_unate", Abc_CommandPrintUnate, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_auto", Abc_CommandPrintAuto, 0 ); @@ -844,6 +850,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Exact synthesis", "lutexact", Abc_CommandLutExact, 0 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "allexact", Abc_CommandAllExact, 0 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "testexact", Abc_CommandTestExact, 0 ); + Cmd_CommandAdd( pAbc, "Exact synthesis", "majgen", Abc_CommandMajGen, 0 ); Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 ); Cmd_CommandAdd( pAbc, "Various", "comb", Abc_CommandComb, 1 ); @@ -874,8 +881,9 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "reach", Abc_CommandReach, 0 ); Cmd_CommandAdd( pAbc, "Various", "cone", Abc_CommandCone, 1 ); Cmd_CommandAdd( pAbc, "Various", "node", Abc_CommandNode, 1 ); + Cmd_CommandAdd( pAbc, "Various", "cof", Abc_CommandCof, 1 ); Cmd_CommandAdd( pAbc, "Various", "topmost", Abc_CommandTopmost, 1 ); - Cmd_CommandAdd( pAbc, "Various", "topand", Abc_CommandTopAnd, 1 ); + Cmd_CommandAdd( pAbc, "Various", "topand", Abc_CommandTopAnd, 1 ); Cmd_CommandAdd( pAbc, "Various", "trim", Abc_CommandTrim, 1 ); Cmd_CommandAdd( pAbc, "Various", "short_names", Abc_CommandShortNames, 0 ); Cmd_CommandAdd( pAbc, "Various", "move_names", Abc_CommandMoveNames, 0 ); @@ -999,6 +1007,8 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Sequential", "permute", Abc_CommandPermute, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "unpermute", Abc_CommandUnpermute, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "cubeenum", Abc_CommandCubeEnum, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "pathenum", Abc_CommandPathEnum, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "funenum", Abc_CommandFunEnum, 0 ); Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 ); Cmd_CommandAdd( pAbc, "Verification", "dcec", Abc_CommandDCec, 0 ); @@ -2013,6 +2023,68 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandPrintMint( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Obj_t * pObj; + int c; + int fVerbose; + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "svwh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for logic networks (run \"clp\").\n" ); + return 1; + } + if ( !Abc_NtkHasBdd(pNtk) ) + { + Abc_Print( -1, "This command works only for logic networks with local functions represented by BDDs.\n" ); + return 1; + } + Abc_NtkForEachNode( pNtk, pObj, c ) + printf( "ObjId %3d : SuppSize = %5d MintCount = %32.0f\n", c, Abc_ObjFaninNum(pObj), + Cudd_CountMinterm((DdManager *)pNtk->pManFunc, (DdNode *)pObj->pData, Abc_ObjFaninNum(pObj)) ); + return 0; + +usage: + Abc_Print( -2, "usage: print_mint [-svwh]\n" ); + Abc_Print( -2, "\t prints the number of on-set minterms in the PO functions\n" ); + Abc_Print( -2, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); @@ -2991,15 +3063,22 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; - int c; - extern void Abc_NodeShowBdd( Abc_Obj_t * pNode ); + int c, fCompl = 0, fGlobal = 0; + extern void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ); + extern void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl ); // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "cgh" ) ) != EOF ) { switch ( c ) { + case 'c': + fCompl ^= 1; + break; + case 'g': + fGlobal ^= 1; + break; case 'h': goto usage; default: @@ -3013,12 +3092,20 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } + if ( fGlobal ) + { + Abc_Ntk_t * pTemp = Abc_NtkIsStrash(pNtk) ? pNtk : Abc_NtkStrash(pNtk, 0, 0, 0); + Abc_NtkShowBdd( pTemp, fCompl ); + if ( pTemp != pNtk ) + Abc_NtkDelete( pTemp ); + return 0; + } + if ( !Abc_NtkIsBddLogic(pNtk) ) { Abc_Print( -1, "Visualizing BDDs can only be done for logic BDD networks (run \"bdd\").\n" ); return 1; } - if ( argc > globalUtilOptind + 1 ) { Abc_Print( -1, "Wrong number of auguments.\n" ); @@ -3042,17 +3129,20 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } } - Abc_NodeShowBdd( pNode ); + Abc_NodeShowBdd( pNode, fCompl ); return 0; usage: - Abc_Print( -2, "usage: show_bdd [-h] <node>\n" ); - Abc_Print( -2, " visualizes the BDD of a node using DOT and GSVIEW\n" ); + Abc_Print( -2, "usage: show_bdd [-cgh] <node>\n" ); + Abc_Print( -2, " uses DOT and GSVIEW to visualize the global BDDs of primary outputs\n" ); + Abc_Print( -2, " in terms of primary inputs or the local BDD of a node in terms of its fanins\n" ); #ifdef WIN32 Abc_Print( -2, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); Abc_Print( -2, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); #endif - Abc_Print( -2, "\t<node>: the node to consider [default = the driver of the first PO]\n"); + Abc_Print( -2, "\t<node>: (optional) the node to consider [default = the driver of the first PO]\n"); + Abc_Print( -2, "\t-c : toggle visualizing BDD with complemented edges [default = %s].\n", fCompl? "yes": "no" ); + Abc_Print( -2, "\t-g : toggle visualizing the global BDDs of primary outputs [default = %s].\n", fGlobal? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -3173,16 +3263,18 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) int fBddSizeMax; int fDualRail; int fReorder; + int fReverse; int c; pNtk = Abc_FrameReadNtk(pAbc); // set defaults fVerbose = 0; fReorder = 1; + fReverse = 0; fDualRail = 0; fBddSizeMax = ABC_INFINITY; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Brdvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Brodvh" ) ) != EOF ) { switch ( c ) { @@ -3197,15 +3289,18 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fBddSizeMax < 0 ) goto usage; break; + case 'r': + fReorder ^= 1; + break; + case 'o': + fReverse ^= 1; + break; case 'd': fDualRail ^= 1; break; case 'v': fVerbose ^= 1; break; - case 'r': - fReorder ^= 1; - break; case 'h': goto usage; default: @@ -3227,11 +3322,11 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) // get the new network if ( Abc_NtkIsStrash(pNtk) ) - pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fReverse, fVerbose ); else { pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fReverse, fVerbose ); Abc_NtkDelete( pNtk ); } if ( pNtkRes == NULL ) @@ -3244,10 +3339,11 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: collapse [-B <num>] [-rdvh]\n" ); + Abc_Print( -2, "usage: collapse [-B <num>] [-rodvh]\n" ); Abc_Print( -2, "\t collapses the network by constructing global BDDs\n" ); Abc_Print( -2, "\t-B <num>: limit on live BDD nodes during collapsing [default = %d]\n", fBddSizeMax ); Abc_Print( -2, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles reverse variable ordering [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-d : toggles dual-rail collapsing mode [default = %s]\n", fDualRail? "yes": "no" ); Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -8217,7 +8313,7 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INaogvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INTaogvh" ) ) != EOF ) { switch ( c ) { @@ -8243,6 +8339,17 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nNodes < 0 ) goto usage; break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + pPars->RuntimeLim = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->RuntimeLim < 0 ) + goto usage; + break; case 'a': pPars->fOnlyAnd ^= 1; break; @@ -8290,10 +8397,11 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: twoexact [-IN <num>] [-aogvh] <hex>\n" ); + Abc_Print( -2, "usage: twoexact [-INT <num>] [-aogvh] <hex>\n" ); Abc_Print( -2, "\t exact synthesis of multi-input function using two-input gates\n" ); Abc_Print( -2, "\t-I <num> : the number of input variables [default = %d]\n", pPars->nVars ); - Abc_Print( -2, "\t-N <num> : the number of MAJ3 nodes [default = %d]\n", pPars->nNodes ); + Abc_Print( -2, "\t-N <num> : the number of two-input nodes [default = %d]\n", pPars->nNodes ); + Abc_Print( -2, "\t-T <num> : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); Abc_Print( -2, "\t-a : toggle using only AND-gates (without XOR-gates) [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); Abc_Print( -2, "\t-o : toggle using additional optimizations [default = %s]\n", pPars->fFewerVars ? "yes" : "no" ); Abc_Print( -2, "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon [default = %s]\n", pPars->fGlucose ? "yes" : "no" ); @@ -8329,7 +8437,7 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INKiaogvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INKTiaogvh" ) ) != EOF ) { switch ( c ) { @@ -8366,6 +8474,17 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nLutSize < 0 ) goto usage; break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + pPars->RuntimeLim = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->RuntimeLim < 0 ) + goto usage; + break; case 'i': pPars->fUseIncr ^= 1; break; @@ -8421,11 +8540,12 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutexact [-INK <num>] [-iaogvh] <hex>\n" ); + Abc_Print( -2, "usage: lutexact [-INKT <num>] [-iaogvh] <hex>\n" ); Abc_Print( -2, "\t exact synthesis of I-input function using N K-input gates\n" ); Abc_Print( -2, "\t-I <num> : the number of input variables [default = %d]\n", pPars->nVars ); Abc_Print( -2, "\t-N <num> : the number of K-input nodes [default = %d]\n", pPars->nNodes ); Abc_Print( -2, "\t-K <num> : the number of node fanins [default = %d]\n", pPars->nLutSize ); + Abc_Print( -2, "\t-T <num> : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); Abc_Print( -2, "\t-i : toggle using incremental solving [default = %s]\n", pPars->fUseIncr ? "yes" : "no" ); Abc_Print( -2, "\t-a : toggle using only AND-gates when K = 2 [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); Abc_Print( -2, "\t-o : toggle using additional optimizations [default = %s]\n", pPars->fFewerVars ? "yes" : "no" ); @@ -8681,6 +8801,62 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandMajGen( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Gem_Enumerate( int nVars, int fDump, int fVerbose ); + int c, nVars = 8, fDump = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ndvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; + case 'd': + fDump ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + Gem_Enumerate( nVars, fDump, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: majgen [-N <num>] [-dvh]>\n" ); + Abc_Print( -2, "\t generates networks for majority gates\n" ); + Abc_Print( -2, "\t-N <num> : the maximum number of variables [default = %d]\n", nVars ); + Abc_Print( -2, "\t-d : toggle dumping functions into a file [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; @@ -11067,6 +11243,81 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCof( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c, Const; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Currently can only be applied to a logic network.\n" ); + return 1; + } + + if ( argc != globalUtilOptind + 2 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + pNode = Abc_NtkFindCi( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Const = atoi( argv[globalUtilOptind+1] ); + if ( Const != 0 && Const != 1 ) + { + Abc_Print( -1, "Constant should be 0 or 1.\n", argv[globalUtilOptind+1] ); + return 1; + } + Abc_ObjReplaceByConstant( pNode, Const ); + return 0; + +usage: + Abc_Print( -2, "usage: cof [-h] <node> <const>\n" ); + Abc_Print( -2, "\t replaces one node in a logic network by constant 0 or 1\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t<node> : the node to replace\n"); + Abc_Print( -2, "\t<const> : the constant to replace the node with\n"); + Abc_Print( -2, "\tname : the node name\n"); + return 1; +} + /**Function************************************************************* @@ -12057,9 +12308,11 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) // Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int nVars; // the number of variables + int nArgs; // the number of arguments int nLutSize = -1; // the size of LUTs int nLuts = -1; // the number of LUTs int fAdder; + int fAdderTree; int fSorter; int fMesh; int fMulti; @@ -12076,10 +12329,13 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) extern void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars ); extern void Abc_GenOneHot( char * pFileName, int nVars ); extern void Abc_GenRandom( char * pFileName, int nPis ); + extern void Abc_GenAdderTree( char * pFileName, int nArgs, int nBits ); // set defaults nVars = 8; + nArgs = 8; fAdder = 0; + fAdderTree = 0; fSorter = 0; fMesh = 0; fMulti = 0; @@ -12088,7 +12344,7 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) fRandom = 0; fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NKLasemftrvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "NAKLabsemftrvh" ) ) != EOF ) { switch ( c ) { @@ -12103,6 +12359,17 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nVars < 0 ) goto usage; break; + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); + goto usage; + } + nArgs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nArgs < 0 ) + goto usage; + break; case 'K': if ( globalUtilOptind >= argc ) { @@ -12128,6 +12395,9 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'a': fAdder ^= 1; break; + case 'b': + fAdderTree ^= 1; + break; case 's': fSorter ^= 1; break; @@ -12183,6 +12453,14 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_GenOneHot( FileName, nVars ); else if ( fRandom ) Abc_GenRandom( FileName, nVars ); + else if ( fAdderTree ) + { + printf( "Generating adder tree with %d arguments and %d bits.\n", nArgs, nVars ); + Abc_GenAdderTree( FileName, nArgs, nVars ); + sprintf( Command, "%%read %s; %%blast; &put", FileName ); + Cmd_CommandExecute( pAbc, Command ); + return 0; + } else { Abc_Print( -1, "Type of circuit is not specified.\n" ); @@ -12194,12 +12472,14 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: gen [-NKL num] [-asemftrvh] <file>\n" ); + Abc_Print( -2, "usage: gen [-NAKL num] [-asemftrvh] <file>\n" ); Abc_Print( -2, "\t generates simple circuits\n" ); Abc_Print( -2, "\t-N num : the number of variables [default = %d]\n", nVars ); + Abc_Print( -2, "\t-A num : the number of agruments (for adder tree) [default = %d]\n", nArgs ); Abc_Print( -2, "\t-K num : the LUT size (to be used with switch -f) [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-L num : the LUT count (to be used with switch -f) [default = %d]\n", nLuts ); Abc_Print( -2, "\t-a : generate ripple-carry adder [default = %s]\n", fAdder? "yes": "no" ); + Abc_Print( -2, "\t-b : generate an adder tree [default = %s]\n", fAdderTree? "yes": "no" ); Abc_Print( -2, "\t-s : generate a sorter [default = %s]\n", fSorter? "yes": "no" ); Abc_Print( -2, "\t-e : generate a mesh [default = %s]\n", fMesh? "yes": "no" ); Abc_Print( -2, "\t-m : generate a multiplier [default = %s]\n", fMulti? "yes": "no" ); @@ -12871,11 +13151,12 @@ int Abc_CommandTestColor( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void Dau_NetworkEnumTest(); //Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int nCutMax = 1; int nLeafMax = 4; int nDivMax = 2; - int nDecMax = 70; + int nDecMax = 3; int nNumOnes = 4; int fNewAlgo = 0; int fNewOrder = 0; @@ -13029,7 +13310,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) */ { // extern void Abc_EnumerateFuncs( int nDecMax, int nDivMax, int fVerbose ); -// Abc_EnumerateFuncs( nDecMax, nDivMax, fVerbose ); +// Abc_EnumerateFuncs( 4, 7, 0 ); } /* if ( fNewAlgo ) @@ -13080,7 +13361,8 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) // Cba_PrsReadBlifTest(); } // Abc_NtkComputePaths( Abc_FrameReadNtk(pAbc) ); -// Psl_FileTest(); + //Dau_NetworkEnumTest(); + //Ext_TruthDiagnoseTest(); return 0; usage: Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] <file_name>\n" ); @@ -22756,6 +23038,183 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPathEnum( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_EnumerateFrontierTest( int nSize ); + int c, nSize = 4, fZddAlgo = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSize < 0 ) + goto usage; + break; + case 'z': + fZddAlgo ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + Abc_Print( -2, "Unknown switch.\n"); + goto usage; + } + } + Abc_EnumerateFrontierTest( nSize ); + return 0; + +usage: + Abc_Print( -2, "usage: pathenum [-N num] [-vh]\n" ); + Abc_Print( -2, "\t enumerates self-avoiding paths on the NxN grid\n" ); + Abc_Print( -2, "\t-N num : the size of the grid to consider [default = %d]\n", nSize ); +// Abc_Print( -2, "\t-z : toggle using ZDD-based algorithm [default = %s]\n", fZddAlgo? "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"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFunEnum( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Dtt_EnumerateLf( int nVars, int nNodeMax, int fDelay, int fMulti, int fVerbose ); + extern void Dau_FunctionEnum( int nInputs, int nVars, int nNodeMax, int fUseTwo, int fReduce, int fVerbose ); + int c, nInputs = 4, nVars = 4, nNodeMax = 32, fUseTwo = 0, fReduce = 0, fSimple = 0, fDelay = 0, fMulti = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "SIMtrldmvh" ) ) != EOF ) + { + switch ( c ) + { + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + nInputs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInputs < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nNodeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodeMax < 0 ) + goto usage; + break; + case 't': + fUseTwo ^= 1; + break; + case 'r': + fReduce ^= 1; + break; + case 'l': + fSimple ^= 1; + break; + case 'd': + fDelay ^= 1; + break; + case 'm': + fMulti ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + Abc_Print( -2, "Unknown switch.\n"); + goto usage; + } + } + if ( fSimple || fDelay ) + { + if ( nVars < 3 || nVars > 5 ) + { + Abc_Print( -1, "The number of inputs should be 3 <= I <= 5.\n" ); + goto usage; + } + Dtt_EnumerateLf( nVars, nNodeMax, fDelay, fMulti, fVerbose ); + } + else + { + if ( nVars < 2 || nVars > 6 ) + { + Abc_Print( -1, "The number of inputs should be 2 <= I <= 6.\n" ); + goto usage; + } + if ( nInputs < nVars || nInputs > 6 ) + { + Abc_Print( -1, "The intermediate support size should be I <= S <= 6.\n" ); + goto usage; + } + Dau_FunctionEnum( nInputs, nVars, nNodeMax, fUseTwo, fReduce, fVerbose ); + } + return 0; + +usage: + Abc_Print( -2, "usage: funenum [-SIM num] [-trldmvh]\n" ); + Abc_Print( -2, "\t enumerates minimum 2-input-gate implementations\n" ); + Abc_Print( -2, "\t-S num : the maximum intermediate support size [default = %d]\n", nInputs ); + Abc_Print( -2, "\t-I num : the number of inputs of Boolean functions [default = %d]\n", nVars ); + Abc_Print( -2, "\t-M num : the maximum number of 2-input gates [default = %d]\n", nNodeMax ); + Abc_Print( -2, "\t-t : toggle adding combination of two gates [default = %s]\n", fUseTwo? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle reducing the last level [default = %s]\n", fReduce? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle generating L(f) rather than C(f) [default = %s]\n", fSimple? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle generating D(f) rather than C(f) [default = %s]\n", fDelay? "yes": "no" ); + Abc_Print( -2, "\t-m : toggle generating multiplicity statistics [default = %s]\n", fMulti? "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"); + return 1; +} + /**Function************************************************************* @@ -42647,11 +43106,11 @@ usage: ***********************************************************************/ int Abc_CommandAbc9Polyn( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Gia_PolynBuild2Test( Gia_Man_t * pGia, int nExtra, int fSigned, int fVerbose, int fVeryVerbose ); - Vec_Int_t * vOrder = NULL; - int c, nExtra = -1, fOld = 0, fSimple = 1, fSigned = 0, fVerbose = 0, fVeryVerbose = 0; + extern void Gia_PolynBuild2Test( Gia_Man_t * pGia, char * pSign, int nExtra, int fSigned, int fVerbose, int fVeryVerbose ); + Vec_Int_t * vOrder = NULL; char * pSign = NULL; + int c, nExtra = 0, fOld = 0, fSimple = 1, fSigned = 0, fVerbose = 0, fVeryVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Noasvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "NSoasvwh" ) ) != EOF ) { switch ( c ) { @@ -42666,6 +43125,15 @@ int Abc_CommandAbc9Polyn( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nExtra < 0 ) goto usage; break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by a char string without spaces.\n" ); + goto usage; + } + pSign = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'o': fOld ^= 1; break; @@ -42692,6 +43160,11 @@ int Abc_CommandAbc9Polyn( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Esop(): There is no AIG.\n" ); return 0; } + if ( argc >= globalUtilOptind + 1 ) + { + printf( "Trailing symbols on the command line (\"%s\").\n", argv[globalUtilOptind] ); + return 0; + } if ( fOld ) { vOrder = fSimple ? NULL : Gia_PolynReorder( pAbc->pGia, fVerbose, fVeryVerbose ); @@ -42699,11 +43172,11 @@ int Abc_CommandAbc9Polyn( Abc_Frame_t * pAbc, int argc, char ** argv ) Vec_IntFreeP( &vOrder ); } else - Gia_PolynBuild2Test( pAbc->pGia, nExtra, fSigned, fVerbose, fVeryVerbose ); + Gia_PolynBuild2Test( pAbc->pGia, pSign, nExtra, fSigned, fVerbose, fVeryVerbose ); return 0; usage: - Abc_Print( -2, "usage: &polyn [-N num] [-oasvwh]\n" ); + Abc_Print( -2, "usage: &polyn [-N num] [-oasvwh] [-S str]\n" ); Abc_Print( -2, "\t derives algebraic polynomial from AIG\n" ); Abc_Print( -2, "\t-N num : the number of additional primary outputs (-1 = unused) [default = %d]\n", nExtra ); Abc_Print( -2, "\t-o : toggles old computation [default = %s]\n", fOld? "yes": "no" ); @@ -42712,6 +43185,18 @@ usage: Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles printing very verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t\n"); + Abc_Print( -2, "\t-S str : (optional) the output signature as a character string\n" ); + Abc_Print( -2, "\t The format used to represent the output signature is very restrictive.\n" ); + Abc_Print( -2, "\t It should be a string without spaces containing monomials in terms of\n" ); + Abc_Print( -2, "\t inputs (i<num>) and outputs (o<num>) where <num> is 0-based. Coefficients\n" ); + Abc_Print( -2, "\t are degrees of two, represented by log2 of their value: for example, \n" ); + Abc_Print( -2, "\t \"2\" is 2^2 = 4, \"-4\" is -2^4=-16, \"-0\" is -2^0=-1, etc\n" ); + Abc_Print( -2, "\t Two types of signature are accepted:\n" ); + Abc_Print( -2, "\t (1) a sequence of monomials without parentheses (for example, \"-2*o0+1*o1+0*o2\")\n" ); + Abc_Print( -2, "\t (2) a product of two sequences followed by a sum with a sequence\n" ); + Abc_Print( -2, "\t (for example, \"(4*o0+2*o1+1*o2)*(4*i3+2*i4+1*i5)+(4*o3+2*o4+1*o5)\")\n" ); + Abc_Print( -2, "\t Here is the signature of a signed 2-bit multiplier: \"(0*o0+1*o1+2*o2-3*o3)\"\n" ); return 1; } @@ -43362,6 +43847,16 @@ int Abc_CommandAbc9Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Mfs(): The current AIG has no mapping.\n" ); return 0; } + if ( Gia_ManLutSizeMax(pAbc->pGia) > 6 ) + { + Abc_Print( -1, "Abc_CommandAbc9Mfs(): The current mapping has nodes with more than 6 inputs. Cannot use \"mfs\".\n" ); + return 0; + } + if ( pAbc->pGia->pAigExtra && Gia_ManPiNum(pAbc->pGia->pAigExtra) > 6 ) + { + Abc_Print( -1, "Abc_CommandAbc9Mfs(): The current white-boxes have more than 6 inputs. Cannot use \"mfs\".\n" ); + return 0; + } pTemp = Gia_ManPerformMfs( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; @@ -43379,7 +43874,7 @@ usage: Abc_Print( -2, "\t-d : toggle performing redundancy removal [default = %s]\n", pPars->fRrOnly? "yes": "no" ); Abc_Print( -2, "\t-a : toggle minimizing area or area+edges [default = %s]\n", pPars->fArea? "area": "area+edges" ); Abc_Print( -2, "\t-e : toggle high-effort resubstitution [default = %s]\n", pPars->fMoreEffort? "yes": "no" ); - Abc_Print( -2, "\t-b : toggle preserving all while boxes [default = %s]\n", pPars->fAllBoxes? "yes": "no" ); + Abc_Print( -2, "\t-b : toggle preserving all white boxes [default = %s]\n", pPars->fAllBoxes? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); diff --git a/src/base/abci/abcAuto.c b/src/base/abci/abcAuto.c index 18c92657..8f7eead0 100644 --- a/src/base/abci/abcAuto.c +++ b/src/base/abci/abcAuto.c @@ -62,7 +62,7 @@ void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ) Abc_Obj_t * pObj; // compute the global BDDs - if ( Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose) == NULL ) + if ( Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, 0, fVerbose) == NULL ) return; // get information about the network diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index 9abdd792..6615bff0 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -70,7 +70,7 @@ Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVer assert( Abc_NtkIsStrash(pNtk) ); // compute the global BDDs - if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL ) + if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, 0, fVerbose) == NULL ) return NULL; if ( fVerbose ) diff --git a/src/base/abci/abcCascade.c b/src/base/abci/abcCascade.c index 70f2e891..50e66675 100644 --- a/src/base/abci/abcCascade.c +++ b/src/base/abci/abcCascade.c @@ -1010,7 +1010,7 @@ Abc_Ntk_t * Abc_NtkBddDec( Abc_Ntk_t * pNtk, int fVerbose ) int i; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkCoNum(pNtk) <= BDD_FUNC_MAX ); - dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, nBddSizeMax, fDropInternal, fReorder, fVerbose ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, nBddSizeMax, fDropInternal, fReorder, 0, fVerbose ); if ( dd == NULL ) { Abc_Print( -1, "Construction of global BDDs has failed.\n" ); diff --git a/src/base/abci/abcCollapse.c b/src/base/abci/abcCollapse.c index 1542c25a..caeea3a1 100644 --- a/src/base/abci/abcCollapse.c +++ b/src/base/abci/abcCollapse.c @@ -118,7 +118,7 @@ int Abc_NtkMinimumBase2( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc ) +Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc, int fReverse ) { Abc_Obj_t * pNodeNew, * pTemp; int i; @@ -126,12 +126,12 @@ Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode pNodeNew = Abc_NtkCreateNode( pNtkNew ); // add the fanins in the order, in which they appear in the reordered manager Abc_NtkForEachCi( pNtkNew, pTemp, i ) - Abc_ObjAddFanin( pNodeNew, Abc_NtkCi(pNtkNew, dd->invperm[i]) ); + Abc_ObjAddFanin( pNodeNew, Abc_NtkCi(pNtkNew, fReverse ? Abc_NtkCiNum(pNtkNew)-1-dd->invperm[i] : dd->invperm[i]) ); // transfer the function pNodeNew->pData = Extra_TransferLevelByLevel( dd, (DdManager *)pNtkNew->pManFunc, bFunc ); Cudd_Ref( (DdNode *)pNodeNew->pData ); return pNodeNew; } -Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ) +Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk, int fReverse ) { ProgressBar * pProgress; Abc_Ntk_t * pNtkNew; @@ -147,7 +147,7 @@ Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ) assert( Abc_NtkIsStrash(pNtk->pExdc) ); assert( Abc_NtkCoNum(pNtk->pExdc) == 1 ); // compute the global BDDs - if ( Abc_NtkBuildGlobalBdds(pNtk->pExdc, 10000000, 1, 1, 0) == NULL ) + if ( Abc_NtkBuildGlobalBdds(pNtk->pExdc, 10000000, 1, 1, 0, 0) == NULL ) return NULL; // transfer tot the same manager ddExdc = (DdManager *)Abc_NtkGlobalBddMan( pNtk->pExdc ); @@ -188,21 +188,21 @@ Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ) Abc_ObjAddFanin( pNode->pCopy, pDriver->pCopy ); continue; } - pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, (DdNode *)Abc_ObjGlobalBdd(pNode) ); + pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, (DdNode *)Abc_ObjGlobalBdd(pNode), fReverse ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); } Extra_ProgressBarStop( pProgress ); return pNtkNew; } -Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ) +Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fReverse, int fVerbose ) { Abc_Ntk_t * pNtkNew; abctime clk = Abc_Clock(); assert( Abc_NtkIsStrash(pNtk) ); // compute the global BDDs - if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL ) + if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fReverse, fVerbose) == NULL ) return NULL; if ( fVerbose ) { @@ -212,7 +212,7 @@ Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, i } // create the new network - pNtkNew = Abc_NtkFromGlobalBdds( pNtk ); + pNtkNew = Abc_NtkFromGlobalBdds( pNtk, fReverse ); Abc_NtkFreeGlobalBdds( pNtk, 1 ); if ( pNtkNew == NULL ) return NULL; @@ -236,7 +236,7 @@ Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, i #else -Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ) +Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fReverse, int fVerbose ) { return NULL; } diff --git a/src/base/abci/abcDsd.c b/src/base/abci/abcDsd.c index 4d8f5217..5121a4fc 100644 --- a/src/base/abci/abcDsd.c +++ b/src/base/abci/abcDsd.c @@ -67,7 +67,7 @@ Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, int fVerbose, int fPrint, int fS DdManager * dd; Abc_Ntk_t * pNtkNew; assert( Abc_NtkIsStrash(pNtk) ); - dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, 0, fVerbose ); if ( dd == NULL ) return NULL; if ( fVerbose ) diff --git a/src/base/abci/abcExact.c b/src/base/abci/abcExact.c index 2fbf63dd..b717f5b4 100644 --- a/src/base/abci/abcExact.c +++ b/src/base/abci/abcExact.c @@ -2983,8 +2983,8 @@ void Abc_ExactStoreTest( int fVerbose ) Abc_Ntk_t * pNtk; Abc_Obj_t * pFanins[4]; Vec_Ptr_t * vNames; - char pPerm[4]; - int Cost; + char pPerm[4] = {0}; + int Cost = 0; pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); pNtk->pName = Extra_UtilStrsav( "exact" ); diff --git a/src/base/abci/abcGen.c b/src/base/abci/abcGen.c index 26ee3f86..e90040ab 100644 --- a/src/base/abci/abcGen.c +++ b/src/base/abci/abcGen.c @@ -821,6 +821,55 @@ void Abc_GenFsm( char * pFileName, int nPis, int nPos, int nStates, int nLines, Vec_StrFree( vCond ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AdderTree( FILE * pFile, int nArgs, int nBits ) +{ + int i, k, nDigits = Abc_Base10Log( nBits ), Log2 = Abc_Base2Log( nArgs ); + assert( nArgs > 1 && nBits > 1 ); + fprintf( pFile, "module adder_tree_%d_%d (\n ", nArgs, nBits ); + for ( i = 0; i < nBits; i++, fprintf(pFile, "\n ") ) + for ( k = 0; k < nArgs; k++ ) + fprintf( pFile, " i%0*d_%0*d,", nDigits, k, nDigits, nBits-1-i ); + fprintf( pFile, " z\n" ); + fprintf( pFile, " );\n" ); + for ( i = 0; i < nBits; i++ ) + { + fprintf( pFile, " input" ); + for ( k = 0; k < nArgs; k++ ) + fprintf( pFile, " i%0*d_%0*d%s", nDigits, k, nDigits, nBits-1-i, k==nArgs-1 ? "":"," ); + fprintf( pFile, ";\n" ); + } + fprintf( pFile, " output [%d:0] z;\n", nBits+Log2-1 ); + for ( i = 0; i < nArgs; i++ ) + { + fprintf( pFile, " wire [%d:0] t%d = {", nBits-1, i ); + for ( k = 0; k < nBits; k++ ) + fprintf( pFile, " i%0*d_%0*d%s", nDigits, i, nDigits, nBits-1-k, k==nBits-1 ? "":"," ); + fprintf( pFile, " };\n" ); + } + for ( i = 0; i < nArgs-1; i++ ) + fprintf( pFile, " wire [%d:0] s%d = t%d + %s%d;\n", nBits+Log2-1, i+1, i+1, i ? "s":"t", i ); + fprintf( pFile, " assign z = s%d;\n", nArgs-1 ); + fprintf( pFile, "endmodule\n\n" ); +} +void Abc_GenAdderTree( char * pFileName, int nArgs, int nBits ) +{ + FILE * pFile = fopen( pFileName, "w" ); + fprintf( pFile, "// %d-argument %d-bit adder-tree generated by ABC on %s\n", nArgs, nBits, Extra_TimeStamp() ); + Abc_AdderTree( pFile, nArgs, nBits ); + fclose( pFile ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcIvy.c b/src/base/abci/abcIvy.c index 59481d3e..e4a5d3b4 100644 --- a/src/base/abci/abcIvy.c +++ b/src/base/abci/abcIvy.c @@ -600,7 +600,7 @@ int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ) printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit ); fflush( stdout ); } - pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 ); + pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0, 0 ); if ( pNtk ) { Abc_NtkDelete( pNtkTemp ); diff --git a/src/base/abci/abcLutmin.c b/src/base/abci/abcLutmin.c index ad686299..2ac44060 100644 --- a/src/base/abci/abcLutmin.c +++ b/src/base/abci/abcLutmin.c @@ -739,7 +739,7 @@ Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fVerbose ) else pNtkNew = Abc_NtkStrash( pNtkInit, 0, 1, 0 ); // collapse the network - pNtkNew = Abc_NtkCollapse( pTemp = pNtkNew, 10000, 0, 1, 0 ); + pNtkNew = Abc_NtkCollapse( pTemp = pNtkNew, 10000, 0, 1, 0, 0 ); Abc_NtkDelete( pTemp ); if ( pNtkNew == NULL ) return NULL; diff --git a/src/base/abci/abcNpn.c b/src/base/abci/abcNpn.c index d2d06924..744b6443 100644 --- a/src/base/abci/abcNpn.c +++ b/src/base/abci/abcNpn.c @@ -295,10 +295,6 @@ void Abc_TruthNpnPerform( Abc_TtStore_t * p, int NpnType, int fVerbose ) } else if ( NpnType == 7 ) { - extern unsigned Abc_TtCanonicizeHie(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int fExact ); - extern Abc_TtHieMan_t * Abc_TtHieManStart( int nVars, int nLevels ); - extern void Abc_TtHieManStop(Abc_TtHieMan_t * p ); - int fExact = 0; Abc_TtHieMan_t * pMan = Abc_TtHieManStart( p->nVars, 5 ); for ( i = 0; i < p->nFuncs; i++ ) @@ -318,8 +314,6 @@ void Abc_TruthNpnPerform( Abc_TtStore_t * p, int NpnType, int fVerbose ) typedef unsigned(*TtCanonicizeFunc)(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int flag); unsigned Abc_TtCanonicizeWrap(TtCanonicizeFunc func, Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int flag); unsigned Abc_TtCanonicizeAda(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int iThres); - Abc_TtHieMan_t * Abc_TtHieManStart(int nVars, int nLevels); - void Abc_TtHieManStop(Abc_TtHieMan_t * p); int fHigh = 1, iEnumThres = 25; Abc_TtHieMan_t * pMan = Abc_TtHieManStart(p->nVars, 5); diff --git a/src/base/abci/abcNtbdd.c b/src/base/abci/abcNtbdd.c index 0225d800..a55ea227 100644 --- a/src/base/abci/abcNtbdd.c +++ b/src/base/abci/abcNtbdd.c @@ -254,7 +254,7 @@ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * SeeAlso [] ***********************************************************************/ -void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ) +void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInternal, int fReorder, int fReverse, int fVerbose ) { ProgressBar * pProgress; Abc_Obj_t * pObj, * pFanin; @@ -287,8 +287,7 @@ void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInter Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) > 0 ) { - bFunc = dd->vars[i]; -// bFunc = dd->vars[Abc_NtkCiNum(pNtk) - 1 - i]; + bFunc = fReverse ? dd->vars[Abc_NtkCiNum(pNtk) - 1 - i] : dd->vars[i]; Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc ); } diff --git a/src/base/abci/abcProve.c b/src/base/abci/abcProve.c index c31e9d94..03722926 100644 --- a/src/base/abci/abcProve.c +++ b/src/base/abci/abcProve.c @@ -201,7 +201,7 @@ int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pPars ) fflush( stdout ); } clk = Abc_Clock(); - pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 ); + pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0, 0 ); if ( pNtk ) { Abc_NtkDelete( pNtkTemp ); diff --git a/src/base/abci/abcReach.c b/src/base/abci/abcReach.c index 908b16be..bf705dc9 100644 --- a/src/base/abci/abcReach.c +++ b/src/base/abci/abcReach.c @@ -271,7 +271,7 @@ void Abc_NtkVerifyUsingBdds( Abc_Ntk_t * pNtk, int nBddMax, int nIterMax, int fP assert( Abc_ObjFanoutNum(Abc_NtkPo(pNtk,0)) == 0 ); // PO should go first // compute the global BDDs of the latches - dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, nBddMax, 1, fReorder, fVerbose ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, nBddMax, 1, fReorder, 0, fVerbose ); if ( dd == NULL ) { printf( "The number of intermediate BDD nodes exceeded the limit (%d).\n", nBddMax ); diff --git a/src/base/abci/abcSymm.c b/src/base/abci/abcSymm.c index 096c3ae4..36a5ee3e 100644 --- a/src/base/abci/abcSymm.c +++ b/src/base/abci/abcSymm.c @@ -99,7 +99,7 @@ void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int // compute the global functions clk = Abc_Clock(); - dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, fReorder, fVerbose ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, fReorder, 0, fVerbose ); printf( "Shared BDD size = %d nodes.\n", Abc_NtkSizeOfGlobalBdds(pNtk) ); Cudd_AutodynDisable( dd ); if ( !fGarbCollect ) diff --git a/src/base/abci/abcUnate.c b/src/base/abci/abcUnate.c index 63003237..211f1ca3 100644 --- a/src/base/abci/abcUnate.c +++ b/src/base/abci/abcUnate.c @@ -82,7 +82,7 @@ void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose ) abctime clkBdd, clkUnate; // compute the global BDDs - dd = (DdManager *)Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose); + dd = (DdManager *)Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, 0, fVerbose); if ( dd == NULL ) return; clkBdd = Abc_Clock() - clk; diff --git a/src/base/abci/abcUnreach.c b/src/base/abci/abcUnreach.c index 679d9eed..ae4bc84b 100644 --- a/src/base/abci/abcUnreach.c +++ b/src/base/abci/abcUnreach.c @@ -67,7 +67,7 @@ int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, int fVerbose ) } // compute the global BDDs of the latches - dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, 0, fVerbose ); if ( dd == NULL ) return 0; if ( fVerbose ) diff --git a/src/base/acb/acbFunc.c b/src/base/acb/acbFunc.c index d73d1d59..1efb5807 100644 --- a/src/base/acb/acbFunc.c +++ b/src/base/acb/acbFunc.c @@ -198,7 +198,7 @@ int Acb_WireIsTarget( int Token, Abc_Nam_t * pNames ) } void * Acb_VerilogSimpleParse( Vec_Int_t * vBuffer, Abc_Nam_t * pNames ) { - void * pDesign = NULL; + Ndr_Data_t * pDesign = NULL; Vec_Int_t * vInputs = Vec_IntAlloc(100); Vec_Int_t * vOutputs = Vec_IntAlloc(100); Vec_Int_t * vWires = Vec_IntAlloc(100); diff --git a/src/base/cmd/cmdStarter.c b/src/base/cmd/cmdStarter.c index 47cdd9ed..ffb2b752 100644 --- a/src/base/cmd/cmdStarter.c +++ b/src/base/cmd/cmdStarter.c @@ -176,7 +176,8 @@ void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCor ABC_FREE( Buffer ); fclose( pFile ); return; - } + } + fclose( pFileTemp ); } } diff --git a/src/base/io/io.c b/src/base/io/io.c index 5133ef0d..f155c7b6 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -2678,14 +2678,24 @@ usage: ***********************************************************************/ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) { + extern int Io_WriteMoPlaM( Abc_Ntk_t * pNtk, char * pFileName, int nMints ); char * pFileName; - int c, fUseMoPla = 0; + int c, fUseMoPla = 0, nMints = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Mmh" ) ) != EOF ) { switch ( c ) { + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMints = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; case 'm': fUseMoPla ^= 1; break; @@ -2705,15 +2715,28 @@ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer - Io_Write( pAbc->pNtkCur, pFileName, fUseMoPla ? IO_FILE_MOPLA : IO_FILE_PLA ); + if ( nMints ) + { + if ( Abc_NtkIsBddLogic(pAbc->pNtkCur) ) + Io_WriteMoPlaM( pAbc->pNtkCur, pFileName, nMints ); + else + { + Abc_Ntk_t * pStrash = Abc_NtkStrash( pAbc->pNtkCur, 0, 0, 0 ); + Io_WriteMoPlaM( pStrash, pFileName, nMints ); + Abc_NtkDelete( pStrash ); + } + } + else + Io_Write( pAbc->pNtkCur, pFileName, fUseMoPla ? IO_FILE_MOPLA : IO_FILE_PLA ); return 0; usage: - fprintf( pAbc->Err, "usage: write_pla [-mh] <file>\n" ); - fprintf( pAbc->Err, "\t writes the collapsed network into a PLA file\n" ); - fprintf( pAbc->Err, "\t-m : toggle writing multi-output PLA [default = %s]\n", fUseMoPla? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + fprintf( pAbc->Err, "usage: write_pla [-M <num>] [-mh] <file>\n" ); + fprintf( pAbc->Err, "\t writes the collapsed network into a PLA file\n" ); + fprintf( pAbc->Err, "\t-M <num> : the number of on-set minterms to write [default = %d]\n", nMints ); + fprintf( pAbc->Err, "\t-m : toggle writing multi-output PLA [default = %s]\n", fUseMoPla? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } diff --git a/src/base/io/ioWritePla.c b/src/base/io/ioWritePla.c index 676617a1..8aa9ee19 100644 --- a/src/base/io/ioWritePla.c +++ b/src/base/io/ioWritePla.c @@ -383,14 +383,14 @@ int Io_WriteMoPlaOneIntMinterms( FILE * pFile, Abc_Ntk_t * pNtk, DdManager * dd, ***********************************************************************/ int Io_WriteMoPlaOne( FILE * pFile, Abc_Ntk_t * pNtk ) { - int fVerbose = 1; + int fVerbose = 0; DdManager * dd; DdNode * bFunc; Vec_Ptr_t * vFuncsGlob; Abc_Obj_t * pObj; int i; assert( Abc_NtkIsStrash(pNtk) ); - dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, 0, fVerbose ); if ( dd == NULL ) return 0; if ( fVerbose ) @@ -445,9 +445,136 @@ int Io_WriteMoPla( Abc_Ntk_t * pNtk, char * pFileName ) return 1; } + + +/**Function************************************************************* + + Synopsis [Writes the network in PLA format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteMoPlaOneIntMintermsM( FILE * pFile, Abc_Ntk_t * pNtk, DdManager * dd, DdNode * bFunc, int nMints ) +{ + Abc_Obj_t * pNode; + int * pArray = ABC_CALLOC( int, dd->size ); + DdNode ** pbMints = Cudd_bddPickArbitraryMinterms( dd, bFunc, dd->vars, dd->size, nMints ); + int i, k, nInputs = Abc_NtkCiNum(pNtk); + assert( dd->size == Abc_NtkCiNum(pNtk) ); + + // write the header + fprintf( pFile, ".i %d\n", nInputs ); + fprintf( pFile, ".o %d\n", 1 ); + fprintf( pFile, ".ilb" ); + Abc_NtkForEachCi( pNtk, pNode, i ) + fprintf( pFile, " %s", Abc_ObjName(pNode) ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".ob" ); + fprintf( pFile, " %s", Abc_ObjName(Abc_NtkCo(pNtk, 0)) ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".p %d\n", nMints ); + + // iterate through minterms + for ( k = 0; k < nMints; k++ ) + { + Cudd_BddToCubeArray( dd, pbMints[k], pArray ); + for ( i = 0; i < Abc_NtkCiNum(pNtk); i++ ) + if ( pArray[i] == 0 ) + fprintf( pFile, "%c", '0' ); + else if ( pArray[i] == 1 ) + fprintf( pFile, "%c", '1' ); + else if ( pArray[i] == 2 ) + fprintf( pFile, "%c", '-' ); + fprintf( pFile, " " ); + fprintf( pFile, "%c", '1' ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".e\n" ); + + //for ( k = 0; k < nMints; k++ ) + // Cudd_RecursiveDeref( dd, pbMints[k] ); + ABC_FREE( pbMints ); + ABC_FREE( pArray ); + return 1; +} +int Io_WriteMoPlaOneM( FILE * pFile, Abc_Ntk_t * pNtk, int nMints ) +{ + int fVerbose = 0; + DdManager * dd; + DdNode * bFunc; + Vec_Ptr_t * vFuncsGlob; + Abc_Obj_t * pObj; + int i; + if ( Abc_NtkIsStrash(pNtk) ) + { + assert( Abc_NtkIsStrash(pNtk) ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, 0, fVerbose ); + if ( dd == NULL ) + return 0; + if ( fVerbose ) + printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); + + // get the output function + bFunc = (DdNode *)Vec_PtrEntry(vFuncsGlob, 0); + if ( bFunc == Cudd_ReadOne(dd) ) + printf( "First primary output has constant 1 function.\n" ); + else if ( Cudd_Not(bFunc) == Cudd_ReadOne(dd) ) + printf( "First primary output has constant 0 function.\n" ); + else + Io_WriteMoPlaOneIntMintermsM( pFile, pNtk, dd, bFunc, nMints ); + Abc_NtkFreeGlobalBdds( pNtk, 0 ); + + // cleanup + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vFuncsGlob ); + //Extra_StopManager( dd ); + Cudd_Quit( dd ); + } + else if ( Abc_NtkIsBddLogic(pNtk) ) + { + DdNode * bFunc = (DdNode *)Abc_ObjFanin0(Abc_NtkCo(pNtk, 0))->pData; + dd = (DdManager *)pNtk->pManFunc; + if ( dd->size == Abc_NtkCiNum(pNtk) ) + Io_WriteMoPlaOneIntMintermsM( pFile, pNtk, dd, bFunc, nMints ); + else + { + printf( "Cannot write minterms because the size of the manager for local BDDs is not equal to\n" ); + printf( "the number of primary inputs. (It is likely that the current network is not collapsed.)\n" ); + } + } + return 1; +} +int Io_WriteMoPlaM( Abc_Ntk_t * pNtk, char * pFileName, int nMints ) +{ + FILE * pFile; + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsBddLogic(pNtk) ); + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteMoPlaM(): Cannot open the output file.\n" ); + return 0; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + Io_WriteMoPlaOneM( pFile, pNtk, nMints ); + fclose( pFile ); + return 1; +} + + #else -int Io_WriteMoPla( Abc_Ntk_t * pNtk, char * pFileName ) { return 1; } +int Io_WriteMoPla( Abc_Ntk_t * pNtk, char * pFileName ) { return 1; } +int Io_WriteMoPlaM( Abc_Ntk_t * pNtk, char * pFileName, int nMints ) { return 1; } #endif diff --git a/src/base/main/abcapis.h b/src/base/main/abcapis.h index af7888e1..9ac2036a 100644 --- a/src/base/main/abcapis.h +++ b/src/base/main/abcapis.h @@ -98,6 +98,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 return sequential equivalences +extern ABC_DLL int * Abc_FrameReadMiniAigEquivClasses( Abc_Frame_t * pAbc ); + ABC_NAMESPACE_HEADER_END #endif diff --git a/src/base/wlc/wlc.h b/src/base/wlc/wlc.h index 02921722..3a84031e 100644 --- a/src/base/wlc/wlc.h +++ b/src/base/wlc/wlc.h @@ -100,7 +100,8 @@ typedef enum { WLC_OBJ_WRITE, // 55: write port WLC_OBJ_ARI_ADDSUB, // 56: adder-subtractor WLC_OBJ_SEL, // 57: positionally encoded selector - WLC_OBJ_NUMBER // 57: unused + WLC_OBJ_DEC, // 58: decoder + WLC_OBJ_NUMBER // 59: unused } Wlc_ObjType_t; // when adding new types, remember to update table Wlc_Names in "wlcNtk.c" @@ -139,6 +140,7 @@ struct Wlc_Ntk_t_ Vec_Int_t vCis; // combinational inputs Vec_Int_t vCos; // combinational outputs Vec_Int_t vFfs; // flops + Vec_Int_t vFfs2; // flops Vec_Int_t * vInits; // initial values char * pInits; // initial values int nObjs[WLC_OBJ_NUMBER]; // counter of objects of each type @@ -208,6 +210,7 @@ struct Wlc_BstPar_t_ int fAddOutputs; int fMulti; int fBooth; + int fCla; int fNoCleanup; int fCreateMiter; int fDecMuxes; @@ -226,6 +229,7 @@ static inline void Wlc_BstParDefault( Wlc_BstPar_t * pPar ) pPar->fAddOutputs = 0; pPar->fMulti = 0; pPar->fBooth = 0; + pPar->fCla = 0; pPar->fCreateMiter = 0; pPar->fDecMuxes = 0; pPar->fVerbose = 0; @@ -272,6 +276,7 @@ static inline Wlc_Obj_t * Wlc_NtkPo( Wlc_Ntk_t * p, int i ) static inline Wlc_Obj_t * Wlc_NtkCi( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vCis, i) ); } static inline Wlc_Obj_t * Wlc_NtkCo( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vCos, i) ); } static inline Wlc_Obj_t * Wlc_NtkFf( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vFfs, i) ); } +static inline Wlc_Obj_t * Wlc_NtkFf2( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vFfs2, i) ); } static inline int Wlc_ObjIsPi( Wlc_Obj_t * p ) { return p->Type == WLC_OBJ_PI; } static inline int Wlc_ObjIsPo( Wlc_Obj_t * p ) { return p->fIsPo; } @@ -347,6 +352,8 @@ static inline Wlc_Obj_t * Wlc_ObjCo2PoFo( Wlc_Ntk_t * p, int iCoId ) for ( i = 0; (i < Wlc_NtkCoNum(p)) && (((pCo) = Wlc_NtkCo(p, i)), 1); i++ ) #define Wlc_NtkForEachFf( p, pFf, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vFfs)) && (((pFf) = Wlc_NtkFf(p, i)), 1); i++ ) +#define Wlc_NtkForEachFf2( p, pFf, i ) \ + for ( i = 0; (i < Vec_IntSize(&p->vFfs2)) && (((pFf) = Wlc_NtkFf2(p, i)), 1); i++ ) #define Wlc_ObjForEachFanin( pObj, iFanin, i ) \ for ( i = 0; (i < Wlc_ObjFaninNum(pObj)) && (((iFanin) = Wlc_ObjFaninId(pObj, i)), 1); i++ ) diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c index b97dfdad..e4088f9c 100644 --- a/src/base/wlc/wlcBlast.c +++ b/src/base/wlc/wlcBlast.c @@ -131,6 +131,12 @@ int Wlc_NtkMuxTree2( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData Vec_IntPush( vTemp, Abc_LitNot( Gia_ManHashAnd(pNew, iLit, Vec_IntEntry(vData, m)) ) ); return Abc_LitNot( Gia_ManHashAndMulti(pNew, vTemp) ); } +void Wlc_NtkPrintNameArray( Vec_Ptr_t * vNames ) +{ + int i; char * pTemp; + Vec_PtrForEachEntry( char *, vNames, pTemp, i ) + printf( "%2d : %s\n", i, pTemp ); +} /**Function************************************************************* @@ -345,9 +351,9 @@ void Wlc_BlastAdder( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int for ( b = 0; b < nBits; b++ ) Wlc_BlastFullAdder( pNew, pAdd0[b], pAdd1[b], Carry, &Carry, &pAdd0[b] ); } -void Wlc_BlastSubtract( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits ) // result is in pAdd0 +void Wlc_BlastSubtract( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int Carry ) // result is in pAdd0 { - int b, Carry = 1; + int b; for ( b = 0; b < nBits; b++ ) Wlc_BlastFullAdder( pNew, pAdd0[b], Abc_LitNot(pAdd1[b]), Carry, &Carry, &pAdd0[b] ); } @@ -375,7 +381,7 @@ void Wlc_BlastAdderCLA_rec( Gia_Man_t * pNew, int * pGen, int * pPro, int * pCar Wlc_BlastAdderCLA_one( pNew, pGen2, pPro2, pCar, pGen1, pPro1, pCar+nBits/2 ); // returns *pGen1, *pPro1, pCar[nBits/2] } } -void Wlc_BlastAdderCLA( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits ) // result is in pAdd0 +void Wlc_BlastAdderCLA_int( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int CarryIn ) // result is in pAdd0 { int * pGen = ABC_CALLOC( int, nBits ); int * pPro = ABC_CALLOC( int, nBits ); @@ -383,12 +389,12 @@ void Wlc_BlastAdderCLA( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits ) int b, Gen, Pro; if ( nBits == 1 ) { - int Carry = 0; + int Carry = CarryIn; Wlc_BlastFullAdder( pNew, pAdd0[0], pAdd1[0], Carry, &Carry, &pAdd0[0] ); return; } assert( nBits >= 2 ); - pCar[0] = 0; + pCar[0] = CarryIn; for ( b = 0; b < nBits; b++ ) { pGen[b] = Gia_ManHashAnd(pNew, pAdd0[b], pAdd1[b]); @@ -401,6 +407,117 @@ void Wlc_BlastAdderCLA( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits ) ABC_FREE(pPro); ABC_FREE(pCar); } +void Wlc_BlastAdderCLA( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int fSign, int CarryIn ) // result is in pAdd0 +{ + int i, Log2 = Abc_Base2Log(nBits); + int * pAdd0n = ABC_CALLOC( int, 1<<Log2 ); + int * pAdd1n = ABC_CALLOC( int, 1<<Log2 ); + for ( i = 0; i < nBits; i++ ) + { + pAdd0n[i] = pAdd0[i]; + pAdd1n[i] = pAdd1[i]; + } + for ( ; i < (1<<Log2); i++ ) + { + pAdd0n[i] = fSign ? pAdd0[nBits-1] : 0; + pAdd1n[i] = fSign ? pAdd1[nBits-1] : 0; + } + Wlc_BlastAdderCLA_int( pNew, pAdd0n, pAdd1n, 1<<Log2, CarryIn ); + for ( i = 0; i < nBits; i++ ) + pAdd0[i] = pAdd0n[i]; + ABC_FREE(pAdd0n); + ABC_FREE(pAdd1n); +} + +void Wlc_BlastAdderFast_int( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int Log2, int CarryIn ) // result is in pAdd0 +{ + int i, b, Gen, Pro, nBits = 1 << Log2; + int * pGen = ABC_CALLOC( int, nBits+1 ); + int * pPro = ABC_CALLOC( int, nBits+1 ); + int * pPro2= ABC_CALLOC( int, nBits+1 ); + if ( nBits == 1 ) + { + int Carry = CarryIn; + Wlc_BlastFullAdder( pNew, pAdd0[0], pAdd1[0], Carry, &Carry, &pAdd0[0] ); + ABC_FREE(pGen); + ABC_FREE(pPro); + ABC_FREE(pPro2); + return; + } + assert( nBits >= 2 ); + pGen[0] = CarryIn; + pPro[0] = 0; + pPro2[0]= 0; + for ( b = 1; b <= nBits; b++ ) + { + pGen[b] = Gia_ManHashAnd(pNew, pAdd0[b-1], pAdd1[b-1]); + pPro[b] = Gia_ManHashXor(pNew, pAdd0[b-1], pAdd1[b-1]); + pPro2[b]= pPro[b]; + } + + // Han-Carlson adder from http://www.aoki.ecei.tohoku.ac.jp/arith/mg/algorithm.html + for ( b = 1; b <= nBits; b += 2 ) + { + Gen = Gia_ManHashOr( pNew, pGen[b], Gia_ManHashAnd(pNew, pPro[b], pGen[b-1]) ); + Pro = Gia_ManHashAnd(pNew, pPro[b], pPro[b-1]); + pPro[b] = Pro; + pGen[b] = Gen; + } + for ( i = 1; i < Log2-1; i++ ) + { + for ( b = 1 + 2*i; b <= nBits; b += 2 ) + { + Gen = Gia_ManHashOr( pNew, pGen[b], Gia_ManHashAnd(pNew, pPro[b], pGen[b-i*2]) ); + Pro = Gia_ManHashAnd(pNew, pPro[b], pPro[b-i*2]); + pPro[b] = Pro; + pGen[b] = Gen; + } + } + for ( b = nBits/2 + 1; b <= nBits; b += 2 ) + { + Gen = Gia_ManHashOr( pNew, pGen[b], Gia_ManHashAnd(pNew, pPro[b], pGen[b-nBits/2]) ); + Pro = Gia_ManHashAnd(pNew, pPro[b], pPro[b-nBits/2]); + pPro[b] = Pro; + pGen[b] = Gen; + } + for ( b = 2; b <= nBits; b += 2 ) + { + Gen = Gia_ManHashOr( pNew, pGen[b], Gia_ManHashAnd(pNew, pPro[b], pGen[b-1]) ); + Pro = Gia_ManHashAnd(pNew, pPro[b], pPro[b-1]); + pPro[b] = Pro; + pGen[b] = Gen; + } + + for ( b = 0; b < nBits; b++ ) + pAdd0[b] = Gia_ManHashXor(pNew, pPro2[b+1], pGen[b]); + pAdd0[nBits] = pGen[nBits]; + + ABC_FREE(pGen); + ABC_FREE(pPro); + ABC_FREE(pPro2); +} +void Wlc_BlastAdderFast( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int fSign, int CarryIn ) // result is in pAdd0 +{ + int i, Log2 = Abc_Base2Log(nBits); + int * pAdd0n = ABC_CALLOC( int, (1<<Log2)+1 ); + int * pAdd1n = ABC_CALLOC( int, (1<<Log2)+1 ); + for ( i = 0; i < nBits; i++ ) + { + pAdd0n[i] = pAdd0[i]; + pAdd1n[i] = pAdd1[i]; + } + for ( ; i < (1<<Log2); i++ ) + { + pAdd0n[i] = fSign ? pAdd0[nBits-1] : 0; + pAdd1n[i] = fSign ? pAdd1[nBits-1] : 0; + } + Wlc_BlastAdderFast_int( pNew, pAdd0n, pAdd1n, Log2, CarryIn ); + for ( i = 0; i <= nBits; i++ ) + pAdd0[i] = pAdd0n[i]; + ABC_FREE(pAdd0n); + ABC_FREE(pAdd1n); +} + void Wlc_BlastMinus( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vRes ) { int * pRes = Wlc_VecCopy( vRes, pNum, nNum ); @@ -700,7 +817,7 @@ void Wlc_BlastPrintMatrix( Gia_Man_t * p, Vec_Wec_t * vProds ) Vec_IntFree( vSupp ); Vec_WrdFree( vTemp ); } -void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vLevels, Vec_Int_t * vRes ) +void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vLevels, Vec_Int_t * vRes, int fSigned, int fCla ) { Vec_Int_t * vLevel, * vProd; int i, NodeS, NodeC, LevelS, LevelC, Node1, Node2, Node3, Level1, Level2, Level3; @@ -758,9 +875,112 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL } Vec_IntPush( vRes, 0 ); Vec_IntPush( vLevel, 0 ); - Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), Vec_IntSize(vRes), 0 ); + + if ( fCla ) + Wlc_BlastAdderCLA( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), Vec_IntSize(vRes), fSigned, 0 ); + else + Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), Vec_IntSize(vRes), 0 ); +} + +int Wlc_BlastAddLevel( Gia_Man_t * pNew, int Start ) +{ + int i; + if ( Start == 0 ) + Gia_ManCleanLevels( pNew, 5 * Gia_ManObjNum(pNew) ); + for ( i = Start; i < Gia_ManObjNum(pNew); i++ ) + { + Gia_Obj_t * pObj = Gia_ManObj( pNew, i ); + if ( Gia_ObjIsAnd(pObj) ) + Gia_ObjSetAndLevel( pNew, pObj ); + } + return Gia_ManObjNum(pNew); +} +void Wlc_IntInsert2( Gia_Man_t * pNew, Vec_Int_t * vProd, int iLit ) +{ + int i, Entry, Level = Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit)); + Vec_IntForEachEntryReverse( vProd, Entry, i ) + if ( Gia_ObjLevelId(pNew, Abc_Lit2Var(Entry)) >= Level ) + break; + Vec_IntInsert( vProd, i + 1, iLit ); +// Vec_IntForEachEntry( vProd, Entry, i ) +// printf( "Obj=%d(%d) ", Abc_Lit2Var(Entry), Gia_ObjLevelId(pNew, Abc_Lit2Var(Entry)) ); +// printf( "\n" ); +} +void Wlc_IntSortCostReverse( Gia_Man_t * pNew, int * pArray, int nSize ) +{ + int i, j, best_i; + for ( i = 0; i < nSize-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nSize; j++ ) + if ( Gia_ObjLevelId(pNew, Abc_Lit2Var(pArray[j])) > Gia_ObjLevelId(pNew, Abc_Lit2Var(pArray[best_i])) ) + best_i = j; + ABC_SWAP( int, pArray[i], pArray[best_i] ); + } +} +void Wlc_BlastReduceMatrix2( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Int_t * vRes, int fSigned, int fCla ) +{ + Vec_Int_t * vProd, * vTemp; + int i, NodeS, NodeC, Node1, Node2, Node3; + int Start = Wlc_BlastAddLevel( pNew, 0 ); + int nSize = Vec_WecSize(vProds); + Vec_WecForEachLevel( vProds, vProd, i ) + Wlc_IntSortCostReverse( pNew, Vec_IntArray(vProd), Vec_IntSize(vProd) ); + for ( i = 0; i < nSize; i++ ) + { + while ( 1 ) + { + vProd = Vec_WecEntry( vProds, i ); + if ( Vec_IntSize(vProd) < 3 ) + break; + + Node1 = Vec_IntPop( vProd ); + Node2 = Vec_IntPop( vProd ); + Node3 = Vec_IntPop( vProd ); + + assert( Gia_ObjLevelId(pNew, Abc_Lit2Var(Node3)) >= Gia_ObjLevelId(pNew, Abc_Lit2Var(Node2)) ); + assert( Gia_ObjLevelId(pNew, Abc_Lit2Var(Node2)) >= Gia_ObjLevelId(pNew, Abc_Lit2Var(Node1)) ); + + Wlc_BlastFullAdder( pNew, Node1, Node2, Node3, &NodeC, &NodeS ); + Start = Wlc_BlastAddLevel( pNew, Start ); + + Wlc_IntInsert2( pNew, vProd, NodeS ); + + vProd = Vec_WecEntry( vProds, i+1 ); + Wlc_IntInsert2( pNew, vProd, NodeC ); + } + } + + // make all ranks have two products + for ( i = 0; i < nSize; i++ ) + { + vProd = Vec_WecEntry( vProds, i ); + while ( Vec_IntSize(vProd) < 2 ) + Vec_IntPush( vProd, 0 ); + assert( Vec_IntSize(vProd) == 2 ); + } +// Vec_WecPrint( vProds, 0 ); + + Vec_IntClear( vRes ); + vTemp = Vec_IntAlloc( 100 ); + for ( i = 0; i < nSize; i++ ) + { + vProd = Vec_WecEntry( vProds, i ); + Vec_IntPush( vRes, Vec_IntEntry(vProd, 0) ); + Vec_IntPush( vTemp, Vec_IntEntry(vProd, 1) ); + } + Vec_IntPush( vRes, 0 ); + Vec_IntPush( vTemp, 0 ); + + if ( fCla ) + Wlc_BlastAdderCLA( pNew, Vec_IntArray(vRes), Vec_IntArray(vTemp), Vec_IntSize(vRes), fSigned, 0 ); + else + Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vTemp), Vec_IntSize(vRes), 0 ); + Vec_IntFree( vTemp ); } -void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes ) + + +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 * vProds = Vec_WecStart( nArgA + nArgB ); Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB ); @@ -768,11 +988,21 @@ void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA for ( i = 0; i < nArgA; i++ ) for ( k = 0; k < nArgB; k++ ) { - Vec_WecPush( vProds, i+k, Gia_ManHashAnd(pNew, pArgA[i], pArgB[k]) ); + int fCompl = fSigned && ((i == nArgA-1) ^ (k == nArgB-1)); + Vec_WecPush( vProds, i+k, Abc_LitNotCond(Gia_ManHashAnd(pNew, pArgA[i], pArgB[k]), fCompl) ); Vec_WecPush( vLevels, i+k, 0 ); } + if ( fSigned ) + { + Vec_WecPush( vProds, nArgA, 1 ); + Vec_WecPush( vLevels, nArgA, 0 ); + + Vec_WecPush( vProds, nArgA+nArgB-1, 1 ); + Vec_WecPush( vLevels, nArgA+nArgB-1, 0 ); + } - Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes ); + Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes, fSigned, fCla ); +// Wlc_BlastReduceMatrix2( pNew, vProds, vRes, fSigned, fCla ); Vec_WecFree( vProds ); Vec_WecFree( vLevels ); @@ -797,12 +1027,24 @@ void Wlc_BlastSquare( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp, } } - Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes ); + Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes, 0, 0 ); Vec_WecFree( vProds ); Vec_WecFree( vLevels ); } -void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned ) +void Wlc_BlastDecoder( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp, Vec_Int_t * vRes ) +{ + int i, k, nMints = 1 << nNum; + Vec_IntClear( vRes ); + for ( i = 0; i < nMints; i++ ) + { + int iMint = 1; + for ( k = 0; k < nNum; k++ ) + iMint = Gia_ManHashAnd( pNew, iMint, Abc_LitNotCond(pNum[k], !((i >> k) & 1)) ); + 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 * vProds = Vec_WecStart( nArgA + nArgB + 3 ); Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB + 3 ); @@ -871,7 +1113,8 @@ void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int //Vec_WecPrint( vProds, 0 ); //Wlc_BlastPrintMatrix( pNew, vProds ); //printf( "Cutoff ID for partial products = %d.\n", Gia_ManObjNum(pNew) ); - Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes ); + Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes, fSigned, fCla ); +// Wlc_BlastReduceMatrix2( pNew, vProds, vRes, fSigned, fCla ); Vec_WecFree( vProds ); Vec_WecFree( vLevels ); @@ -897,13 +1140,15 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) Tim_Man_t * pManTime = NULL; If_LibBox_t * pBoxLib = NULL; Vec_Ptr_t * vTables = NULL; + Vec_Int_t * vFf2Ci = Vec_IntAlloc( 100 ); + Vec_Int_t * vRegClasses = NULL; Gia_Man_t * pTemp, * pNew, * pExtra = NULL; Wlc_Obj_t * pObj, * pObj2; Vec_Int_t * vBits = &p->vBits, * vTemp0, * vTemp1, * vTemp2, * vRes, * vAddOutputs = NULL, * vAddObjs = NULL; int nBits = Wlc_NtkPrepareBits( p ); - int nRange, nRange0, nRange1, nRange2; - int i, k, b, iFanin, iLit, nAndPrev, * pFans0, * pFans1, * pFans2; - int nFFins = 0, nFFouts = 0, curPi = 0, curPo = 0; + int nRange, nRange0, nRange1, nRange2, nRange3; + int i, k, b, iFanin, iLit, nAndPrev, * pFans0, * pFans1, * pFans2, * pFans3; + int nFFins = 0, nFFouts = 0, curPi = 0, curPo = 0, nFf2Regs = 0; int nBitCis = 0, nBitCos = 0, fAdded = 0; Wlc_BstPar_t Par, * pPar = &Par; Wlc_BstParDefault( pPar ); @@ -930,6 +1175,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) if ( pPar->vBoxIds ) { int nNewCis = 0, nNewCos = 0; + assert( Vec_IntSize(&p->vFfs2) == 0 ); Wlc_NtkForEachObj( p, pObj, i ) pObj->Mark = 0; // count bit-width of regular CIs/COs @@ -961,6 +1207,61 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) // create box library pBoxLib = If_LibBoxStart(); } + if ( Vec_IntSize(&p->vFfs2) > 0 ) + { + Vec_Int_t * vSignature; + int nNewCis = 0, nNewCos = 0; + assert( pPar->vBoxIds == 0 ); + // count bit-width of regular CIs/COs + Wlc_NtkForEachCi( p, pObj, i ) + nBitCis += Wlc_ObjRange( pObj ); + Wlc_NtkForEachCo( p, pObj, i ) + nBitCos += Wlc_ObjRange( pObj ); + // count bit-width of additional CIs/COs due to selected multipliers + Wlc_NtkForEachFf2( p, pObj, i ) + { + // currently works only for multipliers + assert( pObj->Type == WLC_OBJ_FF ); + assert( Wlc_ObjRange(pObj) == Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); + nNewCis += Wlc_ObjRange(pObj); + nNewCos += 2*Wlc_ObjRange(pObj) + 3; + nFf2Regs+= Wlc_ObjRange(pObj); + } + // create hierarchy manager + pManTime = Tim_ManStart( nBitCis + nNewCis + nFf2Regs, nBitCos + nNewCos + nFf2Regs ); + curPi = nBitCis + nFf2Regs; + curPo = 0; + // create AIG manager for logic of the boxes + pExtra = Gia_ManStart( Wlc_NtkObjNum(p) ); + Gia_ManHashAlloc( pExtra ); + assert( !pPar->fGiaSimple ); + // create register classes + vRegClasses = Vec_IntAlloc(0); + vSignature = Vec_IntAlloc( 100 ); + Vec_IntPushTwo( vSignature, -1, -1 ); + Wlc_NtkForEachFf2( p, pObj, i ) + { + int iClk0, iClk = Wlc_ObjFaninId( pObj, 1 ); + int iAsyn0, iAsyn = Wlc_ObjFaninId( pObj, 5 ); + nRange = Wlc_ObjRange(pObj); + Vec_IntForEachEntryDouble( vSignature, iClk0, iAsyn0, k ) + if ( iClk == iClk0 && iAsyn == iAsyn0 ) + { + for ( b = 0; b < nRange; b++ ) + Vec_IntPush( vRegClasses, k/2 ); + break; + } + if ( k < Vec_IntSize(vSignature) ) + continue; + for ( b = 0; b < nRange; b++ ) + Vec_IntPush( vRegClasses, k/2 ); + Vec_IntPushTwo( vSignature, iClk, iAsyn ); + } + assert( Vec_IntSize(vRegClasses) == nFf2Regs ); + Vec_IntFree( vSignature ); + // create box library + pBoxLib = If_LibBoxStart(); + } // blast in the topological order Wlc_NtkForEachObj( p, pObj, i ) { @@ -972,9 +1273,11 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) nRange0 = Wlc_ObjFaninNum(pObj) > 0 ? Wlc_ObjRange( Wlc_ObjFanin0(p, pObj) ) : -1; nRange1 = Wlc_ObjFaninNum(pObj) > 1 ? Wlc_ObjRange( Wlc_ObjFanin1(p, pObj) ) : -1; nRange2 = Wlc_ObjFaninNum(pObj) > 2 ? Wlc_ObjRange( Wlc_ObjFanin2(p, pObj) ) : -1; - pFans0 = Wlc_ObjFaninNum(pObj) > 0 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId0(pObj)) ) : NULL; - pFans1 = Wlc_ObjFaninNum(pObj) > 1 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId1(pObj)) ) : NULL; - pFans2 = Wlc_ObjFaninNum(pObj) > 2 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId2(pObj)) ) : NULL; + nRange3 = Wlc_ObjFaninNum(pObj) > 3 ? Wlc_ObjRange( Wlc_ObjFanin(p, pObj, 3) ) : -1; + pFans0 = pObj->Type != WLC_OBJ_FF && Wlc_ObjFaninNum(pObj) > 0 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId0(pObj)) ) : NULL; + pFans1 = pObj->Type != WLC_OBJ_FF && Wlc_ObjFaninNum(pObj) > 1 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId1(pObj)) ) : NULL; + pFans2 = pObj->Type != WLC_OBJ_FF && Wlc_ObjFaninNum(pObj) > 2 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId2(pObj)) ) : NULL; + pFans3 = pObj->Type != WLC_OBJ_FF && Wlc_ObjFaninNum(pObj) > 3 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId(pObj,3)) ) : NULL; Vec_IntClear( vRes ); assert( nRange > 0 ); if ( pPar->vBoxIds && pObj->Mark ) @@ -1043,7 +1346,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) if ( pObj->Type == WLC_OBJ_ARI_ADD ) Wlc_BlastAdder( pExtra, pArg0, pArg1, nRange, CarryIn ); // result is in pFan0 (vRes) else - Wlc_BlastSubtract( pExtra, pArg0, pArg1, nRange ); // result is in pFan0 (vRes) + Wlc_BlastSubtract( pExtra, pArg0, pArg1, nRange, 1 ); // result is in pFan0 (vRes) Vec_IntShrink( vRes, nRange ); } else if ( fUseOldMultiplierBlasting ) @@ -1078,13 +1381,15 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) // add box to the library sprintf( Buffer, "%s%03d", pObj->Type == WLC_OBJ_ARI_ADD ? "add":"mul", 1+If_LibBoxNum(pBoxLib) ); - pBox = If_BoxStart( Abc_UtilStrsav(Buffer), 1+If_LibBoxNum(pBoxLib), nRange, nRange0 + nRange1 + nRange2, 0, 0, 0 ); + pBox = If_BoxStart( Abc_UtilStrsav(Buffer), 1+If_LibBoxNum(pBoxLib), nRange0 + nRange1 + nRange2, nRange, 0, 0, 0 ); If_LibBoxAdd( pBoxLib, pBox ); for ( k = 0; k < pBox->nPis * pBox->nPos; k++ ) pBox->pDelays[k] = 1; } - else if ( Wlc_ObjIsCi(pObj) ) + else if ( Wlc_ObjIsCi(pObj) || pObj->Type == WLC_OBJ_FF ) // assuming that FFs are ordered immediately after PIs { + if ( pObj->Type == WLC_OBJ_FF ) + Vec_IntPush( vFf2Ci, Gia_ManCiNum(pNew) ); if ( Wlc_ObjRangeIsReversed(pObj) ) { for ( k = 0; k < nRange; k++ ) @@ -1099,6 +1404,10 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) } if ( pObj->Type == WLC_OBJ_FO ) nFFouts += Vec_IntSize(vRes); + if ( pObj->Type == WLC_OBJ_FF ) + { + // complement flop output whose init state is 1 + } } else if ( pObj->Type == WLC_OBJ_BUF ) { @@ -1391,12 +1700,31 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); int CarryIn = Wlc_ObjFaninNum(pObj) == 3 ? pFans2[0] : 0; if ( pObj->Type == WLC_OBJ_ARI_ADD ) - Wlc_BlastAdder( pNew, pArg0, pArg1, nRange, CarryIn ); // result is in pFan0 (vRes) -// Wlc_BlastAdderCLA( pNew, pArg0, pArg1, nRange ); // result is in pFan0 (vRes) + { + if ( pPar->fCla ) + Wlc_BlastAdderCLA( pNew, pArg0, pArg1, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj), CarryIn ); // result is in pFan0 (vRes) + //Wlc_BlastAdderFast( pNew, pArg0, pArg1, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj), CarryIn ); // result is in pFan0 (vRes) + else + Wlc_BlastAdder( pNew, pArg0, pArg1, nRangeMax, CarryIn ); // result is in pFan0 (vRes) + } else - Wlc_BlastSubtract( pNew, pArg0, pArg1, nRange ); // result is in pFan0 (vRes) + Wlc_BlastSubtract( pNew, pArg0, pArg1, nRange, 1 ); // result is in pFan0 (vRes) Vec_IntShrink( vRes, nRange ); } + else if ( pObj->Type == WLC_OBJ_ARI_ADDSUB ) + { + int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange2, nRange3) ); + int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans2, nRange2, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); + int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans2, nRange2, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); + int * pArg2 = Wlc_VecLoadFanins( vTemp2, pFans3, nRange3, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); + int ModeIn = pFans0[0]; + int CarryIn = pFans1[0]; int j; + Wlc_BlastAdder ( pNew, pArg0, pArg2, nRangeMax, CarryIn ); // result is in pArg0 (vTemp0) + Wlc_BlastSubtract( pNew, pArg1, pArg2, nRangeMax, Abc_LitNot(CarryIn) ); // result is in pArg1 (vTemp1) + Vec_IntClear( vRes ); + for ( j = 0; j < nRange; j++ ) + Vec_IntPush( vRes, Gia_ManHashMux(pNew, ModeIn, pArg0[j], pArg1[j]) ); + } else if ( pObj->Type == WLC_OBJ_ARI_MULTI ) { if ( fUseOldMultiplierBlasting ) @@ -1416,10 +1744,11 @@ 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 ); + Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned, pPar->fCla ); + else if ( pPar->fCla ) + Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes, Wlc_ObjIsSignedFanin01(p, pObj), pPar->fCla ); else Wlc_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned ); - //Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes ); if ( nRange > Vec_IntSize(vRes) ) Vec_IntFillExtra( vRes, nRange, fSigned ? Vec_IntEntryLast(vRes) : 0 ); else @@ -1475,6 +1804,15 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) else Vec_IntShrink( vRes, nRange ); } + else if ( pObj->Type == WLC_OBJ_DEC ) + { + int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRange0, 0 ); + Wlc_BlastDecoder( pNew, pArg0, nRange0, vTemp2, vRes ); + if ( nRange > Vec_IntSize(vRes) ) + Vec_IntFillExtra( vRes, nRange, 0 ); + else + Vec_IntShrink( vRes, nRange ); + } else if ( pObj->Type == WLC_OBJ_TABLE ) Wlc_BlastTable( pNew, Wlc_ObjTable(p, pObj), pFans0, nRange0, nRange, vRes ); else assert( 0 ); @@ -1499,6 +1837,102 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) Vec_IntFree( vTemp1 ); Vec_IntFree( vTemp2 ); Vec_IntFree( vRes ); + // create flop boxes + Wlc_NtkForEachFf2( p, pObj, i ) + { + If_Box_t * pBox; + char Buffer[100]; + float * pTable; + Vec_Int_t * vTemp0 = Vec_IntAlloc( 100 ); + Vec_Int_t * vTemp1 = Vec_IntAlloc( 100 ); + int iLit, nRange = Wlc_ObjRange(pObj); + int * pFans0, * pFans1, * pFans2, * pFans3; + int iReset, iSet, iEnable; + int nRangeIn = 2*nRange + 3; // D, reset, set, enable, Q + int iSre = Wlc_ObjFaninId(pObj, 6); + + assert( pObj->Type == WLC_OBJ_FF ); + + // create new box + if ( vTables == NULL ) + Tim_ManSetDelayTables( pManTime, (vTables = Vec_PtrAlloc(100)) ); + Tim_ManCreateBox( pManTime, curPo, nRangeIn, curPi, nRange, Vec_PtrSize(vTables), 0 ); + curPi += nRange; + curPo += nRangeIn; + + // create delay table + pTable = ABC_ALLOC( float, 3 + nRange * nRangeIn ); + pTable[0] = Vec_PtrSize(vTables); + pTable[1] = nRangeIn; + pTable[2] = nRange; + for ( k = 0; k < nRange * nRangeIn; k++ ) + pTable[3 + k] = 1.0; + Vec_PtrPush( vTables, pTable ); + + // create combinational outputs in the normal manager + pFans0 = Wlc_ObjFaninNum(pObj) > 0 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId0(pObj)) ) : NULL; + pFans1 = Wlc_ObjFaninNum(pObj) > 1 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId1(pObj)) ) : NULL; + pFans2 = Wlc_ObjFaninNum(pObj) > 2 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId2(pObj)) ) : NULL; + pFans3 = Wlc_ObjFaninNum(pObj) > 3 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId(pObj,3)) ) : NULL; + for ( k = 0; k < nRange; k++ ) + Gia_ManAppendCo( pNew, pFans0[k] ); + Gia_ManAppendCo( pNew, pFans1[0] ); + Gia_ManAppendCo( pNew, pFans2[0] ); + Gia_ManAppendCo( pNew, pFans3[0] ); + for ( k = 0; k < nRange; k++ ) + Gia_ManAppendCo( pNew, Gia_Obj2Lit(pNew, Gia_ManCi(pNew, Vec_IntEntry(vFf2Ci, i)+k)) ); + + // make sure there is enough primary inputs in the manager + for ( k = Gia_ManPiNum(pExtra); k < nRangeIn; k++ ) + Gia_ManAppendCi( pExtra ); + // create combinational inputs + for ( k = 0; k < nRange; k++ ) + Vec_IntPush( vTemp0, Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, k)) ); + iReset = Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, nRange+0)); + iSet = Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, nRange+1)); + iEnable = Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, nRange+2)); + for ( k = 0; k < nRange; k++ ) + Vec_IntPush( vTemp1, Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, nRangeIn-nRange+k)) ); + + // bit-blast in the external manager + for ( k = 0; k < nRange; k++ ) + { + // enable + //iLitFlop = Gia_LitNotCond( Gia_ObjCopy(pObj), Gia_FlopIsOne(pObj) ); + //iLit = Gia_ManHashMux( Gia_ObjGia(pObj), Gia_FlopEnableCopy(pObj), iLit, iLitFlop ); + iLit = Gia_ManHashMux( pExtra, iEnable, Vec_IntEntry(vTemp0, k), Vec_IntEntry(vTemp1, k) ); + if ( iSre ) + { + // reset + //iLit = Gia_ManHashAnd( Gia_ObjGia(pObj), iLit, Gia_LitNot(Gia_FlopResetCopy(pObj)) ); + iLit = Gia_ManHashAnd( pExtra, iLit, Abc_LitNot(iReset) ); + // set + //iLit = Gia_ManHashOr( Gia_ObjGia(pObj), iLit, Gia_FlopSetCopy(pObj) ); + iLit = Gia_ManHashOr( pExtra, iLit, iSet ); + } + else + { + // set + //iLit = Gia_ManHashOr( Gia_ObjGia(pObj), iLit, Gia_FlopSetCopy(pObj) ); + iLit = Gia_ManHashOr( pExtra, iLit, iSet ); + // reset + //iLit = Gia_ManHashAnd( Gia_ObjGia(pObj), iLit, Gia_LitNot(Gia_FlopResetCopy(pObj)) ); + iLit = Gia_ManHashAnd( pExtra, iLit, Abc_LitNot(iReset) ); + } + // create outputs in the external manager + Gia_ManAppendCo( pExtra, iLit ); + } + + // add box to the library + sprintf( Buffer, "%s%03d", "ff_comb", 1+If_LibBoxNum(pBoxLib) ); + pBox = If_BoxStart( Abc_UtilStrsav(Buffer), 1+If_LibBoxNum(pBoxLib), nRangeIn, nRange, 0, 0, 0 ); + If_LibBoxAdd( pBoxLib, pBox ); + for ( k = 0; k < pBox->nPis * pBox->nPos; k++ ) + pBox->pDelays[k] = 1; + Vec_IntFree( vTemp0 ); + Vec_IntFree( vTemp1 ); + } + Vec_IntFree( vFf2Ci ); // create COs if ( pPar->fCreateMiter ) { @@ -1588,8 +2022,19 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) //Vec_IntErase( vBits ); //Vec_IntErase( &p->vCopies ); // set the number of registers - assert( nFFins == nFFouts ); - Gia_ManSetRegNum( pNew, nFFins ); + if ( Vec_IntSize(&p->vFfs2) > 0 ) + { + assert( nFFins == 0 && nFFouts == 0 ); + // complement flop inputs whose init state is 1 + for ( i = 0; i < nFf2Regs; i++ ) + Gia_ManAppendCo( pNew, Gia_ManAppendCi(pNew) ); + //Gia_ManSetRegNum( pNew, nFf2Regs ); + } + else + { + assert( nFFins == nFFouts ); + Gia_ManSetRegNum( pNew, nFFins ); + } // finalize AIG if ( !pPar->fGiaSimple && !pPar->fNoCleanup ) { @@ -1614,6 +2059,24 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) } } // finalize AIG with boxes + if ( Vec_IntSize(&p->vFfs2) > 0 ) + { + curPo += nBitCos + nFf2Regs; + assert( curPi == Tim_ManCiNum(pManTime) ); + assert( curPo == Tim_ManCoNum(pManTime) ); + // finalize the extra AIG + pExtra = Gia_ManCleanup( pTemp = pExtra ); + Gia_ManStop( pTemp ); + assert( Gia_ManPoNum(pExtra) == Gia_ManCiNum(pNew) - nBitCis - nFf2Regs ); + // attach + pNew->pAigExtra = pExtra; + pNew->pManTime = pManTime; + // normalize AIG + pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); + Gia_ManTransferTiming( pNew, pTemp ); + Gia_ManStop( pTemp ); + //Tim_ManPrint( pManTime ); + } if ( pPar->vBoxIds ) { curPo += nBitCos; @@ -1622,7 +2085,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) // finalize the extra AIG pExtra = Gia_ManCleanup( pTemp = pExtra ); Gia_ManStop( pTemp ); - assert( Gia_ManPoNum(pExtra) == Gia_ManCiNum(pNew) - nBitCis ); + assert( Gia_ManPoNum(pExtra) == Gia_ManCiNum(pNew) - nBitCis - nFf2Regs ); // attach pNew->pAigExtra = pExtra; pNew->pManTime = pManTime; @@ -1676,6 +2139,38 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) ); } } + Wlc_NtkForEachFf2( p, pObj, i ) + { + char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); + nRange = Wlc_ObjRange( pObj ); + if ( fSkipBitRange && nRange == 1 ) + { + char Buffer[1000]; + sprintf( Buffer, "%s_fo", pName ); + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) ); + } + else + for ( k = 0; k < nRange; k++ ) + { + char Buffer[1000]; + sprintf( Buffer, "%s_fo[%d]", pName, k ); + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) ); + } + } + Wlc_NtkForEachFf2( p, pObj, i ) + { + char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); + 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, k ); + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) ); + } + } if ( p->pInits && fAdded ) Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav("abc_reset_flop") ); if ( pPar->vBoxIds ) @@ -1696,6 +2191,43 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) assert( Vec_PtrSize(pNew->vNamesIn) == Gia_ManCiNum(pNew) ); // create output names pNew->vNamesOut = Vec_PtrAlloc( Gia_ManCoNum(pNew) ); + Wlc_NtkForEachFf2( p, pObj, i ) + { + int iFanin; + Wlc_ObjForEachFanin( pObj, iFanin, b ) + { + char * pName = Wlc_ObjName(p, iFanin); + nRange = Wlc_ObjRange( Wlc_NtkObj(p, iFanin) ); + 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, k ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } + if ( b == 3 ) + break; + } + { + char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); + nRange = Wlc_ObjRange( pObj ); + if ( fSkipBitRange && nRange == 1 ) + { + char Buffer[1000]; + sprintf( Buffer, "%s_in", pName ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } + else + for ( k = 0; k < nRange; k++ ) + { + char Buffer[1000]; + sprintf( Buffer, "%s_in[%d]", pName, k ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } + } + } if ( pPar->vBoxIds ) { Wlc_NtkForEachObjVec( pPar->vBoxIds, p, pObj, i ) @@ -1786,6 +2318,24 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); } } + Wlc_NtkForEachFf2( p, pObj, i ) + { + char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); + nRange = Wlc_ObjRange( pObj ); + if ( fSkipBitRange && nRange == 1 ) + { + char Buffer[1000]; + sprintf( Buffer, "%s_fi", pName ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } + else + for ( k = 0; k < nRange; k++ ) + { + char Buffer[1000]; + sprintf( Buffer, "%s_fi[%d]", pName, k ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } + } assert( Vec_PtrSize(pNew->vNamesOut) == Gia_ManCoNum(pNew) ); // replace the current library @@ -1815,11 +2365,14 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) ABC_FREE( pNameGeneric ); printf( "Dumped two parts of the miter into files \"%s\" and \"%s\".\n", pFileName0, pFileName1 ); } + //Wlc_NtkPrintNameArray( pNew->vNamesIn ); + //Wlc_NtkPrintNameArray( pNew->vNamesOut ); if ( pPar->vBoxIds ) { - Vec_PtrFreeP( &pNew->vNamesIn ); - Vec_PtrFreeP( &pNew->vNamesOut ); + Vec_PtrFreeFree( pNew->vNamesIn ); pNew->vNamesIn = NULL; + Vec_PtrFreeFree( pNew->vNamesOut ); pNew->vNamesOut = NULL; } + pNew->vRegClasses = vRegClasses; return pNew; } diff --git a/src/base/wlc/wlcCom.c b/src/base/wlc/wlcCom.c index 711763c7..5b99cb00 100644 --- a/src/base/wlc/wlcCom.c +++ b/src/base/wlc/wlcCom.c @@ -38,7 +38,9 @@ static int Abc_CommandPdrAbs ( Abc_Frame_t * pAbc, int argc, char ** argv ) static int Abc_CommandAbs2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMemAbs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBlast ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBlastMem ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandGraft ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandProfile ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandShow ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -82,7 +84,9 @@ void Wlc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Word level", "%abs2", Abc_CommandAbs2, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%memabs", Abc_CommandMemAbs, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%blast", Abc_CommandBlast, 0 ); + Cmd_CommandAdd( pAbc, "Word level", "%blastmem", Abc_CommandBlastMem, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%graft", Abc_CommandGraft, 0 ); + Cmd_CommandAdd( pAbc, "Word level", "%retime", Abc_CommandRetime, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%profile", Abc_CommandProfile, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%short_names", Abc_CommandShortNames, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%show", Abc_CommandShow, 0 ); @@ -967,12 +971,12 @@ usage: int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) { Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); - Gia_Man_t * pNew = NULL; int c; + Gia_Man_t * pNew = NULL; int c, fMiter = 0, fDumpNames = 0; Wlc_BstPar_t Par, * pPar = &Par; Wlc_BstParDefault( pPar ); pPar->nOutputRange = 2; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ORAMcombdsvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ORAMcombadstnvh" ) ) != EOF ) { switch ( c ) { @@ -1032,12 +1036,22 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'b': pPar->fBooth ^= 1; break; + case 'a': + pPar->fCla ^= 1; + break; case 'd': pPar->fCreateMiter ^= 1; break; case 's': pPar->fDecMuxes ^= 1; break; + case 't': + pPar->fCreateMiter ^= 1; + fMiter ^= 1; + break; + case 'n': + fDumpNames ^= 1; + break; case 'v': pPar->fVerbose ^= 1; break; @@ -1080,10 +1094,31 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 1, "Abc_CommandBlast(): Bit-blasting has failed.\n" ); return 0; } + // generate miter + if ( fMiter ) + { + Gia_Man_t * pTemp = pNew; + pNew = Gia_ManTransformMiter( pNew ); + Gia_ManStop( pTemp ); + Abc_Print( 1, "Bit-blasting created a traditional multi-output miter by XORing POs pair-wise.\n" ); + if ( fDumpNames ) + { + int i; char * pName; + FILE * pFile = fopen( "pio_name_map.txt", "wb" ); + if ( pNew->vNamesIn ) + Vec_PtrForEachEntry( char *, pNew->vNamesIn, pName, i ) + fprintf( pFile, "i%d %s\n", i, pName ); + if ( pNew->vNamesOut ) + Vec_PtrForEachEntry( char *, pNew->vNamesOut, pName, i ) + fprintf( pFile, "o%d %s\n", i, pName ); + fclose( pFile ); + Abc_Print( 1, "Finished dumping file \"pio_name_map.txt\" containing PI/PO name mapping.\n" ); + } + } Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: - Abc_Print( -2, "usage: %%blast [-ORAM num] [-combdsvh]\n" ); + Abc_Print( -2, "usage: %%blast [-ORAM num] [-combadstnvh]\n" ); Abc_Print( -2, "\t performs bit-blasting of the word-level design\n" ); Abc_Print( -2, "\t-O num : zero-based index of the first word-level PO to bit-blast [default = %d]\n", pPar->iOutput ); Abc_Print( -2, "\t-R num : the total number of word-level POs to bit-blast [default = %d]\n", pPar->nOutputRange ); @@ -1093,8 +1128,11 @@ usage: Abc_Print( -2, "\t-o : toggle using additional POs on the word-level boundaries [default = %s]\n", pPar->fAddOutputs? "yes": "no" ); Abc_Print( -2, "\t-m : toggle creating boxes for all multipliers in the design [default = %s]\n", pPar->fMulti? "yes": "no" ); Abc_Print( -2, "\t-b : toggle generating radix-4 Booth multipliers [default = %s]\n", pPar->fBooth? "yes": "no" ); - Abc_Print( -2, "\t-d : toggle creating dual-output miter [default = %s]\n", pPar->fCreateMiter? "yes": "no" ); + Abc_Print( -2, "\t-a : toggle generating carry-look-ahead adder [default = %s]\n", pPar->fCla? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle creating dual-output multi-output miter [default = %s]\n", pPar->fCreateMiter? "yes": "no" ); Abc_Print( -2, "\t-s : toggle creating decoded MUXes [default = %s]\n", pPar->fDecMuxes? "yes": "no" ); + Abc_Print( -2, "\t-t : toggle creating regular multi-output miter [default = %s]\n", fMiter? "yes": "no" ); + Abc_Print( -2, "\t-n : toggle dumping signal names into a text file [default = %s]\n", fDumpNames? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPar->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -1111,6 +1149,52 @@ usage: SeeAlso [] ******************************************************************************/ +int Abc_CommandBlastMem( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Wlc_Ntk_t * Wlc_NtkMemBlast( Wlc_Ntk_t * p ); + Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); + 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; + } + } + if ( pNtk == NULL ) + { + Abc_Print( 1, "Abc_CommandBlastMem(): There is no current design.\n" ); + return 0; + } + pNtk = Wlc_NtkMemBlast( pNtk ); + Wlc_AbcUpdateNtk( pAbc, pNtk ); + return 0; +usage: + Abc_Print( -2, "usage: %%blastmem [-vh]\n" ); + Abc_Print( -2, "\t performs blasting of memory read/write ports\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"); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ int Abc_CommandGraft( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Wlc_Ntk_t * Wlc_NtkGraftMulti( Wlc_Ntk_t * p, int fVerbose ); @@ -1157,6 +1241,63 @@ usage: SeeAlso [] ******************************************************************************/ +int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Wln_NtkRetimeTest( char * pFileName ); + FILE * pFile; + char * pFileName = NULL; + 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; + } + } + if ( argc != globalUtilOptind + 1 ) + { + printf( "Abc_CommandRetime(): Input file name should be given on the command line.\n" ); + return 0; + } + // get the file name + pFileName = argv[globalUtilOptind]; + if ( (pFile = fopen( pFileName, "r" )) == NULL ) + { + Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName ); + if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".ndr", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", pFileName ); + Abc_Print( 1, "\n" ); + return 0; + } + fclose( pFile ); + Wln_NtkRetimeTest( pFileName ); + return 0; +usage: + Abc_Print( -2, "usage: %%retime [-vh]\n" ); + Abc_Print( -2, "\t performs retiming for the NDR design\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"); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ int Abc_CommandProfile( Abc_Frame_t * pAbc, int argc, char ** argv ) { Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); @@ -1672,7 +1813,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) //Wlc_NtkSimulateTest( (Wlc_Ntk_t *)pAbc->pAbcWlc ); //pNtk = Wlc_NtkDupSingleNodes( pNtk ); //Wlc_AbcUpdateNtk( pAbc, pNtk ); - Ndr_ModuleTestSelSel(); + //Wln_ReadNdrTest(); //pNtk = Wlc_NtkMemAbstractTest( pNtk ); //Wlc_AbcUpdateNtk( pAbc, pNtk ); return 0; diff --git a/src/base/wlc/wlcMem.c b/src/base/wlc/wlcMem.c index b310afb6..ccc319e5 100644 --- a/src/base/wlc/wlcMem.c +++ b/src/base/wlc/wlcMem.c @@ -35,6 +35,133 @@ ABC_NAMESPACE_IMPL_START /**Function************************************************************* + Synopsis [Memory blasting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wlc_NtkMemBlast_rec( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p, int iObj, Vec_Int_t * vFanins ) +{ + Wlc_Obj_t * pObj; + int i, iFanin; + if ( Wlc_ObjCopy(p, iObj) ) + return; + pObj = Wlc_NtkObj( p, iObj ); + Wlc_ObjForEachFanin( pObj, iFanin, i ) + Wlc_NtkMemBlast_rec( pNew, p, iFanin, vFanins ); + if ( pObj->Type == WLC_OBJ_WRITE ) + { + Vec_Int_t * vTemp = Vec_IntAlloc( 1 ); + Vec_Int_t * vBits = Vec_IntAlloc( 100 ); + Wlc_Obj_t * pMem = Wlc_ObjFanin0(p, pObj); + Wlc_Obj_t * pAddr = Wlc_ObjFanin1(p, pObj); + Wlc_Obj_t * pData = Wlc_ObjFanin2(p, pObj); + int DataW = Wlc_ObjRange(pData); + int AddrW = Wlc_ObjRange(pAddr); + int nRegs = 1 << AddrW, iObjNew, iObjDec; + assert( nRegs * DataW == Wlc_ObjRange(pMem) ); + assert( Wlc_ObjRange(pObj) == Wlc_ObjRange(pMem) ); + // create decoder + iObjDec = Wlc_ObjAlloc( pNew, WLC_OBJ_DEC, 0, nRegs-1, 0 ); + Vec_IntFill( vTemp, 1, Wlc_ObjCopy(p, Wlc_ObjId(p, pAddr)) ); + Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObjDec), vTemp ); + // create decoder bits + for ( i = 0; i < nRegs; i++ ) + { + int iObj2 = Wlc_ObjAlloc( pNew, WLC_OBJ_BIT_SELECT, 0, i, i ); + Vec_IntFill( vTemp, 1, iObjDec ); + Vec_IntPushTwo( vTemp, i, i ); + Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObj2), vTemp ); + Vec_IntPush( vBits, iObj2 ); + } + // create data words + Vec_IntClear( vFanins ); + for ( i = 0; i < nRegs; i++ ) + { + int iObj2 = Wlc_ObjAlloc( pNew, WLC_OBJ_BIT_SELECT, 0, i*DataW+DataW-1, i*DataW ); + Vec_IntFill( vTemp, 1, Wlc_ObjCopy(p, Wlc_ObjId(p, pMem)) ); + Vec_IntPushTwo( vTemp, i*DataW+DataW-1, i*DataW ); + Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObj2), vTemp ); + Vec_IntPush( vFanins, iObj2 ); + } + // create MUXes of data words controlled by decoder bits + for ( i = 0; i < nRegs; i++ ) + { + int iObj2 = Wlc_ObjAlloc( pNew, WLC_OBJ_MUX, 0, DataW-1, 0 ); + Vec_IntFill( vTemp, 1, Vec_IntEntry(vBits, i) ); + Vec_IntPushTwo( vTemp, Wlc_ObjCopy(p, Wlc_ObjId(p, pData)), Vec_IntEntry(vFanins, i) ); + Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObj2), vTemp ); + Vec_IntWriteEntry( vFanins, i, iObj2 ); + } + // concatenate the results + iObjNew = Wlc_ObjAlloc( pNew, WLC_OBJ_BIT_CONCAT, 0, nRegs*DataW-1, 0 ); + Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObjNew), vFanins ); + Wlc_ObjSetCopy( p, iObj, iObjNew ); + Vec_IntFree( vTemp ); + Vec_IntFree( vBits ); + } + else if ( pObj->Type == WLC_OBJ_READ ) + { + Vec_Int_t * vTemp = Vec_IntAlloc( 1 ); + Wlc_Obj_t * pMem = Wlc_ObjFanin0(p, pObj); + Wlc_Obj_t * pAddr = Wlc_ObjFanin1(p, pObj); + int DataW = Wlc_ObjRange(pObj); + int AddrW = Wlc_ObjRange(pAddr); + int nRegs = 1 << AddrW, iObjNew; + assert( nRegs * DataW == Wlc_ObjRange(pMem) ); + Vec_IntClear( vFanins ); + Vec_IntPush( vFanins, Wlc_ObjCopy(p, Wlc_ObjId(p, pAddr)) ); + for ( i = 0; i < nRegs; i++ ) + { + int iObj2 = Wlc_ObjAlloc( pNew, WLC_OBJ_BIT_SELECT, 0, i*DataW+DataW-1, i*DataW ); + Vec_IntFill( vTemp, 1, Wlc_ObjCopy(p, Wlc_ObjId(p, pMem)) ); + Vec_IntPushTwo( vTemp, i*DataW+DataW-1, i*DataW ); + Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObj2), vTemp ); + Vec_IntPush( vFanins, iObj2 ); + } + iObjNew = Wlc_ObjAlloc( pNew, WLC_OBJ_MUX, 0, DataW-1, 0 ); + Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObjNew), vFanins ); + Wlc_ObjSetCopy( p, iObj, iObjNew ); + Vec_IntFree( vTemp ); + } + else + Wlc_ObjDup( pNew, p, iObj, vFanins ); +} +Wlc_Ntk_t * Wlc_NtkMemBlast( Wlc_Ntk_t * p ) +{ + Wlc_Ntk_t * pNew; + Wlc_Obj_t * pObj; + Vec_Int_t * vFanins; + int i; + Wlc_NtkCleanCopy( p ); + vFanins = Vec_IntAlloc( 100 ); + pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc ); + pNew->fSmtLib = p->fSmtLib; + pNew->fMemPorts = p->fMemPorts; + pNew->fEasyFfs = p->fEasyFfs; + Wlc_NtkForEachCi( p, pObj, i ) + Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins ); + Wlc_NtkForEachCo( p, pObj, i ) + Wlc_NtkMemBlast_rec( pNew, p, Wlc_ObjId(p, pObj), vFanins ); + Wlc_NtkForEachCo( p, pObj, i ) + Wlc_ObjSetCo( pNew, Wlc_ObjCopyObj(pNew, p, pObj), pObj->fIsFi ); + if ( p->vInits ) + pNew->vInits = Vec_IntDup( p->vInits ); + if ( p->pInits ) + pNew->pInits = Abc_UtilStrsav( p->pInits ); + Vec_IntFree( vFanins ); + if ( p->pSpec ) + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + return pNew; +} + + +/**Function************************************************************* + Synopsis [Collect memory nodes.] Description [] @@ -827,7 +954,7 @@ int Wlc_NtkMemAbstract( Wlc_Ntk_t * p, int nIterMax, int fDumpAbs, int fPdrVerbo Vec_Wec_t * vRefines = Vec_WecAlloc( 100 ); Vec_Int_t * vNodeFrames = Vec_IntAlloc( 100 ); Vec_Int_t * vMemObjs, * vMemFanins, * vFirstTotal, * vRefine; - int RetValue, iFirstMemPi, iFirstCi, iFirstMemCi, nDcBits, nIters; + int RetValue = -1, iFirstMemPi, iFirstCi, iFirstMemCi, nDcBits, nIters; vMemObjs = Wlc_NtkCollectMemory( p ); vMemFanins = Wlc_NtkCollectMemFanins( p, vMemObjs ); diff --git a/src/base/wlc/wlcNdr.c b/src/base/wlc/wlcNdr.c index 3e6600c3..16c7d778 100644 --- a/src/base/wlc/wlcNdr.c +++ b/src/base/wlc/wlcNdr.c @@ -71,6 +71,7 @@ int Ndr_TypeNdr2Wlc( int Type ) if ( Type == ABC_OPER_LOGIC_XOR ) return WLC_OBJ_LOGIC_XOR; // 30: logic XOR if ( Type == ABC_OPER_SEL_NMUX ) return WLC_OBJ_MUX; // 08: multiplexer if ( Type == ABC_OPER_SEL_SEL ) return WLC_OBJ_SEL; // 57: selector + if ( Type == ABC_OPER_SEL_DEC ) return WLC_OBJ_DEC; // 58: decoder if ( Type == ABC_OPER_COMP_EQU ) return WLC_OBJ_COMP_EQU; // 31: compare equal if ( Type == ABC_OPER_COMP_NOTEQU ) return WLC_OBJ_COMP_NOTEQU; // 32: compare not equal if ( Type == ABC_OPER_COMP_LESS ) return WLC_OBJ_COMP_LESS; // 33: compare less @@ -129,6 +130,7 @@ int Ndr_TypeWlc2Ndr( int Type ) if ( Type == WLC_OBJ_LOGIC_OR ) return ABC_OPER_LOGIC_OR; // 29: logic OR if ( Type == WLC_OBJ_LOGIC_XOR ) return ABC_OPER_LOGIC_XOR; // 30: logic XOR if ( Type == WLC_OBJ_SEL ) return ABC_OPER_SEL_SEL; // 57: selector + if ( Type == WLC_OBJ_DEC ) return ABC_OPER_SEL_DEC; // 58: decoder if ( Type == WLC_OBJ_COMP_EQU ) return ABC_OPER_COMP_EQU; // 31: compare equal if ( Type == WLC_OBJ_COMP_NOTEQU ) return ABC_OPER_COMP_NOTEQU; // 32: compare not equal if ( Type == WLC_OBJ_COMP_LESS ) return ABC_OPER_COMP_LESS; // 33: compare less @@ -342,9 +344,10 @@ void Wlc_NtkCheckIntegrity( void * pData ) } Ndr_ModForEachObj( p, Mod, Obj ) { + int Type = Ndr_ObjReadBody( p, Obj, NDR_OPERTYPE ); int i, * pArray, nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); for ( i = 0; i < nArray; i++ ) - if ( Vec_IntGetEntry(vMap, pArray[i]) == 0 ) + if ( Vec_IntGetEntry(vMap, pArray[i]) == 0 && !(Type == ABC_OPER_DFFRSE && (i >= 5 || i <= 7)) ) printf( "Input name %d appearing as fanin %d of obj %d is not used as output name in any object.\n", pArray[i], i, Obj ); } Vec_IntFree( vMap ); @@ -396,6 +399,8 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) Vec_IntPush( &pNtk->vFfs, Vec_IntEntry(vFanins, 0) ); continue; } + if ( Type == ABC_OPER_DFFRSE ) + Vec_IntPush( &pNtk->vFfs2, iObj ); if ( Type == ABC_OPER_SLICE ) Vec_IntPushTwo( vFanins, End, Beg ); else if ( Type == ABC_OPER_CONST ) @@ -467,6 +472,7 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) assert( !fFound && i == NameId ); } //Ndr_NtkPrintNodes( pNtk ); + //Wlc_WriteVer( pNtk, "temp_ndr.v", 0, 0 ); // derive topological order pNtk = Wlc_NtkDupDfs( pTemp = pNtk, 0, 1 ); Wlc_NtkFree( pTemp ); diff --git a/src/base/wlc/wlcNtk.c b/src/base/wlc/wlcNtk.c index b8a4b9b1..4ac0c66c 100644 --- a/src/base/wlc/wlcNtk.c +++ b/src/base/wlc/wlcNtk.c @@ -87,7 +87,10 @@ static char * Wlc_Names[WLC_OBJ_NUMBER+1] = { "table", // 53: bit table "READ", // 54: mem read port "WRITE", // 55: mem write port - NULL // 56: unused + "addsub", // 56: adder/subtractor + "sel", // 57: selector + "dec", // 58: decoder + NULL // 58: unused }; char * Wlc_ObjTypeName( Wlc_Obj_t * p ) { return Wlc_Names[p->Type]; } @@ -261,6 +264,7 @@ void Wlc_NtkFree( Wlc_Ntk_t * p ) ABC_FREE( p->vCis.pArray ); ABC_FREE( p->vCos.pArray ); ABC_FREE( p->vFfs.pArray ); + ABC_FREE( p->vFfs2.pArray ); Vec_IntFreeP( &p->vInits ); ABC_FREE( p->vTravIds.pArray ); ABC_FREE( p->vNameIds.pArray ); @@ -283,6 +287,7 @@ int Wlc_NtkMemUsage( Wlc_Ntk_t * p ) Mem += 4 * p->vCis.nCap; Mem += 4 * p->vCos.nCap; Mem += 4 * p->vFfs.nCap; + Mem += 4 * p->vFfs2.nCap; Mem += sizeof(Wlc_Obj_t) * p->nObjsAlloc; Mem += Abc_NamMemUsed(p->pManName); Mem += Mem_FlexReadMemUsage(p->pMemFanin); @@ -637,6 +642,11 @@ void Wlc_NtkPrintNode( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) printf( "FO\n" ); return; } + if ( pObj->Type != WLC_OBJ_CONST && Wlc_ObjFaninNum(pObj) == 0 ) + { + printf( "Unknown object without fanins\n" ); + return; + } if ( pObj->Type != WLC_OBJ_CONST ) { printf( "%6d%s %5s ", Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Wlc_ObjIsSigned(Wlc_ObjFanin0(p, pObj)) ? "s" : " ", Wlc_Names[(int)pObj->Type] ); @@ -858,10 +868,13 @@ void Wlc_NtkDupDfs_rec( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p, int iObj, Vec_Int_t * v { Wlc_Obj_t * pObj; int i, iFanin; + if ( iObj == 0 ) + return; if ( Wlc_ObjCopy(p, iObj) ) return; //printf( "Visiting node %d\n", iObj ); pObj = Wlc_NtkObj( p, iObj ); + assert( pObj->Type != WLC_OBJ_FF ); Wlc_ObjForEachFanin( pObj, iFanin, i ) Wlc_NtkDupDfs_rec( pNew, p, iFanin, vFanins ); Wlc_ObjDup( pNew, p, iObj, vFanins ); @@ -898,9 +911,9 @@ Wlc_Ntk_t * Wlc_NtkDupDfsSimple( Wlc_Ntk_t * p ) Wlc_Ntk_t * Wlc_NtkDupDfs( Wlc_Ntk_t * p, int fMarked, int fSeq ) { Wlc_Ntk_t * pNew; - Wlc_Obj_t * pObj; + Wlc_Obj_t * pObj, * pObjNew; Vec_Int_t * vFanins; - int i; + int i, k, iObj, iFanin; vFanins = Vec_IntAlloc( 100 ); Wlc_NtkCleanCopy( p ); pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc ); @@ -915,12 +928,28 @@ Wlc_Ntk_t * Wlc_NtkDupDfs( Wlc_Ntk_t * p, int fMarked, int fSeq ) Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins ); pObj->Type = Type; } + Wlc_NtkForEachFf2( p, pObj, i ) + { + int iObjNew = Wlc_ObjAlloc( pNew, pObj->Type, Wlc_ObjIsSigned(pObj), pObj->End, pObj->Beg ); + Wlc_ObjSetCopy( p, Wlc_ObjId(p, pObj), iObjNew ); + Vec_IntPush( &pNew->vFfs2, iObjNew ); + } Wlc_NtkForEachCo( p, pObj, i ) if ( !fMarked || pObj->Mark ) Wlc_NtkDupDfs_rec( pNew, p, Wlc_ObjId(p, pObj), vFanins ); Wlc_NtkForEachCo( p, pObj, i ) if ( !fMarked || pObj->Mark ) Wlc_ObjSetCo( pNew, Wlc_ObjCopyObj(pNew, p, pObj), fSeq ? pObj->fIsFi : 0 ); + Wlc_NtkForEachFf2( p, pObj, i ) + { + iObj = Wlc_ObjId(p, pObj); + Wlc_ObjForEachFanin( pObj, iFanin, k ) + Wlc_NtkDupDfs_rec( pNew, p, iFanin, vFanins ); + Wlc_ObjCollectCopyFanins( p, iObj, vFanins ); + pObjNew = Wlc_NtkObj( pNew, Wlc_ObjCopy(p, iObj) ); + Wlc_ObjAddFanins( pNew, pObjNew, vFanins ); + pObjNew->fXConst = pObj->fXConst; + } Vec_IntFree( vFanins ); if ( fSeq ) { diff --git a/src/base/wlc/wlcReadVer.c b/src/base/wlc/wlcReadVer.c index 9974dd44..34966777 100644 --- a/src/base/wlc/wlcReadVer.c +++ b/src/base/wlc/wlcReadVer.c @@ -1277,7 +1277,7 @@ startword: } else if ( Wlc_PrsStrCmp( pStart, "ABC_DFFRSE" ) ) { - int NameId[8], fFound, nBits = 1, fFlopIn, fFlopOut, fFlopClk, fFlopRst, fFlopSet, fFlopEna, fFlopAsync, fFlopInit; + int NameId[10] = {0}, fFound, fFlopIn, fFlopClk, fFlopRst, fFlopSet, fFlopEna, fFlopAsync, fFlopSre, fFlopInit, fFlopOut; pStart += strlen("ABC_DFF"); while ( 1 ) { @@ -1286,13 +1286,14 @@ startword: break; pStart = Wlc_PrsSkipSpaces( pStart+1 ); fFlopIn = (pStart[0] == 'd'); - fFlopOut = (pStart[0] == 'q'); fFlopClk = (pStart[0] == 'c'); fFlopRst = (pStart[0] == 'r'); - fFlopSet = (pStart[0] == 's'); + fFlopSet = (pStart[0] == 's' && pStart[1] == 'e'); fFlopEna = (pStart[0] == 'e'); fFlopAsync = (pStart[0] == 'a'); + fFlopSre = (pStart[0] == 's' && pStart[1] == 'r'); fFlopInit = (pStart[0] == 'i'); + fFlopOut = (pStart[0] == 'q'); pStart = Wlc_PrsFindSymbol( pStart, '(' ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." ); @@ -1301,8 +1302,6 @@ startword: return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." ); if ( fFlopIn ) NameId[0] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); - else if ( fFlopOut ) - NameId[7] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); else if ( fFlopClk ) NameId[1] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); else if ( fFlopRst ) @@ -1313,8 +1312,12 @@ startword: NameId[4] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); else if ( fFlopAsync ) NameId[5] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); - else if ( fFlopInit ) + else if ( fFlopSre ) NameId[6] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); + else if ( fFlopInit ) + NameId[7] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); + else if ( fFlopOut ) + NameId[8] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); else assert( 0 ); if ( !fFound ) @@ -1323,7 +1326,7 @@ startword: if ( NameId[0] == -1 || NameId[7] == -1 ) return Wlc_PrsWriteErrorMessage( p, pStart, "Name of flop input or flop output is missing." ); // create output - pObj = Wlc_NtkObj( p->pNtk, NameId[7] ); + pObj = Wlc_NtkObj( p->pNtk, NameId[8] ); Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_FF ); Vec_IntClear( p->vFanins ); Vec_IntPush( p->vFanins, NameId[0] ); @@ -1333,6 +1336,7 @@ startword: Vec_IntPush( p->vFanins, NameId[4] ); Vec_IntPush( p->vFanins, NameId[5] ); Vec_IntPush( p->vFanins, NameId[6] ); + Vec_IntPush( p->vFanins, NameId[7] ); Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins ); } else if ( Wlc_PrsStrCmp( pStart, "ABC_DFF" ) ) @@ -1571,6 +1575,10 @@ Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr ) // derive topological order if ( p->pNtk ) { + Wlc_Obj_t * pObj; int i; + Wlc_NtkForEachObj( p->pNtk, pObj, i ) + if ( pObj->Type == WLC_OBJ_FF ) + Vec_IntPush( &p->pNtk->vFfs2, Wlc_ObjId(p->pNtk, pObj) ); pNtk = Wlc_NtkDupDfs( p->pNtk, 0, 1 ); pNtk->pSpec = Abc_UtilStrsav( pFileName ); } diff --git a/src/base/wlc/wlcWriteVer.c b/src/base/wlc/wlcWriteVer.c index dbf24e68..30f10e14 100644 --- a/src/base/wlc/wlcWriteVer.c +++ b/src/base/wlc/wlcWriteVer.c @@ -192,7 +192,7 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops ) continue; fprintf( pFile, " assign " ); } - else if ( (pObj->Type == WLC_OBJ_MUX && Wlc_ObjFaninNum(pObj) > 3) || pObj->Type == WLC_OBJ_FF ) + else if ( (pObj->Type == WLC_OBJ_MUX && Wlc_ObjFaninNum(pObj) > 3) || pObj->Type == WLC_OBJ_SEL ) fprintf( pFile, "reg %s ", Range ); else fprintf( pFile, "wire %s ", Range ); @@ -275,12 +275,62 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops ) fprintf( pFile, " : %s = ", Wlc_ObjName(p, i) ); fprintf( pFile, "%s ;\n", Wlc_ObjName(p, Wlc_ObjFaninId(pObj, k)) ); } + fprintf( pFile, " " ); + fprintf( pFile, "default" ); + fprintf( pFile, " : %s = ", Wlc_ObjName(p, i) ); + fprintf( pFile, "%d\'b", Wlc_ObjRange(pObj) ); + for ( j = Wlc_ObjRange(pObj)-1; j >= 0; j-- ) + fprintf( pFile, "%d", 0 ); + fprintf( pFile, " ;\n" ); fprintf( pFile, " " ); fprintf( pFile, "endcase\n" ); fprintf( pFile, " " ); fprintf( pFile, "end\n" ); continue; } + else if ( pObj->Type == WLC_OBJ_DEC ) + { + int nRange = Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)); + assert( (1 << nRange) == Wlc_ObjRange(pObj) ); + fprintf( pFile, "%s ;\n", Wlc_ObjName(p, i) ); + for ( k = 0; k < Wlc_ObjRange(pObj); k++ ) + { + fprintf( pFile, " " ); + fprintf( pFile, "wire " ); + fprintf( pFile, "%s_", Wlc_ObjName(p, i) ); + for ( j = 0; j < nRange; j++ ) + fprintf( pFile, "%d", (k >> (nRange-1-j)) & 1 ); + fprintf( pFile, " = " ); + for ( j = 0; j < nRange; j++ ) + fprintf( pFile, "%s%s%s[%d]", + j ? " & ":"", ((k >> (nRange-1-j)) & 1) ? " ":"~", + Wlc_ObjName(p, Wlc_ObjFaninId(pObj, 0)), nRange-1-j ); + fprintf( pFile, " ;\n" ); + } + fprintf( pFile, " " ); + fprintf( pFile, "assign %s = { ", Wlc_ObjName(p, i) ); + for ( k = Wlc_ObjRange(pObj)-1; k >= 0; k-- ) + { + fprintf( pFile, "%s%s_", k < Wlc_ObjRange(pObj)-1 ? ", ":"", Wlc_ObjName(p, i) ); + for ( j = 0; j < nRange; j++ ) + fprintf( pFile, "%d", (k >> (nRange-1-j)) & 1 ); + } + fprintf( pFile, " } ;\n" ); + continue; + } + else if ( pObj->Type == WLC_OBJ_ARI_ADDSUB ) + { + // out = mode ? a+b+cin : a-b-cin + fprintf( pFile, "%s ;\n", Wlc_ObjName(p, i) ); + fprintf( pFile, " " ); + fprintf( pFile, "assign " ); + fprintf( pFile, "%s = %s ? %s + %s + %s : %s - %s - %s ;\n", + Wlc_ObjName(p, i), Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)), + Wlc_ObjName(p, Wlc_ObjFaninId2(pObj)), Wlc_ObjName(p, Wlc_ObjFaninId(pObj,3)), Wlc_ObjName(p, Wlc_ObjFaninId1(pObj)), + Wlc_ObjName(p, Wlc_ObjFaninId2(pObj)), Wlc_ObjName(p, Wlc_ObjFaninId(pObj,3)), Wlc_ObjName(p, Wlc_ObjFaninId1(pObj)) + ); + continue; + } else if ( pObj->Type == WLC_OBJ_READ || pObj->Type == WLC_OBJ_WRITE ) { if ( p->fMemPorts ) @@ -311,13 +361,7 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops ) } else if ( pObj->Type == WLC_OBJ_FF ) { - char * pInNames[8] = {"d", "clk", "reset", "set", "enable", "async", "sre", "init"}; fprintf( pFile, "%s ;\n", Wlc_ObjName(p, i) ); - fprintf( pFile, " " ); - fprintf( pFile, "%s (", "ABC_DFFRSE" ); - Wlc_ObjForEachFanin( pObj, iFanin, k ) - fprintf( pFile, " .%s(%s),", pInNames[k], Wlc_ObjName(p, iFanin) ); - fprintf( pFile, " .%s(%s) ) ;\n", "q", Wlc_ObjName(p, i) ); continue; } else @@ -425,7 +469,8 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops ) fprintf( pFile, "#" ); else { - assert( 0 ); + //assert( 0 ); + printf( "Failed to write node \"%s\" with unknown operator type (%d).\n", Wlc_ObjName(p, i), pObj->Type ); fprintf( pFile, "???\n" ); continue; } @@ -510,6 +555,18 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops ) } assert( !p->vInits || iFanin == (int)strlen(p->pInits) ); } + // write DFFs in the end + fprintf( pFile, "\n" ); + Wlc_NtkForEachFf2( p, pObj, i ) + { + char * pInNames[8] = {"d", "clk", "reset", "set", "enable", "async", "sre", "init"}; + fprintf( pFile, " " ); + fprintf( pFile, "%s (", "ABC_DFFRSE" ); + Wlc_ObjForEachFanin( pObj, iFanin, k ) + if ( iFanin ) fprintf( pFile, " .%s(%s),", pInNames[k], Wlc_ObjName(p, iFanin) ); + fprintf( pFile, " .%s(%s) ) ;\n", "q", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) ); + } + fprintf( pFile, "\n" ); fprintf( pFile, "endmodule\n\n" ); } void Wlc_WriteVer( Wlc_Ntk_t * p, char * pFileName, int fAddCos, int fNoFlops ) diff --git a/src/base/wln/module.make b/src/base/wln/module.make new file mode 100644 index 00000000..6689baf0 --- /dev/null +++ b/src/base/wln/module.make @@ -0,0 +1,6 @@ +SRC += src/base/wln/wln.c \ + src/base/wln/wlnNdr.c \ + src/base/wln/wlnNtk.c \ + src/base/wln/wlnObj.c \ + src/base/wln/wlnRetime.c \ + src/base/wln/wlnWriteVer.c diff --git a/src/base/wln/wln.c b/src/base/wln/wln.c new file mode 100644 index 00000000..2fbe26e0 --- /dev/null +++ b/src/base/wln/wln.c @@ -0,0 +1,51 @@ +/**CFile**************************************************************** + + FileName [wln.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Word-level network.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 23, 2018.] + + Revision [$Id: wln.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "wln.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/wln/wln.h b/src/base/wln/wln.h new file mode 100644 index 00000000..c862b262 --- /dev/null +++ b/src/base/wln/wln.h @@ -0,0 +1,259 @@ +/**CFile**************************************************************** + + FileName [wlc.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 22, 2014.] + + Revision [$Id: wlc.h,v 1.00 2014/09/12 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__base__wln__wln_h +#define ABC__base__wln__wln_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "aig/gia/gia.h" +#include "misc/vec/vecHash.h" +#include "misc/extra/extra.h" +#include "misc/util/utilNam.h" +#include "misc/util/utilTruth.h" +#include "aig/miniaig/abcOper.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Wln_Vec_t_ Wln_Vec_t; +struct Wln_Vec_t_ +{ + int nCap; + int nSize; + union { int Array[2]; + int * pArray[1]; }; +}; + +typedef struct Wln_Ntk_t_ Wln_Ntk_t; +struct Wln_Ntk_t_ +{ + char * pName; // model name + char * pSpec; // input file name + int fSmtLib; // derived from SMT-LIB + Vec_Int_t vCis; // combinational inputs + Vec_Int_t vCos; // combinational outputs + Vec_Int_t vFfs; // flops + Vec_Int_t vTypes; // object types + Wln_Vec_t * vFanins; // object fanins (exceptions: const, select) + Vec_Int_t vRanges; // object ranges + Hash_IntMan_t * pRanges; // object ranges + Vec_Int_t vNameIds; // object name IDs + Vec_Int_t vInstIds; // object name IDs + Abc_Nam_t * pManName; // object names + Vec_Str_t vSigns; // object signedness + int nTravIds; // counter of traversal IDs + Vec_Int_t vTravIds; // trav IDs of the objects + Vec_Int_t vCopies; // object first bits + Vec_Int_t vBits; // object mapping into AIG nodes + Vec_Int_t vLevels; // object levels + Vec_Int_t vRefs; // object reference counters + Vec_Int_t vFanout; // static fanout + Vec_Int_t vFaninAttrs; // static fanin attributes + Vec_Int_t vFaninLists; // static fanin attributes + Vec_Ptr_t * vTables; // tables + int nObjs[ABC_OPER_LAST]; // counter of objects of each type + int nAnds[ABC_OPER_LAST]; // counter of AND gates after blasting +}; + +static inline int Wln_NtkObjNum( Wln_Ntk_t * p ) { return Vec_IntSize(&p->vTypes); } +static inline int Wln_NtkCiNum( Wln_Ntk_t * p ) { return Vec_IntSize(&p->vCis); } +static inline int Wln_NtkCoNum( Wln_Ntk_t * p ) { return Vec_IntSize(&p->vCos); } +static inline int Wln_NtkFfNum( Wln_Ntk_t * p ) { return Vec_IntSize(&p->vFfs); } +static inline int Wln_NtkPiNum( Wln_Ntk_t * p ) { return Wln_NtkCiNum(p) - Wln_NtkFfNum(p); } +static inline int Wln_NtkPoNum( Wln_Ntk_t * p ) { return Wln_NtkCoNum(p) - Wln_NtkFfNum(p); } + +static inline int Wln_NtkCi( Wln_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vCis, i); } +static inline int Wln_NtkCo( Wln_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vCos, i); } +static inline int Wln_NtkFf( Wln_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vFfs, i); } + +static inline int Wln_ObjType( Wln_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vTypes, i); } +static inline int Wln_ObjIsNone( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_NONE; } +static inline int Wln_ObjIsCi( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_CI; } +static inline int Wln_ObjIsCo( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_CO; } +static inline int Wln_ObjIsCio( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_CI || Wln_ObjType(p, i)==ABC_OPER_CO; } +static inline int Wln_ObjIsFon( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_FON; } +static inline int Wln_ObjIsFf( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_DFFRSE; } +static inline int Wln_ObjIsConst( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_CONST; } +static inline int Wln_ObjIsSlice( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_SLICE; } +static inline int Wln_ObjIsRotate( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_SHIFT_ROTL || Wln_ObjType(p, i) == ABC_OPER_SHIFT_ROTR; } +static inline int Wln_ObjIsTable( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_TABLE; } + +static inline int Wln_ObjFaninNum( Wln_Ntk_t * p, int i ) { return p->vFanins[i].nSize; } +static inline int * Wln_ObjFanins( Wln_Ntk_t * p, int i ) { return Wln_ObjFaninNum(p, i) > 2 ? p->vFanins[i].pArray[0] : p->vFanins[i].Array; } +static inline int Wln_ObjFanin( Wln_Ntk_t * p, int i, int f ) { return Wln_ObjFaninNum(p, i) > 2 ? p->vFanins[i].pArray[0][f] : p->vFanins[i].Array[f]; } +static inline void Wln_ObjSetFanin( Wln_Ntk_t * p, int i, int f, int v ) { Wln_ObjFanins( p, i )[f] = v; } +static inline int Wln_ObjFanin0( Wln_Ntk_t * p, int i ) { return Wln_ObjFanin( p, i, 0 ); } +static inline int Wln_ObjFanin1( Wln_Ntk_t * p, int i ) { return Wln_ObjFanin( p, i, 1 ); } +static inline int Wln_ObjFanin2( Wln_Ntk_t * p, int i ) { return Wln_ObjFanin( p, i, 2 ); } + +static inline int Wln_ObjRangeId( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vRanges, i ); } +static inline int Wln_ObjRangeEnd( Wln_Ntk_t * p, int i ) { return Hash_IntObjData0( p->pRanges, Wln_ObjRangeId(p, i) ); } +static inline int Wln_ObjRangeBeg( Wln_Ntk_t * p, int i ) { return Hash_IntObjData1( p->pRanges, Wln_ObjRangeId(p, i) ); } +static inline int Wln_ObjRangeIsReversed( Wln_Ntk_t * p, int i ) { return Wln_ObjRangeEnd(p, i) < Wln_ObjRangeBeg(p, i); } +static inline int Wln_ObjRange( Wln_Ntk_t * p, int i ) { return 1 + Abc_AbsInt(Wln_ObjRangeEnd(p, i)-Wln_ObjRangeBeg(p, i)); } + +static inline int Wln_ObjIsSigned( Wln_Ntk_t * p, int i ) { return (int)Vec_StrEntry(&p->vSigns, i); } +static inline void Wln_ObjSetSigned( Wln_Ntk_t * p, int i ) { Vec_StrSetEntry(&p->vSigns, i, (char)1); } +static inline int Wln_ObjIsSignedFanin0( Wln_Ntk_t * p, int i ) { return Wln_ObjIsSigned( p, p->fSmtLib ? i : Wln_ObjFanin0(p, i) ); } +static inline int Wln_ObjIsSignedFanin1( Wln_Ntk_t * p, int i ) { return Wln_ObjIsSigned( p, p->fSmtLib ? i : Wln_ObjFanin1(p, i) ); } +static inline int Wln_ObjIsSignedFanin01( Wln_Ntk_t * p, int i ) { return Wln_ObjIsSignedFanin0( p, i ) && Wln_ObjIsSignedFanin1( p, i ); } +static inline int Wln_ObjSign( Wln_Ntk_t * p, int i ) { return Abc_Var2Lit( Wln_ObjRange(p, i), Wln_ObjIsSigned(p, i) ); } + +static inline void Wln_NtkCleanCopy( Wln_Ntk_t * p ) { Vec_IntFill( &p->vCopies, Vec_IntCap(&p->vTypes), 0 ); } +static inline int Wln_NtkHasCopy( Wln_Ntk_t * p ) { return Vec_IntSize( &p->vCopies ) > 0; } +static inline void Wln_ObjSetCopy( Wln_Ntk_t * p, int i, int c ) { Vec_IntWriteEntry( &p->vCopies, i, c ); } +static inline int Wln_ObjCopy( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vCopies, i ); } + +static inline void Wln_NtkCleanLevel( Wln_Ntk_t * p ) { Vec_IntFill( &p->vLevels, Vec_IntCap(&p->vTypes), 0 ); } +static inline int Wln_NtkHasLevel( Wln_Ntk_t * p ) { return Vec_IntSize( &p->vLevels ) > 0; } +static inline void Wln_ObjSetLevel( Wln_Ntk_t * p, int i, int l ) { Vec_IntWriteEntry( &p->vLevels, i, l ); } +static inline int Wln_ObjLevel( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vLevels, i ); } + +static inline void Wln_NtkCleanNameId( Wln_Ntk_t * p ) { Vec_IntFill( &p->vNameIds, Vec_IntCap(&p->vTypes), 0 ); } +static inline int Wln_NtkHasNameId( Wln_Ntk_t * p ) { return Vec_IntSize( &p->vNameIds ) > 0; } +static inline void Wln_ObjSetNameId( Wln_Ntk_t * p, int i, int n ) { Vec_IntWriteEntry( &p->vNameIds, i, n ); } +static inline int Wln_ObjNameId( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vNameIds, i ); } + +static inline void Wln_NtkCleanInstId( Wln_Ntk_t * p ) { Vec_IntFill( &p->vInstIds, Vec_IntCap(&p->vTypes), 0 ); } +static inline int Wln_NtkHasInstId( Wln_Ntk_t * p ) { return Vec_IntSize( &p->vInstIds ) > 0; } +static inline void Wln_ObjSetInstId( Wln_Ntk_t * p, int i, int n ) { Vec_IntWriteEntry( &p->vInstIds, i, n ); } +static inline int Wln_ObjInstId( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vInstIds, i ); } + +static inline void Wln_NtkCleanRefs( Wln_Ntk_t * p ) { Vec_IntFill( &p->vRefs, Vec_IntCap(&p->vTypes), 0 ); } +static inline int Wln_NtkHasRefs( Wln_Ntk_t * p ) { return Vec_IntSize( &p->vRefs ) > 0; } +static inline void Wln_ObjSetRefs( Wln_Ntk_t * p, int i, int n ) { Vec_IntWriteEntry( &p->vRefs, i, n ); } +static inline int Wln_ObjRefs( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vRefs, i ); } +static inline int Wln_ObjRefsInc( Wln_Ntk_t * p, int i ) { return (*Vec_IntEntryP( &p->vRefs, i ))++; } +static inline int Wln_ObjRefsDec( Wln_Ntk_t * p, int i ) { return --(*Vec_IntEntryP( &p->vRefs, i )); } +static inline void Wln_ObjRefsFaninInc( Wln_Ntk_t * p, int i, int k ) { Wln_ObjRefsInc( p, Wln_ObjFanin(p, i, k) ); } +static inline void Wln_ObjRefsFaninDec( Wln_Ntk_t * p, int i, int k ) { Wln_ObjRefsDec( p, Wln_ObjFanin(p, i, k) ); } + +static inline int Wln_ObjFanoutNum( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vRefs, i ); } +static inline int * Wln_ObjFanouts( Wln_Ntk_t * p, int i ) { return Vec_IntEntryP( &p->vFanout, Vec_IntEntry(&p->vFanout, i) ); } +static inline int Wln_ObjFanout( Wln_Ntk_t * p, int i, int f ) { return Wln_ObjFanouts( p, i )[f]; } +static inline void Wln_ObjSetFanout( Wln_Ntk_t * p, int i, int f, int v ){ Wln_ObjFanouts( p, i )[f] = v; } + +static inline void Wln_NtkIncrementTravId( Wln_Ntk_t * p ) { if (!p->nTravIds++) Vec_IntFill(&p->vTravIds, Vec_IntCap(&p->vTypes), 0); } +static inline void Wln_ObjSetTravIdCurrent( Wln_Ntk_t * p, int i ) { Vec_IntWriteEntry( &p->vTravIds, i, p->nTravIds ); } +static inline int Wln_ObjIsTravIdCurrent( Wln_Ntk_t * p, int i ) { return (Vec_IntEntry(&p->vTravIds, i) == p->nTravIds); } +static inline int Wln_ObjIsTravIdPrevious( Wln_Ntk_t * p, int i ) { return (Vec_IntEntry(&p->vTravIds, i) == p->nTravIds-1); } +static inline int Wln_ObjCheckTravId( Wln_Ntk_t * p, int i ) { if ( Wln_ObjIsTravIdCurrent(p, i) ) return 1; Wln_ObjSetTravIdCurrent(p, i); return 0; } + +static inline int Wln_ObjCioId( Wln_Ntk_t * p, int i ) { assert( Wln_ObjIsCio(p, i) ); return Wln_ObjFanin1(p, i); } +static inline int Wln_ObjIsPi( Wln_Ntk_t * p, int i ) { return Wln_ObjIsCi(p, i) && Wln_ObjCioId(p, i) < Wln_NtkPiNum(p); } +static inline int Wln_ObjIsPo( Wln_Ntk_t * p, int i ) { return Wln_ObjIsCo(p, i) && Wln_ObjCioId(p, i) < Wln_NtkPoNum(p); } +static inline int Wln_ObjIsRo( Wln_Ntk_t * p, int i ) { return Wln_ObjIsCi(p, i) && Wln_ObjCioId(p, i) >= Wln_NtkPiNum(p); } +static inline int Wln_ObjIsRi( Wln_Ntk_t * p, int i ) { return Wln_ObjIsCo(p, i) && Wln_ObjCioId(p, i) >= Wln_NtkPoNum(p); } +static inline int Wln_ObjRoToRi( Wln_Ntk_t * p, int i ) { assert( Wln_ObjIsRo(p, i) ); return Wln_NtkCo(p, Wln_NtkCoNum(p) - Wln_NtkCiNum(p) + Wln_ObjCioId(p, i)); } +static inline int Wln_ObjRiToRo( Wln_Ntk_t * p, int i ) { assert( Wln_ObjIsRi(p, i) ); return Wln_NtkCi(p, Wln_NtkCiNum(p) - Wln_NtkCoNum(p) + Wln_ObjCioId(p, i)); } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +#define Wln_NtkForEachObj( p, i ) \ + for ( i = 1; i < Wln_NtkObjNum(p); i++ ) +#define Wln_NtkForEachObjReverse( p, i ) \ + for ( i = Wln_NtkObjNum(p) - 1; i > 0; i-- ) +#define Wln_NtkForEachObjInternal( p, i ) \ + for ( i = 1; i < Wln_NtkObjNum(p); i++ ) if ( Wln_ObjIsCio(p, i) ) {} else + +#define Wln_NtkForEachPi( p, iPi, i ) \ + for ( i = 0; (i < Wln_NtkPiNum(p)) && (((iPi) = Wln_NtkCi(p, i)), 1); i++ ) +#define Wln_NtkForEachPo( p, iPo, i ) \ + for ( i = 0; (i < Wln_NtkPoNum(p)) && (((iPo) = Wln_NtkCo(p, i)), 1); i++ ) +#define Wln_NtkForEachCi( p, iCi, i ) \ + for ( i = 0; (i < Wln_NtkCiNum(p)) && (((iCi) = Wln_NtkCi(p, i)), 1); i++ ) +#define Wln_NtkForEachCo( p, iCo, i ) \ + for ( i = 0; (i < Wln_NtkCoNum(p)) && (((iCo) = Wln_NtkCo(p, i)), 1); i++ ) +#define Wln_NtkForEachFf( p, iFf, i ) \ + for ( i = 0; (i < Wln_NtkFfNum(p)) && (((iFf) = Wln_NtkFf(p, i)), 1); i++ ) + +#define Wln_ObjForEachFanin( p, iObj, iFanin, i ) \ + for ( i = 0; (i < Wln_ObjFaninNum(p, iObj)) && (((iFanin) = Wln_ObjFanin(p, iObj, i)), 1); i++ ) if ( !iFanin ) {} else +#define Wln_ObjForEachFaninReverse( pObj, iFanin, i ) \ + for ( i = Wln_ObjFaninNum(p, iObj) - 1; (i >= 0) && (((iFanin) = Wln_ObjFanin(p, iObj, i)), 1); i-- ) if ( !iFanin ) {} else + +#define Wln_ObjForEachFanoutStatic( p, iObj, iFanout, i ) \ + for ( i = 0; (i < Wln_ObjRefs(p, iObj)) && (((iFanout) = Wln_ObjFanout(p, iObj, i)), 1); i++ ) + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== wlcNdr.c ========================================================*/ +extern Wln_Ntk_t * Wln_ReadNdr( char * pFileName ); +extern void Wln_WriteNdr( Wln_Ntk_t * pNtk, char * pFileName ); +extern Wln_Ntk_t * Wln_NtkFromNdr( void * pData ); +extern void * Wln_NtkToNdr( Wln_Ntk_t * pNtk ); +/*=== wlcNtk.c ========================================================*/ +extern Wln_Ntk_t * Wln_NtkAlloc( char * pName, int nObjsMax ); +extern void Wln_NtkFree( Wln_Ntk_t * p ); +extern int Wln_NtkMemUsage( Wln_Ntk_t * p ); +extern void Wln_NtkPrint( Wln_Ntk_t * p ); +extern Wln_Ntk_t * Wln_NtkDupDfs( Wln_Ntk_t * p ); +extern void Wln_NtkCreateRefs( Wln_Ntk_t * p ); +extern void Wln_NtkStartFaninMap( Wln_Ntk_t * p, Vec_Int_t * vFaninMap, int nMulti ); +extern void Wln_NtkStartFanoutMap( Wln_Ntk_t * p, Vec_Int_t * vFanoutMap, Vec_Int_t * vFanoutNums, int nMulti ); +extern void Wln_NtkStaticFanoutStart( Wln_Ntk_t * p ); +extern void Wln_NtkStaticFanoutStop( Wln_Ntk_t * p ); +extern void Wln_NtkStaticFanoutTest( Wln_Ntk_t * p ); +/*=== wlcObj.c ========================================================*/ +extern char * Wln_ObjName( Wln_Ntk_t * p, int iObj ); +extern char * Wln_ObjConstString( Wln_Ntk_t * p, int iObj ); +extern void Wln_ObjUpdateType( Wln_Ntk_t * p, int iObj, int Type ); +extern void Wln_ObjSetConst( Wln_Ntk_t * p, int iObj, int NameId ); +extern void Wln_ObjSetSlice( Wln_Ntk_t * p, int iObj, int SliceId ); +extern void Wln_ObjAddFanin( Wln_Ntk_t * p, int iObj, int i ); +extern int Wln_ObjAddFanins( Wln_Ntk_t * p, int iObj, Vec_Int_t * vFanins ); +extern int Wln_ObjAlloc( Wln_Ntk_t * p, int Type, int Signed, int End, int Beg ); +extern int Wln_ObjClone( Wln_Ntk_t * pNew, Wln_Ntk_t * p, int iObj ); +extern int Wln_ObjCreateCo( Wln_Ntk_t * p, int iFanin ); +extern void Wln_ObjPrint( Wln_Ntk_t * p, int iObj ); +/*=== wlcRetime.c ========================================================*/ +extern Vec_Int_t * Wln_NtkRetime( Wln_Ntk_t * p ); +/*=== wlcWriteVer.c ========================================================*/ +extern void Wln_WriteVer( Wln_Ntk_t * p, char * pFileName ); + + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/base/wln/wlnNdr.c b/src/base/wln/wlnNdr.c new file mode 100644 index 00000000..c87100a2 --- /dev/null +++ b/src/base/wln/wlnNdr.c @@ -0,0 +1,332 @@ +/**CFile**************************************************************** + + FileName [wlnNdr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Word-level network.] + + Synopsis [Constructing WLN network from NDR data structure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 23, 2018.] + + Revision [$Id: wlnNdr.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "wln.h" +#include "aig/miniaig/ndr.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Wln_NtkToNdr( Wln_Ntk_t * p ) +{ + Vec_Int_t * vFanins; + int i, k, iObj, iFanin; + // create a new module + void * pDesign = Ndr_Create( 1 ); + int ModId = Ndr_AddModule( pDesign, 1 ); + // add primary inputs + Wln_NtkForEachPi( p, iObj, i ) + { + Ndr_AddObject( pDesign, ModId, ABC_OPER_CI, 0, + Wln_ObjRangeEnd(p, iObj), Wln_ObjRangeBeg(p, iObj), Wln_ObjIsSigned(p, iObj), + 0, NULL, 1, &iObj, NULL ); // no fanins + } + // add internal nodes + vFanins = Vec_IntAlloc( 10 ); + Wln_NtkForEachObjInternal( p, iObj ) + { + Vec_IntClear( vFanins ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + Vec_IntPush( vFanins, iFanin ); + Ndr_AddObject( pDesign, ModId, Wln_ObjType(p, iObj), 0, + Wln_ObjRangeEnd(p, iObj), Wln_ObjRangeBeg(p, iObj), Wln_ObjIsSigned(p, iObj), + Vec_IntSize(vFanins), Vec_IntArray(vFanins), 1, &iObj, + Wln_ObjIsConst(p, iObj) ? Wln_ObjConstString(p, iObj) : NULL ); + } + Vec_IntFree( vFanins ); + // add primary outputs + Wln_NtkForEachPo( p, iObj, i ) + { + Ndr_AddObject( pDesign, ModId, ABC_OPER_CO, 0, + Wln_ObjRangeEnd(p, iObj), Wln_ObjRangeBeg(p, iObj), Wln_ObjIsSigned(p, iObj), + 1, &iObj, 0, NULL, NULL ); + } + return pDesign; +} +void Wln_WriteNdr( Wln_Ntk_t * p, char * pFileName ) +{ + void * pDesign = Wln_NtkToNdr( p ); + Ndr_Write( pFileName, pDesign ); + Ndr_Delete( pDesign ); + printf( "Dumped the current design into file \"%s\".\n", pFileName ); +} +void Wln_NtkToNdrTest( Wln_Ntk_t * p ) +{ + // transform + void * pDesign = Wln_NtkToNdr( p ); + + // collect names + char ** ppNames = ABC_ALLOC( char *, Wln_NtkObjNum(p) + 1 ); int i; + Wln_NtkForEachObj( p, i ) + ppNames[i] = Abc_UtilStrsav(Wln_ObjName(p, i)); + + // verify by writing Verilog + Ndr_WriteVerilog( NULL, pDesign, ppNames ); + Ndr_Write( "test.ndr", pDesign ); + + // cleanup + Ndr_Delete( pDesign ); + Wln_NtkForEachObj( p, i ) + ABC_FREE( ppNames[i] ); + ABC_FREE( ppNames ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ndr_ObjGetRange( Ndr_Data_t * p, int Obj, int * End, int * Beg ) +{ + int * pArray, nArray = Ndr_ObjReadArray( p, Obj, NDR_RANGE, &pArray ); + int Signed = 0; *End = *Beg = 0; + if ( nArray == 0 ) + return 0; + if ( nArray == 3 ) + Signed = 1; + if ( nArray == 1 ) + *End = *Beg = pArray[0]; + else + *End = pArray[0], *Beg = pArray[1]; + return Signed; +} +void Ndr_NtkPrintObjects( Wln_Ntk_t * pNtk ) +{ + int k, iObj, iFanin; + printf( "Node IDs and their fanins:\n" ); + Wln_NtkForEachObj( pNtk, iObj ) + { + printf( "%5d = ", iObj ); + Wln_ObjForEachFanin( pNtk, iObj, iFanin, k ) + printf( "%5d ", iFanin ); + for ( ; k < 4; k++ ) + printf( " " ); + printf( " Name Id %d ", Wln_ObjNameId(pNtk, iObj) ); + if ( Wln_ObjIsPi(pNtk, iObj) ) + printf( " pi " ); + if ( Wln_ObjIsPo(pNtk, iObj) ) + printf( " po " ); + printf( "\n" ); + } +} +void Wln_NtkCheckIntegrity( void * pData ) +{ + Ndr_Data_t * p = (Ndr_Data_t *)pData; + Vec_Int_t * vMap = Vec_IntAlloc( 100 ); + int Mod = 2, Obj; + Ndr_ModForEachObj( p, Mod, Obj ) + { + int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT ); + if ( NameId == -1 ) + { + int Type = Ndr_ObjReadBody( p, Obj, NDR_OPERTYPE ); + if ( Type != ABC_OPER_CO ) + printf( "Internal object %d of type %s has no output name.\n", Obj, Abc_OperName(Type) ); + continue; + } + if ( Vec_IntGetEntry(vMap, NameId) > 0 ) + printf( "Output name %d is used more than once (obj %d and obj %d).\n", NameId, Vec_IntGetEntry(vMap, NameId), Obj ); + Vec_IntSetEntry( vMap, NameId, Obj ); + } + Ndr_ModForEachObj( p, Mod, Obj ) + { + int Type = Ndr_ObjReadBody( p, Obj, NDR_OPERTYPE ); + int i, * pArray, nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + for ( i = 0; i < nArray; i++ ) + if ( Vec_IntGetEntry(vMap, pArray[i]) == 0 && !(Type == ABC_OPER_DFFRSE && (i >= 5 || i <= 7)) ) + printf( "Input name %d appearing as fanin %d of obj %d is not used as output name in any object.\n", pArray[i], i, Obj ); + } + Vec_IntFree( vMap ); +} +Wln_Ntk_t * Wln_NtkFromNdr( void * pData ) +{ + Ndr_Data_t * p = (Ndr_Data_t *)pData; + Vec_Int_t * vName2Obj, * vFanins = Vec_IntAlloc( 100 ); + Vec_Ptr_t * vConstStrings = Vec_PtrAlloc( 100 ); + int Mod = 2, i, k, iFanin, iObj, Obj, * pArray, nDigits, fFound, NameId, NameIdMax; + Wln_Ntk_t * pTemp, * pNtk = Wln_NtkAlloc( "top", Ndr_DataObjNum(p, Mod) ); + Wln_NtkCheckIntegrity( pData ); + //pNtk->pSpec = Abc_UtilStrsav( pFileName ); + // construct network and save name IDs + Wln_NtkCleanNameId( pNtk ); + Wln_NtkCleanInstId( pNtk ); + Ndr_ModForEachPi( p, Mod, Obj ) + { + int End, Beg, Signed = Ndr_ObjGetRange(p, Obj, &End, &Beg); + int iObj = Wln_ObjAlloc( pNtk, ABC_OPER_CI, Signed, End, Beg ); + int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT ); + int InstId = Ndr_ObjReadBody( p, Obj, NDR_NAME ); + Wln_ObjSetNameId( pNtk, iObj, NameId ); + if ( InstId > 0 ) Wln_ObjSetInstId( pNtk, iObj, InstId ); + } + Ndr_ModForEachNode( p, Mod, Obj ) + { + int End, Beg, Signed = Ndr_ObjGetRange(p, Obj, &End, &Beg); + int Type = Ndr_ObjReadBody( p, Obj, NDR_OPERTYPE ); + int nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + Vec_Int_t F = {nArray, nArray, pArray}, * vTemp = &F; + int iObj = Wln_ObjAlloc( pNtk, Type, Signed, End, Beg ); + int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT ); + int InstId = Ndr_ObjReadBody( p, Obj, NDR_NAME ); + Vec_IntClear( vFanins ); + Vec_IntAppend( vFanins, vTemp ); + assert( Type != ABC_OPER_DFF ); + if ( Wln_ObjIsSlice(pNtk, iObj) ) + Wln_ObjSetSlice( pNtk, iObj, Hash_Int2ManInsert(pNtk->pRanges, End, Beg, 0) ); + else if ( Wln_ObjIsConst(pNtk, iObj) ) + Vec_PtrPush( vConstStrings, (char *)Ndr_ObjReadBodyP(p, Obj, NDR_FUNCTION) ); +// else if ( Type == ABC_OPER_BIT_MUX && Vec_IntSize(vFanins) == 3 ) +// ABC_SWAP( int, Wln_ObjFanins(pNtk, iObj)[1], Wln_ObjFanins(pNtk, iObj)[2] ); + Wln_ObjAddFanins( pNtk, iObj, vFanins ); + Wln_ObjSetNameId( pNtk, iObj, NameId ); + if ( InstId > 0 ) Wln_ObjSetInstId( pNtk, iObj, InstId ); + if ( Type == ABC_OPER_ARI_SMUL ) + { + assert( Wln_ObjFaninNum(pNtk, iObj) == 2 ); + Wln_ObjSetSigned( pNtk, Wln_ObjFanin0(pNtk, iObj) ); + Wln_ObjSetSigned( pNtk, Wln_ObjFanin1(pNtk, iObj) ); + } + } + // mark primary outputs + Ndr_ModForEachPo( p, Mod, Obj ) + { + int End, Beg, Signed = Ndr_ObjGetRange(p, Obj, &End, &Beg); + int nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + int iObj = Wln_ObjAlloc( pNtk, ABC_OPER_CO, Signed, End, Beg ); + int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT ); + int InstId = Ndr_ObjReadBody( p, Obj, NDR_NAME ); + assert( nArray == 1 && NameId == -1 && InstId == -1 ); + Wln_ObjAddFanin( pNtk, iObj, pArray[0] ); + } + Vec_IntFree( vFanins ); + // remove instance names if they are not given + //Vec_IntPrint( &pNtk->vInstIds ); + if ( Vec_IntCountPositive(&pNtk->vInstIds) == 0 ) + Vec_IntErase( &pNtk->vInstIds ); + // map name IDs into object IDs + vName2Obj = Vec_IntInvert( &pNtk->vNameIds, 0 ); + Wln_NtkForEachObj( pNtk, i ) + Wln_ObjForEachFanin( pNtk, i, iFanin, k ) + Wln_ObjSetFanin( pNtk, i, k, Vec_IntEntry(vName2Obj, iFanin) ); + Vec_IntFree(vName2Obj); + // create fake object names + NameIdMax = Vec_IntFindMax(&pNtk->vNameIds); + nDigits = Abc_Base10Log( NameIdMax+1 ); + pNtk->pManName = Abc_NamStart( NameIdMax+1, 10 ); + for ( i = 1; i <= NameIdMax; i++ ) + { + char pName[20]; sprintf( pName, "s%0*d", nDigits, i ); + NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, &fFound ); + assert( !fFound && i == NameId ); + } + // add const strings + i = 0; + Wln_NtkForEachObj( pNtk, iObj ) + if ( Wln_ObjIsConst(pNtk, iObj) ) + Wln_ObjSetConst( pNtk, iObj, Abc_NamStrFindOrAdd(pNtk->pManName, (char *)Vec_PtrEntry(vConstStrings, i++), NULL) ); + assert( i == Vec_PtrSize(vConstStrings) ); + Vec_PtrFree( vConstStrings ); + //Ndr_NtkPrintObjects( pNtk ); + //Wln_WriteVer( pNtk, "temp_ndr.v", 0, 0 ); + // derive topological order + pNtk = Wln_NtkDupDfs( pTemp = pNtk ); + Wln_NtkFree( pTemp ); + //Ndr_NtkPrintObjects( pNtk ); + //pNtk->fMemPorts = 1; // the network contains memory ports + //pNtk->fEasyFfs = 1; // the network contains simple flops + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Wln_Ntk_t * Wln_ReadNdr( char * pFileName ) +{ + void * pData = Ndr_Read( pFileName ); + Wln_Ntk_t * pNtk = Wln_NtkFromNdr( pData ); + //char * ppNames[10] = { NULL, "a", "b", "c", "d", "e", "f", "g", "h", "i" }; + //Ndr_WriteVerilog( NULL, pData, ppNames ); + Ndr_Delete( pData ); + return pNtk; +} +void Wln_ReadNdrTest() +{ + Wln_Ntk_t * pNtk = Wln_ReadNdr( "D:\\temp\\brijesh\\for_alan_dff_warning\\work_fir_filter_fir_filter_proc_out.ndr" ); + //Wln_Ntk_t * pNtk = Wln_ReadNdr( "flop.ndr" ); + Wln_WriteVer( pNtk, "test__test.v" ); + Wln_NtkPrint( pNtk ); + Wln_NtkStaticFanoutTest( pNtk ); + Wln_NtkFree( pNtk ); +} +void Wln_NtkRetimeTest( char * pFileName ) +{ + void * pData = Ndr_Read( pFileName ); + Wln_Ntk_t * pNtk = Wln_NtkFromNdr( pData ); + Ndr_Delete( pData ); + if ( !Wln_NtkHasInstId(pNtk) ) + printf( "The design has no delay information.\n" ); + else + { + Vec_Int_t * vMoves = Wln_NtkRetime( pNtk ); + Vec_IntPrint( vMoves ); + Vec_IntFree( vMoves ); + } + Wln_NtkFree( pNtk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/wln/wlnNtk.c b/src/base/wln/wlnNtk.c new file mode 100644 index 00000000..39c03964 --- /dev/null +++ b/src/base/wln/wlnNtk.c @@ -0,0 +1,321 @@ +/**CFile**************************************************************** + + FileName [wlnNtk.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Word-level network.] + + Synopsis [Network construction procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 23, 2018.] + + Revision [$Id: wlnNtk.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "wln.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creating networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Wln_Ntk_t * Wln_NtkAlloc( char * pName, int nObjsMax ) +{ + Wln_Ntk_t * p; int i; + p = ABC_CALLOC( Wln_Ntk_t, 1 ); + p->pName = pName ? Extra_FileNameGeneric( pName ) : NULL; + Vec_IntGrow( &p->vCis, 111 ); + Vec_IntGrow( &p->vCos, 111 ); + Vec_IntGrow( &p->vFfs, 111 ); + Vec_IntGrow( &p->vTypes, nObjsMax+1 ); + Vec_StrGrow( &p->vSigns, nObjsMax+1 ); + Vec_IntGrow( &p->vRanges, nObjsMax+1 ); + Vec_IntPush( &p->vTypes, -1 ); + Vec_StrPush( &p->vSigns, -1 ); + Vec_IntPush( &p->vRanges, -1 ); + p->vFanins = ABC_CALLOC( Wln_Vec_t, nObjsMax+1 ); + p->pRanges = Hash_IntManStart( 1000 ); + for ( i = 0; i < 65; i++ ) + Hash_Int2ManInsert( p->pRanges, i, i, 0 ); + for ( i = 1; i < 64; i++ ) + Hash_Int2ManInsert( p->pRanges, i, 0, 0 ); + assert( Hash_IntManEntryNum(p->pRanges) == 128 ); + return p; +} +void Wln_NtkFree( Wln_Ntk_t * p ) +{ + int i; + for ( i = 0; i < Wln_NtkObjNum(p); i++ ) + if ( Wln_ObjFaninNum(p, i) > 2 ) + ABC_FREE( p->vFanins[i].pArray[0] ); + ABC_FREE( p->vFanins ); + + if ( p->pRanges ) Hash_IntManStop( p->pRanges ); + if ( p->pManName ) Abc_NamStop( p->pManName ); + + ABC_FREE( p->vCis.pArray ); + ABC_FREE( p->vCos.pArray ); + ABC_FREE( p->vFfs.pArray ); + + ABC_FREE( p->vTypes.pArray ); + ABC_FREE( p->vSigns.pArray ); + ABC_FREE( p->vRanges.pArray ); + ABC_FREE( p->vNameIds.pArray ); + ABC_FREE( p->vInstIds.pArray ); + ABC_FREE( p->vTravIds.pArray ); + ABC_FREE( p->vCopies.pArray ); + ABC_FREE( p->vBits.pArray ); + ABC_FREE( p->vLevels.pArray ); + ABC_FREE( p->vRefs.pArray ); + ABC_FREE( p->vFanout.pArray ); + ABC_FREE( p->vFaninAttrs.pArray ); + ABC_FREE( p->vFaninLists.pArray ); + + ABC_FREE( p->pName ); + ABC_FREE( p->pSpec ); + ABC_FREE( p ); +} +int Wln_NtkMemUsage( Wln_Ntk_t * p ) +{ + int Mem = sizeof(Wln_Ntk_t); + Mem += 4 * p->vCis.nCap; + Mem += 4 * p->vCos.nCap; + Mem += 4 * p->vFfs.nCap; + Mem += 1 * p->vTypes.nCap; + Mem += 4 * p->vRanges.nCap; + Mem += 4 * p->vNameIds.nCap; + Mem += 4 * p->vInstIds.nCap; + Mem += 4 * p->vTravIds.nCap; + Mem += 4 * p->vCopies.nCap; + Mem += 4 * p->vBits.nCap; + Mem += 4 * p->vLevels.nCap; + Mem += 4 * p->vRefs.nCap; + Mem += 4 * p->vFanout.nCap; + Mem += 4 * p->vFaninAttrs.nCap; + Mem += 4 * p->vFaninLists.nCap; + Mem += 20 * Hash_IntManEntryNum(p->pRanges); + Mem += Abc_NamMemUsed(p->pManName); + return Mem; +} +void Wln_NtkPrint( Wln_Ntk_t * p ) +{ + int iObj; + printf( "Printing %d objects of network \"%s\":\n", Wln_NtkObjNum(p), p->pName ); + Wln_NtkForEachObj( p, iObj ) + Wln_ObjPrint( p, iObj ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Duplicating network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_NtkTransferNames( Wln_Ntk_t * pNew, Wln_Ntk_t * p ) +{ + assert( pNew->pManName == NULL && p->pManName != NULL ); + pNew->pManName = p->pManName; + p->pManName = NULL; + assert( !Wln_NtkHasCopy(pNew) && Wln_NtkHasCopy(p) ); + if ( Wln_NtkHasNameId(p) ) + { + int i; + assert( !Wln_NtkHasNameId(pNew) && Wln_NtkHasNameId(p) ); + Wln_NtkCleanNameId( pNew ); + Wln_NtkForEachObj( p, i ) + if ( Wln_ObjCopy(p, i) && i < Vec_IntSize(&p->vNameIds) && Wln_ObjNameId(p, i) ) + Wln_ObjSetNameId( pNew, Wln_ObjCopy(p, i), Wln_ObjNameId(p, i) ); + Vec_IntErase( &p->vNameIds ); + } + if ( Wln_NtkHasInstId(p) ) + { + int i; + assert( !Wln_NtkHasInstId(pNew) && Wln_NtkHasInstId(p) ); + Wln_NtkCleanInstId( pNew ); + Wln_NtkForEachObj( p, i ) + if ( Wln_ObjCopy(p, i) && i < Vec_IntSize(&p->vInstIds) && Wln_ObjInstId(p, i) ) + Wln_ObjSetInstId( pNew, Wln_ObjCopy(p, i), Wln_ObjInstId(p, i) ); + Vec_IntErase( &p->vInstIds ); + } +} +int Wln_ObjDup( Wln_Ntk_t * pNew, Wln_Ntk_t * p, int iObj ) +{ + int i, iFanin, iObjNew = Wln_ObjClone( pNew, p, iObj ); + Wln_ObjForEachFanin( p, iObj, iFanin, i ) + Wln_ObjAddFanin( pNew, iObjNew, Wln_ObjCopy(p, iFanin) ); + if ( Wln_ObjIsConst(p, iObj) ) + Wln_ObjSetConst( pNew, iObjNew, Wln_ObjFanin0(p, iObj) ); + else if ( Wln_ObjIsSlice(p, iObj) || Wln_ObjIsRotate(p, iObj) || Wln_ObjIsTable(p, iObj) ) + Wln_ObjSetFanin( p, iObjNew, 1, Wln_ObjFanin1(p, iObj) ); + Wln_ObjSetCopy( p, iObj, iObjNew ); + return iObjNew; +} +int Wln_NtkDupDfs_rec( Wln_Ntk_t * pNew, Wln_Ntk_t * p, int iObj ) +{ + int i, iFanin; + if ( iObj == 0 ) + return 0; + if ( Wln_ObjCopy(p, iObj) ) + return Wln_ObjCopy(p, iObj); + //printf( "Visiting node %d\n", iObj ); + assert( !Wln_ObjIsFf(p, iObj) ); + Wln_ObjForEachFanin( p, iObj, iFanin, i ) + Wln_NtkDupDfs_rec( pNew, p, iFanin ); + return Wln_ObjDup( pNew, p, iObj ); +} +Wln_Ntk_t * Wln_NtkDupDfs( Wln_Ntk_t * p ) +{ + int i, k, iObj, iFanin; + Wln_Ntk_t * pNew = Wln_NtkAlloc( p->pName, Wln_NtkObjNum(p) ); + pNew->fSmtLib = p->fSmtLib; + if ( p->pSpec ) pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Wln_NtkCleanCopy( p ); + Wln_NtkForEachCi( p, iObj, i ) + Wln_ObjDup( pNew, p, iObj ); + Wln_NtkForEachFf( p, iObj, i ) + Wln_ObjSetCopy( p, iObj, Wln_ObjClone(pNew, p, iObj) ); + Wln_NtkForEachCo( p, iObj, i ) + Wln_NtkDupDfs_rec( pNew, p, iObj ); + Wln_NtkForEachFf( p, iObj, i ) + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + Wln_ObjAddFanin( pNew, Wln_ObjCopy(p, iObj), Wln_NtkDupDfs_rec(pNew, p, iFanin) ); + if ( Wln_NtkHasNameId(p) ) + Wln_NtkTransferNames( pNew, p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Create fanin/fanout map.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_NtkCreateRefs( Wln_Ntk_t * p ) +{ + int k, iObj, iFanin; + Wln_NtkCleanRefs( p ); + Wln_NtkForEachObj( p, iObj ) + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + Wln_ObjRefsInc( p, iFanin ); +} +int Wln_NtkFaninNum( Wln_Ntk_t * p ) +{ + int iObj, nEdges = 0; + Wln_NtkForEachObj( p, iObj ) + nEdges += Wln_ObjFaninNum(p, iObj); + return nEdges; +} +void Wln_NtkStartFaninMap( Wln_Ntk_t * p, Vec_Int_t * vFaninMap, int nMulti ) +{ + int iObj, iOffset = Wln_NtkObjNum(p); + Vec_IntFill( vFaninMap, iOffset + nMulti * Wln_NtkFaninNum(p), 0 ); + Wln_NtkForEachObj( p, iObj ) + { + Vec_IntWriteEntry( vFaninMap, iObj, iOffset ); + iOffset += nMulti * Wln_ObjFaninNum(p, iObj); + } + assert( iOffset == Vec_IntSize(vFaninMap) ); +} +void Wln_NtkStartFanoutMap( Wln_Ntk_t * p, Vec_Int_t * vFanoutMap, Vec_Int_t * vFanoutNums, int nMulti ) +{ + int iObj, iOffset = Wln_NtkObjNum(p); + Vec_IntFill( vFanoutMap, iOffset + nMulti * Vec_IntSum(vFanoutNums), 0 ); + Wln_NtkForEachObj( p, iObj ) + { + Vec_IntWriteEntry( vFanoutMap, iObj, iOffset ); + iOffset += nMulti * Wln_ObjRefs(p, iObj); + } + assert( iOffset == Vec_IntSize(vFanoutMap) ); +} + +/**Function************************************************************* + + Synopsis [Static fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_NtkStaticFanoutStart( Wln_Ntk_t * p ) +{ + int k, iObj, iFanin; + Vec_Int_t * vRefsCopy = Vec_IntAlloc(0); + Wln_NtkCreateRefs( p ); + Wln_NtkStartFanoutMap( p, &p->vFanout, &p->vRefs, 1 ); + ABC_SWAP( Vec_Int_t, *vRefsCopy, p->vRefs ); + // add fanouts + Wln_NtkCleanRefs( p ); + Wln_NtkForEachObj( p, iObj ) + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + Wln_ObjSetFanout( p, iFanin, Wln_ObjRefsInc(p, iFanin), iObj ); + // double-check the current number of fanouts added + Wln_NtkForEachObj( p, iObj ) + assert( Wln_ObjRefs(p, iObj) == Vec_IntEntry(vRefsCopy, iObj) ); + Vec_IntFree( vRefsCopy ); +} +void Wln_NtkStaticFanoutStop( Wln_Ntk_t * p ) +{ + Vec_IntErase( &p->vRefs ); + Vec_IntErase( &p->vFanout ); +} +void Wln_NtkStaticFanoutTest( Wln_Ntk_t * p ) +{ + int k, iObj, iFanout; + printf( "Printing fanouts of %d objects of network \"%s\":\n", Wln_NtkObjNum(p), p->pName ); + Wln_NtkStaticFanoutStart( p ); + Wln_NtkForEachObj( p, iObj ) + { + Wln_ObjPrint( p, iObj ); + printf( " Fanouts : " ); + Wln_ObjForEachFanoutStatic( p, iObj, iFanout, k ) + printf( "%5d ", iFanout ); + printf( "\n" ); + } + Wln_NtkStaticFanoutStop( p ); + printf( "\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/wln/wlnObj.c b/src/base/wln/wlnObj.c new file mode 100644 index 00000000..ec373304 --- /dev/null +++ b/src/base/wln/wlnObj.c @@ -0,0 +1,151 @@ +/**CFile**************************************************************** + + FileName [wlnObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Word-level network.] + + Synopsis [Object construction procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 23, 2018.] + + Revision [$Id: wlnObj.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "wln.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creating objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Wln_ObjName( Wln_Ntk_t * p, int iObj ) +{ + static char Buffer[100]; + if ( Wln_NtkHasNameId(p) && Wln_ObjNameId(p, iObj) ) + return Abc_NamStr( p->pManName, Wln_ObjNameId(p, iObj) ); + sprintf( Buffer, "n%d", iObj ); + return Buffer; +} +char * Wln_ObjConstString( Wln_Ntk_t * p, int iObj ) +{ + assert( Wln_ObjIsConst(p, iObj) ); + return Abc_NamStr( p->pManName, Wln_ObjFanin0(p, iObj) ); +} +void Wln_ObjUpdateType( Wln_Ntk_t * p, int iObj, int Type ) +{ + assert( Wln_ObjIsNone(p, iObj) ); + p->nObjs[Wln_ObjType(p, iObj)]--; + Vec_IntWriteEntry( &p->vTypes, iObj, Type ); + p->nObjs[Wln_ObjType(p, iObj)]++; +} +void Wln_ObjSetConst( Wln_Ntk_t * p, int iObj, int NameId ) +{ + assert( Wln_ObjIsConst(p, iObj) ); + Wln_ObjSetFanin( p, iObj, 0, NameId ); +} +void Wln_ObjSetSlice( Wln_Ntk_t * p, int iObj, int SliceId ) +{ + assert( Wln_ObjIsSlice(p, iObj) ); + Wln_ObjSetFanin( p, iObj, 1, SliceId ); +} +void Wln_ObjAddFanin( Wln_Ntk_t * p, int iObj, int i ) +{ + Wln_Vec_t * pVec = p->vFanins + iObj; + if ( Wln_ObjFaninNum(p, iObj) < 2 ) + pVec->Array[pVec->nSize++] = i; + else if ( Wln_ObjFaninNum(p, iObj) == 2 ) + { + int * pArray = ABC_ALLOC( int, 4 ); + pArray[0] = pVec->Array[0]; + pArray[1] = pVec->Array[1]; + pArray[2] = i; + pVec->pArray[0] = pArray; + pVec->nSize = 3; + pVec->nCap = 4; + } + else + { + if ( pVec->nSize == pVec->nCap ) + pVec->pArray[0] = ABC_REALLOC( int, pVec->pArray[0], (pVec->nCap = 2*pVec->nSize) ); + assert( pVec->nSize < pVec->nCap ); + pVec->pArray[0][pVec->nSize++] = i; + } +} +int Wln_ObjAddFanins( Wln_Ntk_t * p, int iObj, Vec_Int_t * vFanins ) +{ + int i, iFanin; + Vec_IntForEachEntry( vFanins, iFanin, i ) + Wln_ObjAddFanin( p, iObj, iFanin ); + return iObj; +} +int Wln_ObjAlloc( Wln_Ntk_t * p, int Type, int Signed, int End, int Beg ) +{ + int iObj = Vec_IntSize(&p->vTypes); + if ( iObj == Vec_IntCap(&p->vTypes) ) + { + p->vFanins = ABC_REALLOC( Wln_Vec_t, p->vFanins, 2 * iObj ); + memset( p->vFanins + iObj, 0, sizeof(Wln_Vec_t) * iObj ); + Vec_IntGrow( &p->vTypes, 2 * iObj ); + } + assert( iObj == Vec_StrSize(&p->vSigns) ); + assert( iObj == Vec_IntSize(&p->vRanges) ); + Vec_IntPush( &p->vTypes, Type ); + Vec_StrPush( &p->vSigns, (char)Signed ); + Vec_IntPush( &p->vRanges, Hash_Int2ManInsert(p->pRanges, End, Beg, 0) ); + if ( Wln_ObjIsCi(p, iObj) ) Wln_ObjSetFanin( p, iObj, 1, Vec_IntSize(&p->vCis) ), Vec_IntPush( &p->vCis, iObj ); + if ( Wln_ObjIsCo(p, iObj) ) Wln_ObjSetFanin( p, iObj, 1, Vec_IntSize(&p->vCos) ), Vec_IntPush( &p->vCos, iObj ); + if ( Wln_ObjIsFf(p, iObj) ) Vec_IntPush( &p->vFfs, iObj ); + p->nObjs[Type]++; + return iObj; +} +int Wln_ObjClone( Wln_Ntk_t * pNew, Wln_Ntk_t * p, int iObj ) +{ + return Wln_ObjAlloc( pNew, Wln_ObjType(p, iObj), Wln_ObjIsSigned(p, iObj), Wln_ObjRangeEnd(p, iObj), Wln_ObjRangeBeg(p, iObj) ); +} +int Wln_ObjCreateCo( Wln_Ntk_t * p, int iFanin ) +{ + int iCo = Wln_ObjClone( p, p, iFanin ); + Wln_ObjUpdateType( p, iCo, ABC_OPER_CO ); + Wln_ObjAddFanin( p, iCo, iFanin ); + return iCo; +} +void Wln_ObjPrint( Wln_Ntk_t * p, int iObj ) +{ + int k, iFanin, Type = Wln_ObjType(p, iObj); + printf( "Obj %6d : Type = %6s Fanins = %d : ", iObj, Abc_OperName(Type), Wln_ObjFaninNum(p, iObj) ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + printf( "%5d ", iFanin ); + printf( "\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/wln/wlnRetime.c b/src/base/wln/wlnRetime.c new file mode 100644 index 00000000..459af2d9 --- /dev/null +++ b/src/base/wln/wlnRetime.c @@ -0,0 +1,487 @@ +/**CFile**************************************************************** + + FileName [wlnRetime.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Word-level network.] + + Synopsis [Retiming.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 23, 2018.] + + Revision [$Id: wlnRetime.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "wln.h" +#include "misc/vec/vecHsh.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Wln_Ret_t_ Wln_Ret_t; +struct Wln_Ret_t_ +{ + Wln_Ntk_t * pNtk; // static netlist + Vec_Int_t vFanins; // fanins and edge places + Vec_Int_t vFanouts; // fanouts and edge places + Vec_Int_t vEdgeLinks; // edge links + Vec_Int_t vFfClasses; // flop classes + Vec_Int_t vNodeDelays; // object delays + Vec_Int_t vPathDelays; // delays from sources to sinks + Vec_Int_t vSources; // critical sources + Vec_Int_t vSinks; // critical sinks + Vec_Int_t vFront; // retiming frontier + Vec_Int_t vMoves; // retiming moves (paired with delay) + int nClasses; // the number of flop classes + int DelayMax; // critical delay at any time +}; + +static inline int * Wln_RetFanins( Wln_Ret_t * p, int i ) { return Vec_IntEntryP( &p->vFanins, Vec_IntEntry(&p->vFanins, i) ); } +static inline int * Wln_RetFanouts( Wln_Ret_t * p, int i ) { return Vec_IntEntryP( &p->vFanouts, Vec_IntEntry(&p->vFanouts, i) ); } + +#define Wln_RetForEachFanin( p, iObj, iFanin, pLink, i ) \ + for ( i = 0; (i < Wln_ObjFaninNum(p->pNtk, iObj)) && \ + (((iFanin) = Wln_RetFanins(p, iObj)[2*i]), 1) && \ + ((pLink) = (Wln_RetFanins(p, iObj)+2*i+1)); i++ ) if ( !iFanin ) {} else + +#define Wln_RetForEachFanout( p, iObj, iFanout, pLink, i ) \ + for ( i = 0; (i < Wln_ObjRefs(p->pNtk, iObj)) && \ + (((iFanout) = Wln_RetFanouts(p, iObj)[2*i]), 1) && \ + ((pLink) = Vec_IntEntryP(&p->vFanins, Wln_RetFanouts(p, iObj)[2*i+1])); i++ ) if ( !iFanout ) {} else + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Retiming manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Wln_RetComputeFfClasses( Wln_Ntk_t * pNtk, Vec_Int_t * vClasses ) +{ + int i, k, iObj, nClasses; + Hsh_VecMan_t * p = Hsh_VecManStart( 10 ); + Vec_Int_t * vFlop = Vec_IntAlloc( 6 ); + Vec_IntFill( vClasses, Wln_NtkObjNum(pNtk), -1 ); + Wln_NtkForEachFf( pNtk, iObj, i ) + { + Vec_IntClear( vFlop ); + for ( k = 1; k <= 6; k++ ) + Vec_IntPush( vFlop, Wln_ObjFanin(pNtk, iObj, k) ); + Vec_IntWriteEntry( vClasses, iObj, Hsh_VecManAdd(p, vFlop) ); + } + nClasses = Hsh_VecSize( p ); + Hsh_VecManStop( p ); + Vec_IntFree( vFlop ); + printf( "Detected %d flop classes.\n", nClasses ); + return nClasses; +} +Wln_Ret_t * Wln_RetAlloc( Wln_Ntk_t * pNtk ) +{ + Wln_Ret_t * p; int k, iObj, iFanin; + Vec_Int_t * vRefsCopy = Vec_IntAlloc(0); + p = ABC_CALLOC( Wln_Ret_t, 1 ); + p->pNtk = pNtk; + Wln_NtkCreateRefs( pNtk ); + Wln_NtkStartFaninMap( pNtk, &p->vFanins, 2 ); + Wln_NtkStartFanoutMap( pNtk, &p->vFanouts, &pNtk->vRefs, 2 ); + ABC_SWAP( Vec_Int_t, *vRefsCopy, pNtk->vRefs ); + Wln_NtkCleanRefs( pNtk ); + Vec_IntGrow( &p->vEdgeLinks, 10*Wln_NtkFfNum(pNtk) ); + Vec_IntPushTwo( &p->vEdgeLinks, -1, -1 ); + Wln_NtkForEachObj( pNtk, iObj ) + Wln_ObjForEachFanin( pNtk, iObj, iFanin, k ) + { + int * pFanins = Wln_RetFanins( p, iObj ); + int * pFanouts = Wln_RetFanouts( p, iFanin ); + int Index = Wln_ObjRefsInc( pNtk, iFanin ); + pFanins[2*k+0] = iFanin; + pFanins[2*k+1] = Wln_ObjIsFf(pNtk, iFanin) ? Vec_IntSize(&p->vEdgeLinks) : 0; + pFanouts[2*Index+0] = iObj; + pFanouts[2*Index+1] = Vec_IntEntry(&p->vFanins, iObj) + 2*k + 1; + if ( Wln_ObjIsFf(pNtk, iFanin) ) + Vec_IntPushTwo( &p->vEdgeLinks, 0, iFanin ); + } + // double-check the current number of fanouts added + Wln_NtkForEachObj( pNtk, iObj ) + assert( Wln_ObjRefs(pNtk, iObj) == Vec_IntEntry(vRefsCopy, iObj) ); + Vec_IntFree( vRefsCopy ); + // other data + p->nClasses = Wln_RetComputeFfClasses( pNtk, &p->vFfClasses ); + ABC_SWAP( Vec_Int_t, p->vNodeDelays, pNtk->vInstIds ); + Vec_IntGrow( &p->vSources, 1000 ); + Vec_IntGrow( &p->vSinks, 1000 ); + Vec_IntGrow( &p->vFront, 1000 ); + Vec_IntGrow( &p->vMoves, 1000 ); + return p; +} +void Wln_RetFree( Wln_Ret_t * p ) +{ + ABC_FREE( p->vFanins.pArray ); + ABC_FREE( p->vFanouts.pArray ); + ABC_FREE( p->vEdgeLinks.pArray ); + ABC_FREE( p->vFfClasses.pArray ); + ABC_FREE( p->vNodeDelays.pArray ); + ABC_FREE( p->vPathDelays.pArray ); + ABC_FREE( p->vSources.pArray ); + ABC_FREE( p->vSinks.pArray ); + ABC_FREE( p->vFront.pArray ); + ABC_FREE( p->vMoves.pArray ); + ABC_FREE( p ); +} +int Wln_RetMemUsage( Wln_Ret_t * p ) +{ + int Mem = sizeof(Wln_Ret_t); + Mem += 4 * p->vFanins.nCap; + Mem += 4 * p->vFanouts.nCap; + Mem += 4 * p->vEdgeLinks.nCap; + Mem += 4 * p->vFfClasses.nCap; + Mem += 4 * p->vNodeDelays.nCap; + Mem += 4 * p->vPathDelays.nCap; + Mem += 4 * p->vSources.nCap; + Mem += 4 * p->vSinks.nCap; + Mem += 4 * p->vFront.nCap; + Mem += 4 * p->vMoves.nCap; + return Mem; +} + +/**Function************************************************************* + + Synopsis [Delay propagation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_RetMarkChanges_rec( Wln_Ret_t * p, int iObj ) +{ + int k, iFanout, * pLink, * pDelay = Vec_IntEntryP( &p->vPathDelays, iObj ); + if ( *pDelay < 0 ) + return; + *pDelay = -1; + Wln_RetForEachFanout( p, iObj, iFanout, pLink, k ) + if ( !pLink[0] ) + Wln_RetMarkChanges_rec( p, iFanout ); +} +int Wln_RetPropDelay_rec( Wln_Ret_t * p, int iObj ) +{ + int k, iFanin, * pLink, * pDelay = Vec_IntEntryP( &p->vPathDelays, iObj ); + if ( *pDelay >= 0 ) + return *pDelay; + Wln_RetForEachFanin( p, iObj, iFanin, pLink, k ) + if ( pLink[0] ) + *pDelay = Abc_MaxInt(*pDelay, 0); + else + *pDelay = Abc_MaxInt(*pDelay, Wln_RetPropDelay_rec(p, iFanin)); + *pDelay += Vec_IntEntry( &p->vNodeDelays, iObj ); + return *pDelay; +} +int Wln_RetPropDelay( Wln_Ret_t * p, Vec_Int_t * vFront ) +{ + int i, iObj, DelayMax = 0; + if ( vFront ) + { + Vec_IntForEachEntry( vFront, iObj, i ) + Wln_RetMarkChanges_rec( p, iObj ); + } + else + { + Vec_IntFill( &p->vPathDelays, Wln_NtkObjNum(p->pNtk), -1 ); + Wln_NtkForEachCi( p->pNtk, iObj, i ) + Vec_IntWriteEntry( &p->vPathDelays, iObj, 0 ); + } + Vec_IntClear( &p->vSinks ); + Wln_NtkForEachObj( p->pNtk, iObj ) + if ( !Wln_ObjIsCo(p->pNtk, iObj) ) + { + int Delay = Wln_RetPropDelay_rec(p, iObj); + if ( DelayMax == Delay ) + Vec_IntPush( &p->vSinks, iObj ); + else if ( DelayMax < Delay ) + { + DelayMax = Delay; + Vec_IntFill( &p->vSinks, 1, iObj ); + } + } + return DelayMax; +} + +void Wln_RetFindSources_rec( Wln_Ret_t * p, int iObj ) +{ + int k, iFanin, * pLink, FaninDelay, fTerm = 1; + if ( Wln_ObjIsCi(p->pNtk, iObj) || Wln_ObjCheckTravId(p->pNtk, iObj) ) + return; + FaninDelay = Vec_IntEntry( &p->vPathDelays, iObj ) - Vec_IntEntry( &p->vNodeDelays, iObj ); + Wln_RetForEachFanin( p, iObj, iFanin, pLink, k ) + { + if ( !pLink[0] ) + continue; + fTerm = 0; + if ( Vec_IntEntry(&p->vPathDelays, iFanin) == FaninDelay ) + Wln_RetFindSources_rec( p, iFanin ); + } + if ( fTerm ) + Vec_IntPush( &p->vSources, iObj ); +} +void Wln_RetFindSources( Wln_Ret_t * p ) +{ + int i, iObj; + Vec_IntClear( &p->vSources ); + Wln_NtkIncrementTravId( p->pNtk ); + Vec_IntForEachEntry( &p->vSinks, iObj, i ) + Wln_RetFindSources_rec( p, iObj ); +} + +/**Function************************************************************* + + Synopsis [Retimability check.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Wln_RetHeadToTail( Wln_Ret_t * p, int * pHead ) +{ + int * pLink; + assert( pHead[0] ); + pLink = Vec_IntEntryP( &p->vEdgeLinks, pHead[0] ); + if ( pLink[0] == 0 ) + return pHead; + return Wln_RetHeadToTail( p, pLink ); +} + +static inline int Wln_RetCheckForwardOne( Wln_Ret_t * p, int iObj ) +{ + int k, iFanin, * pLink, iFlop, Class = -1; + Wln_RetForEachFanin( p, iObj, iFanin, pLink, k ) + { + if ( !pLink[0] ) + return 0; + iFlop = Vec_IntEntry( &p->vEdgeLinks, pLink[0] + 1 ); + assert( Wln_ObjIsFf( p->pNtk, iFlop ) ); + if ( Class == -1 ) + Class = Vec_IntEntry( &p->vFfClasses, iFlop ); + else if ( Class != Vec_IntEntry( &p->vFfClasses, iFlop ) ) + return 0; + } + return 1; +} +int Wln_RetCheckForward( Wln_Ret_t * p, Vec_Int_t * vSet ) +{ + int i, iObj; + Vec_IntForEachEntry( vSet, iObj, i ) + if ( !Wln_RetCheckForwardOne( p, iObj ) ) + return 0; + return 1; +} + +static inline int Wln_RetCheckBackwardOne( Wln_Ret_t * p, int iObj ) +{ + int k, iFanin, * pLink, iFlop, Class = -1; + Wln_RetForEachFanout( p, iObj, iFanin, pLink, k ) + { + if ( !pLink[0] ) + return 0; + pLink = Wln_RetHeadToTail( p, pLink ); + iFlop = Vec_IntEntry( &p->vEdgeLinks, pLink[0] + 1 ); + assert( Wln_ObjIsFf( p->pNtk, iFlop ) ); + if ( Class == -1 ) + Class = Vec_IntEntry( &p->vFfClasses, iFlop ); + else if ( Class != Vec_IntEntry( &p->vFfClasses, iFlop ) ) + return 0; + } + return 1; +} +int Wln_RetCheckBackward( Wln_Ret_t * p, Vec_Int_t * vSet ) +{ + int i, iObj; + Vec_IntForEachEntry( vSet, iObj, i ) + if ( !Wln_RetCheckBackwardOne( p, iObj ) ) + return 0; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Moving flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Wln_RetRemoveOneFanin( Wln_Ret_t * p, int iObj ) +{ + int k, iFanin, * pLink, iFlop, iFlop1 = -1; + int * pFanins = Wln_RetFanins( p, iObj ); + Wln_RetForEachFanin( p, iObj, iFanin, pLink, k ) + { + assert( pLink[0] ); + pFanins[2*k+1] = Vec_IntEntry( &p->vEdgeLinks, pLink[0] ); + iFlop = Vec_IntEntry( &p->vEdgeLinks, pLink[0] + 1 ); + assert( Wln_ObjIsFf( p->pNtk, iFlop ) ); + if ( iFlop1 == -1 ) + iFlop1 = iFlop; + } + return iFlop1; +} +int Wln_RetRemoveOneFanout( Wln_Ret_t * p, int iObj ) +{ + int k, iFanin, * pLink, iFlop, iFlop1 = -1; + //int * pFanins = Wln_RetFanins( p, iObj ); + Wln_RetForEachFanout( p, iObj, iFanin, pLink, k ) + { + assert( pLink[0] ); + pLink = Wln_RetHeadToTail( p, pLink ); + iFlop = Vec_IntEntry( &p->vEdgeLinks, pLink[0] + 1 ); + pLink[0] = 0; + assert( Wln_ObjIsFf( p->pNtk, iFlop ) ); + if ( iFlop1 == -1 ) + iFlop1 = iFlop; + } + return iFlop1; +} +void Wln_RetInsertOneFanin( Wln_Ret_t * p, int iObj, int iFlop ) +{ + int k, iFanin, * pLink; + int * pFanins = Wln_RetFanins( p, iObj ); + assert( Wln_ObjIsFf( p->pNtk, iFlop ) ); + Wln_RetForEachFanin( p, iObj, iFanin, pLink, k ) + { + int iHead = pFanins[2*k+1]; + pFanins[2*k+1] = Vec_IntSize(&p->vEdgeLinks); + Vec_IntPushTwo( &p->vEdgeLinks, iHead, iFlop ); + } +} +void Wln_RetInsertOneFanout( Wln_Ret_t * p, int iObj, int iFlop ) +{ + int k, iFanin, * pLink; + assert( Wln_ObjIsFf( p->pNtk, iFlop ) ); + Wln_RetForEachFanout( p, iObj, iFanin, pLink, k ) + { + if ( pLink[0] ) + pLink = Wln_RetHeadToTail( p, pLink ); + pLink = Vec_IntEntryP( &p->vEdgeLinks, pLink[0] ); + assert( pLink[0] == 0 ); + pLink[0] = Vec_IntSize(&p->vEdgeLinks); + Vec_IntPushTwo( &p->vEdgeLinks, 0, iFlop ); + } +} +void Wln_RetRetimeForward( Wln_Ret_t * p, Vec_Int_t * vSet ) +{ + int i, iObj, iFlop; + Vec_IntForEachEntry( vSet, iObj, i ) + { + iFlop = Wln_RetRemoveOneFanin( p, iObj ); + Wln_RetInsertOneFanout( p, iObj, iFlop ); + } +} +void Wln_RetRetimeBackward( Wln_Ret_t * p, Vec_Int_t * vSet ) +{ + int i, iObj, iFlop; + Vec_IntForEachEntry( vSet, iObj, i ) + { + iFlop = Wln_RetRemoveOneFanout( p, iObj ); + Wln_RetInsertOneFanin( p, iObj, iFlop ); + } +} +void Wln_RetAddToMoves( Wln_Ret_t * p, Vec_Int_t * vSet, int Delay, int fForward ) +{ + int i, iObj; + if ( vSet == NULL ) + { + Vec_IntPushTwo( &p->vMoves, 0, Delay ); + return; + } + Vec_IntForEachEntry( vSet, iObj, i ) + { + int NameId = Vec_IntEntry( &p->pNtk->vNameIds, iObj ); + Vec_IntPushTwo( &p->vMoves, fForward ? NameId : -NameId, Delay ); + } +} + +/**Function************************************************************* + + Synopsis [Retiming computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Wln_NtkRetime( Wln_Ntk_t * pNtk ) +{ + Wln_Ret_t * p = Wln_RetAlloc( pNtk ); + Vec_Int_t * vSources = &p->vSources; + Vec_Int_t * vSinks = &p->vSinks; + Vec_Int_t * vFront = &p->vFront; + Vec_Int_t * vMoves = Vec_IntAlloc(0); + p->DelayMax = Wln_RetPropDelay( p, NULL ); + Wln_RetFindSources( p ); + Wln_RetAddToMoves( p, NULL, p->DelayMax, 0 ); + while ( Vec_IntSize(vSources) || Vec_IntSize(vSinks) ) + { + int fForward = Vec_IntSize(vSources) && Wln_RetCheckForward( p, vSources ); + int fBackward = Vec_IntSize(vSinks) && Wln_RetCheckBackward( p, vSinks ); + if ( !fForward && !fBackward ) + { + printf( "Cannot retime forward and backward.\n" ); + break; + } + Vec_IntSort( vSources, 0 ); + Vec_IntSort( vSinks, 0 ); + if ( Vec_IntTwoCountCommon(vSources, vSinks) ) + { + printf( "Cannot reduce delay by retiming.\n" ); + break; + } + Vec_IntClear( vFront ); + if ( (fForward && !fBackward) || (fForward && fBackward && Vec_IntSize(vSources) < Vec_IntSize(vSinks)) ) + Wln_RetRetimeForward( p, vSources ), Vec_IntAppend( vFront, vSources ), fForward = 1, fBackward = 0; + else + Wln_RetRetimeBackward( p, vSinks ), Vec_IntAppend( vFront, vSources ), fForward = 0, fBackward = 1; + p->DelayMax = Wln_RetPropDelay( p, vFront ); + Wln_RetAddToMoves( p, vFront, p->DelayMax, fForward ); + Wln_RetFindSources( p ); + if ( 2*Vec_IntSize(&p->vEdgeLinks) > Vec_IntCap(&p->vEdgeLinks) ) + Vec_IntGrow( &p->vEdgeLinks, 4*Vec_IntSize(&p->vEdgeLinks) ); + } + ABC_SWAP( Vec_Int_t, *vMoves, p->vMoves ); + Wln_RetFree( p ); + return vMoves; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/wln/wlnWriteVer.c b/src/base/wln/wlnWriteVer.c new file mode 100644 index 00000000..1c37e311 --- /dev/null +++ b/src/base/wln/wlnWriteVer.c @@ -0,0 +1,494 @@ +/**CFile**************************************************************** + + FileName [wlnWriteVer.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Word-level network.] + + Synopsis [Writing Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 23, 2018.] + + Revision [$Id: wlnWriteVer.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "wln.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_WriteTableOne( FILE * pFile, int nFans, int nOuts, word * pTable, int Id ) +{ + int m, nMints = (1<<nFans); +// Abc_TtPrintHexArrayRev( stdout, pTable, nMints ); printf( "\n" ); + assert( nOuts > 0 && nOuts <= 64 && (64 % nOuts) == 0 ); + fprintf( pFile, "module table%d(ind, val);\n", Id ); + fprintf( pFile, " input [%d:0] ind;\n", nFans-1 ); + fprintf( pFile, " output [%d:0] val;\n", nOuts-1 ); + fprintf( pFile, " reg [%d:0] val;\n", nOuts-1 ); + fprintf( pFile, " always @(ind)\n" ); + fprintf( pFile, " begin\n" ); + fprintf( pFile, " case (ind)\n" ); + for ( m = 0; m < nMints; m++ ) + fprintf( pFile, " %d\'h%x: val = %d\'h%x;\n", nFans, m, nOuts, (unsigned)((pTable[(nOuts * m) >> 6] >> ((nOuts * m) & 63)) & Abc_Tt6Mask(nOuts)) ); + fprintf( pFile, " endcase\n" ); + fprintf( pFile, " end\n" ); + fprintf( pFile, "endmodule\n" ); + fprintf( pFile, "\n" ); +} +void Wln_WriteTables( FILE * pFile, Wln_Ntk_t * p ) +{ + Vec_Int_t * vNodes; + word * pTable; + int i, iObj; + if ( p->vTables == NULL || Vec_PtrSize(p->vTables) == 0 ) + return; + // map tables into their nodes + vNodes = Vec_IntStart( Vec_PtrSize(p->vTables) ); + Wln_NtkForEachObj( p, iObj ) + if ( Wln_ObjType(p, iObj) == ABC_OPER_TABLE ) + Vec_IntWriteEntry( vNodes, Wln_ObjFanin1(p, iObj), iObj ); + // write tables + Vec_PtrForEachEntry( word *, p->vTables, pTable, i ) + { + int iNode = Vec_IntEntry( vNodes, i ); + int iFanin = Wln_ObjFanin0( p, iNode ); + Wln_WriteTableOne( pFile, Wln_ObjRange(p, iFanin), Wln_ObjRange(p, iNode), pTable, i ); + } + Vec_IntFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [This was used to add POs to each node except PIs and MUXes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_WriteAddPos( Wln_Ntk_t * p ) +{ + int iObj; + Wln_NtkForEachObj( p, iObj ) + if ( !Wln_ObjIsCio(p, iObj) ) + Wln_ObjCreateCo( p, iObj ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_WriteVerIntVec( FILE * pFile, Wln_Ntk_t * p, Vec_Int_t * vVec, int Start ) +{ + char * pName; + int LineLength = Start; + int NameCounter = 0; + int AddedLength, i, iObj; + Vec_IntForEachEntry( vVec, iObj, i ) + { + pName = Wln_ObjName( p, iObj ); + // get the line length after this name is written + AddedLength = strlen(pName) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > 70 ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = Start; + NameCounter = 0; + } + fprintf( pFile, " %s%s", pName, (i==Vec_IntSize(vVec)-1)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } +} +void Wln_WriteVerInt( FILE * pFile, Wln_Ntk_t * p ) +{ + int k, j, iObj, iFanin; + char Range[100]; + fprintf( pFile, "module %s ( ", p->pName ); + fprintf( pFile, "\n " ); + if ( Wln_NtkCiNum(p) > 0 ) + { + Wln_WriteVerIntVec( pFile, p, &p->vCis, 3 ); + fprintf( pFile, ",\n " ); + } + if ( Wln_NtkCoNum(p) > 0 ) + Wln_WriteVerIntVec( pFile, p, &p->vCos, 3 ); + fprintf( pFile, " );\n" ); + Wln_NtkForEachObj( p, iObj ) + { + int End = Wln_ObjRangeEnd(p, iObj); + int Beg = Wln_ObjRangeBeg(p, iObj); + int nDigits = Abc_Base10Log(Abc_AbsInt(End)+1) + Abc_Base10Log(Abc_AbsInt(Beg)+1) + (int)(End < 0) + (int)(Beg < 0); + sprintf( Range, "%s[%d:%d]%*s", (!p->fSmtLib && Wln_ObjIsSigned(p, iObj)) ? "signed ":" ", End, Beg, 8-nDigits, "" ); + fprintf( pFile, " " ); + if ( Wln_ObjIsCi(p, iObj) ) + fprintf( pFile, "input " ); + else if ( Wln_ObjIsCo(p, iObj) ) + fprintf( pFile, "output " ); + else + fprintf( pFile, " " ); + if ( Wln_ObjIsCio(p, iObj) ) + { + fprintf( pFile, "wire %s %s ;\n", Range, Wln_ObjName(p, iObj) ); + if ( Wln_ObjIsCi(p, iObj) ) + continue; + fprintf( pFile, " assign " ); + fprintf( pFile, "%-16s = %s ;\n", Wln_ObjName(p, iObj), Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + continue; + } + if ( Wln_ObjType(p, iObj) == ABC_OPER_SEL_NMUX || Wln_ObjType(p, iObj) == ABC_OPER_SEL_SEL ) + fprintf( pFile, "reg %s ", Range ); + else + fprintf( pFile, "wire %s ", Range ); + if ( Wln_ObjType(p, iObj) == ABC_OPER_TABLE ) + { + // wire [3:0] s4972; table0 s4972_Index(s4971, s4972); + fprintf( pFile, "%s ; table%d", Wln_ObjName(p, iObj), Wln_ObjFanin1(p, iObj) ); + fprintf( pFile, " s%d_Index(%s, ", iObj, Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + fprintf( pFile, "%s)", Wln_ObjName(p, iObj) ); + } + else if ( Wln_ObjIsConst(p, iObj) ) + fprintf( pFile, "%-16s = %s", Wln_ObjName(p, iObj), Wln_ObjConstString(p, iObj) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_ROTR || Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_ROTL ) + { + // wire [27:0] s4960 = (s57 >> 17) | (s57 << 11); + int Num0 = Wln_ObjFanin1(p, iObj); + int Num1 = Wln_ObjRange(p, iObj) - Num0; + assert( Num0 > 0 && Num0 < Wln_ObjRange(p, iObj) ); + fprintf( pFile, "%-16s = ", Wln_ObjName(p, iObj) ); + if ( Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_ROTR ) + fprintf( pFile, "(%s >> %d) | (%s << %d)", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), Num0, Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), Num1 ); + else + fprintf( pFile, "(%s << %d) | (%s >> %d)", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), Num0, Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), Num1 ); + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SEL_NMUX ) + { + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + fprintf( pFile, " " ); + fprintf( pFile, "always @( " ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + fprintf( pFile, "%s%s", k ? " or ":"", Wln_ObjName(p, Wln_ObjFanin(p, iObj, k)) ); + fprintf( pFile, " )\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "begin\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "case ( %s )\n", Wln_ObjName(p, Wln_ObjFanin(p, iObj, 0)) ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + { + if ( !k ) continue; + fprintf( pFile, " " ); + fprintf( pFile, "%d : %s = ", k-1, Wln_ObjName(p, iObj) ); + fprintf( pFile, "%s ;\n", Wln_ObjName(p, Wln_ObjFanin(p, iObj, k)) ); + } + fprintf( pFile, " " ); + fprintf( pFile, "endcase\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "end\n" ); + continue; + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SEL_SEL ) + { + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + fprintf( pFile, " " ); + fprintf( pFile, "always @( " ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + fprintf( pFile, "%s%s", k ? " or ":"", Wln_ObjName(p, Wln_ObjFanin(p, iObj, k)) ); + fprintf( pFile, " )\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "begin\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "case ( %s )\n", Wln_ObjName(p, Wln_ObjFanin(p, iObj, 0)) ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + { + if ( !k ) continue; + fprintf( pFile, " " ); + fprintf( pFile, "%d\'b", Wln_ObjFaninNum(p, iObj)-1 ); + for ( j = Wln_ObjFaninNum(p, iObj)-1; j > 0; j-- ) + fprintf( pFile, "%d", (int)(j==k) ); + fprintf( pFile, " : %s = ", Wln_ObjName(p, iObj) ); + fprintf( pFile, "%s ;\n", Wln_ObjName(p, Wln_ObjFanin(p, iObj, k)) ); + } + fprintf( pFile, " " ); + fprintf( pFile, "default" ); + fprintf( pFile, " : %s = ", Wln_ObjName(p, iObj) ); + fprintf( pFile, "%d\'b", Wln_ObjRange(p, iObj) ); + for ( j = Wln_ObjRange(p, iObj)-1; j >= 0; j-- ) + fprintf( pFile, "%d", 0 ); + fprintf( pFile, " ;\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "endcase\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "end\n" ); + continue; + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SEL_DEC ) + { + int nRange = Wln_ObjRange(p, Wln_ObjFanin0(p, iObj)); + assert( (1 << nRange) == Wln_ObjRange(p, iObj) ); + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + for ( k = 0; k < Wln_ObjRange(p, iObj); k++ ) + { + fprintf( pFile, " " ); + fprintf( pFile, "wire " ); + fprintf( pFile, "%s_", Wln_ObjName(p, iObj) ); + for ( j = 0; j < nRange; j++ ) + fprintf( pFile, "%d", (k >> (nRange-1-j)) & 1 ); + fprintf( pFile, " = " ); + for ( j = 0; j < nRange; j++ ) + fprintf( pFile, "%s%s%s[%d]", + j ? " & ":"", ((k >> (nRange-1-j)) & 1) ? " ":"~", + Wln_ObjName(p, Wln_ObjFanin(p, iObj, 0)), nRange-1-j ); + fprintf( pFile, " ;\n" ); + } + fprintf( pFile, " " ); + fprintf( pFile, "assign %s = { ", Wln_ObjName(p, iObj) ); + for ( k = Wln_ObjRange(p, iObj)-1; k >= 0; k-- ) + { + fprintf( pFile, "%s%s_", k < Wln_ObjRange(p, iObj)-1 ? ", ":"", Wln_ObjName(p, iObj) ); + for ( j = 0; j < nRange; j++ ) + fprintf( pFile, "%d", (k >> (nRange-1-j)) & 1 ); + } + fprintf( pFile, " } ;\n" ); + continue; + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_ADDSUB ) + { + // out = mode ? a+b+cin : a-b-cin + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + fprintf( pFile, " " ); + fprintf( pFile, "assign " ); + fprintf( pFile, "%s = %s ? %s + %s + %s : %s - %s - %s ;\n", + Wln_ObjName(p, iObj), Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), + Wln_ObjName(p, Wln_ObjFanin2(p, iObj)), Wln_ObjName(p, Wln_ObjFanin(p, iObj,3)), Wln_ObjName(p, Wln_ObjFanin1(p, iObj)), + Wln_ObjName(p, Wln_ObjFanin2(p, iObj)), Wln_ObjName(p, Wln_ObjFanin(p, iObj,3)), Wln_ObjName(p, Wln_ObjFanin1(p, iObj)) + ); + continue; + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RAMR || Wln_ObjType(p, iObj) == ABC_OPER_RAMW ) + { + if ( 1 ) + { + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + fprintf( pFile, " " ); + fprintf( pFile, "%s (", Wln_ObjType(p, iObj) == ABC_OPER_RAMR ? "ABC_READ" : "ABC_WRITE" ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + fprintf( pFile, " .%s(%s),", k==0 ? "mem_in" : (k==1 ? "addr": "data"), Wln_ObjName(p, iFanin) ); + fprintf( pFile, " .%s(%s) ) ;\n", Wln_ObjType(p, iObj) == ABC_OPER_RAMR ? "data" : "mem_out", Wln_ObjName(p, iObj) ); + continue; + } + else + { + int nBitsMem = Wln_ObjRange(p, Wln_ObjFanin(p, iObj, 0) ); + //int nBitsAddr = Wln_ObjRange(p, Wln_ObjFanin(p, iObj, 1) ); + int nBitsDat = Wln_ObjType(p, iObj) == ABC_OPER_RAMR ? Wln_ObjRange(p, iObj) : Wln_ObjRange(p, Wln_ObjFanin(p, iObj, 2)); + int Depth = nBitsMem / nBitsDat; + assert( nBitsMem % nBitsDat == 0 ); + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + fprintf( pFile, " " ); + fprintf( pFile, "%s_%d (", Wln_ObjType(p, iObj) == ABC_OPER_RAMR ? "CPL_MEM_READ" : "CPL_MEM_WRITE", Depth ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + fprintf( pFile, " .%s(%s),", k==0 ? "mem_data_in" : (k==1 ? "addr_in": "data_in"), Wln_ObjName(p, iFanin) ); + fprintf( pFile, " .%s(%s) ) ;\n", "data_out", Wln_ObjName(p, iObj) ); + continue; + } + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_DFFRSE ) + { + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + continue; + } + else + { + fprintf( pFile, "%-16s = ", Wln_ObjName(p, iObj) ); + if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_BUF ) + fprintf( pFile, "%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_MUX ) + { + fprintf( pFile, "%s ? ", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + fprintf( pFile, "%s : ", Wln_ObjName(p, Wln_ObjFanin1(p, iObj)) ); + fprintf( pFile, "%s", Wln_ObjName(p, Wln_ObjFanin2(p, iObj)) ); + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_MIN ) + fprintf( pFile, "-%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_INV ) + fprintf( pFile, "~%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_LOGIC_NOT ) + fprintf( pFile, "!%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RED_AND ) + fprintf( pFile, "&%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RED_OR ) + fprintf( pFile, "|%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RED_XOR ) + fprintf( pFile, "^%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RED_NAND ) + fprintf( pFile, "~&%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RED_NOR ) + fprintf( pFile, "~|%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RED_NXOR ) + fprintf( pFile, "~^%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SLICE ) + fprintf( pFile, "%s [%d:%d]", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), Wln_ObjRangeEnd(p, iObj), Wln_ObjRangeBeg(p, iObj) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SIGNEXT ) + fprintf( pFile, "{ {%d{%s[%d]}}, %s }", Wln_ObjRange(p, iObj) - Wln_ObjRange(p, Wln_ObjFanin0(p, iObj)), Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), Wln_ObjRange(p, Wln_ObjFanin0(p, iObj)) - 1, Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ZEROPAD ) + fprintf( pFile, "{ {%d{1\'b0}}, %s }", Wln_ObjRange(p, iObj) - Wln_ObjRange(p, Wln_ObjFanin0(p, iObj)), Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_CONCAT ) + { + fprintf( pFile, "{" ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + fprintf( pFile, " %s%s", Wln_ObjName(p, Wln_ObjFanin(p, iObj, k)), k == Wln_ObjFaninNum(p, iObj)-1 ? "":"," ); + fprintf( pFile, " }" ); + } + else + { + fprintf( pFile, "%s ", Wln_ObjName(p, Wln_ObjFanin(p, iObj, 0)) ); + if ( Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_R ) + fprintf( pFile, ">>" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_RA ) + fprintf( pFile, ">>>" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_L ) + fprintf( pFile, "<<" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_LA ) + fprintf( pFile, "<<<" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_AND ) + fprintf( pFile, "&" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_OR ) + fprintf( pFile, "|" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_XOR ) + fprintf( pFile, "^" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_NAND ) + fprintf( pFile, "~&" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_NOR ) + fprintf( pFile, "~|" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_NXOR ) + fprintf( pFile, "~^" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_LOGIC_IMPL ) + fprintf( pFile, "=>" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_LOGIC_AND ) + fprintf( pFile, "&&" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_LOGIC_OR ) + fprintf( pFile, "||" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_LOGIC_XOR ) + fprintf( pFile, "^^" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_COMP_EQU ) + fprintf( pFile, "==" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_COMP_NOTEQU ) + fprintf( pFile, "!=" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_COMP_LESS ) + fprintf( pFile, "<" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_COMP_MORE ) + fprintf( pFile, ">" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_COMP_LESSEQU ) + fprintf( pFile, "<=" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_COMP_MOREEQU ) + fprintf( pFile, ">=" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_ADD ) + fprintf( pFile, "+" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_SUB ) + fprintf( pFile, "-" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_MUL ) + fprintf( pFile, "*" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_DIV ) + fprintf( pFile, "/" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_REM ) + fprintf( pFile, "%%" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_MOD ) + fprintf( pFile, "%%" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_POW ) + fprintf( pFile, "**" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_SQRT ) + fprintf( pFile, "@" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_SQUARE ) + fprintf( pFile, "#" ); + else + { + //assert( 0 ); + printf( "Failed to write node \"%s\" with unknown operator type (%d).\n", Wln_ObjName(p, iObj), Wln_ObjType(p, iObj) ); + fprintf( pFile, "???\n" ); + continue; + } + fprintf( pFile, " %s", Wln_ObjName(p, Wln_ObjFanin(p, iObj, 1)) ); + if ( Wln_ObjFaninNum(p, iObj) == 3 && Wln_ObjType(p, iObj) == ABC_OPER_ARI_ADD ) + fprintf( pFile, " + %s", Wln_ObjName(p, Wln_ObjFanin(p, iObj, 2)) ); + } + } + fprintf( pFile, " ;%s\n", (p->fSmtLib && Wln_ObjIsSigned(p, iObj)) ? " // signed SMT-LIB operator" : "" ); + } + iFanin = 0; + // write DFFs in the end + fprintf( pFile, "\n" ); + Wln_NtkForEachFf( p, iObj, j ) + { + char * pInNames[8] = {"d", "clk", "reset", "set", "enable", "async", "sre", "init"}; + fprintf( pFile, " " ); + fprintf( pFile, "%s (", "ABC_DFFRSE" ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + if ( iFanin ) fprintf( pFile, " .%s(%s),", pInNames[k], Wln_ObjName(p, iFanin) ); + fprintf( pFile, " .%s(%s) ) ;\n", "q", Wln_ObjName(p, iObj) ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "endmodule\n\n" ); +} +void Wln_WriteVer( Wln_Ntk_t * p, char * pFileName ) +{ + FILE * pFile; + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Wln_WriteVer(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", p->pName, Extra_TimeStamp() ); + fprintf( pFile, "\n" ); + Wln_WriteTables( pFile, p ); +// if ( fAddCos ) +// Wln_WriteAddPos( p ); + Wln_WriteVerInt( pFile, p ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + |