diff options
author | Clifford Wolf <clifford@clifford.at> | 2014-09-15 12:42:11 +0200 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2014-09-15 12:42:11 +0200 |
commit | b86410b2ab902b587cbd8f6b14c13caf684af725 (patch) | |
tree | f1b805290ee68950580670e13d8457e5c3fa536d | |
parent | b470c480e97fe112810d04a6051d1029ce1e8c29 (diff) |
More aggressive $macc merging in alumacc
-rw-r--r-- | passes/techmap/alumacc.cc | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc index c52e0e4c..1115eead 100644 --- a/passes/techmap/alumacc.cc +++ b/passes/techmap/alumacc.cc @@ -172,6 +172,42 @@ struct AlumaccWorker } } + static bool macc_may_overflow(Macc &macc, int width, bool is_signed) + { + std::vector<int> port_sizes; + + for (auto &port : macc.ports) { + if (port.is_signed != is_signed) + return true; + if (!port.is_signed && port.do_subtract) + return true; + if (SIZE(port.in_b)) + port_sizes.push_back(SIZE(port.in_a) + SIZE(port.in_b)); + else + port_sizes.push_back(SIZE(port.in_a)); + } + + std::sort(port_sizes.begin(), port_sizes.end()); + + int acc_sum = 0, acc_shift = 0; + for (int sz : port_sizes) { + while ((sz - acc_shift) > 20) { + if (acc_sum & 1) + acc_sum++; + acc_sum = acc_sum >> 1; + acc_shift++; + } + acc_sum += (1 << (sz - acc_shift)) - 1; + } + + while (acc_sum) { + acc_sum = acc_sum >> 1; + acc_shift++; + } + + return acc_shift > width; + } + void merge_macc() { while (1) @@ -197,7 +233,7 @@ struct AlumaccWorker if (other_n->users > 1) continue; - if (SIZE(other_n->y) != SIZE(n->y)) + if (SIZE(other_n->y) != SIZE(n->y) && macc_may_overflow(other_n->macc, SIZE(other_n->y), port.is_signed)) continue; log(" merging $macc model for %s into %s.\n", log_id(other_n->cell), log_id(n->cell)); |