diff --git a/src/aig/gia/giaAiger.c b/src/aig/gia/giaAiger.c index 6339b057f..9bc6c93fc 100644 --- a/src/aig/gia/giaAiger.c +++ b/src/aig/gia/giaAiger.c @@ -982,6 +982,106 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi pNew->pAigExtra = pAigExtra; } + // Apply init state transformation for register boxes with init=1 + if ( pNew->vRegInits && Vec_IntCountEntry(pNew->vRegInits, 1) > 0 ) + { + extern void Gia_ManFlipInit1( Gia_Man_t * p, Vec_Int_t * vInit ); + Tim_Man_t * pTimMan = (Tim_Man_t *)pNew->pManTime; + + if ( pTimMan && Gia_ManRegBoxNum(pNew) > 0 ) + { + // Handle register boxes: apply transformation to box inputs/outputs + Gia_Obj_t * pObj; + int i, curCo, curCi, nBoxIns, nBoxOuts; + int iRegBox = 0; + + assert( Vec_IntSize(pNew->vRegInits) == Gia_ManRegBoxNum(pNew) ); + + // Step 1: Mark register box outputs with init state 1 + curCi = Tim_ManPiNum(pTimMan); + for ( i = 0; i < Gia_ManBoxNum(pNew); i++ ) + { + nBoxIns = Tim_ManBoxInputNum(pTimMan, i); + nBoxOuts = Tim_ManBoxOutputNum(pTimMan, i); + // Check if this is a register box (1-input, 1-output) + if ( nBoxIns == 1 && nBoxOuts == 1 ) + { + if ( Vec_IntEntry(pNew->vRegInits, iRegBox) == 1 ) + { + pObj = Gia_ManCi(pNew, curCi); + pObj->fMark0 = 1; + } + iRegBox++; + } + curCi += nBoxOuts; + } + + // Step 2: Propagate complementation through AND gates + Gia_ManForEachAnd( pNew, pObj, i ) + { + if ( Gia_ObjFanin0(pObj)->fMark0 ) + pObj->fCompl0 ^= 1; + if ( Gia_ObjFanin1(pObj)->fMark0 ) + pObj->fCompl1 ^= 1; + } + + // Step 3: Complement CO fanins if needed + Gia_ManForEachCo( pNew, pObj, i ) + { + if ( Gia_ObjFanin0(pObj)->fMark0 ) + pObj->fCompl0 ^= 1; + } + + // Step 4: Clear marks + curCi = Tim_ManPiNum(pTimMan); + iRegBox = 0; + for ( i = 0; i < Gia_ManBoxNum(pNew); i++ ) + { + nBoxIns = Tim_ManBoxInputNum(pTimMan, i); + nBoxOuts = Tim_ManBoxOutputNum(pTimMan, i); + if ( nBoxIns == 1 && nBoxOuts == 1 ) + { + if ( Vec_IntEntry(pNew->vRegInits, iRegBox) == 1 ) + { + pObj = Gia_ManCi(pNew, curCi); + pObj->fMark0 = 0; + } + iRegBox++; + } + curCi += nBoxOuts; + } + + // Step 5: Complement register box inputs with init state 1 + curCo = Tim_ManPoNum(pTimMan); + iRegBox = 0; + for ( i = 0; i < Gia_ManBoxNum(pNew); i++ ) + { + nBoxIns = Tim_ManBoxInputNum(pTimMan, i); + nBoxOuts = Tim_ManBoxOutputNum(pTimMan, i); + if ( nBoxIns == 1 && nBoxOuts == 1 ) + { + if ( Vec_IntEntry(pNew->vRegInits, iRegBox) == 1 ) + { + pObj = Gia_ManCo(pNew, curCo); + pObj->fCompl0 ^= 1; + } + iRegBox++; + } + curCo += nBoxIns; + } + + // Clear all init states to 0 (transformation is now structural) + Vec_IntFill( pNew->vRegInits, Vec_IntSize(pNew->vRegInits), 0 ); + } + else if ( Gia_ManRegNum(pNew) > 0 ) + { + // Handle regular flops (no boxes) + Gia_ManFlipInit1( pNew, pNew->vRegInits ); + // Clear all init states to 0 (transformation is now structural) + Vec_IntFill( pNew->vRegInits, Vec_IntSize(pNew->vRegInits), 0 ); + } + } + if ( fHieOnly ) { // Tim_ManPrint( (Tim_Man_t *)pNew->pManTime ); diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 84ed665f0..0c0fd3d1e 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -656,6 +656,40 @@ Gia_Man_t * Gia_ManDupFlip( Gia_Man_t * p, int * pInitState ) return pNew; } +/**Function************************************************************* + + Synopsis [Complements some flops without duplicating AIG.] + + Description [The array of integers containing the initial state + of each flop in the AIG.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFlipInit1( Gia_Man_t * p, Vec_Int_t * vInit ) +{ + Gia_Obj_t * pObj; int c; + assert( Gia_ManRegNum(p) == Vec_IntSize(vInit) ); + Gia_ManForEachRo( p, pObj, c ) + pObj->fMark0 = (int)(Vec_IntEntry(vInit, c) == 1); + Gia_ManForEachAnd( p, pObj, c ) { + if ( Gia_ObjFanin0(pObj)->fMark0 ) + pObj->fCompl0 ^= 1; + if ( Gia_ObjFanin1(pObj)->fMark0 ) + pObj->fCompl1 ^= 1; + } + Gia_ManForEachCo( p, pObj, c ) + if ( Gia_ObjFanin0(pObj)->fMark0 ) + pObj->fCompl0 ^= 1; + Gia_ManForEachRo( p, pObj, c ) + pObj->fMark0 = 0; + Gia_ManForEachRi( p, pObj, c ) + if ( Vec_IntEntry(vInit, c) == 1 ) + pObj->fCompl0 ^= 1; +} + /**Function************************************************************* diff --git a/src/aig/gia/giaTim.c b/src/aig/gia/giaTim.c index 080c74471..5f13dcfa7 100644 --- a/src/aig/gia/giaTim.c +++ b/src/aig/gia/giaTim.c @@ -77,7 +77,8 @@ int Gia_ManClockDomainNum( Gia_Man_t * p ) if ( p->vRegClasses == NULL ) return 0; nDoms = Vec_IntFindMax(p->vRegClasses); - assert( Vec_IntCountEntry(p->vRegClasses, 0) == 0 ); + // Class 0 is now allowed - means unmergeable flops not in any clock domain + // assert( Vec_IntCountEntry(p->vRegClasses, 0) == 0 ); for ( i = 1; i <= nDoms; i++ ) if ( Vec_IntCountEntry(p->vRegClasses, i) > 0 ) Count++; diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index ae9f7c2d3..02959f7f4 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -635,6 +635,7 @@ static int Abc_CommandAbc9Gen ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Cfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9ProdAdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9AddFlop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Init1 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9BMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenHie ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9PutOnTop ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1477,6 +1478,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&cfs", Abc_CommandAbc9Cfs, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&prodadd", Abc_CommandAbc9ProdAdd, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&addflop", Abc_CommandAbc9AddFlop, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&init1", Abc_CommandAbc9Init1, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmiter", Abc_CommandAbc9BMiter, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&gen_hie", Abc_CommandAbc9GenHie, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&putontop", Abc_CommandAbc9PutOnTop, 0 ); @@ -10938,15 +10940,35 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 0, "If LUT mapping is not enabled (switch \"-r\"), permutation has not effect.\n" ); if ( argc == globalUtilOptind + 1 ) pPars->pTtStr = argv[globalUtilOptind]; - else if ( argc == globalUtilOptind && Abc_FrameReadNtk(pAbc) ) + else if ( argc == globalUtilOptind && Abc_FrameReadNtk(pAbc) ) { - pPars->pTtStr = Abc_NtkReadTruth( Abc_FrameReadNtk(pAbc) ); - if ( pPars->pTtStr ) - pPars->nVars = Abc_NtkCiNum(Abc_FrameReadNtk(pAbc)); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + if ( Abc_NtkCiNum(pNtk) > 30 ) + { + Abc_Print( -1, "Cannot derive truth table from network: too many inputs (%d > 30).\n", Abc_NtkCiNum(pNtk) ); + Abc_Print( -1, "Please provide truth table on the command line or use a smaller network.\n" ); + return 1; + } + if ( Abc_NtkCoNum(pNtk) != 1 ) + { + Abc_Print( -1, "Cannot derive truth table from network: network must have exactly one output (has %d).\n", Abc_NtkCoNum(pNtk) ); + return 1; + } + pPars->pTtStr = Abc_NtkReadTruth( pNtk ); + if ( pPars->pTtStr ) + { + pPars->nVars = Abc_NtkCiNum(pNtk); + Abc_Print( 0, "Derived %d-input truth table from current network.\n", pPars->nVars ); + } + else + { + Abc_Print( -1, "Failed to derive truth table from current network.\n" ); + return 1; + } } if ( pPars->pTtStr == NULL && pPars->pSymStr == NULL && pPars->nRandFuncs == 0 ) { - Abc_Print( -1, "Truth table should be given on the command line.\n" ); + Abc_Print( -1, "Truth table should be given on the command line, or derived from current single-output network.\n" ); return 1; } if ( pPars->nVars == 0 && pPars->pTtStr ) @@ -34617,6 +34639,11 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_NtkDelete( pNtkNoCh ); Aig_ManStop( pMan ); } + // transfer the spec name to the pNtk + if( pAbc->pGia->pSpec ) + { + pNtk->pSpec = Extra_UtilStrsav( pAbc->pGia->pSpec ); + } // transfer PI names to pNtk if ( pAbc->pGia->vNamesIn ) { @@ -57043,6 +57070,59 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Init1( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManFlipInit1( Gia_Man_t * p, Vec_Int_t * vInit ); + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) { + Abc_Print( -1, "Abc_CommandAbc9Init1(): There is no AIG.\n" ); + return 0; + } + if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { + Abc_Print( -1, "Abc_CommandAbc9Init1(): There is no flops.\n" ); + return 0; + } + if ( pAbc->pGia->vRegInits == NULL ) { + Abc_Print( -1, "Abc_CommandAbc9Init1(): Flop init states are not available.\n" ); + return 0; + } + Gia_ManFlipInit1( pAbc->pGia, pAbc->pGia->vRegInits ); + return 0; + +usage: + Abc_Print( -2, "usage: &init1 [-vh]\n" ); + Abc_Print( -2, "\t complements the inputs/outputs of flops with const-1 initial state\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + /**Function************************************************************* Synopsis [] diff --git a/src/misc/tim/timMan.c b/src/misc/tim/timMan.c index 2df6007cc..274dc0c0e 100644 --- a/src/misc/tim/timMan.c +++ b/src/misc/tim/timMan.c @@ -562,33 +562,56 @@ void Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * */ if ( vInArrs ) { - assert( Vec_FltSize(vInArrs) >= Tim_ManPiNum(p) ); - if ( Vec_FltSize(vInArrs) == Tim_ManPiNum(p) ) { + // Handle special case when timing is only for PIs (without boxes/flops) + // This happens when old files provide timing for actual design PIs only + if ( Vec_FltSize(vInArrs) < Tim_ManPiNum(p) ) + { + // Special case: timing for actual PIs only (less than Tim_ManPiNum when boxes exist) + for ( i = 0; i < Vec_FltSize(vInArrs); i++ ) + p->pCis[i].timeArr = Vec_FltEntry(vInArrs, i); + } + else if ( Vec_FltSize(vInArrs) == Tim_ManPiNum(p) ) + { + // Original case: timing for PIs (up to first box) Tim_ManForEachPi( p, pObj, i ) pObj->timeArr = Vec_FltEntry(vInArrs, i); } - else { + else + { + // General case: timing for all or partial CIs float Num; Vec_FltForEachEntry( vInArrs, Num, i ) - p->pCis[i].timeArr = Num; + if ( i < p->nCis ) + p->pCis[i].timeArr = Num; } } // create required times - // Handles: POs only, POs+Flops (partial COs), or all COs if ( vOutReqs ) { - assert( Vec_FltSize(vOutReqs) >= Tim_ManPoNum(p) ); - if ( Vec_FltSize(vOutReqs) == Tim_ManPoNum(p) ) { + // Handle special case when timing is only for POs (without boxes/flops) + // This happens when old files provide timing for actual design POs only + if ( Vec_FltSize(vOutReqs) < Tim_ManPoNum(p) ) + { + // Special case: timing for actual POs only (less than Tim_ManPoNum when boxes exist) + for ( i = 0; i < Vec_FltSize(vOutReqs); i++ ) + p->pCos[i].timeReq = Vec_FltEntry(vOutReqs, i); + } + else if ( Vec_FltSize(vOutReqs) == Tim_ManPoNum(p) ) + { + // Original case: timing for POs k = 0; Tim_ManForEachPo( p, pObj, i ) pObj->timeReq = Vec_FltEntry(vOutReqs, k++); assert( k == Tim_ManPoNum(p) ); } - else { + else + { + // General case: timing for all or partial COs float Num; Vec_FltForEachEntry( vOutReqs, Num, i ) - p->pCos[i].timeReq = Num; + if ( i < p->nCos ) + p->pCos[i].timeReq = Num; } } }