Using Yosys::dict and Yosys::pool in sigtools.h
[yosys.git] / kernel / sigtools.h
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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(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(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(RTLIL::SigSpec from, 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(RTLIL::SigSpec sig)
79 {
80 RTLIL::SigSpec result;
81 for (auto &bit : sig)
82 if (bit.wire != NULL && bits.count(bit))
83 result.append_bit(bit);
84 return result;
85 }
86
87 RTLIL::SigSpec remove(RTLIL::SigSpec sig)
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(RTLIL::SigBit bit)
97 {
98 return bit.wire != NULL && bits.count(bit);
99 }
100
101 bool check_any(RTLIL::SigSpec sig)
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(RTLIL::SigSpec sig)
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()
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()
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()
133 {
134 return bits.size();
135 }
136 };
137
138 template <typename T, class Compare = std::less<T>>
139 struct SigSet
140 {
141 struct bitDef_t : public std::pair<RTLIL::Wire*, int> {
142 bitDef_t() : std::pair<RTLIL::Wire*, int>(NULL, 0) { }
143 bitDef_t(const RTLIL::SigBit &bit) : std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset) { }
144 unsigned int hash() const { return first->name.hash() + second; }
145 };
146
147 dict<bitDef_t, std::set<T, Compare>> bits;
148
149 void clear()
150 {
151 bits.clear();
152 }
153
154 void insert(RTLIL::SigSpec sig, T data)
155 {
156 for (auto &bit : sig)
157 if (bit.wire != NULL)
158 bits[bit].insert(data);
159 }
160
161 void insert(RTLIL::SigSpec sig, const std::set<T> &data)
162 {
163 for (auto &bit : sig)
164 if (bit.wire != NULL)
165 bits[bit].insert(data.begin(), data.end());
166 }
167
168 void erase(RTLIL::SigSpec sig)
169 {
170 for (auto &bit : sig)
171 if (bit.wire != NULL)
172 bits[bit].clear();
173 }
174
175 void erase(RTLIL::SigSpec sig, T data)
176 {
177 for (auto &bit : sig)
178 if (bit.wire != NULL)
179 bits[bit].erase(data);
180 }
181
182 void erase(RTLIL::SigSpec sig, const std::set<T> &data)
183 {
184 for (auto &bit : sig)
185 if (bit.wire != NULL)
186 bits[bit].erase(data.begin(), data.end());
187 }
188
189 void find(RTLIL::SigSpec sig, std::set<T> &result)
190 {
191 for (auto &bit : sig)
192 if (bit.wire != NULL) {
193 auto &data = bits[bit];
194 result.insert(data.begin(), data.end());
195 }
196 }
197
198 std::set<T> find(RTLIL::SigSpec sig)
199 {
200 std::set<T> result;
201 find(sig, result);
202 return result;
203 }
204
205 bool has(RTLIL::SigSpec sig)
206 {
207 for (auto &bit : sig)
208 if (bit.wire != NULL && bits.count(bit))
209 return true;
210 return false;
211 }
212 };
213
214 struct SigMap
215 {
216 struct bitDef_t : public std::pair<RTLIL::Wire*, int> {
217 bitDef_t() : std::pair<RTLIL::Wire*, int>(NULL, 0) { }
218 bitDef_t(const RTLIL::SigBit &bit) : std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset) { }
219 unsigned int hash() const { return first->name.hash() + second; }
220 };
221
222 struct shared_bit_data_t {
223 RTLIL::SigBit map_to;
224 std::set<bitDef_t> bits;
225 };
226
227 dict<bitDef_t, shared_bit_data_t*> bits;
228
229 SigMap(RTLIL::Module *module = NULL)
230 {
231 if (module != NULL)
232 set(module);
233 }
234
235 SigMap(const SigMap &other)
236 {
237 copy(other);
238 }
239
240 const SigMap &operator=(const SigMap &other)
241 {
242 copy(other);
243 return *this;
244 }
245
246 void copy(const SigMap &other)
247 {
248 clear();
249 for (auto &bit : other.bits) {
250 bits[bit.first] = new shared_bit_data_t;
251 bits[bit.first]->map_to = bit.second->map_to;
252 bits[bit.first]->bits = bit.second->bits;
253 }
254 }
255
256 void swap(SigMap &other)
257 {
258 bits.swap(other.bits);
259 }
260
261 ~SigMap()
262 {
263 clear();
264 }
265
266 void clear()
267 {
268 std::set<shared_bit_data_t*> all_bd_ptr;
269 for (auto &it : bits)
270 all_bd_ptr.insert(it.second);
271 for (auto bd_ptr : all_bd_ptr)
272 delete bd_ptr;
273 bits.clear();
274 }
275
276 void set(RTLIL::Module *module)
277 {
278 clear();
279 for (auto &it : module->connections())
280 add(it.first, it.second);
281 }
282
283 // internal helper function
284 void register_bit(const RTLIL::SigBit &bit)
285 {
286 if (bit.wire && bits.count(bit) == 0) {
287 shared_bit_data_t *bd = new shared_bit_data_t;
288 bd->map_to = bit;
289 bd->bits.insert(bit);
290 bits[bit] = bd;
291 }
292 }
293
294 // internal helper function
295 void unregister_bit(const RTLIL::SigBit &bit)
296 {
297 if (bit.wire && bits.count(bit) > 0) {
298 shared_bit_data_t *bd = bits[bit];
299 bd->bits.erase(bit);
300 if (bd->bits.size() == 0)
301 delete bd;
302 bits.erase(bit);
303 }
304 }
305
306 // internal helper function
307 void merge_bit(const RTLIL::SigBit &bit1, const RTLIL::SigBit &bit2)
308 {
309 log_assert(bit1.wire != NULL && bit2.wire != NULL);
310
311 shared_bit_data_t *bd1 = bits[bit1];
312 shared_bit_data_t *bd2 = bits[bit2];
313 log_assert(bd1 != NULL && bd2 != NULL);
314
315 if (bd1 == bd2)
316 return;
317
318 if (bd1->bits.size() < bd2->bits.size())
319 {
320 for (auto &bit : bd1->bits)
321 bits[bit] = bd2;
322 bd2->bits.insert(bd1->bits.begin(), bd1->bits.end());
323 delete bd1;
324 }
325 else
326 {
327 bd1->map_to = bd2->map_to;
328 for (auto &bit : bd2->bits)
329 bits[bit] = bd1;
330 bd1->bits.insert(bd2->bits.begin(), bd2->bits.end());
331 delete bd2;
332 }
333 }
334
335 // internal helper function
336 void set_bit(const RTLIL::SigBit &bit1, const RTLIL::SigBit &bit2)
337 {
338 log_assert(bit1.wire != NULL);
339 log_assert(bits.count(bit1) > 0);
340 bits[bit1]->map_to = bit2;
341 }
342
343 // internal helper function
344 void map_bit(RTLIL::SigBit &bit) const
345 {
346 if (bit.wire && bits.count(bit) > 0)
347 bit = bits.at(bit)->map_to;
348 }
349
350 void add(RTLIL::SigSpec from, RTLIL::SigSpec to)
351 {
352 log_assert(GetSize(from) == GetSize(to));
353
354 for (int i = 0; i < GetSize(from); i++)
355 {
356 RTLIL::SigBit &bf = from[i];
357 RTLIL::SigBit &bt = to[i];
358
359 if (bf.wire == NULL)
360 continue;
361
362 register_bit(bf);
363 register_bit(bt);
364
365 if (bt.wire != NULL)
366 merge_bit(bf, bt);
367 else
368 set_bit(bf, bt);
369 }
370 }
371
372 void add(RTLIL::SigSpec sig)
373 {
374 for (auto &bit : sig) {
375 register_bit(bit);
376 set_bit(bit, bit);
377 }
378 }
379
380 void del(RTLIL::SigSpec sig)
381 {
382 for (auto &bit : sig)
383 unregister_bit(bit);
384 }
385
386 void apply(RTLIL::SigBit &bit) const
387 {
388 map_bit(bit);
389 }
390
391 void apply(RTLIL::SigSpec &sig) const
392 {
393 for (auto &bit : sig)
394 map_bit(bit);
395 }
396
397 RTLIL::SigBit operator()(RTLIL::SigBit bit) const
398 {
399 apply(bit);
400 return bit;
401 }
402
403 RTLIL::SigSpec operator()(RTLIL::SigSpec sig) const
404 {
405 apply(sig);
406 return sig;
407 }
408
409 RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
410 {
411 RTLIL::SigSpec sig(wire);
412 apply(sig);
413 return sig;
414 }
415 };
416
417 YOSYS_NAMESPACE_END
418
419 #endif /* SIGTOOLS_H */