From e10e102b8b0ff3bf35f16b5276d56059d242e1fd Mon Sep 17 00:00:00 2001 From: Vasilii Chernov Date: Mon, 8 Feb 2016 11:55:33 +0100 Subject: Add support for setting register value to script transfrom. Add set_property and get_property functions to pcipywrap. Cleaning cmakelists from unused dependencies --- pcilib/CMakeLists.txt | 8 +- pcilib/pcipywrap.c | 210 +++++++++++++++++++++++++++++++++++++++----------- pcilib/pcipywrap.i | 4 +- pcilib/xml.c | 60 +++++++++++---- 4 files changed, 215 insertions(+), 67 deletions(-) (limited to 'pcilib') diff --git a/pcilib/CMakeLists.txt b/pcilib/CMakeLists.txt index db74775..41a1169 100644 --- a/pcilib/CMakeLists.txt +++ b/pcilib/CMakeLists.txt @@ -8,8 +8,8 @@ include_directories( ${UTHASH_INCLUDE_DIRS} ) -set(HEADERS pcilib.h pci.h datacpy.h memcpy.h pagecpy.h cpu.h timing.h export.h value.h bar.h fifo.h model.h bank.h register.h view.h property.h unit.h xml.h py.h kmem.h irq.h locking.h lock.h dma.h event.h plugin.h tools.h error.h debug.h env.h version.h config.h) -add_library(pcilib SHARED 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 ) +set(HEADERS pcilib.h pci.h pcipywrap.h datacpy.h memcpy.h pagecpy.h cpu.h timing.h export.h value.h bar.h fifo.h model.h bank.h register.h view.h property.h unit.h xml.h py.h kmem.h irq.h locking.h lock.h dma.h event.h plugin.h tools.h error.h debug.h env.h version.h config.h) +add_library(pcilib SHARED pci.c pcipywrap.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 ) target_link_libraries(pcilib dma protocols views ${CMAKE_THREAD_LIBS_INIT} ${UFODECODE_LIBRARIES} ${CMAKE_DL_LIBS} ${EXTRA_SYSTEM_LIBS} ${LIBXML2_LIBRARIES} ${PYTHON_LIBRARIES}) add_dependencies(pcilib dma protocols views) @@ -22,8 +22,8 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) 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}) +SWIG_ADD_MODULE(pcipywrap python pcipywrap.i) +SWIG_LINK_LIBRARIES(pcipywrap ${PYTHON_LIBRARIES} pcilib) install(TARGETS pcilib LIBRARY DESTINATION lib${LIB_SUFFIX} diff --git a/pcilib/pcipywrap.c b/pcilib/pcipywrap.c index efce909..bed4b31 100644 --- a/pcilib/pcipywrap.c +++ b/pcilib/pcipywrap.c @@ -1,7 +1,6 @@ -#include "pcilib.h" -#include #include "pci.h" #include "error.h" +#include "pcipywrap.h" /*! * \brief Global pointer to pcilib_t context. @@ -24,16 +23,46 @@ PyObject* __createPcilibInstance(const char *fpga_device, const char *model) return PyByteArray_FromStringAndSize((const char*)&ctx, sizeof(pcilib_t*)); } +/*! + * \brief Sets python exeption text. Function interface same as printf. + */ +void setPyExeptionText(const char* msg, ...) +{ + char *buf; + size_t sz; + + va_list vl, vl_copy; + va_start(vl, msg); + va_copy(vl_copy, vl); + + sz = vsnprintf(NULL, 0, msg, vl); + buf = (char *)malloc(sz + 1); + + if(!buf) + { + PyErr_SetString(PyExc_Exception, "Memory error"); + return; + } + + vsnprintf(buf, sz+1, msg, vl_copy); + va_end(vl_copy); + va_end(vl); + + PyErr_SetString(PyExc_Exception, buf); + free(buf); +} + /*! * \brief Sets pcilib context to wraper. * \param[in] addr Pointer to pcilib_t, serialized to bytearray + * \return true, serialized to PyObject, NULL with exeption text, if failed. */ -void __setPcilib(PyObject* addr) +PyObject* __setPcilib(PyObject* addr) { if(!PyByteArray_Check(addr)) { - PyErr_SetString(PyExc_Exception, "Incorrect addr type. Only bytearray is allowed"); - return NULL; + setPyExeptionText(PyExc_Exception, "Incorrect addr type. Only bytearray is allowed"); + return; } //deserializing adress @@ -44,8 +73,82 @@ void __setPcilib(PyObject* addr) ((char*)&__ctx)[i] = pAddr[i]; free(pAddr); + + return PyInt_FromLong((long)1); } +PyObject* pcilib_convert_val_to_pyobject(pcilib_t* ctx, pcilib_value_t *val, void (*errstream)(const char* msg, ...)) +{ + int err; + + switch(val->type) + { + case PCILIB_TYPE_INVALID: + errstream("Invalid register output type (PCILIB_TYPE_INVALID)"); + return NULL; + + case PCILIB_TYPE_STRING: + errstream("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) + { + errstream("Failed: pcilib_get_value_as_int (%i)", err); + return NULL; + } + return PyInt_FromLong((long) ret); + } + + case PCILIB_TYPE_DOUBLE: + { + double ret; + ret = pcilib_get_value_as_float(__ctx, val, &err); + + if(err) + { + errstream("Failed: pcilib_get_value_as_int (%i)", err); + return NULL; + } + return PyFloat_FromDouble((double) ret); + } + + default: + errstream("Invalid register output type (unknown)"); + return NULL; + } +} + +int pcilib_convert_pyobject_to_val(pcilib_t* ctx, PyObject* pyVal, pcilib_value_t *val) +{ + int err; + + if(PyInt_Check(pyVal)) + { + err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(pyVal)); + } + else + if(PyFloat_Check(pyVal)) + err = pcilib_set_value_from_float(ctx, val, PyFloat_AsDouble(pyVal)); + else + if(PyString_Check(pyVal)) + err = pcilib_set_value_from_static_string(ctx, val, PyString_AsString(pyVal)); + else + { + pcilib_error("Invalid input. Input type should be int, float or string."); + return PCILIB_ERROR_NOTSUPPORTED; + } + if(err) + return err; + + return 0; +} + + /*! * \brief Reads register value. * \param[in] regname the name of the register @@ -53,10 +156,10 @@ void __setPcilib(PyObject* addr) * \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"); + setPyExeptionText("pcilib_t handler not initialized"); return NULL; } @@ -70,56 +173,69 @@ PyObject* read_register(const char *regname, const char *bank) err = pcilib_read_register(__ctx, bank, regname, ®_value); if(err) { - PyErr_SetString(PyExc_Exception, "Failed: read_register"); + setPyExeptionText("Failed: read_register (%i)", err); 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"); + setPyExeptionText("Failed: pcilib_set_value_from_register_value (%i)", err); return NULL; } - switch(val.type) + return pcilib_convert_val_to_pyobject(__ctx, &val, setPyExeptionText); +} + + +PyObject* get_property(const char *prop) +{ + if(!__ctx) { - 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); - } - - 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)"); + setPyExeptionText("pcilib_t handler not initialized"); + return NULL; + } + + int err; + pcilib_value_t val = {0}; + + err = pcilib_get_property(__ctx, prop, &val); + + if(err) + { + setPyExeptionText("Failed pcilib_get_property (%i)", err); return NULL; } + + return pcilib_convert_val_to_pyobject(__ctx, &val, setPyExeptionText); +} + +PyObject* set_property(const char *prop, PyObject* val) +{ + int err; + + if(!__ctx) + { + setPyExeptionText("pcilib_t handler not initialized"); + return NULL; + } + + pcilib_value_t val_internal = {0}; + err = pcilib_convert_pyobject_to_val(__ctx, val, &val_internal); + if(err) + { + setPyExeptionText("pcilib_convert_pyobject_to_val (%i)", err); + return NULL; + } + + err = pcilib_set_property(__ctx, prop, &val_internal); + + if(err) + { + setPyExeptionText("Failed pcilib_get_property (%i)", err); + return NULL; + } + + return PyInt_FromLong((long)1); } + diff --git a/pcilib/pcipywrap.i b/pcilib/pcipywrap.i index ed5ca62..8d0f74e 100644 --- a/pcilib/pcipywrap.i +++ b/pcilib/pcipywrap.i @@ -2,4 +2,6 @@ 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); +extern PyObject* __setPcilib(PyObject* addr); +extern PyObject* get_property(const char *prop); +extern PyObject* set_property(const char *prop, PyObject* val); diff --git a/pcilib/xml.c b/pcilib/xml.c index 76ed38c..2384e95 100644 --- a/pcilib/xml.c +++ b/pcilib/xml.c @@ -50,7 +50,6 @@ #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 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 */ @@ -575,8 +574,9 @@ static int pcilib_xml_create_script_view(pcilib_t *ctx, xmlXPathContextPtr xpath //write script name to struct desc.script_name = malloc(strlen(value)); sprintf(desc.script_name, "%s", value); - //set read access + //set read write access mode |= PCILIB_ACCESS_R; + mode |= PCILIB_ACCESS_W; } } @@ -589,7 +589,6 @@ static int pcilib_xml_create_script_view(pcilib_t *ctx, xmlXPathContextPtr xpath return 0; } - static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { int err; xmlAttrPtr cur; @@ -644,6 +643,46 @@ static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xp return 0; } +static int pcilib_xml_create_script_or_transform_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { + int err; + xmlAttrPtr cur; + const char *name; + + int has_read_from_register = 0; + int has_write_to_register = 0; + int has_script = 0; + + //getting transform name in case of error + pcilib_view_description_t desc = {0}; + err = pcilib_xml_parse_view(ctx, xpath, doc, node, &desc); + + for (cur = node->properties; cur != NULL; cur = cur->next) { + if (!cur->children) continue; + if (!xmlNodeIsText(cur->children)) continue; + + name = (char*)cur->name; + + if (!strcasecmp(name, "read_from_register")) + has_read_from_register = 1; + if (!strcasecmp(name, "write_to_register")) + has_write_to_register = 1; + if (!strcasecmp(name, "script")) + has_script = 1; + } + + if (has_script && (has_read_from_register || has_write_to_register)) { + pcilib_error("Invalid transform group attributes specified in XML property (%s)." + "Transform could not contains both script and read_from_register" + " or write_to_register attributes at same time.", desc.name); + return PCILIB_ERROR_INVALID_DATA; + } + + if(has_script) + return pcilib_xml_create_script_view(ctx, xpath, doc, node); + else + return pcilib_xml_create_transform_view(ctx, xpath, doc, node); +} + static int pcilib_xml_parse_value_name(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_register_value_name_t *desc) { xmlAttr *cur; @@ -869,14 +908,13 @@ 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, script_nodes = NULL; + xmlXPathObjectPtr bank_nodes = NULL, transform_nodes = NULL, enum_nodes = NULL, unit_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) script_nodes = xmlXPathEvalExpression(SCRIPT_VIEWS_PATH, xpath); - if (script_nodes) enum_nodes = xmlXPathEvalExpression(ENUM_VIEWS_PATH, xpath); + if (transform_nodes) enum_nodes = xmlXPathEvalExpression(ENUM_VIEWS_PATH, xpath); if (enum_nodes) unit_nodes = xmlXPathEvalExpression(UNITS_PATH, xpath); @@ -899,19 +937,11 @@ 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)) { for(i=0; i < nodeset->nodeNr; i++) { - err = pcilib_xml_create_transform_view(ctx, xpath, doc, nodeset->nodeTab[i]); + err = pcilib_xml_create_script_or_transform_view(ctx, xpath, doc, nodeset->nodeTab[i]); if (err) pcilib_error("Error (%i) creating register transform", err); } } -- cgit v1.2.3