diff --git a/common/arch_pybindings_shared.h b/common/arch_pybindings_shared.h new file mode 100644 index 00000000..b90e80ec --- /dev/null +++ b/common/arch_pybindings_shared.h @@ -0,0 +1,114 @@ +// Common Python bindings #included by all arches + +readonly_wrapper>::def_wrap(ctx_cls, +"cells"); +readonly_wrapper>::def_wrap(ctx_cls, +"nets"); +readonly_wrapper>::def_wrap(ctx_cls, "net_aliases"); + +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getNetByAlias"); +fn_wrapper_2a_v, +pass_through>::def_wrap(ctx_cls, "addClock"); +fn_wrapper_5a_v, pass_through, pass_through, pass_through, +pass_through>::def_wrap(ctx_cls, "createRectangularRegion"); +fn_wrapper_2a_v, +conv_from_str>::def_wrap(ctx_cls, "addBelToRegion"); +fn_wrapper_2a_v, conv_from_str>::def_wrap(ctx_cls, "constrainCellToRegion"); + + +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "createNet"); +fn_wrapper_3a_v, conv_from_str, +conv_from_str>::def_wrap(ctx_cls, "connectPort"); +fn_wrapper_2a_v, +conv_from_str>::def_wrap(ctx_cls, "disconnectPort"); +fn_wrapper_1a_v>::def_wrap( + ctx_cls, "ripupNet"); +fn_wrapper_1a_v>::def_wrap( + ctx_cls, "lockNetRouting"); + +fn_wrapper_2a, +conv_from_str, conv_from_str>::def_wrap(ctx_cls, "createCell"); +fn_wrapper_2a_v, conv_from_str>::def_wrap(ctx_cls, "copyBelPorts"); + +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getBelType"); +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "checkBelAvail"); +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getBelChecksum"); +fn_wrapper_3a_v, +addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindBel"); +fn_wrapper_1a_v>::def_wrap( + ctx_cls, "unbindBel"); +fn_wrapper_1a, +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_2a, +conv_from_str, conv_from_str>::def_wrap(ctx_cls, "getBelPinWire"); +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getWireBelPins"); + +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getWireChecksum"); +fn_wrapper_3a_v, +addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindWire"); +fn_wrapper_1a_v>::def_wrap( + ctx_cls, "unbindWire"); +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "checkWireAvail"); +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getBoundWireNet"); +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, "getPips"); +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getPipChecksum"); +fn_wrapper_3a_v, +addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindPip"); +fn_wrapper_1a_v>::def_wrap( + ctx_cls, "unbindPip"); +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "checkPipAvail"); +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getBoundPipNet"); +fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingPipNet"); + +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getPipsDownhill"); +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getPipsUphill"); +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getWireAliases"); + +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getPipSrcWire"); +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getPipDstWire"); +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getPipDelay"); + +fn_wrapper_1a, +pass_through>::def_wrap(ctx_cls, "getPackagePinBel"); +fn_wrapper_1a, +conv_from_str>::def_wrap(ctx_cls, "getBelPackagePin"); + +fn_wrapper_0a>::def_wrap( + ctx_cls, "getChipName"); +fn_wrapper_0a>::def_wrap(ctx_cls, +"archId"); diff --git a/common/nextpnr.cc b/common/nextpnr.cc index d73c0c02..933f124c 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -19,6 +19,7 @@ #include "nextpnr.h" #include +#include "design_utils.h" #include "log.h" NEXTPNR_NAMESPACE_BEGIN @@ -144,6 +145,27 @@ Property::Property(const std::string &strval) : is_string(true), str(strval), in Property::Property(State bit) : is_string(false), str(std::string("") + char(bit)), intval(bit == S1) {} +void CellInfo::addInput(IdString name) +{ + ports[name].name = name; + ports[name].type = PORT_IN; +} +void CellInfo::addOutput(IdString name) +{ + ports[name].name = name; + ports[name].type = PORT_OUT; +} +void CellInfo::addInout(IdString name) +{ + ports[name].name = name; + ports[name].type = PORT_INOUT; +} + +void CellInfo::setParam(IdString name, Property value) { params[name] = value; } +void CellInfo::unsetParam(IdString name) { params.erase(name); } +void CellInfo::setAttr(IdString name, Property value) { attrs[name] = value; } +void CellInfo::unsetAttr(IdString name) { attrs.erase(name); } + std::string Property::to_string() const { if (is_string) { @@ -638,4 +660,67 @@ void BaseCtx::attributesToArchInfo() getCtx()->assignArchInfo(); } +NetInfo *BaseCtx::createNet(IdString name) +{ + NPNR_ASSERT(!nets.count(name)); + NPNR_ASSERT(!net_aliases.count(name)); + std::unique_ptr net{new NetInfo}; + net->name = name; + net_aliases[name] = name; + NetInfo *ptr = net.get(); + nets[name] = std::move(net); + refreshUi(); + return ptr; +} + +void BaseCtx::connectPort(IdString net, IdString cell, IdString port) +{ + NetInfo *net_info = getNetByAlias(net); + CellInfo *cell_info = cells.at(cell).get(); + connect_port(getCtx(), net_info, cell_info, port); +} + +void BaseCtx::disconnectPort(IdString cell, IdString port) +{ + CellInfo *cell_info = cells.at(cell).get(); + disconnect_port(getCtx(), cell_info, port); +} + +void BaseCtx::ripupNet(IdString name) +{ + NetInfo *net_info = getNetByAlias(name); + std::vector to_unbind; + for (auto &wire : net_info->wires) + to_unbind.push_back(wire.first); + for (auto &unbind : to_unbind) + getCtx()->unbindWire(unbind); +} +void BaseCtx::lockNetRouting(IdString name) +{ + NetInfo *net_info = getNetByAlias(name); + for (auto &wire : net_info->wires) + wire.second.strength = STRENGTH_USER; +} + +CellInfo *BaseCtx::createCell(IdString name, IdString type) +{ + NPNR_ASSERT(!cells.count(name)); + std::unique_ptr cell{new CellInfo}; + cell->name = name; + cell->type = type; + CellInfo *ptr = cell.get(); + cells[name] = std::move(cell); + refreshUi(); + return ptr; +} + +void BaseCtx::copyBelPorts(IdString cell, BelId bel) +{ + CellInfo *cell_info = cells.at(cell).get(); + for (auto pin : getCtx()->getBelPins(bel)) { + cell_info->ports[pin].name = pin; + cell_info->ports[pin].type = getCtx()->getBelPinType(bel, pin); + } +} + NEXTPNR_NAMESPACE_END diff --git a/common/nextpnr.h b/common/nextpnr.h index 4f9f7f23..bae828f6 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -445,6 +445,15 @@ struct CellInfo : ArchCellInfo Region *region = nullptr; TimingConstrObjectId tmg_id; + + void addInput(IdString name); + void addOutput(IdString name); + void addInout(IdString name); + + void setParam(IdString name, Property value); + void unsetParam(IdString name); + void setAttr(IdString name, Property value); + void unsetAttr(IdString name); }; enum TimingPortClass @@ -741,7 +750,10 @@ struct BaseCtx TimingConstrObjectId timingCellObject(CellInfo *cell); TimingConstrObjectId timingPortObject(CellInfo *cell, IdString port); - NetInfo *getNetByAlias(IdString alias) const { return nets.at(net_aliases.at(alias)).get(); } + NetInfo *getNetByAlias(IdString alias) const + { + return nets.count(alias) ? nets.at(alias).get() : nets.at(net_aliases.at(alias)).get(); + } void addConstraint(std::unique_ptr constr); void removeConstraint(IdString constrName); @@ -752,6 +764,16 @@ struct BaseCtx void addBelToRegion(IdString name, BelId bel); void constrainCellToRegion(IdString cell, IdString region_name); + // Helper functions for Python bindings + NetInfo *createNet(IdString name); + void connectPort(IdString net, IdString cell, IdString port); + void disconnectPort(IdString cell, IdString port); + void ripupNet(IdString name); + void lockNetRouting(IdString name); + + CellInfo *createCell(IdString name, IdString type); + void copyBelPorts(IdString cell, BelId bel); + // Workaround for lack of wrappable constructors DecalXY constructDecalXY(DecalId decal, float x, float y); diff --git a/common/pybindings.cc b/common/pybindings.cc index 3f2cb811..03979233 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -160,6 +160,22 @@ BOOST_PYTHON_MODULE(MODULE_NAME) readonly_wrapper>::def_wrap(ci_cls, "pins"); + fn_wrapper_1a_v>::def_wrap( + ci_cls, "addInput"); + fn_wrapper_1a_v>::def_wrap(ci_cls, "addOutput"); + fn_wrapper_1a_v>::def_wrap( + ci_cls, "addInout"); + + fn_wrapper_2a_v, + conv_from_str>::def_wrap(ci_cls, "setParam"); + fn_wrapper_1a_v>::def_wrap(ci_cls, "unsetParam"); + fn_wrapper_2a_v, + conv_from_str>::def_wrap(ci_cls, "setAttr"); + fn_wrapper_1a_v>::def_wrap(ci_cls, "unsetAttr"); + auto pi_cls = class_>("PortInfo", no_init); readwrite_wrapper, conv_from_str>::def_wrap(pi_cls, "name"); diff --git a/docs/python.md b/docs/python.md new file mode 100644 index 00000000..d850300d --- /dev/null +++ b/docs/python.md @@ -0,0 +1,87 @@ +# Using the Python API + +nextpnr provides Python bindings to its internal APIs to enable customisation of the FPGA CAD flow. + +If you are interested in using Python to describe the FPGA rather than customise or explore the flow, see the [nextpnr Generic Architecture](generic.md) documentation. + +## Running Python Scripts + +Python scripts can be run at any point in the flow. The following command line arguments are used to run a script: + + - **--pre-pack script.py**: after reading the JSON, before packing + - **--pre-place script.py**: after packing, before placement + - **--pre-route script.py**: after placement, before routing + - **--post-route script.py**: after routing, before bitstream generation + +## Binding Overview + +The internal `Context` object providing access to the FPGA architecture and netlist is exposed automatically to the script as a global variable `ctx`. + +Internally, nextpnr uses a fast indexed string pool called `IdString`. This is automatically and transparently converted to/from Python strings by the Python binding layer. + +Likewise, the architecture identifiers `BelId`, `WireId` and `PipId` are also translated to/from Python strings containing the object name automatically. + +To query the FPGA architecture, use the functions described in the [Architecture API documentation](archapi.md). Ranges can be iterated over in the same way as any other Python range. + +## Netlist Access + +### Accessing nets + +There is a dictionary `ctx.nets` that provides access to all of the nets in a design by name. Each net item has the following fields: + + - `name`: name of the net + - `wires`: a map of wires used by the net; from wire to the pip driving that wire + - `driver`: a `PortRef` for the net's driving (source) port + - `users`: a list of `PortRef`s for the net's sink ports + - `attrs`: a read-only dictionary of attributes on the net + +A `PortRef` has three fields: + - `cell`: a reference to the cell the port is on + - `port`: the name of the port + - `budget`: the timing budget of the port + +### Accessing cells + +There is a dictionary `ctx.cells` that provides access to all of the cells in a design by name. Each cell item has the following fields: + + - `name`: name of the cell + - `type`: type of the cell + - `ports`: a read-only dictionary of ports on the cell. Each port has the following fields: + - `name`: name of the port + - `net`: reference to the connected net, or `None` if disconnected + - `type`: direction of the port + - `params`: a read-only dictionary of parameters on the cell + - `attrs`: a read-only dictionary of attributes on the cell + - `bel`: the Bel the cell is placed on + +Cells also have the following member functions: + - `addInput(name)`: add a new input port with a given name + - `addOutput(name)`: add a new output port with a given name + - `addInout(name)`: add a new bidirectional port with a given name + - `setParam(name, value)`: set a parameter on a cell to a given value + - `unsetParam(name)`: remove a parameter from the cell + - `setAttr(name, value)`: set an attribute on a cell to a given value + - `unsetAttr(name)`: remove an attribute from the cell + +The value given to `setParam` and `setAttr` should be a string of `[01xz]*` for four-state bitvectors and numerical values. Other values will be interpreted as a textual string. Textual strings of only `[01xz]* *` should have an extra space added at the end which will be stripped off and avoids any ambiguous cases between strings and four-state bitvectors. + +### Creating Objects + +`ctx` has two functions for creating new netlist objects. Both return the created object: + - `createNet(name)` + - `createCell(name, type)` (note this creates an empty cell, ports must be added separately) + +### Other manipulations + +`ctx` has some other helper functions for netlist manipulations: + + - `connectPort(netname, cellname, portname)`: connect a cell port to a net + - `disconnectPort(cellname, portname)`: disconnect a cell port from its net + - `ripupNet(netname)`: remove all routing from a net (but keep netlist connections intact) + - `lockNetRouting(netname)`: set the routing of a net as fixed + - `copyBelPorts(cellname, belname)`: replicate the port definitions of a Bel onto a cell (useful for creating standard cells, as `createCell` doesn't create any ports). + +## Constraints + +See the [constraints documentation](constraints.md) + diff --git a/ecp5/arch_pybindings.cc b/ecp5/arch_pybindings.cc index e131826c..da6d3e50 100644 --- a/ecp5/arch_pybindings.cc +++ b/ecp5/arch_pybindings.cc @@ -46,110 +46,16 @@ void arch_wrap_python() .def("place", &Context::place) .def("route", &Context::route); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getBelType"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "checkBelAvail"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getBelChecksum"); - fn_wrapper_3a_v, - addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindBel"); - fn_wrapper_1a_v>::def_wrap( - ctx_cls, "unbindBel"); - fn_wrapper_1a, - 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_2a, - conv_from_str, conv_from_str>::def_wrap(ctx_cls, "getBelPinWire"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getWireBelPins"); - - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getWireChecksum"); - fn_wrapper_3a_v, - addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindWire"); - fn_wrapper_1a_v>::def_wrap( - ctx_cls, "unbindWire"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "checkWireAvail"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getBoundWireNet"); - 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, "getPips"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getPipChecksum"); - fn_wrapper_3a_v, - addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindPip"); - fn_wrapper_1a_v>::def_wrap( - ctx_cls, "unbindPip"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "checkPipAvail"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getBoundPipNet"); - fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingPipNet"); - - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getPipsDownhill"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getPipsUphill"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getWireAliases"); - - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getPipSrcWire"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getPipDstWire"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getPipDelay"); - - fn_wrapper_1a, - pass_through>::def_wrap(ctx_cls, "getPackagePinBel"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getBelPackagePin"); - - fn_wrapper_0a>::def_wrap( - ctx_cls, "getChipName"); - fn_wrapper_0a>::def_wrap(ctx_cls, - "archId"); - typedef std::unordered_map> CellMap; typedef std::unordered_map> NetMap; typedef std::unordered_map AliasMap; - readonly_wrapper>::def_wrap(ctx_cls, - "cells"); - readonly_wrapper>::def_wrap(ctx_cls, - "nets"); - readonly_wrapper>::def_wrap(ctx_cls, "net_aliases"); - - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getNetByAlias"); - fn_wrapper_2a_v, - pass_through>::def_wrap(ctx_cls, "addClock"); - fn_wrapper_5a_v, pass_through, pass_through, pass_through, - pass_through>::def_wrap(ctx_cls, "createRectangularRegion"); - fn_wrapper_2a_v, - conv_from_str>::def_wrap(ctx_cls, "addBelToRegion"); - fn_wrapper_2a_v, conv_from_str>::def_wrap(ctx_cls, "constrainCellToRegion"); - auto belpin_cls = class_>("BelPin", no_init); readonly_wrapper>::def_wrap(belpin_cls, "bel"); readonly_wrapper>::def_wrap(belpin_cls, "pin"); +#include "arch_pybindings_shared.h" + WRAP_RANGE(Bel, conv_to_str); WRAP_RANGE(Wire, conv_to_str); WRAP_RANGE(AllPip, conv_to_str); diff --git a/ice40/arch_pybindings.cc b/ice40/arch_pybindings.cc index a9aaeb83..cef7c58f 100644 --- a/ice40/arch_pybindings.cc +++ b/ice40/arch_pybindings.cc @@ -57,110 +57,16 @@ void arch_wrap_python() .def("place", &Context::place) .def("route", &Context::route); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getBelType"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "checkBelAvail"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getBelChecksum"); - fn_wrapper_3a_v, - addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindBel"); - fn_wrapper_1a_v>::def_wrap( - ctx_cls, "unbindBel"); - fn_wrapper_1a, - 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_2a, - conv_from_str, conv_from_str>::def_wrap(ctx_cls, "getBelPinWire"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getWireBelPins"); - - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getWireChecksum"); - fn_wrapper_3a_v, - addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindWire"); - fn_wrapper_1a_v>::def_wrap( - ctx_cls, "unbindWire"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "checkWireAvail"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getBoundWireNet"); - 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, "getPips"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getPipChecksum"); - fn_wrapper_3a_v, - addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindPip"); - fn_wrapper_1a_v>::def_wrap( - ctx_cls, "unbindPip"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "checkPipAvail"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getBoundPipNet"); - fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingPipNet"); - - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getPipsDownhill"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getPipsUphill"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getWireAliases"); - - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getPipSrcWire"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getPipDstWire"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getPipDelay"); - - fn_wrapper_1a, - pass_through>::def_wrap(ctx_cls, "getPackagePinBel"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getBelPackagePin"); - - fn_wrapper_0a>::def_wrap( - ctx_cls, "getChipName"); - fn_wrapper_0a>::def_wrap(ctx_cls, - "archId"); - typedef std::unordered_map> CellMap; typedef std::unordered_map> NetMap; typedef std::unordered_map AliasMap; - readonly_wrapper>::def_wrap(ctx_cls, - "cells"); - readonly_wrapper>::def_wrap(ctx_cls, - "nets"); - readonly_wrapper>::def_wrap(ctx_cls, "net_aliases"); - - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getNetByAlias"); - fn_wrapper_2a_v, - pass_through>::def_wrap(ctx_cls, "addClock"); - fn_wrapper_5a_v, pass_through, pass_through, pass_through, - pass_through>::def_wrap(ctx_cls, "createRectangularRegion"); - fn_wrapper_2a_v, - conv_from_str>::def_wrap(ctx_cls, "addBelToRegion"); - fn_wrapper_2a_v, conv_from_str>::def_wrap(ctx_cls, "constrainCellToRegion"); - auto belpin_cls = class_>("BelPin", no_init); readonly_wrapper>::def_wrap(belpin_cls, "bel"); readonly_wrapper>::def_wrap(belpin_cls, "pin"); +#include "arch_pybindings_shared.h" + WRAP_RANGE(Bel, conv_to_str); WRAP_RANGE(Wire, conv_to_str); WRAP_RANGE(AllPip, conv_to_str);