3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-12 20:18:20 +00:00

Merge pull request #2107 from whitequark/flatten-hdlname

flatten: preserve original object names
This commit is contained in:
whitequark 2020-06-09 06:26:02 +00:00 committed by GitHub
commit 4351194e8c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 54 additions and 11 deletions

View file

@ -309,7 +309,9 @@ Verilog Attributes and non-standard features
that have ports with a width that depends on a parameter. that have ports with a width that depends on a parameter.
- The ``hdlname`` attribute is used by some passes to document the original - 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 - 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 never be removed by the optimizer. This is used for example for cells that

View file

@ -508,7 +508,7 @@ std::string get_hdl_name(T *object)
if (object->has_attribute(ID::hdlname)) if (object->has_attribute(ID::hdlname))
return object->get_string_attribute(ID::hdlname); return object->get_string_attribute(ID::hdlname);
else else
return object->name.str(); return object->name.str().substr(1);
} }
struct CxxrtlWorker { struct CxxrtlWorker {

View file

@ -319,7 +319,7 @@ void RTLIL::AttrObject::set_strpool_attribute(RTLIL::IdString id, const pool<str
attrval += "|"; attrval += "|";
attrval += s; attrval += s;
} }
attributes[id] = RTLIL::Const(attrval); set_string_attribute(id, attrval);
} }
void RTLIL::AttrObject::add_strpool_attribute(RTLIL::IdString id, const pool<string> &data) void RTLIL::AttrObject::add_strpool_attribute(RTLIL::IdString id, const pool<string> &data)
@ -334,11 +334,27 @@ pool<string> RTLIL::AttrObject::get_strpool_attribute(RTLIL::IdString id) const
{ {
pool<string> data; pool<string> data;
if (attributes.count(id) != 0) if (attributes.count(id) != 0)
for (auto s : split_tokens(attributes.at(id).decode_string(), "|")) for (auto s : split_tokens(get_string_attribute(id), "|"))
data.insert(s); data.insert(s);
return data; 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 bool RTLIL::Selection::selected_module(RTLIL::IdString mod_name) const
{ {
if (full_selection) if (full_selection)

View file

@ -682,6 +682,9 @@ struct RTLIL::AttrObject
std::string get_src_attribute() const { std::string get_src_attribute() const {
return get_string_attribute(ID::src); return get_string_attribute(ID::src);
} }
void set_hdlname_attribute(const vector<string> &hierarchy);
vector<string> get_hdlname_attribute() const;
}; };
struct RTLIL::SigChunk struct RTLIL::SigChunk

View file

@ -193,6 +193,13 @@ Violating these rules results in a runtime error.
All RTLIL identifiers are case sensitive. 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} \subsection{RTLIL::Design and RTLIL::Module}
The RTLIL::Design object is basically just a container for RTLIL::Module objects. In addition to The RTLIL::Design object is basically just a container for RTLIL::Module objects. In addition to

View file

@ -32,8 +32,12 @@ IdString concat_name(RTLIL::Cell *cell, IdString object_name)
{ {
if (object_name[0] == '\\') if (object_name[0] == '\\')
return stringf("%s.%s", cell->name.c_str(), object_name.c_str() + 1); return stringf("%s.%s", cell->name.c_str(), object_name.c_str() + 1);
else else {
return stringf("$flatten%s.%s", cell->name.c_str(), object_name.c_str()); std::string object_name_str = object_name.str();
if (object_name_str.substr(0, 8) == "$flatten")
object_name_str.erase(0, 8);
return stringf("$flatten%s.%s", cell->name.c_str(), object_name_str.c_str());
}
} }
template<class T> template<class T>
@ -43,10 +47,21 @@ IdString map_name(RTLIL::Cell *cell, T *object)
} }
template<class T> 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)); 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) void map_sigspec(const dict<RTLIL::Wire*, RTLIL::Wire*> &map, RTLIL::SigSpec &sig, RTLIL::Module *into = nullptr)
@ -77,7 +92,7 @@ struct FlattenWorker
dict<IdString, IdString> memory_map; dict<IdString, IdString> memory_map;
for (auto &tpl_memory_it : tpl->memories) { for (auto &tpl_memory_it : tpl->memories) {
RTLIL::Memory *new_memory = module->addMemory(map_name(cell, tpl_memory_it.second), tpl_memory_it.second); 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; memory_map[tpl_memory_it.first] = new_memory->name;
design->select(module, new_memory); design->select(module, new_memory);
} }
@ -107,14 +122,14 @@ struct FlattenWorker
new_wire->port_id = false; new_wire->port_id = false;
} }
map_attributes(cell, new_wire); map_attributes(cell, new_wire, tpl_wire->name);
wire_map[tpl_wire] = new_wire; wire_map[tpl_wire] = new_wire;
design->select(module, new_wire); design->select(module, new_wire);
} }
for (auto tpl_cell : tpl->cells()) { for (auto tpl_cell : tpl->cells()) {
RTLIL::Cell *new_cell = module->addCell(map_name(cell, tpl_cell), tpl_cell); 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))) { if (new_cell->type.in(ID($memrd), ID($memwr), ID($meminit))) {
IdString memid = new_cell->getParam(ID::MEMID).decode_string(); IdString memid = new_cell->getParam(ID::MEMID).decode_string();
new_cell->setParam(ID::MEMID, Const(memory_map.at(memid).str())); new_cell->setParam(ID::MEMID, Const(memory_map.at(memid).str()));