aboutsummaryrefslogtreecommitdiffstats
path: root/passes/opt
diff options
context:
space:
mode:
Diffstat (limited to 'passes/opt')
-rw-r--r--passes/opt/opt_expr.cc116
-rw-r--r--passes/opt/opt_merge.cc234
-rw-r--r--passes/opt/share.cc46
3 files changed, 225 insertions, 171 deletions
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index 882d49a90..f9c5f68f2 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -31,9 +31,8 @@ PRIVATE_NAMESPACE_BEGIN
bool did_something;
-void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
+void replace_undriven(RTLIL::Module *module, const CellTypes &ct)
{
- CellTypes ct(design);
SigMap sigmap(module);
SigPool driven_signals;
SigPool used_signals;
@@ -496,6 +495,42 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
}
+ if (cell->type.in(ID($_XOR_), ID($_XNOR_)) || (cell->type.in(ID($xor), ID($xnor)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::B)) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool()))
+ {
+ SigBit sig_a = assign_map(cell->getPort(ID::A));
+ SigBit sig_b = assign_map(cell->getPort(ID::B));
+ if (!sig_a.wire)
+ std::swap(sig_a, sig_b);
+ if (sig_b == State::S0 || sig_b == State::S1) {
+ if (cell->type.in(ID($xor), ID($_XOR_))) {
+ cover("opt.opt_expr.xor_buffer");
+ SigSpec sig_y;
+ if (cell->type == ID($xor))
+ sig_y = (sig_b == State::S1 ? module->Not(NEW_ID, sig_a).as_bit() : sig_a);
+ else if (cell->type == ID($_XOR_))
+ sig_y = (sig_b == State::S1 ? module->NotGate(NEW_ID, sig_a) : sig_a);
+ else log_abort();
+ replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_y);
+ goto next_cell;
+ }
+ if (cell->type.in(ID($xnor), ID($_XNOR_))) {
+ cover("opt.opt_expr.xnor_buffer");
+ SigSpec sig_y;
+ if (cell->type == ID($xnor)) {
+ sig_y = (sig_b == State::S1 ? sig_a : module->Not(NEW_ID, sig_a).as_bit());
+ int width = cell->getParam(ID(Y_WIDTH)).as_int();
+ sig_y.append(RTLIL::Const(State::S1, width-1));
+ }
+ else if (cell->type == ID($_XNOR_))
+ sig_y = (sig_b == State::S1 ? sig_a : module->NotGate(NEW_ID, sig_a));
+ else log_abort();
+ replace_cell(assign_map, module, cell, "xnor_buffer", ID::Y, sig_y);
+ goto next_cell;
+ }
+ log_abort();
+ }
+ }
+
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool), ID($reduce_xor), ID($reduce_xnor), ID($neg)) &&
GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::Y)) == 1)
{
@@ -651,10 +686,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
int i;
for (i = 0; i < GetSize(sig_y); i++) {
- if (sig_b.at(i, State::Sx) == State::S0 && sig_a.at(i, State::Sx) != State::Sx)
- module->connect(sig_y[i], sig_a[i]);
- else if (!sub && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx)
- module->connect(sig_y[i], sig_b[i]);
+ RTLIL::SigBit b = sig_b.at(i, State::Sx);
+ RTLIL::SigBit a = sig_a.at(i, State::Sx);
+ if (b == State::S0 && a != State::Sx)
+ module->connect(sig_y[i], a);
+ else if (sub && b == State::S1 && a == State::S1)
+ module->connect(sig_y[i], State::S0);
+ else if (!sub && a == State::S0 && b != State::Sx)
+ module->connect(sig_y[i], b);
else
break;
}
@@ -668,7 +707,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
}
- if (cell->type == "$alu")
+ if (cell->type == ID($alu))
{
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
@@ -678,9 +717,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
RTLIL::SigSpec sig_co = cell->getPort(ID(CO));
- if (sig_ci.wire || sig_bi.wire)
- goto next_cell;
-
bool sub = (sig_ci == State::S1 && sig_bi == State::S1);
// If not a subtraction, yet there is a carry or B is inverted
@@ -690,14 +726,21 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
int i;
for (i = 0; i < GetSize(sig_y); i++) {
- if (sig_b.at(i, State::Sx) == State::S0 && sig_a.at(i, State::Sx) != State::Sx) {
- module->connect(sig_x[i], sub ? module->Not(NEW_ID, sig_a[i]).as_bit() : sig_a[i]);
+ RTLIL::SigBit b = sig_b.at(i, State::Sx);
+ RTLIL::SigBit a = sig_a.at(i, State::Sx);
+ if (b == State::S0 && a != State::Sx) {
module->connect(sig_y[i], sig_a[i]);
+ module->connect(sig_x[i], sub ? module->Not(NEW_ID, a).as_bit() : a);
module->connect(sig_co[i], sub ? State::S1 : State::S0);
}
- else if (!sub && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx) {
- module->connect(sig_x[i], sig_b[i]);
- module->connect(sig_y[i], sig_b[i]);
+ else if (sub && b == State::S1 && a == State::S1) {
+ module->connect(sig_y[i], State::S0);
+ module->connect(sig_x[i], module->Not(NEW_ID, a));
+ module->connect(sig_co[i], State::S0);
+ }
+ else if (!sub && a == State::S0 && b != State::Sx) {
+ module->connect(sig_y[i], b);
+ module->connect(sig_x[i], b);
module->connect(sig_co[i], State::S0);
}
else
@@ -842,8 +885,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (input.match("11")) ACTION_DO_Y(0);
if (input.match(" *")) ACTION_DO_Y(x);
if (input.match("* ")) ACTION_DO_Y(x);
- if (input.match(" 0")) ACTION_DO(ID::Y, input.extract(1, 1));
- if (input.match("0 ")) ACTION_DO(ID::Y, input.extract(0, 1));
}
if (cell->type == ID($_MUX_)) {
@@ -1032,12 +1073,26 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
bool identity_wrt_b = false;
bool arith_inverse = false;
- if (cell->type.in(ID($add), ID($sub), ID($or), ID($xor)))
+ if (cell->type.in(ID($add), ID($sub), ID($alu), ID($or), ID($xor)))
{
RTLIL::SigSpec a = assign_map(cell->getPort(ID::A));
RTLIL::SigSpec b = assign_map(cell->getPort(ID::B));
- if (cell->type != ID($sub) && a.is_fully_const() && a.as_bool() == false)
+ bool sub = cell->type == ID($sub);
+
+ if (cell->type == ID($alu)) {
+ RTLIL::SigBit sig_ci = assign_map(cell->getPort(ID(CI)));
+ RTLIL::SigBit sig_bi = assign_map(cell->getPort(ID(BI)));
+
+ sub = (sig_ci == State::S1 && sig_bi == State::S1);
+
+ // If not a subtraction, yet there is a carry or B is inverted
+ // then no optimisation is possible as carry will not be constant
+ if (!sub && (sig_ci != State::S0 || sig_bi != State::S0))
+ goto next_cell;
+ }
+
+ if (!sub && a.is_fully_const() && a.as_bool() == false)
identity_wrt_b = true;
if (b.is_fully_const() && b.as_bool() == false)
@@ -1075,17 +1130,27 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (identity_wrt_a || identity_wrt_b)
{
if (identity_wrt_a)
- cover_list("opt.opt_expr.identwrt.a", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str());
+ cover_list("opt.opt_expr.identwrt.a", "$add", "$sub", "$alu", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str());
if (identity_wrt_b)
- cover_list("opt.opt_expr.identwrt.b", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str());
+ cover_list("opt.opt_expr.identwrt.b", "$add", "$sub", "$alu", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str());
log_debug("Replacing %s cell `%s' in module `%s' with identity for port %c.\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B');
+ if (cell->type == ID($alu)) {
+ int y_width = GetSize(cell->getPort(ID(Y)));
+ module->connect(cell->getPort(ID(X)), RTLIL::Const(State::S0, y_width));
+ module->connect(cell->getPort(ID(CO)), RTLIL::Const(State::S0, y_width));
+ cell->unsetPort(ID(BI));
+ cell->unsetPort(ID(CI));
+ cell->unsetPort(ID(X));
+ cell->unsetPort(ID(CO));
+ }
+
if (!identity_wrt_a) {
cell->setPort(ID::A, cell->getPort(ID::B));
- cell->parameters.at(ID(A_WIDTH)) = cell->parameters.at(ID(B_WIDTH));
- cell->parameters.at(ID(A_SIGNED)) = cell->parameters.at(ID(B_SIGNED));
+ cell->setParam(ID(A_WIDTH), cell->getParam(ID(B_WIDTH)));
+ cell->setParam(ID(A_SIGNED), cell->getParam(ID(B_SIGNED)));
}
cell->type = arith_inverse ? ID($neg) : ID($pos);
@@ -1590,7 +1655,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
int const_bit_set = get_highest_hot_index(const_sig);
- if(const_bit_set >= var_width)
+ if (const_bit_set >= var_width)
{
string cmp_name;
if (cmp_type == ID($lt) || cmp_type == ID($le))
@@ -1737,13 +1802,14 @@ struct OptExprPass : public Pass {
}
extra_args(args, argidx, design);
+ CellTypes ct(design);
for (auto module : design->selected_modules())
{
log("Optimizing module %s.\n", log_id(module));
if (undriven) {
did_something = false;
- replace_undriven(design, module);
+ replace_undriven(module, ct);
if (did_something)
design->scratchpad_set_bool("opt.did_something", true);
}
diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc
index 8823a9061..4aa78ff39 100644
--- a/passes/opt/opt_merge.cc
+++ b/passes/opt/opt_merge.cc
@@ -26,7 +26,6 @@
#include <stdio.h>
#include <set>
-#define USE_CELL_HASH_CACHE
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -41,9 +40,7 @@ struct OptMergeWorker
CellTypes ct;
int total_count;
-#ifdef USE_CELL_HASH_CACHE
- dict<const RTLIL::Cell*, std::string> cell_hash_cache;
-#endif
+ SHA1 checksum;
static void sort_pmux_conn(dict<RTLIL::IdString, RTLIL::SigSpec> &conn)
{
@@ -68,7 +65,6 @@ struct OptMergeWorker
}
}
-#ifdef USE_CELL_HASH_CACHE
std::string int_to_hash_string(unsigned int v)
{
if (v == 0)
@@ -83,14 +79,9 @@ struct OptMergeWorker
std::string hash_cell_parameters_and_connections(const RTLIL::Cell *cell)
{
- if (cell_hash_cache.count(cell) > 0)
- return cell_hash_cache[cell];
-
+ vector<string> hash_conn_strings;
std::string hash_string = cell->type.str() + "\n";
- for (auto &it : cell->parameters)
- hash_string += "P " + it.first.str() + "=" + it.second.as_string() + "\n";
-
const dict<RTLIL::IdString, RTLIL::SigSpec> *conn = &cell->connections();
dict<RTLIL::IdString, RTLIL::SigSpec> alt_conn;
@@ -124,13 +115,22 @@ struct OptMergeWorker
conn = &alt_conn;
}
- vector<string> hash_conn_strings;
-
for (auto &it : *conn) {
- if (cell->output(it.first))
- continue;
- RTLIL::SigSpec sig = it.second;
- assign_map.apply(sig);
+ RTLIL::SigSpec sig;
+ if (cell->output(it.first)) {
+ if (it.first == ID(Q) && (cell->type.begins_with("$dff") || cell->type.begins_with("$dlatch") ||
+ cell->type.begins_with("$_DFF") || cell->type.begins_with("$_DLATCH") || cell->type.begins_with("$_SR_") ||
+ cell->type.in("$adff", "$sr", "$ff", "$_FF_"))) {
+ // For the 'Q' output of state elements,
+ // use its (* init *) attribute value
+ for (const auto &b : dff_init_map(it.second))
+ sig.append(b.wire ? State::Sx : b);
+ }
+ else
+ continue;
+ }
+ else
+ sig = assign_map(it.second);
string s = "C " + it.first.str() + "=";
for (auto &chunk : sig.chunks()) {
if (chunk.wire)
@@ -143,50 +143,59 @@ struct OptMergeWorker
hash_conn_strings.push_back(s + "\n");
}
+ for (auto &it : cell->parameters)
+ hash_conn_strings.push_back("P " + it.first.str() + "=" + it.second.as_string() + "\n");
+
std::sort(hash_conn_strings.begin(), hash_conn_strings.end());
for (auto it : hash_conn_strings)
hash_string += it;
- cell_hash_cache[cell] = sha1(hash_string);
- return cell_hash_cache[cell];
+ checksum.update(hash_string);
+ return checksum.final();
}
-#endif
- bool compare_cell_parameters_and_connections(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2, bool &lt)
+ bool compare_cell_parameters_and_connections(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2)
{
-#ifdef USE_CELL_HASH_CACHE
- std::string hash1 = hash_cell_parameters_and_connections(cell1);
- std::string hash2 = hash_cell_parameters_and_connections(cell2);
-
- if (hash1 != hash2) {
- lt = hash1 < hash2;
- return true;
- }
-#endif
-
- if (cell1->parameters != cell2->parameters) {
- std::map<RTLIL::IdString, RTLIL::Const> p1(cell1->parameters.begin(), cell1->parameters.end());
- std::map<RTLIL::IdString, RTLIL::Const> p2(cell2->parameters.begin(), cell2->parameters.end());
- lt = p1 < p2;
- return true;
- }
-
- dict<RTLIL::IdString, RTLIL::SigSpec> conn1 = cell1->connections();
- dict<RTLIL::IdString, RTLIL::SigSpec> conn2 = cell2->connections();
-
- for (auto &it : conn1) {
- if (cell1->output(it.first))
- it.second = RTLIL::SigSpec();
- else
- assign_map.apply(it.second);
- }
-
- for (auto &it : conn2) {
- if (cell2->output(it.first))
- it.second = RTLIL::SigSpec();
- else
- assign_map.apply(it.second);
+ log_assert(cell1 != cell2);
+ if (cell1->type != cell2->type) return false;
+
+ if (cell1->parameters != cell2->parameters)
+ return false;
+
+ if (cell1->connections_.size() != cell2->connections_.size())
+ return false;
+ for (const auto &it : cell1->connections_)
+ if (!cell2->connections_.count(it.first))
+ return false;
+
+ decltype(Cell::connections_) conn1, conn2;
+ conn1.reserve(cell1->connections_.size());
+ conn2.reserve(cell1->connections_.size());
+
+ for (const auto &it : cell1->connections_) {
+ if (cell1->output(it.first)) {
+ if (it.first == ID(Q) && (cell1->type.begins_with("$dff") || cell1->type.begins_with("$dlatch") ||
+ cell1->type.begins_with("$_DFF") || cell1->type.begins_with("$_DLATCH") || cell1->type.begins_with("$_SR_") ||
+ cell1->type.in("$adff", "$sr", "$ff", "$_FF_"))) {
+ // For the 'Q' output of state elements,
+ // use the (* init *) attribute value
+ auto &sig1 = conn1[it.first];
+ for (const auto &b : dff_init_map(it.second))
+ sig1.append(b.wire ? State::Sx : b);
+ auto &sig2 = conn2[it.first];
+ for (const auto &b : dff_init_map(cell2->getPort(it.first)))
+ sig2.append(b.wire ? State::Sx : b);
+ }
+ else {
+ conn1[it.first] = RTLIL::SigSpec();
+ conn2[it.first] = RTLIL::SigSpec();
+ }
+ }
+ else {
+ conn1[it.first] = assign_map(it.second);
+ conn2[it.first] = assign_map(cell2->getPort(it.first));
+ }
}
if (cell1->type == ID($and) || cell1->type == ID($or) || cell1->type == ID($xor) || cell1->type == ID($xnor) || cell1->type == ID($add) || cell1->type == ID($mul) ||
@@ -215,54 +224,9 @@ struct OptMergeWorker
sort_pmux_conn(conn2);
}
- if (conn1 != conn2) {
- std::map<RTLIL::IdString, RTLIL::SigSpec> c1(conn1.begin(), conn1.end());
- std::map<RTLIL::IdString, RTLIL::SigSpec> c2(conn2.begin(), conn2.end());
- lt = c1 < c2;
- return true;
- }
-
- if (conn1.count(ID(Q)) != 0 && (cell1->type.begins_with("$dff") || cell1->type.begins_with("$dlatch") ||
- cell1->type.begins_with("$_DFF") || cell1->type.begins_with("$_DLATCH") || cell1->type.begins_with("$_SR_") ||
- cell1->type.in("$adff", "$sr", "$ff", "$_FF_"))) {
- std::vector<RTLIL::SigBit> q1 = dff_init_map(cell1->getPort(ID(Q))).to_sigbit_vector();
- std::vector<RTLIL::SigBit> q2 = dff_init_map(cell2->getPort(ID(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;
+ return conn1 == conn2;
}
- bool compare_cells(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2)
- {
- if (cell1->type != cell2->type)
- return cell1->type < cell2->type;
-
- if ((!mode_share_all && !ct.cell_known(cell1->type)) || !cell1->known())
- return cell1 < cell2;
-
- if (cell1->has_keep_attr() || cell2->has_keep_attr())
- return cell1 < cell2;
-
- bool lt;
- if (compare_cell_parameters_and_connections(cell1, cell2, lt))
- return lt;
-
- return false;
- }
-
- struct CompareCells {
- OptMergeWorker *that;
- CompareCells(OptMergeWorker *that) : that(that) {}
- bool operator()(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2) const {
- return that->compare_cells(cell1, cell2);
- }
- };
-
OptMergeWorker(RTLIL::Design *design, RTLIL::Module *module, bool mode_nomux, bool mode_share_all) :
design(design), module(module), assign_map(module), mode_share_all(mode_share_all)
{
@@ -299,9 +263,6 @@ struct OptMergeWorker
bool did_something = true;
while (did_something)
{
-#ifdef USE_CELL_HASH_CACHE
- cell_hash_cache.clear();
-#endif
std::vector<RTLIL::Cell*> cells;
cells.reserve(module->cells_.size());
for (auto &it : module->cells_) {
@@ -312,42 +273,51 @@ struct OptMergeWorker
}
did_something = false;
- std::map<RTLIL::Cell*, RTLIL::Cell*, CompareCells> sharemap(CompareCells(this));
+ dict<std::string, RTLIL::Cell*> sharemap;
for (auto cell : cells)
{
- if (sharemap.count(cell) > 0) {
- did_something = true;
- log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), sharemap[cell]->name.c_str());
- for (auto &it : cell->connections()) {
- if (cell->output(it.first)) {
- RTLIL::SigSpec other_sig = sharemap[cell]->getPort(it.first);
- log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(),
- log_signal(it.second), log_signal(other_sig));
- module->connect(RTLIL::SigSig(it.second, other_sig));
- assign_map.add(it.second, other_sig);
-
- if (it.first == ID(Q) && (cell->type.begins_with("$dff") || cell->type.begins_with("$dlatch") ||
- cell->type.begins_with("$_DFF") || cell->type.begins_with("$_DLATCH") || cell->type.begins_with("$_SR_") ||
- cell->type.in("$adff", "$sr", "$ff", "$_FF_"))) {
- for (auto c : it.second.chunks()) {
- auto jt = c.wire->attributes.find(ID(init));
- if (jt == c.wire->attributes.end())
- continue;
- for (int i = c.offset; i < c.offset + c.width; i++)
- jt->second[i] = State::Sx;
+ if ((!mode_share_all && !ct.cell_known(cell->type)) || !cell->known())
+ continue;
+
+ auto hash = hash_cell_parameters_and_connections(cell);
+ auto r = sharemap.insert(std::make_pair(hash, cell));
+ if (!r.second) {
+ if (compare_cell_parameters_and_connections(cell, r.first->second)) {
+ if (cell->has_keep_attr()) {
+ if (r.first->second->has_keep_attr())
+ continue;
+ std::swap(r.first->second, cell);
+ }
+
+
+ did_something = true;
+ log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), r.first->second->name.c_str());
+ for (auto &it : cell->connections()) {
+ if (cell->output(it.first)) {
+ RTLIL::SigSpec other_sig = r.first->second->getPort(it.first);
+ log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(),
+ log_signal(it.second), log_signal(other_sig));
+ module->connect(RTLIL::SigSig(it.second, other_sig));
+ assign_map.add(it.second, other_sig);
+
+ if (it.first == ID(Q) && (cell->type.begins_with("$dff") || cell->type.begins_with("$dlatch") ||
+ cell->type.begins_with("$_DFF") || cell->type.begins_with("$_DLATCH") || cell->type.begins_with("$_SR_") ||
+ cell->type.in("$adff", "$sr", "$ff", "$_FF_"))) {
+ for (auto c : it.second.chunks()) {
+ auto jt = c.wire->attributes.find(ID(init));
+ if (jt == c.wire->attributes.end())
+ continue;
+ for (int i = c.offset; i < c.offset + c.width; i++)
+ jt->second[i] = State::Sx;
+ }
+ dff_init_map.add(it.second, Const(State::Sx, GetSize(it.second)));
}
- dff_init_map.add(it.second, Const(State::Sx, GetSize(it.second)));
}
}
+ log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str());
+ module->remove(cell);
+ total_count++;
}
- log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str());
-#ifdef USE_CELL_HASH_CACHE
- cell_hash_cache.erase(cell);
-#endif
- module->remove(cell);
- total_count++;
- } else {
- sharemap[cell] = cell;
}
}
}
diff --git a/passes/opt/share.cc b/passes/opt/share.cc
index 611a7862b..c11381138 100644
--- a/passes/opt/share.cc
+++ b/passes/opt/share.cc
@@ -41,7 +41,8 @@ struct ShareWorkerConfig
struct ShareWorker
{
- ShareWorkerConfig config;
+ const ShareWorkerConfig config;
+ int limit;
pool<RTLIL::IdString> generic_ops;
RTLIL::Design *design;
@@ -49,7 +50,6 @@ struct ShareWorker
CellTypes fwd_ct, cone_ct;
ModWalker modwalker;
- ModIndex mi;
pool<RTLIL::Cell*> cells_to_remove;
pool<RTLIL::Cell*> recursion_state;
@@ -1071,6 +1071,8 @@ struct ShareWorker
ct.setup_internals();
ct.setup_stdcells();
+ ModIndex mi(module);
+
pool<RTLIL::Cell*> queue, covered;
queue.insert(cell);
@@ -1117,13 +1119,9 @@ struct ShareWorker
module->remove(cell);
}
- ShareWorker(ShareWorkerConfig config, RTLIL::Design *design, RTLIL::Module *module) :
- config(config), design(design), module(module), mi(module)
+ ShareWorker(ShareWorkerConfig config, RTLIL::Design* design) :
+ config(config), design(design), modwalker(design)
{
- #ifndef NDEBUG
- bool before_scc = module_has_scc();
- #endif
-
generic_ops.insert(config.generic_uni_ops.begin(), config.generic_uni_ops.end());
generic_ops.insert(config.generic_bin_ops.begin(), config.generic_bin_ops.end());
generic_ops.insert(config.generic_cbin_ops.begin(), config.generic_cbin_ops.end());
@@ -1140,8 +1138,27 @@ struct ShareWorker
cone_ct.cell_types.erase(ID($shr));
cone_ct.cell_types.erase(ID($sshl));
cone_ct.cell_types.erase(ID($sshr));
+ }
- modwalker.setup(design, module);
+ void operator()(RTLIL::Module *module) {
+ this->module = module;
+
+ #ifndef NDEBUG
+ bool before_scc = module_has_scc();
+ #endif
+
+ limit = config.limit;
+ modwalker.setup(module);
+
+ cells_to_remove.clear();
+ recursion_state.clear();
+ topo_cell_drivers.clear();
+ topo_bit_drivers.clear();
+ exclusive_ctrls.clear();
+ terminal_bits.clear();
+ shareable_cells.clear();
+ forbidden_controls_cache.clear();
+ activation_patterns_cache.clear();
find_terminal_bits();
find_shareable_cells();
@@ -1399,8 +1416,8 @@ struct ShareWorker
topo_cell_drivers[cell] = { supercell };
topo_cell_drivers[other_cell] = { supercell };
- if (config.limit > 0)
- config.limit--;
+ if (limit > 0)
+ limit--;
break;
}
@@ -1528,9 +1545,10 @@ struct SharePass : public Pass {
}
extra_args(args, argidx, design);
- for (auto &mod_it : design->modules_)
- if (design->selected(mod_it.second))
- ShareWorker(config, design, mod_it.second);
+ ShareWorker sw(config, design);
+
+ for (auto module : design->selected_modules())
+ sw(module);
}
} SharePass;