2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
24 PRIVATE_NAMESPACE_BEGIN
26 static SigSpec
or_generator(Module
*module
, const SigSpec
&sig
)
35 return module
->Or(NEW_ID
, sig
[0], sig
[1]);
37 return module
->ReduceOr(NEW_ID
, sig
);
41 static SigSpec
recursive_mux_generator(Module
*module
, const SigSpec
&sig_data
, const SigSpec
&sig_sel
, SigSpec
&sig_or
)
43 if (GetSize(sig_sel
) == 1) {
44 sig_or
.append(sig_sel
);
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
);
52 SigSpec left_data
= sig_data
.extract(0, stride
*left_size
);
53 SigSpec right_data
= sig_data
.extract(stride
*left_size
, stride
*right_size
);
55 SigSpec left_sel
= sig_sel
.extract(0, left_size
);
56 SigSpec right_sel
= sig_sel
.extract(left_size
, right_size
);
58 SigSpec left_or
, left_result
, right_result
;
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
);
65 return module
->Mux(NEW_ID
, right_result
, left_result
, left_or
);
68 struct PmuxtreePass
: public Pass
{
69 PmuxtreePass() : Pass("pmuxtree", "transform $pmux cells to trees of $mux cells") { }
70 void help() YS_OVERRIDE
72 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
74 log(" pmuxtree [selection]\n");
76 log("This pass transforms $pmux cells to trees of $mux cells.\n");
79 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
81 log_header(design
, "Executing PMUXTREE pass.\n");
84 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
87 extra_args(args
, argidx
, design
);
89 for (auto module
: design
->selected_modules())
90 for (auto cell
: module
->selected_cells())
92 if (cell
->type
!= "$pmux")
95 SigSpec sig_data
= cell
->getPort("\\B");
96 SigSpec sig_sel
= cell
->getPort("\\S");
98 if (!cell
->getPort("\\A").is_fully_undef()) {
99 sig_data
.append(cell
->getPort("\\A"));
100 SigSpec sig_sel_or
= module
->ReduceOr(NEW_ID
, sig_sel
);
101 sig_sel
.append(module
->Not(NEW_ID
, sig_sel_or
));
104 SigSpec result
, result_or
;
105 result
= recursive_mux_generator(module
, sig_data
, sig_sel
, result_or
);
106 module
->connect(cell
->getPort("\\Y"), result
);
107 module
->remove(cell
);
112 PRIVATE_NAMESPACE_END