15 template <
typename Ntk>
24 int nPartitionSizeMin;
25 std::string strVerbosePrefix;
28 std::map<Ntk *, std::tuple<std::set<int>, std::vector<int>, std::vector<bool>, std::vector<int>>> mSubNtk2Io;
29 std::set<int> sBlocked;
30 std::vector<bool> vFailed;
33 template<
typename... Args>
34 void Print(
int nVerboseLevel, Args... args);
37 void GetIo(std::set<int>
const &sNodes, std::set<int> &sInputs, std::set<int> &sOutputs);
38 std::set<int> GetFanouts(std::set<int>
const &sNodes, std::set<int>
const &sOutputs);
39 std::set<int> GetUnblockedNeighborsAndInners(
int id,
int nRadius);
40 Ntk *ExtractDisjoint(
int id);
54 template <
typename Ntk>
55 template <
typename... Args>
56 inline void Partitioner<Ntk>::Print(
int nVerboseLevel, Args... args) {
57 if(nVerbose > nVerboseLevel) {
58 std::cout << strVerbosePrefix;
59 for(
int i = 0; i < nVerboseLevel; i++) {
63 std::cout << std::endl;
71 template <
typename Ntk>
72 void Partitioner<Ntk>::GetIo(std::set<int>
const &sNodes, std::set<int> &sInputs, std::set<int> &sOutputs) {
76 pNtk->ForEachFanin(
id, [&](
int fi) {
77 if(!sNodes.count(fi)) {
82 pNtk->ForEachFanout(
id,
true, [&](
int fo) {
83 if(!sNodes.count(fo)) {
93 template <
typename Ntk>
94 std::set<int> Partitioner<Ntk>::GetFanouts(std::set<int>
const &sNodes, std::set<int>
const &sOutputs) {
95 std::set<int> sFanouts;
96 for(
int id: sOutputs) {
97 pNtk->ForEachFanout(
id,
false, [&](
int fo) {
98 if(!sNodes.count(fo)) {
106 template <
typename Ntk>
107 std::set<int> Partitioner<Ntk>::GetUnblockedNeighborsAndInners(
int id,
int nRadius) {
110 std::vector<int> vNodes = pNtk->GetNeighbors(
id,
false, nRadius);
111 vNodes.push_back(
id);
112 std::set<int> sNodes(vNodes.begin(), vNodes.end());
113 Print(2,
"radius",
NS(), nRadius,
":",
"size =", int_size(sNodes));
115 for(std::set<int>::iterator it = sNodes.begin(); it != sNodes.end();) {
116 if(sBlocked.count(*it)) {
117 it = sNodes.erase(it);
122 Print(2,
"unblocked:",
"size =", int_size(sNodes));
123 if(int_size(sNodes) > nPartitionSize) {
125 return std::set<int>();
128 std::set<int> sInputs, sOutputs;
129 GetIo(sNodes, sInputs, sOutputs);
130 Print(3,
"nodes:", sNodes);
131 Print(3,
"inputs:", sInputs);
132 Print(3,
"outputs:", sOutputs);
134 std::set<int> sFanouts = GetFanouts(sNodes, sOutputs);
135 std::vector<int> vInners = pNtk->GetInners(sFanouts, sInputs);
136 while(!vInners.empty()) {
137 Print(2,
"inner size =", int_size(vInners));
139 for(
int id: vInners) {
140 if(sBlocked.count(
id)) {
142 return std::set<int>();
146 sNodes.insert(vInners.begin(), vInners.end());
147 Print(2,
"expanded:",
"size =", int_size(sNodes));
148 if(int_size(sNodes) > nPartitionSize) {
150 return std::set<int>();
152 GetIo(sNodes, sInputs, sOutputs);
153 Print(3,
"nodes:", sNodes);
154 Print(3,
"inputs:", sInputs);
155 Print(3,
"outputs:", sOutputs);
157 sFanouts = GetFanouts(sNodes, sOutputs);
158 vInners = pNtk->GetInners(sFanouts, sInputs);
163 template <
typename Ntk>
164 Ntk *Partitioner<Ntk>::ExtractDisjoint(
int id) {
166 assert(!sBlocked.count(
id));
168 std::set<int> sNodes = GetUnblockedNeighborsAndInners(
id, nRadius);
169 Print(1,
"radius",
NS(), nRadius,
":",
"size =", int_size(sNodes));
173 std::set<int> sNodesNew = GetUnblockedNeighborsAndInners(
id, nRadius + 1);
174 Print(1,
"radius",
NS(), nRadius + 1,
":",
"size =", int_size(sNodesNew));
176 while(!sNodesNew.empty()) {
177 if(int_size(sNodes) == int_size(sNodesNew)) {
182 sNodesNew = GetUnblockedNeighborsAndInners(
id, nRadius + 1);
183 Print(1,
"radius",
NS(), nRadius + 1,
":",
"size =", int_size(sNodesNew));
185 if(int_size(sNodes) < nPartitionSizeMin) {
189 std::set<int> sInputs, sOutputs;
190 GetIo(sNodes, sInputs, sOutputs);
235 for(
auto const &entry: mSubNtk2Io) {
236 if(!pNtk->IsReachable(sOutputs, std::get<1>(entry.second))) {
239 if(!pNtk->IsReachable(std::get<3>(entry.second), sInputs)) {
247 assert(int_size(sNodes) <= nPartitionSize);
248 assert(int_size(sNodes) >= nPartitionSizeMin);
250 std::vector<int> vInputs(sInputs.begin(), sInputs.end());
251 std::vector<int> vOutputs(sOutputs.begin(), sOutputs.end());
252 Ntk *pSubNtk = pNtk->Extract(sNodes, vInputs, vOutputs);
254 for(
int id: sNodes) {
257 mSubNtk2Io.emplace(pSubNtk, std::make_tuple(std::move(sNodes), std::move(vInputs), std::vector<bool>(vInputs.size()), std::move(vOutputs)));
265 template <
typename Ntk>
267 nVerbose(pPar->nPartitionerVerbose),
268 nPartitionSize(pPar->nPartitionSize),
269 nPartitionSizeMin(pPar->nPartitionSizeMin) {
272 template <
typename Ntk>
275 assert(mSubNtk2Io.empty());
284 template <
typename Ntk>
287 vFailed.resize(pNtk->GetNumNodes());
288 std::mt19937 rng(iSeed);
289 std::vector<int> vInts = pNtk->GetInts();
290 std::shuffle(vInts.begin(), vInts.end(), rng);
291 for(
int i = 0; i < int_size(vInts); i++) {
296 if(!sBlocked.count(
id)) {
297 Print(0,
"try partitioning with node",
id,
"(", i,
"/", int_size(vInts),
")");
298 Ntk *pSubNtk = ExtractDisjoint(
id);
308 template <
typename Ntk>
310 for(
int i: std::get<0>(mSubNtk2Io[pSubNtk])) {
313 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]));
314 std::vector<int> &vOldOutputs = std::get<3>(mSubNtk2Io[pSubNtk]);
315 std::vector<int> &vNewOutputs = vNewSignals.first;
316 std::vector<bool> &vNewCompls = vNewSignals.second;
318 std::map<int, int> mOutput2Idx;
319 for(
int idx = 0; idx < int_size(vOldOutputs); idx++) {
320 mOutput2Idx[vOldOutputs[idx]] = idx;
322 for(
auto &entry: mSubNtk2Io) {
323 if(entry.first != pSubNtk) {
324 std::vector<int> &vInputs = std::get<1>(entry.second);
325 std::vector<bool> &vCompls = std::get<2>(entry.second);
326 for(
int i = 0; i < int_size(vInputs); i++) {
327 if(mOutput2Idx.count(vInputs[i])) {
328 int idx = mOutput2Idx[vInputs[i]];
329 vInputs[i] = vNewOutputs[idx];
330 vCompls[i] = vCompls[i] ^ vNewCompls[idx];
336 mSubNtk2Io.erase(pSubNtk);
#define ABC_NAMESPACE_CXX_HEADER_START
#define ABC_NAMESPACE_CXX_HEADER_END
void AssignNetwork(Ntk *pNtk)
Partitioner(Parameter const *pPar)
void Insert(Ntk *pSubNtk)
void PrintNext(std::ostream &os, T t)