3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-15 03:35:40 +00:00
This commit is contained in:
Emil J. Tywoniak 2026-06-09 20:29:33 +02:00
parent 2117af318c
commit 8ab96a4285
5 changed files with 335 additions and 119 deletions

View file

@ -22,7 +22,7 @@ struct CellTableBuilder {
std::array<TwineRef, MAX_PORTS> ports{};
size_t count = 0;
constexpr PortList() = default;
constexpr PortList(std::initializer_list<TwineRef> init) {
constexpr PortList(std::initializer_list<TW> init) {
for (auto p : init) {
ports[count++] = p;
}
@ -57,7 +57,7 @@ struct CellTableBuilder {
std::array<CellInfo, MAX_CELLS> cells{};
size_t count = 0;
constexpr void setup_type(RTLIL::IdString type, std::initializer_list<TwineRef> inputs, std::initializer_list<TwineRef> outputs, const Features& features) {
constexpr void setup_type(RTLIL::IdString type, std::initializer_list<TW> inputs, std::initializer_list<TW> 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<RTLIL::IdString> inputs, outputs;
pool<TwineRef> inputs, outputs;
bool is_evaluable;
bool is_combinatorial;
bool is_synthesizable;
@ -582,18 +582,18 @@ struct NewCellTypes {
}
void setup_module(RTLIL::Module *module) {
pool<RTLIL::IdString> inputs, outputs;
pool<TwineRef> 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<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs, bool is_evaluable = false, bool is_combinatorial = false, bool is_synthesizable = false) {
void setup_type(RTLIL::IdString type, const pool<TwineRef> &inputs, const pool<TwineRef> &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())

View file

@ -3,42 +3,56 @@
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) {
// 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<short>(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<short>(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<Twine>
// };

View file

@ -18,26 +18,236 @@
YOSYS_NAMESPACE_BEGIN
struct Twine;
struct TwineRef {
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);
// struct TwineRef {
// 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>
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:
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<const Twine> {
using pointer_wrapper<const Twine>::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<std::monostate, std::string, std::vector<TwineRef>, 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<Twine> globals_;
static constexpr std::array<Twine, STATIC_TWINE_END> globals_;
plf::colony<Twine> backing;
std::unordered_set<TwineRef, TwineHash, TwineEq> 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<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);
// }
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<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);
}
// 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 {
// TwinePool& pool;

View file

@ -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<Cell*>& extras = {},
Cell* merge_src_into = nullptr);

View file

@ -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));