yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
proc_dff.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/consteval.h"
23 #include "kernel/log.h"
24 #include <sstream>
25 #include <stdlib.h>
26 #include <stdio.h>
27 
30 
32 {
33  RTLIL::SigSpec lvalue;
34 
35  for (auto sync : proc->syncs)
36  for (auto &action : sync->actions)
37  if (action.first.size() > 0) {
38  lvalue = action.first;
39  lvalue.sort_and_unify();
40  break;
41  }
42 
43  for (auto sync : proc->syncs) {
44  RTLIL::SigSpec this_lvalue;
45  for (auto &action : sync->actions)
46  this_lvalue.append(action.first);
47  this_lvalue.sort_and_unify();
48  RTLIL::SigSpec common_sig = this_lvalue.extract(lvalue);
49  if (common_sig.size() > 0)
50  lvalue = common_sig;
51  }
52 
53  return lvalue;
54 }
55 
57  std::map<RTLIL::SigSpec, std::set<RTLIL::SyncRule*>> &async_rules, RTLIL::Process *proc)
58 {
59  RTLIL::SigSpec sig_sr_set = RTLIL::SigSpec(0, sig_d.size());
60  RTLIL::SigSpec sig_sr_clr = RTLIL::SigSpec(0, sig_d.size());
61 
62  for (auto &it : async_rules)
63  {
64  RTLIL::SigSpec sync_value = it.first;
65  RTLIL::SigSpec sync_value_inv;
66  RTLIL::SigSpec sync_high_signals;
67  RTLIL::SigSpec sync_low_signals;
68 
69  for (auto &it2 : it.second)
70  if (it2->type == RTLIL::SyncType::ST0)
71  sync_low_signals.append(it2->signal);
72  else if (it2->type == RTLIL::SyncType::ST1)
73  sync_high_signals.append(it2->signal);
74  else
75  log_abort();
76 
77  if (sync_low_signals.size() > 1) {
78  RTLIL::Cell *cell = mod->addCell(NEW_ID, "$reduce_or");
79  cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
80  cell->parameters["\\A_WIDTH"] = RTLIL::Const(sync_low_signals.size());
81  cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
82  cell->setPort("\\A", sync_low_signals);
83  cell->setPort("\\Y", sync_low_signals = mod->addWire(NEW_ID));
84  }
85 
86  if (sync_low_signals.size() > 0) {
87  RTLIL::Cell *cell = mod->addCell(NEW_ID, "$not");
88  cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
89  cell->parameters["\\A_WIDTH"] = RTLIL::Const(sync_low_signals.size());
90  cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
91  cell->setPort("\\A", sync_low_signals);
92  cell->setPort("\\Y", mod->addWire(NEW_ID));
93  sync_high_signals.append(cell->getPort("\\Y"));
94  }
95 
96  if (sync_high_signals.size() > 1) {
97  RTLIL::Cell *cell = mod->addCell(NEW_ID, "$reduce_or");
98  cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
99  cell->parameters["\\A_WIDTH"] = RTLIL::Const(sync_high_signals.size());
100  cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
101  cell->setPort("\\A", sync_high_signals);
102  cell->setPort("\\Y", sync_high_signals = mod->addWire(NEW_ID));
103  }
104 
105  RTLIL::Cell *inv_cell = mod->addCell(NEW_ID, "$not");
106  inv_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
107  inv_cell->parameters["\\A_WIDTH"] = RTLIL::Const(sig_d.size());
108  inv_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(sig_d.size());
109  inv_cell->setPort("\\A", sync_value);
110  inv_cell->setPort("\\Y", sync_value_inv = mod->addWire(NEW_ID, sig_d.size()));
111 
112  RTLIL::Cell *mux_set_cell = mod->addCell(NEW_ID, "$mux");
113  mux_set_cell->parameters["\\WIDTH"] = RTLIL::Const(sig_d.size());
114  mux_set_cell->setPort("\\A", sig_sr_set);
115  mux_set_cell->setPort("\\B", sync_value);
116  mux_set_cell->setPort("\\S", sync_high_signals);
117  mux_set_cell->setPort("\\Y", sig_sr_set = mod->addWire(NEW_ID, sig_d.size()));
118 
119  RTLIL::Cell *mux_clr_cell = mod->addCell(NEW_ID, "$mux");
120  mux_clr_cell->parameters["\\WIDTH"] = RTLIL::Const(sig_d.size());
121  mux_clr_cell->setPort("\\A", sig_sr_clr);
122  mux_clr_cell->setPort("\\B", sync_value_inv);
123  mux_clr_cell->setPort("\\S", sync_high_signals);
124  mux_clr_cell->setPort("\\Y", sig_sr_clr = mod->addWire(NEW_ID, sig_d.size()));
125  }
126 
127  std::stringstream sstr;
128  sstr << "$procdff$" << (autoidx++);
129 
130  RTLIL::Cell *cell = mod->addCell(sstr.str(), "$dffsr");
131  cell->attributes = proc->attributes;
132  cell->parameters["\\WIDTH"] = RTLIL::Const(sig_d.size());
133  cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity, 1);
134  cell->parameters["\\SET_POLARITY"] = RTLIL::Const(true, 1);
135  cell->parameters["\\CLR_POLARITY"] = RTLIL::Const(true, 1);
136  cell->setPort("\\D", sig_d);
137  cell->setPort("\\Q", sig_q);
138  cell->setPort("\\CLK", clk);
139  cell->setPort("\\SET", sig_sr_set);
140  cell->setPort("\\CLR", sig_sr_clr);
141 
142  log(" created %s cell `%s' with %s edge clock and multiple level-sensitive resets.\n",
143  cell->type.c_str(), cell->name.c_str(), clk_polarity ? "positive" : "negative");
144 }
145 
147  bool clk_polarity, bool set_polarity, RTLIL::SigSpec clk, RTLIL::SigSpec set, RTLIL::Process *proc)
148 {
149  std::stringstream sstr;
150  sstr << "$procdff$" << (autoidx++);
151 
152  RTLIL::SigSpec sig_set_inv = mod->addWire(NEW_ID, sig_in.size());
153  RTLIL::SigSpec sig_sr_set = mod->addWire(NEW_ID, sig_in.size());
154  RTLIL::SigSpec sig_sr_clr = mod->addWire(NEW_ID, sig_in.size());
155 
156  RTLIL::Cell *inv_set = mod->addCell(NEW_ID, "$not");
157  inv_set->parameters["\\A_SIGNED"] = RTLIL::Const(0);
158  inv_set->parameters["\\A_WIDTH"] = RTLIL::Const(sig_in.size());
159  inv_set->parameters["\\Y_WIDTH"] = RTLIL::Const(sig_in.size());
160  inv_set->setPort("\\A", sig_set);
161  inv_set->setPort("\\Y", sig_set_inv);
162 
163  RTLIL::Cell *mux_sr_set = mod->addCell(NEW_ID, "$mux");
164  mux_sr_set->parameters["\\WIDTH"] = RTLIL::Const(sig_in.size());
165  mux_sr_set->setPort(set_polarity ? "\\A" : "\\B", RTLIL::Const(0, sig_in.size()));
166  mux_sr_set->setPort(set_polarity ? "\\B" : "\\A", sig_set);
167  mux_sr_set->setPort("\\Y", sig_sr_set);
168  mux_sr_set->setPort("\\S", set);
169 
170  RTLIL::Cell *mux_sr_clr = mod->addCell(NEW_ID, "$mux");
171  mux_sr_clr->parameters["\\WIDTH"] = RTLIL::Const(sig_in.size());
172  mux_sr_clr->setPort(set_polarity ? "\\A" : "\\B", RTLIL::Const(0, sig_in.size()));
173  mux_sr_clr->setPort(set_polarity ? "\\B" : "\\A", sig_set_inv);
174  mux_sr_clr->setPort("\\Y", sig_sr_clr);
175  mux_sr_clr->setPort("\\S", set);
176 
177  RTLIL::Cell *cell = mod->addCell(sstr.str(), "$dffsr");
178  cell->attributes = proc->attributes;
179  cell->parameters["\\WIDTH"] = RTLIL::Const(sig_in.size());
180  cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity, 1);
181  cell->parameters["\\SET_POLARITY"] = RTLIL::Const(true, 1);
182  cell->parameters["\\CLR_POLARITY"] = RTLIL::Const(true, 1);
183  cell->setPort("\\D", sig_in);
184  cell->setPort("\\Q", sig_out);
185  cell->setPort("\\CLK", clk);
186  cell->setPort("\\SET", sig_sr_set);
187  cell->setPort("\\CLR", sig_sr_clr);
188 
189  log(" created %s cell `%s' with %s edge clock and %s level non-const reset.\n", cell->type.c_str(), cell->name.c_str(),
190  clk_polarity ? "positive" : "negative", set_polarity ? "positive" : "negative");
191 }
192 
193 void gen_dff(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::Const val_rst, RTLIL::SigSpec sig_out,
194  bool clk_polarity, bool arst_polarity, RTLIL::SigSpec clk, RTLIL::SigSpec *arst, RTLIL::Process *proc)
195 {
196  std::stringstream sstr;
197  sstr << "$procdff$" << (autoidx++);
198 
199  RTLIL::Cell *cell = mod->addCell(sstr.str(), arst ? "$adff" : "$dff");
200  cell->attributes = proc->attributes;
201 
202  cell->parameters["\\WIDTH"] = RTLIL::Const(sig_in.size());
203  if (arst) {
204  cell->parameters["\\ARST_POLARITY"] = RTLIL::Const(arst_polarity, 1);
205  cell->parameters["\\ARST_VALUE"] = val_rst;
206  }
207  cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity, 1);
208 
209  cell->setPort("\\D", sig_in);
210  cell->setPort("\\Q", sig_out);
211  if (arst)
212  cell->setPort("\\ARST", *arst);
213  cell->setPort("\\CLK", clk);
214 
215  log(" created %s cell `%s' with %s edge clock", cell->type.c_str(), cell->name.c_str(), clk_polarity ? "positive" : "negative");
216  if (arst)
217  log(" and %s level reset", arst_polarity ? "positive" : "negative");
218  log(".\n");
219 }
220 
222 {
223  while (1)
224  {
225  RTLIL::SigSpec sig = find_any_lvalue(proc);
226  bool free_sync_level = false;
227 
228  if (sig.size() == 0)
229  break;
230 
231  log("Creating register for signal `%s.%s' using process `%s.%s'.\n",
232  mod->name.c_str(), log_signal(sig), mod->name.c_str(), proc->name.c_str());
233 
236  RTLIL::SyncRule *sync_level = NULL;
237  RTLIL::SyncRule *sync_edge = NULL;
238  RTLIL::SyncRule *sync_always = NULL;
239 
240  std::map<RTLIL::SigSpec, std::set<RTLIL::SyncRule*>> many_async_rules;
241 
242  for (auto sync : proc->syncs)
243  for (auto &action : sync->actions)
244  {
245  if (action.first.extract(sig).size() == 0)
246  continue;
247 
248  if (sync->type == RTLIL::SyncType::ST0 || sync->type == RTLIL::SyncType::ST1) {
249  if (sync_level != NULL && sync_level != sync) {
250  // log_error("Multiple level sensitive events found for this signal!\n");
251  many_async_rules[rstval].insert(sync_level);
252  rstval = RTLIL::SigSpec(RTLIL::State::Sz, sig.size());
253  }
254  rstval = RTLIL::SigSpec(RTLIL::State::Sz, sig.size());
255  sig.replace(action.first, action.second, &rstval);
256  sync_level = sync;
257  }
258  else if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn) {
259  if (sync_edge != NULL && sync_edge != sync)
260  log_error("Multiple edge sensitive events found for this signal!\n");
261  sig.replace(action.first, action.second, &insig);
262  sync_edge = sync;
263  }
264  else if (sync->type == RTLIL::SyncType::STa) {
265  if (sync_always != NULL && sync_always != sync)
266  log_error("Multiple always events found for this signal!\n");
267  sig.replace(action.first, action.second, &insig);
268  sync_always = sync;
269  }
270  else {
271  log_error("Event with any-edge sensitivity found for this signal!\n");
272  }
273 
274  action.first.remove2(sig, &action.second);
275  }
276 
277  if (many_async_rules.size() > 0)
278  {
279  many_async_rules[rstval].insert(sync_level);
280  if (many_async_rules.size() == 1)
281  {
282  sync_level = new RTLIL::SyncRule;
283  sync_level->type = RTLIL::SyncType::ST1;
284  sync_level->signal = mod->addWire(NEW_ID);
285  sync_level->actions.push_back(RTLIL::SigSig(sig, rstval));
286  free_sync_level = true;
287 
288  RTLIL::SigSpec inputs, compare;
289  for (auto &it : many_async_rules[rstval]) {
290  inputs.append(it->signal);
292  }
293  log_assert(inputs.size() == compare.size());
294 
295  RTLIL::Cell *cell = mod->addCell(NEW_ID, "$ne");
296  cell->parameters["\\A_SIGNED"] = RTLIL::Const(false, 1);
297  cell->parameters["\\B_SIGNED"] = RTLIL::Const(false, 1);
298  cell->parameters["\\A_WIDTH"] = RTLIL::Const(inputs.size());
299  cell->parameters["\\B_WIDTH"] = RTLIL::Const(inputs.size());
300  cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
301  cell->setPort("\\A", inputs);
302  cell->setPort("\\B", compare);
303  cell->setPort("\\Y", sync_level->signal);
304 
305  many_async_rules.clear();
306  }
307  else
308  {
309  rstval = RTLIL::SigSpec(RTLIL::State::Sz, sig.size());
310  sync_level = NULL;
311  }
312  }
313 
314  ce.assign_map.apply(insig);
315  ce.assign_map.apply(rstval);
316  ce.assign_map.apply(sig);
317 
318  if (rstval == sig) {
319  rstval = RTLIL::SigSpec(RTLIL::State::Sz, sig.size());
320  sync_level = NULL;
321  }
322 
323  if (sync_always) {
324  if (sync_edge || sync_level || many_async_rules.size() > 0)
325  log_error("Mixed always event with edge and/or level sensitive events!\n");
326  log(" created direct connection (no actual register cell created).\n");
327  mod->connect(RTLIL::SigSig(sig, insig));
328  continue;
329  }
330 
331  if (!sync_edge)
332  log_error("Missing edge-sensitive event for this signal!\n");
333 
334  if (many_async_rules.size() > 0)
335  {
336  log_warning("Complex async reset for dff `%s'.\n", log_signal(sig));
337  gen_dffsr_complex(mod, insig, sig, sync_edge->signal, sync_edge->type == RTLIL::SyncType::STp, many_async_rules, proc);
338  }
339  else if (!rstval.is_fully_const() && !ce.eval(rstval))
340  {
341  log_warning("Async reset value `%s' is not constant!\n", log_signal(rstval));
342  gen_dffsr(mod, insig, rstval, sig,
343  sync_edge->type == RTLIL::SyncType::STp,
344  sync_level && sync_level->type == RTLIL::SyncType::ST1,
345  sync_edge->signal, sync_level->signal, proc);
346  }
347  else
348  gen_dff(mod, insig, rstval.as_const(), sig,
349  sync_edge->type == RTLIL::SyncType::STp,
350  sync_level && sync_level->type == RTLIL::SyncType::ST1,
351  sync_edge->signal, sync_level ? &sync_level->signal : NULL, proc);
352 
353  if (free_sync_level)
354  delete sync_level;
355  }
356 }
357 
358 struct ProcDffPass : public Pass {
359  ProcDffPass() : Pass("proc_dff", "extract flip-flops from processes") { }
360  virtual void help()
361  {
362  // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
363  log("\n");
364  log(" proc_dff [selection]\n");
365  log("\n");
366  log("This pass identifies flip-flops in the processes and converts them to\n");
367  log("d-type flip-flop cells.\n");
368  log("\n");
369  }
370  virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
371  {
372  log_header("Executing PROC_DFF pass (convert process syncs to FFs).\n");
373 
374  extra_args(args, 1, design);
375 
376  for (auto mod : design->modules())
377  if (design->selected(mod)) {
378  ConstEval ce(mod);
379  for (auto &proc_it : mod->processes)
380  if (design->selected(mod, proc_it.second))
381  proc_dff(mod, proc_it.second, ce);
382  }
383  }
384 } ProcDffPass;
385 
const char * c_str() const
Definition: rtlil.h:178
bool selected(T1 *module) const
Definition: rtlil.h:551
void gen_dffsr(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_out, bool clk_polarity, bool set_polarity, RTLIL::SigSpec clk, RTLIL::SigSpec set, RTLIL::Process *proc)
Definition: proc_dff.cc:146
void log_warning(const char *format,...)
Definition: log.cc:196
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
Definition: rtlil.cc:1353
bool clk_polarity
Definition: abc.cc:98
void log_header(const char *format,...)
Definition: log.cc:188
RTLIL::SyncType type
Definition: rtlil.h:1144
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
Definition: log.cc:269
RTLIL::IdString name
Definition: rtlil.h:853
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
Definition: rtlil.cc:1789
bool eval(RTLIL::Cell *cell, RTLIL::SigSpec &undef)
Definition: consteval.h:89
SigMap assign_map
Definition: consteval.h:33
void log_error(const char *format,...)
Definition: log.cc:204
RTLIL::IdString type
Definition: rtlil.h:854
std::map< RTLIL::IdString, RTLIL::Const > parameters
Definition: rtlil.h:856
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)
Definition: proc_dff.cc:370
RTLIL::SigSpec signal
Definition: rtlil.h:1145
int size() const
Definition: rtlil.h:1019
#define log_abort()
Definition: log.h:84
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN RTLIL::SigSpec find_any_lvalue(const RTLIL::Process *proc)
Definition: proc_dff.cc:31
void apply(RTLIL::SigBit &bit) const
Definition: sigtools.h:383
virtual void help()
Definition: proc_dff.cc:360
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
#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
#define NEW_ID
Definition: yosys.h:166
#define PRIVATE_NAMESPACE_END
Definition: yosys.h:98
Definition: register.h:27
RTLIL::IdString name
Definition: rtlil.h:1154
void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce)
Definition: proc_dff.cc:221
#define USING_YOSYS_NAMESPACE
Definition: yosys.h:102
RTLIL::ObjRange< RTLIL::Module * > modules()
Definition: rtlil.cc:249
void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with)
Definition: rtlil.cc:2297
void gen_dff(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::Const val_rst, RTLIL::SigSpec sig_out, bool clk_polarity, bool arst_polarity, RTLIL::SigSpec clk, RTLIL::SigSpec *arst, RTLIL::Process *proc)
Definition: proc_dff.cc:193
void sort_and_unify()
Definition: rtlil.cc:2291
#define NULL
void log(const char *format,...)
Definition: log.cc:180
std::vector< RTLIL::SyncRule * > syncs
Definition: rtlil.h:1157
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other=NULL) const
Definition: rtlil.cc:2414
void append(const RTLIL::SigSpec &signal)
Definition: rtlil.cc:2523
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
ProcDffPass ProcDffPass
YOSYS_NAMESPACE_BEGIN int autoidx
Definition: yosys.cc:51
void gen_dffsr_complex(RTLIL::Module *mod, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, RTLIL::SigSpec clk, bool clk_polarity, std::map< RTLIL::SigSpec, std::set< RTLIL::SyncRule * >> &async_rules, RTLIL::Process *proc)
Definition: proc_dff.cc:56