From 59874188a6800fbaa03ec21e3578160e963c2eb5 Mon Sep 17 00:00:00 2001 From: gatecat Date: Thu, 30 Dec 2021 09:08:02 +0000 Subject: generic: Refactor for faster performance This won't affect Python-built arches significantly; but will be useful for the future 'viaduct' functionality where generic routing graphs can be built on the C++ side; too. Signed-off-by: gatecat --- generic/arch.cc | 274 +++++++++++++++++++---------------------- generic/arch.h | 78 +++++++----- generic/arch_pybindings.cc | 64 +++++----- generic/arch_pybindings.h | 67 ++++++++++ generic/archdefs.h | 39 +++++- generic/examples/write_fasm.py | 2 +- 6 files changed, 319 insertions(+), 205 deletions(-) (limited to 'generic') diff --git a/generic/arch.cc b/generic/arch.cc index 0695ec98..d899bd0b 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -28,46 +28,27 @@ NEXTPNR_NAMESPACE_BEGIN -WireInfo &Arch::wire_info(IdStringList wire) +WireId Arch::addWire(IdStringList name, IdString type, int x, int y) { - auto w = wires.find(wire); - if (w == wires.end()) - NPNR_ASSERT_FALSE_STR("no wire named " + wire.str(getCtx())); - return w->second; -} - -PipInfo &Arch::pip_info(IdStringList pip) -{ - auto p = pips.find(pip); - if (p == pips.end()) - NPNR_ASSERT_FALSE_STR("no pip named " + pip.str(getCtx())); - return p->second; -} - -BelInfo &Arch::bel_info(IdStringList bel) -{ - auto b = bels.find(bel); - if (b == bels.end()) - NPNR_ASSERT_FALSE_STR("no bel named " + bel.str(getCtx())); - return b->second; -} - -void Arch::addWire(IdStringList name, IdString type, int x, int y) -{ - NPNR_ASSERT(wires.count(name) == 0); - WireInfo &wi = wires[name]; + NPNR_ASSERT(wire_by_name.count(name) == 0); + WireId wire(wires.size()); + wire_by_name[name] = wire; + wires.emplace_back(); + WireInfo &wi = wires.back(); wi.name = name; wi.type = type; wi.x = x; wi.y = y; - - wire_ids.push_back(name); + return wire; } -void Arch::addPip(IdStringList name, IdString type, IdStringList srcWire, IdStringList dstWire, delay_t delay, Loc loc) +PipId Arch::addPip(IdStringList name, IdString type, WireId srcWire, WireId dstWire, delay_t delay, Loc loc) { - NPNR_ASSERT(pips.count(name) == 0); - PipInfo &pi = pips[name]; + NPNR_ASSERT(pip_by_name.count(name) == 0); + PipId pip(pips.size()); + pip_by_name[name] = pip; + pips.emplace_back(); + PipInfo &pi = pips.back(); pi.name = name; pi.type = type; pi.srcWire = srcWire; @@ -75,9 +56,8 @@ void Arch::addPip(IdStringList name, IdString type, IdStringList srcWire, IdStri pi.delay = delay; pi.loc = loc; - wire_info(srcWire).downhill.push_back(name); - wire_info(dstWire).uphill.push_back(name); - pip_ids.push_back(name); + wire_info(srcWire).downhill.push_back(pip); + wire_info(dstWire).uphill.push_back(pip); if (int(tilePipDimZ.size()) <= loc.x) tilePipDimZ.resize(loc.x + 1); @@ -88,13 +68,17 @@ void Arch::addPip(IdStringList name, IdString type, IdStringList srcWire, IdStri gridDimX = std::max(gridDimX, loc.x + 1); gridDimY = std::max(gridDimY, loc.x + 1); tilePipDimZ[loc.x][loc.y] = std::max(tilePipDimZ[loc.x][loc.y], loc.z + 1); + return pip; } -void Arch::addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidden) +BelId Arch::addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidden) { - NPNR_ASSERT(bels.count(name) == 0); + NPNR_ASSERT(bel_by_name.count(name) == 0); NPNR_ASSERT(bel_by_loc.count(loc) == 0); - BelInfo &bi = bels[name]; + BelId bel(bels.size()); + bel_by_name[name] = bel; + bels.emplace_back(); + BelInfo &bi = bels.back(); bi.name = name; bi.type = type; bi.x = loc.x; @@ -103,8 +87,7 @@ void Arch::addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidde bi.gb = gb; bi.hidden = hidden; - bel_ids.push_back(name); - bel_by_loc[loc] = name; + bel_by_loc[loc] = bel; if (int(bels_by_tile.size()) <= loc.x) bels_by_tile.resize(loc.x + 1); @@ -112,7 +95,7 @@ void Arch::addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidde if (int(bels_by_tile[loc.x].size()) <= loc.y) bels_by_tile[loc.x].resize(loc.y + 1); - bels_by_tile[loc.x][loc.y].push_back(name); + bels_by_tile[loc.x][loc.y].push_back(bel); if (int(tileBelDimZ.size()) <= loc.x) tileBelDimZ.resize(loc.x + 1); @@ -123,49 +106,50 @@ void Arch::addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidde gridDimX = std::max(gridDimX, loc.x + 1); gridDimY = std::max(gridDimY, loc.x + 1); tileBelDimZ[loc.x][loc.y] = std::max(tileBelDimZ[loc.x][loc.y], loc.z + 1); + return bel; } -void Arch::addBelInput(IdStringList bel, IdString name, IdStringList wire) +void Arch::addBelInput(BelId bel, IdString name, WireId wire) { - NPNR_ASSERT(bel_info(bel).pins.count(name) == 0); - PinInfo &pi = bel_info(bel).pins[name]; + auto &bi = bel_info(bel); + NPNR_ASSERT(bi.pins.count(name) == 0); + PinInfo &pi = bi.pins[name]; pi.name = name; pi.wire = wire; pi.type = PORT_IN; - wire_info(wire).downhill_bel_pins.push_back(BelPin{bel, name}); wire_info(wire).bel_pins.push_back(BelPin{bel, name}); } -void Arch::addBelOutput(IdStringList bel, IdString name, IdStringList wire) +void Arch::addBelOutput(BelId bel, IdString name, WireId wire) { - NPNR_ASSERT(bel_info(bel).pins.count(name) == 0); - PinInfo &pi = bel_info(bel).pins[name]; + auto &bi = bel_info(bel); + NPNR_ASSERT(bi.pins.count(name) == 0); + PinInfo &pi = bi.pins[name]; pi.name = name; pi.wire = wire; pi.type = PORT_OUT; - wire_info(wire).uphill_bel_pin = BelPin{bel, name}; wire_info(wire).bel_pins.push_back(BelPin{bel, name}); } -void Arch::addBelInout(IdStringList bel, IdString name, IdStringList wire) +void Arch::addBelInout(BelId bel, IdString name, WireId wire) { - NPNR_ASSERT(bel_info(bel).pins.count(name) == 0); - PinInfo &pi = bel_info(bel).pins[name]; + auto &bi = bel_info(bel); + NPNR_ASSERT(bi.pins.count(name) == 0); + PinInfo &pi = bi.pins[name]; pi.name = name; pi.wire = wire; pi.type = PORT_INOUT; - wire_info(wire).downhill_bel_pins.push_back(BelPin{bel, name}); wire_info(wire).bel_pins.push_back(BelPin{bel, name}); } -void Arch::addGroupBel(IdStringList group, IdStringList bel) { groups[group].bels.push_back(bel); } +void Arch::addGroupBel(IdStringList group, BelId bel) { groups[group].bels.push_back(bel); } -void Arch::addGroupWire(IdStringList group, IdStringList wire) { groups[group].wires.push_back(wire); } +void Arch::addGroupWire(IdStringList group, WireId wire) { groups[group].wires.push_back(wire); } -void Arch::addGroupPip(IdStringList group, IdStringList pip) { groups[group].pips.push_back(pip); } +void Arch::addGroupPip(IdStringList group, PipId pip) { groups[group].pips.push_back(pip); } void Arch::addGroupGroup(IdStringList group, IdStringList grp) { groups[group].groups.push_back(grp); } @@ -177,19 +161,19 @@ void Arch::addDecalGraphic(DecalId decal, const GraphicElement &graphic) void Arch::setWireDecal(WireId wire, DecalXY decalxy) { - wire_info(wire).decalxy = decalxy; + wires.at(wire.index).decalxy = decalxy; refreshUiWire(wire); } void Arch::setPipDecal(PipId pip, DecalXY decalxy) { - pip_info(pip).decalxy = decalxy; + pips.at(pip.index).decalxy = decalxy; refreshUiPip(pip); } void Arch::setBelDecal(BelId bel, DecalXY decalxy) { - bel_info(bel).decalxy = decalxy; + bels.at(bel.index).decalxy = decalxy; refreshUiBel(bel); } @@ -199,14 +183,11 @@ void Arch::setGroupDecal(GroupId group, DecalXY decalxy) refreshUiGroup(group); } -void Arch::setWireAttr(IdStringList wire, IdString key, const std::string &value) -{ - wire_info(wire).attrs[key] = value; -} +void Arch::setWireAttr(WireId wire, IdString key, const std::string &value) { wire_info(wire).attrs[key] = value; } -void Arch::setPipAttr(IdStringList pip, IdString key, const std::string &value) { pip_info(pip).attrs[key] = value; } +void Arch::setPipAttr(PipId pip, IdString key, const std::string &value) { pip_info(pip).attrs[key] = value; } -void Arch::setBelAttr(IdStringList bel, IdString key, const std::string &value) { bel_info(bel).attrs[key] = value; } +void Arch::setBelAttr(BelId bel, IdString key, const std::string &value) { bel_info(bel).attrs[key] = value; } void Arch::setLutK(int K) { args.K = K; } @@ -268,16 +249,19 @@ void IdString::initialize_arch(const BaseCtx *ctx) {} BelId Arch::getBelByName(IdStringList name) const { - if (bels.count(name)) - return name; - return BelId(); + if (name.size() == 0) + return BelId(); + auto fnd = bel_by_name.find(name); + if (fnd == bel_by_name.end()) + NPNR_ASSERT_FALSE_STR("no bel named " + name.str(getCtx())); + return fnd->second; } -IdStringList Arch::getBelName(BelId bel) const { return bel; } +IdStringList Arch::getBelName(BelId bel) const { return bel_info(bel).name; } Loc Arch::getBelLocation(BelId bel) const { - auto &info = bels.at(bel); + auto &info = bel_info(bel); return Loc(info.x, info.y, info.z); } @@ -291,7 +275,7 @@ BelId Arch::getBelByLocation(Loc loc) const const std::vector &Arch::getBelsByTile(int x, int y) const { return bels_by_tile.at(x).at(y); } -bool Arch::getBelGlobalBuf(BelId bel) const { return bels.at(bel).gb; } +bool Arch::getBelGlobalBuf(BelId bel) const { return bel_info(bel).gb; } uint32_t Arch::getBelChecksum(BelId bel) const { @@ -301,7 +285,7 @@ uint32_t Arch::getBelChecksum(BelId bel) const void Arch::bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) { - bels.at(bel).bound_cell = cell; + bel_info(bel).bound_cell = cell; cell->bel = bel; cell->belStrength = strength; refreshUiBel(bel); @@ -309,40 +293,41 @@ void Arch::bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) void Arch::unbindBel(BelId bel) { - bels.at(bel).bound_cell->bel = BelId(); - bels.at(bel).bound_cell->belStrength = STRENGTH_NONE; - bels.at(bel).bound_cell = nullptr; + auto &bi = bel_info(bel); + bi.bound_cell->bel = BelId(); + bi.bound_cell->belStrength = STRENGTH_NONE; + bi.bound_cell = nullptr; refreshUiBel(bel); } -bool Arch::checkBelAvail(BelId bel) const { return bels.at(bel).bound_cell == nullptr; } +bool Arch::checkBelAvail(BelId bel) const { return bel_info(bel).bound_cell == nullptr; } -CellInfo *Arch::getBoundBelCell(BelId bel) const { return bels.at(bel).bound_cell; } +CellInfo *Arch::getBoundBelCell(BelId bel) const { return bel_info(bel).bound_cell; } -CellInfo *Arch::getConflictingBelCell(BelId bel) const { return bels.at(bel).bound_cell; } +CellInfo *Arch::getConflictingBelCell(BelId bel) const { return bel_info(bel).bound_cell; } -const std::vector &Arch::getBels() const { return bel_ids; } +linear_range Arch::getBels() const { return linear_range(bels.size()); } -IdString Arch::getBelType(BelId bel) const { return bels.at(bel).type; } +IdString Arch::getBelType(BelId bel) const { return bel_info(bel).type; } -bool Arch::getBelHidden(BelId bel) const { return bels.at(bel).hidden; } +bool Arch::getBelHidden(BelId bel) const { return bel_info(bel).hidden; } -const std::map &Arch::getBelAttrs(BelId bel) const { return bels.at(bel).attrs; } +const std::map &Arch::getBelAttrs(BelId bel) const { return bel_info(bel).attrs; } WireId Arch::getBelPinWire(BelId bel, IdString pin) const { - const auto &bdata = bels.at(bel); + const auto &bdata = bel_info(bel); if (!bdata.pins.count(pin)) log_error("bel '%s' has no pin '%s'\n", getCtx()->nameOfBel(bel), pin.c_str(this)); return bdata.pins.at(pin).wire; } -PortType Arch::getBelPinType(BelId bel, IdString pin) const { return bels.at(bel).pins.at(pin).type; } +PortType Arch::getBelPinType(BelId bel, IdString pin) const { return bel_info(bel).pins.at(pin).type; } std::vector Arch::getBelPins(BelId bel) const { std::vector ret; - for (auto &it : bels.at(bel).pins) + for (auto &it : bel_info(bel).pins) ret.push_back(it.first); return ret; } @@ -356,26 +341,25 @@ const std::vector &Arch::getBelPinsForCellPin(const CellInfo *cell_inf WireId Arch::getWireByName(IdStringList name) const { - if (wires.count(name)) - return name; - return WireId(); + if (name.size() == 0) + return WireId(); + auto fnd = wire_by_name.find(name); + if (fnd == wire_by_name.end()) + NPNR_ASSERT_FALSE_STR("no wire named " + name.str(getCtx())); + return fnd->second; } -IdStringList Arch::getWireName(WireId wire) const { return wire; } +IdStringList Arch::getWireName(WireId wire) const { return wire_info(wire).name; } -IdString Arch::getWireType(WireId wire) const { return wires.at(wire).type; } +IdString Arch::getWireType(WireId wire) const { return wire_info(wire).type; } -const std::map &Arch::getWireAttrs(WireId wire) const { return wires.at(wire).attrs; } +const std::map &Arch::getWireAttrs(WireId wire) const { return wire_info(wire).attrs; } -uint32_t Arch::getWireChecksum(WireId wire) const -{ - // FIXME - return 0; -} +uint32_t Arch::getWireChecksum(WireId wire) const { return wire.index; } void Arch::bindWire(WireId wire, NetInfo *net, PlaceStrength strength) { - wires.at(wire).bound_net = net; + wire_info(wire).bound_net = net; net->wires[wire].pip = PipId(); net->wires[wire].strength = strength; refreshUiWire(wire); @@ -383,55 +367,54 @@ void Arch::bindWire(WireId wire, NetInfo *net, PlaceStrength strength) void Arch::unbindWire(WireId wire) { - auto &net_wires = wires.at(wire).bound_net->wires; + auto &net_wires = wire_info(wire).bound_net->wires; auto pip = net_wires.at(wire).pip; if (pip != PipId()) { - pips.at(pip).bound_net = nullptr; + pip_info(pip).bound_net = nullptr; refreshUiPip(pip); } net_wires.erase(wire); - wires.at(wire).bound_net = nullptr; + wire_info(wire).bound_net = nullptr; refreshUiWire(wire); } -bool Arch::checkWireAvail(WireId wire) const { return wires.at(wire).bound_net == nullptr; } +bool Arch::checkWireAvail(WireId wire) const { return wire_info(wire).bound_net == nullptr; } -NetInfo *Arch::getBoundWireNet(WireId wire) const { return wires.at(wire).bound_net; } +NetInfo *Arch::getBoundWireNet(WireId wire) const { return wire_info(wire).bound_net; } -NetInfo *Arch::getConflictingWireNet(WireId wire) const { return wires.at(wire).bound_net; } +NetInfo *Arch::getConflictingWireNet(WireId wire) const { return wire_info(wire).bound_net; } -const std::vector &Arch::getWireBelPins(WireId wire) const { return wires.at(wire).bel_pins; } +const std::vector &Arch::getWireBelPins(WireId wire) const { return wire_info(wire).bel_pins; } -const std::vector &Arch::getWires() const { return wire_ids; } +linear_range Arch::getWires() const { return linear_range(wires.size()); } // --------------------------------------------------------------- PipId Arch::getPipByName(IdStringList name) const { - if (pips.count(name)) - return name; - return PipId(); + if (name.size() == 0) + return PipId(); + auto fnd = pip_by_name.find(name); + if (fnd == pip_by_name.end()) + NPNR_ASSERT_FALSE_STR("no pip named " + name.str(getCtx())); + return fnd->second; } -IdStringList Arch::getPipName(PipId pip) const { return pip; } +IdStringList Arch::getPipName(PipId pip) const { return pip_info(pip).name; } -IdString Arch::getPipType(PipId pip) const { return pips.at(pip).type; } +IdString Arch::getPipType(PipId pip) const { return pip_info(pip).type; } -const std::map &Arch::getPipAttrs(PipId pip) const { return pips.at(pip).attrs; } +const std::map &Arch::getPipAttrs(PipId pip) const { return pip_info(pip).attrs; } -uint32_t Arch::getPipChecksum(PipId wire) const -{ - // FIXME - return 0; -} +uint32_t Arch::getPipChecksum(PipId pip) const { return pip.index; } void Arch::bindPip(PipId pip, NetInfo *net, PlaceStrength strength) { - WireId wire = pips.at(pip).dstWire; - pips.at(pip).bound_net = net; - wires.at(wire).bound_net = net; + WireId wire = pip_info(pip).dstWire; + pip_info(pip).bound_net = net; + wire_info(wire).bound_net = net; net->wires[wire].pip = pip; net->wires[wire].strength = strength; refreshUiPip(pip); @@ -440,41 +423,44 @@ void Arch::bindPip(PipId pip, NetInfo *net, PlaceStrength strength) void Arch::unbindPip(PipId pip) { - WireId wire = pips.at(pip).dstWire; - wires.at(wire).bound_net->wires.erase(wire); - pips.at(pip).bound_net = nullptr; - wires.at(wire).bound_net = nullptr; + WireId wire = pip_info(pip).dstWire; + wire_info(wire).bound_net->wires.erase(wire); + pip_info(pip).bound_net = nullptr; + wire_info(wire).bound_net = nullptr; refreshUiPip(pip); refreshUiWire(wire); } -bool Arch::checkPipAvail(PipId pip) const { return pips.at(pip).bound_net == nullptr; } +bool Arch::checkPipAvail(PipId pip) const { return pip_info(pip).bound_net == nullptr; } bool Arch::checkPipAvailForNet(PipId pip, NetInfo *net) const { - NetInfo *bound_net = pips.at(pip).bound_net; + NetInfo *bound_net = pip_info(pip).bound_net; return bound_net == nullptr || bound_net == net; } -NetInfo *Arch::getBoundPipNet(PipId pip) const { return pips.at(pip).bound_net; } +NetInfo *Arch::getBoundPipNet(PipId pip) const { return pip_info(pip).bound_net; } -NetInfo *Arch::getConflictingPipNet(PipId pip) const { return pips.at(pip).bound_net; } +NetInfo *Arch::getConflictingPipNet(PipId pip) const { return pip_info(pip).bound_net; } -WireId Arch::getConflictingPipWire(PipId pip) const { return pips.at(pip).bound_net ? pips.at(pip).dstWire : WireId(); } +WireId Arch::getConflictingPipWire(PipId pip) const +{ + return pip_info(pip).bound_net ? pip_info(pip).dstWire : WireId(); +} -const std::vector &Arch::getPips() const { return pip_ids; } +linear_range Arch::getPips() const { return linear_range(pips.size()); } -Loc Arch::getPipLocation(PipId pip) const { return pips.at(pip).loc; } +Loc Arch::getPipLocation(PipId pip) const { return pip_info(pip).loc; } -WireId Arch::getPipSrcWire(PipId pip) const { return pips.at(pip).srcWire; } +WireId Arch::getPipSrcWire(PipId pip) const { return pip_info(pip).srcWire; } -WireId Arch::getPipDstWire(PipId pip) const { return pips.at(pip).dstWire; } +WireId Arch::getPipDstWire(PipId pip) const { return pip_info(pip).dstWire; } -DelayQuad Arch::getPipDelay(PipId pip) const { return DelayQuad(pips.at(pip).delay); } +DelayQuad Arch::getPipDelay(PipId pip) const { return DelayQuad(pip_info(pip).delay); } -const std::vector &Arch::getPipsDownhill(WireId wire) const { return wires.at(wire).downhill; } +const std::vector &Arch::getPipsDownhill(WireId wire) const { return wire_info(wire).downhill; } -const std::vector &Arch::getPipsUphill(WireId wire) const { return wires.at(wire).uphill; } +const std::vector &Arch::getPipsUphill(WireId wire) const { return wire_info(wire).uphill; } // --------------------------------------------------------------- @@ -502,8 +488,8 @@ const std::vector &Arch::getGroupGroups(GroupId group) const { return g delay_t Arch::estimateDelay(WireId src, WireId dst) const { - const WireInfo &s = wires.at(src); - const WireInfo &d = wires.at(dst); + const WireInfo &s = wire_info(src); + const WireInfo &d = wire_info(dst); int dx = abs(s.x - d.x); int dy = abs(s.y - d.y); return (dx + dy) * args.delayScale + args.delayOffset; @@ -527,10 +513,10 @@ ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const { ArcBounds bb; - int src_x = wires.at(src).x; - int src_y = wires.at(src).y; - int dst_x = wires.at(dst).x; - int dst_y = wires.at(dst).y; + int src_x = wire_info(src).x; + int src_y = wire_info(src).y; + int dst_x = wire_info(dst).x; + int dst_y = wire_info(dst).y; bb.x0 = src_x; bb.y0 = src_y; @@ -611,11 +597,11 @@ const std::vector &Arch::getDecalGraphics(DecalId decal) const return decal_graphics.at(decal); } -DecalXY Arch::getBelDecal(BelId bel) const { return bels.at(bel).decalxy; } +DecalXY Arch::getBelDecal(BelId bel) const { return bel_info(bel).decalxy; } -DecalXY Arch::getWireDecal(WireId wire) const { return wires.at(wire).decalxy; } +DecalXY Arch::getWireDecal(WireId wire) const { return wire_info(wire).decalxy; } -DecalXY Arch::getPipDecal(PipId pip) const { return pips.at(pip).decalxy; } +DecalXY Arch::getPipDecal(PipId pip) const { return pip_info(pip).decalxy; } DecalXY Arch::getGroupDecal(GroupId group) const { return groups.at(group).decalxy; } diff --git a/generic/arch.h b/generic/arch.h index 7f574f31..885089ca 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -60,8 +60,6 @@ struct WireInfo std::map attrs; NetInfo *bound_net; std::vector downhill, uphill; - BelPin uphill_bel_pin; - std::vector downhill_bel_pins; std::vector bel_pins; DecalXY decalxy; int x, y; @@ -111,23 +109,40 @@ struct CellTiming dict> clockingInfo; }; +template struct linear_range +{ + struct iterator + { + explicit iterator(int32_t index) : index(index){}; + int32_t index; + bool operator==(const iterator &other) const { return index == other.index; } + bool operator!=(const iterator &other) const { return index != other.index; } + void operator++() { ++index; } + TId operator*() const { return TId(index); } + }; + explicit linear_range(int32_t size) : size(size){}; + int32_t size; + iterator begin() const { return iterator(0); } + iterator end() const { return iterator(size); } +}; + struct ArchRanges { using ArchArgsT = ArchArgs; // Bels - using AllBelsRangeT = const std::vector &; + using AllBelsRangeT = linear_range; using TileBelsRangeT = const std::vector &; using BelAttrsRangeT = const std::map &; using BelPinsRangeT = std::vector; using CellBelPinRangeT = const std::vector &; // Wires - using AllWiresRangeT = const std::vector &; + using AllWiresRangeT = linear_range; using DownhillPipRangeT = const std::vector &; using UphillPipRangeT = const std::vector &; using WireBelPinRangeT = const std::vector &; using WireAttrsRangeT = const std::map &; // Pips - using AllPipsRangeT = const std::vector &; + using AllPipsRangeT = linear_range; using PipAttrsRangeT = const std::map &; // Groups using AllGroupsRangeT = std::vector; @@ -147,17 +162,22 @@ struct Arch : ArchAPI { std::string chipName; - dict wires; - dict pips; - dict bels; + std::vector wires; + std::vector pips; + std::vector bels; dict groups; - // These functions include useful errors if not found - WireInfo &wire_info(IdStringList wire); - PipInfo &pip_info(IdStringList wire); - BelInfo &bel_info(IdStringList wire); + WireInfo &wire_info(WireId wire) { return wires.at(wire.index); } + PipInfo &pip_info(PipId pip) { return pips.at(pip.index); } + BelInfo &bel_info(BelId bel) { return bels.at(bel.index); } + + const WireInfo &wire_info(WireId wire) const { return wires.at(wire.index); } + const PipInfo &pip_info(PipId pip) const { return pips.at(pip.index); } + const BelInfo &bel_info(BelId bel) const { return bels.at(bel.index); } - std::vector bel_ids, wire_ids, pip_ids; + dict wire_by_name; + dict pip_by_name; + dict bel_by_name; dict bel_by_loc; std::vector>> bels_by_tile; @@ -170,17 +190,17 @@ struct Arch : ArchAPI dict cellTiming; - void addWire(IdStringList name, IdString type, int x, int y); - void addPip(IdStringList name, IdString type, IdStringList srcWire, IdStringList dstWire, delay_t delay, Loc loc); + WireId addWire(IdStringList name, IdString type, int x, int y); + PipId addPip(IdStringList name, IdString type, WireId srcWire, WireId dstWire, delay_t delay, Loc loc); - void addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidden); - void addBelInput(IdStringList bel, IdString name, IdStringList wire); - void addBelOutput(IdStringList bel, IdString name, IdStringList wire); - void addBelInout(IdStringList bel, IdString name, IdStringList wire); + BelId addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidden); + void addBelInput(BelId bel, IdString name, WireId wire); + void addBelOutput(BelId bel, IdString name, WireId wire); + void addBelInout(BelId bel, IdString name, WireId wire); - void addGroupBel(IdStringList group, IdStringList bel); - void addGroupWire(IdStringList group, IdStringList wire); - void addGroupPip(IdStringList group, IdStringList pip); + void addGroupBel(IdStringList group, BelId bel); + void addGroupWire(IdStringList group, WireId wire); + void addGroupPip(IdStringList group, PipId pip); void addGroupGroup(IdStringList group, IdStringList grp); void addDecalGraphic(DecalId decal, const GraphicElement &graphic); @@ -189,9 +209,9 @@ struct Arch : ArchAPI void setBelDecal(BelId bel, DecalXY decalxy); void setGroupDecal(GroupId group, DecalXY decalxy); - void setWireAttr(IdStringList wire, IdString key, const std::string &value); - void setPipAttr(IdStringList pip, IdString key, const std::string &value); - void setBelAttr(IdStringList bel, IdString key, const std::string &value); + void setWireAttr(WireId wire, IdString key, const std::string &value); + void setPipAttr(PipId pip, IdString key, const std::string &value); + void setBelAttr(BelId bel, IdString key, const std::string &value); void setLutK(int K); void setDelayScaling(double scale, double offset); @@ -234,7 +254,7 @@ struct Arch : ArchAPI bool checkBelAvail(BelId bel) const override; CellInfo *getBoundBelCell(BelId bel) const override; CellInfo *getConflictingBelCell(BelId bel) const override; - const std::vector &getBels() const override; + linear_range getBels() const override; IdString getBelType(BelId bel) const override; bool getBelHidden(BelId bel) const override; const std::map &getBelAttrs(BelId bel) const override; @@ -255,7 +275,7 @@ struct Arch : ArchAPI WireId getConflictingWireWire(WireId wire) const override { return wire; } NetInfo *getConflictingWireNet(WireId wire) const override; DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); } - const std::vector &getWires() const override; + linear_range getWires() const override; const std::vector &getWireBelPins(WireId wire) const override; PipId getPipByName(IdStringList name) const override; @@ -270,7 +290,7 @@ struct Arch : ArchAPI NetInfo *getBoundPipNet(PipId pip) const override; WireId getConflictingPipWire(PipId pip) const override; NetInfo *getConflictingPipNet(PipId pip) const override; - const std::vector &getPips() const override; + linear_range getPips() const override; Loc getPipLocation(PipId pip) const override; WireId getPipSrcWire(PipId pip) const override; WireId getPipDstWire(PipId pip) const override; @@ -307,7 +327,7 @@ struct Arch : ArchAPI { pool cell_types; for (auto bel : bels) { - cell_types.insert(bel.second.type); + cell_types.insert(bel.type); } return std::vector{cell_types.begin(), cell_types.end()}; diff --git a/generic/arch_pybindings.cc b/generic/arch_pybindings.cc index df59b4fe..92c78252 100644 --- a/generic/arch_pybindings.cc +++ b/generic/arch_pybindings.cc @@ -42,6 +42,10 @@ void arch_wrap_python(py::module &m) { using namespace PythonConversion; + typedef linear_range BelRange; + typedef linear_range WireRange; + typedef linear_range AllPipRange; + auto arch_cls = py::class_(m, "Arch").def(py::init()); auto dxy_cls = py::class_>(m, "DecalXY_"); @@ -74,8 +78,8 @@ void arch_wrap_python(py::module &m) conv_from_str>::def_wrap(ctx_cls, "getBoundBelCell"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingBelCell"); - fn_wrapper_0a &>>::def_wrap(ctx_cls, "getBels"); + fn_wrapper_0a>::def_wrap(ctx_cls, + "getBels"); fn_wrapper_2a, conv_from_str, conv_from_str>::def_wrap(ctx_cls, "getBelPinWire"); @@ -96,11 +100,11 @@ void arch_wrap_python(py::module &m) fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingWireNet"); - fn_wrapper_0a &>>::def_wrap(ctx_cls, "getWires"); + fn_wrapper_0a>::def_wrap( + ctx_cls, "getWires"); - fn_wrapper_0a &>>::def_wrap(ctx_cls, "getPips"); + fn_wrapper_0a>::def_wrap( + ctx_cls, "getPips"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getPipChecksum"); fn_wrapper_3a_v, @@ -156,50 +160,50 @@ void arch_wrap_python(py::module &m) "name"_a, "type"_a, "x"_a, "y"_a); fn_wrapper_6a_v, - conv_from_str, conv_from_str, conv_from_str, - pass_through, pass_through>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a, - "srcWire"_a, "dstWire"_a, "delay"_a, "loc"_a); + conv_from_str, conv_from_str, conv_from_str, pass_through, + pass_through>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a, "srcWire"_a, "dstWire"_a, + "delay"_a, "loc"_a); fn_wrapper_5a_v, conv_from_str, pass_through, pass_through, pass_through>::def_wrap(ctx_cls, "addBel", "name"_a, "type"_a, "loc"_a, "gb"_a, "hidden"_a); - fn_wrapper_3a_v, - conv_from_str, conv_from_str>::def_wrap(ctx_cls, "addBelInput", "bel"_a, - "name"_a, "wire"_a); - fn_wrapper_3a_v, - conv_from_str, conv_from_str>::def_wrap(ctx_cls, "addBelOutput", "bel"_a, - "name"_a, "wire"_a); - fn_wrapper_3a_v, - conv_from_str, conv_from_str>::def_wrap(ctx_cls, "addBelInout", "bel"_a, - "name"_a, "wire"_a); + fn_wrapper_3a_v, + conv_from_str, conv_from_str>::def_wrap(ctx_cls, "addBelInput", "bel"_a, "name"_a, + "wire"_a); + fn_wrapper_3a_v, + conv_from_str, conv_from_str>::def_wrap(ctx_cls, "addBelOutput", "bel"_a, + "name"_a, "wire"_a); + fn_wrapper_3a_v, + conv_from_str, conv_from_str>::def_wrap(ctx_cls, "addBelInout", "bel"_a, "name"_a, + "wire"_a); fn_wrapper_2a_v, - conv_from_str>::def_wrap(ctx_cls, "addGroupBel", "group"_a, "bel"_a); + conv_from_str>::def_wrap(ctx_cls, "addGroupBel", "group"_a, "bel"_a); fn_wrapper_2a_v, - conv_from_str>::def_wrap(ctx_cls, "addGroupWire", "group"_a, "wire"_a); + conv_from_str>::def_wrap(ctx_cls, "addGroupWire", "group"_a, "wire"_a); fn_wrapper_2a_v, - conv_from_str>::def_wrap(ctx_cls, "addGroupPip", "group"_a, "pip"_a); - fn_wrapper_2a_v, + conv_from_str>::def_wrap(ctx_cls, "addGroupPip", "group"_a, "pip"_a); + fn_wrapper_2a_v, conv_from_str>::def_wrap(ctx_cls, "addGroupGroup", "group"_a, "grp"_a); fn_wrapper_2a_v, pass_through>::def_wrap(ctx_cls, "addDecalGraphic", (py::arg("decal"), "graphic")); - fn_wrapper_2a_v, + fn_wrapper_2a_v, unwrap_context>::def_wrap(ctx_cls, "setWireDecal", "wire"_a, "decalxy"_a); - fn_wrapper_2a_v, + fn_wrapper_2a_v, unwrap_context>::def_wrap(ctx_cls, "setPipDecal", "pip"_a, "decalxy"_a); - fn_wrapper_2a_v, + fn_wrapper_2a_v, unwrap_context>::def_wrap(ctx_cls, "setBelDecal", "bel"_a, "decalxy"_a); fn_wrapper_2a_v, unwrap_context>::def_wrap(ctx_cls, "setGroupDecal", "group"_a, "decalxy"_a); - fn_wrapper_3a_v, + fn_wrapper_3a_v, conv_from_str, pass_through>::def_wrap(ctx_cls, "setWireAttr", "wire"_a, "key"_a, "value"_a); - fn_wrapper_3a_v, + fn_wrapper_3a_v, conv_from_str, pass_through>::def_wrap(ctx_cls, "setBelAttr", "bel"_a, "key"_a, "value"_a); - fn_wrapper_3a_v, + fn_wrapper_3a_v, conv_from_str, pass_through>::def_wrap(ctx_cls, "setPipAttr", "pip"_a, "key"_a, "value"_a); @@ -254,6 +258,10 @@ void arch_wrap_python(py::module &m) pass_through, conv_from_str, conv_from_str>::def_wrap(ctx_cls, "isValidBelForCellType"); + WRAP_RANGE(m, Bel, conv_to_str); + WRAP_RANGE(m, Wire, conv_to_str); + WRAP_RANGE(m, AllPip, conv_to_str); + WRAP_MAP_UPTR(m, CellMap, "IdCellMap"); WRAP_MAP_UPTR(m, NetMap, "IdNetMap"); WRAP_MAP(m, HierarchyMap, wrap_context, "HierarchyMap"); diff --git a/generic/arch_pybindings.h b/generic/arch_pybindings.h index 9a573540..72d688dc 100644 --- a/generic/arch_pybindings.h +++ b/generic/arch_pybindings.h @@ -26,6 +26,73 @@ NEXTPNR_NAMESPACE_BEGIN +namespace PythonConversion { + +template <> struct string_converter +{ + BelId from_str(Context *ctx, std::string name) { return ctx->getBelByNameStr(name); } + + std::string to_str(Context *ctx, BelId id) + { + if (id == BelId()) + throw bad_wrap(); + return ctx->getBelName(id).str(ctx); + } +}; + +template <> struct string_converter +{ + WireId from_str(Context *ctx, std::string name) { return ctx->getWireByNameStr(name); } + + std::string to_str(Context *ctx, WireId id) + { + if (id == WireId()) + throw bad_wrap(); + return ctx->getWireName(id).str(ctx); + } +}; + +template <> struct string_converter +{ + WireId from_str(Context *ctx, std::string name) { return ctx->getWireByNameStr(name); } + + std::string to_str(Context *ctx, WireId id) + { + if (id == WireId()) + throw bad_wrap(); + return ctx->getWireName(id).str(ctx); + } +}; + +template <> struct string_converter +{ + PipId from_str(Context *ctx, std::string name) { return ctx->getPipByNameStr(name); } + + std::string to_str(Context *ctx, PipId id) + { + if (id == PipId()) + throw bad_wrap(); + return ctx->getPipName(id).str(ctx); + } +}; + +template <> struct string_converter +{ + BelPin from_str(Context *ctx, std::string name) + { + NPNR_ASSERT_FALSE("string_converter::from_str not implemented"); + } + + std::string to_str(Context *ctx, BelPin pin) + { + if (pin.bel == BelId()) + throw bad_wrap(); + return ctx->getBelName(pin.bel).str(ctx) + "/" + pin.pin.str(ctx); + } +}; + +} // namespace PythonConversion + NEXTPNR_NAMESPACE_END #endif #endif diff --git a/generic/archdefs.h b/generic/archdefs.h index c46fba93..2d46c0a2 100644 --- a/generic/archdefs.h +++ b/generic/archdefs.h @@ -27,9 +27,42 @@ NEXTPNR_NAMESPACE_BEGIN typedef float delay_t; -typedef IdStringList BelId; -typedef IdStringList WireId; -typedef IdStringList PipId; +struct BelId +{ + BelId() : index(-1){}; + explicit BelId(int32_t index) : index(index){}; + int32_t index = -1; + + bool operator==(const BelId &other) const { return index == other.index; } + bool operator!=(const BelId &other) const { return index != other.index; } + bool operator<(const BelId &other) const { return index < other.index; } + unsigned int hash() const { return index; } +}; + +struct WireId +{ + WireId() : index(-1){}; + explicit WireId(int32_t index) : index(index){}; + int32_t index = -1; + + bool operator==(const WireId &other) const { return index == other.index; } + bool operator!=(const WireId &other) const { return index != other.index; } + bool operator<(const WireId &other) const { return index < other.index; } + unsigned int hash() const { return index; } +}; + +struct PipId +{ + PipId() : index(-1){}; + explicit PipId(int32_t index) : index(index){}; + int32_t index = -1; + + bool operator==(const PipId &other) const { return index == other.index; } + bool operator!=(const PipId &other) const { return index != other.index; } + bool operator<(const PipId &other) const { return index < other.index; } + unsigned int hash() const { return index; } +}; + typedef IdStringList GroupId; typedef IdStringList DecalId; typedef IdString BelBucketId; diff --git a/generic/examples/write_fasm.py b/generic/examples/write_fasm.py index ede8f16b..057e779c 100644 --- a/generic/examples/write_fasm.py +++ b/generic/examples/write_fasm.py @@ -29,7 +29,7 @@ def write_fasm(ctx, paramCfg, f): for nname, net in sorted(ctx.nets, key=lambda x: str(x[1].name)): print("# Net %s" % nname, file=f) for wire, pip in sorted(net.wires, key=lambda x: str(x[1])): - if pip.pip != "": + if pip.pip is not None: print("%s" % pip.pip, file=f) print("", file=f) for cname, cell in sorted(ctx.cells, key=lambda x: str(x[1].name)): -- cgit v1.2.3