3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-18 13:15:46 +00:00
This commit is contained in:
Emil J. Tywoniak 2026-06-12 16:25:07 +02:00
parent c3ffbf6fae
commit d22805bd47
65 changed files with 739 additions and 718 deletions

View file

@ -866,7 +866,7 @@ DriveSpec DriverMap::operator()(DriveSpec spec)
std::string log_signal(DriveChunkWire const &chunk)
{
std::string id = design->twines.unescaped_str(chunk.wire->name);
std::string id = chunk.wire->module->design->twines.unescaped_str(chunk.wire->name.ref());
if (chunk.is_whole())
return id;
if (chunk.width == 1)

View file

@ -17,6 +17,7 @@
*
*/
#include "kernel/rtlil.h"
#include "kernel/yosys.h"
#include "kernel/macc.h"
#include "kernel/newcelltypes.h"
@ -1833,7 +1834,7 @@ RTLIL::Module::Module()
design = nullptr;
refcount_wires_ = 0;
refcount_cells_ = 0;
meta_ = nullptr;
meta_ = new ObjMeta;
#ifdef YOSYS_ENABLE_PYTHON
RTLIL::Module::get_all_modules()->insert(std::pair<unsigned int, RTLIL::Module*>(hashidx_, this));
@ -2948,14 +2949,11 @@ namespace {
void RTLIL::Module::sort()
{
auto sort_twine_by_str = [this](TwineRef a, TwineRef b) {
return design->twines.flat_string(a) < design->twines.flat_string(b);
};
wires_.sort(sort_twine_by_str);
cells_.sort(sort_twine_by_str);
wires_.sort(sort_by_twine_str_expensive(design->twines));
cells_.sort(sort_by_twine_str_expensive(design->twines));
parameter_default_values.sort(sort_by_id_str());
memories.sort(sort_twine_by_str);
processes.sort(sort_twine_by_str);
memories.sort(sort_by_twine_str_expensive(design->twines));
processes.sort(sort_by_twine_str_expensive(design->twines));
for (auto &it : cells_)
it.second->sort();
for (auto &it : wires_)

View file

@ -130,6 +130,7 @@ namespace RTLIL
struct StaticIdString;
struct SigNormIndex;
struct ObjMeta;
template<typename Derived> struct NameMasqBase;
struct ModuleNameMasq;
struct WireNameMasq;
struct CellNameMasq;
@ -825,6 +826,18 @@ namespace RTLIL {
return a.lt_by_name(b);
}
};
struct sort_by_twine_str_expensive {
const TwinePool& pool;
explicit sort_by_twine_str_expensive(const TwinePool& pool)
: pool(pool) {}
bool operator()(TwineRef a, TwineRef b) const {
bool a_public = a.is_public();
bool b_public = b.is_public();
std::string a_str = pool.str(a);
std::string b_str = pool.str(b);
return std::tie(a_str, a_public) < std::tie(b_str, b_public);
}
};
static inline std::string encode_filename(const std::string &filename)
{
@ -1329,97 +1342,85 @@ struct RTLIL::NamedObject : public RTLIL::AttrObject
RTLIL::IdString name;
};
// CRTP base shared by WireNameMasq, CellNameMasq, and ModuleNameMasq.
// Derived must define ref(), escaped(), and unescaped(); everything else
// is derived from those three via operator IdString().
namespace RTLIL {
template<typename Derived>
struct NameMasqBase {
operator RTLIL::IdString() const {
std::string s = self().escaped();
if (s.empty()) return RTLIL::IdString{};
return RTLIL::IdString(s);
}
bool isPublic() const { return twine_is_public(self().ref()); }
bool empty() const { return RTLIL::IdString(self()).empty(); }
std::string str() const { return self().escaped(); }
const char *c_str() const { return RTLIL::IdString(self()).c_str(); }
std::string unescape() const { return self().unescaped(); }
bool begins_with(const char *s) const { return RTLIL::IdString(self()).begins_with(s); }
bool ends_with(const char *s) const { return RTLIL::IdString(self()).ends_with(s); }
template <typename... Ts> bool in(Ts &&...args) const {
return RTLIL::IdString(self()).in(std::forward<Ts>(args)...);
}
std::string substr(size_t pos = 0, size_t len = std::string::npos) const {
return RTLIL::IdString(self()).substr(pos, len);
}
size_t size() const { return RTLIL::IdString(self()).size(); }
bool contains(const char *p) const { return RTLIL::IdString(self()).contains(p); }
char operator[](int n) const { return RTLIL::IdString(self()).str()[n]; }
bool lt_by_name(RTLIL::IdString rhs) const { return RTLIL::IdString(self()).lt_by_name(rhs); }
bool lt_by_name(const Derived &rhs) const { return RTLIL::IdString(self()).lt_by_name(RTLIL::IdString(rhs)); }
bool operator==(RTLIL::IdString rhs) const { return RTLIL::IdString(self()) == rhs; }
bool operator!=(RTLIL::IdString rhs) const { return RTLIL::IdString(self()) != rhs; }
bool operator<(RTLIL::IdString rhs) const { return RTLIL::IdString(self()) < rhs; }
bool operator==(const std::string &rhs) const { return RTLIL::IdString(self()) == rhs; }
bool operator!=(const std::string &rhs) const { return RTLIL::IdString(self()) != rhs; }
bool operator==(const Derived &rhs) const { return RTLIL::IdString(self()) == RTLIL::IdString(rhs); }
bool operator!=(const Derived &rhs) const { return RTLIL::IdString(self()) != RTLIL::IdString(rhs); }
bool operator<(const Derived &rhs) const { return RTLIL::IdString(self()) < RTLIL::IdString(rhs); }
[[nodiscard]] Hasher hash_into(Hasher h) const { return RTLIL::IdString(self()).hash_into(h); }
private:
const Derived &self() const { return *static_cast<const Derived *>(this); }
};
} // namespace RTLIL
template<typename Derived>
inline bool operator==(RTLIL::IdString lhs, const RTLIL::NameMasqBase<Derived> &rhs) {
return lhs == RTLIL::IdString(rhs);
}
template<typename Derived>
inline bool operator!=(RTLIL::IdString lhs, const RTLIL::NameMasqBase<Derived> &rhs) {
return lhs != RTLIL::IdString(rhs);
}
// Read-only masquerade for Wire::name. Reads materialise the TwineRef in
// the owning Design's twines pool into a temporary IdString. Writes are
// intentionally unsupported — use Module::rename(wire, new_name) instead.
// Defined before Wire so it can be used as a [[no_unique_address]] member.
struct RTLIL::WireNameMasq {
struct RTLIL::WireNameMasq : RTLIL::NameMasqBase<RTLIL::WireNameMasq> {
WireNameMasq() = default;
WireNameMasq(const WireNameMasq &) = delete;
WireNameMasq(WireNameMasq &&) = delete;
WireNameMasq &operator=(const WireNameMasq &) = delete;
WireNameMasq &operator=(WireNameMasq &&) = delete;
// Materialise → IdString. Slow path; intended for plugin code.
operator RTLIL::IdString() const;
// Tagged name handle (Twine::Null when unnamed).
TwineRef ref() const;
// Escaped form ('\'-prefixed when public) / bare content.
std::string escaped() const;
std::string unescaped() const;
bool isPublic() const { return twine_is_public(ref()); }
bool empty() const { return RTLIL::IdString(*this).empty(); }
std::string str() const { return escaped(); }
const char *c_str() const { return RTLIL::IdString(*this).c_str(); }
std::string unescape() const { return unescaped(); }
bool begins_with(const char *s) const { return RTLIL::IdString(*this).begins_with(s); }
bool ends_with(const char *s) const { return RTLIL::IdString(*this).ends_with(s); }
template <typename... Ts> bool in(Ts &&...args) const {
return RTLIL::IdString(*this).in(std::forward<Ts>(args)...);
}
std::string substr(size_t pos = 0, size_t len = std::string::npos) const {
return RTLIL::IdString(*this).substr(pos, len);
}
size_t size() const { return RTLIL::IdString(*this).size(); }
bool contains(const char *p) const { return RTLIL::IdString(*this).contains(p); }
char operator[](int n) const { return RTLIL::IdString(*this).str()[n]; }
bool lt_by_name(RTLIL::IdString rhs) const { return RTLIL::IdString(*this).lt_by_name(rhs); }
bool lt_by_name(const WireNameMasq &rhs) const { return RTLIL::IdString(*this).lt_by_name(RTLIL::IdString(rhs)); }
bool operator==(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) == rhs; }
bool operator!=(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) != rhs; }
bool operator<(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) < rhs; }
bool operator==(const std::string &rhs) const { return RTLIL::IdString(*this) == rhs; }
bool operator!=(const std::string &rhs) const { return RTLIL::IdString(*this) != rhs; }
bool operator==(const WireNameMasq &rhs) const { return RTLIL::IdString(*this) == RTLIL::IdString(rhs); }
bool operator!=(const WireNameMasq &rhs) const { return RTLIL::IdString(*this) != RTLIL::IdString(rhs); }
bool operator<(const WireNameMasq &rhs) const { return RTLIL::IdString(*this) < RTLIL::IdString(rhs); }
[[nodiscard]] Hasher hash_into(Hasher h) const { return RTLIL::IdString(*this).hash_into(h); }
};
inline bool operator==(RTLIL::IdString lhs, const RTLIL::WireNameMasq &rhs) { return lhs == RTLIL::IdString(rhs); }
inline bool operator!=(RTLIL::IdString lhs, const RTLIL::WireNameMasq &rhs) { return lhs != RTLIL::IdString(rhs); }
// Read-only masquerade for Cell::name. Same contract as WireNameMasq.
struct RTLIL::CellNameMasq {
struct RTLIL::CellNameMasq : RTLIL::NameMasqBase<RTLIL::CellNameMasq> {
CellNameMasq() = default;
CellNameMasq(const CellNameMasq &) = delete;
CellNameMasq(CellNameMasq &&) = delete;
CellNameMasq &operator=(const CellNameMasq &) = delete;
CellNameMasq &operator=(CellNameMasq &&) = delete;
operator RTLIL::IdString() const;
// Tagged name handle (Twine::Null when unnamed).
TwineRef ref() const;
// Escaped form ('\'-prefixed when public) / bare content.
std::string escaped() const;
std::string unescaped() const;
bool isPublic() const { return twine_is_public(ref()); }
bool empty() const { return RTLIL::IdString(*this).empty(); }
std::string str() const { return escaped(); }
const char *c_str() const { return RTLIL::IdString(*this).c_str(); }
std::string unescape() const { return unescaped(); }
bool begins_with(const char *s) const { return RTLIL::IdString(*this).begins_with(s); }
bool ends_with(const char *s) const { return RTLIL::IdString(*this).ends_with(s); }
template <typename... Ts> bool in(Ts &&...args) const {
return RTLIL::IdString(*this).in(std::forward<Ts>(args)...);
}
std::string substr(size_t pos = 0, size_t len = std::string::npos) const {
return RTLIL::IdString(*this).substr(pos, len);
}
size_t size() const { return RTLIL::IdString(*this).size(); }
bool contains(const char *p) const { return RTLIL::IdString(*this).contains(p); }
char operator[](int n) const { return RTLIL::IdString(*this).str()[n]; }
bool lt_by_name(RTLIL::IdString rhs) const { return RTLIL::IdString(*this).lt_by_name(rhs); }
bool lt_by_name(const CellNameMasq &rhs) const { return RTLIL::IdString(*this).lt_by_name(RTLIL::IdString(rhs)); }
bool operator==(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) == rhs; }
bool operator!=(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) != rhs; }
bool operator<(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) < rhs; }
bool operator==(const std::string &rhs) const { return RTLIL::IdString(*this) == rhs; }
bool operator!=(const std::string &rhs) const { return RTLIL::IdString(*this) != rhs; }
bool operator==(const CellNameMasq &rhs) const { return RTLIL::IdString(*this) == RTLIL::IdString(rhs); }
bool operator!=(const CellNameMasq &rhs) const { return RTLIL::IdString(*this) != RTLIL::IdString(rhs); }
bool operator<(const CellNameMasq &rhs) const { return RTLIL::IdString(*this) < RTLIL::IdString(rhs); }
[[nodiscard]] Hasher hash_into(Hasher h) const { return RTLIL::IdString(*this).hash_into(h); }
};
inline bool operator==(RTLIL::IdString lhs, const RTLIL::CellNameMasq &rhs) { return lhs == RTLIL::IdString(rhs); }
inline bool operator!=(RTLIL::IdString lhs, const RTLIL::CellNameMasq &rhs) { return lhs != RTLIL::IdString(rhs); }
// Read-only masquerade for Cell::type. Backed by Cell::type_impl.
// Write the type via cell->type_impl directly.
@ -2935,12 +2936,12 @@ public:
RTLIL::SigBit Oai4Gate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, TwineRef src = Twine::Null);
};
// Zero-size masquerade for Module::name. Reads/writes route through
// module->design->obj_name(this) / obj_set_name. Shadows NamedObject::name
// Zero-size masquerade for Module::name. Same contract as WireNameMasq,
// plus a write path via operator=(IdString). Shadows NamedObject::name
// at the Module-instance scope; static_cast<NamedObject*>(module)->name
// still hits the (now-unused) inline base field. Writing requires
// module->design to be set first.
struct RTLIL::ModuleNameMasq {
struct RTLIL::ModuleNameMasq : RTLIL::NameMasqBase<RTLIL::ModuleNameMasq> {
// Copying/moving is forbidden: a ModuleNameMasq derives its identity from
// `this` via offsetof(Module, name), so any instance not embedded in a
// Module would resolve to garbage. All conversions go through
@ -2948,35 +2949,15 @@ struct RTLIL::ModuleNameMasq {
ModuleNameMasq() = default;
ModuleNameMasq(const ModuleNameMasq&) = delete;
ModuleNameMasq(ModuleNameMasq&&) = delete;
operator RTLIL::IdString() const;
operator TwineRef() const;
ModuleNameMasq& operator=(RTLIL::IdString id);
// Without this, `new_mod->name = src_mod->name` invokes the implicit
// copy-assign (no-op) instead of operator=(IdString), so the meta
// never gets written.
ModuleNameMasq& operator=(const ModuleNameMasq& other) { return *this = RTLIL::IdString(other); }
bool empty() const { return RTLIL::IdString(*this).empty(); }
std::string str() const { return RTLIL::IdString(*this).str(); }
const char* c_str() const { return RTLIL::IdString(*this).c_str(); }
bool isPublic() const { return RTLIL::IdString(*this).isPublic(); }
std::string unescape() const { return RTLIL::IdString(*this).unescape(); }
bool begins_with(const char* s) const { return RTLIL::IdString(*this).begins_with(s); }
bool ends_with(const char* s) const { return RTLIL::IdString(*this).ends_with(s); }
template<typename... Ts> bool in(Ts&&... args) const {
return RTLIL::IdString(*this).in(std::forward<Ts>(args)...);
}
std::string substr(size_t pos = 0, size_t len = std::string::npos) const {
return RTLIL::IdString(*this).substr(pos, len);
}
size_t size() const { return RTLIL::IdString(*this).size(); }
bool contains(const char *p) const { return RTLIL::IdString(*this).contains(p); }
bool operator==(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) == rhs; }
bool operator!=(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) != rhs; }
bool operator< (RTLIL::IdString rhs) const { return RTLIL::IdString(*this) < rhs; }
bool operator==(const std::string &rhs) const { return RTLIL::IdString(*this) == rhs; }
bool operator!=(const std::string &rhs) const { return RTLIL::IdString(*this) != rhs; }
bool operator==(const ModuleNameMasq &rhs) const { return RTLIL::IdString(*this) == RTLIL::IdString(rhs); }
bool operator!=(const ModuleNameMasq &rhs) const { return RTLIL::IdString(*this) != RTLIL::IdString(rhs); }
TwineRef ref() const;
std::string escaped() const;
std::string unescaped() const;
};
struct RTLIL::Module : public RTLIL::AttrObject, public CellAdderMixin<RTLIL::Module>
@ -3378,13 +3359,6 @@ inline std::string RTLIL::WireNameMasq::unescaped() const {
return w->module->design->twines.unescaped_str(id);
}
inline RTLIL::WireNameMasq::operator RTLIL::IdString() const {
std::string s = escaped();
if (s.empty())
return RTLIL::IdString{};
return RTLIL::IdString(s);
}
inline TwineRef RTLIL::CellNameMasq::ref() const {
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, name));
@ -3411,13 +3385,6 @@ inline std::string RTLIL::CellNameMasq::unescaped() const {
return c->module->design->twines.unescaped_str(id);
}
inline RTLIL::CellNameMasq::operator RTLIL::IdString() const {
std::string s = escaped();
if (s.empty())
return RTLIL::IdString{};
return RTLIL::IdString(s);
}
inline TwineRef RTLIL::CellTypeMasq::ref() const {
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, type));
@ -3456,13 +3423,33 @@ inline RTLIL::CellTypeMasq::operator RTLIL::IdString() const {
return RTLIL::IdString(s);
}
// inline RTLIL::ModuleNameMasq& RTLIL::ModuleNameMasq::operator=(RTLIL::IdString id) {
// RTLIL::Module *m = reinterpret_cast<RTLIL::Module*>(
// reinterpret_cast<char*>(this) - offsetof(RTLIL::Module, name));
// log_assert(m->design && "assignment to Module::name requires the module to be attached to a design");
// m->design->obj_set_name(m, id);
// return *this;
// }
inline TwineRef RTLIL::ModuleNameMasq::ref() const {
const RTLIL::Module *m = reinterpret_cast<const RTLIL::Module *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Module, name));
if (!m->design || !m->meta_)
return Twine::Null;
return m->meta_->name;
}
inline std::string RTLIL::ModuleNameMasq::escaped() const {
const RTLIL::Module *m = reinterpret_cast<const RTLIL::Module *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Module, name));
TwineRef id = ref();
if (id == Twine::Null)
return std::string();
return m->design->twines.str(id);
}
inline std::string RTLIL::ModuleNameMasq::unescaped() const {
const RTLIL::Module *m = reinterpret_cast<const RTLIL::Module *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Module, name));
TwineRef id = ref();
if (id == Twine::Null)
return std::string();
return m->design->twines.unescaped_str(id);
}
inline RTLIL::ModuleNameMasq::operator TwineRef() const { return ref(); }
YOSYS_NAMESPACE_END

