1
0
mirror of synced 2026-05-16 19:45:21 +00:00

Merge pull request #5888 from mikesinouye/pmux

opt_muxtree: reuse knowledge_t and pass by reference
This commit is contained in:
Emil J
2026-05-15 16:21:33 +00:00
committed by GitHub

View File

@@ -200,6 +200,29 @@ struct OptMuxtreeWorker
root_muxes.at(driving_mux) = true;
}
struct knowledge_t
{
// Known inactive signals
// The payload is a reference counter used to manage the list
// When it is non-zero, the signal in known to be inactive
// When it reaches zero, the map element is removed
std::vector<int> known_inactive;
// database of known active signals
std::vector<int> known_active;
// this is just used to keep track of visited muxes in order to prohibit
// endless recursion in mux loops
std::vector<bool> visited_muxes;
// Initialize with the maximum possible sizes
knowledge_t(int num_bits, int num_muxes) {
known_inactive.assign(num_bits, 0);
known_active.assign(num_bits, 0);
visited_muxes.assign(num_muxes, false);
}
};
OptMuxtreeWorker(RTLIL::Design *design, RTLIL::Module *module) :
design(design), module(module), assign_map(module), removed_count(0)
{
@@ -227,11 +250,13 @@ struct OptMuxtreeWorker
populate_roots();
knowledge_t shared_knowledge(GetSize(bit2info), GetSize(mux2info));
for (int mux_idx = 0; mux_idx < GetSize(root_muxes); mux_idx++)
if (root_muxes.at(mux_idx)) {
log_debug(" Root of a mux tree: %s%s\n", mux2info[mux_idx].cell, root_enable_muxes.at(mux_idx) ? " (pure)" : "");
root_mux_rerun.erase(mux_idx);
eval_root_mux(mux_idx);
eval_root_mux(shared_knowledge, mux_idx);
if (glob_evals_left == 0) {
log(" Giving up (too many iterations)\n");
return;
@@ -243,7 +268,7 @@ struct OptMuxtreeWorker
log_debug(" Root of a mux tree: %s (rerun as non-pure)\n", mux2info[mux_idx].cell);
log_assert(root_enable_muxes.at(mux_idx));
root_mux_rerun.erase(mux_idx);
eval_root_mux(mux_idx);
eval_root_mux(shared_knowledge, mux_idx);
if (glob_evals_left == 0) {
log(" Giving up (too many iterations)\n");
return;
@@ -334,29 +359,6 @@ struct OptMuxtreeWorker
return results;
}
struct knowledge_t
{
// Known inactive signals
// The payload is a reference counter used to manage the list
// When it is non-zero, the signal in known to be inactive
// When it reaches zero, the map element is removed
std::vector<int> known_inactive;
// database of known active signals
std::vector<int> known_active;
// this is just used to keep track of visited muxes in order to prohibit
// endless recursion in mux loops
std::vector<bool> visited_muxes;
// Initialize with the maximum possible sizes
knowledge_t(int num_bits, int num_muxes) {
known_inactive.assign(num_bits, 0);
known_active.assign(num_bits, 0);
visited_muxes.assign(num_muxes, false);
}
};
static void activate_port(knowledge_t &knowledge, int port_idx, const muxinfo_t &muxinfo) {
// First, mark all other ports inactive
for (int i = 0; i < GetSize(muxinfo.ports); i++) {
@@ -579,14 +581,14 @@ struct OptMuxtreeWorker
}
}
void eval_root_mux(int mux_idx)
void eval_root_mux(knowledge_t &knowledge, int mux_idx)
{
log_assert(glob_evals_left > 0);
knowledge_t knowledge(GetSize(bit2info), GetSize(mux2info));
knowledge.visited_muxes[mux_idx] = true;
limits_t limits = {};
limits.do_mark_ports_observable = root_enable_muxes.at(mux_idx);
eval_mux(knowledge, mux_idx, limits);
knowledge.visited_muxes[mux_idx] = false;
}
};