1
0
mirror of https://github.com/YosysHQ/nextpnr.git synced 2026-01-11 23:53:21 +00:00

gatemate: Include and use connection timing data (#1559)

* convert nodes to pips

* add plane info for node pips

* a few multiplier router fixes

* do not need node delay

* add pip delays

* cleanup

* tried fixing clock router

* add PLL delays

* fix clock routing

* Do not use actual pip delay, determine best by number of passed pips

* optimize

* proper parameter check

* more multiplier fixes

* another mult fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* another multiplier fix

* log number of clock net users

* Revert "Do not use actual pip delay, determine best by number of passed pips"

This reverts commit c66e422dd0814edfbfb81fdd6f9dcaaea9cece0d.

We want to guarantee minimum clock skew, so we need pip delay.

* route clocks from source to sink

* add time spent to route_clock

* weakly-bind non-global clocks

* clangformat

* remove dead code

* Require version 1.8

* change to assert

* add revisits in clock router

---------

Co-authored-by: Lofty <dan.ravensloft@gmail.com>
This commit is contained in:
Miodrag Milanović 2025-09-30 09:13:29 +02:00 committed by GitHub
parent 8f8181c717
commit 8381827fa5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 431 additions and 291 deletions

View File

@ -157,6 +157,10 @@ bool GateMateImpl::getCellDelay(const CellInfo *cell, IdString fromPort, IdStrin
return get_delay_from_tmg_db(ctx->idf("timing_glbout_%s_%s", fromPort.c_str(ctx), toPort.c_str(ctx)), delay);
} else if (cell->type.in(id_RAM, id_RAM_HALF)) {
return false;
} else if (cell->type.in(id_PLL)) {
if (fromPort.in(id_CLK_REF, id_USR_CLK_REF) && toPort.in(id_CLK0, id_CLK90, id_CLK180, id_CLK270))
return get_delay_from_tmg_db(ctx->id("timing_pll_clk_ref_i_clk_core0_o"), delay);
return false;
}
return false;
}

View File

@ -44,7 +44,6 @@ import chip
import die
pip_tmg_names = set()
node_tmg_names = set()
@dataclass
class TileExtraData(BBAStruct):
@ -187,14 +186,11 @@ def set_timings(ch):
continue
name = "timing_" + re.sub(r"[-= >]", "_", rename_table.get(name, name))
tmg.get_speed_grade(speed).extra_data.add_timing(name=ch.strs.id(name), delay=convert_timing(val))
#for k in node_tmg_names:
# assert k in timing, f"node class {k} not found in timing data"
# tmg.set_node_class(grade=speed, name=k, delay=convert_timing(timing[k]))
#for k in pip_tmg_names:
# assert k in timing, f"pip class {k} not found in timing data"
# tmg.set_pip_class(grade=speed, name=k, delay=convert_timing(timing[k]))
for k in pip_tmg_names:
assert k in timing, f"pip class {k} not found in timing data"
tmg.set_pip_class(grade=speed, name=k, delay=convert_timing(timing[k]))
EXPECTED_VERSION = 1.7
EXPECTED_VERSION = 1.8
def main():
# Range needs to be +1, but we are adding +2 more to coordinates, since
@ -226,12 +222,29 @@ def main():
print("==============================================================================")
os._exit(-1)
new_wires = dict()
wire_delay = dict()
for _,nodes in dev.get_connections():
for conn in nodes:
if conn.endpoint:
t_name = dev.get_tile_type(conn.x,conn.y)
if t_name not in new_wires:
new_wires[t_name] = set()
new_wires[t_name].add(conn.name)
# Check to confirm no duplicates
if conn.name in wire_delay:
assert wire_delay[conn.name] == conn.delay, f"conflict delay {conn.name}"
wire_delay[conn.name] = conn.delay
for type_name in sorted(die.get_tile_type_list()):
tt = ch.create_tile_type(type_name)
for group in sorted(die.get_groups_for_type(type_name)):
tt.create_group(group.name, group.type)
for wire in sorted(die.get_endpoints_for_type(type_name)):
tt.create_wire(wire.name, wire.type)
if type_name in new_wires:
for wire in sorted(new_wires[type_name]):
tt.create_wire(wire+"_n", "NODE_WIRE")
for prim in sorted(die.get_primitives_for_type(type_name)):
bel = tt.create_bel(prim.name, prim.type, prim.z)
if (prim.name in ["CPE_LT_FULL", "CPE_BRIDGE"]):
@ -260,6 +273,20 @@ def main():
if mux.name == "CPE.C_SN":
mux_flags |= MUX_ROUTING
pp.extra_data = PipExtraData(PIP_EXTRA_MUX, ch.strs.id(mux.name), mux.bits, mux.value, mux_flags, plane)
if type_name in new_wires:
for wire in sorted(new_wires[type_name]):
delay = wire_delay[wire]
if len(delay)>0:
pip_tmg_names.add(delay)
pp = tt.create_pip(wire+"_n", wire, delay)
plane = 0
if wire.startswith("IM"):
plane = int(wire[4:6])
if wire.startswith("SB_SML") or wire.startswith("SB_BIG"):
plane = int(wire[8:10])
if wire.startswith("SB_DRIVE"):
plane = int(wire[10:12])
pp.extra_data = PipExtraData(PIP_EXTRA_MUX, ch.strs.id(""), 0, 0, 0, plane)
# Setup tile grid
for x in range(dev.max_col() + 3):
@ -271,14 +298,9 @@ def main():
# Create nodes between tiles
for _,nodes in dev.get_connections():
node = []
timing = ""
for conn in sorted(nodes):
node.append(NodeWire(conn.x + 2, conn.y + 2, conn.name))
# for now update to last one we have defined
if len(conn.delay)>0:
timing = conn.delay
node_tmg_names.add(conn.delay)
ch.add_node(node, timing)
node.append(NodeWire(conn.x + 2, conn.y + 2, (conn.name + "_n") if conn.endpoint else conn.name))
ch.add_node(node)
set_timings(ch)
for package in dev.get_packages():

