/* * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Clifford Wolf * Copyright (C) 2018 David Shah * Copyright (C) 2018 Serge Bazanski * * 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 "cells.h" #include "nextpnr.h" #include "util.h" #include NEXTPNR_NAMESPACE_BEGIN bool Arch::logicCellsCompatible(const CellInfo **it, const size_t size) const { // bool dffs_exist = false, dffs_neg = false; // const NetInfo *cen = nullptr, *clk = nullptr, *sr = nullptr; // // for (auto cell : boost::make_iterator_range(it, it+size)) { // NPNR_ASSERT(cell->belType == id_ICESTORM_LC); // if (cell->lcInfo.dffEnable) { // if (!dffs_exist) { // dffs_exist = true; // cen = cell->lcInfo.cen; // clk = cell->lcInfo.clk; // sr = cell->lcInfo.sr; // // if (cell->lcInfo.negClk) { // dffs_neg = true; // } // } else { // if (cen != cell->lcInfo.cen) // return false; // if (clk != cell->lcInfo.clk) // return false; // if (sr != cell->lcInfo.sr) // return false; // if (dffs_neg != cell->lcInfo.negClk) // return false; // } // } // locals_count += cell->lcInfo.inputCount; // } // // return locals_count <= 32; return true; } bool Arch::isBelLocationValid(BelId bel) const { if (getBelType(bel) == id_ICESTORM_LC) { std::array bel_cells; size_t num_cells = 0; Loc bel_loc = getBelLocation(bel); for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { CellInfo *ci_other = getBoundBelCell(bel_other); if (ci_other != nullptr) bel_cells[num_cells++] = ci_other; } return logicCellsCompatible(bel_cells.data(), num_cells); } else { CellInfo *ci = getBoundBelCell(bel); if (ci == nullptr) return true; else return isValidBelForCell(ci, bel); } } bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const { // if (cell->type == id_ICESTORM_LC) { // NPNR_ASSERT(getBelType(bel) == id_ICESTORM_LC); // // std::array bel_cells; // size_t num_cells = 0; // // Loc bel_loc = getBelLocation(bel); // for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { // CellInfo *ci_other = getBoundBelCell(bel_other); // if (ci_other != nullptr && bel_other != bel) // bel_cells[num_cells++] = ci_other; // } // // bel_cells[num_cells++] = cell; // return logicCellsCompatible(bel_cells.data(), num_cells); // } else if (cell->type == id_SB_IO) { // // Do not allow placement of input SB_IOs on blocks where there a PLL is outputting to. // // // Find shared PLL by looking for driving bel siblings from D_IN_0 // // that are a PLL clock output. // auto wire = getBelPinWire(bel, id_D_IN_0); // IdString pll_bel_pin; // BelId pll_bel; // for (auto pin : getWireBelPins(wire)) { // if (pin.pin == id_PLLOUT_A || pin.pin == id_PLLOUT_B) { // pll_bel = pin.bel; // pll_bel_pin = pin.pin; // break; // } // } // // Is there a PLL that shares this IO buffer? // if (pll_bel.index != -1) { // auto pll_cell = getBoundBelCell(pll_bel); // // Is a PLL placed in this PLL bel? // if (pll_cell != nullptr) { // // Is the shared port driving a net? // auto pi = pll_cell->ports[pll_bel_pin]; // if (pi.net != nullptr) { // // Are we perhaps a PAD INPUT Bel that can be placed here? // if (pll_cell->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(this)) { // return true; // } // return false; // } // } // } // return getBelPackagePin(bel) != ""; // } else if (cell->type == id_SB_GB) { // NPNR_ASSERT(cell->ports.at(id_GLOBAL_BUFFER_OUTPUT).net != nullptr); // const NetInfo *net = cell->ports.at(id_GLOBAL_BUFFER_OUTPUT).net; // IdString glb_net = getWireName(getBelPinWire(bel, id_GLOBAL_BUFFER_OUTPUT)); // int glb_id = std::stoi(std::string("") + glb_net.str(this).back()); // if (net->is_reset && net->is_enable) // return false; // else if (net->is_reset) // return (glb_id % 2) == 0; // else if (net->is_enable) // return (glb_id % 2) == 1; // else // return true; // } else { // // TODO: IO cell clock checks return true; // } } NEXTPNR_NAMESPACE_END