yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
submod.cc
Go to the documentation of this file.
1 /*
2  * yosys -- Yosys Open SYnthesis Suite
3  *
4  * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  */
19 
20 #include "kernel/register.h"
21 #include "kernel/celltypes.h"
22 #include "kernel/log.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <set>
26 
29 
31 {
35  std::string opt_name;
36 
37  struct SubModule
38  {
39  std::string name, full_name;
40  std::set<RTLIL::Cell*> cells;
41  };
42 
43  std::map<std::string, SubModule> submodules;
44 
45  struct wire_flags_t {
48  wire_flags_t() : new_wire(NULL), is_int_driven(false), is_int_used(false), is_ext_driven(false), is_ext_used(false) { }
49  };
50  std::map<RTLIL::Wire*, wire_flags_t> wire_flags;
52 
53  void flag_wire(RTLIL::Wire *wire, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used)
54  {
55  if (wire_flags.count(wire) == 0) {
56  if (!create)
57  return;
58  wire_flags[wire] = wire_flags_t();
59  }
60  if (set_int_driven)
61  wire_flags[wire].is_int_driven = true;
62  if (set_int_used)
63  wire_flags[wire].is_int_used = true;
64  if (set_ext_driven)
65  wire_flags[wire].is_ext_driven = true;
66  if (set_ext_used)
67  wire_flags[wire].is_ext_used = true;
68  flag_found_something = true;
69  }
70 
71  void flag_signal(const RTLIL::SigSpec &sig, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used)
72  {
73  for (auto &c : sig.chunks())
74  if (c.wire != NULL)
75  flag_wire(c.wire, create, set_int_driven, set_int_used, set_ext_driven, set_ext_used);
76  }
77 
79  {
80  log("Creating submodule %s (%s) of module %s.\n", submod.name.c_str(), submod.full_name.c_str(), module->name.c_str());
81 
82  wire_flags.clear();
83  for (RTLIL::Cell *cell : submod.cells) {
84  if (ct.cell_known(cell->type)) {
85  for (auto &conn : cell->connections())
86  flag_signal(conn.second, true, ct.cell_output(cell->type, conn.first), ct.cell_input(cell->type, conn.first), false, false);
87  } else {
88  log_warning("Port directions for cell %s (%s) are unknown. Assuming inout for all ports.\n", cell->name.c_str(), cell->type.c_str());
89  for (auto &conn : cell->connections())
90  flag_signal(conn.second, true, true, true, false, false);
91  }
92  }
93  for (auto &it : module->cells_) {
94  RTLIL::Cell *cell = it.second;
95  if (submod.cells.count(cell) > 0)
96  continue;
97  if (ct.cell_known(cell->type)) {
98  for (auto &conn : cell->connections())
99  flag_signal(conn.second, false, false, false, ct.cell_output(cell->type, conn.first), ct.cell_input(cell->type, conn.first));
100  } else {
101  flag_found_something = false;
102  for (auto &conn : cell->connections())
103  flag_signal(conn.second, false, false, false, true, true);
105  log_warning("Port directions for cell %s (%s) are unknown. Assuming inout for all ports.\n", cell->name.c_str(), cell->type.c_str());
106  }
107  }
108 
109  RTLIL::Module *new_mod = new RTLIL::Module;
110  new_mod->name = submod.full_name;
111  design->add(new_mod);
112  int auto_name_counter = 1;
113 
114  std::set<RTLIL::IdString> all_wire_names;
115  for (auto &it : wire_flags) {
116  all_wire_names.insert(it.first->name);
117  }
118 
119  for (auto &it : wire_flags)
120  {
121  RTLIL::Wire *wire = it.first;
122  wire_flags_t &flags = it.second;
123 
124  if (wire->port_input)
125  flags.is_ext_driven = true;
126  if (wire->port_output)
127  flags.is_ext_used = true;
128 
129  bool new_wire_port_input = false;
130  bool new_wire_port_output = false;
131 
132  if (flags.is_int_driven && flags.is_ext_used)
133  new_wire_port_output = true;
134  if (flags.is_ext_driven && flags.is_int_used)
135  new_wire_port_input = true;
136 
137  if (flags.is_int_driven && flags.is_ext_driven)
138  new_wire_port_input = true, new_wire_port_output = true;
139 
140  std::string new_wire_name = wire->name.str();
141  if (new_wire_port_input || new_wire_port_output) {
142  while (new_wire_name[0] == '$') {
143  std::string next_wire_name = stringf("\\n%d", auto_name_counter++);
144  if (all_wire_names.count(next_wire_name) == 0) {
145  all_wire_names.insert(next_wire_name);
146  new_wire_name = next_wire_name;
147  }
148  }
149  }
150 
151  RTLIL::Wire *new_wire = new_mod->addWire(new_wire_name, wire->width);
152  new_wire->port_input = new_wire_port_input;
153  new_wire->port_output = new_wire_port_output;
154  new_wire->start_offset = wire->start_offset;
155  new_wire->attributes = wire->attributes;
156 
157  if (new_wire->port_input && new_wire->port_output)
158  log(" signal %s: inout %s\n", wire->name.c_str(), new_wire->name.c_str());
159  else if (new_wire->port_input)
160  log(" signal %s: input %s\n", wire->name.c_str(), new_wire->name.c_str());
161  else if (new_wire->port_output)
162  log(" signal %s: output %s\n", wire->name.c_str(), new_wire->name.c_str());
163  else
164  log(" signal %s: internal\n", wire->name.c_str());
165 
166  flags.new_wire = new_wire;
167  }
168 
169  new_mod->fixup_ports();
170 
171  for (RTLIL::Cell *cell : submod.cells) {
172  RTLIL::Cell *new_cell = new_mod->addCell(cell->name, cell);
173  for (auto &conn : new_cell->connections_)
174  for (auto &bit : conn.second)
175  if (bit.wire != NULL) {
176  log_assert(wire_flags.count(bit.wire) > 0);
177  bit.wire = wire_flags[bit.wire].new_wire;
178  }
179  log(" cell %s (%s)\n", new_cell->name.c_str(), new_cell->type.c_str());
180  module->remove(cell);
181  }
182  submod.cells.clear();
183 
184  RTLIL::Cell *new_cell = module->addCell(submod.full_name, submod.full_name);
185  for (auto &it : wire_flags)
186  {
187  RTLIL::Wire *old_wire = it.first;
188  RTLIL::Wire *new_wire = it.second.new_wire;
189  if (new_wire->port_id > 0)
190  new_cell->setPort(new_wire->name, RTLIL::SigSpec(old_wire));
191  }
192  }
193 
194  SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, std::string opt_name = std::string()) : design(design), module(module), opt_name(opt_name)
195  {
196  if (!design->selected_whole_module(module->name) && opt_name.empty())
197  return;
198 
199  if (module->processes.size() > 0) {
200  log("Skipping module %s as it contains processes (run 'proc' pass first).\n", module->name.c_str());
201  return;
202  }
203 
204  if (module->memories.size() > 0) {
205  log("Skipping module %s as it contains memories (run 'memory' pass first).\n", module->name.c_str());
206  return;
207  }
208 
211  ct.setup_stdcells();
213  ct.setup_design(design);
214 
215  if (opt_name.empty())
216  {
217  for (auto &it : module->wires_)
218  it.second->attributes.erase("\\submod");
219 
220  for (auto &it : module->cells_)
221  {
222  RTLIL::Cell *cell = it.second;
223  if (cell->attributes.count("\\submod") == 0 || cell->attributes["\\submod"].bits.size() == 0) {
224  cell->attributes.erase("\\submod");
225  continue;
226  }
227 
228  std::string submod_str = cell->attributes["\\submod"].decode_string();
229  cell->attributes.erase("\\submod");
230 
231  if (submodules.count(submod_str) == 0) {
232  submodules[submod_str].name = submod_str;
233  submodules[submod_str].full_name = module->name.str() + "_" + submod_str;
234  while (design->modules_.count(submodules[submod_str].full_name) != 0 ||
235  module->count_id(submodules[submod_str].full_name) != 0)
236  submodules[submod_str].full_name += "_";
237  }
238 
239  submodules[submod_str].cells.insert(cell);
240  }
241  }
242  else
243  {
244  for (auto &it : module->cells_)
245  {
246  RTLIL::Cell *cell = it.second;
247  if (!design->selected(module, cell))
248  continue;
249  submodules[opt_name].name = opt_name;
251  submodules[opt_name].cells.insert(cell);
252  }
253 
254  if (submodules.size() == 0)
255  log("Nothing selected -> do nothing.\n");
256  }
257 
258  for (auto &it : submodules)
259  handle_submodule(it.second);
260  }
261 };
262 
263 struct SubmodPass : public Pass {
264  SubmodPass() : Pass("submod", "moving part of a module to a new submodule") { }
265  virtual void help()
266  {
267  // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
268  log("\n");
269  log(" submod [selection]\n");
270  log("\n");
271  log("This pass identifies all cells with the 'submod' attribute and moves them to\n");
272  log("a newly created module. The value of the attribute is used as name for the\n");
273  log("cell that replaces the group of cells with the same attribute value.\n");
274  log("\n");
275  log("This pass can be used to create a design hierarchy in flat design. This can\n");
276  log("be useful for analyzing or reverse-engineering a design.\n");
277  log("\n");
278  log("This pass only operates on completely selected modules with no processes\n");
279  log("or memories.\n");
280  log("\n");
281  log("\n");
282  log(" submod -name <name> [selection]\n");
283  log("\n");
284  log("As above, but don't use the 'submod' attribute but instead use the selection.\n");
285  log("Only objects from one module might be selected. The value of the -name option\n");
286  log("is used as the value of the 'submod' attribute above.\n");
287  log("\n");
288  }
289  virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
290  {
291  log_header("Executing SUBMOD pass (moving cells to submodules as requested).\n");
292  log_push();
293 
294  std::string opt_name;
295 
296  size_t argidx;
297  for (argidx = 1; argidx < args.size(); argidx++) {
298  if (args[argidx] == "-name" && argidx+1 < args.size()) {
299  opt_name = args[++argidx];
300  continue;
301  }
302  break;
303  }
304  extra_args(args, argidx, design);
305 
306  if (opt_name.empty())
307  {
308  Pass::call(design, "opt_clean");
309  log_header("Continuing SUBMOD pass.\n");
310 
311  std::set<RTLIL::IdString> handled_modules;
312 
313  bool did_something = true;
314  while (did_something) {
315  did_something = false;
316  std::vector<RTLIL::IdString> queued_modules;
317  for (auto &mod_it : design->modules_)
318  if (handled_modules.count(mod_it.first) == 0 && design->selected_whole_module(mod_it.first))
319  queued_modules.push_back(mod_it.first);
320  for (auto &modname : queued_modules)
321  if (design->modules_.count(modname) != 0) {
322  SubmodWorker worker(design, design->modules_[modname]);
323  handled_modules.insert(modname);
324  did_something = true;
325  }
326  }
327 
328  Pass::call(design, "opt_clean");
329  }
330  else
331  {
333  for (auto &mod_it : design->modules_) {
334  if (!design->selected_module(mod_it.first))
335  continue;
336  if (module != NULL)
337  log_cmd_error("More than one module selected: %s %s\n", module->name.c_str(), mod_it.first.c_str());
338  module = mod_it.second;
339  }
340  if (module == NULL)
341  log("Nothing selected -> do nothing.\n");
342  else {
343  Pass::call_on_module(design, module, "opt_clean");
344  log_header("Continuing SUBMOD pass.\n");
345  SubmodWorker worker(design, module, opt_name);
346  }
347  }
348 
349  log_pop();
350  }
351 } SubmodPass;
352 
const char * c_str() const
Definition: rtlil.h:178
bool selected(T1 *module) const
Definition: rtlil.h:551
std::string str() const
Definition: rtlil.h:182
void setup_stdcells()
Definition: celltypes.h:132
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)
Definition: submod.cc:289
int auto_name_counter
void log_warning(const char *format,...)
Definition: log.cc:196
RTLIL::Module * module
Definition: submod.cc:34
bool selected_module(RTLIL::IdString mod_name) const
Definition: rtlil.cc:379
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
Definition: rtlil.cc:1353
void add(RTLIL::Module *module)
Definition: rtlil.cc:259
RTLIL::Wire * new_wire
Definition: submod.cc:46
void setup_internals_mem()
Definition: celltypes.h:115
void log_header(const char *format,...)
Definition: log.cc:188
std::map< RTLIL::Wire *, wire_flags_t > wire_flags
Definition: submod.cc:50
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
Definition: rtlil.h:595
RTLIL::IdString name
Definition: rtlil.h:853
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
Definition: rtlil.cc:1789
bool port_input
Definition: rtlil.h:827
int width
Definition: rtlil.h:826
std::map< RTLIL::IdString, RTLIL::Memory * > memories
Definition: rtlil.h:601
RTLIL::Module * module
Definition: abc.cc:94
int port_id
Definition: rtlil.h:826
RTLIL::IdString type
Definition: rtlil.h:854
void log_pop()
Definition: log.cc:237
void handle_submodule(SubModule &submod)
Definition: submod.cc:78
SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, std::string opt_name=std::string())
Definition: submod.cc:194
void flag_wire(RTLIL::Wire *wire, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used)
Definition: submod.cc:53
std::string name
Definition: submod.cc:39
static std::string escape_id(std::string str)
Definition: rtlil.h:251
bool port_output
Definition: rtlil.h:827
SubmodPass SubmodPass
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN bool did_something
Definition: opt_const.cc:32
bool cell_known(RTLIL::IdString type)
Definition: celltypes.h:188
#define PRIVATE_NAMESPACE_BEGIN
Definition: yosys.h:97
bool cell_output(RTLIL::IdString type, RTLIL::IdString port)
Definition: celltypes.h:193
SubmodPass()
Definition: submod.cc:264
std::string full_name
Definition: submod.cc:39
void fixup_ports()
Definition: rtlil.cc:1312
#define log_assert(_assert_expr_)
Definition: log.h:85
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
Definition: rtlil.cc:1331
RTLIL::IdString name
Definition: rtlil.h:599
bool selected_whole_module(RTLIL::IdString mod_name) const
Definition: rtlil.cc:388
bool flag_found_something
Definition: submod.cc:51
#define PRIVATE_NAMESPACE_END
Definition: yosys.h:98
Definition: register.h:27
RTLIL::IdString name
Definition: rtlil.h:825
virtual void help()
Definition: submod.cc:265
void log_cmd_error(const char *format,...)
Definition: log.cc:211
std::map< RTLIL::IdString, RTLIL::Process * > processes
Definition: rtlil.h:602
#define USING_YOSYS_NAMESPACE
Definition: yosys.h:102
virtual size_t count_id(RTLIL::IdString id)
Definition: rtlil.cc:472
std::map< RTLIL::IdString, RTLIL::Module * > modules_
Definition: rtlil.h:507
std::map< std::string, SubModule > submodules
Definition: submod.cc:43
#define NULL
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
Definition: rtlil.h:596
static void call_on_module(RTLIL::Design *design, RTLIL::Module *module, std::string command)
Definition: register.cc:240
void remove(const std::set< RTLIL::Wire * > &wires)
Definition: rtlil.cc:1158
void log(const char *format,...)
Definition: log.cc:180
void setup_internals()
Definition: celltypes.h:83
std::string opt_name
Definition: submod.cc:35
void log_push()
Definition: log.cc:232
void setup_design(RTLIL::Design *design)
Definition: celltypes.h:77
void setup_stdcells_mem()
Definition: celltypes.h:149
std::set< RTLIL::Cell * > cells
Definition: submod.cc:40
int start_offset
Definition: rtlil.h:826
bool cell_input(RTLIL::IdString type, RTLIL::IdString port)
Definition: celltypes.h:199
std::map< RTLIL::IdString, RTLIL::SigSpec > connections_
Definition: rtlil.h:855
RTLIL::Design * design
Definition: submod.cc:33
CellTypes ct
Definition: submod.cc:32
void flag_signal(const RTLIL::SigSpec &sig, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used)
Definition: submod.cc:71
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
Definition: register.cc:128
static void call(RTLIL::Design *design, std::string command)
Definition: register.cc:146
const std::map< RTLIL::IdString, RTLIL::SigSpec > & connections() const
Definition: rtlil.cc:1814
const std::vector< RTLIL::SigChunk > & chunks() const
Definition: rtlil.h:1016