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:
parent
924f3a50ab
commit
c6f408dfa7
@ -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")
|
||||
|
||||
@ -2473,6 +2473,8 @@ X(1A)
|
||||
X(1B)
|
||||
X(2A)
|
||||
X(2B)
|
||||
X(DIE)
|
||||
X(GATEMATE_DIE)
|
||||
|
||||
// Timing
|
||||
X(timing_ADDF2x_IN5_8_comb2)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user