yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
proc_mux.cc File Reference
#include "kernel/register.h"
#include "kernel/bitpattern.h"
#include "kernel/log.h"
#include <sstream>
#include <stdlib.h>
#include <stdio.h>
+ Include dependency graph for proc_mux.cc:

Go to the source code of this file.

Data Structures

struct  ProcMuxPass
 

Functions

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
RTLIL::SigSpec 
find_any_lvalue (const RTLIL::CaseRule *cs)
 
void extract_core_signal (const RTLIL::CaseRule *cs, RTLIL::SigSpec &sig)
 
RTLIL::SigSpec gen_cmp (RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector< RTLIL::SigSpec > &compare, RTLIL::SwitchRule *sw)
 
RTLIL::SigSpec gen_mux (RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector< RTLIL::SigSpec > &compare, RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal, RTLIL::Cell *&last_mux_cell, RTLIL::SwitchRule *sw)
 
void append_pmux (RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector< RTLIL::SigSpec > &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw)
 
RTLIL::SigSpec signal_to_mux_tree (RTLIL::Module *mod, RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval)
 
void proc_mux (RTLIL::Module *mod, RTLIL::Process *proc)
 

Variables

ProcMuxPass ProcMuxPass
 

Function Documentation

void append_pmux ( RTLIL::Module mod,
const RTLIL::SigSpec signal,
const std::vector< RTLIL::SigSpec > &  compare,
RTLIL::SigSpec  when_signal,
RTLIL::Cell last_mux_cell,
RTLIL::SwitchRule sw 
)

Definition at line 162 of file proc_mux.cc.

163 {
164  log_assert(last_mux_cell != NULL);
165  log_assert(when_signal.size() == last_mux_cell->getPort("\\A").size());
166 
167  RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw);
168  log_assert(ctrl_sig.size() == 1);
169  last_mux_cell->type = "$pmux";
170 
171  RTLIL::SigSpec new_s = last_mux_cell->getPort("\\S");
172  new_s.append(ctrl_sig);
173  last_mux_cell->setPort("\\S", new_s);
174 
175  RTLIL::SigSpec new_b = last_mux_cell->getPort("\\B");
176  new_b.append(when_signal);
177  last_mux_cell->setPort("\\B", new_b);
178 
179  last_mux_cell->parameters["\\S_WIDTH"] = last_mux_cell->getPort("\\S").size();
180 }
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
Definition: rtlil.cc:1789
RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector< RTLIL::SigSpec > &compare, RTLIL::SwitchRule *sw)
Definition: proc_mux.cc:60
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
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
Definition: rtlil.cc:1809
#define log_assert(_assert_expr_)
Definition: log.h:85
#define NULL
void append(const RTLIL::SigSpec &signal)
Definition: rtlil.cc:2523

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void extract_core_signal ( const RTLIL::CaseRule cs,
RTLIL::SigSpec sig 
)

Definition at line 47 of file proc_mux.cc.

48 {
49  for (auto &action : cs->actions) {
50  RTLIL::SigSpec lvalue = action.first.extract(sig);
51  if (lvalue.size())
52  sig = lvalue;
53  }
54 
55  for (auto sw : cs->switches)
56  for (auto cs2 : sw->cases)
57  extract_core_signal(cs2, sig);
58 }
int size() const
Definition: rtlil.h:1019
void extract_core_signal(const RTLIL::CaseRule *cs, RTLIL::SigSpec &sig)
Definition: proc_mux.cc:47
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other=NULL) const
Definition: rtlil.cc:2414
std::vector< RTLIL::SigSig > actions
Definition: rtlil.h:1120
std::vector< RTLIL::SwitchRule * > switches
Definition: rtlil.h:1121

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Definition at line 30 of file proc_mux.cc.

31 {
32  for (auto &action : cs->actions) {
33  if (action.first.size())
34  return action.first;
35  }
36 
37  for (auto sw : cs->switches)
38  for (auto cs2 : sw->cases) {
40  if (sig.size())
41  return sig;
42  }
43 
44  return RTLIL::SigSpec();
45 }
int size() const
Definition: rtlil.h:1019
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN RTLIL::SigSpec find_any_lvalue(const RTLIL::CaseRule *cs)
Definition: proc_mux.cc:30
std::vector< RTLIL::SigSig > actions
Definition: rtlil.h:1120
std::vector< RTLIL::SwitchRule * > switches
Definition: rtlil.h:1121

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

RTLIL::SigSpec gen_cmp ( RTLIL::Module mod,
const RTLIL::SigSpec signal,
const std::vector< RTLIL::SigSpec > &  compare,
RTLIL::SwitchRule sw 
)

Definition at line 60 of file proc_mux.cc.

