forked from beremiz/beremiz
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathGlueGenerator.py
More file actions
105 lines (91 loc) · 3.71 KB
/
GlueGenerator.py
File metadata and controls
105 lines (91 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import os
import re
from jinja2 import Environment, FileSystemLoader
from util import paths
# LOCATED_VARIABLES.h example:
# __LOCATED_VAR(BOOL,__QX0_0,Q,X,0,0)
# __LOCATED_VAR(INT,__QW0,Q,W,0)
# __LOCATED_VAR(BOOL,__QX0_1,Q,X,0,1)
class GlueGenerator:
def __init__(self):
self.__loader = FileSystemLoader(
os.path.join(paths.AbsDir(__file__), "templates")
)
def __glue_logic(self, varName):
"""
Generate glue logic based on variable type.
"""
# Extract indices
print(f"Linking variable {varName}")
try:
parts = varName.split("_")
pos1 = int(parts[2][2:]) # number after QX0 or QW0
pos2 = int(parts[3]) if len(parts) > 3 else 0
except Exception as e:
raise Exception(f"Error parsing variable name '{varName}': {e}")
kind = varName[2] # I, Q, M
sub = varName[3] # X, B, W, D, L
if kind == "I":
if sub == "X":
return f"bool_input_ptr[{pos1}][{pos2}] = (IEC_BOOL *){varName};"
elif sub == "B":
return f"byte_input_ptr[{pos1}] = (IEC_BYTE *){varName};"
elif sub == "W":
return f"int_input_ptr[{pos1}] = (IEC_UINT *){varName};"
elif sub == "D":
return f"dint_input_ptr[{pos1}] = (IEC_UDINT *){varName};"
elif sub == "L":
return f"lint_input_ptr[{pos1}] = (IEC_ULINT *){varName};"
elif kind == "Q":
if sub == "X":
return f"bool_output_ptr[{pos1}][{pos2}] = (IEC_BOOL *){varName};"
elif sub == "B":
return f"byte_output_ptr[{pos1}] = (IEC_BYTE *){varName};"
elif sub == "W":
return f"int_output_ptr[{pos1}] = (IEC_UINT *){varName};"
elif sub == "D":
return f"dint_output_ptr[{pos1}] = (IEC_UDINT *){varName};"
elif sub == "L":
return f"lint_output_ptr[{pos1}] = (IEC_ULINT *){varName};"
elif kind == "M":
if sub == "X":
# %MX (bool memory) is only supported in OpenPLC v4
return (
f"#ifdef OPENPLC_V4\n"
f" bool_memory_ptr[{pos1}][{pos2}] = (IEC_BOOL *){varName};\n"
f"#endif"
)
elif sub == "W":
return f"int_memory_ptr[{pos1}] = (IEC_UINT *){varName};"
elif sub == "D":
return f"dint_memory_ptr[{pos1}] = (IEC_UDINT *){varName};"
elif sub == "L":
return f"lint_memory_ptr[{pos1}] = (IEC_ULINT *){varName};"
raise Exception(f"Unhandled variable type: {varName}")
def __parse_line(self, line):
"""
Parse a line from LOCATED_VARIABLES.h to extract variable information.
Example: __LOCATED_VAR(BOOL,__QX0_0,Q,X,0,0)
"""
m = re.match(r"__LOCATED_VAR\(([^,]+),([^,]+),.*\)", line.strip())
if not m:
print(f"Warning: Line '{line.strip()}' does not match expected format.")
return None
varType, varName = m.group(1), m.group(2)
return {
"type": varType,
"name": varName,
"glue_code": self.__glue_logic(varName),
}
def generate_glue_variables(self, located_vars_lines):
"""
Generate glue variables from the LOCATED_VARIABLES content.
"""
parsed = []
for line in located_vars_lines:
entry = self.__parse_line(line)
if entry is not None:
parsed.append(entry)
env = Environment(loader=self.__loader)
template = env.get_template("glueVars.c.j2")
return template.render(vars=parsed)