version 3 with more ABC commands

noah
panhongyang 2023-11-16 17:05:40 +08:00
parent 90b00aa4bc
commit 1f63163872
47 changed files with 338898 additions and 82 deletions

BIN
src/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -2,7 +2,7 @@
* Copyright (C) 2023 */ * Copyright (C) 2023 */
/** /**
* @file get.hpp * @file &get.hpp
* *
* @brief converts the current network into GIA * @brief converts the current network into GIA
* *

92
src/commands/abc/&if.hpp Normal file
View File

@ -0,0 +1,92 @@
/* LogicMap: powerful technology-mapping tool in logic synthesis
* Copyright (C) 2023 */
/**
* @file &if.hpp
*
* @brief performs FPGA mapping of the GIA
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef ABC_GIA_IF_HPP
#define ABC_GIA_IF_HPP
#include "aig/gia/gia.h"
#include "base/abc/abc.h"
using namespace mockturtle;
using namespace std;
using namespace pabc;
namespace alice {
class Aif_command : public command {
public:
explicit Aif_command(const environment::ptr &env)
: command(env, "performs FPGA mapping of the AIG") {
add_flag("--verbose, -v", "print the information");
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
Gia_Man_t *pGia, *pNew;
If_Par_t Pars, *pPars = &Pars;
Gia_ManSetIfParsDefault(pPars);
if (store<pabc::Gia_Man_t *>().size() == 0u)
std::cerr << "Error: Empty GIA network.\n";
else {
pGia = store<pabc::Gia_Man_t *>().current();
// set defaults
pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut();
if (Gia_ManHasMapping(pGia)) {
printf("Current AIG has mapping. Run \"&st\".\n");
return;
}
if (pPars->nLutSize == -1) {
if (pPars->pLutLib == NULL) {
printf("The LUT library is not given.\n");
return;
}
pPars->nLutSize = pPars->pLutLib->LutMax;
}
if (pPars->nLutSize < 2 || pPars->nLutSize > IF_MAX_LUTSIZE) {
printf("Incorrect LUT size (%d).\n", pPars->nLutSize);
return;
}
if (pPars->nCutsMax < 1 || pPars->nCutsMax >= (1 << 12)) {
printf("Incorrect number of cuts.\n");
return;
}
// get the new network
pNew = Gia_ManPerformMapping(pGia, pPars);
if (pNew == NULL) {
printf("Mapping of GIA has failed..\n");
return;
}
store<pabc::Gia_Man_t *>().extend();
store<pabc::Gia_Man_t *>().current() = pNew;
}
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
private:
};
ALICE_ADD_COMMAND(Aif, "Gia")
} // namespace alice
#endif

72
src/commands/abc/&nf.hpp Normal file
View File

@ -0,0 +1,72 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file &nf.hpp
*
* @brief performs technology-independent mapping of the GIA
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef ABC_NF_HPP
#define ABC_NF_HPP
#include "aig/gia/gia.h"
#include "base/abc/abc.h"
#include "aig/gia/giaNf.c"
using namespace mockturtle;
using namespace std;
using namespace pabc;
namespace alice {
class Anf_command : public command {
public:
explicit Anf_command(const environment::ptr &env)
: command(env, "performs technology mapping of the GIA network") {
add_flag("--verbose, -v", "print the information");
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
char Buffer[200];
pabc::Jf_Par_t Pars, *pPars = &Pars;
pabc::Gia_Man_t *pGia, *pNew;
pabc::Nf_ManSetDefaultPars(pPars);
if (store<pabc::Gia_Man_t *>().size() == 0u)
std::cerr << "Error: Empty GIA network.\n";
else {
pGia = store<pabc::Gia_Man_t *>().current();
if (pabc::Abc_FrameReadLibGen() == NULL) {
pabc::Abc_Print(-1, "Current library is not available.\n");
return;
}
pNew = pabc::Nf_ManPerformMapping(pGia, pPars);
store<pabc::Gia_Man_t *>().extend();
store<pabc::Gia_Man_t *>().current() = pNew;
}
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
private:
};
ALICE_ADD_COMMAND(Anf, "Gia")
} // namespace alice
#endif

105
src/commands/abc/amap.hpp Normal file
View File

@ -0,0 +1,105 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file amap.hpp
*
* @brief performs technology-independent mapping of the AIG
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef ABC_AMAP_HPP
#define ABC_AMAP_HPP
#include "map/amap/amap.h"
#include "base/abc/abc.h"
#include "base/abci/abcSweep.c"
using namespace mockturtle;
using namespace std;
using namespace pabc;
namespace alice {
class amap_command : public command {
public:
explicit amap_command(const environment::ptr &env)
: command(env, "performs standard cell mapping of the current network") {
add_flag("--verbose, -v", "print the information");
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
if (store<pabc::Abc_Ntk_t *>().size() == 0u)
std::cerr << "Error: Empty ABC AIG network\n";
else {
Abc_Ntk_t *pNtk = store<pabc::Abc_Ntk_t *>().current();
// set defaults
Amap_Par_t Pars, *pPars = &Pars;
Abc_Ntk_t *pNtkRes;
int fSweep = 0;
Amap_ManSetDefaultParams(pPars);
if (!Abc_NtkIsStrash(pNtk)) {
pNtk = Abc_NtkStrash(pNtk, 0, 0, 0);
if (pNtk == NULL) {
printf("Strashing before mapping has failed.\n");
return;
}
pNtk = Abc_NtkBalance(pNtkRes = pNtk, 0, 0, 1);
Abc_NtkDelete(pNtkRes);
if (pNtk == NULL) {
printf("Balancing before mapping has failed.\n");
return;
}
printf("The network was strashed and balanced before mapping.\n");
// get the new network
pNtkRes = Abc_NtkDarAmap(pNtk, pPars);
if (pNtkRes == NULL) {
Abc_NtkDelete(pNtk);
printf("Mapping has failed.\n");
return;
}
Abc_NtkDelete(pNtk);
} else {
// get the new network
pNtkRes = Abc_NtkDarAmap(pNtk, pPars);
if (pNtkRes == NULL) {
printf("Mapping has failed.\n");
return;
}
}
if (fSweep) {
Abc_NtkFraigSweep(pNtkRes, 0, 0, 0, 0);
if (Abc_NtkHasMapping(pNtkRes)) {
pNtkRes = Abc_NtkDupDfs(pNtk = pNtkRes);
Abc_NtkDelete(pNtk);
}
}
store<pabc::Abc_Ntk_t *>().extend();
store<pabc::Abc_Ntk_t *>().current() = pNtkRes;
}
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
private:
};
ALICE_ADD_COMMAND(amap, "ABC")
} // namespace alice
#endif

View File

@ -0,0 +1,107 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file balance.hpp
*
* @brief transforms the current network into a well-balanced AIG
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef ABC_BALANCE_HPP
#define ABC_BALANCE_HPP
// #include "base/abci/abc.c"
#include "base/abc/abc.h"
#include "base/abci/abcBalance.c"
using namespace std;
using namespace mockturtle;
using namespace pabc;
namespace alice {
class abalance_command : public command {
public:
explicit abalance_command(const environment::ptr &env)
: command(env,
"transforms the current network into a well-balanced AIG") {
add_flag("--verbose, -v", "print the information");
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
if (store<pabc::Abc_Ntk_t *>().size() == 0u)
std::cerr << "Error: Empty AIG network.\n";
else {
Abc_Ntk_t *pNtk, *pNtkRes, *pNtkTemp;
pNtk = store<pabc::Abc_Ntk_t *>().current();
int c;
int fDuplicate;
int fSelective;
int fUpdateLevel;
int fExor;
int fVerbose;
// set defaults
fDuplicate = 0;
fSelective = 0;
fUpdateLevel = 1;
fExor = 0;
fVerbose = 0;
Extra_UtilGetoptReset();
if (pNtk == NULL) {
Abc_Print(-1, "Empty network.\n");
return;
}
// get the new network
if (Abc_NtkIsStrash(pNtk)) {
if (fExor)
pNtkRes = Abc_NtkBalanceExor(pNtk, fUpdateLevel, fVerbose);
else
pNtkRes = Abc_NtkBalance(pNtk, fDuplicate, fSelective, fUpdateLevel);
} else {
pNtkTemp = Abc_NtkStrash(pNtk, 0, 0, 0);
if (pNtkTemp == NULL) {
Abc_Print(-1, "Strashing before balancing has failed.\n");
return;
}
if (fExor)
pNtkRes = Abc_NtkBalanceExor(pNtkTemp, fUpdateLevel, fVerbose);
else
pNtkRes =
Abc_NtkBalance(pNtkTemp, fDuplicate, fSelective, fUpdateLevel);
Abc_NtkDelete(pNtkTemp);
}
// check if balancing worked
if (pNtkRes == NULL) {
Abc_Print(-1, "Balancing has failed.\n");
return;
}
// replace the current network
// Abc_FrameReplaceCurrentNetwork(pAbc, pNtkRes);
store<pabc::Abc_Ntk_t *>().extend();
store<pabc::Abc_Ntk_t *>().current() = pNtkRes;
}
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
private:
};
ALICE_ADD_COMMAND(abalance, "ABC")
} // namespace alice
#endif

View File

@ -77,7 +77,7 @@ class acec_command : public command {
string filename_2; string filename_2;
}; };
ALICE_ADD_COMMAND(acec, "Verification") ALICE_ADD_COMMAND(acec, "ABC")
} // namespace alice } // namespace alice

View File

@ -0,0 +1,290 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file compress2rs.hpp
*
* @brief combination optimization script
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef COMPRESS2RS_HPP
#define COMPRESS2RS_HPP
// #include "base/abci/abc.c"
#include "base/abc/abc.h"
// #include "base/abci/abcDar.c"
#include "base/abci/abcResub.c"
using namespace std;
using namespace mockturtle;
using namespace pabc;
namespace alice {
class compress2rs_command : public command {
public:
explicit compress2rs_command(const environment::ptr &env)
: command(env, "usage: synthesis scripts.") {
add_flag("--verbose, -v", "print the information");
}
public:
void Dar_ManDefaultResParams(Dar_ResPar_t *pPars) {
memset(pPars, 0, sizeof(Dar_ResPar_t));
pPars->nCutsMax = 8; // 8
pPars->nNodesMax = 1;
pPars->nLevelsOdc = 0;
pPars->fUpdateLevel = 1;
pPars->fUseZeros = 0;
pPars->fVerbose = 0;
pPars->fVeryVerbose = 0;
}
Aig_Man_t *Dar_ManCompress2rs(Abc_Ntk_t *pNtk, Aig_Man_t *pAig, int fBalance,
int fUpdateLevel, int fFanout, int fPower,
int fVerbose, int nMinSaved) {
// alias compress2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs
// -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10
// -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l"
Aig_Man_t *pTemp;
Abc_Ntk_t *pNtkAig;
Dar_RwrPar_t ParsRwr, *pParsRwr = &ParsRwr;
Dar_RefPar_t ParsRef, *pParsRef = &ParsRef;
Dar_ResPar_t ParsRes, *pParsRes = &ParsRes;
Dar_ManDefaultRwrParams(pParsRwr);
Dar_ManDefaultRefParams(pParsRef);
Dar_ManDefaultResParams(pParsRes);
pParsRwr->fUpdateLevel = fUpdateLevel;
pParsRef->fUpdateLevel = fUpdateLevel;
pParsRes->fUpdateLevel = fUpdateLevel;
// pParsRes->nCutsMax = nCutsMax;
// pParsRes->nNodesMax = nNodesMax;
pParsRwr->fFanout = fFanout;
pParsRwr->fPower = fPower;
pParsRwr->fVerbose = 0; // fVerbose;
pParsRef->fVerbose = 0; // fVerbose;
pParsRes->fVerbose = 0; // fVerbose;
pAig = Aig_ManDupDfs(pAig);
if (fVerbose) printf("Starting: "), Aig_ManPrintStats(pAig);
// b -l;
fUpdateLevel = 0;
pAig = Dar_ManBalance(pTemp = pAig, fUpdateLevel);
Aig_ManStop(pTemp);
if (fVerbose) printf("Balance: "), Aig_ManPrintStats(pAig);
// rs -K 6 -l;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 6;
pParsRes->fUpdateLevel = 0;
pParsRes->nNodesMax = 1;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// rw -l;
pParsRwr->fUpdateLevel = 0;
Dar_ManRewrite(pAig, pParsRwr);
pAig = Aig_ManDupDfs(pTemp = pAig);
Aig_ManStop(pTemp);
if (fVerbose) printf("Rewrite: "), Aig_ManPrintStats(pAig);
// rs -K 6 -N 2 -l;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 6;
pParsRes->fUpdateLevel = 0;
pParsRes->nNodesMax = 2;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// rf -l;
pParsRef->fUpdateLevel = 0;
Dar_ManRefactor(pAig, pParsRef);
pAig = Aig_ManDupDfs(pTemp = pAig);
Aig_ManStop(pTemp);
if (fVerbose) printf("Refactor: "), Aig_ManPrintStats(pAig);
// rs -K 8 -l;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 8;
pParsRes->fUpdateLevel = 0;
pParsRes->nNodesMax = 1;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// b -l;
fUpdateLevel = 0;
pAig = Dar_ManBalance(pTemp = pAig, fUpdateLevel);
Aig_ManStop(pTemp);
if (fVerbose) printf("Balance: "), Aig_ManPrintStats(pAig);
// rs -K 8 -N 2 -l;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 8;
pParsRes->fUpdateLevel = 0;
pParsRes->nNodesMax = 2;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// rw -l;
pParsRwr->fUpdateLevel = 0;
Dar_ManRewrite(pAig, pParsRwr);
pAig = Aig_ManDupDfs(pTemp = pAig);
Aig_ManStop(pTemp);
if (fVerbose) printf("Rewrite: "), Aig_ManPrintStats(pAig);
// rs -K 10 -l;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 10;
pParsRes->fUpdateLevel = 0;
pParsRes->nNodesMax = 1;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// rwz -l;
pParsRwr->fUpdateLevel = 0;
pParsRwr->fUseZeros = 1;
Dar_ManRewrite(pAig, pParsRwr);
pAig = Aig_ManDupDfs(pTemp = pAig);
Aig_ManStop(pTemp);
if (fVerbose) printf("Rewrite_zerocost: "), Aig_ManPrintStats(pAig);
// rs -K 10 -N 2 -l;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 10;
pParsRes->fUpdateLevel = 0;
pParsRes->nNodesMax = 2;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// b -l;
fUpdateLevel = 0;
pAig = Dar_ManBalance(pTemp = pAig, fUpdateLevel);
Aig_ManStop(pTemp);
if (fVerbose) printf("Balance: "), Aig_ManPrintStats(pAig);
// rs -K 12 -l;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 12;
pParsRes->fUpdateLevel = 0;
pParsRes->nNodesMax = 1;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// rfz -l;
pParsRef->fUpdateLevel = 0;
pParsRef->fUseZeros = 1;
Dar_ManRefactor(pAig, pParsRef);
pAig = Aig_ManDupDfs(pTemp = pAig);
Aig_ManStop(pTemp);
if (fVerbose) printf("Refactor_zerocost: "), Aig_ManPrintStats(pAig);
// rs -K 12 -N 2 -l;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 12;
pParsRes->fUpdateLevel = 0;
pParsRes->nNodesMax = 2;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// rwz -l;
pParsRwr->fUpdateLevel = 0;
pParsRwr->fUseZeros = 1;
Dar_ManRewrite(pAig, pParsRwr);
pAig = Aig_ManDupDfs(pTemp = pAig);
Aig_ManStop(pTemp);
if (fVerbose) printf("Rewrite_zerocost: "), Aig_ManPrintStats(pAig);
// b -l;
fUpdateLevel = 0;
pAig = Dar_ManBalance(pTemp = pAig, fUpdateLevel);
Aig_ManStop(pTemp);
if (fVerbose) printf("Balance: "), Aig_ManPrintStats(pAig);
return pAig;
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
if (store<pabc::Abc_Ntk_t *>().size() == 0u)
std::cerr << "Error: Empty AIG network.\n";
else {
Abc_Ntk_t *pNtk, *pNtkAig;
pNtk = store<pabc::Abc_Ntk_t *>().current();
int fVerbose;
int fUpdateLevel;
int fFanout;
int fPower;
int c;
int fBalance;
int nMinSaved;
// set defaults
fVerbose = 0;
fUpdateLevel = 0;
fFanout = 1;
fPower = 0;
fBalance = 0;
nMinSaved = 1;
Extra_UtilGetoptReset();
if (is_set("verbose")) {
fVerbose = 1;
}
if (pNtk == NULL) {
Abc_Print(-1, "Empty network.\n");
return;
}
if (!Abc_NtkIsStrash(pNtk)) {
Abc_Print(-1, "This command works only for strashed networks.\n");
return;
}
Aig_Man_t *pMan, *pTemp;
abctime clk;
assert(Abc_NtkIsStrash(pNtk));
pMan = Abc_NtkToDar(pNtk, 0, 0);
if (pMan == NULL) return;
clk = Abc_Clock();
pMan = Dar_ManCompress2rs(pNtk, pTemp = pMan, fBalance, fUpdateLevel,
fFanout, fPower, fVerbose, nMinSaved);
Aig_ManStop(pTemp);
pNtkAig = Abc_NtkFromDar(pNtk, pMan);
Aig_ManStop(pMan);
if (pNtkAig == NULL) {
Abc_Print(-1, "Command has failed.\n");
return;
}
store<pabc::Abc_Ntk_t *>().extend();
store<pabc::Abc_Ntk_t *>().current() = pNtkAig;
}
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
private:
};
ALICE_ADD_COMMAND(compress2rs, "ABC")
} // namespace alice
#endif

86
src/commands/abc/dc2.hpp Normal file
View File

@ -0,0 +1,86 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file dc2.hpp
*
* @brief combination optimization script
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef DC2_HPP
#define DC2_HPP
// #include "base/abci/abc.c"
#include "base/abc/abc.h"
// #include "base/abci/abcDar.c"
using namespace std;
using namespace mockturtle;
using namespace pabc;
namespace alice {
class dc2_command : public command {
public:
explicit dc2_command(const environment::ptr &env)
: command(env, "usage: dc2 [-blfpvh]") {
add_flag("--verbose, -v", "print the information");
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
if (store<pabc::Abc_Ntk_t *>().size() == 0u)
std::cerr << "Error: Empty AIG network.\n";
else {
Abc_Ntk_t *pNtk, *pNtkRes;
int fBalance, fVerbose, fUpdateLevel, fFanout, fPower, c;
pNtk = store<pabc::Abc_Ntk_t *>().current();
// set defaults
fBalance = 0;
fVerbose = 0;
fUpdateLevel = 0;
fFanout = 1;
fPower = 0;
Extra_UtilGetoptReset();
if (pNtk == NULL) {
Abc_Print(-1, "Empty network.\n");
return;
}
if (!Abc_NtkIsStrash(pNtk)) {
Abc_Print(-1, "This command works only for strashed networks.\n");
return;
}
pNtkRes =
Abc_NtkDC2(pNtk, fBalance, fUpdateLevel, fFanout, fPower, fVerbose);
if (pNtkRes == NULL) {
Abc_Print(-1, "Command has failed.\n");
return;
}
// replace the current network
// Abc_FrameReplaceCurrentNetwork(pAbc, pNtkRes);
store<pabc::Abc_Ntk_t *>().extend();
store<pabc::Abc_Ntk_t *>().current() = pNtkRes;
}
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
private:
};
ALICE_ADD_COMMAND(dc2, "ABC")
} // namespace alice
#endif

115
src/commands/abc/if.hpp Normal file
View File

@ -0,0 +1,115 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file if.hpp
*
* @brief performs FPGA technology mapping of the network
*
* @author Homyoung
* @since 2023/08/03
*/
#ifndef ABC_IF_HPP
#define ABC_IF_HPP
#include "base/abc/abc.h"
#include "base/abci/abcIf.c"
#include "base/main/main.h"
#include "map/if/if.h"
using namespace mockturtle;
using namespace std;
using namespace pabc;
namespace alice {
class if_command : public command {
public:
explicit if_command(const environment::ptr &env)
: command(env, "performs FPGA mapping of the AIG") {
add_flag("--verbose, -v", "print the information");
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
if (store<pabc::Abc_Ntk_t *>().size() == 0u)
std::cerr << "Error: Empty ABC AIG network\n";
else {
Abc_Ntk_t *pNtk = store<pabc::Abc_Ntk_t *>().current();
// set defaults
Abc_Ntk_t *pNtkRes;
If_Par_t Pars, *pPars = &Pars;
If_ManSetDefaultPars(pPars);
pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut();
if (pPars->nLutSize == -1) {
if (pPars->pLutLib == NULL) {
printf("The LUT library is not given.\n");
return;
}
pPars->nLutSize = pPars->pLutLib->LutMax;
}
if (pPars->nLutSize < 2 || pPars->nLutSize > IF_MAX_LUTSIZE) {
printf("Incorrect LUT size (%d).\n", pPars->nLutSize);
return;
}
if (pPars->nCutsMax < 1 || pPars->nCutsMax >= (1 << 12)) {
printf("Incorrect number of cuts.\n");
return;
}
if (!Abc_NtkIsStrash(pNtk)) {
// strash and balance the network
pNtk = Abc_NtkStrash(pNtk, 0, 0, 0);
if (pNtk == NULL) {
printf("Strashing before FPGA mapping has failed.\n");
return;
}
pNtk = Abc_NtkBalance(pNtkRes = pNtk, 0, 0, 1);
Abc_NtkDelete(pNtkRes);
if (pNtk == NULL) {
printf("Balancing before FPGA mapping has failed.\n");
return;
}
if (!Abc_FrameReadFlag("silentmode"))
printf(
"The network was strashed and balanced before FPGA mapping.\n");
// get the new network
pNtkRes = Abc_NtkIf(pNtk, pPars);
if (pNtkRes == NULL) {
Abc_NtkDelete(pNtk);
printf("FPGA mapping has failed.\n");
return;
}
Abc_NtkDelete(pNtk);
} else {
// get the new network
pNtkRes = Abc_NtkIf(pNtk, pPars);
if (pNtkRes == NULL) {
printf("FPGA mapping has failed.\n");
return;
}
}
store<pabc::Abc_Ntk_t *>().extend();
store<pabc::Abc_Ntk_t *>().current() = pNtkRes;
}
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
private:
};
ALICE_ADD_COMMAND(if, "ABC")
} // namespace alice
#endif

95
src/commands/abc/map.hpp Normal file
View File

@ -0,0 +1,95 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file map.hpp
*
* @brief performs technology-independent mapping of the AIG
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef ABC_MAP_HPP
#define ABC_MAP_HPP
#include "base/abc/abc.h"
#include "base/abci/abcMap.c"
using namespace mockturtle;
using namespace std;
namespace alice {
class map_command : public command {
public:
explicit map_command(const environment::ptr &env)
: command(env, "performs standard cell mapping of the current network") {
add_flag("--verbose, -v", "print the information");
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
pabc::Abc_Ntk_t *pNtkRes;
double DelayTarget;
double AreaMulti;
double DelayMulti;
float LogFan = 0;
float Slew = 0; // choose based on the library
float Gain = 250;
int nGatesMin = 0;
int fAreaOnly;
int fRecovery;
int fSweep;
int fSwitching;
int fSkipFanout;
int fUseProfile;
int fUseBuffs;
int fVerbose;
if (store<pabc::Abc_Ntk_t *>().size() == 0u)
std::cerr << "Error: Empty ABC AIG network\n";
else {
pabc::Abc_Ntk_t *pNtk = store<pabc::Abc_Ntk_t *>().current();
// set defaults
DelayTarget = -1;
AreaMulti = 0;
DelayMulti = 0;
fAreaOnly = 0;
fRecovery = 1;
fSweep = 0;
fSwitching = 0;
fSkipFanout = 0;
fUseProfile = 0;
fUseBuffs = 0;
fVerbose = 0;
if (is_set("verbose")) fVerbose ^= 1;
pNtkRes = Abc_NtkMap(pNtk, DelayTarget, AreaMulti, DelayMulti, LogFan,
Slew, Gain, nGatesMin, fRecovery, fSwitching,
fSkipFanout, fUseProfile, fUseBuffs, fVerbose);
store<pabc::Abc_Ntk_t *>().extend();
store<pabc::Abc_Ntk_t *>().current() = pNtkRes;
}
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
private:
};
ALICE_ADD_COMMAND(map, "ABC")
} // namespace alice
#endif

163
src/commands/abc/put.hpp Normal file
View File

@ -0,0 +1,163 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file put.hpp
*
* @brief converts the current GIA network into Ntk
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef ABC_PUT_HPP
#define ABC_PUT_HPP
#include "base/abc/abc.h"
// #include "base/abci/abcDar.c"
// #include "aig/gia/gia.h"
#include "aig/gia/giaAig.h"
using namespace std;
using namespace mockturtle;
using namespace pabc;
namespace alice {
class put_command : public command {
public:
explicit put_command(const environment::ptr &env)
: command(env, "converts the current network into AIG") {}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
Aig_Man_t *pMan;
Abc_Ntk_t *pNtk;
if (store<pabc::Abc_Ntk_t *>().size() == 0u)
std::cerr << "Error: Empty ABC AIG network\n";
else
pNtk = store<pabc::Abc_Ntk_t *>().current();
if (store<pabc::Gia_Man_t *>().size() == 0u)
std::cerr << "Error: Empty ABC GIA network\n";
else {
Gia_Man_t *pGia = store<pabc::Gia_Man_t *>().current();
int fStatusClear = 1;
int fUseBuffs = 0;
int fFindEnables = 0;
int fVerbose = 0;
if (fFindEnables)
pNtk = Abc_NtkFromMappedGia(pGia, 1, fUseBuffs);
else if (Gia_ManHasCellMapping(pGia))
pNtk = Abc_NtkFromCellMappedGia(pGia, fUseBuffs);
else if (Gia_ManHasMapping(pGia) || pGia->pMuxes)
pNtk = Abc_NtkFromMappedGia(pGia, 0, fUseBuffs);
else if (Gia_ManHasDangling(pGia) == 0) {
pMan = Gia_ManToAig(pGia, 0);
pNtk = Abc_NtkFromAigPhase(pMan);
pNtk->pName = Extra_UtilStrsav(pMan->pName);
Aig_ManStop(pMan);
} else {
Abc_Ntk_t *pNtkNoCh;
Abc_Print(-1, "Transforming AIG with %d choice nodes.\n",
Gia_ManEquivCountClasses(pGia));
// create network without choices
pMan = Gia_ManToAig(pGia, 0);
pNtkNoCh = Abc_NtkFromAigPhase(pMan);
pNtkNoCh->pName = Extra_UtilStrsav(pMan->pName);
Aig_ManStop(pMan);
// derive network with choices
pMan = Gia_ManToAig(pGia, 1);
pNtk = Abc_NtkFromDarChoices(pNtkNoCh, pMan);
Abc_NtkDelete(pNtkNoCh);
Aig_ManStop(pMan);
}
// transfer PI names to pNtk
// if ( pGia->vNamesIn )
// {
// Abc_Obj_t * pObj;
// int i;
// Abc_NtkForEachCi( pNtk, pObj, i ) {
// if (i < Vec_PtrSize(pGia->vNamesIn)) {
// Nm_ManDeleteIdName(pNtk->pManName, pObj->Id);
// Abc_ObjAssignName( pObj, (char
// *)Vec_PtrEntry(pGia->vNamesIn, i), NULL );
// }
// }
// }
// transfer PO names to pNtk
// if ( pGia->vNamesOut )
// {
// char pSuffix[100];
// Abc_Obj_t * pObj;
// int i, nDigits = Abc_Base10Log( Abc_NtkLatchNum(pNtk) );
// Abc_NtkForEachCo( pNtk, pObj, i ) {
// if (i < Vec_PtrSize(pGia->vNamesOut)) {
// Nm_ManDeleteIdName(pNtk->pManName, pObj->Id);
// if ( Abc_ObjIsPo(pObj) )
// Abc_ObjAssignName( pObj, (char
// *)Vec_PtrEntry(pGia->vNamesOut, i), NULL );
// else
// {
// assert( i >= Abc_NtkPoNum(pNtk) );
// sprintf( pSuffix, "_li%0*d", nDigits,
// i-Abc_NtkPoNum(pNtk) ); Abc_ObjAssignName( pObj, (char
// *)Vec_PtrEntry(pGia->vNamesOut, i), pSuffix );
// }
// }
// }
// }
// if ( pGia->vNamesNode )
// Abc_Print( 0, "Internal nodes names are not transferred.\n" );
// // decouple CI/CO with the same name
// if ( pGia->vNamesIn || pGia->vNamesOut )
// Abc_NtkRedirectCiCo( pNtk );
// // transfer timing information
// if ( pGia->vInArrs || pGia->vOutReqs )
// {
// Abc_Obj_t * pObj; int i;
// Abc_NtkTimeInitialize( pNtk, NULL );
// Abc_NtkTimeSetDefaultArrival( pNtk, pGia->DefInArrs,
// pGia->DefInArrs ); Abc_NtkTimeSetDefaultRequired( pNtk,
// pGia->DefOutReqs, pGia->DefOutReqs ); if ( pGia->vInArrs )
// Abc_NtkForEachCi( pNtk, pObj, i )
// Abc_NtkTimeSetArrival( pNtk, Abc_ObjId(pObj),
// Vec_FltEntry(pGia->vInArrs, i), Vec_FltEntry(pGia->vInArrs,
// i) );
// if ( pGia->vOutReqs )
// Abc_NtkForEachCo( pNtk, pObj, i )
// Abc_NtkTimeSetRequired( pNtk, Abc_ObjId(pObj),
// Vec_FltEntry(pGia->vOutReqs, i),
// Vec_FltEntry(pGia->vOutReqs, i) );
// }
// replace the current network
// Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
// if ( fStatusClear )
// Abc_FrameClearVerifStatus( pAbc );
store<pabc::Abc_Ntk_t *>().extend();
store<pabc::Abc_Ntk_t *>().current() = pNtk;
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
}
private:
};
ALICE_ADD_COMMAND(put, "ABC")
} // namespace alice
#endif

View File

@ -0,0 +1,108 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file read_genlib.hpp
*
* @brief read the library from a genlib file
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef ABC_READ_GENLIB_HPP
#define ABC_READ_GENLIB_HPP
#include "base/abc/abc.h"
#include "base/io/ioAbc.h"
#include "base/main/abcapis.h"
#include "base/main/main.h"
#include "map/amap/amap.h"
#include "map/mapper/mapper.h"
#include "map/mio/mio.h"
#include "misc/extra/extra.h"
using namespace std;
using namespace mockturtle;
namespace alice {
class read_agenlib_command : public command {
public:
explicit read_agenlib_command(const environment::ptr &env)
: command(env, "read the library from a genlib file") {
add_option("filename,-f", file_name, "name of input file");
add_flag("--verbose, -v", "print the information");
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
pabc::Abc_Frame_t *pAbc;
pAbc = pabc::Abc_FrameGetGlobalFrame();
// set defaults
FILE *pFile;
// FILE * pOut, * pErr;
pabc::Mio_Library_t *pLib;
pabc::Amap_Lib_t *pLib2;
char *pFileName;
char *pExcludeFile = NULL;
int fVerbose = 1;
// get the input file name
pFileName = (char *)malloc(file_name.length() + 1);
if (pFileName != NULL) {
strcpy(pFileName, file_name.c_str());
} else {
printf("Memory allocation failed\n");
}
// if ( (pFile = pabc::Io_FileOpen( pFileName, "open_path", "r", 0 )) ==
// NULL )
// {
// printf("Cannot open input file \"%s\". ", pFileName );
// if ( (pFileName = pabc::Extra_FileGetSimilarName( pFileName,
// ".genlib", ".lib", ".scl", ".g", NULL )) )
// printf( "Did you mean \"%s\"?", pFileName );
// printf( "\n" );
// return;
// }
// fclose( pFile );
// set the new network
pLib = pabc::Mio_LibraryRead(pFileName, NULL, pExcludeFile, fVerbose);
if (pLib == NULL) {
// fprintf( pErr, "Reading genlib library has failed.\n" );
printf("Reading genlib library has failed.\n");
return;
}
if (fVerbose)
printf("Entered genlib library with %d gates from file \"%s\".\n",
Mio_LibraryReadGateNum(pLib), pFileName);
// prepare libraries
pabc::Mio_UpdateGenlib(pLib);
// replace the current library
pLib2 = pabc::Amap_LibReadAndPrepare(pFileName, NULL, 0, 0);
if (pLib2 == NULL) {
// fprintf( pErr, "Reading second genlib library has failed.\n" );
printf("Reading second genlib library has failed.\n");
return;
}
Abc_FrameSetLibGen2(pLib2);
}
private:
std::string file_name;
};
ALICE_ADD_COMMAND(read_agenlib, "I/O")
} // namespace alice
#endif

View File

@ -0,0 +1,124 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file refactor.hpp
*
* @brief performs technology-independent refactoring of the AIG
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef ABC_REFACTOR_HPP
#define ABC_REFACTOR_HPP
#include "base/abc/abc.h"
#include "base/abci/abc.c"
#include "base/abci/abcRefactor.c"
using namespace std;
using namespace mockturtle;
using namespace pabc;
namespace alice {
class arefactor_command : public command {
public:
explicit arefactor_command(const environment::ptr &env)
: command(env, "performs technology-independent refactoring of the AIG") {
add_flag("--verbose, -v", "print the information");
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
if (store<pabc::Abc_Ntk_t *>().size() == 0u)
std::cerr << "Error: Empty AIG network.\n";
else {
pabc::Abc_Ntk_t *pNtk, *pDup;
pNtk = store<pabc::Abc_Ntk_t *>().current();
int c, RetValue;
int nNodeSizeMax;
int nConeSizeMax;
int fUpdateLevel;
int fUseZeros;
int fUseDcs;
int fVerbose;
int nMinSaved;
// set defaults
nNodeSizeMax = 10;
nConeSizeMax = 16;
fUpdateLevel = 1;
fUseZeros = 0;
fUseDcs = 0;
fVerbose = 0;
nMinSaved = 1;
Extra_UtilGetoptReset();
if (pNtk == NULL) {
Abc_Print(-1, "Empty network.\n");
return;
}
if (!Abc_NtkIsStrash(pNtk)) {
Abc_Print(
-1,
"This command can only be applied to an AIG (run \"strash\").\n");
return;
}
if (Abc_NtkGetChoiceNum(pNtk)) {
Abc_Print(
-1,
"AIG resynthesis cannot be applied to AIGs with choice nodes.\n");
return;
}
if (nNodeSizeMax > 15) {
Abc_Print(-1, "The cone size cannot exceed 15.\n");
return;
}
if (fUseDcs && nNodeSizeMax >= nConeSizeMax) {
Abc_Print(-1,
"For don't-care to work, containing cone should be larger "
"than collapsed node.\n");
return;
}
// modify the current network
pDup = Abc_NtkDup(pNtk);
RetValue = Abc_NtkRefactor(pNtk, nNodeSizeMax, nMinSaved, nConeSizeMax,
fUpdateLevel, fUseZeros, fUseDcs, fVerbose);
if (RetValue == -1) {
// Abc_FrameReplaceCurrentNetwork(pAbc, pDup);
printf(
"An error occurred during computation. The original network is "
"restored.\n");
} else {
Abc_NtkDelete(pDup);
if (RetValue == 0) {
Abc_Print(0, "Refactoring has failed.\n");
return;
}
}
store<pabc::Abc_Ntk_t *>().extend();
store<pabc::Abc_Ntk_t *>().current() = pNtk;
}
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
private:
};
ALICE_ADD_COMMAND(arefactor, "ABC")
} // namespace alice
#endif

View File

@ -0,0 +1,291 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file resyn2rs.hpp
*
* @brief combination optimization script
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef RESYN2RS_HPP
#define RESYN2RS_HPP
// #include "base/abci/abc.c"
#include "base/abc/abc.h"
// #include "base/abci/abcDar.c"
// #include "base/abci/abcResub.c"
using namespace std;
using namespace mockturtle;
using namespace pabc;
namespace alice {
class resyn2rs_command : public command {
public:
explicit resyn2rs_command(const environment::ptr &env)
: command(env, "usage: synthesis scripts.") {
add_flag("--verbose, -v", "print the information");
}
public:
void Dar_ManDefaultResParams(Dar_ResPar_t *pPars) {
memset(pPars, 0, sizeof(Dar_ResPar_t));
pPars->nCutsMax = 8; // 8
pPars->nNodesMax = 1;
pPars->nLevelsOdc = 0;
pPars->fUpdateLevel = 1;
pPars->fUseZeros = 0;
pPars->fVerbose = 0;
pPars->fVeryVerbose = 0;
}
Aig_Man_t *Dar_ManResyn2rs(Abc_Ntk_t *pNtk, Aig_Man_t *pAig, int fBalance,
int fUpdateLevel, int fFanout, int fPower,
int fVerbose, int nMinSaved) {
// alias resyn2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K
// 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12
// -N 2; rwz; b"
Aig_Man_t *pTemp;
Abc_Ntk_t *pNtkAig;
Dar_RwrPar_t ParsRwr, *pParsRwr = &ParsRwr;
Dar_RefPar_t ParsRef, *pParsRef = &ParsRef;
Dar_ResPar_t ParsRes, *pParsRes = &ParsRes;
Dar_ManDefaultRwrParams(pParsRwr);
Dar_ManDefaultRefParams(pParsRef);
Dar_ManDefaultResParams(pParsRes);
pParsRwr->fUpdateLevel = fUpdateLevel;
pParsRef->fUpdateLevel = fUpdateLevel;
pParsRes->fUpdateLevel = fUpdateLevel;
// pParsRes->nCutsMax = nCutsMax;
// pParsRes->nNodesMax = nNodesMax;
pParsRwr->fFanout = fFanout;
pParsRwr->fPower = fPower;
pParsRwr->fVerbose = 0; // fVerbose;
pParsRef->fVerbose = 0; // fVerbose;
pParsRes->fVerbose = 0; // fVerbose;
pAig = Aig_ManDupDfs(pAig);
if (fVerbose) printf("Starting: "), Aig_ManPrintStats(pAig);
// b;
fUpdateLevel = 1;
pAig = Dar_ManBalance(pTemp = pAig, fUpdateLevel);
Aig_ManStop(pTemp);
if (fVerbose) printf("Balance: "), Aig_ManPrintStats(pAig);
// rs -K 6;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 6;
pParsRes->fUpdateLevel = 1;
pParsRes->nNodesMax = 1;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// rw;
pParsRwr->fUpdateLevel = 1;
Dar_ManRewrite(pAig, pParsRwr);
pAig = Aig_ManDupDfs(pTemp = pAig);
Aig_ManStop(pTemp);
if (fVerbose) printf("Rewrite: "), Aig_ManPrintStats(pAig);
// rs -K 6 -N 2;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 6;
pParsRes->fUpdateLevel = 1;
pParsRes->nNodesMax = 2;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// rf;
pParsRef->fUpdateLevel = 1;
Dar_ManRefactor(pAig, pParsRef);
pAig = Aig_ManDupDfs(pTemp = pAig);
Aig_ManStop(pTemp);
if (fVerbose) printf("Refactor: "), Aig_ManPrintStats(pAig);
// rs -K 8;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 8;
pParsRes->fUpdateLevel = 1;
pParsRes->nNodesMax = 1;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// b;
fUpdateLevel = 1;
pAig = Dar_ManBalance(pTemp = pAig, fUpdateLevel);
Aig_ManStop(pTemp);
if (fVerbose) printf("Balance: "), Aig_ManPrintStats(pAig);
// rs -K 8 -N 2;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 8;
pParsRes->fUpdateLevel = 1;
pParsRes->nNodesMax = 2;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// rw;
pParsRwr->fUpdateLevel = 1;
Dar_ManRewrite(pAig, pParsRwr);
pAig = Aig_ManDupDfs(pTemp = pAig);
Aig_ManStop(pTemp);
if (fVerbose) printf("Rewrite: "), Aig_ManPrintStats(pAig);
// rs -K 10;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 10;
pParsRes->fUpdateLevel = 1;
pParsRes->nNodesMax = 1;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// rwz;
pParsRwr->fUpdateLevel = 1;
pParsRwr->fUseZeros = 1;
Dar_ManRewrite(pAig, pParsRwr);
pAig = Aig_ManDupDfs(pTemp = pAig);
Aig_ManStop(pTemp);
if (fVerbose) printf("Rewrite_zerocost: "), Aig_ManPrintStats(pAig);
// rs -K 10 -N 2;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 10;
pParsRes->fUpdateLevel = 1;
pParsRes->nNodesMax = 2;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// b;
fUpdateLevel = 1;
pAig = Dar_ManBalance(pTemp = pAig, fUpdateLevel);
Aig_ManStop(pTemp);
if (fVerbose) printf("Balance: "), Aig_ManPrintStats(pAig);
// rs -K 12;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 12;
pParsRes->fUpdateLevel = 1;
pParsRes->nNodesMax = 1;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// rfz;
pParsRef->fUpdateLevel = 1;
pParsRef->fUseZeros = 1;
Dar_ManRefactor(pAig, pParsRef);
pAig = Aig_ManDupDfs(pTemp = pAig);
Aig_ManStop(pTemp);
if (fVerbose) printf("Refactor_zerocost: "), Aig_ManPrintStats(pAig);
// rs -K 12 -N 2;
pNtkAig = Abc_NtkFromDar(pNtk, pAig);
pParsRes->nCutsMax = 12;
pParsRes->fUpdateLevel = 1;
pParsRes->nNodesMax = 2;
Abc_NtkResubstitute(pNtkAig, pParsRes->nCutsMax, pParsRes->nNodesMax,
nMinSaved, pParsRes->nLevelsOdc, fUpdateLevel, fVerbose,
pParsRes->fVeryVerbose);
pAig = Abc_NtkToDar(pNtkAig, 0, 0);
if (fVerbose) printf("Resub: "), Aig_ManPrintStats(pAig);
// rwz;
pParsRwr->fUpdateLevel = 1;
pParsRwr->fUseZeros = 1;
Dar_ManRewrite(pAig, pParsRwr);
pAig = Aig_ManDupDfs(pTemp = pAig);
Aig_ManStop(pTemp);
if (fVerbose) printf("Rewrite_zerocost: "), Aig_ManPrintStats(pAig);
// b;
fUpdateLevel = 1;
pAig = Dar_ManBalance(pTemp = pAig, fUpdateLevel);
Aig_ManStop(pTemp);
if (fVerbose) printf("Balance: "), Aig_ManPrintStats(pAig);
return pAig;
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
if (store<pabc::Abc_Ntk_t *>().size() == 0u)
std::cerr << "Error: Empty AIG network.\n";
else {
Abc_Ntk_t *pNtk, *pNtkAig;
pNtk = store<pabc::Abc_Ntk_t *>().current();
int fVerbose;
int fUpdateLevel;
int fFanout;
int fPower;
int c;
int fBalance;
int nMinSaved;
// set defaults
fVerbose = 0;
fUpdateLevel = 1;
fFanout = 1;
fPower = 0;
fBalance = 0;
nMinSaved = 1;
Extra_UtilGetoptReset();
if (is_set("verbose")) {
fVerbose = 1;
}
if (pNtk == NULL) {
Abc_Print(-1, "Empty network.\n");
return;
}
if (!Abc_NtkIsStrash(pNtk)) {
Abc_Print(-1, "This command works only for strashed networks.\n");
return;
}
Aig_Man_t *pMan, *pTemp;
abctime clk;
assert(Abc_NtkIsStrash(pNtk));
pMan = Abc_NtkToDar(pNtk, 0, 0);
if (pMan == NULL) return;
clk = Abc_Clock();
pMan = Dar_ManResyn2rs(pNtk, pTemp = pMan, fBalance, fUpdateLevel,
fFanout, fPower, fVerbose, nMinSaved);
Aig_ManStop(pTemp);
pNtkAig = Abc_NtkFromDar(pNtk, pMan);
Aig_ManStop(pMan);
if (pNtkAig == NULL) {
Abc_Print(-1, "Command has failed.\n");
return;
}
store<pabc::Abc_Ntk_t *>().extend();
store<pabc::Abc_Ntk_t *>().current() = pNtkAig;
}
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
private:
};
ALICE_ADD_COMMAND(resyn2rs, "ABC")
} // namespace alice
#endif

View File

@ -0,0 +1,111 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file rewrite.hpp
*
* @brief performs technology-independent rewriting of the AIG
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef ABC_REWRITE_HPP
#define ABC_REWRITE_HPP
#include "base/abc/abc.h"
#include "base/abci/abcRewrite.c"
using namespace std;
using namespace mockturtle;
using namespace pabc;
namespace alice {
class arewrite_command : public command {
public:
explicit arewrite_command(const environment::ptr &env)
: command(env, "performs technology-independent rewriting of the AIG") {
add_flag("--verbose, -v", "print the information");
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
if (store<pabc::Abc_Ntk_t *>().size() == 0u)
std::cerr << "Error: Empty AIG network.\n";
else {
Abc_Ntk_t *pNtk, *pDup;
pNtk = store<pabc::Abc_Ntk_t *>().current();
int c, RetValue;
int fUpdateLevel;
int fPrecompute;
int fUseZeros;
int fVerbose;
int fVeryVerbose;
int fPlaceEnable;
// set defaults
fUpdateLevel = 1;
fUseZeros = 0;
fVerbose = 0;
fVeryVerbose = 0;
fPlaceEnable = 0;
Extra_UtilGetoptReset();
if (pNtk == NULL) {
Abc_Print(-1, "Empty network.\n");
return;
}
if (!Abc_NtkIsStrash(pNtk)) {
Abc_Print(
-1,
"This command can only be applied to an AIG (run \"strash\").\n");
return;
}
if (Abc_NtkGetChoiceNum(pNtk)) {
Abc_Print(
-1,
"AIG resynthesis cannot be applied to AIGs with choice nodes.\n");
return;
}
// modify the current network
pDup = Abc_NtkDup(pNtk);
RetValue = Abc_NtkRewrite(pNtk, fUpdateLevel, fUseZeros, fVerbose,
fVeryVerbose, fPlaceEnable);
if (RetValue == -1) {
// Abc_FrameReplaceCurrentNetwork(pAbc, pDup);
printf(
"An error occurred during computation. The original network is "
"restored.\n");
} else {
Abc_NtkDelete(pDup);
if (RetValue == 0) {
Abc_Print(0, "Rewriting has failed.\n");
return;
}
}
store<pabc::Abc_Ntk_t *>().extend();
store<pabc::Abc_Ntk_t *>().current() = pNtk;
}
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
private:
};
ALICE_ADD_COMMAND(arewrite, "ABC")
} // namespace alice
#endif

84
src/commands/abc/sop.hpp Normal file
View File

@ -0,0 +1,84 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file sop.hpp
*
* @brief converts node functions to SOP
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef SOP_HPP
#define SOP_HPP
// #include "base/abci/abc.c"
#include "base/abc/abc.h"
#include "base/abc/abcFunc.c"
using namespace std;
using namespace mockturtle;
using namespace pabc;
namespace alice {
class sop_command : public command {
public:
explicit sop_command(const environment::ptr &env)
: command(env, "converts node functions to SOP") {
add_flag("--verbose, -v", "print the information");
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
if (store<pabc::Abc_Ntk_t *>().size() == 0u)
std::cerr << "Error: Empty AIG network.\n";
else {
Abc_Ntk_t *pNtk;
pNtk = store<pabc::Abc_Ntk_t *>().current();
int c, fCubeSort = 1, fMode = -1, nCubeLimit = 1000000;
// set defaults
Extra_UtilGetoptReset();
if (pNtk == NULL) {
Abc_Print(-1, "Empty network.\n");
return;
}
if (!Abc_NtkIsLogic(pNtk)) {
Abc_Print(-1,
"Converting to SOP is possible only for logic networks.\n");
return;
}
if (!fCubeSort && Abc_NtkHasBdd(pNtk) &&
!Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 0)) {
Abc_Print(-1, "Converting to SOP has failed.\n");
return;
}
if (!Abc_NtkToSop(pNtk, fMode, nCubeLimit)) {
Abc_Print(-1, "Converting to SOP has failed.\n");
return;
}
store<pabc::Abc_Ntk_t *>().extend();
store<pabc::Abc_Ntk_t *>().current() = pNtk;
}
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
private:
};
ALICE_ADD_COMMAND(sop, "ABC")
} // namespace alice
#endif

View File

@ -1,5 +1,5 @@
/* phyLS: Advanced Logic Synthesis and Optimization tool /* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2019-2021 Ningbo University, Ningbo, China */ * Copyright (C) 2023 */
/** /**
* @file exact_lut.hpp * @file exact_lut.hpp

View File

@ -1,5 +1,5 @@
/* phyLS: Advanced Logic Synthesis and Optimization tool /* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2019-2021 Ningbo University, Ningbo, China */ * Copyright (C) 2023 */
/** /**
* @file lutrw.hpp * @file lutrw.hpp

View File

@ -48,6 +48,7 @@ class fr_command : public command {
double totalTime; double totalTime;
functional_reduction_params ps; functional_reduction_params ps;
ps.max_iterations = 0;
if (is_set("--filename")) ps.pattern_filename = filename; if (is_set("--filename")) ps.pattern_filename = filename;
if (is_set("--tfi_node")) ps.max_TFI_nodes = max_tfi_node; if (is_set("--tfi_node")) ps.max_TFI_nodes = max_tfi_node;
if (is_set("--pattern")) ps.save_patterns = "pattern.log"; if (is_set("--pattern")) ps.save_patterns = "pattern.log";
@ -94,7 +95,7 @@ class fr_command : public command {
} }
private: private:
int max_tfi_node = 500; int max_tfi_node = 10000;
string filename = "pattern.log"; string filename = "pattern.log";
}; };

515
src/commands/ps2.hpp Normal file
View File

@ -0,0 +1,515 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file ps2.hpp
*
* @brief Show statistics in the stored network
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef PS2_HPP
#define PS2_HPP
#include <../core/ps2.hpp>
namespace alice {
using namespace mockturtle;
class ps2_command : public command {
public:
explicit ps2_command(const environment::ptr& env)
: command(env, "Show statistics in the stored network.") {
add_flag("--aig,-a", "Display stats for stored AIG");
add_flag("--mig,-m", "Display stats for stored MIG");
add_flag("--xag,-g", "Display stats for stored XAG");
add_flag("--xmg,-x", "Display stats for stored XMG");
add_flag("--criti,-c", "Display critical path node index and gate");
add_flag("--fanout,-f", "Display fanout histogram");
add_flag("--cone,-o", "Dispaly logic cones from PO to PI(only for AIG)");
add_flag("--level,-l", "Display level histigram");
add_flag("--skip,-k", "Display skip histogram");
}
template <typename network>
void dump_stats(std::string name) {
if (store<network>().empty()) {
env->err() << "[e] " << name << " network not stored\n";
return;
}
auto ntk = store<network>().current();
mockturtle::depth_view dag_depth{ntk};
/*critical_path*/
phyLS::critical_node_view<mockturtle::names_view<network>> critical{ntk};
auto critical_path = critical.get_critical_path();
auto critical_nums = critical.get_critical_nums();
phyLS::function_counts counts;
for (auto curr_node : critical_path) {
update_counts(counts, ntk, curr_node);
}
/*fanin_histogram*/
mockturtle::fanout_view<network> fanout{ntk};
uint32_t times = 0;
fanout.foreach_node([&](auto node) {
bool pure = true;
fanout.foreach_fanin(node, [&](auto fi) {
uint32_t focount = 0;
auto node = fanout.get_node(fi);
fanout.foreach_fanout(node, [&](auto fo) { focount++; });
bool isolated_fanin = (focount == 1) ? 1 : 0;
pure = pure && (fanout.is_constant(node) || isolated_fanin);
});
if (!pure) times++;
});
/*fanout_histogram*/
std::vector<int> fanout_vec;
double average_fanout = 0;
fanout.foreach_node([&](auto node) {
uint32_t foc = 0;
if (ntk.is_constant(node)) return;
fanout.foreach_fanout(node, [&](auto fo) { foc++; });
fanout_vec.emplace_back(foc);
if (foc > max_fanout) {
max_fanout = foc;
}
});
int po = 0;
fanout.foreach_po([&](auto o) { po++; });
average_fanout = std::accumulate(fanout_vec.begin(), fanout_vec.end(), 0.0,
[](double acc, int i) {
return acc + static_cast<double>(i);
}) /
(fanout_vec.size() - 1 - po);
/*function_stats*/
phyLS::function_counts counts1 = phyLS::node_functions(ntk);
/*skip_histogram*/
std::vector<uint32_t> skip_histogram(dag_depth.depth(), 0);
uint32_t mismatch_levels = 0;
fanout.foreach_node([&](auto node) {
uint32_t last_level = 0;
bool mismatched = false;
fanout.foreach_fanout(node, [&](auto f) {
if (last_level != 0 && last_level != dag_depth.level(f)) {
mismatched = true;
}
last_level = dag_depth.level(f);
uint32_t skip = dag_depth.level(f) - dag_depth.level(node);
skip_histogram[skip]++;
});
if (mismatched) {
mismatch_levels++;
}
});
int max_skip = 0;
double average_skip = 0.0;
double dividend = 0.0;
double divisor = 0.0;
for (int i = 0; i < skip_histogram.size(); i++) {
dividend += i * skip_histogram[i];
divisor += skip_histogram[i];
}
average_skip = dividend / divisor;
max_skip = skip_histogram.size() - 1;
env->out() << "************************************************************"
"*******************\n"
<< "* Statistic information "
" *\n"
<< "************************************************************"
"*******************\n"
<< std::setw(2) << std::left << " " << std::setw(70) << std::left
<< "Total size of critical path nodes : " << std::setw(5)
<< std::left << critical_path.size() << "\n"
<< std::setw(2) << std::left << " " << std::setw(70) << std::left
<< "Number of critical paths : " << std::setw(5) << std::left
<< critical_nums << "\n"
<< std::setw(2) << std::left << " " << std::setw(70) << std::left
<< "Number of pure nodes (at least one child node has multiple "
"fanouts) : "
<< std::setw(5) << std::left << times << "\n"
<< "------------------------------------------------------------"
"-------------------\n"
<< " +Node fanout : "
<< "\n"
<< std::setw(3) << std::left << " "
<< "| Max Fanout | = " << max_fanout << std::setw(10) << " "
<< "| Average Fanout | = " << average_fanout << "\n"
<< "------------------------------------------------------------"
"-------------------\n"
<< " +Function_statistic : "
<< "\n";
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(61) << ""
<< std::setfill(' ') << std::endl;
std::cout << std::setw(3) << " "
<< "| " << std::left << std::setw(4) << "Name"
<< " |" << std::setw(4) << "MAJ"
<< " |" << std::setw(4) << "AND"
<< " |" << std::setw(4) << "OR"
<< " |" << std::setw(4) << "XOR3"
<< " |" << std::setw(4) << "XOR"
<< " |" << std::setw(4) << "XNOR"
<< " |" << std::setw(7) << "Unknown"
<< " |" << std::setw(7) << "Input"
<< " |" << std::endl;
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(61) << ""
<< std::setfill(' ') << std::endl;
std::cout
<< std::setw(3) << " "
<< "| " << std::left << std::setw(4) << "nums"
<< " |" << std::setw(4)
<< (counts1.maj_num == 0 ? " / " : std::to_string(counts1.maj_num))
<< " |" << std::setw(4)
<< (counts1.and_num == 0 ? " / " : std::to_string(counts1.and_num))
<< " |" << std::setw(4)
<< (counts1.or_num == 0 ? " / " : std::to_string(counts1.or_num))
<< " |" << std::setw(4)
<< (counts1.xor3_num == 0 ? " / " : std::to_string(counts1.xor3_num))
<< " |" << std::setw(4)
<< (counts1.xor_num == 0 ? " / " : std::to_string(counts1.xor_num))
<< " |" << std::setw(4)
<< (counts1.xnor_num == 0 ? " / " : std::to_string(counts1.xnor_num))
<< " |" << std::setw(7)
<< (counts1.unknown_num == 0 ? " / "
: std::to_string(counts1.unknown_num))
<< " |" << std::setw(7)
<< (counts1.input_num == 0 ? " / " : std::to_string(counts1.input_num))
<< " |" << std::endl;
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(61) << ""
<< std::setfill(' ') << std::endl;
std::cout << "-------------------------------------------------------------"
"------------------\n";
std::cout << " +Skip level : "
<< "\n"
<< " | Number of nodes with inconsistent levels of fanout "
"nodes (skip) : "
<< mismatch_levels << "\n"
<< std::setw(3) << std::left << " "
<< "| Max skip Level | = " << max_skip << std::setw(10) << " "
<< "| Average skip Level | = " << average_skip << "\n";
}
template <typename network>
void critical_path(std::string name) {
if (store<network>().empty()) return;
auto ntk = store<network>().current();
phyLS::critical_node_view<mockturtle::names_view<network>> c{ntk};
auto cp = c.get_critical_path();
phyLS::function_counts cou;
for (auto it : cp) {
update_counts(cou, ntk, it);
}
std::cout << " +Node in critical paths : "
<< "\n";
for (auto it : cp) {
std::cout << std::setw(3) << " ";
std::cout << ntk.node_to_index(it) << " ";
}
std::cout << std::endl;
std::cout << " +Node type in critical paths : "
<< "\n";
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(61) << ""
<< std::setfill(' ') << std::endl;
std::cout << std::setw(3) << " "
<< "| " << std::left << std::setw(4) << "Name"
<< " |" << std::setw(4) << "MAJ"
<< " |" << std::setw(4) << "AND"
<< " |" << std::setw(4) << "OR"
<< " |" << std::setw(4) << "XOR3"
<< " |" << std::setw(4) << "XOR"
<< " |" << std::setw(4) << "XNOR"
<< " |" << std::setw(7) << "Unknown"
<< " |" << std::setw(7) << "Input"
<< " |" << std::endl;
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(61) << ""
<< std::setfill(' ') << std::endl;
std::cout << std::setw(3) << " "
<< "| " << std::left << std::setw(4) << "nums"
<< " |" << std::setw(4)
<< (cou.maj_num == 0 ? " / " : std::to_string(cou.maj_num))
<< " |" << std::setw(4)
<< (cou.and_num == 0 ? " /" : std::to_string(cou.and_num)) << " |"
<< std::setw(4)
<< (cou.or_num == 0 ? " /" : std::to_string(cou.or_num)) << " |"
<< std::setw(4)
<< (cou.xor3_num == 0 ? " /" : std::to_string(cou.xor3_num))
<< " |" << std::setw(4)
<< (cou.xor_num == 0 ? " /" : std::to_string(cou.xor_num)) << " |"
<< std::setw(4)
<< (cou.xnor_num == 0 ? " /" : std::to_string(cou.xnor_num))
<< " |" << std::setw(7)
<< (cou.unknown_num == 0 ? " /" : std::to_string(cou.unknown_num))
<< " |" << std::setw(7)
<< (cou.input_num == 0 ? " /" : std::to_string(cou.input_num))
<< " |" << std::endl;
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(61) << ""
<< std::setfill(' ') << std::endl;
}
template <typename network>
void fanout_histogram(std::string name) {
if (store<network>().empty()) return;
auto ntk = store<network>().current();
mockturtle::fanout_view<network> fanoutP{ntk};
std::vector<uint32_t> fanout_histogram(max_fanout + 1, 0);
fanoutP.foreach_node([&](auto node) {
uint32_t foc = 0;
if (ntk.is_constant(node)) return;
fanoutP.foreach_fanout(node, [&](auto fo) { foc++; });
if (foc >= fanout_histogram.size() - 1) {
fanout_histogram[fanout_histogram.size() - 1]++;
} else {
fanout_histogram[foc]++;
}
});
std::cout << " +Node counts by number of fanouts." << std::endl;
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(22) << ""
<< std::setfill(' ') << std::endl;
std::cout << std::setw(3) << " "
<< "| " << std::left << std::setw(10) << "Fanout" << std::right
<< " | " << std::setw(5) << "Nodes"
<< " |" << std::endl;
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(22) << ""
<< std::setfill(' ') << std::endl;
for (int i = 0; i < fanout_histogram.size(); i++) {
if (fanout_histogram[i] == 0) continue;
std::cout << std::setw(3) << " "
<< "| " << std::left << std::setw(10) << i << std::right
<< " | " << std::setw(5) << fanout_histogram[i] << " |"
<< std::endl;
}
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(22) << ""
<< std::setfill(' ') << std::endl;
}
template <typename network>
void get_cones(std::string name) {
if (!store<network>().empty()) {
auto aig = store<network>().current();
// map with number of nodes in each logical cone
std::unordered_map<int, int> po_nodes;
// number of inputs for each cone
std::unordered_map<int, int> po_ins;
// first processing logical cones for POs
std::cout << " +Logic cones from PO2PI." << std::endl;
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(44)
<< "" << std::setfill(' ') << std::endl;
std::cout << std::setw(3) << " "
<< "| " << std::left << std::setw(10) << "Name" << std::right
<< " | " << std::setw(5) << "Index"
<< " |" << std::setw(5) << "Nodes"
<< " |" << std::setw(5) << "Level"
<< " |" << std::setw(6) << "Inputs"
<< " |" << std::endl;
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(44)
<< "" << std::setfill(' ') << std::endl;
for (int outIndex = 0; outIndex < aig.num_pos(); outIndex++) {
aig.foreach_node([&](auto node) {
// set all nodes as not visited
aig._storage->nodes[node].data[1].h1 = 0;
});
// start counter for a given output index
po_nodes.insert(std::make_pair(outIndex, 0));
// starting the counter of inputs
po_ins.insert(std::make_pair(outIndex, 0));
// calculate the index of the node driving the output
auto inIdx = aig._storage->outputs[outIndex].data;
if (aig._storage->outputs[outIndex].data & 1) {
inIdx = aig._storage->outputs[outIndex].data - 1;
}
inIdx = inIdx >> 1;
// call DFS
phyLS::compute_cone(aig, inIdx, po_nodes, outIndex, po_ins);
aig.foreach_node([&](auto node) {
// set all nodes as not visited
aig._storage->nodes[node].data[1].h1 = 0;
});
int level = phyLS::computeLevel<network>(aig, inIdx);
int nodes = 0;
int inputs = 0;
// for each output prints index, nodes, depth and number of inputs,
// respectively
std::unordered_map<int, int>::iterator it;
it = po_nodes.find(outIndex);
if (it != po_nodes.end()) nodes = it->second;
std::unordered_map<int, int>::iterator init;
init = po_ins.find(outIndex);
if (it != po_ins.end()) inputs = init->second;
std::cout << std::setw(3) << " "
<< "| " << std::left << std::setw(10) << "Output"
<< std::right << " | " << std::setw(5) << outIndex << " |"
<< std::setw(5) << nodes << " |" << std::setw(5) << level
<< " |" << std::setw(6) << inputs << " |" << std::endl;
}
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(44)
<< "" << std::setfill(' ') << std::endl;
} else {
env->err() << "There is not an AIG network stored.\n";
}
}
template <typename ntk>
void level_size(std::string name) {
if (store<ntk>().empty()) {
env->err() << name << " network not stored\n";
return;
}
auto dag = store<ntk>().current();
mockturtle::depth_view dag_view(dag);
std::vector<uint32_t> levels(dag_view.depth() + 1, 0);
dag_view.foreach_node([&](auto node) { levels[dag_view.level(node)]++; });
std::cout << " +Nodes per level." << std::endl;
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(22) << ""
<< std::setfill(' ') << std::endl;
std::cout << std::setw(3) << " "
<< "| " << std::left << std::setw(10) << "Level" << std::right
<< " | " << std::setw(5) << "Nodes"
<< " |" << std::endl;
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(22) << ""
<< std::setfill(' ') << std::endl;
for (int i = 0; i < levels.size(); i++) {
std::cout << std::setw(3) << " "
<< "| " << std::left << std::setw(10) << i << std::right
<< " | " << std::setw(5) << levels[i] << " |" << std::endl;
}
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(22) << ""
<< std::setfill(' ') << std::endl;
}
template <typename ntk>
void skip_histogram(std::string name) {
if (!store<ntk>().empty()) {
auto dag = store<ntk>().current();
mockturtle::depth_view dag_depth{dag};
mockturtle::fanout_view dag_fanout{dag};
std::vector<uint32_t> skip_histogram(dag_depth.depth(), 0);
uint32_t mismatch_levels = 0;
dag_fanout.foreach_node([&](auto node) {
uint32_t last_level = 0;
bool mismatched = false;
dag_fanout.foreach_fanout(node, [&](auto f) {
if (last_level != 0 && last_level != dag_depth.level(f)) {
mismatched = true;
}
last_level = dag_depth.level(f);
uint32_t skip = dag_depth.level(f) - dag_depth.level(node);
skip_histogram[skip]++;
});
if (mismatched) {
mismatch_levels++;
}
});
std::cout << " +Nodes whose fanout skip levels : " << mismatch_levels
<< std::endl;
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(22)
<< "" << std::setfill(' ') << std::endl;
std::cout << std::setw(3) << " "
<< "| " << std::left << std::setw(11) << "Skip_levels"
<< std::right << " | " << std::setw(5) << "Nodes"
<< " |" << std::endl;
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(22)
<< "" << std::setfill(' ') << std::endl;
for (int i = 0; i < skip_histogram.size(); i++) {
std::cout << std::setw(3) << " "
<< "| " << std::left << std::setw(11) << i << std::right
<< " | " << std::setw(5) << skip_histogram[i] << " |"
<< std::endl;
}
std::cout << std::setw(3) << " " << std::setfill('-') << std::setw(22)
<< "" << std::setfill(' ') << std::endl;
} else {
env->err() << "There is not an " << name << " network stored.\n";
}
}
protected:
void execute() {
if (is_set("mig")) {
dump_stats<mockturtle::mig_network>("MIG");
if (is_set("criti")) {
critical_path<mockturtle::mig_network>("MIG");
}
if (is_set("fanout")) {
fanout_histogram<mockturtle::mig_network>("MIG");
}
if (is_set("level")) {
level_size<mockturtle::mig_network>("MIG");
}
if (is_set("skip")) {
skip_histogram<mockturtle::mig_network>("MIG");
}
return;
} else if (is_set("xag")) {
dump_stats<mockturtle::xag_network>("XAG");
if (is_set("criti")) {
critical_path<mockturtle::xag_network>("XAG");
}
if (is_set("fanout")) {
fanout_histogram<mockturtle::xag_network>("XAG");
}
if (is_set("level")) {
level_size<mockturtle::xag_network>("XAG");
}
if (is_set("skip")) {
skip_histogram<mockturtle::xag_network>("XAG");
}
return;
} else if (is_set("xmg")) {
dump_stats<mockturtle::xmg_network>("XMG");
if (is_set("criti")) {
critical_path<mockturtle::xmg_network>("XMG");
}
if (is_set("fanout")) {
fanout_histogram<mockturtle::xmg_network>("XMG");
}
if (is_set("level")) {
level_size<mockturtle::xmg_network>("XMG");
}
if (is_set("skip")) {
skip_histogram<mockturtle::xmg_network>("XMG");
}
return;
} else if (is_set("aig")) {
dump_stats<mockturtle::aig_network>("AIG");
} else {
// default
dump_stats<mockturtle::aig_network>("AIG");
}
if (is_set("criti")) {
critical_path<mockturtle::aig_network>("AIG");
}
if (is_set("fanout")) {
fanout_histogram<mockturtle::aig_network>("AIG");
}
if (is_set("cone")) {
get_cones<mockturtle::aig_network>("AIG");
}
if (is_set("level")) {
level_size<mockturtle::aig_network>("AIG");
}
if (is_set("skip")) {
skip_histogram<mockturtle::aig_network>("AIG");
}
}
private:
int max_fanout = 0;
};
ALICE_ADD_COMMAND(ps2, "General");
} // namespace alice
#endif

View File

@ -13,6 +13,7 @@
#ifndef SIM_HPP #ifndef SIM_HPP
#define SIM_HPP #define SIM_HPP
#include <kitty/static_truth_table.hpp>
#include <mockturtle/algorithms/simulation.hpp> #include <mockturtle/algorithms/simulation.hpp>
using namespace std; using namespace std;
@ -83,7 +84,7 @@ class sim_command : public command {
begin = clock(); begin = clock();
aig_network aig = store<aig_network>().current(); aig_network aig = store<aig_network>().current();
if (is_set("partial_simulate")){ if (is_set("partial_simulate")){
partial_simulator sim(aig.num_pis(), 100000); partial_simulator sim(aig.num_pis(), 10000);
unordered_node_map<kitty::partial_truth_table, aig_network> unordered_node_map<kitty::partial_truth_table, aig_network>
node_to_value(aig); node_to_value(aig);
simulate_nodes(aig, node_to_value, sim); simulate_nodes(aig, node_to_value, sim);
@ -103,8 +104,7 @@ class sim_command : public command {
// }); // });
} else { } else {
default_simulator<kitty::dynamic_truth_table> sim(aig.num_pis()); default_simulator<kitty::dynamic_truth_table> sim(aig.num_pis());
unordered_node_map<kitty::dynamic_truth_table, aig_network> unordered_node_map<kitty::dynamic_truth_table, aig_network> node_to_value(aig);
node_to_value(aig);
simulate_nodes<kitty::dynamic_truth_table>(aig, node_to_value, sim); simulate_nodes<kitty::dynamic_truth_table>(aig, node_to_value, sim);
} }
end = clock(); end = clock();

View File

@ -1,3 +1,14 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file stpfr.hpp
*
* @brief STP-based functional reduction
*
* @author Homyoung
* @since 2023/03/14
*/
#ifndef STPFR_HPP #ifndef STPFR_HPP
#define STPFR_HPP #define STPFR_HPP

View File

@ -0,0 +1,110 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file window_rewriting.hpp
*
* @brief Window rewriting
*
* @author Homyoung
* @since 2023/09/27
*/
#ifndef WINDOW_REWRITING_HPP
#define WINDOW_REWRITING_HPP
#include <mockturtle/algorithms/cleanup.hpp>
#include <mockturtle/algorithms/experimental/boolean_optimization.hpp>
#include <mockturtle/algorithms/experimental/sim_resub.hpp>
#include <mockturtle/algorithms/experimental/window_resub.hpp>
#include <mockturtle/algorithms/window_rewriting.hpp>
#include <mockturtle/networks/aig.hpp>
#include <mockturtle/networks/mig.hpp>
#include <mockturtle/networks/xag.hpp>
#include <mockturtle/networks/xmg.hpp>
#include <mockturtle/traits.hpp>
#include <mockturtle/views/depth_view.hpp>
using namespace std;
using namespace mockturtle;
using namespace mockturtle::experimental;
namespace alice {
class wr_command : public command {
public:
explicit wr_command(const environment::ptr& env)
: command(env, "window rewriting") {
add_option("cut_size, -k", cut_size,
"set the cut size from 2 to 6, default = 4");
add_option("num_levels, -l", num_levels,
"set the window level, default = 5");
add_flag("--gain, -g", "optimize until there is no gain");
add_flag("--resub, -r", "window resub");
add_flag("--mffw, -w", "MFFW rewriting");
add_flag("--verbose, -v", "print the information");
}
protected:
void execute() {
clock_t begin, end;
double totalTime;
begin = clock();
auto aig = store<aig_network>().current();
window_rewriting_params ps;
ps.cut_size = cut_size;
ps.num_levels = num_levels;
if (is_set("resub")) {
window_resub_params ps_r;
if (is_set("gain")) {
window_aig_enumerative_resub(aig, ps_r);
} else {
window_aig_heuristic_resub(aig, ps_r);
}
aig = cleanup_dangling(aig);
} else {
if (is_set("gain")) {
uint64_t const size_before{aig.num_gates()};
uint64_t size_current{};
do {
size_current = aig.num_gates();
window_rewriting_stats win_st;
window_rewriting(aig, ps, &win_st);
if (is_set("verbose")) win_st.report();
aig = cleanup_dangling(aig);
} while (aig.num_gates() < size_current);
} else if (is_set("mffw")) {
window_rewriting_stats win_st;
mffw_rewriting(aig, ps, &win_st);
aig = cleanup_dangling(aig);
} else {
window_rewriting_stats win_st;
window_rewriting(aig, ps, &win_st);
aig = cleanup_dangling(aig);
}
}
phyLS::print_stats(aig);
store<aig_network>().extend();
store<aig_network>().current() = aig;
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
cout.setf(ios::fixed);
cout << "[CPU time] " << setprecision(2) << totalTime << " s" << endl;
}
private:
unsigned cut_size = 4u;
unsigned num_levels = 5u;
};
ALICE_ADD_COMMAND(wr, "Synthesis")
} // namespace alice
#endif

View File

@ -0,0 +1,55 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file xmginv.hpp
*
* @brief Inversion optimization of xmg
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef XMGINV_HPP
#define XMGINV_HPP
#include <mockturtle/mockturtle.hpp>
#include <mockturtle/utils/stopwatch.hpp>
#include "../core/xmginv.hpp"
namespace alice {
class xmginv_command : public command {
public:
explicit xmginv_command(const environment::ptr& env)
: command(env, "inversion optimization of xmg") {
add_flag("--verbose, -v", "print the information");
}
rules validity_rules() const { return {has_store_element<xmg_network>(env)}; }
protected:
void execute() {
/* derive some XMG */
xmg_network xmg = store<xmg_network>().current();
xmg_network xmg_opt;
stopwatch<>::duration time{0};
call_with_stopwatch(
time, [&]() { xmg_opt = phyLS::xmg_inv_optimization(xmg); });
store<xmg_network>().extend();
store<xmg_network>().current() = xmg_opt;
phyLS::print_stats(xmg_opt);
std::cout << fmt::format("[time]: {:5.2f} seconds\n", to_seconds(time));
}
};
ALICE_ADD_COMMAND(xmginv, "Synthesis")
} // namespace alice
#endif

View File

@ -1,5 +1,5 @@
/* phyLS: Advanced Logic Synthesis and Optimization tool /* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2019-2021 Ningbo University, Ningbo, China */ * Copyright (C) 2023 */
/** /**
* @file exact_dag.hpp * @file exact_dag.hpp

View File

@ -77,7 +77,7 @@ class lut_rewriting_manager {
}); });
// clean all redundant luts // clean all redundant luts
auto klut_opt = mockturtle::cleanup_luts(klut); auto klut_opt = mockturtle::cleanup_dangling(klut);
return klut_opt; return klut_opt;
} }
@ -341,43 +341,17 @@ class lut_rewriting_manager {
} }
void es(int nr_in, std::string tt, percy::chain& result) { void es(int nr_in, std::string tt, percy::chain& result) {
int node = nr_in - 1;
bool target = false;
while (true) {
spec spec; spec spec;
bsat_wrapper solver; chain c;
percy::partial_dag_encoder encoder2(solver);
encoder2.reset_sim_tts(nr_in);
spec.add_alonce_clauses = false;
spec.add_nontriv_clauses = false;
spec.add_lex_func_clauses = false;
spec.add_colex_clauses = false;
spec.add_noreapply_clauses = false;
spec.add_symvar_clauses = false;
spec.verbosity = 0; spec.verbosity = 0;
kitty::dynamic_truth_table f(nr_in); kitty::dynamic_truth_table f(nr_in);
kitty::create_from_hex_string(f, tt); kitty::create_from_hex_string(f, tt);
spec[0] = f; spec[0] = f;
auto dags = percy::pd_generate_filtered(node, nr_in);
spec.preprocess(); spec.preprocess();
for (auto& dag : dags) { auto res = pd_ser_synthesize_parallel(spec, c, 4, "../src/pd/");
percy::chain c; if (res == success) result.copy(c);
synth_result status;
status = percy::pd_cegar_synthesize(spec, c, dag, solver, encoder2);
if (status == success) {
result.copy(c);
target = true;
break;
}
}
if (target) {
break;
}
node++;
}
} }
private: private:

277
src/core/ps2.hpp Normal file
View File

@ -0,0 +1,277 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file ps2.hpp
*
* @brief Show statistics in the stored network
*
* @author Homyoung
* @since 2023/11/16
*/
#pragma once
#include <alice/alice.hpp>
#include <mockturtle/mockturtle.hpp>
#include <string>
#include <vector>
namespace phyLS {
using aig_names = mockturtle::names_view<mockturtle::aig_network>;
using mig_names = mockturtle::names_view<mockturtle::mig_network>;
using xag_names = mockturtle::names_view<mockturtle::xag_network>;
using xmg_names = mockturtle::names_view<mockturtle::xmg_network>;
struct function_counts {
int maj_num = 0;
int xor_num = 0;
int xnor_num = 0;
int xor3_num = 0;
int and_num = 0;
int or_num = 0;
int input_num = 0;
int unknown_num = 0;
};
enum reconfig_function { AND, OR, XOR, XNOR, XOR3, MAJ, INPUT, UNKNOWN };
template <typename network>
reconfig_function node_function(const network& ntk,
const typename network::node& node) {
if (ntk.is_pi(node) || ntk.is_constant(node)) {
return reconfig_function::INPUT;
} else if (ntk.is_and(node)) {
return reconfig_function::AND;
} else if (ntk.is_or(node)) {
return reconfig_function::OR;
} else if (ntk.is_xor(node)) {
return reconfig_function::XOR;
} else if (ntk.is_maj(node)) {
typename network::signal first_signal =
ntk._storage->nodes[node].children[0];
typename network::node first_fanin = ntk.get_node(first_signal);
if (ntk.is_constant(first_fanin)) {
if (first_signal.complement) {
return reconfig_function::OR;
} else {
return reconfig_function::AND;
}
} else {
return reconfig_function::MAJ;
}
} else if (ntk.is_xor3(node)) {
typename network::signal first_signal =
ntk._storage->nodes[node].children[0];
typename network::node first_fanin = ntk.get_node(first_signal);
if (ntk.is_constant(first_fanin)) {
if (first_signal.complement) {
return reconfig_function::XNOR;
} else {
return reconfig_function::XOR;
}
} else {
return reconfig_function::XOR3;
}
} else {
return reconfig_function::UNKNOWN;
}
}
template <typename network>
void update_counts(function_counts& counts, const network& ntk,
const typename network::node& node) {
reconfig_function func = node_function(ntk, node);
switch (func) {
case AND:
counts.and_num++;
break;
case OR:
counts.or_num++;
break;
case XOR:
counts.xor_num++;
break;
case XNOR:
counts.xnor_num++;
break;
case XOR3:
counts.xor3_num++;
break;
case MAJ:
counts.maj_num++;
break;
case INPUT:
counts.input_num++;
break;
case UNKNOWN:
default:
counts.unknown_num++;
}
}
template <typename network>
function_counts node_functions(const network& ntk) {
function_counts counts;
ntk.foreach_node([&](auto node) { update_counts(counts, ntk, node); });
return counts;
}
template <typename Ntk>
class critical_node_view : public Ntk {
public:
using storage = typename Ntk::storage;
using node = typename Ntk::node;
using signal = typename Ntk::signal;
public:
critical_node_view() {}
explicit critical_node_view(Ntk const& ntk) : Ntk(ntk), ntk(ntk) {
int depth = depth_ntk.depth();
depth_ntk.clear_visited();
nums_criti = 0;
depth_ntk.foreach_po([&](auto const& po, auto i) {
node pon = depth_ntk.get_node(po);
if (depth_ntk.level(pon) != depth) return;
nums_criti++;
recursive(pon, critical_path, i);
});
}
std::vector<node> recursive(node& n, std::vector<node>& critical, int i) {
if (depth_ntk.visited(n) != 0) return critical;
depth_ntk.set_visited(n, i + 1);
critical.emplace_back(n);
depth_ntk.foreach_fanin(n, [&](auto fi) {
node fin = depth_ntk.get_node(fi);
int level = depth_ntk.level(n);
if (depth_ntk.level(fin) == level - 1) {
recursive(fin, critical, i);
}
});
return critical;
}
std::vector<node> get_critical_path() { return critical_path; }
uint32_t get_critical_nums() { return nums_criti; }
private:
uint32_t nums_criti;
std::vector<node> critical_path;
Ntk const& ntk;
mockturtle::depth_view<Ntk> depth_ntk{ntk};
};
static void compute_cone(mockturtle::aig_network aig, uint64_t index,
std::unordered_map<int, int>& nodes, int outindex,
std::unordered_map<int, int>& ins) {
if (aig._storage->nodes[index].data[1].h1 == 0) {
// increment number of nodes in this cone
std::unordered_map<int, int>::iterator it = nodes.find(outindex);
if (it != nodes.end() && index > aig.num_pis()) {
// increment the number of nodes
it->second++;
}
// set node as visited
aig._storage->nodes[index].data[1].h1 = 1;
// traverse one side to the PIs
if (!aig.is_pi(aig._storage->nodes[index].children[0].index) &&
index > aig.num_pis()) {
if (aig._storage->nodes[index].children[0].data & 1)
aig._storage->nodes[index].children[0].data =
aig._storage->nodes[index].children[0].data - 1;
// calculate input node index
auto inIndex = aig._storage->nodes[index].children[0].data >> 1;
// im ignoring latches
if (inIndex > aig.num_pis()) {
// call recursion
compute_cone(aig, inIndex, nodes, outindex, ins);
}
}
// traverse the other side to the PIs
if (!aig.is_pi(aig._storage->nodes[index].children[1].index) &&
index > aig.num_pis()) {
if (aig._storage->nodes[index].children[1].data & 1)
aig._storage->nodes[index].children[1].data =
aig._storage->nodes[index].children[1].data - 1;
// calculate input node index
auto inIndex = aig._storage->nodes[index].children[1].data >> 1;
// im ignoring latches
if (inIndex > aig.num_pis()) {
// call recursion
compute_cone(aig, inIndex, nodes, outindex, ins);
}
}
// if my child is PI and was not visited yet, I increase the input counter
if (aig.is_ci(aig._storage->nodes[index].children[0].index) &&
aig._storage->nodes[aig._storage->nodes[index].children[0].index]
.data[1]
.h1 == 0) {
aig._storage->nodes[aig._storage->nodes[index].children[0].index]
.data[1]
.h1 = 1;
std::unordered_map<int, int>::iterator it = ins.find(outindex);
if (it != ins.end()) {
// increment the number of inputs
it->second++;
}
}
// if my other child is PI and was not visited yet, I phyLS increase the
// input counter
if (aig.is_ci(aig._storage->nodes[index].children[1].index) &&
aig._storage->nodes[aig._storage->nodes[index].children[1].index]
.data[1]
.h1 == 0) {
aig._storage->nodes[aig._storage->nodes[index].children[1].index]
.data[1]
.h1 = 1;
std::unordered_map<int, int>::iterator it = ins.find(outindex);
if (it != ins.end()) {
// increment the number of inputs
it->second++;
}
}
}
}
template <typename Ntk>
static int computeLevel(Ntk const& ntk, int index) {
// if node not visited
if (ntk._storage->nodes[index].data[1].h1 == 0) {
// set node as visited
ntk._storage->nodes[index].data[1].h1 = 1;
// if is input
if (ntk.is_ci(index)) {
return 0;
}
auto inIdx2 = ntk._storage->nodes[index].children[1].data;
if (inIdx2 & 1) inIdx2 = inIdx2 - 1;
// calculate input node index
auto inNode1 = inIdx2 >> 1;
int levelNode1 = computeLevel<Ntk>(ntk, inNode1);
auto inIdx = ntk._storage->nodes[index].children[0].data;
if (inIdx & 1) inIdx = inIdx - 1;
// calculate input node index
auto inNode0 = inIdx >> 1;
int levelNode0 = computeLevel<Ntk>(ntk, inNode0);
int level = 1 + std::max(levelNode0, levelNode1);
return level;
}
return 0;
}
} // namespace phyLS

View File

@ -3,7 +3,7 @@
namespace phyLS { namespace phyLS {
simulator::simulator(CircuitGraph& graph) : graph(graph) { simulator::simulator(CircuitGraph& graph) : graph(graph) {
pattern_num = 100; // 随机产生100个仿真向量 pattern_num = 10000; // 随机产生100个仿真向量
// max_branch = int( log2(pattern_num) ); //做cut的界 // max_branch = int( log2(pattern_num) ); //做cut的界
max_branch = 8; max_branch = 8;
sim_info.resize(graph.get_lines().size()); // 按照lines的id记录仿真向量的信息 sim_info.resize(graph.get_lines().size()); // 按照lines的id记录仿真向量的信息

54
src/core/utils.hpp Normal file
View File

@ -0,0 +1,54 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file utils.hpp
*
* @brief TODO
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef UTILS_HPP
#define UTILS_HPP
#include <mockturtle/networks/xag.hpp>
#include <mockturtle/networks/xmg.hpp>
using namespace mockturtle;
namespace phyLS {
std::array<xmg_network::signal, 3> get_children(xmg_network const& xmg,
xmg_network::node const& n) {
std::array<xmg_network::signal, 3> children;
xmg.foreach_fanin(n, [&children](auto const& f, auto i) { children[i] = f; });
std::sort(
children.begin(), children.end(),
[&](auto const& c1, auto const& c2) { return c1.index < c2.index; });
return children;
}
std::array<xag_network::signal, 2> get_xag_children(
xag_network const& xag, xag_network::node const& n) {
std::array<xag_network::signal, 2> children;
xag.foreach_fanin(n, [&children](auto const& f, auto i) { children[i] = f; });
std::sort(
children.begin(), children.end(),
[&](auto const& c1, auto const& c2) { return c1.index < c2.index; });
return children;
}
void print_children(std::array<xmg_network::signal, 3> const& children) {
auto i = 0u;
for (auto child : children) {
std::cout << "children " << i << " is " << child.index << " complemented ? "
<< child.complement << std::endl;
i++;
}
}
} // namespace phyLS
#endif

344
src/core/xmginv.hpp Normal file
View File

@ -0,0 +1,344 @@
/* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2023 */
/**
* @file xmginv.hpp
*
* @brief Inversion optimization of xmg
*
* @author Homyoung
* @since 2023/11/16
*/
#ifndef XMG_INV_HPP
#define XMG_INV_HPP
#include <mockturtle/algorithms/cleanup.hpp>
#include <mockturtle/networks/xmg.hpp>
#include <mockturtle/properties/migcost.hpp>
#include "utils.hpp"
using namespace mockturtle;
namespace phyLS {
/* use substitue method for inveters propagation */
xmg_network complement_node(xmg_network& xmg, xmg_network::node const& n) {
xmg_network::signal opt;
auto children = get_children(xmg, n);
if (xmg.is_maj(n)) {
children[0] = !children[0];
children[1] = !children[1];
children[2] = !children[2];
opt = xmg.create_maj_without_complement_opt(children[0], children[1],
children[2]) ^
true;
} else {
if (xmg.is_complemented(children[2])) {
children[2] = !children[2];
} else {
children[1] = !children[1];
}
opt =
xmg.create_xor_without_complement_opt(children[1], children[2]) ^ true;
}
xmg.substitute_node_without_complement_opt(n, opt);
return xmg;
}
/* print information */
void print_node(xmg_network const& xmg, xmg_network::node const& n) {
std::cout << " node " << n << " inverters infro: ";
xmg.foreach_fanin(n, [&](auto s) {
std::cout << " { " << s.index << " , " << s.complement << " } ";
});
std::cout << std::endl;
}
void print_network(xmg_network const& xmg) {
xmg.foreach_gate([&](auto n) { print_node(xmg, n); });
}
/******************************************************************************
* Types *
******************************************************************************/
class inv_manager {
public:
inv_manager(xmg_network xmg);
void compute_parents();
std::vector<xmg_network::node> get_parents(xmg_network::node const& n);
int num_invs_fanins(xmg_network::node const& n);
int num_invs_fanouts(xmg_network::node const& n);
int num_in_edges(xmg_network::node const& n);
int num_out_edges(xmg_network::node const& n);
int num_edges(xmg_network::node const& n);
int num_invs(xmg_network::node const& n);
int one_level_savings(xmg_network::node const& n);
int one_level_savings_nni(xmg_network::node const& n);
int two_level_savings(xmg_network::node const& n);
void xor_jump();
void one_level_optimization(const int& thres1, const int& thres2);
void two_level_optimization(const int& thres1, const int& thres2);
xmg_network run();
private:
xmg_network xmg;
std::map<xmg_network::node, std::vector<xmg_network::node>> pmap;
unsigned num_inv_origin{0u}, num_inv_opt{0u};
};
inv_manager::inv_manager(xmg_network xmg) : xmg(xmg) { compute_parents(); }
/* compute the node parents information and save it */
void inv_manager::compute_parents() {
xmg.foreach_gate([&](auto n) {
xmg.foreach_fanin(n, [&](auto c) {
auto it = pmap.find(xmg.get_node(c));
if (it == pmap.end()) {
std::vector<xmg_network::node> fout;
fout.push_back(n);
pmap[xmg.get_node(c)] = fout;
} else {
auto& f = it->second;
if (std::find(f.begin(), f.end(), n) == f.end()) {
f.push_back(n);
}
}
});
});
}
std::vector<xmg_network::node> inv_manager::get_parents(
xmg_network::node const& n) {
return pmap[n];
}
int inv_manager::num_invs_fanins(xmg_network::node const& n) {
int cost = 0;
xmg.foreach_fanin(n, [&](auto s) {
if (xmg.is_complemented(s)) {
cost++;
}
});
return cost;
}
int inv_manager::num_invs_fanouts(xmg_network::node const& n) {
int cost = 0u;
/* ordinary fanouts */
auto parents = get_parents(n);
for (const auto pn : parents) {
xmg.foreach_fanin(pn, [&](auto s) {
if (xmg.get_node(s) == n && xmg.is_complemented(s)) {
cost++;
}
});
}
/* POs */
xmg.foreach_po([&](auto const& f) {
if (xmg.get_node(f) == n && xmg.is_complemented(f)) {
cost++;
}
});
return cost;
}
int inv_manager::num_in_edges(xmg_network::node const& n) {
auto num_in = (xmg.is_maj(n) ? 3 : 2);
return num_in;
}
int inv_manager::num_out_edges(xmg_network::node const& n) {
/* pos */
int num_po = 0;
xmg.foreach_po([&](auto const& f) {
if (xmg.get_node(f) == n) {
num_po++;
}
});
return get_parents(n).size() + num_po;
}
int inv_manager::num_edges(xmg_network::node const& n) {
assert(xmg.is_maj(n) || xmg.is_xor3(n));
return num_in_edges(n) + num_out_edges(n);
}
int inv_manager::num_invs(xmg_network::node const& n) {
return num_invs_fanins(n) + num_invs_fanouts(n);
}
int inv_manager::one_level_savings(xmg_network::node const& n) {
int before, after;
before = num_invs(n);
if (xmg.is_maj(n)) {
after = num_edges(n) - before;
} else {
int in, out;
out = num_out_edges(n) - num_invs_fanouts(n);
auto tmp = num_invs_fanins(n);
if (tmp == 1 || tmp == 3) {
in = 0;
} else if (tmp == 2 || tmp == 0) {
in = 1;
} else {
assert(false);
}
after = in + out;
}
return before - after;
}
int inv_manager::one_level_savings_nni(xmg_network::node const& n) {
int before, after, after_nni;
before = num_invs(n);
if (xmg.is_maj(n)) {
after = num_edges(n) - before;
if (num_invs_fanins(n) == 2) {
}
} else {
int in, out;
out = num_out_edges(n) - num_invs_fanouts(n);
auto tmp = num_invs_fanins(n);
if (tmp == 1 || tmp == 3) {
in = 0;
} else if (tmp == 2 || tmp == 0) {
in = 1;
} else {
assert(false);
}
after = in + out;
}
return before - after;
}
int inv_manager::two_level_savings(xmg_network::node const& n) {
assert(!xmg.is_pi(n));
auto parents = get_parents(n);
int total_savings = 0;
/* no parents */
if (parents.size() == 0) {
return one_level_savings(n);
} else {
auto child_savings = one_level_savings(n);
for (const auto& p : parents) {
total_savings += one_level_savings(p);
xmg.foreach_fanin(p, [&](auto s) {
if (xmg.get_node(s) == n && xmg.is_complemented(s)) {
if (xmg.is_complemented(s)) {
total_savings -= 2;
} else {
total_savings += 2;
}
}
});
}
total_savings += child_savings;
}
return total_savings;
}
void inv_manager::one_level_optimization(const int& thres1, const int& thres2) {
xmg.foreach_gate([&](auto n) {
if (one_level_savings(n) >= thres1) {
xmg.complement_node(n, pmap[n]);
} else if (two_level_savings(n) >= thres2) {
auto parents = pmap[n];
xmg.complement_node(n, pmap[n]);
for (const auto& p : parents) {
xmg.complement_node(p, pmap[p]);
}
}
});
}
void inv_manager::two_level_optimization(const int& thres1, const int& thres2) {
xmg.foreach_gate([&](auto n) {
auto parents = pmap[n];
auto savings = two_level_savings(n);
if (savings >= thres1) {
xmg.complement_node(n, pmap[n]);
for (const auto& p : parents) {
xmg.complement_node(p, pmap[p]);
}
} else if (one_level_savings(n) >= thres2) {
xmg.complement_node(n, pmap[n]);
}
});
}
void inv_manager::xor_jump() {
xmg.foreach_gate([&](const auto& n) {
if (xmg.is_xor3(n)) {
xmg.xor_inv_jump(n);
}
});
}
xmg_network inv_manager::run() {
num_inv_origin = num_inverters(xmg);
one_level_optimization(0, 1);
two_level_optimization(1, 0);
one_level_optimization(0, 1);
two_level_optimization(1, 1);
num_inv_opt = num_inverters(xmg);
xor_jump();
std::cout << "[xmginv] "
<< " num_inv_origin: " << num_inv_origin
<< " num_opt_inv: " << num_inv_opt << std::endl;
auto xmg_opt = mockturtle::cleanup_dangling(xmg);
return xmg_opt;
}
/* public function */
xmg_network xmg_inv_optimization(xmg_network& xmg) {
inv_manager mgr(xmg);
return mgr.run();
}
} // namespace phyLS
#endif

335636
src/lzmlib.aig Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
/* phyLS: Advanced Logic Synthesis and Optimization tool /* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2019- Ningbo University, Ningbo, China */ * Copyright (C) 2023 */
/** /**
* @file build_xag_db.hpp * @file build_xag_db.hpp

View File

@ -1,5 +1,5 @@
/* phyLS: Advanced Logic Synthesis and Optimization tool /* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2019- Ningbo University, Ningbo, China */ * Copyright (C) 2023 */
/** /**
* @file xag_dec.hpp * @file xag_dec.hpp

View File

@ -1,5 +1,5 @@
/* phyLS: Advanced Logic Synthesis and Optimization tool /* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2019- Ningbo University, Ningbo, China */ * Copyright (C) 2023 */
/** /**
* @file xag_lut_dec.hpp * @file xag_lut_dec.hpp

View File

@ -1,27 +1,5 @@
/* phyLS: Advanced Logic Synthesis and Optimization tool /* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2019- Ningbo University, Ningbo, China * Copyright (C) 2023 */
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*! /*!
\file mg.hpp \file mg.hpp

View File

@ -1,5 +1,6 @@
/* phyLS: Advanced Logic Synthesis and Optimization tool /* phyLS: powerful heightened yielded Logic Synthesis
* Copyright (C) 2019- Ningbo University, Ningbo, China * Copyright (C) 2023 */
/* /*
\file stp_npn.hpp \file stp_npn.hpp
\brief Replace with size-optimum STP-based exact synthesis from NPN \brief Replace with size-optimum STP-based exact synthesis from NPN
@ -72,7 +73,7 @@ class stp_npn_resynthesis {
std::unordered_map<std::string, std::vector<std::string>> opt_klut; std::unordered_map<std::string, std::vector<std::string>> opt_klut;
void load_optimal_klut() { void load_optimal_klut() {
std::ifstream infile("../src/networks/stp/opt_stp.txt"); std::ifstream infile("../src/networks/stp/opt_map.txt");
if (!infile) { if (!infile) {
std::cout << " Cannot open file " << std::endl; std::cout << " Cannot open file " << std::endl;
assert(false); assert(false);

BIN
src/pd/pd1.bin Normal file

Binary file not shown.

BIN
src/pd/pd2.bin Normal file

Binary file not shown.

BIN
src/pd/pd3.bin Normal file

Binary file not shown.

BIN
src/pd/pd4.bin Normal file

Binary file not shown.

BIN
src/pd/pd5.bin Normal file

Binary file not shown.

BIN
src/pd/pd6.bin Normal file

Binary file not shown.

BIN
src/pd/pd7.bin Normal file

Binary file not shown.

BIN
src/pd/pd8.bin Normal file

Binary file not shown.

BIN
src/pd/pd9.bin Normal file

Binary file not shown.

View File

@ -53,5 +53,22 @@
#include "commands/stpfr.hpp" #include "commands/stpfr.hpp"
#include "commands/exact/exact_lut.hpp" #include "commands/exact/exact_lut.hpp"
#include "commands/exact/lutrw.hpp" #include "commands/exact/lutrw.hpp"
#include "commands/abc/if.hpp"
#include "commands/abc/map.hpp"
#include "commands/window_rewriting.hpp"
#include "commands/ps2.hpp"
#include "commands/xmg/xmginv.hpp"
#include "commands/abc/read_genlib.hpp"
#include "commands/abc/&nf.hpp"
#include "commands/abc/&if.hpp"
#include "commands/abc/put.hpp"
#include "commands/abc/amap.hpp"
#include "commands/abc/compress2rs.hpp"
#include "commands/abc/resyn2rs.hpp"
#include "commands/abc/dc2.hpp"
#include "commands/abc/sop.hpp"
#include "commands/abc/balance.hpp"
#include "commands/abc/refactor.hpp"
#include "commands/abc/rewrite.hpp"
ALICE_MAIN(phyLS) ALICE_MAIN(phyLS)