python: Add wrapper for vectors to allow Python access to net.users

Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
David Shah 2018-11-22 12:35:07 +00:00
parent 1731590160
commit e48c9e73e7
3 changed files with 76 additions and 4 deletions

View File

@ -144,7 +144,7 @@ void CommandHandler::setupContext(Context *ctx)
int r;
do {
r = rand();
} while(r == 0);
} while (r == 0);
ctx->rngseed(r);
}

View File

@ -68,6 +68,19 @@ void translate_assertfail(const assertion_failure &e)
PyErr_SetString(PyExc_AssertionError, e.what());
}
namespace PythonConversion {
template <> struct string_converter<PortRef &>
{
inline PortRef from_str(Context *ctx, std::string name) { NPNR_ASSERT_FALSE("PortRef from_str not implemented"); }
inline std::string to_str(Context *ctx, const PortRef &pr)
{
return pr.cell->name.str(ctx) + "." + pr.port.str(ctx);
}
};
} // namespace PythonConversion
BOOST_PYTHON_MODULE(MODULE_NAME)
{
register_exception_translator<assertion_failure>(&translate_assertfail);
@ -120,7 +133,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME)
readwrite_wrapper<PortInfo &, decltype(&PortInfo::type), &PortInfo::type, pass_through<PortType>,
pass_through<PortType>>::def_wrap(pi_cls, "type");
typedef std::vector<PortRef> PortVector;
typedef std::vector<PortRef> PortRefVector;
typedef std::unordered_map<WireId, PipMap> WireMap;
auto ni_cls = class_<ContextualWrapper<NetInfo &>>("NetInfo", no_init);
@ -128,7 +141,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME)
conv_from_str<IdString>>::def_wrap(ni_cls, "name");
readwrite_wrapper<NetInfo &, decltype(&NetInfo::driver), &NetInfo::driver, wrap_context<PortRef &>,
unwrap_context<PortRef &>>::def_wrap(ni_cls, "driver");
readonly_wrapper<NetInfo &, decltype(&NetInfo::users), &NetInfo::users, wrap_context<PortVector &>>::def_wrap(
readonly_wrapper<NetInfo &, decltype(&NetInfo::users), &NetInfo::users, wrap_context<PortRefVector &>>::def_wrap(
ni_cls, "users");
readonly_wrapper<NetInfo &, decltype(&NetInfo::wires), &NetInfo::wires, wrap_context<WireMap &>>::def_wrap(ni_cls,
"wires");
@ -148,6 +161,8 @@ BOOST_PYTHON_MODULE(MODULE_NAME)
WRAP_MAP(PortMap, wrap_context<PortInfo &>, "PortMap");
WRAP_MAP(PinMap, conv_to_str<IdString>, "PinMap");
WRAP_VECTOR(PortRefVector, wrap_context<PortRef &>);
arch_wrap_python();
}

View File

@ -118,10 +118,67 @@ struct range_wrapper
#define WRAP_RANGE(t, conv) \
range_wrapper<t##Range, return_value_policy<return_by_value>, conv>().wrap(#t "Range", #t "Iterator")
/*
A wrapper for a vector or similar structure. With support for conversion
*/
template <typename T, typename P = return_value_policy<return_by_value>,
typename value_conv = PythonConversion::pass_through<T>>
struct vector_wrapper
{
typedef decltype(std::declval<T>().begin()) iterator_t;
typedef decltype(*(std::declval<iterator_t>())) value_t;
typedef typename PythonConversion::ContextualWrapper<T &> wrapped_vector;
typedef typename PythonConversion::ContextualWrapper<std::pair<iterator_t, iterator_t>> wrapped_pair;
using return_t = typename value_conv::ret_type;
static wrapped_pair iter(wrapped_vector &range)
{
return wrapped_pair(range.ctx, std::make_pair(range.base.begin(), range.base.end()));
}
static std::string repr(wrapped_vector &range)
{
PythonConversion::string_converter<value_t> conv;
bool first = true;
std::stringstream ss;
ss << "[";
for (const auto &item : range.base) {
if (!first)
ss << ", ";
ss << "'" << conv.to_str(range.ctx, item) << "'";
first = false;
}
ss << "]";
return ss.str();
}
static int len(wrapped_vector &range) { return range.base.size(); }
static return_t getitem(wrapped_vector &range, int i)
{
return value_conv()(range.ctx, boost::ref(range.base.at(i)));
}
static void wrap(const char *range_name, const char *iter_name)
{
class_<wrapped_vector>(range_name, no_init)
.def("__iter__", iter)
.def("__repr__", repr)
.def("__len__", len)
.def("__getitem__", getitem);
iterator_wrapper<iterator_t, P, value_conv>().wrap(iter_name);
}
typedef iterator_wrapper<iterator_t, P, value_conv> iter_wrap;
};
#define WRAP_VECTOR(t, conv) vector_wrapper<t, return_value_policy<return_by_value>, conv>().wrap(#t, #t "Iterator")
/*
Wrapper for a pair, allows accessing either using C++-style members (.first and
.second) or as a Python iterable and indexable object
*/
*/
template <typename T1, typename T2> struct pair_wrapper
{
typedef std::pair<T1, T2> T;