blob: 903491d6087269901b4e9833a6210a28ad6f586c [file] [log] [blame]
/**CFile****************************************************************
FileName [ifSeq.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [FPGA mapping based on priority cuts.]
Synopsis [Sequential mapping.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 21, 2006.]
Revision [$Id: ifSeq.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
***********************************************************************/
#include "if.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
extern abctime s_MappingTime;
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Prepares for sequential mapping by linking the latches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManPrepareMappingSeq( If_Man_t * p )
{
If_Obj_t * pObjLi, * pObjLo;
int i;
// link the latch outputs (CIs) directly to the drivers of latch inputs (COs)
for ( i = 0; i < p->pPars->nLatchesCi; i++ )
{
pObjLi = If_ManLi( p, i );
pObjLo = If_ManLo( p, i );
pObjLo->pFanin0 = If_ObjFanin0( pObjLi );
pObjLo->fCompl0 = If_ObjFaninC0( pObjLi );
}
}
/**Function*************************************************************
Synopsis [Collects latches in the topological order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManCollectLatches_rec( If_Obj_t * pObj, Vec_Ptr_t * vLatches )
{
if ( !If_ObjIsLatch(pObj) )
return;
if ( pObj->fMark )
return;
pObj->fMark = 1;
If_ManCollectLatches_rec( pObj->pFanin0, vLatches );
Vec_PtrPush( vLatches, pObj );
}
/**Function*************************************************************
Synopsis [Collects latches in the topological order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * If_ManCollectLatches( If_Man_t * p )
{
Vec_Ptr_t * vLatches;
If_Obj_t * pObj;
int i;
// collect latches
vLatches = Vec_PtrAlloc( p->pPars->nLatchesCi );
If_ManForEachLatchOutput( p, pObj, i )
If_ManCollectLatches_rec( pObj, vLatches );
// clean marks
Vec_PtrForEachEntry( If_Obj_t *, vLatches, pObj, i )
pObj->fMark = 0;
assert( Vec_PtrSize(vLatches) == p->pPars->nLatchesCi );
return vLatches;
}
/**Function*************************************************************
Synopsis [Performs one pass of l-value computation over all nodes.]
Description [Experimentally it was found that checking POs changes
is not enough to detect the convergence of l-values in the network.]
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManPerformMappingRoundSeq( If_Man_t * p, int nIter )
{
If_Obj_t * pObj;
int i;
abctime clk = Abc_Clock();
int fVeryVerbose = 0;
int fChange = 0;
if ( nIter == 1 )
{
// if some latches depend on PIs, update their values
Vec_PtrForEachEntry( If_Obj_t *, p->vLatchOrder, pObj, i )
{
If_ObjSetLValue( pObj, If_ObjLValue(If_ObjFanin0(pObj)) - p->Period );
If_ObjSetArrTime( pObj, If_ObjLValue(pObj) );
}
}
// map the internal nodes
p->nCutsMerged = 0;
If_ManForEachNode( p, pObj, i )
{
If_ObjPerformMappingAnd( p, pObj, 0, 0, 0 );
if ( pObj->fRepr )
If_ObjPerformMappingChoice( p, pObj, 0, 0 );
}
// postprocess the mapping
//Abc_Print( 1, "Itereation %d: \n", nIter );
If_ManForEachNode( p, pObj, i )
{
// update the LValues stored separately
if ( If_ObjLValue(pObj) < If_ObjCutBest(pObj)->Delay - p->fEpsilon )
{
If_ObjSetLValue( pObj, If_ObjCutBest(pObj)->Delay );
fChange = 1;
}
//Abc_Print( 1, "%d ", (int)If_ObjLValue(pObj) );
// reset the visit counters
assert( pObj->nVisits == 0 );
pObj->nVisits = pObj->nVisitsCopy;
}
//Abc_Print( 1, "\n" );
// propagate LValues over the registers
Vec_PtrForEachEntry( If_Obj_t *, p->vLatchOrder, pObj, i )
{
If_ObjSetLValue( pObj, If_ObjLValue(If_ObjFanin0(pObj)) - p->Period );
If_ObjSetArrTime( pObj, If_ObjLValue(pObj) );
}
// compute area and delay
If_ManMarkMapping( p );
if ( fVeryVerbose )
{
p->RequiredGlo = If_ManDelayMax( p, 1 );
// p->AreaGlo = If_ManScanMapping(p);
Abc_Print( 1, "S%d: Fi = %6.2f. Del = %6.2f. Area = %8.2f. Cuts = %8d. ",
nIter, (float)p->Period, p->RequiredGlo, p->AreaGlo, p->nCutsMerged );
Abc_PrintTime( 1, "T", Abc_Clock() - clk );
}
return fChange;
}
/**Function*************************************************************
Synopsis [Returns 1 if retiming with this clock period is feasible.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManBinarySearchPeriod( If_Man_t * p )
{
If_Obj_t * pObj;
int i, c, fConverged;
// int fResetRefs = 0;
p->nAttempts++;
// reset initial LValues (PIs to 0; others to -inf)
If_ManForEachObj( p, pObj, i )
{
If_ObjSetLValue( pObj, (float)-IF_INFINITY );
If_ObjSetArrTime( pObj, (float)-IF_INFINITY );
// undo any previous mapping, except for CIs
if ( If_ObjIsAnd(pObj) )
If_ObjCutBest(pObj)->nLeaves = 0;
}
pObj = If_ManConst1( p );
If_ObjSetLValue( pObj, (float)0.0 );
If_ObjSetArrTime( pObj, (float)0.0 );
If_ManForEachPi( p, pObj, i )
{
pObj = If_ManCi( p, i );
If_ObjSetLValue( pObj, (float)0.0 );
If_ObjSetArrTime( pObj, (float)0.0 );
}
// update all values iteratively
fConverged = 0;
for ( c = 1; c <= p->nMaxIters; c++ )
{
if ( !If_ManPerformMappingRoundSeq( p, c ) )
{
p->RequiredGlo = If_ManDelayMax( p, 1 );
fConverged = 1;
break;
}
p->RequiredGlo = If_ManDelayMax( p, 1 );
//Abc_Print( 1, "Global = %d \n", (int)p->RequiredGlo );
if ( p->RequiredGlo > p->Period + p->fEpsilon )
break;
}
// report the results
If_ManMarkMapping( p );
if ( p->pPars->fVerbose )
{
// p->AreaGlo = If_ManScanMapping(p);
Abc_Print( 1, "Attempt = %2d. Iters = %3d. Area = %10.2f. Fi = %6.2f. ", p->nAttempts, c, p->AreaGlo, (float)p->Period );
if ( fConverged )
Abc_Print( 1, " Feasible" );
else if ( c > p->nMaxIters )
Abc_Print( 1, "Infeasible (timeout)" );
else
Abc_Print( 1, "Infeasible" );
Abc_Print( 1, "\n" );
}
return fConverged;
}
/**Function*************************************************************
Synopsis [Performs binary search for the optimal clock period.]
Description [Assumes that FiMin is infeasible while FiMax is feasible.]
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManBinarySearch_rec( If_Man_t * p, int FiMin, int FiMax )
{
assert( FiMin < FiMax );
if ( FiMin + 1 == FiMax )
return FiMax;
// compute the median
p->Period = FiMin + (FiMax - FiMin)/2;
if ( If_ManBinarySearchPeriod( p ) )
return If_ManBinarySearch_rec( p, FiMin, p->Period ); // Median is feasible
else
return If_ManBinarySearch_rec( p, p->Period, FiMax ); // Median is infeasible
}
/**Function*************************************************************
Synopsis [Performs sequential mapping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManPerformMappingSeqPost( If_Man_t * p )
{
If_Obj_t * pObjLi, * pObjLo, * pObj;
int i;
assert( 0 );
// set arrival times
assert( p->pPars->pTimesArr != NULL );
If_ManForEachLatchOutput( p, pObjLo, i )
p->pPars->pTimesArr[i] = If_ObjLValue(pObjLo);
// set the required times
assert( p->pPars->pTimesReq == NULL );
p->pPars->pTimesReq = ABC_ALLOC( float, If_ManCoNum(p) );
If_ManForEachPo( p, pObj, i )
p->pPars->pTimesReq[i] = p->RequiredGlo2;
If_ManForEachLatchInput( p, pObjLi, i )
p->pPars->pTimesReq[i] = If_ObjLValue(If_ObjFanin0(pObjLi));
// undo previous mapping
If_ManForEachObj( p, pObj, i )
if ( If_ObjIsAnd(pObj) )
If_ObjCutBest(pObj)->nLeaves = 0;
// map again combinationally
// p->pPars->fSeqMap = 0;
If_ManPerformMappingComb( p );
// p->pPars->fSeqMap = 1;
}
/**Function*************************************************************
Synopsis [Performs sequential mapping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManPerformMappingSeq( If_Man_t * p )
{
abctime clkTotal = Abc_Clock();
int PeriodBest;
p->SortMode = 0;
// perform combinational mapping to get the upper bound on the clock period
If_ManPerformMappingRound( p, 1, 0, 0, 1, NULL );
p->RequiredGlo = If_ManDelayMax( p, 0 );
p->RequiredGlo2 = p->RequiredGlo;
// set direct linking of latches with their inputs
If_ManPrepareMappingSeq( p );
// collect latches
p->vLatchOrder = If_ManCollectLatches( p );
// set parameters
p->nCutsUsed = p->pPars->nCutsMax;
p->nAttempts = 0;
p->nMaxIters = 50;
p->Period = (int)p->RequiredGlo;
// make sure the clock period works
if ( !If_ManBinarySearchPeriod( p ) )
{
Abc_Print( 1, "If_ManPerformMappingSeq(): The upper bound on the clock period cannot be computed.\n" );
return 0;
}
// perform binary search
PeriodBest = If_ManBinarySearch_rec( p, 0, p->Period );
// recompute the best l-values
if ( p->Period != PeriodBest )
{
p->Period = PeriodBest;
if ( !If_ManBinarySearchPeriod( p ) )
{
Abc_Print( 1, "If_ManPerformMappingSeq(): The final clock period cannot be confirmed.\n" );
return 0;
}
}
// if ( p->pPars->fVerbose )
{
Abc_Print( 1, "The best clock period is %3d. ", p->Period );
Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
}
p->RequiredGlo = (float)(PeriodBest);
// postprocess it using combinational mapping
If_ManPerformMappingSeqPost( p );
s_MappingTime = Abc_Clock() - clkTotal;
return 1;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END