aboutsummaryrefslogtreecommitdiffstats
path: root/passes/proc
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2016-06-01 13:25:06 +0200
committerClifford Wolf <clifford@clifford.at>2016-06-01 13:25:06 +0200
commitadfc80727c19021f911833305f5d322af6b8a0aa (patch)
treea40fa2523befbd2ef17bfee70e7cbc0170bf66aa /passes/proc
parent11f7b8a2a1dd6e5c47e8081e4485127331fd80be (diff)
downloadyosys-adfc80727c19021f911833305f5d322af6b8a0aa.tar.gz
yosys-adfc80727c19021f911833305f5d322af6b8a0aa.tar.bz2
yosys-adfc80727c19021f911833305f5d322af6b8a0aa.zip
Avoid creating undef-muxes when inferring latches in proc_dlatch
Diffstat (limited to 'passes/proc')
-rw-r--r--passes/proc/proc_dlatch.cc44
1 files changed, 44 insertions, 0 deletions
diff --git a/passes/proc/proc_dlatch.cc b/passes/proc/proc_dlatch.cc
index 92bf8906d..8fe843ba3 100644
--- a/passes/proc/proc_dlatch.cc
+++ b/passes/proc/proc_dlatch.cc
@@ -33,6 +33,7 @@ struct proc_dlatch_db_t
Module *module;
SigMap sigmap;
+ pool<Cell*> rewritten_mux_cells;
dict<Cell*, vector<SigBit>> mux_srcbits;
dict<SigBit, pair<Cell*, int>> mux_drivers;
dict<SigBit, int> sigusers;
@@ -189,6 +190,7 @@ struct proc_dlatch_db_t
int n = find_mux_feedback(sig_a[index], needle, set_undef);
if (n != false_node) {
if (set_undef && sig_a[index] == needle) {
+ rewritten_mux_cells.insert(cell);
SigSpec sig = cell->getPort("\\A");
sig[index] = State::Sx;
cell->setPort("\\A", sig);
@@ -202,6 +204,7 @@ struct proc_dlatch_db_t
n = find_mux_feedback(sig_b[i*width + index], needle, set_undef);
if (n != false_node) {
if (set_undef && sig_b[i*width + index] == needle) {
+ rewritten_mux_cells.insert(cell);
SigSpec sig = cell->getPort("\\B");
sig[i*width + index] = State::Sx;
cell->setPort("\\B", sig);
@@ -253,6 +256,46 @@ struct proc_dlatch_db_t
rules_sig[n] = and_bits[0];
return and_bits[0];
}
+
+ void fixup_rewritten_muxes()
+ {
+ for (auto cell : rewritten_mux_cells)
+ {
+ SigSpec sig_a = cell->getPort("\\A");
+ SigSpec sig_b = cell->getPort("\\B");
+ SigSpec sig_s = cell->getPort("\\S");
+ SigSpec sig_any_valid_b;
+
+ SigSpec sig_new_b, sig_new_s;
+ for (int i = 0; i < GetSize(sig_s); i++) {
+ SigSpec b = sig_b.extract(i*GetSize(sig_a), GetSize(sig_a));
+ if (!b.is_fully_undef()) {
+ sig_any_valid_b = b;
+ sig_new_b.append(b);
+ sig_new_s.append(sig_s[i]);
+ }
+ }
+
+ if (sig_new_s.empty()) {
+ sig_new_b = sig_a;
+ sig_new_s = State::S0;
+ }
+
+ if (sig_a.is_fully_undef() && !sig_any_valid_b.empty())
+ cell->setPort("\\A", sig_any_valid_b);
+
+ if (GetSize(sig_new_s) == 1) {
+ cell->type = "$mux";
+ cell->unsetParam("\\S_WIDTH");
+ } else {
+ cell->type = "$pmux";
+ cell->setParam("\\S_WIDTH", GetSize(sig_new_s));
+ }
+
+ cell->setPort("\\B", sig_new_b);
+ cell->setPort("\\S", sig_new_s);
+ }
+ }
};
void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
@@ -360,6 +403,7 @@ struct ProcDlatchPass : public Pass {
for (auto &proc_it : module->processes)
if (design->selected(module, proc_it.second))
proc_dlatch(db, proc_it.second);
+ db.fixup_rewritten_muxes();
}
}
} ProcDlatchPass;