yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
OptMuxtreeWorker Struct Reference
+ Collaboration diagram for OptMuxtreeWorker:

Data Structures

struct  bitDef_t
 
struct  bitinfo_t
 
struct  knowledge_t
 
struct  muxinfo_t
 
struct  portinfo_t
 

Public Member Functions

 OptMuxtreeWorker (RTLIL::Design *design, RTLIL::Module *module)
 
bool list_is_subset (const std::vector< int > &sub, const std::vector< int > &super)
 
bool is_in_list (const std::vector< int > &list, int value)
 
void add_to_list (std::vector< int > &list, int value)
 
std::vector< int > sig2bits (RTLIL::SigSpec sig)
 
void eval_mux_port (knowledge_t &knowledge, int mux_idx, int port_idx)
 
void eval_mux (knowledge_t &knowledge, int mux_idx)
 
void eval_root_mux (int mux_idx)
 

Data Fields

RTLIL::Designdesign
 
RTLIL::Modulemodule
 
SigMap assign_map
 
int removed_count
 
std::map< bitDef_t, int > bit2num
 
std::vector< bitinfo_tbit2info
 
std::vector< muxinfo_tmux2info
 

Detailed Description

Definition at line 33 of file opt_muxtree.cc.

Constructor & Destructor Documentation

OptMuxtreeWorker::OptMuxtreeWorker ( RTLIL::Design design,
RTLIL::Module module 
)
inline

Definition at line 72 of file opt_muxtree.cc.

