aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2019-04-19 17:40:55 +0100
committerGitHub <noreply@github.com>2019-04-19 17:40:55 +0100
commit5344bc3b65f4e06f983db781e9a82d30b3f1512b (patch)
tree5f794074ccc963a9dbf756558e34a8eba0d5fa26 /common
parent0be844e6a8d0a36a50815ec5331fd7480dd20db6 (diff)
parent87a24460813b9f52189323352554a1c352836ee2 (diff)
downloadnextpnr-5344bc3b65f4e06f983db781e9a82d30b3f1512b.tar.gz
nextpnr-5344bc3b65f4e06f983db781e9a82d30b3f1512b.tar.bz2
nextpnr-5344bc3b65f4e06f983db781e9a82d30b3f1512b.zip
Merge pull request #261 from YosysHQ/pygeneric
Python API for generic architecture
Diffstat (limited to 'common')
-rw-r--r--common/nextpnr.cc8
-rw-r--r--common/nextpnr.h6
-rw-r--r--common/pybindings.cc44
-rw-r--r--common/pywrappers.h111
4 files changed, 157 insertions, 12 deletions
diff --git a/common/nextpnr.cc b/common/nextpnr.cc
index 54333b15..daaadf28 100644
--- a/common/nextpnr.cc
+++ b/common/nextpnr.cc
@@ -444,5 +444,13 @@ void BaseCtx::constrainCellToRegion(IdString cell, IdString region_name)
{
cells[cell]->region = region[region_name].get();
}
+DecalXY BaseCtx::constructDecalXY(DecalId decal, float x, float y)
+{
+ DecalXY dxy;
+ dxy.decal = decal;
+ dxy.x = x;
+ dxy.y = y;
+ return dxy;
+}
NEXTPNR_NAMESPACE_END
diff --git a/common/nextpnr.h b/common/nextpnr.h
index 5967ecee..fc49300e 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -181,6 +181,9 @@ struct GraphicElement
float x1 = 0, y1 = 0, x2 = 0, y2 = 0, z = 0;
std::string text;
+ GraphicElement(){};
+ GraphicElement(type_t type, style_t style, float x1, float y1, float x2, float y2, float z)
+ : type(type), style(style), x1(x1), y1(y1), x2(x2), y2(y2), z(z){};
};
struct Loc
@@ -640,6 +643,9 @@ struct BaseCtx
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);
+
+ // Workaround for lack of wrappable constructors
+ DecalXY constructDecalXY(DecalId decal, float x, float y);
};
NEXTPNR_NAMESPACE_END
diff --git a/common/pybindings.cc b/common/pybindings.cc
index eee78b5e..60f87e27 100644
--- a/common/pybindings.cc
+++ b/common/pybindings.cc
@@ -23,8 +23,10 @@
#include "pybindings.h"
#include "arch_pybindings.h"
#include "jsonparse.h"
+#include "log.h"
#include "nextpnr.h"
+#include <boost/filesystem.hpp>
#include <fstream>
#include <memory>
#include <signal.h>
@@ -87,7 +89,26 @@ BOOST_PYTHON_MODULE(MODULE_NAME)
using namespace PythonConversion;
+ enum_<GraphicElement::type_t>("GraphicElementType")
+ .value("TYPE_NONE", GraphicElement::TYPE_NONE)
+ .value("TYPE_LINE", GraphicElement::TYPE_LINE)
+ .value("TYPE_ARROW", GraphicElement::TYPE_ARROW)
+ .value("TYPE_BOX", GraphicElement::TYPE_BOX)
+ .value("TYPE_CIRCLE", GraphicElement::TYPE_CIRCLE)
+ .value("TYPE_LABEL", GraphicElement::TYPE_LABEL)
+ .export_values();
+
+ enum_<GraphicElement::style_t>("GraphicElementStyle")
+ .value("STYLE_GRID", GraphicElement::STYLE_GRID)
+ .value("STYLE_FRAME", GraphicElement::STYLE_FRAME)
+ .value("STYLE_HIDDEN", GraphicElement::STYLE_HIDDEN)
+ .value("STYLE_INACTIVE", GraphicElement::STYLE_INACTIVE)
+ .value("STYLE_ACTIVE", GraphicElement::STYLE_ACTIVE)
+ .export_values();
+
class_<GraphicElement>("GraphicElement")
+ .def(init<GraphicElement::type_t, GraphicElement::style_t, float, float, float, float, float>(
+ (args("type"), "style", "x1", "y1", "x2", "y2", "z")))
.def_readwrite("type", &GraphicElement::type)
.def_readwrite("x1", &GraphicElement::x1)
.def_readwrite("y1", &GraphicElement::y1)
@@ -108,6 +129,12 @@ BOOST_PYTHON_MODULE(MODULE_NAME)
class_<BaseCtx, BaseCtx *, boost::noncopyable>("BaseCtx", no_init);
+ auto loc_cls = class_<Loc>("Loc")
+ .def(init<int, int, int>())
+ .def_readwrite("x", &Loc::x)
+ .def_readwrite("y", &Loc::y)
+ .def_readwrite("z", &Loc::z);
+
auto ci_cls = class_<ContextualWrapper<CellInfo &>>("CellInfo", no_init);
readwrite_wrapper<CellInfo &, decltype(&CellInfo::name), &CellInfo::name, conv_to_str<IdString>,
conv_from_str<IdString>>::def_wrap(ci_cls, "name");
@@ -208,8 +235,14 @@ void init_python(const char *executable, bool first)
PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME);
Py_SetProgramName(program);
Py_Initialize();
- if (first)
- PyImport_ImportModule(TOSTRING(MODULE_NAME));
+
+ // Add cwd to Python's search path so `import` can be used in user scripts
+ boost::filesystem::path cwd = boost::filesystem::absolute("./").normalize();
+ PyObject *sys_path = PySys_GetObject("path");
+ PyList_Insert(sys_path, 0, PyUnicode_FromString(cwd.string().c_str()));
+
+ PyImport_ImportModule(TOSTRING(MODULE_NAME));
+ PyRun_SimpleString("from " TOSTRING(MODULE_NAME) " import *");
} catch (boost::python::error_already_set const &) {
// Parse and output the exception
std::string perror_str = parse_python_exception();
@@ -235,12 +268,15 @@ void execute_python_file(const char *python_file)
fprintf(stderr, "Fatal error: file not found %s\n", python_file);
exit(1);
}
- PyRun_SimpleFile(fp, python_file);
+ int result = PyRun_SimpleFile(fp, python_file);
fclose(fp);
+ if (result == -1) {
+ log_error("Error occurred while executing Python script %s\n", python_file);
+ }
} catch (boost::python::error_already_set const &) {
// Parse and output the exception
std::string perror_str = parse_python_exception();
- std::cout << "Error in Python: " << perror_str << std::endl;
+ log_error("Error in Python: %s\n", perror_str.c_str());
}
}
diff --git a/common/pywrappers.h b/common/pywrappers.h
index 427c3623..1d970985 100644
--- a/common/pywrappers.h
+++ b/common/pywrappers.h
@@ -155,11 +155,15 @@ template <typename Class, typename FuncT, FuncT fn, typename rv_conv> struct fn_
using class_type = typename WrapIfNotContext<Class>::maybe_wrapped_t;
using conv_result_type = typename rv_conv::ret_type;
- static conv_result_type wrapped_fn(class_type &cls)
+ static object wrapped_fn(class_type &cls)
{
Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls);
- return rv_conv()(ctx, (base.*fn)());
+ try {
+ return object(rv_conv()(ctx, (base.*fn)()));
+ } catch (bad_wrap &) {
+ return object();
+ }
}
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@@ -172,11 +176,15 @@ template <typename Class, typename FuncT, FuncT fn, typename rv_conv, typename a
using conv_result_type = typename rv_conv::ret_type;
using conv_arg1_type = typename arg1_conv::arg_type;
- static conv_result_type wrapped_fn(class_type &cls, conv_arg1_type arg1)
+ static object wrapped_fn(class_type &cls, conv_arg1_type arg1)
{
Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls);
- return rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1)));
+ try {
+ return object(rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1))));
+ } catch (bad_wrap &) {
+ return object();
+ }
}
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@@ -191,11 +199,15 @@ struct fn_wrapper_2a
using conv_arg1_type = typename arg1_conv::arg_type;
using conv_arg2_type = typename arg2_conv::arg_type;
- static conv_result_type wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2)
+ static object wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2)
{
Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls);
- return rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2)));
+ try {
+ return object(rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2))));
+ } catch (bad_wrap &) {
+ return object();
+ }
}
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@@ -212,11 +224,16 @@ struct fn_wrapper_3a
using conv_arg2_type = typename arg2_conv::arg_type;
using conv_arg3_type = typename arg3_conv::arg_type;
- static conv_result_type wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3)
+ static object wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3)
{
Context *ctx = get_ctx<Class>(cls);
Class &base = get_base<Class>(cls);
- return rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3)));
+ try {
+ return object(
+ rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3))));
+ } catch (bad_wrap &) {
+ return object();
+ }
}
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
@@ -250,6 +267,11 @@ template <typename Class, typename FuncT, FuncT fn, typename arg1_conv> struct f
}
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
+
+ template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, Ta a = arg("arg1"))
+ {
+ cls_.def(name, wrapped_fn, a);
+ }
};
// Two parameters, one return
@@ -267,6 +289,11 @@ 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); }
+
+ template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, const Ta &a)
+ {
+ cls_.def(name, wrapped_fn, a);
+ }
};
// Three parameters, no return
@@ -286,6 +313,39 @@ struct fn_wrapper_3a_v
}
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
+
+ template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, const Ta &a)
+ {
+ cls_.def(name, wrapped_fn, a);
+ }
+};
+
+// Four parameters, no return
+template <typename Class, typename FuncT, FuncT fn, typename arg1_conv, typename arg2_conv, typename arg3_conv,
+ typename arg4_conv>
+struct fn_wrapper_4a_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;
+
+ static void wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3,
+ conv_arg4_type arg4)
+ {
+ 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));
+ }
+
+ template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
+
+ template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, const Ta &a)
+ {
+ cls_.def(name, wrapped_fn, a);
+ }
};
// Five parameters, no return
@@ -310,6 +370,41 @@ struct fn_wrapper_5a_v
}
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
+
+ template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, const Ta &a)
+ {
+ cls_.def(name, wrapped_fn, a);
+ }
+};
+
+// Six 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, typename arg6_conv>
+struct fn_wrapper_6a_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;
+ using conv_arg6_type = typename arg6_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, conv_arg6_type arg6)
+ {
+ 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), arg6_conv()(ctx, arg6));
+ }
+
+ template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
+
+ template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, const Ta &a)
+ {
+ cls_.def(name, wrapped_fn, a);
+ }
};
// Wrapped getter