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:
parent
8ab96a4285
commit
015ab4e45b
7 changed files with 482 additions and 696 deletions
|
|
@ -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())
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
531
kernel/twine.h
531
kernel/twine.h
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue