From ec4d783d4c4c155f43b72054b367c6f47c8f3a14 Mon Sep 17 00:00:00 2001 From: YRabbit Date: Mon, 29 Jul 2024 16:19:04 +1000 Subject: [PATCH] Gowin. BUGFIX. Fix placement checks It was not taken into account that there are only 6 ALUs per cell. As a result, on complex designs where ALUs and LUT-based memory are involved and there are many LUTs (like in the RISCV emulator), there were sometimes false positives about placement conflicts. Signed-off-by: YRabbit --- himbaechel/uarch/gowin/gowin.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/himbaechel/uarch/gowin/gowin.cc b/himbaechel/uarch/gowin/gowin.cc index 8942154b33..b9ca90707d 100644 --- a/himbaechel/uarch/gowin/gowin.cc +++ b/himbaechel/uarch/gowin/gowin.cc @@ -539,8 +539,10 @@ bool GowinImpl::dsp_valid(Loc l, IdString bel_type, bool explain_invalid) const bool GowinImpl::slice_valid(int x, int y, int z) const { const CellInfo *lut = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, z * 2))); + const bool lut_in_4_5 = lut && (z == 4 || z == 5); const CellInfo *ff = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, z * 2 + 1))); - const CellInfo *alu = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, z + BelZ::ALU0_Z))); + // There are only 6 ALUs + const CellInfo *alu = (z < 6) ? ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, z + BelZ::ALU0_Z))) : nullptr; const CellInfo *ramw = (z == 4 || z == 5) ? ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, BelZ::RAMW_Z))) : nullptr; @@ -549,7 +551,7 @@ bool GowinImpl::slice_valid(int x, int y, int z) const } if (ramw) { - if (alu || ff || lut) { + if (alu || ff || lut_in_4_5) { return false; } return true; @@ -560,7 +562,9 @@ bool GowinImpl::slice_valid(int x, int y, int z) const int adj_alu_z = adj_lut_z / 2 + BelZ::ALU0_Z; const CellInfo *adj_lut = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, adj_lut_z))); const CellInfo *adj_ff = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, adj_lut_z + 1))); - const CellInfo *adj_alu = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, adj_alu_z))); + const CellInfo *adj_alu = adj_alu_z < (6 + BelZ::ALU0_Z) + ? ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, adj_alu_z))) + : nullptr; if ((alu && (adj_lut || (adj_ff && !adj_alu))) || ((lut || (ff && !alu)) && adj_alu)) { return false;