Merge pull request #889 from YosysHQ/gatecat/generic-refactor

generic: Refactor for faster performance
This commit is contained in:
gatecat 2021-12-30 13:12:20 +00:00 committed by GitHub
commit d65c629fb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 348 additions and 228 deletions

View File

@ -257,7 +257,7 @@ template <typename Class, typename FuncT, FuncT fn, typename arg1_conv> struct f
{ {
Context *ctx = get_ctx<Class>(cls); Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls); Class &base = get_base<Class>(cls);
return (base.*fn)(arg1_conv()(ctx, arg1)); (base.*fn)(arg1_conv()(ctx, arg1));
} }
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@ -280,7 +280,7 @@ template <typename Class, typename FuncT, FuncT fn, typename arg1_conv, typename
{ {
Context *ctx = get_ctx<Class>(cls); Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls); Class &base = get_base<Class>(cls);
return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2)); (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2));
} }
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@ -304,7 +304,7 @@ struct fn_wrapper_3a_v
{ {
Context *ctx = get_ctx<Class>(cls); Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls); Class &base = get_base<Class>(cls);
return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3)); (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3));
} }
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@ -331,8 +331,7 @@ struct fn_wrapper_4a_v
{ {
Context *ctx = get_ctx<Class>(cls); Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls); Class &base = get_base<Class>(cls);
return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), arg4_conv()(ctx, arg4));
arg4_conv()(ctx, arg4));
} }
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@ -360,8 +359,8 @@ struct fn_wrapper_5a_v
{ {
Context *ctx = get_ctx<Class>(cls); Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls); Class &base = get_base<Class>(cls);
return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), arg4_conv()(ctx, arg4),
arg4_conv()(ctx, arg4), arg5_conv()(ctx, arg5)); arg5_conv()(ctx, arg5));
} }
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@ -390,8 +389,8 @@ struct fn_wrapper_6a_v
{ {
Context *ctx = get_ctx<Class>(cls); Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls); Class &base = get_base<Class>(cls);
return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), arg4_conv()(ctx, arg4),
arg4_conv()(ctx, arg4), arg5_conv()(ctx, arg5), arg6_conv()(ctx, arg6)); arg5_conv()(ctx, arg5), arg6_conv()(ctx, arg6));
} }
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }

View File

@ -12,35 +12,42 @@ will be worked on in the future.
## Python API ## Python API
All identifiers (`IdString`) are automatically converted to All identifiers (`IdString`, `IdStringList`, `WireId`, `PipId`, and `BelId`) are
and from a Python string, so no manual conversion is required. automatically converted to and from a Python string, so no manual conversion is
required.
`IdStringList`s will be most efficient if strings can be split according to a
separator (currently fixed to `/`), as only the components need be stored
in-memory. For example; instead of needing to store an entire pip name
`X33/Y45/V4A_TO_A6` which scales badly for large numbers of pips; the strings
`X33`, `Y45` and `V4A_TO_A6` are stored.
Argument names are included in the Python bindings, Argument names are included in the Python bindings,
so named arguments may be used. so named arguments may be used.
### void addWire(IdString name, IdString type, int x, int y); ### void addWire(IdStringList name, IdString type, int x, int y);
Adds a wire with a name, type (for user purposes only, ignored by all nextpnr code other than the UI) to the FPGA description. x and y give a nominal location of the wire for delay estimation purposes. Delay estimates are important for router performance (as the router uses an A* type algorithm), even if timing is not of importance. Adds a wire with a name, type (for user purposes only, ignored by all nextpnr code other than the UI) to the FPGA description. x and y give a nominal location of the wire for delay estimation purposes. Delay estimates are important for router performance (as the router uses an A* type algorithm), even if timing is not of importance.
### addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, float delay, Loc loc); ### addPip(IdStringList name, IdString type, WireId srcWire, WireId dstWire, float delay, Loc loc);
Adds a pip (programmable connection between two named wires). Pip delays that correspond to delay estimates are important for router performance (as the router uses an A* type algorithm), even if timing is otherwise not of importance. Adds a pip (programmable connection between two named wires). Pip delays that correspond to delay estimates are important for router performance (as the router uses an A* type algorithm), even if timing is otherwise not of importance.
Loc is constructed using `Loc(x, y, z)`. 'z' for pips is only important if region constraints (e.g. for partial reconfiguration regions) are used. Loc is constructed using `Loc(x, y, z)`. 'z' for pips is only important if region constraints (e.g. for partial reconfiguration regions) are used.
### void addBel(IdString name, IdString type, Loc loc, bool gb, bool hidden); ### void addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidden);
Adds a bel to the FPGA description. Bel type should match the type of cells in the netlist that are placed at this bel (see below for information on special bel types supported by the packer). Loc is constructed using `Loc(x, y, z)` and must be unique. If `hidden` is true, then the bel will not be included in utilisation reports (e.g. for routing/internal use bels). Adds a bel to the FPGA description. Bel type should match the type of cells in the netlist that are placed at this bel (see below for information on special bel types supported by the packer). Loc is constructed using `Loc(x, y, z)` and must be unique. If `hidden` is true, then the bel will not be included in utilisation reports (e.g. for routing/internal use bels).
### void addBelInput(IdString bel, IdString name, IdString wire); ### void addBelInput(BelId bel, IdString name, WireId wire);
### void addBelOutput(IdString bel, IdString name, IdString wire); ### void addBelOutput(BelId bel, IdString name, WireId wire);
### void addBelInout(IdString bel, IdString name, IdString wire); ### void addBelInout(BelId bel, IdString name, WireId wire);
Adds an input, output or inout pin to a bel, with an associated wire. Note that both `bel` and `wire` must have been created before calling this function. Adds an input, output or inout pin to a bel, with an associated wire. Note that both `bel` and `wire` must have been created before calling this function.
### void addGroupBel(IdString group, IdString bel); ### void addGroupBel(IdString group, BelId bel);
### void addGroupWire(IdString group, IdString wire); ### void addGroupWire(IdString group, WireId wire);
### void addGroupPip(IdString group, IdString pip); ### void addGroupPip(IdString group, PipId pip);
### void addGroupGroup(IdString group, IdString grp); ### void addGroupGroup(IdString group, IdString grp);
Add a bel, wire, pip or subgroup to a group, which will be created if it doesn't already exist. Groups are purely for visual presentation purposes in the user interface and are not used by any place-and-route algorithms. Add a bel, wire, pip or subgroup to a group, which will be created if it doesn't already exist. Groups are purely for visual presentation purposes in the user interface and are not used by any place-and-route algorithms.
@ -56,9 +63,9 @@ Add a graphic element to a _decal_, a reusable drawing that may be used to repre
Sets the decal ID and offset for a wire, bel, pip or group in the UI. Sets the decal ID and offset for a wire, bel, pip or group in the UI.
### void setWireAttr(IdString wire, IdString key, const std::string &value); ### void setWireAttr(WireId wire, IdString key, const std::string &value);
### void setPipAttr(IdString pip, IdString key, const std::string &value); ### void setPipAttr(PipId pip, IdString key, const std::string &value);
### void setBelAttr(IdString bel, IdString key, const std::string &value); ### void setBelAttr(BelId bel, IdString key, const std::string &value);
Sets an attribute on a wire, pip or bel. Attributes are displayed in the tree view in the UI, but have no bearing on place-and-route itself. Sets an attribute on a wire, pip or bel. Attributes are displayed in the tree view in the UI, but have no bearing on place-and-route itself.

View File

