summaryrefslogtreecommitdiffstats
path: root/pywrap
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2016-02-23 07:20:33 +0100
committerSuren A. Chilingaryan <csa@suren.me>2016-02-23 07:20:33 +0100
commita962c90543955bac98308c1b0d909048070d900a (patch)
tree70b06851187e6bf8cfd8ee28931bdea25ea92ac7 /pywrap
parent055279e09c3db9429e02874ec9620b9af357c80a (diff)
parent52eb7f4fb76ddf99dedf44332aae7af4df76ab36 (diff)
downloadpcitool-a962c90543955bac98308c1b0d909048070d900a.tar.gz
pcitool-a962c90543955bac98308c1b0d909048070d900a.tar.bz2
pcitool-a962c90543955bac98308c1b0d909048070d900a.tar.xz
pcitool-a962c90543955bac98308c1b0d909048070d900a.zip
Merge Python scripting support from Vasiliy Chernov
Diffstat (limited to 'pywrap')
-rw-r--r--pywrap/CMakeLists.txt22
-rw-r--r--pywrap/pcipywrap.c503
-rw-r--r--pywrap/pcipywrap.h68
-rw-r--r--pywrap/pcipywrap.i25
-rw-r--r--pywrap/server.py399
-rw-r--r--pywrap/test_pcipywrap.py119
6 files changed, 1136 insertions, 0 deletions
diff --git a/pywrap/CMakeLists.txt b/pywrap/CMakeLists.txt
new file mode 100644
index 0000000..1693232
--- /dev/null
+++ b/pywrap/CMakeLists.txt
@@ -0,0 +1,22 @@
+include_directories(
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/pcilib
+ ${CMAKE_BINARY_DIR}/pcilib
+ ${LIBXML2_INCLUDE_DIRS}
+ ${PYTHON_INCLUDE_DIR}
+ ${UTHASH_INCLUDE_DIRS}
+)
+
+set(HEADERS pcipywrap.h)
+
+#Creating python wrapping
+include(${SWIG_USE_FILE})
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+set(CMAKE_SWIG_FLAGS "")
+
+swig_add_module(pcipywrap python pcipywrap.i pcipywrap.c)
+swig_link_libraries(pcipywrap ${PYTHON_LIBRARIES} pcilib)
+
+#configure_file(server.py server.py)
+#configure_file(test_pcipywrap.py test_pcipywrap.py)
diff --git a/pywrap/pcipywrap.c b/pywrap/pcipywrap.c
new file mode 100644
index 0000000..bcf4561
--- /dev/null
+++ b/pywrap/pcipywrap.c
@@ -0,0 +1,503 @@
+#include "pcipywrap.h"
+
+char* full_log = NULL;
+
+/*!
+ * \brief Wraping for vsnprintf function, that saves string to char*
+ * \return saved from vsnprintf string
+ */
+char* vmake_str(const char* msg, va_list vl)
+{
+ char *buf;
+ size_t sz;
+
+ va_list vl_copy;
+ va_copy(vl_copy, vl);
+
+ sz = vsnprintf(NULL, 0, msg, vl);
+ buf = (char *)malloc(sz + 1);
+
+ if(!buf)
+ {
+ return NULL;
+ }
+
+ vsnprintf(buf, sz+1, msg, vl_copy);
+ va_end(vl_copy);
+
+ return buf;
+}
+
+
+/*!
+ * \brief Wraping for vsnprintf function, that saves string to char*
+ * \return saved from vsnprintf string
+ */
+char* make_str(const char* msg, ...)
+{
+ va_list vl;
+ va_start(vl, msg);
+ char *buf = vmake_str(msg, vl);
+ va_end(vl);
+ return buf;
+}
+
+/*!
+ * \brief Version of pcilib_logger_t, that saves error text to Python exeption
+ */
+void pcilib_print_error_to_py(void *arg, const char *file, int line,
+ pcilib_log_priority_t prio, const char *msg,
+ va_list va) {
+ //wrap error message with file and line number
+ char* buf_raw_msg = vmake_str(msg, va);
+ char* buf_wrapped_message = make_str("%s [%s:%d]\n", buf_raw_msg, file, line);
+
+ if(prio == PCILIB_LOG_ERROR)
+ {
+ if(!full_log)
+ full_log = make_str("");
+
+ //copy received message to log
+ char* buf = full_log;
+ full_log = make_str("%s%s", buf, buf_wrapped_message);
+ free(buf);
+ }
+ else
+ printf("%s", buf_wrapped_message);
+
+ free(buf_wrapped_message);
+ free(buf_raw_msg);
+}
+
+void set_python_exception(const char* msg, ...)
+{
+ va_list vl;
+ va_start(vl, msg);
+ char *buf = vmake_str(msg, vl);
+
+ char* wrapped_exeption;
+ if(full_log)
+ wrapped_exeption = make_str("%s\nprogramm error log:\n%s", buf, full_log);
+ else
+ wrapped_exeption = buf;
+
+ free(full_log);
+ full_log = NULL;
+
+ PyErr_SetString(PyExc_Exception, wrapped_exeption);
+
+ free(buf);
+ if(full_log)
+ free(wrapped_exeption);
+ va_end(vl);
+}
+
+
+void __redirect_logs_to_exeption()
+{
+ pcilib_set_logger(pcilib_get_log_level(),
+ pcilib_print_error_to_py,
+ pcilib_get_logger_context());
+}
+
+/*!
+ * \brief Wrap for PyDict_SetItem, with decrease reference counting after set.
+ */
+void pcilib_pydict_set_item(PyObject* dict, PyObject* name, PyObject* value)
+{
+ PyDict_SetItem(dict,
+ name,
+ value);
+ Py_XDECREF(name);
+ Py_XDECREF(value);
+}
+
+/*!
+ * \brief Wrap for PyList_Append, with decrease reference counting after append.
+ */
+void pcilib_pylist_append(PyObject* list, PyObject* value)
+{
+ PyList_Append(list, value);
+ Py_XDECREF(value);
+}
+
+void add_pcilib_value_to_dict(pcilib_t* ctx, PyObject* dict, pcilib_value_t* val, const char *name)
+{
+ PyObject *py_val = (PyObject*)pcilib_get_value_as_pyobject(ctx, val, NULL);
+
+ if(py_val)
+ pcilib_pydict_set_item(dict,
+ PyString_FromString(name),
+ py_val);
+ else
+ pcilib_pydict_set_item(dict,
+ PyString_FromString("defvalue"),
+ PyString_FromString("invalid"));
+}
+
+PyObject * pcilib_convert_property_info_to_pyobject(pcilib_t* ctx, pcilib_property_info_t listItem)
+{
+ PyObject* pylistItem = PyDict_New();
+
+ if(listItem.name)
+ pcilib_pydict_set_item(pylistItem,
+ PyString_FromString("name"),
+ PyString_FromString(listItem.name));
+
+ if(listItem.description)
+ pcilib_pydict_set_item(pylistItem,
+ PyString_FromString("description"),
+ PyString_FromString(listItem.description));
+
+ if(listItem.path)
+ pcilib_pydict_set_item(pylistItem,
+ PyString_FromString("path"),
+ PyString_FromString(listItem.path));
+
+ //serialize types
+ const char* type = "invalid";
+ switch(listItem.type)
+ {
+ case PCILIB_TYPE_INVALID:
+ type = "invalid";
+ break;
+ case PCILIB_TYPE_STRING:
+ type = "string";
+ break;
+ case PCILIB_TYPE_DOUBLE:
+ type = "double";
+ break;
+ case PCILIB_TYPE_LONG :
+ type = "long";
+ break;
+ default:
+ break;
+ }
+ pcilib_pydict_set_item(pylistItem,
+ PyString_FromString("type"),
+ PyString_FromString(type));
+
+
+ //serialize modes
+ PyObject* modes = PyList_New(0);
+
+ if((listItem.mode & PCILIB_ACCESS_R ) == PCILIB_REGISTER_R)
+ pcilib_pylist_append(modes, PyString_FromString("R"));
+ if((listItem.mode & PCILIB_ACCESS_W ) == PCILIB_REGISTER_W)
+ pcilib_pylist_append(modes, PyString_FromString("W"));
+ if((listItem.mode & PCILIB_ACCESS_RW ) == PCILIB_REGISTER_RW)
+ pcilib_pylist_append(modes, PyString_FromString("RW"));
+ if((listItem.mode & PCILIB_REGISTER_INCONSISTENT) == PCILIB_REGISTER_INCONSISTENT)
+ pcilib_pylist_append(modes, PyString_FromString("NO_CHK"));
+
+ pcilib_pydict_set_item(pylistItem,
+ PyString_FromString("mode"),
+ modes);
+
+ //serialize flags
+ PyObject* flags = PyList_New(0);
+
+ if((listItem.flags & PCILIB_LIST_FLAG_CHILDS ) == PCILIB_LIST_FLAG_CHILDS)
+ pcilib_pylist_append(flags, PyString_FromString("childs"));
+
+ pcilib_pydict_set_item(pylistItem,
+ PyString_FromString("flags"),
+ flags);
+
+ if(listItem.unit)
+ pcilib_pydict_set_item(pylistItem,
+ PyString_FromString("unit"),
+ PyString_FromString(listItem.unit));
+
+ return pylistItem;
+}
+
+PyObject * pcilib_convert_register_info_to_pyobject(pcilib_t* ctx, pcilib_register_info_t listItem)
+{
+ PyObject* pylistItem = PyDict_New();
+
+ if(listItem.name)
+ pcilib_pydict_set_item(pylistItem,
+ PyString_FromString("name"),
+ PyString_FromString(listItem.name));
+
+ if(listItem.description)
+ pcilib_pydict_set_item(pylistItem,
+ PyString_FromString("description"),
+ PyString_FromString(listItem.description));
+
+ if(listItem.bank)
+ pcilib_pydict_set_item(pylistItem,
+ PyString_FromString("bank"),
+ PyString_FromString(listItem.bank));
+
+ //serialize modes
+ PyObject* modes = PyList_New(0);
+
+ if((listItem.mode & PCILIB_REGISTER_R) == PCILIB_REGISTER_R)
+ pcilib_pylist_append(modes, PyString_FromString("R"));
+ if((listItem.mode & PCILIB_REGISTER_W) == PCILIB_REGISTER_W)
+ pcilib_pylist_append(modes, PyString_FromString("W"));
+ if((listItem.mode & PCILIB_REGISTER_RW) == PCILIB_REGISTER_RW)
+ pcilib_pylist_append(modes, PyString_FromString("RW"));
+ if((listItem.mode & PCILIB_REGISTER_W1C) == PCILIB_REGISTER_W1C)
+ pcilib_pylist_append(modes, PyString_FromString("W1C"));
+ if((listItem.mode & PCILIB_REGISTER_RW1C) == PCILIB_REGISTER_RW1C)
+ pcilib_pylist_append(modes, PyString_FromString("RW1C"));
+ if((listItem.mode & PCILIB_REGISTER_W1I) == PCILIB_REGISTER_W1I)
+ pcilib_pylist_append(modes, PyString_FromString("W1I"));
+ if((listItem.mode & PCILIB_REGISTER_RW1I) == PCILIB_REGISTER_RW1I)
+ pcilib_pylist_append(modes, PyString_FromString("RW1I"));
+ if((listItem.mode & PCILIB_REGISTER_INCONSISTENT) == PCILIB_REGISTER_INCONSISTENT)
+ pcilib_pylist_append(modes, PyString_FromString("NO_CHK"));
+
+ pcilib_pydict_set_item(pylistItem,
+ PyString_FromString("mode"),
+ modes);
+
+ pcilib_value_t defval = {0};
+ pcilib_set_value_from_register_value(ctx, &defval, listItem.defvalue);
+ add_pcilib_value_to_dict(ctx, pylistItem, &defval, "defvalue");
+
+ if(listItem.range)
+ {
+ pcilib_value_t minval = {0};
+ pcilib_set_value_from_register_value(ctx, &minval, listItem.range->min);
+
+ pcilib_value_t maxval = {0};
+ pcilib_set_value_from_register_value(ctx, &maxval, listItem.range->max);
+
+ PyObject* range = PyDict_New();
+ add_pcilib_value_to_dict(ctx, range, &minval, "min");
+ add_pcilib_value_to_dict(ctx, range, &maxval, "max");
+ pcilib_pydict_set_item(pylistItem,
+ PyString_FromString("range"),
+ range);
+ }
+
+ if(listItem.values)
+ {
+ PyObject* values = PyList_New(0);
+
+ for (int j = 0; listItem.values[j].name; j++)
+ {
+ PyObject* valuesItem = PyDict_New();
+
+ pcilib_value_t val = {0};
+ pcilib_set_value_from_register_value(ctx, &val, listItem.values[j].value);
+
+ pcilib_value_t min = {0};
+ pcilib_set_value_from_register_value(ctx, &min, listItem.values[j].min);
+
+ pcilib_value_t max = {0};
+ pcilib_set_value_from_register_value(ctx, &max, listItem.values[j].max);
+
+ add_pcilib_value_to_dict(ctx, valuesItem, &val, "value");
+ add_pcilib_value_to_dict(ctx, valuesItem, &min, "min");
+ add_pcilib_value_to_dict(ctx, valuesItem, &max, "max");
+
+ if(listItem.values[j].name)
+ pcilib_pydict_set_item(valuesItem,
+ PyString_FromString("name"),
+ PyString_FromString(listItem.values[j].name));
+
+ if(listItem.values[j].description)
+ pcilib_pydict_set_item(valuesItem,
+ PyString_FromString("name"),
+ PyString_FromString(listItem.values[j].description));
+
+ pcilib_pylist_append(values, valuesItem);
+ }
+
+ pcilib_pydict_set_item(pylistItem,
+ PyString_FromString("values"),
+ values);
+ }
+
+ return pylistItem;
+}
+
+Pcipywrap *new_Pcipywrap(const char* fpga_device, const char* model)
+{
+ //opening device
+ pcilib_t* ctx = pcilib_open(fpga_device, model);
+ if(!ctx)
+ {
+ set_python_exception("Failed pcilib_open(%s, %s)", fpga_device, model);
+ return NULL;
+ }
+ Pcipywrap *self;
+ self = (Pcipywrap *) malloc(sizeof(Pcipywrap));
+ self->shared = 0;
+ self->ctx = ctx;
+ return self;
+}
+
+Pcipywrap *create_Pcipywrap(PyObject* ctx)
+{
+ if(!PyCObject_Check(ctx))
+ {
+ set_python_exception("Incorrect ctx type. Only PyCObject is allowed");
+ return NULL;
+ }
+
+ Pcipywrap *self;
+ self = (Pcipywrap *) malloc(sizeof(Pcipywrap));
+ self->shared = 1;
+ self->ctx = PyCObject_AsVoidPtr(ctx);
+ return self;
+}
+
+void delete_Pcipywrap(Pcipywrap *self) {
+ if(!self->shared)
+ pcilib_close(self->ctx);
+
+ free(self);
+}
+
+PyObject* Pcipywrap_read_register(Pcipywrap *self, const char *regname, const char *bank)
+{
+ pcilib_value_t val = {0};
+ pcilib_register_value_t reg_value;
+
+ int err;
+
+ err = pcilib_read_register(self->ctx, bank, regname, &reg_value);
+ if(err)
+ {
+ set_python_exception("Failed pcilib_read_register");
+ return NULL;
+ }
+
+ err = pcilib_set_value_from_register_value(self->ctx, &val, reg_value);
+ if(err)
+ {
+ set_python_exception("Failed pcilib_set_value_from_register_value");
+ return NULL;
+ }
+
+ return pcilib_get_value_as_pyobject(self->ctx, &val, NULL);
+}
+
+PyObject* Pcipywrap_write_register(Pcipywrap *self, PyObject* val, const char *regname, const char *bank)
+{
+ pcilib_value_t val_internal = {0};
+ pcilib_register_value_t reg_value;
+
+ int err;
+
+ err = pcilib_set_value_from_pyobject(self->ctx, &val_internal, val);
+
+ if(err)
+ {
+ set_python_exception("Failed pcilib_set_value_from_pyobject");
+ return NULL;
+ }
+
+
+ reg_value = pcilib_get_value_as_register_value(self->ctx, &val_internal, &err);
+ if(err)
+ {
+ set_python_exception("Failed pcilib_set_value_from_pyobject, (error %i)", err);
+ return NULL;
+ }
+
+ err = pcilib_write_register(self->ctx, bank, regname, reg_value);
+
+ if(err)
+ {
+ set_python_exception("Failed pcilib_set_value_from_pyobject, (error %i)", err);
+ return NULL;
+ }
+
+ return PyInt_FromLong((long)1);
+}
+
+PyObject* Pcipywrap_get_property(Pcipywrap *self, const char *prop)
+{
+ int err;
+ pcilib_value_t val = {0};
+
+ err = pcilib_get_property(self->ctx, prop, &val);
+
+ if(err)
+ {
+ set_python_exception("Failed pcilib_get_property, (error %i)", err);
+ return NULL;
+ }
+
+ return pcilib_get_value_as_pyobject(self->ctx, &val, NULL);
+}
+
+PyObject* Pcipywrap_set_property(Pcipywrap *self, PyObject* val, const char *prop)
+{
+ int err;
+
+ pcilib_value_t val_internal = {0};
+ err = pcilib_set_value_from_pyobject(self->ctx, &val_internal, val);
+ if(err)
+ {
+ set_python_exception("pcilib_set_value_from_pyobject, (error %i)", err);
+ return NULL;
+ }
+
+ err = pcilib_set_property(self->ctx, prop, &val_internal);
+ if(err)
+ {
+ set_python_exception("pcilib_set_property, (error %i)", err);
+ return NULL;
+ }
+
+ return PyInt_FromLong((long)1);
+}
+
+PyObject* Pcipywrap_get_registers_list(Pcipywrap *self, const char *bank)
+{
+ pcilib_register_info_t *list = pcilib_get_register_list(self->ctx, bank, PCILIB_LIST_FLAGS_DEFAULT);
+
+ PyObject* pyList = PyList_New(0);
+ for(int i = 0; i < ((pcilib_t*)self->ctx)->num_reg; i++)
+ {
+ //serialize item attributes
+ PyObject* pylistItem = pcilib_convert_register_info_to_pyobject(self->ctx, list[i]);
+ pcilib_pylist_append(pyList, pylistItem);
+ }
+
+ pcilib_free_register_info(self->ctx, list);
+
+ return pyList;
+}
+
+PyObject* Pcipywrap_get_register_info(Pcipywrap *self, const char* reg,const char *bank)
+{
+ pcilib_register_info_t *info = pcilib_get_register_info(self->ctx, bank, reg, PCILIB_LIST_FLAGS_DEFAULT);
+
+ if(!info)
+ {
+ return NULL;
+ }
+
+ PyObject* py_info = pcilib_convert_register_info_to_pyobject(self->ctx, info[0]);
+
+ pcilib_free_register_info(self->ctx, info);
+
+ return py_info;
+}
+
+PyObject* Pcipywrap_get_property_list(Pcipywrap *self, const char* branch)
+{
+ pcilib_property_info_t *list = pcilib_get_property_list(self->ctx, branch, PCILIB_LIST_FLAGS_DEFAULT);
+
+ PyObject* pyList = PyList_New(0);
+
+ for(int i = 0; list[i].path; i++)
+ {
+ //serialize item attributes
+ PyObject* pylistItem = pcilib_convert_property_info_to_pyobject(self->ctx, list[i]);
+ pcilib_pylist_append(pyList, pylistItem);
+ }
+
+ pcilib_free_property_info(self->ctx, list);
+
+ return pyList;
+}
diff --git a/pywrap/pcipywrap.h b/pywrap/pcipywrap.h
new file mode 100644
index 0000000..99cebd7
--- /dev/null
+++ b/pywrap/pcipywrap.h
@@ -0,0 +1,68 @@
+#ifndef PCIPYWRAP_H
+#define PCIPYWRAP_H
+
+#include "pci.h"
+#include "error.h"
+#include <Python.h>
+
+typedef struct {
+ void* ctx;
+ int shared;
+} Pcipywrap;
+
+/*!
+ * \brief Redirect pcilib standart log stream to exeption text.
+ * Logger will accumulate errors untill get message, starts with "#E".
+ * After that, logger will write last error, and all accumulated errors
+ * to Python exeption text
+ */
+void __redirect_logs_to_exeption();
+
+/*!
+ * \brief Wraps for pcilib_open function.
+ * \param[in] fpga_device path to the device file [/dev/fpga0]
+ * \param[in] model specifies the model of hardware, autodetected if NULL is passed
+ * \return Pointer to pcilib_t, created by pcilib_open; NULL with exeption text, if failed.
+ */
+PyObject* create_pcilib_instance(const char *fpga_device, const char *model);
+
+Pcipywrap *new_Pcipywrap(const char* fpga_device, const char* model);
+Pcipywrap *create_Pcipywrap(PyObject* ctx);
+void delete_Pcipywrap(Pcipywrap *self);
+
+/*!
+ * \brief Reads register value. Wrap for pcilib_read_register function.
+ * \param[in] regname the name of the register
+ * \param[in] bank should specify the bank name if register with the same name may occur in multiple banks, NULL otherwise
+ * \return register value, can be integer or float type; NULL with exeption text, if failed.
+ */
+PyObject* Pcipywrap_read_register(Pcipywrap *self, const char *regname, const char *bank);
+
+/*!
+ * \brief Writes value to register. Wrap for pcilib_write_register function.
+ * \param[in] val Register value, that needs to be set. Can be int, float or string.
+ * \param[in] regname the name of the register
+ * \param[in] bank should specify the bank name if register with the same name may occur in multiple banks, NULL otherwise
+ * \return 1, serialized to PyObject or NULL with exeption text, if failed.
+ */
+PyObject* Pcipywrap_write_register(Pcipywrap *self, PyObject* val, const char *regname, const char *bank);
+
+/*!
+ * \brief Reads propety value. Wrap for pcilib_get_property function.
+ * \param[in] prop property name (full name including path)
+ * \return property value, can be integer or float type; NULL with exeption text, if failed.
+ */
+PyObject* Pcipywrap_get_property(Pcipywrap *self, const char *prop);
+
+/*!
+ * \brief Writes value to property. Wrap for pcilib_set_property function.
+ * \param[in] prop property name (full name including path)
+ * \param[in] val Property value, that needs to be set. Can be int, float or string.
+ * \return 1, serialized to PyObject or NULL with exeption text, if failed.
+ */
+PyObject* Pcipywrap_set_property(Pcipywrap *self, PyObject* val, const char *prop);
+PyObject* Pcipywrap_get_registers_list(Pcipywrap *self, const char *bank);
+PyObject* Pcipywrap_get_register_info(Pcipywrap *self, const char* reg,const char *bank);
+PyObject* Pcipywrap_get_property_list(Pcipywrap *self, const char* branch);
+
+#endif /* PCIPYWRAP_H */
diff --git a/pywrap/pcipywrap.i b/pywrap/pcipywrap.i
new file mode 100644
index 0000000..88a746f
--- /dev/null
+++ b/pywrap/pcipywrap.i
@@ -0,0 +1,25 @@
+%module pcipywrap
+
+%{
+#include "pcipywrap.h"
+%}
+
+extern void __redirect_logs_to_exeption();
+
+typedef struct {
+ %extend {
+ Pcipywrap(const char* fpga_device = NULL, const char* model = NULL);
+ Pcipywrap(PyObject* ctx){return create_Pcipywrap(ctx);}
+ ~Pcipywrap();
+
+ PyObject* read_register(const char *regname = NULL, const char *bank = NULL);
+ PyObject* write_register(PyObject* val, const char *regname, const char *bank = NULL);
+
+ PyObject* get_property(const char *prop);
+ PyObject* set_property(PyObject* val, const char *prop);
+
+ PyObject* get_registers_list(const char *bank = NULL);
+ PyObject* get_register_info(const char* reg,const char *bank = NULL);
+ PyObject* get_property_list(const char* branch = NULL);
+ }
+} Pcipywrap;
diff --git a/pywrap/server.py b/pywrap/server.py
new file mode 100644
index 0000000..03302a2
--- /dev/null
+++ b/pywrap/server.py
@@ -0,0 +1,399 @@
+import time
+import os
+import pcipywrap
+import json
+import BaseHTTPServer
+import sys
+from optparse import OptionParser
+
+class PcilibServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+ def __init__(s, pcilib, *args):
+ s.pcilib = pcilib
+ BaseHTTPServer.BaseHTTPRequestHandler.__init__(s, *args)
+
+ def do_HEAD(s):
+ s.send_response(200)
+ s.send_header('content-type', 'application/json')
+ s.end_headers()
+
+ def do_GET(s):
+ length = int(s.headers['Content-Length'])
+
+ #deserialize input data
+ data = json.loads(s.rfile.read(length).decode('utf-8'))
+
+ if 'command' in data:
+ command = data['command']
+ if(command == 'help'):
+ s.help(data)
+
+ #elif(command == 'open'):
+ # #check required arguments
+ # if not 'device' in data:
+ # s.error('message doesnt contains "device" field, '
+ # 'which is required for "open" command', data)
+ # return
+ # #parse command arguments and convert them to string
+ # device = str(data.get('device', None))
+ # model = data.get('model', None)
+ # if not model is None:
+ # model = str(model)
+ #
+ # try:
+ # s.openPcilibInstance(device, model)
+ # except Exception as e:
+ # s.error(str(e), data)
+ # return
+ #
+ # #Success! Create and send reply
+ # s.send_response(200)
+ # s.send_header('content-type', 'application/json')
+ # s.end_headers()
+ # out = dict()
+ # out['status'] = 'ok'
+ # s.wrapMessageAndSend(out, data)
+
+ elif(command == 'get_registers_list'):
+ #parse command arguments and convert them to string
+ bank = data.get('bank', None)
+ if not bank is None:
+ bank = str(bank)
+
+ registers = dict()
+ try:
+ registers = s.pcilib.get_registers_list(bank)
+ except Exception as e:
+ s.error(str(e), data)
+ return
+
+ #Success! Create and send reply
+ s.send_response(200)
+ s.send_header('content-type', 'application/json')
+ s.end_headers()
+ out = dict()
+ out['status'] = 'ok'
+ out['registers'] = registers
+ s.wrapMessageAndSend(out, data)
+
+ elif(command == 'get_register_info'):
+ #check required arguments
+ if not 'reg' in data:
+ s.error('message doesnt contains "reg" field, '
+ 'which is required for "get_register_info" command', data)
+ return
+
+ #parse command arguments and convert them to string
+ reg = str(data.get('reg', None))
+ bank = data.get('bank', None)
+ if not bank is None:
+ bank = str(bank)
+
+ register = dict()
+ try:
+ register = s.pcilib.get_register_info(reg, bank)
+ except Exception as e:
+ s.error(str(e), data)
+ return
+
+ #Success! Create and send reply
+ s.send_response(200)
+ s.send_header('content-type', 'application/json')
+ s.end_headers()
+ out = dict()
+ out['status'] = 'ok'
+ out['register'] = register
+ s.wrapMessageAndSend(out, data)
+
+ elif(command == 'get_property_list'):
+ #parse command arguments and convert them to string
+ branch = data.get('branch', None)
+ if not branch is None:
+ branch = str(branch)
+
+ properties = dict()
+ try:
+ properties = s.pcilib.get_property_list(branch)
+ except Exception as e:
+ s.error(str(e), data)
+ return
+
+ #Success! Create and send reply
+ s.send_response(200)
+ s.send_header('content-type', 'application/json')
+ s.end_headers()
+ out = dict()
+ out['status'] = 'ok'
+ out['properties'] = properties
+ s.wrapMessageAndSend(out, data)
+
+ elif(command == 'read_register'):
+ #check required arguments
+ if not 'reg' in data:
+ s.error('message doesnt contains "reg" field, '
+ 'which is required for "read_register" command', data)
+ return
+
+ #parse command arguments and convert them to string
+ reg = str(data.get('reg', None))
+ bank = data.get('bank', None)
+ if not bank is None:
+ bank = str(bank)
+
+ value = 0
+ try:
+ value = s.pcilib.read_register(reg, bank)
+ except Exception as e:
+ s.error(str(e), data)
+ return
+
+ #Success! Create and send reply
+ s.send_response(200)
+ s.send_header('content-type', 'application/json')
+ s.end_headers()
+ out = dict()
+ out['status'] = 'ok'
+ out['value'] = value
+ s.wrapMessageAndSend(out, data)
+
+ elif(command == 'write_register'):
+ #check required arguments
+ if not 'reg' in data:
+ s.error('message doesnt contains "reg" field, '
+ 'which is required for "write_register" command', data)
+ return
+
+ if not 'value' in data:
+ s.error('message doesnt contains "value" field, '
+ 'which is required for "write_register" command', data)
+ return
+
+ #parse command arguments and convert them to string
+ reg = str(data.get('reg', None))
+ value = str(data.get('value', None))
+ bank = data.get('bank', None)
+ if not bank is None:
+ bank = str(bank)
+
+ try:
+ s.pcilib.write_register(value, reg, bank)
+ except Exception as e:
+ s.error(str(e), data)
+ return
+
+ #Success! Create and send reply
+ s.send_response(200)
+ s.send_header('content-type', 'application/json')
+ s.end_headers()
+ out = dict()
+ out['status'] = 'ok'
+ s.wrapMessageAndSend(out, data)
+
+ elif(command == 'get_property'):
+ #check required arguments
+ if not 'prop' in data:
+ s.error('message doesnt contains "prop" field, '
+ 'which is required for "get_property" command', data)
+ return
+
+ #parse command arguments and convert them to string
+ prop = str(data.get('prop', None))
+
+ value = 0
+ try:
+ value = s.pcilib.get_property(prop)
+ except Exception as e:
+ s.error(str(e), data)
+ return
+
+ #Success! Create and send reply
+ s.send_response(200)
+ s.send_header('content-type', 'application/json')
+ s.end_headers()
+ out = dict()
+ out['status'] = 'ok'
+ out['value'] = value
+ s.wrapMessageAndSend(out, data)
+
+ elif(command == 'set_property'):
+ #check required arguments
+ if not 'prop' in data:
+ s.error('message doesnt contains "prop" field, '
+ 'which is required for "set_property" command', data)
+ return
+
+ if not 'value' in data:
+ s.error('message doesnt contains "value" field, '
+ 'which is required for "set_property" command', data)
+ return
+
+ #parse command arguments and convert them to string
+ prop = str(data.get('prop', None))
+ value = str(data.get('value', None))
+
+ try:
+ s.pcilib.set_property(value, prop)
+ except Exception as e:
+ s.error(str(e), data)
+ return
+
+ #Success! Create and send reply
+ s.send_response(200)
+ s.send_header('content-type', 'application/json')
+ s.end_headers()
+ out = dict()
+ out['status'] = 'ok'
+ s.wrapMessageAndSend(out, data)
+
+
+ else:
+ s.error('command "' + command + '" undefined', data)
+ return
+ else:
+ s.error('message doesnt contains "command" field, which is required', data)
+ return
+
+
+ #print str(s.headers['content-type'])
+ #print post_data['some']
+
+ """open device context """
+ def openPcilibInstance(s, device, model):
+ s.pcilib = pcipywrap.create_pcilib_instance(device, model)
+
+ """Send help message"""
+ def help(s, received_message = None):
+ s.send_response(200)
+ s.send_header('content-type', 'application/json')
+ s.end_headers()
+ usage = str('Usage:\n'
+ ' Server receive commands via http GET with json packet.\n'
+ ' content-type should have value "application/json"\n'
+ ' Server could handle only commands. to set command, you\n'
+ ' should specify field "command" in packet with command name\n'
+ ' List of commands:\n'
+ '\n'
+ ' command: help - Get help. This will return usage\n'
+ '\n'
+
+ ' command: open - Opens context of device. It will be reopened if already open.\n'
+ ' required fields\n'
+ ' device: - path to the device file [/dev/fpga0]\n'
+ ' optional fields\n'
+ ' model: - specifies the model of hardware, autodetected if doesnt exists\n'
+ '\n'
+
+ ' command: get_registers_list - Returns the list of registers provided by the hardware model.\n'
+ ' optional fields\n'
+ ' bank: - if set, only register within the specified bank will be returned\n'
+ '\n'
+
+ ' command: get_register_info - Returns the information about the specified register.\n'
+ ' required fields\n'
+ ' reg: - the name of the register\n'
+ ' optional fields\n'
+ ' bank: - if set, only register within the specified bank will be returned\n'
+ '\n'
+
+ ' command: get_property_list - Returns the list of properties available under the specified path.\n'
+ ' optional fields\n'
+ ' branch: - Path. If not set, will return the top-level properties\n'
+ '\n'
+
+ ' command: read_register - Reads the specified register.\n'
+ ' required fields\n'
+ ' reg: - the name of the register\n'
+ ' optional fields\n'
+ ' bank: - if set, only register within the specified bank will be processed\n'
+ '\n'
+
+ ' command: write_register - Writes to specified register.\n'
+ ' required fields\n'
+ ' reg: - the name of the register\n'
+ ' value: - the register value to write. Should be int, float or string (with number)\n'
+ ' optional fields\n'
+ ' bank: - if set, only register within the specified bank will be processed\n'
+ '\n'
+
+ ' command: get_property - Reads / computes the property value.\n'
+ ' required fields\n'
+ ' prop: - full name including path\n'
+ '\n'
+
+ ' command: set_property - Writes the property value or executes the code associated with property.\n'
+ ' required fields\n'
+ ' prop: - full name including path\n'
+ ' value: - the property value to write. Should be int, float or string (with number)\n'
+ '\n')
+ out = {'status': 'ok', 'usage' : usage}
+ s.wrapMessageAndSend(out, received_message)
+
+ """Send error message with text description"""
+ def error(s, info, received_message = None):
+ s.send_response(400)
+ s.send_header('content-type', 'application/json')
+ s.end_headers()
+ out = dict()
+
+ out['status'] = 'error'
+ out['description'] = info
+ out['note'] = 'send {"command" : "help"} to get help'
+ s.wrapMessageAndSend(out, received_message)
+
+ def wrapMessageAndSend(s, message, received_message = None):
+ if not received_message is None:
+ message['received_message'] = received_message
+ s.wfile.write(json.dumps(message))
+
+if __name__ == '__main__':
+
+ #parce command line options
+ parser = OptionParser()
+ parser.add_option("-p", "--port", action="store",
+ type="int", dest="port", default=9000,
+ help="Set server port (9000)")
+ parser.add_option("-d", "--device", action="store",
+ type="string", dest="device", default=str('/dev/fpga0'),
+ help="FPGA device (/dev/fpga0)")
+ parser.add_option("-m", "--model", action="store",
+ type="string", dest="model", default=None,
+ help="Memory model (autodetected)")
+ opts = parser.parse_args()[0]
+
+ HOST_NAME = ''
+ PORT_NUMBER = opts.port
+ MODEL = opts.model
+ DEVICE = opts.device
+
+ #Set enviroment variables, if it not setted already
+ if not 'APP_PATH' in os.environ:
+ APP_PATH = ''
+ file_dir = os.path.dirname(os.path.abspath(__file__))
+ APP_PATH = str(os.path.abspath(file_dir + '/../..'))
+ os.environ["APP_PATH"] = APP_PATH
+
+ if not 'PCILIB_MODEL_DIR' in os.environ:
+ os.environ['PCILIB_MODEL_DIR'] = os.environ["APP_PATH"] + "/xml"
+
+ if not 'LD_LIBRARY_PATH' in os.environ:
+ os.environ['LD_LIBRARY_PATH'] = os.environ["APP_PATH"] + "/pcilib"
+
+ #redirect logs to exeption
+ pcipywrap.__redirect_logs_to_exeption()
+
+ #start server
+ pcilib_server = BaseHTTPServer.HTTPServer
+
+ #pass Pcipywrap to to server handler
+ lib = pcipywrap.Pcipywrap(DEVICE, MODEL)
+ def handler(*args):
+ PcilibServerHandler(lib, *args)
+
+ httpd = pcilib_server((HOST_NAME, PORT_NUMBER), handler)
+
+ print time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER)
+ try:
+ httpd.serve_forever()
+ except KeyboardInterrupt:
+ pass
+ httpd.server_close()
+ print time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER)
diff --git a/pywrap/test_pcipywrap.py b/pywrap/test_pcipywrap.py
new file mode 100644
index 0000000..257b4a5
--- /dev/null
+++ b/pywrap/test_pcipywrap.py
@@ -0,0 +1,119 @@
+import threading
+import pcipywrap
+import random
+import os
+import json
+import requests
+import time
+
+class test_pcipywrap():
+ def __init__(self, device, model, num_threads = 150,
+ write_percentage = 0.1, register = 'test_prop2',
+ server_host = 'http://localhost', server_port = 12412,
+ server_message_delay = 0):
+ #initialize enviroment variables
+ if not 'APP_PATH' in os.environ:
+ APP_PATH = ''
+ file_dir = os.path.dirname(os.path.abspath(__file__))
+ APP_PATH = str(os.path.abspath(file_dir + '/../..'))
+ os.environ["APP_PATH"] = APP_PATH
+
+ if not 'PCILIB_MODEL_DIR' in os.environ:
+ os.environ['PCILIB_MODEL_DIR'] = os.environ["APP_PATH"] + "/xml"
+ if not 'LD_LIBRARY_PATH' in os.environ:
+ os.environ['LD_LIBRARY_PATH'] = os.environ["APP_PATH"] + "/pcilib"
+
+ random.seed()
+ #create pcilib_instance
+ self.pcilib = pcipywrap.Pcipywrap(device, model)
+ self.num_threads = num_threads
+ self.write_percentage = write_percentage
+ self.register = register
+ self.server_message_delay = server_message_delay
+ self.server_port = server_port
+ self.server_host = server_host
+
+ def testThreadSafeReadWrite(self):
+ def threadFunc():
+ if random.randint(0, 100) >= (self.write_percentage * 100):
+ ret = self.pcilib.get_property('/test/prop2')
+ print self.register, ':', ret
+ del ret
+ else:
+ val = random.randint(0, 65536)
+ print 'set value:', val
+ self.pcilib.write_register(val, self.register)
+ try:
+ while(1):
+ thread_list = [threading.Thread(target=threadFunc) for i in range(0, self.num_threads)]
+ for i in range(0, self.num_threads):
+ thread_list[i].start()
+ for i in range(0, self.num_threads):
+ thread_list[i].join()
+ print 'cycle done'
+ except KeyboardInterrupt:
+ print 'testing done'
+ pass
+
+ def testMemoryLeak(self):
+ try:
+ while(1):
+ #print self.pcilib.create_pcilib_instance('/dev/fpga0','test_pywrap')
+
+ print self.pcilib.get_property_list('/test')
+ print self.pcilib.get_register_info('test_prop1')
+ #print self.pcilib.get_registers_list();
+
+ #print self.pcilib.read_register('reg1')
+ #print self.pcilib.write_register(12, 'reg1')
+
+ #print self.pcilib.get_property('/test/prop2')
+ #print self.pcilib.set_property(12, '/test/prop2')
+ except KeyboardInterrupt:
+ print 'testing done'
+ pass
+
+ def testServer(self):
+ url = str(self.server_host + ':' + str(self.server_port))
+ headers = {'content-type': 'application/json'}
+ payload =[{'com': 'open', 'data2' : '12341'},
+ #{'command': 'open', 'device' : '/dev/fpga0', 'model': 'test_pywrap'},
+ {'command': 'help'},
+ {'command': 'get_registers_list'},
+ {'command': 'get_register_info', 'reg': 'reg1'},
+ {'command': 'get_property_list'},
+ {'command': 'read_register', 'reg': 'reg1'},
+ {'command': 'write_register', 'reg': 'reg1'},
+ {'command': 'get_property', 'prop': '/test/prop2'},
+ {'command': 'set_property', 'prop': '/test/prop2'}]
+
+ def sendRandomMessage():
+ message_number = random.randint(1, len(payload) - 1)
+ print 'message number: ', message_number
+ payload[message_number]['value'] = random.randint(0, 65535)
+ r = requests.get(url, data=json.dumps(payload[message_number]), headers=headers)
+ print json.dumps(r.json(), sort_keys=True, indent=4, separators=(',', ': '))
+
+ try:
+ r = requests.get(url, data=json.dumps(payload[1]), headers=headers)
+ print json.dumps(r.json(), sort_keys=True, indent=3, separators=(',', ': '))
+
+ while(1):
+ time.sleep(self.server_message_delay)
+ thread_list = [threading.Thread(target=sendRandomMessage) for i in range(0, self.num_threads)]
+ for i in range(0, self.num_threads):
+ thread_list[i].start()
+ for i in range(0, self.num_threads):
+ thread_list[i].join()
+ print 'cycle done'
+
+ except KeyboardInterrupt:
+ print 'testing done'
+ pass
+
+if __name__ == '__main__':
+ lib = test_pcipywrap('/dev/fpga0','test_pywrap', num_threads = 150,
+ write_percentage = 0.1, register = 'test_prop2',server_host = 'http://localhost', server_port = 12412,
+ server_message_delay = 0)
+ lib.testThreadSafeReadWrite()
+