From 111f085d6464d944a73b30c48c8df70aec4c6095 Mon Sep 17 00:00:00 2001 From: YRabbit Date: Fri, 6 Mar 2026 08:40:20 +1000 Subject: [PATCH] GOWIN. Fix dual port CE-OCE. We are fixing a hardware error - in BYPASS mode, dual port bsram requires synchronization of CE and OCE signals for some data widths. We are also getting rid of port renaming in the loop, but not all of them yet. Signed-off-by: YRabbit --- himbaechel/uarch/gowin/gowin.h | 1 + himbaechel/uarch/gowin/gowin_arch_gen.py | 3 +++ himbaechel/uarch/gowin/gowin_utils.cc | 6 +++++ himbaechel/uarch/gowin/gowin_utils.h | 1 + himbaechel/uarch/gowin/pack.cc | 8 +++---- himbaechel/uarch/gowin/pack_bsram.cc | 28 +++++++++++++++--------- 6 files changed, 33 insertions(+), 14 deletions(-) diff --git a/himbaechel/uarch/gowin/gowin.h b/himbaechel/uarch/gowin/gowin.h index 5d79eb30..62e236b6 100644 --- a/himbaechel/uarch/gowin/gowin.h +++ b/himbaechel/uarch/gowin/gowin.h @@ -226,6 +226,7 @@ NPNR_PACKED_STRUCT(struct Extra_chip_data_POD { static constexpr int32_t NEED_CFGPINS_INVERSION = 4096; static constexpr int32_t HAS_I2CCFG = 8192; static constexpr int32_t HAS_5A_DSP = 16384; + static constexpr int32_t NEED_BSRAM_DP_CE_FIX = 32768; }); } // namespace diff --git a/himbaechel/uarch/gowin/gowin_arch_gen.py b/himbaechel/uarch/gowin/gowin_arch_gen.py index 3c1f5aff..648d45e4 100644 --- a/himbaechel/uarch/gowin/gowin_arch_gen.py +++ b/himbaechel/uarch/gowin/gowin_arch_gen.py @@ -34,6 +34,7 @@ CHIP_NEED_SDP_FIX = 0x800 CHIP_NEED_CFGPINS_INVERSION = 0x1000 CHIP_HAS_I2CCFG = 0x2000 CHIP_HAS_5A_DSP = 0x4000 +CHIP_NEED_BSRAM_DP_CE_FIX = 0x8000 # Tile flags TILE_I3C_CAPABLE_IO = 0x1 @@ -1768,6 +1769,8 @@ def main(): chip_flags |= CHIP_NEED_SP_FIX; if "NEED_BSRAM_OUTREG_FIX" in db.chip_flags: chip_flags |= CHIP_NEED_BSRAM_OUTREG_FIX; + if "NEED_BSRAM_DP_CE_FIX" in db.chip_flags: + chip_flags |= CHIP_NEED_BSRAM_DP_CE_FIX; if "NEED_BLKSEL_FIX" in db.chip_flags: chip_flags |= CHIP_NEED_BLKSEL_FIX; if "HAS_BANDGAP" in db.chip_flags: diff --git a/himbaechel/uarch/gowin/gowin_utils.cc b/himbaechel/uarch/gowin/gowin_utils.cc index 371e3365..5b675c61 100644 --- a/himbaechel/uarch/gowin/gowin_utils.cc +++ b/himbaechel/uarch/gowin/gowin_utils.cc @@ -449,6 +449,12 @@ bool GowinUtils::need_BSRAM_OUTREG_fix(void) return extra->chip_flags & Extra_chip_data_POD::NEED_BSRAM_OUTREG_FIX; } +bool GowinUtils::need_BSRAM_DP_CE_fix(void) +{ + const Extra_chip_data_POD *extra = reinterpret_cast(ctx->chip_info->extra_data.get()); + return extra->chip_flags & Extra_chip_data_POD::NEED_BSRAM_DP_CE_FIX; +} + bool GowinUtils::need_BSRAM_RESET_fix(void) { const Extra_chip_data_POD *extra = reinterpret_cast(ctx->chip_info->extra_data.get()); diff --git a/himbaechel/uarch/gowin/gowin_utils.h b/himbaechel/uarch/gowin/gowin_utils.h index aebae06d..6e960855 100644 --- a/himbaechel/uarch/gowin/gowin_utils.h +++ b/himbaechel/uarch/gowin/gowin_utils.h @@ -110,6 +110,7 @@ struct GowinUtils bool need_SP_fix(void); bool need_SDP_fix(void); bool need_BSRAM_OUTREG_fix(void); + bool need_BSRAM_DP_CE_fix(void); bool need_BSRAM_RESET_fix(void); bool need_BLKSEL_fix(void); bool has_PLL_HCLK(void); diff --git a/himbaechel/uarch/gowin/pack.cc b/himbaechel/uarch/gowin/pack.cc index 03502bd8..ab2327a6 100644 --- a/himbaechel/uarch/gowin/pack.cc +++ b/himbaechel/uarch/gowin/pack.cc @@ -197,7 +197,7 @@ void GowinPacker::pack_adc(void) auto &ci = *cell.second; if (is_adc(&ci)) { - gwu.remove_brackets(&ci); + gwu.remove_brackets(&ci); } } } @@ -265,7 +265,7 @@ void GowinPacker::pack_dlldly(void) log_info(" pack %s to use clock pin at %s\n", ctx->nameOf(ci), ctx->nameOfBel(io_bel)); } ctx->bindBel(dlldly_bel, ci, STRENGTH_LOCKED); - gwu.remove_brackets(ci); + gwu.remove_brackets(ci); } } @@ -439,7 +439,7 @@ void GowinPacker::pack_userflash(bool have_emcu) ci.addInput(id_INUSEN); ci.connectPort(id_INUSEN, ctx->nets.at(ctx->id("$PACKER_GND")).get()); } - gwu.remove_brackets(&ci); + gwu.remove_brackets(&ci); if (have_emcu) { continue; @@ -505,7 +505,7 @@ void GowinPacker::pack_emcu_and_flash(void) } have_emcu = true; - gwu.remove_brackets(&ci); + gwu.remove_brackets(&ci); // The flash data bus is connected directly to the CPU so just disconnect these networks // also other non-switched networks diff --git a/himbaechel/uarch/gowin/pack_bsram.cc b/himbaechel/uarch/gowin/pack_bsram.cc index 59b8ceeb..1e3ad5d4 100644 --- a/himbaechel/uarch/gowin/pack_bsram.cc +++ b/himbaechel/uarch/gowin/pack_bsram.cc @@ -475,16 +475,6 @@ void GowinPacker::pack_DPB(CellInfo *ci) default_bw = 18; } - for (int i = 0; i < 14; ++i) { - ci->renamePort(ctx->idf("ADA[%d]", i), ctx->idf("ADA%d", i)); - ci->renamePort(ctx->idf("ADB[%d]", i), ctx->idf("ADB%d", i)); - } - - for (int i = 0; i < 3; ++i) { - ci->renamePort(ctx->idf("BLKSELA[%d]", i), ctx->idf("BLKSELA%d", i)); - ci->renamePort(ctx->idf("BLKSELB[%d]", i), ctx->idf("BLKSELB%d", i)); - } - if (!ci->params.count(id_BIT_WIDTH_0)) { ci->setParam(id_BIT_WIDTH_0, Property(default_bw, 32)); } @@ -492,12 +482,30 @@ void GowinPacker::pack_DPB(CellInfo *ci) bsram_rename_ports(ci, bit_width, "DIA[%d]", "DIA%d"); bsram_rename_ports(ci, bit_width, "DOA[%d]", "DOA%d"); + // In BYPASS mode, the OCE signal is dictated by CE. + if (gwu.need_BSRAM_DP_CE_fix()) { + if (bit_width <= 9) { + ci->disconnectPort(id_OCEA); + ci->copyPortTo(id_CEA, ci, id_OCEA); + } + } + if (!ci->params.count(id_BIT_WIDTH_1)) { ci->setParam(id_BIT_WIDTH_1, Property(default_bw, 32)); } bit_width = ci->params.at(id_BIT_WIDTH_1).as_int64(); bsram_rename_ports(ci, bit_width, "DIB[%d]", "DIB%d"); bsram_rename_ports(ci, bit_width, "DOB[%d]", "DOB%d"); + + // In BYPASS mode, the OCE signal is dictated by CE. + if (gwu.need_BSRAM_DP_CE_fix()) { + if (bit_width <= 9) { + ci->disconnectPort(id_OCEB); + ci->copyPortTo(id_CEB, ci, id_OCEB); + } + } + + gwu.remove_brackets(ci); } void GowinPacker::divide_sp(CellInfo *ci, std::vector> &new_cells)