2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
20 #include "kernel/register.h"
21 #include "kernel/log.h"
27 PRIVATE_NAMESPACE_BEGIN
29 void handle_memory(RTLIL::Module
*module
, RTLIL::Cell
*memory
)
31 log("Creating $memrd and $memwr for memory `%s' in module `%s':\n",
32 memory
->name
.c_str(), module
->name
.c_str());
34 RTLIL::IdString mem_name
= RTLIL::escape_id(memory
->parameters
.at("\\MEMID").decode_string());
36 while (module
->memories
.count(mem_name
) != 0)
37 mem_name
= mem_name
.str() + stringf("_%d", autoidx
++);
39 RTLIL::Memory
*mem
= new RTLIL::Memory
;
41 mem
->width
= memory
->parameters
.at("\\WIDTH").as_int();
42 mem
->start_offset
= memory
->parameters
.at("\\OFFSET").as_int();
43 mem
->size
= memory
->parameters
.at("\\SIZE").as_int();
44 module
->memories
[mem_name
] = mem
;
46 int abits
= memory
->parameters
.at("\\ABITS").as_int();
47 int num_rd_ports
= memory
->parameters
.at("\\RD_PORTS").as_int();
48 int num_wr_ports
= memory
->parameters
.at("\\WR_PORTS").as_int();
50 for (int i
= 0; i
< num_rd_ports
; i
++)
52 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, "$memrd");
53 cell
->parameters
["\\MEMID"] = mem_name
.str();
54 cell
->parameters
["\\ABITS"] = memory
->parameters
.at("\\ABITS");
55 cell
->parameters
["\\WIDTH"] = memory
->parameters
.at("\\WIDTH");
56 cell
->parameters
["\\CLK_ENABLE"] = RTLIL::SigSpec(memory
->parameters
.at("\\RD_CLK_ENABLE")).extract(i
, 1).as_const();
57 cell
->parameters
["\\CLK_POLARITY"] = RTLIL::SigSpec(memory
->parameters
.at("\\RD_CLK_POLARITY")).extract(i
, 1).as_const();
58 cell
->parameters
["\\TRANSPARENT"] = RTLIL::SigSpec(memory
->parameters
.at("\\RD_TRANSPARENT")).extract(i
, 1).as_const();
59 cell
->setPort("\\CLK", memory
->getPort("\\RD_CLK").extract(i
, 1));
60 cell
->setPort("\\EN", memory
->getPort("\\RD_EN").extract(i
, 1));
61 cell
->setPort("\\ADDR", memory
->getPort("\\RD_ADDR").extract(i
*abits
, abits
));
62 cell
->setPort("\\DATA", memory
->getPort("\\RD_DATA").extract(i
*mem
->width
, mem
->width
));
65 for (int i
= 0; i
< num_wr_ports
; i
++)
67 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, "$memwr");
68 cell
->parameters
["\\MEMID"] = mem_name
.str();
69 cell
->parameters
["\\ABITS"] = memory
->parameters
.at("\\ABITS");
70 cell
->parameters
["\\WIDTH"] = memory
->parameters
.at("\\WIDTH");
71 cell
->parameters
["\\CLK_ENABLE"] = RTLIL::SigSpec(memory
->parameters
.at("\\WR_CLK_ENABLE")).extract(i
, 1).as_const();
72 cell
->parameters
["\\CLK_POLARITY"] = RTLIL::SigSpec(memory
->parameters
.at("\\WR_CLK_POLARITY")).extract(i
, 1).as_const();
73 cell
->parameters
["\\PRIORITY"] = i
;
74 cell
->setPort("\\CLK", memory
->getPort("\\WR_CLK").extract(i
, 1));
75 cell
->setPort("\\EN", memory
->getPort("\\WR_EN").extract(i
*mem
->width
, mem
->width
));
76 cell
->setPort("\\ADDR", memory
->getPort("\\WR_ADDR").extract(i
*abits
, abits
));
77 cell
->setPort("\\DATA", memory
->getPort("\\WR_DATA").extract(i
*mem
->width
, mem
->width
));
80 Const initval
= memory
->parameters
.at("\\INIT");
81 RTLIL::Cell
*last_init_cell
= nullptr;
82 SigSpec last_init_data
;
85 for (int i
= 0; i
< GetSize(initval
) && i
/mem
->width
< (1 << abits
); i
+= mem
->width
) {
86 Const val
= initval
.extract(i
, mem
->width
, State::Sx
);
87 for (auto bit
: val
.bits
)
89 goto found_non_undef_initval
;
91 found_non_undef_initval
:
92 if (last_init_cell
&& last_init_addr
+1 == i
/mem
->width
) {
93 last_init_cell
->parameters
["\\WORDS"] = last_init_cell
->parameters
["\\WORDS"].as_int() + 1;
94 last_init_data
.append(val
);
98 last_init_cell
->setPort("\\DATA", last_init_data
);
99 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, "$meminit");
100 cell
->parameters
["\\MEMID"] = mem_name
.str();
101 cell
->parameters
["\\ABITS"] = memory
->parameters
.at("\\ABITS");
102 cell
->parameters
["\\WIDTH"] = memory
->parameters
.at("\\WIDTH");
103 cell
->parameters
["\\WORDS"] = 1;
104 cell
->parameters
["\\PRIORITY"] = i
/mem
->width
;
105 cell
->setPort("\\ADDR", SigSpec(i
/mem
->width
, abits
));
106 last_init_cell
= cell
;
107 last_init_addr
= i
/mem
->width
;
108 last_init_data
= val
;
113 last_init_cell
->setPort("\\DATA", last_init_data
);
115 module
->remove(memory
);
118 void handle_module(RTLIL::Design
*design
, RTLIL::Module
*module
)
120 std::vector
<RTLIL::IdString
> memcells
;
121 for (auto &cell_it
: module
->cells_
)
122 if (cell_it
.second
->type
== "$mem" && design
->selected(module
, cell_it
.second
))
123 memcells
.push_back(cell_it
.first
);
124 for (auto &it
: memcells
)
125 handle_memory(module
, module
->cells_
.at(it
));
128 struct MemoryUnpackPass
: public Pass
{
129 MemoryUnpackPass() : Pass("memory_unpack", "unpack multi-port memory cells") { }
130 void help() YS_OVERRIDE
132 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
134 log(" memory_unpack [selection]\n");
136 log("This pass converts the multi-port $mem memory cells into individual $memrd and\n");
137 log("$memwr cells. It is the counterpart to the memory_collect pass.\n");
140 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
{
141 log_header(design
, "Executing MEMORY_UNPACK pass (generating $memrd/$memwr cells form $mem cells).\n");
142 extra_args(args
, 1, design
);
143 for (auto &mod_it
: design
->modules_
)
144 if (design
->selected(mod_it
.second
))
145 handle_module(design
, mod_it
.second
);
149 PRIVATE_NAMESPACE_END