/* * 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" #include "nextpnr.h" NEXTPNR_NAMESPACE_BEGIN // ============================================================================ SiteLutMappingKey SiteLutMappingKey::create(const SiteInformation &siteInfo) { const Context *ctx = siteInfo.ctx; // Look for LUT cells in the site std::vector 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; key.cells.resize(ctx->max_lut_cells); // 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 netMap; for (CellInfo *cellInfo : lutCells) { NPNR_ASSERT(key.numCells < key.cells.size()); auto &cell = key.cells[key.numCells++]; cell.type = cellInfo->type; cell.belIndex = cellInfo->bel.index; cell.conns.resize(ctx->max_lut_pins, 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 < cell.conns.size()); cell.conns[portId++] = netId; } } // Compute hash key.computeHash(); return key; } // ============================================================================ bool SiteLutMappingResult::apply(const SiteInformation &siteInfo) { Context *ctx = const_cast(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 pin_connections ? cellInfo->lut_cell.pin_connections = std::move(cell.lutCell.pin_connections); } return true; } size_t SiteLutMappingResult::getSizeInBytes() const { size_t size = 0; size += sizeof(SiteLutMappingResult); size += blockedWires.size() * sizeof(std::pair); for (const auto &cell : cells) { size += sizeof(Cell); size += cell.belPins.size() * sizeof(decltype(cell.belPins)::value_type); } return size; } // ============================================================================ 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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126