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.