From b470c480e97fe112810d04a6051d1029ce1e8c29 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 15 Sep 2014 12:22:03 +0200 Subject: [PATCH] Added the obvious optimizations to alumacc $macc generator --- kernel/macc.h | 60 +++++++++++++++++++++++++++++++++++++++ passes/techmap/alumacc.cc | 1 + 2 files changed, 61 insertions(+) diff --git a/kernel/macc.h b/kernel/macc.h index 362acab29..271141112 100644 --- a/kernel/macc.h +++ b/kernel/macc.h @@ -34,6 +34,66 @@ struct Macc std::vector ports; RTLIL::SigSpec bit_ports; + void optimize(int width) + { + std::vector 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 3fddcef13..c52e0e4ca 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(); -- 2.30.2