USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-void proc_get_const(RTLIL::SigSpec &sig, RTLIL::CaseRule &rule)
-{
- log_assert(rule.compare.size() == 0);
-
- while (1) {
- RTLIL::SigSpec tmp = sig;
- for (auto &it : rule.actions)
- tmp.replace(it.first, it.second);
- if (tmp == sig)
- break;
- sig = tmp;
- }
-}
-
-void proc_init(RTLIL::Module *mod, RTLIL::Process *proc)
+void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc)
{
bool found_init = false;
for (auto &action : sync->actions)
{
RTLIL::SigSpec lhs = action.first;
- RTLIL::SigSpec rhs = action.second;
-
- proc_get_const(rhs, proc->root_case);
+ RTLIL::SigSpec rhs = sigmap(action.second);
if (!rhs.is_fully_const())
log_cmd_error("Failed to get a constant init value for %s: %s\n", log_signal(lhs), log_signal(rhs));
extra_args(args, 1, design);
for (auto mod : design->modules())
- if (design->selected(mod))
+ if (design->selected(mod)) {
+ SigMap sigmap(mod);
for (auto &proc_it : mod->processes)
if (design->selected(mod, proc_it.second))
- proc_init(mod, proc_it.second);
+ proc_init(mod, sigmap, proc_it.second);
+ }
}
} ProcInitPass;
RTLIL::Module *module;
SigMap sigmap;
- int count = 0;
+ int removed_count = 0, promoted_count = 0;
PruneWorker(RTLIL::Module *mod) : module(mod), sigmap(mod) {}
- pool<RTLIL::SigBit> do_switch(RTLIL::SwitchRule *sw, pool<RTLIL::SigBit> assigned)
+ pool<RTLIL::SigBit> do_switch(RTLIL::SwitchRule *sw, pool<RTLIL::SigBit> assigned, pool<RTLIL::SigBit> &affected)
{
pool<RTLIL::SigBit> all_assigned;
bool full_case = sw->get_bool_attribute("\\full_case");
for (auto it : sw->cases) {
if (it->compare.empty())
full_case = true;
- pool<RTLIL::SigBit> case_assigned = do_case(it, assigned);
+ pool<RTLIL::SigBit> case_assigned = do_case(it, assigned, affected);
if (first) {
first = false;
all_assigned = case_assigned;
return assigned;
}
- pool<RTLIL::SigBit> do_case(RTLIL::CaseRule *cs, pool<RTLIL::SigBit> assigned)
+ pool<RTLIL::SigBit> do_case(RTLIL::CaseRule *cs, pool<RTLIL::SigBit> assigned, pool<RTLIL::SigBit> &affected,
+ bool root = false)
{
for (auto it = cs->switches.rbegin(); it != cs->switches.rend(); ++it) {
- pool<RTLIL::SigBit> sw_assigned = do_switch((*it), assigned);
+ pool<RTLIL::SigBit> sw_assigned = do_switch((*it), assigned, affected);
assigned.insert(sw_assigned.begin(), sw_assigned.end());
}
pool<RTLIL::SigSig> remove;
break;
}
}
- if (redundant)
+ if (redundant) {
+ removed_count++;
remove.insert(*it);
- else {
+ } else {
+ if (root) {
+ bool promotable = true;
+ for (auto &bit : lhs) {
+ if (bit.wire && affected[bit]) {
+ promotable = false;
+ break;
+ }
+ }
+ if (promotable) {
+ promoted_count++;
+ module->connect(*it);
+ remove.insert(*it);
+ }
+ }
for (auto &bit : lhs)
if (bit.wire)
assigned.insert(bit);
+ for (auto &bit : lhs)
+ if (bit.wire)
+ affected.insert(bit);
}
}
for (auto it = cs->actions.begin(); it != cs->actions.end(); ) {
if (remove[*it]) {
it = cs->actions.erase(it);
- count++;
} else it++;
}
return assigned;
void do_process(RTLIL::Process *pr)
{
- do_case(&pr->root_case, {});
+ pool<RTLIL::SigBit> affected;
+ do_case(&pr->root_case, {}, affected, /*root=*/true);
}
};
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
- int total_count = 0;
+ int total_removed_count = 0, total_promoted_count = 0;
log_header(design, "Executing PROC_PRUNE pass (remove redundant assignments in processes).\n");
extra_args(args, 1, design);
continue;
worker.do_process(proc_it.second);
}
- total_count += worker.count;
+ total_removed_count += worker.removed_count;
+ total_promoted_count += worker.promoted_count;
}
- log("Removed %d redundant assignment%s.\n", total_count, total_count == 1 ? "" : "s");
+ log("Removed %d redundant assignment%s.\n",
+ total_removed_count, total_removed_count == 1 ? "" : "s");
+ log("Promoted %d assignment%s to connection%s.\n",
+ total_promoted_count, total_promoted_count == 1 ? "" : "s", total_promoted_count == 1 ? "" : "s");
}
} ProcPrunePass;