summaryrefslogtreecommitdiff
path: root/passes/opt/opt_rmdff.cc
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2014-02-04 12:02:47 +0100
committerClifford Wolf <clifford@clifford.at>2014-02-04 12:02:47 +0100
commitecdf1f5577dec6a02c944e68d1e923140e51f5bc (patch)
treee7905b9e54cd3c2eb19c1728f426be7dfaf2bb1b /passes/opt/opt_rmdff.cc
parent9e938aa32ad2b03eb9a9ea3bc1702ec4683cc37b (diff)
Improved handling of reg init in opt_share and opt_rmdff
Diffstat (limited to 'passes/opt/opt_rmdff.cc')
-rw-r--r--passes/opt/opt_rmdff.cc36
1 files changed, 29 insertions, 7 deletions
diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc
index a8e2c412..02b7f77e 100644
--- a/passes/opt/opt_rmdff.cc
+++ b/passes/opt/opt_rmdff.cc
@@ -24,7 +24,7 @@
#include <stdlib.h>
#include <stdio.h>
-static SigMap assign_map;
+static SigMap assign_map, dff_init_map;
static SigSet<RTLIL::Cell*> mux_drivers;
static bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
@@ -73,6 +73,14 @@ static bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
assign_map.apply(sig_c);
assign_map.apply(sig_r);
+ bool has_init;
+ RTLIL::Const val_init;
+ for (auto bit : dff_init_map(sig_q).to_sigbit_vector()) {
+ if (bit.wire == NULL)
+ has_init = true;
+ val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx);
+ }
+
if (dff->type == "$dff" && mux_drivers.has(sig_d)) {
std::set<RTLIL::Cell*> muxes;
mux_drivers.find(sig_d, muxes);
@@ -92,31 +100,41 @@ static bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
}
}
- if (sig_c.is_fully_const()) {
+ if (sig_c.is_fully_const() && (!sig_r.width || !has_init)) {
if (val_rv.bits.size() == 0)
- val_rv = RTLIL::Const(RTLIL::State::Sx, sig_q.width);
+ val_rv = val_init;
RTLIL::SigSig conn(sig_q, val_rv);
mod->connections.push_back(conn);
goto delete_dff;
}
- if (sig_d.is_fully_undef() && sig_d.width == int(val_rv.bits.size())) {
+ if (sig_d.is_fully_undef() && sig_r.width && !has_init) {
RTLIL::SigSig conn(sig_q, val_rv);
mod->connections.push_back(conn);
goto delete_dff;
}
- if (sig_d.is_fully_const() && sig_r.width == 0) {
+ if (sig_d.is_fully_undef() && !sig_r.width && has_init) {
+ RTLIL::SigSig conn(sig_q, val_init);
+ mod->connections.push_back(conn);
+ goto delete_dff;
+ }
+
+ if (sig_d.is_fully_const() && !sig_r.width && !has_init) {
RTLIL::SigSig conn(sig_q, sig_d);
mod->connections.push_back(conn);
goto delete_dff;
}
- if (sig_d == sig_q) {
- if (sig_r.width > 0) {
+ if (sig_d == sig_q && !(sig_r.width && has_init)) {
+ if (sig_r.width) {
RTLIL::SigSig conn(sig_q, val_rv);
mod->connections.push_back(conn);
}
+ if (has_init) {
+ RTLIL::SigSig conn(sig_q, val_init);
+ mod->connections.push_back(conn);
+ }
goto delete_dff;
}
@@ -155,6 +173,10 @@ struct OptRmdffPass : public Pass {
continue;
assign_map.set(mod_it.second);
+ dff_init_map.set(mod_it.second);
+ for (auto &it : mod_it.second->wires)
+ if (it.second->attributes.count("\\init") != 0)
+ dff_init_map.add(it.second, it.second->attributes.at("\\init"));
mux_drivers.clear();
std::vector<std::string> dff_list;