Browse Source

1. pywrap:
- fix get_registers_list crash with bank != NULL
- set correct python version in cmake install step
2. html_server:
- merge set and get value boxes into one box
- add registers bank view mode
- read registers/properties values in bank/branch view mode
3. xml/test
- remove cmosis registers
- add multithread safe property example

Vasilii Chernov 8 years ago
parent
commit
e2550e6df1

+ 1 - 0
CMakeLists.txt

@@ -41,6 +41,7 @@ if (NOT DISABLE_PYTHON)
     find_package(PythonLibs 2.7 REQUIRED)
     find_package(SWIG REQUIRED)
     set(HAVE_PYTHON TRUE)
+    include(FindPythonInterp)
 endif (NOT DISABLE_PYTHON)
 
 set(EXTRA_SYSTEM_LIBS -lrt)

+ 32 - 11
html_server/html_server.py

@@ -13,7 +13,7 @@ from flask import send_from_directory
 app = Flask(__name__)
 pcilib = 0;
 device = '/dev/fpga0'
-model = 'test_pywrap'
+model = ''
 
 # property json api
 @app.route("/property_info_json")
@@ -113,10 +113,10 @@ def get_register_info():
    bank = request.args.get('bank')
    
    reg_info = 0
-   value = 0
+   value = dict()
    try:
       reg_info = pcilib.get_register_info(str(name), str(bank))
