flatten: preserve original object names via hdlname attribute.

This commit is contained in:
whitequark 2020-06-04 10:46:54 +00:00
parent 8d821dbbdb
commit fbb346ea91
5 changed files with 45 additions and 6 deletions

View File

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

View File

@ -339,6 +339,22 @@ pool<string> RTLIL::AttrObject::get_strpool_attribute(RTLIL::IdString id) const
return data;
}
void RTLIL::AttrObject::set_hdlname_attribute(const vector<string> &hierarchy)
{
string attrval;
for (const auto &ident : hierarchy) {
if (!attrval.empty())
attrval += " ";
attrval += ident;
}
set_string_attribute(ID::hdlname, attrval);
}
vector<string> 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)

View File

@ -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<string> &hierarchy);
vector<string> get_hdlname_attribute() const;
};
struct RTLIL::SigChunk

View File

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

View File

@ -47,10 +47,21 @@ IdString map_name(RTLIL::Cell *cell, T *object)
}
template<class T>
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<std::string> 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<RTLIL::Wire*, RTLIL::Wire*> &map, RTLIL::SigSpec &sig, RTLIL::Module *into = nullptr)
@ -81,7 +92,7 @@ struct FlattenWorker
dict<IdString, IdString> 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()));