From 44bcb7a187ffa00921cb14fa50428ce272ce3b6b Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 9 Jul 2019 08:14:52 +0000 Subject: [PATCH] proc_prune: promote assigns to module connections when legal. This can pave the way for further transformations by exposing identities that were previously hidden in a process to any pass that uses SigMap. Indeed, this commit removes some ad-hoc logic from proc_init that appears to have been tailored to the output of genrtlil in favor of using `SigMap.apply()`. (This removal is not optional, as the ad-hoc logic cannot cope with the result of running proc_prune; a similar issue was fixed in proc_arst.) --- passes/proc/proc_arst.cc | 2 +- passes/proc/proc_init.cc | 26 +++++----------------- passes/proc/proc_prune.cc | 47 +++++++++++++++++++++++++++++---------- 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index b69eba3f9..d069f152a 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -172,7 +172,7 @@ restart_proc_arst: sync->type = sync->type == RTLIL::SyncType::STp ? RTLIL::SyncType::ST1 : RTLIL::SyncType::ST0; } for (auto &action : sync->actions) { - RTLIL::SigSpec rspec = action.second; + RTLIL::SigSpec rspec = assign_map(action.second); RTLIL::SigSpec rval = RTLIL::SigSpec(RTLIL::State::Sm, rspec.size()); for (int i = 0; i < GetSize(rspec); i++) if (rspec[i].wire == NULL) diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc index e2dc07e53..462a384b7 100644 --- a/passes/proc/proc_init.cc +++ b/passes/proc/proc_init.cc @@ -26,21 +26,7 @@ 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; @@ -53,9 +39,7 @@ void proc_init(RTLIL::Module *mod, RTLIL::Process *proc) 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)); @@ -120,10 +104,12 @@ struct ProcInitPass : public Pass { 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; diff --git a/passes/proc/proc_prune.cc b/passes/proc/proc_prune.cc index 7222d414d..9e00b0a8a 100644 --- a/passes/proc/proc_prune.cc +++ b/passes/proc/proc_prune.cc @@ -31,11 +31,11 @@ struct PruneWorker RTLIL::Module *module; SigMap sigmap; - int count = 0; + int removed_count = 0, promoted_count = 0; PruneWorker(RTLIL::Module *mod) : module(mod), sigmap(mod) {} - pool do_switch(RTLIL::SwitchRule *sw, pool assigned) + pool do_switch(RTLIL::SwitchRule *sw, pool assigned, pool &affected) { pool all_assigned; bool full_case = sw->get_bool_attribute("\\full_case"); @@ -43,7 +43,7 @@ struct PruneWorker for (auto it : sw->cases) { if (it->compare.empty()) full_case = true; - pool case_assigned = do_case(it, assigned); + pool case_assigned = do_case(it, assigned, affected); if (first) { first = false; all_assigned = case_assigned; @@ -58,10 +58,11 @@ struct PruneWorker return assigned; } - pool do_case(RTLIL::CaseRule *cs, pool assigned) + pool do_case(RTLIL::CaseRule *cs, pool assigned, pool &affected, + bool root = false) { for (auto it = cs->switches.rbegin(); it != cs->switches.rend(); ++it) { - pool sw_assigned = do_switch((*it), assigned); + pool sw_assigned = do_switch((*it), assigned, affected); assigned.insert(sw_assigned.begin(), sw_assigned.end()); } pool remove; @@ -74,18 +75,35 @@ struct PruneWorker 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; @@ -93,7 +111,8 @@ struct PruneWorker void do_process(RTLIL::Process *pr) { - do_case(&pr->root_case, {}); + pool affected; + do_case(&pr->root_case, {}, affected, /*root=*/true); } }; @@ -111,7 +130,7 @@ struct ProcPrunePass : public Pass { } void execute(std::vector 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); @@ -125,10 +144,14 @@ struct ProcPrunePass : public Pass { 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; -- 2.30.2