From fbb346ea91a04f2feaf6fa96770fe0cd57020e75 Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 4 Jun 2020 10:46:54 +0000 Subject: flatten: preserve original object names via hdlname attribute. --- README.md | 4 +++- kernel/rtlil.cc | 16 ++++++++++++++++ kernel/rtlil.h | 3 +++ manual/CHAPTER_Overview.tex | 7 +++++++ passes/techmap/flatten.cc | 21 ++++++++++++++++----- 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 770c62459..203a292d1 100644 --- a/README.md +++ b/README.md @@ -309,7 +309,9 @@ Verilog Attributes and non-standard features that have ports with a width that depends on a parameter. - The ``hdlname`` attribute is used by some passes to document the original - (HDL) name of a module when renaming a module. + (HDL) name of a module when renaming a module. It should contain a single + name, or, when describing a hierarchical name in a flattened design, multiple + names separated by a single space character. - The ``keep`` attribute on cells and wires is used to mark objects that should never be removed by the optimizer. This is used for example for cells that diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 335c48456..b876862c8 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -339,6 +339,22 @@ pool RTLIL::AttrObject::get_strpool_attribute(RTLIL::IdString id) const return data; } +void RTLIL::AttrObject::set_hdlname_attribute(const vector &hierarchy) +{ + string attrval; + for (const auto &ident : hierarchy) { + if (!attrval.empty()) + attrval += " "; + attrval += ident; + } + set_string_attribute(ID::hdlname, attrval); +} + +vector RTLIL::AttrObject::get_hdlname_attribute() const +{ + return split_tokens(get_string_attribute(ID::hdlname), " "); +} + bool RTLIL::Selection::selected_module(RTLIL::IdString mod_name) const { if (full_selection) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 86b4e25b6..f751bdce4 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -682,6 +682,9 @@ struct RTLIL::AttrObject std::string get_src_attribute() const { return get_string_attribute(ID::src); } + + void set_hdlname_attribute(const vector &hierarchy); + vector get_hdlname_attribute() const; }; struct RTLIL::SigChunk diff --git a/manual/CHAPTER_Overview.tex b/manual/CHAPTER_Overview.tex index ac0f48e47..83cfa5cc4 100644 --- a/manual/CHAPTER_Overview.tex +++ b/manual/CHAPTER_Overview.tex @@ -193,6 +193,13 @@ Violating these rules results in a runtime error. All RTLIL identifiers are case sensitive. +Some transformations, such as flattening, may have to change identifiers provided by the user +to avoid name collisions. When that happens, attribute ``{\tt hdlname}`` is attached to the object +with the changed identifier. This attribute contains one name (if emitted directly by the frontend, +or is a result of disambiguation) or multiple names separated by spaces (if a result of flattening). +All names specified in the ``{\tt hdlname}`` attribute are public and do not include the leading +``\textbackslash``. + \subsection{RTLIL::Design and RTLIL::Module} The RTLIL::Design object is basically just a container for RTLIL::Module objects. In addition to diff --git a/passes/techmap/flatten.cc b/passes/techmap/flatten.cc index e913b3059..a2794541a 100644 --- a/passes/techmap/flatten.cc +++ b/passes/techmap/flatten.cc @@ -47,10 +47,21 @@ IdString map_name(RTLIL::Cell *cell, T *object) } template -void map_attributes(RTLIL::Cell *cell, T *object) +void map_attributes(RTLIL::Cell *cell, T *object, IdString orig_object_name) { - if (object->attributes.count(ID::src)) + if (object->has_attribute(ID::src)) object->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + + // Preserve original names via the hdlname attribute, but only for objects with a fully public name. + if (cell->name[0] == '\\' && (object->has_attribute(ID::hdlname) || orig_object_name[0] == '\\')) { + std::vector hierarchy; + if (object->has_attribute(ID::hdlname)) + hierarchy = object->get_hdlname_attribute(); + else + hierarchy.push_back(orig_object_name.str().substr(1)); + hierarchy.insert(hierarchy.begin(), cell->name.str().substr(1)); + object->set_hdlname_attribute(hierarchy); + } } void map_sigspec(const dict &map, RTLIL::SigSpec &sig, RTLIL::Module *into = nullptr) @@ -81,7 +92,7 @@ struct FlattenWorker dict memory_map; for (auto &tpl_memory_it : tpl->memories) { RTLIL::Memory *new_memory = module->addMemory(map_name(cell, tpl_memory_it.second), tpl_memory_it.second); - map_attributes(cell, new_memory); + map_attributes(cell, new_memory, tpl_memory_it.second->name); memory_map[tpl_memory_it.first] = new_memory->name; design->select(module, new_memory); } @@ -111,14 +122,14 @@ struct FlattenWorker new_wire->port_id = false; } - map_attributes(cell, new_wire); + map_attributes(cell, new_wire, tpl_wire->name); wire_map[tpl_wire] = new_wire; design->select(module, new_wire); } for (auto tpl_cell : tpl->cells()) { RTLIL::Cell *new_cell = module->addCell(map_name(cell, tpl_cell), tpl_cell); - map_attributes(cell, new_cell); + map_attributes(cell, new_cell, tpl_cell->name); if (new_cell->type.in(ID($memrd), ID($memwr), ID($meminit))) { IdString memid = new_cell->getParam(ID::MEMID).decode_string(); new_cell->setParam(ID::MEMID, Const(memory_map.at(memid).str())); -- cgit v1.2.3