-      value = pcilib.read_register(str(name), str(bank))
+      value[name] = pcilib.read_register(str(name), str(bank))
    except Exception as e:
       return str(e)
    return render_template('register_info.html',
@@ -125,14 +125,29 @@ def get_register_info():
                              
 @app.route("/registers_list")
 def get_registers_list():
+   bank = request.args.get('bank')
+   if not bank is None:
+      bank = str(bank)
+      
    reg_list = 0
    try:
-      reg_list = pcilib.get_registers_list()
+      reg_list = pcilib.get_registers_list(bank)
    except Exception as e:
       return str(e)
+   
+   value = dict()
+   for reg in reg_list:
+      print reg
+      try:
+         value[reg['name']] = pcilib.read_register(str(reg['name']),
+                                                   str(reg['bank']))
+      except Exception as e:
+         value[reg['name']] = str(e)
 
    return render_template('registers_list.html',
-                          registers=reg_list,
+                          registers = reg_list,
+                          render_template = render_template,
+                          value = value
                          )
 
 @app.route("/property_info")
@@ -147,18 +162,26 @@ def get_property_list():
    except Exception as e:
       return str(e)
    
-   value = -1
+   value = dict()
    if (len(prop_info) == 1) and not ('childs' in (prop_info[0])['flags']):
       try:
          branch = (prop_info[0])['path']
-         value = pcilib.get_property(branch)
+         value[branch] = pcilib.get_property(branch)
       except Exception as e:
-         return str(e)
+         return str(e) 
+   else:
+      for prop in prop_info:
+         try:
+            path = prop['path']
+            value[path] = pcilib.get_property(path)
+         except Exception as e:
+            value[path] = str(e)
 
    return render_template('property_info.html',
                           value = value,
                           branch = branch,
-                          properties = prop_info
+                          properties = prop_info,
+                          json = json
                          )
                          
 @app.route("/")
@@ -187,8 +210,6 @@ if __name__ == "__main__":
    device = opts.device
    model = opts.model
    
-   app.debug = True
-   
    pcilib = pcipywrap.Pcipywrap(device, model)
    pcipywrap.__redirect_logs_to_exeption()
    app.run(host = HOST_NAME, port = PORT_NUMBER)

+ 4 - 0
html_server/static/check_err.js

@@ -0,0 +1,4 @@
+function checkError(json) {
+   if(json.error)
+      alert('Error: ' + json.error)
+} 

+ 34 - 20
html_server/templates/base.html

@@ -58,6 +58,37 @@
       function createRegistersList() {
          function parseJsonRegisterList(json) {
             
+            function loadRegistersList(bank) {
+               var pathToGetRegisterList = "{{ url_for('get_registers_list') }}"
+               var completePath = pathToGetRegisterList + '?bank=' + bank
+
+               $("#reg_info_place").load(completePath)
+            }
+
+            function loadRegisterInfo(bank, name) {
+               var pathToGetRegister = "{{ url_for('get_register_info') }}"
+               var completePath = pathToGetRegister + '?bank=' + bank +
+                              '&name=' + name
+
+               $("#reg_info_place").load(completePath)
+            }
+
+            function setRegisterField(id, bank, name) {
+               
+               var itemId = bank + "_" + name
+               var func = function(){loadRegisterInfo(bank, name)}
+               
+               regTree.insertNewItem(id, itemId, name, func)
+               regTree.closeAllItems()
+            }
+            
+            function setbankField(bank) {
+               
+               var func = function(){loadRegistersList(bank)}
+               regTree.insertNewItem(0, bank, bank, func);
+               regTree.closeAllItems()
+            }
+            
             checkError(json)
             if(json.lenght <= 0)
                return
@@ -86,28 +117,12 @@
                }
                
                if(!created) {
-                  regTree.insertNewItem(0, json[i].bank, json[i].bank, 0);
+                  setbankField(json[i].bank )
                   created = 1
                }
                
                
                //insert register info to bank
-               function loadRegisterInfo(bank, name) {
-                  var pathToGetProperty = "{{ url_for('get_register_info') }}"
-                  var completePath = pathToGetProperty + '?bank=' + bank +
-                                 '&name=' + name
-               
-                  $("#reg_info_place").load(completePath)
-               }
-               
-               function setRegisterField(id, bank, name) {
-                  
-                  var itemId = bank + "_" + name
-                  var func = function(){loadRegisterInfo(bank, name)}
-                  
-                  regTree.insertNewItem(id, itemId, name, func)
-                  regTree.closeAllItems()
-               }
                
                setRegisterField(json[i].bank, json[i].bank, json[i].name)
             }
@@ -121,12 +136,12 @@
 		function doOnLoad()
       {
 			propsTree = new dhtmlXTreeObject("treeboxbox_tree","100%","100%",0);
-			propsTree.setImagePath("codebase/imgs/dhxtree_skyblue/");
+			propsTree.setImagePath("{{ url_for('static', filename='codebase/imgs/dhxtree_skyblue/') }}");
          //generating properties list
          createPropertyTree('', 0)
          
 			regTree = new dhtmlXTreeObject("treeboxbox_tree2","100%","100%",0,0,0,0,'SELECT')
-			regTree.setImagePath("codebase/imgs/dhxtree_skyblue/");
+			regTree.setImagePath("{{ url_for('static', filename='codebase/imgs/dhxtree_skyblue/') }}");
          createRegistersList()
 		}
 	</script>
@@ -137,7 +152,6 @@
          <h2>Device {{ device }} model={{ model }} control page </h2>
       </div>
    {% endblock %}
-   
    <style>
       .tabs > div, .tabs > input { display: none; }
 

+ 14 - 16
html_server/templates/property_info.html

@@ -12,14 +12,14 @@
       
       $.getJSON(completePath, function(json){
                   checkError(json)
-                  var valFieldId = "#actVal"+prop.split('/').join("_")
-                  $(valFieldId).text(json.value)
+                  var valFieldId = "#set_val_" + prop.split('/').join("_")
+                  $(valFieldId).val(json.value)
                })
    }
    
    function setProperty(prop)
    {
-      var value = document.getElementById("set_val_" + prop).value;
+      var value = document.getElementById("set_val_" + prop.split('/').join("_")).value;
       if(value == "")
          return
       
@@ -34,7 +34,7 @@
                 })
    };
 </script>
-   
+
 <table class="infoTable">
    <tr class="infoTable">
       <td class="infoTable">Name</td>
@@ -55,24 +55,22 @@
          </td>
          <td class="infoTable">
             <table>
-               <tr>
-                  <td id = "actVal{{ property.path.replace('/', '_') }}" class="infoTable"> 
-                     {{ value }}
-                  </td>
-                  {% if 'R' in property.mode %}
-                  <td> 
-                     <input type="button" value="update" style="width:100%;height:100%" onclick="updateProperty('{{ property.path }}')">
-                  </td>
-                  {% endif %}
-               </tr>
-               {% if 'W' in property.mode %}
+               {% if 'R' in property.mode %}
                   <tr>
                      <td> 
