From 77bc2f9130204e40023411c3fd13b3a3a3aa8a5b Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Tue, 23 Mar 2021 16:53:42 -0700 Subject: Add initial handling of local site inverters and constant signals. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- fpga_interchange/arch.cc | 115 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 95 insertions(+), 20 deletions(-) (limited to 'fpga_interchange/arch.cc') diff --git a/fpga_interchange/arch.cc b/fpga_interchange/arch.cc index a8b62f95..5c252802 100644 --- a/fpga_interchange/arch.cc +++ b/fpga_interchange/arch.cc @@ -144,6 +144,7 @@ Arch::Arch(ArchArgs args) : args(args) io_port_types.emplace(this->id("$nextpnr_ibuf")); io_port_types.emplace(this->id("$nextpnr_obuf")); io_port_types.emplace(this->id("$nextpnr_iobuf")); + io_port_types.emplace(this->id("$nextpnr_inv")); if (!this->args.package.empty()) { IdString package = this->id(this->args.package); @@ -711,6 +712,10 @@ bool Arch::pack() bool Arch::place() { + // Before placement, ripup placement specific bindings and unmask all cell + // pins. + remove_site_routing(); + std::string placer = str_or_default(settings, id("placer"), defaultPlacer); // Re-map BEL pins without constant pins @@ -750,6 +755,10 @@ bool Arch::route() { std::string router = str_or_default(settings, id("router"), defaultRouter); + // Reset site routing and remove masked cell pins from previous router run + // (if any). + remove_site_routing(); + // Re-map BEL pins with constant pins for (BelId bel : getBels()) { CellInfo *cell = getBoundBelCell(bel); @@ -758,26 +767,6 @@ bool Arch::route() } } - HashTables::HashSet wires_to_unbind; - for (auto &net_pair : nets) { - for (auto &wire_pair : net_pair.second->wires) { - WireId wire = wire_pair.first; - if (wire_pair.second.strength != STRENGTH_PLACER) { - // Only looking for bound placer wires - continue; - } - - const TileWireInfoPOD &wire_data = wire_info(wire); - NPNR_ASSERT(wire_data.site != -1); - - wires_to_unbind.emplace(wire); - } - } - - for (WireId wire : wires_to_unbind) { - unbindWire(wire); - } - for (auto &tile_pair : tileStatus) { for (auto &site_router : tile_pair.second.sites) { if (site_router.cells_in_site.empty()) { @@ -805,6 +794,9 @@ bool Arch::route() getCtx()->attrs[getCtx()->id("step")] = std::string("route"); archInfoToAttributes(); + // Now that routing is complete, unmask BEL pins. + unmask_bel_pins(); + return result; } @@ -1799,6 +1791,89 @@ bool Arch::can_invert(PipId pip) const return bel_data.non_inverting_pin == pip_info.extra_data && bel_data.inverting_pin == pip_info.extra_data; } +void Arch::mask_bel_pins_on_site_wire(NetInfo *net, WireId wire) +{ + std::vector bel_pins_to_mask; + for (const PortRef &port_ref : net->users) { + if (port_ref.cell->bel == BelId()) { + continue; + } + + NPNR_ASSERT(port_ref.cell != nullptr); + auto iter = port_ref.cell->cell_bel_pins.find(port_ref.port); + if (iter == port_ref.cell->cell_bel_pins.end()) { + continue; + } + + std::vector &cell_bel_pins = iter->second; + bel_pins_to_mask.clear(); + + for (size_t bel_pin_idx = 0; bel_pin_idx < cell_bel_pins.size(); ++bel_pin_idx) { + IdString bel_pin = cell_bel_pins.at(bel_pin_idx); + WireId bel_pin_wire = getBelPinWire(port_ref.cell->bel, bel_pin); + if (bel_pin_wire == wire) { + bel_pins_to_mask.push_back(bel_pin_idx); + } + } + + if (!bel_pins_to_mask.empty()) { + std::vector &masked_cell_bel_pins = port_ref.cell->masked_cell_bel_pins[port_ref.port]; + // Remove in reverse order to preserve indicies. + for (auto riter = bel_pins_to_mask.rbegin(); riter != bel_pins_to_mask.rend(); ++riter) { + size_t bel_pin_idx = *riter; + masked_cell_bel_pins.push_back(cell_bel_pins.at(bel_pin_idx)); + cell_bel_pins.erase(cell_bel_pins.begin() + bel_pin_idx); + } + } + } +} + +void Arch::unmask_bel_pins() +{ + for (auto &cell_pair : cells) { + CellInfo *cell = cell_pair.second.get(); + if (cell->masked_cell_bel_pins.empty()) { + continue; + } + + for (auto &mask_pair : cell->masked_cell_bel_pins) { + IdString cell_port = mask_pair.first; + const std::vector &bel_pins = mask_pair.second; + std::vector &cell_bel_pins = cell->cell_bel_pins[cell_port]; + cell_bel_pins.insert(cell_bel_pins.begin(), bel_pins.begin(), bel_pins.end()); + } + + cell->masked_cell_bel_pins.clear(); + } +} + +void Arch::remove_site_routing() +{ + HashTables::HashSet wires_to_unbind; + for (auto &net_pair : nets) { + for (auto &wire_pair : net_pair.second->wires) { + WireId wire = wire_pair.first; + if (wire_pair.second.strength != STRENGTH_PLACER) { + // Only looking for bound placer wires + continue; + } + + const TileWireInfoPOD &wire_data = wire_info(wire); + NPNR_ASSERT(wire_data.site != -1); + + wires_to_unbind.emplace(wire); + } + } + + for (WireId wire : wires_to_unbind) { + unbindWire(wire); + } + + // FIXME: !!!!! Remove $nextpnr_inv cells here !!!!! + + unmask_bel_pins(); +} + // Instance constraint templates. template void Arch::ArchConstraints::bindBel(Arch::ArchConstraints::TagState *, const Arch::ConstraintRange); template void Arch::ArchConstraints::unbindBel(Arch::ArchConstraints::TagState *, const Arch::ConstraintRange); -- cgit v1.2.3