3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-15 03:35:40 +00:00

twine: start indexable colony with integer indices including preallocated twines

This commit is contained in:
Emil J. Tywoniak 2026-06-10 13:46:28 +02:00
parent 8ab96a4285
commit 015ab4e45b
7 changed files with 482 additions and 696 deletions

View file

@ -22,7 +22,7 @@ struct CellTableBuilder {
std::array<TwineRef, MAX_PORTS> ports{}; std::array<TwineRef, MAX_PORTS> ports{};
size_t count = 0; size_t count = 0;
constexpr PortList() = default; constexpr PortList() = default;
constexpr PortList(std::initializer_list<TW> init) { constexpr PortList(std::initializer_list<TwineRef> init) {
for (auto p : init) { for (auto p : init) {
ports[count++] = p; ports[count++] = p;
} }
@ -57,7 +57,7 @@ struct CellTableBuilder {
std::array<CellInfo, MAX_CELLS> cells{}; std::array<CellInfo, MAX_CELLS> cells{};
size_t count = 0; size_t count = 0;
constexpr void setup_type(RTLIL::IdString type, std::initializer_list<TW> inputs, std::initializer_list<TW> outputs, const Features& features) { constexpr void setup_type(RTLIL::IdString type, std::initializer_list<TwineRef> inputs, std::initializer_list<TwineRef> outputs, const Features& features) {
cells[count++] = {type, PortList(inputs), PortList(outputs), features}; cells[count++] = {type, PortList(inputs), PortList(outputs), features};
} }
constexpr void setup_internals_other() constexpr void setup_internals_other()
@ -619,7 +619,7 @@ struct NewCellTypes {
bool cell_input(const RTLIL::IdString &type, TwineRef port) const bool cell_input(const RTLIL::IdString &type, TwineRef port) const
{ {
if (static_cell_types(type) && StaticCellTypes::port_info.inputs(type).contains(static_to_offset(port))) { if (static_cell_types(type) && StaticCellTypes::port_info.inputs(type).contains(port)) {
return true; return true;
} }
auto it = custom_cell_types.find(type); auto it = custom_cell_types.find(type);
@ -630,8 +630,8 @@ struct NewCellTypes {
{ {
bool is_input, is_output; bool is_input, is_output;
if (static_cell_types(type)) { if (static_cell_types(type)) {
is_input = StaticCellTypes::port_info.inputs(type).contains(static_to_offset(port)); is_input = StaticCellTypes::port_info.inputs(type).contains(port);
is_output = StaticCellTypes::port_info.outputs(type).contains(static_to_offset(port)); is_output = StaticCellTypes::port_info.outputs(type).contains(port);
} else { } else {
auto it = custom_cell_types.find(type); auto it = custom_cell_types.find(type);
if (it == custom_cell_types.end()) if (it == custom_cell_types.end())

View file

@ -3302,7 +3302,7 @@ inline RTLIL::ModuleNameMasq::operator RTLIL::IdString() const {
inline RTLIL::ModuleNameMasq::operator TwineRef() const { inline RTLIL::ModuleNameMasq::operator TwineRef() const {
const RTLIL::Module *m = reinterpret_cast<const RTLIL::Module*>( const RTLIL::Module *m = reinterpret_cast<const RTLIL::Module*>(
reinterpret_cast<const char*>(this) - offsetof(RTLIL::Module, name)); reinterpret_cast<const char*>(this) - offsetof(RTLIL::Module, name));
return m->design ? m->design->obj_src_id(m) : nullptr; return m->design ? m->design->obj_src_id(m) : Twine::Null;
} }
// inline RTLIL::ModuleNameMasq& RTLIL::ModuleNameMasq::operator=(RTLIL::IdString id) { // inline RTLIL::ModuleNameMasq& RTLIL::ModuleNameMasq::operator=(RTLIL::IdString id) {

View file

@ -3,43 +3,24 @@
YOSYS_NAMESPACE_BEGIN YOSYS_NAMESPACE_BEGIN
// std::vector<Twine> TwinePool::globals_; std::vector<Twine> TwinePool::globals_;
constexpr inline std::array<Twine, STATIC_ID_END> globals_;
TwineRef twine_populate(std::string name) { TwineRef twine_populate(std::string name) {
if (name[1] == '$') { if (name[1] == '$') {
// Skip prepended '\' // Skip prepended '\'
name = name.substr(1); name = name.substr(1);
} }
TwinePool::globals_.push_back(Twine(name)); TwinePool::globals_.push_back(Twine{std::move(name)});
return &TwinePool::globals_.back(); return TwinePool::globals_.size() - 1;
} }
void twine_prepopulate() { void twine_prepopulate() {
int size = static_cast<short>(RTLIL::StaticId::STATIC_ID_END); TwinePool::globals_.reserve(STATIC_TWINE_END);
TwinePool::globals_.reserve(size); TwinePool::globals_.push_back(Twine{std::string()});
TwinePool::globals_.push_back(Twine(""));
#define X(_id) twine_populate("\\" #_id); #define X(_id) twine_populate("\\" #_id);
#include "kernel/constids.inc" #include "kernel/constids.inc"
#undef X #undef X
} }
#define X(N) constexpr TW TW::N{IDX_##N};
#include "kernel/constids.inc"
#undef X
TW::EnumType static_to_offset(TwineRef ref); {
size_t offset = ref - &TwinePool::globals_.front();
log_assert(offset > STATIC_TWINE_BEGIN);
log_assert(offset < STATIC_TWINE_END);
return (TW::EnumType)offset;
}
TwineRef offset_to_static(TW::EnumType offset) {
log_assert(offset > STATIC_TWINE_BEGIN);
log_assert(offset < STATIC_TWINE_END);
return &TwinePool::globals_[offset];
}
// enum : short // enum : short
// { // {
// STATIC_ID_BEGIN = 0, // STATIC_ID_BEGIN = 0,

View file

@ -8,6 +8,7 @@
#include <cstdint> #include <cstdint>
#include <limits> #include <limits>
#include <span> #include <span>
#include <sstream>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <unordered_set> #include <unordered_set>
@ -18,239 +19,26 @@
YOSYS_NAMESPACE_BEGIN YOSYS_NAMESPACE_BEGIN
struct Twine; struct Twine;
// struct TwineRef { struct TwinePool;
// std::variant<Twine*, size_t> data;
// constexpr TwineRef(Twine* p) : data(p) {}
// constexpr TwineRef(size_t global) : data(global) {}
// const Twine& operator*() const;
// Twine& operator*();
// Twine* operator->() {
// return &(**this);
// }
// const Twine* operator->() const {
// return &(**this);
// }
// friend constexpr bool operator==(const TwineRef& a, const TwineRef& b) {
// return &*a == &*b;
// }
// friend constexpr auto operator<=>(const TwineRef& a, const TwineRef& b) {
// return &*a <=> &*b;
// }
// };
template <class T> using TwineRef = size_t;
struct pointer_wrapper {
using element_type = T;
using value_type = std::remove_cv_t<T>;
using pointer = T*;
using reference = T&;
using difference_type = std::ptrdiff_t;
private: enum : short {
pointer ptr_ = nullptr;
public:
// ---------------------------------------------------------------------
// Construction
// ---------------------------------------------------------------------
constexpr pointer_wrapper() noexcept = default;
constexpr pointer_wrapper(std::nullptr_t) noexcept
: ptr_(nullptr) {}
constexpr explicit pointer_wrapper(pointer p) noexcept
: ptr_(p) {}
constexpr pointer_wrapper(const pointer_wrapper&) noexcept = default;
constexpr pointer_wrapper(pointer_wrapper&&) noexcept = default;
constexpr pointer_wrapper&
operator=(const pointer_wrapper&) noexcept = default;
constexpr pointer_wrapper&
operator=(pointer_wrapper&&) noexcept = default;
constexpr pointer_wrapper&
operator=(std::nullptr_t) noexcept {
ptr_ = nullptr;
return *this;
}
// ---------------------------------------------------------------------
// Access
// ---------------------------------------------------------------------
[[nodiscard]]
constexpr pointer get() const noexcept {
return ptr_;
}
[[nodiscard]]
constexpr reference operator*() const noexcept {
return *ptr_;
}
[[nodiscard]]
constexpr pointer operator->() const noexcept {
return ptr_;
}
[[nodiscard]]
constexpr reference operator[](difference_type n) const noexcept {
return ptr_[n];
}
// ---------------------------------------------------------------------
// Conversions
// ---------------------------------------------------------------------
constexpr explicit operator bool() const noexcept {
return ptr_ != nullptr;
}
// Optional: allow passing to APIs expecting T*
constexpr operator pointer() const noexcept {
return ptr_;
}
// ---------------------------------------------------------------------
// Increment / decrement
// ---------------------------------------------------------------------
constexpr pointer_wrapper& operator++() noexcept {
++ptr_;
return *this;
}
constexpr pointer_wrapper operator++(int) noexcept {
auto tmp = *this;
++(*this);
return tmp;
}
constexpr pointer_wrapper& operator--() noexcept {
--ptr_;
return *this;
}
constexpr pointer_wrapper operator--(int) noexcept {
auto tmp = *this;
--(*this);
return tmp;
}
// ---------------------------------------------------------------------
// Arithmetic
// ---------------------------------------------------------------------
constexpr pointer_wrapper&
operator+=(difference_type n) noexcept {
ptr_ += n;
return *this;
}
constexpr pointer_wrapper&
operator-=(difference_type n) noexcept {
ptr_ -= n;
return *this;
}
[[nodiscard]]
friend constexpr pointer_wrapper
operator+(pointer_wrapper p, difference_type n) noexcept {
p += n;
return p;
}
[[nodiscard]]
friend constexpr pointer_wrapper
operator+(difference_type n, pointer_wrapper p) noexcept {
p += n;
return p;
}
[[nodiscard]]
friend constexpr pointer_wrapper
operator-(pointer_wrapper p, difference_type n) noexcept {
p -= n;
return p;
}
[[nodiscard]]
friend constexpr difference_type
operator-(pointer_wrapper lhs,
pointer_wrapper rhs) noexcept {
return lhs.ptr_ - rhs.ptr_;
}
// ---------------------------------------------------------------------
// Comparisons
// ---------------------------------------------------------------------
[[nodiscard]]
friend constexpr bool
operator==(pointer_wrapper lhs,
pointer_wrapper rhs) noexcept = default;
[[nodiscard]]
friend constexpr auto
operator<=>(pointer_wrapper lhs,
pointer_wrapper rhs) noexcept {
return lhs.ptr_ <=> rhs.ptr_;
}
[[nodiscard]]
friend constexpr bool
operator==(pointer_wrapper lhs,
std::nullptr_t) noexcept {
return lhs.ptr_ == nullptr;
}
[[nodiscard]]
friend constexpr auto
operator<=>(pointer_wrapper lhs,
std::nullptr_t) noexcept {
return lhs.ptr_ <=> nullptr;
}
};
// class TW
// {
// public:
// using EnumType = short;
// // constexpr explicit TW() : internal(0) {}
// constexpr explicit TW(short v) : internal(v) {}
// // constexpr operator TwineRef() const
// // {
// // return TwineRef(&TwinePool::globals_[internal]);
// // }
// #define X(N) static constexpr TW N{IDX_##N};
// #include "kernel/constids.inc"
// #undef X
// private:
// EnumType internal;
// };
enum class TW : short {
STATIC_TWINE_BEGIN = 0, STATIC_TWINE_BEGIN = 0,
#define X(N) N, #define X(N) IDX_##N,
#include "kernel/constids.inc" #include "kernel/constids.inc"
#undef X #undef X
STATIC_TWINE_END, STATIC_TWINE_END
}; };
// using TwineRef = const Twine*; struct TW {
struct TwineRef : public pointer_wrapper<const Twine> { #define X(N) static constexpr TwineRef N = IDX_##N;
using pointer_wrapper<const Twine>::pointer_wrapper; #include "kernel/constids.inc"
// TwineRef(TW tw); #undef X
constexpr TwineRef(TW tw);
}; };
struct Twine { struct Twine {
static constexpr TwineRef Null = nullptr; static constexpr TwineRef Null = std::numeric_limits<size_t>::max();
struct Suffix { struct Suffix {
TwineRef prefix; TwineRef prefix;
@ -269,8 +57,49 @@ struct Twine {
const std::string &leaf() const { return std::get<std::string>(data); } const std::string &leaf() const { return std::get<std::string>(data); }
const std::vector<TwineRef> &children() const { return std::get<std::vector<TwineRef>>(data); } const std::vector<TwineRef> &children() const { return std::get<std::vector<TwineRef>>(data); }
const Suffix &suffix() const { return std::get<Suffix>(data); } const Suffix &suffix() const { return std::get<Suffix>(data); }
void dump(std::ostream& os = std::cout) const { };
std::visit([&os](const auto& val) {
struct TwineHash {
using is_transparent = void;
const TwinePool* pool = nullptr;
size_t operator()(const Twine& t) const noexcept;
size_t operator()(TwineRef ref) const noexcept;
// size_t operator()(std::string_view v) const noexcept;
};
struct TwineEq {
using is_transparent = void;
const TwinePool* pool = nullptr;
bool operator()(TwineRef a, TwineRef b) const noexcept;
bool operator()(TwineRef a, const Twine& b) const noexcept;
bool operator()(const Twine& a, TwineRef b) const noexcept;
// bool operator()(TwineRef a, std::string_view b) const noexcept;
// bool operator()(std::string_view a, TwineRef b) const noexcept;
};
TwineRef twine_populate(std::string name);
void twine_prepopulate();
struct TwinePool {
static std::vector<Twine> globals_;
plf::colony<Twine> backing;
std::unordered_set<TwineRef, TwineHash, TwineEq> index;
const Twine& operator[] (TwineRef ref) const {
if (ref < STATIC_TWINE_END)
return globals_[ref];
else
return backing[ref - STATIC_TWINE_END];
}
void dump(TwineRef ref, std::ostream& os = std::cout) const {
const Twine& twine = (*this)[ref];
std::visit([&](const auto& val) {
using T = std::decay_t<decltype(val)>; using T = std::decay_t<decltype(val)>;
if constexpr (std::is_same_v<T, std::monostate>) { if constexpr (std::is_same_v<T, std::monostate>) {
os << "Dead()"; os << "Dead()";
@ -281,18 +110,18 @@ struct Twine {
for (size_t i = 0; i < val.size(); ++i) { for (size_t i = 0; i < val.size(); ++i) {
if (i > 0) if (i > 0)
os << ", "; os << ", ";
val[i]->dump(os); dump(val[i], os);
} }
os << "]"; os << "]";
} else if constexpr (std::is_same_v<T, Suffix>) { } else if constexpr (std::is_same_v<T, Twine::Suffix>) {
os << "Suffix(prefix: "; os << "Suffix(prefix: ";
val.prefix->dump(os); dump(val.prefix, os);
os << ", tail: \"" << val.tail << "\")"; os << ", tail: \"" << val.tail << "\")";
} }
}, data); }, twine.data);
} }
void print(std::ostream& os = std::cout) const { void print(TwineRef ref, std::ostream& os = std::cout) const {
std::visit([&os](const auto& val) { std::visit([&](const auto& val) {
using T = std::decay_t<decltype(val)>; using T = std::decay_t<decltype(val)>;
if constexpr (std::is_same_v<T, std::monostate>) { if constexpr (std::is_same_v<T, std::monostate>) {
} else if constexpr (std::is_same_v<T, std::string>) { } else if constexpr (std::is_same_v<T, std::string>) {
@ -301,89 +130,83 @@ struct Twine {
for (size_t i = 0; i < val.size(); ++i) { for (size_t i = 0; i < val.size(); ++i) {
if (i > 0) if (i > 0)
os << "|"; os << "|";
val[i]->print(os); print(val[i], os);
} }
} else if constexpr (std::is_same_v<T, Suffix>) { } else if constexpr (std::is_same_v<T, Twine::Suffix>) {
val.prefix->print(os); print(val.prefix, os);
os << val.tail; os << val.tail;
} }
}, data); }, (*this)[ref].data);
} }
std::string str() const { std::string str(TwineRef ref) const {
std::string str; std::ostringstream os;
std::stringstream os(str); print(ref, os);
print(os); return os.str();
return str;
}
};
struct TwineHash {
using is_transparent = void;
size_t operator()(const Twine& t) const noexcept;
size_t operator()(TwineRef ptr) const noexcept;
// size_t operator()(std::string_view v) const noexcept;
};
struct TwineEq {
using is_transparent = void;
bool operator()(TwineRef a, TwineRef b) const noexcept;
bool operator()(TwineRef a, const Twine& b) const noexcept;
bool operator()(const Twine& a, TwineRef b) const noexcept;
// bool operator()(TwineRef a, std::string_view b) const noexcept;
// bool operator()(std::string_view a, TwineRef b) const noexcept;
};
enum : short {
STATIC_TWINE_BEGIN = 0,
#define X(N) IDX_##N,
#include "kernel/constids.inc"
#undef X
STATIC_TWINE_END
};
struct TwinePool {
static constexpr std::array<Twine, STATIC_TWINE_END> globals_;
plf::colony<Twine> backing;
std::unordered_set<TwineRef, TwineHash, TwineEq> index;
TwinePool() {
for (auto t : globals_)
index.insert(TwineRef(&t));
} }
TwineRef find(Twine t) const { TwinePool() : index(0, TwineHash{this}, TwineEq{this}) {
if (auto it = index.find(TwineRef(&t)); it != index.end()) { rebuild_index();
}
TwinePool(const TwinePool& other) : backing(other.backing), index(0, TwineHash{this}, TwineEq{this}) {
rebuild_index();
}
TwinePool(TwinePool&& other) : backing(std::move(other.backing)), index(0, TwineHash{this}, TwineEq{this}) {
rebuild_index();
}
TwinePool& operator=(const TwinePool& other) {
if (this != &other) {
backing = other.backing;
index = std::unordered_set<TwineRef, TwineHash, TwineEq>(0, TwineHash{this}, TwineEq{this});
rebuild_index();
}
return *this;
}
TwinePool& operator=(TwinePool&& other) {
if (this != &other) {
backing = std::move(other.backing);
index = std::unordered_set<TwineRef, TwineHash, TwineEq>(0, TwineHash{this}, TwineEq{this});
rebuild_index();
}
return *this;
}
void rebuild_index() {
for (TwineRef ref = 0; ref < globals_.size(); ref++)
index.insert(ref);
for (auto it = backing.begin(); it != backing.end(); ++it)
index.insert(STATIC_TWINE_END + backing.get_index(it));
}
TwineRef find(const Twine& t) const {
if (auto it = index.find(t); it != index.end()) {
return *it; return *it;
} }
return Twine::Null; return Twine::Null;
} }
TwineRef add(Twine t) { TwineRef add(Twine t) {
if (auto it = index.find(TwineRef(&t)); it != index.end()) { if (auto it = index.find(t); it != index.end()) {
return *it; return *it;
} }
auto colony_it = backing.insert(std::move(t)); auto colony_it = backing.insert(std::move(t));
TwineRef ptr(&(*colony_it)); TwineRef ref = STATIC_TWINE_END + backing.get_index(colony_it);
index.insert(ptr); index.insert(ref);
return ptr; return ref;
} }
void dump(std::ostream& os = std::cout) const { void dump(std::ostream& os = std::cout) const {
os << "--- TwinePool Dump (" << backing.size() << " nodes) ---\n"; os << "--- TwinePool Dump (" << backing.size() << " nodes) ---\n";
for (const auto& t : backing) { for (auto it = backing.begin(); it != backing.end(); ++it) {
os << static_cast<const void*>(&t) << " -> "; TwineRef ref = STATIC_TWINE_END + backing.get_index(it);
t.dump(os); os << ref << " -> ";
dump(ref, os);
os << '\n'; os << '\n';
} }
os << "--------------------------------\n"; os << "--------------------------------\n";
} }
// Silly compat // Silly compat
std::string flat_string(TwineRef t) const { return t->str(); } std::string flat_string(TwineRef t) const { return str(t); }
}; };
inline size_t TwineHash::operator()(const Twine& t) const noexcept { inline size_t TwineHash::operator()(const Twine& t) const noexcept {
@ -394,7 +217,7 @@ inline size_t TwineHash::operator()(const Twine& t) const noexcept {
using T = std::decay_t<decltype(val)>; using T = std::decay_t<decltype(val)>;
// auto combine = [&h](auto v) { // auto combine = [&h](auto v) {
// h ^= v + 0x9e3779b9 + (h << 6) + (h >> 2); // h ^= v + 0x9e3779b9 + (h << 6) + (h >> 2);
// }; // };
if constexpr (std::is_same_v<T, std::string>) { if constexpr (std::is_same_v<T, std::string>) {
@ -416,26 +239,28 @@ inline size_t TwineHash::operator()(const Twine& t) const noexcept {
return h.yield(); return h.yield();
} }
inline size_t TwineHash::operator()(TwineRef ptr) const noexcept { inline size_t TwineHash::operator()(TwineRef ref) const noexcept {
return (*this)(*ptr); return (*this)((*pool)[ref]);
} }
inline bool TwineEq::operator()(TwineRef a, TwineRef b) const noexcept { inline bool TwineEq::operator()(TwineRef a, TwineRef b) const noexcept {
return a->data == b->data; return (*pool)[a].data == (*pool)[b].data;
} }
inline bool TwineEq::operator()(TwineRef a, const Twine& b) const noexcept { inline bool TwineEq::operator()(TwineRef a, const Twine& b) const noexcept {
return a->data == b.data; return (*pool)[a].data == b.data;
} }
inline bool TwineEq::operator()(const Twine& a, TwineRef b) const noexcept { inline bool TwineEq::operator()(const Twine& a, TwineRef b) const noexcept {
return a.data == b->data; return a.data == (*pool)[b].data;
} }
struct DeepTwineHash { struct DeepTwineHash {
using is_transparent = void; using is_transparent = void;
const TwinePool* pool = nullptr;
// FNV-1a constants for 64-bit // FNV-1a constants for 64-bit
static constexpr size_t FNV_OFFSET_BASIS = 14695981039346656037ull; static constexpr size_t FNV_OFFSET_BASIS = 14695981039346656037ull;
static constexpr size_t FNV_PRIME = 1099511628211ull; static constexpr size_t FNV_PRIME = 1099511628211ull;
@ -448,16 +273,19 @@ struct DeepTwineHash {
} }
// Recursively hash the fragments of a Twine // Recursively hash the fragments of a Twine
static void combine(size_t& hash, TwineRef t) noexcept { void combine(size_t& hash, TwineRef t) const noexcept {
if (!t || t->is_dead()) return; if (t == Twine::Null)
return;
const Twine& n = (*pool)[t];
if (n.is_dead()) return;
if (t->is_leaf()) { if (n.is_leaf()) {
combine(hash, t->leaf()); combine(hash, std::string_view(n.leaf()));
} else if (t->is_concat()) { } else if (n.is_concat()) {
for (auto child : t->children()) combine(hash, child); for (auto child : n.children()) combine(hash, child);
} else if (t->is_suffix()) { } else if (n.is_suffix()) {
combine(hash, t->suffix().prefix); combine(hash, n.suffix().prefix);
combine(hash, t->suffix().tail); combine(hash, std::string_view(n.suffix().tail));
} }
} }
@ -477,23 +305,28 @@ struct DeepTwineHash {
struct DeepTwineEq { struct DeepTwineEq {
using is_transparent = void; using is_transparent = void;
// Recursively consumes the string_view to check for deep equality const TwinePool* pool = nullptr;
static bool consume(TwineRef t, std::string_view& sv) noexcept {
if (!t || t->is_dead()) return true;
if (t->is_leaf()) { // Recursively consumes the string_view to check for deep equality
if (!sv.starts_with(t->leaf())) return false; bool consume(TwineRef t, std::string_view& sv) const noexcept {
sv.remove_prefix(t->leaf().size()); if (t == Twine::Null)
return true; return true;
} else if (t->is_concat()) { const Twine& n = (*pool)[t];
for (auto child : t->children()) { if (n.is_dead()) return true;
if (n.is_leaf()) {
if (!sv.starts_with(n.leaf())) return false;
sv.remove_prefix(n.leaf().size());
return true;
} else if (n.is_concat()) {
for (auto child : n.children()) {
if (!consume(child, sv)) return false; if (!consume(child, sv)) return false;
} }
return true; return true;
} else if (t->is_suffix()) { } else if (n.is_suffix()) {
if (!consume(t->suffix().prefix, sv)) return false; if (!consume(n.suffix().prefix, sv)) return false;
if (!sv.starts_with(t->suffix().tail)) return false; if (!sv.starts_with(n.suffix().tail)) return false;
sv.remove_prefix(t->suffix().tail.size()); sv.remove_prefix(n.suffix().tail.size());
return true; return true;
} }
return false; return false;
@ -509,21 +342,25 @@ struct DeepTwineEq {
// Required by unordered_set to handle hash collisions between two TwineRefs. // Required by unordered_set to handle hash collisions between two TwineRefs.
bool operator()(TwineRef a, TwineRef b) const { bool operator()(TwineRef a, TwineRef b) const {
if (a == b) return true; // Pointer or structural equality shortcut if (a == b) return true; // Index or structural equality shortcut
return (*this)(a, flatten(b)); std::string fb = flatten(b);
return (*this)(a, std::string_view(fb));
} }
// Helper to flatten a twine (used only during rare hash collisions) // Helper to flatten a twine (used only during rare hash collisions)
static std::string flatten(TwineRef t) { std::string flatten(TwineRef t) const {
std::string result; std::string result;
auto append = [&result](auto& self, TwineRef node) -> void { auto append = [&](auto& self, TwineRef ref) -> void {
if (!node || node->is_dead()) return; if (ref == Twine::Null)
if (node->is_leaf()) result += node->leaf(); return;
else if (node->is_concat()) { const Twine& node = (*pool)[ref];
for (auto child : node->children()) self(self, child); if (node.is_dead()) return;
} else if (node->is_suffix()) { if (node.is_leaf()) result += node.leaf();
self(self, node->suffix().prefix); else if (node.is_concat()) {
result += node->suffix().tail; for (auto child : node.children()) self(self, child);
} else if (node.is_suffix()) {
self(self, node.suffix().prefix);
result += node.suffix().tail;
} }
}; };
append(append, t); append(append, t);
@ -532,11 +369,11 @@ struct DeepTwineEq {
}; };
struct TwineSearch { struct TwineSearch {
std::unordered_set<TwineRef, DeepTwineHash, DeepTwineEq> index;
TwinePool* pool; TwinePool* pool;
TwineSearch(TwinePool* pool) : pool(pool) { std::unordered_set<TwineRef, DeepTwineHash, DeepTwineEq> index;
for (auto& t : pool->backing) { TwineSearch(TwinePool* pool) : pool(pool), index(0, DeepTwineHash{pool}, DeepTwineEq{pool}) {
index.insert(TwineRef(&t)); for (auto it = pool->backing.begin(); it != pool->backing.end(); ++it) {
index.insert(STATIC_TWINE_END + pool->backing.get_index(it));
} }
} }
TwineRef find(std::string_view sv) const { TwineRef find(std::string_view sv) const {
@ -547,38 +384,6 @@ struct TwineSearch {
} }
}; };
#define static_to_offset
#define offset_to_static
// TW static_to_offset(TwineRef ref);
// TwineRef offset_to_static(TW offset);
constexpr TwineRef::TwineRef(TW tw)
: pointer_wrapper<const Twine>(&TwinePool::globals_[(short)tw]) {}
// Twine& TwineRef::operator*() {
// // Ugly
// std::visit([](const auto& data) {
// using T = std::decay_t<decltype(data)>;
// if constexpr (std::is_same_v<Twine*, std::monostate>) {
// return *data;
// } else {
// return TwinePool::globals_[data];
// }
// }, data);
// }
// const Twine& TwineRef::operator*() const {
// // Ugly
// std::visit([](const auto& data) {
// using T = std::decay_t<decltype(data)>;
// if constexpr (std::is_same_v<Twine*, std::monostate>) {
// return *data;
// } else {
// return TwinePool::globals_[data];
// }
// }, data);
// }
// struct TwinePoolExtender { // struct TwinePoolExtender {
// TwinePool& pool; // TwinePool& pool;
// size_t offset; // size_t offset;

View file

@ -26,8 +26,8 @@ public:
SigMap* map; SigMap* map;
vector<std::unique_ptr<Wire>> wires_ = {}; vector<std::unique_ptr<Wire>> wires_ = {};
vector<std::unique_ptr<Cell>> cells_ = {}; vector<std::unique_ptr<Cell>> cells_ = {};
dict<RTLIL::Cell*, RTLIL::IdString> staged_cell_names_; dict<RTLIL::Cell*, Twine> staged_cell_names_;
dict<RTLIL::Wire*, RTLIL::IdString> staged_wire_names_; dict<RTLIL::Wire*, Twine> staged_wire_names_;
void connect(const RTLIL::SigSig &conn); void connect(const RTLIL::SigSig &conn);
void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs); void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs);
@ -53,7 +53,7 @@ public:
// Src is auto-merged from root_cell + extras + merge_src_into into // Src is auto-merged from root_cell + extras + merge_src_into into
// every staged new cell and into merge_src_into. // every staged new cell and into merge_src_into.
void patch_ports(Cell* root_cell, void patch_ports(Cell* root_cell,
const std::vector<std::pair<IdString, SigSpec>>& port_replacements, const std::vector<std::pair<TwineRef, SigSpec>>& port_replacements,
const std::vector<Cell*>& extras = {}, const std::vector<Cell*>& extras = {},
Cell* merge_src_into = nullptr); Cell* merge_src_into = nullptr);

@ -1 +1 @@
Subproject commit bc11fa510423f80308fa43818185df01f41a29c8 Subproject commit bdc219742d116b569c2a44956ba0aba5f3ef5717

File diff suppressed because it is too large Load diff