gatemate: delay, assign proper RAM clock

This commit is contained in:
Miodrag Milanovic 2025-08-25 10:55:19 +02:00
parent d796cc720b
commit 84234e7d79
4 changed files with 83 additions and 2 deletions

View File

@ -110,6 +110,8 @@ bool GateMateImpl::getCellDelay(const CellInfo *cell, IdString fromPort, IdStrin
return get_delay_from_tmg_db(ctx->idf("timing__MULT_%s_%s", fromPort.c_str(ctx), toPort.c_str(ctx)), delay);
} else if (cell->type.in(id_CPE_FF, id_CPE_LATCH, id_CPE_FF_L, id_CPE_FF_U)) {
return false;
} else if (cell->type.in(id_CPE_CPLINES)) {
return true;
} else if (cell->type.in(id_CPE_COMP)) {
return get_delay_from_tmg_db(fromPort == id_COMB1 ? id_timing_comb1_compout : id_timing_comb2_compout, delay);
} else if (cell->type.in(id_CPE_RAMI, id_CPE_RAMO, id_CPE_RAMIO)) {
@ -277,6 +279,30 @@ TimingPortClass GateMateImpl::getPortTimingClass(const CellInfo *cell, IdString
}
}
IdString clock(uint8_t val, IdString clk1, IdString clk2, IdString clk3, IdString clk4)
{
switch (val) {
case 0b00000000:
return clk1;
case 0b00000100:
return clk2;
case 0b00001000:
return clk3;
case 0b00001100:
return clk4;
case 0b00100011:
return id_CLOCK1;
case 0b00110011:
return id_CLOCK2;
case 0b00000011:
return id_CLOCK3;
case 0b00010011:
return id_CLOCK4;
default:
return clk1;
}
}
TimingClockingInfo GateMateImpl::getPortClockingInfo(const CellInfo *cell, IdString port, int index) const
{
TimingClockingInfo info;
@ -346,8 +372,36 @@ TimingClockingInfo GateMateImpl::getPortClockingInfo(const CellInfo *cell, IdStr
inverted = int_or_default(cell->params, id_B_CLK_INV, 0);
info.edge = inverted ? FALLING_EDGE : RISING_EDGE;
// TODO: Fix which clock is actually used
info.clock_port = is_clk_b ? id_CLOCK1 : id_CLOCK1;
uint8_t a0_clk_val = int_or_default(cell->params, id_RAM_cfg_forward_a0_clk, 0);
uint8_t a1_clk_val = int_or_default(cell->params, id_RAM_cfg_forward_a1_clk, 0);
uint8_t b0_clk_val = int_or_default(cell->params, id_RAM_cfg_forward_b0_clk, 0);
uint8_t b1_clk_val = int_or_default(cell->params, id_RAM_cfg_forward_b1_clk, 0);
IdString a0_clk =
clock(a0_clk_val, ctx->id("CLKA[0]"), ctx->id("CLKA[1]"), ctx->id("CLKB[0]"), ctx->id("CLKB[1]"));
IdString a1_clk =
clock(a1_clk_val, ctx->id("CLKA[2]"), ctx->id("CLKA[3]"), ctx->id("CLKB[2]"), ctx->id("CLKB[3]"));
IdString b0_clk =
clock(b0_clk_val, ctx->id("CLKB[0]"), ctx->id("CLKB[1]"), ctx->id("CLKA[0]"), ctx->id("CLKA[1]"));
IdString b1_clk =
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)) {
switch (ram_signal_clk.at(port)) {
case 0:
info.clock_port = a0_clk;
break;
case 1:
info.clock_port = a1_clk;
break;
case 2:
info.clock_port = b0_clk;
break;
case 3:
info.clock_port = b1_clk;
break;
}
} else {
log_error("Uknown clock signal for %s\n", name.c_str());
}
}
return info;

View File

@ -130,6 +130,29 @@ void GateMateImpl::init(Context *ctx)
for (int i = 0; i < sp->timings.ssize(); i++) {
timing.emplace(IdString(sp->timings[i].name), &sp->timings[i]);
}
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);
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);
}
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);
}
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);
}
}
}
bool GateMateImpl::isBelLocationValid(BelId bel, bool explain_invalid) const

View File

@ -112,6 +112,7 @@ struct GateMateImpl : HimbaechelAPI
std::vector<GateMateCellInfo> fast_cell_info;
std::map<BelId, std::map<IdString, const GateMateBelPinConstraintPOD *>> pin_to_constr;
std::map<IdString, const GateMateTimingExtraDataPOD *> timing;
dict<IdString, int> ram_signal_clk;
};
NEXTPNR_NAMESPACE_END

View File

@ -149,6 +149,9 @@ void GateMatePacker::pack_ram_cell(CellInfo &ci, CellInfo *cell, int num, bool i
int a_do_reg = int_or_default(cell->params, id_A_DO_REG, 0);
int b_do_reg = int_or_default(cell->params, id_B_DO_REG, 0);
disconnect_if_gnd(cell, id_A_CLK);
disconnect_if_gnd(cell, id_B_CLK);
uint8_t cfg_a = ram_clk_signal(cell, id_A_CLK);
uint8_t cfg_b = ram_clk_signal(cell, id_B_CLK);
uint8_t a_inv = a_clk_inv << 2 | a_we_inv << 1 | a_en_inv;