Gowin. Taking into account the features of ROM

For pROM(X9) primitives in images generated by Gowin IDE, there is an
interesting recommunication of inputs depending on the data bit depth.
For example, in some cases, a high logical level may be applied to the
Write Enable input, which, let’s say, is not entirely usual for Read
Only memory.

Here we will do similar manipulations.

In addition, several minor bug fixes are included:

 - Fixed bit numbering for non-X9 series primitives.
 - Fixed decoder generation for BLKSEL - do not assume unused inputs are
   connected to GND.
 - Use default values for BSRAM parameters - don't assume their
   mandatory presence.

Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
YRabbit 2024-07-04 19:10:07 +10:00
parent ba293437e0
commit 7f58300928

View File

@ -1,6 +1,7 @@
#include "design_utils.h"
#include "log.h"
#include "nextpnr.h"
#include "util.h"
#define HIMBAECHEL_CONSTIDS "uarch/gowin/constids.inc"
#include "himbaechel_constids.h"
@ -1324,7 +1325,7 @@ struct GowinPacker
{
int num = (bit_width == 9 || bit_width == 18 || bit_width == 36) ? 36 : 32;
for (int i = 0, j = offset; i < num; ++i, ++j) {
if (((i + 1) % 9) == 0 && (bit_width == 16 || bit_width == 32)) {
if (((j + 1) % 9) == 0 && (bit_width == 16 || bit_width == 32)) {
++j;
}
ci->renamePort(ctx->idf(from, i), ctx->idf(to, offset ? j % 36 : j));
@ -1390,6 +1391,15 @@ struct GowinPacker
}
++idx;
}
switch (idx) {
case 1:
init |= init << 2; /* fallthrough */
case 2:
init |= init << 4;
break;
default:
break;
}
lut->setParam(id_INIT, init);
new_cells.push_back(std::move(lut_cell));
@ -1406,7 +1416,7 @@ struct GowinPacker
if (bit_width == 32 || bit_width == 36) {
return;
}
int read_mode = ci->params.at(id_READ_MODE).as_int64();
int read_mode = int_or_default(ci->params, id_READ_MODE, 0);
if (read_mode == 0) {
return;
}
@ -1511,7 +1521,7 @@ struct GowinPacker
CellInfo *new_ce_net_src = ce_pre_dff;
// add delay register in pipeline mode
int read_mode = ci->params.at(id_READ_MODE).as_int64();
int read_mode = int_or_default(ci->params, id_READ_MODE, 0);
if (read_mode) {
auto ce_pipe_dff_cell = gwu.create_cell(create_aux_name(ci->name, 0, "_ce_pipe_dff$"), id_DFF);
new_cells.push_back(std::move(ce_pipe_dff_cell));
@ -1587,10 +1597,7 @@ struct GowinPacker
ci->connectPort(port, vcc_net);
}
ci->addInput(id_WRE);
ci->connectPort(id_WRE, vss_net);
ci->addInput(id_WREB);
ci->connectPort(id_WREB, vss_net);
if (!ci->params.count(id_BIT_WIDTH)) {
ci->setParam(id_BIT_WIDTH, Property(default_bw, 32));
@ -1602,10 +1609,19 @@ struct GowinPacker
ci->copyPortTo(id_CE, ci, id_CEB);
ci->copyPortTo(id_OCE, ci, id_OCEB);
ci->copyPortTo(id_RESET, ci, id_RESETB);
ci->connectPort(id_WREB, vcc_net);
for (int i = 0; i < 14; ++i) {
ci->renamePort(ctx->idf("AD[%d]", i), ctx->idf("ADA%d", i));
ci->copyPortTo(ctx->idf("ADA%d", i), ci, ctx->idf("ADB%d", i));
// disconnect lower address bits for ROM
static int rom_ignore_bits[] = {2, 4, 8, 16, 32};
static int romx9_ignore_bits[] = {9, 9, 9, 18, 36};
for (unsigned int i = 0; i < 14; ++i) {
if (i < sizeof(rom_ignore_bits) && ((ci->type == id_pROM && bit_width >= rom_ignore_bits[i]) ||
(ci->type == id_pROMX9 && bit_width >= romx9_ignore_bits[i]))) {
ci->disconnectPort(ctx->idf("AD[%d]", i));
} else {
ci->renamePort(ctx->idf("AD[%d]", i), ctx->idf("ADA%d", i));
ci->copyPortTo(ctx->idf("ADA%d", i), ci, ctx->idf("ADB%d", i));
}
}
bsram_rename_ports(ci, bit_width, "DO[%d]", "DO%d");
} else {
@ -1614,9 +1630,18 @@ struct GowinPacker
ci->renamePort(id_OCE, id_OCEB);
ci->renamePort(id_CE, id_CEB);
ci->renamePort(id_RESET, id_RESETB);
ci->connectPort(id_WREB, vss_net);
ci->addInput(id_CEA);
ci->connectPort(id_CEA, vss_net);
ci->addInput(id_CE);
ci->connectPort(id_CE, vcc_net);
ci->disconnectPort(id_OCEB);
int read_mode = int_or_default(ci->params, id_READ_MODE, 0);
if (read_mode) {
ci->connectPort(id_OCEB, vcc_net);
} else {
ci->copyPortTo(id_CEB, ci, id_OCEB);
}
for (int i = 0; i < 14; ++i) {
ci->renamePort(ctx->idf("AD[%d]", i), ctx->idf("ADB%d", i));
}
@ -1798,6 +1823,15 @@ struct GowinPacker
bsram_fix_blksel(ci, new_cells);
}
// XXX
NetInfo *oce_net = ci->getPort(id_OCE);
if (oce_net == nullptr || oce_net->name == ctx->id("$PACKER_VCC") || oce_net->name == ctx->id("$PACKER_GND")) {
if (oce_net != nullptr) {
ci->disconnectPort(id_OCE);
ci->copyPortTo(id_CE, ci, id_OCE);
}
}
// XXX UG285-1.3.6_E Gowin BSRAM & SSRAM User Guide:
// For GW1N-9/GW1NR-9/GW1NS-4 series, 32/36-bit SP/SPX9 is divided into two
// SP/SPX9s, which occupy two BSRAMs.