abc9_ops: still emit delay table even box has no timing
[yosys.git] / passes / techmap / pmuxtree.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
22
23 USING_YOSYS_NAMESPACE
24 PRIVATE_NAMESPACE_BEGIN
25
26 static SigSpec or_generator(Module *module, const SigSpec &sig)
27 {
28 switch (GetSize(sig))
29 {
30 case 0:
31 return State::S0;
32 case 1:
33 return sig;
34 case 2:
35 return module->Or(NEW_ID, sig[0], sig[1]);
36 default:
37 return module->ReduceOr(NEW_ID, sig);
38 }
39 }
40
41 static SigSpec recursive_mux_generator(Module *module, const SigSpec &sig_data, const SigSpec &sig_sel, SigSpec &sig_or)
42 {
43 if (GetSize(sig_sel) == 1) {
44 sig_or.append(sig_sel);
45 return sig_data;
46 }
47
48 int left_size = GetSize(sig_sel) / 2;
49 int right_size = GetSize(sig_sel) - left_size;
50 int stride = GetSize(sig_data) / GetSize(sig_sel);
51
52 SigSpec left_data = sig_data.extract(0, stride*left_size);
53 SigSpec right_data = sig_data.extract(stride*left_size, stride*right_size);
54
55 SigSpec left_sel = sig_sel.extract(0, left_size);
56 SigSpec right_sel = sig_sel.extract(left_size, right_size);
57
58 SigSpec left_or, left_result, right_result;
59
60 left_result = recursive_mux_generator(module, left_data, left_sel, left_or);
61 right_result = recursive_mux_generator(module, right_data, right_sel, sig_or);
62 left_or = or_generator(module, left_or);
63 sig_or.append(left_or);
64
65 return module->Mux(NEW_ID, right_result, left_result, left_or);
66 }
67
68 struct PmuxtreePass : public Pass {
69 PmuxtreePass() : Pass("pmuxtree", "transform $pmux cells to trees of $mux cells") { }
70 void help() YS_OVERRIDE
71 {
72 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
73 log("\n");
74 log(" pmuxtree [selection]\n");
75 log("\n");
76 log("This pass transforms $pmux cells to trees of $mux cells.\n");
77 log("\n");
78 }
79 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
80 {
81 log_header(design, "Executing PMUXTREE pass.\n");
82
83 size_t argidx;
84 for (argidx = 1; argidx < args.size(); argidx++) {
85 break;
86 }
87 extra_args(args, argidx, design);
88
89 for (auto module : design->selected_modules())
90 for (auto cell : module->selected_cells())
91 {
92 if (cell->type != ID($pmux))
93 continue;
94
95 SigSpec sig_data = cell->getPort(ID::B);
96 SigSpec sig_sel = cell->getPort(ID(S));
97
98 if (!cell->getPort(ID::A).is_fully_undef()) {
99 sig_data.append(cell->getPort(ID::A));
100 SigSpec sig_sel_or = module->ReduceOr(NEW_ID, sig_sel);
101 sig_sel.append(module->Not(NEW_ID, sig_sel_or));
102 }
103
104 SigSpec result, result_or;
105 result = recursive_mux_generator(module, sig_data, sig_sel, result_or);
106 module->connect(cell->getPort(ID::Y), result);
107 module->remove(cell);
108 }
109 }
110 } PmuxtreePass;
111
112 PRIVATE_NAMESPACE_END