From 724cead61d07906bf652c2d4b0f18360b6a13a29 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 7 Apr 2015 20:27:10 +0200 Subject: Added "pmuxtree" command --- passes/techmap/pmuxtree.cc | 112 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 passes/techmap/pmuxtree.cc (limited to 'passes/techmap/pmuxtree.cc') diff --git a/passes/techmap/pmuxtree.cc b/passes/techmap/pmuxtree.cc new file mode 100644 index 00000000..87762c0b --- /dev/null +++ b/passes/techmap/pmuxtree.cc @@ -0,0 +1,112 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +static SigSpec or_generator(Module *module, const SigSpec &sig) +{ + switch (GetSize(sig)) + { + case 0: + return State::S0; + case 1: + return sig; + case 2: + return module->Or(NEW_ID, sig[0], sig[1]); + default: + return module->ReduceOr(NEW_ID, sig); + } +} + +static SigSpec recursive_mux_generator(Module *module, const SigSpec &sig_data, const SigSpec &sig_sel, SigSpec &sig_or) +{ + if (GetSize(sig_sel) == 1) { + sig_or.append(sig_sel); + return sig_data; + } + + int left_size = GetSize(sig_sel) / 2; + int right_size = GetSize(sig_sel) - left_size; + int stride = GetSize(sig_data) / GetSize(sig_sel); + + SigSpec left_data = sig_data.extract(0, stride*left_size); + SigSpec right_data = sig_data.extract(stride*left_size, stride*right_size); + + SigSpec left_sel = sig_sel.extract(0, left_size); + SigSpec right_sel = sig_sel.extract(left_size, right_size); + + SigSpec left_or, left_result, right_result; + + left_result = recursive_mux_generator(module, left_data, left_sel, left_or); + right_result = recursive_mux_generator(module, right_data, right_sel, sig_or); + left_or = or_generator(module, left_or); + sig_or.append(left_or); + + return module->Mux(NEW_ID, right_result, left_result, left_or); +} + +struct PmuxtreePass : public Pass { + PmuxtreePass() : Pass("pmuxtree", "transform $pmux cells to trees of $mux cells") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" pmuxtree [options] [selection]\n"); + log("\n"); + log("This pass transforms $pmux cells to a trees of $mux cells.\n"); + log("\n"); + } + virtual void execute(std::vector args, RTLIL::Design *design) + { + log_header("Executing PMUXTREE pass.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + for (auto cell : module->selected_cells()) + { + if (cell->type != "$pmux") + continue; + + SigSpec sig_data = cell->getPort("\\B"); + SigSpec sig_sel = cell->getPort("\\S"); + + if (!cell->getPort("\\A").is_fully_undef()) { + sig_data.append(cell->getPort("\\A")); + SigSpec sig_sel_or = module->ReduceOr(NEW_ID, sig_sel); + sig_sel.append(module->Not(NEW_ID, sig_sel_or)); + } + + SigSpec result, result_or; + result = recursive_mux_generator(module, sig_data, sig_sel, result_or); + module->connect(cell->getPort("\\Y"), result); + module->remove(cell); + } + } +} PmuxtreePass; + +PRIVATE_NAMESPACE_END -- cgit v1.2.3