2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
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/bitpattern.h"
22 #include "kernel/log.h"
29 PRIVATE_NAMESPACE_BEGIN
31 static bool can_use_fully_defined_pool(RTLIL::SwitchRule
*sw
)
33 if (!GetSize(sw
->signal
))
36 for (const RTLIL::SigBit
&bit
: sw
->signal
)
40 for (const RTLIL::CaseRule
*cas
: sw
->cases
)
41 for (const RTLIL::SigSpec
&sig
: cas
->compare
)
42 if (!sig
.is_fully_def())
48 // This replicates the necessary parts of BitPatternPool's interface, but rather
49 // than storing remaining patterns, this explicitly stores which fully-defined
50 // constants have already been matched.
51 struct FullyDefinedPool
53 FullyDefinedPool(const RTLIL::SigSpec
&signal
)
54 : max_patterns
{signal
.size() >= 32 ? 0ul : 1ul << signal
.size()}
57 bool take(RTLIL::SigSpec sig
)
59 if (default_reached
|| patterns
.count(sig
))
67 default_reached
= true;
72 return default_reached
||
73 (max_patterns
&& max_patterns
== patterns
.size());
76 pool
<RTLIL::SigSpec
> patterns
;
77 bool default_reached
= false;
81 void proc_rmdead(RTLIL::SwitchRule
*sw
, int &counter
, int &full_case_counter
);
84 static void proc_rmdead_impl(RTLIL::SwitchRule
*sw
, int &counter
, int &full_case_counter
)
86 Pool
pool(sw
->signal
);
88 for (size_t i
= 0; i
< sw
->cases
.size(); i
++)
90 bool is_default
= GetSize(sw
->cases
[i
]->compare
) == 0 && (!pool
.empty() || GetSize(sw
->signal
) == 0);
92 for (size_t j
= 0; j
< sw
->cases
[i
]->compare
.size(); j
++) {
93 RTLIL::SigSpec sig
= sw
->cases
[i
]->compare
[j
];
94 if (!sig
.is_fully_const())
97 sw
->cases
[i
]->compare
.erase(sw
->cases
[i
]->compare
.begin() + (j
--));
101 if (sw
->cases
[i
]->compare
.size() == 0) {
103 sw
->cases
.erase(sw
->cases
.begin() + (i
--));
108 // sw->cases[i]->compare.clear();
111 for (auto switch_it
: sw
->cases
[i
]->switches
)
112 proc_rmdead(switch_it
, counter
, full_case_counter
);
118 if (pool
.empty() && !sw
->get_bool_attribute(ID::full_case
)) {
119 sw
->set_bool_attribute(ID::full_case
);
124 void proc_rmdead(RTLIL::SwitchRule
*sw
, int &counter
, int &full_case_counter
)
126 if (can_use_fully_defined_pool(sw
))
127 proc_rmdead_impl
<FullyDefinedPool
>(sw
, counter
, full_case_counter
);
129 proc_rmdead_impl
<BitPatternPool
>(sw
, counter
, full_case_counter
);
132 struct ProcRmdeadPass
: public Pass
{
133 ProcRmdeadPass() : Pass("proc_rmdead", "eliminate dead trees in decision trees") { }
136 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
138 log(" proc_rmdead [selection]\n");
140 log("This pass identifies unreachable branches in decision trees and removes them.\n");
143 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) override
145 log_header(design
, "Executing PROC_RMDEAD pass (remove dead branches from decision trees).\n");
147 extra_args(args
, 1, design
);
149 int total_counter
= 0;
150 for (auto mod
: design
->modules()) {
151 if (!design
->selected(mod
))
153 for (auto &proc_it
: mod
->processes
) {
154 if (!design
->selected(mod
, proc_it
.second
))
156 int counter
= 0, full_case_counter
= 0;
157 for (auto switch_it
: proc_it
.second
->root_case
.switches
)
158 proc_rmdead(switch_it
, counter
, full_case_counter
);
160 log("Removed %d dead cases from process %s in module %s.\n", counter
,
161 log_id(proc_it
.first
), log_id(mod
));
162 if (full_case_counter
> 0)
163 log("Marked %d switch rules as full_case in process %s in module %s.\n",
164 full_case_counter
, log_id(proc_it
.first
), log_id(mod
));
165 total_counter
+= counter
;
169 log("Removed a total of %d dead cases.\n", total_counter
);
173 PRIVATE_NAMESPACE_END