mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-15 03:35:40 +00:00
twine
This commit is contained in:
parent
3d27e83d0f
commit
3424c00cd0
63 changed files with 2635 additions and 503 deletions
3
Makefile
3
Makefile
|
|
@ -646,6 +646,7 @@ $(eval $(call add_include_file,kernel/sexpr.h))
|
|||
$(eval $(call add_include_file,kernel/sigtools.h))
|
||||
$(eval $(call add_include_file,kernel/threading.h))
|
||||
$(eval $(call add_include_file,kernel/timinginfo.h))
|
||||
$(eval $(call add_include_file,kernel/twine.h))
|
||||
$(eval $(call add_include_file,kernel/utils.h))
|
||||
$(eval $(call add_include_file,kernel/yosys.h))
|
||||
$(eval $(call add_include_file,kernel/yosys_common.h))
|
||||
|
|
@ -670,7 +671,7 @@ ifeq ($(ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS),1)
|
|||
OBJS += kernel/log_compat.o
|
||||
endif
|
||||
OBJS += kernel/binding.o kernel/tclapi.o
|
||||
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/cost.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o kernel/sexpr.o
|
||||
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/cost.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o kernel/sexpr.o kernel/twine.o
|
||||
OBJS += kernel/drivertools.o kernel/functional.o kernel/threading.o
|
||||
ifeq ($(ENABLE_ZLIB),1)
|
||||
OBJS += kernel/fstdata.o
|
||||
|
|
|
|||
|
|
@ -121,8 +121,9 @@ struct BtorWorker
|
|||
{
|
||||
string infostr = obj->name.unescape();
|
||||
if (!srcsym && !print_internal_names && infostr[0] == '$') return "";
|
||||
if (obj->attributes.count(ID::src)) {
|
||||
string src = obj->attributes.at(ID::src).decode_string().c_str();
|
||||
if (obj->has_attribute(ID::src)) {
|
||||
string raw_src = module && module->design ? obj->get_src_attribute(&module->design->src_twines) : std::string();
|
||||
string src = module && module->design ? module->design->resolve_src(raw_src) : raw_src;
|
||||
if (srcsym && infostr[0] == '$') {
|
||||
std::replace(src.begin(), src.end(), ' ', '_');
|
||||
if (srcsymbols.count(src) || module->count_id("\\" + src)) {
|
||||
|
|
|
|||
|
|
@ -404,8 +404,8 @@ struct EdifBackend : public Backend {
|
|||
|
||||
{
|
||||
auto count_nontrivial_attr = [](Wire *w) {
|
||||
// src isn't in attributes anymore (typed field).
|
||||
int count = w->attributes.size();
|
||||
count -= w->attributes.count(ID::src);
|
||||
count -= w->attributes.count(ID::unused_bits);
|
||||
return count;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@ static const FDirection FD_OUT = 0x2;
|
|||
static const FDirection FD_INOUT = 0x3;
|
||||
static const int FIRRTL_MAX_DSH_WIDTH_ERROR = 20; // For historic reasons, this is actually one greater than the maximum allowed shift width
|
||||
|
||||
std::string getFileinfo(const RTLIL::AttrObject *design_entity)
|
||||
std::string getFileinfo(const RTLIL::AttrObject *design_entity, const RTLIL::Design *design = nullptr)
|
||||
{
|
||||
std::string src(design_entity->get_src_attribute());
|
||||
std::string src = design ? design_entity->get_src_attribute(&design->src_twines) : std::string();
|
||||
std::string fileinfo_str = src.empty() ? "" : "@[" + src + "]";
|
||||
return fileinfo_str;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,9 +130,16 @@ struct JsonWriter
|
|||
}
|
||||
}
|
||||
|
||||
void write_parameters(const dict<IdString, Const> ¶meters, bool for_module=false)
|
||||
void write_parameters(const dict<IdString, Const> ¶meters, bool for_module=false, const RTLIL::AttrObject *src_obj=nullptr)
|
||||
{
|
||||
bool first = true;
|
||||
// Emit the typed src field first if present — it lives outside the
|
||||
// attribute dict after the typed-src migration.
|
||||
if (src_obj && src_obj->src_id() != Twine::Null && design) {
|
||||
f << stringf("\n %s%s: ", for_module ? "" : " ", get_name(RTLIL::ID::src));
|
||||
write_parameter_value(RTLIL::Const(src_obj->get_src_attribute(&design->src_twines)));
|
||||
first = false;
|
||||
}
|
||||
for (auto ¶m : parameters) {
|
||||
f << stringf("%s\n", first ? "" : ",");
|
||||
f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first));
|
||||
|
|
@ -158,7 +165,7 @@ struct JsonWriter
|
|||
f << stringf(" %s: {\n", get_name(module->name));
|
||||
|
||||
f << stringf(" \"attributes\": {");
|
||||
write_parameters(module->attributes, /*for_module=*/true);
|
||||
write_parameters(module->attributes, /*for_module=*/true, module);
|
||||
f << stringf("\n },\n");
|
||||
|
||||
if (module->parameter_default_values.size()) {
|
||||
|
|
@ -210,7 +217,7 @@ struct JsonWriter
|
|||
write_parameters(c->parameters);
|
||||
f << stringf("\n },\n");
|
||||
f << stringf(" \"attributes\": {");
|
||||
write_parameters(c->attributes);
|
||||
write_parameters(c->attributes, false, c);
|
||||
f << stringf("\n },\n");
|
||||
if (c->known()) {
|
||||
f << stringf(" \"port_directions\": {");
|
||||
|
|
@ -248,7 +255,7 @@ struct JsonWriter
|
|||
f << stringf(" %s: {\n", get_name(it.second->name));
|
||||
f << stringf(" \"hide_name\": %s,\n", it.second->name[0] == '$' ? "1" : "0");
|
||||
f << stringf(" \"attributes\": {");
|
||||
write_parameters(it.second->attributes);
|
||||
write_parameters(it.second->attributes, false, it.second);
|
||||
f << stringf("\n },\n");
|
||||
f << stringf(" \"width\": %d,\n", it.second->width);
|
||||
f << stringf(" \"start_offset\": %d,\n", it.second->start_offset);
|
||||
|
|
@ -275,7 +282,7 @@ struct JsonWriter
|
|||
if (w->is_signed)
|
||||
f << stringf(" \"signed\": %d,\n", w->is_signed);
|
||||
f << stringf(" \"attributes\": {");
|
||||
write_parameters(w->attributes);
|
||||
write_parameters(w->attributes, false, w);
|
||||
f << stringf("\n }\n");
|
||||
f << stringf(" }");
|
||||
first = false;
|
||||
|
|
|
|||
|
|
@ -32,8 +32,20 @@ USING_YOSYS_NAMESPACE
|
|||
using namespace RTLIL_BACKEND;
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
void RTLIL_BACKEND::dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj)
|
||||
void RTLIL_BACKEND::dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj, const RTLIL::Design *design, bool resolve_src)
|
||||
{
|
||||
// Emit the typed src field first. It is not stored in obj->attributes
|
||||
// — the dict no longer holds ID::src under any circumstance. Backends
|
||||
// that want to materialize the pipe-joined literal pass resolve_src.
|
||||
if (obj->src_id() != Twine::Null && design) {
|
||||
f << stringf("%s" "attribute \\src ", indent);
|
||||
if (resolve_src) {
|
||||
dump_const(f, RTLIL::Const(design->src_twines.flatten(obj->src_id())));
|
||||
} else {
|
||||
dump_const(f, RTLIL::Const(TwinePool::format_ref(obj->src_id())));
|
||||
}
|
||||
f << stringf("\n");
|
||||
}
|
||||
for (const auto& [name, value] : reversed(obj->attributes)) {
|
||||
f << stringf("%s" "attribute %s ", indent, name);
|
||||
dump_const(f, value);
|
||||
|
|
@ -41,6 +53,30 @@ void RTLIL_BACKEND::dump_attributes(std::ostream &f, std::string indent, const R
|
|||
}
|
||||
}
|
||||
|
||||
void RTLIL_BACKEND::dump_twines(std::ostream &f, const RTLIL::Design *design)
|
||||
{
|
||||
if (!design || design->src_twines.size() == 0)
|
||||
return;
|
||||
f << stringf("twines\n");
|
||||
design->src_twines.for_each_live([&](Twine::Id id, const Twine &n) {
|
||||
if (n.is_leaf()) {
|
||||
f << stringf(" leaf %u ", id);
|
||||
dump_const(f, RTLIL::Const(n.leaf()));
|
||||
f << stringf("\n");
|
||||
} else if (n.is_suffix()) {
|
||||
f << stringf(" suffix %u %u ", id, n.suffix().parent);
|
||||
dump_const(f, RTLIL::Const(n.suffix().tail));
|
||||
f << stringf("\n");
|
||||
} else {
|
||||
f << stringf(" concat %u", id);
|
||||
for (Twine::Id c : n.children())
|
||||
f << stringf(" %u", c);
|
||||
f << stringf("\n");
|
||||
}
|
||||
});
|
||||
f << stringf("end\n");
|
||||
}
|
||||
|
||||
void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint)
|
||||
{
|
||||
if (width < 0)
|
||||
|
|
@ -132,9 +168,9 @@ void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo
|
|||
}
|
||||
}
|
||||
|
||||
void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire)
|
||||
void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire, const RTLIL::Design *design, bool resolve_src)
|
||||
{
|
||||
dump_attributes(f, indent, wire);
|
||||
dump_attributes(f, indent, wire, design, resolve_src);
|
||||
if (wire->driverCell_) {
|
||||
f << stringf("%s" "# driver %s %s\n", indent,
|
||||
wire->driverCell()->name, wire->driverPort());
|
||||
|
|
@ -157,9 +193,9 @@ void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::
|
|||
f << stringf("%s\n", wire->name);
|
||||
}
|
||||
|
||||
void RTLIL_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory)
|
||||
void RTLIL_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory, const RTLIL::Design *design, bool resolve_src)
|
||||
{
|
||||
dump_attributes(f, indent, memory);
|
||||
dump_attributes(f, indent, memory, design, resolve_src);
|
||||
f << stringf("%s" "memory ", indent);
|
||||
if (memory->width != 1)
|
||||
f << stringf("width %d ", memory->width);
|
||||
|
|
@ -170,9 +206,9 @@ void RTLIL_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL
|
|||
f << stringf("%s\n", memory->name);
|
||||
}
|
||||
|
||||
void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell)
|
||||
void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell, const RTLIL::Design *design, bool resolve_src)
|
||||
{
|
||||
dump_attributes(f, indent, cell);
|
||||
dump_attributes(f, indent, cell, design, resolve_src);
|
||||
f << stringf("%s" "cell %s %s\n", indent, cell->type, cell->name);
|
||||
for (const auto& [name, param] : reversed(cell->parameters)) {
|
||||
f << stringf("%s parameter%s%s%s %s ", indent,
|
||||
|
|
@ -191,7 +227,7 @@ void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::
|
|||
f << stringf("%s" "end\n", indent);
|
||||
}
|
||||
|
||||
void RTLIL_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs)
|
||||
void RTLIL_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs, const RTLIL::Design *design, bool resolve_src)
|
||||
{
|
||||
for (const auto& [lhs, rhs] : cs->actions) {
|
||||
f << stringf("%s" "assign ", indent);
|
||||
|
|
@ -202,12 +238,12 @@ void RTLIL_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, con
|
|||
}
|
||||
|
||||
for (const auto& sw : cs->switches)
|
||||
dump_proc_switch(f, indent, sw);
|
||||
dump_proc_switch(f, indent, sw, design, resolve_src);
|
||||
}
|
||||
|
||||
void RTLIL_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw)
|
||||
void RTLIL_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw, const RTLIL::Design *design, bool resolve_src)
|
||||
{
|
||||
dump_attributes(f, indent, sw);
|
||||
dump_attributes(f, indent, sw, design, resolve_src);
|
||||
|
||||
f << stringf("%s" "switch ", indent);
|
||||
dump_sigspec(f, sw->signal);
|
||||
|
|
@ -215,7 +251,7 @@ void RTLIL_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const
|
|||
|
||||
for (const auto case_ : sw->cases)
|
||||
{
|
||||
dump_attributes(f, indent, case_);
|
||||
dump_attributes(f, indent, case_, design, resolve_src);
|
||||
f << stringf("%s case ", indent);
|
||||
for (size_t i = 0; i < case_->compare.size(); i++) {
|
||||
if (i > 0)
|
||||
|
|
@ -224,13 +260,13 @@ void RTLIL_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const
|
|||
}
|
||||
f << stringf("\n");
|
||||
|
||||
dump_proc_case_body(f, indent + " ", case_);
|
||||
dump_proc_case_body(f, indent + " ", case_, design, resolve_src);
|
||||
}
|
||||
|
||||
f << stringf("%s" "end\n", indent);
|
||||
}
|
||||
|
||||
void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy)
|
||||
void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy, const RTLIL::Design *design, bool resolve_src)
|
||||
{
|
||||
f << stringf("%s" "sync ", indent);
|
||||
switch (sy->type) {
|
||||
|
|
@ -256,7 +292,7 @@ void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT
|
|||
}
|
||||
|
||||
for (auto &it: sy->mem_write_actions) {
|
||||
dump_attributes(f, indent, &it);
|
||||
dump_attributes(f, indent, &it, design, resolve_src);
|
||||
f << stringf("%s memwr %s ", indent, it.memid);
|
||||
dump_sigspec(f, it.address);
|
||||
f << stringf(" ");
|
||||
|
|
@ -269,13 +305,13 @@ void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT
|
|||
}
|
||||
}
|
||||
|
||||
void RTLIL_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc)
|
||||
void RTLIL_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc, const RTLIL::Design *design, bool resolve_src)
|
||||
{
|
||||
dump_attributes(f, indent, proc);
|
||||
dump_attributes(f, indent, proc, design, resolve_src);
|
||||
f << stringf("%s" "process %s\n", indent, proc->name);
|
||||
dump_proc_case_body(f, indent + " ", &proc->root_case);
|
||||
dump_proc_case_body(f, indent + " ", &proc->root_case, design, resolve_src);
|
||||
for (auto* sync : proc->syncs)
|
||||
dump_proc_sync(f, indent + " ", sync);
|
||||
dump_proc_sync(f, indent + " ", sync, design, resolve_src);
|
||||
f << stringf("%s" "end\n", indent);
|
||||
}
|
||||
|
||||
|
|
@ -288,14 +324,14 @@ void RTLIL_BACKEND::dump_conn(std::ostream &f, std::string indent, const RTLIL::
|
|||
f << stringf("\n");
|
||||
}
|
||||
|
||||
void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n)
|
||||
void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n, bool resolve_src)
|
||||
{
|
||||
bool print_header = flag_m || module->is_selected_whole();
|
||||
bool print_body = !flag_n || !module->is_selected_whole();
|
||||
|
||||
if (print_header)
|
||||
{
|
||||
dump_attributes(f, indent, module);
|
||||
dump_attributes(f, indent, module, design, resolve_src);
|
||||
|
||||
f << stringf("%s" "module %s\n", indent, module->name);
|
||||
|
||||
|
|
@ -321,28 +357,28 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
|
|||
if (!only_selected || design->selected(module, wire)) {
|
||||
if (only_selected)
|
||||
f << stringf("\n");
|
||||
dump_wire(f, indent + " ", wire);
|
||||
dump_wire(f, indent + " ", wire, design, resolve_src);
|
||||
}
|
||||
|
||||
for (const auto& [_, mem] : reversed(module->memories))
|
||||
if (!only_selected || design->selected(module, mem)) {
|
||||
if (only_selected)
|
||||
f << stringf("\n");
|
||||
dump_memory(f, indent + " ", mem);
|
||||
dump_memory(f, indent + " ", mem, design, resolve_src);
|
||||
}
|
||||
|
||||
for (const auto& [_, cell] : reversed(module->cells_))
|
||||
if (!only_selected || design->selected(module, cell)) {
|
||||
if (only_selected)
|
||||
f << stringf("\n");
|
||||
dump_cell(f, indent + " ", cell);
|
||||
dump_cell(f, indent + " ", cell, design, resolve_src);
|
||||
}
|
||||
|
||||
for (const auto& [_, process] : reversed(module->processes))
|
||||
if (!only_selected || design->selected(module, process)) {
|
||||
if (only_selected)
|
||||
f << stringf("\n");
|
||||
dump_proc(f, indent + " ", process);
|
||||
dump_proc(f, indent + " ", process, design, resolve_src);
|
||||
}
|
||||
|
||||
bool first_conn_line = true;
|
||||
|
|
@ -370,7 +406,7 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
|
|||
f << stringf("%s" "end\n", indent);
|
||||
}
|
||||
|
||||
void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n)
|
||||
void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n, bool resolve_src)
|
||||
{
|
||||
int init_autoidx = autoidx;
|
||||
|
||||
|
|
@ -390,13 +426,15 @@ void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl
|
|||
if (only_selected)
|
||||
f << stringf("\n");
|
||||
f << stringf("autoidx %d\n", autoidx);
|
||||
if (!resolve_src)
|
||||
dump_twines(f, design);
|
||||
}
|
||||
|
||||
for (const auto& [_, module] : reversed(design->modules_)) {
|
||||
if (!only_selected || design->selected(module)) {
|
||||
if (only_selected)
|
||||
f << stringf("\n");
|
||||
dump_module(f, "", module, design, only_selected, flag_m, flag_n);
|
||||
dump_module(f, "", module, design, only_selected, flag_m, flag_n, resolve_src);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -423,11 +461,18 @@ struct RTLILBackend : public Backend {
|
|||
log(" -sort\n");
|
||||
log(" sort design in-place (used to be default).\n");
|
||||
log("\n");
|
||||
log(" -resolve-src\n");
|
||||
log(" expand twine references in src attributes inline. Without\n");
|
||||
log(" this flag the design-level twine pool is emitted as a\n");
|
||||
log(" `twines` header block and cell src attributes keep their\n");
|
||||
log(" compact \"@N\" reference form.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
bool selected = false;
|
||||
bool do_sort = false;
|
||||
bool resolve_src = false;
|
||||
|
||||
log_header(design, "Executing RTLIL backend.\n");
|
||||
|
||||
|
|
@ -442,6 +487,10 @@ struct RTLILBackend : public Backend {
|
|||
do_sort = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-resolve-src") {
|
||||
resolve_src = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(f, filename, args, argidx);
|
||||
|
|
@ -452,7 +501,7 @@ struct RTLILBackend : public Backend {
|
|||
design->sort();
|
||||
|
||||
*f << stringf("# Generated by %s\n", yosys_maybe_version());
|
||||
RTLIL_BACKEND::dump_design(*f, design, selected, true, false);
|
||||
RTLIL_BACKEND::dump_design(*f, design, selected, true, false, resolve_src);
|
||||
}
|
||||
} RTLILBackend;
|
||||
|
||||
|
|
@ -480,11 +529,17 @@ struct DumpPass : public Pass {
|
|||
log(" -a <filename>\n");
|
||||
log(" like -outfile but append instead of overwrite\n");
|
||||
log("\n");
|
||||
log(" -resolve-src\n");
|
||||
log(" expand twine references in src attributes inline. Without\n");
|
||||
log(" this flag the design-level twine pool is emitted as a\n");
|
||||
log(" `twines` header block and cell src attributes keep their\n");
|
||||
log(" compact \"@N\" reference form.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
std::string filename;
|
||||
bool flag_m = false, flag_n = false, append = false;
|
||||
bool flag_m = false, flag_n = false, append = false, resolve_src = false;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
|
|
@ -508,6 +563,10 @@ struct DumpPass : public Pass {
|
|||
flag_n = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-resolve-src") {
|
||||
resolve_src = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
|
@ -529,7 +588,7 @@ struct DumpPass : public Pass {
|
|||
f = &buf;
|
||||
}
|
||||
|
||||
RTLIL_BACKEND::dump_design(*f, design, true, flag_m, flag_n);
|
||||
RTLIL_BACKEND::dump_design(*f, design, true, flag_m, flag_n, resolve_src);
|
||||
|
||||
if (!empty) {
|
||||
delete f;
|
||||
|
|
|
|||
|
|
@ -31,20 +31,30 @@
|
|||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
namespace RTLIL_BACKEND {
|
||||
void dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj);
|
||||
// If `design` is non-null AND `resolve_src` is true, the ID::src
|
||||
// attribute is expanded through design->src_twines so the emitted
|
||||
// value is the flat path:line.col string. Otherwise the stored value
|
||||
// is written verbatim — including any "@N" twine references, which
|
||||
// the matching `twines` header block emitted by dump_design lets the
|
||||
// parser reconstruct on load.
|
||||
void dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
||||
|
||||
// Emit the design-level twine pool as a top-level `twines` block.
|
||||
// Skipped if the pool is empty.
|
||||
void dump_twines(std::ostream &f, const RTLIL::Design *design);
|
||||
void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool autoint = true);
|
||||
void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint = true);
|
||||
void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint = true);
|
||||
void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire);
|
||||
void dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory);
|
||||
void dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell);
|
||||
void dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs);
|
||||
void dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw);
|
||||
void dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy);
|
||||
void dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc);
|
||||
void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
||||
void dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
||||
void dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
||||
void dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
||||
void dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
||||
void dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
||||
void dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
||||
void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right);
|
||||
void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false);
|
||||
void dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false);
|
||||
void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false, bool resolve_src = false);
|
||||
void dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false, bool resolve_src = false);
|
||||
}
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -614,7 +614,13 @@ struct Smt2Worker
|
|||
{
|
||||
auto QY = cell->type == ID($anyinit) ? ID::Q : ID::Y;
|
||||
registers.insert(cell);
|
||||
string infostr = cell->attributes.count(ID::src) ? cell->attributes.at(ID::src).decode_string().c_str() : get_id(cell);
|
||||
string infostr;
|
||||
if (cell->has_attribute(ID::src)) {
|
||||
string raw_src = cell->get_src_attribute();
|
||||
infostr = module && module->design ? module->design->resolve_src(raw_src) : raw_src;
|
||||
} else {
|
||||
infostr = get_id(cell);
|
||||
}
|
||||
if (cell->attributes.count(ID::reg))
|
||||
infostr += " " + cell->attributes.at(ID::reg).decode_string();
|
||||
decls.push_back(stringf("; yosys-smt2-%s %s#%d %d %s\n", cell->type.c_str() + 1, get_id(module), idcounter, GetSize(cell->getPort(QY)), infostr));
|
||||
|
|
@ -1130,8 +1136,11 @@ struct Smt2Worker
|
|||
}
|
||||
}
|
||||
|
||||
if (private_name && cell->attributes.count(ID::src))
|
||||
decls.push_back(stringf("; yosys-smt2-%s %d %s %s\n", cell->type.c_str() + 1, id, get_id(cell), cell->attributes.at(ID::src).decode_string()));
|
||||
if (private_name && cell->has_attribute(ID::src)) {
|
||||
string raw_src = cell->get_src_attribute();
|
||||
string resolved_src = module && module->design ? module->design->resolve_src(raw_src) : raw_src;
|
||||
decls.push_back(stringf("; yosys-smt2-%s %d %s %s\n", cell->type.c_str() + 1, id, get_id(cell), resolved_src.c_str()));
|
||||
}
|
||||
else
|
||||
decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id, get_id(cell)));
|
||||
|
||||
|
|
|
|||
|
|
@ -416,6 +416,8 @@ void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString,
|
|||
f << stringf(" 0 ");
|
||||
else if (modattr && (it->second == State::S1 || it->second == Const(1)))
|
||||
f << stringf(" 1 ");
|
||||
else if (it->first == ID::src && (it->second.flags & RTLIL::CONST_FLAG_STRING) && active_module && active_module->design)
|
||||
dump_const(f, RTLIL::Const(active_module->design->resolve_src(it->second.decode_string())), -1, 0, false, as_comment);
|
||||
else
|
||||
dump_const(f, it->second, -1, 0, false, as_comment);
|
||||
f << stringf(" %s%s", as_comment ? "*/" : "*)", term);
|
||||
|
|
|
|||
|
|
@ -1106,7 +1106,31 @@ std::string AstNode::loc_string() const
|
|||
|
||||
void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
|
||||
{
|
||||
obj->attributes[ID::src] = ast->loc_string();
|
||||
// All AttrObjects in genrtlil — Cell/Wire/Module/Process AND the inner
|
||||
// types (CaseRule, SwitchRule, MemWriteAction) — share current_module's
|
||||
// design's twine pool. process_module attaches current_module->design
|
||||
// early so this is reachable.
|
||||
if (!current_module || !current_module->design)
|
||||
return;
|
||||
const auto &loc = ast->location;
|
||||
if (!loc.begin.filename || loc.begin.filename->empty()) {
|
||||
obj->set_src_attribute(¤t_module->design->src_twines, ast->loc_string());
|
||||
return;
|
||||
}
|
||||
// Split filename and per-location tail so the filename interns once
|
||||
// per file and every cell/wire src for that file gets a Suffix node
|
||||
// carrying only ":line.col-line.col". For a typical large design with
|
||||
// thousands of objects in one file this collapses N copies of a long
|
||||
// path into 1 Leaf + N short Suffix tails.
|
||||
TwinePool *pool = ¤t_module->design->src_twines;
|
||||
Twine::Id file_id = pool->intern(*loc.begin.filename);
|
||||
std::string tail = stringf(":%d.%d-%d.%d",
|
||||
loc.begin.line, loc.begin.column,
|
||||
loc.end.line, loc.end.column);
|
||||
Twine::Id suffix_id = pool->intern_suffix(file_id, tail);
|
||||
pool->release(file_id); // suffix internally holds a ref now
|
||||
obj->set_src_id(pool, suffix_id);
|
||||
pool->release(suffix_id); // set_src_id retained on obj's behalf
|
||||
}
|
||||
|
||||
static bool param_has_no_default(const AstNode* param) {
|
||||
|
|
@ -1130,6 +1154,12 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
|
|||
|
||||
AstModule *module = new AstModule;
|
||||
current_module = module;
|
||||
// Set design backpointer early — every set_src_attr in genrtlil.cc
|
||||
// resolves the pool via current_module->design->src_twines. The
|
||||
// final design->add(current_module) at end-of-process_module hooks
|
||||
// the module into the design's modules_ dict; we just need design
|
||||
// reachable as a backpointer for src interning meanwhile.
|
||||
module->design = design;
|
||||
|
||||
module->ast = nullptr;
|
||||
module->name = ast->str;
|
||||
|
|
@ -1920,6 +1950,29 @@ RTLIL::Module *AstModule::clone() const
|
|||
return new_mod;
|
||||
}
|
||||
|
||||
RTLIL::Module *AstModule::clone(RTLIL::Design *dst, bool src_id_verbatim) const
|
||||
{
|
||||
AstModule *new_mod = new AstModule;
|
||||
new_mod->name = name;
|
||||
dst->add(new_mod);
|
||||
cloneInto(new_mod, src_id_verbatim);
|
||||
|
||||
new_mod->ast = ast->clone();
|
||||
new_mod->nolatches = nolatches;
|
||||
new_mod->nomeminit = nomeminit;
|
||||
new_mod->nomem2reg = nomem2reg;
|
||||
new_mod->mem2reg = mem2reg;
|
||||
new_mod->noblackbox = noblackbox;
|
||||
new_mod->lib = lib;
|
||||
new_mod->nowb = nowb;
|
||||
new_mod->noopt = noopt;
|
||||
new_mod->icells = icells;
|
||||
new_mod->pwires = pwires;
|
||||
new_mod->autowire = autowire;
|
||||
|
||||
return new_mod;
|
||||
}
|
||||
|
||||
void AstModule::loadconfig() const
|
||||
{
|
||||
current_ast = NULL;
|
||||
|
|
|
|||
|
|
@ -402,6 +402,7 @@ namespace AST
|
|||
void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces) override;
|
||||
bool reprocess_if_necessary(RTLIL::Design *design) override;
|
||||
RTLIL::Module *clone() const override;
|
||||
RTLIL::Module *clone(RTLIL::Design *dst, bool src_id_verbatim = false) const override;
|
||||
void loadconfig() const;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -167,7 +167,9 @@ static void check_unique_id(RTLIL::Module *module, RTLIL::IdString id,
|
|||
const AstNode *node, const char *to_add_kind)
|
||||
{
|
||||
auto already_exists = [&](const RTLIL::AttrObject *existing, const char *existing_kind) {
|
||||
std::string src = existing->get_string_attribute(ID::src);
|
||||
std::string src;
|
||||
if (module->design)
|
||||
src = existing->get_src_attribute(&module->design->src_twines);
|
||||
std::string location_str = "earlier";
|
||||
if (!src.empty())
|
||||
location_str = "at " + src;
|
||||
|
|
|
|||
|
|
@ -287,6 +287,25 @@ void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
|
|||
}
|
||||
}
|
||||
|
||||
// AttrObject-aware overload: extracts ID::src and routes it to the typed
|
||||
// src_id_ field via set_src_attribute. Other keys still land in the
|
||||
// attributes dict via the generic path.
|
||||
void json_parse_attributes(TwinePool *pool, RTLIL::AttrObject *obj, JsonNode *node)
|
||||
{
|
||||
if (node->type != 'D')
|
||||
log_error("JSON attributes or parameters node is not a dictionary.\n");
|
||||
|
||||
for (auto it : node->data_dict)
|
||||
{
|
||||
IdString key = RTLIL::escape_id(it.first.c_str());
|
||||
Const value = json_parse_attr_param_value(it.second);
|
||||
if (key == ID::src && (value.flags & RTLIL::CONST_FLAG_STRING))
|
||||
obj->set_src_attribute(pool, value.decode_string());
|
||||
else
|
||||
obj->attributes[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void json_import(Design *design, string &modname, JsonNode *node)
|
||||
{
|
||||
log("Importing module %s from JSON tree.\n", modname);
|
||||
|
|
@ -300,7 +319,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
|
|||
design->add(module);
|
||||
|
||||
if (node->data_dict.count("attributes"))
|
||||
json_parse_attr_param(module->attributes, node->data_dict.at("attributes"));
|
||||
json_parse_attributes(&design->src_twines, module, node->data_dict.at("attributes"));
|
||||
|
||||
if (node->data_dict.count("parameter_default_values"))
|
||||
json_parse_attr_param(module->parameter_default_values, node->data_dict.at("parameter_default_values"));
|
||||
|
|
@ -483,7 +502,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
|
|||
}
|
||||
|
||||
if (net_node->data_dict.count("attributes"))
|
||||
json_parse_attr_param(wire->attributes, net_node->data_dict.at("attributes"));
|
||||
json_parse_attributes(&design->src_twines, wire, net_node->data_dict.at("attributes"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -564,7 +583,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
|
|||
}
|
||||
|
||||
if (cell_node->data_dict.count("attributes"))
|
||||
json_parse_attr_param(cell->attributes, cell_node->data_dict.at("attributes"));
|
||||
json_parse_attributes(&design->src_twines, cell, cell_node->data_dict.at("attributes"));
|
||||
|
||||
if (cell_node->data_dict.count("parameters"))
|
||||
json_parse_attr_param(cell->parameters, cell_node->data_dict.at("parameters"));
|
||||
|
|
@ -611,7 +630,7 @@ void json_import(Design *design, string &modname, JsonNode *node)
|
|||
}
|
||||
|
||||
if (memory_node->data_dict.count("attributes"))
|
||||
json_parse_attr_param(mem->attributes, memory_node->data_dict.at("attributes"));
|
||||
json_parse_attributes(&design->src_twines, mem, memory_node->data_dict.at("attributes"));
|
||||
|
||||
module->memories[mem->name] = mem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "kernel/register.h"
|
||||
#include "kernel/log.h"
|
||||
#include "kernel/utils.h"
|
||||
#include "kernel/twine.h"
|
||||
#include <charconv>
|
||||
#include <deque>
|
||||
#include <optional>
|
||||
|
|
@ -52,6 +53,14 @@ struct RTLILFrontendWorker {
|
|||
std::vector<std::vector<RTLIL::SwitchRule*>*> switch_stack;
|
||||
std::vector<RTLIL::CaseRule*> case_stack;
|
||||
|
||||
// Remap from file-local twine ids (as they appear in the `twines` block
|
||||
// and on cell/wire src attrs) to ids in design->src_twines. Filled by
|
||||
// parse_twines; consumed by parse_attribute. Parser-side ids retained
|
||||
// during parse_twines are tracked here so they can be released at
|
||||
// end-of-parse — only the cell/wire references should survive.
|
||||
dict<Twine::Id, Twine::Id> twine_remap;
|
||||
std::vector<Twine::Id> twine_parser_holds;
|
||||
|
||||
template <typename... Args>
|
||||
[[noreturn]]
|
||||
void error(FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
|
||||
|
|
@ -436,9 +445,15 @@ struct RTLILFrontendWorker {
|
|||
|
||||
current_module = new RTLIL::Module;
|
||||
current_module->name = std::move(module_name);
|
||||
current_module->attributes = std::move(attrbuf);
|
||||
if (!delete_current_module)
|
||||
if (delete_current_module) {
|
||||
// Module is about to be discarded — drop its src attribute
|
||||
// rather than push it into a pool we'll never reach.
|
||||
attrbuf.erase(ID::src);
|
||||
current_module->attributes = std::move(attrbuf);
|
||||
} else {
|
||||
design->add(current_module);
|
||||
current_module->absorb_attrs(&design->src_twines, std::move(attrbuf));
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
|
@ -491,10 +506,105 @@ struct RTLILFrontendWorker {
|
|||
{
|
||||
RTLIL::IdString id = parse_id();
|
||||
RTLIL::Const c = parse_const();
|
||||
// The '|' separator inside a src attribute is a Yosys-internal
|
||||
// merge convention emitted only by the legacy strpool path or by
|
||||
// a `dump -resolve-src`; no external tool should be producing it.
|
||||
// Warn so the producer learns to emit one path:line.col per
|
||||
// attribute. We don't try to repair the value — the user's input
|
||||
// is wrong and silently interning it would hide that.
|
||||
if (id == RTLIL::ID::src && (c.flags & RTLIL::CONST_FLAG_STRING)) {
|
||||
std::string raw = c.decode_string();
|
||||
Twine::Id file_id = TwinePool::parse_ref(raw);
|
||||
if (file_id != Twine::Null) {
|
||||
// Translate the file-local twine id to the destination
|
||||
// design's pool id via twine_remap. If the file had no
|
||||
// `twines` block (legacy) the remap is empty — accept the
|
||||
// ref verbatim and let downstream code intern it.
|
||||
auto it = twine_remap.find(file_id);
|
||||
if (it != twine_remap.end())
|
||||
c = RTLIL::Const(TwinePool::format_ref(it->second));
|
||||
} else if (raw.find('|') != std::string::npos) {
|
||||
log_warning("line %d: src attribute %s contains '|' separators. "
|
||||
"That convention is Yosys-internal; the producing tool "
|
||||
"should emit a single path:line.col per attribute and "
|
||||
"let Yosys merge through the twine pool.\n",
|
||||
line_num, raw.c_str());
|
||||
}
|
||||
}
|
||||
attrbuf.insert({std::move(id), std::move(c)});
|
||||
expect_eol();
|
||||
}
|
||||
|
||||
// Parses a `twines` ... `end` block. Builds twine_remap so subsequent
|
||||
// cell/wire src "@N" references (which use file-local ids) translate
|
||||
// to ids in design->src_twines. The destination pool may already be
|
||||
// non-empty (multi-file load) — interned/concated nodes are dedup'd
|
||||
// against the existing pool by the pool itself. Each parser-side
|
||||
// retain is tracked in twine_parser_holds and released at end-of-parse
|
||||
// so only cell/wire references survive.
|
||||
void parse_twines()
|
||||
{
|
||||
expect_eol();
|
||||
while (true) {
|
||||
if (try_parse_keyword("end"))
|
||||
break;
|
||||
if (try_parse_keyword("leaf")) {
|
||||
int file_id = static_cast<int>(parse_integer());
|
||||
std::string text = parse_string();
|
||||
expect_eol();
|
||||
Twine::Id local_id = design->src_twines.intern(text);
|
||||
twine_parser_holds.push_back(local_id);
|
||||
twine_remap[static_cast<Twine::Id>(file_id)] = local_id;
|
||||
continue;
|
||||
}
|
||||
if (try_parse_keyword("suffix")) {
|
||||
int file_id = static_cast<int>(parse_integer());
|
||||
Twine::Id file_parent = static_cast<Twine::Id>(parse_integer());
|
||||
std::string tail = parse_string();
|
||||
expect_eol();
|
||||
auto it = twine_remap.find(file_parent);
|
||||
if (it == twine_remap.end())
|
||||
error("twines: suffix %d references undefined parent %u.",
|
||||
file_id, file_parent);
|
||||
Twine::Id local_id = design->src_twines.intern_suffix(it->second, tail);
|
||||
twine_parser_holds.push_back(local_id);
|
||||
twine_remap[static_cast<Twine::Id>(file_id)] = local_id;
|
||||
continue;
|
||||
}
|
||||
if (try_parse_keyword("concat")) {
|
||||
int file_id = static_cast<int>(parse_integer());
|
||||
std::vector<Twine::Id> children;
|
||||
while (!try_parse_eol()) {
|
||||
Twine::Id file_child = static_cast<Twine::Id>(parse_integer());
|
||||
auto it = twine_remap.find(file_child);
|
||||
if (it == twine_remap.end())
|
||||
error("twines: concat %d references undefined leaf/concat %u.",
|
||||
file_id, file_child);
|
||||
children.push_back(it->second);
|
||||
}
|
||||
Twine::Id local_id = design->src_twines.concat(
|
||||
std::span<const Twine::Id>{children});
|
||||
twine_parser_holds.push_back(local_id);
|
||||
twine_remap[static_cast<Twine::Id>(file_id)] = local_id;
|
||||
continue;
|
||||
}
|
||||
error("Expected `leaf`, `suffix` or `concat` inside twines block, got `%s'.",
|
||||
error_token());
|
||||
}
|
||||
expect_eol();
|
||||
}
|
||||
|
||||
// Release the per-file parser refs gathered during parse_twines. Call
|
||||
// once the entire file has been parsed and every cell/wire that ever
|
||||
// referred to a file_id has already adopted the corresponding local_id.
|
||||
void release_twine_parser_holds()
|
||||
{
|
||||
for (Twine::Id id : twine_parser_holds)
|
||||
design->src_twines.release(id);
|
||||
twine_parser_holds.clear();
|
||||
twine_remap.clear();
|
||||
}
|
||||
|
||||
void parse_parameter()
|
||||
{
|
||||
RTLIL::IdString id = parse_id();
|
||||
|
|
@ -556,7 +666,7 @@ struct RTLILFrontendWorker {
|
|||
error("Unexpected wire option: %s", error_token());
|
||||
}
|
||||
|
||||
wire->attributes = std::move(attrbuf);
|
||||
wire->absorb_attrs(&design->src_twines, std::move(attrbuf));
|
||||
wire->width = width;
|
||||
wire->upto = upto;
|
||||
wire->start_offset = start_offset;
|
||||
|
|
@ -570,7 +680,7 @@ struct RTLILFrontendWorker {
|
|||
void parse_memory()
|
||||
{
|
||||
RTLIL::Memory *memory = new RTLIL::Memory;
|
||||
memory->attributes = std::move(attrbuf);
|
||||
memory->absorb_attrs(&design->src_twines, std::move(attrbuf));
|
||||
|
||||
int width = 1;
|
||||
int start_offset = 0;
|
||||
|
|
@ -638,7 +748,7 @@ struct RTLILFrontendWorker {
|
|||
error("RTLIL error: redefinition of cell %s.", cell_name);
|
||||
}
|
||||
RTLIL::Cell *cell = current_module->addCell(cell_name, cell_type);
|
||||
cell->attributes = std::move(attrbuf);
|
||||
cell->absorb_attrs(&design->src_twines, std::move(attrbuf));
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
|
@ -728,7 +838,7 @@ struct RTLILFrontendWorker {
|
|||
{
|
||||
RTLIL::SwitchRule *rule = new RTLIL::SwitchRule;
|
||||
rule->signal = parse_sigspec();
|
||||
rule->attributes = std::move(attrbuf);
|
||||
rule->absorb_attrs(&design->src_twines, std::move(attrbuf));
|
||||
switch_stack.back()->push_back(rule);
|
||||
expect_eol();
|
||||
|
||||
|
|
@ -745,7 +855,7 @@ struct RTLILFrontendWorker {
|
|||
|
||||
expect_keyword("case");
|
||||
RTLIL::CaseRule *case_rule = new RTLIL::CaseRule;
|
||||
case_rule->attributes = std::move(attrbuf);
|
||||
case_rule->absorb_attrs(&design->src_twines, std::move(attrbuf));
|
||||
rule->cases.push_back(case_rule);
|
||||
switch_stack.push_back(&case_rule->switches);
|
||||
case_stack.push_back(case_rule);
|
||||
|
|
@ -779,7 +889,7 @@ struct RTLILFrontendWorker {
|
|||
error("RTLIL error: redefinition of process %s.", proc_name);
|
||||
}
|
||||
RTLIL::Process *proc = current_module->addProcess(std::move(proc_name));
|
||||
proc->attributes = std::move(attrbuf);
|
||||
proc->absorb_attrs(&design->src_twines, std::move(attrbuf));
|
||||
|
||||
switch_stack.clear();
|
||||
switch_stack.push_back(&proc->root_case.switches);
|
||||
|
|
@ -828,7 +938,7 @@ struct RTLILFrontendWorker {
|
|||
break;
|
||||
|
||||
RTLIL::MemWriteAction act;
|
||||
act.attributes = std::move(attrbuf);
|
||||
act.absorb_attrs(&design->src_twines, std::move(attrbuf));
|
||||
act.memid = parse_id();
|
||||
act.address = parse_sigspec();
|
||||
act.data = parse_sigspec();
|
||||
|
|
@ -869,10 +979,15 @@ struct RTLILFrontendWorker {
|
|||
expect_eol();
|
||||
continue;
|
||||
}
|
||||
if (try_parse_keyword("twines")) {
|
||||
parse_twines();
|
||||
continue;
|
||||
}
|
||||
error("Unexpected token: %s", error_token());
|
||||
}
|
||||
if (attrbuf.size() != 0)
|
||||
error("dangling attribute");
|
||||
release_twine_parser_holds();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
26
kernel/ff.cc
26
kernel/ff.cc
|
|
@ -39,6 +39,15 @@ void manufacture_info(InputType flop, OutputType& info, FfInitVals *initvals) {
|
|||
info.sig_q = cell->getPort(ID::Q);
|
||||
info.width = GetSize(info.sig_q);
|
||||
info.attributes = cell->attributes;
|
||||
// Carry src across construction → emit() as an owning Twine
|
||||
// reference. Retaining a slot on the source pool keeps it
|
||||
// alive even if the source cell gets removed between
|
||||
// manufacture_info() and emit(); emit() then transfers the
|
||||
// id verbatim into the new cell — no flatten/re-intern, no
|
||||
// pipe-leaf risk for cells whose src is a Concat.
|
||||
if (cell->src_id() != Twine::Null && cell->module && cell->module->design)
|
||||
info.src_twine = OwnedTwine(&cell->module->design->src_twines,
|
||||
cell->src_id());
|
||||
if (initvals)
|
||||
info.val_init = (*initvals)(info.sig_q);
|
||||
}
|
||||
|
|
@ -753,7 +762,24 @@ Cell *FfData::emit() {
|
|||
}
|
||||
}
|
||||
}
|
||||
// src is carried in info.src_twine (an OwnedTwine retaining the
|
||||
// source slot). Transfer the id verbatim to the new cell — same
|
||||
// pool, no flatten. The OwnedTwine still holds its own ref until
|
||||
// FfData is destroyed; set_src_id retains on the cell's behalf.
|
||||
cell->attributes = attributes;
|
||||
if (!src_twine.empty() && cell->module && cell->module->design) {
|
||||
TwinePool *dst_pool = &cell->module->design->src_twines;
|
||||
if (src_twine.pool() == dst_pool) {
|
||||
cell->set_src_id(dst_pool, src_twine.id());
|
||||
} else {
|
||||
// Cross-pool (unusual — FfData migrated between
|
||||
// designs). Rebuild the twine structure into the
|
||||
// destination pool, then adopt that fresh id.
|
||||
Twine::Id migrated = dst_pool->copy_from(*src_twine.pool(), src_twine.id());
|
||||
cell->set_src_id(dst_pool, migrated);
|
||||
dst_pool->release(migrated);
|
||||
}
|
||||
}
|
||||
if (initvals && !is_anyinit)
|
||||
initvals->set_init(cell->getPort(ID::Q), val_init);
|
||||
return cell;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/ffinit.h"
|
||||
#include "kernel/twine.h"
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
|
|
@ -169,6 +170,10 @@ struct FfData : FfTypeData {
|
|||
// The FF data width in bits.
|
||||
int width;
|
||||
dict<IdString, Const> attributes;
|
||||
// Stashed src across construction → emit. Refcount-managed so the
|
||||
// source cell's pool slot survives if the cell itself is removed
|
||||
// before emit() runs. Empty when the source cell had no src.
|
||||
OwnedTwine src_twine;
|
||||
|
||||
FfData(Module *module = nullptr, FfInitVals *initvals = nullptr, IdString name = IdString()) : module(module), initvals(initvals), cell(nullptr), name(name) {
|
||||
width = 0;
|
||||
|
|
|
|||
|
|
@ -888,7 +888,14 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
|
|||
if (!port.clk_enable)
|
||||
return nullptr;
|
||||
|
||||
std::string mem_src = get_src_attribute();
|
||||
// Keep src as a "@N" reference into the design's twine pool throughout
|
||||
// — never flatten to a literal path string. That way every addX call
|
||||
// below adopts the same slot as Mem itself (via set_src_attribute's
|
||||
// "@N" parse_ref path), and there's no flatten → re-intern → pipe-
|
||||
// leaf round-trip on cells whose src is a Concat node.
|
||||
TwinePool *src_pool = (module && module->design) ? &module->design->src_twines : nullptr;
|
||||
std::string mem_src = (src_pool && src_id_ != Twine::Null) ?
|
||||
TwinePool::format_ref(src_id_) : std::string();
|
||||
|
||||
Cell *c;
|
||||
|
||||
|
|
@ -994,8 +1001,10 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
|
|||
|
||||
IdString name = stringf("$%s$rdreg[%d]", memid, idx);
|
||||
FfData ff(module, initvals, name);
|
||||
if (!mem_src.empty())
|
||||
ff.attributes[ID::src] = mem_src;
|
||||
// Carry mem's src into the ff via the OwnedTwine handle — same
|
||||
// pool, direct id retain. emit() transfers verbatim.
|
||||
if (src_pool && src_id_ != Twine::Null)
|
||||
ff.src_twine = OwnedTwine(src_pool, src_id_);
|
||||
ff.width = GetSize(port.data);
|
||||
ff.has_clk = true;
|
||||
ff.sig_clk = port.clk;
|
||||
|
|
|
|||
25
kernel/pmux.h
Normal file
25
kernel/pmux.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef PMUX_H
|
||||
#define PMUX_H
|
||||
|
||||
#include "kernel/yosys_common.h"
|
||||
#include "kernel/rtlil.h"
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
struct PmuxBPortIterator {
|
||||
Cell* cell;
|
||||
std::vector<SigBit> b;
|
||||
int port_idx;
|
||||
int port_count;
|
||||
PmuxBPortIterator(Cell* mux) : cell(mux) {
|
||||
log_assert(mux->type == ID($mux) || mux->type == ID($pmux));
|
||||
port_idx = 0;
|
||||
b = mux->getPort(ID::B).to_sigbit_vector();
|
||||
|
||||
port_count = GetSize(sig_b) / s_width;
|
||||
}
|
||||
};
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
775
kernel/rtlil.cc
775
kernel/rtlil.cc
File diff suppressed because it is too large
Load diff
555
kernel/rtlil.h
555
kernel/rtlil.h
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "kernel/yosys_common.h"
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/twine.h"
|
||||
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
|
@ -125,11 +126,39 @@ namespace RTLIL
|
|||
struct OwningIdString;
|
||||
struct StaticIdString;
|
||||
struct SigNormIndex;
|
||||
struct SrcAttr;
|
||||
|
||||
typedef std::pair<SigSpec, SigSpec> SigSig;
|
||||
struct PortBit;
|
||||
};
|
||||
|
||||
// A small polymorphic handle representing src to be applied to an
|
||||
// AttrObject by a CellAdder method or set_src_attribute call. Holds
|
||||
// EITHER a pre-interned twine id (preferred — the destination just
|
||||
// retains the slot, no flatten/intern) OR a literal string ("@N" or a
|
||||
// raw path:line.col) for legacy callers. Implicit conversions cover
|
||||
// both shapes so existing string-passing call sites keep compiling
|
||||
// without changes; new code passing `cell->src_ref()` lands in the
|
||||
// cheap id branch.
|
||||
//
|
||||
// The caller must keep any pool slot named by `id` alive for the
|
||||
// duration of the call (typically: the source AttrObject still holds
|
||||
// it). Empty by default — passing a default-constructed SrcAttr to
|
||||
// set_src_attribute clears src_id_.
|
||||
struct RTLIL::SrcAttr
|
||||
{
|
||||
Twine::Id id = Twine::Null;
|
||||
std::string literal;
|
||||
|
||||
SrcAttr() = default;
|
||||
SrcAttr(Twine::Id i) : id(i) {}
|
||||
SrcAttr(std::string s) : literal(std::move(s)) {}
|
||||
SrcAttr(const char *s) : literal(s ? s : "") {}
|
||||
SrcAttr(std::string_view s) : literal(s) {}
|
||||
|
||||
bool empty() const { return id == Twine::Null && literal.empty(); }
|
||||
};
|
||||
|
||||
// TODO clean up?
|
||||
extern int64_t signorm_ns;
|
||||
extern int signorm_count;
|
||||
|
|
@ -1266,6 +1295,18 @@ struct RTLIL::AttrObject
|
|||
{
|
||||
dict<RTLIL::IdString, RTLIL::Const> attributes;
|
||||
|
||||
// Typed src field. Outside the attribute dict — src is a structured
|
||||
// reference into a TwinePool. The pool is NOT stored here: every live
|
||||
// AttrObject is reachable from a Design (Cell/Wire/Process via their
|
||||
// module, Module via its design field), and inner-process AttrObjects
|
||||
// (CaseRule, SwitchRule, MemWriteAction) are owned by a Process whose
|
||||
// dtor drives their refcount on their behalf. src_id_ is a "weak"
|
||||
// integer reference — copying it does not retain; destroying the
|
||||
// AttrObject does not release. Lifecycle is driven by the leaf
|
||||
// subtype's destructor (Cell, Wire, Module, Process) walking up to
|
||||
// its owning pool, and by Process::~Process for the nested types.
|
||||
Twine::Id src_id_ = Twine::Null;
|
||||
|
||||
bool has_attribute(RTLIL::IdString id) const;
|
||||
|
||||
void set_bool_attribute(RTLIL::IdString id, bool value=true);
|
||||
|
|
@ -1284,12 +1325,49 @@ struct RTLIL::AttrObject
|
|||
void add_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
|
||||
pool<string> get_strpool_attribute(RTLIL::IdString id) const;
|
||||
|
||||
void set_src_attribute(const std::string &src) {
|
||||
set_string_attribute(ID::src, src);
|
||||
}
|
||||
std::string get_src_attribute() const {
|
||||
return get_string_attribute(ID::src);
|
||||
}
|
||||
Twine::Id src_id() const { return src_id_; }
|
||||
|
||||
// Store an interned id and manage refcount via the provided pool:
|
||||
// retain the new id; release the previous one if any. Twine::Null
|
||||
// clears. The caller supplies the pool because AttrObject does not
|
||||
// store one — typically derived from context (cell->module->design->
|
||||
// src_twines and friends) or known directly (frontends, copy_from).
|
||||
void set_src_id(TwinePool *pool, Twine::Id id);
|
||||
|
||||
// Apply `src` to this AttrObject via `pool`. If `src` carries a
|
||||
// pre-interned id (returned by e.g. `other->src_ref()`) it is
|
||||
// retained directly — no flatten/intern. Otherwise `src.literal`
|
||||
// is interned (handling "@N" refs and splitting pipe-joined
|
||||
// multi-leaf inputs into a Concat). Empty `src` clears src_id_.
|
||||
void set_src_attribute(TwinePool *pool, const RTLIL::SrcAttr &src);
|
||||
// Flatten the held src_id_ via `pool` to its pipe-joined literal.
|
||||
std::string get_src_attribute(const TwinePool *pool) const;
|
||||
|
||||
// Transfer src verbatim from `source` to this object. The two-arg
|
||||
// form assumes same-pool: `source`'s src_id_ is retained directly
|
||||
// on the destination in `pool`. The three-arg form handles the
|
||||
// cross-pool case by rebuilding `source`'s subtree (Concat/Suffix/
|
||||
// Leaf) into `dst_pool` via copy_from. Either way no flatten/
|
||||
// re-intern round-trip on the canonical leaf strings, so a Concat
|
||||
// src never collapses into a pipe-containing Leaf.
|
||||
void adopt_src_from(TwinePool *pool, const RTLIL::AttrObject *source);
|
||||
void adopt_src_from(TwinePool *dst_pool, const RTLIL::AttrObject *source,
|
||||
const TwinePool *src_pool);
|
||||
|
||||
// The raw twine id naming this object's src. Pass this — never the
|
||||
// flattened path string from get_src_attribute() — when handing
|
||||
// src to a CellAdder method or to another object's set_src: every
|
||||
// CellAdder method has a Twine::Id overload that adopts the slot
|
||||
// directly with no flatten/intern round-trip, preserving Suffix/
|
||||
// Concat structure and never producing a pipe-containing Leaf
|
||||
// from a Concat src.
|
||||
Twine::Id src_ref() const { return src_id_; }
|
||||
|
||||
// Replace `attributes` with `buf`, extracting any ID::src entry first
|
||||
// and routing it via `pool` to the typed src_id_ field. Use this in
|
||||
// frontends instead of `obj->attributes = std::move(buf)` so file src
|
||||
// lands in the twine pool rather than the attribute dict.
|
||||
void absorb_attrs(TwinePool *pool, dict<RTLIL::IdString, RTLIL::Const> &&buf);
|
||||
|
||||
void set_hdlname_attribute(const vector<string> &hierarchy);
|
||||
vector<string> get_hdlname_attribute() const;
|
||||
|
|
@ -1911,6 +1989,49 @@ struct RTLIL::Design
|
|||
dict<RTLIL::IdString, RTLIL::Module*> modules_;
|
||||
std::vector<RTLIL::Binding*> bindings_;
|
||||
|
||||
// Interns src-attribute strings and concats thereof. Cells reach this
|
||||
// via cell->module->design->src_twines.
|
||||
TwinePool src_twines;
|
||||
|
||||
// Resolve a stored src-attribute string to its flat path:line.col
|
||||
// representation. If `raw` is a twine reference ("@N") returns
|
||||
// src_twines.flatten(N); otherwise returns `raw` unchanged. Backends
|
||||
// must call this whenever they emit src to a user-facing format.
|
||||
std::string resolve_src(std::string_view raw) const {
|
||||
Twine::Id id = TwinePool::parse_ref(raw);
|
||||
if (id == Twine::Null)
|
||||
return std::string(raw);
|
||||
return src_twines.flatten(id);
|
||||
}
|
||||
|
||||
// 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
|
||||
// any AttrObject's src, then compact src_twines to contain only those
|
||||
// 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();
|
||||
|
||||
std::vector<std::unique_ptr<AST::AstNode>> verilog_packages, verilog_globals;
|
||||
std::unique_ptr<define_map_t> verilog_defines;
|
||||
|
||||
|
|
@ -1952,6 +2073,13 @@ struct RTLIL::Design
|
|||
void check();
|
||||
void optimize();
|
||||
|
||||
// Wholesale-copy this design into `dst`. `dst` must be empty (no
|
||||
// modules). Copies src_twines verbatim and clones each module
|
||||
// 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;
|
||||
|
||||
// checks if the given module is included in the current selection
|
||||
bool selected_module(RTLIL::IdString mod_name) const;
|
||||
|
||||
|
|
@ -2065,7 +2193,7 @@ struct RTLIL::Design
|
|||
};
|
||||
|
||||
namespace RTLIL_BACKEND {
|
||||
void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire);
|
||||
void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire, const RTLIL::Design *design, bool resolve_src);
|
||||
}
|
||||
|
||||
struct RTLIL::Wire : public RTLIL::NamedObject
|
||||
|
|
@ -2083,7 +2211,7 @@ public:
|
|||
Wire(ConstructToken);
|
||||
~Wire();
|
||||
|
||||
friend void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire);
|
||||
friend void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire, const RTLIL::Design *design, bool resolve_src);
|
||||
RTLIL::Cell *driverCell_ = nullptr;
|
||||
RTLIL::IdString driverPort_;
|
||||
|
||||
|
|
@ -2095,6 +2223,17 @@ public:
|
|||
int width, start_offset, port_id;
|
||||
bool port_input, port_output, upto, is_signed;
|
||||
|
||||
// Context-aware src helpers. Resolve the destination pool via
|
||||
// `module->design->src_twines`; assert the wire is attached.
|
||||
using AttrObject::set_src_attribute;
|
||||
using AttrObject::get_src_attribute;
|
||||
using AttrObject::adopt_src_from;
|
||||
void set_src_attribute(const RTLIL::SrcAttr &src);
|
||||
std::string get_src_attribute() const;
|
||||
// Transfer src from `source` verbatim (same pool). Asserts attached
|
||||
// to a design — derives the pool via module->design->src_twines.
|
||||
void adopt_src_from(const RTLIL::AttrObject *source);
|
||||
|
||||
bool known_driver() const { return driverCell_ != nullptr; }
|
||||
|
||||
RTLIL::Cell *driverCell() const { log_assert(driverCell_); return driverCell_; };
|
||||
|
|
@ -2172,6 +2311,17 @@ public:
|
|||
dict<RTLIL::IdString, RTLIL::SigSpec> connections_;
|
||||
dict<RTLIL::IdString, RTLIL::Const> parameters;
|
||||
|
||||
// Context-aware src helpers. Resolve the destination pool via
|
||||
// `module->design->src_twines`; assert the cell is attached.
|
||||
using AttrObject::set_src_attribute;
|
||||
using AttrObject::get_src_attribute;
|
||||
using AttrObject::adopt_src_from;
|
||||
void set_src_attribute(const RTLIL::SrcAttr &src);
|
||||
std::string get_src_attribute() const;
|
||||
// Transfer src from `source` verbatim (same pool). Asserts attached
|
||||
// to a design — derives the pool via module->design->src_twines.
|
||||
void adopt_src_from(const RTLIL::AttrObject *source);
|
||||
|
||||
// access cell ports
|
||||
bool hasPort(RTLIL::IdString portname) const;
|
||||
void unsetPort(RTLIL::IdString portname);
|
||||
|
|
@ -2281,6 +2431,17 @@ public:
|
|||
RTLIL::CaseRule root_case;
|
||||
std::vector<RTLIL::SyncRule*> syncs;
|
||||
|
||||
// Context-aware src helpers. Resolve the destination pool via
|
||||
// `module->design->src_twines`; assert the process is attached.
|
||||
using AttrObject::set_src_attribute;
|
||||
using AttrObject::get_src_attribute;
|
||||
using AttrObject::adopt_src_from;
|
||||
void set_src_attribute(const RTLIL::SrcAttr &src);
|
||||
std::string get_src_attribute() const;
|
||||
// Transfer src from `source` verbatim (same pool). Asserts attached
|
||||
// to a design — derives the pool via module->design->src_twines.
|
||||
void adopt_src_from(const RTLIL::AttrObject *source);
|
||||
|
||||
template<typename T> void rewrite_sigspecs(T &functor);
|
||||
template<typename T> void rewrite_sigspecs2(T &functor);
|
||||
RTLIL::Process *clone() const;
|
||||
|
|
@ -2380,212 +2541,212 @@ class CellAdderMixin {
|
|||
public:
|
||||
// The add* methods create a cell and return the created cell. All signals must exist in advance.
|
||||
|
||||
RTLIL::Cell* addNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addPos (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addBuf (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addNeg (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addPos (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addBuf (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addNeg (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addXor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addXnor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addXor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addXnor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addReduceAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addReduceOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addReduceXor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addReduceXnor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addReduceBool (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addReduceAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addReduceOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addReduceXor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addReduceXnor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addReduceBool (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addShl (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addShr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addSshl (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addSshr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addShift (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addShiftx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addShl (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addShr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addSshl (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addSshr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addShift (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addShiftx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addLt (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addLe (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addEq (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addNe (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addEqx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addNex (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addGe (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addGt (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addLt (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addLe (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addEq (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addNe (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addEqx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addNex (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addGe (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addGt (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addAdd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addSub (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addMul (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addAdd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addSub (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addMul (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
// truncating division
|
||||
RTLIL::Cell* addDiv (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addDiv (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
// truncating modulo
|
||||
RTLIL::Cell* addMod (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addDivFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addModFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addPow (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool a_signed = false, bool b_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addMod (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDivFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addModFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addPow (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool a_signed = false, bool b_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addFa (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addFa (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addLogicNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addLogicAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addLogicOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addLogicNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addLogicAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addLogicOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addMux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addPmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addBmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addDemux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addMux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addPmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addBmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDemux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addBweqx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addBwmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addBweqx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addBwmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addSlice (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const offset, const std::string &src = "");
|
||||
RTLIL::Cell* addConcat (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addLut (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const lut, const std::string &src = "");
|
||||
RTLIL::Cell* addTribuf (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addAssert (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src = "");
|
||||
RTLIL::Cell* addAssume (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src = "");
|
||||
RTLIL::Cell* addLive (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src = "");
|
||||
RTLIL::Cell* addFair (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src = "");
|
||||
RTLIL::Cell* addCover (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src = "");
|
||||
RTLIL::Cell* addEquiv (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addSlice (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const offset, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addConcat (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addLut (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const lut, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addTribuf (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAssert (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAssume (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addLive (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addFair (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addCover (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addEquiv (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addSr (RTLIL::IdString name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, const RTLIL::SigSpec &sig_q, bool set_polarity = true, bool clr_polarity = true, const std::string &src = "");
|
||||
RTLIL::Cell* addFf (RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src = "");
|
||||
RTLIL::Cell* addDff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, const std::string &src = "");
|
||||
RTLIL::Cell* addDffe (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addDffsr (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addDffsre (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addAdff (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addAdffe (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addAldff (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addAldffe (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addSdff (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addSdffe (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addSdffce (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addDlatch (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, const std::string &src = "");
|
||||
RTLIL::Cell* addAdlatch (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addDlatchsr (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addSr (RTLIL::IdString name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, const RTLIL::SigSpec &sig_q, bool set_polarity = true, bool clr_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addFf (RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDffe (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDffsr (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDffsre (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAdff (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAdffe (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAldff (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAldffe (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addSdff (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addSdffe (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addSdffce (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDlatch (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAdlatch (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDlatchsr (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addBufGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addNotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addAndGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addNandGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addOrGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addNorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addXorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addXnorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addAndnotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addOrnotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addMuxGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addNmuxGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addAoi3Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addOai3Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addAoi4Gate (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addOai4Gate (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::Cell* addBufGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addNotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAndGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addNandGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addOrGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addNorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addXorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addXnorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAndnotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addOrnotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addMuxGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addNmuxGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAoi3Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addOai3Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_y, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAoi4Gate (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addOai4Gate (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addSrGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr,
|
||||
const RTLIL::SigSpec &sig_q, bool set_polarity = true, bool clr_polarity = true, const std::string &src = "");
|
||||
RTLIL::Cell* addFfGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src = "");
|
||||
RTLIL::Cell* addDffGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, const std::string &src = "");
|
||||
RTLIL::Cell* addDffeGate (RTLIL::IdString 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, const std::string &src = "");
|
||||
const RTLIL::SigSpec &sig_q, bool set_polarity = true, bool clr_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addFfGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDffGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDffeGate (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDffsrGate (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool set_polarity = true, bool clr_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDffsreGate (RTLIL::IdString 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, const std::string &src = "");
|
||||
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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAdffGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
|
||||
bool arst_value = false, bool clk_polarity = true, bool arst_polarity = true, const std::string &src = "");
|
||||
bool arst_value = false, bool clk_polarity = true, bool arst_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAdffeGate (RTLIL::IdString 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,
|
||||
bool arst_value = false, bool clk_polarity = true, bool en_polarity = true, bool arst_polarity = true, const std::string &src = "");
|
||||
bool arst_value = false, bool clk_polarity = true, bool en_polarity = true, bool arst_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAldffGate (RTLIL::IdString 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, const std::string &src = "");
|
||||
const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool aload_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAldffeGate (RTLIL::IdString 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, const std::string &src = "");
|
||||
const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool en_polarity = true, bool aload_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addSdffGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
|
||||
bool srst_value = false, bool clk_polarity = true, bool srst_polarity = true, const std::string &src = "");
|
||||
bool srst_value = false, bool clk_polarity = true, bool srst_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addSdffeGate (RTLIL::IdString 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,
|
||||
bool srst_value = false, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, const std::string &src = "");
|
||||
bool srst_value = false, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addSdffceGate (RTLIL::IdString 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,
|
||||
bool srst_value = false, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, const std::string &src = "");
|
||||
RTLIL::Cell* addDlatchGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, const std::string &src = "");
|
||||
bool srst_value = false, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDlatchGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addAdlatchGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
|
||||
bool arst_value = false, bool en_polarity = true, bool arst_polarity = true, const std::string &src = "");
|
||||
bool arst_value = false, bool en_polarity = true, bool arst_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addDlatchsrGate (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::Cell* addAnyinit(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src = "");
|
||||
RTLIL::Cell* addAnyinit(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
// The methods without the add* prefix create a cell and an output signal. They return the newly created output signal.
|
||||
|
||||
RTLIL::SigSpec Not (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Pos (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Buf (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Neg (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Not (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Pos (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Buf (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Neg (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::SigSpec And (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Or (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Xor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Xnor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec And (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Or (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Xor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Xnor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::SigSpec ReduceAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec ReduceOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec ReduceXor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec ReduceXnor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec ReduceBool (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec ReduceAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec ReduceOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec ReduceXor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec ReduceXnor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec ReduceBool (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::SigSpec Shl (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Shr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Sshl (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Sshr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Shift (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Shiftx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Shl (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Shr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Sshl (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Sshr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Shift (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Shiftx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::SigSpec Lt (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Le (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Eq (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Ne (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Eqx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Nex (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Ge (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Gt (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Lt (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Le (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Eq (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Ne (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Eqx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Nex (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Ge (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Gt (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::SigSpec Add (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Sub (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Mul (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Add (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Sub (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Mul (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
// truncating division
|
||||
RTLIL::SigSpec Div (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Div (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
// truncating modulo
|
||||
RTLIL::SigSpec Mod (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec DivFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec ModFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Pow (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool a_signed = false, bool b_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec Mod (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec DivFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec ModFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Pow (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool a_signed = false, bool b_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::SigSpec LogicNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec LogicAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec LogicOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::SigSpec LogicNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec LogicAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec LogicOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::SigSpec Mux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const std::string &src = "");
|
||||
RTLIL::SigSpec Pmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const std::string &src = "");
|
||||
RTLIL::SigSpec Bmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const std::string &src = "");
|
||||
RTLIL::SigSpec Demux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const std::string &src = "");
|
||||
RTLIL::SigSpec Mux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Pmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Bmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Demux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::SigSpec Bweqx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const std::string &src = "");
|
||||
RTLIL::SigSpec Bwmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const std::string &src = "");
|
||||
RTLIL::SigSpec Bweqx (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Bwmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::SigBit BufGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const std::string &src = "");
|
||||
RTLIL::SigBit NotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const std::string &src = "");
|
||||
RTLIL::SigBit AndGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = "");
|
||||
RTLIL::SigBit NandGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = "");
|
||||
RTLIL::SigBit OrGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = "");
|
||||
RTLIL::SigBit NorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = "");
|
||||
RTLIL::SigBit XorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = "");
|
||||
RTLIL::SigBit XnorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = "");
|
||||
RTLIL::SigBit AndnotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = "");
|
||||
RTLIL::SigBit OrnotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const std::string &src = "");
|
||||
RTLIL::SigBit MuxGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const std::string &src = "");
|
||||
RTLIL::SigBit NmuxGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const std::string &src = "");
|
||||
RTLIL::SigBit Aoi3Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const std::string &src = "");
|
||||
RTLIL::SigBit Oai3Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const std::string &src = "");
|
||||
RTLIL::SigBit Aoi4Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, const std::string &src = "");
|
||||
RTLIL::SigBit Oai4Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, const std::string &src = "");
|
||||
RTLIL::SigBit BufGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit NotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit AndGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit NandGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit OrGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit NorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit XorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit XnorGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit AndnotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit OrnotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit MuxGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit NmuxGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_s, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit Aoi3Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit Oai3Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit Aoi4Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigBit Oai4Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
};
|
||||
|
||||
struct RTLIL::Module : public RTLIL::NamedObject, public CellAdderMixin<RTLIL::Module>
|
||||
|
|
@ -2620,6 +2781,17 @@ public:
|
|||
dict<RTLIL::IdString, RTLIL::Memory*> memories;
|
||||
dict<RTLIL::IdString, RTLIL::Process*> processes;
|
||||
|
||||
// Context-aware src helpers. Resolve the destination pool via
|
||||
// `design->src_twines`; assert the module is attached.
|
||||
using AttrObject::set_src_attribute;
|
||||
using AttrObject::get_src_attribute;
|
||||
using AttrObject::adopt_src_from;
|
||||
void set_src_attribute(const RTLIL::SrcAttr &src);
|
||||
std::string get_src_attribute() const;
|
||||
// Transfer src from `source` verbatim (same pool). Asserts attached
|
||||
// to a design — derives the pool via module->design->src_twines.
|
||||
void adopt_src_from(const RTLIL::AttrObject *source);
|
||||
|
||||
Module();
|
||||
virtual ~Module();
|
||||
virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, bool mayfail = false);
|
||||
|
|
@ -2675,8 +2847,21 @@ public:
|
|||
|
||||
template<typename T> void rewrite_sigspecs(T &functor);
|
||||
template<typename T> void rewrite_sigspecs2(T &functor);
|
||||
void cloneInto(RTLIL::Module *new_mod) const;
|
||||
// `src_id_verbatim`: when true, the caller guarantees that
|
||||
// `new_mod->design->src_twines` is a verbatim copy of
|
||||
// `this->design->src_twines`, so src_id_ values can be transferred
|
||||
// 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;
|
||||
virtual RTLIL::Module *clone() const;
|
||||
// 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;
|
||||
|
||||
bool has_memories() const;
|
||||
bool has_processes() const;
|
||||
|
|
@ -2754,22 +2939,22 @@ public:
|
|||
|
||||
// The add* methods create a cell and return the created cell. All signals must exist in advance.
|
||||
|
||||
RTLIL::Cell* addAnyinit(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src = "");
|
||||
RTLIL::Cell* addAnyinit(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
// The methods without the add* prefix create a cell and an output signal. They return the newly created output signal.
|
||||
|
||||
RTLIL::SigSpec Anyconst (RTLIL::IdString name, int width = 1, const std::string &src = "");
|
||||
RTLIL::SigSpec Anyseq (RTLIL::IdString name, int width = 1, const std::string &src = "");
|
||||
RTLIL::SigSpec Allconst (RTLIL::IdString name, int width = 1, const std::string &src = "");
|
||||
RTLIL::SigSpec Allseq (RTLIL::IdString name, int width = 1, const std::string &src = "");
|
||||
RTLIL::SigSpec Initstate (RTLIL::IdString name, const std::string &src = "");
|
||||
RTLIL::SigSpec Anyconst (RTLIL::IdString name, int width = 1, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Anyseq (RTLIL::IdString name, int width = 1, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Allconst (RTLIL::IdString name, int width = 1, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Allseq (RTLIL::IdString name, int width = 1, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec Initstate (RTLIL::IdString name, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
RTLIL::SigSpec SetTag (RTLIL::IdString name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, const std::string &src = "");
|
||||
RTLIL::Cell* addSetTag (RTLIL::IdString 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, const std::string &src = "");
|
||||
RTLIL::SigSpec GetTag (RTLIL::IdString name, const std::string &tag, const RTLIL::SigSpec &sig_a, const std::string &src = "");
|
||||
RTLIL::Cell* addOverwriteTag (RTLIL::IdString name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, const std::string &src = "");
|
||||
RTLIL::SigSpec OriginalTag (RTLIL::IdString name, const std::string &tag, const RTLIL::SigSpec &sig_a, const std::string &src = "");
|
||||
RTLIL::SigSpec FutureFF (RTLIL::IdString name, const RTLIL::SigSpec &sig_e, const std::string &src = "");
|
||||
RTLIL::SigSpec SetTag (RTLIL::IdString name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addSetTag (RTLIL::IdString 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, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec GetTag (RTLIL::IdString name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::Cell* addOverwriteTag (RTLIL::IdString name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec OriginalTag (RTLIL::IdString name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
RTLIL::SigSpec FutureFF (RTLIL::IdString name, const RTLIL::SigSpec &sig_e, const RTLIL::SrcAttr &src = RTLIL::SrcAttr());
|
||||
|
||||
std::string to_rtlil_str() const;
|
||||
#ifdef YOSYS_ENABLE_PYTHON
|
||||
|
|
|
|||
455
kernel/twine.cc
Normal file
455
kernel/twine.cc
Normal file
|
|
@ -0,0 +1,455 @@
|
|||
#include "kernel/twine.h"
|
||||
#include "kernel/log.h"
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
Twine::Id TwinePool::alloc_slot_(Twine &&node)
|
||||
{
|
||||
if (!free_list_.empty()) {
|
||||
// Pop the SMALLEST free id (not the most recent), so reuse order
|
||||
// matches the original allocation order when an entire pool gets
|
||||
// freed and rebuilt. That makes write_rtlil emit byte-identical
|
||||
// "@N" refs across design -push;-pop and similar wholesale-clone
|
||||
// cycles, even though the in-memory pool got renumbered through
|
||||
// the free list.
|
||||
auto it = std::min_element(free_list_.begin(), free_list_.end());
|
||||
Twine::Id id = *it;
|
||||
free_list_.erase(it);
|
||||
nodes_[id] = std::move(node);
|
||||
refcount_[id] = 0;
|
||||
return id;
|
||||
}
|
||||
Twine::Id id = static_cast<Twine::Id>(nodes_.size());
|
||||
nodes_.push_back(std::move(node));
|
||||
refcount_.push_back(0);
|
||||
return id;
|
||||
}
|
||||
|
||||
Twine::Id TwinePool::intern(std::string_view leaf)
|
||||
{
|
||||
if (leaf.empty())
|
||||
return Twine::Null;
|
||||
std::string key{leaf};
|
||||
if (auto it = leaf_index_.find(key); it != leaf_index_.end()) {
|
||||
retain(it->second);
|
||||
return it->second;
|
||||
}
|
||||
Twine::Id id = alloc_slot_(Twine{std::move(key)});
|
||||
leaf_index_[std::get<std::string>(nodes_[id].data)] = id;
|
||||
refcount_[id] = 1;
|
||||
return id;
|
||||
}
|
||||
|
||||
Twine::Id TwinePool::intern_suffix(Twine::Id parent, std::string_view tail)
|
||||
{
|
||||
if (parent == Twine::Null)
|
||||
return intern(tail);
|
||||
log_assert(parent < nodes_.size() && !nodes_[parent].is_dead());
|
||||
log_assert(nodes_[parent].is_flat() && "Suffix parent must be a flat node (Leaf or Suffix)");
|
||||
if (tail.empty()) {
|
||||
// No tail means "the same string as parent". Hand back a fresh
|
||||
// owning ref on parent — semantically equivalent to a degenerate
|
||||
// suffix node, but we avoid allocating a slot for it.
|
||||
retain(parent);
|
||||
return parent;
|
||||
}
|
||||
|
||||
std::pair<Twine::Id, std::string> key{parent, std::string{tail}};
|
||||
if (auto it = suffix_index_.find(key); it != suffix_index_.end()) {
|
||||
retain(it->second);
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Internal child ref: the suffix node owns one ref on its parent.
|
||||
retain(parent);
|
||||
Twine::Id id = alloc_slot_(Twine{Twine::Suffix{parent, std::string{tail}}});
|
||||
const auto &stored = std::get<Twine::Suffix>(nodes_[id].data);
|
||||
suffix_index_[std::make_pair(stored.parent, stored.tail)] = id;
|
||||
refcount_[id] = 1;
|
||||
return id;
|
||||
}
|
||||
|
||||
Twine::Id TwinePool::concat(std::span<const Twine::Id> parts)
|
||||
{
|
||||
// Flat invariant: a Concat node only ever holds flat children (Leaf
|
||||
// or Suffix), never another Concat. Splice in concats' children
|
||||
// directly so identical sets map to byte-equal child vectors
|
||||
// regardless of how callers nested concats.
|
||||
std::vector<Twine::Id> children;
|
||||
children.reserve(parts.size());
|
||||
pool<Twine::Id> seen;
|
||||
auto push_flat = [&](Twine::Id flat_id) {
|
||||
if (seen.insert(flat_id).second)
|
||||
children.push_back(flat_id);
|
||||
};
|
||||
for (Twine::Id p : parts) {
|
||||
if (p == Twine::Null)
|
||||
continue;
|
||||
log_assert(p < nodes_.size() && !nodes_[p].is_dead());
|
||||
const Twine &n = nodes_[p];
|
||||
if (n.is_flat()) {
|
||||
push_flat(p);
|
||||
} else {
|
||||
for (Twine::Id grandchild : n.children())
|
||||
push_flat(grandchild);
|
||||
}
|
||||
}
|
||||
|
||||
if (children.empty())
|
||||
return Twine::Null;
|
||||
if (children.size() == 1) {
|
||||
retain(children.front());
|
||||
return children.front();
|
||||
}
|
||||
|
||||
if (auto it = concat_index_.find(children); it != concat_index_.end()) {
|
||||
retain(it->second);
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Internal child refs: the concat node owns one ref on each child.
|
||||
for (Twine::Id c : children)
|
||||
retain(c);
|
||||
Twine::Id id = alloc_slot_(Twine{std::move(children)});
|
||||
concat_index_[std::get<std::vector<Twine::Id>>(nodes_[id].data)] = id;
|
||||
refcount_[id] = 1;
|
||||
return id;
|
||||
}
|
||||
|
||||
Twine::Id TwinePool::concat(Twine::Id a, Twine::Id b)
|
||||
{
|
||||
std::array<Twine::Id, 2> pair{a, b};
|
||||
return concat(std::span<const Twine::Id>{pair});
|
||||
}
|
||||
|
||||
void TwinePool::retain(Twine::Id id)
|
||||
{
|
||||
if (id == Twine::Null)
|
||||
return;
|
||||
log_assert(id < nodes_.size() && !nodes_[id].is_dead());
|
||||
refcount_[id]++;
|
||||
}
|
||||
|
||||
void TwinePool::release(Twine::Id id)
|
||||
{
|
||||
if (id == Twine::Null)
|
||||
return;
|
||||
log_assert(id < nodes_.size() && !nodes_[id].is_dead());
|
||||
log_assert(refcount_[id] > 0);
|
||||
if (--refcount_[id] == 0)
|
||||
destroy_slot_(id);
|
||||
}
|
||||
|
||||
uint32_t TwinePool::refcount(Twine::Id id) const
|
||||
{
|
||||
if (id == Twine::Null)
|
||||
return 0;
|
||||
return refcount_.at(id);
|
||||
}
|
||||
|
||||
bool TwinePool::is_alive(Twine::Id id) const
|
||||
{
|
||||
if (id == Twine::Null)
|
||||
return false;
|
||||
return id < nodes_.size() && !nodes_[id].is_dead();
|
||||
}
|
||||
|
||||
void TwinePool::destroy_slot_(Twine::Id id)
|
||||
{
|
||||
Twine &n = nodes_[id];
|
||||
if (n.is_leaf()) {
|
||||
leaf_index_.erase(n.leaf());
|
||||
} else if (n.is_concat()) {
|
||||
// Release internal child refs. Capture by move so iteration is
|
||||
// stable across child destroy_slot_ side effects.
|
||||
std::vector<Twine::Id> children = std::move(std::get<std::vector<Twine::Id>>(n.data));
|
||||
concat_index_.erase(children);
|
||||
n.data = std::monostate{};
|
||||
free_list_.push_back(id);
|
||||
for (Twine::Id c : children)
|
||||
release(c);
|
||||
return;
|
||||
} else if (n.is_suffix()) {
|
||||
// Capture parent by move and release after dropping the slot,
|
||||
// since releasing may recursively destroy the parent and we
|
||||
// want this slot's tombstone to be visible by then.
|
||||
Twine::Suffix s = std::move(std::get<Twine::Suffix>(n.data));
|
||||
suffix_index_.erase(std::make_pair(s.parent, s.tail));
|
||||
n.data = std::monostate{};
|
||||
free_list_.push_back(id);
|
||||
release(s.parent);
|
||||
return;
|
||||
}
|
||||
n.data = std::monostate{};
|
||||
free_list_.push_back(id);
|
||||
}
|
||||
|
||||
void TwinePool::collect_leaves(Twine::Id id, pool<std::string> &out) const
|
||||
{
|
||||
if (id == Twine::Null)
|
||||
return;
|
||||
const Twine &n = nodes_.at(id);
|
||||
if (n.is_dead())
|
||||
return;
|
||||
if (n.is_leaf()) {
|
||||
out.insert(n.leaf());
|
||||
return;
|
||||
}
|
||||
if (n.is_suffix()) {
|
||||
// A suffix is semantically a single flat string. Materialize it
|
||||
// and insert into the set just like a leaf.
|
||||
out.insert(flat_string_(id));
|
||||
return;
|
||||
}
|
||||
for (Twine::Id c : n.children())
|
||||
collect_leaves(c, out);
|
||||
}
|
||||
|
||||
std::string TwinePool::flat_string_(Twine::Id id) const
|
||||
{
|
||||
// Walk the parent chain iteratively to avoid recursion depth concerns
|
||||
// on deep suffix trees. Collect tails (and the root leaf) then stitch
|
||||
// in root-to-tail order.
|
||||
log_assert(id != Twine::Null);
|
||||
std::vector<std::string_view> parts;
|
||||
while (true) {
|
||||
const Twine &n = nodes_.at(id);
|
||||
if (n.is_leaf()) {
|
||||
parts.push_back(n.leaf());
|
||||
break;
|
||||
}
|
||||
log_assert(n.is_suffix());
|
||||
parts.push_back(n.suffix().tail);
|
||||
id = n.suffix().parent;
|
||||
}
|
||||
size_t total = 0;
|
||||
for (auto p : parts)
|
||||
total += p.size();
|
||||
std::string out;
|
||||
out.reserve(total);
|
||||
for (auto it = parts.rbegin(); it != parts.rend(); ++it)
|
||||
out.append(*it);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string TwinePool::flatten(Twine::Id id, char sep) const
|
||||
{
|
||||
if (id == Twine::Null)
|
||||
return {};
|
||||
pool<std::string> leaves;
|
||||
collect_leaves(id, leaves);
|
||||
std::string out;
|
||||
for (const auto &s : leaves) {
|
||||
if (s.empty())
|
||||
continue;
|
||||
if (!out.empty())
|
||||
out += sep;
|
||||
out += s;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string TwinePool::format_ref(Twine::Id id)
|
||||
{
|
||||
if (id == Twine::Null)
|
||||
return {};
|
||||
return "@" + std::to_string(id);
|
||||
}
|
||||
|
||||
Twine::Id TwinePool::parse_ref(std::string_view s)
|
||||
{
|
||||
if (s.size() < 2 || s[0] != '@')
|
||||
return Twine::Null;
|
||||
uint64_t v = 0;
|
||||
for (size_t i = 1; i < s.size(); i++) {
|
||||
char c = s[i];
|
||||
if (c < '0' || c > '9')
|
||||
return Twine::Null;
|
||||
v = v * 10 + static_cast<uint64_t>(c - '0');
|
||||
if (v >= std::numeric_limits<Twine::Id>::max())
|
||||
return Twine::Null;
|
||||
}
|
||||
return static_cast<Twine::Id>(v);
|
||||
}
|
||||
|
||||
void TwinePool::dump(const char *banner) const
|
||||
{
|
||||
if (banner)
|
||||
log("%s (%zu live nodes: %zu leaves, %zu suffixes, %zu concats, %zu free slots)\n",
|
||||
banner, nodes_.size() - free_list_.size(),
|
||||
leaf_index_.size(), suffix_index_.size(),
|
||||
concat_index_.size(), free_list_.size());
|
||||
for_each_live([&](Twine::Id id, const Twine &n) {
|
||||
if (n.is_leaf()) {
|
||||
log(" @%u leaf rc=%u %s\n", id, refcount_[id], n.leaf().c_str());
|
||||
} else if (n.is_suffix()) {
|
||||
log(" @%u suffix rc=%u @%u + %s\n", id, refcount_[id],
|
||||
n.suffix().parent, n.suffix().tail.c_str());
|
||||
} else {
|
||||
std::string children;
|
||||
for (Twine::Id c : n.children()) {
|
||||
if (!children.empty())
|
||||
children += ", ";
|
||||
children += "@" + std::to_string(c);
|
||||
}
|
||||
log(" @%u concat rc=%u [%s]\n", id, refcount_[id], children.c_str());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dict<Twine::Id, Twine::Id> TwinePool::gc(const pool<Twine::Id> &live)
|
||||
{
|
||||
// Closure: mark every node reachable from `live`. Concat children
|
||||
// (Leaf or Suffix) and Suffix parents (Leaf or Suffix) are both
|
||||
// followed. With Suffix nodes chains can be more than one step deep,
|
||||
// so use a worklist rather than a single BFS step.
|
||||
pool<Twine::Id> reachable;
|
||||
std::vector<Twine::Id> work;
|
||||
for (Twine::Id id : live) {
|
||||
if (id == Twine::Null || id >= nodes_.size() || nodes_[id].is_dead())
|
||||
continue;
|
||||
if (reachable.insert(id).second)
|
||||
work.push_back(id);
|
||||
}
|
||||
while (!work.empty()) {
|
||||
Twine::Id id = work.back();
|
||||
work.pop_back();
|
||||
const Twine &n = nodes_[id];
|
||||
if (n.is_concat()) {
|
||||
for (Twine::Id c : n.children())
|
||||
if (reachable.insert(c).second)
|
||||
work.push_back(c);
|
||||
} else if (n.is_suffix()) {
|
||||
Twine::Id p = n.suffix().parent;
|
||||
if (reachable.insert(p).second)
|
||||
work.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuild the pool from scratch. Process flats (Leaf, then Suffix)
|
||||
// before Concats so concat-child lookups can resolve, and process
|
||||
// suffixes parent-before-child via a recursive helper that memoizes
|
||||
// into `remap`.
|
||||
std::vector<Twine> new_nodes;
|
||||
std::vector<uint32_t> new_refcount;
|
||||
dict<std::string, Twine::Id> new_leaf_index;
|
||||
dict<std::vector<Twine::Id>, Twine::Id> new_concat_index;
|
||||
dict<std::pair<Twine::Id, std::string>, Twine::Id> new_suffix_index;
|
||||
dict<Twine::Id, Twine::Id> remap;
|
||||
|
||||
auto intern_leaf = [&](const std::string &text) -> Twine::Id {
|
||||
if (auto it = new_leaf_index.find(text); it != new_leaf_index.end())
|
||||
return it->second;
|
||||
Twine::Id id = static_cast<Twine::Id>(new_nodes.size());
|
||||
new_nodes.push_back(Twine{text});
|
||||
new_refcount.push_back(0);
|
||||
new_leaf_index[std::get<std::string>(new_nodes.back().data)] = id;
|
||||
return id;
|
||||
};
|
||||
|
||||
for (Twine::Id old_id : reachable) {
|
||||
const Twine &n = nodes_[old_id];
|
||||
if (n.is_leaf())
|
||||
remap[old_id] = intern_leaf(n.leaf());
|
||||
}
|
||||
|
||||
std::function<Twine::Id(Twine::Id)> remap_flat = [&](Twine::Id old_id) -> Twine::Id {
|
||||
if (auto it = remap.find(old_id); it != remap.end())
|
||||
return it->second;
|
||||
const Twine &n = nodes_[old_id];
|
||||
log_assert(n.is_suffix());
|
||||
Twine::Id new_parent = remap_flat(n.suffix().parent);
|
||||
std::pair<Twine::Id, std::string> key{new_parent, n.suffix().tail};
|
||||
if (auto sit = new_suffix_index.find(key); sit != new_suffix_index.end()) {
|
||||
remap[old_id] = sit->second;
|
||||
return sit->second;
|
||||
}
|
||||
Twine::Id new_id = static_cast<Twine::Id>(new_nodes.size());
|
||||
new_nodes.push_back(Twine{Twine::Suffix{new_parent, n.suffix().tail}});
|
||||
new_refcount.push_back(0);
|
||||
const auto &stored = std::get<Twine::Suffix>(new_nodes.back().data);
|
||||
new_suffix_index[std::make_pair(stored.parent, stored.tail)] = new_id;
|
||||
remap[old_id] = new_id;
|
||||
return new_id;
|
||||
};
|
||||
|
||||
for (Twine::Id old_id : reachable) {
|
||||
const Twine &n = nodes_[old_id];
|
||||
if (n.is_suffix() && remap.find(old_id) == remap.end())
|
||||
remap_flat(old_id);
|
||||
}
|
||||
|
||||
for (Twine::Id old_id : reachable) {
|
||||
const Twine &n = nodes_[old_id];
|
||||
if (!n.is_concat())
|
||||
continue;
|
||||
std::vector<Twine::Id> children;
|
||||
children.reserve(n.children().size());
|
||||
for (Twine::Id c : n.children())
|
||||
children.push_back(remap.at(c));
|
||||
if (auto it = new_concat_index.find(children); it != new_concat_index.end()) {
|
||||
remap[old_id] = it->second;
|
||||
} else {
|
||||
Twine::Id new_id = static_cast<Twine::Id>(new_nodes.size());
|
||||
new_nodes.push_back(Twine{std::move(children)});
|
||||
new_refcount.push_back(0);
|
||||
new_concat_index[std::get<std::vector<Twine::Id>>(new_nodes.back().data)] = new_id;
|
||||
remap[old_id] = new_id;
|
||||
}
|
||||
}
|
||||
|
||||
// Refcounts in the rebuilt pool: every external "live" id passed in by
|
||||
// the caller corresponds to one external owner reference; concats
|
||||
// hold one ref per stored child; suffixes hold one ref on their parent.
|
||||
for (Twine::Id old_id : live) {
|
||||
auto it = remap.find(old_id);
|
||||
if (it != remap.end())
|
||||
new_refcount[it->second]++;
|
||||
}
|
||||
for (size_t i = 0; i < new_nodes.size(); i++) {
|
||||
if (new_nodes[i].is_concat()) {
|
||||
for (Twine::Id c : new_nodes[i].children())
|
||||
new_refcount[c]++;
|
||||
} else if (new_nodes[i].is_suffix()) {
|
||||
new_refcount[new_nodes[i].suffix().parent]++;
|
||||
}
|
||||
}
|
||||
|
||||
nodes_ = std::move(new_nodes);
|
||||
refcount_ = std::move(new_refcount);
|
||||
free_list_.clear();
|
||||
leaf_index_ = std::move(new_leaf_index);
|
||||
concat_index_ = std::move(new_concat_index);
|
||||
suffix_index_ = std::move(new_suffix_index);
|
||||
return remap;
|
||||
}
|
||||
|
||||
Twine::Id TwinePool::copy_from(const TwinePool &src, Twine::Id src_id)
|
||||
{
|
||||
if (src_id == Twine::Null)
|
||||
return Twine::Null;
|
||||
log_assert(src_id < src.nodes_.size() && !src.nodes_[src_id].is_dead());
|
||||
const Twine &n = src.nodes_[src_id];
|
||||
if (n.is_leaf())
|
||||
return intern(n.leaf());
|
||||
if (n.is_suffix()) {
|
||||
Twine::Id new_parent = copy_from(src, n.suffix().parent);
|
||||
Twine::Id result = intern_suffix(new_parent, n.suffix().tail);
|
||||
// intern_suffix retained the parent internally; the caller-side
|
||||
// +1 ref from copy_from(parent) is surplus.
|
||||
release(new_parent);
|
||||
return result;
|
||||
}
|
||||
std::vector<Twine::Id> children;
|
||||
children.reserve(n.children().size());
|
||||
for (Twine::Id c : n.children())
|
||||
children.push_back(copy_from(src, c));
|
||||
Twine::Id result = concat(std::span<const Twine::Id>{children});
|
||||
// concat retained each child internally; the caller-side +1 refs from
|
||||
// copy_from(child) are surplus.
|
||||
for (Twine::Id c : children)
|
||||
release(c);
|
||||
return result;
|
||||
}
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
246
kernel/twine.h
Normal file
246
kernel/twine.h
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
#ifndef YOSYS_TWINE_H
|
||||
#define YOSYS_TWINE_H
|
||||
|
||||
#include "kernel/yosys_common.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
// A Twine is an interned, possibly composite source-location string. Leaves
|
||||
// are flat path:line.col substrings (the existing src-attribute literal). A
|
||||
// Concat node holds an ordered sequence of child twines, so merging the src
|
||||
// of N cells is O(N) lookups plus one concat-table probe — independent of
|
||||
// the total path-string length the materialized result would have.
|
||||
//
|
||||
// Twines are valid only relative to the TwinePool that minted them. The pool
|
||||
// lives on RTLIL::Design (design->src_twines).
|
||||
struct Twine
|
||||
{
|
||||
using Id = uint32_t;
|
||||
static constexpr Id Null = std::numeric_limits<Id>::max();
|
||||
|
||||
// Suffix shares a `parent` prefix with other suffixes and contributes
|
||||
// its own `tail` string. The materialized leaf string is
|
||||
// flat_string(parent) + tail, i.e. suffixes form trees whose leaves
|
||||
// (string variant) are the roots — like a reverse-trie of common
|
||||
// prefixes. The parent is itself flat (Leaf or Suffix), never a
|
||||
// Concat.
|
||||
struct Suffix {
|
||||
Id parent;
|
||||
std::string tail;
|
||||
};
|
||||
|
||||
// Leaf holds the literal path:line.col string. Suffix holds a parent
|
||||
// id + own tail (see above). Concat holds the ordered children.
|
||||
// Concats are kept flat by TwinePool::concat — children are always
|
||||
// flat (Leaf or Suffix), never other Concats. monostate is the
|
||||
// tombstone marker for freed slots awaiting reuse via the free list.
|
||||
std::variant<std::monostate, std::string, std::vector<Id>, Suffix> data;
|
||||
|
||||
bool is_dead() const { return std::holds_alternative<std::monostate>(data); }
|
||||
bool is_leaf() const { return std::holds_alternative<std::string>(data); }
|
||||
bool is_concat() const { return std::holds_alternative<std::vector<Id>>(data); }
|
||||
bool is_suffix() const { return std::holds_alternative<Suffix>(data); }
|
||||
bool is_flat() const { return is_leaf() || is_suffix(); }
|
||||
const std::string &leaf() const { return std::get<std::string>(data); }
|
||||
const std::vector<Id> &children() const { return std::get<std::vector<Id>>(data); }
|
||||
const Suffix &suffix() const { return std::get<Suffix>(data); }
|
||||
};
|
||||
|
||||
class TwinePool
|
||||
{
|
||||
public:
|
||||
TwinePool() = default;
|
||||
|
||||
// Intern a leaf string. Returns the same Id for byte-equal inputs. The
|
||||
// returned Id carries one reference for the caller — release it when
|
||||
// you are done holding it. Empty input returns Twine::Null.
|
||||
Twine::Id intern(std::string_view leaf);
|
||||
|
||||
// Intern a Suffix node. The resulting flat string is
|
||||
// flat_string(parent) + tail. `parent` must be a flat node (Leaf or
|
||||
// Suffix) — pass Twine::Null with a non-empty `tail` to fall back to
|
||||
// intern(tail). Suffixes with the same (parent, tail) dedup. The
|
||||
// returned Id carries one reference for the caller. Internally the
|
||||
// new suffix retains a reference on `parent`; releasing the suffix
|
||||
// releases that internal parent ref. Empty `tail` returns `parent`
|
||||
// (with +1 ref for the caller).
|
||||
Twine::Id intern_suffix(Twine::Id parent, std::string_view tail);
|
||||
|
||||
// Build a Concat node referencing `parts` in order. Concat children are
|
||||
// always leaves (flat-leaf invariant): any Concat passed in `parts` has
|
||||
// its leaves spliced in instead. Duplicate leaves and Twine::Null are
|
||||
// dropped. If only one distinct leaf remains its Id is returned directly
|
||||
// (no Concat node created). Concats with the same child sequence dedup.
|
||||
// The returned Id carries one reference for the caller. Internally the
|
||||
// concat retains each child it stores; releasing the concat releases
|
||||
// those internal child references.
|
||||
Twine::Id concat(std::span<const Twine::Id> parts);
|
||||
Twine::Id concat(Twine::Id a, Twine::Id b);
|
||||
|
||||
// Refcount control. retain bumps; release decrements and, on reaching
|
||||
// zero, marks the slot dead, drops it from the dedup indexes, releases
|
||||
// any child refs the slot owned, and pushes the slot id onto the free
|
||||
// list for reuse by the next intern/concat. Both no-op on Twine::Null.
|
||||
void retain(Twine::Id id);
|
||||
void release(Twine::Id id);
|
||||
uint32_t refcount(Twine::Id id) const;
|
||||
bool is_alive(Twine::Id id) const;
|
||||
|
||||
// Materialize a Twine to the pipe-separated flat string used by the
|
||||
// existing src attribute convention. Leaves visit in left-to-right DFS
|
||||
// order; duplicate leaves are skipped to match `pool`-style semantics.
|
||||
std::string flatten(Twine::Id id, char sep = '|') const;
|
||||
|
||||
// Materialize a flat node (Leaf or Suffix) to its single string. id
|
||||
// must be a flat node (not a Concat) and not Twine::Null.
|
||||
std::string flat_string(Twine::Id id) const { return flat_string_(id); }
|
||||
|
||||
// Format an interned Id as the canonical src-attribute reference "@N".
|
||||
// Twine::Null formats as the empty string.
|
||||
static std::string format_ref(Twine::Id id);
|
||||
|
||||
// Parse an "@N" reference back to an Id. Returns Twine::Null if `s` is
|
||||
// not exactly "@" followed by one or more decimal digits — so legacy
|
||||
// literal src strings (which always contain ':' separators and have no
|
||||
// reason to start with '@') are passed through unrecognized.
|
||||
static Twine::Id parse_ref(std::string_view s);
|
||||
|
||||
// Lookup. Bounds-checked: out-of-range Id triggers log_assert via op.
|
||||
const Twine &operator[](Twine::Id id) const { return nodes_.at(id); }
|
||||
|
||||
size_t size() const { return nodes_.size(); }
|
||||
size_t leaf_count() const { return leaf_index_.size(); }
|
||||
size_t concat_count() const { return concat_index_.size(); }
|
||||
size_t suffix_count() const { return suffix_index_.size(); }
|
||||
|
||||
// One-shot debug dump of the entire pool to stdout via log(). Each leaf
|
||||
// shows its string; each concat shows its child id list. Intended for
|
||||
// `dump -twines` or ad-hoc tracing — output volume scales with size().
|
||||
void dump(const char *banner = nullptr) const;
|
||||
|
||||
// Rebuild the pool to contain only the nodes named in `live` plus the
|
||||
// transitive children of any live concats. Returns an old-id -> new-id
|
||||
// remap; ids not in the result are dead. Callers must rewrite every
|
||||
// stored "@N" cell src through the returned remap immediately, since
|
||||
// after this call the old ids no longer mean what they used to.
|
||||
dict<Twine::Id, Twine::Id> gc(const pool<Twine::Id> &live);
|
||||
|
||||
// Reconstruct `src->nodes_[src_id]` inside *this. Walks the structure
|
||||
// — intern leaves, concat children — so a concat in `src` becomes a
|
||||
// concat in this pool, not a flat literal of its leaves. Returns the
|
||||
// id in this pool with +1 for the caller (release when done). Both
|
||||
// pools may differ; the source is consulted read-only.
|
||||
Twine::Id copy_from(const TwinePool &src, Twine::Id src_id);
|
||||
|
||||
// Iterate every live (non-tombstoned) node. fn is `void(Twine::Id, const Twine&)`.
|
||||
template <typename Fn>
|
||||
void for_each_live(Fn fn) const {
|
||||
for (size_t i = 0; i < nodes_.size(); i++) {
|
||||
const Twine &n = nodes_[i];
|
||||
if (n.is_dead())
|
||||
continue;
|
||||
fn(static_cast<Twine::Id>(i), n);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Twine> nodes_;
|
||||
std::vector<uint32_t> refcount_;
|
||||
std::vector<Twine::Id> free_list_;
|
||||
dict<std::string, Twine::Id> leaf_index_;
|
||||
dict<std::vector<Twine::Id>, Twine::Id> concat_index_;
|
||||
dict<std::pair<Twine::Id, std::string>, Twine::Id> suffix_index_;
|
||||
|
||||
Twine::Id alloc_slot_(Twine &&node);
|
||||
void destroy_slot_(Twine::Id id);
|
||||
void collect_leaves(Twine::Id id, pool<std::string> &out) const;
|
||||
// Materialize a flat node (Leaf or Suffix) into its full string.
|
||||
std::string flat_string_(Twine::Id id) const;
|
||||
};
|
||||
|
||||
// Owning reference to a Twine slot. Retains on construction (and on copy
|
||||
// of a non-empty ref), releases on destruction. Use this in transient
|
||||
// container types — FfData, Mem helpers — that need to keep a src_id_
|
||||
// alive across destruction of the original AttrObject that minted it,
|
||||
// without having to fall back to a flattened path-string stash.
|
||||
//
|
||||
// Empty (no pool/no id) by default. A non-empty ref always carries a
|
||||
// non-null pool and a live id.
|
||||
class OwnedTwine
|
||||
{
|
||||
public:
|
||||
OwnedTwine() = default;
|
||||
|
||||
// Adopt the +1 reference returned by `intern` / `concat` / `intern_suffix`
|
||||
// / `copy_from`. Use OwnedTwine(pool, id, retain=true) when copying an
|
||||
// id already held elsewhere (e.g. another AttrObject's src_id_).
|
||||
OwnedTwine(TwinePool *pool, Twine::Id id, bool retain = true) : pool_(pool), id_(id) {
|
||||
if (retain && pool_ && id_ != Twine::Null)
|
||||
pool_->retain(id_);
|
||||
}
|
||||
|
||||
OwnedTwine(const OwnedTwine &other) : pool_(other.pool_), id_(other.id_) {
|
||||
if (pool_ && id_ != Twine::Null)
|
||||
pool_->retain(id_);
|
||||
}
|
||||
|
||||
OwnedTwine(OwnedTwine &&other) noexcept : pool_(other.pool_), id_(other.id_) {
|
||||
other.pool_ = nullptr;
|
||||
other.id_ = Twine::Null;
|
||||
}
|
||||
|
||||
OwnedTwine &operator=(const OwnedTwine &other) {
|
||||
if (this == &other)
|
||||
return *this;
|
||||
release_();
|
||||
pool_ = other.pool_;
|
||||
id_ = other.id_;
|
||||
if (pool_ && id_ != Twine::Null)
|
||||
pool_->retain(id_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
OwnedTwine &operator=(OwnedTwine &&other) noexcept {
|
||||
if (this == &other)
|
||||
return *this;
|
||||
release_();
|
||||
pool_ = other.pool_;
|
||||
id_ = other.id_;
|
||||
other.pool_ = nullptr;
|
||||
other.id_ = Twine::Null;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~OwnedTwine() { release_(); }
|
||||
|
||||
void reset() {
|
||||
release_();
|
||||
pool_ = nullptr;
|
||||
id_ = Twine::Null;
|
||||
}
|
||||
|
||||
TwinePool *pool() const { return pool_; }
|
||||
Twine::Id id() const { return id_; }
|
||||
bool empty() const { return id_ == Twine::Null; }
|
||||
|
||||
private:
|
||||
TwinePool *pool_ = nullptr;
|
||||
Twine::Id id_ = Twine::Null;
|
||||
|
||||
void release_() {
|
||||
if (pool_ && id_ != Twine::Null)
|
||||
pool_->release(id_);
|
||||
}
|
||||
};
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
|
@ -76,25 +76,39 @@ std::vector<Cell*> Patch::commit_staged() {
|
|||
}
|
||||
|
||||
namespace {
|
||||
void collect_src(Cell* root, const std::vector<Cell*>& extras,
|
||||
Cell* merge_src_into, pool<std::string>& out)
|
||||
{
|
||||
out.insert(root->get_src_attribute());
|
||||
for (Cell* c : extras)
|
||||
if (c)
|
||||
out.insert(c->get_src_attribute());
|
||||
if (merge_src_into)
|
||||
out.insert(merge_src_into->get_src_attribute());
|
||||
}
|
||||
|
||||
void apply_src(const pool<std::string>& src_pool,
|
||||
void apply_src(Module* mod, Cell* root, const std::vector<Cell*>& extras,
|
||||
const std::vector<Cell*>& targets, Cell* merge_src_into)
|
||||
{
|
||||
std::string src_str = AttrObject::strpool_attribute_to_str(src_pool);
|
||||
// Without a design there's no pool — the cells can't carry typed
|
||||
// src, so silently drop merge-of-src in that path.
|
||||
if (!mod || !mod->design)
|
||||
return;
|
||||
|
||||
TwinePool& pool = mod->design->src_twines;
|
||||
std::vector<Twine::Id> ids;
|
||||
ids.reserve(2 + extras.size());
|
||||
auto push = [&](Cell *c) {
|
||||
if (c && c->src_id() != Twine::Null)
|
||||
ids.push_back(c->src_id());
|
||||
};
|
||||
push(root);
|
||||
for (Cell *c : extras)
|
||||
push(c);
|
||||
push(merge_src_into);
|
||||
if (ids.empty())
|
||||
return;
|
||||
Twine::Id merged = pool.concat(std::span<const Twine::Id>{ids});
|
||||
if (ys_debug()) {
|
||||
log_debug("twine: merge yields %s (pool size %zu)\n",
|
||||
TwinePool::format_ref(merged).c_str(), pool.size());
|
||||
if (ys_debug(2))
|
||||
pool.dump("twine pool state");
|
||||
}
|
||||
for (Cell* c : targets)
|
||||
c->set_src_attribute(src_str);
|
||||
c->set_src_id(&pool, merged);
|
||||
if (merge_src_into)
|
||||
merge_src_into->set_src_attribute(src_str);
|
||||
merge_src_into->set_src_id(&pool, merged);
|
||||
pool.release(merged);
|
||||
}
|
||||
|
||||
// Verifies via newcelltypes that root_cell has exactly one output port
|
||||
|
|
@ -133,11 +147,8 @@ void Patch::patch(Cell* root_cell, IdString old_port, SigSpec new_sig,
|
|||
log_id(root_cell->name), log_id(old_port),
|
||||
log_signal(old_sig), log_signal(new_sig));
|
||||
|
||||
pool<std::string> src_pool;
|
||||
collect_src(root_cell, extras, merge_src_into, src_pool);
|
||||
|
||||
std::vector<Cell*> committed = commit_staged();
|
||||
apply_src(src_pool, committed, merge_src_into);
|
||||
apply_src(mod, root_cell, extras, committed, merge_src_into);
|
||||
|
||||
// Drop root_cell's driver on the output port BEFORE wiring old_sig to
|
||||
// new_sig — otherwise old_sig would briefly have two drivers (root_cell
|
||||
|
|
@ -179,11 +190,8 @@ void Patch::patch_ports(Cell* root_cell,
|
|||
log_error("patch_ports: cell %s of type %s has output port %s not in port_replacements\n",
|
||||
log_id(root_cell->name), log_id(root_cell->type), log_id(port));
|
||||
|
||||
pool<std::string> src_pool;
|
||||
collect_src(root_cell, extras, merge_src_into, src_pool);
|
||||
|
||||
std::vector<Cell*> committed = commit_staged();
|
||||
apply_src(src_pool, committed, merge_src_into);
|
||||
apply_src(mod, root_cell, extras, committed, merge_src_into);
|
||||
|
||||
// Drop every port (inputs included) so root_cell becomes a disconnected
|
||||
// shell before we wire old_sigs to new_sigs. Doing this first ensures
|
||||
|
|
@ -208,11 +216,14 @@ void Patch::patch_ports(Cell* root_cell,
|
|||
}
|
||||
|
||||
void Patch::commit_inheriting_src(Cell* src_source) {
|
||||
std::string src = src_source ? src_source->get_src_attribute() : std::string();
|
||||
for (auto& cell : cells_) {
|
||||
cell->set_src_attribute(src);
|
||||
cell->fixup_parameters();
|
||||
commit_cell(std::move(cell));
|
||||
Cell *committed = commit_cell(std::move(cell));
|
||||
// commit_cell attaches the cell to mod, so adopt_src_from can
|
||||
// now resolve the pool via committed->module->design. Direct
|
||||
// id transfer — no flatten/re-intern detour.
|
||||
if (src_source)
|
||||
committed->adopt_src_from(src_source);
|
||||
}
|
||||
for (auto& wire : wires_)
|
||||
commit_wire(std::move(wire));
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ OBJS += passes/cmds/tee.o
|
|||
OBJS += passes/cmds/write_file.o
|
||||
OBJS += passes/cmds/connwrappers.o
|
||||
OBJS += passes/cmds/trace.o
|
||||
OBJS += passes/cmds/dump_twines.o
|
||||
OBJS += passes/cmds/plugin.o
|
||||
OBJS += passes/cmds/check.o
|
||||
OBJS += passes/cmds/edgetypes.o
|
||||
|
|
|
|||
|
|
@ -375,6 +375,8 @@ struct ChformalPass : public Pass {
|
|||
if (cell->type == ID($check)) {
|
||||
Cell *cover = module->addCell(NEW_ID_SUFFIX("coverenable"), ID($check));
|
||||
cover->attributes = cell->attributes;
|
||||
if (cell->src_id() != Twine::Null && module->design)
|
||||
cover->set_src_id(&module->design->src_twines, cell->src_id());
|
||||
cover->parameters = cell->parameters;
|
||||
cover->setParam(ID(FLAVOR), Const("cover"));
|
||||
|
||||
|
|
@ -420,6 +422,8 @@ struct ChformalPass : public Pass {
|
|||
Cell *plain_cell = module->addCell(NEW_ID, formal_flavor(cell));
|
||||
|
||||
plain_cell->attributes = cell->attributes;
|
||||
if (cell->src_id() != Twine::Null && module->design)
|
||||
plain_cell->set_src_id(&module->design->src_twines, cell->src_id());
|
||||
|
||||
SigBit sig_a = cell->getPort(ID::A);
|
||||
SigBit sig_en = cell->getPort(ID::EN);
|
||||
|
|
|
|||
|
|
@ -338,11 +338,12 @@ struct DesignPass : public Pass {
|
|||
{
|
||||
RTLIL::Design *design_copy = new RTLIL::Design;
|
||||
|
||||
for (auto mod : design->modules()) {
|
||||
// Triggers signorm flush if needed (hacky)
|
||||
(void)mod->connections();
|
||||
design_copy->add(mod->clone());
|
||||
}
|
||||
// Force signorm to flush any pending connection writes back
|
||||
// to the modules' connections_ vectors before we read them.
|
||||
for (auto &it : design->modules_)
|
||||
(void)it.second->connections();
|
||||
|
||||
design->clone_into(design_copy);
|
||||
|
||||
design_copy->selection_stack = design->selection_stack;
|
||||
design_copy->selection_vars = design->selection_vars;
|
||||
|
|
@ -383,8 +384,7 @@ struct DesignPass : public Pass {
|
|||
RTLIL::Design *saved_design = pop_mode ? pushed_designs.back() : saved_designs.at(load_name);
|
||||
|
||||
design->flagSigNormalized = saved_design->flagSigNormalized;
|
||||
for (auto mod : saved_design->modules())
|
||||
design->add(mod->clone());
|
||||
saved_design->clone_into(design);
|
||||
|
||||
design->selection_stack = saved_design->selection_stack;
|
||||
design->selection_vars = saved_design->selection_vars;
|
||||
|
|
|
|||
108
passes/cmds/dump_twines.cc
Normal file
108
passes/cmds/dump_twines.cc
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Inspect the design-level twine pool that backs src-attribute interning.
|
||||
*/
|
||||
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/rtlil.h"
|
||||
#include "kernel/twine.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct DumpTwinesPass : public Pass {
|
||||
DumpTwinesPass() : Pass("dump_twines", "dump the design-level src twine pool") { }
|
||||
|
||||
void help() override
|
||||
{
|
||||
log("\n");
|
||||
log(" dump_twines [-flat]\n");
|
||||
log("\n");
|
||||
log("Print every node in design->src_twines. Leaves show the literal\n");
|
||||
log("path:line.col string, concats show their child id list. With\n");
|
||||
log("-flat each concat is additionally rendered as the pipe-joined\n");
|
||||
log("flat string a backend would emit.\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
bool flat = false;
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
if (args[argidx] == "-flat") {
|
||||
flat = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
const TwinePool &pool = design->src_twines;
|
||||
log("twine pool: %zu nodes (%zu leaves, %zu suffixes, %zu concats)\n",
|
||||
pool.size(), pool.leaf_count(), pool.suffix_count(), pool.concat_count());
|
||||
pool.for_each_live([&](Twine::Id id, const Twine &n) {
|
||||
if (n.is_leaf()) {
|
||||
log(" @%u leaf rc=%u %s\n", id, pool.refcount(id), n.leaf().c_str());
|
||||
} else if (n.is_suffix()) {
|
||||
if (flat) {
|
||||
log(" @%u suffix rc=%u @%u + %s -> %s\n", id, pool.refcount(id),
|
||||
n.suffix().parent, n.suffix().tail.c_str(),
|
||||
pool.flat_string(id).c_str());
|
||||
} else {
|
||||
log(" @%u suffix rc=%u @%u + %s\n", id, pool.refcount(id),
|
||||
n.suffix().parent, n.suffix().tail.c_str());
|
||||
}
|
||||
} else {
|
||||
std::string children;
|
||||
for (Twine::Id c : n.children()) {
|
||||
if (!children.empty())
|
||||
children += ", ";
|
||||
children += "@" + std::to_string(c);
|
||||
}
|
||||
if (flat) {
|
||||
log(" @%u concat rc=%u [%s] -> %s\n", id, pool.refcount(id),
|
||||
children.c_str(), pool.flatten(id).c_str());
|
||||
} else {
|
||||
log(" @%u concat rc=%u [%s]\n", id, pool.refcount(id),
|
||||
children.c_str());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} DumpTwinesPass;
|
||||
|
||||
struct GcTwinesPass : public Pass {
|
||||
GcTwinesPass() : Pass("gc_twines", "reap unreferenced entries from the src twine pool") { }
|
||||
|
||||
void help() override
|
||||
{
|
||||
log("\n");
|
||||
log(" gc_twines\n");
|
||||
log("\n");
|
||||
log("Walk the design, collect every \"@N\" referenced by any cell, wire,\n");
|
||||
log("module, memory, or process attribute, and rebuild design->src_twines\n");
|
||||
log("to contain only those entries plus their transitive leaf children.\n");
|
||||
log("Cell src attributes are rewritten in place via the resulting id\n");
|
||||
log("remap, so the design is unchanged at the path:line.col layer.\n");
|
||||
log("\n");
|
||||
log("Useful after long opt_merge / techmap runs that leave intermediate\n");
|
||||
log("concat nodes orphaned: each merge step splices a previous concat's\n");
|
||||
log("leaves into the new node (the flatten invariant), so the prior\n");
|
||||
log("concat becomes unreferenced as soon as the surviving cell's src is\n");
|
||||
log("rewritten.\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
extra_args(args, 1, design);
|
||||
size_t before = design->src_twines.size();
|
||||
size_t freed = design->gc_twines();
|
||||
log("twine gc: %zu nodes -> %zu (%zu freed)\n",
|
||||
before, design->src_twines.size(), freed);
|
||||
}
|
||||
} GcTwinesPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
||||
|
|
@ -70,34 +70,34 @@ private:
|
|||
void add_precise_GLIFT_logic(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
|
||||
//AKA AN2_SH2 or OR2_SH2
|
||||
bool is_and = cell->type.in(ID($_AND_), ID($_NAND_));
|
||||
RTLIL::SigSpec n_port_a = module->LogicNot(cell->name.str() + "_t_1_1", port_a, false, cell->get_src_attribute());
|
||||
RTLIL::SigSpec n_port_b = module->LogicNot(cell->name.str() + "_t_1_2", port_b, false, cell->get_src_attribute());
|
||||
auto subexpr1 = module->And(cell->name.str() + "_t_1_3", is_and? port_a : n_port_a, port_b_taint, false, cell->get_src_attribute());
|
||||
auto subexpr2 = module->And(cell->name.str() + "_t_1_4", is_and? port_b : n_port_b, port_a_taint, false, cell->get_src_attribute());
|
||||
auto subexpr3 = module->And(cell->name.str() + "_t_1_5", port_a_taint, port_b_taint, false, cell->get_src_attribute());
|
||||
auto subexpr4 = module->Or(cell->name.str() + "_t_1_6", subexpr1, subexpr2, false, cell->get_src_attribute());
|
||||
module->addOr(cell->name.str() + "_t_1_7", subexpr4, subexpr3, port_y_taint, false, cell->get_src_attribute());
|
||||
RTLIL::SigSpec n_port_a = module->LogicNot(cell->name.str() + "_t_1_1", port_a, false, cell->src_ref());
|
||||
RTLIL::SigSpec n_port_b = module->LogicNot(cell->name.str() + "_t_1_2", port_b, false, cell->src_ref());
|
||||
auto subexpr1 = module->And(cell->name.str() + "_t_1_3", is_and? port_a : n_port_a, port_b_taint, false, cell->src_ref());
|
||||
auto subexpr2 = module->And(cell->name.str() + "_t_1_4", is_and? port_b : n_port_b, port_a_taint, false, cell->src_ref());
|
||||
auto subexpr3 = module->And(cell->name.str() + "_t_1_5", port_a_taint, port_b_taint, false, cell->src_ref());
|
||||
auto subexpr4 = module->Or(cell->name.str() + "_t_1_6", subexpr1, subexpr2, false, cell->src_ref());
|
||||
module->addOr(cell->name.str() + "_t_1_7", subexpr4, subexpr3, port_y_taint, false, cell->src_ref());
|
||||
}
|
||||
|
||||
void add_imprecise_GLIFT_logic_1(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
|
||||
//AKA AN2_SH3 or OR2_SH3
|
||||
bool is_and = cell->type.in(ID($_AND_), ID($_NAND_));
|
||||
RTLIL::SigSpec n_port_a = module->LogicNot(cell->name.str() + "_t_2_1", port_a, false, cell->get_src_attribute());
|
||||
auto subexpr1 = module->And(cell->name.str() + "_t_2_2", is_and? port_b : n_port_a, is_and? port_a_taint : port_b_taint, false, cell->get_src_attribute());
|
||||
module->addOr(cell->name.str() + "_t_2_3", is_and? port_b_taint : port_a_taint, subexpr1, port_y_taint, false, cell->get_src_attribute());
|
||||
RTLIL::SigSpec n_port_a = module->LogicNot(cell->name.str() + "_t_2_1", port_a, false, cell->src_ref());
|
||||
auto subexpr1 = module->And(cell->name.str() + "_t_2_2", is_and? port_b : n_port_a, is_and? port_a_taint : port_b_taint, false, cell->src_ref());
|
||||
module->addOr(cell->name.str() + "_t_2_3", is_and? port_b_taint : port_a_taint, subexpr1, port_y_taint, false, cell->src_ref());
|
||||
}
|
||||
|
||||
void add_imprecise_GLIFT_logic_2(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
|
||||
//AKA AN2_SH4 or OR2_SH4
|
||||
bool is_and = cell->type.in(ID($_AND_), ID($_NAND_));
|
||||
RTLIL::SigSpec n_port_b = module->LogicNot(cell->name.str() + "_t_3_1", port_b, false, cell->get_src_attribute());
|
||||
auto subexpr1 = module->And(cell->name.str() + "_t_3_2", is_and? port_a : n_port_b, is_and? port_b_taint : port_a_taint, false, cell->get_src_attribute());
|
||||
module->addOr(cell->name.str() + "_t_3_3", is_and? port_a_taint : port_b_taint, subexpr1, port_y_taint, false, cell->get_src_attribute());
|
||||
RTLIL::SigSpec n_port_b = module->LogicNot(cell->name.str() + "_t_3_1", port_b, false, cell->src_ref());
|
||||
auto subexpr1 = module->And(cell->name.str() + "_t_3_2", is_and? port_a : n_port_b, is_and? port_b_taint : port_a_taint, false, cell->src_ref());
|
||||
module->addOr(cell->name.str() + "_t_3_3", is_and? port_a_taint : port_b_taint, subexpr1, port_y_taint, false, cell->src_ref());
|
||||
}
|
||||
|
||||
void add_imprecise_GLIFT_logic_3(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
|
||||
//AKA AN2_SH5 or OR2_SH5 or XR2_SH2
|
||||
module->addOr(cell->name.str() + "_t_4_1", port_a_taint, port_b_taint, port_y_taint, false, cell->get_src_attribute());
|
||||
module->addOr(cell->name.str() + "_t_4_1", port_a_taint, port_b_taint, port_y_taint, false, cell->src_ref());
|
||||
}
|
||||
|
||||
void add_imprecise_GLIFT_logic_4(RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_y_taint) {
|
||||
|
|
@ -118,22 +118,22 @@ private:
|
|||
|
||||
void add_precise_GLIFT_mux(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_s, RTLIL::SigSpec &port_s_taint, RTLIL::SigSpec &port_y_taint) {
|
||||
//S&At | ~S&Bt | ~A&B&St | A&~B&St | At&St | Bt&St
|
||||
RTLIL::SigSpec n_port_a = module->LogicNot(cell->name.str() + "_t_4_1", port_a, false, cell->get_src_attribute());
|
||||
RTLIL::SigSpec n_port_b = module->LogicNot(cell->name.str() + "_t_4_2", port_b, false, cell->get_src_attribute());
|
||||
RTLIL::SigSpec n_port_s = module->LogicNot(cell->name.str() + "_t_4_3", port_s, false, cell->get_src_attribute());
|
||||
auto subexpr1 = module->And(cell->name.str() + "_t_4_4", port_s, port_a_taint, false, cell->get_src_attribute());
|
||||
auto subexpr2 = module->And(cell->name.str() + "_t_4_5", n_port_s, port_b_taint, false, cell->get_src_attribute());
|
||||
auto subexpr3 = module->And(cell->name.str() + "_t_4_6", n_port_a, port_b, false, cell->get_src_attribute());
|
||||
auto subexpr4 = module->And(cell->name.str() + "_t_4_7", subexpr3, port_s_taint, false, cell->get_src_attribute());
|
||||
auto subexpr5 = module->And(cell->name.str() + "_t_4_8", port_a, n_port_b, false, cell->get_src_attribute());
|
||||
auto subexpr6 = module->And(cell->name.str() + "_t_4_9", subexpr5, port_s_taint, false, cell->get_src_attribute());
|
||||
auto subexpr7 = module->And(cell->name.str() + "_t_4_10", port_a_taint, port_s_taint, false, cell->get_src_attribute());
|
||||
auto subexpr8 = module->And(cell->name.str() + "_t_4_11", port_b_taint, port_s_taint, false, cell->get_src_attribute());
|
||||
auto subexpr9 = module->Or(cell->name.str() + "_t_4_12", subexpr1, subexpr2, false, cell->get_src_attribute());
|
||||
auto subexpr10 = module->Or(cell->name.str() + "_t_4_13", subexpr4, subexpr6, false, cell->get_src_attribute());
|
||||
auto subexpr11 = module->Or(cell->name.str() + "_t_4_14", subexpr7, subexpr8, false, cell->get_src_attribute());
|
||||
auto subexpr12 = module->Or(cell->name.str() + "_t_4_15", subexpr9, subexpr10, false, cell->get_src_attribute());
|
||||
module->addOr(cell->name.str() + "_t_4_16", subexpr11, subexpr12, port_y_taint, false, cell->get_src_attribute());
|
||||
RTLIL::SigSpec n_port_a = module->LogicNot(cell->name.str() + "_t_4_1", port_a, false, cell->src_ref());
|
||||
RTLIL::SigSpec n_port_b = module->LogicNot(cell->name.str() + "_t_4_2", port_b, false, cell->src_ref());
|
||||
RTLIL::SigSpec n_port_s = module->LogicNot(cell->name.str() + "_t_4_3", port_s, false, cell->src_ref());
|
||||
auto subexpr1 = module->And(cell->name.str() + "_t_4_4", port_s, port_a_taint, false, cell->src_ref());
|
||||
auto subexpr2 = module->And(cell->name.str() + "_t_4_5", n_port_s, port_b_taint, false, cell->src_ref());
|
||||
auto subexpr3 = module->And(cell->name.str() + "_t_4_6", n_port_a, port_b, false, cell->src_ref());
|
||||
auto subexpr4 = module->And(cell->name.str() + "_t_4_7", subexpr3, port_s_taint, false, cell->src_ref());
|
||||
auto subexpr5 = module->And(cell->name.str() + "_t_4_8", port_a, n_port_b, false, cell->src_ref());
|
||||
auto subexpr6 = module->And(cell->name.str() + "_t_4_9", subexpr5, port_s_taint, false, cell->src_ref());
|
||||
auto subexpr7 = module->And(cell->name.str() + "_t_4_10", port_a_taint, port_s_taint, false, cell->src_ref());
|
||||
auto subexpr8 = module->And(cell->name.str() + "_t_4_11", port_b_taint, port_s_taint, false, cell->src_ref());
|
||||
auto subexpr9 = module->Or(cell->name.str() + "_t_4_12", subexpr1, subexpr2, false, cell->src_ref());
|
||||
auto subexpr10 = module->Or(cell->name.str() + "_t_4_13", subexpr4, subexpr6, false, cell->src_ref());
|
||||
auto subexpr11 = module->Or(cell->name.str() + "_t_4_14", subexpr7, subexpr8, false, cell->src_ref());
|
||||
auto subexpr12 = module->Or(cell->name.str() + "_t_4_15", subexpr9, subexpr10, false, cell->src_ref());
|
||||
module->addOr(cell->name.str() + "_t_4_16", subexpr11, subexpr12, port_y_taint, false, cell->src_ref());
|
||||
}
|
||||
|
||||
RTLIL::SigSpec score_metamux_select(const RTLIL::SigSpec &metamux_select, const RTLIL::IdString celltype) {
|
||||
|
|
@ -144,7 +144,7 @@ private:
|
|||
//In this case, a nonzero hole metamux select value means less logic.
|
||||
//Thus we should invert the ReduceOr over the metamux_select signal.
|
||||
RTLIL::SigSpec pmux_select = module->ReduceOr(metamux_select.as_wire()->name.str() + "_nonzero", metamux_select);
|
||||
return module->Pmux(NEW_ID, RTLIL::Const(1), RTLIL::Const(0), pmux_select, metamux_select.as_wire()->get_src_attribute());
|
||||
return module->Pmux(NEW_ID, RTLIL::Const(1), RTLIL::Const(0), pmux_select, metamux_select.as_wire()->src_ref());
|
||||
} else {
|
||||
auto select_width = metamux_select.as_wire()->width;
|
||||
|
||||
|
|
@ -163,7 +163,7 @@ private:
|
|||
std::vector<RTLIL::SigSpec> next_pmux_y_ports, pmux_y_ports(costs.begin(), costs.begin() + exp2(select_width));
|
||||
for (auto i = 0; pmux_y_ports.size() > 1; ++i) {
|
||||
for (auto j = 0; j+1 < GetSize(pmux_y_ports); j += 2) {
|
||||
next_pmux_y_ports.emplace_back(module->Pmux(stringf("%s_mux_%d_%d", metamux_select.as_wire()->name, i, j), pmux_y_ports[j], pmux_y_ports[j+1], metamux_select[GetSize(metamux_select) - 1 - i], metamux_select.as_wire()->get_src_attribute()));
|
||||
next_pmux_y_ports.emplace_back(module->Pmux(stringf("%s_mux_%d_%d", metamux_select.as_wire()->name, i, j), pmux_y_ports[j], pmux_y_ports[j+1], metamux_select[GetSize(metamux_select) - 1 - i], metamux_select.as_wire()->src_ref()));
|
||||
}
|
||||
if (GetSize(pmux_y_ports) % 2 == 1)
|
||||
next_pmux_y_ports.push_back(pmux_y_ports[GetSize(pmux_y_ports) - 1]);
|
||||
|
|
@ -234,7 +234,7 @@ private:
|
|||
log_assert(exp2(select_width) == num_versions);
|
||||
RTLIL::SigSpec meta_mux_select(module->addWire(cell->name.str() + "_sel", select_width));
|
||||
meta_mux_selects.push_back(make_pair(meta_mux_select, cell->type));
|
||||
module->connect(meta_mux_select, module->Anyconst(cell->name.str() + "_hole", select_width, cell->get_src_attribute()));
|
||||
module->connect(meta_mux_select, module->Anyconst(cell->name.str() + "_hole", select_width, cell->src_ref()));
|
||||
|
||||
std::vector<RTLIL::SigSpec> next_meta_mux_y_ports, meta_mux_y_ports(taint_version);
|
||||
for (auto i = 0; meta_mux_y_ports.size() > 1; ++i) {
|
||||
|
|
@ -289,7 +289,7 @@ private:
|
|||
|
||||
RTLIL::SigSpec meta_mux_select(module->addWire(cell->name.str() + "_sel", select_width));
|
||||
meta_mux_selects.push_back(make_pair(meta_mux_select, cell->type));
|
||||
module->connect(meta_mux_select, module->Anyconst(cell->name.str() + "_hole", select_width, cell->get_src_attribute()));
|
||||
module->connect(meta_mux_select, module->Anyconst(cell->name.str() + "_hole", select_width, cell->src_ref()));
|
||||
|
||||
std::vector<RTLIL::SigSpec> next_meta_mux_y_ports, meta_mux_y_ports(taint_version);
|
||||
for (auto i = 0; meta_mux_y_ports.size() > 1; ++i) {
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ struct CoveragePass : public Pass {
|
|||
log_debug("Module %s:\n", module);
|
||||
for (auto wire: module->wires()) {
|
||||
log_debug("%s\t%s\t%s\n", module->selected(wire) ? "*" : " ", wire->get_src_attribute(), wire->name.unescape());
|
||||
for (auto src: wire->get_strpool_attribute(ID::src)) {
|
||||
for (auto src: design->src_leaves(wire)) {
|
||||
auto filename = extract_src_filename(src);
|
||||
if (filename.empty()) continue;
|
||||
auto [begin, end] = extract_src_lines(src);
|
||||
|
|
@ -110,7 +110,7 @@ struct CoveragePass : public Pass {
|
|||
}
|
||||
for (auto cell: module->cells()) {
|
||||
log_debug("%s\t%s\t%s\n", module->selected(cell) ? "*" : " ", cell->get_src_attribute(), cell->name.unescape());
|
||||
for (auto src: cell->get_strpool_attribute(ID::src)) {
|
||||
for (auto src: design->src_leaves(cell)) {
|
||||
auto filename = extract_src_filename(src);
|
||||
if (filename.empty()) continue;
|
||||
auto [begin, end] = extract_src_lines(src);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,14 @@ struct PrintAttrsPass : public Pass {
|
|||
log_assert(x.flags & RTLIL::CONST_FLAG_STRING || x.flags == RTLIL::CONST_FLAG_NONE); //intended to fail
|
||||
}
|
||||
|
||||
static void log_src(const Yosys::TwinePool *pool, const RTLIL::AttrObject *obj, const unsigned int indent) {
|
||||
// Emit src outside the attributes loop — it lives on the typed
|
||||
// src_id_ field, not in obj->attributes.
|
||||
if (obj->src_id() != Twine::Null && pool)
|
||||
log("%s(* src=\"%s\" *)\n", get_indent_str(indent),
|
||||
obj->get_src_attribute(pool).c_str());
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
size_t argidx = 1;
|
||||
|
|
@ -65,6 +73,7 @@ struct PrintAttrsPass : public Pass {
|
|||
if (design->selected_whole_module(mod)) {
|
||||
log("%s%s\n", get_indent_str(indent), mod->name.unescape());
|
||||
indent += 2;
|
||||
log_src(design ? &design->src_twines : nullptr, mod, indent);
|
||||
for (auto &it : mod->attributes)
|
||||
log_const(it.first, it.second, indent);
|
||||
}
|
||||
|
|
@ -72,6 +81,7 @@ struct PrintAttrsPass : public Pass {
|
|||
for (auto cell : mod->selected_cells()) {
|
||||
log("%s%s\n", get_indent_str(indent), cell->name.unescape());
|
||||
indent += 2;
|
||||
log_src(design ? &design->src_twines : nullptr, cell, indent);
|
||||
for (auto &it : cell->attributes)
|
||||
log_const(it.first, it.second, indent);
|
||||
indent -= 2;
|
||||
|
|
@ -80,6 +90,7 @@ struct PrintAttrsPass : public Pass {
|
|||
for (auto wire : mod->selected_wires()) {
|
||||
log("%s%s\n", get_indent_str(indent), wire->name.unescape());
|
||||
indent += 2;
|
||||
log_src(design ? &design->src_twines : nullptr, wire, indent);
|
||||
for (auto &it : wire->attributes)
|
||||
log_const(it.first, it.second, indent);
|
||||
indent -= 2;
|
||||
|
|
|
|||
|
|
@ -138,6 +138,27 @@ static bool match_attr(const dict<RTLIL::IdString, RTLIL::Const> &attributes, co
|
|||
return match_attr(attributes, match_expr, std::string(), 0);
|
||||
}
|
||||
|
||||
// AttrObject-aware overload: routes src queries to the typed src_id_ field.
|
||||
// `a:src` and `a:src=path:lo-col` are popular legacy selectors; preserve
|
||||
// them after the migration of src out of the attribute dict by synthesizing
|
||||
// a one-element dict view containing the flattened ID::src and feeding it
|
||||
// through the normal match_attr path. Other ID::src-shaped patterns like
|
||||
// wildcards still flow through the (empty) dict and won't match src — those
|
||||
// uses were rare and the dict-path migration is a separate concern.
|
||||
static bool match_attr(const Yosys::TwinePool *pool, const RTLIL::AttrObject *obj, const std::string &match_expr)
|
||||
{
|
||||
if (obj->src_id() != Twine::Null && pool) {
|
||||
size_t pos = match_expr.find_first_of("<!=>");
|
||||
std::string name_part = (pos == std::string::npos) ? match_expr : match_expr.substr(0, pos);
|
||||
if (name_part == "src" || name_part == "\\src") {
|
||||
dict<RTLIL::IdString, RTLIL::Const> synthesized;
|
||||
synthesized[RTLIL::ID::src] = RTLIL::Const(obj->get_src_attribute(pool));
|
||||
return match_attr(synthesized, match_expr);
|
||||
}
|
||||
}
|
||||
return match_attr(obj->attributes, match_expr);
|
||||
}
|
||||
|
||||
static void select_all(RTLIL::Design *design, RTLIL::Selection &lhs)
|
||||
{
|
||||
if (!lhs.selects_all())
|
||||
|
|
@ -950,17 +971,18 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp
|
|||
sel.selected_members[mod->name].insert(it.first);
|
||||
} else
|
||||
if (arg_memb.compare(0, 2, "a:") == 0) {
|
||||
Yosys::TwinePool *pool = design ? &design->src_twines : nullptr;
|
||||
for (auto wire : mod->wires())
|
||||
if (match_attr(wire->attributes, arg_memb.substr(2)))
|
||||
if (match_attr(pool, wire, arg_memb.substr(2)))
|
||||
sel.selected_members[mod->name].insert(wire->name);
|
||||
for (auto &it : mod->memories)
|
||||
if (match_attr(it.second->attributes, arg_memb.substr(2)))
|
||||
if (match_attr(pool, it.second, arg_memb.substr(2)))
|
||||
sel.selected_members[mod->name].insert(it.first);
|
||||
for (auto cell : mod->cells())
|
||||
if (match_attr(cell->attributes, arg_memb.substr(2)))
|
||||
if (match_attr(pool, cell, arg_memb.substr(2)))
|
||||
sel.selected_members[mod->name].insert(cell->name);
|
||||
for (auto &it : mod->processes)
|
||||
if (match_attr(it.second->attributes, arg_memb.substr(2)))
|
||||
if (match_attr(pool, it.second, arg_memb.substr(2)))
|
||||
sel.selected_members[mod->name].insert(it.first);
|
||||
} else
|
||||
if (arg_memb.compare(0, 2, "r:") == 0) {
|
||||
|
|
|
|||
|
|
@ -436,8 +436,8 @@ struct ShowWorker
|
|||
const bool is_borderless = (shape == "plaintext") || (shape == "plain") || (shape == "none");
|
||||
if (wire->name.isPublic()) {
|
||||
std::string src_href;
|
||||
if (href && wire->attributes.count(ID::src) > 0)
|
||||
src_href = stringf(", href=\"%s\" ", escape(wire->attributes.at(ID::src).decode_string()));
|
||||
if (href && wire->has_attribute(ID::src) > 0)
|
||||
src_href = stringf(", href=\"%s\" ", escape(wire->get_src_attribute()));
|
||||
fprintf(f, "n%d [ shape=%s,%s label=\"%s\", %s%s];\n",
|
||||
id2num(wire->name), shape.c_str(), is_borderless? " margin=0, width=0" : "", findLabel(wire->name.str()),
|
||||
is_borderless
|
||||
|
|
@ -506,8 +506,8 @@ struct ShowWorker
|
|||
}
|
||||
|
||||
std::string src_href;
|
||||
if (href && cell->attributes.count(ID::src) > 0) {
|
||||
src_href = stringf("%shref=\"%s\" ", (findColor(cell->name).empty() ? "" :" , "), escape(cell->attributes.at(ID::src).decode_string()));
|
||||
if (href && cell->has_attribute(ID::src) > 0) {
|
||||
src_href = stringf("%shref=\"%s\" ", (findColor(cell->name).empty() ? "" :" , "), escape(cell->get_src_attribute()));
|
||||
}
|
||||
#ifdef CLUSTER_CELLS_AND_PORTBOXES
|
||||
if (!code.empty())
|
||||
|
|
@ -550,8 +550,8 @@ struct ShowWorker
|
|||
}
|
||||
|
||||
std::string proc_src = proc->name.unescape();
|
||||
if (proc->attributes.count(ID::src) > 0)
|
||||
proc_src = proc->attributes.at(ID::src).decode_string();
|
||||
if (proc->has_attribute(ID::src) > 0)
|
||||
proc_src = proc->get_src_attribute();
|
||||
fprintf(f, "p%d [shape=box, style=rounded, label=\"PROC %s\\n%s\", %s];\n", pidx, findLabel(proc->name.str()), proc_src.c_str(), findColor(proc->name).c_str());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ struct FlattenWorker
|
|||
void map_attributes(RTLIL::Cell *cell, T *object, IdString orig_object_name)
|
||||
{
|
||||
if (!create_scopeinfo && object->has_attribute(ID::src))
|
||||
object->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
|
||||
cell->module->design->merge_src(object, cell);
|
||||
|
||||
// Preserve original names via the hdlname attribute, but only for objects with a fully public name.
|
||||
// If the '-scopename' option is used, also preserve the containing scope of private objects if their scope is fully public.
|
||||
|
|
@ -285,9 +285,16 @@ struct FlattenWorker
|
|||
else
|
||||
scopeinfo->attributes.emplace(stringf("\\cell_%s", attr.first.unescape()), attr.second);
|
||||
}
|
||||
// src lives outside cell->attributes after the typed-src
|
||||
// migration — fold it into the renamed-attribute view by
|
||||
// hand so `a:cell_src` selectors keep working.
|
||||
if (cell->src_id() != Twine::Null)
|
||||
scopeinfo->attributes.emplace(ID(cell_src), RTLIL::Const(cell->get_src_attribute()));
|
||||
|
||||
for (auto const &attr : tpl->attributes)
|
||||
scopeinfo->attributes.emplace(stringf("\\module_%s", attr.first.unescape()), attr.second);
|
||||
if (tpl->src_id() != Twine::Null)
|
||||
scopeinfo->attributes.emplace(ID(module_src), RTLIL::Const(tpl->get_src_attribute()));
|
||||
|
||||
scopeinfo->attributes.emplace(ID(module), tpl->name.unescape());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,12 @@ struct MemoryMapWorker
|
|||
std::set<int> static_ports;
|
||||
std::map<int, RTLIL::SigSpec> static_cells_map;
|
||||
|
||||
mem_src = mem.get_src_attribute();
|
||||
// "@N" ref, not a flattened literal — avoids re-interning a
|
||||
// possibly-Concat src as a single pipe-joined leaf on every
|
||||
// new cell. set_src_attribute's parse_ref path retains the
|
||||
// pool slot directly.
|
||||
mem_src = (mem.module && mem.module->design && mem.src_id() != Twine::Null) ?
|
||||
TwinePool::format_ref(mem.src_id()) : std::string();
|
||||
|
||||
SigSpec init_data = mem.get_init_data();
|
||||
|
||||
|
|
|
|||
|
|
@ -82,8 +82,9 @@ struct ExactCellWires {
|
|||
|
||||
int count_nontrivial_wire_attrs(RTLIL::Wire *w)
|
||||
{
|
||||
// w->attributes no longer holds ID::src (typed src field), so it isn't
|
||||
// counted in attributes.size() and we don't subtract for it here.
|
||||
int count = w->attributes.size();
|
||||
count -= w->attributes.count(ID::src);
|
||||
count -= w->attributes.count(ID::hdlname);
|
||||
count -= w->attributes.count(ID::scopename);
|
||||
count -= w->attributes.count(ID::unused_bits);
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ code
|
|||
// used to drive other nodes. If it isn't, it will be trivially removed by
|
||||
// clean
|
||||
SigSpec flopped_en = module->addWire(NEW_ID);
|
||||
module->addDff(NEW_ID, clk, en, flopped_en, true, latch->get_src_attribute());
|
||||
module->addDff(NEW_ID, clk, en, flopped_en, true, latch->src_ref());
|
||||
and_gate->setPort(latched_en_port_name, flopped_en);
|
||||
did_something = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -459,8 +459,8 @@ struct WreduceWorker
|
|||
|
||||
static int count_nontrivial_wire_attrs(RTLIL::Wire *w)
|
||||
{
|
||||
// w->attributes no longer holds ID::src — typed src field, not counted.
|
||||
int count = w->attributes.size();
|
||||
count -= w->attributes.count(ID::src);
|
||||
count -= w->attributes.count(ID::unused_bits);
|
||||
return count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ struct SnippetSwCache
|
|||
void apply_attrs(RTLIL::Cell *cell, const RTLIL::SwitchRule *sw, const RTLIL::CaseRule *cs)
|
||||
{
|
||||
cell->attributes = sw->attributes;
|
||||
cell->add_strpool_attribute(ID::src, cs->get_strpool_attribute(ID::src));
|
||||
cell->module->design->merge_src(cell, cs);
|
||||
}
|
||||
|
||||
RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode)
|
||||
|
|
|
|||
|
|
@ -184,9 +184,9 @@ struct RomWorker
|
|||
|
||||
mem.emit();
|
||||
|
||||
if (sw->has_attribute(ID::src)) {
|
||||
mem.inits[0].cell->attributes[ID::src] = sw->attributes[ID::src];
|
||||
mem.rd_ports[0].cell->attributes[ID::src] = sw->attributes[ID::src];
|
||||
if (sw->src_id() != Twine::Null && module->design) {
|
||||
mem.inits[0].cell->set_src_id(&module->design->src_twines, sw->src_id());
|
||||
mem.rd_ports[0].cell->set_src_id(&module->design->src_twines, sw->src_id());
|
||||
}
|
||||
|
||||
for (auto cs: sw->cases)
|
||||
|
|
|
|||
|
|
@ -176,8 +176,8 @@ struct AssertpmuxWorker
|
|||
|
||||
Cell *assert_cell = module->addAssert(NEW_ID, assert_a, assert_en);
|
||||
|
||||
if (pmux->attributes.count(ID::src) != 0)
|
||||
assert_cell->attributes[ID::src] = pmux->attributes.at(ID::src);
|
||||
if (pmux->src_id() != Twine::Null && module->design)
|
||||
assert_cell->set_src_id(&module->design->src_twines, pmux->src_id());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -107,15 +107,15 @@ struct Async2syncPass : public Pass {
|
|||
Wire *sig_en_q = module->addWire(NEW_ID);
|
||||
Wire *sig_args_q = module->addWire(NEW_ID, GetSize(sig_args));
|
||||
sig_en_q->attributes.emplace(ID::init, State::S0);
|
||||
module->addDff(NEW_ID, sig_trg, sig_en, sig_en_q, trg_polarity, cell->get_src_attribute());
|
||||
module->addDff(NEW_ID, sig_trg, sig_args, sig_args_q, trg_polarity, cell->get_src_attribute());
|
||||
module->addDff(NEW_ID, sig_trg, sig_en, sig_en_q, trg_polarity, cell->src_ref());
|
||||
module->addDff(NEW_ID, sig_trg, sig_args, sig_args_q, trg_polarity, cell->src_ref());
|
||||
cell->setPort(ID::EN, sig_en_q);
|
||||
cell->setPort(ID::ARGS, sig_args_q);
|
||||
if (cell->type == ID($check)) {
|
||||
SigBit sig_a = cell->getPort(ID::A);
|
||||
Wire *sig_a_q = module->addWire(NEW_ID);
|
||||
sig_a_q->attributes.emplace(ID::init, State::S1);
|
||||
module->addDff(NEW_ID, sig_trg, sig_a, sig_a_q, trg_polarity, cell->get_src_attribute());
|
||||
module->addDff(NEW_ID, sig_trg, sig_a, sig_a_q, trg_polarity, cell->src_ref());
|
||||
cell->setPort(ID::A, sig_a_q);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ struct FmcombinePass : public Pass {
|
|||
|
||||
Cell *cell = module->addCell(combined_cell_name, worker.combined_type);
|
||||
cell->attributes = gold_cell->attributes;
|
||||
cell->add_strpool_attribute(ID::src, gate_cell->get_strpool_attribute(ID::src));
|
||||
module->design->merge_src(cell, gate_cell);
|
||||
|
||||
log("Combining cells %s and %s in module %s into new cell %s.\n", gold_cell, gate_cell, module, cell);
|
||||
|
||||
|
|
|
|||
|
|
@ -440,7 +440,7 @@ void mutate_list(Design *design, const mutate_opts_t &opts, const string &filena
|
|||
dict<SigBit, int> bit_user_cnt;
|
||||
|
||||
for (auto wire : module->wires()) {
|
||||
if (wire->name.isPublic() && wire->attributes.count(ID::src))
|
||||
if (wire->name.isPublic() && wire->has_attribute(ID::src))
|
||||
sigmap.add(wire);
|
||||
}
|
||||
|
||||
|
|
@ -490,12 +490,12 @@ void mutate_list(Design *design, const mutate_opts_t &opts, const string &filena
|
|||
entry.port = conn.first;
|
||||
entry.portbit = i;
|
||||
|
||||
for (auto &s : cell->get_strpool_attribute(ID::src))
|
||||
for (auto &s : design->src_leaves(cell))
|
||||
entry.src.insert(s);
|
||||
|
||||
SigBit bit = sigmap(conn.second[i]);
|
||||
if (bit.wire && bit.wire->name.isPublic() && (cell->output(conn.first) || bit_user_cnt[bit] == 1)) {
|
||||
for (auto &s : bit.wire->get_strpool_attribute(ID::src))
|
||||
for (auto &s : design->src_leaves(bit.wire))
|
||||
entry.src.insert(s);
|
||||
entry.wire = bit.wire->name;
|
||||
entry.wirebit = bit.offset;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ void specialize_from_file(RTLIL::Module *module, const std::string &file) {
|
|||
|
||||
for (auto cell : module->cells())
|
||||
if (cell->type == "$anyconst")
|
||||
anyconst_loc_to_cell[cell->get_strpool_attribute(ID::src)] = cell;
|
||||
anyconst_loc_to_cell[module->design->src_leaves(cell)] = cell;
|
||||
|
||||
std::ifstream fin(file.c_str());
|
||||
if (!fin)
|
||||
|
|
@ -132,7 +132,7 @@ void specialize(RTLIL::Module *module, const QbfSolutionType &sol, bool quiet =
|
|||
pool<RTLIL::Cell *> anyconsts_to_remove;
|
||||
for (auto cell : module->cells())
|
||||
if (cell->type == "$anyconst")
|
||||
if (hole_loc_idx_to_sigbit.find(std::make_pair(cell->get_strpool_attribute(ID::src), 0)) != hole_loc_idx_to_sigbit.end())
|
||||
if (hole_loc_idx_to_sigbit.find(std::make_pair(module->design->src_leaves(cell), 0)) != hole_loc_idx_to_sigbit.end())
|
||||
anyconsts_to_remove.insert(cell);
|
||||
for (auto cell : anyconsts_to_remove)
|
||||
module->remove(cell);
|
||||
|
|
@ -166,7 +166,7 @@ void allconstify_inputs(RTLIL::Module *module, const pool<std::string> &input_wi
|
|||
RTLIL::Cell *allconst = module->addCell("$allconst$" + n, "$allconst");
|
||||
allconst->setParam(ID(WIDTH), input->width);
|
||||
allconst->setPort(ID::Y, input);
|
||||
allconst->set_src_attribute(input->get_src_attribute());
|
||||
allconst->adopt_src_from(input);
|
||||
input->port_input = false;
|
||||
log("Replaced input %s with $allconst cell.\n", n);
|
||||
}
|
||||
|
|
@ -190,7 +190,7 @@ void assume_miter_outputs(RTLIL::Module *module, bool assume_neg) {
|
|||
|
||||
if (assume_neg) {
|
||||
for (unsigned int i = 0; i < wires_to_assume.size(); ++i) {
|
||||
RTLIL::SigSpec n_wire = module->LogicNot(wires_to_assume[i]->name.str() + "__n__qbfsat", wires_to_assume[i], false, wires_to_assume[i]->get_src_attribute());
|
||||
RTLIL::SigSpec n_wire = module->LogicNot(wires_to_assume[i]->name.str() + "__n__qbfsat", wires_to_assume[i], false, wires_to_assume[i]->src_ref());
|
||||
wires_to_assume[i] = n_wire.as_wire();
|
||||
}
|
||||
}
|
||||
|
|
@ -200,7 +200,7 @@ void assume_miter_outputs(RTLIL::Module *module, bool assume_neg) {
|
|||
for (auto j = 0; j + 1 < GetSize(wires_to_assume); j += 2) {
|
||||
std::stringstream strstr; strstr << i << "_" << j;
|
||||
RTLIL::Wire *and_wire = module->addWire("\\_qbfsat_and_" + strstr.str(), 1);
|
||||
module->addLogicAnd("$_qbfsat_and_" + strstr.str(), wires_to_assume[j], wires_to_assume[j+1], and_wire, false, wires_to_assume[j]->get_src_attribute());
|
||||
module->addLogicAnd("$_qbfsat_and_" + strstr.str(), wires_to_assume[j], wires_to_assume[j+1], and_wire, false, wires_to_assume[j]->src_ref());
|
||||
buf.push_back(and_wire);
|
||||
}
|
||||
if (wires_to_assume.size() % 2 == 1)
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ struct QbfSolutionType {
|
|||
dict<RTLIL::SigBit, RTLIL::SigBit> anyconst_sigbit_to_wire_sigbit;
|
||||
|
||||
for (auto cell : module->cells()) {
|
||||
pool<std::string> cell_src = cell->get_strpool_attribute(ID::src);
|
||||
pool<std::string> cell_src = module->design->src_leaves(cell);
|
||||
auto pos = hole_to_value.find(cell_src);
|
||||
if (pos != hole_to_value.end() && cell->type.in("$anyconst", "$anyseq")) {
|
||||
RTLIL::SigSpec port_y = cell->getPort(ID::Y);
|
||||
|
|
|
|||
|
|
@ -696,7 +696,7 @@ struct SatHelper
|
|||
std::string module_fname = "unknown";
|
||||
auto apos = module->attributes.find(ID::src);
|
||||
if(apos != module->attributes.end())
|
||||
module_fname = module->attributes[ID::src].decode_string();
|
||||
module_fname = module->get_src_attribute();
|
||||
|
||||
fprintf(f, "$date\n");
|
||||
fprintf(f, " %s\n", stime);
|
||||
|
|
|
|||
|
|
@ -811,10 +811,10 @@ struct SimInstance
|
|||
return did_something;
|
||||
}
|
||||
|
||||
static void log_source(RTLIL::AttrObject *src)
|
||||
void log_source(RTLIL::AttrObject *src)
|
||||
{
|
||||
for (auto src : src->get_strpool_attribute(ID::src))
|
||||
log(" %s\n", src);
|
||||
for (auto leaf : module->design->src_leaves(src))
|
||||
log(" %s\n", leaf);
|
||||
}
|
||||
|
||||
void log_cell_w_hierarchy(std::string opening_verbiage, RTLIL::Cell *cell)
|
||||
|
|
@ -931,8 +931,8 @@ struct SimInstance
|
|||
for (auto cell : formal_database)
|
||||
{
|
||||
string label = cell->name.unescape();
|
||||
if (cell->attributes.count(ID::src))
|
||||
label = cell->attributes.at(ID::src).decode_string();
|
||||
if (cell->has_attribute(ID::src))
|
||||
label = cell->get_src_attribute();
|
||||
|
||||
State a = get_state(cell->getPort(ID::A))[0];
|
||||
State en = get_state(cell->getPort(ID::EN))[0];
|
||||
|
|
@ -2088,7 +2088,7 @@ struct SimWorker : SimShared
|
|||
json.entry("step", assertion.step);
|
||||
json.entry("type", assertion.cell->type.unescape());
|
||||
json.entry("path", assertion.instance->witness_full_path(assertion.cell));
|
||||
auto src = assertion.cell->get_string_attribute(ID::src);
|
||||
auto src = assertion.cell->get_src_attribute();
|
||||
if (!src.empty()) {
|
||||
json.entry("src", src);
|
||||
}
|
||||
|
|
@ -2101,7 +2101,7 @@ struct SimWorker : SimShared
|
|||
json.begin_object();
|
||||
json.entry("step", output.step);
|
||||
json.entry("path", output.instance->witness_full_path(output.cell));
|
||||
auto src = output.cell->get_string_attribute(ID::src);
|
||||
auto src = output.cell->get_src_attribute();
|
||||
if (!src.empty()) {
|
||||
json.entry("src", src);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1551,8 +1551,8 @@ void AbcModuleState::extract(AbcSigMap &assign_map, RTLIL::Design *design, RTLIL
|
|||
for (auto w : mapped_mod->wires()) {
|
||||
RTLIL::Wire *orig_wire = nullptr;
|
||||
RTLIL::Wire *wire = module->addWire(remap_name(w->name, &orig_wire));
|
||||
if (orig_wire != nullptr && orig_wire->attributes.count(ID::src))
|
||||
wire->attributes[ID::src] = orig_wire->attributes[ID::src];
|
||||
if (orig_wire != nullptr && orig_wire->src_id() != Twine::Null && module->design)
|
||||
wire->set_src_id(&module->design->src_twines, orig_wire->src_id());
|
||||
if (markgroups) wire->attributes[ID::abcgroup] = map_autoidx;
|
||||
design->select(module, wire);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ struct AlumaccWorker
|
|||
get_lt(is_signed);
|
||||
get_eq();
|
||||
SigSpec Or = alu_cell->module->Or(NEW_ID, cached_slt, cached_eq);
|
||||
cached_sgt = alu_cell->module->Not(NEW_ID, Or, false, alu_cell->get_src_attribute());
|
||||
cached_sgt = alu_cell->module->Not(NEW_ID, Or, false, alu_cell->src_ref());
|
||||
}
|
||||
|
||||
return cached_sgt;
|
||||
|
|
@ -80,7 +80,7 @@ struct AlumaccWorker
|
|||
get_lt(is_signed);
|
||||
get_eq();
|
||||
SigSpec Or = alu_cell->module->Or(NEW_ID, cached_lt, cached_eq);
|
||||
cached_gt = alu_cell->module->Not(NEW_ID, Or, false, alu_cell->get_src_attribute());
|
||||
cached_gt = alu_cell->module->Not(NEW_ID, Or, false, alu_cell->src_ref());
|
||||
}
|
||||
|
||||
return cached_gt;
|
||||
|
|
@ -89,13 +89,13 @@ struct AlumaccWorker
|
|||
|
||||
RTLIL::SigSpec get_eq() {
|
||||
if (GetSize(cached_eq) == 0)
|
||||
cached_eq = alu_cell->module->ReduceAnd(NEW_ID, alu_cell->getPort(ID::X), false, alu_cell->get_src_attribute());
|
||||
cached_eq = alu_cell->module->ReduceAnd(NEW_ID, alu_cell->getPort(ID::X), false, alu_cell->src_ref());
|
||||
return cached_eq;
|
||||
}
|
||||
|
||||
RTLIL::SigSpec get_ne() {
|
||||
if (GetSize(cached_ne) == 0)
|
||||
cached_ne = alu_cell->module->Not(NEW_ID, get_eq(), false, alu_cell->get_src_attribute());
|
||||
cached_ne = alu_cell->module->Not(NEW_ID, get_eq(), false, alu_cell->src_ref());
|
||||
return cached_ne;
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ struct AlumaccWorker
|
|||
if (GetSize(cached_cf) == 0) {
|
||||
cached_cf = alu_cell->getPort(ID::CO);
|
||||
log_assert(GetSize(cached_cf) >= 1);
|
||||
cached_cf = alu_cell->module->Not(NEW_ID, cached_cf[GetSize(cached_cf)-1], false, alu_cell->get_src_attribute());
|
||||
cached_cf = alu_cell->module->Not(NEW_ID, cached_cf[GetSize(cached_cf)-1], false, alu_cell->src_ref());
|
||||
}
|
||||
return cached_cf;
|
||||
}
|
||||
|
|
@ -385,7 +385,7 @@ struct AlumaccWorker
|
|||
|
||||
log(" creating $macc cell for %s: %s\n", n->cell, cell);
|
||||
|
||||
cell->set_src_attribute(n->cell->get_src_attribute());
|
||||
cell->adopt_src_from(n->cell);
|
||||
|
||||
n->macc.optimize(GetSize(n->y));
|
||||
n->macc.to_cell(cell);
|
||||
|
|
@ -518,7 +518,7 @@ struct AlumaccWorker
|
|||
log(": %s\n", n->alu_cell);
|
||||
|
||||
if (n->cells.size() > 0)
|
||||
n->alu_cell->set_src_attribute(n->cells[0]->get_src_attribute());
|
||||
n->alu_cell->adopt_src_from(n->cells[0]);
|
||||
|
||||
n->alu_cell->setPort(ID::A, n->a);
|
||||
n->alu_cell->setPort(ID::B, n->b);
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ struct BmuxmapPass : public Pass {
|
|||
module->addEq(NEW_ID, sel, SigSpec(val, GetSize(sel)), new_s[val]);
|
||||
}
|
||||
RTLIL::Cell *pmux = module->addPmux(NEW_ID, new_a, data, new_s, new_data);
|
||||
pmux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
|
||||
module->design->merge_src(pmux, cell);
|
||||
data = new_data;
|
||||
}
|
||||
else
|
||||
|
|
@ -88,7 +88,7 @@ struct BmuxmapPass : public Pass {
|
|||
data.extract(i*2+width, width),
|
||||
sel[idx],
|
||||
new_data.extract(i, width));
|
||||
mux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
|
||||
module->design->merge_src(mux, cell);
|
||||
}
|
||||
data = new_data;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,17 +58,17 @@ struct DemuxmapPass : public Pass {
|
|||
for (int i = 0; i < 1 << GetSize(sel); i++) {
|
||||
if (width == 1 && data == State::S1) {
|
||||
RTLIL::Cell *eq_cell = module->addEq(NEW_ID, sel, Const(i, GetSize(sel)), out[i]);
|
||||
eq_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
|
||||
module->design->merge_src(eq_cell, cell);
|
||||
} else {
|
||||
Wire *eq = module->addWire(NEW_ID);
|
||||
RTLIL::Cell *eq_cell = module->addEq(NEW_ID, sel, Const(i, GetSize(sel)), eq);
|
||||
eq_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
|
||||
module->design->merge_src(eq_cell, cell);
|
||||
RTLIL::Cell *mux = module->addMux(NEW_ID,
|
||||
Const(State::S0, width),
|
||||
data,
|
||||
eq,
|
||||
out.extract(i*width, width));
|
||||
mux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
|
||||
module->design->merge_src(mux, cell);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -532,7 +532,7 @@ void counter_worker(
|
|||
RTLIL::Wire* port_wire = port.as_wire();
|
||||
bool force_extract = false;
|
||||
bool never_extract = false;
|
||||
string count_reg_src = port_wire->attributes[ID::src].decode_string().c_str();
|
||||
string count_reg_src = port_wire->get_src_attribute().c_str();
|
||||
if(port_wire->attributes.find(ID(COUNT_EXTRACT)) != port_wire->attributes.end())
|
||||
{
|
||||
pool<string> sa = port_wire->get_strpool_attribute(ID(COUNT_EXTRACT));
|
||||
|
|
|
|||
|
|
@ -1416,7 +1416,7 @@ struct FlowmapWorker
|
|||
for (auto gate_node : lut_gates[node])
|
||||
{
|
||||
auto gate_origin = node_origins[gate_node];
|
||||
lut->add_strpool_attribute(ID::src, gate_origin.cell->get_strpool_attribute(ID::src));
|
||||
module->design->merge_src(lut, gate_origin.cell);
|
||||
packed_count++;
|
||||
}
|
||||
lut_count++;
|
||||
|
|
|
|||
|
|
@ -27,12 +27,9 @@
|
|||
USING_YOSYS_NAMESPACE
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
static void transfer_attr (Cell* to, const Cell* from, IdString attr) {
|
||||
if (from->has_attribute(attr))
|
||||
to->attributes[attr] = from->attributes.at(attr);
|
||||
}
|
||||
static void transfer_src (Cell* to, const Cell* from) {
|
||||
transfer_attr(to, from, ID::src);
|
||||
if (from->src_id() != Twine::Null && to->module && to->module->design)
|
||||
to->set_src_id(&to->module->design->src_twines, from->src_id());
|
||||
}
|
||||
|
||||
void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||
|
|
|
|||
|
|
@ -157,7 +157,11 @@ struct TechmapWorker
|
|||
}
|
||||
|
||||
std::string orig_cell_name;
|
||||
pool<string> extra_src_attrs = cell->get_strpool_attribute(ID::src);
|
||||
// Cache the source cell's src attribute (a "@N" ref or a legacy
|
||||
// literal). Each technology-mapped object inherits this via
|
||||
// design->merge_src, which routes through the twine pool so
|
||||
// successive merges share substructure.
|
||||
const RTLIL::Cell *src_cell = cell;
|
||||
|
||||
orig_cell_name = cell->name.str();
|
||||
for (auto tpl_cell : tpl->cells())
|
||||
|
|
@ -172,8 +176,8 @@ struct TechmapWorker
|
|||
IdString m_name = it.first;
|
||||
apply_prefix(cell->name, m_name);
|
||||
RTLIL::Memory *m = module->addMemory(m_name, it.second);
|
||||
if (m->attributes.count(ID::src))
|
||||
m->add_strpool_attribute(ID::src, extra_src_attrs);
|
||||
if (m->has_attribute(ID::src))
|
||||
design->merge_src(m, src_cell);
|
||||
memory_renames[it.first] = m->name;
|
||||
design->select(module, m);
|
||||
}
|
||||
|
|
@ -217,8 +221,8 @@ struct TechmapWorker
|
|||
w->attributes.erase(ID::techmap_autopurge);
|
||||
if (tpl_w->get_bool_attribute(ID::_techmap_special_))
|
||||
w->attributes.clear();
|
||||
if (w->attributes.count(ID::src))
|
||||
w->add_strpool_attribute(ID::src, extra_src_attrs);
|
||||
if (w->has_attribute(ID::src))
|
||||
design->merge_src(w, src_cell);
|
||||
}
|
||||
design->select(module, w);
|
||||
|
||||
|
|
@ -377,8 +381,8 @@ struct TechmapWorker
|
|||
c->setParam(ID::MEMID, Const(memid.c_str()));
|
||||
}
|
||||
|
||||
if (c->attributes.count(ID::src))
|
||||
c->add_strpool_attribute(ID::src, extra_src_attrs);
|
||||
if (c->has_attribute(ID::src))
|
||||
design->merge_src(c, src_cell);
|
||||
|
||||
if (techmap_replace_cell) {
|
||||
for (auto attr : cell->attributes)
|
||||
|
|
@ -514,8 +518,9 @@ struct TechmapWorker
|
|||
{
|
||||
extmapper_module = extmapper_design->addModule(m_name);
|
||||
RTLIL::Cell *extmapper_cell = extmapper_module->addCell(cell->type, cell);
|
||||
|
||||
extmapper_cell->set_src_attribute(cell->get_src_attribute());
|
||||
// addCell(name, cell) already migrated src across
|
||||
// designs via copy_src_into — no need for an
|
||||
// explicit set_src_attribute round-trip here.
|
||||
|
||||
int port_counter = 1;
|
||||
for (auto &c : extmapper_cell->connections_) {
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ struct TribufWorker {
|
|||
std::string name = stringf("$tribuf_conflict$%s", cell->name.unescape());
|
||||
auto assert_cell = module->addAssert(name, module->Not(NEW_ID, conflict), SigSpec(true));
|
||||
|
||||
assert_cell->set_src_attribute(cell->get_src_attribute());
|
||||
assert_cell->adopt_src_from(cell);
|
||||
assert_cell->set_bool_attribute(ID::keep);
|
||||
|
||||
module->design->scratchpad_set_bool("tribuf.added_something", true);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,21 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm)
|
|||
cell->attributes[stringf("\\SB_CARRY.%s", a.first)] = a.second;
|
||||
for (const auto &a : st.lut->attributes)
|
||||
cell->attributes[stringf("\\SB_LUT4.%s", a.first)] = a.second;
|
||||
// src now lives in src_id_, not the attributes dict — propagate it
|
||||
// via prefixed flat-literal attributes so the unwrap pass can restore.
|
||||
if (st.carry->src_id() != Twine::Null)
|
||||
cell->attributes[IdString("\\SB_CARRY.\\src")] = Const(st.carry->get_src_attribute());
|
||||
if (st.lut->src_id() != Twine::Null)
|
||||
cell->attributes[IdString("\\SB_LUT4.\\src")] = Const(st.lut->get_src_attribute());
|
||||
// Propagate one of the cell-level srcs to the wrapper too so backends
|
||||
// emitting `attribute \src` see a usable value on the wrapper.
|
||||
if (cell->module && cell->module->design) {
|
||||
TwinePool *pool = &cell->module->design->src_twines;
|
||||
if (st.carry->src_id() != Twine::Null)
|
||||
cell->set_src_id(pool, st.carry->src_id());
|
||||
else if (st.lut->src_id() != Twine::Null)
|
||||
cell->set_src_id(pool, st.lut->src_id());
|
||||
}
|
||||
cell->attributes[IdString{"\\SB_LUT4.name"}] = Const(st.lut->name.str());
|
||||
if (st.carry->get_bool_attribute(ID::keep) || st.lut->get_bool_attribute(ID::keep))
|
||||
cell->attributes[ID::keep] = true;
|
||||
|
|
@ -134,23 +149,30 @@ struct Ice40WrapCarryPass : public Pass {
|
|||
lut->setPort(ID::A, { I3, cell->getPort(ID::B), cell->getPort(ID::A), cell->getPort(ID(I0)) });
|
||||
lut->setPort(ID::Y, cell->getPort(ID::O));
|
||||
|
||||
Const src;
|
||||
for (const auto &a : cell->attributes)
|
||||
if (a.first.begins_with("\\SB_CARRY.\\"))
|
||||
std::string carry_src, lut_src, fallback_src;
|
||||
if (cell->src_id() != Twine::Null)
|
||||
fallback_src = cell->get_src_attribute();
|
||||
for (const auto &a : cell->attributes) {
|
||||
// Match the prefixed src first so we don't fall through
|
||||
// to the generic SB_CARRY./SB_LUT4. prefix copy.
|
||||
if (a.first == IdString("\\SB_CARRY.\\src")) {
|
||||
carry_src = a.second.decode_string();
|
||||
} else if (a.first == IdString("\\SB_LUT4.\\src")) {
|
||||
lut_src = a.second.decode_string();
|
||||
} else if (a.first.begins_with("\\SB_CARRY.\\")) {
|
||||
carry->attributes[a.first.c_str() + strlen("\\SB_CARRY.")] = a.second;
|
||||
else if (a.first.begins_with("\\SB_LUT4.\\"))
|
||||
} else if (a.first.begins_with("\\SB_LUT4.\\")) {
|
||||
lut->attributes[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second;
|
||||
else if (a.first == ID::src)
|
||||
src = a.second;
|
||||
else if (a.first.in(IdString{"\\SB_LUT4.name"}, ID::keep, ID::module_not_derived, ID::src))
|
||||
} else if (a.first.in(IdString{"\\SB_LUT4.name"}, ID::keep, ID::module_not_derived)) {
|
||||
continue;
|
||||
else
|
||||
} else {
|
||||
log_abort();
|
||||
|
||||
if (!src.empty()) {
|
||||
carry->attributes.insert(std::make_pair(ID::src, src));
|
||||
lut->attributes.insert(std::make_pair(ID::src, src));
|
||||
}
|
||||
}
|
||||
if (carry_src.empty()) carry_src = fallback_src;
|
||||
if (lut_src.empty()) lut_src = fallback_src;
|
||||
if (!carry_src.empty()) carry->set_src_attribute(carry_src);
|
||||
if (!lut_src.empty()) lut->set_src_attribute(lut_src);
|
||||
|
||||
module->remove(cell);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ cd fsm # Constrain all select calls below inside the top module
|
|||
select -assert-count 1 t:CC_BUFG
|
||||
select -assert-count 6 t:CC_DFF
|
||||
select -assert-max 2 t:CC_LUT1
|
||||
select -assert-count 1 t:CC_LUT2
|
||||
select -assert-max 15 t:CC_L2T4
|
||||
select -assert-count 2 t:CC_LUT2
|
||||
select -assert-max 14 t:CC_L2T4
|
||||
select -assert-max 5 t:CC_L2T5
|
||||
select -assert-max 1 t:CC_MX2
|
||||
select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT1 t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 t:CC_MX2 %% t:* %D
|
||||
|
|
|
|||
49
tests/rtlil/no-pipe-leaf.sh
Normal file
49
tests/rtlil/no-pipe-leaf.sh
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
set -euo pipefail
|
||||
|
||||
mkdir -p temp
|
||||
|
||||
# Synthesize a tiny design through paths that previously round-tripped
|
||||
# src through get_src_attribute() → set_src_attribute() and broke the
|
||||
# flat-leaf invariant: opt_merge -share_all produces a Concat src on the
|
||||
# surviving cell, then opt_dff / FfData emit re-emits the cell. Before
|
||||
# the adopt_src_from refactor every pipe-joined flatten was re-interned
|
||||
# as a single pipe-containing Leaf — now those paths transfer the id
|
||||
# verbatim and no Leaf ever contains '|'.
|
||||
cat > temp/pipe.v <<'EOF'
|
||||
module top(input clk, input [7:0] a, b, c, d, output reg [7:0] x, y);
|
||||
always @(posedge clk) begin
|
||||
x <= a + b;
|
||||
y <= c + d;
|
||||
end
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
${YOSYS} -p "read_verilog temp/pipe.v; hierarchy -top top; proc; opt; opt_merge -share_all; alumacc; opt_dff; dump_twines" \
|
||||
> temp/pipe-dump.txt 2>&1
|
||||
|
||||
if grep -E '^\s*@[0-9]+ leaf rc=[0-9]+ ' temp/pipe-dump.txt | grep -q '|'; then
|
||||
echo "FAIL: dump_twines produced a leaf containing '|':" >&2
|
||||
grep -E '^\s*@[0-9]+ leaf rc=[0-9]+ ' temp/pipe-dump.txt | grep '|' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# A second pattern that exercises the memory-mapping code path
|
||||
# (Mem::extract_rdff stash + FfData::emit).
|
||||
cat > temp/mem.v <<'EOF'
|
||||
module mem(input clk, input we, input [3:0] addr, input [7:0] din, output reg [7:0] dout);
|
||||
reg [7:0] m [0:15];
|
||||
always @(posedge clk) begin
|
||||
if (we) m[addr] <= din;
|
||||
dout <= m[addr];
|
||||
end
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
${YOSYS} -p "read_verilog temp/mem.v; hierarchy -top mem; proc; opt; memory_map; opt_dff; dump_twines" \
|
||||
> temp/mem-dump.txt 2>&1
|
||||
|
||||
if grep -E '^\s*@[0-9]+ leaf rc=[0-9]+ ' temp/mem-dump.txt | grep -q '|'; then
|
||||
echo "FAIL: dump_twines (memory_map path) produced a leaf containing '|':" >&2
|
||||
grep -E '^\s*@[0-9]+ leaf rc=[0-9]+ ' temp/mem-dump.txt | grep '|' >&2
|
||||
exit 1
|
||||
fi
|
||||
32
tests/rtlil/roundtrip-suffix.sh
Normal file
32
tests/rtlil/roundtrip-suffix.sh
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
set -euo pipefail
|
||||
|
||||
mkdir -p temp
|
||||
|
||||
# Read a hand-crafted RTLIL file with Suffix twine nodes, write it back,
|
||||
# and verify byte-for-byte roundtrip — exercises the Suffix parser path,
|
||||
# the Suffix backend emitter, and Design::clone_into across design -push
|
||||
# (which must preserve Suffix tree topology verbatim).
|
||||
${YOSYS} -p "read_rtlil suffix-twines.il; write_rtlil temp/suffix-twines-write.il"
|
||||
tail -n +2 temp/suffix-twines-write.il > temp/suffix-twines-write-nogen.il
|
||||
diff suffix-twines.il temp/suffix-twines-write-nogen.il
|
||||
|
||||
${YOSYS} -p "read_rtlil suffix-twines.il; design -push; design -pop; write_rtlil temp/suffix-twines-push.il"
|
||||
tail -n +2 temp/suffix-twines-push.il > temp/suffix-twines-push-nogen.il
|
||||
diff suffix-twines.il temp/suffix-twines-push-nogen.il
|
||||
|
||||
# Multi-level Suffix chain — verifies that Suffix-with-Suffix-parent
|
||||
# survives read/write and a design -push/-pop verbatim cycle.
|
||||
${YOSYS} -p "read_rtlil suffix-chain.il; design -push; design -pop; write_rtlil temp/suffix-chain-push.il"
|
||||
tail -n +2 temp/suffix-chain-push.il > temp/suffix-chain-push-nogen.il
|
||||
diff suffix-chain.il temp/suffix-chain-push-nogen.il
|
||||
|
||||
# Verify that gc preserves the Suffix tree (number of nodes and the
|
||||
# materialized leaf strings on each cell src), even if the rebuilt pool
|
||||
# is renumbered by hash-set iteration order.
|
||||
${YOSYS} -p "read_rtlil suffix-chain.il; gc_twines; write_rtlil -resolve-src temp/suffix-chain-gc-resolved.il"
|
||||
grep '\\src' temp/suffix-chain-gc-resolved.il | sort > temp/suffix-chain-gc-resolved.srcs
|
||||
cat > temp/suffix-chain-expected.srcs <<EOF
|
||||
attribute \\src "/home/emil/repo/foo/bar.v:10.1-10.5"
|
||||
attribute \\src "/home/emil/repo/foo/bar.v:11.1-11.5"
|
||||
EOF
|
||||
diff temp/suffix-chain-expected.srcs temp/suffix-chain-gc-resolved.srcs
|
||||
15
tests/rtlil/suffix-chain.il
Normal file
15
tests/rtlil/suffix-chain.il
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
autoidx 1
|
||||
twines
|
||||
leaf 0 "/home/emil/repo/"
|
||||
suffix 1 0 "foo/"
|
||||
suffix 2 1 "bar.v"
|
||||
suffix 3 2 ":10.1-10.5"
|
||||
suffix 4 2 ":11.1-11.5"
|
||||
end
|
||||
module \chain
|
||||
attribute \src "@3"
|
||||
wire input 1 \a
|
||||
attribute \src "@4"
|
||||
wire output 2 \b
|
||||
connect \b \a
|
||||
end
|
||||
15
tests/rtlil/suffix-twines.il
Normal file
15
tests/rtlil/suffix-twines.il
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
autoidx 1
|
||||
twines
|
||||
leaf 0 "everything.v"
|
||||
suffix 1 0 ":1.1-1.10"
|
||||
suffix 2 0 ":2.5-2.8"
|
||||
concat 3 1 2
|
||||
end
|
||||
attribute \src "@3"
|
||||
module \tiny
|
||||
attribute \src "@1"
|
||||
wire input 1 \a
|
||||
attribute \src "@2"
|
||||
wire output 2 \b
|
||||
connect \b \a
|
||||
end
|
||||
|
|
@ -10,5 +10,5 @@ read_json temp/test_escapes.json
|
|||
write_json temp/test_escapes.json
|
||||
design -reset
|
||||
read_json temp/test_escapes.json
|
||||
write_rtlil temp/test_escapes.json.il
|
||||
write_rtlil -resolve-src temp/test_escapes.json.il
|
||||
! grep -F 'attribute \src "\" / \\ \010 \014 \n \015 \t \025 \033"' temp/test_escapes.json.il
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue