diff options
-rw-r--r-- | passes/opt/wreduce.cc | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 09983bc67..1f7222e49 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -53,6 +53,7 @@ struct WreduceWorker std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells; std::set<SigBit> work_queue_bits; pool<SigBit> keep_bits; + dict<SigBit, State> init_bits; WreduceWorker(WreduceConfig *config, Module *module) : config(config), module(module), mi(module) { } @@ -141,6 +142,7 @@ struct WreduceWorker SigSpec sig_d = mi.sigmap(cell->getPort("\\D")); SigSpec sig_q = mi.sigmap(cell->getPort("\\Q")); + Const initval; int width_before = GetSize(sig_q); @@ -150,16 +152,24 @@ struct WreduceWorker bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0; bool sign_ext = !zero_ext; + for (int i = 0; i < GetSize(sig_q); i++) { + SigBit bit = sig_q[i]; + if (init_bits.count(bit)) + initval.bits.push_back(init_bits.at(bit)); + else + initval.bits.push_back(State::Sx); + } + for (int i = GetSize(sig_q)-1; i >= 0; i--) { - if (zero_ext && sig_d[i] == State::S0) { + if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) { module->connect(sig_q[i], State::S0); sig_d.remove(i); sig_q.remove(i); continue; } - if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1]) { + if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1]) { module->connect(sig_q[i], sig_q[i-1]); sig_d.remove(i); sig_q.remove(i); @@ -167,7 +177,7 @@ struct WreduceWorker } auto info = mi.query(sig_q[i]); - if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) { + if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) { sig_d.remove(i); sig_q.remove(i); zero_ext = false; @@ -183,10 +193,11 @@ struct WreduceWorker if (GetSize(sig_q) == 0) { log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + module->remove(cell); return; } - log("Removed top %d bits (of %d) from mux cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before, + log("Removed top %d bits (of %d) from FF cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before, log_id(module), log_id(cell), log_id(cell->type)); for (auto bit : sig_d) @@ -376,10 +387,18 @@ struct WreduceWorker void run() { - for (auto w : module->wires()) + for (auto w : module->wires()) { if (w->get_bool_attribute("\\keep")) for (auto bit : mi.sigmap(w)) keep_bits.insert(bit); + if (w->attributes.count("\\init")) { + Const initval = w->attributes.at("\\init"); + SigSpec initsig = mi.sigmap(w); + int width = std::min(GetSize(initval), GetSize(initsig)); + for (int i = 0; i < width; i++) + init_bits[initsig[i]] = initval[i]; + } + } for (auto c : module->selected_cells()) work_queue_cells.insert(c); |