-                           <input type="text" name="set_val_{{ property.path }}" id="set_val_{{ property.path }}" value="" />
+                           <input type="text"
+                                  name="set_val_{{ property.path.replace('/', '_') }}"
+                                  id="set_val_{{ property.path.replace('/', '_') }}"
+                                  value="{{ value[property.path] }}" />
                      </td>
+                     {% if 'W' in property.mode %}
                      <td> 
                            <input type="button" value="set" style="width:100%;height:100%" onclick="setProperty('{{ property.path }}')">
                      </td>
+                     {% endif %}
+                     <td> 
+                        <input type="button" value="update" style="width:100%;height:100%" onclick="updateProperty('{{ property.path }}')">
+                     </td>
                   </tr>
                {% endif %}
             </table>

+ 3 - 142
html_server/templates/register_info.html

@@ -1,148 +1,9 @@
 {% block content %}
 
-{% if standalone %}
-<script src="{{ url_for('static', filename='codebase/dhtmlx.js') }}"></script>
-<script src="{{ url_for('static', filename='check_err.js') }}"></script>
-{% endif %}
-
-<script>
-   function updateRegister(bank, name) {
-      var pathToReadRegister = "{{ url_for('read_register_json') }}"
-      var completePath = pathToReadRegister + '?bank=' + bank +
-                     '&name=' + name
-      
-      $.getJSON(completePath, function(json){
-                  checkError(json)
-                  $("#actVal").text(json.value)
-               })
-   }
-   
-   function writeRegister(bank, name)
-   {
-      var value = document.getElementById("set_val_box").value;
-      if(value == "")
-         return
-      
-      var pathToReadRegister = "{{ url_for('write_register_json') }}"
-      var completePath = pathToReadRegister + '?bank=' + bank +
-                     '&name=' + name + '&val=' + value;
-                        
-      $.getJSON(completePath, 
-                function(json) {
-                   checkError(json)
-                   updateRegister(bank, name)
-                })
-   }; 
-</script>
+{% include 'registers/table_scripts.html' %}
 
 <table class="infoTable">
-   <tr class="infoTable">
-      {% if 'description' in register %}
-      <td class="infoTable"> Description </td>
-      {% endif %}
-      <td class="infoTable"> Value </td>
-      <td class="infoTable">Default value</td>
-      <td class="infoTable">Bank</td>
-      <td class="infoTable">Mode</td>
-      {% if 'range' in register %}
-         <td class="infoTable">Range</td>
-      {% endif %}
-      {% if 'values' in register %}
-         <td class="infoTable">Values</td>
-      {% endif %}
-   </tr>
-   
-   <tr class="infoTable">
-      {% if 'description' in register %}
-         <td class="infoTable"> {{ register.description }} </td>
-      {% endif %}
-      <td class="infoTable">
-         <table>
-            <tr class="infoTable">
-               <td id="actVal" class="infoTable"> {{ value }} </td>
-               {% if 'R' in register.mode %}
-                  <td> 
-                     <input type="button" value="update"
-                            style="width:100%;height:100%"
-                            onclick="updateRegister('{{ register.bank }}', '{{ register.name }}')">
-                  </td>
-               {% endif %}
-            </tr>
-            {% if 'W' in register.mode %}
-               <tr class="infoTable">
-                  <td> 
-                     <input type="text" name="set_val_box" id="set_val_box" value="" />
-                  </td>
-                  <td> 
-                     <input type="button" value="set" 
-                            style="width:100%;height:100%" 
-                            onclick="writeRegister('{{ register.bank }}', '{{ register.name }}')">
-                  </td>
-               </tr>
-            {% endif %}
-         </table>
-      </td>
-      <td class="infoTable">{{ register.defvalue }}</td>
-      <td class="infoTable">{{ register.bank }}</td>
-      <td class="infoTable">
-         <ul>
-         {% for m in register.mode %}
-            {{ m + ';  '}}
-         {% endfor %}
-         </ul>
-      </td>
-      {% if 'range' in register %}
-         <td class="infoTable">
-            <table>
-               <tr class="infoTable">
-                  <td class="infoTable"> min </td>
-                  <td class="infoTable"> max </td>
-               </tr>
-               <tr class="infoTable">
-                  <td class="infoTable"> {{ register.range.min }} </td>
-                  <td class="infoTable"> {{ register.range.max }} </td>
-               </tr>
-            </table>
-         </td>
-      {% endif %}
-      {% if 'values' in register %}
-      <td class="infoTable">
-         <table>
-            <tr>
-            {% for v in register['values'] %}
-               <td>
-               <table>
-                  {% if 'name' in v %}
-                     <tr class="infoTable">
-                        <td class="infoTable"> Name </td>
-                        <td class="infoTable"> {{v.name}} </td>
-                     </tr>
-                  {% endif %}
-                  {% if 'description' in v %}
-                     <tr class="infoTable">
-                        <td class="infoTable"> Description </td>
-                        <td class="infoTable"> {{ v.description }} </td>
-                     </tr>
-                  {% endif %}
-                  <tr class="infoTable">
-                     <td class="infoTable"> Min </td>
-                     <td class="infoTable"> {{ v.min }} </td>
-                  </tr>
-                  <tr class="infoTable">
-                     <td class="infoTable"> Max </td>
-                     <td class="infoTable"> {{ v.max }} </td>
-                  </tr>
-                  <tr class="infoTable">
-                     <td class="infoTable"> Value </td>
-                     <td class="infoTable"> {{ v.value }} </td>
-                  </tr>
-               </table>
-               </td>
-            {% endfor %}
-            </tr>
-         </table>
-      </td>
-      {% endif %}
-   </tr>
+   {% include 'registers/table_header.html' %}
+   {% include 'registers/table_cell.html' %}
 </table>
 {% endblock %}

