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

gatemate: additional region handling (#1583)

* gatemate: Use GATEMATE_DIE attribute to select placement die

* add DIE parameter in CCF

* add penalty delay when crossing between dies

* Add predictDelay
This commit is contained in:
Miodrag Milanović 2025-10-21 13:47:07 +02:00 committed by GitHub
parent 924f3a50ab
commit c6f408dfa7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 92 additions and 17 deletions

View File

@ -69,7 +69,7 @@ struct GateMateCCFReader
boost::algorithm::to_upper(name);
if (expr.size() != 2) {
if (name == "LOC" || name == "DRIVE" || name == "DELAY_IBF" || name == "DELAY_OBF")
if (name == "LOC" || name == "DRIVE" || name == "DELAY_IBF" || name == "DELAY_OBF" || name == "DIE")
log_error("Parameter must be in form NAME=VALUE (on line %d)\n", lineno);
log_warning("Parameter '%s' missing value, defaulting to '1' (on line %d)\n", name.c_str(), lineno);
expr.push_back("1");
@ -99,6 +99,12 @@ struct GateMateCCFReader
uarch->available_pads.erase(ctx->id("SER_CLK_N"));
if (value == "SER_CLK_N")
uarch->available_pads.erase(ctx->id("SER_CLK"));
} else if (name == "DIE") {
if (uarch->die_to_index.count(ctx->id(value))) {
props->emplace(ctx->id(name), Property(value));
} else
log_error("Uknown value '%s' for parameter '%s' in line %d.\n", value.c_str(), name.c_str(),
lineno);
} else if (name == "SCHMITT_TRIGGER" || name == "PULLUP" || name == "PULLDOWN" || name == "KEEPER" ||
name == "FF_IBF" || name == "FF_OBF" || name == "LVDS_BOOST" || name == "LVDS_RTERM") {
if (value == "1")

View File

@ -2473,6 +2473,8 @@ X(1A)
X(1B)
X(2A)
X(2B)
X(DIE)
X(GATEMATE_DIE)
// Timing
X(timing_ADDF2x_IN5_8_comb2)

View File

@ -30,10 +30,23 @@ NEXTPNR_NAMESPACE_BEGIN
delay_t GateMateImpl::estimateDelay(WireId src, WireId dst) const
{
int sx, sy, dx, dy;
int d2d = 0;
if (tile_extra_data(src.tile)->die != tile_extra_data(dst.tile)->die)
d2d += 2000;
tile_xy(ctx->chip_info, src.tile, sx, sy);
tile_xy(ctx->chip_info, dst.tile, dx, dy);
return 100 + 100 * (std::abs(dx - sx) + std::abs(dy - sy));
return 100 + 100 * (std::abs(dx - sx) + std::abs(dy - sy)) + d2d;
}
delay_t GateMateImpl::predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const
{
int d2d = 0;
if (tile_extra_data(src_bel.tile)->die != tile_extra_data(dst_bel.tile)->die)
d2d += 2000;
Loc src_loc = ctx->getBelLocation(src_bel), dst_loc = ctx->getBelLocation(dst_bel);
return 100 + 100 * (std::abs(dst_loc.x - src_loc.x) + std::abs(dst_loc.y - src_loc.y)) + d2d;
}
bool GateMateImpl::get_delay_from_tmg_db(IdString id, DelayQuad &delay) const

View File

@ -58,6 +58,7 @@ struct GateMateImpl : HimbaechelAPI
bool isBelLocationValid(BelId bel, bool explain_invalid = false) const override;
delay_t estimateDelay(WireId src, WireId dst) const override;
delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const override;
bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const override;
TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const override;
TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const override;
@ -106,6 +107,7 @@ struct GateMateImpl : HimbaechelAPI
pool<IdString> ignore;
MultiDieStrategy strategy;
dict<int, IdString> index_to_die;
dict<IdString, int> die_to_index;
private:
bool getChildPlacement(const BaseClusterInfo *cluster, Loc root_loc,
@ -139,7 +141,6 @@ struct GateMateImpl : HimbaechelAPI
std::map<IdString, const GateMateTimingExtraDataPOD *> timing;
dict<IdString, int> ram_signal_clk;
IdString forced_die;
dict<IdString, int> die_to_index;
};
NEXTPNR_NAMESPACE_END

View File

@ -420,10 +420,35 @@ void GateMatePacker::assign_clocks()
if (user.cell->region && user.cell->region->name != die)
log_error("Trying to assign cell '%s' to multiple regions.\n", user.cell->name.c_str(ctx));
ctx->constrainCellToRegion(user.cell->name, die);
if (user.cell->cluster != ClusterId()) {
CellInfo *root = ctx->getClusterRootCell(user.cell->cluster);
recursiveAddToRegion(root, die);
}
}
}
}
void GateMatePacker::assign_regions()
{
log_info("Assign cell region based on attributes..\n");
for (auto &cell : ctx->cells) {
CellInfo &ci = *cell.second;
if (ci.attrs.count(id_GATEMATE_DIE) != 0) {
std::string die_name = str_or_default(ci.attrs, id_GATEMATE_DIE, "");
IdString die = ctx->id(die_name);
if (!uarch->die_to_index.count(die))
log_error("Trying to assign cell '%s' to non existing die '%s'.\n", ci.name.c_str(ctx), die.c_str(ctx));
if (ci.region && ci.region->name != die)
log_error("Trying to assign cell '%s' to multiple regions.\n", ci.name.c_str(ctx));
ctx->constrainCellToRegion(ci.name, die);
}
}
}
void GateMatePacker::fix_regions()
{
log_info("Fix cell assigned regions..\n");
for (auto &cell : ctx->cells) {
CellInfo &ci = *cell.second;
if (ci.region && ci.cluster != ClusterId()) {
CellInfo *root = ctx->getClusterRootCell(ci.cluster);
recursiveAddToRegion(root, ci.region->name);
}
}
}
@ -487,6 +512,8 @@ void GateMateImpl::pack()
preferred_die = 0;
GateMatePacker packer(ctx, this);
if (forced_die == IdString())
packer.assign_regions();
packer.pack_constants();
packer.cleanup();
packer.pack_io();
@ -503,16 +530,15 @@ void GateMateImpl::pack()
packer.copy_clocks();
packer.remove_constants();
packer.remove_double_constrained();
if (forced_die != IdString()) {
for (auto &cell : ctx->cells) {
if (cell.second->belStrength != PlaceStrength::STRENGTH_FIXED)
ctx->constrainCellToRegion(cell.second->name, forced_die);
}
}
if (strategy == MultiDieStrategy::FULL_USE)
packer.assign_clocks();
packer.fix_regions();
}
void GateMateImpl::repack()

