mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Replaced std::unordered_set (nodict) with Yosys::pool
This commit is contained in:
		
							parent
							
								
									9e6fb0b02c
								
							
						
					
					
						commit
						ec4751e55c
					
				
					 8 changed files with 394 additions and 137 deletions
				
			
		
							
								
								
									
										352
									
								
								kernel/hashmap.h
									
										
									
									
									
								
							
							
						
						
									
										352
									
								
								kernel/hashmap.h
									
										
									
									
									
								
							|  | @ -57,6 +57,21 @@ template<> struct hash_ops<std::string> { | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct hash_cstr_ops { | ||||||
|  | 	bool cmp(const char *a, const char *b) const { | ||||||
|  | 		for (int i = 0; a[i] || b[i]; i++) | ||||||
|  | 			if (a[i] != b[i]) | ||||||
|  | 				return false; | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 	unsigned int hash(const char *a) const { | ||||||
|  | 		size_t hash = 5381; | ||||||
|  | 		while (*a) | ||||||
|  | 			 hash = mkhash(hash, *(a++)); | ||||||
|  | 		 return hash; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct hash_ptr_ops { | struct hash_ptr_ops { | ||||||
| 	bool cmp(const void *a, const void *b) const { | 	bool cmp(const void *a, const void *b) const { | ||||||
| 		return a == b; | 		return a == b; | ||||||
|  | @ -423,4 +438,341 @@ public: | ||||||
| 	const_iterator end() const { return const_iterator(this, entries.size()); } | 	const_iterator end() const { return const_iterator(this, entries.size()); } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | template<typename K, typename OPS = hash_ops<K>> | ||||||
|  | class pool | ||||||
|  | { | ||||||
|  | 	struct entry_t | ||||||
|  | 	{ | ||||||
|  | 		int link; | ||||||
|  | 		K key; | ||||||
|  | 
 | ||||||
|  | 		entry_t() : link(-1) { } | ||||||
|  | 		entry_t(const K &key) : link(1), key(key) { } | ||||||
|  | 
 | ||||||
|  | 		bool is_free() const { return link < 0; } | ||||||
|  | 		int get_next() const { return (link > 0 ? link : -link) - 2; } | ||||||
|  | 		bool get_last() const { return get_next() == -1; } | ||||||
|  | 		void set_next_used(int next) { link = next + 2; } | ||||||
|  | 		void set_next_free(int next) { link = -(next + 2); } | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	std::vector<int> hashtable; | ||||||
|  | 	std::vector<entry_t> entries; | ||||||
|  | 	int free_list, counter; | ||||||
|  | 	OPS ops; | ||||||
|  | 
 | ||||||
|  | 	void init() | ||||||
|  | 	{ | ||||||
|  | 		free_list = -1; | ||||||
|  | 		counter = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void init_from(const pool<K, OPS> &other) | ||||||
|  | 	{ | ||||||
|  | 		hashtable.clear(); | ||||||
|  | 		entries.clear(); | ||||||
|  | 
 | ||||||
|  | 		counter = other.size(); | ||||||
|  | 		int new_size = grow_size(counter); | ||||||
|  | 		entries.reserve(new_size); | ||||||
|  | 
 | ||||||
|  | 		for (auto &it : other) | ||||||
|  | 			entries.push_back(entry_t(it)); | ||||||
|  | 		entries.resize(new_size); | ||||||
|  | 		rehash(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	size_t grow_size(size_t old_size) | ||||||
|  | 	{ | ||||||
|  | 		if (old_size <         53) return         53; | ||||||
|  | 		if (old_size <        113) return        113; | ||||||
|  | 		if (old_size <        251) return        251; | ||||||
|  | 		if (old_size <        503) return        503; | ||||||
|  | 		if (old_size <       1130) return       1130; | ||||||
|  | 		if (old_size <       2510) return       2510; | ||||||
|  | 		if (old_size <       5030) return       5030; | ||||||
|  | 		if (old_size <      11300) return      11300; | ||||||
|  | 		if (old_size <      25100) return      25100; | ||||||
|  | 		if (old_size <      50300) return      50300; | ||||||
|  | 		if (old_size <     113000) return     113000; | ||||||
|  | 		if (old_size <     251000) return     251000; | ||||||
|  | 		if (old_size <     503000) return     503000; | ||||||
|  | 		if (old_size <    1130000) return    1130000; | ||||||
|  | 		if (old_size <    2510000) return    2510000; | ||||||
|  | 		if (old_size <    5030000) return    5030000; | ||||||
|  | 		if (old_size <   11300000) return   11300000; | ||||||
|  | 		if (old_size <   25100000) return   25100000; | ||||||
|  | 		if (old_size <   50300000) return   50300000; | ||||||
|  | 		if (old_size <  113000000) return  113000000; | ||||||
|  | 		if (old_size <  251000000) return  251000000; | ||||||
|  | 		if (old_size <  503000000) return  503000000; | ||||||
|  | 		if (old_size < 1130000000) return 1130000000; | ||||||
|  | 		throw std::length_error("maximum size for pool reached"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int mkhash(const K &key) const | ||||||
|  | 	{ | ||||||
|  | 		unsigned int hash = 0; | ||||||
|  | 		if (!hashtable.empty()) | ||||||
|  | 			hash = ops.hash(key) % (unsigned int)(hashtable.size()); | ||||||
|  | 		return hash; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void rehash() | ||||||
|  | 	{ | ||||||
|  | 		free_list = -1; | ||||||
|  | 
 | ||||||
|  | 		hashtable.resize(entries.size()); | ||||||
|  | 		for (auto &h : hashtable) | ||||||
|  | 			h = -1; | ||||||
|  | 
 | ||||||
|  | 		for (int i = 0; i < int(entries.size()); i++) | ||||||
|  | 			if (entries[i].is_free()) { | ||||||
|  | 				entries[i].set_next_free(free_list); | ||||||
|  | 				free_list = i; | ||||||
|  | 			} else { | ||||||
|  | 				int hash = mkhash(entries[i].key); | ||||||
|  | 				entries[i].set_next_used(hashtable[hash]); | ||||||
|  | 				hashtable[hash] = i; | ||||||
|  | 			} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void do_erase(const K &key, int hash) | ||||||
|  | 	{ | ||||||
|  | 		int last_index = -1; | ||||||
|  | 		int index = hashtable.empty() ? -1 : hashtable[hash]; | ||||||
|  | 		while (1) { | ||||||
|  | 			if (index < 0) | ||||||
|  | 				return; | ||||||
|  | 			if (ops.cmp(entries[index].key, key)) { | ||||||
|  | 				if (last_index < 0) | ||||||
|  | 					hashtable[hash] = entries[index].get_next(); | ||||||
|  | 				else | ||||||
|  | 					entries[last_index].set_next_used(entries[index].get_next()); | ||||||
|  | 				entries[index].key = K(); | ||||||
|  | 				entries[index].set_next_free(free_list); | ||||||
|  | 				free_list = index; | ||||||
|  | 				if (--counter == 0) | ||||||
|  | 					init(); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 			last_index = index; | ||||||
|  | 			index = entries[index].get_next(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int lookup_index(const K &key, int hash) const | ||||||
|  | 	{ | ||||||
|  | 		int index = hashtable.empty() ? -1 : hashtable[hash]; | ||||||
|  | 		while (1) { | ||||||
|  | 			if (index < 0) | ||||||
|  | 				return -1; | ||||||
|  | 			if (ops.cmp(entries[index].key, key)) | ||||||
|  | 				return index; | ||||||
|  | 			index = entries[index].get_next(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int insert_at(const K &key, int hash) | ||||||
|  | 	{ | ||||||
|  | 		if (free_list < 0) | ||||||
|  | 		{ | ||||||
|  | 			int i = entries.size(); | ||||||
|  | 			entries.resize(grow_size(i)); | ||||||
|  | 			entries[i].key = key; | ||||||
|  | 			entries[i].set_next_used(0); | ||||||
|  | 			counter++; | ||||||
|  | 			rehash(); | ||||||
|  | 			return i; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		int i = free_list; | ||||||
|  | 		free_list = entries[i].get_next(); | ||||||
|  | 		entries[i].key = key; | ||||||
|  | 		entries[i].set_next_used(hashtable[hash]); | ||||||
|  | 		hashtable[hash] = i; | ||||||
|  | 		counter++; | ||||||
|  | 		return i; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 	class iterator | ||||||
|  | 	{ | ||||||
|  | 		pool<K, OPS> *ptr; | ||||||
|  | 		int index; | ||||||
|  | 	public: | ||||||
|  | 		iterator() { } | ||||||
|  | 		iterator(pool<K, OPS> *ptr, int index) : ptr(ptr), index(index) { } | ||||||
|  | 		iterator operator++() { do index++; while (index != int(ptr->entries.size()) && ptr->entries[index].is_free()); return *this; } | ||||||
|  | 		iterator operator--() { do index--; while (index != 0 && ptr->entries[index].is_free()); return *this; } | ||||||
|  | 		bool operator==(const iterator &other) const { return index == other.index; } | ||||||
|  | 		bool operator!=(const iterator &other) const { return index != other.index; } | ||||||
|  | 		K &operator*() { return ptr->entries[index].key; } | ||||||
|  | 		K *operator->() { return &ptr->entries[index].key; } | ||||||
|  | 		const K &operator*() const { return ptr->entries[index].key; } | ||||||
|  | 		const K *operator->() const { return &ptr->entries[index].key; } | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	class const_iterator | ||||||
|  | 	{ | ||||||
|  | 		const pool<K, OPS> *ptr; | ||||||
|  | 		int index; | ||||||
|  | 	public: | ||||||
|  | 		const_iterator() { } | ||||||
|  | 		const_iterator(const pool<K, OPS> *ptr, int index) : ptr(ptr), index(index) { } | ||||||
|  | 		const_iterator operator++() { do index++; while (index != int(ptr->entries.size()) && ptr->entries[index].is_free()); return *this; } | ||||||
|  | 		const_iterator operator--() { do index--; while (index != 0 && ptr->entries[index].is_free()); return *this; } | ||||||
|  | 		bool operator==(const const_iterator &other) const { return index == other.index; } | ||||||
|  | 		bool operator!=(const const_iterator &other) const { return index != other.index; } | ||||||
|  | 		const K &operator*() const { return ptr->entries[index].key; } | ||||||
|  | 		const K *operator->() const { return &ptr->entries[index].key; } | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	pool() | ||||||
|  | 	{ | ||||||
|  | 		init(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pool(const pool<K, OPS> &other) | ||||||
|  | 	{ | ||||||
|  | 		init_from(other); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pool(pool<K, OPS> &&other) | ||||||
|  | 	{ | ||||||
|  | 		free_list = -1; | ||||||
|  | 		counter = 0; | ||||||
|  | 		swap(other); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pool<K, OPS> &operator=(const pool<K, OPS> &other) { | ||||||
|  | 		clear(); | ||||||
|  | 		init_from(other); | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pool<K, OPS> &operator=(pool<K, OPS> &&other) { | ||||||
|  | 		clear(); | ||||||
|  | 		swap(other); | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pool(const std::initializer_list<K> &list) | ||||||
|  | 	{ | ||||||
|  | 		init(); | ||||||
|  | 		for (auto &it : list) | ||||||
|  | 			insert(it); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	template<class InputIterator> | ||||||
|  | 	pool(InputIterator first, InputIterator last) | ||||||
|  | 	{ | ||||||
|  | 		init(); | ||||||
|  | 		insert(first, last); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	template<class InputIterator> | ||||||
|  | 	void insert(InputIterator first, InputIterator last) | ||||||
|  | 	{ | ||||||
|  | 		for (; first != last; ++first) | ||||||
|  | 			insert(*first); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	iterator insert(const K &key) | ||||||
|  | 	{ | ||||||
|  | 		int hash = mkhash(key); | ||||||
|  | 		int i = lookup_index(key, hash); | ||||||
|  | 		if (i >= 0) | ||||||
|  | 			return iterator(this, i); | ||||||
|  | 		i = insert_at(key, hash); | ||||||
|  | 		return iterator(this, i); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void erase(const K &key) | ||||||
|  | 	{ | ||||||
|  | 		int hash = mkhash(key); | ||||||
|  | 		do_erase(key, hash); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void erase(const iterator it) | ||||||
|  | 	{ | ||||||
|  | 		int hash = mkhash(it->first); | ||||||
|  | 		do_erase(it->first, hash); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int count(const K &key) const | ||||||
|  | 	{ | ||||||
|  | 		int hash = mkhash(key); | ||||||
|  | 		int i = lookup_index(key, hash); | ||||||
|  | 		return i < 0 ? 0 : 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	iterator find(const K &key) | ||||||
|  | 	{ | ||||||
|  | 		int hash = mkhash(key); | ||||||
|  | 		int i = lookup_index(key, hash); | ||||||
|  | 		if (i < 0) | ||||||
|  | 			return end(); | ||||||
|  | 		return iterator(this, i); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const_iterator find(const K &key) const | ||||||
|  | 	{ | ||||||
|  | 		int hash = mkhash(key); | ||||||
|  | 		int i = lookup_index(key, hash); | ||||||
|  | 		if (i < 0) | ||||||
|  | 			return end(); | ||||||
|  | 		return const_iterator(this, i); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool operator[](const K &key) const | ||||||
|  | 	{ | ||||||
|  | 		int hash = mkhash(key); | ||||||
|  | 		int i = lookup_index(key, hash); | ||||||
|  | 		return i >= 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void swap(pool<K, OPS> &other) | ||||||
|  | 	{ | ||||||
|  | 		hashtable.swap(other.hashtable); | ||||||
|  | 		entries.swap(other.entries); | ||||||
|  | 		std::swap(free_list, other.free_list); | ||||||
|  | 		std::swap(counter, other.counter); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool operator==(const pool<K, OPS> &other) const { | ||||||
|  | 		if (counter != other.counter) | ||||||
|  | 			return false; | ||||||
|  | 		if (counter == 0) | ||||||
|  | 			return true; | ||||||
|  | 		if (entries.size() < other.entries.size()) | ||||||
|  | 			for (auto &it : *this) { | ||||||
|  | 				auto oit = other.find(it.first); | ||||||
|  | 				if (oit == other.end() || oit->second != it.second) | ||||||
|  | 					return false; | ||||||
|  | 			} | ||||||
|  | 		else | ||||||
|  | 			for (auto &oit : other) { | ||||||
|  | 				auto it = find(oit.first); | ||||||
|  | 				if (it == end() || it->second != oit.second) | ||||||
|  | 					return false; | ||||||
|  | 			} | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool operator!=(const pool<K, OPS> &other) const { | ||||||
|  | 		return !(*this == other); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	size_t size() const { return counter; } | ||||||
|  | 	bool empty() const { return counter == 0; } | ||||||
|  | 	void clear() { hashtable.clear(); entries.clear(); init(); } | ||||||
|  | 
 | ||||||
|  | 	iterator begin() { int index = 0; while (index != int(entries.size()) && entries[index].is_free()) index++; return iterator(this, index); } | ||||||
|  | 	iterator end() { return iterator(this, entries.size()); } | ||||||
|  | 
 | ||||||
|  | 	const_iterator begin() const { int index = 0; while (index != int(entries.size()) && entries[index].is_free()) index++; return const_iterator(this, index); } | ||||||
|  | 	const_iterator end() const { return const_iterator(this, entries.size()); } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ YOSYS_NAMESPACE_BEGIN | ||||||
| RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard; | RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard; | ||||||
| std::vector<int> RTLIL::IdString::global_refcount_storage_; | std::vector<int> RTLIL::IdString::global_refcount_storage_; | ||||||
| std::vector<char*> RTLIL::IdString::global_id_storage_; | std::vector<char*> RTLIL::IdString::global_id_storage_; | ||||||
| dict<char*, int, RTLIL::IdString::char_ptr_ops> RTLIL::IdString::global_id_index_; | dict<char*, int, hash_cstr_ops> RTLIL::IdString::global_id_index_; | ||||||
| std::vector<int> RTLIL::IdString::global_free_idx_list_; | std::vector<int> RTLIL::IdString::global_free_idx_list_; | ||||||
| 
 | 
 | ||||||
| RTLIL::Const::Const() | RTLIL::Const::Const() | ||||||
|  | @ -480,7 +480,7 @@ namespace { | ||||||
| 	{ | 	{ | ||||||
| 		RTLIL::Module *module; | 		RTLIL::Module *module; | ||||||
| 		RTLIL::Cell *cell; | 		RTLIL::Cell *cell; | ||||||
| 		nodict<RTLIL::IdString> expected_params, expected_ports; | 		pool<RTLIL::IdString> expected_params, expected_ports; | ||||||
| 
 | 
 | ||||||
| 		InternalCellChecker(RTLIL::Module *module, RTLIL::Cell *cell) : module(module), cell(cell) { } | 		InternalCellChecker(RTLIL::Module *module, RTLIL::Cell *cell) : module(module), cell(cell) { } | ||||||
| 
 | 
 | ||||||
|  | @ -1132,7 +1132,7 @@ namespace { | ||||||
| 	struct DeleteWireWorker | 	struct DeleteWireWorker | ||||||
| 	{ | 	{ | ||||||
| 		RTLIL::Module *module; | 		RTLIL::Module *module; | ||||||
| 		const nodict<RTLIL::Wire*> *wires_p; | 		const pool<RTLIL::Wire*, hash_ptr_ops> *wires_p; | ||||||
| 
 | 
 | ||||||
| 		void operator()(RTLIL::SigSpec &sig) { | 		void operator()(RTLIL::SigSpec &sig) { | ||||||
| 			std::vector<RTLIL::SigChunk> chunks = sig; | 			std::vector<RTLIL::SigChunk> chunks = sig; | ||||||
|  | @ -1146,7 +1146,7 @@ namespace { | ||||||
| 	}; | 	}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RTLIL::Module::remove(const nodict<RTLIL::Wire*> &wires) | void RTLIL::Module::remove(const pool<RTLIL::Wire*, hash_ptr_ops> &wires) | ||||||
| { | { | ||||||
| 	log_assert(refcount_wires_ == 0); | 	log_assert(refcount_wires_ == 0); | ||||||
| 
 | 
 | ||||||
|  | @ -2169,9 +2169,9 @@ RTLIL::SigSpec::SigSpec(std::vector<RTLIL::SigBit> bits) | ||||||
| 	check(); | 	check(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RTLIL::SigSpec::SigSpec(nodict<RTLIL::SigBit> bits) | RTLIL::SigSpec::SigSpec(pool<RTLIL::SigBit> bits) | ||||||
| { | { | ||||||
| 	cover("kernel.rtlil.sigspec.init.nodict_bits"); | 	cover("kernel.rtlil.sigspec.init.pool_bits"); | ||||||
| 
 | 
 | ||||||
| 	width_ = 0; | 	width_ = 0; | ||||||
| 	hash_ = 0; | 	hash_ = 0; | ||||||
|  | @ -2378,22 +2378,22 @@ void RTLIL::SigSpec::remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other | ||||||
| 
 | 
 | ||||||
| void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) | void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) | ||||||
| { | { | ||||||
| 	nodict<RTLIL::SigBit> pattern_bits = pattern.to_sigbit_nodict(); | 	pool<RTLIL::SigBit> pattern_bits = pattern.to_sigbit_nodict(); | ||||||
| 	remove2(pattern_bits, other); | 	remove2(pattern_bits, other); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RTLIL::SigSpec::remove(const nodict<RTLIL::SigBit> &pattern) | void RTLIL::SigSpec::remove(const pool<RTLIL::SigBit> &pattern) | ||||||
| { | { | ||||||
| 	remove2(pattern, NULL); | 	remove2(pattern, NULL); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RTLIL::SigSpec::remove(const nodict<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other) const | void RTLIL::SigSpec::remove(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other) const | ||||||
| { | { | ||||||
| 	RTLIL::SigSpec tmp = *this; | 	RTLIL::SigSpec tmp = *this; | ||||||
| 	tmp.remove2(pattern, other); | 	tmp.remove2(pattern, other); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RTLIL::SigSpec::remove2(const nodict<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other) | void RTLIL::SigSpec::remove2(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other) | ||||||
| { | { | ||||||
| 	if (other) | 	if (other) | ||||||
| 		cover("kernel.rtlil.sigspec.remove_other"); | 		cover("kernel.rtlil.sigspec.remove_other"); | ||||||
|  | @ -2439,11 +2439,11 @@ void RTLIL::SigSpec::remove2(const nodict<RTLIL::SigBit> &pattern, RTLIL::SigSpe | ||||||
| 
 | 
 | ||||||
| RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other) const | RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other) const | ||||||
| { | { | ||||||
| 	nodict<RTLIL::SigBit> pattern_bits = pattern.to_sigbit_nodict(); | 	pool<RTLIL::SigBit> pattern_bits = pattern.to_sigbit_nodict(); | ||||||
| 	return extract(pattern_bits, other); | 	return extract(pattern_bits, other); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RTLIL::SigSpec RTLIL::SigSpec::extract(const nodict<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other) const | RTLIL::SigSpec RTLIL::SigSpec::extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other) const | ||||||
| { | { | ||||||
| 	if (other) | 	if (other) | ||||||
| 		cover("kernel.rtlil.sigspec.extract_other"); | 		cover("kernel.rtlil.sigspec.extract_other"); | ||||||
|  | @ -2943,12 +2943,12 @@ std::set<RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_set() const | ||||||
| 	return sigbits; | 	return sigbits; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| nodict<RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_nodict() const | pool<RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_nodict() const | ||||||
| { | { | ||||||
| 	cover("kernel.rtlil.sigspec.to_sigbit_nodict"); | 	cover("kernel.rtlil.sigspec.to_sigbit_pool"); | ||||||
| 
 | 
 | ||||||
| 	pack(); | 	pack(); | ||||||
| 	nodict<RTLIL::SigBit> sigbits; | 	pool<RTLIL::SigBit> sigbits; | ||||||
| 	for (auto &c : chunks_) | 	for (auto &c : chunks_) | ||||||
| 		for (int i = 0; i < c.width; i++) | 		for (int i = 0; i < c.width; i++) | ||||||
| 			sigbits.insert(RTLIL::SigBit(c, i)); | 			sigbits.insert(RTLIL::SigBit(c, i)); | ||||||
|  |  | ||||||
							
								
								
									
										132
									
								
								kernel/rtlil.h
									
										
									
									
									
								
							
							
						
						
									
										132
									
								
								kernel/rtlil.h
									
										
									
									
									
								
							|  | @ -22,27 +22,6 @@ | ||||||
| #ifndef RTLIL_H | #ifndef RTLIL_H | ||||||
| #define RTLIL_H | #define RTLIL_H | ||||||
| 
 | 
 | ||||||
| namespace std { |  | ||||||
| 	template<> struct hash<Yosys::RTLIL::IdString> { |  | ||||||
| 		size_t operator()(const Yosys::RTLIL::IdString &arg) const; |  | ||||||
| 	}; |  | ||||||
| 	template<> struct equal_to<Yosys::RTLIL::IdString> { |  | ||||||
| 		bool operator()(const Yosys::RTLIL::IdString &lhs, const Yosys::RTLIL::IdString &rhs) const; |  | ||||||
| 	}; |  | ||||||
| 	template<> struct hash<Yosys::RTLIL::SigBit> { |  | ||||||
| 		size_t operator()(const Yosys::RTLIL::SigBit &arg) const; |  | ||||||
| 	}; |  | ||||||
| 	template<> struct equal_to<Yosys::RTLIL::SigBit> { |  | ||||||
| 		bool operator()(const Yosys::RTLIL::SigBit &lhs, const Yosys::RTLIL::SigBit &rhs) const; |  | ||||||
| 	}; |  | ||||||
| 	template<> struct hash<Yosys::RTLIL::SigSpec> { |  | ||||||
| 		size_t operator()(const Yosys::RTLIL::SigSpec &arg) const; |  | ||||||
| 	}; |  | ||||||
| 	template<> struct equal_to<Yosys::RTLIL::SigSpec> { |  | ||||||
| 		bool operator()(const Yosys::RTLIL::SigSpec &lhs, const Yosys::RTLIL::SigSpec &rhs) const; |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| YOSYS_NAMESPACE_BEGIN | YOSYS_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
| namespace RTLIL | namespace RTLIL | ||||||
|  | @ -97,48 +76,6 @@ namespace RTLIL | ||||||
| 	{ | 	{ | ||||||
| 		// the global id string cache
 | 		// the global id string cache
 | ||||||
| 
 | 
 | ||||||
| 		struct char_ptr_cmp { |  | ||||||
| 			bool operator()(const char *a, const char *b) const { |  | ||||||
| 				for (int i = 0; a[i] || b[i]; i++) |  | ||||||
| 					if (a[i] != b[i]) |  | ||||||
| 						return a[i] < b[i]; |  | ||||||
| 				return false; |  | ||||||
| 			} |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		struct char_ptr_hash { |  | ||||||
| 			size_t operator()(const char *a) const { |  | ||||||
| 				size_t hash = 5381; |  | ||||||
| 				for (int c; (c = *a); a++) |  | ||||||
| 					hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ |  | ||||||
| 				return hash; |  | ||||||
| 			} |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		struct char_ptr_eq { |  | ||||||
| 			bool operator()(const char *a, const char *b) const { |  | ||||||
| 				for (int i = 0; a[i] || b[i]; i++) |  | ||||||
| 					if (a[i] != b[i]) |  | ||||||
| 						return false; |  | ||||||
| 				return true; |  | ||||||
| 			} |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		struct char_ptr_ops { |  | ||||||
| 			bool cmp(const char *a, const char *b) const { |  | ||||||
| 				for (int i = 0; a[i] || b[i]; i++) |  | ||||||
| 					if (a[i] != b[i]) |  | ||||||
| 						return false; |  | ||||||
| 				return true; |  | ||||||
| 			} |  | ||||||
| 			unsigned int hash(const char *a) const { |  | ||||||
| 				size_t hash = 5381; |  | ||||||
| 				while (*a) |  | ||||||
| 					hash = mkhash(hash, *(a++)); |  | ||||||
| 				return hash; |  | ||||||
| 			} |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		static struct destruct_guard_t { | 		static struct destruct_guard_t { | ||||||
| 			bool ok; // POD, will be initialized to zero
 | 			bool ok; // POD, will be initialized to zero
 | ||||||
| 			destruct_guard_t() { ok = true; } | 			destruct_guard_t() { ok = true; } | ||||||
|  | @ -147,7 +84,7 @@ namespace RTLIL | ||||||
| 
 | 
 | ||||||
| 		static std::vector<int> global_refcount_storage_; | 		static std::vector<int> global_refcount_storage_; | ||||||
| 		static std::vector<char*> global_id_storage_; | 		static std::vector<char*> global_id_storage_; | ||||||
| 		static dict<char*, int, char_ptr_ops> global_id_index_; | 		static dict<char*, int, hash_cstr_ops> global_id_index_; | ||||||
| 		static std::vector<int> global_free_idx_list_; | 		static std::vector<int> global_free_idx_list_; | ||||||
| 
 | 
 | ||||||
| 		static inline int get_reference(int idx) | 		static inline int get_reference(int idx) | ||||||
|  | @ -282,8 +219,8 @@ namespace RTLIL | ||||||
| 			return index_; | 			return index_; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// The following is a helper key_compare class. Instead of for example nodict<Cell*>
 | 		// The following is a helper key_compare class. Instead of for example pool<Cell*>
 | ||||||
| 		// use nodict<Cell*, IdString::compare_ptr_by_name<Cell>> if the order of cells in the
 | 		// use pool<Cell*, IdString::compare_ptr_by_name<Cell>> if the order of cells in the
 | ||||||
| 		// set has an influence on the algorithm.
 | 		// set has an influence on the algorithm.
 | ||||||
| 
 | 
 | ||||||
| 		template<typename T> struct compare_ptr_by_name { | 		template<typename T> struct compare_ptr_by_name { | ||||||
|  | @ -303,7 +240,7 @@ namespace RTLIL | ||||||
| 		bool in(IdString rhs) { return *this == rhs; } | 		bool in(IdString rhs) { return *this == rhs; } | ||||||
| 		bool in(const char *rhs) { return *this == rhs; } | 		bool in(const char *rhs) { return *this == rhs; } | ||||||
| 		bool in(const std::string &rhs) { return *this == rhs; } | 		bool in(const std::string &rhs) { return *this == rhs; } | ||||||
| 		bool in(const nodict<IdString> &rhs) { return rhs.count(*this) != 0; } | 		bool in(const pool<IdString> &rhs) { return rhs.count(*this) != 0; } | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	static inline std::string escape_id(std::string str) { | 	static inline std::string escape_id(std::string str) { | ||||||
|  | @ -470,8 +407,8 @@ namespace RTLIL | ||||||
| 			return list_p->size(); | 			return list_p->size(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		operator nodict<T>() const { | 		operator pool<T>() const { | ||||||
| 			nodict<T> result; | 			pool<T> result; | ||||||
| 			for (auto &it : *list_p) | 			for (auto &it : *list_p) | ||||||
| 				result.insert(it.second); | 				result.insert(it.second); | ||||||
| 			return result; | 			return result; | ||||||
|  | @ -485,7 +422,7 @@ namespace RTLIL | ||||||
| 			return result; | 			return result; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		nodict<T> to_set() const { return *this; } | 		pool<T> to_set() const { return *this; } | ||||||
| 		std::vector<T> to_vector() const { return *this; } | 		std::vector<T> to_vector() const { return *this; } | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
|  | @ -619,7 +556,7 @@ public: | ||||||
| 	SigSpec(RTLIL::SigBit bit, int width = 1); | 	SigSpec(RTLIL::SigBit bit, int width = 1); | ||||||
| 	SigSpec(std::vector<RTLIL::SigChunk> chunks); | 	SigSpec(std::vector<RTLIL::SigChunk> chunks); | ||||||
| 	SigSpec(std::vector<RTLIL::SigBit> bits); | 	SigSpec(std::vector<RTLIL::SigBit> bits); | ||||||
| 	SigSpec(nodict<RTLIL::SigBit> bits); | 	SigSpec(pool<RTLIL::SigBit> bits); | ||||||
| 	SigSpec(std::set<RTLIL::SigBit> bits); | 	SigSpec(std::set<RTLIL::SigBit> bits); | ||||||
| 	SigSpec(bool bit); | 	SigSpec(bool bit); | ||||||
| 
 | 
 | ||||||
|  | @ -676,15 +613,15 @@ public: | ||||||
| 	void remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) const; | 	void remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) const; | ||||||
| 	void remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other); | 	void remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other); | ||||||
| 
 | 
 | ||||||
| 	void remove(const nodict<RTLIL::SigBit> &pattern); | 	void remove(const pool<RTLIL::SigBit> &pattern); | ||||||
| 	void remove(const nodict<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other) const; | 	void remove(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other) const; | ||||||
| 	void remove2(const nodict<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other); | 	void remove2(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other); | ||||||
| 
 | 
 | ||||||
| 	void remove(int offset, int length = 1); | 	void remove(int offset, int length = 1); | ||||||
| 	void remove_const(); | 	void remove_const(); | ||||||
| 
 | 
 | ||||||
| 	RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const; | 	RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const; | ||||||
| 	RTLIL::SigSpec extract(const nodict<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const; | 	RTLIL::SigSpec extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const; | ||||||
| 	RTLIL::SigSpec extract(int offset, int length = 1) const; | 	RTLIL::SigSpec extract(int offset, int length = 1) const; | ||||||
| 
 | 
 | ||||||
| 	void append(const RTLIL::SigSpec &signal); | 	void append(const RTLIL::SigSpec &signal); | ||||||
|  | @ -717,7 +654,7 @@ public: | ||||||
| 	bool match(std::string pattern) const; | 	bool match(std::string pattern) const; | ||||||
| 
 | 
 | ||||||
| 	std::set<RTLIL::SigBit> to_sigbit_set() const; | 	std::set<RTLIL::SigBit> to_sigbit_set() const; | ||||||
| 	nodict<RTLIL::SigBit> to_sigbit_nodict() const; | 	pool<RTLIL::SigBit> to_sigbit_nodict() const; | ||||||
| 	std::vector<RTLIL::SigBit> to_sigbit_vector() const; | 	std::vector<RTLIL::SigBit> to_sigbit_vector() const; | ||||||
| 	std::map<RTLIL::SigBit, RTLIL::SigBit> to_sigbit_map(const RTLIL::SigSpec &other) const; | 	std::map<RTLIL::SigBit, RTLIL::SigBit> to_sigbit_map(const RTLIL::SigSpec &other) const; | ||||||
| 	dict<RTLIL::SigBit, RTLIL::SigBit> to_sigbit_dict(const RTLIL::SigSpec &other) const; | 	dict<RTLIL::SigBit, RTLIL::SigBit> to_sigbit_dict(const RTLIL::SigSpec &other) const; | ||||||
|  | @ -742,8 +679,8 @@ public: | ||||||
| struct RTLIL::Selection | struct RTLIL::Selection | ||||||
| { | { | ||||||
| 	bool full_selection; | 	bool full_selection; | ||||||
| 	nodict<RTLIL::IdString> selected_modules; | 	pool<RTLIL::IdString> selected_modules; | ||||||
| 	dict<RTLIL::IdString, nodict<RTLIL::IdString>> selected_members; | 	dict<RTLIL::IdString, pool<RTLIL::IdString>> selected_members; | ||||||
| 
 | 
 | ||||||
| 	Selection(bool full = true) : full_selection(full) { } | 	Selection(bool full = true) : full_selection(full) { } | ||||||
| 
 | 
 | ||||||
|  | @ -782,7 +719,7 @@ struct RTLIL::Monitor | ||||||
| 
 | 
 | ||||||
| struct RTLIL::Design | struct RTLIL::Design | ||||||
| { | { | ||||||
| 	nodict<RTLIL::Monitor*> monitors; | 	pool<RTLIL::Monitor*, hash_ptr_ops> monitors; | ||||||
| 	dict<std::string, std::string> scratchpad; | 	dict<std::string, std::string> scratchpad; | ||||||
| 
 | 
 | ||||||
| 	int refcount_modules_; | 	int refcount_modules_; | ||||||
|  | @ -869,7 +806,7 @@ protected: | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
| 	RTLIL::Design *design; | 	RTLIL::Design *design; | ||||||
| 	nodict<RTLIL::Monitor*> monitors; | 	pool<RTLIL::Monitor*, hash_ptr_ops> monitors; | ||||||
| 
 | 
 | ||||||
| 	int refcount_wires_; | 	int refcount_wires_; | ||||||
| 	int refcount_cells_; | 	int refcount_cells_; | ||||||
|  | @ -879,7 +816,7 @@ public: | ||||||
| 	std::vector<RTLIL::SigSig> connections_; | 	std::vector<RTLIL::SigSig> connections_; | ||||||
| 
 | 
 | ||||||
| 	RTLIL::IdString name; | 	RTLIL::IdString name; | ||||||
| 	nodict<RTLIL::IdString> avail_parameters; | 	pool<RTLIL::IdString> avail_parameters; | ||||||
| 	dict<RTLIL::IdString, RTLIL::Memory*> memories; | 	dict<RTLIL::IdString, RTLIL::Memory*> memories; | ||||||
| 	dict<RTLIL::IdString, RTLIL::Process*> processes; | 	dict<RTLIL::IdString, RTLIL::Process*> processes; | ||||||
| 	RTLIL_ATTRIBUTE_MEMBERS | 	RTLIL_ATTRIBUTE_MEMBERS | ||||||
|  | @ -923,7 +860,7 @@ public: | ||||||
| 	RTLIL::ObjRange<RTLIL::Cell*> cells() { return RTLIL::ObjRange<RTLIL::Cell*>(&cells_, &refcount_cells_); } | 	RTLIL::ObjRange<RTLIL::Cell*> cells() { return RTLIL::ObjRange<RTLIL::Cell*>(&cells_, &refcount_cells_); } | ||||||
| 
 | 
 | ||||||
| 	// Removing wires is expensive. If you have to remove wires, remove them all at once.
 | 	// Removing wires is expensive. If you have to remove wires, remove them all at once.
 | ||||||
| 	void remove(const nodict<RTLIL::Wire*> &wires); | 	void remove(const pool<RTLIL::Wire*, hash_ptr_ops> &wires); | ||||||
| 	void remove(RTLIL::Cell *cell); | 	void remove(RTLIL::Cell *cell); | ||||||
| 
 | 
 | ||||||
| 	void rename(RTLIL::Wire *wire, RTLIL::IdString new_name); | 	void rename(RTLIL::Wire *wire, RTLIL::IdString new_name); | ||||||
|  | @ -1313,35 +1250,4 @@ void RTLIL::Process::rewrite_sigspecs(T functor) | ||||||
| 
 | 
 | ||||||
| YOSYS_NAMESPACE_END | YOSYS_NAMESPACE_END | ||||||
| 
 | 
 | ||||||
| inline size_t std::hash<Yosys::RTLIL::IdString>::operator()(const Yosys::RTLIL::IdString &arg) const { |  | ||||||
| 	return arg.index_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| inline bool std::equal_to<Yosys::RTLIL::IdString>::operator()(const Yosys::RTLIL::IdString &lhs, const Yosys::RTLIL::IdString &rhs) const { |  | ||||||
| 	return lhs.index_ == rhs.index_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| inline size_t std::hash<Yosys::RTLIL::SigBit>::operator()(const Yosys::RTLIL::SigBit &arg) const { |  | ||||||
| 	if (arg.wire) { |  | ||||||
| 		size_t hash = arg.wire->name.index_; |  | ||||||
| 		hash = ((hash << 5) + hash) + arg.offset; |  | ||||||
| 		return hash; |  | ||||||
| 	} |  | ||||||
| 	return arg.data; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| inline bool std::equal_to<Yosys::RTLIL::SigBit>::operator()(const Yosys::RTLIL::SigBit &lhs, const Yosys::RTLIL::SigBit &rhs) const { |  | ||||||
| 	if (lhs.wire || rhs.wire) |  | ||||||
| 		return lhs.wire == rhs.wire && lhs.offset == rhs.offset; |  | ||||||
| 	return lhs.data == rhs.data; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| inline size_t std::hash<Yosys::RTLIL::SigSpec>::operator()(const Yosys::RTLIL::SigSpec &arg) const { |  | ||||||
| 	return arg.get_hash(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| inline bool std::equal_to<Yosys::RTLIL::SigSpec>::operator()(const Yosys::RTLIL::SigSpec &lhs, const Yosys::RTLIL::SigSpec &rhs) const { |  | ||||||
| 	return lhs == rhs; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -124,7 +124,6 @@ | ||||||
| 
 | 
 | ||||||
| YOSYS_NAMESPACE_BEGIN | YOSYS_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
| #define nodict std::unordered_set |  | ||||||
| #include "kernel/hashmap.h" | #include "kernel/hashmap.h" | ||||||
| using std::vector; | using std::vector; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -91,10 +91,10 @@ struct DeletePass : public Pass { | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			nodict<RTLIL::Wire*> delete_wires; | 			pool<RTLIL::Wire*, hash_ptr_ops> delete_wires; | ||||||
| 			nodict<RTLIL::Cell*> delete_cells; | 			pool<RTLIL::Cell*, hash_ptr_ops> delete_cells; | ||||||
| 			nodict<RTLIL::IdString> delete_procs; | 			pool<RTLIL::IdString> delete_procs; | ||||||
| 			nodict<RTLIL::IdString> delete_mems; | 			pool<RTLIL::IdString> delete_mems; | ||||||
| 
 | 
 | ||||||
| 			for (auto &it : module->wires_) | 			for (auto &it : module->wires_) | ||||||
| 				if (design->selected(module, it.second)) | 				if (design->selected(module, it.second)) | ||||||
|  |  | ||||||
|  | @ -176,7 +176,7 @@ struct SplitnetsPass : public Pass { | ||||||
| 
 | 
 | ||||||
| 			module->rewrite_sigspecs(worker); | 			module->rewrite_sigspecs(worker); | ||||||
| 
 | 
 | ||||||
| 			nodict<RTLIL::Wire*> delete_wires; | 			pool<RTLIL::Wire*, hash_ptr_ops> delete_wires; | ||||||
| 			for (auto &it : worker.splitmap) | 			for (auto &it : worker.splitmap) | ||||||
| 				delete_wires.insert(it.first); | 				delete_wires.insert(it.first); | ||||||
| 			module->remove(delete_wires); | 			module->remove(delete_wires); | ||||||
|  |  | ||||||
|  | @ -262,7 +262,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	nodict<RTLIL::Wire*> del_wires; | 	pool<RTLIL::Wire*, hash_ptr_ops> del_wires; | ||||||
| 
 | 
 | ||||||
| 	int del_wires_count = 0; | 	int del_wires_count = 0; | ||||||
| 	for (auto wire : maybe_del_wires) | 	for (auto wire : maybe_del_wires) | ||||||
|  |  | ||||||
|  | @ -28,11 +28,11 @@ PRIVATE_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
| struct WreduceConfig | struct WreduceConfig | ||||||
| { | { | ||||||
| 	nodict<IdString> supported_cell_types; | 	pool<IdString> supported_cell_types; | ||||||
| 
 | 
 | ||||||
| 	WreduceConfig() | 	WreduceConfig() | ||||||
| 	{ | 	{ | ||||||
| 		supported_cell_types = nodict<IdString>({ | 		supported_cell_types = pool<IdString>({ | ||||||
| 			"$not", "$pos", "$neg", | 			"$not", "$pos", "$neg", | ||||||
| 			"$and", "$or", "$xor", "$xnor", | 			"$and", "$or", "$xor", "$xnor", | ||||||
| 			"$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", | 			"$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue