ソースを参照

Add support for python script properties. Correct pcilib python wrapping. Update examples. Update cmakelists for work in shadow build mode.

Vasilii Chernov 8 年 前
コミット
5349163e93

+ 5 - 1
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

+ 0 - 1
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}

+ 103 - 168
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;
 }

+ 4 - 5
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);

+ 0 - 1
pcilib/py.c

@@ -5,7 +5,6 @@
 #include <string.h>
 #include <strings.h>
 
-
 #include "pci.h"
 #include "debug.h"
 #include "pcilib.h"

+ 61 - 4
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)) {

+ 2 - 2
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)

+ 157 - 0
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};

+ 18 - 0
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 */

+ 27 - 0
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)

+ 1 - 0
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>

+ 1 - 0
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" />

+ 0 - 0
xml/test2/reg2.py


+ 0 - 0
xml/test2/camera.xml → xml/test_pywrap/camera.xml


+ 0 - 0
xml/test2/names.xml → xml/test_pywrap/names.xml


+ 10 - 0
xml/test2/props.xml → 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>

+ 7 - 0
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;

+ 4 - 0
xml/test_pywrap/test_prop3.py

@@ -0,0 +1,4 @@
+import os
+    
+def read_from_register(): 
+    return 10;

+ 0 - 0
xml/test2/units.xml → xml/test_pywrap/units.xml


+ 0 - 0
xml/test2/views.xml → xml/test_pywrap/views.xml


+ 11 - 0
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>