View file

@ -100,13 +100,13 @@ static const char *attr_prefix(ScopeinfoAttrs attrs)
bool scopeinfo_has_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, RTLIL::IdString id)
{
log_assert(scopeinfo->type == TW($scopeinfo));
return scopeinfo->has_attribute(attr_prefix(attrs) + design->twines.unescaped_str(id));
return scopeinfo->has_attribute(attr_prefix(attrs) + RTLIL::unescape_id(id));
}
RTLIL::Const scopeinfo_get_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, RTLIL::IdString id)
{
log_assert(scopeinfo->type == TW($scopeinfo));
auto found = scopeinfo->attributes.find(attr_prefix(attrs) + design->twines.unescaped_str(id));
auto found = scopeinfo->attributes.find(attr_prefix(attrs) + RTLIL::unescape_id(id));
if (found == scopeinfo->attributes.end())
return RTLIL::Const();
return found->second;

View file

@ -196,6 +196,8 @@ struct TwinePool {
os << ", tail: \"" << val.tail << "\")";
}
}, twine.data);
if (ref.is_public())
os << " pub";
}
void print(TwineRef ref, std::ostream& os = std::cout) const {
if (ref == Twine::Null)
@ -302,29 +304,22 @@ struct TwinePool {
// and concat names inherit the prefix/first-child handle's publicity.
TwineRef add(Twine t) {
bool is_public = false;
if (auto *leaf = std::get_if<std::string>(&t.data)) {
assert(!leaf->empty());
if ((*leaf)[0] == '\\') {
is_public = true;
leaf->erase(0, 1);
assert(!leaf->empty());
} else {
assert((*leaf)[0] == '$');
}
} else if (auto *sfx = std::get_if<Twine::Suffix>(&t.data)) {
if (auto *sfx = std::get_if<Twine::Suffix>(&t.data)) {
is_public = twine_is_public(sfx->prefix);
} else if (auto *children = std::get_if<std::vector<TwineRef>>(&t.data)) {
is_public = false;
}
return twine_tag(add_inner(std::move(t)), is_public);
}
TwineRef add(std::string&& s) {
if (s.size()) {
if (s.size() > 1) {
if (s[0] == '\\')
return twine_tag(add(Twine{s.substr(1)}), true);
else if (s[0] == '$')
return twine_tag(add(Twine{std::move(s)}), false);
else
return twine_tag(add(Twine{std::move(s)}), true);
} else if (s.size() > 0) {
return twine_tag(add(Twine{std::move(s)}), true);
} else {
return Twine::Null;
}