Skip to content

Commit b7bd8a5

Browse files
committed
Make IdString refcounts a hashtable containing only the nonzero refcounts
This saves space and doesn't cost very much since we hardly ever have nonzero refcounts any more. It also allows for IdStrings with negative indexes, which we're going to add.
1 parent dc4f655 commit b7bd8a5

File tree

2 files changed

+33
-21
lines changed

2 files changed

+33
-21
lines changed

kernel/rtlil.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard;
3838
std::vector<char*> RTLIL::IdString::global_id_storage_;
3939
std::unordered_map<std::string_view, int> RTLIL::IdString::global_id_index_;
4040
#ifndef YOSYS_NO_IDS_REFCNT
41-
std::vector<uint32_t> RTLIL::IdString::global_refcount_storage_;
41+
std::unordered_map<int, int> RTLIL::IdString::global_refcount_storage_;
4242
std::vector<int> RTLIL::IdString::global_free_idx_list_;
4343
#endif
4444

@@ -62,7 +62,6 @@ void RTLIL::IdString::prepopulate()
6262
global_id_storage_.reserve(size);
6363
RTLIL::IdString::global_id_storage_.push_back(const_cast<char*>(""));
6464
global_id_index_.reserve(size);
65-
global_refcount_storage_.resize(size, 1);
6665
#define X(N) populate("\\" #N);
6766
#include "kernel/constids.inc"
6867
#undef X
@@ -179,17 +178,20 @@ struct IdStringCollector {
179178
void RTLIL::OwningIdString::collect_garbage()
180179
{
181180
#ifndef YOSYS_NO_IDS_REFCNT
182-
int size = GetSize(global_refcount_storage_);
181+
int size = GetSize(global_id_storage_);
183182
IdStringCollector collector(size);
184183
for (auto &[idx, design] : *RTLIL::Design::get_all_designs()) {
185184
collector.trace(*design);
186185
}
187186
for (int i = static_cast<int>(StaticId::STATIC_ID_END); i < size; ++i) {
188-
if (collector.live[i] || global_refcount_storage_[i] > 0)
187+
if (collector.live[i])
189188
continue;
190189
char *&storage = global_id_storage_.at(i);
191190
if (storage == nullptr)
192191
continue;
192+
if (global_refcount_storage_.find(i) != global_refcount_storage_.end())
193+
continue;
194+
193195
if (yosys_xtrace) {
194196
log("#X# Removed IdString '%s' with index %d.\n", storage, i);
195197
log_backtrace("-X- ", yosys_xtrace-1);

kernel/rtlil.h

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -153,16 +153,18 @@ struct RTLIL::IdString
153153
static std::vector<char*> global_id_storage_;
154154
static std::unordered_map<std::string_view, int> global_id_index_;
155155
#ifndef YOSYS_NO_IDS_REFCNT
156-
// For prepopulated IdStrings, the refcount is meaningless since they
157-
// are never freed even if the refcount is zero. For code efficiency
158-
// we increment the refcount of prepopulated IdStrings like any other string,
159-
// but we never decrement the refcount or check whether it's zero.
160-
// So, make this unsigned because refcounts of preopulated IdStrings may overflow
161-
// and overflow of signed integers is undefined behavior.
162-
static std::vector<uint32_t> global_refcount_storage_;
156+
// All (index, refcount) pairs in this map have refcount > 0.
157+
static std::unordered_map<int, int> global_refcount_storage_;
163158
static std::vector<int> global_free_idx_list_;
164159
#endif
165160

161+
static int refcount(int idx) {
162+
auto it = global_refcount_storage_.find(idx);
163+
if (it == global_refcount_storage_.end())
164+
return 0;
165+
return it->second;
166+
}
167+
166168
static inline void xtrace_db_dump()
167169
{
168170
#ifdef YOSYS_XTRACE_GET_PUT
@@ -171,7 +173,7 @@ struct RTLIL::IdString
171173
if (global_id_storage_.at(idx) == nullptr)
172174
log("#X# DB-DUMP index %d: FREE\n", idx);
173175
else
174-
log("#X# DB-DUMP index %d: '%s' (ref %u)\n", idx, global_id_storage_.at(idx), global_refcount_storage_.at(idx));
176+
log("#X# DB-DUMP index %d: '%s' (ref %u)\n", idx, refcount(idx), refcount);
175177
}
176178
#endif
177179
}
@@ -191,7 +193,7 @@ struct RTLIL::IdString
191193
if (it != global_id_index_.end()) {
192194
#ifdef YOSYS_XTRACE_GET_PUT
193195
if (yosys_xtrace)
194-
log("#X# GET-BY-NAME '%s' (index %d, refcount %u)\n", global_id_storage_.at(it->second), it->second, global_refcount_storage_.at(it->second));
196+
log("#X# GET-BY-NAME '%s' (index %d, refcount %u)\n", global_id_storage_.at(it->second), it->second, refcount(it->second));
195197
#endif
196198
return it->second;
197199
}
@@ -211,7 +213,6 @@ struct RTLIL::IdString
211213
log_assert(global_id_storage_.size() < 0x40000000);
212214
global_free_idx_list_.push_back(global_id_storage_.size());
213215
global_id_storage_.push_back(nullptr);
214-
global_refcount_storage_.push_back(0);
215216
}
216217

217218
int idx = global_free_idx_list_.back();
@@ -234,7 +235,7 @@ struct RTLIL::IdString
234235

235236
#ifdef YOSYS_XTRACE_GET_PUT
236237
if (yosys_xtrace)
237-
log("#X# GET-BY-NAME '%s' (index %d, refcount %u)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
238+
log("#X# GET-BY-NAME '%s' (index %d, refcount %u)\n", global_id_storage_.at(idx), idx, refcount(idx));
238239
#endif
239240

240241
return idx;
@@ -436,11 +437,17 @@ struct RTLIL::OwningIdString : public RTLIL::IdString {
436437
static void get_reference(int idx)
437438
{
438439
#ifndef YOSYS_NO_IDS_REFCNT
439-
global_refcount_storage_[idx]++;
440+
if (idx < static_cast<short>(StaticId::STATIC_ID_END))
441+
return;
442+
auto it = global_refcount_storage_.find(idx);
443+
if (it == global_refcount_storage_.end())
444+
global_refcount_storage_.insert(it, {idx, 1});
445+
else
446+
++it->second;
440447
#endif
441448
#ifdef YOSYS_XTRACE_GET_PUT
442449
if (yosys_xtrace && idx >= static_cast<short>(StaticId::STATIC_ID_END))
443-
log("#X# GET-BY-INDEX '%s' (index %d, refcount %u)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
450+
log("#X# GET-BY-INDEX '%s' (index %d, refcount %u)\n", global_id_storage_.at(idx), idx, refcount(idx));
444451
#endif
445452
}
446453

@@ -452,11 +459,14 @@ struct RTLIL::OwningIdString : public RTLIL::IdString {
452459
if (index_ < static_cast<short>(StaticId::STATIC_ID_END) || !destruct_guard_ok)
453460
return;
454461
#ifdef YOSYS_XTRACE_GET_PUT
455-
if (yosys_xtrace) {
456-
log("#X# PUT '%s' (index %d, refcount %u)\n", global_id_storage_.at(index_), index_, global_refcount_storage_.at(index_));
457-
}
462+
if (yosys_xtrace)
463+
log("#X# PUT '%s' (index %d, refcount %u)\n", global_id_storage_.at(index_), index_, refcount(index_));
458464
#endif
459-
--global_refcount_storage_[index_];
465+
auto it = global_refcount_storage_.find(index_);
466+
log_assert(it != global_refcount_storage_.end() && it->second >= 1);
467+
if (--it->second == 0) {
468+
global_refcount_storage_.erase(it);
469+
}
460470
#endif
461471
}
462472
};

0 commit comments

Comments
 (0)