From: Clifford Wolf Date: Tue, 4 Feb 2014 11:02:47 +0000 (+0100) Subject: Improved handling of reg init in opt_share and opt_rmdff X-Git-Tag: yosys-0.2.0~101 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ecdf1f5577dec6a02c944e68d1e923140e51f5bc;p=yosys.git Improved handling of reg init in opt_share and opt_rmdff --- diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index a8e2c4121..02b7f77e7 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -24,7 +24,7 @@ #include #include -static SigMap assign_map; +static SigMap assign_map, dff_init_map; static SigSet 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 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 dff_list; diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index 43d1a57e1..eb639d8ab 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -35,6 +35,7 @@ struct OptShareWorker RTLIL::Design *design; RTLIL::Module *module; SigMap assign_map; + SigMap dff_init_map; CellTypes ct; int total_count; @@ -178,6 +179,16 @@ struct OptShareWorker return true; } + if (cell1->type.substr(0, 1) == "$" && conn1.count("\\Q") != 0) { + std::vector q1 = dff_init_map(cell1->connections.at("\\Q")).to_sigbit_vector(); + std::vector q2 = dff_init_map(cell2->connections.at("\\Q")).to_sigbit_vector(); + for (size_t i = 0; i < q1.size(); i++) + if ((q1.at(i).wire == NULL || q2.at(i).wire == NULL) && q1.at(i) != q2.at(i)) { + lt = q1.at(i) < q2.at(i); + return true; + } + } + return false; } @@ -189,6 +200,9 @@ struct OptShareWorker if (!ct.cell_known(cell1->type)) return cell1 < cell2; + if (cell1->get_bool_attribute("\\keep") || cell2->get_bool_attribute("\\keep")) + return cell1 < cell2; + bool lt; if (compare_cell_parameters_and_connections(cell1, cell2, lt)) return lt; @@ -222,6 +236,11 @@ struct OptShareWorker log("Finding identical cells in module `%s'.\n", module->name.c_str()); assign_map.set(module); + dff_init_map.set(module); + for (auto &it : module->wires) + if (it.second->attributes.count("\\init") != 0) + dff_init_map.add(it.second, it.second->attributes.at("\\init")); + bool did_something = true; while (did_something) {