View File

@ -72,6 +72,8 @@ struct GateMatePacker
void reassign_clocks();
void copy_clocks();
void assign_clocks();
void assign_regions();
void fix_regions();
private:
void rename_param(CellInfo *cell, IdString name, IdString new_name, int width);
@ -93,6 +95,7 @@ struct GateMatePacker
void strategy_clk1();
void strategy_full();
void override_region(CellInfo *first, CellInfo *second);
void recursiveAddToRegion(CellInfo *root, IdString die);
PllCfgRecord get_pll_settings(double f_ref, double f_core, int mode, int low_jitter, bool pdiv0_mux, bool feedback);

View File

@ -166,6 +166,18 @@ void GateMatePacker::dff_update_params()
}
}
void GateMatePacker::override_region(CellInfo *first, CellInfo *second)
{
if (first->region) {
if (second->region && second->region->name != first->region->name) {
log_warning("Unable to place cell '%s' in '%s' region\n", first->name.c_str(ctx),
first->region->name.c_str(ctx));
}
} else {
second->region = first->region;
}
}
void GateMatePacker::pack_cpe()
{
log_info("Packing CPEs..\n");
@ -173,7 +185,7 @@ void GateMatePacker::pack_cpe()
auto merge_dff = [&](CellInfo &ci, CellInfo *dff) {
dff->cluster = ci.name;
dff->region = ci.region;
override_region(dff, &ci);
dff->constr_abs_z = false;
dff->constr_z = +2;
ci.cluster = ci.name;
@ -520,7 +532,7 @@ void GateMatePacker::pack_addf()
CellInfo *dff = net_only_drives(ctx, o, is_dff, id_D, true);
if (dff && are_ffs_compatible(dff, other)) {
dff->cluster = cell->cluster;
dff->region = cell->region;
override_region(dff, cell);
dff->constr_abs_z = false;
dff->constr_z = +2;
cell->constr_children.push_back(dff);
@ -589,7 +601,7 @@ void GateMatePacker::pack_addf()
CellInfo *cy = grp.at(i);
if (i != 0) {
cy->cluster = root->name;
cy->region = root->region;
override_region(cy, root);
root->constr_children.push_back(cy);
cy->constr_abs_z = false;
cy->constr_y = +i;

View File

@ -28,7 +28,7 @@ std::string get_die_name(int total_dies, int die)
{
if (total_dies == 1)
return "";
return stringf("on die '%d%c'", int(die / total_dies) + 1, 'A' + int(die % total_dies));
return stringf(" on die '%d%c'", int(die / total_dies) + 1, 'A' + int(die % total_dies));
}
void GateMatePacker::pack_io()
@ -187,6 +187,8 @@ void GateMatePacker::pack_io()
keys.push_back(p.first);
continue;
}
if (p.first.in(id_DIE))
continue;
if (ci.type.in(id_CC_IBUF, id_CC_IOBUF) &&
p.first.in(id_PULLUP, id_PULLDOWN, id_KEEPER, id_SCHMITT_TRIGGER, id_DELAY_IBF, id_FF_IBF))
continue;
@ -305,10 +307,20 @@ void GateMatePacker::pack_io()
}
BelId bel;
if (uarch->locations.count(std::make_pair(ctx->id(loc), uarch->preferred_die)))
bel = ctx->getBelByLocation(uarch->locations[std::make_pair(ctx->id(loc), uarch->preferred_die)]);
else
bel = ctx->get_package_pin_bel(ctx->id(loc));
if (ci.params.count(id_DIE)) {
std::string die_name = str_or_default(ci.params, id_DIE, "");
int die = uarch->die_to_index[ctx->id(die_name)];
ci.unsetParam(id_DIE);
if (uarch->locations.count(std::make_pair(ctx->id(loc), die)))
bel = ctx->getBelByLocation(uarch->locations[std::make_pair(ctx->id(loc), die)]);
else
log_error("Unable to place '%s' to specified '%s' die.\n", ci.name.c_str(ctx), die_name.c_str());
} else {
if (uarch->locations.count(std::make_pair(ctx->id(loc), uarch->preferred_die)))
bel = ctx->getBelByLocation(uarch->locations[std::make_pair(ctx->id(loc), uarch->preferred_die)]);
else
bel = ctx->get_package_pin_bel(ctx->id(loc));
}
if (bel == BelId())
log_error("Unable to constrain IO '%s', device does not have a pin named '%s'\n", ci.name.c_str(ctx),
loc.c_str());