From e3f9ccf56d65ba72dfa625e9716d1182f36a381e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 22 May 2019 13:56:56 +0200 Subject: Keep zero-width wires in opt_clean if and only if they are ports, fixes #1023 Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index bf8020169..7011d4602 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -319,8 +319,9 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos wire->attributes.erase("\\init"); if (GetSize(wire) == 0) { - // delete zero-width wires - goto delete_this_wire; + // delete zero-width wires, unless they are module ports + if (wire->port_id == 0) + goto delete_this_wire; } else if (wire->port_id != 0 || wire->get_bool_attribute("\\keep") || !initval.is_fully_undef()) { // do not delete anything with "keep" or module ports or initialized wires -- cgit v1.2.3 From 50ed34a6d0fe1013fae0a14165fc4fce1d1a3685 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 23 May 2019 11:26:18 -0700 Subject: opt_rmdff to work on $dffe and $_DFFE_* --- passes/opt/opt_rmdff.cc | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index e8570f0eb..a4ed582cb 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -260,8 +260,8 @@ delete_dlatch: bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) { - RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r; - RTLIL::Const val_cp, val_rp, val_rv; + RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e; + RTLIL::Const val_cp, val_rp, val_rv, val_ep; if (dff->type == "$_FF_") { sig_d = dff->getPort("\\D"); @@ -285,6 +285,16 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) val_rp = RTLIL::Const(dff->type[7] == 'P', 1); val_rv = RTLIL::Const(dff->type[8] == '1', 1); } + else if (dff->type.substr(0,7) == "$_DFFE_" && dff->type.substr(9) == "_" && + (dff->type[7] == 'N' || dff->type[7] == 'P') && + (dff->type[8] == 'N' || dff->type[8] == 'P')) { + sig_d = dff->getPort("\\D"); + sig_q = dff->getPort("\\Q"); + sig_c = dff->getPort("\\C"); + sig_e = dff->getPort("\\E"); + val_cp = RTLIL::Const(dff->type[6] == 'P', 1); + val_ep = RTLIL::Const(dff->type[7] == 'P', 1); + } else if (dff->type == "$ff") { sig_d = dff->getPort("\\D"); sig_q = dff->getPort("\\Q"); @@ -295,6 +305,14 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) sig_c = dff->getPort("\\CLK"); val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1); } + else if (dff->type == "$dffe") { + sig_e = dff->getPort("\\EN"); + sig_d = dff->getPort("\\D"); + sig_q = dff->getPort("\\Q"); + sig_c = dff->getPort("\\CLK"); + val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1); + val_ep = RTLIL::Const(dff->parameters["\\EN_POLARITY"].as_bool(), 1); + } else if (dff->type == "$adff") { sig_d = dff->getPort("\\D"); sig_q = dff->getPort("\\Q"); @@ -320,6 +338,16 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx); } + if (sig_e.size()) { + if (!sig_e.is_fully_const()) + return false; + if (sig_e != val_ep) { + if (has_init) + mod->connect(sig_q, val_init); + goto delete_dff; + } + } + if (dff->type.in("$ff", "$dff") && mux_drivers.has(sig_d)) { std::set muxes; mux_drivers.find(sig_d, muxes); @@ -489,7 +517,8 @@ struct OptRmdffPass : public Pass { if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", "$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_", - "$ff", "$dff", "$adff")) + "$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_", + "$ff", "$dff", "$dffe", "$adff")) dff_list.push_back(cell->name); if (cell->type.in("$dlatch", "$_DLATCH_P_", "$_DLATCH_N_")) -- cgit v1.2.3 From 5ac7e38d0aab1c73150accd9befbccc5398b8e42 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 23 May 2019 12:58:30 -0700 Subject: Fix spacing --- passes/opt/opt_rmdff.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index a4ed582cb..3cb8e2b1e 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -342,8 +342,8 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) if (!sig_e.is_fully_const()) return false; if (sig_e != val_ep) { - if (has_init) - mod->connect(sig_q, val_init); + if (has_init) + mod->connect(sig_q, val_init); goto delete_dff; } } -- cgit v1.2.3 From 357b1de6bc3dcddc9bc0870e20c68c21c869a323 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 24 May 2019 16:15:22 -0700 Subject: Resolve @cliffordwolf review, set even if !has_init --- passes/opt/opt_rmdff.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 3cb8e2b1e..a36b279c2 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -342,8 +342,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) if (!sig_e.is_fully_const()) return false; if (sig_e != val_ep) { - if (has_init) - mod->connect(sig_q, val_init); + mod->connect(sig_q, val_init); goto delete_dff; } } -- cgit v1.2.3 From 0d66103cbb462e6be613cc1187fa7be4f5ee4701 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 24 May 2019 16:33:10 -0700 Subject: Add comments --- passes/opt/opt_rmdff.cc | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'passes') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index a36b279c2..abbf8b5d1 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -364,39 +364,60 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) } } + // If clock is driven by a constant and (i) no reset signal + // (ii) Q has no initial value + // (iii) initial value is same as reset value if (!sig_c.empty() && sig_c.is_fully_const() && (!sig_r.size() || !has_init || val_init == val_rv)) { if (val_rv.bits.size() == 0) val_rv = val_init; + // Q is permanently reset value or initial value mod->connect(sig_q, val_rv); goto delete_dff; } + // If D is fully undefined and reset signal present and (i) Q has no initial value + // (ii) initial value is same as reset value if (sig_d.is_fully_undef() && sig_r.size() && (!has_init || val_init == val_rv)) { + // Q is permanently reset value mod->connect(sig_q, val_rv); goto delete_dff; } + // If D is fully undefined and no reset signal and Q has an initial value if (sig_d.is_fully_undef() && !sig_r.size() && has_init) { + // Q is permanently initial value mod->connect(sig_q, val_init); goto delete_dff; } + // If D is fully constant and (i) no reset signal + // (ii) reset value is same as constant D + // and (a) has initial value + // (b) initial value same as constant D if (sig_d.is_fully_const() && (!sig_r.size() || val_rv == sig_d.as_const()) && (!has_init || val_init == sig_d.as_const())) { + // Q is permanently D mod->connect(sig_q, sig_d); goto delete_dff; } + // If D input is same as Q output and (i) no reset signal + // (ii) no initial signal + // (iii) initial value is same as reset value if (sig_d == sig_q && (sig_r.empty() || !has_init || val_init == val_rv)) { + // Q is permanently reset value or initial value if (sig_r.size()) mod->connect(sig_q, val_rv); - if (has_init) + else if (has_init) mod->connect(sig_q, val_init); goto delete_dff; } + // If reset signal is present, and is fully constant if (!sig_r.empty() && sig_r.is_fully_const()) { + // If reset value is permanently enable or if reset is undefined if (sig_r == val_rp || sig_r.is_fully_undef()) { + // Q is permanently reset value mod->connect(sig_q, val_rv); goto delete_dff; } -- cgit v1.2.3 From 822d0b7789fdfe94bfe11b96546af8430e5f3299 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 24 May 2019 18:30:51 -0700 Subject: opt_rmdff to optimise even in presence of enable signal, even removing --- passes/opt/opt_rmdff.cc | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index abbf8b5d1..d10cf508f 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -338,15 +338,6 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx); } - if (sig_e.size()) { - if (!sig_e.is_fully_const()) - return false; - if (sig_e != val_ep) { - mod->connect(sig_q, val_init); - goto delete_dff; - } - } - if (dff->type.in("$ff", "$dff") && mux_drivers.has(sig_d)) { std::set muxes; mux_drivers.find(sig_d, muxes); @@ -392,9 +383,11 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) // If D is fully constant and (i) no reset signal // (ii) reset value is same as constant D - // and (a) has initial value + // and (a) has no initial value // (b) initial value same as constant D - if (sig_d.is_fully_const() && (!sig_r.size() || val_rv == sig_d.as_const()) && (!has_init || val_init == sig_d.as_const())) { + // and (1) has no enable signal + // (2) enable is always active + if (sig_d.is_fully_const() && (!sig_r.size() || val_rv == sig_d.as_const()) && (!has_init || val_init == sig_d.as_const()) && (!sig_e.size() || (sig_d.is_fully_undef() && !has_init))) { // Q is permanently D mod->connect(sig_q, sig_d); goto delete_dff; @@ -415,7 +408,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) // If reset signal is present, and is fully constant if (!sig_r.empty() && sig_r.is_fully_const()) { - // If reset value is permanently enable or if reset is undefined + // If reset value is permanently active or if reset is undefined if (sig_r == val_rp || sig_r.is_fully_undef()) { // Q is permanently reset value mod->connect(sig_q, val_rv); @@ -437,6 +430,30 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) dff->unsetPort("\\R"); } + // If enable signal is present, and is fully constant + if (!sig_e.empty() && sig_e.is_fully_const()) + { + // If enable value is permanently inactive + if (sig_e != val_ep) { + // Q is permanently initial value + mod->connect(sig_q, val_init); + goto delete_dff; + } + + log("Removing unused enable from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod)); + + if (dff->type == "$dffe") { + dff->type = "$dff"; + dff->unsetPort("\\EN"); + dff->unsetParam("\\EN_POLARITY"); + return true; + } + + log_assert(dff->type.substr(0,7) == "$_DFFE_"); + dff->type = stringf("$_DFF_%c_", + dff->type[7]); + dff->unsetPort("\\E"); + } + return false; delete_dff: -- cgit v1.2.3 From d4fb6cac7c4c93f868e294dfc95936516813eeac Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 25 May 2019 12:55:57 -0700 Subject: Revert enable check --- passes/opt/opt_rmdff.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index d10cf508f..2abffa2a9 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -385,9 +385,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) // (ii) reset value is same as constant D // and (a) has no initial value // (b) initial value same as constant D - // and (1) has no enable signal - // (2) enable is always active - if (sig_d.is_fully_const() && (!sig_r.size() || val_rv == sig_d.as_const()) && (!has_init || val_init == sig_d.as_const()) && (!sig_e.size() || (sig_d.is_fully_undef() && !has_init))) { + if (sig_d.is_fully_const() && (!sig_r.size() || val_rv == sig_d.as_const()) && (!has_init || val_init == sig_d.as_const())) { // Q is permanently D mod->connect(sig_q, sig_d); goto delete_dff; -- cgit v1.2.3