yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
splitnets.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/rtlil.h"
23 #include "kernel/log.h"
24 
27 
29 {
30  std::map<RTLIL::Wire*, std::vector<RTLIL::SigBit>> splitmap;
31 
32  void append_wire(RTLIL::Module *module, RTLIL::Wire *wire, int offset, int width, std::string format)
33  {
34  std::string new_wire_name = wire->name.str();
35 
36  if (format.size() > 0)
37  new_wire_name += format.substr(0, 1);
38 
39  if (width > 1) {
40  new_wire_name += stringf("%d", offset+width-1);
41  if (format.size() > 2)
42  new_wire_name += format.substr(2, 1);
43  else
44  new_wire_name += ":";
45  }
46 
47  new_wire_name += stringf("%d", offset);
48 
49  if (format.size() > 1)
50  new_wire_name += format.substr(1, 1);
51 
52  RTLIL::Wire *new_wire = module->addWire(module->uniquify(new_wire_name), width);
53  new_wire->port_id = wire->port_id;
54  new_wire->port_input = wire->port_input;
55  new_wire->port_output = wire->port_output;
56 
57  std::vector<RTLIL::SigBit> sigvec = RTLIL::SigSpec(new_wire).to_sigbit_vector();
58  splitmap[wire].insert(splitmap[wire].end(), sigvec.begin(), sigvec.end());
59  }
60 
62  {
63  for (auto &bit : sig)
64  if (splitmap.count(bit.wire) > 0)
65  bit = splitmap.at(bit.wire).at(bit.offset);
66  }
67 };
68 
69 struct SplitnetsPass : public Pass {
70  SplitnetsPass() : Pass("splitnets", "split up multi-bit nets") { }
71  virtual void help()
72  {
73  // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
74  log("\n");
75  log(" splitnets [options] [selection]\n");
76  log("\n");
77  log("This command splits multi-bit nets into single-bit nets.\n");
78  log("\n");
79  log(" -format char1[char2[char3]]\n");
80  log(" the first char is inserted between the net name and the bit index, the\n");
81  log(" second char is appended to the netname. e.g. -format () creates net\n");
82  log(" names like 'mysignal(42)'. the 3rd character is the range separation\n");
83  log(" character when creating multi-bit wires. the default is '[]:'.\n");
84  log("\n");
85  log(" -ports\n");
86  log(" also split module ports. per default only internal signals are split.\n");
87  log("\n");
88  log(" -driver\n");
89  log(" don't blindly split nets in individual bits. instead look at the driver\n");
90  log(" and split nets so that no driver drives only part of a net.\n");
91  log("\n");
92  }
93  virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
94  {
95  bool flag_ports = false;
96  bool flag_driver = false;
97  std::string format = "[]:";
98 
99  log_header("Executing SPLITNETS pass (splitting up multi-bit signals).\n");
100 
101  size_t argidx;
102  for (argidx = 1; argidx < args.size(); argidx++)
103  {
104  if (args[argidx] == "-format" && argidx+1 < args.size()) {
105  format = args[++argidx];
106  continue;
107  }
108  if (args[argidx] == "-ports") {
109  flag_ports = true;
110  continue;
111  }
112  if (args[argidx] == "-driver") {
113  flag_driver = true;
114  continue;
115  }
116  break;
117  }
118  extra_args(args, argidx, design);
119 
120  for (auto &mod_it : design->modules_)
121  {
122  RTLIL::Module *module = mod_it.second;
123  if (!design->selected(module))
124  continue;
125 
126  SplitnetsWorker worker;
127 
128  if (flag_driver)
129  {
130  CellTypes ct(design);
131 
132  std::map<RTLIL::Wire*, std::set<int>> split_wires_at;
133 
134  for (auto &c : module->cells_)
135  for (auto &p : c.second->connections())
136  {
137  if (!ct.cell_known(c.second->type))
138  continue;
139  if (!ct.cell_output(c.second->type, p.first))
140  continue;
141 
142  RTLIL::SigSpec sig = p.second;
143  for (auto &chunk : sig.chunks()) {
144  if (chunk.wire == NULL)
145  continue;
146  if (chunk.wire->port_id == 0 || flag_ports) {
147  if (chunk.offset != 0)
148  split_wires_at[chunk.wire].insert(chunk.offset);
149  if (chunk.offset + chunk.width < chunk.wire->width)
150  split_wires_at[chunk.wire].insert(chunk.offset + chunk.width);
151  }
152  }
153  }
154 
155  for (auto &it : split_wires_at) {
156  int cursor = 0;
157  for (int next_cursor : it.second) {
158  worker.append_wire(module, it.first, cursor, next_cursor - cursor, format);
159  cursor = next_cursor;
160  }
161  worker.append_wire(module, it.first, cursor, it.first->width - cursor, format);
162  }
163  }
164  else
165  {
166  for (auto &w : module->wires_) {
167  RTLIL::Wire *wire = w.second;
168  if (wire->width > 1 && (wire->port_id == 0 || flag_ports) && design->selected(module, w.second))
169  worker.splitmap[wire] = std::vector<RTLIL::SigBit>();
170  }
171 
172  for (auto &it : worker.splitmap)
173  for (int i = 0; i < it.first->width; i++)
174  worker.append_wire(module, it.first, i, 1, format);
175  }
176 
177  module->rewrite_sigspecs(worker);
178 
179  std::set<RTLIL::Wire*> delete_wires;
180  for (auto &it : worker.splitmap)
181  delete_wires.insert(it.first);
182  module->remove(delete_wires);
183 
184  module->fixup_ports();
185  }
186  }
187 } SplitnetsPass;
188 
std::map< RTLIL::Wire *, std::vector< RTLIL::SigBit > > splitmap
Definition: splitnets.cc:30
bool selected(T1 *module) const
Definition: rtlil.h:551
std::string str() const
Definition: rtlil.h:182
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
void log_header(const char *format,...)
Definition: log.cc:188
CellTypes ct
Definition: opt_clean.cc:33
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
Definition: rtlil.h:595
void rewrite_sigspecs(T functor)
Definition: rtlil.h:1166
bool port_input
Definition: rtlil.h:827
int width
Definition: rtlil.h:826
RTLIL::Module * module
Definition: abc.cc:94
int port_id
Definition: rtlil.h:826
bool port_output
Definition: rtlil.h:827
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
void fixup_ports()
Definition: rtlil.cc:1312
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
Definition: rtlil.cc:1331
void append_wire(RTLIL::Module *module, RTLIL::Wire *wire, int offset, int width, std::string format)
Definition: splitnets.cc:32
virtual void help()
Definition: splitnets.cc:71
#define PRIVATE_NAMESPACE_END
Definition: yosys.h:98
SplitnetsPass SplitnetsPass
Definition: register.h:27
RTLIL::IdString name
Definition: rtlil.h:825
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)
Definition: splitnets.cc:93
#define USING_YOSYS_NAMESPACE
Definition: yosys.h:102
std::map< RTLIL::IdString, RTLIL::Module * > modules_
Definition: rtlil.h:507
#define NULL
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
Definition: rtlil.h:596
void remove(const std::set< RTLIL::Wire * > &wires)
Definition: rtlil.cc:1158
RTLIL::IdString uniquify(RTLIL::IdString name)
Definition: rtlil.cc:1244
void log(const char *format,...)
Definition: log.cc:180
void operator()(RTLIL::SigSpec &sig)
Definition: splitnets.cc:61
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
Definition: register.cc:128
std::vector< RTLIL::SigBit > to_sigbit_vector() const
Definition: rtlil.cc:2921
const std::vector< RTLIL::SigChunk > & chunks() const
Definition: rtlil.h:1016