diff options
author | David Shah <dave@ds0.me> | 2019-09-19 20:15:42 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-19 20:15:42 +0100 |
commit | cb71b488ecaf34ea2d55bb2bfe5b1b6ebfd06a6e (patch) | |
tree | 51512791d33754c31145182976c4dd8478591d99 | |
parent | f8b3c13a538501369c13ca4053371c3d8ead32ae (diff) | |
parent | 6bb098b4761ba6d5fbbda07b3dcb88356ece6ce1 (diff) | |
download | nextpnr-cb71b488ecaf34ea2d55bb2bfe5b1b6ebfd06a6e.tar.gz nextpnr-cb71b488ecaf34ea2d55bb2bfe5b1b6ebfd06a6e.tar.bz2 nextpnr-cb71b488ecaf34ea2d55bb2bfe5b1b6ebfd06a6e.zip |
Merge pull request #332 from YosysHQ/dave/python-refactor
Improving Python API and adding docs for it
-rw-r--r-- | common/arch_pybindings_shared.h | 114 | ||||
-rw-r--r-- | common/nextpnr.cc | 85 | ||||
-rw-r--r-- | common/nextpnr.h | 24 | ||||
-rw-r--r-- | common/pybindings.cc | 16 | ||||
-rw-r--r-- | docs/python.md | 87 | ||||
-rw-r--r-- | ecp5/arch_pybindings.cc | 98 | ||||
-rw-r--r-- | ice40/arch_pybindings.cc | 98 |
7 files changed, 329 insertions, 193 deletions
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<Context, decltype(&Context::cells), &Context::cells, wrap_context<CellMap &>>::def_wrap(ctx_cls, +"cells"); +readonly_wrapper<Context, decltype(&Context::nets), &Context::nets, wrap_context<NetMap &>>::def_wrap(ctx_cls, +"nets"); +readonly_wrapper<Context, decltype(&Context::net_aliases), &Context::net_aliases, + wrap_context<AliasMap &>>::def_wrap(ctx_cls, "net_aliases"); + +fn_wrapper_1a<Context, decltype(&Context::getNetByAlias), &Context::getNetByAlias, deref_and_wrap<NetInfo>, +conv_from_str<IdString>>::def_wrap(ctx_cls, "getNetByAlias"); +fn_wrapper_2a_v<Context, decltype(&Context::addClock), &Context::addClock, conv_from_str<IdString>, +pass_through<float>>::def_wrap(ctx_cls, "addClock"); +fn_wrapper_5a_v<Context, decltype(&Context::createRectangularRegion), &Context::createRectangularRegion, + conv_from_str<IdString>, pass_through<int>, pass_through<int>, pass_through<int>, +pass_through<int>>::def_wrap(ctx_cls, "createRectangularRegion"); +fn_wrapper_2a_v<Context, decltype(&Context::addBelToRegion), &Context::addBelToRegion, conv_from_str<IdString>, +conv_from_str<BelId>>::def_wrap(ctx_cls, "addBelToRegion"); +fn_wrapper_2a_v<Context, decltype(&Context::constrainCellToRegion), &Context::constrainCellToRegion, + conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "constrainCellToRegion"); + + +fn_wrapper_1a<Context, decltype(&Context::createNet), &Context::createNet, deref_and_wrap<NetInfo>, +conv_from_str<IdString>>::def_wrap(ctx_cls, "createNet"); +fn_wrapper_3a_v<Context, decltype(&Context::connectPort), &Context::connectPort, conv_from_str<IdString>, conv_from_str<IdString>, +conv_from_str<IdString>>::def_wrap(ctx_cls, "connectPort"); +fn_wrapper_2a_v<Context, decltype(&Context::disconnectPort), &Context::disconnectPort, conv_from_str<IdString>, +conv_from_str<IdString>>::def_wrap(ctx_cls, "disconnectPort"); +fn_wrapper_1a_v<Context, decltype(&Context::ripupNet), &Context::ripupNet, conv_from_str<IdString>>::def_wrap( + ctx_cls, "ripupNet"); +fn_wrapper_1a_v<Context, decltype(&Context::lockNetRouting), &Context::lockNetRouting, conv_from_str<IdString>>::def_wrap( + ctx_cls, "lockNetRouting"); + +fn_wrapper_2a<Context, decltype(&Context::createCell), &Context::createCell, deref_and_wrap<CellInfo>, +conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "createCell"); +fn_wrapper_2a_v<Context, decltype(&Context::copyBelPorts), &Context::copyBelPorts, +conv_from_str<IdString>, conv_from_str<BelId>>::def_wrap(ctx_cls, "copyBelPorts"); + +fn_wrapper_1a<Context, decltype(&Context::getBelType), &Context::getBelType, conv_to_str<IdString>, +conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelType"); +fn_wrapper_1a<Context, decltype(&Context::checkBelAvail), &Context::checkBelAvail, pass_through<bool>, +conv_from_str<BelId>>::def_wrap(ctx_cls, "checkBelAvail"); +fn_wrapper_1a<Context, decltype(&Context::getBelChecksum), &Context::getBelChecksum, pass_through<uint32_t>, +conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelChecksum"); +fn_wrapper_3a_v<Context, decltype(&Context::bindBel), &Context::bindBel, conv_from_str<BelId>, +addr_and_unwrap<CellInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindBel"); +fn_wrapper_1a_v<Context, decltype(&Context::unbindBel), &Context::unbindBel, conv_from_str<BelId>>::def_wrap( + ctx_cls, "unbindBel"); +fn_wrapper_1a<Context, decltype(&Context::getBoundBelCell), &Context::getBoundBelCell, deref_and_wrap<CellInfo>, +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<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"); +fn_wrapper_1a<Context, decltype(&Context::getWireBelPins), &Context::getWireBelPins, wrap_context<BelPinRange>, +conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireBelPins"); + +fn_wrapper_1a<Context, decltype(&Context::getWireChecksum), &Context::getWireChecksum, pass_through<uint32_t>, +conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireChecksum"); +fn_wrapper_3a_v<Context, decltype(&Context::bindWire), &Context::bindWire, conv_from_str<WireId>, +addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindWire"); +fn_wrapper_1a_v<Context, decltype(&Context::unbindWire), &Context::unbindWire, conv_from_str<WireId>>::def_wrap( + ctx_cls, "unbindWire"); +fn_wrapper_1a<Context, decltype(&Context::checkWireAvail), &Context::checkWireAvail, pass_through<bool>, +conv_from_str<WireId>>::def_wrap(ctx_cls, "checkWireAvail"); +fn_wrapper_1a<Context, decltype(&Context::getBoundWireNet), &Context::getBoundWireNet, deref_and_wrap<NetInfo>, +conv_from_str<WireId>>::def_wrap(ctx_cls, "getBoundWireNet"); +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<WireRange>>::def_wrap( + ctx_cls, "getWires"); + +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>, +addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindPip"); +fn_wrapper_1a_v<Context, decltype(&Context::unbindPip), &Context::unbindPip, conv_from_str<PipId>>::def_wrap( + ctx_cls, "unbindPip"); +fn_wrapper_1a<Context, decltype(&Context::checkPipAvail), &Context::checkPipAvail, pass_through<bool>, +conv_from_str<PipId>>::def_wrap(ctx_cls, "checkPipAvail"); +fn_wrapper_1a<Context, decltype(&Context::getBoundPipNet), &Context::getBoundPipNet, deref_and_wrap<NetInfo>, +conv_from_str<PipId>>::def_wrap(ctx_cls, "getBoundPipNet"); +fn_wrapper_1a<Context, decltype(&Context::getConflictingPipNet), &Context::getConflictingPipNet, + deref_and_wrap<NetInfo>, conv_from_str<PipId>>::def_wrap(ctx_cls, "getConflictingPipNet"); + +fn_wrapper_1a<Context, decltype(&Context::getPipsDownhill), &Context::getPipsDownhill, wrap_context<PipRange>, +conv_from_str<WireId>>::def_wrap(ctx_cls, "getPipsDownhill"); +fn_wrapper_1a<Context, decltype(&Context::getPipsUphill), &Context::getPipsUphill, wrap_context<PipRange>, +conv_from_str<WireId>>::def_wrap(ctx_cls, "getPipsUphill"); +fn_wrapper_1a<Context, decltype(&Context::getWireAliases), &Context::getWireAliases, wrap_context<PipRange>, +conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireAliases"); + +fn_wrapper_1a<Context, decltype(&Context::getPipSrcWire), &Context::getPipSrcWire, conv_to_str<WireId>, +conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipSrcWire"); +fn_wrapper_1a<Context, decltype(&Context::getPipDstWire), &Context::getPipDstWire, conv_to_str<WireId>, +conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipDstWire"); +fn_wrapper_1a<Context, decltype(&Context::getPipDelay), &Context::getPipDelay, pass_through<DelayInfo>, +conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipDelay"); + +fn_wrapper_1a<Context, decltype(&Context::getPackagePinBel), &Context::getPackagePinBel, conv_to_str<BelId>, +pass_through<std::string>>::def_wrap(ctx_cls, "getPackagePinBel"); +fn_wrapper_1a<Context, decltype(&Context::getBelPackagePin), &Context::getBelPackagePin, pass_through<std::string>, +conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelPackagePin"); + +fn_wrapper_0a<Context, decltype(&Context::getChipName), &Context::getChipName, pass_through<std::string>>::def_wrap( + ctx_cls, "getChipName"); +fn_wrapper_0a<Context, decltype(&Context::archId), &Context::archId, conv_to_str<IdString>>::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 <boost/algorithm/string.hpp> +#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<NetInfo> 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<WireId> 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<CellInfo> 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<TimingConstraint> 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<CellInfo &, decltype(&CellInfo::pins), &CellInfo::pins, wrap_context<PinMap &>>::def_wrap(ci_cls, "pins"); + fn_wrapper_1a_v<CellInfo &, decltype(&CellInfo::addInput), &CellInfo::addInput, conv_from_str<IdString>>::def_wrap( + ci_cls, "addInput"); + fn_wrapper_1a_v<CellInfo &, decltype(&CellInfo::addOutput), &CellInfo::addOutput, + conv_from_str<IdString>>::def_wrap(ci_cls, "addOutput"); + fn_wrapper_1a_v<CellInfo &, decltype(&CellInfo::addInout), &CellInfo::addInout, conv_from_str<IdString>>::def_wrap( + ci_cls, "addInout"); + + fn_wrapper_2a_v<CellInfo &, decltype(&CellInfo::setParam), &CellInfo::setParam, conv_from_str<IdString>, + conv_from_str<Property>>::def_wrap(ci_cls, "setParam"); + fn_wrapper_1a_v<CellInfo &, decltype(&CellInfo::unsetParam), &CellInfo::unsetParam, + conv_from_str<IdString>>::def_wrap(ci_cls, "unsetParam"); + fn_wrapper_2a_v<CellInfo &, decltype(&CellInfo::setAttr), &CellInfo::setAttr, conv_from_str<IdString>, + conv_from_str<Property>>::def_wrap(ci_cls, "setAttr"); + fn_wrapper_1a_v<CellInfo &, decltype(&CellInfo::unsetAttr), &CellInfo::unsetAttr, + conv_from_str<IdString>>::def_wrap(ci_cls, "unsetAttr"); + auto pi_cls = class_<ContextualWrapper<PortInfo &>>("PortInfo", no_init); readwrite_wrapper<PortInfo &, decltype(&PortInfo::name), &PortInfo::name, conv_to_str<IdString>, conv_from_str<IdString>>::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<Context, decltype(&Context::getBelType), &Context::getBelType, conv_to_str<IdString>, - conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelType"); - fn_wrapper_1a<Context, decltype(&Context::checkBelAvail), &Context::checkBelAvail, pass_through<bool>, - conv_from_str<BelId>>::def_wrap(ctx_cls, "checkBelAvail"); - fn_wrapper_1a<Context, decltype(&Context::getBelChecksum), &Context::getBelChecksum, pass_through<uint32_t>, - conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelChecksum"); - fn_wrapper_3a_v<Context, decltype(&Context::bindBel), &Context::bindBel, conv_from_str<BelId>, - addr_and_unwrap<CellInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindBel"); - fn_wrapper_1a_v<Context, decltype(&Context::unbindBel), &Context::unbindBel, conv_from_str<BelId>>::def_wrap( - ctx_cls, "unbindBel"); - fn_wrapper_1a<Context, decltype(&Context::getBoundBelCell), &Context::getBoundBelCell, deref_and_wrap<CellInfo>, - 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<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"); - fn_wrapper_1a<Context, decltype(&Context::getWireBelPins), &Context::getWireBelPins, wrap_context<BelPinRange>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireBelPins"); - - fn_wrapper_1a<Context, decltype(&Context::getWireChecksum), &Context::getWireChecksum, pass_through<uint32_t>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireChecksum"); - fn_wrapper_3a_v<Context, decltype(&Context::bindWire), &Context::bindWire, conv_from_str<WireId>, - addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindWire"); - fn_wrapper_1a_v<Context, decltype(&Context::unbindWire), &Context::unbindWire, conv_from_str<WireId>>::def_wrap( - ctx_cls, "unbindWire"); - fn_wrapper_1a<Context, decltype(&Context::checkWireAvail), &Context::checkWireAvail, pass_through<bool>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "checkWireAvail"); - fn_wrapper_1a<Context, decltype(&Context::getBoundWireNet), &Context::getBoundWireNet, deref_and_wrap<NetInfo>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "getBoundWireNet"); - 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<WireRange>>::def_wrap( - ctx_cls, "getWires"); - - 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>, - addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindPip"); - fn_wrapper_1a_v<Context, decltype(&Context::unbindPip), &Context::unbindPip, conv_from_str<PipId>>::def_wrap( - ctx_cls, "unbindPip"); - fn_wrapper_1a<Context, decltype(&Context::checkPipAvail), &Context::checkPipAvail, pass_through<bool>, - conv_from_str<PipId>>::def_wrap(ctx_cls, "checkPipAvail"); - fn_wrapper_1a<Context, decltype(&Context::getBoundPipNet), &Context::getBoundPipNet, deref_and_wrap<NetInfo>, - conv_from_str<PipId>>::def_wrap(ctx_cls, "getBoundPipNet"); - fn_wrapper_1a<Context, decltype(&Context::getConflictingPipNet), &Context::getConflictingPipNet, - deref_and_wrap<NetInfo>, conv_from_str<PipId>>::def_wrap(ctx_cls, "getConflictingPipNet"); - - fn_wrapper_1a<Context, decltype(&Context::getPipsDownhill), &Context::getPipsDownhill, wrap_context<PipRange>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "getPipsDownhill"); - fn_wrapper_1a<Context, decltype(&Context::getPipsUphill), &Context::getPipsUphill, wrap_context<PipRange>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "getPipsUphill"); - fn_wrapper_1a<Context, decltype(&Context::getWireAliases), &Context::getWireAliases, wrap_context<PipRange>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireAliases"); - - fn_wrapper_1a<Context, decltype(&Context::getPipSrcWire), &Context::getPipSrcWire, conv_to_str<WireId>, - conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipSrcWire"); - fn_wrapper_1a<Context, decltype(&Context::getPipDstWire), &Context::getPipDstWire, conv_to_str<WireId>, - conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipDstWire"); - fn_wrapper_1a<Context, decltype(&Context::getPipDelay), &Context::getPipDelay, pass_through<DelayInfo>, - conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipDelay"); - - fn_wrapper_1a<Context, decltype(&Context::getPackagePinBel), &Context::getPackagePinBel, conv_to_str<BelId>, - pass_through<std::string>>::def_wrap(ctx_cls, "getPackagePinBel"); - fn_wrapper_1a<Context, decltype(&Context::getBelPackagePin), &Context::getBelPackagePin, pass_through<std::string>, - conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelPackagePin"); - - fn_wrapper_0a<Context, decltype(&Context::getChipName), &Context::getChipName, pass_through<std::string>>::def_wrap( - ctx_cls, "getChipName"); - fn_wrapper_0a<Context, decltype(&Context::archId), &Context::archId, conv_to_str<IdString>>::def_wrap(ctx_cls, - "archId"); - typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap; typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap; typedef std::unordered_map<IdString, IdString> AliasMap; - readonly_wrapper<Context, decltype(&Context::cells), &Context::cells, wrap_context<CellMap &>>::def_wrap(ctx_cls, - "cells"); - readonly_wrapper<Context, decltype(&Context::nets), &Context::nets, wrap_context<NetMap &>>::def_wrap(ctx_cls, - "nets"); - readonly_wrapper<Context, decltype(&Context::net_aliases), &Context::net_aliases, - wrap_context<AliasMap &>>::def_wrap(ctx_cls, "net_aliases"); - - fn_wrapper_1a<Context, decltype(&Context::getNetByAlias), &Context::getNetByAlias, deref_and_wrap<NetInfo>, - conv_from_str<IdString>>::def_wrap(ctx_cls, "getNetByAlias"); - fn_wrapper_2a_v<Context, decltype(&Context::addClock), &Context::addClock, conv_from_str<IdString>, - pass_through<float>>::def_wrap(ctx_cls, "addClock"); - fn_wrapper_5a_v<Context, decltype(&Context::createRectangularRegion), &Context::createRectangularRegion, - conv_from_str<IdString>, pass_through<int>, pass_through<int>, pass_through<int>, - pass_through<int>>::def_wrap(ctx_cls, "createRectangularRegion"); - fn_wrapper_2a_v<Context, decltype(&Context::addBelToRegion), &Context::addBelToRegion, conv_from_str<IdString>, - conv_from_str<BelId>>::def_wrap(ctx_cls, "addBelToRegion"); - fn_wrapper_2a_v<Context, decltype(&Context::constrainCellToRegion), &Context::constrainCellToRegion, - conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "constrainCellToRegion"); - auto belpin_cls = class_<ContextualWrapper<BelPin>>("BelPin", no_init); readonly_wrapper<BelPin, decltype(&BelPin::bel), &BelPin::bel, conv_to_str<BelId>>::def_wrap(belpin_cls, "bel"); readonly_wrapper<BelPin, decltype(&BelPin::pin), &BelPin::pin, conv_to_str<IdString>>::def_wrap(belpin_cls, "pin"); +#include "arch_pybindings_shared.h" + WRAP_RANGE(Bel, conv_to_str<BelId>); WRAP_RANGE(Wire, conv_to_str<WireId>); WRAP_RANGE(AllPip, conv_to_str<PipId>); 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<Context, decltype(&Context::getBelType), &Context::getBelType, conv_to_str<IdString>, - conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelType"); - fn_wrapper_1a<Context, decltype(&Context::checkBelAvail), &Context::checkBelAvail, pass_through<bool>, - conv_from_str<BelId>>::def_wrap(ctx_cls, "checkBelAvail"); - fn_wrapper_1a<Context, decltype(&Context::getBelChecksum), &Context::getBelChecksum, pass_through<uint32_t>, - conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelChecksum"); - fn_wrapper_3a_v<Context, decltype(&Context::bindBel), &Context::bindBel, conv_from_str<BelId>, - addr_and_unwrap<CellInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindBel"); - fn_wrapper_1a_v<Context, decltype(&Context::unbindBel), &Context::unbindBel, conv_from_str<BelId>>::def_wrap( - ctx_cls, "unbindBel"); - fn_wrapper_1a<Context, decltype(&Context::getBoundBelCell), &Context::getBoundBelCell, deref_and_wrap<CellInfo>, - 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<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"); - fn_wrapper_1a<Context, decltype(&Context::getWireBelPins), &Context::getWireBelPins, wrap_context<BelPinRange>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireBelPins"); - - fn_wrapper_1a<Context, decltype(&Context::getWireChecksum), &Context::getWireChecksum, pass_through<uint32_t>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireChecksum"); - fn_wrapper_3a_v<Context, decltype(&Context::bindWire), &Context::bindWire, conv_from_str<WireId>, - addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindWire"); - fn_wrapper_1a_v<Context, decltype(&Context::unbindWire), &Context::unbindWire, conv_from_str<WireId>>::def_wrap( - ctx_cls, "unbindWire"); - fn_wrapper_1a<Context, decltype(&Context::checkWireAvail), &Context::checkWireAvail, pass_through<bool>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "checkWireAvail"); - fn_wrapper_1a<Context, decltype(&Context::getBoundWireNet), &Context::getBoundWireNet, deref_and_wrap<NetInfo>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "getBoundWireNet"); - 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<WireRange>>::def_wrap( - ctx_cls, "getWires"); - - 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>, - addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindPip"); - fn_wrapper_1a_v<Context, decltype(&Context::unbindPip), &Context::unbindPip, conv_from_str<PipId>>::def_wrap( - ctx_cls, "unbindPip"); - fn_wrapper_1a<Context, decltype(&Context::checkPipAvail), &Context::checkPipAvail, pass_through<bool>, - conv_from_str<PipId>>::def_wrap(ctx_cls, "checkPipAvail"); - fn_wrapper_1a<Context, decltype(&Context::getBoundPipNet), &Context::getBoundPipNet, deref_and_wrap<NetInfo>, - conv_from_str<PipId>>::def_wrap(ctx_cls, "getBoundPipNet"); - fn_wrapper_1a<Context, decltype(&Context::getConflictingPipNet), &Context::getConflictingPipNet, - deref_and_wrap<NetInfo>, conv_from_str<PipId>>::def_wrap(ctx_cls, "getConflictingPipNet"); - - fn_wrapper_1a<Context, decltype(&Context::getPipsDownhill), &Context::getPipsDownhill, wrap_context<PipRange>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "getPipsDownhill"); - fn_wrapper_1a<Context, decltype(&Context::getPipsUphill), &Context::getPipsUphill, wrap_context<PipRange>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "getPipsUphill"); - fn_wrapper_1a<Context, decltype(&Context::getWireAliases), &Context::getWireAliases, wrap_context<PipRange>, - conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireAliases"); - - fn_wrapper_1a<Context, decltype(&Context::getPipSrcWire), &Context::getPipSrcWire, conv_to_str<WireId>, - conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipSrcWire"); - fn_wrapper_1a<Context, decltype(&Context::getPipDstWire), &Context::getPipDstWire, conv_to_str<WireId>, - conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipDstWire"); - fn_wrapper_1a<Context, decltype(&Context::getPipDelay), &Context::getPipDelay, pass_through<DelayInfo>, - conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipDelay"); - - fn_wrapper_1a<Context, decltype(&Context::getPackagePinBel), &Context::getPackagePinBel, conv_to_str<BelId>, - pass_through<std::string>>::def_wrap(ctx_cls, "getPackagePinBel"); - fn_wrapper_1a<Context, decltype(&Context::getBelPackagePin), &Context::getBelPackagePin, pass_through<std::string>, - conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelPackagePin"); - - fn_wrapper_0a<Context, decltype(&Context::getChipName), &Context::getChipName, pass_through<std::string>>::def_wrap( - ctx_cls, "getChipName"); - fn_wrapper_0a<Context, decltype(&Context::archId), &Context::archId, conv_to_str<IdString>>::def_wrap(ctx_cls, - "archId"); - typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap; typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap; typedef std::unordered_map<IdString, IdString> AliasMap; - readonly_wrapper<Context, decltype(&Context::cells), &Context::cells, wrap_context<CellMap &>>::def_wrap(ctx_cls, - "cells"); - readonly_wrapper<Context, decltype(&Context::nets), &Context::nets, wrap_context<NetMap &>>::def_wrap(ctx_cls, - "nets"); - readonly_wrapper<Context, decltype(&Context::net_aliases), &Context::net_aliases, - wrap_context<AliasMap &>>::def_wrap(ctx_cls, "net_aliases"); - - fn_wrapper_1a<Context, decltype(&Context::getNetByAlias), &Context::getNetByAlias, deref_and_wrap<NetInfo>, - conv_from_str<IdString>>::def_wrap(ctx_cls, "getNetByAlias"); - fn_wrapper_2a_v<Context, decltype(&Context::addClock), &Context::addClock, conv_from_str<IdString>, - pass_through<float>>::def_wrap(ctx_cls, "addClock"); - fn_wrapper_5a_v<Context, decltype(&Context::createRectangularRegion), &Context::createRectangularRegion, - conv_from_str<IdString>, pass_through<int>, pass_through<int>, pass_through<int>, - pass_through<int>>::def_wrap(ctx_cls, "createRectangularRegion"); - fn_wrapper_2a_v<Context, decltype(&Context::addBelToRegion), &Context::addBelToRegion, conv_from_str<IdString>, - conv_from_str<BelId>>::def_wrap(ctx_cls, "addBelToRegion"); - fn_wrapper_2a_v<Context, decltype(&Context::constrainCellToRegion), &Context::constrainCellToRegion, - conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "constrainCellToRegion"); - auto belpin_cls = class_<ContextualWrapper<BelPin>>("BelPin", no_init); readonly_wrapper<BelPin, decltype(&BelPin::bel), &BelPin::bel, conv_to_str<BelId>>::def_wrap(belpin_cls, "bel"); readonly_wrapper<BelPin, decltype(&BelPin::pin), &BelPin::pin, conv_to_str<IdString>>::def_wrap(belpin_cls, "pin"); +#include "arch_pybindings_shared.h" + WRAP_RANGE(Bel, conv_to_str<BelId>); WRAP_RANGE(Wire, conv_to_str<WireId>); WRAP_RANGE(AllPip, conv_to_str<PipId>); |