72  :
73  design(design), module(module), assign_map(module), removed_count(0)
74  {
75  log("Running muxtree optimizier on module %s..\n", module->name.c_str());
76 
77  log(" Creating internal representation of mux trees.\n");
78 
79  // Populate bit2info[]:
80  // .seen_non_mux
81  // .mux_users
82  // .mux_drivers
83  // Populate mux2info[].ports[]:
84  // .ctrl_sigs
85  // .input_sigs
86  // .const_activated
87  for (auto cell : module->cells())
88  {
89  if (cell->type == "$mux" || cell->type == "$pmux")
90  {
91  RTLIL::SigSpec sig_a = cell->getPort("\\A");
92  RTLIL::SigSpec sig_b = cell->getPort("\\B");
93  RTLIL::SigSpec sig_s = cell->getPort("\\S");
94  RTLIL::SigSpec sig_y = cell->getPort("\\Y");
95 
96  muxinfo_t muxinfo;
97  muxinfo.cell = cell;
98 
99  for (int i = 0; i < sig_s.size(); i++) {
100  RTLIL::SigSpec sig = sig_b.extract(i*sig_a.size(), sig_a.size());
101  RTLIL::SigSpec ctrl_sig = assign_map(sig_s.extract(i, 1));
102  portinfo_t portinfo;
103  for (int idx : sig2bits(sig)) {
104  add_to_list(bit2info[idx].mux_users, mux2info.size());
105  add_to_list(portinfo.input_sigs, idx);
106  }
107  for (int idx : sig2bits(ctrl_sig))
108  add_to_list(portinfo.ctrl_sigs, idx);
109  portinfo.const_activated = ctrl_sig.is_fully_const() && ctrl_sig.as_bool();
110  portinfo.enabled = false;
111  muxinfo.ports.push_back(portinfo);
112  }
113 
114  portinfo_t portinfo;
115  for (int idx : sig2bits(sig_a)) {
116  add_to_list(bit2info[idx].mux_users, mux2info.size());
117  add_to_list(portinfo.input_sigs, idx);
118  }
119  portinfo.const_activated = false;
120  portinfo.enabled = false;
121  muxinfo.ports.push_back(portinfo);
122 
123  for (int idx : sig2bits(sig_y))
125 
126  for (int idx : sig2bits(sig_s))
127  bit2info[idx].seen_non_mux = true;
128 
129  mux2info.push_back(muxinfo);
130  }
131  else
132  {
133  for (auto &it : cell->connections()) {
134  for (int idx : sig2bits(it.second))
135  bit2info[idx].seen_non_mux = true;
136  }
137  }
138  }
139  for (auto wire : module->wires()) {
140  if (wire->port_output)
141  for (int idx : sig2bits(RTLIL::SigSpec(wire)))
142  bit2info[idx].seen_non_mux = true;
143  }
144 
145  if (mux2info.size() == 0) {
146  log(" No muxes found in this module.\n");
147  return;
148  }
149 
150  // Populate mux2info[].ports[]:
151  // .input_muxes
152  for (size_t i = 0; i < bit2info.size(); i++)
153  for (int j : bit2info[i].mux_users)
154  for (auto &p : mux2info[j].ports) {
155  if (is_in_list(p.input_sigs, i))
156  for (int k : bit2info[i].mux_drivers)
157  add_to_list(p.input_muxes, k);
158  }
159 
160  log(" Evaluating internal representation of mux trees.\n");
161 
162  std::set<int> root_muxes;
163  for (auto &bi : bit2info) {
164  if (!bi.seen_non_mux)
165  continue;
166  for (int mux_idx : bi.mux_drivers)
167  root_muxes.insert(mux_idx);
168  }
169  for (int mux_idx : root_muxes)
170  eval_root_mux(mux_idx);
171 
172  log(" Analyzing evaluation results.\n");
173 
174  for (auto &mi : mux2info)
175  {
176  std::vector<int> live_ports;
177  for (int port_idx = 0; port_idx < GetSize(mi.ports); port_idx++) {
178  portinfo_t &pi = mi.ports[port_idx];
179  if (pi.enabled) {
180  live_ports.push_back(port_idx);
181  } else {
182  log(" dead port %d/%d on %s %s.\n", port_idx+1, GetSize(mi.ports),
183  mi.cell->type.c_str(), mi.cell->name.c_str());
184  removed_count++;
185  }
186  }
187 
188  if (live_ports.size() == mi.ports.size())
189  continue;
190 
191  if (live_ports.size() == 0) {
192  module->remove(mi.cell);
193  continue;
194  }
195 
196  RTLIL::SigSpec sig_a = mi.cell->getPort("\\A");
197  RTLIL::SigSpec sig_b = mi.cell->getPort("\\B");
198  RTLIL::SigSpec sig_s = mi.cell->getPort("\\S");
199  RTLIL::SigSpec sig_y = mi.cell->getPort("\\Y");
200 
201  RTLIL::SigSpec sig_ports = sig_b;
202  sig_ports.append(sig_a);
203 
204  if (live_ports.size() == 1)
205  {
206  RTLIL::SigSpec sig_in = sig_ports.extract(live_ports[0]*sig_a.size(), sig_a.size());
207  module->connect(RTLIL::SigSig(sig_y, sig_in));
208  module->remove(mi.cell);
209  }
210  else
211  {
212  RTLIL::SigSpec new_sig_a, new_sig_b, new_sig_s;
213 
214  for (size_t i = 0; i < live_ports.size(); i++) {
215  RTLIL::SigSpec sig_in = sig_ports.extract(live_ports[i]*sig_a.size(), sig_a.size());
216  if (i == live_ports.size()-1) {
217  new_sig_a = sig_in;
218  } else {
219  new_sig_b.append(sig_in);
220  new_sig_s.append(sig_s.extract(live_ports[i], 1));
221  }
222  }
223 
224  mi.cell->setPort("\\A", new_sig_a);
225  mi.cell->setPort("\\B", new_sig_b);
226  mi.cell->setPort("\\S", new_sig_s);
227  if (new_sig_s.size() == 1) {
228  mi.cell->type = "$mux";
229  mi.cell->parameters.erase("\\S_WIDTH");
230  } else {
231  mi.cell->parameters["\\S_WIDTH"] = RTLIL::Const(new_sig_s.size());
232  }
233  }
234  }
235  }
const char * c_str() const
Definition: rtlil.h:178
RTLIL::Design * design
Definition: opt_muxtree.cc:35
std::vector< bitinfo_t > bit2info
Definition: opt_muxtree.cc:55
RTLIL::Module * module
Definition: opt_muxtree.cc:36
bool as_bool() const
Definition: rtlil.cc:2818
static std::string idx(std::string str)
Definition: test_autotb.cc:57
RTLIL::ObjRange< RTLIL::Wire * > wires()
Definition: rtlil.h:640
int size() const
Definition: rtlil.h:1019
std::vector< muxinfo_t > mux2info
Definition: opt_muxtree.cc:70
std::vector< int > sig2bits(RTLIL::SigSpec sig)
Definition: opt_muxtree.cc:259
void add_to_list(std::vector< int > &list, int value)
Definition: opt_muxtree.cc:253
void connect(const RTLIL::SigSig &conn)
Definition: rtlil.cc:1278
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
bool is_fully_const() const
Definition: rtlil.cc:2763
RTLIL::IdString name
Definition: rtlil.h:599
void eval_root_mux(int mux_idx)
Definition: opt_muxtree.cc:396
RTLIL::ObjRange< RTLIL::Cell * > cells()
Definition: rtlil.h:641
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
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
bool is_in_list(const std::vector< int > &list, int value)
Definition: opt_muxtree.cc:245
std::pair< SigSpec, SigSpec > SigSig
Definition: rtlil.h:71