@ -28,46 +28,27 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
WireInfo &Arch::wire_info(IdStringList wire) WireId Arch::addWire(IdStringList name, IdString type, int x, int y)
{ {
auto w = wires.find(wire); NPNR_ASSERT(wire_by_name.count(name) == 0);
if (w == wires.end()) WireId wire(wires.size());
NPNR_ASSERT_FALSE_STR("no wire named " + wire.str(getCtx())); wire_by_name[name] = wire;
return w->second; wires.emplace_back();
} WireInfo &wi = wires.back();
PipInfo &Arch::pip_info(IdStringList pip)
{
auto p = pips.find(pip);
if (p == pips.end())
NPNR_ASSERT_FALSE_STR("no pip named " + pip.str(getCtx()));
return p->second;
}
BelInfo &Arch::bel_info(IdStringList bel)
{
auto b = bels.find(bel);
if (b == bels.end())
NPNR_ASSERT_FALSE_STR("no bel named " + bel.str(getCtx()));
return b->second;
}
void Arch::addWire(IdStringList name, IdString type, int x, int y)
{
NPNR_ASSERT(wires.count(name) == 0);
WireInfo &wi = wires[name];
wi.name = name; wi.name = name;
wi.type = type; wi.type = type;
wi.x = x; wi.x = x;
wi.y = y; wi.y = y;
return wire;
wire_ids.push_back(name);
} }
void Arch::addPip(IdStringList name, IdString type, IdStringList srcWire, IdStringList dstWire, delay_t delay, Loc loc) PipId Arch::addPip(IdStringList name, IdString type, WireId srcWire, WireId dstWire, delay_t delay, Loc loc)
{ {
NPNR_ASSERT(pips.count(name) == 0); NPNR_ASSERT(pip_by_name.count(name) == 0);
PipInfo &pi = pips[name]; PipId pip(pips.size());
pip_by_name[name] = pip;
pips.emplace_back();
PipInfo &pi = pips.back();
pi.name = name; pi.name = name;
pi.type = type; pi.type = type;
pi.srcWire = srcWire; pi.srcWire = srcWire;
@ -75,9 +56,8 @@ void Arch::addPip(IdStringList name, IdString type, IdStringList srcWire, IdStri
pi.delay = delay; pi.delay = delay;
pi.loc = loc; pi.loc = loc;
wire_info(srcWire).downhill.push_back(name); wire_info(srcWire).downhill.push_back(pip);
wire_info(dstWire).uphill.push_back(name); wire_info(dstWire).uphill.push_back(pip);
pip_ids.push_back(name);
if (int(tilePipDimZ.size()) <= loc.x) if (int(tilePipDimZ.size()) <= loc.x)
tilePipDimZ.resize(loc.x + 1); tilePipDimZ.resize(loc.x + 1);
@ -88,13 +68,17 @@ void Arch::addPip(IdStringList name, IdString type, IdStringList srcWire, IdStri
gridDimX = std::max(gridDimX, loc.x + 1); gridDimX = std::max(gridDimX, loc.x + 1);
gridDimY = std::max(gridDimY, loc.x + 1); gridDimY = std::max(gridDimY, loc.x + 1);
tilePipDimZ[loc.x][loc.y] = std::max(tilePipDimZ[loc.x][loc.y], loc.z + 1); tilePipDimZ[loc.x][loc.y] = std::max(tilePipDimZ[loc.x][loc.y], loc.z + 1);
return pip;
} }
void Arch::addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidden) BelId Arch::addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidden)
{ {
NPNR_ASSERT(bels.count(name) == 0); NPNR_ASSERT(bel_by_name.count(name) == 0);
NPNR_ASSERT(bel_by_loc.count(loc) == 0); NPNR_ASSERT(bel_by_loc.count(loc) == 0);
BelInfo &bi = bels[name]; BelId bel(bels.size());
bel_by_name[name] = bel;
bels.emplace_back();
BelInfo &bi = bels.back();
bi.name = name; bi.name = name;
bi.type = type; bi.type = type;
bi.x = loc.x; bi.x = loc.x;
@ -103,8 +87,7 @@ void Arch::addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidde
bi.gb = gb; bi.gb = gb;
bi.hidden = hidden; bi.hidden = hidden;
bel_ids.push_back(name); bel_by_loc[loc] = bel;
bel_by_loc[loc] = name;
if (int(bels_by_tile.size()) <= loc.x) if (int(bels_by_tile.size()) <= loc.x)
bels_by_tile.resize(loc.x + 1); bels_by_tile.resize(loc.x + 1);
@ -112,7 +95,7 @@ void Arch::addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidde
if (int(bels_by_tile[loc.x].size()) <= loc.y) if (int(bels_by_tile[loc.x].size()) <= loc.y)
bels_by_tile[loc.x].resize(loc.y + 1); bels_by_tile[loc.x].resize(loc.y + 1);
bels_by_tile[loc.x][loc.y].push_back(name); bels_by_tile[loc.x][loc.y].push_back(bel);
if (int(tileBelDimZ.size()) <= loc.x) if (int(tileBelDimZ.size()) <= loc.x)
tileBelDimZ.resize(loc.x + 1); tileBelDimZ.resize(loc.x + 1);
@ -123,49 +106,50 @@ void Arch::addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidde
gridDimX = std::max(gridDimX, loc.x + 1); gridDimX = std::max(gridDimX, loc.x + 1);
gridDimY = std::max(gridDimY, loc.x + 1); gridDimY = std::max(gridDimY, loc.x + 1);
tileBelDimZ[loc.x][loc.y] = std::max(tileBelDimZ[loc.x][loc.y], loc.z + 1); tileBelDimZ[loc.x][loc.y] = std::max(tileBelDimZ[loc.x][loc.y], loc.z + 1);
return bel;
} }
void Arch::addBelInput(IdStringList bel, IdString name, IdStringList wire) void Arch::addBelInput(BelId bel, IdString name, WireId wire)
{ {
NPNR_ASSERT(bel_info(bel).pins.count(name) == 0); auto &bi = bel_info(bel);
PinInfo &pi = bel_info(bel).pins[name]; NPNR_ASSERT(bi.pins.count(name) == 0);
PinInfo &pi = bi.pins[name];
pi.name = name; pi.name = name;
pi.wire = wire; pi.wire = wire;
pi.type = PORT_IN; pi.type = PORT_IN;
wire_info(wire).downhill_bel_pins.push_back(BelPin{bel, name});
wire_info(wire).bel_pins.push_back(BelPin{bel, name}); wire_info(wire).bel_pins.push_back(BelPin{bel, name});
} }
void Arch::addBelOutput(IdStringList bel, IdString name, IdStringList wire) void Arch::addBelOutput(BelId bel, IdString name, WireId wire)
{ {
NPNR_ASSERT(bel_info(bel).pins.count(name) == 0); auto &bi = bel_info(bel);
PinInfo &pi = bel_info(bel).pins[name]; NPNR_ASSERT(bi.pins.count(name) == 0);
PinInfo &pi = bi.pins[name];
pi.name = name; pi.name = name;
pi.wire = wire; pi.wire = wire;
pi.type = PORT_OUT; pi.type = PORT_OUT;
wire_info(wire).uphill_bel_pin = BelPin{bel, name};
wire_info(wire).bel_pins.push_back(BelPin{bel, name}); wire_info(wire).bel_pins.push_back(BelPin{bel, name});
} }
void Arch::addBelInout(IdStringList bel, IdString name, IdStringList wire) void Arch::addBelInout(BelId bel, IdString name, WireId wire)
{ {
NPNR_ASSERT(bel_info(bel).pins.count(name) == 0); auto &bi = bel_info(bel);
PinInfo &pi = bel_info(bel).pins[name]; NPNR_ASSERT(bi.pins.count(name) == 0);
PinInfo &pi = bi.pins[name];
pi.name = name; pi.name = name;
pi.wire = wire; pi.wire = wire;
pi.type = PORT_INOUT; pi.type = PORT_INOUT;
wire_info(wire).downhill_bel_pins.push_back(BelPin{bel, name});
wire_info(wire).bel_pins.push_back(BelPin{bel, name}); wire_info(wire).bel_pins.push_back(BelPin{bel, name});
} }
void Arch::addGroupBel(IdStringList group, IdStringList bel) { groups[group].bels.push_back(bel); } void Arch::addGroupBel(IdStringList group, BelId bel) { groups[group].bels.push_back(bel); }
void Arch::addGroupWire(IdStringList group, IdStringList wire) { groups[group].wires.push_back(wire); } void Arch::addGroupWire(IdStringList group, WireId wire) { groups[group].wires.push_back(wire); }
void Arch::addGroupPip(IdStringList group, IdStringList pip) { groups[group].pips.push_back(pip); } void Arch::addGroupPip(IdStringList group, PipId pip) { groups[group].pips.push_back(pip); }
void Arch::addGroupGroup(IdStringList group, IdStringList grp) { groups[group].groups.push_back(grp); } void Arch::addGroupGroup(IdStringList group, IdStringList grp) { groups[group].groups.push_back(grp); }
@ -177,19 +161,19 @@ void Arch::addDecalGraphic(DecalId decal, const GraphicElement &graphic)
void Arch::setWireDecal(WireId wire, DecalXY decalxy) void Arch::setWireDecal(WireId wire, DecalXY decalxy)
{ {
wire_info(wire).decalxy = decalxy; wires.at(wire.index).decalxy = decalxy;
refreshUiWire(wire); refreshUiWire(wire);
} }
void Arch::setPipDecal(PipId pip, DecalXY decalxy) void Arch::setPipDecal(PipId pip, DecalXY decalxy)
{ {
pip_info(pip).decalxy = decalxy; pips.at(pip.index).decalxy = decalxy;
refreshUiPip(pip); refreshUiPip(pip);
} }
void Arch::setBelDecal(BelId bel, DecalXY decalxy) void Arch::setBelDecal(BelId bel, DecalXY decalxy)
{ {
bel_info(bel).decalxy = decalxy; bels.at(bel.index).decalxy = decalxy;
refreshUiBel(bel); refreshUiBel(bel);
} }
@ -199,14 +183,11 @@ void Arch::setGroupDecal(GroupId group, DecalXY decalxy)
refreshUiGroup(group); refreshUiGroup(group);
} }
void Arch::setWireAttr(IdStringList wire, IdString key, const std::string &value) void Arch::setWireAttr(WireId wire, IdString key, const std::string &value) { wire_info(wire).attrs[key] = value; }
{
wire_info(wire).attrs[key] = value;
}
void Arch::setPipAttr(IdStringList pip, IdString key, const std::string &value) { pip_info(pip).attrs[key] = value; } void Arch::setPipAttr(PipId pip, IdString key, const std::string &value) { pip_info(pip).attrs[key] = value; }
void Arch::setBelAttr(IdStringList bel, IdString key, const std::string &value) { bel_info(bel).attrs[key] = value; } void Arch::setBelAttr(BelId bel, IdString key, const std::string &value) { bel_info(bel).attrs[key] = value; }
void Arch::setLutK(int K) { args.K = K; } void Arch::setLutK(int K) { args.K = K; }
@ -268,16 +249,19 @@ void IdString::initialize_arch(const BaseCtx *ctx) {}
BelId Arch::getBelByName(IdStringList name) const BelId Arch::getBelByName(IdStringList name) const
{ {
if (bels.count(name)) if (name.size() == 0)
return name; return BelId();
return BelId(); auto fnd = bel_by_name.find(name);
if (fnd == bel_by_name.end())
NPNR_ASSERT_FALSE_STR("no bel named " + name.str(getCtx()));
return fnd->second;
} }
IdStringList Arch::getBelName(BelId bel) const { return bel; } IdStringList Arch::getBelName(BelId bel) const { return bel_info(bel).name; }
Loc Arch::getBelLocation(BelId bel) const Loc Arch::getBelLocation(BelId bel) const
{ {
auto &info = bels.at(bel); auto &info = bel_info(bel);
return Loc(info.x, info.y, info.z); return Loc(info.x, info.y, info.z);
} }
@ -291,7 +275,7 @@ BelId Arch::getBelByLocation(Loc loc) const
const std::vector<BelId> &Arch::getBelsByTile(int x, int y) const { return bels_by_tile.at(x).at(y); } const std::vector<BelId> &Arch::getBelsByTile(int x, int y) const { return bels_by_tile.at(x).at(y); }
bool Arch::getBelGlobalBuf(BelId bel) const { return bels.at(bel).gb; } bool Arch::getBelGlobalBuf(BelId bel) const { return bel_info(bel).gb; }
uint32_t Arch::getBelChecksum(BelId bel) const uint32_t Arch::getBelChecksum(BelId bel) const
{ {
@ -301,7 +285,7 @@ uint32_t Arch::getBelChecksum(BelId bel) const
void Arch::bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) void Arch::bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
{ {
bels.at(bel).bound_cell = cell; bel_info(bel).bound_cell = cell;
cell->bel = bel; cell->bel = bel;
cell->belStrength = strength; cell->belStrength = strength;
refreshUiBel(bel); refreshUiBel(bel);
@ -309,40 +293,41 @@ void Arch::bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
void Arch::unbindBel(BelId bel) void Arch::unbindBel(BelId bel)
{ {
bels.at(bel).bound_cell->bel = BelId(); auto &bi = bel_info(bel);
bels.at(bel).bound_cell->belStrength = STRENGTH_NONE; bi.bound_cell->bel = BelId();
bels.at(bel).bound_cell = nullptr; bi.bound_cell->belStrength = STRENGTH_NONE;
bi.bound_cell = nullptr;
refreshUiBel(bel); refreshUiBel(bel);
} }
bool Arch::checkBelAvail(BelId bel) const { return bels.at(bel).bound_cell == nullptr; } bool Arch::checkBelAvail(BelId bel) const { return bel_info(bel).bound_cell == nullptr; }
CellInfo *Arch::getBoundBelCell(BelId bel) const { return bels.at(bel).bound_cell; } CellInfo *Arch::getBoundBelCell(BelId bel) const { return bel_info(bel).bound_cell; }
CellInfo *Arch::getConflictingBelCell(BelId bel) const { return bels.at(bel).bound_cell; } CellInfo *Arch::getConflictingBelCell(BelId bel) const { return bel_info(bel).bound_cell; }
const std::vector<BelId> &Arch::getBels() const { return bel_ids; } linear_range<BelId> Arch::getBels() const { return linear_range<BelId>(bels.size()); }
IdString Arch::getBelType(BelId bel) const { return bels.at(bel).type; } IdString Arch::getBelType(BelId bel) const { return bel_info(bel).type; }
bool Arch::getBelHidden(BelId bel) const { return bels.at(bel).hidden; } bool Arch::getBelHidden(BelId bel) const { return bel_info(bel).hidden; }
const std::map<IdString, std::string> &Arch::getBelAttrs(BelId bel) const { return bels.at(bel).attrs; } const std::map<IdString, std::string> &Arch::getBelAttrs(BelId bel) const { return bel_info(bel).attrs; }
WireId Arch::getBelPinWire(BelId bel, IdString pin) const WireId Arch::getBelPinWire(BelId bel, IdString pin) const
{ {
const auto &bdata = bels.at(bel); const auto &bdata = bel_info(bel);
if (!bdata.pins.count(pin)) if (!bdata.pins.count(pin))
log_error("bel '%s' has no pin '%s'\n", getCtx()->nameOfBel(bel), pin.c_str(this)); log_error("bel '%s' has no pin '%s'\n", getCtx()->nameOfBel(bel), pin.c_str(this));
return bdata.pins.at(pin).wire; return bdata.pins.at(pin).wire;
} }
PortType Arch::getBelPinType(BelId bel, IdString pin) const { return bels.at(bel).pins.at(pin).type; } PortType Arch::getBelPinType(BelId bel, IdString pin) const { return bel_info(bel).pins.at(pin).type; }
std::vector<IdString> Arch::getBelPins(BelId bel) const std::vector<IdString> Arch::getBelPins(BelId bel) const
{ {
std::vector<IdString> ret; std::vector<IdString> ret;
for (auto &it : bels.at(bel).pins) for (auto &it : bel_info(bel).pins)
ret.push_back(it.first); ret.push_back(it.first);
return ret; return ret;
} }
@ -356,26 +341,25 @@ const std::vector<IdString> &Arch::getBelPinsForCellPin(const CellInfo *cell_inf
WireId Arch::getWireByName(IdStringList name) const WireId Arch::getWireByName(IdStringList name) const
{ {
if (wires.count(name)) if (name.size() == 0)
return name; return WireId();
return WireId(); auto fnd = wire_by_name.find(name);
if (fnd == wire_by_name.end())
NPNR_ASSERT_FALSE_STR("no wire named " + name.str(getCtx()));
return fnd->second;
} }
IdStringList Arch::getWireName(WireId wire) const { return wire; } IdStringList Arch::getWireName(WireId wire) const { return wire_info(wire).name; }
IdString Arch::getWireType(WireId wire) const { return wires.at(wire).type; } IdString Arch::getWireType(WireId wire) const { return wire_info(wire).type; }
const std::map<IdString, std::string> &Arch::getWireAttrs(WireId wire) const { return wires.at(wire).attrs; } const std::map<IdString, std::string> &Arch::getWireAttrs(WireId wire) const { return wire_info(wire).attrs; }
uint32_t Arch::getWireChecksum(WireId wire) const uint32_t Arch::getWireChecksum(WireId wire) const { return wire.index; }
{
// FIXME
return 0;
}
void Arch::bindWire(WireId wire, NetInfo *net, PlaceStrength strength) void Arch::bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
{ {
wires.at(wire).bound_net = net; wire_info(wire).bound_net = net;
net->wires[wire].pip = PipId(); net->wires[wire].pip = PipId();
net->wires[wire].strength = strength; net->wires[wire].strength = strength;
refreshUiWire(wire); refreshUiWire(wire);
@ -383,55 +367,54 @@ void Arch::bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
void Arch::unbindWire(WireId wire) void Arch::unbindWire(WireId wire)
{ {
auto &net_wires = wires.at(wire).bound_net->wires; auto &net_wires = wire_info(wire).bound_net->wires;
auto pip = net_wires.at(wire).pip; auto pip = net_wires.at(wire).pip;
if (pip != PipId()) { if (pip != PipId()) {
pips.at(pip).bound_net = nullptr; pip_info(pip).bound_net = nullptr;
refreshUiPip(pip); refreshUiPip(pip);
} }
net_wires.erase(wire); net_wires.erase(wire);
wires.at(wire).bound_net = nullptr; wire_info(wire).bound_net = nullptr;
refreshUiWire(wire); refreshUiWire(wire);
} }
bool Arch::checkWireAvail(WireId wire) const { return wires.at(wire).bound_net == nullptr; } bool Arch::checkWireAvail(WireId wire) const { return wire_info(wire).bound_net == nullptr; }
NetInfo *Arch::getBoundWireNet(WireId wire) const { return wires.at(wire).bound_net; } NetInfo *Arch::getBoundWireNet(WireId wire) const { return wire_info(wire).bound_net; }
NetInfo *Arch::getConflictingWireNet(WireId wire) const { return wires.at(wire).bound_net; } NetInfo *Arch::getConflictingWireNet(WireId wire) const { return wire_info(wire).bound_net; }
const std::vector<BelPin> &Arch::getWireBelPins(WireId wire) const { return wires.at(wire).bel_pins; } const std::vector<BelPin> &Arch::getWireBelPins(WireId wire) const { return wire_info(wire).bel_pins; }
const std::vector<WireId> &Arch::getWires() const { return wire_ids; } linear_range<WireId> Arch::getWires() const { return linear_range<WireId>(wires.size()); }
// --------------------------------------------------------------- // ---------------------------------------------------------------
PipId Arch::getPipByName(IdStringList name) const PipId Arch::getPipByName(IdStringList name) const
{ {
if (pips.count(name)) if (name.size() == 0)
return name; return PipId();
return PipId(); auto fnd = pip_by_name.find(name);
if (fnd == pip_by_name.end())
NPNR_ASSERT_FALSE_STR("no pip named " + name.str(getCtx()));
return fnd->second;
} }
IdStringList Arch::getPipName(PipId pip) const { return pip; } IdStringList Arch::getPipName(PipId pip) const { return pip_info(pip).name; }
IdString Arch::getPipType(PipId pip) const { return pips.at(pip).type; } IdString Arch::getPipType(PipId pip) const { return pip_info(pip).type; }
const std::map<IdString, std::string> &Arch::getPipAttrs(PipId pip) const { return pips.at(pip).attrs; } const std::map<IdString, std::string> &Arch::getPipAttrs(PipId pip) const { return pip_info(pip).attrs; }
uint32_t Arch::getPipChecksum(PipId wire) const uint32_t Arch::getPipChecksum(PipId pip) const { return pip.index; }
{
// FIXME
return 0;
}
void Arch::bindPip(PipId pip, NetInfo *net, PlaceStrength strength) void Arch::bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
{ {
WireId wire = pips.at(pip).dstWire; WireId wire = pip_info(pip).dstWire;
pips.at(pip).bound_net = net; pip_info(pip).bound_net = net;
wires.at(wire).bound_net = net; wire_info(wire).bound_net = net;
net->wires[wire].pip = pip; net->wires[wire].pip = pip;
net->wires[wire].strength = strength; net->wires[wire].strength = strength;
refreshUiPip(pip); refreshUiPip(pip);
@ -440,41 +423,44 @@ void Arch::bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
void Arch::unbindPip(PipId pip) void Arch::unbindPip(PipId pip)
{ {
WireId wire = pips.at(pip).dstWire; WireId wire = pip_info(pip).dstWire;
wires.at(wire).bound_net->wires.erase(wire); wire_info(wire).bound_net->wires.erase(wire);
pips.at(pip).bound_net = nullptr; pip_info(pip).bound_net = nullptr;
wires.at(wire).bound_net = nullptr; wire_info(wire).bound_net = nullptr;
refreshUiPip(pip); refreshUiPip(pip);
refreshUiWire(wire); refreshUiWire(wire);
} }
bool Arch::checkPipAvail(PipId pip) const { return pips.at(pip).bound_net == nullptr; } bool Arch::checkPipAvail(PipId pip) const { return pip_info(pip).bound_net == nullptr; }
bool Arch::checkPipAvailForNet(PipId pip, NetInfo *net) const bool Arch::checkPipAvailForNet(PipId pip, NetInfo *net) const
{ {
NetInfo *bound_net = pips.at(pip).bound_net; NetInfo *bound_net = pip_info(pip).bound_net;
return bound_net == nullptr || bound_net == net; return bound_net == nullptr || bound_net == net;
} }
NetInfo *Arch::getBoundPipNet(PipId pip) const { return pips.at(pip).bound_net; } NetInfo *Arch::getBoundPipNet(PipId pip) const { return pip_info(pip).bound_net; }
NetInfo *Arch::getConflictingPipNet(PipId pip) const { return pips.at(pip).bound_net; } NetInfo *Arch::getConflictingPipNet(PipId pip) const { return pip_info(pip).bound_net; }
WireId Arch::getConflictingPipWire(PipId pip) const { return pips.at(pip).bound_net ? pips.at(pip).dstWire : WireId(); } WireId Arch::getConflictingPipWire(PipId pip) const
{
return pip_info(pip).bound_net ? pip_info(pip).dstWire : WireId();
}
const std::vector<PipId> &Arch::getPips() const { return pip_ids; } linear_range<PipId> Arch::getPips() const { return linear_range<PipId>(pips.size()); }
Loc Arch::getPipLocation(PipId pip) const { return pips.at(pip).loc; } Loc Arch::getPipLocation(PipId pip) const { return pip_info(pip).loc; }
WireId Arch::getPipSrcWire(PipId pip) const { return pips.at(pip).srcWire; } WireId Arch::getPipSrcWire(PipId pip) const { return pip_info(pip).srcWire; }
WireId Arch::getPipDstWire(PipId pip) const { return pips.at(pip).dstWire; } WireId Arch::getPipDstWire(PipId pip) const { return pip_info(pip).dstWire; }
DelayQuad Arch::getPipDelay(PipId pip) const { return DelayQuad(pips.at(pip).delay); } DelayQuad Arch::getPipDelay(PipId pip) const { return DelayQuad(pip_info(pip).delay); }
const std::vector<PipId> &Arch::getPipsDownhill(WireId wire) const { return wires.at(wire).downhill; } const std::vector<PipId> &Arch::getPipsDownhill(WireId wire) const { return wire_info(wire).downhill; }
const std::vector<PipId> &Arch::getPipsUphill(WireId wire) const { return wires.at(wire).uphill; } const std::vector<PipId> &Arch::getPipsUphill(WireId wire) const { return wire_info(wire).uphill; }
// --------------------------------------------------------------- // ---------------------------------------------------------------
@ -502,8 +488,8 @@ const std::vector<GroupId> &Arch::getGroupGroups(GroupId group) const { return g
delay_t Arch::estimateDelay(WireId src, WireId dst) const delay_t Arch::estimateDelay(WireId src, WireId dst) const
{ {
const WireInfo &s = wires.at(src); const WireInfo &s = wire_info(src);
const WireInfo &d = wires.at(dst); const WireInfo &d = wire_info(dst);
int dx = abs(s.x - d.x); int dx = abs(s.x - d.x);
int dy = abs(s.y - d.y); int dy = abs(s.y - d.y);
return (dx + dy) * args.delayScale + args.delayOffset; return (dx + dy) * args.delayScale + args.delayOffset;
@ -527,10 +513,10 @@ ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const
{ {
ArcBounds bb; ArcBounds bb;
int src_x = wires.at(src).x; int src_x = wire_info(src).x;
int src_y = wires.at(src).y; int src_y = wire_info(src).y;
int dst_x = wires.at(dst).x; int dst_x = wire_info(dst).x;
int dst_y = wires.at(dst).y; int dst_y = wire_info(dst).y;
bb.x0 = src_x; bb.x0 = src_x;
bb.y0 = src_y; bb.y0 = src_y;
@ -611,11 +597,11 @@ const std::vector<GraphicElement> &Arch::getDecalGraphics(DecalId decal) const
return decal_graphics.at(decal); return decal_graphics.at(decal);
} }
DecalXY Arch::getBelDecal(BelId bel) const { return bels.at(bel).decalxy; } DecalXY Arch::getBelDecal(BelId bel) const { return bel_info(bel).decalxy; }
DecalXY Arch::getWireDecal(WireId wire) const { return wires.at(wire).decalxy; } DecalXY Arch::getWireDecal(WireId wire) const { return wire_info(wire).decalxy; }
DecalXY Arch::getPipDecal(PipId pip) const { return pips.at(pip).decalxy; } DecalXY Arch::getPipDecal(PipId pip) const { return pip_info(pip).decalxy; }
DecalXY Arch::getGroupDecal(GroupId group) const { return groups.at(group).decalxy; } DecalXY Arch::getGroupDecal(GroupId group) const { return groups.at(group).decalxy; }

View File

@ -60,8 +60,6 @@ struct WireInfo
std::map<IdString, std::string> attrs; std::map<IdString, std::string> attrs;
NetInfo *bound_net; NetInfo *bound_net;
std::vector<PipId> downhill, uphill; std::vector<PipId> downhill, uphill;
BelPin uphill_bel_pin;
std::vector<BelPin> downhill_bel_pins;
std::vector<BelPin> bel_pins; std::vector<BelPin> bel_pins;
DecalXY decalxy; DecalXY decalxy;
int x, y; int x, y;
@ -111,23 +109,40 @@ struct CellTiming
dict<IdString, std::vector<TimingClockingInfo>> clockingInfo; dict<IdString, std::vector<TimingClockingInfo>> clockingInfo;
}; };
template <typename TId> struct linear_range
{
struct iterator
{
explicit iterator(int32_t index) : index(index){};
int32_t index;
bool operator==(const iterator &other) const { return index == other.index; }
bool operator!=(const iterator &other) const { return index != other.index; }
void operator++() { ++index; }
TId operator*() const { return TId(index); }
};
explicit linear_range(int32_t size) : size(size){};
int32_t size;
iterator begin() const { return iterator(0); }
iterator end() const { return iterator(size); }
};
struct ArchRanges struct ArchRanges
{ {
using ArchArgsT = ArchArgs; using ArchArgsT = ArchArgs;
// Bels // Bels
using AllBelsRangeT = const std::vector<BelId> &; using AllBelsRangeT = linear_range<BelId>;
using TileBelsRangeT = const std::vector<BelId> &; using TileBelsRangeT = const std::vector<BelId> &;
using BelAttrsRangeT = const std::map<IdString, std::string> &; using BelAttrsRangeT = const std::map<IdString, std::string> &;
using BelPinsRangeT = std::vector<IdString>; using BelPinsRangeT = std::vector<IdString>;
using CellBelPinRangeT = const std::vector<IdString> &; using CellBelPinRangeT = const std::vector<IdString> &;
// Wires // Wires
using AllWiresRangeT = const std::vector<WireId> &; using AllWiresRangeT = linear_range<WireId>;
using DownhillPipRangeT = const std::vector<PipId> &; using DownhillPipRangeT = const std::vector<PipId> &;
using UphillPipRangeT = const std::vector<PipId> &; using UphillPipRangeT = const std::vector<PipId> &;
using WireBelPinRangeT = const std::vector<BelPin> &; using WireBelPinRangeT = const std::vector<BelPin> &;
using WireAttrsRangeT = const std::map<IdString, std::string> &; using WireAttrsRangeT = const std::map<IdString, std::string> &;
// Pips // Pips
using AllPipsRangeT = const std::vector<PipId> &; using AllPipsRangeT = linear_range<PipId>;
using PipAttrsRangeT = const std::map<IdString, std::string> &; using PipAttrsRangeT = const std::map<IdString, std::string> &;
// Groups // Groups
using AllGroupsRangeT = std::vector<GroupId>; using AllGroupsRangeT = std::vector<GroupId>;
@ -147,17 +162,22 @@ struct Arch : ArchAPI<ArchRanges>
{ {
std::string chipName; std::string chipName;
dict<IdStringList, WireInfo> wires; std::vector<WireInfo> wires;
dict<IdStringList, PipInfo> pips; std::vector<PipInfo> pips;
dict<IdStringList, BelInfo> bels; std::vector<BelInfo> bels;
dict<GroupId, GroupInfo> groups; dict<GroupId, GroupInfo> groups;
// These functions include useful errors if not found WireInfo &wire_info(WireId wire) { return wires.at(wire.index); }
WireInfo &wire_info(IdStringList wire); PipInfo &pip_info(PipId pip) { return pips.at(pip.index); }
PipInfo &pip_info(IdStringList wire); BelInfo &bel_info(BelId bel) { return bels.at(bel.index); }
BelInfo &bel_info(IdStringList wire);
std::vector<IdStringList> bel_ids, wire_ids, pip_ids; const WireInfo &wire_info(WireId wire) const { return wires.at(wire.index); }
const PipInfo &pip_info(PipId pip) const { return pips.at(pip.index); }
const BelInfo &bel_info(BelId bel) const { return bels.at(bel.index); }
dict<IdStringList, WireId> wire_by_name;
dict<IdStringList, PipId> pip_by_name;
dict<IdStringList, BelId> bel_by_name;
dict<Loc, BelId> bel_by_loc; dict<Loc, BelId> bel_by_loc;
std::vector<std::vector<std::vector<BelId>>> bels_by_tile; std::vector<std::vector<std::vector<BelId>>> bels_by_tile;
@ -170,17 +190,17 @@ struct Arch : ArchAPI<ArchRanges>
dict<IdString, CellTiming> cellTiming; dict<IdString, CellTiming> cellTiming;
void addWire(IdStringList name, IdString type, int x, int y); WireId addWire(IdStringList name, IdString type, int x, int y);
void addPip(IdStringList name, IdString type, IdStringList srcWire, IdStringList dstWire, delay_t delay, Loc loc); PipId addPip(IdStringList name, IdString type, WireId srcWire, WireId dstWire, delay_t delay, Loc loc);
void addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidden); BelId addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidden);
void addBelInput(IdStringList bel, IdString name, IdStringList wire); void addBelInput(BelId bel, IdString name, WireId wire);
void addBelOutput(IdStringList bel, IdString name, IdStringList wire); void addBelOutput(BelId bel, IdString name, WireId wire);
void addBelInout(IdStringList bel, IdString name, IdStringList wire); void addBelInout(BelId bel, IdString name, WireId wire);
void addGroupBel(IdStringList group, IdStringList bel); void addGroupBel(IdStringList group, BelId bel);
void addGroupWire(IdStringList group, IdStringList wire); void addGroupWire(IdStringList group, WireId wire);
void addGroupPip(IdStringList group, IdStringList pip); void addGroupPip(IdStringList group, PipId pip);
void addGroupGroup(IdStringList group, IdStringList grp); void addGroupGroup(IdStringList group, IdStringList grp);
void addDecalGraphic(DecalId decal, const GraphicElement &graphic); void addDecalGraphic(DecalId decal, const GraphicElement &graphic);
@ -189,9 +209,9 @@ struct Arch : ArchAPI<ArchRanges>
void setBelDecal(BelId bel, DecalXY decalxy); void setBelDecal(BelId bel, DecalXY decalxy);
void setGroupDecal(GroupId group, DecalXY decalxy); void setGroupDecal(GroupId group, DecalXY decalxy);
void setWireAttr(IdStringList wire, IdString key, const std::string &value); void setWireAttr(WireId wire, IdString key, const std::string &value);
void setPipAttr(IdStringList pip, IdString key, const std::string &value); void setPipAttr(PipId pip, IdString key, const std::string &value);
void setBelAttr(IdStringList bel, IdString key, const std::string &value); void setBelAttr(BelId bel, IdString key, const std::string &value);
void setLutK(int K); void setLutK(int K);
void setDelayScaling(double scale, double offset); void setDelayScaling(double scale, double offset);
@ -234,7 +254,7 @@ struct Arch : ArchAPI<ArchRanges>
bool checkBelAvail(BelId bel) const override; bool checkBelAvail(BelId bel) const override;
CellInfo *getBoundBelCell(BelId bel) const override; CellInfo *getBoundBelCell(BelId bel) const override;
CellInfo *getConflictingBelCell(BelId bel) const override; CellInfo *getConflictingBelCell(BelId bel) const override;
const std::vector<BelId> &getBels() const override; linear_range<BelId> getBels() const override;
IdString getBelType(BelId bel) const override; IdString getBelType(BelId bel) const override;
bool getBelHidden(BelId bel) const override; bool getBelHidden(BelId bel) const override;
const std::map<IdString, std::string> &getBelAttrs(BelId bel) const override; const std::map<IdString, std::string> &getBelAttrs(BelId bel) const override;
@ -255,7 +275,7 @@ struct Arch : ArchAPI<ArchRanges>
WireId getConflictingWireWire(WireId wire) const override { return wire; } WireId getConflictingWireWire(WireId wire) const override { return wire; }
NetInfo *getConflictingWireNet(WireId wire) const override; NetInfo *getConflictingWireNet(WireId wire) const override;
DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); } DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); }
const std::vector<WireId> &getWires() const override; linear_range<WireId> getWires() const override;
const std::vector<BelPin> &getWireBelPins(WireId wire) const override; const std::vector<BelPin> &getWireBelPins(WireId wire) const override;
PipId getPipByName(IdStringList name) const override; PipId getPipByName(IdStringList name) const override;
@ -270,7 +290,7 @@ struct Arch : ArchAPI<ArchRanges>
NetInfo *getBoundPipNet(PipId pip) const override; NetInfo *getBoundPipNet(PipId pip) const override;
WireId getConflictingPipWire(PipId pip) const override; WireId getConflictingPipWire(PipId pip) const override;
NetInfo *getConflictingPipNet(PipId pip) const override; NetInfo *getConflictingPipNet(PipId pip) const override;
const std::vector<PipId> &getPips() const override; linear_range<PipId> getPips() const override;
Loc getPipLocation(PipId pip) const override; Loc getPipLocation(PipId pip) const override;
WireId getPipSrcWire(PipId pip) const override; WireId getPipSrcWire(PipId pip) const override;
WireId getPipDstWire(PipId pip) const override; WireId getPipDstWire(PipId pip) const override;
@ -307,7 +327,7 @@ struct Arch : ArchAPI<ArchRanges>
{ {
pool<IdString> cell_types; pool<IdString> cell_types;
for (auto bel : bels) { for (auto bel : bels) {
cell_types.insert(bel.second.type); cell_types.insert(bel.type);
} }
return std::vector<IdString>{cell_types.begin(), cell_types.end()}; return std::vector<IdString>{cell_types.begin(), cell_types.end()};

View File

@ -42,6 +42,10 @@ void arch_wrap_python(py::module &m)
{ {
using namespace PythonConversion; using namespace PythonConversion;
typedef linear_range<BelId> BelRange;
typedef linear_range<WireId> WireRange;
typedef linear_range<PipId> AllPipRange;
auto arch_cls = py::class_<Arch, BaseCtx>(m, "Arch").def(py::init<ArchArgs>()); auto arch_cls = py::class_<Arch, BaseCtx>(m, "Arch").def(py::init<ArchArgs>());
auto dxy_cls = py::class_<ContextualWrapper<DecalXY>>(m, "DecalXY_"); auto dxy_cls = py::class_<ContextualWrapper<DecalXY>>(m, "DecalXY_");
@ -74,8 +78,8 @@ void arch_wrap_python(py::module &m)
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBoundBelCell"); conv_from_str<BelId>>::def_wrap(ctx_cls, "getBoundBelCell");
fn_wrapper_1a<Context, decltype(&Context::getConflictingBelCell), &Context::getConflictingBelCell, fn_wrapper_1a<Context, decltype(&Context::getConflictingBelCell), &Context::getConflictingBelCell,
deref_and_wrap<CellInfo>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell"); deref_and_wrap<CellInfo>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell");
fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels, fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels, wrap_context<BelRange>>::def_wrap(ctx_cls,
wrap_context<const std::vector<BelId> &>>::def_wrap(ctx_cls, "getBels"); "getBels");
fn_wrapper_2a<Context, decltype(&Context::getBelPinWire), &Context::getBelPinWire, conv_to_str<WireId>, 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"); conv_from_str<BelId>, conv_from_str<IdString>>::def_wrap(ctx_cls, "getBelPinWire");
@ -96,11 +100,11 @@ void arch_wrap_python(py::module &m)
fn_wrapper_1a<Context, decltype(&Context::getConflictingWireNet), &Context::getConflictingWireNet, fn_wrapper_1a<Context, decltype(&Context::getConflictingWireNet), &Context::getConflictingWireNet,
deref_and_wrap<NetInfo>, conv_from_str<WireId>>::def_wrap(ctx_cls, "getConflictingWireNet"); deref_and_wrap<NetInfo>, conv_from_str<WireId>>::def_wrap(ctx_cls, "getConflictingWireNet");
fn_wrapper_0a<Context, decltype(&Context::getWires), &Context::getWires, fn_wrapper_0a<Context, decltype(&Context::getWires), &Context::getWires, wrap_context<WireRange>>::def_wrap(
wrap_context<const std::vector<WireId> &>>::def_wrap(ctx_cls, "getWires"); ctx_cls, "getWires");
fn_wrapper_0a<Context, decltype(&Context::getPips), &Context::getPips, fn_wrapper_0a<Context, decltype(&Context::getPips), &Context::getPips, wrap_context<AllPipRange>>::def_wrap(
wrap_context<const std::vector<PipId> &>>::def_wrap(ctx_cls, "getPips"); ctx_cls, "getPips");
fn_wrapper_1a<Context, decltype(&Context::getPipChecksum), &Context::getPipChecksum, pass_through<uint32_t>, fn_wrapper_1a<Context, decltype(&Context::getPipChecksum), &Context::getPipChecksum, pass_through<uint32_t>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipChecksum"); conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindPip), &Context::bindPip, conv_from_str<PipId>, fn_wrapper_3a_v<Context, decltype(&Context::bindPip), &Context::bindPip, conv_from_str<PipId>,
@ -156,50 +160,50 @@ void arch_wrap_python(py::module &m)
"name"_a, "type"_a, "x"_a, "name"_a, "type"_a, "x"_a,
"y"_a); "y"_a);
fn_wrapper_6a_v<Context, decltype(&Context::addPip), &Context::addPip, conv_from_str<IdStringList>, fn_wrapper_6a_v<Context, decltype(&Context::addPip), &Context::addPip, conv_from_str<IdStringList>,
conv_from_str<IdString>, conv_from_str<IdStringList>, conv_from_str<IdStringList>, conv_from_str<IdString>, conv_from_str<WireId>, conv_from_str<WireId>, pass_through<delay_t>,
pass_through<delay_t>, pass_through<Loc>>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a, pass_through<Loc>>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a, "srcWire"_a, "dstWire"_a,
"srcWire"_a, "dstWire"_a, "delay"_a, "loc"_a); "delay"_a, "loc"_a);
fn_wrapper_5a_v<Context, decltype(&Context::addBel), &Context::addBel, conv_from_str<IdStringList>, fn_wrapper_5a_v<Context, decltype(&Context::addBel), &Context::addBel, conv_from_str<IdStringList>,
conv_from_str<IdString>, pass_through<Loc>, pass_through<bool>, conv_from_str<IdString>, pass_through<Loc>, pass_through<bool>,
pass_through<bool>>::def_wrap(ctx_cls, "addBel", "name"_a, "type"_a, "loc"_a, "gb"_a, "hidden"_a); pass_through<bool>>::def_wrap(ctx_cls, "addBel", "name"_a, "type"_a, "loc"_a, "gb"_a, "hidden"_a);
fn_wrapper_3a_v<Context, decltype(&Context::addBelInput), &Context::addBelInput, conv_from_str<IdStringList>, fn_wrapper_3a_v<Context, decltype(&Context::addBelInput), &Context::addBelInput, conv_from_str<BelId>,
conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelInput", "bel"_a, conv_from_str<IdString>, conv_from_str<WireId>>::def_wrap(ctx_cls, "addBelInput", "bel"_a, "name"_a,
"name"_a, "wire"_a); "wire"_a);
fn_wrapper_3a_v<Context, decltype(&Context::addBelOutput), &Context::addBelOutput, conv_from_str<IdStringList>, fn_wrapper_3a_v<Context, decltype(&Context::addBelOutput), &Context::addBelOutput, conv_from_str<BelId>,
conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelOutput", "bel"_a, conv_from_str<IdString>, conv_from_str<WireId>>::def_wrap(ctx_cls, "addBelOutput", "bel"_a,
"name"_a, "wire"_a); "name"_a, "wire"_a);
fn_wrapper_3a_v<Context, decltype(&Context::addBelInout), &Context::addBelInout, conv_from_str<IdStringList>, fn_wrapper_3a_v<Context, decltype(&Context::addBelInout), &Context::addBelInout, conv_from_str<BelId>,
conv_from_str<IdString>, conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addBelInout", "bel"_a, conv_from_str<IdString>, conv_from_str<WireId>>::def_wrap(ctx_cls, "addBelInout", "bel"_a, "name"_a,
"name"_a, "wire"_a); "wire"_a);
fn_wrapper_2a_v<Context, decltype(&Context::addGroupBel), &Context::addGroupBel, conv_from_str<IdStringList>, fn_wrapper_2a_v<Context, decltype(&Context::addGroupBel), &Context::addGroupBel, conv_from_str<IdStringList>,
conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupBel", "group"_a, "bel"_a); conv_from_str<BelId>>::def_wrap(ctx_cls, "addGroupBel", "group"_a, "bel"_a);
fn_wrapper_2a_v<Context, decltype(&Context::addGroupWire), &Context::addGroupWire, conv_from_str<IdStringList>, fn_wrapper_2a_v<Context, decltype(&Context::addGroupWire), &Context::addGroupWire, conv_from_str<IdStringList>,
conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupWire", "group"_a, "wire"_a); conv_from_str<WireId>>::def_wrap(ctx_cls, "addGroupWire", "group"_a, "wire"_a);
fn_wrapper_2a_v<Context, decltype(&Context::addGroupPip), &Context::addGroupPip, conv_from_str<IdStringList>, fn_wrapper_2a_v<Context, decltype(&Context::addGroupPip), &Context::addGroupPip, conv_from_str<IdStringList>,
conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupPip", "group"_a, "pip"_a); conv_from_str<PipId>>::def_wrap(ctx_cls, "addGroupPip", "group"_a, "pip"_a);
fn_wrapper_2a_v<Context, decltype(&Context::addGroupGroup), &Context::addGroupPip, conv_from_str<IdStringList>, fn_wrapper_2a_v<Context, decltype(&Context::addGroupGroup), &Context::addGroupGroup, conv_from_str<IdStringList>,
conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupGroup", "group"_a, "grp"_a); conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupGroup", "group"_a, "grp"_a);
fn_wrapper_2a_v<Context, decltype(&Context::addDecalGraphic), &Context::addDecalGraphic, conv_from_str<DecalId>, fn_wrapper_2a_v<Context, decltype(&Context::addDecalGraphic), &Context::addDecalGraphic, conv_from_str<DecalId>,
pass_through<GraphicElement>>::def_wrap(ctx_cls, "addDecalGraphic", (py::arg("decal"), "graphic")); pass_through<GraphicElement>>::def_wrap(ctx_cls, "addDecalGraphic", (py::arg("decal"), "graphic"));
fn_wrapper_2a_v<Context, decltype(&Context::setWireDecal), &Context::setWireDecal, conv_from_str<DecalId>, fn_wrapper_2a_v<Context, decltype(&Context::setWireDecal), &Context::setWireDecal, conv_from_str<WireId>,
unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setWireDecal", "wire"_a, "decalxy"_a); unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setWireDecal", "wire"_a, "decalxy"_a);
fn_wrapper_2a_v<Context, decltype(&Context::setPipDecal), &Context::setPipDecal, conv_from_str<DecalId>, fn_wrapper_2a_v<Context, decltype(&Context::setPipDecal), &Context::setPipDecal, conv_from_str<PipId>,
unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setPipDecal", "pip"_a, "decalxy"_a); unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setPipDecal", "pip"_a, "decalxy"_a);
fn_wrapper_2a_v<Context, decltype(&Context::setBelDecal), &Context::setBelDecal, conv_from_str<DecalId>, fn_wrapper_2a_v<Context, decltype(&Context::setBelDecal), &Context::setBelDecal, conv_from_str<BelId>,
unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setBelDecal", "bel"_a, "decalxy"_a); unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setBelDecal", "bel"_a, "decalxy"_a);
fn_wrapper_2a_v<Context, decltype(&Context::setGroupDecal), &Context::setGroupDecal, conv_from_str<DecalId>, fn_wrapper_2a_v<Context, decltype(&Context::setGroupDecal), &Context::setGroupDecal, conv_from_str<DecalId>,
unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setGroupDecal", "group"_a, "decalxy"_a); unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setGroupDecal", "group"_a, "decalxy"_a);
fn_wrapper_3a_v<Context, decltype(&Context::setWireAttr), &Context::setWireAttr, conv_from_str<DecalId>, fn_wrapper_3a_v<Context, decltype(&Context::setWireAttr), &Context::setWireAttr, conv_from_str<WireId>,
conv_from_str<IdString>, pass_through<std::string>>::def_wrap(ctx_cls, "setWireAttr", "wire"_a, conv_from_str<IdString>, pass_through<std::string>>::def_wrap(ctx_cls, "setWireAttr", "wire"_a,
"key"_a, "value"_a); "key"_a, "value"_a);
fn_wrapper_3a_v<Context, decltype(&Context::setBelAttr), &Context::setBelAttr, conv_from_str<DecalId>, fn_wrapper_3a_v<Context, decltype(&Context::setBelAttr), &Context::setBelAttr, conv_from_str<BelId>,
conv_from_str<IdString>, pass_through<std::string>>::def_wrap(ctx_cls, "setBelAttr", "bel"_a, conv_from_str<IdString>, pass_through<std::string>>::def_wrap(ctx_cls, "setBelAttr", "bel"_a,
"key"_a, "value"_a); "key"_a, "value"_a);
fn_wrapper_3a_v<Context, decltype(&Context::setPipAttr), &Context::setPipAttr, conv_from_str<DecalId>, fn_wrapper_3a_v<Context, decltype(&Context::setPipAttr), &Context::setPipAttr, conv_from_str<PipId>,
conv_from_str<IdString>, pass_through<std::string>>::def_wrap(ctx_cls, "setPipAttr", "pip"_a, conv_from_str<IdString>, pass_through<std::string>>::def_wrap(ctx_cls, "setPipAttr", "pip"_a,
"key"_a, "value"_a); "key"_a, "value"_a);
@ -254,6 +258,10 @@ void arch_wrap_python(py::module &m)
pass_through<bool>, conv_from_str<IdString>, conv_from_str<BelId>>::def_wrap(ctx_cls, pass_through<bool>, conv_from_str<IdString>, conv_from_str<BelId>>::def_wrap(ctx_cls,
"isValidBelForCellType"); "isValidBelForCellType");
WRAP_RANGE(m, Bel, conv_to_str<BelId>);
WRAP_RANGE(m, Wire, conv_to_str<WireId>);
WRAP_RANGE(m, AllPip, conv_to_str<PipId>);
WRAP_MAP_UPTR(m, CellMap, "IdCellMap"); WRAP_MAP_UPTR(m, CellMap, "IdCellMap");
WRAP_MAP_UPTR(m, NetMap, "IdNetMap"); WRAP_MAP_UPTR(m, NetMap, "IdNetMap");
WRAP_MAP(m, HierarchyMap, wrap_context<HierarchicalCell &>, "HierarchyMap"); WRAP_MAP(m, HierarchyMap, wrap_context<HierarchicalCell &>, "HierarchyMap");

