2018-07-21 08:41:18 +02:00
|
|
|
/* -*- c++ -*-
|
2013-01-05 11:13:26 +01:00
|
|
|
* yosys -- Yosys Open SYnthesis Suite
|
|
|
|
|
*
|
2021-06-08 00:39:36 +02:00
|
|
|
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
|
2015-07-02 11:14:30 +02:00
|
|
|
*
|
2013-01-05 11:13:26 +01:00
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
2015-07-02 11:14:30 +02:00
|
|
|
*
|
2013-01-05 11:13:26 +01:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef RTLIL_H
|
|
|
|
|
#define RTLIL_H
|
|
|
|
|
|
2024-04-02 15:58:06 +02:00
|
|
|
#include "kernel/yosys_common.h"
|
|
|
|
|
#include "kernel/yosys.h"
|
2026-06-05 12:04:19 +02:00
|
|
|
#include "kernel/twine.h"
|
2024-04-02 15:58:06 +02:00
|
|
|
|
2026-06-05 18:50:58 +02:00
|
|
|
#include <deque>
|
2025-07-22 21:49:10 +02:00
|
|
|
#include <string_view>
|
|
|
|
|
#include <unordered_map>
|
|
|
|
|
|
2014-07-31 13:19:47 +02:00
|
|
|
YOSYS_NAMESPACE_BEGIN
|
|
|
|
|
|
2013-01-05 11:13:26 +01:00
|
|
|
namespace RTLIL
|
|
|
|
|
{
|
2014-07-27 02:00:04 +02:00
|
|
|
enum State : unsigned char {
|
2013-01-05 11:13:26 +01:00
|
|
|
S0 = 0,
|
|
|
|
|
S1 = 1,
|
|
|
|
|
Sx = 2, // undefined value or conflict
|
|
|
|
|
Sz = 3, // high-impedance / not-connected
|
|
|
|
|
Sa = 4, // don't care (used only in cases)
|
|
|
|
|
Sm = 5 // marker (used internally by some passes)
|
|
|
|
|
};
|
2013-12-04 14:14:05 +01:00
|
|
|
|
2014-07-27 02:00:04 +02:00
|
|
|
enum SyncType : unsigned char {
|
2013-01-05 11:13:26 +01:00
|
|
|
ST0 = 0, // level sensitive: 0
|
|
|
|
|
ST1 = 1, // level sensitive: 1
|
|
|
|
|
STp = 2, // edge sensitive: posedge
|
|
|
|
|
STn = 3, // edge sensitive: negedge
|
|
|
|
|
STe = 4, // edge sensitive: both edges
|
2013-11-21 13:49:00 +01:00
|
|
|
STa = 5, // always active
|
2016-10-14 12:33:56 +02:00
|
|
|
STg = 6, // global clock
|
|
|
|
|
STi = 7 // init
|
2013-01-05 11:13:26 +01:00
|
|
|
};
|
|
|
|
|
|
2024-10-09 19:39:45 +02:00
|
|
|
// Semantic metadata - how can this constant be interpreted?
|
|
|
|
|
// Values may be generally non-exclusive
|
2014-07-27 02:00:04 +02:00
|
|
|
enum ConstFlags : unsigned char {
|
2025-11-07 05:45:07 +01:00
|
|
|
CONST_FLAG_NONE = 0,
|
|
|
|
|
CONST_FLAG_STRING = 1,
|
|
|
|
|
CONST_FLAG_SIGNED = 2, // only used for parameters
|
|
|
|
|
CONST_FLAG_REAL = 4, // only used for parameters
|
|
|
|
|
CONST_FLAG_UNSIZED = 8, // only used for parameters
|
2013-12-04 14:14:05 +01:00
|
|
|
};
|
|
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
enum SelectPartials : unsigned char {
|
|
|
|
|
SELECT_ALL = 0, // include partial modules
|
|
|
|
|
SELECT_WHOLE_ONLY = 1, // ignore partial modules
|
|
|
|
|
SELECT_WHOLE_WARN = 2, // call log_warning on partial module
|
|
|
|
|
SELECT_WHOLE_ERR = 3, // call log_error on partial module
|
|
|
|
|
SELECT_WHOLE_CMDERR = 4 // call log_cmd_error on partial module
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum SelectBoxes : unsigned char {
|
|
|
|
|
SB_ALL = 0, // include boxed modules
|
2025-04-08 01:43:27 +02:00
|
|
|
SB_WARN = 1, // helper for log_warning (not for direct use)
|
|
|
|
|
SB_ERR = 2, // helper for log_error (not for direct use)
|
|
|
|
|
SB_CMDERR = 3, // helper for log_cmd_error (not for direct use)
|
2025-04-08 01:57:43 +02:00
|
|
|
SB_UNBOXED_ONLY = 4, // ignore boxed modules
|
|
|
|
|
SB_UNBOXED_WARN = 5, // call log_warning on boxed module
|
|
|
|
|
SB_UNBOXED_ERR = 6, // call log_error on boxed module
|
|
|
|
|
SB_UNBOXED_CMDERR = 7, // call log_cmd_error on boxed module
|
2025-04-08 01:43:27 +02:00
|
|
|
SB_INCL_WB = 8, // helper for white boxes (not for direct use)
|
2025-04-08 01:57:43 +02:00
|
|
|
SB_EXCL_BB_ONLY = 12, // ignore black boxes, but not white boxes
|
|
|
|
|
SB_EXCL_BB_WARN = 13, // call log_warning on black boxed module
|
|
|
|
|
SB_EXCL_BB_ERR = 14, // call log_error on black boxed module
|
|
|
|
|
SB_EXCL_BB_CMDERR = 15 // call log_cmd_error on black boxed module
|
|
|
|
|
};
|
|
|
|
|
|
2025-09-06 02:28:52 +02:00
|
|
|
enum class StaticId : short {
|
|
|
|
|
STATIC_ID_BEGIN = 0,
|
|
|
|
|
#define X(N) N,
|
|
|
|
|
#include "kernel/constids.inc"
|
|
|
|
|
#undef X
|
|
|
|
|
STATIC_ID_END,
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-09 18:50:00 +02:00
|
|
|
|
|
|
|
|
|
2025-08-14 16:13:43 +02:00
|
|
|
enum PortDir : unsigned char {
|
|
|
|
|
PD_UNKNOWN = 0,
|
|
|
|
|
PD_INPUT = 1,
|
|
|
|
|
PD_OUTPUT = 2,
|
|
|
|
|
PD_INOUT = 3
|
|
|
|
|
};
|
|
|
|
|
|
2013-01-05 11:13:26 +01:00
|
|
|
struct Const;
|
2015-04-24 22:04:05 +02:00
|
|
|
struct AttrObject;
|
2025-04-08 01:57:43 +02:00
|
|
|
struct NamedObject;
|
2013-01-05 11:13:26 +01:00
|
|
|
struct Selection;
|
2014-07-31 14:34:12 +02:00
|
|
|
struct Monitor;
|
2013-01-05 11:13:26 +01:00
|
|
|
struct Design;
|
|
|
|
|
struct Module;
|
2025-12-19 19:14:33 +01:00
|
|
|
struct Patch;
|
2013-01-05 11:13:26 +01:00
|
|
|
struct Wire;
|
|
|
|
|
struct Memory;
|
|
|
|
|
struct Cell;
|
|
|
|
|
struct SigChunk;
|
2013-11-22 04:07:13 +01:00
|
|
|
struct SigBit;
|
2014-07-22 23:49:26 +02:00
|
|
|
struct SigSpecIterator;
|
2014-07-27 14:47:23 +02:00
|
|
|
struct SigSpecConstIterator;
|
2013-01-05 11:13:26 +01:00
|
|
|
struct SigSpec;
|
|
|
|
|
struct CaseRule;
|
|
|
|
|
struct SwitchRule;
|
2021-02-23 00:21:46 +01:00
|
|
|
struct MemWriteAction;
|
2013-01-05 11:13:26 +01:00
|
|
|
struct SyncRule;
|
|
|
|
|
struct Process;
|
2020-04-20 17:06:53 +02:00
|
|
|
struct Binding;
|
2024-11-06 12:58:04 +01:00
|
|
|
struct IdString;
|
2025-10-10 01:28:10 +02:00
|
|
|
struct OwningIdString;
|
2025-10-06 14:39:25 +02:00
|
|
|
struct StaticIdString;
|
|
|
|
|
struct SigNormIndex;
|
2026-06-05 18:50:58 +02:00
|
|
|
struct ObjMeta;
|
2026-06-05 23:40:22 +02:00
|
|
|
struct ModuleNameMasq;
|
2026-06-08 23:40:51 +02:00
|
|
|
struct WireNameMasq;
|
|
|
|
|
struct CellNameMasq;
|
2026-06-11 20:02:02 +02:00
|
|
|
struct CellTypeMasq;
|
2013-01-05 11:13:26 +01:00
|
|
|
|
|
|
|
|
typedef std::pair<SigSpec, SigSpec> SigSig;
|
2025-10-06 14:39:25 +02:00
|
|
|
struct PortBit;
|
2024-11-06 12:58:04 +01:00
|
|
|
};
|
2013-01-05 11:13:26 +01:00
|
|
|
|
2026-06-05 12:04:19 +02:00
|
|
|
|
2026-05-06 12:14:48 +02:00
|
|
|
// TODO clean up?
|
|
|
|
|
extern int64_t signorm_ns;
|
|
|
|
|
extern int signorm_count;
|
|
|
|
|
extern int64_t signorm_restore_ns;
|
|
|
|
|
extern int signorm_restore_count;
|
|
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
struct RTLIL::IdString
|
|
|
|
|
{
|
2025-08-20 05:47:03 +02:00
|
|
|
struct Storage {
|
|
|
|
|
char *buf;
|
|
|
|
|
int size;
|
2025-10-13 22:51:35 +02:00
|
|
|
|
|
|
|
|
std::string_view str_view() const { return {buf, static_cast<size_t>(size)}; }
|
2025-08-20 05:47:03 +02:00
|
|
|
};
|
2025-11-25 01:47:11 +01:00
|
|
|
struct AutoidxStorage {
|
|
|
|
|
// Append the negated (i.e. positive) ID to this string to get
|
|
|
|
|
// the real string. The prefix strings must live forever.
|
|
|
|
|
const std::string *prefix;
|
|
|
|
|
// Cache of the full string, or nullptr if not cached yet.
|
2025-11-25 02:02:01 +01:00
|
|
|
std::atomic<char *> full_str;
|
|
|
|
|
|
|
|
|
|
AutoidxStorage(const std::string *prefix) : prefix(prefix), full_str(nullptr) {}
|
|
|
|
|
AutoidxStorage(AutoidxStorage&& other) : prefix(other.prefix), full_str(other.full_str.exchange(nullptr, std::memory_order_relaxed)) {}
|
|
|
|
|
~AutoidxStorage() { delete[] full_str.load(std::memory_order_acquire); }
|
2025-11-25 01:47:11 +01:00
|
|
|
};
|
2025-08-20 05:47:03 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
// the global id string cache
|
|
|
|
|
|
|
|
|
|
static bool destruct_guard_ok; // POD, will be initialized to zero
|
|
|
|
|
static struct destruct_guard_t {
|
|
|
|
|
destruct_guard_t() { destruct_guard_ok = true; }
|
|
|
|
|
~destruct_guard_t() { destruct_guard_ok = false; }
|
|
|
|
|
} destruct_guard;
|
|
|
|
|
|
2025-10-13 04:56:32 +02:00
|
|
|
// String storage for non-autoidx IDs
|
2025-08-20 05:47:03 +02:00
|
|
|
static std::vector<Storage> global_id_storage_;
|
2025-10-13 04:56:32 +02:00
|
|
|
// Lookup table for non-autoidx IDs
|
2025-07-22 21:49:10 +02:00
|
|
|
static std::unordered_map<std::string_view, int> global_id_index_;
|
2025-11-25 01:47:11 +01:00
|
|
|
// Storage for autoidx IDs, which have negative indices, i.e. all entries in this
|
|
|
|
|
// map have negative keys.
|
|
|
|
|
static std::unordered_map<int, AutoidxStorage> global_autoidx_id_storage_;
|
2025-10-13 02:12:51 +02:00
|
|
|
// All (index, refcount) pairs in this map have refcount > 0.
|
|
|
|
|
static std::unordered_map<int, int> global_refcount_storage_;
|
2024-11-06 12:58:04 +01:00
|
|
|
static std::vector<int> global_free_idx_list_;
|
2014-08-02 15:11:35 +02:00
|
|
|
|
2025-10-13 02:12:51 +02:00
|
|
|
static int refcount(int idx) {
|
|
|
|
|
auto it = global_refcount_storage_.find(idx);
|
|
|
|
|
if (it == global_refcount_storage_.end())
|
|
|
|
|
return 0;
|
|
|
|
|
return it->second;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
static inline void xtrace_db_dump()
|
|
|
|
|
{
|
|
|
|
|
#ifdef YOSYS_XTRACE_GET_PUT
|
|
|
|
|
for (int idx = 0; idx < GetSize(global_id_storage_); idx++)
|
|
|
|
|
{
|
2025-08-20 05:47:03 +02:00
|
|
|
if (global_id_storage_.at(idx).buf == nullptr)
|
2024-11-06 12:58:04 +01:00
|
|
|
log("#X# DB-DUMP index %d: FREE\n", idx);
|
|
|
|
|
else
|
2025-11-12 20:20:51 +01:00
|
|
|
log("#X# DB-DUMP index %d: '%s' (ref %u)\n", idx, global_id_storage_.at(idx).buf, refcount(idx));
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
2019-08-11 12:23:16 +02:00
|
|
|
#endif
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
2014-08-02 15:11:35 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
static inline void checkpoint()
|
|
|
|
|
{
|
|
|
|
|
#ifdef YOSYS_SORT_ID_FREE_LIST
|
|
|
|
|
std::sort(global_free_idx_list_.begin(), global_free_idx_list_.end(), std::greater<int>());
|
2019-08-10 11:41:09 +02:00
|
|
|
#endif
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
2019-03-11 20:12:28 +01:00
|
|
|
|
2025-10-10 03:10:33 +02:00
|
|
|
static int insert(std::string_view p)
|
2024-11-06 12:58:04 +01:00
|
|
|
{
|
|
|
|
|
log_assert(destruct_guard_ok);
|
2025-11-24 23:29:06 +01:00
|
|
|
log_assert(!Multithreading::active());
|
2019-03-11 20:12:28 +01:00
|
|
|
|
2025-09-12 06:58:39 +02:00
|
|
|
auto it = global_id_index_.find(p);
|
2024-11-06 12:58:04 +01:00
|
|
|
if (it != global_id_index_.end()) {
|
|
|
|
|
#ifdef YOSYS_XTRACE_GET_PUT
|
|
|
|
|
if (yosys_xtrace)
|
2025-10-13 02:12:51 +02:00
|
|
|
log("#X# GET-BY-NAME '%s' (index %d, refcount %u)\n", global_id_storage_.at(it->second).buf, it->second, refcount(it->second));
|
2024-11-06 12:58:04 +01:00
|
|
|
#endif
|
|
|
|
|
return it->second;
|
|
|
|
|
}
|
2025-10-13 04:56:32 +02:00
|
|
|
return really_insert(p, it);
|
|
|
|
|
}
|
2014-08-02 15:11:35 +02:00
|
|
|
|
2025-10-13 04:56:32 +02:00
|
|
|
// Inserts an ID with string `prefix + autoidx', incrementing autoidx.
|
|
|
|
|
// `prefix` must start with '$auto$', end with '$', and live forever.
|
|
|
|
|
static IdString new_autoidx_with_prefix(const std::string *prefix) {
|
2025-11-24 23:29:06 +01:00
|
|
|
log_assert(!Multithreading::active());
|
2025-10-13 04:56:32 +02:00
|
|
|
int index = -(autoidx++);
|
2025-11-25 02:02:01 +01:00
|
|
|
global_autoidx_id_storage_.insert({index, prefix});
|
2025-10-13 04:56:32 +02:00
|
|
|
return from_index(index);
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
2014-12-29 13:33:33 +01:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
// the actual IdString object is just is a single int
|
2014-08-02 15:11:35 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
int index_;
|
2014-08-02 15:11:35 +02:00
|
|
|
|
2025-10-14 03:00:20 +02:00
|
|
|
constexpr inline IdString() : index_(0) { }
|
2025-10-10 03:10:33 +02:00
|
|
|
inline IdString(const char *str) : index_(insert(std::string_view(str))) { }
|
2025-12-30 04:53:02 +01:00
|
|
|
constexpr IdString(const IdString &str) = default;
|
|
|
|
|
IdString(IdString &&str) = default;
|
2025-10-10 03:10:33 +02:00
|
|
|
inline IdString(const std::string &str) : index_(insert(std::string_view(str))) { }
|
|
|
|
|
inline IdString(std::string_view str) : index_(insert(str)) { }
|
2025-10-14 03:00:20 +02:00
|
|
|
constexpr inline IdString(StaticId id) : index_(static_cast<short>(id)) {}
|
2014-08-02 15:44:10 +02:00
|
|
|
|
2025-10-10 03:10:33 +02:00
|
|
|
IdString &operator=(const IdString &rhs) = default;
|
2025-09-12 06:59:20 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
inline void operator=(const char *rhs) {
|
|
|
|
|
IdString id(rhs);
|
|
|
|
|
*this = id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void operator=(const std::string &rhs) {
|
|
|
|
|
IdString id(rhs);
|
|
|
|
|
*this = id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline const char *c_str() const {
|
2025-10-13 04:56:32 +02:00
|
|
|
if (index_ >= 0)
|
|
|
|
|
return global_id_storage_.at(index_).buf;
|
|
|
|
|
|
2025-11-25 01:47:11 +01:00
|
|
|
AutoidxStorage &s = global_autoidx_id_storage_.at(index_);
|
2025-11-25 02:02:01 +01:00
|
|
|
char *full_str = s.full_str.load(std::memory_order_acquire);
|
|
|
|
|
if (full_str != nullptr)
|
|
|
|
|
return full_str;
|
2025-11-25 01:47:11 +01:00
|
|
|
const std::string &prefix = *s.prefix;
|
2025-10-13 04:56:32 +02:00
|
|
|
std::string suffix = std::to_string(-index_);
|
|
|
|
|
char *c = new char[prefix.size() + suffix.size() + 1];
|
|
|
|
|
memcpy(c, prefix.data(), prefix.size());
|
|
|
|
|
memcpy(c + prefix.size(), suffix.c_str(), suffix.size() + 1);
|
2025-11-25 02:02:01 +01:00
|
|
|
if (s.full_str.compare_exchange_strong(full_str, c, std::memory_order_acq_rel))
|
|
|
|
|
return c;
|
|
|
|
|
delete[] c;
|
|
|
|
|
return full_str;
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
2014-08-02 13:11:01 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
inline std::string str() const {
|
2025-10-13 04:56:32 +02:00
|
|
|
std::string result;
|
|
|
|
|
append_to(&result);
|
|
|
|
|
return result;
|
2025-08-20 05:47:03 +02:00
|
|
|
}
|
|
|
|
|
|
2025-10-13 04:56:32 +02:00
|
|
|
inline void append_to(std::string *out) const {
|
|
|
|
|
if (index_ >= 0) {
|
2025-10-13 22:51:35 +02:00
|
|
|
*out += global_id_storage_.at(index_).str_view();
|
2025-10-13 04:56:32 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2025-11-25 01:47:11 +01:00
|
|
|
*out += *global_autoidx_id_storage_.at(index_).prefix;
|
2025-10-13 04:56:32 +02:00
|
|
|
*out += std::to_string(-index_);
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
|
|
|
|
|
2026-01-28 19:13:12 +01:00
|
|
|
std::string unescape() const {
|
|
|
|
|
if (index_ < 0) {
|
|
|
|
|
// Must start with "$auto$" so no unescaping required.
|
|
|
|
|
return str();
|
|
|
|
|
}
|
|
|
|
|
std::string_view str = global_id_storage_.at(index_).str_view();
|
|
|
|
|
if (str.size() < 2 || str[0] != '\\' || str[1] == '$' || str[1] == '\\' || (str[1] >= '0' && str[1] <= '9'))
|
|
|
|
|
return std::string(str);
|
|
|
|
|
return std::string(str.substr(1));
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-13 22:51:35 +02:00
|
|
|
class Substrings {
|
|
|
|
|
std::string_view first_;
|
|
|
|
|
int suffix_number;
|
|
|
|
|
char buf[10];
|
|
|
|
|
public:
|
|
|
|
|
Substrings(const Storage &storage) : first_(storage.str_view()), suffix_number(-1) {}
|
|
|
|
|
// suffix_number must be non-negative
|
|
|
|
|
Substrings(const std::string *prefix, int suffix_number)
|
|
|
|
|
: first_(*prefix), suffix_number(suffix_number) {}
|
|
|
|
|
std::string_view first() { return first_; }
|
|
|
|
|
std::optional<std::string_view> next() {
|
|
|
|
|
if (suffix_number < 0)
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
int i = sizeof(buf);
|
|
|
|
|
do {
|
|
|
|
|
--i;
|
|
|
|
|
buf[i] = (suffix_number % 10) + '0';
|
|
|
|
|
suffix_number /= 10;
|
|
|
|
|
} while (suffix_number > 0);
|
|
|
|
|
suffix_number = -1;
|
|
|
|
|
return std::string_view(buf + i, sizeof(buf) - i);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class const_iterator {
|
|
|
|
|
const std::string *prefix;
|
|
|
|
|
std::string suffix;
|
|
|
|
|
const char *c_str;
|
|
|
|
|
int c_str_len;
|
|
|
|
|
// When this is INT_MAX it's the generic "end" value.
|
|
|
|
|
int index;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
using iterator_category = std::forward_iterator_tag;
|
|
|
|
|
using value_type = char;
|
|
|
|
|
using difference_type = std::ptrdiff_t;
|
|
|
|
|
using pointer = const char*;
|
|
|
|
|
using reference = const char&;
|
|
|
|
|
|
|
|
|
|
const_iterator(const Storage &storage) : prefix(nullptr), c_str(storage.buf), c_str_len(storage.size), index(0) {}
|
|
|
|
|
const_iterator(const std::string *prefix, int number) :
|
|
|
|
|
prefix(prefix), suffix(std::to_string(number)), c_str(nullptr), c_str_len(0), index(0) {}
|
|
|
|
|
// Construct end-marker
|
|
|
|
|
const_iterator() : prefix(nullptr), c_str(nullptr), c_str_len(0), index(INT_MAX) {}
|
|
|
|
|
|
|
|
|
|
int size() const {
|
|
|
|
|
if (c_str != nullptr)
|
|
|
|
|
return c_str_len;
|
|
|
|
|
return GetSize(*prefix) + GetSize(suffix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char operator*() const {
|
|
|
|
|
if (c_str != nullptr)
|
|
|
|
|
return c_str[index];
|
|
|
|
|
int prefix_size = GetSize(*prefix);
|
|
|
|
|
if (index < prefix_size)
|
|
|
|
|
return prefix->at(index);
|
|
|
|
|
return suffix[index - prefix_size];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const_iterator& operator++() { ++index; return *this; }
|
|
|
|
|
const_iterator operator++(int) { const_iterator result(*this); ++index; return result; }
|
|
|
|
|
const_iterator& operator+=(int i) { index += i; return *this; }
|
|
|
|
|
|
|
|
|
|
const_iterator operator+(int add) {
|
|
|
|
|
const_iterator result = *this;
|
|
|
|
|
result += add;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool operator==(const const_iterator& other) const {
|
|
|
|
|
return index == other.index || (other.index == INT_MAX && index == size())
|
|
|
|
|
|| (index == INT_MAX && other.index == other.size());
|
|
|
|
|
}
|
|
|
|
|
bool operator!=(const const_iterator& other) const {
|
|
|
|
|
return !(*this == other);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const_iterator begin() const {
|
|
|
|
|
if (index_ >= 0) {
|
|
|
|
|
return const_iterator(global_id_storage_.at(index_));
|
|
|
|
|
}
|
2025-11-25 01:47:11 +01:00
|
|
|
return const_iterator(global_autoidx_id_storage_.at(index_).prefix, -index_);
|
2025-10-13 22:51:35 +02:00
|
|
|
}
|
|
|
|
|
const_iterator end() const {
|
|
|
|
|
return const_iterator();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Substrings substrings() const {
|
|
|
|
|
if (index_ >= 0) {
|
|
|
|
|
return Substrings(global_id_storage_.at(index_));
|
|
|
|
|
}
|
2025-11-25 01:47:11 +01:00
|
|
|
return Substrings(global_autoidx_id_storage_.at(index_).prefix, -index_);
|
2025-10-13 22:51:35 +02:00
|
|
|
}
|
|
|
|
|
|
2025-12-22 02:52:59 +01:00
|
|
|
inline bool lt_by_name(IdString rhs) const {
|
2025-10-13 22:51:35 +02:00
|
|
|
Substrings lhs_it = substrings();
|
|
|
|
|
Substrings rhs_it = rhs.substrings();
|
|
|
|
|
std::string_view lhs_substr = lhs_it.first();
|
|
|
|
|
std::string_view rhs_substr = rhs_it.first();
|
|
|
|
|
while (true) {
|
|
|
|
|
int min = std::min(GetSize(lhs_substr), GetSize(rhs_substr));
|
|
|
|
|
int diff = memcmp(lhs_substr.data(), rhs_substr.data(), min);
|
|
|
|
|
if (diff != 0)
|
|
|
|
|
return diff < 0;
|
|
|
|
|
lhs_substr = lhs_substr.substr(min);
|
|
|
|
|
rhs_substr = rhs_substr.substr(min);
|
|
|
|
|
if (rhs_substr.empty()) {
|
|
|
|
|
if (std::optional<std::string_view> s = rhs_it.next())
|
|
|
|
|
rhs_substr = *s;
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (lhs_substr.empty()) {
|
|
|
|
|
if (std::optional<std::string_view> s = lhs_it.next())
|
|
|
|
|
lhs_substr = *s;
|
|
|
|
|
else
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-22 02:52:59 +01:00
|
|
|
inline bool operator<(IdString rhs) const {
|
2024-11-06 12:58:04 +01:00
|
|
|
return index_ < rhs.index_;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-22 02:52:59 +01:00
|
|
|
inline bool operator==(IdString rhs) const { return index_ == rhs.index_; }
|
|
|
|
|
inline bool operator!=(IdString rhs) const { return index_ != rhs.index_; }
|
2014-08-02 13:11:01 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
// The methods below are just convenience functions for better compatibility with std::string.
|
2014-08-02 13:11:01 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
bool operator==(const std::string &rhs) const { return c_str() == rhs; }
|
|
|
|
|
bool operator!=(const std::string &rhs) const { return c_str() != rhs; }
|
2014-08-02 15:11:35 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
bool operator==(const char *rhs) const { return strcmp(c_str(), rhs) == 0; }
|
|
|
|
|
bool operator!=(const char *rhs) const { return strcmp(c_str(), rhs) != 0; }
|
2014-08-02 13:11:01 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
char operator[](size_t i) const {
|
2025-10-13 22:51:35 +02:00
|
|
|
if (index_ >= 0) {
|
|
|
|
|
const Storage &storage = global_id_storage_.at(index_);
|
2023-10-03 00:57:18 +02:00
|
|
|
#ifndef NDEBUG
|
2025-10-13 22:51:35 +02:00
|
|
|
log_assert(static_cast<int>(i) < storage.size);
|
2023-10-03 00:57:18 +02:00
|
|
|
#endif
|
2025-10-13 22:51:35 +02:00
|
|
|
return *(storage.buf + i);
|
|
|
|
|
}
|
2025-11-25 01:47:11 +01:00
|
|
|
const std::string &id_start = *global_autoidx_id_storage_.at(index_).prefix;
|
2025-10-13 22:51:35 +02:00
|
|
|
if (i < id_start.size())
|
|
|
|
|
return id_start[i];
|
|
|
|
|
i -= id_start.size();
|
|
|
|
|
std::string suffix = std::to_string(-index_);
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
// Allow indexing to access the trailing null.
|
|
|
|
|
log_assert(i <= suffix.size());
|
|
|
|
|
#endif
|
|
|
|
|
return suffix[i];
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
2014-08-02 18:58:40 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
std::string substr(size_t pos = 0, size_t len = std::string::npos) const {
|
2025-10-13 22:51:35 +02:00
|
|
|
std::string result;
|
|
|
|
|
const_iterator it = begin() + pos;
|
|
|
|
|
const_iterator end_it = end();
|
|
|
|
|
if (len != std::string::npos && len < it.size() - pos) {
|
|
|
|
|
end_it = it + len;
|
|
|
|
|
}
|
|
|
|
|
std::copy(it, end_it, std::back_inserter(result));
|
|
|
|
|
return result;
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
2014-08-02 15:44:10 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
int compare(size_t pos, size_t len, const char* s) const {
|
2025-10-13 22:51:35 +02:00
|
|
|
const_iterator it = begin() + pos;
|
|
|
|
|
const_iterator end_it = end();
|
|
|
|
|
while (len > 0 && *s != 0 && it != end_it) {
|
|
|
|
|
int diff = *it - *s;
|
|
|
|
|
if (diff != 0)
|
|
|
|
|
return diff;
|
|
|
|
|
++it;
|
|
|
|
|
++s;
|
|
|
|
|
--len;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
2019-08-07 01:42:25 +02:00
|
|
|
|
2025-10-16 05:37:49 +02:00
|
|
|
bool begins_with(std::string_view prefix) const {
|
2025-10-13 22:51:35 +02:00
|
|
|
Substrings it = substrings();
|
|
|
|
|
std::string_view substr = it.first();
|
|
|
|
|
while (true) {
|
|
|
|
|
int min = std::min(GetSize(substr), GetSize(prefix));
|
|
|
|
|
if (memcmp(substr.data(), prefix.data(), min) != 0)
|
|
|
|
|
return false;
|
|
|
|
|
prefix = prefix.substr(min);
|
|
|
|
|
if (prefix.empty())
|
|
|
|
|
return true;
|
|
|
|
|
substr = substr.substr(min);
|
|
|
|
|
if (substr.empty()) {
|
|
|
|
|
if (std::optional<std::string_view> s = it.next())
|
|
|
|
|
substr = *s;
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
2019-06-14 21:25:06 +02:00
|
|
|
|
2025-10-16 05:37:49 +02:00
|
|
|
bool ends_with(std::string_view suffix) const {
|
|
|
|
|
size_t sz = size();
|
|
|
|
|
if (sz < suffix.size()) return false;
|
|
|
|
|
return compare(sz - suffix.size(), suffix.size(), suffix.data()) == 0;
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
2019-02-26 21:04:16 +01:00
|
|
|
|
2025-10-16 06:05:56 +02:00
|
|
|
bool contains(std::string_view s) const {
|
2025-10-13 22:51:35 +02:00
|
|
|
if (index_ >= 0)
|
|
|
|
|
return global_id_storage_.at(index_).str_view().find(s) != std::string::npos;
|
|
|
|
|
return str().find(s) != std::string::npos;
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
verilog: significant block scoping improvements
This change set contains a number of bug fixes and improvements related to
scoping and resolution in generate and procedural blocks. While many of the
frontend changes are interdependent, it may be possible bring the techmap
changes in under a separate PR.
Declarations within unnamed generate blocks previously encountered issues
because the data declarations were left un-prefixed, breaking proper scoping.
The LRM outlines behavior for generating names for unnamed generate blocks. The
original goal was to add this implicit labelling, but doing so exposed a number
of issues downstream. Additional testing highlighted other closely related scope
resolution issues, which have been fixed. This change also adds support for
block item declarations within unnamed blocks in SystemVerilog mode.
1. Unlabled generate blocks are now implicitly named according to the LRM in
`label_genblks`, which is invoked at the beginning of module elaboration
2. The Verilog parser no longer wraps explicitly named generate blocks in a
synthetic unnamed generate block to avoid creating extra hierarchy levels
where they should not exist
3. The techmap phase now allows special control identifiers to be used outside
of the topmost scope, which is necessary because such wires and cells often
appear in unlabeled generate blocks, which now prefix the declarations within
4. Some techlibs required modifications because they relied on the previous
invalid scope resolution behavior
5. `expand_genblock` has been simplified, now only expanding the outermost
scope, completely deferring the inspection and elaboration of nested scopes;
names are now resolved by looking in the innermost scope and stepping outward
6. Loop variables now always become localparams during unrolling, allowing them
to be resolved and shadowed like any other identifier
7. Identifiers in synthetic function call scopes are now prefixed and resolved
in largely the same manner as other blocks
before: `$func$\func_01$tests/simple/scopes.blk.v:60$5$\blk\x`
after: `\func_01$func$tests/simple/scopes.v:60$5.blk.x`
8. Support identifiers referencing a local generate scope nested more
than 1 level deep, i.e. `B.C.x` while within generate scope `A`, or using a
prefix of a current or parent scope, i.e. `B.C.D.x` while in `A.B`, `A.B.C`,
or `A.B.C.D`
9. Variables can now be declared within unnamed blocks in SystemVerilog mode
Addresses the following issues: 656, 2423, 2493
2021-01-27 19:30:22 +01:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
size_t size() const {
|
2025-10-13 22:51:35 +02:00
|
|
|
return begin().size();
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
2014-08-02 15:44:10 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
bool empty() const {
|
2025-10-01 04:47:47 +02:00
|
|
|
return index_ == 0;
|
2024-11-06 12:58:04 +01:00
|
|
|
}
|
2014-08-02 15:44:10 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
void clear() {
|
|
|
|
|
*this = IdString();
|
|
|
|
|
}
|
2014-08-02 16:03:18 +02:00
|
|
|
|
2025-01-14 12:39:15 +01:00
|
|
|
[[nodiscard]] Hasher hash_into(Hasher h) const { return hash_ops<int>::hash_into(index_, h); }
|
2024-10-30 10:49:17 +01:00
|
|
|
|
2025-01-14 12:48:59 +01:00
|
|
|
[[nodiscard]] Hasher hash_top() const {
|
2024-11-06 12:58:04 +01:00
|
|
|
Hasher h;
|
|
|
|
|
h.force((Hasher::hash_t) index_);
|
|
|
|
|
return h;
|
|
|
|
|
}
|
2014-12-26 21:35:22 +01:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
// The following is a helper key_compare class. Instead of for example std::set<Cell*>
|
|
|
|
|
// use std::set<Cell*, IdString::compare_ptr_by_name<Cell>> if the order of cells in the
|
|
|
|
|
// set has an influence on the algorithm.
|
2014-08-02 16:03:18 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
template<typename T> struct compare_ptr_by_name {
|
|
|
|
|
bool operator()(const T *a, const T *b) const {
|
|
|
|
|
return (a == nullptr || b == nullptr) ? (a < b) : (a->name < b->name);
|
|
|
|
|
}
|
|
|
|
|
};
|
2014-08-04 15:08:35 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
// often one needs to check if a given IdString is part of a list (for example a list
|
|
|
|
|
// of cell types). the following functions helps with that.
|
|
|
|
|
template<typename... Args>
|
2025-09-02 04:43:03 +02:00
|
|
|
bool in(const Args &... args) const {
|
2024-11-06 12:58:04 +01:00
|
|
|
return (... || in(args));
|
|
|
|
|
}
|
2014-08-04 15:08:35 +02:00
|
|
|
|
2025-12-22 02:52:59 +01:00
|
|
|
bool in(IdString rhs) const { return *this == rhs; }
|
2024-11-06 12:58:04 +01:00
|
|
|
bool in(const char *rhs) const { return *this == rhs; }
|
|
|
|
|
bool in(const std::string &rhs) const { return *this == rhs; }
|
|
|
|
|
inline bool in(const pool<IdString> &rhs) const;
|
|
|
|
|
inline bool in(const pool<IdString> &&rhs) const;
|
2014-08-04 15:08:35 +02:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
bool isPublic() const { return begins_with("\\"); }
|
2025-09-06 02:28:52 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
static void prepopulate();
|
2025-10-13 04:56:32 +02:00
|
|
|
static int really_insert(std::string_view p, std::unordered_map<std::string_view, int>::iterator &it);
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
static IdString from_index(int index) {
|
|
|
|
|
IdString result;
|
|
|
|
|
result.index_ = index;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2025-09-08 13:33:46 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
static void ensure_prepopulated() {
|
|
|
|
|
if (global_id_index_.empty())
|
|
|
|
|
prepopulate();
|
|
|
|
|
}
|
2026-06-08 23:40:51 +02:00
|
|
|
|
|
|
|
|
// Thread-safe read-only pool lookup for use while Multithreading::active().
|
|
|
|
|
// global_id_index_ is stable (no writes) during parallel passes, so
|
|
|
|
|
// concurrent find() calls are safe. Returns empty IdString if not found.
|
|
|
|
|
static IdString lookup_threadsafe(std::string_view p) {
|
|
|
|
|
auto it = global_id_index_.find(p);
|
|
|
|
|
return from_index(it != global_id_index_.end() ? it->second : 0);
|
|
|
|
|
}
|
2024-11-06 12:58:04 +01:00
|
|
|
};
|
2020-09-03 17:37:58 +02:00
|
|
|
|
2026-06-11 20:02:02 +02:00
|
|
|
inline bool operator==(TwineRef a, RTLIL::IdString b) { return a.untag().value == (size_t)(unsigned)b.index_; }
|
|
|
|
|
inline bool operator==(RTLIL::IdString a, TwineRef b) { return b == a; }
|
|
|
|
|
|
2025-10-10 01:28:10 +02:00
|
|
|
struct RTLIL::OwningIdString : public RTLIL::IdString {
|
|
|
|
|
inline OwningIdString() { }
|
2025-10-10 03:10:33 +02:00
|
|
|
inline OwningIdString(const OwningIdString &str) : IdString(str) { get_reference(); }
|
|
|
|
|
inline OwningIdString(const char *str) : IdString(str) { get_reference(); }
|
|
|
|
|
inline OwningIdString(const IdString &str) : IdString(str) { get_reference(); }
|
|
|
|
|
inline OwningIdString(IdString &&str) : IdString(str) { get_reference(); }
|
|
|
|
|
inline OwningIdString(const std::string &str) : IdString(str) { get_reference(); }
|
|
|
|
|
inline OwningIdString(std::string_view str) : IdString(str) { get_reference(); }
|
|
|
|
|
inline OwningIdString(StaticId id) : IdString(id) {}
|
|
|
|
|
inline ~OwningIdString() {
|
|
|
|
|
put_reference();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline OwningIdString &operator=(const OwningIdString &rhs) {
|
|
|
|
|
put_reference();
|
|
|
|
|
index_ = rhs.index_;
|
|
|
|
|
get_reference();
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
inline OwningIdString &operator=(const IdString &rhs) {
|
|
|
|
|
put_reference();
|
|
|
|
|
index_ = rhs.index_;
|
|
|
|
|
get_reference();
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
inline OwningIdString &operator=(OwningIdString &&rhs) {
|
|
|
|
|
std::swap(index_, rhs.index_);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Collect all non-owning references.
|
2025-11-14 15:32:10 +01:00
|
|
|
static void collect_garbage();
|
2025-10-17 01:15:53 +02:00
|
|
|
static int64_t garbage_collection_ns() { return gc_ns; }
|
|
|
|
|
static int garbage_collection_count() { return gc_count; }
|
2025-10-10 03:10:33 +02:00
|
|
|
|
|
|
|
|
// Used by the ID() macro to create an IdString with no destructor whose string will
|
|
|
|
|
// never be released. If ID() creates a closure-static `OwningIdString` then
|
|
|
|
|
// initialization of the static registers its destructor to run at exit, which is
|
|
|
|
|
// wasteful.
|
|
|
|
|
static IdString immortal(const char* str) {
|
|
|
|
|
IdString result(str);
|
|
|
|
|
get_reference(result.index_);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
private:
|
2025-10-17 01:15:53 +02:00
|
|
|
static int64_t gc_ns;
|
|
|
|
|
static int gc_count;
|
|
|
|
|
|
2025-10-10 03:10:33 +02:00
|
|
|
void get_reference()
|
|
|
|
|
{
|
|
|
|
|
get_reference(index_);
|
|
|
|
|
}
|
|
|
|
|
static void get_reference(int idx)
|
|
|
|
|
{
|
2025-11-24 23:29:06 +01:00
|
|
|
log_assert(!Multithreading::active());
|
|
|
|
|
|
2025-10-13 02:12:51 +02:00
|
|
|
if (idx < static_cast<short>(StaticId::STATIC_ID_END))
|
|
|
|
|
return;
|
|
|
|
|
auto it = global_refcount_storage_.find(idx);
|
|
|
|
|
if (it == global_refcount_storage_.end())
|
|
|
|
|
global_refcount_storage_.insert(it, {idx, 1});
|
|
|
|
|
else
|
|
|
|
|
++it->second;
|
2025-10-10 03:10:33 +02:00
|
|
|
#ifdef YOSYS_XTRACE_GET_PUT
|
|
|
|
|
if (yosys_xtrace && idx >= static_cast<short>(StaticId::STATIC_ID_END))
|
2025-10-13 04:56:32 +02:00
|
|
|
log("#X# GET-BY-INDEX '%s' (index %d, refcount %u)\n", from_index(idx), idx, refcount(idx));
|
2025-10-10 03:10:33 +02:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void put_reference()
|
|
|
|
|
{
|
2025-11-24 23:29:06 +01:00
|
|
|
log_assert(!Multithreading::active());
|
|
|
|
|
|
2025-10-10 03:10:33 +02:00
|
|
|
// put_reference() may be called from destructors after the destructor of
|
|
|
|
|
// global_refcount_storage_ has been run. in this case we simply do nothing.
|
|
|
|
|
if (index_ < static_cast<short>(StaticId::STATIC_ID_END) || !destruct_guard_ok)
|
|
|
|
|
return;
|
|
|
|
|
#ifdef YOSYS_XTRACE_GET_PUT
|
2025-10-13 02:12:51 +02:00
|
|
|
if (yosys_xtrace)
|
2025-10-13 04:56:32 +02:00
|
|
|
log("#X# PUT '%s' (index %d, refcount %u)\n", from_index(index_), index_, refcount(index_));
|
2025-10-10 03:10:33 +02:00
|
|
|
#endif
|
2025-10-13 02:12:51 +02:00
|
|
|
auto it = global_refcount_storage_.find(index_);
|
|
|
|
|
log_assert(it != global_refcount_storage_.end() && it->second >= 1);
|
|
|
|
|
if (--it->second == 0) {
|
|
|
|
|
global_refcount_storage_.erase(it);
|
|
|
|
|
}
|
2025-10-10 03:10:33 +02:00
|
|
|
}
|
2025-10-10 01:28:10 +02:00
|
|
|
};
|
|
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
namespace hashlib {
|
|
|
|
|
template <>
|
2025-01-13 20:21:05 +01:00
|
|
|
struct hash_ops<RTLIL::IdString> {
|
2025-12-22 02:52:59 +01:00
|
|
|
static inline bool cmp(RTLIL::IdString a, RTLIL::IdString b) {
|
2024-11-06 12:58:04 +01:00
|
|
|
return a == b;
|
|
|
|
|
}
|
2025-12-22 02:52:59 +01:00
|
|
|
[[nodiscard]] static inline Hasher hash(RTLIL::IdString id) {
|
2024-11-06 12:58:04 +01:00
|
|
|
return id.hash_top();
|
|
|
|
|
}
|
2025-12-22 02:52:59 +01:00
|
|
|
[[nodiscard]] static inline Hasher hash_into(RTLIL::IdString id, Hasher h) {
|
2025-01-13 20:21:05 +01:00
|
|
|
return id.hash_into(h);
|
|
|
|
|
}
|
2014-08-02 00:45:25 +02:00
|
|
|
};
|
2024-11-06 12:58:04 +01:00
|
|
|
};
|
|
|
|
|
|
2024-11-20 17:06:49 +01:00
|
|
|
/**
|
|
|
|
|
* How to not use these methods:
|
|
|
|
|
* 1. if(celltype.in({...})) -> if(celltype.in(...))
|
|
|
|
|
* 2. pool<IdString> p; ... a.in(p) -> (bool)p.count(a)
|
|
|
|
|
*/
|
|
|
|
|
[[deprecated]]
|
2024-11-06 12:58:04 +01:00
|
|
|
inline bool RTLIL::IdString::in(const pool<IdString> &rhs) const { return rhs.count(*this) != 0; }
|
2024-11-20 17:06:49 +01:00
|
|
|
[[deprecated]]
|
2024-11-06 12:58:04 +01:00
|
|
|
inline bool RTLIL::IdString::in(const pool<IdString> &&rhs) const { return rhs.count(*this) != 0; }
|
2013-01-05 11:13:26 +01:00
|
|
|
|
2024-11-06 12:58:04 +01:00
|
|
|
namespace RTLIL {
|
2025-09-23 05:25:16 +02:00
|
|
|
namespace ID {
|
2025-10-14 03:00:20 +02:00
|
|
|
#define X(_id) constexpr IdString _id(StaticId::_id);
|
2025-09-23 05:25:16 +02:00
|
|
|
#include "kernel/constids.inc"
|
2020-03-12 20:54:30 +01:00
|
|
|
#undef X
|
2025-09-06 02:28:52 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct IdTableEntry {
|
|
|
|
|
const std::string_view name;
|
2025-10-14 03:00:20 +02:00
|
|
|
const RTLIL::IdString static_id;
|
2025-09-06 02:28:52 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
constexpr IdTableEntry IdTable[] = {
|
2025-09-23 05:25:16 +02:00
|
|
|
#define X(_id) {#_id, ID::_id},
|
2025-09-06 02:28:52 +02:00
|
|
|
#include "kernel/constids.inc"
|
|
|
|
|
#undef X
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
constexpr int lookup_well_known_id(std::string_view name)
|
|
|
|
|
{
|
|
|
|
|
int low = 0;
|
|
|
|
|
int high = sizeof(IdTable) / sizeof(IdTable[0]);
|
|
|
|
|
while (high - low >= 2) {
|
|
|
|
|
int mid = (low + high) / 2;
|
|
|
|
|
if (name < IdTable[mid].name)
|
|
|
|
|
high = mid;
|
|
|
|
|
else
|
|
|
|
|
low = mid;
|
|
|
|
|
}
|
|
|
|
|
if (IdTable[low].name == name)
|
|
|
|
|
return low;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-12 00:18:53 +02:00
|
|
|
// Create a statically allocated IdString object, using for example ID::A or TW($add).
|
2025-09-06 02:28:52 +02:00
|
|
|
//
|
|
|
|
|
// Recipe for Converting old code that is using conversion of strings like ID::A and
|
|
|
|
|
// "$add" for creating IdStrings: Run below SED command on the .cc file and then use for
|
|
|
|
|
// example "meld foo.cc foo.cc.orig" to manually compile errors, if necessary.
|
|
|
|
|
//
|
|
|
|
|
// sed -i.orig -r 's/"\\\\([a-zA-Z0-9_]+)"/ID(\1)/g; s/"(\$[a-zA-Z0-9_]+)"/ID(\1)/g;' <filename>
|
|
|
|
|
//
|
2025-10-14 03:00:20 +02:00
|
|
|
typedef RTLIL::IdString IDMacroHelperFunc();
|
2025-09-06 02:28:52 +02:00
|
|
|
|
|
|
|
|
template <int IdTableIndex> struct IDMacroHelper {
|
2025-10-14 03:00:20 +02:00
|
|
|
static constexpr RTLIL::IdString eval(IDMacroHelperFunc) {
|
2025-09-06 02:28:52 +02:00
|
|
|
return IdTable[IdTableIndex].static_id;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
template <> struct IDMacroHelper<-1> {
|
2025-10-14 03:00:20 +02:00
|
|
|
static constexpr RTLIL::IdString eval(IDMacroHelperFunc func) {
|
2025-09-06 02:28:52 +02:00
|
|
|
return func();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-10-31 09:36:00 +01:00
|
|
|
#undef ID
|
2025-09-08 11:34:53 +02:00
|
|
|
#define ID(_id) \
|
|
|
|
|
YOSYS_NAMESPACE_PREFIX IDMacroHelper< \
|
|
|
|
|
YOSYS_NAMESPACE_PREFIX lookup_well_known_id(#_id) \
|
|
|
|
|
>::eval([]() \
|
2025-10-14 03:00:20 +02:00
|
|
|
-> YOSYS_NAMESPACE_PREFIX RTLIL::IdString { \
|
2025-09-08 11:34:53 +02:00
|
|
|
const char *p = "\\" #_id, *q = p[1] == '$' ? p+1 : p; \
|
2025-10-10 03:10:33 +02:00
|
|
|
static const YOSYS_NAMESPACE_PREFIX RTLIL::IdString id = \
|
|
|
|
|
YOSYS_NAMESPACE_PREFIX RTLIL::OwningIdString::immortal(q); \
|
2025-09-08 11:34:53 +02:00
|
|
|
return id; \
|
2025-09-06 02:28:52 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
namespace RTLIL {
|
2020-01-07 21:52:03 +01:00
|
|
|
extern dict<std::string, std::string> constpad;
|
|
|
|
|
|
2026-03-02 12:11:25 +01:00
|
|
|
[[deprecated("use StaticCellTypes::categories.is_ff() instead")]]
|
2026-06-11 20:02:02 +02:00
|
|
|
const pool<TwineRef> &builtin_ff_cell_types();
|
2026-03-02 12:11:25 +01:00
|
|
|
|
2020-03-18 19:21:53 +01:00
|
|
|
static inline std::string escape_id(const std::string &str) {
|
2013-01-05 11:13:26 +01:00
|
|
|
if (str.size() > 0 && str[0] != '\\' && str[0] != '$')
|
|
|
|
|
return "\\" + str;
|
|
|
|
|
return str;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-18 19:21:53 +01:00
|
|
|
static inline std::string unescape_id(const std::string &str) {
|
2015-01-30 22:51:16 +01:00
|
|
|
if (str.size() < 2)
|
|
|
|
|
return str;
|
|
|
|
|
if (str[0] != '\\')
|
|
|
|
|
return str;
|
|
|
|
|
if (str[1] == '$' || str[1] == '\\')
|
|
|
|
|
return str;
|
|
|
|
|
if (str[1] >= '0' && str[1] <= '9')
|
|
|
|
|
return str;
|
|
|
|
|
return str.substr(1);
|
2013-01-05 11:13:26 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-22 02:52:59 +01:00
|
|
|
static inline std::string unescape_id(RTLIL::IdString str) {
|
2026-01-28 19:13:12 +01:00
|
|
|
return str.unescape();
|
2014-08-02 00:45:25 +02:00
|
|
|
}
|
|
|
|
|
|
2025-12-22 02:52:59 +01:00
|
|
|
static inline const char *id2cstr(RTLIL::IdString str) {
|
2014-08-02 16:03:18 +02:00
|
|
|
return log_id(str);
|
2014-08-02 00:45:25 +02:00
|
|
|
}
|
|
|
|
|
|
2026-06-10 19:22:53 +02:00
|
|
|
template <typename T> struct sort_by_name {
|
2013-08-09 12:42:32 +02:00
|
|
|
bool operator()(T *a, T *b) const {
|
|
|
|
|
return a->name < b->name;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2014-08-15 02:40:46 +02:00
|
|
|
template <typename T> struct sort_by_name_str {
|
|
|
|
|
bool operator()(T *a, T *b) const {
|
2025-10-13 22:51:35 +02:00
|
|
|
return a->name.lt_by_name(b->name);
|
2014-08-15 02:40:46 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct sort_by_id_str {
|
2025-12-22 02:52:59 +01:00
|
|
|
bool operator()(RTLIL::IdString a, RTLIL::IdString b) const {
|
2025-10-13 22:51:35 +02:00
|
|
|
return a.lt_by_name(b);
|
2014-08-15 02:40:46 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2022-08-08 16:13:33 +02:00
|
|
|
static inline std::string encode_filename(const std::string &filename)
|
|
|
|
|
{
|
|
|
|
|
std::stringstream val;
|
2023-07-26 21:50:55 +02:00
|
|
|
if (!std::any_of(filename.begin(), filename.end(), [](char c) {
|
|
|
|
|
return static_cast<unsigned char>(c) < 33 || static_cast<unsigned char>(c) > 126;
|
2022-08-08 16:13:33 +02:00
|
|
|
})) return filename;
|
|
|
|
|
for (unsigned char const c : filename) {
|
|
|
|
|
if (c < 33 || c > 126)
|
|
|
|
|
val << stringf("$%02x", c);
|
2023-07-26 21:50:55 +02:00
|
|
|
else
|
2022-08-08 16:13:33 +02:00
|
|
|
val << c;
|
|
|
|
|
}
|
|
|
|
|
return val.str();
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-05 11:13:26 +01:00
|
|
|
// see calc.cc for the implementation of this functions
|
|
|
|
|
RTLIL::Const const_not (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_and (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_or (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_xor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_xnor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
|
|
|
|
|
RTLIL::Const const_reduce_and (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_reduce_or (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_reduce_xor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_reduce_xnor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_reduce_bool (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
|
|
|
|
|
RTLIL::Const const_logic_not (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_logic_and (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_logic_or (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
|
|
|
|
|
RTLIL::Const const_shl (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_shr (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_sshl (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_sshr (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
2014-07-29 14:42:33 +02:00
|
|
|
RTLIL::Const const_shift (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_shiftx (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
2013-01-05 11:13:26 +01:00
|
|
|
|
|
|
|
|
RTLIL::Const const_lt (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_le (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_eq (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_ne (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
2013-12-27 13:50:08 +01:00
|
|
|
RTLIL::Const const_eqx (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_nex (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
2013-01-05 11:13:26 +01:00
|
|
|
RTLIL::Const const_ge (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_gt (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
|
|
|
|
|
RTLIL::Const const_add (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_sub (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_mul (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_div (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
2020-04-21 12:51:58 +02:00
|
|
|
RTLIL::Const const_divfloor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
2020-04-08 19:30:47 +02:00
|
|
|
RTLIL::Const const_modfloor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
2013-01-05 11:13:26 +01:00
|
|
|
RTLIL::Const const_mod (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
RTLIL::Const const_pow (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
|
|
|
|
|
|
|
|
|
RTLIL::Const const_pos (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
2023-09-29 07:03:23 +02:00
|
|
|
RTLIL::Const const_buf (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
2013-01-05 11:13:26 +01:00
|
|
|
RTLIL::Const const_neg (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
|
2014-07-27 10:13:22 +02:00
|
|
|
|
2022-10-21 15:41:20 +02:00
|
|
|
RTLIL::Const const_mux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3);
|
|
|
|
|
RTLIL::Const const_pmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3);
|
2022-01-24 16:02:29 +01:00
|
|
|
RTLIL::Const const_bmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2);
|
|
|
|
|
RTLIL::Const const_demux (const RTLIL::Const &arg1, const RTLIL::Const &arg2);
|
|
|
|
|
|
2022-11-02 17:12:51 +01:00
|
|
|
RTLIL::Const const_bweqx (const RTLIL::Const &arg1, const RTLIL::Const &arg2);
|
|
|
|
|
RTLIL::Const const_bwmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3);
|
|
|
|
|
|
2014-07-27 10:13:22 +02:00
|
|
|
|
|
|
|
|
// This iterator-range-pair is used for Design::modules(), Module::wires() and Module::cells().
|
|
|
|
|
// It maintains a reference counter that is used to make sure that the container is not modified while being iterated over.
|
|
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
template<typename T, typename Key = RTLIL::IdString>
|
2019-07-25 09:51:09 +02:00
|
|
|
struct ObjIterator {
|
|
|
|
|
using iterator_category = std::forward_iterator_tag;
|
|
|
|
|
using value_type = T;
|
|
|
|
|
using difference_type = ptrdiff_t;
|
|
|
|
|
using pointer = T*;
|
|
|
|
|
using reference = T&;
|
2026-06-08 23:40:51 +02:00
|
|
|
typename dict<Key, T>::iterator it;
|
|
|
|
|
dict<Key, T> *list_p;
|
2014-07-27 10:13:22 +02:00
|
|
|
int *refcount_p;
|
|
|
|
|
|
|
|
|
|
ObjIterator() : list_p(nullptr), refcount_p(nullptr) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ObjIterator(decltype(list_p) list_p, int *refcount_p) : list_p(list_p), refcount_p(refcount_p) {
|
|
|
|
|
if (list_p->empty()) {
|
|
|
|
|
this->list_p = nullptr;
|
|
|
|
|
this->refcount_p = nullptr;
|
|
|
|
|
} else {
|
|
|
|
|
it = list_p->begin();
|
|
|
|
|
(*refcount_p)++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
ObjIterator(const RTLIL::ObjIterator<T, Key> &other) {
|
2014-07-27 10:13:22 +02:00
|
|
|
it = other.it;
|
|
|
|
|
list_p = other.list_p;
|
|
|
|
|
refcount_p = other.refcount_p;
|
|
|
|
|
if (refcount_p)
|
|
|
|
|
(*refcount_p)++;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
ObjIterator &operator=(const RTLIL::ObjIterator<T, Key> &other) {
|
2014-07-27 10:13:22 +02:00
|
|
|
if (refcount_p)
|
|
|
|
|
(*refcount_p)--;
|
|
|
|
|
it = other.it;
|
|
|
|
|
list_p = other.list_p;
|
|
|
|
|
refcount_p = other.refcount_p;
|
|
|
|
|
if (refcount_p)
|
|
|
|
|
(*refcount_p)++;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~ObjIterator() {
|
|
|
|
|
if (refcount_p)
|
|
|
|
|
(*refcount_p)--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline T operator*() const {
|
2014-07-28 11:08:55 +02:00
|
|
|
log_assert(list_p != nullptr);
|
2014-07-27 10:13:22 +02:00
|
|
|
return it->second;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
inline bool operator!=(const RTLIL::ObjIterator<T, Key> &other) const {
|
2014-07-27 10:13:22 +02:00
|
|
|
if (list_p == nullptr || other.list_p == nullptr)
|
|
|
|
|
return list_p != other.list_p;
|
|
|
|
|
return it != other.it;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-24 13:33:07 +02:00
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
inline bool operator==(const RTLIL::ObjIterator<T, Key> &other) const {
|
2019-07-24 13:33:07 +02:00
|
|
|
return !(*this != other);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
inline ObjIterator<T, Key>& operator++() {
|
2014-07-28 11:08:55 +02:00
|
|
|
log_assert(list_p != nullptr);
|
2014-07-27 10:13:22 +02:00
|
|
|
if (++it == list_p->end()) {
|
|
|
|
|
(*refcount_p)--;
|
|
|
|
|
list_p = nullptr;
|
|
|
|
|
refcount_p = nullptr;
|
|
|
|
|
}
|
2019-07-24 13:33:07 +02:00
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
inline ObjIterator<T, Key>& operator+=(int amt) {
|
2020-06-18 00:32:34 +02:00
|
|
|
log_assert(list_p != nullptr);
|
|
|
|
|
it += amt;
|
|
|
|
|
if (it == list_p->end()) {
|
|
|
|
|
(*refcount_p)--;
|
|
|
|
|
list_p = nullptr;
|
|
|
|
|
refcount_p = nullptr;
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
inline ObjIterator<T, Key> operator+(int amt) {
|
2020-06-18 00:32:34 +02:00
|
|
|
log_assert(list_p != nullptr);
|
2026-06-08 23:40:51 +02:00
|
|
|
ObjIterator<T, Key> new_obj(*this);
|
2020-06-18 00:32:34 +02:00
|
|
|
new_obj.it += amt;
|
|
|
|
|
if (new_obj.it == list_p->end()) {
|
|
|
|
|
(*(new_obj.refcount_p))--;
|
|
|
|
|
new_obj.list_p = nullptr;
|
|
|
|
|
new_obj.refcount_p = nullptr;
|
|
|
|
|
}
|
|
|
|
|
return new_obj;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
inline const ObjIterator<T, Key> operator++(int) {
|
|
|
|
|
ObjIterator<T, Key> result(*this);
|
2019-07-24 13:33:07 +02:00
|
|
|
++(*this);
|
|
|
|
|
return result;
|
2014-07-27 10:13:22 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
template<typename T, typename Key = RTLIL::IdString>
|
2014-07-27 10:13:22 +02:00
|
|
|
struct ObjRange
|
|
|
|
|
{
|
2026-06-08 23:40:51 +02:00
|
|
|
dict<Key, T> *list_p;
|
2014-07-27 10:13:22 +02:00
|
|
|
int *refcount_p;
|
|
|
|
|
|
|
|
|
|
ObjRange(decltype(list_p) list_p, int *refcount_p) : list_p(list_p), refcount_p(refcount_p) { }
|
2026-06-08 23:40:51 +02:00
|
|
|
RTLIL::ObjIterator<T, Key> begin() { return RTLIL::ObjIterator<T, Key>(list_p, refcount_p); }
|
|
|
|
|
RTLIL::ObjIterator<T, Key> end() { return RTLIL::ObjIterator<T, Key>(); }
|
2014-07-27 10:41:06 +02:00
|
|
|
|
2014-07-31 14:11:39 +02:00
|
|
|
size_t size() const {
|
|
|
|
|
return list_p->size();
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-26 21:59:41 +01:00
|
|
|
operator pool<T>() const {
|
|
|
|
|
pool<T> result;
|
2014-07-27 10:41:06 +02:00
|
|
|
for (auto &it : *list_p)
|
|
|
|
|
result.insert(it.second);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
operator std::vector<T>() const {
|
|
|
|
|
std::vector<T> result;
|
|
|
|
|
result.reserve(list_p->size());
|
|
|
|
|
for (auto &it : *list_p)
|
|
|
|
|
result.push_back(it.second);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2014-07-30 22:04:30 +02:00
|
|
|
|
2015-01-19 13:59:08 +01:00
|
|
|
pool<T> to_pool() const { return *this; }
|
2014-07-30 22:04:30 +02:00
|
|
|
std::vector<T> to_vector() const { return *this; }
|
2014-07-27 10:13:22 +02:00
|
|
|
};
|
2013-01-05 11:13:26 +01:00
|
|
|
};
|
|
|
|
|
|
2014-07-27 02:00:04 +02:00
|
|
|
struct RTLIL::Const
|
|
|
|
|
{
|
2024-10-18 11:31:20 +02:00
|
|
|
short int flags;
|
2024-10-09 19:39:45 +02:00
|
|
|
private:
|
|
|
|
|
friend class KernelRtlilTest;
|
|
|
|
|
FRIEND_TEST(KernelRtlilTest, ConstStr);
|
|
|
|
|
using bitvectype = std::vector<RTLIL::State>;
|
|
|
|
|
enum class backing_tag: bool { bits, string };
|
|
|
|
|
// Do not access the union or tag even in Const methods unless necessary
|
2025-08-29 07:56:19 +02:00
|
|
|
backing_tag tag;
|
2024-10-09 19:39:45 +02:00
|
|
|
union {
|
2025-08-29 07:56:19 +02:00
|
|
|
bitvectype bits_;
|
|
|
|
|
std::string str_;
|
2024-10-09 19:39:45 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Use these private utilities instead
|
|
|
|
|
bool is_bits() const { return tag == backing_tag::bits; }
|
|
|
|
|
bool is_str() const { return tag == backing_tag::string; }
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2025-08-29 07:56:19 +02:00
|
|
|
bitvectype* get_if_bits() { return is_bits() ? &bits_ : NULL; }
|
|
|
|
|
std::string* get_if_str() { return is_str() ? &str_ : NULL; }
|
|
|
|
|
const bitvectype* get_if_bits() const { return is_bits() ? &bits_ : NULL; }
|
|
|
|
|
const std::string* get_if_str() const { return is_str() ? &str_ : NULL; }
|
2024-10-09 19:39:45 +02:00
|
|
|
|
2025-08-29 07:56:19 +02:00
|
|
|
bitvectype& get_bits();
|
|
|
|
|
std::string& get_str();
|
|
|
|
|
const bitvectype& get_bits() const;
|
|
|
|
|
const std::string& get_str() const;
|
2025-08-28 07:21:21 +02:00
|
|
|
std::vector<RTLIL::State>& bits_internal();
|
2025-08-29 07:56:19 +02:00
|
|
|
void bitvectorize_internal();
|
2025-08-28 07:21:21 +02:00
|
|
|
|
2024-10-09 19:39:45 +02:00
|
|
|
public:
|
|
|
|
|
Const() : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::vector<RTLIL::State>()) {}
|
2025-09-12 06:57:08 +02:00
|
|
|
Const(std::string str);
|
2025-08-29 05:08:31 +02:00
|
|
|
Const(long long val); // default width is 32
|
|
|
|
|
Const(long long val, int width);
|
2013-01-05 11:13:26 +01:00
|
|
|
Const(RTLIL::State bit, int width = 1);
|
2025-08-28 03:54:41 +02:00
|
|
|
Const(std::vector<RTLIL::State> bits) : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::move(bits)) {}
|
2014-09-19 15:50:55 +02:00
|
|
|
Const(const std::vector<bool> &bits);
|
2024-10-09 19:39:45 +02:00
|
|
|
Const(const RTLIL::Const &other);
|
|
|
|
|
Const(RTLIL::Const &&other);
|
|
|
|
|
RTLIL::Const &operator =(const RTLIL::Const &other);
|
|
|
|
|
~Const();
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2025-08-28 03:54:41 +02:00
|
|
|
struct Builder
|
|
|
|
|
{
|
|
|
|
|
Builder() {}
|
|
|
|
|
Builder(int expected_width) { bits.reserve(expected_width); }
|
|
|
|
|
void push_back(RTLIL::State b) { bits.push_back(b); }
|
|
|
|
|
int size() const { return static_cast<int>(bits.size()); }
|
|
|
|
|
Const build() { return Const(std::move(bits)); }
|
|
|
|
|
private:
|
|
|
|
|
std::vector<RTLIL::State> bits;
|
|
|
|
|
};
|
|
|
|
|
|
2013-01-05 11:13:26 +01:00
|
|
|
bool operator <(const RTLIL::Const &other) const;
|
|
|
|
|
bool operator ==(const RTLIL::Const &other) const;
|
|
|
|
|
bool operator !=(const RTLIL::Const &other) const;
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2025-08-28 08:00:50 +02:00
|
|
|
[[deprecated("Don't use direct access to the internal std::vector<State>, that's an implementation detail.")]]
|
2025-08-28 07:21:21 +02:00
|
|
|
std::vector<RTLIL::State>& bits() { return bits_internal(); }
|
2025-08-28 08:00:50 +02:00
|
|
|
[[deprecated("Don't call bitvectorize() directly, it's an implementation detail.")]]
|
2025-08-29 07:56:19 +02:00
|
|
|
void bitvectorize() const { const_cast<Const*>(this)->bitvectorize_internal(); }
|
2025-08-28 08:00:50 +02:00
|
|
|
|
2013-01-05 11:13:26 +01:00
|
|
|
bool as_bool() const;
|
2025-05-21 13:20:08 +02:00
|
|
|
|
|
|
|
|
// Convert the constant value to a C++ int.
|
|
|
|
|
// NOTE: If the constant is too wide to fit in int (32 bits) this will
|
|
|
|
|
// truncate any higher bits, potentially over/underflowing. Consider using
|
|
|
|
|
// try_as_int, as_int_saturating, or guarding behind convertible_to_int
|
|
|
|
|
// instead.
|
2014-08-24 15:14:00 +02:00
|
|
|
int as_int(bool is_signed = false) const;
|
2025-05-21 13:20:08 +02:00
|
|
|
|
|
|
|
|
// Returns true iff the constant can be converted to an int without
|
|
|
|
|
// over/underflow.
|
2025-05-07 14:36:48 +02:00
|
|
|
bool convertible_to_int(bool is_signed = false) const;
|
2025-05-21 13:20:08 +02:00
|
|
|
|
|
|
|
|
// Returns the constant's value as an int if it can be represented without
|
|
|
|
|
// over/underflow, or std::nullopt otherwise.
|
2025-05-07 14:36:48 +02:00
|
|
|
std::optional<int> try_as_int(bool is_signed = false) const;
|
2025-05-21 13:20:08 +02:00
|
|
|
|
|
|
|
|
// Returns the constant's value as an int if it can be represented without
|
|
|
|
|
// over/underflow, otherwise the max/min value for int depending on the sign.
|
2025-05-07 14:36:48 +02:00
|
|
|
int as_int_saturating(bool is_signed = false) const;
|
2025-05-21 13:20:08 +02:00
|
|
|
|
2024-10-09 19:39:45 +02:00
|
|
|
std::string as_string(const char* any = "-") const;
|
2020-03-18 19:21:53 +01:00
|
|
|
static Const from_string(const std::string &str);
|
2024-10-09 19:39:45 +02:00
|
|
|
std::vector<RTLIL::State> to_bits() const;
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2013-12-04 14:14:05 +01:00
|
|
|
std::string decode_string() const;
|
2024-10-09 19:39:45 +02:00
|
|
|
int size() const;
|
|
|
|
|
bool empty() const;
|
|
|
|
|
|
2024-12-13 18:59:35 +01:00
|
|
|
void append(const RTLIL::Const &other);
|
2025-08-28 03:54:41 +02:00
|
|
|
void set(int i, RTLIL::State state) {
|
2025-08-28 07:21:21 +02:00
|
|
|
bits_internal()[i] = state;
|
2025-08-28 03:54:41 +02:00
|
|
|
}
|
|
|
|
|
void resize(int size, RTLIL::State fill) {
|
2025-08-28 07:21:21 +02:00
|
|
|
bits_internal().resize(size, fill);
|
2025-08-28 03:54:41 +02:00
|
|
|
}
|
2024-12-13 18:59:35 +01:00
|
|
|
|
2024-10-09 19:39:45 +02:00
|
|
|
class const_iterator {
|
|
|
|
|
private:
|
2025-08-29 06:34:41 +02:00
|
|
|
const Const* parent;
|
2024-10-09 19:39:45 +02:00
|
|
|
size_t idx;
|
|
|
|
|
|
|
|
|
|
public:
|
2025-08-29 06:34:41 +02:00
|
|
|
using iterator_category = std::bidirectional_iterator_tag;
|
2024-10-09 19:39:45 +02:00
|
|
|
using value_type = State;
|
|
|
|
|
using difference_type = std::ptrdiff_t;
|
|
|
|
|
using pointer = const State*;
|
|
|
|
|
using reference = const State&;
|
2014-08-31 18:07:48 +02:00
|
|
|
|
2025-08-29 06:34:41 +02:00
|
|
|
const_iterator(const Const& c, size_t i) : parent(&c), idx(i) {}
|
2024-10-09 19:39:45 +02:00
|
|
|
|
|
|
|
|
State operator*() const;
|
|
|
|
|
|
|
|
|
|
const_iterator& operator++() { ++idx; return *this; }
|
|
|
|
|
const_iterator& operator--() { --idx; return *this; }
|
2025-08-29 06:33:14 +02:00
|
|
|
const_iterator operator++(int) { const_iterator result(*this); ++idx; return result; }
|
|
|
|
|
const_iterator operator--(int) { const_iterator result(*this); --idx; return result; }
|
2024-10-09 19:39:45 +02:00
|
|
|
const_iterator& operator+=(int i) { idx += i; return *this; }
|
|
|
|
|
|
|
|
|
|
const_iterator operator+(int add) {
|
2025-08-29 06:34:41 +02:00
|
|
|
return const_iterator(*parent, idx + add);
|
2024-10-09 19:39:45 +02:00
|
|
|
}
|
|
|
|
|
const_iterator operator-(int sub) {
|
2025-08-29 06:34:41 +02:00
|
|
|
return const_iterator(*parent, idx - sub);
|
2024-10-09 19:39:45 +02:00
|
|
|
}
|
|
|
|
|
int operator-(const const_iterator& other) {
|
|
|
|
|
return idx - other.idx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool operator==(const const_iterator& other) const {
|
|
|
|
|
return idx == other.idx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool operator!=(const const_iterator& other) const {
|
|
|
|
|
return !(*this == other);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-28 03:54:41 +02:00
|
|
|
class iterator {
|
|
|
|
|
private:
|
|
|
|
|
Const* parent;
|
|
|
|
|
size_t idx;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
class proxy {
|
|
|
|
|
private:
|
|
|
|
|
Const* parent;
|
|
|
|
|
size_t idx;
|
|
|
|
|
public:
|
|
|
|
|
proxy(Const* parent, size_t idx) : parent(parent), idx(idx) {}
|
|
|
|
|
operator State() const { return (*parent)[idx]; }
|
|
|
|
|
proxy& operator=(State s) { parent->set(idx, s); return *this; }
|
|
|
|
|
proxy& operator=(const proxy& other) { parent->set(idx, (*other.parent)[other.idx]); return *this; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using iterator_category = std::bidirectional_iterator_tag;
|
|
|
|
|
using value_type = State;
|
|
|
|
|
using difference_type = std::ptrdiff_t;
|
|
|
|
|
using pointer = proxy*;
|
|
|
|
|
using reference = proxy;
|
|
|
|
|
|
|
|
|
|
iterator(Const& c, size_t i) : parent(&c), idx(i) {}
|
|
|
|
|
|
|
|
|
|
proxy operator*() const { return proxy(parent, idx); }
|
|
|
|
|
iterator& operator++() { ++idx; return *this; }
|
|
|
|
|
iterator& operator--() { --idx; return *this; }
|
|
|
|
|
iterator operator++(int) { iterator result(*this); ++idx; return result; }
|
|
|
|
|
iterator operator--(int) { iterator result(*this); --idx; return result; }
|
|
|
|
|
iterator& operator+=(int i) { idx += i; return *this; }
|
|
|
|
|
|
|
|
|
|
iterator operator+(int add) {
|
|
|
|
|
return iterator(*parent, idx + add);
|
|
|
|
|
}
|
|
|
|
|
iterator operator-(int sub) {
|
|
|
|
|
return iterator(*parent, idx - sub);
|
|
|
|
|
}
|
|
|
|
|
int operator-(const iterator& other) {
|
|
|
|
|
return idx - other.idx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool operator==(const iterator& other) const {
|
|
|
|
|
return idx == other.idx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool operator!=(const iterator& other) const {
|
|
|
|
|
return !(*this == other);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-10-09 19:39:45 +02:00
|
|
|
const_iterator begin() const {
|
|
|
|
|
return const_iterator(*this, 0);
|
|
|
|
|
}
|
|
|
|
|
const_iterator end() const {
|
|
|
|
|
return const_iterator(*this, size());
|
|
|
|
|
}
|
2025-08-28 03:54:41 +02:00
|
|
|
iterator begin() {
|
|
|
|
|
return iterator(*this, 0);
|
|
|
|
|
}
|
|
|
|
|
iterator end() {
|
|
|
|
|
return iterator(*this, size());
|
|
|
|
|
}
|
2024-10-09 19:39:45 +02:00
|
|
|
State back() const {
|
|
|
|
|
return *(end() - 1);
|
|
|
|
|
}
|
|
|
|
|
State front() const {
|
|
|
|
|
return *begin();
|
|
|
|
|
}
|
|
|
|
|
State at(size_t i) const {
|
|
|
|
|
return *const_iterator(*this, i);
|
|
|
|
|
}
|
|
|
|
|
State operator[](size_t i) const {
|
|
|
|
|
return *const_iterator(*this, i);
|
|
|
|
|
}
|
2015-04-06 17:06:15 +02:00
|
|
|
|
2017-08-18 11:40:08 +02:00
|
|
|
bool is_fully_zero() const;
|
2017-12-14 02:06:39 +01:00
|
|
|
bool is_fully_ones() const;
|
2017-08-18 11:40:08 +02:00
|
|
|
bool is_fully_def() const;
|
|
|
|
|
bool is_fully_undef() const;
|
2023-01-29 13:54:02 +01:00
|
|
|
bool is_fully_undef_x_only() const;
|
2021-06-09 18:41:57 +02:00
|
|
|
bool is_onehot(int *pos = nullptr) const;
|
2017-08-18 11:40:08 +02:00
|
|
|
|
2024-10-09 19:39:45 +02:00
|
|
|
RTLIL::Const extract(int offset, int len = 1, RTLIL::State padding = RTLIL::State::S0) const;
|
2014-12-29 02:01:42 +01:00
|
|
|
|
2024-09-23 13:57:07 +02:00
|
|
|
// find the MSB without redundant leading bits
|
2024-11-29 00:31:34 +01:00
|
|
|
int get_min_size(bool is_signed) const;
|
2024-09-23 13:57:07 +02:00
|
|
|
|
2024-09-19 18:06:42 +02:00
|
|
|
// compress representation to the minimum required bits
|
|
|
|
|
void compress(bool is_signed = false);
|
|
|
|
|
|
2024-09-23 13:57:07 +02:00
|
|
|
std::optional<int> as_int_compress(bool is_signed) const;
|
|
|
|
|
|
2019-03-23 14:38:48 +01:00
|
|
|
void extu(int width) {
|
2025-08-28 03:54:41 +02:00
|
|
|
resize(width, RTLIL::State::S0);
|
2019-03-23 14:38:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void exts(int width) {
|
2025-08-28 03:54:41 +02:00
|
|
|
resize(width, empty() ? RTLIL::State::Sx : back());
|
2019-03-23 14:38:48 +01:00
|
|
|
}
|
|
|
|
|
|
2025-08-29 05:48:16 +02:00
|
|
|
[[nodiscard]] Hasher hash_into(Hasher h) const;
|
2013-01-05 11:13:26 +01:00
|
|
|
};
|
|
|
|
|
|
2026-06-05 18:50:58 +02:00
|
|
|
struct RTLIL::ObjMeta
|
|
|
|
|
{
|
2026-06-09 18:50:00 +02:00
|
|
|
TwineRef src = Twine::Null;
|
2026-06-08 23:40:51 +02:00
|
|
|
// RTLIL::IdString name; // used by Module names
|
2026-06-10 19:22:53 +02:00
|
|
|
TwineRef name = Twine::Null; // used by Wire/Cell names (per-Design twines)
|
2026-06-05 18:50:58 +02:00
|
|
|
};
|
|
|
|
|
|
2015-04-24 22:04:05 +02:00
|
|
|
struct RTLIL::AttrObject
|
|
|
|
|
{
|
|
|
|
|
dict<RTLIL::IdString, RTLIL::Const> attributes;
|
|
|
|
|
|
2026-06-05 18:50:58 +02:00
|
|
|
// Pointer to a per-object metadata record in some pool (typically
|
|
|
|
|
// the owning Design's). Nullable: cleared until first non-null write
|
|
|
|
|
// of any field (src or name) and reset to null when all fields empty.
|
|
|
|
|
RTLIL::ObjMeta *meta_ = nullptr;
|
2026-06-05 12:04:19 +02:00
|
|
|
|
2025-12-22 02:52:59 +01:00
|
|
|
bool has_attribute(RTLIL::IdString id) const;
|
2020-04-16 23:49:49 +02:00
|
|
|
|
2025-12-22 02:52:59 +01:00
|
|
|
void set_bool_attribute(RTLIL::IdString id, bool value=true);
|
|
|
|
|
bool get_bool_attribute(RTLIL::IdString id) const;
|
2017-08-30 11:39:11 +02:00
|
|
|
|
2024-11-27 23:19:16 +01:00
|
|
|
[[deprecated("Use Module::get_blackbox_attribute() instead.")]]
|
2019-04-18 19:19:45 +02:00
|
|
|
bool get_blackbox_attribute(bool ignore_wb=false) const {
|
2019-08-10 12:24:16 +02:00
|
|
|
return get_bool_attribute(ID::blackbox) || (!ignore_wb && get_bool_attribute(ID::whitebox));
|
2019-04-18 17:42:12 +02:00
|
|
|
}
|
|
|
|
|
|
2025-12-22 02:52:59 +01:00
|
|
|
void set_string_attribute(RTLIL::IdString id, string value);
|
|
|
|
|
string get_string_attribute(RTLIL::IdString id) const;
|
2020-04-16 23:43:03 +02:00
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
// static std::string strpool_attribute_to_str(const pool<string> &data);
|
|
|
|
|
// void set_strpool_attribute(IdString id, const pool<string> &data);
|
|
|
|
|
// void add_strpool_attribute(IdString id, const pool<string> &data);
|
|
|
|
|
// pool<string> get_strpool_attribute(RTLIL::IdString id) const;
|
2017-08-30 11:39:11 +02:00
|
|
|
|
2020-06-04 12:46:54 +02:00
|
|
|
void set_hdlname_attribute(const vector<string> &hierarchy);
|
|
|
|
|
vector<string> get_hdlname_attribute() const;
|
2021-11-24 22:21:08 +01:00
|
|
|
|
2025-12-22 02:52:59 +01:00
|
|
|
void set_intvec_attribute(RTLIL::IdString id, const vector<int> &data);
|
|
|
|
|
vector<int> get_intvec_attribute(RTLIL::IdString id) const;
|
2015-04-24 22:04:05 +02:00
|
|
|
};
|
|
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
struct RTLIL::NamedObject : public RTLIL::AttrObject
|
|
|
|
|
{
|
|
|
|
|
RTLIL::IdString name;
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-09 18:50:00 +02:00
|
|
|
// Read-only masquerade for Wire::name. Reads materialise the TwineRef in
|
2026-06-08 23:40:51 +02:00
|
|
|
// 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 {
|
|
|
|
|
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;
|
2026-06-11 20:02:02 +02:00
|
|
|
// 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()); }
|
2026-06-08 23:40:51 +02:00
|
|
|
bool empty() const { return RTLIL::IdString(*this).empty(); }
|
2026-06-11 20:02:02 +02:00
|
|
|
std::string str() const { return escaped(); }
|
2026-06-08 23:40:51 +02:00
|
|
|
const char *c_str() const { return RTLIL::IdString(*this).c_str(); }
|
2026-06-11 20:02:02 +02:00
|
|
|
std::string unescape() const { return unescaped(); }
|
2026-06-08 23:40:51 +02:00
|
|
|
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 {
|
|
|
|
|
CellNameMasq() = default;
|
|
|
|
|
CellNameMasq(const CellNameMasq &) = delete;
|
|
|
|
|
CellNameMasq(CellNameMasq &&) = delete;
|
|
|
|
|
CellNameMasq &operator=(const CellNameMasq &) = delete;
|
|
|
|
|
CellNameMasq &operator=(CellNameMasq &&) = delete;
|
|
|
|
|
operator RTLIL::IdString() const;
|
2026-06-11 20:02:02 +02:00
|
|
|
// 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()); }
|
2026-06-08 23:40:51 +02:00
|
|
|
bool empty() const { return RTLIL::IdString(*this).empty(); }
|
2026-06-11 20:02:02 +02:00
|
|
|
std::string str() const { return escaped(); }
|
2026-06-08 23:40:51 +02:00
|
|
|
const char *c_str() const { return RTLIL::IdString(*this).c_str(); }
|
2026-06-11 20:02:02 +02:00
|
|
|
std::string unescape() const { return unescaped(); }
|
2026-06-08 23:40:51 +02:00
|
|
|
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); }
|
|
|
|
|
|
2026-06-11 20:02:02 +02:00
|
|
|
// Read-only masquerade for Cell::type. Backed by Cell::type_impl.
|
|
|
|
|
// Write the type via cell->type_impl directly.
|
|
|
|
|
struct RTLIL::CellTypeMasq {
|
|
|
|
|
CellTypeMasq() = default;
|
|
|
|
|
CellTypeMasq(const CellTypeMasq &) = delete;
|
|
|
|
|
CellTypeMasq(CellTypeMasq &&) = delete;
|
|
|
|
|
CellTypeMasq &operator=(const CellTypeMasq &) = delete;
|
|
|
|
|
CellTypeMasq &operator=(CellTypeMasq &&) = delete;
|
|
|
|
|
operator RTLIL::IdString() const;
|
|
|
|
|
explicit operator TwineRef() const { return ref(); }
|
|
|
|
|
TwineRef ref() const;
|
|
|
|
|
std::string escaped() const;
|
|
|
|
|
std::string unescaped() const;
|
|
|
|
|
bool isPublic() const { return twine_is_public(ref()); }
|
|
|
|
|
bool empty() const { return ref() == Twine::Null; }
|
|
|
|
|
std::string str() const { return escaped(); } // TODO deprecate
|
|
|
|
|
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 ref().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 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==(TwineRef rhs) const { return ref() == rhs; }
|
|
|
|
|
bool operator!=(TwineRef rhs) const { return ref() != 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 CellTypeMasq &rhs) const { return ref() == rhs.ref(); }
|
|
|
|
|
bool operator!=(const CellTypeMasq &rhs) const { return ref() != rhs.ref(); }
|
|
|
|
|
[[nodiscard]] Hasher hash_into(Hasher h) const { return RTLIL::IdString(*this).hash_into(h); }
|
|
|
|
|
};
|
|
|
|
|
inline bool operator==(RTLIL::IdString lhs, const RTLIL::CellTypeMasq &rhs) { return lhs == RTLIL::IdString(rhs); }
|
|
|
|
|
inline bool operator!=(RTLIL::IdString lhs, const RTLIL::CellTypeMasq &rhs) { return lhs != RTLIL::IdString(rhs); }
|
|
|
|
|
inline bool operator==(TwineRef lhs, const RTLIL::CellTypeMasq &rhs) { return lhs == rhs.ref(); }
|
|
|
|
|
inline bool operator!=(TwineRef lhs, const RTLIL::CellTypeMasq &rhs) { return lhs != rhs.ref(); }
|
|
|
|
|
|
2014-12-26 10:53:21 +01:00
|
|
|
struct RTLIL::SigChunk
|
|
|
|
|
{
|
|
|
|
|
RTLIL::Wire *wire;
|
|
|
|
|
std::vector<RTLIL::State> data; // only used if wire == NULL, LSB at index 0
|
|
|
|
|
int width, offset;
|
|
|
|
|
|
2022-07-27 16:15:11 +02:00
|
|
|
SigChunk() : wire(nullptr), width(0), offset(0) {}
|
2024-10-09 19:39:45 +02:00
|
|
|
SigChunk(const RTLIL::Const &value) : wire(nullptr), data(value.to_bits()), width(GetSize(data)), offset(0) {}
|
|
|
|
|
SigChunk(RTLIL::Const &&value) : wire(nullptr), data(value.to_bits()), width(GetSize(data)), offset(0) {}
|
2022-07-27 16:15:11 +02:00
|
|
|
SigChunk(RTLIL::Wire *wire) : wire(wire), width(GetSize(wire)), offset(0) {}
|
|
|
|
|
SigChunk(RTLIL::Wire *wire, int offset, int width = 1) : wire(wire), width(width), offset(offset) {}
|
|
|
|
|
SigChunk(const std::string &str) : SigChunk(RTLIL::Const(str)) {}
|
2025-08-29 05:34:17 +02:00
|
|
|
SigChunk(int val) /*default width 32*/ : SigChunk(RTLIL::Const(val)) {}
|
|
|
|
|
SigChunk(int val, int width) : SigChunk(RTLIL::Const(val, width)) {}
|
2022-07-27 16:15:11 +02:00
|
|
|
SigChunk(RTLIL::State bit, int width = 1) : SigChunk(RTLIL::Const(bit, width)) {}
|
2020-03-18 19:21:53 +01:00
|
|
|
SigChunk(const RTLIL::SigBit &bit);
|
2014-12-26 10:53:21 +01:00
|
|
|
|
|
|
|
|
RTLIL::SigChunk extract(int offset, int length) const;
|
2024-04-15 14:08:58 +02:00
|
|
|
RTLIL::SigBit operator[](int offset) const;
|
2019-05-28 16:43:25 +02:00
|
|
|
inline int size() const { return width; }
|
2021-02-22 05:00:31 +01:00
|
|
|
inline bool is_wire() const { return wire != NULL; }
|
2014-12-26 10:53:21 +01:00
|
|
|
|
|
|
|
|
bool operator <(const RTLIL::SigChunk &other) const;
|
|
|
|
|
bool operator ==(const RTLIL::SigChunk &other) const;
|
|
|
|
|
bool operator !=(const RTLIL::SigChunk &other) const;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct RTLIL::SigBit
|
|
|
|
|
{
|
|
|
|
|
RTLIL::Wire *wire;
|
|
|
|
|
union {
|
|
|
|
|
RTLIL::State data; // used if wire == NULL
|
|
|
|
|
int offset; // used if wire != NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
SigBit();
|
|
|
|
|
SigBit(RTLIL::State bit);
|
2021-10-21 18:26:47 +02:00
|
|
|
explicit SigBit(bool bit);
|
2014-12-26 10:53:21 +01:00
|
|
|
SigBit(RTLIL::Wire *wire);
|
|
|
|
|
SigBit(RTLIL::Wire *wire, int offset);
|
|
|
|
|
SigBit(const RTLIL::SigChunk &chunk);
|
|
|
|
|
SigBit(const RTLIL::SigChunk &chunk, int index);
|
|
|
|
|
SigBit(const RTLIL::SigSpec &sig);
|
2020-05-22 17:59:24 +02:00
|
|
|
SigBit(const RTLIL::SigBit &sigbit) = default;
|
2019-05-05 10:00:27 +02:00
|
|
|
RTLIL::SigBit &operator =(const RTLIL::SigBit &other) = default;
|
2014-12-26 10:53:21 +01:00
|
|
|
|
2021-02-22 05:00:31 +01:00
|
|
|
inline bool is_wire() const { return wire != NULL; }
|
2021-02-20 20:46:30 +01:00
|
|
|
|
2014-12-26 10:53:21 +01:00
|
|
|
bool operator <(const RTLIL::SigBit &other) const;
|
|
|
|
|
bool operator ==(const RTLIL::SigBit &other) const;
|
|
|
|
|
bool operator !=(const RTLIL::SigBit &other) const;
|
2025-01-14 12:39:15 +01:00
|
|
|
[[nodiscard]] Hasher hash_into(Hasher h) const;
|
2025-01-14 12:48:59 +01:00
|
|
|
[[nodiscard]] Hasher hash_top() const;
|
2024-11-04 12:41:00 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
namespace hashlib {
|
|
|
|
|
template <>
|
2025-01-13 20:21:05 +01:00
|
|
|
struct hash_ops<RTLIL::SigBit> {
|
2024-11-04 12:41:00 +01:00
|
|
|
static inline bool cmp(const RTLIL::SigBit &a, const RTLIL::SigBit &b) {
|
|
|
|
|
return a == b;
|
|
|
|
|
}
|
2025-01-13 20:21:05 +01:00
|
|
|
[[nodiscard]] static inline Hasher hash(const RTLIL::SigBit sb) {
|
2024-11-04 12:41:00 +01:00
|
|
|
return sb.hash_top();
|
|
|
|
|
}
|
2025-01-13 20:21:05 +01:00
|
|
|
[[nodiscard]] static inline Hasher hash_into(const RTLIL::SigBit sb, Hasher h) {
|
|
|
|
|
return sb.hash_into(h);
|
|
|
|
|
}
|
2024-11-04 12:41:00 +01:00
|
|
|
};
|
2014-12-26 10:53:21 +01:00
|
|
|
};
|
|
|
|
|
|
2023-12-09 18:43:38 +01:00
|
|
|
struct RTLIL::SigSpecIterator
|
2014-12-26 10:53:21 +01:00
|
|
|
{
|
2023-12-09 18:43:38 +01:00
|
|
|
typedef std::input_iterator_tag iterator_category;
|
2023-12-09 18:48:30 +01:00
|
|
|
typedef RTLIL::SigBit value_type;
|
2023-12-09 18:43:38 +01:00
|
|
|
typedef ptrdiff_t difference_type;
|
2023-12-09 18:48:30 +01:00
|
|
|
typedef RTLIL::SigBit* pointer;
|
|
|
|
|
typedef RTLIL::SigBit& reference;
|
2023-12-09 18:43:38 +01:00
|
|
|
|
2014-12-26 10:53:21 +01:00
|
|
|
RTLIL::SigSpec *sig_p;
|
|
|
|
|
int index;
|
|
|
|
|
|
|
|
|
|
inline RTLIL::SigBit &operator*() const;
|
|
|
|
|
inline bool operator!=(const RTLIL::SigSpecIterator &other) const { return index != other.index; }
|
|
|
|
|
inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; }
|
|
|
|
|
inline void operator++() { index++; }
|
|
|
|
|
};
|
|
|
|
|
|
2023-12-09 18:43:38 +01:00
|
|
|
struct RTLIL::SigSpecConstIterator
|
2014-12-26 10:53:21 +01:00
|
|
|
{
|
2023-12-09 18:43:38 +01:00
|
|
|
typedef std::input_iterator_tag iterator_category;
|
2023-12-09 18:48:30 +01:00
|
|
|
typedef RTLIL::SigBit value_type;
|
2023-12-09 18:43:38 +01:00
|
|
|
typedef ptrdiff_t difference_type;
|
2023-12-09 18:48:30 +01:00
|
|
|
typedef RTLIL::SigBit* pointer;
|
|
|
|
|
typedef RTLIL::SigBit& reference;
|
2023-12-09 18:43:38 +01:00
|
|
|
|
2014-12-26 10:53:21 +01:00
|
|
|
const RTLIL::SigSpec *sig_p;
|
2025-10-31 11:06:13 +01:00
|
|
|
RTLIL::SigBit bit;
|
2014-12-26 10:53:21 +01:00
|
|
|
int index;
|
|
|
|
|
|
2025-10-31 11:06:13 +01:00
|
|
|
inline const RTLIL::SigBit &operator*();
|
2014-12-26 10:53:21 +01:00
|
|
|
inline bool operator!=(const RTLIL::SigSpecConstIterator &other) const { return index != other.index; }
|
|
|
|
|
inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; }
|
|
|
|
|
inline void operator++() { index++; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct RTLIL::SigSpec
|
|
|
|
|
{
|
|
|
|
|
private:
|
2026-04-23 17:47:17 +02:00
|
|
|
friend class SigSpecRepTest;
|
2026-04-24 11:03:02 +02:00
|
|
|
FRIEND_TEST(SigSpecRepTest, Extract);
|
2025-10-30 16:02:39 +01:00
|
|
|
enum Representation : char {
|
|
|
|
|
CHUNK,
|
|
|
|
|
BITS,
|
|
|
|
|
};
|
2025-10-31 11:48:39 +01:00
|
|
|
// An AtomicHash is either clear or a nonzero integer.
|
|
|
|
|
struct AtomicHash {
|
|
|
|
|
// Create an initially clear value.
|
|
|
|
|
AtomicHash() : atomic_(0) {}
|
|
|
|
|
AtomicHash(const AtomicHash &rhs) : atomic_(rhs.load()) {}
|
|
|
|
|
AtomicHash &operator=(const AtomicHash &rhs) { store(rhs.load()); return *this; }
|
|
|
|
|
// Read the hash. Returns nullopt if the hash is clear.
|
|
|
|
|
std::optional<Hasher::hash_t> read() const {
|
|
|
|
|
Hasher::hash_t value = load();
|
|
|
|
|
if (value == 0)
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
// Set the hash. If the value is already set, then the new value must
|
|
|
|
|
// equal the current value.
|
|
|
|
|
void set(Hasher::hash_t value) const {
|
|
|
|
|
log_assert(value != 0);
|
|
|
|
|
Hasher::hash_t old = const_cast<std::atomic<Hasher::hash_t>&>(atomic_)
|
|
|
|
|
.exchange(value, std::memory_order_relaxed);
|
|
|
|
|
log_assert(old == 0 || old == value);
|
|
|
|
|
}
|
|
|
|
|
void clear() { store(0); }
|
|
|
|
|
private:
|
|
|
|
|
int load() const { return atomic_.load(std::memory_order_relaxed); }
|
|
|
|
|
void store(Hasher::hash_t value) const {
|
|
|
|
|
const_cast<std::atomic<Hasher::hash_t>&>(atomic_).store(value, std::memory_order_relaxed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::atomic<Hasher::hash_t> atomic_;
|
|
|
|
|
};
|
2014-12-26 10:53:21 +01:00
|
|
|
|
2025-10-30 16:02:39 +01:00
|
|
|
Representation rep_;
|
2025-10-31 11:48:39 +01:00
|
|
|
AtomicHash hash_;
|
2025-10-30 16:02:39 +01:00
|
|
|
union {
|
|
|
|
|
RTLIL::SigChunk chunk_;
|
|
|
|
|
std::vector<RTLIL::SigBit> bits_; // LSB at index 0
|
|
|
|
|
};
|
2014-12-26 10:53:21 +01:00
|
|
|
|
2025-10-30 16:02:39 +01:00
|
|
|
void init_empty_bits() {
|
|
|
|
|
rep_ = BITS;
|
|
|
|
|
new (&bits_) std::vector<RTLIL::SigBit>;
|
2014-12-26 10:53:21 +01:00
|
|
|
}
|
|
|
|
|
|
2025-10-31 11:06:13 +01:00
|
|
|
void unpack();
|
|
|
|
|
inline void inline_unpack() {
|
2025-10-30 16:02:39 +01:00
|
|
|
if (rep_ == CHUNK)
|
2014-12-26 10:53:21 +01:00
|
|
|
unpack();
|
|
|
|
|
}
|
2025-11-07 16:50:57 +01:00
|
|
|
void try_repack();
|
2014-12-26 10:53:21 +01:00
|
|
|
|
2025-10-31 11:48:39 +01:00
|
|
|
Hasher::hash_t updhash() const;
|
2025-10-30 16:02:39 +01:00
|
|
|
void destroy() {
|
|
|
|
|
if (rep_ == CHUNK)
|
|
|
|
|
chunk_.~SigChunk();
|
|
|
|
|
else
|
|
|
|
|
bits_.~vector();
|
|
|
|
|
}
|
|
|
|
|
friend struct Chunks;
|
|
|
|
|
|
2014-12-26 10:53:21 +01:00
|
|
|
public:
|
2025-10-30 16:02:39 +01:00
|
|
|
SigSpec() { init_empty_bits(); }
|
2014-12-26 10:53:21 +01:00
|
|
|
SigSpec(std::initializer_list<RTLIL::SigSpec> parts);
|
2025-10-30 16:02:39 +01:00
|
|
|
SigSpec(const SigSpec &value) : rep_(value.rep_), hash_(value.hash_) {
|
|
|
|
|
if (value.rep_ == CHUNK)
|
|
|
|
|
new (&chunk_) RTLIL::SigChunk(value.chunk_);
|
|
|
|
|
else
|
|
|
|
|
new (&bits_) std::vector<RTLIL::SigBit>(value.bits_);
|
|
|
|
|
}
|
|
|
|
|
SigSpec(SigSpec &&value) : rep_(value.rep_), hash_(value.hash_) {
|
|
|
|
|
if (value.rep_ == CHUNK)
|
|
|
|
|
new (&chunk_) RTLIL::SigChunk(std::move(value.chunk_));
|
|
|
|
|
else
|
|
|
|
|
new (&bits_) std::vector<RTLIL::SigBit>(std::move(value.bits_));
|
|
|
|
|
}
|
2014-12-26 10:53:21 +01:00
|
|
|
SigSpec(const RTLIL::Const &value);
|
2022-07-27 16:15:11 +02:00
|
|
|
SigSpec(RTLIL::Const &&value);
|
2014-12-26 10:53:21 +01:00
|
|
|
SigSpec(const RTLIL::SigChunk &chunk);
|
2022-07-27 16:15:11 +02:00
|
|
|
SigSpec(RTLIL::SigChunk &&chunk);
|
2014-12-26 10:53:21 +01:00
|
|
|
SigSpec(RTLIL::Wire *wire);
|
|
|
|
|
SigSpec(RTLIL::Wire *wire, int offset, int width = 1);
|
|
|
|
|
SigSpec(const std::string &str);
|
|
|
|
|
SigSpec(int val, int width = 32);
|
|
|
|
|
SigSpec(RTLIL::State bit, int width = 1);
|
2020-03-18 19:21:53 +01:00
|
|
|
SigSpec(const RTLIL::SigBit &bit, int width = 1);
|
|
|
|
|
SigSpec(const std::vector<RTLIL::SigChunk> &chunks);
|
|
|
|
|
SigSpec(const std::vector<RTLIL::SigBit> &bits);
|
|
|
|
|
SigSpec(const pool<RTLIL::SigBit> &bits);
|
|
|
|
|
SigSpec(const std::set<RTLIL::SigBit> &bits);
|
2021-10-21 18:26:47 +02:00
|
|
|
explicit SigSpec(bool bit);
|
2025-10-30 16:02:39 +01:00
|
|
|
~SigSpec() {
|
|
|
|
|
destroy();
|
|
|
|
|
}
|
2014-12-26 10:53:21 +01:00
|
|
|
|
2025-10-30 16:02:39 +01:00
|
|
|
SigSpec &operator=(const SigSpec &rhs) {
|
|
|
|
|
destroy();
|
|
|
|
|
rep_ = rhs.rep_;
|
|
|
|
|
hash_ = rhs.hash_;
|
|
|
|
|
if (rep_ == CHUNK)
|
|
|
|
|
new (&chunk_) RTLIL::SigChunk(rhs.chunk_);
|
|
|
|
|
else
|
|
|
|
|
new (&bits_) std::vector<RTLIL::SigBit>(rhs.bits_);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
SigSpec &operator=(SigSpec &&rhs) {
|
|
|
|
|
destroy();
|
|
|
|
|
rep_ = rhs.rep_;
|
|
|
|
|
hash_ = rhs.hash_;
|
|
|
|
|
if (rep_ == CHUNK)
|
|
|
|
|
new (&chunk_) RTLIL::SigChunk(std::move(rhs.chunk_));
|
|
|
|
|
else
|
|
|
|
|
new (&bits_) std::vector<RTLIL::SigBit>(std::move(rhs.bits_));
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2025-09-25 05:04:17 +02:00
|
|
|
|
2025-11-10 12:02:21 +01:00
|
|
|
// SigSpec::Chunks holds one reconstructed chunk at a time
|
|
|
|
|
// to provide the SigSpec::chunks() read-only chunks view
|
|
|
|
|
// since vector<SigChunk> SigSpec::chunks_ has been removed
|
2025-10-27 16:46:36 +01:00
|
|
|
struct Chunks {
|
2025-10-30 12:07:02 +01:00
|
|
|
Chunks(const SigSpec &spec) : spec(spec) {}
|
2025-10-27 16:46:36 +01:00
|
|
|
struct const_iterator {
|
|
|
|
|
using iterator_category = std::forward_iterator_tag;
|
|
|
|
|
using value_type = const SigChunk &;
|
|
|
|
|
using difference_type = std::ptrdiff_t;
|
|
|
|
|
using pointer = const SigChunk *;
|
|
|
|
|
using reference = const SigChunk &;
|
|
|
|
|
|
|
|
|
|
const SigSpec &spec;
|
|
|
|
|
int bit_index;
|
|
|
|
|
SigChunk chunk;
|
|
|
|
|
|
|
|
|
|
const_iterator(const SigSpec &spec) : spec(spec) {
|
|
|
|
|
bit_index = 0;
|
2025-10-30 16:02:39 +01:00
|
|
|
if (spec.rep_ == BITS)
|
2025-10-27 16:46:36 +01:00
|
|
|
next_chunk_bits();
|
|
|
|
|
}
|
|
|
|
|
enum End { END };
|
|
|
|
|
const_iterator(const SigSpec &spec, End) : spec(spec) {
|
|
|
|
|
bit_index = spec.size();
|
|
|
|
|
}
|
|
|
|
|
void next_chunk_bits();
|
|
|
|
|
|
|
|
|
|
const SigChunk &operator*() {
|
2025-10-30 16:02:39 +01:00
|
|
|
if (spec.rep_ == CHUNK)
|
|
|
|
|
return spec.chunk_;
|
2025-10-27 16:46:36 +01:00
|
|
|
return chunk;
|
|
|
|
|
};
|
|
|
|
|
const SigChunk *operator->() { return &**this; }
|
|
|
|
|
const_iterator &operator++() {
|
|
|
|
|
bit_index += (**this).width;
|
2025-10-30 16:02:39 +01:00
|
|
|
if (spec.rep_ == BITS)
|
2025-10-27 16:46:36 +01:00
|
|
|
next_chunk_bits();
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
bool operator==(const const_iterator &rhs) const { return bit_index == rhs.bit_index; }
|
|
|
|
|
bool operator!=(const const_iterator &rhs) const { return !(*this == rhs); }
|
|
|
|
|
};
|
|
|
|
|
const_iterator begin() const { return const_iterator(spec); }
|
|
|
|
|
const_iterator end() const {
|
|
|
|
|
const_iterator it(spec, const_iterator::END);
|
|
|
|
|
return it;
|
|
|
|
|
}
|
2025-10-30 12:07:02 +01:00
|
|
|
// Later we should deprecate these and remove their in-tree calls,
|
|
|
|
|
// so we can eventually remove chunk_vector.
|
|
|
|
|
std::vector<RTLIL::SigChunk>::const_reverse_iterator rbegin() {
|
|
|
|
|
ensure_chunk_vector();
|
|
|
|
|
return chunk_vector.rbegin();
|
2025-10-27 16:46:36 +01:00
|
|
|
}
|
2025-10-30 12:07:02 +01:00
|
|
|
std::vector<RTLIL::SigChunk>::const_reverse_iterator rend() {
|
|
|
|
|
ensure_chunk_vector();
|
|
|
|
|
return chunk_vector.rend();
|
|
|
|
|
}
|
|
|
|
|
int size() {
|
|
|
|
|
ensure_chunk_vector();
|
|
|
|
|
return chunk_vector.size();
|
2025-10-27 16:46:36 +01:00
|
|
|
}
|
|
|
|
|
int size() const {
|
2025-11-10 12:02:36 +01:00
|
|
|
return std::distance(begin(), end());
|
2025-10-27 16:46:36 +01:00
|
|
|
}
|
2025-10-30 12:07:02 +01:00
|
|
|
const SigChunk &at(int index) {
|
|
|
|
|
ensure_chunk_vector();
|
|
|
|
|
return chunk_vector.at(index);
|
2025-10-27 16:46:36 +01:00
|
|
|
}
|
2025-10-30 12:07:02 +01:00
|
|
|
operator const std::vector<RTLIL::SigChunk>&() {
|
|
|
|
|
ensure_chunk_vector();
|
|
|
|
|
return chunk_vector;
|
2025-10-27 16:46:36 +01:00
|
|
|
}
|
2025-10-30 12:07:02 +01:00
|
|
|
private:
|
|
|
|
|
void ensure_chunk_vector() {
|
|
|
|
|
if (spec.size() > 0 && chunk_vector.empty()) {
|
|
|
|
|
for (const RTLIL::SigChunk &c : *this)
|
|
|
|
|
chunk_vector.push_back(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const SigSpec &spec;
|
|
|
|
|
std::vector<RTLIL::SigChunk> chunk_vector;
|
2025-10-27 16:46:36 +01:00
|
|
|
};
|
|
|
|
|
friend struct Chunks::const_iterator;
|
|
|
|
|
|
|
|
|
|
inline Chunks chunks() const { return {*this}; }
|
2025-10-31 11:06:13 +01:00
|
|
|
inline const SigSpec &bits() const { return *this; }
|
2014-12-26 10:53:21 +01:00
|
|
|
|
2025-10-30 16:02:39 +01:00
|
|
|
inline int size() const { return rep_ == CHUNK ? chunk_.width : GetSize(bits_); }
|
2025-10-31 11:48:39 +01:00
|
|
|
inline bool empty() const { return size() == 0; };
|
2014-12-26 10:53:21 +01:00
|
|
|
|
2025-10-31 11:48:39 +01:00
|
|
|
inline RTLIL::SigBit &operator[](int index) { inline_unpack(); hash_.clear(); return bits_.at(index); }
|
2025-10-31 11:06:13 +01:00
|
|
|
inline RTLIL::SigBit operator[](int index) const {
|
|
|
|
|
if (rep_ == CHUNK) {
|
|
|
|
|
if (index < 0 || index >= chunk_.width)
|
|
|
|
|
throw std::out_of_range("SigSpec::operator[]");
|
|
|
|
|
if (chunk_.wire)
|
|
|
|
|
return RTLIL::SigBit(chunk_.wire, chunk_.offset + index);
|
|
|
|
|
return RTLIL::SigBit(chunk_.data[index]);
|
|
|
|
|
}
|
|
|
|
|
return bits_.at(index);
|
|
|
|
|
}
|
2014-12-26 10:53:21 +01:00
|
|
|
|
|
|
|
|
inline RTLIL::SigSpecIterator begin() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = 0; return it; }
|
2025-10-30 15:13:46 +01:00
|
|
|
inline RTLIL::SigSpecIterator end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = size(); return it; }
|
2014-12-26 10:53:21 +01:00
|
|
|
|
|
|
|
|
inline RTLIL::SigSpecConstIterator begin() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = 0; return it; }
|
2025-10-30 15:13:46 +01:00
|
|
|
inline RTLIL::SigSpecConstIterator end() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = size(); return it; }
|
2014-12-26 10:53:21 +01:00
|
|
|
|
|
|
|
|
void sort();
|
|
|
|
|
void sort_and_unify();
|
|
|
|
|
|
|
|
|
|
void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with);
|
|
|
|
|
void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with, RTLIL::SigSpec *other) const;
|
|
|
|
|
|
|
|
|
|
void replace(const dict<RTLIL::SigBit, RTLIL::SigBit> &rules);
|
|
|
|
|
void replace(const dict<RTLIL::SigBit, RTLIL::SigBit> &rules, RTLIL::SigSpec *other) const;
|
|
|
|
|
|
|
|
|
|
void replace(const std::map<RTLIL::SigBit, RTLIL::SigBit> &rules);
|
|
|
|
|
void replace(const std::map<RTLIL::SigBit, RTLIL::SigBit> &rules, RTLIL::SigSpec *other) const;
|
|
|
|
|
|
|
|
|
|
void replace(int offset, const RTLIL::SigSpec &with);
|
|
|
|
|
|
|
|
|
|
void remove(const RTLIL::SigSpec &pattern);
|
|
|
|
|
void remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) const;
|
|
|
|
|
void remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other);
|
|
|
|
|
|
2014-12-26 21:59:41 +01:00
|
|
|
void remove(const pool<RTLIL::SigBit> &pattern);
|
|
|
|
|
void remove(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other) const;
|
|
|
|
|
void remove2(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other);
|
2016-01-30 07:03:12 +01:00
|
|
|
void remove2(const std::set<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other);
|
2024-01-08 14:06:38 +01:00
|
|
|
void remove2(const pool<RTLIL::Wire*> &pattern, RTLIL::SigSpec *other);
|
2016-01-30 07:03:12 +01:00
|
|
|
|
2014-12-26 10:53:21 +01:00
|
|
|
void remove(int offset, int length = 1);
|
|
|
|
|
void remove_const();
|
|
|
|
|
|
|
|
|
|
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const;
|
2014-12-26 21:59:41 +01:00
|
|
|
RTLIL::SigSpec extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const;
|
2014-12-26 10:53:21 +01:00
|
|
|
RTLIL::SigSpec extract(int offset, int length = 1) const;
|
2025-10-30 15:13:46 +01:00
|
|
|
RTLIL::SigSpec extract_end(int offset) const { return extract(offset, size() - offset); }
|
2014-12-26 10:53:21 +01:00
|
|
|
|
2025-10-27 13:41:50 +01:00
|
|
|
void rewrite_wires(std::function<void(RTLIL::Wire*& wire)> rewrite);
|
|
|
|
|
|
2025-10-30 15:13:46 +01:00
|
|
|
RTLIL::SigBit lsb() const { log_assert(size()); return (*this)[0]; };
|
|
|
|
|
RTLIL::SigBit msb() const { log_assert(size()); return (*this)[size() - 1]; };
|
2025-10-31 11:06:13 +01:00
|
|
|
RTLIL::SigBit front() const { return (*this)[0]; }
|
|
|
|
|
RTLIL::SigBit back() const { return (*this)[size() - 1]; }
|
2023-11-22 12:33:47 +01:00
|
|
|
|
2014-12-26 10:53:21 +01:00
|
|
|
void append(const RTLIL::SigSpec &signal);
|
2020-03-13 16:17:39 +01:00
|
|
|
inline void append(Wire *wire) { append(RTLIL::SigSpec(wire)); }
|
|
|
|
|
inline void append(const RTLIL::SigChunk &chunk) { append(RTLIL::SigSpec(chunk)); }
|
|
|
|
|
inline void append(const RTLIL::Const &const_) { append(RTLIL::SigSpec(const_)); }
|
|
|
|
|
|
|
|
|
|
void append(const RTLIL::SigBit &bit);
|
|
|
|
|
inline void append(RTLIL::State state) { append(RTLIL::SigBit(state)); }
|
|
|
|
|
inline void append(bool bool_) { append(RTLIL::SigBit(bool_)); }
|
2014-12-26 10:53:21 +01:00
|
|
|
|
|
|
|
|
void extend_u0(int width, bool is_signed = false);
|
|
|
|
|
|
|
|
|
|
RTLIL::SigSpec repeat(int num) const;
|
|
|
|
|
|
2020-01-28 19:37:16 +01:00
|
|
|
void reverse() { inline_unpack(); std::reverse(bits_.begin(), bits_.end()); }
|
|
|
|
|
|
2014-12-26 10:53:21 +01:00
|
|
|
bool operator <(const RTLIL::SigSpec &other) const;
|
|
|
|
|
bool operator ==(const RTLIL::SigSpec &other) const;
|
|
|
|
|
inline bool operator !=(const RTLIL::SigSpec &other) const { return !(*this == other); }
|
|
|
|
|
|
|
|
|
|
bool is_wire() const;
|
|
|
|
|
bool is_chunk() const;
|
2025-10-30 15:13:46 +01:00
|
|
|
inline bool is_bit() const { return size() == 1; }
|
2014-12-26 10:53:21 +01:00
|
|
|
|
2025-09-03 15:29:08 +02:00
|
|
|
bool known_driver() const;
|
|
|
|
|
|
2014-12-26 10:53:21 +01:00
|
|
|
bool is_fully_const() const;
|
2015-04-29 07:28:15 +02:00
|
|
|
bool is_fully_zero() const;
|
2017-12-12 21:48:31 +01:00
|
|
|
bool is_fully_ones() const;
|
2014-12-26 10:53:21 +01:00
|
|
|
bool is_fully_def() const;
|
|
|
|
|
bool is_fully_undef() const;
|
2015-02-08 00:01:51 +01:00
|
|
|
bool has_const() const;
|
2025-09-03 15:34:51 +02:00
|
|
|
bool has_const(State state) const;
|
2014-12-26 10:53:21 +01:00
|
|
|
bool has_marked_bits() const;
|
2021-06-09 18:41:57 +02:00
|
|
|
bool is_onehot(int *pos = nullptr) const;
|
2014-12-26 10:53:21 +01:00
|
|
|
|
|
|
|
|
bool as_bool() const;
|
2025-05-21 13:20:08 +02:00
|
|
|
|
|
|
|
|
// Convert the SigSpec to a C++ int, assuming all bits are constant.
|
|
|
|
|
// NOTE: If the value is too wide to fit in int (32 bits) this will
|
|
|
|
|
// truncate any higher bits, potentially over/underflowing. Consider using
|
|
|
|
|
// try_as_int, as_int_saturating, or guarding behind convertible_to_int
|
|
|
|
|
// instead.
|
2014-12-26 10:53:21 +01:00
|
|
|
int as_int(bool is_signed = false) const;
|
2025-05-21 13:20:08 +02:00
|
|
|
|
|
|
|
|
// Returns true iff the SigSpec is constant and can be converted to an int
|
|
|
|
|
// without over/underflow.
|
2025-05-07 14:36:48 +02:00
|
|
|
bool convertible_to_int(bool is_signed = false) const;
|
2025-05-21 13:20:08 +02:00
|
|
|
|
|
|
|
|
// Returns the SigSpec's value as an int if it is a constant and can be
|
|
|
|
|
// represented without over/underflow, or std::nullopt otherwise.
|
2025-05-07 14:36:48 +02:00
|
|
|
std::optional<int> try_as_int(bool is_signed = false) const;
|
2025-05-21 13:20:08 +02:00
|
|
|
|
|
|
|
|
// Returns an all constant SigSpec's value as an int if it can be represented
|
|
|
|
|
// without over/underflow, otherwise the max/min value for int depending on
|
|
|
|
|
// the sign.
|
2025-05-07 14:36:48 +02:00
|
|
|
int as_int_saturating(bool is_signed = false) const;
|
2025-05-21 13:20:08 +02:00
|
|
|
|
2014-12-26 10:53:21 +01:00
|
|
|
std::string as_string() const;
|
2025-10-28 16:48:24 +01:00
|
|
|
// Returns std::nullopt if there are any non-constant bits. Returns an empty
|
|
|
|
|
// Const if this has zero width.
|
|
|
|
|
std::optional<RTLIL::Const> try_as_const() const;
|
2014-12-26 10:53:21 +01:00
|
|
|
RTLIL::Const as_const() const;
|
|
|
|
|
RTLIL::Wire *as_wire() const;
|
|
|
|
|
RTLIL::SigChunk as_chunk() const;
|
2015-10-24 22:56:40 +02:00
|
|
|
RTLIL::SigBit as_bit() const;
|
2014-12-26 10:53:21 +01:00
|
|
|
|
2020-03-18 19:21:53 +01:00
|
|
|
bool match(const char* pattern) const;
|
2014-12-26 10:53:21 +01:00
|
|
|
|
|
|
|
|
std::set<RTLIL::SigBit> to_sigbit_set() const;
|
2014-12-27 12:02:57 +01:00
|
|
|
pool<RTLIL::SigBit> to_sigbit_pool() const;
|
2014-12-26 10:53:21 +01:00
|
|
|
std::vector<RTLIL::SigBit> to_sigbit_vector() const;
|
|
|
|
|
std::map<RTLIL::SigBit, RTLIL::SigBit> to_sigbit_map(const RTLIL::SigSpec &other) const;
|
|
|
|
|
dict<RTLIL::SigBit, RTLIL::SigBit> to_sigbit_dict(const RTLIL::SigSpec &other) const;
|
|
|
|
|
|
|
|
|
|
static bool parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str);
|
|
|
|
|
static bool parse_sel(RTLIL::SigSpec &sig, RTLIL::Design *design, RTLIL::Module *module, std::string str);
|
|
|
|
|
static bool parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str);
|
|
|
|
|
|
2025-10-30 11:30:03 +01:00
|
|
|
operator std::vector<RTLIL::SigChunk>() const;
|
2025-10-31 11:06:13 +01:00
|
|
|
operator std::vector<RTLIL::SigBit>() const { return to_sigbit_vector(); }
|
2025-10-30 15:13:46 +01:00
|
|
|
const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < size() ? (*this)[offset] : defval; }
|
2025-11-17 10:14:51 +01:00
|
|
|
RTLIL::SigBit& at(int offset) { return (*this)[offset]; }
|
|
|
|
|
RTLIL::SigBit at(int offset) const { return (*this)[offset]; }
|
2014-12-26 10:53:21 +01:00
|
|
|
|
2025-10-31 11:48:39 +01:00
|
|
|
[[nodiscard]] Hasher hash_into(Hasher h) const {
|
|
|
|
|
Hasher::hash_t val;
|
|
|
|
|
if (std::optional<Hasher::hash_t> current = hash_.read())
|
|
|
|
|
val = *current;
|
|
|
|
|
else
|
|
|
|
|
val = updhash();
|
|
|
|
|
h.eat(val);
|
|
|
|
|
return h;
|
|
|
|
|
}
|
2014-12-26 21:35:22 +01:00
|
|
|
|
2014-12-26 10:53:21 +01:00
|
|
|
#ifndef NDEBUG
|
2026-01-29 23:45:10 +01:00
|
|
|
void check(const Module *mod = nullptr) const;
|
2014-12-26 10:53:21 +01:00
|
|
|
#else
|
2026-01-29 23:45:10 +01:00
|
|
|
void check(const Module *mod = nullptr) const { (void)mod; }
|
2014-12-26 10:53:21 +01:00
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
2014-07-27 02:00:04 +02:00
|
|
|
struct RTLIL::Selection
|
|
|
|
|
{
|
2025-04-08 01:57:43 +02:00
|
|
|
// selection includes boxed modules
|
|
|
|
|
bool selects_boxes;
|
|
|
|
|
// selection covers full design, including boxed modules
|
|
|
|
|
bool complete_selection;
|
|
|
|
|
// selection covers full design, not including boxed modules
|
2025-04-04 23:40:19 +02:00
|
|
|
bool full_selection;
|
2026-06-09 18:50:00 +02:00
|
|
|
pool<TwineRef> selected_modules;
|
|
|
|
|
dict<TwineRef, pool<TwineRef>> selected_members;
|
2025-04-08 01:57:43 +02:00
|
|
|
RTLIL::Design *current_design;
|
|
|
|
|
|
|
|
|
|
// create a new selection
|
|
|
|
|
Selection(
|
|
|
|
|
// should the selection cover the full design
|
|
|
|
|
bool full = true,
|
|
|
|
|
// should the selection include boxed modules
|
|
|
|
|
bool boxes = false,
|
|
|
|
|
// the design to select from
|
|
|
|
|
RTLIL::Design *design = nullptr
|
2025-05-14 15:18:57 +02:00
|
|
|
) :
|
2025-04-07 11:36:50 +02:00
|
|
|
selects_boxes(boxes), complete_selection(full && boxes), full_selection(full && !boxes), current_design(design) { }
|
2025-04-08 01:57:43 +02:00
|
|
|
|
|
|
|
|
// checks if the given module exists in the current design and is a
|
|
|
|
|
// boxed module, warning the user if the current design is not set
|
2026-06-09 18:50:00 +02:00
|
|
|
bool boxed_module(TwineRef mod_name) const;
|
2025-04-08 01:57:43 +02:00
|
|
|
|
|
|
|
|
// checks if the given module is included in this selection
|
2026-06-09 18:50:00 +02:00
|
|
|
bool selected_module(TwineRef mod_name) const;
|
2025-04-08 01:57:43 +02:00
|
|
|
|
|
|
|
|
// checks if the given module is wholly included in this selection,
|
|
|
|
|
// i.e. not partially selected
|
2026-06-09 18:50:00 +02:00
|
|
|
bool selected_whole_module(TwineRef mod_name) const;
|
2025-04-08 01:57:43 +02:00
|
|
|
|
|
|
|
|
// checks if the given member from the given module is included in this
|
|
|
|
|
// selection
|
2026-06-09 18:50:00 +02:00
|
|
|
bool selected_member(TwineRef mod_name, TwineRef memb_name) const;
|
2025-04-08 01:57:43 +02:00
|
|
|
|
|
|
|
|
// optimizes this selection for the given design by:
|
|
|
|
|
// - removing non-existent modules and members, any boxed modules and
|
|
|
|
|
// their members (if selection does not include boxes), and any
|
|
|
|
|
// partially selected modules with no selected members;
|
|
|
|
|
// - marking partially selected modules as wholly selected if all
|
|
|
|
|
// members of that module are selected; and
|
|
|
|
|
// - marking selection as a complete_selection if all modules in the
|
|
|
|
|
// given design are selected, or a full_selection if it does not
|
|
|
|
|
// include boxes.
|
2013-01-05 11:13:26 +01:00
|
|
|
void optimize(RTLIL::Design *design);
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
// checks if selection covers full design (may or may not include
|
|
|
|
|
// boxed-modules)
|
|
|
|
|
bool selects_all() const {
|
|
|
|
|
return full_selection || complete_selection;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add whole module to this selection
|
2013-11-23 15:58:06 +01:00
|
|
|
template<typename T1> void select(T1 *module) {
|
2026-06-10 19:22:53 +02:00
|
|
|
if (!selects_all() && selected_modules.count(module->meta_->name) == 0) {
|
|
|
|
|
TwineRef name = module->meta_->name;
|
2026-06-08 23:40:51 +02:00
|
|
|
selected_modules.insert(name);
|
|
|
|
|
selected_members.erase(name);
|
2025-04-08 01:57:43 +02:00
|
|
|
if (module->get_blackbox_attribute())
|
|
|
|
|
selects_boxes = true;
|
2013-11-23 15:58:06 +01:00
|
|
|
}
|
|
|
|
|
}
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
// add member of module to this selection
|
2013-08-09 15:20:22 +02:00
|
|
|
template<typename T1, typename T2> void select(T1 *module, T2 *member) {
|
2026-06-11 13:17:54 +02:00
|
|
|
if (!selects_all() && selected_modules.count(module->meta_->name) == 0) {
|
|
|
|
|
selected_members[module->meta_->name].insert(member->meta_->name);
|
2025-04-08 01:57:43 +02:00
|
|
|
if (module->get_blackbox_attribute())
|
|
|
|
|
selects_boxes = true;
|
|
|
|
|
}
|
2013-08-09 15:20:22 +02:00
|
|
|
}
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
// checks if selection is empty
|
2014-01-17 16:34:50 +01:00
|
|
|
bool empty() const {
|
2025-04-08 01:57:43 +02:00
|
|
|
return !selects_all() && selected_modules.empty() && selected_members.empty();
|
2014-01-17 16:34:50 +01:00
|
|
|
}
|
2025-04-08 01:57:43 +02:00
|
|
|
|
|
|
|
|
// clear this selection, leaving it empty
|
|
|
|
|
void clear();
|
|
|
|
|
|
|
|
|
|
// create a new selection which is empty
|
|
|
|
|
static Selection EmptySelection(RTLIL::Design *design = nullptr) { return Selection(false, false, design); };
|
|
|
|
|
|
|
|
|
|
// create a new selection with all non-boxed modules
|
|
|
|
|
static Selection FullSelection(RTLIL::Design *design = nullptr) { return Selection(true, false, design); };
|
|
|
|
|
|
|
|
|
|
// create a new selection with all modules, including boxes
|
|
|
|
|
static Selection CompleteSelection(RTLIL::Design *design = nullptr) { return Selection(true, true, design); };
|
2013-01-05 11:13:26 +01:00
|
|
|
};
|
|
|
|
|
|
2014-07-31 14:34:12 +02:00
|
|
|
struct RTLIL::Monitor
|
|
|
|
|
{
|
2024-10-01 15:12:03 +02:00
|
|
|
Hasher::hash_t hashidx_;
|
2025-01-14 12:39:15 +01:00
|
|
|
[[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; }
|
2014-12-28 17:51:16 +01:00
|
|
|
|
|
|
|
|
Monitor() {
|
2014-12-29 00:12:36 +01:00
|
|
|
static unsigned int hashidx_count = 123456789;
|
|
|
|
|
hashidx_count = mkhash_xorshift(hashidx_count);
|
|
|
|
|
hashidx_ = hashidx_count;
|
2014-12-28 17:51:16 +01:00
|
|
|
}
|
|
|
|
|
|
2014-07-31 16:38:54 +02:00
|
|
|
virtual ~Monitor() { }
|
2014-07-31 14:34:12 +02:00
|
|
|
virtual void notify_module_add(RTLIL::Module*) { }
|
|
|
|
|
virtual void notify_module_del(RTLIL::Module*) { }
|
2026-06-10 19:22:53 +02:00
|
|
|
virtual void notify_connect(RTLIL::Cell*, TwineRef, const RTLIL::SigSpec&, const RTLIL::SigSpec&) { }
|
2014-07-31 14:34:12 +02:00
|
|
|
virtual void notify_connect(RTLIL::Module*, const RTLIL::SigSig&) { }
|
2014-08-01 16:53:15 +02:00
|
|
|
virtual void notify_connect(RTLIL::Module*, const std::vector<RTLIL::SigSig>&) { }
|
2014-07-31 14:34:12 +02:00
|
|
|
virtual void notify_blackout(RTLIL::Module*) { }
|
|
|
|
|
};
|
|
|
|
|
|
2020-03-17 10:34:31 +01:00
|
|
|
// Forward declaration; defined in preproc.h.
|
|
|
|
|
struct define_map_t;
|
|
|
|
|
|
2014-07-27 02:00:04 +02:00
|
|
|
struct RTLIL::Design
|
|
|
|
|
{
|
2024-10-01 15:12:03 +02:00
|
|
|
Hasher::hash_t hashidx_;
|
2025-01-14 12:39:15 +01:00
|
|
|
[[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; }
|
2014-12-28 17:51:16 +01:00
|
|
|
|
|
|
|
|
pool<RTLIL::Monitor*> monitors;
|
2014-12-26 10:53:21 +01:00
|
|
|
dict<std::string, std::string> scratchpad;
|
2014-07-31 14:34:12 +02:00
|
|
|
|
2023-09-29 15:49:15 +02:00
|
|
|
bool flagBufferedNormalized = false;
|
2025-10-06 14:39:25 +02:00
|
|
|
bool flagSigNormalized = false;
|
2023-09-29 15:49:15 +02:00
|
|
|
void bufNormalize(bool enable=true);
|
2025-10-06 14:39:25 +02:00
|
|
|
void sigNormalize(bool enable=true);
|
2023-09-29 15:49:15 +02:00
|
|
|
|
2014-07-27 10:40:31 +02:00
|
|
|
int refcount_modules_;
|
2026-06-10 19:22:53 +02:00
|
|
|
dict<TwineRef, RTLIL::Module*> modules_;
|
2020-04-20 17:06:53 +02:00
|
|
|
std::vector<RTLIL::Binding*> bindings_;
|
|
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
TwinePool twines;
|
2026-06-05 12:04:19 +02:00
|
|
|
|
2026-06-05 18:50:58 +02:00
|
|
|
// Per-Design ObjMeta pool: stable storage (deque) + LIFO freelist of
|
|
|
|
|
// returned slots. AttrObject::meta_ points into obj_meta_storage_.
|
|
|
|
|
std::deque<RTLIL::ObjMeta> obj_meta_storage_;
|
|
|
|
|
std::vector<RTLIL::ObjMeta*> obj_meta_free_;
|
2026-06-05 14:15:51 +02:00
|
|
|
|
2026-06-05 18:50:58 +02:00
|
|
|
RTLIL::ObjMeta *alloc_obj_meta();
|
|
|
|
|
void free_obj_meta(RTLIL::ObjMeta *m);
|
2026-06-05 16:18:43 +02:00
|
|
|
|
2026-06-09 18:50:00 +02:00
|
|
|
TwineRef obj_src_id(const RTLIL::AttrObject *obj) const {
|
2026-06-05 18:50:58 +02:00
|
|
|
return (obj->meta_ ? obj->meta_->src : Twine::Null);
|
2026-06-05 14:15:51 +02:00
|
|
|
}
|
2026-06-09 18:50:00 +02:00
|
|
|
void obj_set_src_id(RTLIL::AttrObject *obj, TwineRef id);
|
2026-06-05 18:50:58 +02:00
|
|
|
void obj_release_src(RTLIL::AttrObject *obj);
|
|
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
std::string obj_name(const RTLIL::AttrObject *obj) const {
|
2026-06-10 19:22:53 +02:00
|
|
|
return (obj->meta_ ? twines.flat_string(obj->meta_->name) : std::string());
|
2026-06-05 16:18:43 +02:00
|
|
|
}
|
2026-06-10 19:22:53 +02:00
|
|
|
// void obj_set_name(RTLIL::AttrObject *obj, RTLIL::IdString name);
|
|
|
|
|
// void obj_release_name(RTLIL::AttrObject *obj);
|
2026-06-05 14:15:51 +02:00
|
|
|
|
2026-06-09 18:50:00 +02:00
|
|
|
// Wire/Cell names: stored as TwineRef in twines.
|
2026-06-10 19:22:53 +02:00
|
|
|
// TwineRef obj_name(const RTLIL::AttrObject *obj) const {
|
|
|
|
|
// return (obj->meta_ ? obj->meta_->name : Twine::Null);
|
|
|
|
|
// }
|
|
|
|
|
// void obj_set_name(RTLIL::AttrObject *obj, TwineRef id);
|
|
|
|
|
// void obj_release_name(RTLIL::AttrObject *obj);
|
2026-06-08 23:40:51 +02:00
|
|
|
|
2026-06-05 14:15:51 +02:00
|
|
|
// Replacements for the methods that used to live on AttrObject and
|
|
|
|
|
// took an explicit TwinePool*. Same semantics; the pool resolves
|
2026-06-08 23:40:51 +02:00
|
|
|
// to this->twines internally.
|
2026-06-10 19:22:53 +02:00
|
|
|
void set_src_attribute(RTLIL::AttrObject *obj, TwineRef src);
|
2026-06-05 14:15:51 +02:00
|
|
|
std::string get_src_attribute(const RTLIL::AttrObject *obj) const;
|
|
|
|
|
void adopt_src_from(RTLIL::AttrObject *obj, const RTLIL::AttrObject *source);
|
|
|
|
|
void adopt_src_from(RTLIL::AttrObject *obj, const RTLIL::AttrObject *source,
|
|
|
|
|
const TwinePool *src_pool);
|
|
|
|
|
void absorb_attrs(RTLIL::AttrObject *obj, dict<RTLIL::IdString, RTLIL::Const> &&buf);
|
|
|
|
|
|
2026-06-05 12:04:19 +02:00
|
|
|
// Merge `source`'s src attribute into `target`'s src attribute via the
|
|
|
|
|
// twine pool. After the call `target` carries the combined "@N" ref.
|
|
|
|
|
// Handles every case: source has a "@N" ref → reuse that Id; source
|
|
|
|
|
// has a legacy pipe-joined literal → split and intern each leaf;
|
|
|
|
|
// target had pre-existing src → its leaves are folded in too. Use
|
|
|
|
|
// this instead of `target->add_strpool_attribute(ID::src, source->get_strpool_attribute(ID::src))`,
|
|
|
|
|
// which round-trips through a flat string and corrupts "@N" refs.
|
|
|
|
|
void merge_src(RTLIL::AttrObject *target, const RTLIL::AttrObject *source);
|
|
|
|
|
|
|
|
|
|
// Same as merge_src but consumes a raw set of leaf strings (each of
|
|
|
|
|
// which may itself be either a "@N" ref or a literal path).
|
|
|
|
|
void merge_src(RTLIL::AttrObject *target, const pool<std::string> &leaves);
|
|
|
|
|
|
|
|
|
|
// Returns the resolved leaf-string set backing obj's src attribute.
|
|
|
|
|
// "@N" refs are expanded through the pool; legacy pipe-joined
|
|
|
|
|
// literals are split. Use this instead of get_strpool_attribute(ID::src)
|
|
|
|
|
// when you actually need to iterate the path:line.col entries.
|
|
|
|
|
pool<std::string> src_leaves(const RTLIL::AttrObject *obj) const;
|
|
|
|
|
|
|
|
|
|
// Walk the design, collect the set of "@N" ids actually referenced by
|
2026-06-08 23:40:51 +02:00
|
|
|
// any AttrObject's src, then compact twines to contain only those
|
2026-06-05 12:04:19 +02:00
|
|
|
// nodes plus their transitive leaf children, and rewrite every cell
|
|
|
|
|
// src attribute through the resulting old-id -> new-id remap.
|
|
|
|
|
// Intermediate concats produced by successive merges become unreferenced
|
|
|
|
|
// once a fresh concat takes their place on the surviving cell, so this
|
|
|
|
|
// is what reaps them. Returns the number of nodes freed.
|
|
|
|
|
size_t gc_twines();
|
|
|
|
|
|
2025-06-16 22:55:24 +02:00
|
|
|
std::vector<std::unique_ptr<AST::AstNode>> verilog_packages, verilog_globals;
|
2020-03-17 10:34:31 +01:00
|
|
|
std::unique_ptr<define_map_t> verilog_defines;
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2013-01-05 11:13:26 +01:00
|
|
|
std::vector<RTLIL::Selection> selection_stack;
|
2014-12-26 10:53:21 +01:00
|
|
|
dict<RTLIL::IdString, RTLIL::Selection> selection_vars;
|
2026-06-09 18:50:00 +02:00
|
|
|
TwineRef selected_active_module;
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2014-07-29 16:06:27 +02:00
|
|
|
Design();
|
2013-01-05 11:13:26 +01:00
|
|
|
~Design();
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2026-06-09 18:50:00 +02:00
|
|
|
RTLIL::ObjRange<RTLIL::Module*, TwineRef> modules();
|
2026-06-08 23:40:51 +02:00
|
|
|
RTLIL::Module *module(IdString name);
|
2026-06-10 19:22:53 +02:00
|
|
|
const RTLIL::Module *module(IdString name) const;
|
|
|
|
|
RTLIL::Module *module(TwineRef name);
|
|
|
|
|
const RTLIL::Module *module(TwineRef name) const;
|
2025-04-08 01:57:43 +02:00
|
|
|
RTLIL::Module *top_module() const;
|
2014-07-27 21:12:09 +02:00
|
|
|
|
2026-06-10 19:22:53 +02:00
|
|
|
bool has(TwineRef id) const {
|
2014-07-29 16:06:27 +02:00
|
|
|
return modules_.count(id) != 0;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-27 21:12:09 +02:00
|
|
|
void add(RTLIL::Module *module);
|
2020-04-20 17:06:53 +02:00
|
|
|
void add(RTLIL::Binding *binding);
|
|
|
|
|
|
2026-06-09 18:50:00 +02:00
|
|
|
RTLIL::Module *addModule(TwineRef name);
|
2014-07-27 21:12:09 +02:00
|
|
|
void remove(RTLIL::Module *module);
|
2026-06-09 18:50:00 +02:00
|
|
|
void rename(RTLIL::Module *module, TwineRef new_name);
|
2014-07-27 10:40:31 +02:00
|
|
|
|
2020-03-18 19:21:53 +01:00
|
|
|
void scratchpad_unset(const std::string &varname);
|
2014-08-30 19:37:12 +02:00
|
|
|
|
2020-03-18 19:21:53 +01:00
|
|
|
void scratchpad_set_int(const std::string &varname, int value);
|
|
|
|
|
void scratchpad_set_bool(const std::string &varname, bool value);
|
2020-03-27 20:21:09 +01:00
|
|
|
void scratchpad_set_string(const std::string &varname, std::string value);
|
2014-08-30 19:37:12 +02:00
|
|
|
|
2020-03-18 19:21:53 +01:00
|
|
|
int scratchpad_get_int(const std::string &varname, int default_value = 0) const;
|
|
|
|
|
bool scratchpad_get_bool(const std::string &varname, bool default_value = false) const;
|
|
|
|
|
std::string scratchpad_get_string(const std::string &varname, const std::string &default_value = std::string()) const;
|
2014-08-30 19:37:12 +02:00
|
|
|
|
2015-01-24 00:13:27 +01:00
|
|
|
void sort();
|
2025-07-21 07:32:31 +02:00
|
|
|
void sort_modules();
|
2013-01-05 11:13:26 +01:00
|
|
|
void check();
|
|
|
|
|
void optimize();
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2026-06-05 12:04:19 +02:00
|
|
|
// Wholesale-copy this design into `dst`. `dst` must be empty (no
|
2026-06-08 23:40:51 +02:00
|
|
|
// modules). Copies twines verbatim and clones each module
|
2026-06-05 12:04:19 +02:00
|
|
|
// preserving src_id_ values directly — avoids the per-module
|
|
|
|
|
// copy_from pool rebuild and yields byte-identical RTLIL output
|
|
|
|
|
// across design -push/-pop, -save/-load, etc.
|
|
|
|
|
void clone_into(RTLIL::Design *dst) const;
|
|
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
// checks if the given module is included in the current selection
|
2026-06-09 18:50:00 +02:00
|
|
|
bool selected_module(TwineRef mod_name) const;
|
2025-04-08 01:57:43 +02:00
|
|
|
|
|
|
|
|
// checks if the given module is wholly included in the current
|
|
|
|
|
// selection, i.e. not partially selected
|
2026-06-09 18:50:00 +02:00
|
|
|
bool selected_whole_module(TwineRef mod_name) const;
|
2025-04-08 01:57:43 +02:00
|
|
|
|
|
|
|
|
// checks if the given member from the given module is included in the
|
|
|
|
|
// current selection
|
2026-06-09 18:50:00 +02:00
|
|
|
bool selected_member(TwineRef mod_name, TwineRef memb_name) const;
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
// checks if the given module is included in the current selection
|
2014-07-27 11:03:56 +02:00
|
|
|
bool selected_module(RTLIL::Module *mod) const;
|
2025-04-08 01:57:43 +02:00
|
|
|
|
|
|
|
|
// checks if the given module is wholly included in the current
|
|
|
|
|
// selection, i.e. not partially selected
|
2014-07-27 11:03:56 +02:00
|
|
|
bool selected_whole_module(RTLIL::Module *mod) const;
|
|
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
// push the given selection to the selection stack
|
|
|
|
|
void push_selection(RTLIL::Selection sel);
|
|
|
|
|
// push a new selection to the selection stack, with nothing selected
|
|
|
|
|
void push_empty_selection();
|
|
|
|
|
// push a new selection to the selection stack, with all non-boxed
|
|
|
|
|
// modules selected
|
|
|
|
|
void push_full_selection();
|
|
|
|
|
// push a new selection to the selection stack, with all modules
|
|
|
|
|
// selected including boxes
|
|
|
|
|
void push_complete_selection();
|
|
|
|
|
// pop the current selection from the stack, returning to a full
|
|
|
|
|
// selection (no boxes) if the stack is empty
|
|
|
|
|
void pop_selection();
|
|
|
|
|
|
|
|
|
|
// get the current selection
|
2015-02-24 22:31:30 +01:00
|
|
|
RTLIL::Selection &selection() {
|
|
|
|
|
return selection_stack.back();
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
// get the current selection
|
2015-02-24 22:31:30 +01:00
|
|
|
const RTLIL::Selection &selection() const {
|
|
|
|
|
return selection_stack.back();
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
// is the current selection a full selection (no boxes)
|
2013-10-27 09:30:58 +01:00
|
|
|
bool full_selection() const {
|
2025-04-08 01:57:43 +02:00
|
|
|
return selection().full_selection;
|
2013-10-27 09:30:58 +01:00
|
|
|
}
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
// is the given module in the current selection
|
2013-06-02 17:53:30 +02:00
|
|
|
template<typename T1> bool selected(T1 *module) const {
|
2013-01-05 11:13:26 +01:00
|
|
|
return selected_module(module->name);
|
|
|
|
|
}
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
// is the given member of the given module in the current selection
|
2013-06-02 17:53:30 +02:00
|
|
|
template<typename T1, typename T2> bool selected(T1 *module, T2 *member) const {
|
2026-06-10 19:22:53 +02:00
|
|
|
return selected_member(module->meta_->name, member->meta_->name);
|
2013-01-05 11:13:26 +01:00
|
|
|
}
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
// add whole module to the current selection
|
2020-06-17 22:28:56 +02:00
|
|
|
template<typename T1> void select(T1 *module) {
|
2025-04-08 01:57:43 +02:00
|
|
|
RTLIL::Selection &sel = selection();
|
|
|
|
|
sel.select(module);
|
2020-06-17 22:28:56 +02:00
|
|
|
}
|
|
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
// add member of module to the current selection
|
2013-03-03 20:53:24 +01:00
|
|
|
template<typename T1, typename T2> void select(T1 *module, T2 *member) {
|
2025-04-08 01:57:43 +02:00
|
|
|
RTLIL::Selection &sel = selection();
|
|
|
|
|
sel.select(module, member);
|
2013-03-03 20:53:24 +01:00
|
|
|
}
|
2014-07-31 14:11:39 +02:00
|
|
|
|
2018-07-09 15:48:06 +02:00
|
|
|
|
2025-04-08 01:57:43 +02:00
|
|
|
// returns all selected modules
|
|
|
|
|
std::vector<RTLIL::Module*> selected_modules(
|
|
|
|
|
// controls if partially selected modules are included
|
|
|
|
|
RTLIL::SelectPartials partials = SELECT_ALL,
|
|
|
|
|
// controls if boxed modules are included
|
|
|
|
|
RTLIL::SelectBoxes boxes = SB_UNBOXED_WARN
|
|
|
|
|
) const;
|
|
|
|
|
|
|
|
|
|
// returns all selected modules, and may include boxes
|
|
|
|
|
std::vector<RTLIL::Module*> all_selected_modules() const { return selected_modules(SELECT_ALL, SB_ALL); }
|
|
|
|
|
// returns all selected unboxed modules, silently ignoring any boxed
|
|
|
|
|
// modules in the selection
|
|
|
|
|
std::vector<RTLIL::Module*> selected_unboxed_modules() const { return selected_modules(SELECT_ALL, SB_UNBOXED_ONLY); }
|
|
|
|
|
// returns all selected unboxed modules, warning the user if any boxed
|
|
|
|
|
// modules have been ignored
|
|
|
|
|
std::vector<RTLIL::Module*> selected_unboxed_modules_warn() const { return selected_modules(SELECT_ALL, SB_UNBOXED_WARN); }
|
|
|
|
|
|
|
|
|
|
[[deprecated("Use select_unboxed_whole_modules() to maintain prior behaviour, or consider one of the other selected whole module helpers.")]]
|
|
|
|
|
std::vector<RTLIL::Module*> selected_whole_modules() const { return selected_modules(SELECT_WHOLE_ONLY, SB_UNBOXED_WARN); }
|
|
|
|
|
// returns all selected whole modules, silently ignoring partially
|
|
|
|
|
// selected modules, and may include boxes
|
|
|
|
|
std::vector<RTLIL::Module*> all_selected_whole_modules() const { return selected_modules(SELECT_WHOLE_ONLY, SB_ALL); }
|
|
|
|
|
// returns all selected whole modules, warning the user if any partially
|
|
|
|
|
// selected or boxed modules have been ignored; optionally includes
|
|
|
|
|
// selected whole modules with the 'whitebox' attribute
|
|
|
|
|
std::vector<RTLIL::Module*> selected_whole_modules_warn(
|
|
|
|
|
// should whole modules with the 'whitebox' attribute be
|
|
|
|
|
// included
|
|
|
|
|
bool include_wb = false
|
|
|
|
|
) const { return selected_modules(SELECT_WHOLE_WARN, include_wb ? SB_EXCL_BB_WARN : SB_UNBOXED_WARN); }
|
|
|
|
|
// returns all selected unboxed whole modules, silently ignoring
|
|
|
|
|
// partially selected or boxed modules
|
|
|
|
|
std::vector<RTLIL::Module*> selected_unboxed_whole_modules() const { return selected_modules(SELECT_WHOLE_ONLY, SB_UNBOXED_ONLY); }
|
|
|
|
|
// returns all selected unboxed whole modules, warning the user if any
|
|
|
|
|
// partially selected or boxed modules have been ignored
|
|
|
|
|
std::vector<RTLIL::Module*> selected_unboxed_whole_modules_warn() const { return selected_modules(SELECT_WHOLE_WARN, SB_UNBOXED_WARN); }
|
2026-01-15 02:35:45 +01:00
|
|
|
|
2018-08-13 15:18:46 +02:00
|
|
|
static std::map<unsigned int, RTLIL::Design*> *get_all_designs(void);
|
2026-01-14 15:37:18 +01:00
|
|
|
|
|
|
|
|
std::string to_rtlil_str(bool only_selected = true) const;
|
2013-01-05 11:13:26 +01:00
|
|
|
};
|
|
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
namespace RTLIL_BACKEND {
|
2026-06-05 12:04:19 +02:00
|
|
|
void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire, const RTLIL::Design *design, bool resolve_src);
|
2026-01-01 17:06:38 +01:00
|
|
|
}
|
|
|
|
|
|
2026-06-10 19:22:53 +02:00
|
|
|
struct RTLIL::Wire : public RTLIL::AttrObject
|
2014-07-25 15:05:18 +02:00
|
|
|
{
|
2026-01-01 17:06:38 +01:00
|
|
|
private:
|
|
|
|
|
struct ConstructToken { explicit ConstructToken() = default; };
|
2025-10-06 14:39:25 +02:00
|
|
|
friend struct RTLIL::Design;
|
2026-01-01 17:06:38 +01:00
|
|
|
friend struct RTLIL::Cell;
|
|
|
|
|
friend struct RTLIL::Module;
|
|
|
|
|
friend struct RTLIL::Patch;
|
|
|
|
|
public:
|
2026-06-08 23:40:51 +02:00
|
|
|
// Shadows NamedObject::name. Reads materialise via twines; writes
|
|
|
|
|
// are a compile error — use Module::rename(wire, new_name) instead.
|
|
|
|
|
[[no_unique_address]] RTLIL::WireNameMasq name;
|
|
|
|
|
|
2024-10-01 15:12:03 +02:00
|
|
|
Hasher::hash_t hashidx_;
|
2025-01-14 12:39:15 +01:00
|
|
|
[[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; }
|
2026-01-01 17:06:38 +01:00
|
|
|
// use module->addWire() and module->remove() to create or destroy wires
|
|
|
|
|
Wire(ConstructToken);
|
|
|
|
|
~Wire();
|
2014-12-28 17:51:16 +01:00
|
|
|
|
2026-06-05 12:04:19 +02:00
|
|
|
friend void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire, const RTLIL::Design *design, bool resolve_src);
|
2026-01-01 17:06:38 +01:00
|
|
|
RTLIL::Cell *driverCell_ = nullptr;
|
2026-06-10 19:22:53 +02:00
|
|
|
TwineRef driverPort_;
|
2020-04-20 17:06:53 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
// do not simply copy wires
|
|
|
|
|
Wire(ConstructToken, RTLIL::Wire &other);
|
|
|
|
|
void operator=(RTLIL::Wire &other) = delete;
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
RTLIL::Module *module;
|
|
|
|
|
int width, start_offset, port_id;
|
|
|
|
|
bool port_input, port_output, upto, is_signed;
|
2014-07-26 11:58:03 +02:00
|
|
|
|
2026-06-05 14:15:51 +02:00
|
|
|
// Context-aware src helpers. Resolve Design via module->design and
|
|
|
|
|
// route to the per-Design meta vector; assert the wire is attached.
|
2026-06-09 18:50:00 +02:00
|
|
|
TwineRef src_id() const;
|
|
|
|
|
TwineRef src_ref() const { return src_id(); }
|
|
|
|
|
void set_src_id(TwineRef id);
|
2026-06-10 19:22:53 +02:00
|
|
|
void set_src_attribute(TwineRef src);
|
2026-06-05 12:04:19 +02:00
|
|
|
std::string get_src_attribute() const;
|
|
|
|
|
// Transfer src from `source` verbatim (same pool). Asserts attached
|
2026-06-05 14:15:51 +02:00
|
|
|
// to a design.
|
2026-06-05 12:04:19 +02:00
|
|
|
void adopt_src_from(const RTLIL::AttrObject *source);
|
2026-06-05 14:15:51 +02:00
|
|
|
void absorb_attrs(dict<RTLIL::IdString, RTLIL::Const> &&buf);
|
2026-06-05 12:04:19 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
bool known_driver() const { return driverCell_ != nullptr; }
|
2015-01-24 00:13:27 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
RTLIL::Cell *driverCell() const { log_assert(driverCell_); return driverCell_; };
|
2026-06-10 19:22:53 +02:00
|
|
|
TwineRef driverPort() const { log_assert(driverCell_); return driverPort_; };
|
2014-07-26 11:58:03 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
int from_hdl_index(int hdl_index) {
|
|
|
|
|
int zero_index = hdl_index - start_offset;
|
|
|
|
|
int rtlil_index = upto ? width - 1 - zero_index : zero_index;
|
|
|
|
|
return rtlil_index >= 0 && rtlil_index < width ? rtlil_index : INT_MIN;
|
2024-11-27 23:19:16 +01:00
|
|
|
}
|
|
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
int to_hdl_index(int rtlil_index) {
|
|
|
|
|
if (rtlil_index < 0 || rtlil_index >= width)
|
|
|
|
|
return INT_MIN;
|
|
|
|
|
int zero_index = upto ? width - 1 - rtlil_index : rtlil_index;
|
|
|
|
|
return zero_index + start_offset;
|
|
|
|
|
}
|
2014-08-14 16:13:42 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
std::string to_rtlil_str() const;
|
2013-06-18 17:11:13 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
#ifdef YOSYS_ENABLE_PYTHON
|
|
|
|
|
static std::map<unsigned int, RTLIL::Wire*> *get_all_wires(void);
|
|
|
|
|
#endif
|
|
|
|
|
};
|
2023-09-29 15:49:15 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
inline int GetSize(RTLIL::Wire *wire) {
|
|
|
|
|
return wire->width;
|
|
|
|
|
}
|
2025-10-06 14:39:25 +02:00
|
|
|
|
2026-06-10 19:22:53 +02:00
|
|
|
struct RTLIL::Memory : public RTLIL::AttrObject
|
2026-01-01 17:06:38 +01:00
|
|
|
{
|
|
|
|
|
Hasher::hash_t hashidx_;
|
|
|
|
|
[[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; }
|
2025-10-06 14:39:25 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
Memory();
|
2026-06-05 14:15:51 +02:00
|
|
|
~Memory();
|
2013-10-24 10:59:27 +02:00
|
|
|
|
2026-06-05 13:49:50 +02:00
|
|
|
// Back-pointer to the owning module — same role as Cell::module /
|
|
|
|
|
// Wire::module. Set by Module::addMemory / the frontends that
|
|
|
|
|
// construct Memory free-standing before attaching to a module.
|
2026-06-05 14:15:51 +02:00
|
|
|
// Lets Memory's src access resolve uniformly via module->design.
|
2026-06-05 13:49:50 +02:00
|
|
|
RTLIL::Module *module = nullptr;
|
|
|
|
|
|
2026-06-05 14:15:51 +02:00
|
|
|
// Context-aware src helpers. Resolve Design via module->design and
|
|
|
|
|
// route to the per-Design meta vector; assert the memory is attached.
|
2026-06-09 18:50:00 +02:00
|
|
|
TwineRef src_id() const;
|
|
|
|
|
TwineRef src_ref() const { return src_id(); }
|
|
|
|
|
void set_src_id(TwineRef id);
|
2026-06-10 19:22:53 +02:00
|
|
|
void set_src_attribute(TwineRef src);
|
2026-06-05 14:15:51 +02:00
|
|
|
std::string get_src_attribute() const;
|
|
|
|
|
void adopt_src_from(const RTLIL::AttrObject *source);
|
|
|
|
|
void absorb_attrs(dict<RTLIL::IdString, RTLIL::Const> &&buf);
|
|
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
int width, start_offset, size;
|
|
|
|
|
#ifdef YOSYS_ENABLE_PYTHON
|
|
|
|
|
static std::map<unsigned int, RTLIL::Memory*> *get_all_memorys(void);
|
|
|
|
|
#endif
|
2014-07-31 14:11:39 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
std::string to_rtlil_str() const;
|
|
|
|
|
};
|
2014-07-31 14:11:39 +02:00
|
|
|
|
2026-06-10 19:22:53 +02:00
|
|
|
struct RTLIL::Cell : public RTLIL::AttrObject
|
2026-01-01 17:06:38 +01:00
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
struct ConstructToken { explicit ConstructToken() = default; };
|
|
|
|
|
friend struct RTLIL::Module;
|
|
|
|
|
friend struct RTLIL::Patch;
|
2026-05-23 01:09:26 +02:00
|
|
|
|
|
|
|
|
// Push existing port connections into signorm/bufnorm indices after module assignment.
|
|
|
|
|
// Assumes signals are already in normalized form.
|
|
|
|
|
void initIndex();
|
|
|
|
|
|
|
|
|
|
// Signorm index helpers (used by setPort/unsetPort/initIndex)
|
2026-06-10 19:22:53 +02:00
|
|
|
void signorm_index_remove(TwineRef portname, const RTLIL::SigSpec &old_signal, bool is_input);
|
|
|
|
|
void signorm_index_add(TwineRef portname, const RTLIL::SigSpec &new_signal, bool is_input);
|
|
|
|
|
bool bufnorm_handle_setPort(TwineRef portname, RTLIL::SigSpec &signal, dict<TwineRef, RTLIL::SigSpec>::iterator conn_it);
|
2026-01-01 17:06:38 +01:00
|
|
|
public:
|
2026-06-08 23:40:51 +02:00
|
|
|
// Shadows NamedObject::name. Reads materialise via twines; writes
|
|
|
|
|
// are a compile error — use Module::rename(cell, new_name) instead.
|
|
|
|
|
[[no_unique_address]] RTLIL::CellNameMasq name;
|
|
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
Hasher::hash_t hashidx_;
|
|
|
|
|
[[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; }
|
2025-04-08 01:57:43 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
// use module->addCell() and module->remove() to create or destroy cells
|
|
|
|
|
Cell(ConstructToken);
|
|
|
|
|
~Cell();
|
2014-07-31 14:11:39 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
// do not simply copy cells
|
|
|
|
|
Cell(ConstructToken, RTLIL::Cell &other);
|
|
|
|
|
void operator=(RTLIL::Cell &other) = delete;
|
2014-08-05 14:47:03 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
RTLIL::Module *module;
|
2026-06-11 20:02:02 +02:00
|
|
|
TwineRef type_impl;
|
|
|
|
|
[[no_unique_address]] RTLIL::CellTypeMasq type;
|
2026-06-10 19:22:53 +02:00
|
|
|
dict<TwineRef, RTLIL::SigSpec> connections_;
|
2026-01-01 17:06:38 +01:00
|
|
|
dict<RTLIL::IdString, RTLIL::Const> parameters;
|
2014-07-27 11:03:56 +02:00
|
|
|
|
2026-06-05 14:15:51 +02:00
|
|
|
// Context-aware src helpers. Resolve Design via module->design and
|
|
|
|
|
// route to the per-Design meta vector; assert the cell is attached.
|
2026-06-09 18:50:00 +02:00
|
|
|
TwineRef src_id() const;
|
|
|
|
|
TwineRef src_ref() const { return src_id(); }
|
|
|
|
|
void set_src_id(TwineRef id);
|
2026-06-10 19:22:53 +02:00
|
|
|
void set_src_attribute(TwineRef src);
|
2026-06-05 12:04:19 +02:00
|
|
|
std::string get_src_attribute() const;
|
|
|
|
|
void adopt_src_from(const RTLIL::AttrObject *source);
|
2026-06-05 14:15:51 +02:00
|
|
|
void absorb_attrs(dict<RTLIL::IdString, RTLIL::Const> &&buf);
|
2026-06-05 12:04:19 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
// access cell ports
|
2026-06-09 18:50:00 +02:00
|
|
|
bool hasPort(TwineRef portname) const;
|
|
|
|
|
void unsetPort(TwineRef portname);
|
|
|
|
|
void setPort(TwineRef portname, RTLIL::SigSpec signal);
|
|
|
|
|
const RTLIL::SigSpec &getPort(TwineRef portname) const;
|
|
|
|
|
const dict<TwineRef, RTLIL::SigSpec> &connections() const;
|
2021-03-24 16:23:23 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
// information about cell ports
|
|
|
|
|
bool known() const;
|
2026-06-09 18:50:00 +02:00
|
|
|
bool input(TwineRef portname) const;
|
|
|
|
|
bool output(TwineRef portname) const;
|
|
|
|
|
PortDir port_dir(TwineRef portname) const;
|
2014-07-27 10:13:22 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
// access cell parameters
|
|
|
|
|
bool hasParam(RTLIL::IdString paramname) const;
|
|
|
|
|
void unsetParam(RTLIL::IdString paramname);
|
|
|
|
|
void setParam(RTLIL::IdString paramname, RTLIL::Const value);
|
|
|
|
|
const RTLIL::Const &getParam(RTLIL::IdString paramname) const;
|
2020-04-20 17:06:53 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
void sort();
|
|
|
|
|
void check();
|
|
|
|
|
void fixup_parameters(bool set_a_signed = false, bool set_b_signed = false);
|
2014-07-21 12:35:06 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
bool has_keep_attr() const;
|
2014-07-25 15:05:18 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
template<typename T> void rewrite_sigspecs(T &functor);
|
|
|
|
|
template<typename T> void rewrite_sigspecs2(T &functor);
|
2014-08-05 14:47:03 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
#ifdef YOSYS_ENABLE_PYTHON
|
|
|
|
|
static std::map<unsigned int, RTLIL::Cell*> *get_all_cells(void);
|
|
|
|
|
#endif
|
2014-08-16 23:50:36 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
bool has_memid() const;
|
|
|
|
|
bool is_mem_cell() const;
|
|
|
|
|
bool is_builtin_ff() const;
|
2014-07-26 21:16:05 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
std::string to_rtlil_str() const;
|
|
|
|
|
};
|
2014-07-21 12:02:55 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
struct RTLIL::CaseRule : public RTLIL::AttrObject
|
|
|
|
|
{
|
2026-06-05 13:35:46 +02:00
|
|
|
// Back-pointer to the owning module. Set by the frontend / kernel
|
|
|
|
|
// attach path before any src access; the per-Design src meta vector
|
|
|
|
|
// is resolved as `module->design`. Frontends that construct an
|
|
|
|
|
// inner-process tree must call setModuleRecursive() on the root before
|
|
|
|
|
// the tree is consumed (e.g. before set_src_attribute is invoked on
|
|
|
|
|
// any nested CaseRule/SwitchRule/MemWriteAction).
|
|
|
|
|
RTLIL::Module *module = nullptr;
|
|
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
std::vector<RTLIL::SigSpec> compare;
|
|
|
|
|
std::vector<RTLIL::SigSig> actions;
|
|
|
|
|
std::vector<RTLIL::SwitchRule*> switches;
|
2020-06-03 16:35:27 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
~CaseRule();
|
2020-06-09 11:55:48 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
bool empty() const;
|
2014-07-18 10:27:06 +02:00
|
|
|
|
2026-06-05 13:35:46 +02:00
|
|
|
// Walk the whole CaseRule subtree (this case, every switch, every
|
|
|
|
|
// nested case, every MemWriteAction inside this process's sync rules
|
|
|
|
|
// — those are reached through Process, not here) and set `module` on
|
|
|
|
|
// each. Idempotent.
|
|
|
|
|
void setModuleRecursive(RTLIL::Module *m);
|
|
|
|
|
|
2026-06-05 14:15:51 +02:00
|
|
|
// Context-aware src helpers via module->design.
|
2026-06-09 18:50:00 +02:00
|
|
|
TwineRef src_id() const;
|
|
|
|
|
TwineRef src_ref() const { return src_id(); }
|
|
|
|
|
void set_src_id(TwineRef id);
|
2026-06-10 19:22:53 +02:00
|
|
|
void set_src_attribute(TwineRef src);
|
2026-06-05 14:15:51 +02:00
|
|
|
std::string get_src_attribute() const;
|
|
|
|
|
void adopt_src_from(const RTLIL::AttrObject *source);
|
|
|
|
|
void absorb_attrs(dict<RTLIL::IdString, RTLIL::Const> &&buf);
|
|
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
template<typename T> void rewrite_sigspecs(T &functor);
|
|
|
|
|
template<typename T> void rewrite_sigspecs2(T &functor);
|
|
|
|
|
RTLIL::CaseRule *clone() const;
|
|
|
|
|
};
|
2020-03-18 19:21:53 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
struct RTLIL::SwitchRule : public RTLIL::AttrObject
|
|
|
|
|
{
|
2026-06-05 13:35:46 +02:00
|
|
|
// Back-pointer to the owning module; see CaseRule::module.
|
|
|
|
|
RTLIL::Module *module = nullptr;
|
|
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
RTLIL::SigSpec signal;
|
|
|
|
|
std::vector<RTLIL::CaseRule*> cases;
|
2020-03-18 19:21:53 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
~SwitchRule();
|
2020-03-18 19:21:53 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
bool empty() const;
|
|
|
|
|
|
2026-06-05 13:35:46 +02:00
|
|
|
void setModuleRecursive(RTLIL::Module *m);
|
|
|
|
|
|
2026-06-05 14:15:51 +02:00
|
|
|
// Context-aware src helpers via module->design.
|
2026-06-09 18:50:00 +02:00
|
|
|
TwineRef src_id() const;
|
|
|
|
|
TwineRef src_ref() const { return src_id(); }
|
|
|
|
|
void set_src_id(TwineRef id);
|
2026-06-10 19:22:53 +02:00
|
|
|
void set_src_attribute(TwineRef src);
|
2026-06-05 14:15:51 +02:00
|
|
|
std::string get_src_attribute() const;
|
|
|
|
|
void adopt_src_from(const RTLIL::AttrObject *source);
|
|
|
|
|
void absorb_attrs(dict<RTLIL::IdString, RTLIL::Const> &&buf);
|
|
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
template<typename T> void rewrite_sigspecs(T &functor);
|
|
|
|
|
template<typename T> void rewrite_sigspecs2(T &functor);
|
|
|
|
|
RTLIL::SwitchRule *clone() const;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct RTLIL::MemWriteAction : RTLIL::AttrObject
|
|
|
|
|
{
|
2026-06-05 13:35:46 +02:00
|
|
|
// Back-pointer to the owning module; see CaseRule::module.
|
|
|
|
|
RTLIL::Module *module = nullptr;
|
|
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
RTLIL::IdString memid;
|
|
|
|
|
RTLIL::SigSpec address;
|
|
|
|
|
RTLIL::SigSpec data;
|
|
|
|
|
RTLIL::SigSpec enable;
|
|
|
|
|
RTLIL::Const priority_mask;
|
2026-06-05 14:15:51 +02:00
|
|
|
|
|
|
|
|
// Context-aware src helpers via module->design.
|
2026-06-09 18:50:00 +02:00
|
|
|
TwineRef src_id() const;
|
|
|
|
|
TwineRef src_ref() const { return src_id(); }
|
|
|
|
|
void set_src_id(TwineRef id);
|
2026-06-10 19:22:53 +02:00
|
|
|
void set_src_attribute(TwineRef src);
|
2026-06-05 14:15:51 +02:00
|
|
|
std::string get_src_attribute() const;
|
|
|
|
|
void adopt_src_from(const RTLIL::AttrObject *source);
|
|
|
|
|
void absorb_attrs(dict<RTLIL::IdString, RTLIL::Const> &&buf);
|
2026-01-01 17:06:38 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct RTLIL::SyncRule
|
|
|
|
|
{
|
|
|
|
|
RTLIL::SyncType type;
|
|
|
|
|
RTLIL::SigSpec signal;
|
|
|
|
|
std::vector<RTLIL::SigSig> actions;
|
|
|
|
|
std::vector<RTLIL::MemWriteAction> mem_write_actions;
|
|
|
|
|
|
|
|
|
|
template<typename T> void rewrite_sigspecs(T &functor);
|
|
|
|
|
template<typename T> void rewrite_sigspecs2(T &functor);
|
|
|
|
|
RTLIL::SyncRule *clone() const;
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-10 19:22:53 +02:00
|
|
|
struct RTLIL::Process : public RTLIL::AttrObject
|
2026-01-01 17:06:38 +01:00
|
|
|
{
|
|
|
|
|
friend struct RTLIL::SigNormIndex;
|
|
|
|
|
friend struct RTLIL::Cell;
|
|
|
|
|
friend struct RTLIL::Design;
|
|
|
|
|
|
|
|
|
|
Hasher::hash_t hashidx_;
|
|
|
|
|
[[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; }
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
// use module->addProcess() and module->remove() to create or destroy processes
|
|
|
|
|
friend struct RTLIL::Module;
|
|
|
|
|
Process();
|
|
|
|
|
~Process();
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
RTLIL::Module *module;
|
|
|
|
|
RTLIL::CaseRule root_case;
|
|
|
|
|
std::vector<RTLIL::SyncRule*> syncs;
|
|
|
|
|
|
2026-06-05 14:15:51 +02:00
|
|
|
// Context-aware src helpers. Resolve Design via module->design and
|
|
|
|
|
// route to the per-Design meta vector; assert the process is attached.
|
2026-06-09 18:50:00 +02:00
|
|
|
TwineRef src_id() const;
|
|
|
|
|
TwineRef src_ref() const { return src_id(); }
|
|
|
|
|
void set_src_id(TwineRef id);
|
2026-06-10 19:22:53 +02:00
|
|
|
void set_src_attribute(TwineRef src);
|
2026-06-05 12:04:19 +02:00
|
|
|
std::string get_src_attribute() const;
|
|
|
|
|
void adopt_src_from(const RTLIL::AttrObject *source);
|
2026-06-05 14:15:51 +02:00
|
|
|
void absorb_attrs(dict<RTLIL::IdString, RTLIL::Const> &&buf);
|
2026-06-05 12:04:19 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
template<typename T> void rewrite_sigspecs(T &functor);
|
|
|
|
|
template<typename T> void rewrite_sigspecs2(T &functor);
|
|
|
|
|
RTLIL::Process *clone() const;
|
|
|
|
|
|
|
|
|
|
std::string to_rtlil_str() const;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct RTLIL::PortBit
|
|
|
|
|
{
|
|
|
|
|
RTLIL::Cell *cell;
|
2026-06-10 19:22:53 +02:00
|
|
|
TwineRef port;
|
2026-01-01 17:06:38 +01:00
|
|
|
int offset;
|
2026-06-10 19:22:53 +02:00
|
|
|
PortBit(Cell* c, TwineRef p, int o) : cell(c), port(p), offset(o) {}
|
2026-01-01 17:06:38 +01:00
|
|
|
|
|
|
|
|
bool operator<(const PortBit &other) const {
|
|
|
|
|
if (cell != other.cell)
|
|
|
|
|
return cell < other.cell;
|
|
|
|
|
if (port != other.port)
|
|
|
|
|
return port < other.port;
|
|
|
|
|
return offset < other.offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool operator==(const PortBit &other) const {
|
|
|
|
|
return cell == other.cell && port == other.port && offset == other.offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] Hasher hash_into(Hasher h) const {
|
|
|
|
|
h.eat(cell->name);
|
|
|
|
|
h.eat(port);
|
|
|
|
|
h.eat(offset);
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline RTLIL::SigBit::SigBit() : wire(NULL), data(RTLIL::State::S0) { }
|
|
|
|
|
inline RTLIL::SigBit::SigBit(RTLIL::State bit) : wire(NULL), data(bit) { }
|
|
|
|
|
inline RTLIL::SigBit::SigBit(bool bit) : wire(NULL), data(bit ? State::S1 : State::S0) { }
|
|
|
|
|
inline RTLIL::SigBit::SigBit(RTLIL::Wire *wire) : wire(wire), offset(0) { log_assert(wire && wire->width == 1); }
|
|
|
|
|
inline RTLIL::SigBit::SigBit(RTLIL::Wire *wire, int offset) : wire(wire), offset(offset) { log_assert(wire != nullptr); }
|
|
|
|
|
inline RTLIL::SigBit::SigBit(const RTLIL::SigChunk &chunk) : wire(chunk.wire) { log_assert(chunk.width == 1); if (wire) offset = chunk.offset; else data = chunk.data[0]; }
|
|
|
|
|
inline RTLIL::SigBit::SigBit(const RTLIL::SigChunk &chunk, int index) : wire(chunk.wire) { if (wire) offset = chunk.offset + index; else data = chunk.data[index]; }
|
|
|
|
|
|
|
|
|
|
inline bool RTLIL::SigBit::operator<(const RTLIL::SigBit &other) const {
|
|
|
|
|
if (wire == other.wire)
|
|
|
|
|
return wire ? (offset < other.offset) : (data < other.data);
|
|
|
|
|
if (wire != nullptr && other.wire != nullptr)
|
|
|
|
|
return wire->name < other.wire->name;
|
|
|
|
|
return (wire != nullptr) < (other.wire != nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline bool RTLIL::SigBit::operator==(const RTLIL::SigBit &other) const {
|
|
|
|
|
return (wire == other.wire) && (wire ? (offset == other.offset) : (data == other.data));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline bool RTLIL::SigBit::operator!=(const RTLIL::SigBit &other) const {
|
|
|
|
|
return (wire != other.wire) || (wire ? (offset != other.offset) : (data != other.data));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline Hasher RTLIL::SigBit::hash_into(Hasher h) const {
|
|
|
|
|
if (wire) {
|
|
|
|
|
h.eat(offset);
|
|
|
|
|
h.eat(wire->name);
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
h.eat(data);
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline Hasher RTLIL::SigBit::hash_top() const {
|
|
|
|
|
Hasher h;
|
|
|
|
|
if (wire) {
|
2026-06-10 19:22:53 +02:00
|
|
|
// Use the wire's name (TwineRef) directly — avoids IdString materialisation.
|
|
|
|
|
TwineRef name = wire->meta_ ? wire->meta_->name : Twine::Null;
|
|
|
|
|
h.eat(name);
|
2026-06-08 23:40:51 +02:00
|
|
|
h.eat(offset);
|
2026-01-01 17:06:38 +01:00
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
h.force(data);
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const {
|
|
|
|
|
return (*sig_p)[index];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() {
|
|
|
|
|
bit = (*sig_p)[index];
|
|
|
|
|
return bit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) {
|
|
|
|
|
log_assert(sig.size() == 1);
|
|
|
|
|
auto it = sig.chunks().begin();
|
|
|
|
|
*this = SigBit(*it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
|
class CellAdderMixin {
|
|
|
|
|
public:
|
|
|
|
|
// The add* methods create a cell and return the created cell. All signals must exist in advance.
|
|
|
|
|
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addNot (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addPos (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addBuf (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addNeg (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::Cell* addAnd (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addOr (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addXor (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addXnor (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::Cell* addReduceAnd (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addReduceOr (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addReduceXor (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addReduceXnor (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addReduceBool (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::Cell* addShl (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addShr (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addSshl (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addSshr (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addShift (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addShiftx (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::Cell* addLt (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addLe (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addEq (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addNe (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addEqx (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addNex (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addGe (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addGt (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::Cell* addAdd (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addSub (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addMul (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
2020-05-02 11:24:19 +02:00
|
|
|
// truncating division
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addDiv (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
2020-05-02 11:24:19 +02:00
|
|
|
// truncating modulo
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addMod (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addDivFloor (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addModFloor (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addPow (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool a_signed = false, bool b_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::Cell* addFa (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_c, const RTLIL::SigSpec &sig_x, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::Cell* addLogicNot (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addLogicAnd (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addLogicOr (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::Cell* addMux (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addPmux (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addBmux (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addDemux (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::Cell* addBweqx (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addBwmux (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::Cell* addSlice (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const offset, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addConcat (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addLut (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const lut, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addTribuf (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addAssert (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addAssume (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addLive (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addFair (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addCover (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addEquiv (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::Cell* addSr (Twine &&name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, const RTLIL::SigSpec &sig_q, bool set_polarity = true, bool clr_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addFf (Twine &&name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addDff (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addDffe (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool en_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addDffsr (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool set_polarity = true, bool clr_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addDffsre (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addAdff (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const arst_value, bool clk_polarity = true, bool arst_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addAdffe (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const arst_value, bool clk_polarity = true, bool en_polarity = true, bool arst_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addAldff (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool aload_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addAldffe (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool en_polarity = true, bool aload_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addSdff (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const srst_value, bool clk_polarity = true, bool srst_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addSdffe (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const srst_value, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addSdffce (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const srst_value, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addDlatch (Twine &&name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addAdlatch (Twine &&name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const arst_value, bool en_polarity = true, bool arst_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addDlatchsr (Twine &&name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::Cell* addBufGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addNotGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addAndGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addNandGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addOrGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addNorGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addXorGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addXnorGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addAndnotGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addOrnotGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addMuxGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addNmuxGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addAoi3Gate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addOai3Gate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addAoi4Gate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addOai4Gate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, const RTLIL::SigBit &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::Cell* addSrGate (Twine &&name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr,
|
2026-06-09 18:50:00 +02:00
|
|
|
const RTLIL::SigSpec &sig_q, bool set_polarity = true, bool clr_polarity = true, TwineRef src = Twine::Null);
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addFfGate (Twine &&name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addDffGate (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addDffeGate (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool en_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addDffsrGate (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr,
|
2026-06-09 18:50:00 +02:00
|
|
|
RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool set_polarity = true, bool clr_polarity = true, TwineRef src = Twine::Null);
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addDffsreGate (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr,
|
2026-06-09 18:50:00 +02:00
|
|
|
RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, TwineRef src = Twine::Null);
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addAdffGate (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
|
2026-06-09 18:50:00 +02:00
|
|
|
bool arst_value = false, bool clk_polarity = true, bool arst_polarity = true, TwineRef src = Twine::Null);
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addAdffeGate (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
|
2026-06-09 18:50:00 +02:00
|
|
|
bool arst_value = false, bool clk_polarity = true, bool en_polarity = true, bool arst_polarity = true, TwineRef src = Twine::Null);
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addAldffGate (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
|
2026-06-09 18:50:00 +02:00
|
|
|
const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool aload_polarity = true, TwineRef src = Twine::Null);
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addAldffeGate (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
|
2026-06-09 18:50:00 +02:00
|
|
|
const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool en_polarity = true, bool aload_polarity = true, TwineRef src = Twine::Null);
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addSdffGate (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
|
2026-06-09 18:50:00 +02:00
|
|
|
bool srst_value = false, bool clk_polarity = true, bool srst_polarity = true, TwineRef src = Twine::Null);
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addSdffeGate (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
|
2026-06-09 18:50:00 +02:00
|
|
|
bool srst_value = false, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, TwineRef src = Twine::Null);
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addSdffceGate (Twine &&name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
|
2026-06-09 18:50:00 +02:00
|
|
|
bool srst_value = false, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, TwineRef src = Twine::Null);
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addDlatchGate (Twine &&name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addAdlatchGate(Twine &&name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
|
2026-06-09 18:50:00 +02:00
|
|
|
bool arst_value = false, bool en_polarity = true, bool arst_polarity = true, TwineRef src = Twine::Null);
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell* addDlatchsrGate (Twine &&name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr,
|
2026-06-09 18:50:00 +02:00
|
|
|
RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, TwineRef src = Twine::Null);
|
2014-07-18 10:27:06 +02:00
|
|
|
|
|
|
|
|
// The methods without the add* prefix create a cell and an output signal. They return the newly created output signal.
|
|
|
|
|
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::SigSpec Not (Twine &&name, const RTLIL::SigSpec &sig_a, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Pos (Twine &&name, const RTLIL::SigSpec &sig_a, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Buf (Twine &&name, const RTLIL::SigSpec &sig_a, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Neg (Twine &&name, const RTLIL::SigSpec &sig_a, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::SigSpec And (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Or (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Xor (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Xnor (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::SigSpec ReduceAnd (Twine &&name, const RTLIL::SigSpec &sig_a, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec ReduceOr (Twine &&name, const RTLIL::SigSpec &sig_a, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec ReduceXor (Twine &&name, const RTLIL::SigSpec &sig_a, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec ReduceXnor (Twine &&name, const RTLIL::SigSpec &sig_a, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec ReduceBool (Twine &&name, const RTLIL::SigSpec &sig_a, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::SigSpec Shl (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Shr (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Sshl (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Sshr (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Shift (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Shiftx (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::SigSpec Lt (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Le (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Eq (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Ne (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Eqx (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Nex (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Ge (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Gt (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::SigSpec Add (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Sub (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Mul (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
2020-05-02 11:24:19 +02:00
|
|
|
// truncating division
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::SigSpec Div (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
2020-05-02 11:24:19 +02:00
|
|
|
// truncating modulo
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::SigSpec Mod (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec DivFloor (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec ModFloor (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Pow (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool a_signed = false, bool b_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::SigSpec LogicNot (Twine &&name, const RTLIL::SigSpec &sig_a, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec LogicAnd (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec LogicOr (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::SigSpec Mux (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Pmux (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Bmux (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Demux (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::SigSpec Bweqx (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Bwmux (Twine &&name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, TwineRef src = Twine::Null);
|
|
|
|
|
|
|
|
|
|
RTLIL::SigBit BufGate (Twine &&name, const RTLIL::SigBit &sig_a, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit NotGate (Twine &&name, const RTLIL::SigBit &sig_a, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit AndGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit NandGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit OrGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit NorGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit XorGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit XnorGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit AndnotGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit OrnotGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit MuxGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit NmuxGate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit Aoi3Gate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit Oai3Gate (Twine &&name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigBit Aoi4Gate (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);
|
|
|
|
|
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);
|
2013-01-05 11:13:26 +01:00
|
|
|
};
|
|
|
|
|
|
2026-06-05 23:40:22 +02:00
|
|
|
// Zero-size masquerade for Module::name. Reads/writes route through
|
|
|
|
|
// module->design->obj_name(this) / obj_set_name. 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 {
|
2026-06-06 13:32:57 +02:00
|
|
|
// 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
|
|
|
|
|
// operator IdString() at the embedded location.
|
|
|
|
|
ModuleNameMasq() = default;
|
|
|
|
|
ModuleNameMasq(const ModuleNameMasq&) = delete;
|
|
|
|
|
ModuleNameMasq(ModuleNameMasq&&) = delete;
|
2026-06-05 23:40:22 +02:00
|
|
|
operator RTLIL::IdString() const;
|
2026-06-09 18:50:00 +02:00
|
|
|
operator TwineRef() const;
|
2026-06-05 23:40:22 +02:00
|
|
|
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); }
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-11 13:17:54 +02:00
|
|
|
struct RTLIL::Module : public RTLIL::AttrObject, public CellAdderMixin<RTLIL::Module>
|
2014-07-26 11:58:03 +02:00
|
|
|
{
|
2026-01-01 17:06:38 +01:00
|
|
|
friend struct RTLIL::SigNormIndex;
|
2025-12-23 16:58:16 +01:00
|
|
|
friend struct RTLIL::Cell;
|
2026-01-01 17:06:38 +01:00
|
|
|
friend struct RTLIL::Design;
|
|
|
|
|
|
2026-06-11 13:17:54 +02:00
|
|
|
[[no_unique_address]] RTLIL::ModuleNameMasq name;
|
2026-06-05 23:40:22 +02:00
|
|
|
|
2024-10-01 15:12:03 +02:00
|
|
|
Hasher::hash_t hashidx_;
|
2025-01-14 12:39:15 +01:00
|
|
|
[[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; }
|
2014-07-26 11:58:03 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
protected:
|
|
|
|
|
void add(RTLIL::Wire *wire);
|
|
|
|
|
void add(RTLIL::Cell *cell);
|
|
|
|
|
void add(RTLIL::Process *process);
|
2024-05-21 13:08:40 +02:00
|
|
|
|
2014-07-26 11:58:03 +02:00
|
|
|
public:
|
2026-01-01 17:06:38 +01:00
|
|
|
RTLIL::Design *design;
|
|
|
|
|
pool<RTLIL::Monitor*> monitors;
|
2014-07-26 11:58:03 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
int refcount_wires_;
|
|
|
|
|
int refcount_cells_;
|
2018-07-09 15:48:06 +02:00
|
|
|
|
2026-06-09 18:50:00 +02:00
|
|
|
dict<TwineRef, RTLIL::Wire*> wires_;
|
|
|
|
|
dict<TwineRef, RTLIL::Cell*> cells_;
|
2025-09-03 15:29:08 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
std::vector<RTLIL::SigSig> connections_;
|
|
|
|
|
std::vector<RTLIL::Binding*> bindings_;
|
2023-09-29 15:49:15 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
idict<RTLIL::IdString> avail_parameters;
|
|
|
|
|
dict<RTLIL::IdString, RTLIL::Const> parameter_default_values;
|
2026-06-11 13:17:54 +02:00
|
|
|
dict<TwineRef, RTLIL::Memory*> memories;
|
|
|
|
|
dict<TwineRef, RTLIL::Process*> processes;
|
2025-02-12 15:34:51 +01:00
|
|
|
|
2026-06-05 14:15:51 +02:00
|
|
|
// Context-aware src helpers. Resolve Design via this->design and
|
|
|
|
|
// route to the per-Design meta vector; assert the module is attached.
|
2026-06-09 18:50:00 +02:00
|
|
|
TwineRef src_id() const;
|
|
|
|
|
TwineRef src_ref() const { return src_id(); }
|
|
|
|
|
void set_src_id(TwineRef id);
|
2026-06-10 19:22:53 +02:00
|
|
|
void set_src_attribute(TwineRef src);
|
2026-06-05 12:04:19 +02:00
|
|
|
std::string get_src_attribute() const;
|
|
|
|
|
void adopt_src_from(const RTLIL::AttrObject *source);
|
2026-06-05 14:15:51 +02:00
|
|
|
void absorb_attrs(dict<RTLIL::IdString, RTLIL::Const> &&buf);
|
2026-06-05 12:04:19 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
Module();
|
|
|
|
|
virtual ~Module();
|
2026-06-11 20:02:02 +02:00
|
|
|
virtual TwineRef derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, bool mayfail = false);
|
2026-06-12 00:18:53 +02:00
|
|
|
virtual TwineRef derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, const dict<TwineRef, RTLIL::Module*> &interfaces, const dict<TwineRef, TwineRef> &modports, bool mayfail = false);
|
2026-06-10 19:22:53 +02:00
|
|
|
virtual size_t count_id(TwineRef id);
|
2026-01-01 17:06:38 +01:00
|
|
|
virtual void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces);
|
|
|
|
|
virtual bool reprocess_if_necessary(RTLIL::Design *design);
|
2025-02-12 15:34:51 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
virtual void sort();
|
|
|
|
|
virtual void check();
|
|
|
|
|
virtual void optimize();
|
|
|
|
|
virtual void makeblackbox();
|
2013-01-05 11:13:26 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
bool get_blackbox_attribute(bool ignore_wb=false) const {
|
|
|
|
|
return get_bool_attribute(ID::blackbox) || (!ignore_wb && get_bool_attribute(ID::whitebox));
|
|
|
|
|
}
|
2014-12-28 17:51:16 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
void connect(const RTLIL::SigSig &conn);
|
|
|
|
|
void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs);
|
|
|
|
|
void new_connections(const std::vector<RTLIL::SigSig> &new_conn);
|
|
|
|
|
const std::vector<RTLIL::SigSig> &connections() const;
|
2014-07-26 11:58:03 +02:00
|
|
|
|
2026-06-09 18:50:00 +02:00
|
|
|
std::vector<TwineRef> ports;
|
2026-01-01 17:06:38 +01:00
|
|
|
void fixup_ports();
|
2026-01-14 15:37:18 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
pool<RTLIL::Cell *> buf_norm_cell_queue;
|
2026-06-10 19:22:53 +02:00
|
|
|
pool<pair<RTLIL::Cell *, TwineRef>> buf_norm_cell_port_queue;
|
2026-01-01 17:06:38 +01:00
|
|
|
pool<RTLIL::Wire *> buf_norm_wire_queue;
|
|
|
|
|
pool<RTLIL::Cell *> pending_deleted_cells;
|
|
|
|
|
dict<RTLIL::Wire *, pool<RTLIL::Cell *>> buf_norm_connect_index;
|
|
|
|
|
void bufNormalize();
|
|
|
|
|
void dump_sigmap();
|
2013-01-05 11:13:26 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
protected:
|
|
|
|
|
SigNormIndex *sig_norm_index = nullptr;
|
|
|
|
|
void clear_sig_norm_index();
|
|
|
|
|
int timestamp_ = 0;
|
2025-12-21 16:56:14 +01:00
|
|
|
public:
|
2026-01-01 17:06:38 +01:00
|
|
|
void sigNormalize();
|
2014-07-25 15:05:18 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
int timestamp() const { return timestamp_; }
|
|
|
|
|
int next_timestamp();
|
|
|
|
|
std::vector<Cell *> dirty_cells(int starting_from);
|
|
|
|
|
const pool<PortBit> &fanout(SigBit bit);
|
|
|
|
|
const dict<SigBit, pool<PortBit>> &signorm_fanout() const;
|
2014-07-25 15:05:18 +02:00
|
|
|
|
2026-05-29 12:36:48 +02:00
|
|
|
// Equivalent to `connect(lhs, rhs)` followed by `sigNormalize()` for the
|
|
|
|
|
// merge implied by this single connection: updates the sigmap, promotes
|
|
|
|
|
// the driven side as canonical, and re-normalizes any existing fanout
|
|
|
|
|
// consumers of the demoted side. Lets callers in signorm mode merge
|
|
|
|
|
// signals without the overhead of a full normalize.
|
|
|
|
|
void connect_incremental(const SigSpec &lhs, const SigSpec &rhs);
|
|
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
template<typename T> void rewrite_sigspecs(T &functor);
|
|
|
|
|
template<typename T> void rewrite_sigspecs2(T &functor);
|
2026-06-05 12:04:19 +02:00
|
|
|
// `src_id_verbatim`: when true, the caller guarantees that
|
2026-06-08 23:40:51 +02:00
|
|
|
// `new_mod->design->twines` is a verbatim copy of
|
|
|
|
|
// `this->design->twines`, so src_id_ values can be transferred
|
2026-06-05 12:04:19 +02:00
|
|
|
// without retain/release on the destination pool (the copied refcounts
|
|
|
|
|
// already account for the new AttrObject references). Used by
|
|
|
|
|
// Design::clone_into for wholesale design copies.
|
|
|
|
|
void cloneInto(RTLIL::Module *new_mod, bool src_id_verbatim = false) const;
|
2026-01-01 17:06:38 +01:00
|
|
|
virtual RTLIL::Module *clone() const;
|
2026-06-05 12:04:19 +02:00
|
|
|
// Clone variant that attaches the new module to `dst` BEFORE cloneInto
|
|
|
|
|
// runs. This is the right pattern when the destination design is known
|
|
|
|
|
// up front — it avoids the "detached module, attach later" flow and
|
|
|
|
|
// the pending-literal src stashing it entails. Subtypes override to
|
|
|
|
|
// preserve their type (AstModule). `src_id_verbatim` is forwarded to
|
|
|
|
|
// cloneInto.
|
|
|
|
|
virtual RTLIL::Module *clone(RTLIL::Design *dst, bool src_id_verbatim = false) const;
|
2026-06-06 13:32:57 +02:00
|
|
|
// As above, but additionally renames the new module to `target_name` in
|
|
|
|
|
// `dst`. Used when source and destination designs may contain modules
|
|
|
|
|
// with the same name and the new one must take a different identity.
|
2026-06-11 20:02:02 +02:00
|
|
|
virtual RTLIL::Module *clone(RTLIL::Design *dst, TwineRef target_name, bool src_id_verbatim = false) const;
|
2014-07-26 12:22:58 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
bool has_memories() const;
|
|
|
|
|
bool has_processes() const;
|
2014-07-26 12:22:58 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
bool has_memories_warn() const;
|
|
|
|
|
bool has_processes_warn() const;
|
2015-02-07 11:40:19 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
bool is_selected() const;
|
|
|
|
|
bool is_selected_whole() const;
|
2014-07-31 16:38:54 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
std::vector<RTLIL::Wire*> selected_wires() const;
|
|
|
|
|
std::vector<RTLIL::Cell*> selected_cells() const;
|
|
|
|
|
std::vector<RTLIL::Memory*> selected_memories() const;
|
|
|
|
|
std::vector<RTLIL::Process*> selected_processes() const;
|
2026-06-11 13:17:54 +02:00
|
|
|
std::vector<RTLIL::AttrObject*> selected_members() const;
|
2013-06-18 17:11:13 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
template<typename T> bool selected(T *member) const {
|
2026-06-10 19:22:53 +02:00
|
|
|
return design->selected_member(meta_->name, member->meta_->name);
|
2014-09-29 12:51:54 +02:00
|
|
|
}
|
|
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
// Primary (fast) overloads — key directly into the dict.
|
2026-06-09 18:50:00 +02:00
|
|
|
RTLIL::Wire* wire(TwineRef id) {
|
2026-01-01 17:06:38 +01:00
|
|
|
auto it = wires_.find(id);
|
|
|
|
|
return it == wires_.end() ? nullptr : it->second;
|
|
|
|
|
}
|
2026-06-09 18:50:00 +02:00
|
|
|
RTLIL::Cell* cell(TwineRef id) {
|
2026-01-01 17:06:38 +01:00
|
|
|
auto it = cells_.find(id);
|
|
|
|
|
return it == cells_.end() ? nullptr : it->second;
|
|
|
|
|
}
|
2026-06-09 18:50:00 +02:00
|
|
|
const RTLIL::Wire* wire(TwineRef id) const {
|
2026-01-01 17:06:38 +01:00
|
|
|
auto it = wires_.find(id);
|
|
|
|
|
return it == wires_.end() ? nullptr : it->second;
|
|
|
|
|
}
|
2026-06-09 18:50:00 +02:00
|
|
|
const RTLIL::Cell* cell(TwineRef id) const {
|
2026-01-01 17:06:38 +01:00
|
|
|
auto it = cells_.find(id);
|
|
|
|
|
return it == cells_.end() ? nullptr : it->second;
|
|
|
|
|
}
|
2021-05-22 19:14:13 +02:00
|
|
|
|
2026-06-09 18:50:00 +02:00
|
|
|
RTLIL::ObjRange<RTLIL::Wire*, TwineRef> wires() { return RTLIL::ObjRange<RTLIL::Wire*, TwineRef>(&wires_, &refcount_wires_); }
|
2026-01-01 17:06:38 +01:00
|
|
|
int wires_size() const { return wires_.size(); }
|
|
|
|
|
RTLIL::Wire* wire_at(int index) const { return wires_.element(index)->second; }
|
2026-06-09 18:50:00 +02:00
|
|
|
RTLIL::ObjRange<RTLIL::Cell*, TwineRef> cells() { return RTLIL::ObjRange<RTLIL::Cell*, TwineRef>(&cells_, &refcount_cells_); }
|
2026-01-01 17:06:38 +01:00
|
|
|
int cells_size() const { return cells_.size(); }
|
|
|
|
|
RTLIL::Cell* cell_at(int index) const { return cells_.element(index)->second; }
|
2013-01-05 11:13:26 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
void add(RTLIL::Binding *binding);
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
// Removing wires is expensive. If you have to remove wires, remove them all at once.
|
|
|
|
|
void remove(const pool<RTLIL::Wire*> &wires);
|
|
|
|
|
void remove(RTLIL::Cell *cell);
|
|
|
|
|
void remove(RTLIL::Memory *memory);
|
|
|
|
|
void remove(RTLIL::Process *process);
|
2013-06-18 17:11:13 +02:00
|
|
|
|
2026-06-10 19:22:53 +02:00
|
|
|
void rename(RTLIL::Wire *wire, TwineRef new_name);
|
|
|
|
|
void rename(RTLIL::Cell *cell, TwineRef new_name);
|
|
|
|
|
void rename(TwineRef old_name, TwineRef new_name);
|
2018-12-23 10:04:23 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
void swap_names(RTLIL::Wire *w1, RTLIL::Wire *w2);
|
|
|
|
|
void swap_names(RTLIL::Cell *c1, RTLIL::Cell *c2);
|
2013-01-05 11:13:26 +01:00
|
|
|
|
2026-06-10 19:22:53 +02:00
|
|
|
TwineRef uniquify(TwineRef name);
|
2026-06-12 00:18:53 +02:00
|
|
|
TwineRef uniquify(Twine&& name);
|
2026-06-10 19:22:53 +02:00
|
|
|
TwineRef uniquify(TwineRef name, int &index);
|
2026-06-12 00:18:53 +02:00
|
|
|
TwineRef uniquify(Twine&& name, int &index);
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
// Primary overloads: name already interned in design->twines.
|
2026-06-09 18:50:00 +02:00
|
|
|
RTLIL::Wire *addWire(TwineRef name, int width = 1);
|
|
|
|
|
RTLIL::Wire *addWire(TwineRef name, const RTLIL::Wire *other);
|
2026-06-10 19:22:53 +02:00
|
|
|
// Convenience: adds name into twines, then dispatches.
|
|
|
|
|
RTLIL::Wire *addWire(Twine &&name, int width = 1);
|
|
|
|
|
RTLIL::Wire *addWire(Twine &&name, const RTLIL::Wire *other);
|
2013-06-18 17:11:13 +02:00
|
|
|
|
2026-06-08 23:40:51 +02:00
|
|
|
// Primary overloads.
|
2026-06-11 20:02:02 +02:00
|
|
|
RTLIL::Cell *addCell(TwineRef name, TwineRef type);
|
2026-06-09 18:50:00 +02:00
|
|
|
RTLIL::Cell *addCell(TwineRef name, const RTLIL::Cell *other);
|
2026-06-10 19:22:53 +02:00
|
|
|
// Convenience.
|
2026-06-12 00:18:53 +02:00
|
|
|
RTLIL::Cell *addCell(Twine name, Twine type);
|
2026-06-11 20:02:02 +02:00
|
|
|
RTLIL::Cell *addCell(Twine &&name, TwineRef type);
|
|
|
|
|
RTLIL::Cell *addCell(TwineRef name, Twine &&type);
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::Cell *addCell(Twine &&name, const RTLIL::Cell *other);
|
|
|
|
|
|
|
|
|
|
// NEW_ID analog for twine names; see NEW_TWINE in yosys_common.h.
|
|
|
|
|
TwineRef new_name(const std::string *prefix) {
|
|
|
|
|
TwineRef pref = design->twines.add(Twine{*prefix});
|
|
|
|
|
return design->twines.add(Twine{Twine::Suffix{pref, std::to_string(autoidx++)}});
|
|
|
|
|
}
|
2018-12-23 10:04:23 +01:00
|
|
|
|
2026-06-11 13:17:54 +02:00
|
|
|
RTLIL::Memory *addMemory(TwineRef name);
|
|
|
|
|
RTLIL::Memory *addMemory(Twine &&name);
|
|
|
|
|
RTLIL::Memory *addMemory(TwineRef name, const RTLIL::Memory *other);
|
2013-01-05 11:13:26 +01:00
|
|
|
|
2026-06-11 13:17:54 +02:00
|
|
|
RTLIL::Process *addProcess(TwineRef name);
|
|
|
|
|
RTLIL::Process *addProcess(Twine &&name);
|
|
|
|
|
RTLIL::Process *addProcess(TwineRef name, const RTLIL::Process *other);
|
2021-02-23 00:21:46 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
// The add* methods create a cell and return the created cell. All signals must exist in advance.
|
2013-06-18 17:11:13 +02:00
|
|
|
|
2026-06-11 20:02:02 +02:00
|
|
|
RTLIL::Cell* addAnyinit(TwineRef name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addAnyinit(Twine &&name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, TwineRef src = Twine::Null);
|
2013-01-05 11:13:26 +01:00
|
|
|
|
2026-01-01 17:06:38 +01:00
|
|
|
// The methods without the add* prefix create a cell and an output signal. They return the newly created output signal.
|
2021-07-11 23:57:53 +02:00
|
|
|
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::SigSpec Anyconst (TwineRef name, int width = 1, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Anyseq (TwineRef name, int width = 1, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Allconst (TwineRef name, int width = 1, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Allseq (TwineRef name, int width = 1, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Initstate (TwineRef name, TwineRef src = Twine::Null);
|
2026-06-11 20:02:02 +02:00
|
|
|
RTLIL::SigSpec Anyconst (Twine &&name, int width = 1, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Anyseq (Twine &&name, int width = 1, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Allconst (Twine &&name, int width = 1, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Allseq (Twine &&name, int width = 1, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec Initstate (Twine &&name, TwineRef src = Twine::Null);
|
2026-06-05 12:04:19 +02:00
|
|
|
|
2026-06-10 19:22:53 +02:00
|
|
|
RTLIL::SigSpec SetTag (TwineRef name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addSetTag (TwineRef name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec GetTag (TwineRef name, const std::string &tag, const RTLIL::SigSpec &sig_a, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addOverwriteTag (TwineRef name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec OriginalTag (TwineRef name, const std::string &tag, const RTLIL::SigSpec &sig_a, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec FutureFF (TwineRef name, const RTLIL::SigSpec &sig_e, TwineRef src = Twine::Null);
|
2026-06-11 20:02:02 +02:00
|
|
|
RTLIL::SigSpec SetTag (Twine &&name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addSetTag (Twine &&name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec GetTag (Twine &&name, const std::string &tag, const RTLIL::SigSpec &sig_a, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::Cell* addOverwriteTag (Twine &&name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec OriginalTag (Twine &&name, const std::string &tag, const RTLIL::SigSpec &sig_a, TwineRef src = Twine::Null);
|
|
|
|
|
RTLIL::SigSpec FutureFF (Twine &&name, const RTLIL::SigSpec &sig_e, TwineRef src = Twine::Null);
|
2014-07-27 02:00:04 +02:00
|
|
|
|
2026-01-14 15:37:18 +01:00
|
|
|
std::string to_rtlil_str() const;
|
2026-01-01 17:06:38 +01:00
|
|
|
#ifdef YOSYS_ENABLE_PYTHON
|
|
|
|
|
static std::map<unsigned int, RTLIL::Module*> *get_all_modules(void);
|
|
|
|
|
#endif
|
2013-01-05 11:13:26 +01:00
|
|
|
};
|
|
|
|
|
|
2013-06-18 19:54:33 +02:00
|
|
|
template<typename T>
|
2017-05-28 11:59:05 +02:00
|
|
|
void RTLIL::Module::rewrite_sigspecs(T &functor)
|
2013-06-18 19:54:33 +02:00
|
|
|
{
|
2026-03-11 21:07:06 +01:00
|
|
|
log_assert(sig_norm_index == nullptr);
|
2014-07-27 01:51:45 +02:00
|
|
|
for (auto &it : cells_)
|
2013-06-18 19:54:33 +02:00
|
|
|
it.second->rewrite_sigspecs(functor);
|
|
|
|
|
for (auto &it : processes)
|
|
|
|
|
it.second->rewrite_sigspecs(functor);
|
2014-07-26 11:58:03 +02:00
|
|
|
for (auto &it : connections_) {
|
2013-06-18 19:54:33 +02:00
|
|
|
functor(it.first);
|
|
|
|
|
functor(it.second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-15 16:01:00 +02:00
|
|
|
template<typename T>
|
|
|
|
|
void RTLIL::Module::rewrite_sigspecs2(T &functor)
|
|
|
|
|
{
|
2026-03-11 21:07:06 +01:00
|
|
|
log_assert(sig_norm_index == nullptr);
|
2019-05-15 16:01:00 +02:00
|
|
|
for (auto &it : cells_)
|
|
|
|
|
it.second->rewrite_sigspecs2(functor);
|
|
|
|
|
for (auto &it : processes)
|
|
|
|
|
it.second->rewrite_sigspecs2(functor);
|
|
|
|
|
for (auto &it : connections_) {
|
|
|
|
|
functor(it.first, it.second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-18 19:54:33 +02:00
|
|
|
template<typename T>
|
2017-05-28 11:59:05 +02:00
|
|
|
void RTLIL::Cell::rewrite_sigspecs(T &functor) {
|
2014-07-26 11:58:03 +02:00
|
|
|
for (auto &it : connections_)
|
2013-06-18 19:54:33 +02:00
|
|
|
functor(it.second);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-15 16:01:00 +02:00
|
|
|
template<typename T>
|
|
|
|
|
void RTLIL::Cell::rewrite_sigspecs2(T &functor) {
|
|
|
|
|
for (auto &it : connections_)
|
|
|
|
|
functor(it.second);
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-18 19:54:33 +02:00
|
|
|
template<typename T>
|
2017-05-28 11:59:05 +02:00
|
|
|
void RTLIL::CaseRule::rewrite_sigspecs(T &functor) {
|
2013-06-18 19:54:33 +02:00
|
|
|
for (auto &it : compare)
|
|
|
|
|
functor(it);
|
|
|
|
|
for (auto &it : actions) {
|
|
|
|
|
functor(it.first);
|
|
|
|
|
functor(it.second);
|
|
|
|
|
}
|
|
|
|
|
for (auto it : switches)
|
|
|
|
|
it->rewrite_sigspecs(functor);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-15 16:01:00 +02:00
|
|
|
template<typename T>
|
|
|
|
|
void RTLIL::CaseRule::rewrite_sigspecs2(T &functor) {
|
|
|
|
|
for (auto &it : compare)
|
|
|
|
|
functor(it);
|
|
|
|
|
for (auto &it : actions) {
|
|
|
|
|
functor(it.first, it.second);
|
|
|
|
|
}
|
|
|
|
|
for (auto it : switches)
|
|
|
|
|
it->rewrite_sigspecs2(functor);
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-18 19:54:33 +02:00
|
|
|
template<typename T>
|
2017-05-28 11:59:05 +02:00
|
|
|
void RTLIL::SwitchRule::rewrite_sigspecs(T &functor)
|
2013-06-18 19:54:33 +02:00
|
|
|
{
|
|
|
|
|
functor(signal);
|
|
|
|
|
for (auto it : cases)
|
|
|
|
|
it->rewrite_sigspecs(functor);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-15 16:01:00 +02:00
|
|
|
template<typename T>
|
|
|
|
|
void RTLIL::SwitchRule::rewrite_sigspecs2(T &functor)
|
|
|
|
|
{
|
|
|
|
|
functor(signal);
|
|
|
|
|
for (auto it : cases)
|
|
|
|
|
it->rewrite_sigspecs2(functor);
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-18 19:54:33 +02:00
|
|
|
template<typename T>
|
2017-05-28 11:59:05 +02:00
|
|
|
void RTLIL::SyncRule::rewrite_sigspecs(T &functor)
|
2013-06-18 19:54:33 +02:00
|
|
|
{
|
|
|
|
|
functor(signal);
|
|
|
|
|
for (auto &it : actions) {
|
|
|
|
|
functor(it.first);
|
|
|
|
|
functor(it.second);
|
|
|
|
|
}
|
2021-02-23 00:21:46 +01:00
|
|
|
for (auto &it : mem_write_actions) {
|
|
|
|
|
functor(it.address);
|
|
|
|
|
functor(it.data);
|
|
|
|
|
functor(it.enable);
|
|
|
|
|
}
|
2013-06-18 19:54:33 +02:00
|
|
|
}
|
|
|
|
|
|
2019-05-15 16:01:00 +02:00
|
|
|
template<typename T>
|
|
|
|
|
void RTLIL::SyncRule::rewrite_sigspecs2(T &functor)
|
|
|
|
|
{
|
|
|
|
|
functor(signal);
|
|
|
|
|
for (auto &it : actions) {
|
|
|
|
|
functor(it.first, it.second);
|
|
|
|
|
}
|
2021-02-23 00:21:46 +01:00
|
|
|
for (auto &it : mem_write_actions) {
|
|
|
|
|
functor(it.address);
|
|
|
|
|
functor(it.data);
|
|
|
|
|
functor(it.enable);
|
|
|
|
|
}
|
2019-05-15 16:01:00 +02:00
|
|
|
}
|
|
|
|
|
|
2013-06-18 19:54:33 +02:00
|
|
|
template<typename T>
|
2017-05-28 11:59:05 +02:00
|
|
|
void RTLIL::Process::rewrite_sigspecs(T &functor)
|
2013-06-18 19:54:33 +02:00
|
|
|
{
|
|
|
|
|
root_case.rewrite_sigspecs(functor);
|
|
|
|
|
for (auto it : syncs)
|
|
|
|
|
it->rewrite_sigspecs(functor);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-15 16:01:00 +02:00
|
|
|
template<typename T>
|
|
|
|
|
void RTLIL::Process::rewrite_sigspecs2(T &functor)
|
|
|
|
|
{
|
|
|
|
|
root_case.rewrite_sigspecs2(functor);
|
|
|
|
|
for (auto it : syncs)
|
|
|
|
|
it->rewrite_sigspecs2(functor);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-11 20:02:02 +02:00
|
|
|
inline TwineRef RTLIL::WireNameMasq::ref() const {
|
2026-06-08 23:40:51 +02:00
|
|
|
const RTLIL::Wire *w = reinterpret_cast<const RTLIL::Wire *>(
|
|
|
|
|
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Wire, name));
|
|
|
|
|
if (!w->module || !w->module->design || !w->meta_)
|
2026-06-11 20:02:02 +02:00
|
|
|
return Twine::Null;
|
|
|
|
|
return w->meta_->name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline std::string RTLIL::WireNameMasq::escaped() const {
|
|
|
|
|
const RTLIL::Wire *w = reinterpret_cast<const RTLIL::Wire *>(
|
|
|
|
|
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Wire, name));
|
|
|
|
|
TwineRef id = ref();
|
2026-06-08 23:40:51 +02:00
|
|
|
if (id == Twine::Null)
|
2026-06-11 20:02:02 +02:00
|
|
|
return std::string();
|
|
|
|
|
return w->module->design->twines.str(id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline std::string RTLIL::WireNameMasq::unescaped() const {
|
|
|
|
|
const RTLIL::Wire *w = reinterpret_cast<const RTLIL::Wire *>(
|
|
|
|
|
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Wire, name));
|
|
|
|
|
TwineRef id = ref();
|
|
|
|
|
if (id == Twine::Null)
|
|
|
|
|
return std::string();
|
|
|
|
|
return w->module->design->twines.unescaped_str(id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline RTLIL::WireNameMasq::operator RTLIL::IdString() const {
|
|
|
|
|
std::string s = escaped();
|
|
|
|
|
if (s.empty())
|
2026-06-08 23:40:51 +02:00
|
|
|
return RTLIL::IdString{};
|
2026-06-11 20:02:02 +02:00
|
|
|
return RTLIL::IdString(s);
|
2026-06-08 23:40:51 +02:00
|
|
|
}
|
|
|
|
|
|
2026-06-11 20:02:02 +02:00
|
|
|
inline TwineRef RTLIL::CellNameMasq::ref() const {
|
2026-06-08 23:40:51 +02:00
|
|
|
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
|
|
|
|
|
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, name));
|
|
|
|
|
if (!c->module || !c->module->design || !c->meta_)
|
2026-06-11 20:02:02 +02:00
|
|
|
return Twine::Null;
|
|
|
|
|
return c->meta_->name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline std::string RTLIL::CellNameMasq::escaped() const {
|
|
|
|
|
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
|
|
|
|
|
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, name));
|
|
|
|
|
TwineRef id = ref();
|
|
|
|
|
if (id == Twine::Null)
|
|
|
|
|
return std::string();
|
|
|
|
|
return c->module->design->twines.str(id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline std::string RTLIL::CellNameMasq::unescaped() const {
|
|
|
|
|
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
|
|
|
|
|
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, name));
|
|
|
|
|
TwineRef id = ref();
|
|
|
|
|
if (id == Twine::Null)
|
|
|
|
|
return std::string();
|
|
|
|
|
return c->module->design->twines.unescaped_str(id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline RTLIL::CellNameMasq::operator RTLIL::IdString() const {
|
|
|
|
|
std::string s = escaped();
|
|
|
|
|
if (s.empty())
|
2026-06-08 23:40:51 +02:00
|
|
|
return RTLIL::IdString{};
|
2026-06-11 20:02:02 +02:00
|
|
|
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));
|
|
|
|
|
return c->type_impl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline std::string RTLIL::CellTypeMasq::escaped() const {
|
|
|
|
|
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
|
|
|
|
|
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, type));
|
|
|
|
|
TwineRef id = c->type_impl;
|
|
|
|
|
if (id == Twine::Null)
|
|
|
|
|
return std::string();
|
|
|
|
|
if (c->module && c->module->design)
|
|
|
|
|
return c->module->design->twines.str(id);
|
|
|
|
|
// Static (TW::) refs are pool-independent; assert non-local ref.
|
|
|
|
|
log_assert(twine_untag(id) < STATIC_TWINE_END);
|
|
|
|
|
return TwinePool{}.str(id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline std::string RTLIL::CellTypeMasq::unescaped() const {
|
|
|
|
|
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
|
|
|
|
|
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, type));
|
|
|
|
|
TwineRef id = c->type_impl;
|
2026-06-08 23:40:51 +02:00
|
|
|
if (id == Twine::Null)
|
2026-06-11 20:02:02 +02:00
|
|
|
return std::string();
|
|
|
|
|
if (c->module && c->module->design)
|
|
|
|
|
return c->module->design->twines.unescaped_str(id);
|
|
|
|
|
log_assert(twine_untag(id) < STATIC_TWINE_END);
|
|
|
|
|
return TwinePool{}.unescaped_str(id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline RTLIL::CellTypeMasq::operator RTLIL::IdString() const {
|
|
|
|
|
std::string s = escaped();
|
|
|
|
|
if (s.empty())
|
2026-06-08 23:40:51 +02:00
|
|
|
return RTLIL::IdString{};
|
2026-06-11 20:02:02 +02:00
|
|
|
return RTLIL::IdString(s);
|
2026-06-08 23:40:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
// }
|
|
|
|
|
|
2014-07-31 13:19:47 +02:00
|
|
|
YOSYS_NAMESPACE_END
|
|
|
|
|
|
2013-01-05 11:13:26 +01:00
|
|
|
#endif
|