From 49f178ed94b5fad00d25dbd12adea0bf4732f803 Mon Sep 17 00:00:00 2001 From: gatecat Date: Fri, 8 Apr 2022 13:42:54 +0100 Subject: Split up common into kernel,place,route Signed-off-by: gatecat --- common/pycontainers.h | 575 -------------------------------------------------- 1 file changed, 575 deletions(-) delete mode 100644 common/pycontainers.h (limited to 'common/pycontainers.h') diff --git a/common/pycontainers.h b/common/pycontainers.h deleted file mode 100644 index ff49c34c..00000000 --- a/common/pycontainers.h +++ /dev/null @@ -1,575 +0,0 @@ -/* - * nextpnr -- Next Generation Place and Route - * - * Copyright (C) 2018 Claire Xenia Wolf - * Copyright (C) 2018 gatecat - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#ifndef COMMON_PYCONTAINERS_H -#define COMMON_PYCONTAINERS_H - -#include -#include -#include -#include -#include -#include "nextpnr.h" -#include "pywrappers.h" - -NEXTPNR_NAMESPACE_BEGIN - -namespace py = pybind11; - -inline void KeyError() -{ - PyErr_SetString(PyExc_KeyError, "Key not found"); - throw py::error_already_set(); -} - -/* -A wrapper for a Pythonised nextpnr Iterator. The actual class wrapped is a -pair containing (current, end), wrapped in a ContextualWrapper - -*/ - -template > -struct iterator_wrapper -{ - typedef decltype(*(std::declval())) value_t; - - typedef PythonConversion::ContextualWrapper> wrapped_iter_t; - using return_t = typename value_conv::ret_type; - - static return_t next(wrapped_iter_t &iter) - { - if (iter.base.first != iter.base.second) { - return_t val = value_conv()(iter.ctx, *iter.base.first); - ++iter.base.first; - return val; - } else { - PyErr_SetString(PyExc_StopIteration, "End of range reached"); - throw py::error_already_set(); - } - } - - static void wrap(py::module &m, const char *python_name) - { - py::class_(m, python_name).def("__next__", next, P); - } -}; - -/* -A pair that doesn't automatically become a tuple -*/ -template struct iter_pair -{ - iter_pair(){}; - iter_pair(const Ta &first, const Tb &second) : first(first), second(second){}; - Ta first; - Tb second; -}; - -/* -A wrapper for a nextpnr Range. Ranges should have two functions, begin() -and end() which return iterator-like objects supporting ++, * and != -Full STL iterator semantics are not required, unlike the standard Boost wrappers -*/ - -template > -struct range_wrapper -{ - typedef decltype(std::declval().begin()) iterator_t; - typedef decltype(*(std::declval())) value_t; - typedef typename PythonConversion::ContextualWrapper wrapped_range; - typedef typename PythonConversion::ContextualWrapper> wrapped_pair; - static wrapped_pair iter(wrapped_range &range) - { - return wrapped_pair(range.ctx, std::make_pair(range.base.begin(), range.base.end())); - } - - static std::string repr(wrapped_range &range) - { - PythonConversion::string_converter 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 void wrap(py::module &m, const char *range_name, const char *iter_name) - { - py::class_(m, range_name).def("__iter__", iter).def("__repr__", repr); - iterator_wrapper().wrap(m, iter_name); - } - - typedef iterator_wrapper iter_wrap; -}; - -#define WRAP_RANGE(m, t, conv) \ - range_wrapper().wrap(m, #t "Range", #t "Iterator") - -/* -A wrapper for a vector or similar structure. With support for conversion -*/ - -template > -struct vector_wrapper -{ - typedef decltype(std::declval().begin()) iterator_t; - typedef decltype(*(std::declval())) value_t; - typedef typename PythonConversion::ContextualWrapper wrapped_vector; - typedef typename PythonConversion::ContextualWrapper> 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 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(py::module &m, const char *range_name, const char *iter_name) - { - py::class_(m, range_name) - .def("__iter__", iter) - .def("__repr__", repr) - .def("__len__", len) - .def("__getitem__", getitem); - - iterator_wrapper().wrap(m, iter_name); - } - - typedef iterator_wrapper iter_wrap; -}; - -#define WRAP_VECTOR(m, t, conv) vector_wrapper().wrap(m, #t, #t "Iterator") - -template > -struct indexed_store_wrapper -{ - typedef decltype(std::declval().begin()) iterator_t; - typedef decltype(*(std::declval())) value_t; - typedef typename PythonConversion::ContextualWrapper wrapped_vector; - typedef typename PythonConversion::ContextualWrapper> 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 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.capacity(); } - - static py::object getitem(wrapped_vector &range, int i) - { - store_index> idx(i); - if (!range.base.count(idx)) - throw py::none(); - return py::cast(value_conv()(range.ctx, boost::ref(range.base.at(idx)))); - } - - static void wrap(py::module &m, const char *range_name, const char *iter_name) - { - py::class_(m, range_name) - .def("__iter__", iter) - .def("__repr__", repr) - .def("__len__", len) - .def("__getitem__", getitem); - - iterator_wrapper().wrap(m, iter_name); - } - - typedef iterator_wrapper iter_wrap; -}; - -#define WRAP_INDEXSTORE(m, t, conv) \ - indexed_store_wrapper().wrap(m, #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 struct pair_wrapper -{ - typedef std::pair T; - - struct pair_iterator_wrapper - { - static py::object next(iter_pair &iter) - { - if (iter.second == 0) { - iter.second++; - return py::cast(iter.first.first); - } else if (iter.second == 1) { - iter.second++; - return py::cast(iter.first.second); - } else { - PyErr_SetString(PyExc_StopIteration, "End of range reached"); - throw py::error_already_set(); - } - } - - static void wrap(py::module &m, const char *python_name) - { - py::class_>(m, python_name).def("__next__", next); - } - }; - - static py::object get(T &x, int i) - { - if ((i >= 2) || (i < 0)) - KeyError(); - return (i == 1) ? py::object(x.second) : py::object(x.first); - } - - static void set(T &x, int i, py::object val) - { - if ((i >= 2) || (i < 0)) - KeyError(); - if (i == 0) - x.first = val.cast(); - if (i == 1) - x.second = val.cast(); - } - - static int len(T &x) { return 2; } - - static iter_pair iter(T &x) { return iter_pair(boost::ref(x), 0); }; - - static void wrap(py::module &m, const char *pair_name, const char *iter_name) - { - pair_iterator_wrapper::wrap(m, iter_name); - py::class_(m, pair_name) - .def("__iter__", iter) - .def("__len__", len) - .def("__getitem__", get) - .def("__setitem__", set, py::keep_alive<1, 2>()) - .def_readwrite("first", &T::first) - .def_readwrite("second", &T::second); - } -}; - -/* -Special case of above for map key/values - */ -template struct map_pair_wrapper -{ - typedef std::pair T; - typedef PythonConversion::ContextualWrapper wrapped_pair; - typedef typename T::second_type V; - - struct pair_iterator_wrapper - { - static py::object next(iter_pair &iter) - { - if (iter.second == 0) { - iter.second++; - return py::cast(PythonConversion::string_converter().to_str( - iter.first.ctx, iter.first.base.first)); - } else if (iter.second == 1) { - iter.second++; - return py::cast(value_conv()(iter.first.ctx, iter.first.base.second)); - } else { - PyErr_SetString(PyExc_StopIteration, "End of range reached"); - throw py::error_already_set(); - } - } - - static void wrap(py::module &m, const char *python_name) - { - py::class_>(m, python_name).def("__next__", next); - } - }; - - static py::object get(wrapped_pair &x, int i) - { - if ((i >= 2) || (i < 0)) - KeyError(); - return (i == 1) ? py::cast(value_conv()(x.ctx, x.base.second)) - : py::cast(PythonConversion::string_converter().to_str(x.ctx, - x.base.first)); - } - - static int len(wrapped_pair &x) { return 2; } - - static iter_pair iter(wrapped_pair &x) - { - return iter_pair(boost::ref(x), 0); - }; - - static std::string first_getter(wrapped_pair &t) - { - return PythonConversion::string_converter().to_str(t.ctx, t.base.first); - } - - static typename value_conv::ret_type second_getter(wrapped_pair &t) { return value_conv()(t.ctx, t.base.second); } - - static void wrap(py::module &m, const char *pair_name, const char *iter_name) - { - pair_iterator_wrapper::wrap(m, iter_name); - py::class_(m, pair_name) - .def("__iter__", iter) - .def("__len__", len) - .def("__getitem__", get) - .def_property_readonly("first", first_getter) - .def_property_readonly("second", second_getter); - } -}; - -/* -Wrapper for a map, either an unordered_map, regular map or dict - */ - -template struct map_wrapper -{ - typedef typename std::remove_cv::type>::type K; - typedef typename T::mapped_type V; - typedef typename value_conv::ret_type wrapped_V; - typedef typename T::value_type KV; - typedef typename PythonConversion::ContextualWrapper wrapped_map; - - static wrapped_V get(wrapped_map &x, std::string const &i) - { - K k = PythonConversion::string_converter().from_str(x.ctx, i); - if (x.base.find(k) != x.base.end()) - return value_conv()(x.ctx, x.base.at(k)); - KeyError(); - - // Should be unreachable, but prevent control may reach end of non-void - throw std::runtime_error("unreachable"); - } - - static void set(wrapped_map &x, std::string const &i, V const &v) - { - x.base[PythonConversion::string_converter().from_str(x.ctx, i)] = v; - } - - static size_t len(wrapped_map &x) { return x.base.size(); } - - static void del(T const &x, std::string const &i) - { - K k = PythonConversion::string_converter().from_str(x.ctx, i); - if (x.base.find(k) != x.base.end()) - x.base.erase(k); - else - KeyError(); - } - - static bool contains(wrapped_map &x, std::string const &i) - { - K k = PythonConversion::string_converter().from_str(x.ctx, i); - return x.base.count(k); - } - - static void wrap(py::module &m, const char *map_name, const char *kv_name, const char *kv_iter_name, - const char *iter_name) - { - map_pair_wrapper::wrap(m, kv_name, kv_iter_name); - typedef range_wrapper> rw; - typename rw::iter_wrap().wrap(m, iter_name); - py::class_(m, map_name) - .def("__iter__", rw::iter) - .def("__len__", len) - .def("__contains__", contains) - .def("__getitem__", get) - .def("__setitem__", set, py::keep_alive<1, 2>()); - } -}; - -/* -Special case of above for map key/values where value is a unique_ptr - */ -template struct map_pair_wrapper_uptr -{ - typedef std::pair T; - typedef PythonConversion::ContextualWrapper wrapped_pair; - typedef typename T::second_type::element_type V; - - struct pair_iterator_wrapper - { - static py::object next(iter_pair &iter) - { - if (iter.second == 0) { - iter.second++; - return py::cast(PythonConversion::string_converter().to_str( - iter.first.ctx, iter.first.base.first)); - } else if (iter.second == 1) { - iter.second++; - return py::cast( - PythonConversion::ContextualWrapper(iter.first.ctx, *iter.first.base.second.get())); - } else { - PyErr_SetString(PyExc_StopIteration, "End of range reached"); - throw py::error_already_set(); - } - } - - static void wrap(py::module &m, const char *python_name) - { - py::class_>(m, python_name).def("__next__", next); - } - }; - - static py::object get(wrapped_pair &x, int i) - { - if ((i >= 2) || (i < 0)) - KeyError(); - return (i == 1) ? py::cast(PythonConversion::ContextualWrapper(x.ctx, *x.base.second.get())) - : py::cast(PythonConversion::string_converter().to_str(x.ctx, - x.base.first)); - } - - static int len(wrapped_pair &x) { return 2; } - - static iter_pair iter(wrapped_pair &x) - { - return iter_pair(boost::ref(x), 0); - }; - - static std::string first_getter(wrapped_pair &t) - { - return PythonConversion::string_converter().to_str(t.ctx, t.base.first); - } - - static PythonConversion::ContextualWrapper second_getter(wrapped_pair &t) - { - return PythonConversion::ContextualWrapper(t.ctx, *t.base.second.get()); - } - - static void wrap(py::module &m, const char *pair_name, const char *iter_name) - { - pair_iterator_wrapper::wrap(m, iter_name); - py::class_(m, pair_name) - .def("__iter__", iter) - .def("__len__", len) - .def("__getitem__", get) - .def_property_readonly("first", first_getter) - .def_property_readonly("second", second_getter); - } -}; - -/* -Wrapper for a map, either an unordered_map, regular map or dict - */ - -template struct map_wrapper_uptr -{ - typedef typename std::remove_cv::type>::type K; - typedef typename T::mapped_type::pointer V; - typedef typename T::mapped_type::element_type &Vr; - typedef typename T::value_type KV; - typedef typename PythonConversion::ContextualWrapper wrapped_map; - - static PythonConversion::ContextualWrapper get(wrapped_map &x, std::string const &i) - { - K k = PythonConversion::string_converter().from_str(x.ctx, i); - if (x.base.find(k) != x.base.end()) - return PythonConversion::ContextualWrapper(x.ctx, *x.base.at(k).get()); - KeyError(); - - // Should be unreachable, but prevent control may reach end of non-void - throw std::runtime_error("unreachable"); - } - - static void set(wrapped_map &x, std::string const &i, V const &v) - { - x.base[PythonConversion::string_converter().from_str(x.ctx, i)] = typename T::mapped_type(v); - } - - static size_t len(wrapped_map &x) { return x.base.size(); } - - static void del(T const &x, std::string const &i) - { - K k = PythonConversion::string_converter().from_str(x.ctx, i); - if (x.base.find(k) != x.base.end()) - x.base.erase(k); - else - KeyError(); - } - - static bool contains(wrapped_map &x, std::string const &i) - { - K k = PythonConversion::string_converter().from_str(x.ctx, i); - return x.base.count(k); - } - - static void wrap(py::module &m, const char *map_name, const char *kv_name, const char *kv_iter_name, - const char *iter_name) - { - map_pair_wrapper_uptr::wrap(m, kv_name, kv_iter_name); - typedef range_wrapper> rw; - typename rw::iter_wrap().wrap(m, iter_name); - py::class_(m, map_name) - .def("__iter__", rw::iter) - .def("__len__", len) - .def("__contains__", contains) - .def("__getitem__", get) - .def("__setitem__", set, py::keep_alive<1, 2>()); - } -}; - -#define WRAP_MAP(m, t, conv, name) \ - map_wrapper().wrap(m, #name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") -#define WRAP_MAP_UPTR(m, t, name) \ - map_wrapper_uptr().wrap(m, #name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") - -NEXTPNR_NAMESPACE_END - -#endif -- cgit v1.2.3