yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
opt_rmdff.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/log.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 
28 
31 
33 {
34  RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r;
35  RTLIL::Const val_cp, val_rp, val_rv;
36 
37  if (dff->type == "$_DFF_N_" || dff->type == "$_DFF_P_") {
38  sig_d = dff->getPort("\\D");
39  sig_q = dff->getPort("\\Q");
40  sig_c = dff->getPort("\\C");
41  val_cp = RTLIL::Const(dff->type == "$_DFF_P_", 1);
42  }
43  else if (dff->type.substr(0,6) == "$_DFF_" && dff->type.substr(9) == "_" &&
44  (dff->type[6] == 'N' || dff->type[6] == 'P') &&
45  (dff->type[7] == 'N' || dff->type[7] == 'P') &&
46  (dff->type[8] == '0' || dff->type[8] == '1')) {
47  sig_d = dff->getPort("\\D");
48  sig_q = dff->getPort("\\Q");
49  sig_c = dff->getPort("\\C");
50  sig_r = dff->getPort("\\R");
51  val_cp = RTLIL::Const(dff->type[6] == 'P', 1);
52  val_rp = RTLIL::Const(dff->type[7] == 'P', 1);
53  val_rv = RTLIL::Const(dff->type[8] == '1', 1);
54  }
55  else if (dff->type == "$dff") {
56  sig_d = dff->getPort("\\D");
57  sig_q = dff->getPort("\\Q");
58  sig_c = dff->getPort("\\CLK");
59  val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
60  }
61  else if (dff->type == "$adff") {
62  sig_d = dff->getPort("\\D");
63  sig_q = dff->getPort("\\Q");
64  sig_c = dff->getPort("\\CLK");
65  sig_r = dff->getPort("\\ARST");
66  val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
67  val_rp = RTLIL::Const(dff->parameters["\\ARST_POLARITY"].as_bool(), 1);
68  val_rv = dff->parameters["\\ARST_VALUE"];
69  }
70  else
71  log_abort();
72 
73  assign_map.apply(sig_d);
74  assign_map.apply(sig_q);
75  assign_map.apply(sig_c);
76  assign_map.apply(sig_r);
77 
78  bool has_init = false;
79  RTLIL::Const val_init;
80  for (auto bit : dff_init_map(sig_q).to_sigbit_vector()) {
81  if (bit.wire == NULL)
82  has_init = true;
83  val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx);
84  }
85 
86  if (dff->type == "$dff" && mux_drivers.has(sig_d) && !has_init) {
87  std::set<RTLIL::Cell*> muxes;
88  mux_drivers.find(sig_d, muxes);
89  for (auto mux : muxes) {
90  RTLIL::SigSpec sig_a = assign_map(mux->getPort("\\A"));
91  RTLIL::SigSpec sig_b = assign_map(mux->getPort("\\B"));
92  if (sig_a == sig_q && sig_b.is_fully_const()) {
93  RTLIL::SigSig conn(sig_q, sig_b);
94  mod->connect(conn);
95  goto delete_dff;
96  }
97  if (sig_b == sig_q && sig_a.is_fully_const()) {
98  RTLIL::SigSig conn(sig_q, sig_a);
99  mod->connect(conn);
100  goto delete_dff;
101  }
102  }
103  }
104 
105  if (sig_c.is_fully_const() && (!sig_r.size() || !has_init)) {
106  if (val_rv.bits.size() == 0)
107  val_rv = val_init;
108  RTLIL::SigSig conn(sig_q, val_rv);
109  mod->connect(conn);
110  goto delete_dff;
111  }
112 
113  if (sig_d.is_fully_undef() && sig_r.size() && !has_init) {
114  RTLIL::SigSig conn(sig_q, val_rv);
115  mod->connect(conn);
116  goto delete_dff;
117  }
118 
119  if (sig_d.is_fully_undef() && !sig_r.size() && has_init) {
120  RTLIL::SigSig conn(sig_q, val_init);
121  mod->connect(conn);
122  goto delete_dff;
123  }
124 
125  if (sig_d.is_fully_const() && !sig_r.size() && !has_init) {
126  RTLIL::SigSig conn(sig_q, sig_d);
127  mod->connect(conn);
128  goto delete_dff;
129  }
130 
131  if (sig_d == sig_q && !(sig_r.size() && has_init)) {
132  if (sig_r.size()) {
133  RTLIL::SigSig conn(sig_q, val_rv);
134  mod->connect(conn);
135  }
136  if (has_init) {
137  RTLIL::SigSig conn(sig_q, val_init);
138  mod->connect(conn);
139  }
140  goto delete_dff;
141  }
142 
143  return false;
144 
145 delete_dff:
146  log("Removing %s (%s) from module %s.\n", dff->name.c_str(), dff->type.c_str(), mod->name.c_str());
147  mod->remove(dff);
148  return true;
149 }
150 
151 struct OptRmdffPass : public Pass {
152  OptRmdffPass() : Pass("opt_rmdff", "remove DFFs with constant inputs") { }
153  virtual void help()
154  {
155  // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
156  log("\n");
157  log(" opt_rmdff [selection]\n");
158  log("\n");
159  log("This pass identifies flip-flops with constant inputs and replaces them with\n");
160  log("a constant driver.\n");
161  log("\n");
162  }
163  virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
164  {
165  int total_count = 0;
166  log_header("Executing OPT_RMDFF pass (remove dff with constant values).\n");
167 
168  extra_args(args, 1, design);
169 
170  for (auto &mod_it : design->modules_)
171  {
172  if (!design->selected(mod_it.second))
173  continue;
174 
175  assign_map.set(mod_it.second);
176  dff_init_map.set(mod_it.second);
177  for (auto &it : mod_it.second->wires_)
178  if (it.second->attributes.count("\\init") != 0)
179  dff_init_map.add(it.second, it.second->attributes.at("\\init"));
180  mux_drivers.clear();
181 
182  std::vector<RTLIL::IdString> dff_list;
183  for (auto &it : mod_it.second->cells_) {
184  if (it.second->type == "$mux" || it.second->type == "$pmux") {
185  if (it.second->getPort("\\A").size() == it.second->getPort("\\B").size())
186  mux_drivers.insert(assign_map(it.second->getPort("\\Y")), it.second);
187  continue;
188  }
189  if (!design->selected(mod_it.second, it.second))
190  continue;
191  if (it.second->type == "$_DFF_N_") dff_list.push_back(it.first);
192  if (it.second->type == "$_DFF_P_") dff_list.push_back(it.first);
193  if (it.second->type == "$_DFF_NN0_") dff_list.push_back(it.first);
194  if (it.second->type == "$_DFF_NN1_") dff_list.push_back(it.first);
195  if (it.second->type == "$_DFF_NP0_") dff_list.push_back(it.first);
196  if (it.second->type == "$_DFF_NP1_") dff_list.push_back(it.first);
197  if (it.second->type == "$_DFF_PN0_") dff_list.push_back(it.first);
198  if (it.second->type == "$_DFF_PN1_") dff_list.push_back(it.first);
199  if (it.second->type == "$_DFF_PP0_") dff_list.push_back(it.first);
200  if (it.second->type == "$_DFF_PP1_") dff_list.push_back(it.first);
201  if (it.second->type == "$dff") dff_list.push_back(it.first);
202  if (it.second->type == "$adff") dff_list.push_back(it.first);
203  }
204 
205  for (auto &id : dff_list) {
206  if (mod_it.second->cells_.count(id) > 0 &&
207  handle_dff(mod_it.second, mod_it.second->cells_[id]))
208  total_count++;
209  }
210  }
211 
212  assign_map.clear();
213  mux_drivers.clear();
214 
215  if (total_count)
216  design->scratchpad_set_bool("opt.did_something", true);
217  log("Replaced %d DFF cells.\n", total_count);
218  }
219 } OptRmdffPass;
220 
const char * c_str() const
Definition: rtlil.h:178
bool selected(T1 *module) const
Definition: rtlil.h:551
bool is_fully_undef() const
Definition: rtlil.cc:2789
virtual void help()
Definition: opt_rmdff.cc:153
bool has(RTLIL::SigSpec sig)
Definition: sigtools.h:203
void log_header(const char *format,...)
Definition: log.cc:188
void clear()
Definition: sigtools.h:263
RTLIL::IdString name
Definition: rtlil.h:853
RTLIL::IdString type
Definition: rtlil.h:854
std::map< RTLIL::IdString, RTLIL::Const > parameters
Definition: rtlil.h:856
int size() const
Definition: rtlil.h:1019
#define log_abort()
Definition: log.h:84
void apply(RTLIL::SigBit &bit) const
Definition: sigtools.h:383
void set(RTLIL::Module *module)
Definition: sigtools.h:273
void connect(const RTLIL::SigSig &conn)
Definition: rtlil.cc:1278
#define PRIVATE_NAMESPACE_BEGIN
Definition: yosys.h:97
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
Definition: rtlil.cc:1809
void clear()
Definition: sigtools.h:147
bool is_fully_const() const
Definition: rtlil.cc:2763
RTLIL::IdString name
Definition: rtlil.h:599
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN SigMap dff_init_map
Definition: opt_rmdff.cc:29
#define PRIVATE_NAMESPACE_END
Definition: yosys.h:98
Definition: register.h:27
std::string substr(size_t pos=0, size_t len=std::string::npos) const
Definition: rtlil.h:208
#define USING_YOSYS_NAMESPACE
Definition: yosys.h:102
std::map< RTLIL::IdString, RTLIL::Module * > modules_
Definition: rtlil.h:507
bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
Definition: opt_rmdff.cc:32
#define NULL
void remove(const std::set< RTLIL::Wire * > &wires)
Definition: rtlil.cc:1158
SigSet< RTLIL::Cell * > mux_drivers
Definition: opt_rmdff.cc:30
void log(const char *format,...)
Definition: log.cc:180
void scratchpad_set_bool(std::string varname, bool value)
Definition: rtlil.cc:296
std::vector< RTLIL::State > bits
Definition: rtlil.h:438
void add(RTLIL::SigSpec from, RTLIL::SigSpec to)
Definition: sigtools.h:347
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
Definition: register.cc:128
std::pair< SigSpec, SigSpec > SigSig
Definition: rtlil.h:71
void find(RTLIL::SigSpec sig, std::set< T > &result)
Definition: sigtools.h:187
void insert(RTLIL::SigSpec sig, T data)
Definition: sigtools.h:152
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)
Definition: opt_rmdff.cc:163
OptRmdffPass OptRmdffPass
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN SigMap assign_map
Definition: opt_rmdff.cc:29