aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelina Koƛcielnicka <mwk@0x04.net>2021-05-22 16:48:46 +0200
committerMarcelina Koƛcielnicka <mwk@0x04.net>2021-05-25 02:07:25 +0200
commitff9713dd86cb6390f30392580e665095055a867c (patch)
tree3cf9283d25bda9068970b8ee311765201ec93387
parent95a39d342584fc9f98c57550aa7fba9e4652067b (diff)
downloadyosys-ff9713dd86cb6390f30392580e665095055a867c.tar.gz
yosys-ff9713dd86cb6390f30392580e665095055a867c.tar.bz2
yosys-ff9713dd86cb6390f30392580e665095055a867c.zip
kernel/mem: Add model for wide ports.
Such ports cannot actually be created or used yet, this just adds the necessary plumbing in the helper. Subsequent commits will gradually add wide port support to various yosys passes.
-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;