yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
memory_collect.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/log.h"
22 #include <sstream>
23 #include <algorithm>
24 #include <stdlib.h>
25 
28 
30 {
31  if (a->type == "$memrd" && b->type == "$memrd")
32  return a->name < b->name;
33  if (a->type == "$memrd" || b->type == "$memrd")
34  return (a->type == "$memrd") < (b->type == "$memrd");
35  return a->parameters.at("\\PRIORITY").as_int() < b->parameters.at("\\PRIORITY").as_int();
36 }
37 
39 {
40  log("Collecting $memrd and $memwr for memory `%s' in module `%s':\n",
41  memory->name.c_str(), module->name.c_str());
42 
43  int addr_bits = 0;
44  while ((1 << addr_bits) < memory->size)
45  addr_bits++;
46 
47  int wr_ports = 0;
48  RTLIL::SigSpec sig_wr_clk;
49  RTLIL::SigSpec sig_wr_clk_enable;
50  RTLIL::SigSpec sig_wr_clk_polarity;
51  RTLIL::SigSpec sig_wr_addr;
52  RTLIL::SigSpec sig_wr_data;
53  RTLIL::SigSpec sig_wr_en;
54 
55  int rd_ports = 0;
56  RTLIL::SigSpec sig_rd_clk;
57  RTLIL::SigSpec sig_rd_clk_enable;
58  RTLIL::SigSpec sig_rd_clk_polarity;
59  RTLIL::SigSpec sig_rd_transparent;
60  RTLIL::SigSpec sig_rd_addr;
61  RTLIL::SigSpec sig_rd_data;
62 
63  std::vector<RTLIL::Cell*> del_cells;
64  std::vector<RTLIL::Cell*> memcells;
65 
66  for (auto &cell_it : module->cells_) {
67  RTLIL::Cell *cell = cell_it.second;
68  if ((cell->type == "$memwr" || cell->type == "$memrd") && memory->name == cell->parameters["\\MEMID"].decode_string())
69  memcells.push_back(cell);
70  }
71 
72  std::sort(memcells.begin(), memcells.end(), memcells_cmp);
73 
74  for (auto cell : memcells)
75  {
76  if (cell->type == "$memwr" && memory->name == cell->parameters["\\MEMID"].decode_string())
77  {
78  wr_ports++;
79  del_cells.push_back(cell);
80 
81  RTLIL::SigSpec clk = cell->getPort("\\CLK");
82  RTLIL::SigSpec clk_enable = RTLIL::SigSpec(cell->parameters["\\CLK_ENABLE"]);
83  RTLIL::SigSpec clk_polarity = RTLIL::SigSpec(cell->parameters["\\CLK_POLARITY"]);
84  RTLIL::SigSpec addr = cell->getPort("\\ADDR");
85  RTLIL::SigSpec data = cell->getPort("\\DATA");
86  RTLIL::SigSpec en = cell->getPort("\\EN");
87 
88  clk.extend(1, false);
89  clk_enable.extend(1, false);
90  clk_polarity.extend(1, false);
91  addr.extend(addr_bits, false);
92  data.extend(memory->width, false);
93  en.extend(memory->width, false);
94 
95  sig_wr_clk.append(clk);
96  sig_wr_clk_enable.append(clk_enable);
97  sig_wr_clk_polarity.append(clk_polarity);
98  sig_wr_addr.append(addr);
99  sig_wr_data.append(data);
100  sig_wr_en.append(en);
101  }
102 
103  if (cell->type == "$memrd" && memory->name == cell->parameters["\\MEMID"].decode_string())
104  {
105  rd_ports++;
106  del_cells.push_back(cell);
107 
108  RTLIL::SigSpec clk = cell->getPort("\\CLK");
109  RTLIL::SigSpec clk_enable = RTLIL::SigSpec(cell->parameters["\\CLK_ENABLE"]);
110  RTLIL::SigSpec clk_polarity = RTLIL::SigSpec(cell->parameters["\\CLK_POLARITY"]);
111  RTLIL::SigSpec transparent = RTLIL::SigSpec(cell->parameters["\\TRANSPARENT"]);
112  RTLIL::SigSpec addr = cell->getPort("\\ADDR");
113  RTLIL::SigSpec data = cell->getPort("\\DATA");
114 
115  clk.extend(1, false);
116  clk_enable.extend(1, false);
117  clk_polarity.extend(1, false);
118  transparent.extend(1, false);
119  addr.extend(addr_bits, false);
120  data.extend(memory->width, false);
121 
122  sig_rd_clk.append(clk);
123  sig_rd_clk_enable.append(clk_enable);
124  sig_rd_clk_polarity.append(clk_polarity);
125  sig_rd_transparent.append(transparent);
126  sig_rd_addr.append(addr);
127  sig_rd_data.append(data);
128  }
129  }
130 
131  std::stringstream sstr;
132  sstr << "$mem$" << memory->name.str() << "$" << (autoidx++);
133 
134  RTLIL::Cell *mem = module->addCell(sstr.str(), "$mem");
135  mem->parameters["\\MEMID"] = RTLIL::Const(memory->name.str());
136  mem->parameters["\\WIDTH"] = RTLIL::Const(memory->width);
137  mem->parameters["\\OFFSET"] = RTLIL::Const(memory->start_offset);
138  mem->parameters["\\SIZE"] = RTLIL::Const(memory->size);
139  mem->parameters["\\ABITS"] = RTLIL::Const(addr_bits);
140 
141  log_assert(sig_wr_clk.size() == wr_ports);
142  log_assert(sig_wr_clk_enable.size() == wr_ports && sig_wr_clk_enable.is_fully_const());
143  log_assert(sig_wr_clk_polarity.size() == wr_ports && sig_wr_clk_polarity.is_fully_const());
144  log_assert(sig_wr_addr.size() == wr_ports * addr_bits);
145  log_assert(sig_wr_data.size() == wr_ports * memory->width);
146  log_assert(sig_wr_en.size() == wr_ports * memory->width);
147 
148  mem->parameters["\\WR_PORTS"] = RTLIL::Const(wr_ports);
149  mem->parameters["\\WR_CLK_ENABLE"] = wr_ports ? sig_wr_clk_enable.as_const() : RTLIL::Const(0, 0);
150  mem->parameters["\\WR_CLK_POLARITY"] = wr_ports ? sig_wr_clk_polarity.as_const() : RTLIL::Const(0, 0);
151 
152  mem->setPort("\\WR_CLK", sig_wr_clk);
153  mem->setPort("\\WR_ADDR", sig_wr_addr);
154  mem->setPort("\\WR_DATA", sig_wr_data);
155  mem->setPort("\\WR_EN", sig_wr_en);
156 
157  log_assert(sig_rd_clk.size() == rd_ports);
158  log_assert(sig_rd_clk_enable.size() == rd_ports && sig_rd_clk_enable.is_fully_const());
159  log_assert(sig_rd_clk_polarity.size() == rd_ports && sig_rd_clk_polarity.is_fully_const());
160  log_assert(sig_rd_addr.size() == rd_ports * addr_bits);
161  log_assert(sig_rd_data.size() == rd_ports * memory->width);
162 
163  mem->parameters["\\RD_PORTS"] = RTLIL::Const(rd_ports);
164  mem->parameters["\\RD_CLK_ENABLE"] = rd_ports ? sig_rd_clk_enable.as_const() : RTLIL::Const(0, 0);
165  mem->parameters["\\RD_CLK_POLARITY"] = rd_ports ? sig_rd_clk_polarity.as_const() : RTLIL::Const(0, 0);
166  mem->parameters["\\RD_TRANSPARENT"] = rd_ports ? sig_rd_transparent.as_const() : RTLIL::Const(0, 0);
167 
168  mem->setPort("\\RD_CLK", sig_rd_clk);
169  mem->setPort("\\RD_ADDR", sig_rd_addr);
170  mem->setPort("\\RD_DATA", sig_rd_data);
171 
172  for (auto c : del_cells)
173  module->remove(c);
174 }
175 
177 {
178  std::vector<RTLIL::IdString> delme;
179  for (auto &mem_it : module->memories)
180  if (design->selected(module, mem_it.second)) {
181  handle_memory(module, mem_it.second);
182  delme.push_back(mem_it.first);
183  }
184  for (auto &it : delme) {
185  delete module->memories.at(it);
186  module->memories.erase(it);
187  }
188 }
189 
190 struct MemoryCollectPass : public Pass {
191  MemoryCollectPass() : Pass("memory_collect", "creating multi-port memory cells") { }
192  virtual void help()
193  {
194  // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
195  log("\n");
196  log(" memory_collect [selection]\n");
197  log("\n");
198  log("This pass collects memories and memory ports and creates generic multiport\n");
199  log("memory cells.\n");
200  log("\n");
201  }
202  virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
203  log_header("Executing MEMORY_COLLECT pass (generating $mem cells).\n");
204  extra_args(args, 1, design);
205  for (auto &mod_it : design->modules_)
206  if (design->selected(mod_it.second))
207  handle_module(design, mod_it.second);
208  }
210 
const char * c_str() const
Definition: rtlil.h:178
virtual void help()
bool selected(T1 *module) const
Definition: rtlil.h:551
std::string str() const
Definition: rtlil.h:182
void sort(T *array, int size, LessThan lt)
Definition: Sort.h:57
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::Const as_const() const
Definition: rtlil.cc:2857
RTLIL::IdString name
Definition: rtlil.h:853
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
Definition: rtlil.cc:1789
std::map< RTLIL::IdString, RTLIL::Memory * > memories
Definition: rtlil.h:601
RTLIL::Module * module
Definition: abc.cc:94
RTLIL::IdString type
Definition: rtlil.h:854
std::map< RTLIL::IdString, RTLIL::Const > parameters
Definition: rtlil.h:856
int size
Definition: rtlil.h:836
int size() const
Definition: rtlil.h:1019
int start_offset
Definition: rtlil.h:836
#define PRIVATE_NAMESPACE_BEGIN
Definition: yosys.h:97
void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory)
MemoryCollectPass MemoryCollectPass
RTLIL::IdString name
Definition: rtlil.h:835
#define log_assert(_assert_expr_)
Definition: log.h:85
bool is_fully_const() const
Definition: rtlil.cc:2763
RTLIL::IdString name
Definition: rtlil.h:599
#define PRIVATE_NAMESPACE_END
Definition: yosys.h:98
Definition: register.h:27
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN bool memcells_cmp(RTLIL::Cell *a, RTLIL::Cell *b)
#define USING_YOSYS_NAMESPACE
Definition: yosys.h:102
std::map< RTLIL::IdString, RTLIL::Module * > modules_
Definition: rtlil.h:507
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
Definition: rtlil.h:596
void remove(const std::set< RTLIL::Wire * > &wires)
Definition: rtlil.cc:1158
void log(const char *format,...)
Definition: log.cc:180
void append(const RTLIL::SigSpec &signal)
Definition: rtlil.cc:2523
void extend(int width, bool is_signed=false)
Definition: rtlil.cc:2593
int width
Definition: rtlil.h:836
static void handle_module(RTLIL::Design *design, RTLIL::Module *module)
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
Definition: register.cc:128
YOSYS_NAMESPACE_BEGIN int autoidx
Definition: yosys.cc:51
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)