aboutsummaryrefslogtreecommitdiffstats
path: root/passes/memory/memory_map.cc
diff options
context:
space:
mode:
Diffstat (limited to 'passes/memory/memory_map.cc')
-rw-r--r--passes/memory/memory_map.cc68
1 files changed, 48 insertions, 20 deletions
diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc
index 4fb10a989..bffeec857 100644
--- a/passes/memory/memory_map.cc
+++ b/passes/memory/memory_map.cc
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
@@ -37,7 +37,7 @@ struct MemoryMapWorker
{
std::stringstream sstr;
sstr << "$memory" << name.str() << token1;
-
+
if (i >= 0)
sstr << "[" << i << "]";
@@ -80,13 +80,20 @@ struct MemoryMapWorker
{
std::set<int> static_ports;
std::map<int, RTLIL::SigSpec> static_cells_map;
+
+ int wr_ports = cell->parameters["\\WR_PORTS"].as_int();
+ int rd_ports = cell->parameters["\\RD_PORTS"].as_int();
+
int mem_size = cell->parameters["\\SIZE"].as_int();
int mem_width = cell->parameters["\\WIDTH"].as_int();
int mem_offset = cell->parameters["\\OFFSET"].as_int();
int mem_abits = cell->parameters["\\ABITS"].as_int();
+ SigSpec init_data = cell->getParam("\\INIT");
+ init_data.extend_u0(mem_size*mem_width, true);
+
// delete unused memory cell
- if (cell->parameters["\\RD_PORTS"].as_int() == 0 && cell->parameters["\\WR_PORTS"].as_int() == 0) {
+ if (wr_ports == 0 && rd_ports == 0) {
module->remove(cell);
return;
}
@@ -95,6 +102,8 @@ struct MemoryMapWorker
RTLIL::SigSpec clocks = cell->getPort("\\WR_CLK");
RTLIL::Const clocks_pol = cell->parameters["\\WR_CLK_POLARITY"];
RTLIL::Const clocks_en = cell->parameters["\\WR_CLK_ENABLE"];
+ clocks_pol.bits.resize(wr_ports);
+ clocks_en.bits.resize(wr_ports);
RTLIL::SigSpec refclock;
RTLIL::State refclock_pol = RTLIL::State::Sx;
for (int i = 0; i < clocks.size(); i++) {
@@ -110,7 +119,7 @@ struct MemoryMapWorker
// FIXME: Actually we should check for wr_en.is_fully_const() also and
// create a $adff cell with this ports wr_en input as reset pin when wr_en
// is not a simple static 1.
- static_cells_map[wr_addr.as_int()] = wr_data;
+ static_cells_map[wr_addr.as_int() - mem_offset] = wr_data;
static_ports.insert(i);
continue;
}
@@ -165,7 +174,10 @@ struct MemoryMapWorker
w_out_name = genid(cell->name, "", i, "$q");
RTLIL::Wire *w_out = module->addWire(w_out_name, mem_width);
- w_out->start_offset = mem_offset;
+ SigSpec w_init = init_data.extract(i*mem_width, mem_width);
+
+ if (!w_init.is_fully_undef())
+ w_out->attributes["\\init"] = w_init.as_const();
data_reg_out.push_back(RTLIL::SigSpec(w_out));
c->setPort("\\Q", data_reg_out.back());
@@ -180,39 +192,51 @@ struct MemoryMapWorker
{
RTLIL::SigSpec rd_addr = cell->getPort("\\RD_ADDR").extract(i*mem_abits, mem_abits);
+ if (mem_offset)
+ rd_addr = module->Sub(NEW_ID, rd_addr, SigSpec(mem_offset, GetSize(rd_addr)));
+
std::vector<RTLIL::SigSpec> rd_signals;
rd_signals.push_back(cell->getPort("\\RD_DATA").extract(i*mem_width, mem_width));
if (cell->parameters["\\RD_CLK_ENABLE"].bits[i] == RTLIL::State::S1)
{
+ RTLIL::Cell *dff_cell = nullptr;
+
if (cell->parameters["\\RD_TRANSPARENT"].bits[i] == RTLIL::State::S1)
{
- RTLIL::Cell *c = module->addCell(genid(cell->name, "$rdreg", i), "$dff");
- c->parameters["\\WIDTH"] = RTLIL::Const(mem_abits);
- c->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]);
- c->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1));
- c->setPort("\\D", rd_addr);
+ dff_cell = module->addCell(genid(cell->name, "$rdreg", i), "$dff");
+ dff_cell->parameters["\\WIDTH"] = RTLIL::Const(mem_abits);
+ dff_cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]);
+ dff_cell->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1));
+ dff_cell->setPort("\\D", rd_addr);
count_dff++;
RTLIL::Wire *w = module->addWire(genid(cell->name, "$rdreg", i, "$q"), mem_abits);
- c->setPort("\\Q", RTLIL::SigSpec(w));
+ dff_cell->setPort("\\Q", RTLIL::SigSpec(w));
rd_addr = RTLIL::SigSpec(w);
}
else
{
- RTLIL::Cell *c = module->addCell(genid(cell->name, "$rdreg", i), "$dff");
- c->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"];
- c->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]);
- c->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1));
- c->setPort("\\Q", rd_signals.back());
+ dff_cell = module->addCell(genid(cell->name, "$rdreg", i), "$dff");
+ dff_cell->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"];
+ dff_cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]);
+ dff_cell->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1));
+ dff_cell->setPort("\\Q", rd_signals.back());
count_dff++;
RTLIL::Wire *w = module->addWire(genid(cell->name, "$rdreg", i, "$d"), mem_width);
rd_signals.clear();
rd_signals.push_back(RTLIL::SigSpec(w));
- c->setPort("\\D", rd_signals.back());
+ dff_cell->setPort("\\D", rd_signals.back());
+ }
+
+ SigBit en_bit = cell->getPort("\\RD_EN").extract(i);
+ if (en_bit != State::S1) {
+ SigSpec new_d = module->Mux(genid(cell->name, "$rdenmux", i),
+ dff_cell->getPort("\\Q"), dff_cell->getPort("\\D"), en_bit);
+ dff_cell->setPort("\\D", new_d);
}
}
@@ -256,6 +280,10 @@ struct MemoryMapWorker
RTLIL::SigSpec wr_addr = cell->getPort("\\WR_ADDR").extract(j*mem_abits, mem_abits);
RTLIL::SigSpec wr_data = cell->getPort("\\WR_DATA").extract(j*mem_width, mem_width);
RTLIL::SigSpec wr_en = cell->getPort("\\WR_EN").extract(j*mem_width, mem_width);
+
+ if (mem_offset)
+ wr_addr = module->Sub(NEW_ID, wr_addr, SigSpec(mem_offset, GetSize(wr_addr)));
+
RTLIL::Wire *w_seladdr = addr_decode(wr_addr, RTLIL::SigSpec(i, mem_abits));
int wr_offset = 0;
@@ -335,11 +363,11 @@ struct MemoryMapPass : public Pass {
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
- log_header("Executing MEMORY_MAP pass (converting $mem cells to logic and flip-flops).\n");
+ log_header(design, "Executing MEMORY_MAP pass (converting $mem cells to logic and flip-flops).\n");
extra_args(args, 1, design);
for (auto mod : design->selected_modules())
MemoryMapWorker(design, mod);
}
} MemoryMapPass;
-
+
PRIVATE_NAMESPACE_END