Improvements in equiv_struct

This commit is contained in:
Clifford Wolf 2015-10-25 22:04:20 +01:00
parent d014ba2d0e
commit 27714acd8a
1 changed files with 62 additions and 17 deletions

View File

@ -84,7 +84,7 @@ struct EquivStructWorker
for (int i = 0; i < GetSize(inputs_a); i++) { for (int i = 0; i < GetSize(inputs_a); i++) {
SigBit bit_a = inputs_a[i], bit_b = inputs_b[i]; SigBit bit_a = inputs_a[i], bit_b = inputs_b[i];
SigBit bit_y = module->addWire(NEW_ID); SigBit bit_y = module->addWire(NEW_ID);
log(" New $equiv for input %s: A: %s, B: %s, Y: %s\n", log(" New $equiv for input %s: A: %s, B: %s, Y: %s\n",
input_names[i].c_str(), log_signal(bit_a), log_signal(bit_b), log_signal(bit_y)); input_names[i].c_str(), log_signal(bit_a), log_signal(bit_b), log_signal(bit_y));
module->addEquiv(NEW_ID, bit_a, bit_b, bit_y); module->addEquiv(NEW_ID, bit_a, bit_b, bit_y);
merged_map.add(bit_a, bit_y); merged_map.add(bit_a, bit_y);
@ -169,13 +169,14 @@ struct EquivStructWorker
for (auto &conn : cell->connections()) for (auto &conn : cell->connections())
{ {
SigSpec sig = equiv_bits(conn.second); if (cell->input(conn.first)) {
SigSpec sig = sigmap(conn.second);
if (cell->input(conn.first))
for (int i = 0; i < GetSize(sig); i++) for (int i = 0; i < GetSize(sig); i++)
fwd_connections.push_back(make_tuple(conn.first, i, sig[i])); fwd_connections.push_back(make_tuple(conn.first, i, sig[i]));
}
if (cell->output(conn.first)) if (cell->output(conn.first)) {
SigSpec sig = equiv_bits(conn.second);
for (int i = 0; i < GetSize(sig); i++) { for (int i = 0; i < GetSize(sig); i++) {
key.connections.clear(); key.connections.clear();
key.connections.push_back(make_tuple(conn.first, i, sig[i])); key.connections.push_back(make_tuple(conn.first, i, sig[i]));
@ -184,6 +185,7 @@ struct EquivStructWorker
bwd_merge_cache.insert(key); bwd_merge_cache.insert(key);
merge_cache[key].insert(cell_name); merge_cache[key].insert(cell_name);
} }
}
} }
std::sort(fwd_connections.begin(), fwd_connections.end()); std::sort(fwd_connections.begin(), fwd_connections.end());
@ -200,27 +202,66 @@ struct EquivStructWorker
for (auto &key : queue) for (auto &key : queue)
{ {
Cell *gold_cell = nullptr; const char *strategy = nullptr;
pool<Cell*> cells; vector<Cell*> gold_cells, gate_cells, other_cells;
vector<pair<Cell*, Cell*>> cell_pairs;
for (auto cell_name : merge_cache[key]) { for (auto cell_name : merge_cache[key]) {
Cell *c = module->cell(cell_name); Cell *c = module->cell(cell_name);
if (c != nullptr) { if (c != nullptr) {
string n = cell_name.str(); string n = cell_name.str();
if (gold_cell == nullptr || (GetSize(n) > 5 && n.substr(GetSize(n)-5) == "_gold")) if (GetSize(n) > 5 && n.substr(GetSize(n)-5) == "_gold")
gold_cell = c; gold_cells.push_back(c);
cells.insert(c); else if (GetSize(n) > 5 && n.substr(GetSize(n)-5) == "_gate")
gate_cells.push_back(c);
else
other_cells.push_back(c);
} }
} }
if (GetSize(cells) < 2) if (GetSize(gold_cells) > 1 || GetSize(gate_cells) > 1 || GetSize(other_cells) > 1)
continue; {
strategy = "deduplicate";
for (int i = 0; i+1 < GetSize(gold_cells); i += 2)
cell_pairs.push_back(make_pair(gold_cells[i], gold_cells[i+1]));
for (int i = 0; i+1 < GetSize(gate_cells); i += 2)
cell_pairs.push_back(make_pair(gate_cells[i], gate_cells[i+1]));
for (int i = 0; i+1 < GetSize(other_cells); i += 2)
cell_pairs.push_back(make_pair(other_cells[i], other_cells[i+1]));
goto run_strategy;
}
for (auto gate_cell : cells) if (GetSize(gold_cells) == 1 && GetSize(gate_cells) == 1)
if (gate_cell != gold_cell) { {
log(" %s merging cells %s and %s.\n", phase ? "Bwd" : "Fwd", log_id(gold_cell), log_id(gate_cell)); strategy = "gold-gate-pairs";
merge_cell_pair(gold_cell, gate_cell); cell_pairs.push_back(make_pair(gold_cells[0], gate_cells[0]));
} goto run_strategy;
}
if (GetSize(gold_cells) == 1 && GetSize(other_cells) == 1)
{
strategy = "gold-guess";
cell_pairs.push_back(make_pair(gold_cells[0], other_cells[0]));
goto run_strategy;
}
if (GetSize(other_cells) == 1 && GetSize(gate_cells) == 1)
{
strategy = "gate-guess";
cell_pairs.push_back(make_pair(other_cells[0], gate_cells[0]));
goto run_strategy;
}
log_assert(GetSize(gold_cells) + GetSize(gate_cells) + GetSize(other_cells) < 2);
continue;
run_strategy:
log(" %s merging %d cells (from group of %d) using strategy %s:\n", phase ? "Bwd" : "Fwd",
2*GetSize(cell_pairs), GetSize(gold_cells) + GetSize(gate_cells) + GetSize(other_cells), strategy);
for (auto it : cell_pairs) {
log(" Merging cells %s and %s.\n", log_id(it.first), log_id(it.second));
merge_cell_pair(it.first, it.second);
}
} }
if (merge_count > 0) if (merge_count > 0)
@ -278,12 +319,16 @@ struct EquivStructPass : public Pass {
extra_args(args, argidx, design); extra_args(args, argidx, design);
for (auto module : design->selected_modules()) { for (auto module : design->selected_modules()) {
int module_merge_count = 0;
log("Running equiv_struct on module %s:\n", log_id(module)); log("Running equiv_struct on module %s:\n", log_id(module));
while (1) { while (1) {
EquivStructWorker worker(module, mode_fwd, mode_icells); EquivStructWorker worker(module, mode_fwd, mode_icells);
if (worker.merge_count == 0) if (worker.merge_count == 0)
break; break;
module_merge_count += worker.merge_count;
} }
if (module_merge_count)
log(" Performed a total of %d merges in module %s.\n", module_merge_count, log_id(module));
} }
} }
} EquivStructPass; } EquivStructPass;