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 |