pattern dffmux state cemuxAB rstmuxBA state sigD match dff select dff->type == $dff select GetSize(port(dff, \D)) > 1 endmatch code sigD sigD = port(dff, \D); endcode match rstmux select rstmux->type == $mux select GetSize(port(rstmux, \Y)) > 1 index port(rstmux, \Y) === sigD choice BA {\B, \A} select port(rstmux, BA).is_fully_const() set rstmuxBA BA semioptional endmatch code sigD if (rstmux) sigD = port(rstmux, rstmuxBA == \B ? \A : \B); endcode match cemux select cemux->type == $mux select GetSize(port(cemux, \Y)) > 1 index port(cemux, \Y) === sigD choice AB {\A, \B} index port(cemux, AB) === port(dff, \Q) set cemuxAB AB semioptional endmatch code if (!cemux && !rstmux) reject; endcode code Const rst; SigSpec D; if (cemux) { D = port(cemux, cemuxAB == \A ? \B : \A); if (rstmux) rst = port(rstmux, rstmuxBA).as_const(); else rst = Const(State::Sx, GetSize(D)); } else { log_assert(rstmux); D = port(rstmux, rstmuxBA == \B ? \A : \B); rst = port(rstmux, rstmuxBA).as_const(); } SigSpec Q = port(dff, \Q); int width = GetSize(D); SigSpec &dffD = dff->connections_.at(\D); SigSpec &dffQ = dff->connections_.at(\Q); Const init; for (const auto &b : Q) { auto it = b.wire->attributes.find(\init); init.bits.push_back(it == b.wire->attributes.end() ? State::Sx : it->second[b.offset]); } auto cmpx = [=](State lhs, State rhs) { if (lhs == State::Sx || rhs == State::Sx) return true; return lhs == rhs; }; int i = width; while (i > 2) { i--; if (D[i] != D[i-1]) break; if (!cmpx(rst[i], rst[i-1])) break; if (!cmpx(init[i], init[i-1])) break; if (!cmpx(rst[i], init[i])) break; module->connect(Q[i], Q[i-1]); did_something = true; } if (i < width-1) { if (cemux) { SigSpec &ceA = cemux->connections_.at(\A); SigSpec &ceB = cemux->connections_.at(\B); SigSpec &ceY = cemux->connections_.at(\Y); ceA.remove(i, width-i); ceB.remove(i, width-i); ceY.remove(i, width-i); cemux->fixup_parameters(); } dffD.remove(i, width-i); dffQ.remove(i, width-i); dff->fixup_parameters(); log("dffcemux pattern in %s: dff=%s, cemux=%s; removed top %d bits.\n", log_id(module), log_id(dff), log_id(cemux), width-i); accept; } else if (cemux) { SigSpec &ceA = cemux->connections_.at(\A); SigSpec &ceB = cemux->connections_.at(\B); SigSpec &ceY = cemux->connections_.at(\Y); int count = 0; for (int i = width-1; i >= 0; i--) { if (D[i].wire) continue; Wire *w = Q[i].wire; auto it = w->attributes.find(\init); State init; if (it != w->attributes.end()) init = it->second[Q[i].offset]; else init = State::Sx; if (init == State::Sx || init == D[i].data) { count++; module->connect(Q[i], D[i]); ceA.remove(i); ceB.remove(i); ceY.remove(i); dffD.remove(i); dffQ.remove(i); } } if (count > 0) { did_something = true; cemux->fixup_parameters(); dff->fixup_parameters(); log("dffcemux pattern in %s: dff=%s, cemux=%s; removed %d constant bits.\n", log_id(module), log_id(dff), log_id(cemux), count); } accept; } endcode