+ Here is the call graph for this function:

Member Function Documentation

void OptMuxtreeWorker::add_to_list ( std::vector< int > &  list,
int  value 
)
inline

Definition at line 253 of file opt_muxtree.cc.

254  {
255  if (!is_in_list(list, value))
256  list.push_back(value);
257  }
bool is_in_list(const std::vector< int > &list, int value)
Definition: opt_muxtree.cc:245

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void OptMuxtreeWorker::eval_mux ( knowledge_t knowledge,
int  mux_idx 
)
inline

Definition at line 334 of file opt_muxtree.cc.

335  {
336  muxinfo_t &muxinfo = mux2info[mux_idx];
337 
338  // if there is a constant activated port we just use it
339  for (size_t port_idx = 0; port_idx < muxinfo.ports.size()-1; port_idx++)
340  {
341  portinfo_t &portinfo = muxinfo.ports[port_idx];
342  if (portinfo.const_activated) {
343  eval_mux_port(knowledge, mux_idx, port_idx);
344  return;
345  }
346  }
347 
348  // compare ports with known_active signals. if we find a match, only this
349  // port can be active. do not include the last port (its the default port
350  // that has no control signals).
351  for (size_t port_idx = 0; port_idx < muxinfo.ports.size()-1; port_idx++)
352  {
353  portinfo_t &portinfo = muxinfo.ports[port_idx];
354  for (size_t i = 0; i < knowledge.known_active.size(); i++) {
355  if (list_is_subset(knowledge.known_active[i], portinfo.ctrl_sigs)) {
356  eval_mux_port(knowledge, mux_idx, port_idx);
357  return;
358  }
359  }
360  }
361 
362  // compare ports with known_inactive and known_active signals. If all control
363  // signals of the port are know_inactive or if the control signals of all other
364  // ports are known_active this port can't be activated. this loop includes the
365  // default port but no known_inactive match is performed on the default port.
366  for (size_t port_idx = 0; port_idx < muxinfo.ports.size(); port_idx++)
367  {
368  portinfo_t &portinfo = muxinfo.ports[port_idx];
369 
370  if (port_idx < muxinfo.ports.size()-1) {
371  bool found_non_known_inactive = false;
372  for (int i : portinfo.ctrl_sigs)
373  if (knowledge.known_inactive[i] == 0)
374  found_non_known_inactive = true;
375  if (!found_non_known_inactive)
376  continue;
377  }
378 
379  bool port_active = true;
380  std::vector<int> other_ctrl_sig;
381  for (size_t i = 0; i < muxinfo.ports.size()-1; i++) {
382  if (i == port_idx)
383  continue;
384  other_ctrl_sig.insert(other_ctrl_sig.end(),
385  muxinfo.ports[i].ctrl_sigs.begin(), muxinfo.ports[i].ctrl_sigs.end());
386  }
387  for (size_t i = 0; i < knowledge.known_active.size(); i++) {
388  if (list_is_subset(knowledge.known_active[i], other_ctrl_sig))
389  port_active = false;
390  }
391  if (port_active)
392  eval_mux_port(knowledge, mux_idx, port_idx);
393  }
394  }
bool list_is_subset(const std::vector< int > &sub, const std::vector< int > &super)
Definition: opt_muxtree.cc:237
std::vector< muxinfo_t > mux2info
Definition: opt_muxtree.cc:70
void eval_mux_port(knowledge_t &knowledge, int mux_idx, int port_idx)
Definition: opt_muxtree.cc:296

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void OptMuxtreeWorker::eval_mux_port ( knowledge_t knowledge,
int  mux_idx,
int  port_idx 
)
inline

Definition at line 296 of file opt_muxtree.cc.

