From 634482380cfe5d6a1c801af0ce04e8048c5c9baf Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 22 Apr 2019 10:03:18 +0200 Subject: Preserve $specify[23] cells Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index c38e9df5e..3f38dd580 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -64,7 +64,7 @@ struct keep_cache_t bool query(Cell *cell) { - if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover")) + if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover", "$specify2", "$specify3")) return true; if (cell->has_keep_attr()) -- cgit v1.2.3 From 71c38d9de527e1a8b55ba295df459fbcf2a0fe47 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 23 Apr 2019 15:46:40 +0200 Subject: Add $specrule cells for $setup/$hold/$skew specify rules Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 3f38dd580..3e131d2af 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -64,7 +64,7 @@ struct keep_cache_t bool query(Cell *cell) { - if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover", "$specify2", "$specify3")) + if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover", "$specify2", "$specify3", "$specrule")) return true; if (cell->has_keep_attr()) -- cgit v1.2.3 From a30b99e66e048530d74e9dfc5c103d5fac47c5bc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 1 May 2019 09:29:34 +0200 Subject: Silently resolve completely unused cell-vs-const driver-driver conflicts Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 5d95c4f1a..242680290 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -85,7 +85,14 @@ void rmunused_module_cells(Module *module, bool verbose) { SigMap sigmap(module); pool queue, unused; + pool used_raw_bits; dict> wire2driver; + dict> driver_driver_logs; + + for (auto &it : module->connections_) { + for (auto raw_bit : it.second) + used_raw_bits.insert(raw_bit); + } for (auto &it : module->cells_) { Cell *cell = it.second; @@ -96,11 +103,15 @@ void rmunused_module_cells(Module *module, bool verbose) continue; auto bit = sigmap(raw_bit); if (bit.wire == nullptr) - log_warning("Driver-driver conflict for %s between cell %s.%s and constant %s in %s: Resolved using constant.\n", - log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module)); + driver_driver_logs[raw_bit].push_back(stringf("Driver-driver conflict " + "for %s between cell %s.%s and constant %s in %s: Resolved using constant.", + log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module))); if (bit.wire != nullptr) wire2driver[bit].insert(cell); } + if (!ct_all.cell_known(cell->type) || ct_all.cell_input(cell->type, it2.first)) + for (auto raw_bit : it2.second) + used_raw_bits.insert(raw_bit); } if (keep_cache.query(cell)) queue.insert(cell); @@ -114,9 +125,17 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto bit : sigmap(wire)) for (auto c : wire2driver[bit]) queue.insert(c), unused.erase(c); + for (auto raw_bit : SigSpec(wire)) + used_raw_bits.insert(raw_bit); } } + for (auto it : driver_driver_logs) { + if (used_raw_bits.count(it.first)) + for (auto msg : it.second) + log_warning("%s\n", msg.c_str()); + } + while (!queue.empty()) { pool bits; -- cgit v1.2.3 From aa081f83c791b1d666214776aaf744a80ce6a690 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 May 2019 17:40:39 -0700 Subject: dffinit -noreinit to silently continue when init value is 1'bx --- passes/techmap/dffinit.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'passes') diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc index 48390488e..37479da65 100644 --- a/passes/techmap/dffinit.cc +++ b/passes/techmap/dffinit.cc @@ -135,10 +135,18 @@ struct DffinitPass : public Pass { continue; while (GetSize(value.bits) <= i) value.bits.push_back(State::S0); - if (noreinit && value.bits[i] != State::Sx && value.bits[i] != init_bits.at(sig[i])) - log_error("Trying to assign a different init value for %s.%s.%s which technically " - "have a conflicted init value.\n", - log_id(module), log_id(cell), log_id(it.second)); + if (noreinit && value.bits[i] != State::Sx && value.bits[i] != init_bits.at(sig[i])) { + if (init_bits.at(sig[i]) != State::Sx) { + log_error("Trying to assign a different init value for %s.%s.%s which technically " + "have a conflicted init value.\n", + log_id(module), log_id(cell), log_id(it.second)); + } + else { + // Trying to overwrite an existing INIT value with 1'bx, + // silently ignore? + continue; + } + } value.bits[i] = init_bits.at(sig[i]); cleanup_bits.insert(sig[i]); } -- cgit v1.2.3 From e8c5afcb84a2f52c26759952cb9288e42821a49f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 May 2019 08:25:30 +0200 Subject: Fix typo Signed-off-by: Clifford Wolf --- passes/pmgen/peepopt.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes') diff --git a/passes/pmgen/peepopt.cc b/passes/pmgen/peepopt.cc index 78eb68c7a..e7f95cf85 100644 --- a/passes/pmgen/peepopt.cc +++ b/passes/pmgen/peepopt.cc @@ -40,7 +40,7 @@ struct PeepoptPass : public Pass { } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - log_header(design, "Executing PEEOPOPT pass (run peephole optimizers).\n"); + log_header(design, "Executing PEEPOPT pass (run peephole optimizers).\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) -- cgit v1.2.3 From 2b29aa5c86021eb79c461975a0281b6d7635bb67 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 May 2019 08:35:45 +0200 Subject: Update pmgen documentation Signed-off-by: Clifford Wolf --- passes/pmgen/README.md | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'passes') diff --git a/passes/pmgen/README.md b/passes/pmgen/README.md index 320e95a77..2f0b1fd5a 100644 --- a/passes/pmgen/README.md +++ b/passes/pmgen/README.md @@ -29,19 +29,25 @@ up in any future matches: pm.blacklist(some_cell); -The `.run(callback_function)` method searches for all matches and calls the -callback function for each found match: +The `.run_(callback_function)` method searches for all matches +for the pattern`` and calls the callback function for each found +match: - pm.run([&](){ + pm.run_foobar([&](){ log("found matching 'foo' cell: %s\n", log_id(pm.st.foo)); log(" with 'bar' cell: %s\n", log_id(pm.st.bar)); }); The `.pmg` file declares matcher state variables that are accessible via the -`.st.` members. (The `.st` member is of type `foobar_pm::state_t`.) +`.st_.` members. (The `.st_` member is +of type `foobar_pm::state__t`.) Similarly the `.pmg` file declares user data variables that become members of -`.ud`, a struct of type `foobar_pm::udata_t`. +`.ud_`, a struct of type `foobar_pm::udata__t`. + +There are four versions of the `run_()` method: Without callback, +callback without arguments, callback with reference to `pm`, and callback with +reference to `pm.st_`. The .pmg File Format @@ -52,6 +58,12 @@ lines consist of whitespace-separated tokens. Lines in `.pmg` files starting with `//` are comments. +Declaring a pattern +------------------- + +A `.pmg` file contains one or more patterns. Each pattern starts with a line +with the `pattern` keyword followed by the name of the pattern. + Declaring state variables ------------------------- @@ -66,7 +78,7 @@ State variables are automatically managed by the generated backtracking algorith and saved and restored as needed. They are automatically initialized to the default constructed value of their type -when `.run(callback_function)` is called. +when `.run_(callback_function)` is called. Declaring udata variables ------------------------- -- cgit v1.2.3 From f12e1155f1d77443ee9d876d5ba3d407b9447540 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 May 2019 09:12:10 +0200 Subject: Improve unused-detection for opt_clean driver-driver conflict warning Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 50 ++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 21 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 242680290..f287fdcff 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -97,21 +97,19 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto &it : module->cells_) { Cell *cell = it.second; for (auto &it2 : cell->connections()) { - if (!ct_all.cell_known(cell->type) || ct_all.cell_output(cell->type, it2.first)) - for (auto raw_bit : it2.second) { - if (raw_bit.wire == nullptr) - continue; - auto bit = sigmap(raw_bit); - if (bit.wire == nullptr) - driver_driver_logs[raw_bit].push_back(stringf("Driver-driver conflict " - "for %s between cell %s.%s and constant %s in %s: Resolved using constant.", - log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module))); - if (bit.wire != nullptr) - wire2driver[bit].insert(cell); - } - if (!ct_all.cell_known(cell->type) || ct_all.cell_input(cell->type, it2.first)) - for (auto raw_bit : it2.second) - used_raw_bits.insert(raw_bit); + if (ct_all.cell_known(cell->type) && !ct_all.cell_output(cell->type, it2.first)) + continue; + for (auto raw_bit : it2.second) { + if (raw_bit.wire == nullptr) + continue; + auto bit = sigmap(raw_bit); + if (bit.wire == nullptr) + driver_driver_logs[raw_bit].push_back(stringf("Driver-driver conflict " + "for %s between cell %s.%s and constant %s in %s: Resolved using constant.", + log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module))); + if (bit.wire != nullptr) + wire2driver[bit].insert(cell); + } } if (keep_cache.query(cell)) queue.insert(cell); @@ -130,12 +128,6 @@ void rmunused_module_cells(Module *module, bool verbose) } } - for (auto it : driver_driver_logs) { - if (used_raw_bits.count(it.first)) - for (auto msg : it.second) - log_warning("%s\n", msg.c_str()); - } - while (!queue.empty()) { pool bits; @@ -161,6 +153,22 @@ void rmunused_module_cells(Module *module, bool verbose) module->remove(cell); count_rm_cells++; } + + for (auto &it : module->cells_) { + Cell *cell = it.second; + for (auto &it2 : cell->connections()) { + if (ct_all.cell_known(cell->type) && !ct_all.cell_input(cell->type, it2.first)) + continue; + for (auto raw_bit : it2.second) + used_raw_bits.insert(raw_bit); + } + } + + for (auto it : driver_driver_logs) { + if (used_raw_bits.count(it.first)) + for (auto msg : it.second) + log_warning("%s\n", msg.c_str()); + } } int count_nontrivial_wire_attrs(RTLIL::Wire *w) -- cgit v1.2.3 From 5c2c0b4bb2ade51396da3acbcce0d5916fb1c7d6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 May 2019 09:22:26 +0200 Subject: Further improve unused-detection for opt_clean driver-driver conflict warning Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index f287fdcff..fcb662b59 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -89,9 +89,12 @@ void rmunused_module_cells(Module *module, bool verbose) dict> wire2driver; dict> driver_driver_logs; + SigMap raw_sigmap; for (auto &it : module->connections_) { - for (auto raw_bit : it.second) - used_raw_bits.insert(raw_bit); + for (int i = 0; i < GetSize(it.second); i++) { + if (it.second[i].wire != nullptr) + raw_sigmap.add(it.first[i], it.second[i]); + } } for (auto &it : module->cells_) { @@ -104,7 +107,7 @@ void rmunused_module_cells(Module *module, bool verbose) continue; auto bit = sigmap(raw_bit); if (bit.wire == nullptr) - driver_driver_logs[raw_bit].push_back(stringf("Driver-driver conflict " + driver_driver_logs[raw_sigmap(raw_bit)].push_back(stringf("Driver-driver conflict " "for %s between cell %s.%s and constant %s in %s: Resolved using constant.", log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module))); if (bit.wire != nullptr) @@ -124,7 +127,7 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto c : wire2driver[bit]) queue.insert(c), unused.erase(c); for (auto raw_bit : SigSpec(wire)) - used_raw_bits.insert(raw_bit); + used_raw_bits.insert(raw_sigmap(raw_bit)); } } @@ -159,7 +162,7 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto &it2 : cell->connections()) { if (ct_all.cell_known(cell->type) && !ct_all.cell_input(cell->type, it2.first)) continue; - for (auto raw_bit : it2.second) + for (auto raw_bit : raw_sigmap(it2.second)) used_raw_bits.insert(raw_bit); } } -- cgit v1.2.3 From 42190207b4a5ae37240e58652d173c7164f025f7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 May 2019 14:24:53 +0200 Subject: Improve opt_expr and opt_clean handling of (partially) undriven and/or unused wires, fixes #981 Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 112 +++++++++++++++++++++++++++++++----------------- passes/opt/opt_expr.cc | 13 ++++-- 2 files changed, 81 insertions(+), 44 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 5d95c4f1a..96118e906 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -274,50 +274,53 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos std::vector maybe_del_wires; for (auto wire : module->wires()) { + SigSpec s1 = SigSpec(wire), s2 = assign_map(s1); + log_assert(GetSize(s1) == GetSize(s2)); + + bool maybe_del = false; if ((!purge_mode && check_public_name(wire->name)) || wire->port_id != 0 || wire->get_bool_attribute("\\keep") || wire->attributes.count("\\init")) { - RTLIL::SigSpec s1 = RTLIL::SigSpec(wire), s2 = s1; - assign_map.apply(s2); - if (!used_signals.check_any(s2) && wire->port_id == 0 && !wire->get_bool_attribute("\\keep")) { - maybe_del_wires.push_back(wire); - } else { - log_assert(GetSize(s1) == GetSize(s2)); - Const initval; - if (wire->attributes.count("\\init")) - initval = wire->attributes.at("\\init"); - if (GetSize(initval) != GetSize(wire)) - initval.bits.resize(GetSize(wire), State::Sx); - RTLIL::SigSig new_conn; - for (int i = 0; i < GetSize(s1); i++) - if (s1[i] != s2[i]) { - if (s2[i] == State::Sx && (initval[i] == State::S0 || initval[i] == State::S1)) { - s2[i] = initval[i]; - initval[i] = State::Sx; - } - new_conn.first.append_bit(s1[i]); - new_conn.second.append_bit(s2[i]); + if (!used_signals.check_any(s2) && wire->port_id == 0 && !wire->get_bool_attribute("\\keep")) + maybe_del = true; + } else { + if (!used_signals.check_any(s2)) + maybe_del = true; + } + + if (maybe_del) { + maybe_del_wires.push_back(wire); + } else { + Const initval; + if (wire->attributes.count("\\init")) + initval = wire->attributes.at("\\init"); + if (GetSize(initval) != GetSize(wire)) + initval.bits.resize(GetSize(wire), State::Sx); + RTLIL::SigSig new_conn; + for (int i = 0; i < GetSize(s1); i++) + if (s1[i] != s2[i]) { + if (s2[i] == State::Sx && (initval[i] == State::S0 || initval[i] == State::S1)) { + s2[i] = initval[i]; + initval[i] = State::Sx; } - if (new_conn.first.size() > 0) { - if (initval.is_fully_undef()) - wire->attributes.erase("\\init"); - else - wire->attributes.at("\\init") = initval; - used_signals.add(new_conn.first); - used_signals.add(new_conn.second); - module->connect(new_conn); + new_conn.first.append_bit(s1[i]); + new_conn.second.append_bit(s2[i]); } + if (new_conn.first.size() > 0) { + if (initval.is_fully_undef()) + wire->attributes.erase("\\init"); + else + wire->attributes.at("\\init") = initval; + used_signals.add(new_conn.first); + used_signals.add(new_conn.second); + module->connect(new_conn); } - } else { - if (!used_signals.check_any(RTLIL::SigSpec(wire))) - maybe_del_wires.push_back(wire); } - RTLIL::SigSpec sig = assign_map(RTLIL::SigSpec(wire)); - if (!used_signals_nodrivers.check_any(sig)) { + if (!used_signals_nodrivers.check_all(s2)) { std::string unused_bits; - for (int i = 0; i < GetSize(sig); i++) { - if (sig[i].wire == NULL) + for (int i = 0; i < GetSize(s2); i++) { + if (s2[i].wire == NULL) continue; - if (!used_signals_nodrivers.check(sig[i])) { + if (!used_signals_nodrivers.check(s2[i])) { if (!unused_bits.empty()) unused_bits += " "; unused_bits += stringf("%d", i); @@ -336,14 +339,40 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos pool del_wires; int del_wires_count = 0; - for (auto wire : maybe_del_wires) - if (!used_signals.check_any(RTLIL::SigSpec(wire))) { - if (check_public_name(wire->name) && verbose) { + for (auto wire : maybe_del_wires) { + SigSpec s1 = SigSpec(wire); + if (used_signals.check_any(s1)) { + SigSpec s2 = assign_map(s1); + Const initval; + if (wire->attributes.count("\\init")) + initval = wire->attributes.at("\\init"); + if (GetSize(initval) != GetSize(wire)) + initval.bits.resize(GetSize(wire), State::Sx); + RTLIL::SigSig new_conn; + for (int i = 0; i < GetSize(s1); i++) + if (s1[i] != s2[i]) { + if (s2[i] == State::Sx && (initval[i] == State::S0 || initval[i] == State::S1)) { + s2[i] = initval[i]; + initval[i] = State::Sx; + } + new_conn.first.append_bit(s1[i]); + new_conn.second.append_bit(s2[i]); + } + if (new_conn.first.size() > 0) { + if (initval.is_fully_undef()) + wire->attributes.erase("\\init"); + else + wire->attributes.at("\\init") = initval; + module->connect(new_conn); + } + } else { + if (ys_debug() || (check_public_name(wire->name) && verbose)) { log_debug(" removing unused non-port wire %s.\n", wire->name.c_str()); } del_wires.insert(wire); del_wires_count++; } + } module->remove(del_wires); count_rm_wires += del_wires.size(); @@ -496,6 +525,9 @@ struct OptCleanPass : public Pass { ct_all.setup(design); + count_rm_cells = 0; + count_rm_wires = 0; + for (auto module : design->selected_whole_modules_warn()) { if (module->has_processes_warn()) continue; @@ -561,7 +593,7 @@ struct CleanPass : public Pass { for (auto module : design->selected_whole_modules()) { if (module->has_processes()) continue; - rmunused_module(module, purge_mode, false, false); + rmunused_module(module, purge_mode, ys_debug(), false); } log_suppressed(); diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index b445afdc8..512ef0cbf 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -61,7 +61,7 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) } if (wire->port_input) driven_signals.add(sigmap(wire)); - if (wire->port_output) + if (wire->port_output || wire->get_bool_attribute("\\keep")) used_signals.add(sigmap(wire)); all_signals.add(sigmap(wire)); } @@ -88,7 +88,7 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) } } - log_debug("Setting undriven signal in %s to constant: %s = %s\n", RTLIL::id2cstr(module->name), log_signal(sig), log_signal(val)); + log_debug("Setting undriven signal in %s to constant: %s = %s\n", log_id(module), log_signal(sig), log_signal(val)); module->connect(sig, val); did_something = true; } @@ -104,10 +104,15 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) if (SigBit(initval[i]) == sig[i]) initval[i] = State::Sx; } - if (initval.is_fully_undef()) + if (initval.is_fully_undef()) { + log_debug("Removing init attribute from %s/%s.\n", log_id(module), log_id(wire)); wire->attributes.erase("\\init"); - else + did_something = true; + } else if (initval != wire->attributes.at("\\init")) { + log_debug("Updating init attribute on %s/%s: %s\n", log_id(module), log_id(wire), log_signal(initval)); wire->attributes["\\init"] = initval; + did_something = true; + } } } } -- cgit v1.2.3 From fc349de0338db3831e7156a5dc60f028382bcab1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 3 May 2019 08:05:37 -0700 Subject: Revert "dffinit -noreinit to silently continue when init value is 1'bx" This reverts commit aa081f83c791b1d666214776aaf744a80ce6a690. --- passes/techmap/dffinit.cc | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'passes') diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc index 37479da65..48390488e 100644 --- a/passes/techmap/dffinit.cc +++ b/passes/techmap/dffinit.cc @@ -135,18 +135,10 @@ struct DffinitPass : public Pass { continue; while (GetSize(value.bits) <= i) value.bits.push_back(State::S0); - if (noreinit && value.bits[i] != State::Sx && value.bits[i] != init_bits.at(sig[i])) { - if (init_bits.at(sig[i]) != State::Sx) { - log_error("Trying to assign a different init value for %s.%s.%s which technically " - "have a conflicted init value.\n", - log_id(module), log_id(cell), log_id(it.second)); - } - else { - // Trying to overwrite an existing INIT value with 1'bx, - // silently ignore? - continue; - } - } + if (noreinit && value.bits[i] != State::Sx && value.bits[i] != init_bits.at(sig[i])) + log_error("Trying to assign a different init value for %s.%s.%s which technically " + "have a conflicted init value.\n", + log_id(module), log_id(cell), log_id(it.second)); value.bits[i] = init_bits.at(sig[i]); cleanup_bits.insert(sig[i]); } -- cgit v1.2.3 From e08df0c7390e1e7736c3d5b0abbe2679bf9b4518 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 3 May 2019 08:06:16 -0700 Subject: If init is 1'bx, do not add to dict as per @cliffordwolf --- passes/techmap/dffinit.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'passes') diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc index 48390488e..0ad33dc0e 100644 --- a/passes/techmap/dffinit.cc +++ b/passes/techmap/dffinit.cc @@ -102,7 +102,8 @@ struct DffinitPass : public Pass { if (wire->attributes.count("\\init")) { Const value = wire->attributes.at("\\init"); for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) - init_bits[sigmap(SigBit(wire, i))] = value[i]; + if (value[i] != State::Sx) + init_bits[sigmap(SigBit(wire, i))] = value[i]; } if (wire->port_output) for (auto bit : sigmap(wire)) -- cgit v1.2.3 From a27b42e97571c817b0698964329d61dddc6e9a3a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Mar 2019 19:42:18 +0000 Subject: WIP -chparam support for hierarchy when verific --- passes/hierarchy/hierarchy.cc | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'passes') diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index b8ff99884..483b386e5 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -570,7 +570,7 @@ struct HierarchyPass : public Pass { log("\n"); log(" -simcheck\n"); log(" like -check, but also throw an error if blackbox modules are\n"); - log(" instantiated, and throw an error if the design has no top module\n"); + log(" instantiated, and throw an error if the design has no top module.\n"); log("\n"); log(" -purge_lib\n"); log(" by default the hierarchy command will not remove library (blackbox)\n"); @@ -583,20 +583,20 @@ struct HierarchyPass : public Pass { log("\n"); log(" -keep_positionals\n"); log(" per default this pass also converts positional arguments in cells\n"); - log(" to arguments using port names. this option disables this behavior.\n"); + log(" to arguments using port names. This option disables this behavior.\n"); log("\n"); log(" -keep_portwidths\n"); log(" per default this pass adjusts the port width on cells that are\n"); - log(" module instances when the width does not match the module port. this\n"); + log(" module instances when the width does not match the module port. This\n"); log(" option disables this behavior.\n"); log("\n"); log(" -nokeep_asserts\n"); log(" per default this pass sets the \"keep\" attribute on all modules\n"); - log(" that directly or indirectly contain one or more $assert cells. this\n"); + log(" that directly or indirectly contain one or more $assert cells. This\n"); log(" option disables this behavior.\n"); log("\n"); log(" -top \n"); - log(" use the specified top module to built a design hierarchy. modules\n"); + log(" use the specified top module to build the design hierarchy. Modules\n"); log(" outside this tree (unused modules) are removed.\n"); log("\n"); log(" when the -top option is used, the 'top' attribute will be set on the\n"); @@ -606,6 +606,12 @@ struct HierarchyPass : public Pass { log(" -auto-top\n"); log(" automatically determine the top of the design hierarchy and mark it.\n"); log("\n"); + log(" -chparam name value \n"); + log(" elaborate the top module using this parameter value. Modules on which\n"); + log(" this parameter does not exist may cause a warning message to be output.\n"); + log(" This option can be specified multiple times to override multiple\n"); + log(" parameters. String values must be passed in double quotes (\").\n"); + log("\n"); log("In -generate mode this pass generates blackbox modules for the given cell\n"); log("types (wildcards supported). For this the design is searched for cells that\n"); log("match the given types and then the given port declarations are used to\n"); @@ -641,6 +647,7 @@ struct HierarchyPass : public Pass { bool nokeep_asserts = false; std::vector generate_cells; std::vector generate_ports; + std::map parameters; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -729,6 +736,16 @@ struct HierarchyPass : public Pass { auto_top_mode = true; continue; } + if (args[argidx] == "-chparam" && argidx+2 < args.size()) { + const std::string &key = args[++argidx]; + const std::string &value = args[++argidx]; + auto r = parameters.emplace(key, value); + if (!r.second) { + log_warning_noprefix("-chparam %s already specified: overwriting.\n", key.c_str()); + r.first->second = value; + } + continue; + } break; } extra_args(args, argidx, design, false); @@ -736,7 +753,7 @@ struct HierarchyPass : public Pass { if (!load_top_mod.empty()) { #ifdef YOSYS_ENABLE_VERIFIC if (verific_import_pending) { - verific_import(design, load_top_mod); + verific_import(design, parameters, load_top_mod); top_mod = design->module(RTLIL::escape_id(load_top_mod)); } #endif @@ -745,7 +762,7 @@ struct HierarchyPass : public Pass { } else { #ifdef YOSYS_ENABLE_VERIFIC if (verific_import_pending) - verific_import(design); + verific_import(design, parameters); #endif } -- cgit v1.2.3 From eb21bf36513151a6df434cf277be0df70337356a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Mar 2019 15:29:43 +0000 Subject: log_warning_noprefix -> log_warning as per review --- passes/hierarchy/hierarchy.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes') diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 483b386e5..71dcfb194 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -741,7 +741,7 @@ struct HierarchyPass : public Pass { const std::string &value = args[++argidx]; auto r = parameters.emplace(key, value); if (!r.second) { - log_warning_noprefix("-chparam %s already specified: overwriting.\n", key.c_str()); + log_warning("-chparam %s already specified: overwriting.\n", key.c_str()); r.first->second = value; } continue; -- cgit v1.2.3 From ec39cfd0ad8c0d3d5757c7a8736952e74dd6dd79 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 May 2019 22:03:43 +0200 Subject: Add "hierarchy -chparam" support for non-verific top modules Signed-off-by: Clifford Wolf --- passes/hierarchy/hierarchy.cc | 47 ++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 12 deletions(-) (limited to 'passes') diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 71dcfb194..72bc2e133 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -592,8 +592,8 @@ struct HierarchyPass : public Pass { log("\n"); log(" -nokeep_asserts\n"); log(" per default this pass sets the \"keep\" attribute on all modules\n"); - log(" that directly or indirectly contain one or more $assert cells. This\n"); - log(" option disables this behavior.\n"); + log(" that directly or indirectly contain one or more formal properties.\n"); + log(" This option disables this behavior.\n"); log("\n"); log(" -top \n"); log(" use the specified top module to build the design hierarchy. Modules\n"); @@ -722,14 +722,7 @@ struct HierarchyPass : public Pass { if (args[argidx] == "-top") { if (++argidx >= args.size()) log_cmd_error("Option -top requires an additional argument!\n"); - top_mod = design->modules_.count(RTLIL::escape_id(args[argidx])) ? design->modules_.at(RTLIL::escape_id(args[argidx])) : NULL; - if (top_mod == NULL && design->modules_.count("$abstract" + RTLIL::escape_id(args[argidx]))) { - dict empty_parameters; - design->modules_.at("$abstract" + RTLIL::escape_id(args[argidx]))->derive(design, empty_parameters); - top_mod = design->modules_.count(RTLIL::escape_id(args[argidx])) ? design->modules_.at(RTLIL::escape_id(args[argidx])) : NULL; - } - if (top_mod == NULL) - load_top_mod = args[argidx]; + load_top_mod = args[argidx]; continue; } if (args[argidx] == "-auto-top") { @@ -750,7 +743,37 @@ struct HierarchyPass : public Pass { } extra_args(args, argidx, design, false); - if (!load_top_mod.empty()) { + if (!load_top_mod.empty()) + { + IdString top_name = RTLIL::escape_id(load_top_mod); + IdString abstract_id = "$abstract" + RTLIL::escape_id(load_top_mod); + top_mod = design->module(top_name); + + dict top_parameters; + for (auto ¶ : parameters) { + SigSpec sig_value; + if (!RTLIL::SigSpec::parse(sig_value, NULL, para.second)) + log_cmd_error("Can't decode value '%s'!\n", para.second.c_str()); + top_parameters[RTLIL::escape_id(para.first)] = sig_value.as_const(); + } + + if (top_mod == nullptr && design->module(abstract_id)) + top_mod = design->module(design->module(abstract_id)->derive(design, top_parameters)); + else if (top_mod != nullptr && !top_parameters.empty()) + top_mod = design->module(top_mod->derive(design, top_parameters)); + + if (top_mod != nullptr && top_mod->name != top_name) { + Module *m = top_mod->clone(); + m->name = top_name; + Module *old_mod = design->module(top_name); + if (old_mod) + design->remove(old_mod); + design->add(m); + top_mod = m; + } + } + + if (top_mod == nullptr && !load_top_mod.empty()) { #ifdef YOSYS_ENABLE_VERIFIC if (verific_import_pending) { verific_import(design, parameters, load_top_mod); @@ -863,7 +886,7 @@ struct HierarchyPass : public Pass { std::map cache; for (auto mod : design->modules()) if (set_keep_assert(cache, mod)) { - log("Module %s directly or indirectly contains $assert cells -> setting \"keep\" attribute.\n", log_id(mod)); + log("Module %s directly or indirectly contains formal properties -> setting \"keep\" attribute.\n", log_id(mod)); mod->set_bool_attribute("\\keep"); } } -- cgit v1.2.3 From a01386c0e45b4eee5295db440740a1ab271396fe Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 4 May 2019 09:47:16 +0200 Subject: Improve opt_clean handling of unused wires Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 96118e906..9f6212526 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -242,6 +242,10 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } } + SigPool raw_used_signals_noaliases; + for (auto &it : module->connections_) + raw_used_signals_noaliases.add(it.second); + module->connections_.clear(); SigPool used_signals; @@ -251,6 +255,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos for (auto &it2 : cell->connections_) { assign_map.apply(it2.second); used_signals.add(it2.second); + raw_used_signals_noaliases.add(it2.second); if (!ct_all.cell_output(cell->type, it2.first)) used_signals_nodrivers.add(it2.second); } @@ -277,23 +282,30 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos SigSpec s1 = SigSpec(wire), s2 = assign_map(s1); log_assert(GetSize(s1) == GetSize(s2)); + Const initval; + if (wire->attributes.count("\\init")) + initval = wire->attributes.at("\\init"); + if (GetSize(initval) != GetSize(wire)) + initval.bits.resize(GetSize(wire), State::Sx); + if (initval.is_fully_undef()) + wire->attributes.erase("\\init"); + bool maybe_del = false; - if ((!purge_mode && check_public_name(wire->name)) || wire->port_id != 0 || wire->get_bool_attribute("\\keep") || wire->attributes.count("\\init")) { - if (!used_signals.check_any(s2) && wire->port_id == 0 && !wire->get_bool_attribute("\\keep")) - maybe_del = true; + 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 */ + } else + if (!purge_mode && check_public_name(wire->name)) { + /* do not get rid of public names unless in purge mode */ } else { - if (!used_signals.check_any(s2)) + if (!raw_used_signals_noaliases.check_any(s1)) + maybe_del = true; + if (!used_signals_nodrivers.check_any(s2)) maybe_del = true; } if (maybe_del) { maybe_del_wires.push_back(wire); } else { - Const initval; - if (wire->attributes.count("\\init")) - initval = wire->attributes.at("\\init"); - if (GetSize(initval) != GetSize(wire)) - initval.bits.resize(GetSize(wire), State::Sx); RTLIL::SigSig new_conn; for (int i = 0; i < GetSize(s1); i++) if (s1[i] != s2[i]) { @@ -341,7 +353,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos int del_wires_count = 0; for (auto wire : maybe_del_wires) { SigSpec s1 = SigSpec(wire); - if (used_signals.check_any(s1)) { + if (used_signals_nodrivers.check_any(s1)) { SigSpec s2 = assign_map(s1); Const initval; if (wire->attributes.count("\\init")) -- cgit v1.2.3 From 5ce9113eda2e82034fd47106d6f75b8f30fd79ab Mon Sep 17 00:00:00 2001 From: David Shah Date: Sat, 4 May 2019 16:53:25 +0100 Subject: abc: Improve name recovery Signed-off-by: David Shah --- passes/techmap/abc.cc | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'passes') diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 547115459..d7500f3c3 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -330,18 +330,31 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullptr) { std::string abc_sname = abc_name.substr(1); - if (abc_sname.substr(0, 5) == "ys__n") { + bool isnew = false; + if (abc_sname.substr(0, 4) == "new_") + { + abc_sname.erase(0, 4); + isnew = true; + } + if (abc_sname.substr(0, 5) == "ys__n") + { bool inv = abc_sname.back() == 'v'; if (inv) abc_sname.pop_back(); abc_sname.erase(0, 5); - if (abc_sname.find_last_not_of("012345689") == std::string::npos) { + if (std::isdigit(abc_sname.at(0))) + { int sid = std::stoi(abc_sname); - for (auto sig : signal_list) { - if (sig.id == sid && sig.bit.wire != nullptr) { + if (sid < GetSize(signal_list)) + { + auto sig = signal_list.at(sid); + if (sig.bit.wire != nullptr) + { std::stringstream sstr; sstr << "$abc$" << map_autoidx << "$" << sig.bit.wire->name.substr(1); if (sig.bit.wire->width != 1) sstr << "[" << sig.bit.offset << "]"; + if (isnew) + sstr << "_new"; if (inv) sstr << "_inv"; if (orig_wire != nullptr) -- cgit v1.2.3 From a84256aa366cd1e74de48444c136052564fdd0fe Mon Sep 17 00:00:00 2001 From: David Shah Date: Sat, 4 May 2019 17:17:30 +0100 Subject: abc: Fix handling of postfixed names (e.g. for retiming) Signed-off-by: David Shah --- passes/techmap/abc.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'passes') diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index d7500f3c3..5b19d84fb 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -338,12 +338,13 @@ std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullp } if (abc_sname.substr(0, 5) == "ys__n") { - bool inv = abc_sname.back() == 'v'; - if (inv) abc_sname.pop_back(); abc_sname.erase(0, 5); if (std::isdigit(abc_sname.at(0))) { int sid = std::stoi(abc_sname); + size_t postfix_start = abc_sname.find_first_not_of("0123456789"); + std::string postfix = postfix_start != std::string::npos ? abc_sname.substr(postfix_start) : ""; + if (sid < GetSize(signal_list)) { auto sig = signal_list.at(sid); @@ -355,8 +356,7 @@ std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullp sstr << "[" << sig.bit.offset << "]"; if (isnew) sstr << "_new"; - if (inv) - sstr << "_inv"; + sstr << postfix; if (orig_wire != nullptr) *orig_wire = sig.bit.wire; return sstr.str(); -- cgit v1.2.3 From ba6ce21a74425788b5a98e2e628c089841b47aa3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 6 May 2019 12:45:22 +0200 Subject: Cleanups in opt_clean Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 63 +++++++++++++------------------------------------ 1 file changed, 16 insertions(+), 47 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 9f6212526..81432b175 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -276,7 +276,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } } - std::vector maybe_del_wires; + pool del_wires_queue; for (auto wire : module->wires()) { SigSpec s1 = SigSpec(wire), s2 = assign_map(s1); @@ -290,7 +290,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (initval.is_fully_undef()) wire->attributes.erase("\\init"); - bool maybe_del = false; + bool delete_this_wire = false; 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 */ } else @@ -298,13 +298,13 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos /* do not get rid of public names unless in purge mode */ } else { if (!raw_used_signals_noaliases.check_any(s1)) - maybe_del = true; + delete_this_wire = true; if (!used_signals_nodrivers.check_any(s2)) - maybe_del = true; + delete_this_wire = true; } - if (maybe_del) { - maybe_del_wires.push_back(wire); + if (delete_this_wire) { + del_wires_queue.insert(wire); } else { RTLIL::SigSig new_conn; for (int i = 0; i < GetSize(s1); i++) @@ -347,50 +347,19 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } } - - pool del_wires; - - int del_wires_count = 0; - for (auto wire : maybe_del_wires) { - SigSpec s1 = SigSpec(wire); - if (used_signals_nodrivers.check_any(s1)) { - SigSpec s2 = assign_map(s1); - Const initval; - if (wire->attributes.count("\\init")) - initval = wire->attributes.at("\\init"); - if (GetSize(initval) != GetSize(wire)) - initval.bits.resize(GetSize(wire), State::Sx); - RTLIL::SigSig new_conn; - for (int i = 0; i < GetSize(s1); i++) - if (s1[i] != s2[i]) { - if (s2[i] == State::Sx && (initval[i] == State::S0 || initval[i] == State::S1)) { - s2[i] = initval[i]; - initval[i] = State::Sx; - } - new_conn.first.append_bit(s1[i]); - new_conn.second.append_bit(s2[i]); - } - if (new_conn.first.size() > 0) { - if (initval.is_fully_undef()) - wire->attributes.erase("\\init"); - else - wire->attributes.at("\\init") = initval; - module->connect(new_conn); - } - } else { - if (ys_debug() || (check_public_name(wire->name) && verbose)) { - log_debug(" removing unused non-port wire %s.\n", wire->name.c_str()); - } - del_wires.insert(wire); - del_wires_count++; - } + int del_temp_wires_count = 0; + for (auto wire : del_wires_queue) { + if (ys_debug() || (check_public_name(wire->name) && verbose)) + log_debug(" removing unused non-port wire %s.\n", wire->name.c_str()); + else + del_temp_wires_count++; } - module->remove(del_wires); - count_rm_wires += del_wires.size(); + module->remove(del_wires_queue); + count_rm_wires += GetSize(del_wires_queue); - if (verbose && del_wires_count > 0) - log_debug(" removed %d unused temporary wires.\n", del_wires_count); + if (verbose && del_temp_wires_count) + log_debug(" removed %d unused temporary wires.\n", del_temp_wires_count); } bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose) -- cgit v1.2.3 From f02e22a35a2b23bbeefa38e68f4fd06a7a7cebc7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 6 May 2019 13:30:43 +0200 Subject: Fix bug in "expose -input" Signed-off-by: Clifford Wolf --- passes/sat/expose.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes') diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc index 809345486..71ce1683d 100644 --- a/passes/sat/expose.cc +++ b/passes/sat/expose.cc @@ -508,7 +508,7 @@ struct ExposePass : public Pass { } for (auto &conn : module->connections_) - conn.first = out_to_in_map(sigmap(conn.first)); + conn.first = out_to_in_map(conn.first); } if (flag_cut) -- cgit v1.2.3 From b37c31e2cb82343e363d39e4b35ebdb82f4f69a3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 6 May 2019 15:34:19 +0200 Subject: Bugfix in peepopt_shiftmul.pmg Signed-off-by: Clifford Wolf --- passes/pmgen/peepopt_shiftmul.pmg | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'passes') diff --git a/passes/pmgen/peepopt_shiftmul.pmg b/passes/pmgen/peepopt_shiftmul.pmg index 1f9b3c2b9..fe861b728 100644 --- a/passes/pmgen/peepopt_shiftmul.pmg +++ b/passes/pmgen/peepopt_shiftmul.pmg @@ -8,9 +8,13 @@ endmatch code shamt shamt = port(shift, \B); + if (shamt.empty()) + reject; if (shamt[GetSize(shamt)-1] == State::S0) { do { shamt.remove(GetSize(shamt)-1); + if (shamt.empty()) + reject; } while (shamt[GetSize(shamt)-1] == State::S0); } else if (shift->type.in($shift, $shiftx) && param(shift, \B_SIGNED).as_bool()) { -- cgit v1.2.3 From a76189e7adb88a81b8c1a8910524323fe93a421c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 7 May 2019 14:41:58 +0200 Subject: More opt_clean cleanups Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 62 ++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 26 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 249939876..6ca6ac820 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -320,22 +320,32 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (initval.is_fully_undef()) wire->attributes.erase("\\init"); - bool delete_this_wire = false; + if (GetSize(wire) == 0) { + // delete zero-width wires + 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 */ + // do not delete anything with "keep" or module ports or initialized wires } else if (!purge_mode && check_public_name(wire->name)) { - /* do not get rid of public names unless in purge mode */ - } else { - if (!raw_used_signals_noaliases.check_any(s1)) - delete_this_wire = true; - if (!used_signals_nodrivers.check_any(s2)) - delete_this_wire = true; + // do not get rid of public names unless in purge mode + } else + if (!raw_used_signals_noaliases.check_any(s1)) { + // delete wires that aren't used by anything directly + goto delete_this_wire; + } else + if (!used_signals_nodrivers.check_any(s2)) { + // delete wires that aren't used by anything indirectly, even though other wires may alias it + goto delete_this_wire; } - if (delete_this_wire) { + if (0) + { + delete_this_wire: del_wires_queue.insert(wire); - } else { + } + else + { RTLIL::SigSig new_conn; for (int i = 0; i < GetSize(s1); i++) if (s1[i] != s2[i]) { @@ -355,25 +365,25 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos used_signals.add(new_conn.second); module->connect(new_conn); } - } - if (!used_signals_nodrivers.check_all(s2)) { - std::string unused_bits; - for (int i = 0; i < GetSize(s2); i++) { - if (s2[i].wire == NULL) - continue; - if (!used_signals_nodrivers.check(s2[i])) { - if (!unused_bits.empty()) - unused_bits += " "; - unused_bits += stringf("%d", i); + if (!used_signals_nodrivers.check_all(s2)) { + std::string unused_bits; + for (int i = 0; i < GetSize(s2); i++) { + if (s2[i].wire == NULL) + continue; + if (!used_signals_nodrivers.check(s2[i])) { + if (!unused_bits.empty()) + unused_bits += " "; + unused_bits += stringf("%d", i); + } } - } - if (unused_bits.empty() || wire->port_id != 0) + if (unused_bits.empty() || wire->port_id != 0) + wire->attributes.erase("\\unused_bits"); + else + wire->attributes["\\unused_bits"] = RTLIL::Const(unused_bits); + } else { wire->attributes.erase("\\unused_bits"); - else - wire->attributes["\\unused_bits"] = RTLIL::Const(unused_bits); - } else { - wire->attributes.erase("\\unused_bits"); + } } } -- cgit v1.2.3 From 30c762d3a148afa9e27a93c1fa098b7c478511a4 Mon Sep 17 00:00:00 2001 From: Kristoffer Ellersgaard Koch Date: Sun, 5 May 2019 10:00:27 +0200 Subject: Fix all warnings that occurred when compiling with gcc9 --- passes/cmds/bugpoint.cc | 3 +-- passes/techmap/flowmap.cc | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'passes') diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc index 4b22f6d2d..85e2b0d56 100644 --- a/passes/cmds/bugpoint.cc +++ b/passes/cmds/bugpoint.cc @@ -298,7 +298,7 @@ struct BugpointPass : public Pass { if (!check_logfile(grep)) log_cmd_error("The provided grep string is not found in the log file!\n"); - int seed = 0, crashing_seed = seed; + int seed = 0; bool found_something = false, stage2 = false; while (true) { @@ -324,7 +324,6 @@ struct BugpointPass : public Pass { if (crashing_design != design) delete crashing_design; crashing_design = simplified; - crashing_seed = seed; found_something = true; } else diff --git a/passes/techmap/flowmap.cc b/passes/techmap/flowmap.cc index 0b7931e48..f5892a60e 100644 --- a/passes/techmap/flowmap.cc +++ b/passes/techmap/flowmap.cc @@ -397,7 +397,6 @@ struct FlowGraph pool x, xi; NodePrime source_prime = {source, true}; - NodePrime sink_prime = {sink, false}; pool visited; vector worklist = {source_prime}; while (!worklist.empty()) @@ -1382,7 +1381,8 @@ struct FlowmapWorker vector input_nodes(lut_edges_bw[node].begin(), lut_edges_bw[node].end()); RTLIL::Const lut_table(State::Sx, max(1 << input_nodes.size(), 1 << minlut)); - for (unsigned i = 0; i < (1 << input_nodes.size()); i++) + unsigned const mask = 1 << input_nodes.size(); + for (unsigned i = 0; i < mask; i++) { ce.push(); for (size_t n = 0; n < input_nodes.size(); n++) -- cgit v1.2.3 From 2f5cfa014b4fda75eefdf1499721aae4aabb8419 Mon Sep 17 00:00:00 2001 From: Makai Mann Date: Fri, 10 May 2019 10:23:14 -0700 Subject: Zinit option '-singleton' -> '-all' --- passes/techmap/zinit.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes') diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc index b46147fb9..2aefc091d 100644 --- a/passes/techmap/zinit.cc +++ b/passes/techmap/zinit.cc @@ -46,7 +46,7 @@ struct ZinitPass : public Pass { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-singleton") { + if (args[argidx] == "-all") { all_mode = true; continue; } -- cgit v1.2.3 From 04ef222cfb618b6ee7c43b6bef82299d5b5bc010 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 May 2019 09:24:52 +0200 Subject: Add "stat -tech xilinx" Signed-off-by: Clifford Wolf --- passes/cmds/stat.cc | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 3 deletions(-) (limited to 'passes') diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 54f4ea817..d22685b62 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -37,7 +37,9 @@ struct statdata_t STAT_INT_MEMBERS #undef X double area; + string tech; + std::map techinfo; std::map num_cells_by_type; std::set unknown_cell_area; @@ -70,8 +72,10 @@ struct statdata_t #undef X } - statdata_t(RTLIL::Design *design, RTLIL::Module *mod, bool width_mode, const dict &cell_area) + statdata_t(RTLIL::Design *design, RTLIL::Module *mod, bool width_mode, const dict &cell_area, string techname) { + tech = techname; + #define X(_name) _name = 0; STAT_NUMERIC_MEMBERS #undef X @@ -153,7 +157,8 @@ struct statdata_t log(" Number of processes: %6d\n", num_processes); log(" Number of cells: %6d\n", num_cells); for (auto &it : num_cells_by_type) - log(" %-26s %6d\n", RTLIL::id2cstr(it.first), it.second); + if (it.second) + log(" %-26s %6d\n", RTLIL::id2cstr(it.first), it.second); if (!unknown_cell_area.empty()) { log("\n"); @@ -165,6 +170,59 @@ struct statdata_t log("\n"); log(" Chip area for %smodule '%s': %f\n", (top_mod) ? "top " : "", mod_name.c_str(), area); } + + if (tech == "xilinx") + { + int lut6_cnt = num_cells_by_type["\\LUT6"]; + int lut5_cnt = num_cells_by_type["\\LUT5"]; + int lut4_cnt = num_cells_by_type["\\LUT4"]; + int lut3_cnt = num_cells_by_type["\\LUT3"]; + int lut2_cnt = num_cells_by_type["\\LUT2"]; + int lut1_cnt = num_cells_by_type["\\LUT1"]; + int lc_cnt = 0; + + lc_cnt += lut6_cnt; + + lc_cnt += lut5_cnt; + if (lut1_cnt) { + int cnt = std::min(lut5_cnt, lut1_cnt); + lut5_cnt -= cnt; + lut1_cnt -= cnt; + } + + lc_cnt += lut4_cnt; + if (lut1_cnt) { + int cnt = std::min(lut4_cnt, lut1_cnt); + lut4_cnt -= cnt; + lut1_cnt -= cnt; + } + if (lut2_cnt) { + int cnt = std::min(lut4_cnt, lut2_cnt); + lut4_cnt -= cnt; + lut2_cnt -= cnt; + } + + lc_cnt += lut3_cnt; + if (lut1_cnt) { + int cnt = std::min(lut3_cnt, lut1_cnt); + lut3_cnt -= cnt; + lut1_cnt -= cnt; + } + if (lut2_cnt) { + int cnt = std::min(lut3_cnt, lut2_cnt); + lut3_cnt -= cnt; + lut2_cnt -= cnt; + } + if (lut3_cnt) { + int cnt = (lut3_cnt + 1) / 2; + lut3_cnt -= cnt; + } + + lc_cnt += (lut2_cnt + lut1_cnt + 1) / 2; + + log("\n"); + log(" Estimated number of LCs: %10d\n", lc_cnt); + } } }; @@ -226,6 +284,10 @@ struct StatPass : public Pass { log(" -liberty \n"); log(" use cell area information from the provided liberty file\n"); log("\n"); + log(" -tech \n"); + log(" print area estemate for the specified technology. Corrently supported\n"); + log(" calues for : xilinx\n"); + log("\n"); log(" -width\n"); log(" annotate internal cell types with their word width.\n"); log(" e.g. $add_8 for an 8 bit wide $add cell.\n"); @@ -239,6 +301,7 @@ struct StatPass : public Pass { RTLIL::Module *top_mod = NULL; std::map mod_stat; dict cell_area; + string techname; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -253,6 +316,10 @@ struct StatPass : public Pass { read_liberty_cellarea(cell_area, liberty_file); continue; } + if (args[argidx] == "-tech" && argidx+1 < args.size()) { + techname = args[++argidx]; + continue; + } if (args[argidx] == "-top" && argidx+1 < args.size()) { if (design->modules_.count(RTLIL::escape_id(args[argidx+1])) == 0) log_cmd_error("Can't find module %s.\n", args[argidx+1].c_str()); @@ -263,13 +330,16 @@ struct StatPass : public Pass { } extra_args(args, argidx, design); + if (techname != "" && techname != "xilinx") + log_cmd_error("Unsupported technology: '%s'\n", techname.c_str()); + for (auto mod : design->selected_modules()) { if (!top_mod && design->full_selection()) if (mod->get_bool_attribute("\\top")) top_mod = mod; - statdata_t data(design, mod, width_mode, cell_area); + statdata_t data(design, mod, width_mode, cell_area, techname); mod_stat[mod->name] = data; log("\n"); -- cgit v1.2.3 From b66b657b6b161910be8a62d37b2d981d33c9f1e3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 May 2019 09:28:55 +0200 Subject: Add "fmcombine -initeq -anyeq" Signed-off-by: Clifford Wolf --- passes/sat/fmcombine.cc | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) (limited to 'passes') diff --git a/passes/sat/fmcombine.cc b/passes/sat/fmcombine.cc index cd75ca860..f64d99dc2 100644 --- a/passes/sat/fmcombine.cc +++ b/passes/sat/fmcombine.cc @@ -26,6 +26,8 @@ PRIVATE_NAMESPACE_BEGIN struct opts_t { + bool initeq = false; + bool anyeq = false; bool fwd = false; bool bwd = false; bool nop = false; @@ -56,7 +58,7 @@ struct FmcombineWorker return newsig; } - void import_prim_cell(Cell *cell, const string &suffix) + Cell *import_prim_cell(Cell *cell, const string &suffix) { Cell *c = module->addCell(cell->name.str() + suffix, cell->type); c->parameters = cell->parameters; @@ -64,6 +66,8 @@ struct FmcombineWorker for (auto &conn : cell->connections()) c->setPort(conn.first, import_sig(conn.second, suffix)); + + return c; } void import_hier_cell(Cell *cell) @@ -102,8 +106,24 @@ struct FmcombineWorker for (auto cell : original->cells()) { if (design->module(cell->type) == nullptr) { - import_prim_cell(cell, "_gold"); - import_prim_cell(cell, "_gate"); + if (opts.anyeq && cell->type.in("$anyseq", "$anyconst")) { + Cell *gold = import_prim_cell(cell, "_gold"); + for (auto &conn : cell->connections()) + module->connect(import_sig(conn.second, "_gate"), gold->getPort(conn.first)); + } else { + Cell *gold = import_prim_cell(cell, "_gold"); + Cell *gate = import_prim_cell(cell, "_gate"); + if (opts.initeq) { + if (cell->type.in("$ff", "$dff", "$dffe", + "$dffsr", "$adff", "$dlatch", "$dlatchsr")) { + SigSpec gold_q = gold->getPort("\\Q"); + SigSpec gate_q = gate->getPort("\\Q"); + SigSpec en = module->Initstate(NEW_ID); + SigSpec eq = module->Eq(NEW_ID, gold_q, gate_q); + module->addAssume(NEW_ID, eq, en); + } + } + } } else { import_hier_cell(cell); } @@ -229,6 +249,13 @@ struct FmcombinePass : public Pass { log("This is useful for formal test benches that check what differences in behavior\n"); log("a slight difference in input causes in a module.\n"); log("\n"); + log(" -initeq\n"); + log(" Insert assumptions that initially all FFs in both circuits have the\n"); + log(" same initial values.\n"); + log("\n"); + log(" -anyeq\n"); + log(" Do not duplicate $anyseq/$anyconst cells.\n"); + log("\n"); log(" -fwd\n"); log(" Insert forward hint assumptions into the combined module.\n"); log("\n"); @@ -261,6 +288,14 @@ struct FmcombinePass : public Pass { // filename = args[++argidx]; // continue; // } + if (args[argidx] == "-initeq") { + opts.initeq = true; + continue; + } + if (args[argidx] == "-anyeq") { + opts.anyeq = true; + continue; + } if (args[argidx] == "-fwd") { opts.fwd = true; continue; -- cgit v1.2.3 From 8166a142dd251f9d9ba2d172737d757ac52aa772 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 12 May 2019 13:51:12 +0200 Subject: Fix handling of glob_abort_cnt in opt_muxtree, fixes #1002 Signed-off-by: Clifford Wolf --- passes/opt/opt_muxtree.cc | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index dbebf21e0..6511e091b 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -184,6 +184,10 @@ struct OptMuxtreeWorker log_debug(" Root of a mux tree: %s%s\n", log_id(mux2info[mux_idx].cell), root_enable_muxes.at(mux_idx) ? " (pure)" : ""); root_mux_rerun.erase(mux_idx); eval_root_mux(mux_idx); + if (glob_abort_cnt == 0) { + log(" Giving up (too many iterations)\n"); + return; + } } while (!root_mux_rerun.empty()) { @@ -192,9 +196,14 @@ struct OptMuxtreeWorker log_assert(root_enable_muxes.at(mux_idx)); root_mux_rerun.erase(mux_idx); eval_root_mux(mux_idx); + if (glob_abort_cnt == 0) { + log(" Giving up (too many iterations)\n"); + return; + } } log(" Analyzing evaluation results.\n"); + log_assert(glob_abort_cnt > 0); for (auto &mi : mux2info) { @@ -397,10 +406,8 @@ struct OptMuxtreeWorker void eval_mux(knowledge_t &knowledge, int mux_idx, bool do_replace_known, bool do_enable_ports, int abort_count) { - if (glob_abort_cnt == 0) { - log(" Giving up (too many iterations)\n"); + if (glob_abort_cnt == 0) return; - } glob_abort_cnt--; muxinfo_t &muxinfo = mux2info[mux_idx]; @@ -454,6 +461,7 @@ struct OptMuxtreeWorker void eval_root_mux(int mux_idx) { + log_assert(glob_abort_cnt > 0); knowledge_t knowledge; knowledge.known_inactive.resize(GetSize(bit2info)); knowledge.known_active.resize(GetSize(bit2info)); -- cgit v1.2.3 From c8c1df23a0ddf85b6d5a822299634b42b82a6e15 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 13 May 2019 16:55:15 +0000 Subject: bugpoint: check for -script option. Fixes #925. --- passes/cmds/bugpoint.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'passes') diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc index 85e2b0d56..038ab7c7c 100644 --- a/passes/cmds/bugpoint.cc +++ b/passes/cmds/bugpoint.cc @@ -281,6 +281,9 @@ struct BugpointPass : public Pass { } extra_args(args, argidx, design); + if (script.empty()) + log_cmd_error("Missing -script option.\n"); + if (!has_part) { modules = true; -- cgit v1.2.3 From 5e443a5d0db8f517582818e756871ec2e8117dbe Mon Sep 17 00:00:00 2001 From: Henner Zeller Date: Tue, 14 May 2019 22:01:15 -0700 Subject: Fix two instances of integer-assignment to string. o In cover.cc, the int-result of mkstemps() was assigned to a string and silently interpreted as a single-character filename with a funny value. Fix with the intent: assign the filename. o in libparse.cc, an int was assigned to a string, but depending on visible constructors, this is ambiguous. Explicitly cast this to a char. --- passes/cmds/cover.cc | 3 ++- passes/techmap/libparse.cc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'passes') diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc index 0ec747671..721ebded4 100644 --- a/passes/cmds/cover.cc +++ b/passes/cmds/cover.cc @@ -105,7 +105,8 @@ struct CoverPass : public Pass { #else char filename_buffer[4096]; snprintf(filename_buffer, 4096, "%s/yosys_cover_%d_XXXXXX.txt", filename.c_str(), getpid()); - filename = mkstemps(filename_buffer, 4); + mkstemps(filename_buffer, 4); + filename = filename_buffer; #endif } FILE *f = fopen(filename.c_str(), open_mode); diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc index 991cc4498..349ccc115 100644 --- a/passes/techmap/libparse.cc +++ b/passes/techmap/libparse.cc @@ -94,7 +94,7 @@ int LibertyParser::lexer(std::string &str) // search for identifiers, numbers, plus or minus. if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.') { - str = c; + str = static_cast(c); while (1) { c = f.get(); if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.') -- cgit v1.2.3 From f67ec1b2350c3bd88edacba7ad799bf60b33da61 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 15 May 2019 13:51:02 +0200 Subject: Do not leak file descriptors in cover.cc Signed-off-by: Clifford Wolf --- passes/cmds/cover.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'passes') diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc index 721ebded4..1128116b4 100644 --- a/passes/cmds/cover.cc +++ b/passes/cmds/cover.cc @@ -98,22 +98,23 @@ struct CoverPass : public Pass { } if ((args[argidx] == "-o" || args[argidx] == "-a" || args[argidx] == "-d") && argidx+1 < args.size()) { const char *open_mode = args[argidx] == "-a" ? "a+" : "w"; - std::string filename = args[++argidx]; + const std::string &filename = args[++argidx]; + FILE *f = nullptr; if (args[argidx-1] == "-d") { #ifdef _WIN32 log_cmd_error("The 'cover -d' option is not supported on win32.\n"); #else char filename_buffer[4096]; snprintf(filename_buffer, 4096, "%s/yosys_cover_%d_XXXXXX.txt", filename.c_str(), getpid()); - mkstemps(filename_buffer, 4); - filename = filename_buffer; + f = fdopen(mkstemps(filename_buffer, 4), "w"); #endif + } else { + f = fopen(filename.c_str(), open_mode); } - FILE *f = fopen(filename.c_str(), open_mode); if (f == NULL) { for (auto f : out_files) fclose(f); - log_cmd_error("Can't create file %s.\n", args[argidx].c_str()); + log_cmd_error("Can't create file %s%s.\n", args[argidx-1] == "-d" ? "in directory " : "", args[argidx].c_str()); } out_files.push_back(f); continue; -- cgit v1.2.3 From a21a84b3b45d252ff050d3ae7e738d157b0b2be8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 15 May 2019 16:01:28 +0200 Subject: Improvements in opt_clean Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'passes') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 6ca6ac820..bf8020169 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -232,7 +232,7 @@ bool check_public_name(RTLIL::IdString id) return true; } -void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbose) +bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbose) { SigPool register_signals; SigPool connected_signals; @@ -272,20 +272,17 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } } - SigPool raw_used_signals_noaliases; - for (auto &it : module->connections_) - raw_used_signals_noaliases.add(it.second); - module->connections_.clear(); SigPool used_signals; + SigPool raw_used_signals; SigPool used_signals_nodrivers; for (auto &it : module->cells_) { RTLIL::Cell *cell = it.second; for (auto &it2 : cell->connections_) { assign_map.apply(it2.second); + raw_used_signals.add(it2.second); used_signals.add(it2.second); - raw_used_signals_noaliases.add(it2.second); if (!ct_all.cell_output(cell->type, it2.first)) used_signals_nodrivers.add(it2.second); } @@ -294,6 +291,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos RTLIL::Wire *wire = it.second; if (wire->port_id > 0) { RTLIL::SigSpec sig = RTLIL::SigSpec(wire); + raw_used_signals.add(sig); assign_map.apply(sig); used_signals.add(sig); if (!wire->port_input) @@ -330,11 +328,11 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (!purge_mode && check_public_name(wire->name)) { // do not get rid of public names unless in purge mode } else - if (!raw_used_signals_noaliases.check_any(s1)) { + if (!raw_used_signals.check_any(s1)) { // delete wires that aren't used by anything directly goto delete_this_wire; } else - if (!used_signals_nodrivers.check_any(s2)) { + if (!used_signals.check_any(s2)) { // delete wires that aren't used by anything indirectly, even though other wires may alias it goto delete_this_wire; } @@ -400,6 +398,8 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (verbose && del_temp_wires_count) log_debug(" removed %d unused temporary wires.\n", del_temp_wires_count); + + return !del_wires_queue.empty(); } bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose) @@ -497,10 +497,10 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool module->design->scratchpad_set_bool("opt.did_something", true); rmunused_module_cells(module, verbose); - rmunused_module_signals(module, purge_mode, verbose); + while (rmunused_module_signals(module, purge_mode, verbose)) { } if (rminit && rmunused_module_init(module, purge_mode, verbose)) - rmunused_module_signals(module, purge_mode, verbose); + while (rmunused_module_signals(module, purge_mode, verbose)) { } } struct OptCleanPass : public Pass { -- cgit v1.2.3