diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2005-08-31 08:01:00 -0700 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2005-08-31 08:01:00 -0700 |
commit | ab7cb9c6ad52934b80e44f2bb5ae94049a5a4ae5 (patch) | |
tree | eecf964e680ab7f91dc9f2635cfd508f44769afd /src | |
parent | 2b85f5ba649bcc81873697718fe8a9085d09c31d (diff) | |
download | abc-ab7cb9c6ad52934b80e44f2bb5ae94049a5a4ae5.tar.gz abc-ab7cb9c6ad52934b80e44f2bb5ae94049a5a4ae5.tar.bz2 abc-ab7cb9c6ad52934b80e44f2bb5ae94049a5a4ae5.zip |
Version abc50831
Diffstat (limited to 'src')
37 files changed, 3983 insertions, 280 deletions
diff --git a/src/base/abc/abc.c b/src/base/abc/abc.c index 7c949ee0..0d911e79 100644 --- a/src/base/abc/abc.c +++ b/src/base/abc/abc.c @@ -36,8 +36,11 @@ static int Abc_CommandPrintFanio ( Abc_Frame_t * pAbc, int argc, char ** argv 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_CommandPrintSymms ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShowCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShowAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCollapse ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandStrash ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -105,8 +108,11 @@ 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_symm", Abc_CommandPrintSymms, 0 ); Cmd_CommandAdd( pAbc, "Printing", "show_bdd", Abc_CommandShowBdd, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "show_cut", Abc_CommandShowCut, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "show_aig", Abc_CommandShowAig, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "collapse", Abc_CommandCollapse, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "strash", Abc_CommandStrash, 1 ); @@ -297,9 +303,10 @@ int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: print_io [-h]\n" ); + fprintf( pErr, "usage: print_io [-h] <node>\n" ); fprintf( pErr, "\t prints the PIs/POs or fanins/fanouts of a node\n" ); fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tnode : the node to print fanins/fanouts\n"); return 1; } @@ -629,13 +636,85 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fUseBdds; + int fNaive; + int fVerbose; + extern void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fVerbose ); + + pNtk = Abc_FrameReadNet(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseBdds = 1; + fNaive = 0; + fVerbose = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "bnvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fUseBdds ^= 1; + break; + case 'n': + fNaive ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs.\n" ); + return 1; + } + Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: print_symm [-nbvh]\n" ); + fprintf( pErr, "\t computes symmetries of the PO functions\n" ); + fprintf( pErr, "\t-b : enable efficient BDD-based computation [default = %s].\n", fUseBdds? "yes": "no" ); + fprintf( pErr, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" ); + fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk; Abc_Obj_t * pNode; int c; - extern void Abc_NodePrintBdd( Abc_Obj_t * pNode ); + extern void Abc_NodeShowBdd( Abc_Obj_t * pNode ); pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); @@ -662,7 +741,7 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( !Abc_NtkIsBddLogic(pNtk) ) { - fprintf( pErr, "Printing BDDs can only be done for logic BDD networks.\n" ); + fprintf( pErr, "Visualizing BDDs can only be done for logic BDD networks.\n" ); return 1; } @@ -678,7 +757,7 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); return 1; } - Abc_NodePrintBdd( pNode ); + Abc_NodeShowBdd( pNode ); return 0; usage: @@ -693,6 +772,168 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c; + int nNodeSizeMax; + int nConeSizeMax; + extern void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ); + + pNtk = Abc_FrameReadNet(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nNodeSizeMax = 10; + nConeSizeMax = ABC_INFINITY; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "NCh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodeSizeMax = atoi(argv[util_optind]); + util_optind++; + if ( nNodeSizeMax < 0 ) + goto usage; + break; + case 'C': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConeSizeMax = atoi(argv[util_optind]); + util_optind++; + if ( nConeSizeMax < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Visualizing cuts only works for AIGs.\n" ); + return 1; + } + if ( argc != util_optind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); + return 1; + } + Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax ); + return 0; + +usage: + fprintf( pErr, "usage: show_cut [-N num] [-C num] [-h] <node>\n" ); + fprintf( pErr, " visualizes the cut of a node using DOT and GSVIEW\n" ); +#ifdef WIN32 + fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); + fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); +#endif + fprintf( pErr, "\t-N num : the max size of the cut to be computed [default = %d]\n", nNodeSizeMax ); + fprintf( pErr, "\t-C num : the max support of the containing cone [default = %d]\n", nConeSizeMax ); + fprintf( pErr, "\tnode : the node to consider\n"); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShowAig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + extern void Abc_NtkShowAig( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNet(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Visualizing AIG can only be done for AIGs.\n" ); + return 1; + } + Abc_NtkShowAig( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: show_aig [-h]\n" ); + fprintf( pErr, " visualizes the AIG with choices using DOT and GSVIEW\n" ); +#ifdef WIN32 + fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); + fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); +#endif + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* @@ -745,7 +986,7 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) pNtkRes = Abc_NtkCollapse( pNtk, 1 ); else { - pNtk = Abc_NtkStrash( pNtk, 0 ); + pNtk = Abc_NtkStrash( pNtk, 0, 0 ); pNtkRes = Abc_NtkCollapse( pNtk, 1 ); Abc_NtkDelete( pNtk ); } @@ -783,6 +1024,7 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Ntk_t * pNtk, * pNtkRes; int c; int fAllNodes; + int fCleanup; pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); @@ -790,14 +1032,18 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fAllNodes = 0; + fCleanup = 1; util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "ah" ) ) != EOF ) + while ( ( c = util_getopt( argc, argv, "ach" ) ) != EOF ) { switch ( c ) { case 'a': fAllNodes ^= 1; break; + case 'c': + fCleanup ^= 1; + break; case 'h': goto usage; default: @@ -812,7 +1058,7 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) } // get the new network - pNtkRes = Abc_NtkStrash( pNtk, fAllNodes ); + pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup ); if ( pNtkRes == NULL ) { fprintf( pErr, "Strashing has failed.\n" ); @@ -823,9 +1069,10 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: strash [-ah]\n" ); + fprintf( pErr, "usage: strash [-ach]\n" ); fprintf( pErr, "\t transforms combinational logic into an AIG\n" ); fprintf( pErr, "\t-a : toggles between using all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "DFS" ); + fprintf( pErr, "\t-c : toggles cleanup to remove the dagling AIG nodes [default = %s]\n", fCleanup? "all": "DFS" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; } @@ -882,7 +1129,7 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv ) } else { - pNtkTemp = Abc_NtkStrash( pNtk, 0 ); + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0 ); if ( pNtkTemp == NULL ) { fprintf( pErr, "Strashing before balancing has failed.\n" ); @@ -1274,7 +1521,7 @@ int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv ) // get the new network if ( !Abc_NtkIsStrash(pNtk) ) { - pNtkNew = Abc_NtkStrash( pNtk, 0 ); + pNtkNew = Abc_NtkStrash( pNtk, 0, 0 ); pNtkRes = Abc_NtkDsdGlobal( pNtkNew, fVerbose, fPrint, fShort ); Abc_NtkDelete( pNtkNew ); } @@ -1732,7 +1979,7 @@ int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv ) // get the new network if ( !Abc_NtkIsStrash(pNtk) ) { - pNtkTemp = Abc_NtkStrash( pNtk, 0 ); + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0 ); pNtkRes = Abc_NtkFrames( pNtkTemp, nFrames, fInitial ); Abc_NtkDelete( pNtkTemp ); } @@ -2424,7 +2671,7 @@ int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes ); else { - pNtk = Abc_NtkStrash( pNtk, 0 ); + pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes ); pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes ); Abc_NtkDelete( pNtk ); } @@ -2845,7 +3092,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( !Abc_NtkIsStrash(pNtk) ) { - pNtk = Abc_NtkStrash( pNtk, 0 ); + pNtk = Abc_NtkStrash( pNtk, 0, 0 ); if ( pNtk == NULL ) { fprintf( pErr, "Strashing before mapping has failed.\n" ); @@ -3087,8 +3334,10 @@ int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: fprintf( pErr, "usage: sc [-h]\n" ); - fprintf( pErr, "\t performs superchoicing\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t performs superchoicing\n" ); + fprintf( pErr, "\t (accumulate: \"r file.blif; rsup; b; sc; f -ac; wb file_sc.blif\")\n" ); + fprintf( pErr, "\t (map without supergate library: \"r file_sc.blif; ft; map\")\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); return 1; } @@ -3146,7 +3395,7 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( !Abc_NtkIsStrash(pNtk) ) { // strash and balance the network - pNtk = Abc_NtkStrash( pNtk, 0 ); + pNtk = Abc_NtkStrash( pNtk, 0, 0 ); if ( pNtk == NULL ) { fprintf( pErr, "Strashing before FPGA mapping has failed.\n" ); diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index a3f7ddb7..ab457cc9 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -51,7 +51,7 @@ typedef enum { ABC_TYPE_OTHER // 5: unused } Abc_NtkType_t; -// functionality types +// network functionality typedef enum { ABC_FUNC_NONE, // 0: unknown ABC_FUNC_SOP, // 1: sum-of-products @@ -155,13 +155,16 @@ struct Abc_Ntk_t_ int nPos; // the number of primary outputs // the functionality manager void * pManFunc; // AIG manager, BDD manager, or memory manager for SOPs + // the global functions (BDDs) + void * pManGlob; // the BDD manager + Vec_Ptr_t * vFuncsGlob; // the BDDs of CO functions // the timing manager (for mapped networks) Abc_ManTime_t * pManTime; // stores arrival/required times for all nodes // the cut manager (for AIGs) void * pManCut; // stores information about the cuts computed for the nodes // level information (for AIGs) int LevelMax; // maximum number of levels - Vec_Int_t * vLevelsR; // level in the reverse topological order + Vec_Int_t * vLevelsR; // level in the reverse topological order // the external don't-care if given Abc_Ntk_t * pExdc; // the EXDC network // miscellaneous data members @@ -401,8 +404,11 @@ extern void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld extern bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode ); extern bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode ); extern void Abc_AigPrintNode( Abc_Obj_t * pNode ); +extern bool Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot ); /*=== abcAttach.c ==========================================================*/ extern int Abc_NtkAttach( Abc_Ntk_t * pNtk ); +/*=== abcBalance.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate ); /*=== abcCheck.c ==========================================================*/ extern bool Abc_NtkCheck( Abc_Ntk_t * pNtk ); extern bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ); @@ -410,7 +416,7 @@ extern bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * /*=== abcCollapse.c ==========================================================*/ extern Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fVerbose ); extern DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fLatchOnly ); -extern void Abc_NtkFreeGlobalBdds( DdManager * dd, Abc_Ntk_t * pNtk ); +extern void Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk ); /*=== abcCreate.c ==========================================================*/ extern Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func ); extern Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ); @@ -475,6 +481,7 @@ extern char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager extern int Abc_NtkBddToSop( Abc_Ntk_t * pNtk ); extern void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, char ** ppSop0, char ** ppSop1 ); extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ); +extern void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ); /*=== abcLatch.c ==========================================================*/ extern bool Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch ); extern int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk ); @@ -519,13 +526,15 @@ extern void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode ) extern void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile ); extern void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ); /*=== abcReconv.c ==========================================================*/ -extern Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax ); +extern Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ); extern void Abc_NtkManCutStop( Abc_ManCut_t * p ); -extern Vec_Ptr_t * Abc_NtkManCutReadLeaves( Abc_ManCut_t * p ); +extern Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p ); +extern Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p ); extern Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, bool fContain ); +extern void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited, int fIncludeFanins ); extern DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited ); extern DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited ); -extern void Abc_NodeCollectTfoCands( Abc_Ntk_t * pNtk, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, int LevelMax, Vec_Vec_t * vLevels, Vec_Ptr_t * vResult ); +extern Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, int LevelMax ); /*=== abcRefs.c ==========================================================*/ extern int Abc_NodeMffcSize( Abc_Obj_t * pNode ); extern int Abc_NodeMffcLabel( Abc_Obj_t * pNode ); @@ -576,12 +585,11 @@ extern bool Abc_SopCheck( char * pSop, int nFanins ); extern void Abc_SopWriteCnf( FILE * pFile, char * pClauses, Vec_Int_t * vVars ); extern void Abc_SopAddCnfToSolver( solver * pSat, char * pClauses, Vec_Int_t * vVars, Vec_Int_t * vTemp ); /*=== abcStrash.c ==========================================================*/ -extern Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes ); +extern Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup ); extern Abc_Obj_t * Abc_NodeStrash( Abc_Aig_t * pMan, Abc_Obj_t * pNode ); extern Abc_Obj_t * Abc_NodeStrashDec( Abc_Aig_t * pMan, Vec_Ptr_t * vFanins, Vec_Int_t * vForm ); extern int Abc_NodeStrashDecCount( Abc_Aig_t * pMan, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, Vec_Int_t * vForm, Vec_Int_t * vLevels, int NodeMax, int LevelMax ); extern int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ); -extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate ); /*=== abcSweep.c ==========================================================*/ extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose ); extern int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ); @@ -643,6 +651,7 @@ extern char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollect extern void Abc_NtkAlphaOrderSignals( Abc_Ntk_t * pNtk, int fComb ); extern void Abc_NtkShortNames( Abc_Ntk_t * pNtk ); extern Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk ); //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/base/abc/abcAig.c b/src/base/abc/abcAig.c index f71c0a15..9588f1e0 100644 --- a/src/base/abc/abcAig.c +++ b/src/base/abc/abcAig.c @@ -705,8 +705,10 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan ) assert( iFanin == 0 || iFanin == 1 ); // get the new fanin pFanin1 = Abc_ObjNotCond( pNew, Abc_ObjFaninC(pFanout, iFanin) ); + assert( Abc_ObjRegular(pFanin1) != pFanout ); // get another fanin pFanin2 = Abc_ObjChild( pFanout, iFanin ^ 1 ); + assert( Abc_ObjRegular(pFanin2) != pFanout ); // check if the node with these fanins exists if ( pFanoutNew = Abc_AigAndLookup( pMan, pFanin1, pFanin2 ) ) { // such node exists (it may be a constant) @@ -732,6 +734,7 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan ) Abc_ObjRemoveFanins( pFanout ); // recreate the old fanout with new fanins and add it to the table Abc_AigAndCreateFrom( pMan, pFanin1, pFanin2, pFanout ); + assert( Abc_AigNodeIsAcyclic(pFanout, pFanout) ); // schedule the updated fanout for updating direct level assert( pFanout->fMarkA == 0 ); @@ -876,6 +879,7 @@ void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan ) if ( pNode == NULL ) continue; assert( Abc_ObjIsNode(pNode) ); + assert( (int)pNode->Level == i ); // clean the mark assert( pNode->fMarkA == 1 ); pNode->fMarkA = 0; @@ -931,6 +935,7 @@ void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan ) if ( pNode == NULL ) continue; assert( Abc_ObjIsNode(pNode) ); + assert( Abc_NodeReadReverseLevel(pNode) == i ); // clean the mark assert( pNode->fMarkB == 1 ); pNode->fMarkB = 0; @@ -1113,6 +1118,56 @@ void Abc_AigPrintNode( Abc_Obj_t * pNode ) printf( "\n" ); } + +/**Function************************************************************* + + Synopsis [Check if the node has a combination loop of depth 1 or 2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot ) +{ + Abc_Obj_t * pFanin0, * pFanin1; + Abc_Obj_t * pChild00, * pChild01; + Abc_Obj_t * pChild10, * pChild11; + if ( !Abc_NodeIsAigAnd(pNode) ) + return 1; + pFanin0 = Abc_ObjFanin0(pNode); + pFanin1 = Abc_ObjFanin1(pNode); + if ( pRoot == pFanin0 || pRoot == pFanin1 ) + return 0; + if ( Abc_ObjIsCi(pFanin0) ) + { + pChild00 = NULL; + pChild01 = NULL; + } + else + { + pChild00 = Abc_ObjFanin0(pFanin0); + pChild01 = Abc_ObjFanin1(pFanin0); + if ( pRoot == pChild00 || pRoot == pChild01 ) + return 0; + } + if ( Abc_ObjIsCi(pFanin1) ) + { + pChild10 = NULL; + pChild11 = NULL; + } + else + { + pChild10 = Abc_ObjFanin0(pFanin1); + pChild11 = Abc_ObjFanin1(pFanin1); + if ( pRoot == pChild10 || pRoot == pChild11 ) + return 0; + } + return 1; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/abcCollapse.c b/src/base/abc/abcCollapse.c index e07636cc..a6eda7b3 100644 --- a/src/base/abc/abcCollapse.c +++ b/src/base/abc/abcCollapse.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// static DdNode * Abc_NtkGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode ); -static Abc_Ntk_t * Abc_NtkFromGlobalBdds( DdManager * dd, Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ); static Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc ); //////////////////////////////////////////////////////////////////////// @@ -47,26 +47,26 @@ Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fVerbose ) { int fCheck = 1; Abc_Ntk_t * pNtkNew; - DdManager * dd; assert( Abc_NtkIsStrash(pNtk) ); // compute the global BDDs - dd = Abc_NtkGlobalBdds( pNtk, 0 ); - if ( dd == NULL ) + if ( Abc_NtkGlobalBdds(pNtk, 0) == NULL ) return NULL; if ( fVerbose ) - printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(pNtk->pManGlob) - Cudd_ReadDead(pNtk->pManGlob) ); // create the new network - pNtkNew = Abc_NtkFromGlobalBdds( dd, pNtk ); - Abc_NtkFreeGlobalBdds( dd, pNtk ); + pNtkNew = Abc_NtkFromGlobalBdds( pNtk ); + Abc_NtkFreeGlobalBdds( pNtk ); if ( pNtkNew == NULL ) { - Cudd_Quit( dd ); + Cudd_Quit( pNtk->pManGlob ); + pNtk->pManGlob = NULL; return NULL; } - Extra_StopManager( dd ); + Extra_StopManager( pNtk->pManGlob ); + pNtk->pManGlob = NULL; // make the network minimum base Abc_NtkMinimumBase( pNtkNew ); @@ -96,12 +96,14 @@ DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fLatchOnly ) { int fReorder = 1; ProgressBar * pProgress; + Vec_Ptr_t * vFuncsGlob; Abc_Obj_t * pNode; DdNode * bFunc; DdManager * dd; int i; // start the manager + assert( pNtk->pManGlob == NULL ); dd = Cudd_Init( Abc_NtkCiNum(pNtk), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); if ( fReorder ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); @@ -114,6 +116,7 @@ DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fLatchOnly ) pNode = Abc_AigConst1( pNtk->pManFunc ); pNode->pCopy = (Abc_Obj_t *)dd->one; Cudd_Ref( dd->one ); + vFuncsGlob = Vec_PtrAlloc( 100 ); if ( fLatchOnly ) { // construct the BDDs @@ -129,8 +132,8 @@ DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fLatchOnly ) Cudd_Quit( dd ); return NULL; } - bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pNode) ); - pNode->pNext = (Abc_Obj_t *)bFunc; Cudd_Ref( bFunc ); + bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pNode) ); Cudd_Ref( bFunc ); + Vec_PtrPush( vFuncsGlob, bFunc ); } Extra_ProgressBarStop( pProgress ); } @@ -149,8 +152,8 @@ DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fLatchOnly ) Cudd_Quit( dd ); return NULL; } - bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pNode) ); - pNode->pNext = (Abc_Obj_t *)bFunc; Cudd_Ref( bFunc ); + bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pNode) ); Cudd_Ref( bFunc ); + Vec_PtrPush( vFuncsGlob, bFunc ); } Extra_ProgressBarStop( pProgress ); } @@ -168,6 +171,8 @@ DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fLatchOnly ) Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); Cudd_AutodynDisable( dd ); } + pNtk->pManGlob = dd; + pNtk->vFuncsGlob = vFuncsGlob; return dd; } @@ -223,11 +228,12 @@ DdNode * Abc_NtkGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromGlobalBdds( DdManager * dd, Abc_Ntk_t * pNtk ) +Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pNode, * pNodeNew; + DdManager * dd = pNtk->pManGlob; int i; // start the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_BDD ); @@ -238,7 +244,7 @@ Abc_Ntk_t * Abc_NtkFromGlobalBdds( DdManager * dd, Abc_Ntk_t * pNtk ) Abc_NtkForEachCo( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); - pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, (DdNode *)pNode->pNext ); + pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Vec_PtrEntry(pNtk->vFuncsGlob, i) ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); } Extra_ProgressBarStop( pProgress ); @@ -281,17 +287,16 @@ Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode SeeAlso [] ***********************************************************************/ -void Abc_NtkFreeGlobalBdds( DdManager * dd, Abc_Ntk_t * pNtk ) +void Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk ) { - Abc_Obj_t * pNode; + DdNode * bFunc; int i; - Abc_NtkForEachCo( pNtk, pNode, i ) - { - if ( pNode->pNext == NULL ) - continue; - Cudd_RecursiveDeref( dd, (DdNode *)pNode->pNext ); - pNode->pNext = NULL; - } + assert( pNtk->pManGlob ); + assert( pNtk->vFuncsGlob ); + Vec_PtrForEachEntry( pNtk->vFuncsGlob, bFunc, i ) + Cudd_RecursiveDeref( pNtk->pManGlob, bFunc ); + Vec_PtrFree( pNtk->vFuncsGlob ); + pNtk->vFuncsGlob = NULL; } diff --git a/src/base/abc/abcCreate.c b/src/base/abc/abcCreate.c index 9186ec5a..d6500803 100644 --- a/src/base/abc/abcCreate.c +++ b/src/base/abc/abcCreate.c @@ -818,7 +818,7 @@ Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ) // find the internal node if ( pName[0] != '[' || pName[strlen(pName)-1] != ']' ) { - printf( "Node \"%s\" has non-standard name (expected name is \"[integer]\").\n", pName ); + printf( "Name \"%s\" is not found among CIs/COs (internal name looks like this: \"[integer]\").\n", pName ); return NULL; } Num = atoi( pName + 1 ); diff --git a/src/base/abc/abcDsd.c b/src/base/abc/abcDsd.c index d1445e75..ccb52ffa 100644 --- a/src/base/abc/abcDsd.c +++ b/src/base/abc/abcDsd.c @@ -25,8 +25,7 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static Abc_Ntk_t * Abc_NtkDsdInternal( DdManager * dd, Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ); -static Dsd_Manager_t * Abc_NtkDsdPerform( DdManager * dd, Abc_Ntk_t * pNtk, bool fVerbose ); +static Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ); static void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); static Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew ); @@ -58,25 +57,25 @@ Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool { int fCheck = 1; Abc_Ntk_t * pNtkNew; - DdManager * dd; assert( Abc_NtkIsStrash(pNtk) ); // perform FPGA mapping - dd = Abc_NtkGlobalBdds( pNtk, 0 ); - if ( dd == NULL ) + if ( Abc_NtkGlobalBdds(pNtk, 0) == NULL ) return NULL; if ( fVerbose ) - printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(pNtk->pManGlob) - Cudd_ReadDead(pNtk->pManGlob) ); // transform the result of mapping into a BDD network - pNtkNew = Abc_NtkDsdInternal( dd, pNtk, fVerbose, fPrint, fShort ); + pNtkNew = Abc_NtkDsdInternal( pNtk, fVerbose, fPrint, fShort ); if ( pNtkNew == NULL ) { - Cudd_Quit( dd ); + Cudd_Quit( pNtk->pManGlob ); + pNtk->pManGlob = NULL; return NULL; } - Extra_StopManager( dd ); + Extra_StopManager( pNtk->pManGlob ); + pNtk->pManGlob = NULL; // make sure that everything is okay if ( fCheck && !Abc_NtkCheck( pNtkNew ) ) @@ -99,17 +98,33 @@ Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkDsdInternal( DdManager * dd, Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ) +Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ) { + DdManager * dd = pNtk->pManGlob; Dsd_Manager_t * pManDsd; Abc_Ntk_t * pNtkNew; + DdNode * bFunc; char ** ppNamesCi, ** ppNamesCo; + Abc_Obj_t * pObj; + int i; + + // complement the global functions + Abc_NtkForEachCo( pNtk, pObj, i ) + { + bFunc = Vec_PtrEntry(pNtk->vFuncsGlob, i); + Vec_PtrWriteEntry(pNtk->vFuncsGlob, i, Cudd_NotCond(bFunc, Abc_ObjFaninC0(pObj)) ); + } // perform the decomposition - pManDsd = Abc_NtkDsdPerform( dd, pNtk, fVerbose ); - Abc_NtkFreeGlobalBdds( dd, pNtk ); + assert( Vec_PtrSize(pNtk->vFuncsGlob) == Abc_NtkCoNum(pNtk) ); + pManDsd = Dsd_ManagerStart( dd, Abc_NtkCiNum(pNtk), fVerbose ); + Dsd_Decompose( pManDsd, (DdNode **)pNtk->vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) ); + Abc_NtkFreeGlobalBdds( pNtk ); if ( pManDsd == NULL ) + { + Cudd_Quit( dd ); return NULL; + } // start the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_BDD ); @@ -119,6 +134,8 @@ Abc_Ntk_t * Abc_NtkDsdInternal( DdManager * dd, Abc_Ntk_t * pNtk, bool fVerbose, Abc_NtkDsdConstruct( pManDsd, pNtk, pNtkNew ); // finalize the new network Abc_NtkFinalize( pNtk, pNtkNew ); + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); if ( fPrint ) { @@ -136,39 +153,6 @@ Abc_Ntk_t * Abc_NtkDsdInternal( DdManager * dd, Abc_Ntk_t * pNtk, bool fVerbose, /**Function************************************************************* - Synopsis [Performs DSD by creating the manager and decomposing the functions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Manager_t * Abc_NtkDsdPerform( DdManager * dd, Abc_Ntk_t * pNtk, bool fVerbose ) -{ - Dsd_Manager_t * pManDsd; - DdNode ** pbFuncsGlo; - Abc_Obj_t * pNode; - int i; - - // collect global functions into the array - pbFuncsGlo = ALLOC( DdNode *, Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - pbFuncsGlo[i] = Cudd_NotCond( pNode->pNext, Abc_ObjFaninC0(pNode) ); -//printf( "Output %3d : Support size = %3d. Nodes = %5d.\n", i, Cudd_SupportSize(dd, pbFuncsGlo[i]), Cudd_DagSize(pbFuncsGlo[i]) ); - } - - // start the DSD manager and decompose global functions - pManDsd = Dsd_ManagerStart( dd, Abc_NtkCiNum(pNtk), fVerbose ); - Dsd_Decompose( pManDsd, pbFuncsGlo, Abc_NtkCoNum(pNtk) ); - FREE( pbFuncsGlo ); - return pManDsd; -} - -/**Function************************************************************* - Synopsis [Constructs the decomposed network.] Description [] diff --git a/src/base/abc/abcFraig.c b/src/base/abc/abcFraig.c index bb7d8cfa..83735e47 100644 --- a/src/base/abc/abcFraig.c +++ b/src/base/abc/abcFraig.c @@ -433,7 +433,7 @@ int Abc_NtkFraigStore( Abc_Ntk_t * pNtk ) if ( pStore == NULL ) { // start the stored network - pStore = Abc_NtkStrash( pNtk, 0 ); + pStore = Abc_NtkStrash( pNtk, 0, 0 ); if ( pStore == NULL ) { printf( "Abc_NtkFraigStore: Initial strashing has failed.\n" ); diff --git a/src/base/abc/abcFunc.c b/src/base/abc/abcFunc.c index f616a258..44acb699 100644 --- a/src/base/abc/abcFunc.c +++ b/src/base/abc/abcFunc.c @@ -128,6 +128,57 @@ DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop, int nFanins ) return bRes; } +/**Function************************************************************* + + Synopsis [Removes complemented SOP covers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) +{ + DdManager * dd; + DdNode * bFunc; + Vec_Str_t * vCube; + Abc_Obj_t * pNode; + int nFaninsMax, fFound, i; + + assert( Abc_NtkIsSopLogic(pNtk) ); + + // check if there are nodes with complemented SOPs + fFound = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( Abc_SopIsComplement(pNode->pData) ) + { + fFound = 1; + break; + } + if ( !fFound ) + return; + + // start the BDD package + nFaninsMax = Abc_NtkGetFaninMax( pNtk ); + if ( nFaninsMax == 0 ) + printf( "Warning: The network has only constant nodes.\n" ); + dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + // change the cover of negated nodes + vCube = Vec_StrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( Abc_SopIsComplement(pNode->pData) ) + { + bFunc = Abc_ConvertSopToBdd( dd, pNode->pData, Abc_ObjFaninNum(pNode) ); Cudd_Ref( bFunc ); + pNode->pData = Abc_ConvertBddToSop( pNtk->pManFunc, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), vCube, 1 ); + Cudd_RecursiveDeref( dd, bFunc ); + assert( !Abc_SopIsComplement(pNode->pData) ); + } + Vec_StrFree( vCube ); + Extra_StopManager( dd ); +} diff --git a/src/base/abc/abcMiter.c b/src/base/abc/abcMiter.c index b8bcec4d..a0426dc2 100644 --- a/src/base/abc/abcMiter.c +++ b/src/base/abc/abcMiter.c @@ -55,8 +55,8 @@ Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, fComb ) ) return NULL; // make sure the circuits are strashed - fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0)); - fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0)); + fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0)); + fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0)); if ( pNtk1 && pNtk2 ) pTemp = Abc_NtkMiterInt( pNtk1, pNtk2, fComb ); if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); diff --git a/src/base/abc/abcPrint.c b/src/base/abc/abcPrint.c index 337dd43b..c7599f11 100644 --- a/src/base/abc/abcPrint.c +++ b/src/base/abc/abcPrint.c @@ -44,8 +44,8 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) { int Num; - fprintf( pFile, "%-15s:", pNtk->pName ); - fprintf( pFile, " i/o = %4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) ); + fprintf( pFile, "%-13s:", pNtk->pName ); + fprintf( pFile, " i/o = %4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) ); if ( !Abc_NtkIsSeq(pNtk) ) fprintf( pFile, " lat = %4d", Abc_NtkLatchNum(pNtk) ); diff --git a/src/base/abc/abcReconv.c b/src/base/abc/abcReconv.c index e02ccba0..ea662799 100644 --- a/src/base/abc/abcReconv.c +++ b/src/base/abc/abcReconv.c @@ -30,14 +30,19 @@ struct Abc_ManCut_t_ // user specified parameters int nNodeSizeMax; // the limit on the size of the supernode int nConeSizeMax; // the limit on the size of the containing cone + int nNodeFanStop; // the limit on the size of the supernode + int nConeFanStop; // the limit on the size of the containing cone // internal parameters - Vec_Ptr_t * vFaninsNode; // fanins of the supernode - Vec_Ptr_t * vFaninsCone; // fanins of the containing cone + Vec_Ptr_t * vNodeLeaves; // fanins of the collapsed node (the cut) + Vec_Ptr_t * vConeLeaves; // fanins of the containing cone Vec_Ptr_t * vVisited; // the visited nodes + Vec_Vec_t * vLevels; // the data structure to compute TFO nodes + Vec_Ptr_t * vNodesTfo; // the nodes in the TFO of the cut }; -static int Abc_NodeFindCut_int( Vec_Ptr_t * vFanins, int nSizeLimit ); -static void Abc_NodesMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ); +static int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit ); +static int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit ); +static void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFITIONS /// @@ -92,45 +97,142 @@ static inline void Abc_NodesUnmark( Vec_Ptr_t * vVisited ) SeeAlso [] ***********************************************************************/ -static inline void Abc_NodesUnmarkBoth( Vec_Ptr_t * vVisited ) +static inline void Abc_NodesUnmarkB( Vec_Ptr_t * vVisited ) { Abc_Obj_t * pNode; int i; Vec_PtrForEachEntry( vVisited, pNode, i ) - pNode->fMarkA = pNode->fMarkB = 0; + pNode->fMarkB = 0; } /**Function************************************************************* - Synopsis [Evaluate the fanin cost.] + Synopsis [Evaluate the cost of removing the node from the set of leaves.] - Description [Returns the number of fanins that will be brought in. - Returns large number if the node cannot be added.] + Description [Returns the number of new leaves that will be brought in. + Returns large number if the node cannot be removed from the set of leaves.] SideEffects [] SeeAlso [] ***********************************************************************/ -static inline int Abc_NodeGetFaninCost( Abc_Obj_t * pNode ) +static inline int Abc_NodeGetLeafCostOne( Abc_Obj_t * pNode, int nFaninLimit ) { - Abc_Obj_t * pFanout; - int i; - assert( pNode->fMarkA == 1 ); // this node is in the TFI - assert( pNode->fMarkB == 1 ); // this node is in the constructed cone - // check the PI node + int Cost; + // make sure the node is in the construction zone + assert( pNode->fMarkB == 1 ); + // cannot expand over the PI node + if ( Abc_ObjIsCi(pNode) ) + return 999; + // get the cost of the cone + Cost = (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB); + // always accept if the number of leaves does not increase + if ( Cost < 2 ) + return Cost; + // skip nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > nFaninLimit ) + return 999; + // return the number of nodes that will be on the leaves if this node is removed + return Cost; +} + +/**Function************************************************************* + + Synopsis [Evaluate the cost of removing the node from the set of leaves.] + + Description [Returns the number of new leaves that will be brought in. + Returns large number if the node cannot be removed from the set of leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_NodeGetLeafCostTwo( Abc_Obj_t * pNode, int nFaninLimit, + Abc_Obj_t ** ppLeafToAdd, Abc_Obj_t ** pNodeToMark1, Abc_Obj_t ** pNodeToMark2 ) +{ + Abc_Obj_t * pFanin0, * pFanin1, * pTemp; + Abc_Obj_t * pGrand, * pGrandToAdd; + // make sure the node is in the construction zone + assert( pNode->fMarkB == 1 ); + // cannot expand over the PI node if ( Abc_ObjIsCi(pNode) ) return 999; // skip nodes with many fanouts - if ( Abc_ObjFanoutNum(pNode) > 5 ) +// if ( Abc_ObjFanoutNum(pNode) > nFaninLimit ) +// return 999; + // get the children + pFanin0 = Abc_ObjFanin0(pNode); + pFanin1 = Abc_ObjFanin1(pNode); + assert( !pFanin0->fMarkB && !pFanin1->fMarkB ); + // count the number of unique grandchildren that will be included + // return infinite cost if this number if more than 1 + if ( Abc_ObjIsCi(pFanin0) && Abc_ObjIsCi(pFanin1) ) return 999; - // check the fanouts - Abc_ObjForEachFanout( pNode, pFanout, i ) - if ( pFanout->fMarkA && pFanout->fMarkB == 0 ) // the fanout is in the TFI but not in the cone + // consider the special case when a non-CI fanin can be dropped + if ( !Abc_ObjIsCi(pFanin0) && Abc_ObjFanin0(pFanin0)->fMarkB && Abc_ObjFanin1(pFanin0)->fMarkB ) + { + *ppLeafToAdd = pFanin1; + *pNodeToMark1 = pFanin0; + *pNodeToMark2 = NULL; + return 1; + } + if ( !Abc_ObjIsCi(pFanin1) && Abc_ObjFanin0(pFanin1)->fMarkB && Abc_ObjFanin1(pFanin1)->fMarkB ) + { + *ppLeafToAdd = pFanin0; + *pNodeToMark1 = pFanin1; + *pNodeToMark2 = NULL; + return 1; + } + + // make the first node CI if any + if ( Abc_ObjIsCi(pFanin1) ) + pTemp = pFanin0, pFanin0 = pFanin1, pFanin1 = pTemp; + // consider the first node + pGrandToAdd = NULL; + if ( Abc_ObjIsCi(pFanin0) ) + { + *pNodeToMark1 = NULL; + pGrandToAdd = pFanin0; + } + else + { + *pNodeToMark1 = pFanin0; + pGrand = Abc_ObjFanin0(pFanin0); + if ( !pGrand->fMarkB ) + { + if ( pGrandToAdd && pGrandToAdd != pGrand ) + return 999; + pGrandToAdd = pGrand; + } + pGrand = Abc_ObjFanin1(pFanin0); + if ( !pGrand->fMarkB ) + { + if ( pGrandToAdd && pGrandToAdd != pGrand ) + return 999; + pGrandToAdd = pGrand; + } + } + // consider the second node + *pNodeToMark2 = pFanin1; + pGrand = Abc_ObjFanin0(pFanin1); + if ( !pGrand->fMarkB ) + { + if ( pGrandToAdd && pGrandToAdd != pGrand ) + return 999; + pGrandToAdd = pGrand; + } + pGrand = Abc_ObjFanin1(pFanin1); + if ( !pGrand->fMarkB ) + { + if ( pGrandToAdd && pGrandToAdd != pGrand ) return 999; - // the fanouts are in the TFI and inside the constructed cone - // return the number of fanins that will be on the boundary if this node is added - return (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB); + pGrandToAdd = pGrand; + } + assert( pGrandToAdd != NULL ); + *ppLeafToAdd = pGrandToAdd; + return 1; } @@ -153,117 +255,206 @@ Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, bool fContain assert( !Abc_ObjIsComplement(pRoot) ); assert( Abc_ObjIsNode(pRoot) ); - // mark TFI using fMarkA + // start the visited nodes and mark them Vec_PtrClear( p->vVisited ); - Abc_NodesMarkCollect_rec( pRoot, p->vVisited ); - - // start the cut - Vec_PtrClear( p->vFaninsNode ); - Vec_PtrPush( p->vFaninsNode, Abc_ObjFanin0(pRoot) ); - Vec_PtrPush( p->vFaninsNode, Abc_ObjFanin1(pRoot) ); + Vec_PtrPush( p->vVisited, pRoot ); + Vec_PtrPush( p->vVisited, Abc_ObjFanin0(pRoot) ); + Vec_PtrPush( p->vVisited, Abc_ObjFanin1(pRoot) ); pRoot->fMarkB = 1; Abc_ObjFanin0(pRoot)->fMarkB = 1; Abc_ObjFanin1(pRoot)->fMarkB = 1; + // start the cut + Vec_PtrClear( p->vNodeLeaves ); + Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin0(pRoot) ); + Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin1(pRoot) ); + // compute the cut - while ( Abc_NodeFindCut_int( p->vFaninsNode, p->nNodeSizeMax ) ); - assert( Vec_PtrSize(p->vFaninsNode) <= p->nNodeSizeMax ); + while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vNodeLeaves, p->nNodeSizeMax, p->nNodeFanStop ) ); + assert( Vec_PtrSize(p->vNodeLeaves) <= p->nNodeSizeMax ); // return if containing cut is not requested if ( !fContain ) { - // unmark TFI using fMarkA and fMarkB - Abc_NodesUnmarkBoth( p->vVisited ); - return p->vFaninsNode; + // unmark both fMarkA and fMarkB in tbe TFI + Abc_NodesUnmarkB( p->vVisited ); + return p->vNodeLeaves; } +//printf( "\n\n\n" ); // compute the containing cut assert( p->nNodeSizeMax < p->nConeSizeMax ); // copy the current boundary - Vec_PtrClear( p->vFaninsCone ); - Vec_PtrForEachEntry( p->vFaninsNode, pNode, i ) - Vec_PtrPush( p->vFaninsCone, pNode ); + Vec_PtrClear( p->vConeLeaves ); + Vec_PtrForEachEntry( p->vNodeLeaves, pNode, i ) + Vec_PtrPush( p->vConeLeaves, pNode ); // compute the containing cut - while ( Abc_NodeFindCut_int( p->vFaninsCone, p->nConeSizeMax ) ); - assert( Vec_PtrSize(p->vFaninsCone) <= p->nConeSizeMax ); + while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vConeLeaves, p->nConeSizeMax, p->nConeFanStop ) ); + assert( Vec_PtrSize(p->vConeLeaves) <= p->nConeSizeMax ); // unmark TFI using fMarkA and fMarkB - Abc_NodesUnmarkBoth( p->vVisited ); - return p->vFaninsNode; + Abc_NodesUnmarkB( p->vVisited ); + return p->vNodeLeaves; } /**Function************************************************************* - Synopsis [Finds a reconvergence-driven cut.] + Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] - Description [] + Description [This procedure looks at the current leaves and tries to change + one leaf at a time in such a way that the cut grows as little as possible. + In evaluating the fanins, this procedure looks only at their immediate + predecessors (this is why it is called a one-level construction procedure).] SideEffects [] SeeAlso [] ***********************************************************************/ -int Abc_NodeFindCut_int( Vec_Ptr_t * vFanins, int nSizeLimit ) +int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit ) { Abc_Obj_t * pNode, * pFaninBest, * pNext; int CostBest, CostCur, i; -// int fFlagProb = (rand() & 1); - int fFlagProb = 1; // find the best fanin CostBest = 100; pFaninBest = NULL; - if ( fFlagProb ) - { - Vec_PtrForEachEntry( vFanins, pNode, i ) - { - CostCur = Abc_NodeGetFaninCost( pNode ); - if ( CostBest > CostCur ) - { - CostBest = CostCur; - pFaninBest = pNode; - } - } - } - else +//printf( "Evaluating fanins of the cut:\n" ); + Vec_PtrForEachEntry( vLeaves, pNode, i ) { - Vec_PtrForEachEntry( vFanins, pNode, i ) + CostCur = Abc_NodeGetLeafCostOne( pNode, nFaninLimit ); +//printf( " Fanin %s has cost %d.\n", Abc_ObjName(pNode), CostCur ); + if ( CostBest > CostCur ) { - CostCur = Abc_NodeGetFaninCost( pNode ); - if ( CostBest >= CostCur ) - { - CostBest = CostCur; - pFaninBest = pNode; - } + CostBest = CostCur; + pFaninBest = pNode; } + if ( CostBest == 0 ) + break; } if ( pFaninBest == NULL ) return 0; +// return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit ); + assert( CostBest < 3 ); - if ( vFanins->nSize - 1 + CostBest > nSizeLimit ) + if ( vLeaves->nSize - 1 + CostBest > nSizeLimit ) return 0; +// return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit ); + assert( Abc_ObjIsNode(pFaninBest) ); // remove the node from the array - Vec_PtrRemove( vFanins, pFaninBest ); + Vec_PtrRemove( vLeaves, pFaninBest ); +//printf( "Removing fanin %s.\n", Abc_ObjName(pFaninBest) ); + // add the left child to the fanins pNext = Abc_ObjFanin0(pFaninBest); if ( !pNext->fMarkB ) { +//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) ); pNext->fMarkB = 1; - Vec_PtrPush( vFanins, pNext ); + Vec_PtrPush( vLeaves, pNext ); + Vec_PtrPush( vVisited, pNext ); } // add the right child to the fanins pNext = Abc_ObjFanin1(pFaninBest); if ( !pNext->fMarkB ) { +//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) ); pNext->fMarkB = 1; - Vec_PtrPush( vFanins, pNext ); + Vec_PtrPush( vLeaves, pNext ); + Vec_PtrPush( vVisited, pNext ); } - assert( vFanins->nSize <= nSizeLimit ); + assert( vLeaves->nSize <= nSizeLimit ); // keep doing this return 1; } /**Function************************************************************* + Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] + + Description [This procedure looks at the current leaves and tries to change + one leaf at a time in such a way that the cut grows as little as possible. + In evaluating the fanins, this procedure looks across two levels of fanins + (this is why it is called a two-level construction procedure).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit ) +{ + Abc_Obj_t * pNode, * pLeafToAdd, * pNodeToMark1, * pNodeToMark2; + int CostCur, i; + // find the best fanin + Vec_PtrForEachEntry( vLeaves, pNode, i ) + { + CostCur = Abc_NodeGetLeafCostTwo( pNode, nFaninLimit, &pLeafToAdd, &pNodeToMark1, &pNodeToMark2 ); + if ( CostCur < 2 ) + break; + } + if ( CostCur > 2 ) + return 0; + // remove the node from the array + Vec_PtrRemove( vLeaves, pNode ); + // add the node to the leaves + if ( pLeafToAdd ) + { + assert( !pLeafToAdd->fMarkB ); + pLeafToAdd->fMarkB = 1; + Vec_PtrPush( vLeaves, pLeafToAdd ); + Vec_PtrPush( vVisited, pLeafToAdd ); + } + // mark the other nodes + if ( pNodeToMark1 ) + { + assert( !pNodeToMark1->fMarkB ); + pNodeToMark1->fMarkB = 1; + Vec_PtrPush( vVisited, pNodeToMark1 ); + } + if ( pNodeToMark2 ) + { + assert( !pNodeToMark2->fMarkB ); + pNodeToMark2->fMarkB = 1; + Vec_PtrPush( vVisited, pNodeToMark2 ); + } + // keep doing this + return 1; +} + + +/**Function************************************************************* + + Synopsis [Get the nodes contained in the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited, int fIncludeFanins ) +{ + Abc_Obj_t * pTemp; + int i; + // mark the fanins of the cone + Abc_NodesMark( vLeaves ); + // collect the nodes in the DFS order + Vec_PtrClear( vVisited ); + // add the fanins + if ( fIncludeFanins ) + Vec_PtrForEachEntry( vLeaves, pTemp, i ) + Vec_PtrPush( vVisited, pTemp ); + // add other nodes + for ( i = 0; i < nRoots; i++ ) + Abc_NodeConeMarkCollect_rec( ppRoots[i], vVisited ); + // unmark both sets + Abc_NodesUnmark( vLeaves ); + Abc_NodesUnmark( vVisited ); +} + +/**Function************************************************************* + Synopsis [Marks the TFI cone.] Description [] @@ -273,22 +464,21 @@ int Abc_NodeFindCut_int( Vec_Ptr_t * vFanins, int nSizeLimit ) SeeAlso [] ***********************************************************************/ -void Abc_NodesMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ) +void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ) { if ( pNode->fMarkA == 1 ) return; // visit transitive fanin if ( Abc_ObjIsNode(pNode) ) { - Abc_NodesMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited ); - Abc_NodesMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited ); + Abc_NodeConeMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited ); + Abc_NodeConeMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited ); } assert( pNode->fMarkA == 0 ); pNode->fMarkA = 1; Vec_PtrPush( vVisited, pNode ); } - /**Function************************************************************* Synopsis [Returns BDD representing the logic function of the cone.] @@ -300,20 +490,14 @@ void Abc_NodesMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ) SeeAlso [] ***********************************************************************/ -DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited ) +DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited ) { DdNode * bFunc0, * bFunc1, * bFunc; int i; - // mark the fanins of the cone - Abc_NodesMark( vFanins ); - // collect the nodes in the DFS order - Vec_PtrClear( vVisited ); - Abc_NodesMarkCollect_rec( pNode, vVisited ); - // unmark both sets - Abc_NodesUnmark( vFanins ); - Abc_NodesUnmark( vVisited ); + // get the nodes in the cut without fanins in the DFS order + Abc_NodeConeCollect( &pNode, 1, vLeaves, vVisited, 0 ); // set the elementary BDDs - Vec_PtrForEachEntry( vFanins, pNode, i ) + Vec_PtrForEachEntry( vLeaves, pNode, i ) pNode->pCopy = (Abc_Obj_t *)pbVars[i]; // compute the BDDs for the collected nodes Vec_PtrForEachEntry( vVisited, pNode, i ) @@ -347,15 +531,8 @@ DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, DdNode * bFunc0, * bFunc1, * bFunc, * bTrans, * bTemp, * bCube, * bResult; Abc_Obj_t * pNode; int i; - // mark the fanins of the cone - Abc_NodesMark( vLeaves ); - // collect the nodes in the DFS order - Vec_PtrClear( vVisited ); - Vec_PtrForEachEntry( vRoots, pNode, i ) - Abc_NodesMarkCollect_rec( pNode, vVisited ); - // unmark both sets - Abc_NodesUnmark( vLeaves ); - Abc_NodesUnmark( vVisited ); + // get the nodes in the cut without fanins in the DFS order + Abc_NodeConeCollect( (Abc_Obj_t **)vRoots->pArray, vRoots->nSize, vLeaves, vVisited, 0 ); // set the elementary BDDs Vec_PtrForEachEntry( vLeaves, pNode, i ) pNode->pCopy = (Abc_Obj_t *)pbVarsX[i]; @@ -400,16 +577,20 @@ DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, SeeAlso [] ***********************************************************************/ -Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax ) +Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ) { Abc_ManCut_t * p; p = ALLOC( Abc_ManCut_t, 1 ); memset( p, 0, sizeof(Abc_ManCut_t) ); - p->vFaninsNode = Vec_PtrAlloc( 100 ); - p->vFaninsCone = Vec_PtrAlloc( 100 ); + p->vNodeLeaves = Vec_PtrAlloc( 100 ); + p->vConeLeaves = Vec_PtrAlloc( 100 ); p->vVisited = Vec_PtrAlloc( 100 ); + p->vLevels = Vec_VecAlloc( 100 ); + p->vNodesTfo = Vec_PtrAlloc( 100 ); p->nNodeSizeMax = nNodeSizeMax; p->nConeSizeMax = nConeSizeMax; + p->nNodeFanStop = nNodeFanStop; + p->nConeFanStop = nConeFanStop; return p; } @@ -426,9 +607,11 @@ Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax ) ***********************************************************************/ void Abc_NtkManCutStop( Abc_ManCut_t * p ) { - Vec_PtrFree( p->vFaninsNode ); - Vec_PtrFree( p->vFaninsCone ); + Vec_PtrFree( p->vNodeLeaves ); + Vec_PtrFree( p->vConeLeaves ); Vec_PtrFree( p->vVisited ); + Vec_VecFree( p->vLevels ); + Vec_PtrFree( p->vNodesTfo ); free( p ); } @@ -443,9 +626,25 @@ void Abc_NtkManCutStop( Abc_ManCut_t * p ) SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Abc_NtkManCutReadLeaves( Abc_ManCut_t * p ) +Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p ) +{ + return p->vConeLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the leaves of the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p ) { - return p->vFaninsCone; + return p->vVisited; } @@ -466,27 +665,27 @@ Vec_Ptr_t * Abc_NtkManCutReadLeaves( Abc_ManCut_t * p ) SeeAlso [] ***********************************************************************/ -void Abc_NodeCollectTfoCands( Abc_Ntk_t * pNtk, Abc_Obj_t * pRoot, - Vec_Ptr_t * vFanins, int LevelMax, Vec_Vec_t * vLevels, Vec_Ptr_t * vResult ) +Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int LevelMax ) { + Abc_Ntk_t * pNtk = pRoot->pNtk; Vec_Ptr_t * vVec; Abc_Obj_t * pNode, * pFanout; int i, k, v, LevelMin; assert( Abc_NtkIsStrash(pNtk) ); // assuming that the structure is clean - Vec_VecForEachLevel( vLevels, vVec, i ) + Vec_VecForEachLevel( p->vLevels, vVec, i ) assert( vVec->nSize == 0 ); // put fanins into the structure while labeling them Abc_NtkIncrementTravId( pNtk ); - LevelMin = ABC_INFINITY; - Vec_PtrForEachEntry( vFanins, pNode, i ) + LevelMin = -1; + Vec_PtrForEachEntry( vLeaves, pNode, i ) { if ( pNode->Level > (unsigned)LevelMax ) continue; Abc_NodeSetTravIdCurrent( pNode ); - Vec_VecPush( vLevels, pNode->Level, pNode ); + Vec_VecPush( p->vLevels, pNode->Level, pNode ); if ( LevelMin < (int)pNode->Level ) LevelMin = pNode->Level; } @@ -497,9 +696,11 @@ void Abc_NodeCollectTfoCands( Abc_Ntk_t * pNtk, Abc_Obj_t * pRoot, Abc_NodeMffcLabel( pRoot ); // go through the levels up - Vec_PtrClear( vResult ); - Vec_VecForEachEntryStartStop( vLevels, pNode, i, k, LevelMin, LevelMax ) + Vec_PtrClear( p->vNodesTfo ); + Vec_VecForEachEntryStart( p->vLevels, pNode, i, k, LevelMin ) { + if ( i > LevelMax ) + break; // if the node is not marked, it is not a fanin if ( !Abc_NodeIsTravIdCurrent(pNode) ) { @@ -508,7 +709,7 @@ void Abc_NodeCollectTfoCands( Abc_Ntk_t * pNtk, Abc_Obj_t * pRoot, !Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pNode)) ) continue; // save the node in the TFO and label it - Vec_PtrPush( vResult, pNode ); + Vec_PtrPush( p->vNodesTfo, pNode ); Abc_NodeSetTravIdCurrent( pNode ); } // go through the fanouts and add them to the structure if they meet the conditions @@ -521,13 +722,18 @@ void Abc_NodeCollectTfoCands( Abc_Ntk_t * pNtk, Abc_Obj_t * pRoot, if ( Abc_NodeIsTravIdCurrent(pFanout) ) continue; // add it to the structure but do not mark it (until tested later) - Vec_VecPush( vLevels, pFanout->Level, pFanout ); + Vec_VecPushUnique( p->vLevels, pFanout->Level, pFanout ); } } // clear the levelized structure - Vec_VecForEachLevelStartStop( vLevels, vVec, i, LevelMin, LevelMax ) + Vec_VecForEachLevelStart( p->vLevels, vVec, i, LevelMin ) + { + if ( i > LevelMax ) + break; Vec_PtrClear( vVec ); + } + return p->vNodesTfo; } //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/abcRefactor.c b/src/base/abc/abcRefactor.c index 7e387b47..9a413bb1 100644 --- a/src/base/abc/abcRefactor.c +++ b/src/base/abc/abcRefactor.c @@ -96,9 +96,9 @@ int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool assert( Abc_NtkIsStrash(pNtk) ); // start the managers - pManCut = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax ); + pManCut = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, 1000 ); pManRef = Abc_NtkManRefStart( nNodeSizeMax, nConeSizeMax, fUseDcs, fVerbose ); - pManRef->vLeaves = Abc_NtkManCutReadLeaves( pManCut ); + pManRef->vLeaves = Abc_NtkManCutReadCutLarge( pManCut ); Abc_NtkStartReverseLevels( pNtk ); // resynthesize each node once diff --git a/src/base/abc/abcRefs.c b/src/base/abc/abcRefs.c index 081ccfaa..dfcc3ae5 100644 --- a/src/base/abc/abcRefs.c +++ b/src/base/abc/abcRefs.c @@ -174,6 +174,10 @@ void Abc_NodeUpdate( Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Int_t * vForm, // create the new structure of nodes assert( vForm->nSize == 1 || Vec_PtrSize(vFanins) < Vec_IntSize(vForm) ); pNodeNew = Abc_NodeStrashDec( pNtk->pManFunc, vFanins, vForm ); + // in some cases, the new node may have a minor redundancy + // (has to do with the precomputed subgraph library) + if ( !Abc_AigNodeIsAcyclic( Abc_ObjRegular(pNodeNew), pNode ) ) + return; // remove the old nodes Abc_AigReplace( pNtk->pManFunc, pNode, pNodeNew ); // compare the gains diff --git a/src/base/abc/abcShow.c b/src/base/abc/abcShow.c index 730aca90..38840de0 100644 --- a/src/base/abc/abcShow.c +++ b/src/base/abc/abcShow.c @@ -18,22 +18,27 @@ ***********************************************************************/ -#include "abc.h" #ifdef WIN32 -#include "process.h" +#include <process.h> #endif +#include "abc.h" +#include "io.h" + //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// - + +static void Abc_ShowFile( char * FileNameDot ); +static void Abc_ShowGetFileName( char * pName, char * pBuffer ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Prints the factored form of one node.] + Synopsis [Visualizes BDD of the node.] Description [] @@ -42,15 +47,152 @@ SeeAlso [] ***********************************************************************/ -void Abc_NodePrintBdd( Abc_Obj_t * pNode ) +void Abc_NodeShowBdd( Abc_Obj_t * pNode ) { FILE * pFile; Vec_Ptr_t * vNamesIn; - char * FileNameIn; - char * FileNameOut; - char * FileGeneric; - char * pCur, * pNameOut; char FileNameDot[200]; + char * pNameOut; + + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + // create the file names + Abc_ShowGetFileName( Abc_ObjName(pNode), 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 + vNamesIn = Abc_NodeGetFaninNames( pNode ); + pNameOut = Abc_ObjName(pNode); + Cudd_DumpDot( pNode->pNtk->pManFunc, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); + Abc_NodeFreeFaninNames( vNamesIn ); + Abc_NtkCleanCopy( pNode->pNtk ); + fclose( pFile ); + + // visualize the file + Abc_ShowFile( FileNameDot ); +} + +/**Function************************************************************* + + Synopsis [Visualizes AIG with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkShowAig( Abc_Ntk_t * pNtk ) +{ + FILE * pFile; + Abc_Obj_t * pNode; + Vec_Ptr_t * vNodes; + char FileNameDot[200]; + int i; + + assert( Abc_NtkIsStrash(pNtk) ); + // create the file names + 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; + } + + // collect all nodes in the network + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachObj( pNtk, pNode, i ) + Vec_PtrPush( vNodes, pNode ); + // write the DOT file + Io_WriteDot( pNtk, vNodes, NULL, FileNameDot ); + Vec_PtrFree( vNodes ); + + // visualize the file + Abc_ShowFile( FileNameDot ); +} + +/**Function************************************************************* + + Synopsis [Visualizes reconvergence driven cut at the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) +{ + FILE * pFile; + char FileNameDot[200]; + Abc_ManCut_t * p; + Vec_Ptr_t * vCutSmall; + Vec_Ptr_t * vCutLarge; + Vec_Ptr_t * vInside; + Vec_Ptr_t * vNodesTfo; + Abc_Obj_t * pTemp; + int i; + + assert( Abc_NtkIsStrash(pNode->pNtk) ); + + // start the cut computation manager + p = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, ABC_INFINITY ); + // get the recovergence driven cut + vCutSmall = Abc_NodeFindCut( p, pNode, 1 ); + // get the containing cut + vCutLarge = Abc_NtkManCutReadCutLarge( p ); + // get the array for the inside nodes + vInside = Abc_NtkManCutReadVisited( p ); + // get the inside nodes of the containing cone + Abc_NodeConeCollect( &pNode, 1, vCutLarge, vInside, 1 ); + + // add the nodes in the TFO + vNodesTfo = Abc_NodeCollectTfoCands( p, pNode, vCutSmall, ABC_INFINITY ); + Vec_PtrForEachEntry( vNodesTfo, pTemp, i ) + Vec_PtrPushUnique( vInside, pTemp ); + + // create the file names + Abc_ShowGetFileName( Abc_ObjName(pNode), 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; + } + // add the root node to the cone (for visualization) + Vec_PtrPush( vCutSmall, pNode ); + // write the DOT file + Io_WriteDot( pNode->pNtk, vInside, vCutSmall, FileNameDot ); + // stop the cut computation manager + Abc_NtkManCutStop( p ); + + // visualize the file + Abc_ShowFile( FileNameDot ); +} + + +/**Function************************************************************* + + Synopsis [Shows the given DOT file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ShowFile( char * FileNameDot ) +{ + FILE * pFile; + char * FileGeneric; char FileNamePs[200]; char CommandDot[1000]; #ifndef WIN32 @@ -60,8 +202,6 @@ void Abc_NodePrintBdd( Abc_Obj_t * pNode ) char * pProgGsViewName; int RetValue; - assert( Abc_NtkIsBddLogic(pNode->pNtk) ); - #ifdef WIN32 pProgDotName = "dot.exe"; pProgGsViewName = NULL; @@ -70,34 +210,6 @@ void Abc_NodePrintBdd( Abc_Obj_t * pNode ) pProgGsViewName = "gv"; #endif - FileNameIn = NULL; - FileNameOut = NULL; - - // get the generic file name - pNode->pCopy = NULL; - FileGeneric = Abc_ObjName(pNode); - // get rid of not-alpha-numeric characters - for ( pCur = FileGeneric; *pCur; pCur++ ) - if ( !((*pCur >= '0' && *pCur <= '9') || (*pCur >= 'a' && *pCur <= 'z') || (*pCur >= 'A' && *pCur <= 'Z')) ) - *pCur = '_'; - // create the file names - sprintf( FileNameDot, "%s.dot", FileGeneric ); - sprintf( FileNamePs, "%s.ps", FileGeneric ); - - // write the DOT file - if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); - return; - } - // set the node names - vNamesIn = Abc_NodeGetFaninNames( pNode ); - pNameOut = Abc_ObjName(pNode); - Cudd_DumpDot( pNode->pNtk->pManFunc, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); - Abc_NodeFreeFaninNames( vNamesIn ); - Abc_NtkCleanCopy( pNode->pNtk ); - fclose( pFile ); - // check that the input file is okay if ( (pFile = fopen( FileNameDot, "r" )) == NULL ) { @@ -106,6 +218,12 @@ void Abc_NodePrintBdd( Abc_Obj_t * pNode ) } fclose( pFile ); + // get the generic file name + FileGeneric = Extra_FileNameGeneric( FileNameDot ); + // create the PostScript file name + sprintf( FileNamePs, "%s.ps", FileGeneric ); + free( FileGeneric ); + // generate the DOT file sprintf( CommandDot, "%s -Tps -o %s %s", pProgDotName, FileNamePs, FileNameDot ); RetValue = system( CommandDot ); @@ -146,10 +264,9 @@ void Abc_NodePrintBdd( Abc_Obj_t * pNode ) #endif } - /**Function************************************************************* - Synopsis [] + Synopsis [Derives the DOT file name.] Description [] @@ -158,6 +275,18 @@ void Abc_NodePrintBdd( Abc_Obj_t * pNode ) SeeAlso [] ***********************************************************************/ +void Abc_ShowGetFileName( char * pName, char * pBuffer ) +{ + char * pCur; + // creat the file name + sprintf( pBuffer, "%s.dot", pName ); + // get rid of not-alpha-numeric characters + for ( pCur = pBuffer; *pCur; pCur++ ) + if ( !((*pCur >= '0' && *pCur <= '9') || (*pCur >= 'a' && *pCur <= 'z') || + (*pCur >= 'A' && *pCur <= 'Z') || (*pCur == '.')) ) + *pCur = '_'; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/base/abc/abcStrash.c b/src/base/abc/abcStrash.c index 19394fb3..0a28c3c1 100644 --- a/src/base/abc/abcStrash.c +++ b/src/base/abc/abcStrash.c @@ -49,7 +49,7 @@ extern char * Mio_GateReadSop( void * pGate ); SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes ) +Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup ) { int fCheck = 1; Abc_Ntk_t * pNtkAig; @@ -68,11 +68,11 @@ Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes ) // print warning about self-feed latches if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) printf( "The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); - if ( nNodes = Abc_AigCleanup(pNtkAig->pManFunc) ) + if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) printf( "Cleanup has removed %d nodes.\n", nNodes ); // duplicate EXDC if ( pNtk->pExdc ) - pNtkAig->pExdc = Abc_NtkStrash( pNtk->pExdc, 0 ); + pNtkAig->pExdc = Abc_NtkStrash( pNtk->pExdc, 0, 1 ); // make sure everything is okay if ( fCheck && !Abc_NtkCheck( pNtkAig ) ) { diff --git a/src/base/abc/abcSweep.c b/src/base/abc/abcSweep.c index 47565241..61d65ce3 100644 --- a/src/base/abc/abcSweep.c +++ b/src/base/abc/abcSweep.c @@ -61,7 +61,7 @@ bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose ) assert( !Abc_NtkIsStrash(pNtk) ); // derive the AIG - pNtkAig = Abc_NtkStrash( pNtk, 0 ); + pNtkAig = Abc_NtkStrash( pNtk, 0, 1 ); // perform fraiging of the AIG Fraig_ParamsSetDefault( &Params ); pMan = Abc_NtkToFraig( pNtkAig, &Params, 0 ); diff --git a/src/base/abc/abcSymm.c b/src/base/abc/abcSymm.c new file mode 100644 index 00000000..8df3a837 --- /dev/null +++ b/src/base/abc/abcSymm.c @@ -0,0 +1,202 @@ +/**CFile**************************************************************** + + FileName [abcSymm.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Computation of two-variable symmetries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcSymm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fVerbose ); +static void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose ); +static void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [The top level procedure to compute symmetries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fVerbose ) +{ + if ( fUseBdds || fNaive ) + Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fVerbose ); + else + printf( "This option is currently not implemented.\n" ); +} + +/**Function************************************************************* + + Synopsis [Symmetry computation using BDDs (both naive and smart).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fVerbose ) +{ + DdManager * dd; + int clk, clkBdd, clkSym; + + // compute the global functions +clk = clock(); + dd = Abc_NtkGlobalBdds( pNtk, 0 ); + Cudd_AutodynDisable( dd ); + Cudd_zddVarsFromBddVars( dd, 2 ); +clkBdd = clock() - clk; + // create the collapsed network +clk = clock(); + Ntk_NetworkSymmsBdd( dd, pNtk, fNaive, fVerbose ); +clkSym = clock() - clk; + // undo the global functions + Abc_NtkFreeGlobalBdds( pNtk ); + Extra_StopManager( dd ); + pNtk->pManGlob = NULL; + +PRT( "Constructing BDDs", clkBdd ); +PRT( "Computing symms ", clkSym ); +PRT( "TOTAL ", clkBdd + clkSym ); +} + +/**Function************************************************************* + + Synopsis [Symmetry computation using BDDs (both naive and smart).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose ) +{ + Extra_SymmInfo_t * pSymms; + Abc_Obj_t * pNode; + DdNode * bFunc; + int nSymms = 0; + int i; + + // compute symmetry info for each PO + Abc_NtkForEachCo( pNtk, pNode, i ) + { + bFunc = pNtk->vFuncsGlob->pArray[i]; + if ( Cudd_IsConstant(bFunc) ) + continue; + if ( fNaive ) + pSymms = Extra_SymmPairsComputeNaive( dd, bFunc ); + else + pSymms = Extra_SymmPairsCompute( dd, bFunc ); + nSymms += pSymms->nSymms; + if ( fVerbose ) + { + printf( "Output %6s (%d): ", Abc_ObjName(pNode), pSymms->nSymms ); + Ntk_NetworkSymmsPrint( pNtk, pSymms ); + } +//Extra_SymmPairsPrint( pSymms ); + Extra_SymmPairsDissolve( pSymms ); + } + printf( "The total number of symmetries is %d.\n", nSymms ); +} + +/**Function************************************************************* + + Synopsis [Printing symmetry groups from the symmetry data structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms ) +{ + char ** pInputNames; + int * pVarTaken; + int i, k, nVars, nSize, fStart; + + // get variable names + nVars = Abc_NtkCiNum(pNtk); + pInputNames = Abc_NtkCollectCioNames( pNtk, 0 ); + + // alloc the array of marks + pVarTaken = ALLOC( int, nVars ); + memset( pVarTaken, 0, sizeof(int) * nVars ); + + // print the groups + fStart = 1; + nSize = pSymms->nVars; + for ( i = 0; i < nSize; i++ ) + { + // skip the variable already considered + if ( pVarTaken[i] ) + continue; + // find all the vars symmetric with this one + for ( k = 0; k < nSize; k++ ) + { + if ( k == i ) + continue; + if ( pSymms->pSymms[i][k] == 0 ) + continue; + // vars i and k are symmetric + assert( pVarTaken[k] == 0 ); + // there is a new symmetry pair + if ( fStart == 1 ) + { // start a new symmetry class + fStart = 0; + printf( " { %s", pInputNames[ pSymms->pVars[i] ] ); + // mark the var as taken + pVarTaken[i] = 1; + } + printf( " %s", pInputNames[ pSymms->pVars[k] ] ); + // mark the var as taken + pVarTaken[k] = 1; + } + if ( fStart == 0 ) + { + printf( " }" ); + fStart = 1; + } + } + printf( "\n" ); + + free( pInputNames ); + free( pVarTaken ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abc/abcUnreach.c b/src/base/abc/abcUnreach.c index 04e5c96c..0fe3ec63 100644 --- a/src/base/abc/abcUnreach.c +++ b/src/base/abc/abcUnreach.c @@ -91,6 +91,7 @@ int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose ) pNtk->pExdc = Abc_NtkConstructExdc( dd, pNtk, bUnreach ); Cudd_RecursiveDeref( dd, bUnreach ); Extra_StopManager( dd ); + pNtk->pManGlob = NULL; // make sure that everything is okay if ( fCheck && !Abc_NtkCheck( pNtk->pExdc ) ) @@ -135,13 +136,13 @@ DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbo Abc_NtkForEachLatch( pNtk, pNode, i ) { bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i ); - bProd = Cudd_bddXnor( dd, bVar, (DdNode *)pNode->pNext ); Cudd_Ref( bProd ); - bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel ); + bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd ); + bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); } // free the global BDDs - Abc_NtkFreeGlobalBdds( dd, pNtk ); + Abc_NtkFreeGlobalBdds( pNtk ); // quantify the PI variables bInputs = Extra_bddComputeRangeCube( dd, 0, Abc_NtkPiNum(pNtk) ); Cudd_Ref( bInputs ); diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c index 7d2ca107..9a2acc32 100644 --- a/src/base/abc/abcUtil.c +++ b/src/base/abc/abcUtil.c @@ -1046,6 +1046,29 @@ Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk ) return vFanNums; } +/**Function************************************************************* + + Synopsis [Collects all objects into one array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachObj( pNtk, pNode, i ) + Vec_PtrPush( vNodes, pNode ); + return vNodes; +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/module.make b/src/base/abc/module.make index d9bed264..d3d4091b 100644 --- a/src/base/abc/module.make +++ b/src/base/abc/module.make @@ -32,6 +32,7 @@ SRC += src/base/abc/abc.c \ src/base/abc/abcSop.c \ src/base/abc/abcStrash.c \ src/base/abc/abcSweep.c \ + src/base/abc/abcSymm.c \ src/base/abc/abcTiming.c \ src/base/abc/abcUnreach.c \ src/base/abc/abcUtil.c \ diff --git a/src/base/io/io.c b/src/base/io/io.c index 9ffbc3cf..89703214 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -29,12 +29,16 @@ static int IoCommandRead ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadBench ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadEdif ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadVerilog ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadPla ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBench ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteCnf ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteDot ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteGml ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWritePla ( Abc_Frame_t * pAbc, int argc, char **argv ); //////////////////////////////////////////////////////////////////////// @@ -58,12 +62,16 @@ void Io_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "I/O", "read_blif", IoCommandReadBlif, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_bench", IoCommandReadBench, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_edif", IoCommandReadEdif, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_eqn", IoCommandReadEqn, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_verilog", IoCommandReadVerilog, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_pla", IoCommandReadPla, 1 ); Cmd_CommandAdd( pAbc, "I/O", "write_blif", IoCommandWriteBlif, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_bench", IoCommandWriteBench, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_cnf", IoCommandWriteCnf, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_dot", IoCommandWriteDot, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_eqn", IoCommandWriteEqn, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_gml", IoCommandWriteGml, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_pla", IoCommandWritePla, 0 ); } @@ -127,7 +135,7 @@ int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); - if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".mvpla", NULL ) ) + if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) ) fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName ); fprintf( pAbc->Err, "\n" ); return 1; @@ -199,7 +207,7 @@ int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); - if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".mvpla", NULL ) ) + if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) ) fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName ); fprintf( pAbc->Err, "\n" ); return 1; @@ -280,7 +288,7 @@ int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); - if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".mvpla", NULL ) ) + if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) ) fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName ); fprintf( pAbc->Err, "\n" ); return 1; @@ -360,7 +368,7 @@ int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); - if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".mvpla", NULL ) ) + if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) ) fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName ); fprintf( pAbc->Err, "\n" ); return 1; @@ -406,6 +414,86 @@ usage: SeeAlso [] ***********************************************************************/ +int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pTemp; + char * FileName; + FILE * pFile; + int fCheck; + int c; + + fCheck = 1; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != util_optind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[util_optind]; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); + if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) ) + fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName ); + fprintf( pAbc->Err, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pNtk = Io_ReadEqn( FileName, fCheck ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Reading network from the equation file has failed.\n" ); + return 1; + } + + pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Converting to logic network after reading has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_eqn [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in equation format\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pTemp; @@ -440,7 +528,7 @@ int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); - if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".mvpla", NULL ) ) + if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) ) fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName ); fprintf( pAbc->Err, "\n" ); return 1; @@ -451,7 +539,7 @@ int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv ) pNtk = Io_ReadVerilog( FileName, fCheck ); if ( pNtk == NULL ) { - fprintf( pAbc->Err, "Reading network from Verilog file has failed.\n" ); + fprintf( pAbc->Err, "Reading network from the verilog file has failed.\n" ); return 1; } @@ -520,7 +608,7 @@ int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); - if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".mvpla", NULL ) ) + if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) ) fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName ); fprintf( pAbc->Err, "\n" ); return 1; @@ -764,6 +852,199 @@ usage: SeeAlso [] ***********************************************************************/ +int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * FileName; + Vec_Ptr_t * vNodes; + int c; + + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + if ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) + { + fprintf( stdout, "IoCommandWriteDot(): Currently can only process logic networks with BDDs.\n" ); + return 0; + } + + if ( argc != util_optind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[util_optind]; + // write the file + vNodes = Abc_NtkCollectObjects( pAbc->pNtkCur ); + Io_WriteDot( pAbc->pNtkCur, vNodes, NULL, FileName ); + Vec_PtrFree( vNodes ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_dot [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the AIG into a DOT file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNtk, * pNtkTemp; + char * FileName; + int c; + + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + pNtk = pAbc->pNtkCur; + if ( pNtk == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + if ( argc != util_optind + 1 ) + { + goto usage; + } + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "IoCommandWriteGml(): Currently can only process logic networks with BDDs.\n" ); + return 0; + } + + // get the input file name + FileName = argv[util_optind]; + // write the file + // get rid of complemented covers if present + if ( Abc_NtkIsSopLogic(pNtk) ) + Abc_NtkLogicMakeDirectSops(pNtk); + // derive the netlist + pNtkTemp = Abc_NtkLogicToNetlist(pNtk); + if ( pNtkTemp == NULL ) + { + fprintf( pAbc->Out, "Writing BENCH has failed.\n" ); + return 0; + } + Io_WriteEqn( pNtkTemp, FileName ); + Abc_NtkDelete( pNtkTemp ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_eqn [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the current network in the equation format\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * FileName; + int c; + + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + if ( !Abc_NtkIsLogic(pAbc->pNtkCur) && !Abc_NtkIsStrash(pAbc->pNtkCur) ) + { + fprintf( stdout, "IoCommandWriteGml(): Currently can only process logic networks with BDDs.\n" ); + return 0; + } + + if ( argc != util_optind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[util_optind]; + // write the file + Io_WriteGml( pAbc->pNtkCur, FileName ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_gml [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write network using graph representation formal GML\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) { Abc_Ntk_t * pNtk, * pNtkTemp; diff --git a/src/base/io/io.h b/src/base/io/io.h index d45b7b1b..6bf3a85c 100644 --- a/src/base/io/io.h +++ b/src/base/io/io.h @@ -53,6 +53,8 @@ extern Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ); extern Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck ); /*=== abcReadEdif.c ==========================================================*/ extern Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck ); +/*=== abcReadEqn.c ==========================================================*/ +extern Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck ); /*=== abcReadVerilog.c ==========================================================*/ extern Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck ); /*=== abcReadPla.c ==========================================================*/ @@ -73,6 +75,12 @@ extern void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ); extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcWriteCnf.c ==========================================================*/ extern int Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcWriteDot.c ==========================================================*/ +extern void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName ); +/*=== abcWriteEqn.c ==========================================================*/ +extern void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWriteGml.c ==========================================================*/ +extern void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ); /*=== abcWritePla.c ==========================================================*/ extern int Io_WritePla( Abc_Ntk_t * pNtk, char * FileName ); diff --git a/src/base/io/ioRead.c b/src/base/io/ioRead.c index 75c87a80..acf4deda 100644 --- a/src/base/io/ioRead.c +++ b/src/base/io/ioRead.c @@ -53,6 +53,8 @@ Abc_Ntk_t * Io_Read( char * pFileName, int fCheck ) pNtk = Io_ReadEdif( pFileName, fCheck ); else if ( Extra_FileNameCheckExtension( pFileName, "pla" ) ) pNtk = Io_ReadPla( pFileName, fCheck ); + else if ( Extra_FileNameCheckExtension( pFileName, "eqn" ) ) + pNtk = Io_ReadEqn( pFileName, fCheck ); else { fprintf( stderr, "Unknown file format\n" ); diff --git a/src/base/io/ioReadEqn.c b/src/base/io/ioReadEqn.c new file mode 100644 index 00000000..54890729 --- /dev/null +++ b/src/base/io/ioReadEqn.c @@ -0,0 +1,254 @@ +/**CFile**************************************************************** + + FileName [ioReadEqn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read equation format files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ); +static void Io_ReadEqnStrCompact( char * pStr ); +static int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName ); +static void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from a BENCH file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck ) +{ + Extra_FileReader_t * p; + Abc_Ntk_t * pNtk; + + // start the file + p = Extra_FileReaderAlloc( pFileName, "#", ";", "=" ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadEqnNetwork( p ); + Extra_FileReaderFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheck( pNtk ) ) + { + printf( "Io_ReadEqn: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vTokens; + Vec_Ptr_t * vCubes, * vLits, * vVars; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + char * pCubesCopy, * pSopCube, * pVarName; + int iLine, iNum, i, k; + + // allocate the empty network + pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); + + // go through the lines of the file + vCubes = Vec_PtrAlloc( 100 ); + vVars = Vec_PtrAlloc( 100 ); + vLits = Vec_PtrAlloc( 100 ); + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); + for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) + { + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); + + // check if the first token contains anything + Io_ReadEqnStrCompact( vTokens->pArray[0] ); + if ( strlen(vTokens->pArray[0]) == 0 ) + break; + + // if the number of tokens is different from two, error + if ( vTokens->nSize != 2 ) + { + printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); + Abc_NtkDelete( pNtk ); + return NULL; + } + + // get the type of the line + if ( strncmp( vTokens->pArray[0], "INORDER", 7 ) == 0 ) + { + Io_ReadEqnStrCutAt( vTokens->pArray[1], " \n\r\t", 0, vVars ); + Vec_PtrForEachEntry( vVars, pVarName, i ) + Io_ReadCreatePi( pNtk, pVarName ); + } + else if ( strncmp( vTokens->pArray[0], "OUTORDER", 8 ) == 0 ) + { + Io_ReadEqnStrCutAt( vTokens->pArray[1], " \n\r\t", 0, vVars ); + Vec_PtrForEachEntry( vVars, pVarName, i ) + Io_ReadCreatePo( pNtk, pVarName ); + } + else + { + // remove spaces + pCubesCopy = vTokens->pArray[1]; + Io_ReadEqnStrCompact( pCubesCopy ); + // consider the case of the constant node + if ( (pCubesCopy[0] == '0' || pCubesCopy[0] == '1') && pCubesCopy[1] == 0 ) + { + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], NULL, 0 ); + if ( pCubesCopy[0] == '0' ) + pNode->pData = Abc_SopCreateConst0( pNtk->pManFunc ); + else + pNode->pData = Abc_SopCreateConst1( pNtk->pManFunc ); + continue; + } + // determine unique variables + pCubesCopy = util_strsav( pCubesCopy ); + // find the names of the fanins of this node + Io_ReadEqnStrCutAt( pCubesCopy, "!*+", 1, vVars ); + // create the node + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], (char **)vVars->pArray, vVars->nSize ); + // split the string into cubes + Io_ReadEqnStrCutAt( vTokens->pArray[1], "+", 0, vCubes ); + // start the sop + pNode->pData = Abc_SopStart( pNtk->pManFunc, vCubes->nSize, vVars->nSize ); + // read the cubes + i = 0; + Abc_SopForEachCube( pNode->pData, vVars->nSize, pSopCube ) + { + // split this cube into lits + Io_ReadEqnStrCutAt( vCubes->pArray[i], "*", 0, vLits ); + // read the literals + Vec_PtrForEachEntry( vLits, pVarName, k ) + { + iNum = Io_ReadEqnStrFind( vVars, pVarName + (pVarName[0] == '!') ); + assert( iNum >= 0 ); + pSopCube[iNum] = '1' - (pVarName[0] == '!'); + } + i++; + } + assert( i == vCubes->nSize ); + // remove the cubes + free( pCubesCopy ); + } + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vCubes ); + Vec_PtrFree( vLits ); + Vec_PtrFree( vVars ); + Abc_NtkFinalizeRead( pNtk ); + return pNtk; +} + + + +/**Function************************************************************* + + Synopsis [Compacts the string by throwing away space-like chars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadEqnStrCompact( char * pStr ) +{ + char * pCur, * pNew; + for ( pNew = pCur = pStr; *pCur; pCur++ ) + if ( !(*pCur == ' ' || *pCur == '\n' || *pCur == '\r' || *pCur == '\t') ) + *pNew++ = *pCur; + *pNew = 0; +} + +/**Function************************************************************* + + Synopsis [Determines unique variables in the string.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName ) +{ + char * pToken; + int i; + Vec_PtrForEachEntry( vTokens, pToken, i ) + if ( strcmp( pToken, pName ) == 0 ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Cuts the string into pieces using stop chars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens ) +{ + char * pToken; + Vec_PtrClear( vTokens ); + for ( pToken = strtok( pStr, pStop ); pToken; pToken = strtok( NULL, pStop ) ) + if ( !fUniqueOnly || Io_ReadEqnStrFind( vTokens, pToken ) == -1 ) + Vec_PtrPush( vTokens, pToken ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/src/base/io/ioWriteBlif.c b/src/base/io/ioWriteBlif.c index 5135105f..7d6815b9 100644 --- a/src/base/io/ioWriteBlif.c +++ b/src/base/io/ioWriteBlif.c @@ -107,10 +107,7 @@ void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) Synopsis [Write one network.] - Description [Writes a network composed of PIs, POs, internal nodes, - and latches. The following rules are used to print the names of - internal nodes: - ] + Description [] SideEffects [] diff --git a/src/base/io/ioWriteCnf.c b/src/base/io/ioWriteCnf.c index bb216bb6..09824f38 100644 --- a/src/base/io/ioWriteCnf.c +++ b/src/base/io/ioWriteCnf.c @@ -6,7 +6,7 @@ PackageName [Command processing package.] - Synopsis [Procedures to CNF of the miter cone.] + Synopsis [Procedures to output CNF of the miter cone.] Author [Alan Mishchenko] @@ -24,8 +24,6 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static void Io_WriteCnfInt( FILE * pFile, Abc_Ntk_t * pNtk ); - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/io/ioWriteDot.c b/src/base/io/ioWriteDot.c new file mode 100644 index 00000000..7d88e52d --- /dev/null +++ b/src/base/io/ioWriteDot.c @@ -0,0 +1,322 @@ +/**CFile**************************************************************** + + FileName [ioWriteDot.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the graph structure of AIG in DOT.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteDot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the graph structure of AIG in DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName ) +{ + FILE * pFile; + Abc_Obj_t * pNode, * pTemp, * pPrev; + int LevelMin, LevelMax, fHasCos, Level, i; + int Limit = 200; + + if ( vNodes->nSize < 1 ) + { + printf( "The set has no nodes. DOT file is not written.\n" ); + return; + } + + if ( vNodes->nSize > Limit ) + { + printf( "The set has more than %d nodes. DOT file is not written.\n", Limit ); + return; + } + + // start the stream + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // mark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 1; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 1; + + // find the largest and the smallest levels + LevelMin = 10000; + LevelMax = -1; + fHasCos = 0; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + { + fHasCos = 1; + continue; + } + if ( LevelMin > (int)pNode->Level ) + LevelMin = pNode->Level; + if ( LevelMax < (int)pNode->Level ) + LevelMax = pNode->Level; + } + + // set the level of the CO nodes + if ( fHasCos ) + { + LevelMax++; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + pNode->Level = LevelMax; + } + } + + // write the DOT header + fprintf( pFile, "# %s\n", "AIG generated by ABC" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph AIG {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != LevelMin ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "AIG generated by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); + fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "The set contains %d nodes and spans %d levels.", vNodes->nSize, LevelMax - LevelMin ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the POs + if ( fHasCos ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generat the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsCo(pNode) ) + continue; + fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = invtriangle" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate nodes of each rank + for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( (int)pNode->Level != Level ) + continue; + fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the PI nodes if any + if ( LevelMin == 0 ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMin ); + // generat the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsCi(pNode) ) + continue; + fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = triangle" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( (int)pNode->Level != LevelMax ) + continue; + fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); + } + + // generate edges + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjFaninNum(pNode) == 0 ) + continue; + // generate the edge from this node to the next + if ( Abc_ObjFanin0(pNode)->fMarkC ) + { + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Abc_ObjFaninId0(pNode) ); + fprintf( pFile, " [style = %s]", Abc_ObjFaninC0(pNode)? "dashed" : "bold" ); + fprintf( pFile, ";\n" ); + } + if ( Abc_ObjFaninNum(pNode) == 1 ) + continue; + // generate the edge from this node to the next + if ( Abc_ObjFanin1(pNode)->fMarkC ) + { + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Abc_ObjFaninId1(pNode) ); + fprintf( pFile, " [style = %s]", Abc_ObjFaninC1(pNode)? "dashed" : "bold" ); + fprintf( pFile, ";\n" ); + } + // generate the edges between the equivalent nodes + pPrev = pNode; + for ( pTemp = pNode->pData; pTemp; pTemp = pTemp->pData ) + { + if ( pTemp->fMarkC ) + { + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pTemp->Id ); + fprintf( pFile, " [style = %s]", (pPrev->fPhase ^ pTemp->fPhase)? "dashed" : "bold" ); + fprintf( pFile, ";\n" ); + pPrev = pTemp; + } + } + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 0; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/io/ioWriteEqn.c b/src/base/io/ioWriteEqn.c new file mode 100644 index 00000000..6c2893b5 --- /dev/null +++ b/src/base/io/ioWriteEqn.c @@ -0,0 +1,261 @@ +/**CFile**************************************************************** + + FileName [ioWriteEqn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write equation representation of the network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteEqnPis( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteEqnPos( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteEqnNode( FILE * pFile, Abc_Obj_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the logic network in the equation format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ) +{ + FILE * pFile; + + assert( Abc_NtkIsSopNetlist(pNtk) ); + if ( Abc_NtkLatchNum(pNtk) > 0 ) + printf( "Warning: only combinational portion is being written.\n" ); + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteEqn(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "# Equations for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + + // write the equations for the network + Io_NtkWriteEqnOne( pFile, pNtk ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Write one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode; + int i; + + // write the PIs + fprintf( pFile, "INORDER =" ); + Io_NtkWriteEqnPis( pFile, pNtk ); + fprintf( pFile, ";\n" ); + + // write the POs + fprintf( pFile, "OUTORDER =" ); + Io_NtkWriteEqnPos( pFile, pNtk ); + fprintf( pFile, ";\n" ); + + // write each internal node + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_NtkWriteEqnNode( pFile, pNode ); + } + Extra_ProgressBarStop( pProgress ); +} + + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteEqnPis( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 9; + NameCounter = 0; + + Abc_NtkForEachCi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteEqnPos( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 10; + NameCounter = 0; + + Abc_NtkForEachCo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteEqnNode( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNet; + int LineLength; + int AddedLength; + int NameCounter; + char * pCube; + int Value, fFirstLit, i; + + fprintf( pFile, "%s = ", Abc_ObjName(pNode) ); + + if ( Abc_SopIsConst0(pNode->pData) ) + { + fprintf( pFile, "0;\n" ); + return; + } + if ( Abc_SopIsConst1(pNode->pData) ) + { + fprintf( pFile, "1;\n" ); + return; + } + + NameCounter = 0; + LineLength = strlen(Abc_ObjName(pNode)) + 3; + Abc_SopForEachCube( pNode->pData, Abc_ObjFaninNum(pNode), pCube ) + { + if ( pCube != pNode->pData ) + { + fprintf( pFile, " + " ); + LineLength += 3; + } + + // add the cube + fFirstLit = 1; + Abc_CubeForEachVar( pCube, Value, i ) + { + if ( Value == '-' ) + continue; + pNet = Abc_ObjFanin( pNode, i ); + // get the line length after this name is written + AddedLength = !fFirstLit + (Value == '0') + strlen(Abc_ObjName(pNet)); + if ( NameCounter && LineLength + AddedLength + 6 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \n " ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, "%s%s%s", (fFirstLit? "": "*"), ((Value == '0')? "!":""), Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + fFirstLit = 0; + } + } + fprintf( pFile, ";\n" ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/io/ioWriteGml.c b/src/base/io/ioWriteGml.c new file mode 100644 index 00000000..ab9f1143 --- /dev/null +++ b/src/base/io/ioWriteGml.c @@ -0,0 +1,116 @@ +/**CFile**************************************************************** + + FileName [ioWriteGml.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the graph structure of AIG in GML.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteGml.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the graph structure of AIG in GML.] + + Description [Useful for graph visualization using tools such as yEd: + http://www.yworks.com/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ) +{ + FILE * pFile; + Abc_Obj_t * pObj, * pFanin; + int i, k; + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteGml(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "# GML for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + fprintf( pFile, "graph [\n" ); + + // output the POs + fprintf( pFile, "\n" ); + Abc_NtkForEachPo( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"triangle\" fill \"#00FFFF\" ]\n" ); // blue + fprintf( pFile, " ]\n" ); + } + // output the PIs + fprintf( pFile, "\n" ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"triangle\" fill \"#00FF00\" ]\n" ); // green + fprintf( pFile, " ]\n" ); + } + // output the latches + fprintf( pFile, "\n" ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"rectangle\" fill \"#FF0000\" ]\n" ); // red + fprintf( pFile, " ]\n" ); + } + // output the nodes + fprintf( pFile, "\n" ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"ellipse\" fill \"#CCCCFF\" ]\n" ); // grey + fprintf( pFile, " ]\n" ); + } + + // output the edges + fprintf( pFile, "\n" ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + fprintf( pFile, " edge [ source %5d target %5d\n", pObj->Id, pFanin->Id ); + fprintf( pFile, " graphics [ type \"line\" arrow \"first\" ]\n" ); + fprintf( pFile, " ]\n" ); + } + } + + fprintf( pFile, "]\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/io/module.make b/src/base/io/module.make index cb39c481..34582473 100644 --- a/src/base/io/module.make +++ b/src/base/io/module.make @@ -3,10 +3,14 @@ SRC += src/base/io/io.c \ src/base/io/ioReadBench.c \ src/base/io/ioReadBlif.c \ src/base/io/ioReadEdif.c \ + src/base/io/ioReadEqn.c \ src/base/io/ioReadPla.c \ src/base/io/ioReadVerilog.c \ src/base/io/ioUtil.c \ src/base/io/ioWriteBench.c \ src/base/io/ioWriteBlif.c \ src/base/io/ioWriteCnf.c \ + src/base/io/ioWriteDot.c \ + src/base/io/ioWriteEqn.c \ + src/base/io/ioWriteGml.c \ src/base/io/ioWritePla.c diff --git a/src/map/fpga/fpgaCore.c b/src/map/fpga/fpgaCore.c index b181e997..0fc90228 100644 --- a/src/map/fpga/fpgaCore.c +++ b/src/map/fpga/fpgaCore.c @@ -71,7 +71,7 @@ int Fpga_Mapping( Fpga_Man_t * p ) return 0; p->timeRecover = clock() - clk; } -PRT( "Total mapping time", clock() - clkTotal ); +//PRT( "Total mapping time", clock() - clkTotal ); // print the AI-graph used for mapping //Fpga_ManShow( p, "test" ); diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h index d298a204..14a3d950 100644 --- a/src/misc/extra/extra.h +++ b/src/misc/extra/extra.h @@ -117,6 +117,57 @@ extern DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ); extern DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ); extern DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ); +/*=== extraBddSymm.c =================================================================*/ + +typedef struct Extra_SymmInfo_t_ Extra_SymmInfo_t; +struct Extra_SymmInfo_t_ { + int nVars; // the number of variables in the support + int nVarsMax; // the number of variables in the DD manager + int nSymms; // the number of pair-wise symmetries + int nNodes; // the number of nodes in a ZDD (if applicable) + int * pVars; // the list of all variables present in the support + char ** pSymms; // the symmetry information +}; + +/* computes the classical symmetry information for the function - recursive */ +extern Extra_SymmInfo_t * Extra_SymmPairsCompute( DdManager * dd, DdNode * bFunc ); +/* computes the classical symmetry information for the function - using naive approach */ +extern Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ); +extern int Extra_bddCheckVarsSymmetricNaive( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); + +/* allocates the data structure */ +extern Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ); +/* deallocates the data structure */ +extern void Extra_SymmPairsDissolve( Extra_SymmInfo_t * ); +/* print the contents the data structure */ +extern void Extra_SymmPairsPrint( Extra_SymmInfo_t * ); +/* converts the ZDD into the Extra_SymmInfo_t structure */ +extern Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bVars ); + +/* computes the classical symmetry information as a ZDD */ +extern DdNode * Extra_zddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); +extern DdNode * extraZddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); +/* returns a singleton-set ZDD containing all variables that are symmetric with the given one */ +extern DdNode * Extra_zddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); +extern DdNode * extraZddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); +/* converts a set of variables into a set of singleton subsets */ +extern DdNode * Extra_zddGetSingletons( DdManager * dd, DdNode * bVars ); +extern DdNode * extraZddGetSingletons( DdManager * dd, DdNode * bVars ); +/* filters the set of variables using the support of the function */ +extern DdNode * Extra_bddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); +extern DdNode * extraBddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); + +/* checks the possibility that the two vars are symmetric */ +extern int Extra_bddCheckVarsSymmetric( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); +extern DdNode * extraBddCheckVarsSymmetric( DdManager * dd, DdNode * bF, DdNode * bVars ); + +/* build the set of all tuples of K variables out of N from the BDD cube */ +extern DdNode * Extra_zddTuplesFromBdd( DdManager * dd, int K, DdNode * bVarsN ); +extern DdNode * extraZddTuplesFromBdd( DdManager * dd, DdNode * bVarsK, DdNode * bVarsN ); +/* selects one subset from a ZDD representing the set of subsets */ +extern DdNode * Extra_zddSelectOneSubset( DdManager * dd, DdNode * zS ); +extern DdNode * extraZddSelectOneSubset( DdManager * dd, DdNode * zS ); + /*=== extraUtilBitMatrix.c ================================================================*/ typedef struct Extra_BitMat_t_ Extra_BitMat_t; diff --git a/src/misc/extra/extraUtilBdd.c b/src/misc/extra/extraBddMisc.c index 38e3345c..373ce5c5 100644 --- a/src/misc/extra/extraUtilBdd.c +++ b/src/misc/extra/extraBddMisc.c @@ -1,6 +1,6 @@ /**CFile**************************************************************** - FileName [extraUtilBdd.c] + FileName [extraBddMisc.c] SystemName [ABC: Logic synthesis and verification system.] @@ -14,7 +14,7 @@ Date [Ver. 1.0. Started - June 20, 2005.] - Revision [$Id: extraUtilBdd.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] + Revision [$Id: extraBddMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ diff --git a/src/misc/extra/extraBddSymm.c b/src/misc/extra/extraBddSymm.c new file mode 100644 index 00000000..474f663f --- /dev/null +++ b/src/misc/extra/extraBddSymm.c @@ -0,0 +1,1469 @@ +/**CFile**************************************************************** + + FileName [extraBddSymm.c] + + PackageName [extra] + + Synopsis [Efficient methods to compute the information about + symmetric variables using the algorithm presented in the paper: + A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. + Transactions on CAD, Nov. 2003.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - September 1, 2003.] + + Revision [$Id: extraBddSymm.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "extra.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#define DD_GET_SYMM_VARS_TAG 0x0a /* former DD_BDD_XOR_EXIST_ABSTRACT_TAG */ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Computes the classical symmetry information for the function.] + + Description [Returns the symmetry information in the form of Extra_SymmInfo_t structure.] + + SideEffects [If the ZDD variables are not derived from BDD variables with + multiplicity 2, this function may derive them in a wrong way.] + + SeeAlso [] + +******************************************************************************/ +Extra_SymmInfo_t * Extra_SymmPairsCompute( + DdManager * dd, /* the manager */ + DdNode * bFunc) /* the function whose symmetries are computed */ +{ + DdNode * bSupp; + DdNode * zRes; + Extra_SymmInfo_t * p; + + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + zRes = Extra_zddSymmPairsCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes ); + + p = Extra_SymmPairsCreateFromZdd( dd, zRes, bSupp ); + + Cudd_RecursiveDeref( dd, bSupp ); + Cudd_RecursiveDerefZdd( dd, zRes ); + + return p; + +} /* end of Extra_SymmPairsCompute */ + + +/**Function******************************************************************** + + Synopsis [Computes the classical symmetry information as a ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddSymmPairsCompute( + DdManager * dd, /* the DD manager */ + DdNode * bF, + DdNode * bVars) +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraZddSymmPairsCompute( dd, bF, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddSymmPairsCompute */ + +/**Function******************************************************************** + + Synopsis [Returns a singleton-set ZDD containing all variables that are symmetric with the given one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddGetSymmetricVars( + DdManager * dd, /* the DD manager */ + DdNode * bF, /* the first function - originally, the positive cofactor */ + DdNode * bG, /* the second fucntion - originally, the negative cofactor */ + DdNode * bVars) /* the set of variables, on which F and G depend */ +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraZddGetSymmetricVars( dd, bF, bG, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddGetSymmetricVars */ + + +/**Function******************************************************************** + + Synopsis [Converts a set of variables into a set of singleton subsets.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddGetSingletons( + DdManager * dd, /* the DD manager */ + DdNode * bVars) /* the set of variables */ +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraZddGetSingletons( dd, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddGetSingletons */ + +/**Function******************************************************************** + + Synopsis [Filters the set of variables using the support of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddReduceVarSet( + DdManager * dd, /* the DD manager */ + DdNode * bVars, /* the set of variables to be reduced */ + DdNode * bF) /* the function whose support is used for reduction */ +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraBddReduceVarSet( dd, bVars, bF ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_bddReduceVarSet */ + + +/**Function******************************************************************** + + Synopsis [Allocates symmetry information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ) +{ + int i; + Extra_SymmInfo_t * p; + + // allocate and clean the storage for symmetry info + p = ALLOC( Extra_SymmInfo_t, 1 ); + memset( p, 0, sizeof(Extra_SymmInfo_t) ); + p->nVars = nVars; + p->pVars = ALLOC( int, nVars ); + p->pSymms = ALLOC( char *, nVars ); + p->pSymms[0] = ALLOC( char , nVars * nVars ); + memset( p->pSymms[0], 0, nVars * nVars * sizeof(char) ); + + for ( i = 1; i < nVars; i++ ) + p->pSymms[i] = p->pSymms[i-1] + nVars; + + return p; +} /* end of Extra_SymmPairsAllocate */ + +/**Function******************************************************************** + + Synopsis [Delocates symmetry information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Extra_SymmPairsDissolve( Extra_SymmInfo_t * p ) +{ + free( p->pVars ); + free( p->pSymms[0] ); + free( p->pSymms ); + free( p ); +} /* end of Extra_SymmPairsDissolve */ + +/**Function******************************************************************** + + Synopsis [Allocates symmetry information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Extra_SymmPairsPrint( Extra_SymmInfo_t * p ) +{ + int i, k; + printf( "\n" ); + for ( i = 0; i < p->nVars; i++ ) + { + for ( k = 0; k <= i; k++ ) + printf( " " ); + for ( k = i+1; k < p->nVars; k++ ) + if ( p->pSymms[i][k] ) + printf( "1" ); + else + printf( "." ); + printf( "\n" ); + } +} /* end of Extra_SymmPairsPrint */ + + +/**Function******************************************************************** + + Synopsis [Creates the symmetry information structure from ZDD.] + + Description [ZDD representation of symmetries is the set of cubes, each + of which has two variables in the positive polarity. These variables correspond + to the symmetric variable pair.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp ) +{ + int i; + int nSuppSize; + Extra_SymmInfo_t * p; + int * pMapVars2Nums; + DdNode * bTemp; + DdNode * zSet, * zCube, * zTemp; + int iVar1, iVar2; + + nSuppSize = Extra_bddSuppSize( dd, bSupp ); + + // allocate and clean the storage for symmetry info + p = Extra_SymmPairsAllocate( nSuppSize ); + + // allocate the storage for the temporary map + pMapVars2Nums = ALLOC( int, dd->size ); + memset( pMapVars2Nums, 0, dd->size * sizeof(int) ); + + // assign the variables + p->nVarsMax = dd->size; +// p->nNodes = Cudd_DagSize( zPairs ); + p->nNodes = 0; + for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) + { + p->pVars[i] = bTemp->index; + pMapVars2Nums[bTemp->index] = i; + } + + // write the symmetry info into the structure + zSet = zPairs; Cudd_Ref( zSet ); + while ( zSet != z0 ) + { + // get the next cube + zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube ); + + // add these two variables to the data structure + assert( cuddT( cuddT(zCube) ) == z1 ); + iVar1 = zCube->index/2; + iVar2 = cuddT(zCube)->index/2; + if ( pMapVars2Nums[iVar1] < pMapVars2Nums[iVar2] ) + p->pSymms[ pMapVars2Nums[iVar1] ][ pMapVars2Nums[iVar2] ] = 1; + else + p->pSymms[ pMapVars2Nums[iVar2] ][ pMapVars2Nums[iVar1] ] = 1; + // count the symmetric pairs + p->nSymms ++; + + // update the cuver and deref the cube + zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zCube ); + + } // for each cube + Cudd_RecursiveDerefZdd( dd, zSet ); + + FREE( pMapVars2Nums ); + return p; + +} /* end of Extra_SymmPairsCreateFromZdd */ + + +/**Function******************************************************************** + + Synopsis [Checks the possibility of two variables being symmetric.] + + Description [Returns 0 if vars are not symmetric. Return 1 if vars can be symmetric.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddCheckVarsSymmetric( + DdManager * dd, /* the DD manager */ + DdNode * bF, + int iVar1, + int iVar2) +{ + DdNode * bVars; + int Res; + +// return 1; + + assert( iVar1 != iVar2 ); + assert( iVar1 < dd->size ); + assert( iVar2 < dd->size ); + + bVars = Cudd_bddAnd( dd, dd->vars[iVar1], dd->vars[iVar2] ); Cudd_Ref( bVars ); + + Res = (int)( extraBddCheckVarsSymmetric( dd, bF, bVars ) == b1 ); + + Cudd_RecursiveDeref( dd, bVars ); + + return Res; +} /* end of Extra_bddCheckVarsSymmetric */ + + +/**Function******************************************************************** + + Synopsis [Computes the classical symmetry information for the function.] + + Description [Uses the naive way of comparing cofactors.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ) +{ + DdNode * bSupp, * bTemp; + int nSuppSize; + Extra_SymmInfo_t * p; + int i, k; + + // compute the support + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + nSuppSize = Extra_bddSuppSize( dd, bSupp ); +//printf( "Support = %d. ", nSuppSize ); +//Extra_bddPrint( dd, bSupp ); +//printf( "%d ", nSuppSize ); + + // allocate the storage for symmetry info + p = Extra_SymmPairsAllocate( nSuppSize ); + + // assign the variables + p->nVarsMax = dd->size; + for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) + p->pVars[i] = bTemp->index; + + // go through the candidate pairs and check using Idea1 + for ( i = 0; i < nSuppSize; i++ ) + for ( k = i+1; k < nSuppSize; k++ ) + { + p->pSymms[k][i] = p->pSymms[i][k] = Extra_bddCheckVarsSymmetricNaive( dd, bFunc, p->pVars[i], p->pVars[k] ); + if ( p->pSymms[i][k] ) + p->nSymms++; + } + + Cudd_RecursiveDeref( dd, bSupp ); + return p; + +} /* end of Extra_SymmPairsComputeNaive */ + +/**Function******************************************************************** + + Synopsis [Checks if the two variables are symmetric.] + + Description [Returns 0 if vars are not symmetric. Return 1 if vars are symmetric.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddCheckVarsSymmetricNaive( + DdManager * dd, /* the DD manager */ + DdNode * bF, + int iVar1, + int iVar2) +{ + DdNode * bCube1, * bCube2; + DdNode * bCof01, * bCof10; + int Res; + + assert( iVar1 != iVar2 ); + assert( iVar1 < dd->size ); + assert( iVar2 < dd->size ); + + bCube1 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar1] ), dd->vars[iVar2] ); Cudd_Ref( bCube1 ); + bCube2 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar2] ), dd->vars[iVar1] ); Cudd_Ref( bCube2 ); + + bCof01 = Cudd_Cofactor( dd, bF, bCube1 ); Cudd_Ref( bCof01 ); + bCof10 = Cudd_Cofactor( dd, bF, bCube2 ); Cudd_Ref( bCof10 ); + + Res = (int)( bCof10 == bCof01 ); + + Cudd_RecursiveDeref( dd, bCof01 ); + Cudd_RecursiveDeref( dd, bCof10 ); + Cudd_RecursiveDeref( dd, bCube1 ); + Cudd_RecursiveDeref( dd, bCube2 ); + + return Res; +} /* end of Extra_bddCheckVarsSymmetricNaive */ + + +/**Function******************************************************************** + + Synopsis [Builds ZDD representing the set of fixed-size variable tuples.] + + Description [Creates ZDD of all combinations of variables in Support that + is represented by a BDD.] + + SideEffects [New ZDD variables are created if indices of the variables + present in the combination are larger than the currently + allocated number of ZDD variables.] + + SeeAlso [] + +******************************************************************************/ +DdNode* Extra_zddTuplesFromBdd( + DdManager * dd, /* the DD manager */ + int K, /* the number of variables in tuples */ + DdNode * bVarsN) /* the set of all variables represented as a BDD */ +{ + DdNode *zRes; + int autoDynZ; + + autoDynZ = dd->autoDynZ; + dd->autoDynZ = 0; + + do { + /* transform the numeric arguments (K) into a DdNode* argument; + * this allows us to use the standard internal CUDD cache */ + DdNode *bVarSet = bVarsN, *bVarsK = bVarsN; + int nVars = 0, i; + + /* determine the number of variables in VarSet */ + while ( bVarSet != b1 ) + { + nVars++; + /* make sure that the VarSet is a cube */ + if ( cuddE( bVarSet ) != b0 ) + return NULL; + bVarSet = cuddT( bVarSet ); + } + /* make sure that the number of variables in VarSet is less or equal + that the number of variables that should be present in the tuples + */ + if ( K > nVars ) + return NULL; + + /* the second argument in the recursive call stannds for <n>; + /* reate the first argument, which stands for <k> + * as when we are talking about the tuple of <k> out of <n> */ + for ( i = 0; i < nVars-K; i++ ) + bVarsK = cuddT( bVarsK ); + + dd->reordered = 0; + zRes = extraZddTuplesFromBdd(dd, bVarsK, bVarsN ); + + } while (dd->reordered == 1); + dd->autoDynZ = autoDynZ; + return zRes; + +} /* end of Extra_zddTuplesFromBdd */ + +/**Function******************************************************************** + + Synopsis [Selects one subset from the set of subsets represented by a ZDD.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode* Extra_zddSelectOneSubset( + DdManager * dd, /* the DD manager */ + DdNode * zS) /* the ZDD */ +{ + DdNode *res; + do { + dd->reordered = 0; + res = extraZddSelectOneSubset(dd, zS); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddSelectOneSubset */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_SymmPairsCompute.] + + Description [Returns the set of symmetric variable pairs represented as a set + of two-literal ZDD cubes. Both variables always appear in the positive polarity + in the cubes. This function works without building new BDD nodes. Some relatively + small number of ZDD nodes may be built to ensure proper bookkeeping of the + symmetry information.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraZddSymmPairsCompute( + DdManager * dd, /* the manager */ + DdNode * bFunc, /* the function whose symmetries are computed */ + DdNode * bVars ) /* the set of variables on which this function depends */ +{ + DdNode * zRes; + DdNode * bFR = Cudd_Regular(bFunc); + + if ( cuddIsConstant(bFR) ) + { + int nVars, i; + + // determine how many vars are in the bVars + nVars = Extra_bddSuppSize( dd, bVars ); + if ( nVars < 2 ) + return z0; + else + { + DdNode * bVarsK; + + // create the BDD bVarsK corresponding to K = 2; + bVarsK = bVars; + for ( i = 0; i < nVars-2; i++ ) + bVarsK = cuddT( bVarsK ); + return extraZddTuplesFromBdd( dd, bVarsK, bVars ); + } + } + assert( bVars != b1 ); + + if ( zRes = cuddCacheLookup2Zdd(dd, extraZddSymmPairsCompute, bFunc, bVars) ) + return zRes; + else + { + DdNode * zRes0, * zRes1; + DdNode * zTemp, * zPlus, * zSymmVars; + DdNode * bF0, * bF1; + DdNode * bVarsNew; + int nVarsExtra; + int LevelF; + + // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV + // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F + // count how many extra vars are there in bVars + nVarsExtra = 0; + LevelF = dd->perm[bFR->index]; + for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) + nVarsExtra++; + // the indexes (level) of variables should be synchronized now + assert( bFR->index == bVarsNew->index ); + + // cofactor the function + if ( bFR != bFunc ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + // solve subproblems + zRes0 = extraZddSymmPairsCompute( dd, bF0, cuddT(bVarsNew) ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + // if there is no symmetries in the negative cofactor + // there is no need to test the positive cofactor + if ( zRes0 == z0 ) + zRes = zRes0; // zRes takes reference + else + { + zRes1 = extraZddSymmPairsCompute( dd, bF1, cuddT(bVarsNew) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + + // only those variables are pair-wise symmetric + // that are pair-wise symmetric in both cofactors + // therefore, intersect the solutions + zRes = cuddZddIntersect( dd, zRes0, zRes1 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + } + + // consider the current top-most variable and find all the vars + // that are pairwise symmetric with it + // these variables are returned as a set of ZDD singletons + zSymmVars = extraZddGetSymmetricVars( dd, bF1, bF0, cuddT(bVarsNew) ); + if ( zSymmVars == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zSymmVars ); + + // attach the topmost variable to the set, to get the variable pairs + // use the positive polarity ZDD variable for the purpose + + // there is no need to do so, if zSymmVars is empty + if ( zSymmVars == z0 ) + Cudd_RecursiveDerefZdd( dd, zSymmVars ); + else + { + zPlus = cuddZddGetNode( dd, 2*bFR->index, zSymmVars, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + Cudd_RecursiveDerefZdd( dd, zSymmVars ); + return NULL; + } + cuddRef( zPlus ); + cuddDeref( zSymmVars ); + + // add these variable pairs to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + + // only zRes is referenced at this point + + // if we skipped some variables, these variables cannot be symmetric with + // any variables that are currently in the support of bF, but they can be + // symmetric with the variables that are in bVars but not in the support of bF + if ( nVarsExtra ) + { + // it is possible to improve this step: + // (1) there is no need to enter here, if nVarsExtra < 2 + + // create the set of topmost nVarsExtra in bVars + DdNode * bVarsExtra; + int nVars; + + // remove from bVars all the variable that are in the support of bFunc + bVarsExtra = extraBddReduceVarSet( dd, bVars, bFunc ); + if ( bVarsExtra == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( bVarsExtra ); + + // determine how many vars are in the bVarsExtra + nVars = Extra_bddSuppSize( dd, bVarsExtra ); + if ( nVars < 2 ) + { + Cudd_RecursiveDeref( dd, bVarsExtra ); + } + else + { + int i; + DdNode * bVarsK; + + // create the BDD bVarsK corresponding to K = 2; + bVarsK = bVarsExtra; + for ( i = 0; i < nVars-2; i++ ) + bVarsK = cuddT( bVarsK ); + + // create the 2 variable tuples + zPlus = extraZddTuplesFromBdd( dd, bVarsK, bVarsExtra ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDeref( dd, bVarsExtra ); + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + Cudd_RecursiveDeref( dd, bVarsExtra ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + } + cuddDeref( zRes ); + + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddSymmPairsCompute, bFunc, bVars, zRes); + return zRes; + } +} /* end of extraZddSymmPairsCompute */ + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_zddGetSymmetricVars.] + + Description [Returns the set of ZDD singletons, containing those positive + ZDD variables that correspond to BDD variables x, for which it is true + that bF(x=0) == bG(x=1).] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraZddGetSymmetricVars( + DdManager * dd, /* the DD manager */ + DdNode * bF, /* the first function - originally, the positive cofactor */ + DdNode * bG, /* the second function - originally, the negative cofactor */ + DdNode * bVars) /* the set of variables, on which F and G depend */ +{ + DdNode * zRes; + DdNode * bFR = Cudd_Regular(bF); + DdNode * bGR = Cudd_Regular(bG); + + if ( cuddIsConstant(bFR) && cuddIsConstant(bGR) ) + { + if ( bF == bG ) + return extraZddGetSingletons( dd, bVars ); + else + return z0; + } + assert( bVars != b1 ); + + if ( zRes = cuddCacheLookupZdd(dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars) ) + return zRes; + else + { + DdNode * zRes0, * zRes1; + DdNode * zPlus, * zTemp; + DdNode * bF0, * bF1; + DdNode * bG0, * bG1; + DdNode * bVarsNew; + + int LevelF = cuddI(dd,bFR->index); + int LevelG = cuddI(dd,bGR->index); + int LevelFG; + + if ( LevelF < LevelG ) + LevelFG = LevelF; + else + LevelFG = LevelG; + + // at least one of the arguments is not a constant + assert( LevelFG < dd->size ); + + // every variable in bF and bG should be also in bVars, therefore LevelFG cannot be above LevelV + // if LevelFG is below LevelV, scroll through the vars in bVars to the same level as LevelFG + for ( bVarsNew = bVars; LevelFG > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ); + assert( LevelFG == dd->perm[bVarsNew->index] ); + + // cofactor the functions + if ( LevelF == LevelFG ) + { + if ( bFR != bF ) // bF is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + } + else + bF0 = bF1 = bF; + + if ( LevelG == LevelFG ) + { + if ( bGR != bG ) // bG is complemented + { + bG0 = Cudd_Not( cuddE(bGR) ); + bG1 = Cudd_Not( cuddT(bGR) ); + } + else + { + bG0 = cuddE(bGR); + bG1 = cuddT(bGR); + } + } + else + bG0 = bG1 = bG; + + // solve subproblems + zRes0 = extraZddGetSymmetricVars( dd, bF0, bG0, cuddT(bVarsNew) ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + // if there is not symmetries in the negative cofactor + // there is no need to test the positive cofactor + if ( zRes0 == z0 ) + zRes = zRes0; // zRes takes reference + else + { + zRes1 = extraZddGetSymmetricVars( dd, bF1, bG1, cuddT(bVarsNew) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + + // only those variables should belong to the resulting set + // for which the property is true for both cofactors + zRes = cuddZddIntersect( dd, zRes0, zRes1 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + } + + // add one more singleton if the property is true for this variable + if ( bF0 == bG1 ) + { + zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these variable pairs to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + + if ( bF == bG && bVars != bVarsNew ) + { + // if the functions are equal, so are their cofactors + // add those variables from V that are above F and G + + DdNode * bVarsExtra; + + assert( LevelFG > dd->perm[bVars->index] ); + + // create the BDD of the extra variables + bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsNew ); + if ( bVarsExtra == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( bVarsExtra ); + + zPlus = extraZddGetSingletons( dd, bVarsExtra ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDeref( dd, bVarsExtra ); + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + Cudd_RecursiveDeref( dd, bVarsExtra ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + cuddDeref( zRes ); + + cuddCacheInsert( dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars, zRes ); + return zRes; + } +} /* end of extraZddGetSymmetricVars */ + + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_zddGetSingletons.] + + Description [Returns the set of ZDD singletons, containing those positive + polarity ZDD variables that correspond to the BDD variables in bVars.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraZddGetSingletons( + DdManager * dd, /* the DD manager */ + DdNode * bVars) /* the set of variables */ +{ + DdNode * zRes; + + if ( bVars == b1 ) +// if ( bVars == b0 ) // bug fixed by Jin Zhang, Jan 23, 2004 + return z1; + + if ( zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletons, bVars) ) + return zRes; + else + { + DdNode * zTemp, * zPlus; + + // solve subproblem + zRes = extraZddGetSingletons( dd, cuddT(bVars) ); + if ( zRes == NULL ) + return NULL; + cuddRef( zRes ); + + zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + cuddDeref( zRes ); + + cuddCacheInsert1( dd, extraZddGetSingletons, bVars, zRes ); + return zRes; + } +} /* end of extraZddGetSingletons */ + + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_bddReduceVarSet.] + + Description [Returns the set of all variables in the given set that are not in the + support of the given function.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraBddReduceVarSet( + DdManager * dd, /* the DD manager */ + DdNode * bVars, /* the set of variables to be reduced */ + DdNode * bF) /* the function whose support is used for reduction */ +{ + DdNode * bRes; + DdNode * bFR = Cudd_Regular(bF); + + if ( cuddIsConstant(bFR) || bVars == b1 ) + return bVars; + + if ( bRes = cuddCacheLookup2(dd, extraBddReduceVarSet, bVars, bF) ) + return bRes; + else + { + DdNode * bF0, * bF1; + DdNode * bVarsThis, * bVarsLower, * bTemp; + int LevelF; + + // if LevelF is below LevelV, scroll through the vars in bVars + LevelF = dd->perm[bFR->index]; + for ( bVarsThis = bVars; LevelF > cuddI(dd,bVarsThis->index); bVarsThis = cuddT(bVarsThis) ); + // scroll also through the current var, because it should be not be added + if ( LevelF == cuddI(dd,bVarsThis->index) ) + bVarsLower = cuddT(bVarsThis); + else + bVarsLower = bVarsThis; + + // cofactor the function + if ( bFR != bF ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + // solve subproblems + bRes = extraBddReduceVarSet( dd, bVarsLower, bF0 ); + if ( bRes == NULL ) + return NULL; + cuddRef( bRes ); + + bRes = extraBddReduceVarSet( dd, bTemp = bRes, bF1 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + return NULL; + } + cuddRef( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + + // the current var should not be added + // add the skipped vars + if ( bVarsThis != bVars ) + { + DdNode * bVarsExtra; + + // extract the skipped variables + bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsThis ); + if ( bVarsExtra == NULL ) + { + Cudd_RecursiveDeref( dd, bRes ); + return NULL; + } + cuddRef( bVarsExtra ); + + // add these variables + bRes = cuddBddAndRecur( dd, bTemp = bRes, bVarsExtra ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bVarsExtra ); + return NULL; + } + cuddRef( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bVarsExtra ); + } + cuddDeref( bRes ); + + cuddCacheInsert2( dd, extraBddReduceVarSet, bVars, bF, bRes ); + return bRes; + } +} /* end of extraBddReduceVarSet */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_bddCheckVarsSymmetric().] + + Description [Returns b0 if the variables are not symmetric. Returns b1 if the + variables can be symmetric. The variables are represented in the form of a + two-variable cube. In case the cube contains one variable (below Var1 level), + the cube's pointer is complemented if the variable Var1 occurred on the + current path; otherwise, the cube's pointer is regular. Uses additional + complemented bit (Hash_Not) to mark the result if in the BDD rooted that this + node there is a branch passing though the node labeled with Var2.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraBddCheckVarsSymmetric( + DdManager * dd, /* the DD manager */ + DdNode * bF, + DdNode * bVars) +{ + DdNode * bRes; + + if ( bF == b0 ) + return b1; + + assert( bVars != b1 ); + + if ( bRes = cuddCacheLookup2(dd, extraBddCheckVarsSymmetric, bF, bVars) ) + return bRes; + else + { + DdNode * bRes0, * bRes1; + DdNode * bF0, * bF1; + DdNode * bFR = Cudd_Regular(bF); + int LevelF = cuddI(dd,bFR->index); + + DdNode * bVarsR = Cudd_Regular(bVars); + int fVar1Pres; + int iLev1; + int iLev2; + + if ( bVarsR != bVars ) // cube's pointer is complemented + { + assert( cuddT(bVarsR) == b1 ); + fVar1Pres = 1; // the first var is present on the path + iLev1 = -1; // we are already below the first var level + iLev2 = dd->perm[bVarsR->index]; // the level of the second var + } + else // cube's pointer is NOT complemented + { + fVar1Pres = 0; // the first var is absent on the path + if ( cuddT(bVars) == b1 ) + { + iLev1 = -1; // we are already below the first var level + iLev2 = dd->perm[bVars->index]; // the level of the second var + } + else + { + assert( cuddT(cuddT(bVars)) == b1 ); + iLev1 = dd->perm[bVars->index]; // the level of the first var + iLev2 = dd->perm[cuddT(bVars)->index]; // the level of the second var + } + } + + // cofactor the function + // the cofactors are needed only if we are above the second level + if ( LevelF < iLev2 ) + { + if ( bFR != bF ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + } + else + bF0 = bF1 = NULL; + + // consider five cases: + // (1) F is above iLev1 + // (2) F is on the level iLev1 + // (3) F is between iLev1 and iLev2 + // (4) F is on the level iLev2 + // (5) F is below iLev2 + + // (1) F is above iLev1 + if ( LevelF < iLev1 ) + { + // the returned result cannot have the hash attribute + // because we still did not reach the level of Var1; + // the attribute never travels above the level of Var1 + bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); +// assert( !Hash_IsComplement( bRes0 ) ); + assert( bRes0 != z0 ); + if ( bRes0 == b0 ) + bRes = b0; + else + bRes = extraBddCheckVarsSymmetric( dd, bF1, bVars ); +// assert( !Hash_IsComplement( bRes ) ); + assert( bRes != z0 ); + } + // (2) F is on the level iLev1 + else if ( LevelF == iLev1 ) + { + bRes0 = extraBddCheckVarsSymmetric( dd, bF0, Cudd_Not( cuddT(bVars) ) ); + if ( bRes0 == b0 ) + bRes = b0; + else + { + bRes1 = extraBddCheckVarsSymmetric( dd, bF1, Cudd_Not( cuddT(bVars) ) ); + if ( bRes1 == b0 ) + bRes = b0; + else + { +// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) + if ( bRes0 == z0 || bRes1 == z0 ) + bRes = b1; + else + bRes = b0; + } + } + } + // (3) F is between iLev1 and iLev2 + else if ( LevelF < iLev2 ) + { + bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); + if ( bRes0 == b0 ) + bRes = b0; + else + { + bRes1 = extraBddCheckVarsSymmetric( dd, bF1, bVars ); + if ( bRes1 == b0 ) + bRes = b0; + else + { +// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) +// bRes = Hash_Not( b1 ); + if ( bRes0 == z0 || bRes1 == z0 ) + bRes = z0; + else + bRes = b1; + } + } + } + // (4) F is on the level iLev2 + else if ( LevelF == iLev2 ) + { + // this is the only place where the hash attribute (Hash_Not) can be added + // to the result; it can be added only if the path came through the node + // lebeled with Var1; therefore, the hash attribute cannot be returned + // to the caller function + if ( fVar1Pres ) +// bRes = Hash_Not( b1 ); + bRes = z0; + else + bRes = b0; + } + // (5) F is below iLev2 + else // if ( LevelF > iLev2 ) + { + // it is possible that the path goes through the node labeled by Var1 + // and still everything is okay; we do not label with Hash_Not here + // because the path does not go through node labeled by Var2 + bRes = b1; + } + + cuddCacheInsert2(dd, extraBddCheckVarsSymmetric, bF, bVars, bRes); + return bRes; + } +} /* end of extraBddCheckVarsSymmetric */ + +/**Function******************************************************************** + + Synopsis [Performs the reordering-sensitive step of Extra_zddTupleFromBdd().] + + Description [Generates in a bottom-up fashion ZDD for all combinations + composed of k variables out of variables belonging to Support.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode* extraZddTuplesFromBdd( + DdManager * dd, /* the DD manager */ + DdNode * bVarsK, /* the number of variables in tuples */ + DdNode * bVarsN) /* the set of all variables */ +{ + DdNode *zRes, *zRes0, *zRes1; + statLine(dd); + + /* terminal cases */ +/* if ( k < 0 || k > n ) + * return dd->zero; + * if ( n == 0 ) + * return dd->one; + */ + if ( cuddI( dd, bVarsK->index ) < cuddI( dd, bVarsN->index ) ) + return z0; + if ( bVarsN == b1 ) + return z1; + + /* check cache */ + zRes = cuddCacheLookup2Zdd(dd, extraZddTuplesFromBdd, bVarsK, bVarsN); + if (zRes) + return(zRes); + + /* ZDD in which this variable is 0 */ +/* zRes0 = extraZddTuplesFromBdd( dd, k, n-1 ); */ + zRes0 = extraZddTuplesFromBdd( dd, bVarsK, cuddT(bVarsN) ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + /* ZDD in which this variable is 1 */ +/* zRes1 = extraZddTuplesFromBdd( dd, k-1, n-1 ); */ + if ( bVarsK == b1 ) + { + zRes1 = z0; + cuddRef( zRes1 ); + } + else + { + zRes1 = extraZddTuplesFromBdd( dd, cuddT(bVarsK), cuddT(bVarsN) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + } + + /* compose Res0 and Res1 with the given ZDD variable */ + zRes = cuddZddGetNode( dd, 2*bVarsN->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddTuplesFromBdd, bVarsK, bVarsN, zRes); + return zRes; + +} /* end of extraZddTuplesFromBdd */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddSelectOneSubset.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraZddSelectOneSubset( + DdManager * dd, + DdNode * zS ) +// selects one subset from the ZDD zS +// returns z0 if and only if zS is an empty set of cubes +{ + DdNode * zRes; + + if ( zS == z0 ) return z0; + if ( zS == z1 ) return z1; + + // check cache + if ( zRes = cuddCacheLookup1Zdd( dd, extraZddSelectOneSubset, zS ) ) + return zRes; + else + { + DdNode * zS0, * zS1, * zTemp; + + zS0 = cuddE(zS); + zS1 = cuddT(zS); + + if ( zS0 != z0 ) + { + zRes = extraZddSelectOneSubset( dd, zS0 ); + if ( zRes == NULL ) + return NULL; + } + else // if ( zS0 == z0 ) + { + assert( zS1 != z0 ); + zRes = extraZddSelectOneSubset( dd, zS1 ); + if ( zRes == NULL ) + return NULL; + cuddRef( zRes ); + + zRes = cuddZddGetNode( dd, zS->index, zTemp = zRes, z0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + return NULL; + } + cuddDeref( zTemp ); + } + + // insert the result into cache + cuddCacheInsert1( dd, extraZddSelectOneSubset, zS, zRes ); + return zRes; + } +} /* end of extraZddSelectOneSubset */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static Functions */ +/*---------------------------------------------------------------------------*/ diff --git a/src/misc/extra/extraUtilReader.c b/src/misc/extra/extraUtilReader.c index 2dc597bf..042dfaca 100644 --- a/src/misc/extra/extraUtilReader.c +++ b/src/misc/extra/extraUtilReader.c @@ -321,6 +321,7 @@ void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p ) // through EXTRA_OFFSET_SIZE chars till the end of the buffer if ( p->pBufferStop == p->pBufferEnd ) // end of file { + *pChar = 0; p->fStop = 1; return p->vTokens; } diff --git a/src/misc/extra/module.make b/src/misc/extra/module.make index 3098a23c..6cbf5d2c 100644 --- a/src/misc/extra/module.make +++ b/src/misc/extra/module.make @@ -1,4 +1,5 @@ -SRC += src/misc/extra/extraUtilBdd.c \ +SRC += src/misc/extra/extraBddMisc.c \ + src/misc/extra/extraBddSymm.c \ src/misc/extra/extraUtilBitMatrix.c \ src/misc/extra/extraUtilCanon.c \ src/misc/extra/extraUtilFile.c \ diff --git a/src/misc/vec/vecVec.h b/src/misc/vec/vecVec.h index bb911bfe..af7ca571 100644 --- a/src/misc/vec/vecVec.h +++ b/src/misc/vec/vecVec.h @@ -52,7 +52,7 @@ struct Vec_Vec_t_ #define Vec_VecForEachLevel( vGlob, vVec, i ) \ for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ ) #define Vec_VecForEachLevelStart( vGlob, vVec, i, LevelStart ) \ - for ( i = LevelStart; (i < Vec_PtrSize(vGlob)) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ ) + for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ ) #define Vec_VecForEachLevelStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \ for ( i = LevelStart; (i <= LevelStop) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ ) #define Vec_VecForEachLevelReverse( vGlob, vVec, i ) \ @@ -234,6 +234,25 @@ static inline void Vec_VecPush( Vec_Vec_t * p, int Level, void * Entry ) Vec_PtrPush( p->pArray[Level], Entry ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_VecPushUnique( Vec_Vec_t * p, int Level, void * Entry ) +{ + if ( p->nSize < Level + 1 ) + Vec_VecPush( p, Level, Entry ); + else + Vec_PtrPushUnique( p->pArray[Level], Entry ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// |