From 60e6b017cb5f5efde8ef8280ee9780ed650c7743 Mon Sep 17 00:00:00 2001 From: MiO Date: Tue, 12 May 2026 09:38:11 +0200 Subject: [PATCH 1/2] merge L2T5 and upper L2T4 int a single CPE if possible --- himbaechel/uarch/gatemate/pack_cpe.cc | 61 +++++++++++++++++++++------ 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/himbaechel/uarch/gatemate/pack_cpe.cc b/himbaechel/uarch/gatemate/pack_cpe.cc index e9887999..236e875c 100644 --- a/himbaechel/uarch/gatemate/pack_cpe.cc +++ b/himbaechel/uarch/gatemate/pack_cpe.cc @@ -294,20 +294,55 @@ void GateMatePacker::pack_cpe() } } } - for (auto ci : l2t5_list) { - CellInfo *upper = create_cell_ptr(id_CPE_L2T4, ctx->idf("%s$upper", ci->name.c_str(ctx))); - upper->cluster = ci->name; - upper->region = ci->region; - upper->constr_abs_z = true; - upper->constr_z = CPE_LT_U_Z; - ci->movePortTo(id_I4, upper, id_D0_10); - upper->params[id_INIT_L10] = Property(LUT_D0, 4); - ci->constr_children.push_back(upper); - NetInfo *ci_out_conn = ctx->createNet(ctx->idf("%s$combin", ci->name.c_str(ctx))); - upper->connectPort(id_OUT, ci_out_conn); - ci->addInput(id_COMBIN); - ci->connectPort(id_COMBIN, ci_out_conn); + std::sort(l2t5_list.begin(), l2t5_list.end()); + for (auto ci : l2t5_list) { + NetInfo *upperNet = ci->getPort(id_I4); + + bool merge = false; + if (upperNet && + upperNet->driver.cell && + upperNet->driver.cell->type == id_CPE_L2T4 && + upperNet->driver.cell->cluster.empty()) { + auto it = std::lower_bound(l2t5_list.begin(), l2t5_list.end(), upperNet->driver.cell); + merge = it == l2t5_list.end() || *it != upperNet->driver.cell; + } + + if (merge) { + CellInfo *upper = upperNet->driver.cell; + + // rename cell + IdString newName = ctx->idf("%s$upper", ci->name.c_str(ctx)); + auto itOld = ctx->cells.find(upper->name); + ctx->cells.insert(std::pair{newName, move(itOld->second)}); + ctx->cells.erase(itOld); + upper->name = newName; + + // cluster into single CPE + upper->cluster = ci->name; + upper->region = ci->region; + upper->constr_abs_z = true; + upper->constr_z = CPE_LT_U_Z; + ci->constr_children.push_back(upper); + + // rename internal net and port + ctx->renameNet(upperNet->name, ctx->idf("%s$combin", ci->name.c_str(ctx))); + ci->renamePort(id_I4, id_COMBIN); + } else { + CellInfo* upper = create_cell_ptr(id_CPE_L2T4, ctx->idf("%s$upper", ci->name.c_str(ctx))); + upper->cluster = ci->name; + upper->region = ci->region; + upper->constr_abs_z = true; + upper->constr_z = CPE_LT_U_Z; + ci->movePortTo(id_I4, upper, id_D0_10); + upper->params[id_INIT_L10] = Property(LUT_D0, 4); + ci->constr_children.push_back(upper); + + NetInfo *ci_out_conn = ctx->createNet(ctx->idf("%s$combin", ci->name.c_str(ctx))); + upper->connectPort(id_OUT, ci_out_conn); + ci->addInput(id_COMBIN); + ci->connectPort(id_COMBIN, ci_out_conn); + } } l2t5_list.clear(); flush_cells(); From ac4610b594bec9b316b4af81de8e00fe20e079d0 Mon Sep 17 00:00:00 2001 From: MiO Date: Wed, 13 May 2026 21:34:02 +0200 Subject: [PATCH 2/2] do not rename cell and net use pool of IdStream instead of sorted ptr array for determinism --- himbaechel/uarch/gatemate/pack_cpe.cc | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/himbaechel/uarch/gatemate/pack_cpe.cc b/himbaechel/uarch/gatemate/pack_cpe.cc index 236e875c..49bb3395 100644 --- a/himbaechel/uarch/gatemate/pack_cpe.cc +++ b/himbaechel/uarch/gatemate/pack_cpe.cc @@ -181,7 +181,7 @@ void GateMatePacker::override_region(CellInfo *first, CellInfo *second) void GateMatePacker::pack_cpe() { log_info("Packing CPEs..\n"); - std::vector l2t5_list; + pool l2t5_list; auto merge_dff = [&](CellInfo &ci, CellInfo *dff) { dff->cluster = ci.name; @@ -203,7 +203,7 @@ void GateMatePacker::pack_cpe() continue; bool is_l2t5 = false; if (ci.type == id_CC_L2T5) { - l2t5_list.push_back(&ci); + l2t5_list.insert(ci.name); ci.renamePort(id_I0, id_D0_00); ci.renamePort(id_I1, id_D1_00); ci.renamePort(id_I2, id_D0_01); @@ -295,29 +295,18 @@ void GateMatePacker::pack_cpe() } } - std::sort(l2t5_list.begin(), l2t5_list.end()); - for (auto ci : l2t5_list) { + for (auto& it : l2t5_list) { + CellInfo *ci = ctx->cells.at(it).get(); NetInfo *upperNet = ci->getPort(id_I4); - bool merge = false; if (upperNet && upperNet->driver.cell && upperNet->driver.cell->type == id_CPE_L2T4 && - upperNet->driver.cell->cluster.empty()) { - auto it = std::lower_bound(l2t5_list.begin(), l2t5_list.end(), upperNet->driver.cell); - merge = it == l2t5_list.end() || *it != upperNet->driver.cell; - } + upperNet->driver.cell->cluster.empty() && + !l2t5_list.count(upperNet->driver.cell->name)) { - if (merge) { CellInfo *upper = upperNet->driver.cell; - // rename cell - IdString newName = ctx->idf("%s$upper", ci->name.c_str(ctx)); - auto itOld = ctx->cells.find(upper->name); - ctx->cells.insert(std::pair{newName, move(itOld->second)}); - ctx->cells.erase(itOld); - upper->name = newName; - // cluster into single CPE upper->cluster = ci->name; upper->region = ci->region; @@ -325,8 +314,6 @@ void GateMatePacker::pack_cpe() upper->constr_z = CPE_LT_U_Z; ci->constr_children.push_back(upper); - // rename internal net and port - ctx->renameNet(upperNet->name, ctx->idf("%s$combin", ci->name.c_str(ctx))); ci->renamePort(id_I4, id_COMBIN); } else { CellInfo* upper = create_cell_ptr(id_CPE_L2T4, ctx->idf("%s$upper", ci->name.c_str(ctx)));