summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasilii Chernov <vchernov@inr.ru>2016-02-05 12:33:48 +0100
committerVasilii Chernov <vchernov@inr.ru>2016-02-05 12:33:48 +0100
commit5349163e93a107fdfea2ad58760f6149a8d749b0 (patch)
tree84afe1008bac52a00785ba71f415ae51b1b9c768
parent99c165c078222c789d5fc90a79c756c8fffdafea (diff)
downloadpcitool-5349163e93a107fdfea2ad58760f6149a8d749b0.tar.gz
pcitool-5349163e93a107fdfea2ad58760f6149a8d749b0.tar.bz2
pcitool-5349163e93a107fdfea2ad58760f6149a8d749b0.tar.xz
pcitool-5349163e93a107fdfea2ad58760f6149a8d749b0.zip
Add support for python script properties. Correct pcilib python wrapping. Update examples. Update cmakelists for work in shadow build mode.
-rw-r--r--CMakeLists.txt6
-rw-r--r--pcilib/CMakeLists.txt1
-rw-r--r--pcilib/pcipywrap.c271
-rw-r--r--pcilib/pcipywrap.i9
-rw-r--r--pcilib/py.c1
-rw-r--r--pcilib/xml.c65
-rw-r--r--views/CMakeLists.txt4
-rw-r--r--views/script.c157
-rw-r--r--views/script.h18
-rw-r--r--xml/CMakeLists.txt27
-rw-r--r--xml/model.xsd1
-rw-r--r--xml/references.xsd1
-rw-r--r--xml/test2/reg2.py0
-rw-r--r--xml/test_pywrap/camera.xml (renamed from xml/test2/camera.xml)0
-rw-r--r--xml/test_pywrap/names.xml (renamed from xml/test2/names.xml)0
-rw-r--r--xml/test_pywrap/props.xml (renamed from xml/test2/props.xml)10
-rw-r--r--xml/test_pywrap/test_prop2.py7
-rw-r--r--xml/test_pywrap/test_prop3.py4
-rw-r--r--xml/test_pywrap/units.xml (renamed from xml/test2/units.xml)0
-rw-r--r--xml/test_pywrap/views.xml (renamed from xml/test2/views.xml)0
-rw-r--r--xml/types.xsd11
21 files changed, 411 insertions, 182 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 63bdeb3..a0fe0f0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,7 +35,7 @@ SET(ENV{PKG_CONFIG_PATH} "${LIB_INSTALL_DIR}/pkgconfig:$ENV{PKG_CONFIG_PATH}")
find_package(PkgConfig REQUIRED)
find_package(Threads REQUIRED)
-find_package(PythonLibs REQUIRED)
+find_package(PythonLibs 2.7 REQUIRED)
set(EXTRA_SYSTEM_LIBS -lrt)
@@ -91,6 +91,10 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/misc/pcitool.pc.in ${CMAKE_CURRENT_BI
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pcilib/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/pcilib/config.h)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pcilib/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/pcilib/version.h)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/docs/Doxyfile)
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/pci
+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
+ FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
+ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/misc/pcitool.pc
diff --git a/pcilib/CMakeLists.txt b/pcilib/CMakeLists.txt
index ea275a3..db74775 100644
--- a/pcilib/CMakeLists.txt
+++ b/pcilib/CMakeLists.txt
@@ -24,7 +24,6 @@ SET(CMAKE_SWIG_FLAGS "")
SET_SOURCE_FILES_PROPERTIES(pcipywrap.i PROPERTIES SWIG_FLAGS "-includeall")
SWIG_ADD_MODULE(pcipywrap python pcipywrap.i pcipywrap.c pci.c datacpy.c memcpy.c pagecpy.c cpu.c timing.c export.c value.c bar.c fifo.c model.c bank.c register.c view.c unit.c property.c xml.c py.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c)
SWIG_LINK_LIBRARIES(pcipywrap ${PYTHON_LIBRARIES} dma protocols views ${CMAKE_THREAD_LIBS_INIT} ${UFODECODE_LIBRARIES} ${CMAKE_DL_LIBS} ${EXTRA_SYSTEM_LIBS} ${LIBXML2_LIBRARIES})
-#wrapping end
install(TARGETS pcilib
LIBRARY DESTINATION lib${LIB_SUFFIX}
diff --git a/pcilib/pcipywrap.c b/pcilib/pcipywrap.c
index 5abd56c..efce909 100644
--- a/pcilib/pcipywrap.c
+++ b/pcilib/pcipywrap.c
@@ -1,190 +1,125 @@
#include "pcilib.h"
-
-//Remove unused headers
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <alloca.h>
-#include <arpa/inet.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <pthread.h>
-#include <signal.h>
-#include <dlfcn.h>
-
-#include <getopt.h>
-
-#include <fastwriter.h>
-
-#include "pcitool/sysinfo.h"
-#include "pcitool/formaters.h"
-
-#include "views/transform.h"
-#include "views/enum.h"
+#include <Python.h>
#include "pci.h"
-#include "plugin.h"
-#include "config.h"
-#include "tools.h"
-#include "kmem.h"
#include "error.h"
-#include "debug.h"
-#include "model.h"
-#include "locking.h"
+/*!
+ * \brief Global pointer to pcilib_t context.
+ * Used by __setPcilib and read_register.
+ */
pcilib_t* __ctx = 0;
-pcilib_model_description_t *model_info = 0;
/*!
- * \brief присваивание указателя на устройство. Закрытая функция. Будет проходить при парсинге xml.
- * \param ctx
+ * \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, serialized to bytearray
*/
-void __initCtx(void* ctx)
+PyObject* __createPcilibInstance(const char *fpga_device, const char *model)
{
- __ctx = ctx;
+ //opening device
+ pcilib_t* ctx = pcilib_open(fpga_device, model);
+
+ //serializing object
+ return PyByteArray_FromStringAndSize((const char*)&ctx, sizeof(pcilib_t*));
}
/*!
- * \brief создание хэндлера устройства, для тестирования скрипта не из программы.
- * \return
+ * \brief Sets pcilib context to wraper.
+ * \param[in] addr Pointer to pcilib_t, serialized to bytearray
*/
-void __createCtxInstance(const char *fpga_device, const char *model)
+void __setPcilib(PyObject* addr)
{
- __ctx = pcilib_open(fpga_device, model);
- model_info = pcilib_get_model_description(__ctx);
-}
-
-int read_register(const char *bank, const char *regname, void *value)
-{
- int ret = pcilib_read_register(__ctx, bank, regname, (pcilib_register_value_t*)value);
- return ret;
-}
-
-void Error(const char *message, const char *attr, ...)
-{
- printf("Catch error: %s, %s\n", message, attr);
+ if(!PyByteArray_Check(addr))
+ {
+ PyErr_SetString(PyExc_Exception, "Incorrect addr type. Only bytearray is allowed");
+ return NULL;
+ }
+
+ //deserializing adress
+ char* pAddr = PyByteArray_AsString(addr);
+
+ //hard copy context adress
+ for(int i = 0; i < sizeof(pcilib_t*) + 10; i++)
+ ((char*)&__ctx)[i] = pAddr[i];
+
+ free(pAddr);
}
-int ReadRegister(const char *bank, const char *reg) {
+/*!
+ * \brief Reads register value.
+ * \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
+ */
+PyObject* read_register(const char *regname, const char *bank)
+{
+ if(!__ctx)
+ {
+ PyErr_SetString(PyExc_Exception, "pcilib_t handler not initialized");
+ return NULL;
+ }
- const char *view = NULL;
- const char *unit = NULL;
- const char *attr = NULL;
- pcilib_t *handle = __ctx;
- int i;
- int err;
- const char *format;
-
- pcilib_register_bank_t bank_id;
- pcilib_register_bank_addr_t bank_addr = 0;
-
- pcilib_register_value_t value;
-
- // Adding DMA registers
- pcilib_get_dma_description(handle);
-
- if (reg||view||attr) {
- pcilib_value_t val = {0};
- if (attr) {
- if (reg) err = pcilib_get_register_attr(handle, bank, reg, attr, &val);
- else if (view) err = pcilib_get_property_attr(handle, view, attr, &val);
- else if (bank) err = pcilib_get_register_bank_attr(handle, bank, attr, &val);
- else err = PCILIB_ERROR_INVALID_ARGUMENT;
-
- if (err) {
- if (err == PCILIB_ERROR_NOTFOUND)
- Error("Attribute %s is not found", attr);
- else
- Error("Error (%i) reading attribute %s", err, attr);
- }
-
- err = pcilib_convert_value_type(handle, &val, PCILIB_TYPE_STRING);
- if (err) Error("Error converting attribute %s to string", attr);
-
- printf("%s = %s", attr, val.sval);
- if ((val.unit)&&(strcasecmp(val.unit, "name")))
- printf(" %s", val.unit);
- printf(" (for %s)\n", (reg?reg:(view?view:bank)));
- } else if (view) {
- if (reg) {
- err = pcilib_read_register_view(handle, bank, reg, view, &val);
- if (err) Error("Error reading view %s of register %s", view, reg);
- } else {
- err = pcilib_get_property(handle, view, &val);
- if (err) Error("Error reading property %s", view);
- }
-
- if (unit) {
- err = pcilib_convert_value_unit(handle, &val, unit);
- if (err) {
- if (reg) Error("Error converting view %s of register %s to unit %s", view, reg, unit);
- else Error("Error converting property %s to unit %s", view, unit);
- }
- }
-
- err = pcilib_convert_value_type(handle, &val, PCILIB_TYPE_STRING);
- if (err) {
- if (reg) Error("Error converting view %s of register %s to string", view);
- else Error("Error converting property %s to string", view);
- }
-
- printf("%s = %s", (reg?reg:view), val.sval);
- if ((val.unit)&&(strcasecmp(val.unit, "name")))
- printf(" %s", val.unit);
- printf("\n");
- } else {
- pcilib_register_t regid = pcilib_find_register(handle, bank, reg);
- bank_id = pcilib_find_register_bank_by_addr(handle, model_info->registers[regid].bank);
- format = model_info->banks[bank_id].format;
- if (!format) format = "%lu";
- err = pcilib_read_register_by_id(handle, regid, &value);
- if (err) Error("Error reading register %s", reg);
-
- printf("%s = ", reg);
- printf(format, value);
- printf("\n");
+ pcilib_get_dma_description(__ctx);
+
+ pcilib_value_t val = {0};
+ pcilib_register_value_t reg_value;
+
+ int err;
+
+ err = pcilib_read_register(__ctx, bank, regname, &reg_value);
+ if(err)
+ {
+ PyErr_SetString(PyExc_Exception, "Failed: read_register");
+ return NULL;
+ }
+
+ err = pcilib_set_value_from_register_value(__ctx, &val, reg_value);
+
+ if(err)
+ {
+ PyErr_SetString(PyExc_Exception, "Failed: pcilib_set_value_from_register_value");
+ return NULL;
}
- } else {
- if (model_info->registers) {
- if (bank) {
- bank_id = pcilib_find_register_bank(handle, bank);
- bank_addr = model_info->banks[bank_id].addr;
- }
-
- printf("Registers:\n");
- for (i = 0; model_info->registers[i].bits; i++) {
- if ((model_info->registers[i].mode & PCILIB_REGISTER_R)&&((!bank)||(model_info->registers[i].bank == bank_addr))&&(model_info->registers[i].type != PCILIB_REGISTER_BITS)) {
- bank_id = pcilib_find_register_bank_by_addr(handle, model_info->registers[i].bank);
- format = model_info->banks[bank_id].format;
- if (!format) format = "%lu";
-
- err = pcilib_read_register_by_id(handle, i, &value);
- if (err) printf(" %s = error reading value", model_info->registers[i].name);
- else {
- printf(" %s = ", model_info->registers[i].name);
- printf(format, value);
- }
- printf(" [");
- printf(format, model_info->registers[i].defvalue);
- printf("]");
- printf("\n");
+ switch(val.type)
+ {
+ case PCILIB_TYPE_INVALID:
+ PyErr_SetString(PyExc_Exception, "Invalid register output type (PCILIB_TYPE_INVALID)");
+ return NULL;
+
+ case PCILIB_TYPE_STRING:
+ PyErr_SetString(PyExc_Exception, "Invalid register output type (PCILIB_TYPE_STRING)");
+ return NULL;
+
+ case PCILIB_TYPE_LONG:
+ {
+ long ret;
+ ret = pcilib_get_value_as_int(__ctx, &val, &err);
+
+ if(err)
+ {
+ PyErr_SetString(PyExc_Exception, "Failed: pcilib_get_value_as_int");
+ return NULL;
+ }
+ return PyInt_FromLong((long) ret);
}
- }
- } else {
- printf("No registers");
+
+ case PCILIB_TYPE_DOUBLE:
+ {
+ double ret;
+ ret = pcilib_get_value_as_float(__ctx, &val, &err);
+
+ if(err)
+ {
+ PyErr_SetString(PyExc_Exception, "Failed: pcilib_get_value_as_int");
+ return NULL;
+ }
+ return PyFloat_FromDouble((double) ret);
+ }
+
+ default:
+ PyErr_SetString(PyExc_Exception, "Invalid register output type (unknown)");
+ return NULL;
}
- printf("\n");
- }
-
- return 0;
}
diff --git a/pcilib/pcipywrap.i b/pcilib/pcipywrap.i
index fc7f4ef..ed5ca62 100644
--- a/pcilib/pcipywrap.i
+++ b/pcilib/pcipywrap.i
@@ -1,6 +1,5 @@
%module pcipywrap
-/*extern void* __ctx;*/
-extern void __initCtx(void* ctx);
-extern void __createCtxInstance(const char *fpga_device, const char *model);
-extern int read_register(const char *bank, const char *regname, void *value);
-extern int ReadRegister(const char *reg);
+
+extern PyObject* read_register(const char *regname, const char *bank = NULL);
+extern PyObject* __createPcilibInstance(const char *fpga_device, const char *model = NULL);
+extern void __setPcilib(PyObject* addr);
diff --git a/pcilib/py.c b/pcilib/py.c
index 4256afc..13113d7 100644
--- a/pcilib/py.c
+++ b/pcilib/py.c
@@ -5,7 +5,6 @@
#include <string.h>
#include <strings.h>
-
#include "pci.h"
#include "debug.h"
#include "pcilib.h"
diff --git a/pcilib/xml.c b/pcilib/xml.c
index 50aaa35..76ed38c 100644
--- a/pcilib/xml.c
+++ b/pcilib/xml.c
@@ -42,17 +42,19 @@
#include "view.h"
#include "views/enum.h"
#include "views/transform.h"
+#include "views/script.h"
#define BANKS_PATH ((xmlChar*)"/model/bank") /**< path to complete nodes of banks */
#define REGISTERS_PATH ((xmlChar*)"./register") /**< all standard registers nodes */
#define BIT_REGISTERS_PATH ((xmlChar*)"./field") /**< all bits registers nodes */
#define REGISTER_VIEWS_PATH ((xmlChar*)"./view") /**< supported register & field views */
-#define TRANSFORM_VIEWS_PATH ((xmlChar*)"/model/transform") /**< path to complete nodes of views */
+#define TRANSFORM_VIEWS_PATH ((xmlChar*)"/model/transform") /**< path to complete nodes of views */
+#define SCRIPT_VIEWS_PATH ((xmlChar*)"/model/script") /**< path to complete nodes of views */
#define ENUM_VIEWS_PATH ((xmlChar*)"/model/enum") /**< path to complete nodes of views */
#define ENUM_ELEMENTS_PATH ((xmlChar*)"./name") /**< all elements in the enum */
#define UNITS_PATH ((xmlChar*)"/model/unit") /**< path to complete nodes of units */
-#define UNIT_TRANSFORMS_PATH ((xmlChar*)"./transform") /**< all transforms of the unit */
+#define UNIT_TRANSFORMS_PATH ((xmlChar*)"./transform") /**< all transforms of the unit */
@@ -543,6 +545,51 @@ static int pcilib_xml_parse_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDoc
return 0;
}
+static int pcilib_xml_create_script_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
+ int err;
+ xmlAttrPtr cur;
+ const char *value, *name;
+ pcilib_view_context_t *view_ctx;
+
+ pcilib_access_mode_t mode = 0;
+ pcilib_script_view_description_t desc = {{0}};
+
+ desc.base.api = &pcilib_script_view_api;
+ desc.base.type = PCILIB_TYPE_DOUBLE;
+ desc.base.mode = PCILIB_ACCESS_RW;
+ desc.py_script_module = NULL;
+ desc.script_name = NULL;
+
+ err = pcilib_xml_parse_view(ctx, xpath, doc, node, (pcilib_view_description_t*)&desc);
+ if (err) return err;
+
+ for (cur = node->properties; cur != NULL; cur = cur->next) {
+ if (!cur->children) continue;
+ if (!xmlNodeIsText(cur->children)) continue;
+
+ name = (char*)cur->name;
+ value = (char*)cur->children->content;
+ if (!value) continue;
+
+ if (!strcasecmp(name, "script")) {
+ //write script name to struct
+ desc.script_name = malloc(strlen(value));
+ sprintf(desc.script_name, "%s", value);
+ //set read access
+ mode |= PCILIB_ACCESS_R;
+ }
+ }
+
+ desc.base.mode &= mode;
+
+ err = pcilib_add_views_custom(ctx, 1, (pcilib_view_description_t*)&desc, &view_ctx);
+ if (err) return err;
+
+ view_ctx->xml = node;
+ return 0;
+}
+
+
static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
int err;
xmlAttrPtr cur;
@@ -822,14 +869,16 @@ static int pcilib_xml_create_unit(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo
*/
static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathContextPtr xpath) {
int err;
- xmlXPathObjectPtr bank_nodes = NULL, transform_nodes = NULL, enum_nodes = NULL, unit_nodes = NULL;
+ xmlXPathObjectPtr bank_nodes = NULL, transform_nodes = NULL, enum_nodes = NULL, unit_nodes = NULL, script_nodes = NULL;
xmlNodeSetPtr nodeset;
int i;
bank_nodes = xmlXPathEvalExpression(BANKS_PATH, xpath);
if (bank_nodes) transform_nodes = xmlXPathEvalExpression(TRANSFORM_VIEWS_PATH, xpath);
- if (transform_nodes) enum_nodes = xmlXPathEvalExpression(ENUM_VIEWS_PATH, xpath);
+ if (transform_nodes) script_nodes = xmlXPathEvalExpression(SCRIPT_VIEWS_PATH, xpath);
+ if (script_nodes) enum_nodes = xmlXPathEvalExpression(ENUM_VIEWS_PATH, xpath);
if (enum_nodes) unit_nodes = xmlXPathEvalExpression(UNITS_PATH, xpath);
+
if (!unit_nodes) {
const unsigned char *expr = (enum_nodes?UNITS_PATH:(transform_nodes?ENUM_VIEWS_PATH:(bank_nodes?TRANSFORM_VIEWS_PATH:BANKS_PATH)));
@@ -850,6 +899,14 @@ static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathCon
if (err) pcilib_error("Error (%i) creating unit", err);
}
}
+
+ nodeset = script_nodes->nodesetval;
+ if(!xmlXPathNodeSetIsEmpty(nodeset)) {
+ for(i=0; i < nodeset->nodeNr; i++) {
+ err = pcilib_xml_create_script_view(ctx, xpath, doc, nodeset->nodeTab[i]);
+ if (err) pcilib_error("Error (%i) creating script transform", err);
+ }
+ }
nodeset = transform_nodes->nodesetval;
if (!xmlXPathNodeSetIsEmpty(nodeset)) {
diff --git a/views/CMakeLists.txt b/views/CMakeLists.txt
index 0e0c20b..c060067 100644
--- a/views/CMakeLists.txt
+++ b/views/CMakeLists.txt
@@ -8,6 +8,6 @@ include_directories(
${UTHASH_INCLUDE_DIRS}
)
-set(HEADERS ${HEADERS} enum.h transform.h register.h)
+set(HEADERS ${HEADERS} enum.h transform.h register.h script.h)
-add_library(views STATIC enum.c transform.c register.c)
+add_library(views STATIC enum.c transform.c register.c script.c)
diff --git a/views/script.c b/views/script.c
new file mode 100644
index 0000000..50b31b5
--- /dev/null
+++ b/views/script.c
@@ -0,0 +1,157 @@
+#define _PCILIB_VIEW_TRANSFORM_C
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pci.h"
+#include "error.h"
+
+#include "model.h"
+#include "script.h"
+
+static int pcilib_script_view_read(pcilib_t *ctx, pcilib_view_context_t *view_ctx, pcilib_register_value_t regval, pcilib_value_t *val) {
+
+ int err;
+
+ const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
+ pcilib_script_view_description_t *v = (pcilib_script_view_description_t*)(model_info->views[view_ctx->view]);
+
+ //Initialize python script, if it has not initialized already.
+ if(!v->py_script_module)
+ {
+ if(!v->script_name)
+ {
+ pcilib_error("Invalid script name specified in XML property (NULL)");
+ return PCILIB_ERROR_INVALID_DATA;
+ }
+
+ //create path string to scripts
+ char* model_dir = getenv("PCILIB_MODEL_DIR");
+ char* model_path = malloc(strlen(model_dir) + strlen(ctx->model) + 2);
+ if (!model_path) return PCILIB_ERROR_MEMORY;
+ sprintf(model_path, "%s/%s", model_dir, ctx->model);
+
+ //set model path to python
+ PySys_SetPath(model_path);
+ free(model_path);
+ model_path = NULL;
+
+ //create path string to pcipywrap library
+ char* app_dir = getenv("APP_PATH");
+ char* pcipywrap_path;
+ if(app_dir)
+ {
+ pcipywrap_path = malloc(strlen(app_dir) + strlen("/pcilib"));
+ if (!pcipywrap_path) return PCILIB_ERROR_MEMORY;
+ sprintf(pcipywrap_path, "%s/%s", "/pcilib", ctx->model);
+ }
+ else
+ {
+ pcipywrap_path = malloc(strlen("./pcilib"));
+ if (!pcipywrap_path) return PCILIB_ERROR_MEMORY;
+ sprintf(pcipywrap_path, "%s", "./pcilib");
+
+ }
+
+ //set pcipywrap library path to python
+ PyObject* path = PySys_GetObject("path");
+ if(PyList_Append(path, PyString_FromString(pcipywrap_path)) == -1)
+ {
+ pcilib_error("Cant set pcipywrap library path to python.");
+ return PCILIB_ERROR_FAILED;
+ }
+ free(pcipywrap_path);
+ pcipywrap_path = NULL;
+
+
+ //extract module name from script name
+ char* py_module_name = strtok(v->script_name, ".");
+
+ if(!py_module_name)
+ {
+ pcilib_error("Invalid script name specified in XML property (%s)."
+ " Seems like name doesnt contains extension", v->script_name);
+ return PCILIB_ERROR_INVALID_DATA;
+ }
+
+ //import python script
+ v->py_script_module = PyImport_ImportModule(py_module_name);
+
+ if(!v->py_script_module)
+ {
+ printf("Error in import python module: ");
+ PyErr_Print();
+ return PCILIB_ERROR_INVALID_DATA;
+ }
+ }
+
+ //Initializing pcipywrap module if script use it
+ PyObject* dict = PyModule_GetDict(v->py_script_module);
+ if(PyDict_Contains(dict, PyString_FromString("pcipywrap")))
+ {
+ PyObject* pcipywrap_module = PyDict_GetItemString(dict, "pcipywrap");
+ if(!pcipywrap_module)
+ {
+ pcilib_error("Cant extract pcipywrap module from script dictionary");
+ return PCILIB_ERROR_FAILED;
+ }
+
+ //setting pcilib_t instance
+ PyObject_CallMethodObjArgs(pcipywrap_module,
+ PyUnicode_FromString("__setPcilib"),
+ PyByteArray_FromStringAndSize((const char*)&ctx, sizeof(pcilib_t*)),
+ NULL);
+ }
+
+
+ PyObject *ret = PyObject_CallMethod(v->py_script_module, "read_from_register", "()");
+ if (!ret)
+ {
+ printf("Python script error: ");
+ PyErr_Print();
+ return PCILIB_ERROR_FAILED;
+ }
+
+ if(PyInt_Check(ret))
+ {
+ err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(ret));
+ }
+ else
+ if(PyFloat_Check(ret))
+ err = pcilib_set_value_from_float(ctx, val, PyFloat_AsDouble(ret));
+ else
+ if(PyString_Check(ret))
+ err = pcilib_set_value_from_static_string(ctx, val, PyString_AsString(ret));
+ else
+ {
+ pcilib_error("Invalid return type in read_from_register() method. Return type should be int, float or string.");
+ return PCILIB_ERROR_NOTSUPPORTED;
+ }
+ if(err)
+ {
+ pcilib_error("Failed to convert python script return value to internal type: %i", err);
+ return err;
+ }
+ return 0;
+}
+
+
+void pcilib_script_view_free_description (pcilib_t *ctx, pcilib_view_description_t *view)
+{
+ pcilib_script_view_description_t *v = (pcilib_script_view_description_t*)(view);
+
+ if(v->script_name)
+ {
+ free(v->script_name);
+ v->script_name = NULL;
+ }
+
+ if(v->py_script_module)
+ {
+ PyObject_Free(v->py_script_module);
+ v->py_script_module = NULL;
+ }
+}
+
+const pcilib_view_api_description_t pcilib_script_view_api =
+ { PCILIB_VERSION, sizeof(pcilib_script_view_description_t), NULL, NULL, pcilib_script_view_free_description, pcilib_script_view_read, NULL};
diff --git a/views/script.h b/views/script.h
new file mode 100644
index 0000000..2929f4c
--- /dev/null
+++ b/views/script.h
@@ -0,0 +1,18 @@
+#ifndef _PCILIB_VIEW_SCRIPT_H
+#define _PCILIB_VIEW_SCRIPT_H
+
+#include <pcilib.h>
+#include <pcilib/view.h>
+#include <Python.h>
+
+typedef struct {
+ pcilib_view_description_t base;
+ PyObject *py_script_module; /**< PyModule object, contains script enviroment */
+ char* script_name;
+} pcilib_script_view_description_t;
+
+#ifndef _PCILIB_VIEW_SCRIPT_C
+const pcilib_view_api_description_t pcilib_script_view_api;
+#endif /* _PCILIB_VIEW_SCRIPT_C */
+
+#endif /* _PCILIB_VIEW_SCRIPT_H */
diff --git a/xml/CMakeLists.txt b/xml/CMakeLists.txt
index a7ac800..0b12d87 100644
--- a/xml/CMakeLists.txt
+++ b/xml/CMakeLists.txt
@@ -1,3 +1,30 @@
install(FILES model.xsd references.xsd types.xsd
DESTINATION ${PCILIB_MODEL_DIR}
)
+
+# Copy files from source directory to destination directory, substituting any
+# variables. Create destination directory if it does not exist.
+
+macro(configure_files srcDir destDir)
+ message(STATUS "Configuring directory ${destDir}")
+ make_directory(${destDir})
+
+ file(GLOB templateFiles RELATIVE ${srcDir} ${srcDir}/*)
+ foreach(templateFile ${templateFiles})
+ set(srcTemplatePath ${srcDir}/${templateFile})
+ if(NOT IS_DIRECTORY ${srcTemplatePath})
+ message(STATUS "Configuring file ${templateFile}")
+ configure_file(
+ ${srcTemplatePath}
+ ${destDir}/${templateFile}
+ @ONLY)
+ endif(NOT IS_DIRECTORY ${srcTemplatePath})
+ endforeach(templateFile)
+endmacro(configure_files)
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/model.xsd ${CMAKE_CURRENT_BINARY_DIR}/model.xsd)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/references.xsd ${CMAKE_CURRENT_BINARY_DIR}/references.xsd)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/types.xsd ${CMAKE_CURRENT_BINARY_DIR}/types.xsd)
+
+configure_files(${CMAKE_CURRENT_SOURCE_DIR}/test ${CMAKE_CURRENT_BINARY_DIR}/test)
+configure_files(${CMAKE_CURRENT_SOURCE_DIR}/test_pywrap ${CMAKE_CURRENT_BINARY_DIR}/test_pywrap)
diff --git a/xml/model.xsd b/xml/model.xsd
index 164e887..f6f5ea3 100644
--- a/xml/model.xsd
+++ b/xml/model.xsd
@@ -7,6 +7,7 @@
<xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element name="bank" type="pcilib_bank_t" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="transform" type="pcilib_transform_view_t" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="script" type="pcilib_script_view_t" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="enum" type="pcilib_enum_view_t" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="unit" type="pcilib_unit_t" minOccurs="0" maxOccurs="unbounded" />
</xsd:choice>
diff --git a/xml/references.xsd b/xml/references.xsd
index 4474141..523daa2 100644
--- a/xml/references.xsd
+++ b/xml/references.xsd
@@ -6,6 +6,7 @@
<xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element name="bank" type="pcilib_bank_t" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="transform" type="pcilib_transform_view_t" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="script" type="pcilib_script_view_t" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="enum" type="pcilib_enum_view_t" minOccurs="0" maxOccurs="unbounded">
<xsd:key name="pcilib_value_name_key">
<xsd:selector xpath="name" />
diff --git a/xml/test2/reg2.py b/xml/test2/reg2.py
deleted file mode 100644
index e69de29..0000000
--- a/xml/test2/reg2.py
+++ /dev/null
diff --git a/xml/test2/camera.xml b/xml/test_pywrap/camera.xml
index 4b31209..4b31209 100644
--- a/xml/test2/camera.xml
+++ b/xml/test_pywrap/camera.xml
diff --git a/xml/test2/names.xml b/xml/test_pywrap/names.xml
index f6ddbcc..f6ddbcc 100644
--- a/xml/test2/names.xml
+++ b/xml/test_pywrap/names.xml
diff --git a/xml/test2/props.xml b/xml/test_pywrap/props.xml
index f7a1329..137ad04 100644
--- a/xml/test2/props.xml
+++ b/xml/test_pywrap/props.xml
@@ -1,4 +1,14 @@
<?xml version="1.0"?>
<model xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<transform path="/test/prop1" register="test_prop1" unit="C" read_from_register="(503975./1024000)*${/registers/fpga/reg1} + 28715./100" description="formula to get real fpga temperature from the fpga_temperature register in decimal"/>
+ <script path="/test/prop2"
+ register="test_prop2"
+ unit="C"
+ script="test_prop2.py"
+ description="test python script #1"/>
+ <script path="/test/prop3"
+ register="test_prop3"
+ unit="C"
+ script="test_prop3.py"
+ description="test python script #2"/>
</model>
diff --git a/xml/test_pywrap/test_prop2.py b/xml/test_pywrap/test_prop2.py
new file mode 100644
index 0000000..e9a3364
--- /dev/null
+++ b/xml/test_pywrap/test_prop2.py
@@ -0,0 +1,7 @@
+import pcipywrap
+import os
+
+def read_from_register():
+ reg1_val = pcipywrap.read_register('reg1');
+ test_prop1_val = pcipywrap.read_register('test_prop3');
+ return test_prop1_val - reg1_val;
diff --git a/xml/test_pywrap/test_prop3.py b/xml/test_pywrap/test_prop3.py
new file mode 100644
index 0000000..c1300b3
--- /dev/null
+++ b/xml/test_pywrap/test_prop3.py
@@ -0,0 +1,4 @@
+import os
+
+def read_from_register():
+ return 10;
diff --git a/xml/test2/units.xml b/xml/test_pywrap/units.xml
index 74ab9f7..74ab9f7 100644
--- a/xml/test2/units.xml
+++ b/xml/test_pywrap/units.xml
diff --git a/xml/test2/views.xml b/xml/test_pywrap/views.xml
index c40cd0f..c40cd0f 100644
--- a/xml/test2/views.xml
+++ b/xml/test_pywrap/views.xml
diff --git a/xml/types.xsd b/xml/types.xsd
index 78be773..239df8d 100644
--- a/xml/types.xsd
+++ b/xml/types.xsd
@@ -74,6 +74,17 @@
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
+
+ <xsd:complexType name="pcilib_script_view_t">
+ <xsd:complexContent>
+ <xsd:extension base="pcilib_view_t">
+ <xsd:attribute name="path" type="xsd:string" />
+ <xsd:attribute name="register" type="xsd:string" />
+ <xsd:attribute name="script" type="xsd:string" />
+ <!-- xsd 1.1 <xsd:assert test="(@path and not(@name)) or (not(@path) and @name)"/> -->
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
<xsd:complexType name="pcilib_enum_view_t">
<xsd:complexContent>