pattern reduce state portname udata >> chain longest_chain udata > non_first_cells udata leaves code non_first_cells.clear(); subpattern(setup); endcode match first select first->type.in($_AND_, $_OR_, $_XOR_) filter !non_first_cells.count(first) generate SigSpec A = module->addWire(NEW_ID); SigSpec B = module->addWire(NEW_ID); SigSpec Y = module->addWire(NEW_ID); switch (rng(3)) { case 0: module->addAndGate(NEW_ID, A, B, Y); break; case 1: module->addOrGate(NEW_ID, A, B, Y); break; case 2: module->addXorGate(NEW_ID, A, B, Y); break; } endmatch code leaves = SigSpec(); longest_chain.clear(); chain.push_back(make_pair(first, \A)); subpattern(tail); chain.back().second = \B; subpattern(tail); finally chain.pop_back(); log_assert(chain.empty()); if (GetSize(longest_chain) > 1) accept; endcode // ------------------------------------------------------------------ subpattern setup match first select first->type.in($_AND_, $_OR_, $_XOR_) endmatch code portname portname = \A; branch; portname = \B; endcode match next select nusers(port(next, \Y)) == 2 select next->type.in($_AND_, $_OR_, $_XOR_) index next->type === first->type index port(next, \Y) === port(first, portname) endmatch code non_first_cells.insert(next); endcode // ------------------------------------------------------------------ subpattern tail arg first match next semioptional select nusers(port(next, \Y)) == 2 select next->type.in($_AND_, $_OR_, $_XOR_) index next->type === chain.back().first->type index port(next, \Y) === port(chain.back().first, chain.back().second) generate 10 SigSpec A = module->addWire(NEW_ID); SigSpec B = module->addWire(NEW_ID); SigSpec Y = port(chain.back().first, chain.back().second); Cell *c = module->addAndGate(NEW_ID, A, B, Y); c->type = chain.back().first->type; endmatch code if (next) { chain.push_back(make_pair(next, \A)); subpattern(tail); chain.back().second = \B; subpattern(tail); } else { if (GetSize(chain) > GetSize(longest_chain)) longest_chain = chain; leaves.append(port(chain.back().first, chain.back().second)); } finally if (next) chain.pop_back(); endcode