yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
connwrappers.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/sigtools.h"
22 #include "kernel/rtlil.h"
23 #include "kernel/log.h"
24 
27 
29 {
30  struct portdecl_t {
31  // key: celltype, portname;
32  std::string widthparam, signparam;
33  bool is_signed;
34  };
35 
36  std::set<RTLIL::IdString> decl_celltypes;
37  std::map<std::pair<RTLIL::IdString, RTLIL::IdString>, portdecl_t> decls;
38 
39  void add_port(std::string celltype, std::string portname, std::string widthparam, std::string signparam)
40  {
41  std::pair<std::string, std::string> key(RTLIL::escape_id(celltype), RTLIL::escape_id(portname));
42  decl_celltypes.insert(key.first);
43 
44  if (decls.count(key))
45  log_cmd_error("Duplicate port decl: %s %s\n", celltype.c_str(), portname.c_str());
46 
47  portdecl_t decl;
48  decl.widthparam = RTLIL::escape_id(widthparam);
49  decl.signparam = RTLIL::escape_id(signparam);
50  decl.is_signed = false;
51  decls[key] = decl;
52  }
53 
54  void add_port(std::string celltype, std::string portname, std::string widthparam, bool is_signed)
55  {
56  std::pair<std::string, std::string> key(RTLIL::escape_id(celltype), RTLIL::escape_id(portname));
57  decl_celltypes.insert(key.first);
58 
59  if (decls.count(key))
60  log_cmd_error("Duplicate port decl: %s %s\n", celltype.c_str(), portname.c_str());
61 
62  portdecl_t decl;
63  decl.widthparam = RTLIL::escape_id(widthparam);
64  decl.is_signed = is_signed;
65  decls[key] = decl;
66  }
67 
69  {
70  std::map<RTLIL::SigBit, std::pair<bool, RTLIL::SigSpec>> extend_map;
71  SigMap sigmap(module);
72 
73  for (auto &it : module->cells_)
74  {
75  RTLIL::Cell *cell = it.second;
76 
77  if (!decl_celltypes.count(cell->type))
78  continue;
79 
80  for (auto &conn : cell->connections())
81  {
82  std::pair<RTLIL::IdString, RTLIL::IdString> key(cell->type, conn.first);
83 
84  if (!decls.count(key))
85  continue;
86 
87  portdecl_t &decl = decls.at(key);
88 
89  if (!cell->parameters.count(decl.widthparam))
90  continue;
91 
92  if (!decl.signparam.empty() && !cell->parameters.count(decl.signparam))
93  continue;
94 
95  int inner_width = cell->parameters.at(decl.widthparam).as_int();
96  int outer_width = conn.second.size();
97  bool is_signed = decl.signparam.empty() ? decl.is_signed : cell->parameters.at(decl.signparam).as_bool();
98 
99  if (inner_width >= outer_width)
100  continue;
101 
102  RTLIL::SigSpec sig = sigmap(conn.second);
103  extend_map[sig.extract(inner_width - 1, 1)] = std::pair<bool, RTLIL::SigSpec>(is_signed,
104  sig.extract(inner_width, outer_width - inner_width));
105  }
106  }
107 
108  for (auto &it : module->cells_)
109  {
110  RTLIL::Cell *cell = it.second;
111 
112  if (!design->selected(module, cell))
113  continue;
114 
115  for (auto &conn : cell->connections_)
116  {
117  std::vector<RTLIL::SigBit> sigbits = sigmap(conn.second).to_sigbit_vector();
118  RTLIL::SigSpec old_sig;
119 
120  for (size_t i = 0; i < sigbits.size(); i++)
121  {
122  if (!extend_map.count(sigbits[i]))
123  continue;
124 
125  bool is_signed = extend_map.at(sigbits[i]).first;
126  RTLIL::SigSpec extend_sig = extend_map.at(sigbits[i]).second;
127 
128  int extend_width = 0;
129  RTLIL::SigBit extend_bit = is_signed ? sigbits[i] : RTLIL::SigBit(RTLIL::State::S0);
130  while (extend_width < extend_sig.size() && i + extend_width + 1 < sigbits.size() &&
131  sigbits[i + extend_width + 1] == extend_bit) extend_width++;
132 
133  if (extend_width == 0)
134  continue;
135 
136  if (old_sig.size() == 0)
137  old_sig = conn.second;
138 
139  conn.second.replace(i+1, extend_sig.extract(0, extend_width));
140  i += extend_width;
141  }
142 
143  if (old_sig.size())
144  log("Connected extended bits of %s.%s:%s: %s -> %s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name),
145  RTLIL::id2cstr(conn.first), log_signal(old_sig), log_signal(conn.second));
146  }
147  }
148  }
149 };
150 
151 struct ConnwrappersPass : public Pass {
152  ConnwrappersPass() : Pass("connwrappers", "replace undef values with defined constants") { }
153  virtual void help()
154  {
155  // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
156  log("\n");
157  log(" connwrappers [options] [selection]\n");
158  log("\n");
159  log("Wrappers are used in coarse-grain synthesis to wrap cells with smaller ports\n");
160  log("in wrapper cells with a (larger) constant port size. I.e. the upper bits\n");
161  log("of the wrapper outut are signed/unsigned bit extended. This command uses this\n");
162  log("knowlege to rewire the inputs of the driven cells to match the output of\n");
163  log("the driving cell.\n");
164  log("\n");
165  log(" -signed <cell_type> <port_name> <width_param>\n");
166  log(" -unsigned <cell_type> <port_name> <width_param>\n");
167  log(" consider the specified signed/unsigned wrapper output\n");
168  log("\n");
169  log(" -port <cell_type> <port_name> <width_param> <sign_param>\n");
170  log(" use the specified parameter to decide if signed or unsigned\n");
171  log("\n");
172  log("The options -signed, -unsigned, and -port can be specified multiple times.\n");
173  log("\n");
174  }
175  virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
176  {
177  ConnwrappersWorker worker;
178 
179  size_t argidx;
180  for (argidx = 1; argidx < args.size(); argidx++)
181  {
182  if (args[argidx] == "-signed" && argidx+3 < args.size()) {
183  worker.add_port(args[argidx+1], args[argidx+2], args[argidx+3], true);
184  argidx += 3;
185  continue;
186  }
187  if (args[argidx] == "-unsigned" && argidx+3 < args.size()) {
188  worker.add_port(args[argidx+1], args[argidx+2], args[argidx+3], false);
189  argidx += 3;
190  continue;
191  }
192  if (args[argidx] == "-port" && argidx+4 < args.size()) {
193  worker.add_port(args[argidx+1], args[argidx+2], args[argidx+3], args[argidx+4]);
194  argidx += 4;
195  continue;
196  }
197  break;
198  }
199  extra_args(args, argidx, design);
200 
201  log_header("Executing CONNWRAPPERS pass (connect extended ports of wrapper cells).\n");
202 
203  for (auto &mod_it : design->modules_)
204  if (design->selected(mod_it.second))
205  worker.work(design, mod_it.second);
206  }
208 
bool selected(T1 *module) const
Definition: rtlil.h:551
std::set< RTLIL::IdString > decl_celltypes
Definition: connwrappers.cc:36
void log_header(const char *format,...)
Definition: log.cc:188
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
Definition: log.cc:269
RTLIL::IdString name
Definition: rtlil.h:853
RTLIL::Module * module
Definition: abc.cc:94
RTLIL::IdString type
Definition: rtlil.h:854
std::map< RTLIL::IdString, RTLIL::Const > parameters
Definition: rtlil.h:856
void work(RTLIL::Design *design, RTLIL::Module *module)
Definition: connwrappers.cc:68
int size() const
Definition: rtlil.h:1019
static std::string escape_id(std::string str)
Definition: rtlil.h:251
#define PRIVATE_NAMESPACE_BEGIN
Definition: yosys.h:97
void add_port(std::string celltype, std::string portname, std::string widthparam, bool is_signed)
Definition: connwrappers.cc:54
RTLIL::IdString name
Definition: rtlil.h:599
std::map< std::pair< RTLIL::IdString, RTLIL::IdString >, portdecl_t > decls
Definition: connwrappers.cc:37
virtual void help()
#define PRIVATE_NAMESPACE_END
Definition: yosys.h:98
Definition: register.h:27
static const char * id2cstr(const RTLIL::IdString &str)
Definition: rtlil.h:267
void log_cmd_error(const char *format,...)
Definition: log.cc:211
#define USING_YOSYS_NAMESPACE
Definition: yosys.h:102
void add_port(std::string celltype, std::string portname, std::string widthparam, std::string signparam)
Definition: connwrappers.cc:39
std::map< RTLIL::IdString, RTLIL::Module * > modules_
Definition: rtlil.h:507
void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with)
Definition: rtlil.cc:2297
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
Definition: rtlil.h:596
void log(const char *format,...)
Definition: log.cc:180
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other=NULL) const
Definition: rtlil.cc:2414
ConnwrappersPass ConnwrappersPass
std::map< RTLIL::IdString, RTLIL::SigSpec > connections_
Definition: rtlil.h:855
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
Definition: register.cc:128
const std::map< RTLIL::IdString, RTLIL::SigSpec > & connections() const
Definition: rtlil.cc:1814