diff options
author | Clifford Wolf <clifford@clifford.at> | 2015-04-07 20:27:10 +0200 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2015-04-07 20:27:10 +0200 |
commit | 724cead61d07906bf652c2d4b0f18360b6a13a29 (patch) | |
tree | 4e717788fdcd64933ea4cb5c91ea4d700cbfbef4 | |
parent | 1f33b2a490cf44ec24de5e085ff2957a680519fb (diff) | |
download | yosys-724cead61d07906bf652c2d4b0f18360b6a13a29.tar.gz yosys-724cead61d07906bf652c2d4b0f18360b6a13a29.tar.bz2 yosys-724cead61d07906bf652c2d4b0f18360b6a13a29.zip |
Added "pmuxtree" command
-rw-r--r-- | passes/techmap/Makefile.inc | 1 | ||||
-rw-r--r-- | passes/techmap/pmuxtree.cc | 112 | ||||
-rw-r--r-- | tests/various/muxcover.ys | 51 |
3 files changed, 164 insertions, 0 deletions
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 4f72ea6bc..a3e429cec 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -12,6 +12,7 @@ OBJS += passes/techmap/extract.o OBJS += passes/techmap/alumacc.o OBJS += passes/techmap/dff2dffe.o OBJS += passes/techmap/dffinit.o +OBJS += passes/techmap/pmuxtree.o OBJS += passes/techmap/muxcover.o endif diff --git a/passes/techmap/pmuxtree.cc b/passes/techmap/pmuxtree.cc new file mode 100644 index 000000000..87762c0bc --- /dev/null +++ b/passes/techmap/pmuxtree.cc @@ -0,0 +1,112 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> + * + * 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<std::string> 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 diff --git a/tests/various/muxcover.ys b/tests/various/muxcover.ys new file mode 100644 index 000000000..7ac460f13 --- /dev/null +++ b/tests/various/muxcover.ys @@ -0,0 +1,51 @@ + +read_verilog -formal <<EOT + module gate (input [2:0] A, B, C, D, X, output reg [2:0] Y); + always @* + (* parallel_case *) + casez (X) + 3'b??1: Y = A; + 3'b?1?: Y = B; + 3'b1??: Y = C; + 3'b000: Y = D; + endcase + endmodule +EOT + + +## Examle usage for "pmuxtree" and "muxcover" + +proc +pmuxtree +techmap +muxcover -mux4 + +splitnets -ports +clean +# show + + +## Equivalence checking + +read_verilog -formal <<EOT + module gold (input [2:0] A, B, C, D, X, output reg [2:0] Y); + always @* + casez (X) + 3'b001: Y = A; + 3'b010: Y = B; + 3'b100: Y = C; + 3'b000: Y = D; + default: Y = 'bx; + endcase + endmodule +EOT + +proc +splitnets -ports +techmap -map +/simcells.v t:$_MUX4_ + +equiv_make gold gate equiv +hierarchy -top equiv +equiv_simple -undef +equiv_status -assert + |