61 {
62  std::stringstream sstr;
63  sstr << "$procmux$" << (autoidx++);
64 
65  RTLIL::Wire *cmp_wire = mod->addWire(sstr.str() + "_CMP", 0);
66 
67  for (auto comp : compare)
68  {
69  RTLIL::SigSpec sig = signal;
70 
71  // get rid of don't-care bits
72  log_assert(sig.size() == comp.size());
73  for (int i = 0; i < comp.size(); i++)
74  if (comp[i] == RTLIL::State::Sa) {
75  sig.remove(i);
76  comp.remove(i--);
77  }
78  if (comp.size() == 0)
79  return RTLIL::SigSpec();
80 
81  if (sig.size() == 1 && comp == RTLIL::SigSpec(1,1))
82  {
83  mod->connect(RTLIL::SigSig(RTLIL::SigSpec(cmp_wire, cmp_wire->width++), sig));
84  }
85  else
86  {
87  // create compare cell
88  RTLIL::Cell *eq_cell = mod->addCell(stringf("%s_CMP%d", sstr.str().c_str(), cmp_wire->width), "$eq");
89  eq_cell->attributes = sw->attributes;
90 
91  eq_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
92  eq_cell->parameters["\\B_SIGNED"] = RTLIL::Const(0);
93 
94  eq_cell->parameters["\\A_WIDTH"] = RTLIL::Const(sig.size());
95  eq_cell->parameters["\\B_WIDTH"] = RTLIL::Const(comp.size());
96  eq_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
97 
98  eq_cell->setPort("\\A", sig);
99  eq_cell->setPort("\\B", comp);
100  eq_cell->setPort("\\Y", RTLIL::SigSpec(cmp_wire, cmp_wire->width++));
101  }
102  }
103 
104  RTLIL::Wire *ctrl_wire;
105  if (cmp_wire->width == 1)
106  {
107  ctrl_wire = cmp_wire;
108  }
109  else
110  {
111  ctrl_wire = mod->addWire(sstr.str() + "_CTRL");
112 
113  // reduce cmp vector to one logic signal
114  RTLIL::Cell *any_cell = mod->addCell(sstr.str() + "_ANY", "$reduce_or");
115  any_cell->attributes = sw->attributes;
116 
117  any_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
118  any_cell->parameters["\\A_WIDTH"] = RTLIL::Const(cmp_wire->width);
119  any_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
120 
121  any_cell->setPort("\\A", cmp_wire);
122  any_cell->setPort("\\Y", RTLIL::SigSpec(ctrl_wire));
123  }
124 
125  return RTLIL::SigSpec(ctrl_wire);
126 }
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
Definition: rtlil.cc:1353
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
Definition: rtlil.cc:1789
std::map< RTLIL::IdString, RTLIL::Const > parameters
Definition: rtlil.h:856
int size() const
Definition: rtlil.h:1019
void remove(const RTLIL::SigSpec &pattern)
Definition: rtlil.cc:2342
void connect(const RTLIL::SigSig &conn)
Definition: rtlil.cc:1278
#define log_assert(_assert_expr_)
Definition: log.h:85
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
Definition: rtlil.cc:1331
std::pair< SigSpec, SigSpec > SigSig
Definition: rtlil.h:71
YOSYS_NAMESPACE_BEGIN int autoidx
Definition: yosys.cc:51

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

RTLIL::SigSpec gen_mux ( RTLIL::Module mod,
const RTLIL::SigSpec signal,
const std::vector< RTLIL::SigSpec > &  compare,
RTLIL::SigSpec  when_signal,
RTLIL::SigSpec  else_signal,
RTLIL::Cell *&  last_mux_cell,
RTLIL::SwitchRule sw 
)

Definition at line 128 of file proc_mux.cc.

129 {
130  log_assert(when_signal.size() == else_signal.size());
131 
132  std::stringstream sstr;
133  sstr << "$procmux$" << (autoidx++);
134 
135  // the trivial cases
136  if (compare.size() == 0 || when_signal == else_signal)
137  return when_signal;
138 
139  // compare results
140  RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw);
141  if (ctrl_sig.size() == 0)
142  return when_signal;
143  log_assert(ctrl_sig.size() == 1);
144 
145  // prepare multiplexer output signal
146  RTLIL::Wire *result_wire = mod->addWire(sstr.str() + "_Y", when_signal.size());
147 
148  // create the multiplexer itself
149  RTLIL::Cell *mux_cell = mod->addCell(sstr.str(), "$mux");
150  mux_cell->attributes = sw->attributes;
151 
152  mux_cell->parameters["\\WIDTH"] = RTLIL::Const(when_signal.size());
153  mux_cell->setPort("\\A", else_signal);
154  mux_cell->setPort("\\B", when_signal);
155  mux_cell->setPort("\\S", ctrl_sig);
156  mux_cell->setPort("\\Y", RTLIL::SigSpec(result_wire));
157 
158  last_mux_cell = mux_cell;
159  return RTLIL::SigSpec(result_wire);
160 }
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
Definition: rtlil.cc:1353
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
Definition: rtlil.cc:1789
RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector< RTLIL::SigSpec > &compare, RTLIL::SwitchRule *sw)
Definition: proc_mux.cc:60
std::map< RTLIL::IdString, RTLIL::Const > parameters
Definition: rtlil.h:856
int size() const
Definition: rtlil.h:1019
#define log_assert(_assert_expr_)
Definition: log.h:85
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
Definition: rtlil.cc:1331
YOSYS_NAMESPACE_BEGIN int autoidx
Definition: yosys.cc:51

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void proc_mux ( RTLIL::Module mod,
RTLIL::Process proc 
)

