More "freduce" related fixes and improvements

This commit is contained in:
Clifford Wolf 2014-01-02 19:37:34 +01:00
parent ced4d7b321
commit 0759c97748
1 changed files with 67 additions and 19 deletions

View File

@ -38,6 +38,7 @@ struct equiv_bit_t
{ {
int depth; int depth;
bool inverted; bool inverted;
RTLIL::Cell *drv;
RTLIL::SigBit bit; RTLIL::SigBit bit;
bool operator<(const equiv_bit_t &other) const { bool operator<(const equiv_bit_t &other) const {
@ -45,6 +46,8 @@ struct equiv_bit_t
return depth < other.depth; return depth < other.depth;
if (inverted != other.inverted) if (inverted != other.inverted)
return inverted < other.inverted; return inverted < other.inverted;
if (drv != other.drv)
return drv < other.drv;
return bit < other.bit; return bit < other.bit;
} }
}; };
@ -216,7 +219,7 @@ struct PerformReduction
out_inverted = std::vector<bool>(sat_out.size(), false); out_inverted = std::vector<bool>(sat_out.size(), false);
} }
void analyze(std::vector<std::vector<equiv_bit_t>> &results, std::vector<int> &bucket, int level) void analyze(std::vector<std::set<int>> &results, std::map<int, int> &results_map, std::vector<int> &bucket, int level)
{ {
if (bucket.size() <= 1) if (bucket.size() <= 1)
return; return;
@ -233,10 +236,9 @@ struct PerformReduction
std::vector<int> modelVars = sat_out; std::vector<int> modelVars = sat_out;
std::vector<bool> model; std::vector<bool> model;
if (verbose_level >= 2) { modelVars.insert(modelVars.end(), sat_def.begin(), sat_def.end());
modelVars.insert(modelVars.end(), sat_def.begin(), sat_def.end()); if (verbose_level >= 2)
modelVars.insert(modelVars.end(), sat_pi.begin(), sat_pi.end()); modelVars.insert(modelVars.end(), sat_pi.begin(), sat_pi.end());
}
if (ez.solve(modelVars, model, ez.expression(ezSAT::OpOr, sat_list), ez.expression(ezSAT::OpOr, sat_inv_list))) if (ez.solve(modelVars, model, ez.expression(ezSAT::OpOr, sat_list), ez.expression(ezSAT::OpOr, sat_inv_list)))
{ {
@ -248,11 +250,17 @@ struct PerformReduction
out_inverted.at(idx) ? "~" : "", log_signal(out_bits[idx])); out_inverted.at(idx) ? "~" : "", log_signal(out_bits[idx]));
} }
std::vector<int> buckets[2]; std::vector<int> buckets_a;
for (int idx : bucket) std::vector<int> buckets_b;
buckets[model[idx] ? 1 : 0].push_back(idx);
analyze(results, buckets[0], level+1); for (int idx : bucket) {
analyze(results, buckets[1], level+1); if (!model[sat_out.size() + idx] || model[idx])
buckets_a.push_back(idx);
if (!model[sat_out.size() + idx] || !model[idx])
buckets_b.push_back(idx);
}
analyze(results, results_map, buckets_a, level+1);
analyze(results, results_map, buckets_b, level+1);
} }
else else
{ {
@ -263,16 +271,58 @@ struct PerformReduction
log("\n"); log("\n");
} }
std::vector<equiv_bit_t> result; int result_idx = -1;
for (int idx : bucket) { for (int idx : bucket) {
if (results_map.count(idx) == 0)
continue;
if (result_idx == -1) {
result_idx = results_map.at(idx);
continue;
}
int result_idx2 = results_map.at(idx);
results[result_idx].insert(results[result_idx2].begin(), results[result_idx2].end());
for (int idx2 : results[result_idx2])
results_map[idx2] = result_idx;
results[result_idx2].clear();
}
if (result_idx == -1) {
result_idx = results.size();
results.push_back(std::set<int>());
}
results[result_idx].insert(bucket.begin(), bucket.end());
}
}
void analyze(std::vector<std::vector<equiv_bit_t>> &results)
{
std::vector<int> bucket;
for (size_t i = 0; i < sat_out.size(); i++)
bucket.push_back(i);
std::vector<std::set<int>> results_buf;
std::map<int, int> results_map;
analyze(results_buf, results_map, bucket, 1);
for (auto &r : results_buf)
{
if (r.size() <= 1)
continue;
std::vector<equiv_bit_t> result;
for (int idx : r) {
equiv_bit_t bit; equiv_bit_t bit;
bit.depth = out_depth[idx]; bit.depth = out_depth[idx];
bit.inverted = out_inverted[idx]; bit.inverted = out_inverted[idx];
bit.drv = drivers.count(out_bits[idx]) ? drivers.at(out_bits[idx]).first : NULL;
bit.bit = out_bits[idx]; bit.bit = out_bits[idx];
result.push_back(bit); result.push_back(bit);
} }
std::sort(result.begin(), result.end()); std::sort(result.begin(), result.end());
if (result.front().inverted) if (result.front().inverted)
for (auto &bit : result) for (auto &bit : result)
bit.inverted = !bit.inverted; bit.inverted = !bit.inverted;
@ -287,14 +337,6 @@ struct PerformReduction
results.push_back(result); results.push_back(result);
} }
} }
void analyze(std::vector<std::vector<equiv_bit_t>> &results)
{
std::vector<int> bucket;
for (size_t i = 0; i < sat_out.size(); i++)
bucket.push_back(i);
analyze(results, bucket, 1);
}
}; };
struct FreduceHelper struct FreduceHelper
@ -318,6 +360,9 @@ struct FreduceHelper
ct.setup_stdcells(); ct.setup_stdcells();
std::vector<std::set<RTLIL::SigBit>> batches; std::vector<std::set<RTLIL::SigBit>> batches;
for (auto &it : module->wires)
if (it.second->port_input)
batches.push_back(sigmap(it.second).to_sigbit_set());
for (auto &it : module->cells) { for (auto &it : module->cells) {
if (ct.cell_known(it.second->type)) { if (ct.cell_known(it.second->type)) {
std::set<RTLIL::SigBit> inputs, outputs; std::set<RTLIL::SigBit> inputs, outputs;
@ -426,7 +471,10 @@ struct FreducePass : public Pass {
log("\n"); log("\n");
log("This pass performs functional reduction in the circuit. I.e. if two nodes are\n"); log("This pass performs functional reduction in the circuit. I.e. if two nodes are\n");
log("equivialent, they are merged to one node and one of the redundant drivers is\n"); log("equivialent, they are merged to one node and one of the redundant drivers is\n");
log("removed.\n"); log("unconnected. A subsequent call to 'clean' will remove the redundant drivers.\n");
log("\n");
log("This pass is undef-aware, i.e. it considers don't-care values for detecting\n");
log("equivialent nodes.\n");
log("\n"); log("\n");
log(" -v, -vv\n"); log(" -v, -vv\n");
log(" enable verbose or very verbose output\n"); log(" enable verbose or very verbose output\n");