Merge remote-tracking branch 'upstream/master' into yosys-experimental

This commit is contained in:
Miodrag Milanovic 2026-02-02 11:22:23 +01:00
commit 734f64d5b9
5 changed files with 253 additions and 15 deletions

View File

@ -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 );

View File

@ -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*************************************************************

View File

@ -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++;

View File

@ -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 []

View File

@ -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;
}
}
}