Fixup some of the re-mapping logic.
- Add IDEMPOTENT_CHECK define to perform some expected idempotent operations more than once to verify they work as expected. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
parent
77bc2f9130
commit
5dda3a14ff
@ -49,6 +49,10 @@
|
|||||||
//#define USE_LOOKAHEAD
|
//#define USE_LOOKAHEAD
|
||||||
//#define DEBUG_CELL_PIN_MAPPING
|
//#define DEBUG_CELL_PIN_MAPPING
|
||||||
|
|
||||||
|
// Define to enable some idempotent sanity checks for some important
|
||||||
|
// operations prior to placement and routing.
|
||||||
|
#define IDEMPOTENT_CHECK
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
struct SiteBelPair
|
struct SiteBelPair
|
||||||
{
|
{
|
||||||
@ -710,22 +714,32 @@ bool Arch::pack()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void prepare_for_placement(Context *ctx)
|
||||||
|
{
|
||||||
|
ctx->remove_site_routing();
|
||||||
|
|
||||||
|
// Re-map BEL pins without constant pins
|
||||||
|
for (BelId bel : ctx->getBels()) {
|
||||||
|
CellInfo *cell = ctx->getBoundBelCell(bel);
|
||||||
|
if (cell != nullptr && cell->cell_mapping != -1) {
|
||||||
|
ctx->map_cell_pins(cell, cell->cell_mapping, /*bind_constants=*/false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Arch::place()
|
bool Arch::place()
|
||||||
{
|
{
|
||||||
// Before placement, ripup placement specific bindings and unmask all cell
|
// Before placement, ripup placement specific bindings and unmask all cell
|
||||||
// pins.
|
// pins.
|
||||||
remove_site_routing();
|
getCtx()->check();
|
||||||
|
prepare_for_placement(getCtx());
|
||||||
|
getCtx()->check();
|
||||||
|
#ifdef IDEMPOTENT_CHECK
|
||||||
|
prepare_for_placement(getCtx());
|
||||||
|
getCtx()->check();
|
||||||
|
#endif
|
||||||
|
|
||||||
std::string placer = str_or_default(settings, id("placer"), defaultPlacer);
|
std::string placer = str_or_default(settings, id("placer"), defaultPlacer);
|
||||||
|
|
||||||
// Re-map BEL pins without constant pins
|
|
||||||
for (BelId bel : getBels()) {
|
|
||||||
CellInfo *cell = getBoundBelCell(bel);
|
|
||||||
if (cell != nullptr && cell->cell_mapping != -1) {
|
|
||||||
map_cell_pins(cell, cell->cell_mapping, /*bind_constants=*/false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (placer == "heap") {
|
if (placer == "heap") {
|
||||||
PlacerHeapCfg cfg(getCtx());
|
PlacerHeapCfg cfg(getCtx());
|
||||||
cfg.criticalityExponent = 7;
|
cfg.criticalityExponent = 7;
|
||||||
@ -748,34 +762,51 @@ bool Arch::place()
|
|||||||
|
|
||||||
getCtx()->attrs[getCtx()->id("step")] = std::string("place");
|
getCtx()->attrs[getCtx()->id("step")] = std::string("place");
|
||||||
archInfoToAttributes();
|
archInfoToAttributes();
|
||||||
|
|
||||||
|
getCtx()->check();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Arch::route()
|
static void prepare_sites_for_routing(Context *ctx)
|
||||||
{
|
{
|
||||||
std::string router = str_or_default(settings, id("router"), defaultRouter);
|
|
||||||
|
|
||||||
// Reset site routing and remove masked cell pins from previous router run
|
// Reset site routing and remove masked cell pins from previous router run
|
||||||
// (if any).
|
// (if any).
|
||||||
remove_site_routing();
|
ctx->remove_site_routing();
|
||||||
|
|
||||||
// Re-map BEL pins with constant pins
|
// Re-map BEL pins with constant pins
|
||||||
for (BelId bel : getBels()) {
|
for (BelId bel : ctx->getBels()) {
|
||||||
CellInfo *cell = getBoundBelCell(bel);
|
CellInfo *cell = ctx->getBoundBelCell(bel);
|
||||||
if (cell != nullptr && cell->cell_mapping != -1) {
|
if (cell != nullptr && cell->cell_mapping != -1) {
|
||||||
map_cell_pins(cell, cell->cell_mapping, /*bind_constants=*/true);
|
ctx->map_cell_pins(cell, cell->cell_mapping, /*bind_constants=*/true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &tile_pair : tileStatus) {
|
// Have site router bind site routing (via bindPip and bindWire).
|
||||||
|
// This is important so that the pseudo pips are correctly blocked prior
|
||||||
|
// to handing the design to the generalized router algorithms.
|
||||||
|
for (auto &tile_pair : ctx->tileStatus) {
|
||||||
for (auto &site_router : tile_pair.second.sites) {
|
for (auto &site_router : tile_pair.second.sites) {
|
||||||
if (site_router.cells_in_site.empty()) {
|
if (site_router.cells_in_site.empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
site_router.bindSiteRouting(getCtx());
|
site_router.bindSiteRouting(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Arch::route()
|
||||||
|
{
|
||||||
|
getCtx()->check();
|
||||||
|
prepare_sites_for_routing(getCtx());
|
||||||
|
getCtx()->check();
|
||||||
|
#ifdef IDEMPOTENT_CHECK
|
||||||
|
prepare_sites_for_routing(getCtx());
|
||||||
|
getCtx()->check();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string router = str_or_default(settings, id("router"), defaultRouter);
|
||||||
|
|
||||||
bool result;
|
bool result;
|
||||||
if (router == "router1") {
|
if (router == "router1") {
|
||||||
@ -794,9 +825,13 @@ bool Arch::route()
|
|||||||
getCtx()->attrs[getCtx()->id("step")] = std::string("route");
|
getCtx()->attrs[getCtx()->id("step")] = std::string("route");
|
||||||
archInfoToAttributes();
|
archInfoToAttributes();
|
||||||
|
|
||||||
|
getCtx()->check();
|
||||||
|
|
||||||
// Now that routing is complete, unmask BEL pins.
|
// Now that routing is complete, unmask BEL pins.
|
||||||
unmask_bel_pins();
|
unmask_bel_pins();
|
||||||
|
|
||||||
|
getCtx()->check();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1012,6 +1047,7 @@ void Arch::map_cell_pins(CellInfo *cell, int32_t mapping, bool bind_constants)
|
|||||||
cell->cell_mapping = mapping;
|
cell->cell_mapping = mapping;
|
||||||
if (cell->lut_cell.pins.empty()) {
|
if (cell->lut_cell.pins.empty()) {
|
||||||
cell->cell_bel_pins.clear();
|
cell->cell_bel_pins.clear();
|
||||||
|
cell->masked_cell_bel_pins.clear();
|
||||||
} else {
|
} else {
|
||||||
std::vector<IdString> cell_pin_to_remove;
|
std::vector<IdString> cell_pin_to_remove;
|
||||||
for (auto port_pair : cell->cell_bel_pins) {
|
for (auto port_pair : cell->cell_bel_pins) {
|
||||||
@ -1024,7 +1060,9 @@ void Arch::map_cell_pins(CellInfo *cell, int32_t mapping, bool bind_constants)
|
|||||||
NPNR_ASSERT(cell->cell_bel_pins.erase(cell_pin));
|
NPNR_ASSERT(cell->cell_bel_pins.erase(cell_pin));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IdString const_port : cell->const_ports) {
|
for (IdString const_port : cell->const_ports) {
|
||||||
|
disconnectPort(cell->name, const_port);
|
||||||
NPNR_ASSERT(cell->ports.erase(const_port));
|
NPNR_ASSERT(cell->ports.erase(const_port));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1857,10 +1895,6 @@ void Arch::remove_site_routing()
|
|||||||
// Only looking for bound placer wires
|
// Only looking for bound placer wires
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TileWireInfoPOD &wire_data = wire_info(wire);
|
|
||||||
NPNR_ASSERT(wire_data.site != -1);
|
|
||||||
|
|
||||||
wires_to_unbind.emplace(wire);
|
wires_to_unbind.emplace(wire);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1869,9 +1903,25 @@ void Arch::remove_site_routing()
|
|||||||
unbindWire(wire);
|
unbindWire(wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: !!!!! Remove $nextpnr_inv cells here !!!!!
|
|
||||||
|
|
||||||
unmask_bel_pins();
|
unmask_bel_pins();
|
||||||
|
|
||||||
|
IdString id_NEXTPNR_INV = id("$nextpnr_inv");
|
||||||
|
IdString id_I = id("I");
|
||||||
|
std::vector<IdString> cells_to_remove;
|
||||||
|
for (auto &cell_pair : cells) {
|
||||||
|
CellInfo *cell = cell_pair.second.get();
|
||||||
|
if (cell->type != id_NEXTPNR_INV) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnectPort(cell_pair.first, id_I);
|
||||||
|
cells_to_remove.push_back(cell_pair.first);
|
||||||
|
tileStatus.at(cell->bel.tile).boundcells[cell->bel.index] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (IdString cell_name : cells_to_remove) {
|
||||||
|
NPNR_ASSERT(cells.erase(cell_name) == 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instance constraint templates.
|
// Instance constraint templates.
|
||||||
|
@ -109,9 +109,7 @@ struct ArchNetInfo
|
|||||||
|
|
||||||
struct ArchCellInfo
|
struct ArchCellInfo
|
||||||
{
|
{
|
||||||
ArchCellInfo() : cell_mapping(-1) {}
|
int32_t cell_mapping = -1;
|
||||||
|
|
||||||
int32_t cell_mapping;
|
|
||||||
HashTables::HashMap<IdString, std::vector<IdString>> cell_bel_pins;
|
HashTables::HashMap<IdString, std::vector<IdString>> cell_bel_pins;
|
||||||
HashTables::HashMap<IdString, std::vector<IdString>> masked_cell_bel_pins;
|
HashTables::HashMap<IdString, std::vector<IdString>> masked_cell_bel_pins;
|
||||||
HashTables::HashSet<IdString> const_ports;
|
HashTables::HashSet<IdString> const_ports;
|
||||||
|
Loading…
Reference in New Issue
Block a user