From 9f441ba45539849222c0cee7ee31ee96e72ebb37 Mon Sep 17 00:00:00 2001 From: Michael Offel Date: Sun, 12 Jul 2026 11:29:43 +0200 Subject: [PATCH] fix association of BRAM port to clock in SDP mode (#1746) Co-authored-by: MiO --- himbaechel/uarch/gatemate/delay.cc | 27 +++++++++++++++++++++- himbaechel/uarch/gatemate/gatemate.cc | 32 +++++++++++++-------------- himbaechel/uarch/gatemate/gatemate.h | 21 +++++++++++++++++- 3 files changed, 62 insertions(+), 18 deletions(-) diff --git a/himbaechel/uarch/gatemate/delay.cc b/himbaechel/uarch/gatemate/delay.cc index dc93d56b..6f5b8700 100644 --- a/himbaechel/uarch/gatemate/delay.cc +++ b/himbaechel/uarch/gatemate/delay.cc @@ -355,6 +355,31 @@ IdString clock(uint8_t val, IdString clk1, IdString clk2, IdString clk3, IdStrin } } +int GateMateImpl::ram_clock_index(const CellInfo *cell, const RamPinInfo &pin) const +{ + int mode = int_or_default(cell->params, id_RAM_cfg_sram_mode, 0); + bool split = mode & 0b01; + bool sdp = mode & 0b10; + + bool domain_b = pin.port_b; + if (sdp) { + switch (pin.kind) { + case RamPinKind::DATA_IN: + case RamPinKind::BITMASK: + domain_b = false; + break; + case RamPinKind::DATA_OUT: + case RamPinKind::ECC_STATUS: + domain_b = true; + break; + default: + break; + } + } + // Native 40K blocks only use the a0/b0 control sets + return (domain_b ? 2 : 0) + (split ? pin.half : 0); +} + TimingClockingInfo GateMateImpl::getPortClockingInfo(const CellInfo *cell, IdString port, int index) const { TimingClockingInfo info; @@ -484,7 +509,7 @@ TimingClockingInfo GateMateImpl::getPortClockingInfo(const CellInfo *cell, IdStr clock(b1_clk_val, ctx->id("CLKB[2]"), ctx->id("CLKB[3]"), ctx->id("CLKA[2]"), ctx->id("CLKA[3]")); if (ram_signal_clk.count(port)) { IdString edge_param; - switch (ram_signal_clk.at(port)) { + switch (ram_clock_index(cell, ram_signal_clk.at(port))) { case 0: edge_param = id_RAM_cfg_inversion_a0; info.clock_port = a0_clk; diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index 4d96ffc2..6c08e76f 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -152,29 +152,29 @@ void GateMateImpl::init(Context *ctx) } for (int num = 0; num < 2; num++) { int index = (num == 0) ? 0 : 2; - ram_signal_clk.emplace(ctx->idf("ENA[%d]", index), num); - ram_signal_clk.emplace(ctx->idf("ENB[%d]", index), num + 2); - ram_signal_clk.emplace(ctx->idf("GLWEA[%d]", index), num); - ram_signal_clk.emplace(ctx->idf("GLWEB[%d]", index), num + 2); - ram_signal_clk.emplace(ctx->idf("ECC1B_ERRA[%d]", index), num); - ram_signal_clk.emplace(ctx->idf("ECC1B_ERRB[%d]", index), num + 2); - ram_signal_clk.emplace(ctx->idf("ECC2B_ERRA[%d]", index), num); - ram_signal_clk.emplace(ctx->idf("ECC2B_ERRB[%d]", index), num + 2); + ram_signal_clk.emplace(ctx->idf("ENA[%d]", index), RamPinInfo{RamPinKind::CTRL, false, num}); + ram_signal_clk.emplace(ctx->idf("ENB[%d]", index), RamPinInfo{RamPinKind::CTRL, true, num}); + ram_signal_clk.emplace(ctx->idf("GLWEA[%d]", index), RamPinInfo{RamPinKind::CTRL, false, num}); + ram_signal_clk.emplace(ctx->idf("GLWEB[%d]", index), RamPinInfo{RamPinKind::CTRL, true, num}); + ram_signal_clk.emplace(ctx->idf("ECC1B_ERRA[%d]", index), RamPinInfo{RamPinKind::ECC_STATUS, false, num}); + ram_signal_clk.emplace(ctx->idf("ECC1B_ERRB[%d]", index), RamPinInfo{RamPinKind::ECC_STATUS, true, num}); + ram_signal_clk.emplace(ctx->idf("ECC2B_ERRA[%d]", index), RamPinInfo{RamPinKind::ECC_STATUS, false, num}); + ram_signal_clk.emplace(ctx->idf("ECC2B_ERRB[%d]", index), RamPinInfo{RamPinKind::ECC_STATUS, true, num}); for (int i = 0; i < 20; i++) { - ram_signal_clk.emplace(ctx->idf("WEA[%d]", i + num * 20), num); - ram_signal_clk.emplace(ctx->idf("WEB[%d]", i + num * 20), num + 2); + ram_signal_clk.emplace(ctx->idf("WEA[%d]", i + num * 20), RamPinInfo{RamPinKind::BITMASK, false, num}); + ram_signal_clk.emplace(ctx->idf("WEB[%d]", i + num * 20), RamPinInfo{RamPinKind::BITMASK, true, num}); } for (int i = 0; i < 16; i++) { - ram_signal_clk.emplace(ctx->idf("ADDRA%d[%d]", num, i), num); - ram_signal_clk.emplace(ctx->idf("ADDRB%d[%d]", num, i), num + 2); + ram_signal_clk.emplace(ctx->idf("ADDRA%d[%d]", num, i), RamPinInfo{RamPinKind::ADDR, false, num}); + ram_signal_clk.emplace(ctx->idf("ADDRB%d[%d]", num, i), RamPinInfo{RamPinKind::ADDR, true, num}); } for (int i = 0; i < 20; i++) { - ram_signal_clk.emplace(ctx->idf("DIA[%d]", i + num * 20), num); - ram_signal_clk.emplace(ctx->idf("DOA[%d]", i + num * 20), num); - ram_signal_clk.emplace(ctx->idf("DIB[%d]", i + num * 20), num + 2); - ram_signal_clk.emplace(ctx->idf("DOB[%d]", i + num * 20), num + 2); + ram_signal_clk.emplace(ctx->idf("DIA[%d]", i + num * 20), RamPinInfo{RamPinKind::DATA_IN, false, num}); + ram_signal_clk.emplace(ctx->idf("DOA[%d]", i + num * 20), RamPinInfo{RamPinKind::DATA_OUT, false, num}); + ram_signal_clk.emplace(ctx->idf("DIB[%d]", i + num * 20), RamPinInfo{RamPinKind::DATA_IN, true, num}); + ram_signal_clk.emplace(ctx->idf("DOB[%d]", i + num * 20), RamPinInfo{RamPinKind::DATA_OUT, true, num}); } } diff --git a/himbaechel/uarch/gatemate/gatemate.h b/himbaechel/uarch/gatemate/gatemate.h index 746e5bf8..5fc003f0 100644 --- a/himbaechel/uarch/gatemate/gatemate.h +++ b/himbaechel/uarch/gatemate/gatemate.h @@ -153,7 +153,26 @@ struct GateMateImpl : HimbaechelAPI std::vector fast_cell_info; std::map> pin_to_constr; std::map timing; - dict ram_signal_clk; + + enum class RamPinKind + { + DATA_IN, + DATA_OUT, + BITMASK, + ADDR, + CTRL, + ECC_STATUS, + }; + struct RamPinInfo + { + RamPinKind kind; + bool port_b; // physical A/B pin side + int half; // 0 or 1 (bit index / 20, resp. control set 0/1) + }; + // Resolve the clock domain (0=a0, 1=a1, 2=b0, 3=b1) a RAM pin is timed + // against, depending on the cell mode. + int ram_clock_index(const CellInfo *cell, const RamPinInfo &pin) const; + dict ram_signal_clk; IdString forced_die; bool use_cp_for_clk; bool use_cp_for_cpe;