Change implicit conversions from bool to Sig* to explicit.
[yosys.git] / kernel / sigtools.h
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
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 #ifndef SIGTOOLS_H
21 #define SIGTOOLS_H
22
23 #include "kernel/yosys.h"
24
25 YOSYS_NAMESPACE_BEGIN
26
27 struct SigPool
28 {
29 struct bitDef_t : public std::pair<RTLIL::Wire*, int> {
30 bitDef_t() : std::pair<RTLIL::Wire*, int>(NULL, 0) { }
31 bitDef_t(const RTLIL::SigBit &bit) : std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset) { }
32 unsigned int hash() const { return first->name.hash() + second; }
33 };
34
35 pool<bitDef_t> bits;
36
37 void clear()
38 {
39 bits.clear();
40 }
41
42 void add(const RTLIL::SigSpec &sig)
43 {
44 for (auto &bit : sig)
45 if (bit.wire != NULL)
46 bits.insert(bit);
47 }
48
49 void add(const SigPool &other)
50 {
51 for (auto &bit : other.bits)
52 bits.insert(bit);
53 }
54
55 void del(const RTLIL::SigSpec &sig)
56 {
57 for (auto &bit : sig)
58 if (bit.wire != NULL)
59 bits.erase(bit);
60 }
61
62 void del(const SigPool &other)
63 {
64 for (auto &bit : other.bits)
65 bits.erase(bit);
66 }
67
68 void expand(const RTLIL::SigSpec &from, const RTLIL::SigSpec &to)
69 {
70 log_assert(GetSize(from) == GetSize(to));
71 for (int i = 0; i < GetSize(from); i++) {
72 bitDef_t bit_from(from[i]), bit_to(to[i]);
73 if (bit_from.first != NULL && bit_to.first != NULL && bits.count(bit_from) > 0)
74 bits.insert(bit_to);
75 }
76 }
77
78 RTLIL::SigSpec extract(const RTLIL::SigSpec &sig) const
79 {
80 RTLIL::SigSpec result;
81 for (auto &bit : sig)
82 if (bit.wire != NULL && bits.count(bit))
83 result.append(bit);
84 return result;
85 }
86
87 RTLIL::SigSpec remove(const RTLIL::SigSpec &sig) const
88 {
89 RTLIL::SigSpec result;
90 for (auto &bit : sig)
91 if (bit.wire != NULL && bits.count(bit) == 0)
92 result.append(bit);
93 return result;
94 }
95
96 bool check(const RTLIL::SigBit &bit) const
97 {
98 return bit.wire != NULL && bits.count(bit);
99 }
100
101 bool check_any(const RTLIL::SigSpec &sig) const
102 {
103 for (auto &bit : sig)
104 if (bit.wire != NULL && bits.count(bit))
105 return true;
106 return false;
107 }
108
109 bool check_all(const RTLIL::SigSpec &sig) const
110 {
111 for (auto &bit : sig)
112 if (bit.wire != NULL && bits.count(bit) == 0)
113 return false;
114 return true;
115 }
116
117 RTLIL::SigSpec export_one() const
118 {
119 for (auto &bit : bits)
120 return RTLIL::SigSpec(bit.first, bit.second);
121 return RTLIL::SigSpec();
122 }
123
124 RTLIL::SigSpec export_all() const
125 {
126 pool<RTLIL::SigBit> sig;
127 for (auto &bit : bits)
128 sig.insert(RTLIL::SigBit(bit.first, bit.second));
129 return sig;
130 }
131
132 size_t size() const
133 {
134 return bits.size();
135 }
136 };
137
138 template <typename T, class Compare = void>
139 struct SigSet
140 {
141 static_assert(!std::is_same<Compare,void>::value, "Default value for `Compare' class not found for SigSet<T>. Please specify.");
142
143 struct bitDef_t : public std::pair<RTLIL::Wire*, int> {
144 bitDef_t() : std::pair<RTLIL::Wire*, int>(NULL, 0) { }
145 bitDef_t(const RTLIL::SigBit &bit) : std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset) { }
146 unsigned int hash() const { return first->name.hash() + second; }
147 };
148
149 dict<bitDef_t, std::set<T, Compare>> bits;
150
151 void clear()
152 {
153 bits.clear();
154 }
155
156 void insert(const RTLIL::SigSpec &sig, T data)
157 {
158 for (const auto &bit : sig)
159 if (bit.wire != NULL)
160 bits[bit].insert(data);
161 }
162
163 void insert(const RTLIL::SigSpec& sig, const std::set<T> &data)
164 {
165 for (const auto &bit : sig)
166 if (bit.wire != NULL)
167 bits[bit].insert(data.begin(), data.end());
168 }
169
170 void erase(const RTLIL::SigSpec& sig)
171 {
172 for (const auto &bit : sig)
173 if (bit.wire != NULL)
174 bits[bit].clear();
175 }
176
177 void erase(const RTLIL::SigSpec &sig, T data)
178 {
179 for (const auto &bit : sig)
180 if (bit.wire != NULL)
181 bits[bit].erase(data);
182 }
183
184 void erase(const RTLIL::SigSpec &sig, const std::set<T> &data)
185 {
186 for (const auto &bit : sig)
187 if (bit.wire != NULL)
188 bits[bit].erase(data.begin(), data.end());
189 }
190
191 void find(const RTLIL::SigSpec &sig, std::set<T> &result)
192 {
193 for (const auto &bit : sig)
194 if (bit.wire != NULL) {
195 auto &data = bits[bit];
196 result.insert(data.begin(), data.end());
197 }
198 }
199
200 void find(const RTLIL::SigSpec &sig, pool<T> &result)
201 {
202 for (const auto &bit : sig)
203 if (bit.wire != NULL) {
204 auto &data = bits[bit];
205 result.insert(data.begin(), data.end());
206 }
207 }
208
209 std::set<T> find(const RTLIL::SigSpec &sig)
210 {
211 std::set<T> result;
212 find(sig, result);
213 return result;
214 }
215
216 bool has(const RTLIL::SigSpec &sig)
217 {
218 for (auto &bit : sig)
219 if (bit.wire != NULL && bits.count(bit))
220 return true;
221 return false;
222 }
223 };
224
225 template<typename T>
226 class SigSet<T, typename std::enable_if<!std::is_pointer<T>::value>::type> : public SigSet<T, std::less<T>> {};
227 template<typename T>
228 using sort_by_name_id_guard = typename std::enable_if<std::is_same<T,RTLIL::Cell*>::value>::type;
229 template<typename T>
230 class SigSet<T, sort_by_name_id_guard<T>> : public SigSet<T, RTLIL::sort_by_name_id<typename std::remove_pointer<T>::type>> {};
231
232 struct SigMap
233 {
234 mfp<SigBit> database;
235
236 SigMap(RTLIL::Module *module = NULL)
237 {
238 if (module != NULL)
239 set(module);
240 }
241
242 void swap(SigMap &other)
243 {
244 database.swap(other.database);
245 }
246
247 void clear()
248 {
249 database.clear();
250 }
251
252 void set(RTLIL::Module *module)
253 {
254 int bitcount = 0;
255 for (auto &it : module->connections())
256 bitcount += it.first.size();
257
258 database.clear();
259 database.reserve(bitcount);
260
261 for (auto &it : module->connections())
262 add(it.first, it.second);
263 }
264
265 void add(const RTLIL::SigSpec& from, const RTLIL::SigSpec& to)
266 {
267 log_assert(GetSize(from) == GetSize(to));
268
269 for (int i = 0; i < GetSize(from); i++)
270 {
271 int bfi = database.lookup(from[i]);
272 int bti = database.lookup(to[i]);
273
274 const RTLIL::SigBit &bf = database[bfi];
275 const RTLIL::SigBit &bt = database[bti];
276
277 if (bf.wire || bt.wire)
278 {
279 database.imerge(bfi, bti);
280
281 if (bf.wire == nullptr)
282 database.ipromote(bfi);
283
284 if (bt.wire == nullptr)
285 database.ipromote(bti);
286 }
287 }
288 }
289
290 void add(const RTLIL::SigBit &bit)
291 {
292 const auto &b = database.find(bit);
293 if (b.wire != nullptr)
294 database.promote(bit);
295 }
296
297 void add(const RTLIL::SigSpec &sig)
298 {
299 for (const auto &bit : sig)
300 add(bit);
301 }
302
303 inline void add(Wire *wire) { return add(RTLIL::SigSpec(wire)); }
304
305 void apply(RTLIL::SigBit &bit) const
306 {
307 bit = database.find(bit);
308 }
309
310 void apply(RTLIL::SigSpec &sig) const
311 {
312 for (auto &bit : sig)
313 apply(bit);
314 }
315
316 RTLIL::SigBit operator()(RTLIL::SigBit bit) const
317 {
318 apply(bit);
319 return bit;
320 }
321
322 RTLIL::SigSpec operator()(RTLIL::SigSpec sig) const
323 {
324 apply(sig);
325 return sig;
326 }
327
328 RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
329 {
330 SigSpec sig(wire);
331 apply(sig);
332 return sig;
333 }
334
335 RTLIL::SigSpec allbits() const
336 {
337 RTLIL::SigSpec sig;
338 for (const auto &bit : database)
339 if (bit.wire != nullptr)
340 sig.append(bit);
341 return sig;
342 }
343 };
344
345 YOSYS_NAMESPACE_END
346
347 #endif /* SIGTOOLS_H */