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