Definition at line 239 of file proc_mux.cc.

240 {
241  bool first = true;
242  while (1)
243  {
245 
246  if (sig.size() == 0)
247  break;
248 
249  if (first) {
250  log("Creating decoders for process `%s.%s'.\n", mod->name.c_str(), proc->name.c_str());
251  first = false;
252  }
253 
254  extract_core_signal(&proc->root_case, sig);
255 
256  log(" creating decoder for signal `%s'.\n", log_signal(sig));
257 
259  mod->connect(RTLIL::SigSig(sig, value));
260  }
261 }
const char * c_str() const
Definition: rtlil.h:178
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
Definition: log.cc:269
int size() const
Definition: rtlil.h:1019
void connect(const RTLIL::SigSig &conn)
Definition: rtlil.cc:1278
RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval)
Definition: proc_mux.cc:182
RTLIL::IdString name
Definition: rtlil.h:599
RTLIL::IdString name
Definition: rtlil.h:1154
void extract_core_signal(const RTLIL::CaseRule *cs, RTLIL::SigSpec &sig)
Definition: proc_mux.cc:47
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN RTLIL::SigSpec find_any_lvalue(const RTLIL::CaseRule *cs)
Definition: proc_mux.cc:30
void log(const char *format,...)
Definition: log.cc:180
std::pair< SigSpec, SigSpec > SigSig
Definition: rtlil.h:71
RTLIL_ATTRIBUTE_MEMBERS RTLIL::CaseRule root_case
Definition: rtlil.h:1156

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

RTLIL::SigSpec signal_to_mux_tree ( RTLIL::Module mod,
RTLIL::CaseRule cs,
const RTLIL::SigSpec sig,
const RTLIL::SigSpec defval 
)

Definition at line 182 of file proc_mux.cc.

183 {
184  RTLIL::SigSpec result = defval;
185 
186  for (auto &action : cs->actions) {
187  sig.replace(action.first, action.second, &result);
188  action.first.remove2(sig, &action.second);
189  }
190 
191  for (auto sw : cs->switches)
192  {
193  // detect groups of parallel cases
194  std::vector<int> pgroups(sw->cases.size());
195  if (!sw->get_bool_attribute("\\parallel_case")) {
196  BitPatternPool pool(sw->signal.size());
197  bool extra_group_for_next_case = false;
198  for (size_t i = 0; i < sw->cases.size(); i++) {
199  RTLIL::CaseRule *cs2 = sw->cases[i];
200  if (i != 0) {
201  pgroups[i] = pgroups[i-1];
202  if (extra_group_for_next_case) {
203  pgroups[i] = pgroups[i-1]+1;
204  extra_group_for_next_case = false;
205  }
206  for (auto pat : cs2->compare)
207  if (!pat.is_fully_const() || !pool.has_all(pat))
208  pgroups[i] = pgroups[i-1]+1;
209  if (cs2->compare.empty())
210  pgroups[i] = pgroups[i-1]+1;
211  if (pgroups[i] != pgroups[i-1])
212  pool = BitPatternPool(sw->signal.size());
213  }
214  for (auto pat : cs2->compare)
215  if (!pat.is_fully_const())
216  extra_group_for_next_case = true;
217  else
218  pool.take(pat);
219  }
220  }
221 
222  // evaluate in reverse order to give the first entry the top priority
223  RTLIL::SigSpec initial_val = result;
224  RTLIL::Cell *last_mux_cell = NULL;
225  for (size_t i = 0; i < sw->cases.size(); i++) {
226  int case_idx = sw->cases.size() - i - 1;
227  RTLIL::CaseRule *cs2 = sw->cases[case_idx];
228  RTLIL::SigSpec value = signal_to_mux_tree(mod, cs2, sig, initial_val);
229  if (last_mux_cell && pgroups[case_idx] == pgroups[case_idx+1])
230  append_pmux(mod, sw->signal, cs2->compare, value, last_mux_cell, sw);
231  else
232  result = gen_mux(mod, sw->signal, cs2->compare, value, result, last_mux_cell, sw);
233  }
234  }
235 
236  return result;
237 }
std::vector< RTLIL::SigSpec > compare
Definition: rtlil.h:1119
void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector< RTLIL::SigSpec > &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw)
Definition: proc_mux.cc:162
RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval)
Definition: proc_mux.cc:182
void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with)
Definition: rtlil.cc:2297
#define NULL
std::vector< RTLIL::SigSig > actions
Definition: rtlil.h:1120
bool take(RTLIL::SigSpec sig)
Definition: bitpattern.h:102
std::vector< RTLIL::SwitchRule * > switches
Definition: rtlil.h:1121
RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector< RTLIL::SigSpec > &compare, RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal, RTLIL::Cell *&last_mux_cell, RTLIL::SwitchRule *sw)
Definition: proc_mux.cc:128

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation