summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/macc.h60
-rw-r--r--passes/techmap/alumacc.cc1
2 files changed, 61 insertions, 0 deletions
diff --git a/kernel/macc.h b/kernel/macc.h
index 362acab2..27114111 100644
--- a/kernel/macc.h
+++ b/kernel/macc.h
@@ -34,6 +34,66 @@ struct Macc
std::vector<port_t> ports;
RTLIL::SigSpec bit_ports;
+ void optimize(int width)
+ {
+ std::vector<port_t> new_ports;
+ RTLIL::SigSpec new_bit_ports;
+ RTLIL::Const off(0, width);
+
+ for (auto &port : ports)
+ {
+ if (SIZE(port.in_a) == 0 && SIZE(port.in_b) == 0)
+ continue;
+
+ if (SIZE(port.in_a) == 1 && SIZE(port.in_b) == 0 && !port.is_signed && !port.do_subtract) {
+ bit_ports.append(port.in_a);
+ continue;
+ }
+
+ if (port.in_a.is_fully_const() && port.in_b.is_fully_const()) {
+ RTLIL::Const v = port.in_a.as_const();
+ if (SIZE(port.in_b))
+ v = const_mul(v, port.in_b.as_const(), port.is_signed, port.is_signed, width);
+ if (port.do_subtract)
+ off = const_sub(off, v, port.is_signed, port.is_signed, width);
+ else
+ off = const_add(off, v, port.is_signed, port.is_signed, width);
+ continue;
+ }
+
+ if (port.is_signed) {
+ while (SIZE(port.in_a) > 1 && port.in_a[SIZE(port.in_a)-1] == port.in_a[SIZE(port.in_a)-2])
+ port.in_a.remove(SIZE(port.in_a)-1);
+ while (SIZE(port.in_b) > 1 && port.in_b[SIZE(port.in_b)-1] == port.in_b[SIZE(port.in_b)-2])
+ port.in_b.remove(SIZE(port.in_b)-1);
+ } else {
+ while (SIZE(port.in_a) > 1 && port.in_a[SIZE(port.in_a)-1] == RTLIL::S0)
+ port.in_a.remove(SIZE(port.in_a)-1);
+ while (SIZE(port.in_b) > 1 && port.in_b[SIZE(port.in_b)-1] == RTLIL::S0)
+ port.in_b.remove(SIZE(port.in_b)-1);
+ }
+
+ new_ports.push_back(port);
+ }
+
+ for (auto &bit : bit_ports)
+ if (bit == RTLIL::S1)
+ off = const_add(off, RTLIL::Const(1, width), false, false, width);
+ else if (bit != RTLIL::S0)
+ new_bit_ports.append(bit);
+
+ if (off.as_bool()) {
+ port_t port;
+ port.in_a = off;
+ port.is_signed = false;
+ port.do_subtract = false;
+ new_ports.push_back(port);
+ }
+
+ new_ports.swap(ports);
+ bit_ports = new_bit_ports;
+ }
+
void from_cell(RTLIL::Cell *cell)
{
RTLIL::SigSpec port_a = cell->getPort("\\A");
diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc
index 3fddcef1..c52e0e4c 100644
--- a/passes/techmap/alumacc.cc
+++ b/passes/techmap/alumacc.cc
@@ -317,6 +317,7 @@ struct AlumaccWorker
log(" creating $macc cell for %s: %s\n", log_id(n->cell), log_id(cell));
+ n->macc.optimize(SIZE(n->y));
n->macc.to_cell(cell);
cell->setPort("\\Y", n->y);
cell->fixup_parameters();