View File

@ -26,6 +26,73 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
namespace PythonConversion {
template <> struct string_converter<BelId>
{
BelId from_str(Context *ctx, std::string name) { return ctx->getBelByNameStr(name); }
std::string to_str(Context *ctx, BelId id)
{
if (id == BelId())
throw bad_wrap();
return ctx->getBelName(id).str(ctx);
}
};
template <> struct string_converter<WireId>
{
WireId from_str(Context *ctx, std::string name) { return ctx->getWireByNameStr(name); }
std::string to_str(Context *ctx, WireId id)
{
if (id == WireId())
throw bad_wrap();
return ctx->getWireName(id).str(ctx);
}
};
template <> struct string_converter<const WireId>
{
WireId from_str(Context *ctx, std::string name) { return ctx->getWireByNameStr(name); }
std::string to_str(Context *ctx, WireId id)
{
if (id == WireId())
throw bad_wrap();
return ctx->getWireName(id).str(ctx);
}
};
template <> struct string_converter<PipId>
{
PipId from_str(Context *ctx, std::string name) { return ctx->getPipByNameStr(name); }
std::string to_str(Context *ctx, PipId id)
{
if (id == PipId())
throw bad_wrap();
return ctx->getPipName(id).str(ctx);
}
};
template <> struct string_converter<BelPin>
{
BelPin from_str(Context *ctx, std::string name)
{
NPNR_ASSERT_FALSE("string_converter<BelPin>::from_str not implemented");
}
std::string to_str(Context *ctx, BelPin pin)
{
if (pin.bel == BelId())
throw bad_wrap();
return ctx->getBelName(pin.bel).str(ctx) + "/" + pin.pin.str(ctx);
}
};
} // namespace PythonConversion
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END
#endif #endif
#endif #endif

