diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2012-12-13 15:18:53 -0800 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2012-12-13 15:18:53 -0800 |
commit | 82050bbe111a25b808f26b9196c797e7d2e1b916 (patch) | |
tree | 057e9ca6fb54381405d0aa018b5d5e2abe251ce2 | |
parent | 5ef3c1db3abea9270796e270e42e88e74a6e5587 (diff) | |
download | abc-82050bbe111a25b808f26b9196c797e7d2e1b916.tar.gz abc-82050bbe111a25b808f26b9196c797e7d2e1b916.tar.bz2 abc-82050bbe111a25b808f26b9196c797e7d2e1b916.zip |
Assembling timing/hierarchy manager from input data.
-rw-r--r-- | src/aig/gia/giaAiger.c | 17 | ||||
-rw-r--r-- | src/base/abc/abc.h | 1 | ||||
-rw-r--r-- | src/base/abc/abcUtil.c | 36 | ||||
-rw-r--r-- | src/base/abci/abc.c | 15 | ||||
-rw-r--r-- | src/base/abci/abcTim.c | 197 | ||||
-rw-r--r-- | src/map/if/ifLibBox.c | 1 | ||||
-rw-r--r-- | src/misc/tim/tim.h | 2 | ||||
-rw-r--r-- | src/misc/tim/timMan.c | 30 |
8 files changed, 170 insertions, 129 deletions
diff --git a/src/aig/gia/giaAiger.c b/src/aig/gia/giaAiger.c index c837763b..eabeb5a1 100644 --- a/src/aig/gia/giaAiger.c +++ b/src/aig/gia/giaAiger.c @@ -21,6 +21,7 @@ #include "gia.h" #include "misc/tim/tim.h" +#include "base/main/main.h" ABC_NAMESPACE_IMPL_START @@ -176,7 +177,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fSkipS Gia_Man_t * pNew, * pTemp; Vec_Int_t * vLits = NULL, * vPoTypes = NULL; Vec_Int_t * vNodes, * vDrivers;//, * vTerms; - int iObj, iNode0, iNode1; + int iObj, iNode0, iNode1, fHieOnly = 0; int nTotal, nInputs, nOutputs, nLatches, nAnds, i;//, iTerm, nDigits; int nBad = 0, nConstr = 0, nJust = 0, nFair = 0; unsigned char * pDrivers, * pSymbols, * pCur;//, * pType; @@ -561,6 +562,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fSkipS pCur += Vec_StrSize(vStr); pNew->pManTime = Tim_ManLoad( vStr, 1 ); Vec_StrFree( vStr ); + fHieOnly = 1; } // read packing else if ( *pCur == 'k' ) @@ -669,11 +671,21 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fSkipS pNew->vObjClasses = vObjMap; pNew->pManTime = pManTime; } + + if ( fHieOnly ) + { + Tim_ManPrint( pNew->pManTime ); + Tim_ManCreate( pNew->pManTime, Abc_FrameReadLibBox(), pNew->vInArrs, pNew->vOutReqs ); + Tim_ManPrint( pNew->pManTime ); + } + +/* if ( pNew->pManTime ) { pNew = Gia_ManDupUnnomalize( pTemp = pNew ); Gia_ManStop( pTemp ); } +*/ /* // check the result if ( fCheck && !Gia_ManCheck( pNew ) ) @@ -909,6 +921,7 @@ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int int i, nBufferSize, Pos; unsigned char * pBuffer; unsigned uLit0, uLit1, uLit; + assert( Gia_ManIsNormalized(pInit) ); if ( Gia_ManCoNum(pInit) == 0 ) { @@ -1112,6 +1125,7 @@ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int Gia_FileWriteBufferSize( pFile, Gia_ManObjNum(p) ); fwrite( p->pSwitching, 1, Gia_ManObjNum(p), pFile ); } +/* // write timing information if ( p->pManTime ) { @@ -1121,6 +1135,7 @@ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); Vec_StrFree( vStrExt ); } +*/ // write object classes if ( p->vObjClasses ) { diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 30e3ad92..3180dac8 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -973,6 +973,7 @@ extern ABC_DLL void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkInvertConstraints( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkPrintCiLevels( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkReverseTopoOrder( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkIsTopo( Abc_Ntk_t * pNtk ); diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c index be16c834..8909a15d 100644 --- a/src/base/abc/abcUtil.c +++ b/src/base/abc/abcUtil.c @@ -2648,6 +2648,42 @@ void Abc_NtkFromPlaTest() Abc_NtkDelete( pNtkAig ); } +/**Function************************************************************* + + Synopsis [Checks if the logic network is in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsTopo( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pFanin; + int i, k, Counter = 0; + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Abc_NodeSetTravIdCurrent(pObj); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + // check if fanins are in the topo order + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + break; + if ( k != Abc_ObjFaninNum(pObj) ) + { + if ( Counter++ == 0 ) + printf( "Node %d is out of topo order.\n", Abc_ObjId(pObj) ); + } + Abc_NodeSetTravIdCurrent(pObj); + } + if ( Counter ) + printf( "Topological order does not hold for %d internal nodes.\n", Counter ); + return (int)(Counter == 0); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 651b70ec..2baab045 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -9429,17 +9429,16 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) } */ + if ( !Abc_NtkIsTopo(pNtk) ) + { + Abc_Print( -1, "Current network is not in a topological order.\n" ); + return 1; + } + if ( pNtk ) { extern void Abc_NtkTestTim( Abc_Ntk_t * pNtk, int fVerbose ); - extern void Abc_NtkTestPinGia( Abc_Ntk_t * pNtk, int fWhiteBoxOnly, int fVerbose ); -// Abc_NtkTestTim( pNtk, fVerbose ); - if ( !Abc_NtkIsLogic(pNtk) ) - { - Abc_Print( -1, "The current ABC netowrk is not a logic network.\n" ); - return 1; - } - Abc_NtkTestPinGia( pNtk, 0, 0 ); + Abc_NtkTestTim( pNtk, fVerbose ); } return 0; diff --git a/src/base/abci/abcTim.c b/src/base/abci/abcTim.c index 41406ce4..56285058 100644 --- a/src/base/abci/abcTim.c +++ b/src/base/abci/abcTim.c @@ -23,6 +23,7 @@ #include "misc/tim/tim.h" #include "opt/dar/dar.h" #include "proof/dch/dch.h" +#include "base/main/main.h" ABC_NAMESPACE_IMPL_START @@ -30,10 +31,10 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -#define TIM_TEST_BOX_RATIO 30 +#define TIM_TEST_BOX_RATIO 200 // assume that every TIM_TEST_BOX_RATIO'th object is a white box -static inline int Abc_NodeIsWhiteBox( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return Abc_ObjId(pObj) % TIM_TEST_BOX_RATIO == 0; } +static inline int Abc_NodeIsWhiteBox( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return Abc_ObjId(pObj) % TIM_TEST_BOX_RATIO == 0 && Abc_ObjFaninNum(pObj) > 0 && Abc_ObjFaninNum(pObj) < 10; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -41,62 +42,6 @@ static inline int Abc_NodeIsWhiteBox( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNod /**Function************************************************************* - Synopsis [Derives one delay table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float * Abc_NtkTestTimDelayTableOne( int nInputs, int nOutputs ) -{ - float * pTable; - int i, k; - pTable = ABC_ALLOC( float, 3 + nInputs * nOutputs ); - pTable[0] = (float)-1; - pTable[1] = (float)nInputs; - pTable[2] = (float)nOutputs; - for ( i = 0; i < nOutputs; i++ ) - for ( k = 0; k < nInputs; k++ ) - pTable[3 + i * nInputs + k] = 1.0; - return pTable; -} - -/**Function************************************************************* - - Synopsis [Derives timing tables for each fanin size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkTestTimDelayTables( int nFaninsMax ) -{ - Vec_Ptr_t * vTables; - float * pTable; - int i; - vTables = Vec_PtrAlloc( nFaninsMax + 1 ); - for ( i = 0; i <= nFaninsMax; i++ ) - { - // derive delay table - pTable = Abc_NtkTestTimDelayTableOne( i, 1 ); - // set its table ID - pTable[0] = (float)Vec_PtrSize(vTables); - // save in the resulting array - Vec_PtrPush( vTables, pTable ); - } - return vTables; -} - - - -/**Function************************************************************* - Synopsis [Derives GIA for the output of the local function of one node.] Description [] @@ -290,86 +235,118 @@ Vec_Ptr_t * Abc_NtkTestTimCollectCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) SeeAlso [] ***********************************************************************/ -Gia_Man_t * Abc_NtkTestTimDeriveGia( Abc_Ntk_t * pNtk, int fVerbose ) +Gia_Man_t * Abc_NtkTestTimDeriveGia( Abc_Ntk_t * pNtk, int fVerbose ) { Gia_Man_t * pTemp; Gia_Man_t * pGia = NULL; + Gia_Man_t * pHoles = NULL; Tim_Man_t * pTim = NULL; - Vec_Ptr_t * vNodes, * vCone; + Vec_Int_t * vGiaCoLits; Abc_Obj_t * pObj, * pFanin; - int i, k, curPi, curPo, TableID; + int i, k, Entry, curPi, curPo, BoxUniqueId; + int nBoxFaninMax = 0; + assert( Abc_NtkIsTopo(pNtk) ); + Abc_NtkFillTemp( pNtk ); - // compute topological order - vNodes = Abc_NtkDfs( pNtk, 0 ); + // create white boxes + curPi = Abc_NtkCiNum(pNtk); + curPo = Abc_NtkCoNum(pNtk); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + pObj->fMarkA = Abc_NodeIsWhiteBox( pObj ); + if ( !pObj->fMarkA ) + continue; + nBoxFaninMax = Abc_MaxInt( nBoxFaninMax, Abc_ObjFaninNum(pObj) ); + curPi++; + curPo += Abc_ObjFaninNum(pObj); + if ( fVerbose ) + printf( "Selecting node %6d as white boxes with %d inputs and %d output.\n", i, Abc_ObjFaninNum(pObj), 1 ); + } // construct GIA - Abc_NtkFillTemp( pNtk ); pGia = Gia_ManStart( Abc_NtkObjNumMax(pNtk) ); + pHoles = Gia_ManStart( 1000 ); + for ( i = 0; i < curPi; i++ ) + Gia_ManAppendCi(pGia); + for ( i = 0; i < nBoxFaninMax; i++ ) + Gia_ManAppendCi(pHoles); Gia_ManHashAlloc( pGia ); - // create primary inputs + Gia_ManHashAlloc( pHoles ); + + // construct the timing manager + pTim = Tim_ManStart( curPi, curPo ); + + // assign primary inputs + curPi = 0; + curPo = 0; Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->iTemp = Gia_ManAppendCi(pGia); + pObj->iTemp = Abc_Var2Lit( Gia_ObjId(pGia, Gia_ManCi(pGia, curPi++)), 0 ); // create internal nodes in a topologic order from white boxes - Abc_NtkIncrementTravId( pNtk ); - Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + vGiaCoLits = Vec_IntAlloc( 1000 ); + Abc_NtkForEachNode( pNtk, pObj, i ) { - if ( !Abc_NodeIsWhiteBox(pObj) ) + if ( !pObj->fMarkA ) // not a white box + { + pObj->iTemp = Abc_NtkTestTimNodeStrash( pGia, pObj ); continue; - // collect nodes in the DFS order from this box - vCone = Abc_NtkTestTimCollectCone( pNtk, pObj ); - // perform GIA constructino for these nodes - Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pFanin, k ) - pFanin->iTemp = Abc_NtkTestTimNodeStrash( pGia, pFanin ); - // create inputs of the box + } + // create box + BoxUniqueId = Abc_ObjFaninNum(pObj); // in this case, the node size is the ID of its delay table + Tim_ManCreateBox( pTim, curPo, Abc_ObjFaninNum(pObj), curPi, 1, BoxUniqueId ); + curPo += Abc_ObjFaninNum(pObj); + + // handle box inputs Abc_ObjForEachFanin( pObj, pFanin, k ) - Gia_ManAppendCo( pGia, pFanin->iTemp ); - // craete outputs of the box - pObj->iTemp = Gia_ManAppendCi(pGia); - if ( fVerbose ) - printf( "White box %7d : Cone = %7d Lit = %7d.\n", Abc_ObjId(pObj), Vec_PtrSize(vCone), pObj->iTemp ); - Vec_PtrFree( vCone ); + { + // save CO drivers for the AIG + Vec_IntPush( vGiaCoLits, pFanin->iTemp ); + // load CI nodes for the Holes + pFanin->iTemp = Abc_Var2Lit( Gia_ObjId(pHoles, Gia_ManCi(pHoles, k)), 0 ); + } + + // handle logic of the box + pObj->iTemp = Abc_NtkTestTimNodeStrash( pHoles, pObj ); + + // handle box outputs + // save CO drivers for the Holes + Gia_ManAppendCo( pHoles, pObj->iTemp ); + // load CO drivers for the AIG + pObj->iTemp = Abc_Var2Lit( Gia_ObjId(pGia, Gia_ManCi(pGia, curPi++)), 0 ); } - // collect node in the DSF from the primary outputs - vCone = Abc_NtkTestTimCollectCone( pNtk, NULL ); - // perform GIA constructino for these nodes - Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pFanin, k ) - pFanin->iTemp = Abc_NtkTestTimNodeStrash( pGia, pFanin ); - Vec_PtrFree( vCone ); - // create primary outputs + Abc_NtkCleanMarkA( pNtk ); + // create COs of the AIG Abc_NtkForEachCo( pNtk, pObj, i ) - pObj->iTemp = Gia_ManAppendCo( pGia, Abc_ObjFanin0(pObj)->iTemp ); + Gia_ManAppendCo( pGia, Abc_ObjFanin0(pObj)->iTemp ); + Vec_IntForEachEntry( vGiaCoLits, Entry, i ) + Gia_ManAppendCo( pGia, Entry ); + Vec_IntFree( vGiaCoLits ); + // check parameters + curPo += Abc_NtkPoNum( pNtk ); + assert( curPi == Gia_ManPiNum(pGia) ); + assert( curPo == Gia_ManPoNum(pGia) ); // finalize GIA Gia_ManHashStop( pGia ); Gia_ManSetRegNum( pGia, 0 ); + Gia_ManHashStop( pHoles ); + Gia_ManSetRegNum( pHoles, 0 ); + // clean up GIA pGia = Gia_ManCleanup( pTemp = pGia ); Gia_ManStop( pTemp ); -//Gia_ManPrint( pGia ); - - // construct the timing manager - pTim = Tim_ManStart( Gia_ManPiNum(pGia), Gia_ManPoNum(pGia) ); - Tim_ManSetDelayTables( pTim, Abc_NtkTestTimDelayTables(Abc_NtkGetFaninMax(pNtk)) ); - // create timing boxes - curPi = Abc_NtkPiNum( pNtk ); - curPo = 0; - Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) - { - if ( !Abc_NodeIsWhiteBox(pObj) ) - continue; - TableID = Abc_ObjFaninNum(pObj); // in this case, the node size is the ID of its delay table - Tim_ManCreateBox( pTim, curPo, Abc_ObjFaninNum(pObj), curPi, 1, TableID ); - curPi += 1; - curPo += Abc_ObjFaninNum(pObj); - } - curPo += Abc_NtkPoNum( pNtk ); - assert( curPi == Gia_ManPiNum(pGia) ); - assert( curPo == Gia_ManPoNum(pGia) ); - Vec_PtrFree( vNodes ); + pHoles = Gia_ManCleanup( pTemp = pHoles ); + Gia_ManStop( pTemp ); // attach the timing manager assert( pGia->pManTime == NULL ); pGia->pManTime = pTim; + + // combinen hierarchy manager with box info and input/output arrival/required info + Tim_ManPrint( pGia->pManTime ); + Tim_ManCreate( pGia->pManTime, Abc_FrameReadLibBox(), NULL, NULL ); + Tim_ManPrint( pGia->pManTime ); + // return + pGia->pAigExtra = pHoles; return pGia; } diff --git a/src/map/if/ifLibBox.c b/src/map/if/ifLibBox.c index 678f4e68..8d7cb33b 100644 --- a/src/map/if/ifLibBox.c +++ b/src/map/if/ifLibBox.c @@ -221,6 +221,7 @@ void If_LibBoxPrint( FILE * pFile, If_LibBox_t * p ) If_Box_t * pBox; int i, j, k; fprintf( pFile, "# Box library written by ABC on %s.\n", Extra_TimeStamp() ); + fprintf( pFile, "# <Name> <ID> <Type> <I> <O>\n" ); If_LibBoxForEachBox( p, pBox, i ) { fprintf( pFile, "%s %d %d %d %d\n", pBox->pName, pBox->Id, pBox->fWhite, pBox->nPis, pBox->nPos ); diff --git a/src/misc/tim/tim.h b/src/misc/tim/tim.h index 420398b6..97e55b9d 100644 --- a/src/misc/tim/tim.h +++ b/src/misc/tim/tim.h @@ -127,7 +127,7 @@ extern Tim_Man_t * Tim_ManLoad( Vec_Str_t * p, int fHieOnly ); /*=== timMan.c ===========================================================*/ extern Tim_Man_t * Tim_ManStart( int nCis, int nCos ); extern Tim_Man_t * Tim_ManDup( Tim_Man_t * p, int fUnitDelay ); -extern Tim_Man_t * Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * vOutReqs ); +extern void Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * vOutReqs ); extern void Tim_ManStop( Tim_Man_t * p ); extern void Tim_ManStopP( Tim_Man_t ** p ); extern void Tim_ManPrint( Tim_Man_t * p ); diff --git a/src/misc/tim/timMan.c b/src/misc/tim/timMan.c index f3cd696e..965f3d11 100644 --- a/src/misc/tim/timMan.c +++ b/src/misc/tim/timMan.c @@ -181,13 +181,13 @@ void Tim_ManStopP( Tim_Man_t ** p ) SeeAlso [] ***********************************************************************/ -Tim_Man_t * Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * vOutReqs ) +void Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * vOutReqs ) { - Tim_Box_t * pBox; If_LibBox_t * pLibBox = (If_LibBox_t *)pLib; If_Box_t * pIfBox; - int i, k, * pTable; - float Entry; + Tim_Box_t * pBox; + float * pTable, Entry; + int i, k; assert( p->vDelayTables == NULL ); p->vDelayTables = Vec_PtrStart( Vec_PtrSize(pLibBox->vBoxes) ); Tim_ManForEachBox( p, pBox, i ) @@ -195,9 +195,15 @@ Tim_Man_t * Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_ if ( pBox->iDelayTable == -1 ) { // create table with constants - pTable = ABC_ALLOC( int, pBox->nInputs * pBox->nOutputs ); + pTable = ABC_ALLOC( float, 3 + pBox->nInputs * pBox->nOutputs ); + pTable[0] = pBox->iDelayTable; + pTable[1] = pBox->nInputs; + pTable[2] = pBox->nOutputs; for ( k = 0; k < pBox->nInputs * pBox->nOutputs; k++ ) - pTable[k] = 1; + pTable[3 + k] = 1.0; + // save table + pBox->iDelayTable = Vec_PtrSize(p->vDelayTables); + Vec_PtrPush( p->vDelayTables, pTable ); continue; } assert( pBox->iDelayTable >= 0 && pBox->iDelayTable < Vec_PtrSize(pLibBox->vBoxes) ); @@ -208,9 +214,14 @@ Tim_Man_t * Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_ if ( Vec_PtrEntry( p->vDelayTables, pBox->iDelayTable ) != NULL ) continue; // create table of boxes - pTable = ABC_ALLOC( int, pBox->nInputs * pBox->nOutputs ); + pTable = ABC_ALLOC( float, 3 + pBox->nInputs * pBox->nOutputs ); + pTable[0] = pBox->iDelayTable; + pTable[1] = pBox->nInputs; + pTable[2] = pBox->nOutputs; for ( k = 0; k < pBox->nInputs * pBox->nOutputs; k++ ) - pTable[k] = pIfBox->pDelays[k]; + pTable[3 + k] = pIfBox->pDelays[k]; + // save table + Vec_PtrWriteEntry( p->vDelayTables, pBox->iDelayTable, pTable ); } // create arrival times if ( vInArrs ) @@ -226,7 +237,6 @@ Tim_Man_t * Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_ Vec_FltForEachEntry( vOutReqs, Entry, i ) Tim_ManInitPoRequired( p, i, Entry ); } - return p; } @@ -309,6 +319,8 @@ void Tim_ManPrint( Tim_Man_t * p ) if ( Tim_ManDelayTableNum(p) > 0 ) Tim_ManForEachTable( p, pTable, i ) { + if ( pTable == NULL ) + continue; printf( "Delay table %d:\n", i ); assert( i == (int)pTable[0] ); TableX = (int)pTable[1]; |