31 "B" : ["SINT", "USINT", "BYTE", "STRING"], |
31 "B" : ["SINT", "USINT", "BYTE", "STRING"], |
32 "W" : ["INT", "UINT", "WORD", "WSTRING"], |
32 "W" : ["INT", "UINT", "WORD", "WSTRING"], |
33 "D" : ["DINT", "UDINT", "REAL", "DWORD"], |
33 "D" : ["DINT", "UDINT", "REAL", "DWORD"], |
34 "L" : ["LINT", "ULINT", "LREAL", "LWORD"]} |
34 "L" : ["LINT", "ULINT", "LREAL", "LWORD"]} |
35 |
35 |
|
36 # Helper for emulate join on element list |
|
37 def JoinList(separator, list): |
|
38 return reduce(lambda x, y: x + separator + y, list) |
|
39 |
36 def generate_block(generator, block, body, link, order=False): |
40 def generate_block(generator, block, body, link, order=False): |
37 body_type = body.getcontent()["name"] |
41 body_type = body.getcontent()["name"] |
38 name = block.getinstanceName() |
42 name = block.getinstanceName() |
39 type = block.gettypeName() |
43 type = block.gettypeName() |
40 executionOrderId = block.getexecutionOrderId() |
44 executionOrderId = block.getexecutionOrderId() |
41 block_infos = GetBlockType(type) |
45 block_infos = generator.GetBlockType(type) |
42 if block_infos["type"] == "function": |
46 if block_infos["type"] == "function": |
43 output_variable = block.outputVariables.getvariable()[0] |
47 output_variable = block.outputVariables.getvariable()[0] |
44 output_name = "%s%d_OUT"%(type, block.getlocalId()) |
48 output_name = "%s%d_OUT"%(type, block.getlocalId()) |
|
49 output_info = (generator.TagName, "block", block.getlocalId(), "output", 0) |
45 if not generator.ComputedBlocks.get(block, False) and not order: |
50 if not generator.ComputedBlocks.get(block, False) and not order: |
46 generator.ComputedBlocks[block] = True |
51 generator.ComputedBlocks[block] = True |
47 if generator.Interface[-1][0] != "VAR" or generator.Interface[-1][1] or generator.Interface[-1][2] or generator.Interface[-1][3]: |
52 if generator.Interface[-1][0] != "VAR" or generator.Interface[-1][1] or generator.Interface[-1][2] or generator.Interface[-1][3]: |
48 generator.Interface.append(("VAR", False, False, False, [])) |
53 generator.Interface.append(("VAR", False, False, False, [])) |
49 if output_variable.connectionPointOut in generator.ConnectionTypes: |
54 if output_variable.connectionPointOut in generator.ConnectionTypes: |
50 generator.Interface[-1][4].append((generator.ConnectionTypes[output_variable.connectionPointOut], output_name, None, None)) |
55 generator.Interface[-1][4].append((generator.ConnectionTypes[output_variable.connectionPointOut], output_name, None, None)) |
51 else: |
56 else: |
52 generator.Interface[-1][4].append(("ANY", output_name, None, None)) |
57 generator.Interface[-1][4].append(("ANY", output_name, None, None)) |
53 vars = [] |
58 vars = [] |
54 for variable in block.inputVariables.getvariable(): |
59 for i, variable in enumerate(block.inputVariables.getvariable()): |
|
60 input_info = (generator.TagName, "block", block.getlocalId(), "input", i) |
55 connections = variable.connectionPointIn.getconnections() |
61 connections = variable.connectionPointIn.getconnections() |
56 if connections and len(connections) == 1: |
62 if connections and len(connections) == 1: |
57 if body_type == "FBD" or body_type == "SFC": |
63 if body_type == "FBD" or body_type == "SFC": |
58 value = generator.ComputeFBDExpression(body, connections[0], executionOrderId > 0) |
64 value = generator.ComputeFBDExpression(body, connections[0], executionOrderId > 0) |
59 elif body_type == "LD": |
65 elif body_type == "LD": |
61 if len(paths) > 0: |
67 if len(paths) > 0: |
62 paths = tuple(paths) |
68 paths = tuple(paths) |
63 else: |
69 else: |
64 paths = paths[0] |
70 paths = paths[0] |
65 value = generator.ComputeLDExpression(paths, True) |
71 value = generator.ComputeLDExpression(paths, True) |
66 vars.append(generator.ExtractModifier(variable, value)) |
72 vars.append(generator.ExtractModifier(variable, value, input_info)) |
67 generator.Program += " %s := %s(%s);\n"%(output_name, type, ", ".join(vars)) |
73 generator.Program += [(generator.CurrentIndent, ()), |
68 return generator.ExtractModifier(output_variable, output_name) |
74 (output_name, output_info), |
|
75 (" := ", ()), |
|
76 (type, (generator.TagName, "block", block.getlocalId(), "type")), |
|
77 ("(", ())] |
|
78 generator.Program += JoinList([(", ", ())], vars) |
|
79 generator.Program += [(");\n", ())] |
|
80 return generator.ExtractModifier(output_variable, [(output_name, output_info)], output_info) |
69 elif block_infos["type"] == "functionBlock": |
81 elif block_infos["type"] == "functionBlock": |
70 if not generator.ComputedBlocks.get(block, False) and not order: |
82 if not generator.ComputedBlocks.get(block, False) and not order: |
71 generator.ComputedBlocks[block] = True |
83 generator.ComputedBlocks[block] = True |
72 vars = [] |
84 vars = [] |
73 for variable in block.inputVariables.getvariable(): |
85 for i, variable in enumerate(block.inputVariables.getvariable()): |
|
86 input_info = (generator.TagName, "block", block.getlocalId(), "input", i) |
74 connections = variable.connectionPointIn.getconnections() |
87 connections = variable.connectionPointIn.getconnections() |
75 if connections and len(connections) == 1: |
88 if connections and len(connections) == 1: |
76 parameter = variable.getformalParameter() |
89 parameter = variable.getformalParameter() |
77 if body_type == "FBD" or body_type == "SFC": |
90 if body_type == "FBD" or body_type == "SFC": |
78 value = generator.ComputeFBDExpression(body, connections[0], executionOrderId > 0) |
91 value = generator.ComputeFBDExpression(body, connections[0], executionOrderId > 0) |
81 if len(paths) > 0: |
94 if len(paths) > 0: |
82 paths = tuple(paths) |
95 paths = tuple(paths) |
83 else: |
96 else: |
84 paths = paths[0] |
97 paths = paths[0] |
85 value = generator.ComputeLDExpression(paths, True) |
98 value = generator.ComputeLDExpression(paths, True) |
86 vars.append("%s := %s"%(parameter, generator.ExtractModifier(variable, value))) |
99 vars.append([(parameter, input_info), |
87 generator.Program += " %s(%s);\n"%(name, ", ".join(vars)) |
100 (" := ", ())] + generator.ExtractModifier(variable, value, input_info)) |
|
101 generator.Program += [(generator.CurrentIndent, ()), |
|
102 (name, (generator.TagName, "block", block.getlocalId(), "name")), |
|
103 ("(", ())] |
|
104 generator.Program += JoinList([(", ", ())], vars) |
|
105 generator.Program += [(");\n", ())] |
88 if link: |
106 if link: |
89 connectionPoint = link.getposition()[-1] |
107 connectionPoint = link.getposition()[-1] |
90 else: |
108 else: |
91 connectionPoint = None |
109 connectionPoint = None |
92 for variable in block.outputVariables.getvariable(): |
110 for i, variable in enumerate(block.outputVariables.getvariable()): |
93 blockPointx, blockPointy = variable.connectionPointOut.getrelPositionXY() |
111 blockPointx, blockPointy = variable.connectionPointOut.getrelPositionXY() |
|
112 output_info = (generator.TagName, "block", block.getlocalId(), "output", i) |
94 if not connectionPoint or block.getx() + blockPointx == connectionPoint.getx() and block.gety() + blockPointy == connectionPoint.gety(): |
113 if not connectionPoint or block.getx() + blockPointx == connectionPoint.getx() and block.gety() + blockPointy == connectionPoint.gety(): |
95 return generator.ExtractModifier(variable, "%s.%s"%(name, variable.getformalParameter())) |
114 return generator.ExtractModifier(variable, [("%s.%s"%(name, variable.getformalParameter()), output_info)], output_info) |
96 raise ValueError, "No output variable found" |
115 raise ValueError, "No output variable found" |
97 |
116 |
98 def initialise_block(type, name, block = None): |
117 def initialise_block(type, name, block = None): |
99 return [(type, name, None, None)] |
118 return [(type, name, None, None)] |
100 |
119 |
210 "outputs" : [("ALARM","BOOL","none"),("TOTAL_ERR","BOOL","none")], |
229 "outputs" : [("ALARM","BOOL","none"),("TOTAL_ERR","BOOL","none")], |
211 "comment" : "Ratio monitor\nThe ratio_monitor function block checks that one process value PV1 is always a given ratio (defined by input RATIO) of a second process value PV2.", |
230 "comment" : "Ratio monitor\nThe ratio_monitor function block checks that one process value PV1 is always a given ratio (defined by input RATIO) of a second process value PV2.", |
212 "generate" : generate_block, "initialise" : initialise_block} |
231 "generate" : generate_block, "initialise" : initialise_block} |
213 ]}, |
232 ]}, |
214 ] |
233 ] |
215 |
234 |
216 PluginTypes = [] |
|
217 |
|
218 """ |
|
219 Function that returns the block definition associated to the block type given |
|
220 """ |
|
221 |
|
222 def GetBlockType(type, inputs = None): |
|
223 for category in BlockTypes + PluginTypes: |
|
224 for blocktype in category["list"]: |
|
225 if inputs: |
|
226 block_inputs = tuple([var_type for name, var_type, modifier in blocktype["inputs"]]) |
|
227 same_inputs = inputs == block_inputs |
|
228 else: |
|
229 same_inputs = True |
|
230 if blocktype["name"] == type and same_inputs: |
|
231 return blocktype |
|
232 return None |
|
233 |
|
234 """ |
|
235 Function that add a new plugin to the plugin list |
|
236 """ |
|
237 |
|
238 def AddPluginBlockList(blocklist): |
|
239 PluginTypes.extend(blocklist) |
|
240 |
|
241 def ClearPluginTypes(): |
|
242 for i in xrange(len(PluginTypes)): |
|
243 PluginTypes.pop(0) |
|
244 |
235 |
245 #------------------------------------------------------------------------------- |
236 #------------------------------------------------------------------------------- |
246 # Data Types definitions |
237 # Data Types definitions |
247 #------------------------------------------------------------------------------- |
238 #------------------------------------------------------------------------------- |
248 |
239 |
263 ("ANY_NUM", "ANY_MAGNITUDE"), |
254 ("ANY_NUM", "ANY_MAGNITUDE"), |
264 ("ANY_REAL", "ANY_NUM"), |
255 ("ANY_REAL", "ANY_NUM"), |
265 ("ANY_INT", "ANY_NUM"), |
256 ("ANY_INT", "ANY_NUM"), |
266 ("ANY_SINT", "ANY_INT"), |
257 ("ANY_SINT", "ANY_INT"), |
267 ("ANY_UINT", "ANY_INT"), |
258 ("ANY_UINT", "ANY_INT"), |
268 ("BOOL", "ANY_BIT"), |
259 ("BOOL", "ANY_BIT"), |
269 ("SINT", "ANY_SINT"), |
260 ("SINT", "ANY_SINT"), |
270 ("INT", "ANY_SINT"), |
261 ("INT", "ANY_SINT"), |
271 ("DINT", "ANY_SINT"), |
262 ("DINT", "ANY_SINT"), |
272 ("LINT", "ANY_SINT"), |
263 ("LINT", "ANY_SINT"), |
273 ("USINT", "ANY_UINT"), |
264 ("USINT", "ANY_UINT"), |
288 #("WSTRING", "ANY_STRING") # TODO |
279 #("WSTRING", "ANY_STRING") # TODO |
289 ] |
280 ] |
290 |
281 |
291 TypeHierarchy = dict(TypeHierarchy_list) |
282 TypeHierarchy = dict(TypeHierarchy_list) |
292 |
283 |
293 def ResetTypeHierarchy(): |
284 """ |
294 TypeHierarchy = dict(TypeHierarchy_list) |
285 returns true if the given data type is the same that "reference" meta-type or one of its types. |
295 |
286 """ |
296 def AddDataTypeHierarchy(name, reference): |
287 def IsOfType(type, reference): |
297 TypeHierarchy[name] = reference |
288 if reference is None: |
|
289 return True |
|
290 elif type == reference: |
|
291 return True |
|
292 else: |
|
293 parent_type = TypeHierarchy[type] |
|
294 if parent_type is not None: |
|
295 return IsOfType(parent_type, reference) |
|
296 return False |
|
297 |
|
298 """ |
|
299 returns list of all types that correspont to the ANY* meta type |
|
300 """ |
|
301 def GetSubTypes(type): |
|
302 return [typename for typename, parenttype in TypeHierarchy.items() if not typename.startswith("ANY") and IsOfType(typename, type)] |
|
303 |
298 |
304 |
299 DataTypeRange_list = [ |
305 DataTypeRange_list = [ |
300 ("SINT", (-2**7, 2**7 - 1)), |
306 ("SINT", (-2**7, 2**7 - 1)), |
301 ("INT", (-2**15, 2**15 - 1)), |
307 ("INT", (-2**15, 2**15 - 1)), |
302 ("DINT", (-2**31, 2**31 - 1)), |
308 ("DINT", (-2**31, 2**31 - 1)), |
307 ("ULINT", (0, 2**31 - 1)) |
313 ("ULINT", (0, 2**31 - 1)) |
308 ] |
314 ] |
309 |
315 |
310 DataTypeRange = dict(DataTypeRange_list) |
316 DataTypeRange = dict(DataTypeRange_list) |
311 |
317 |
312 def ResetDataTypeRange(): |
318 |
313 DataTypeRange = dict(DataTypeRange_list) |
|
314 |
|
315 def AddDataTypeRange(name, range): |
|
316 DataTypeRange[name] = range |
|
317 |
|
318 """ |
|
319 returns true if the given data type is the same that "reference" meta-type or one of its types. |
|
320 """ |
|
321 |
|
322 def IsOfType(test, reference): |
|
323 if reference is None: |
|
324 return True |
|
325 while test is not None: |
|
326 if test == reference: |
|
327 return True |
|
328 test = TypeHierarchy[test] |
|
329 return False |
|
330 |
|
331 def IsEndType(reference): |
|
332 if reference is not None: |
|
333 return not reference.startswith("ANY") |
|
334 else: |
|
335 return True |
|
336 |
|
337 def GetBaseType(type): |
|
338 parent_type = TypeHierarchy[type] |
|
339 if parent_type.startswith("ANY"): |
|
340 return type |
|
341 else: |
|
342 return GetBaseType(parent_type) |
|
343 |
|
344 def GetDataTypeRange(reference): |
|
345 while reference is not None: |
|
346 if reference in DataTypeRange: |
|
347 return DataTypeRange[reference] |
|
348 else: |
|
349 reference = TypeHierarchy[reference] |
|
350 return None |
|
351 |
|
352 """ |
|
353 returns list of all types that correspont to the ANY* meta type |
|
354 """ |
|
355 def GetSubTypes(reference): |
|
356 return [typename for typename, parenttype in TypeHierarchy.items() if not typename.startswith("ANY") and IsOfType(typename, reference)] |
|
357 |
|
358 |
|
359 EnumeratedDataValues = [] |
|
360 |
|
361 def ResetEnumeratedDataValues(): |
|
362 EnumeratedDataValues = [] |
|
363 |
|
364 def AddEnumeratedDataValues(values): |
|
365 EnumeratedDataValues.extend(values) |
|
366 |
319 |
367 #------------------------------------------------------------------------------- |
320 #------------------------------------------------------------------------------- |
368 # Test identifier |
321 # Test identifier |
369 #------------------------------------------------------------------------------- |
322 #------------------------------------------------------------------------------- |
370 |
323 |