Add Python helper functions for floorplanning
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
ae33ff397f
commit
493d6c3fb9
@ -421,4 +421,25 @@ void BaseCtx::addClock(IdString net, float freq)
|
||||
}
|
||||
}
|
||||
|
||||
void BaseCtx::createRectangularRegion(IdString name, int x0, int y0, int x1, int y1)
|
||||
{
|
||||
std::unique_ptr<Region> new_region(new Region());
|
||||
new_region->name = name;
|
||||
new_region->constr_bels = true;
|
||||
new_region->constr_pips = false;
|
||||
new_region->constr_wires = false;
|
||||
for (int x = x0; x <= x1; x++) {
|
||||
for (int y = y0; y <= y1; y++) {
|
||||
for (auto bel : getCtx()->getBelsByTile(x, y))
|
||||
new_region->bels.insert(bel);
|
||||
}
|
||||
}
|
||||
region[name] = std::move(new_region);
|
||||
}
|
||||
void BaseCtx::addBelToRegion(IdString name, BelId bel) { region[name]->bels.insert(bel); }
|
||||
void BaseCtx::constrainCellToRegion(IdString cell, IdString region_name)
|
||||
{
|
||||
cells[cell]->region = region[region_name].get();
|
||||
}
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
@ -637,6 +637,9 @@ struct BaseCtx
|
||||
|
||||
// Intended to simplify Python API
|
||||
void addClock(IdString net, float freq);
|
||||
void createRectangularRegion(IdString name, int x0, int y0, int x1, int y1);
|
||||
void addBelToRegion(IdString name, BelId bel);
|
||||
void constrainCellToRegion(IdString cell, IdString region_name);
|
||||
};
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
@ -104,6 +104,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME)
|
||||
typedef std::unordered_map<IdString, std::string> AttrMap;
|
||||
typedef std::unordered_map<IdString, PortInfo> PortMap;
|
||||
typedef std::unordered_map<IdString, IdString> PinMap;
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<Region>> RegionMap;
|
||||
|
||||
class_<BaseCtx, BaseCtx *, boost::noncopyable>("BaseCtx", no_init);
|
||||
|
||||
@ -135,6 +136,8 @@ BOOST_PYTHON_MODULE(MODULE_NAME)
|
||||
|
||||
typedef std::vector<PortRef> PortRefVector;
|
||||
typedef std::unordered_map<WireId, PipMap> WireMap;
|
||||
typedef std::unordered_set<BelId> BelSet;
|
||||
typedef std::unordered_set<WireId> WireSet;
|
||||
|
||||
auto ni_cls = class_<ContextualWrapper<NetInfo &>>("NetInfo", no_init);
|
||||
readwrite_wrapper<NetInfo &, decltype(&NetInfo::name), &NetInfo::name, conv_to_str<IdString>,
|
||||
@ -163,10 +166,25 @@ BOOST_PYTHON_MODULE(MODULE_NAME)
|
||||
def("parse_json", parse_json_shim);
|
||||
def("load_design", load_design_shim, return_value_policy<manage_new_object>());
|
||||
|
||||
auto region_cls = class_<ContextualWrapper<Region &>>("Region", no_init);
|
||||
readwrite_wrapper<Region &, decltype(&Region::name), &Region::name, conv_to_str<IdString>,
|
||||
conv_from_str<IdString>>::def_wrap(region_cls, "name");
|
||||
readwrite_wrapper<Region &, decltype(&Region::constr_bels), &Region::constr_bels, pass_through<bool>,
|
||||
pass_through<bool>>::def_wrap(region_cls, "constr_bels");
|
||||
readwrite_wrapper<Region &, decltype(&Region::constr_wires), &Region::constr_wires, pass_through<bool>,
|
||||
pass_through<bool>>::def_wrap(region_cls, "constr_bels");
|
||||
readwrite_wrapper<Region &, decltype(&Region::constr_pips), &Region::constr_pips, pass_through<bool>,
|
||||
pass_through<bool>>::def_wrap(region_cls, "constr_pips");
|
||||
readonly_wrapper<Region &, decltype(&Region::bels), &Region::bels, wrap_context<BelSet &>>::def_wrap(region_cls,
|
||||
"bels");
|
||||
readonly_wrapper<Region &, decltype(&Region::wires), &Region::wires, wrap_context<WireSet &>>::def_wrap(region_cls,
|
||||
"wires");
|
||||
|
||||
WRAP_MAP(AttrMap, pass_through<std::string>, "AttrMap");
|
||||
WRAP_MAP(PortMap, wrap_context<PortInfo &>, "PortMap");
|
||||
WRAP_MAP(PinMap, conv_to_str<IdString>, "PinMap");
|
||||
WRAP_MAP(WireMap, wrap_context<PipMap &>, "WireMap");
|
||||
WRAP_MAP_UPTR(RegionMap, "RegionMap");
|
||||
|
||||
WRAP_VECTOR(PortRefVector, wrap_context<PortRef &>);
|
||||
|
||||
|
@ -269,7 +269,7 @@ template <typename Class, typename FuncT, FuncT fn, typename arg1_conv, typename
|
||||
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
|
||||
};
|
||||
|
||||
// Three parameters, one return
|
||||
// Three parameters, no return
|
||||
template <typename Class, typename FuncT, FuncT fn, typename arg1_conv, typename arg2_conv, typename arg3_conv>
|
||||
struct fn_wrapper_3a_v
|
||||
{
|
||||
@ -288,6 +288,30 @@ struct fn_wrapper_3a_v
|
||||
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
|
||||
};
|
||||
|
||||
// Five parameters, no return
|
||||
template <typename Class, typename FuncT, FuncT fn, typename arg1_conv, typename arg2_conv, typename arg3_conv,
|
||||
typename arg4_conv, typename arg5_conv>
|
||||
struct fn_wrapper_5a_v
|
||||
{
|
||||
using class_type = typename WrapIfNotContext<Class>::maybe_wrapped_t;
|
||||
using conv_arg1_type = typename arg1_conv::arg_type;
|
||||
using conv_arg2_type = typename arg2_conv::arg_type;
|
||||
using conv_arg3_type = typename arg3_conv::arg_type;
|
||||
using conv_arg4_type = typename arg4_conv::arg_type;
|
||||
using conv_arg5_type = typename arg5_conv::arg_type;
|
||||
|
||||
static void wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3,
|
||||
conv_arg4_type arg4, conv_arg5_type arg5)
|
||||
{
|
||||
Context *ctx = get_ctx<Class>(cls);
|
||||
Class &base = get_base<Class>(cls);
|
||||
return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3),
|
||||
arg4_conv()(ctx, arg4), arg5_conv()(ctx, arg5));
|
||||
}
|
||||
|
||||
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
|
||||
};
|
||||
|
||||
// Wrapped getter
|
||||
template <typename Class, typename MemT, MemT mem, typename v_conv> struct readonly_wrapper
|
||||
{
|
||||
|
@ -133,6 +133,13 @@ void arch_wrap_python()
|
||||
|
||||
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");
|
||||
|
||||
WRAP_RANGE(Bel, conv_to_str<BelId>);
|
||||
WRAP_RANGE(Wire, conv_to_str<WireId>);
|
||||
|
@ -144,6 +144,13 @@ void arch_wrap_python()
|
||||
|
||||
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");
|
||||
|
||||
WRAP_RANGE(Bel, conv_to_str<BelId>);
|
||||
WRAP_RANGE(Wire, conv_to_str<WireId>);
|
||||
|
Loading…
Reference in New Issue
Block a user