aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/mem.cc32
-rw-r--r--kernel/mem.h2
2 files changed, 28 insertions, 6 deletions
diff --git a/kernel/mem.cc b/kernel/mem.cc
index 2a51ec5d9..2285cf74d 100644
--- a/kernel/mem.cc
+++ b/kernel/mem.cc
@@ -121,6 +121,8 @@ void Mem::emit() {
abits = std::max(abits, GetSize(port.addr));
cell->parameters[ID::ABITS] = Const(abits);
for (auto &port : rd_ports) {
+ // TODO: remove
+ log_assert(port.wide_log2 == 0);
if (port.cell) {
module->remove(port.cell);
port.cell = nullptr;
@@ -152,6 +154,8 @@ void Mem::emit() {
cell->setPort(ID::RD_ADDR, rd_addr);
cell->setPort(ID::RD_DATA, rd_data);
for (auto &port : wr_ports) {
+ // TODO: remove
+ log_assert(port.wide_log2 == 0);
if (port.cell) {
module->remove(port.cell);
port.cell = nullptr;
@@ -206,7 +210,7 @@ void Mem::emit() {
port.cell = module->addCell(NEW_ID, ID($memrd));
port.cell->parameters[ID::MEMID] = memid.str();
port.cell->parameters[ID::ABITS] = GetSize(port.addr);
- port.cell->parameters[ID::WIDTH] = width;
+ port.cell->parameters[ID::WIDTH] = width << port.wide_log2;
port.cell->parameters[ID::CLK_ENABLE] = port.clk_enable;
port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
port.cell->parameters[ID::TRANSPARENT] = port.transparent;
@@ -221,7 +225,7 @@ void Mem::emit() {
port.cell = module->addCell(NEW_ID, ID($memwr));
port.cell->parameters[ID::MEMID] = memid.str();
port.cell->parameters[ID::ABITS] = GetSize(port.addr);
- port.cell->parameters[ID::WIDTH] = width;
+ port.cell->parameters[ID::WIDTH] = width << port.wide_log2;
port.cell->parameters[ID::CLK_ENABLE] = port.clk_enable;
port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
port.cell->parameters[ID::PRIORITY] = idx++;
@@ -264,23 +268,32 @@ Const Mem::get_init_data() const {
}
void Mem::check() {
+ int max_wide_log2 = 0;
for (auto &port : rd_ports) {
if (port.removed)
continue;
log_assert(GetSize(port.clk) == 1);
log_assert(GetSize(port.en) == 1);
- log_assert(GetSize(port.data) == width);
+ log_assert(GetSize(port.data) == (width << port.wide_log2));
if (!port.clk_enable) {
log_assert(!port.transparent);
}
+ for (int j = 0; j < port.wide_log2; j++) {
+ log_assert(port.addr[j] == State::S0);
+ }
+ max_wide_log2 = std::max(max_wide_log2, port.wide_log2);
}
for (int i = 0; i < GetSize(wr_ports); i++) {
auto &port = wr_ports[i];
if (port.removed)
continue;
log_assert(GetSize(port.clk) == 1);
- log_assert(GetSize(port.en) == width);
- log_assert(GetSize(port.data) == width);
+ log_assert(GetSize(port.en) == (width << port.wide_log2));
+ log_assert(GetSize(port.data) == (width << port.wide_log2));
+ for (int j = 0; j < port.wide_log2; j++) {
+ log_assert(port.addr[j] == State::S0);
+ }
+ max_wide_log2 = std::max(max_wide_log2, port.wide_log2);
log_assert(GetSize(port.priority_mask) == GetSize(wr_ports));
for (int j = 0; j < GetSize(wr_ports); j++) {
auto &wport = wr_ports[j];
@@ -294,6 +307,9 @@ void Mem::check() {
}
}
}
+ int mask = (1 << max_wide_log2) - 1;
+ log_assert(!(start_offset & mask));
+ log_assert(!(size & mask));
}
namespace {
@@ -331,6 +347,7 @@ namespace {
mrd.en = cell->getPort(ID::EN);
mrd.addr = cell->getPort(ID::ADDR);
mrd.data = cell->getPort(ID::DATA);
+ mrd.wide_log2 = ceil_log2(GetSize(mrd.data) / mem->width);
res.rd_ports.push_back(mrd);
}
}
@@ -346,6 +363,7 @@ namespace {
mwr.en = cell->getPort(ID::EN);
mwr.addr = cell->getPort(ID::ADDR);
mwr.data = cell->getPort(ID::DATA);
+ mwr.wide_log2 = ceil_log2(GetSize(mwr.data) / mem->width);
ports.push_back(std::make_pair(cell->parameters.at(ID::PRIORITY).as_int(), mwr));
}
std::sort(ports.begin(), ports.end(), [](const std::pair<int, MemWr> &a, const std::pair<int, MemWr> &b) { return a.first < b.first; });
@@ -424,6 +442,7 @@ namespace {
}
for (int i = 0; i < cell->parameters.at(ID::RD_PORTS).as_int(); i++) {
MemRd mrd;
+ mrd.wide_log2 = 0;
mrd.clk_enable = cell->parameters.at(ID::RD_CLK_ENABLE).extract(i, 1).as_bool();
mrd.clk_polarity = cell->parameters.at(ID::RD_CLK_POLARITY).extract(i, 1).as_bool();
mrd.transparent = cell->parameters.at(ID::RD_TRANSPARENT).extract(i, 1).as_bool();
@@ -435,6 +454,7 @@ namespace {
}
for (int i = 0; i < cell->parameters.at(ID::WR_PORTS).as_int(); i++) {
MemWr mwr;
+ mwr.wide_log2 = 0;
mwr.clk_enable = cell->parameters.at(ID::WR_CLK_ENABLE).extract(i, 1).as_bool();
mwr.clk_polarity = cell->parameters.at(ID::WR_CLK_POLARITY).extract(i, 1).as_bool();
mwr.clk = cell->getPort(ID::WR_CLK).extract(i, 1);
@@ -507,7 +527,7 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
}
else
{
- SigSpec sig_d = module->addWire(stringf("%s$rdreg[%d]$d", memid.c_str(), idx), width);
+ SigSpec sig_d = module->addWire(stringf("%s$rdreg[%d]$d", memid.c_str(), idx), GetSize(port.data));
SigSpec sig_q = port.data;
port.data = sig_d;
c = module->addDffe(stringf("%s$rdreg[%d]", memid.c_str(), idx), port.clk, port.en, sig_d, sig_q, port.clk_polarity, true);
diff --git a/kernel/mem.h b/kernel/mem.h
index af06e970a..e0d8c277f 100644
--- a/kernel/mem.h
+++ b/kernel/mem.h
@@ -29,6 +29,7 @@ struct MemRd {
bool removed;
dict<IdString, Const> attributes;
Cell *cell;
+ int wide_log2;
bool clk_enable, clk_polarity;
bool transparent;
SigSpec clk, en, addr, data;
@@ -39,6 +40,7 @@ struct MemWr {
bool removed;
dict<IdString, Const> attributes;
Cell *cell;
+ int wide_log2;
bool clk_enable, clk_polarity;
std::vector<bool> priority_mask;
SigSpec clk, en, addr, data;