View File

@ -303,7 +303,7 @@ void GateMatePacker::remove_clocking()
flush_cells();
}
static const char *fpga_mode_to_str(int mode)
static const char *timing_mode_to_str(int mode)
{
switch (mode) {
case 1:
@ -444,9 +444,9 @@ void GateMatePacker::pack_pll()
log_error("Unknown PERF_MD parameter value '%s' for cell %s.\n", mode.c_str(), ci.name.c_str(ctx));
}
if (perf_md != uarch->fpga_mode)
log_warning("PLL '%s' mode is '%s' but FPGA mode is '%s'.\n", ci.name.c_str(ctx),
fpga_mode_to_str(perf_md), fpga_mode_to_str(uarch->fpga_mode));
if (perf_md != uarch->timing_mode)
log_warning("PLL '%s' timing mode is '%s' but FPGA timing mode is '%s'.\n", ci.name.c_str(ctx),
timing_mode_to_str(perf_md), timing_mode_to_str(uarch->timing_mode));
double ref_clk = double_or_default(ci.params, id_REF_CLK, 0.0);
if (ref_clk <= 0 || ref_clk > 125)

View File

@ -33,10 +33,10 @@ namespace {
struct QueuedWire
{
explicit QueuedWire(WireId wire, float delay = 0.0) : wire{wire}, delay{delay} {};
explicit QueuedWire(WireId wire, delay_t delay = 0) : wire{wire}, delay{delay} {};
WireId wire;
float delay;
delay_t delay;
bool operator>(const QueuedWire &rhs) const { return this->delay > rhs.delay; }
};
@ -45,6 +45,9 @@ struct QueuedWire
void GateMateImpl::route_clock()
{
log_info("Routing clock nets...\n");
auto rstart = std::chrono::high_resolution_clock::now();
auto clk_nets = std::vector<NetInfo *>{};
auto reserved_wires = dict<WireId, IdString>{};
@ -64,6 +67,10 @@ void GateMateImpl::route_clock()
};
auto reserve = [&](WireId wire, NetInfo *net) {
for (auto pip : ctx->getPipsUphill(wire)) {
wire = ctx->getPipSrcWire(pip);
break;
}
if (ctx->debug) {
auto wire_name = "(uninitialized)";
if (wire != WireId())
@ -73,8 +80,6 @@ void GateMateImpl::route_clock()
reserved_wires.insert({wire, net->name});
};
log_info("Routing clock nets...\n");
for (auto &net_pair : ctx->nets) {
NetInfo *net = net_pair.second.get();
if (!net->driver.cell)
@ -107,37 +112,72 @@ void GateMateImpl::route_clock()
}
for (auto clk_net : clk_nets) {
log_info(" routing net '%s'\n", clk_net->name.c_str(ctx));
ctx->bindWire(ctx->getNetinfoSourceWire(clk_net), clk_net, STRENGTH_LOCKED);
auto clk_plane = 0;
switch (clk_net->driver.port.index) {
case id_GLB0.index:
clk_plane = 9;
break;
case id_GLB1.index:
clk_plane = 10;
break;
case id_GLB2.index:
clk_plane = 11;
break;
case id_GLB3.index:
clk_plane = 12;
break;
}
log_info(" routing net '%s' to %d users\n", clk_net->name.c_str(ctx), clk_net->users.entries());
auto src_wire = ctx->getNetinfoSourceWire(clk_net);
ctx->bindWire(src_wire, clk_net, STRENGTH_LOCKED);
auto sink_wires = dict<WireId, PortRef>{};
auto sink_wires_to_do = pool<WireId>{};
for (auto &usr : clk_net->users) {
std::priority_queue<QueuedWire, std::vector<QueuedWire>, std::greater<QueuedWire>> visit;
dict<WireId, PipId> backtrace;
WireId dest = WireId();
if (!feeds_clk_port(usr) && !feeds_ddr_port(clk_net, usr))
continue;
auto cpe_loc = ctx->getBelLocation(usr.cell->bel);
auto is_glb_clk = clk_net->driver.cell->type == id_GLBOUT;
auto sink_wire = ctx->getNetinfoSinkWire(clk_net, usr, 0);
sink_wires.insert({sink_wire, usr});
sink_wires_to_do.insert(sink_wire);
}
std::priority_queue<QueuedWire, std::vector<QueuedWire>, std::greater<QueuedWire>> visit;
dict<WireId, PipId> backtrace;
dict<WireId, delay_t> delay_map;
auto is_glb_clk = clk_net->driver.cell->type == id_GLBOUT;
visit.push(QueuedWire(src_wire));
while (!visit.empty()) {
QueuedWire curr = visit.top();
visit.pop();
if (sink_wires_to_do.count(curr.wire)) {
if (ctx->debug) {
auto sink_wire_name = "(uninitialized)";
if (curr.wire != WireId())
sink_wire_name = ctx->nameOfWire(curr.wire);
log_info(" -> %s (%.3fns)\n", sink_wire_name, ctx->getDelayNS(curr.delay));
}
sink_wires_to_do.erase(curr.wire);
if (sink_wires_to_do.empty())
break;
}
for (auto dh : ctx->getPipsDownhill(curr.wire)) {
if (!ctx->checkPipAvailForNet(dh, clk_net))
continue;
WireId dst = ctx->getPipDstWire(dh);
if (!ctx->checkWireAvail(dst) && ctx->getBoundWireNet(dst) != clk_net)
continue;
// Has this wire been reserved for another net?
auto reserved = reserved_wires.find(dst);
if (reserved != reserved_wires.end() && reserved->second != clk_net->name)
continue;
auto delay = curr.delay + ctx->getPipDelay(dh).maxDelay() + ctx->getWireDelay(dst).maxDelay() +
ctx->getDelayEpsilon();
if (backtrace.count(dst) && delay_map.at(dst) <= delay)
continue;
delay_map[dst] = delay;
backtrace[dst] = dh;
visit.push(QueuedWire(dst, delay));
}
}
for (auto sink_wire : sink_wires_to_do) {
log_info(" failed to find a route using dedicated resources. %s -> %s\n",
clk_net->driver.cell->name.c_str(ctx), ctx->nameOfWire(sink_wire));
}
for (auto pair : sink_wires) {
auto sink_wire = pair.first;
auto usr = pair.second;
auto src = sink_wire;
if (ctx->debug) {
auto sink_wire_name = "(uninitialized)";
if (sink_wire != WireId())
@ -145,87 +185,30 @@ void GateMateImpl::route_clock()
log_info(" routing arc to %s.%s (wire %s):\n", usr.cell->name.c_str(ctx), usr.port.c_str(ctx),
sink_wire_name);
}
visit.push(QueuedWire(sink_wire));
while (!visit.empty()) {
QueuedWire curr = visit.top();
visit.pop();
if (curr.wire == ctx->getNetinfoSourceWire(clk_net)) {
if (ctx->debug)
log_info(" (%.3fns)\n", curr.delay);
dest = curr.wire;
break;
}
PipId bound_pip;
auto fnd_wire = clk_net->wires.find(curr.wire);
if (fnd_wire != clk_net->wires.end()) {
bound_pip = fnd_wire->second.pip;
}
for (auto uh : ctx->getPipsUphill(curr.wire)) {
if (!ctx->checkPipAvailForNet(uh, clk_net))
continue;
WireId src = ctx->getPipSrcWire(uh);
if (backtrace.count(src))
continue;
if (!ctx->checkWireAvail(src) && ctx->getBoundWireNet(src) != clk_net)
continue;
if (bound_pip != PipId() && uh != bound_pip)
continue;
// Has this wire been reserved for another net?
auto reserved = reserved_wires.find(src);
if (reserved != reserved_wires.end() && reserved->second != clk_net->name)
continue;
auto pip_loc = ctx->getPipLocation(uh);
// Use only a specific plane to minimise congestion for global clocks.
if (is_glb_clk && (pip_loc.x != cpe_loc.x || pip_loc.y != cpe_loc.y)) {
// Plane 9 is the clock plane, so it should only ever use itself.
if (clk_plane == 9 && pip_plane(uh) != 9)
continue;
// Plane 10 is the enable plane.
// When there's a set/reset, we want to use the switchbox X23 pip to change directly to plane 9.
if (clk_plane == 10 && pip_plane(uh) != 9 && pip_plane(uh) != 10)
continue;
// Plane 11 is the set/reset plane; we want to use the switchbox X14 pip to go to plane 12, then
// use the IM to switch to plane 9.
if (clk_plane == 11 && pip_plane(uh) == 10)
continue;
// Plane 12 is the spare plane; we can use the IM to change directly to plane 9.
if (clk_plane == 12 && pip_plane(uh) != 9 && pip_plane(uh) != 12)
continue;
}
backtrace[src] = uh;
auto delay = ctx->getDelayNS(ctx->getPipDelay(uh).maxDelay() + ctx->getWireDelay(src).maxDelay() +
ctx->getDelayEpsilon());
visit.push(QueuedWire(src, curr.delay + delay));
}
}
if (dest == WireId()) {
log_info(" failed to find a route using dedicated resources. %s -> %s\n",
clk_net->driver.cell->name.c_str(ctx), usr.cell->name.c_str(ctx));
}
while (backtrace.count(dest)) {
auto uh = backtrace[dest];
dest = ctx->getPipDstWire(uh);
if (ctx->getBoundWireNet(dest) == clk_net) {
NPNR_ASSERT(clk_net->wires.at(dest).pip == uh);
while (backtrace.count(src)) {
auto uh = backtrace[src];
if (ctx->getBoundWireNet(src) == clk_net) {
if (ctx->debug)
log_info(" pip %s --> %s (plane %hhd)\n", ctx->nameOfPip(uh),
ctx->nameOfWire(dest), pip_plane(uh));
} else if (ctx->getBoundWireNet(dest) == nullptr) {
ctx->bindPip(uh, clk_net, STRENGTH_LOCKED);
ctx->nameOfWire(src), pip_plane(uh));
} else if (ctx->getBoundWireNet(src) == nullptr) {
if (ctx->debug)
log_info(" bind pip %s --> %s (plane %hhd)\n", ctx->nameOfPip(uh),
ctx->nameOfWire(dest), pip_plane(uh));
ctx->nameOfWire(src), pip_plane(uh));
ctx->bindPip(uh, clk_net, is_glb_clk ? STRENGTH_LOCKED : STRENGTH_WEAK);
} else {
log_error("Can't bind pip %s because wire %s is already bound\n", ctx->nameOfPip(uh),
ctx->nameOfWire(dest));
ctx->nameOfWire(src));
}
if (dest == sink_wire)
if (src == src_wire)
break;
src = ctx->getPipSrcWire(uh);
}
}
}
auto rend = std::chrono::high_resolution_clock::now();
log_info("Clock router time %.02fs\n", std::chrono::duration<float>(rend - rstart).count());
}
NEXTPNR_NAMESPACE_END

View File

@ -64,15 +64,23 @@ void route_mult_diag(Context *ctx, NetInfo *net, Loc loc, WireId last_wire, int
log_info(" routing diagonal: %d hops\n", hops);
for (int i = 0; i < hops; i++) {
auto in_mux_y = ctx->getWireByName(
IdStringList::concat(ctx->idf("X%dY%d", loc.x + i, loc.y + i), ctx->idf("IM.P%02d.Y", plane)));
auto d4 = ctx->getWireByName(
IdStringList::concat(ctx->idf("X%dY%d", loc.x + i + 1, loc.y + i + 1), ctx->idf("IM.P%02d.D4", plane)));
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, last_wire, in_mux_y, net);
find_and_bind_downhill_pip(ctx, in_mux_y, cpe_in, net);
find_and_bind_downhill_pip(ctx, cpe_in, cpe_in_int, net);
last_wire = cpe_in;
if (i != hops - 1)
find_and_bind_downhill_pip(ctx, in_mux_y, d4, net);
last_wire = d4;
}
}
@ -86,23 +94,29 @@ void route_mult_x1y1_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc,
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_out1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1")));
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);
find_and_bind_downhill_pip(ctx, cpe_out1_int, cpe_out1, net);
if (is_fourgroup_a) {
auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0")));
auto sb_big_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.D0")));
auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.Y1")));
find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big, net);
find_and_bind_downhill_pip(ctx, sb_big, in_mux, net); // inverting
find_and_bind_downhill_pip(ctx, cpe_out1, 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, in_mux, net);
} 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")));
auto sb_sml_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.Y1")));
find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out1, 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
find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_y1, net);
find_and_bind_downhill_pip(ctx, sb_sml_y1, in_mux, net); // inverting
}
route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5);
@ -118,23 +132,29 @@ void route_mult_x1y1_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc
auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT);
auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int")));
auto cpe_out2 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2")));
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);
find_and_bind_downhill_pip(ctx, cpe_out2_int, cpe_out2, net);
if (is_fourgroup_a) {
auto sb_big = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0")));
auto sb_big_d0 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.D0")));
auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.Y1")));
find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big, net);
find_and_bind_downhill_pip(ctx, sb_big, in_mux, net); // inverting
find_and_bind_downhill_pip(ctx, cpe_out2, 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, 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")));
auto sb_sml_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.Y1")));
find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out2, 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
find_and_bind_downhill_pip(ctx, sb_sml_y1_int, sb_sml_y1, net);
find_and_bind_downhill_pip(ctx, sb_sml_y1, in_mux, net);
}
route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1);
@ -152,6 +172,7 @@ void route_mult_x1y1_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc
auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT);
auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int")));
auto cpe_out2 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2")));
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")));
@ -159,41 +180,57 @@ void route_mult_x1y1_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc
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, cpe_out2_int, cpe_out2, net);
}
find_and_bind_downhill_pip(ctx, cpe_out2, 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_sml_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.D0")));
auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.Y1_int")));
auto sb_sml_y1 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_SML.P12.Y1")));
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 sb_big_y3 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_BIG.P12.Y3")));
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
find_and_bind_downhill_pip(ctx, out_mux_y, 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_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, sb_big_y3, net); // inverting
find_and_bind_downhill_pip(ctx, sb_big_y3, 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_big_d0 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_BIG.P12.D0")));
auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("SB_BIG.P12.Y1")));
auto sb_sml_d2_1 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("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 sb_sml_y3 = ctx->getWireByName(IdStringList::concat(x4y2, ctx->idf("SB_SML.P12.Y3")));
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, out_mux_y, 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_d2_1, net);
find_and_bind_downhill_pip(ctx, sb_sml_d2_1, 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
find_and_bind_downhill_pip(ctx, sb_sml_y3_int, sb_sml_y3, net);
find_and_bind_downhill_pip(ctx, sb_sml_y3, in_mux_p12, net);
}
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_p12_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.Y")));
auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7")));
auto in_mux_p04_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.Y")));
auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6")));
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_p12, in_mux_p12_y, net);
find_and_bind_downhill_pip(ctx, in_mux_p12_y, in_mux_p04, net);
find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p04_y, net);
find_and_bind_downhill_pip(ctx, in_mux_p04_y, in_mux_p08, net);
route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8);
}
@ -209,54 +246,65 @@ void route_mult_x1y2_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc,
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_out1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1")));
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);
find_and_bind_downhill_pip(ctx, cpe_out1_int, cpe_out1, 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_p06_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P06.YDIAG")));
auto sb_sml_p05_x23 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("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_d2_1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P05.D2_1")));
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
auto sb_big_y3 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P05.Y3")));
find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_p06_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out1, 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_p06_ydiag, sb_sml_p05_x23, net);
find_and_bind_downhill_pip(ctx, sb_sml_p05_x23, 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_sml_p05_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);
find_and_bind_downhill_pip(ctx, sb_big_ydiag, sb_big_y3, net);
find_and_bind_downhill_pip(ctx, sb_big_y3, 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_p06_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P06.YDIAG")));
auto sb_big_p05_x23 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("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_d2_1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P05.D2_1")));
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")));
auto sb_sml_y3 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P05.Y3")));
find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big_p06_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out1, 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_p06_ydiag, sb_big_p05_x23, net);
find_and_bind_downhill_pip(ctx, sb_big_p05_x23, 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_big_p05_y1, sb_sml_d2_1, net);
find_and_bind_downhill_pip(ctx, sb_sml_d2_1, 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);
find_and_bind_downhill_pip(ctx, sb_sml_y3_int, 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, 5);
@ -273,9 +321,11 @@ void route_mult_x1y2_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc
auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT);
auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int")));
auto cpe_out2 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2")));
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, cpe_out2, net);
auto in_mux = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("IM.P01.D2")));
@ -283,44 +333,53 @@ void route_mult_x1y2_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc
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_p02_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P02.YDIAG")));
auto sb_sml_p01_x23 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("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_sml_p01_y1_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P01.Y1_int")));
auto sb_sml_p01_y1 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P01.Y1")));
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
auto sb_big_y3 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_BIG.P01.Y3")));
find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_p02_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out2, 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_p02_ydiag, sb_sml_p01_x23, net);
find_and_bind_downhill_pip(ctx, sb_sml_p01_x23, sb_sml_p01_ydiag, net);
find_and_bind_downhill_pip(ctx, sb_sml_p01_ydiag, sb_sml_p01_y1_int, net);
find_and_bind_downhill_pip(ctx, sb_sml_p01_y1_int, 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);
find_and_bind_downhill_pip(ctx, sb_big_ydiag, sb_big_y3, net);
find_and_bind_downhill_pip(ctx, sb_big_y3, 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_p02_ydiag = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P02.YDIAG")));
auto sb_big_p01_x23 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("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_d2_1 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P01.D2_1")));
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")));
auto sb_sml_y3_int = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P01.Y3_int")));
auto sb_sml_y3 = ctx->getWireByName(IdStringList::concat(x4y1, ctx->idf("SB_SML.P01.Y3")));
find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_p02_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out2, 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_p02_ydiag, sb_big_p01_x23, net);
find_and_bind_downhill_pip(ctx, sb_big_p01_x23, 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_big_p01_y1, sb_sml_d2_1, net);
find_and_bind_downhill_pip(ctx, sb_sml_d2_1, 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_ydiag, sb_sml_y3_int, net);
find_and_bind_downhill_pip(ctx, sb_sml_y3_int, sb_sml_y3, net);
find_and_bind_downhill_pip(ctx, sb_sml_y3, in_mux, net);
}
@ -339,6 +398,7 @@ void route_mult_x1y2_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc
auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT);
auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int")));
auto cpe_out2 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2")));
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")));
@ -346,30 +406,43 @@ void route_mult_x1y2_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc
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, cpe_out2_int, cpe_out2, net);
}
find_and_bind_downhill_pip(ctx, cpe_out2, 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")));
auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P10.D0")));
auto sb_sml_y2_int = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P10.Y2_int")));
auto sb_sml_y2 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_SML.P10.Y2")));
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
find_and_bind_downhill_pip(ctx, out_mux_y, sb_sml_d0, net);
find_and_bind_downhill_pip(ctx, sb_sml_d0, 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_p10, net);
} else {
// x2y1/OM.P10.Y is x2y1/SB_BIG.P10.D0
// x2y2/IM.P10.D1 is x2y1/SB_BIG.P10.Y2
auto sb_big_d0 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P10.D0")));
auto sb_big_y2 = ctx->getWireByName(IdStringList::concat(x2y1, ctx->idf("SB_BIG.P10.Y2")));
find_and_bind_downhill_pip(ctx, out_mux_y, in_mux_p10, net); // inverting
find_and_bind_downhill_pip(ctx, out_mux_y, sb_big_d0, net);
find_and_bind_downhill_pip(ctx, sb_big_d0, sb_big_y2, net);
find_and_bind_downhill_pip(ctx, sb_big_y2, in_mux_p10, net);
}
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_p10_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P10.Y")));
auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D6")));
auto in_mux_p12_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.Y")));
auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7")));
auto in_mux_p04_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.Y")));
auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6")));
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_p10, in_mux_p10_y, net);
find_and_bind_downhill_pip(ctx, in_mux_p10_y, in_mux_p12, net);
find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p12_y, net);
find_and_bind_downhill_pip(ctx, in_mux_p12_y, in_mux_p04, net);
find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p04_y, net);
find_and_bind_downhill_pip(ctx, in_mux_p04_y, in_mux_p08, net);
route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8);
}
@ -385,48 +458,57 @@ void route_mult_x2y1_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc,
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_out1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1")));
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);
find_and_bind_downhill_pip(ctx, cpe_out1_int, cpe_out1, 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_p07_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P07.YDIAG")));
auto sb_big_p06_x23 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P06.X23")));
auto sb_big_p06_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P06.YDIAG")));
auto sb_big_p05_x23 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("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
auto sb_big_p05_y1 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P05.Y1")));
find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big_p07_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out1, 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);
find_and_bind_downhill_pip(ctx, sb_big_p07_ydiag, sb_big_p06_x23, net);
find_and_bind_downhill_pip(ctx, sb_big_p06_x23, sb_big_p06_ydiag, net);
find_and_bind_downhill_pip(ctx, sb_big_p06_ydiag, sb_big_p05_x23, net);
find_and_bind_downhill_pip(ctx, sb_big_p05_x23, 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, 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_p07_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P07.YDIAG")));
auto sb_sml_p06_x23 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("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_p06_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P06.YDIAG")));
auto sb_sml_p05_x23 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("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")));
auto sb_sml_p05_y1 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P05.Y1")));
find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_p07_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out1, 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_p07_ydiag, sb_sml_p06_x23, net);
find_and_bind_downhill_pip(ctx, sb_sml_p06_x23, 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_p06_ydiag, sb_sml_p05_x23, net);
find_and_bind_downhill_pip(ctx, sb_sml_p05_x23, 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, sb_sml_p05_y1, net);
find_and_bind_downhill_pip(ctx, sb_sml_p05_y1, in_mux, net);
}
route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5);
@ -443,48 +525,57 @@ void route_mult_x2y1_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc
auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT);
auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int")));
auto cpe_out2 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2")));
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);
find_and_bind_downhill_pip(ctx, cpe_out2_int, cpe_out2, 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_p03_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P03.YDIAG")));
auto sb_big_p02_x23 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P02.X23")));
auto sb_big_p02_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P02.YDIAG")));
auto sb_big_p01_x23 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("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
auto sb_big_p01_y1 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_BIG.P01.Y1")));
find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_p03_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out2, 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);
find_and_bind_downhill_pip(ctx, sb_big_p03_ydiag, sb_big_p02_x23, net);
find_and_bind_downhill_pip(ctx, sb_big_p02_x23, sb_big_p02_ydiag, net);
find_and_bind_downhill_pip(ctx, sb_big_p02_ydiag, sb_big_p01_x23, net);
find_and_bind_downhill_pip(ctx, sb_big_p01_x23, 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, 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_p03_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P03.YDIAG")));
auto sb_sml_p02_x23 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("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_p02_ydiag = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P02.YDIAG")));
auto sb_sml_p01_x23 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("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")));
auto sb_sml_p01_y1 = ctx->getWireByName(IdStringList::concat(x0y1, ctx->idf("SB_SML.P01.Y1")));
find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_p03_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out2, 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_p03_ydiag, sb_sml_p02_x23, net);
find_and_bind_downhill_pip(ctx, sb_sml_p02_x23, 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_p02_ydiag, sb_sml_p01_x23, net);
find_and_bind_downhill_pip(ctx, sb_sml_p01_x23, 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);
find_and_bind_downhill_pip(ctx, sb_sml_p01_y1_int, sb_sml_p01_y1, net);
find_and_bind_downhill_pip(ctx, sb_sml_p01_y1, in_mux, net);
}
route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1);
@ -502,6 +593,7 @@ void route_mult_x2y1_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc
auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT);
auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int")));
auto cpe_out2 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2")));
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")));
@ -509,30 +601,43 @@ void route_mult_x2y1_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc
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, cpe_out2_int, cpe_out2, net);
}
find_and_bind_downhill_pip(ctx, cpe_out2, 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")));
auto sb_sml_d0 = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("SB_SML.P09.D0")));
auto sb_sml_y1_int = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("SB_SML.P09.Y1_int")));
auto sb_sml_y1 = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("SB_SML.P09.Y1")));
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
find_and_bind_downhill_pip(ctx, out_mux_y, 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, 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
auto sb_big_d0 = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("SB_BIG.P09.D0")));
auto sb_big_y1 = ctx->getWireByName(IdStringList::concat(x1y2, ctx->idf("SB_BIG.P09.Y1")));
find_and_bind_downhill_pip(ctx, out_mux_y, in_mux_p09, net); // inverting
find_and_bind_downhill_pip(ctx, out_mux_y, 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, in_mux_p09, net);
}
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
auto in_mux_p09_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P09.Y")));
auto in_mux_p12 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.D7")));
auto in_mux_p12_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P12.Y")));
auto in_mux_p04 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.D7")));
auto in_mux_p04_y = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P04.Y")));
auto in_mux_p08 = ctx->getWireByName(IdStringList::concat(x2y2, ctx->idf("IM.P08.D6")));
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_p09, in_mux_p09_y, net);
find_and_bind_downhill_pip(ctx, in_mux_p09_y, in_mux_p12, net);
find_and_bind_downhill_pip(ctx, in_mux_p12, in_mux_p12_y, net);
find_and_bind_downhill_pip(ctx, in_mux_p12_y, in_mux_p04, net);
find_and_bind_downhill_pip(ctx, in_mux_p04, in_mux_p04_y, net);
find_and_bind_downhill_pip(ctx, in_mux_p04_y, in_mux_p08, net);
route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux_p08, 8);
}
@ -547,56 +652,67 @@ void route_mult_x2y2_lower(Context *ctx, NetInfo *net, CellInfo *lower, Loc loc,
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_out1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT1")));
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);
find_and_bind_downhill_pip(ctx, cpe_out1_int, cpe_out1, 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_p08_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P08.YDIAG")));
auto sb_sml_p07_x23 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("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_p07_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P07.YDIAG")));
auto sb_sml_p06_x23 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("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_p06_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P06.YDIAG")));
auto sb_sml_p05_x23 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("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")));
auto sb_sml_p05_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P05.Y1")));
find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_sml_p08_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out1, 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_p08_ydiag, sb_sml_p07_x23, net);
find_and_bind_downhill_pip(ctx, sb_sml_p07_x23, 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_p07_ydiag, sb_sml_p06_x23, net);
find_and_bind_downhill_pip(ctx, sb_sml_p06_x23, 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_p06_ydiag, sb_sml_p05_x23, net);
find_and_bind_downhill_pip(ctx, sb_sml_p05_x23, 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
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, 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_p08_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P08.YDIAG")));
auto sb_big_p07_x23 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P07.X23")));
auto sb_big_p07_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P07.YDIAG")));
auto sb_big_p06_x23 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P06.X23")));
auto sb_big_p06_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P06.YDIAG")));
auto sb_big_p05_x23 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("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
auto sb_big_p05_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P05.Y1")));
find_and_bind_downhill_pip(ctx, cpe_out1_int, sb_big_p08_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out1, 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);
find_and_bind_downhill_pip(ctx, sb_big_p08_ydiag, sb_big_p07_x23, net);
find_and_bind_downhill_pip(ctx, sb_big_p07_x23, sb_big_p07_ydiag, net);
find_and_bind_downhill_pip(ctx, sb_big_p07_ydiag, sb_big_p06_x23, net);
find_and_bind_downhill_pip(ctx, sb_big_p06_x23, sb_big_p06_ydiag, net);
find_and_bind_downhill_pip(ctx, sb_big_p06_ydiag, sb_big_p05_x23, net);
find_and_bind_downhill_pip(ctx, sb_big_p05_x23, 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, in_mux, net);
}
route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 5);
@ -612,56 +728,67 @@ void route_mult_x2y2_upper_in1(Context *ctx, NetInfo *net, CellInfo *upper, Loc
auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT);
auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int")));
auto cpe_out2 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2")));
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);
find_and_bind_downhill_pip(ctx, cpe_out2_int, cpe_out2, 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_p04_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P04.YDIAG")));
auto sb_sml_p03_x23 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("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_p03_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P03.YDIAG")));
auto sb_sml_p02_x23 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("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_p02_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P02.YDIAG")));
auto sb_sml_p01_x23 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("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")));
auto sb_sml_p01_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_SML.P01.Y1")));
find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_sml_p04_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out2, 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_p04_ydiag, sb_sml_p03_x23, net);
find_and_bind_downhill_pip(ctx, sb_sml_p03_x23, 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_p03_ydiag, sb_sml_p02_x23, net);
find_and_bind_downhill_pip(ctx, sb_sml_p02_x23, 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_p02_ydiag, sb_sml_p01_x23, net);
find_and_bind_downhill_pip(ctx, sb_sml_p01_x23, 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);
find_and_bind_downhill_pip(ctx, sb_sml_p01_y1_int, sb_sml_p01_y1, net);
find_and_bind_downhill_pip(ctx, sb_sml_p01_y1, 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_p04_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P04.YDIAG")));
auto sb_big_p03_x23 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P03.X23")));
auto sb_big_p03_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P03.YDIAG")));
auto sb_big_p02_x23 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P02.X23")));
auto sb_big_p02_ydiag = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P02.YDIAG")));
auto sb_big_p01_x23 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.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
auto sb_big_p01_y1 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("SB_BIG.P01.Y1")));
find_and_bind_downhill_pip(ctx, cpe_out2_int, sb_big_p04_d0, net);
find_and_bind_downhill_pip(ctx, cpe_out2, 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);
find_and_bind_downhill_pip(ctx, sb_big_p04_ydiag, sb_big_p03_x23, net);
find_and_bind_downhill_pip(ctx, sb_big_p03_x23, sb_big_p03_ydiag, net);
find_and_bind_downhill_pip(ctx, sb_big_p03_ydiag, sb_big_p02_x23, net);
find_and_bind_downhill_pip(ctx, sb_big_p02_x23, sb_big_p02_ydiag, net);
find_and_bind_downhill_pip(ctx, sb_big_p02_ydiag, sb_big_p01_x23, net);
find_and_bind_downhill_pip(ctx, sb_big_p01_x23, 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, in_mux, net);
}
route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y, 0}, in_mux, 1);
@ -680,45 +807,49 @@ void route_mult_x2y2_upper_in8(Context *ctx, NetInfo *net, CellInfo *upper, Loc
auto cpe_combout2 = ctx->getBelPinWire(upper->bel, id_OUT);
auto cpe_out2_int = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2_int")));
auto cpe_out2 = ctx->getWireByName(IdStringList::concat(x1y1, ctx->idf("CPE.OUT2")));
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);
}
find_and_bind_downhill_pip(ctx, cpe_out2_int, cpe_out2, 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_d2_1 = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_SML.P08.D2_1")));
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, 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_big_y1, sb_sml_d2_1, net);
find_and_bind_downhill_pip(ctx, sb_sml_d2_1, 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);
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_d2_1 = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_BIG.P08.D2_1")));
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
auto sb_big_y2 = ctx->getWireByName(IdStringList::concat(x2y0, ctx->idf("SB_BIG.P08.Y2")));
find_and_bind_downhill_pip(ctx, cpe_out2, 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_sml_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);
find_and_bind_downhill_pip(ctx, sb_big_ydiag, sb_big_y2, net);
find_and_bind_downhill_pip(ctx, sb_big_y2, in_mux, net);
}
route_mult_diag(ctx, net, Loc{loc.x + 1, loc.y + 1, 0}, in_mux, 8);