3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-22 23:25:51 +00:00
This commit is contained in:
Emil J. Tywoniak 2026-06-05 12:04:19 +02:00
parent 3d27e83d0f
commit 3424c00cd0
63 changed files with 2635 additions and 503 deletions

View file

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

View file

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

View file

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

View file

@ -130,9 +130,16 @@ struct JsonWriter
}
}
void write_parameters(const dict<IdString, Const> &parameters, bool for_module=false)
void write_parameters(const dict<IdString, Const> &parameters, 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 &param : 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;

View file

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

View file

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

View file

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

View file

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