gatemate: pack output flops for multipliers

This commit is contained in:
Lofty 2025-11-19 16:46:41 +00:00
parent c228475a71
commit 0b8201ac88
1 changed files with 37 additions and 0 deletions

View File

@ -916,6 +916,43 @@ void GateMatePacker::pack_mult()
auto *cpe_half = (p % 2 == 1) ? mult_cell.upper : mult_cell.lower;
mult->movePortTo(ctx->idf("P[%d]", p), cpe_half, id_CPOUT);
auto *cpe_half_cpout = cpe_half->getPort(id_CPOUT);
if (cpe_half_cpout && cpe_half_cpout->users.entries() == 1) {
auto cpe_half_cpout_user = *cpe_half_cpout->users.begin();
auto *dff = cpe_half_cpout_user.cell;
NPNR_ASSERT(dff != nullptr);
if (dff->type == id_CC_DFF) {
// Instantiate a P passthrough L2T4 for the flop.
auto *p_passthru =
create_cell_ptr(id_CPE_L2T4, ctx->idf("%s$p[%d]_passthru", cpe_half->name.c_str(ctx), p));
p_passthru->params[id_INIT_L00] = Property(LUT_D0, 4); // IN5
p_passthru->params[id_INIT_L01] = Property(LUT_ZERO, 4); // (unused)
p_passthru->params[id_INIT_L10] = Property(LUT_D0, 4); // L02
// Reconfigure the flop.
dff->renamePort(id_D, id_DIN);
dff->renamePort(id_Q, id_DOUT);
dff->type = id_CPE_FF;
// Connect the passthrough.
dff->movePortTo(id_DIN, p_passthru, id_IN1);
auto *p_passthru_net = ctx->createNet(ctx->idf("%s$p", p_passthru->name.c_str(ctx)));
p_passthru->connectPort(id_OUT, p_passthru_net);
dff->connectPort(id_DIN, p_passthru_net);
// Constrain the passthrough and flop.
constrain_cell(p_passthru, b_width / 2, b_width / 2 + p / 2,
(p % 2 == 1) ? CPE_LT_U_Z : CPE_LT_L_Z);
constrain_cell(dff, b_width / 2, b_width / 2 + p / 2, (p % 2 == 1) ? CPE_FF_U_Z : CPE_FF_L_Z);
log_info(" Constrained '%s' as register for P[%d] at (%d, %d).\n", dff->name.c_str(ctx), p,
b_width / 2, b_width / 2 + p / 2);
}
}
}
for (int p = 0; p < vertical_p_width; p++) {