py_ext/PythonFileCTNMixin.py
changeset 1144 21475ee0e688
parent 1132 28f96aa9c070
child 1145 203f4eff3313
equal deleted inserted replaced
1143:59818c488ead 1144:21475ee0e688
    53                getattr(self.CodeFile, section).gettext() + "\n" + \
    53                getattr(self.CodeFile, section).gettext() + "\n" + \
    54                self.PostSectionsTexts.get(section,"")
    54                self.PostSectionsTexts.get(section,"")
    55         
    55         
    56 
    56 
    57     def CTNGenerate_C(self, buildpath, locations):
    57     def CTNGenerate_C(self, buildpath, locations):
    58         current_location = self.GetCurrentLocation()
    58         # location string for that CTN 
    59         # define a unique name for the generated C file
    59         location_str = "_".join(map(lambda x:str(x), 
    60         location_str = "_".join(map(lambda x:str(x), current_location))
    60                                 self.GetCurrentLocation()))
    61         
    61         configname = self.GetCTRoot().GetProjectConfigNames()[0]
    62         
    62         
    63         # Generate Beremiz python runtime variables code
    63         
    64         config = self.GetCTRoot().GetProjectConfigNames()[0]
    64         # python side PLC global variables access stub
    65         variables_str = ""
    65         globalstubs = "\n".join(["""\
    66         for variable in self.CodeFile.variables.variable:
    66 _%(name)s_ctype, _%(name)s_unpack, _%(name)s_pack = \\
    67             global_name = "%s_%s" % (config.upper(), variable.getname().upper())
    67     TypeTranslator["%(IECtype)s"]
    68             variables_str += "# global_var:%s python_var:%s type:%s initial:%s\n" % (
    68 _PySafeGetPLCGlob_%(name)s = PLCBinary.__SafeGetPLCGlob_%(name)s
    69                 global_name,
    69 _PySafeGetPLCGlob_%(name)s.restype = _%(name)s_ctype 
    70                 variable.getname(),
    70 _PySafeGetPLCGlob_%(name)s.argtypes = []
    71                 variable.gettype(),
    71 _PySafeSetPLCGlob_%(name)s = PLCBinary.__SafeSetPLCGlob_%(name)s
    72                 str(variable.getinitial()))
    72 _PySafeSetPLCGlob_%(name)s.restype = None
       
    73 _PySafeSetPLCGlob_%(name)s.argtypes = [ctypes.POINTER(_%(name)s_ctype)]
       
    74 """ % { "name": variable.getname(),
       
    75         "configname": configname.upper(),
       
    76         "uppername": variable.getname().upper(),
       
    77         "IECtype": variable.gettype(),
       
    78         "initial" : str(variable.getinitial())}
       
    79             for variable in self.CodeFile.variables.variable])
    73 
    80 
    74         # Runtime calls (start, stop, init, and cleanup)
    81         # Runtime calls (start, stop, init, and cleanup)
    75         rtcalls = ""
    82         rtcalls = ""
    76         for section in self.SECTIONS_NAMES:
    83         for section in self.SECTIONS_NAMES:
    77             if section != "globals":
    84             if section != "globals":
    80                 if sectiontext:
    87                 if sectiontext:
    81                     rtcalls += '    ' + \
    88                     rtcalls += '    ' + \
    82                         sectiontext.strip().replace('\n', '\n    ')+"\n"
    89                         sectiontext.strip().replace('\n', '\n    ')+"\n"
    83                 else:
    90                 else:
    84                     rtcalls += "    pass\n\n"
    91                     rtcalls += "    pass\n\n"
    85         
    92 
    86         text = """\
    93         globalsection = self.GetSection("globals")      
       
    94 
       
    95         PyFileContent = """\
    87 #!/usr/bin/env python
    96 #!/usr/bin/env python
    88 # -*- coding: utf-8 -*-
    97 # -*- coding: utf-8 -*-
    89 ## Code generated by Beremiz python mixin confnode
    98 ## Code generated by Beremiz python mixin confnode
    90 ##        
    99 ##        
    91         
   100         
    92 ## Code for PLC global variable access
   101 ## Code for PLC global variable access
    93 %s
   102 from targets.typemapping import TypeTranslator
       
   103 import ctypes 
       
   104 %(globalstubs)s
    94         
   105         
    95 ## User code in "global" scope
   106 ## User code in "global" scope
    96 %s
   107 %(globalsection)s
    97 
   108 
    98 ## Beremiz python runtime calls
   109 ## Beremiz python runtime calls
    99 %s
   110 %(rtcalls)s
   100 
   111 
   101 """%(   # variables
   112 """ % locals()
   102         variables_str,
   113 
   103         # globals
   114         # write generated content to python file
   104         self.GetSection("globals"),
       
   105         # Beremiz python runtime functions
       
   106         rtcalls)
       
   107 
       
   108         runtimefile_path = os.path.join(buildpath, 
   115         runtimefile_path = os.path.join(buildpath, 
   109             "runtime_%s.py"%location_str)
   116             "runtime_%s.py"%location_str)
   110         runtimefile = open(runtimefile_path, 'w')
   117         runtimefile = open(runtimefile_path, 'w')
   111         runtimefile.write(text.encode('utf-8'))
   118         runtimefile.write(PyFileContent.encode('utf-8'))
   112         runtimefile.close()
   119         runtimefile.close()
   113 
   120 
   114         text = """\
   121         # C code for safe global variables access
       
   122         
       
   123         vardecfmt = """\
       
   124 extern  __%(IECtype)s_t %(configname)s__%(uppername)s;
       
   125 %(IECtype)s __%(name)s_rbuffer = %(initial)s;
       
   126 %(IECtype)s __%(name)s_wbuffer;
       
   127 long __%(name)s_rlock = 0;
       
   128 long __%(name)s_wlock = 0;
       
   129 int __%(name)s_wbuffer_written = 0;
       
   130 %(IECtype)s __SafeGetPLCGlob_%(name)s(){
       
   131     %(IECtype)s res;
       
   132     while(AtomicCompareExchange(&__%(name)s_rlock, 0, 1));
       
   133     res = __%(name)s_rbuffer;
       
   134     AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0);
       
   135     return res;
       
   136 }
       
   137 __SafeSetPLCGlob_%(name)s(%(IECtype)s *value){
       
   138     while(AtomicCompareExchange(&__%(name)s_wlock, 0, 1));
       
   139     __%(name)s_wbuffer = *value;
       
   140     __%(name)s_wbuffer_written = 1;
       
   141     AtomicCompareExchange((long*)&__%(name)s_wlock, 1, 0);
       
   142 }
       
   143 
       
   144 """
       
   145         varretfmt = """\
       
   146     if(!AtomicCompareExchange(&__%(name)s_wlock, 0, 1)){
       
   147         if(__%(name)s_wbuffer_written == 1){
       
   148             %(configname)s__%(uppername)s.value = __%(name)s_wbuffer;
       
   149             __%(name)s_wbuffer_written = 0;
       
   150         }
       
   151         AtomicCompareExchange((long*)&__%(name)s_wlock, 1, 0);
       
   152     }
       
   153 """ 
       
   154         varpubfmt = """\
       
   155     if(!AtomicCompareExchange(&__%(name)s_rlock, 0, 1)){
       
   156         __%(name)s_rbuffer = %(configname)s__%(uppername)s.value;
       
   157         AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0);
       
   158     }
       
   159 """ 
       
   160 
       
   161         vardec, varret, varpub = map("\n".join, zip(*[
       
   162             map(lambda f : f % varinfo,
       
   163                 (vardecfmt, varretfmt, varpubfmt))
       
   164                 for varinfo in map(lambda variable : {
       
   165                     "name": variable.getname(),
       
   166                     "configname": configname.upper(),
       
   167                     "uppername": variable.getname().upper(),
       
   168                     "IECtype": "IEC_%s"%variable.gettype(),
       
   169                     "initial" : str(variable.getinitial())},
       
   170                     self.CodeFile.variables.variable)]))
       
   171         
       
   172         PyCFileContent = """\
   115 /* 
   173 /* 
   116  * Code generated by Beremiz py_ext confnode 
   174  * Code generated by Beremiz py_ext confnode 
   117  * for safe global variables access
   175  * for safe global variables access
   118  */
   176  */
   119 #include "iec_types_all.h"
   177 #include "iec_types_all.h"
   120 """
   178 #include "beremiz.h"
   121         
   179 
   122         # Adding variables
   180 /* User variables reference */
   123         text += "/* User variables reference */\n"
   181 %(vardec)s
   124         for variable in self.CodeFile.variables.variable:
   182 
   125             var_infos = {
   183 /* Beremiz confnode functions */
   126                 "name": variable.getname(),
   184 int __init_%(location_str)s(int argc,char **argv){
   127                 "global": "%s__%s" % (config.upper(),
   185     return 0;
   128                                       variable.getname().upper()),
   186 }
   129                 "type": "__IEC_%s_t" % variable.gettype()}
   187 
   130             text += "extern %(type)s %(global)s;\n" % var_infos
   188 void __cleanup_%(location_str)s(void){
   131             text += "%(type)s __buffer_%(name)s;\n" % var_infos
   189 }
   132         text += "\n"
   190 
   133         
   191 void __retrieve_%(location_str)s(void){
   134         # Adding Beremiz confnode functions
   192 %(varret)s
   135         text += "/* Beremiz confnode functions */\n"
   193 }
   136         text += "int __init_%s(int argc,char **argv)\n{\n"%location_str
   194 
   137         text += "/*TODO*/\n"
   195 void __publish_%(location_str)s(void){
   138         text += "  return 0;\n}\n\n"
   196 %(varpub)s
   139         
   197 }
   140         text += "void __cleanup_%s(void)\n{\n"%location_str
   198 """ % locals()
   141         text += "/*TODO*/\n"
       
   142         text += "\n}\n\n"
       
   143         
       
   144         text += "void __retrieve_%s(void)\n{\n"%location_str
       
   145         text += "/*TODO*/\n"
       
   146         text += "\n}\n\n"
       
   147         
       
   148         text += "void __publish_%s(void)\n{\n"%location_str
       
   149         text += "/*TODO*/\n"
       
   150         text += "\n}\n\n"
       
   151         
   199         
   152         Gen_PyCfile_path = os.path.join(buildpath, "PyCFile_%s.c"%location_str)
   200         Gen_PyCfile_path = os.path.join(buildpath, "PyCFile_%s.c"%location_str)
   153         pycfile = open(Gen_PyCfile_path,'w')
   201         pycfile = open(Gen_PyCfile_path,'w')
   154         pycfile.write(text)
   202         pycfile.write(PyCFileContent)
   155         pycfile.close()
   203         pycfile.close()
   156         
   204         
   157         matiec_flags = '"-I%s"'%os.path.abspath(
   205         matiec_flags = '"-I%s"'%os.path.abspath(
   158             self.GetCTRoot().GetIECLibPath())
   206             self.GetCTRoot().GetIECLibPath())
   159         
   207