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 bool redundant
= true;
71 for (auto &bit
: lhs
) {
72 if (bit
.wire
&& !assigned
[bit
]) {
83 bool promotable
= true;
84 for (auto &bit
: lhs
) {
85 if (bit
.wire
&& affected
[bit
] && !assigned
[bit
]) {
91 RTLIL::SigSpec rhs
= sigmap(it
->second
);
93 for (int i
= 0; i
< GetSize(lhs
); i
++) {
94 RTLIL::SigBit lhs_bit
= lhs
[i
];
95 if (lhs_bit
.wire
&& !assigned
[lhs_bit
]) {
96 conn
.first
.append(lhs_bit
);
97 conn
.second
.append(rhs
.extract(i
));
101 module
->connect(conn
);
105 for (auto &bit
: lhs
)
107 assigned
.insert(bit
);
108 for (auto &bit
: lhs
)
110 affected
.insert(bit
);
113 cs
->actions
.erase((it
++).base() - 1);
119 void do_process(RTLIL::Process
*pr
)
121 pool
<RTLIL::SigBit
> affected
;
122 do_case(&pr
->root_case
, {}, affected
, /*root=*/true);
126 struct ProcPrunePass
: public Pass
{
127 ProcPrunePass() : Pass("proc_prune", "remove redundant assignments") { }
130 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
132 log(" proc_prune [selection]\n");
134 log("This pass identifies assignments in processes that are always overwritten by\n");
135 log("a later assignment to the same signal and removes them.\n");
138 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) override
140 int total_removed_count
= 0, total_promoted_count
= 0;
141 log_header(design
, "Executing PROC_PRUNE pass (remove redundant assignments in processes).\n");
143 extra_args(args
, 1, design
);
145 for (auto mod
: design
->modules()) {
146 if (!design
->selected(mod
))
148 PruneWorker
worker(mod
);
149 for (auto &proc_it
: mod
->processes
) {
150 if (!design
->selected(mod
, proc_it
.second
))
152 worker
.do_process(proc_it
.second
);
154 total_removed_count
+= worker
.removed_count
;
155 total_promoted_count
+= worker
.promoted_count
;
158 log("Removed %d redundant assignment%s.\n",
159 total_removed_count
, total_removed_count
== 1 ? "" : "s");
160 log("Promoted %d assignment%s to connection%s.\n",
161 total_promoted_count
, total_promoted_count
== 1 ? "" : "s", total_promoted_count
== 1 ? "" : "s");
165 PRIVATE_NAMESPACE_END