diff options
Diffstat (limited to 'ice40/arch.cc')
-rw-r--r-- | ice40/arch.cc | 357 |
1 files changed, 291 insertions, 66 deletions
diff --git a/ice40/arch.cc b/ice40/arch.cc index 6c00f0d2..7c6af263 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -2,6 +2,7 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com> + * Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -28,6 +29,16 @@ NEXTPNR_NAMESPACE_BEGIN +ArchRWProxy Arch::rwproxy(void) { + ArchRWProxy res(this); + return res; +} + +ArchRProxy Arch::rproxy(void) const { + ArchRProxy res(this); + return res; +} + // ----------------------------------------------------------------------- IdString Arch::belTypeToId(BelType type) const @@ -239,28 +250,6 @@ IdString Arch::archArgsToId(ArchArgs args) const // ----------------------------------------------------------------------- -BelId Arch::getBelByName(IdString name) const -{ - boost::lock_guard<boost::shared_mutex> lock(mtx_); - return getBelByNameUnlocked(name); -} - -BelId Arch::getBelByNameUnlocked(IdString name) const -{ - BelId ret; - - if (bel_by_name.empty()) { - for (int i = 0; i < chip_info->num_bels; i++) - bel_by_name[id(chip_info->bel_data[i].name.get())] = i; - } - - auto it = bel_by_name.find(name); - if (it != bel_by_name.end()) - ret.index = it->second; - - return ret; -} - BelRange Arch::getBelsAtSameTile(BelId bel) const { BelRange br; @@ -279,81 +268,105 @@ BelRange Arch::getBelsAtSameTile(BelId bel) const return br; } -WireId Arch::getWireBelPin(BelId bel, PortPin pin) const +// ----------------------------------------------------------------------- +// Shorthands to ArchProxy + +BelId Arch::getBelByName(IdString name) const { - boost::shared_lock_guard<boost::shared_mutex> lock(mtx_); - return getWireBelPinUnlocked(bel, pin); + return rproxy().getBelByName(name); } -WireId Arch::getWireBelPinUnlocked(BelId bel, PortPin pin) const +void Arch::bindWire(WireId wire, IdString net, PlaceStrength strength) { - WireId ret; + rwproxy().bindWire(wire, net, strength); +} - NPNR_ASSERT(bel != BelId()); +void Arch::unbindWire(WireId wire) +{ + rwproxy().unbindWire(wire); +} - int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires; - const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get(); +void Arch::bindBel(BelId bel, IdString cell, PlaceStrength strength) { + rwproxy().bindBel(bel, cell, strength); +} - for (int i = 0; i < num_bel_wires; i++) - if (bel_wires[i].port == pin) { - ret.index = bel_wires[i].wire_index; - break; - } +void Arch::unbindBel(BelId bel) +{ + rwproxy().unbindBel(bel); +} - return ret; +bool Arch::checkBelAvail(BelId bel) const +{ + return rproxy().checkBelAvail(bel); } -// ----------------------------------------------------------------------- +IdString Arch::getBoundBelCell(BelId bel) const +{ + return rproxy().getBoundBelCell(bel); +} -WireId Arch::getWireByName(IdString name) const +IdString Arch::getConflictingBelCell(BelId bel) const { - boost::shared_lock_guard<boost::shared_mutex> lock(mtx_); - return getWireByNameUnlocked(name); + return rproxy().getConflictingBelCell(bel); } -WireId Arch::getWireByNameUnlocked(IdString name) const +WireId Arch::getWireByName(IdString name) const { - WireId ret; + return rproxy().getWireByName(name); +} - if (wire_by_name.empty()) { - for (int i = 0; i < chip_info->num_wires; i++) - wire_by_name[id(chip_info->wire_data[i].name.get())] = i; - } +WireId Arch::getWireBelPin(BelId bel, PortPin pin) const +{ + return rproxy().getWireBelPin(bel, pin); +} - auto it = wire_by_name.find(name); - if (it != wire_by_name.end()) - ret.index = it->second; +bool Arch::checkWireAvail(WireId wire) const +{ + return rproxy().checkWireAvail(wire); +} - return ret; +IdString Arch::getBoundWireNet(WireId wire) const +{ + return rproxy().getBoundWireNet(wire); } -// ----------------------------------------------------------------------- +IdString Arch::getConflictingWireNet(WireId wire) const +{ + return rproxy().getConflictingWireNet(wire); +} PipId Arch::getPipByName(IdString name) const { - boost::shared_lock_guard<boost::shared_mutex> lock(mtx_); - return getPipByNameUnlocked(name); + return rproxy().getPipByName(name); } -PipId Arch::getPipByNameUnlocked(IdString name) const +void Arch::bindPip(PipId pip, IdString net, PlaceStrength strength) { - PipId ret; + return rwproxy().bindPip(pip, net, strength); +} - if (pip_by_name.empty()) { - for (int i = 0; i < chip_info->num_pips; i++) { - PipId pip; - pip.index = i; - pip_by_name[getPipName(pip)] = i; - } - } +void Arch::unbindPip(PipId pip) +{ + return rwproxy().unbindPip(pip); +} - auto it = pip_by_name.find(name); - if (it != pip_by_name.end()) - ret.index = it->second; +bool Arch::checkPipAvail(PipId pip) const +{ + return rproxy().checkPipAvail(pip); +} - return ret; +IdString Arch::getBoundPipNet(PipId pip) const +{ + return rproxy().getBoundPipNet(pip); } +IdString Arch::getConflictingPipNet(PipId pip) const +{ + return rproxy().getConflictingPipNet(pip); +} + +// ----------------------------------------------------------------------- + IdString Arch::getPipName(PipId pip) const { NPNR_ASSERT(pip != PipId()); @@ -682,4 +695,216 @@ bool Arch::isGlobalNet(const NetInfo *net) const return net->driver.cell != nullptr && net->driver.port == id_glb_buf_out; } +// ----------------------------------------------------------------------- + +bool ArchRProxyMethods::checkBelAvail(BelId bel) const +{ + NPNR_ASSERT(bel != BelId()); + return parent_->bel_to_cell[bel.index] == IdString(); +} + +IdString ArchRProxyMethods::getBoundBelCell(BelId bel) const +{ + NPNR_ASSERT(bel != BelId()); + return parent_->bel_to_cell[bel.index]; +} + +IdString ArchRProxyMethods::getConflictingBelCell(BelId bel) const +{ + NPNR_ASSERT(bel != BelId()); + return parent_->bel_to_cell[bel.index]; +} + +WireId ArchRProxyMethods::getWireBelPin(BelId bel, PortPin pin) const +{ + WireId ret; + + NPNR_ASSERT(bel != BelId()); + + int num_bel_wires = parent_->chip_info->bel_data[bel.index].num_bel_wires; + const BelWirePOD *bel_wires = parent_->chip_info->bel_data[bel.index].bel_wires.get(); + + for (int i = 0; i < num_bel_wires; i++) + if (bel_wires[i].port == pin) { + ret.index = bel_wires[i].wire_index; + break; + } + + return ret; +} + +WireId ArchRProxyMethods::getWireByName(IdString name) const +{ + WireId ret; + + if (parent_->wire_by_name.empty()) { + for (int i = 0; i < parent_->chip_info->num_wires; i++) + parent_->wire_by_name[parent_->id(parent_->chip_info->wire_data[i].name.get())] = i; + } + + auto it = parent_->wire_by_name.find(name); + if (it != parent_->wire_by_name.end()) + ret.index = it->second; + + return ret; +} + +bool ArchRProxyMethods::checkWireAvail(WireId wire) const +{ + NPNR_ASSERT(wire != WireId()); + return parent_->wire_to_net[wire.index] == IdString(); +} + +IdString ArchRProxyMethods::getBoundWireNet(WireId wire) const +{ + NPNR_ASSERT(wire != WireId()); + return parent_->wire_to_net[wire.index]; +} + +IdString ArchRProxyMethods::getConflictingWireNet(WireId wire) const +{ + NPNR_ASSERT(wire != WireId()); + return parent_->wire_to_net[wire.index]; +} + +PipId ArchRProxyMethods::getPipByName(IdString name) const +{ + PipId ret; + + if (parent_->pip_by_name.empty()) { + for (int i = 0; i < parent_->chip_info->num_pips; i++) { + PipId pip; + pip.index = i; + parent_->pip_by_name[parent_->getPipName(pip)] = i; + } + } + + auto it = parent_->pip_by_name.find(name); + if (it != parent_->pip_by_name.end()) + ret.index = it->second; + + return ret; +} + +bool ArchRProxyMethods::checkPipAvail(PipId pip) const +{ + NPNR_ASSERT(pip != PipId()); + return parent_->switches_locked[parent_->chip_info->pip_data[pip.index].switch_index] == IdString(); +} + +IdString ArchRProxyMethods::getBoundPipNet(PipId pip) const +{ + NPNR_ASSERT(pip != PipId()); + return parent_->pip_to_net[pip.index]; +} + +IdString ArchRProxyMethods::getConflictingPipNet(PipId pip) const +{ + NPNR_ASSERT(pip != PipId()); + return parent_->switches_locked[parent_->chip_info->pip_data[pip.index].switch_index]; +} + +BelId ArchRProxyMethods::getBelByName(IdString name) const +{ + BelId ret; + + if (parent_->bel_by_name.empty()) { + for (int i = 0; i < parent_->chip_info->num_bels; i++) + parent_->bel_by_name[parent_->id(parent_->chip_info->bel_data[i].name.get())] = i; + } + + auto it = parent_->bel_by_name.find(name); + if (it != parent_->bel_by_name.end()) + ret.index = it->second; + + return ret; +} + +// ----------------------------------------------------------------------- + +void ArchRWProxyMethods::bindWire(WireId wire, IdString net, PlaceStrength strength) +{ + NPNR_ASSERT(wire != WireId()); + NPNR_ASSERT(parent_->wire_to_net[wire.index] == IdString()); + + parent_->wire_to_net[wire.index] = net; + parent_->nets[net]->wires[wire].pip = PipId(); + parent_->nets[net]->wires[wire].strength = strength; +} + +void ArchRWProxyMethods::bindBel(BelId bel, IdString cell, PlaceStrength strength) +{ + NPNR_ASSERT(bel != BelId()); + NPNR_ASSERT(parent_->bel_to_cell[bel.index] == IdString()); + parent_->bel_to_cell[bel.index] = cell; + parent_->cells[cell]->bel = bel; + parent_->cells[cell]->belStrength = strength; +} + +void ArchRWProxyMethods::unbindBel(BelId bel) +{ + NPNR_ASSERT(bel != BelId()); + NPNR_ASSERT(parent_->bel_to_cell[bel.index] != IdString()); + parent_->cells[parent_->bel_to_cell[bel.index]]->bel = BelId(); + parent_->cells[parent_->bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE; + parent_->bel_to_cell[bel.index] = IdString(); +} + +void ArchRWProxyMethods::unbindWire(WireId wire) +{ + NPNR_ASSERT(wire != WireId()); + NPNR_ASSERT(parent_->wire_to_net[wire.index] != IdString()); + + auto &net_wires = parent_->nets[parent_->wire_to_net[wire.index]]->wires; + auto it = net_wires.find(wire); + NPNR_ASSERT(it != net_wires.end()); + + auto pip = it->second.pip; + if (pip != PipId()) { + parent_->pip_to_net[pip.index] = IdString(); + parent_->switches_locked[parent_->chip_info->pip_data[pip.index].switch_index] = IdString(); + } + + net_wires.erase(it); + parent_->wire_to_net[wire.index] = IdString(); +} + +void ArchRWProxyMethods::bindPip(PipId pip, IdString net, PlaceStrength strength) +{ + NPNR_ASSERT(pip != PipId()); + NPNR_ASSERT(parent_->pip_to_net[pip.index] == IdString()); + NPNR_ASSERT(parent_->switches_locked[parent_->chip_info->pip_data[pip.index].switch_index] == IdString()); + + parent_->pip_to_net[pip.index] = net; + parent_->switches_locked[parent_->chip_info->pip_data[pip.index].switch_index] = net; + + WireId dst; + dst.index = parent_->chip_info->pip_data[pip.index].dst; + NPNR_ASSERT(parent_->wire_to_net[dst.index] == IdString()); + parent_->wire_to_net[dst.index] = net; + parent_->nets[net]->wires[dst].pip = pip; + parent_->nets[net]->wires[dst].strength = strength; +} + +void ArchRWProxyMethods::unbindPip(PipId pip) +{ + NPNR_ASSERT(pip != PipId()); + NPNR_ASSERT(parent_->pip_to_net[pip.index] != IdString()); + NPNR_ASSERT(parent_->switches_locked[parent_->chip_info->pip_data[pip.index].switch_index] != IdString()); + + WireId dst; + dst.index = parent_->chip_info->pip_data[pip.index].dst; + NPNR_ASSERT(parent_->wire_to_net[dst.index] != IdString()); + parent_->wire_to_net[dst.index] = IdString(); + parent_->nets[parent_->pip_to_net[pip.index]]->wires.erase(dst); + + parent_->pip_to_net[pip.index] = IdString(); + parent_->switches_locked[parent_->chip_info->pip_data[pip.index].switch_index] = IdString(); +} + +CellInfo *ArchRWProxyMethods::getCell(IdString cell) +{ + return parent_->cells.at(cell).get(); +} + NEXTPNR_NAMESPACE_END |