2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2019 whitequark <whitequark@whitequark.org>
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/register.h"
21 #include "kernel/sigtools.h"
22 #include "kernel/log.h"
27 PRIVATE_NAMESPACE_BEGIN
31 RTLIL::Module
*module
;
34 int removed_count
= 0, promoted_count
= 0;
36 PruneWorker(RTLIL::Module
*mod
) : module(mod
), sigmap(mod
) {}
38 pool
<RTLIL::SigBit
> do_switch(RTLIL::SwitchRule
*sw
, pool
<RTLIL::SigBit
> assigned
, pool
<RTLIL::SigBit
> &affected
)
40 pool
<RTLIL::SigBit
> all_assigned
;
41 bool full_case
= sw
->get_bool_attribute(ID::full_case
);
43 for (auto it
: sw
->cases
) {
44 if (it
->compare
.empty())
46 pool
<RTLIL::SigBit
> case_assigned
= do_case(it
, assigned
, affected
);
49 all_assigned
= case_assigned
;
51 for (auto &bit
: all_assigned
)
52 if (!case_assigned
[bit
])
53 all_assigned
.erase(bit
);
57 assigned
.insert(all_assigned
.begin(), all_assigned
.end());
61 pool
<RTLIL::SigBit
> do_case(RTLIL::CaseRule
*cs
, pool
<RTLIL::SigBit
> assigned
, pool
<RTLIL::SigBit
> &affected
,
64 for (auto it
= cs
->switches
.rbegin(); it
!= cs
->switches
.rend(); ++it
) {
65 pool
<RTLIL::SigBit
> sw_assigned
= do_switch((*it
), assigned
, affected
);
66 assigned
.insert(sw_assigned
.begin(), sw_assigned
.end());
68 for (auto it
= cs
->actions
.rbegin(); it
!= cs
->actions
.rend(); ) {
69 RTLIL::SigSpec lhs
= sigmap(it
->first
);
70 RTLIL::SigSpec rhs
= sigmap(it
->second
);
71 SigSpec new_lhs
, new_rhs
;
72 SigSpec conn_lhs
, conn_rhs
;
73 for (int i
= 0; i
< GetSize(lhs
); i
++) {
75 if (bit
.wire
&& !assigned
[bit
]) {
76 if (!affected
[bit
] && root
) {
78 conn_rhs
.append(rhs
[i
]);
81 new_rhs
.append(rhs
[i
]);
87 if (GetSize(conn_lhs
)) {
89 module
->connect(conn_lhs
, conn_rhs
);
91 if (GetSize(new_lhs
) == 0) {
92 if (GetSize(conn_lhs
) == 0)
94 cs
->actions
.erase((it
++).base() - 1);
104 void do_process(RTLIL::Process
*pr
)
106 pool
<RTLIL::SigBit
> affected
;
107 do_case(&pr
->root_case
, {}, affected
, /*root=*/true);
111 struct ProcPrunePass
: public Pass
{
112 ProcPrunePass() : Pass("proc_prune", "remove redundant assignments") { }
115 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
117 log(" proc_prune [selection]\n");
119 log("This pass identifies assignments in processes that are always overwritten by\n");
120 log("a later assignment to the same signal and removes them.\n");
123 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) override
125 int total_removed_count
= 0, total_promoted_count
= 0;
126 log_header(design
, "Executing PROC_PRUNE pass (remove redundant assignments in processes).\n");
128 extra_args(args
, 1, design
);
130 for (auto mod
: design
->modules()) {
131 if (!design
->selected(mod
))
133 PruneWorker
worker(mod
);
134 for (auto &proc_it
: mod
->processes
) {
135 if (!design
->selected(mod
, proc_it
.second
))
137 worker
.do_process(proc_it
.second
);
139 total_removed_count
+= worker
.removed_count
;
140 total_promoted_count
+= worker
.promoted_count
;
143 log("Removed %d redundant assignment%s.\n",
144 total_removed_count
, total_removed_count
== 1 ? "" : "s");
145 log("Promoted %d assignment%s to connection%s.\n",
146 total_promoted_count
, total_promoted_count
== 1 ? "" : "s", total_promoted_count
== 1 ? "" : "s");
150 PRIVATE_NAMESPACE_END