Merge branch 'master' of https://github.com/YosysHQ/yosys into gowin
[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() 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(RTLIL::SigSpec sig, T data)
157 {
158 for (auto &bit : sig)
159 if (bit.wire != NULL)
160 bits[bit].insert(data);
161 }
162
163 void insert(RTLIL::SigSpec sig, const std::set<T> &data)
164 {
165 for (auto &bit : sig)
166 if (bit.wire != NULL)
167 bits[bit].insert(data.begin(), data.end());
168 }
169
170 void erase(RTLIL::SigSpec sig)
171 {
172 for (auto &bit : sig)
173 if (bit.wire != NULL)
174 bits[bit].clear();
175 }
176
177 void erase(RTLIL::SigSpec sig, T data)
178 {
179 for (auto &bit : sig)
180 if (bit.wire != NULL)
181 bits[bit].erase(data);
182 }
183
184 void erase(RTLIL::SigSpec sig, const std::set<T> &data)
185 {
186 for (auto &bit : sig)
187 if (bit.wire != NULL)
188 bits[bit].erase(data.begin(), data.end());
189 }
190
191 void find(RTLIL::SigSpec sig, std::set<T> &result)
192 {
193 for (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(RTLIL::SigSpec sig, pool<T> &result)
201 {
202 for (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(RTLIL::SigSpec sig)
210 {
211 std::set<T> result;
212 find(sig, result);
213 return result;
214 }
215
216 bool has(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(RTLIL::SigSpec from, 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(RTLIL::SigSpec sig)
291 {
292 for (auto &bit : sig) {
293 RTLIL::SigBit b = database.find(bit);
294 if (b.wire != nullptr)
295 database.promote(bit);
296 }
297 }
298
299 void apply(RTLIL::SigBit &bit) const
300 {
301 bit = database.find(bit);
302 }
303
304 void apply(RTLIL::SigSpec &sig) const
305 {
306 for (auto &bit : sig)
307 apply(bit);
308 }
309
310 RTLIL::SigBit operator()(RTLIL::SigBit bit) const
311 {
312 apply(bit);
313 return bit;
314 }
315
316 RTLIL::SigSpec operator()(RTLIL::SigSpec sig) const
317 {
318 apply(sig);
319 return sig;
320 }
321
322 RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
323 {
324 SigSpec sig(wire);
325 apply(sig);
326 return sig;
327 }
328
329 RTLIL::SigSpec allbits() const
330 {
331 RTLIL::SigSpec sig;
332 for (auto &bit : database)
333 if (bit.wire != nullptr)
334 sig.append(bit);
335 return sig;
336 }
337 };
338
339 YOSYS_NAMESPACE_END
340
341 #endif /* SIGTOOLS_H */