diff options
Diffstat (limited to 'ice40')
-rw-r--r-- | ice40/arch_place.cc | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc index cf1276a7..9c76851b 100644 --- a/ice40/arch_place.cc +++ b/ice40/arch_place.cc @@ -106,6 +106,30 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const bel_cells.push_back(cell); return logicCellsCompatible(bel_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. + for (auto iter_bel : getBels()) { + if (getBelType(iter_bel) != TYPE_ICESTORM_PLL) + continue; + if (checkBelAvail(iter_bel)) + continue; + + auto bel_cell = cells.at(getBoundBelCell(iter_bel)).get(); + for (auto type : {id("PLLOUT_A"), id("PLLOUT_B")}) { + auto it = bel_cell->ports.find(type); + if (it == bel_cell->ports.end()) + continue; + if (it->second.net == nullptr) + continue; + auto wire = getBelPinWire(iter_bel, portPinFromId(type)); + for (auto pip : getPipsDownhill(wire)) { + auto driven_wire = getPipDstWire(pip); + auto io_bel = chip_info->wire_data[driven_wire.index].bel_uphill.bel_index; + if (io_bel == bel.index) { + return false; + } + } + } + } return getBelPackagePin(bel) != ""; } else if (cell->type == id_sb_gb) { NPNR_ASSERT(cell->ports.at(id_glb_buf_out).net != nullptr); |