3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-24 16:12:33 +00:00
This commit is contained in:
Emil J. Tywoniak 2026-06-10 19:22:53 +02:00
parent 015ab4e45b
commit f592f2f3af
203 changed files with 4575 additions and 4481 deletions

View file

@ -23,6 +23,9 @@ struct TwinePool;
using TwineRef = size_t;
// Tags TwineChildPool-local refs; never set on refs handed out by TwinePool.
constexpr TwineRef TWINE_LOCAL_BIT = TwineRef(1) << 63;
enum : short {
STATIC_TWINE_BEGIN = 0,
#define X(N) IDX_##N,
@ -195,6 +198,68 @@ struct TwinePool {
return ref;
}
size_t size() const { return backing.size(); }
TwineRef concat(std::span<const TwineRef> ids) {
if (ids.size() == 1)
return ids[0];
return add(Twine{std::vector<TwineRef>(ids.begin(), ids.end())});
}
TwineRef copy_from(const TwinePool& src, TwineRef ref) {
if (ref == Twine::Null || ref < STATIC_TWINE_END)
return ref;
const Twine& t = src[ref];
if (t.is_leaf())
return add(Twine{t.leaf()});
if (t.is_concat()) {
std::vector<TwineRef> children;
children.reserve(t.children().size());
for (TwineRef c : t.children())
children.push_back(copy_from(src, c));
return add(Twine{std::move(children)});
}
if (t.is_suffix())
return add(Twine{Twine::Suffix{copy_from(src, t.suffix().prefix), t.suffix().tail}});
return Twine::Null;
}
// linear deep scan; only for rare by-string lookups
TwineRef lookup(std::string_view sv) const;
// Erases every backing node not reachable from `roots`; refs to
// surviving nodes stay valid. Returns the number of erased nodes.
template<typename Pool>
size_t gc(const Pool& roots) {
std::unordered_set<TwineRef> live;
for (TwineRef ref : roots)
mark_live(ref, live);
size_t erased = 0;
for (auto it = backing.begin(); it != backing.end();) {
TwineRef ref = STATIC_TWINE_END + backing.get_index(it);
if (live.count(ref)) {
++it;
} else {
index.erase(ref);
it = backing.erase(it);
erased++;
}
}
return erased;
}
void mark_live(TwineRef ref, std::unordered_set<TwineRef>& live) const {
if (ref == Twine::Null || ref < STATIC_TWINE_END || !live.insert(ref).second)
return;
const Twine& t = (*this)[ref];
if (t.is_concat()) {
for (TwineRef c : t.children())
mark_live(c, live);
} else if (t.is_suffix()) {
mark_live(t.suffix().prefix, live);
}
}
void dump(std::ostream& os = std::cout) const {
os << "--- TwinePool Dump (" << backing.size() << " nodes) ---\n";
for (auto it = backing.begin(); it != backing.end(); ++it) {
@ -368,6 +433,67 @@ struct DeepTwineEq {
}
};
// Parallel-safe staging while the parent stays read-only; nodes may reference parent refs and earlier local refs
struct TwineChildPool {
const TwinePool* parent;
std::vector<Twine> local_;
std::vector<TwineRef> remap_;
TwineChildPool(const TwinePool* parent) : parent(parent) {}
static bool is_local(TwineRef ref) {
return ref != Twine::Null && (ref & TWINE_LOCAL_BIT);
}
const Twine& operator[] (TwineRef ref) const {
if (is_local(ref))
return local_[ref & ~TWINE_LOCAL_BIT];
return (*parent)[ref];
}
TwineRef add(Twine t) {
local_.push_back(std::move(t));
return (local_.size() - 1) | TWINE_LOCAL_BIT;
}
bool empty() const { return local_.empty(); }
// serial phase only; dest must be *parent; resolve() covers refs added since the previous commit
void commit_into(TwinePool& dest) {
remap_.clear();
remap_.reserve(local_.size());
for (Twine& t : local_) {
if (t.is_concat()) {
for (TwineRef& c : std::get<std::vector<TwineRef>>(t.data))
c = resolve(c);
} else if (t.is_suffix()) {
std::get<Twine::Suffix>(t.data).prefix = resolve(std::get<Twine::Suffix>(t.data).prefix);
}
remap_.push_back(dest.add(std::move(t)));
}
local_.clear();
}
TwineRef resolve(TwineRef ref) const {
if (!is_local(ref))
return ref;
return remap_[ref & ~TWINE_LOCAL_BIT];
}
};
inline TwineRef TwinePool::lookup(std::string_view sv) const {
DeepTwineEq eq{this};
for (TwineRef ref = 0; ref < globals_.size(); ref++)
if (eq(ref, sv))
return ref;
for (auto it = backing.begin(); it != backing.end(); ++it) {
TwineRef ref = STATIC_TWINE_END + backing.get_index(it);
if (eq(ref, sv))
return ref;
}
return Twine::Null;
}
struct TwineSearch {
TwinePool* pool;
std::unordered_set<TwineRef, DeepTwineHash, DeepTwineEq> index;