Convert code to use pybind11
diff --git a/libtrellis/CMakeLists.txt b/libtrellis/CMakeLists.txt
index 17fa0c8..d838d44 100644
--- a/libtrellis/CMakeLists.txt
+++ b/libtrellis/CMakeLists.txt
@@ -57,54 +57,7 @@
 
 find_package(Boost REQUIRED COMPONENTS ${boost_libs})
 
-if (BUILD_PYTHON)
-    # Find Boost::Python of a suitable version in a cross-platform way
-    # Some distributions (Arch) call it libboost_python3, others such as Ubuntu
-    # call it libboost_python35. In the latter case we must consider all minor versions
-    # Original source: https://github.com/BVLC/caffe/blob/master/cmake/Dependencies.cmake#L148
-    set(version ${PYTHONLIBS_VERSION_STRING})
-
-    STRING(REGEX REPLACE "[^0-9]" "" boost_py_version "${version}")
-    find_package(Boost QUIET COMPONENTS "python-py${boost_py_version}" ${boost_libs})
-    set(Boost_PYTHON_FOUND ${Boost_PYTHON-PY${boost_py_version}_FOUND})
-
-    while (NOT "${version}" STREQUAL "" AND NOT Boost_PYTHON_FOUND)
-        STRING(REGEX REPLACE "([0-9.]+).[0-9]+" "\\1" version "${version}")
-
-        STRING(REGEX REPLACE "[^0-9]" "" boost_py_version "${version}")
-        find_package(Boost QUIET COMPONENTS "python-py${boost_py_version}" ${boost_libs})
-        set(Boost_PYTHON_FOUND ${Boost_PYTHON-PY${boost_py_version}_FOUND})
-
-        STRING(REGEX MATCHALL "([0-9.]+).[0-9]+" has_more_version "${version}")
-        if ("${has_more_version}" STREQUAL "")
-            break()
-        endif ()
-    endwhile ()
-
-    if (NOT Boost_PYTHON_FOUND)
-        foreach (PyVer 3 36 37 38 39 310)
-            find_package(Boost QUIET COMPONENTS python${PyVer} ${boost_libs})
-            if ("${Boost_LIBRARIES}" MATCHES ".*(python|PYTHON).*" )
-                set(Boost_PYTHON_FOUND TRUE)
-                break()
-            endif ()
-        endforeach ()
-    endif ()
-
-    if (NOT Boost_PYTHON_FOUND)
-        STRING(REGEX REPLACE "([0-9]+\\.[0-9]+).*" "\\1" gentoo_version "${PYTHONLIBS_VERSION_STRING}")
-        find_package(Boost QUIET COMPONENTS python-${gentoo_version} ${boost_libs})
-        if ("${Boost_LIBRARIES}" MATCHES ".*(python|PYTHON).*" )
-            set(Boost_PYTHON_FOUND TRUE)
-        endif ()
-    endif ()
-
-    if (NOT Boost_PYTHON_FOUND )
-        message( FATAL_ERROR "No version of Boost::Python 3.x could be found.")
-    endif ()
-endif()
-
-include_directories(include/ ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
+include_directories(include/ ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS} 3rdparty/pybind11/include)
 
 aux_source_directory(include/ INCLUDE_FILES)
 aux_source_directory(src/ SOURCE_FILES)
diff --git a/libtrellis/src/PyTrellis.cpp b/libtrellis/src/PyTrellis.cpp
index 3ea2f7d..fa003fd 100644
--- a/libtrellis/src/PyTrellis.cpp
+++ b/libtrellis/src/PyTrellis.cpp
@@ -14,70 +14,81 @@
 
 #ifdef INCLUDE_PYTHON
 
-#include <boost/python.hpp>
+#include <pybind11/pybind11.h>
+#include <pybind11/operators.h>
+#include <pybind11/stl_bind.h>
 
-#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
-#include <boost/python/suite/indexing/map_indexing_suite.hpp>
-#include <boost/python/exception_translator.hpp>
-#include "set_indexing_suite.h"
-
-using namespace boost::python;
+using namespace pybind11;
 using namespace Trellis;
+using namespace DDChipDb;
 
-void translate_bspe(const BitstreamParseError &e)
-{
-    // Use the Python 'C' API to set up an exception object
-    PyErr_SetString(PyExc_ValueError, e.what());
-}
+namespace py = pybind11;
 
-void translate_dbce(const DatabaseConflictError &e)
-{
-    // Use the Python 'C' API to set up an exception object
-    PyErr_SetString(PyExc_ValueError, e.what());
-}
+    typedef pair<int, int> IntPair;
+    typedef pair<string, bool> StringBoolPair;
+    typedef pair<RoutingId, ident_t> BelPin;
+    typedef pair<RoutingId, PortDirection> BelWireDir;
 
+    // Common Types
+    PYBIND11_MAKE_OPAQUE(IntPair)
+    PYBIND11_MAKE_OPAQUE(LocationData)
+    PYBIND11_MAKE_OPAQUE(checksum_t)
+    PYBIND11_MAKE_OPAQUE(map<checksum_t, LocationData>)
+    PYBIND11_MAKE_OPAQUE(Location)
+    PYBIND11_MAKE_OPAQUE(std::set<RelId>)
 
