diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2005-10-02 08:01:00 -0700 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2005-10-02 08:01:00 -0700 |
commit | 91ca630b0fd316f0843dee8b9e6d236d849eb445 (patch) | |
tree | e43afba1c8b2180e981bf75aa02551fa7b2f7793 /src/base | |
parent | 78fbd336aa584c4d285123ad18617aa9277016b4 (diff) | |
download | abc-91ca630b0fd316f0843dee8b9e6d236d849eb445.tar.gz abc-91ca630b0fd316f0843dee8b9e6d236d849eb445.tar.bz2 abc-91ca630b0fd316f0843dee8b9e6d236d849eb445.zip |
Version abc51002
Diffstat (limited to 'src/base')
-rw-r--r-- | src/base/abci/abc.c | 191 | ||||
-rw-r--r-- | src/base/abci/abcCut.c | 70 | ||||
-rw-r--r-- | src/base/abcs/abcFpgaDelay.c | 327 | ||||
-rw-r--r-- | src/base/abcs/abcFpgaSeq.c | 201 | ||||
-rw-r--r-- | src/base/abcs/abcRetDelay.c | 6 | ||||
-rw-r--r-- | src/base/abcs/abcs.h | 26 |
6 files changed, 801 insertions, 20 deletions
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 4e2e14a2..ca9f1dfa 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -91,6 +91,8 @@ static int Abc_CommandPipe ( Abc_Frame_t * pAbc, int argc, char ** argv static int Abc_CommandSeq ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandUnseq ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -172,6 +174,8 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Sequential", "seq", Abc_CommandSeq, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "unseq", Abc_CommandUnseq, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "retime", Abc_CommandRetime, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "sfpga", Abc_CommandSeqFpga, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "smap", Abc_CommandSeqMap, 1 ); Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 ); Cmd_CommandAdd( pAbc, "Verification", "sec", Abc_CommandSec, 0 ); @@ -2735,16 +2739,20 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cut_Params_t Params, * pParams = &Params; Cut_Man_t * pCutMan; + Cut_Oracle_t * pCutOracle; FILE * pOut, * pErr; Abc_Ntk_t * pNtk; int c; + int fOracle; extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); + extern void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * pCutOracle ); pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults + fOracle = 0; memset( pParams, 0, sizeof(Cut_Params_t) ); pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts) pParams->nKeepMax = 1000; // the max number of cuts kept at a node @@ -2754,7 +2762,7 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) pParams->fMulti = 0; // use multi-input AND-gates pParams->fVerbose = 0; // the verbosiness flag util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "KMtfdmvh" ) ) != EOF ) + while ( ( c = util_getopt( argc, argv, "KMtfdmvoh" ) ) != EOF ) { switch ( c ) { @@ -2795,6 +2803,9 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'v': pParams->fVerbose ^= 1; break; + case 'o': + fOracle ^= 1; + break; case 'h': goto usage; default: @@ -2812,20 +2823,35 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Cut computation is available only for AIGs (run \"strash\").\n" ); return 1; } + if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX ) + { + fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX ); + return 1; + } + + if ( fOracle ) + pParams->fRecord = 1; pCutMan = Abc_NtkCuts( pNtk, pParams ); Cut_ManPrintStats( pCutMan ); + if ( fOracle ) + pCutOracle = Cut_OracleStart( pCutMan ); Cut_ManStop( pCutMan ); + if ( fOracle ) + { + Abc_NtkCutsOracle( pNtk, pCutOracle ); + Cut_OracleStop( pCutOracle ); + } return 0; usage: fprintf( pErr, "usage: cut [-K num] [-M num] [-tfdmvh]\n" ); fprintf( pErr, "\t computes k-feasible cuts for the AIG\n" ); - fprintf( pErr, "\t-K num : max number of leaves (4 <= num <= 6) [default = %d]\n", pParams->nVarsMax ); + fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); - fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); - fprintf( pErr, "\t-f : toggle filtering of duplicated/dominated [default = %s]\n", pParams->fFilter? "yes": "no" ); - fprintf( pErr, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" ); - fprintf( pErr, "\t-m : toggle using multi-input AND-gates [default = %s]\n", pParams->fMulti? "yes": "no" ); + fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); + fprintf( pErr, "\t-f : toggle filtering of duplicated/dominated [default = %s]\n", pParams->fFilter? "yes": "no" ); + fprintf( pErr, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" ); + fprintf( pErr, "\t-m : toggle using multi-input AND-gates [default = %s]\n", pParams->fMulti? "yes": "no" ); fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; @@ -2913,6 +2939,12 @@ int Abc_CommandScut( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Sequential cuts can be computed for sequential AIGs (run \"seq\").\n" ); return 1; } + if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX ) + { + fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX ); + return 1; + } + pCutMan = Abc_NtkSeqCuts( pNtk, pParams ); Cut_ManPrintStats( pCutMan ); Cut_ManStop( pCutMan ); @@ -2921,9 +2953,9 @@ int Abc_CommandScut( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: fprintf( pErr, "usage: scut [-K num] [-M num] [-tvh]\n" ); fprintf( pErr, "\t computes k-feasible cuts for the sequential AIG\n" ); - fprintf( pErr, "\t-K num : max number of leaves (4 <= num <= 6) [default = %d]\n", pParams->nVarsMax ); + fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); - fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); + fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; @@ -4434,6 +4466,149 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkFpgaSeq( Abc_Ntk_t * pNtk, int fVerbose ); + + pNtk = Abc_FrameReadNet(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 1; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsSeq(pNtk) ) + { + fprintf( pErr, "Works only for sequential AIG (run \"seq\").\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkFpgaSeq( pNtk, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Sequential FPGA mapping has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: sfpga [-vh]\n" ); + fprintf( pErr, "\t performs integrated sequential FPGA mapping\n" ); + fprintf( pErr, "\t-v : toggle 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_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkMapSeq( Abc_Ntk_t * pNtk, int fVerbose ); + + pNtk = Abc_FrameReadNet(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 1; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsSeq(pNtk) ) + { + fprintf( pErr, "Works only for sequential AIG (run \"seq\").\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkMapSeq( pNtk, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Sequential FPGA mapping has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: smap [-vh]\n" ); + fprintf( pErr, "\t performs integrated sequential standard-cell mapping" ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + /**Function************************************************************* diff --git a/src/base/abci/abcCut.c b/src/base/abci/abcCut.c index 7cc3d65b..8081c769 100644 --- a/src/base/abci/abcCut.c +++ b/src/base/abci/abcCut.c @@ -69,7 +69,7 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) if ( Abc_ObjFanoutNum(pObj) > 0 ) Cut_NodeSetTriv( p, pObj->Id ); // compute cuts for internal nodes - vNodes = Abc_AigDfs( pNtk, 0, 1 ); + vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs vChoices = Vec_IntAlloc( 100 ); Vec_PtrForEachEntry( vNodes, pObj, i ) { @@ -105,13 +105,72 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) if ( pParams->fMulti ) Abc_NtkBalanceDetach(pNtk); PRT( "Total", clock() - clk ); -Abc_NtkPrintCuts_( p, pNtk, 0 ); +//Abc_NtkPrintCuts_( p, pNtk, 0 ); // Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk ); return p; } /**Function************************************************************* + Synopsis [Cut computation using the oracle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p ) +{ + Abc_Obj_t * pObj; + Vec_Ptr_t * vNodes; + int i, clk = clock(); + int fDrop = Cut_OracleReadDrop(p); + + assert( Abc_NtkIsStrash(pNtk) ); + + // prepare cut droppping + if ( fDrop ) + Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); + + // set cuts for PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_OracleNodeSetTriv( p, pObj->Id ); + + // compute cuts for internal nodes + vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // when we reached a CO, it is time to deallocate the cuts + if ( Abc_ObjIsCo(pObj) ) + { + if ( fDrop ) + Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + continue; + } + // skip constant node, it has no cuts + if ( Abc_NodeIsConst(pObj) ) + continue; + // compute the cuts to the internal node + Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), + Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); + // consider dropping the fanins cuts + if ( fDrop ) + { + Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); + } + } + Vec_PtrFree( vNodes ); +//PRT( "Total", clock() - clk ); +//Abc_NtkPrintCuts_( p, pNtk, 0 ); +} + + +/**Function************************************************************* + Synopsis [Computes the cuts for the network.] Description [] @@ -156,7 +215,6 @@ Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) // compute the cuts for the internal nodes Abc_AigForEachAnd( pNtk, pObj, i ) Abc_NodeGetCutsSeq( p, pObj, nIters==0 ); -Abc_NtkPrintCuts( p, pNtk, 1 ); // merge the new cuts with the old cuts Abc_NtkForEachPi( pNtk, pObj, i ) Cut_NodeNewMergeWithOld( p, pObj->Id ); @@ -183,7 +241,7 @@ Abc_NtkPrintCuts( p, pNtk, 1 ); pObj->fMarkC = 0; PRT( "Total", clock() - clk ); printf( "Converged after %d iterations.\n", nIters ); -Abc_NtkPrintCuts( p, pNtk, 1 ); +//Abc_NtkPrintCuts( p, pNtk, 1 ); return p; } @@ -225,7 +283,7 @@ void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fMulti ) assert( Abc_NtkIsStrash(pObj->pNtk) ); assert( Abc_ObjFaninNum(pObj) == 2 ); return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), - Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), 1, 1, fTriv ); + Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv ); } /**Function************************************************************* @@ -244,7 +302,7 @@ void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv ) int CutSetNum; assert( Abc_NtkIsSeq(pObj->pNtk) ); assert( Abc_ObjFaninNum(pObj) == 2 ); -// fTriv = pObj->fMarkC ? 0 : fTriv; + fTriv = pObj->fMarkC ? 0 : fTriv; CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1; Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Abc_ObjFaninL0(pObj), Abc_ObjFaninL1(pObj), fTriv, CutSetNum ); diff --git a/src/base/abcs/abcFpgaDelay.c b/src/base/abcs/abcFpgaDelay.c new file mode 100644 index 00000000..1b957093 --- /dev/null +++ b/src/base/abcs/abcFpgaDelay.c @@ -0,0 +1,327 @@ +/**CFile**************************************************************** + + FileName [abcFpgaDelay.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Utilities working sequential AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFpgaDelay.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abcs.h" +#include "cut.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the internal procedures +static int Abc_NtkFpgaRetimeSearch_rec( Seq_FpgaMan_t * p, Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose ); +static int Abc_NtkFpgaRetimeForPeriod( Seq_FpgaMan_t * p, Abc_Ntk_t * pNtk, int Fi, int fVerbose ); +static int Abc_NodeFpgaUpdateLValue( Seq_FpgaMan_t * p, Abc_Obj_t * pObj, int Fi ); +static void Abc_NtkFpgaCollect( Seq_FpgaMan_t * p ); + +// node status after updating its arrival time +enum { ABC_FPGA_UPDATE_FAIL, ABC_FPGA_UPDATE_NO, ABC_FPGA_UPDATE_YES }; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Retimes AIG for optimal delay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFpgaSeqRetimeDelayLags( Seq_FpgaMan_t * p ) +{ + Abc_Ntk_t * pNtk = p->pNtk; + int fVerbose = p->fVerbose; + Abc_Obj_t * pNode; + int i, FiMax, FiBest, RetValue; + + // start storage for sequential arrival times + assert( pNtk->pData == NULL ); + pNtk->pData = p->vArrivals; + + // get the upper bound on the clock period +// FiMax = Abc_NtkNodeNum(pNtk); + FiMax = 0; + Abc_AigForEachAnd( pNtk, pNode, i ) + if ( FiMax < (int)pNode->Level ) + FiMax = pNode->Level; + FiMax += 2; + + // make sure this clock period is feasible + assert( Abc_NtkFpgaRetimeForPeriod( p, pNtk, FiMax, fVerbose ) ); + + // search for the optimal clock period between 0 and nLevelMax + FiBest = Abc_NtkFpgaRetimeSearch_rec( p, pNtk, 0, FiMax, fVerbose ); + + // recompute the best LValues + RetValue = Abc_NtkFpgaRetimeForPeriod( p, pNtk, FiBest, fVerbose ); + assert( RetValue ); + + // print the result + if ( fVerbose ) + printf( "The best clock period is %3d.\n", FiBest ); + + // convert to lags + Abc_AigForEachAnd( pNtk, pNode, i ) + Vec_StrWriteEntry( p->vLagsMap, i, (char)Abc_NodeGetLag(Abc_NodeReadLValue(pNode), FiBest) ); +/* + printf( "LValues : " ); + Abc_AigForEachAnd( pNtk, pNode, i ) + printf( "%d=%d ", i, Abc_NodeReadLValue(pNode) ); + printf( "\n" ); + printf( "Lags : " ); + Abc_AigForEachAnd( pNtk, pNode, i ) + if ( Vec_StrEntry(vLags,i) != 0 ) + printf( "%d=%d(%d)(%d) ", i, Vec_StrEntry(vLags,i), Abc_NodeReadLValue(pNode), Abc_NodeReadLValue(pNode) - FiBest * Vec_StrEntry(vLags,i) ); + printf( "\n" ); +*/ + Abc_NtkFpgaCollect( p ); + + pNtk->pData = NULL; + + Cut_ManStop( p->pMan ); + p->pMan = NULL; +} + +/**Function************************************************************* + + Synopsis [Performs binary search for the optimal clock period.] + + Description [Assumes that FiMin is infeasible while FiMax is feasible.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkFpgaRetimeSearch_rec( Seq_FpgaMan_t * p, Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose ) +{ + int Median; + assert( FiMin < FiMax ); + if ( FiMin + 1 == FiMax ) + return FiMax; + Median = FiMin + (FiMax - FiMin)/2; + if ( Abc_NtkFpgaRetimeForPeriod( p, pNtk, Median, fVerbose ) ) + return Abc_NtkFpgaRetimeSearch_rec( p, pNtk, FiMin, Median, fVerbose ); // Median is feasible + else + return Abc_NtkFpgaRetimeSearch_rec( p, pNtk, Median, FiMax, fVerbose ); // Median is infeasible +} + +/**Function************************************************************* + + Synopsis [Returns 1 if retiming with this clock period is feasible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkFpgaRetimeForPeriod( Seq_FpgaMan_t * p, Abc_Ntk_t * pNtk, int Fi, int fVerbose ) +{ + Abc_Obj_t * pObj; + int i, c, RetValue, fChange, Counter; + char * pReason = ""; + + // set l-values of all nodes to be minus infinity + Vec_IntFill( p->vArrivals, Abc_NtkObjNumMax(pNtk), -ABC_INFINITY ); + Vec_PtrFill( p->vBestCuts, Abc_NtkObjNumMax(pNtk), NULL ); + + // set l-values for the constant and PIs + pObj = Abc_NtkObj( pNtk, 0 ); + Abc_NodeSetLValue( pObj, 0 ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NodeSetLValue( pObj, 0 ); + + // update all values iteratively + Counter = 0; + for ( c = 0; c < 20; c++ ) + { + fChange = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( Abc_ObjIsPi(pObj) ) + continue; + if ( Abc_ObjFaninNum(pObj) == 0 ) + continue; + RetValue = Abc_NodeFpgaUpdateLValue( p, pObj, Fi ); + Counter++; + if ( RetValue == ABC_FPGA_UPDATE_FAIL ) + break; + if ( RetValue == ABC_FPGA_UPDATE_NO ) + continue; + fChange = 1; + } + if ( RetValue == ABC_FPGA_UPDATE_FAIL ) + break; + if ( fChange == 0 ) + break; + } + if ( c == 20 ) + { + RetValue = ABC_FPGA_UPDATE_FAIL; + pReason = "(timeout)"; + } + + // report the results + if ( fVerbose ) + { + if ( RetValue == ABC_FPGA_UPDATE_FAIL ) + printf( "Period = %3d. Iterations = %3d. Updates = %6d. Infeasible %s\n", Fi, c, Counter, pReason ); + else + printf( "Period = %3d. Iterations = %3d. Updates = %6d. Feasible\n", Fi, c, Counter ); + } + return RetValue != ABC_FPGA_UPDATE_FAIL; +} + +/**Function************************************************************* + + Synopsis [Computes the l-value of the node.] + + Description [The node can be internal or a PO.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeFpgaUpdateLValue( Seq_FpgaMan_t * p, Abc_Obj_t * pObj, int Fi ) +{ + Abc_Obj_t * pFanin; + Cut_Cut_t * pList, * pCut, * pCutBest; + int lValueNew, lValueOld, lValueCur, lValueFan; + int i; + + assert( !Abc_ObjIsPi(pObj) ); + assert( Abc_ObjFaninNum(pObj) > 0 ); + + if ( Abc_ObjIsPo(pObj) ) + { + lValueOld = Abc_NodeReadLValue(Abc_ObjFanin0(pObj)); + lValueNew = lValueOld - Fi * Abc_ObjFaninL0(pObj); + return (lValueNew > Fi)? ABC_FPGA_UPDATE_FAIL : ABC_FPGA_UPDATE_NO; + } + + pCutBest = NULL; + lValueNew = ABC_INFINITY; + pList = Abc_NodeReadCuts( p->pMan, pObj ); + for ( pCut = pList; pCut; pCut = pCut->pNext ) + { + if ( pCut->nLeaves < 2 ) + continue; + lValueCur = -ABC_INFINITY; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + pFanin = Abc_NtkObj( pObj->pNtk, (pCut->pLeaves[i] >> CUT_SHIFT) ); + lValueFan = Abc_NodeReadLValue(pFanin) - Fi * (pCut->pLeaves[i] & CUT_MASK); + lValueCur = ABC_MAX( lValueCur, lValueFan ); + } + lValueCur += 1; + lValueNew = ABC_MIN( lValueNew, lValueCur ); + if ( lValueNew == lValueCur ) + pCutBest = pCut; + } + + lValueOld = Abc_NodeReadLValue(pObj); +// if ( lValueNew == lValueOld ) + if ( lValueNew <= lValueOld ) + return ABC_FPGA_UPDATE_NO; + + Abc_NodeSetLValue( pObj, lValueNew ); + Vec_PtrWriteEntry( p->vBestCuts, pObj->Id, pCutBest ); + return ABC_FPGA_UPDATE_YES; +} + + + +/**Function************************************************************* + + Synopsis [Select nodes visible in the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeFpgaCollect_rec( Seq_FpgaMan_t * p, Abc_Obj_t * pNode ) +{ + Cut_Cut_t * pCutBest; + Abc_Obj_t * pFanin; + Vec_Int_t * vLeaves; + int i; + // skip the CI + if ( Abc_ObjIsCi(pNode) ) + return; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // get the best cut of the node + pCutBest = Vec_PtrEntry( p->vBestCuts, pNode->Id ); + for ( i = 0; i < (int)pCutBest->nLeaves; i++ ) + { + pFanin = Abc_NtkObj( pNode->pNtk, (pCutBest->pLeaves[i] >> CUT_SHIFT) ); + Abc_NodeFpgaCollect_rec( p, pFanin ); + } + // collect the node and its cut + vLeaves = Vec_IntAlloc( pCutBest->nLeaves ); + for ( i = 0; i < (int)pCutBest->nLeaves; i++ ) + Vec_IntPush( vLeaves, pCutBest->pLeaves[i] ); + Vec_PtrPush( p->vMapCuts, vLeaves ); + Vec_PtrPush( p->vMapping, pNode ); +} + +/**Function************************************************************* + + Synopsis [Select nodes visible in the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFpgaCollect( Seq_FpgaMan_t * p ) +{ + Abc_Ntk_t * pNtk = p->pNtk; + Abc_Obj_t * pObj; + int i; + Vec_PtrClear( p->vMapping ); + Vec_PtrClear( p->vMapCuts ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NodeFpgaCollect_rec( p, Abc_ObjFanin0(pObj) ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abcs/abcFpgaSeq.c b/src/base/abcs/abcFpgaSeq.c new file mode 100644 index 00000000..d68c2082 --- /dev/null +++ b/src/base/abcs/abcFpgaSeq.c @@ -0,0 +1,201 @@ +/**CFile**************************************************************** + + FileName [abcFpgaSeq.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Mapping for FPGAs using sequential cuts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFpgaSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abcs.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +Abc_Ntk_t * Abc_NtkMapSeq( Abc_Ntk_t * pNtk, int fVerbose ) { return 0; } + +extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); +extern void Abc_NtkFpgaSeqRetimeDelayLags( Seq_FpgaMan_t * p ); + +static Seq_FpgaMan_t * Abc_NtkFpgaSeqStart( Abc_Ntk_t * pNtk, int fVerbose ); +static void Abc_NtkFpgaSeqStop( Seq_FpgaMan_t * p ); + +static Abc_Ntk_t * Abc_NtkFpgaSeqConstruct( Seq_FpgaMan_t * p ); +static void Abc_NtkFpgaSeqRetime( Seq_FpgaMan_t * p, Abc_Ntk_t * pNtkNew ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Retimes AIG for optimal delay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFpgaSeq( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew; + Seq_FpgaMan_t * p; + Cut_Params_t Params, * pParams = &Params; + int clk; + + assert( Abc_NtkIsSeq( pNtk ) ); + + // get the sequential FPGA manager + p = Abc_NtkFpgaSeqStart( pNtk, fVerbose ); + + // create the cuts + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts) + pParams->nKeepMax = 1000; // the max number of cuts kept at a node + pParams->fTruth = 0; // compute truth tables + pParams->fFilter = 1; // filter dominated cuts + pParams->fSeq = 1; // compute sequential cuts + pParams->fVerbose = 0; // the verbosiness flag + +clk = clock(); + p->pMan = Abc_NtkSeqCuts( pNtk, pParams ); +p->timeCuts += clock() - clk; + + // find best arrival times (p->vArrivals) and free the cuts + // select mapping (p->vMapping) and remember best cuts (p->vMapCuts) +clk = clock(); + Abc_NtkFpgaSeqRetimeDelayLags( p ); +p->timeDelay += clock() - clk; + +return NULL; + + // construct the network +clk = clock(); + pNtkNew = Abc_NtkFpgaSeqConstruct( p ); +p->timeNtk += clock() - clk; + + // retime the network +clk = clock(); + Abc_NtkFpgaSeqRetime( p, pNtkNew ); +p->timeRet += clock() - clk; + + // remove temporaries + Abc_NtkFpgaSeqStop( p ); + + // check the resulting network + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkFpgaSeq(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Starts sequential FPGA mapper.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Seq_FpgaMan_t * Abc_NtkFpgaSeqStart( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Seq_FpgaMan_t * p; + // create the FPGA mapping manager + p = ALLOC( Seq_FpgaMan_t, 1 ); + memset( p, 0, sizeof(Seq_FpgaMan_t) ); + p->pNtk = pNtk; + p->pMan = NULL; + p->vArrivals = Vec_IntAlloc( 0 ); + p->vBestCuts = Vec_PtrAlloc( 0 ); + p->vMapping = Vec_PtrAlloc( 0 ); + p->vMapCuts = Vec_PtrAlloc( 0 ); + p->vLagsMap = Vec_StrStart( Abc_NtkObjNumMax(pNtk) ); + p->fVerbose = fVerbose; + return p; +} + +/**Function************************************************************* + + Synopsis [Stops sequential FPGA mapper.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFpgaSeqStop( Seq_FpgaMan_t * p ) +{ + if ( p->fVerbose ) + { + printf( "Sequential FPGA mapping stats:\n" ); +// printf( "Total allocated = %8d.\n", p->nCutsAlloc ); +// printf( "Cuts per node = %8.1f\n", ((float)(p->nCutsCur-p->nCutsTriv))/p->nNodes ); + PRT( "Cuts ", p->timeCuts ); + PRT( "Arrival", p->timeDelay ); + PRT( "Network", p->timeNtk ); + PRT( "Retime ", p->timeRet ); + } + Vec_IntFree( p->vArrivals ); + Vec_PtrFree( p->vBestCuts ); + Vec_PtrFree( p->vMapping ); + Vec_VecFree( (Vec_Vec_t *)p->vMapCuts ); + Vec_StrFree( p->vLagsMap ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Construct the final network after mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFpgaSeqConstruct( Seq_FpgaMan_t * p ) +{ + Abc_Ntk_t * pNtk = NULL; + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Retimes the final network after mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFpgaSeqRetime( Seq_FpgaMan_t * p, Abc_Ntk_t * pNtkNew ) +{ +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abcs/abcRetDelay.c b/src/base/abcs/abcRetDelay.c index 0697c699..0eda33c9 100644 --- a/src/base/abcs/abcRetDelay.c +++ b/src/base/abcs/abcRetDelay.c @@ -24,12 +24,6 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -// storing arrival times in the nodes -static inline int Abc_NodeReadLValue( Abc_Obj_t * pNode ) { return Vec_IntEntry( (pNode)->pNtk->pData, (pNode)->Id ); } -static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { Vec_IntWriteEntry( (pNode)->pNtk->pData, (pNode)->Id, (Value) ); } -//static inline int Abc_NodeGetLag( int LValue, int Fi ) { return LValue/Fi - (int)(LValue % Fi == 0); } -static inline int Abc_NodeGetLag( int LValue, int Fi ) { return (LValue + 256*Fi)/Fi - 256 - (int)(LValue % Fi == 0); } - // the internal procedures static int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose ); static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, int Fi, int fVerbose ); diff --git a/src/base/abcs/abcs.h b/src/base/abcs/abcs.h index fb45efba..e250d929 100644 --- a/src/base/abcs/abcs.h +++ b/src/base/abcs/abcs.h @@ -26,6 +26,7 @@ //////////////////////////////////////////////////////////////////////// #include "abc.h" +#include "cut.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -38,6 +39,25 @@ /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// +typedef struct Seq_FpgaMan_t_ Seq_FpgaMan_t; +struct Seq_FpgaMan_t_ +{ + Abc_Ntk_t * pNtk; // the network to be mapped + Cut_Man_t * pMan; // the cut manager + Vec_Int_t * vArrivals; // the arrival times (L-Values of nodes) + Vec_Ptr_t * vBestCuts; // the best cuts for nodes + Vec_Ptr_t * vMapping; // the nodes used in the mapping + Vec_Ptr_t * vMapCuts; // the info about the cut of each mapped node + Vec_Str_t * vLagsMap; // the lags of the mapped nodes + int fVerbose; // the verbose flag + // runtime stats + int timeCuts; // runtime to compute the cuts + int timeDelay; // runtime to compute the L-values + int timeRet; // runtime to retime the resulting network + int timeNtk; // runtime to create the final network +}; + + // representation of latch on the edge typedef struct Abc_RetEdge_t_ Abc_RetEdge_t; struct Abc_RetEdge_t_ // 1 word @@ -61,6 +81,12 @@ static inline Abc_RetEdge_t Abc_Int2RetEdge( int Num ) { return *((A static inline int Abc_RetStep2Int( Abc_RetStep_t Str ) { return *((int *)&Str); } static inline Abc_RetStep_t Abc_Int2RetStep( int Num ) { return *((Abc_RetStep_t *)&Num); } +// storing arrival times in the nodes +static inline int Abc_NodeReadLValue( Abc_Obj_t * pNode ) { return Vec_IntEntry( (pNode)->pNtk->pData, (pNode)->Id ); } +static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { Vec_IntWriteEntry( (pNode)->pNtk->pData, (pNode)->Id, (Value) ); } +//static inline int Abc_NodeGetLag( int LValue, int Fi ) { return LValue/Fi - (int)(LValue % Fi == 0); } +static inline int Abc_NodeGetLag( int LValue, int Fi ) { return (LValue + 256*Fi)/Fi - 256 - (int)(LValue % Fi == 0); } + //////////////////////////////////////////////////////////////////////// /// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// |