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> {
bitDef_tSigPool::bitDef_t30 		bitDef_t() : std::pair<RTLIL::Wire*, int>(NULL, 0) { }
bitDef_tSigPool::bitDef_t31 		bitDef_t(const RTLIL::SigBit &bit) : std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset) { }
hashSigPool::bitDef_t32 		unsigned int hash() const { return first->name.hash() + second; }
33 	};
34 
35 	pool<bitDef_t> bits;
36 
clearSigPool37 	void clear()
38 	{
39 		bits.clear();
40 	}
41 
addSigPool42 	void add(const RTLIL::SigSpec &sig)
43 	{
44 		for (auto &bit : sig)
45 			if (bit.wire != NULL)
46 				bits.insert(bit);
47 	}
48 
addSigPool49 	void add(const SigPool &other)
50 	{
51 		for (auto &bit : other.bits)
52 			bits.insert(bit);
53 	}
54 
delSigPool55 	void del(const RTLIL::SigSpec &sig)
56 	{
57 		for (auto &bit : sig)
58 			if (bit.wire != NULL)
59 				bits.erase(bit);
60 	}
61 
delSigPool62 	void del(const SigPool &other)
63 	{
64 		for (auto &bit : other.bits)
65 			bits.erase(bit);
66 	}
67 
expandSigPool68 	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 
extractSigPool78 	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 
removeSigPool87 	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 
checkSigPool96 	bool check(const RTLIL::SigBit &bit) const
97 	{
98 		return bit.wire != NULL && bits.count(bit);
99 	}
100 
check_anySigPool101 	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 
check_allSigPool109 	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 
export_oneSigPool117 	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 
export_allSigPool124 	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 
sizeSigPool132 	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> {
bitDef_tSigSet::bitDef_t144 		bitDef_t() : std::pair<RTLIL::Wire*, int>(NULL, 0) { }
bitDef_tSigSet::bitDef_t145 		bitDef_t(const RTLIL::SigBit &bit) : std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset) { }
hashSigSet::bitDef_t146 		unsigned int hash() const { return first->name.hash() + second; }
147 	};
148 
149 	dict<bitDef_t, std::set<T, Compare>> bits;
150 
clearSigSet151 	void clear()
152 	{
153 		bits.clear();
154 	}
155 
insertSigSet156 	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 
insertSigSet163 	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 
eraseSigSet170 	void erase(const RTLIL::SigSpec& sig)
171 	{
172 		for (const auto &bit : sig)
173 			if (bit.wire != NULL)
174 				bits[bit].clear();
175 	}
176 
eraseSigSet177 	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 
eraseSigSet184 	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 
findSigSet191 	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 
findSigSet200 	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 
findSigSet209 	std::set<T> find(const RTLIL::SigSpec &sig)
210 	{
211 		std::set<T> result;
212 		find(sig, result);
213 		return result;
214 	}
215 
hasSigSet216 	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 
swapSigMap242 	void swap(SigMap &other)
243 	{
244 		database.swap(other.database);
245 	}
246 
clearSigMap247 	void clear()
248 	{
249 		database.clear();
250 	}
251 
setSigMap252 	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 
addSigMap265 	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 
addSigMap290 	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 
addSigMap297 	void add(const RTLIL::SigSpec &sig)
298 	{
299 		for (const auto &bit : sig)
300 			add(bit);
301 	}
302 
addSigMap303 	inline void add(Wire *wire) { return add(RTLIL::SigSpec(wire)); }
304 
applySigMap305 	void apply(RTLIL::SigBit &bit) const
306 	{
307 		bit = database.find(bit);
308 	}
309 
applySigMap310 	void apply(RTLIL::SigSpec &sig) const
311 	{
312 		for (auto &bit : sig)
313 			apply(bit);
314 	}
315 
operatorSigMap316 	RTLIL::SigBit operator()(RTLIL::SigBit bit) const
317 	{
318 		apply(bit);
319 		return bit;
320 	}
321 
operatorSigMap322 	RTLIL::SigSpec operator()(RTLIL::SigSpec sig) const
323 	{
324 		apply(sig);
325 		return sig;
326 	}
327 
operatorSigMap328 	RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
329 	{
330 		SigSpec sig(wire);
331 		apply(sig);
332 		return sig;
333 	}
334 
allbitsSigMap335 	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 */
348