-BOOST_PYTHON_MODULE (pytrellis)
+PYBIND11_MODULE (pytrellis, m)
 {
     // Common Types
-    class_<vector<string>>("StringVector")
-            .def(vector_indexing_suite<vector<string>>());
+    py::bind_vector<vector<string>>(m, "StringVector");
 
-    class_<vector<uint8_t>>("ByteVector")
-            .def(vector_indexing_suite<vector<uint8_t>>());
+    py::bind_vector<vector<uint8_t>>(m, "ByteVector");
 
-    class_<vector<bool>>("BoolVector")
-            .def(vector_indexing_suite<vector<bool>>());
+    py::bind_vector<vector<bool>>(m, "BoolVector");
 
-    class_<std::pair<int, int> >("IntPair")
-            .def_readwrite("first", &std::pair<int, int>::first)
-            .def_readwrite("second", &std::pair<int, int>::second);
+    class_<IntPair>(m, "IntPair")
+            .def(init<IntPair>())
+            .def_readonly("first", &std::pair<int, int>::first)
+            .def_readonly("second", &std::pair<int, int>::second);
+
+
+    m.def("make_IntPair", [](int first, int second) {
+        return std::make_pair(first, second);
+    });
 
     // From Bitstream.cpp
-    register_exception_translator<BitstreamParseError>(&translate_bspe);
-    class_<Bitstream>("Bitstream", no_init)
-            .def("read_bit", &Bitstream::read_bit_py)
-            .staticmethod("read_bit")
-            .def("serialise_chip", &Bitstream::serialise_chip_py)
-            .staticmethod("serialise_chip")
-            .def("serialise_chip_delta", &Bitstream::serialise_chip_delta_py)
-            .staticmethod("serialise_chip_delta")
+    py::register_exception_translator([](std::exception_ptr p) {
+        try {
+            if (p)
+                std::rethrow_exception(p);
+        } catch (const BitstreamParseError &e) {
+            PyErr_SetString(PyExc_ValueError, e.what());
+        } catch (const DatabaseConflictError &e) {
+            PyErr_SetString(PyExc_ValueError, e.what());
+        }
+    });
+
+    class_<Bitstream>(m, "Bitstream")
+            .def_static("read_bit", &Bitstream::read_bit_py)
+            .def_static("serialise_chip", &Bitstream::serialise_chip_py)
+            .def_static("serialise_chip_delta", &Bitstream::serialise_chip_delta_py)
             .def("write_bit", &Bitstream::write_bit_py)
             .def_readwrite("metadata", &Bitstream::metadata)
             .def_readwrite("data", &Bitstream::data)
         .def("deserialise_chip", static_cast<Chip (Bitstream::*)()>(&Bitstream::deserialise_chip));
 
-    class_<DeviceLocator>("DeviceLocator")
+    class_<DeviceLocator>(m, "DeviceLocator")
             .def_readwrite("family", &DeviceLocator::family)
             .def_readwrite("device", &DeviceLocator::device);
 
-    class_<TileLocator>("TileLocator", init<string, string, string>())
+    class_<TileLocator>(m, "TileLocator")
+            .def(init<string, string, string>())
             .def_readwrite("family", &TileLocator::family)
             .def_readwrite("device", &TileLocator::device)
             .def_readwrite("tiletype", &TileLocator::tiletype);
 
     // From Chip.cpp
-    class_<ChipInfo>("ChipInfo")
+    class_<ChipInfo>(m, "ChipInfo")
             .def_readwrite("name", &ChipInfo::name)
             .def_readwrite("family", &ChipInfo::family)
             .def_readwrite("idcode", &ChipInfo::idcode)
@@ -89,13 +100,11 @@
             .def_readonly("max_col", &ChipInfo::max_col)
             .def_readonly("col_bias", &ChipInfo::col_bias);
 
-    class_<map<string, shared_ptr<Tile>>>("TileMap")
-            .def(map_indexing_suite<map<string, shared_ptr<Tile>>, true>());
+    py::bind_map<map<string, shared_ptr<Tile>>>(m, "TileMap");
 
-    class_<vector<shared_ptr<Tile>>>("TileVector")
-            .def(vector_indexing_suite<vector<shared_ptr<Tile>>, true>());
+    py::bind_vector<vector<shared_ptr<Tile>>>(m, "TileVector");
 
-    class_<GlobalRegion>("GlobalRegion")
+    class_<GlobalRegion>(m, "GlobalRegion")
             .def_readwrite("name", &GlobalRegion::name)
             .def_readwrite("x0", &GlobalRegion::x0)
             .def_readwrite("y0", &GlobalRegion::y0)
@@ -103,10 +112,9 @@
             .def_readwrite("y1", &GlobalRegion::y1)
             .def("matches", &GlobalRegion::matches);
 
-    class_<vector<GlobalRegion>>("GlobalRegionVector")
-            .def(vector_indexing_suite<vector<GlobalRegion>>());
+    py::bind_vector<vector<GlobalRegion>>(m, "GlobalRegionVector");
 
-    class_<TapSegment>("TapSegment")
+    class_<TapSegment>(m, "TapSegment")
             .def_readwrite("tap_col", &TapSegment::tap_col)
             .def_readwrite("lx0", &TapSegment::lx0)
             .def_readwrite("lx1", &TapSegment::lx1)
@@ -115,58 +123,52 @@
             .def("matches_left", &TapSegment::matches_left)
             .def("matches_right", &TapSegment::matches_right);
 
-    enum_<TapDriver::TapDir>("TapDir")
+    enum_<TapDriver::TapDir>(m, "TapDir")
             .value("LEFT", TapDriver::LEFT)
             .value("RIGHT", TapDriver::RIGHT);
 
-    class_<TapDriver>("TapDriver")
+    class_<TapDriver>(m, "TapDriver")
             .def_readwrite("col", &TapDriver::col)
             .def_readwrite("dir", &TapDriver::dir);
 
-    class_<vector<TapSegment>>("TapSegmentVector")
-            .def(vector_indexing_suite<vector<TapSegment>>());
+    py::bind_vector<vector<TapSegment>>(m, "TapSegmentVector");
 
-    class_<Ecp5GlobalsInfo>("Ecp5GlobalsInfo")
+    class_<Ecp5GlobalsInfo>(m, "Ecp5GlobalsInfo")
             .def_readwrite("quadrants", &Ecp5GlobalsInfo::quadrants)
             .def_readwrite("tapsegs", &Ecp5GlobalsInfo::tapsegs)
             .def("get_quadrant", &Ecp5GlobalsInfo::get_quadrant)
             .def("get_tap_driver", &Ecp5GlobalsInfo::get_tap_driver)
             .def("get_spine_driver", &Ecp5GlobalsInfo::get_spine_driver);
 
-    class_<LeftRightConn>("LeftRightConn")
+    class_<LeftRightConn>(m, "LeftRightConn")
             .def_readwrite("name", &LeftRightConn::name)
             .def_readwrite("row", &LeftRightConn::row)
             .def_readwrite("row_span", &LeftRightConn::row_span);
 
-    class_<MissingDccs>("MissingDccs")
+    class_<MissingDccs>(m, "MissingDccs")
             .def_readwrite("row", &MissingDccs::row)
             .def_readwrite("missing", &MissingDccs::missing);
 
-    class_<vector<LeftRightConn>>("LeftRightConnVector")
-            .def(vector_indexing_suite<vector<LeftRightConn>>());
+    py::bind_vector<vector<LeftRightConn>>(m, "LeftRightConnVector");
 
-    class_<vector<vector<int>>>("UpDownConnVector")
-            .def(vector_indexing_suite<vector<vector<int>>>());
+    py::bind_vector<vector<vector<int>>>(m, "UpDownConnVector");
 
-    class_<vector<vector<std::pair<int, int>>>>("BranchSpanVector")
-            .def(vector_indexing_suite<vector<vector<std::pair<int, int>>>>());
+    py::bind_vector<vector<vector<std::pair<int, int>>>>(m, "BranchSpanVector");
 
-    class_<vector<MissingDccs>>("MissingDccsVector")
-            .def(vector_indexing_suite<vector<MissingDccs>>());
+    py::bind_vector<vector<MissingDccs>>(m, "MissingDccsVector");
 
-    class_<vector<int>>("IntVector")
-            .def(vector_indexing_suite<vector<int>>());
+    py::bind_vector<vector<int>>(m, "IntVector");
 
-    class_<vector<std::pair<int, int>>>("IntPairVector")
-            .def(vector_indexing_suite<vector<std::pair<int, int>>>());
+    py::bind_vector<vector<std::pair<int, int>>>(m, "IntPairVector");
 
-    class_<MachXO2GlobalsInfo>("MachXO2GlobalsInfo")
+    class_<MachXO2GlobalsInfo>(m, "MachXO2GlobalsInfo")
             .def_readwrite("lr_conns", &MachXO2GlobalsInfo::lr_conns)
             .def_readwrite("ud_conns", &MachXO2GlobalsInfo::ud_conns)
             .def_readwrite("branch_spans", &MachXO2GlobalsInfo::branch_spans)
             .def_readwrite("missing_dccs", &MachXO2GlobalsInfo::missing_dccs);
 
-    class_<Chip>("Chip", init<string>())
+    class_<Chip>(m, "Chip")
+            .def(init<string>())
             .def(init<uint32_t>())
             .def(init<const ChipInfo &>())
             .def("get_tile_by_name", &Chip::get_tile_by_name)
@@ -187,16 +189,15 @@
             .def_readwrite("global_data_machxo2", &Chip::global_data_machxo2)
             .def(self - self);
 
-    class_<ChipDelta>("ChipDelta")
-            .def(map_indexing_suite<ChipDelta>());
+    py::bind_map<ChipDelta>(m, "ChipDelta");
 
     // From CRAM.cpp
-    class_<ChangedBit>("ChangedBit")
+    class_<ChangedBit>(m, "ChangedBit")
             .def_readonly("frame", &ChangedBit::frame)
             .def_readonly("bit", &ChangedBit::bit)
             .def_readonly("delta", &ChangedBit::delta);
 
-    class_<CRAMView>("CRAMView", no_init)
+    class_<CRAMView>(m, "CRAMView")
             .def("bit", &CRAMView::get_bit)
             .def("set_bit", &CRAMView::set_bit)
             .def("bits", &CRAMView::bits)
@@ -204,28 +205,27 @@
             .def("clear", &CRAMView::clear)
             .def(self - self);
 
-    class_<CRAM>("CRAM", init<int, int>())
+    class_<CRAM>(m, "CRAM")
+            .def(init<int, int>())
             .def("bit", &CRAM::get_bit)
             .def("set_bit", &CRAM::set_bit)
             .def("bits", &CRAM::bits)
             .def("frames", &CRAM::frames)
             .def("make_view", &CRAM::make_view);
 
-    class_<CRAMDelta>("CRAMDelta")
-            .def(vector_indexing_suite<CRAMDelta>());
+    py::bind_vector<CRAMDelta>(m, "CRAMDelta");
 
     // From Tile.cpp
-    def("get_row_col_pair_from_chipsize", get_row_col_pair_from_chipsize);
+    m.def("get_row_col_pair_from_chipsize", get_row_col_pair_from_chipsize);
 
-    class_<vector<SiteInfo>>("SiteInfoVector")
-            .def(vector_indexing_suite<vector<SiteInfo>>());
+    py::bind_vector<vector<SiteInfo>>(m, "SiteInfoVector");
 
-    class_<SiteInfo>("SiteInfo")
+    class_<SiteInfo>(m, "SiteInfo")
             .def_readonly("type", &SiteInfo::type)
             .def_readonly("row", &SiteInfo::row)
             .def_readonly("col", &SiteInfo::col);
 
-    class_<TileInfo>("TileInfo")
+    class_<TileInfo>(m, "TileInfo")
             .def_readonly("name", &TileInfo::name)
             .def_readonly("type", &TileInfo::type)
             .def_readonly("num_frames", &TileInfo::num_frames)
@@ -235,7 +235,7 @@
             .def_readonly("sites", &TileInfo::sites)
             .def("get_row_col", &TileInfo::get_row_col);
 
-    class_<Tile, shared_ptr<Tile>>("Tile", no_init)
+    class_<Tile, shared_ptr<Tile>>(m, "Tile")
             .def_readonly("info", &Tile::info)
             .def_readwrite("cram", &Tile::cram)
             .def_readwrite("known_bits", &Tile::known_bits)
@@ -244,27 +244,24 @@
             .def("read_config", &Tile::read_config);
 
     // From Database.cpp
-    def("load_database", load_database);
-    def("find_device_by_name", find_device_by_name);
-    def("find_device_by_idcode", find_device_by_idcode);
-    def("get_chip_info", get_chip_info);
-    def("get_device_tilegrid", get_device_tilegrid);
-    def("get_tile_bitdata", get_tile_bitdata);
+    m.def("load_database", load_database);
+    m.def("find_device_by_name", find_device_by_name);
+    m.def("find_device_by_idcode", find_device_by_idcode);
+    m.def("get_chip_info", get_chip_info);
+    m.def("get_device_tilegrid", get_device_tilegrid);
+    m.def("get_tile_bitdata", get_tile_bitdata);
 
     // From BitDatabase.cpp
-    register_exception_translator<DatabaseConflictError>(&translate_dbce);
-    class_<ConfigBit>("ConfigBit")
+    class_<ConfigBit>(m, "ConfigBit")
             .def_readwrite("frame", &ConfigBit::frame)
             .def_readwrite("bit", &ConfigBit::bit)
             .def_readwrite("inv", &ConfigBit::inv);
 
-    def("cbit_from_str", cbit_from_str);
-    class_<vector<ConfigBit>>("ConfigBitVector")
-            .def(vector_indexing_suite<vector<ConfigBit>>());
-    class_<set<ConfigBit>>("ConfigBitSet")
-            .def(bond::python::set_indexing_suite<set<ConfigBit>, true>());
-
-    class_<BitGroup>("BitGroup")
+    m.def("cbit_from_str", cbit_from_str);
+    py::bind_vector<vector<ConfigBit>>(m, "ConfigBitVector");
+    class_<std::set<ConfigBit>>(m, "ConfigBitSet");
+ 
+    class_<BitGroup>(m, "BitGroup")
             .def(init<const CRAMDelta &>())
             .def_readwrite("bits", &BitGroup::bits)
             .def("match", &BitGroup::match)
@@ -272,50 +269,46 @@
             .def("set_group", &BitGroup::set_group)
             .def("clear_group", &BitGroup::clear_group);
 
-    class_<vector<BitGroup>>("BitGroupVector")
-            .def(vector_indexing_suite<vector<BitGroup>>());
+    py::bind_vector<vector<BitGroup>>(m, "BitGroupVector");
 
-    class_<ArcData>("ArcData")
+    class_<ArcData>(m, "ArcData")
             .def_readwrite("source", &ArcData::source)
             .def_readwrite("sink", &ArcData::sink)
             .def_readwrite("bits", &ArcData::bits);
 
-    class_<map<string, ArcData>>("ArcDataMap")
-            .def(map_indexing_suite<map<string, ArcData>>());
+    py::bind_map<map<string, ArcData>>(m, "ArcDataMap");
 
-    class_<MuxBits>("MuxBits")
+    class_<MuxBits>(m, "MuxBits")
             .def_readwrite("sink", &MuxBits::sink)
             .def_readwrite("arcs", &MuxBits::arcs)
             .def("get_sources", &MuxBits::get_sources)
             .def("get_driver", &MuxBits::get_driver)
             .def("set_driver", &MuxBits::set_driver);
 
-    class_<WordSettingBits>("WordSettingBits")
+    class_<WordSettingBits>(m, "WordSettingBits")
             .def_readwrite("name", &WordSettingBits::name)
             .def_readwrite("bits", &WordSettingBits::bits)
             .def_readwrite("defval", &WordSettingBits::defval)
             .def("get_value", &WordSettingBits::get_value)
             .def("set_value", &WordSettingBits::set_value);
 
-    class_<map<string, BitGroup>>("BitGroupMap")
-            .def(map_indexing_suite<map<string, BitGroup>>());
+    py::bind_map<map<string, BitGroup>>(m, "BitGroupMap");
 
-    class_<EnumSettingBits>("EnumSettingBits")
+    class_<EnumSettingBits>(m, "EnumSettingBits")
             .def_readwrite("name", &EnumSettingBits::name)
             .def_readwrite("options", &EnumSettingBits::options)
             .def("get_options", &EnumSettingBits::get_options)
-            .add_property("defval", &EnumSettingBits::get_defval, &EnumSettingBits::set_defval)
+            .def_property("defval", &EnumSettingBits::get_defval, &EnumSettingBits::set_defval)
             .def("get_value", &EnumSettingBits::get_value)
             .def("set_value", &EnumSettingBits::set_value);
 
-    class_<FixedConnection>("FixedConnection")
+    class_<FixedConnection>(m, "FixedConnection")
             .def_readwrite("source", &FixedConnection::source)
             .def_readwrite("sink", &FixedConnection::sink);
 
-    class_<vector<FixedConnection>>("FixedConnectionVector")
-            .def(vector_indexing_suite<vector<FixedConnection>>());
+    py::bind_vector<vector<FixedConnection>>(m, "FixedConnectionVector");
 
-    class_<TileBitDatabase, shared_ptr<TileBitDatabase>>("TileBitDatabase", no_init)
+    class_<TileBitDatabase, shared_ptr<TileBitDatabase>>(m, "TileBitDatabase")
             .def("config_to_tile_cram", &TileBitDatabase::config_to_tile_cram)
             .def("tile_cram_to_config", &TileBitDatabase::tile_cram_to_config)
             .def("get_sinks", &TileBitDatabase::get_sinks)
@@ -335,39 +328,32 @@
             .def("remove_setting_enum", &TileBitDatabase::remove_setting_enum)
             .def("save", &TileBitDatabase::save);
 
-    typedef pair<string, bool> StringBoolPair;
-    typedef pair<string, bool> StringBoolPair;
-    class_<StringBoolPair>("StringBoolPair")
-            .def_readwrite("first", &StringBoolPair::first)
-            .def_readwrite("second", &StringBoolPair::second);
+    class_<StringBoolPair>(m, "StringBoolPair")
+            .def_readonly("first", &StringBoolPair::first)
+            .def_readonly("second", &StringBoolPair::second);
 
-    class_<vector<StringBoolPair>>("StringBoolPairVector")
-            .def(vector_indexing_suite<vector<StringBoolPair>>());
+    py::bind_vector<vector<StringBoolPair>>(m, "StringBoolPairVector");
 
     // From TileConfig.hpp
-    class_<ConfigArc>("ConfigArc")
+    class_<ConfigArc>(m, "ConfigArc")
             .def_readwrite("source", &ConfigArc::source)
             .def_readwrite("sink", &ConfigArc::sink);
-    class_<ConfigWord>("ConfigWord")
+    class_<ConfigWord>(m, "ConfigWord")
             .def_readwrite("name", &ConfigWord::name)
             .def_readwrite("value", &ConfigWord::value);
-    class_<ConfigEnum>("ConfigEnum")
+    class_<ConfigEnum>(m, "ConfigEnum")
             .def_readwrite("name", &ConfigEnum::name)
             .def_readwrite("value", &ConfigEnum::value);
-    class_<ConfigUnknown>("ConfigUnknown")
+    class_<ConfigUnknown>(m, "ConfigUnknown")
             .def_readwrite("frame", &ConfigUnknown::frame)
             .def_readwrite("bit", &ConfigUnknown::bit);
 
-    class_<vector<ConfigArc>>("ConfigArcVector")
-            .def(vector_indexing_suite<vector<ConfigArc>>());
-    class_<vector<ConfigWord>>("ConfigWordVector")
-            .def(vector_indexing_suite<vector<ConfigWord>>());
-    class_<vector<ConfigEnum>>("ConfigEnumVector")
-            .def(vector_indexing_suite<vector<ConfigEnum>>());
-    class_<vector<ConfigUnknown>>("ConfigUnknownVector")
-            .def(vector_indexing_suite<vector<ConfigUnknown>>());
+    py::bind_vector<vector<ConfigArc>>(m, "ConfigArcVector");
+    py::bind_vector<vector<ConfigWord>>(m, "ConfigWordVector");
+    py::bind_vector<vector<ConfigEnum>>(m, "ConfigEnumVector");
+    py::bind_vector<vector<ConfigUnknown>>(m, "ConfigUnknownVector");
 
-    class_<TileConfig>("TileConfig")
+    class_<TileConfig>(m, "TileConfig")
             .def_readwrite("carcs", &TileConfig::carcs)
             .def_readwrite("cwords", &TileConfig::cwords)
             .def_readwrite("cenums", &TileConfig::cenums)
@@ -377,107 +363,93 @@
             .def("add_word", &TileConfig::add_word)
             .def("add_unknown", &TileConfig::add_unknown)
             .def("to_string", &TileConfig::to_string)
-            .def("from_string", &TileConfig::from_string)
-            .staticmethod("from_string");
+            .def_static("from_string", &TileConfig::from_string);
 
     // From ChipConfig.hpp
-    class_<map<string, TileConfig>>("TileConfigMap")
-            .def(map_indexing_suite<map<string, TileConfig>>());
-    class_<vector<uint16_t>>("Uint16Vector")
-            .def(vector_indexing_suite<vector<uint16_t>>());
-    class_<map<uint16_t, vector<uint16_t>>>("Uint16VMap")
-            .def(map_indexing_suite<map<uint16_t, vector<uint16_t>>>());
+    py::bind_map<map<string, TileConfig>>(m, "TileConfigMap");
+    py::bind_vector<vector<uint16_t>>(m, "Uint16Vector");
+    py::bind_map<map<uint16_t, vector<uint16_t>>>(m, "Uint16VMap");
 
-    class_<ChipConfig>("ChipConfig")
+    class_<ChipConfig>(m, "ChipConfig")
             .def_readwrite("chip_name", &ChipConfig::chip_name)
             .def_readwrite("metadata", &ChipConfig::metadata)
             .def_readwrite("tiles", &ChipConfig::tiles)
             .def_readwrite("tilegroups", &ChipConfig::tilegroups)
             .def_readwrite("bram_data", &ChipConfig::bram_data)
             .def("to_string", &ChipConfig::to_string)
-            .def("from_string", &ChipConfig::from_string)
-            .staticmethod("from_string")
+            .def_static("from_string", &ChipConfig::from_string)
             .def("to_chip", &ChipConfig::to_chip)
-            .def("from_chip", &ChipConfig::from_chip)
-            .staticmethod("from_chip");
+            .def_static("from_chip", &ChipConfig::from_chip);
 
     // From RoutingGraph.hpp
-    class_<Location>("Location", init<int, int>())
+    class_<Location>(m, "Location")
+            .def(init<int, int>())
             .def_readwrite("x", &Location::x)
             .def_readwrite("y", &Location::y)
             .def(self + self)
             .def(self == self)
             .def(self != self);
 
-    class_<RoutingId>("RoutingId")
+    class_<RoutingId>(m, "RoutingId")
             .def_readwrite("loc", &RoutingId::loc)
             .def_readwrite("id", &RoutingId::id)
             .def(self == self)
             .def(self != self);
 
-    class_<vector<RoutingId>>("RoutingIdVector")
-            .def(vector_indexing_suite<vector<RoutingId>>());
+    py::bind_vector<vector<RoutingId>>(m, "RoutingIdVector");
 
-    typedef pair<RoutingId, ident_t> BelPin;
-    class_<BelPin>("BelPin")
-            .def_readwrite("bel", &BelPin::first)
-            .def_readwrite("pin", &BelPin::second);
+    class_<BelPin>(m, "BelPin")
+            .def_readonly("bel", &BelPin::first)
+            .def_readonly("pin", &BelPin::second);
 
-    typedef pair<RoutingId, PortDirection> BelWireDir;
-    class_<BelWireDir>("BelWireDir")
-            .def_readwrite("wire", &BelWireDir::first)
-            .def_readwrite("dir", &BelWireDir::second);
+    class_<BelWireDir>(m, "BelWireDir")
+            .def_readonly("wire", &BelWireDir::first)
+            .def_readonly("dir", &BelWireDir::second);
 
-    enum_<PortDirection>("PortDirection")
+    enum_<PortDirection>(m, "PortDirection")
             .value("PORT_IN", PORT_IN)
             .value("PORT_OUT", PORT_OUT)
             .value("PORT_INOUT", PORT_INOUT);
 
-    class_<vector<BelPin>>("BelPinVector")
-            .def(vector_indexing_suite<vector<BelPin>>());
+    py::bind_vector<vector<BelPin>>(m, "BelPinVector");
 
-    class_<RoutingWire>("RoutingWire")
+    class_<RoutingWire>(m, "RoutingWire")
             .def_readwrite("id", &RoutingWire::id)
             .def_readwrite("uphill", &RoutingWire::uphill)
             .def_readwrite("downhill", &RoutingWire::downhill)
             .def_readwrite("belsUphill", &RoutingWire::belsUphill)
             .def_readwrite("belsDownhill", &RoutingWire::belsDownhill);
 
-    class_<RoutingArc>("RoutingArc")
+    class_<RoutingArc>(m, "RoutingArc")
             .def_readwrite("id", &RoutingArc::id)
             .def_readwrite("tiletype", &RoutingArc::tiletype)
             .def_readwrite("source", &RoutingArc::source)
             .def_readwrite("sink", &RoutingArc::sink)
             .def_readwrite("configurable", &RoutingArc::configurable);
 
-    class_<map<ident_t, BelWireDir>>("RoutingPinMap")
-            .def(map_indexing_suite<map<ident_t, BelWireDir>>());
+    py::bind_map<map<ident_t, BelWireDir>>(m, "RoutingPinMap");
 
-    class_<RoutingBel>("RoutingBel")
+    class_<RoutingBel>(m, "RoutingBel")
             .def_readwrite("name", &RoutingBel::name)
             .def_readwrite("type", &RoutingBel::type)
             .def_readwrite("pins", &RoutingBel::pins)
             .def_readwrite("z", &RoutingBel::z);
 
-    class_<map<ident_t, RoutingWire>>("RoutingWireMap")
-            .def(map_indexing_suite<map<ident_t, RoutingWire>>());
+    py::bind_map<map<ident_t, RoutingWire>>(m, "RoutingWireMap");
 
-    class_<map<ident_t, RoutingArc>>("RoutingArcMap")
-            .def(map_indexing_suite<map<ident_t, RoutingArc>>());
+    py::bind_map<map<ident_t, RoutingArc>>(m, "RoutingArcMap");
 
-    class_<map<ident_t, RoutingBel>>("RoutingBelMap")
-            .def(map_indexing_suite<map<ident_t, RoutingBel>>());
+    py::bind_map<map<ident_t, RoutingBel>>(m, "RoutingBelMap");
 
-    class_<RoutingTileLoc>("RoutingTileLoc")
+    class_<RoutingTileLoc>(m, "RoutingTileLoc")
             .def_readwrite("loc", &RoutingTileLoc::loc)
             .def_readwrite("wires", &RoutingTileLoc::wires)
             .def_readwrite("arcs", &RoutingTileLoc::arcs)
             .def_readwrite("bels", &RoutingTileLoc::bels);
 
-    class_<map<Location, RoutingTileLoc>>("RoutingTileMap")
-            .def(map_indexing_suite<map<Location, RoutingTileLoc>>());
+    py::bind_map<map<Location, RoutingTileLoc>>(m, "RoutingTileMap");
 
-    class_<RoutingGraph, shared_ptr<RoutingGraph>>("RoutingGraph", no_init)
+    class_<RoutingGraph, shared_ptr<RoutingGraph>>(m, "RoutingGraph")
             .def_readonly("chip_name", &RoutingGraph::chip_name)
             .def_readonly("chip_family", &RoutingGraph::chip_family)
             .def_readonly("max_row", &RoutingGraph::max_row)
@@ -491,94 +463,88 @@
             .def("add_wire", &RoutingGraph::add_wire);
 
     // DedupChipdb
-    using namespace DDChipDb;
-    class_<RelId>("RelId")
+    class_<RelId>(m, "RelId")
             .def_readwrite("rel", &RelId::rel)
             .def_readwrite("id", &RelId::id)
             .def(self == self)
             .def(self != self);
 
-    class_<BelPort>("BelPort")
+    class_<BelPort>(m, "BelPort")
             .def_readwrite("bel", &BelPort::bel)
             .def_readwrite("pin", &BelPort::pin);
-    class_<BelWire>("BelWire")
+    class_<BelWire>(m, "BelWire")
             .def_readwrite("wire", &BelWire::wire)
             .def_readwrite("pin", &BelWire::pin)
             .def_readwrite("dir", &BelWire::dir);
 
-    class_<vector<BelPort>>("BelPortVector")
-            .def(vector_indexing_suite<vector<BelPort>>());
-    class_<vector<BelWire>>("BelWireVector")
-            .def(vector_indexing_suite<vector<BelWire>>());
-    class_<vector<RelId>>("RelIdVector")
-            .def(vector_indexing_suite<vector<RelId>>());
-    class_<set<RelId>>("RelIdSet")
-            .def(bond::python::set_indexing_suite<set<RelId>,true>());
+    py::bind_vector<vector<BelPort>>(m, "BelPortVector");
+    py::bind_vector<vector<BelWire>>(m, "BelWireVector");
+    py::bind_vector<vector<RelId>>(m, "RelIdVector");
+    class_<std::set<RelId>>(m, "RelIdSet")
+        .def("__len__", [](const std::set<RelId> &v) { return v.size(); })
+        .def("__iter__", [](std::set<RelId> &v) {
+            return py::make_iterator(v.begin(), v.end());
+        }, py::keep_alive<0, 1>()); /* Keep vector alive while iterator is used */
 
-    enum_<ArcClass>("ArcClass")
+    enum_<ArcClass>(m, "ArcClass")
             .value("ARC_STANDARD", ARC_STANDARD)
             .value("ARC_FIXED", ARC_FIXED);
-    class_<DdArcData>("DdArcData")
+    class_<DdArcData>(m, "DdArcData")
             .def_readwrite("srcWire", &DdArcData::srcWire)
             .def_readwrite("sinkWire", &DdArcData::sinkWire)
             .def_readwrite("cls", &DdArcData::cls)
             .def_readwrite("delay", &DdArcData::delay)
             .def_readwrite("tiletype", &DdArcData::tiletype);
 
-    class_<WireData>("WireData")
+    class_<WireData>(m, "WireData")
             .def_readwrite("name", &WireData::name)
             .def_readwrite("arcsDownhill", &WireData::arcsDownhill)
             .def_readwrite("arcsUphill", &WireData::arcsUphill)
             .def_readwrite("belPins", &WireData::belPins);
 
-    class_<BelData>("BelData")
+    class_<BelData>(m, "BelData")
             .def_readwrite("name", &BelData::name)
             .def_readwrite("type", &BelData::type)
             .def_readwrite("z", &BelData::z)
             .def_readwrite("wires", &BelData::wires);
 
-    class_<vector<BelData>>("BelDataVector")
-            .def(vector_indexing_suite<vector<BelData>>());
-    class_<vector<WireData>>("WireDataVector")
-            .def(vector_indexing_suite<vector<WireData>>());
-    class_<vector<DdArcData>>("DdArcDataVector")
-            .def(vector_indexing_suite<vector<DdArcData>>());
+    py::bind_vector<vector<BelData>>(m, "BelDataVector");
+    py::bind_vector<vector<WireData>>(m, "WireDataVector");
+    py::bind_vector<vector<DdArcData>>(m, "DdArcDataVector");
 
-    class_<LocationData>("LocationData")
+    class_<LocationData>(m, "LocationData")
             .def_readwrite("wires", &LocationData::wires)
             .def_readwrite("arcs", &LocationData::arcs)
             .def_readwrite("bels", &LocationData::bels)
             .def("checksum", &LocationData::checksum);
 
-    class_<map<Location, checksum_t>>("LocationMap")
-            .def(map_indexing_suite<map<Location, checksum_t>>());
+    py::bind_map<map<Location, checksum_t>>(m, "LocationMap");
 
-    class_<map<checksum_t, LocationData>>("LocationTypesMap")
-            .def(map_indexing_suite<map<checksum_t, LocationData>>());
+    py::bind_map<map<checksum_t, LocationData>>(m, "LocationTypesMap");
 
-    class_<map<Location, LocationData>>("LocationMapDirect")
-            .def(map_indexing_suite<map<Location, LocationData>>());
+    py::bind_map<map<Location, LocationData>>(m, "LocationMapDirect");
 
-    class_<checksum_t>("checksum_t")
-            .def_readwrite("first", &checksum_t::first)
-            .def_readwrite("second", &checksum_t::second)
+    class_<checksum_t>(m, "checksum_t")
+            .def_readonly("first", &checksum_t::first)
+            .def_readonly("second", &checksum_t::second)
+            .def("key", [](const checksum_t &v) { return v; })
             .def(self == self);
 
-    class_<DedupChipdb, shared_ptr<DedupChipdb>>("DedupChipdb")
+    class_<DedupChipdb, shared_ptr<DedupChipdb>>(m, "DedupChipdb")
             .def_readwrite("locationTypes", &DedupChipdb::locationTypes)
             .def_readwrite("typeAtLocation", &DedupChipdb::typeAtLocation)
             .def("get_cs_data", &DedupChipdb::get_cs_data)
             .def("ident", &DedupChipdb::ident)
             .def("to_str", &DedupChipdb::to_str);
 
-    def("make_dedup_chipdb", make_dedup_chipdb);
+    m.def("make_dedup_chipdb", make_dedup_chipdb);
 
-    class_<OptimizedChipdb, shared_ptr<OptimizedChipdb>>("OptimizedChipdb")
+    class_<OptimizedChipdb, shared_ptr<OptimizedChipdb>>(m, "OptimizedChipdb")
             .def_readwrite("tiles", &OptimizedChipdb::tiles)
             .def("ident", &OptimizedChipdb::ident)
             .def("to_str", &OptimizedChipdb::to_str);
 
-    def("make_optimized_chipdb", make_optimized_chipdb);
+    m.def("make_optimized_chipdb", make_optimized_chipdb);
 
 }
 
diff --git a/util/common/tiles.py b/util/common/tiles.py
index d4c2043..e64c9a1 100644
--- a/util/common/tiles.py
+++ b/util/common/tiles.py
@@ -6,10 +6,8 @@
     """
     Extract the tile position as a (row, column) tuple from its name
     """
-    size = pytrellis.IntPair()
-    size.first = chip_size[0]
-    size.second = chip_size[1]
-
+    pair = pytrellis.make_IntPair(chip_size[0],chip_size[1])
+    size = pytrellis.IntPair(pair)
     pos = pytrellis.get_row_col_pair_from_chipsize(tile, size, bias)
     return int(pos.first), int(pos.second)