From 1871afe9b9970af8adc410b2715746c0bdeade50 Mon Sep 17 00:00:00 2001 From: YRabbit Date: Thu, 4 Jul 2024 19:10:07 +1000 Subject: [PATCH] Gowin. Taking into account the features of ROM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- himbaechel/uarch/gowin/pack.cc | 56 +++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/himbaechel/uarch/gowin/pack.cc b/himbaechel/uarch/gowin/pack.cc index 7fedad6e15..bc8f70fde4 100644 --- a/himbaechel/uarch/gowin/pack.cc +++ b/himbaechel/uarch/gowin/pack.cc @@ -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_CE); + ci->connectPort(id_CE, vcc_net); + ci->disconnectPort(id_OCEB); - ci->addInput(id_CEA); - ci->connectPort(id_CEA, vss_net); + 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.