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:
parent
ba293437e0
commit
7f58300928
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user