+ 99 - 0
html_server/templates/registers/table_cell.html

@@ -0,0 +1,99 @@
+<tr class="infoTable">
+   {% if 'description' in register %}
+      <td class="infoTable"> {{ register.description }} </td>
+   {% else %}
+      <td class="infoTable">  </td>
+   {% endif %}
+   <td class="infoTable">
+      <table>
+         {% if 'R' in register.mode %}
+         <tr class="infoTable">
+            <td> 
+                  <input type="text"
+                         name="set_val_box_{{ register.bank }}_{{ register.name }}"
+                         id="set_val_box_{{ register.bank }}_{{ register.name }}" 
+                         value="{{ value[register.name] }}" />
+            </td>
+            {% if 'W' in register.mode %}
+            <td> 
+               <input type="button" value="set"
+                      style="width:100%;height:100%" 
+                      onclick="writeRegister('{{ register.bank }}', '{{ register.name }}')">
+            </td>
+            {% endif %}
+            <td> 
+               <input type="button" value="update"
+                      style="width:100%;height:100%"
+                      onclick="updateRegister('{{ register.bank }}', '{{ register.name }}')">
+            </td>
+         </tr>
+         {% endif %}
+      </table>
+   </td>
+   <td class="infoTable">{{ register.defvalue }}</td>
+   <td class="infoTable">{{ register.bank }}</td>
+   <td class="infoTable">
+      <ul>
+      {% for m in register.mode %}
+         {{ m + ';  '}}
+      {% endfor %}
+      </ul>
+   </td>
+   {% if 'range' in register %}
+      <td class="infoTable">
+         <table>
+            <tr class="infoTable">
+               <td class="infoTable"> min </td>
+               <td class="infoTable"> max </td>
+            </tr>
+            <tr class="infoTable">
+               <td class="infoTable"> {{ register.range.min }} </td>
+               <td class="infoTable"> {{ register.range.max }} </td>
+            </tr>
+         </table>
+      </td>
+   {% else %}
+      <td class="infoTable">  </td>
+   {% endif %}
+   {% if 'values' in register %}
+   <td class="infoTable">
+      <table>
+         <tr>
+         {% for v in register['values'] %}
+            <td>
+            <table>
+               {% if 'name' in v %}
+                  <tr class="infoTable">
+                     <td class="infoTable"> Name </td>
+                     <td class="infoTable"> {{v.name}} </td>
+                  </tr>
+               {% endif %}
+               {% if 'description' in v %}
+                  <tr class="infoTable">
+                     <td class="infoTable"> Description </td>
+                     <td class="infoTable"> {{ v.description }} </td>
+                  </tr>
+               {% endif %}
+               <tr class="infoTable">
+                  <td class="infoTable"> Min </td>
+                  <td class="infoTable"> {{ v.min }} </td>
+               </tr>
+               <tr class="infoTable">
+                  <td class="infoTable"> Max </td>
+                  <td class="infoTable"> {{ v.max }} </td>
+               </tr>
+               <tr class="infoTable">
+                  <td class="infoTable"> Value </td>
+                  <td class="infoTable"> {{ v.value }} </td>
+               </tr>
+            </table>
+            </td>
+         {% endfor %}
+         </tr>
+      </table>
+   </td>
+   {% else %}
+      <td class="infoTable">  </td>
+   {% endif %}
+</tr>
+

