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

Public Member Functions

std::string genid (RTLIL::IdString name, std::string token1="", int i=-1, std::string token2="", int j=-1, std::string token3="", int k=-1, std::string token4="")
 
RTLIL::Wireaddr_decode (RTLIL::SigSpec addr_sig, RTLIL::SigSpec addr_val)
 
void handle_cell (RTLIL::Cell *cell)
 
 MemoryMapWorker (RTLIL::Design *design, RTLIL::Module *module)
 

Data Fields

RTLIL::Designdesign
 
RTLIL::Modulemodule
 
std::map< std::pair
< RTLIL::SigSpec,
RTLIL::SigSpec >
, RTLIL::SigBit
decoder_cache
 

Detailed Description

Definition at line 29 of file memory_map.cc.

Constructor & Destructor Documentation

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

Definition at line 314 of file memory_map.cc.

314  : design(design), module(module)
315  {
316  std::vector<RTLIL::Cell*> cells;
317  for (auto cell : module->selected_cells())
318  if (cell->type == "$mem" && design->selected(module, cell))
319  cells.push_back(cell);
320  for (auto cell : cells)
321  handle_cell(cell);
322  }
bool selected(T1 *module) const
Definition: rtlil.h:551
RTLIL::Module * module
Definition: memory_map.cc:32
RTLIL::Design * design
Definition: memory_map.cc:31
std::vector< RTLIL::Cell * > selected_cells() const
Definition: rtlil.cc:1103
void handle_cell(RTLIL::Cell *cell)
Definition: memory_map.cc:79

+ Here is the call graph for this function:

Member Function Documentation

RTLIL::Wire* MemoryMapWorker::addr_decode ( RTLIL::SigSpec  addr_sig,
RTLIL::SigSpec  addr_val 
)
inline

Definition at line 58 of file memory_map.cc.

59  {
60  std::pair<RTLIL::SigSpec, RTLIL::SigSpec> key(addr_sig, addr_val);
61  log_assert(GetSize(addr_sig) == GetSize(addr_val));
62 
63  if (decoder_cache.count(key) == 0) {
64  if (GetSize(addr_sig) < 2) {
65  decoder_cache[key] = module->Eq(NEW_ID, addr_sig, addr_val);
66  } else {
67  int split_at = GetSize(addr_sig) / 2;
68  RTLIL::SigBit left_eq = addr_decode(addr_sig.extract(0, split_at), addr_val.extract(0, split_at));
69  RTLIL::SigBit right_eq = addr_decode(addr_sig.extract(split_at, GetSize(addr_sig) - split_at), addr_val.extract(split_at, GetSize(addr_val) - split_at));
70  decoder_cache[key] = module->And(NEW_ID, left_eq, right_eq);
71  }
72  }
73 
74  RTLIL::SigBit bit = decoder_cache.at(key);
75  log_assert(bit.wire != nullptr && GetSize(bit.wire) == 1);
76  return bit.wire;
77  }
RTLIL::Wire * wire
Definition: rtlil.h:907
std::map< std::pair< RTLIL::SigSpec, RTLIL::SigSpec >, RTLIL::SigBit > decoder_cache
Definition: memory_map.cc:34
RTLIL::SigSpec Eq(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed=false)
RTLIL::Module * module
Definition: memory_map.cc:32
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
#define log_assert(_assert_expr_)
Definition: log.h:85
#define NEW_ID
Definition: yosys.h:166
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other=NULL) const
Definition: rtlil.cc:2414
RTLIL::SigSpec And(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed=false)
RTLIL::Wire * addr_decode(RTLIL::SigSpec addr_sig, RTLIL::SigSpec addr_val)
Definition: memory_map.cc:58

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::string MemoryMapWorker::genid ( RTLIL::IdString  name,
std::string  token1 = "",
int  i = -1,
std::string  token2 = "",
int  j = -1,
std::string  token3 = "",
int  k = -1,
std::string  token4 = "" 
)
inline

Definition at line 36 of file memory_map.cc.

37  {
38  std::stringstream sstr;
39  sstr << "$memory" << name.str() << token1;
40 
41  if (i >= 0)
42  sstr << "[" << i << "]";
43 
44  sstr << token2;
45 
46  if (j >= 0)
47  sstr << "[" << j << "]";
48 
49  sstr << token3;
50 
51  if (k >= 0)
52  sstr << "[" << k << "]";
53 
54  sstr << token4 << "$" << (autoidx++);
55  return sstr.str();
56  }
std::string str() const
Definition: rtlil.h:182
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 MemoryMapWorker::handle_cell ( RTLIL::Cell cell)
inline

