2021-07-09 21:40:06 +08:00
|
|
|
/*
|
|
|
|
* 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 "site_lut_mapping_cache.h"
|
2021-07-16 22:01:21 +08:00
|
|
|
#include "nextpnr.h"
|
2021-07-09 21:40:06 +08:00
|
|
|
|
|
|
|
NEXTPNR_NAMESPACE_BEGIN
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
2021-07-16 22:01:21 +08:00
|
|
|
SiteLutMappingKey SiteLutMappingKey::create(const SiteInformation &siteInfo)
|
|
|
|
{
|
2021-07-09 21:40:06 +08:00
|
|
|
const Context *ctx = siteInfo.ctx;
|
|
|
|
|
|
|
|
// Look for LUT cells in the site
|
2021-07-16 22:01:21 +08:00
|
|
|
std::vector<CellInfo *> lutCells;
|
2021-07-09 21:40:06 +08:00
|
|
|
lutCells.reserve(siteInfo.cells_in_site.size());
|
|
|
|
|
2021-07-16 22:01:21 +08:00
|
|
|
for (CellInfo *cellInfo : siteInfo.cells_in_site) {
|
2021-07-09 21:40:06 +08:00
|
|
|
|
|
|
|
// 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(),
|
2021-07-16 22:01:21 +08:00
|
|
|
[](const CellInfo *a, const CellInfo *b) { return a->bel.index > b->bel.index; });
|
2021-07-09 21:40:06 +08:00
|
|
|
|
|
|
|
// Initialize the key
|
|
|
|
SiteLutMappingKey key;
|
|
|
|
key.tileType = siteInfo.tile_type;
|
|
|
|
key.siteType = ctx->chip_info->sites[siteInfo.site].site_type;
|
2021-07-16 19:55:19 +08:00
|
|
|
key.numCells = 0;
|
2021-07-09 21:40:06 +08:00
|
|
|
|
|
|
|
// 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;
|
2021-07-16 22:01:21 +08:00
|
|
|
for (CellInfo *cellInfo : lutCells) {
|
2021-07-09 21:40:06 +08:00
|
|
|
|
2021-07-16 19:55:19 +08:00
|
|
|
NPNR_ASSERT(key.numCells < SiteLutMappingKey::MAX_LUT_CELLS);
|
2021-07-16 22:01:21 +08:00
|
|
|
auto &cell = key.cells[key.numCells++];
|
2021-07-16 19:55:19 +08:00
|
|
|
|
2021-07-16 22:01:21 +08:00
|
|
|
cell.type = cellInfo->type;
|
|
|
|
cell.belIndex = cellInfo->bel.index;
|
2021-07-09 21:40:06 +08:00
|
|
|
|
2021-07-16 20:55:45 +08:00
|
|
|
cell.conns.fill(0);
|
2021-07-16 19:28:40 +08:00
|
|
|
|
|
|
|
size_t portId = 0;
|
2021-07-16 22:01:21 +08:00
|
|
|
for (const auto &port : cellInfo->ports) {
|
|
|
|
const auto &portInfo = port.second;
|
2021-07-16 19:28:40 +08:00
|
|
|
|
|
|
|
// Consider only LUT inputs
|
|
|
|
if (portInfo.type != PORT_IN) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assign net id if any
|
|
|
|
int32_t netId = 0;
|
2021-07-09 21:40:06 +08:00
|
|
|
if (portInfo.net != nullptr) {
|
2021-07-16 22:01:21 +08:00
|
|
|
auto netInfo = portInfo.net;
|
2021-07-09 21:40:06 +08:00
|
|
|
|
|
|
|
auto it = netMap.find(netInfo->name);
|
|
|
|
if (it != netMap.end()) {
|
|
|
|
netId = it->second;
|
2021-07-16 22:01:21 +08:00
|
|
|
} else {
|
2021-07-16 19:28:40 +08:00
|
|
|
netId = (int32_t)netMap.size() + 1;
|
2021-07-09 21:40:06 +08:00
|
|
|
netMap[netInfo->name] = netId;
|
|
|
|
}
|
|
|
|
}
|
2021-07-16 19:28:40 +08:00
|
|
|
|
|
|
|
NPNR_ASSERT(portId < SiteLutMappingKey::MAX_LUT_INPUTS);
|
|
|
|
cell.conns[portId++] = netId;
|
2021-07-09 21:40:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-16 19:28:40 +08:00
|
|
|
// Compute hash
|
|
|
|
key.computeHash();
|
|
|
|
|
2021-07-09 21:40:06 +08:00
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
2021-07-16 22:01:21 +08:00
|
|
|
bool SiteLutMappingResult::apply(const SiteInformation &siteInfo)
|
|
|
|
{
|
2021-07-09 21:40:06 +08:00
|
|
|
|
2021-07-16 22:01:21 +08:00
|
|
|
Context *ctx = const_cast<Context *>(siteInfo.ctx);
|
2021-07-09 21:40:06 +08:00
|
|
|
TileStatus &tileStatus = ctx->get_tile_status(siteInfo.tile);
|
|
|
|
|
2021-07-16 22:01:21 +08:00
|
|
|
for (auto &cell : cells) {
|
2021-07-09 21:40:06 +08:00
|
|
|
|
|
|
|
// Get the bound cell
|
2021-07-16 22:01:21 +08:00
|
|
|
CellInfo *cellInfo = tileStatus.boundcells[cell.belIndex];
|
2021-07-09 21:40:06 +08:00
|
|
|
NPNR_ASSERT(cellInfo);
|
|
|
|
|
|
|
|
// Double check BEL binding
|
2021-07-16 22:01:21 +08:00
|
|
|
NPNR_ASSERT(cellInfo->bel.tile == siteInfo.tile);
|
2021-07-16 21:16:31 +08:00
|
|
|
NPNR_ASSERT(cellInfo->bel.index == cell.belIndex);
|
2021-07-09 21:40:06 +08:00
|
|
|
|
|
|
|
// Cell <-> BEL pin map
|
|
|
|
size_t numPins = cellInfo->lut_cell.pins.size();
|
|
|
|
for (size_t pinIdx = 0; pinIdx < numPins; ++pinIdx) {
|
2021-07-16 22:01:21 +08:00
|
|
|
const IdString &cellPin = cellInfo->lut_cell.pins[pinIdx];
|
|
|
|
auto &belPins = cellInfo->cell_bel_pins[cellPin];
|
2021-07-09 21:40:06 +08:00
|
|
|
|
2021-07-16 19:28:40 +08:00
|
|
|
// There is only one pin
|
2021-07-09 21:40:06 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-07-16 22:01:21 +08:00
|
|
|
size_t SiteLutMappingResult::getSizeInBytes() const
|
|
|
|
{
|
2021-07-16 21:53:00 +08:00
|
|
|
|
|
|
|
size_t size = 0;
|
|
|
|
|
|
|
|
size += sizeof(SiteLutMappingResult);
|
|
|
|
size += blockedWires.size() * sizeof(std::pair<IdString, IdString>);
|
|
|
|
|
2021-07-16 22:01:21 +08:00
|
|
|
for (const auto &cell : cells) {
|
2021-07-16 21:53:00 +08:00
|
|
|
size += sizeof(Cell);
|
|
|
|
size += cell.belPins.size() * sizeof(decltype(cell.belPins)::value_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2021-07-09 21:40:06 +08:00
|
|
|
// ============================================================================
|
|
|
|
|
2021-07-16 22:01:21 +08:00
|
|
|
void SiteLutMappingCache::add(const SiteLutMappingKey &key, const SiteLutMappingResult &result)
|
2021-07-09 21:40:06 +08:00
|
|
|
{
|
|
|
|
cache_[key] = result;
|
|
|
|
}
|
|
|
|
|
2021-07-16 22:01:21 +08:00
|
|
|
bool SiteLutMappingCache::get(const SiteLutMappingKey &key, SiteLutMappingResult *result)
|
2021-07-09 21:40:06 +08:00
|
|
|
{
|
|
|
|
if (cache_.count(key) == 0) {
|
|
|
|
numMisses++;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
numHits++;
|
|
|
|
*result = cache_[key];
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-07-16 22:01:21 +08:00
|
|
|
void SiteLutMappingCache::clear()
|
|
|
|
{
|
2021-07-09 21:40:06 +08:00
|
|
|
cache_.clear();
|
|
|
|
clearStats();
|
|
|
|
}
|
|
|
|
|
2021-07-16 22:01:21 +08:00
|
|
|
void SiteLutMappingCache::clearStats()
|
|
|
|
{
|
|
|
|
numHits = 0;
|
2021-07-09 21:40:06 +08:00
|
|
|
numMisses = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
NEXTPNR_NAMESPACE_END
|