From f2c736ef8149026310a12c3fe3027c15b5b8002b Mon Sep 17 00:00:00 2001 From: Hannah Ravensloft Date: Sun, 13 Jul 2025 23:24:20 +0100 Subject: [PATCH 01/34] Beginnings of the multiplier router --- himbaechel/uarch/gatemate/gatemate.cc | 91 ++++++++++++++++++++++++++ himbaechel/uarch/gatemate/gatemate.h | 1 + himbaechel/uarch/gatemate/pack.cc | 2 +- himbaechel/uarch/gatemate/pack_mult.cc | 2 + 4 files changed, 95 insertions(+), 1 deletion(-) diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index b9a28ebf..b77872c2 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -187,6 +187,97 @@ void GateMateImpl::preRoute() { ctx->assignArchInfo(); route_clock(); + + log_info("Routing multipliers...\n"); + + // I am fully aware the nextpnr API is absolutely not designed around naming specific pips. + // Unfortunately, this is the easiest way to describe the specific routing required. + // Myrtle, please forgive me. + for (auto &a_passthru : this->multiplier_a_passthrus) { + auto *lower = a_passthru.first; + auto *upper = a_passthru.second; + + auto *lower_out = lower->ports.at(id_OUT).net; + auto *upper_out = upper->ports.at(id_OUT).net; + + auto loc = ctx->getBelLocation(lower->bel); + log_info(" A passthrough at (%d, %d) has 4-group (%d, %d)\n", loc.x, loc.y, (loc.x - 3) % 4, (loc.y - 3) % 4); + log_info(" lower.OUT [OUT1] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(lower->bel, id_OUT))); + log_info(" upper.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(upper->bel, id_OUT))); + + auto x_fourgroup = (loc.x - 3) % 4; + auto y_fourgroup = (loc.y - 3) % 4; + + auto find_downhill_pip = [&](WireId from, WireId to) { + NPNR_ASSERT(from != WireId()); + NPNR_ASSERT(to != WireId()); + for (auto pip : ctx->getPipsDownhill(from)) { + if (ctx->getPipDstWire(pip) == to) + return pip; + } + log_error("Couldn't find pip from %s to %s\n", ctx->nameOfWire(from), ctx->nameOfWire(to)); + }; + + if (x_fourgroup == 0 && y_fourgroup == 0) { + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); + auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); + + { + log_info(" routing net '%s'\n", lower_out->name.c_str(ctx)); + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); + auto cpe_in5 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5"))); + auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); + + ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1), lower_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(cpe_out1, sb_big), lower_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_big, in_mux), lower_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(cpe_in5, cpe_in5_int), lower_out, STRENGTH_USER); + } + + { + log_info(" routing net '%s'\n", upper_out->name.c_str(ctx)); + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); + auto cpe_in1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1"))); + auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); + + ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_big), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_big, in_mux), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(cpe_in1, cpe_in1_int), upper_out, STRENGTH_USER); + + auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); + auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); + auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.Y1_int"))); + auto sb_big_d2_1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.D2_1"))); + auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.Y1"))); + auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.YDIAG"))); + auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); + auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); + + ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(out_mux_y, sb_sml), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_sml, sb_big_d2_1), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_big_d2_1, sb_big_y1), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_big_y1, sb_big_ydiag), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_big_ydiag, in_mux_p12), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(in_mux_p08, cpe_in8_int), upper_out, STRENGTH_USER); + } + } + } } void GateMateImpl::postRoute() diff --git a/himbaechel/uarch/gatemate/gatemate.h b/himbaechel/uarch/gatemate/gatemate.h index 43ecf246..148dce55 100644 --- a/himbaechel/uarch/gatemate/gatemate.h +++ b/himbaechel/uarch/gatemate/gatemate.h @@ -73,6 +73,7 @@ struct GateMateImpl : HimbaechelAPI int dies; int preferred_die; std::vector multipliers; + std::vector> multiplier_a_passthrus; private: bool getChildPlacement(const BaseClusterInfo *cluster, Loc root_loc, diff --git a/himbaechel/uarch/gatemate/pack.cc b/himbaechel/uarch/gatemate/pack.cc index 393f56c7..f2caef1d 100644 --- a/himbaechel/uarch/gatemate/pack.cc +++ b/himbaechel/uarch/gatemate/pack.cc @@ -397,7 +397,7 @@ void GateMateImpl::pack() packer.pack_misc(); packer.pack_ram(); packer.pack_serdes(); - // packer.pack_mult(); + packer.pack_mult(); packer.pack_addf(); packer.pack_cpe(); packer.remove_constants(); diff --git a/himbaechel/uarch/gatemate/pack_mult.cc b/himbaechel/uarch/gatemate/pack_mult.cc index 0195bafa..06226fa9 100644 --- a/himbaechel/uarch/gatemate/pack_mult.cc +++ b/himbaechel/uarch/gatemate/pack_mult.cc @@ -412,6 +412,8 @@ void GateMatePacker::pack_mult() a_passthru_comp->connectPort(id_COMPOUT, comp_conn); a_passthru_lines->connectPort(id_COMPOUT, comp_conn); + uarch->multiplier_a_passthrus.push_back({a_passthru_lower, a_passthru_upper}); + return APassThroughCell{a_passthru_lower, a_passthru_upper, a_passthru_comp, a_passthru_lines, name}; }; From 8047369347b3540f1c5535b8791a547f2bf8f971 Mon Sep 17 00:00:00 2001 From: Hannah Ravensloft Date: Mon, 14 Jul 2025 00:54:58 +0100 Subject: [PATCH 02/34] better inversion verification --- himbaechel/uarch/gatemate/bitstream.cc | 50 ++++++++++++++++++++------ himbaechel/uarch/gatemate/gatemate.cc | 8 ++++- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/himbaechel/uarch/gatemate/bitstream.cc b/himbaechel/uarch/gatemate/bitstream.cc index a6c70a5b..ed63bfe2 100644 --- a/himbaechel/uarch/gatemate/bitstream.cc +++ b/himbaechel/uarch/gatemate/bitstream.cc @@ -219,24 +219,52 @@ struct BitstreamBackend void check_multipliers() { + pool multiplier_nets; + for (auto *mult : uarch->multipliers) { NPNR_ASSERT(mult != nullptr); - auto should_be_inverted = mult->constr_x % 2 == 1; + multiplier_nets.insert(mult->ports.at(id_IN8).net->name); + multiplier_nets.insert(mult->ports.at(id_IN5).net->name); + multiplier_nets.insert(mult->ports.at(id_IN1).net->name); + } - // TODO: these are errors, but downgraded to allow providing *some* output. + for (auto net_name : multiplier_nets) { + auto *net = ctx->nets.at(net_name).get(); - // IN8 - if (need_inversion(mult, id_IN8) != should_be_inverted) - log_warning("%s.IN8 has wrong inversion state\n", mult->name.c_str(ctx)); + bool all_correct = true; + bool all_inverted = true; - // IN5 - if (need_inversion(mult, id_IN5) != should_be_inverted) - log_warning("%s.IN5 has wrong inversion state\n", mult->name.c_str(ctx)); + for (PortRef user : net->users) { + auto should_be_inverted = user.cell->constr_x % 2 == 1; + auto inversion = need_inversion(user.cell, user.port); + all_correct &= (inversion == should_be_inverted); + all_inverted &= (inversion != should_be_inverted); + } - // IN1 - if (need_inversion(mult, id_IN1) != should_be_inverted) - log_warning("%s.IN1 has wrong inversion state\n", mult->name.c_str(ctx)); + NPNR_ASSERT(!(all_correct && all_inverted) && "net doesn't drive any ports?"); + + if (!all_correct && !all_inverted) { + log_warning("multiplier net '%s' has inconsistent inversion\n", net_name.c_str(ctx)); + + log_warning(" these ports are not inverted:\n"); + for (PortRef user : net->users) { + auto should_be_inverted = user.cell->constr_x % 2 == 1; + auto inversion = need_inversion(user.cell, user.port); + if (inversion == should_be_inverted) + log_warning(" %s.%s\n", user.cell->name.c_str(ctx), user.port.c_str(ctx)); + } + + log_warning(" these ports are inverted:\n"); + for (PortRef user : net->users) { + auto should_be_inverted = user.cell->constr_x % 2 == 1; + auto inversion = need_inversion(user.cell, user.port); + if (inversion != should_be_inverted) + log_warning(" %s.%s\n", user.cell->name.c_str(ctx), user.port.c_str(ctx)); + } + } else if (all_inverted) { + log_info("multiplier net '%s' has fixable inversion (but I haven't implemented it yet)\n", net_name.c_str(ctx)); + } } } diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index b77872c2..78f03bf8 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -212,8 +212,11 @@ void GateMateImpl::preRoute() NPNR_ASSERT(from != WireId()); NPNR_ASSERT(to != WireId()); for (auto pip : ctx->getPipsDownhill(from)) { - if (ctx->getPipDstWire(pip) == to) + if (ctx->getPipDstWire(pip) == to) { + log_info(" pip %s\n", ctx->nameOfPip(pip)); + return pip; + } } log_error("Couldn't find pip from %s to %s\n", ctx->nameOfWire(from), ctx->nameOfWire(to)); }; @@ -276,6 +279,9 @@ void GateMateImpl::preRoute() ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_USER); ctx->bindPip(find_downhill_pip(in_mux_p08, cpe_in8_int), upper_out, STRENGTH_USER); } + } else { + log_info(" don't know how to route net '%s'\n", lower_out->name.c_str(ctx)); + log_info(" don't know how to route net '%s'\n", upper_out->name.c_str(ctx)); } } } From 0533a4c12b1a22befff5c966f750534ba047973a Mon Sep 17 00:00:00 2001 From: Lofty Date: Tue, 15 Jul 2025 07:43:04 +0100 Subject: [PATCH 03/34] fixed missing pip --- himbaechel/uarch/gatemate/bitstream.cc | 23 +++++++++-- himbaechel/uarch/gatemate/gatemate.cc | 54 +++++++++++++++++--------- 2 files changed, 54 insertions(+), 23 deletions(-) diff --git a/himbaechel/uarch/gatemate/bitstream.cc b/himbaechel/uarch/gatemate/bitstream.cc index ed63bfe2..50828c26 100644 --- a/himbaechel/uarch/gatemate/bitstream.cc +++ b/himbaechel/uarch/gatemate/bitstream.cc @@ -23,6 +23,8 @@ #include "config.h" #include "gatemate.h" #include "gatemate_util.h" +#include "property.h" +#include "uarch/gatemate/pack.h" #define HIMBAECHEL_CONSTIDS "uarch/gatemate/constids.inc" #include "himbaechel_constids.h" @@ -232,11 +234,15 @@ struct BitstreamBackend for (auto net_name : multiplier_nets) { auto *net = ctx->nets.at(net_name).get(); + int64_t driver_l10 = net->driver.cell->params[id_INIT_L10].as_int64(); + bool driver_is_inverted = driver_l10 == LUT_ONE || driver_l10 == LUT_INV_D0; + bool all_correct = true; bool all_inverted = true; for (PortRef user : net->users) { - auto should_be_inverted = user.cell->constr_x % 2 == 1; + auto column_parity = user.cell->constr_x % 2; + auto should_be_inverted = driver_is_inverted ? column_parity == 0 : column_parity == 1; auto inversion = need_inversion(user.cell, user.port); all_correct &= (inversion == should_be_inverted); all_inverted &= (inversion != should_be_inverted); @@ -249,21 +255,30 @@ struct BitstreamBackend log_warning(" these ports are not inverted:\n"); for (PortRef user : net->users) { + auto loc = ctx->getBelLocation(user.cell->bel); + auto x_fourgroup = (loc.x - 3) % 4; + auto y_fourgroup = (loc.y - 3) % 4; + auto should_be_inverted = user.cell->constr_x % 2 == 1; auto inversion = need_inversion(user.cell, user.port); if (inversion == should_be_inverted) - log_warning(" %s.%s\n", user.cell->name.c_str(ctx), user.port.c_str(ctx)); + log_warning(" %s.%s with four-group (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), x_fourgroup, y_fourgroup); } log_warning(" these ports are inverted:\n"); for (PortRef user : net->users) { + auto loc = ctx->getBelLocation(user.cell->bel); + auto x_fourgroup = (loc.x - 3) % 4; + auto y_fourgroup = (loc.y - 3) % 4; + auto should_be_inverted = user.cell->constr_x % 2 == 1; auto inversion = need_inversion(user.cell, user.port); if (inversion != should_be_inverted) - log_warning(" %s.%s\n", user.cell->name.c_str(ctx), user.port.c_str(ctx)); + log_warning(" %s.%s with four-group (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), x_fourgroup, y_fourgroup); } } else if (all_inverted) { - log_info("multiplier net '%s' has fixable inversion (but I haven't implemented it yet)\n", net_name.c_str(ctx)); + net->driver.cell->params[id_INIT_L10] = Property(~driver_l10 & 0b1111, 4); + log_info("multiplier net '%s': fixed inversion\n", net_name.c_str(ctx)); } } } diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index 78f03bf8..33800fd8 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -20,6 +20,7 @@ #include "gatemate.h" #include "log.h" #include "placer_heap.h" +#include "property.h" #define GEN_INIT_CONSTIDS #define HIMBAECHEL_CONSTIDS "uarch/gatemate/constids.inc" @@ -221,14 +222,17 @@ void GateMateImpl::preRoute() log_error("Couldn't find pip from %s to %s\n", ctx->nameOfWire(from), ctx->nameOfWire(to)); }; - if (x_fourgroup == 0 && y_fourgroup == 0) { + bool is_fourgroup_a = (x_fourgroup == 0 && y_fourgroup == 0) || (x_fourgroup == 2 && y_fourgroup == 2); + bool is_fourgroup_b = (x_fourgroup == 2 && y_fourgroup == 0) || (x_fourgroup == 0 && y_fourgroup == 2); + + if (is_fourgroup_a) { auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); { - log_info(" routing net '%s'\n", lower_out->name.c_str(ctx)); + log_info(" routing net '%s' -> IN5\n", lower_out->name.c_str(ctx)); auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); auto cpe_out1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0"))); @@ -238,13 +242,13 @@ void GateMateImpl::preRoute() ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1), lower_out, STRENGTH_USER); ctx->bindPip(find_downhill_pip(cpe_out1, sb_big), lower_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_big, in_mux), lower_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_big, in_mux), lower_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_USER); // inverting ctx->bindPip(find_downhill_pip(cpe_in5, cpe_in5_int), lower_out, STRENGTH_USER); } { - log_info(" routing net '%s'\n", upper_out->name.c_str(ctx)); + log_info(" routing net '%s' -> IN1\n", upper_out->name.c_str(ctx)); auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0"))); @@ -254,10 +258,12 @@ void GateMateImpl::preRoute() ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_USER); ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_big), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_big, in_mux), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_big, in_mux), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_USER); // inverting ctx->bindPip(find_downhill_pip(cpe_in1, cpe_in1_int), upper_out, STRENGTH_USER); + log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); + auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.Y1_int"))); @@ -265,23 +271,33 @@ void GateMateImpl::preRoute() auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.Y1"))); auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.YDIAG"))); auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); - auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); - auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y + auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); // auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); - ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_USER); // inverting ctx->bindPip(find_downhill_pip(out_mux_y, sb_sml), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_sml, sb_big_d2_1), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_big_d2_1, sb_big_y1), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_big_y1, sb_big_ydiag), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_big_ydiag, in_mux_p12), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(in_mux_p08, cpe_in8_int), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_sml, sb_big_d2_1), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(sb_big_d2_1, sb_big_y1), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(sb_big_y1, sb_big_ydiag), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(sb_big_ydiag, in_mux_p12), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_USER); } + } else if (is_fourgroup_b) { + log_info(" don't know how to route net '%s' (it's four-group B)\n", lower_out->name.c_str(ctx)); + log_info(" don't know how to route net '%s' (it's four-group B)\n", upper_out->name.c_str(ctx)); } else { - log_info(" don't know how to route net '%s'\n", lower_out->name.c_str(ctx)); - log_info(" don't know how to route net '%s'\n", upper_out->name.c_str(ctx)); + auto lower_l10 = lower->params[id_INIT_L10].as_int64(); + lower->params[id_INIT_L10] = Property(~lower_l10 & 0b1111, 4); + auto upper_l10 = upper->params[id_INIT_L10].as_int64(); + upper->params[id_INIT_L10] = Property(~upper_l10 & 0b1111, 4); + + log_info(" don't know how to route net '%s' (it's a light square)\n", lower_out->name.c_str(ctx)); + log_info(" don't know how to route net '%s' (it's a light square)\n", upper_out->name.c_str(ctx)); } } } From 0829b46e9ba9ee5031dc432d6559c0f31f42fcbb Mon Sep 17 00:00:00 2001 From: Lofty Date: Thu, 17 Jul 2025 07:54:22 +0100 Subject: [PATCH 04/34] move multiplier router to its own file --- himbaechel/uarch/gatemate/CMakeLists.txt | 1 + himbaechel/uarch/gatemate/gatemate.cc | 113 +------------------ himbaechel/uarch/gatemate/gatemate.h | 1 + himbaechel/uarch/gatemate/route_mult.cc | 138 +++++++++++++++++++++++ 4 files changed, 141 insertions(+), 112 deletions(-) create mode 100644 himbaechel/uarch/gatemate/route_mult.cc diff --git a/himbaechel/uarch/gatemate/CMakeLists.txt b/himbaechel/uarch/gatemate/CMakeLists.txt index 85f706a1..b5f61388 100644 --- a/himbaechel/uarch/gatemate/CMakeLists.txt +++ b/himbaechel/uarch/gatemate/CMakeLists.txt @@ -20,6 +20,7 @@ set(SOURCES pack.h pll.cc route_clock.cc + route_mult.cc ) set(TEST_SOURCES diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index 33800fd8..eb4b3d7d 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -188,118 +188,7 @@ void GateMateImpl::preRoute() { ctx->assignArchInfo(); route_clock(); - - log_info("Routing multipliers...\n"); - - // I am fully aware the nextpnr API is absolutely not designed around naming specific pips. - // Unfortunately, this is the easiest way to describe the specific routing required. - // Myrtle, please forgive me. - for (auto &a_passthru : this->multiplier_a_passthrus) { - auto *lower = a_passthru.first; - auto *upper = a_passthru.second; - - auto *lower_out = lower->ports.at(id_OUT).net; - auto *upper_out = upper->ports.at(id_OUT).net; - - auto loc = ctx->getBelLocation(lower->bel); - log_info(" A passthrough at (%d, %d) has 4-group (%d, %d)\n", loc.x, loc.y, (loc.x - 3) % 4, (loc.y - 3) % 4); - log_info(" lower.OUT [OUT1] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(lower->bel, id_OUT))); - log_info(" upper.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(upper->bel, id_OUT))); - - auto x_fourgroup = (loc.x - 3) % 4; - auto y_fourgroup = (loc.y - 3) % 4; - - auto find_downhill_pip = [&](WireId from, WireId to) { - NPNR_ASSERT(from != WireId()); - NPNR_ASSERT(to != WireId()); - for (auto pip : ctx->getPipsDownhill(from)) { - if (ctx->getPipDstWire(pip) == to) { - log_info(" pip %s\n", ctx->nameOfPip(pip)); - - return pip; - } - } - log_error("Couldn't find pip from %s to %s\n", ctx->nameOfWire(from), ctx->nameOfWire(to)); - }; - - bool is_fourgroup_a = (x_fourgroup == 0 && y_fourgroup == 0) || (x_fourgroup == 2 && y_fourgroup == 2); - bool is_fourgroup_b = (x_fourgroup == 2 && y_fourgroup == 0) || (x_fourgroup == 0 && y_fourgroup == 2); - - if (is_fourgroup_a) { - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); - auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); - auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); - - { - log_info(" routing net '%s' -> IN5\n", lower_out->name.c_str(ctx)); - auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); - auto cpe_out1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); - auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); - auto cpe_in5 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5"))); - auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); - - ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1), lower_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(cpe_out1, sb_big), lower_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_big, in_mux), lower_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(cpe_in5, cpe_in5_int), lower_out, STRENGTH_USER); - } - - { - log_info(" routing net '%s' -> IN1\n", upper_out->name.c_str(ctx)); - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); - auto cpe_in1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1"))); - auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); - - ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_big), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_big, in_mux), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(cpe_in1, cpe_in1_int), upper_out, STRENGTH_USER); - - log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); - - auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); - auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); - auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.Y1_int"))); - auto sb_big_d2_1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.D2_1"))); - auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.Y1"))); - auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.YDIAG"))); - auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); - auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y - auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y - auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); // - auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); - - ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(out_mux_y, sb_sml), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_sml, sb_big_d2_1), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(sb_big_d2_1, sb_big_y1), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(sb_big_y1, sb_big_ydiag), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(sb_big_ydiag, in_mux_p12), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_USER); - } - } else if (is_fourgroup_b) { - log_info(" don't know how to route net '%s' (it's four-group B)\n", lower_out->name.c_str(ctx)); - log_info(" don't know how to route net '%s' (it's four-group B)\n", upper_out->name.c_str(ctx)); - } else { - auto lower_l10 = lower->params[id_INIT_L10].as_int64(); - lower->params[id_INIT_L10] = Property(~lower_l10 & 0b1111, 4); - auto upper_l10 = upper->params[id_INIT_L10].as_int64(); - upper->params[id_INIT_L10] = Property(~upper_l10 & 0b1111, 4); - - log_info(" don't know how to route net '%s' (it's a light square)\n", lower_out->name.c_str(ctx)); - log_info(" don't know how to route net '%s' (it's a light square)\n", upper_out->name.c_str(ctx)); - } - } + route_mult(); } void GateMateImpl::postRoute() diff --git a/himbaechel/uarch/gatemate/gatemate.h b/himbaechel/uarch/gatemate/gatemate.h index 148dce55..44cca731 100644 --- a/himbaechel/uarch/gatemate/gatemate.h +++ b/himbaechel/uarch/gatemate/gatemate.h @@ -85,6 +85,7 @@ struct GateMateImpl : HimbaechelAPI void assign_cell_info(); void route_clock(); + void route_mult(); void repack(); const GateMateBelExtraDataPOD *bel_extra_data(BelId bel) const; diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc new file mode 100644 index 00000000..90ef0190 --- /dev/null +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -0,0 +1,138 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2024 The Project Peppercorn Authors. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "gatemate.h" +#include "nextpnr_namespaces.h" + +#define HIMBAECHEL_CONSTIDS "uarch/gatemate/constids.inc" +#include "himbaechel_constids.h" + +NEXTPNR_NAMESPACE_BEGIN + +void GateMateImpl::route_mult() { + log_info("Routing multipliers...\n"); + + // I am fully aware the nextpnr API is absolutely not designed around naming specific pips. + // Unfortunately, this is the easiest way to describe the specific routing required. + // Myrtle, please forgive me. + for (auto &a_passthru : this->multiplier_a_passthrus) { + auto *lower = a_passthru.first; + auto *upper = a_passthru.second; + + auto *lower_out = lower->ports.at(id_OUT).net; + auto *upper_out = upper->ports.at(id_OUT).net; + + auto loc = ctx->getBelLocation(lower->bel); + log_info(" A passthrough at (%d, %d) has 4-group (%d, %d)\n", loc.x, loc.y, (loc.x - 3) % 4, (loc.y - 3) % 4); + log_info(" lower.OUT [OUT1] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(lower->bel, id_OUT))); + log_info(" upper.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(upper->bel, id_OUT))); + + auto x_fourgroup = (loc.x - 3) % 4; + auto y_fourgroup = (loc.y - 3) % 4; + bool is_fourgroup_a = (x_fourgroup == 0 && y_fourgroup == 0) || (x_fourgroup == 2 && y_fourgroup == 2); + bool is_fourgroup_b = (x_fourgroup == 2 && y_fourgroup == 0) || (x_fourgroup == 0 && y_fourgroup == 2); + auto x_within_fourgroup = (loc.x - 3) % 2; + auto y_within_fourgroup = (loc.y - 3) % 2; + + auto find_downhill_pip = [&](WireId from, WireId to) { + NPNR_ASSERT(from != WireId()); + NPNR_ASSERT(to != WireId()); + for (auto pip : ctx->getPipsDownhill(from)) { + if (ctx->getPipDstWire(pip) == to) { + log_info(" pip %s\n", ctx->nameOfPip(pip)); + + return pip; + } + } + log_error("Couldn't find pip from %s to %s\n", ctx->nameOfWire(from), ctx->nameOfWire(to)); + }; + + if (is_fourgroup_a) { + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); + auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); + + { + log_info(" routing net '%s' -> IN5\n", lower_out->name.c_str(ctx)); + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); + auto cpe_in5 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5"))); + auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); + + ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1), lower_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(cpe_out1, sb_big), lower_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_big, in_mux), lower_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(cpe_in5, cpe_in5_int), lower_out, STRENGTH_USER); + } + + { + log_info(" routing net '%s' -> IN1\n", upper_out->name.c_str(ctx)); + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); + auto cpe_in1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1"))); + auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); + + ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_big), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_big, in_mux), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(cpe_in1, cpe_in1_int), upper_out, STRENGTH_USER); + + log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); + + auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); + auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); + auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.Y1_int"))); + auto sb_big_d2_1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.D2_1"))); + auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.Y1"))); + auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.YDIAG"))); + auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y + auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); // + auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); + + ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(out_mux_y, sb_sml), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_sml, sb_big_d2_1), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(sb_big_d2_1, sb_big_y1), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(sb_big_y1, sb_big_ydiag), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(sb_big_ydiag, in_mux_p12), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_USER); + } + } else if (is_fourgroup_b) { + log_info(" don't know how to route net '%s' (it's four-group B)\n", lower_out->name.c_str(ctx)); + log_info(" don't know how to route net '%s' (it's four-group B)\n", upper_out->name.c_str(ctx)); + } else { + log_info(" don't know how to route net '%s' (it's a light square)\n", lower_out->name.c_str(ctx)); + log_info(" don't know how to route net '%s' (it's a light square)\n", upper_out->name.c_str(ctx)); + } + } +} + +NEXTPNR_NAMESPACE_END From 530a08606b824dfedd97773b22e0428377bdf06e Mon Sep 17 00:00:00 2001 From: Lofty Date: Sun, 20 Jul 2025 15:07:12 +0100 Subject: [PATCH 05/34] current progress --- himbaechel/uarch/gatemate/route_mult.cc | 155 +++++++++++++----------- 1 file changed, 87 insertions(+), 68 deletions(-) diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index 90ef0190..0acfad8f 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -18,6 +18,8 @@ */ #include "gatemate.h" +#include "log.h" +#include "nextpnr_base_types.h" #include "nextpnr_namespaces.h" #define HIMBAECHEL_CONSTIDS "uarch/gatemate/constids.inc" @@ -39,23 +41,34 @@ void GateMateImpl::route_mult() { auto *upper_out = upper->ports.at(id_OUT).net; auto loc = ctx->getBelLocation(lower->bel); - log_info(" A passthrough at (%d, %d) has 4-group (%d, %d)\n", loc.x, loc.y, (loc.x - 3) % 4, (loc.y - 3) % 4); - log_info(" lower.OUT [OUT1] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(lower->bel, id_OUT))); - log_info(" upper.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(upper->bel, id_OUT))); auto x_fourgroup = (loc.x - 3) % 4; auto y_fourgroup = (loc.y - 3) % 4; - bool is_fourgroup_a = (x_fourgroup == 0 && y_fourgroup == 0) || (x_fourgroup == 2 && y_fourgroup == 2); - bool is_fourgroup_b = (x_fourgroup == 2 && y_fourgroup == 0) || (x_fourgroup == 0 && y_fourgroup == 2); + bool is_fourgroup_a = (x_fourgroup < 2 && y_fourgroup < 2) || (x_fourgroup >= 2 && y_fourgroup >= 2); auto x_within_fourgroup = (loc.x - 3) % 2; auto y_within_fourgroup = (loc.y - 3) % 2; + bool needs_in8_route = false; + + log_info(" A passthrough at (%d, %d) has 4-group %c\n", loc.x, loc.y, is_fourgroup_a ? 'A' : 'B'); + + log_info(" lower.OUT [OUT1] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(lower->bel, id_OUT))); + for (auto sink_port : lower->ports.at(id_OUT).net->users) + log_info(" -> %s.%s\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx)); + + log_info(" upper.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(upper->bel, id_OUT))); + for (auto sink_port : upper->ports.at(id_OUT).net->users) { + if (sink_port.port == id_IN8) + needs_in8_route = true; + log_info(" -> %s.%s\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx)); + } + auto find_downhill_pip = [&](WireId from, WireId to) { NPNR_ASSERT(from != WireId()); NPNR_ASSERT(to != WireId()); for (auto pip : ctx->getPipsDownhill(from)) { if (ctx->getPipDstWire(pip) == to) { - log_info(" pip %s\n", ctx->nameOfPip(pip)); + log_info(" pip %s: %s -> %s\n", ctx->nameOfPip(pip), ctx->nameOfWire(from), ctx->nameOfWire(to)); return pip; } @@ -64,73 +77,79 @@ void GateMateImpl::route_mult() { }; if (is_fourgroup_a) { - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); - auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); - auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); + if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); + auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); - { - log_info(" routing net '%s' -> IN5\n", lower_out->name.c_str(ctx)); - auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); - auto cpe_out1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); - auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); - auto cpe_in5 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5"))); - auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); + { + log_info(" routing net '%s' -> IN5\n", lower_out->name.c_str(ctx)); + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); + auto cpe_in5 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5"))); + auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); - ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1), lower_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(cpe_out1, sb_big), lower_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_big, in_mux), lower_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(cpe_in5, cpe_in5_int), lower_out, STRENGTH_USER); + ctx->bindWire(cpe_combout1, lower_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1), lower_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(cpe_out1, sb_big), lower_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_big, in_mux), lower_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(cpe_in5, cpe_in5_int), lower_out, STRENGTH_USER); + } + + { + log_info(" routing net '%s' -> IN1\n", upper_out->name.c_str(ctx)); + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); + auto cpe_in1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1"))); + auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); + + ctx->bindWire(cpe_combout2, upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_big), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_big, in_mux), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(cpe_in1, cpe_in1_int), upper_out, STRENGTH_USER); + } + + if (needs_in8_route) { + log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); + + auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); + auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); + auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.Y1_int"))); + auto sb_big_d2_1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.D2_1"))); + auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.Y1"))); + auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.YDIAG"))); + auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y + auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); + auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); + + ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(out_mux_y, sb_sml), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(sb_sml, sb_big_d2_1), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(sb_big_d2_1, sb_big_y1), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(sb_big_y1, sb_big_ydiag), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(sb_big_ydiag, in_mux_p12), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_USER); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_USER); + } + } else { + log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", lower_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); + log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", upper_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); } - - { - log_info(" routing net '%s' -> IN1\n", upper_out->name.c_str(ctx)); - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); - auto cpe_in1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1"))); - auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); - - ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_big), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_big, in_mux), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(cpe_in1, cpe_in1_int), upper_out, STRENGTH_USER); - - log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); - - auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); - auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); - auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.Y1_int"))); - auto sb_big_d2_1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.D2_1"))); - auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.Y1"))); - auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.YDIAG"))); - auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); - auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y - auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y - auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); // - auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); - - ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(out_mux_y, sb_sml), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_sml, sb_big_d2_1), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(sb_big_d2_1, sb_big_y1), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(sb_big_y1, sb_big_ydiag), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(sb_big_ydiag, in_mux_p12), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_USER); - } - } else if (is_fourgroup_b) { + } else { log_info(" don't know how to route net '%s' (it's four-group B)\n", lower_out->name.c_str(ctx)); log_info(" don't know how to route net '%s' (it's four-group B)\n", upper_out->name.c_str(ctx)); - } else { - log_info(" don't know how to route net '%s' (it's a light square)\n", lower_out->name.c_str(ctx)); - log_info(" don't know how to route net '%s' (it's a light square)\n", upper_out->name.c_str(ctx)); } } } From 90f5f719f308b4b3e8653763e45e6fec0b2fd16c Mon Sep 17 00:00:00 2001 From: Lofty Date: Mon, 21 Jul 2025 09:20:47 +0100 Subject: [PATCH 06/34] current progress --- himbaechel/uarch/gatemate/route_mult.cc | 204 ++++++++++++++++++++---- 1 file changed, 172 insertions(+), 32 deletions(-) diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index 0acfad8f..096a67e3 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -63,6 +63,11 @@ void GateMateImpl::route_mult() { log_info(" -> %s.%s\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx)); } + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); + auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); + auto find_downhill_pip = [&](WireId from, WireId to) { NPNR_ASSERT(from != WireId()); NPNR_ASSERT(to != WireId()); @@ -78,43 +83,44 @@ void GateMateImpl::route_mult() { if (is_fourgroup_a) { if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); - auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); - auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + + ctx->bindWire(cpe_combout1, lower_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1_int), lower_out, STRENGTH_LOCKED); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + + ctx->bindWire(cpe_combout2, upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_LOCKED); { log_info(" routing net '%s' -> IN5\n", lower_out->name.c_str(ctx)); - auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); - auto cpe_out1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0"))); auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); auto cpe_in5 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5"))); auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); - ctx->bindWire(cpe_combout1, lower_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1), lower_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(cpe_out1, sb_big), lower_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_big, in_mux), lower_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(cpe_in5, cpe_in5_int), lower_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(cpe_out1_int, sb_big), lower_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_big, in_mux), lower_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(cpe_in5, cpe_in5_int), lower_out, STRENGTH_LOCKED); } { log_info(" routing net '%s' -> IN1\n", upper_out->name.c_str(ctx)); - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0"))); auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); auto cpe_in1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1"))); auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); - ctx->bindWire(cpe_combout2, upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_big), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_big, in_mux), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(cpe_in1, cpe_in1_int), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_big), upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_big, in_mux), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(cpe_in1, cpe_in1_int), upper_out, STRENGTH_LOCKED); } if (needs_in8_route) { @@ -132,24 +138,158 @@ void GateMateImpl::route_mult() { auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); - ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(out_mux_y, sb_sml), upper_out, STRENGTH_USER); - ctx->bindPip(find_downhill_pip(sb_sml, sb_big_d2_1), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(sb_big_d2_1, sb_big_y1), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(sb_big_y1, sb_big_ydiag), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(sb_big_ydiag, in_mux_p12), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_USER); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_USER); + ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(out_mux_y, sb_sml), upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml, sb_big_d2_1), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(sb_big_d2_1, sb_big_y1), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(sb_big_y1, sb_big_ydiag), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(sb_big_ydiag, in_mux_p12), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_LOCKED); + } + } else if (x_within_fourgroup == 0 && y_within_fourgroup == 1) { + /* auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + + ctx->bindWire(cpe_combout1, lower_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1_int), lower_out, STRENGTH_LOCKED);*/ + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + + ctx->bindWire(cpe_combout2, upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_LOCKED); + + { + //log_info(" routing net '%s' -> IN5\n", lower_out->name.c_str(ctx)); + + auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P06.D0"))); + // the cologne chip guide for this magically teleports from plane 6 to plane 5. I do not know how. + } + + if (needs_in8_route) { + log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); + + auto out_mux_d1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.D1"))); + auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.Y"))); + auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P10.Y2_int"))); + auto in_mux_p10 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P10.D1"))); + auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D6"))); // aka IM.P10.Y + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y + auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); + auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); + + ctx->bindPip(find_downhill_pip(cpe_out2_int, out_mux_d1), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(out_mux_d1, out_mux_y), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(out_mux_y, sb_sml), upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml, in_mux_p10), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p10, in_mux_p12), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_LOCKED); + } + } else if (x_within_fourgroup == 0 && y_within_fourgroup == 1) { + /* auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + + ctx->bindWire(cpe_combout1, lower_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1_int), lower_out, STRENGTH_LOCKED);*/ + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + + ctx->bindWire(cpe_combout2, upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_LOCKED); + + if (needs_in8_route) { + log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); + + } } else { log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", lower_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", upper_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); } } else { - log_info(" don't know how to route net '%s' (it's four-group B)\n", lower_out->name.c_str(ctx)); - log_info(" don't know how to route net '%s' (it's four-group B)\n", upper_out->name.c_str(ctx)); + if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + + ctx->bindWire(cpe_combout1, lower_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1_int), lower_out, STRENGTH_LOCKED); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + + ctx->bindWire(cpe_combout2, upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_LOCKED); + + { + log_info(" routing net '%s' -> IN5\n", lower_out->name.c_str(ctx)); + + auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.D0"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.Y1_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); + auto cpe_in5 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5"))); + auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); + + ctx->bindPip(find_downhill_pip(cpe_out1_int, sb_sml_d0), lower_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_d0, sb_sml_y1_int), lower_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_y1_int, in_mux), lower_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(cpe_in5, cpe_in5_int), lower_out, STRENGTH_LOCKED); + } + + { + log_info(" routing net '%s' -> IN1\n", upper_out->name.c_str(ctx)); + + auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.D0"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.Y1_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); + auto cpe_in1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1"))); + auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); + + ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_sml_d0), upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_d0, sb_sml_y1_int), upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_y1_int, in_mux), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(cpe_in1, cpe_in1_int), upper_out, STRENGTH_LOCKED); + } + + if (needs_in8_route) { + log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); + + auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); + auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); + auto sb_big = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_BIG.P12.Y1"))); // aka x4y2/SB_SML.P12.D2_1 + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y1_int"))); + auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.YDIAG_int"))); + auto sb_sml_y3_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y3_int"))); + auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y + auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); + auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); + + ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(out_mux_y, sb_big), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(sb_big, sb_sml_y1_int), upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_y1_int, sb_sml_ydiag_int), upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_ydiag_int, sb_sml_y3_int), upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_y3_int, in_mux_p12), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_LOCKED); + } + } else { + log_info(" don't know how to route net '%s' (it's four-group B, (%d, %d))\n", lower_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); + log_info(" don't know how to route net '%s' (it's four-group B, (%d, %d))\n", upper_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); + } } } } From 56e1452d3107e812d13ffb4f072a64e228e0e1f3 Mon Sep 17 00:00:00 2001 From: Lofty Date: Mon, 21 Jul 2025 09:38:27 +0100 Subject: [PATCH 07/34] refactor common routes --- himbaechel/uarch/gatemate/route_mult.cc | 196 ++++++++++-------------- 1 file changed, 81 insertions(+), 115 deletions(-) diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index 096a67e3..4eb045a5 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -81,75 +81,114 @@ void GateMateImpl::route_mult() { log_error("Couldn't find pip from %s to %s\n", ctx->nameOfWire(from), ctx->nameOfWire(to)); }; - if (is_fourgroup_a) { - if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { - auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); - auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); - ctx->bindWire(cpe_combout1, lower_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1_int), lower_out, STRENGTH_LOCKED); + if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + ctx->bindWire(cpe_combout1, lower_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1_int), lower_out, STRENGTH_LOCKED); - ctx->bindWire(cpe_combout2, upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_LOCKED); + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - { - log_info(" routing net '%s' -> IN5\n", lower_out->name.c_str(ctx)); + ctx->bindWire(cpe_combout2, upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_LOCKED); + { + log_info(" routing net '%s' -> IN5\n", lower_out->name.c_str(ctx)); + + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); + auto cpe_in5 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5"))); + auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); + + if (is_fourgroup_a) { auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); - auto cpe_in5 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5"))); - auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); ctx->bindPip(find_downhill_pip(cpe_out1_int, sb_big), lower_out, STRENGTH_LOCKED); ctx->bindPip(find_downhill_pip(sb_big, in_mux), lower_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(cpe_in5, cpe_in5_int), lower_out, STRENGTH_LOCKED); + } else { + auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.D0"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.Y1_int"))); + + ctx->bindPip(find_downhill_pip(cpe_out1_int, sb_sml_d0), lower_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_d0, sb_sml_y1_int), lower_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_y1_int, in_mux), lower_out, STRENGTH_LOCKED); // inverting } - { - log_info(" routing net '%s' -> IN1\n", upper_out->name.c_str(ctx)); + ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(cpe_in5, cpe_in5_int), lower_out, STRENGTH_LOCKED); + } + { + log_info(" routing net '%s' -> IN1\n", upper_out->name.c_str(ctx)); + + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); + auto cpe_in1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1"))); + auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); + + if (is_fourgroup_a) { auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); - auto cpe_in1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1"))); - auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_big), upper_out, STRENGTH_LOCKED); ctx->bindPip(find_downhill_pip(sb_big, in_mux), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(cpe_in1, cpe_in1_int), upper_out, STRENGTH_LOCKED); + } else { + auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.D0"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.Y1_int"))); + + ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_sml_d0), upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_d0, sb_sml_y1_int), upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_y1_int, in_mux), upper_out, STRENGTH_LOCKED); // inverting } - if (needs_in8_route) { - log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); + ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(cpe_in1, cpe_in1_int), upper_out, STRENGTH_LOCKED); + } - auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); - auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); + if (needs_in8_route) { + log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); + + auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); + auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); + auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y + auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); + auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); + + ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_LOCKED); // inverting + + if (is_fourgroup_a) { auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.Y1_int"))); auto sb_big_d2_1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.D2_1"))); auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.Y1"))); auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.YDIAG"))); - auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); - auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y - auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y - auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); - auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); - ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_LOCKED); // inverting ctx->bindPip(find_downhill_pip(out_mux_y, sb_sml), upper_out, STRENGTH_LOCKED); ctx->bindPip(find_downhill_pip(sb_sml, sb_big_d2_1), upper_out, STRENGTH_LOCKED); // inverting ctx->bindPip(find_downhill_pip(sb_big_d2_1, sb_big_y1), upper_out, STRENGTH_LOCKED); // inverting ctx->bindPip(find_downhill_pip(sb_big_y1, sb_big_ydiag), upper_out, STRENGTH_LOCKED); // inverting ctx->bindPip(find_downhill_pip(sb_big_ydiag, in_mux_p12), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_LOCKED); + } else { + auto sb_big = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_BIG.P12.Y1"))); // aka x4y2/SB_SML.P12.D2_1 + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y1_int"))); + auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.YDIAG_int"))); + auto sb_sml_y3_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y3_int"))); + + ctx->bindPip(find_downhill_pip(out_mux_y, sb_big), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(sb_big, sb_sml_y1_int), upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_y1_int, sb_sml_ydiag_int), upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_ydiag_int, sb_sml_y3_int), upper_out, STRENGTH_LOCKED); + ctx->bindPip(find_downhill_pip(sb_sml_y3_int, in_mux_p12), upper_out, STRENGTH_LOCKED); // inverting } - } else if (x_within_fourgroup == 0 && y_within_fourgroup == 1) { + + ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_LOCKED); // inverting + ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_LOCKED); + } + } else if (is_fourgroup_a) { + if (x_within_fourgroup == 0 && y_within_fourgroup == 1) { /* auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); @@ -192,7 +231,7 @@ void GateMateImpl::route_mult() { ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_LOCKED); // inverting ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_LOCKED); } - } else if (x_within_fourgroup == 0 && y_within_fourgroup == 1) { + } else if (false && x_within_fourgroup == 0 && y_within_fourgroup == 1) { /* auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); @@ -215,81 +254,8 @@ void GateMateImpl::route_mult() { log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", upper_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); } } else { - if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { - auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); - auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); - - ctx->bindWire(cpe_combout1, lower_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1_int), lower_out, STRENGTH_LOCKED); - - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - - ctx->bindWire(cpe_combout2, upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_LOCKED); - - { - log_info(" routing net '%s' -> IN5\n", lower_out->name.c_str(ctx)); - - auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.D0"))); - auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.Y1_int"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); - auto cpe_in5 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5"))); - auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); - - ctx->bindPip(find_downhill_pip(cpe_out1_int, sb_sml_d0), lower_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_d0, sb_sml_y1_int), lower_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_y1_int, in_mux), lower_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(cpe_in5, cpe_in5_int), lower_out, STRENGTH_LOCKED); - } - - { - log_info(" routing net '%s' -> IN1\n", upper_out->name.c_str(ctx)); - - auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.D0"))); - auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.Y1_int"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); - auto cpe_in1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1"))); - auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); - - ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_sml_d0), upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_d0, sb_sml_y1_int), upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_y1_int, in_mux), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(cpe_in1, cpe_in1_int), upper_out, STRENGTH_LOCKED); - } - - if (needs_in8_route) { - log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); - - auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); - auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); - auto sb_big = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_BIG.P12.Y1"))); // aka x4y2/SB_SML.P12.D2_1 - auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y1_int"))); - auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.YDIAG_int"))); - auto sb_sml_y3_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y3_int"))); - auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); - auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y - auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y - auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); - auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); - - ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(out_mux_y, sb_big), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(sb_big, sb_sml_y1_int), upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_y1_int, sb_sml_ydiag_int), upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_ydiag_int, sb_sml_y3_int), upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_y3_int, in_mux_p12), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_LOCKED); - } - } else { - log_info(" don't know how to route net '%s' (it's four-group B, (%d, %d))\n", lower_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); - log_info(" don't know how to route net '%s' (it's four-group B, (%d, %d))\n", upper_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); - } + log_info(" don't know how to route net '%s' (it's four-group B, (%d, %d))\n", lower_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); + log_info(" don't know how to route net '%s' (it's four-group B, (%d, %d))\n", upper_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); } } } From 8637e3bc182bfe2f63e1904cb8ecbaf36b6bc733 Mon Sep 17 00:00:00 2001 From: Lofty Date: Mon, 21 Jul 2025 11:52:02 +0100 Subject: [PATCH 08/34] heavy refactoring --- himbaechel/uarch/gatemate/route_mult.cc | 399 +++++++++++++----------- 1 file changed, 211 insertions(+), 188 deletions(-) diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index 4eb045a5..fc978eb6 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -19,12 +19,212 @@ #include "gatemate.h" #include "log.h" +#include "nextpnr_assertions.h" #include "nextpnr_base_types.h" #include "nextpnr_namespaces.h" #define HIMBAECHEL_CONSTIDS "uarch/gatemate/constids.inc" #include "himbaechel_constids.h" +namespace { + USING_NEXTPNR_NAMESPACE; + + void find_and_bind_downhill_pip(Context *ctx, WireId from, WireId to, NetInfo *net) { + NPNR_ASSERT(from != WireId()); + NPNR_ASSERT(to != WireId()); + for (auto pip : ctx->getPipsDownhill(from)) { + if (ctx->getPipDstWire(pip) == to) { + log_info(" pip %s: %s -> %s\n", ctx->nameOfPip(pip), ctx->nameOfWire(from), ctx->nameOfWire(to)); + + ctx->bindPip(pip, net, STRENGTH_LOCKED); + return; + } + } + log_error("Couldn't find pip from %s to %s\n", ctx->nameOfWire(from), ctx->nameOfWire(to)); + } + + void route_mult_x1y1_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { + log_info(" routing net '%s' -> IN5\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); + + ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); + + if (is_fourgroup_a) { + auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0"))); + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big, net); + find_and_bind_downhill_pip(ctx, sb_big, in_mux, net); // inverting + } else { + auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.D0"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.Y1_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_d0, sb_sml_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1_int, in_mux, net); // inverting + } + + auto cpe_in5 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5"))); + auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); + + find_and_bind_downhill_pip(ctx, in_mux, cpe_in5, net); // inverting + find_and_bind_downhill_pip(ctx, cpe_in5, cpe_in5_int, net); + } + + void route_mult_x1y1_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { + log_info(" routing net '%s' -> IN1\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); + + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + + if (is_fourgroup_a) { + auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0"))); + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big, net); + find_and_bind_downhill_pip(ctx, sb_big, in_mux, net); // inverting + } else { + auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.D0"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.Y1_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_d0, sb_sml_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1_int, in_mux, net); // inverting + } + + auto cpe_in1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1"))); + auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); + + find_and_bind_downhill_pip(ctx, in_mux, cpe_in1, net); // inverting + find_and_bind_downhill_pip(ctx, cpe_in1, cpe_in1_int, net); + } + + void route_mult_x1y1_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { + log_info(" routing net '%s' -> IN8\n", net->name.c_str(ctx)); + + auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); + auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); + + auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); + auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); + auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); + + find_and_bind_downhill_pip(ctx, out_mux_d0, out_mux_y, net); // inverting + + if (is_fourgroup_a) { + auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.Y1_int"))); + auto sb_big_d2_1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.D2_1"))); + auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.Y1"))); + auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.YDIAG"))); + + find_and_bind_downhill_pip(ctx, out_mux_y, sb_sml, net); + find_and_bind_downhill_pip(ctx, sb_sml, sb_big_d2_1, net); // inverting + find_and_bind_downhill_pip(ctx, sb_big_d2_1, sb_big_y1, net); // inverting + find_and_bind_downhill_pip(ctx, sb_big_y1, sb_big_ydiag, net); // inverting + find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux_p12, net); // inverting + } else { + auto sb_big = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_BIG.P12.Y1"))); // aka x4y2/SB_SML.P12.D2_1 + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y1_int"))); + auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.YDIAG_int"))); + auto sb_sml_y3_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y3_int"))); + + find_and_bind_downhill_pip(ctx, out_mux_y, sb_big, net); // inverting + find_and_bind_downhill_pip(ctx, sb_big, sb_sml_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_ydiag_int, sb_sml_y3_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y3_int, in_mux_p12, net); // inverting + } + + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y + auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); + auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); + + find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p08, in_mux_p08_y, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p08_y, cpe_in8_int, net); + } + + void route_mult_x1y2_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { + log_info(" routing net '%s' -> IN5\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + + //ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); + //find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); + } + + void route_mult_x1y2_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { + log_info(" routing net '%s' -> IN1\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + + auto out_mux_d1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.D1"))); + + find_and_bind_downhill_pip(ctx, cpe_out2_int, out_mux_d1, net); // inverting + } + + void route_mult_x1y2_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { + log_info(" routing net '%s' -> IN8\n", net->name.c_str(ctx)); + + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); + + auto out_mux_d1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.D1"))); + auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.Y"))); + auto in_mux_p10 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P10.D1"))); + + find_and_bind_downhill_pip(ctx, out_mux_d1, out_mux_y, net); // inverting + + if (is_fourgroup_a) { + auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P10.Y2_int"))); + + find_and_bind_downhill_pip(ctx, out_mux_y, sb_sml, net); + find_and_bind_downhill_pip(ctx, sb_sml, in_mux_p10, net); // inverting + } else { + // x2y1/OM.P10.Y is x2y1/SB_BIG.P10.D0 + // x2y2/IM.P10.D1 is x2y1/SB_BIG.P10.Y2 + + find_and_bind_downhill_pip(ctx, out_mux_y, in_mux_p10, net); // inverting + } + + auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D6"))); // aka IM.P10.Y + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y + auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); + auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); + + find_and_bind_downhill_pip(ctx, in_mux_p10, in_mux_p12, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p08, in_mux_p08_y, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p08_y, cpe_in8_int, net); + } +} + NEXTPNR_NAMESPACE_BEGIN void GateMateImpl::route_mult() { @@ -63,196 +263,19 @@ void GateMateImpl::route_mult() { log_info(" -> %s.%s\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx)); } - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); - auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); - auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); - - auto find_downhill_pip = [&](WireId from, WireId to) { - NPNR_ASSERT(from != WireId()); - NPNR_ASSERT(to != WireId()); - for (auto pip : ctx->getPipsDownhill(from)) { - if (ctx->getPipDstWire(pip) == to) { - log_info(" pip %s: %s -> %s\n", ctx->nameOfPip(pip), ctx->nameOfWire(from), ctx->nameOfWire(to)); - - return pip; - } - } - log_error("Couldn't find pip from %s to %s\n", ctx->nameOfWire(from), ctx->nameOfWire(to)); - }; - - if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { - auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); - auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); - - ctx->bindWire(cpe_combout1, lower_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1_int), lower_out, STRENGTH_LOCKED); - - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - - ctx->bindWire(cpe_combout2, upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_LOCKED); - - { - log_info(" routing net '%s' -> IN5\n", lower_out->name.c_str(ctx)); - - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); - auto cpe_in5 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5"))); - auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); - - if (is_fourgroup_a) { - auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0"))); - - ctx->bindPip(find_downhill_pip(cpe_out1_int, sb_big), lower_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_big, in_mux), lower_out, STRENGTH_LOCKED); // inverting - } else { - auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.D0"))); - auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.Y1_int"))); - - ctx->bindPip(find_downhill_pip(cpe_out1_int, sb_sml_d0), lower_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_d0, sb_sml_y1_int), lower_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_y1_int, in_mux), lower_out, STRENGTH_LOCKED); // inverting - } - - ctx->bindPip(find_downhill_pip(in_mux, cpe_in5), lower_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(cpe_in5, cpe_in5_int), lower_out, STRENGTH_LOCKED); - } - - { - log_info(" routing net '%s' -> IN1\n", upper_out->name.c_str(ctx)); - - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); - auto cpe_in1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1"))); - auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); - - if (is_fourgroup_a) { - auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0"))); - - ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_big), upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_big, in_mux), upper_out, STRENGTH_LOCKED); // inverting - } else { - auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.D0"))); - auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.Y1_int"))); - - ctx->bindPip(find_downhill_pip(cpe_out2_int, sb_sml_d0), upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_d0, sb_sml_y1_int), upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_y1_int, in_mux), upper_out, STRENGTH_LOCKED); // inverting - } - - ctx->bindPip(find_downhill_pip(in_mux, cpe_in1), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(cpe_in1, cpe_in1_int), upper_out, STRENGTH_LOCKED); - } - - if (needs_in8_route) { - log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); - - auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); - auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); - auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); - auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y - auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y - auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); - auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); - - ctx->bindPip(find_downhill_pip(out_mux_d0, out_mux_y), upper_out, STRENGTH_LOCKED); // inverting - - if (is_fourgroup_a) { - auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.Y1_int"))); - auto sb_big_d2_1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.D2_1"))); - auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.Y1"))); - auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.YDIAG"))); - - ctx->bindPip(find_downhill_pip(out_mux_y, sb_sml), upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml, sb_big_d2_1), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(sb_big_d2_1, sb_big_y1), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(sb_big_y1, sb_big_ydiag), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(sb_big_ydiag, in_mux_p12), upper_out, STRENGTH_LOCKED); // inverting - } else { - auto sb_big = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_BIG.P12.Y1"))); // aka x4y2/SB_SML.P12.D2_1 - auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y1_int"))); - auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.YDIAG_int"))); - auto sb_sml_y3_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y3_int"))); - - ctx->bindPip(find_downhill_pip(out_mux_y, sb_big), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(sb_big, sb_sml_y1_int), upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_y1_int, sb_sml_ydiag_int), upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_ydiag_int, sb_sml_y3_int), upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml_y3_int, in_mux_p12), upper_out, STRENGTH_LOCKED); // inverting - } - - ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_LOCKED); - } + route_mult_x1y1_lower(ctx, lower_out, lower, loc, is_fourgroup_a); + route_mult_x1y1_upper_in1(ctx, upper_out, upper, loc, is_fourgroup_a); + if (needs_in8_route) + route_mult_x1y1_upper_in8(ctx, upper_out, upper, loc, is_fourgroup_a); + } else if (x_within_fourgroup == 0 && y_within_fourgroup == 1) { + route_mult_x1y2_lower(ctx, lower_out, lower, loc, is_fourgroup_a); + route_mult_x1y2_upper_in1(ctx, upper_out, upper, loc, is_fourgroup_a); + if (needs_in8_route) + route_mult_x1y2_upper_in8(ctx, upper_out, upper, loc, is_fourgroup_a); } else if (is_fourgroup_a) { - if (x_within_fourgroup == 0 && y_within_fourgroup == 1) { - /* auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); - auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); - - ctx->bindWire(cpe_combout1, lower_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1_int), lower_out, STRENGTH_LOCKED);*/ - - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - - ctx->bindWire(cpe_combout2, upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_LOCKED); - - { - //log_info(" routing net '%s' -> IN5\n", lower_out->name.c_str(ctx)); - - auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P06.D0"))); - // the cologne chip guide for this magically teleports from plane 6 to plane 5. I do not know how. - } - - if (needs_in8_route) { - log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); - - auto out_mux_d1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.D1"))); - auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.Y"))); - auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P10.Y2_int"))); - auto in_mux_p10 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P10.D1"))); - auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D6"))); // aka IM.P10.Y - auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y - auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y - auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); - auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); - - ctx->bindPip(find_downhill_pip(cpe_out2_int, out_mux_d1), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(out_mux_d1, out_mux_y), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(out_mux_y, sb_sml), upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(sb_sml, in_mux_p10), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p10, in_mux_p12), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p12, in_mux_p04), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p04, in_mux_p08), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08, in_mux_p08_y), upper_out, STRENGTH_LOCKED); // inverting - ctx->bindPip(find_downhill_pip(in_mux_p08_y, cpe_in8_int), upper_out, STRENGTH_LOCKED); - } - } else if (false && x_within_fourgroup == 0 && y_within_fourgroup == 1) { - /* auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); - auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); - - ctx->bindWire(cpe_combout1, lower_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(cpe_combout1, cpe_out1_int), lower_out, STRENGTH_LOCKED);*/ - - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - - ctx->bindWire(cpe_combout2, upper_out, STRENGTH_LOCKED); - ctx->bindPip(find_downhill_pip(cpe_combout2, cpe_out2_int), upper_out, STRENGTH_LOCKED); - - if (needs_in8_route) { - log_info(" routing net '%s' -> IN8\n", upper_out->name.c_str(ctx)); - - - } - } else { - log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", lower_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); - log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", upper_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); - } + log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", lower_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); + log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", upper_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); } else { log_info(" don't know how to route net '%s' (it's four-group B, (%d, %d))\n", lower_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); log_info(" don't know how to route net '%s' (it's four-group B, (%d, %d))\n", upper_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); From 4cf33090a94121f1013c06ef4d8e9e51ca1ff2ac Mon Sep 17 00:00:00 2001 From: Lofty Date: Mon, 21 Jul 2025 13:14:49 +0100 Subject: [PATCH 09/34] current progress --- himbaechel/uarch/gatemate/route_mult.cc | 64 +++++++++++++++++++++---- 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index fc978eb6..755ddeac 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -44,7 +44,7 @@ namespace { } void route_mult_x1y1_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN5\n", net->name.c_str(ctx)); + log_info(" routing net '%s' -> IN5 using x1y1\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); @@ -78,7 +78,7 @@ namespace { } void route_mult_x1y1_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN1\n", net->name.c_str(ctx)); + log_info(" routing net '%s' -> IN1 using x1y1\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); @@ -112,7 +112,7 @@ namespace { } void route_mult_x1y1_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN8\n", net->name.c_str(ctx)); + log_info(" routing net '%s' -> IN8 using x1y1\n", net->name.c_str(ctx)); auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); @@ -159,7 +159,7 @@ namespace { } void route_mult_x1y2_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN5\n", net->name.c_str(ctx)); + log_info(" routing net '%s' -> IN5 using x1y2\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); @@ -171,10 +171,11 @@ namespace { } void route_mult_x1y2_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN1\n", net->name.c_str(ctx)); + log_info(" routing net '%s' -> IN1 using x1y2\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + auto x4y1 = ctx->idf("X%dY%d", loc.x + 3, loc.y); auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); @@ -182,13 +183,60 @@ namespace { ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); - auto out_mux_d1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.D1"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D2"))); - find_and_bind_downhill_pip(ctx, cpe_out2_int, out_mux_d1, net); // inverting + if (is_fourgroup_a) { + auto sb_sml_p02_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P02.D0"))); + auto sb_sml_p02_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P02.Y1_int"))); + auto sb_sml_p02_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P02.YDIAG_int"))); + auto sb_sml_p02_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P02.YDIAG"))); // AKA SB_SML.P01.X23 + auto sb_sml_p01_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P01.YDIAG_int"))); + auto sb_sml_p01_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P01.Y1_int"))); + auto sb_big_d2_1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P01.D2_1"))); + auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P01.Y1"))); + auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P01.YDIAG"))); + // x2y1/IM.P01.D2 is x4y1/SB_BIG.P01.Y3 + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_p02_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_d0, sb_sml_p02_y1, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_y1, sb_sml_p02_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag_int, sb_sml_p02_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag, sb_sml_p01_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p01_ydiag, sb_sml_p01_y1, net); + find_and_bind_downhill_pip(ctx, sb_sml_p01_y1, sb_big_d2_1, net); + find_and_bind_downhill_pip(ctx, sb_big_d2_1, sb_big_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_y1, sb_big_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux, net); + } else { + auto sb_big_p02_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P02.D0"))); + auto sb_big_p02_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P02.Y1"))); + auto sb_big_p02_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P02.YDIAG"))); // AKA SB_BIG.P01.X23 + auto sb_big_p01_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P01.YDIAG"))); + auto sb_big_p01_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P01.Y1"))); + auto sb_sml_y1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P01.Y1_int"))); + auto sb_sml_ydiag = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P01.YDIAG_int"))); + auto sb_sml_y3 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P01.Y3_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_p02_d0, net); + find_and_bind_downhill_pip(ctx, sb_big_p02_d0, sb_big_p02_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p02_y1, sb_big_p02_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p02_ydiag, sb_big_p01_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p01_ydiag, sb_big_p01_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p01_y1, sb_sml_y1, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1, sb_sml_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_ydiag, sb_sml_y3, net); + find_and_bind_downhill_pip(ctx, sb_sml_y3, in_mux, net); + } + + auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.Y"))); + auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); + + find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); + find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in1_int, net); } void route_mult_x1y2_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN8\n", net->name.c_str(ctx)); + log_info(" routing net '%s' -> IN8 using x1y2\n", net->name.c_str(ctx)); auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); From d1f80ca5bbaec405aa3205557be73aed65bae91a Mon Sep 17 00:00:00 2001 From: Lofty Date: Mon, 21 Jul 2025 21:28:30 +0100 Subject: [PATCH 10/34] current progress --- himbaechel/uarch/gatemate/route_mult.cc | 56 ++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index 755ddeac..aacaf7d8 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -162,12 +162,64 @@ namespace { log_info(" routing net '%s' -> IN5 using x1y2\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + auto x4y1 = ctx->idf("X%dY%d", loc.x + 3, loc.y); auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D2"))); - //ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); - //find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); + ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); + + if (is_fourgroup_a) { + auto sb_sml_p06_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P06.D0"))); + auto sb_sml_p06_y1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P06.Y1_int"))); + auto sb_sml_p06_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P06.YDIAG_int"))); + auto sb_sml_p06_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P06.YDIAG"))); // AKA SB_SML.P05.X23 + auto sb_sml_p05_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P05.YDIAG_int"))); + auto sb_sml_p05_y1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P05.Y1_int"))); + auto sb_sml_p05_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P05.Y1"))); + auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P05.Y1"))); + auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P05.YDIAG"))); + // x2y1/IM.P05.D2 is x4y1/SB_BIG.P05.Y3 + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_p06_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_d0, sb_sml_p06_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_y1_int, sb_sml_p06_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag_int, sb_sml_p06_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag, sb_sml_p05_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_ydiag_int, sb_sml_p05_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, sb_sml_p05_y1, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_y1,sb_big_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_y1, sb_big_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux, net); + } else { + auto sb_big_p06_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P06.D0"))); + auto sb_big_p06_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P06.Y1"))); + auto sb_big_p06_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P06.YDIAG"))); // AKA SB_BIG.P05.X23 + auto sb_big_p05_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P05.YDIAG"))); + auto sb_big_p05_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P05.Y1"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P05.Y1_int"))); + auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P05.YDIAG_int"))); + auto sb_sml_y3_int = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P05.Y3_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big_p06_d0, net); + find_and_bind_downhill_pip(ctx, sb_big_p06_d0, sb_big_p06_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p06_y1, sb_big_p06_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p06_ydiag, sb_big_p05_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p05_ydiag, sb_big_p05_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p05_y1, sb_sml_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1_int,sb_sml_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_ydiag_int, sb_sml_y3_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y3_int, in_mux, net); + } + + auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.Y"))); + auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); + + find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); + find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in5_int, net); } void route_mult_x1y2_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { From 15767039377ac3d82c2b9d7452fa9dba62d0adc0 Mon Sep 17 00:00:00 2001 From: Lofty Date: Tue, 22 Jul 2025 13:21:54 +0100 Subject: [PATCH 11/34] current progress (route zero driver too) --- himbaechel/uarch/gatemate/bitstream.cc | 21 +++++++++++ himbaechel/uarch/gatemate/gatemate.h | 1 + himbaechel/uarch/gatemate/pack_mult.cc | 3 ++ himbaechel/uarch/gatemate/route_mult.cc | 50 ++++++++++++++++++++++++- 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/himbaechel/uarch/gatemate/bitstream.cc b/himbaechel/uarch/gatemate/bitstream.cc index 50828c26..1360de08 100644 --- a/himbaechel/uarch/gatemate/bitstream.cc +++ b/himbaechel/uarch/gatemate/bitstream.cc @@ -221,6 +221,27 @@ struct BitstreamBackend void check_multipliers() { + for (auto *mult : uarch->multipliers) { + NPNR_ASSERT(mult != nullptr); + + auto should_be_inverted = mult->constr_x % 2 == 1; + + // TODO: these are errors, but downgraded to allow providing *some* output. + + // IN8 + if (need_inversion(mult, id_IN8) != should_be_inverted) + log_warning("%s.IN8 has wrong inversion state\n", mult->name.c_str(ctx)); + + // IN5 + if (need_inversion(mult, id_IN5) != should_be_inverted) + log_warning("%s.IN5 has wrong inversion state\n", mult->name.c_str(ctx)); + + // IN1 + if (need_inversion(mult, id_IN1) != should_be_inverted) + log_warning("%s.IN1 has wrong inversion state\n", mult->name.c_str(ctx)); + } + log_info("===\n"); + pool multiplier_nets; for (auto *mult : uarch->multipliers) { diff --git a/himbaechel/uarch/gatemate/gatemate.h b/himbaechel/uarch/gatemate/gatemate.h index 44cca731..a303e6dc 100644 --- a/himbaechel/uarch/gatemate/gatemate.h +++ b/himbaechel/uarch/gatemate/gatemate.h @@ -74,6 +74,7 @@ struct GateMateImpl : HimbaechelAPI int preferred_die; std::vector multipliers; std::vector> multiplier_a_passthrus; + std::vector multiplier_zero_drivers; private: bool getChildPlacement(const BaseClusterInfo *cluster, Loc root_loc, diff --git a/himbaechel/uarch/gatemate/pack_mult.cc b/himbaechel/uarch/gatemate/pack_mult.cc index 06226fa9..8a5e69d2 100644 --- a/himbaechel/uarch/gatemate/pack_mult.cc +++ b/himbaechel/uarch/gatemate/pack_mult.cc @@ -399,6 +399,9 @@ void GateMatePacker::pack_mult() auto create_zero_driver = [&](IdString name) { auto *zero_lower = create_cell_ptr(id_CPE_DUMMY, ctx->idf("%s$zero_lower", name.c_str(ctx))); auto *zero_upper = create_cell_ptr(id_CPE_L2T4, ctx->idf("%s$zero", name.c_str(ctx))); + + uarch->multiplier_zero_drivers.push_back(zero_upper); + return ZeroDriver{zero_lower, zero_upper, name}; }; diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index aacaf7d8..e6235950 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -111,16 +111,25 @@ namespace { find_and_bind_downhill_pip(ctx, cpe_in1, cpe_in1_int, net); } - void route_mult_x1y1_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { + void route_mult_x1y1_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { log_info(" routing net '%s' -> IN8 using x1y1\n", net->name.c_str(ctx)); + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); + if (bind_route_start) { + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + find_and_bind_downhill_pip(ctx, cpe_out2_int, out_mux_d0, net); + } + find_and_bind_downhill_pip(ctx, out_mux_d0, out_mux_y, net); // inverting if (is_fourgroup_a) { @@ -287,16 +296,25 @@ namespace { find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in1_int, net); } - void route_mult_x1y2_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { + void route_mult_x1y2_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { log_info(" routing net '%s' -> IN8 using x1y2\n", net->name.c_str(ctx)); + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); auto out_mux_d1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.D1"))); auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.Y"))); auto in_mux_p10 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P10.D1"))); + if (bind_route_start) { + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + find_and_bind_downhill_pip(ctx, cpe_out2_int, out_mux_d1, net); + } + find_and_bind_downhill_pip(ctx, out_mux_d1, out_mux_y, net); // inverting if (is_fourgroup_a) { @@ -381,6 +399,34 @@ void GateMateImpl::route_mult() { log_info(" don't know how to route net '%s' (it's four-group B, (%d, %d))\n", upper_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); } } + + for (auto &zero_driver : this->multiplier_zero_drivers) { + auto *out = zero_driver->ports.at(id_OUT).net; + + auto loc = ctx->getBelLocation(zero_driver->bel); + + auto x_fourgroup = (loc.x - 3) % 4; + auto y_fourgroup = (loc.y - 3) % 4; + bool is_fourgroup_a = (x_fourgroup < 2 && y_fourgroup < 2) || (x_fourgroup >= 2 && y_fourgroup >= 2); + auto x_within_fourgroup = (loc.x - 3) % 2; + auto y_within_fourgroup = (loc.y - 3) % 2; + + log_info(" Zero driver at (%d, %d) has 4-group %c\n", loc.x, loc.y, is_fourgroup_a ? 'A' : 'B'); + + log_info(" zero_driver.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(zero_driver->bel, id_OUT))); + for (auto sink_port : zero_driver->ports.at(id_OUT).net->users) + log_info(" -> %s.%s\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx)); + + if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { + route_mult_x1y1_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /* bind_route_start=*/true); + } else if (x_within_fourgroup == 0 && y_within_fourgroup == 1) { + route_mult_x1y2_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /* bind_route_start=*/true); + } else if (is_fourgroup_a) { + log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); + } else { + log_info(" don't know how to route net '%s' (it's four-group B, (%d, %d))\n", out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); + } + } } NEXTPNR_NAMESPACE_END From 78b614ed31a4157bc12c4872f5a8970ee636b414 Mon Sep 17 00:00:00 2001 From: Lofty Date: Thu, 24 Jul 2025 09:41:28 +0100 Subject: [PATCH 12/34] current progress --- himbaechel/uarch/gatemate/route_mult.cc | 143 ++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index e6235950..92c5b36e 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -341,6 +341,142 @@ namespace { find_and_bind_downhill_pip(ctx, in_mux_p08, in_mux_p08_y, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p08_y, cpe_in8_int, net); } + + void route_mult_x2y1_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { + log_info(" routing net '%s' -> IN5 using x2y1\n", net->name.c_str(ctx)); + + auto x0y1 = ctx->idf("X%dY%d", loc.x - 1, loc.y); + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); + + ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); + + if (is_fourgroup_a) { + NPNR_ASSERT_FALSE("route_mult_x2y1_lower: not yet implemented for four-group A"); + } else { + auto sb_sml_p07_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.D0"))); + auto sb_sml_p07_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.Y1_int"))); + auto sb_sml_p07_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.YDIAG_int"))); + auto sb_sml_p07_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.YDIAG"))); // AKA SB_SML.P06.X23 + auto sb_sml_p06_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P06.YDIAG_int"))); + auto sb_sml_p06_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P06.YDIAG"))); // AKA SB_SML.P05.X23 + auto sb_sml_p05_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P05.YDIAG_int"))); + auto sb_sml_p05_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P05.Y1_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_p07_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_p07_d0, sb_sml_p07_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p07_y1_int, sb_sml_p07_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag_int, sb_sml_p07_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag, sb_sml_p06_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag_int, sb_sml_p06_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag, sb_sml_p05_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_ydiag_int, sb_sml_p05_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, in_mux, net); + } + + auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.Y"))); + auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); + + find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); + find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in5_int, net); + } + + void route_mult_x2y1_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { + log_info(" routing net '%s' -> IN1 using x2y1\n", net->name.c_str(ctx)); + + auto x0y1 = ctx->idf("X%dY%d", loc.x - 1, loc.y); + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); + + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + + if (is_fourgroup_a) { + NPNR_ASSERT_FALSE("route_mult_x2y1_upper_in1: not yet implemented for four-group A"); + } else { + auto sb_sml_p03_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.D0"))); + auto sb_sml_p03_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.Y1_int"))); + auto sb_sml_p03_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.YDIAG_int"))); + auto sb_sml_p03_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.YDIAG"))); // AKA SB_SML.P02.X23 + auto sb_sml_p02_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P02.YDIAG_int"))); + auto sb_sml_p02_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P02.YDIAG"))); // AKA SB_SML.P01.X23 + auto sb_sml_p01_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P01.YDIAG_int"))); + auto sb_sml_p01_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P01.Y1_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_p03_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_p03_d0, sb_sml_p03_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p03_y1_int, sb_sml_p03_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p03_ydiag_int, sb_sml_p03_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p03_ydiag, sb_sml_p02_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag_int, sb_sml_p02_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag, sb_sml_p01_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p01_ydiag_int, sb_sml_p01_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p01_y1_int, in_mux, net); + } + + auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.Y"))); + auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); + + find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); + find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in1_int, net); + } + + void route_mult_x2y1_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { + log_info(" routing net '%s' -> IN8 using x2y1\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x1y2 = ctx->idf("X%dY%d", loc.x, loc.y + 1); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); + auto x3y2 = ctx->idf("X%dY%d", loc.x + 2, loc.y + 1); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto out_mux_d2 = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("OM.P09.D2"))); + auto out_mux_y = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("OM.P09.Y"))); + auto in_mux_p09 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P09.D0"))); + + if (bind_route_start) { + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + find_and_bind_downhill_pip(ctx, cpe_out2_int, out_mux_d2, net); + } + + find_and_bind_downhill_pip(ctx, out_mux_d2, out_mux_y, net); // inverting + + if (is_fourgroup_a) { + auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P09.Y1_int"))); + + find_and_bind_downhill_pip(ctx, out_mux_y, sb_sml, net); + find_and_bind_downhill_pip(ctx, sb_sml, in_mux_p09, net); // inverting + } else { + // x1y2/OM.P09.Y is x1y2/SB_BIG.P09.D0 + // x2y2/IM.P09.D0 is x2y1/SB_BIG.P09.Y1 + + find_and_bind_downhill_pip(ctx, out_mux_y, in_mux_p09, net); // inverting + } + + auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x3y2, ctx->idf("IM.P12.D7"))); // aka IM.P09.Y + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x3y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x3y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y + auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x3y2, ctx->idf("IM.P08.Y"))); + auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x3y2, ctx->idf("CPE.IN8_int"))); + + find_and_bind_downhill_pip(ctx, in_mux_p09, in_mux_p12, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p08, in_mux_p08_y, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p08_y, cpe_in8_int, net); + } } NEXTPNR_NAMESPACE_BEGIN @@ -391,6 +527,11 @@ void GateMateImpl::route_mult() { route_mult_x1y2_upper_in1(ctx, upper_out, upper, loc, is_fourgroup_a); if (needs_in8_route) route_mult_x1y2_upper_in8(ctx, upper_out, upper, loc, is_fourgroup_a); + } else if (x_within_fourgroup == 1 && y_within_fourgroup == 0) { + route_mult_x2y1_lower(ctx, lower_out, lower, loc, is_fourgroup_a); + route_mult_x2y1_upper_in1(ctx, upper_out, upper, loc, is_fourgroup_a); + if (needs_in8_route) + route_mult_x2y1_upper_in8(ctx, upper_out, upper, loc, is_fourgroup_a); } else if (is_fourgroup_a) { log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", lower_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", upper_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); @@ -421,6 +562,8 @@ void GateMateImpl::route_mult() { route_mult_x1y1_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /* bind_route_start=*/true); } else if (x_within_fourgroup == 0 && y_within_fourgroup == 1) { route_mult_x1y2_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /* bind_route_start=*/true); + } else if (x_within_fourgroup == 1 && y_within_fourgroup == 0) { + route_mult_x2y1_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /*bind_route_start=*/true); } else if (is_fourgroup_a) { log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); } else { From 80664e55b779fc06a6c9f1951d0a63e6da02509a Mon Sep 17 00:00:00 2001 From: Lofty Date: Sun, 27 Jul 2025 17:38:26 +0100 Subject: [PATCH 13/34] current progress (fixed routing done?) --- himbaechel/uarch/gatemate/route_mult.cc | 225 ++++++++++++++++++++++-- 1 file changed, 211 insertions(+), 14 deletions(-) diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index 92c5b36e..c8b47a11 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -357,7 +357,19 @@ namespace { find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); if (is_fourgroup_a) { - NPNR_ASSERT_FALSE("route_mult_x2y1_lower: not yet implemented for four-group A"); + auto sb_big_p07_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P07.D0"))); + auto sb_big_p07_y1 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P07.Y1"))); + auto sb_big_p07_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P07.YDIAG"))); // AKA SB_BIG.P06.X23 + auto sb_big_p06_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P06.YDIAG"))); // AKA SB_BIG.P05.X23 + auto sb_big_p05_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P05.YDIAG"))); + // x2y1/IM.P05.D0 is x0y1/SB_BIG.P05.Y1 + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big_p07_d0, net); + find_and_bind_downhill_pip(ctx, sb_big_p07_d0, sb_big_p07_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p07_y1, sb_big_p07_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p07_ydiag, sb_big_p06_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p06_ydiag, sb_big_p05_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p05_ydiag, in_mux, net); } else { auto sb_sml_p07_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.D0"))); auto sb_sml_p07_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.Y1_int"))); @@ -401,7 +413,19 @@ namespace { find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); if (is_fourgroup_a) { - NPNR_ASSERT_FALSE("route_mult_x2y1_upper_in1: not yet implemented for four-group A"); + auto sb_big_p03_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P03.D0"))); + auto sb_big_p03_y1 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P03.Y1"))); + auto sb_big_p03_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P03.YDIAG"))); // AKA SB_BIG.P02.X23 + auto sb_big_p02_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P02.YDIAG"))); // AKA SB_BIG.P01.X23 + auto sb_big_p01_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P01.YDIAG"))); + // x2y1/IM.P01.D0 is x0y1/SB_BIG.P01.Y1 + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_p03_d0, net); + find_and_bind_downhill_pip(ctx, sb_big_p03_d0, sb_big_p03_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p03_y1, sb_big_p03_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p03_ydiag, sb_big_p02_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p02_ydiag, sb_big_p01_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p01_ydiag, in_mux, net); } else { auto sb_sml_p03_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.D0"))); auto sb_sml_p03_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.Y1_int"))); @@ -435,7 +459,6 @@ namespace { auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x1y2 = ctx->idf("X%dY%d", loc.x, loc.y + 1); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); auto x3y2 = ctx->idf("X%dY%d", loc.x + 2, loc.y + 1); @@ -454,7 +477,7 @@ namespace { find_and_bind_downhill_pip(ctx, out_mux_d2, out_mux_y, net); // inverting if (is_fourgroup_a) { - auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P09.Y1_int"))); + auto sb_sml = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("SB_SML.P09.Y1_int"))); find_and_bind_downhill_pip(ctx, out_mux_y, sb_sml, net); find_and_bind_downhill_pip(ctx, sb_sml, in_mux_p09, net); // inverting @@ -477,6 +500,183 @@ namespace { find_and_bind_downhill_pip(ctx, in_mux_p08, in_mux_p08_y, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p08_y, cpe_in8_int, net); } + + void route_mult_x2y2_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { + log_info(" routing net '%s' -> IN5 using x2y2\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); + + ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); + + if (is_fourgroup_a) { + auto sb_sml_p08_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P08.D0"))); + auto sb_sml_p08_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P08.Y1_int"))); + auto sb_sml_p08_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P08.YDIAG_int"))); + auto sb_sml_p08_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P08.YDIAG"))); // AKA SB_SML.P07.X23 + auto sb_sml_p07_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P07.YDIAG_int"))); + auto sb_sml_p07_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P07.YDIAG"))); // AKA SB_SML.P06.X23 + auto sb_sml_p06_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P06.YDIAG_int"))); + auto sb_sml_p06_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P06.YDIAG"))); // AKA SB_SML.P05.X23 + auto sb_sml_p05_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.YDIAG_int"))); + auto sb_sml_p05_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.Y1_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_p08_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_p08_d0, sb_sml_p08_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p08_y1_int, sb_sml_p08_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p08_ydiag_int, sb_sml_p08_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p08_ydiag, sb_sml_p07_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag_int, sb_sml_p07_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag, sb_sml_p06_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag_int, sb_sml_p06_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag, sb_sml_p05_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_ydiag_int, sb_sml_p05_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, in_mux, net); + } else { + auto sb_big_p08_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P08.D0"))); + auto sb_big_p08_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P08.Y1"))); + auto sb_big_p08_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P08.YDIAG"))); // AKA SB_BIG.P07.X23 + auto sb_big_p07_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P07.YDIAG"))); // AKA SB_BIG.P06.X23 + auto sb_big_p06_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P06.YDIAG"))); // AKA SB_BIG.P05.X23 + auto sb_big_p05_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.YDIAG"))); + // x2y1/IM.P05.D0 is x1y1/SB_BIG.P05.Y1 + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big_p08_d0, net); + find_and_bind_downhill_pip(ctx, sb_big_p08_d0, sb_big_p08_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p08_y1, sb_big_p08_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p08_ydiag, sb_big_p07_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p07_ydiag, sb_big_p06_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p06_ydiag, sb_big_p05_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p05_ydiag, in_mux, net); + } + + auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.Y"))); + auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); + + find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); + find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in5_int, net); + } + + void route_mult_x2y2_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { + log_info(" routing net '%s' -> IN1 using x2y2\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); + + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + + if (is_fourgroup_a) { + auto sb_sml_p04_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P04.D0"))); + auto sb_sml_p04_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P04.Y1_int"))); + auto sb_sml_p04_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P04.YDIAG_int"))); + auto sb_sml_p04_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P04.YDIAG"))); // AKA SB_SML.P03.X23 + auto sb_sml_p03_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P03.YDIAG_int"))); + auto sb_sml_p03_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P03.YDIAG"))); // AKA SB_SML.P02.X23 + auto sb_sml_p02_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P02.YDIAG_int"))); + auto sb_sml_p02_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P02.YDIAG"))); // AKA SB_SML.P01.X23 + auto sb_sml_p01_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.YDIAG_int"))); + auto sb_sml_p01_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.Y1_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_p04_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_p04_d0, sb_sml_p04_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p04_y1_int, sb_sml_p04_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p04_ydiag_int, sb_sml_p04_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p04_ydiag, sb_sml_p03_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p03_ydiag_int, sb_sml_p03_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p03_ydiag, sb_sml_p02_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag_int, sb_sml_p02_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag, sb_sml_p01_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p01_ydiag_int, sb_sml_p01_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p01_y1_int, in_mux, net); + } else { + auto sb_big_p04_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P04.D0"))); + auto sb_big_p04_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P04.Y1"))); + auto sb_big_p04_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P04.YDIAG"))); // AKA SB_BIG.P07.X23 + auto sb_big_p03_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P03.YDIAG"))); // AKA SB_BIG.P05.X23 + auto sb_big_p02_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P02.YDIAG"))); // AKA SB_BIG.P05.X23 + auto sb_big_p01_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.YDIAG"))); + // x2y1/IM.P05.D0 is x1y1/SB_BIG.P05.Y1 + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_p04_d0, net); + find_and_bind_downhill_pip(ctx, sb_big_p04_d0, sb_big_p04_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p04_y1, sb_big_p04_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p04_ydiag, sb_big_p03_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p03_ydiag, sb_big_p02_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p02_ydiag, sb_big_p01_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p01_ydiag, in_mux, net); + } + + auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.Y"))); + auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); + + find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); + find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in1_int, net); + } + + void route_mult_x2y2_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { + log_info(" routing net '%s' -> IN8 using x2y2\n", net->name.c_str(ctx)); + + auto x0y0 = ctx->idf("X%dY%d", loc.x - 1, loc.y - 1); + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y0 = ctx->idf("X%dY%d", loc.x + 1, loc.y - 1); + auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D1"))); + + if (bind_route_start) { + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + } + + if (is_fourgroup_a) { + auto sb_big_d0 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_BIG.P08.D0"))); + auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_BIG.P08.Y1"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.Y1_int"))); + auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.YDIAG_int"))); + auto sb_sml_y2_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.Y2_int"))); + auto sb_sml_y2 = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.Y2"))); + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_d0, net); + find_and_bind_downhill_pip(ctx, sb_big_d0, sb_big_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_y1, sb_sml_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_ydiag_int, sb_sml_y2_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y2_int, sb_sml_y2, net); + find_and_bind_downhill_pip(ctx, sb_sml_y2, in_mux, net); + } else { + auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.D0"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.Y1_int"))); + auto sb_sml_y1 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.Y1"))); + auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_BIG.P08.Y1"))); + auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_BIG.P08.YDIAG"))); + // x2y2/IM.P08.D0 is x2y0/SB_BIG.P08.Y2 + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_d0, sb_sml_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_y1, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1, sb_big_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_y1, sb_big_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux, net); + } + + auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); + auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); + + find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); + find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in8_int, net); + } } NEXTPNR_NAMESPACE_BEGIN @@ -532,12 +732,11 @@ void GateMateImpl::route_mult() { route_mult_x2y1_upper_in1(ctx, upper_out, upper, loc, is_fourgroup_a); if (needs_in8_route) route_mult_x2y1_upper_in8(ctx, upper_out, upper, loc, is_fourgroup_a); - } else if (is_fourgroup_a) { - log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", lower_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); - log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", upper_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); - } else { - log_info(" don't know how to route net '%s' (it's four-group B, (%d, %d))\n", lower_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); - log_info(" don't know how to route net '%s' (it's four-group B, (%d, %d))\n", upper_out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); + } else /* if (x_within_fourgroup == 1 && y_within_fourgroup == 1) */ { + route_mult_x2y2_lower(ctx, lower_out, lower, loc, is_fourgroup_a); + route_mult_x2y2_upper_in1(ctx, upper_out, upper, loc, is_fourgroup_a); + if (needs_in8_route) + route_mult_x2y2_upper_in8(ctx, upper_out, upper, loc, is_fourgroup_a); } } @@ -564,10 +763,8 @@ void GateMateImpl::route_mult() { route_mult_x1y2_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /* bind_route_start=*/true); } else if (x_within_fourgroup == 1 && y_within_fourgroup == 0) { route_mult_x2y1_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /*bind_route_start=*/true); - } else if (is_fourgroup_a) { - log_info(" don't know how to route net '%s' (it's four-group A, (%d, %d))\n", out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); - } else { - log_info(" don't know how to route net '%s' (it's four-group B, (%d, %d))\n", out->name.c_str(ctx), x_within_fourgroup, y_within_fourgroup); + } else /* if (x_within_fourgroup == 1 && y_within_fourgroup == 1) */ { + route_mult_x2y2_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /*bind_route_start=*/true); } } } From 9837b6f6760d76bb906f838f9431495d2ac81603 Mon Sep 17 00:00:00 2001 From: Lofty Date: Mon, 28 Jul 2025 07:07:52 +0100 Subject: [PATCH 14/34] current progress (broken diagonal router) --- himbaechel/uarch/gatemate/route_mult.cc | 86 +++++++++---------------- 1 file changed, 29 insertions(+), 57 deletions(-) diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index c8b47a11..589e961e 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -43,6 +43,20 @@ namespace { log_error("Couldn't find pip from %s to %s\n", ctx->nameOfWire(from), ctx->nameOfWire(to)); } + void route_mult_diag(Context *ctx, NetInfo *net, Loc loc, WireId last_wire, int plane) { + log_info(" routing diagonal\n"); + + for (int i = 0; i < net->users.entries(); i++) { + auto cpe_in = ctx->getWireByName(IdStringList::concat(ctx->idf("X%dY%d", loc.x + i, loc.y + i), ctx->idf("CPE.IN%d", plane))); + auto cpe_in_int = ctx->getWireByName(IdStringList::concat(ctx->idf("X%dY%d", loc.x + i, loc.y + i), ctx->idf("CPE.IN%d_int", plane))); + + find_and_bind_downhill_pip(ctx, last_wire, cpe_in, net); // inverting + find_and_bind_downhill_pip(ctx, cpe_in, cpe_in_int, net); + + last_wire = cpe_in; + } + } + void route_mult_x1y1_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { log_info(" routing net '%s' -> IN5 using x1y1\n", net->name.c_str(ctx)); @@ -70,11 +84,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_y1_int, in_mux, net); // inverting } - auto cpe_in5 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5"))); - auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); - - find_and_bind_downhill_pip(ctx, in_mux, cpe_in5, net); // inverting - find_and_bind_downhill_pip(ctx, cpe_in5, cpe_in5_int, net); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); } void route_mult_x1y1_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { @@ -104,11 +114,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_y1_int, in_mux, net); // inverting } - auto cpe_in1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1"))); - auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); - - find_and_bind_downhill_pip(ctx, in_mux, cpe_in1, net); // inverting - find_and_bind_downhill_pip(ctx, cpe_in1, cpe_in1_int, net); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); } void route_mult_x1y1_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { @@ -158,13 +164,11 @@ namespace { auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y - auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); - auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting - find_and_bind_downhill_pip(ctx, in_mux_p08, in_mux_p08_y, net); // inverting - find_and_bind_downhill_pip(ctx, in_mux_p08_y, cpe_in8_int, net); + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8); } void route_mult_x1y2_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { @@ -224,11 +228,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_y3_int, in_mux, net); } - auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.Y"))); - auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); - - find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); - find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in5_int, net); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); } void route_mult_x1y2_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { @@ -289,11 +289,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_y3, in_mux, net); } - auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.Y"))); - auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); - - find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); - find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in1_int, net); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); } void route_mult_x1y2_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { @@ -332,14 +328,12 @@ namespace { auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D6"))); // aka IM.P10.Y auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y - auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); - auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); find_and_bind_downhill_pip(ctx, in_mux_p10, in_mux_p12, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting - find_and_bind_downhill_pip(ctx, in_mux_p08, in_mux_p08_y, net); // inverting - find_and_bind_downhill_pip(ctx, in_mux_p08_y, cpe_in8_int, net); + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8); } void route_mult_x2y1_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { @@ -391,11 +385,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, in_mux, net); } - auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.Y"))); - auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); - - find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); - find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in5_int, net); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); } void route_mult_x2y1_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { @@ -447,11 +437,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_p01_y1_int, in_mux, net); } - auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.Y"))); - auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); - - find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); - find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in1_int, net); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); } void route_mult_x2y1_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { @@ -491,14 +477,12 @@ namespace { auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x3y2, ctx->idf("IM.P12.D7"))); // aka IM.P09.Y auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x3y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x3y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y - auto in_mux_p08_y = ctx->getWireByName(IdStringList::concat(x3y2, ctx->idf("IM.P08.Y"))); - auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x3y2, ctx->idf("CPE.IN8_int"))); find_and_bind_downhill_pip(ctx, in_mux_p09, in_mux_p12, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting - find_and_bind_downhill_pip(ctx, in_mux_p08, in_mux_p08_y, net); // inverting - find_and_bind_downhill_pip(ctx, in_mux_p08_y, cpe_in8_int, net); + + route_mult_diag(ctx, net, Loc{loc.x + 2, loc.y + 1, 0}, in_mux_p08, 8); } void route_mult_x2y2_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { @@ -555,11 +539,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_big_p05_ydiag, in_mux, net); } - auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.Y"))); - auto cpe_in5_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN5_int"))); - - find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); - find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in5_int, net); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); } void route_mult_x2y2_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { @@ -616,11 +596,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_big_p01_ydiag, in_mux, net); } - auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.Y"))); - auto cpe_in1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("CPE.IN1_int"))); - - find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); - find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in1_int, net); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); } void route_mult_x2y2_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { @@ -671,11 +647,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux, net); } - auto in_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.Y"))); - auto cpe_in8_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("CPE.IN8_int"))); - - find_and_bind_downhill_pip(ctx, in_mux, in_mux_y, net); - find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in8_int, net); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux, 8); } } From 95b32a2b5614fe2e71271f7566c9b7075d5d0356 Mon Sep 17 00:00:00 2001 From: Lofty Date: Mon, 28 Jul 2025 18:39:36 +0100 Subject: [PATCH 15/34] working diagonal router; unhappy inversion checker --- himbaechel/uarch/gatemate/route_mult.cc | 58 +++++++++++++------------ 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index 589e961e..d44f45ed 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -43,10 +43,10 @@ namespace { log_error("Couldn't find pip from %s to %s\n", ctx->nameOfWire(from), ctx->nameOfWire(to)); } - void route_mult_diag(Context *ctx, NetInfo *net, Loc loc, WireId last_wire, int plane) { - log_info(" routing diagonal\n"); + void route_mult_diag(Context *ctx, NetInfo *net, Loc loc, WireId last_wire, int plane, int hops) { + log_info(" routing diagonal: %d hops\n", hops); - for (int i = 0; i < net->users.entries(); i++) { + for (int i = 0; i < hops; i++) { auto cpe_in = ctx->getWireByName(IdStringList::concat(ctx->idf("X%dY%d", loc.x + i, loc.y + i), ctx->idf("CPE.IN%d", plane))); auto cpe_in_int = ctx->getWireByName(IdStringList::concat(ctx->idf("X%dY%d", loc.x + i, loc.y + i), ctx->idf("CPE.IN%d_int", plane))); @@ -84,7 +84,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_y1_int, in_mux, net); // inverting } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5, net->users.entries()); } void route_mult_x1y1_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { @@ -114,7 +114,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_y1_int, in_mux, net); // inverting } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1, net->users.entries() / 2); } void route_mult_x1y1_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { @@ -168,7 +168,7 @@ namespace { find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8, bind_route_start ? net->users.entries() : net->users.entries() / 2); } void route_mult_x1y2_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { @@ -228,7 +228,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_y3_int, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5, net->users.entries()); } void route_mult_x1y2_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { @@ -289,7 +289,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_y3, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1, net->users.entries() / 2); } void route_mult_x1y2_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { @@ -333,7 +333,7 @@ namespace { find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8, bind_route_start ? net->users.entries() : net->users.entries() / 2); } void route_mult_x2y1_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { @@ -385,7 +385,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5, net->users.entries()); } void route_mult_x2y1_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { @@ -437,7 +437,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_p01_y1_int, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1, net->users.entries() / 2); } void route_mult_x2y1_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { @@ -446,7 +446,6 @@ namespace { auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x1y2 = ctx->idf("X%dY%d", loc.x, loc.y + 1); auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); - auto x3y2 = ctx->idf("X%dY%d", loc.x + 2, loc.y + 1); auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); @@ -474,15 +473,15 @@ namespace { find_and_bind_downhill_pip(ctx, out_mux_y, in_mux_p09, net); // inverting } - auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x3y2, ctx->idf("IM.P12.D7"))); // aka IM.P09.Y - auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x3y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y - auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x3y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y + auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D7"))); // aka IM.P09.Y + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y find_and_bind_downhill_pip(ctx, in_mux_p09, in_mux_p12, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting - route_mult_diag(ctx, net, Loc{loc.x + 2, loc.y + 1, 0}, in_mux_p08, 8); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8, bind_route_start ? net->users.entries() : net->users.entries() / 2); } void route_mult_x2y2_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { @@ -539,7 +538,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_big_p05_ydiag, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5, net->users.entries()); } void route_mult_x2y2_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { @@ -596,7 +595,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_big_p01_ydiag, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1, net->users.entries() / 2); } void route_mult_x2y2_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { @@ -622,15 +621,13 @@ namespace { auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.Y1_int"))); auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.YDIAG_int"))); auto sb_sml_y2_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.Y2_int"))); - auto sb_sml_y2 = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.Y2"))); find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_d0, net); find_and_bind_downhill_pip(ctx, sb_big_d0, sb_big_y1, net); find_and_bind_downhill_pip(ctx, sb_big_y1, sb_sml_y1_int, net); find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_ydiag_int, net); find_and_bind_downhill_pip(ctx, sb_sml_ydiag_int, sb_sml_y2_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_y2_int, sb_sml_y2, net); - find_and_bind_downhill_pip(ctx, sb_sml_y2, in_mux, net); + find_and_bind_downhill_pip(ctx, sb_sml_y2_int, in_mux, net); } else { auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.D0"))); auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.Y1_int"))); @@ -647,7 +644,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux, 8); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux, 8, bind_route_start ? net->users.entries() : net->users.entries() / 2); } } @@ -679,14 +676,17 @@ void GateMateImpl::route_mult() { log_info(" A passthrough at (%d, %d) has 4-group %c\n", loc.x, loc.y, is_fourgroup_a ? 'A' : 'B'); log_info(" lower.OUT [OUT1] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(lower->bel, id_OUT))); - for (auto sink_port : lower->ports.at(id_OUT).net->users) - log_info(" -> %s.%s\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx)); + for (auto sink_port : lower->ports.at(id_OUT).net->users) { + auto sink_loc = ctx->getBelLocation(sink_port.cell->bel); + log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), sink_loc.x, sink_loc.y); + } log_info(" upper.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(upper->bel, id_OUT))); for (auto sink_port : upper->ports.at(id_OUT).net->users) { if (sink_port.port == id_IN8) needs_in8_route = true; - log_info(" -> %s.%s\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx)); + auto sink_loc = ctx->getBelLocation(sink_port.cell->bel); + log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), sink_loc.x, sink_loc.y); } if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { @@ -712,7 +712,7 @@ void GateMateImpl::route_mult() { } } - for (auto &zero_driver : this->multiplier_zero_drivers) { + for (auto *zero_driver : this->multiplier_zero_drivers) { auto *out = zero_driver->ports.at(id_OUT).net; auto loc = ctx->getBelLocation(zero_driver->bel); @@ -726,8 +726,10 @@ void GateMateImpl::route_mult() { log_info(" Zero driver at (%d, %d) has 4-group %c\n", loc.x, loc.y, is_fourgroup_a ? 'A' : 'B'); log_info(" zero_driver.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(zero_driver->bel, id_OUT))); - for (auto sink_port : zero_driver->ports.at(id_OUT).net->users) - log_info(" -> %s.%s\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx)); + for (auto sink_port : zero_driver->ports.at(id_OUT).net->users) { + auto sink_loc = ctx->getBelLocation(sink_port.cell->bel); + log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), sink_loc.x, sink_loc.y); + } if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { route_mult_x1y1_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /* bind_route_start=*/true); From ff9fa6f4cc4b52193637e53c06a1efb4566242c8 Mon Sep 17 00:00:00 2001 From: Lofty Date: Tue, 29 Jul 2025 08:18:44 +0100 Subject: [PATCH 16/34] route comments --- himbaechel/uarch/gatemate/route_mult.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index d44f45ed..457617aa 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -512,14 +512,14 @@ namespace { find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_p08_d0, net); find_and_bind_downhill_pip(ctx, sb_sml_p08_d0, sb_sml_p08_y1_int, net); find_and_bind_downhill_pip(ctx, sb_sml_p08_y1_int, sb_sml_p08_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p08_ydiag_int, sb_sml_p08_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p08_ydiag_int, sb_sml_p08_ydiag, net); // inverting find_and_bind_downhill_pip(ctx, sb_sml_p08_ydiag, sb_sml_p07_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag_int, sb_sml_p07_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag_int, sb_sml_p07_ydiag, net); // inverting find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag, sb_sml_p06_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag_int, sb_sml_p06_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag_int, sb_sml_p06_ydiag, net); // inverting find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag, sb_sml_p05_ydiag_int, net); find_and_bind_downhill_pip(ctx, sb_sml_p05_ydiag_int, sb_sml_p05_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, in_mux, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, in_mux, net); // inverting } else { auto sb_big_p08_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P08.D0"))); auto sb_big_p08_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P08.Y1"))); @@ -732,9 +732,9 @@ void GateMateImpl::route_mult() { } if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { - route_mult_x1y1_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /* bind_route_start=*/true); + route_mult_x1y1_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /*bind_route_start=*/true); } else if (x_within_fourgroup == 0 && y_within_fourgroup == 1) { - route_mult_x1y2_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /* bind_route_start=*/true); + route_mult_x1y2_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /*bind_route_start=*/true); } else if (x_within_fourgroup == 1 && y_within_fourgroup == 0) { route_mult_x2y1_upper_in8(ctx, out, zero_driver, loc, is_fourgroup_a, /*bind_route_start=*/true); } else /* if (x_within_fourgroup == 1 && y_within_fourgroup == 1) */ { From ac8a12aee5a78615dc1d060bc68ae39e6f2f1751 Mon Sep 17 00:00:00 2001 From: Lofty Date: Tue, 29 Jul 2025 08:50:10 +0100 Subject: [PATCH 17/34] bugfix for number of hops --- himbaechel/uarch/gatemate/bitstream.cc | 12 ++++----- himbaechel/uarch/gatemate/route_mult.cc | 33 +++++++++++++++---------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/himbaechel/uarch/gatemate/bitstream.cc b/himbaechel/uarch/gatemate/bitstream.cc index 1360de08..d2baf908 100644 --- a/himbaechel/uarch/gatemate/bitstream.cc +++ b/himbaechel/uarch/gatemate/bitstream.cc @@ -23,6 +23,7 @@ #include "config.h" #include "gatemate.h" #include "gatemate_util.h" +#include "log.h" #include "property.h" #include "uarch/gatemate/pack.h" @@ -274,28 +275,27 @@ struct BitstreamBackend if (!all_correct && !all_inverted) { log_warning("multiplier net '%s' has inconsistent inversion\n", net_name.c_str(ctx)); + auto driver_loc = ctx->getBelLocation(net->driver.cell->bel); + log_warning("net is driven from (%d, %d)\n", driver_loc.x, driver_loc.y); + log_warning(" these ports are not inverted:\n"); for (PortRef user : net->users) { auto loc = ctx->getBelLocation(user.cell->bel); - auto x_fourgroup = (loc.x - 3) % 4; - auto y_fourgroup = (loc.y - 3) % 4; auto should_be_inverted = user.cell->constr_x % 2 == 1; auto inversion = need_inversion(user.cell, user.port); if (inversion == should_be_inverted) - log_warning(" %s.%s with four-group (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), x_fourgroup, y_fourgroup); + log_warning(" %s.%s at (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), loc.x, loc.y); } log_warning(" these ports are inverted:\n"); for (PortRef user : net->users) { auto loc = ctx->getBelLocation(user.cell->bel); - auto x_fourgroup = (loc.x - 3) % 4; - auto y_fourgroup = (loc.y - 3) % 4; auto should_be_inverted = user.cell->constr_x % 2 == 1; auto inversion = need_inversion(user.cell, user.port); if (inversion != should_be_inverted) - log_warning(" %s.%s with four-group (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), x_fourgroup, y_fourgroup); + log_warning(" %s.%s at (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), loc.x, loc.y); } } else if (all_inverted) { net->driver.cell->params[id_INIT_L10] = Property(~driver_l10 & 0b1111, 4); diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index 457617aa..eed80f2a 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -43,7 +43,14 @@ namespace { log_error("Couldn't find pip from %s to %s\n", ctx->nameOfWire(from), ctx->nameOfWire(to)); } - void route_mult_diag(Context *ctx, NetInfo *net, Loc loc, WireId last_wire, int plane, int hops) { + void route_mult_diag(Context *ctx, NetInfo *net, Loc loc, WireId last_wire, int plane) { + auto hops = 0; + auto in_port = ctx->idf("IN%d", plane); + for (auto user : net->users) { + if (user.port == in_port) + hops++; + } + log_info(" routing diagonal: %d hops\n", hops); for (int i = 0; i < hops; i++) { @@ -84,7 +91,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_y1_int, in_mux, net); // inverting } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5, net->users.entries()); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); } void route_mult_x1y1_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { @@ -114,7 +121,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_y1_int, in_mux, net); // inverting } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1, net->users.entries() / 2); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); } void route_mult_x1y1_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { @@ -168,7 +175,7 @@ namespace { find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8, bind_route_start ? net->users.entries() : net->users.entries() / 2); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8); } void route_mult_x1y2_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { @@ -228,7 +235,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_y3_int, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5, net->users.entries()); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); } void route_mult_x1y2_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { @@ -289,7 +296,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_y3, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1, net->users.entries() / 2); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); } void route_mult_x1y2_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { @@ -333,7 +340,7 @@ namespace { find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8, bind_route_start ? net->users.entries() : net->users.entries() / 2); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8); } void route_mult_x2y1_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { @@ -385,7 +392,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5, net->users.entries()); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); } void route_mult_x2y1_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { @@ -437,7 +444,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_sml_p01_y1_int, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1, net->users.entries() / 2); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); } void route_mult_x2y1_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { @@ -481,7 +488,7 @@ namespace { find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8, bind_route_start ? net->users.entries() : net->users.entries() / 2); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8); } void route_mult_x2y2_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { @@ -538,7 +545,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_big_p05_ydiag, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5, net->users.entries()); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); } void route_mult_x2y2_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { @@ -595,7 +602,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_big_p01_ydiag, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1, net->users.entries() / 2); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); } void route_mult_x2y2_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { @@ -644,7 +651,7 @@ namespace { find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux, net); } - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux, 8, bind_route_start ? net->users.entries() : net->users.entries() / 2); + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux, 8); } } From d26aa342b7b475445d52d9dea6562bcfe97c8812 Mon Sep 17 00:00:00 2001 From: Lofty Date: Tue, 29 Jul 2025 09:25:54 +0100 Subject: [PATCH 18/34] bugfix for x2y2 in8 binding a pip twice --- himbaechel/uarch/gatemate/route_mult.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index eed80f2a..a0579f60 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -620,6 +620,13 @@ namespace { if (bind_route_start) { ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + if (is_fourgroup_a) { + auto sb_big_d0 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_BIG.P08.D0"))); + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_d0, net); + } else { + auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.D0"))); + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_d0, net); + } } if (is_fourgroup_a) { @@ -629,7 +636,6 @@ namespace { auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.YDIAG_int"))); auto sb_sml_y2_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.Y2_int"))); - find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_d0, net); find_and_bind_downhill_pip(ctx, sb_big_d0, sb_big_y1, net); find_and_bind_downhill_pip(ctx, sb_big_y1, sb_sml_y1_int, net); find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_ydiag_int, net); @@ -643,7 +649,6 @@ namespace { auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_BIG.P08.YDIAG"))); // x2y2/IM.P08.D0 is x2y0/SB_BIG.P08.Y2 - find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_d0, net); find_and_bind_downhill_pip(ctx, sb_sml_d0, sb_sml_y1_int, net); find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_y1, net); find_and_bind_downhill_pip(ctx, sb_sml_y1, sb_big_y1, net); From 7d8b7da20b4d8b2b5218e049008d7c0ee036c49b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 29 Jul 2025 13:59:59 +0200 Subject: [PATCH 19/34] Add missing connection --- himbaechel/uarch/gatemate/pack_mult.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/himbaechel/uarch/gatemate/pack_mult.cc b/himbaechel/uarch/gatemate/pack_mult.cc index 8a5e69d2..859de5a5 100644 --- a/himbaechel/uarch/gatemate/pack_mult.cc +++ b/himbaechel/uarch/gatemate/pack_mult.cc @@ -528,6 +528,10 @@ void GateMatePacker::pack_mult() msb_route_comp->connectPort(id_COMPOUT, comp_conn); msb_route_lines->connectPort(id_COMPOUT, comp_conn); + NetInfo *out_conn = ctx->createNet(ctx->idf("%s$msb_route$out", name.c_str(ctx))); + msb_route_upper->connectPort(id_OUT, out_conn); + msb_route_lines->connectPort(id_OUT2, out_conn); + col.msb_route = MsbRoutingCell{msb_route_lower, msb_route_upper, msb_route_comp, msb_route_lines, name}; } From 341e288488d6905c0ca28502eb711d1dddc82a7e Mon Sep 17 00:00:00 2001 From: Lofty Date: Thu, 31 Jul 2025 14:50:36 +0100 Subject: [PATCH 20/34] fix swapped B inputs --- himbaechel/uarch/gatemate/pack_mult.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/himbaechel/uarch/gatemate/pack_mult.cc b/himbaechel/uarch/gatemate/pack_mult.cc index 859de5a5..8a843eb3 100644 --- a/himbaechel/uarch/gatemate/pack_mult.cc +++ b/himbaechel/uarch/gatemate/pack_mult.cc @@ -709,8 +709,8 @@ void GateMatePacker::pack_mult() auto &b_passthru = m.cols.at(b).b_passthru; // Connect B input passthrough cell. - mult->movePortTo(ctx->idf("B[%d]", 2 * b), b_passthru.upper, id_IN1); - mult->movePortTo(ctx->idf("B[%d]", 2 * b + 1), b_passthru.lower, id_IN1); + mult->movePortTo(ctx->idf("B[%d]", 2 * b), b_passthru.lower, id_IN1); + mult->movePortTo(ctx->idf("B[%d]", 2 * b + 1), b_passthru.upper, id_IN1); } // Intermediate multiplier connections. From d53f7740785c78c7105161a1e48b756e1466503c Mon Sep 17 00:00:00 2001 From: Lofty Date: Thu, 31 Jul 2025 14:54:43 +0100 Subject: [PATCH 21/34] re-disable multiplier packing --- himbaechel/uarch/gatemate/pack.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/himbaechel/uarch/gatemate/pack.cc b/himbaechel/uarch/gatemate/pack.cc index f2caef1d..393f56c7 100644 --- a/himbaechel/uarch/gatemate/pack.cc +++ b/himbaechel/uarch/gatemate/pack.cc @@ -397,7 +397,7 @@ void GateMateImpl::pack() packer.pack_misc(); packer.pack_ram(); packer.pack_serdes(); - packer.pack_mult(); + // packer.pack_mult(); packer.pack_addf(); packer.pack_cpe(); packer.remove_constants(); From da5d42dc9daa370df988782d2a44f79d1997171a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 1 Aug 2025 12:25:22 +0200 Subject: [PATCH 22/34] Add missing connection --- himbaechel/uarch/gatemate/pack_mult.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/himbaechel/uarch/gatemate/pack_mult.cc b/himbaechel/uarch/gatemate/pack_mult.cc index 8a843eb3..03ae85b5 100644 --- a/himbaechel/uarch/gatemate/pack_mult.cc +++ b/himbaechel/uarch/gatemate/pack_mult.cc @@ -476,6 +476,9 @@ void GateMatePacker::pack_mult() NetInfo *comb2_conn = ctx->createNet(ctx->idf("%s$multf%c$comb2", name.c_str(ctx), is_even_x ? 'a' : 'b')); multfab_upper->connectPort(id_OUT, comb2_conn); + multfab_lower->ports[id_COMBIN].name = id_COMBIN; + multfab_lower->ports[id_COMBIN].type = PORT_IN; + multfab_lower->connectPort(id_COMBIN, comb2_conn); multfab_comp->connectPort(id_COMB2, comb2_conn); NetInfo *comp_out = ctx->createNet(ctx->idf("%s$multf%c$comp_out", name.c_str(ctx), is_even_x ? 'a' : 'b')); From 49001df2901b7f91cafd1efac5b1b273b44645f8 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 1 Aug 2025 14:46:54 +0200 Subject: [PATCH 23/34] Fix when width is 1 --- himbaechel/uarch/gatemate/pack_mult.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/himbaechel/uarch/gatemate/pack_mult.cc b/himbaechel/uarch/gatemate/pack_mult.cc index 03ae85b5..7bae5514 100644 --- a/himbaechel/uarch/gatemate/pack_mult.cc +++ b/himbaechel/uarch/gatemate/pack_mult.cc @@ -555,6 +555,10 @@ void GateMatePacker::pack_mult() auto a_width = int_or_default(mult->params, id_A_WIDTH); auto b_width = int_or_default(mult->params, id_B_WIDTH); auto p_width = int_or_default(mult->params, id_P_WIDTH); + if (mult->getPort(id_A)) + mult->renamePort(id_A, ctx->id("A[0]")); + if (mult->getPort(id_B)) + mult->renamePort(id_B, ctx->id("B[0]")); // Sign-extend odd A_WIDTH to even, because we're working with 2x2 multiplier cells. while (a_width < p_width || a_width % 2 == 1) { From d26fc197248fd10bb2378a6917a6bf009ce3bd53 Mon Sep 17 00:00:00 2001 From: Lofty Date: Fri, 1 Aug 2025 16:46:22 +0100 Subject: [PATCH 24/34] clangformat --- himbaechel/uarch/gatemate/bitstream.cc | 6 +- himbaechel/uarch/gatemate/route_mult.cc | 1297 ++++++++++++----------- 2 files changed, 677 insertions(+), 626 deletions(-) diff --git a/himbaechel/uarch/gatemate/bitstream.cc b/himbaechel/uarch/gatemate/bitstream.cc index d2baf908..23f49805 100644 --- a/himbaechel/uarch/gatemate/bitstream.cc +++ b/himbaechel/uarch/gatemate/bitstream.cc @@ -285,7 +285,8 @@ struct BitstreamBackend auto should_be_inverted = user.cell->constr_x % 2 == 1; auto inversion = need_inversion(user.cell, user.port); if (inversion == should_be_inverted) - log_warning(" %s.%s at (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), loc.x, loc.y); + log_warning(" %s.%s at (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), loc.x, + loc.y); } log_warning(" these ports are inverted:\n"); @@ -295,7 +296,8 @@ struct BitstreamBackend auto should_be_inverted = user.cell->constr_x % 2 == 1; auto inversion = need_inversion(user.cell, user.port); if (inversion != should_be_inverted) - log_warning(" %s.%s at (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), loc.x, loc.y); + log_warning(" %s.%s at (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), loc.x, + loc.y); } } else if (all_inverted) { net->driver.cell->params[id_INIT_L10] = Property(~driver_l10 & 0b1111, 4); diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index a0579f60..6e2b2408 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -27,642 +27,688 @@ #include "himbaechel_constids.h" namespace { - USING_NEXTPNR_NAMESPACE; +USING_NEXTPNR_NAMESPACE; - void find_and_bind_downhill_pip(Context *ctx, WireId from, WireId to, NetInfo *net) { - NPNR_ASSERT(from != WireId()); - NPNR_ASSERT(to != WireId()); - for (auto pip : ctx->getPipsDownhill(from)) { - if (ctx->getPipDstWire(pip) == to) { - log_info(" pip %s: %s -> %s\n", ctx->nameOfPip(pip), ctx->nameOfWire(from), ctx->nameOfWire(to)); +void find_and_bind_downhill_pip(Context *ctx, WireId from, WireId to, NetInfo *net) +{ + NPNR_ASSERT(from != WireId()); + NPNR_ASSERT(to != WireId()); + for (auto pip : ctx->getPipsDownhill(from)) { + if (ctx->getPipDstWire(pip) == to) { + log_info(" pip %s: %s -> %s\n", ctx->nameOfPip(pip), ctx->nameOfWire(from), ctx->nameOfWire(to)); - ctx->bindPip(pip, net, STRENGTH_LOCKED); - return; - } - } - log_error("Couldn't find pip from %s to %s\n", ctx->nameOfWire(from), ctx->nameOfWire(to)); - } - - void route_mult_diag(Context *ctx, NetInfo *net, Loc loc, WireId last_wire, int plane) { - auto hops = 0; - auto in_port = ctx->idf("IN%d", plane); - for (auto user : net->users) { - if (user.port == in_port) - hops++; - } - - log_info(" routing diagonal: %d hops\n", hops); - - for (int i = 0; i < hops; i++) { - auto cpe_in = ctx->getWireByName(IdStringList::concat(ctx->idf("X%dY%d", loc.x + i, loc.y + i), ctx->idf("CPE.IN%d", plane))); - auto cpe_in_int = ctx->getWireByName(IdStringList::concat(ctx->idf("X%dY%d", loc.x + i, loc.y + i), ctx->idf("CPE.IN%d_int", plane))); - - find_and_bind_downhill_pip(ctx, last_wire, cpe_in, net); // inverting - find_and_bind_downhill_pip(ctx, cpe_in, cpe_in_int, net); - - last_wire = cpe_in; + ctx->bindPip(pip, net, STRENGTH_LOCKED); + return; } } + log_error("Couldn't find pip from %s to %s\n", ctx->nameOfWire(from), ctx->nameOfWire(to)); +} - void route_mult_x1y1_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN5 using x1y1\n", net->name.c_str(ctx)); - - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); - - auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); - auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); - - ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); - find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); - - if (is_fourgroup_a) { - auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0"))); - - find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big, net); - find_and_bind_downhill_pip(ctx, sb_big, in_mux, net); // inverting - } else { - auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.D0"))); - auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.Y1_int"))); - - find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_d0, net); - find_and_bind_downhill_pip(ctx, sb_sml_d0, sb_sml_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_y1_int, in_mux, net); // inverting - } - - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); +void route_mult_diag(Context *ctx, NetInfo *net, Loc loc, WireId last_wire, int plane) +{ + auto hops = 0; + auto in_port = ctx->idf("IN%d", plane); + for (auto user : net->users) { + if (user.port == in_port) + hops++; } - void route_mult_x1y1_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN1 using x1y1\n", net->name.c_str(ctx)); + log_info(" routing diagonal: %d hops\n", hops); - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + for (int i = 0; i < hops; i++) { + auto cpe_in = ctx->getWireByName( + IdStringList::concat(ctx->idf("X%dY%d", loc.x + i, loc.y + i), ctx->idf("CPE.IN%d", plane))); + auto cpe_in_int = ctx->getWireByName( + IdStringList::concat(ctx->idf("X%dY%d", loc.x + i, loc.y + i), ctx->idf("CPE.IN%d_int", plane))); - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); + find_and_bind_downhill_pip(ctx, last_wire, cpe_in, net); // inverting + find_and_bind_downhill_pip(ctx, cpe_in, cpe_in_int, net); - ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); - find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); - - if (is_fourgroup_a) { - auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0"))); - - find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big, net); - find_and_bind_downhill_pip(ctx, sb_big, in_mux, net); // inverting - } else { - auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.D0"))); - auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.Y1_int"))); - - find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_d0, net); - find_and_bind_downhill_pip(ctx, sb_sml_d0, sb_sml_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_y1_int, in_mux, net); // inverting - } - - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); - } - - void route_mult_x1y1_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { - log_info(" routing net '%s' -> IN8 using x1y1\n", net->name.c_str(ctx)); - - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); - auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); - - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); - auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); - auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); - - if (bind_route_start) { - ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); - find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); - find_and_bind_downhill_pip(ctx, cpe_out2_int, out_mux_d0, net); - } - - find_and_bind_downhill_pip(ctx, out_mux_d0, out_mux_y, net); // inverting - - if (is_fourgroup_a) { - auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.Y1_int"))); - auto sb_big_d2_1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.D2_1"))); - auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.Y1"))); - auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.YDIAG"))); - - find_and_bind_downhill_pip(ctx, out_mux_y, sb_sml, net); - find_and_bind_downhill_pip(ctx, sb_sml, sb_big_d2_1, net); // inverting - find_and_bind_downhill_pip(ctx, sb_big_d2_1, sb_big_y1, net); // inverting - find_and_bind_downhill_pip(ctx, sb_big_y1, sb_big_ydiag, net); // inverting - find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux_p12, net); // inverting - } else { - auto sb_big = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_BIG.P12.Y1"))); // aka x4y2/SB_SML.P12.D2_1 - auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y1_int"))); - auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.YDIAG_int"))); - auto sb_sml_y3_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y3_int"))); - - find_and_bind_downhill_pip(ctx, out_mux_y, sb_big, net); // inverting - find_and_bind_downhill_pip(ctx, sb_big, sb_sml_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_ydiag_int, sb_sml_y3_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_y3_int, in_mux_p12, net); // inverting - } - - auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y - auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y - - find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting - find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting - - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8); - } - - void route_mult_x1y2_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN5 using x1y2\n", net->name.c_str(ctx)); - - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); - auto x4y1 = ctx->idf("X%dY%d", loc.x + 3, loc.y); - - auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); - auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D2"))); - - ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); - find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); - - if (is_fourgroup_a) { - auto sb_sml_p06_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P06.D0"))); - auto sb_sml_p06_y1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P06.Y1_int"))); - auto sb_sml_p06_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P06.YDIAG_int"))); - auto sb_sml_p06_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P06.YDIAG"))); // AKA SB_SML.P05.X23 - auto sb_sml_p05_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P05.YDIAG_int"))); - auto sb_sml_p05_y1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P05.Y1_int"))); - auto sb_sml_p05_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P05.Y1"))); - auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P05.Y1"))); - auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P05.YDIAG"))); - // x2y1/IM.P05.D2 is x4y1/SB_BIG.P05.Y3 - - find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_p06_d0, net); - find_and_bind_downhill_pip(ctx, sb_sml_p06_d0, sb_sml_p06_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p06_y1_int, sb_sml_p06_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag_int, sb_sml_p06_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag, sb_sml_p05_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p05_ydiag_int, sb_sml_p05_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, sb_sml_p05_y1, net); - find_and_bind_downhill_pip(ctx, sb_sml_p05_y1,sb_big_y1, net); - find_and_bind_downhill_pip(ctx, sb_big_y1, sb_big_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux, net); - } else { - auto sb_big_p06_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P06.D0"))); - auto sb_big_p06_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P06.Y1"))); - auto sb_big_p06_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P06.YDIAG"))); // AKA SB_BIG.P05.X23 - auto sb_big_p05_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P05.YDIAG"))); - auto sb_big_p05_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P05.Y1"))); - auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P05.Y1_int"))); - auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P05.YDIAG_int"))); - auto sb_sml_y3_int = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P05.Y3_int"))); - - find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big_p06_d0, net); - find_and_bind_downhill_pip(ctx, sb_big_p06_d0, sb_big_p06_y1, net); - find_and_bind_downhill_pip(ctx, sb_big_p06_y1, sb_big_p06_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p06_ydiag, sb_big_p05_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p05_ydiag, sb_big_p05_y1, net); - find_and_bind_downhill_pip(ctx, sb_big_p05_y1, sb_sml_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_y1_int,sb_sml_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_ydiag_int, sb_sml_y3_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_y3_int, in_mux, net); - } - - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); - } - - void route_mult_x1y2_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN1 using x1y2\n", net->name.c_str(ctx)); - - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); - auto x4y1 = ctx->idf("X%dY%d", loc.x + 3, loc.y); - - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - - ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); - find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); - - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D2"))); - - if (is_fourgroup_a) { - auto sb_sml_p02_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P02.D0"))); - auto sb_sml_p02_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P02.Y1_int"))); - auto sb_sml_p02_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P02.YDIAG_int"))); - auto sb_sml_p02_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P02.YDIAG"))); // AKA SB_SML.P01.X23 - auto sb_sml_p01_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P01.YDIAG_int"))); - auto sb_sml_p01_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P01.Y1_int"))); - auto sb_big_d2_1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P01.D2_1"))); - auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P01.Y1"))); - auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P01.YDIAG"))); - // x2y1/IM.P01.D2 is x4y1/SB_BIG.P01.Y3 - - find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_p02_d0, net); - find_and_bind_downhill_pip(ctx, sb_sml_p02_d0, sb_sml_p02_y1, net); - find_and_bind_downhill_pip(ctx, sb_sml_p02_y1, sb_sml_p02_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag_int, sb_sml_p02_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag, sb_sml_p01_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_sml_p01_ydiag, sb_sml_p01_y1, net); - find_and_bind_downhill_pip(ctx, sb_sml_p01_y1, sb_big_d2_1, net); - find_and_bind_downhill_pip(ctx, sb_big_d2_1, sb_big_y1, net); - find_and_bind_downhill_pip(ctx, sb_big_y1, sb_big_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux, net); - } else { - auto sb_big_p02_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P02.D0"))); - auto sb_big_p02_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P02.Y1"))); - auto sb_big_p02_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P02.YDIAG"))); // AKA SB_BIG.P01.X23 - auto sb_big_p01_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P01.YDIAG"))); - auto sb_big_p01_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P01.Y1"))); - auto sb_sml_y1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P01.Y1_int"))); - auto sb_sml_ydiag = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P01.YDIAG_int"))); - auto sb_sml_y3 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P01.Y3_int"))); - - find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_p02_d0, net); - find_and_bind_downhill_pip(ctx, sb_big_p02_d0, sb_big_p02_y1, net); - find_and_bind_downhill_pip(ctx, sb_big_p02_y1, sb_big_p02_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p02_ydiag, sb_big_p01_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p01_ydiag, sb_big_p01_y1, net); - find_and_bind_downhill_pip(ctx, sb_big_p01_y1, sb_sml_y1, net); - find_and_bind_downhill_pip(ctx, sb_sml_y1, sb_sml_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_sml_ydiag, sb_sml_y3, net); - find_and_bind_downhill_pip(ctx, sb_sml_y3, in_mux, net); - } - - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); - } - - void route_mult_x1y2_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { - log_info(" routing net '%s' -> IN8 using x1y2\n", net->name.c_str(ctx)); - - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); - auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); - - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - auto out_mux_d1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.D1"))); - auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.Y"))); - auto in_mux_p10 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P10.D1"))); - - if (bind_route_start) { - ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); - find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); - find_and_bind_downhill_pip(ctx, cpe_out2_int, out_mux_d1, net); - } - - find_and_bind_downhill_pip(ctx, out_mux_d1, out_mux_y, net); // inverting - - if (is_fourgroup_a) { - auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P10.Y2_int"))); - - find_and_bind_downhill_pip(ctx, out_mux_y, sb_sml, net); - find_and_bind_downhill_pip(ctx, sb_sml, in_mux_p10, net); // inverting - } else { - // x2y1/OM.P10.Y is x2y1/SB_BIG.P10.D0 - // x2y2/IM.P10.D1 is x2y1/SB_BIG.P10.Y2 - - find_and_bind_downhill_pip(ctx, out_mux_y, in_mux_p10, net); // inverting - } - - auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D6"))); // aka IM.P10.Y - auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y - auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y - - find_and_bind_downhill_pip(ctx, in_mux_p10, in_mux_p12, net); // inverting - find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting - find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting - - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8); - } - - void route_mult_x2y1_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN5 using x2y1\n", net->name.c_str(ctx)); - - auto x0y1 = ctx->idf("X%dY%d", loc.x - 1, loc.y); - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); - - auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); - auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); - - ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); - find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); - - if (is_fourgroup_a) { - auto sb_big_p07_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P07.D0"))); - auto sb_big_p07_y1 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P07.Y1"))); - auto sb_big_p07_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P07.YDIAG"))); // AKA SB_BIG.P06.X23 - auto sb_big_p06_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P06.YDIAG"))); // AKA SB_BIG.P05.X23 - auto sb_big_p05_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P05.YDIAG"))); - // x2y1/IM.P05.D0 is x0y1/SB_BIG.P05.Y1 - - find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big_p07_d0, net); - find_and_bind_downhill_pip(ctx, sb_big_p07_d0, sb_big_p07_y1, net); - find_and_bind_downhill_pip(ctx, sb_big_p07_y1, sb_big_p07_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p07_ydiag, sb_big_p06_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p06_ydiag, sb_big_p05_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p05_ydiag, in_mux, net); - } else { - auto sb_sml_p07_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.D0"))); - auto sb_sml_p07_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.Y1_int"))); - auto sb_sml_p07_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.YDIAG_int"))); - auto sb_sml_p07_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.YDIAG"))); // AKA SB_SML.P06.X23 - auto sb_sml_p06_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P06.YDIAG_int"))); - auto sb_sml_p06_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P06.YDIAG"))); // AKA SB_SML.P05.X23 - auto sb_sml_p05_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P05.YDIAG_int"))); - auto sb_sml_p05_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P05.Y1_int"))); - - find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_p07_d0, net); - find_and_bind_downhill_pip(ctx, sb_sml_p07_d0, sb_sml_p07_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p07_y1_int, sb_sml_p07_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag_int, sb_sml_p07_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag, sb_sml_p06_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag_int, sb_sml_p06_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag, sb_sml_p05_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p05_ydiag_int, sb_sml_p05_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, in_mux, net); - } - - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); - } - - void route_mult_x2y1_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN1 using x2y1\n", net->name.c_str(ctx)); - - auto x0y1 = ctx->idf("X%dY%d", loc.x - 1, loc.y); - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); - - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); - - ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); - find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); - - if (is_fourgroup_a) { - auto sb_big_p03_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P03.D0"))); - auto sb_big_p03_y1 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P03.Y1"))); - auto sb_big_p03_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P03.YDIAG"))); // AKA SB_BIG.P02.X23 - auto sb_big_p02_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P02.YDIAG"))); // AKA SB_BIG.P01.X23 - auto sb_big_p01_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P01.YDIAG"))); - // x2y1/IM.P01.D0 is x0y1/SB_BIG.P01.Y1 - - find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_p03_d0, net); - find_and_bind_downhill_pip(ctx, sb_big_p03_d0, sb_big_p03_y1, net); - find_and_bind_downhill_pip(ctx, sb_big_p03_y1, sb_big_p03_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p03_ydiag, sb_big_p02_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p02_ydiag, sb_big_p01_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p01_ydiag, in_mux, net); - } else { - auto sb_sml_p03_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.D0"))); - auto sb_sml_p03_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.Y1_int"))); - auto sb_sml_p03_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.YDIAG_int"))); - auto sb_sml_p03_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.YDIAG"))); // AKA SB_SML.P02.X23 - auto sb_sml_p02_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P02.YDIAG_int"))); - auto sb_sml_p02_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P02.YDIAG"))); // AKA SB_SML.P01.X23 - auto sb_sml_p01_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P01.YDIAG_int"))); - auto sb_sml_p01_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P01.Y1_int"))); - - find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_p03_d0, net); - find_and_bind_downhill_pip(ctx, sb_sml_p03_d0, sb_sml_p03_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p03_y1_int, sb_sml_p03_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p03_ydiag_int, sb_sml_p03_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_sml_p03_ydiag, sb_sml_p02_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag_int, sb_sml_p02_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag, sb_sml_p01_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p01_ydiag_int, sb_sml_p01_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p01_y1_int, in_mux, net); - } - - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); - } - - void route_mult_x2y1_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { - log_info(" routing net '%s' -> IN8 using x2y1\n", net->name.c_str(ctx)); - - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x1y2 = ctx->idf("X%dY%d", loc.x, loc.y + 1); - auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); - - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - auto out_mux_d2 = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("OM.P09.D2"))); - auto out_mux_y = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("OM.P09.Y"))); - auto in_mux_p09 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P09.D0"))); - - if (bind_route_start) { - ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); - find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); - find_and_bind_downhill_pip(ctx, cpe_out2_int, out_mux_d2, net); - } - - find_and_bind_downhill_pip(ctx, out_mux_d2, out_mux_y, net); // inverting - - if (is_fourgroup_a) { - auto sb_sml = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("SB_SML.P09.Y1_int"))); - - find_and_bind_downhill_pip(ctx, out_mux_y, sb_sml, net); - find_and_bind_downhill_pip(ctx, sb_sml, in_mux_p09, net); // inverting - } else { - // x1y2/OM.P09.Y is x1y2/SB_BIG.P09.D0 - // x2y2/IM.P09.D0 is x2y1/SB_BIG.P09.Y1 - - find_and_bind_downhill_pip(ctx, out_mux_y, in_mux_p09, net); // inverting - } - - auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D7"))); // aka IM.P09.Y - auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y - auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y - - find_and_bind_downhill_pip(ctx, in_mux_p09, in_mux_p12, net); // inverting - find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting - find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting - - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8); - } - - void route_mult_x2y2_lower(Context *ctx, NetInfo *net, CellInfo* lower, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN5 using x2y2\n", net->name.c_str(ctx)); - - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); - - auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); - auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); - - ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); - find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); - - if (is_fourgroup_a) { - auto sb_sml_p08_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P08.D0"))); - auto sb_sml_p08_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P08.Y1_int"))); - auto sb_sml_p08_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P08.YDIAG_int"))); - auto sb_sml_p08_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P08.YDIAG"))); // AKA SB_SML.P07.X23 - auto sb_sml_p07_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P07.YDIAG_int"))); - auto sb_sml_p07_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P07.YDIAG"))); // AKA SB_SML.P06.X23 - auto sb_sml_p06_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P06.YDIAG_int"))); - auto sb_sml_p06_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P06.YDIAG"))); // AKA SB_SML.P05.X23 - auto sb_sml_p05_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.YDIAG_int"))); - auto sb_sml_p05_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.Y1_int"))); - - find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_p08_d0, net); - find_and_bind_downhill_pip(ctx, sb_sml_p08_d0, sb_sml_p08_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p08_y1_int, sb_sml_p08_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p08_ydiag_int, sb_sml_p08_ydiag, net); // inverting - find_and_bind_downhill_pip(ctx, sb_sml_p08_ydiag, sb_sml_p07_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag_int, sb_sml_p07_ydiag, net); // inverting - find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag, sb_sml_p06_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag_int, sb_sml_p06_ydiag, net); // inverting - find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag, sb_sml_p05_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p05_ydiag_int, sb_sml_p05_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, in_mux, net); // inverting - } else { - auto sb_big_p08_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P08.D0"))); - auto sb_big_p08_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P08.Y1"))); - auto sb_big_p08_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P08.YDIAG"))); // AKA SB_BIG.P07.X23 - auto sb_big_p07_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P07.YDIAG"))); // AKA SB_BIG.P06.X23 - auto sb_big_p06_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P06.YDIAG"))); // AKA SB_BIG.P05.X23 - auto sb_big_p05_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.YDIAG"))); - // x2y1/IM.P05.D0 is x1y1/SB_BIG.P05.Y1 - - find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big_p08_d0, net); - find_and_bind_downhill_pip(ctx, sb_big_p08_d0, sb_big_p08_y1, net); - find_and_bind_downhill_pip(ctx, sb_big_p08_y1, sb_big_p08_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p08_ydiag, sb_big_p07_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p07_ydiag, sb_big_p06_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p06_ydiag, sb_big_p05_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p05_ydiag, in_mux, net); - } - - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); - } - - void route_mult_x2y2_upper_in1(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN1 using x2y2\n", net->name.c_str(ctx)); - - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); - - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); - - ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); - find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); - - if (is_fourgroup_a) { - auto sb_sml_p04_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P04.D0"))); - auto sb_sml_p04_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P04.Y1_int"))); - auto sb_sml_p04_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P04.YDIAG_int"))); - auto sb_sml_p04_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P04.YDIAG"))); // AKA SB_SML.P03.X23 - auto sb_sml_p03_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P03.YDIAG_int"))); - auto sb_sml_p03_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P03.YDIAG"))); // AKA SB_SML.P02.X23 - auto sb_sml_p02_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P02.YDIAG_int"))); - auto sb_sml_p02_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P02.YDIAG"))); // AKA SB_SML.P01.X23 - auto sb_sml_p01_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.YDIAG_int"))); - auto sb_sml_p01_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.Y1_int"))); - - find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_p04_d0, net); - find_and_bind_downhill_pip(ctx, sb_sml_p04_d0, sb_sml_p04_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p04_y1_int, sb_sml_p04_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p04_ydiag_int, sb_sml_p04_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_sml_p04_ydiag, sb_sml_p03_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p03_ydiag_int, sb_sml_p03_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_sml_p03_ydiag, sb_sml_p02_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag_int, sb_sml_p02_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag, sb_sml_p01_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p01_ydiag_int, sb_sml_p01_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_p01_y1_int, in_mux, net); - } else { - auto sb_big_p04_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P04.D0"))); - auto sb_big_p04_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P04.Y1"))); - auto sb_big_p04_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P04.YDIAG"))); // AKA SB_BIG.P07.X23 - auto sb_big_p03_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P03.YDIAG"))); // AKA SB_BIG.P05.X23 - auto sb_big_p02_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P02.YDIAG"))); // AKA SB_BIG.P05.X23 - auto sb_big_p01_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.YDIAG"))); - // x2y1/IM.P05.D0 is x1y1/SB_BIG.P05.Y1 - - find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_p04_d0, net); - find_and_bind_downhill_pip(ctx, sb_big_p04_d0, sb_big_p04_y1, net); - find_and_bind_downhill_pip(ctx, sb_big_p04_y1, sb_big_p04_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p04_ydiag, sb_big_p03_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p03_ydiag, sb_big_p02_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p02_ydiag, sb_big_p01_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_p01_ydiag, in_mux, net); - } - - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); - } - - void route_mult_x2y2_upper_in8(Context *ctx, NetInfo *net, CellInfo* upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { - log_info(" routing net '%s' -> IN8 using x2y2\n", net->name.c_str(ctx)); - - auto x0y0 = ctx->idf("X%dY%d", loc.x - 1, loc.y - 1); - auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); - auto x2y0 = ctx->idf("X%dY%d", loc.x + 1, loc.y - 1); - auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); - - auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); - auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); - auto in_mux = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D1"))); - - if (bind_route_start) { - ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); - find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); - if (is_fourgroup_a) { - auto sb_big_d0 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_BIG.P08.D0"))); - find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_d0, net); - } else { - auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.D0"))); - find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_d0, net); - } - } - - if (is_fourgroup_a) { - auto sb_big_d0 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_BIG.P08.D0"))); - auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_BIG.P08.Y1"))); - auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.Y1_int"))); - auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.YDIAG_int"))); - auto sb_sml_y2_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.Y2_int"))); - - find_and_bind_downhill_pip(ctx, sb_big_d0, sb_big_y1, net); - find_and_bind_downhill_pip(ctx, sb_big_y1, sb_sml_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_ydiag_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_ydiag_int, sb_sml_y2_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_y2_int, in_mux, net); - } else { - auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.D0"))); - auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.Y1_int"))); - auto sb_sml_y1 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.Y1"))); - auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_BIG.P08.Y1"))); - auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_BIG.P08.YDIAG"))); - // x2y2/IM.P08.D0 is x2y0/SB_BIG.P08.Y2 - - find_and_bind_downhill_pip(ctx, sb_sml_d0, sb_sml_y1_int, net); - find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_y1, net); - find_and_bind_downhill_pip(ctx, sb_sml_y1, sb_big_y1, net); - find_and_bind_downhill_pip(ctx, sb_big_y1, sb_big_ydiag, net); - find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux, net); - } - - route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux, 8); + last_wire = cpe_in; } } +void route_mult_x1y1_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc, bool is_fourgroup_a) +{ + log_info(" routing net '%s' -> IN5 using x1y1\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); + + ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); + + if (is_fourgroup_a) { + auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0"))); + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big, net); + find_and_bind_downhill_pip(ctx, sb_big, in_mux, net); // inverting + } else { + auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.D0"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.Y1_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_d0, sb_sml_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1_int, in_mux, net); // inverting + } + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); +} + +void route_mult_x1y1_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a) +{ + log_info(" routing net '%s' -> IN1 using x1y1\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); + + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + + if (is_fourgroup_a) { + auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0"))); + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big, net); + find_and_bind_downhill_pip(ctx, sb_big, in_mux, net); // inverting + } else { + auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.D0"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.Y1_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_d0, sb_sml_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1_int, in_mux, net); // inverting + } + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); +} + +void route_mult_x1y1_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a, + bool bind_route_start = false) +{ + log_info(" routing net '%s' -> IN8 using x1y1\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); + auto x4y2 = ctx->idf("X%dY%d", loc.x + 3, loc.y + 1); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto out_mux_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.D0"))); + auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("OM.P12.Y"))); + auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D2"))); + + if (bind_route_start) { + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + find_and_bind_downhill_pip(ctx, cpe_out2_int, out_mux_d0, net); + } + + find_and_bind_downhill_pip(ctx, out_mux_d0, out_mux_y, net); // inverting + + if (is_fourgroup_a) { + auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.Y1_int"))); + auto sb_big_d2_1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.D2_1"))); + auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.Y1"))); + auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.YDIAG"))); + + find_and_bind_downhill_pip(ctx, out_mux_y, sb_sml, net); + find_and_bind_downhill_pip(ctx, sb_sml, sb_big_d2_1, net); // inverting + find_and_bind_downhill_pip(ctx, sb_big_d2_1, sb_big_y1, net); // inverting + find_and_bind_downhill_pip(ctx, sb_big_y1, sb_big_ydiag, net); // inverting + find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux_p12, net); // inverting + } else { + auto sb_big = + ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_BIG.P12.Y1"))); // aka x4y2/SB_SML.P12.D2_1 + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y1_int"))); + auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.YDIAG_int"))); + auto sb_sml_y3_int = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y3_int"))); + + find_and_bind_downhill_pip(ctx, out_mux_y, sb_big, net); // inverting + find_and_bind_downhill_pip(ctx, sb_big, sb_sml_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_ydiag_int, sb_sml_y3_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y3_int, in_mux_p12, net); // inverting + } + + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y + + find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8); +} + +void route_mult_x1y2_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc, bool is_fourgroup_a) +{ + log_info(" routing net '%s' -> IN5 using x1y2\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + auto x4y1 = ctx->idf("X%dY%d", loc.x + 3, loc.y); + + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D2"))); + + ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); + + if (is_fourgroup_a) { + auto sb_sml_p06_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P06.D0"))); + auto sb_sml_p06_y1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P06.Y1_int"))); + auto sb_sml_p06_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P06.YDIAG_int"))); + auto sb_sml_p06_ydiag = + ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P06.YDIAG"))); // AKA SB_SML.P05.X23 + auto sb_sml_p05_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P05.YDIAG_int"))); + auto sb_sml_p05_y1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P05.Y1_int"))); + auto sb_sml_p05_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P05.Y1"))); + auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P05.Y1"))); + auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P05.YDIAG"))); + // x2y1/IM.P05.D2 is x4y1/SB_BIG.P05.Y3 + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_p06_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_d0, sb_sml_p06_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_y1_int, sb_sml_p06_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag_int, sb_sml_p06_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag, sb_sml_p05_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_ydiag_int, sb_sml_p05_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, sb_sml_p05_y1, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_y1, sb_big_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_y1, sb_big_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux, net); + } else { + auto sb_big_p06_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P06.D0"))); + auto sb_big_p06_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P06.Y1"))); + auto sb_big_p06_ydiag = + ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P06.YDIAG"))); // AKA SB_BIG.P05.X23 + auto sb_big_p05_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P05.YDIAG"))); + auto sb_big_p05_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P05.Y1"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P05.Y1_int"))); + auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P05.YDIAG_int"))); + auto sb_sml_y3_int = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P05.Y3_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big_p06_d0, net); + find_and_bind_downhill_pip(ctx, sb_big_p06_d0, sb_big_p06_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p06_y1, sb_big_p06_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p06_ydiag, sb_big_p05_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p05_ydiag, sb_big_p05_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p05_y1, sb_sml_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_ydiag_int, sb_sml_y3_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y3_int, in_mux, net); + } + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); +} + +void route_mult_x1y2_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a) +{ + log_info(" routing net '%s' -> IN1 using x1y2\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + auto x4y1 = ctx->idf("X%dY%d", loc.x + 3, loc.y); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D2"))); + + if (is_fourgroup_a) { + auto sb_sml_p02_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P02.D0"))); + auto sb_sml_p02_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P02.Y1_int"))); + auto sb_sml_p02_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P02.YDIAG_int"))); + auto sb_sml_p02_ydiag = + ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P02.YDIAG"))); // AKA SB_SML.P01.X23 + auto sb_sml_p01_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P01.YDIAG_int"))); + auto sb_sml_p01_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P01.Y1_int"))); + auto sb_big_d2_1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P01.D2_1"))); + auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P01.Y1"))); + auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P01.YDIAG"))); + // x2y1/IM.P01.D2 is x4y1/SB_BIG.P01.Y3 + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_p02_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_d0, sb_sml_p02_y1, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_y1, sb_sml_p02_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag_int, sb_sml_p02_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag, sb_sml_p01_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p01_ydiag, sb_sml_p01_y1, net); + find_and_bind_downhill_pip(ctx, sb_sml_p01_y1, sb_big_d2_1, net); + find_and_bind_downhill_pip(ctx, sb_big_d2_1, sb_big_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_y1, sb_big_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux, net); + } else { + auto sb_big_p02_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P02.D0"))); + auto sb_big_p02_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P02.Y1"))); + auto sb_big_p02_ydiag = + ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P02.YDIAG"))); // AKA SB_BIG.P01.X23 + auto sb_big_p01_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P01.YDIAG"))); + auto sb_big_p01_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P01.Y1"))); + auto sb_sml_y1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P01.Y1_int"))); + auto sb_sml_ydiag = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P01.YDIAG_int"))); + auto sb_sml_y3 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P01.Y3_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_p02_d0, net); + find_and_bind_downhill_pip(ctx, sb_big_p02_d0, sb_big_p02_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p02_y1, sb_big_p02_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p02_ydiag, sb_big_p01_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p01_ydiag, sb_big_p01_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p01_y1, sb_sml_y1, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1, sb_sml_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_ydiag, sb_sml_y3, net); + find_and_bind_downhill_pip(ctx, sb_sml_y3, in_mux, net); + } + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); +} + +void route_mult_x1y2_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a, + bool bind_route_start = false) +{ + log_info(" routing net '%s' -> IN8 using x1y2\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto out_mux_d1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.D1"))); + auto out_mux_y = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("OM.P10.Y"))); + auto in_mux_p10 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P10.D1"))); + + if (bind_route_start) { + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + find_and_bind_downhill_pip(ctx, cpe_out2_int, out_mux_d1, net); + } + + find_and_bind_downhill_pip(ctx, out_mux_d1, out_mux_y, net); // inverting + + if (is_fourgroup_a) { + auto sb_sml = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P10.Y2_int"))); + + find_and_bind_downhill_pip(ctx, out_mux_y, sb_sml, net); + find_and_bind_downhill_pip(ctx, sb_sml, in_mux_p10, net); // inverting + } else { + // x2y1/OM.P10.Y is x2y1/SB_BIG.P10.D0 + // x2y2/IM.P10.D1 is x2y1/SB_BIG.P10.Y2 + + find_and_bind_downhill_pip(ctx, out_mux_y, in_mux_p10, net); // inverting + } + + auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D6"))); // aka IM.P10.Y + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y + + find_and_bind_downhill_pip(ctx, in_mux_p10, in_mux_p12, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8); +} + +void route_mult_x2y1_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc, bool is_fourgroup_a) +{ + log_info(" routing net '%s' -> IN5 using x2y1\n", net->name.c_str(ctx)); + + auto x0y1 = ctx->idf("X%dY%d", loc.x - 1, loc.y); + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); + + ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); + + if (is_fourgroup_a) { + auto sb_big_p07_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P07.D0"))); + auto sb_big_p07_y1 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P07.Y1"))); + auto sb_big_p07_ydiag = + ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P07.YDIAG"))); // AKA SB_BIG.P06.X23 + auto sb_big_p06_ydiag = + ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P06.YDIAG"))); // AKA SB_BIG.P05.X23 + auto sb_big_p05_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P05.YDIAG"))); + // x2y1/IM.P05.D0 is x0y1/SB_BIG.P05.Y1 + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big_p07_d0, net); + find_and_bind_downhill_pip(ctx, sb_big_p07_d0, sb_big_p07_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p07_y1, sb_big_p07_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p07_ydiag, sb_big_p06_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p06_ydiag, sb_big_p05_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p05_ydiag, in_mux, net); + } else { + auto sb_sml_p07_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.D0"))); + auto sb_sml_p07_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.Y1_int"))); + auto sb_sml_p07_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.YDIAG_int"))); + auto sb_sml_p07_ydiag = + ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.YDIAG"))); // AKA SB_SML.P06.X23 + auto sb_sml_p06_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P06.YDIAG_int"))); + auto sb_sml_p06_ydiag = + ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P06.YDIAG"))); // AKA SB_SML.P05.X23 + auto sb_sml_p05_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P05.YDIAG_int"))); + auto sb_sml_p05_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P05.Y1_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_p07_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_p07_d0, sb_sml_p07_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p07_y1_int, sb_sml_p07_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag_int, sb_sml_p07_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag, sb_sml_p06_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag_int, sb_sml_p06_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag, sb_sml_p05_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_ydiag_int, sb_sml_p05_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, in_mux, net); + } + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); +} + +void route_mult_x2y1_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a) +{ + log_info(" routing net '%s' -> IN1 using x2y1\n", net->name.c_str(ctx)); + + auto x0y1 = ctx->idf("X%dY%d", loc.x - 1, loc.y); + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); + + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + + if (is_fourgroup_a) { + auto sb_big_p03_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P03.D0"))); + auto sb_big_p03_y1 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P03.Y1"))); + auto sb_big_p03_ydiag = + ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P03.YDIAG"))); // AKA SB_BIG.P02.X23 + auto sb_big_p02_ydiag = + ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P02.YDIAG"))); // AKA SB_BIG.P01.X23 + auto sb_big_p01_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P01.YDIAG"))); + // x2y1/IM.P01.D0 is x0y1/SB_BIG.P01.Y1 + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_p03_d0, net); + find_and_bind_downhill_pip(ctx, sb_big_p03_d0, sb_big_p03_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p03_y1, sb_big_p03_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p03_ydiag, sb_big_p02_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p02_ydiag, sb_big_p01_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p01_ydiag, in_mux, net); + } else { + auto sb_sml_p03_d0 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.D0"))); + auto sb_sml_p03_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.Y1_int"))); + auto sb_sml_p03_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.YDIAG_int"))); + auto sb_sml_p03_ydiag = + ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.YDIAG"))); // AKA SB_SML.P02.X23 + auto sb_sml_p02_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P02.YDIAG_int"))); + auto sb_sml_p02_ydiag = + ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P02.YDIAG"))); // AKA SB_SML.P01.X23 + auto sb_sml_p01_ydiag_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P01.YDIAG_int"))); + auto sb_sml_p01_y1_int = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P01.Y1_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_p03_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_p03_d0, sb_sml_p03_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p03_y1_int, sb_sml_p03_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p03_ydiag_int, sb_sml_p03_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p03_ydiag, sb_sml_p02_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag_int, sb_sml_p02_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag, sb_sml_p01_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p01_ydiag_int, sb_sml_p01_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p01_y1_int, in_mux, net); + } + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); +} + +void route_mult_x2y1_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a, + bool bind_route_start = false) +{ + log_info(" routing net '%s' -> IN8 using x2y1\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x1y2 = ctx->idf("X%dY%d", loc.x, loc.y + 1); + auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto out_mux_d2 = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("OM.P09.D2"))); + auto out_mux_y = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("OM.P09.Y"))); + auto in_mux_p09 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P09.D0"))); + + if (bind_route_start) { + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + find_and_bind_downhill_pip(ctx, cpe_out2_int, out_mux_d2, net); + } + + find_and_bind_downhill_pip(ctx, out_mux_d2, out_mux_y, net); // inverting + + if (is_fourgroup_a) { + auto sb_sml = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("SB_SML.P09.Y1_int"))); + + find_and_bind_downhill_pip(ctx, out_mux_y, sb_sml, net); + find_and_bind_downhill_pip(ctx, sb_sml, in_mux_p09, net); // inverting + } else { + // x1y2/OM.P09.Y is x1y2/SB_BIG.P09.D0 + // x2y2/IM.P09.D0 is x2y1/SB_BIG.P09.Y1 + + find_and_bind_downhill_pip(ctx, out_mux_y, in_mux_p09, net); // inverting + } + + auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D7"))); // aka IM.P09.Y + auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7"))); // aka IM.P12.Y + auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6"))); // aka IM.P04.Y + + find_and_bind_downhill_pip(ctx, in_mux_p09, in_mux_p12, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p04, net); // inverting + find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p08, net); // inverting + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8); +} + +void route_mult_x2y2_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc, bool is_fourgroup_a) +{ + log_info(" routing net '%s' -> IN5 using x2y2\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + + auto cpe_combout1 = ctx->getBelPinWire(lower->bel, id_OUT); + auto cpe_out1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P05.D0"))); + + ctx->bindWire(cpe_combout1, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout1, cpe_out1_int, net); + + if (is_fourgroup_a) { + auto sb_sml_p08_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P08.D0"))); + auto sb_sml_p08_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P08.Y1_int"))); + auto sb_sml_p08_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P08.YDIAG_int"))); + auto sb_sml_p08_ydiag = + ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P08.YDIAG"))); // AKA SB_SML.P07.X23 + auto sb_sml_p07_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P07.YDIAG_int"))); + auto sb_sml_p07_ydiag = + ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P07.YDIAG"))); // AKA SB_SML.P06.X23 + auto sb_sml_p06_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P06.YDIAG_int"))); + auto sb_sml_p06_ydiag = + ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P06.YDIAG"))); // AKA SB_SML.P05.X23 + auto sb_sml_p05_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.YDIAG_int"))); + auto sb_sml_p05_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.Y1_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_p08_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_p08_d0, sb_sml_p08_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p08_y1_int, sb_sml_p08_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p08_ydiag_int, sb_sml_p08_ydiag, net); // inverting + find_and_bind_downhill_pip(ctx, sb_sml_p08_ydiag, sb_sml_p07_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag_int, sb_sml_p07_ydiag, net); // inverting + find_and_bind_downhill_pip(ctx, sb_sml_p07_ydiag, sb_sml_p06_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag_int, sb_sml_p06_ydiag, net); // inverting + find_and_bind_downhill_pip(ctx, sb_sml_p06_ydiag, sb_sml_p05_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_ydiag_int, sb_sml_p05_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p05_y1_int, in_mux, net); // inverting + } else { + auto sb_big_p08_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P08.D0"))); + auto sb_big_p08_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P08.Y1"))); + auto sb_big_p08_ydiag = + ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P08.YDIAG"))); // AKA SB_BIG.P07.X23 + auto sb_big_p07_ydiag = + ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P07.YDIAG"))); // AKA SB_BIG.P06.X23 + auto sb_big_p06_ydiag = + ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P06.YDIAG"))); // AKA SB_BIG.P05.X23 + auto sb_big_p05_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.YDIAG"))); + // x2y1/IM.P05.D0 is x1y1/SB_BIG.P05.Y1 + + find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big_p08_d0, net); + find_and_bind_downhill_pip(ctx, sb_big_p08_d0, sb_big_p08_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p08_y1, sb_big_p08_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p08_ydiag, sb_big_p07_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p07_ydiag, sb_big_p06_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p06_ydiag, sb_big_p05_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p05_ydiag, in_mux, net); + } + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5); +} + +void route_mult_x2y2_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a) +{ + log_info(" routing net '%s' -> IN1 using x2y2\n", net->name.c_str(ctx)); + + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D0"))); + + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + + if (is_fourgroup_a) { + auto sb_sml_p04_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P04.D0"))); + auto sb_sml_p04_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P04.Y1_int"))); + auto sb_sml_p04_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P04.YDIAG_int"))); + auto sb_sml_p04_ydiag = + ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P04.YDIAG"))); // AKA SB_SML.P03.X23 + auto sb_sml_p03_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P03.YDIAG_int"))); + auto sb_sml_p03_ydiag = + ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P03.YDIAG"))); // AKA SB_SML.P02.X23 + auto sb_sml_p02_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P02.YDIAG_int"))); + auto sb_sml_p02_ydiag = + ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P02.YDIAG"))); // AKA SB_SML.P01.X23 + auto sb_sml_p01_ydiag_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.YDIAG_int"))); + auto sb_sml_p01_y1_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.Y1_int"))); + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_p04_d0, net); + find_and_bind_downhill_pip(ctx, sb_sml_p04_d0, sb_sml_p04_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p04_y1_int, sb_sml_p04_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p04_ydiag_int, sb_sml_p04_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p04_ydiag, sb_sml_p03_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p03_ydiag_int, sb_sml_p03_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p03_ydiag, sb_sml_p02_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag_int, sb_sml_p02_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_sml_p02_ydiag, sb_sml_p01_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p01_ydiag_int, sb_sml_p01_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_p01_y1_int, in_mux, net); + } else { + auto sb_big_p04_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P04.D0"))); + auto sb_big_p04_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P04.Y1"))); + auto sb_big_p04_ydiag = + ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P04.YDIAG"))); // AKA SB_BIG.P07.X23 + auto sb_big_p03_ydiag = + ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P03.YDIAG"))); // AKA SB_BIG.P05.X23 + auto sb_big_p02_ydiag = + ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P02.YDIAG"))); // AKA SB_BIG.P05.X23 + auto sb_big_p01_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.YDIAG"))); + // x2y1/IM.P05.D0 is x1y1/SB_BIG.P05.Y1 + + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_p04_d0, net); + find_and_bind_downhill_pip(ctx, sb_big_p04_d0, sb_big_p04_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_p04_y1, sb_big_p04_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p04_ydiag, sb_big_p03_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p03_ydiag, sb_big_p02_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p02_ydiag, sb_big_p01_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_p01_ydiag, in_mux, net); + } + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1); +} + +void route_mult_x2y2_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a, + bool bind_route_start = false) +{ + log_info(" routing net '%s' -> IN8 using x2y2\n", net->name.c_str(ctx)); + + auto x0y0 = ctx->idf("X%dY%d", loc.x - 1, loc.y - 1); + auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); + auto x2y0 = ctx->idf("X%dY%d", loc.x + 1, loc.y - 1); + auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); + + auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT); + auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int"))); + auto in_mux = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D1"))); + + if (bind_route_start) { + ctx->bindWire(cpe_combout2, net, STRENGTH_LOCKED); + find_and_bind_downhill_pip(ctx, cpe_combout2, cpe_out2_int, net); + if (is_fourgroup_a) { + auto sb_big_d0 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_BIG.P08.D0"))); + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_d0, net); + } else { + auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.D0"))); + find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_d0, net); + } + } + + if (is_fourgroup_a) { + auto sb_big_d0 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_BIG.P08.D0"))); + auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_BIG.P08.Y1"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.Y1_int"))); + auto sb_sml_ydiag_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.YDIAG_int"))); + auto sb_sml_y2_int = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.Y2_int"))); + + find_and_bind_downhill_pip(ctx, sb_big_d0, sb_big_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_y1, sb_sml_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_ydiag_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_ydiag_int, sb_sml_y2_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y2_int, in_mux, net); + } else { + auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.D0"))); + auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.Y1_int"))); + auto sb_sml_y1 = ctx->getWireByName(IdStringList::concat(x0y0, ctx->idf("SB_SML.P08.Y1"))); + auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_BIG.P08.Y1"))); + auto sb_big_ydiag = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_BIG.P08.YDIAG"))); + // x2y2/IM.P08.D0 is x2y0/SB_BIG.P08.Y2 + + find_and_bind_downhill_pip(ctx, sb_sml_d0, sb_sml_y1_int, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_y1, net); + find_and_bind_downhill_pip(ctx, sb_sml_y1, sb_big_y1, net); + find_and_bind_downhill_pip(ctx, sb_big_y1, sb_big_ydiag, net); + find_and_bind_downhill_pip(ctx, sb_big_ydiag, in_mux, net); + } + + route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux, 8); +} +} // namespace + NEXTPNR_NAMESPACE_BEGIN -void GateMateImpl::route_mult() { +void GateMateImpl::route_mult() +{ log_info("Routing multipliers...\n"); // I am fully aware the nextpnr API is absolutely not designed around naming specific pips. @@ -690,7 +736,8 @@ void GateMateImpl::route_mult() { log_info(" lower.OUT [OUT1] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(lower->bel, id_OUT))); for (auto sink_port : lower->ports.at(id_OUT).net->users) { auto sink_loc = ctx->getBelLocation(sink_port.cell->bel); - log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), sink_loc.x, sink_loc.y); + log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), + sink_loc.x, sink_loc.y); } log_info(" upper.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(upper->bel, id_OUT))); @@ -698,7 +745,8 @@ void GateMateImpl::route_mult() { if (sink_port.port == id_IN8) needs_in8_route = true; auto sink_loc = ctx->getBelLocation(sink_port.cell->bel); - log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), sink_loc.x, sink_loc.y); + log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), + sink_loc.x, sink_loc.y); } if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { @@ -740,7 +788,8 @@ void GateMateImpl::route_mult() { log_info(" zero_driver.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(zero_driver->bel, id_OUT))); for (auto sink_port : zero_driver->ports.at(id_OUT).net->users) { auto sink_loc = ctx->getBelLocation(sink_port.cell->bel); - log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), sink_loc.x, sink_loc.y); + log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), + sink_loc.x, sink_loc.y); } if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { From 1748f38aad0d66939f5d858409b182736ef05a97 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 1 Aug 2025 17:46:43 +0200 Subject: [PATCH 25/34] Add MULT_INVERT property --- himbaechel/uarch/gatemate/bitstream.cc | 1 + himbaechel/uarch/gatemate/constids.inc | 1 + himbaechel/uarch/gatemate/pack_mult.cc | 1 + 3 files changed, 3 insertions(+) diff --git a/himbaechel/uarch/gatemate/bitstream.cc b/himbaechel/uarch/gatemate/bitstream.cc index 23f49805..30859430 100644 --- a/himbaechel/uarch/gatemate/bitstream.cc +++ b/himbaechel/uarch/gatemate/bitstream.cc @@ -347,6 +347,7 @@ struct BitstreamBackend dict params = cell.second->params; Loc l = ctx->getBelLocation(cell.second->bel); params.erase(id_L2T4_UPPER); + params.erase(id_MULT_INVERT); int c_i1 = int_or_default(params, id_C_I1, 0); int c_i2 = int_or_default(params, id_C_I2, 0); int c_i3 = int_or_default(params, id_C_I3, 0); diff --git a/himbaechel/uarch/gatemate/constids.inc b/himbaechel/uarch/gatemate/constids.inc index d68a5196..11140382 100644 --- a/himbaechel/uarch/gatemate/constids.inc +++ b/himbaechel/uarch/gatemate/constids.inc @@ -2272,3 +2272,4 @@ X(CPE_LATCH) X(L2T4_UPPER) X(CPE_MX8) X(CPE_BRIDGE) +X(MULT_INVERT) diff --git a/himbaechel/uarch/gatemate/pack_mult.cc b/himbaechel/uarch/gatemate/pack_mult.cc index 7bae5514..b8dc36e6 100644 --- a/himbaechel/uarch/gatemate/pack_mult.cc +++ b/himbaechel/uarch/gatemate/pack_mult.cc @@ -516,6 +516,7 @@ void GateMatePacker::pack_mult() for (int i = 0; i < (a_width / 2); i++) { auto *mult_lower = create_cell_ptr(id_CPE_LT_L, ctx->idf("%s$row%d$mult_lower", name.c_str(ctx), i)); auto *mult_upper = create_cell_ptr(id_CPE_LT_U, ctx->idf("%s$row%d$mult_upper", name.c_str(ctx), i)); + mult_lower->params[id_MULT_INVERT] = Property(is_even_x ? Property::State::S0 : Property::State::S1); col.mults.push_back(MultCell{mult_lower, mult_upper, name, i == ((a_width / 2) - 1)}); uarch->multipliers.push_back(mult_lower); From 6a3c4a2dca1a07f89d4ba866b15a535414a557d2 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 1 Aug 2025 17:47:07 +0200 Subject: [PATCH 26/34] Enable pack_mult --- himbaechel/uarch/gatemate/pack.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/himbaechel/uarch/gatemate/pack.cc b/himbaechel/uarch/gatemate/pack.cc index 393f56c7..f2caef1d 100644 --- a/himbaechel/uarch/gatemate/pack.cc +++ b/himbaechel/uarch/gatemate/pack.cc @@ -397,7 +397,7 @@ void GateMateImpl::pack() packer.pack_misc(); packer.pack_ram(); packer.pack_serdes(); - // packer.pack_mult(); + packer.pack_mult(); packer.pack_addf(); packer.pack_cpe(); packer.remove_constants(); From 0810a9a24391dbed799d53996a4642aa2b3f8394 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 2 Aug 2025 13:04:13 +0200 Subject: [PATCH 27/34] More multiplier fixes --- himbaechel/uarch/gatemate/pack_mult.cc | 37 +++++++++++++++----------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/himbaechel/uarch/gatemate/pack_mult.cc b/himbaechel/uarch/gatemate/pack_mult.cc index b8dc36e6..9aff205f 100644 --- a/himbaechel/uarch/gatemate/pack_mult.cc +++ b/himbaechel/uarch/gatemate/pack_mult.cc @@ -240,8 +240,8 @@ CarryGenCell::CarryGenCell(CellInfo *lower, CellInfo *upper, CellInfo *comp, Cel { lower->params[id_INIT_L00] = Property(LUT_D1, 4); // PINY1 lower->params[id_INIT_L01] = Property(LUT_ZERO, 4); // (overriden by CIN) - lower->params[id_INIT_L10] = Property(is_odd_x ? LUT_OR : LUT_ZERO, 4); - lower->params[id_INIT_L20] = Property(is_odd_x ? LUT_OR : LUT_ZERO, 4); + lower->params[id_INIT_L10] = Property(is_odd_x ? LUT_OR : !enable_cinx ? LUT_ZERO : LUT_AND, 4); + lower->params[id_INIT_L20] = Property(is_odd_x ? LUT_OR : !enable_cinx ? LUT_ZERO : LUT_AND, 4); lower->params[id_C_FUNCTION] = Property(C_EN_CIN, 3); lower->params[id_C_I3] = Property(1, 1); // PINY1 for L02 lower->params[id_C_HORIZ] = Property(0, 1); // CINY1 for CIN_ for L03 @@ -420,8 +420,7 @@ void GateMatePacker::pack_mult() return APassThroughCell{a_passthru_lower, a_passthru_upper, a_passthru_comp, a_passthru_lines, name}; }; - auto create_mult_col = [&](IdString name, int a_width, bool is_even_x, bool carry_enable_cinx, - bool multfab_enable_cinx) { + auto create_mult_col = [&](IdString name, int a_width, bool is_even_x, bool enable_cinx) { // Ideally this would be the MultiplierColumn constructor, but we need create_cell_ptr here. auto col = MultiplierColumn{}; @@ -448,6 +447,12 @@ void GateMatePacker::pack_mult() auto *carry_comp = create_cell_ptr(id_CPE_COMP, ctx->idf("%s$carry_comp", name.c_str(ctx))); auto *carry_lines = create_cell_ptr(id_CPE_CPLINES, ctx->idf("%s$carry_lines", name.c_str(ctx))); + NetInfo *comb2_conn = ctx->createNet(ctx->idf("%s$carrycomb2", name.c_str(ctx))); + carry_upper->connectPort(id_OUT, comb2_conn); + carry_lower->ports[id_COMBIN].name = id_COMBIN; + carry_lower->ports[id_COMBIN].type = PORT_IN; + carry_lower->connectPort(id_COMBIN, comb2_conn); + NetInfo *comp_in = ctx->createNet(ctx->idf("%s$carry$comp_in", name.c_str(ctx))); carry_lower->connectPort(id_OUT, comp_in); carry_comp->connectPort(id_COMB1, comp_in); @@ -456,8 +461,7 @@ void GateMatePacker::pack_mult() carry_comp->connectPort(id_COMPOUT, comp_out); carry_lines->connectPort(id_COMPOUT, comp_out); - col.carry = CarryGenCell{carry_lower, carry_upper, carry_comp, carry_lines, - name, !is_even_x, carry_enable_cinx}; + col.carry = CarryGenCell{carry_lower, carry_upper, carry_comp, carry_lines, name, !is_even_x, enable_cinx}; } { @@ -485,8 +489,8 @@ void GateMatePacker::pack_mult() multfab_comp->connectPort(id_COMPOUT, comp_out); multfab_lines->connectPort(id_COMPOUT, comp_out); - col.multfab = MultfabCell{multfab_lower, multfab_upper, multfab_comp, multfab_lines, - name, is_even_x, multfab_enable_cinx}; + col.multfab = MultfabCell{multfab_lower, multfab_upper, multfab_comp, multfab_lines, + name, is_even_x, enable_cinx}; } { @@ -556,19 +560,20 @@ void GateMatePacker::pack_mult() auto a_width = int_or_default(mult->params, id_A_WIDTH); auto b_width = int_or_default(mult->params, id_B_WIDTH); auto p_width = int_or_default(mult->params, id_P_WIDTH); - if (mult->getPort(id_A)) - mult->renamePort(id_A, ctx->id("A[0]")); - if (mult->getPort(id_B)) - mult->renamePort(id_B, ctx->id("B[0]")); + mult->renamePort(id_A, ctx->id("A[0]")); + mult->renamePort(id_B, ctx->id("B[0]")); + mult->renamePort(id_P, ctx->id("P[0]")); + int a_size = (((a_width + 1) / 2) + 1) * 2; + int b_size = (((b_width + 1) / 2) + 1) * 2; // Sign-extend odd A_WIDTH to even, because we're working with 2x2 multiplier cells. - while (a_width < p_width || a_width % 2 == 1) { + while (a_width < a_size) { mult->copyPortTo(ctx->idf("A[%d]", a_width - 1), mult, ctx->idf("A[%d]", a_width)); a_width += 1; } // Sign-extend odd B_WIDTH to even, because we're working with 2x2 multiplier cells. - while (b_width < p_width || b_width % 2 == 1) { + while (b_width < b_size) { mult->copyPortTo(ctx->idf("B[%d]", b_width - 1), mult, ctx->idf("B[%d]", b_width)); b_width += 1; } @@ -583,8 +588,8 @@ void GateMatePacker::pack_mult() for (int a = 0; a < a_width / 2; a++) m.a_passthrus.push_back(create_a_passthru(ctx->idf("%s$col0$row%d", mult->name.c_str(ctx), a))); for (int b = 0; b < b_width / 2; b++) - m.cols.push_back(create_mult_col(ctx->idf("%s$col%d", mult->name.c_str(ctx), b + 1), a_width, b % 2 == 0, - b == 2 /* ??? */, b > 0 /* ??? */)); + m.cols.push_back( + create_mult_col(ctx->idf("%s$col%d", mult->name.c_str(ctx), b + 1), a_width, b % 2 == 0, b > 0)); // Step 2: constrain them together. // We define (0, 0) to be the B passthrough cell of column 1. From fe7546fda5733c9787b7bd3201668577c24470cb Mon Sep 17 00:00:00 2001 From: Lofty Date: Sat, 2 Aug 2025 14:00:25 +0100 Subject: [PATCH 28/34] Multiplier routing needs priority over clocks --- himbaechel/uarch/gatemate/gatemate.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index eb4b3d7d..ce278e67 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -187,8 +187,8 @@ void GateMateImpl::postPlace() { repack(); } void GateMateImpl::preRoute() { ctx->assignArchInfo(); - route_clock(); route_mult(); + route_clock(); } void GateMateImpl::postRoute() From 60f3c25cb05ab9c179294ae2acae6bd00e13a94a Mon Sep 17 00:00:00 2001 From: Lofty Date: Sat, 2 Aug 2025 15:23:56 +0100 Subject: [PATCH 29/34] refactor inversion checker --- himbaechel/uarch/gatemate/bitstream.cc | 111 +++++++++--------------- himbaechel/uarch/gatemate/gatemate.h | 7 +- himbaechel/uarch/gatemate/pack_mult.cc | 9 +- himbaechel/uarch/gatemate/route_mult.cc | 53 +++++++---- 4 files changed, 85 insertions(+), 95 deletions(-) diff --git a/himbaechel/uarch/gatemate/bitstream.cc b/himbaechel/uarch/gatemate/bitstream.cc index 30859430..492cb183 100644 --- a/himbaechel/uarch/gatemate/bitstream.cc +++ b/himbaechel/uarch/gatemate/bitstream.cc @@ -220,96 +220,61 @@ struct BitstreamBackend } } - void check_multipliers() + void update_multiplier_input(IdString cell_name, dict ¶ms) { - for (auto *mult : uarch->multipliers) { - NPNR_ASSERT(mult != nullptr); + auto *net = ctx->cells.at(cell_name)->ports.at(id_OUT).net; - auto should_be_inverted = mult->constr_x % 2 == 1; + int64_t driver_l10 = ctx->cells.at(cell_name)->params[id_INIT_L10].as_int64(); + bool driver_is_inverted = driver_l10 == LUT_ONE || driver_l10 == LUT_INV_D0; - // TODO: these are errors, but downgraded to allow providing *some* output. + bool all_correct = true; + bool all_inverted = true; - // IN8 - if (need_inversion(mult, id_IN8) != should_be_inverted) - log_warning("%s.IN8 has wrong inversion state\n", mult->name.c_str(ctx)); - - // IN5 - if (need_inversion(mult, id_IN5) != should_be_inverted) - log_warning("%s.IN5 has wrong inversion state\n", mult->name.c_str(ctx)); - - // IN1 - if (need_inversion(mult, id_IN1) != should_be_inverted) - log_warning("%s.IN1 has wrong inversion state\n", mult->name.c_str(ctx)); - } - log_info("===\n"); - - pool multiplier_nets; - - for (auto *mult : uarch->multipliers) { - NPNR_ASSERT(mult != nullptr); - - multiplier_nets.insert(mult->ports.at(id_IN8).net->name); - multiplier_nets.insert(mult->ports.at(id_IN5).net->name); - multiplier_nets.insert(mult->ports.at(id_IN1).net->name); + for (PortRef user : net->users) { + auto column_parity = user.cell->constr_x % 2; + auto should_be_inverted = driver_is_inverted ? column_parity == 0 : column_parity == 1; + auto inversion = need_inversion(user.cell, user.port); + all_correct &= (inversion == should_be_inverted); + all_inverted &= (inversion != should_be_inverted); } - for (auto net_name : multiplier_nets) { - auto *net = ctx->nets.at(net_name).get(); + NPNR_ASSERT(!(all_correct && all_inverted) && "net doesn't drive any ports?"); - int64_t driver_l10 = net->driver.cell->params[id_INIT_L10].as_int64(); - bool driver_is_inverted = driver_l10 == LUT_ONE || driver_l10 == LUT_INV_D0; + if (!all_correct && !all_inverted) { + log_warning("multiplier net '%s' has inconsistent inversion\n", net->name.c_str(ctx)); - bool all_correct = true; - bool all_inverted = true; + auto driver_loc = ctx->getBelLocation(net->driver.cell->bel); + log_warning("net is driven from (%d, %d)\n", driver_loc.x, driver_loc.y); + log_warning(" these ports are not inverted:\n"); for (PortRef user : net->users) { - auto column_parity = user.cell->constr_x % 2; - auto should_be_inverted = driver_is_inverted ? column_parity == 0 : column_parity == 1; + auto loc = ctx->getBelLocation(user.cell->bel); + + auto should_be_inverted = user.cell->constr_x % 2 == 1; auto inversion = need_inversion(user.cell, user.port); - all_correct &= (inversion == should_be_inverted); - all_inverted &= (inversion != should_be_inverted); + if (inversion == should_be_inverted) + log_warning(" %s.%s at (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), loc.x, + loc.y); } - NPNR_ASSERT(!(all_correct && all_inverted) && "net doesn't drive any ports?"); + log_warning(" these ports are inverted:\n"); + for (PortRef user : net->users) { + auto loc = ctx->getBelLocation(user.cell->bel); - if (!all_correct && !all_inverted) { - log_warning("multiplier net '%s' has inconsistent inversion\n", net_name.c_str(ctx)); - - auto driver_loc = ctx->getBelLocation(net->driver.cell->bel); - log_warning("net is driven from (%d, %d)\n", driver_loc.x, driver_loc.y); - - log_warning(" these ports are not inverted:\n"); - for (PortRef user : net->users) { - auto loc = ctx->getBelLocation(user.cell->bel); - - auto should_be_inverted = user.cell->constr_x % 2 == 1; - auto inversion = need_inversion(user.cell, user.port); - if (inversion == should_be_inverted) - log_warning(" %s.%s at (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), loc.x, - loc.y); - } - - log_warning(" these ports are inverted:\n"); - for (PortRef user : net->users) { - auto loc = ctx->getBelLocation(user.cell->bel); - - auto should_be_inverted = user.cell->constr_x % 2 == 1; - auto inversion = need_inversion(user.cell, user.port); - if (inversion != should_be_inverted) - log_warning(" %s.%s at (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), loc.x, - loc.y); - } - } else if (all_inverted) { - net->driver.cell->params[id_INIT_L10] = Property(~driver_l10 & 0b1111, 4); - log_info("multiplier net '%s': fixed inversion\n", net_name.c_str(ctx)); + auto should_be_inverted = user.cell->constr_x % 2 == 1; + auto inversion = need_inversion(user.cell, user.port); + if (inversion != should_be_inverted) + log_warning(" %s.%s at (%d, %d)\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), loc.x, + loc.y); } + } else if (all_inverted) { + params[id_INIT_L10] = Property(~driver_l10 & 0b1111, 4); + log_info("multiplier net '%s': fixed inversion\n", net->name.c_str(ctx)); } } void write_bitstream() { - check_multipliers(); - ChipConfig cc; cc.chip_name = device; std::vector> bank(uarch->dies); @@ -399,6 +364,12 @@ struct BitstreamBackend else update_cpe_inv(cell.second.get(), id_SR, id_C_CPE_RES, params); } + + if (uarch->multiplier_a_passthru_lowers.count(cell.first) || + uarch->multiplier_a_passthru_uppers.count(cell.first) || + uarch->multiplier_zero_drivers.count(cell.first)) + update_multiplier_input(cell.first, params); + int id = tile_extra_data(cell.second.get()->bel.tile)->prim_id; for (auto &p : params) { IdString name = p.first; diff --git a/himbaechel/uarch/gatemate/gatemate.h b/himbaechel/uarch/gatemate/gatemate.h index a303e6dc..3d468b57 100644 --- a/himbaechel/uarch/gatemate/gatemate.h +++ b/himbaechel/uarch/gatemate/gatemate.h @@ -22,6 +22,7 @@ #include "extra_data.h" #include "himbaechel_api.h" +#include "idstring.h" #include "log.h" #include "nextpnr.h" #include "util.h" @@ -72,9 +73,9 @@ struct GateMateImpl : HimbaechelAPI dict, Loc> locations; int dies; int preferred_die; - std::vector multipliers; - std::vector> multiplier_a_passthrus; - std::vector multiplier_zero_drivers; + pool multiplier_a_passthru_lowers; + pool multiplier_a_passthru_uppers; + pool multiplier_zero_drivers; private: bool getChildPlacement(const BaseClusterInfo *cluster, Loc root_loc, diff --git a/himbaechel/uarch/gatemate/pack_mult.cc b/himbaechel/uarch/gatemate/pack_mult.cc index 9aff205f..9fe0683c 100644 --- a/himbaechel/uarch/gatemate/pack_mult.cc +++ b/himbaechel/uarch/gatemate/pack_mult.cc @@ -400,7 +400,7 @@ void GateMatePacker::pack_mult() auto *zero_lower = create_cell_ptr(id_CPE_DUMMY, ctx->idf("%s$zero_lower", name.c_str(ctx))); auto *zero_upper = create_cell_ptr(id_CPE_L2T4, ctx->idf("%s$zero", name.c_str(ctx))); - uarch->multiplier_zero_drivers.push_back(zero_upper); + uarch->multiplier_zero_drivers.insert(zero_upper->name); return ZeroDriver{zero_lower, zero_upper, name}; }; @@ -415,7 +415,8 @@ void GateMatePacker::pack_mult() a_passthru_comp->connectPort(id_COMPOUT, comp_conn); a_passthru_lines->connectPort(id_COMPOUT, comp_conn); - uarch->multiplier_a_passthrus.push_back({a_passthru_lower, a_passthru_upper}); + uarch->multiplier_a_passthru_lowers.insert(a_passthru_lower->name); + uarch->multiplier_a_passthru_uppers.insert(a_passthru_upper->name); return APassThroughCell{a_passthru_lower, a_passthru_upper, a_passthru_comp, a_passthru_lines, name}; }; @@ -506,9 +507,8 @@ void GateMatePacker::pack_mult() NetInfo *comb2_conn = ctx->createNet(ctx->idf("%s$f_route$comb2", name.c_str(ctx))); f_route_upper->connectPort(id_OUT, comb2_conn); f_route_lines->connectPort(id_OUT2, comb2_conn); - if (!is_even_x) { + if (!is_even_x) f_route_comp->connectPort(id_COMB2, comb2_conn); - } NetInfo *comp_out = ctx->createNet(ctx->idf("%s$f_route$comp_out", name.c_str(ctx))); f_route_comp->connectPort(id_COMPOUT, comp_out); @@ -523,7 +523,6 @@ void GateMatePacker::pack_mult() mult_lower->params[id_MULT_INVERT] = Property(is_even_x ? Property::State::S0 : Property::State::S1); col.mults.push_back(MultCell{mult_lower, mult_upper, name, i == ((a_width / 2) - 1)}); - uarch->multipliers.push_back(mult_lower); } { diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index 6e2b2408..c27c989c 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -714,12 +714,9 @@ void GateMateImpl::route_mult() // I am fully aware the nextpnr API is absolutely not designed around naming specific pips. // Unfortunately, this is the easiest way to describe the specific routing required. // Myrtle, please forgive me. - for (auto &a_passthru : this->multiplier_a_passthrus) { - auto *lower = a_passthru.first; - auto *upper = a_passthru.second; - + for (auto a_passthru_lower : this->multiplier_a_passthru_lowers) { + auto *lower = ctx->cells.at(a_passthru_lower).get(); auto *lower_out = lower->ports.at(id_OUT).net; - auto *upper_out = upper->ports.at(id_OUT).net; auto loc = ctx->getBelLocation(lower->bel); @@ -729,17 +726,42 @@ void GateMateImpl::route_mult() auto x_within_fourgroup = (loc.x - 3) % 2; auto y_within_fourgroup = (loc.y - 3) % 2; + log_info(" A passthrough at (%d, %d) has 4-group %c\n", loc.x, loc.y, is_fourgroup_a ? 'A' : 'B'); + + log_info(" lower.OUT [OUT1] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(lower->bel, id_OUT))); + for (auto sink_port : lower->ports.at(id_OUT).net->users) { + auto sink_loc = ctx->getBelLocation(sink_port.cell->bel); + log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), + sink_loc.x, sink_loc.y); + } + + if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { + route_mult_x1y1_lower(ctx, lower_out, lower, loc, is_fourgroup_a); + } else if (x_within_fourgroup == 0 && y_within_fourgroup == 1) { + route_mult_x1y2_lower(ctx, lower_out, lower, loc, is_fourgroup_a); + } else if (x_within_fourgroup == 1 && y_within_fourgroup == 0) { + route_mult_x2y1_lower(ctx, lower_out, lower, loc, is_fourgroup_a); + } else /* if (x_within_fourgroup == 1 && y_within_fourgroup == 1) */ { + route_mult_x2y2_lower(ctx, lower_out, lower, loc, is_fourgroup_a); + } + } + + for (auto a_passthru_upper : this->multiplier_a_passthru_uppers) { + auto *upper = ctx->cells.at(a_passthru_upper).get(); + auto *upper_out = upper->ports.at(id_OUT).net; + + auto loc = ctx->getBelLocation(upper->bel); + + auto x_fourgroup = (loc.x - 3) % 4; + auto y_fourgroup = (loc.y - 3) % 4; + bool is_fourgroup_a = (x_fourgroup < 2 && y_fourgroup < 2) || (x_fourgroup >= 2 && y_fourgroup >= 2); + auto x_within_fourgroup = (loc.x - 3) % 2; + auto y_within_fourgroup = (loc.y - 3) % 2; + bool needs_in8_route = false; log_info(" A passthrough at (%d, %d) has 4-group %c\n", loc.x, loc.y, is_fourgroup_a ? 'A' : 'B'); - log_info(" lower.OUT [OUT1] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(lower->bel, id_OUT))); - for (auto sink_port : lower->ports.at(id_OUT).net->users) { - auto sink_loc = ctx->getBelLocation(sink_port.cell->bel); - log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), - sink_loc.x, sink_loc.y); - } - log_info(" upper.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(upper->bel, id_OUT))); for (auto sink_port : upper->ports.at(id_OUT).net->users) { if (sink_port.port == id_IN8) @@ -750,29 +772,26 @@ void GateMateImpl::route_mult() } if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { - route_mult_x1y1_lower(ctx, lower_out, lower, loc, is_fourgroup_a); route_mult_x1y1_upper_in1(ctx, upper_out, upper, loc, is_fourgroup_a); if (needs_in8_route) route_mult_x1y1_upper_in8(ctx, upper_out, upper, loc, is_fourgroup_a); } else if (x_within_fourgroup == 0 && y_within_fourgroup == 1) { - route_mult_x1y2_lower(ctx, lower_out, lower, loc, is_fourgroup_a); route_mult_x1y2_upper_in1(ctx, upper_out, upper, loc, is_fourgroup_a); if (needs_in8_route) route_mult_x1y2_upper_in8(ctx, upper_out, upper, loc, is_fourgroup_a); } else if (x_within_fourgroup == 1 && y_within_fourgroup == 0) { - route_mult_x2y1_lower(ctx, lower_out, lower, loc, is_fourgroup_a); route_mult_x2y1_upper_in1(ctx, upper_out, upper, loc, is_fourgroup_a); if (needs_in8_route) route_mult_x2y1_upper_in8(ctx, upper_out, upper, loc, is_fourgroup_a); } else /* if (x_within_fourgroup == 1 && y_within_fourgroup == 1) */ { - route_mult_x2y2_lower(ctx, lower_out, lower, loc, is_fourgroup_a); route_mult_x2y2_upper_in1(ctx, upper_out, upper, loc, is_fourgroup_a); if (needs_in8_route) route_mult_x2y2_upper_in8(ctx, upper_out, upper, loc, is_fourgroup_a); } } - for (auto *zero_driver : this->multiplier_zero_drivers) { + for (auto zero_driver_name : this->multiplier_zero_drivers) { + auto *zero_driver = ctx->cells.at(zero_driver_name).get(); auto *out = zero_driver->ports.at(id_OUT).net; auto loc = ctx->getBelLocation(zero_driver->bel); From 88f52bcaba40fcb4c87fb63de054208b8630daaf Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 4 Aug 2025 13:26:26 +0200 Subject: [PATCH 30/34] Fix multipliers on hardware --- himbaechel/uarch/gatemate/bitstream.cc | 2 +- himbaechel/uarch/gatemate/pack_mult.cc | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/himbaechel/uarch/gatemate/bitstream.cc b/himbaechel/uarch/gatemate/bitstream.cc index 492cb183..1ddb74d4 100644 --- a/himbaechel/uarch/gatemate/bitstream.cc +++ b/himbaechel/uarch/gatemate/bitstream.cc @@ -225,7 +225,7 @@ struct BitstreamBackend auto *net = ctx->cells.at(cell_name)->ports.at(id_OUT).net; int64_t driver_l10 = ctx->cells.at(cell_name)->params[id_INIT_L10].as_int64(); - bool driver_is_inverted = driver_l10 == LUT_ONE || driver_l10 == LUT_INV_D0; + bool driver_is_inverted = driver_l10 == LUT_INV_D0; bool all_correct = true; bool all_inverted = true; diff --git a/himbaechel/uarch/gatemate/pack_mult.cc b/himbaechel/uarch/gatemate/pack_mult.cc index 9fe0683c..f2005526 100644 --- a/himbaechel/uarch/gatemate/pack_mult.cc +++ b/himbaechel/uarch/gatemate/pack_mult.cc @@ -360,8 +360,9 @@ MultCell::MultCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_msb) lower->params[id_C_C_P] = Property(0, 1); } - // upper->params[id_C_O1] = Property(0b10, 2); // CP_OUT1 -> OUT1 - // upper->params[id_C_O2] = Property(0b10, 2); // CP_OUT2 -> OUT2 + // Must force this one, even if outputs are not used to preserve logic + lower->params[id_C_O1] = Property(0b10, 2); // CP_OUT1 -> OUT1 + lower->params[id_C_O2] = Property(0b10, 2); // CP_OUT2 -> OUT2 } MsbRoutingCell::MsbRoutingCell(CellInfo *lower, CellInfo *upper, CellInfo *comp, CellInfo *cplines, IdString name) From eb77362b9735a0564a3f6cc9edd293f34451c1a3 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 4 Aug 2025 13:50:19 +0200 Subject: [PATCH 31/34] Added logs under debug, and removed include for idstring.h --- himbaechel/uarch/gatemate/gatemate.h | 1 - himbaechel/uarch/gatemate/route_mult.cc | 82 ++++++++++++++++--------- 2 files changed, 52 insertions(+), 31 deletions(-) diff --git a/himbaechel/uarch/gatemate/gatemate.h b/himbaechel/uarch/gatemate/gatemate.h index 3d468b57..ae280461 100644 --- a/himbaechel/uarch/gatemate/gatemate.h +++ b/himbaechel/uarch/gatemate/gatemate.h @@ -22,7 +22,6 @@ #include "extra_data.h" #include "himbaechel_api.h" -#include "idstring.h" #include "log.h" #include "nextpnr.h" #include "util.h" diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index c27c989c..35c56003 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -35,7 +35,8 @@ void find_and_bind_downhill_pip(Context *ctx, WireId from, WireId to, NetInfo *n NPNR_ASSERT(to != WireId()); for (auto pip : ctx->getPipsDownhill(from)) { if (ctx->getPipDstWire(pip) == to) { - log_info(" pip %s: %s -> %s\n", ctx->nameOfPip(pip), ctx->nameOfWire(from), ctx->nameOfWire(to)); + if (ctx->debug) + log_info(" pip %s: %s -> %s\n", ctx->nameOfPip(pip), ctx->nameOfWire(from), ctx->nameOfWire(to)); ctx->bindPip(pip, net, STRENGTH_LOCKED); return; @@ -53,7 +54,8 @@ void route_mult_diag(Context *ctx, NetInfo *net, Loc loc, WireId last_wire, int hops++; } - log_info(" routing diagonal: %d hops\n", hops); + if (ctx->debug) + log_info(" routing diagonal: %d hops\n", hops); for (int i = 0; i < hops; i++) { auto cpe_in = ctx->getWireByName( @@ -70,7 +72,8 @@ void route_mult_diag(Context *ctx, NetInfo *net, Loc loc, WireId last_wire, int void route_mult_x1y1_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN5 using x1y1\n", net->name.c_str(ctx)); + if (ctx->debug) + log_info(" routing net '%s' -> IN5 using x1y1\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); @@ -101,7 +104,8 @@ void route_mult_x1y1_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc, void route_mult_x1y1_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN1 using x1y1\n", net->name.c_str(ctx)); + if (ctx->debug) + log_info(" routing net '%s' -> IN1 using x1y1\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); @@ -133,7 +137,8 @@ void route_mult_x1y1_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc void route_mult_x1y1_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { - log_info(" routing net '%s' -> IN8 using x1y1\n", net->name.c_str(ctx)); + if (ctx->debug) + log_info(" routing net '%s' -> IN8 using x1y1\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y2 = ctx->idf("X%dY%d", loc.x + 1, loc.y + 1); @@ -189,7 +194,8 @@ void route_mult_x1y1_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc void route_mult_x1y2_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN5 using x1y2\n", net->name.c_str(ctx)); + if (ctx->debug) + log_info(" routing net '%s' -> IN5 using x1y2\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); @@ -252,7 +258,8 @@ void route_mult_x1y2_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc, void route_mult_x1y2_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN1 using x1y2\n", net->name.c_str(ctx)); + if (ctx->debug) + log_info(" routing net '%s' -> IN1 using x1y2\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); @@ -317,7 +324,8 @@ void route_mult_x1y2_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc void route_mult_x1y2_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { - log_info(" routing net '%s' -> IN8 using x1y2\n", net->name.c_str(ctx)); + if (ctx->debug) + log_info(" routing net '%s' -> IN8 using x1y2\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); @@ -362,7 +370,8 @@ void route_mult_x1y2_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc void route_mult_x2y1_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN5 using x2y1\n", net->name.c_str(ctx)); + if (ctx->debug) + log_info(" routing net '%s' -> IN5 using x2y1\n", net->name.c_str(ctx)); auto x0y1 = ctx->idf("X%dY%d", loc.x - 1, loc.y); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); @@ -419,7 +428,8 @@ void route_mult_x2y1_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc, void route_mult_x2y1_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN1 using x2y1\n", net->name.c_str(ctx)); + if (ctx->debug) + log_info(" routing net '%s' -> IN1 using x2y1\n", net->name.c_str(ctx)); auto x0y1 = ctx->idf("X%dY%d", loc.x - 1, loc.y); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); @@ -477,7 +487,8 @@ void route_mult_x2y1_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc void route_mult_x2y1_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { - log_info(" routing net '%s' -> IN8 using x2y1\n", net->name.c_str(ctx)); + if (ctx->debug) + log_info(" routing net '%s' -> IN8 using x2y1\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x1y2 = ctx->idf("X%dY%d", loc.x, loc.y + 1); @@ -522,7 +533,8 @@ void route_mult_x2y1_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc void route_mult_x2y2_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN5 using x2y2\n", net->name.c_str(ctx)); + if (ctx->debug) + log_info(" routing net '%s' -> IN5 using x2y2\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); @@ -586,7 +598,8 @@ void route_mult_x2y2_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc, void route_mult_x2y2_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a) { - log_info(" routing net '%s' -> IN1 using x2y2\n", net->name.c_str(ctx)); + if (ctx->debug) + log_info(" routing net '%s' -> IN1 using x2y2\n", net->name.c_str(ctx)); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); auto x2y1 = ctx->idf("X%dY%d", loc.x + 1, loc.y); @@ -651,7 +664,8 @@ void route_mult_x2y2_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc void route_mult_x2y2_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc loc, bool is_fourgroup_a, bool bind_route_start = false) { - log_info(" routing net '%s' -> IN8 using x2y2\n", net->name.c_str(ctx)); + if (ctx->debug) + log_info(" routing net '%s' -> IN8 using x2y2\n", net->name.c_str(ctx)); auto x0y0 = ctx->idf("X%dY%d", loc.x - 1, loc.y - 1); auto x1y1 = ctx->idf("X%dY%d", loc.x, loc.y); @@ -726,13 +740,15 @@ void GateMateImpl::route_mult() auto x_within_fourgroup = (loc.x - 3) % 2; auto y_within_fourgroup = (loc.y - 3) % 2; - log_info(" A passthrough at (%d, %d) has 4-group %c\n", loc.x, loc.y, is_fourgroup_a ? 'A' : 'B'); + if (ctx->debug) { + log_info(" A passthrough at (%d, %d) has 4-group %c\n", loc.x, loc.y, is_fourgroup_a ? 'A' : 'B'); - log_info(" lower.OUT [OUT1] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(lower->bel, id_OUT))); - for (auto sink_port : lower->ports.at(id_OUT).net->users) { - auto sink_loc = ctx->getBelLocation(sink_port.cell->bel); - log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), - sink_loc.x, sink_loc.y); + log_info(" lower.OUT [OUT1] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(lower->bel, id_OUT))); + for (auto sink_port : lower->ports.at(id_OUT).net->users) { + auto sink_loc = ctx->getBelLocation(sink_port.cell->bel); + log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), + sink_loc.x, sink_loc.y); + } } if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { @@ -760,15 +776,18 @@ void GateMateImpl::route_mult() bool needs_in8_route = false; - log_info(" A passthrough at (%d, %d) has 4-group %c\n", loc.x, loc.y, is_fourgroup_a ? 'A' : 'B'); + if (ctx->debug) { + log_info(" A passthrough at (%d, %d) has 4-group %c\n", loc.x, loc.y, is_fourgroup_a ? 'A' : 'B'); - log_info(" upper.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(upper->bel, id_OUT))); + log_info(" upper.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(upper->bel, id_OUT))); + } for (auto sink_port : upper->ports.at(id_OUT).net->users) { if (sink_port.port == id_IN8) needs_in8_route = true; auto sink_loc = ctx->getBelLocation(sink_port.cell->bel); - log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), - sink_loc.x, sink_loc.y); + if (ctx->debug) + log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), + sink_loc.x, sink_loc.y); } if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { @@ -802,13 +821,16 @@ void GateMateImpl::route_mult() auto x_within_fourgroup = (loc.x - 3) % 2; auto y_within_fourgroup = (loc.y - 3) % 2; - log_info(" Zero driver at (%d, %d) has 4-group %c\n", loc.x, loc.y, is_fourgroup_a ? 'A' : 'B'); + if (ctx->debug) { + log_info(" Zero driver at (%d, %d) has 4-group %c\n", loc.x, loc.y, is_fourgroup_a ? 'A' : 'B'); - log_info(" zero_driver.OUT [OUT2] = %s\n", ctx->nameOfWire(ctx->getBelPinWire(zero_driver->bel, id_OUT))); - for (auto sink_port : zero_driver->ports.at(id_OUT).net->users) { - auto sink_loc = ctx->getBelLocation(sink_port.cell->bel); - log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), - sink_loc.x, sink_loc.y); + log_info(" zero_driver.OUT [OUT2] = %s\n", + ctx->nameOfWire(ctx->getBelPinWire(zero_driver->bel, id_OUT))); + for (auto sink_port : zero_driver->ports.at(id_OUT).net->users) { + auto sink_loc = ctx->getBelLocation(sink_port.cell->bel); + log_info(" -> %s.%s at (%d, %d)\n", sink_port.cell->name.c_str(ctx), sink_port.port.c_str(ctx), + sink_loc.x, sink_loc.y); + } } if (x_within_fourgroup == 0 && y_within_fourgroup == 0) { From 89e7e059d8d49f73f6b552cdefbe72561510eec0 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 4 Aug 2025 13:55:19 +0200 Subject: [PATCH 32/34] cleanup --- himbaechel/uarch/gatemate/bitstream.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/himbaechel/uarch/gatemate/bitstream.cc b/himbaechel/uarch/gatemate/bitstream.cc index 1ddb74d4..388216a1 100644 --- a/himbaechel/uarch/gatemate/bitstream.cc +++ b/himbaechel/uarch/gatemate/bitstream.cc @@ -23,8 +23,6 @@ #include "config.h" #include "gatemate.h" #include "gatemate_util.h" -#include "log.h" -#include "property.h" #include "uarch/gatemate/pack.h" #define HIMBAECHEL_CONSTIDS "uarch/gatemate/constids.inc" @@ -269,7 +267,8 @@ struct BitstreamBackend } } else if (all_inverted) { params[id_INIT_L10] = Property(~driver_l10 & 0b1111, 4); - log_info("multiplier net '%s': fixed inversion\n", net->name.c_str(ctx)); + if (ctx->debug) + log_info("multiplier net '%s': fixed inversion\n", net->name.c_str(ctx)); } } From f0e03ed6e72b76a2c1f63e8e452e7ef6ed3fca37 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 4 Aug 2025 14:23:18 +0200 Subject: [PATCH 33/34] cleanup --- himbaechel/uarch/gatemate/gatemate.cc | 1 - himbaechel/uarch/gatemate/route_mult.cc | 3 --- 2 files changed, 4 deletions(-) diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index ce278e67..b30b380b 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -20,7 +20,6 @@ #include "gatemate.h" #include "log.h" #include "placer_heap.h" -#include "property.h" #define GEN_INIT_CONSTIDS #define HIMBAECHEL_CONSTIDS "uarch/gatemate/constids.inc" diff --git a/himbaechel/uarch/gatemate/route_mult.cc b/himbaechel/uarch/gatemate/route_mult.cc index 35c56003..dc9ce38e 100644 --- a/himbaechel/uarch/gatemate/route_mult.cc +++ b/himbaechel/uarch/gatemate/route_mult.cc @@ -19,9 +19,6 @@ #include "gatemate.h" #include "log.h" -#include "nextpnr_assertions.h" -#include "nextpnr_base_types.h" -#include "nextpnr_namespaces.h" #define HIMBAECHEL_CONSTIDS "uarch/gatemate/constids.inc" #include "himbaechel_constids.h" From 6b11a82d04aa8129676b8272dbb17b874179055a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 4 Aug 2025 14:28:43 +0200 Subject: [PATCH 34/34] cleanup --- himbaechel/uarch/gatemate/pack_mult.cc | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/himbaechel/uarch/gatemate/pack_mult.cc b/himbaechel/uarch/gatemate/pack_mult.cc index f2005526..7da4b028 100644 --- a/himbaechel/uarch/gatemate/pack_mult.cc +++ b/himbaechel/uarch/gatemate/pack_mult.cc @@ -259,16 +259,12 @@ CarryGenCell::CarryGenCell(CellInfo *lower, CellInfo *upper, CellInfo *comp, Cel cplines->params[id_C_CY2_I] = Property(1, 1); // CY2_VAL -> COUTY2 cplines->params[id_C_SEL_C] = Property(1, 1); // COMP_OUT -> CY2_VAL cplines->params[id_C_SELY2] = Property(0, 1); // COMP_OUT -> CY2_VAL - - // upper->params[id_C_O1] = Property(0b11, 2); // COMB1OUT -> OUT1 } MultfabCell::MultfabCell(CellInfo *lower, CellInfo *upper, CellInfo *comp, CellInfo *cplines, IdString name, bool is_even_x, bool enable_cinx) : lower{lower}, upper{upper}, comp{comp}, cplines{cplines} { - // TODO: perhaps C_I[1234] could be pips? - lower->params[id_INIT_L00] = Property(LUT_D1, 4); // PINY1 // lower->params[id_INIT_L01] = Property(LUT_ZERO, 4); // (unused) lower->params[id_INIT_L10] = Property(LUT_D0, 4); // L02 @@ -286,7 +282,6 @@ MultfabCell::MultfabCell(CellInfo *lower, CellInfo *upper, CellInfo *comp, CellI if (enable_cinx) upper->params[id_C_I2] = Property(1, 1); // CINX for L01 lower->params[id_C_I3] = Property(1, 1); // PINY1 for L02 - // upper->params[id_C_FUNCTION] = Property(C_ADDCIN, 3); cplines->params[id_C_SELX] = Property(1, 1); // inverted CINY2 -> CX_VAL cplines->params[id_C_SEL_C] = Property(1, 1); // inverted CINY2 -> CX_VAL; COMP_OUT -> CY1_VAL @@ -296,16 +291,12 @@ MultfabCell::MultfabCell(CellInfo *lower, CellInfo *upper, CellInfo *comp, CellI cplines->params[id_C_PY1_I] = Property(1, 1); // PY1_VAL -> POUTY1 cplines->params[id_C_SEL_P] = Property(0, 1); // OUT1 -> PY1_VAL cplines->params[id_C_SELY1] = Property(0, 1); // COMP_OUT -> CY1_VAL; OUT1 -> PY1_VAL - - // upper->params[id_C_O1] = Property(0b11, 2); // COMB1OUT -> OUT1 } FRoutingCell::FRoutingCell(CellInfo *lower, CellInfo *upper, CellInfo *comp, CellInfo *cplines, IdString name, bool is_even_x) : lower{lower}, upper{upper}, comp{comp}, cplines{cplines} { - // TODO: simplify AND with zero/OR with zero into something more sensical. - lower->params[id_INIT_L00] = Property(LUT_ZERO, 4); // (unused) lower->params[id_INIT_L01] = Property(LUT_ZERO, 4); // (unused) lower->params[id_INIT_L10] = Property(LUT_ZERO, 4); @@ -319,7 +310,6 @@ FRoutingCell::FRoutingCell(CellInfo *lower, CellInfo *upper, CellInfo *comp, Cel // upper->params[id_INIT_L01] = Property(LUT_ONE, 4); // (unused) upper->params[id_INIT_L10] = Property(LUT_D0, 4); upper->params[id_C_I1] = Property(1, 1); // PINY1 for L00 - // upper->params[id_C_FUNCTION] = Property(C_ADDCIN, 3); cplines->params[id_C_SELX] = Property(1, 1); cplines->params[id_C_SEL_C] = Property(1, 1); @@ -329,9 +319,6 @@ FRoutingCell::FRoutingCell(CellInfo *lower, CellInfo *upper, CellInfo *comp, Cel cplines->params[id_C_CY2_I] = Property(1, 1); cplines->params[id_C_PY1_I] = Property(1, 1); cplines->params[id_C_PY2_I] = Property(1, 1); - - // upper->params[id_C_O1] = Property(0b11, 2); // COMB1OUT -> OUT1 - // upper->params[id_C_O2] = Property(0b11, 2); // COMB2OUT -> OUT2 } MultCell::MultCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_msb) : lower{lower}, upper{upper} @@ -339,7 +326,6 @@ MultCell::MultCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_msb) lower->params[id_INIT_L02] = Property(LUT_AND, 4); lower->params[id_INIT_L03] = Property(LUT_D1, 4); // PINX lower->params[id_INIT_L11] = Property(LUT_XOR, 4); - // lower->params[id_INIT_L20] = Property(LUT_D1, 4); // L11 lower->params[id_C_FUNCTION] = Property(C_MULT, 3); upper->params[id_INIT_L00] = Property(LUT_AND, 4); @@ -360,7 +346,7 @@ MultCell::MultCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_msb) lower->params[id_C_C_P] = Property(0, 1); } - // Must force this one, even if outputs are not used to preserve logic + // Must force these, even if outputs are not used, to preserve logic lower->params[id_C_O1] = Property(0b10, 2); // CP_OUT1 -> OUT1 lower->params[id_C_O2] = Property(0b10, 2); // CP_OUT2 -> OUT2 } @@ -368,11 +354,6 @@ MultCell::MultCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_msb) MsbRoutingCell::MsbRoutingCell(CellInfo *lower, CellInfo *upper, CellInfo *comp, CellInfo *cplines, IdString name) : lower{lower}, upper{upper}, comp{comp}, cplines{cplines} { - // lower->params[id_INIT_L02] = Property(LUT_ZERO, 4); // (unused) - // lower->params[id_INIT_L03] = Property(LUT_ZERO, 4); // (unused) - // lower->params[id_INIT_L11] = Property(LUT_ZERO, 4); // (unused) - // lower->params[id_INIT_L20] = Property(LUT_ZERO, 4); // (unused) - comp->params[id_INIT_L30] = Property(LUT_ONE, 4); // zero -> COMP_OUT (L30 is inverted) upper->params[id_INIT_L00] = Property(LUT_D1, 4); // PINY1 @@ -388,8 +369,6 @@ MsbRoutingCell::MsbRoutingCell(CellInfo *lower, CellInfo *upper, CellInfo *comp, cplines->params[id_C_PX_I] = Property(1, 1); // PX_VAL -> POUTX cplines->params[id_C_PY1_I] = Property(1, 1); // PY1_VAL -> POUTY1 cplines->params[id_C_PY2_I] = Property(1, 1); // PY2_VAL -> POUTY2 - - // upper->params[id_C_O2] = Property(0b11, 2); // COMB2 -> OUT2 } void GateMatePacker::pack_mult()