aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/pywrappers.h17
-rw-r--r--docs/generic.md35
-rw-r--r--generic/arch.cc274
-rw-r--r--generic/arch.h78
-rw-r--r--generic/arch_pybindings.cc64
-rw-r--r--generic/arch_pybindings.h67
-rw-r--r--generic/archdefs.h39
-rw-r--r--generic/examples/write_fasm.py2
8 files changed, 348 insertions, 228 deletions
diff --git a/common/pywrappers.h b/common/pywrappers.h
index 66dec6fb..60ef65be 100644
--- a/common/pywrappers.h
+++ b/common/pywrappers.h
@@ -257,7 +257,7 @@ template <typename Class, typename FuncT, FuncT fn, typename arg1_conv> struct f
{
Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls);
- return (base.*fn)(arg1_conv()(ctx, arg1));
+ (base.*fn)(arg1_conv()(ctx, arg1));
}
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@@ -280,7 +280,7 @@ template <typename Class, typename FuncT, FuncT fn, typename arg1_conv, typename
{
Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls);
- return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2));
+ (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2));
}
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@@ -304,7 +304,7 @@ struct fn_wrapper_3a_v
{
Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls);
- return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3));
+ (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3));
}
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@@ -331,8 +331,7 @@ struct fn_wrapper_4a_v
{
Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls);
- return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3),
- arg4_conv()(ctx, arg4));
+ (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), arg4_conv()(ctx, arg4));
}
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@@ -360,8 +359,8 @@ struct fn_wrapper_5a_v
{
Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls);
- return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3),
- arg4_conv()(ctx, arg4), arg5_conv()(ctx, arg5));
+ (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), arg4_conv()(ctx, arg4),
+ arg5_conv()(ctx, arg5));
}
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@@ -390,8 +389,8 @@ struct fn_wrapper_6a_v
{
Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls);
- return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3),
- arg4_conv()(ctx, arg4), arg5_conv()(ctx, arg5), arg6_conv()(ctx, arg6));
+ (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), arg4_conv()(ctx, arg4),
+ arg5_conv()(ctx, arg5), arg6_conv()(ctx, arg6));
}
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
diff --git a/docs/generic.md b/docs/generic.md
index 0562bed3..96db872e 100644
--- a/docs/generic.md
+++ b/docs/generic.md
@@ -12,35 +12,42 @@ will be worked on in the future.
## Python API
-All identifiers (`IdString`) are automatically converted to
-and from a Python string, so no manual conversion is required.
+All identifiers (`IdString`, `IdStringList`, `WireId`, `PipId`, and `BelId`) are
+automatically converted to and from a Python string, so no manual conversion is
+required.
+
+`IdStringList`s will be most efficient if strings can be split according to a
+separator (currently fixed to `/`), as only the components need be stored
+in-memory. For example; instead of needing to store an entire pip name
+`X33/Y45/V4A_TO_A6` which scales badly for large numbers of pips; the strings
+`X33`, `Y45` and `V4A_TO_A6` are stored.
Argument names are included in the Python bindings,
so named arguments may be used.
-### void addWire(IdString name, IdString type, int x, int y);
+### void addWire(IdStringList name, IdString type, int x, int y);
Adds a wire with a name, type (for user purposes only, ignored by all nextpnr code other than the UI) to the FPGA description. x and y give a nominal location of the wire for delay estimation purposes. Delay estimates are important for router performance (as the router uses an A* type algorithm), even if timing is not of importance.
-### addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, float delay, Loc loc);
+### addPip(IdStringList name, IdString type, WireId srcWire, WireId dstWire, float delay, Loc loc);
Adds a pip (programmable connection between two named wires). Pip delays that correspond to delay estimates are important for router performance (as the router uses an A* type algorithm), even if timing is otherwise not of importance.
Loc is constructed using `Loc(x, y, z)`. 'z' for pips is only important if region constraints (e.g. for partial reconfiguration regions) are used.
-### void addBel(IdString name, IdString type, Loc loc, bool gb, bool hidden);
+### void addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidden);
Adds a bel to the FPGA description. Bel type should match the type of cells in the netlist that are placed at this bel (see below for information on special bel types supported by the packer). Loc is constructed using `Loc(x, y, z)` and must be unique. If `hidden` is true, then the bel will not be included in utilisation reports (e.g. for routing/internal use bels).
-### void addBelInput(IdString bel, IdString name, IdString wire);
-### void addBelOutput(IdString bel, IdString name, IdString wire);
-### void addBelInout(IdString bel, IdString name, IdString wire);
+### void addBelInput(BelId bel, IdString name, WireId wire);
+### void addBelOutput(BelId bel, IdString name, WireId wire);
+### void addBelInout(BelId bel, IdString name, WireId wire);
Adds an input, output or inout pin to a bel, with an associated wire. Note that both `bel` and `wire` must have been created before calling this function.
-### void addGroupBel(IdString group, IdString bel);
-### void addGroupWire(IdString group, IdString wire);
-### void addGroupPip(IdString group, IdString pip);
+### void addGroupBel(IdString group, BelId bel);
+### void addGroupWire(IdString group, WireId wire);
+### void addGroupPip(IdString group, PipId pip);
### void addGroupGroup(IdString group, IdString grp);
Add a bel, wire, pip or subgroup to a group, which will be created if it doesn't already exist. Groups are purely for visual presentation purposes in the user interface and are not used by any place-and-route algorithms.
@@ -56,9 +63,9 @@ Add a graphic element to a _decal_, a reusable drawing that may be used to repre
Sets the decal ID and offset for a wire, bel, pip or group in the UI.
-### void setWireAttr(IdString wire, IdString key, const std::string &value);
-### void setPipAttr(IdString pip, IdString key, const std::string &value);
-### void setBelAttr(IdString 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);
Sets an attribute on a wire, pip or bel. Attributes are displayed in the tree view in the UI, but have no bearing on place-and-route itself.
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<BelId> &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<BelId> &Arch::getBels() const { return bel_ids; }
+linear_range<BelId> Arch::getBels() const { return linear_range<BelId>(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<IdString, std::string> &Arch::getBelAttrs(BelId bel) const { return bels.at(bel).attrs; }
+const std::map<IdString, std::string> &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<IdString> Arch::getBelPins(BelId bel) const
{
std::vector<IdString> 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<IdString> &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<IdString, std::string> &Arch::getWireAttrs(WireId wire) const { return wires.at(wire).attrs; }
+const std::map<IdString, std::string> &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<BelPin> &Arch::getWireBelPins(WireId wire) const { return wires.at(wire).bel_pins; }
+const std::vector<BelPin> &Arch::getWireBelPins(WireId wire) const { return wire_info(wire).bel_pins; }
-const std::vector<WireId> &Arch::getWires() const { return wire_ids; }
+linear_range<WireId> Arch::getWires() const { return linear_range<WireId>(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<IdString, std::string> &Arch::getPipAttrs(PipId pip) const { return pips.at(pip).attrs; }
+const std::map<IdString, std::string> &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<PipId> &Arch::getPips() const { return pip_ids; }
+linear_range<PipId> Arch::getPips() const { return linear_range<PipId>(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<PipId> &Arch::getPipsDownhill(WireId wire) const { return wires.at(wire).downhill; }
+const std::vector<PipId> &Arch::getPipsDownhill(WireId wire) const { return wire_info(wire).downhill; }
-const std::vector<PipId> &Arch::getPipsUphill(WireId wire) const { return wires.at(wire).uphill; }
+const std::vector<PipId> &Arch::getPipsUphill(WireId wire) const { return wire_info(wire).uphill; }
// ---------------------------------------------------------------
@@ -502,8 +488,8 @@ const std::vector<GroupId> &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<GraphicElement> &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<IdString, std::string> attrs;
NetInfo *bound_net;
std::vector<PipId> downhill, uphill;
- BelPin uphill_bel_pin;
- std::vector<BelPin> downhill_bel_pins;
std::vector<BelPin> bel_pins;
DecalXY decalxy;
int x, y;
@@ -111,23 +109,40 @@ struct CellTiming
dict<IdString, std::vector<TimingClockingInfo>> clockingInfo;
};
+template <typename TId> 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<BelId> &;
+ using AllBelsRangeT = linear_range<BelId>;
using TileBelsRangeT = const std::vector<BelId> &;
using BelAttrsRangeT = const std::map<IdString, std::string> &;
using BelPinsRangeT = std::vector<IdString>;
using CellBelPinRangeT = const std::vector<IdString> &;
// Wires
- using AllWiresRangeT = const std::vector<WireId> &;
+ using AllWiresRangeT = linear_range<WireId>;
using DownhillPipRangeT = const std::vector<PipId> &;
using UphillPipRangeT = const std::vector<PipId> &;
using WireBelPinRangeT = const std::vector<BelPin> &;
using WireAttrsRangeT = const std::map<IdString, std::string> &;
// Pips
- using AllPipsRangeT = const std::vector<PipId> &;
+ using AllPipsRangeT = linear_range<PipId>;
using PipAttrsRangeT = const std::map<IdString, std::string> &;
// Groups
using AllGroupsRangeT = std::vector<GroupId>;
@@ -147,17 +162,22 @@ struct Arch : ArchAPI<ArchRanges>
{
std::string chipName;
- dict<IdStringList, WireInfo> wires;
- dict<IdStringList, PipInfo> pips;
- dict<IdStringList, BelInfo> bels;
+ std::vector<WireInfo> wires;
+ std::vector<PipInfo> pips;
+ std::vector<BelInfo> bels;
dict<GroupId, GroupInfo> 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<IdStringList> bel_ids, wire_ids, pip_ids;
+ dict<IdStringList, WireId> wire_by_name;
+ dict<IdStringList, PipId> pip_by_name;
+ dict<IdStringList, BelId> bel_by_name;
dict<Loc, BelId> bel_by_loc;
std::vector<std::vector<std::vector<BelId>>> bels_by_tile;
@@ -170,17 +190,17 @@ struct Arch : ArchAPI<ArchRanges>
dict<IdString, CellTiming> 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<ArchRanges>
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<ArchRanges>
bool checkBelAvail(BelId bel) const override;
CellInfo *getBoundBelCell(BelId bel) const override;
CellInfo *getConflictingBelCell(BelId bel) const override;
- const std::vector<BelId> &getBels() const override;
+ linear_range<BelId> getBels() const override;
IdString getBelType(BelId bel) const override;
bool getBelHidden(BelId bel) const override;
const std::map<IdString, std::string> &getBelAttrs(BelId bel) const override;
@@ -255,7 +275,7 @@ struct Arch : ArchAPI<ArchRanges>
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<WireId> &getWires() const override;
+ linear_range<WireId> getWires() const override;
const std::vector<BelPin> &getWireBelPins(WireId wire) const override;
PipId getPipByName(IdStringList name) const override;
@@ -270,7 +290,7 @@ struct Arch : ArchAPI<ArchRanges>
NetInfo *getBoundPipNet(PipId pip) const override;
WireId getConflictingPipWire(PipId pip) const override;
NetInfo *getConflictingPipNet(PipId pip) const override;
- const std::vector<PipId> &getPips() const override;
+ linear_range<PipId> 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<ArchRanges>
{
pool<IdString> cell_types;
for (auto bel : bels) {
- cell_types.insert(bel.second.type);
+ cell_types.insert(bel.type);
}
return std::vector<IdString>{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<BelId> BelRange;
+ typedef linear_range<WireId> WireRange;
+ typedef linear_range<PipId> AllPipRange;
+
auto arch_cls = py::class_<Arch, BaseCtx>(m, "Arch").def(py::init<ArchArgs>());
auto dxy_cls = py::class_<ContextualWrapper<DecalXY>>(m, "DecalXY_");
@@ -74,8 +78,8 @@ void arch_wrap_python(py::module &m)
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBoundBelCell");
fn_wrapper_1a<Context, decltype(&Context::getConflictingBelCell), &Context::getConflictingBelCell,
deref_and_wrap<CellInfo>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell");
- fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels,
- wrap_context<const std::vector<BelId> &>>::def_wrap(ctx_cls, "getBels");
+ fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels, wrap_context<BelRange>>::def_wrap(ctx_cls,
+ "getBels");
fn_wrapper_2a<Context, decltype(&Context::getBelPinWire), &Context::getBelPinWire, conv_to_str<WireId>,
conv_from_str<BelId>, conv_from_str<IdString>>::def_wrap(ctx_cls, "getBelPinWire");
@@ -96,11 +100,11 @@ void arch_wrap_python(py::module &m)
fn_wrapper_1a<Context, decltype(&Context::getConflictingWireNet), &Context::getConflictingWireNet,
deref_and_wrap<NetInfo>, conv_from_str<WireId>>::def_wrap(ctx_cls, "getConflictingWireNet");
- fn_wrapper_0a<Context, decltype(&Context::getWires), &Context::getWires,
- wrap_context<const std::vector<WireId> &>>::def_wrap(ctx_cls, "getWires");
+ fn_wrapper_0a<Context, decltype(&Context::getWires), &Context::getWires, wrap_context<WireRange>>::def_wrap(
+ ctx_cls, "getWires");
- fn_wrapper_0a<Context, decltype(&Context::getPips), &Context::getPips,
- wrap_context<const std::vector<PipId> &>>::def_wrap(ctx_cls, "getPips");
+ fn_wrapper_0a<Context, decltype(&Context::getPips), &Context::getPips, wrap_context<AllPipRange>>::def_wrap(
+ ctx_cls, "getPips");
fn_wrapper_1a<Context, decltype(&Context::getPipChecksum), &Context::getPipChecksum, pass_through<uint32_t>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindPip), &Context::bindPip, conv_from_str<PipId>,
@@ -156,50 +160,50 @@ void arch_wrap_python(py::module &m)
"name"_a, "type"_a, "x"_a,
"y"_a);
fn_wrapper_6a_v<Context, decltype(&Context::addPip), &Context::addPip, conv_from_str<IdStringList>,
- conv_from_str<IdString>, conv_from_str<IdStringList>, conv_from_str<IdStringList>,
- pass_through<delay_t>, pass_through<Loc>>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a,
- "srcWire"_a, "dstWire"_a, "delay"_a, "loc"_a);
+ conv_from_str<IdString>, conv_from_str<WireId>, conv_from_str<WireId>, pass_through<delay_t>,
+ pass_through<Loc>>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a, "srcWire"_a, "dstWire"_a,
+ "delay"_a, "loc"_a);
fn_wrapper_5a_v<Context, decltype(&Context::addBel), &Context::addBel, conv_from_str<IdStringList>,
conv_from_str<IdString>, pass_through<Loc>, pass_through<bool>,
pass_through<bool>>::def_wrap(ctx_cls, "addBel", "name"_a, "type"_a, "loc"_a, "gb"_a, "hidden"_a);
- fn_wrapper_3a_v<Context, decltype(&Context::addBelInput), &Context::addBelInput, conv_from_str<IdStringList>,
- conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelInput", "bel"_a,
- "name"_a, "wire"_a);
- fn_wrapper_3a_v<Context, decltype(&Context::addBelOutput), &Context::addBelOutput, conv_from_str<IdStringList>,
- conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelOutput", "bel"_a,
- "name"_a, "wire"_a);
- fn_wrapper_3a_v<Context, decltype(&Context::addBelInout), &Context::addBelInout, conv_from_str<IdStringList>,
- conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelInout", "bel"_a,
- "name"_a, "wire"_a);
+ fn_wrapper_3a_v<Context, decltype(&Context::addBelInput), &Context::addBelInput, conv_from_str<BelId>,
+ conv_from_str<IdString>, conv_from_str<WireId>>::def_wrap(ctx_cls, "addBelInput", "bel"_a, "name"_a,
+ "wire"_a);
+ fn_wrapper_3a_v<Context, decltype(&Context::addBelOutput), &Context::addBelOutput, conv_from_str<BelId>,
+ conv_from_str<IdString>, conv_from_str<WireId>>::def_wrap(ctx_cls, "addBelOutput", "bel"_a,
+ "name"_a, "wire"_a);
+ fn_wrapper_3a_v<Context, decltype(&Context::addBelInout), &Context::addBelInout, conv_from_str<BelId>,
+ conv_from_str<IdString>, conv_from_str<WireId>>::def_wrap(ctx_cls, "addBelInout", "bel"_a, "name"_a,
+ "wire"_a);
fn_wrapper_2a_v<Context, decltype(&Context::addGroupBel), &Context::addGroupBel, conv_from_str<IdStringList>,
- conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupBel", "group"_a, "bel"_a);
+ conv_from_str<BelId>>::def_wrap(ctx_cls, "addGroupBel", "group"_a, "bel"_a);
fn_wrapper_2a_v<Context, decltype(&Context::addGroupWire), &Context::addGroupWire, conv_from_str<IdStringList>,
- conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupWire", "group"_a, "wire"_a);
+ conv_from_str<WireId>>::def_wrap(ctx_cls, "addGroupWire", "group"_a, "wire"_a);
fn_wrapper_2a_v<Context, decltype(&Context::addGroupPip), &Context::addGroupPip, conv_from_str<IdStringList>,
- conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupPip", "group"_a, "pip"_a);
- fn_wrapper_2a_v<Context, decltype(&Context::addGroupGroup), &Context::addGroupPip, conv_from_str<IdStringList>,
+ conv_from_str<PipId>>::def_wrap(ctx_cls, "addGroupPip", "group"_a, "pip"_a);
+ fn_wrapper_2a_v<Context, decltype(&Context::addGroupGroup), &Context::addGroupGroup, conv_from_str<IdStringList>,
conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupGroup", "group"_a, "grp"_a);
fn_wrapper_2a_v<Context, decltype(&Context::addDecalGraphic), &Context::addDecalGraphic, conv_from_str<DecalId>,
pass_through<GraphicElement>>::def_wrap(ctx_cls, "addDecalGraphic", (py::arg("decal"), "graphic"));
- fn_wrapper_2a_v<Context, decltype(&Context::setWireDecal), &Context::setWireDecal, conv_from_str<DecalId>,
+ fn_wrapper_2a_v<Context, decltype(&Context::setWireDecal), &Context::setWireDecal, conv_from_str<WireId>,
unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setWireDecal", "wire"_a, "decalxy"_a);
- fn_wrapper_2a_v<Context, decltype(&Context::setPipDecal), &Context::setPipDecal, conv_from_str<DecalId>,
+ fn_wrapper_2a_v<Context, decltype(&Context::setPipDecal), &Context::setPipDecal, conv_from_str<PipId>,
unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setPipDecal", "pip"_a, "decalxy"_a);
- fn_wrapper_2a_v<Context, decltype(&Context::setBelDecal), &Context::setBelDecal, conv_from_str<DecalId>,
+ fn_wrapper_2a_v<Context, decltype(&Context::setBelDecal), &Context::setBelDecal, conv_from_str<BelId>,
unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setBelDecal", "bel"_a, "decalxy"_a);
fn_wrapper_2a_v<Context, decltype(&Context::setGroupDecal), &Context::setGroupDecal, conv_from_str<DecalId>,
unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setGroupDecal", "group"_a, "decalxy"_a);
- fn_wrapper_3a_v<Context, decltype(&Context::setWireAttr), &Context::setWireAttr, conv_from_str<DecalId>,
+ fn_wrapper_3a_v<Context, decltype(&Context::setWireAttr), &Context::setWireAttr, conv_from_str<WireId>,
conv_from_str<IdString>, pass_through<std::string>>::def_wrap(ctx_cls, "setWireAttr", "wire"_a,
"key"_a, "value"_a);
- fn_wrapper_3a_v<Context, decltype(&Context::setBelAttr), &Context::setBelAttr, conv_from_str<DecalId>,
+ fn_wrapper_3a_v<Context, decltype(&Context::setBelAttr), &Context::setBelAttr, conv_from_str<BelId>,
conv_from_str<IdString>, pass_through<std::string>>::def_wrap(ctx_cls, "setBelAttr", "bel"_a,
"key"_a, "value"_a);
- fn_wrapper_3a_v<Context, decltype(&Context::setPipAttr), &Context::setPipAttr, conv_from_str<DecalId>,
+ fn_wrapper_3a_v<Context, decltype(&Context::setPipAttr), &Context::setPipAttr, conv_from_str<PipId>,
conv_from_str<IdString>, pass_through<std::string>>::def_wrap(ctx_cls, "setPipAttr", "pip"_a,
"key"_a, "value"_a);
@@ -254,6 +258,10 @@ void arch_wrap_python(py::module &m)
pass_through<bool>, conv_from_str<IdString>, conv_from_str<BelId>>::def_wrap(ctx_cls,
"isValidBelForCellType");
+ WRAP_RANGE(m, Bel, conv_to_str<BelId>);
+ WRAP_RANGE(m, Wire, conv_to_str<WireId>);
+ WRAP_RANGE(m, AllPip, conv_to_str<PipId>);
+
WRAP_MAP_UPTR(m, CellMap, "IdCellMap");
WRAP_MAP_UPTR(m, NetMap, "IdNetMap");
WRAP_MAP(m, HierarchyMap, wrap_context<HierarchicalCell &>, "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>
+{
+ 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>
+{
+ 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<const WireId>
+{
+ 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>
+{
+ 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>
+{
+ BelPin from_str(Context *ctx, std::string name)
+ {
+ NPNR_ASSERT_FALSE("string_converter<BelPin>::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)):