297  {
298  muxinfo_t &muxinfo = mux2info[mux_idx];
299  muxinfo.ports[port_idx].enabled = true;
300 
301  for (size_t i = 0; i < muxinfo.ports.size(); i++) {
302  if (int(i) == port_idx)
303  continue;
304  for (int b : muxinfo.ports[i].ctrl_sigs)
305  knowledge.known_inactive[b]++;
306  }
307 
308  if (port_idx < int(muxinfo.ports.size())-1 && !muxinfo.ports[port_idx].const_activated)
309  knowledge.known_active.push_back(muxinfo.ports[port_idx].ctrl_sigs);
310 
311  std::vector<int> parent_muxes;
312  for (int m : muxinfo.ports[port_idx].input_muxes) {
313  if (knowledge.visited_muxes.count(m) > 0)
314  continue;
315  knowledge.visited_muxes.insert(m);
316  parent_muxes.push_back(m);
317  }
318  for (int m : parent_muxes)
319  eval_mux(knowledge, m);
320  for (int m : parent_muxes)
321  knowledge.visited_muxes.erase(m);
322 
323  if (port_idx < int(muxinfo.ports.size())-1 && !muxinfo.ports[port_idx].const_activated)
324  knowledge.known_active.pop_back();
325 
326  for (size_t i = 0; i < muxinfo.ports.size(); i++) {
327  if (int(i) == port_idx)
328  continue;
329  for (int b : muxinfo.ports[i].ctrl_sigs)
330  knowledge.known_inactive[b]--;
331  }
332  }
std::vector< muxinfo_t > mux2info
Definition: opt_muxtree.cc:70
void eval_mux(knowledge_t &knowledge, int mux_idx)
Definition: opt_muxtree.cc:334

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void OptMuxtreeWorker::eval_root_mux ( int  mux_idx)
inline

Definition at line 396 of file opt_muxtree.cc.

397  {
398  knowledge_t knowledge;
399  knowledge.visited_muxes.insert(mux_idx);
400  eval_mux(knowledge, mux_idx);
401  }
void eval_mux(knowledge_t &knowledge, int mux_idx)
Definition: opt_muxtree.cc:334

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool OptMuxtreeWorker::is_in_list ( const std::vector< int > &  list,
int  value 
)
inline

Definition at line 245 of file opt_muxtree.cc.

246  {
247  for (int v : list)
248  if (v == value)
249  return true;
250  return false;
251  }

+ Here is the caller graph for this function:

bool OptMuxtreeWorker::list_is_subset ( const std::vector< int > &  sub,
const std::vector< int > &  super 
)
inline

Definition at line 237 of file opt_muxtree.cc.

238  {
239  for (int v : sub)
240  if (!is_in_list(super, v))
241  return false;
242  return true;
243  }
bool is_in_list(const std::vector< int > &list, int value)
Definition: opt_muxtree.cc:245

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector<int> OptMuxtreeWorker::sig2bits ( RTLIL::SigSpec  sig)
inline

Definition at line 259 of file opt_muxtree.cc.

260  {
261  std::vector<int> results;
262  assign_map.apply(sig);
263  for (auto &bit : sig)
264  if (bit.wire != NULL) {
265  if (bit2num.count(bit) == 0) {
266  bitinfo_t info;
267  info.num = bit2info.size();
268  info.bit = bit;
269  info.seen_non_mux = false;
270  bit2info.push_back(info);
271  bit2num[info.bit] = info.num;
272  }
273  results.push_back(bit2num[bit]);
274  }
275  return results;
276  }
std::vector< bitinfo_t > bit2info
Definition: opt_muxtree.cc:55
void apply(RTLIL::SigBit &bit) const
Definition: sigtools.h:383
std::map< bitDef_t, int > bit2num
Definition: opt_muxtree.cc:54
#define NULL

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Field Documentation

SigMap OptMuxtreeWorker::assign_map

Definition at line 37 of file opt_muxtree.cc.

std::vector<bitinfo_t> OptMuxtreeWorker::bit2info

Definition at line 55 of file opt_muxtree.cc.

std::map<bitDef_t, int> OptMuxtreeWorker::bit2num

Definition at line 54 of file opt_muxtree.cc.

RTLIL::Design* OptMuxtreeWorker::design

Definition at line 35 of file opt_muxtree.cc.

RTLIL::Module* OptMuxtreeWorker::module

Definition at line 36 of file opt_muxtree.cc.

std::vector<muxinfo_t> OptMuxtreeWorker::mux2info

Definition at line 70 of file opt_muxtree.cc.

int OptMuxtreeWorker::removed_count

Definition at line 38 of file opt_muxtree.cc.


The documentation for this struct was generated from the following file: