nextpnr/fpga_interchange/site_lut_mapping_cache.cc
Maciej Kurc 857961a6bb Migrated C arrays to std::array containers.
Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
2021-07-16 14:55:45 +02:00

187 lines
5.4 KiB
C++

/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2021 Symbiflow Authors
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "nextpnr.h"
#include "archdefs.h"
#include "site_arch.h"
#include "site_lut_mapping_cache.h"
NEXTPNR_NAMESPACE_BEGIN
// ============================================================================
SiteLutMappingKey SiteLutMappingKey::create (const SiteInformation& siteInfo) {
const Context *ctx = siteInfo.ctx;
// Look for LUT cells in the site
std::vector<CellInfo*> lutCells;
lutCells.reserve(siteInfo.cells_in_site.size());
for (CellInfo* cellInfo : siteInfo.cells_in_site) {
// Not a LUT cell
if (cellInfo->lut_cell.pins.empty()) {
continue;
}
// Not bound to a LUT BEL
BelId bel = cellInfo->bel;
const auto &bel_data = bel_info(ctx->chip_info, bel);
if (bel_data.lut_element == -1) {
continue;
}
lutCells.push_back(cellInfo);
}
// Sort cells by BEL indices to maintain always the same order
std::sort(lutCells.begin(), lutCells.end(),
[](const CellInfo* a, const CellInfo* b)
{
return a->bel.index > b->bel.index;
});
// Initialize the key
SiteLutMappingKey key;
key.tileType = siteInfo.tile_type;
key.siteType = ctx->chip_info->sites[siteInfo.site].site_type;
key.numCells = 0;
// Get bound nets. Store localized (to the LUT cluster) net indices only
// to get always the same key for the same LUT port configuration even
// when the actual global net names are different.
dict<IdString, int32_t> netMap;
for (CellInfo* cellInfo : lutCells) {
NPNR_ASSERT(key.numCells < SiteLutMappingKey::MAX_LUT_CELLS);
auto& cell = key.cells[key.numCells++];
cell.type = cellInfo->type;
cell.belIndex = cellInfo->bel.index;
cell.conns.fill(0);
size_t portId = 0;
for (const auto& port : cellInfo->ports) {
const auto& portInfo = port.second;
// Consider only LUT inputs
if (portInfo.type != PORT_IN) {
continue;
}
// Assign net id if any
int32_t netId = 0;
if (portInfo.net != nullptr) {
auto netInfo = portInfo.net;
auto it = netMap.find(netInfo->name);
if (it != netMap.end()) {
netId = it->second;
}
else {
netId = (int32_t)netMap.size() + 1;
netMap[netInfo->name] = netId;
}
}
NPNR_ASSERT(portId < SiteLutMappingKey::MAX_LUT_INPUTS);
cell.conns[portId++] = netId;
}
}
// Compute hash
key.computeHash();
return key;
}
// ============================================================================
bool SiteLutMappingResult::apply (const SiteInformation& siteInfo) {
Context *ctx = const_cast<Context*>(siteInfo.ctx);
TileStatus &tileStatus = ctx->get_tile_status(siteInfo.tile);
for (auto& cell : cells) {
// Get the bound cell
CellInfo* cellInfo = tileStatus.boundcells[cell.belIndex];
NPNR_ASSERT(cellInfo);
// Double check BEL binding
NPNR_ASSERT(cellInfo->bel.tile = siteInfo.tile);
NPNR_ASSERT(cellInfo->bel.index = cell.belIndex);
// Cell <-> BEL pin map
size_t numPins = cellInfo->lut_cell.pins.size();
for (size_t pinIdx = 0; pinIdx < numPins; ++pinIdx) {
const IdString& cellPin = cellInfo->lut_cell.pins[pinIdx];
auto &belPins = cellInfo->cell_bel_pins[cellPin];
// There is only one pin
belPins.resize(1);
belPins[0] = cell.belPins[cellPin];
}
// LUT data
// FIXME: Is there any other info that is being updated than vcc_pins ?
cellInfo->lut_cell.vcc_pins = std::move(cell.lutCell.vcc_pins);
}
return true;
}
// ============================================================================
void SiteLutMappingCache::add (const SiteLutMappingKey& key,
const SiteLutMappingResult& result)
{
cache_[key] = result;
}
bool SiteLutMappingCache::get (const SiteLutMappingKey& key,
SiteLutMappingResult* result)
{
if (cache_.count(key) == 0) {
numMisses++;
return false;
}
numHits++;
*result = cache_[key];
return true;
}
void SiteLutMappingCache::clear () {
cache_.clear();
clearStats();
}
void SiteLutMappingCache::clearStats () {
numHits = 0;
numMisses = 0;
}
// ============================================================================
NEXTPNR_NAMESPACE_END