From 16c94acda9c08556a496fc26be4c1f017a07ba2f Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 9 Jul 2025 09:23:32 +0200 Subject: [PATCH] Check if DFFs are compatible before merging --- himbaechel/uarch/gatemate/gatemate.cc | 34 ++++++++++++++++----------- himbaechel/uarch/gatemate/gatemate.h | 2 ++ himbaechel/uarch/gatemate/pack_cpe.cc | 19 ++++++++++++--- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index 2a4a503a..b9a28ebf 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -205,6 +205,25 @@ void GateMateImpl::configurePlacerHeap(PlacerHeapCfg &cfg) cfg.placeAllAtOnce = true; } +int GateMateImpl::get_dff_config(CellInfo *dff) const +{ + int val = 0; + val |= int_or_default(dff->params, id_C_CPE_EN, 0); + val <<= 2; + val |= int_or_default(dff->params, id_C_CPE_CLK, 0); + val <<= 2; + val |= int_or_default(dff->params, id_C_CPE_RES, 0); + val <<= 2; + val |= int_or_default(dff->params, id_C_CPE_SET, 0); + val <<= 2; + val |= int_or_default(dff->params, id_C_EN_SR, 0); + val <<= 1; + val |= int_or_default(dff->params, id_C_L_D, 0); + val <<= 1; + val |= int_or_default(dff->params, id_FF_INIT, 0); + return val; +} + void GateMateImpl::assign_cell_info() { fast_cell_info.resize(ctx->cells.size()); @@ -215,20 +234,7 @@ void GateMateImpl::assign_cell_info() fc.ff_en = ci->getPort(id_EN); fc.ff_clk = ci->getPort(id_CLK); fc.ff_sr = ci->getPort(id_SR); - fc.ff_config = 0; - fc.ff_config |= int_or_default(ci->params, id_C_CPE_EN, 0); - fc.ff_config <<= 2; - fc.ff_config |= int_or_default(ci->params, id_C_CPE_CLK, 0); - fc.ff_config <<= 2; - fc.ff_config |= int_or_default(ci->params, id_C_CPE_RES, 0); - fc.ff_config <<= 2; - fc.ff_config |= int_or_default(ci->params, id_C_CPE_SET, 0); - fc.ff_config <<= 2; - fc.ff_config |= int_or_default(ci->params, id_C_EN_SR, 0); - fc.ff_config <<= 1; - fc.ff_config |= int_or_default(ci->params, id_C_L_D, 0); - fc.ff_config <<= 1; - fc.ff_config |= int_or_default(ci->params, id_FF_INIT, 0); + fc.ff_config = get_dff_config(ci); fc.dff_used = true; } } diff --git a/himbaechel/uarch/gatemate/gatemate.h b/himbaechel/uarch/gatemate/gatemate.h index d2b16dca..43ecf246 100644 --- a/himbaechel/uarch/gatemate/gatemate.h +++ b/himbaechel/uarch/gatemate/gatemate.h @@ -64,6 +64,8 @@ struct GateMateImpl : HimbaechelAPI const GateMateTileExtraDataPOD *tile_extra_data(int tile) const; + int get_dff_config(CellInfo *dff) const; + std::set available_pads; std::map bel_to_pad; pool ddr_nets; diff --git a/himbaechel/uarch/gatemate/pack_cpe.cc b/himbaechel/uarch/gatemate/pack_cpe.cc index 0693c8cb..22d121a8 100644 --- a/himbaechel/uarch/gatemate/pack_cpe.cc +++ b/himbaechel/uarch/gatemate/pack_cpe.cc @@ -461,11 +461,21 @@ void GateMatePacker::pack_addf() } }; - auto merge_dff = [&](CellInfo *cell, IdString port) { + auto merge_dff = [&](CellInfo *cell, IdString port, CellInfo *other) -> CellInfo * { NetInfo *o = cell->getPort(port); if (o) { CellInfo *dff = net_only_drives(ctx, o, is_dff, id_D, true); if (dff) { + if (other) { + if (dff->getPort(id_CLK) != other->getPort(id_CLK)) + return nullptr; + if (dff->getPort(id_EN) != other->getPort(id_EN)) + return nullptr; + if (dff->getPort(id_SR) != other->getPort(id_SR)) + return nullptr; + if (uarch->get_dff_config(dff) != uarch->get_dff_config(other)) + return nullptr; + } dff->cluster = cell->cluster; dff->constr_abs_z = false; dff->constr_z = +2; @@ -473,8 +483,10 @@ void GateMatePacker::pack_addf() dff->renamePort(id_D, id_DIN); dff->renamePort(id_Q, id_DOUT); dff->type = (dff->type == id_CC_DLT) ? id_CPE_LATCH : id_CPE_FF; + return dff; } } + return nullptr; }; for (auto &grp : splitNestedVector(groups)) { @@ -557,14 +569,15 @@ void GateMatePacker::pack_addf() upper->constr_abs_z = false; upper->constr_y = +i; upper->constr_z = -1; + CellInfo *other_dff = nullptr; if (merged) { cy->movePortTo(id_S, upper, id_OUT); cy->renamePort(id_S2, id_OUT); - merge_dff(upper, id_OUT); + other_dff = merge_dff(upper, id_OUT, other_dff); } else { cy->renamePort(id_S, id_OUT); } - merge_dff(cy, id_OUT); + merge_dff(cy, id_OUT, other_dff); merge_input(cy, upper, id_A, id_INIT_L00, id_IN1, id_IN2); merge_input(cy, upper, id_B, id_INIT_L01, id_IN3, id_IN4); upper->params[id_INIT_L10] = Property(LUT_XOR, 4); // XOR