Definition at line 79 of file memory_map.cc.

80  {
81  std::set<int> static_ports;
82  std::map<int, RTLIL::SigSpec> static_cells_map;
83  int mem_size = cell->parameters["\\SIZE"].as_int();
84  int mem_width = cell->parameters["\\WIDTH"].as_int();
85  int mem_offset = cell->parameters["\\OFFSET"].as_int();
86  int mem_abits = cell->parameters["\\ABITS"].as_int();
87 
88  // delete unused memory cell
89  if (cell->parameters["\\RD_PORTS"].as_int() == 0 && cell->parameters["\\WR_PORTS"].as_int() == 0) {
90  module->remove(cell);
91  return;
92  }
93 
94  // all write ports must share the same clock
95  RTLIL::SigSpec clocks = cell->getPort("\\WR_CLK");
96  RTLIL::Const clocks_pol = cell->parameters["\\WR_CLK_POLARITY"];
97  RTLIL::Const clocks_en = cell->parameters["\\WR_CLK_ENABLE"];
98  RTLIL::SigSpec refclock;
99  RTLIL::State refclock_pol = RTLIL::State::Sx;
100  for (int i = 0; i < clocks.size(); i++) {
101  RTLIL::SigSpec wr_en = cell->getPort("\\WR_EN").extract(i * mem_width, mem_width);
102  if (wr_en.is_fully_const() && !wr_en.as_bool()) {
103  static_ports.insert(i);
104  continue;
105  }
106  if (clocks_en.bits[i] != RTLIL::State::S1) {
107  RTLIL::SigSpec wr_addr = cell->getPort("\\WR_ADDR").extract(i*mem_abits, mem_abits);
108  RTLIL::SigSpec wr_data = cell->getPort("\\WR_DATA").extract(i*mem_width, mem_width);
109  if (wr_addr.is_fully_const()) {
110  // FIXME: Actually we should check for wr_en.is_fully_const() also and
111  // create a $adff cell with this ports wr_en input as reset pin when wr_en
112  // is not a simple static 1.
113  static_cells_map[wr_addr.as_int()] = wr_data;
114  static_ports.insert(i);
115  continue;
116  }
117  log("Not mapping memory cell %s in module %s (write port %d has no clock).\n",
118  cell->name.c_str(), module->name.c_str(), i);
119  return;
120  }
121  if (refclock.size() == 0) {
122  refclock = clocks.extract(i, 1);
123  refclock_pol = clocks_pol.bits[i];
124  }
125  if (clocks.extract(i, 1) != refclock || clocks_pol.bits[i] != refclock_pol) {
126  log("Not mapping memory cell %s in module %s (write clock %d is incompatible with other clocks).\n",
127  cell->name.c_str(), module->name.c_str(), i);
128  return;
129  }
130  }
131 
132  log("Mapping memory cell %s in module %s:\n", cell->name.c_str(), module->name.c_str());
133 
134  std::vector<RTLIL::SigSpec> data_reg_in;
135  std::vector<RTLIL::SigSpec> data_reg_out;
136 
137  int count_static = 0;
138 
139  for (int i = 0; i < mem_size; i++)
140  {
141  if (static_cells_map.count(i) > 0)
142  {
143  data_reg_in.push_back(RTLIL::SigSpec(RTLIL::State::Sz, mem_width));
144  data_reg_out.push_back(static_cells_map[i]);
145  count_static++;
146  }
147  else
148  {
149  RTLIL::Cell *c = module->addCell(genid(cell->name, "", i), "$dff");
150  c->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"];
151  if (clocks_pol.bits.size() > 0) {
152  c->parameters["\\CLK_POLARITY"] = RTLIL::Const(clocks_pol.bits[0]);
153  c->setPort("\\CLK", clocks.extract(0, 1));
154  } else {
155  c->parameters["\\CLK_POLARITY"] = RTLIL::Const(RTLIL::State::S1);
157  }
158 
159  RTLIL::Wire *w_in = module->addWire(genid(cell->name, "", i, "$d"), mem_width);
160  data_reg_in.push_back(RTLIL::SigSpec(w_in));
161  c->setPort("\\D", data_reg_in.back());
162 
163  std::string w_out_name = stringf("%s[%d]", cell->parameters["\\MEMID"].decode_string().c_str(), i);
164  if (module->wires_.count(w_out_name) > 0)
165  w_out_name = genid(cell->name, "", i, "$q");
166 
167  RTLIL::Wire *w_out = module->addWire(w_out_name, mem_width);
168  w_out->start_offset = mem_offset;
169 
170  data_reg_out.push_back(RTLIL::SigSpec(w_out));
171  c->setPort("\\Q", data_reg_out.back());
172  }
173  }
174 
175  log(" created %d $dff cells and %d static cells of width %d.\n", mem_size-count_static, count_static, mem_width);
176 
177  int count_dff = 0, count_mux = 0, count_wrmux = 0;
178 
179  for (int i = 0; i < cell->parameters["\\RD_PORTS"].as_int(); i++)
180  {
181  RTLIL::SigSpec rd_addr = cell->getPort("\\RD_ADDR").extract(i*mem_abits, mem_abits);
182 
183  std::vector<RTLIL::SigSpec> rd_signals;
184  rd_signals.push_back(cell->getPort("\\RD_DATA").extract(i*mem_width, mem_width));
185 
186  if (cell->parameters["\\RD_CLK_ENABLE"].bits[i] == RTLIL::State::S1)
187  {
188  if (cell->parameters["\\RD_TRANSPARENT"].bits[i] == RTLIL::State::S1)
189  {
190  RTLIL::Cell *c = module->addCell(genid(cell->name, "$rdreg", i), "$dff");
191  c->parameters["\\WIDTH"] = RTLIL::Const(mem_abits);
192  c->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]);
193  c->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1));
194  c->setPort("\\D", rd_addr);
195  count_dff++;
196 
197  RTLIL::Wire *w = module->addWire(genid(cell->name, "$rdreg", i, "$q"), mem_abits);
198 
199  c->setPort("\\Q", RTLIL::SigSpec(w));
200  rd_addr = RTLIL::SigSpec(w);
201  }
202  else
203  {
204  RTLIL::Cell *c = module->addCell(genid(cell->name, "$rdreg", i), "$dff");
205  c->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"];
206  c->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]);
207  c->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1));
208  c->setPort("\\Q", rd_signals.back());
209  count_dff++;
210 
211  RTLIL::Wire *w = module->addWire(genid(cell->name, "$rdreg", i, "$d"), mem_width);
212 
213  rd_signals.clear();
214  rd_signals.push_back(RTLIL::SigSpec(w));
215  c->setPort("\\D", rd_signals.back());
216  }
217  }
218 
219  for (int j = 0; j < mem_abits; j++)
220  {
221  std::vector<RTLIL::SigSpec> next_rd_signals;
222 
223  for (size_t k = 0; k < rd_signals.size(); k++)
224  {
225  RTLIL::Cell *c = module->addCell(genid(cell->name, "$rdmux", i, "", j, "", k), "$mux");
226  c->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"];
227  c->setPort("\\Y", rd_signals[k]);
228  c->setPort("\\S", rd_addr.extract(mem_abits-j-1, 1));
229  count_mux++;
230 
231  c->setPort("\\A", module->addWire(genid(cell->name, "$rdmux", i, "", j, "", k, "$a"), mem_width));
232  c->setPort("\\B", module->addWire(genid(cell->name, "$rdmux", i, "", j, "", k, "$b"), mem_width));
233 
234  next_rd_signals.push_back(c->getPort("\\A"));
235  next_rd_signals.push_back(c->getPort("\\B"));
236  }
237 
238  next_rd_signals.swap(rd_signals);
239  }
240 
241  for (int j = 0; j < mem_size; j++)
242  module->connect(RTLIL::SigSig(rd_signals[j], data_reg_out[j]));
243  }
244 
245  log(" read interface: %d $dff and %d $mux cells.\n", count_dff, count_mux);
246 
247  for (int i = 0; i < mem_size; i++)
248  {
249  if (static_cells_map.count(i) > 0)
250  continue;
251 
252  RTLIL::SigSpec sig = data_reg_out[i];
253 
254  for (int j = 0; j < cell->parameters["\\WR_PORTS"].as_int(); j++)
255  {
256  RTLIL::SigSpec wr_addr = cell->getPort("\\WR_ADDR").extract(j*mem_abits, mem_abits);
257  RTLIL::SigSpec wr_data = cell->getPort("\\WR_DATA").extract(j*mem_width, mem_width);
258  RTLIL::SigSpec wr_en = cell->getPort("\\WR_EN").extract(j*mem_width, mem_width);
259  RTLIL::Wire *w_seladdr = addr_decode(wr_addr, RTLIL::SigSpec(i, mem_abits));
260 
261  int wr_offset = 0;
262  while (wr_offset < wr_en.size())
263  {
264  int wr_width = 1;
265  RTLIL::SigSpec wr_bit = wr_en.extract(wr_offset, 1);
266 
267  while (wr_offset + wr_width < wr_en.size()) {
268  RTLIL::SigSpec next_wr_bit = wr_en.extract(wr_offset + wr_width, 1);
269  if (next_wr_bit != wr_bit)
270  break;
271  wr_width++;
272  }
273 
274  RTLIL::Wire *w = w_seladdr;
275 
276  if (wr_bit != RTLIL::SigSpec(1, 1))
277  {
278  RTLIL::Cell *c = module->addCell(genid(cell->name, "$wren", i, "", j, "", wr_offset), "$and");
279  c->parameters["\\A_SIGNED"] = RTLIL::Const(0);
280  c->parameters["\\B_SIGNED"] = RTLIL::Const(0);
281  c->parameters["\\A_WIDTH"] = RTLIL::Const(1);
282  c->parameters["\\B_WIDTH"] = RTLIL::Const(1);
283  c->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
284  c->setPort("\\A", w);
285  c->setPort("\\B", wr_bit);
286 
287  w = module->addWire(genid(cell->name, "$wren", i, "", j, "", wr_offset, "$y"));
288  c->setPort("\\Y", RTLIL::SigSpec(w));
289  }
290 
291  RTLIL::Cell *c = module->addCell(genid(cell->name, "$wrmux", i, "", j, "", wr_offset), "$mux");
292  c->parameters["\\WIDTH"] = wr_width;
293  c->setPort("\\A", sig.extract(wr_offset, wr_width));
294  c->setPort("\\B", wr_data.extract(wr_offset, wr_width));
295  c->setPort("\\S", RTLIL::SigSpec(w));
296 
297  w = module->addWire(genid(cell->name, "$wrmux", i, "", j, "", wr_offset, "$y"), wr_width);
298  c->setPort("\\Y", w);
299 
300  sig.replace(wr_offset, w);
301  wr_offset += wr_width;
302  count_wrmux++;
303  }
304  }
305 
306  module->connect(RTLIL::SigSig(data_reg_in[i], sig));
307  }
308 
309  log(" write interface: %d write mux blocks.\n", count_wrmux);
310 
311  module->remove(cell);
312  }
const char * c_str() const
Definition: rtlil.h:178
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
Definition: rtlil.cc:1353
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
Definition: rtlil.h:595
bool as_bool() const
Definition: rtlil.cc:2818
RTLIL::IdString name
Definition: rtlil.h:853
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 connect(const RTLIL::SigSig &conn)
Definition: rtlil.cc:1278
RTLIL::Module * module
Definition: memory_map.cc:32
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
Definition: rtlil.cc:1809
bool is_fully_const() const
Definition: rtlil.cc:2763
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
Definition: rtlil.cc:1331
RTLIL::IdString name
Definition: rtlil.h:599
void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with)
Definition: rtlil.cc:2297
int as_int(bool is_signed=false) const
Definition: rtlil.cc:2829
void remove(const std::set< RTLIL::Wire * > &wires)
Definition: rtlil.cc:1158
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
std::vector< RTLIL::State > bits
Definition: rtlil.h:438
State
Definition: rtlil.h:29
int start_offset
Definition: rtlil.h:826
RTLIL::Wire * addr_decode(RTLIL::SigSpec addr_sig, RTLIL::SigSpec addr_val)
Definition: memory_map.cc:58
std::string genid(RTLIL::IdString name, std::string token1="", int i=-1, std::string token2="", int j=-1, std::string token3="", int k=-1, std::string token4="")
Definition: memory_map.cc:36
std::pair< SigSpec, SigSpec > SigSig
Definition: rtlil.h:71

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Field Documentation

std::map<std::pair<RTLIL::SigSpec, RTLIL::SigSpec>, RTLIL::SigBit> MemoryMapWorker::decoder_cache

Definition at line 34 of file memory_map.cc.

RTLIL::Design* MemoryMapWorker::design

Definition at line 31 of file memory_map.cc.

RTLIL::Module* MemoryMapWorker::module

Definition at line 32 of file memory_map.cc.


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