28
28
USING_YOSYS_NAMESPACE
29
29
PRIVATE_NAMESPACE_BEGIN
30
30
31
- IdString concat_name (RTLIL::Cell *cell, IdString object_name)
31
+ IdString concat_name (RTLIL::Cell *cell, IdString object_name, const std::string &separator = " . " )
32
32
{
33
33
if (object_name[0 ] == ' \\ ' )
34
- return stringf (" %s.%s " , cell->name .c_str (), object_name.c_str () + 1 );
34
+ return stringf (" %s%s%s " , cell->name . c_str (), separator .c_str (), object_name.c_str () + 1 );
35
35
else {
36
36
std::string object_name_str = object_name.str ();
37
37
if (object_name_str.substr (0 , 8 ) == " $flatten" )
38
38
object_name_str.erase (0 , 8 );
39
- return stringf (" $flatten%s.%s " , cell->name .c_str (), object_name_str.c_str ());
39
+ return stringf (" $flatten%s%s%s " , cell->name . c_str (), separator .c_str (), object_name_str.c_str ());
40
40
}
41
41
}
42
42
43
43
template <class T >
44
- IdString map_name (RTLIL::Cell *cell, T *object)
44
+ IdString map_name (RTLIL::Cell *cell, T *object, const std::string &separator = " . " )
45
45
{
46
- return cell->module ->uniquify (concat_name (cell, object->name ));
46
+ return cell->module ->uniquify (concat_name (cell, object->name , separator ));
47
47
}
48
48
49
49
void map_sigspec (const dict<RTLIL::Wire*, RTLIL::Wire*> &map, RTLIL::SigSpec &sig, RTLIL::Module *into = nullptr )
@@ -60,6 +60,7 @@ struct FlattenWorker
60
60
bool ignore_wb = false ;
61
61
bool create_scopeinfo = true ;
62
62
bool create_scopename = false ;
63
+ std::string separator = " ." ;
63
64
64
65
template <class T >
65
66
void map_attributes (RTLIL::Cell *cell, T *object, IdString orig_object_name)
@@ -107,13 +108,13 @@ struct FlattenWorker
107
108
}
108
109
}
109
110
110
- void flatten_cell (RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl, SigMap &sigmap, std::vector<RTLIL::Cell*> &new_cells)
111
+ void flatten_cell (RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl, SigMap &sigmap, std::vector<RTLIL::Cell*> &new_cells, const std::string &separator )
111
112
{
112
113
// Copy the contents of the flattened cell
113
114
114
115
dict<IdString, IdString> memory_map;
115
116
for (auto &tpl_memory_it : tpl->memories ) {
116
- RTLIL::Memory *new_memory = module->addMemory (map_name (cell, tpl_memory_it.second ), tpl_memory_it.second );
117
+ RTLIL::Memory *new_memory = module->addMemory (map_name (cell, tpl_memory_it.second , separator ), tpl_memory_it.second );
117
118
map_attributes (cell, new_memory, tpl_memory_it.second ->name );
118
119
memory_map[tpl_memory_it.first ] = new_memory->name ;
119
120
design->select (module, new_memory);
@@ -127,7 +128,7 @@ struct FlattenWorker
127
128
128
129
RTLIL::Wire *new_wire = nullptr ;
129
130
if (tpl_wire->name [0 ] == ' \\ ' ) {
130
- RTLIL::Wire *hier_wire = module->wire (concat_name (cell, tpl_wire->name ));
131
+ RTLIL::Wire *hier_wire = module->wire (concat_name (cell, tpl_wire->name , separator ));
131
132
if (hier_wire != nullptr && hier_wire->get_bool_attribute (ID::hierconn)) {
132
133
hier_wire->attributes .erase (ID::hierconn);
133
134
if (GetSize (hier_wire) < GetSize (tpl_wire)) {
@@ -139,7 +140,7 @@ struct FlattenWorker
139
140
}
140
141
}
141
142
if (new_wire == nullptr ) {
142
- new_wire = module->addWire (map_name (cell, tpl_wire), tpl_wire);
143
+ new_wire = module->addWire (map_name (cell, tpl_wire, separator ), tpl_wire);
143
144
new_wire->port_input = new_wire->port_output = false ;
144
145
new_wire->port_id = false ;
145
146
}
@@ -150,7 +151,7 @@ struct FlattenWorker
150
151
}
151
152
152
153
for (auto &tpl_proc_it : tpl->processes ) {
153
- RTLIL::Process *new_proc = module->addProcess (map_name (cell, tpl_proc_it.second ), tpl_proc_it.second );
154
+ RTLIL::Process *new_proc = module->addProcess (map_name (cell, tpl_proc_it.second , separator ), tpl_proc_it.second );
154
155
map_attributes (cell, new_proc, tpl_proc_it.second ->name );
155
156
for (auto new_proc_sync : new_proc->syncs )
156
157
for (auto &memwr_action : new_proc_sync->mem_write_actions )
@@ -161,14 +162,14 @@ struct FlattenWorker
161
162
}
162
163
163
164
for (auto tpl_cell : tpl->cells ()) {
164
- RTLIL::Cell *new_cell = module->addCell (map_name (cell, tpl_cell), tpl_cell);
165
+ RTLIL::Cell *new_cell = module->addCell (map_name (cell, tpl_cell, separator ), tpl_cell);
165
166
map_attributes (cell, new_cell, tpl_cell->name );
166
167
if (new_cell->has_memid ()) {
167
168
IdString memid = new_cell->getParam (ID::MEMID).decode_string ();
168
169
new_cell->setParam (ID::MEMID, Const (memory_map.at (memid).str ()));
169
170
} else if (new_cell->is_mem_cell ()) {
170
171
IdString memid = new_cell->getParam (ID::MEMID).decode_string ();
171
- new_cell->setParam (ID::MEMID, Const (concat_name (cell, memid).str ()));
172
+ new_cell->setParam (ID::MEMID, Const (concat_name (cell, memid, separator ).str ()));
172
173
}
173
174
auto rewriter = [&](RTLIL::SigSpec &sig) { map_sigspec (wire_map, sig); };
174
175
new_cell->rewrite_sigspecs (rewriter);
@@ -279,7 +280,7 @@ struct FlattenWorker
279
280
module->rename (scopeinfo, cell_name);
280
281
}
281
282
282
- void flatten_module (RTLIL::Design *design, RTLIL::Module *module, pool<RTLIL::Module*> &used_modules)
283
+ void flatten_module (RTLIL::Design *design, RTLIL::Module *module, pool<RTLIL::Module*> &used_modules, const std::string &separator )
283
284
{
284
285
if (!design->selected (module) || module->get_blackbox_attribute (ignore_wb))
285
286
return ;
@@ -308,7 +309,7 @@ struct FlattenWorker
308
309
// If a design is fully selected and has a top module defined, topological sorting ensures that all cells
309
310
// added during flattening are black boxes, and flattening is finished in one pass. However, when flattening
310
311
// individual modules, this isn't the case, and the newly added cells might have to be flattened further.
311
- flatten_cell (design, module, cell, tpl, sigmap, worklist);
312
+ flatten_cell (design, module, cell, tpl, sigmap, worklist, separator );
312
313
}
313
314
}
314
315
};
@@ -345,6 +346,9 @@ struct FlattenPass : public Pass {
345
346
log (" with a public name the enclosing scope can be found via their\n " );
346
347
log (" 'hdlname' attribute.\n " );
347
348
log (" \n " );
349
+ log (" -separator <char>\n " );
350
+ log (" Use this separator char instead of '.' when concatenating design levels.\n " );
351
+ log (" \n " );
348
352
}
349
353
void execute (std::vector<std::string> args, RTLIL::Design *design) override
350
354
{
@@ -367,6 +371,10 @@ struct FlattenPass : public Pass {
367
371
worker.create_scopename = true ;
368
372
continue ;
369
373
}
374
+ if (args[argidx] == " -separator" && argidx + 1 < args.size ()) {
375
+ worker.separator = args[++argidx];
376
+ continue ;
377
+ }
370
378
break ;
371
379
}
372
380
extra_args (args, argidx, design);
@@ -401,7 +409,7 @@ struct FlattenPass : public Pass {
401
409
log_error (" Cannot flatten a design containing recursive instantiations.\n " );
402
410
403
411
for (auto module : topo_modules.sorted )
404
- worker.flatten_module (design, module, used_modules);
412
+ worker.flatten_module (design, module, used_modules, worker. separator );
405
413
406
414
if (top != nullptr )
407
415
for (auto module : design->modules ().to_vector ())
0 commit comments