Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
abc
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
abc
Commits
88c57c93
Commit
88c57c93
authored
Dec 13, 2014
by
Alan Mishchenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Several additional files for source control.
parent
6b6e5861
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
6537 additions
and
8 deletions
+6537
-8
src/aig/gia/giaLf.c
+2234
-4
src/aig/gia/giaNf.c
+2494
-1
src/aig/gia/giaStr.c
+1809
-3
No files found.
src/aig/gia/giaLf.c
View file @
88c57c93
...
...
@@ -8,7 +8,7 @@
Synopsis [Cut computation.]
Author [Alan Mishchenko]
Author [Alan Mishchenko]
`
Affiliation [UC Berkeley]
...
...
@@ -19,7 +19,10 @@
***********************************************************************/
#include "gia.h"
#include "misc/tim/tim.h"
#include "misc/vec/vecSet.h"
#include "misc/vec/vecMem.h"
#include "misc/util/utilTruth.h"
ABC_NAMESPACE_IMPL_START
...
...
@@ -27,11 +30,1942 @@ ABC_NAMESPACE_IMPL_START
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define LF_LEAF_MAX 12
#define LF_CUT_MAX 32
#define LF_LOG_PAGE 12
#define LF_NO_LEAF 255
#define LF_CUT_WORDS (4+LF_LEAF_MAX/2)
#define LF_TT_WORDS ((LF_LEAF_MAX > 6) ? 1 << (LF_LEAF_MAX-6) : 1)
typedef
struct
Lf_Cut_t_
Lf_Cut_t
;
struct
Lf_Cut_t_
{
word
Sign
;
// signature
int
Delay
;
// delay
float
Flow
;
// flow
int
iFunc
;
// functionality
unsigned
Cost
:
22
;
// misc cut cost
unsigned
fLate
:
1
;
// fails timing
unsigned
fMux7
:
1
;
// specialized cut
unsigned
nLeaves
:
8
;
// the number of leaves
int
pLeaves
[
0
];
// leaves
};
typedef
struct
Lf_Plc_t_
Lf_Plc_t
;
struct
Lf_Plc_t_
{
unsigned
fUsed
:
1
;
// the cut is used
unsigned
Handle
:
31
;
// the cut handle
};
typedef
struct
Lf_Bst_t_
Lf_Bst_t
;
struct
Lf_Bst_t_
{
int
Delay
[
3
];
// delay
float
Flow
[
3
];
// flow
Lf_Plc_t
Cut
[
2
];
// cut info
};
typedef
struct
Lf_Mem_t_
Lf_Mem_t
;
struct
Lf_Mem_t_
{
int
LogPage
;
// log size of memory page
int
MaskPage
;
// page mask
int
nCutWords
;
// cut size in words
int
iCur
;
// writing position
Vec_Ptr_t
vPages
;
// memory pages
Vec_Ptr_t
*
vFree
;
// free pages
};
typedef
struct
Lf_Man_t_
Lf_Man_t
;
struct
Lf_Man_t_
{
// user data
Gia_Man_t
*
pGia
;
// manager
Jf_Par_t
*
pPars
;
// parameters
// cut data
int
nCutWords
;
// cut size in words
int
nSetWords
;
// set size in words
Lf_Bst_t
*
pObjBests
;
// best cuts
Vec_Ptr_t
vMemSets
;
// memory for cutsets
Vec_Int_t
vFreeSets
;
// free cutsets
Vec_Mem_t
*
vTtMem
;
// truth tables
Vec_Ptr_t
vFreePages
;
// free memory pages
Lf_Mem_t
vStoreOld
;
// previous cuts
Lf_Mem_t
vStoreNew
;
// current cuts
// mapper data
Vec_Int_t
vOffsets
;
// offsets
Vec_Int_t
vRequired
;
// required times
Vec_Int_t
vCutSets
;
// cutsets (pObj->Value stores cut refs)
Vec_Flt_t
vFlowRefs
;
// flow refs
Vec_Int_t
vMapRefs
;
// mapping refs
Vec_Flt_t
vSwitches
;
// switching activity
Vec_Int_t
vCiArrivals
;
// arrival times of the CIs
// statistics
abctime
clkStart
;
// starting time
double
CutCount
[
4
];
// cut counts
double
Switches
;
// switching activity
int
nFrontMax
;
// frontier
int
nCoDrivers
;
// CO drivers
int
nInverters
;
// inverters
int
nTimeFails
;
// timing fails
int
Iter
;
// mapping iteration
int
fUseEla
;
// use exact local area
int
nCutMux
;
// non-trivial MUX cuts
int
nCutEqual
;
// equal two cuts
int
nCutCounts
[
LF_LEAF_MAX
+
1
];
};
static
inline
void
Lf_CutCopy
(
Lf_Cut_t
*
p
,
Lf_Cut_t
*
q
,
int
n
)
{
memcpy
(
p
,
q
,
sizeof
(
word
)
*
n
);
}
static
inline
Lf_Cut_t
*
Lf_CutNext
(
Lf_Cut_t
*
p
,
int
n
)
{
return
(
Lf_Cut_t
*
)((
word
*
)
p
+
n
);
}
static
inline
word
*
Lf_CutTruth
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut
)
{
return
Vec_MemReadEntry
(
p
->
vTtMem
,
Abc_Lit2Var
(
pCut
->
iFunc
));
}
static
inline
int
Lf_ObjOff
(
Lf_Man_t
*
p
,
int
i
)
{
return
Vec_IntEntry
(
&
p
->
vOffsets
,
i
);
}
static
inline
int
Lf_ObjRequired
(
Lf_Man_t
*
p
,
int
i
)
{
return
Vec_IntEntry
(
&
p
->
vRequired
,
i
);
}
static
inline
void
Lf_ObjSetRequired
(
Lf_Man_t
*
p
,
int
i
,
int
t
)
{
Vec_IntDowndateEntry
(
&
p
->
vRequired
,
i
,
t
);
}
static
inline
Lf_Bst_t
*
Lf_ObjReadBest
(
Lf_Man_t
*
p
,
int
i
)
{
return
p
->
pObjBests
+
Lf_ObjOff
(
p
,
i
);
}
static
inline
float
Lf_ObjFlowRefs
(
Lf_Man_t
*
p
,
int
i
)
{
return
Vec_FltEntry
(
&
p
->
vFlowRefs
,
Lf_ObjOff
(
p
,
i
));
}
static
inline
int
Lf_ObjMapRefNum
(
Lf_Man_t
*
p
,
int
i
)
{
return
Vec_IntEntry
(
&
p
->
vMapRefs
,
Lf_ObjOff
(
p
,
i
));
}
static
inline
int
Lf_ObjMapRefInc
(
Lf_Man_t
*
p
,
int
i
)
{
return
(
*
Vec_IntEntryP
(
&
p
->
vMapRefs
,
Lf_ObjOff
(
p
,
i
)))
++
;
}
static
inline
int
Lf_ObjMapRefDec
(
Lf_Man_t
*
p
,
int
i
)
{
return
--
(
*
Vec_IntEntryP
(
&
p
->
vMapRefs
,
Lf_ObjOff
(
p
,
i
)));
}
static
inline
float
Lf_ObjSwitches
(
Lf_Man_t
*
p
,
int
i
)
{
return
Vec_FltEntry
(
&
p
->
vSwitches
,
i
);
}
static
inline
int
Lf_BestDiffCuts
(
Lf_Bst_t
*
p
)
{
return
p
->
Cut
[
0
].
Handle
!=
p
->
Cut
[
1
].
Handle
;
}
static
inline
int
Lf_BestIsMapped
(
Lf_Bst_t
*
p
)
{
return
(
int
)(
p
->
Cut
[
0
].
fUsed
^
p
->
Cut
[
1
].
fUsed
);
}
static
inline
int
Lf_BestIndex
(
Lf_Bst_t
*
p
)
{
return
p
->
Cut
[
1
].
fUsed
;
}
static
inline
int
Lf_BestCutIndex
(
Lf_Bst_t
*
p
)
{
if
(
p
->
Cut
[
0
].
fUsed
)
return
0
;
if
(
p
->
Cut
[
1
].
fUsed
)
return
1
;
return
2
;
}
#define Lf_CutSetForEachCut( nWords, pCutSet, pCut, i, nCuts ) for ( i = 0, pCut = pCutSet; i < nCuts; pCut = Lf_CutNext(pCut, nWords), i++ )
#define Lf_CutForEachVar( pCut, Var, i ) for ( i = 0; i < (int)pCut->nLeaves && (Var = pCut->pLeaves[i]); i++ ) if ( Lf_ObjOff(p, Var) < 0 ) {} else
extern
int
Kit_TruthToGia
(
Gia_Man_t
*
pMan
,
unsigned
*
pTruth
,
int
nVars
,
Vec_Int_t
*
vMemory
,
Vec_Int_t
*
vLeaves
,
int
fHash
);
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
void
Lf_ObjSetCiArrival
(
Lf_Man_t
*
p
,
int
iCi
,
int
Time
)
{
Vec_IntWriteEntry
(
&
p
->
vCiArrivals
,
iCi
,
Time
);
}
static
inline
int
Lf_ObjCiArrival
(
Lf_Man_t
*
p
,
int
iCi
)
{
return
Vec_IntEntry
(
&
p
->
vCiArrivals
,
iCi
);
}
int
Lf_ObjArrival_rec
(
Lf_Man_t
*
p
,
Gia_Obj_t
*
pDriver
)
{
if
(
Gia_ObjIsBuf
(
pDriver
)
)
return
Lf_ObjArrival_rec
(
p
,
Gia_ObjFanin0
(
pDriver
)
);
if
(
Gia_ObjIsAnd
(
pDriver
)
)
return
Lf_ObjReadBest
(
p
,
Gia_ObjId
(
p
->
pGia
,
pDriver
))
->
Delay
[
0
];
if
(
Gia_ObjIsCi
(
pDriver
)
)
return
Lf_ObjCiArrival
(
p
,
Gia_ObjCioId
(
pDriver
));
return
0
;
}
static
inline
int
Lf_ObjCoArrival
(
Lf_Man_t
*
p
,
int
iCo
)
{
Gia_Obj_t
*
pObj
=
Gia_ManCo
(
p
->
pGia
,
iCo
);
Gia_Obj_t
*
pDriver
=
Gia_ObjFanin0
(
pObj
);
return
Lf_ObjArrival_rec
(
p
,
pDriver
);
// if ( Gia_ObjIsAnd(pDriver) )
// return Lf_ObjReadBest(p, Gia_ObjId(p->pGia, pDriver))->Delay[0];
// if ( Gia_ObjIsCi(pDriver) )
// return Lf_ObjCiArrival(p, Gia_ObjCioId(pDriver));
// return 0;
}
int
Lf_ObjCoArrival2_rec
(
Lf_Man_t
*
p
,
Gia_Obj_t
*
pDriver
)
{
if
(
Gia_ObjIsBuf
(
pDriver
)
)
return
Lf_ObjCoArrival2_rec
(
p
,
Gia_ObjFanin0
(
pDriver
)
);
if
(
Gia_ObjIsAnd
(
pDriver
)
)
{
Lf_Bst_t
*
pBest
=
Lf_ObjReadBest
(
p
,
Gia_ObjId
(
p
->
pGia
,
pDriver
));
int
Index
=
Lf_BestCutIndex
(
pBest
);
assert
(
Index
<
2
||
Gia_ObjIsMux
(
p
->
pGia
,
pDriver
)
);
return
pBest
->
Delay
[
Index
];
}
if
(
Gia_ObjIsCi
(
pDriver
)
)
return
Lf_ObjCiArrival
(
p
,
Gia_ObjCioId
(
pDriver
));
return
0
;
}
static
inline
int
Lf_ObjCoArrival2
(
Lf_Man_t
*
p
,
int
iCo
)
{
Gia_Obj_t
*
pObj
=
Gia_ManCo
(
p
->
pGia
,
iCo
);
Gia_Obj_t
*
pDriver
=
Gia_ObjFanin0
(
pObj
);
return
Lf_ObjCoArrival2_rec
(
p
,
pDriver
);
// if ( Gia_ObjIsAnd(pDriver) )
// {
// Lf_Bst_t * pBest = Lf_ObjReadBest(p, Gia_ObjId(p->pGia, pDriver));
// int Index = Lf_BestCutIndex( pBest );
// assert( Index < 2 || Gia_ObjIsMux(p->pGia, pDriver) );
// return pBest->Delay[Index];
// }
// if ( Gia_ObjIsCi(pDriver) )
// return Lf_ObjCiArrival(p, Gia_ObjCioId(pDriver));
// return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int
Lf_ManComputeCrossCut
(
Gia_Man_t
*
p
)
{
Gia_Obj_t
*
pObj
;
int
i
,
nCutMax
=
0
,
nCutCur
=
0
;
assert
(
p
->
pMuxes
==
NULL
);
Gia_ManForEachObj
(
p
,
pObj
,
i
)
pObj
->
Value
=
0
;
Gia_ManForEachAnd
(
p
,
pObj
,
i
)
{
if
(
Gia_ObjIsAnd
(
Gia_ObjFanin0
(
pObj
))
)
Gia_ObjFanin0
(
pObj
)
->
Value
++
;
if
(
Gia_ObjIsAnd
(
Gia_ObjFanin1
(
pObj
))
)
Gia_ObjFanin1
(
pObj
)
->
Value
++
;
}
Gia_ManForEachAnd
(
p
,
pObj
,
i
)
{
if
(
pObj
->
Value
)
nCutCur
++
;
if
(
nCutMax
<
nCutCur
)
nCutMax
=
nCutCur
;
if
(
Gia_ObjIsAnd
(
Gia_ObjFanin0
(
pObj
))
&&
--
Gia_ObjFanin0
(
pObj
)
->
Value
==
0
)
nCutCur
--
;
if
(
Gia_ObjIsAnd
(
Gia_ObjFanin1
(
pObj
))
&&
--
Gia_ObjFanin1
(
pObj
)
->
Value
==
0
)
nCutCur
--
;
}
assert
(
nCutCur
==
0
);
if
(
nCutCur
)
printf
(
"Cutset is not 0
\n
"
);
Gia_ManForEachObj
(
p
,
pObj
,
i
)
assert
(
pObj
->
Value
==
0
);
printf
(
"CutMax = %d
\n
"
,
nCutMax
);
return
nCutMax
;
}
/**Function*************************************************************
Synopsis [Detect MUX truth tables.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int
Lf_ManTtIsMux
(
word
t
)
{
static
unsigned
s_Muxes
[
24
]
=
{
(
~
0xAAAAAAAA
&
~
0xCCCCCCCC
)
|
(
0xAAAAAAAA
&
~
0xF0F0F0F0
),
(
~
0xAAAAAAAA
&
~
0xCCCCCCCC
)
|
(
0xAAAAAAAA
&
0xF0F0F0F0
),
(
~
0xAAAAAAAA
&
0xCCCCCCCC
)
|
(
0xAAAAAAAA
&
~
0xF0F0F0F0
),
(
~
0xAAAAAAAA
&
0xCCCCCCCC
)
|
(
0xAAAAAAAA
&
0xF0F0F0F0
),
(
0xAAAAAAAA
&
~
0xCCCCCCCC
)
|
(
~
0xAAAAAAAA
&
~
0xF0F0F0F0
),
(
0xAAAAAAAA
&
~
0xCCCCCCCC
)
|
(
~
0xAAAAAAAA
&
0xF0F0F0F0
),
(
0xAAAAAAAA
&
0xCCCCCCCC
)
|
(
~
0xAAAAAAAA
&
~
0xF0F0F0F0
),
(
0xAAAAAAAA
&
0xCCCCCCCC
)
|
(
~
0xAAAAAAAA
&
0xF0F0F0F0
),
(
~
0xCCCCCCCC
&
~
0xAAAAAAAA
)
|
(
0xCCCCCCCC
&
~
0xF0F0F0F0
),
(
~
0xCCCCCCCC
&
~
0xAAAAAAAA
)
|
(
0xCCCCCCCC
&
0xF0F0F0F0
),
(
~
0xCCCCCCCC
&
0xAAAAAAAA
)
|
(
0xCCCCCCCC
&
~
0xF0F0F0F0
),
(
~
0xCCCCCCCC
&
0xAAAAAAAA
)
|
(
0xCCCCCCCC
&
0xF0F0F0F0
),
(
0xCCCCCCCC
&
~
0xAAAAAAAA
)
|
(
~
0xCCCCCCCC
&
~
0xF0F0F0F0
),
(
0xCCCCCCCC
&
~
0xAAAAAAAA
)
|
(
~
0xCCCCCCCC
&
0xF0F0F0F0
),
(
0xCCCCCCCC
&
0xAAAAAAAA
)
|
(
~
0xCCCCCCCC
&
~
0xF0F0F0F0
),
(
0xCCCCCCCC
&
0xAAAAAAAA
)
|
(
~
0xCCCCCCCC
&
0xF0F0F0F0
),
(
~
0xF0F0F0F0
&
~
0xCCCCCCCC
)
|
(
0xF0F0F0F0
&
~
0xAAAAAAAA
),
(
~
0xF0F0F0F0
&
~
0xCCCCCCCC
)
|
(
0xF0F0F0F0
&
0xAAAAAAAA
),
(
~
0xF0F0F0F0
&
0xCCCCCCCC
)
|
(
0xF0F0F0F0
&
~
0xAAAAAAAA
),
(
~
0xF0F0F0F0
&
0xCCCCCCCC
)
|
(
0xF0F0F0F0
&
0xAAAAAAAA
),
(
0xF0F0F0F0
&
~
0xCCCCCCCC
)
|
(
~
0xF0F0F0F0
&
~
0xAAAAAAAA
),
(
0xF0F0F0F0
&
~
0xCCCCCCCC
)
|
(
~
0xF0F0F0F0
&
0xAAAAAAAA
),
(
0xF0F0F0F0
&
0xCCCCCCCC
)
|
(
~
0xF0F0F0F0
&
~
0xAAAAAAAA
),
(
0xF0F0F0F0
&
0xCCCCCCCC
)
|
(
~
0xF0F0F0F0
&
0xAAAAAAAA
)
};
int
i
;
for
(
i
=
0
;
i
<
24
;
i
++
)
if
(
((
unsigned
)
t
)
==
s_Muxes
[
i
]
)
return
1
;
return
0
;
}
/**Function*************************************************************
Synopsis [Count the number of unique drivers and invertors.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void
Lf_ManAnalyzeCoDrivers
(
Gia_Man_t
*
p
,
int
*
pnDrivers
,
int
*
pnInverts
)
{
Gia_Obj_t
*
pObj
;
int
i
,
Entry
,
nDrivers
,
nInverts
;
Vec_Int_t
*
vMarks
=
Vec_IntStart
(
Gia_ManObjNum
(
p
)
);
nDrivers
=
nInverts
=
0
;
Gia_ManForEachCo
(
p
,
pObj
,
i
)
*
Vec_IntEntryP
(
vMarks
,
Gia_ObjFaninId0p
(
p
,
pObj
)
)
|=
Gia_ObjFaninC0
(
pObj
)
?
2
:
1
;
Vec_IntForEachEntry
(
vMarks
,
Entry
,
i
)
nDrivers
+=
(
int
)(
Entry
!=
0
),
nInverts
+=
(
int
)(
Entry
==
3
);
Vec_IntFree
(
vMarks
);
*
pnDrivers
=
nDrivers
;
*
pnInverts
=
nInverts
;
}
void
Lf_ManComputeSwitching
(
Gia_Man_t
*
p
,
Vec_Flt_t
*
vSwitches
)
{
// abctime clk = Abc_Clock();
Vec_Flt_t
*
vSwitching
=
(
Vec_Flt_t
*
)
Gia_ManComputeSwitchProbs
(
p
,
48
,
16
,
0
);
assert
(
Vec_FltCap
(
vSwitches
)
==
0
);
*
vSwitches
=
*
vSwitching
;
ABC_FREE
(
vSwitching
);
// Abc_PrintTime( 1, "Computing switching activity", Abc_Clock() - clk );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Lf_CutCreateUnit
(
Lf_Cut_t
*
p
,
int
i
)
{
p
->
fLate
=
0
;
p
->
fMux7
=
0
;
p
->
iFunc
=
2
;
p
->
nLeaves
=
1
;
p
->
pLeaves
[
0
]
=
i
;
p
->
Sign
=
((
word
)
1
)
<<
(
i
&
0x3F
);
return
1
;
}
static
inline
Lf_Cut_t
*
Lf_ManFetchSet
(
Lf_Man_t
*
p
,
int
i
)
{
int
uMaskPage
=
(
1
<<
LF_LOG_PAGE
)
-
1
;
Gia_Obj_t
*
pObj
=
Gia_ManObj
(
p
->
pGia
,
i
);
int
iOffSet
=
Vec_IntEntry
(
&
p
->
vOffsets
,
i
);
int
Entry
=
Vec_IntEntry
(
&
p
->
vCutSets
,
iOffSet
);
assert
(
Gia_ObjIsAndNotBuf
(
pObj
)
);
assert
(
pObj
->
Value
>
0
);
if
(
Entry
==
-
1
)
// first visit
{
if
(
Vec_IntSize
(
&
p
->
vFreeSets
)
==
0
)
// add new
{
Lf_Cut_t
*
pCut
=
(
Lf_Cut_t
*
)
ABC_CALLOC
(
word
,
p
->
nSetWords
*
(
1
<<
LF_LOG_PAGE
)
);
int
uMaskShift
=
Vec_PtrSize
(
&
p
->
vMemSets
)
<<
LF_LOG_PAGE
;
Vec_PtrPush
(
&
p
->
vMemSets
,
pCut
);
for
(
Entry
=
uMaskPage
;
Entry
>=
0
;
Entry
--
)
{
Vec_IntPush
(
&
p
->
vFreeSets
,
uMaskShift
|
Entry
);
pCut
[
Entry
].
nLeaves
=
LF_NO_LEAF
;
}
}
Entry
=
Vec_IntPop
(
&
p
->
vFreeSets
);
Vec_IntWriteEntry
(
&
p
->
vCutSets
,
iOffSet
,
Entry
);
p
->
nFrontMax
=
Abc_MaxInt
(
p
->
nFrontMax
,
Entry
+
1
);
}
else
if
(
--
pObj
->
Value
==
0
)
{
Vec_IntPush
(
&
p
->
vFreeSets
,
Entry
);
Vec_IntWriteEntry
(
&
p
->
vCutSets
,
iOffSet
,
-
1
);
}
return
(
Lf_Cut_t
*
)((
word
*
)
Vec_PtrEntry
(
&
p
->
vMemSets
,
Entry
>>
LF_LOG_PAGE
)
+
p
->
nSetWords
*
(
Entry
&
uMaskPage
));
}
static
inline
int
Lf_ManPrepareSet
(
Lf_Man_t
*
p
,
int
iObj
,
int
Index
,
Lf_Cut_t
**
ppCutSet
)
{
static
word
CutTemp
[
3
][
LF_CUT_WORDS
];
if
(
Vec_IntEntry
(
&
p
->
vOffsets
,
iObj
)
==
-
1
)
return
Lf_CutCreateUnit
(
(
*
ppCutSet
=
(
Lf_Cut_t
*
)
CutTemp
[
Index
]),
iObj
);
{
Lf_Cut_t
*
pCut
;
int
i
,
nCutNum
=
p
->
pPars
->
nCutNum
;
*
ppCutSet
=
Lf_ManFetchSet
(
p
,
iObj
);
Lf_CutSetForEachCut
(
p
->
nCutWords
,
*
ppCutSet
,
pCut
,
i
,
nCutNum
)
if
(
pCut
->
nLeaves
==
LF_NO_LEAF
)
return
i
;
return
i
;
}
}
/**Function*************************************************************
Synopsis [Cut manipulation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
word
Lf_CutGetSign
(
Lf_Cut_t
*
pCut
)
{
word
Sign
=
0
;
int
i
;
for
(
i
=
0
;
i
<
(
int
)
pCut
->
nLeaves
;
i
++
)
Sign
|=
((
word
)
1
)
<<
(
pCut
->
pLeaves
[
i
]
&
0x3F
);
return
Sign
;
}
static
inline
int
Lf_CutCountBits
(
word
i
)
{
i
=
i
-
((
i
>>
1
)
&
0x5555555555555555
);
i
=
(
i
&
0x3333333333333333
)
+
((
i
>>
2
)
&
0x3333333333333333
);
i
=
((
i
+
(
i
>>
4
))
&
0x0F0F0F0F0F0F0F0F
);
return
(
i
*
(
0x0101010101010101
))
>>
56
;
}
static
inline
int
Lf_CutEqual
(
Lf_Cut_t
*
pCut0
,
Lf_Cut_t
*
pCut1
)
{
int
i
;
if
(
pCut0
->
iFunc
!=
pCut1
->
iFunc
)
return
0
;
if
(
pCut0
->
nLeaves
!=
pCut1
->
nLeaves
)
return
0
;
for
(
i
=
0
;
i
<
(
int
)
pCut0
->
nLeaves
;
i
++
)
if
(
pCut0
->
pLeaves
[
i
]
!=
pCut1
->
pLeaves
[
i
]
)
return
0
;
return
1
;
}
static
inline
float
Lf_CutSwitches
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut
)
{
float
Switches
=
0
;
int
i
;
for
(
i
=
0
;
i
<
(
int
)
pCut
->
nLeaves
;
i
++
)
Switches
+=
Lf_ObjSwitches
(
p
,
pCut
->
pLeaves
[
i
]);
//printf( "%.2f ", Switches );
return
Switches
;
}
static
inline
void
Lf_CutPrint
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut
)
{
int
i
,
nDigits
=
Abc_Base10Log
(
Gia_ManObjNum
(
p
->
pGia
));
printf
(
"%d {"
,
pCut
->
nLeaves
);
for
(
i
=
0
;
i
<
(
int
)
pCut
->
nLeaves
;
i
++
)
printf
(
" %*d"
,
nDigits
,
pCut
->
pLeaves
[
i
]
);
for
(
;
i
<
(
int
)
p
->
pPars
->
nLutSize
;
i
++
)
printf
(
" %*s"
,
nDigits
,
" "
);
printf
(
" } Late = %d D = %4d A = %9.4f F = %6d
\n
"
,
pCut
->
fLate
,
pCut
->
Delay
,
pCut
->
Flow
,
pCut
->
iFunc
);
}
static
inline
float
Lf_CutArea
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut
)
{
if
(
pCut
->
nLeaves
<
2
||
pCut
->
fMux7
)
return
0
;
if
(
p
->
pPars
->
fPower
)
return
1
.
0
*
pCut
->
nLeaves
+
Lf_CutSwitches
(
p
,
pCut
);
if
(
p
->
pPars
->
fOptEdge
)
return
pCut
->
nLeaves
+
p
->
pPars
->
nAreaTuner
;
return
1
;
}
static
inline
int
Lf_CutIsMux
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut
,
Gia_Obj_t
*
pMux
)
{
int
i
,
Id
;
if
(
pCut
->
nLeaves
!=
3
)
return
0
;
assert
(
Gia_ObjIsMux
(
p
->
pGia
,
pMux
)
);
if
(
Gia_ObjIsCi
(
Gia_ObjFanin0
(
pMux
))
||
Gia_ObjIsCi
(
Gia_ObjFanin1
(
pMux
))
)
return
0
;
Id
=
Gia_ObjFaninId0p
(
p
->
pGia
,
pMux
);
for
(
i
=
0
;
i
<
3
;
i
++
)
if
(
pCut
->
pLeaves
[
i
]
==
Id
)
break
;
if
(
i
==
3
)
return
0
;
Id
=
Gia_ObjFaninId1p
(
p
->
pGia
,
pMux
);
for
(
i
=
0
;
i
<
3
;
i
++
)
if
(
pCut
->
pLeaves
[
i
]
==
Id
)
break
;
if
(
i
==
3
)
return
0
;
Id
=
Gia_ObjFaninId2p
(
p
->
pGia
,
pMux
);
for
(
i
=
0
;
i
<
3
;
i
++
)
if
(
pCut
->
pLeaves
[
i
]
==
Id
)
break
;
if
(
i
==
3
)
return
0
;
return
1
;
}
/**Function*************************************************************
Synopsis [Cut packing.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
void
Lf_MemAlloc
(
Lf_Mem_t
*
p
,
int
LogPage
,
Vec_Ptr_t
*
vFree
,
int
nCutWords
)
{
memset
(
p
,
0
,
sizeof
(
Lf_Mem_t
)
);
p
->
LogPage
=
LogPage
;
p
->
MaskPage
=
(
1
<<
LogPage
)
-
1
;
p
->
nCutWords
=
nCutWords
;
p
->
vFree
=
vFree
;
}
static
inline
int
Lf_MemSaveCut
(
Lf_Mem_t
*
p
,
Lf_Cut_t
*
pCut
,
int
iObj
)
{
unsigned
char
*
pPlace
;
int
i
,
iPlace
,
Prev
=
iObj
,
iCur
=
p
->
iCur
;
assert
(
!
pCut
->
fMux7
);
if
(
Vec_PtrSize
(
&
p
->
vPages
)
==
(
p
->
iCur
>>
p
->
LogPage
)
)
Vec_PtrPush
(
&
p
->
vPages
,
Vec_PtrSize
(
p
->
vFree
)
?
Vec_PtrPop
(
p
->
vFree
)
:
ABC_ALLOC
(
char
,
p
->
MaskPage
+
1
)
);
assert
(
p
->
MaskPage
-
(
p
->
iCur
&
p
->
MaskPage
)
>=
4
*
(
LF_LEAF_MAX
+
2
)
);
iPlace
=
iCur
&
p
->
MaskPage
;
pPlace
=
(
unsigned
char
*
)
Vec_PtrEntry
(
&
p
->
vPages
,
p
->
iCur
>>
p
->
LogPage
);
iPlace
=
Gia_AigerWriteUnsignedBuffer
(
pPlace
,
iPlace
,
pCut
->
nLeaves
);
for
(
i
=
pCut
->
nLeaves
-
1
;
i
>=
0
;
i
--
)
iPlace
=
Gia_AigerWriteUnsignedBuffer
(
pPlace
,
iPlace
,
Prev
-
pCut
->
pLeaves
[
i
]
),
Prev
=
pCut
->
pLeaves
[
i
];
assert
(
pCut
->
nLeaves
>=
2
||
pCut
->
iFunc
<=
3
);
if
(
pCut
->
iFunc
>=
0
)
iPlace
=
Gia_AigerWriteUnsignedBuffer
(
pPlace
,
iPlace
,
pCut
->
iFunc
);
if
(
p
->
MaskPage
-
(
iPlace
&
p
->
MaskPage
)
<
4
*
(
LF_LEAF_MAX
+
2
)
)
p
->
iCur
=
((
p
->
iCur
>>
p
->
LogPage
)
+
1
)
<<
p
->
LogPage
;
else
p
->
iCur
=
(
p
->
iCur
&
~
p
->
MaskPage
)
|
iPlace
;
return
iCur
;
}
static
inline
Lf_Cut_t
*
Lf_MemLoadCut
(
Lf_Mem_t
*
p
,
int
iCur
,
int
iObj
,
Lf_Cut_t
*
pCut
,
int
fTruth
,
int
fRecycle
)
{
unsigned
char
*
pPlace
;
int
i
,
Prev
=
iObj
,
Page
=
iCur
>>
p
->
LogPage
;
assert
(
Page
<
Vec_PtrSize
(
&
p
->
vPages
)
);
pPlace
=
(
unsigned
char
*
)
Vec_PtrEntry
(
&
p
->
vPages
,
Page
)
+
(
iCur
&
p
->
MaskPage
);
pCut
->
nLeaves
=
Gia_AigerReadUnsigned
(
&
pPlace
);
assert
(
pCut
->
nLeaves
<=
LF_LEAF_MAX
);
for
(
i
=
pCut
->
nLeaves
-
1
;
i
>=
0
;
i
--
)
pCut
->
pLeaves
[
i
]
=
Prev
-
Gia_AigerReadUnsigned
(
&
pPlace
),
Prev
=
pCut
->
pLeaves
[
i
];
pCut
->
iFunc
=
fTruth
?
Gia_AigerReadUnsigned
(
&
pPlace
)
:
-
1
;
assert
(
pCut
->
nLeaves
>=
2
||
pCut
->
iFunc
<=
3
);
if
(
fRecycle
&&
Page
&&
Vec_PtrEntry
(
&
p
->
vPages
,
Page
-
1
)
)
{
Vec_PtrPush
(
p
->
vFree
,
Vec_PtrEntry
(
&
p
->
vPages
,
Page
-
1
)
);
Vec_PtrWriteEntry
(
&
p
->
vPages
,
Page
-
1
,
NULL
);
}
pCut
->
Sign
=
fRecycle
?
Lf_CutGetSign
(
pCut
)
:
0
;
pCut
->
fMux7
=
0
;
return
pCut
;
}
static
inline
void
Lf_MemRecycle
(
Lf_Mem_t
*
p
)
{
void
*
pPlace
;
int
i
;
Vec_PtrForEachEntry
(
void
*
,
&
p
->
vPages
,
pPlace
,
i
)
if
(
pPlace
)
Vec_PtrPush
(
p
->
vFree
,
pPlace
);
Vec_PtrClear
(
&
p
->
vPages
);
p
->
iCur
=
0
;
}
static
inline
Lf_Cut_t
*
Lf_MemLoadMuxCut
(
Lf_Man_t
*
p
,
int
iObj
,
Lf_Cut_t
*
pCut
)
{
Gia_Obj_t
*
pMux
=
Gia_ManObj
(
p
->
pGia
,
iObj
);
assert
(
Gia_ObjIsMux
(
p
->
pGia
,
pMux
)
);
pCut
->
iFunc
=
p
->
pPars
->
fCutMin
?
4
:
-
1
;
pCut
->
pLeaves
[
0
]
=
Gia_ObjFaninId0
(
pMux
,
iObj
);
pCut
->
pLeaves
[
1
]
=
Gia_ObjFaninId1
(
pMux
,
iObj
);
pCut
->
pLeaves
[
2
]
=
Gia_ObjFaninId2
(
p
->
pGia
,
iObj
);
pCut
->
nLeaves
=
3
;
pCut
->
fMux7
=
1
;
return
pCut
;
}
static
inline
Lf_Cut_t
*
Lf_ObjCutMux
(
Lf_Man_t
*
p
,
int
i
)
{
static
word
CutSet
[
LF_CUT_WORDS
];
return
Lf_MemLoadMuxCut
(
p
,
i
,
(
Lf_Cut_t
*
)
CutSet
);
}
static
inline
Lf_Cut_t
*
Lf_ObjCutBest
(
Lf_Man_t
*
p
,
int
i
)
{
static
word
CutSet
[
LF_CUT_WORDS
];
Lf_Bst_t
*
pBest
=
Lf_ObjReadBest
(
p
,
i
);
Lf_Cut_t
*
pCut
=
(
Lf_Cut_t
*
)
CutSet
;
int
Index
=
Lf_BestCutIndex
(
pBest
);
pCut
->
Delay
=
pBest
->
Delay
[
Index
];
pCut
->
Flow
=
pBest
->
Flow
[
Index
];
if
(
Index
==
2
)
return
Lf_MemLoadMuxCut
(
p
,
i
,
pCut
);
return
Lf_MemLoadCut
(
&
p
->
vStoreOld
,
pBest
->
Cut
[
Index
].
Handle
,
i
,
pCut
,
p
->
pPars
->
fCutMin
,
0
);
}
static
inline
Lf_Cut_t
*
Lf_ObjCutBestNew
(
Lf_Man_t
*
p
,
int
i
,
Lf_Cut_t
*
pCut
)
{
Lf_Bst_t
*
pBest
=
Lf_ObjReadBest
(
p
,
i
);
int
Index
=
Lf_BestCutIndex
(
pBest
);
pCut
->
Delay
=
pBest
->
Delay
[
Index
];
pCut
->
Flow
=
pBest
->
Flow
[
Index
];
if
(
Index
==
2
)
return
Lf_MemLoadMuxCut
(
p
,
i
,
pCut
);
return
Lf_MemLoadCut
(
&
p
->
vStoreNew
,
pBest
->
Cut
[
Index
].
Handle
,
i
,
pCut
,
0
,
0
);
}
/**Function*************************************************************
Synopsis [Check correctness of cuts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Lf_CutCheck
(
Lf_Cut_t
*
pBase
,
Lf_Cut_t
*
pCut
)
// check if pCut is contained in pBase
{
int
nSizeB
=
pBase
->
nLeaves
;
int
nSizeC
=
pCut
->
nLeaves
;
int
i
,
*
pB
=
pBase
->
pLeaves
;
int
k
,
*
pC
=
pCut
->
pLeaves
;
for
(
i
=
0
;
i
<
nSizeC
;
i
++
)
{
for
(
k
=
0
;
k
<
nSizeB
;
k
++
)
if
(
pC
[
i
]
==
pB
[
k
]
)
break
;
if
(
k
==
nSizeB
)
return
0
;
}
return
1
;
}
static
inline
int
Lf_SetCheckArray
(
Lf_Cut_t
**
ppCuts
,
int
nCuts
)
{
Lf_Cut_t
*
pCut0
,
*
pCut1
;
int
i
,
k
,
m
,
n
,
Value
;
assert
(
nCuts
>
0
);
for
(
i
=
0
;
i
<
nCuts
;
i
++
)
{
pCut0
=
ppCuts
[
i
];
assert
(
!
pCut0
->
fMux7
);
assert
(
pCut0
->
nLeaves
<
LF_LEAF_MAX
);
assert
(
pCut0
->
Sign
==
Lf_CutGetSign
(
pCut0
)
);
// check duplicates
for
(
m
=
0
;
m
<
(
int
)
pCut0
->
nLeaves
;
m
++
)
for
(
n
=
m
+
1
;
n
<
(
int
)
pCut0
->
nLeaves
;
n
++
)
assert
(
pCut0
->
pLeaves
[
m
]
<
pCut0
->
pLeaves
[
n
]
);
// check pairs
for
(
k
=
0
;
k
<
nCuts
;
k
++
)
{
pCut1
=
ppCuts
[
k
];
if
(
pCut0
==
pCut1
)
continue
;
// check containments
Value
=
Lf_CutCheck
(
pCut0
,
pCut1
);
assert
(
Value
==
0
);
}
}
return
1
;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Lf_CutMergeOrder
(
Lf_Cut_t
*
pCut0
,
Lf_Cut_t
*
pCut1
,
Lf_Cut_t
*
pCut
,
int
nLutSize
)
{
int
nSize0
=
pCut0
->
nLeaves
;
int
nSize1
=
pCut1
->
nLeaves
;
int
i
,
*
pC0
=
pCut0
->
pLeaves
;
int
k
,
*
pC1
=
pCut1
->
pLeaves
;
int
c
,
*
pC
=
pCut
->
pLeaves
;
// the case of the largest cut sizes
if
(
nSize0
==
nLutSize
&&
nSize1
==
nLutSize
)
{
for
(
i
=
0
;
i
<
nSize0
;
i
++
)
{
if
(
pC0
[
i
]
!=
pC1
[
i
]
)
return
0
;
pC
[
i
]
=
pC0
[
i
];
}
pCut
->
nLeaves
=
nLutSize
;
pCut
->
iFunc
=
-
1
;
pCut
->
Sign
=
pCut0
->
Sign
|
pCut1
->
Sign
;
return
1
;
}
// compare two cuts with different numbers
i
=
k
=
c
=
0
;
if
(
nSize0
==
0
)
goto
FlushCut1
;
if
(
nSize1
==
0
)
goto
FlushCut0
;
while
(
1
)
{
if
(
c
==
nLutSize
)
return
0
;
if
(
pC0
[
i
]
<
pC1
[
k
]
)
{
pC
[
c
++
]
=
pC0
[
i
++
];
if
(
i
>=
nSize0
)
goto
FlushCut1
;
}
else
if
(
pC0
[
i
]
>
pC1
[
k
]
)
{
pC
[
c
++
]
=
pC1
[
k
++
];
if
(
k
>=
nSize1
)
goto
FlushCut0
;
}
else
{
pC
[
c
++
]
=
pC0
[
i
++
];
k
++
;
if
(
i
>=
nSize0
)
goto
FlushCut1
;
if
(
k
>=
nSize1
)
goto
FlushCut0
;
}
}
FlushCut0:
if
(
c
+
nSize0
>
nLutSize
+
i
)
return
0
;
while
(
i
<
nSize0
)
pC
[
c
++
]
=
pC0
[
i
++
];
pCut
->
nLeaves
=
c
;
pCut
->
iFunc
=
-
1
;
pCut
->
fMux7
=
0
;
pCut
->
Sign
=
pCut0
->
Sign
|
pCut1
->
Sign
;
return
1
;
FlushCut1:
if
(
c
+
nSize1
>
nLutSize
+
k
)
return
0
;
while
(
k
<
nSize1
)
pC
[
c
++
]
=
pC1
[
k
++
];
pCut
->
nLeaves
=
c
;
pCut
->
iFunc
=
-
1
;
pCut
->
fMux7
=
0
;
pCut
->
Sign
=
pCut0
->
Sign
|
pCut1
->
Sign
;
return
1
;
}
static
inline
int
Lf_CutMergeOrder2
(
Lf_Cut_t
*
pCut0
,
Lf_Cut_t
*
pCut1
,
Lf_Cut_t
*
pCut
,
int
nLutSize
)
{
int
x0
,
i0
=
0
,
nSize0
=
pCut0
->
nLeaves
,
*
pC0
=
pCut0
->
pLeaves
;
int
x1
,
i1
=
0
,
nSize1
=
pCut1
->
nLeaves
,
*
pC1
=
pCut1
->
pLeaves
;
int
xMin
,
c
=
0
,
*
pC
=
pCut
->
pLeaves
;
while
(
1
)
{
x0
=
(
i0
==
nSize0
)
?
ABC_INFINITY
:
pC0
[
i0
];
x1
=
(
i1
==
nSize1
)
?
ABC_INFINITY
:
pC1
[
i1
];
xMin
=
Abc_MinInt
(
x0
,
x1
);
if
(
xMin
==
ABC_INFINITY
)
break
;
if
(
c
==
nLutSize
)
return
0
;
pC
[
c
++
]
=
xMin
;
if
(
x0
==
xMin
)
i0
++
;
if
(
x1
==
xMin
)
i1
++
;
}
pCut
->
nLeaves
=
c
;
pCut
->
iFunc
=
-
1
;
pCut
->
fMux7
=
0
;
pCut
->
Sign
=
pCut0
->
Sign
|
pCut1
->
Sign
;
return
1
;
}
static
inline
int
Lf_CutMergeOrderMux
(
Lf_Cut_t
*
pCut0
,
Lf_Cut_t
*
pCut1
,
Lf_Cut_t
*
pCut2
,
Lf_Cut_t
*
pCut
,
int
nLutSize
)
{
int
x0
,
i0
=
0
,
nSize0
=
pCut0
->
nLeaves
,
*
pC0
=
pCut0
->
pLeaves
;
int
x1
,
i1
=
0
,
nSize1
=
pCut1
->
nLeaves
,
*
pC1
=
pCut1
->
pLeaves
;
int
x2
,
i2
=
0
,
nSize2
=
pCut2
->
nLeaves
,
*
pC2
=
pCut2
->
pLeaves
;
int
xMin
,
c
=
0
,
*
pC
=
pCut
->
pLeaves
;
while
(
1
)
{
x0
=
(
i0
==
nSize0
)
?
ABC_INFINITY
:
pC0
[
i0
];
x1
=
(
i1
==
nSize1
)
?
ABC_INFINITY
:
pC1
[
i1
];
x2
=
(
i2
==
nSize2
)
?
ABC_INFINITY
:
pC2
[
i2
];
xMin
=
Abc_MinInt
(
Abc_MinInt
(
x0
,
x1
),
x2
);
if
(
xMin
==
ABC_INFINITY
)
break
;
if
(
c
==
nLutSize
)
return
0
;
pC
[
c
++
]
=
xMin
;
if
(
x0
==
xMin
)
i0
++
;
if
(
x1
==
xMin
)
i1
++
;
if
(
x2
==
xMin
)
i2
++
;
}
pCut
->
nLeaves
=
c
;
pCut
->
iFunc
=
-
1
;
pCut
->
fMux7
=
0
;
pCut
->
Sign
=
pCut0
->
Sign
|
pCut1
->
Sign
|
pCut2
->
Sign
;
return
1
;
}
static
inline
int
Lf_SetCutIsContainedOrder
(
Lf_Cut_t
*
pBase
,
Lf_Cut_t
*
pCut
)
// check if pCut is contained in pBase
{
int
i
,
nSizeB
=
pBase
->
nLeaves
;
int
k
,
nSizeC
=
pCut
->
nLeaves
;
if
(
nSizeB
==
nSizeC
)
{
for
(
i
=
0
;
i
<
nSizeB
;
i
++
)
if
(
pBase
->
pLeaves
[
i
]
!=
pCut
->
pLeaves
[
i
]
)
return
0
;
return
1
;
}
assert
(
nSizeB
>
nSizeC
);
if
(
nSizeC
==
0
)
return
1
;
for
(
i
=
k
=
0
;
i
<
nSizeB
;
i
++
)
{
if
(
pBase
->
pLeaves
[
i
]
>
pCut
->
pLeaves
[
k
]
)
return
0
;
if
(
pBase
->
pLeaves
[
i
]
==
pCut
->
pLeaves
[
k
]
)
{
if
(
++
k
==
nSizeC
)
return
1
;
}
}
return
0
;
}
static
inline
int
Lf_SetLastCutIsContained
(
Lf_Cut_t
**
pCuts
,
int
nCuts
)
{
int
i
;
for
(
i
=
0
;
i
<
nCuts
;
i
++
)
if
(
pCuts
[
i
]
->
nLeaves
<=
pCuts
[
nCuts
]
->
nLeaves
&&
(
pCuts
[
i
]
->
Sign
&
pCuts
[
nCuts
]
->
Sign
)
==
pCuts
[
i
]
->
Sign
&&
Lf_SetCutIsContainedOrder
(
pCuts
[
nCuts
],
pCuts
[
i
])
)
return
1
;
return
0
;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Lf_CutCompareDelay
(
Lf_Cut_t
*
pCut0
,
Lf_Cut_t
*
pCut1
)
{
if
(
pCut0
->
Delay
<
pCut1
->
Delay
)
return
-
1
;
if
(
pCut0
->
Delay
>
pCut1
->
Delay
)
return
1
;
if
(
pCut0
->
nLeaves
<
pCut1
->
nLeaves
)
return
-
1
;
if
(
pCut0
->
nLeaves
>
pCut1
->
nLeaves
)
return
1
;
if
(
pCut0
->
Flow
<
pCut1
->
Flow
)
return
-
1
;
if
(
pCut0
->
Flow
>
pCut1
->
Flow
)
return
1
;
return
0
;
}
static
inline
int
Lf_CutCompareArea
(
Lf_Cut_t
*
pCut0
,
Lf_Cut_t
*
pCut1
)
{
if
(
pCut0
->
fLate
<
pCut1
->
fLate
)
return
-
1
;
if
(
pCut0
->
fLate
>
pCut1
->
fLate
)
return
1
;
if
(
pCut0
->
Flow
<
pCut1
->
Flow
)
return
-
1
;
if
(
pCut0
->
Flow
>
pCut1
->
Flow
)
return
1
;
if
(
pCut0
->
Delay
<
pCut1
->
Delay
)
return
-
1
;
if
(
pCut0
->
Delay
>
pCut1
->
Delay
)
return
1
;
if
(
pCut0
->
nLeaves
<
pCut1
->
nLeaves
)
return
-
1
;
if
(
pCut0
->
nLeaves
>
pCut1
->
nLeaves
)
return
1
;
return
0
;
}
static
inline
int
Lf_SetLastCutContainsArea
(
Lf_Cut_t
**
pCuts
,
int
nCuts
)
{
int
i
,
k
,
fChanges
=
0
;
for
(
i
=
1
;
i
<
nCuts
;
i
++
)
if
(
pCuts
[
nCuts
]
->
nLeaves
<
pCuts
[
i
]
->
nLeaves
&&
(
pCuts
[
nCuts
]
->
Sign
&
pCuts
[
i
]
->
Sign
)
==
pCuts
[
nCuts
]
->
Sign
&&
Lf_SetCutIsContainedOrder
(
pCuts
[
i
],
pCuts
[
nCuts
])
)
pCuts
[
i
]
->
nLeaves
=
LF_NO_LEAF
,
fChanges
=
1
;
if
(
!
fChanges
)
return
nCuts
;
for
(
i
=
k
=
1
;
i
<=
nCuts
;
i
++
)
{
if
(
pCuts
[
i
]
->
nLeaves
==
LF_NO_LEAF
)
continue
;
if
(
k
<
i
)
ABC_SWAP
(
Lf_Cut_t
*
,
pCuts
[
k
],
pCuts
[
i
]
);
k
++
;
}
return
k
-
1
;
}
static
inline
void
Lf_SetSortByArea
(
Lf_Cut_t
**
pCuts
,
int
nCuts
)
{
int
i
;
for
(
i
=
nCuts
;
i
>
1
;
i
--
)
{
if
(
Lf_CutCompareArea
(
pCuts
[
i
-
1
],
pCuts
[
i
])
<
0
)
//!= 1 )
return
;
ABC_SWAP
(
Lf_Cut_t
*
,
pCuts
[
i
-
1
],
pCuts
[
i
]
);
}
}
static
inline
int
Lf_SetAddCut
(
Lf_Cut_t
**
pCuts
,
int
nCuts
,
int
nCutNum
)
{
if
(
nCuts
==
0
)
return
1
;
nCuts
=
Lf_SetLastCutContainsArea
(
pCuts
,
nCuts
);
assert
(
nCuts
>=
1
);
if
(
Lf_CutCompareDelay
(
pCuts
[
0
],
pCuts
[
nCuts
])
==
1
)
// new cut is better for delay
{
ABC_SWAP
(
Lf_Cut_t
*
,
pCuts
[
0
],
pCuts
[
nCuts
]
);
// if old cut (now cut number nCuts) is contained - remove it
if
(
pCuts
[
0
]
->
nLeaves
<
pCuts
[
nCuts
]
->
nLeaves
&&
(
pCuts
[
0
]
->
Sign
&
pCuts
[
nCuts
]
->
Sign
)
==
pCuts
[
0
]
->
Sign
&&
Lf_SetCutIsContainedOrder
(
pCuts
[
nCuts
],
pCuts
[
0
])
)
return
nCuts
;
}
// sort area cuts by area
Lf_SetSortByArea
(
pCuts
,
nCuts
);
// add new cut if there is room
return
Abc_MinInt
(
nCuts
+
1
,
nCutNum
-
1
);
}
static
inline
void
Lf_SetSortBySize
(
Lf_Cut_t
**
pCutsR
,
int
nCutsR
)
{
int
i
,
j
,
best_i
;
for
(
i
=
1
;
i
<
nCutsR
-
1
;
i
++
)
{
best_i
=
i
;
for
(
j
=
i
+
1
;
j
<
nCutsR
;
j
++
)
if
(
pCutsR
[
j
]
->
nLeaves
>
pCutsR
[
best_i
]
->
nLeaves
)
best_i
=
j
;
ABC_SWAP
(
Lf_Cut_t
*
,
pCutsR
[
i
],
pCutsR
[
best_i
]
);
}
}
/**Function*************************************************************
Synopsis [Check if truth table has non-const-cof cofactoring variable.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Lf_ManFindCofVar
(
word
*
pTruth
,
int
nWords
,
int
nVars
)
{
word
uTruthCof
[
LF_TT_WORDS
];
int
iVar
;
for
(
iVar
=
0
;
iVar
<
nVars
;
iVar
++
)
{
Abc_TtCofactor0p
(
uTruthCof
,
pTruth
,
nWords
,
iVar
);
if
(
Abc_TtSupportSize
(
uTruthCof
,
nVars
)
<
2
)
continue
;
Abc_TtCofactor1p
(
uTruthCof
,
pTruth
,
nWords
,
iVar
);
if
(
Abc_TtSupportSize
(
uTruthCof
,
nVars
)
<
2
)
continue
;
return
iVar
;
}
return
-
1
;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Lf_CutComputeTruth6
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut0
,
Lf_Cut_t
*
pCut1
,
int
fCompl0
,
int
fCompl1
,
Lf_Cut_t
*
pCutR
,
int
fIsXor
)
{
// extern int Mf_ManTruthCanonicize( word * t, int nVars );
int
nOldSupp
=
pCutR
->
nLeaves
,
truthId
,
fCompl
;
word
t
;
word
t0
=
*
Lf_CutTruth
(
p
,
pCut0
);
word
t1
=
*
Lf_CutTruth
(
p
,
pCut1
);
if
(
Abc_LitIsCompl
(
pCut0
->
iFunc
)
^
fCompl0
)
t0
=
~
t0
;
if
(
Abc_LitIsCompl
(
pCut1
->
iFunc
)
^
fCompl1
)
t1
=
~
t1
;
t0
=
Abc_Tt6Expand
(
t0
,
pCut0
->
pLeaves
,
pCut0
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
t1
=
Abc_Tt6Expand
(
t1
,
pCut1
->
pLeaves
,
pCut1
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
t
=
fIsXor
?
t0
^
t1
:
t0
&
t1
;
if
(
(
fCompl
=
(
int
)(
t
&
1
))
)
t
=
~
t
;
pCutR
->
nLeaves
=
Abc_Tt6MinBase
(
&
t
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
assert
(
(
int
)(
t
&
1
)
==
0
);
truthId
=
Vec_MemHashInsert
(
p
->
vTtMem
,
&
t
);
pCutR
->
iFunc
=
Abc_Var2Lit
(
truthId
,
fCompl
);
// p->nCutMux += Lf_ManTtIsMux( t );
assert
(
(
int
)
pCutR
->
nLeaves
<=
nOldSupp
);
// Mf_ManTruthCanonicize( &t, pCutR->nLeaves );
return
(
int
)
pCutR
->
nLeaves
<
nOldSupp
;
}
static
inline
int
Lf_CutComputeTruth
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut0
,
Lf_Cut_t
*
pCut1
,
int
fCompl0
,
int
fCompl1
,
Lf_Cut_t
*
pCutR
,
int
fIsXor
)
{
if
(
p
->
pPars
->
nLutSize
<=
6
)
return
Lf_CutComputeTruth6
(
p
,
pCut0
,
pCut1
,
fCompl0
,
fCompl1
,
pCutR
,
fIsXor
);
{
word
uTruth
[
LF_TT_WORDS
],
uTruth0
[
LF_TT_WORDS
],
uTruth1
[
LF_TT_WORDS
];
int
nOldSupp
=
pCutR
->
nLeaves
,
truthId
;
int
LutSize
=
p
->
pPars
->
nLutSize
,
fCompl
;
int
nWords
=
Abc_Truth6WordNum
(
LutSize
);
word
*
pTruth0
=
Lf_CutTruth
(
p
,
pCut0
);
word
*
pTruth1
=
Lf_CutTruth
(
p
,
pCut1
);
Abc_TtCopy
(
uTruth0
,
pTruth0
,
nWords
,
Abc_LitIsCompl
(
pCut0
->
iFunc
)
^
fCompl0
);
Abc_TtCopy
(
uTruth1
,
pTruth1
,
nWords
,
Abc_LitIsCompl
(
pCut1
->
iFunc
)
^
fCompl1
);
Abc_TtExpand
(
uTruth0
,
LutSize
,
pCut0
->
pLeaves
,
pCut0
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
Abc_TtExpand
(
uTruth1
,
LutSize
,
pCut1
->
pLeaves
,
pCut1
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
if
(
fIsXor
)
Abc_TtXor
(
uTruth
,
uTruth0
,
uTruth1
,
nWords
,
(
fCompl
=
(
int
)((
uTruth0
[
0
]
^
uTruth1
[
0
])
&
1
))
);
else
Abc_TtAnd
(
uTruth
,
uTruth0
,
uTruth1
,
nWords
,
(
fCompl
=
(
int
)((
uTruth0
[
0
]
&
uTruth1
[
0
])
&
1
))
);
pCutR
->
nLeaves
=
Abc_TtMinBase
(
uTruth
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
,
LutSize
);
assert
(
(
uTruth
[
0
]
&
1
)
==
0
);
//Kit_DsdPrintFromTruth( uTruth, pCutR->nLeaves ), printf("\n" ), printf("\n" );
truthId
=
Vec_MemHashInsert
(
p
->
vTtMem
,
uTruth
);
pCutR
->
iFunc
=
Abc_Var2Lit
(
truthId
,
fCompl
);
assert
(
(
int
)
pCutR
->
nLeaves
<=
nOldSupp
);
return
(
int
)
pCutR
->
nLeaves
<
nOldSupp
;
}
}
static
inline
int
Lf_CutComputeTruthMux6
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut0
,
Lf_Cut_t
*
pCut1
,
Lf_Cut_t
*
pCutC
,
int
fCompl0
,
int
fCompl1
,
int
fComplC
,
Lf_Cut_t
*
pCutR
)
{
int
nOldSupp
=
pCutR
->
nLeaves
,
truthId
,
fCompl
;
word
t
;
word
t0
=
*
Lf_CutTruth
(
p
,
pCut0
);
word
t1
=
*
Lf_CutTruth
(
p
,
pCut1
);
word
tC
=
*
Lf_CutTruth
(
p
,
pCutC
);
if
(
Abc_LitIsCompl
(
pCut0
->
iFunc
)
^
fCompl0
)
t0
=
~
t0
;
if
(
Abc_LitIsCompl
(
pCut1
->
iFunc
)
^
fCompl1
)
t1
=
~
t1
;
if
(
Abc_LitIsCompl
(
pCutC
->
iFunc
)
^
fComplC
)
tC
=
~
tC
;
t0
=
Abc_Tt6Expand
(
t0
,
pCut0
->
pLeaves
,
pCut0
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
t1
=
Abc_Tt6Expand
(
t1
,
pCut1
->
pLeaves
,
pCut1
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
tC
=
Abc_Tt6Expand
(
tC
,
pCutC
->
pLeaves
,
pCutC
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
t
=
(
tC
&
t1
)
|
(
~
tC
&
t0
);
if
(
(
fCompl
=
(
int
)(
t
&
1
))
)
t
=
~
t
;
pCutR
->
nLeaves
=
Abc_Tt6MinBase
(
&
t
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
assert
(
(
int
)(
t
&
1
)
==
0
);
truthId
=
Vec_MemHashInsert
(
p
->
vTtMem
,
&
t
);
pCutR
->
iFunc
=
Abc_Var2Lit
(
truthId
,
fCompl
);
assert
(
(
int
)
pCutR
->
nLeaves
<=
nOldSupp
);
return
(
int
)
pCutR
->
nLeaves
<
nOldSupp
;
}
static
inline
int
Lf_CutComputeTruthMux
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut0
,
Lf_Cut_t
*
pCut1
,
Lf_Cut_t
*
pCutC
,
int
fCompl0
,
int
fCompl1
,
int
fComplC
,
Lf_Cut_t
*
pCutR
)
{
if
(
p
->
pPars
->
nLutSize
<=
6
)
return
Lf_CutComputeTruthMux6
(
p
,
pCut0
,
pCut1
,
pCutC
,
fCompl0
,
fCompl1
,
fComplC
,
pCutR
);
{
word
uTruth
[
LF_TT_WORDS
],
uTruth0
[
LF_TT_WORDS
],
uTruth1
[
LF_TT_WORDS
],
uTruthC
[
LF_TT_WORDS
];
int
nOldSupp
=
pCutR
->
nLeaves
,
truthId
;
int
LutSize
=
p
->
pPars
->
nLutSize
,
fCompl
;
int
nWords
=
Abc_Truth6WordNum
(
LutSize
);
word
*
pTruth0
=
Lf_CutTruth
(
p
,
pCut0
);
word
*
pTruth1
=
Lf_CutTruth
(
p
,
pCut1
);
word
*
pTruthC
=
Lf_CutTruth
(
p
,
pCutC
);
Abc_TtCopy
(
uTruth0
,
pTruth0
,
nWords
,
Abc_LitIsCompl
(
pCut0
->
iFunc
)
^
fCompl0
);
Abc_TtCopy
(
uTruth1
,
pTruth1
,
nWords
,
Abc_LitIsCompl
(
pCut1
->
iFunc
)
^
fCompl1
);
Abc_TtCopy
(
uTruthC
,
pTruthC
,
nWords
,
Abc_LitIsCompl
(
pCutC
->
iFunc
)
^
fComplC
);
Abc_TtExpand
(
uTruth0
,
LutSize
,
pCut0
->
pLeaves
,
pCut0
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
Abc_TtExpand
(
uTruth1
,
LutSize
,
pCut1
->
pLeaves
,
pCut1
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
Abc_TtExpand
(
uTruthC
,
LutSize
,
pCutC
->
pLeaves
,
pCutC
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
Abc_TtMux
(
uTruth
,
uTruthC
,
uTruth1
,
uTruth0
,
nWords
);
fCompl
=
(
int
)(
uTruth
[
0
]
&
1
);
if
(
fCompl
)
Abc_TtNot
(
uTruth
,
nWords
);
pCutR
->
nLeaves
=
Abc_TtMinBase
(
uTruth
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
,
LutSize
);
assert
(
(
uTruth
[
0
]
&
1
)
==
0
);
truthId
=
Vec_MemHashInsert
(
p
->
vTtMem
,
uTruth
);
pCutR
->
iFunc
=
Abc_Var2Lit
(
truthId
,
fCompl
);
assert
(
(
int
)
pCutR
->
nLeaves
<=
nOldSupp
);
return
(
int
)
pCutR
->
nLeaves
<
nOldSupp
;
}
}
/**Function*************************************************************
Synopsis [Exact local area.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float
Lf_CutRef_rec
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut
)
{
word
CutTemp
[
LF_CUT_WORDS
]
=
{
0
};
float
Count
=
Lf_CutArea
(
p
,
pCut
);
int
i
,
Var
;
Lf_CutForEachVar
(
pCut
,
Var
,
i
)
if
(
!
Lf_ObjMapRefInc
(
p
,
Var
)
)
Count
+=
Lf_CutRef_rec
(
p
,
Lf_ObjCutBestNew
(
p
,
Var
,
(
Lf_Cut_t
*
)
CutTemp
)
);
return
Count
;
}
float
Lf_CutDeref_rec
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut
)
{
word
CutTemp
[
LF_CUT_WORDS
]
=
{
0
};
float
Count
=
Lf_CutArea
(
p
,
pCut
);
int
i
,
Var
;
Lf_CutForEachVar
(
pCut
,
Var
,
i
)
if
(
!
Lf_ObjMapRefDec
(
p
,
Var
)
)
Count
+=
Lf_CutDeref_rec
(
p
,
Lf_ObjCutBestNew
(
p
,
Var
,
(
Lf_Cut_t
*
)
CutTemp
)
);
return
Count
;
}
static
inline
float
Lf_CutAreaDerefed
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut
)
{
float
Ela1
=
Lf_CutRef_rec
(
p
,
pCut
);
Lf_CutDeref_rec
(
p
,
pCut
);
// float Ela2 = Lf_CutDeref_rec( p, pCut );
// assert( Ela1 == Ela2 );
return
Ela1
;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Lf_CutRequired
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut
)
{
int
i
,
Arr
,
Req
,
Arrival
=
0
,
Required
=
0
;
for
(
i
=
0
;
i
<
(
int
)
pCut
->
nLeaves
;
i
++
)
{
if
(
Lf_ObjOff
(
p
,
pCut
->
pLeaves
[
i
])
<
0
)
// Arr = Lf_ObjCiArrival( p, Gia_ObjCioId(Gia_ManObj(p->pGia, pCut->pLeaves[i])) );
Arr
=
Lf_ObjArrival_rec
(
p
,
Gia_ManObj
(
p
->
pGia
,
pCut
->
pLeaves
[
i
])
);
else
Arr
=
Lf_ObjReadBest
(
p
,
pCut
->
pLeaves
[
i
])
->
Delay
[
0
];
Arrival
=
Abc_MaxInt
(
Arrival
,
Arr
);
Req
=
Lf_ObjRequired
(
p
,
pCut
->
pLeaves
[
i
]);
if
(
Req
<
ABC_INFINITY
)
Required
=
Abc_MaxInt
(
Required
,
Req
);
}
return
Abc_MaxInt
(
Required
+
2
,
Arrival
+
1
);
}
static
inline
void
Lf_CutParams
(
Lf_Man_t
*
p
,
Lf_Cut_t
*
pCut
,
int
Required
,
float
FlowRefs
,
Gia_Obj_t
*
pMux
)
{
Lf_Bst_t
*
pBest
;
int
i
,
Index
,
Delay
;
assert
(
!
pCut
->
fMux7
||
Gia_ObjIsMux
(
p
->
pGia
,
pMux
)
);
pCut
->
fLate
=
0
;
pCut
->
Delay
=
0
;
pCut
->
Flow
=
0
;
assert
(
pCut
->
nLeaves
<
LF_NO_LEAF
);
for
(
i
=
0
;
i
<
(
int
)
pCut
->
nLeaves
;
i
++
)
{
if
(
Lf_ObjOff
(
p
,
pCut
->
pLeaves
[
i
])
<
0
)
// Delay = Lf_ObjCiArrival( p, Gia_ObjCioId(Gia_ManObj(p->pGia, pCut->pLeaves[i])) );
Delay
=
Lf_ObjArrival_rec
(
p
,
Gia_ManObj
(
p
->
pGia
,
pCut
->
pLeaves
[
i
])
);
else
{
pBest
=
Lf_ObjReadBest
(
p
,
pCut
->
pLeaves
[
i
]);
assert
(
pBest
->
Delay
[
0
]
<=
pBest
->
Delay
[
1
]
);
assert
(
pBest
->
Flow
[
0
]
>=
pBest
->
Flow
[
1
]
);
if
(
p
->
fUseEla
)
Index
=
Lf_BestIndex
(
pBest
);
else
{
Index
=
(
int
)(
pBest
->
Delay
[
1
]
+
1
<=
Required
&&
Required
!=
ABC_INFINITY
);
pCut
->
Flow
+=
pBest
->
Flow
[
Index
];
}
Delay
=
pBest
->
Delay
[
Index
];
}
// if ( pCut->fMux7 && pCut->pLeaves[i] == Gia_ObjFaninId2p(p->pGia, pMux) )
// Delay += 1;
pCut
->
Delay
=
Abc_MaxInt
(
pCut
->
Delay
,
Delay
);
}
pCut
->
Delay
+=
(
int
)(
pCut
->
nLeaves
>
1
);
// && !pCut->fMux7;
if
(
pCut
->
Delay
>
Required
)
pCut
->
fLate
=
1
;
if
(
p
->
fUseEla
)
pCut
->
Flow
=
Lf_CutAreaDerefed
(
p
,
pCut
)
/
FlowRefs
;
else
pCut
->
Flow
=
(
pCut
->
Flow
+
Lf_CutArea
(
p
,
pCut
))
/
FlowRefs
;
}
void
Lf_ObjMergeOrder
(
Lf_Man_t
*
p
,
int
iObj
)
{
word
CutSet
[
LF_CUT_MAX
][
LF_CUT_WORDS
]
=
{{
0
}};
Lf_Cut_t
*
pCutSet0
,
*
pCutSet1
,
*
pCutSet2
,
*
pCut0
,
*
pCut1
,
*
pCut2
;
Lf_Cut_t
*
pCutSet
=
(
Lf_Cut_t
*
)
CutSet
,
*
pCutsR
[
LF_CUT_MAX
];
Gia_Obj_t
*
pObj
=
Gia_ManObj
(
p
->
pGia
,
iObj
);
Lf_Bst_t
*
pBest
=
Lf_ObjReadBest
(
p
,
iObj
);
float
FlowRefs
=
Lf_ObjFlowRefs
(
p
,
iObj
);
int
Required
=
Lf_ObjRequired
(
p
,
iObj
);
int
nLutSize
=
p
->
pPars
->
nLutSize
;
int
nCutNum
=
p
->
pPars
->
nCutNum
;
int
nCutWords
=
p
->
nCutWords
;
int
fComp0
=
Gia_ObjFaninC0
(
pObj
);
int
fComp1
=
Gia_ObjFaninC1
(
pObj
);
int
nCuts0
=
Lf_ManPrepareSet
(
p
,
Gia_ObjFaninId0
(
pObj
,
iObj
),
0
,
&
pCutSet0
);
int
nCuts1
=
Lf_ManPrepareSet
(
p
,
Gia_ObjFaninId1
(
pObj
,
iObj
),
1
,
&
pCutSet1
);
int
iSibl
=
Gia_ObjSibl
(
p
->
pGia
,
iObj
);
int
i
,
k
,
n
,
iCutUsed
,
nCutsR
=
0
;
float
Value1
=
-
1
,
Value2
=
-
1
;
assert
(
!
Gia_ObjIsBuf
(
pObj
)
);
Lf_CutSetForEachCut
(
nCutWords
,
pCutSet
,
pCut0
,
i
,
nCutNum
)
pCutsR
[
i
]
=
pCut0
;
if
(
p
->
Iter
)
{
assert
(
nCutsR
==
0
);
// load cuts
Lf_MemLoadCut
(
&
p
->
vStoreOld
,
pBest
->
Cut
[
0
].
Handle
,
iObj
,
pCutsR
[
0
],
p
->
pPars
->
fCutMin
,
1
);
if
(
Lf_BestDiffCuts
(
pBest
)
)
Lf_MemLoadCut
(
&
p
->
vStoreOld
,
pBest
->
Cut
[
1
].
Handle
,
iObj
,
pCutsR
[
1
],
p
->
pPars
->
fCutMin
,
1
);
// deref the cut
if
(
p
->
fUseEla
&&
Lf_ObjMapRefNum
(
p
,
iObj
)
>
0
)
Value1
=
Lf_CutDeref_rec
(
p
,
pCutsR
[
Lf_BestIndex
(
pBest
)]
);
// update required times
if
(
Required
==
ABC_INFINITY
)
//&& !p->fUseEla )
Required
=
Lf_CutRequired
(
p
,
pCutsR
[
0
]
);
// compute parameters
Lf_CutParams
(
p
,
pCutsR
[
nCutsR
++
],
Required
,
FlowRefs
,
pObj
);
if
(
Lf_BestDiffCuts
(
pBest
)
)
{
assert
(
nCutsR
==
1
);
Lf_CutParams
(
p
,
pCutsR
[
nCutsR
],
Required
,
FlowRefs
,
pObj
);
nCutsR
=
Lf_SetAddCut
(
pCutsR
,
nCutsR
,
nCutNum
);
}
if
(
pCutsR
[
0
]
->
fLate
)
p
->
nTimeFails
++
;
}
if
(
iSibl
)
{
Gia_Obj_t
*
pObjE
=
Gia_ObjSiblObj
(
p
->
pGia
,
iObj
);
int
fCompE
=
Gia_ObjPhase
(
pObj
)
^
Gia_ObjPhase
(
pObjE
);
int
nCutsE
=
Lf_ManPrepareSet
(
p
,
iSibl
,
2
,
&
pCutSet2
);
Lf_CutSetForEachCut
(
nCutWords
,
pCutSet2
,
pCut2
,
n
,
nCutsE
)
{
if
(
pCut2
->
pLeaves
[
0
]
==
iSibl
)
continue
;
Lf_CutCopy
(
pCutsR
[
nCutsR
],
pCut2
,
nCutWords
);
if
(
pCutsR
[
nCutsR
]
->
iFunc
>=
0
)
pCutsR
[
nCutsR
]
->
iFunc
=
Abc_LitNotCond
(
pCutsR
[
nCutsR
]
->
iFunc
,
fCompE
);
Lf_CutParams
(
p
,
pCutsR
[
nCutsR
],
Required
,
FlowRefs
,
pObj
);
nCutsR
=
Lf_SetAddCut
(
pCutsR
,
nCutsR
,
nCutNum
);
}
}
if
(
Gia_ObjIsMuxId
(
p
->
pGia
,
iObj
)
)
{
int
fComp2
=
Gia_ObjFaninC2
(
p
->
pGia
,
pObj
);
int
nCuts2
=
Lf_ManPrepareSet
(
p
,
Gia_ObjFaninId2
(
p
->
pGia
,
iObj
),
2
,
&
pCutSet2
);
p
->
CutCount
[
0
]
+=
nCuts0
*
nCuts1
*
nCuts2
;
Lf_CutSetForEachCut
(
nCutWords
,
pCutSet0
,
pCut0
,
i
,
nCuts0
)
Lf_CutSetForEachCut
(
nCutWords
,
pCutSet1
,
pCut1
,
k
,
nCuts1
)
Lf_CutSetForEachCut
(
nCutWords
,
pCutSet2
,
pCut2
,
n
,
nCuts2
)
{
if
(
Lf_CutCountBits
(
pCut0
->
Sign
|
pCut1
->
Sign
|
pCut2
->
Sign
)
>
nLutSize
)
continue
;
p
->
CutCount
[
1
]
++
;
if
(
!
Lf_CutMergeOrderMux
(
pCut0
,
pCut1
,
pCut2
,
pCutsR
[
nCutsR
],
nLutSize
)
)
continue
;
if
(
Lf_SetLastCutIsContained
(
pCutsR
,
nCutsR
)
)
continue
;
p
->
CutCount
[
2
]
++
;
if
(
p
->
pPars
->
fCutMin
&&
Lf_CutComputeTruthMux
(
p
,
pCut0
,
pCut1
,
pCut2
,
fComp0
,
fComp1
,
fComp2
,
pCutsR
[
nCutsR
])
)
pCutsR
[
nCutsR
]
->
Sign
=
Lf_CutGetSign
(
pCutsR
[
nCutsR
]);
if
(
p
->
pPars
->
nLutSizeMux
&&
p
->
pPars
->
nLutSizeMux
==
(
int
)
pCutsR
[
nCutsR
]
->
nLeaves
&&
Lf_ManFindCofVar
(
Lf_CutTruth
(
p
,
pCutsR
[
nCutsR
]),
Abc_Truth6WordNum
(
nLutSize
),
pCutsR
[
nCutsR
]
->
nLeaves
)
==
-
1
)
continue
;
Lf_CutParams
(
p
,
pCutsR
[
nCutsR
],
Required
,
FlowRefs
,
pObj
);
nCutsR
=
Lf_SetAddCut
(
pCutsR
,
nCutsR
,
nCutNum
);
}
}
else
{
int
fIsXor
=
Gia_ObjIsXor
(
pObj
);
p
->
CutCount
[
0
]
+=
nCuts0
*
nCuts1
;
Lf_CutSetForEachCut
(
nCutWords
,
pCutSet0
,
pCut0
,
i
,
nCuts0
)
Lf_CutSetForEachCut
(
nCutWords
,
pCutSet1
,
pCut1
,
k
,
nCuts1
)
{
if
(
(
int
)(
pCut0
->
nLeaves
+
pCut1
->
nLeaves
)
>
nLutSize
&&
Lf_CutCountBits
(
pCut0
->
Sign
|
pCut1
->
Sign
)
>
nLutSize
)
continue
;
p
->
CutCount
[
1
]
++
;
if
(
!
Lf_CutMergeOrder
(
pCut0
,
pCut1
,
pCutsR
[
nCutsR
],
nLutSize
)
)
continue
;
if
(
Lf_SetLastCutIsContained
(
pCutsR
,
nCutsR
)
)
continue
;
p
->
CutCount
[
2
]
++
;
if
(
p
->
pPars
->
fCutMin
&&
Lf_CutComputeTruth
(
p
,
pCut0
,
pCut1
,
fComp0
,
fComp1
,
pCutsR
[
nCutsR
],
fIsXor
)
)
pCutsR
[
nCutsR
]
->
Sign
=
Lf_CutGetSign
(
pCutsR
[
nCutsR
]);
if
(
p
->
pPars
->
nLutSizeMux
&&
p
->
pPars
->
nLutSizeMux
==
(
int
)
pCutsR
[
nCutsR
]
->
nLeaves
&&
Lf_ManFindCofVar
(
Lf_CutTruth
(
p
,
pCutsR
[
nCutsR
]),
Abc_Truth6WordNum
(
nLutSize
),
pCutsR
[
nCutsR
]
->
nLeaves
)
==
-
1
)
continue
;
Lf_CutParams
(
p
,
pCutsR
[
nCutsR
],
Required
,
FlowRefs
,
pObj
);
nCutsR
=
Lf_SetAddCut
(
pCutsR
,
nCutsR
,
nCutNum
);
}
}
// debug printout
if
(
0
)
{
printf
(
"*** Obj = %d FlowRefs = %.2f MapRefs = %2d Required = %2d
\n
"
,
iObj
,
FlowRefs
,
Lf_ObjMapRefNum
(
p
,
iObj
),
Required
);
for
(
i
=
0
;
i
<
nCutsR
;
i
++
)
Lf_CutPrint
(
p
,
pCutsR
[
i
]
);
printf
(
"
\n
"
);
}
// verify
assert
(
nCutsR
>
0
&&
nCutsR
<
nCutNum
);
// assert( Lf_SetCheckArray(pCutsR, nCutsR) );
// delay cut
assert
(
nCutsR
==
1
||
pCutsR
[
0
]
->
Delay
<=
pCutsR
[
1
]
->
Delay
);
pBest
->
Cut
[
0
].
fUsed
=
pBest
->
Cut
[
1
].
fUsed
=
0
;
pBest
->
Cut
[
0
].
Handle
=
pBest
->
Cut
[
1
].
Handle
=
Lf_MemSaveCut
(
&
p
->
vStoreNew
,
pCutsR
[
0
],
iObj
);
pBest
->
Delay
[
0
]
=
pBest
->
Delay
[
1
]
=
pCutsR
[
0
]
->
Delay
;
pBest
->
Flow
[
0
]
=
pBest
->
Flow
[
1
]
=
pCutsR
[
0
]
->
Flow
;
p
->
nCutCounts
[
pCutsR
[
0
]
->
nLeaves
]
++
;
p
->
CutCount
[
3
]
+=
nCutsR
;
p
->
nCutEqual
++
;
// area cut
iCutUsed
=
0
;
if
(
nCutsR
>
1
&&
pCutsR
[
0
]
->
Flow
>
pCutsR
[
1
]
->
Flow
)
//&& !pCutsR[1]->fLate ) // can remove !fLate
{
pBest
->
Cut
[
1
].
Handle
=
Lf_MemSaveCut
(
&
p
->
vStoreNew
,
pCutsR
[
1
],
iObj
);
pBest
->
Delay
[
1
]
=
pCutsR
[
1
]
->
Delay
;
pBest
->
Flow
[
1
]
=
pCutsR
[
1
]
->
Flow
;
p
->
nCutCounts
[
pCutsR
[
1
]
->
nLeaves
]
++
;
p
->
nCutEqual
--
;
if
(
!
pCutsR
[
1
]
->
fLate
)
iCutUsed
=
1
;
}
// mux cut
if
(
p
->
pPars
->
fUseMux7
&&
Gia_ObjIsMuxId
(
p
->
pGia
,
iObj
)
)
{
pCut2
=
Lf_ObjCutMux
(
p
,
iObj
);
Lf_CutParams
(
p
,
pCut2
,
Required
,
FlowRefs
,
pObj
);
pBest
->
Delay
[
2
]
=
pCut2
->
Delay
;
pBest
->
Flow
[
2
]
=
pCut2
->
Flow
;
// update area value of the best area cut
// if ( !pCut2->fLate )
// pBest->Flow[1] = Abc_MinFloat( pBest->Flow[1], pBest->Flow[2] );
}
// reference resulting cut
if
(
p
->
fUseEla
)
{
pBest
->
Cut
[
iCutUsed
].
fUsed
=
1
;
if
(
Lf_ObjMapRefNum
(
p
,
iObj
)
>
0
)
Value2
=
Lf_CutRef_rec
(
p
,
pCutsR
[
iCutUsed
]
);
// if ( Value1 < Value2 )
// printf( "ELA degradated cost at node %d from %d to %d.\n", iObj, Value1, Value2 ), fflush(stdout);
// assert( Value1 >= Value2 );
// if ( Value1 != -1 )
// printf( "%.2f -> %.2f ", Value1, Value2 );
}
if
(
pObj
->
Value
==
0
)
return
;
// store the cutset
pCutSet
=
Lf_ManFetchSet
(
p
,
iObj
);
Lf_CutSetForEachCut
(
nCutWords
,
pCutSet
,
pCut0
,
i
,
nCutNum
)
{
assert
(
!
pCut0
->
fMux7
);
if
(
i
<
nCutsR
)
Lf_CutCopy
(
pCut0
,
pCutsR
[
i
],
nCutWords
);
else
if
(
i
==
nCutsR
&&
pCutsR
[
0
]
->
nLeaves
>
1
&&
(
nCutsR
==
1
||
pCutsR
[
1
]
->
nLeaves
>
1
)
)
Lf_CutCreateUnit
(
pCut0
,
iObj
);
else
pCut0
->
nLeaves
=
LF_NO_LEAF
;
}
}
/**Function*************************************************************
Synopsis [Computing delay/area.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
void
Lf_ManSetFlowRefInc
(
Gia_Man_t
*
p
,
Vec_Flt_t
*
vRefs
,
Vec_Int_t
*
vOffsets
,
int
i
)
{
if
(
Gia_ObjIsAndNotBuf
(
Gia_ManObj
(
p
,
i
))
)
Vec_FltAddToEntry
(
vRefs
,
Vec_IntEntry
(
vOffsets
,
i
),
1
);
}
void
Lf_ManSetFlowRefs
(
Gia_Man_t
*
p
,
Vec_Flt_t
*
vRefs
,
Vec_Int_t
*
vOffsets
)
{
int
fDiscount
=
1
;
Gia_Obj_t
*
pObj
,
*
pCtrl
,
*
pData0
,
*
pData1
;
int
i
,
Id
;
Vec_FltFill
(
vRefs
,
Gia_ManAndNotBufNum
(
p
),
0
);
Gia_ManForEachAnd
(
p
,
pObj
,
i
)
{
if
(
Gia_ObjIsAndNotBuf
(
Gia_ObjFanin0
(
pObj
))
)
Vec_FltAddToEntry
(
vRefs
,
Vec_IntEntry
(
vOffsets
,
Gia_ObjFaninId0
(
pObj
,
i
)),
1
);
if
(
Gia_ObjIsBuf
(
pObj
)
)
continue
;
if
(
Gia_ObjIsAndNotBuf
(
Gia_ObjFanin1
(
pObj
))
)
Vec_FltAddToEntry
(
vRefs
,
Vec_IntEntry
(
vOffsets
,
Gia_ObjFaninId1
(
pObj
,
i
)),
1
);
if
(
p
->
pMuxes
)
{
if
(
Gia_ObjIsMuxId
(
p
,
i
)
&&
Gia_ObjIsAndNotBuf
(
Gia_ObjFanin2
(
p
,
pObj
))
)
Vec_FltAddToEntry
(
vRefs
,
Vec_IntEntry
(
vOffsets
,
Gia_ObjFaninId2
(
p
,
i
)),
1
);
}
else
if
(
fDiscount
&&
Gia_ObjIsMuxType
(
pObj
)
)
// discount XOR/MUX
{
pCtrl
=
Gia_Regular
(
Gia_ObjRecognizeMux
(
pObj
,
&
pData1
,
&
pData0
));
pData0
=
Gia_Regular
(
pData0
);
pData1
=
Gia_Regular
(
pData1
);
if
(
Gia_ObjIsAndNotBuf
(
pCtrl
)
)
Vec_FltAddToEntry
(
vRefs
,
Vec_IntEntry
(
vOffsets
,
Gia_ObjId
(
p
,
pCtrl
)),
-
1
);
if
(
pData0
==
pData1
&&
Gia_ObjIsAndNotBuf
(
pData0
)
)
Vec_FltAddToEntry
(
vRefs
,
Vec_IntEntry
(
vOffsets
,
Gia_ObjId
(
p
,
pData0
)),
-
1
);
}
}
Gia_ManForEachCoDriverId
(
p
,
Id
,
i
)
if
(
Gia_ObjIsAndNotBuf
(
Gia_ManObj
(
p
,
Id
))
)
Vec_FltAddToEntry
(
vRefs
,
Vec_IntEntry
(
vOffsets
,
Id
),
1
);
for
(
i
=
0
;
i
<
Vec_FltSize
(
vRefs
);
i
++
)
Vec_FltUpdateEntry
(
vRefs
,
i
,
1
);
}
void
Lf_ManSetCutRefs
(
Lf_Man_t
*
p
)
{
Gia_Obj_t
*
pObj
;
int
i
;
if
(
Vec_PtrSize
(
&
p
->
vMemSets
)
*
(
1
<<
LF_LOG_PAGE
)
!=
Vec_IntSize
(
&
p
->
vFreeSets
)
)
printf
(
"The number of used cutsets = %d.
\n
"
,
Vec_PtrSize
(
&
p
->
vMemSets
)
*
(
1
<<
LF_LOG_PAGE
)
-
Vec_IntSize
(
&
p
->
vFreeSets
)
);
Gia_ManForEachAnd
(
p
->
pGia
,
pObj
,
i
)
{
assert
(
pObj
->
Value
==
0
);
if
(
Gia_ObjIsBuf
(
pObj
)
)
continue
;
if
(
Gia_ObjIsAndNotBuf
(
Gia_ObjFanin0
(
pObj
))
)
Gia_ObjFanin0
(
pObj
)
->
Value
++
;
if
(
Gia_ObjIsAndNotBuf
(
Gia_ObjFanin1
(
pObj
))
)
Gia_ObjFanin1
(
pObj
)
->
Value
++
;
if
(
Gia_ObjIsMuxId
(
p
->
pGia
,
i
)
&&
Gia_ObjIsAndNotBuf
(
Gia_ObjFanin2
(
p
->
pGia
,
pObj
))
)
Gia_ObjFanin2
(
p
->
pGia
,
pObj
)
->
Value
++
;
if
(
Gia_ObjSibl
(
p
->
pGia
,
i
)
&&
Gia_ObjIsAndNotBuf
(
Gia_ObjSiblObj
(
p
->
pGia
,
i
))
)
Gia_ObjSiblObj
(
p
->
pGia
,
i
)
->
Value
++
;
}
}
static
inline
int
Lf_ManSetMuxCut
(
Lf_Man_t
*
p
,
Lf_Bst_t
*
pBest
,
int
iObj
,
int
Required
)
{
Gia_Obj_t
*
pMux
;
if
(
!
Gia_ObjIsMuxId
(
p
->
pGia
,
iObj
)
)
return
0
;
if
(
pBest
->
Delay
[
2
]
>
Required
)
return
0
;
if
(
pBest
->
Flow
[
2
]
>
1
.
1
*
pBest
->
Flow
[
1
]
)
return
0
;
pMux
=
Gia_ManObj
(
p
->
pGia
,
iObj
);
if
(
pMux
->
fMark0
||
Gia_ObjFanin0
(
pMux
)
->
fMark0
||
Gia_ObjFanin1
(
pMux
)
->
fMark0
)
return
0
;
Gia_ObjFanin0
(
pMux
)
->
fMark0
=
1
;
Gia_ObjFanin1
(
pMux
)
->
fMark0
=
1
;
return
1
;
}
void
Lf_ManSetMapRefsOne
(
Lf_Man_t
*
p
,
int
iObj
)
{
Lf_Cut_t
*
pCut
;
Lf_Bst_t
*
pBest
=
Lf_ObjReadBest
(
p
,
iObj
);
int
k
,
Index
,
Required
=
Lf_ObjRequired
(
p
,
iObj
);
assert
(
Lf_ObjMapRefNum
(
p
,
iObj
)
>
0
);
assert
(
!
pBest
->
Cut
[
0
].
fUsed
&&
!
pBest
->
Cut
[
1
].
fUsed
);
if
(
!
p
->
pPars
->
fUseMux7
||
!
Lf_ManSetMuxCut
(
p
,
pBest
,
iObj
,
Required
)
)
{
Index
=
(
int
)(
Lf_BestDiffCuts
(
pBest
)
&&
pBest
->
Delay
[
1
]
<=
Required
);
pBest
->
Cut
[
Index
].
fUsed
=
1
;
}
pCut
=
Lf_ObjCutBest
(
p
,
iObj
);
assert
(
!
pCut
->
fMux7
||
pCut
->
nLeaves
==
3
);
// assert( pCut->Delay <= Required );
for
(
k
=
0
;
k
<
(
int
)
pCut
->
nLeaves
;
k
++
)
{
// if ( pCut->fMux7 && pCut->pLeaves[k] != Gia_ObjFaninId2(p->pGia, iObj) )
// Lf_ObjSetRequired( p, pCut->pLeaves[k], Required );
// else
Lf_ObjSetRequired
(
p
,
pCut
->
pLeaves
[
k
],
Required
-
1
);
if
(
Gia_ObjIsAndNotBuf
(
Gia_ManObj
(
p
->
pGia
,
pCut
->
pLeaves
[
k
]))
)
Lf_ObjMapRefInc
(
p
,
pCut
->
pLeaves
[
k
]
);
}
if
(
pCut
->
fMux7
)
{
p
->
pPars
->
Mux7
++
;
p
->
pPars
->
Edge
++
;
return
;
}
if
(
Vec_FltSize
(
&
p
->
vSwitches
)
)
p
->
Switches
+=
Lf_CutSwitches
(
p
,
pCut
);
p
->
pPars
->
Edge
+=
pCut
->
nLeaves
;
p
->
pPars
->
Area
++
;
}
int
Lf_ManSetMapRefs
(
Lf_Man_t
*
p
)
{
float
Coef
=
1
.
0
/
(
1
.
0
+
(
p
->
Iter
+
1
)
*
(
p
->
Iter
+
1
));
float
*
pFlowRefs
;
int
*
pMapRefs
,
i
;
Gia_Obj_t
*
pObj
;
// compute delay
int
Delay
=
0
;
for
(
i
=
0
;
i
<
Gia_ManCoNum
(
p
->
pGia
);
i
++
)
Delay
=
Abc_MaxInt
(
Delay
,
Lf_ObjCoArrival
(
p
,
i
)
);
// check delay target
if
(
p
->
pPars
->
DelayTarget
==
-
1
&&
p
->
pPars
->
nRelaxRatio
)
p
->
pPars
->
DelayTarget
=
(
int
)((
float
)
Delay
*
(
100
.
0
+
p
->
pPars
->
nRelaxRatio
)
/
100
.
0
);
if
(
p
->
pPars
->
DelayTarget
!=
-
1
)
{
if
(
Delay
<
p
->
pPars
->
DelayTarget
+
0
.
01
)
Delay
=
p
->
pPars
->
DelayTarget
;
else
if
(
p
->
pPars
->
nRelaxRatio
==
0
)
Abc_Print
(
0
,
"Relaxing user-specified delay target from %d to %d.
\n
"
,
p
->
pPars
->
DelayTarget
,
Delay
);
}
p
->
pPars
->
Delay
=
Delay
;
// compute area/edges/required
p
->
pPars
->
Mux7
=
p
->
pPars
->
Area
=
p
->
pPars
->
Edge
=
p
->
Switches
=
0
;
Vec_IntFill
(
&
p
->
vMapRefs
,
Gia_ManAndNotBufNum
(
p
->
pGia
),
0
);
Vec_IntFill
(
&
p
->
vRequired
,
Gia_ManObjNum
(
p
->
pGia
),
ABC_INFINITY
);
if
(
p
->
pPars
->
fUseMux7
)
{
Gia_ManCleanMark0
(
p
->
pGia
);
Gia_ManForEachCi
(
p
->
pGia
,
pObj
,
i
)
pObj
->
fMark0
=
1
;
}
if
(
p
->
pGia
->
pManTime
!=
NULL
)
{
assert
(
Gia_ManBufNum
(
p
->
pGia
)
);
Tim_ManIncrementTravId
(
p
->
pGia
->
pManTime
);
if
(
p
->
pPars
->
fDoAverage
)
for
(
i
=
0
;
i
<
Gia_ManCoNum
(
p
->
pGia
);
i
++
)
Tim_ManSetCoRequired
(
p
->
pGia
->
pManTime
,
i
,
(
int
)(
Lf_ObjCoArrival
(
p
,
i
)
*
(
100
.
0
+
p
->
pPars
->
nRelaxRatio
)
/
100
.
0
)
);
else
Tim_ManInitPoRequiredAll
(
p
->
pGia
->
pManTime
,
Delay
);
Gia_ManForEachObjReverse1
(
p
->
pGia
,
pObj
,
i
)
{
if
(
Gia_ObjIsBuf
(
pObj
)
)
Lf_ObjSetRequired
(
p
,
Gia_ObjFaninId0
(
pObj
,
i
),
Lf_ObjRequired
(
p
,
i
)
);
else
if
(
Gia_ObjIsAnd
(
pObj
)
)
{
if
(
Lf_ObjMapRefNum
(
p
,
i
)
)
Lf_ManSetMapRefsOne
(
p
,
i
);
}
else
if
(
Gia_ObjIsCi
(
pObj
)
)
Tim_ManSetCiRequired
(
p
->
pGia
->
pManTime
,
Gia_ObjCioId
(
pObj
),
Lf_ObjRequired
(
p
,
i
)
);
else
if
(
Gia_ObjIsCo
(
pObj
)
)
{
int
iDriverId
=
Gia_ObjFaninId0
(
pObj
,
i
);
int
reqTime
=
Tim_ManGetCoRequired
(
p
->
pGia
->
pManTime
,
Gia_ObjCioId
(
pObj
)
);
Lf_ObjSetRequired
(
p
,
iDriverId
,
reqTime
);
if
(
Gia_ObjIsAndNotBuf
(
Gia_ObjFanin0
(
pObj
))
)
Lf_ObjMapRefInc
(
p
,
iDriverId
);
}
else
assert
(
0
);
}
}
else
{
Gia_ManForEachCo
(
p
->
pGia
,
pObj
,
i
)
{
int
iDriverId
=
Gia_ObjFaninId0p
(
p
->
pGia
,
pObj
);
int
reqTime
=
p
->
pPars
->
fDoAverage
?
(
int
)(
Lf_ObjCoArrival
(
p
,
i
)
*
(
100
.
0
+
p
->
pPars
->
nRelaxRatio
)
/
100
.
0
)
:
Delay
;
Lf_ObjSetRequired
(
p
,
iDriverId
,
reqTime
);
if
(
Gia_ObjIsAndNotBuf
(
Gia_ObjFanin0
(
pObj
))
)
Lf_ObjMapRefInc
(
p
,
iDriverId
);
}
Gia_ManForEachAndReverse
(
p
->
pGia
,
pObj
,
i
)
{
if
(
Gia_ObjIsBuf
(
pObj
)
)
{
Lf_ObjSetRequired
(
p
,
Gia_ObjFaninId0
(
pObj
,
i
),
Lf_ObjRequired
(
p
,
i
)
);
if
(
Gia_ObjIsAndNotBuf
(
Gia_ObjFanin0
(
pObj
))
)
Lf_ObjMapRefInc
(
p
,
Gia_ObjFaninId0
(
pObj
,
i
)
);
}
else
if
(
Lf_ObjMapRefNum
(
p
,
i
)
)
Lf_ManSetMapRefsOne
(
p
,
i
);
}
}
if
(
p
->
pPars
->
fUseMux7
)
Gia_ManCleanMark0
(
p
->
pGia
);
// blend references
assert
(
Vec_IntSize
(
&
p
->
vMapRefs
)
==
Gia_ManAndNotBufNum
(
p
->
pGia
)
);
assert
(
Vec_FltSize
(
&
p
->
vFlowRefs
)
==
Gia_ManAndNotBufNum
(
p
->
pGia
)
);
pMapRefs
=
Vec_IntArray
(
&
p
->
vMapRefs
);
pFlowRefs
=
Vec_FltArray
(
&
p
->
vFlowRefs
);
for
(
i
=
0
;
i
<
Vec_IntSize
(
&
p
->
vMapRefs
);
i
++
)
pFlowRefs
[
i
]
=
Coef
*
pFlowRefs
[
i
]
+
(
1
.
0
-
Coef
)
*
Abc_MaxFloat
(
1
,
pMapRefs
[
i
]);
// pFlowRefs[i] = 0.2 * pFlowRefs[i] + 0.8 * Abc_MaxFloat(1, pMapRefs[i]);
return
p
->
pPars
->
Area
;
}
void
Lf_ManCountMapRefsOne
(
Lf_Man_t
*
p
,
int
iObj
)
{
Lf_Bst_t
*
pBest
=
Lf_ObjReadBest
(
p
,
iObj
);
Lf_Cut_t
*
pCut
=
Lf_ObjCutBest
(
p
,
iObj
);
int
k
,
Required
=
Lf_ObjRequired
(
p
,
iObj
);
assert
(
Lf_ObjMapRefNum
(
p
,
iObj
)
>
0
);
assert
(
Lf_BestIsMapped
(
pBest
)
);
assert
(
!
pCut
->
fMux7
);
// assert( pCut->Delay <= Required );
for
(
k
=
0
;
k
<
(
int
)
pCut
->
nLeaves
;
k
++
)
Lf_ObjSetRequired
(
p
,
pCut
->
pLeaves
[
k
],
Required
-
1
);
if
(
Vec_FltSize
(
&
p
->
vSwitches
)
)
p
->
Switches
+=
Lf_CutSwitches
(
p
,
pCut
);
p
->
pPars
->
Edge
+=
pCut
->
nLeaves
;
p
->
pPars
->
Area
++
;
}
void
Lf_ManCountMapRefs
(
Lf_Man_t
*
p
)
{
// compute delay
Gia_Obj_t
*
pObj
;
int
i
,
Id
,
Delay
=
0
;
for
(
i
=
0
;
i
<
Gia_ManCoNum
(
p
->
pGia
);
i
++
)
Delay
=
Abc_MaxInt
(
Delay
,
Lf_ObjCoArrival2
(
p
,
i
)
);
// check delay target
if
(
p
->
pPars
->
DelayTarget
==
-
1
&&
p
->
pPars
->
nRelaxRatio
)
p
->
pPars
->
DelayTarget
=
(
int
)((
float
)
Delay
*
(
100
.
0
+
p
->
pPars
->
nRelaxRatio
)
/
100
.
0
);
if
(
p
->
pPars
->
DelayTarget
!=
-
1
)
{
if
(
Delay
<
p
->
pPars
->
DelayTarget
+
0
.
01
)
Delay
=
p
->
pPars
->
DelayTarget
;
else
if
(
p
->
pPars
->
nRelaxRatio
==
0
)
Abc_Print
(
0
,
"Relaxing user-specified delay target from %d to %d.
\n
"
,
p
->
pPars
->
DelayTarget
,
Delay
);
}
p
->
pPars
->
Delay
=
Delay
;
// compute area/edges/required
p
->
pPars
->
Mux7
=
p
->
pPars
->
Area
=
p
->
pPars
->
Edge
=
p
->
Switches
=
0
;
Vec_IntFill
(
&
p
->
vRequired
,
Gia_ManObjNum
(
p
->
pGia
),
ABC_INFINITY
);
if
(
p
->
pPars
->
fUseMux7
)
Gia_ManCleanMark0
(
p
->
pGia
);
if
(
p
->
pGia
->
pManTime
!=
NULL
)
{
Tim_ManIncrementTravId
(
p
->
pGia
->
pManTime
);
if
(
p
->
pPars
->
fDoAverage
)
for
(
i
=
0
;
i
<
Gia_ManCoNum
(
p
->
pGia
);
i
++
)
Tim_ManSetCoRequired
(
p
->
pGia
->
pManTime
,
i
,
(
int
)(
Lf_ObjCoArrival
(
p
,
i
)
*
(
100
.
0
+
p
->
pPars
->
nRelaxRatio
)
/
100
.
0
)
);
else
Tim_ManInitPoRequiredAll
(
p
->
pGia
->
pManTime
,
Delay
);
Gia_ManForEachObjReverse1
(
p
->
pGia
,
pObj
,
i
)
{
if
(
Gia_ObjIsBuf
(
pObj
)
)
Lf_ObjSetRequired
(
p
,
Gia_ObjFaninId0
(
pObj
,
i
),
Lf_ObjRequired
(
p
,
i
)
);
else
if
(
Gia_ObjIsAnd
(
pObj
)
)
{
if
(
Lf_ObjMapRefNum
(
p
,
i
)
)
Lf_ManCountMapRefsOne
(
p
,
i
);
}
else
if
(
Gia_ObjIsCi
(
pObj
)
)
Tim_ManSetCiRequired
(
p
->
pGia
->
pManTime
,
Gia_ObjCioId
(
pObj
),
Lf_ObjRequired
(
p
,
i
)
);
else
if
(
Gia_ObjIsCo
(
pObj
)
)
{
int
reqTime
=
Tim_ManGetCoRequired
(
p
->
pGia
->
pManTime
,
Gia_ObjCioId
(
pObj
)
);
Lf_ObjSetRequired
(
p
,
Gia_ObjFaninId0
(
pObj
,
i
),
reqTime
);
}
else
assert
(
0
);
}
}
else
{
Gia_ManForEachCoDriverId
(
p
->
pGia
,
Id
,
i
)
Lf_ObjSetRequired
(
p
,
Id
,
p
->
pPars
->
fDoAverage
?
(
int
)(
Lf_ObjCoArrival
(
p
,
i
)
*
(
100
.
0
+
p
->
pPars
->
nRelaxRatio
)
/
100
.
0
)
:
Delay
);
Gia_ManForEachAndReverse
(
p
->
pGia
,
pObj
,
i
)
if
(
Gia_ObjIsBuf
(
pObj
)
)
Lf_ObjSetRequired
(
p
,
Gia_ObjFaninId0
(
pObj
,
i
),
Lf_ObjRequired
(
p
,
i
)
);
else
if
(
Lf_ObjMapRefNum
(
p
,
i
)
)
Lf_ManCountMapRefsOne
(
p
,
i
);
}
if
(
p
->
pPars
->
fUseMux7
)
Gia_ManCleanMark0
(
p
->
pGia
);
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t
*
Lf_ManDeriveMapping
(
Lf_Man_t
*
p
)
{
Vec_Int_t
*
vMapping
;
Lf_Cut_t
*
pCut
;
int
i
,
k
;
assert
(
!
p
->
pPars
->
fCutMin
&&
p
->
pGia
->
vMapping
==
NULL
);
vMapping
=
Vec_IntAlloc
(
Gia_ManObjNum
(
p
->
pGia
)
+
(
int
)
p
->
pPars
->
Edge
+
(
int
)
p
->
pPars
->
Area
*
2
);
Vec_IntFill
(
vMapping
,
Gia_ManObjNum
(
p
->
pGia
),
0
);
Gia_ManForEachAndId
(
p
->
pGia
,
i
)
{
if
(
!
Lf_ObjMapRefNum
(
p
,
i
)
)
continue
;
assert
(
!
Gia_ObjIsBuf
(
Gia_ManObj
(
p
->
pGia
,
i
))
);
pCut
=
Lf_ObjCutBest
(
p
,
i
);
assert
(
!
pCut
->
fMux7
);
Vec_IntWriteEntry
(
vMapping
,
i
,
Vec_IntSize
(
vMapping
)
);
Vec_IntPush
(
vMapping
,
pCut
->
nLeaves
);
for
(
k
=
0
;
k
<
(
int
)
pCut
->
nLeaves
;
k
++
)
Vec_IntPush
(
vMapping
,
pCut
->
pLeaves
[
k
]
);
Vec_IntPush
(
vMapping
,
i
);
}
assert
(
Vec_IntCap
(
vMapping
)
==
16
||
Vec_IntSize
(
vMapping
)
==
Vec_IntCap
(
vMapping
)
);
p
->
pGia
->
vMapping
=
vMapping
;
return
p
->
pGia
;
}
Gia_Man_t
*
Lf_ManDeriveMappingCoarse
(
Lf_Man_t
*
p
)
{
Gia_Man_t
*
pNew
,
*
pGia
=
p
->
pGia
;
Gia_Obj_t
*
pObj
;
Lf_Cut_t
*
pCut
;
int
i
,
k
;
assert
(
!
p
->
pPars
->
fCutMin
&&
pGia
->
pMuxes
);
// create new manager
pNew
=
Gia_ManStart
(
Gia_ManObjNum
(
pGia
)
);
pNew
->
pName
=
Abc_UtilStrsav
(
pGia
->
pName
);
pNew
->
pSpec
=
Abc_UtilStrsav
(
pGia
->
pSpec
);
// start mapping
pNew
->
vMapping
=
Vec_IntAlloc
(
Gia_ManObjNum
(
pGia
)
+
2
*
Gia_ManXorNum
(
pGia
)
+
2
*
Gia_ManMuxNum
(
pGia
)
+
(
int
)
p
->
pPars
->
Edge
+
2
*
(
int
)
p
->
pPars
->
Area
+
4
*
(
int
)
p
->
pPars
->
Mux7
);
Vec_IntFill
(
pNew
->
vMapping
,
Gia_ManObjNum
(
pGia
)
+
2
*
Gia_ManXorNum
(
pGia
)
+
2
*
Gia_ManMuxNum
(
pGia
),
0
);
// process objects
Gia_ManConst0
(
pGia
)
->
Value
=
0
;
Gia_ManForEachObj1
(
pGia
,
pObj
,
i
)
{
if
(
Gia_ObjIsCi
(
pObj
)
)
{
pObj
->
Value
=
Gia_ManAppendCi
(
pNew
);
continue
;
}
if
(
Gia_ObjIsCo
(
pObj
)
)
{
pObj
->
Value
=
Gia_ManAppendCo
(
pNew
,
Gia_ObjFanin0Copy
(
pObj
)
);
continue
;
}
if
(
Gia_ObjIsBuf
(
pObj
)
)
{
pObj
->
Value
=
Gia_ManAppendBuf
(
pNew
,
Gia_ObjFanin0Copy
(
pObj
)
);
continue
;
}
if
(
Gia_ObjIsMuxId
(
pGia
,
i
)
)
pObj
->
Value
=
Gia_ManAppendMux
(
pNew
,
Gia_ObjFanin2Copy
(
pGia
,
pObj
),
Gia_ObjFanin1Copy
(
pObj
),
Gia_ObjFanin0Copy
(
pObj
)
);
else
if
(
Gia_ObjIsXor
(
pObj
)
)
pObj
->
Value
=
Gia_ManAppendXor
(
pNew
,
Gia_ObjFanin0Copy
(
pObj
),
Gia_ObjFanin1Copy
(
pObj
)
);
else
pObj
->
Value
=
Gia_ManAppendAnd
(
pNew
,
Gia_ObjFanin0Copy
(
pObj
),
Gia_ObjFanin1Copy
(
pObj
)
);
if
(
!
Lf_ObjMapRefNum
(
p
,
i
)
)
continue
;
pCut
=
Lf_ObjCutBest
(
p
,
i
);
Vec_IntWriteEntry
(
pNew
->
vMapping
,
Abc_Lit2Var
(
pObj
->
Value
),
Vec_IntSize
(
pNew
->
vMapping
)
);
Vec_IntPush
(
pNew
->
vMapping
,
pCut
->
nLeaves
);
for
(
k
=
0
;
k
<
(
int
)
pCut
->
nLeaves
;
k
++
)
Vec_IntPush
(
pNew
->
vMapping
,
Abc_Lit2Var
(
Gia_ManObj
(
pGia
,
pCut
->
pLeaves
[
k
])
->
Value
)
);
Vec_IntPush
(
pNew
->
vMapping
,
pCut
->
fMux7
?
-
Abc_Lit2Var
(
pObj
->
Value
)
:
Abc_Lit2Var
(
pObj
->
Value
)
);
}
Gia_ManSetRegNum
(
pNew
,
Gia_ManRegNum
(
pGia
)
);
assert
(
Vec_IntCap
(
pNew
->
vMapping
)
==
16
||
Vec_IntSize
(
pNew
->
vMapping
)
==
Vec_IntCap
(
pNew
->
vMapping
)
);
return
pNew
;
}
static
inline
int
Lf_ManDerivePart
(
Lf_Man_t
*
p
,
Gia_Man_t
*
pNew
,
Vec_Int_t
*
vMapping
,
Vec_Int_t
*
vMapping2
,
Vec_Int_t
*
vCopies
,
Lf_Cut_t
*
pCut
,
Vec_Int_t
*
vLeaves
,
Vec_Int_t
*
vCover
,
Gia_Obj_t
*
pObj
)
{
word
*
pTruth
;
int
k
,
iLit
,
iTemp
;
if
(
p
->
pPars
->
nLutSizeMux
&&
p
->
pPars
->
nLutSizeMux
==
(
int
)
pCut
->
nLeaves
)
{
word
pTruthCof
[
LF_TT_WORDS
],
*
pTruth
=
Lf_CutTruth
(
p
,
pCut
);
int
pVarsNew
[
LF_LEAF_MAX
],
nVarsNew
,
iLitCofs
[
2
];
int
LutSize
=
p
->
pPars
->
nLutSize
;
int
nWords
=
Abc_Truth6WordNum
(
LutSize
);
int
c
,
iVar
=
Lf_ManFindCofVar
(
pTruth
,
nWords
,
pCut
->
nLeaves
);
assert
(
iVar
>=
0
&&
iVar
<
(
int
)
pCut
->
nLeaves
);
for
(
c
=
0
;
c
<
2
;
c
++
)
{
for
(
k
=
0
;
k
<
(
int
)
pCut
->
nLeaves
;
k
++
)
pVarsNew
[
k
]
=
k
;
if
(
c
)
Abc_TtCofactor1p
(
pTruthCof
,
pTruth
,
nWords
,
iVar
);
else
Abc_TtCofactor0p
(
pTruthCof
,
pTruth
,
nWords
,
iVar
);
nVarsNew
=
Abc_TtMinBase
(
pTruthCof
,
pVarsNew
,
pCut
->
nLeaves
,
LutSize
);
assert
(
nVarsNew
>
0
);
// derive LUT
Vec_IntClear
(
vLeaves
);
for
(
k
=
0
;
k
<
nVarsNew
;
k
++
)
Vec_IntPush
(
vLeaves
,
Vec_IntEntry
(
vCopies
,
pCut
->
pLeaves
[
pVarsNew
[
k
]])
);
iLitCofs
[
c
]
=
Kit_TruthToGia
(
pNew
,
(
unsigned
*
)
pTruthCof
,
nVarsNew
,
vCover
,
vLeaves
,
0
);
// create mapping
Vec_IntSetEntry
(
vMapping
,
Abc_Lit2Var
(
iLitCofs
[
c
]),
Vec_IntSize
(
vMapping2
)
);
Vec_IntPush
(
vMapping2
,
Vec_IntSize
(
vLeaves
)
);
Vec_IntForEachEntry
(
vLeaves
,
iTemp
,
k
)
Vec_IntPush
(
vMapping2
,
Abc_Lit2Var
(
iTemp
)
);
Vec_IntPush
(
vMapping2
,
Abc_Lit2Var
(
iLitCofs
[
c
])
);
}
// derive MUX
pTruthCof
[
0
]
=
ABC_CONST
(
0xCACACACACACACACA
);
Vec_IntClear
(
vLeaves
);
Vec_IntPush
(
vLeaves
,
iLitCofs
[
0
]
);
Vec_IntPush
(
vLeaves
,
iLitCofs
[
1
]
);
Vec_IntPush
(
vLeaves
,
Vec_IntEntry
(
vCopies
,
pCut
->
pLeaves
[
iVar
])
);
iLit
=
Kit_TruthToGia
(
pNew
,
(
unsigned
*
)
pTruthCof
,
Vec_IntSize
(
vLeaves
),
vCover
,
vLeaves
,
0
);
// create mapping
Vec_IntSetEntry
(
vMapping
,
Abc_Lit2Var
(
iLit
),
Vec_IntSize
(
vMapping2
)
);
Vec_IntPush
(
vMapping2
,
Vec_IntSize
(
vLeaves
)
);
Vec_IntForEachEntry
(
vLeaves
,
iTemp
,
k
)
Vec_IntPush
(
vMapping2
,
Abc_Lit2Var
(
iTemp
)
);
Vec_IntPush
(
vMapping2
,
-
Abc_Lit2Var
(
iLit
)
);
return
iLit
;
}
Vec_IntClear
(
vLeaves
);
if
(
pCut
->
fMux7
)
{
assert
(
pCut
->
nLeaves
==
3
);
Vec_IntPush
(
vLeaves
,
Abc_LitNotCond
(
Vec_IntEntry
(
vCopies
,
pCut
->
pLeaves
[
0
]),
Gia_ObjFaninC0
(
pObj
))
);
Vec_IntPush
(
vLeaves
,
Abc_LitNotCond
(
Vec_IntEntry
(
vCopies
,
pCut
->
pLeaves
[
1
]),
Gia_ObjFaninC1
(
pObj
))
);
Vec_IntPush
(
vLeaves
,
Abc_LitNotCond
(
Vec_IntEntry
(
vCopies
,
pCut
->
pLeaves
[
2
]),
Gia_ObjFaninC2
(
p
->
pGia
,
pObj
))
);
}
else
{
for
(
k
=
0
;
k
<
(
int
)
pCut
->
nLeaves
;
k
++
)
Vec_IntPush
(
vLeaves
,
Vec_IntEntry
(
vCopies
,
pCut
->
pLeaves
[
k
])
);
}
pTruth
=
Lf_CutTruth
(
p
,
pCut
);
iLit
=
Kit_TruthToGia
(
pNew
,
(
unsigned
*
)
pTruth
,
Vec_IntSize
(
vLeaves
),
vCover
,
vLeaves
,
0
);
// create mapping
Vec_IntSetEntry
(
vMapping
,
Abc_Lit2Var
(
iLit
),
Vec_IntSize
(
vMapping2
)
);
Vec_IntPush
(
vMapping2
,
Vec_IntSize
(
vLeaves
)
);
Vec_IntForEachEntry
(
vLeaves
,
iTemp
,
k
)
Vec_IntPush
(
vMapping2
,
Abc_Lit2Var
(
iTemp
)
);
Vec_IntPush
(
vMapping2
,
pCut
->
fMux7
?
-
Abc_Lit2Var
(
iLit
)
:
Abc_Lit2Var
(
iLit
)
);
return
iLit
;
}
Gia_Man_t
*
Lf_ManDeriveMappingGia
(
Lf_Man_t
*
p
)
{
Gia_Man_t
*
pNew
;
Gia_Obj_t
*
pObj
;
Vec_Int_t
*
vCopies
=
Vec_IntStartFull
(
Gia_ManObjNum
(
p
->
pGia
)
);
Vec_Int_t
*
vMapping
=
Vec_IntStart
(
2
*
Gia_ManObjNum
(
p
->
pGia
)
+
(
int
)
p
->
pPars
->
Edge
+
2
*
(
int
)
p
->
pPars
->
Area
+
4
*
(
int
)
p
->
pPars
->
Mux7
);
Vec_Int_t
*
vMapping2
=
Vec_IntStart
(
(
int
)
p
->
pPars
->
Edge
+
2
*
(
int
)
p
->
pPars
->
Area
+
1000
);
Vec_Int_t
*
vCover
=
Vec_IntAlloc
(
1
<<
16
);
Vec_Int_t
*
vLeaves
=
Vec_IntAlloc
(
16
);
Lf_Cut_t
*
pCut
;
int
i
,
iLit
;
assert
(
p
->
pPars
->
fCutMin
);
// create new manager
pNew
=
Gia_ManStart
(
Gia_ManObjNum
(
p
->
pGia
)
);
pNew
->
pName
=
Abc_UtilStrsav
(
p
->
pGia
->
pName
);
pNew
->
pSpec
=
Abc_UtilStrsav
(
p
->
pGia
->
pSpec
);
Vec_IntWriteEntry
(
vCopies
,
0
,
0
);
Gia_ManForEachObj1
(
p
->
pGia
,
pObj
,
i
)
{
if
(
Gia_ObjIsCi
(
pObj
)
)
{
Vec_IntWriteEntry
(
vCopies
,
i
,
Gia_ManAppendCi
(
pNew
)
);
continue
;
}
if
(
Gia_ObjIsCo
(
pObj
)
)
{
iLit
=
Vec_IntEntry
(
vCopies
,
Gia_ObjFaninId0p
(
p
->
pGia
,
pObj
)
);
iLit
=
Gia_ManAppendCo
(
pNew
,
Abc_LitNotCond
(
iLit
,
Gia_ObjFaninC0
(
pObj
))
);
continue
;
}
if
(
Gia_ObjIsBuf
(
pObj
)
)
{
iLit
=
Vec_IntEntry
(
vCopies
,
Gia_ObjFaninId0p
(
p
->
pGia
,
pObj
)
);
iLit
=
Gia_ManAppendBuf
(
pNew
,
Abc_LitNotCond
(
iLit
,
Gia_ObjFaninC0
(
pObj
))
);
Vec_IntWriteEntry
(
vCopies
,
i
,
iLit
);
continue
;
}
if
(
!
Lf_ObjMapRefNum
(
p
,
i
)
)
continue
;
pCut
=
Lf_ObjCutBest
(
p
,
i
);
assert
(
pCut
->
iFunc
>=
0
);
if
(
pCut
->
nLeaves
==
0
)
{
assert
(
Abc_Lit2Var
(
pCut
->
iFunc
)
==
0
);
Vec_IntWriteEntry
(
vCopies
,
i
,
pCut
->
iFunc
);
continue
;
}
if
(
pCut
->
nLeaves
==
1
)
{
assert
(
Abc_Lit2Var
(
pCut
->
iFunc
)
==
1
);
iLit
=
Vec_IntEntry
(
vCopies
,
pCut
->
pLeaves
[
0
]
);
Vec_IntWriteEntry
(
vCopies
,
i
,
Abc_LitNotCond
(
iLit
,
Abc_LitIsCompl
(
pCut
->
iFunc
))
);
continue
;
}
iLit
=
Lf_ManDerivePart
(
p
,
pNew
,
vMapping
,
vMapping2
,
vCopies
,
pCut
,
vLeaves
,
vCover
,
pObj
);
Vec_IntWriteEntry
(
vCopies
,
i
,
Abc_LitNotCond
(
iLit
,
Abc_LitIsCompl
(
pCut
->
iFunc
))
);
}
Vec_IntFree
(
vCopies
);
Vec_IntFree
(
vCover
);
Vec_IntFree
(
vLeaves
);
// finish mapping
if
(
Vec_IntSize
(
vMapping
)
>
Gia_ManObjNum
(
pNew
)
)
Vec_IntShrink
(
vMapping
,
Gia_ManObjNum
(
pNew
)
);
else
Vec_IntFillExtra
(
vMapping
,
Gia_ManObjNum
(
pNew
),
0
);
assert
(
Vec_IntSize
(
vMapping
)
==
Gia_ManObjNum
(
pNew
)
);
Vec_IntForEachEntry
(
vMapping
,
iLit
,
i
)
if
(
iLit
>
0
)
Vec_IntAddToEntry
(
vMapping
,
i
,
Gia_ManObjNum
(
pNew
)
);
Vec_IntAppend
(
vMapping
,
vMapping2
);
Vec_IntFree
(
vMapping2
);
// attach mapping and packing
assert
(
pNew
->
vMapping
==
NULL
);
pNew
->
vMapping
=
vMapping
;
Gia_ManSetRegNum
(
pNew
,
Gia_ManRegNum
(
p
->
pGia
)
);
return
pNew
;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Lf_Man_t
*
Lf_ManAlloc
(
Gia_Man_t
*
pGia
,
Jf_Par_t
*
pPars
)
{
Lf_Man_t
*
p
;
int
i
,
k
=
0
;
assert
(
pPars
->
nCutNum
>
1
&&
pPars
->
nCutNum
<=
LF_CUT_MAX
);
assert
(
pPars
->
nLutSize
>
1
&&
pPars
->
nLutSize
<=
LF_LEAF_MAX
);
ABC_FREE
(
pGia
->
pRefs
);
Vec_IntFreeP
(
&
pGia
->
vMapping
);
Gia_ManCleanValue
(
pGia
);
if
(
Gia_ManHasChoices
(
pGia
)
)
Gia_ManSetPhase
(
pGia
);
p
=
ABC_CALLOC
(
Lf_Man_t
,
1
);
Lf_ManAnalyzeCoDrivers
(
pGia
,
&
p
->
nCoDrivers
,
&
p
->
nInverters
);
if
(
pPars
->
fPower
)
Lf_ManComputeSwitching
(
pGia
,
&
p
->
vSwitches
);
p
->
clkStart
=
Abc_Clock
();
p
->
pGia
=
pGia
;
p
->
pPars
=
pPars
;
p
->
nCutWords
=
(
sizeof
(
Lf_Cut_t
)
/
sizeof
(
int
)
+
pPars
->
nLutSize
+
1
)
>>
1
;
p
->
nSetWords
=
p
->
nCutWords
*
pPars
->
nCutNum
;
p
->
vTtMem
=
pPars
->
fCutMin
?
Vec_MemAllocForTT
(
pPars
->
nLutSize
,
0
)
:
NULL
;
if
(
pPars
->
fCutMin
&&
pPars
->
fUseMux7
)
Vec_MemAddMuxTT
(
p
->
vTtMem
,
pPars
->
nLutSize
);
p
->
pObjBests
=
ABC_CALLOC
(
Lf_Bst_t
,
Gia_ManAndNotBufNum
(
pGia
)
);
Vec_IntGrow
(
&
p
->
vFreeSets
,
(
1
<<
14
)
);
Vec_PtrGrow
(
&
p
->
vFreePages
,
256
);
Lf_MemAlloc
(
&
p
->
vStoreOld
,
16
,
&
p
->
vFreePages
,
p
->
nCutWords
);
Lf_MemAlloc
(
&
p
->
vStoreNew
,
16
,
&
p
->
vFreePages
,
p
->
nCutWords
);
Vec_IntFill
(
&
p
->
vOffsets
,
Gia_ManObjNum
(
pGia
),
-
1
);
Vec_IntFill
(
&
p
->
vRequired
,
Gia_ManObjNum
(
pGia
),
ABC_INFINITY
);
Vec_IntFill
(
&
p
->
vCutSets
,
Gia_ManAndNotBufNum
(
pGia
),
-
1
);
Vec_FltFill
(
&
p
->
vFlowRefs
,
Gia_ManAndNotBufNum
(
pGia
),
0
);
Vec_IntFill
(
&
p
->
vMapRefs
,
Gia_ManAndNotBufNum
(
pGia
),
0
);
Vec_IntFill
(
&
p
->
vCiArrivals
,
Gia_ManCiNum
(
pGia
),
0
);
Gia_ManForEachAndId
(
pGia
,
i
)
if
(
!
Gia_ObjIsBuf
(
Gia_ManObj
(
pGia
,
i
))
)
Vec_IntWriteEntry
(
&
p
->
vOffsets
,
i
,
k
++
);
assert
(
k
==
Gia_ManAndNotBufNum
(
pGia
)
);
Lf_ManSetFlowRefs
(
pGia
,
&
p
->
vFlowRefs
,
&
p
->
vOffsets
);
if
(
pPars
->
pTimesArr
)
for
(
i
=
0
;
i
<
Gia_ManPiNum
(
pGia
);
i
++
)
Vec_IntWriteEntry
(
&
p
->
vCiArrivals
,
i
,
pPars
->
pTimesArr
[
i
]
);
return
p
;
}
void
Lf_ManFree
(
Lf_Man_t
*
p
)
{
ABC_FREE
(
p
->
pPars
->
pTimesArr
);
ABC_FREE
(
p
->
pPars
->
pTimesReq
);
if
(
p
->
pPars
->
fCutMin
)
Vec_MemHashFree
(
p
->
vTtMem
);
if
(
p
->
pPars
->
fCutMin
)
Vec_MemFree
(
p
->
vTtMem
);
Vec_PtrFreeData
(
&
p
->
vMemSets
);
Vec_PtrFreeData
(
&
p
->
vFreePages
);
Vec_PtrFreeData
(
&
p
->
vStoreOld
.
vPages
);
Vec_PtrFreeData
(
&
p
->
vStoreNew
.
vPages
);
ABC_FREE
(
p
->
vMemSets
.
pArray
);
ABC_FREE
(
p
->
vFreePages
.
pArray
);
ABC_FREE
(
p
->
vStoreOld
.
vPages
.
pArray
);
ABC_FREE
(
p
->
vStoreNew
.
vPages
.
pArray
);
ABC_FREE
(
p
->
vFreePages
.
pArray
);
ABC_FREE
(
p
->
vFreeSets
.
pArray
);
ABC_FREE
(
p
->
vOffsets
.
pArray
);
ABC_FREE
(
p
->
vRequired
.
pArray
);
ABC_FREE
(
p
->
vCutSets
.
pArray
);
ABC_FREE
(
p
->
vFlowRefs
.
pArray
);
ABC_FREE
(
p
->
vMapRefs
.
pArray
);
ABC_FREE
(
p
->
vSwitches
.
pArray
);
ABC_FREE
(
p
->
vCiArrivals
.
pArray
);
ABC_FREE
(
p
->
pObjBests
);
ABC_FREE
(
p
);
}
/**Function*************************************************************
...
...
@@ -46,15 +1980,311 @@ ABC_NAMESPACE_IMPL_START
***********************************************************************/
void
Lf_ManSetDefaultPars
(
Jf_Par_t
*
pPars
)
{
Jf_ManSetDefaultPars
(
pPars
);
memset
(
pPars
,
0
,
sizeof
(
Jf_Par_t
)
);
pPars
->
nLutSize
=
6
;
pPars
->
nCutNum
=
8
;
pPars
->
nProcNum
=
0
;
pPars
->
nRounds
=
4
;
pPars
->
nRoundsEla
=
1
;
pPars
->
nRelaxRatio
=
0
;
pPars
->
nCoarseLimit
=
3
;
pPars
->
nAreaTuner
=
1
;
pPars
->
nVerbLimit
=
5
;
pPars
->
DelayTarget
=
-
1
;
pPars
->
fAreaOnly
=
0
;
pPars
->
fOptEdge
=
1
;
pPars
->
fUseMux7
=
0
;
pPars
->
fPower
=
0
;
pPars
->
fCoarsen
=
1
;
pPars
->
fCutMin
=
0
;
pPars
->
fFuncDsd
=
0
;
pPars
->
fGenCnf
=
0
;
pPars
->
fPureAig
=
0
;
pPars
->
fCutHashing
=
0
;
pPars
->
fCutSimple
=
0
;
pPars
->
fVerbose
=
0
;
pPars
->
fVeryVerbose
=
0
;
pPars
->
nLutSizeMax
=
LF_LEAF_MAX
;
pPars
->
nCutNumMax
=
LF_CUT_MAX
;
}
void
Lf_ManPrintStats
(
Lf_Man_t
*
p
,
char
*
pTitle
)
{
if
(
!
p
->
pPars
->
fVerbose
)
return
;
printf
(
"%s : "
,
pTitle
);
printf
(
"Level =%6lu "
,
p
->
pPars
->
Delay
);
printf
(
"Area =%9lu "
,
p
->
pPars
->
Area
);
printf
(
"Edge =%9lu "
,
p
->
pPars
->
Edge
);
printf
(
"LUT =%9lu "
,
p
->
pPars
->
Area
+
p
->
nInverters
);
if
(
Vec_FltSize
(
&
p
->
vSwitches
)
)
printf
(
"Swt =%8.1f "
,
p
->
Switches
);
if
(
p
->
pPars
->
fUseMux7
)
printf
(
"Mux7 =%7lu "
,
p
->
pPars
->
Mux7
);
Abc_PrintTime
(
1
,
"Time"
,
Abc_Clock
()
-
p
->
clkStart
);
fflush
(
stdout
);
}
void
Lf_ManPrintInit
(
Lf_Man_t
*
p
)
{
if
(
!
p
->
pPars
->
fVerbose
)
return
;
printf
(
"LutSize = %d "
,
p
->
pPars
->
nLutSize
);
printf
(
"CutNum = %d "
,
p
->
pPars
->
nCutNum
);
printf
(
"Iter = %d "
,
p
->
pPars
->
nRounds
+
p
->
pPars
->
nRoundsEla
);
if
(
p
->
pPars
->
nRelaxRatio
)
printf
(
"Ratio = %d "
,
p
->
pPars
->
nRelaxRatio
);
printf
(
"Edge = %d "
,
p
->
pPars
->
fOptEdge
);
if
(
p
->
pPars
->
DelayTarget
!=
-
1
)
printf
(
"Delay = %d "
,
p
->
pPars
->
DelayTarget
);
printf
(
"CutMin = %d "
,
p
->
pPars
->
fCutMin
);
printf
(
"Coarse = %d "
,
p
->
pPars
->
fCoarsen
);
printf
(
"Cut/Set = %d/%d Bytes"
,
8
*
p
->
nCutWords
,
8
*
p
->
nSetWords
);
printf
(
"
\n
"
);
printf
(
"Computing cuts...
\r
"
);
fflush
(
stdout
);
}
void
Lf_ManPrintQuit
(
Lf_Man_t
*
p
,
Gia_Man_t
*
pNew
)
{
float
MemGia
=
Gia_ManMemory
(
p
->
pGia
)
/
(
1
<<
20
);
float
MemMan
=
1
.
0
*
sizeof
(
int
)
*
(
2
*
Gia_ManObjNum
(
p
->
pGia
)
+
3
*
Gia_ManAndNotBufNum
(
p
->
pGia
))
/
(
1
<<
20
);
// offset, required, cutsets, maprefs, flowrefs
float
MemCutsB
=
1
.
0
*
(
p
->
vStoreOld
.
MaskPage
+
1
)
*
(
Vec_PtrSize
(
&
p
->
vFreePages
)
+
Vec_PtrSize
(
&
p
->
vStoreOld
.
vPages
))
/
(
1
<<
20
)
+
1
.
0
*
sizeof
(
Lf_Bst_t
)
*
Gia_ManAndNotBufNum
(
p
->
pGia
)
/
(
1
<<
20
);
float
MemCutsF
=
1
.
0
*
sizeof
(
word
)
*
p
->
nSetWords
*
(
1
<<
LF_LOG_PAGE
)
*
Vec_PtrSize
(
&
p
->
vMemSets
)
/
(
1
<<
20
);
float
MemTt
=
p
->
vTtMem
?
Vec_MemMemory
(
p
->
vTtMem
)
/
(
1
<<
20
)
:
0
;
float
MemMap
=
Vec_IntMemory
(
pNew
->
vMapping
)
/
(
1
<<
20
);
if
(
p
->
CutCount
[
0
]
==
0
)
p
->
CutCount
[
0
]
=
1
;
if
(
!
p
->
pPars
->
fVerbose
)
return
;
printf
(
"CutPair = %.0f "
,
p
->
CutCount
[
0
]
);
printf
(
"Merge = %.0f (%.2f %%) "
,
p
->
CutCount
[
1
],
100
.
0
*
p
->
CutCount
[
1
]
/
p
->
CutCount
[
0
]
);
printf
(
"Eval = %.0f (%.2f %%) "
,
p
->
CutCount
[
2
],
100
.
0
*
p
->
CutCount
[
2
]
/
p
->
CutCount
[
0
]
);
printf
(
"Cut = %.0f (%.2f %%) "
,
p
->
CutCount
[
3
],
100
.
0
*
p
->
CutCount
[
3
]
/
p
->
CutCount
[
0
]
);
printf
(
"
\n
"
);
printf
(
"Gia = %.2f MB "
,
MemGia
);
printf
(
"Man = %.2f MB "
,
MemMan
);
printf
(
"Best = %.2f MB "
,
MemCutsB
);
printf
(
"Front = %.2f MB "
,
MemCutsF
);
printf
(
"Map = %.2f MB "
,
MemMap
);
printf
(
"TT = %.2f MB "
,
MemTt
);
printf
(
"Total = %.2f MB"
,
MemGia
+
MemMan
+
MemCutsB
+
MemCutsF
+
MemMap
+
MemTt
);
printf
(
"
\n
"
);
if
(
1
)
{
int
i
;
for
(
i
=
0
;
i
<=
p
->
pPars
->
nLutSize
;
i
++
)
printf
(
"%d:%d "
,
i
,
p
->
nCutCounts
[
i
]
);
printf
(
"Equal = %d (%.0f %%) "
,
p
->
nCutEqual
,
100
.
0
*
p
->
nCutEqual
/
p
->
Iter
/
Gia_ManAndNotBufNum
(
p
->
pGia
)
);
if
(
p
->
vTtMem
)
printf
(
"TT = %d (%.2f %%) "
,
Vec_MemEntryNum
(
p
->
vTtMem
),
100
.
0
*
Vec_MemEntryNum
(
p
->
vTtMem
)
/
p
->
CutCount
[
2
]
);
if
(
p
->
pGia
->
pMuxes
&&
p
->
nCutMux
)
printf
(
"MuxTT = %d (%.0f %%) "
,
p
->
nCutMux
,
100
.
0
*
p
->
nCutMux
/
p
->
Iter
/
Gia_ManMuxNum
(
p
->
pGia
)
);
printf
(
"
\n
"
);
}
printf
(
"CoDrvs = %d (%.2f %%) "
,
p
->
nCoDrivers
,
100
.
0
*
p
->
nCoDrivers
/
Gia_ManCoNum
(
p
->
pGia
)
);
printf
(
"CoInvs = %d (%.2f %%) "
,
p
->
nInverters
,
100
.
0
*
p
->
nInverters
/
Gia_ManCoNum
(
p
->
pGia
)
);
printf
(
"Front = %d (%.2f %%) "
,
p
->
nFrontMax
,
100
.
0
*
p
->
nFrontMax
/
Gia_ManAndNum
(
p
->
pGia
)
);
printf
(
"TimeFails = %d "
,
p
->
nTimeFails
);
Abc_PrintTime
(
1
,
"Time"
,
Abc_Clock
()
-
p
->
clkStart
);
fflush
(
stdout
);
}
void
Lf_ManComputeMapping
(
Lf_Man_t
*
p
)
{
Gia_Obj_t
*
pObj
;
int
i
,
arrTime
;
assert
(
p
->
vStoreNew
.
iCur
==
0
);
Lf_ManSetCutRefs
(
p
);
if
(
p
->
pGia
->
pManTime
!=
NULL
)
{
assert
(
!
Gia_ManBufNum
(
p
->
pGia
)
);
Tim_ManIncrementTravId
(
p
->
pGia
->
pManTime
);
Gia_ManForEachObj1
(
p
->
pGia
,
pObj
,
i
)
{
if
(
Gia_ObjIsBuf
(
pObj
)
)
continue
;
if
(
Gia_ObjIsAnd
(
pObj
)
)
Lf_ObjMergeOrder
(
p
,
i
);
else
if
(
Gia_ObjIsCi
(
pObj
)
)
{
arrTime
=
Tim_ManGetCiArrival
(
p
->
pGia
->
pManTime
,
Gia_ObjCioId
(
pObj
)
);
Lf_ObjSetCiArrival
(
p
,
Gia_ObjCioId
(
pObj
),
arrTime
);
}
else
if
(
Gia_ObjIsCo
(
pObj
)
)
{
arrTime
=
Lf_ObjCoArrival
(
p
,
Gia_ObjCioId
(
pObj
)
);
Tim_ManSetCoArrival
(
p
->
pGia
->
pManTime
,
Gia_ObjCioId
(
pObj
),
arrTime
);
}
else
assert
(
0
);
}
// Tim_ManPrint( p->pGia->pManTime );
}
else
{
Gia_ManForEachAnd
(
p
->
pGia
,
pObj
,
i
)
if
(
!
Gia_ObjIsBuf
(
pObj
)
)
Lf_ObjMergeOrder
(
p
,
i
);
}
Lf_MemRecycle
(
&
p
->
vStoreOld
);
ABC_SWAP
(
Lf_Mem_t
,
p
->
vStoreOld
,
p
->
vStoreNew
);
if
(
p
->
fUseEla
)
Lf_ManCountMapRefs
(
p
);
else
Lf_ManSetMapRefs
(
p
);
Lf_ManPrintStats
(
p
,
p
->
fUseEla
?
"Ela "
:
(
p
->
Iter
?
"Area "
:
"Delay"
)
);
}
Gia_Man_t
*
Lf_ManPerformMappingInt
(
Gia_Man_t
*
pGia
,
Jf_Par_t
*
pPars
)
{
int
fUsePowerMode
=
0
;
Lf_Man_t
*
p
;
Gia_Man_t
*
pNew
,
*
pCls
;
if
(
pPars
->
fUseMux7
)
pPars
->
fCoarsen
=
1
,
pPars
->
nRoundsEla
=
0
;
if
(
Gia_ManHasChoices
(
pGia
)
||
pPars
->
nLutSizeMux
)
pPars
->
fCutMin
=
1
;
if
(
pPars
->
fCoarsen
)
{
pCls
=
Gia_ManDupMuxes
(
pGia
,
pPars
->
nCoarseLimit
);
pCls
->
pManTime
=
pGia
->
pManTime
;
pGia
->
pManTime
=
NULL
;
}
else
pCls
=
pGia
;
p
=
Lf_ManAlloc
(
pCls
,
pPars
);
if
(
pPars
->
fVerbose
&&
pPars
->
fCoarsen
)
{
printf
(
"Initial "
);
Gia_ManPrintMuxStats
(
pGia
);
printf
(
"
\n
"
);
printf
(
"Derived "
);
Gia_ManPrintMuxStats
(
pCls
);
printf
(
"
\n
"
);
}
Lf_ManPrintInit
(
p
);
// power mode
if
(
fUsePowerMode
&&
Vec_FltSize
(
&
p
->
vSwitches
)
)
pPars
->
fPower
=
0
;
// perform mapping
for
(
p
->
Iter
=
0
;
p
->
Iter
<
p
->
pPars
->
nRounds
;
p
->
Iter
++
)
Lf_ManComputeMapping
(
p
);
p
->
fUseEla
=
1
;
for
(
;
p
->
Iter
<
p
->
pPars
->
nRounds
+
pPars
->
nRoundsEla
;
p
->
Iter
++
)
Lf_ManComputeMapping
(
p
);
// power mode
if
(
fUsePowerMode
&&
Vec_FltSize
(
&
p
->
vSwitches
)
)
{
pPars
->
fPower
=
1
;
for
(
;
p
->
Iter
<
p
->
pPars
->
nRounds
+
pPars
->
nRoundsEla
+
2
;
p
->
Iter
++
)
Lf_ManComputeMapping
(
p
);
}
if
(
pPars
->
fVeryVerbose
&&
pPars
->
fCutMin
)
Vec_MemDumpTruthTables
(
p
->
vTtMem
,
Gia_ManName
(
p
->
pGia
),
pPars
->
nLutSize
);
if
(
pPars
->
fCutMin
)
pNew
=
Lf_ManDeriveMappingGia
(
p
);
else
if
(
pPars
->
fCoarsen
)
pNew
=
Lf_ManDeriveMappingCoarse
(
p
);
else
pNew
=
Lf_ManDeriveMapping
(
p
);
Gia_ManMappingVerify
(
pNew
);
Lf_ManPrintQuit
(
p
,
pNew
);
Lf_ManFree
(
p
);
if
(
pCls
!=
pGia
)
{
pGia
->
pManTime
=
pCls
->
pManTime
;
pCls
->
pManTime
=
NULL
;
Gia_ManStop
(
pCls
);
}
return
pNew
;
}
Gia_Man_t
*
Lf_ManPerformMapping
(
Gia_Man_t
*
p
Gia
,
Jf_Par_t
*
pPars
)
Gia_Man_t
*
Lf_ManPerformMapping
(
Gia_Man_t
*
p
,
Jf_Par_t
*
pPars
)
{
return
Jf_ManPerformMapping
(
pGia
,
pPars
);
Gia_Man_t
*
pNew
;
if
(
p
->
pManTime
&&
Tim_ManBoxNum
(
p
->
pManTime
)
&&
Gia_ManIsNormalized
(
p
)
)
{
Tim_Man_t
*
pTimOld
=
(
Tim_Man_t
*
)
p
->
pManTime
;
p
->
pManTime
=
Tim_ManDup
(
pTimOld
,
1
);
pNew
=
Gia_ManDupUnnormalize
(
p
);
if
(
pNew
==
NULL
)
return
NULL
;
Gia_ManTransferTiming
(
pNew
,
p
);
p
=
pNew
;
// mapping
pNew
=
Lf_ManPerformMappingInt
(
p
,
pPars
);
if
(
pNew
!=
p
)
{
Gia_ManTransferTiming
(
pNew
,
p
);
Gia_ManStop
(
p
);
}
// normalize
pNew
=
Gia_ManDupNormalize
(
p
=
pNew
);
Gia_ManTransferMapping
(
pNew
,
p
);
// Gia_ManTransferPacking( pNew, p );
Gia_ManTransferTiming
(
pNew
,
p
);
Gia_ManStop
(
p
);
// do not delete if the original one!
// cleanup
Tim_ManStop
(
(
Tim_Man_t
*
)
pNew
->
pManTime
);
pNew
->
pManTime
=
pTimOld
;
assert
(
Gia_ManIsNormalized
(
pNew
)
);
}
else
{
// mapping
pNew
=
Lf_ManPerformMappingInt
(
p
,
pPars
);
Gia_ManTransferTiming
(
pNew
,
p
);
}
return
pNew
;
}
/**Function*************************************************************
Synopsis [Interface of LUT mapping package.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t
*
Gia_ManPerformLfMapping
(
Gia_Man_t
*
p
,
Jf_Par_t
*
pPars
,
int
fNormalized
)
{
Gia_Man_t
*
pNew
;
// reconstruct GIA according to the hierarchy manager
assert
(
pPars
->
pTimesArr
==
NULL
);
assert
(
pPars
->
pTimesReq
==
NULL
);
if
(
p
->
pManTime
)
{
if
(
fNormalized
)
{
pNew
=
Gia_ManDupUnnormalize
(
p
);
if
(
pNew
==
NULL
)
return
NULL
;
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
);
}
else
p
=
Gia_ManDup
(
p
);
}
else
p
=
Gia_ManDup
(
p
);
// perform mapping
pNew
=
Lf_ManPerformMappingInt
(
p
,
pPars
);
if
(
pNew
!=
p
)
{
// transfer name
ABC_FREE
(
pNew
->
pName
);
ABC_FREE
(
pNew
->
pSpec
);
pNew
->
pName
=
Abc_UtilStrsav
(
p
->
pName
);
pNew
->
pSpec
=
Abc_UtilStrsav
(
p
->
pSpec
);
Gia_ManSetRegNum
(
pNew
,
Gia_ManRegNum
(
p
)
);
// return the original (unmodified by the mapper) timing manager
Gia_ManTransferTiming
(
pNew
,
p
);
Gia_ManStop
(
p
);
}
// normalize and transfer mapping
pNew
=
Gia_ManDupNormalize
(
p
=
pNew
);
Gia_ManTransferMapping
(
pNew
,
p
);
// Gia_ManTransferPacking( pNew, p );
Gia_ManTransferTiming
(
pNew
,
p
);
Gia_ManStop
(
p
);
return
pNew
;
}
////////////////////////////////////////////////////////////////////////
...
...
src/aig/gia/giaNf.c
View file @
88c57c93
...
...
@@ -6,7 +6,7 @@
PackageName [Scalable AIG package.]
Synopsis [
Technology
mapper.]
Synopsis [
Standard-cell
mapper.]
Author [Alan Mishchenko]
...
...
@@ -18,7 +18,16 @@
***********************************************************************/
#include <float.h>
#include "gia.h"
#include "misc/st/st.h"
#include "map/mio/mio.h"
#include "misc/util/utilTruth.h"
#include "misc/extra/extra.h"
#include "base/main/main.h"
#include "misc/vec/vecMem.h"
#include "misc/vec/vecWec.h"
#include "opt/dau/dau.h"
ABC_NAMESPACE_IMPL_START
...
...
@@ -26,12 +35,663 @@ ABC_NAMESPACE_IMPL_START
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define NF_LEAF_MAX 6
#define NF_CUT_MAX 32
#define NF_NO_LEAF 31
#define NF_INFINITY FLT_MAX
enum
{
NF_ANDOR
=
1
,
NF_XOR
=
2
,
NF_PRIME
=
3
};
typedef
struct
Nf_Cut_t_
Nf_Cut_t
;
struct
Nf_Cut_t_
{
word
Sign
;
// signature
int
Delay
;
// delay
float
Flow
;
// flow
unsigned
iFunc
:
26
;
// function
unsigned
Useless
:
1
;
// function
unsigned
nLeaves
:
5
;
// leaf number (NF_NO_LEAF)
int
pLeaves
[
NF_LEAF_MAX
+
1
];
// leaves
};
typedef
struct
Nf_Mat_t_
Nf_Mat_t
;
struct
Nf_Mat_t_
{
unsigned
Gate
:
20
;
// gate
unsigned
CutH
:
10
;
// cut handle
unsigned
fCompl
:
1
;
// complemented
unsigned
fBest
:
1
;
// best cut
int
Conf
;
// input literals
float
D
;
// delay
float
A
;
// area
};
typedef
struct
Nf_Obj_t_
Nf_Obj_t
;
struct
Nf_Obj_t_
{
Nf_Mat_t
M
[
2
][
2
];
// del/area (2x)
};
typedef
struct
Nf_Man_t_
Nf_Man_t
;
struct
Nf_Man_t_
{
// user data
Gia_Man_t
*
pGia
;
// derived manager
Jf_Par_t
*
pPars
;
// parameters
// matching
Vec_Mem_t
*
vTtMem
;
// truth tables
Vec_Wec_t
*
vTt2Match
;
// matches for truth tables
Vec_Str_t
*
vMemStore
;
// memory for matches
Mio_Cell_t
*
pCells
;
// library gates
int
nCells
;
// library gate count
// cut data
Nf_Obj_t
*
pNfObjs
;
// best cuts
Vec_Ptr_t
vPages
;
// cut memory
Vec_Int_t
vCutSets
;
// cut offsets
Vec_Int_t
vMapRefs
;
// mapping refs (2x)
Vec_Flt_t
vFlowRefs
;
// flow refs (2x)
Vec_Flt_t
vRequired
;
// required times (2x)
Vec_Flt_t
vCutFlows
;
// temporary cut area
Vec_Int_t
vCutDelays
;
// temporary cut delay
Vec_Int_t
vBackup
;
// backup literals
Vec_Int_t
vBackup2
;
// backup literals
int
iCur
;
// current position
int
Iter
;
// mapping iterations
int
fUseEla
;
// use exact area
int
nInvs
;
// the inverter count
float
InvDelay
;
// inverter delay
float
InvArea
;
// inverter area
// statistics
abctime
clkStart
;
// starting time
double
CutCount
[
6
];
// cut counts
int
nCutUseAll
;
// objects with useful cuts
};
static
inline
Nf_Obj_t
*
Nf_ManObj
(
Nf_Man_t
*
p
,
int
i
)
{
return
p
->
pNfObjs
+
i
;
}
static
inline
Mio_Cell_t
*
Nf_ManCell
(
Nf_Man_t
*
p
,
int
i
)
{
return
p
->
pCells
+
i
;
}
static
inline
int
*
Nf_ManCutSet
(
Nf_Man_t
*
p
,
int
i
)
{
return
(
int
*
)
Vec_PtrEntry
(
&
p
->
vPages
,
i
>>
16
)
+
(
i
&
0xFFFF
);
}
static
inline
int
Nf_ObjCutSetId
(
Nf_Man_t
*
p
,
int
i
)
{
return
Vec_IntEntry
(
&
p
->
vCutSets
,
i
);
}
static
inline
int
*
Nf_ObjCutSet
(
Nf_Man_t
*
p
,
int
i
)
{
return
Nf_ManCutSet
(
p
,
Nf_ObjCutSetId
(
p
,
i
));
}
static
inline
int
Nf_ObjHasCuts
(
Nf_Man_t
*
p
,
int
i
)
{
return
(
int
)(
Vec_IntEntry
(
&
p
->
vCutSets
,
i
)
>
0
);
}
static
inline
int
*
Nf_ObjCutBest
(
Nf_Man_t
*
p
,
int
i
)
{
return
NULL
;
}
static
inline
int
Nf_ObjCutUseless
(
Nf_Man_t
*
p
,
int
TruthId
)
{
return
(
int
)(
TruthId
>=
Vec_WecSize
(
p
->
vTt2Match
));
}
static
inline
float
Nf_ObjCutFlow
(
Nf_Man_t
*
p
,
int
i
)
{
return
Vec_FltEntry
(
&
p
->
vCutFlows
,
i
);
}
static
inline
int
Nf_ObjCutDelay
(
Nf_Man_t
*
p
,
int
i
)
{
return
Vec_IntEntry
(
&
p
->
vCutDelays
,
i
);
}
static
inline
void
Nf_ObjSetCutFlow
(
Nf_Man_t
*
p
,
int
i
,
float
a
)
{
Vec_FltWriteEntry
(
&
p
->
vCutFlows
,
i
,
a
);
}
static
inline
void
Nf_ObjSetCutDelay
(
Nf_Man_t
*
p
,
int
i
,
int
d
)
{
Vec_IntWriteEntry
(
&
p
->
vCutDelays
,
i
,
d
);
}
static
inline
int
Nf_ObjMapRefNum
(
Nf_Man_t
*
p
,
int
i
,
int
c
)
{
return
Vec_IntEntry
(
&
p
->
vMapRefs
,
Abc_Var2Lit
(
i
,
c
));
}
static
inline
int
Nf_ObjMapRefInc
(
Nf_Man_t
*
p
,
int
i
,
int
c
)
{
return
(
*
Vec_IntEntryP
(
&
p
->
vMapRefs
,
Abc_Var2Lit
(
i
,
c
)))
++
;
}
static
inline
int
Nf_ObjMapRefDec
(
Nf_Man_t
*
p
,
int
i
,
int
c
)
{
return
--
(
*
Vec_IntEntryP
(
&
p
->
vMapRefs
,
Abc_Var2Lit
(
i
,
c
)));
}
static
inline
float
Nf_ObjFlowRefs
(
Nf_Man_t
*
p
,
int
i
,
int
c
)
{
return
Vec_FltEntry
(
&
p
->
vFlowRefs
,
Abc_Var2Lit
(
i
,
c
));
}
static
inline
float
Nf_ObjRequired
(
Nf_Man_t
*
p
,
int
i
,
int
c
)
{
return
Vec_FltEntry
(
&
p
->
vRequired
,
Abc_Var2Lit
(
i
,
c
));
}
static
inline
void
Nf_ObjSetRequired
(
Nf_Man_t
*
p
,
int
i
,
int
c
,
float
f
)
{
Vec_FltWriteEntry
(
&
p
->
vRequired
,
Abc_Var2Lit
(
i
,
c
),
f
);
}
static
inline
void
Nf_ObjUpdateRequired
(
Nf_Man_t
*
p
,
int
i
,
int
c
,
float
f
)
{
if
(
Nf_ObjRequired
(
p
,
i
,
c
)
>
f
)
Nf_ObjSetRequired
(
p
,
i
,
c
,
f
);
}
static
inline
Nf_Mat_t
*
Nf_ObjMatchD
(
Nf_Man_t
*
p
,
int
i
,
int
c
)
{
return
&
Nf_ManObj
(
p
,
i
)
->
M
[
c
][
0
];
}
static
inline
Nf_Mat_t
*
Nf_ObjMatchA
(
Nf_Man_t
*
p
,
int
i
,
int
c
)
{
return
&
Nf_ManObj
(
p
,
i
)
->
M
[
c
][
1
];
}
static
inline
Nf_Mat_t
*
Nf_ObjMatchBest
(
Nf_Man_t
*
p
,
int
i
,
int
c
)
{
Nf_Mat_t
*
pD
=
Nf_ObjMatchD
(
p
,
i
,
c
);
Nf_Mat_t
*
pA
=
Nf_ObjMatchA
(
p
,
i
,
c
);
assert
(
pD
->
fBest
!=
pA
->
fBest
);
assert
(
Nf_ObjMapRefNum
(
p
,
i
,
c
)
>
0
);
if
(
pA
->
fBest
)
return
pA
;
if
(
pD
->
fBest
)
return
pD
;
return
NULL
;
}
static
inline
int
Nf_CutSize
(
int
*
pCut
)
{
return
pCut
[
0
]
&
NF_NO_LEAF
;
}
static
inline
int
Nf_CutFunc
(
int
*
pCut
)
{
return
((
unsigned
)
pCut
[
0
]
>>
5
);
}
static
inline
int
*
Nf_CutLeaves
(
int
*
pCut
)
{
return
pCut
+
1
;
}
static
inline
int
Nf_CutSetBoth
(
int
n
,
int
f
)
{
return
n
|
(
f
<<
5
);
}
static
inline
int
Nf_CutIsTriv
(
int
*
pCut
,
int
i
)
{
return
Nf_CutSize
(
pCut
)
==
1
&&
pCut
[
1
]
==
i
;
}
static
inline
int
Nf_CutHandle
(
int
*
pCutSet
,
int
*
pCut
)
{
assert
(
pCut
>
pCutSet
);
return
pCut
-
pCutSet
;
}
static
inline
int
*
Nf_CutFromHandle
(
int
*
pCutSet
,
int
h
)
{
assert
(
h
>
0
);
return
pCutSet
+
h
;
}
static
inline
int
Nf_CutConfLit
(
int
Conf
,
int
i
)
{
return
15
&
(
Conf
>>
(
i
<<
2
));
}
static
inline
int
Nf_CutConfVar
(
int
Conf
,
int
i
)
{
return
Abc_Lit2Var
(
Nf_CutConfLit
(
Conf
,
i
)
);
}
static
inline
int
Nf_CutConfC
(
int
Conf
,
int
i
)
{
return
Abc_LitIsCompl
(
Nf_CutConfLit
(
Conf
,
i
)
);
}
#define Nf_SetForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Nf_CutSize(pCut) + 1 )
#define Nf_ObjForEachCut( pCuts, i, nCuts ) for ( i = 0, i < nCuts; i++ )
#define Nf_CutForEachLit( pCut, Conf, iLit, i ) for ( i = 0; i < Nf_CutSize(pCut) && (iLit = Abc_Lit2LitV(Nf_CutLeaves(pCut), Nf_CutConfLit(Conf, i))); i++ )
#define Nf_CutForEachVar( pCut, Conf, iVar, c, i ) for ( i = 0; i < Nf_CutSize(pCut) && (iVar = Nf_CutLeaves(pCut)[Nf_CutConfVar(Conf, i)]) && ((c = Nf_CutConfC(Conf, i)), 1); i++ )
/*
Three types of config:
<match> : <gate> <compl> <type> <offset>
<type> : AND/OR | XOR | prime
<offset> : <record>
<record>
- XOR : <array>
- prime : <array>, ... <array>
- AND/OR : <num_configs>, <config>, ... <config>
<config> : <num_entries>, <num_neg_entries>, <array>
<array> : <entry>, ...., <entry> (sorted by increasing order of arrivals)
*/
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Sort inputs by delay.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
void
Nf_StoSelectSort
(
int
*
pArray
,
int
nSize
,
Mio_Cell_t
*
pCell
)
{
int
i
,
j
,
best_i
;
for
(
i
=
0
;
i
<
nSize
-
1
;
i
++
)
{
best_i
=
i
;
for
(
j
=
i
+
1
;
j
<
nSize
;
j
++
)
if
(
pCell
->
Delays
[
Abc_Lit2Var
(
pArray
[
j
])]
<
pCell
->
Delays
[
Abc_Lit2Var
(
pArray
[
best_i
])]
)
best_i
=
j
;
if
(
i
!=
best_i
)
ABC_SWAP
(
int
,
pArray
[
i
],
pArray
[
best_i
]
);
}
}
static
inline
void
Nf_StoSelectSortLit
(
int
*
pArray
,
int
nSize
,
Mio_Cell_t
*
pCell
)
{
int
i
,
j
,
best_i
;
for
(
i
=
0
;
i
<
nSize
-
1
;
i
++
)
{
best_i
=
i
;
for
(
j
=
i
+
1
;
j
<
nSize
;
j
++
)
if
(
Abc_LitIsCompl
(
pArray
[
j
])
>
Abc_LitIsCompl
(
pArray
[
best_i
])
||
(
Abc_LitIsCompl
(
pArray
[
j
])
==
Abc_LitIsCompl
(
pArray
[
best_i
])
&&
pCell
->
Delays
[
Abc_Lit2Var
(
pArray
[
j
])]
<
pCell
->
Delays
[
Abc_Lit2Var
(
pArray
[
best_i
])])
)
best_i
=
j
;
if
(
i
!=
best_i
)
ABC_SWAP
(
int
,
pArray
[
i
],
pArray
[
best_i
]
);
}
}
void
Nf_StoCreateGateAdd
(
Nf_Man_t
*
pMan
,
word
uTruth
,
int
*
pFans
,
int
nFans
,
int
CellId
,
int
Type
)
{
Vec_Int_t
*
vArray
;
int
i
,
fCompl
=
(
int
)(
uTruth
&
1
);
word
uFunc
=
fCompl
?
~
uTruth
:
uTruth
;
int
iFunc
=
Vec_MemHashInsert
(
pMan
->
vTtMem
,
&
uFunc
);
if
(
iFunc
==
Vec_WecSize
(
pMan
->
vTt2Match
)
)
Vec_WecPushLevel
(
pMan
->
vTt2Match
);
vArray
=
Vec_WecEntry
(
pMan
->
vTt2Match
,
iFunc
);
Vec_IntPush
(
vArray
,
(
CellId
<<
8
)
|
(
Type
<<
4
)
|
fCompl
);
Vec_IntPush
(
vArray
,
Vec_StrSize
(
pMan
->
vMemStore
)
);
if
(
Type
==
NF_ANDOR
)
return
;
for
(
i
=
0
;
i
<
nFans
;
i
++
)
Vec_StrPush
(
pMan
->
vMemStore
,
(
char
)
pFans
[
i
]
);
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int
Nf_StoBuildDsdAnd_rec
(
Nf_Man_t
*
pMan
,
Mio_Cell_t
*
pCell
,
char
*
pStr
,
char
**
p
,
int
*
pMatches
,
int
pGroups
[
NF_LEAF_MAX
][
NF_LEAF_MAX
],
int
*
nGroupSizes
,
int
*
pnGroups
)
{
int
fCompl
=
0
;
if
(
**
p
==
'!'
)
(
*
p
)
++
,
fCompl
=
1
;
if
(
**
p
>=
'a'
&&
**
p
<
'a'
+
NF_LEAF_MAX
)
// var
// return Abc_Var2Lit( **p - 'a', fCompl );
return
Abc_Var2Lit
(
**
p
-
'a'
,
0
);
if
(
**
p
==
'('
)
// and/or
{
char
*
q
=
pStr
+
pMatches
[
*
p
-
pStr
];
int
pFans
[
NF_LEAF_MAX
],
nFans
=
0
;
assert
(
**
p
==
'('
&&
*
q
==
')'
);
for
(
(
*
p
)
++
;
*
p
<
q
;
(
*
p
)
++
)
{
int
Value
=
Nf_StoBuildDsdAnd_rec
(
pMan
,
pCell
,
pStr
,
p
,
pMatches
,
pGroups
,
nGroupSizes
,
pnGroups
);
if
(
Value
==
-
1
)
continue
;
pFans
[
nFans
++
]
=
Value
;
}
// collect
if
(
nFans
>
0
)
{
memcpy
(
pGroups
[
*
pnGroups
],
pFans
,
sizeof
(
int
)
*
nFans
);
nGroupSizes
[
*
pnGroups
]
=
nFans
;
(
*
pnGroups
)
++
;
}
assert
(
*
p
==
q
);
return
-
1
;
}
assert
(
0
);
return
0
;
}
int
Nf_StoBuildDsdAnd
(
Nf_Man_t
*
pMan
,
Mio_Cell_t
*
pCell
,
char
*
p
)
{
int
pGroups
[
NF_LEAF_MAX
][
NF_LEAF_MAX
],
pGroups2
[
NF_LEAF_MAX
][
NF_LEAF_MAX
];
int
nGroupSizes
[
NF_LEAF_MAX
],
nGroupInvs
[
NF_LEAF_MAX
],
Phases
[
NF_LEAF_MAX
];
int
nGroups
=
0
,
nVars
=
0
,
nConfigs
=
1
;
int
i
,
k
,
c
,
Res
,
fCompl
=
0
;
char
**
pp
=
&
p
;
word
uTruth
;
assert
(
*
(
p
+
1
)
!=
0
);
if
(
*
p
==
'!'
)
(
*
pp
)
++
,
fCompl
=
1
;
assert
(
**
pp
!=
'!'
);
Res
=
Nf_StoBuildDsdAnd_rec
(
pMan
,
pCell
,
p
,
pp
,
Dau_DsdComputeMatches
(
p
),
pGroups
,
nGroupSizes
,
&
nGroups
);
assert
(
Res
==
-
1
);
assert
(
*++
p
==
0
);
// create groups
for
(
i
=
0
;
i
<
nGroups
;
i
++
)
{
nVars
+=
nGroupSizes
[
i
];
nConfigs
*=
(
1
<<
nGroupSizes
[
i
]);
}
assert
(
nVars
==
(
int
)
pCell
->
nFanins
);
// iterate through phase assignments
for
(
c
=
0
;
c
<
nConfigs
;
c
++
)
{
int
Start
=
c
;
for
(
i
=
nGroups
-
1
;
i
>=
0
;
i
--
)
{
Phases
[
i
]
=
Start
%
(
1
<<
nGroupSizes
[
i
]);
Start
/=
(
1
<<
nGroupSizes
[
i
]);
memcpy
(
pGroups2
[
i
],
pGroups
[
i
],
sizeof
(
int
)
*
nGroupSizes
[
i
]
);
// printf( "%d ", Phases[i] );
}
// printf( "\n" );
// create configuration
uTruth
=
pCell
->
uTruth
;
for
(
i
=
0
;
i
<
nGroups
;
i
++
)
{
nGroupInvs
[
i
]
=
0
;
for
(
k
=
0
;
k
<
nGroupSizes
[
i
];
k
++
)
if
(
(
Phases
[
i
]
>>
k
)
&
1
)
{
pGroups2
[
i
][
k
]
=
Abc_LitNot
(
pGroups2
[
i
][
k
]);
uTruth
=
Abc_Tt6Flip
(
uTruth
,
Abc_Lit2Var
(
pGroups2
[
i
][
k
])
);
nGroupInvs
[
i
]
++
;
}
/*
if ( pCell->nFanins == 4 && nGroups == 1 )
{
printf( "Group before:\n" );
for ( k = 0; k < nGroupSizes[i]; k++ )
printf( "%d %.2f\n", pGroups2[i][k], pCell->Delays[Abc_Lit2Var(pGroups2[i][k])] );
}
*/
// Nf_StoSelectSortLit( pGroups2[i], nGroupSizes[i], pCell );
/*
if ( pCell->nFanins == 4 && nGroups == 1 )
{
printf( "Group after:\n" );
for ( k = 0; k < nGroupSizes[i]; k++ )
printf( "%d %.2f\n", pGroups2[i][k], pCell->Delays[Abc_Lit2Var(pGroups2[i][k])] );
printf( "\n" );
}
*/
}
// save
Nf_StoCreateGateAdd
(
pMan
,
uTruth
,
NULL
,
-
1
,
pCell
->
Id
,
NF_ANDOR
);
Vec_StrPush
(
pMan
->
vMemStore
,
(
char
)
nGroups
);
for
(
i
=
0
;
i
<
nGroups
;
i
++
)
for
(
k
=
0
;
k
<
nGroupSizes
[
i
];
k
++
)
{
Vec_StrPush
(
pMan
->
vMemStore
,
(
char
)
nGroupSizes
[
i
]
);
Vec_StrPush
(
pMan
->
vMemStore
,
(
char
)
nGroupInvs
[
i
]
);
for
(
k
=
0
;
k
<
nGroupSizes
[
i
];
k
++
)
Vec_StrPush
(
pMan
->
vMemStore
,
(
char
)
pGroups2
[
i
][
k
]
);
}
}
return
Res
;
}
int
Nf_StoCheckDsdAnd_rec
(
char
*
pStr
,
char
**
p
,
int
*
pMatches
)
{
if
(
**
p
==
'!'
)
(
*
p
)
++
;
if
(
**
p
>=
'a'
&&
**
p
<
'a'
+
NF_LEAF_MAX
)
// var
return
1
;
if
(
**
p
==
'('
)
// and/or
{
char
*
q
=
pStr
+
pMatches
[
*
p
-
pStr
];
assert
(
**
p
==
'('
&&
*
q
==
')'
);
for
(
(
*
p
)
++
;
*
p
<
q
;
(
*
p
)
++
)
if
(
Nf_StoCheckDsdAnd_rec
(
pStr
,
p
,
pMatches
)
!=
1
)
return
0
;
assert
(
*
p
==
q
);
return
1
;
}
return
0
;
}
int
Nf_StoCheckDsdAnd
(
char
*
p
)
{
int
Res
;
assert
(
*
(
p
+
1
)
!=
0
);
Res
=
Nf_StoCheckDsdAnd_rec
(
p
,
&
p
,
Dau_DsdComputeMatches
(
p
)
);
// assert( *++p == 0 );
return
Res
;
}
int
Nf_StoCheckDsdXor_rec
(
char
*
pStr
,
char
**
p
,
int
*
pMatches
)
{
int
Value
,
fCompl
=
0
;
if
(
**
p
==
'!'
)
(
*
p
)
++
,
fCompl
^=
1
;
if
(
**
p
>=
'a'
&&
**
p
<
'a'
+
NF_LEAF_MAX
)
// var
return
fCompl
;
if
(
**
p
==
'['
)
// xor
{
char
*
q
=
pStr
+
pMatches
[
*
p
-
pStr
];
assert
(
**
p
==
'['
&&
*
q
==
']'
);
for
(
(
*
p
)
++
;
*
p
<
q
;
(
*
p
)
++
)
{
Value
=
Nf_StoCheckDsdXor_rec
(
pStr
,
p
,
pMatches
);
if
(
Value
==
-
1
)
return
-
1
;
fCompl
^=
Value
;
}
assert
(
*
p
==
q
);
return
fCompl
;
}
return
-
1
;
}
int
Nf_StoCheckDsdXor
(
char
*
p
)
{
int
Res
;
assert
(
*
(
p
+
1
)
!=
0
);
Res
=
Nf_StoCheckDsdXor_rec
(
p
,
&
p
,
Dau_DsdComputeMatches
(
p
)
);
// assert( *++p == 0 );
return
Res
;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void
Nf_StoCreateGateNonDsd
(
Nf_Man_t
*
pMan
,
Mio_Cell_t
*
pCell
,
int
**
pComp
,
int
**
pPerm
,
int
*
pnPerms
)
{
int
Perm
[
NF_LEAF_MAX
],
*
Perm1
,
*
Perm2
;
int
nPerms
=
pnPerms
[
pCell
->
nFanins
];
int
nMints
=
(
1
<<
pCell
->
nFanins
);
word
tCur
,
tTemp1
,
tTemp2
;
int
i
,
p
,
c
;
for
(
i
=
0
;
i
<
(
int
)
pCell
->
nFanins
;
i
++
)
Perm
[
i
]
=
Abc_Var2Lit
(
i
,
0
);
tCur
=
tTemp1
=
pCell
->
uTruth
;
for
(
p
=
0
;
p
<
nPerms
;
p
++
)
{
tTemp2
=
tCur
;
for
(
c
=
0
;
c
<
nMints
;
c
++
)
{
Nf_StoCreateGateAdd
(
pMan
,
tCur
,
Perm
,
pCell
->
nFanins
,
pCell
->
Id
,
NF_PRIME
);
// update
tCur
=
Abc_Tt6Flip
(
tCur
,
pComp
[
pCell
->
nFanins
][
c
]
);
Perm1
=
Perm
+
pComp
[
pCell
->
nFanins
][
c
];
*
Perm1
=
Abc_LitNot
(
*
Perm1
);
}
assert
(
tTemp2
==
tCur
);
// update
tCur
=
Abc_Tt6SwapAdjacent
(
tCur
,
pPerm
[
pCell
->
nFanins
][
p
]
);
Perm1
=
Perm
+
pPerm
[
pCell
->
nFanins
][
p
];
Perm2
=
Perm1
+
1
;
ABC_SWAP
(
int
,
*
Perm1
,
*
Perm2
);
}
assert
(
tTemp1
==
tCur
);
}
void
Nf_StoCreateGateDsd
(
Nf_Man_t
*
pMan
,
Mio_Cell_t
*
pCell
,
int
**
pComp
,
int
**
pPerm
,
int
*
pnPerms
)
{
/*
char pDsd[1000];
int i, Value, Perm[NF_LEAF_MAX];
word uTruth = pCell->uTruth;
int nSizeNonDec = Dau_DsdDecompose( &uTruth, pCell->nFanins, 0, 0, pDsd );
assert( pCell->nFanins > 1 );
if ( nSizeNonDec == 0 )
{
if ( Nf_StoCheckDsdAnd(pDsd) )
{
Nf_StoBuildDsdAnd( pMan, pCell, pDsd );
return;
}
Value = Nf_StoCheckDsdXor(pDsd);
if ( Value >= 0 )
{
for ( i = 0; i < (int)pCell->nFanins; i++ )
Perm[i] = Abc_Var2Lit(i, 0);
// Nf_StoSelectSort( Perm, pCell->nFanins, pCell );
Nf_StoCreateGateAdd( pMan, pCell->uTruth, Perm, pCell->nFanins, pCell->Id, NF_XOR );
return;
}
}
*/
Nf_StoCreateGateNonDsd
(
pMan
,
pCell
,
pComp
,
pPerm
,
pnPerms
);
}
void
Nf_StoDeriveMatches
(
Nf_Man_t
*
p
,
int
fVerbose
)
{
// abctime clk = Abc_Clock();
int
*
pComp
[
7
];
int
*
pPerm
[
7
];
int
nPerms
[
7
],
i
;
for
(
i
=
2
;
i
<=
6
;
i
++
)
pComp
[
i
]
=
Extra_GreyCodeSchedule
(
i
);
for
(
i
=
2
;
i
<=
6
;
i
++
)
pPerm
[
i
]
=
Extra_PermSchedule
(
i
);
for
(
i
=
2
;
i
<=
6
;
i
++
)
nPerms
[
i
]
=
Extra_Factorial
(
i
);
p
->
pCells
=
Mio_CollectRootsNewDefault
(
6
,
&
p
->
nCells
,
fVerbose
);
for
(
i
=
4
;
i
<
p
->
nCells
;
i
++
)
Nf_StoCreateGateDsd
(
p
,
p
->
pCells
+
i
,
pComp
,
pPerm
,
nPerms
);
for
(
i
=
2
;
i
<=
6
;
i
++
)
ABC_FREE
(
pComp
[
i
]
);
for
(
i
=
2
;
i
<=
6
;
i
++
)
ABC_FREE
(
pPerm
[
i
]
);
// Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
void
Nf_StoPrintOne
(
Nf_Man_t
*
p
,
int
Count
,
int
t
,
int
i
,
Mio_Cell_t
*
pC
,
int
Type
,
int
fCompl
,
char
*
pInfo
)
{
word
*
pTruth
=
Vec_MemReadEntry
(
p
->
vTtMem
,
t
);
int
k
,
nSuppSize
=
Abc_TtSupportSize
(
pTruth
,
6
);
printf
(
"%6d : "
,
Count
++
);
printf
(
"%6d : "
,
t
);
printf
(
"%6d : "
,
i
/
2
);
printf
(
"Gate %16s "
,
pC
->
pName
);
printf
(
"Inputs = %d "
,
pC
->
nFanins
);
if
(
Type
==
NF_PRIME
)
printf
(
"prime"
);
else
if
(
Type
==
NF_XOR
)
printf
(
"xor "
);
else
if
(
Type
==
NF_ANDOR
)
printf
(
"andor"
);
else
assert
(
0
);
if
(
fCompl
)
printf
(
" compl "
);
else
printf
(
" "
);
if
(
Type
==
NF_PRIME
||
Type
==
NF_XOR
)
{
for
(
k
=
0
;
k
<
(
int
)
pC
->
nFanins
;
k
++
)
{
int
fComplF
=
Abc_LitIsCompl
((
int
)
pInfo
[
k
]);
int
iFanin
=
Abc_Lit2Var
((
int
)
pInfo
[
k
]);
printf
(
"%c"
,
'a'
+
iFanin
-
fComplF
*
(
'a'
-
'A'
)
);
}
}
else
if
(
Type
==
NF_ANDOR
)
{
int
g
,
nGroups
=
(
int
)
*
pInfo
++
;
for
(
g
=
0
;
g
<
nGroups
;
g
++
)
{
int
nSizeAll
=
(
int
)
*
pInfo
++
;
int
nSizeNeg
=
(
int
)
*
pInfo
++
;
printf
(
"{"
);
for
(
k
=
0
;
k
<
nSizeAll
;
k
++
)
{
int
fComplF
=
Abc_LitIsCompl
((
int
)
pInfo
[
k
]);
int
iFanin
=
Abc_Lit2Var
((
int
)
pInfo
[
k
]);
printf
(
"%c"
,
'a'
+
iFanin
-
fComplF
*
(
'a'
-
'A'
)
);
}
printf
(
"}"
);
pInfo
+=
nSizeAll
;
}
}
else
assert
(
0
);
printf
(
" "
);
Dau_DsdPrintFromTruth
(
pTruth
,
nSuppSize
);
}
void
Nf_StoPrint
(
Nf_Man_t
*
p
,
int
fVerbose
)
{
int
t
,
i
,
Info
,
Offset
,
Count
=
0
,
CountMux
=
0
;
for
(
t
=
2
;
t
<
Vec_WecSize
(
p
->
vTt2Match
);
t
++
)
{
Vec_Int_t
*
vArr
=
Vec_WecEntry
(
p
->
vTt2Match
,
t
);
Vec_IntForEachEntryDouble
(
vArr
,
Info
,
Offset
,
i
)
{
Mio_Cell_t
*
pC
=
p
->
pCells
+
(
Info
>>
8
);
int
Type
=
(
Info
>>
4
)
&
15
;
int
fCompl
=
(
Info
&
1
);
char
*
pInfo
=
Vec_StrEntryP
(
p
->
vMemStore
,
Offset
);
if
(
Type
==
NF_PRIME
&&
pC
->
nFanins
!=
3
)
{
Count
++
;
CountMux
++
;
continue
;
}
if
(
!
fVerbose
)
{
Count
++
;
continue
;
}
Nf_StoPrintOne
(
p
,
Count
,
t
,
i
,
pC
,
Type
,
fCompl
,
pInfo
);
}
}
printf
(
"Gates = %d. Truths = %d. Matches = %d. MatchesPrime = %d. Size = %d.
\n
"
,
p
->
nCells
,
Vec_MemEntryNum
(
p
->
vTtMem
),
Count
,
CountMux
,
Vec_StrSize
(
p
->
vMemStore
)
);
}
/*
void Nf_ManPrepareLibraryTest()
{
int fVerbose = 0;
abctime clk = Abc_Clock();
Nf_Man_t * p;
p = Nf_StoCreate( NULL, NULL, fVerbose );
Nf_StoPrint( p, fVerbose );
Nf_StoDelete(p);
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
*/
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Nf_Man_t
*
Nf_StoCreate
(
Gia_Man_t
*
pGia
,
Jf_Par_t
*
pPars
)
{
extern
void
Mf_ManSetFlowRefs
(
Gia_Man_t
*
p
,
Vec_Int_t
*
vRefs
);
Vec_Int_t
*
vFlowRefs
;
Nf_Man_t
*
p
;
int
i
,
Entry
;
assert
(
pPars
->
nCutNum
>
1
&&
pPars
->
nCutNum
<=
NF_CUT_MAX
);
assert
(
pPars
->
nLutSize
>
1
&&
pPars
->
nLutSize
<=
NF_LEAF_MAX
);
ABC_FREE
(
pGia
->
pRefs
);
Vec_IntFreeP
(
&
pGia
->
vCellMapping
);
if
(
Gia_ManHasChoices
(
pGia
)
)
Gia_ManSetPhase
(
pGia
);
// create
p
=
ABC_CALLOC
(
Nf_Man_t
,
1
);
p
->
clkStart
=
Abc_Clock
();
p
->
pGia
=
pGia
;
p
->
pPars
=
pPars
;
p
->
pNfObjs
=
ABC_CALLOC
(
Nf_Obj_t
,
Gia_ManObjNum
(
pGia
)
);
p
->
iCur
=
2
;
// other
Vec_PtrGrow
(
&
p
->
vPages
,
256
);
// cut memory
Vec_IntFill
(
&
p
->
vMapRefs
,
2
*
Gia_ManObjNum
(
pGia
),
0
);
// mapping refs (2x)
Vec_FltFill
(
&
p
->
vFlowRefs
,
2
*
Gia_ManObjNum
(
pGia
),
0
);
// flow refs (2x)
Vec_FltFill
(
&
p
->
vRequired
,
2
*
Gia_ManObjNum
(
pGia
),
NF_INFINITY
);
// required times (2x)
Vec_IntFill
(
&
p
->
vCutSets
,
Gia_ManObjNum
(
pGia
),
0
);
// cut offsets
Vec_FltFill
(
&
p
->
vCutFlows
,
Gia_ManObjNum
(
pGia
),
0
);
// cut area
Vec_IntFill
(
&
p
->
vCutDelays
,
Gia_ManObjNum
(
pGia
),
0
);
// cut delay
Vec_IntGrow
(
&
p
->
vBackup
,
1000
);
Vec_IntGrow
(
&
p
->
vBackup2
,
1000
);
// references
vFlowRefs
=
Vec_IntAlloc
(
0
);
Mf_ManSetFlowRefs
(
pGia
,
vFlowRefs
);
Vec_IntForEachEntry
(
vFlowRefs
,
Entry
,
i
)
{
Vec_FltWriteEntry
(
&
p
->
vFlowRefs
,
2
*
i
,
/*0.5* */
Entry
);
Vec_FltWriteEntry
(
&
p
->
vFlowRefs
,
2
*
i
+
1
,
/*0.5* */
Entry
);
}
Vec_IntFree
(
vFlowRefs
);
// matching
p
->
vTtMem
=
Vec_MemAllocForTT
(
6
,
0
);
p
->
vTt2Match
=
Vec_WecAlloc
(
1000
);
p
->
vMemStore
=
Vec_StrAlloc
(
10000
);
Vec_WecPushLevel
(
p
->
vTt2Match
);
Vec_WecPushLevel
(
p
->
vTt2Match
);
assert
(
Vec_WecSize
(
p
->
vTt2Match
)
==
Vec_MemEntryNum
(
p
->
vTtMem
)
);
Nf_StoDeriveMatches
(
p
,
0
);
//pPars->fVerbose );
p
->
InvDelay
=
p
->
pCells
[
3
].
Delays
[
0
];
p
->
InvArea
=
p
->
pCells
[
3
].
Area
;
Nf_ObjMatchD
(
p
,
0
,
0
)
->
Gate
=
0
;
Nf_ObjMatchD
(
p
,
0
,
1
)
->
Gate
=
1
;
// prepare cuts
return
p
;
}
void
Nf_StoDelete
(
Nf_Man_t
*
p
)
{
Vec_PtrFreeData
(
&
p
->
vPages
);
ABC_FREE
(
p
->
vPages
.
pArray
);
ABC_FREE
(
p
->
vMapRefs
.
pArray
);
ABC_FREE
(
p
->
vFlowRefs
.
pArray
);
ABC_FREE
(
p
->
vRequired
.
pArray
);
ABC_FREE
(
p
->
vCutSets
.
pArray
);
ABC_FREE
(
p
->
vCutFlows
.
pArray
);
ABC_FREE
(
p
->
vCutDelays
.
pArray
);
ABC_FREE
(
p
->
vBackup
.
pArray
);
ABC_FREE
(
p
->
vBackup2
.
pArray
);
ABC_FREE
(
p
->
pNfObjs
);
// matching
Vec_WecFree
(
p
->
vTt2Match
);
Vec_MemHashFree
(
p
->
vTtMem
);
Vec_MemFree
(
p
->
vTtMem
);
Vec_StrFree
(
p
->
vMemStore
);
ABC_FREE
(
p
->
pCells
);
ABC_FREE
(
p
);
}
/**Function*************************************************************
Synopsis []
Description []
...
...
@@ -41,12 +701,1845 @@ ABC_NAMESPACE_IMPL_START
SeeAlso []
***********************************************************************/
static
inline
int
Nf_CutComputeTruth6
(
Nf_Man_t
*
p
,
Nf_Cut_t
*
pCut0
,
Nf_Cut_t
*
pCut1
,
int
fCompl0
,
int
fCompl1
,
Nf_Cut_t
*
pCutR
,
int
fIsXor
)
{
// extern int Nf_ManTruthCanonicize( word * t, int nVars );
int
nOldSupp
=
pCutR
->
nLeaves
,
truthId
,
fCompl
;
word
t
;
word
t0
=
*
Vec_MemReadEntry
(
p
->
vTtMem
,
Abc_Lit2Var
(
pCut0
->
iFunc
));
word
t1
=
*
Vec_MemReadEntry
(
p
->
vTtMem
,
Abc_Lit2Var
(
pCut1
->
iFunc
));
if
(
Abc_LitIsCompl
(
pCut0
->
iFunc
)
^
fCompl0
)
t0
=
~
t0
;
if
(
Abc_LitIsCompl
(
pCut1
->
iFunc
)
^
fCompl1
)
t1
=
~
t1
;
t0
=
Abc_Tt6Expand
(
t0
,
pCut0
->
pLeaves
,
pCut0
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
t1
=
Abc_Tt6Expand
(
t1
,
pCut1
->
pLeaves
,
pCut1
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
t
=
fIsXor
?
t0
^
t1
:
t0
&
t1
;
if
(
(
fCompl
=
(
int
)(
t
&
1
))
)
t
=
~
t
;
pCutR
->
nLeaves
=
Abc_Tt6MinBase
(
&
t
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
assert
(
(
int
)(
t
&
1
)
==
0
);
truthId
=
Vec_MemHashInsert
(
p
->
vTtMem
,
&
t
);
pCutR
->
iFunc
=
Abc_Var2Lit
(
truthId
,
fCompl
);
pCutR
->
Useless
=
Nf_ObjCutUseless
(
p
,
truthId
);
assert
(
(
int
)
pCutR
->
nLeaves
<=
nOldSupp
);
return
(
int
)
pCutR
->
nLeaves
<
nOldSupp
;
}
static
inline
int
Nf_CutComputeTruthMux6
(
Nf_Man_t
*
p
,
Nf_Cut_t
*
pCut0
,
Nf_Cut_t
*
pCut1
,
Nf_Cut_t
*
pCutC
,
int
fCompl0
,
int
fCompl1
,
int
fComplC
,
Nf_Cut_t
*
pCutR
)
{
int
nOldSupp
=
pCutR
->
nLeaves
,
truthId
,
fCompl
;
word
t
;
word
t0
=
*
Vec_MemReadEntry
(
p
->
vTtMem
,
Abc_Lit2Var
(
pCut0
->
iFunc
));
word
t1
=
*
Vec_MemReadEntry
(
p
->
vTtMem
,
Abc_Lit2Var
(
pCut1
->
iFunc
));
word
tC
=
*
Vec_MemReadEntry
(
p
->
vTtMem
,
Abc_Lit2Var
(
pCutC
->
iFunc
));
if
(
Abc_LitIsCompl
(
pCut0
->
iFunc
)
^
fCompl0
)
t0
=
~
t0
;
if
(
Abc_LitIsCompl
(
pCut1
->
iFunc
)
^
fCompl1
)
t1
=
~
t1
;
if
(
Abc_LitIsCompl
(
pCutC
->
iFunc
)
^
fComplC
)
tC
=
~
tC
;
t0
=
Abc_Tt6Expand
(
t0
,
pCut0
->
pLeaves
,
pCut0
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
t1
=
Abc_Tt6Expand
(
t1
,
pCut1
->
pLeaves
,
pCut1
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
tC
=
Abc_Tt6Expand
(
tC
,
pCutC
->
pLeaves
,
pCutC
->
nLeaves
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
t
=
(
tC
&
t1
)
|
(
~
tC
&
t0
);
if
(
(
fCompl
=
(
int
)(
t
&
1
))
)
t
=
~
t
;
pCutR
->
nLeaves
=
Abc_Tt6MinBase
(
&
t
,
pCutR
->
pLeaves
,
pCutR
->
nLeaves
);
assert
(
(
int
)(
t
&
1
)
==
0
);
truthId
=
Vec_MemHashInsert
(
p
->
vTtMem
,
&
t
);
pCutR
->
iFunc
=
Abc_Var2Lit
(
truthId
,
fCompl
);
pCutR
->
Useless
=
Nf_ObjCutUseless
(
p
,
truthId
);
assert
(
(
int
)
pCutR
->
nLeaves
<=
nOldSupp
);
return
(
int
)
pCutR
->
nLeaves
<
nOldSupp
;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Nf_CutCountBits
(
word
i
)
{
i
=
i
-
((
i
>>
1
)
&
0x5555555555555555
);
i
=
(
i
&
0x3333333333333333
)
+
((
i
>>
2
)
&
0x3333333333333333
);
i
=
((
i
+
(
i
>>
4
))
&
0x0F0F0F0F0F0F0F0F
);
return
(
i
*
(
0x0101010101010101
))
>>
56
;
}
static
inline
word
Nf_CutGetSign
(
int
*
pLeaves
,
int
nLeaves
)
{
word
Sign
=
0
;
int
i
;
for
(
i
=
0
;
i
<
nLeaves
;
i
++
)
Sign
|=
((
word
)
1
)
<<
(
pLeaves
[
i
]
&
0x3F
);
return
Sign
;
}
static
inline
int
Nf_CutCreateUnit
(
Nf_Cut_t
*
p
,
int
i
)
{
p
->
Delay
=
0
;
p
->
Flow
=
0
;
p
->
iFunc
=
2
;
p
->
nLeaves
=
1
;
p
->
pLeaves
[
0
]
=
i
;
p
->
Sign
=
((
word
)
1
)
<<
(
i
&
0x3F
);
return
1
;
}
static
inline
void
Nf_Cutprintf
(
Nf_Man_t
*
p
,
Nf_Cut_t
*
pCut
)
{
int
i
,
nDigits
=
Abc_Base10Log
(
Gia_ManObjNum
(
p
->
pGia
));
printf
(
"%d {"
,
pCut
->
nLeaves
);
for
(
i
=
0
;
i
<
(
int
)
pCut
->
nLeaves
;
i
++
)
printf
(
" %*d"
,
nDigits
,
pCut
->
pLeaves
[
i
]
);
for
(
;
i
<
(
int
)
p
->
pPars
->
nLutSize
;
i
++
)
printf
(
" %*s"
,
nDigits
,
" "
);
printf
(
" } Useless = %d. D = %4d A = %9.4f F = %6d "
,
pCut
->
Useless
,
pCut
->
Delay
,
pCut
->
Flow
,
pCut
->
iFunc
);
if
(
p
->
vTtMem
)
Dau_DsdPrintFromTruth
(
Vec_MemReadEntry
(
p
->
vTtMem
,
Abc_Lit2Var
(
pCut
->
iFunc
)),
pCut
->
nLeaves
);
else
printf
(
"
\n
"
);
}
static
inline
int
Nf_ManPrepareCuts
(
Nf_Cut_t
*
pCuts
,
Nf_Man_t
*
p
,
int
iObj
,
int
fAddUnit
)
{
if
(
Nf_ObjHasCuts
(
p
,
iObj
)
)
{
Nf_Cut_t
*
pMfCut
=
pCuts
;
int
i
,
*
pCut
,
*
pList
=
Nf_ObjCutSet
(
p
,
iObj
);
Nf_SetForEachCut
(
pList
,
pCut
,
i
)
{
pMfCut
->
Delay
=
0
;
pMfCut
->
Flow
=
0
;
pMfCut
->
iFunc
=
Nf_CutFunc
(
pCut
);
pMfCut
->
nLeaves
=
Nf_CutSize
(
pCut
);
pMfCut
->
Sign
=
Nf_CutGetSign
(
pCut
+
1
,
Nf_CutSize
(
pCut
)
);
memcpy
(
pMfCut
->
pLeaves
,
pCut
+
1
,
sizeof
(
int
)
*
Nf_CutSize
(
pCut
)
);
pMfCut
++
;
}
if
(
fAddUnit
&&
pCuts
->
nLeaves
>
1
)
return
pList
[
0
]
+
Nf_CutCreateUnit
(
pMfCut
,
iObj
);
return
pList
[
0
];
}
return
Nf_CutCreateUnit
(
pCuts
,
iObj
);
}
static
inline
int
Nf_ManSaveCuts
(
Nf_Man_t
*
p
,
Nf_Cut_t
**
pCuts
,
int
nCuts
,
int
fUseful
)
{
int
i
,
*
pPlace
,
iCur
,
nInts
=
1
,
nCutsNew
=
0
;
for
(
i
=
0
;
i
<
nCuts
;
i
++
)
if
(
!
fUseful
||
!
pCuts
[
i
]
->
Useless
)
nInts
+=
pCuts
[
i
]
->
nLeaves
+
1
,
nCutsNew
++
;
if
(
(
p
->
iCur
&
0xFFFF
)
+
nInts
>
0xFFFF
)
p
->
iCur
=
((
p
->
iCur
>>
16
)
+
1
)
<<
16
;
if
(
Vec_PtrSize
(
&
p
->
vPages
)
==
(
p
->
iCur
>>
16
)
)
Vec_PtrPush
(
&
p
->
vPages
,
ABC_ALLOC
(
int
,
(
1
<<
16
))
);
iCur
=
p
->
iCur
;
p
->
iCur
+=
nInts
;
pPlace
=
Nf_ManCutSet
(
p
,
iCur
);
*
pPlace
++
=
nCutsNew
;
for
(
i
=
0
;
i
<
nCuts
;
i
++
)
if
(
!
fUseful
||
!
pCuts
[
i
]
->
Useless
)
{
*
pPlace
++
=
Nf_CutSetBoth
(
pCuts
[
i
]
->
nLeaves
,
pCuts
[
i
]
->
iFunc
);
memcpy
(
pPlace
,
pCuts
[
i
]
->
pLeaves
,
sizeof
(
int
)
*
pCuts
[
i
]
->
nLeaves
);
pPlace
+=
pCuts
[
i
]
->
nLeaves
;
}
return
iCur
;
}
static
inline
int
Nf_ManCountUseful
(
Nf_Cut_t
**
pCuts
,
int
nCuts
)
{
int
i
,
Count
=
0
;
for
(
i
=
0
;
i
<
nCuts
;
i
++
)
Count
+=
!
pCuts
[
i
]
->
Useless
;
return
Count
;
}
static
inline
int
Nf_ManCountMatches
(
Nf_Man_t
*
p
,
Nf_Cut_t
**
pCuts
,
int
nCuts
)
{
int
i
,
Count
=
0
;
for
(
i
=
0
;
i
<
nCuts
;
i
++
)
if
(
!
pCuts
[
i
]
->
Useless
)
Count
+=
Vec_IntSize
(
Vec_WecEntry
(
p
->
vTt2Match
,
Abc_Lit2Var
(
pCuts
[
i
]
->
iFunc
)))
/
2
;
return
Count
;
}
/**Function*************************************************************
Synopsis [Check correctness of cuts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Nf_CutCheck
(
Nf_Cut_t
*
pBase
,
Nf_Cut_t
*
pCut
)
// check if pCut is contained in pBase
{
int
nSizeB
=
pBase
->
nLeaves
;
int
nSizeC
=
pCut
->
nLeaves
;
int
i
,
*
pB
=
pBase
->
pLeaves
;
int
k
,
*
pC
=
pCut
->
pLeaves
;
for
(
i
=
0
;
i
<
nSizeC
;
i
++
)
{
for
(
k
=
0
;
k
<
nSizeB
;
k
++
)
if
(
pC
[
i
]
==
pB
[
k
]
)
break
;
if
(
k
==
nSizeB
)
return
0
;
}
return
1
;
}
static
inline
int
Nf_SetCheckArray
(
Nf_Cut_t
**
ppCuts
,
int
nCuts
)
{
Nf_Cut_t
*
pCut0
,
*
pCut1
;
int
i
,
k
,
m
,
n
,
Value
;
assert
(
nCuts
>
0
);
for
(
i
=
0
;
i
<
nCuts
;
i
++
)
{
pCut0
=
ppCuts
[
i
];
assert
(
pCut0
->
nLeaves
<=
NF_LEAF_MAX
);
assert
(
pCut0
->
Sign
==
Nf_CutGetSign
(
pCut0
->
pLeaves
,
pCut0
->
nLeaves
)
);
// check duplicates
for
(
m
=
0
;
m
<
(
int
)
pCut0
->
nLeaves
;
m
++
)
for
(
n
=
m
+
1
;
n
<
(
int
)
pCut0
->
nLeaves
;
n
++
)
assert
(
pCut0
->
pLeaves
[
m
]
<
pCut0
->
pLeaves
[
n
]
);
// check pairs
for
(
k
=
0
;
k
<
nCuts
;
k
++
)
{
pCut1
=
ppCuts
[
k
];
if
(
pCut0
==
pCut1
)
continue
;
// check containments
Value
=
Nf_CutCheck
(
pCut0
,
pCut1
);
assert
(
Value
==
0
);
}
}
return
1
;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Nf_CutMergeOrder
(
Nf_Cut_t
*
pCut0
,
Nf_Cut_t
*
pCut1
,
Nf_Cut_t
*
pCut
,
int
nLutSize
)
{
int
nSize0
=
pCut0
->
nLeaves
;
int
nSize1
=
pCut1
->
nLeaves
;
int
i
,
*
pC0
=
pCut0
->
pLeaves
;
int
k
,
*
pC1
=
pCut1
->
pLeaves
;
int
c
,
*
pC
=
pCut
->
pLeaves
;
// the case of the largest cut sizes
if
(
nSize0
==
nLutSize
&&
nSize1
==
nLutSize
)
{
for
(
i
=
0
;
i
<
nSize0
;
i
++
)
{
if
(
pC0
[
i
]
!=
pC1
[
i
]
)
return
0
;
pC
[
i
]
=
pC0
[
i
];
}
pCut
->
nLeaves
=
nLutSize
;
pCut
->
iFunc
=
-
1
;
pCut
->
Sign
=
pCut0
->
Sign
|
pCut1
->
Sign
;
return
1
;
}
// compare two cuts with different numbers
i
=
k
=
c
=
0
;
if
(
nSize0
==
0
)
goto
FlushCut1
;
if
(
nSize1
==
0
)
goto
FlushCut0
;
while
(
1
)
{
if
(
c
==
nLutSize
)
return
0
;
if
(
pC0
[
i
]
<
pC1
[
k
]
)
{
pC
[
c
++
]
=
pC0
[
i
++
];
if
(
i
>=
nSize0
)
goto
FlushCut1
;
}
else
if
(
pC0
[
i
]
>
pC1
[
k
]
)
{
pC
[
c
++
]
=
pC1
[
k
++
];
if
(
k
>=
nSize1
)
goto
FlushCut0
;
}
else
{
pC
[
c
++
]
=
pC0
[
i
++
];
k
++
;
if
(
i
>=
nSize0
)
goto
FlushCut1
;
if
(
k
>=
nSize1
)
goto
FlushCut0
;
}
}
FlushCut0:
if
(
c
+
nSize0
>
nLutSize
+
i
)
return
0
;
while
(
i
<
nSize0
)
pC
[
c
++
]
=
pC0
[
i
++
];
pCut
->
nLeaves
=
c
;
pCut
->
iFunc
=
-
1
;
pCut
->
Sign
=
pCut0
->
Sign
|
pCut1
->
Sign
;
return
1
;
FlushCut1:
if
(
c
+
nSize1
>
nLutSize
+
k
)
return
0
;
while
(
k
<
nSize1
)
pC
[
c
++
]
=
pC1
[
k
++
];
pCut
->
nLeaves
=
c
;
pCut
->
iFunc
=
-
1
;
pCut
->
Sign
=
pCut0
->
Sign
|
pCut1
->
Sign
;
return
1
;
}
static
inline
int
Nf_CutMergeOrderMux
(
Nf_Cut_t
*
pCut0
,
Nf_Cut_t
*
pCut1
,
Nf_Cut_t
*
pCut2
,
Nf_Cut_t
*
pCut
,
int
nLutSize
)
{
int
x0
,
i0
=
0
,
nSize0
=
pCut0
->
nLeaves
,
*
pC0
=
pCut0
->
pLeaves
;
int
x1
,
i1
=
0
,
nSize1
=
pCut1
->
nLeaves
,
*
pC1
=
pCut1
->
pLeaves
;
int
x2
,
i2
=
0
,
nSize2
=
pCut2
->
nLeaves
,
*
pC2
=
pCut2
->
pLeaves
;
int
xMin
,
c
=
0
,
*
pC
=
pCut
->
pLeaves
;
while
(
1
)
{
x0
=
(
i0
==
nSize0
)
?
ABC_INFINITY
:
pC0
[
i0
];
x1
=
(
i1
==
nSize1
)
?
ABC_INFINITY
:
pC1
[
i1
];
x2
=
(
i2
==
nSize2
)
?
ABC_INFINITY
:
pC2
[
i2
];
xMin
=
Abc_MinInt
(
Abc_MinInt
(
x0
,
x1
),
x2
);
if
(
xMin
==
ABC_INFINITY
)
break
;
if
(
c
==
nLutSize
)
return
0
;
pC
[
c
++
]
=
xMin
;
if
(
x0
==
xMin
)
i0
++
;
if
(
x1
==
xMin
)
i1
++
;
if
(
x2
==
xMin
)
i2
++
;
}
pCut
->
nLeaves
=
c
;
pCut
->
iFunc
=
-
1
;
pCut
->
Sign
=
pCut0
->
Sign
|
pCut1
->
Sign
|
pCut2
->
Sign
;
return
1
;
}
static
inline
int
Nf_SetCutIsContainedOrder
(
Nf_Cut_t
*
pBase
,
Nf_Cut_t
*
pCut
)
// check if pCut is contained in pBase
{
int
i
,
nSizeB
=
pBase
->
nLeaves
;
int
k
,
nSizeC
=
pCut
->
nLeaves
;
if
(
nSizeB
==
nSizeC
)
{
for
(
i
=
0
;
i
<
nSizeB
;
i
++
)
if
(
pBase
->
pLeaves
[
i
]
!=
pCut
->
pLeaves
[
i
]
)
return
0
;
return
1
;
}
assert
(
nSizeB
>
nSizeC
);
if
(
nSizeC
==
0
)
return
1
;
for
(
i
=
k
=
0
;
i
<
nSizeB
;
i
++
)
{
if
(
pBase
->
pLeaves
[
i
]
>
pCut
->
pLeaves
[
k
]
)
return
0
;
if
(
pBase
->
pLeaves
[
i
]
==
pCut
->
pLeaves
[
k
]
)
{
if
(
++
k
==
nSizeC
)
return
1
;
}
}
return
0
;
}
static
inline
int
Nf_SetLastCutIsContained
(
Nf_Cut_t
**
pCuts
,
int
nCuts
)
{
int
i
;
for
(
i
=
0
;
i
<
nCuts
;
i
++
)
if
(
pCuts
[
i
]
->
nLeaves
<=
pCuts
[
nCuts
]
->
nLeaves
&&
(
pCuts
[
i
]
->
Sign
&
pCuts
[
nCuts
]
->
Sign
)
==
pCuts
[
i
]
->
Sign
&&
Nf_SetCutIsContainedOrder
(
pCuts
[
nCuts
],
pCuts
[
i
])
)
return
1
;
return
0
;
}
static
inline
int
Nf_SetLastCutContainsArea
(
Nf_Cut_t
**
pCuts
,
int
nCuts
)
{
int
i
,
k
,
fChanges
=
0
;
for
(
i
=
0
;
i
<
nCuts
;
i
++
)
if
(
pCuts
[
nCuts
]
->
nLeaves
<
pCuts
[
i
]
->
nLeaves
&&
(
pCuts
[
nCuts
]
->
Sign
&
pCuts
[
i
]
->
Sign
)
==
pCuts
[
nCuts
]
->
Sign
&&
Nf_SetCutIsContainedOrder
(
pCuts
[
i
],
pCuts
[
nCuts
])
)
pCuts
[
i
]
->
nLeaves
=
NF_NO_LEAF
,
fChanges
=
1
;
if
(
!
fChanges
)
return
nCuts
;
for
(
i
=
k
=
0
;
i
<=
nCuts
;
i
++
)
{
if
(
pCuts
[
i
]
->
nLeaves
==
NF_NO_LEAF
)
continue
;
if
(
k
<
i
)
ABC_SWAP
(
Nf_Cut_t
*
,
pCuts
[
k
],
pCuts
[
i
]
);
k
++
;
}
return
k
-
1
;
}
static
inline
int
Nf_CutCompareArea
(
Nf_Cut_t
*
pCut0
,
Nf_Cut_t
*
pCut1
)
{
if
(
pCut0
->
Useless
<
pCut1
->
Useless
)
return
-
1
;
if
(
pCut0
->
Useless
>
pCut1
->
Useless
)
return
1
;
if
(
pCut0
->
Flow
<
pCut1
->
Flow
)
return
-
1
;
if
(
pCut0
->
Flow
>
pCut1
->
Flow
)
return
1
;
if
(
pCut0
->
Delay
<
pCut1
->
Delay
)
return
-
1
;
if
(
pCut0
->
Delay
>
pCut1
->
Delay
)
return
1
;
if
(
pCut0
->
nLeaves
<
pCut1
->
nLeaves
)
return
-
1
;
if
(
pCut0
->
nLeaves
>
pCut1
->
nLeaves
)
return
1
;
return
0
;
}
static
inline
void
Nf_SetSortByArea
(
Nf_Cut_t
**
pCuts
,
int
nCuts
)
{
int
i
;
for
(
i
=
nCuts
;
i
>
0
;
i
--
)
{
if
(
Nf_CutCompareArea
(
pCuts
[
i
-
1
],
pCuts
[
i
])
<
0
)
//!= 1 )
return
;
ABC_SWAP
(
Nf_Cut_t
*
,
pCuts
[
i
-
1
],
pCuts
[
i
]
);
}
}
static
inline
int
Nf_SetAddCut
(
Nf_Cut_t
**
pCuts
,
int
nCuts
,
int
nCutNum
)
{
if
(
nCuts
==
0
)
return
1
;
nCuts
=
Nf_SetLastCutContainsArea
(
pCuts
,
nCuts
);
Nf_SetSortByArea
(
pCuts
,
nCuts
);
return
Abc_MinInt
(
nCuts
+
1
,
nCutNum
-
1
);
}
static
inline
int
Nf_CutArea
(
Nf_Man_t
*
p
,
int
nLeaves
)
{
if
(
nLeaves
<
2
)
return
0
;
return
nLeaves
+
p
->
pPars
->
nAreaTuner
;
}
static
inline
void
Nf_CutParams
(
Nf_Man_t
*
p
,
Nf_Cut_t
*
pCut
,
float
FlowRefs
)
{
int
i
,
nLeaves
=
pCut
->
nLeaves
;
assert
(
nLeaves
<=
p
->
pPars
->
nLutSize
);
pCut
->
Delay
=
0
;
pCut
->
Flow
=
0
;
for
(
i
=
0
;
i
<
nLeaves
;
i
++
)
{
pCut
->
Delay
=
Abc_MaxInt
(
pCut
->
Delay
,
Nf_ObjCutDelay
(
p
,
pCut
->
pLeaves
[
i
])
);
pCut
->
Flow
+=
Nf_ObjCutFlow
(
p
,
pCut
->
pLeaves
[
i
]);
}
pCut
->
Delay
+=
(
int
)(
nLeaves
>
1
);
pCut
->
Flow
=
(
pCut
->
Flow
+
Nf_CutArea
(
p
,
nLeaves
))
/
FlowRefs
;
}
void
Nf_ObjMergeOrder
(
Nf_Man_t
*
p
,
int
iObj
)
{
Nf_Cut_t
pCuts0
[
NF_CUT_MAX
],
pCuts1
[
NF_CUT_MAX
],
pCuts
[
NF_CUT_MAX
],
*
pCutsR
[
NF_CUT_MAX
];
Gia_Obj_t
*
pObj
=
Gia_ManObj
(
p
->
pGia
,
iObj
);
Nf_Obj_t
*
pBest
=
Nf_ManObj
(
p
,
iObj
);
float
dFlowRefs
=
Nf_ObjFlowRefs
(
p
,
iObj
,
0
)
+
Nf_ObjFlowRefs
(
p
,
iObj
,
1
);
int
nLutSize
=
p
->
pPars
->
nLutSize
;
int
nCutNum
=
p
->
pPars
->
nCutNum
;
int
nCuts0
=
Nf_ManPrepareCuts
(
pCuts0
,
p
,
Gia_ObjFaninId0
(
pObj
,
iObj
),
1
);
int
nCuts1
=
Nf_ManPrepareCuts
(
pCuts1
,
p
,
Gia_ObjFaninId1
(
pObj
,
iObj
),
1
);
int
fComp0
=
Gia_ObjFaninC0
(
pObj
);
int
fComp1
=
Gia_ObjFaninC1
(
pObj
);
int
iSibl
=
Gia_ObjSibl
(
p
->
pGia
,
iObj
);
Nf_Cut_t
*
pCut0
,
*
pCut1
,
*
pCut0Lim
=
pCuts0
+
nCuts0
,
*
pCut1Lim
=
pCuts1
+
nCuts1
;
int
i
,
nCutsUse
,
nCutsR
=
0
;
assert
(
!
Gia_ObjIsBuf
(
pObj
)
);
for
(
i
=
0
;
i
<
nCutNum
;
i
++
)
pCutsR
[
i
]
=
pCuts
+
i
;
if
(
iSibl
)
{
Nf_Cut_t
pCuts2
[
NF_CUT_MAX
];
Gia_Obj_t
*
pObjE
=
Gia_ObjSiblObj
(
p
->
pGia
,
iObj
);
int
fCompE
=
Gia_ObjPhase
(
pObj
)
^
Gia_ObjPhase
(
pObjE
);
int
nCuts2
=
Nf_ManPrepareCuts
(
pCuts2
,
p
,
iSibl
,
0
);
Nf_Cut_t
*
pCut2
,
*
pCut2Lim
=
pCuts2
+
nCuts2
;
for
(
pCut2
=
pCuts2
;
pCut2
<
pCut2Lim
;
pCut2
++
)
{
*
pCutsR
[
nCutsR
]
=
*
pCut2
;
pCutsR
[
nCutsR
]
->
iFunc
=
Abc_LitNotCond
(
pCutsR
[
nCutsR
]
->
iFunc
,
fCompE
);
Nf_CutParams
(
p
,
pCutsR
[
nCutsR
],
dFlowRefs
);
nCutsR
=
Nf_SetAddCut
(
pCutsR
,
nCutsR
,
nCutNum
);
}
}
if
(
Gia_ObjIsMuxId
(
p
->
pGia
,
iObj
)
)
{
Nf_Cut_t
pCuts2
[
NF_CUT_MAX
];
int
nCuts2
=
Nf_ManPrepareCuts
(
pCuts2
,
p
,
Gia_ObjFaninId2
(
p
->
pGia
,
iObj
),
1
);
int
fComp2
=
Gia_ObjFaninC2
(
p
->
pGia
,
pObj
);
Nf_Cut_t
*
pCut2
,
*
pCut2Lim
=
pCuts2
+
nCuts2
;
p
->
CutCount
[
0
]
+=
nCuts0
*
nCuts1
*
nCuts2
;
for
(
pCut0
=
pCuts0
;
pCut0
<
pCut0Lim
;
pCut0
++
)
for
(
pCut1
=
pCuts1
;
pCut1
<
pCut1Lim
;
pCut1
++
)
for
(
pCut2
=
pCuts2
;
pCut2
<
pCut2Lim
;
pCut2
++
)
{
if
(
Nf_CutCountBits
(
pCut0
->
Sign
|
pCut1
->
Sign
|
pCut2
->
Sign
)
>
nLutSize
)
continue
;
p
->
CutCount
[
1
]
++
;
if
(
!
Nf_CutMergeOrderMux
(
pCut0
,
pCut1
,
pCut2
,
pCutsR
[
nCutsR
],
nLutSize
)
)
continue
;
if
(
Nf_SetLastCutIsContained
(
pCutsR
,
nCutsR
)
)
continue
;
p
->
CutCount
[
2
]
++
;
if
(
Nf_CutComputeTruthMux6
(
p
,
pCut0
,
pCut1
,
pCut2
,
fComp0
,
fComp1
,
fComp2
,
pCutsR
[
nCutsR
])
)
pCutsR
[
nCutsR
]
->
Sign
=
Nf_CutGetSign
(
pCutsR
[
nCutsR
]
->
pLeaves
,
pCutsR
[
nCutsR
]
->
nLeaves
);
Nf_CutParams
(
p
,
pCutsR
[
nCutsR
],
dFlowRefs
);
nCutsR
=
Nf_SetAddCut
(
pCutsR
,
nCutsR
,
nCutNum
);
}
}
else
{
int
fIsXor
=
Gia_ObjIsXor
(
pObj
);
p
->
CutCount
[
0
]
+=
nCuts0
*
nCuts1
;
for
(
pCut0
=
pCuts0
;
pCut0
<
pCut0Lim
;
pCut0
++
)
for
(
pCut1
=
pCuts1
;
pCut1
<
pCut1Lim
;
pCut1
++
)
{
if
(
(
int
)(
pCut0
->
nLeaves
+
pCut1
->
nLeaves
)
>
nLutSize
&&
Nf_CutCountBits
(
pCut0
->
Sign
|
pCut1
->
Sign
)
>
nLutSize
)
continue
;
p
->
CutCount
[
1
]
++
;
if
(
!
Nf_CutMergeOrder
(
pCut0
,
pCut1
,
pCutsR
[
nCutsR
],
nLutSize
)
)
continue
;
if
(
Nf_SetLastCutIsContained
(
pCutsR
,
nCutsR
)
)
continue
;
p
->
CutCount
[
2
]
++
;
if
(
Nf_CutComputeTruth6
(
p
,
pCut0
,
pCut1
,
fComp0
,
fComp1
,
pCutsR
[
nCutsR
],
fIsXor
)
)
pCutsR
[
nCutsR
]
->
Sign
=
Nf_CutGetSign
(
pCutsR
[
nCutsR
]
->
pLeaves
,
pCutsR
[
nCutsR
]
->
nLeaves
);
Nf_CutParams
(
p
,
pCutsR
[
nCutsR
],
dFlowRefs
);
nCutsR
=
Nf_SetAddCut
(
pCutsR
,
nCutsR
,
nCutNum
);
}
}
// debug printout
if
(
0
)
// if ( iObj % 10000 == 0 )
// if ( iObj == 1090 )
{
printf
(
"*** Obj = %d Useful = %d
\n
"
,
iObj
,
Nf_ManCountUseful
(
pCutsR
,
nCutsR
)
);
for
(
i
=
0
;
i
<
nCutsR
;
i
++
)
Nf_Cutprintf
(
p
,
pCutsR
[
i
]
);
printf
(
"
\n
"
);
}
// verify
assert
(
nCutsR
>
0
&&
nCutsR
<
nCutNum
);
// assert( Nf_SetCheckArray(pCutsR, nCutsR) );
// store the cutset
Nf_ObjSetCutFlow
(
p
,
iObj
,
pCutsR
[
0
]
->
Flow
);
Nf_ObjSetCutDelay
(
p
,
iObj
,
pCutsR
[
0
]
->
Delay
);
*
Vec_IntEntryP
(
&
p
->
vCutSets
,
iObj
)
=
Nf_ManSaveCuts
(
p
,
pCutsR
,
nCutsR
,
0
);
p
->
CutCount
[
3
]
+=
nCutsR
;
nCutsUse
=
Nf_ManCountUseful
(
pCutsR
,
nCutsR
);
p
->
CutCount
[
4
]
+=
nCutsUse
;
p
->
nCutUseAll
+=
nCutsUse
==
nCutsR
;
p
->
CutCount
[
5
]
+=
Nf_ManCountMatches
(
p
,
pCutsR
,
nCutsR
);
}
void
Nf_ManComputeCuts
(
Nf_Man_t
*
p
)
{
Gia_Obj_t
*
pObj
;
int
i
,
iFanin
;
Gia_ManForEachAnd
(
p
->
pGia
,
pObj
,
i
)
if
(
Gia_ObjIsBuf
(
pObj
)
)
{
iFanin
=
Gia_ObjFaninId0
(
pObj
,
i
);
Nf_ObjSetCutFlow
(
p
,
i
,
Nf_ObjCutFlow
(
p
,
iFanin
)
);
Nf_ObjSetCutDelay
(
p
,
i
,
Nf_ObjCutDelay
(
p
,
iFanin
)
);
}
else
Nf_ObjMergeOrder
(
p
,
i
);
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void
Nf_ManPrintStats
(
Nf_Man_t
*
p
,
char
*
pTitle
)
{
if
(
!
p
->
pPars
->
fVerbose
)
return
;
printf
(
"%s : "
,
pTitle
);
printf
(
"Delay =%8.2f "
,
p
->
pPars
->
MapDelay
);
printf
(
"Area =%12.2f "
,
p
->
pPars
->
MapArea
);
printf
(
"Gate =%6d "
,
(
int
)
p
->
pPars
->
Area
);
printf
(
"Inv =%6d "
,
(
int
)
p
->
nInvs
);
printf
(
"Edge =%7d "
,
(
int
)
p
->
pPars
->
Edge
);
Abc_PrintTime
(
1
,
"Time"
,
Abc_Clock
()
-
p
->
clkStart
);
fflush
(
stdout
);
}
void
Nf_ManPrintInit
(
Nf_Man_t
*
p
)
{
int
nChoices
;
if
(
!
p
->
pPars
->
fVerbose
)
return
;
printf
(
"LutSize = %d "
,
p
->
pPars
->
nLutSize
);
printf
(
"CutNum = %d "
,
p
->
pPars
->
nCutNum
);
printf
(
"Iter = %d "
,
p
->
pPars
->
nRounds
+
p
->
pPars
->
nRoundsEla
);
printf
(
"Coarse = %d "
,
p
->
pPars
->
fCoarsen
);
printf
(
"Cells = %d "
,
p
->
nCells
);
printf
(
"Funcs = %d "
,
Vec_MemEntryNum
(
p
->
vTtMem
)
);
printf
(
"Matches = %d "
,
Vec_WecSizeSize
(
p
->
vTt2Match
)
/
2
);
nChoices
=
Gia_ManChoiceNum
(
p
->
pGia
);
if
(
nChoices
)
printf
(
"Choices = %d "
,
nChoices
);
printf
(
"
\n
"
);
printf
(
"Computing cuts...
\r
"
);
fflush
(
stdout
);
}
void
Nf_ManPrintQuit
(
Nf_Man_t
*
p
)
{
float
MemGia
=
Gia_ManMemory
(
p
->
pGia
)
/
(
1
<<
20
);
float
MemMan
=
(
1
.
0
*
sizeof
(
Nf_Obj_t
)
+
8
.
0
*
sizeof
(
int
))
*
Gia_ManObjNum
(
p
->
pGia
)
/
(
1
<<
20
);
float
MemCuts
=
1
.
0
*
sizeof
(
int
)
*
(
1
<<
16
)
*
Vec_PtrSize
(
&
p
->
vPages
)
/
(
1
<<
20
);
float
MemTt
=
p
->
vTtMem
?
Vec_MemMemory
(
p
->
vTtMem
)
/
(
1
<<
20
)
:
0
;
if
(
p
->
CutCount
[
0
]
==
0
)
p
->
CutCount
[
0
]
=
1
;
if
(
!
p
->
pPars
->
fVerbose
)
return
;
printf
(
"CutPair = %.0f "
,
p
->
CutCount
[
0
]
);
printf
(
"Merge = %.0f (%.1f) "
,
p
->
CutCount
[
1
],
1
.
0
*
p
->
CutCount
[
1
]
/
Gia_ManAndNum
(
p
->
pGia
)
);
printf
(
"Eval = %.0f (%.1f) "
,
p
->
CutCount
[
2
],
1
.
0
*
p
->
CutCount
[
2
]
/
Gia_ManAndNum
(
p
->
pGia
)
);
printf
(
"Cut = %.0f (%.1f) "
,
p
->
CutCount
[
3
],
1
.
0
*
p
->
CutCount
[
3
]
/
Gia_ManAndNum
(
p
->
pGia
)
);
printf
(
"Use = %.0f (%.1f) "
,
p
->
CutCount
[
4
],
1
.
0
*
p
->
CutCount
[
4
]
/
Gia_ManAndNum
(
p
->
pGia
)
);
printf
(
"Mat = %.0f (%.1f) "
,
p
->
CutCount
[
5
],
1
.
0
*
p
->
CutCount
[
5
]
/
Gia_ManAndNum
(
p
->
pGia
)
);
// printf( "Equ = %d (%.2f %%) ", p->nCutUseAll, 100.0*p->nCutUseAll /p->CutCount[0] );
printf
(
"
\n
"
);
printf
(
"Gia = %.2f MB "
,
MemGia
);
printf
(
"Man = %.2f MB "
,
MemMan
);
printf
(
"Cut = %.2f MB "
,
MemCuts
);
printf
(
"TT = %.2f MB "
,
MemTt
);
printf
(
"Total = %.2f MB "
,
MemGia
+
MemMan
+
MemCuts
+
MemTt
);
// printf( "\n" );
Abc_PrintTime
(
1
,
"Time"
,
Abc_Clock
()
-
p
->
clkStart
);
fflush
(
stdout
);
}
/**Function*************************************************************
Synopsis [Technology mappping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float
Nf_MatchDeref2_rec
(
Nf_Man_t
*
p
,
int
i
,
int
c
,
Nf_Mat_t
*
pM
)
{
int
k
,
iVar
,
fCompl
,
*
pCut
;
float
Area
=
0
;
if
(
pM
->
fCompl
)
{
assert
(
Nf_ObjMapRefNum
(
p
,
i
,
!
c
)
>
0
);
if
(
!
Nf_ObjMapRefDec
(
p
,
i
,
!
c
)
)
Area
+=
Nf_MatchDeref2_rec
(
p
,
i
,
!
c
,
Nf_ObjMatchBest
(
p
,
i
,
!
c
)
);
return
Area
+
p
->
InvArea
;
}
if
(
Nf_ObjCutSetId
(
p
,
i
)
==
0
)
return
0
;
pCut
=
Nf_CutFromHandle
(
Nf_ObjCutSet
(
p
,
i
),
pM
->
CutH
);
Nf_CutForEachVar
(
pCut
,
pM
->
Conf
,
iVar
,
fCompl
,
k
)
{
assert
(
Nf_ObjMapRefNum
(
p
,
iVar
,
fCompl
)
>
0
);
if
(
!
Nf_ObjMapRefDec
(
p
,
iVar
,
fCompl
)
)
Area
+=
Nf_MatchDeref2_rec
(
p
,
iVar
,
fCompl
,
Nf_ObjMatchBest
(
p
,
iVar
,
fCompl
)
);
}
return
Area
+
Nf_ManCell
(
p
,
pM
->
Gate
)
->
Area
;
}
float
Nf_MatchRef2_rec
(
Nf_Man_t
*
p
,
int
i
,
int
c
,
Nf_Mat_t
*
pM
,
Vec_Int_t
*
vBackup
)
{
int
k
,
iVar
,
fCompl
,
*
pCut
;
float
Area
=
0
;
if
(
pM
->
fCompl
)
{
if
(
vBackup
)
Vec_IntPush
(
vBackup
,
Abc_Var2Lit
(
i
,
!
c
)
);
assert
(
Nf_ObjMapRefNum
(
p
,
i
,
!
c
)
>=
0
);
if
(
!
Nf_ObjMapRefInc
(
p
,
i
,
!
c
)
)
Area
+=
Nf_MatchRef2_rec
(
p
,
i
,
!
c
,
Nf_ObjMatchBest
(
p
,
i
,
!
c
),
vBackup
);
return
Area
+
p
->
InvArea
;
}
if
(
Nf_ObjCutSetId
(
p
,
i
)
==
0
)
return
0
;
pCut
=
Nf_CutFromHandle
(
Nf_ObjCutSet
(
p
,
i
),
pM
->
CutH
);
Nf_CutForEachVar
(
pCut
,
pM
->
Conf
,
iVar
,
fCompl
,
k
)
{
if
(
vBackup
)
Vec_IntPush
(
vBackup
,
Abc_Var2Lit
(
iVar
,
fCompl
)
);
assert
(
Nf_ObjMapRefNum
(
p
,
iVar
,
fCompl
)
>=
0
);
if
(
!
Nf_ObjMapRefInc
(
p
,
iVar
,
fCompl
)
)
Area
+=
Nf_MatchRef2_rec
(
p
,
iVar
,
fCompl
,
Nf_ObjMatchBest
(
p
,
iVar
,
fCompl
),
vBackup
);
}
return
Area
+
Nf_ManCell
(
p
,
pM
->
Gate
)
->
Area
;
}
float
Nf_MatchRef2Area
(
Nf_Man_t
*
p
,
int
i
,
int
c
,
Nf_Mat_t
*
pM
)
{
float
Area
;
int
iLit
,
k
;
Vec_IntClear
(
&
p
->
vBackup
);
Area
=
Nf_MatchRef2_rec
(
p
,
i
,
c
,
pM
,
&
p
->
vBackup
);
Vec_IntForEachEntry
(
&
p
->
vBackup
,
iLit
,
k
)
{
assert
(
Nf_ObjMapRefNum
(
p
,
Abc_Lit2Var
(
iLit
),
Abc_LitIsCompl
(
iLit
))
>
0
);
Nf_ObjMapRefDec
(
p
,
Abc_Lit2Var
(
iLit
),
Abc_LitIsCompl
(
iLit
)
);
}
return
Area
;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void
Nf_ManCutMatchprintf
(
Nf_Man_t
*
p
,
int
iObj
,
int
fCompl
,
Nf_Mat_t
*
pM
)
{
Mio_Cell_t
*
pCell
;
int
i
,
*
pCut
;
printf
(
"%5d %d : "
,
iObj
,
fCompl
);
if
(
pM
->
CutH
==
0
)
{
printf
(
"Unassigned
\n
"
);
return
;
}
pCell
=
Nf_ManCell
(
p
,
pM
->
Gate
);
pCut
=
Nf_CutFromHandle
(
Nf_ObjCutSet
(
p
,
iObj
),
pM
->
CutH
);
printf
(
"D = %8.2f "
,
pM
->
D
);
printf
(
"A = %8.2f "
,
pM
->
A
);
printf
(
"C = %d "
,
pM
->
fCompl
);
// printf( "B = %d ", pM->fBest );
printf
(
" "
);
printf
(
"Cut = {"
);
for
(
i
=
0
;
i
<
(
int
)
pCell
->
nFanins
;
i
++
)
printf
(
"%5d "
,
Nf_CutLeaves
(
pCut
)[
i
]
);
for
(
;
i
<
6
;
i
++
)
printf
(
" "
);
printf
(
"} "
);
printf
(
"%12s "
,
pCell
->
pName
);
printf
(
"%d "
,
pCell
->
nFanins
);
printf
(
"{"
);
for
(
i
=
0
;
i
<
(
int
)
pCell
->
nFanins
;
i
++
)
printf
(
"%7.2f "
,
pCell
->
Delays
[
i
]
);
for
(
;
i
<
6
;
i
++
)
printf
(
" "
);
printf
(
" } "
);
for
(
i
=
0
;
i
<
(
int
)
pCell
->
nFanins
;
i
++
)
printf
(
"%2d "
,
Nf_CutConfLit
(
pM
->
Conf
,
i
)
);
for
(
;
i
<
6
;
i
++
)
printf
(
" "
);
Dau_DsdPrintFromTruth
(
&
pCell
->
uTruth
,
pCell
->
nFanins
);
}
void
Nf_ManCutMatchOne
(
Nf_Man_t
*
p
,
int
iObj
,
int
*
pCut
,
int
*
pCutSet
)
{
Nf_Obj_t
*
pBest
=
Nf_ManObj
(
p
,
iObj
);
int
*
pFans
=
Nf_CutLeaves
(
pCut
);
int
nFans
=
Nf_CutSize
(
pCut
);
int
iFuncLit
=
Nf_CutFunc
(
pCut
);
int
fComplExt
=
Abc_LitIsCompl
(
iFuncLit
);
float
Epsilon
=
p
->
pPars
->
Epsilon
;
Vec_Int_t
*
vArr
=
Vec_WecEntry
(
p
->
vTt2Match
,
Abc_Lit2Var
(
iFuncLit
)
);
int
i
,
k
,
c
,
Info
,
Offset
,
iFanin
,
fComplF
;
float
ArrivalD
,
ArrivalA
;
Nf_Mat_t
*
pD
,
*
pA
;
// assign fanins matches
Nf_Obj_t
*
pBestF
[
NF_LEAF_MAX
];
for
(
i
=
0
;
i
<
nFans
;
i
++
)
pBestF
[
i
]
=
Nf_ManObj
(
p
,
pFans
[
i
]
);
// special cases
if
(
nFans
==
0
)
{
int
Const
=
(
iFuncLit
==
1
);
assert
(
iFuncLit
==
0
||
iFuncLit
==
1
);
for
(
c
=
0
;
c
<
2
;
c
++
)
{
pD
=
Nf_ObjMatchD
(
p
,
iObj
,
c
);
pA
=
Nf_ObjMatchA
(
p
,
iObj
,
c
);
pD
->
D
=
pA
->
D
=
0
;
pD
->
A
=
pA
->
A
=
p
->
pCells
[
c
^
Const
].
Area
;
pD
->
CutH
=
pA
->
CutH
=
Nf_CutHandle
(
pCutSet
,
pCut
);
pD
->
Gate
=
pA
->
Gate
=
c
^
Const
;
pD
->
Conf
=
pA
->
Conf
=
0
;
}
return
;
}
if
(
nFans
==
1
)
{
int
Const
=
(
iFuncLit
==
3
);
assert
(
iFuncLit
==
2
||
iFuncLit
==
3
);
for
(
c
=
0
;
c
<
2
;
c
++
)
{
pD
=
Nf_ObjMatchD
(
p
,
iObj
,
c
);
pA
=
Nf_ObjMatchA
(
p
,
iObj
,
c
);
pD
->
D
=
pA
->
D
=
pBestF
[
0
]
->
M
[
c
^
!
Const
][
0
].
D
+
p
->
pCells
[
2
+
(
c
^
Const
)].
Delays
[
0
];
pD
->
A
=
pA
->
A
=
pBestF
[
0
]
->
M
[
c
^
!
Const
][
0
].
A
+
p
->
pCells
[
2
+
(
c
^
Const
)].
Area
;
pD
->
CutH
=
pA
->
CutH
=
Nf_CutHandle
(
pCutSet
,
pCut
);
pD
->
Gate
=
pA
->
Gate
=
2
+
(
c
^
Const
);
pD
->
Conf
=
pA
->
Conf
=
0
;
}
return
;
}
// consider matches of this function
Vec_IntForEachEntryDouble
(
vArr
,
Info
,
Offset
,
i
)
{
Mio_Cell_t
*
pC
=
Nf_ManCell
(
p
,
Info
>>
8
);
int
Type
=
(
Info
>>
4
)
&
15
;
int
fCompl
=
(
Info
&
1
)
^
fComplExt
;
char
*
pInfo
=
Vec_StrEntryP
(
p
->
vMemStore
,
Offset
);
float
Required
=
Nf_ObjRequired
(
p
,
iObj
,
fCompl
);
Nf_Mat_t
*
pD
=
&
pBest
->
M
[
fCompl
][
0
];
Nf_Mat_t
*
pA
=
&
pBest
->
M
[
fCompl
][
1
];
assert
(
nFans
==
(
int
)
pC
->
nFanins
);
// if ( iObj == 9 && fCompl == 0 && i == 192 )
// Nf_StoPrintOne( p, -1, Abc_Lit2Var(iFuncLit), i, pC, Type, fCompl, pInfo );
if
(
Type
==
NF_PRIME
)
{
float
Area
=
pC
->
Area
,
Delay
=
0
;
for
(
k
=
0
;
k
<
nFans
;
k
++
)
{
iFanin
=
Abc_Lit2Var
((
int
)
pInfo
[
k
]);
fComplF
=
Abc_LitIsCompl
((
int
)
pInfo
[
k
]);
ArrivalD
=
pBestF
[
k
]
->
M
[
fComplF
][
0
].
D
;
ArrivalA
=
pBestF
[
k
]
->
M
[
fComplF
][
1
].
D
;
if
(
ArrivalA
+
pC
->
Delays
[
iFanin
]
<
Required
+
Epsilon
&&
Required
!=
NF_INFINITY
)
{
Delay
=
Abc_MaxFloat
(
Delay
,
ArrivalA
+
pC
->
Delays
[
iFanin
]
);
Area
+=
pBestF
[
k
]
->
M
[
fComplF
][
1
].
A
;
}
else
{
// assert( ArrivalD + pC->Delays[iFanin] < Required + Epsilon );
if
(
pD
->
D
<
NF_INFINITY
&&
pA
->
D
<
NF_INFINITY
&&
ArrivalD
+
pC
->
Delays
[
iFanin
]
>=
Required
+
Epsilon
)
break
;
Delay
=
Abc_MaxFloat
(
Delay
,
ArrivalD
+
pC
->
Delays
[
iFanin
]
);
Area
+=
pBestF
[
k
]
->
M
[
fComplF
][
0
].
A
;
}
}
if
(
k
<
nFans
)
continue
;
if
(
p
->
fUseEla
)
{
Nf_Mat_t
Temp
,
*
pTemp
=
&
Temp
;
memset
(
pTemp
,
0
,
sizeof
(
Nf_Mat_t
)
);
pTemp
->
D
=
Delay
;
pTemp
->
A
=
Area
;
pTemp
->
CutH
=
Nf_CutHandle
(
pCutSet
,
pCut
);
pTemp
->
Gate
=
pC
->
Id
;
pTemp
->
Conf
=
0
;
for
(
k
=
0
;
k
<
nFans
;
k
++
)
// pD->Conf |= ((int)pInfo[k] << (k << 2));
pTemp
->
Conf
|=
(
Abc_Var2Lit
(
k
,
Abc_LitIsCompl
((
int
)
pInfo
[
k
]))
<<
(
Abc_Lit2Var
((
int
)
pInfo
[
k
])
<<
2
));
Area
=
Nf_MatchRef2Area
(
p
,
iObj
,
fCompl
,
pTemp
);
}
// select best match
if
(
pD
->
D
>
Delay
)
//+ Epsilon )
{
pD
->
D
=
Delay
;
pD
->
A
=
Area
;
pD
->
CutH
=
Nf_CutHandle
(
pCutSet
,
pCut
);
pD
->
Gate
=
pC
->
Id
;
pD
->
Conf
=
0
;
for
(
k
=
0
;
k
<
nFans
;
k
++
)
// pD->Conf |= ((int)pInfo[k] << (k << 2));
pD
->
Conf
|=
(
Abc_Var2Lit
(
k
,
Abc_LitIsCompl
((
int
)
pInfo
[
k
]))
<<
(
Abc_Lit2Var
((
int
)
pInfo
[
k
])
<<
2
));
}
if
(
pA
->
A
>
Area
)
//+ Epsilon )
{
pA
->
D
=
Delay
;
pA
->
A
=
Area
;
pA
->
CutH
=
Nf_CutHandle
(
pCutSet
,
pCut
);
pA
->
Gate
=
pC
->
Id
;
pA
->
Conf
=
0
;
for
(
k
=
0
;
k
<
nFans
;
k
++
)
// pA->Conf |= ((int)pInfo[k] << (k << 2));
pA
->
Conf
|=
(
Abc_Var2Lit
(
k
,
Abc_LitIsCompl
((
int
)
pInfo
[
k
]))
<<
(
Abc_Lit2Var
((
int
)
pInfo
[
k
])
<<
2
));
}
}
else
if
(
Type
==
NF_XOR
)
{
int
m
,
nMints
=
1
<<
nFans
;
for
(
m
=
0
;
m
<
nMints
;
m
++
)
{
int
fComplAll
=
fCompl
;
// collect best fanin delays
float
Area
=
pC
->
Area
,
Delay
=
0
;
for
(
k
=
0
;
k
<
nFans
;
k
++
)
{
assert
(
!
Abc_LitIsCompl
((
int
)
pInfo
[
k
])
);
iFanin
=
Abc_Lit2Var
((
int
)
pInfo
[
k
]);
fComplF
=
((
m
>>
k
)
&
1
);
ArrivalD
=
pBestF
[
k
]
->
M
[
fComplF
][
0
].
D
;
ArrivalA
=
pBestF
[
k
]
->
M
[
fComplF
][
1
].
D
;
if
(
ArrivalA
+
pC
->
Delays
[
iFanin
]
<=
Required
&&
Required
!=
NF_INFINITY
)
{
Delay
=
Abc_MaxFloat
(
Delay
,
ArrivalA
+
pC
->
Delays
[
iFanin
]
);
Area
+=
pBestF
[
k
]
->
M
[
fComplF
][
1
].
A
;
}
else
{
assert
(
ArrivalD
+
pC
->
Delays
[
iFanin
]
<
Required
+
Epsilon
);
Delay
=
Abc_MaxFloat
(
Delay
,
ArrivalD
+
pC
->
Delays
[
iFanin
]
);
Area
+=
pBestF
[
k
]
->
M
[
fComplF
][
0
].
A
;
}
fComplAll
^=
fComplF
;
}
pD
=
&
pBest
->
M
[
fComplAll
][
0
];
pA
=
&
pBest
->
M
[
fComplAll
][
1
];
if
(
pD
->
D
>
Delay
)
{
pD
->
D
=
Delay
;
pD
->
A
=
Area
;
pD
->
CutH
=
Nf_CutHandle
(
pCutSet
,
pCut
);
pD
->
Gate
=
pC
->
Id
;
pD
->
Conf
=
0
;
for
(
k
=
0
;
k
<
nFans
;
k
++
)
// pD->Conf |= Abc_LitNotCond((int)pInfo[k], (m >> k) & 1) << (k << 2);
pD
->
Conf
|=
(
Abc_Var2Lit
(
k
,
(
m
>>
k
)
&
1
)
<<
(
Abc_Lit2Var
((
int
)
pInfo
[
k
])
<<
2
));
}
if
(
pA
->
A
>
Area
)
{
pA
->
D
=
Delay
;
pA
->
A
=
Area
;
pA
->
CutH
=
Nf_CutHandle
(
pCutSet
,
pCut
);
pA
->
Gate
=
pC
->
Id
;
pA
->
Conf
=
0
;
for
(
k
=
0
;
k
<
nFans
;
k
++
)
// pA->Conf |= Abc_LitNotCond((int)pInfo[k], (m >> k) & 1) << (k << 2);
pA
->
Conf
|=
(
Abc_Var2Lit
(
k
,
(
m
>>
k
)
&
1
)
<<
(
Abc_Lit2Var
((
int
)
pInfo
[
k
])
<<
2
));
}
}
}
else
if
(
Type
==
NF_ANDOR
)
{
float
Area
=
pC
->
Area
,
Delay
=
0
;
int
g
,
Conf
=
0
,
nGroups
=
(
int
)
*
pInfo
++
;
for
(
g
=
0
;
g
<
nGroups
;
g
++
)
{
int
nSizeAll
=
(
int
)
*
pInfo
++
;
int
nSizeNeg
=
(
int
)
*
pInfo
++
;
float
ArrivalD
,
ArrivalA
;
for
(
k
=
0
;
k
<
nSizeAll
;
k
++
)
{
fComplF
=
Abc_LitIsCompl
((
int
)
pInfo
[
k
]);
iFanin
=
Abc_Lit2Var
((
int
)
pInfo
[
k
]);
ArrivalD
=
pBestF
[
k
]
->
M
[
fComplF
][
0
].
D
;
ArrivalA
=
pBestF
[
k
]
->
M
[
fComplF
][
1
].
D
;
if
(
ArrivalA
+
pC
->
Delays
[
iFanin
]
<
Required
+
Epsilon
&&
Required
!=
NF_INFINITY
)
{
Delay
=
Abc_MaxFloat
(
Delay
,
ArrivalA
+
pC
->
Delays
[
iFanin
]
);
Area
+=
pBestF
[
k
]
->
M
[
fComplF
][
1
].
A
;
}
else
{
assert
(
ArrivalD
+
pC
->
Delays
[
iFanin
]
<
Required
+
Epsilon
);
Delay
=
Abc_MaxFloat
(
Delay
,
ArrivalD
+
pC
->
Delays
[
iFanin
]
);
Area
+=
pBestF
[
k
]
->
M
[
fComplF
][
0
].
A
;
}
// Conf |= Abc_LitNotCond((int)pInfo[k], 0) << (iFanin << 2);
Conf
|=
Abc_Var2Lit
(
iFanin
,
Abc_LitIsCompl
((
int
)
pInfo
[
k
]))
<<
(
Abc_Lit2Var
((
int
)
pInfo
[
k
])
<<
2
);
}
pInfo
+=
nSizeAll
;
}
assert
(
Conf
>
0
);
if
(
pD
->
D
>
Delay
)
{
pD
->
D
=
Delay
;
pD
->
A
=
Area
;
pD
->
CutH
=
Nf_CutHandle
(
pCutSet
,
pCut
);
pD
->
Gate
=
pC
->
Id
;
pD
->
Conf
=
Conf
;
}
if
(
pA
->
A
>
Area
)
{
pA
->
D
=
Delay
;
pA
->
A
=
Area
;
pA
->
CutH
=
Nf_CutHandle
(
pCutSet
,
pCut
);
pA
->
Gate
=
pC
->
Id
;
pA
->
Conf
=
Conf
;
}
}
}
/*
Nf_ManCutMatchprintf( p, iObj, 0, &pBest->M[0][0] );
Nf_ManCutMatchprintf( p, iObj, 0, &pBest->M[0][1] );
Nf_ManCutMatchprintf( p, iObj, 1, &pBest->M[1][0] );
Nf_ManCutMatchprintf( p, iObj, 1, &pBest->M[1][1] );
*/
}
static
inline
void
Nf_ObjPrepareCi
(
Nf_Man_t
*
p
,
int
iObj
)
{
Nf_Mat_t
*
pD
=
Nf_ObjMatchD
(
p
,
iObj
,
1
);
Nf_Mat_t
*
pA
=
Nf_ObjMatchA
(
p
,
iObj
,
1
);
pD
->
fCompl
=
1
;
pD
->
D
=
p
->
InvDelay
;
pD
->
A
=
p
->
InvArea
;
pA
->
fCompl
=
1
;
pA
->
D
=
p
->
InvDelay
;
pA
->
A
=
p
->
InvArea
;
Nf_ObjMatchD
(
p
,
iObj
,
0
)
->
fBest
=
1
;
Nf_ObjMatchD
(
p
,
iObj
,
1
)
->
fBest
=
1
;
}
static
inline
void
Nf_ObjPrepareBuf
(
Nf_Man_t
*
p
,
Gia_Obj_t
*
pObj
)
{
// get fanin info
int
iObj
=
Gia_ObjId
(
p
->
pGia
,
pObj
);
int
iFanin
=
Gia_ObjFaninId0
(
pObj
,
iObj
);
Nf_Mat_t
*
pDf
=
Nf_ObjMatchD
(
p
,
iFanin
,
Gia_ObjFaninC0
(
pObj
)
);
Nf_Mat_t
*
pAf
=
Nf_ObjMatchA
(
p
,
iFanin
,
Gia_ObjFaninC0
(
pObj
)
);
// set the direct phase
Nf_Mat_t
*
pDp
=
Nf_ObjMatchD
(
p
,
iObj
,
0
);
Nf_Mat_t
*
pAp
=
Nf_ObjMatchA
(
p
,
iObj
,
0
);
Nf_Mat_t
*
pDn
=
Nf_ObjMatchD
(
p
,
iObj
,
1
);
Nf_Mat_t
*
pAn
=
Nf_ObjMatchA
(
p
,
iObj
,
1
);
assert
(
Gia_ObjIsBuf
(
pObj
)
);
memset
(
Nf_ManObj
(
p
,
iObj
),
0
,
sizeof
(
Nf_Obj_t
)
);
// set the direct phase
pDp
->
D
=
pAp
->
D
=
pDf
->
D
;
pDp
->
A
=
pAp
->
A
=
pDf
->
A
;
// do not pass flow???
pDp
->
fBest
=
1
;
// set the inverted phase
pDn
->
D
=
pAn
->
D
=
pDf
->
D
+
p
->
InvDelay
;
pDn
->
A
=
pAn
->
A
=
pDf
->
A
+
p
->
InvArea
;
pDn
->
fCompl
=
pAn
->
fCompl
=
1
;
pDn
->
fBest
=
1
;
}
static
inline
float
Nf_CutRequired
(
Nf_Man_t
*
p
,
Nf_Mat_t
*
pM
,
int
*
pCutSet
)
{
Mio_Cell_t
*
pCell
=
Nf_ManCell
(
p
,
pM
->
Gate
);
int
*
pCut
=
Nf_CutFromHandle
(
pCutSet
,
pM
->
CutH
);
int
*
pFans
=
Nf_CutLeaves
(
pCut
);
int
i
,
nFans
=
Nf_CutSize
(
pCut
);
float
Arrival
=
0
,
Required
=
0
;
for
(
i
=
0
;
i
<
nFans
;
i
++
)
{
int
iLit
=
Nf_CutConfLit
(
pM
->
Conf
,
i
);
int
iFanin
=
pFans
[
Abc_Lit2Var
(
iLit
)
];
int
fCompl
=
Abc_LitIsCompl
(
iLit
);
float
Arr
=
Nf_ManObj
(
p
,
iFanin
)
->
M
[
fCompl
][
0
].
D
+
pCell
->
Delays
[
i
];
float
Req
=
Nf_ObjRequired
(
p
,
iFanin
,
fCompl
);
Arrival
=
Abc_MaxInt
(
Arrival
,
Arr
);
if
(
Req
<
NF_INFINITY
)
Required
=
Abc_MaxInt
(
Required
,
Req
+
pCell
->
Delays
[
i
]
);
}
return
Abc_MaxFloat
(
Required
+
2
*
p
->
InvDelay
,
Arrival
);
}
static
inline
void
Nf_ObjComputeRequired
(
Nf_Man_t
*
p
,
int
iObj
)
{
Nf_Obj_t
*
pBest
=
Nf_ManObj
(
p
,
iObj
);
int
c
,
*
pCutSet
=
Nf_ObjCutSet
(
p
,
iObj
);
for
(
c
=
0
;
c
<
2
;
c
++
)
if
(
Nf_ObjRequired
(
p
,
iObj
,
c
)
==
NF_INFINITY
)
Nf_ObjSetRequired
(
p
,
iObj
,
c
,
Nf_CutRequired
(
p
,
&
pBest
->
M
[
c
][
0
],
pCutSet
)
);
}
void
Nf_ManCutMatch
(
Nf_Man_t
*
p
,
int
iObj
)
{
Nf_Obj_t
*
pBest
=
Nf_ManObj
(
p
,
iObj
);
Nf_Mat_t
*
pDp
=
&
pBest
->
M
[
0
][
0
];
Nf_Mat_t
*
pDn
=
&
pBest
->
M
[
1
][
0
];
Nf_Mat_t
*
pAp
=
&
pBest
->
M
[
0
][
1
];
Nf_Mat_t
*
pAn
=
&
pBest
->
M
[
1
][
1
];
float
FlowRefP
=
Nf_ObjFlowRefs
(
p
,
iObj
,
0
);
float
FlowRefN
=
Nf_ObjFlowRefs
(
p
,
iObj
,
1
);
float
Epsilon
=
p
->
pPars
->
Epsilon
;
int
i
,
Index
,
*
pCut
,
*
pCutSet
=
Nf_ObjCutSet
(
p
,
iObj
);
float
ValueBeg
[
2
]
=
{
0
},
ValueEnd
[
2
]
=
{
0
},
Required
[
2
]
=
{
0
};
if
(
p
->
Iter
)
{
Nf_ObjComputeRequired
(
p
,
iObj
);
Required
[
0
]
=
Nf_ObjRequired
(
p
,
iObj
,
0
);
Required
[
1
]
=
Nf_ObjRequired
(
p
,
iObj
,
1
);
}
if
(
p
->
fUseEla
&&
Nf_ObjMapRefNum
(
p
,
iObj
,
0
)
>
0
)
ValueBeg
[
0
]
=
Nf_MatchDeref2_rec
(
p
,
iObj
,
0
,
Nf_ObjMatchBest
(
p
,
iObj
,
0
)
);
if
(
p
->
fUseEla
&&
Nf_ObjMapRefNum
(
p
,
iObj
,
1
)
>
0
)
ValueBeg
[
1
]
=
Nf_MatchDeref2_rec
(
p
,
iObj
,
1
,
Nf_ObjMatchBest
(
p
,
iObj
,
1
)
);
memset
(
pBest
,
0
,
sizeof
(
Nf_Obj_t
)
);
pDp
->
D
=
pDp
->
A
=
NF_INFINITY
;
pDn
->
D
=
pDn
->
A
=
NF_INFINITY
;
pAp
->
D
=
pAp
->
A
=
NF_INFINITY
;
pAn
->
D
=
pAn
->
A
=
NF_INFINITY
;
Nf_SetForEachCut
(
pCutSet
,
pCut
,
i
)
{
if
(
Abc_Lit2Var
(
Nf_CutFunc
(
pCut
))
>=
Vec_WecSize
(
p
->
vTt2Match
)
)
continue
;
assert
(
!
Nf_CutIsTriv
(
pCut
,
iObj
)
);
assert
(
Nf_CutSize
(
pCut
)
<=
p
->
pPars
->
nLutSize
);
assert
(
Abc_Lit2Var
(
Nf_CutFunc
(
pCut
))
<
Vec_WecSize
(
p
->
vTt2Match
)
);
Nf_ManCutMatchOne
(
p
,
iObj
,
pCut
,
pCutSet
);
}
/*
if ( 18687 == iObj )
{
printf( "Obj %6d (%f %f):\n", iObj, Required[0], Required[1] );
Nf_ManCutMatchprintf( p, iObj, 0, &pBest->M[0][0] );
Nf_ManCutMatchprintf( p, iObj, 0, &pBest->M[0][1] );
Nf_ManCutMatchprintf( p, iObj, 1, &pBest->M[1][0] );
Nf_ManCutMatchprintf( p, iObj, 1, &pBest->M[1][1] );
printf( "\n" );
}
*/
// divide by ref count
pDp
->
A
/=
FlowRefP
;
pAp
->
A
/=
FlowRefP
;
pDn
->
A
/=
FlowRefN
;
pAn
->
A
/=
FlowRefN
;
// add the inverters
//assert( pDp->D < NF_INFINITY || pDn->D < NF_INFINITY );
if
(
pDp
->
D
>
pDn
->
D
+
p
->
InvDelay
+
Epsilon
)
{
*
pDp
=
*
pDn
;
pDp
->
D
+=
p
->
InvDelay
;
pDp
->
A
+=
p
->
InvArea
;
pDp
->
fCompl
=
1
;
if
(
pAp
->
D
==
NF_INFINITY
)
*
pAp
=
*
pDp
;
//printf( "Using inverter to improve delay at node %d in phase %d.\n", iObj, 1 );
}
else
if
(
pDn
->
D
>
pDp
->
D
+
p
->
InvDelay
+
Epsilon
)
{
*
pDn
=
*
pDp
;
pDn
->
D
+=
p
->
InvDelay
;
pDn
->
A
+=
p
->
InvArea
;
pDn
->
fCompl
=
1
;
if
(
pAn
->
D
==
NF_INFINITY
)
*
pAn
=
*
pDn
;
//printf( "Using inverter to improve delay at node %d in phase %d.\n", iObj, 0 );
}
//assert( pAp->A < NF_INFINITY || pAn->A < NF_INFINITY );
// try replacing pos with neg
if
(
pAp
->
D
==
NF_INFINITY
||
(
pAp
->
A
>
pAn
->
A
+
p
->
InvArea
+
Epsilon
&&
pAn
->
D
+
p
->
InvDelay
+
Epsilon
<
Required
[
1
])
)
{
assert
(
p
->
Iter
>
0
);
*
pAp
=
*
pAn
;
pAp
->
D
+=
p
->
InvDelay
;
pAp
->
A
+=
p
->
InvArea
;
pAp
->
fCompl
=
1
;
if
(
pDp
->
D
==
NF_INFINITY
)
*
pDp
=
*
pAp
;
//printf( "Using inverter to improve area at node %d in phase %d.\n", iObj, 1 );
}
// try replacing neg with pos
else
if
(
pAn
->
D
==
NF_INFINITY
||
(
pAn
->
A
>
pAp
->
A
+
p
->
InvArea
+
Epsilon
&&
pAp
->
D
+
p
->
InvDelay
+
Epsilon
<
Required
[
0
])
)
{
assert
(
p
->
Iter
>
0
);
*
pAn
=
*
pAp
;
pAn
->
D
+=
p
->
InvDelay
;
pAn
->
A
+=
p
->
InvArea
;
pAn
->
fCompl
=
1
;
if
(
pDn
->
D
==
NF_INFINITY
)
*
pDn
=
*
pAn
;
//printf( "Using inverter to improve area at node %d in phase %d.\n", iObj, 0 );
}
if
(
pDp
->
D
==
NF_INFINITY
)
printf
(
"Object %d has pDp unassigned.
\n
"
,
iObj
);
if
(
pDn
->
D
==
NF_INFINITY
)
printf
(
"Object %d has pDn unassigned.
\n
"
,
iObj
);
if
(
pAp
->
D
==
NF_INFINITY
)
printf
(
"Object %d has pAp unassigned.
\n
"
,
iObj
);
if
(
pAn
->
D
==
NF_INFINITY
)
printf
(
"Object %d has pAn unassigned.
\n
"
,
iObj
);
pDp
->
A
=
Abc_MinFloat
(
pDp
->
A
,
NF_INFINITY
/
1000000
);
pDn
->
A
=
Abc_MinFloat
(
pDn
->
A
,
NF_INFINITY
/
1000000
);
pAp
->
A
=
Abc_MinFloat
(
pAp
->
A
,
NF_INFINITY
/
1000000
);
pAn
->
A
=
Abc_MinFloat
(
pAn
->
A
,
NF_INFINITY
/
1000000
);
assert
(
pDp
->
D
<
NF_INFINITY
);
assert
(
pDn
->
D
<
NF_INFINITY
);
assert
(
pAp
->
D
<
NF_INFINITY
);
assert
(
pAn
->
D
<
NF_INFINITY
);
assert
(
pDp
->
A
<
NF_INFINITY
);
assert
(
pDn
->
A
<
NF_INFINITY
);
assert
(
pAp
->
A
<
NF_INFINITY
);
assert
(
pAn
->
A
<
NF_INFINITY
);
//printf( "%16f %16f %16f %16f\n", pDp->A, pDn->A, pAp->A, pAn->A );
// assert ( pDp->A < 1000 );
if
(
p
->
fUseEla
)
{
// set the first good cut
Index
=
(
pAp
->
D
!=
NF_INFINITY
&&
pAp
->
D
<
Nf_ObjRequired
(
p
,
iObj
,
0
)
+
Epsilon
);
assert
(
!
pDp
->
fBest
&&
!
pAp
->
fBest
);
pBest
->
M
[
0
][
Index
].
fBest
=
1
;
assert
(
pDp
->
fBest
!=
pAp
->
fBest
);
// set the second good cut
Index
=
(
pAn
->
D
!=
NF_INFINITY
&&
pAn
->
D
<
Nf_ObjRequired
(
p
,
iObj
,
1
)
+
Epsilon
);
assert
(
!
pDn
->
fBest
&&
!
pAn
->
fBest
);
pBest
->
M
[
1
][
Index
].
fBest
=
1
;
assert
(
pDn
->
fBest
!=
pAn
->
fBest
);
// reference if needed
if
(
Nf_ObjMapRefNum
(
p
,
iObj
,
0
)
>
0
)
ValueEnd
[
0
]
=
Nf_MatchRef2_rec
(
p
,
iObj
,
0
,
Nf_ObjMatchBest
(
p
,
iObj
,
0
),
NULL
);
if
(
Nf_ObjMapRefNum
(
p
,
iObj
,
1
)
>
0
)
ValueEnd
[
1
]
=
Nf_MatchRef2_rec
(
p
,
iObj
,
1
,
Nf_ObjMatchBest
(
p
,
iObj
,
1
),
NULL
);
// assert( ValueBeg[0] > ValueEnd[0] - Epsilon );
// assert( ValueBeg[1] > ValueEnd[1] - Epsilon );
}
}
void
Nf_ManComputeMapping
(
Nf_Man_t
*
p
)
{
Gia_Obj_t
*
pObj
;
int
i
;
Gia_ManForEachAnd
(
p
->
pGia
,
pObj
,
i
)
if
(
Gia_ObjIsBuf
(
pObj
)
)
Nf_ObjPrepareBuf
(
p
,
pObj
);
else
Nf_ManCutMatch
(
p
,
i
);
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void
Nf_ManSetMapRefsGate
(
Nf_Man_t
*
p
,
int
iObj
,
float
Required
,
Nf_Mat_t
*
pM
)
{
int
k
,
iVar
,
fCompl
;
Mio_Cell_t
*
pCell
=
Nf_ManCell
(
p
,
pM
->
Gate
);
int
*
pCut
=
Nf_CutFromHandle
(
Nf_ObjCutSet
(
p
,
iObj
),
pM
->
CutH
);
Nf_CutForEachVar
(
pCut
,
pM
->
Conf
,
iVar
,
fCompl
,
k
)
{
Nf_ObjMapRefInc
(
p
,
iVar
,
fCompl
);
Nf_ObjUpdateRequired
(
p
,
iVar
,
fCompl
,
Required
-
pCell
->
Delays
[
k
]
);
}
assert
(
Nf_CutSize
(
pCut
)
==
(
int
)
pCell
->
nFanins
);
// update global stats
p
->
pPars
->
MapArea
+=
pCell
->
Area
;
p
->
pPars
->
Edge
+=
Nf_CutSize
(
pCut
);
p
->
pPars
->
Area
++
;
// update status of the gate
assert
(
pM
->
fBest
==
0
);
pM
->
fBest
=
1
;
}
int
Nf_ManSetMapRefs
(
Nf_Man_t
*
p
)
{
float
Coef
=
1
.
0
/
(
1
.
0
+
(
p
->
Iter
+
1
)
*
(
p
->
Iter
+
1
));
float
*
pFlowRefs
=
Vec_FltArray
(
&
p
->
vFlowRefs
);
int
*
pMapRefs
=
Vec_IntArray
(
&
p
->
vMapRefs
);
float
Epsilon
=
p
->
pPars
->
Epsilon
;
int
nLits
=
2
*
Gia_ManObjNum
(
p
->
pGia
);
int
i
,
c
,
Id
,
nRefs
[
2
];
Nf_Mat_t
*
pD
,
*
pA
,
*
pM
;
Nf_Mat_t
*
pDs
[
2
],
*
pAs
[
2
],
*
pMs
[
2
];
Gia_Obj_t
*
pObj
;
float
Required
,
Requireds
[
2
];
// check references
assert
(
!
p
->
fUseEla
);
memset
(
pMapRefs
,
0
,
sizeof
(
int
)
*
nLits
);
Vec_FltFill
(
&
p
->
vRequired
,
nLits
,
NF_INFINITY
);
// for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ )
// assert( !Nf_ObjMapRefNum(p, i, 0) && !Nf_ObjMapRefNum(p, i, 1) );
// compute delay
p
->
pPars
->
MapDelay
=
0
;
Gia_ManForEachCo
(
p
->
pGia
,
pObj
,
i
)
{
Required
=
Nf_ObjMatchD
(
p
,
Gia_ObjFaninId0p
(
p
->
pGia
,
pObj
),
Gia_ObjFaninC0
(
pObj
)
)
->
D
;
if
(
Required
==
NF_INFINITY
)
{
Nf_ManCutMatchprintf
(
p
,
Gia_ObjFaninId0p
(
p
->
pGia
,
pObj
),
Gia_ObjFaninC0
(
pObj
),
Nf_ObjMatchD
(
p
,
Gia_ObjFaninId0p
(
p
->
pGia
,
pObj
),
Gia_ObjFaninC0
(
pObj
)
)
);
}
p
->
pPars
->
MapDelay
=
Abc_MaxFloat
(
p
->
pPars
->
MapDelay
,
Required
);
}
// check delay target
if
(
p
->
pPars
->
MapDelayTarget
==
-
1
&&
p
->
pPars
->
nRelaxRatio
)
p
->
pPars
->
MapDelayTarget
=
(
int
)((
float
)
p
->
pPars
->
MapDelay
*
(
100
.
0
+
p
->
pPars
->
nRelaxRatio
)
/
100
.
0
);
if
(
p
->
pPars
->
MapDelayTarget
!=
-
1
)
{
if
(
p
->
pPars
->
MapDelay
<
p
->
pPars
->
MapDelayTarget
+
Epsilon
)
p
->
pPars
->
MapDelay
=
p
->
pPars
->
MapDelayTarget
;
else
if
(
p
->
pPars
->
nRelaxRatio
==
0
)
Abc_Print
(
0
,
"Relaxing user-specified delay target from %.2f to %.2f.
\n
"
,
p
->
pPars
->
MapDelayTarget
,
p
->
pPars
->
MapDelay
);
}
// set required times
Gia_ManForEachCo
(
p
->
pGia
,
pObj
,
i
)
{
Required
=
Nf_ObjMatchD
(
p
,
Gia_ObjFaninId0p
(
p
->
pGia
,
pObj
),
Gia_ObjFaninC0
(
pObj
)
)
->
D
;
Required
=
p
->
pPars
->
fDoAverage
?
Required
*
(
100
.
0
+
p
->
pPars
->
nRelaxRatio
)
/
100
.
0
:
p
->
pPars
->
MapDelay
;
Nf_ObjUpdateRequired
(
p
,
Gia_ObjFaninId0p
(
p
->
pGia
,
pObj
),
Gia_ObjFaninC0
(
pObj
),
Required
);
Nf_ObjMapRefInc
(
p
,
Gia_ObjFaninId0p
(
p
->
pGia
,
pObj
),
Gia_ObjFaninC0
(
pObj
));
}
// compute area and edges
p
->
nInvs
=
0
;
p
->
pPars
->
MapArea
=
0
;
p
->
pPars
->
Area
=
p
->
pPars
->
Edge
=
0
;
Gia_ManForEachAndReverse
(
p
->
pGia
,
pObj
,
i
)
{
if
(
Gia_ObjIsBuf
(
pObj
)
)
{
if
(
Nf_ObjMapRefNum
(
p
,
i
,
1
)
)
{
Nf_ObjMapRefInc
(
p
,
i
,
0
);
Nf_ObjUpdateRequired
(
p
,
i
,
0
,
Nf_ObjRequired
(
p
,
i
,
1
)
-
p
->
InvDelay
);
p
->
pPars
->
MapArea
+=
p
->
InvArea
;
p
->
pPars
->
Edge
++
;
p
->
pPars
->
Area
++
;
p
->
nInvs
++
;
}
Nf_ObjUpdateRequired
(
p
,
Gia_ObjFaninId0
(
pObj
,
i
),
Gia_ObjFaninC0
(
pObj
),
Nf_ObjRequired
(
p
,
i
,
0
)
);
Nf_ObjMapRefInc
(
p
,
Gia_ObjFaninId0
(
pObj
,
i
),
Gia_ObjFaninC0
(
pObj
));
continue
;
}
// skip if this node is not used
for
(
c
=
0
;
c
<
2
;
c
++
)
{
nRefs
[
c
]
=
Nf_ObjMapRefNum
(
p
,
i
,
c
);
//if ( Nf_ObjMatchD( p, i, c )->fCompl )
// printf( "Match D of node %d has inv in phase %d.\n", i, c );
//if ( Nf_ObjMatchA( p, i, c )->fCompl )
// printf( "Match A of node %d has inv in phase %d.\n", i, c );
}
if
(
!
nRefs
[
0
]
&&
!
nRefs
[
1
]
)
continue
;
// consider two cases
if
(
nRefs
[
0
]
&&
nRefs
[
1
]
)
{
// find best matches for both phases
for
(
c
=
0
;
c
<
2
;
c
++
)
{
Requireds
[
c
]
=
Nf_ObjRequired
(
p
,
i
,
c
);
assert
(
Requireds
[
c
]
<
NF_INFINITY
);
pDs
[
c
]
=
Nf_ObjMatchD
(
p
,
i
,
c
);
pAs
[
c
]
=
Nf_ObjMatchA
(
p
,
i
,
c
);
pMs
[
c
]
=
(
pAs
[
c
]
->
D
<
Requireds
[
c
]
+
Epsilon
)
?
pAs
[
c
]
:
pDs
[
c
];
}
// swap complemented matches
if
(
pMs
[
0
]
->
fCompl
&&
pMs
[
1
]
->
fCompl
)
{
pMs
[
0
]
->
fCompl
=
pMs
[
1
]
->
fCompl
=
0
;
ABC_SWAP
(
Nf_Mat_t
*
,
pMs
[
0
],
pMs
[
1
]
);
}
// check if intervers are involved
if
(
!
pMs
[
0
]
->
fCompl
&&
!
pMs
[
1
]
->
fCompl
)
{
// no inverters
for
(
c
=
0
;
c
<
2
;
c
++
)
Nf_ManSetMapRefsGate
(
p
,
i
,
Requireds
[
c
],
pMs
[
c
]
);
}
else
{
// one interver
assert
(
!
pMs
[
0
]
->
fCompl
||
!
pMs
[
1
]
->
fCompl
);
c
=
pMs
[
1
]
->
fCompl
;
assert
(
pMs
[
c
]
->
fCompl
&&
!
pMs
[
!
c
]
->
fCompl
);
//printf( "Using inverter at node %d in phase %d\n", i, c );
// update this phase phase
pM
=
pMs
[
c
];
pM
->
fBest
=
1
;
Required
=
Requireds
[
c
];
// update opposite phase
Nf_ObjMapRefInc
(
p
,
i
,
!
c
);
Nf_ObjUpdateRequired
(
p
,
i
,
!
c
,
Required
-
p
->
InvDelay
);
// select oppositve phase
Required
=
Nf_ObjRequired
(
p
,
i
,
!
c
);
assert
(
Required
<
NF_INFINITY
);
pD
=
Nf_ObjMatchD
(
p
,
i
,
!
c
);
pA
=
Nf_ObjMatchA
(
p
,
i
,
!
c
);
pM
=
(
pA
->
D
<
Required
+
Epsilon
)
?
pA
:
pD
;
assert
(
!
pM
->
fCompl
);
// account for the inverter
p
->
pPars
->
MapArea
+=
p
->
InvArea
;
p
->
pPars
->
Edge
++
;
p
->
pPars
->
Area
++
;
p
->
nInvs
++
;
// create gate
Nf_ManSetMapRefsGate
(
p
,
i
,
Required
,
pM
);
}
}
else
{
c
=
(
int
)(
nRefs
[
1
]
>
0
);
assert
(
nRefs
[
c
]
&&
!
nRefs
[
!
c
]
);
// consider this phase
Required
=
Nf_ObjRequired
(
p
,
i
,
c
);
assert
(
Required
<
NF_INFINITY
);
pD
=
Nf_ObjMatchD
(
p
,
i
,
c
);
pA
=
Nf_ObjMatchA
(
p
,
i
,
c
);
pM
=
(
pA
->
D
<
Required
+
Epsilon
)
?
pA
:
pD
;
if
(
pM
->
fCompl
)
// use inverter
{
p
->
nInvs
++
;
//printf( "Using inverter at node %d in phase %d\n", i, c );
pM
->
fBest
=
1
;
// update opposite phase
Nf_ObjMapRefInc
(
p
,
i
,
!
c
);
Nf_ObjUpdateRequired
(
p
,
i
,
!
c
,
Required
-
p
->
InvDelay
);
// select oppositve phase
Required
=
Nf_ObjRequired
(
p
,
i
,
!
c
);
assert
(
Required
<
NF_INFINITY
);
pD
=
Nf_ObjMatchD
(
p
,
i
,
!
c
);
pA
=
Nf_ObjMatchA
(
p
,
i
,
!
c
);
pM
=
(
pA
->
D
<
Required
+
Epsilon
)
?
pA
:
pD
;
assert
(
!
pM
->
fCompl
);
// account for the inverter
p
->
pPars
->
MapArea
+=
p
->
InvArea
;
p
->
pPars
->
Edge
++
;
p
->
pPars
->
Area
++
;
}
// create gate
Nf_ManSetMapRefsGate
(
p
,
i
,
Required
,
pM
);
}
// the result of this:
// - only one phase can be implemented as inverter of the other phase
// - required times are propagated correctly
// - references are set correctly
}
Gia_ManForEachCiId
(
p
->
pGia
,
Id
,
i
)
if
(
Nf_ObjMapRefNum
(
p
,
Id
,
1
)
)
{
Nf_ObjMapRefInc
(
p
,
Id
,
0
);
Nf_ObjUpdateRequired
(
p
,
Id
,
0
,
Required
-
p
->
InvDelay
);
p
->
pPars
->
MapArea
+=
p
->
InvArea
;
p
->
pPars
->
Edge
++
;
p
->
pPars
->
Area
++
;
p
->
nInvs
++
;
}
// blend references
for
(
i
=
0
;
i
<
nLits
;
i
++
)
// pFlowRefs[i] = Abc_MaxFloat(1.0, pMapRefs[i]);
pFlowRefs
[
i
]
=
Abc_MaxFloat
(
1
.
0
,
Coef
*
pFlowRefs
[
i
]
+
(
1
.
0
-
Coef
)
*
Abc_MaxFloat
(
1
,
pMapRefs
[
i
]));
// pFlowRefs[i] = 0.2 * pFlowRefs[i] + 0.8 * Abc_MaxFloat(1, pMapRefs[i]);
// memset( pMapRefs, 0, sizeof(int) * nLits );
return
p
->
pPars
->
Area
;
}
Gia_Man_t
*
Nf_ManDeriveMapping
(
Nf_Man_t
*
p
)
{
Vec_Int_t
*
vMapping
;
Nf_Mat_t
*
pM
;
int
i
,
k
,
c
,
Id
,
iLit
,
*
pCut
;
assert
(
p
->
pGia
->
vCellMapping
==
NULL
);
vMapping
=
Vec_IntAlloc
(
2
*
Gia_ManObjNum
(
p
->
pGia
)
+
(
int
)
p
->
pPars
->
Edge
+
(
int
)
p
->
pPars
->
Area
*
2
);
Vec_IntFill
(
vMapping
,
2
*
Gia_ManObjNum
(
p
->
pGia
),
0
);
// create CI inverters
Gia_ManForEachCiId
(
p
->
pGia
,
Id
,
i
)
if
(
Nf_ObjMapRefNum
(
p
,
Id
,
1
)
)
Vec_IntWriteEntry
(
vMapping
,
Abc_Var2Lit
(
Id
,
1
),
-
1
);
// create internal nodes
Gia_ManForEachAndId
(
p
->
pGia
,
i
)
{
Gia_Obj_t
*
pObj
=
Gia_ManObj
(
p
->
pGia
,
i
);
if
(
Gia_ObjIsBuf
(
pObj
)
)
{
if
(
Nf_ObjMapRefNum
(
p
,
i
,
1
)
)
Vec_IntWriteEntry
(
vMapping
,
Abc_Var2Lit
(
i
,
1
),
-
1
);
Vec_IntWriteEntry
(
vMapping
,
Abc_Var2Lit
(
i
,
0
),
-
2
);
continue
;
}
for
(
c
=
0
;
c
<
2
;
c
++
)
if
(
Nf_ObjMapRefNum
(
p
,
i
,
c
)
)
{
// printf( "Using %d %d\n", i, c );
pM
=
Nf_ObjMatchBest
(
p
,
i
,
c
);
// remember inverter
if
(
pM
->
fCompl
)
{
Vec_IntWriteEntry
(
vMapping
,
Abc_Var2Lit
(
i
,
c
),
-
1
);
continue
;
}
// Nf_ManCutMatchprintf( p, i, c, pM );
pCut
=
Nf_CutFromHandle
(
Nf_ObjCutSet
(
p
,
i
),
pM
->
CutH
);
// create mapping
Vec_IntWriteEntry
(
vMapping
,
Abc_Var2Lit
(
i
,
c
),
Vec_IntSize
(
vMapping
)
);
Vec_IntPush
(
vMapping
,
Nf_CutSize
(
pCut
)
);
Nf_CutForEachLit
(
pCut
,
pM
->
Conf
,
iLit
,
k
)
Vec_IntPush
(
vMapping
,
iLit
);
Vec_IntPush
(
vMapping
,
pM
->
Gate
);
}
}
// assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) );
p
->
pGia
->
vCellMapping
=
vMapping
;
return
p
->
pGia
;
}
void
Nf_ManUpdateStats
(
Nf_Man_t
*
p
)
{
Nf_Mat_t
*
pM
;
Gia_Obj_t
*
pObj
;
Mio_Cell_t
*
pCell
;
int
i
,
c
,
Id
,
*
pCut
;
p
->
pPars
->
MapDelay
=
0
;
Gia_ManForEachCo
(
p
->
pGia
,
pObj
,
i
)
{
float
Delay
=
Nf_ObjMatchD
(
p
,
Gia_ObjFaninId0p
(
p
->
pGia
,
pObj
),
Gia_ObjFaninC0
(
pObj
)
)
->
D
;
p
->
pPars
->
MapDelay
=
Abc_MaxFloat
(
p
->
pPars
->
MapDelay
,
Delay
);
}
p
->
pPars
->
MapArea
=
0
;
p
->
pPars
->
Area
=
p
->
pPars
->
Edge
=
0
;
Gia_ManForEachAndId
(
p
->
pGia
,
i
)
for
(
c
=
0
;
c
<
2
;
c
++
)
if
(
Nf_ObjMapRefNum
(
p
,
i
,
c
)
)
{
pM
=
Nf_ObjMatchBest
(
p
,
i
,
c
);
pCut
=
Nf_CutFromHandle
(
Nf_ObjCutSet
(
p
,
i
),
pM
->
CutH
);
pCell
=
Nf_ManCell
(
p
,
pM
->
Gate
);
assert
(
Nf_CutSize
(
pCut
)
==
(
int
)
pCell
->
nFanins
);
p
->
pPars
->
MapArea
+=
pCell
->
Area
;
p
->
pPars
->
Edge
+=
Nf_CutSize
(
pCut
);
p
->
pPars
->
Area
++
;
}
Gia_ManForEachCiId
(
p
->
pGia
,
Id
,
i
)
if
(
Nf_ObjMapRefNum
(
p
,
Id
,
1
)
)
{
p
->
pPars
->
MapArea
+=
p
->
InvArea
;
p
->
pPars
->
Edge
++
;
p
->
pPars
->
Area
++
;
}
}
/**Function*************************************************************
Synopsis [Technology mappping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
/*
static inline Nf_Mat_t * Nf_ObjMatchBestReq( Nf_Man_t * p, int i, int c, float r )
{
Nf_Mat_t * pD = Nf_ObjMatchD(p, i, c);
Nf_Mat_t * pA = Nf_ObjMatchA(p, i, c);
assert( !pD->fBest && !pA->fBest );
assert( Nf_ObjMapRefNum(p, i, c) == 0 );
if ( pA->D < r + p->pPars->Epsilon )
return pA;
return pD;
}
float Nf_MatchDeref_rec( Nf_Man_t * p, int i, int c, Nf_Mat_t * pM )
{
int k, iVar, fCompl, * pCut;
float Area = 0;
int Value = pM->fBest;
pM->fBest = 0;
if ( pM->fCompl )
{
assert( Nf_ObjMapRefNum(p, i, !c) > 0 );
if ( !Nf_ObjMapRefDec(p, i, !c) )
Area += Nf_MatchDeref_rec( p, i, !c, Nf_ObjMatchBest(p, i, !c) );
return Area + p->InvArea;
}
if ( Nf_ObjCutSetId(p, i) == 0 )
return 0;
assert( Value == 1 );
pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, i), pM->CutH );
Nf_CutForEachVar( pCut, pM->Conf, iVar, fCompl, k )
{
assert( Nf_ObjMapRefNum(p, iVar, fCompl) > 0 );
if ( !Nf_ObjMapRefDec(p, iVar, fCompl) )
Area += Nf_MatchDeref_rec( p, iVar, fCompl, Nf_ObjMatchBest(p, iVar, fCompl) );
}
return Area + Nf_ManCell(p, pM->Gate)->Area;
}
float Nf_MatchRef_rec( Nf_Man_t * p, int i, int c, Nf_Mat_t * pM, float Required, Vec_Int_t * vBackup )
{
int k, iVar, fCompl, * pCut;
float ReqFanin, Area = 0;
assert( pM->fBest == 0 );
if ( vBackup == NULL )
pM->fBest = 1;
if ( pM->fCompl )
{
ReqFanin = Required - p->InvDelay;
if ( vBackup )
Vec_IntPush( vBackup, Abc_Var2Lit(i, !c) );
assert( Nf_ObjMapRefNum(p, i, !c) >= 0 );
if ( !Nf_ObjMapRefInc(p, i, !c) )
Area += Nf_MatchRef_rec( p, i, !c, Nf_ObjMatchBestReq(p, i, !c, ReqFanin), ReqFanin, vBackup );
return Area + p->InvArea;
}
if ( Nf_ObjCutSetId(p, i) == 0 )
return 0;
pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, i), pM->CutH );
Nf_CutForEachVar( pCut, pM->Conf, iVar, fCompl, k )
{
ReqFanin = Required - Nf_ManCell(p, pM->Gate)->Delays[k];
if ( vBackup )
Vec_IntPush( vBackup, Abc_Var2Lit(iVar, fCompl) );
assert( Nf_ObjMapRefNum(p, iVar, fCompl) >= 0 );
if ( !Nf_ObjMapRefInc(p, iVar, fCompl) )
Area += Nf_MatchRef_rec( p, iVar, fCompl, Nf_ObjMatchBestReq(p, iVar, fCompl, ReqFanin), ReqFanin, vBackup );
}
return Area + Nf_ManCell(p, pM->Gate)->Area;
}
float Nf_MatchRefArea( Nf_Man_t * p, int i, int c, Nf_Mat_t * pM, float Required )
{
float Area; int iLit, k;
Vec_IntClear( &p->vBackup );
Area = Nf_MatchRef_rec( p, i, c, pM, Required, &p->vBackup );
Vec_IntForEachEntry( &p->vBackup, iLit, k )
{
assert( Nf_ObjMapRefNum(p, Abc_Lit2Var(iLit), Abc_LitIsCompl(iLit)) > 0 );
Nf_ObjMapRefDec( p, Abc_Lit2Var(iLit), Abc_LitIsCompl(iLit) );
}
return Area;
}
void Nf_ManElaBestMatchOne( Nf_Man_t * p, int iObj, int c, int * pCut, int * pCutSet, Nf_Mat_t * pRes, float Required )
{
Nf_Mat_t Mb, * pMb = &Mb;
Nf_Obj_t * pBest = Nf_ManObj(p, iObj);
int * pFans = Nf_CutLeaves(pCut);
int nFans = Nf_CutSize(pCut);
int iFuncLit = Nf_CutFunc(pCut);
int fComplExt = Abc_LitIsCompl(iFuncLit);
float Epsilon = p->pPars->Epsilon;
Vec_Int_t * vArr = Vec_WecEntry( p->vTt2Match, Abc_Lit2Var(iFuncLit) );
int i, k, Info, Offset, iFanin, fComplF;
float ArrivalD, ArrivalA;
// assign fanins matches
Nf_Obj_t * pBestF[NF_LEAF_MAX];
for ( i = 0; i < nFans; i++ )
pBestF[i] = Nf_ManObj( p, pFans[i] );
// special cases
if ( nFans < 2 )
{
*pRes = *Nf_ObjMatchBestReq( p, iObj, c, Required );
return;
}
// consider matches of this function
memset( pMb, 0, sizeof(Nf_Mat_t) );
pMb->D = pMb->A = NF_INFINITY;
Vec_IntForEachEntryDouble( vArr, Info, Offset, i )
{
Mio_Cell_t* pC = Nf_ManCell( p, Info >> 8 );
int Type = (Info >> 4) & 15;
int fCompl = (Info & 1) ^ fComplExt;
char * pInfo = Vec_StrEntryP( p->vMemStore, Offset );
Nf_Mat_t * pD = &pBest->M[fCompl][0];
Nf_Mat_t * pA = &pBest->M[fCompl][1];
assert( nFans == (int)pC->nFanins );
if ( fCompl != c )
continue;
if ( Type == NF_PRIME )
{
float Delay = 0;
for ( k = 0; k < nFans; k++ )
{
iFanin = Abc_Lit2Var((int)pInfo[k]);
fComplF = Abc_LitIsCompl((int)pInfo[k]);
ArrivalD = pBestF[k]->M[fComplF][0].D;
ArrivalA = pBestF[k]->M[fComplF][1].D;
if ( ArrivalA + pC->Delays[iFanin] < Required + Epsilon && Required != NF_INFINITY )
Delay = Abc_MaxFloat( Delay, ArrivalA + pC->Delays[iFanin] );
else
Delay = Abc_MaxFloat( Delay, ArrivalD + pC->Delays[iFanin] );
if ( Delay > Required + Epsilon )
break;
}
if ( k < nFans )
continue;
// create match
pMb->D = Delay;
pMb->A = -1;
pMb->CutH = Nf_CutHandle(pCutSet, pCut);
pMb->Gate = pC->Id;
pMb->Conf = 0;
for ( k = 0; k < nFans; k++ )
// pD->Conf |= ((int)pInfo[k] << (k << 2));
pMb->Conf |= (Abc_Var2Lit(k, Abc_LitIsCompl((int)pInfo[k])) << (Abc_Lit2Var((int)pInfo[k]) << 2));
// compute area
pMb->A = Nf_MatchRefArea( p, iObj, c, pMb, Required );
// compare
if ( pRes->A > pMb->A + Epsilon || (pRes->A == pMb->A && pRes->D > pMb->D + Epsilon) )
*pRes = *pMb;
}
}
}
void Nf_ManElaBestMatch( Nf_Man_t * p, int iObj, int c, Nf_Mat_t * pRes, float Required )
{
int k, * pCut, * pCutSet = Nf_ObjCutSet( p, iObj );
memset( pRes, 0, sizeof(Nf_Mat_t) );
pRes->D = pRes->A = NF_INFINITY;
Nf_SetForEachCut( pCutSet, pCut, k )
{
if ( Abc_Lit2Var(Nf_CutFunc(pCut)) >= Vec_WecSize(p->vTt2Match) )
continue;
Nf_ManElaBestMatchOne( p, iObj, c, pCut, pCutSet, pRes, Required );
}
}
// the best match is stored in pA provided that it satisfies pA->D < req
// area is never compared
void Nf_ManComputeMappingEla( Nf_Man_t * p )
{
Gia_Obj_t * pObj;
Mio_Cell_t * pCell;
Nf_Mat_t Mb, * pMb = &Mb, * pM;
float Epsilon = p->pPars->Epsilon;
float AreaBef, AreaAft, Required, MapArea;
int nLits = 2*Gia_ManObjNum(p->pGia);
int i, c, iVar, Id, fCompl, k, * pCut;
Vec_FltFill( &p->vRequired, nLits, NF_INFINITY );
// compute delay
p->pPars->MapDelay = 0;
Gia_ManForEachCo( p->pGia, pObj, i )
{
Required = Nf_ObjMatchD( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj) )->D;
p->pPars->MapDelay = Abc_MaxFloat( p->pPars->MapDelay, Required );
}
// check delay target
if ( p->pPars->MapDelayTarget == -1 && p->pPars->nRelaxRatio )
p->pPars->MapDelayTarget = (int)((float)p->pPars->MapDelay * (100.0 + p->pPars->nRelaxRatio) / 100.0);
if ( p->pPars->MapDelayTarget != -1 )
{
if ( p->pPars->MapDelay < p->pPars->MapDelayTarget + Epsilon )
p->pPars->MapDelay = p->pPars->MapDelayTarget;
else if ( p->pPars->nRelaxRatio == 0 )
Abc_Print( 0, "Relaxing user-specified delay target from %.2f to %.2f.\n", p->pPars->MapDelayTarget, p->pPars->MapDelay );
}
// set required times
Gia_ManForEachCo( p->pGia, pObj, i )
{
Required = Nf_ObjMatchD( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj) )->D;
Required = p->pPars->fDoAverage ? Required * (100.0 + p->pPars->nRelaxRatio) / 100.0 : p->pPars->MapDelay;
Nf_ObjUpdateRequired( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj), Required );
Nf_ObjMapRefInc( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj));
}
// compute area and edges
MapArea = p->pPars->MapArea;
p->pPars->MapArea = 0;
p->pPars->Area = p->pPars->Edge = 0;
Gia_ManForEachAndReverseId( p->pGia, i )
for ( c = 0; c < 2; c++ )
if ( Nf_ObjMapRefNum(p, i, c) )
{
pM = Nf_ObjMatchBest( p, i, c );
Required = Nf_ObjRequired( p, i, c );
assert( pM->D < Required + Epsilon );
// try different cuts at this node and find best match
Vec_IntClear( &p->vBackup2 );
AreaBef = Nf_MatchDeref_rec( p, i, c, pM );
Nf_ManElaBestMatch( p, i, c, pMb, Required );
AreaAft = Nf_MatchRef_rec( p, i, c, pMb, Required, NULL );
assert( pMb->A == AreaAft );
assert( AreaBef + Epsilon > AreaAft );
MapArea += AreaAft - AreaBef;
// printf( "%8.2f %8.2f\n", AreaBef, AreaAft );
// set match
assert( pMb->D < Required + Epsilon );
assert( pMb->fBest == 0 );
*Nf_ObjMatchA(p, i, c) = *pMb;
assert( Nf_ObjMatchA(p, i, c) == Nf_ObjMatchBest( p, i, c ) );
// count status
pCell = Nf_ManCell( p, pMb->Gate );
pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, i), pMb->CutH );
Nf_CutForEachVar( pCut, pMb->Conf, iVar, fCompl, k )
Nf_ObjUpdateRequired( p, iVar, fCompl, Required - pCell->Delays[k] );
p->pPars->MapArea += pCell->Area;
p->pPars->Edge += Nf_CutSize(pCut);
p->pPars->Area++;
}
Gia_ManForEachCiId( p->pGia, Id, i )
if ( Nf_ObjMapRefNum(p, Id, 1) )
{
Nf_ObjMapRefInc( p, Id, 0 );
Nf_ObjUpdateRequired( p, Id, 0, Required - p->InvDelay );
p->pPars->MapArea += p->InvArea;
p->pPars->Edge++;
p->pPars->Area++;
}
// Nf_ManUpdateStats( p );
if ( !(MapArea < p->pPars->MapArea + Epsilon && MapArea + Epsilon > p->pPars->MapArea) )
printf( "Mismatch: Estimated = %.2f Real = %.2f\n", MapArea, p->pPars->MapArea );
// assert( MapArea < p->pPars->MapArea + Epsilon && MapArea + Epsilon > p->pPars->MapArea );
Nf_ManPrintStats( p, "Ela " );
}
*/
/**Function*************************************************************
Synopsis [Technology mappping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void
Nf_ManSetDefaultPars
(
Jf_Par_t
*
pPars
)
{
memset
(
pPars
,
0
,
sizeof
(
Jf_Par_t
)
);
pPars
->
nLutSize
=
6
;
pPars
->
nCutNum
=
16
;
pPars
->
nProcNum
=
0
;
pPars
->
nRounds
=
3
;
pPars
->
nRoundsEla
=
0
;
pPars
->
nRelaxRatio
=
0
;
pPars
->
nCoarseLimit
=
3
;
pPars
->
nAreaTuner
=
1
;
pPars
->
nVerbLimit
=
5
;
pPars
->
DelayTarget
=
-
1
;
pPars
->
fAreaOnly
=
0
;
pPars
->
fOptEdge
=
1
;
pPars
->
fCoarsen
=
0
;
pPars
->
fCutMin
=
1
;
pPars
->
fGenCnf
=
0
;
pPars
->
fPureAig
=
0
;
pPars
->
fVerbose
=
0
;
pPars
->
fVeryVerbose
=
0
;
pPars
->
nLutSizeMax
=
NF_LEAF_MAX
;
pPars
->
nCutNumMax
=
NF_CUT_MAX
;
pPars
->
MapDelayTarget
=
-
1
;
pPars
->
Epsilon
=
(
float
)
0
.
01
;
}
Gia_Man_t
*
Nf_ManPerformMapping
(
Gia_Man_t
*
pGia
,
Jf_Par_t
*
pPars
)
{
Gia_Man_t
*
pNew
=
NULL
,
*
pCls
;
Nf_Man_t
*
p
;
int
i
,
Id
;
if
(
Gia_ManHasChoices
(
pGia
)
)
pPars
->
fCoarsen
=
0
;
pCls
=
pPars
->
fCoarsen
?
Gia_ManDupMuxes
(
pGia
,
pPars
->
nCoarseLimit
)
:
pGia
;
p
=
Nf_StoCreate
(
pCls
,
pPars
);
// if ( pPars->fVeryVerbose )
// Nf_StoPrint( p, pPars->fVeryVerbose );
if
(
pPars
->
fVerbose
&&
pPars
->
fCoarsen
)
{
printf
(
"Initial "
);
Gia_ManPrintMuxStats
(
pGia
);
printf
(
"
\n
"
);
printf
(
"Derived "
);
Gia_ManPrintMuxStats
(
pCls
);
printf
(
"
\n
"
);
}
Nf_ManPrintInit
(
p
);
Nf_ManComputeCuts
(
p
);
Nf_ManPrintQuit
(
p
);
Gia_ManForEachCiId
(
p
->
pGia
,
Id
,
i
)
Nf_ObjPrepareCi
(
p
,
Id
);
for
(
p
->
Iter
=
0
;
p
->
Iter
<
p
->
pPars
->
nRounds
;
p
->
Iter
++
)
{
Nf_ManComputeMapping
(
p
);
Nf_ManSetMapRefs
(
p
);
Nf_ManPrintStats
(
p
,
p
->
Iter
?
"Area "
:
"Delay"
);
}
p
->
fUseEla
=
1
;
for
(
;
p
->
Iter
<
p
->
pPars
->
nRounds
+
pPars
->
nRoundsEla
;
p
->
Iter
++
)
{
Nf_ManComputeMapping
(
p
);
Nf_ManUpdateStats
(
p
);
Nf_ManPrintStats
(
p
,
"Ela "
);
}
pNew
=
Nf_ManDeriveMapping
(
p
);
// Gia_ManMappingVerify( pNew );
Nf_StoDelete
(
p
);
if
(
pCls
!=
pGia
)
Gia_ManStop
(
pCls
);
if
(
pNew
==
NULL
)
return
Gia_ManDup
(
pGia
);
return
pNew
;
}
////////////////////////////////////////////////////////////////////////
...
...
src/aig/gia/giaStr.c
View file @
88c57c93
...
...
@@ -6,7 +6,7 @@
PackageName [Scalable AIG package.]
Synopsis [
Cut computation
.]
Synopsis [
AIG structuring
.]
Author [Alan Mishchenko]
...
...
@@ -19,6 +19,9 @@
***********************************************************************/
#include "gia.h"
#include "misc/util/utilNam.h"
#include "misc/vec/vecWec.h"
#include "misc/tim/tim.h"
ABC_NAMESPACE_IMPL_START
...
...
@@ -26,15 +29,1343 @@ ABC_NAMESPACE_IMPL_START
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define STR_SUPER 100
enum
{
STR_NONE
=
0
,
STR_CONST0
=
1
,
STR_PI
=
2
,
STR_AND
=
3
,
STR_XOR
=
4
,
STR_MUX
=
5
,
STR_BUF
=
6
,
STR_PO
=
7
,
STR_UNUSED
=
8
};
typedef
struct
Str_Obj_t_
Str_Obj_t
;
struct
Str_Obj_t_
{
unsigned
Type
:
4
;
// object type
unsigned
nFanins
:
28
;
// fanin count
int
iOffset
;
// place where fanins are stored
int
iTop
;
// top level MUX
int
iCopy
;
// copy of this node
};
typedef
struct
Str_Ntk_t_
Str_Ntk_t
;
struct
Str_Ntk_t_
{
int
nObjs
;
// object count
int
nObjsAlloc
;
// alloc objects
Str_Obj_t
*
pObjs
;
// objects
Vec_Int_t
vFanins
;
// object fanins
int
nObjCount
[
STR_UNUSED
];
int
nTrees
;
int
nGroups
;
int
DelayGain
;
};
typedef
struct
Str_Man_t_
Str_Man_t
;
struct
Str_Man_t_
{
// user data
Gia_Man_t
*
pOld
;
// manager
int
nLutSize
;
// LUT size
int
fCutMin
;
// cut minimization
// internal data
Str_Ntk_t
*
pNtk
;
// balanced network
// AIG under construction
Gia_Man_t
*
pNew
;
// newly constructed
Vec_Int_t
*
vDelays
;
// delays of each object
};
static
inline
Str_Obj_t
*
Str_NtkObj
(
Str_Ntk_t
*
p
,
int
i
)
{
assert
(
i
<
p
->
nObjs
);
return
p
->
pObjs
+
i
;
}
static
inline
int
Str_ObjFaninId
(
Str_Ntk_t
*
p
,
Str_Obj_t
*
pObj
,
int
i
)
{
return
Abc_Lit2Var
(
Vec_IntEntry
(
&
p
->
vFanins
,
pObj
->
iOffset
+
i
)
);
}
static
inline
Str_Obj_t
*
Str_ObjFanin
(
Str_Ntk_t
*
p
,
Str_Obj_t
*
pObj
,
int
i
)
{
return
Str_NtkObj
(
p
,
Str_ObjFaninId
(
p
,
pObj
,
i
)
);
}
static
inline
int
Str_ObjFaninC
(
Str_Ntk_t
*
p
,
Str_Obj_t
*
pObj
,
int
i
)
{
return
Abc_LitIsCompl
(
Vec_IntEntry
(
&
p
->
vFanins
,
pObj
->
iOffset
+
i
)
);
}
static
inline
int
Str_ObjFaninCopy
(
Str_Ntk_t
*
p
,
Str_Obj_t
*
pObj
,
int
i
)
{
return
Abc_LitNotCond
(
Str_ObjFanin
(
p
,
pObj
,
i
)
->
iCopy
,
Str_ObjFaninC
(
p
,
pObj
,
i
)
);
}
static
inline
int
Str_ObjId
(
Str_Ntk_t
*
p
,
Str_Obj_t
*
pObj
)
{
return
pObj
-
p
->
pObjs
;
}
#define Str_NtkManForEachObj( p, pObj ) \
for ( pObj = p->pObjs; Str_ObjId(p, pObj) < p->nObjs; pObj++ )
#define Str_NtkManForEachObjVec( vVec, p, pObj, i ) \
for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Str_NtkObj(p, Vec_IntEntry(vVec,i))); i++ )
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Logic network manipulation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Str_ObjCreate
(
Str_Ntk_t
*
p
,
int
Type
,
int
nFanins
,
int
*
pFanins
)
{
Str_Obj_t
*
pObj
=
p
->
pObjs
+
p
->
nObjs
;
int
i
;
assert
(
p
->
nObjs
<
p
->
nObjsAlloc
);
pObj
->
Type
=
Type
;
pObj
->
nFanins
=
nFanins
;
pObj
->
iOffset
=
Vec_IntSize
(
&
p
->
vFanins
);
pObj
->
iTop
=
pObj
->
iCopy
=
-
1
;
for
(
i
=
0
;
i
<
nFanins
;
i
++
)
{
Vec_IntPush
(
&
p
->
vFanins
,
pFanins
[
i
]
);
assert
(
pFanins
[
i
]
>=
0
);
}
p
->
nObjCount
[
Type
]
++
;
return
Abc_Var2Lit
(
p
->
nObjs
++
,
0
);
}
static
inline
Str_Ntk_t
*
Str_NtkCreate
(
int
nObjsAlloc
,
int
nFaninsAlloc
)
{
Str_Ntk_t
*
p
;
p
=
ABC_CALLOC
(
Str_Ntk_t
,
1
);
p
->
pObjs
=
ABC_ALLOC
(
Str_Obj_t
,
nObjsAlloc
);
p
->
nObjsAlloc
=
nObjsAlloc
;
Str_ObjCreate
(
p
,
STR_CONST0
,
0
,
NULL
);
Vec_IntGrow
(
&
p
->
vFanins
,
nFaninsAlloc
);
return
p
;
}
static
inline
void
Str_NtkDelete
(
Str_Ntk_t
*
p
)
{
// printf( "Total delay gain = %d.\n", p->DelayGain );
ABC_FREE
(
p
->
vFanins
.
pArray
);
ABC_FREE
(
p
->
pObjs
);
ABC_FREE
(
p
);
}
static
inline
void
Str_NtkPs
(
Str_Ntk_t
*
p
,
abctime
clk
)
{
printf
(
"Network contains %d ands, %d xors, %d muxes (%d trees in %d groups). "
,
p
->
nObjCount
[
STR_AND
],
p
->
nObjCount
[
STR_XOR
],
p
->
nObjCount
[
STR_MUX
],
p
->
nTrees
,
p
->
nGroups
);
Abc_PrintTime
(
1
,
"Time"
,
clk
);
}
static
inline
void
Str_ObjReadGroup
(
Str_Ntk_t
*
p
,
Str_Obj_t
*
pObj
,
int
*
pnGroups
,
int
*
pnMuxes
)
{
Str_Obj_t
*
pObj1
,
*
pObj2
;
*
pnGroups
=
*
pnMuxes
=
0
;
if
(
pObj
->
iTop
==
0
)
return
;
pObj1
=
Str_NtkObj
(
p
,
pObj
->
iTop
);
pObj2
=
Str_NtkObj
(
p
,
pObj1
->
iTop
);
*
pnMuxes
=
pObj1
-
pObj
+
1
;
*
pnGroups
=
(
pObj2
-
pObj
+
1
)
/
*
pnMuxes
;
}
static
inline
void
Str_NtkPrintGroups
(
Str_Ntk_t
*
p
)
{
Str_Obj_t
*
pObj
;
int
nGroups
,
nMuxes
;
Str_NtkManForEachObj
(
p
,
pObj
)
if
(
pObj
->
Type
==
STR_MUX
&&
pObj
->
iTop
>
0
)
{
Str_ObjReadGroup
(
p
,
pObj
,
&
nGroups
,
&
nMuxes
);
pObj
+=
nGroups
*
nMuxes
-
1
;
printf
(
"%d x %d "
,
nGroups
,
nMuxes
);
}
printf
(
"
\n
"
);
}
Gia_Man_t
*
Str_NtkToGia
(
Gia_Man_t
*
pGia
,
Str_Ntk_t
*
p
)
{
Gia_Man_t
*
pNew
,
*
pTemp
;
Str_Obj_t
*
pObj
;
int
k
;
assert
(
pGia
->
pMuxes
==
NULL
);
pNew
=
Gia_ManStart
(
3
*
Gia_ManObjNum
(
pGia
)
/
2
);
pNew
->
pName
=
Abc_UtilStrsav
(
pGia
->
pName
);
pNew
->
pSpec
=
Abc_UtilStrsav
(
pGia
->
pSpec
);
Gia_ManHashStart
(
pNew
);
Str_NtkManForEachObj
(
p
,
pObj
)
{
if
(
pObj
->
Type
==
STR_PI
)
pObj
->
iCopy
=
Gia_ManAppendCi
(
pNew
);
else
if
(
pObj
->
Type
==
STR_AND
)
{
pObj
->
iCopy
=
1
;
for
(
k
=
0
;
k
<
(
int
)
pObj
->
nFanins
;
k
++
)
pObj
->
iCopy
=
Gia_ManHashAnd
(
pNew
,
pObj
->
iCopy
,
Str_ObjFaninCopy
(
p
,
pObj
,
k
)
);
}
else
if
(
pObj
->
Type
==
STR_XOR
)
{
pObj
->
iCopy
=
0
;
for
(
k
=
0
;
k
<
(
int
)
pObj
->
nFanins
;
k
++
)
pObj
->
iCopy
=
Gia_ManHashXor
(
pNew
,
pObj
->
iCopy
,
Str_ObjFaninCopy
(
p
,
pObj
,
k
)
);
}
else
if
(
pObj
->
Type
==
STR_MUX
)
pObj
->
iCopy
=
Gia_ManHashMux
(
pNew
,
Str_ObjFaninCopy
(
p
,
pObj
,
2
),
Str_ObjFaninCopy
(
p
,
pObj
,
1
),
Str_ObjFaninCopy
(
p
,
pObj
,
0
)
);
else
if
(
pObj
->
Type
==
STR_PO
)
pObj
->
iCopy
=
Gia_ManAppendCo
(
pNew
,
Str_ObjFaninCopy
(
p
,
pObj
,
0
)
);
else
if
(
pObj
->
Type
==
STR_CONST0
)
pObj
->
iCopy
=
0
;
else
assert
(
0
);
}
Gia_ManHashStop
(
pNew
);
// assert( Gia_ManObjNum(pNew) <= Gia_ManObjNum(pGia) );
Gia_ManSetRegNum
(
pNew
,
Gia_ManRegNum
(
pGia
)
);
pNew
=
Gia_ManCleanup
(
pTemp
=
pNew
);
Gia_ManStop
(
pTemp
);
return
pNew
;
}
/**Function*************************************************************
Synopsis [Constructs a normalized AIG without structural hashing.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t
*
Gia_ManDupMuxesNoHash
(
Gia_Man_t
*
p
)
{
Gia_Man_t
*
pNew
;
Gia_Obj_t
*
pObj
,
*
pFan0
,
*
pFan1
,
*
pFanC
;
int
i
,
iLit0
,
iLit1
,
fCompl
;
assert
(
p
->
pMuxes
==
NULL
);
ABC_FREE
(
p
->
pRefs
);
Gia_ManCreateRefs
(
p
);
// discount nodes with one fanout pointed to by MUX type
Gia_ManForEachAnd
(
p
,
pObj
,
i
)
{
if
(
!
Gia_ObjIsMuxType
(
pObj
)
)
continue
;
Gia_ObjRefDec
(
p
,
Gia_ObjFanin0
(
pObj
));
Gia_ObjRefDec
(
p
,
Gia_ObjFanin1
(
pObj
));
}
// start the new manager
pNew
=
Gia_ManStart
(
Gia_ManObjNum
(
p
)
);
pNew
->
pName
=
Abc_UtilStrsav
(
p
->
pName
);
pNew
->
pSpec
=
Abc_UtilStrsav
(
p
->
pSpec
);
pNew
->
pMuxes
=
ABC_CALLOC
(
unsigned
,
pNew
->
nObjsAlloc
);
Gia_ManFillValue
(
p
);
Gia_ManConst0
(
p
)
->
Value
=
0
;
Gia_ManForEachCi
(
p
,
pObj
,
i
)
pObj
->
Value
=
Gia_ManAppendCi
(
pNew
);
Gia_ManForEachAnd
(
p
,
pObj
,
i
)
{
if
(
!
Gia_ObjRefNumId
(
p
,
i
)
)
continue
;
if
(
!
Gia_ObjIsMuxType
(
pObj
)
)
pObj
->
Value
=
Gia_ManAppendAnd
(
pNew
,
Gia_ObjFanin0Copy
(
pObj
),
Gia_ObjFanin1Copy
(
pObj
)
);
else
if
(
Gia_ObjRecognizeExor
(
pObj
,
&
pFan0
,
&
pFan1
)
)
{
iLit0
=
Gia_ObjLitCopy
(
p
,
Gia_ObjToLit
(
p
,
pFan0
));
iLit1
=
Gia_ObjLitCopy
(
p
,
Gia_ObjToLit
(
p
,
pFan1
));
fCompl
=
Abc_LitIsCompl
(
iLit0
)
^
Abc_LitIsCompl
(
iLit1
);
pObj
->
Value
=
fCompl
^
Gia_ManAppendXorReal
(
pNew
,
Abc_LitRegular
(
iLit0
),
Abc_LitRegular
(
iLit1
)
);
}
else
{
pFanC
=
Gia_ObjRecognizeMux
(
pObj
,
&
pFan1
,
&
pFan0
);
iLit0
=
Gia_ObjLitCopy
(
p
,
Gia_ObjToLit
(
p
,
pFan0
));
iLit1
=
Gia_ObjLitCopy
(
p
,
Gia_ObjToLit
(
p
,
pFan1
));
if
(
iLit0
==
iLit1
)
pObj
->
Value
=
iLit0
;
else
if
(
Abc_Lit2Var
(
iLit0
)
==
Abc_Lit2Var
(
iLit1
)
)
{
iLit1
=
Gia_ObjLitCopy
(
p
,
Gia_ObjToLit
(
p
,
pFanC
));
fCompl
=
Abc_LitIsCompl
(
iLit0
)
^
Abc_LitIsCompl
(
iLit1
);
pObj
->
Value
=
fCompl
^
Gia_ManAppendXorReal
(
pNew
,
Abc_LitRegular
(
iLit0
),
Abc_LitRegular
(
iLit1
)
);
}
else
pObj
->
Value
=
Gia_ManAppendMuxReal
(
pNew
,
Gia_ObjLitCopy
(
p
,
Gia_ObjToLit
(
p
,
pFanC
)),
Gia_ObjLitCopy
(
p
,
Gia_ObjToLit
(
p
,
pFan1
)),
Gia_ObjLitCopy
(
p
,
Gia_ObjToLit
(
p
,
pFan0
))
);
}
}
Gia_ManForEachCo
(
p
,
pObj
,
i
)
pObj
->
Value
=
Gia_ManAppendCo
(
pNew
,
Gia_ObjFanin0Copy
(
pObj
)
);
Gia_ManSetRegNum
(
pNew
,
Gia_ManRegNum
(
p
)
);
assert
(
!
Gia_ManHasDangling
(
pNew
)
);
return
pNew
;
}
/**Function*************************************************************
Synopsis [Constructs AIG ordered for balancing.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void
Str_MuxInputsCollect_rec
(
Gia_Man_t
*
p
,
Gia_Obj_t
*
pObj
,
Vec_Int_t
*
vNodes
)
{
if
(
!
pObj
->
fMark0
)
{
Vec_IntPush
(
vNodes
,
Gia_ObjId
(
p
,
pObj
)
);
return
;
}
Vec_IntPush
(
vNodes
,
Gia_ObjFaninId2p
(
p
,
pObj
)
);
Str_MuxInputsCollect_rec
(
p
,
Gia_ObjFanin0
(
pObj
),
vNodes
);
Str_MuxInputsCollect_rec
(
p
,
Gia_ObjFanin1
(
pObj
),
vNodes
);
}
void
Str_MuxInputsCollect
(
Gia_Man_t
*
p
,
Gia_Obj_t
*
pObj
,
Vec_Int_t
*
vNodes
)
{
assert
(
!
pObj
->
fMark0
);
pObj
->
fMark0
=
1
;
Vec_IntClear
(
vNodes
);
Str_MuxInputsCollect_rec
(
p
,
pObj
,
vNodes
);
pObj
->
fMark0
=
0
;
}
void
Str_MuxStructCollect_rec
(
Gia_Man_t
*
p
,
Gia_Obj_t
*
pObj
,
Vec_Int_t
*
vNodes
)
{
if
(
!
pObj
->
fMark0
)
return
;
Str_MuxStructCollect_rec
(
p
,
Gia_ObjFanin0
(
pObj
),
vNodes
);
Str_MuxStructCollect_rec
(
p
,
Gia_ObjFanin1
(
pObj
),
vNodes
);
Vec_IntPush
(
vNodes
,
Gia_ObjId
(
p
,
pObj
)
);
}
void
Str_MuxStructCollect
(
Gia_Man_t
*
p
,
Gia_Obj_t
*
pObj
,
Vec_Int_t
*
vNodes
)
{
assert
(
!
pObj
->
fMark0
);
pObj
->
fMark0
=
1
;
Vec_IntClear
(
vNodes
);
Str_MuxStructCollect_rec
(
p
,
pObj
,
vNodes
);
pObj
->
fMark0
=
0
;
}
void
Str_MuxStructDump_rec
(
Gia_Man_t
*
p
,
Gia_Obj_t
*
pObj
,
Vec_Str_t
*
vStr
)
{
if
(
!
pObj
->
fMark0
)
return
;
Vec_StrPush
(
vStr
,
'['
);
Vec_StrPush
(
vStr
,
'('
);
Vec_StrPrintNum
(
vStr
,
Gia_ObjFaninId2p
(
p
,
pObj
)
);
Vec_StrPush
(
vStr
,
')'
);
Str_MuxStructDump_rec
(
p
,
Gia_ObjFaninC2
(
p
,
pObj
)
?
Gia_ObjFanin0
(
pObj
)
:
Gia_ObjFanin1
(
pObj
),
vStr
);
Vec_StrPush
(
vStr
,
'|'
);
Str_MuxStructDump_rec
(
p
,
Gia_ObjFaninC2
(
p
,
pObj
)
?
Gia_ObjFanin1
(
pObj
)
:
Gia_ObjFanin0
(
pObj
),
vStr
);
Vec_StrPush
(
vStr
,
']'
);
}
void
Str_MuxStructDump
(
Gia_Man_t
*
p
,
Gia_Obj_t
*
pObj
,
Vec_Str_t
*
vStr
)
{
assert
(
!
pObj
->
fMark0
);
pObj
->
fMark0
=
1
;
Vec_StrClear
(
vStr
);
Str_MuxStructDump_rec
(
p
,
pObj
,
vStr
);
Vec_StrPush
(
vStr
,
'\0'
);
pObj
->
fMark0
=
0
;
}
int
Str_ManMuxCountOne
(
char
*
p
)
{
int
Count
=
0
;
for
(
;
*
p
;
p
++
)
Count
+=
(
*
p
==
'['
);
return
Count
;
}
Vec_Wec_t
*
Str_ManDeriveTrees
(
Gia_Man_t
*
p
)
{
int
fPrintStructs
=
0
;
Abc_Nam_t
*
pNames
;
Vec_Wec_t
*
vGroups
;
Vec_Str_t
*
vStr
;
Gia_Obj_t
*
pObj
,
*
pFanin
;
int
i
,
iStructId
,
fFound
;
assert
(
p
->
pMuxes
!=
NULL
);
// mark MUXes whose only fanout is a MUX
ABC_FREE
(
p
->
pRefs
);
Gia_ManCreateRefs
(
p
);
Gia_ManForEachMuxId
(
p
,
i
)
{
pObj
=
Gia_ManObj
(
p
,
i
);
pFanin
=
Gia_ObjFanin0
(
pObj
);
if
(
Gia_ObjIsMux
(
p
,
pFanin
)
&&
Gia_ObjRefNum
(
p
,
pFanin
)
==
1
)
pFanin
->
fMark0
=
1
;
pFanin
=
Gia_ObjFanin1
(
pObj
);
if
(
Gia_ObjIsMux
(
p
,
pFanin
)
&&
Gia_ObjRefNum
(
p
,
pFanin
)
==
1
)
pFanin
->
fMark0
=
1
;
}
// traverse for top level MUXes
vStr
=
Vec_StrAlloc
(
1000
);
pNames
=
Abc_NamStart
(
10000
,
50
);
vGroups
=
Vec_WecAlloc
(
1000
);
Vec_WecPushLevel
(
vGroups
);
Gia_ManForEachMuxId
(
p
,
i
)
{
// skip internal
pObj
=
Gia_ManObj
(
p
,
i
);
if
(
pObj
->
fMark0
)
continue
;
// skip trees of size one
if
(
!
Gia_ObjFanin0
(
pObj
)
->
fMark0
&&
!
Gia_ObjFanin1
(
pObj
)
->
fMark0
)
continue
;
// hash the tree
Str_MuxStructDump
(
p
,
pObj
,
vStr
);
iStructId
=
Abc_NamStrFindOrAdd
(
pNames
,
Vec_StrArray
(
vStr
),
&
fFound
);
if
(
!
fFound
)
Vec_WecPushLevel
(
vGroups
);
assert
(
Abc_NamObjNumMax
(
pNames
)
==
Vec_WecSize
(
vGroups
)
);
Vec_IntPush
(
Vec_WecEntry
(
vGroups
,
iStructId
),
i
);
}
if
(
fPrintStructs
)
{
char
*
pTemp
;
Abc_NamManForEachObj
(
pNames
,
pTemp
,
i
)
{
printf
(
"%5d : "
,
i
);
printf
(
"Occur = %4d "
,
Vec_IntSize
(
Vec_WecEntry
(
vGroups
,
i
))
);
printf
(
"Size = %4d "
,
Str_ManMuxCountOne
(
pTemp
)
);
printf
(
"%s
\n
"
,
pTemp
);
}
}
Abc_NamStop
(
pNames
);
Vec_StrFree
(
vStr
);
return
vGroups
;
}
Vec_Int_t
*
Str_ManCreateRoots
(
Vec_Wec_t
*
vGroups
,
int
nObjs
)
{
// map tree MUXes into their classes
Vec_Int_t
*
vRoots
;
Vec_Int_t
*
vGroup
;
int
i
,
k
,
Entry
;
vRoots
=
Vec_IntStartFull
(
nObjs
);
Vec_WecForEachLevel
(
vGroups
,
vGroup
,
i
)
Vec_IntForEachEntry
(
vGroup
,
Entry
,
k
)
Vec_IntWriteEntry
(
vRoots
,
Entry
,
i
);
return
vRoots
;
}
void
Str_MuxTraverse_rec
(
Gia_Man_t
*
p
,
int
i
)
{
Gia_Obj_t
*
pObj
;
if
(
Gia_ObjIsTravIdCurrentId
(
p
,
i
)
)
return
;
Gia_ObjSetTravIdCurrentId
(
p
,
i
);
pObj
=
Gia_ManObj
(
p
,
i
);
if
(
!
Gia_ObjIsAnd
(
pObj
)
)
return
;
Str_MuxTraverse_rec
(
p
,
Gia_ObjFaninId0
(
pObj
,
i
)
);
Str_MuxTraverse_rec
(
p
,
Gia_ObjFaninId1
(
pObj
,
i
)
);
if
(
Gia_ObjIsMux
(
p
,
pObj
)
)
Str_MuxTraverse_rec
(
p
,
Gia_ObjFaninId2
(
p
,
i
)
);
}
void
Str_ManCheckOverlap
(
Gia_Man_t
*
p
,
Vec_Wec_t
*
vGroups
)
{
// check that members of each group are not in the TFI of each other
Vec_Int_t
*
vGroup
,
*
vGroup2
;
int
i
,
k
,
n
,
iObj
,
iObj2
;
// vGroup = Vec_WecEntry(vGroups, 7);
// Vec_IntForEachEntry( vGroup, iObj, n )
// Gia_ManPrintCone2( p, Gia_ManObj(p, iObj) ), printf( "\n" );
Vec_WecForEachLevel
(
vGroups
,
vGroup
,
i
)
Vec_IntForEachEntry
(
vGroup
,
iObj
,
k
)
{
if
(
Vec_IntSize
(
vGroup
)
==
1
)
continue
;
// high light the cone
Gia_ManIncrementTravId
(
p
);
Str_MuxTraverse_rec
(
p
,
iObj
);
// check that none of the others are highlighted
Vec_IntForEachEntry
(
vGroup
,
iObj2
,
n
)
if
(
iObj
!=
iObj2
&&
Gia_ObjIsTravIdCurrentId
(
p
,
iObj2
)
)
break
;
if
(
n
==
Vec_IntSize
(
vGroup
)
)
continue
;
// split the group into individual trees
Vec_IntForEachEntryStart
(
vGroup
,
iObj2
,
n
,
1
)
{
vGroup2
=
Vec_WecPushLevel
(
vGroups
);
vGroup
=
Vec_WecEntry
(
vGroups
,
i
);
Vec_IntPush
(
vGroup2
,
iObj2
);
}
Vec_IntShrink
(
vGroup
,
1
);
/*
// this does not work because there can be a pair of independent trees
// with another tree squeezed in between them, so that there is a combo loop
// divide this group
nNew = 0;
vGroup2 = Vec_WecPushLevel( vGroups );
vGroup = Vec_WecEntry( vGroups, i );
Vec_IntForEachEntry( vGroup, iObj2, n )
{
if ( iObj != iObj2 && Gia_ObjIsTravIdCurrentId(p, iObj2) )
Vec_IntPush( vGroup2, iObj2 );
else
Vec_IntWriteEntry( vGroup, nNew++, iObj2 );
}
Vec_IntShrink( vGroup, nNew );
i--;
break;
*/
/*
// check that none of the others are highlighted
Vec_IntForEachEntry( vGroup, iObj, n )
if ( n != k && Gia_ObjIsTravIdCurrentId(p, iObj) )
{
printf( "Overlap of TFI cones of trees %d and %d in group %d of size %d!\n", k, n, i, Vec_IntSize(vGroup) );
Vec_IntShrink( vGroup, 1 );
break;
}
*/
}
}
/**Function*************************************************************
Synopsis [Simplify multi-input AND/XOR.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
void
Gia_ManSimplifyXor
(
Vec_Int_t
*
vSuper
)
{
int
i
,
k
=
0
,
Prev
=
-
1
,
This
,
fCompl
=
0
;
Vec_IntForEachEntry
(
vSuper
,
This
,
i
)
{
if
(
This
==
0
)
continue
;
if
(
This
==
1
)
fCompl
^=
1
;
else
if
(
Prev
!=
This
)
Vec_IntWriteEntry
(
vSuper
,
k
++
,
This
),
Prev
=
This
;
else
Prev
=
-
1
,
k
--
;
}
Vec_IntShrink
(
vSuper
,
k
);
if
(
Vec_IntSize
(
vSuper
)
==
0
)
Vec_IntPush
(
vSuper
,
fCompl
);
else
if
(
fCompl
)
Vec_IntWriteEntry
(
vSuper
,
0
,
Abc_LitNot
(
Vec_IntEntry
(
vSuper
,
0
))
);
}
static
inline
void
Gia_ManSimplifyAnd
(
Vec_Int_t
*
vSuper
)
{
int
i
,
k
=
0
,
Prev
=
-
1
,
This
;
Vec_IntForEachEntry
(
vSuper
,
This
,
i
)
{
if
(
This
==
0
)
{
Vec_IntFill
(
vSuper
,
1
,
0
);
return
;
}
if
(
This
==
1
)
continue
;
if
(
Prev
==
-
1
||
Abc_Lit2Var
(
Prev
)
!=
Abc_Lit2Var
(
This
)
)
Vec_IntWriteEntry
(
vSuper
,
k
++
,
This
),
Prev
=
This
;
else
if
(
Prev
!=
This
)
{
Vec_IntFill
(
vSuper
,
1
,
0
);
return
;
}
}
Vec_IntShrink
(
vSuper
,
k
);
if
(
Vec_IntSize
(
vSuper
)
==
0
)
Vec_IntPush
(
vSuper
,
1
);
}
/**Function*************************************************************
Synopsis [Collect multi-input AND/XOR.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
void
Gia_ManSuperCollectXor_rec
(
Gia_Man_t
*
p
,
Gia_Obj_t
*
pObj
)
{
assert
(
!
Gia_IsComplement
(
pObj
)
);
if
(
!
Gia_ObjIsXor
(
pObj
)
||
Gia_ObjRefNum
(
p
,
pObj
)
>
1
||
// Gia_ObjRefNum(p, pObj) > 3 ||
// (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) ||
Vec_IntSize
(
p
->
vSuper
)
>
STR_SUPER
)
{
Vec_IntPush
(
p
->
vSuper
,
Gia_ObjToLit
(
p
,
pObj
)
);
return
;
}
assert
(
!
Gia_ObjFaninC0
(
pObj
)
&&
!
Gia_ObjFaninC1
(
pObj
)
);
Gia_ManSuperCollectXor_rec
(
p
,
Gia_ObjFanin0
(
pObj
)
);
Gia_ManSuperCollectXor_rec
(
p
,
Gia_ObjFanin1
(
pObj
)
);
}
static
inline
void
Gia_ManSuperCollectAnd_rec
(
Gia_Man_t
*
p
,
Gia_Obj_t
*
pObj
)
{
if
(
Gia_IsComplement
(
pObj
)
||
!
Gia_ObjIsAndReal
(
p
,
pObj
)
||
Gia_ObjRefNum
(
p
,
pObj
)
>
1
||
// Gia_ObjRefNum(p, pObj) > 3 ||
// (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) ||
Vec_IntSize
(
p
->
vSuper
)
>
STR_SUPER
)
{
Vec_IntPush
(
p
->
vSuper
,
Gia_ObjToLit
(
p
,
pObj
)
);
return
;
}
Gia_ManSuperCollectAnd_rec
(
p
,
Gia_ObjChild0
(
pObj
)
);
Gia_ManSuperCollectAnd_rec
(
p
,
Gia_ObjChild1
(
pObj
)
);
}
static
inline
void
Gia_ManSuperCollect
(
Gia_Man_t
*
p
,
Gia_Obj_t
*
pObj
)
{
if
(
p
->
vSuper
==
NULL
)
p
->
vSuper
=
Vec_IntAlloc
(
STR_SUPER
);
else
Vec_IntClear
(
p
->
vSuper
);
if
(
Gia_ObjIsXor
(
pObj
)
)
{
assert
(
!
Gia_ObjFaninC0
(
pObj
)
&&
!
Gia_ObjFaninC1
(
pObj
)
);
Gia_ManSuperCollectXor_rec
(
p
,
Gia_ObjFanin0
(
pObj
)
);
Gia_ManSuperCollectXor_rec
(
p
,
Gia_ObjFanin1
(
pObj
)
);
Vec_IntSort
(
p
->
vSuper
,
0
);
Gia_ManSimplifyXor
(
p
->
vSuper
);
}
else
if
(
Gia_ObjIsAndReal
(
p
,
pObj
)
)
{
Gia_ManSuperCollectAnd_rec
(
p
,
Gia_ObjChild0
(
pObj
)
);
Gia_ManSuperCollectAnd_rec
(
p
,
Gia_ObjChild1
(
pObj
)
);
Vec_IntSort
(
p
->
vSuper
,
0
);
Gia_ManSimplifyAnd
(
p
->
vSuper
);
}
else
assert
(
0
);
assert
(
Vec_IntSize
(
p
->
vSuper
)
>
0
);
}
/**Function*************************************************************
Synopsis [Constructs AIG ordered for balancing.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void
Str_ManNormalize_rec
(
Str_Ntk_t
*
pNtk
,
Gia_Man_t
*
p
,
Gia_Obj_t
*
pObj
,
Vec_Wec_t
*
vGroups
,
Vec_Int_t
*
vRoots
)
{
int
i
,
k
,
iVar
,
iLit
,
iBeg
,
iEnd
;
if
(
~
pObj
->
Value
)
return
;
pObj
->
Value
=
0
;
assert
(
Gia_ObjIsAnd
(
pObj
)
);
if
(
Gia_ObjIsMux
(
p
,
pObj
)
)
{
Vec_Int_t
*
vGroup
;
Gia_Obj_t
*
pRoot
,
*
pMux
;
int
pFanins
[
3
];
if
(
Vec_IntEntry
(
vRoots
,
Gia_ObjId
(
p
,
pObj
))
==
-
1
)
{
Str_ManNormalize_rec
(
pNtk
,
p
,
Gia_ObjFanin0
(
pObj
),
vGroups
,
vRoots
);
Str_ManNormalize_rec
(
pNtk
,
p
,
Gia_ObjFanin1
(
pObj
),
vGroups
,
vRoots
);
Str_ManNormalize_rec
(
pNtk
,
p
,
Gia_ObjFanin2
(
p
,
pObj
),
vGroups
,
vRoots
);
pFanins
[
0
]
=
Gia_ObjFanin0Copy
(
pObj
);
pFanins
[
1
]
=
Gia_ObjFanin1Copy
(
pObj
);
pFanins
[
2
]
=
Gia_ObjFanin2Copy
(
p
,
pObj
);
if
(
Abc_LitIsCompl
(
pFanins
[
2
])
)
{
pFanins
[
2
]
=
Abc_LitNot
(
pFanins
[
2
]);
ABC_SWAP
(
int
,
pFanins
[
0
],
pFanins
[
1
]
);
}
pObj
->
Value
=
Str_ObjCreate
(
pNtk
,
STR_MUX
,
3
,
pFanins
);
return
;
}
vGroup
=
Vec_WecEntry
(
vGroups
,
Vec_IntEntry
(
vRoots
,
Gia_ObjId
(
p
,
pObj
))
);
// build data-inputs for each tree
Gia_ManForEachObjVec
(
vGroup
,
p
,
pRoot
,
i
)
{
Str_MuxInputsCollect
(
p
,
pRoot
,
p
->
vSuper
);
iBeg
=
Vec_IntSize
(
p
->
vStore
);
Vec_IntAppend
(
p
->
vStore
,
p
->
vSuper
);
iEnd
=
Vec_IntSize
(
p
->
vStore
);
Vec_IntForEachEntryStartStop
(
p
->
vStore
,
iVar
,
k
,
iBeg
,
iEnd
)
Str_ManNormalize_rec
(
pNtk
,
p
,
Gia_ManObj
(
p
,
iVar
),
vGroups
,
vRoots
);
Vec_IntShrink
(
p
->
vStore
,
iBeg
);
}
// build internal structures
Gia_ManForEachObjVec
(
vGroup
,
p
,
pRoot
,
i
)
{
Str_MuxStructCollect
(
p
,
pRoot
,
p
->
vSuper
);
Gia_ManForEachObjVec
(
p
->
vSuper
,
p
,
pMux
,
k
)
{
pFanins
[
0
]
=
Gia_ObjFanin0Copy
(
pMux
);
pFanins
[
1
]
=
Gia_ObjFanin1Copy
(
pMux
);
pFanins
[
2
]
=
Gia_ObjFanin2Copy
(
p
,
pMux
);
if
(
Abc_LitIsCompl
(
pFanins
[
2
])
)
{
pFanins
[
2
]
=
Abc_LitNot
(
pFanins
[
2
]);
ABC_SWAP
(
int
,
pFanins
[
0
],
pFanins
[
1
]
);
}
pMux
->
Value
=
Str_ObjCreate
(
pNtk
,
STR_MUX
,
3
,
pFanins
);
}
assert
(
~
pRoot
->
Value
);
// set mapping
Gia_ManForEachObjVec
(
p
->
vSuper
,
p
,
pMux
,
k
)
Str_NtkObj
(
pNtk
,
Abc_Lit2Var
(
pMux
->
Value
))
->
iTop
=
Abc_Lit2Var
(
pRoot
->
Value
);
pNtk
->
nTrees
++
;
}
assert
(
~
pObj
->
Value
);
// set mapping
pObj
=
Gia_ManObj
(
p
,
Vec_IntEntryLast
(
vGroup
)
);
Gia_ManForEachObjVec
(
vGroup
,
p
,
pRoot
,
i
)
Str_NtkObj
(
pNtk
,
Abc_Lit2Var
(
pRoot
->
Value
))
->
iTop
=
Abc_Lit2Var
(
pObj
->
Value
);
pNtk
->
nGroups
++
;
//printf( "%d x %d ", Vec_IntSize(vGroup), Vec_IntSize(p->vSuper) );
return
;
}
// find supergate
Gia_ManSuperCollect
(
p
,
pObj
);
// save entries
iBeg
=
Vec_IntSize
(
p
->
vStore
);
Vec_IntAppend
(
p
->
vStore
,
p
->
vSuper
);
iEnd
=
Vec_IntSize
(
p
->
vStore
);
// call recursively
Vec_IntForEachEntryStartStop
(
p
->
vStore
,
iLit
,
i
,
iBeg
,
iEnd
)
{
Gia_Obj_t
*
pTemp
=
Gia_ManObj
(
p
,
Abc_Lit2Var
(
iLit
)
);
Str_ManNormalize_rec
(
pNtk
,
p
,
pTemp
,
vGroups
,
vRoots
);
Vec_IntWriteEntry
(
p
->
vStore
,
i
,
Abc_LitNotCond
(
pTemp
->
Value
,
Abc_LitIsCompl
(
iLit
))
);
}
assert
(
Vec_IntSize
(
p
->
vStore
)
==
iEnd
);
// consider general case
pObj
->
Value
=
Str_ObjCreate
(
pNtk
,
Gia_ObjIsXor
(
pObj
)
?
STR_XOR
:
STR_AND
,
iEnd
-
iBeg
,
Vec_IntEntryP
(
p
->
vStore
,
iBeg
)
);
Vec_IntShrink
(
p
->
vStore
,
iBeg
);
}
Str_Ntk_t
*
Str_ManNormalizeInt
(
Gia_Man_t
*
p
,
Vec_Wec_t
*
vGroups
,
Vec_Int_t
*
vRoots
)
{
Str_Ntk_t
*
pNtk
;
Gia_Obj_t
*
pObj
;
int
i
,
iFanin
;
assert
(
p
->
pMuxes
!=
NULL
);
if
(
p
->
vSuper
==
NULL
)
p
->
vSuper
=
Vec_IntAlloc
(
STR_SUPER
);
if
(
p
->
vStore
==
NULL
)
p
->
vStore
=
Vec_IntAlloc
(
STR_SUPER
);
Gia_ManFillValue
(
p
);
pNtk
=
Str_NtkCreate
(
Gia_ManObjNum
(
p
),
1
+
Gia_ManCoNum
(
p
)
+
2
*
Gia_ManAndNum
(
p
)
+
Gia_ManMuxNum
(
p
)
);
Gia_ManConst0
(
p
)
->
Value
=
0
;
Gia_ManForEachObj1
(
p
,
pObj
,
i
)
{
if
(
Gia_ObjIsCi
(
pObj
)
)
pObj
->
Value
=
Str_ObjCreate
(
pNtk
,
STR_PI
,
0
,
NULL
);
else
if
(
Gia_ObjIsCo
(
pObj
)
)
{
Str_ManNormalize_rec
(
pNtk
,
p
,
Gia_ObjFanin0
(
pObj
),
vGroups
,
vRoots
);
iFanin
=
Gia_ObjFanin0Copy
(
pObj
);
pObj
->
Value
=
Str_ObjCreate
(
pNtk
,
STR_PO
,
1
,
&
iFanin
);
}
}
assert
(
pNtk
->
nObjs
<=
Gia_ManObjNum
(
p
)
);
return
pNtk
;
}
Str_Ntk_t
*
Str_ManNormalize
(
Gia_Man_t
*
p
)
{
Str_Ntk_t
*
pNtk
;
Gia_Man_t
*
pMuxes
=
Gia_ManDupMuxes
(
p
,
5
);
Vec_Wec_t
*
vGroups
=
Str_ManDeriveTrees
(
pMuxes
);
Vec_Int_t
*
vRoots
;
Str_ManCheckOverlap
(
pMuxes
,
vGroups
);
vRoots
=
Str_ManCreateRoots
(
vGroups
,
Gia_ManObjNum
(
pMuxes
)
);
pNtk
=
Str_ManNormalizeInt
(
pMuxes
,
vGroups
,
vRoots
);
Gia_ManCleanMark0
(
pMuxes
);
Gia_ManStop
(
pMuxes
);
Vec_IntFree
(
vRoots
);
Vec_WecFree
(
vGroups
);
return
pNtk
;
}
/**Function*************************************************************
Synopsis [Delay computation]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Str_Delay2
(
int
d0
,
int
d1
,
int
nLutSize
)
{
int
n
,
d
=
Abc_MaxInt
(
d0
>>
4
,
d1
>>
4
);
n
=
(
d
==
(
d0
>>
4
))
?
(
d0
&
15
)
:
1
;
n
+=
(
d
==
(
d1
>>
4
))
?
(
d1
&
15
)
:
1
;
return
(
d
<<
4
)
+
(
n
>
nLutSize
?
18
:
n
);
}
static
inline
int
Str_Delay3
(
int
d0
,
int
d1
,
int
d2
,
int
nLutSize
)
{
int
n
,
d
=
Abc_MaxInt
(
Abc_MaxInt
(
d0
>>
4
,
d1
>>
4
),
d2
>>
4
);
n
=
(
d
==
(
d0
>>
4
))
?
(
d0
&
15
)
:
1
;
n
+=
(
d
==
(
d1
>>
4
))
?
(
d1
&
15
)
:
1
;
n
+=
(
d
==
(
d2
>>
4
))
?
(
d2
&
15
)
:
1
;
return
(
d
<<
4
)
+
(
n
>
nLutSize
?
19
:
n
);
}
static
inline
int
Str_ObjDelay
(
Gia_Man_t
*
pNew
,
int
iObj
,
int
nLutSize
,
Vec_Int_t
*
vDelay
)
{
int
Delay
=
Vec_IntEntry
(
vDelay
,
iObj
);
if
(
Delay
==
0
)
{
if
(
Gia_ObjIsMuxId
(
pNew
,
iObj
)
)
{
int
d0
=
Vec_IntEntry
(
vDelay
,
Gia_ObjFaninId0
(
Gia_ManObj
(
pNew
,
iObj
),
iObj
)
);
int
d1
=
Vec_IntEntry
(
vDelay
,
Gia_ObjFaninId1
(
Gia_ManObj
(
pNew
,
iObj
),
iObj
)
);
int
d2
=
Vec_IntEntry
(
vDelay
,
Gia_ObjFaninId2
(
pNew
,
iObj
)
);
Delay
=
Str_Delay3
(
d0
,
d1
,
d2
,
nLutSize
);
}
else
{
int
d0
=
Vec_IntEntry
(
vDelay
,
Gia_ObjFaninId0
(
Gia_ManObj
(
pNew
,
iObj
),
iObj
)
);
int
d1
=
Vec_IntEntry
(
vDelay
,
Gia_ObjFaninId1
(
Gia_ManObj
(
pNew
,
iObj
),
iObj
)
);
Delay
=
Str_Delay2
(
d0
,
d1
,
nLutSize
);
}
Vec_IntWriteEntry
(
vDelay
,
iObj
,
Delay
);
}
return
Delay
;
}
/**Function*************************************************************
Synopsis [Transposing 64-bit matrix.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
void
transpose64
(
word
A
[
64
]
)
{
int
j
,
k
;
word
t
,
m
=
0x00000000FFFFFFFF
;
for
(
j
=
32
;
j
!=
0
;
j
=
j
>>
1
,
m
=
m
^
(
m
<<
j
)
)
{
for
(
k
=
0
;
k
<
64
;
k
=
(
k
+
j
+
1
)
&
~
j
)
{
t
=
(
A
[
k
]
^
(
A
[
k
+
j
]
>>
j
))
&
m
;
A
[
k
]
=
A
[
k
]
^
t
;
A
[
k
+
j
]
=
A
[
k
+
j
]
^
(
t
<<
j
);
}
}
}
/**Function*************************************************************
Synopsis [Perform affinity computation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Str_ManNum
(
Gia_Man_t
*
p
,
int
iObj
)
{
return
Vec_IntEntry
(
&
p
->
vCopies
,
iObj
);
}
static
inline
void
Str_ManSetNum
(
Gia_Man_t
*
p
,
int
iObj
,
int
Num
)
{
Vec_IntWriteEntry
(
&
p
->
vCopies
,
iObj
,
Num
);
}
int
Str_ManVectorAffinity
(
Gia_Man_t
*
p
,
Vec_Int_t
*
vSuper
,
Vec_Int_t
*
vDelay
,
word
Matrix
[
256
],
int
nLimit
)
{
int
fVerbose
=
0
;
int
Levels
[
256
];
int
nSize
=
Vec_IntSize
(
vSuper
);
int
Prev
=
nSize
,
nLevels
=
1
;
int
i
,
k
,
iLit
,
iFanin
,
nSizeNew
;
word
Mask
;
assert
(
nSize
>
2
);
if
(
nSize
>
64
)
{
for
(
i
=
0
;
i
<
64
;
i
++
)
Matrix
[
i
]
=
0
;
return
0
;
}
// mark current nodes
Gia_ManIncrementTravId
(
p
);
Vec_IntForEachEntry
(
vSuper
,
iLit
,
i
)
{
Gia_ObjSetTravIdCurrentId
(
p
,
Abc_Lit2Var
(
iLit
)
);
Str_ManSetNum
(
p
,
Abc_Lit2Var
(
iLit
),
i
);
Matrix
[
i
]
=
((
word
)
1
)
<<
(
63
-
i
);
Levels
[
i
]
=
0
;
}
// collect 64 nodes
Vec_IntForEachEntry
(
vSuper
,
iLit
,
i
)
{
Gia_Obj_t
*
pObj
=
Gia_ManObj
(
p
,
Abc_Lit2Var
(
iLit
)
);
if
(
Gia_ObjIsAnd
(
pObj
)
)
{
for
(
k
=
0
;
k
<
2
;
k
++
)
{
iFanin
=
k
?
Gia_ObjFaninId1p
(
p
,
pObj
)
:
Gia_ObjFaninId0p
(
p
,
pObj
);
if
(
!
Gia_ObjIsTravIdCurrentId
(
p
,
iFanin
)
)
{
if
(
Vec_IntSize
(
vSuper
)
==
nLimit
)
break
;
Gia_ObjSetTravIdCurrentId
(
p
,
iFanin
);
Matrix
[
Vec_IntSize
(
vSuper
)]
=
0
;
Levels
[
Vec_IntSize
(
vSuper
)]
=
nLevels
;
Str_ManSetNum
(
p
,
iFanin
,
Vec_IntSize
(
vSuper
)
);
Vec_IntPush
(
vSuper
,
Abc_Var2Lit
(
iFanin
,
0
)
);
}
Matrix
[
Str_ManNum
(
p
,
iFanin
)]
|=
Matrix
[
i
];
}
}
if
(
Gia_ObjIsMux
(
p
,
pObj
)
)
{
iFanin
=
Gia_ObjFaninId2p
(
p
,
pObj
);
if
(
!
Gia_ObjIsTravIdCurrentId
(
p
,
iFanin
)
)
{
if
(
Vec_IntSize
(
vSuper
)
==
nLimit
)
break
;
Gia_ObjSetTravIdCurrentId
(
p
,
iFanin
);
Matrix
[
Vec_IntSize
(
vSuper
)]
=
0
;
Levels
[
Vec_IntSize
(
vSuper
)]
=
nLevels
;
Str_ManSetNum
(
p
,
iFanin
,
Vec_IntSize
(
vSuper
)
);
Vec_IntPush
(
vSuper
,
Abc_Var2Lit
(
iFanin
,
0
)
);
}
Matrix
[
Str_ManNum
(
p
,
iFanin
)]
|=
Matrix
[
i
];
}
if
(
Prev
==
i
)
Prev
=
Vec_IntSize
(
vSuper
),
nLevels
++
;
if
(
nLevels
==
8
)
break
;
}
// remove those that have all 1s or only one 1
Mask
=
(
~
(
word
)
0
)
<<
(
64
-
nSize
);
for
(
k
=
i
=
0
;
i
<
Vec_IntSize
(
vSuper
);
i
++
)
{
assert
(
Matrix
[
i
]
);
if
(
(
Matrix
[
i
]
&
(
Matrix
[
i
]
-
1
))
==
0
)
continue
;
if
(
Matrix
[
i
]
==
Mask
)
continue
;
Matrix
[
k
]
=
Matrix
[
i
];
Levels
[
k
]
=
Levels
[
i
];
k
++
;
if
(
k
==
64
)
break
;
}
// clean the remaining ones
for
(
i
=
k
;
i
<
64
;
i
++
)
Matrix
[
i
]
=
0
;
nSizeNew
=
k
;
if
(
nSizeNew
==
0
)
{
Vec_IntShrink
(
vSuper
,
nSize
);
return
0
;
}
/*
// report
if ( fVerbose && nSize > 20 )
{
for ( i = 0; i < nSizeNew; i++ )
Extra_PrintBinary( stdout, Matrix+i, 64 ), printf( "\n" );
printf( "\n" );
}
*/
transpose64
(
Matrix
);
// report
if
(
fVerbose
&&
nSize
>
10
)
{
printf
(
"Gate inputs = %d. Collected fanins = %d. All = %d. Good = %d. Levels = %d
\n
"
,
nSize
,
Vec_IntSize
(
vSuper
)
-
nSize
,
Vec_IntSize
(
vSuper
),
nSizeNew
,
nLevels
);
printf
(
" "
);
for
(
i
=
0
;
i
<
nSizeNew
;
i
++
)
printf
(
"%d"
,
Levels
[
i
]
);
printf
(
"
\n
"
);
for
(
i
=
0
;
i
<
nSize
;
i
++
)
{
printf
(
"%6d : "
,
Abc_Lit2Var
(
Vec_IntEntry
(
vSuper
,
i
))
);
printf
(
"%3d "
,
Vec_IntEntry
(
vDelay
,
i
)
>>
4
);
printf
(
"%3d "
,
Vec_IntEntry
(
vDelay
,
i
)
&
15
);
// Extra_PrintBinary( stdout, Matrix+i, 64 ), printf( "\n" );
}
i
=
0
;
}
Vec_IntShrink
(
vSuper
,
nSize
);
return
nSizeNew
;
}
/**Function*************************************************************
Synopsis [Count 1s.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static
inline
int
Str_CountBits
(
word
i
)
{
if
(
i
==
0
)
return
0
;
i
=
(
i
&
(
i
-
1
));
if
(
i
==
0
)
return
1
;
i
=
(
i
&
(
i
-
1
));
if
(
i
==
0
)
return
2
;
i
=
i
-
((
i
>>
1
)
&
0x5555555555555555
);
i
=
(
i
&
0x3333333333333333
)
+
((
i
>>
2
)
&
0x3333333333333333
);
i
=
((
i
+
(
i
>>
4
))
&
0x0F0F0F0F0F0F0F0F
);
return
(
i
*
(
0x0101010101010101
))
>>
56
;
}
static
inline
void
Str_PrintState
(
int
*
pCost
,
int
*
pSuper
,
word
*
pMatrix
,
int
nSize
)
{
int
i
;
for
(
i
=
0
;
i
<
nSize
;
i
++
)
{
printf
(
"%6d : "
,
i
);
printf
(
"%6d : "
,
Abc_Lit2Var
(
pSuper
[
i
])
);
printf
(
"%3d "
,
pCost
[
i
]
>>
4
);
printf
(
"%3d "
,
pCost
[
i
]
&
15
);
// Extra_PrintBinary( stdout, pMatrix+i, 64 ), printf( "\n" );
}
printf
(
"
\n
"
);
}
/**Function*************************************************************
Synopsis [Perform balancing.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void
Str_NtkBalanceMulti2
(
Gia_Man_t
*
pNew
,
Str_Ntk_t
*
p
,
Str_Obj_t
*
pObj
,
Vec_Int_t
*
vDelay
,
int
nLutSize
)
{
int
k
;
pObj
->
iCopy
=
(
pObj
->
Type
==
STR_AND
);
for
(
k
=
0
;
k
<
(
int
)
pObj
->
nFanins
;
k
++
)
{
if
(
pObj
->
Type
==
STR_AND
)
pObj
->
iCopy
=
Gia_ManHashAnd
(
pNew
,
pObj
->
iCopy
,
Str_ObjFaninCopy
(
p
,
pObj
,
k
)
);
else
pObj
->
iCopy
=
Gia_ManHashXorReal
(
pNew
,
pObj
->
iCopy
,
Str_ObjFaninCopy
(
p
,
pObj
,
k
)
);
Str_ObjDelay
(
pNew
,
Abc_Lit2Var
(
pObj
->
iCopy
),
nLutSize
,
vDelay
);
}
}
int
Str_NtkBalanceTwo
(
Gia_Man_t
*
pNew
,
Str_Ntk_t
*
p
,
Str_Obj_t
*
pObj
,
int
i
,
int
j
,
Vec_Int_t
*
vDelay
,
int
*
pCost
,
int
*
pSuper
,
word
*
pMatrix
,
int
nSize
,
int
nLutSize
,
int
CostBest
)
{
int
k
,
iLitRes
,
Delay
;
assert
(
i
<
j
);
// printf( "Merging node %d and %d\n", i, j );
if
(
pObj
->
Type
==
STR_AND
)
iLitRes
=
Gia_ManHashAnd
(
pNew
,
pSuper
[
i
],
pSuper
[
j
]
);
else
iLitRes
=
Gia_ManHashXorReal
(
pNew
,
pSuper
[
i
],
pSuper
[
j
]
);
Delay
=
Str_ObjDelay
(
pNew
,
Abc_Lit2Var
(
iLitRes
),
nLutSize
,
vDelay
);
// update
pCost
[
i
]
=
Delay
;
pSuper
[
i
]
=
iLitRes
;
pMatrix
[
i
]
|=
pMatrix
[
j
];
// assert( (pCost[i] & 15) == CostBest || CostBest == -1 );
// remove entry j
nSize
--
;
for
(
k
=
j
;
k
<
nSize
;
k
++
)
{
pCost
[
k
]
=
pCost
[
k
+
1
];
pSuper
[
k
]
=
pSuper
[
k
+
1
];
pMatrix
[
k
]
=
pMatrix
[
k
+
1
];
}
// move up the first one
nSize
--
;
for
(
k
=
0
;
k
<
nSize
;
k
++
)
{
if
(
pCost
[
k
]
<=
pCost
[
k
+
1
]
)
break
;
ABC_SWAP
(
int
,
pCost
[
k
],
pCost
[
k
+
1
]
);
ABC_SWAP
(
int
,
pSuper
[
k
],
pSuper
[
k
+
1
]
);
ABC_SWAP
(
word
,
pMatrix
[
k
],
pMatrix
[
k
+
1
]
);
}
return
iLitRes
;
}
void
Str_NtkBalanceMulti
(
Gia_Man_t
*
pNew
,
Str_Ntk_t
*
p
,
Str_Obj_t
*
pObj
,
Vec_Int_t
*
vDelay
,
int
nLutSize
)
{
word
pMatrix
[
256
];
int
Limit
=
256
;
Vec_Int_t
*
vSuper
=
pNew
->
vSuper
;
Vec_Int_t
*
vCosts
=
pNew
->
vStore
;
int
*
pSuper
=
Vec_IntArray
(
vSuper
);
int
*
pCost
=
Vec_IntArray
(
vCosts
);
int
k
,
iLit
,
MatrixSize
=
0
;
assert
(
Limit
<=
Vec_IntCap
(
vSuper
)
);
assert
(
Limit
<=
Vec_IntCap
(
vCosts
)
);
// collect nodes
Vec_IntClear
(
vSuper
);
for
(
k
=
0
;
k
<
(
int
)
pObj
->
nFanins
;
k
++
)
Vec_IntPush
(
vSuper
,
Str_ObjFaninCopy
(
p
,
pObj
,
k
)
);
Vec_IntSort
(
vSuper
,
0
);
if
(
pObj
->
Type
==
STR_AND
)
Gia_ManSimplifyAnd
(
vSuper
);
else
Gia_ManSimplifyXor
(
vSuper
);
assert
(
Vec_IntSize
(
vSuper
)
>
0
);
if
(
Vec_IntSize
(
vSuper
)
==
1
)
{
pObj
->
iCopy
=
Vec_IntEntry
(
vSuper
,
0
);
return
;
}
if
(
Vec_IntSize
(
vSuper
)
==
2
)
{
pObj
->
iCopy
=
Str_NtkBalanceTwo
(
pNew
,
p
,
pObj
,
0
,
1
,
vDelay
,
pCost
,
pSuper
,
pMatrix
,
2
,
nLutSize
,
-
1
);
return
;
}
// sort by cost
Vec_IntClear
(
vCosts
);
Vec_IntForEachEntry
(
vSuper
,
iLit
,
k
)
Vec_IntPush
(
vCosts
,
Vec_IntEntry
(
vDelay
,
Abc_Lit2Var
(
iLit
))
);
Vec_IntSelectSortCost2
(
pSuper
,
Vec_IntSize
(
vSuper
),
pCost
);
// compute affinity
if
(
Vec_IntSize
(
vSuper
)
<
64
)
MatrixSize
=
Str_ManVectorAffinity
(
pNew
,
vSuper
,
vCosts
,
pMatrix
,
Limit
);
// start the new product
while
(
Vec_IntSize
(
vSuper
)
>
2
)
{
// pair the first entry with another one on the same level
int
i
,
iStop
,
iBest
,
iBest2
;
int
CostNew
,
CostBest
,
CostBest2
;
int
OccurNew
,
OccurBest
,
OccurBest2
;
if
(
Vec_IntSize
(
vSuper
)
>
64
)
{
Str_NtkBalanceTwo
(
pNew
,
p
,
pObj
,
0
,
1
,
vDelay
,
pCost
,
pSuper
,
pMatrix
,
Vec_IntSize
(
vSuper
),
nLutSize
,
-
1
);
vSuper
->
nSize
--
;
vCosts
->
nSize
--
;
continue
;
}
// compute affinity
if
(
Vec_IntSize
(
vSuper
)
==
64
)
MatrixSize
=
Str_ManVectorAffinity
(
pNew
,
vSuper
,
vCosts
,
pMatrix
,
Limit
);
assert
(
Vec_IntSize
(
vSuper
)
<=
64
);
// Str_PrintState( pCost, pSuper, pMatrix, Vec_IntSize(vSuper) );
// if the first two are PIs group them
if
(
pCost
[
0
]
==
17
&&
pCost
[
1
]
==
17
)
{
Str_NtkBalanceTwo
(
pNew
,
p
,
pObj
,
0
,
1
,
vDelay
,
pCost
,
pSuper
,
pMatrix
,
Vec_IntSize
(
vSuper
),
nLutSize
,
2
);
vSuper
->
nSize
--
;
vCosts
->
nSize
--
;
continue
;
}
// find the end of the level
for
(
iStop
=
0
;
iStop
<
Vec_IntSize
(
vSuper
);
iStop
++
)
if
(
(
pCost
[
iStop
]
>>
4
)
!=
(
pCost
[
0
]
>>
4
)
)
break
;
// if there is only one this level, pair it with the best match in the next level
if
(
iStop
==
1
)
{
iBest
=
iStop
,
OccurBest
=
Str_CountBits
(
pMatrix
[
0
]
&
pMatrix
[
iStop
]);
for
(
i
=
iStop
+
1
;
i
<
Vec_IntSize
(
vSuper
);
i
++
)
{
if
(
(
pCost
[
i
]
>>
4
)
!=
(
pCost
[
iStop
]
>>
4
)
)
break
;
OccurNew
=
Str_CountBits
(
pMatrix
[
0
]
&
pMatrix
[
i
]);
if
(
OccurBest
<
OccurNew
)
iBest
=
i
,
OccurBest
=
OccurNew
;
}
assert
(
iBest
>
0
&&
iBest
<
Vec_IntSize
(
vSuper
)
);
Str_NtkBalanceTwo
(
pNew
,
p
,
pObj
,
0
,
iBest
,
vDelay
,
pCost
,
pSuper
,
pMatrix
,
Vec_IntSize
(
vSuper
),
nLutSize
,
-
1
);
vSuper
->
nSize
--
;
vCosts
->
nSize
--
;
continue
;
}
// pair the first entry with another one on the same level
iBest
=
-
1
;
CostBest
=
-
1
;
OccurBest2
=
-
1
;
OccurBest
=
-
1
;
for
(
i
=
1
;
i
<
iStop
;
i
++
)
{
CostNew
=
(
pCost
[
0
]
&
15
)
+
(
pCost
[
i
]
&
15
);
if
(
CostNew
>
nLutSize
)
continue
;
OccurNew
=
Str_CountBits
(
pMatrix
[
0
]
&
pMatrix
[
i
]);
if
(
CostBest
<
CostNew
||
(
CostBest
==
CostNew
&&
OccurBest
<
OccurNew
)
)
CostBest
=
CostNew
,
iBest
=
i
,
OccurBest
=
OccurNew
;
}
// if the best found is perfect, take it
if
(
CostBest
==
nLutSize
)
{
assert
(
iBest
>
0
&&
iBest
<
Vec_IntSize
(
vSuper
)
);
Str_NtkBalanceTwo
(
pNew
,
p
,
pObj
,
0
,
iBest
,
vDelay
,
pCost
,
pSuper
,
pMatrix
,
Vec_IntSize
(
vSuper
),
nLutSize
,
CostBest
);
vSuper
->
nSize
--
;
vCosts
->
nSize
--
;
continue
;
}
// find the best pair on this level
iBest
=
iBest2
=
-
1
;
CostBest
=
CostBest2
=
-
1
,
OccurBest
=
OccurBest2
=
-
1
;
for
(
i
=
0
;
i
<
iStop
;
i
++
)
for
(
k
=
i
+
1
;
k
<
iStop
;
k
++
)
{
CostNew
=
(
pCost
[
i
]
&
15
)
+
(
pCost
[
k
]
&
15
);
OccurNew
=
Str_CountBits
(
pMatrix
[
i
]
&
pMatrix
[
k
]);
if
(
CostNew
<=
nLutSize
)
// the same level
{
if
(
OccurBest
<
OccurNew
||
(
OccurBest
==
OccurNew
&&
CostBest
<
CostNew
))
CostBest
=
CostNew
,
iBest
=
(
i
<<
16
)
|
k
,
OccurBest
=
OccurNew
;
}
else
// overflow to the next level
{
if
(
OccurBest2
<
OccurNew
||
(
OccurBest2
==
OccurNew
&&
CostBest2
<
CostNew
)
)
CostBest2
=
CostNew
,
iBest2
=
(
i
<<
16
)
|
k
,
OccurBest2
=
OccurNew
;
}
}
if
(
iBest
>=
0
)
{
assert
(
iBest
>
0
);
Str_NtkBalanceTwo
(
pNew
,
p
,
pObj
,
iBest
>>
16
,
iBest
&
0xFFFF
,
vDelay
,
pCost
,
pSuper
,
pMatrix
,
Vec_IntSize
(
vSuper
),
nLutSize
,
CostBest
);
vSuper
->
nSize
--
;
vCosts
->
nSize
--
;
continue
;
}
// take any remaining pair
assert
(
iBest2
>
0
);
Str_NtkBalanceTwo
(
pNew
,
p
,
pObj
,
iBest2
>>
16
,
iBest2
&
0xFFFF
,
vDelay
,
pCost
,
pSuper
,
pMatrix
,
Vec_IntSize
(
vSuper
),
nLutSize
,
-
1
);
vSuper
->
nSize
--
;
vCosts
->
nSize
--
;
continue
;
}
pObj
->
iCopy
=
Str_NtkBalanceTwo
(
pNew
,
p
,
pObj
,
0
,
1
,
vDelay
,
pCost
,
pSuper
,
pMatrix
,
2
,
nLutSize
,
-
1
);
/*
// simple
pObj->iCopy = (pObj->Type == STR_AND);
for ( k = 0; k < Vec_IntSize(vSuper); k++ )
{
if ( pObj->Type == STR_AND )
pObj->iCopy = Gia_ManHashAnd( pNew, pObj->iCopy, Vec_IntEntry(vSuper, k) );
else
pObj->iCopy = Gia_ManHashXorReal( pNew, pObj->iCopy, Vec_IntEntry(vSuper, k) );
Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay );
}
*/
}
void
Str_NtkBalanceMux
(
Gia_Man_t
*
pNew
,
Str_Ntk_t
*
p
,
Str_Obj_t
*
pObj
,
Vec_Int_t
*
vDelay
,
int
nLutSize
,
int
nGroups
,
int
nMuxes
,
int
fRecursive
,
int
fOptArea
,
int
fVerbose
)
{
extern
int
Str_MuxRestructure
(
Gia_Man_t
*
pNew
,
Str_Ntk_t
*
pNtk
,
int
iMux
,
int
nMuxes
,
Vec_Int_t
*
vDelay
,
int
nLutSize
,
int
fRecursive
,
int
fOptArea
,
int
fVerbose
);
int
n
,
m
,
iRes
,
fUseRestruct
=
1
;
if
(
fUseRestruct
)
{
for
(
n
=
0
;
n
<
nGroups
;
n
++
)
{
iRes
=
Str_MuxRestructure
(
pNew
,
p
,
Str_ObjId
(
p
,
pObj
),
nMuxes
,
vDelay
,
nLutSize
,
fRecursive
,
fOptArea
,
fVerbose
);
if
(
iRes
==
-
1
)
{
for
(
m
=
0
;
m
<
nMuxes
;
m
++
,
pObj
++
)
{
pObj
->
iCopy
=
Gia_ManHashMuxReal
(
pNew
,
Str_ObjFaninCopy
(
p
,
pObj
,
2
),
Str_ObjFaninCopy
(
p
,
pObj
,
1
),
Str_ObjFaninCopy
(
p
,
pObj
,
0
)
);
Str_ObjDelay
(
pNew
,
Abc_Lit2Var
(
pObj
->
iCopy
),
nLutSize
,
vDelay
);
}
}
else
{
pObj
+=
nMuxes
-
1
;
pObj
->
iCopy
=
iRes
;
pObj
++
;
}
}
}
else
{
for
(
n
=
0
;
n
<
nGroups
*
nMuxes
;
n
++
,
pObj
++
)
{
pObj
->
iCopy
=
Gia_ManHashMuxReal
(
pNew
,
Str_ObjFaninCopy
(
p
,
pObj
,
2
),
Str_ObjFaninCopy
(
p
,
pObj
,
1
),
Str_ObjFaninCopy
(
p
,
pObj
,
0
)
);
Str_ObjDelay
(
pNew
,
Abc_Lit2Var
(
pObj
->
iCopy
),
nLutSize
,
vDelay
);
}
}
}
Gia_Man_t
*
Str_NtkBalance
(
Gia_Man_t
*
pGia
,
Str_Ntk_t
*
p
,
int
nLutSize
,
int
fUseMuxes
,
int
fRecursive
,
int
fOptArea
,
int
fVerbose
)
{
Gia_Man_t
*
pNew
,
*
pTemp
;
Vec_Int_t
*
vDelay
;
Str_Obj_t
*
pObj
;
int
nGroups
,
nMuxes
,
CioId
;
int
arrTime
,
Delay
=
0
;
assert
(
nLutSize
<
16
);
assert
(
pGia
->
pMuxes
==
NULL
);
pNew
=
Gia_ManStart
(
Gia_ManObjNum
(
pGia
)
);
pNew
->
pName
=
Abc_UtilStrsav
(
pGia
->
pName
);
pNew
->
pSpec
=
Abc_UtilStrsav
(
pGia
->
pSpec
);
pNew
->
pMuxes
=
ABC_CALLOC
(
unsigned
,
pNew
->
nObjsAlloc
);
Vec_IntFill
(
&
pNew
->
vCopies
,
pNew
->
nObjsAlloc
,
-
1
);
if
(
pNew
->
vSuper
==
NULL
)
pNew
->
vSuper
=
Vec_IntAlloc
(
1000
);
if
(
pNew
->
vStore
==
NULL
)
pNew
->
vStore
=
Vec_IntAlloc
(
1000
);
vDelay
=
Vec_IntStart
(
pNew
->
nObjsAlloc
);
Gia_ManHashStart
(
pNew
);
if
(
pGia
->
pManTime
!=
NULL
)
// Tim_Man with unit delay 16
{
Tim_ManInitPiArrivalAll
(
(
Tim_Man_t
*
)
pGia
->
pManTime
,
17
);
Tim_ManIncrementTravId
(
(
Tim_Man_t
*
)
pGia
->
pManTime
);
}
Str_NtkManForEachObj
(
p
,
pObj
)
{
if
(
pObj
->
Type
==
STR_PI
)
{
pObj
->
iCopy
=
Gia_ManAppendCi
(
pNew
);
arrTime
=
17
;
if
(
pGia
->
pManTime
!=
NULL
)
{
CioId
=
Gia_ObjCioId
(
Gia_ManObj
(
pNew
,
Abc_Lit2Var
(
pObj
->
iCopy
))
);
arrTime
=
(
int
)
Tim_ManGetCiArrival
(
(
Tim_Man_t
*
)
pGia
->
pManTime
,
CioId
);
}
Vec_IntWriteEntry
(
vDelay
,
Abc_Lit2Var
(
pObj
->
iCopy
),
arrTime
);
}
else
if
(
pObj
->
Type
==
STR_AND
||
pObj
->
Type
==
STR_XOR
)
Str_NtkBalanceMulti
(
pNew
,
p
,
pObj
,
vDelay
,
nLutSize
);
else
if
(
pObj
->
Type
==
STR_MUX
&&
pObj
->
iTop
>=
0
&&
fUseMuxes
)
{
Str_ObjReadGroup
(
p
,
pObj
,
&
nGroups
,
&
nMuxes
);
assert
(
nGroups
*
nMuxes
>=
2
);
Str_NtkBalanceMux
(
pNew
,
p
,
pObj
,
vDelay
,
nLutSize
,
nGroups
,
nMuxes
,
fRecursive
,
fOptArea
,
fVerbose
);
pObj
+=
nGroups
*
nMuxes
-
1
;
}
else
if
(
pObj
->
Type
==
STR_MUX
)
{
pObj
->
iCopy
=
Gia_ManHashMuxReal
(
pNew
,
Str_ObjFaninCopy
(
p
,
pObj
,
2
),
Str_ObjFaninCopy
(
p
,
pObj
,
1
),
Str_ObjFaninCopy
(
p
,
pObj
,
0
)
);
Str_ObjDelay
(
pNew
,
Abc_Lit2Var
(
pObj
->
iCopy
),
nLutSize
,
vDelay
);
}
else
if
(
pObj
->
Type
==
STR_PO
)
{
pObj
->
iCopy
=
Gia_ManAppendCo
(
pNew
,
Str_ObjFaninCopy
(
p
,
pObj
,
0
)
);
arrTime
=
Vec_IntEntry
(
vDelay
,
Abc_Lit2Var
(
Str_ObjFaninCopy
(
p
,
pObj
,
0
))
);
Delay
=
Abc_MaxInt
(
Delay
,
arrTime
);
if
(
pGia
->
pManTime
!=
NULL
)
{
CioId
=
Gia_ObjCioId
(
Gia_ManObj
(
pNew
,
Abc_Lit2Var
(
pObj
->
iCopy
))
);
Tim_ManSetCoArrival
(
(
Tim_Man_t
*
)
pGia
->
pManTime
,
CioId
,
(
float
)
arrTime
);
}
}
else
if
(
pObj
->
Type
==
STR_CONST0
)
pObj
->
iCopy
=
0
,
Vec_IntWriteEntry
(
vDelay
,
0
,
17
);
else
assert
(
0
);
}
if
(
fVerbose
)
printf
(
"Max delay = %d. Old objs = %d. New objs = %d.
\n
"
,
Delay
>>
4
,
Gia_ManObjNum
(
pGia
),
Gia_ManObjNum
(
pNew
)
);
Vec_IntFree
(
vDelay
);
ABC_FREE
(
pNew
->
vCopies
.
pArray
);
Gia_ManHashStop
(
pNew
);
Gia_ManSetRegNum
(
pNew
,
Gia_ManRegNum
(
pGia
)
);
pNew
=
Gia_ManDupNoMuxes
(
pTemp
=
pNew
);
Gia_ManStop
(
pTemp
);
// if ( pGia->pManTime != NULL )
// pNew->pManTime = Tim_ManDup( (Tim_Man_t *)pGia->pManTime, 0 );
return
pNew
;
}
/**Function*************************************************************
Synopsis []
Synopsis [
Test normalization procedure.
]
Description []
...
...
@@ -45,10 +1376,485 @@ ABC_NAMESPACE_IMPL_START
***********************************************************************/
Gia_Man_t
*
Gia_ManLutBalance
(
Gia_Man_t
*
p
,
int
nLutSize
,
int
fUseMuxes
,
int
fRecursive
,
int
fOptArea
,
int
fVerbose
)
{
return
Gia_ManDup
(
p
);
Str_Ntk_t
*
pNtk
;
Gia_Man_t
*
pNew
;
abctime
clk
=
Abc_Clock
();
if
(
p
->
pManTime
&&
Tim_ManBoxNum
(
p
->
pManTime
)
&&
Gia_ManIsNormalized
(
p
)
)
{
Tim_Man_t
*
pTimOld
=
(
Tim_Man_t
*
)
p
->
pManTime
;
p
->
pManTime
=
Tim_ManDup
(
pTimOld
,
16
);
pNew
=
Gia_ManDupUnnormalize
(
p
);
if
(
pNew
==
NULL
)
return
NULL
;
Gia_ManTransferTiming
(
pNew
,
p
);
p
=
pNew
;
// optimize
pNtk
=
Str_ManNormalize
(
p
);
pNew
=
Str_NtkBalance
(
p
,
pNtk
,
nLutSize
,
fUseMuxes
,
fRecursive
,
fOptArea
,
fVerbose
);
Gia_ManTransferTiming
(
pNew
,
p
);
Gia_ManStop
(
p
);
// normalize
pNew
=
Gia_ManDupNormalize
(
p
=
pNew
);
Gia_ManTransferTiming
(
pNew
,
p
);
Gia_ManStop
(
p
);
// cleanup
Tim_ManStop
(
(
Tim_Man_t
*
)
pNew
->
pManTime
);
pNew
->
pManTime
=
pTimOld
;
assert
(
Gia_ManIsNormalized
(
pNew
)
);
}
else
{
pNtk
=
Str_ManNormalize
(
p
);
// Str_NtkPrintGroups( pNtk );
pNew
=
Str_NtkBalance
(
p
,
pNtk
,
nLutSize
,
fUseMuxes
,
fRecursive
,
fOptArea
,
fVerbose
);
Gia_ManTransferTiming
(
pNew
,
p
);
}
if
(
fVerbose
)
Str_NtkPs
(
pNtk
,
Abc_Clock
()
-
clk
);
Str_NtkDelete
(
pNtk
);
return
pNew
;
}
/**Function*************************************************************
Synopsis [Perform MUX restructuring.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
typedef
struct
Str_Edg_t_
Str_Edg_t
;
struct
Str_Edg_t_
{
int
Fan
;
// fanin ID
int
fCompl
;
// fanin complement
int
FanDel
;
// fanin delay
int
Copy
;
// fanin copy
};
typedef
struct
Str_Mux_t_
Str_Mux_t
;
// 64 bytes
struct
Str_Mux_t_
{
int
Id
;
// node ID
int
Delay
;
// node delay
int
Copy
;
// node copy
int
nLutSize
;
// LUT size
Str_Edg_t
Edge
[
3
];
// fanins
};
static
inline
Str_Mux_t
*
Str_MuxFanin
(
Str_Mux_t
*
pMux
,
int
i
)
{
return
pMux
-
pMux
->
Id
+
pMux
->
Edge
[
i
].
Fan
;
}
static
inline
int
Str_MuxHasFanin
(
Str_Mux_t
*
pMux
,
int
i
)
{
return
pMux
->
Edge
[
i
].
Fan
>
0
&&
Str_MuxFanin
(
pMux
,
i
)
->
Copy
!=
-
2
;
}
void
Str_MuxDelayPrint_rec
(
Str_Mux_t
*
pMux
,
int
i
)
{
int
fShowDelay
=
1
;
Str_Mux_t
*
pFanin
;
if
(
pMux
->
Edge
[
i
].
Fan
<=
0
)
{
printf
(
"%d"
,
-
pMux
->
Edge
[
i
].
Fan
);
if
(
fShowDelay
)
printf
(
"{%d}"
,
pMux
->
Edge
[
i
].
FanDel
);
return
;
}
pFanin
=
Str_MuxFanin
(
pMux
,
i
);
printf
(
"[ "
);
if
(
pFanin
->
Edge
[
0
].
fCompl
)
printf
(
"!"
);
Str_MuxDelayPrint_rec
(
pFanin
,
0
);
printf
(
"|"
);
if
(
pFanin
->
Edge
[
1
].
fCompl
)
printf
(
"!"
);
Str_MuxDelayPrint_rec
(
pFanin
,
1
);
printf
(
"("
);
if
(
pFanin
->
Edge
[
2
].
fCompl
)
printf
(
"!"
);
Str_MuxDelayPrint_rec
(
pFanin
,
2
);
printf
(
")"
);
printf
(
" ]"
);
}
int
Str_MuxDelayEdge_rec
(
Str_Mux_t
*
pMux
,
int
i
)
{
if
(
pMux
->
Edge
[
i
].
Fan
>
0
)
{
Str_Mux_t
*
pFanin
=
Str_MuxFanin
(
pMux
,
i
);
Str_MuxDelayEdge_rec
(
pFanin
,
0
);
Str_MuxDelayEdge_rec
(
pFanin
,
1
);
pMux
->
Edge
[
i
].
FanDel
=
Str_Delay3
(
pFanin
->
Edge
[
0
].
FanDel
,
pFanin
->
Edge
[
1
].
FanDel
,
pFanin
->
Edge
[
2
].
FanDel
,
pFanin
->
nLutSize
);
}
return
pMux
->
Edge
[
i
].
FanDel
;
}
void
Str_MuxCreate
(
Str_Mux_t
*
pTree
,
Str_Ntk_t
*
pNtk
,
int
iMux
,
int
nMuxes
,
Vec_Int_t
*
vDelay
,
int
nLutSize
)
{
Str_Obj_t
*
pObj
;
Str_Mux_t
*
pMux
;
int
i
,
k
,
nPis
=
0
;
assert
(
nMuxes
>=
2
);
memset
(
pTree
,
0
,
sizeof
(
Str_Mux_t
)
*
(
nMuxes
+
1
)
);
pTree
->
nLutSize
=
nLutSize
;
pTree
->
Edge
[
0
].
Fan
=
1
;
for
(
i
=
1
;
i
<=
nMuxes
;
i
++
)
{
pMux
=
pTree
+
i
;
pMux
->
Id
=
i
;
pMux
->
nLutSize
=
nLutSize
;
pMux
->
Delay
=
pMux
->
Copy
=
-
1
;
// assign fanins
pObj
=
Str_NtkObj
(
pNtk
,
iMux
+
nMuxes
-
i
);
assert
(
pObj
->
Type
==
STR_MUX
);
for
(
k
=
0
;
k
<
3
;
k
++
)
{
pMux
->
Edge
[
k
].
fCompl
=
Str_ObjFaninC
(
pNtk
,
pObj
,
k
);
if
(
Str_ObjFaninId
(
pNtk
,
pObj
,
k
)
>=
iMux
)
pMux
->
Edge
[
k
].
Fan
=
iMux
+
nMuxes
-
Str_ObjFaninId
(
pNtk
,
pObj
,
k
);
else
{
pMux
->
Edge
[
k
].
Fan
=
-
nPis
++
;
// count external inputs, including controls
pMux
->
Edge
[
k
].
Copy
=
Str_ObjFanin
(
pNtk
,
pObj
,
k
)
->
iCopy
;
pMux
->
Edge
[
k
].
FanDel
=
Vec_IntEntry
(
vDelay
,
Abc_Lit2Var
(
pMux
->
Edge
[
k
].
Copy
)
);
}
}
}
}
int
Str_MuxToGia_rec
(
Gia_Man_t
*
pNew
,
Str_Mux_t
*
pMux
,
int
i
,
Vec_Int_t
*
vDelay
)
{
if
(
pMux
->
Edge
[
i
].
Fan
>
0
)
{
Str_Mux_t
*
pFanin
=
Str_MuxFanin
(
pMux
,
i
);
int
iLit0
=
Str_MuxToGia_rec
(
pNew
,
pFanin
,
0
,
vDelay
);
int
iLit1
=
Str_MuxToGia_rec
(
pNew
,
pFanin
,
1
,
vDelay
);
assert
(
pFanin
->
Edge
[
2
].
Fan
<=
0
);
assert
(
pFanin
->
Edge
[
2
].
fCompl
==
0
);
pMux
->
Edge
[
i
].
Copy
=
Gia_ManHashMuxReal
(
pNew
,
pFanin
->
Edge
[
2
].
Copy
,
iLit1
,
iLit0
);
Str_ObjDelay
(
pNew
,
Abc_Lit2Var
(
pMux
->
Edge
[
i
].
Copy
),
pFanin
->
nLutSize
,
vDelay
);
}
return
Abc_LitNotCond
(
pMux
->
Edge
[
i
].
Copy
,
pMux
->
Edge
[
i
].
fCompl
);
}
void
Str_MuxChangeOnce
(
Str_Mux_t
*
pTree
,
int
*
pPath
,
int
i
,
int
k
,
Str_Mux_t
*
pBackup
,
Gia_Man_t
*
pNew
,
Vec_Int_t
*
vDelay
)
{
Str_Mux_t
*
pSpots
[
3
];
int
pInds
[
3
],
MidFan
,
MidCom
,
MidDel
,
MidCop
,
c
;
int
iRes
,
iCond
,
fCompl
;
// save backup
assert
(
i
+
1
<
k
);
if
(
pBackup
)
{
pBackup
[
0
]
=
pTree
[
Abc_Lit2Var
(
pPath
[
k
])
];
pBackup
[
1
]
=
pTree
[
Abc_Lit2Var
(
pPath
[
i
+
1
])];
pBackup
[
2
]
=
pTree
[
Abc_Lit2Var
(
pPath
[
i
])
];
}
// perform changes
pSpots
[
0
]
=
pTree
+
Abc_Lit2Var
(
pPath
[
k
]);
pSpots
[
1
]
=
pTree
+
Abc_Lit2Var
(
pPath
[
i
+
1
]);
pSpots
[
2
]
=
pTree
+
Abc_Lit2Var
(
pPath
[
i
]);
pInds
[
0
]
=
Abc_LitIsCompl
(
pPath
[
k
]);
pInds
[
1
]
=
Abc_LitIsCompl
(
pPath
[
i
+
1
]);
pInds
[
2
]
=
Abc_LitIsCompl
(
pPath
[
i
]);
// check
assert
(
pSpots
[
0
]
->
Edge
[
pInds
[
0
]].
Fan
>
0
);
assert
(
pSpots
[
1
]
->
Edge
[
pInds
[
1
]].
Fan
>
0
);
// collect complement
fCompl
=
0
;
for
(
c
=
i
+
1
;
c
<
k
;
c
++
)
fCompl
^=
pTree
[
Abc_Lit2Var
(
pPath
[
c
])].
Edge
[
Abc_LitIsCompl
(
pPath
[
c
])].
fCompl
;
// remember bottom side
MidFan
=
pSpots
[
2
]
->
Edge
[
!
pInds
[
2
]].
Fan
;
MidCom
=
pSpots
[
2
]
->
Edge
[
!
pInds
[
2
]].
fCompl
;
MidDel
=
pSpots
[
2
]
->
Edge
[
!
pInds
[
2
]].
FanDel
;
MidCop
=
pSpots
[
2
]
->
Edge
[
!
pInds
[
2
]].
Copy
;
// update bottom
pSpots
[
2
]
->
Edge
[
!
pInds
[
2
]].
Fan
=
pSpots
[
0
]
->
Edge
[
pInds
[
0
]].
Fan
;
pSpots
[
2
]
->
Edge
[
!
pInds
[
2
]].
fCompl
=
0
;
// update top
pSpots
[
0
]
->
Edge
[
pInds
[
0
]].
Fan
=
pSpots
[
2
]
->
Id
;
// update middle
pSpots
[
1
]
->
Edge
[
pInds
[
1
]].
Fan
=
MidFan
;
pSpots
[
1
]
->
Edge
[
pInds
[
1
]].
fCompl
^=
MidCom
;
pSpots
[
1
]
->
Edge
[
pInds
[
1
]].
FanDel
=
MidDel
;
pSpots
[
1
]
->
Edge
[
pInds
[
1
]].
Copy
=
MidCop
;
// update delay of the control
for
(
c
=
i
+
1
;
c
<
k
;
c
++
)
pSpots
[
2
]
->
Edge
[
2
].
FanDel
=
Str_Delay2
(
pSpots
[
2
]
->
Edge
[
2
].
FanDel
,
pTree
[
Abc_Lit2Var
(
pPath
[
c
])].
Edge
[
2
].
FanDel
,
pTree
->
nLutSize
);
if
(
pNew
==
NULL
)
return
;
// create AND gates
iRes
=
1
;
for
(
c
=
i
;
c
<
k
;
c
++
)
{
assert
(
pTree
[
Abc_Lit2Var
(
pPath
[
c
])].
Edge
[
2
].
fCompl
==
0
);
iCond
=
pTree
[
Abc_Lit2Var
(
pPath
[
c
])].
Edge
[
2
].
Copy
;
iCond
=
Abc_LitNotCond
(
iCond
,
!
Abc_LitIsCompl
(
pPath
[
c
])
);
iRes
=
Gia_ManHashAnd
(
pNew
,
iRes
,
iCond
);
Str_ObjDelay
(
pNew
,
Abc_Lit2Var
(
iRes
),
pTree
->
nLutSize
,
vDelay
);
}
// complement the condition
pSpots
[
2
]
->
Edge
[
2
].
Copy
=
Abc_LitNotCond
(
iRes
,
!
Abc_LitIsCompl
(
pPath
[
i
])
);
// complement the path
pSpots
[
2
]
->
Edge
[
pInds
[
2
]].
fCompl
^=
fCompl
;
}
void
Str_MuxChangeUndo
(
Str_Mux_t
*
pTree
,
int
*
pPath
,
int
i
,
int
k
,
Str_Mux_t
*
pBackup
)
{
pTree
[
Abc_Lit2Var
(
pPath
[
k
])
]
=
pBackup
[
0
];
pTree
[
Abc_Lit2Var
(
pPath
[
i
+
1
])]
=
pBackup
[
1
];
pTree
[
Abc_Lit2Var
(
pPath
[
i
])
]
=
pBackup
[
2
];
}
int
Str_MuxFindPathEdge_rec
(
Str_Mux_t
*
pMux
,
int
i
,
int
*
pPath
,
int
*
pnLength
)
{
extern
int
Str_MuxFindPath_rec
(
Str_Mux_t
*
pMux
,
int
*
pPath
,
int
*
pnLength
);
if
(
pMux
->
Edge
[
i
].
Fan
>
0
&&
!
Str_MuxFindPath_rec
(
Str_MuxFanin
(
pMux
,
i
),
pPath
,
pnLength
)
)
return
0
;
pPath
[
(
*
pnLength
)
++
]
=
Abc_Var2Lit
(
pMux
->
Id
,
i
);
return
1
;
}
int
Str_MuxFindPath_rec
(
Str_Mux_t
*
pMux
,
int
*
pPath
,
int
*
pnLength
)
{
int
i
,
DelayMax
=
Abc_MaxInt
(
pMux
->
Edge
[
0
].
FanDel
,
Abc_MaxInt
(
pMux
->
Edge
[
1
].
FanDel
,
pMux
->
Edge
[
2
].
FanDel
)
);
for
(
i
=
0
;
i
<
2
;
i
++
)
if
(
pMux
->
Edge
[
i
].
FanDel
==
DelayMax
)
return
Str_MuxFindPathEdge_rec
(
pMux
,
i
,
pPath
,
pnLength
);
if
(
pMux
->
Edge
[
2
].
FanDel
==
DelayMax
)
return
0
;
assert
(
0
);
return
-
1
;
}
// return node whose both branches are non-trivial
Str_Mux_t
*
Str_MuxFindBranching
(
Str_Mux_t
*
pRoot
,
int
i
)
{
Str_Mux_t
*
pMux
;
if
(
pRoot
->
Edge
[
i
].
Fan
<=
0
)
return
NULL
;
pMux
=
Str_MuxFanin
(
pRoot
,
i
);
while
(
1
)
{
if
(
pMux
->
Edge
[
0
].
Fan
<=
0
&&
pMux
->
Edge
[
1
].
Fan
<=
0
)
return
NULL
;
if
(
pMux
->
Edge
[
0
].
Fan
>
0
&&
pMux
->
Edge
[
1
].
Fan
>
0
)
return
pMux
;
if
(
pMux
->
Edge
[
0
].
Fan
>
0
)
pMux
=
Str_MuxFanin
(
pMux
,
0
);
if
(
pMux
->
Edge
[
1
].
Fan
>
0
)
pMux
=
Str_MuxFanin
(
pMux
,
1
);
}
assert
(
0
);
return
NULL
;
}
int
Str_MuxTryOnce
(
Gia_Man_t
*
pNew
,
Str_Ntk_t
*
pNtk
,
Str_Mux_t
*
pTree
,
Str_Mux_t
*
pRoot
,
int
Edge
,
Vec_Int_t
*
vDelay
,
int
fVerbose
)
{
int
pPath
[
500
];
Str_Mux_t
pBackup
[
3
];
int
Delay
,
DelayBest
=
Str_MuxDelayEdge_rec
(
pRoot
,
Edge
),
DelayInit
=
DelayBest
;
int
i
,
k
,
nLength
=
0
,
ForkBest
=
-
1
,
nChecks
=
0
;
int
RetValue
=
Str_MuxFindPathEdge_rec
(
pRoot
,
Edge
,
pPath
,
&
nLength
);
if
(
RetValue
==
0
)
return
0
;
if
(
fVerbose
)
printf
(
"Trying node %d with path of length %d.
\n
"
,
pRoot
->
Id
,
nLength
);
for
(
i
=
0
;
i
<
nLength
;
i
++
)
for
(
k
=
i
+
2
;
k
<
nLength
;
k
++
)
{
Str_MuxChangeOnce
(
pTree
,
pPath
,
i
,
k
,
pBackup
,
NULL
,
NULL
);
Delay
=
Str_MuxDelayEdge_rec
(
pRoot
,
Edge
);
Str_MuxChangeUndo
(
pTree
,
pPath
,
i
,
k
,
pBackup
);
if
(
DelayBest
>
Delay
||
(
ForkBest
>
0
&&
DelayBest
==
Delay
)
)
DelayBest
=
Delay
,
ForkBest
=
(
i
<<
16
)
|
k
;
if
(
fVerbose
)
printf
(
"%2d %2d -> %3d (%3d)
\n
"
,
i
,
k
,
Delay
,
DelayBest
);
nChecks
++
;
}
if
(
ForkBest
==
-
1
)
{
if
(
fVerbose
)
printf
(
"Did not find!
\n
"
);
return
0
;
}
// Str_MuxDelayPrint_rec( pRoot, Edge ); printf( "\n" );
Str_MuxChangeOnce
(
pTree
,
pPath
,
ForkBest
>>
16
,
ForkBest
&
0xFFFF
,
NULL
,
pNew
,
vDelay
);
// Str_MuxDelayPrint_rec( pRoot, Edge ); printf( "\n" );
if
(
fVerbose
)
printf
(
"Node %6d (%3d %3d) : Checks = %d. Delay: %d -> %d.
\n
"
,
pRoot
->
Id
,
ForkBest
>>
16
,
ForkBest
&
0xFFFF
,
nChecks
,
DelayInit
,
DelayBest
);
if
(
fVerbose
)
printf
(
"
\n
"
);
return
1
;
}
int
Str_MuxRestruct_rec
(
Gia_Man_t
*
pNew
,
Str_Ntk_t
*
pNtk
,
Str_Mux_t
*
pTree
,
Str_Mux_t
*
pRoot
,
int
Edge
,
Vec_Int_t
*
vDelay
,
int
fVerbose
)
{
int
fChanges
=
0
;
Str_Mux_t
*
pMux
=
Str_MuxFindBranching
(
pRoot
,
Edge
);
if
(
pMux
!=
NULL
)
fChanges
|=
Str_MuxRestruct_rec
(
pNew
,
pNtk
,
pTree
,
pMux
,
0
,
vDelay
,
fVerbose
);
if
(
pMux
!=
NULL
)
fChanges
|=
Str_MuxRestruct_rec
(
pNew
,
pNtk
,
pTree
,
pMux
,
1
,
vDelay
,
fVerbose
);
fChanges
|=
Str_MuxTryOnce
(
pNew
,
pNtk
,
pTree
,
pRoot
,
Edge
,
vDelay
,
fVerbose
);
return
fChanges
;
}
int
Str_MuxRestructure2
(
Gia_Man_t
*
pNew
,
Str_Ntk_t
*
pNtk
,
int
iMux
,
int
nMuxes
,
Vec_Int_t
*
vDelay
,
int
nLutSize
,
int
fVerbose
)
{
int
Limit
=
500
;
Str_Mux_t
pTree
[
500
];
int
Delay
,
Delay2
,
fChanges
=
0
;
if
(
nMuxes
>=
Limit
)
return
-
1
;
assert
(
nMuxes
<
Limit
);
Str_MuxCreate
(
pTree
,
pNtk
,
iMux
,
nMuxes
,
vDelay
,
nLutSize
);
Delay
=
Str_MuxDelayEdge_rec
(
pTree
,
0
);
while
(
1
)
{
if
(
!
Str_MuxRestruct_rec
(
pNew
,
pNtk
,
pTree
,
pTree
,
0
,
vDelay
,
fVerbose
)
)
break
;
fChanges
=
1
;
}
if
(
!
fChanges
)
return
-
1
;
Delay2
=
Str_MuxDelayEdge_rec
(
pTree
,
0
);
// printf( "Improved delay for tree %d with %d MUXes (%d -> %d).\n", iMux, nMuxes, Delay, Delay2 );
pNtk
->
DelayGain
+=
Delay
-
Delay2
;
return
Str_MuxToGia_rec
(
pNew
,
pTree
,
0
,
vDelay
);
}
int
Str_MuxRestructure1
(
Gia_Man_t
*
pNew
,
Str_Ntk_t
*
pNtk
,
int
iMux
,
int
nMuxes
,
Vec_Int_t
*
vDelay
,
int
nLutSize
,
int
fVerbose
)
{
int
Limit
=
500
;
Str_Mux_t
pTree
[
500
];
int
Delay
,
Delay2
,
fChanges
=
0
;
if
(
nMuxes
>=
Limit
)
return
-
1
;
assert
(
nMuxes
<
Limit
);
Str_MuxCreate
(
pTree
,
pNtk
,
iMux
,
nMuxes
,
vDelay
,
nLutSize
);
Delay
=
Str_MuxDelayEdge_rec
(
pTree
,
0
);
while
(
1
)
{
if
(
!
Str_MuxTryOnce
(
pNew
,
pNtk
,
pTree
,
pTree
,
0
,
vDelay
,
fVerbose
)
)
break
;
fChanges
=
1
;
}
if
(
!
fChanges
)
return
-
1
;
Delay2
=
Str_MuxDelayEdge_rec
(
pTree
,
0
);
// printf( "Improved delay for tree %d with %d MUXes (%d -> %d).\n", iMux, nMuxes, Delay, Delay2 );
pNtk
->
DelayGain
+=
Delay
-
Delay2
;
return
Str_MuxToGia_rec
(
pNew
,
pTree
,
0
,
vDelay
);
}
int
Str_MuxRestructure
(
Gia_Man_t
*
pNew
,
Str_Ntk_t
*
pNtk
,
int
iMux
,
int
nMuxes
,
Vec_Int_t
*
vDelay
,
int
nLutSize
,
int
fRecursive
,
int
fOptArea
,
int
fVerbose
)
{
extern
int
Str_MuxRestructureArea
(
Gia_Man_t
*
pNew
,
Str_Ntk_t
*
pNtk
,
int
iMux
,
int
nMuxes
,
Vec_Int_t
*
vDelay
,
int
nLutSize
,
int
fVerbose
);
if
(
fOptArea
)
{
if
(
nMuxes
<
2
)
return
Str_MuxRestructure1
(
pNew
,
pNtk
,
iMux
,
nMuxes
,
vDelay
,
nLutSize
,
fVerbose
);
return
Str_MuxRestructureArea
(
pNew
,
pNtk
,
iMux
,
nMuxes
,
vDelay
,
nLutSize
,
fVerbose
);
}
if
(
fRecursive
)
return
Str_MuxRestructure2
(
pNew
,
pNtk
,
iMux
,
nMuxes
,
vDelay
,
nLutSize
,
fVerbose
);
return
Str_MuxRestructure1
(
pNew
,
pNtk
,
iMux
,
nMuxes
,
vDelay
,
nLutSize
,
fVerbose
);
}
/**Function*************************************************************
Synopsis [Perform MUX restructuring for area.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int
Str_MuxRestructAreaThree
(
Gia_Man_t
*
pNew
,
Str_Mux_t
*
pMux
,
Vec_Int_t
*
vDelay
,
int
fVerbose
)
{
int
iRes
;
Str_Mux_t
*
pFanin0
=
Str_MuxFanin
(
pMux
,
0
);
Str_Mux_t
*
pFanin1
=
Str_MuxFanin
(
pMux
,
1
);
assert
(
pMux
->
Copy
==
-
1
);
pMux
->
Copy
=
-
2
;
if
(
pFanin0
->
Edge
[
2
].
Copy
==
pFanin1
->
Edge
[
2
].
Copy
)
return
0
;
iRes
=
Gia_ManHashMuxReal
(
pNew
,
pMux
->
Edge
[
2
].
Copy
,
pFanin1
->
Edge
[
2
].
Copy
,
pFanin0
->
Edge
[
2
].
Copy
);
Str_ObjDelay
(
pNew
,
Abc_Lit2Var
(
iRes
),
pMux
->
nLutSize
,
vDelay
);
pFanin0
->
Edge
[
2
].
Copy
=
pFanin1
->
Edge
[
2
].
Copy
=
iRes
;
// printf( "Created triple\n" );
return
0
;
}
int
Str_MuxRestructArea_rec
(
Gia_Man_t
*
pNew
,
Str_Mux_t
*
pTree
,
Str_Mux_t
*
pRoot
,
int
i
,
Vec_Int_t
*
vDelay
,
int
fVerbose
)
{
int
Path
[
4
];
int
fSkipMoving
=
1
;
Str_Mux_t
*
pMux
,
*
pFanin0
,
*
pFanin1
;
int
nMuxes0
,
nMuxes1
;
if
(
pRoot
->
Edge
[
i
].
Fan
<=
0
)
return
0
;
pMux
=
Str_MuxFanin
(
pRoot
,
i
);
nMuxes0
=
Str_MuxRestructArea_rec
(
pNew
,
pTree
,
pMux
,
0
,
vDelay
,
fVerbose
);
nMuxes1
=
Str_MuxRestructArea_rec
(
pNew
,
pTree
,
pMux
,
1
,
vDelay
,
fVerbose
);
if
(
nMuxes0
+
nMuxes1
<
2
)
return
1
+
nMuxes0
+
nMuxes1
;
if
(
nMuxes0
+
nMuxes1
==
2
)
{
if
(
nMuxes0
==
2
||
nMuxes1
==
2
)
{
pFanin0
=
Str_MuxFanin
(
pMux
,
(
int
)(
nMuxes1
==
2
)
);
assert
(
Str_MuxHasFanin
(
pFanin0
,
0
)
!=
Str_MuxHasFanin
(
pFanin0
,
1
)
);
Path
[
2
]
=
Abc_Var2Lit
(
pRoot
->
Id
,
i
);
Path
[
1
]
=
Abc_Var2Lit
(
pMux
->
Id
,
(
int
)(
nMuxes1
==
2
)
);
Path
[
0
]
=
Abc_Var2Lit
(
pFanin0
->
Id
,
Str_MuxHasFanin
(
pFanin0
,
1
));
Str_MuxChangeOnce
(
pTree
,
Path
,
0
,
2
,
NULL
,
pNew
,
vDelay
);
}
Str_MuxRestructAreaThree
(
pNew
,
Str_MuxFanin
(
pRoot
,
i
),
vDelay
,
fVerbose
);
return
0
;
}
assert
(
nMuxes0
+
nMuxes1
==
3
||
nMuxes0
+
nMuxes1
==
4
);
assert
(
nMuxes0
==
2
||
nMuxes1
==
2
);
if
(
fSkipMoving
)
{
Str_MuxRestructAreaThree
(
pNew
,
pMux
,
vDelay
,
fVerbose
);
return
0
;
}
if
(
nMuxes0
==
2
)
{
pFanin0
=
Str_MuxFanin
(
pMux
,
0
);
assert
(
Str_MuxHasFanin
(
pFanin0
,
0
)
!=
Str_MuxHasFanin
(
pFanin0
,
1
)
);
Path
[
3
]
=
Abc_Var2Lit
(
pRoot
->
Id
,
i
);
Path
[
2
]
=
Abc_Var2Lit
(
pMux
->
Id
,
0
);
Path
[
1
]
=
Abc_Var2Lit
(
pFanin0
->
Id
,
Str_MuxHasFanin
(
pFanin0
,
1
));
pFanin1
=
Str_MuxFanin
(
pFanin0
,
Str_MuxHasFanin
(
pFanin0
,
1
)
);
assert
(
!
Str_MuxHasFanin
(
pFanin1
,
0
)
&&
!
Str_MuxHasFanin
(
pFanin1
,
1
)
);
Path
[
0
]
=
Abc_Var2Lit
(
pFanin1
->
Id
,
0
);
Str_MuxChangeOnce
(
pTree
,
Path
,
0
,
3
,
NULL
,
pNew
,
vDelay
);
}
if
(
nMuxes1
==
2
)
{
pFanin0
=
Str_MuxFanin
(
pMux
,
1
);
assert
(
Str_MuxHasFanin
(
pFanin0
,
0
)
!=
Str_MuxHasFanin
(
pFanin0
,
1
)
);
Path
[
3
]
=
Abc_Var2Lit
(
pRoot
->
Id
,
i
);
Path
[
2
]
=
Abc_Var2Lit
(
pMux
->
Id
,
1
);
Path
[
1
]
=
Abc_Var2Lit
(
pFanin0
->
Id
,
Str_MuxHasFanin
(
pFanin0
,
1
));
pFanin1
=
Str_MuxFanin
(
pFanin0
,
Str_MuxHasFanin
(
pFanin0
,
1
)
);
assert
(
!
Str_MuxHasFanin
(
pFanin1
,
0
)
&&
!
Str_MuxHasFanin
(
pFanin1
,
1
)
);
Path
[
0
]
=
Abc_Var2Lit
(
pFanin1
->
Id
,
0
);
Str_MuxChangeOnce
(
pTree
,
Path
,
0
,
3
,
NULL
,
pNew
,
vDelay
);
}
Str_MuxRestructAreaThree
(
pNew
,
pMux
,
vDelay
,
fVerbose
);
return
nMuxes0
+
nMuxes1
-
2
;
}
int
Str_MuxRestructureArea
(
Gia_Man_t
*
pNew
,
Str_Ntk_t
*
pNtk
,
int
iMux
,
int
nMuxes
,
Vec_Int_t
*
vDelay
,
int
nLutSize
,
int
fVerbose
)
{
int
Limit
=
500
;
Str_Mux_t
pTree
[
500
];
int
Result
;
if
(
nMuxes
>=
Limit
)
return
-
1
;
assert
(
nMuxes
<
Limit
);
Str_MuxCreate
(
pTree
,
pNtk
,
iMux
,
nMuxes
,
vDelay
,
nLutSize
);
Result
=
Str_MuxRestructArea_rec
(
pNew
,
pTree
,
pTree
,
0
,
vDelay
,
fVerbose
);
assert
(
Result
>=
0
&&
Result
<=
2
);
return
Str_MuxToGia_rec
(
pNew
,
pTree
,
0
,
vDelay
);
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment