2828USING_YOSYS_NAMESPACE
2929PRIVATE_NAMESPACE_BEGIN
3030
31- IdString concat_name (RTLIL::Cell *cell, IdString object_name)
31+ IdString concat_name (RTLIL::Cell *cell, IdString object_name, const std::string &separator = " . " )
3232{
3333 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 );
3535 else {
3636 std::string object_name_str = object_name.str ();
3737 if (object_name_str.substr (0 , 8 ) == " $flatten" )
3838 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 ());
4040 }
4141}
4242
4343template <class T >
44- IdString map_name (RTLIL::Cell *cell, T *object)
44+ IdString map_name (RTLIL::Cell *cell, T *object, const std::string &separator = " . " )
4545{
46- return cell->module ->uniquify (concat_name (cell, object->name ));
46+ return cell->module ->uniquify (concat_name (cell, object->name , separator ));
4747}
4848
4949void map_sigspec (const dict<RTLIL::Wire*, RTLIL::Wire*> &map, RTLIL::SigSpec &sig, RTLIL::Module *into = nullptr )
@@ -60,6 +60,7 @@ struct FlattenWorker
6060 bool ignore_wb = false ;
6161 bool create_scopeinfo = true ;
6262 bool create_scopename = false ;
63+ std::string separator = " ." ;
6364
6465 template <class T >
6566 void map_attributes (RTLIL::Cell *cell, T *object, IdString orig_object_name)
@@ -107,13 +108,13 @@ struct FlattenWorker
107108 }
108109 }
109110
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 )
111112 {
112113 // Copy the contents of the flattened cell
113114
114115 dict<IdString, IdString> memory_map;
115116 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 );
117118 map_attributes (cell, new_memory, tpl_memory_it.second ->name );
118119 memory_map[tpl_memory_it.first ] = new_memory->name ;
119120 design->select (module , new_memory);
@@ -127,7 +128,7 @@ struct FlattenWorker
127128
128129 RTLIL::Wire *new_wire = nullptr ;
129130 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 ));
131132 if (hier_wire != nullptr && hier_wire->get_bool_attribute (ID::hierconn)) {
132133 hier_wire->attributes .erase (ID::hierconn);
133134 if (GetSize (hier_wire) < GetSize (tpl_wire)) {
@@ -139,7 +140,7 @@ struct FlattenWorker
139140 }
140141 }
141142 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);
143144 new_wire->port_input = new_wire->port_output = false ;
144145 new_wire->port_id = false ;
145146 }
@@ -150,7 +151,7 @@ struct FlattenWorker
150151 }
151152
152153 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 );
154155 map_attributes (cell, new_proc, tpl_proc_it.second ->name );
155156 for (auto new_proc_sync : new_proc->syncs )
156157 for (auto &memwr_action : new_proc_sync->mem_write_actions )
@@ -161,14 +162,14 @@ struct FlattenWorker
161162 }
162163
163164 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);
165166 map_attributes (cell, new_cell, tpl_cell->name );
166167 if (new_cell->has_memid ()) {
167168 IdString memid = new_cell->getParam (ID::MEMID).decode_string ();
168169 new_cell->setParam (ID::MEMID, Const (memory_map.at (memid).str ()));
169170 } else if (new_cell->is_mem_cell ()) {
170171 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 ()));
172173 }
173174 auto rewriter = [&](RTLIL::SigSpec &sig) { map_sigspec (wire_map, sig); };
174175 new_cell->rewrite_sigspecs (rewriter);
@@ -279,7 +280,7 @@ struct FlattenWorker
279280 module ->rename (scopeinfo, cell_name);
280281 }
281282
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 )
283284 {
284285 if (!design->selected (module ) || module ->get_blackbox_attribute (ignore_wb))
285286 return ;
@@ -308,7 +309,7 @@ struct FlattenWorker
308309 // If a design is fully selected and has a top module defined, topological sorting ensures that all cells
309310 // added during flattening are black boxes, and flattening is finished in one pass. However, when flattening
310311 // 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 );
312313 }
313314 }
314315};
@@ -345,6 +346,9 @@ struct FlattenPass : public Pass {
345346 log (" with a public name the enclosing scope can be found via their\n " );
346347 log (" 'hdlname' attribute.\n " );
347348 log (" \n " );
349+ log (" -separator <char>\n " );
350+ log (" Use this separator char instead of '.' when concatenating design levels.\n " );
351+ log (" \n " );
348352 }
349353 void execute (std::vector<std::string> args, RTLIL::Design *design) override
350354 {
@@ -367,6 +371,10 @@ struct FlattenPass : public Pass {
367371 worker.create_scopename = true ;
368372 continue ;
369373 }
374+ if (args[argidx] == " -separator" && argidx + 1 < args.size ()) {
375+ worker.separator = args[++argidx];
376+ continue ;
377+ }
370378 break ;
371379 }
372380 extra_args (args, argidx, design);
@@ -401,7 +409,7 @@ struct FlattenPass : public Pass {
401409 log_error (" Cannot flatten a design containing recursive instantiations.\n " );
402410
403411 for (auto module : topo_modules.sorted )
404- worker.flatten_module (design, module , used_modules);
412+ worker.flatten_module (design, module , used_modules, worker. separator );
405413
406414 if (top != nullptr )
407415 for (auto module : design->modules ().to_vector ())
0 commit comments