+ 9 - 0
html_server/templates/registers/table_header.html

@@ -0,0 +1,9 @@
+<tr class="infoTable">
+      <td class="infoTable"> Description </td>
+      <td class="infoTable"> Value </td>
+      <td class="infoTable">Default value</td>
+      <td class="infoTable">Bank</td>
+      <td class="infoTable">Mode</td>
+      <td class="infoTable">Range</td>
+      <td class="infoTable">Values</td>
+</tr> 

+ 42 - 0
html_server/templates/registers/table_scripts.html

@@ -0,0 +1,42 @@
+{% if standalone %}
+<script src="{{ url_for('static', filename='codebase/dhtmlx.js') }}"></script>
+<script src="{{ url_for('static', filename='check_err.js') }}"></script>
+{% endif %}
+
+<script>
+   /*
+   $("#set_val_box").keyup(function(event){
+    if(event.keyCode == 13){
+        $("#set_val_button").click();
+    }
+   });
+   */
+   
+   function updateRegister(bank, name) {
+      var pathToReadRegister = "{{ url_for('read_register_json') }}"
+      var completePath = pathToReadRegister + '?bank=' + bank +
+                     '&name=' + name
+      
+      $.getJSON(completePath, function(json){
+                  checkError(json)
+                  $("#set_val_box_" + bank + "_" + name).val(json.value)
+               })
+   }
+   
+   function writeRegister(bank, name)
+   {
+      var value = document.getElementById("set_val_box_" + bank + "_" + name).value;
+      if(value == "")
+         return
+      
+      var pathToReadRegister = "{{ url_for('write_register_json') }}"
+      var completePath = pathToReadRegister + '?bank=' + bank +
+                     '&name=' + name + '&val=' + value;
+                        
+      $.getJSON(completePath, 
+                function(json) {
+                   checkError(json)
+                   updateRegister(bank, name)
+                })
+   }; 
+</script> 

+ 5 - 19
html_server/templates/registers_list.html

@@ -1,24 +1,10 @@
-{% extends "base.html" %}
-{% block title %}Registers list{% endblock %}
-{% block info %}
-<h1>List of aviable registers</h1>
-{% endblock %}
-
 {% block content %}
-<table border="1" style="width:100%">
-   <tr>
-    <th>Name</th>
-    <th>Description</th> 
-  </tr>
+{% include 'registers/table_scripts.html' %}
+
+<table class="infoTable">
+{% include 'registers/table_header.html' %}
 {% for register in registers %}
-   <tr>
-      <td><a href="{{ url_for('get_register_info', bank=register.bank, name=register.name) }}">{{ register.name }}</td>
-      {% if 'description' in register %}
-         <td>{{ register.description }}</td>
-      {% else %}
-         <td></td>
-      {% endif %}
-   </tr>
+   {% include 'registers/table_cell.html' %}
 {% endfor %}
 </table>
 {% endblock %}

+ 1 - 1
pywrap/CMakeLists.txt

@@ -19,7 +19,7 @@ swig_add_module(pcipywrap python pcipywrap.i pcipywrap.c)
 swig_link_libraries(pcipywrap ${PYTHON_LIBRARIES} pcilib)
 
 #install pcilib python wrapper into Python site packages folder
