mirror of https://github.com/YosysHQ/abc.git
commit
5305d93037
|
|
@ -35,7 +35,7 @@ Gia_Man_t *Gia_ManRrr(Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int
|
||||||
Par.fOptOnInsert = fOptOnInsert;
|
Par.fOptOnInsert = fOptOnInsert;
|
||||||
Par.fGreedy = fGreedy;
|
Par.fGreedy = fGreedy;
|
||||||
rrr::Perform(&ntk, &Par);
|
rrr::Perform(&ntk, &Par);
|
||||||
Gia_Man_t *pNew = rrr::CreateGia(&ntk);
|
Gia_Man_t *pNew = rrr::CreateGia(&ntk, false);
|
||||||
return pNew;
|
return pNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46327,7 +46327,7 @@ int Abc_CommandAbc9Rrr( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||||
{
|
{
|
||||||
Gia_Man_t *pNew;
|
Gia_Man_t *pNew;
|
||||||
int c;
|
int c;
|
||||||
int iSeed = 0, nWords = 10, nTimeout = 0, nSchedulerVerbose = 1, nPartitionerVerbose = 0, nOptimizerVerbose = 0, nAnalyzerVerbose = 0, nSimulatorVerbose = 0, nSatSolverVerbose = 0, fUseBddCspf = 0, fUseBddMspf = 0, nConflictLimit = 0, nSortType = -1, nOptimizerFlow = 0, nSchedulerFlow = 0, nPartitionType = 0, nDistance = 0, nJobs = 1, nThreads = 1, nPartitionSize = 0, nPartitionSizeMin = 0, fDeterministic = 1, nParallelPartitions = 1, fOptOnInsert = 0, fGreedy = 1;
|
int iSeed = 0, nWords = 10, nTimeout = 0, nSchedulerVerbose = 0, nPartitionerVerbose = 0, nOptimizerVerbose = 0, nAnalyzerVerbose = 0, nSimulatorVerbose = 0, nSatSolverVerbose = 0, fUseBddCspf = 0, fUseBddMspf = 0, nConflictLimit = 0, nSortType = -1, nOptimizerFlow = 0, nSchedulerFlow = 0, nPartitionType = 0, nDistance = 0, nJobs = 1, nThreads = 1, nPartitionSize = 0, nPartitionSizeMin = 0, fDeterministic = 1, nParallelPartitions = 1, fOptOnInsert = 0, fGreedy = 1;
|
||||||
Extra_UtilGetoptReset();
|
Extra_UtilGetoptReset();
|
||||||
while ( ( c = Extra_UtilGetopt( argc, argv, "XYZNJKLBDRWTCGVPOAQSabdegh" ) ) != EOF )
|
while ( ( c = Extra_UtilGetopt( argc, argv, "XYZNJKLBDRWTCGVPOAQSabdegh" ) ) != EOF )
|
||||||
{
|
{
|
||||||
|
|
@ -46446,6 +46446,51 @@ int Abc_CommandAbc9Rrr( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( nSchedulerVerbose )
|
||||||
|
{
|
||||||
|
Abc_Print( 2, "Using the following parameters :\n" );
|
||||||
|
Abc_Print( 2, "\t-X %3d : method ", nOptimizerFlow );
|
||||||
|
switch( nOptimizerFlow )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
Abc_Print( 2, "(0 = single-add resub)" );
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Abc_Print( 2, "(1 = multi-add resub)" );
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Abc_Print( 2, "(2 = repeat single-add and multi-add resubs)" );
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
Abc_Print( 2, "(3 = random one meaningful resub)" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Abc_Print( 2, "\n" );
|
||||||
|
Abc_Print( 2, "\t-Y %3d : flow ", nSchedulerFlow );
|
||||||
|
switch ( nSchedulerFlow )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
Abc_Print( 2, "(0 = apply method once)" );
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Abc_Print( 2, "(1 = iterate like transtoch)" );
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Abc_Print( 2, "(2 = iterate like deepsyn)" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Abc_Print( 2, "\n" );
|
||||||
|
Abc_Print( 2, "\t-N %3d : number of jobs to create by restarting or partitioning\n", nJobs );
|
||||||
|
Abc_Print( 2, "\t-J %3d : number of threads\n", nThreads );
|
||||||
|
Abc_Print( 2, "\t-K %3d : maximum partition size (0 = no partitioning)\n", nPartitionSize );
|
||||||
|
Abc_Print( 2, "\t-L %3d : minimum partition size\n", nPartitionSizeMin );
|
||||||
|
Abc_Print( 2, "\t-B %3d : maximum number of partitions to optimize in parallel\n", nParallelPartitions );
|
||||||
|
Abc_Print( 2, "\t-R %3d : random number generator seed\n", iSeed );
|
||||||
|
Abc_Print( 2, "\t-T %3d : timeout in seconds (0 = no timeout)\n", nTimeout );
|
||||||
|
Abc_Print( 2, "\t-C %3d : conflict limit (0 = no limit)\n", nConflictLimit );
|
||||||
|
Abc_Print( 2, "Use command line switch \"-h\" to see more options\n\n" );
|
||||||
|
}
|
||||||
|
|
||||||
pNew = Gia_ManRrr( pAbc->pGia, iSeed, nWords, nTimeout, nSchedulerVerbose, nPartitionerVerbose, nOptimizerVerbose, nAnalyzerVerbose, nSimulatorVerbose, nSatSolverVerbose, fUseBddCspf, fUseBddMspf, nConflictLimit, nSortType, nOptimizerFlow, nSchedulerFlow, nPartitionType, nDistance, nJobs, nThreads, nPartitionSize, nPartitionSizeMin, fDeterministic, nParallelPartitions, fOptOnInsert, fGreedy );
|
pNew = Gia_ManRrr( pAbc->pGia, iSeed, nWords, nTimeout, nSchedulerVerbose, nPartitionerVerbose, nOptimizerVerbose, nAnalyzerVerbose, nSimulatorVerbose, nSatSolverVerbose, fUseBddCspf, fUseBddMspf, nConflictLimit, nSortType, nOptimizerFlow, nSchedulerFlow, nPartitionType, nDistance, nJobs, nThreads, nPartitionSize, nPartitionSizeMin, fDeterministic, nParallelPartitions, fOptOnInsert, fGreedy );
|
||||||
|
|
||||||
Abc_FrameUpdateGia( pAbc, pNew );
|
Abc_FrameUpdateGia( pAbc, pNew );
|
||||||
|
|
@ -46469,10 +46514,10 @@ usage:
|
||||||
Abc_Print( -2, "\t 1: level base\n" );
|
Abc_Print( -2, "\t 1: level base\n" );
|
||||||
Abc_Print( -2, "\t-N num : number of jobs to create by restarting or partitioning [default = %d]\n", nJobs );
|
Abc_Print( -2, "\t-N num : number of jobs to create by restarting or partitioning [default = %d]\n", nJobs );
|
||||||
Abc_Print( -2, "\t-J num : number of threads [default = %d]\n", nThreads );
|
Abc_Print( -2, "\t-J num : number of threads [default = %d]\n", nThreads );
|
||||||
Abc_Print( -2, "\t-K num : partition size (0 = no partitioning) [default = %d]\n", nPartitionSize );
|
Abc_Print( -2, "\t-K num : maximum partition size (0 = no partitioning) [default = %d]\n", nPartitionSize );
|
||||||
Abc_Print( -2, "\t-K num : minimum partition size [default = %d]\n", nPartitionSizeMin );
|
Abc_Print( -2, "\t-L num : minimum partition size [default = %d]\n", nPartitionSizeMin );
|
||||||
Abc_Print( -2, "\t-B num : max number of partitions in parallel [default = %d]\n", nParallelPartitions );
|
Abc_Print( -2, "\t-B num : maximum number of partitions in parallel [default = %d]\n", nParallelPartitions );
|
||||||
Abc_Print( -2, "\t-D num : distance between nodes (0 = no limit) [default = %d]\n", nDistance );
|
Abc_Print( -2, "\t-D num : maximum distance between node and new fanin (0 = no limit) [default = %d]\n", nDistance );
|
||||||
Abc_Print( -2, "\t-R num : random number generator seed [default = %d]\n", iSeed );
|
Abc_Print( -2, "\t-R num : random number generator seed [default = %d]\n", iSeed );
|
||||||
Abc_Print( -2, "\t-W num : number of simulation words [default = %d]\n", nWords );
|
Abc_Print( -2, "\t-W num : number of simulation words [default = %d]\n", nWords );
|
||||||
Abc_Print( -2, "\t-T num : timeout in seconds (0 = no timeout) [default = %d]\n", nTimeout );
|
Abc_Print( -2, "\t-T num : timeout in seconds (0 = no timeout) [default = %d]\n", nTimeout );
|
||||||
|
|
@ -46487,7 +46532,7 @@ usage:
|
||||||
Abc_Print( -2, "\t-a : use BDD-based analyzer (CSPF) [default = %s]\n", fUseBddCspf? "yes": "no" );
|
Abc_Print( -2, "\t-a : use BDD-based analyzer (CSPF) [default = %s]\n", fUseBddCspf? "yes": "no" );
|
||||||
Abc_Print( -2, "\t-b : use BDD-based analyzer (MSPF) [default = %s]\n", fUseBddMspf? "yes": "no" );
|
Abc_Print( -2, "\t-b : use BDD-based analyzer (MSPF) [default = %s]\n", fUseBddMspf? "yes": "no" );
|
||||||
Abc_Print( -2, "\t-d : ensure deterministic execution [default = %s]\n", fDeterministic? "yes": "no" );
|
Abc_Print( -2, "\t-d : ensure deterministic execution [default = %s]\n", fDeterministic? "yes": "no" );
|
||||||
Abc_Print( -2, "\t-e : apply c2rs; dc2 after importing changes of partitions [default = %s]\n", fOptOnInsert? "yes": "no" );
|
Abc_Print( -2, "\t-e : apply \"c2rs; dc2\" after importing changes of partitions [default = %s]\n", fOptOnInsert? "yes": "no" );
|
||||||
Abc_Print( -2, "\t-g : discard changes that increased the cost [default = %s]\n", fGreedy? "yes": "no" );
|
Abc_Print( -2, "\t-g : discard changes that increased the cost [default = %s]\n", fGreedy? "yes": "no" );
|
||||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,11 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
Gia_Man_t *CreateGia(Ntk *pNtk) {
|
Gia_Man_t *CreateGia(Ntk *pNtk, bool fHash = true) {
|
||||||
Gia_Man_t *pGia = Gia_ManStart(pNtk->GetNumNodes());
|
Gia_Man_t *pGia = Gia_ManStart(pNtk->GetNumNodes());
|
||||||
Gia_ManHashStart(pGia);
|
if(fHash) {
|
||||||
|
Gia_ManHashStart(pGia);
|
||||||
|
}
|
||||||
std::vector<int> v(pNtk->GetNumNodes());
|
std::vector<int> v(pNtk->GetNumNodes());
|
||||||
v[0] = Gia_ManConst0Lit();
|
v[0] = Gia_ManConst0Lit();
|
||||||
pNtk->ForEachPi([&](int id) {
|
pNtk->ForEachPi([&](int id) {
|
||||||
|
|
@ -43,8 +45,10 @@ namespace rrr {
|
||||||
pNtk->ForEachFanin(id, [&](int fi, bool c) {
|
pNtk->ForEachFanin(id, [&](int fi, bool c) {
|
||||||
if(x == -1) {
|
if(x == -1) {
|
||||||
x = Abc_LitNotCond(v[fi], c);
|
x = Abc_LitNotCond(v[fi], c);
|
||||||
} else {
|
} else if(fHash) {
|
||||||
x = Gia_ManHashAnd(pGia, x, Abc_LitNotCond(v[fi], c));
|
x = Gia_ManHashAnd(pGia, x, Abc_LitNotCond(v[fi], c));
|
||||||
|
} else {
|
||||||
|
x = Gia_ManAppendAnd(pGia, x, Abc_LitNotCond(v[fi], c));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if(x == -1) {
|
if(x == -1) {
|
||||||
|
|
@ -55,7 +59,9 @@ namespace rrr {
|
||||||
pNtk->ForEachPoDriver([&](int fi, bool c) {
|
pNtk->ForEachPoDriver([&](int fi, bool c) {
|
||||||
Gia_ManAppendCo(pGia, Abc_LitNotCond(v[fi], c));
|
Gia_ManAppendCo(pGia, Abc_LitNotCond(v[fi], c));
|
||||||
});
|
});
|
||||||
Gia_ManHashStop(pGia);
|
if(fHash) {
|
||||||
|
Gia_ManHashStop(pGia);
|
||||||
|
}
|
||||||
return pGia;
|
return pGia;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,7 +78,7 @@ namespace rrr {
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
Abc_FrameSetBatchMode(0);
|
Abc_FrameSetBatchMode(0);
|
||||||
}
|
}
|
||||||
pNtk->Read(Abc_FrameReadGia(pAbc), GiaReader<Ntk>);
|
pNtk->Read(Abc_FrameReadGia(pAbc), GiaReader<Ntk>, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,16 @@ namespace rrr {
|
||||||
public:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
Analyzer(Parameter const *pPar);
|
Analyzer(Parameter const *pPar);
|
||||||
void UpdateNetwork(Ntk *pNtk_, bool fSame);
|
void AssignNetwork(Ntk *pNtk_, bool fReuse);
|
||||||
|
|
||||||
// checks
|
// checks
|
||||||
bool CheckRedundancy(int id, int idx);
|
bool CheckRedundancy(int id, int idx);
|
||||||
bool CheckFeasibility(int id, int fi, bool c);
|
bool CheckFeasibility(int id, int fi, bool c);
|
||||||
|
|
||||||
|
// summary
|
||||||
|
void ResetSummary();
|
||||||
|
summary<int> GetStatsSummary() const;
|
||||||
|
summary<double> GetTimesSummary() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* {{{ Constructors */
|
/* {{{ Constructors */
|
||||||
|
|
@ -41,10 +46,10 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk, typename Sim, typename Sol>
|
template <typename Ntk, typename Sim, typename Sol>
|
||||||
void Analyzer<Ntk, Sim, Sol>::UpdateNetwork(Ntk *pNtk_, bool fSame) {
|
void Analyzer<Ntk, Sim, Sol>::AssignNetwork(Ntk *pNtk_, bool fReuse) {
|
||||||
pNtk = pNtk_;
|
pNtk = pNtk_;
|
||||||
sim.UpdateNetwork(pNtk, fSame);
|
sim.AssignNetwork(pNtk, fReuse);
|
||||||
sol.UpdateNetwork(pNtk, fSame);
|
sol.AssignNetwork(pNtk, fReuse);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -70,6 +75,10 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
sim.AddCex(sol.GetCex());
|
sim.AddCex(sol.GetCex());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// if(nVerbose) {
|
||||||
|
// std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is not redundant" << std::endl;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -93,12 +102,42 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
sim.AddCex(sol.GetCex());
|
sim.AddCex(sol.GetCex());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// if(nVerbose) {
|
||||||
|
// std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is not feasible" << std::endl;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ Summary */
|
||||||
|
|
||||||
|
template <typename Ntk, typename Sim, typename Sol>
|
||||||
|
void Analyzer<Ntk, Sim, Sol>::ResetSummary() {
|
||||||
|
sim.ResetSummary();
|
||||||
|
sol.ResetSummary();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk, typename Sim, typename Sol>
|
||||||
|
summary<int> Analyzer<Ntk, Sim, Sol>::GetStatsSummary() const {
|
||||||
|
summary<int> v = sim.GetStatsSummary();
|
||||||
|
summary<int> v2 = sol.GetStatsSummary();
|
||||||
|
v.insert(v.end(), v2.begin(), v2.end());
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk, typename Sim, typename Sol>
|
||||||
|
summary<double> Analyzer<Ntk, Sim, Sol>::GetTimesSummary() const {
|
||||||
|
summary<double> v = sim.GetTimesSummary();
|
||||||
|
summary<double> v2 = sol.GetTimesSummary();
|
||||||
|
v.insert(v.end(), v2.begin(), v2.end());
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ABC_NAMESPACE_CXX_HEADER_END
|
ABC_NAMESPACE_CXX_HEADER_END
|
||||||
|
|
|
||||||
|
|
@ -64,13 +64,13 @@ namespace rrr {
|
||||||
AndNetwork &operator=(AndNetwork const &x);
|
AndNetwork &operator=(AndNetwork const &x);
|
||||||
|
|
||||||
// initialization APIs (should not be called after optimization has started)
|
// initialization APIs (should not be called after optimization has started)
|
||||||
void Clear();
|
void Clear(bool fClearCallbacks = true);
|
||||||
void Reserve(int nReserve);
|
void Reserve(int nReserve);
|
||||||
int AddPi();
|
int AddPi();
|
||||||
int AddAnd(int id0, int id1, bool c0, bool c1);
|
int AddAnd(int id0, int id1, bool c0, bool c1);
|
||||||
int AddPo(int id, bool c);
|
int AddPo(int id, bool c);
|
||||||
template <typename Ntk, typename Reader>
|
template <typename Ntk, typename Reader>
|
||||||
void Read(Ntk *pFrom, Reader &reader);
|
void Read(Ntk *pFrom, Reader &reader, bool fNew = true);
|
||||||
|
|
||||||
// network properties
|
// network properties
|
||||||
bool UseComplementedEdges() const;
|
bool UseComplementedEdges() const;
|
||||||
|
|
@ -78,6 +78,7 @@ namespace rrr {
|
||||||
int GetNumPis() const;
|
int GetNumPis() const;
|
||||||
int GetNumInts() const;
|
int GetNumInts() const;
|
||||||
int GetNumPos() const;
|
int GetNumPos() const;
|
||||||
|
int GetNumLevels() const;
|
||||||
int GetConst0() const;
|
int GetConst0() const;
|
||||||
int GetPi(int idx) const;
|
int GetPi(int idx) const;
|
||||||
int GetPo(int idx) const;
|
int GetPo(int idx) const;
|
||||||
|
|
@ -272,7 +273,7 @@ namespace rrr {
|
||||||
|
|
||||||
/* {{{ Initialization APIs */
|
/* {{{ Initialization APIs */
|
||||||
|
|
||||||
void AndNetwork::Clear() {
|
void AndNetwork::Clear(bool fClearCallbacks) {
|
||||||
nNodes = 0;
|
nNodes = 0;
|
||||||
vPis.clear();
|
vPis.clear();
|
||||||
lInts.clear();
|
lInts.clear();
|
||||||
|
|
@ -284,7 +285,9 @@ namespace rrr {
|
||||||
iTrav = 0;
|
iTrav = 0;
|
||||||
vTrav.clear();
|
vTrav.clear();
|
||||||
fPropagating = false;
|
fPropagating = false;
|
||||||
vCallbacks.clear();
|
if(fClearCallbacks) {
|
||||||
|
vCallbacks.clear();
|
||||||
|
}
|
||||||
vBackups.clear();
|
vBackups.clear();
|
||||||
// add constant node
|
// add constant node
|
||||||
vvFaninEdges.emplace_back();
|
vvFaninEdges.emplace_back();
|
||||||
|
|
@ -330,9 +333,13 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk, typename Reader>
|
template <typename Ntk, typename Reader>
|
||||||
void AndNetwork::Read(Ntk *pFrom, Reader &reader) {
|
void AndNetwork::Read(Ntk *pFrom, Reader &reader, bool fNew) {
|
||||||
Clear();
|
Clear(false);
|
||||||
reader(pFrom, this);
|
reader(pFrom, this);
|
||||||
|
Action action;
|
||||||
|
action.type = READ;
|
||||||
|
action.fNew = fNew;
|
||||||
|
TakenAction(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -359,6 +366,23 @@ namespace rrr {
|
||||||
return int_size(vPos);
|
return int_size(vPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AndNetwork::GetNumLevels() const {
|
||||||
|
int nMaxLevel = 0;
|
||||||
|
std::vector<int> vLevels(nNodes);
|
||||||
|
ForEachInt([&](int id) {
|
||||||
|
ForEachFanin(id, [&](int fi) {
|
||||||
|
if(vLevels[id] < vLevels[fi]) {
|
||||||
|
vLevels[id] = vLevels[fi];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
vLevels[id] += 1;
|
||||||
|
if(nMaxLevel < vLevels[id]) {
|
||||||
|
nMaxLevel = vLevels[id];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return nMaxLevel;
|
||||||
|
}
|
||||||
|
|
||||||
inline int AndNetwork::GetConst0() const {
|
inline int AndNetwork::GetConst0() const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ namespace rrr {
|
||||||
int nVerbose;
|
int nVerbose;
|
||||||
|
|
||||||
// data
|
// data
|
||||||
|
bool fInitialized;
|
||||||
NewBdd::Man *pBdd;
|
NewBdd::Man *pBdd;
|
||||||
int target;
|
int target;
|
||||||
std::vector<lit> vFs;
|
std::vector<lit> vFs;
|
||||||
|
|
@ -35,6 +36,14 @@ namespace rrr {
|
||||||
// backups
|
// backups
|
||||||
std::vector<BddAnalyzer> vBackups;
|
std::vector<BddAnalyzer> vBackups;
|
||||||
|
|
||||||
|
// stats
|
||||||
|
uint64_t nNodesOld;
|
||||||
|
uint64_t nNodesAccumulated;
|
||||||
|
double durationSimulation;
|
||||||
|
double durationPf;
|
||||||
|
double durationCheck;
|
||||||
|
double durationReorder;
|
||||||
|
|
||||||
// BDD utils
|
// BDD utils
|
||||||
void IncRef(lit x) const;
|
void IncRef(lit x) const;
|
||||||
void DecRef(lit x) const;
|
void DecRef(lit x) const;
|
||||||
|
|
@ -61,6 +70,10 @@ namespace rrr {
|
||||||
void CspfNode(int id);
|
void CspfNode(int id);
|
||||||
void Cspf(int id = -1, bool fC = true);
|
void Cspf(int id = -1, bool fC = true);
|
||||||
|
|
||||||
|
// preparation
|
||||||
|
void Reset(bool fReuse = false);
|
||||||
|
void Initialize();
|
||||||
|
|
||||||
// save & load
|
// save & load
|
||||||
void Save(int slot);
|
void Save(int slot);
|
||||||
void Load(int slot);
|
void Load(int slot);
|
||||||
|
|
@ -71,11 +84,16 @@ namespace rrr {
|
||||||
BddAnalyzer();
|
BddAnalyzer();
|
||||||
BddAnalyzer(Parameter const *pPar);
|
BddAnalyzer(Parameter const *pPar);
|
||||||
~BddAnalyzer();
|
~BddAnalyzer();
|
||||||
void UpdateNetwork(Ntk *pNtk_, bool fSame);
|
void AssignNetwork(Ntk *pNtk_, bool fReuse);
|
||||||
|
|
||||||
// checks
|
// checks
|
||||||
bool CheckRedundancy(int id, int idx);
|
bool CheckRedundancy(int id, int idx);
|
||||||
bool CheckFeasibility(int id, int fi, bool c);
|
bool CheckFeasibility(int id, int fi, bool c);
|
||||||
|
|
||||||
|
// summary
|
||||||
|
void ResetSummary();
|
||||||
|
summary<int> GetStatsSummary() const;
|
||||||
|
summary<double> GetTimesSummary() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* {{{ BDD utils */
|
/* {{{ BDD utils */
|
||||||
|
|
@ -163,103 +181,136 @@ namespace rrr {
|
||||||
void BddAnalyzer<Ntk>::ActionCallback(Action const &action) {
|
void BddAnalyzer<Ntk>::ActionCallback(Action const &action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case REMOVE_FANIN:
|
case REMOVE_FANIN:
|
||||||
|
assert(fInitialized);
|
||||||
vUpdates[action.id] = true;
|
vUpdates[action.id] = true;
|
||||||
vGUpdates[action.fi] = true;
|
vGUpdates[action.fi] = true;
|
||||||
DecRef(vvCs[action.id][action.idx]);
|
DecRef(vvCs[action.id][action.idx]);
|
||||||
vvCs[action.id].erase(vvCs[action.id].begin() + action.idx);
|
vvCs[action.id].erase(vvCs[action.id].begin() + action.idx);
|
||||||
|
if(target != action.id) {
|
||||||
|
// require resimulate before next fesibility check
|
||||||
|
// (this is not mandatory if no pending updates are in TFI of new fanin, but we would rather update than checking every time)
|
||||||
|
target = -1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case REMOVE_UNUSED:
|
case REMOVE_UNUSED:
|
||||||
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
if(fInitialized) {
|
||||||
|
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
||||||
|
for(int fi: action.vFanins) {
|
||||||
|
vGUpdates[fi] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assign(vFs[action.id], LitMax);
|
||||||
|
Assign(vGs[action.id], LitMax);
|
||||||
|
DelVec(vvCs[action.id]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REMOVE_BUFFER:
|
||||||
|
if(fInitialized) {
|
||||||
|
if(vUpdates[action.id]) {
|
||||||
|
for(int fo: action.vFanouts) {
|
||||||
|
vUpdates[fo] = true;
|
||||||
|
vCUpdates[fo] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
||||||
|
vGUpdates[action.fi] = true;
|
||||||
|
}
|
||||||
|
Assign(vFs[action.id], LitMax);
|
||||||
|
Assign(vGs[action.id], LitMax);
|
||||||
|
DelVec(vvCs[action.id]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REMOVE_CONST:
|
||||||
|
if(fInitialized) {
|
||||||
|
if(vUpdates[action.id]) {
|
||||||
|
for(int fo: action.vFanouts) {
|
||||||
|
vUpdates[fo] = true;
|
||||||
|
vCUpdates[fo] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
for(int fi: action.vFanins) {
|
for(int fi: action.vFanins) {
|
||||||
vGUpdates[fi] = true;
|
vGUpdates[fi] = true;
|
||||||
}
|
}
|
||||||
|
Assign(vFs[action.id], LitMax);
|
||||||
|
Assign(vGs[action.id], LitMax);
|
||||||
|
DelVec(vvCs[action.id]);
|
||||||
}
|
}
|
||||||
Assign(vFs[action.id], LitMax);
|
|
||||||
Assign(vGs[action.id], LitMax);
|
|
||||||
DelVec(vvCs[action.id]);
|
|
||||||
break;
|
|
||||||
case REMOVE_BUFFER:
|
|
||||||
if(vUpdates[action.id]) {
|
|
||||||
for(int fo: action.vFanouts) {
|
|
||||||
vUpdates[fo] = true;
|
|
||||||
vCUpdates[fo] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
|
||||||
vGUpdates[action.fi] = true;
|
|
||||||
}
|
|
||||||
Assign(vFs[action.id], LitMax);
|
|
||||||
Assign(vGs[action.id], LitMax);
|
|
||||||
DelVec(vvCs[action.id]);
|
|
||||||
break;
|
|
||||||
case REMOVE_CONST:
|
|
||||||
if(vUpdates[action.id]) {
|
|
||||||
for(int fo: action.vFanouts) {
|
|
||||||
vUpdates[fo] = true;
|
|
||||||
vCUpdates[fo] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int fi: action.vFanins) {
|
|
||||||
vGUpdates[fi] = true;
|
|
||||||
}
|
|
||||||
Assign(vFs[action.id], LitMax);
|
|
||||||
Assign(vGs[action.id], LitMax);
|
|
||||||
DelVec(vvCs[action.id]);
|
|
||||||
break;
|
break;
|
||||||
case ADD_FANIN:
|
case ADD_FANIN:
|
||||||
|
assert(action.id == target);
|
||||||
|
assert(fInitialized);
|
||||||
vUpdates[action.id] = true;
|
vUpdates[action.id] = true;
|
||||||
vCUpdates[action.id] = true;
|
vCUpdates[action.id] = true;
|
||||||
vvCs[action.id].insert(vvCs[action.id].begin() + action.idx, LitMax);
|
vvCs[action.id].insert(vvCs[action.id].begin() + action.idx, LitMax);
|
||||||
break;
|
break;
|
||||||
case TRIVIAL_COLLAPSE: {
|
case TRIVIAL_COLLAPSE:
|
||||||
if(vGUpdates[action.fi] || vCUpdates[action.fi]) {
|
if(fInitialized) {
|
||||||
|
if(vGUpdates[action.fi] || vCUpdates[action.fi]) {
|
||||||
|
vCUpdates[action.id] = true;
|
||||||
|
}
|
||||||
|
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
||||||
|
DecRef(*it);
|
||||||
|
it = vvCs[action.id].erase(it);
|
||||||
|
vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end());
|
||||||
|
vvCs[action.fi].clear();
|
||||||
|
Assign(vFs[action.fi], LitMax);
|
||||||
|
Assign(vGs[action.fi], LitMax);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TRIVIAL_DECOMPOSE:
|
||||||
|
if(fInitialized) {
|
||||||
|
Allocate();
|
||||||
|
SimulateNode(action.fi, vFs);
|
||||||
|
// time of this simulation is not measured for simplicity sake
|
||||||
|
assert(vGs[action.fi] == LitMax);
|
||||||
|
Assign(vGs[action.fi], vGs[action.id]);
|
||||||
|
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
||||||
|
assert(vvCs[action.fi].empty());
|
||||||
|
vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end());
|
||||||
|
vvCs[action.id].erase(it, vvCs[action.id].end());
|
||||||
|
assert(vvCs[action.id].size() == action.idx);
|
||||||
|
vvCs[action.id].resize(action.idx + 1, LitMax);
|
||||||
|
Assign(vvCs[action.id][action.idx], vGs[action.fi]);
|
||||||
|
vUpdates[action.fi] = false;
|
||||||
|
vGUpdates[action.fi] = false;
|
||||||
|
vCUpdates[action.fi] = vCUpdates[action.id];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SORT_FANINS:
|
||||||
|
if(fInitialized) {
|
||||||
|
std::vector<lit> vCs = vvCs[action.id];
|
||||||
|
vvCs[action.id].clear();
|
||||||
|
for(int index: action.vIndices) {
|
||||||
|
vvCs[action.id].push_back(vCs[index]);
|
||||||
|
}
|
||||||
|
if(!fResim) {
|
||||||
|
fResim = true;
|
||||||
|
/* commenting out the following because it might not be worth checking
|
||||||
|
// if sorted node is in TFO of functionally updated nodes, resimulation is required
|
||||||
|
std::vector<int> vFanouts;
|
||||||
|
pNtk->ForEachInt([&](int id) {
|
||||||
|
if(vUpdates[id]) {
|
||||||
|
pNtk->ForEachFanout(id, false, [&](int fo) {
|
||||||
|
vFanouts.push_back(fo);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
pNtk->ForEachTfos(vFanouts, false, [&](int fo) {
|
||||||
|
if(fResim) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(fo == action.id) {
|
||||||
|
fResim = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
}
|
||||||
vCUpdates[action.id] = true;
|
vCUpdates[action.id] = true;
|
||||||
}
|
}
|
||||||
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
|
||||||
DecRef(*it);
|
|
||||||
it = vvCs[action.id].erase(it);
|
|
||||||
vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end());
|
|
||||||
vvCs[action.fi].clear();
|
|
||||||
Assign(vFs[action.fi], LitMax);
|
|
||||||
Assign(vGs[action.fi], LitMax);
|
|
||||||
break;
|
break;
|
||||||
}
|
case READ:
|
||||||
case TRIVIAL_DECOMPOSE: {
|
Reset(!action.fNew);
|
||||||
Allocate();
|
|
||||||
SimulateNode(action.fi, vFs);
|
|
||||||
assert(vGs[action.fi] == LitMax);
|
|
||||||
Assign(vGs[action.fi], vGs[action.id]);
|
|
||||||
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
|
||||||
assert(vvCs[action.fi].empty());
|
|
||||||
vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end());
|
|
||||||
vvCs[action.id].erase(it, vvCs[action.id].end());
|
|
||||||
assert(vvCs[action.id].size() == action.idx);
|
|
||||||
vvCs[action.id].resize(action.idx + 1, LitMax);
|
|
||||||
Assign(vvCs[action.id][action.idx], vGs[action.fi]);
|
|
||||||
vUpdates[action.fi] = false;
|
|
||||||
vGUpdates[action.fi] = false;
|
|
||||||
vCUpdates[action.fi] = vCUpdates[action.id];
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case SORT_FANINS: {
|
|
||||||
std::vector<lit> vCs = vvCs[action.id];
|
|
||||||
vvCs[action.id].clear();
|
|
||||||
for(int index: action.vIndices) {
|
|
||||||
vvCs[action.id].push_back(vCs[index]);
|
|
||||||
}
|
|
||||||
if(!fResim && target != -1 && target != action.id) {
|
|
||||||
pNtk->ForEachTfo(target, false, [&](int fo) {
|
|
||||||
if(fResim) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(fo == action.id) {
|
|
||||||
fResim = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
vCUpdates[action.id] = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SAVE:
|
case SAVE:
|
||||||
Save(action.idx);
|
Save(action.idx);
|
||||||
break;
|
break;
|
||||||
|
|
@ -306,6 +357,7 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
void BddAnalyzer<Ntk>::Simulate() {
|
void BddAnalyzer<Ntk>::Simulate() {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "symbolic simulation with BDD" << std::endl;
|
std::cout << "symbolic simulation with BDD" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
@ -324,6 +376,7 @@ namespace rrr {
|
||||||
vUpdates[id] = false;
|
vUpdates[id] = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
durationSimulation += Duration(timeStart, GetCurrentTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -410,6 +463,7 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
void BddAnalyzer<Ntk>::Cspf(int id, bool fC) {
|
void BddAnalyzer<Ntk>::Cspf(int id, bool fC) {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
if(id != -1) {
|
if(id != -1) {
|
||||||
pNtk->ForEachTfoReverse(id, false, [&](int fo) {
|
pNtk->ForEachTfoReverse(id, false, [&](int fo) {
|
||||||
CspfNode(fo);
|
CspfNode(fo);
|
||||||
|
|
@ -427,6 +481,78 @@ namespace rrr {
|
||||||
CspfNode(id);
|
CspfNode(id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
durationPf += Duration(timeStart, GetCurrentTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ Preparation */
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
void BddAnalyzer<Ntk>::Reset(bool fReuse) {
|
||||||
|
while(!vBackups.empty()) {
|
||||||
|
PopBack();
|
||||||
|
}
|
||||||
|
DelVec(vFs);
|
||||||
|
DelVec(vGs);
|
||||||
|
DelVecVec(vvCs);
|
||||||
|
fInitialized = false;
|
||||||
|
target = -1;
|
||||||
|
fResim = false;
|
||||||
|
vUpdates.clear();
|
||||||
|
vGUpdates.clear();
|
||||||
|
vCUpdates.clear();
|
||||||
|
if(!fReuse) {
|
||||||
|
nNodesOld = 0;
|
||||||
|
if(pBdd) {
|
||||||
|
nNodesAccumulated += pBdd->GetNumTotalCreatedNodes();
|
||||||
|
}
|
||||||
|
delete pBdd;
|
||||||
|
pBdd = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
void BddAnalyzer<Ntk>::Initialize() {
|
||||||
|
bool fUseReo = false;
|
||||||
|
if(!pBdd) {
|
||||||
|
NewBdd::Param Par;
|
||||||
|
Par.nObjsMaxLog = 25;
|
||||||
|
Par.nCacheMaxLog = 20;
|
||||||
|
Par.fCountOnes = false;
|
||||||
|
Par.nGbc = 1;
|
||||||
|
Par.nReo = 4000;
|
||||||
|
pBdd = new NewBdd::Man(pNtk->GetNumPis(), Par);
|
||||||
|
fUseReo = true;
|
||||||
|
}
|
||||||
|
assert(pBdd->GetNumVars() == pNtk->GetNumPis());
|
||||||
|
Allocate();
|
||||||
|
Assign(vFs[0], pBdd->Const0());
|
||||||
|
int idx = 0;
|
||||||
|
pNtk->ForEachPi([&](int id) {
|
||||||
|
Assign(vFs[id], pBdd->IthVar(idx));
|
||||||
|
idx++;
|
||||||
|
});
|
||||||
|
pNtk->ForEachInt([&](int id) {
|
||||||
|
vUpdates[id] = true;
|
||||||
|
});
|
||||||
|
Simulate();
|
||||||
|
if(fUseReo) {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
|
pBdd->Reorder();
|
||||||
|
pBdd->TurnOffReo();
|
||||||
|
durationReorder += Duration(timeStart, GetCurrentTime());
|
||||||
|
}
|
||||||
|
pNtk->ForEachInt([&](int id) {
|
||||||
|
vvCs[id].resize(pNtk->GetNumFanins(id), LitMax);
|
||||||
|
});
|
||||||
|
pNtk->ForEachPo([&](int id) {
|
||||||
|
vvCs[id].resize(1, LitMax);
|
||||||
|
Assign(vvCs[id][0], pBdd->Const0());
|
||||||
|
int fi = pNtk->GetFanin(id, 0);
|
||||||
|
vGUpdates[fi] = true;
|
||||||
|
});
|
||||||
|
fInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -468,7 +594,7 @@ namespace rrr {
|
||||||
vBackups.pop_back();
|
vBackups.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} Save & load end */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ Constructors */
|
/* {{{ Constructors */
|
||||||
|
|
||||||
|
|
@ -476,93 +602,34 @@ namespace rrr {
|
||||||
BddAnalyzer<Ntk>::BddAnalyzer() :
|
BddAnalyzer<Ntk>::BddAnalyzer() :
|
||||||
pNtk(NULL),
|
pNtk(NULL),
|
||||||
nVerbose(0),
|
nVerbose(0),
|
||||||
|
fInitialized(false),
|
||||||
pBdd(NULL),
|
pBdd(NULL),
|
||||||
target(-1),
|
target(-1),
|
||||||
fResim(false) {
|
fResim(false) {
|
||||||
|
ResetSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
BddAnalyzer<Ntk>::BddAnalyzer(Parameter const *pPar) :
|
BddAnalyzer<Ntk>::BddAnalyzer(Parameter const *pPar) :
|
||||||
pNtk(NULL),
|
pNtk(NULL),
|
||||||
nVerbose(pPar->nAnalyzerVerbose),
|
nVerbose(pPar->nAnalyzerVerbose),
|
||||||
|
fInitialized(false),
|
||||||
pBdd(NULL),
|
pBdd(NULL),
|
||||||
target(-1),
|
target(-1),
|
||||||
fResim(false) {
|
fResim(false) {
|
||||||
}
|
ResetSummary();
|
||||||
|
|
||||||
template <typename Ntk>
|
|
||||||
void BddAnalyzer<Ntk>::UpdateNetwork(Ntk *pNtk_, bool fSame) {
|
|
||||||
// clear
|
|
||||||
while(!vBackups.empty()) {
|
|
||||||
PopBack();
|
|
||||||
}
|
|
||||||
DelVec(vFs);
|
|
||||||
DelVec(vGs);
|
|
||||||
DelVecVec(vvCs);
|
|
||||||
pNtk = pNtk_;
|
|
||||||
target = -1;
|
|
||||||
fResim = false;
|
|
||||||
vUpdates.clear();
|
|
||||||
vGUpdates.clear();
|
|
||||||
vCUpdates.clear();
|
|
||||||
// alloc
|
|
||||||
bool fUseReo = false;
|
|
||||||
if(!pBdd || pBdd->GetNumVars() != pNtk->GetNumPis()) {
|
|
||||||
// need to reset manager
|
|
||||||
delete pBdd;
|
|
||||||
NewBdd::Param Par;
|
|
||||||
Par.nObjsMaxLog = 25;
|
|
||||||
Par.nCacheMaxLog = 20;
|
|
||||||
Par.fCountOnes = true;
|
|
||||||
Par.nGbc = 1;
|
|
||||||
Par.nReo = 4000;
|
|
||||||
pBdd = new NewBdd::Man(pNtk->GetNumPis(), Par);
|
|
||||||
fUseReo = true;
|
|
||||||
} else if(!fSame) {
|
|
||||||
// turning on reordering if network function changed
|
|
||||||
pBdd->TurnOnReo();
|
|
||||||
fUseReo = true;
|
|
||||||
}
|
|
||||||
Allocate();
|
|
||||||
// prepare
|
|
||||||
Assign(vFs[0], pBdd->Const0());
|
|
||||||
int idx = 0;
|
|
||||||
pNtk->ForEachPi([&](int id) {
|
|
||||||
Assign(vFs[id], pBdd->IthVar(idx));
|
|
||||||
idx++;
|
|
||||||
});
|
|
||||||
pNtk->ForEachInt([&](int id) {
|
|
||||||
vUpdates[id] = true;
|
|
||||||
});
|
|
||||||
Simulate();
|
|
||||||
if(fUseReo) {
|
|
||||||
pBdd->Reorder();
|
|
||||||
pBdd->TurnOffReo();
|
|
||||||
}
|
|
||||||
pNtk->ForEachInt([&](int id) {
|
|
||||||
vvCs[id].resize(pNtk->GetNumFanins(id), LitMax);
|
|
||||||
});
|
|
||||||
pNtk->ForEachPo([&](int id) {
|
|
||||||
vvCs[id].resize(1, LitMax);
|
|
||||||
Assign(vvCs[id][0], pBdd->Const0());
|
|
||||||
int fi = pNtk->GetFanin(id, 0);
|
|
||||||
vGUpdates[fi] = true;
|
|
||||||
});
|
|
||||||
pNtk->AddCallback(std::bind(&BddAnalyzer<Ntk>::ActionCallback, this, std::placeholders::_1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
BddAnalyzer<Ntk>::~BddAnalyzer() {
|
BddAnalyzer<Ntk>::~BddAnalyzer() {
|
||||||
while(!vBackups.empty()) {
|
Reset();
|
||||||
PopBack();
|
}
|
||||||
}
|
|
||||||
DelVec(vFs);
|
template <typename Ntk>
|
||||||
DelVec(vGs);
|
void BddAnalyzer<Ntk>::AssignNetwork(Ntk *pNtk_, bool fReuse) {
|
||||||
DelVecVec(vvCs);
|
Reset(fReuse);
|
||||||
if(pBdd) {
|
pNtk = pNtk_;
|
||||||
pBdd->PrintStats();
|
pNtk->AddCallback(std::bind(&BddAnalyzer<Ntk>::ActionCallback, this, std::placeholders::_1));
|
||||||
}
|
|
||||||
delete pBdd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -571,20 +638,22 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
bool BddAnalyzer<Ntk>::CheckRedundancy(int id, int idx) {
|
bool BddAnalyzer<Ntk>::CheckRedundancy(int id, int idx) {
|
||||||
if(fResim) {
|
if(!fInitialized) {
|
||||||
|
Initialize();
|
||||||
|
} else if(fResim) {
|
||||||
Simulate();
|
Simulate();
|
||||||
|
fResim = false;
|
||||||
}
|
}
|
||||||
Cspf(id);
|
Cspf(id);
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
|
bool fRedundant = false;
|
||||||
switch(pNtk->GetNodeType(id)) {
|
switch(pNtk->GetNodeType(id)) {
|
||||||
case AND: {
|
case AND: {
|
||||||
int fi = pNtk->GetFanin(id, idx);
|
int fi = pNtk->GetFanin(id, idx);
|
||||||
bool c = pNtk->GetCompl(id, idx);
|
bool c = pNtk->GetCompl(id, idx);
|
||||||
lit x = pBdd->Or(pBdd->LitNotCond(vFs[fi], c), vvCs[id][idx]);
|
lit x = pBdd->Or(pBdd->LitNotCond(vFs[fi], c), vvCs[id][idx]);
|
||||||
if(pBdd->IsConst1(x)) {
|
if(pBdd->IsConst1(x)) {
|
||||||
if(nVerbose) {
|
fRedundant = true;
|
||||||
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is redundant" << std::endl;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -592,18 +661,30 @@ namespace rrr {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is NOT redundant" << std::endl;
|
if(fRedundant) {
|
||||||
|
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is redundant" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is NOT redundant" << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
durationCheck += Duration(timeStart, GetCurrentTime());
|
||||||
|
return fRedundant;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
bool BddAnalyzer<Ntk>::CheckFeasibility(int id, int fi, bool c) {
|
bool BddAnalyzer<Ntk>::CheckFeasibility(int id, int fi, bool c) {
|
||||||
if(target != id) { // simualte if there has been update in non-tfo of this node
|
if(!fInitialized) {
|
||||||
|
Initialize();
|
||||||
|
} else if(target != id && (target == -1 || vUpdates[target])) {
|
||||||
|
// resimulation is required if there are pending updates in TFI of new fanin
|
||||||
|
// but it seems not worthwhile to check that condition every time
|
||||||
|
// so we update if pending updates are not only at current target
|
||||||
Simulate();
|
Simulate();
|
||||||
target = id;
|
|
||||||
}
|
}
|
||||||
|
target = id;
|
||||||
Cspf(id, false);
|
Cspf(id, false);
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
|
bool fFeasible = false;
|
||||||
switch(pNtk->GetNodeType(id)) {
|
switch(pNtk->GetNodeType(id)) {
|
||||||
case AND: {
|
case AND: {
|
||||||
lit x = pBdd->Or(pBdd->LitNot(vFs[id]), vGs[id]);
|
lit x = pBdd->Or(pBdd->LitNot(vFs[id]), vGs[id]);
|
||||||
|
|
@ -611,10 +692,7 @@ namespace rrr {
|
||||||
lit y = pBdd->Or(x, pBdd->LitNotCond(vFs[fi], c));
|
lit y = pBdd->Or(x, pBdd->LitNotCond(vFs[fi], c));
|
||||||
DecRef(x);
|
DecRef(x);
|
||||||
if(pBdd->IsConst1(y)) {
|
if(pBdd->IsConst1(y)) {
|
||||||
if(nVerbose) {
|
fFeasible = true;
|
||||||
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is feasible" << std::endl;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -622,9 +700,49 @@ namespace rrr {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is NOT feasible" << std::endl;
|
if(fFeasible) {
|
||||||
|
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is feasible" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is NOT feasible" << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
durationCheck += Duration(timeStart, GetCurrentTime());
|
||||||
|
return fFeasible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ Summary */
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
void BddAnalyzer<Ntk>::ResetSummary() {
|
||||||
|
if(pBdd) {
|
||||||
|
nNodesOld = pBdd->GetNumTotalCreatedNodes();
|
||||||
|
} else {
|
||||||
|
nNodesOld = 0;
|
||||||
|
}
|
||||||
|
nNodesAccumulated = 0;
|
||||||
|
durationSimulation = 0;
|
||||||
|
durationPf = 0;
|
||||||
|
durationCheck = 0;
|
||||||
|
durationReorder = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
summary<int> BddAnalyzer<Ntk>::GetStatsSummary() const {
|
||||||
|
summary<int> v;
|
||||||
|
v.emplace_back("bdd node", pBdd->GetNumTotalCreatedNodes() - nNodesOld + nNodesAccumulated);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
summary<double> BddAnalyzer<Ntk>::GetTimesSummary() const {
|
||||||
|
summary<double> v;
|
||||||
|
v.emplace_back("bdd symbolic simulation", durationSimulation);
|
||||||
|
v.emplace_back("bdd care computation", durationPf);
|
||||||
|
v.emplace_back("bdd check", durationCheck);
|
||||||
|
v.emplace_back("bdd reorder", durationReorder);
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,7 @@ namespace NewBdd {
|
||||||
bvar nObjs;
|
bvar nObjs;
|
||||||
bvar nObjsAlloc;
|
bvar nObjsAlloc;
|
||||||
bvar nObjsMax;
|
bvar nObjsMax;
|
||||||
|
unsigned long long nCreatedTotal;
|
||||||
bvar RemovedHead;
|
bvar RemovedHead;
|
||||||
int nGbc;
|
int nGbc;
|
||||||
bvar nReo;
|
bvar nReo;
|
||||||
|
|
@ -396,6 +397,7 @@ namespace NewBdd {
|
||||||
for(; *q; q = vNexts.begin() + *q)
|
for(; *q; q = vNexts.begin() + *q)
|
||||||
if(VarOfBvar(*q) == v && ThenOfBvar(*q) == x1 && ElseOfBvar(*q) == x0)
|
if(VarOfBvar(*q) == v && ThenOfBvar(*q) == x1 && ElseOfBvar(*q) == x0)
|
||||||
return Bvar2Lit(*q);
|
return Bvar2Lit(*q);
|
||||||
|
nCreatedTotal++;
|
||||||
bvar next = *p;
|
bvar next = *p;
|
||||||
if(nObjs < nObjsAlloc)
|
if(nObjs < nObjsAlloc)
|
||||||
*p = nObjs++;
|
*p = nObjs++;
|
||||||
|
|
@ -642,6 +644,7 @@ namespace NewBdd {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Man(int nVars_, Param p) {
|
Man(int nVars_, Param p) {
|
||||||
|
nCreatedTotal = 0;
|
||||||
nVerbose = p.nVerbose;
|
nVerbose = p.nVerbose;
|
||||||
// parameter sanity check
|
// parameter sanity check
|
||||||
if(p.nObjsMaxLog < p.nObjsAllocLog)
|
if(p.nObjsMaxLog < p.nObjsAllocLog)
|
||||||
|
|
@ -840,6 +843,9 @@ namespace NewBdd {
|
||||||
<< "alloc: " << std::setw(10) << nObjsAlloc
|
<< "alloc: " << std::setw(10) << nObjsAlloc
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
unsigned long long GetNumTotalCreatedNodes() {
|
||||||
|
return nCreatedTotal;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ namespace rrr {
|
||||||
int nVerbose;
|
int nVerbose;
|
||||||
|
|
||||||
// data
|
// data
|
||||||
|
bool fInitialized;
|
||||||
NewBdd::Man *pBdd;
|
NewBdd::Man *pBdd;
|
||||||
std::vector<lit> vFs;
|
std::vector<lit> vFs;
|
||||||
std::vector<lit> vGs;
|
std::vector<lit> vGs;
|
||||||
|
|
@ -35,6 +36,14 @@ namespace rrr {
|
||||||
// backups
|
// backups
|
||||||
std::vector<BddMspfAnalyzer> vBackups;
|
std::vector<BddMspfAnalyzer> vBackups;
|
||||||
|
|
||||||
|
// stats
|
||||||
|
uint64_t nNodesOld;
|
||||||
|
uint64_t nNodesAccumulated;
|
||||||
|
double durationSimulation;
|
||||||
|
double durationPf;
|
||||||
|
double durationCheck;
|
||||||
|
double durationReorder;
|
||||||
|
|
||||||
// BDD utils
|
// BDD utils
|
||||||
void IncRef(lit x) const;
|
void IncRef(lit x) const;
|
||||||
void DecRef(lit x) const;
|
void DecRef(lit x) const;
|
||||||
|
|
@ -63,6 +72,10 @@ namespace rrr {
|
||||||
void MspfNode(int id);
|
void MspfNode(int id);
|
||||||
void Mspf(int id = -1, bool fC = true);
|
void Mspf(int id = -1, bool fC = true);
|
||||||
|
|
||||||
|
// preparation
|
||||||
|
void Reset(bool fReuse = false);
|
||||||
|
void Initialize();
|
||||||
|
|
||||||
// save & load
|
// save & load
|
||||||
void Save(int slot);
|
void Save(int slot);
|
||||||
void Load(int slot);
|
void Load(int slot);
|
||||||
|
|
@ -73,11 +86,16 @@ namespace rrr {
|
||||||
BddMspfAnalyzer();
|
BddMspfAnalyzer();
|
||||||
BddMspfAnalyzer(Parameter const *pPar);
|
BddMspfAnalyzer(Parameter const *pPar);
|
||||||
~BddMspfAnalyzer();
|
~BddMspfAnalyzer();
|
||||||
void UpdateNetwork(Ntk *pNtk_, bool fSame);
|
void AssignNetwork(Ntk *pNtk_, bool fReuse);
|
||||||
|
|
||||||
// checks
|
// checks
|
||||||
bool CheckRedundancy(int id, int idx);
|
bool CheckRedundancy(int id, int idx);
|
||||||
bool CheckFeasibility(int id, int fi, bool c);
|
bool CheckFeasibility(int id, int fi, bool c);
|
||||||
|
|
||||||
|
// summary
|
||||||
|
void ResetSummary();
|
||||||
|
summary<int> GetStatsSummary() const;
|
||||||
|
summary<double> GetTimesSummary() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* {{{ BDD utils */
|
/* {{{ BDD utils */
|
||||||
|
|
@ -165,6 +183,7 @@ namespace rrr {
|
||||||
void BddMspfAnalyzer<Ntk>::ActionCallback(Action const &action) {
|
void BddMspfAnalyzer<Ntk>::ActionCallback(Action const &action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case REMOVE_FANIN:
|
case REMOVE_FANIN:
|
||||||
|
assert(fInitialized);
|
||||||
fUpdate = true;
|
fUpdate = true;
|
||||||
std::fill(vVisits.begin(), vVisits.end(), false);
|
std::fill(vVisits.begin(), vVisits.end(), false);
|
||||||
vUpdates[action.id] = true;
|
vUpdates[action.id] = true;
|
||||||
|
|
@ -174,103 +193,117 @@ namespace rrr {
|
||||||
vvCs[action.id].erase(vvCs[action.id].begin() + action.idx);
|
vvCs[action.id].erase(vvCs[action.id].begin() + action.idx);
|
||||||
break;
|
break;
|
||||||
case REMOVE_UNUSED:
|
case REMOVE_UNUSED:
|
||||||
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
if(fInitialized) {
|
||||||
|
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
||||||
|
for(int fi: action.vFanins) {
|
||||||
|
vGUpdates[fi] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assign(vGs[action.id], LitMax);
|
||||||
|
DelVec(vvCs[action.id]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REMOVE_BUFFER:
|
||||||
|
if(fInitialized) {
|
||||||
|
if(vUpdates[action.id]) {
|
||||||
|
fUpdate = true;
|
||||||
|
for(int fo: action.vFanouts) {
|
||||||
|
vUpdates[fo] = true;
|
||||||
|
vCUpdates[fo] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
||||||
|
vGUpdates[action.fi] = true;
|
||||||
|
}
|
||||||
|
Assign(vGs[action.id], LitMax);
|
||||||
|
DelVec(vvCs[action.id]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REMOVE_CONST:
|
||||||
|
if(fInitialized) {
|
||||||
|
if(vUpdates[action.id]) {
|
||||||
|
fUpdate = true;
|
||||||
|
for(int fo: action.vFanouts) {
|
||||||
|
vUpdates[fo] = true;
|
||||||
|
vCUpdates[fo] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
for(int fi: action.vFanins) {
|
for(int fi: action.vFanins) {
|
||||||
vGUpdates[fi] = true;
|
vGUpdates[fi] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Assign(vGs[action.id], LitMax);
|
|
||||||
DelVec(vvCs[action.id]);
|
|
||||||
break;
|
|
||||||
case REMOVE_BUFFER:
|
|
||||||
if(vUpdates[action.id]) {
|
|
||||||
fUpdate = true;
|
|
||||||
for(int fo: action.vFanouts) {
|
|
||||||
vUpdates[fo] = true;
|
|
||||||
vCUpdates[fo] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
|
||||||
vGUpdates[action.fi] = true;
|
|
||||||
}
|
|
||||||
Assign(vGs[action.id], LitMax);
|
|
||||||
DelVec(vvCs[action.id]);
|
|
||||||
break;
|
|
||||||
case REMOVE_CONST:
|
|
||||||
if(vUpdates[action.id]) {
|
|
||||||
fUpdate = true;
|
|
||||||
for(int fo: action.vFanouts) {
|
|
||||||
vUpdates[fo] = true;
|
|
||||||
vCUpdates[fo] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int fi: action.vFanins) {
|
|
||||||
vGUpdates[fi] = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ADD_FANIN:
|
case ADD_FANIN:
|
||||||
|
assert(fInitialized);
|
||||||
fUpdate = true;
|
fUpdate = true;
|
||||||
std::fill(vVisits.begin(), vVisits.end(), false);
|
std::fill(vVisits.begin(), vVisits.end(), false);
|
||||||
vUpdates[action.id] = true;
|
vUpdates[action.id] = true;
|
||||||
vCUpdates[action.id] = true;
|
vCUpdates[action.id] = true;
|
||||||
vvCs[action.id].insert(vvCs[action.id].begin() + action.idx, LitMax);
|
vvCs[action.id].insert(vvCs[action.id].begin() + action.idx, LitMax);
|
||||||
break;
|
break;
|
||||||
case TRIVIAL_COLLAPSE: {
|
case TRIVIAL_COLLAPSE:
|
||||||
if(vGUpdates[action.fi] || vCUpdates[action.fi]) {
|
if(fInitialized) {
|
||||||
vCUpdates[action.id] = true;
|
if(vGUpdates[action.fi] || vCUpdates[action.fi]) {
|
||||||
}
|
vCUpdates[action.id] = true;
|
||||||
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
|
||||||
DecRef(*it);
|
|
||||||
it = vvCs[action.id].erase(it);
|
|
||||||
vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end());
|
|
||||||
vvCs[action.fi].clear();
|
|
||||||
Assign(vFs[action.fi], LitMax);
|
|
||||||
Assign(vGs[action.fi], LitMax);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TRIVIAL_DECOMPOSE: {
|
|
||||||
Allocate();
|
|
||||||
SimulateNode(action.fi, vFs);
|
|
||||||
assert(vGs[action.fi] == LitMax);
|
|
||||||
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
|
||||||
assert(vvCs[action.fi].empty());
|
|
||||||
vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end());
|
|
||||||
vvCs[action.id].erase(it, vvCs[action.id].end());
|
|
||||||
assert(vvCs[action.id].size() == action.idx);
|
|
||||||
if(!vGUpdates[action.id] && !vCUpdates[action.id]) {
|
|
||||||
// recompute here only when updates are unlikely to happen
|
|
||||||
if(pBdd->IsConst1(vGs[action.id])) {
|
|
||||||
Assign(vGs[action.fi], pBdd->Const1());
|
|
||||||
} else {
|
|
||||||
lit x = pBdd->Const1();
|
|
||||||
IncRef(x);
|
|
||||||
for(int idx2 = 0; idx2 < action.idx; idx2++) {
|
|
||||||
int fi = pNtk->GetFanin(action.id, idx2);
|
|
||||||
bool c = pNtk->GetCompl(action.id, idx2);
|
|
||||||
Assign(x, pBdd->And(x, pBdd->LitNotCond(vFs[fi], c)));
|
|
||||||
}
|
|
||||||
Assign(vGs[action.fi], pBdd->Or(pBdd->LitNot(x), vGs[action.id]));
|
|
||||||
DecRef(x);
|
|
||||||
}
|
}
|
||||||
} else {
|
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
||||||
// otherwise mark the node for future update
|
DecRef(*it);
|
||||||
vCUpdates[action.id] = true;
|
it = vvCs[action.id].erase(it);
|
||||||
}
|
vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end());
|
||||||
vvCs[action.id].resize(action.idx + 1, LitMax);
|
vvCs[action.fi].clear();
|
||||||
Assign(vvCs[action.id][action.idx], vGs[action.fi]);
|
Assign(vFs[action.fi], LitMax);
|
||||||
vUpdates[action.fi] = false;
|
Assign(vGs[action.fi], LitMax);
|
||||||
vGUpdates[action.fi] = false;
|
|
||||||
vCUpdates[action.fi] = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SORT_FANINS: {
|
|
||||||
std::vector<lit> vCs = vvCs[action.id];
|
|
||||||
vvCs[action.id].clear();
|
|
||||||
for(int index: action.vIndices) {
|
|
||||||
vvCs[action.id].push_back(vCs[index]);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
case TRIVIAL_DECOMPOSE:
|
||||||
|
if(fInitialized) {
|
||||||
|
Allocate();
|
||||||
|
SimulateNode(action.fi, vFs);
|
||||||
|
// time of this simulation is not measured for simplicity sake
|
||||||
|
assert(vGs[action.fi] == LitMax);
|
||||||
|
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
||||||
|
assert(vvCs[action.fi].empty());
|
||||||
|
vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end());
|
||||||
|
vvCs[action.id].erase(it, vvCs[action.id].end());
|
||||||
|
assert(vvCs[action.id].size() == action.idx);
|
||||||
|
if(!vGUpdates[action.id] && !vCUpdates[action.id]) {
|
||||||
|
// recompute here only when updates are unlikely to happen
|
||||||
|
if(pBdd->IsConst1(vGs[action.id])) {
|
||||||
|
Assign(vGs[action.fi], pBdd->Const1());
|
||||||
|
} else {
|
||||||
|
lit x = pBdd->Const1();
|
||||||
|
IncRef(x);
|
||||||
|
for(int idx2 = 0; idx2 < action.idx; idx2++) {
|
||||||
|
int fi = pNtk->GetFanin(action.id, idx2);
|
||||||
|
bool c = pNtk->GetCompl(action.id, idx2);
|
||||||
|
Assign(x, pBdd->And(x, pBdd->LitNotCond(vFs[fi], c)));
|
||||||
|
}
|
||||||
|
Assign(vGs[action.fi], pBdd->Or(pBdd->LitNot(x), vGs[action.id]));
|
||||||
|
DecRef(x);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// otherwise mark the node for future update
|
||||||
|
vCUpdates[action.id] = true;
|
||||||
|
}
|
||||||
|
vvCs[action.id].resize(action.idx + 1, LitMax);
|
||||||
|
Assign(vvCs[action.id][action.idx], vGs[action.fi]);
|
||||||
|
vUpdates[action.fi] = false;
|
||||||
|
vGUpdates[action.fi] = false;
|
||||||
|
vCUpdates[action.fi] = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SORT_FANINS:
|
||||||
|
if(fInitialized) {
|
||||||
|
std::vector<lit> vCs = vvCs[action.id];
|
||||||
|
vvCs[action.id].clear();
|
||||||
|
for(int index: action.vIndices) {
|
||||||
|
vvCs[action.id].push_back(vCs[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case READ:
|
||||||
|
Reset(!action.fNew);
|
||||||
|
break;
|
||||||
case SAVE:
|
case SAVE:
|
||||||
Save(action.idx);
|
Save(action.idx);
|
||||||
break;
|
break;
|
||||||
|
|
@ -326,6 +359,7 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
void BddMspfAnalyzer<Ntk>::Simulate() {
|
void BddMspfAnalyzer<Ntk>::Simulate() {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "symbolic simulation with BDD" << std::endl;
|
std::cout << "symbolic simulation with BDD" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
@ -340,6 +374,7 @@ namespace rrr {
|
||||||
vUpdates[id] = false;
|
vUpdates[id] = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
durationSimulation += Duration(timeStart, GetCurrentTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -507,6 +542,7 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename pNtk>
|
template <typename pNtk>
|
||||||
void BddMspfAnalyzer<pNtk>::Mspf(int id, bool fC) {
|
void BddMspfAnalyzer<pNtk>::Mspf(int id, bool fC) {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
if(id != -1) {
|
if(id != -1) {
|
||||||
pNtk->ForEachTfoReverse(id, false, [&](int fo) {
|
pNtk->ForEachTfoReverse(id, false, [&](int fo) {
|
||||||
MspfNode(fo);
|
MspfNode(fo);
|
||||||
|
|
@ -524,6 +560,78 @@ namespace rrr {
|
||||||
MspfNode(id);
|
MspfNode(id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
durationPf += Duration(timeStart, GetCurrentTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ Preparation */
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
void BddMspfAnalyzer<Ntk>::Reset(bool fReuse) {
|
||||||
|
while(!vBackups.empty()) {
|
||||||
|
PopBack();
|
||||||
|
}
|
||||||
|
DelVec(vFs);
|
||||||
|
DelVec(vGs);
|
||||||
|
DelVecVec(vvCs);
|
||||||
|
fInitialized = false;
|
||||||
|
fUpdate = false;
|
||||||
|
vUpdates.clear();
|
||||||
|
vGUpdates.clear();
|
||||||
|
vCUpdates.clear();
|
||||||
|
vVisits.clear();
|
||||||
|
if(!fReuse) {
|
||||||
|
nNodesOld = 0;
|
||||||
|
if(pBdd) {
|
||||||
|
nNodesAccumulated += pBdd->GetNumTotalCreatedNodes();
|
||||||
|
}
|
||||||
|
delete pBdd;
|
||||||
|
pBdd = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
void BddMspfAnalyzer<Ntk>::Initialize() {
|
||||||
|
bool fUseReo = false;
|
||||||
|
if(!pBdd) {
|
||||||
|
NewBdd::Param Par;
|
||||||
|
Par.nObjsMaxLog = 25;
|
||||||
|
Par.nCacheMaxLog = 20;
|
||||||
|
Par.fCountOnes = false;
|
||||||
|
Par.nGbc = 1;
|
||||||
|
Par.nReo = 4000;
|
||||||
|
pBdd = new NewBdd::Man(pNtk->GetNumPis(), Par);
|
||||||
|
fUseReo = true;
|
||||||
|
}
|
||||||
|
assert(pBdd->GetNumVars() == pNtk->GetNumPis());
|
||||||
|
Allocate();
|
||||||
|
Assign(vFs[0], pBdd->Const0());
|
||||||
|
int idx = 0;
|
||||||
|
pNtk->ForEachPi([&](int id) {
|
||||||
|
Assign(vFs[id], pBdd->IthVar(idx));
|
||||||
|
idx++;
|
||||||
|
});
|
||||||
|
pNtk->ForEachInt([&](int id) {
|
||||||
|
vUpdates[id] = true;
|
||||||
|
});
|
||||||
|
Simulate();
|
||||||
|
if(fUseReo) {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
|
pBdd->Reorder();
|
||||||
|
pBdd->TurnOffReo();
|
||||||
|
durationReorder += Duration(timeStart, GetCurrentTime());
|
||||||
|
}
|
||||||
|
pNtk->ForEachInt([&](int id) {
|
||||||
|
vvCs[id].resize(pNtk->GetNumFanins(id), LitMax);
|
||||||
|
});
|
||||||
|
pNtk->ForEachPo([&](int id) {
|
||||||
|
vvCs[id].resize(1, LitMax);
|
||||||
|
Assign(vvCs[id][0], pBdd->Const0());
|
||||||
|
int fi = pNtk->GetFanin(id, 0);
|
||||||
|
vGUpdates[fi] = true;
|
||||||
|
});
|
||||||
|
fInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -575,90 +683,32 @@ namespace rrr {
|
||||||
BddMspfAnalyzer<Ntk>::BddMspfAnalyzer() :
|
BddMspfAnalyzer<Ntk>::BddMspfAnalyzer() :
|
||||||
pNtk(NULL),
|
pNtk(NULL),
|
||||||
nVerbose(0),
|
nVerbose(0),
|
||||||
pBdd(NULL) {
|
fInitialized(false),
|
||||||
|
pBdd(NULL),
|
||||||
|
fUpdate(false) {
|
||||||
|
ResetSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
BddMspfAnalyzer<Ntk>::BddMspfAnalyzer(Parameter const *pPar) :
|
BddMspfAnalyzer<Ntk>::BddMspfAnalyzer(Parameter const *pPar) :
|
||||||
pNtk(NULL),
|
pNtk(NULL),
|
||||||
nVerbose(pPar->nAnalyzerVerbose),
|
nVerbose(pPar->nAnalyzerVerbose),
|
||||||
|
fInitialized(false),
|
||||||
pBdd(NULL),
|
pBdd(NULL),
|
||||||
fUpdate(false) {
|
fUpdate(false) {
|
||||||
}
|
ResetSummary();
|
||||||
|
|
||||||
template <typename Ntk>
|
|
||||||
void BddMspfAnalyzer<Ntk>::UpdateNetwork(Ntk *pNtk_, bool fSame) {
|
|
||||||
// clear
|
|
||||||
while(!vBackups.empty()) {
|
|
||||||
PopBack();
|
|
||||||
}
|
|
||||||
DelVec(vFs);
|
|
||||||
DelVec(vGs);
|
|
||||||
DelVecVec(vvCs);
|
|
||||||
pNtk = pNtk_;
|
|
||||||
fUpdate = false;
|
|
||||||
vUpdates.clear();
|
|
||||||
vGUpdates.clear();
|
|
||||||
vCUpdates.clear();
|
|
||||||
vVisits.clear();
|
|
||||||
// alloc
|
|
||||||
bool fUseReo = false;
|
|
||||||
if(!pBdd || pBdd->GetNumVars() != pNtk->GetNumPis()) {
|
|
||||||
// need to reset manager
|
|
||||||
delete pBdd;
|
|
||||||
NewBdd::Param Par;
|
|
||||||
Par.nObjsMaxLog = 25;
|
|
||||||
Par.nCacheMaxLog = 20;
|
|
||||||
Par.fCountOnes = false;
|
|
||||||
Par.nGbc = 1;
|
|
||||||
Par.nReo = 4000;
|
|
||||||
pBdd = new NewBdd::Man(pNtk->GetNumPis(), Par);
|
|
||||||
fUseReo = true;
|
|
||||||
} else if(!fSame) {
|
|
||||||
// turning on reordering if network function changed
|
|
||||||
pBdd->TurnOnReo();
|
|
||||||
fUseReo = true;
|
|
||||||
}
|
|
||||||
Allocate();
|
|
||||||
// prepare
|
|
||||||
Assign(vFs[0], pBdd->Const0());
|
|
||||||
int idx = 0;
|
|
||||||
pNtk->ForEachPi([&](int id) {
|
|
||||||
Assign(vFs[id], pBdd->IthVar(idx));
|
|
||||||
idx++;
|
|
||||||
});
|
|
||||||
pNtk->ForEachInt([&](int id) {
|
|
||||||
vUpdates[id] = true;
|
|
||||||
});
|
|
||||||
Simulate();
|
|
||||||
if(fUseReo) {
|
|
||||||
pBdd->Reorder();
|
|
||||||
pBdd->TurnOffReo();
|
|
||||||
}
|
|
||||||
pNtk->ForEachInt([&](int id) {
|
|
||||||
vvCs[id].resize(pNtk->GetNumFanins(id), LitMax);
|
|
||||||
});
|
|
||||||
pNtk->ForEachPo([&](int id) {
|
|
||||||
vvCs[id].resize(1, LitMax);
|
|
||||||
Assign(vvCs[id][0], pBdd->Const0());
|
|
||||||
int fi = pNtk->GetFanin(id, 0);
|
|
||||||
vGUpdates[fi] = true;
|
|
||||||
});
|
|
||||||
pNtk->AddCallback(std::bind(&BddMspfAnalyzer<Ntk>::ActionCallback, this, std::placeholders::_1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
BddMspfAnalyzer<Ntk>::~BddMspfAnalyzer() {
|
BddMspfAnalyzer<Ntk>::~BddMspfAnalyzer() {
|
||||||
while(!vBackups.empty()) {
|
Reset();
|
||||||
PopBack();
|
}
|
||||||
}
|
|
||||||
DelVec(vFs);
|
template <typename Ntk>
|
||||||
DelVec(vGs);
|
void BddMspfAnalyzer<Ntk>::AssignNetwork(Ntk *pNtk_, bool fReuse) {
|
||||||
DelVecVec(vvCs);
|
Reset(fReuse);
|
||||||
if(pBdd) {
|
pNtk = pNtk_;
|
||||||
pBdd->PrintStats();
|
pNtk->AddCallback(std::bind(&BddMspfAnalyzer<Ntk>::ActionCallback, this, std::placeholders::_1));
|
||||||
}
|
|
||||||
delete pBdd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -667,21 +717,22 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
bool BddMspfAnalyzer<Ntk>::CheckRedundancy(int id, int idx) {
|
bool BddMspfAnalyzer<Ntk>::CheckRedundancy(int id, int idx) {
|
||||||
if(fUpdate) {
|
if(!fInitialized) {
|
||||||
|
Initialize();
|
||||||
|
} else if(fUpdate) {
|
||||||
Simulate();
|
Simulate();
|
||||||
fUpdate = false;
|
fUpdate = false;
|
||||||
}
|
}
|
||||||
Mspf(id);
|
Mspf(id);
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
|
bool fRedundant = false;
|
||||||
switch(pNtk->GetNodeType(id)) {
|
switch(pNtk->GetNodeType(id)) {
|
||||||
case AND: {
|
case AND: {
|
||||||
int fi = pNtk->GetFanin(id, idx);
|
int fi = pNtk->GetFanin(id, idx);
|
||||||
bool c = pNtk->GetCompl(id, idx);
|
bool c = pNtk->GetCompl(id, idx);
|
||||||
lit x = pBdd->Or(pBdd->LitNotCond(vFs[fi], c), vvCs[id][idx]);
|
lit x = pBdd->Or(pBdd->LitNotCond(vFs[fi], c), vvCs[id][idx]);
|
||||||
if(pBdd->IsConst1(x)) {
|
if(pBdd->IsConst1(x)) {
|
||||||
if(nVerbose) {
|
fRedundant = true;
|
||||||
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is redundant" << std::endl;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -689,18 +740,27 @@ namespace rrr {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is NOT redundant" << std::endl;
|
if(fRedundant) {
|
||||||
|
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is redundant" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is NOT redundant" << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
durationCheck += Duration(timeStart, GetCurrentTime());
|
||||||
|
return fRedundant;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
bool BddMspfAnalyzer<Ntk>::CheckFeasibility(int id, int fi, bool c) {
|
bool BddMspfAnalyzer<Ntk>::CheckFeasibility(int id, int fi, bool c) {
|
||||||
if(fUpdate) {
|
if(!fInitialized) {
|
||||||
|
Initialize();
|
||||||
|
} else if(fUpdate) {
|
||||||
Simulate();
|
Simulate();
|
||||||
fUpdate = false;
|
fUpdate = false;
|
||||||
}
|
}
|
||||||
Mspf(id, false);
|
Mspf(id, false);
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
|
bool fFeasible = false;
|
||||||
switch(pNtk->GetNodeType(id)) {
|
switch(pNtk->GetNodeType(id)) {
|
||||||
case AND: {
|
case AND: {
|
||||||
lit x = pBdd->Or(pBdd->LitNot(vFs[id]), vGs[id]);
|
lit x = pBdd->Or(pBdd->LitNot(vFs[id]), vGs[id]);
|
||||||
|
|
@ -708,9 +768,7 @@ namespace rrr {
|
||||||
lit y = pBdd->Or(x, pBdd->LitNotCond(vFs[fi], c));
|
lit y = pBdd->Or(x, pBdd->LitNotCond(vFs[fi], c));
|
||||||
DecRef(x);
|
DecRef(x);
|
||||||
if(pBdd->IsConst1(y)) {
|
if(pBdd->IsConst1(y)) {
|
||||||
if(nVerbose) {
|
fFeasible = true;
|
||||||
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is feasible" << std::endl;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -719,9 +777,49 @@ namespace rrr {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is NOT feasible" << std::endl;
|
if(fFeasible) {
|
||||||
|
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is feasible" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is NOT feasible" << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
durationCheck += Duration(timeStart, GetCurrentTime());
|
||||||
|
return fFeasible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ Summary */
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
void BddMspfAnalyzer<Ntk>::ResetSummary() {
|
||||||
|
if(pBdd) {
|
||||||
|
nNodesOld = pBdd->GetNumTotalCreatedNodes();
|
||||||
|
} else {
|
||||||
|
nNodesOld = 0;
|
||||||
|
}
|
||||||
|
nNodesAccumulated = 0;
|
||||||
|
durationSimulation = 0;
|
||||||
|
durationPf = 0;
|
||||||
|
durationCheck = 0;
|
||||||
|
durationReorder = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
summary<int> BddMspfAnalyzer<Ntk>::GetStatsSummary() const {
|
||||||
|
summary<int> v;
|
||||||
|
v.emplace_back("bdd node", pBdd->GetNumTotalCreatedNodes() - nNodesOld + nNodesAccumulated);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
summary<double> BddMspfAnalyzer<Ntk>::GetTimesSummary() const {
|
||||||
|
summary<double> v;
|
||||||
|
v.emplace_back("bdd symbolic simulation", durationSimulation);
|
||||||
|
v.emplace_back("bdd care computation", durationPf);
|
||||||
|
v.emplace_back("bdd check", durationCheck);
|
||||||
|
v.emplace_back("bdd reorder", durationReorder);
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ namespace rrr {
|
||||||
public:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
LevelBasePartitioner(Parameter const *pPar);
|
LevelBasePartitioner(Parameter const *pPar);
|
||||||
void UpdateNetwork(Ntk *pNtk);
|
void AssignNetwork(Ntk *pNtk);
|
||||||
|
|
||||||
// APIs
|
// APIs
|
||||||
Ntk *Extract(int iSeed);
|
Ntk *Extract(int iSeed);
|
||||||
|
|
@ -214,7 +214,7 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
void LevelBasePartitioner<Ntk>::UpdateNetwork(Ntk *pNtk_) {
|
void LevelBasePartitioner<Ntk>::AssignNetwork(Ntk *pNtk_) {
|
||||||
pNtk = pNtk_;
|
pNtk = pNtk_;
|
||||||
assert(mSubNtk2Io.empty());
|
assert(mSubNtk2Io.empty());
|
||||||
assert(sBlocked.empty());
|
assert(sBlocked.empty());
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ namespace rrr {
|
||||||
bool fCompatible;
|
bool fCompatible;
|
||||||
bool fGreedy;
|
bool fGreedy;
|
||||||
seconds nTimeout; // assigned upon Run
|
seconds nTimeout; // assigned upon Run
|
||||||
std::string strVerbosePrefix;
|
std::function<void(std::string)> PrintLine;
|
||||||
|
|
||||||
// data
|
// data
|
||||||
Ana ana;
|
Ana ana;
|
||||||
|
|
@ -52,6 +52,11 @@ namespace rrr {
|
||||||
int target;
|
int target;
|
||||||
std::vector<bool> vTfoMarks;
|
std::vector<bool> vTfoMarks;
|
||||||
|
|
||||||
|
// statistics
|
||||||
|
struct Stats;
|
||||||
|
std::map<std::string, Stats> stats;
|
||||||
|
Stats statsLocal;
|
||||||
|
|
||||||
// print
|
// print
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void Print(int nVerboseLevel, Args... args);
|
void Print(int nVerboseLevel, Args... args);
|
||||||
|
|
@ -76,17 +81,18 @@ namespace rrr {
|
||||||
bool ReduceFaninsOneRandom(int id, bool fRemoveUnused = false);
|
bool ReduceFaninsOneRandom(int id, bool fRemoveUnused = false);
|
||||||
|
|
||||||
// reduce
|
// reduce
|
||||||
bool Reduce();
|
bool Reduce(bool fSubRoutine = false);
|
||||||
void ReduceRandom();
|
void ReduceRandom();
|
||||||
|
|
||||||
// remove redundancy
|
// remove redundancy
|
||||||
void RemoveRedundancy();
|
bool RemoveRedundancy();
|
||||||
void RemoveRedundancyRandom();
|
void RemoveRedundancyRandom();
|
||||||
|
|
||||||
// addition
|
// addition
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T SingleAdd(int id, T begin, T end);
|
T SingleAdd(int id, T begin, T end);
|
||||||
int MultiAdd(int id, std::vector<int> const &vCands, int nMax = 0);
|
int MultiAdd(int id, std::vector<int> const &vCands, int nMax = 0);
|
||||||
|
void Undo();
|
||||||
|
|
||||||
// resub
|
// resub
|
||||||
void SingleResub(int id, std::vector<int> const &vCands);
|
void SingleResub(int id, std::vector<int> const &vCands);
|
||||||
|
|
@ -108,25 +114,81 @@ namespace rrr {
|
||||||
public:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
Optimizer(Parameter const *pPar, std::function<double(Ntk *)> CostFunction);
|
Optimizer(Parameter const *pPar, std::function<double(Ntk *)> CostFunction);
|
||||||
void UpdateNetwork(Ntk *pNtk_, bool fSame = false);
|
void AssignNetwork(Ntk *pNtk_, bool fReuse = false);
|
||||||
|
void SetPrintLine(std::function<void(std::string)> const &PrintLine_);
|
||||||
|
|
||||||
// run
|
// run
|
||||||
void Run(int iSeed = 0, seconds nTimeout_ = 0);
|
void Run(int iSeed = 0, seconds nTimeout_ = 0);
|
||||||
|
|
||||||
|
// summary
|
||||||
|
void ResetSummary();
|
||||||
|
summary<int> GetStatsSummary() const;
|
||||||
|
summary<double> GetTimesSummary() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* {{{ Stats */
|
||||||
|
|
||||||
|
template <typename Ntk, typename Ana>
|
||||||
|
struct Optimizer<Ntk, Ana>::Stats {
|
||||||
|
int nTriedFis = 0;
|
||||||
|
int nAddedFis = 0;
|
||||||
|
int nTried = 0;
|
||||||
|
int nAdded = 0;
|
||||||
|
int nChanged = 0;
|
||||||
|
int nUps = 0;
|
||||||
|
int nEqs = 0;
|
||||||
|
int nDowns = 0;
|
||||||
|
double durationAdd = 0;
|
||||||
|
double durationReduce = 0;
|
||||||
|
|
||||||
|
void Reset() {
|
||||||
|
nTriedFis = 0;
|
||||||
|
nAddedFis = 0;
|
||||||
|
nTried = 0;
|
||||||
|
nAdded = 0;
|
||||||
|
nChanged = 0;
|
||||||
|
nUps = 0;
|
||||||
|
nEqs = 0;
|
||||||
|
nDowns = 0;
|
||||||
|
durationAdd = 0;
|
||||||
|
durationReduce = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stats& operator+=(Stats const &other) {
|
||||||
|
this->nTriedFis += other.nTriedFis;
|
||||||
|
this->nAddedFis += other.nAddedFis;
|
||||||
|
this->nTried += other.nTried;
|
||||||
|
this->nAdded += other.nAdded;
|
||||||
|
this->nChanged += other.nChanged;
|
||||||
|
this->nUps += other.nUps;
|
||||||
|
this->nEqs += other.nEqs;
|
||||||
|
this->nDowns += other.nDowns;
|
||||||
|
this->durationAdd += other.durationAdd;
|
||||||
|
this->durationReduce += other.durationReduce;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetString() const {
|
||||||
|
std::stringstream ss;
|
||||||
|
PrintNext(ss, "tried node/fanin", "=", nTried, "/", nTriedFis, ",", "added node/fanin", "=", nAdded, "/", nAddedFis, ",", "changed", "=", nChanged, ",", "up/eq/dn", "=", nUps, "/", nEqs, "/", nDowns);
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ Print */
|
/* {{{ Print */
|
||||||
|
|
||||||
template <typename Ntk, typename Ana>
|
template <typename Ntk, typename Ana>
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline void Optimizer<Ntk, Ana>::Print(int nVerboseLevel, Args... args) {
|
inline void Optimizer<Ntk, Ana>::Print(int nVerboseLevel, Args... args) {
|
||||||
if(nVerbose > nVerboseLevel) {
|
if(nVerbose > nVerboseLevel) {
|
||||||
std::cout << strVerbosePrefix;
|
std::stringstream ss;
|
||||||
for(int i = 0; i < nVerboseLevel; i++) {
|
for(int i = 0; i < nVerboseLevel; i++) {
|
||||||
std::cout << "\t";
|
ss << "\t";
|
||||||
}
|
}
|
||||||
PrintNext(std::cout, args...);
|
PrintNext(ss, args...);
|
||||||
std::cout << std::endl;
|
PrintLine(ss.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,13 +198,13 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename Ntk, typename Ana>
|
template <typename Ntk, typename Ana>
|
||||||
void Optimizer<Ntk, Ana>::ActionCallback(Action const &action) {
|
void Optimizer<Ntk, Ana>::ActionCallback(Action const &action) {
|
||||||
if(nVerbose > 2) {
|
if(nVerbose > 4) {
|
||||||
std::stringstream ss = GetActionDescription(action);
|
std::stringstream ss = GetActionDescription(action);
|
||||||
std::string str;
|
std::string str;
|
||||||
std::getline(ss, str);
|
std::getline(ss, str);
|
||||||
Print(2, str);
|
Print(4, str);
|
||||||
while(std::getline(ss, str)) {
|
while(std::getline(ss, str)) {
|
||||||
Print(3, str);
|
Print(5, str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
|
|
@ -171,6 +233,9 @@ namespace rrr {
|
||||||
break;
|
break;
|
||||||
case SORT_FANINS:
|
case SORT_FANINS:
|
||||||
break;
|
break;
|
||||||
|
case READ:
|
||||||
|
target = -1;
|
||||||
|
break;
|
||||||
case SAVE:
|
case SAVE:
|
||||||
break;
|
break;
|
||||||
case LOAD:
|
case LOAD:
|
||||||
|
|
@ -482,7 +547,7 @@ namespace rrr {
|
||||||
template <typename Ntk, typename Ana>
|
template <typename Ntk, typename Ana>
|
||||||
inline bool Optimizer<Ntk, Ana>::ReduceFanins(int id, bool fRemoveUnused) {
|
inline bool Optimizer<Ntk, Ana>::ReduceFanins(int id, bool fRemoveUnused) {
|
||||||
assert(pNtk->GetNumFanouts(id) > 0);
|
assert(pNtk->GetNumFanouts(id) > 0);
|
||||||
bool fRemoved = false;
|
bool fReduced = false;
|
||||||
for(int idx = 0; idx < pNtk->GetNumFanins(id); idx++) {
|
for(int idx = 0; idx < pNtk->GetNumFanins(id); idx++) {
|
||||||
// skip fanins that were just added
|
// skip fanins that were just added
|
||||||
if(mapNewFanins.count(id)) {
|
if(mapNewFanins.count(id)) {
|
||||||
|
|
@ -495,14 +560,14 @@ namespace rrr {
|
||||||
if(ana.CheckRedundancy(id, idx)) {
|
if(ana.CheckRedundancy(id, idx)) {
|
||||||
int fi = pNtk->GetFanin(id, idx);
|
int fi = pNtk->GetFanin(id, idx);
|
||||||
pNtk->RemoveFanin(id, idx);
|
pNtk->RemoveFanin(id, idx);
|
||||||
fRemoved = true;
|
fReduced = true;
|
||||||
idx--;
|
idx--;
|
||||||
if(fRemoveUnused && pNtk->GetNumFanouts(fi) == 0) {
|
if(fRemoveUnused && pNtk->GetNumFanouts(fi) == 0) {
|
||||||
pNtk->RemoveUnused(fi, true);
|
pNtk->RemoveUnused(fi, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fRemoved;
|
return fReduced;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -542,7 +607,8 @@ namespace rrr {
|
||||||
/* {{{ Reduce */
|
/* {{{ Reduce */
|
||||||
|
|
||||||
template <typename Ntk, typename Ana>
|
template <typename Ntk, typename Ana>
|
||||||
bool Optimizer<Ntk, Ana>::Reduce() {
|
bool Optimizer<Ntk, Ana>::Reduce(bool fSubRoutine) {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
bool fReduced = false;
|
bool fReduced = false;
|
||||||
std::vector<int> vInts = pNtk->GetInts();
|
std::vector<int> vInts = pNtk->GetInts();
|
||||||
for(critr it = vInts.rbegin(); it != vInts.rend(); it++) {
|
for(critr it = vInts.rbegin(); it != vInts.rend(); it++) {
|
||||||
|
|
@ -558,6 +624,10 @@ namespace rrr {
|
||||||
pNtk->Propagate(*it);
|
pNtk->Propagate(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(!fSubRoutine) {
|
||||||
|
time_point timeEnd = GetCurrentTime();
|
||||||
|
statsLocal.durationReduce += Duration(timeStart, timeEnd);
|
||||||
|
}
|
||||||
return fReduced;
|
return fReduced;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -588,35 +658,42 @@ namespace rrr {
|
||||||
/* {{{ Redundancy removal */
|
/* {{{ Redundancy removal */
|
||||||
|
|
||||||
template <typename Ntk, typename Ana>
|
template <typename Ntk, typename Ana>
|
||||||
void Optimizer<Ntk, Ana>::RemoveRedundancy() {
|
bool Optimizer<Ntk, Ana>::RemoveRedundancy() {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
|
bool fReduced = false;
|
||||||
if(fCompatible) {
|
if(fCompatible) {
|
||||||
while(Reduce()) {
|
while(Reduce(true)) {
|
||||||
|
fReduced = true;
|
||||||
SortFanins();
|
SortFanins();
|
||||||
}
|
}
|
||||||
return;
|
} else {
|
||||||
}
|
std::vector<int> vInts = pNtk->GetInts();
|
||||||
std::vector<int> vInts = pNtk->GetInts();
|
for(critr it = vInts.rbegin(); it != vInts.rend();) {
|
||||||
for(critr it = vInts.rbegin(); it != vInts.rend();) {
|
if(!pNtk->IsInt(*it)) {
|
||||||
if(!pNtk->IsInt(*it)) {
|
it++;
|
||||||
it++;
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
if(pNtk->GetNumFanouts(*it) == 0) {
|
||||||
if(pNtk->GetNumFanouts(*it) == 0) {
|
pNtk->RemoveUnused(*it);
|
||||||
pNtk->RemoveUnused(*it);
|
it++;
|
||||||
it++;
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
SortFanins(*it);
|
||||||
SortFanins(*it);
|
bool fReduced_ = ReduceFanins(*it);
|
||||||
bool fReduced = ReduceFanins(*it);
|
fReduced |= fReduced_;
|
||||||
if(pNtk->GetNumFanins(*it) <= 1) {
|
if(pNtk->GetNumFanins(*it) <= 1) {
|
||||||
pNtk->Propagate(*it);
|
pNtk->Propagate(*it);
|
||||||
}
|
}
|
||||||
if(fReduced) {
|
if(fReduced_) {
|
||||||
it = vInts.rbegin();
|
it = vInts.rbegin();
|
||||||
} else {
|
} else {
|
||||||
it++;
|
it++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
time_point timeEnd = GetCurrentTime();
|
||||||
|
statsLocal.durationReduce += Duration(timeStart, timeEnd);
|
||||||
|
return fReduced;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -656,6 +733,7 @@ namespace rrr {
|
||||||
template <typename Ntk, typename Ana>
|
template <typename Ntk, typename Ana>
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T Optimizer<Ntk, Ana>::SingleAdd(int id, T begin, T end) {
|
T Optimizer<Ntk, Ana>::SingleAdd(int id, T begin, T end) {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
MarkTfo(id);
|
MarkTfo(id);
|
||||||
pNtk->ForEachFanin(id, [&](int fi) {
|
pNtk->ForEachFanin(id, [&](int fi) {
|
||||||
vTfoMarks[fi] = true;
|
vTfoMarks[fi] = true;
|
||||||
|
|
@ -668,10 +746,13 @@ namespace rrr {
|
||||||
if(vTfoMarks[*it]) {
|
if(vTfoMarks[*it]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
statsLocal.nTriedFis++;
|
||||||
if(ana.CheckFeasibility(id, *it, false)) {
|
if(ana.CheckFeasibility(id, *it, false)) {
|
||||||
pNtk->AddFanin(id, *it, false);
|
pNtk->AddFanin(id, *it, false);
|
||||||
|
statsLocal.nAddedFis++;
|
||||||
} else if(pNtk->UseComplementedEdges() && ana.CheckFeasibility(id, *it, true)) {
|
} else if(pNtk->UseComplementedEdges() && ana.CheckFeasibility(id, *it, true)) {
|
||||||
pNtk->AddFanin(id, *it, true);
|
pNtk->AddFanin(id, *it, true);
|
||||||
|
statsLocal.nAddedFis++;
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -681,16 +762,19 @@ namespace rrr {
|
||||||
pNtk->ForEachFanin(id, [&](int fi) {
|
pNtk->ForEachFanin(id, [&](int fi) {
|
||||||
vTfoMarks[fi] = false;
|
vTfoMarks[fi] = false;
|
||||||
});
|
});
|
||||||
|
time_point timeEnd = GetCurrentTime();
|
||||||
|
statsLocal.durationAdd += Duration(timeStart, timeEnd);
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk, typename Ana>
|
template <typename Ntk, typename Ana>
|
||||||
int Optimizer<Ntk, Ana>::MultiAdd(int id, std::vector<int> const &vCands, int nMax) {
|
int Optimizer<Ntk, Ana>::MultiAdd(int id, std::vector<int> const &vCands, int nMax) {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
MarkTfo(id);
|
MarkTfo(id);
|
||||||
pNtk->ForEachFanin(id, [&](int fi) {
|
pNtk->ForEachFanin(id, [&](int fi) {
|
||||||
vTfoMarks[fi] = true;
|
vTfoMarks[fi] = true;
|
||||||
});
|
});
|
||||||
int nAdded = 0;
|
int nAddedFis_ = 0;
|
||||||
for(int cand: vCands) {
|
for(int cand: vCands) {
|
||||||
if(!pNtk->IsInt(cand) && !pNtk->IsPi(cand)) {
|
if(!pNtk->IsInt(cand) && !pNtk->IsPi(cand)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -698,23 +782,39 @@ namespace rrr {
|
||||||
if(vTfoMarks[cand]) {
|
if(vTfoMarks[cand]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
statsLocal.nTriedFis++;
|
||||||
if(ana.CheckFeasibility(id, cand, false)) {
|
if(ana.CheckFeasibility(id, cand, false)) {
|
||||||
pNtk->AddFanin(id, cand, false);
|
pNtk->AddFanin(id, cand, false);
|
||||||
|
statsLocal.nAddedFis++;
|
||||||
} else if(pNtk->UseComplementedEdges() && ana.CheckFeasibility(id, cand, true)) {
|
} else if(pNtk->UseComplementedEdges() && ana.CheckFeasibility(id, cand, true)) {
|
||||||
pNtk->AddFanin(id, cand, true);
|
pNtk->AddFanin(id, cand, true);
|
||||||
|
statsLocal.nAddedFis++;
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
mapNewFanins[id].insert(cand);
|
mapNewFanins[id].insert(cand);
|
||||||
nAdded++;
|
nAddedFis_++;
|
||||||
if(nAdded == nMax) {
|
if(nAddedFis_ == nMax) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pNtk->ForEachFanin(id, [&](int fi) {
|
pNtk->ForEachFanin(id, [&](int fi) {
|
||||||
vTfoMarks[fi] = false;
|
vTfoMarks[fi] = false;
|
||||||
});
|
});
|
||||||
return nAdded;
|
time_point timeEnd = GetCurrentTime();
|
||||||
|
statsLocal.durationAdd += Duration(timeStart, timeEnd);
|
||||||
|
return nAddedFis_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk, typename Ana>
|
||||||
|
void Optimizer<Ntk, Ana>::Undo() {
|
||||||
|
for(auto const &entry: mapNewFanins) {
|
||||||
|
int id = entry.first;
|
||||||
|
for(int fi: entry.second) {
|
||||||
|
int idx = pNtk->FindFanin(id, fi);
|
||||||
|
pNtk->RemoveFanin(id, idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -731,11 +831,12 @@ namespace rrr {
|
||||||
pNtk->TrivialCollapse(id);
|
pNtk->TrivialCollapse(id);
|
||||||
// save if wanted
|
// save if wanted
|
||||||
int slot = -2;
|
int slot = -2;
|
||||||
if(fGreedy) {
|
if(fGreedy || fCompatible) {
|
||||||
slot = pNtk->Save();
|
slot = pNtk->Save();
|
||||||
}
|
}
|
||||||
double dCost = CostFunction(pNtk);
|
|
||||||
// main loop
|
// main loop
|
||||||
|
double cost = CostFunction(pNtk);
|
||||||
|
bool fTried = false, fAdded = false;
|
||||||
for(citr it = vCands.begin(); it != vCands.end(); it++) {
|
for(citr it = vCands.begin(); it != vCands.end(); it++) {
|
||||||
if(Timeout()) {
|
if(Timeout()) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -743,25 +844,44 @@ namespace rrr {
|
||||||
if(!pNtk->IsInt(id)) {
|
if(!pNtk->IsInt(id)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
fTried = true;
|
||||||
it = SingleAdd<citr>(id, it, vCands.end());
|
it = SingleAdd<citr>(id, it, vCands.end());
|
||||||
if(it == vCands.end()) {
|
if(it == vCands.end()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Print(1, "cand", *it, "(", int_distance(vCands.begin(), it) + 1, "/", int_size(vCands), "):", "cost", "=", dCost);
|
fAdded = true;
|
||||||
RemoveRedundancy();
|
Print(2, "cand", *it, "(", int_distance(vCands.begin(), it) + 1, "/", int_size(vCands), ")", ":", "cost", "=", cost);
|
||||||
mapNewFanins.clear();
|
if(RemoveRedundancy()) {
|
||||||
double dNewCost = CostFunction(pNtk);
|
double costNew = CostFunction(pNtk);
|
||||||
Print(2, "cost:", dCost, "->", dNewCost);
|
// stats
|
||||||
if(fGreedy) {
|
statsLocal.nChanged++;
|
||||||
if(dNewCost <= dCost) {
|
if(costNew < cost) {
|
||||||
pNtk->Save(slot);
|
statsLocal.nDowns++;
|
||||||
dCost = dNewCost;
|
} else if (costNew == cost) {
|
||||||
|
statsLocal.nEqs++;
|
||||||
} else {
|
} else {
|
||||||
pNtk->Load(slot);
|
statsLocal.nUps++;
|
||||||
|
}
|
||||||
|
// greedy
|
||||||
|
if(fGreedy) {
|
||||||
|
if(costNew <= cost) {
|
||||||
|
pNtk->Save(slot);
|
||||||
|
cost = costNew;
|
||||||
|
} else {
|
||||||
|
pNtk->Load(slot);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cost = costNew;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dCost = dNewCost;
|
// assuming addition only always increases cost
|
||||||
|
if(fCompatible) {
|
||||||
|
pNtk->Load(slot);
|
||||||
|
} else {
|
||||||
|
Undo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
mapNewFanins.clear();
|
||||||
}
|
}
|
||||||
if(pNtk->IsInt(id)) {
|
if(pNtk->IsInt(id)) {
|
||||||
pNtk->TrivialDecompose(id);
|
pNtk->TrivialDecompose(id);
|
||||||
|
|
@ -770,9 +890,15 @@ namespace rrr {
|
||||||
RemoveRedundancy();
|
RemoveRedundancy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(fGreedy) {
|
if(fGreedy || fCompatible) {
|
||||||
pNtk->PopBack();
|
pNtk->PopBack();
|
||||||
}
|
}
|
||||||
|
if(fTried) {
|
||||||
|
statsLocal.nTried++;
|
||||||
|
}
|
||||||
|
if(fAdded) {
|
||||||
|
statsLocal.nAdded++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk, typename Ana>
|
template <typename Ntk, typename Ana>
|
||||||
|
|
@ -781,24 +907,43 @@ namespace rrr {
|
||||||
// let us assume the node is not trivially redundant for now
|
// let us assume the node is not trivially redundant for now
|
||||||
assert(pNtk->GetNumFanouts(id) != 0);
|
assert(pNtk->GetNumFanouts(id) != 0);
|
||||||
assert(pNtk->GetNumFanins(id) > 1);
|
assert(pNtk->GetNumFanins(id) > 1);
|
||||||
|
statsLocal.nTried++;
|
||||||
// save if wanted
|
// save if wanted
|
||||||
int slot = -2;
|
int slot = -2;
|
||||||
if(fGreedy) {
|
if(fGreedy || fCompatible) {
|
||||||
slot = pNtk->Save();
|
slot = pNtk->Save();
|
||||||
}
|
}
|
||||||
double dCost = CostFunction(pNtk);
|
|
||||||
// collapse
|
// collapse
|
||||||
pNtk->TrivialCollapse(id);
|
pNtk->TrivialCollapse(id);
|
||||||
// resub
|
// resub
|
||||||
MultiAdd(id, vCands, nMax);
|
double cost = CostFunction(pNtk);
|
||||||
RemoveRedundancy();
|
if(MultiAdd(id, vCands, nMax)) {
|
||||||
mapNewFanins.clear();
|
statsLocal.nAdded++;
|
||||||
// TODO: we could quit here if nothing has been removed
|
if(RemoveRedundancy()) {
|
||||||
RemoveRedundancy();
|
mapNewFanins.clear();
|
||||||
double dNewCost = CostFunction(pNtk);
|
RemoveRedundancy();
|
||||||
Print(1, "cost:", dCost, "->", dNewCost);
|
double costNew = CostFunction(pNtk);
|
||||||
if(fGreedy && dNewCost > dCost) {
|
// stats
|
||||||
pNtk->Load(slot);
|
statsLocal.nChanged++;
|
||||||
|
if(costNew < cost) {
|
||||||
|
statsLocal.nDowns++;
|
||||||
|
} else if (costNew == cost) {
|
||||||
|
statsLocal.nEqs++;
|
||||||
|
} else {
|
||||||
|
statsLocal.nUps++;
|
||||||
|
}
|
||||||
|
// greedy
|
||||||
|
if(fGreedy && costNew > cost) {
|
||||||
|
pNtk->Load(slot);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(fCompatible) {
|
||||||
|
pNtk->Load(slot);
|
||||||
|
} else {
|
||||||
|
Undo();
|
||||||
|
}
|
||||||
|
mapNewFanins.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(pNtk->IsInt(id)) {
|
if(pNtk->IsInt(id)) {
|
||||||
pNtk->TrivialDecompose(id);
|
pNtk->TrivialDecompose(id);
|
||||||
|
|
@ -807,7 +952,7 @@ namespace rrr {
|
||||||
RemoveRedundancy();
|
RemoveRedundancy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(fGreedy) {
|
if(fGreedy || fCompatible) {
|
||||||
pNtk->PopBack();
|
pNtk->PopBack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -824,57 +969,77 @@ namespace rrr {
|
||||||
// let us assume the node is not trivially redundant for now
|
// let us assume the node is not trivially redundant for now
|
||||||
assert(pNtk->GetNumFanouts(id) != 0);
|
assert(pNtk->GetNumFanouts(id) != 0);
|
||||||
assert(pNtk->GetNumFanins(id) > 1);
|
assert(pNtk->GetNumFanins(id) > 1);
|
||||||
// save before trivial collapse
|
Print(2, "method", "=", "single");
|
||||||
int slot0 = pNtk->Save();
|
|
||||||
// collapse
|
// collapse
|
||||||
pNtk->TrivialCollapse(id);
|
pNtk->TrivialCollapse(id);
|
||||||
// save after trivial collapse
|
// save
|
||||||
int slot = pNtk->Save();
|
int slot = pNtk->Save();
|
||||||
double dCost = CostFunction(pNtk);
|
|
||||||
// remember fanins
|
// remember fanins
|
||||||
std::set<int> sFanins = pNtk->GetExtendedFanins(id);
|
std::set<int> sFanins = pNtk->GetExtendedFanins(id);
|
||||||
Print(2, "extended fanins:", sFanins);
|
Print(3, "extended fanins", ":", sFanins);
|
||||||
// main loop
|
// main loop
|
||||||
|
bool fChanged = false;
|
||||||
|
double cost = CostFunction(pNtk);
|
||||||
|
bool fTried = false, fAdded = false;
|
||||||
for(citr it = vCands.begin(); it != vCands.end(); it++) {
|
for(citr it = vCands.begin(); it != vCands.end(); it++) {
|
||||||
if(Timeout()) {
|
if(Timeout()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
assert(pNtk->IsInt(id));
|
assert(pNtk->IsInt(id));
|
||||||
|
fTried = true;
|
||||||
it = SingleAdd<citr>(id, it, vCands.end());
|
it = SingleAdd<citr>(id, it, vCands.end());
|
||||||
if(it == vCands.end()) {
|
if(it == vCands.end()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Print(1, "cand", *it, "(", int_distance(vCands.begin(), it) + 1, "/", int_size(vCands), "):", "cost", "=", dCost);
|
fAdded = true;
|
||||||
RemoveRedundancy();
|
Print(3, "cand", *it, "(", int_distance(vCands.begin(), it) + 1, "/", int_size(vCands), ")", ":", "cost", "=", cost);
|
||||||
mapNewFanins.clear();
|
if(RemoveRedundancy()) {
|
||||||
double dNewCost = CostFunction(pNtk);
|
mapNewFanins.clear();
|
||||||
Print(2, "cost:", dCost, "->", dNewCost);
|
double costNew = CostFunction(pNtk);
|
||||||
if(dNewCost <= dCost) {
|
if(costNew <= cost) {
|
||||||
bool fChanged = false;
|
fChanged = false;
|
||||||
if(dNewCost < dCost || !pNtk->IsInt(id)) {
|
if(costNew < cost || !pNtk->IsInt(id)) {
|
||||||
fChanged = true;
|
|
||||||
} else {
|
|
||||||
std::set<int> sNewFanins = pNtk->GetExtendedFanins(id);
|
|
||||||
Print(2, "new extended fanins:", sNewFanins);
|
|
||||||
if(sFanins != sNewFanins) {
|
|
||||||
fChanged = true;
|
fChanged = true;
|
||||||
|
} else {
|
||||||
|
std::set<int> sNewFanins = pNtk->GetExtendedFanins(id);
|
||||||
|
Print(3, "new extended fanins", ":", sNewFanins);
|
||||||
|
if(sFanins != sNewFanins) {
|
||||||
|
fChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(fChanged) {
|
||||||
|
statsLocal.nChanged++;
|
||||||
|
if(costNew < cost) {
|
||||||
|
statsLocal.nDowns++;
|
||||||
|
} else if (costNew == cost) {
|
||||||
|
statsLocal.nEqs++;
|
||||||
|
} else {
|
||||||
|
statsLocal.nUps++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(fChanged) {
|
pNtk->Load(slot);
|
||||||
if(pNtk->IsInt(id)) {
|
} else {
|
||||||
pNtk->TrivialDecompose(id);
|
if(fCompatible) {
|
||||||
}
|
pNtk->Load(slot);
|
||||||
pNtk->PopBack(); // slot
|
} else {
|
||||||
pNtk->PopBack(); // slot0
|
Undo();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
mapNewFanins.clear();
|
||||||
}
|
}
|
||||||
pNtk->Load(slot);
|
|
||||||
}
|
}
|
||||||
pNtk->PopBack(); // slot
|
if(pNtk->IsInt(id)) {
|
||||||
pNtk->Load(slot0);
|
pNtk->TrivialDecompose(id);
|
||||||
pNtk->PopBack(); // slot0
|
}
|
||||||
return false;
|
pNtk->PopBack();
|
||||||
|
if(fTried) {
|
||||||
|
statsLocal.nTried++;
|
||||||
|
}
|
||||||
|
if(fAdded) {
|
||||||
|
statsLocal.nAdded++;
|
||||||
|
}
|
||||||
|
return fChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk, typename Ana>
|
template <typename Ntk, typename Ana>
|
||||||
|
|
@ -885,44 +1050,59 @@ namespace rrr {
|
||||||
// let us assume the node is not trivially redundant for now
|
// let us assume the node is not trivially redundant for now
|
||||||
assert(pNtk->GetNumFanouts(id) != 0);
|
assert(pNtk->GetNumFanouts(id) != 0);
|
||||||
assert(pNtk->GetNumFanins(id) > 1);
|
assert(pNtk->GetNumFanins(id) > 1);
|
||||||
|
Print(2, "method", "=", "multi");
|
||||||
|
statsLocal.nTried++;
|
||||||
// save
|
// save
|
||||||
int slot = pNtk->Save();
|
int slot = pNtk->Save();
|
||||||
double dCost = CostFunction(pNtk);
|
|
||||||
// remember fanins
|
// remember fanins
|
||||||
std::set<int> sFanins = pNtk->GetExtendedFanins(id);
|
std::set<int> sFanins = pNtk->GetExtendedFanins(id);
|
||||||
Print(2, "extended fanins:", sFanins);
|
Print(3, "extended fanins", ":", sFanins);
|
||||||
// collapse
|
// collapse
|
||||||
pNtk->TrivialCollapse(id);
|
pNtk->TrivialCollapse(id);
|
||||||
// resub
|
// resub
|
||||||
MultiAdd(id, vCands, nMax);
|
bool fChanged = false;
|
||||||
RemoveRedundancy();
|
double cost = CostFunction(pNtk);
|
||||||
mapNewFanins.clear();
|
if(MultiAdd(id, vCands, nMax)) {
|
||||||
// TODO: we could quit here if nothing has been removed
|
statsLocal.nAdded++;
|
||||||
RemoveRedundancy();
|
if(RemoveRedundancy()) {
|
||||||
double dNewCost = CostFunction(pNtk);
|
mapNewFanins.clear();
|
||||||
Print(1, "cost:", dCost, "->", dNewCost);
|
RemoveRedundancy();
|
||||||
if(!fGreedy || dNewCost <= dCost) {
|
double costNew = CostFunction(pNtk);
|
||||||
bool fChanged = false;
|
if(!fGreedy || costNew <= cost) {
|
||||||
if(dNewCost < dCost || !pNtk->IsInt(id)) {
|
fChanged = false;
|
||||||
fChanged = true;
|
if(costNew < cost || !pNtk->IsInt(id)) {
|
||||||
|
fChanged = true;
|
||||||
|
} else {
|
||||||
|
std::set<int> sNewFanins = pNtk->GetExtendedFanins(id);
|
||||||
|
Print(3, "new extended fanins", ":", sNewFanins);
|
||||||
|
if(sFanins != sNewFanins) {
|
||||||
|
fChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(fChanged) {
|
||||||
|
statsLocal.nChanged++;
|
||||||
|
if(costNew < cost) {
|
||||||
|
statsLocal.nDowns++;
|
||||||
|
} else if (costNew == cost) {
|
||||||
|
statsLocal.nEqs++;
|
||||||
|
} else {
|
||||||
|
statsLocal.nUps++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
std::set<int> sNewFanins = pNtk->GetExtendedFanins(id);
|
mapNewFanins.clear();
|
||||||
Print(2, "new extended fanins:", sNewFanins);
|
|
||||||
if(sFanins != sNewFanins) {
|
|
||||||
fChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(fChanged) {
|
|
||||||
if(pNtk->IsInt(id)) {
|
|
||||||
pNtk->TrivialDecompose(id);
|
|
||||||
}
|
|
||||||
pNtk->PopBack();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pNtk->Load(slot);
|
if(fChanged) {
|
||||||
|
if(pNtk->IsInt(id)) {
|
||||||
|
pNtk->TrivialDecompose(id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pNtk->Load(slot);
|
||||||
|
}
|
||||||
pNtk->PopBack();
|
pNtk->PopBack();
|
||||||
return false;
|
return fChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -948,7 +1128,7 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// add while remembering extended fanins
|
// add while remembering extended fanins
|
||||||
Print(1, "targets:", vTargets);
|
Print(2, "targets", ":", vTargets);
|
||||||
std::vector<std::set<int>> vsFanins;
|
std::vector<std::set<int>> vsFanins;
|
||||||
for(int id: vTargets) {
|
for(int id: vTargets) {
|
||||||
// get candidates
|
// get candidates
|
||||||
|
|
@ -961,7 +1141,7 @@ namespace rrr {
|
||||||
std::shuffle(vCands.begin(), vCands.end(), rng);
|
std::shuffle(vCands.begin(), vCands.end(), rng);
|
||||||
// remember fanins
|
// remember fanins
|
||||||
std::set<int> sFanins = pNtk->GetExtendedFanins(id);
|
std::set<int> sFanins = pNtk->GetExtendedFanins(id);
|
||||||
Print(2, "extended fanins:", sFanins);
|
Print(3, "extended fanins", ":", sFanins);
|
||||||
vsFanins.push_back(std::move(sFanins));
|
vsFanins.push_back(std::move(sFanins));
|
||||||
// add
|
// add
|
||||||
MultiAdd(id, vCands, nMax);
|
MultiAdd(id, vCands, nMax);
|
||||||
|
|
@ -972,7 +1152,7 @@ namespace rrr {
|
||||||
// TODO: we could quit here if nothing has been removed
|
// TODO: we could quit here if nothing has been removed
|
||||||
RemoveRedundancy();
|
RemoveRedundancy();
|
||||||
double dNewCost = CostFunction(pNtk);
|
double dNewCost = CostFunction(pNtk);
|
||||||
Print(1, "cost:", dCost, "->", dNewCost);
|
Print(2, "cost =", dCost, "->", dNewCost);
|
||||||
if(!fGreedy || dNewCost <= dCost) {
|
if(!fGreedy || dNewCost <= dCost) {
|
||||||
bool fChanged = false;
|
bool fChanged = false;
|
||||||
if(dNewCost < dCost) {
|
if(dNewCost < dCost) {
|
||||||
|
|
@ -986,7 +1166,7 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
for(int i = 0; !fChanged && i < int_size(vTargets); i++) {
|
for(int i = 0; !fChanged && i < int_size(vTargets); i++) {
|
||||||
std::set<int> sNewFanins = pNtk->GetExtendedFanins(vTargets[i]);
|
std::set<int> sNewFanins = pNtk->GetExtendedFanins(vTargets[i]);
|
||||||
Print(2, "new extended fanins:", sNewFanins);
|
Print(3, "new extended fanins", ":", sNewFanins);
|
||||||
if(vsFanins[i] != sNewFanins) {
|
if(vsFanins[i] != sNewFanins) {
|
||||||
fChanged = true;
|
fChanged = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1021,7 +1201,7 @@ namespace rrr {
|
||||||
if(!pNtk->IsInt(*it)) {
|
if(!pNtk->IsInt(*it)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Print(0, "node", *it, "(", int_distance(vInts.crbegin(), it) + 1, "/", int_size(vInts), "):", "cost", "=", CostFunction(pNtk));
|
Print(1, "node", *it, "(", int_distance(vInts.crbegin(), it) + 1, "/", int_size(vInts), ")", ":", "cost", "=", CostFunction(pNtk));
|
||||||
func(*it);
|
func(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1037,7 +1217,7 @@ namespace rrr {
|
||||||
if(!pNtk->IsInt(*it)) {
|
if(!pNtk->IsInt(*it)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Print(0, "node", *it, "(", int_distance(vInts.cbegin(), it) + 1, "/", int_size(vInts), "):", "cost", "=", CostFunction(pNtk));
|
Print(1, "node", *it, "(", int_distance(vInts.cbegin(), it) + 1, "/", int_size(vInts), ")", ":", "cost", "=", CostFunction(pNtk));
|
||||||
if(func(*it)) {
|
if(func(*it)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1048,10 +1228,10 @@ namespace rrr {
|
||||||
void Optimizer<Ntk, Ana>::ApplyCombinationRandomlyStop(int k, std::function<bool(std::vector<int> const &)> const &func) {
|
void Optimizer<Ntk, Ana>::ApplyCombinationRandomlyStop(int k, std::function<bool(std::vector<int> const &)> const &func) {
|
||||||
std::vector<int> vInts = pNtk->GetInts();
|
std::vector<int> vInts = pNtk->GetInts();
|
||||||
std::shuffle(vInts.begin(), vInts.end(), rng); // order is decided here, so it's not truely exhaustive
|
std::shuffle(vInts.begin(), vInts.end(), rng); // order is decided here, so it's not truely exhaustive
|
||||||
int nTried = 0;
|
int nTried_ = 0;
|
||||||
int nCombs = k * (k - 1) / 2;
|
int nCombs = k * (k - 1) / 2;
|
||||||
ForEachCombinationStop(int_size(vInts), k, [&](std::vector<int> const &vIdxs) {
|
ForEachCombinationStop(int_size(vInts), k, [&](std::vector<int> const &vIdxs) {
|
||||||
Print(0, "comb", vIdxs, "(", ++nTried, "/", nCombs, ")");
|
Print(1, "comb", vIdxs, "(", ++nTried_, "/", nCombs, ")");
|
||||||
assert(int_size(vIdxs) == k);
|
assert(int_size(vIdxs) == k);
|
||||||
if(Timeout()) {
|
if(Timeout()) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1078,7 +1258,7 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
std::vector<int> vIdxs(sIdxs.begin(), sIdxs.end());
|
std::vector<int> vIdxs(sIdxs.begin(), sIdxs.end());
|
||||||
std::shuffle(vIdxs.begin(), vIdxs.end(), rng);
|
std::shuffle(vIdxs.begin(), vIdxs.end(), rng);
|
||||||
Print(0, "comb", vIdxs, "(", i + 1, "/", nSamples, ")");
|
Print(1, "comb", vIdxs, "(", i + 1, "/", nSamples, ")");
|
||||||
std::vector<int> vTargets(k);
|
std::vector<int> vTargets(k);
|
||||||
for(int i = 0; i < k; i++) {
|
for(int i = 0; i < k; i++) {
|
||||||
vTargets[i] = vInts[vIdxs[i]];
|
vTargets[i] = vInts[vIdxs[i]];
|
||||||
|
|
@ -1109,11 +1289,16 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk, typename Ana>
|
template <typename Ntk, typename Ana>
|
||||||
void Optimizer<Ntk, Ana>::UpdateNetwork(Ntk *pNtk_, bool fSame) {
|
void Optimizer<Ntk, Ana>::AssignNetwork(Ntk *pNtk_, bool fReuse) {
|
||||||
pNtk = pNtk_;
|
pNtk = pNtk_;
|
||||||
target = -1;
|
target = -1;
|
||||||
pNtk->AddCallback(std::bind(&Optimizer<Ntk, Ana>::ActionCallback, this, std::placeholders::_1));
|
pNtk->AddCallback(std::bind(&Optimizer<Ntk, Ana>::ActionCallback, this, std::placeholders::_1));
|
||||||
ana.UpdateNetwork(pNtk, fSame);
|
ana.AssignNetwork(pNtk, fReuse);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk, typename Ana>
|
||||||
|
void Optimizer<Ntk, Ana>::SetPrintLine(std::function<void(std::string)> const &PrintLine_) {
|
||||||
|
PrintLine = PrintLine_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -1127,13 +1312,14 @@ namespace rrr {
|
||||||
vRandCosts.clear();
|
vRandCosts.clear();
|
||||||
if(nSortTypeOriginal < 0) {
|
if(nSortTypeOriginal < 0) {
|
||||||
nSortType = rng() % 18;
|
nSortType = rng() % 18;
|
||||||
Print(0, "sorttype =", nSortType);
|
Print(0, "fanin cost function =", nSortType);
|
||||||
}
|
}
|
||||||
nTimeout = nTimeout_;
|
nTimeout = nTimeout_;
|
||||||
start = GetCurrentTime();
|
start = GetCurrentTime();
|
||||||
switch(nFlow) {
|
switch(nFlow) {
|
||||||
case 0:
|
case 0:
|
||||||
RemoveRedundancy();
|
RemoveRedundancy();
|
||||||
|
statsLocal.Reset();
|
||||||
ApplyReverseTopologically([&](int id) {
|
ApplyReverseTopologically([&](int id) {
|
||||||
std::vector<int> vCands;
|
std::vector<int> vCands;
|
||||||
if(nDistance) {
|
if(nDistance) {
|
||||||
|
|
@ -1143,9 +1329,12 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
SingleResub(id, vCands);
|
SingleResub(id, vCands);
|
||||||
});
|
});
|
||||||
|
stats["single"] += statsLocal;
|
||||||
|
Print(0, statsLocal.GetString());
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
RemoveRedundancy();
|
RemoveRedundancy();
|
||||||
|
statsLocal.Reset();
|
||||||
ApplyReverseTopologically([&](int id) {
|
ApplyReverseTopologically([&](int id) {
|
||||||
std::vector<int> vCands;
|
std::vector<int> vCands;
|
||||||
if(nDistance) {
|
if(nDistance) {
|
||||||
|
|
@ -1155,11 +1344,14 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
MultiResub(id, vCands);
|
MultiResub(id, vCands);
|
||||||
});
|
});
|
||||||
|
stats["multi"] += statsLocal;
|
||||||
|
Print(0, statsLocal.GetString());
|
||||||
break;
|
break;
|
||||||
case 2: {
|
case 2: {
|
||||||
RemoveRedundancy();
|
RemoveRedundancy();
|
||||||
double dCost = CostFunction(pNtk);
|
double dCost = CostFunction(pNtk);
|
||||||
while(true) {
|
while(true) {
|
||||||
|
statsLocal.Reset();
|
||||||
ApplyReverseTopologically([&](int id) {
|
ApplyReverseTopologically([&](int id) {
|
||||||
std::vector<int> vCands;
|
std::vector<int> vCands;
|
||||||
if(nDistance) {
|
if(nDistance) {
|
||||||
|
|
@ -1169,6 +1361,9 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
SingleResub(id, vCands);
|
SingleResub(id, vCands);
|
||||||
});
|
});
|
||||||
|
stats["single"] += statsLocal;
|
||||||
|
Print(0, "single", ":", "cost", "=", CostFunction(pNtk), ",", statsLocal.GetString());
|
||||||
|
statsLocal.Reset();
|
||||||
ApplyReverseTopologically([&](int id) {
|
ApplyReverseTopologically([&](int id) {
|
||||||
std::vector<int> vCands;
|
std::vector<int> vCands;
|
||||||
if(nDistance) {
|
if(nDistance) {
|
||||||
|
|
@ -1179,6 +1374,8 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
MultiResub(id, vCands);
|
MultiResub(id, vCands);
|
||||||
});
|
});
|
||||||
|
stats["multi"] += statsLocal;
|
||||||
|
Print(0, "multi ", ":", "cost", "=", CostFunction(pNtk), ",", statsLocal.GetString());
|
||||||
double dNewCost = CostFunction(pNtk);
|
double dNewCost = CostFunction(pNtk);
|
||||||
if(dNewCost < dCost) {
|
if(dNewCost < dCost) {
|
||||||
dCost = dNewCost;
|
dCost = dNewCost;
|
||||||
|
|
@ -1195,17 +1392,27 @@ namespace rrr {
|
||||||
vCands = pNtk->GetPisInts();
|
vCands = pNtk->GetPisInts();
|
||||||
std::shuffle(vCands.begin(), vCands.end(), rng);
|
std::shuffle(vCands.begin(), vCands.end(), rng);
|
||||||
}
|
}
|
||||||
|
Stats statsSingle, statsMulti;
|
||||||
ApplyRandomlyStop([&](int id) {
|
ApplyRandomlyStop([&](int id) {
|
||||||
|
statsLocal.Reset();
|
||||||
if(nDistance) {
|
if(nDistance) {
|
||||||
vCands = pNtk->GetNeighbors(id, true, nDistance);
|
vCands = pNtk->GetNeighbors(id, true, nDistance);
|
||||||
std::shuffle(vCands.begin(), vCands.end(), rng);
|
std::shuffle(vCands.begin(), vCands.end(), rng);
|
||||||
}
|
}
|
||||||
|
bool fChanged;
|
||||||
if(rng() & 1) {
|
if(rng() & 1) {
|
||||||
return SingleResubStop(id, vCands);
|
fChanged = SingleResubStop(id, vCands);
|
||||||
|
statsSingle += statsLocal;
|
||||||
} else {
|
} else {
|
||||||
return MultiResubStop(id, vCands);
|
fChanged = MultiResubStop(id, vCands);
|
||||||
|
statsMulti += statsLocal;
|
||||||
}
|
}
|
||||||
|
return fChanged;
|
||||||
});
|
});
|
||||||
|
stats["single"] += statsSingle;
|
||||||
|
stats["multi"] += statsMulti;
|
||||||
|
Print(0, "single", ":", statsSingle.GetString());
|
||||||
|
Print(0, "multi ", ":", statsMulti.GetString());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: {
|
case 4: {
|
||||||
|
|
@ -1222,6 +1429,46 @@ namespace rrr {
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ Summary */
|
||||||
|
|
||||||
|
template <typename Ntk, typename Ana>
|
||||||
|
void Optimizer<Ntk, Ana>::ResetSummary() {
|
||||||
|
stats.clear();
|
||||||
|
ana.ResetSummary();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk, typename Ana>
|
||||||
|
summary<int> Optimizer<Ntk, Ana>::GetStatsSummary() const {
|
||||||
|
summary<int> v;
|
||||||
|
for(auto const &entry: stats) {
|
||||||
|
v.emplace_back("opt " + entry.first + " tried node", entry.second.nTried);
|
||||||
|
v.emplace_back("opt " + entry.first + " tried fanin", entry.second.nTriedFis);
|
||||||
|
v.emplace_back("opt " + entry.first + " added node", entry.second.nAdded);
|
||||||
|
v.emplace_back("opt " + entry.first + " added fanin", entry.second.nAddedFis);
|
||||||
|
v.emplace_back("opt " + entry.first + " changed", entry.second.nChanged);
|
||||||
|
v.emplace_back("opt " + entry.first + " up", entry.second.nUps);
|
||||||
|
v.emplace_back("opt " + entry.first + " eq", entry.second.nEqs);
|
||||||
|
v.emplace_back("opt " + entry.first + " dn", entry.second.nDowns);
|
||||||
|
}
|
||||||
|
summary<int> v2 = ana.GetStatsSummary();
|
||||||
|
v.insert(v.end(), v2.begin(), v2.end());
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk, typename Ana>
|
||||||
|
summary<double> Optimizer<Ntk, Ana>::GetTimesSummary() const {
|
||||||
|
summary<double> v;
|
||||||
|
for(auto const &entry: stats) {
|
||||||
|
v.emplace_back("opt " + entry.first + " add", entry.second.durationAdd);
|
||||||
|
v.emplace_back("opt " + entry.first + " reduce", entry.second.durationReduce);
|
||||||
|
}
|
||||||
|
summary<double> v2 = ana.GetTimesSummary();
|
||||||
|
v.insert(v.end(), v2.begin(), v2.end());
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ABC_NAMESPACE_CXX_HEADER_END
|
ABC_NAMESPACE_CXX_HEADER_END
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace rrr {
|
||||||
int iSeed = 0;
|
int iSeed = 0;
|
||||||
int nWords = 10;
|
int nWords = 10;
|
||||||
int nTimeout = 0;
|
int nTimeout = 0;
|
||||||
int nSchedulerVerbose = 1;
|
int nSchedulerVerbose = 0;
|
||||||
int nPartitionerVerbose = 0;
|
int nPartitionerVerbose = 0;
|
||||||
int nOptimizerVerbose = 0;
|
int nOptimizerVerbose = 0;
|
||||||
int nAnalyzerVerbose = 0;
|
int nAnalyzerVerbose = 0;
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ namespace rrr {
|
||||||
public:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
Partitioner(Parameter const *pPar);
|
Partitioner(Parameter const *pPar);
|
||||||
void UpdateNetwork(Ntk *pNtk);
|
void AssignNetwork(Ntk *pNtk);
|
||||||
|
|
||||||
// APIs
|
// APIs
|
||||||
Ntk *Extract(int iSeed);
|
Ntk *Extract(int iSeed);
|
||||||
|
|
@ -270,7 +270,7 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
void Partitioner<Ntk>::UpdateNetwork(Ntk *pNtk_) {
|
void Partitioner<Ntk>::AssignNetwork(Ntk *pNtk_) {
|
||||||
pNtk = pNtk_;
|
pNtk = pNtk_;
|
||||||
assert(mSubNtk2Io.empty());
|
assert(mSubNtk2Io.empty());
|
||||||
assert(sBlocked.empty());
|
assert(sBlocked.empty());
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,12 @@ namespace rrr {
|
||||||
std::vector<VarValue> vValues; // values in satisfied problem
|
std::vector<VarValue> vValues; // values in satisfied problem
|
||||||
bool fUpdate;
|
bool fUpdate;
|
||||||
|
|
||||||
// statistics
|
// stats
|
||||||
int nCalls;
|
int nCalls;
|
||||||
int nSats;
|
int nSats;
|
||||||
int nUnsats;
|
int nUnsats;
|
||||||
|
double durationRedundancy;
|
||||||
|
double durationFeasibility;
|
||||||
|
|
||||||
// callback
|
// callback
|
||||||
void ActionCallback(Action const &action);
|
void ActionCallback(Action const &action);
|
||||||
|
|
@ -45,7 +47,7 @@ namespace rrr {
|
||||||
// constructors
|
// constructors
|
||||||
SatSolver(Parameter const *pPar);
|
SatSolver(Parameter const *pPar);
|
||||||
~SatSolver();
|
~SatSolver();
|
||||||
void UpdateNetwork(Ntk *pNtk_, bool fSame);
|
void AssignNetwork(Ntk *pNtk_, bool fReuse);
|
||||||
|
|
||||||
// checks
|
// checks
|
||||||
SatResult CheckRedundancy(int id, int idx);
|
SatResult CheckRedundancy(int id, int idx);
|
||||||
|
|
@ -53,6 +55,11 @@ namespace rrr {
|
||||||
|
|
||||||
// cex
|
// cex
|
||||||
std::vector<VarValue> GetCex();
|
std::vector<VarValue> GetCex();
|
||||||
|
|
||||||
|
// stats
|
||||||
|
void ResetSummary();
|
||||||
|
summary<int> GetStatsSummary() const;
|
||||||
|
summary<double> GetTimesSummary() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* {{{ Callback */
|
/* {{{ Callback */
|
||||||
|
|
@ -88,6 +95,11 @@ namespace rrr {
|
||||||
break;
|
break;
|
||||||
case SORT_FANINS:
|
case SORT_FANINS:
|
||||||
break;
|
break;
|
||||||
|
case READ:
|
||||||
|
status = false;
|
||||||
|
target = -1;
|
||||||
|
fUpdate = false;
|
||||||
|
break;
|
||||||
case SAVE:
|
case SAVE:
|
||||||
break;
|
break;
|
||||||
case LOAD:
|
case LOAD:
|
||||||
|
|
@ -259,25 +271,23 @@ namespace rrr {
|
||||||
pSat(sat_solver_new()),
|
pSat(sat_solver_new()),
|
||||||
status(false),
|
status(false),
|
||||||
target(-1),
|
target(-1),
|
||||||
fUpdate(false),
|
fUpdate(false) {
|
||||||
nCalls(0),
|
ResetSummary();
|
||||||
nSats(0),
|
|
||||||
nUnsats(0) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
SatSolver<Ntk>::~SatSolver() {
|
SatSolver<Ntk>::~SatSolver() {
|
||||||
sat_solver_delete(pSat);
|
sat_solver_delete(pSat);
|
||||||
std::cout << "SAT solver stats: calls = " << nCalls << " (SAT = " << nSats << ", UNSAT = " << nUnsats << ", UNDET = " << nCalls - nSats - nUnsats << ")" << std::endl;
|
//std::cout << "SAT solver stats: calls = " << nCalls << " (SAT = " << nSats << ", UNSAT = " << nUnsats << ", UNDET = " << nCalls - nSats - nUnsats << ")" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
void SatSolver<Ntk>::UpdateNetwork(Ntk *pNtk_, bool fSame) {
|
void SatSolver<Ntk>::AssignNetwork(Ntk *pNtk_, bool fReuse) {
|
||||||
(void)fSame;
|
(void)fReuse;
|
||||||
pNtk = pNtk_;
|
|
||||||
status = false;
|
status = false;
|
||||||
target = -1;
|
target = -1;
|
||||||
fUpdate = false;
|
fUpdate = false;
|
||||||
|
pNtk = pNtk_;
|
||||||
pNtk->AddCallback(std::bind(&SatSolver<Ntk>::ActionCallback, this, std::placeholders::_1));
|
pNtk->AddCallback(std::bind(&SatSolver<Ntk>::ActionCallback, this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -287,11 +297,13 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
SatResult SatSolver<Ntk>::CheckRedundancy(int id, int idx) {
|
SatResult SatSolver<Ntk>::CheckRedundancy(int id, int idx) {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
SetTarget(id);
|
SetTarget(id);
|
||||||
if(!status) {
|
if(!status) {
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "trivially UNSATISFIABLE" << std::endl;
|
std::cout << "trivially UNSATISFIABLE" << std::endl;
|
||||||
}
|
}
|
||||||
|
durationRedundancy += Duration(timeStart, GetCurrentTime());
|
||||||
return UNSAT;
|
return UNSAT;
|
||||||
}
|
}
|
||||||
vLits.clear();
|
vLits.clear();
|
||||||
|
|
@ -319,12 +331,14 @@ namespace rrr {
|
||||||
std::cout << "UNSATISFIABLE" << std::endl;
|
std::cout << "UNSATISFIABLE" << std::endl;
|
||||||
}
|
}
|
||||||
nUnsats++;
|
nUnsats++;
|
||||||
|
durationRedundancy += Duration(timeStart, GetCurrentTime());
|
||||||
return UNSAT;
|
return UNSAT;
|
||||||
}
|
}
|
||||||
if(res == l_Undef) {
|
if(res == l_Undef) {
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "UNDETERMINED" << std::endl;
|
std::cout << "UNDETERMINED" << std::endl;
|
||||||
}
|
}
|
||||||
|
durationRedundancy += Duration(timeStart, GetCurrentTime());
|
||||||
return UNDET;
|
return UNDET;
|
||||||
}
|
}
|
||||||
assert(res == l_True);
|
assert(res == l_True);
|
||||||
|
|
@ -353,16 +367,19 @@ namespace rrr {
|
||||||
assert((vValues[fi] == TEMP_TRUE) ^ (idx == idx2) ^ c);
|
assert((vValues[fi] == TEMP_TRUE) ^ (idx == idx2) ^ c);
|
||||||
vValues[fi] = DecideVarValue(vValues[fi]);
|
vValues[fi] = DecideVarValue(vValues[fi]);
|
||||||
});
|
});
|
||||||
|
durationRedundancy += Duration(timeStart, GetCurrentTime());
|
||||||
return SAT;
|
return SAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
SatResult SatSolver<Ntk>::CheckFeasibility(int id, int fi, bool c) {
|
SatResult SatSolver<Ntk>::CheckFeasibility(int id, int fi, bool c) {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
SetTarget(id);
|
SetTarget(id);
|
||||||
if(!status) {
|
if(!status) {
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "trivially UNSATISFIABLE" << std::endl;
|
std::cout << "trivially UNSATISFIABLE" << std::endl;
|
||||||
}
|
}
|
||||||
|
durationFeasibility += Duration(timeStart, GetCurrentTime());
|
||||||
return UNSAT;
|
return UNSAT;
|
||||||
}
|
}
|
||||||
vLits.clear();
|
vLits.clear();
|
||||||
|
|
@ -385,12 +402,14 @@ namespace rrr {
|
||||||
std::cout << "UNSATISFIABLE" << std::endl;
|
std::cout << "UNSATISFIABLE" << std::endl;
|
||||||
}
|
}
|
||||||
nUnsats++;
|
nUnsats++;
|
||||||
|
durationFeasibility += Duration(timeStart, GetCurrentTime());
|
||||||
return UNSAT;
|
return UNSAT;
|
||||||
}
|
}
|
||||||
if(res == l_Undef) {
|
if(res == l_Undef) {
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "UNDETERMINED" << std::endl;
|
std::cout << "UNDETERMINED" << std::endl;
|
||||||
}
|
}
|
||||||
|
durationFeasibility += Duration(timeStart, GetCurrentTime());
|
||||||
return UNDET;
|
return UNDET;
|
||||||
}
|
}
|
||||||
assert(res == l_True);
|
assert(res == l_True);
|
||||||
|
|
@ -419,6 +438,7 @@ namespace rrr {
|
||||||
vValues[id] = DecideVarValue(vValues[id]);
|
vValues[id] = DecideVarValue(vValues[id]);
|
||||||
assert((vValues[fi] == TEMP_TRUE) ^ !c);
|
assert((vValues[fi] == TEMP_TRUE) ^ !c);
|
||||||
vValues[fi] = DecideVarValue(vValues[fi]);
|
vValues[fi] = DecideVarValue(vValues[fi]);
|
||||||
|
durationFeasibility += Duration(timeStart, GetCurrentTime());
|
||||||
return SAT;
|
return SAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -537,6 +557,36 @@ namespace rrr {
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ Stats */
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
void SatSolver<Ntk>::ResetSummary() {
|
||||||
|
nCalls = 0;
|
||||||
|
nSats = 0;
|
||||||
|
nUnsats = 0;
|
||||||
|
durationRedundancy = 0;
|
||||||
|
durationFeasibility = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
summary<int> SatSolver<Ntk>::GetStatsSummary() const {
|
||||||
|
summary<int> v;
|
||||||
|
v.emplace_back("sat call", nCalls);
|
||||||
|
v.emplace_back("sat satisfiable", nSats);
|
||||||
|
v.emplace_back("sat unsatisfiable", nUnsats);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
summary<double> SatSolver<Ntk>::GetTimesSummary() const {
|
||||||
|
summary<double> v;
|
||||||
|
v.emplace_back("sat redundancy", durationRedundancy);
|
||||||
|
v.emplace_back("sat feasibility", durationFeasibility);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ABC_NAMESPACE_CXX_HEADER_END
|
ABC_NAMESPACE_CXX_HEADER_END
|
||||||
|
|
|
||||||
|
|
@ -46,10 +46,14 @@ namespace rrr {
|
||||||
// data
|
// data
|
||||||
int nCreatedJobs;
|
int nCreatedJobs;
|
||||||
int nFinishedJobs;
|
int nFinishedJobs;
|
||||||
time_point start;
|
time_point timeStart;
|
||||||
Par par;
|
Par par;
|
||||||
std::queue<Job *> qPendingJobs;
|
std::queue<Job *> qPendingJobs;
|
||||||
Opt *pOpt; // used only in case of single thread execution
|
Opt *pOpt; // used only in case of single thread execution
|
||||||
|
std::vector<std::string> vStatsSummaryKeys;
|
||||||
|
std::map<std::string, int> mStatsSummary;
|
||||||
|
std::vector<std::string> vTimesSummaryKeys;
|
||||||
|
std::map<std::string, double> mTimesSummary;
|
||||||
#ifdef ABC_USE_PTHREADS
|
#ifdef ABC_USE_PTHREADS
|
||||||
bool fTerminate;
|
bool fTerminate;
|
||||||
std::vector<std::thread> vThreads;
|
std::vector<std::thread> vThreads;
|
||||||
|
|
@ -57,21 +61,27 @@ namespace rrr {
|
||||||
std::mutex mutexAbc;
|
std::mutex mutexAbc;
|
||||||
std::mutex mutexPendingJobs;
|
std::mutex mutexPendingJobs;
|
||||||
std::mutex mutexFinishedJobs;
|
std::mutex mutexFinishedJobs;
|
||||||
|
std::mutex mutexPrint;
|
||||||
std::condition_variable condPendingJobs;
|
std::condition_variable condPendingJobs;
|
||||||
std::condition_variable condFinishedJobs;
|
std::condition_variable condFinishedJobs;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// print
|
||||||
|
template <typename... Args>
|
||||||
|
void Print(int nVerboseLevel, std::string prefix, Args... args);
|
||||||
|
|
||||||
// time
|
// time
|
||||||
seconds GetRemainingTime() const;
|
seconds GetRemainingTime() const;
|
||||||
|
double GetElapsedTime() const;
|
||||||
|
|
||||||
// abc
|
// abc
|
||||||
void CallAbc(Ntk *pNtk_, std::string Command);
|
void CallAbc(Ntk *pNtk_, std::string Command);
|
||||||
|
|
||||||
// run jobs
|
// run jobs
|
||||||
void RunJob(Opt &opt, Job const *pJob);
|
void RunJob(Opt &opt, Job *pJob);
|
||||||
|
|
||||||
// manage jobs
|
// manage jobs
|
||||||
void CreateJob(Ntk *pNtk_, int iSeed_);
|
Job *CreateJob(Ntk *pNtk_, int iSeed_, double cost);
|
||||||
void OnJobEnd(std::function<void(Job *pJob)> const &func);
|
void OnJobEnd(std::function<void(Job *pJob)> const &func);
|
||||||
|
|
||||||
// thread
|
// thread
|
||||||
|
|
@ -79,6 +89,10 @@ namespace rrr {
|
||||||
void Thread(Parameter const *pPar);
|
void Thread(Parameter const *pPar);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// summary
|
||||||
|
template <typename T>
|
||||||
|
void AddToSummary(std::vector<std::string> &keys, std::map<std::string, T> &m, summary<T> const &result) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
Scheduler(Ntk *pNtk, Parameter const *pPar);
|
Scheduler(Ntk *pNtk, Parameter const *pPar);
|
||||||
|
|
@ -96,12 +110,21 @@ namespace rrr {
|
||||||
int id;
|
int id;
|
||||||
Ntk *pNtk;
|
Ntk *pNtk;
|
||||||
int iSeed;
|
int iSeed;
|
||||||
|
double costInitial;
|
||||||
|
std::string prefix;
|
||||||
|
double duration;
|
||||||
|
summary<int> stats;
|
||||||
|
summary<double> times;
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
Job(int id, Ntk *pNtk, int iSeed) :
|
Job(int id, Ntk *pNtk, int iSeed, double cost) :
|
||||||
id(id),
|
id(id),
|
||||||
pNtk(pNtk),
|
pNtk(pNtk),
|
||||||
iSeed(iSeed) {
|
iSeed(iSeed),
|
||||||
|
costInitial(cost) {
|
||||||
|
std::stringstream ss;
|
||||||
|
PrintNext(ss, "job", id, ":");
|
||||||
|
prefix = ss.str() + " ";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -115,21 +138,53 @@ namespace rrr {
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ Print */
|
||||||
|
|
||||||
|
template <typename Ntk, typename Opt, typename Par>
|
||||||
|
template<typename... Args>
|
||||||
|
inline void Scheduler<Ntk, Opt, Par>::Print(int nVerboseLevel, std::string prefix, Args... args) {
|
||||||
|
if(nVerbose <= nVerboseLevel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef ABC_USE_PTHREADS
|
||||||
|
if(fMultiThreading) {
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> l(mutexPrint);
|
||||||
|
std::cout << prefix;
|
||||||
|
PrintNext(std::cout, args...);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
std::cout << prefix;
|
||||||
|
PrintNext(std::cout, args...);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ Time */
|
/* {{{ Time */
|
||||||
|
|
||||||
template <typename Ntk, typename Opt, typename Par>
|
template <typename Ntk, typename Opt, typename Par>
|
||||||
seconds Scheduler<Ntk, Opt, Par>::GetRemainingTime() const {
|
inline seconds Scheduler<Ntk, Opt, Par>::GetRemainingTime() const {
|
||||||
if(nTimeout == 0) {
|
if(nTimeout == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
time_point current = GetCurrentTime();
|
time_point timeCurrent = GetCurrentTime();
|
||||||
seconds nRemainingTime = nTimeout - DurationInSeconds(start, current);
|
seconds nRemainingTime = nTimeout - DurationInSeconds(timeStart, timeCurrent);
|
||||||
if(nRemainingTime == 0) { // avoid glitch
|
if(nRemainingTime == 0) { // avoid glitch
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return nRemainingTime;
|
return nRemainingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Ntk, typename Opt, typename Par>
|
||||||
|
inline double Scheduler<Ntk, Opt, Par>::GetElapsedTime() const {
|
||||||
|
time_point timeCurrent = GetCurrentTime();
|
||||||
|
return Duration(timeStart, timeCurrent);
|
||||||
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ Abc */
|
/* {{{ Abc */
|
||||||
|
|
@ -153,8 +208,12 @@ namespace rrr {
|
||||||
/* {{{ Run jobs */
|
/* {{{ Run jobs */
|
||||||
|
|
||||||
template <typename Ntk, typename Opt, typename Par>
|
template <typename Ntk, typename Opt, typename Par>
|
||||||
void Scheduler<Ntk, Opt, Par>::RunJob(Opt &opt, Job const *pJob) {
|
void Scheduler<Ntk, Opt, Par>::RunJob(Opt &opt, Job *pJob) {
|
||||||
opt.UpdateNetwork(pJob->pNtk);
|
time_point timeStartLocal = GetCurrentTime();
|
||||||
|
opt.AssignNetwork(pJob->pNtk, !fPartitioning); // reuse backend if restarting
|
||||||
|
opt.SetPrintLine([&](std::string str) {
|
||||||
|
Print(-1, pJob->prefix, str);
|
||||||
|
});
|
||||||
// start flow
|
// start flow
|
||||||
switch(nFlow) {
|
switch(nFlow) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
@ -162,23 +221,17 @@ namespace rrr {
|
||||||
break;
|
break;
|
||||||
case 1: { // transtoch
|
case 1: { // transtoch
|
||||||
std::mt19937 rng(pJob->iSeed);
|
std::mt19937 rng(pJob->iSeed);
|
||||||
double dCost = CostFunction(pJob->pNtk);
|
double cost = pJob->costInitial;
|
||||||
double dBestCost = dCost;
|
double costBest = cost;
|
||||||
Ntk best(*(pJob->pNtk));
|
Ntk best(*(pJob->pNtk));
|
||||||
if(nVerbose) {
|
|
||||||
std::cout << "start: cost = " << dCost << std::endl;
|
|
||||||
}
|
|
||||||
for(int i = 0; i < 10; i++) {
|
for(int i = 0; i < 10; i++) {
|
||||||
if(GetRemainingTime() < 0) {
|
if(GetRemainingTime() < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(i != 0) {
|
if(i != 0) {
|
||||||
CallAbc(pJob->pNtk, "&if -K 6; &mfs; &st");
|
CallAbc(pJob->pNtk, "&if -K 6; &mfs; &st");
|
||||||
dCost = CostFunction(pJob->pNtk);
|
cost = CostFunction(pJob->pNtk);
|
||||||
opt.UpdateNetwork(pJob->pNtk, true);
|
Print(1, pJob->prefix, "hop", i, ":", "cost", "=", cost);
|
||||||
if(nVerbose) {
|
|
||||||
std::cout << "hop " << std::setw(3) << i << ": cost = " << dCost << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for(int j = 0; true; j++) {
|
for(int j = 0; true; j++) {
|
||||||
if(GetRemainingTime() < 0) {
|
if(GetRemainingTime() < 0) {
|
||||||
|
|
@ -186,37 +239,28 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
opt.Run(rng(), GetRemainingTime());
|
opt.Run(rng(), GetRemainingTime());
|
||||||
CallAbc(pJob->pNtk, "&dc2");
|
CallAbc(pJob->pNtk, "&dc2");
|
||||||
double dNewCost = CostFunction(pJob->pNtk);
|
double costNew = CostFunction(pJob->pNtk);
|
||||||
if(nVerbose) {
|
Print(1, pJob->prefix, "ite", j, ":", "cost", "=", costNew);
|
||||||
std::cout << "\tite " << std::setw(3) << j << ": cost = " << dNewCost << std::endl;
|
if(costNew < cost) {
|
||||||
}
|
cost = costNew;
|
||||||
if(dNewCost < dCost) {
|
|
||||||
dCost = dNewCost;
|
|
||||||
opt.UpdateNetwork(pJob->pNtk, true);
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(dCost < dBestCost) {
|
if(cost < costBest) {
|
||||||
dBestCost = dCost;
|
costBest = cost;
|
||||||
best = *(pJob->pNtk);
|
best = *(pJob->pNtk);
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*(pJob->pNtk) = best;
|
*(pJob->pNtk) = best;
|
||||||
if(nVerbose) {
|
|
||||||
std::cout << "end: cost = " << dBestCost << std::endl;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: { // deep
|
case 2: { // deep
|
||||||
std::mt19937 rng(pJob->iSeed);
|
std::mt19937 rng(pJob->iSeed);
|
||||||
int n = 0;
|
int n = 0;
|
||||||
double dCost = CostFunction(pJob->pNtk);
|
double cost = pJob->costInitial;
|
||||||
Ntk best(*(pJob->pNtk));
|
Ntk best(*(pJob->pNtk));
|
||||||
if(nVerbose) {
|
|
||||||
std::cout << "start: cost = " << dCost << std::endl;
|
|
||||||
}
|
|
||||||
for(int i = 0; i < 1000000; i++) {
|
for(int i = 0; i < 1000000; i++) {
|
||||||
if(GetRemainingTime() < 0) {
|
if(GetRemainingTime() < 0) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -246,38 +290,30 @@ namespace rrr {
|
||||||
Command += "; &fx; &st";
|
Command += "; &fx; &st";
|
||||||
Command += pComp;
|
Command += pComp;
|
||||||
CallAbc(pJob->pNtk, Command);
|
CallAbc(pJob->pNtk, Command);
|
||||||
if(nVerbose) {
|
Print(1, pJob->prefix, "ite", i, ":", "cost", "=", CostFunction(pJob->pNtk));
|
||||||
std::cout << "ite " << std::setw(6) << i << ": cost = " << CostFunction(pJob->pNtk) << std::endl;
|
|
||||||
}
|
|
||||||
// rrr
|
// rrr
|
||||||
for(int j = 0; j < n; j++) {
|
for(int j = 0; j < n; j++) {
|
||||||
if(GetRemainingTime() < 0) {
|
if(GetRemainingTime() < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
opt.UpdateNetwork(pJob->pNtk, true);
|
|
||||||
opt.Run(rng(), GetRemainingTime());
|
opt.Run(rng(), GetRemainingTime());
|
||||||
if(rng() & 1) {
|
if(rng() & 1) {
|
||||||
CallAbc(pJob->pNtk, "&dc2");
|
CallAbc(pJob->pNtk, "&dc2");
|
||||||
} else {
|
} else {
|
||||||
CallAbc(pJob->pNtk, std::string("&put; ") + pCompress2rs + "; &get");
|
CallAbc(pJob->pNtk, std::string("&put; ") + pCompress2rs + "; &get");
|
||||||
}
|
}
|
||||||
if(nVerbose) {
|
Print(1, pJob->prefix, "rrr", j, ":", "cost", "=", CostFunction(pJob->pNtk));
|
||||||
std::cout << "\trrr " << std::setw(6) << j << ": cost = " << CostFunction(pJob->pNtk) << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// eval
|
// eval
|
||||||
double dNewCost = CostFunction(pJob->pNtk);
|
double costNew = CostFunction(pJob->pNtk);
|
||||||
if(dNewCost < dCost) {
|
if(costNew < cost) {
|
||||||
dCost = dNewCost;
|
cost = costNew;
|
||||||
best = *(pJob->pNtk);
|
best = *(pJob->pNtk);
|
||||||
} else {
|
} else {
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*(pJob->pNtk) = best;
|
*(pJob->pNtk) = best;
|
||||||
if(nVerbose) {
|
|
||||||
std::cout << "end: cost = " << dCost << std::endl;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3:
|
case 3:
|
||||||
|
|
@ -287,6 +323,11 @@ namespace rrr {
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
time_point timeEndLocal = GetCurrentTime();
|
||||||
|
pJob->duration = Duration(timeStartLocal, timeEndLocal);
|
||||||
|
pJob->stats = opt.GetStatsSummary();
|
||||||
|
pJob->times = opt.GetTimesSummary();
|
||||||
|
opt.ResetSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -294,8 +335,8 @@ namespace rrr {
|
||||||
/* {{{ Manage jobs */
|
/* {{{ Manage jobs */
|
||||||
|
|
||||||
template <typename Ntk, typename Opt, typename Par>
|
template <typename Ntk, typename Opt, typename Par>
|
||||||
void Scheduler<Ntk, Opt, Par>::CreateJob(Ntk *pNtk_, int iSeed_) {
|
typename Scheduler<Ntk, Opt, Par>::Job *Scheduler<Ntk, Opt, Par>::CreateJob(Ntk *pNtk_, int iSeed_, double cost) {
|
||||||
Job *pJob = new Job(nCreatedJobs++, pNtk_, iSeed_);
|
Job *pJob = new Job(nCreatedJobs++, pNtk_, iSeed_, cost);
|
||||||
#ifdef ABC_USE_PTHREADS
|
#ifdef ABC_USE_PTHREADS
|
||||||
if(fMultiThreading) {
|
if(fMultiThreading) {
|
||||||
{
|
{
|
||||||
|
|
@ -303,10 +344,11 @@ namespace rrr {
|
||||||
qPendingJobs.push(pJob);
|
qPendingJobs.push(pJob);
|
||||||
condPendingJobs.notify_one();
|
condPendingJobs.notify_one();
|
||||||
}
|
}
|
||||||
return;
|
return pJob;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
qPendingJobs.push(pJob);
|
qPendingJobs.push(pJob);
|
||||||
|
return pJob;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk, typename Opt, typename Par>
|
template <typename Ntk, typename Opt, typename Par>
|
||||||
|
|
@ -324,6 +366,8 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
assert(pJob != NULL);
|
assert(pJob != NULL);
|
||||||
func(pJob);
|
func(pJob);
|
||||||
|
AddToSummary(vStatsSummaryKeys, mStatsSummary, pJob->stats);
|
||||||
|
AddToSummary(vTimesSummaryKeys, mTimesSummary, pJob->times);
|
||||||
delete pJob;
|
delete pJob;
|
||||||
nFinishedJobs++;
|
nFinishedJobs++;
|
||||||
return;
|
return;
|
||||||
|
|
@ -335,6 +379,8 @@ namespace rrr {
|
||||||
qPendingJobs.pop();
|
qPendingJobs.pop();
|
||||||
RunJob(*pOpt, pJob);
|
RunJob(*pOpt, pJob);
|
||||||
func(pJob);
|
func(pJob);
|
||||||
|
AddToSummary(vStatsSummaryKeys, mStatsSummary, pJob->stats);
|
||||||
|
AddToSummary(vTimesSummaryKeys, mTimesSummary, pJob->times);
|
||||||
delete pJob;
|
delete pJob;
|
||||||
nFinishedJobs++;
|
nFinishedJobs++;
|
||||||
}
|
}
|
||||||
|
|
@ -374,6 +420,28 @@ namespace rrr {
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ Summary */
|
||||||
|
|
||||||
|
template <typename Ntk, typename Opt, typename Par>
|
||||||
|
template <typename T>
|
||||||
|
void Scheduler<Ntk, Opt, Par>::AddToSummary(std::vector<std::string> &keys, std::map<std::string, T> &m, summary<T> const &result) const {
|
||||||
|
std::vector<std::string>::iterator it = keys.begin();
|
||||||
|
for(auto const &entry: result) {
|
||||||
|
if(m.count(entry.first)) {
|
||||||
|
m[entry.first] += entry.second;
|
||||||
|
it = std::find(it, keys.end(), entry.first);
|
||||||
|
assert(it != keys.end());
|
||||||
|
it++;
|
||||||
|
} else {
|
||||||
|
m[entry.first] = entry.second;
|
||||||
|
it = keys.insert(it, entry.first);
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ Constructors */
|
/* {{{ Constructors */
|
||||||
|
|
||||||
template <typename Ntk, typename Opt, typename Par>
|
template <typename Ntk, typename Opt, typename Par>
|
||||||
|
|
@ -439,74 +507,90 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename Ntk, typename Opt, typename Par>
|
template <typename Ntk, typename Opt, typename Par>
|
||||||
void Scheduler<Ntk, Opt, Par>::Run() {
|
void Scheduler<Ntk, Opt, Par>::Run() {
|
||||||
start = GetCurrentTime();
|
timeStart = GetCurrentTime();
|
||||||
|
double costStart = CostFunction(pNtk);
|
||||||
if(fPartitioning) {
|
if(fPartitioning) {
|
||||||
fDeterministic = false; // it is deterministic anyways as we wait until all jobs finish each round
|
fDeterministic = false; // it is deterministic anyways as we wait until all jobs finish each round
|
||||||
pNtk->Sweep();
|
pNtk->Sweep();
|
||||||
par.UpdateNetwork(pNtk);
|
par.AssignNetwork(pNtk);
|
||||||
while(nCreatedJobs < nJobs) {
|
while(nCreatedJobs < nJobs) {
|
||||||
assert(nParallelPartitions > 0);
|
assert(nParallelPartitions > 0);
|
||||||
if(nCreatedJobs < nFinishedJobs + nParallelPartitions) {
|
if(nCreatedJobs < nFinishedJobs + nParallelPartitions) {
|
||||||
Ntk *pSubNtk = par.Extract(iSeed + nCreatedJobs);
|
Ntk *pSubNtk = par.Extract(iSeed + nCreatedJobs);
|
||||||
if(pSubNtk) {
|
if(pSubNtk) {
|
||||||
CreateJob(pSubNtk, iSeed + nCreatedJobs);
|
Job *pJob = CreateJob(pSubNtk, iSeed + nCreatedJobs, CostFunction(pSubNtk));
|
||||||
std::cout << "job " << nCreatedJobs - 1 << " created (size = " << pSubNtk->GetNumInts() << ")" << std::endl;
|
Print(1, pJob->prefix, "created ", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", pJob->costInitial);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(nCreatedJobs == nFinishedJobs) {
|
if(nCreatedJobs == nFinishedJobs) {
|
||||||
std::cout << "failed to partition" << std::endl;
|
PrintWarning("failed to partition");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while(nFinishedJobs < nCreatedJobs) {
|
while(nFinishedJobs < nCreatedJobs) {
|
||||||
OnJobEnd([&](Job *pJob) {
|
OnJobEnd([&](Job *pJob) {
|
||||||
std::cout << "job " << pJob->id << " finished (size = " << pJob->pNtk->GetNumInts() << ")" << std::endl;
|
double cost = CostFunction(pJob->pNtk);
|
||||||
|
Print(1, pJob->prefix, "finished", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost);
|
||||||
|
Print(0, "", "job", pJob->id, "(", nFinishedJobs + 1, "/", nJobs, ")", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - pJob->costInitial) / pJob->costInitial, "%", ")", ",", "duration", "=", pJob->duration, "s", ",", "elapsed", "=", GetElapsedTime(), "s");
|
||||||
par.Insert(pJob->pNtk);
|
par.Insert(pJob->pNtk);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if(fOptOnInsert) {
|
if(fOptOnInsert) {
|
||||||
|
time_point timeStartLocal = GetCurrentTime();
|
||||||
CallAbc(pNtk, std::string("&put; ") + pCompress2rs + "; dc2; &get");
|
CallAbc(pNtk, std::string("&put; ") + pCompress2rs + "; dc2; &get");
|
||||||
par.UpdateNetwork(pNtk);
|
time_point timeEndLocal = GetCurrentTime();
|
||||||
|
par.AssignNetwork(pNtk);
|
||||||
|
double cost = CostFunction(pNtk);
|
||||||
|
Print(0, "", "c2rs; dc2", ":", std::string(34, ' '), "node", "=", pNtk->GetNumInts(), ",", "level", "=", pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - costStart) / costStart, "%", ")", ",", "duration", "=", Duration(timeStartLocal, timeEndLocal), "s", ",", "elapsed", "=", GetElapsedTime(), "s");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(nFinishedJobs < nCreatedJobs) {
|
while(nFinishedJobs < nCreatedJobs) {
|
||||||
OnJobEnd([&](Job *pJob) {
|
OnJobEnd([&](Job *pJob) {
|
||||||
std::cout << "job " << pJob->id << " finished (size = " << pJob->pNtk->GetNumInts() << ")" << std::endl;
|
double cost = CostFunction(pJob->pNtk);
|
||||||
|
Print(1, pJob->prefix, "finished", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", CostFunction(pJob->pNtk));
|
||||||
|
Print(0, "", "job", pJob->id, "(", nFinishedJobs + 1, "/", nJobs, ")", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - pJob->costInitial) / pJob->costInitial, "%", ")", ",", "duration", "=", pJob->duration, "s", ",", "elapsed", "=", GetElapsedTime(), "s");
|
||||||
par.Insert(pJob->pNtk);
|
par.Insert(pJob->pNtk);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if(fOptOnInsert) {
|
if(fOptOnInsert) {
|
||||||
CallAbc(pNtk, std::string("&put; ") + pCompress2rs + "; dc2; &get");
|
CallAbc(pNtk, std::string("&put; ") + pCompress2rs + "; dc2; &get");
|
||||||
par.UpdateNetwork(pNtk);
|
par.AssignNetwork(pNtk);
|
||||||
}
|
}
|
||||||
} else if(nJobs > 1) {
|
} else if(nJobs > 1) {
|
||||||
double dCost = CostFunction(pNtk);
|
double costBest = costStart;
|
||||||
for(int i = 0; i < nJobs; i++) {
|
for(int i = 0; i < nJobs; i++) {
|
||||||
Ntk *pCopy = new Ntk(*pNtk);
|
Ntk *pCopy = new Ntk(*pNtk);
|
||||||
CreateJob(pCopy, iSeed + i);
|
CreateJob(pCopy, iSeed + i, costBest);
|
||||||
}
|
}
|
||||||
for(int i = 0; i < nJobs; i++) {
|
for(int i = 0; i < nJobs; i++) {
|
||||||
OnJobEnd([&](Job *pJob) {
|
OnJobEnd([&](Job *pJob) {
|
||||||
double dNewCost = CostFunction(pJob->pNtk);
|
double cost = CostFunction(pJob->pNtk);
|
||||||
if(nVerbose) {
|
Print(0, "", "job", pJob->id, "(", nFinishedJobs + 1, "/", nJobs, ")", ":", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - pJob->costInitial) / pJob->costInitial, "%", ")", ",", "duration", "=", pJob->duration, "s", ",", "elapsed", "=", GetElapsedTime(), "s");
|
||||||
std::cout << "run " << pJob->id << ": cost = " << dNewCost << std::endl;
|
if(cost < costBest) {
|
||||||
}
|
costBest = cost;
|
||||||
if(dNewCost < dCost) {
|
|
||||||
dCost = dNewCost;
|
|
||||||
*pNtk = *(pJob->pNtk);
|
*pNtk = *(pJob->pNtk);
|
||||||
}
|
}
|
||||||
delete pJob->pNtk;
|
delete pJob->pNtk;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CreateJob(pNtk, iSeed);
|
CreateJob(pNtk, iSeed, costStart);
|
||||||
OnJobEnd([&](Job *pJob) { (void)pJob; });
|
OnJobEnd([&](Job *pJob) {
|
||||||
|
double cost = CostFunction(pJob->pNtk);
|
||||||
|
Print(0, "", "job", pJob->id, "(", nFinishedJobs + 1, "/", nJobs, ")", ":", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - pJob->costInitial) / pJob->costInitial, "%", ")", ",", "duration", "=", pJob->duration, "s", ",", "elapsed", "=", GetElapsedTime(), "s");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
time_point end = GetCurrentTime();
|
double cost = CostFunction(pNtk);
|
||||||
double elapsed_seconds = Duration(start, end);
|
double duration = GetElapsedTime();
|
||||||
if(nVerbose) {
|
Print(0, "\n", "stats summary", ":");
|
||||||
std::cout << "elapsed: " << std::fixed << std::setprecision(3) << elapsed_seconds << "s" << std::endl;
|
for(std::string key: vStatsSummaryKeys) {
|
||||||
|
Print(0, "\t", SW{30, true}, key, ":", SW{10}, mStatsSummary[key]);
|
||||||
}
|
}
|
||||||
|
Print(0, "", "runtime summary", ":");
|
||||||
|
for(std::string key: vTimesSummaryKeys) {
|
||||||
|
Print(0, "\t", SW{30, true}, key, ":", mTimesSummary[key], "s", "(", 100 * mTimesSummary[key] / duration, "%", ")");
|
||||||
|
}
|
||||||
|
Print(0, "", "end", ":", "cost", "=", cost, "(", 100 * (cost - costStart) / costStart, "%", ")", ",", "time", "=", duration, "s");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ namespace rrr {
|
||||||
int nWords;
|
int nWords;
|
||||||
|
|
||||||
// data
|
// data
|
||||||
|
bool fGenerated;
|
||||||
|
bool fInitialized;
|
||||||
int target; // node for which the careset has been computed
|
int target; // node for which the careset has been computed
|
||||||
std::vector<word> vValues;
|
std::vector<word> vValues;
|
||||||
std::vector<word> vValues2; // simulation with an inverter
|
std::vector<word> vValues2; // simulation with an inverter
|
||||||
|
|
@ -46,9 +48,14 @@ namespace rrr {
|
||||||
// backups
|
// backups
|
||||||
std::vector<Simulator> vBackups;
|
std::vector<Simulator> vBackups;
|
||||||
|
|
||||||
// statistics
|
// stats
|
||||||
int nAdds;
|
int nCex;
|
||||||
int nResets;
|
int nDiscarded;
|
||||||
|
int nPackedCountOld;
|
||||||
|
std::vector<int> vPackedCount;
|
||||||
|
std::vector<int> vPackedCountEvicted;
|
||||||
|
double durationSimulation;
|
||||||
|
double durationCare;
|
||||||
|
|
||||||
// vector computations
|
// vector computations
|
||||||
void Clear(int n, itr x) const;
|
void Clear(int n, itr x) const;
|
||||||
|
|
@ -77,6 +84,9 @@ namespace rrr {
|
||||||
// careset computation
|
// careset computation
|
||||||
void ComputeCare(int id);
|
void ComputeCare(int id);
|
||||||
|
|
||||||
|
// preparation
|
||||||
|
void Initialize();
|
||||||
|
|
||||||
// save & load
|
// save & load
|
||||||
void Save(int slot);
|
void Save(int slot);
|
||||||
void Load(int slot);
|
void Load(int slot);
|
||||||
|
|
@ -85,8 +95,7 @@ namespace rrr {
|
||||||
// constructors
|
// constructors
|
||||||
Simulator();
|
Simulator();
|
||||||
Simulator(Parameter const *pPar);
|
Simulator(Parameter const *pPar);
|
||||||
~Simulator();
|
void AssignNetwork(Ntk *pNtk_, bool fReuse);
|
||||||
void UpdateNetwork(Ntk *pNtk_, bool fSame);
|
|
||||||
|
|
||||||
// checks
|
// checks
|
||||||
bool CheckRedundancy(int id, int idx);
|
bool CheckRedundancy(int id, int idx);
|
||||||
|
|
@ -94,6 +103,11 @@ namespace rrr {
|
||||||
|
|
||||||
// cex
|
// cex
|
||||||
void AddCex(std::vector<VarValue> const &vCex);
|
void AddCex(std::vector<VarValue> const &vCex);
|
||||||
|
|
||||||
|
// summary
|
||||||
|
void ResetSummary();
|
||||||
|
summary<int> GetStatsSummary() const;
|
||||||
|
summary<double> GetTimesSummary() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -195,53 +209,71 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
void Simulator<Ntk>::ActionCallback(Action const &action) {
|
void Simulator<Ntk>::ActionCallback(Action const &action) {
|
||||||
if(target == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case REMOVE_FANIN:
|
case REMOVE_FANIN:
|
||||||
if(action.id == target) {
|
assert(fInitialized);
|
||||||
fUpdate = true;
|
if(target != -1) {
|
||||||
} else {
|
if(action.id == target) {
|
||||||
sUpdates.insert(action.id);
|
fUpdate = true;
|
||||||
|
} else {
|
||||||
|
sUpdates.insert(action.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REMOVE_UNUSED:
|
case REMOVE_UNUSED:
|
||||||
break;
|
break;
|
||||||
case REMOVE_BUFFER:
|
case REMOVE_BUFFER:
|
||||||
case REMOVE_CONST:
|
case REMOVE_CONST:
|
||||||
if(action.id == target) {
|
if(fInitialized) {
|
||||||
if(fUpdate) {
|
if(target != -1) {
|
||||||
for(int fo: action.vFanouts) {
|
if(action.id == target) {
|
||||||
sUpdates.insert(fo);
|
if(fUpdate) {
|
||||||
}
|
for(int fo: action.vFanouts) {
|
||||||
fUpdate = false;
|
sUpdates.insert(fo);
|
||||||
}
|
}
|
||||||
target = -1;
|
fUpdate = false;
|
||||||
} else {
|
}
|
||||||
if(sUpdates.count(action.id)) {
|
target = -1;
|
||||||
sUpdates.erase(action.id);
|
} else {
|
||||||
for(int fo: action.vFanouts) {
|
if(sUpdates.count(action.id)) {
|
||||||
sUpdates.insert(fo);
|
sUpdates.erase(action.id);
|
||||||
|
for(int fo: action.vFanouts) {
|
||||||
|
sUpdates.insert(fo);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ADD_FANIN:
|
case ADD_FANIN:
|
||||||
if(action.id == target) {
|
assert(fInitialized);
|
||||||
fUpdate = true;
|
if(target != -1) {
|
||||||
} else {
|
if(action.id == target) {
|
||||||
sUpdates.insert(action.id);
|
fUpdate = true;
|
||||||
|
} else {
|
||||||
|
sUpdates.insert(action.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TRIVIAL_COLLAPSE:
|
case TRIVIAL_COLLAPSE:
|
||||||
break;
|
break;
|
||||||
case TRIVIAL_DECOMPOSE:
|
case TRIVIAL_DECOMPOSE:
|
||||||
vValues.resize(nWords * pNtk->GetNumNodes());
|
if(fInitialized) {
|
||||||
SimulateNode(vValues, action.fi);
|
if(target != -1) {
|
||||||
|
vValues.resize(nWords * pNtk->GetNumNodes());
|
||||||
|
SimulateNode(vValues, action.fi);
|
||||||
|
// time of this simulation is not measured for simplicity sake
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SORT_FANINS:
|
case SORT_FANINS:
|
||||||
break;
|
break;
|
||||||
|
case READ:
|
||||||
|
fInitialized = false;
|
||||||
|
if(action.fNew) {
|
||||||
|
fGenerated = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SAVE:
|
case SAVE:
|
||||||
Save(action.idx);
|
Save(action.idx);
|
||||||
break;
|
break;
|
||||||
|
|
@ -345,6 +377,7 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
void Simulator<Ntk>::Simulate() {
|
void Simulator<Ntk>::Simulate() {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "simulating" << std::endl;
|
std::cout << "simulating" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
@ -356,10 +389,12 @@ namespace rrr {
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
durationSimulation += Duration(timeStart, GetCurrentTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
void Simulator<Ntk>::Resimulate() {
|
void Simulator<Ntk>::Resimulate() {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "resimulating" << std::endl;
|
std::cout << "resimulating" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
@ -382,10 +417,12 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
durationSimulation += Duration(timeStart, GetCurrentTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
void Simulator<Ntk>::SimulateOneWord(int offset) {
|
void Simulator<Ntk>::SimulateOneWord(int offset) {
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "simulating word " << offset << std::endl;
|
std::cout << "simulating word " << offset << std::endl;
|
||||||
}
|
}
|
||||||
|
|
@ -397,6 +434,7 @@ namespace rrr {
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
durationSimulation += Duration(timeStart, GetCurrentTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -440,6 +478,7 @@ namespace rrr {
|
||||||
sUpdates.clear();
|
sUpdates.clear();
|
||||||
}
|
}
|
||||||
target = id;
|
target = id;
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "computing careset of " << target << std::endl;
|
std::cout << "computing careset of " << target << std::endl;
|
||||||
}
|
}
|
||||||
|
|
@ -450,6 +489,7 @@ namespace rrr {
|
||||||
Print(nWords, care.begin());
|
Print(nWords, care.begin());
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
durationCare += Duration(timeStart, GetCurrentTime());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
vValues2 = vValues;
|
vValues2 = vValues;
|
||||||
|
|
@ -484,6 +524,36 @@ namespace rrr {
|
||||||
Print(nWords, care.begin());
|
Print(nWords, care.begin());
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
durationCare += Duration(timeStart, GetCurrentTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ Preparation */
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
void Simulator<Ntk>::Initialize() {
|
||||||
|
if(!fGenerated) {
|
||||||
|
// TODO: reset nWords to default here maybe, if such a mechanism that changes nWords has been implemneted
|
||||||
|
vValues.resize(nWords * pNtk->GetNumNodes());
|
||||||
|
iPivot = 0;
|
||||||
|
vAssignedStimuli.clear();
|
||||||
|
vAssignedStimuli.resize(nWords * pNtk->GetNumPis());
|
||||||
|
for(int count: vPackedCount) {
|
||||||
|
if(count) {
|
||||||
|
vPackedCountEvicted.push_back(count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vPackedCount.clear();
|
||||||
|
vPackedCount.resize(nWords * 64);
|
||||||
|
GenerateRandomStimuli();
|
||||||
|
fGenerated = true;
|
||||||
|
} else {
|
||||||
|
// use same nWords as we are reusing patterns even if nWords has changed
|
||||||
|
vValues.resize(nWords * pNtk->GetNumNodes());
|
||||||
|
}
|
||||||
|
Simulate();
|
||||||
|
fInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -517,6 +587,12 @@ namespace rrr {
|
||||||
vBackups[slot].iPivot = iPivot;
|
vBackups[slot].iPivot = iPivot;
|
||||||
vBackups[slot].vAssignedStimuli = vAssignedStimuli;
|
vBackups[slot].vAssignedStimuli = vAssignedStimuli;
|
||||||
target = vBackups[slot].target; // assigned to -1 when careset needs updating
|
target = vBackups[slot].target; // assigned to -1 when careset needs updating
|
||||||
|
if(!fKeepStimula) {
|
||||||
|
vBackups[slot].nCex = nCex;
|
||||||
|
vBackups[slot].nPackedCountOld = nPackedCountOld;
|
||||||
|
vBackups[slot].vPackedCount = vPackedCount;
|
||||||
|
vBackups[slot].vPackedCountEvicted = vPackedCountEvicted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
|
|
@ -532,6 +608,11 @@ namespace rrr {
|
||||||
care = vBackups[slot].care;
|
care = vBackups[slot].care;
|
||||||
iPivot = vBackups[slot].iPivot;
|
iPivot = vBackups[slot].iPivot;
|
||||||
vAssignedStimuli = vBackups[slot].vAssignedStimuli;
|
vAssignedStimuli = vBackups[slot].vAssignedStimuli;
|
||||||
|
nDiscarded += nCex - vBackups[slot].nCex;
|
||||||
|
nCex = vBackups[slot].nCex;
|
||||||
|
nPackedCountOld = vBackups[slot].nPackedCountOld;
|
||||||
|
vPackedCount = vBackups[slot].vPackedCount;
|
||||||
|
vPackedCountEvicted = vBackups[slot].vPackedCountEvicted;
|
||||||
tmp.resize(nWords);
|
tmp.resize(nWords);
|
||||||
} else {
|
} else {
|
||||||
std::vector<int> vOffsets;
|
std::vector<int> vOffsets;
|
||||||
|
|
@ -567,7 +648,7 @@ namespace rrr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// when nWords has changed
|
// TODO: when nWords has changed
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -582,11 +663,12 @@ namespace rrr {
|
||||||
pNtk(NULL),
|
pNtk(NULL),
|
||||||
nVerbose(0),
|
nVerbose(0),
|
||||||
nWords(0),
|
nWords(0),
|
||||||
|
fGenerated(false),
|
||||||
|
fInitialized(false),
|
||||||
target(-1),
|
target(-1),
|
||||||
iPivot(0),
|
iPivot(0),
|
||||||
fUpdate(false),
|
fUpdate(false) {
|
||||||
nAdds(0),
|
ResetSummary();
|
||||||
nResets(0) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
|
|
@ -594,38 +676,27 @@ namespace rrr {
|
||||||
pNtk(NULL),
|
pNtk(NULL),
|
||||||
nVerbose(pPar->nSimulatorVerbose),
|
nVerbose(pPar->nSimulatorVerbose),
|
||||||
nWords(pPar->nWords),
|
nWords(pPar->nWords),
|
||||||
|
fGenerated(false),
|
||||||
|
fInitialized(false),
|
||||||
target(-1),
|
target(-1),
|
||||||
iPivot(0),
|
iPivot(0),
|
||||||
fUpdate(false),
|
fUpdate(false) {
|
||||||
nAdds(0),
|
|
||||||
nResets(0) {
|
|
||||||
care.resize(nWords);
|
care.resize(nWords);
|
||||||
tmp.resize(nWords);
|
tmp.resize(nWords);
|
||||||
|
ResetSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
Simulator<Ntk>::~Simulator() {
|
void Simulator<Ntk>::AssignNetwork(Ntk *pNtk_, bool fReuse) {
|
||||||
if(pNtk) {
|
if(!fReuse) {
|
||||||
std::cout << "simulator stats: added CEXs = " << nAdds << ", resets = " << nResets << std::endl;
|
fGenerated = false;
|
||||||
}
|
}
|
||||||
}
|
fInitialized = false;
|
||||||
|
|
||||||
template <typename Ntk>
|
|
||||||
void Simulator<Ntk>::UpdateNetwork(Ntk *pNtk_, bool fSame) {
|
|
||||||
pNtk = pNtk_;
|
|
||||||
pNtk->AddCallback(std::bind(&Simulator<Ntk>::ActionCallback, this, std::placeholders::_1));
|
|
||||||
// TODO: what if nWords has changed? shall we reset it to default?
|
|
||||||
vValues.resize(nWords * pNtk->GetNumNodes());
|
|
||||||
target = -1;
|
target = -1;
|
||||||
fUpdate = false;
|
fUpdate = false;
|
||||||
sUpdates.clear();
|
sUpdates.clear();
|
||||||
if(!fSame) { // reset stimuli if network function changed
|
pNtk = pNtk_;
|
||||||
iPivot = 0;
|
pNtk->AddCallback(std::bind(&Simulator<Ntk>::ActionCallback, this, std::placeholders::_1));
|
||||||
vAssignedStimuli.clear();
|
|
||||||
vAssignedStimuli.resize(nWords * pNtk->GetNumPis());
|
|
||||||
GenerateRandomStimuli();
|
|
||||||
}
|
|
||||||
Simulate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
@ -634,6 +705,9 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
bool Simulator<Ntk>::CheckRedundancy(int id, int idx) {
|
bool Simulator<Ntk>::CheckRedundancy(int id, int idx) {
|
||||||
|
if(!fInitialized) {
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
ComputeCare(id);
|
ComputeCare(id);
|
||||||
switch(pNtk->GetNodeType(id)) {
|
switch(pNtk->GetNodeType(id)) {
|
||||||
case AND: {
|
case AND: {
|
||||||
|
|
@ -671,6 +745,9 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename Ntk>
|
template <typename Ntk>
|
||||||
bool Simulator<Ntk>::CheckFeasibility(int id, int fi, bool c) {
|
bool Simulator<Ntk>::CheckFeasibility(int id, int fi, bool c) {
|
||||||
|
if(!fInitialized) {
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
ComputeCare(id);
|
ComputeCare(id);
|
||||||
switch(pNtk->GetNodeType(id)) {
|
switch(pNtk->GetNodeType(id)) {
|
||||||
case AND: {
|
case AND: {
|
||||||
|
|
@ -768,6 +845,7 @@ namespace rrr {
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "fusing into stimulus word " << iWord << " bit " << iBit << std::endl;
|
std::cout << "fusing into stimulus word " << iWord << " bit " << iBit << std::endl;
|
||||||
}
|
}
|
||||||
|
vPackedCount[iWord * 64 + iBit]++;
|
||||||
} else {
|
} else {
|
||||||
// no bits are compatible, so reset at pivot
|
// no bits are compatible, so reset at pivot
|
||||||
iWord = iPivot / 64;
|
iWord = iPivot / 64;
|
||||||
|
|
@ -775,6 +853,11 @@ namespace rrr {
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "resetting stimulus word " << iWord << " bit " << iBit << std::endl;
|
std::cout << "resetting stimulus word " << iWord << " bit " << iBit << std::endl;
|
||||||
}
|
}
|
||||||
|
if(vPackedCount[iWord * 64 + iBit]) {
|
||||||
|
// this can be zero only when stats has been reset
|
||||||
|
vPackedCountEvicted.push_back(vPackedCount[iWord * 64 + iBit]);
|
||||||
|
}
|
||||||
|
vPackedCount[iWord * 64 + iBit] = 1;
|
||||||
word mask = 1ull << iBit;
|
word mask = 1ull << iBit;
|
||||||
for(int idx = 0; idx < pNtk->GetNumPis(); idx++) {
|
for(int idx = 0; idx < pNtk->GetNumPis(); idx++) {
|
||||||
vAssignedStimuli[idx * nWords + iWord] &= ~mask;
|
vAssignedStimuli[idx * nWords + iWord] &= ~mask;
|
||||||
|
|
@ -783,7 +866,6 @@ namespace rrr {
|
||||||
if(iPivot == 64 * nWords) {
|
if(iPivot == 64 * nWords) {
|
||||||
iPivot = 0;
|
iPivot = 0;
|
||||||
}
|
}
|
||||||
nResets++;
|
|
||||||
}
|
}
|
||||||
// update stimulus
|
// update stimulus
|
||||||
for(int idx: vCarePiIdxs) {
|
for(int idx: vCarePiIdxs) {
|
||||||
|
|
@ -808,6 +890,7 @@ namespace rrr {
|
||||||
// simulate
|
// simulate
|
||||||
SimulateOneWord(iWord);
|
SimulateOneWord(iWord);
|
||||||
// recompute care with new stimulus
|
// recompute care with new stimulus
|
||||||
|
time_point timeStart = GetCurrentTime();
|
||||||
if(target != -1 && !pNtk->IsPoDriver(target)) {
|
if(target != -1 && !pNtk->IsPoDriver(target)) {
|
||||||
if(nVerbose) {
|
if(nVerbose) {
|
||||||
std::cout << "recomputing careset of " << target << std::endl;
|
std::cout << "recomputing careset of " << target << std::endl;
|
||||||
|
|
@ -838,11 +921,57 @@ namespace rrr {
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nAdds++;
|
durationCare += Duration(timeStart, GetCurrentTime());
|
||||||
|
nCex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ Summary */
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
void Simulator<Ntk>::ResetSummary() {
|
||||||
|
nCex = 0;
|
||||||
|
nDiscarded = 0;
|
||||||
|
nPackedCountOld = 0;
|
||||||
|
for(int count: vPackedCount) {
|
||||||
|
if(count) {
|
||||||
|
nPackedCountOld++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vPackedCountEvicted.clear();
|
||||||
|
durationSimulation = 0;
|
||||||
|
durationCare = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
summary<int> Simulator<Ntk>::GetStatsSummary() const {
|
||||||
|
summary<int> v;
|
||||||
|
v.emplace_back("sim cex", nCex);
|
||||||
|
if(!fKeepStimula) {
|
||||||
|
v.emplace_back("sim discarded cex", nDiscarded);
|
||||||
|
}
|
||||||
|
int nPackedCount = vPackedCountEvicted.size() - nPackedCountOld;
|
||||||
|
for(int count: vPackedCount) {
|
||||||
|
if(count) {
|
||||||
|
nPackedCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.emplace_back("sim packed pattern", nPackedCount);
|
||||||
|
v.emplace_back("sim evicted pattern", vPackedCountEvicted.size());
|
||||||
|
return v;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Ntk>
|
||||||
|
summary<double> Simulator<Ntk>::GetTimesSummary() const {
|
||||||
|
summary<double> v;
|
||||||
|
v.emplace_back("sim simulation", durationSimulation);
|
||||||
|
v.emplace_back("sim care computation", durationCare);
|
||||||
|
return v;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ABC_NAMESPACE_CXX_HEADER_END
|
ABC_NAMESPACE_CXX_HEADER_END
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ namespace rrr {
|
||||||
TRIVIAL_COLLAPSE,
|
TRIVIAL_COLLAPSE,
|
||||||
TRIVIAL_DECOMPOSE,
|
TRIVIAL_DECOMPOSE,
|
||||||
SORT_FANINS,
|
SORT_FANINS,
|
||||||
|
READ,
|
||||||
SAVE,
|
SAVE,
|
||||||
LOAD,
|
LOAD,
|
||||||
POP_BACK,
|
POP_BACK,
|
||||||
|
|
@ -51,6 +52,7 @@ namespace rrr {
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
int fi = -1;
|
int fi = -1;
|
||||||
bool c = false;
|
bool c = false;
|
||||||
|
bool fNew = false;
|
||||||
std::vector<int> vFanins;
|
std::vector<int> vFanins;
|
||||||
std::vector<int> vIndices;
|
std::vector<int> vIndices;
|
||||||
std::vector<int> vFanouts;
|
std::vector<int> vFanouts;
|
||||||
|
|
@ -60,6 +62,9 @@ namespace rrr {
|
||||||
using clock_type = std::chrono::steady_clock;
|
using clock_type = std::chrono::steady_clock;
|
||||||
using time_point = std::chrono::time_point<clock_type>;
|
using time_point = std::chrono::time_point<clock_type>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using summary = std::vector<std::pair<std::string, T>>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ABC_NAMESPACE_CXX_HEADER_END
|
ABC_NAMESPACE_CXX_HEADER_END
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,8 @@ namespace rrr {
|
||||||
/* {{{ Print next */
|
/* {{{ Print next */
|
||||||
|
|
||||||
struct SW {
|
struct SW {
|
||||||
int width;
|
int width = 0;
|
||||||
|
bool left = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NS {}; // no space
|
struct NS {}; // no space
|
||||||
|
|
@ -107,6 +108,16 @@ namespace rrr {
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
void PrintNext(std::ostream &os, T t, Args... args);
|
void PrintNext(std::ostream &os, T t, Args... args);
|
||||||
|
|
||||||
|
static inline void PrintNext(std::ostream &os, int t) {
|
||||||
|
os << std::setw(4) << t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
static inline void PrintNext(std::ostream &os, int t, Args... args) {
|
||||||
|
os << std::setw(4) << t << " ";
|
||||||
|
PrintNext(os, args...);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void PrintNext(std::ostream &os, bool arg) {
|
static inline void PrintNext(std::ostream &os, bool arg) {
|
||||||
os << arg;
|
os << arg;
|
||||||
}
|
}
|
||||||
|
|
@ -121,16 +132,6 @@ namespace rrr {
|
||||||
PrintNext(os, args...);
|
PrintNext(os, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void PrintNext(std::ostream &os, int t) {
|
|
||||||
os << std::setw(4) << t;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
static inline void PrintNext(std::ostream &os, int t, Args... args) {
|
|
||||||
os << std::setw(4) << t << " ";
|
|
||||||
PrintNext(os, args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void PrintNext(std::ostream &os, double t) {
|
static inline void PrintNext(std::ostream &os, double t) {
|
||||||
os << std::fixed << std::setprecision(2) << std::setw(8) << t;
|
os << std::fixed << std::setprecision(2) << std::setw(8) << t;
|
||||||
}
|
}
|
||||||
|
|
@ -143,12 +144,24 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline void PrintNext(std::ostream &os, SW sw, T arg) {
|
static inline void PrintNext(std::ostream &os, SW sw, T arg) {
|
||||||
|
if(sw.left) {
|
||||||
|
os << std::left;
|
||||||
|
}
|
||||||
os << std::setw(sw.width) << arg;
|
os << std::setw(sw.width) << arg;
|
||||||
|
if(sw.left) {
|
||||||
|
os << std::right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
static inline void PrintNext(std::ostream &os, SW sw, T arg, Args... args) {
|
static inline void PrintNext(std::ostream &os, SW sw, T arg, Args... args) {
|
||||||
|
if(sw.left) {
|
||||||
|
os << std::left;
|
||||||
|
}
|
||||||
os << std::setw(sw.width) << arg << " ";
|
os << std::setw(sw.width) << arg << " ";
|
||||||
|
if(sw.left) {
|
||||||
|
os << std::right;
|
||||||
|
}
|
||||||
PrintNext(os, args...);
|
PrintNext(os, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -161,24 +174,20 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline void PrintNext(std::ostream& os, std::vector<T> const &arg) {
|
static inline void PrintNext(std::ostream& os, std::vector<T> const &arg) {
|
||||||
std::string delim;
|
os << "[ ";
|
||||||
os << "[";
|
|
||||||
for(T const &e: arg) {
|
for(T const &e: arg) {
|
||||||
os << delim;
|
|
||||||
PrintNext(os, e);
|
PrintNext(os, e);
|
||||||
delim = ", ";
|
os << " ";
|
||||||
}
|
}
|
||||||
os << "]";
|
os << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
static inline void PrintNext(std::ostream& os, std::vector<T> const &arg, Args... args) {
|
static inline void PrintNext(std::ostream& os, std::vector<T> const &arg, Args... args) {
|
||||||
std::string delim;
|
os << "[ ";
|
||||||
os << "[";
|
|
||||||
for(T const &e: arg) {
|
for(T const &e: arg) {
|
||||||
os << delim;
|
|
||||||
PrintNext(os, e);
|
PrintNext(os, e);
|
||||||
delim = ", ";
|
os << " ";
|
||||||
}
|
}
|
||||||
os << "] ";
|
os << "] ";
|
||||||
PrintNext(os, args...);
|
PrintNext(os, args...);
|
||||||
|
|
@ -186,24 +195,20 @@ namespace rrr {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline void PrintNext(std::ostream& os, std::set<T> const &arg) {
|
static inline void PrintNext(std::ostream& os, std::set<T> const &arg) {
|
||||||
std::string delim;
|
os << "{ ";
|
||||||
os << "{";
|
|
||||||
for(T const &e: arg) {
|
for(T const &e: arg) {
|
||||||
os << delim;
|
|
||||||
PrintNext(os, e);
|
PrintNext(os, e);
|
||||||
delim = ", ";
|
os << " ";
|
||||||
}
|
}
|
||||||
os << "}";
|
os << "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
static inline void PrintNext(std::ostream& os, std::set<T> const &arg, Args... args) {
|
static inline void PrintNext(std::ostream& os, std::set<T> const &arg, Args... args) {
|
||||||
std::string delim;
|
os << "{ ";
|
||||||
os << "{";
|
|
||||||
for(T const &e: arg) {
|
for(T const &e: arg) {
|
||||||
os << delim;
|
|
||||||
PrintNext(os, e);
|
PrintNext(os, e);
|
||||||
delim = ", ";
|
os << " ";
|
||||||
}
|
}
|
||||||
os << "} ";
|
os << "} ";
|
||||||
PrintNext(os, args...);
|
PrintNext(os, args...);
|
||||||
|
|
@ -222,6 +227,14 @@ namespace rrr {
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ Print others */
|
||||||
|
|
||||||
|
static inline void PrintWarning(std::string message) {
|
||||||
|
std::cerr << "[w] " << message << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ Combination */
|
/* {{{ Combination */
|
||||||
|
|
||||||
bool ForEachCombinationStopRec(std::vector<int> &v, int n, int k, std::function<bool(std::vector<int> const &)> const &func) {
|
bool ForEachCombinationStopRec(std::vector<int> &v, int n, int k, std::function<bool(std::vector<int> const &)> const &func) {
|
||||||
|
|
@ -306,6 +319,8 @@ namespace rrr {
|
||||||
return "trivial decompose";
|
return "trivial decompose";
|
||||||
case SORT_FANINS:
|
case SORT_FANINS:
|
||||||
return "sort fanins";
|
return "sort fanins";
|
||||||
|
case READ:
|
||||||
|
return "read";
|
||||||
case SAVE:
|
case SAVE:
|
||||||
return "save";
|
return "save";
|
||||||
case LOAD:
|
case LOAD:
|
||||||
|
|
@ -323,32 +338,35 @@ namespace rrr {
|
||||||
static inline std::stringstream GetActionDescription(Action const &action) {
|
static inline std::stringstream GetActionDescription(Action const &action) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << GetActionTypeCstr(action);
|
ss << GetActionTypeCstr(action);
|
||||||
std::string delim = ": ";
|
std::string delim = " : ";
|
||||||
if(action.id != -1) {
|
if(action.id != -1) {
|
||||||
ss << delim;
|
ss << delim;
|
||||||
PrintNext(ss, "node", action.id);
|
PrintNext(ss, "node", action.id);
|
||||||
delim = ", ";
|
delim = " , ";
|
||||||
}
|
}
|
||||||
if(action.fi != -1) {
|
if(action.fi != -1) {
|
||||||
ss << delim;
|
ss << delim;
|
||||||
PrintNext(ss, "fanin", (bool)action.c, action.fi);
|
PrintNext(ss, "fanin", (bool)action.c, action.fi);
|
||||||
delim = ", ";
|
delim = " , ";
|
||||||
}
|
}
|
||||||
if(action.idx != -1) {
|
if(action.idx != -1) {
|
||||||
ss << delim;
|
ss << delim;
|
||||||
PrintNext(ss, "index", action.idx);
|
PrintNext(ss, "index", action.idx);
|
||||||
}
|
}
|
||||||
|
if(action.fNew) {
|
||||||
|
ss << " new";
|
||||||
|
}
|
||||||
ss << std::endl;
|
ss << std::endl;
|
||||||
if(!action.vFanins.empty()) {
|
if(!action.vFanins.empty()) {
|
||||||
ss << "fanins: ";
|
ss << "fanins : ";
|
||||||
PrintNext(ss, action.vFanins);
|
PrintNext(ss, action.vFanins);
|
||||||
}
|
}
|
||||||
if(!action.vIndices.empty()) {
|
if(!action.vIndices.empty()) {
|
||||||
ss << "indices: ";
|
ss << "indices : ";
|
||||||
PrintNext(ss, action.vIndices);
|
PrintNext(ss, action.vIndices);
|
||||||
}
|
}
|
||||||
if(!action.vFanouts.empty()) {
|
if(!action.vFanouts.empty()) {
|
||||||
ss << "fanouts: ";
|
ss << "fanouts : ";
|
||||||
PrintNext(ss, action.vFanouts);
|
PrintNext(ss, action.vFanouts);
|
||||||
}
|
}
|
||||||
return ss;
|
return ss;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue