Skip to content

Commit d8734f9

Browse files
committed
Add per-node origin cap (nOriginsMax) to bound accumulation
Shared fanin cones can accumulate origins from all CO drivers, causing O(n²) dedup cost in Gia_ObjAddOrigin. Add nOriginsMax field to Gia_Man_t that short-circuits overflow-mode AddOrigin when the node has reached the limit. Cap is set via &origins_id -M. Pathological case (10K outputs, shared 50-deep cone): No cap: 5.70s, 1.01M total origins, max 10000/node -M 256: 0.79s, 45K total origins, max 256/node (7.2x faster) Normal designs (i10.aig, max 165/node): identical results. Co-developed-by: Claude Code v2.1.89 (claude-opus-4-6)
1 parent 4496674 commit d8734f9

3 files changed

Lines changed: 32 additions & 4 deletions

File tree

src/aig/gia/gia.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ struct Gia_Man_t_
220220
Vec_Int_t * vIdsEquiv; // original object IDs proved equivalent
221221
Vec_Int_t * vEquLitIds; // original object IDs proved equivalent
222222
Vec_Int_t * vOrigins; // per-object origin mapping (from "y" extension)
223+
int nOriginsMax; // max origins per object (0 = unlimited)
223224
Vec_Int_t * vCofVars; // cofactoring variables
224225
Vec_Vec_t * vClockDoms; // clock domains
225226
Vec_Flt_t * vTiming; // arrival/required/slack

src/aig/gia/giaDup.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ void Gia_ObjAddOrigin( Gia_Man_t * p, int iObj, int iOrig )
213213
e = Gia_ObjOriginsEntry( p, iObj );
214214
if ( Gia_ObjOriginsIsOverflow(e) )
215215
{
216+
// cap check: skip if at user-specified limit
217+
if ( p->nOriginsMax > 0 && e->large.count >= p->nOriginsMax )
218+
return;
216219
// overflow mode: check for duplicate
217220
for ( k = 0; k < e->large.count; k++ )
218221
if ( e->large.overflow[k] == iOrig ) return;
@@ -331,6 +334,7 @@ void Gia_ManOriginsDup( Gia_Man_t * pNew, Gia_Man_t * pOld )
331334
if ( !pOld->vOrigins )
332335
return;
333336
Gia_ManOriginsReset( pNew );
337+
pNew->nOriginsMax = pOld->nOriginsMax;
334338
pNew->vOrigins = Gia_ManOriginsAlloc( Gia_ManObjNum(pNew) );
335339
Gia_ManForEachObj( pOld, pObj, i )
336340
{
@@ -364,6 +368,7 @@ void Gia_ManOriginsDupVec( Gia_Man_t * pNew, Gia_Man_t * pOld, Vec_Int_t * vCopi
364368
if ( !pOld->vOrigins )
365369
return;
366370
Gia_ManOriginsReset( pNew );
371+
pNew->nOriginsMax = pOld->nOriginsMax;
367372
pNew->vOrigins = Gia_ManOriginsAlloc( Gia_ManObjNum(pNew) );
368373
Vec_IntForEachEntry( vCopies, iLit, i )
369374
{
@@ -399,6 +404,7 @@ void Gia_ManOriginsAfterRoundTrip( Gia_Man_t * pNew, Gia_Man_t * pOld )
399404
assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(pOld) );
400405
assert( Gia_ManCoNum(pNew) == Gia_ManCoNum(pOld) );
401406
Gia_ManOriginsReset( pNew );
407+
pNew->nOriginsMax = pOld->nOriginsMax;
402408
pNew->vOrigins = Gia_ManOriginsAlloc( Gia_ManObjNum(pNew) );
403409
// const0
404410
Gia_ObjUnionOrigins( pNew, 0, pOld, 0 );
@@ -456,6 +462,7 @@ void Gia_ManOriginsDupIf( Gia_Man_t * pNew, Gia_Man_t * p, void * pIfManVoid )
456462
if ( !p->vOrigins )
457463
return;
458464
Gia_ManOriginsReset( pNew );
465+
pNew->nOriginsMax = p->nOriginsMax;
459466
pNew->vOrigins = Gia_ManOriginsAlloc( Gia_ManObjNum(pNew) );
460467
If_ManForEachObj( pIfMan, pIfObj, i )
461468
{
@@ -1108,6 +1115,7 @@ Gia_Man_t * Gia_ManDupWithAttributes( Gia_Man_t * p )
11081115
if ( p->pCellStr )
11091116
pNew->pCellStr = Abc_UtilStrsav( p->pCellStr );
11101117
// copy origins if present (deep-copy overflow arrays)
1118+
pNew->nOriginsMax = p->nOriginsMax;
11111119
if ( p->vOrigins )
11121120
{
11131121
int iObj, nObjs;

src/base/abci/abc.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35617,12 +35617,26 @@ int Abc_CommandAbc9Origins( Abc_Frame_t * pAbc, int argc, char ** argv )
3561735617
int Abc_CommandAbc9OriginsId( Abc_Frame_t * pAbc, int argc, char ** argv )
3561835618
{
3561935619
Gia_Man_t * pGia = pAbc->pGia;
35620-
int c;
35620+
int c, nOriginsMax = 0;
3562135621
Extra_UtilGetoptReset();
35622-
while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
35622+
while ( ( c = Extra_UtilGetopt( argc, argv, "Mh" ) ) != EOF )
3562335623
{
3562435624
switch ( c )
3562535625
{
35626+
case 'M':
35627+
if ( globalUtilOptind >= argc )
35628+
{
35629+
Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
35630+
goto usage;
35631+
}
35632+
nOriginsMax = atoi(argv[globalUtilOptind]);
35633+
globalUtilOptind++;
35634+
if ( nOriginsMax < 0 )
35635+
{
35636+
Abc_Print( -1, "The max origins value should be non-negative.\n" );
35637+
goto usage;
35638+
}
35639+
break;
3562635640
case 'h':
3562735641
goto usage;
3562835642
default:
@@ -35643,17 +35657,22 @@ int Abc_CommandAbc9OriginsId( Abc_Frame_t * pAbc, int argc, char ** argv )
3564335657
{
3564435658
int i, nObjs = Gia_ManObjNum(pGia);
3564535659
Gia_Obj_t * pObj;
35660+
pGia->nOriginsMax = nOriginsMax;
3564635661
pGia->vOrigins = Gia_ManOriginsAlloc( nObjs );
3564735662
Gia_ManForEachAnd( pGia, pObj, i )
3564835663
Gia_ObjSetOrigin( pGia, i, i );
35649-
Abc_Print( 1, "Initialized identity origins for %d AND nodes.\n", Gia_ManAndNum(pGia) );
35664+
Abc_Print( 1, "Initialized identity origins for %d AND nodes", Gia_ManAndNum(pGia) );
35665+
if ( nOriginsMax > 0 )
35666+
Abc_Print( 1, " (max %d per node)", nOriginsMax );
35667+
Abc_Print( 1, ".\n" );
3565035668
}
3565135669
return 0;
3565235670

3565335671
usage:
35654-
Abc_Print( -2, "usage: &origins_id [-h]\n" );
35672+
Abc_Print( -2, "usage: &origins_id [-M num] [-h]\n" );
3565535673
Abc_Print( -2, "\t sets identity origins for testing (each AND node -> itself)\n" );
3565635674
Abc_Print( -2, "\t in normal abc9 flow, origins come from XAIGER \"y\" extension\n" );
35675+
Abc_Print( -2, "\t-M num : max origins per object, 0 = unlimited [default = %d]\n", nOriginsMax );
3565735676
Abc_Print( -2, "\t-h : print the command usage\n");
3565835677
return 1;
3565935678
}

0 commit comments

Comments
 (0)