proc_prune: promote assigns to module connections when legal.
authorwhitequark <whitequark@whitequark.org>
Tue, 9 Jul 2019 08:14:52 +0000 (08:14 +0000)
committerwhitequark <whitequark@whitequark.org>
Tue, 9 Jul 2019 09:30:58 +0000 (09:30 +0000)
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
passes/proc/proc_init.cc
passes/proc/proc_prune.cc

index b69eba3f9d327480ecf8c23b72fd10109276eaad..d069f152a388195a5d845917be9ce5bd5ab883a5 100644 (file)
@@ -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)
index e2dc07e5356ce3c5582411f6050621c5f92d03fe..462a384b73b98ec68c82fa99924971717bac45ad 100644 (file)
 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;
 
index 7222d414df8a2e469d55337421e67fecb0ab5ab0..9e00b0a8a23e0757e0b53e59d8e30ac9b4223a68 100644 (file)
@@ -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<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");
@@ -43,7 +43,7 @@ struct PruneWorker
                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;
@@ -58,10 +58,11 @@ struct PruneWorker
                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;
@@ -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<RTLIL::SigBit> affected;
+               do_case(&pr->root_case, {}, affected, /*root=*/true);
        }
 };
 
@@ -111,7 +130,7 @@ struct ProcPrunePass : public Pass {
        }
        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);
@@ -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;