mirror of https://github.com/YosysHQ/yosys.git
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.
This commit is contained in:
parent
95a39d3425
commit
ff9713dd86
|
@ -121,6 +121,8 @@ void Mem::emit() {
|
||||||
abits = std::max(abits, GetSize(port.addr));
|
abits = std::max(abits, GetSize(port.addr));
|
||||||
cell->parameters[ID::ABITS] = Const(abits);
|
cell->parameters[ID::ABITS] = Const(abits);
|
||||||
for (auto &port : rd_ports) {
|
for (auto &port : rd_ports) {
|
||||||
|
// TODO: remove
|
||||||
|
log_assert(port.wide_log2 == 0);
|
||||||
if (port.cell) {
|
if (port.cell) {
|
||||||
module->remove(port.cell);
|
module->remove(port.cell);
|
||||||
port.cell = nullptr;
|
port.cell = nullptr;
|
||||||
|
@ -152,6 +154,8 @@ void Mem::emit() {
|
||||||
cell->setPort(ID::RD_ADDR, rd_addr);
|
cell->setPort(ID::RD_ADDR, rd_addr);
|
||||||
cell->setPort(ID::RD_DATA, rd_data);
|
cell->setPort(ID::RD_DATA, rd_data);
|
||||||
for (auto &port : wr_ports) {
|
for (auto &port : wr_ports) {
|
||||||
|
// TODO: remove
|
||||||
|
log_assert(port.wide_log2 == 0);
|
||||||
if (port.cell) {
|
if (port.cell) {
|
||||||
module->remove(port.cell);
|
module->remove(port.cell);
|
||||||
port.cell = nullptr;
|
port.cell = nullptr;
|
||||||
|
@ -206,7 +210,7 @@ void Mem::emit() {
|
||||||
port.cell = module->addCell(NEW_ID, ID($memrd));
|
port.cell = module->addCell(NEW_ID, ID($memrd));
|
||||||
port.cell->parameters[ID::MEMID] = memid.str();
|
port.cell->parameters[ID::MEMID] = memid.str();
|
||||||
port.cell->parameters[ID::ABITS] = GetSize(port.addr);
|
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_ENABLE] = port.clk_enable;
|
||||||
port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
|
port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
|
||||||
port.cell->parameters[ID::TRANSPARENT] = port.transparent;
|
port.cell->parameters[ID::TRANSPARENT] = port.transparent;
|
||||||
|
@ -221,7 +225,7 @@ void Mem::emit() {
|
||||||
port.cell = module->addCell(NEW_ID, ID($memwr));
|
port.cell = module->addCell(NEW_ID, ID($memwr));
|
||||||
port.cell->parameters[ID::MEMID] = memid.str();
|
port.cell->parameters[ID::MEMID] = memid.str();
|
||||||
port.cell->parameters[ID::ABITS] = GetSize(port.addr);
|
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_ENABLE] = port.clk_enable;
|
||||||
port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
|
port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
|
||||||
port.cell->parameters[ID::PRIORITY] = idx++;
|
port.cell->parameters[ID::PRIORITY] = idx++;
|
||||||
|
@ -264,23 +268,32 @@ Const Mem::get_init_data() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mem::check() {
|
void Mem::check() {
|
||||||
|
int max_wide_log2 = 0;
|
||||||
for (auto &port : rd_ports) {
|
for (auto &port : rd_ports) {
|
||||||
if (port.removed)
|
if (port.removed)
|
||||||
continue;
|
continue;
|
||||||
log_assert(GetSize(port.clk) == 1);
|
log_assert(GetSize(port.clk) == 1);
|
||||||
log_assert(GetSize(port.en) == 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) {
|
if (!port.clk_enable) {
|
||||||
log_assert(!port.transparent);
|
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++) {
|
for (int i = 0; i < GetSize(wr_ports); i++) {
|
||||||
auto &port = wr_ports[i];
|
auto &port = wr_ports[i];
|
||||||
if (port.removed)
|
if (port.removed)
|
||||||
continue;
|
continue;
|
||||||
log_assert(GetSize(port.clk) == 1);
|
log_assert(GetSize(port.clk) == 1);
|
||||||
log_assert(GetSize(port.en) == width);
|
log_assert(GetSize(port.en) == (width << port.wide_log2));
|
||||||
log_assert(GetSize(port.data) == width);
|
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));
|
log_assert(GetSize(port.priority_mask) == GetSize(wr_ports));
|
||||||
for (int j = 0; j < GetSize(wr_ports); j++) {
|
for (int j = 0; j < GetSize(wr_ports); j++) {
|
||||||
auto &wport = 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 {
|
namespace {
|
||||||
|
@ -331,6 +347,7 @@ namespace {
|
||||||
mrd.en = cell->getPort(ID::EN);
|
mrd.en = cell->getPort(ID::EN);
|
||||||
mrd.addr = cell->getPort(ID::ADDR);
|
mrd.addr = cell->getPort(ID::ADDR);
|
||||||
mrd.data = cell->getPort(ID::DATA);
|
mrd.data = cell->getPort(ID::DATA);
|
||||||
|
mrd.wide_log2 = ceil_log2(GetSize(mrd.data) / mem->width);
|
||||||
res.rd_ports.push_back(mrd);
|
res.rd_ports.push_back(mrd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,6 +363,7 @@ namespace {
|
||||||
mwr.en = cell->getPort(ID::EN);
|
mwr.en = cell->getPort(ID::EN);
|
||||||
mwr.addr = cell->getPort(ID::ADDR);
|
mwr.addr = cell->getPort(ID::ADDR);
|
||||||
mwr.data = cell->getPort(ID::DATA);
|
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));
|
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; });
|
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++) {
|
for (int i = 0; i < cell->parameters.at(ID::RD_PORTS).as_int(); i++) {
|
||||||
MemRd mrd;
|
MemRd mrd;
|
||||||
|
mrd.wide_log2 = 0;
|
||||||
mrd.clk_enable = cell->parameters.at(ID::RD_CLK_ENABLE).extract(i, 1).as_bool();
|
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.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();
|
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++) {
|
for (int i = 0; i < cell->parameters.at(ID::WR_PORTS).as_int(); i++) {
|
||||||
MemWr mwr;
|
MemWr mwr;
|
||||||
|
mwr.wide_log2 = 0;
|
||||||
mwr.clk_enable = cell->parameters.at(ID::WR_CLK_ENABLE).extract(i, 1).as_bool();
|
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_polarity = cell->parameters.at(ID::WR_CLK_POLARITY).extract(i, 1).as_bool();
|
||||||
mwr.clk = cell->getPort(ID::WR_CLK).extract(i, 1);
|
mwr.clk = cell->getPort(ID::WR_CLK).extract(i, 1);
|
||||||
|
@ -507,7 +527,7 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
|
||||||
}
|
}
|
||||||
else
|
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;
|
SigSpec sig_q = port.data;
|
||||||
port.data = sig_d;
|
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);
|
c = module->addDffe(stringf("%s$rdreg[%d]", memid.c_str(), idx), port.clk, port.en, sig_d, sig_q, port.clk_polarity, true);
|
||||||
|
|
|
@ -29,6 +29,7 @@ struct MemRd {
|
||||||
bool removed;
|
bool removed;
|
||||||
dict<IdString, Const> attributes;
|
dict<IdString, Const> attributes;
|
||||||
Cell *cell;
|
Cell *cell;
|
||||||
|
int wide_log2;
|
||||||
bool clk_enable, clk_polarity;
|
bool clk_enable, clk_polarity;
|
||||||
bool transparent;
|
bool transparent;
|
||||||
SigSpec clk, en, addr, data;
|
SigSpec clk, en, addr, data;
|
||||||
|
@ -39,6 +40,7 @@ struct MemWr {
|
||||||
bool removed;
|
bool removed;
|
||||||
dict<IdString, Const> attributes;
|
dict<IdString, Const> attributes;
|
||||||
Cell *cell;
|
Cell *cell;
|
||||||
|
int wide_log2;
|
||||||
bool clk_enable, clk_polarity;
|
bool clk_enable, clk_polarity;
|
||||||
std::vector<bool> priority_mask;
|
std::vector<bool> priority_mask;
|
||||||
SigSpec clk, en, addr, data;
|
SigSpec clk, en, addr, data;
|
||||||
|
|
Loading…
Reference in New Issue