From 56ea2306764e1363688e0f9e1146f98bd48d3037 Mon Sep 17 00:00:00 2001
From: Clifford Wolf <clifford@clifford.at>
Date: Sat, 19 Oct 2013 00:50:13 +0200
Subject: Added handling of multiple async paths in proc_arst

---
 passes/proc/proc_arst.cc  | 12 ++++++++++++
 passes/proc/proc_clean.cc | 17 +++++++++--------
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc
index d0a0d864c..021d87c81 100644
--- a/passes/proc/proc_arst.cc
+++ b/passes/proc/proc_arst.cc
@@ -23,6 +23,9 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+// defined in proc_clean.cc
+extern void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth);
+
 static bool check_signal(RTLIL::Module *mod, RTLIL::SigSpec signal, RTLIL::SigSpec ref, bool &polarity)
 {
 	if (signal.width != 1)
@@ -132,10 +135,18 @@ static void eliminate_const(RTLIL::Module *mod, RTLIL::CaseRule *cs, RTLIL::SigS
 				eliminate_const(mod, cs2, const_sig, polarity);
 		}
 	}
+
+	int dummy_count = 0;
+	bool did_something = true;
+	while (did_something) {
+		did_something = false;
+		proc_clean_case(cs, did_something, dummy_count, 1);
+	}
 }
 
 static void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map)
 {
+restart_proc_arst:
 	if (proc->root_case.switches.size() != 1)
 		return;
 
@@ -173,6 +184,7 @@ static void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_m
 					action.second = rval;
 				}
 				eliminate_const(mod, &proc->root_case, root_sig, polarity);
+				goto restart_proc_arst;
 			}
 		}
 	}
diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc
index e247f2882..83554df90 100644
--- a/passes/proc/proc_clean.cc
+++ b/passes/proc/proc_clean.cc
@@ -22,10 +22,10 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-static void switch_clean(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did_something, int &count);
-static void case_clean(RTLIL::CaseRule *cs, bool &did_something, int &count);
+extern void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did_something, int &count, int max_depth);
+extern void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth);
 
-static void switch_clean(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did_something, int &count)
+void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did_something, int &count, int max_depth)
 {
 	if (sw->signal.width > 0 && sw->signal.is_fully_const())
 	{
@@ -76,7 +76,8 @@ static void switch_clean(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &d
 		for (auto cs : sw->cases) {
 			if (cs->actions.size() != 0 || cs->switches.size() != 0)
 				all_cases_are_empty = false;
-			case_clean(cs, did_something, count);
+			if (max_depth != 0)
+				proc_clean_case(cs, did_something, count, max_depth-1);
 		}
 		if (all_cases_are_empty) {
 			did_something = true;
@@ -87,7 +88,7 @@ static void switch_clean(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &d
 	}
 }
 
-static void case_clean(RTLIL::CaseRule *cs, bool &did_something, int &count)
+void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth)
 {
 	for (size_t i = 0; i < cs->actions.size(); i++) {
 		if (cs->actions[i].first.width == 0) {
@@ -102,8 +103,8 @@ static void case_clean(RTLIL::CaseRule *cs, bool &did_something, int &count)
 			did_something = true;
 			delete sw;
 			count++;
-		} else
-			switch_clean(sw, cs, did_something, count);
+		} else if (max_depth != 0)
+			proc_clean_switch(sw, cs, did_something, count, max_depth-1);
 	}
 }
 
@@ -122,7 +123,7 @@ static void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_coun
 	}
 	while (did_something) {
 		did_something = false;
-		case_clean(&proc->root_case, did_something, count);
+		proc_clean_case(&proc->root_case, did_something, count, -1);
 	}
 	if (count > 0)
 		log("Found and cleaned up %d empty switch%s in `%s.%s'.\n", count, count == 1 ? "" : "es", mod->name.c_str(), proc->name.c_str());
-- 
cgit v1.2.3