View File

@ -27,9 +27,42 @@ NEXTPNR_NAMESPACE_BEGIN
typedef float delay_t; typedef float delay_t;
typedef IdStringList BelId; struct BelId
typedef IdStringList WireId; {
typedef IdStringList PipId; BelId() : index(-1){};
explicit BelId(int32_t index) : index(index){};
int32_t index = -1;
bool operator==(const BelId &other) const { return index == other.index; }
bool operator!=(const BelId &other) const { return index != other.index; }
bool operator<(const BelId &other) const { return index < other.index; }
unsigned int hash() const { return index; }
};
struct WireId
{
WireId() : index(-1){};
explicit WireId(int32_t index) : index(index){};
int32_t index = -1;
bool operator==(const WireId &other) const { return index == other.index; }
bool operator!=(const WireId &other) const { return index != other.index; }
bool operator<(const WireId &other) const { return index < other.index; }
unsigned int hash() const { return index; }
};
struct PipId
{
PipId() : index(-1){};
explicit PipId(int32_t index) : index(index){};
int32_t index = -1;
bool operator==(const PipId &other) const { return index == other.index; }
bool operator!=(const PipId &other) const { return index != other.index; }
bool operator<(const PipId &other) const { return index < other.index; }
unsigned int hash() const { return index; }
};
typedef IdStringList GroupId; typedef IdStringList GroupId;
typedef IdStringList DecalId; typedef IdStringList DecalId;
typedef IdString BelBucketId; typedef IdString BelBucketId;

View File

@ -29,7 +29,7 @@ def write_fasm(ctx, paramCfg, f):
for nname, net in sorted(ctx.nets, key=lambda x: str(x[1].name)): for nname, net in sorted(ctx.nets, key=lambda x: str(x[1].name)):
print("# Net %s" % nname, file=f) print("# Net %s" % nname, file=f)
for wire, pip in sorted(net.wires, key=lambda x: str(x[1])): for wire, pip in sorted(net.wires, key=lambda x: str(x[1])):
if pip.pip != "": if pip.pip is not None:
print("%s" % pip.pip, file=f) print("%s" % pip.pip, file=f)
print("", file=f) print("", file=f)
for cname, cell in sorted(ctx.cells, key=lambda x: str(x[1].name)): for cname, cell in sorted(ctx.cells, key=lambda x: str(x[1].name)):