diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index 35f6e2d4..2a4a503a 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -179,112 +179,16 @@ bool GateMateImpl::getClusterPlacement(ClusterId cluster, BelId root_bel, return getChildPlacement(root_cell, root_loc, placement); } -void GateMateImpl::rename_param(CellInfo *cell, IdString name, IdString new_name, int width) -{ - if (cell->params.count(name)) { - cell->params[new_name] = Property(int_or_default(cell->params, name, 0), width); - cell->unsetParam(name); - } -} - void GateMateImpl::prePlace() { assign_cell_info(); } -void GateMateImpl::postPlace() +void GateMateImpl::postPlace() { repack(); } + +void GateMateImpl::preRoute() { ctx->assignArchInfo(); - std::vector delete_cells; - for (auto &cell : ctx->cells) { - if (cell.second->type.in(id_CPE_L2T4)) { - Loc l = ctx->getBelLocation(cell.second->bel); - if (l.z == CPE_LT_L_Z) { - if (!cell.second->params.count(id_INIT_L20)) - cell.second->params[id_INIT_L20] = Property(0b1100, 4); - } - cell.second->params[id_L2T4_UPPER] = Property((l.z == CPE_LT_U_Z) ? 1 : 0, 1); - } else if (cell.second->type.in(id_CPE_LT_L)) { - BelId bel = cell.second->bel; - PlaceStrength strength = cell.second->belStrength; - uint8_t func = int_or_default(cell.second->params, id_C_FUNCTION, 0); - Loc loc = ctx->getBelLocation(bel); - loc.z = CPE_LT_FULL_Z; - ctx->unbindBel(bel); - ctx->bindBel(ctx->getBelByLocation(loc), cell.second.get(), strength); - cell.second->renamePort(id_IN1, id_IN5); - cell.second->renamePort(id_IN2, id_IN6); - cell.second->renamePort(id_IN3, id_IN7); - cell.second->renamePort(id_IN4, id_IN8); - cell.second->renamePort(id_OUT, id_OUT1); - cell.second->renamePort(id_CPOUT, id_CPOUT1); - if (!cell.second->params.count(id_INIT_L20)) - cell.second->params[id_INIT_L20] = Property(0b1100, 4); - rename_param(cell.second.get(), id_INIT_L00, id_INIT_L02, 4); - rename_param(cell.second.get(), id_INIT_L01, id_INIT_L03, 4); - rename_param(cell.second.get(), id_INIT_L10, id_INIT_L11, 4); - - switch (func) { - case C_ADDF: - cell.second->type = id_CPE_ADDF; - break; - case C_ADDF2: - cell.second->type = id_CPE_ADDF2; - break; - case C_MULT: - cell.second->type = id_CPE_MULT; - break; - case C_MX4: - cell.second->type = id_CPE_MX4; - break; - case C_EN_CIN: - log_error("EN_CIN should be using L2T4.\n"); - break; - case C_CONCAT: - cell.second->type = id_CPE_CONCAT; - break; - case C_ADDCIN: - log_error("ADDCIN should be using L2T4.\n"); - break; - default: - break; - } - - loc.z = CPE_LT_U_Z; - CellInfo *upper = ctx->getBoundBelCell(ctx->getBelByLocation(loc)); - if (upper->params.count(id_INIT_L00)) - cell.second->params[id_INIT_L00] = Property(int_or_default(upper->params, id_INIT_L00, 0), 4); - if (upper->params.count(id_INIT_L01)) - cell.second->params[id_INIT_L01] = Property(int_or_default(upper->params, id_INIT_L01, 0), 4); - if (upper->params.count(id_INIT_L10)) - cell.second->params[id_INIT_L10] = Property(int_or_default(upper->params, id_INIT_L10, 0), 4); - if (upper->params.count(id_C_I1)) - cell.second->params[id_C_I1] = Property(int_or_default(upper->params, id_C_I1, 0), 1); - if (upper->params.count(id_C_I2)) - cell.second->params[id_C_I2] = Property(int_or_default(upper->params, id_C_I2, 0), 1); - upper->movePortTo(id_IN1, cell.second.get(), id_IN1); - upper->movePortTo(id_IN2, cell.second.get(), id_IN2); - upper->movePortTo(id_IN3, cell.second.get(), id_IN3); - upper->movePortTo(id_IN4, cell.second.get(), id_IN4); - upper->movePortTo(id_OUT, cell.second.get(), id_OUT2); - upper->movePortTo(id_CPOUT, cell.second.get(), id_CPOUT2); - - } - // Mark for deletion - else if (cell.second->type.in(id_CPE_LT_U, id_CPE_DUMMY)) { - delete_cells.push_back(cell.second->name); - } - } - for (auto pcell : delete_cells) { - for (auto &port : ctx->cells[pcell]->ports) { - ctx->cells[pcell]->disconnectPort(port.first); - } - ctx->unbindBel(ctx->cells[pcell]->bel); - ctx->cells.erase(pcell); - } - delete_cells.clear(); - ctx->assignArchInfo(); + route_clock(); } -void GateMateImpl::preRoute() { route_clock(); } - void GateMateImpl::postRoute() { ctx->assignArchInfo(); diff --git a/himbaechel/uarch/gatemate/gatemate.h b/himbaechel/uarch/gatemate/gatemate.h index f63b38c6..d2b16dca 100644 --- a/himbaechel/uarch/gatemate/gatemate.h +++ b/himbaechel/uarch/gatemate/gatemate.h @@ -63,7 +63,6 @@ struct GateMateImpl : HimbaechelAPI bool isPipInverting(PipId pip) const override; const GateMateTileExtraDataPOD *tile_extra_data(int tile) const; - void rename_param(CellInfo *cell, IdString name, IdString new_name, int width); std::set available_pads; std::map bel_to_pad; @@ -83,6 +82,7 @@ struct GateMateImpl : HimbaechelAPI void assign_cell_info(); void route_clock(); + void repack(); const GateMateBelExtraDataPOD *bel_extra_data(BelId bel) const; diff --git a/himbaechel/uarch/gatemate/pack.cc b/himbaechel/uarch/gatemate/pack.cc index 906b665b..37f1e811 100644 --- a/himbaechel/uarch/gatemate/pack.cc +++ b/himbaechel/uarch/gatemate/pack.cc @@ -26,12 +26,14 @@ NEXTPNR_NAMESPACE_BEGIN -void GateMatePacker::flush_cells() +void GateMatePacker::flush_cells(bool unbind) { for (auto pcell : packed_cells) { for (auto &port : ctx->cells[pcell]->ports) { ctx->cells[pcell]->disconnectPort(port.first); } + if (unbind) + ctx->unbindBel(ctx->cells[pcell]->bel); ctx->cells.erase(pcell); } packed_cells.clear(); @@ -347,6 +349,98 @@ void GateMatePacker::cleanup() } while (count != 0); } +void GateMatePacker::rename_param(CellInfo *cell, IdString name, IdString new_name, int width) +{ + if (cell->params.count(name)) { + cell->params[new_name] = Property(int_or_default(cell->params, name, 0), width); + cell->unsetParam(name); + } +} + +void GateMatePacker::repack() +{ + for (auto &cell : ctx->cells) { + if (cell.second->type.in(id_CPE_L2T4)) { + Loc l = ctx->getBelLocation(cell.second->bel); + if (l.z == CPE_LT_L_Z) { + if (!cell.second->params.count(id_INIT_L20)) + cell.second->params[id_INIT_L20] = Property(LUT_D1, 4); + } + cell.second->params[id_L2T4_UPPER] = Property((l.z == CPE_LT_U_Z) ? 1 : 0, 1); + } else if (cell.second->type.in(id_CPE_LT_L)) { + BelId bel = cell.second->bel; + PlaceStrength strength = cell.second->belStrength; + uint8_t func = int_or_default(cell.second->params, id_C_FUNCTION, 0); + Loc loc = ctx->getBelLocation(bel); + loc.z = CPE_LT_FULL_Z; + ctx->unbindBel(bel); + ctx->bindBel(ctx->getBelByLocation(loc), cell.second.get(), strength); + cell.second->renamePort(id_IN1, id_IN5); + cell.second->renamePort(id_IN2, id_IN6); + cell.second->renamePort(id_IN3, id_IN7); + cell.second->renamePort(id_IN4, id_IN8); + cell.second->renamePort(id_OUT, id_OUT1); + cell.second->renamePort(id_CPOUT, id_CPOUT1); + if (!cell.second->params.count(id_INIT_L20)) + cell.second->params[id_INIT_L20] = Property(LUT_D1, 4); + rename_param(cell.second.get(), id_INIT_L00, id_INIT_L02, 4); + rename_param(cell.second.get(), id_INIT_L01, id_INIT_L03, 4); + rename_param(cell.second.get(), id_INIT_L10, id_INIT_L11, 4); + + switch (func) { + case C_ADDF: + cell.second->type = id_CPE_ADDF; + break; + case C_ADDF2: + cell.second->type = id_CPE_ADDF2; + break; + case C_MULT: + cell.second->type = id_CPE_MULT; + break; + case C_MX4: + cell.second->type = id_CPE_MX4; + break; + case C_EN_CIN: + log_error("EN_CIN should be using L2T4.\n"); + break; + case C_CONCAT: + cell.second->type = id_CPE_CONCAT; + break; + case C_ADDCIN: + log_error("ADDCIN should be using L2T4.\n"); + break; + default: + break; + } + + loc.z = CPE_LT_U_Z; + CellInfo *upper = ctx->getBoundBelCell(ctx->getBelByLocation(loc)); + if (upper->params.count(id_INIT_L00)) + cell.second->params[id_INIT_L00] = Property(int_or_default(upper->params, id_INIT_L00, 0), 4); + if (upper->params.count(id_INIT_L01)) + cell.second->params[id_INIT_L01] = Property(int_or_default(upper->params, id_INIT_L01, 0), 4); + if (upper->params.count(id_INIT_L10)) + cell.second->params[id_INIT_L10] = Property(int_or_default(upper->params, id_INIT_L10, 0), 4); + if (upper->params.count(id_C_I1)) + cell.second->params[id_C_I1] = Property(int_or_default(upper->params, id_C_I1, 0), 1); + if (upper->params.count(id_C_I2)) + cell.second->params[id_C_I2] = Property(int_or_default(upper->params, id_C_I2, 0), 1); + upper->movePortTo(id_IN1, cell.second.get(), id_IN1); + upper->movePortTo(id_IN2, cell.second.get(), id_IN2); + upper->movePortTo(id_IN3, cell.second.get(), id_IN3); + upper->movePortTo(id_IN4, cell.second.get(), id_IN4); + upper->movePortTo(id_OUT, cell.second.get(), id_OUT2); + upper->movePortTo(id_CPOUT, cell.second.get(), id_CPOUT2); + + } + // Mark for deletion + else if (cell.second->type.in(id_CPE_LT_U, id_CPE_DUMMY)) { + packed_cells.insert(cell.second->name); + } + } + flush_cells(true); +} + void GateMateImpl::pack() { const ArchArgs &args = ctx->args; @@ -373,4 +467,10 @@ void GateMateImpl::pack() packer.remove_clocking(); } +void GateMateImpl::repack() +{ + GateMatePacker packer(ctx, this); + packer.repack(); +} + NEXTPNR_NAMESPACE_END diff --git a/himbaechel/uarch/gatemate/pack.h b/himbaechel/uarch/gatemate/pack.h index 4a648312..28123f2e 100644 --- a/himbaechel/uarch/gatemate/pack.h +++ b/himbaechel/uarch/gatemate/pack.h @@ -67,8 +67,10 @@ struct GateMatePacker void remove_not_used(); void cleanup(); + void repack(); private: + void rename_param(CellInfo *cell, IdString name, IdString new_name, int width); void dff_to_cpe(CellInfo *dff); void insert_bufg(CellInfo *cell, IdString port); void disconnect_if_gnd(CellInfo *cell, IdString input); @@ -93,7 +95,7 @@ struct GateMatePacker bool is_gpio_valid_dff(CellInfo *dff); // Cell creating CellInfo *create_cell_ptr(IdString type, IdString name); - void flush_cells(); + void flush_cells(bool unbind = false); void pack_ram_cell(CellInfo &ci, CellInfo *cell, int num, bool is_split); void copy_constraint(NetInfo *in_net, NetInfo *out_net); diff --git a/himbaechel/uarch/gatemate/pack_cpe.cc b/himbaechel/uarch/gatemate/pack_cpe.cc index b531dadb..0c93c0b6 100644 --- a/himbaechel/uarch/gatemate/pack_cpe.cc +++ b/himbaechel/uarch/gatemate/pack_cpe.cc @@ -157,9 +157,9 @@ void GateMatePacker::pack_cpe() ci.renamePort(id_I3, id_IN4); ci.renamePort(id_O, id_OUT); - uarch->rename_param(&ci, id_INIT_L02, id_INIT_L00, 4); - uarch->rename_param(&ci, id_INIT_L03, id_INIT_L01, 4); - uarch->rename_param(&ci, id_INIT_L11, id_INIT_L10, 4); + rename_param(&ci, id_INIT_L02, id_INIT_L00, 4); + rename_param(&ci, id_INIT_L03, id_INIT_L01, 4); + rename_param(&ci, id_INIT_L11, id_INIT_L10, 4); ci.cluster = ci.name; ci.constr_abs_z = true; ci.constr_z = CPE_LT_L_Z;