-execute_process ( COMMAND python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
+execute_process ( COMMAND python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
 install(TARGETS ${SWIG_MODULE_pcipywrap_REAL_NAME} DESTINATION ${PYTHON_SITE_PACKAGES})
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pcipywrap.py DESTINATION ${PYTHON_SITE_PACKAGES})
 

+ 17 - 12
pywrap/pcipywrap.c

@@ -458,17 +458,22 @@ PyObject* Pcipywrap_set_property(Pcipywrap *self, PyObject* val, const char *pro
 
 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);
-        //Py_DECREF(pylistItem);
-    }
-    pcilib_free_register_info(self->ctx, list);
-    return pyList;
+   pcilib_register_info_t *list = pcilib_get_register_list(self->ctx, bank, PCILIB_LIST_FLAGS_DEFAULT);
+
+   if(!list) {
+      set_python_exception("pcilib_get_register_list return NULL");
+      return NULL;
+   }
+
+   PyObject* pyList = PyList_New(0);
+   for(int i = 0; list[i].name; 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)
@@ -551,7 +556,7 @@ PyObject* Pcipywrap_lock(Pcipywrap *self, const char *lock_id)
    pcilib_lock_t* lock = pcilib_get_lock(self->ctx,
 										  PCILIB_LOCK_FLAGS_DEFAULT,
 										  lock_id);
