diff --git a/src/aig/gia/giaAiger.c b/src/aig/gia/giaAiger.c index 85b48b118..6339b057f 100644 --- a/src/aig/gia/giaAiger.c +++ b/src/aig/gia/giaAiger.c @@ -649,23 +649,35 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi { pCur++; nInputs = Gia_AigerReadInt(pCur)/4; pCur += 4; + int nPiFf = Gia_ManPiNum(pNew) + Gia_ManRegNum(pNew); + if ( nInputs > nPiFf ) { + printf( "Warning: Timing info size (%d) exceeds PIs+FFs (%d). Using first %d values.\n", nInputs, nPiFf, nPiFf ); + nInputs = nPiFf; + } + else if ( nInputs > Gia_ManPiNum(pNew) && nInputs < nPiFf ) { + printf( "Warning: Timing info size (%d) is between PIs (%d) and PIs+FFs (%d). Using first %d values.\n", nInputs, Gia_ManPiNum(pNew), nPiFf, Gia_ManPiNum(pNew) ); + nInputs = Gia_ManPiNum(pNew); + } pNew->vInArrs = Vec_FltStart( nInputs ); memcpy( Vec_FltArray(pNew->vInArrs), pCur, (size_t)4*nInputs ); pCur += 4*nInputs; if ( fVerbose ) printf( "Finished reading extension \"i\".\n" ); - //if ( Vec_FltSize(pNew->vInArrs) == Gia_ManPiNum(pNew) ) - // Vec_FltFillExtra(pNew->vInArrs, Gia_ManCiNum(pNew), 0); - //assert( Vec_FltSize(pNew->vInArrs) == Gia_ManCiNum(pNew) ); } else if ( *pCur == 'o' ) { pCur++; nOutputs = Gia_AigerReadInt(pCur)/4; pCur += 4; + int nPoFf = Gia_ManPoNum(pNew) + Gia_ManRegNum(pNew); + if ( nOutputs > nPoFf ) { + printf( "Warning: Required time size (%d) exceeds POs+FFs (%d). Using first %d values.\n", nOutputs, nPoFf, nPoFf ); + nOutputs = nPoFf; + } + else if ( nOutputs > Gia_ManPoNum(pNew) && nOutputs < nPoFf ) { + printf( "Warning: Required time size (%d) is between POs (%d) and POs+FFs (%d). Using first %d values.\n", nOutputs, Gia_ManPoNum(pNew), nPoFf, Gia_ManPoNum(pNew) ); + nOutputs = Gia_ManPoNum(pNew); + } pNew->vOutReqs = Vec_FltStart( nOutputs ); memcpy( Vec_FltArray(pNew->vOutReqs), pCur, (size_t)4*nOutputs ); pCur += 4*nOutputs; if ( fVerbose ) printf( "Finished reading extension \"o\".\n" ); - //if ( Vec_FltSize(pNew->vOutReqs) == Gia_ManPoNum(pNew) ) - // Vec_FltFillExtra(pNew->vOutReqs, Gia_ManCoNum(pNew), 0); - //assert( Vec_FltSize(pNew->vOutReqs) == Gia_ManCoNum(pNew) ); } // read equivalence classes else if ( *pCur == 'e' ) @@ -1429,23 +1441,27 @@ void Gia_AigerWriteS( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, in if ( p->pManTime ) { float * pTimes; - pTimes = Tim_ManGetArrTimes( (Tim_Man_t *)p->pManTime ); + pTimes = Tim_ManGetArrTimes( (Tim_Man_t *)p->pManTime, Gia_ManRegNum(p) ); if ( pTimes ) { + int nPis = Tim_ManPiNum((Tim_Man_t *)p->pManTime); + int nFlops = Gia_ManRegNum(p); fprintf( pFile, "i" ); - Gia_FileWriteBufferSize( pFile, 4*Tim_ManPiNum((Tim_Man_t *)p->pManTime) ); - fwrite( pTimes, 1, 4*Tim_ManPiNum((Tim_Man_t *)p->pManTime), pFile ); + Gia_FileWriteBufferSize( pFile, 4*(nPis + nFlops) ); + fwrite( pTimes, 1, 4*(nPis + nFlops), pFile ); ABC_FREE( pTimes ); - if ( fVerbose ) printf( "Finished writing extension \"i\".\n" ); + if ( fVerbose ) printf( "Finished writing extension \"i\" (PIs+Flops).\n" ); } - pTimes = Tim_ManGetReqTimes( (Tim_Man_t *)p->pManTime ); + pTimes = Tim_ManGetReqTimes( (Tim_Man_t *)p->pManTime, Gia_ManRegNum(p) ); if ( pTimes ) { + int nPos = Tim_ManPoNum((Tim_Man_t *)p->pManTime); + int nFlops = Gia_ManRegNum(p); fprintf( pFile, "o" ); - Gia_FileWriteBufferSize( pFile, 4*Tim_ManPoNum((Tim_Man_t *)p->pManTime) ); - fwrite( pTimes, 1, 4*Tim_ManPoNum((Tim_Man_t *)p->pManTime), pFile ); + Gia_FileWriteBufferSize( pFile, 4*(nPos + nFlops) ); + fwrite( pTimes, 1, 4*(nPos + nFlops), pFile ); ABC_FREE( pTimes ); - if ( fVerbose ) printf( "Finished writing extension \"o\".\n" ); + if ( fVerbose ) printf( "Finished writing extension \"o\" (POs+Flops).\n" ); } } // write equivalences diff --git a/src/aig/gia/giaLf.c b/src/aig/gia/giaLf.c index 130660050..006ac18f4 100644 --- a/src/aig/gia/giaLf.c +++ b/src/aig/gia/giaLf.c @@ -2306,8 +2306,8 @@ Gia_Man_t * Gia_ManPerformLfMapping( Gia_Man_t * p, Jf_Par_t * pPars, int fNorma Gia_ManTransferTiming( pNew, p ); p = pNew; // set arrival and required times - pPars->pTimesArr = Tim_ManGetArrTimes( (Tim_Man_t *)p->pManTime ); - pPars->pTimesReq = Tim_ManGetReqTimes( (Tim_Man_t *)p->pManTime ); + pPars->pTimesArr = Tim_ManGetArrTimes( (Tim_Man_t *)p->pManTime, Gia_ManRegNum(p) ); + pPars->pTimesReq = Tim_ManGetReqTimes( (Tim_Man_t *)p->pManTime, Gia_ManRegNum(p) ); } else p = Gia_ManDup( p ); diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index b60874601..889a49c0e 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -1033,15 +1033,28 @@ Vec_Int_t * Gia_ManDfsArrivals( Gia_Man_t * p, Vec_Int_t * vObjs ) Vec_Int_t * vTimes = Vec_IntStartFull( Gia_ManObjNum(p) ); Gia_Obj_t * pObj; int j, Entry, k, iFan; Vec_IntWriteEntry( vTimes, 0, 0 ); - if ( pManTime ) + if ( pManTime ) { Tim_ManIncrementTravId( pManTime ); Gia_ManForEachCi( p, pObj, j ) + { + float arrTime = 0; if ( j < Tim_ManPiNum(pManTime) ) { - float arrTime = Tim_ManGetCiArrival( pManTime, j ); + // PIs - direct index + arrTime = Tim_ManGetCiArrival( pManTime, j ); Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), (int)arrTime ); } + else if ( j >= Tim_ManCiNum(pManTime) - Gia_ManRegNum(p) ) + { + // Flops - need to remap index: stored at Tim_ManPiNum + flop_index + int flopIndex = j - (Tim_ManCiNum(pManTime) - Gia_ManRegNum(p)); + int remappedIndex = Tim_ManPiNum(pManTime) + flopIndex; + arrTime = Tim_ManGetCiArrival( pManTime, remappedIndex ); + Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), (int)arrTime ); + } + // BoxOutputs in the middle are skipped (no timing set) + } } else { @@ -1115,17 +1128,28 @@ Vec_Int_t * Gia_ManDfsRequireds( Gia_Man_t * p, Vec_Int_t * vObjs, int ReqTime ) Gia_Obj_t * pObj; int j, Entry, k, iFan, Req; Vec_IntWriteEntry( vTimes, 0, 0 ); - if ( pManTime ) + if ( pManTime ) { - int nCoLimit = Gia_ManCoNum(p) - Tim_ManPoNum(pManTime); Tim_ManIncrementTravId( pManTime ); //Tim_ManInitPoRequiredAll( pManTime, (float)ReqTime ); Gia_ManForEachCo( p, pObj, j ) - if ( j >= nCoLimit ) + { + if ( j < Gia_ManPoNum(p) ) { + // POs - direct index works since they come first Tim_ManSetCoRequired( pManTime, j, ReqTime ); Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0p(p, pObj), ReqTime ); } + else if ( j >= Gia_ManCoNum(p) - Gia_ManRegNum(p) ) + { + // Flop inputs - remap index: stored at Tim_ManPoNum + flop_index + int flopIndex = j - (Gia_ManCoNum(p) - Gia_ManRegNum(p)); + int remappedIndex = Tim_ManPoNum(pManTime) + flopIndex; + Tim_ManSetCoRequired( pManTime, remappedIndex, ReqTime ); + Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0p(p, pObj), ReqTime ); + } + // BoxInputs in the middle are skipped (no required time set) + } } else { diff --git a/src/aig/gia/giaTim.c b/src/aig/gia/giaTim.c index 54012bbde..cb48d1de9 100644 --- a/src/aig/gia/giaTim.c +++ b/src/aig/gia/giaTim.c @@ -372,8 +372,14 @@ Vec_Int_t * Gia_ManOrderWithBoxes( Gia_Man_t * p ) Synopsis [Duplicates AIG according to the timing manager.] - Description [] - + Description [Converts a normalized AIG to unnormalized form for box processing. + In normalized AIG: CIs are ordered as PIs + BoxOutputs + FlopOutputs + In unnormalized AIG: CIs are ordered as PIs + FlopOutputs only, + with BoxOutputs spread throughout the AIG in topological order. + This transformation allows proper timing-aware processing of boxes. + For sequential AIGs, flop count is preserved, with flop outputs + remaining as CIs and flop inputs as COs.] + SideEffects [] SeeAlso [] diff --git a/src/misc/tim/tim.h b/src/misc/tim/tim.h index a01d53e32..3ab54335e 100644 --- a/src/misc/tim/tim.h +++ b/src/misc/tim/tim.h @@ -135,8 +135,8 @@ extern Tim_Man_t * Tim_ManTrim( Tim_Man_t * p, Vec_Int_t * vBoxPres ); extern Tim_Man_t * Tim_ManReduce( Tim_Man_t * p, Vec_Int_t * vBoxesLeft, int nTermsDiff ); extern Vec_Int_t * Tim_ManAlignTwo( Tim_Man_t * pSpec, Tim_Man_t * pImpl ); extern void Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * vOutReqs ); -extern float * Tim_ManGetArrTimes( Tim_Man_t * p ); -extern float * Tim_ManGetReqTimes( Tim_Man_t * p ); +extern float * Tim_ManGetArrTimes( Tim_Man_t * p, int nRegs ); +extern float * Tim_ManGetReqTimes( Tim_Man_t * p, int nRegs ); 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 9bcdaaae6..b90cb0b4d 100644 --- a/src/misc/tim/timMan.c +++ b/src/misc/tim/timMan.c @@ -449,6 +449,7 @@ void Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * Vec_PtrWriteEntry( p->vDelayTables, pBox->iDelayTable, pTable ); } // create arrival times +/* if ( vInArrs ) { if ( Vec_FltSize(vInArrs) == Tim_ManPiNum(p) ) { @@ -461,21 +462,37 @@ void Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * } else assert( 0 ); } +*/ + if ( vInArrs ) + { + assert( Vec_FltSize(vInArrs) >= Tim_ManPiNum(p) ); + if ( Vec_FltSize(vInArrs) == Tim_ManPiNum(p) ) { + Tim_ManForEachPi( p, pObj, i ) + pObj->timeArr = Vec_FltEntry(vInArrs, i); + } + else { + float Num; + Vec_FltForEachEntry( vInArrs, Num, i ) + p->pCis[i].timeArr = Num; + } + } + // create required times + // Handles: POs only, POs+Flops (partial COs), or all COs if ( vOutReqs ) { - k = 0; + assert( Vec_FltSize(vOutReqs) >= Tim_ManPoNum(p) ); if ( Vec_FltSize(vOutReqs) == Tim_ManPoNum(p) ) { + k = 0; Tim_ManForEachPo( p, pObj, i ) pObj->timeReq = Vec_FltEntry(vOutReqs, k++); assert( k == Tim_ManPoNum(p) ); } - else if ( Vec_FltSize(vOutReqs) == Tim_ManCoNum(p) ) { - Tim_ManForEachCo( p, pObj, i ) - pObj->timeReq = Vec_FltEntry(vOutReqs, k++); - assert( k == Tim_ManCoNum(p) ); + else { + float Num; + Vec_FltForEachEntry( vOutReqs, Num, i ) + p->pCos[i].timeReq = Num; } - else assert( 0 ); } } @@ -491,35 +508,65 @@ void Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * SeeAlso [] ***********************************************************************/ -float * Tim_ManGetArrTimes( Tim_Man_t * p ) +float * Tim_ManGetArrTimes( Tim_Man_t * p, int nRegs ) { float * pTimes; Tim_Obj_t * pObj; int i; + // Check if any PIs have non-zero arrival times Tim_ManForEachPi( p, pObj, i ) if ( pObj->timeArr != 0.0 ) break; - if ( i == Tim_ManPiNum(p) ) + if ( i == Tim_ManPiNum(p) && nRegs > 0 ) + { + // Check if any flops have non-zero arrival times + for ( i = Tim_ManCiNum(p) - nRegs; i < Tim_ManCiNum(p); i++ ) + if ( p->pCis[i].timeArr != 0.0 ) + break; + if ( i == Tim_ManCiNum(p) ) + return NULL; // No timing info at all + } + else if ( i == Tim_ManPiNum(p) ) return NULL; - pTimes = ABC_FALLOC( float, Tim_ManCiNum(p) ); + // Allocate array for PIs + Flops (compact format, no box outputs) + pTimes = ABC_FALLOC( float, Tim_ManPiNum(p) + nRegs ); + // Copy PI timings Tim_ManForEachPi( p, pObj, i ) pTimes[i] = pObj->timeArr; + // Copy flop timings (from the end of CI array) + for ( i = 0; i < nRegs; i++ ) + pTimes[Tim_ManPiNum(p) + i] = p->pCis[Tim_ManCiNum(p) - nRegs + i].timeArr; return pTimes; } -float * Tim_ManGetReqTimes( Tim_Man_t * p ) +float * Tim_ManGetReqTimes( Tim_Man_t * p, int nRegs ) { float * pTimes; Tim_Obj_t * pObj; int i, k = 0; + // Check if any POs have non-infinity required times Tim_ManForEachPo( p, pObj, i ) if ( pObj->timeReq != TIM_ETERNITY ) break; - if ( i == Tim_ManPoNum(p) ) + if ( i == Tim_ManPoNum(p) && nRegs > 0 ) + { + // Check if any flops have non-infinity required times + for ( i = Tim_ManCoNum(p) - nRegs; i < Tim_ManCoNum(p); i++ ) + if ( p->pCos[i].timeReq != TIM_ETERNITY ) + break; + if ( i == Tim_ManCoNum(p) ) + return NULL; // No timing info at all + } + else if ( i == Tim_ManPoNum(p) ) return NULL; - pTimes = ABC_FALLOC( float, Tim_ManCoNum(p) ); + // Allocate array for POs + Flops (compact format, no box inputs) + pTimes = ABC_FALLOC( float, Tim_ManPoNum(p) + nRegs ); + // Copy PO timings Tim_ManForEachPo( p, pObj, i ) - pTimes[k++] = pObj->timeArr; + pTimes[k++] = pObj->timeReq; assert( k == Tim_ManPoNum(p) ); + // Copy flop timings (from the end of CO array) + for ( i = 0; i < nRegs; i++ ) + pTimes[Tim_ManPoNum(p) + i] = p->pCos[Tim_ManCoNum(p) - nRegs + i].timeReq; return pTimes; }