15 template <
typename Ntk>
24 int nPartitionSizeMin;
25 std::string strVerbosePrefix;
29 std::vector<int> vLevels;
30 std::map<Ntk *, std::tuple<std::set<int>, std::vector<int>, std::vector<bool>, std::vector<int>>> mSubNtk2Io;
31 std::set<int> sBlocked;
32 std::vector<bool> vFailed;
35 template<
typename... Args>
36 void Print(
int nVerboseLevel, Args... args);
40 std::vector<int> GetIOI(
int id,
int nLevels);
41 Ntk *ExtractIOI(
int id);
55 template <
typename Ntk>
56 template <
typename... Args>
57 inline void LevelBasePartitioner<Ntk>::Print(
int nVerboseLevel, Args... args) {
58 if(nVerbose > nVerboseLevel) {
59 std::cout << strVerbosePrefix;
60 for(
int i = 0; i < nVerboseLevel; i++) {
64 std::cout << std::endl;
72 template <
typename Ntk>
73 void LevelBasePartitioner<Ntk>::ComputeLevel() {
76 vLevels.resize(pNtk->GetNumNodes());
77 pNtk->ForEachInt([&](
int id) {
78 pNtk->ForEachFanin(
id, [&](
int fi) {
79 if(vLevels[
id] < vLevels[fi]) {
80 vLevels[id] = vLevels[fi];
84 if(nMaxLevel < vLevels[
id]) {
85 nMaxLevel = vLevels[id];
90 template <
typename Ntk>
91 std::vector<int> LevelBasePartitioner<Ntk>::GetIOI(
int id,
int nLevels) {
92 std::vector<int> vNodes, vNodes2;
94 pNtk->ForEachTfiUpdate(
id,
false, [&](
int fi) {
95 if(vLevels[fi] < vLevels[
id] - nLevels) {
101 pNtk->ForEachTfosUpdate(vNodes,
false, [&](
int fo) {
102 if(vLevels[fo] > vLevels[
id] + nLevels) {
105 vNodes2.push_back(fo);
109 pNtk->ForEachTfisUpdate(vNodes2,
false, [&](
int fi) {
110 if(vLevels[fi] < vLevels[
id] - nLevels) {
113 vNodes.push_back(fi);
119 template <
typename Ntk>
120 Ntk *LevelBasePartitioner<Ntk>::ExtractIOI(
int id) {
122 assert(!sBlocked.count(
id));
124 std::vector<int> vNodes = GetIOI(
id, nLevels);
125 Print(1,
"level",
NS(), nLevels,
":",
"size =", int_size(vNodes));
126 std::vector<int> vNodesNew = GetIOI(
id, nLevels + 1);
127 Print(1,
"level",
NS(), nLevels + 1,
":",
"size =", int_size(vNodesNew));
129 while(int_size(vNodesNew) < nPartitionSize) {
130 if(vLevels[
id] - nLevels < 1 && vLevels[
id] + nLevels >= nMaxLevel) {
135 vNodesNew = GetIOI(
id, nLevels + 1);
136 Print(1,
"level",
NS(), nLevels + 1,
":",
"size =", int_size(vNodesNew));
138 std::set<int> sNodes(vNodes.begin(), vNodes.end());
140 for(std::set<int>::iterator it = sNodes.begin(); it != sNodes.end();) {
141 if(sBlocked.count(*it)) {
142 it = sNodes.erase(it);
147 Print(1,
"checking:",
"size =", int_size(sNodes));
149 std::set<int> sInputs, sOutputs;
150 for(
int id: sNodes) {
151 pNtk->ForEachFanin(
id, [&](
int fi) {
152 if(!sNodes.count(fi)) {
156 bool fOutput =
false;
157 pNtk->ForEachFanout(
id,
true, [&](
int fo) {
158 if(!sNodes.count(fo)) {
166 Print(2,
"nodes:", sNodes);
167 Print(2,
"inputs:", sInputs);
168 Print(2,
"outputs:", sOutputs);
169 if(int_size(sNodes) < nPartitionSizeMin) {
173 std::set<int> sFanouts;
174 for(
int id: sOutputs) {
175 pNtk->ForEachFanout(
id,
false, [&](
int fo) {
176 if(!sNodes.count(fo)) {
181 if(pNtk->IsReachable(sFanouts, sInputs)) {
184 for(
auto const &entry: mSubNtk2Io) {
185 if(!pNtk->IsReachable(sOutputs, std::get<1>(entry.second))) {
188 if(!pNtk->IsReachable(std::get<3>(entry.second), sInputs)) {
194 std::vector<int> vInputs(sInputs.begin(), sInputs.end());
195 std::vector<int> vOutputs(sOutputs.begin(), sOutputs.end());
196 Ntk *pSubNtk = pNtk->Extract(sNodes, vInputs, vOutputs);
198 for(
int id: sNodes) {
201 mSubNtk2Io.emplace(pSubNtk, std::make_tuple(std::move(sNodes), std::move(vInputs), std::vector<bool>(vInputs.size()), std::move(vOutputs)));
209 template <
typename Ntk>
211 nVerbose(pPar->nPartitionerVerbose),
212 nPartitionSize(pPar->nPartitionSize),
213 nPartitionSizeMin(pPar->nPartitionSizeMin) {
216 template <
typename Ntk>
219 assert(mSubNtk2Io.empty());
229 template <
typename Ntk>
232 vFailed.resize(pNtk->GetNumNodes());
233 if(vLevels.empty()) {
236 std::mt19937 rng(iSeed);
237 std::vector<int> vInts = pNtk->GetInts();
238 std::shuffle(vInts.begin(), vInts.end(), rng);
239 for(
int i = 0; i < int_size(vInts); i++) {
244 if(!sBlocked.count(
id)) {
245 Print(0,
"try partitioning with node",
id,
"(", i,
"/", int_size(vInts),
")");
246 Ntk *pSubNtk = ExtractIOI(
id);
256 template <
typename Ntk>
258 for(
int i: std::get<0>(mSubNtk2Io[pSubNtk])) {
261 std::pair<std::vector<int>, std::vector<bool>> vNewSignals = pNtk->Insert(pSubNtk, std::get<1>(mSubNtk2Io[pSubNtk]), std::get<2>(mSubNtk2Io[pSubNtk]), std::get<3>(mSubNtk2Io[pSubNtk]));
262 std::vector<int> &vOldOutputs = std::get<3>(mSubNtk2Io[pSubNtk]);
263 std::vector<int> &vNewOutputs = vNewSignals.first;
264 std::vector<bool> &vNewCompls = vNewSignals.second;
266 std::map<int, int> mOutput2Idx;
267 for(
int idx = 0; idx < int_size(vOldOutputs); idx++) {
268 mOutput2Idx[vOldOutputs[idx]] = idx;
270 for(
auto &entry: mSubNtk2Io) {
271 if(entry.first != pSubNtk) {
272 std::vector<int> &vInputs = std::get<1>(entry.second);
273 std::vector<bool> &vCompls = std::get<2>(entry.second);
274 for(
int i = 0; i < int_size(vInputs); i++) {
275 if(mOutput2Idx.count(vInputs[i])) {
276 int idx = mOutput2Idx[vInputs[i]];
277 vInputs[i] = vNewOutputs[idx];
278 vCompls[i] = vCompls[i] ^ vNewCompls[idx];
284 mSubNtk2Io.erase(pSubNtk);
#define ABC_NAMESPACE_CXX_HEADER_START
#define ABC_NAMESPACE_CXX_HEADER_END
void Insert(Ntk *pSubNtk)
LevelBasePartitioner(Parameter const *pPar)
void AssignNetwork(Ntk *pNtk)
void PrintNext(std::ostream &os, T t)