mirror of https://github.com/YosysHQ/yosys.git
hashlib: remove is_new from HasherDJB32, implement hash_top for IdString
This commit is contained in:
parent
8513021e0b
commit
60c1e41557
|
@ -48,14 +48,9 @@ namespace hashlib {
|
||||||
* instead of pointers.
|
* instead of pointers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO describe how comparison hashes are special
|
|
||||||
// TODO draw the line between generic and hash function specific code
|
|
||||||
|
|
||||||
const int hashtable_size_trigger = 2;
|
const int hashtable_size_trigger = 2;
|
||||||
const int hashtable_size_factor = 3;
|
const int hashtable_size_factor = 3;
|
||||||
|
|
||||||
#define DJB2_32
|
|
||||||
|
|
||||||
namespace legacy {
|
namespace legacy {
|
||||||
inline uint32_t mkhash_add(uint32_t a, uint32_t b) {
|
inline uint32_t mkhash_add(uint32_t a, uint32_t b) {
|
||||||
return ((a << 5) + a) + b;
|
return ((a << 5) + a) + b;
|
||||||
|
@ -89,16 +84,11 @@ inline unsigned int mkhash_xorshift(unsigned int a) {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Hasher {
|
class HasherDJB32 {
|
||||||
public:
|
public:
|
||||||
#ifdef DJB2_32
|
|
||||||
using hash_t = uint32_t;
|
using hash_t = uint32_t;
|
||||||
#endif
|
|
||||||
#ifdef DJB2_64
|
|
||||||
using hash_t = uint64_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Hasher() {
|
HasherDJB32() {
|
||||||
// traditionally 5381 is used as starting value for the djb2 hash
|
// traditionally 5381 is used as starting value for the djb2 hash
|
||||||
state = 5381;
|
state = 5381;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +96,7 @@ class Hasher {
|
||||||
fudge = f;
|
fudge = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t state;
|
uint32_t state;
|
||||||
static uint32_t fudge;
|
static uint32_t fudge;
|
||||||
// The XOR version of DJB2
|
// The XOR version of DJB2
|
||||||
|
@ -142,19 +132,17 @@ class Hasher {
|
||||||
*this = hash_ops<T>::hash_acc(t, *this);
|
*this = hash_ops<T>::hash_acc(t, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void commutative_acc(uint32_t t) {
|
void commutative_acc(hash_t t) {
|
||||||
state ^= t;
|
state ^= t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void force(hash_t new_state) {
|
void force(hash_t new_state) {
|
||||||
state = new_state;
|
state = new_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_new() const {
|
|
||||||
return state == Hasher().state;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using Hasher = HasherDJB32;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct hash_top_ops {
|
struct hash_top_ops {
|
||||||
static inline bool cmp(const T &a, const T &b) {
|
static inline bool cmp(const T &a, const T &b) {
|
||||||
|
|
601
kernel/rtlil.h
601
kernel/rtlil.h
|
@ -76,335 +76,348 @@ namespace RTLIL
|
||||||
struct SyncRule;
|
struct SyncRule;
|
||||||
struct Process;
|
struct Process;
|
||||||
struct Binding;
|
struct Binding;
|
||||||
|
struct IdString;
|
||||||
|
|
||||||
typedef std::pair<SigSpec, SigSpec> SigSig;
|
typedef std::pair<SigSpec, SigSpec> SigSig;
|
||||||
|
};
|
||||||
|
|
||||||
struct IdString
|
struct RTLIL::IdString
|
||||||
|
{
|
||||||
|
#undef YOSYS_XTRACE_GET_PUT
|
||||||
|
#undef YOSYS_SORT_ID_FREE_LIST
|
||||||
|
#undef YOSYS_USE_STICKY_IDS
|
||||||
|
#undef YOSYS_NO_IDS_REFCNT
|
||||||
|
|
||||||
|
// the global id string cache
|
||||||
|
|
||||||
|
static bool destruct_guard_ok; // POD, will be initialized to zero
|
||||||
|
static struct destruct_guard_t {
|
||||||
|
destruct_guard_t() { destruct_guard_ok = true; }
|
||||||
|
~destruct_guard_t() { destruct_guard_ok = false; }
|
||||||
|
} destruct_guard;
|
||||||
|
|
||||||
|
static std::vector<char*> global_id_storage_;
|
||||||
|
static dict<char*, int> global_id_index_;
|
||||||
|
#ifndef YOSYS_NO_IDS_REFCNT
|
||||||
|
static std::vector<int> global_refcount_storage_;
|
||||||
|
static std::vector<int> global_free_idx_list_;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef YOSYS_USE_STICKY_IDS
|
||||||
|
static int last_created_idx_ptr_;
|
||||||
|
static int last_created_idx_[8];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void xtrace_db_dump()
|
||||||
{
|
{
|
||||||
#undef YOSYS_XTRACE_GET_PUT
|
#ifdef YOSYS_XTRACE_GET_PUT
|
||||||
#undef YOSYS_SORT_ID_FREE_LIST
|
for (int idx = 0; idx < GetSize(global_id_storage_); idx++)
|
||||||
#undef YOSYS_USE_STICKY_IDS
|
{
|
||||||
#undef YOSYS_NO_IDS_REFCNT
|
if (global_id_storage_.at(idx) == nullptr)
|
||||||
|
log("#X# DB-DUMP index %d: FREE\n", idx);
|
||||||
// the global id string cache
|
else
|
||||||
|
log("#X# DB-DUMP index %d: '%s' (ref %d)\n", idx, global_id_storage_.at(idx), global_refcount_storage_.at(idx));
|
||||||
static bool destruct_guard_ok; // POD, will be initialized to zero
|
}
|
||||||
static struct destruct_guard_t {
|
|
||||||
destruct_guard_t() { destruct_guard_ok = true; }
|
|
||||||
~destruct_guard_t() { destruct_guard_ok = false; }
|
|
||||||
} destruct_guard;
|
|
||||||
|
|
||||||
static std::vector<char*> global_id_storage_;
|
|
||||||
static dict<char*, int> global_id_index_;
|
|
||||||
#ifndef YOSYS_NO_IDS_REFCNT
|
|
||||||
static std::vector<int> global_refcount_storage_;
|
|
||||||
static std::vector<int> global_free_idx_list_;
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void checkpoint()
|
||||||
|
{
|
||||||
#ifdef YOSYS_USE_STICKY_IDS
|
#ifdef YOSYS_USE_STICKY_IDS
|
||||||
static int last_created_idx_ptr_;
|
last_created_idx_ptr_ = 0;
|
||||||
static int last_created_idx_[8];
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if (last_created_idx_[i])
|
||||||
|
put_reference(last_created_idx_[i]);
|
||||||
|
last_created_idx_[i] = 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef YOSYS_SORT_ID_FREE_LIST
|
||||||
|
std::sort(global_free_idx_list_.begin(), global_free_idx_list_.end(), std::greater<int>());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static inline void xtrace_db_dump()
|
static inline int get_reference(int idx)
|
||||||
{
|
{
|
||||||
#ifdef YOSYS_XTRACE_GET_PUT
|
if (idx) {
|
||||||
for (int idx = 0; idx < GetSize(global_id_storage_); idx++)
|
#ifndef YOSYS_NO_IDS_REFCNT
|
||||||
{
|
global_refcount_storage_[idx]++;
|
||||||
if (global_id_storage_.at(idx) == nullptr)
|
#endif
|
||||||
log("#X# DB-DUMP index %d: FREE\n", idx);
|
#ifdef YOSYS_XTRACE_GET_PUT
|
||||||
else
|
if (yosys_xtrace)
|
||||||
log("#X# DB-DUMP index %d: '%s' (ref %d)\n", idx, global_id_storage_.at(idx), global_refcount_storage_.at(idx));
|
log("#X# GET-BY-INDEX '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
|
||||||
}
|
#endif
|
||||||
#endif
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_reference(const char *p)
|
||||||
|
{
|
||||||
|
log_assert(destruct_guard_ok);
|
||||||
|
|
||||||
|
if (!p[0])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto it = global_id_index_.find((char*)p);
|
||||||
|
if (it != global_id_index_.end()) {
|
||||||
|
#ifndef YOSYS_NO_IDS_REFCNT
|
||||||
|
global_refcount_storage_.at(it->second)++;
|
||||||
|
#endif
|
||||||
|
#ifdef YOSYS_XTRACE_GET_PUT
|
||||||
|
if (yosys_xtrace)
|
||||||
|
log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(it->second), it->second, global_refcount_storage_.at(it->second));
|
||||||
|
#endif
|
||||||
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void checkpoint()
|
log_assert(p[0] == '$' || p[0] == '\\');
|
||||||
{
|
log_assert(p[1] != 0);
|
||||||
#ifdef YOSYS_USE_STICKY_IDS
|
for (const char *c = p; *c; c++)
|
||||||
last_created_idx_ptr_ = 0;
|
if ((unsigned)*c <= (unsigned)' ')
|
||||||
for (int i = 0; i < 8; i++) {
|
log_error("Found control character or space (0x%02x) in string '%s' which is not allowed in RTLIL identifiers\n", *c, p);
|
||||||
if (last_created_idx_[i])
|
|
||||||
put_reference(last_created_idx_[i]);
|
|
||||||
last_created_idx_[i] = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef YOSYS_SORT_ID_FREE_LIST
|
|
||||||
std::sort(global_free_idx_list_.begin(), global_free_idx_list_.end(), std::greater<int>());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int get_reference(int idx)
|
#ifndef YOSYS_NO_IDS_REFCNT
|
||||||
{
|
if (global_free_idx_list_.empty()) {
|
||||||
if (idx) {
|
|
||||||
#ifndef YOSYS_NO_IDS_REFCNT
|
|
||||||
global_refcount_storage_[idx]++;
|
|
||||||
#endif
|
|
||||||
#ifdef YOSYS_XTRACE_GET_PUT
|
|
||||||
if (yosys_xtrace)
|
|
||||||
log("#X# GET-BY-INDEX '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_reference(const char *p)
|
|
||||||
{
|
|
||||||
log_assert(destruct_guard_ok);
|
|
||||||
|
|
||||||
if (!p[0])
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
auto it = global_id_index_.find((char*)p);
|
|
||||||
if (it != global_id_index_.end()) {
|
|
||||||
#ifndef YOSYS_NO_IDS_REFCNT
|
|
||||||
global_refcount_storage_.at(it->second)++;
|
|
||||||
#endif
|
|
||||||
#ifdef YOSYS_XTRACE_GET_PUT
|
|
||||||
if (yosys_xtrace)
|
|
||||||
log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(it->second), it->second, global_refcount_storage_.at(it->second));
|
|
||||||
#endif
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_assert(p[0] == '$' || p[0] == '\\');
|
|
||||||
log_assert(p[1] != 0);
|
|
||||||
for (const char *c = p; *c; c++)
|
|
||||||
if ((unsigned)*c <= (unsigned)' ')
|
|
||||||
log_error("Found control character or space (0x%02x) in string '%s' which is not allowed in RTLIL identifiers\n", *c, p);
|
|
||||||
|
|
||||||
#ifndef YOSYS_NO_IDS_REFCNT
|
|
||||||
if (global_free_idx_list_.empty()) {
|
|
||||||
if (global_id_storage_.empty()) {
|
|
||||||
global_refcount_storage_.push_back(0);
|
|
||||||
global_id_storage_.push_back((char*)"");
|
|
||||||
global_id_index_[global_id_storage_.back()] = 0;
|
|
||||||
}
|
|
||||||
log_assert(global_id_storage_.size() < 0x40000000);
|
|
||||||
global_free_idx_list_.push_back(global_id_storage_.size());
|
|
||||||
global_id_storage_.push_back(nullptr);
|
|
||||||
global_refcount_storage_.push_back(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int idx = global_free_idx_list_.back();
|
|
||||||
global_free_idx_list_.pop_back();
|
|
||||||
global_id_storage_.at(idx) = strdup(p);
|
|
||||||
global_id_index_[global_id_storage_.at(idx)] = idx;
|
|
||||||
global_refcount_storage_.at(idx)++;
|
|
||||||
#else
|
|
||||||
if (global_id_storage_.empty()) {
|
if (global_id_storage_.empty()) {
|
||||||
|
global_refcount_storage_.push_back(0);
|
||||||
global_id_storage_.push_back((char*)"");
|
global_id_storage_.push_back((char*)"");
|
||||||
global_id_index_[global_id_storage_.back()] = 0;
|
global_id_index_[global_id_storage_.back()] = 0;
|
||||||
}
|
}
|
||||||
int idx = global_id_storage_.size();
|
log_assert(global_id_storage_.size() < 0x40000000);
|
||||||
global_id_storage_.push_back(strdup(p));
|
global_free_idx_list_.push_back(global_id_storage_.size());
|
||||||
global_id_index_[global_id_storage_.back()] = idx;
|
global_id_storage_.push_back(nullptr);
|
||||||
#endif
|
global_refcount_storage_.push_back(0);
|
||||||
|
|
||||||
if (yosys_xtrace) {
|
|
||||||
log("#X# New IdString '%s' with index %d.\n", p, idx);
|
|
||||||
log_backtrace("-X- ", yosys_xtrace-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef YOSYS_XTRACE_GET_PUT
|
|
||||||
if (yosys_xtrace)
|
|
||||||
log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef YOSYS_USE_STICKY_IDS
|
|
||||||
// Avoid Create->Delete->Create pattern
|
|
||||||
if (last_created_idx_[last_created_idx_ptr_])
|
|
||||||
put_reference(last_created_idx_[last_created_idx_ptr_]);
|
|
||||||
last_created_idx_[last_created_idx_ptr_] = idx;
|
|
||||||
get_reference(last_created_idx_[last_created_idx_ptr_]);
|
|
||||||
last_created_idx_ptr_ = (last_created_idx_ptr_ + 1) & 7;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return idx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef YOSYS_NO_IDS_REFCNT
|
int idx = global_free_idx_list_.back();
|
||||||
static inline void put_reference(int idx)
|
global_free_idx_list_.pop_back();
|
||||||
{
|
global_id_storage_.at(idx) = strdup(p);
|
||||||
// put_reference() may be called from destructors after the destructor of
|
global_id_index_[global_id_storage_.at(idx)] = idx;
|
||||||
// global_refcount_storage_ has been run. in this case we simply do nothing.
|
global_refcount_storage_.at(idx)++;
|
||||||
if (!destruct_guard_ok || !idx)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#ifdef YOSYS_XTRACE_GET_PUT
|
|
||||||
if (yosys_xtrace) {
|
|
||||||
log("#X# PUT '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int &refcount = global_refcount_storage_[idx];
|
|
||||||
|
|
||||||
if (--refcount > 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
log_assert(refcount == 0);
|
|
||||||
free_reference(idx);
|
|
||||||
}
|
|
||||||
static inline void free_reference(int idx)
|
|
||||||
{
|
|
||||||
if (yosys_xtrace) {
|
|
||||||
log("#X# Removed IdString '%s' with index %d.\n", global_id_storage_.at(idx), idx);
|
|
||||||
log_backtrace("-X- ", yosys_xtrace-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
global_id_index_.erase(global_id_storage_.at(idx));
|
|
||||||
free(global_id_storage_.at(idx));
|
|
||||||
global_id_storage_.at(idx) = nullptr;
|
|
||||||
global_free_idx_list_.push_back(idx);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
static inline void put_reference(int) { }
|
if (global_id_storage_.empty()) {
|
||||||
|
global_id_storage_.push_back((char*)"");
|
||||||
|
global_id_index_[global_id_storage_.back()] = 0;
|
||||||
|
}
|
||||||
|
int idx = global_id_storage_.size();
|
||||||
|
global_id_storage_.push_back(strdup(p));
|
||||||
|
global_id_index_[global_id_storage_.back()] = idx;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// the actual IdString object is just is a single int
|
if (yosys_xtrace) {
|
||||||
|
log("#X# New IdString '%s' with index %d.\n", p, idx);
|
||||||
int index_;
|
log_backtrace("-X- ", yosys_xtrace-1);
|
||||||
|
|
||||||
inline IdString() : index_(0) { }
|
|
||||||
inline IdString(const char *str) : index_(get_reference(str)) { }
|
|
||||||
inline IdString(const IdString &str) : index_(get_reference(str.index_)) { }
|
|
||||||
inline IdString(IdString &&str) : index_(str.index_) { str.index_ = 0; }
|
|
||||||
inline IdString(const std::string &str) : index_(get_reference(str.c_str())) { }
|
|
||||||
inline ~IdString() { put_reference(index_); }
|
|
||||||
|
|
||||||
inline void operator=(const IdString &rhs) {
|
|
||||||
put_reference(index_);
|
|
||||||
index_ = get_reference(rhs.index_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void operator=(const char *rhs) {
|
#ifdef YOSYS_XTRACE_GET_PUT
|
||||||
IdString id(rhs);
|
if (yosys_xtrace)
|
||||||
*this = id;
|
log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef YOSYS_USE_STICKY_IDS
|
||||||
|
// Avoid Create->Delete->Create pattern
|
||||||
|
if (last_created_idx_[last_created_idx_ptr_])
|
||||||
|
put_reference(last_created_idx_[last_created_idx_ptr_]);
|
||||||
|
last_created_idx_[last_created_idx_ptr_] = idx;
|
||||||
|
get_reference(last_created_idx_[last_created_idx_ptr_]);
|
||||||
|
last_created_idx_ptr_ = (last_created_idx_ptr_ + 1) & 7;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef YOSYS_NO_IDS_REFCNT
|
||||||
|
static inline void put_reference(int idx)
|
||||||
|
{
|
||||||
|
// put_reference() may be called from destructors after the destructor of
|
||||||
|
// global_refcount_storage_ has been run. in this case we simply do nothing.
|
||||||
|
if (!destruct_guard_ok || !idx)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef YOSYS_XTRACE_GET_PUT
|
||||||
|
if (yosys_xtrace) {
|
||||||
|
log("#X# PUT '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int &refcount = global_refcount_storage_[idx];
|
||||||
|
|
||||||
|
if (--refcount > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
log_assert(refcount == 0);
|
||||||
|
free_reference(idx);
|
||||||
|
}
|
||||||
|
static inline void free_reference(int idx)
|
||||||
|
{
|
||||||
|
if (yosys_xtrace) {
|
||||||
|
log("#X# Removed IdString '%s' with index %d.\n", global_id_storage_.at(idx), idx);
|
||||||
|
log_backtrace("-X- ", yosys_xtrace-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void operator=(const std::string &rhs) {
|
global_id_index_.erase(global_id_storage_.at(idx));
|
||||||
IdString id(rhs);
|
free(global_id_storage_.at(idx));
|
||||||
*this = id;
|
global_id_storage_.at(idx) = nullptr;
|
||||||
}
|
global_free_idx_list_.push_back(idx);
|
||||||
|
}
|
||||||
inline const char *c_str() const {
|
|
||||||
return global_id_storage_.at(index_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string str() const {
|
|
||||||
return std::string(global_id_storage_.at(index_));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator<(const IdString &rhs) const {
|
|
||||||
return index_ < rhs.index_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator==(const IdString &rhs) const { return index_ == rhs.index_; }
|
|
||||||
inline bool operator!=(const IdString &rhs) const { return index_ != rhs.index_; }
|
|
||||||
|
|
||||||
// The methods below are just convenience functions for better compatibility with std::string.
|
|
||||||
|
|
||||||
bool operator==(const std::string &rhs) const { return c_str() == rhs; }
|
|
||||||
bool operator!=(const std::string &rhs) const { return c_str() != rhs; }
|
|
||||||
|
|
||||||
bool operator==(const char *rhs) const { return strcmp(c_str(), rhs) == 0; }
|
|
||||||
bool operator!=(const char *rhs) const { return strcmp(c_str(), rhs) != 0; }
|
|
||||||
|
|
||||||
char operator[](size_t i) const {
|
|
||||||
const char *p = c_str();
|
|
||||||
#ifndef NDEBUG
|
|
||||||
for (; i != 0; i--, p++)
|
|
||||||
log_assert(*p != 0);
|
|
||||||
return *p;
|
|
||||||
#else
|
#else
|
||||||
return *(p + i);
|
static inline void put_reference(int) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// the actual IdString object is just is a single int
|
||||||
|
|
||||||
|
int index_;
|
||||||
|
|
||||||
|
inline IdString() : index_(0) { }
|
||||||
|
inline IdString(const char *str) : index_(get_reference(str)) { }
|
||||||
|
inline IdString(const IdString &str) : index_(get_reference(str.index_)) { }
|
||||||
|
inline IdString(IdString &&str) : index_(str.index_) { str.index_ = 0; }
|
||||||
|
inline IdString(const std::string &str) : index_(get_reference(str.c_str())) { }
|
||||||
|
inline ~IdString() { put_reference(index_); }
|
||||||
|
|
||||||
|
inline void operator=(const IdString &rhs) {
|
||||||
|
put_reference(index_);
|
||||||
|
index_ = get_reference(rhs.index_);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void operator=(const char *rhs) {
|
||||||
|
IdString id(rhs);
|
||||||
|
*this = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void operator=(const std::string &rhs) {
|
||||||
|
IdString id(rhs);
|
||||||
|
*this = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *c_str() const {
|
||||||
|
return global_id_storage_.at(index_);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string str() const {
|
||||||
|
return std::string(global_id_storage_.at(index_));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator<(const IdString &rhs) const {
|
||||||
|
return index_ < rhs.index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(const IdString &rhs) const { return index_ == rhs.index_; }
|
||||||
|
inline bool operator!=(const IdString &rhs) const { return index_ != rhs.index_; }
|
||||||
|
|
||||||
|
// The methods below are just convenience functions for better compatibility with std::string.
|
||||||
|
|
||||||
|
bool operator==(const std::string &rhs) const { return c_str() == rhs; }
|
||||||
|
bool operator!=(const std::string &rhs) const { return c_str() != rhs; }
|
||||||
|
|
||||||
|
bool operator==(const char *rhs) const { return strcmp(c_str(), rhs) == 0; }
|
||||||
|
bool operator!=(const char *rhs) const { return strcmp(c_str(), rhs) != 0; }
|
||||||
|
|
||||||
|
char operator[](size_t i) const {
|
||||||
|
const char *p = c_str();
|
||||||
|
#ifndef NDEBUG
|
||||||
|
for (; i != 0; i--, p++)
|
||||||
|
log_assert(*p != 0);
|
||||||
|
return *p;
|
||||||
|
#else
|
||||||
|
return *(p + i);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string substr(size_t pos = 0, size_t len = std::string::npos) const {
|
||||||
|
if (len == std::string::npos || len >= strlen(c_str() + pos))
|
||||||
|
return std::string(c_str() + pos);
|
||||||
|
else
|
||||||
|
return std::string(c_str() + pos, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int compare(size_t pos, size_t len, const char* s) const {
|
||||||
|
return strncmp(c_str()+pos, s, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool begins_with(const char* prefix) const {
|
||||||
|
size_t len = strlen(prefix);
|
||||||
|
if (size() < len) return false;
|
||||||
|
return compare(0, len, prefix) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ends_with(const char* suffix) const {
|
||||||
|
size_t len = strlen(suffix);
|
||||||
|
if (size() < len) return false;
|
||||||
|
return compare(size()-len, len, suffix) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const char* str) const {
|
||||||
|
return strstr(c_str(), str);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return strlen(c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const {
|
||||||
|
return c_str()[0] == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
*this = IdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
Hasher hash_acc(Hasher h) const { return hash_ops<int>::hash_acc(index_, h); }
|
||||||
|
|
||||||
|
Hasher hash_top() const {
|
||||||
|
Hasher h;
|
||||||
|
h.force((Hasher::hash_t) index_);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following is a helper key_compare class. Instead of for example std::set<Cell*>
|
||||||
|
// use std::set<Cell*, IdString::compare_ptr_by_name<Cell>> if the order of cells in the
|
||||||
|
// set has an influence on the algorithm.
|
||||||
|
|
||||||
|
template<typename T> struct compare_ptr_by_name {
|
||||||
|
bool operator()(const T *a, const T *b) const {
|
||||||
|
return (a == nullptr || b == nullptr) ? (a < b) : (a->name < b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string substr(size_t pos = 0, size_t len = std::string::npos) const {
|
|
||||||
if (len == std::string::npos || len >= strlen(c_str() + pos))
|
|
||||||
return std::string(c_str() + pos);
|
|
||||||
else
|
|
||||||
return std::string(c_str() + pos, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int compare(size_t pos, size_t len, const char* s) const {
|
|
||||||
return strncmp(c_str()+pos, s, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool begins_with(const char* prefix) const {
|
|
||||||
size_t len = strlen(prefix);
|
|
||||||
if (size() < len) return false;
|
|
||||||
return compare(0, len, prefix) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ends_with(const char* suffix) const {
|
|
||||||
size_t len = strlen(suffix);
|
|
||||||
if (size() < len) return false;
|
|
||||||
return compare(size()-len, len, suffix) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool contains(const char* str) const {
|
|
||||||
return strstr(c_str(), str);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const {
|
|
||||||
return strlen(c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool empty() const {
|
|
||||||
return c_str()[0] == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
*this = IdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
Hasher hash_acc(Hasher h) const {
|
|
||||||
// If we're starting a hashing sequence, simply start with unhashed ID
|
|
||||||
if (h.is_new()) {
|
|
||||||
h.force((Hasher::hash_t) index_);
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash_ops<int>::hash_acc(index_, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The following is a helper key_compare class. Instead of for example std::set<Cell*>
|
|
||||||
// use std::set<Cell*, IdString::compare_ptr_by_name<Cell>> if the order of cells in the
|
|
||||||
// set has an influence on the algorithm.
|
|
||||||
|
|
||||||
template<typename T> struct compare_ptr_by_name {
|
|
||||||
bool operator()(const T *a, const T *b) const {
|
|
||||||
return (a == nullptr || b == nullptr) ? (a < b) : (a->name < b->name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// often one needs to check if a given IdString is part of a list (for example a list
|
|
||||||
// of cell types). the following functions helps with that.
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
bool in(Args... args) const {
|
|
||||||
// Credit: https://articles.emptycrate.com/2016/05/14/folds_in_cpp11_ish.html
|
|
||||||
bool result = false;
|
|
||||||
(void) std::initializer_list<int>{ (result = result || in(args), 0)... };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool in(const IdString &rhs) const { return *this == rhs; }
|
|
||||||
bool in(const char *rhs) const { return *this == rhs; }
|
|
||||||
bool in(const std::string &rhs) const { return *this == rhs; }
|
|
||||||
bool in(const pool<IdString> &rhs) const { return rhs.count(*this) != 0; }
|
|
||||||
|
|
||||||
bool isPublic() const { return begins_with("\\"); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// often one needs to check if a given IdString is part of a list (for example a list
|
||||||
|
// of cell types). the following functions helps with that.
|
||||||
|
template<typename... Args>
|
||||||
|
bool in(Args... args) const {
|
||||||
|
return (... || in(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool in(const IdString &rhs) const { return *this == rhs; }
|
||||||
|
bool in(const char *rhs) const { return *this == rhs; }
|
||||||
|
bool in(const std::string &rhs) const { return *this == rhs; }
|
||||||
|
inline bool in(const pool<IdString> &rhs) const;
|
||||||
|
inline bool in(const pool<IdString> &&rhs) const;
|
||||||
|
|
||||||
|
bool isPublic() const { return begins_with("\\"); }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace hashlib {
|
||||||
|
template <>
|
||||||
|
struct hash_top_ops<RTLIL::IdString> {
|
||||||
|
static inline bool cmp(const RTLIL::IdString &a, const RTLIL::IdString &b) {
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
static inline Hasher hash(const RTLIL::IdString id) {
|
||||||
|
return id.hash_top();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO deprecate this
|
||||||
|
inline bool RTLIL::IdString::in(const pool<IdString> &rhs) const { return rhs.count(*this) != 0; }
|
||||||
|
inline bool RTLIL::IdString::in(const pool<IdString> &&rhs) const { return rhs.count(*this) != 0; }
|
||||||
|
|
||||||
|
namespace RTLIL {
|
||||||
namespace ID {
|
namespace ID {
|
||||||
#define X(_id) extern IdString _id;
|
#define X(_id) extern IdString _id;
|
||||||
#include "kernel/constids.inc"
|
#include "kernel/constids.inc"
|
||||||
#undef X
|
#undef X
|
||||||
};
|
};
|
||||||
|
|
||||||
extern dict<std::string, std::string> constpad;
|
extern dict<std::string, std::string> constpad;
|
||||||
|
|
||||||
const pool<IdString> &builtin_ff_cell_types();
|
const pool<IdString> &builtin_ff_cell_types();
|
||||||
|
|
Loading…
Reference in New Issue