mirror of https://github.com/YosysHQ/nextpnr.git
Implement full use strategy
This commit is contained in:
parent
0e61a373d1
commit
587c5e086d
|
|
@ -162,6 +162,7 @@ void GateMateImpl::init(Context *ctx)
|
|||
int index = 0;
|
||||
for (auto &die : extra->dies) {
|
||||
IdString name(die.name);
|
||||
index_to_die[index] = name;
|
||||
die_to_index[name] = index++;
|
||||
ctx->createRectangularRegion(name, die.x1, die.y1, die.x2, die.y2);
|
||||
if (die_name == name.c_str(ctx)) {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,13 @@
|
|||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
enum MultiDieStrategy
|
||||
{
|
||||
CLOCK_MIRROR,
|
||||
REUSE_CLK1,
|
||||
FULL_USE,
|
||||
};
|
||||
|
||||
struct GateMateImpl : HimbaechelAPI
|
||||
{
|
||||
~GateMateImpl();
|
||||
|
|
@ -97,6 +104,8 @@ struct GateMateImpl : HimbaechelAPI
|
|||
std::vector<CellInfo *> glbout;
|
||||
std::vector<CellInfo *> pll;
|
||||
pool<IdString> ignore;
|
||||
MultiDieStrategy strategy;
|
||||
dict<int, IdString> index_to_die;
|
||||
|
||||
private:
|
||||
bool getChildPlacement(const BaseClusterInfo *cluster, Loc root_loc,
|
||||
|
|
|
|||
|
|
@ -397,6 +397,37 @@ void GateMatePacker::remove_double_constrained()
|
|||
}
|
||||
}
|
||||
|
||||
void GateMatePacker::recursiveAddToRegion(CellInfo *root, IdString die)
|
||||
{
|
||||
if (root->region && root->region->name != die)
|
||||
log_error("Trying to assing cell '%s' to multiple regions.\n", root->name.c_str(ctx));
|
||||
ctx->constrainCellToRegion(root->name, die);
|
||||
for (auto cell : root->constr_children) {
|
||||
if (cell->region && cell->region->name != die)
|
||||
log_error("Trying to assing cell '%s' to multiple regions.\n", cell->name.c_str(ctx));
|
||||
ctx->constrainCellToRegion(cell->name, die);
|
||||
recursiveAddToRegion(cell, die);
|
||||
}
|
||||
}
|
||||
|
||||
void GateMatePacker::assign_clocks()
|
||||
{
|
||||
log_info("Assign cells based on clock..\n");
|
||||
for (auto &glob : uarch->global_signals) {
|
||||
const NetInfo *net = glob.first;
|
||||
for (auto &user : net->users) {
|
||||
IdString die = uarch->index_to_die[uarch->tile_extra_data(net->driver.cell->bel.tile)->die];
|
||||
if (user.cell->region && user.cell->region->name != die)
|
||||
log_error("Trying to assing 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 GateMateImpl::pack()
|
||||
{
|
||||
const ArchArgs &args = ctx->args;
|
||||
|
|
@ -404,7 +435,6 @@ void GateMateImpl::pack()
|
|||
parse_ccf(args.options.at("ccf"));
|
||||
}
|
||||
|
||||
MultiDieStrategy strategy;
|
||||
if (args.options.count("multi")) {
|
||||
std::string val = args.options.at("multi");
|
||||
if (val == "mirror") {
|
||||
|
|
@ -413,8 +443,11 @@ void GateMateImpl::pack()
|
|||
} else if (val == "clk1") {
|
||||
strategy = MultiDieStrategy::REUSE_CLK1;
|
||||
log_info("Multidie mode: REUSE CLK1\n");
|
||||
} else if (val == "full") {
|
||||
strategy = MultiDieStrategy::FULL_USE;
|
||||
log_info("Multidie mode: FULL USE\n");
|
||||
} else {
|
||||
log_error("Unknown value for 'multi' option. Allowed values are 'mirror' and 'clk1'.\n");
|
||||
log_error("Unknown value for 'multi' option. Allowed values are 'mirror', 'full' and 'clk1'.\n");
|
||||
}
|
||||
} else {
|
||||
strategy = MultiDieStrategy::CLOCK_MIRROR;
|
||||
|
|
@ -422,14 +455,16 @@ void GateMateImpl::pack()
|
|||
log_warning("Multi die clock placement strategy set to 'mirror'.\n");
|
||||
}
|
||||
|
||||
if (forced_die != IdString())
|
||||
if (forced_die != IdString()) {
|
||||
preferred_die = die_to_index[forced_die];
|
||||
if (strategy == MultiDieStrategy::FULL_USE)
|
||||
log_error("Not allowed to use forced die in FULL USE mode.\n");
|
||||
}
|
||||
|
||||
if (strategy == MultiDieStrategy::REUSE_CLK1)
|
||||
if (strategy == MultiDieStrategy::REUSE_CLK1 || strategy == MultiDieStrategy::FULL_USE)
|
||||
preferred_die = 0;
|
||||
|
||||
GateMatePacker packer(ctx, this);
|
||||
packer.set_strategy(strategy);
|
||||
packer.pack_constants();
|
||||
packer.cleanup();
|
||||
packer.pack_io();
|
||||
|
|
@ -453,6 +488,9 @@ void GateMateImpl::pack()
|
|||
ctx->constrainCellToRegion(cell.second->name, forced_die);
|
||||
}
|
||||
}
|
||||
|
||||
if (strategy == MultiDieStrategy::FULL_USE)
|
||||
packer.assign_clocks();
|
||||
}
|
||||
|
||||
void GateMateImpl::repack()
|
||||
|
|
@ -460,7 +498,8 @@ void GateMateImpl::repack()
|
|||
GateMatePacker packer(ctx, this);
|
||||
packer.repack_ram();
|
||||
packer.repack_cpe();
|
||||
packer.reassign_clocks();
|
||||
if (strategy != MultiDieStrategy::FULL_USE)
|
||||
packer.reassign_clocks();
|
||||
packer.remove_clocking();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,12 +44,6 @@ enum CPELut
|
|||
LUT_ONE = 0b1111
|
||||
};
|
||||
|
||||
enum MultiDieStrategy
|
||||
{
|
||||
CLOCK_MIRROR,
|
||||
REUSE_CLK1,
|
||||
};
|
||||
|
||||
struct GateMatePacker
|
||||
{
|
||||
GateMatePacker(Context *ctx, GateMateImpl *uarch) : ctx(ctx), uarch(uarch) { h.init(ctx); };
|
||||
|
|
@ -59,7 +53,7 @@ struct GateMatePacker
|
|||
void pack_cpe();
|
||||
void pack_addf();
|
||||
void pack_bufg();
|
||||
void sort_bufg();
|
||||
void sort_bufg(unsigned max_num);
|
||||
void insert_clocking();
|
||||
void pack_pll();
|
||||
void pack_misc();
|
||||
|
|
@ -77,8 +71,7 @@ struct GateMatePacker
|
|||
void repack_ram();
|
||||
void reassign_clocks();
|
||||
void copy_clocks();
|
||||
|
||||
void set_strategy(MultiDieStrategy strategy) { this->strategy = strategy; }
|
||||
void assign_clocks();
|
||||
|
||||
private:
|
||||
void rename_param(CellInfo *cell, IdString name, IdString new_name, int width);
|
||||
|
|
@ -98,6 +91,9 @@ struct GateMatePacker
|
|||
|
||||
void strategy_mirror();
|
||||
void strategy_clk1();
|
||||
void strategy_full();
|
||||
|
||||
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);
|
||||
|
||||
|
|
@ -132,7 +128,6 @@ struct GateMatePacker
|
|||
NetInfo *net_SER_CLK;
|
||||
int count;
|
||||
std::map<IdString, int> count_per_type;
|
||||
MultiDieStrategy strategy;
|
||||
};
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ NEXTPNR_NAMESPACE_BEGIN
|
|||
|
||||
inline bool is_bufg(const BaseCtx *ctx, const CellInfo *cell) { return cell->type.in(id_CC_BUFG); }
|
||||
|
||||
void GateMatePacker::sort_bufg()
|
||||
void GateMatePacker::sort_bufg(unsigned max_num)
|
||||
{
|
||||
struct ItemBufG
|
||||
{
|
||||
|
|
@ -61,8 +61,8 @@ void GateMatePacker::sort_bufg()
|
|||
bufg.push_back(ItemBufG(&ci, o_net->users.entries()));
|
||||
}
|
||||
|
||||
if (bufg.size() > 4) {
|
||||
log_warning("More than 4 BUFG used. Those with highest fan-out will be used.\n");
|
||||
if (bufg.size() > max_num) {
|
||||
log_warning("More than %d BUFG used. Those with highest fan-out will be used.\n", max_num);
|
||||
std::sort(bufg.begin(), bufg.end(), [](const ItemBufG &a, const ItemBufG &b) { return a.fan_out > b.fan_out; });
|
||||
for (size_t i = 4; i < bufg.size(); i++) {
|
||||
log_warning("Removing BUFG cell %s.\n", bufg.at(i).cell->name.c_str(ctx));
|
||||
|
|
@ -92,7 +92,7 @@ static int glb_mux_mapping[] = {
|
|||
|
||||
void GateMatePacker::pack_bufg()
|
||||
{
|
||||
sort_bufg();
|
||||
sort_bufg(uarch->strategy == MultiDieStrategy::FULL_USE ? 4 * uarch->dies : 4);
|
||||
|
||||
log_info("Packing BUFGs..\n");
|
||||
auto update_bufg_port = [&](std::vector<CellInfo *> &bufg, CellInfo *cell, int port_num, int pll_num) {
|
||||
|
|
@ -682,7 +682,7 @@ void GateMatePacker::copy_clocks()
|
|||
{
|
||||
if (uarch->dies == 1)
|
||||
return;
|
||||
switch (strategy) {
|
||||
switch (uarch->strategy) {
|
||||
case MultiDieStrategy::REUSE_CLK1:
|
||||
if (uarch->global_signals.size() > 1 || uarch->pll.size() > 1)
|
||||
log_error("Unable to use REUSE CLK1 strategy when there is more than one clock/PLL.\n");
|
||||
|
|
@ -693,6 +693,48 @@ void GateMatePacker::copy_clocks()
|
|||
log_error("Unable to use MIRROR CLOCK strategy when there is more than 4 clocks/PLLs.\n");
|
||||
strategy_mirror();
|
||||
break;
|
||||
case MultiDieStrategy::FULL_USE:
|
||||
strategy_full();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GateMatePacker::strategy_full()
|
||||
{
|
||||
log_info("All resources for clock distribution..\n");
|
||||
|
||||
for (int new_die = 1; new_die < uarch->dies; new_die++) {
|
||||
// Create appropriate GPIO and IOSEL cells
|
||||
for (int i = 0; i < 4; i++) {
|
||||
NetInfo *in_net = uarch->clkin[new_die]->getPort(ctx->idf("CLK%d", i));
|
||||
if (in_net && in_net->driver.cell) {
|
||||
CellInfo *iosel = in_net->driver.cell;
|
||||
auto pad_info = uarch->bel_to_pad[iosel->bel];
|
||||
Loc l = uarch->locations[std::make_pair(IdString(pad_info->package_pin), new_die)];
|
||||
CellInfo *iosel_new = ctx->getBoundBelCell(ctx->getBelByLocation(l));
|
||||
if (!iosel_new) {
|
||||
iosel_new = create_cell_ptr(iosel->type, ctx->idf("%s$die%d", iosel->name.c_str(ctx), new_die));
|
||||
iosel_new->params = iosel->params;
|
||||
ctx->bindBel(ctx->getBelByLocation(l), iosel_new, PlaceStrength::STRENGTH_FIXED);
|
||||
|
||||
CellInfo *gpio = iosel->getPort(id_GPIO_IN)->driver.cell;
|
||||
CellInfo *gpio_new =
|
||||
create_cell_ptr(gpio->type, ctx->idf("%s$die%d", gpio->name.c_str(ctx), new_die));
|
||||
gpio_new->params = gpio->params;
|
||||
ctx->bindBel(ctx->getBelByLocation({l.x, l.y, 0}), gpio_new, PlaceStrength::STRENGTH_FIXED);
|
||||
|
||||
// Duplicate input connection
|
||||
gpio_new->connectPort(id_I, gpio->getPort(id_I));
|
||||
// Connect IOSEL and CPE_IBUF
|
||||
gpio_new->connectPorts(id_Y, iosel_new, id_GPIO_IN);
|
||||
}
|
||||
uarch->clkin[new_die]->disconnectPort(ctx->idf("CLK%d", i));
|
||||
if (iosel_new->getPort(id_IN1))
|
||||
uarch->clkin[new_die]->connectPort(ctx->idf("CLK%d", i), iosel_new->getPort(id_IN1));
|
||||
else
|
||||
iosel_new->connectPorts(id_IN1, uarch->clkin[new_die], ctx->idf("CLK%d", i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue