diff options
author | Clifford Wolf <clifford@clifford.at> | 2014-09-14 10:45:28 +0200 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2014-09-14 10:45:28 +0200 |
commit | 0b72f0acb13e14d329cf408d22b636d61174eb8e (patch) | |
tree | 35f399892bac002353de9e5a7145b98ab8ee0871 | |
parent | ff157fb74fc1b46408c075a0827adbca1b8c496e (diff) | |
download | yosys-0b72f0acb13e14d329cf408d22b636d61174eb8e.tar.gz yosys-0b72f0acb13e14d329cf408d22b636d61174eb8e.tar.bz2 yosys-0b72f0acb13e14d329cf408d22b636d61174eb8e.zip |
Basic $macc extract in alumacc
-rw-r--r-- | passes/techmap/alumacc.cc | 108 |
1 files changed, 104 insertions, 4 deletions
diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc index 0e2fe4e7f..757dc7cf2 100644 --- a/passes/techmap/alumacc.cc +++ b/passes/techmap/alumacc.cc @@ -18,14 +18,112 @@ */ #include "kernel/yosys.h" +#include "kernel/sigtools.h" #include "kernel/macc.h" struct AlumaccWorker { RTLIL::Module *module; + SigMap sigmap; - AlumaccWorker(RTLIL::Module *module) : module(module) + struct maccnode_t { + Macc macc; + RTLIL::Cell *cell; + RTLIL::SigSpec y; + int users; + }; + + std::map<RTLIL::SigBit, int> bit_users; + std::map<RTLIL::SigSpec, maccnode_t*> sig_macc; + + AlumaccWorker(RTLIL::Module *module) : module(module), sigmap(module) { } + + void count_bit_users() + { + for (auto port : module->ports) + for (auto bit : sigmap(module->wire(port))) + bit_users[bit]++; + + for (auto cell : module->cells()) + for (auto &conn : cell->connections()) + for (auto bit : sigmap(conn.second)) + bit_users[bit]++; + } + + void extract_macc() + { + for (auto cell : module->selected_cells()) + { + if (!cell->type.in("$pos", "$neg", "$add", "$sub", "$mul")) + continue; + + maccnode_t *n = new maccnode_t; + Macc::port_t new_port; + + n->cell = cell; + n->y = sigmap(cell->getPort("\\Y")); + n->users = 0; + + for (auto bit : n->y) + n->users = std::max(n->users, bit_users.at(bit) - 1); + + + if (cell->type.in("$pos", "$neg")) + { + new_port.in_a = sigmap(cell->getPort("\\A")); + new_port.is_signed = cell->getParam("\\A_SIGNED").as_bool(); + new_port.do_subtract = cell->type == "$neg"; + n->macc.ports.push_back(new_port); + } + + if (cell->type.in("$add", "$sub")) + { + new_port.in_a = sigmap(cell->getPort("\\A")); + new_port.is_signed = cell->getParam("\\A_SIGNED").as_bool(); + new_port.do_subtract = false; + n->macc.ports.push_back(new_port); + + new_port.in_a = sigmap(cell->getPort("\\B")); + new_port.is_signed = cell->getParam("\\B_SIGNED").as_bool(); + new_port.do_subtract = cell->type == "$sub"; + n->macc.ports.push_back(new_port); + } + + if (cell->type.in("$mul")) + { + new_port.in_a = sigmap(cell->getPort("\\A")); + new_port.in_b = sigmap(cell->getPort("\\B")); + new_port.is_signed = cell->getParam("\\A_SIGNED").as_bool(); + new_port.do_subtract = false; + n->macc.ports.push_back(new_port); + } + + log_assert(sig_macc.count(n->y) == 0); + sig_macc[n->y] = n; + } + } + + void replace_macc() { + for (auto &it : sig_macc) + { + auto n = it.second; + auto cell = module->addCell(NEW_ID, "$macc"); + n->macc.to_cell(cell); + cell->setPort("\\Y", n->y); + cell->fixup_parameters(); + module->remove(n->cell); + delete n; + } + + sig_macc.clear(); + } + + void run() + { + count_bit_users(); + extract_macc(); + replace_macc(); } }; @@ -55,9 +153,11 @@ struct AlumaccPass : public Pass { } extra_args(args, argidx, design); - for (auto mod : design->selected_modules()) { - AlumaccWorker worker(mod); - } + for (auto mod : design->selected_modules()) + if (!mod->has_processes_warn()) { + AlumaccWorker worker(mod); + worker.run(); + } } } AlumaccPass; |