diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index fef0dc32d..7c335ec19 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -22,7 +22,7 @@ struct CellTableBuilder { std::array ports{}; size_t count = 0; constexpr PortList() = default; - constexpr PortList(std::initializer_list init) { + constexpr PortList(std::initializer_list init) { for (auto p : init) { ports[count++] = p; } @@ -57,7 +57,7 @@ struct CellTableBuilder { std::array cells{}; size_t count = 0; - constexpr void setup_type(RTLIL::IdString type, std::initializer_list inputs, std::initializer_list outputs, const Features& features) { + constexpr void setup_type(RTLIL::IdString type, std::initializer_list inputs, std::initializer_list outputs, const Features& features) { cells[count++] = {type, PortList(inputs), PortList(outputs), features}; } constexpr void setup_internals_other() @@ -418,7 +418,7 @@ struct CellTableBuilder { }; -constexpr CellTableBuilder builder{}; +constexpr CellTableBuilder builder {}; struct PortInfo { struct PortLists { @@ -548,7 +548,7 @@ namespace { struct NewCellType { RTLIL::IdString type; - pool inputs, outputs; + pool inputs, outputs; bool is_evaluable; bool is_combinatorial; bool is_synthesizable; @@ -582,18 +582,18 @@ struct NewCellTypes { } void setup_module(RTLIL::Module *module) { - pool inputs, outputs; + pool inputs, outputs; for (auto wire_name : module->ports) { RTLIL::Wire *wire = module->wire(wire_name); if (wire->port_input) - inputs.insert(wire->name); + inputs.insert(wire->meta_->name_id); if (wire->port_output) - outputs.insert(wire->name); + outputs.insert(wire->meta_->name_id); } setup_type(module->name, inputs, outputs); } - void setup_type(RTLIL::IdString type, const pool &inputs, const pool &outputs, bool is_evaluable = false, bool is_combinatorial = false, bool is_synthesizable = false) { + void setup_type(RTLIL::IdString type, const pool &inputs, const pool &outputs, bool is_evaluable = false, bool is_combinatorial = false, bool is_synthesizable = false) { NewCellType ct = {type, inputs, outputs, is_evaluable, is_combinatorial, is_synthesizable}; custom_cell_types[ct.type] = ct; } @@ -609,6 +609,7 @@ struct NewCellTypes { bool cell_output(const RTLIL::IdString &type, TwineRef port) const { + // TODO refactor if (static_cell_types(type) && StaticCellTypes::port_info.outputs(type).contains(port)) { return true; } @@ -618,19 +619,19 @@ struct NewCellTypes { bool cell_input(const RTLIL::IdString &type, TwineRef port) const { - if (static_cell_types(type) && StaticCellTypes::port_info.inputs(type).contains(port)) { + if (static_cell_types(type) && StaticCellTypes::port_info.inputs(type).contains(static_to_offset(port))) { return true; } auto it = custom_cell_types.find(type); return it != custom_cell_types.end() && it->second.inputs.count(port) != 0; } - RTLIL::PortDir cell_port_dir(RTLIL::IdString type, RTLIL::IdString port) const + RTLIL::PortDir cell_port_dir(RTLIL::IdString type, TwineRef port) const { bool is_input, is_output; if (static_cell_types(type)) { - is_input = StaticCellTypes::port_info.inputs(type).contains(port); - is_output = StaticCellTypes::port_info.outputs(type).contains(port); + is_input = StaticCellTypes::port_info.inputs(type).contains(static_to_offset(port)); + is_output = StaticCellTypes::port_info.outputs(type).contains(static_to_offset(port)); } else { auto it = custom_cell_types.find(type); if (it == custom_cell_types.end()) diff --git a/kernel/twine.cc b/kernel/twine.cc index 732b25a77..80b932253 100644 --- a/kernel/twine.cc +++ b/kernel/twine.cc @@ -3,42 +3,56 @@ YOSYS_NAMESPACE_BEGIN -std::vector TwinePool::globals_; +// std::vector TwinePool::globals_; +constexpr inline std::array globals_; -// TwineRef twine_populate(std::string name) { -// if (name[1] == '$') { -// // Skip prepended '\' -// name = name.substr(1); -// } -// TwinePool::globals_.push_back(Twine(name)); -// return &TwinePool::globals_.back(); -// } -// void twine_prepopulate() { -// int size = static_cast(RTLIL::StaticId::STATIC_ID_END); -// TwinePool::globals_.reserve(size); -// TwinePool::globals_.push_back(Twine("")); -// #define X(_id) twine_populate("\\" #_id); +TwineRef twine_populate(std::string name) { + if (name[1] == '$') { + // Skip prepended '\' + name = name.substr(1); + } + TwinePool::globals_.push_back(Twine(name)); + return &TwinePool::globals_.back(); +} +void twine_prepopulate() { + int size = static_cast(RTLIL::StaticId::STATIC_ID_END); + TwinePool::globals_.reserve(size); + TwinePool::globals_.push_back(Twine("")); +#define X(_id) twine_populate("\\" #_id); +#include "kernel/constids.inc" +#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 +// { +// STATIC_ID_BEGIN = 0, +// #define X(N) IDX_##N, // #include "kernel/constids.inc" // #undef X -// } +// STATIC_ID_END +// }; // #define X(N) const TW TW::N{IDX_##N}; // #include "kernel/constids.inc" // #undef X -enum : short -{ - STATIC_ID_BEGIN = 0, -#define X(N) IDX_##N, -#include "kernel/constids.inc" -#undef X - STATIC_ID_END -}; - -#define X(N) const TW TW::N{IDX_##N}; -#include "kernel/constids.inc" -#undef X - // struct TwinePool { // colony // }; diff --git a/kernel/twine.h b/kernel/twine.h index 8f15f1e79..6ddafb910 100644 --- a/kernel/twine.h +++ b/kernel/twine.h @@ -18,26 +18,236 @@ YOSYS_NAMESPACE_BEGIN struct Twine; -struct TwineRef { - std::variant data; - constexpr TwineRef(Twine* p) : data(p) {} - constexpr TwineRef(size_t global) : data(global) {} - const Twine& operator*() const; - Twine& operator*(); - Twine* operator->() { - return &(**this); +// struct TwineRef { +// std::variant 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 +struct pointer_wrapper { + using element_type = T; + using value_type = std::remove_cv_t; + using pointer = T*; + using reference = T&; + using difference_type = std::ptrdiff_t; + +private: + 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; } - const Twine* operator->() const { - return &(**this); + + // --------------------------------------------------------------------- + // Access + // --------------------------------------------------------------------- + + [[nodiscard]] + constexpr pointer get() const noexcept { + return ptr_; } - friend constexpr bool operator==(const TwineRef& a, const TwineRef& b) { - return &*a == &*b; + + [[nodiscard]] + constexpr reference operator*() const noexcept { + return *ptr_; } - friend constexpr auto operator<=>(const TwineRef& a, const TwineRef& b) { - return &*a <=> &*b; + + [[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, +#define X(N) N, +#include "kernel/constids.inc" +#undef X + STATIC_TWINE_END, +}; + // using TwineRef = const Twine*; +struct TwineRef : public pointer_wrapper { + using pointer_wrapper::pointer_wrapper; + // TwineRef(TW tw); + constexpr TwineRef(TW tw); +}; struct Twine { static constexpr TwineRef Null = nullptr; @@ -46,7 +256,7 @@ struct Twine { TwineRef prefix; std::string tail; // TODO check - // auto operator<=>(const Suffix&) const = default; + auto operator<=>(const Suffix&) const = default; }; std::variant, Suffix> data; @@ -125,30 +335,40 @@ struct TwineEq { // 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 std::vector globals_; + static constexpr std::array globals_; plf::colony backing; std::unordered_set index; TwinePool() { - for (Twine& t : globals_) - index.insert(&t); + for (auto t : globals_) + index.insert(TwineRef(&t)); } TwineRef find(Twine t) const { - if (auto it = index.find(t); it != index.end()) { + if (auto it = index.find(TwineRef(&t)); it != index.end()) { return *it; } return Twine::Null; } TwineRef add(Twine t) { - if (auto it = index.find(t); it != index.end()) { + if (auto it = index.find(TwineRef(&t)); it != index.end()) { return *it; } auto colony_it = backing.insert(std::move(t)); - TwineRef ptr = &(*colony_it); + TwineRef ptr(&(*colony_it)); index.insert(ptr); return ptr; } @@ -316,7 +536,7 @@ struct TwineSearch { TwinePool* pool; TwineSearch(TwinePool* pool) : pool(pool) { for (auto& t : pool->backing) { - index.insert(&t); + index.insert(TwineRef(&t)); } } TwineRef find(std::string_view sv) const { @@ -327,56 +547,37 @@ struct TwineSearch { } }; -// enum : short { -// STATIC_ID_BEGIN = 0, -// #define X(N) IDX_##N, -// #include "kernel/constids.inc" -// #undef X -// STATIC_ID_END -// }; +#define static_to_offset +#define offset_to_static +// TW static_to_offset(TwineRef ref); +// TwineRef offset_to_static(TW offset); -class TW -{ -public: - constexpr explicit TW(short v) : internal(v) {} +constexpr TwineRef::TwineRef(TW tw) + : pointer_wrapper(&TwinePool::globals_[(short)tw]) {} +// Twine& TwineRef::operator*() { +// // Ugly +// std::visit([](const auto& data) { +// using T = std::decay_t; +// if constexpr (std::is_same_v) { +// return *data; +// } else { +// return TwinePool::globals_[data]; +// } +// }, data); +// } - constexpr operator TwineRef() const - { - return &TwinePool::globals_[internal]; - } - -#define X(N) static const TW N; -#include "kernel/constids.inc" -#undef X - -private: - short internal; -}; - -Twine& TwineRef::operator*() { - // Ugly - std::visit([](const auto& data) { - using T = std::decay_t; - if constexpr (std::is_same_v) { - return *data; - } else { - return TwinePool::globals_[data]; - } - }, data); -} - -const Twine& TwineRef::operator*() const { - // Ugly - std::visit([](const auto& data) { - using T = std::decay_t; - if constexpr (std::is_same_v) { - return *data; - } else { - return TwinePool::globals_[data]; - } - }, data); -} +// const Twine& TwineRef::operator*() const { +// // Ugly +// std::visit([](const auto& data) { +// using T = std::decay_t; +// if constexpr (std::is_same_v) { +// return *data; +// } else { +// return TwinePool::globals_[data]; +// } +// }, data); +// } // struct TwinePoolExtender { // TwinePool& pool; diff --git a/kernel/unstable/patch.h b/kernel/unstable/patch.h index b0c4e8e53..68b148d22 100644 --- a/kernel/unstable/patch.h +++ b/kernel/unstable/patch.h @@ -39,7 +39,7 @@ public: // merge_src_into if set) into every staged new cell and into // merge_src_into, then removes root_cell from the module. No input-cone // walk: only root_cell is removed. - void patch(Cell* root_cell, IdString old_port, SigSpec new_sig, + void patch(Cell* root_cell, TwineRef old_port, SigSpec new_sig, const std::vector& extras = {}, Cell* merge_src_into = nullptr); diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index c16cefa98..5ce518fcb 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -128,7 +128,7 @@ void log_replace_sig(RTLIL::Module *module, RTLIL::Cell *cell, } void log_replace_port(RTLIL::Module *module, RTLIL::Cell *cell, - const std::string &info, RTLIL::IdString port, RTLIL::SigSpec new_sig) + const std::string &info, TwineRef port, RTLIL::SigSpec new_sig) { log_replace_sig(module, cell, info, cell->getPort(port), new_sig); } @@ -136,7 +136,7 @@ void log_replace_port(RTLIL::Module *module, RTLIL::Cell *cell, struct OptExprPatcher : public RTLIL::Patch { OptExprPatcher(Module *mod, SigMap *map) : RTLIL::Patch(mod, map) {} // Single-output rewrite via the compatible Patch::patch interface. - void patch(Cell *old_cell, IdString old_port, SigSpec new_sig, const std::string &info) { + void patch(Cell *old_cell, TwineRef old_port, SigSpec new_sig, const std::string &info) { new_sig.extend_u0(old_cell->getPort(old_port).size(), false); log_replace_port(mod, old_cell, info, old_port, new_sig); RTLIL::Patch::patch(old_cell, old_port, new_sig); @@ -157,14 +157,14 @@ struct OptExprPatcher : public RTLIL::Patch { bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutative, SigMap &sigmap, bool keepdc) { - IdString b_name = cell->hasPort(ID::B) ? ID::B : ID::A; + TwineRef b_name = cell->hasPort(TW::B) ? TW::B : TW::A; bool a_signed = cell->parameters.at(ID::A_SIGNED).as_bool(); bool b_signed = cell->parameters.at(b_name.str() + "_SIGNED").as_bool(); - RTLIL::SigSpec sig_a = sigmap(cell->getPort(ID::A)); + RTLIL::SigSpec sig_a = sigmap(cell->getPort(TW::A)); RTLIL::SigSpec sig_b = sigmap(cell->getPort(b_name)); - RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID::Y)); + RTLIL::SigSpec sig_y = sigmap(cell->getPort(TW::Y)); sig_a.extend_u0(sig_y.size(), a_signed); sig_b.extend_u0(sig_y.size(), b_signed); @@ -326,17 +326,17 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ RTLIL::Cell *c = patcher.addCell(NEW_ID, cell->type); - c->setPort(ID::A, new_a); + c->setPort(TW::A, new_a); c->parameters[ID::A_WIDTH] = new_a.size(); c->parameters[ID::A_SIGNED] = false; - if (b_name == ID::B) { - c->setPort(ID::B, new_b); + if (b_name == TW::B) { + c->setPort(TW::B, new_b); c->parameters[ID::B_WIDTH] = new_b.size(); c->parameters[ID::B_SIGNED] = false; } - c->setPort(ID::Y, new_y); + c->setPort(TW::Y, new_y); c->parameters[ID::Y_WIDTH] = GetSize(new_y); log_debug(" New cell `%s': A=%s", c, log_signal(new_a));