Added the obvious optimizations to alumacc $macc generator
authorClifford Wolf <clifford@clifford.at>
Mon, 15 Sep 2014 10:22:03 +0000 (12:22 +0200)
committerClifford Wolf <clifford@clifford.at>
Mon, 15 Sep 2014 10:22:03 +0000 (12:22 +0200)
kernel/macc.h
passes/techmap/alumacc.cc

index 362acab2995be1d400c4b054fb027e1acdfe6114..271141112f265d65b25a3b4944f4e8d4291cd7f5 100644 (file)
@@ -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");
index 3fddcef13f05ab8b254462470bfa9632216cb4bd..c52e0e4cac02e15d512c3315579e78bc2c2a3851 100644 (file)
@@ -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();