Merge pull request #332 from YosysHQ/dave/python-refactor
Improving Python API and adding docs for it
This commit is contained in:
commit
cb71b488ec
114
common/arch_pybindings_shared.h
Normal file
114
common/arch_pybindings_shared.h
Normal file
@ -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");
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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");
|
||||
|
87
docs/python.md
Normal file
87
docs/python.md
Normal file
@ -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)
|
||||
|
@ -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>);
|
||||
|
@ -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>);
|
||||
|
Loading…
Reference in New Issue
Block a user