Suport $scopeinfo in flatten and opt_clean

This commit is contained in:
Jannis Harder 2023-12-19 16:23:38 +01:00
parent f728927307
commit 8902fc94b6
2 changed files with 105 additions and 20 deletions

View File

@ -35,10 +35,12 @@ struct keep_cache_t
{
Design *design;
dict<Module*, bool> cache;
bool purge_mode = false;
void reset(Design *design = nullptr)
void reset(Design *design = nullptr, bool purge_mode = false)
{
this->design = design;
this->purge_mode = purge_mode;
cache.clear();
}
@ -88,6 +90,9 @@ struct keep_cache_t
if (cell->has_keep_attr())
return true;
if (!purge_mode && cell->type == ID($scopeinfo))
return true;
if (cell->module && cell->module->design)
return query(cell->module->design->module(cell->type));
@ -236,6 +241,8 @@ int count_nontrivial_wire_attrs(RTLIL::Wire *w)
{
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);
return count;
}
@ -661,7 +668,7 @@ struct OptCleanPass : public Pass {
}
extra_args(args, argidx, design);
keep_cache.reset(design);
keep_cache.reset(design, purge_mode);
ct_reg.setup_internals_mem();
ct_reg.setup_internals_anyinit();

View File

@ -46,24 +46,6 @@ IdString map_name(RTLIL::Cell *cell, T *object)
return cell->module->uniquify(concat_name(cell, object->name));
}
template<class T>
void map_attributes(RTLIL::Cell *cell, T *object, IdString orig_object_name)
{
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)
{
vector<SigChunk> chunks = sig;
@ -76,6 +58,54 @@ void map_sigspec(const dict<RTLIL::Wire*, RTLIL::Wire*> &map, RTLIL::SigSpec &si
struct FlattenWorker
{
bool ignore_wb = false;
bool create_scopeinfo = true;
bool create_scopename = false;
template<class T>
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));
// 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.
if (cell->name[0] == '\\') {
if (object->has_attribute(ID::hdlname) || orig_object_name[0] == '\\') {
std::string new_hdlname;
if (cell->has_attribute(ID::hdlname)) {
new_hdlname = cell->get_string_attribute(ID(hdlname));
} else {
log_assert(!cell->name.empty());
new_hdlname = cell->name.c_str() + 1;
}
new_hdlname += ' ';
if (object->has_attribute(ID::hdlname)) {
new_hdlname += object->get_string_attribute(ID(hdlname));
} else {
log_assert(!orig_object_name.empty());
new_hdlname += orig_object_name.c_str() + 1;
}
object->set_string_attribute(ID(hdlname), new_hdlname);
} else if (object->has_attribute(ID(scopename))) {
std::string new_scopename;
if (cell->has_attribute(ID::hdlname)) {
new_scopename = cell->get_string_attribute(ID(hdlname));
} else {
log_assert(!cell->name.empty());
new_scopename = cell->name.c_str() + 1;
}
new_scopename += ' ';
new_scopename += object->get_string_attribute(ID(scopename));
object->set_string_attribute(ID(scopename), new_scopename);
} else if (create_scopename) {
log_assert(!cell->name.empty());
object->set_string_attribute(ID(scopename), cell->name.c_str() + 1);
}
}
}
void flatten_cell(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl, SigMap &sigmap, std::vector<RTLIL::Cell*> &new_cells)
{
@ -220,7 +250,33 @@ struct FlattenWorker
sigmap.add(new_conn.first, new_conn.second);
}
RTLIL::Cell *scopeinfo = nullptr;
RTLIL::IdString cell_name = cell->name;
if (create_scopeinfo && cell_name.isPublic())
{
// The $scopeinfo's name will be changed below after removing the flattened cell
scopeinfo = module->addCell(NEW_ID, ID($scopeinfo));
scopeinfo->setParam(ID::TYPE, RTLIL::Const("module"));
for (auto const &attr : cell->attributes)
{
if (attr.first == ID::hdlname)
scopeinfo->attributes.insert(attr);
else
scopeinfo->attributes.emplace(stringf("\\cell_%s", RTLIL::unescape_id(attr.first).c_str()), attr.second);
}
for (auto const &attr : tpl->attributes)
scopeinfo->attributes.emplace(stringf("\\module_%s", RTLIL::unescape_id(attr.first).c_str()), attr.second);
scopeinfo->attributes.emplace(ID(module), RTLIL::unescape_id(tpl->name));
}
module->remove(cell);
if (scopeinfo != nullptr)
module->rename(scopeinfo, cell_name);
}
void flatten_module(RTLIL::Design *design, RTLIL::Module *module, pool<RTLIL::Module*> &used_modules)
@ -275,6 +331,20 @@ struct FlattenPass : public Pass {
log(" -wb\n");
log(" Ignore the 'whitebox' attribute on cell implementations.\n");
log("\n");
log(" -noscopeinfo\n");
log(" Do not create '$scopeinfo' cells that preserve attributes of cells and\n");
log(" modules that were removed during flattening. With this option, the\n");
log(" 'src' attribute of a given cell is merged into all objects replacing\n");
log(" that cell, with multiple distinct 'src' locations separated by '|'.\n");
log(" Without this option these 'src' locations can be found via the\n");
log(" cell_src' and 'module_src' attribute of '$scopeinfo' cells.\n");
log("\n");
log(" -scopename\n");
log(" Create 'scopename' attributes for objects with a private name. This\n");
log(" attribute records the 'hdlname' of the enclosing scope. For objects\n");
log(" with a public name the enclosing scope can be found via their\n");
log(" 'hdlname' attribute.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
@ -289,6 +359,14 @@ struct FlattenPass : public Pass {
worker.ignore_wb = true;
continue;
}
if (args[argidx] == "-noscopeinfo") {
worker.create_scopeinfo = false;
continue;
}
if (args[argidx] == "-scopename") {
worker.create_scopename = true;
continue;
}
break;
}
extra_args(args, argidx, design);