powertrain-build 1.13.1__py3-none-any.whl → 1.13.3.dev3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- powertrain_build/__init__.py +40 -40
- powertrain_build/__main__.py +6 -6
- powertrain_build/a2l.py +582 -582
- powertrain_build/a2l_merge.py +650 -650
- powertrain_build/a2l_templates.py +717 -717
- powertrain_build/build.py +985 -985
- powertrain_build/build_defs.py +309 -309
- powertrain_build/build_proj_config.py +690 -690
- powertrain_build/check_interface.py +575 -575
- powertrain_build/cli.py +141 -141
- powertrain_build/config.py +542 -542
- powertrain_build/core.py +395 -395
- powertrain_build/core_dummy.py +343 -343
- powertrain_build/create_conversion_table.py +73 -73
- powertrain_build/dids.py +916 -916
- powertrain_build/dummy.py +157 -157
- powertrain_build/dummy_spm.py +252 -252
- powertrain_build/environmentcheck.py +52 -52
- powertrain_build/ext_dbg.py +255 -255
- powertrain_build/ext_var.py +327 -327
- powertrain_build/feature_configs.py +301 -301
- powertrain_build/gen_allsysteminfo.py +227 -227
- powertrain_build/gen_label_split.py +449 -449
- powertrain_build/handcode_replacer.py +124 -124
- powertrain_build/html_report.py +133 -133
- powertrain_build/interface/__init__.py +4 -4
- powertrain_build/interface/application.py +511 -511
- powertrain_build/interface/base.py +500 -500
- powertrain_build/interface/csp_api.py +490 -490
- powertrain_build/interface/device_proxy.py +677 -677
- powertrain_build/interface/ems.py +67 -67
- powertrain_build/interface/export_global_vars.py +121 -121
- powertrain_build/interface/generate_adapters.py +132 -132
- powertrain_build/interface/generate_hi_interface.py +87 -87
- powertrain_build/interface/generate_service.py +69 -69
- powertrain_build/interface/generate_wrappers.py +147 -147
- powertrain_build/interface/generation_utils.py +142 -142
- powertrain_build/interface/hal.py +194 -194
- powertrain_build/interface/model_yaml_verification.py +348 -348
- powertrain_build/interface/service.py +296 -296
- powertrain_build/interface/simulink.py +249 -249
- powertrain_build/interface/update_call_sources.py +180 -180
- powertrain_build/interface/update_model_yaml.py +186 -186
- powertrain_build/interface/zone_controller.py +362 -362
- powertrain_build/lib/__init__.py +4 -4
- powertrain_build/lib/helper_functions.py +127 -127
- powertrain_build/lib/logger.py +55 -55
- powertrain_build/matlab_scripts/CodeGen/BuildAutomationPyBuild.m +78 -78
- powertrain_build/matlab_scripts/CodeGen/Generate_A2L.m +154 -154
- powertrain_build/matlab_scripts/CodeGen/generateTLUnit.m +239 -239
- powertrain_build/matlab_scripts/CodeGen/getAsilClassification.m +28 -28
- powertrain_build/matlab_scripts/CodeGen/modelConfiguredForTL.m +28 -28
- powertrain_build/matlab_scripts/CodeGen/moveDefOutports.m +88 -88
- powertrain_build/matlab_scripts/CodeGen/parseCalMeasData.m +410 -410
- powertrain_build/matlab_scripts/CodeGen/parseCoreIdentifiers.m +139 -139
- powertrain_build/matlab_scripts/CodeGen/parseDIDs.m +141 -141
- powertrain_build/matlab_scripts/CodeGen/parseInPorts.m +106 -106
- powertrain_build/matlab_scripts/CodeGen/parseIncludeConfigs.m +25 -25
- powertrain_build/matlab_scripts/CodeGen/parseModelInfo.m +38 -38
- powertrain_build/matlab_scripts/CodeGen/parseNVM.m +81 -81
- powertrain_build/matlab_scripts/CodeGen/parseOutPorts.m +120 -120
- powertrain_build/matlab_scripts/CodeGen/parsePreProcBlks.m +23 -23
- powertrain_build/matlab_scripts/CodeGen/struct2JSON.m +128 -128
- powertrain_build/matlab_scripts/CodeGen/updateCodeSwConfig.m +31 -31
- powertrain_build/matlab_scripts/Init_PyBuild.m +91 -91
- powertrain_build/matlab_scripts/__init__.py +2 -2
- powertrain_build/matlab_scripts/helperFunctions/Get_Full_Name.m +46 -46
- powertrain_build/matlab_scripts/helperFunctions/Get_SrcLines.m +12 -12
- powertrain_build/matlab_scripts/helperFunctions/Init_Models.m +78 -78
- powertrain_build/matlab_scripts/helperFunctions/Init_Projects.m +67 -67
- powertrain_build/matlab_scripts/helperFunctions/Read_Units.m +34 -34
- powertrain_build/matlab_scripts/helperFunctions/SetProjectTimeSamples.m +26 -26
- powertrain_build/matlab_scripts/helperFunctions/Strip_Suffix.m +16 -16
- powertrain_build/matlab_scripts/helperFunctions/followLink.m +118 -118
- powertrain_build/matlab_scripts/helperFunctions/getCodeSwitches.m +50 -50
- powertrain_build/matlab_scripts/helperFunctions/getConsumerBlocks.m +30 -30
- powertrain_build/matlab_scripts/helperFunctions/getDefBlock.m +39 -39
- powertrain_build/matlab_scripts/helperFunctions/getDefOutport.m +58 -58
- powertrain_build/matlab_scripts/helperFunctions/getDstBlocks.m +19 -19
- powertrain_build/matlab_scripts/helperFunctions/getDstLines.m +13 -13
- powertrain_build/matlab_scripts/helperFunctions/getInterfaceSignals.m +37 -37
- powertrain_build/matlab_scripts/helperFunctions/getName.m +37 -37
- powertrain_build/matlab_scripts/helperFunctions/getPath.m +6 -6
- powertrain_build/matlab_scripts/helperFunctions/getProperValue.m +21 -21
- powertrain_build/matlab_scripts/helperFunctions/getSrcBlocks.m +19 -19
- powertrain_build/matlab_scripts/helperFunctions/getSrcLines.m +13 -13
- powertrain_build/matlab_scripts/helperFunctions/loadLibraries.m +10 -10
- powertrain_build/matlab_scripts/helperFunctions/loadjson.m +6 -6
- powertrain_build/matlab_scripts/helperFunctions/modifyEnumStructField.m +21 -21
- powertrain_build/matlab_scripts/helperFunctions/removeConfigDuplicates.m +31 -31
- powertrain_build/matlab_scripts/helperFunctions/sortSystemByClass.m +26 -26
- powertrain_build/matlab_scripts/helperFunctions/tl_getfast.m +89 -89
- powertrain_build/matlab_scripts/helperFunctions/topLevelSystem.m +20 -20
- powertrain_build/matlab_scripts/helperFunctions/updateModels.m +131 -131
- powertrain_build/memory_section.py +224 -224
- powertrain_build/nvm_def.py +729 -729
- powertrain_build/problem_logger.py +86 -86
- powertrain_build/pt_matlab.py +430 -430
- powertrain_build/pt_win32.py +144 -144
- powertrain_build/replace_compu_tab_ref.py +105 -105
- powertrain_build/rte_dummy.py +254 -254
- powertrain_build/sched_funcs.py +209 -207
- powertrain_build/signal.py +7 -7
- powertrain_build/signal_if_html_rep.py +221 -221
- powertrain_build/signal_if_html_rep_all.py +302 -302
- powertrain_build/signal_incons_html_rep.py +180 -180
- powertrain_build/signal_incons_html_rep_all.py +366 -366
- powertrain_build/signal_incons_html_rep_base.py +168 -168
- powertrain_build/signal_inconsistency_check.py +641 -641
- powertrain_build/signal_interfaces.py +864 -864
- powertrain_build/templates/Index_SigCheck_All.html +22 -22
- powertrain_build/templates/Index_SigIf_All.html +19 -19
- powertrain_build/types.py +218 -218
- powertrain_build/unit_configs.py +419 -419
- powertrain_build/user_defined_types.py +660 -660
- powertrain_build/versioncheck.py +66 -66
- powertrain_build/wrapper.py +512 -512
- powertrain_build/xlrd_csv.py +87 -87
- powertrain_build/zone_controller/__init__.py +4 -4
- powertrain_build/zone_controller/calibration.py +176 -176
- powertrain_build/zone_controller/composition_yaml.py +880 -878
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/METADATA +100 -100
- powertrain_build-1.13.3.dev3.dist-info/RECORD +130 -0
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/WHEEL +1 -1
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/licenses/LICENSE +202 -202
- powertrain_build-1.13.3.dev3.dist-info/pbr.json +1 -0
- powertrain_build-1.13.1.dist-info/RECORD +0 -130
- powertrain_build-1.13.1.dist-info/pbr.json +0 -1
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/entry_points.txt +0 -0
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/licenses/AUTHORS +0 -0
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/licenses/NOTICE +0 -0
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/top_level.txt +0 -0
powertrain_build/ext_var.py
CHANGED
|
@@ -1,327 +1,327 @@
|
|
|
1
|
-
# Copyright 2024 Volvo Car Corporation
|
|
2
|
-
# Licensed under Apache 2.0.
|
|
3
|
-
|
|
4
|
-
# -*- coding: utf-8 -*-
|
|
5
|
-
"""Module containing classes for VCC - Supplier signal interface."""
|
|
6
|
-
|
|
7
|
-
from powertrain_build import build_defs
|
|
8
|
-
from powertrain_build.types import byte_size_string, get_bitmask
|
|
9
|
-
from powertrain_build.a2l import A2l
|
|
10
|
-
from powertrain_build.problem_logger import ProblemLogger
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class ExtVarBase(ProblemLogger):
|
|
14
|
-
"""Generate a2l- and c-files.
|
|
15
|
-
|
|
16
|
-
These which declares all variables in the interface that the
|
|
17
|
-
supplier platform writes to.
|
|
18
|
-
|
|
19
|
-
This is needed due to legacy handling of the interfaces between units.
|
|
20
|
-
Note that all variables sent from the VCC SPM to the platform should be declared in
|
|
21
|
-
the function that produces the signal!
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
INPORT_INDEX = 0
|
|
25
|
-
OUTPORT_INDEX = 1
|
|
26
|
-
|
|
27
|
-
__data_type_size = {
|
|
28
|
-
"Float32": "4",
|
|
29
|
-
"UInt32": "4",
|
|
30
|
-
"Int32": "4",
|
|
31
|
-
"UInt16": "2",
|
|
32
|
-
"Int16": "2",
|
|
33
|
-
"UInt8": "1",
|
|
34
|
-
"Int8": "1",
|
|
35
|
-
"Bool": "1",
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
def __init__(self, variable_dict, prj_cfg, unit_cfg, user_defined_types, integrity_level=build_defs.ASIL_QM):
|
|
39
|
-
"""Constructor.
|
|
40
|
-
|
|
41
|
-
Args:
|
|
42
|
-
variable_dict (dict): dictionary with signal information.
|
|
43
|
-
prj_cfg (BuildProjConfig): Build project class holding where files should be stored.
|
|
44
|
-
user_defined_types (UserDefinedTypes): Class holding user defined data types.
|
|
45
|
-
integrity_level (str): integrity level of the unit from 'A' to 'D' or 'QM'.
|
|
46
|
-
"""
|
|
47
|
-
super().__init__()
|
|
48
|
-
self.set_integrity_level(integrity_level)
|
|
49
|
-
self._var_dict = variable_dict
|
|
50
|
-
self._ext_vars = {}
|
|
51
|
-
self._prj_cfg = prj_cfg
|
|
52
|
-
self._unit_cfg = unit_cfg
|
|
53
|
-
self._enumerations = user_defined_types.get_enumerations()
|
|
54
|
-
self._common_header_files = user_defined_types.common_header_files
|
|
55
|
-
|
|
56
|
-
def set_integrity_level(self, integrity_level):
|
|
57
|
-
"""Set integrity level of code generation.
|
|
58
|
-
|
|
59
|
-
Args:
|
|
60
|
-
integrity_level (str): integrity level of the unit from 'A' to 'D' or 'QM'
|
|
61
|
-
"""
|
|
62
|
-
self._disp_start = integrity_level["CVC"]["DISP"]["START"]
|
|
63
|
-
self._disp_end = integrity_level["CVC"]["DISP"]["END"]
|
|
64
|
-
self._decl_start = integrity_level["PREDECL"]["DISP"]["START"]
|
|
65
|
-
self._decl_end = integrity_level["PREDECL"]["DISP"]["END"]
|
|
66
|
-
|
|
67
|
-
def _get_byte_size_string(self, data_type):
|
|
68
|
-
"""Get byte size of a data type as string.
|
|
69
|
-
Enumeration byte sizes are derived from the underlying data type.
|
|
70
|
-
|
|
71
|
-
Args:
|
|
72
|
-
data_type (str): Data type.
|
|
73
|
-
Returns:
|
|
74
|
-
byte_size_string(powertrain_build.types.byte_size_string): Return result of
|
|
75
|
-
powertrain_build.types.byte_size_string.
|
|
76
|
-
"""
|
|
77
|
-
if data_type in self._enumerations:
|
|
78
|
-
return byte_size_string(self._enumerations[data_type]["underlying_data_type"])
|
|
79
|
-
return byte_size_string(data_type)
|
|
80
|
-
|
|
81
|
-
def _get_bitmask(self, data_type):
|
|
82
|
-
"""Get bitmask of a data type.
|
|
83
|
-
Enumeration bitmasks are derived from the underlying data type.
|
|
84
|
-
|
|
85
|
-
Args:
|
|
86
|
-
data_type (str): Data type.
|
|
87
|
-
Returns:
|
|
88
|
-
get_bitmask(powertrain_build.types.get_bitmask): Return result of powertrain_build.types.get_bitmask.
|
|
89
|
-
"""
|
|
90
|
-
if data_type in self._enumerations:
|
|
91
|
-
return get_bitmask(self._enumerations[data_type]["underlying_data_type"])
|
|
92
|
-
return get_bitmask(data_type)
|
|
93
|
-
|
|
94
|
-
def _restruct_input_data(self):
|
|
95
|
-
"""Restructure all the input variables per data-type.
|
|
96
|
-
|
|
97
|
-
This will be used for declaring the variables and generating the
|
|
98
|
-
A2L-file
|
|
99
|
-
"""
|
|
100
|
-
external_inports = {}
|
|
101
|
-
external_outports = {}
|
|
102
|
-
for external_port_type in self.EXTERNAL_INPORT_TYPES:
|
|
103
|
-
if external_port_type in self._var_dict:
|
|
104
|
-
for var, data in self._var_dict[external_port_type].items():
|
|
105
|
-
data_type_size = self._get_byte_size_string(data[self.TYPE_NAME])
|
|
106
|
-
external_inports.setdefault(data_type_size, {})[var] = data
|
|
107
|
-
for external_port_type in self.EXTERNAL_OUTPORT_TYPES:
|
|
108
|
-
if external_port_type in self._var_dict:
|
|
109
|
-
for var, data in self._var_dict[external_port_type].items():
|
|
110
|
-
data_type_size = self._get_byte_size_string(data[self.TYPE_NAME])
|
|
111
|
-
external_outports.setdefault(data_type_size, {})[var] = data
|
|
112
|
-
self._ext_vars = external_inports, external_outports
|
|
113
|
-
|
|
114
|
-
def _a2l_dict(self):
|
|
115
|
-
"""Return a dict defining all parameters for a2l-generation."""
|
|
116
|
-
res = {"vars": {}, "function": "VcExtVar"}
|
|
117
|
-
for inp in self.EXTERNAL_INPORT_TYPES:
|
|
118
|
-
if inp in self._var_dict:
|
|
119
|
-
for var, data in self._var_dict[inp].items():
|
|
120
|
-
if data[self.TYPE_NAME] in self._enumerations:
|
|
121
|
-
data_type = self._enumerations[data[self.TYPE_NAME]]["underlying_data_type"]
|
|
122
|
-
else:
|
|
123
|
-
data_type = data[self.TYPE_NAME]
|
|
124
|
-
|
|
125
|
-
resv = res["vars"]
|
|
126
|
-
resv.setdefault(var, {})["a2l_data"] = self.get_a2l_format(data)
|
|
127
|
-
resv[var]["array"] = []
|
|
128
|
-
resv[var]["function"] = ["VcEc"]
|
|
129
|
-
resv[var]["var"] = {"cvc_type": "CVC_DISP", "type": data_type, "var": var}
|
|
130
|
-
return res
|
|
131
|
-
|
|
132
|
-
def _get_array_declaration(self, var, width):
|
|
133
|
-
"""Get array declaration string from width information.
|
|
134
|
-
|
|
135
|
-
Args:
|
|
136
|
-
var (str): Variable name.
|
|
137
|
-
width (int or list): Width information.
|
|
138
|
-
Returns:
|
|
139
|
-
array (str): Array declaration string.
|
|
140
|
-
"""
|
|
141
|
-
array = ""
|
|
142
|
-
widths = [width] if not isinstance(width, list) else width
|
|
143
|
-
if len(widths) != 1 or widths[0] != 1:
|
|
144
|
-
for w in widths:
|
|
145
|
-
if w > 1:
|
|
146
|
-
if not isinstance(w, int):
|
|
147
|
-
self.critical(f'{var} widths must be integers. Got "{type(w)}"')
|
|
148
|
-
array += f'[{w}]'
|
|
149
|
-
elif w < 0:
|
|
150
|
-
self.critical(f'{var} widths can not be negative. Got "{w}"')
|
|
151
|
-
return array
|
|
152
|
-
|
|
153
|
-
def _generate_c_file(self, path):
|
|
154
|
-
"""Generate the c-file defining all the supplier input signals."""
|
|
155
|
-
header = path.with_suffix(".h").name
|
|
156
|
-
var_set = set()
|
|
157
|
-
with path.open("w") as fh_c:
|
|
158
|
-
fh_c.write(f'#include "{header}"\n')
|
|
159
|
-
fh_c.write(f'#include "{self._disp_start}"\n\n')
|
|
160
|
-
for data_type_s, ext_vars in self._ext_vars[self.INPORT_INDEX].items():
|
|
161
|
-
fh_c.write(f"/* Variables of size {data_type_s} bytes */\n\n")
|
|
162
|
-
for var in sorted(ext_vars.keys()):
|
|
163
|
-
data = ext_vars[var]
|
|
164
|
-
if var not in var_set:
|
|
165
|
-
array = self._get_array_declaration(var, data.get("width", 1))
|
|
166
|
-
if array:
|
|
167
|
-
init_value = data["init"] if data["init"] != 0 else "{0}"
|
|
168
|
-
else:
|
|
169
|
-
init_value = data["init"]
|
|
170
|
-
fh_c.write(f"CVC_DISP {data[self.TYPE_NAME]} {var}{array} = {init_value};\n")
|
|
171
|
-
var_set.add(var)
|
|
172
|
-
fh_c.write("\n")
|
|
173
|
-
fh_c.write(f'\n#include "{self._disp_end}"\n')
|
|
174
|
-
self.info("Generated %s", path.name)
|
|
175
|
-
|
|
176
|
-
def _generate_h_file(self, path):
|
|
177
|
-
"""Generate header file externally declaring interface signals."""
|
|
178
|
-
filename = path.stem
|
|
179
|
-
guard = f"{filename.upper()}_H"
|
|
180
|
-
var_set = set()
|
|
181
|
-
with path.open("w") as fh_c:
|
|
182
|
-
fh_c.write(f"#ifndef {guard}\n")
|
|
183
|
-
fh_c.write(f"#define {guard}\n")
|
|
184
|
-
fh_c.write("#define CVC_DISP\n")
|
|
185
|
-
fh_c.write(self._unit_cfg.base_types_headers)
|
|
186
|
-
|
|
187
|
-
for common_header_file in self._common_header_files:
|
|
188
|
-
fh_c.write(f'#include "{common_header_file}"\n')
|
|
189
|
-
fh_c.write("\n")
|
|
190
|
-
|
|
191
|
-
fh_c.write(f'#include "{self._decl_start}"\n')
|
|
192
|
-
fh_c.write("/* VCC Inports */\n")
|
|
193
|
-
for data_type_s, ext_vars in self._ext_vars[self.INPORT_INDEX].items():
|
|
194
|
-
fh_c.write(f"/* Variables of size {data_type_s} bytes */\n\n")
|
|
195
|
-
for var in sorted(ext_vars.keys()):
|
|
196
|
-
if var not in var_set:
|
|
197
|
-
data = ext_vars[var]
|
|
198
|
-
array = self._get_array_declaration(var, data.get("width", 1))
|
|
199
|
-
fh_c.write(f"extern CVC_DISP {data[self.TYPE_NAME]} {var}{array};\n")
|
|
200
|
-
var_set.add(var)
|
|
201
|
-
fh_c.write("\n")
|
|
202
|
-
|
|
203
|
-
fh_c.write("/* VCC Outports */\n")
|
|
204
|
-
for data_type_s, ext_vars in self._ext_vars[self.OUTPORT_INDEX].items():
|
|
205
|
-
fh_c.write(f"/* Variables of size {data_type_s} bytes */\n\n")
|
|
206
|
-
for var in sorted(ext_vars.keys()):
|
|
207
|
-
if var not in var_set:
|
|
208
|
-
data = ext_vars[var]
|
|
209
|
-
array = self._get_array_declaration(var, data.get("width", 1))
|
|
210
|
-
fh_c.write(f"extern CVC_DISP {data[self.TYPE_NAME]} {var}{array};\n")
|
|
211
|
-
var_set.add(var)
|
|
212
|
-
fh_c.write("\n")
|
|
213
|
-
fh_c.write(f'#include "{self._decl_end}"\n')
|
|
214
|
-
fh_c.write("#endif\n")
|
|
215
|
-
self.info("Generated %s", path.name)
|
|
216
|
-
|
|
217
|
-
def generate_files(self, path):
|
|
218
|
-
"""Generate the c- and a2l-file for defining all the supplier input variables."""
|
|
219
|
-
self._restruct_input_data()
|
|
220
|
-
if not self._ext_vars[0] and not self._ext_vars[1]:
|
|
221
|
-
self.info(f"Skipping {path.name} as there were no corresponding vars.")
|
|
222
|
-
return
|
|
223
|
-
self._generate_c_file(path.with_suffix(".c"))
|
|
224
|
-
self._generate_h_file(path.with_suffix(".h"))
|
|
225
|
-
a2l_dict = self._a2l_dict()
|
|
226
|
-
a2l = A2l(a2l_dict, self._prj_cfg)
|
|
227
|
-
a2l.gen_a2l(path.with_suffix(".a2l"))
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
class ExtVarCsv(ExtVarBase):
|
|
231
|
-
"""Handles variable dicts from CSV files.
|
|
232
|
-
|
|
233
|
-
Variable dict shall have the following format and is generated by the
|
|
234
|
-
:doc:`CsvSignalInterfaces <signal_interfaces>` class::
|
|
235
|
-
|
|
236
|
-
{
|
|
237
|
-
'CAN-Input': {
|
|
238
|
-
'signal1': {
|
|
239
|
-
'IOType': 'd',
|
|
240
|
-
'description': 'Some description',
|
|
241
|
-
'init': 0,
|
|
242
|
-
'max': 1,
|
|
243
|
-
'min': 0,
|
|
244
|
-
'type': 'UInt8',
|
|
245
|
-
'unit': '-'
|
|
246
|
-
},
|
|
247
|
-
'signal2': {
|
|
248
|
-
...
|
|
249
|
-
}
|
|
250
|
-
},
|
|
251
|
-
'CAN-Output': {
|
|
252
|
-
'signal3': {
|
|
253
|
-
...
|
|
254
|
-
}
|
|
255
|
-
},
|
|
256
|
-
'xxx-Input': ...,
|
|
257
|
-
'xxx-Output': ...
|
|
258
|
-
}
|
|
259
|
-
"""
|
|
260
|
-
|
|
261
|
-
EXTERNAL_INPORT_TYPES = ["EMS-Input", "CAN-Input", "Private CAN-Input", "LIN-Input"]
|
|
262
|
-
EXTERNAL_OUTPORT_TYPES = ["EMS-Output", "CAN-Output", "Private CAN-Output", "LIN-Output"]
|
|
263
|
-
TYPE_NAME = "type"
|
|
264
|
-
|
|
265
|
-
def get_a2l_format(self, data):
|
|
266
|
-
"""Get a2l format.
|
|
267
|
-
|
|
268
|
-
Args:
|
|
269
|
-
data (dict): Data dictionary.
|
|
270
|
-
Returns:
|
|
271
|
-
dict: A2l format dictionary.
|
|
272
|
-
"""
|
|
273
|
-
return {
|
|
274
|
-
"bitmask": self._get_bitmask(data[self.TYPE_NAME]),
|
|
275
|
-
"description": data["description"],
|
|
276
|
-
"lsb": "2^0",
|
|
277
|
-
"max": data["max"],
|
|
278
|
-
"min": data["min"],
|
|
279
|
-
"offset": "0",
|
|
280
|
-
"unit": data["unit"],
|
|
281
|
-
"x_axis": None,
|
|
282
|
-
"y_axis": None,
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
class ExtVarYaml(ExtVarBase):
|
|
287
|
-
"""Handles variable dicts from Yaml files.
|
|
288
|
-
|
|
289
|
-
Variable dict shall have the following format and is generated by the
|
|
290
|
-
:doc:`YamlSignalInterfaces <signal_interfaces>` class::
|
|
291
|
-
|
|
292
|
-
{
|
|
293
|
-
'input': {
|
|
294
|
-
'sVcIhfa_D_WhlMotSysFrntLimnIndcn': {},
|
|
295
|
-
'sVcIhfa_D_WhlMotSysFrntModSts': {},
|
|
296
|
-
'sVcIhfa_I_WhlMotSysFrntIdc': {},
|
|
297
|
-
'sVcIhfa_U_UDcDcActHiSide1': {},
|
|
298
|
-
'sVcIhfa_U_WhlMotSysFrntUdc': {}
|
|
299
|
-
},
|
|
300
|
-
'output': {},
|
|
301
|
-
'status': {},
|
|
302
|
-
}
|
|
303
|
-
"""
|
|
304
|
-
|
|
305
|
-
EXTERNAL_INPORT_TYPES = ["input", "status"]
|
|
306
|
-
EXTERNAL_OUTPORT_TYPES = ["output"]
|
|
307
|
-
TYPE_NAME = "variable_type"
|
|
308
|
-
|
|
309
|
-
def get_a2l_format(self, data):
|
|
310
|
-
"""Get a2l format.
|
|
311
|
-
|
|
312
|
-
Args:
|
|
313
|
-
data (dict): Data dictionary.
|
|
314
|
-
Returns:
|
|
315
|
-
dict: A2l format dictionary.
|
|
316
|
-
"""
|
|
317
|
-
return {
|
|
318
|
-
"bitmask": self._get_bitmask(data[self.TYPE_NAME]),
|
|
319
|
-
"description": data["description"],
|
|
320
|
-
"lsb": "2^0",
|
|
321
|
-
"max": data["range"]["max"],
|
|
322
|
-
"min": data["range"]["min"],
|
|
323
|
-
"offset": "0",
|
|
324
|
-
"unit": data["unit"],
|
|
325
|
-
"x_axis": None,
|
|
326
|
-
"y_axis": None,
|
|
327
|
-
}
|
|
1
|
+
# Copyright 2024 Volvo Car Corporation
|
|
2
|
+
# Licensed under Apache 2.0.
|
|
3
|
+
|
|
4
|
+
# -*- coding: utf-8 -*-
|
|
5
|
+
"""Module containing classes for VCC - Supplier signal interface."""
|
|
6
|
+
|
|
7
|
+
from powertrain_build import build_defs
|
|
8
|
+
from powertrain_build.types import byte_size_string, get_bitmask
|
|
9
|
+
from powertrain_build.a2l import A2l
|
|
10
|
+
from powertrain_build.problem_logger import ProblemLogger
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ExtVarBase(ProblemLogger):
|
|
14
|
+
"""Generate a2l- and c-files.
|
|
15
|
+
|
|
16
|
+
These which declares all variables in the interface that the
|
|
17
|
+
supplier platform writes to.
|
|
18
|
+
|
|
19
|
+
This is needed due to legacy handling of the interfaces between units.
|
|
20
|
+
Note that all variables sent from the VCC SPM to the platform should be declared in
|
|
21
|
+
the function that produces the signal!
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
INPORT_INDEX = 0
|
|
25
|
+
OUTPORT_INDEX = 1
|
|
26
|
+
|
|
27
|
+
__data_type_size = {
|
|
28
|
+
"Float32": "4",
|
|
29
|
+
"UInt32": "4",
|
|
30
|
+
"Int32": "4",
|
|
31
|
+
"UInt16": "2",
|
|
32
|
+
"Int16": "2",
|
|
33
|
+
"UInt8": "1",
|
|
34
|
+
"Int8": "1",
|
|
35
|
+
"Bool": "1",
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
def __init__(self, variable_dict, prj_cfg, unit_cfg, user_defined_types, integrity_level=build_defs.ASIL_QM):
|
|
39
|
+
"""Constructor.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
variable_dict (dict): dictionary with signal information.
|
|
43
|
+
prj_cfg (BuildProjConfig): Build project class holding where files should be stored.
|
|
44
|
+
user_defined_types (UserDefinedTypes): Class holding user defined data types.
|
|
45
|
+
integrity_level (str): integrity level of the unit from 'A' to 'D' or 'QM'.
|
|
46
|
+
"""
|
|
47
|
+
super().__init__()
|
|
48
|
+
self.set_integrity_level(integrity_level)
|
|
49
|
+
self._var_dict = variable_dict
|
|
50
|
+
self._ext_vars = {}
|
|
51
|
+
self._prj_cfg = prj_cfg
|
|
52
|
+
self._unit_cfg = unit_cfg
|
|
53
|
+
self._enumerations = user_defined_types.get_enumerations()
|
|
54
|
+
self._common_header_files = user_defined_types.common_header_files
|
|
55
|
+
|
|
56
|
+
def set_integrity_level(self, integrity_level):
|
|
57
|
+
"""Set integrity level of code generation.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
integrity_level (str): integrity level of the unit from 'A' to 'D' or 'QM'
|
|
61
|
+
"""
|
|
62
|
+
self._disp_start = integrity_level["CVC"]["DISP"]["START"]
|
|
63
|
+
self._disp_end = integrity_level["CVC"]["DISP"]["END"]
|
|
64
|
+
self._decl_start = integrity_level["PREDECL"]["DISP"]["START"]
|
|
65
|
+
self._decl_end = integrity_level["PREDECL"]["DISP"]["END"]
|
|
66
|
+
|
|
67
|
+
def _get_byte_size_string(self, data_type):
|
|
68
|
+
"""Get byte size of a data type as string.
|
|
69
|
+
Enumeration byte sizes are derived from the underlying data type.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
data_type (str): Data type.
|
|
73
|
+
Returns:
|
|
74
|
+
byte_size_string(powertrain_build.types.byte_size_string): Return result of
|
|
75
|
+
powertrain_build.types.byte_size_string.
|
|
76
|
+
"""
|
|
77
|
+
if data_type in self._enumerations:
|
|
78
|
+
return byte_size_string(self._enumerations[data_type]["underlying_data_type"])
|
|
79
|
+
return byte_size_string(data_type)
|
|
80
|
+
|
|
81
|
+
def _get_bitmask(self, data_type):
|
|
82
|
+
"""Get bitmask of a data type.
|
|
83
|
+
Enumeration bitmasks are derived from the underlying data type.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
data_type (str): Data type.
|
|
87
|
+
Returns:
|
|
88
|
+
get_bitmask(powertrain_build.types.get_bitmask): Return result of powertrain_build.types.get_bitmask.
|
|
89
|
+
"""
|
|
90
|
+
if data_type in self._enumerations:
|
|
91
|
+
return get_bitmask(self._enumerations[data_type]["underlying_data_type"])
|
|
92
|
+
return get_bitmask(data_type)
|
|
93
|
+
|
|
94
|
+
def _restruct_input_data(self):
|
|
95
|
+
"""Restructure all the input variables per data-type.
|
|
96
|
+
|
|
97
|
+
This will be used for declaring the variables and generating the
|
|
98
|
+
A2L-file
|
|
99
|
+
"""
|
|
100
|
+
external_inports = {}
|
|
101
|
+
external_outports = {}
|
|
102
|
+
for external_port_type in self.EXTERNAL_INPORT_TYPES:
|
|
103
|
+
if external_port_type in self._var_dict:
|
|
104
|
+
for var, data in self._var_dict[external_port_type].items():
|
|
105
|
+
data_type_size = self._get_byte_size_string(data[self.TYPE_NAME])
|
|
106
|
+
external_inports.setdefault(data_type_size, {})[var] = data
|
|
107
|
+
for external_port_type in self.EXTERNAL_OUTPORT_TYPES:
|
|
108
|
+
if external_port_type in self._var_dict:
|
|
109
|
+
for var, data in self._var_dict[external_port_type].items():
|
|
110
|
+
data_type_size = self._get_byte_size_string(data[self.TYPE_NAME])
|
|
111
|
+
external_outports.setdefault(data_type_size, {})[var] = data
|
|
112
|
+
self._ext_vars = external_inports, external_outports
|
|
113
|
+
|
|
114
|
+
def _a2l_dict(self):
|
|
115
|
+
"""Return a dict defining all parameters for a2l-generation."""
|
|
116
|
+
res = {"vars": {}, "function": "VcExtVar"}
|
|
117
|
+
for inp in self.EXTERNAL_INPORT_TYPES:
|
|
118
|
+
if inp in self._var_dict:
|
|
119
|
+
for var, data in self._var_dict[inp].items():
|
|
120
|
+
if data[self.TYPE_NAME] in self._enumerations:
|
|
121
|
+
data_type = self._enumerations[data[self.TYPE_NAME]]["underlying_data_type"]
|
|
122
|
+
else:
|
|
123
|
+
data_type = data[self.TYPE_NAME]
|
|
124
|
+
|
|
125
|
+
resv = res["vars"]
|
|
126
|
+
resv.setdefault(var, {})["a2l_data"] = self.get_a2l_format(data)
|
|
127
|
+
resv[var]["array"] = []
|
|
128
|
+
resv[var]["function"] = ["VcEc"]
|
|
129
|
+
resv[var]["var"] = {"cvc_type": "CVC_DISP", "type": data_type, "var": var}
|
|
130
|
+
return res
|
|
131
|
+
|
|
132
|
+
def _get_array_declaration(self, var, width):
|
|
133
|
+
"""Get array declaration string from width information.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
var (str): Variable name.
|
|
137
|
+
width (int or list): Width information.
|
|
138
|
+
Returns:
|
|
139
|
+
array (str): Array declaration string.
|
|
140
|
+
"""
|
|
141
|
+
array = ""
|
|
142
|
+
widths = [width] if not isinstance(width, list) else width
|
|
143
|
+
if len(widths) != 1 or widths[0] != 1:
|
|
144
|
+
for w in widths:
|
|
145
|
+
if w > 1:
|
|
146
|
+
if not isinstance(w, int):
|
|
147
|
+
self.critical(f'{var} widths must be integers. Got "{type(w)}"')
|
|
148
|
+
array += f'[{w}]'
|
|
149
|
+
elif w < 0:
|
|
150
|
+
self.critical(f'{var} widths can not be negative. Got "{w}"')
|
|
151
|
+
return array
|
|
152
|
+
|
|
153
|
+
def _generate_c_file(self, path):
|
|
154
|
+
"""Generate the c-file defining all the supplier input signals."""
|
|
155
|
+
header = path.with_suffix(".h").name
|
|
156
|
+
var_set = set()
|
|
157
|
+
with path.open("w") as fh_c:
|
|
158
|
+
fh_c.write(f'#include "{header}"\n')
|
|
159
|
+
fh_c.write(f'#include "{self._disp_start}"\n\n')
|
|
160
|
+
for data_type_s, ext_vars in self._ext_vars[self.INPORT_INDEX].items():
|
|
161
|
+
fh_c.write(f"/* Variables of size {data_type_s} bytes */\n\n")
|
|
162
|
+
for var in sorted(ext_vars.keys()):
|
|
163
|
+
data = ext_vars[var]
|
|
164
|
+
if var not in var_set:
|
|
165
|
+
array = self._get_array_declaration(var, data.get("width", 1))
|
|
166
|
+
if array:
|
|
167
|
+
init_value = data["init"] if data["init"] != 0 else "{0}"
|
|
168
|
+
else:
|
|
169
|
+
init_value = data["init"]
|
|
170
|
+
fh_c.write(f"CVC_DISP {data[self.TYPE_NAME]} {var}{array} = {init_value};\n")
|
|
171
|
+
var_set.add(var)
|
|
172
|
+
fh_c.write("\n")
|
|
173
|
+
fh_c.write(f'\n#include "{self._disp_end}"\n')
|
|
174
|
+
self.info("Generated %s", path.name)
|
|
175
|
+
|
|
176
|
+
def _generate_h_file(self, path):
|
|
177
|
+
"""Generate header file externally declaring interface signals."""
|
|
178
|
+
filename = path.stem
|
|
179
|
+
guard = f"{filename.upper()}_H"
|
|
180
|
+
var_set = set()
|
|
181
|
+
with path.open("w") as fh_c:
|
|
182
|
+
fh_c.write(f"#ifndef {guard}\n")
|
|
183
|
+
fh_c.write(f"#define {guard}\n")
|
|
184
|
+
fh_c.write("#define CVC_DISP\n")
|
|
185
|
+
fh_c.write(self._unit_cfg.base_types_headers)
|
|
186
|
+
|
|
187
|
+
for common_header_file in self._common_header_files:
|
|
188
|
+
fh_c.write(f'#include "{common_header_file}"\n')
|
|
189
|
+
fh_c.write("\n")
|
|
190
|
+
|
|
191
|
+
fh_c.write(f'#include "{self._decl_start}"\n')
|
|
192
|
+
fh_c.write("/* VCC Inports */\n")
|
|
193
|
+
for data_type_s, ext_vars in self._ext_vars[self.INPORT_INDEX].items():
|
|
194
|
+
fh_c.write(f"/* Variables of size {data_type_s} bytes */\n\n")
|
|
195
|
+
for var in sorted(ext_vars.keys()):
|
|
196
|
+
if var not in var_set:
|
|
197
|
+
data = ext_vars[var]
|
|
198
|
+
array = self._get_array_declaration(var, data.get("width", 1))
|
|
199
|
+
fh_c.write(f"extern CVC_DISP {data[self.TYPE_NAME]} {var}{array};\n")
|
|
200
|
+
var_set.add(var)
|
|
201
|
+
fh_c.write("\n")
|
|
202
|
+
|
|
203
|
+
fh_c.write("/* VCC Outports */\n")
|
|
204
|
+
for data_type_s, ext_vars in self._ext_vars[self.OUTPORT_INDEX].items():
|
|
205
|
+
fh_c.write(f"/* Variables of size {data_type_s} bytes */\n\n")
|
|
206
|
+
for var in sorted(ext_vars.keys()):
|
|
207
|
+
if var not in var_set:
|
|
208
|
+
data = ext_vars[var]
|
|
209
|
+
array = self._get_array_declaration(var, data.get("width", 1))
|
|
210
|
+
fh_c.write(f"extern CVC_DISP {data[self.TYPE_NAME]} {var}{array};\n")
|
|
211
|
+
var_set.add(var)
|
|
212
|
+
fh_c.write("\n")
|
|
213
|
+
fh_c.write(f'#include "{self._decl_end}"\n')
|
|
214
|
+
fh_c.write("#endif\n")
|
|
215
|
+
self.info("Generated %s", path.name)
|
|
216
|
+
|
|
217
|
+
def generate_files(self, path):
|
|
218
|
+
"""Generate the c- and a2l-file for defining all the supplier input variables."""
|
|
219
|
+
self._restruct_input_data()
|
|
220
|
+
if not self._ext_vars[0] and not self._ext_vars[1]:
|
|
221
|
+
self.info(f"Skipping {path.name} as there were no corresponding vars.")
|
|
222
|
+
return
|
|
223
|
+
self._generate_c_file(path.with_suffix(".c"))
|
|
224
|
+
self._generate_h_file(path.with_suffix(".h"))
|
|
225
|
+
a2l_dict = self._a2l_dict()
|
|
226
|
+
a2l = A2l(a2l_dict, self._prj_cfg)
|
|
227
|
+
a2l.gen_a2l(path.with_suffix(".a2l"))
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class ExtVarCsv(ExtVarBase):
|
|
231
|
+
"""Handles variable dicts from CSV files.
|
|
232
|
+
|
|
233
|
+
Variable dict shall have the following format and is generated by the
|
|
234
|
+
:doc:`CsvSignalInterfaces <signal_interfaces>` class::
|
|
235
|
+
|
|
236
|
+
{
|
|
237
|
+
'CAN-Input': {
|
|
238
|
+
'signal1': {
|
|
239
|
+
'IOType': 'd',
|
|
240
|
+
'description': 'Some description',
|
|
241
|
+
'init': 0,
|
|
242
|
+
'max': 1,
|
|
243
|
+
'min': 0,
|
|
244
|
+
'type': 'UInt8',
|
|
245
|
+
'unit': '-'
|
|
246
|
+
},
|
|
247
|
+
'signal2': {
|
|
248
|
+
...
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
'CAN-Output': {
|
|
252
|
+
'signal3': {
|
|
253
|
+
...
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
'xxx-Input': ...,
|
|
257
|
+
'xxx-Output': ...
|
|
258
|
+
}
|
|
259
|
+
"""
|
|
260
|
+
|
|
261
|
+
EXTERNAL_INPORT_TYPES = ["EMS-Input", "CAN-Input", "Private CAN-Input", "LIN-Input"]
|
|
262
|
+
EXTERNAL_OUTPORT_TYPES = ["EMS-Output", "CAN-Output", "Private CAN-Output", "LIN-Output"]
|
|
263
|
+
TYPE_NAME = "type"
|
|
264
|
+
|
|
265
|
+
def get_a2l_format(self, data):
|
|
266
|
+
"""Get a2l format.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
data (dict): Data dictionary.
|
|
270
|
+
Returns:
|
|
271
|
+
dict: A2l format dictionary.
|
|
272
|
+
"""
|
|
273
|
+
return {
|
|
274
|
+
"bitmask": self._get_bitmask(data[self.TYPE_NAME]),
|
|
275
|
+
"description": data["description"],
|
|
276
|
+
"lsb": "2^0",
|
|
277
|
+
"max": data["max"],
|
|
278
|
+
"min": data["min"],
|
|
279
|
+
"offset": "0",
|
|
280
|
+
"unit": data["unit"],
|
|
281
|
+
"x_axis": None,
|
|
282
|
+
"y_axis": None,
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
class ExtVarYaml(ExtVarBase):
|
|
287
|
+
"""Handles variable dicts from Yaml files.
|
|
288
|
+
|
|
289
|
+
Variable dict shall have the following format and is generated by the
|
|
290
|
+
:doc:`YamlSignalInterfaces <signal_interfaces>` class::
|
|
291
|
+
|
|
292
|
+
{
|
|
293
|
+
'input': {
|
|
294
|
+
'sVcIhfa_D_WhlMotSysFrntLimnIndcn': {},
|
|
295
|
+
'sVcIhfa_D_WhlMotSysFrntModSts': {},
|
|
296
|
+
'sVcIhfa_I_WhlMotSysFrntIdc': {},
|
|
297
|
+
'sVcIhfa_U_UDcDcActHiSide1': {},
|
|
298
|
+
'sVcIhfa_U_WhlMotSysFrntUdc': {}
|
|
299
|
+
},
|
|
300
|
+
'output': {},
|
|
301
|
+
'status': {},
|
|
302
|
+
}
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
EXTERNAL_INPORT_TYPES = ["input", "status"]
|
|
306
|
+
EXTERNAL_OUTPORT_TYPES = ["output"]
|
|
307
|
+
TYPE_NAME = "variable_type"
|
|
308
|
+
|
|
309
|
+
def get_a2l_format(self, data):
|
|
310
|
+
"""Get a2l format.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
data (dict): Data dictionary.
|
|
314
|
+
Returns:
|
|
315
|
+
dict: A2l format dictionary.
|
|
316
|
+
"""
|
|
317
|
+
return {
|
|
318
|
+
"bitmask": self._get_bitmask(data[self.TYPE_NAME]),
|
|
319
|
+
"description": data["description"],
|
|
320
|
+
"lsb": "2^0",
|
|
321
|
+
"max": data["range"]["max"],
|
|
322
|
+
"min": data["range"]["min"],
|
|
323
|
+
"offset": "0",
|
|
324
|
+
"unit": data["unit"],
|
|
325
|
+
"x_axis": None,
|
|
326
|
+
"y_axis": None,
|
|
327
|
+
}
|