-    if(!lock)
+   if(!lock)
 	{
 		set_python_exception("Failed pcilib_get_lock");
 		return NULL;

+ 1 - 1
pywrap/pcipywrap.h

@@ -74,7 +74,7 @@ void Pcipywrap_unlock_global(Pcipywrap *self);
  * \brief Wrap for pcilib_lock
  * \param lock_id lock identificator
  * \warning This function should be called only under Python standart threading lock.
- * Otherwise it will stuck with more than 1 threads. See /xml/test_pywrap/test_prop_mt.py
+ * Otherwise it will stuck with more than 1 threads. See /xml/test/test_prop_mt.py
  * for example.
  * \return 1, serialized to PyObject or NULL with exeption text, if failed.
  */

+ 0 - 50
xml/test/cmosis.xml

@@ -1,50 +0,0 @@
-<?xml version="1.0"?>
-<model xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-  <bank bar="0" size="128" protocol="software_registers" read_address="0x9010" write_address="0x9000" word_size="8" endianess="little" format="%lu" name="cmosis" description="CMOSIS CMV2000 Registers">
-    <register address="1" offset="0" size="16" default="1088" rwmask="0" mode="RW" name="cmosis_number_lines" description="test"/>
-    <register address="3" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start1"/>
-    <register address="5" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start2"/>
-    <register address="7" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start3"/>
-    <register address="9" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start4"/>
-    <register address="11" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start5"/>
-    <register address="13" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start6"/>
-    <register address="15" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start7"/>
-    <register address="17" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start8"/>
-    <register address="19" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines1"/>
-    <register address="21" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines2"/>
-    <register address="23" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines3"/>
-    <register address="25" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines4"/>
-    <register address="27" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines5"/>
-    <register address="29" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines6"/>
-    <register address="31" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines7"/>
-    <register address="33" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines8"/>
-    <register address="35" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_sub_s"/>
-    <register address="37" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_sub_a"/>
-    <register address="39" offset="0" size="1" default="1" rwmask="0" mode="RW" name="cmosis_color"/>
-    <register address="40" offset="0" size="2" default="0" rwmask="0" mode="RW" name="cmosis_image_flipping"/>
-    <register address="41" offset="0" size="2" default="0" rwmask="0" mode="RW" name="cmosis_exp_flags"/>
-    <register address="42" offset="0" size="24" default="1088" rwmask="0" mode="RW" name="cmosis_exp_time"><view view="formuu3"/><view view="enumm3"/></register>
-    <register address="45" offset="0" size="24" default="1088" rwmask="0" mode="RW" name="cmosis_exp_step"/>
-    <register address="48" offset="0" size="24" default="1" rwmask="0" mode="RW" name="cmosis_exp_kp1"/>
-    <register address="51" offset="0" size="24" default="1" rwmask="0" mode="RW" name="cmosis_exp_kp2"/>
-    <register address="54" offset="0" size="2" default="1" rwmask="0" mode="RW" name="cmosis_nr_slopes"/>
-    <register address="55" offset="0" size="8" default="1" rwmask="0" mode="RW" name="cmosis_exp_seq"/>
-    <register address="56" offset="0" size="24" default="1088" rwmask="0" mode="RW" name="cmosis_exp_time2"/>
-    <register address="59" offset="0" size="24" default="1088" rwmask="0" mode="RW" name="cmosis_exp_step2"/>
-    <register address="68" offset="0" size="2" default="1" rwmask="0" mode="RW" name="cmosis_nr_slopes2"/>
-    <register address="69" offset="0" size="8" default="1" rwmask="0" mode="RW" name="cmosis_exp_seq2"/>
-    <register address="70" offset="0" size="16" default="1" rwmask="0" mode="RW" name="cmosis_number_frames"/>
-    <register address="72" offset="0" size="2" default="0" rwmask="0" mode="RW" name="cmosis_output_mode"/>
-    <register address="78" offset="0" size="12" default="85" rwmask="0" mode="RW" name="cmosis_training_pattern"/>
-    <register address="80" offset="0" size="18" default="0x3FFFF" rwmask="0" mode="RW" name="cmosis_channel_en"/>
-    <register address="82" offset="0" size="3" default="7" rwmask="0" mode="RW" name="cmosis_special_82"/>
-    <register address="89" offset="0" size="8" default="96" rwmask="0" mode="RW" name="cmosis_vlow2"/>
-    <register address="90" offset="0" size="8" default="96" rwmask="0" mode="RW" name="cmosis_vlow3"/>
-    <register address="100" offset="0" size="14" default="16260" rwmask="0" mode="RW" name="cmosis_offset"/>
-    <register address="102" offset="0" size="2" default="0" rwmask="0" mode="RW" name="cmosis_pga"/>
-    <register address="103" offset="0" size="8" default="32" rwmask="0" mode="RW" name="cmosis_adc_gain"/>
-    <register address="111" offset="0" size="1" default="1" rwmask="0" mode="RW" name="cmosis_bit_mode"/>
-    <register address="112" offset="0" size="2" default="0" rwmask="0" mode="RW" name="cmosis_adc_resolution"/>
-    <register address="115" offset="0" size="1" default="1" rwmask="0" mode="RW" name="cmosis_special_115"/>
-  </bank>
-</model>

+ 6 - 1
xml/test/props.xml

@@ -1,6 +1,11 @@
 <?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) - 27315./100" description="formula to get real fpga temperature from the fpga_temperature register in decimal"/>
+  <transform path="/test/prop1" register="test_prop1" unit="C" read_from_register="(503975./1024000)*${/registers/fpga/fpga_temperature} + 28715./100" description="formula to get real fpga temperature from the fpga_temperature register in decimal"/>
   <transform path="/test/prop2" register="test_prop2" unit="C" script="test_prop2.py" description="test python script #1" write_verification="0" />
   <transform path="/test/prop3" register="test_prop3" unit="C" script="test_prop3.py" description="test python script #2" />
+  <transform path="/test/prop_mt"
+	  register="test_prop_mt"
+	  unit="C"
+	  script="test_prop_mt.py"
+	  description="Example of thread safe python property"/>
 </model>

+ 24 - 0
xml/test/test_prop_mt.py

@@ -0,0 +1,24 @@
+import time
+import threading
+lock = threading.Lock()
+
+def read_from_register(ctx, value):
+   with lock:
+      ctx.lock('lock5')
+      
+      cur = read_from_register.counter
+      read_from_register.counter += 1
+      for i in range (0, 5):
+         time.sleep(0.1)
+         print cur
+      out = ctx.get_property('/test/prop3') / 2
+      ctx.unlock('lock5')
+      
+      return out
+      
+      
+read_from_register.counter = 0
+    
+def write_to_register(ctx, value):
+   with lock:
+      ctx.set_property(value*2, '/test/prop3')