mirror of https://github.com/YosysHQ/nextpnr.git
himbaechel: Enable use of electrostatic placer (#1657)
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
ab7aa9ffab
commit
575689b7e4
|
|
@ -279,13 +279,16 @@ class StaticPlacer
|
|||
}
|
||||
}
|
||||
|
||||
bool lookup_group(IdString type, int &group, StaticRect &rect)
|
||||
bool lookup_group(const CellInfo *ci, int &group, StaticRect &rect)
|
||||
{
|
||||
for (size_t i = 0; i < cfg.cell_groups.size(); i++) {
|
||||
const auto &g = cfg.cell_groups.at(i);
|
||||
if (g.cell_area.count(type)) {
|
||||
if (g.cell_area.count(ci->type)) {
|
||||
group = i;
|
||||
rect = g.cell_area.at(type);
|
||||
rect = g.cell_area.at(ci->type);
|
||||
if (auto rect_override = cfg.get_cell_area_override(ctx, ci)) {
|
||||
rect = *rect_override;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -320,6 +323,8 @@ class StaticPlacer
|
|||
for (int dx = 0; dx <= int(size.w); dx++) {
|
||||
float h = (dy == int(size.h)) ? (size.h - int(size.h)) : 1;
|
||||
float w = (dx == int(size.w)) ? (size.w - int(size.w)) : 1;
|
||||
if ((loc.x + dx) >= width || (loc.y + dy) >= height)
|
||||
continue;
|
||||
group.loc_area.at(loc.x + dx, loc.y + dy) += w * h;
|
||||
}
|
||||
}
|
||||
|
|
@ -412,7 +417,7 @@ class StaticPlacer
|
|||
int cell_group;
|
||||
StaticRect rect;
|
||||
// Mismatched group case
|
||||
if (!lookup_group(ci->type, cell_group, rect)) {
|
||||
if (!lookup_group(ci, cell_group, rect)) {
|
||||
if (ci->bel == BelId()) {
|
||||
for (auto bel : ctx->getBels()) {
|
||||
if (ctx->isValidBelForCellType(ci->type, bel) && ctx->checkBelAvail(bel)) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
#include "log.h"
|
||||
#include "nextpnr.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
struct StaticRect
|
||||
|
|
@ -64,6 +66,11 @@ struct PlacerStaticCfg
|
|||
// groups < logic_groups are logic like LUTs and FFs, further groups for BRAM/DSP/misc
|
||||
std::vector<StaticCellGroupCfg> cell_groups;
|
||||
int logic_groups = 2;
|
||||
|
||||
// this is an optional callback to override the area of a cell e.g. based on configuration
|
||||
std::function<std::optional<StaticRect>(Context *, const CellInfo *)> get_cell_area_override = [](Context *, const CellInfo *) {
|
||||
return std::optional<StaticRect>{};
|
||||
};
|
||||
};
|
||||
|
||||
extern bool placer_static(Context *ctx, PlacerStaticCfg cfg);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include "command.h"
|
||||
#include "placer1.h"
|
||||
#include "placer_heap.h"
|
||||
#include "placer_static.h"
|
||||
|
||||
#include "router1.h"
|
||||
#include "router2.h"
|
||||
#include "util.h"
|
||||
|
|
@ -271,6 +273,10 @@ bool Arch::place()
|
|||
uarch->configurePlacerHeap(cfg);
|
||||
cfg.ioBufTypes.insert(id("GENERIC_IOB"));
|
||||
retVal = placer_heap(getCtx(), cfg);
|
||||
} else if (placer == "static") {
|
||||
PlacerStaticCfg cfg(getCtx());
|
||||
uarch->configurePlacerStatic(cfg);
|
||||
retVal = placer_static(getCtx(), cfg);
|
||||
} else if (placer == "sa") {
|
||||
retVal = placer1(getCtx(), Placer1Cfg(getCtx()));
|
||||
} else {
|
||||
|
|
@ -403,7 +409,7 @@ void IdString::initialize_arch(const BaseCtx *ctx) {}
|
|||
|
||||
const std::string Arch::defaultPlacer = "heap";
|
||||
|
||||
const std::vector<std::string> Arch::availablePlacers = {"sa", "heap"};
|
||||
const std::vector<std::string> Arch::availablePlacers = {"sa", "heap", "static"};
|
||||
|
||||
const std::string Arch::defaultRouter = "default";
|
||||
const std::vector<std::string> Arch::availableRouters = {"default", "router1", "router2"};
|
||||
|
|
|
|||
|
|
@ -102,6 +102,11 @@ TimingClockingInfo HimbaechelAPI::getPortClockingInfo(const CellInfo *cell, IdSt
|
|||
return ctx->get_port_clocking_info_default(cell, port, index);
|
||||
}
|
||||
|
||||
void HimbaechelAPI::configurePlacerStatic(PlacerStaticCfg &)
|
||||
{
|
||||
log_error("This uarch does not support the 'static' placer.\n");
|
||||
}
|
||||
|
||||
HimbaechelArch *HimbaechelArch::list_head;
|
||||
HimbaechelArch::HimbaechelArch(const std::string &name) : name(name)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ struct Arch;
|
|||
struct Context;
|
||||
|
||||
struct PlacerHeapCfg;
|
||||
struct PlacerStaticCfg;
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
|
|
@ -146,6 +147,7 @@ struct HimbaechelAPI
|
|||
|
||||
// For custom placer configuration
|
||||
virtual void configurePlacerHeap(PlacerHeapCfg &cfg) {};
|
||||
virtual void configurePlacerStatic(PlacerStaticCfg &cfg);
|
||||
|
||||
virtual std::string getDefaultRouter() const { return "router1"; };
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include "util.h"
|
||||
|
||||
#include "placer_heap.h"
|
||||
#include "placer_static.h"
|
||||
|
||||
#include "xilinx.h"
|
||||
|
||||
#include "himbaechel_helpers.h"
|
||||
|
|
@ -295,6 +297,85 @@ void XilinxImpl::configurePlacerHeap(PlacerHeapCfg &cfg)
|
|||
};
|
||||
}
|
||||
|
||||
void XilinxImpl::configurePlacerStatic(PlacerStaticCfg &cfg)
|
||||
{
|
||||
cfg.hpwl_scale_x = 2;
|
||||
cfg.hpwl_scale_y = 1;
|
||||
|
||||
{
|
||||
cfg.cell_groups.emplace_back();
|
||||
auto &comb = cfg.cell_groups.back();
|
||||
comb.name = ctx->id("COMB");
|
||||
comb.bel_area[id_SLICE_LUTX] = StaticRect(1.0f, 0.125f);
|
||||
comb.bel_area[id_CARRY4] = StaticRect(0.0f, 0.0f);
|
||||
comb.bel_area[id_SELMUX2_1] = StaticRect(0.0f, 0.0f);
|
||||
|
||||
comb.cell_area[id_SLICE_LUTX] = StaticRect(1.0f, 0.125f);
|
||||
comb.cell_area[id_CARRY4] = StaticRect(1.0f, 0.5f);
|
||||
comb.cell_area[id_SELMUX2_1] = StaticRect(1.0f, 0.125f);
|
||||
|
||||
comb.zero_area_cells.insert(id_CARRY4);
|
||||
comb.zero_area_cells.insert(id_SELMUX2_1);
|
||||
|
||||
comb.spacer_rect = StaticRect(1.0f, 0.125f);
|
||||
}
|
||||
|
||||
{
|
||||
cfg.cell_groups.emplace_back();
|
||||
auto &comb = cfg.cell_groups.back();
|
||||
comb.name = ctx->id("FF");
|
||||
comb.cell_area[id_SLICE_FFX] = StaticRect(1.0f, 0.125f);
|
||||
comb.bel_area[id_SLICE_FFX] = StaticRect(1.0f, 0.125f);
|
||||
comb.spacer_rect = StaticRect(1.0f, 0.125f);
|
||||
}
|
||||
|
||||
{
|
||||
cfg.cell_groups.emplace_back();
|
||||
auto &comb = cfg.cell_groups.back();
|
||||
comb.name = ctx->id("RAM");
|
||||
comb.cell_area[id_RAMB18E1_RAMB18E1] = StaticRect(1.0f, 3.0f);
|
||||
comb.bel_area[id_RAMB18E1_RAMB18E1] = StaticRect(1.0f, 3.0f);
|
||||
comb.cell_area[id_RAMB36E1_RAMB36E1] = StaticRect(1.0f, 6.0f);
|
||||
comb.bel_area[id_RAMB36E1_RAMB36E1] = StaticRect(0.0f, 0.0f);
|
||||
comb.spacer_rect = StaticRect(1.0f, 3.0f);
|
||||
}
|
||||
{
|
||||
cfg.cell_groups.emplace_back();
|
||||
auto &comb = cfg.cell_groups.back();
|
||||
comb.name = ctx->id("DSP");
|
||||
comb.cell_area[id_DSP48E1_DSP48E1] = StaticRect(1.0f, 3.0f);
|
||||
comb.bel_area[id_DSP48E1_DSP48E1] = StaticRect(1.0f, 3.0f);
|
||||
comb.spacer_rect = StaticRect(1.0f, 3.0f);
|
||||
}
|
||||
cfg.get_cell_area_override = [this](Context *ctx, const CellInfo *ci) -> std::optional<StaticRect> {
|
||||
if (ci->type != id_SLICE_LUTX)
|
||||
return {};
|
||||
auto tags = get_tags(ci);
|
||||
if (tags->lut.is_memory ||
|
||||
(ci->cluster != ClusterId() && ctx->getClusterRootCell(ci->cluster)->type == id_CARRY4)) {
|
||||
// macro LUTs use either a half or whole LUT, always
|
||||
return {(tags->lut.input_count == 6) ? StaticRect(1.0f, 0.125f) : StaticRect(1.0f, 0.0625f)};
|
||||
} else {
|
||||
switch (tags->lut.input_count) { // sliding scale, smaller LUTs pack better
|
||||
case 6:
|
||||
return {StaticRect(1.0f, 0.125f)};
|
||||
case 5:
|
||||
return {StaticRect(1.0f, 0.09f)};
|
||||
case 4:
|
||||
return {StaticRect(1.0f, 0.07f)};
|
||||
case 3:
|
||||
return {StaticRect(1.0f, 0.06f)};
|
||||
case 2:
|
||||
return {StaticRect(1.0f, 0.04f)};
|
||||
case 1:
|
||||
return {StaticRect(1.0f, 0.03f)};
|
||||
default:
|
||||
NPNR_ASSERT_FALSE("unhandled LUT input count");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void XilinxImpl::preRoute()
|
||||
{
|
||||
find_source_sink_locs();
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ struct XilinxImpl : HimbaechelAPI
|
|||
void write_fasm(const std::string &filename);
|
||||
|
||||
void configurePlacerHeap(PlacerHeapCfg &cfg) override;
|
||||
void configurePlacerStatic(PlacerStaticCfg &cfg) override;
|
||||
|
||||
void fixup_placement();
|
||||
void fixup_routing();
|
||||
|
|
|
|||
Loading…
Reference in New Issue