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.
Files changed (132) hide show
  1. powertrain_build/__init__.py +40 -40
  2. powertrain_build/__main__.py +6 -6
  3. powertrain_build/a2l.py +582 -582
  4. powertrain_build/a2l_merge.py +650 -650
  5. powertrain_build/a2l_templates.py +717 -717
  6. powertrain_build/build.py +985 -985
  7. powertrain_build/build_defs.py +309 -309
  8. powertrain_build/build_proj_config.py +690 -690
  9. powertrain_build/check_interface.py +575 -575
  10. powertrain_build/cli.py +141 -141
  11. powertrain_build/config.py +542 -542
  12. powertrain_build/core.py +395 -395
  13. powertrain_build/core_dummy.py +343 -343
  14. powertrain_build/create_conversion_table.py +73 -73
  15. powertrain_build/dids.py +916 -916
  16. powertrain_build/dummy.py +157 -157
  17. powertrain_build/dummy_spm.py +252 -252
  18. powertrain_build/environmentcheck.py +52 -52
  19. powertrain_build/ext_dbg.py +255 -255
  20. powertrain_build/ext_var.py +327 -327
  21. powertrain_build/feature_configs.py +301 -301
  22. powertrain_build/gen_allsysteminfo.py +227 -227
  23. powertrain_build/gen_label_split.py +449 -449
  24. powertrain_build/handcode_replacer.py +124 -124
  25. powertrain_build/html_report.py +133 -133
  26. powertrain_build/interface/__init__.py +4 -4
  27. powertrain_build/interface/application.py +511 -511
  28. powertrain_build/interface/base.py +500 -500
  29. powertrain_build/interface/csp_api.py +490 -490
  30. powertrain_build/interface/device_proxy.py +677 -677
  31. powertrain_build/interface/ems.py +67 -67
  32. powertrain_build/interface/export_global_vars.py +121 -121
  33. powertrain_build/interface/generate_adapters.py +132 -132
  34. powertrain_build/interface/generate_hi_interface.py +87 -87
  35. powertrain_build/interface/generate_service.py +69 -69
  36. powertrain_build/interface/generate_wrappers.py +147 -147
  37. powertrain_build/interface/generation_utils.py +142 -142
  38. powertrain_build/interface/hal.py +194 -194
  39. powertrain_build/interface/model_yaml_verification.py +348 -348
  40. powertrain_build/interface/service.py +296 -296
  41. powertrain_build/interface/simulink.py +249 -249
  42. powertrain_build/interface/update_call_sources.py +180 -180
  43. powertrain_build/interface/update_model_yaml.py +186 -186
  44. powertrain_build/interface/zone_controller.py +362 -362
  45. powertrain_build/lib/__init__.py +4 -4
  46. powertrain_build/lib/helper_functions.py +127 -127
  47. powertrain_build/lib/logger.py +55 -55
  48. powertrain_build/matlab_scripts/CodeGen/BuildAutomationPyBuild.m +78 -78
  49. powertrain_build/matlab_scripts/CodeGen/Generate_A2L.m +154 -154
  50. powertrain_build/matlab_scripts/CodeGen/generateTLUnit.m +239 -239
  51. powertrain_build/matlab_scripts/CodeGen/getAsilClassification.m +28 -28
  52. powertrain_build/matlab_scripts/CodeGen/modelConfiguredForTL.m +28 -28
  53. powertrain_build/matlab_scripts/CodeGen/moveDefOutports.m +88 -88
  54. powertrain_build/matlab_scripts/CodeGen/parseCalMeasData.m +410 -410
  55. powertrain_build/matlab_scripts/CodeGen/parseCoreIdentifiers.m +139 -139
  56. powertrain_build/matlab_scripts/CodeGen/parseDIDs.m +141 -141
  57. powertrain_build/matlab_scripts/CodeGen/parseInPorts.m +106 -106
  58. powertrain_build/matlab_scripts/CodeGen/parseIncludeConfigs.m +25 -25
  59. powertrain_build/matlab_scripts/CodeGen/parseModelInfo.m +38 -38
  60. powertrain_build/matlab_scripts/CodeGen/parseNVM.m +81 -81
  61. powertrain_build/matlab_scripts/CodeGen/parseOutPorts.m +120 -120
  62. powertrain_build/matlab_scripts/CodeGen/parsePreProcBlks.m +23 -23
  63. powertrain_build/matlab_scripts/CodeGen/struct2JSON.m +128 -128
  64. powertrain_build/matlab_scripts/CodeGen/updateCodeSwConfig.m +31 -31
  65. powertrain_build/matlab_scripts/Init_PyBuild.m +91 -91
  66. powertrain_build/matlab_scripts/__init__.py +2 -2
  67. powertrain_build/matlab_scripts/helperFunctions/Get_Full_Name.m +46 -46
  68. powertrain_build/matlab_scripts/helperFunctions/Get_SrcLines.m +12 -12
  69. powertrain_build/matlab_scripts/helperFunctions/Init_Models.m +78 -78
  70. powertrain_build/matlab_scripts/helperFunctions/Init_Projects.m +67 -67
  71. powertrain_build/matlab_scripts/helperFunctions/Read_Units.m +34 -34
  72. powertrain_build/matlab_scripts/helperFunctions/SetProjectTimeSamples.m +26 -26
  73. powertrain_build/matlab_scripts/helperFunctions/Strip_Suffix.m +16 -16
  74. powertrain_build/matlab_scripts/helperFunctions/followLink.m +118 -118
  75. powertrain_build/matlab_scripts/helperFunctions/getCodeSwitches.m +50 -50
  76. powertrain_build/matlab_scripts/helperFunctions/getConsumerBlocks.m +30 -30
  77. powertrain_build/matlab_scripts/helperFunctions/getDefBlock.m +39 -39
  78. powertrain_build/matlab_scripts/helperFunctions/getDefOutport.m +58 -58
  79. powertrain_build/matlab_scripts/helperFunctions/getDstBlocks.m +19 -19
  80. powertrain_build/matlab_scripts/helperFunctions/getDstLines.m +13 -13
  81. powertrain_build/matlab_scripts/helperFunctions/getInterfaceSignals.m +37 -37
  82. powertrain_build/matlab_scripts/helperFunctions/getName.m +37 -37
  83. powertrain_build/matlab_scripts/helperFunctions/getPath.m +6 -6
  84. powertrain_build/matlab_scripts/helperFunctions/getProperValue.m +21 -21
  85. powertrain_build/matlab_scripts/helperFunctions/getSrcBlocks.m +19 -19
  86. powertrain_build/matlab_scripts/helperFunctions/getSrcLines.m +13 -13
  87. powertrain_build/matlab_scripts/helperFunctions/loadLibraries.m +10 -10
  88. powertrain_build/matlab_scripts/helperFunctions/loadjson.m +6 -6
  89. powertrain_build/matlab_scripts/helperFunctions/modifyEnumStructField.m +21 -21
  90. powertrain_build/matlab_scripts/helperFunctions/removeConfigDuplicates.m +31 -31
  91. powertrain_build/matlab_scripts/helperFunctions/sortSystemByClass.m +26 -26
  92. powertrain_build/matlab_scripts/helperFunctions/tl_getfast.m +89 -89
  93. powertrain_build/matlab_scripts/helperFunctions/topLevelSystem.m +20 -20
  94. powertrain_build/matlab_scripts/helperFunctions/updateModels.m +131 -131
  95. powertrain_build/memory_section.py +224 -224
  96. powertrain_build/nvm_def.py +729 -729
  97. powertrain_build/problem_logger.py +86 -86
  98. powertrain_build/pt_matlab.py +430 -430
  99. powertrain_build/pt_win32.py +144 -144
  100. powertrain_build/replace_compu_tab_ref.py +105 -105
  101. powertrain_build/rte_dummy.py +254 -254
  102. powertrain_build/sched_funcs.py +209 -207
  103. powertrain_build/signal.py +7 -7
  104. powertrain_build/signal_if_html_rep.py +221 -221
  105. powertrain_build/signal_if_html_rep_all.py +302 -302
  106. powertrain_build/signal_incons_html_rep.py +180 -180
  107. powertrain_build/signal_incons_html_rep_all.py +366 -366
  108. powertrain_build/signal_incons_html_rep_base.py +168 -168
  109. powertrain_build/signal_inconsistency_check.py +641 -641
  110. powertrain_build/signal_interfaces.py +864 -864
  111. powertrain_build/templates/Index_SigCheck_All.html +22 -22
  112. powertrain_build/templates/Index_SigIf_All.html +19 -19
  113. powertrain_build/types.py +218 -218
  114. powertrain_build/unit_configs.py +419 -419
  115. powertrain_build/user_defined_types.py +660 -660
  116. powertrain_build/versioncheck.py +66 -66
  117. powertrain_build/wrapper.py +512 -512
  118. powertrain_build/xlrd_csv.py +87 -87
  119. powertrain_build/zone_controller/__init__.py +4 -4
  120. powertrain_build/zone_controller/calibration.py +176 -176
  121. powertrain_build/zone_controller/composition_yaml.py +880 -878
  122. {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/METADATA +100 -100
  123. powertrain_build-1.13.3.dev3.dist-info/RECORD +130 -0
  124. {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/WHEEL +1 -1
  125. {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/licenses/LICENSE +202 -202
  126. powertrain_build-1.13.3.dev3.dist-info/pbr.json +1 -0
  127. powertrain_build-1.13.1.dist-info/RECORD +0 -130
  128. powertrain_build-1.13.1.dist-info/pbr.json +0 -1
  129. {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/entry_points.txt +0 -0
  130. {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/licenses/AUTHORS +0 -0
  131. {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/licenses/NOTICE +0 -0
  132. {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/top_level.txt +0 -0
powertrain_build/core.py CHANGED
@@ -1,395 +1,395 @@
1
- # Copyright 2024 Volvo Car Corporation
2
- # Licensed under Apache 2.0.
3
-
4
- # -*- coding: utf-8 -*-
5
- """This module is used to parse the core definition files.
6
-
7
- Also provides methods to filter the definitions per project.
8
- """
9
-
10
- import os
11
- import time
12
- from collections import defaultdict
13
- from pathlib import Path
14
- from ruamel.yaml import YAML
15
- from powertrain_build import build_defs
16
- from powertrain_build.xlrd_csv import WorkBook
17
- from powertrain_build.problem_logger import ProblemLogger
18
-
19
-
20
- class Core(ProblemLogger):
21
- """A class holding core configuration data."""
22
-
23
- __wrk_sheets = {'EventIDs': {'mdl_col': 0,
24
- 'id_col': 1,
25
- 'desc_col': 2,
26
- 'fid_col': 3,
27
- 'com_col': 4,
28
- 'data_col': 5},
29
- 'FunctionIDs': {'mdl_col': 0,
30
- 'id_col': 1,
31
- 'desc_col': 2,
32
- 'com_col': 3,
33
- 'data_col': 4},
34
- 'IUMPR': {'mdl_col': 0,
35
- 'id_col': 1,
36
- 'desc_col': 2,
37
- 'fid_col': 3,
38
- 'com_col': 4,
39
- 'data_col': 5},
40
- 'Mode$06': {'mdl_col': 0,
41
- 'id_col': 1,
42
- 'desc_col': 2,
43
- 'fid_col': 3,
44
- 'UAS_col': 4,
45
- 'com_col': 5,
46
- 'data_col': 6},
47
- 'Ranking': {'mdl_col': 0,
48
- 'id_col': 1,
49
- 'desc_col': 2,
50
- 'fid_col': 3,
51
- 'com_col': 4,
52
- 'data_col': 5}}
53
-
54
- _NoFid = '_NoFid'
55
-
56
- def __init__(self, project_cfg, unit_cfgs):
57
- """Parse the config files to an internal representation.
58
-
59
- Args:
60
- project_cfg (BuildProjConfig): Project configuration
61
- unit_cfgs (UnitConfigs): Unit definitions
62
- """
63
- super().__init__()
64
- self._prj_cfg = project_cfg
65
- self._unit_cfgs = unit_cfgs
66
- self._csv_files = None
67
- self._read_csv_files(self._prj_cfg.get_prj_cfg_dir())
68
- self._parse_core_config()
69
-
70
- def _read_csv_files(self, config_path):
71
- """Metod for reading the core csv confgiuration files."""
72
- self.info('******************************************************')
73
- self.info('Start parsing the core configuration files')
74
- start_time = time.time()
75
- csv_file_names = []
76
- for sheet in self.__wrk_sheets:
77
- fname = os.path.join(config_path,
78
- 'CoreIdNameDefinition_' + sheet + '.csv')
79
- self.debug('Core csv: %s', fname)
80
- csv_file_names.append(fname)
81
- self._csv_files = WorkBook(csv_file_names)
82
- self.info('Finished parsing the core configuration files (in %4.2f s)', time.time() - start_time)
83
-
84
- def _parse_core_config(self):
85
- """Parse core IDs for all projects."""
86
- # Parse sheet by sheet
87
- tmp_ids = {}
88
- for sheet_name, cols in self.__wrk_sheets.items():
89
- worksheet = self._csv_files.sheet_by_name(sheet_name)
90
- prj_row = worksheet.row(1)
91
- curr_sheet = tmp_ids[sheet_name] = {}
92
- for prj_col in range(cols['data_col'], len(prj_row)):
93
- prj = prj_row[prj_col].value
94
- curr_id = curr_sheet[prj] = {}
95
- for curr_row in range(2, worksheet.nrows):
96
- row = worksheet.row(curr_row)
97
- val = row[prj_col].value
98
- if val and val.strip() in 'xX':
99
- func_tmp = row[cols['id_col']].value.strip()
100
- if func_tmp != '':
101
- if sheet_name == 'Mode$06':
102
- uas_val = row[cols['UAS_col']].value
103
- if isinstance(uas_val, float):
104
- uas_val = int(uas_val)
105
- curr_id[func_tmp] = (row[cols['desc_col']].value,
106
- str(uas_val))
107
- else:
108
- curr_id[func_tmp] = row[
109
- cols['desc_col']].value
110
- # Reformat from Sheet->Proj->Id to Proj->Sheet->Id
111
- self._ids = defaultdict(dict)
112
- for s_name, s_data in tmp_ids.items():
113
- for p_name, p_data in s_data.items():
114
- self._ids[p_name][s_name] = p_data
115
-
116
- def get_core_ids_proj(self, project):
117
- """Get the core IDs for a project.
118
-
119
- Returns:
120
- dict: Core IDs
121
-
122
- """
123
- core_ids = self._ids[project]
124
- # Check for unused core symbols
125
- for sheet_name, sheet_data in core_ids.items():
126
- for id_ in sheet_data:
127
- if not self._unit_cfgs.check_if_in_per_cfg_unit_cfg('core', id_):
128
- self.debug('Core symbol not used in current project: %s/%s', sheet_name, id_)
129
- # Check for undefined core symbols in unit configs
130
- ucfg = self._unit_cfgs.get_per_cfg_unit_cfg()
131
- for id_ in ucfg.get('core', {}):
132
- for _, core_sheet in core_ids.items():
133
- if id_ in core_sheet:
134
- break
135
- else:
136
- self.warning('Core symbol not defined for current project: %s', id_)
137
- return core_ids
138
-
139
- def get_current_core_config(self):
140
- """Return all the core configuration parameters for the current project.
141
-
142
- Returns:
143
- dict: All the core configuration parameters
144
-
145
- """
146
- return self.get_core_ids_proj(self._prj_cfg.get_prj_config())
147
-
148
-
149
- class HICore(ProblemLogger):
150
- """A class holding HI core configuration data."""
151
-
152
- DTC_DEFINITION_FILE_NAME = 'DTCs.yaml'
153
- FILE_NAME = 'VcCoreSupplierAbstraction'
154
-
155
- def __init__(self, project_cfg, unit_cfgs):
156
- """Parse the config files to an internal representation.
157
-
158
- Args:
159
- project_cfg (BuildProjConfig): Project configuration.
160
- unit_cfgs (UnitConfigs): Unit definitions.
161
- """
162
- super().__init__()
163
- self._prj_cfg = project_cfg
164
- self._unit_cfgs = unit_cfgs
165
- self.diagnostic_trouble_codes = self.get_diagnostic_trouble_codes()
166
-
167
- def _get_project_dtcs(self):
168
- """Return a set with DTCs in the currently included SW-Units.
169
-
170
- Returns:
171
- (set): Set of DTCs in the currently included SW-Units.
172
- """
173
- project_dtcs = set()
174
- unit_cfg = self._unit_cfgs.get_per_unit_cfg()
175
- for unit, data in unit_cfg.items():
176
- event_data = data.get('core', {}).get('Events')
177
- if event_data is None:
178
- self.critical(f'No "core" or "core.Events" key in unit config for {unit}.')
179
- continue
180
- project_dtcs |= set(event_data.keys())
181
- return project_dtcs
182
-
183
- def _read_dtc_yaml_file(self):
184
- """Return a set with DTCs loaded from the project DTC yaml file.
185
-
186
- Returns:
187
- (set): Set of DTCs loaded from the DTC yaml file.
188
- """
189
- diagnostic_trouble_codes = {}
190
- dtc_definition_file_path = Path(self._prj_cfg.get_prj_cfg_dir(), self.DTC_DEFINITION_FILE_NAME)
191
- if dtc_definition_file_path.exists():
192
- with dtc_definition_file_path.open(mode='r', encoding='utf-8') as dtc_fh:
193
- yaml = YAML(typ='safe', pure=True)
194
- diagnostic_trouble_codes = yaml.load(dtc_fh)
195
- else:
196
- self.warning(
197
- 'Unable to generate DTC function calls. '
198
- f'Cannot find file: {dtc_definition_file_path.as_posix()}.'
199
- )
200
- return diagnostic_trouble_codes
201
-
202
- def get_diagnostic_trouble_codes(self):
203
- """Return a set of DTCs appearing in both the project and the project yaml file.
204
-
205
- Returns:
206
- (dict): Dict of DTCs, project yaml dict where the keys also appear in the project.
207
- """
208
- project_dtcs = self._get_project_dtcs()
209
- yaml_dtc_dict = self._read_dtc_yaml_file()
210
- yaml_dtcs = set(yaml_dtc_dict.keys())
211
- dtcs_not_in_project = yaml_dtcs - project_dtcs
212
- dtcs_not_in_yaml = project_dtcs - yaml_dtcs
213
- for key in dtcs_not_in_project:
214
- self.warning(f'Ignoring DTC {key} since it does not appear in any model.')
215
- del yaml_dtc_dict[key]
216
- for key in dtcs_not_in_yaml:
217
- self.warning(f'Ignoring DTC {key} since it does not appear in the project DTC yaml file.')
218
- return yaml_dtc_dict
219
-
220
- def get_header_content(self):
221
- """Get content for the DTC header file.
222
-
223
- Returns:
224
- (list(str)): List of lines to write to the DTC header file.
225
- """
226
- name = self._prj_cfg.get_a2l_cfg()['name']
227
- header_guard = f'{self.FILE_NAME.upper()}_H'
228
- header = [
229
- f'#ifndef {header_guard}\n',
230
- f'#define {header_guard}\n',
231
- '\n',
232
- '/* Core API Supplier Abstraction */\n',
233
- '\n',
234
- '#include "tl_basetypes.h"\n',
235
- f'#include "Rte_{name}.h"\n',
236
- '\n'
237
- ]
238
- footer = [f'\n#endif /* {header_guard} */\n']
239
-
240
- if not self.diagnostic_trouble_codes:
241
- return header + footer
242
-
243
- body = [
244
- '/* enum EventStatus {passed=0, failed=1, prepassed=2, prefailed=3} */\n',
245
- '#define Dem_SetEventStatus(EventName, EventStatus)',
246
- ' ',
247
- f'{self.FILE_NAME}_##EventName##_SetEventStatus(EventStatus)\n'
248
- ]
249
- body.append(f'\n#include "{build_defs.PREDECL_CODE_ASIL_D_START}"\n')
250
- for dtc_name in self.diagnostic_trouble_codes:
251
- body.append(f'UInt8 {self.FILE_NAME}_{dtc_name}_SetEventStatus(UInt8 EventStatus);\n')
252
- body.append(f'#include "{build_defs.PREDECL_CODE_ASIL_D_END}"\n')
253
- return header + body + footer
254
-
255
- def get_source_content(self):
256
- """Get content for the DTC source file.
257
-
258
- Returns:
259
- (list(str)): List of lines to write to the DTC source file.
260
- """
261
- header = [
262
- f'#include "{self.FILE_NAME}.h"\n',
263
- '\n'
264
- ]
265
-
266
- if not self.diagnostic_trouble_codes:
267
- return header
268
-
269
- body = [f'#include "{build_defs.CVC_CODE_ASIL_D_START}"\n']
270
- for dtc_name, dtc_id in self.diagnostic_trouble_codes.items():
271
- # hex function removes leading 0, below solution zero pads to 6 digits
272
- dtc_hex_str = f"0x{dtc_id:06X}"
273
- body.extend([
274
- f'UInt8 {self.FILE_NAME}_{dtc_name}_SetEventStatus(UInt8 EventStatus)\n',
275
- '{\n',
276
- f' Rte_Call_Event_DTC_{dtc_hex_str}_SetEventStatus(EventStatus);\n',
277
- ' return 0;\n',
278
- '}\n',
279
- '\n'
280
- ])
281
- body.append(f'#include "{build_defs.CVC_CODE_ASIL_D_END}"\n')
282
-
283
- return header + body
284
-
285
- def generate_dtc_files(self):
286
- """Generate required HI Core header files.
287
- Only use for some projects, which doesn't copy static code."""
288
- file_contents = {
289
- '.h': self.get_header_content(),
290
- '.c': self.get_source_content()
291
- }
292
- src_dst_dir = self._prj_cfg.get_src_code_dst_dir()
293
- for extension, content in file_contents.items():
294
- file_path = Path(src_dst_dir, self.FILE_NAME + extension)
295
- with file_path.open(mode='w', encoding='utf-8') as file_handler:
296
- file_handler.writelines(content)
297
-
298
-
299
- class ZCCore(ProblemLogger):
300
- """A class holding ZC core configuration data."""
301
-
302
- FILE_NAME = 'VcCoreSupplierAbstraction'
303
-
304
- def __init__(self, project_cfg, unit_cfgs):
305
- """Parse the config files to an internal representation.
306
-
307
- Args:
308
- project_cfg (BuildProjConfig): Project configuration.
309
- unit_cfgs (UnitConfigs): Unit definitions.
310
- """
311
- super().__init__()
312
- self._prj_cfg = project_cfg
313
- self._unit_cfgs = unit_cfgs
314
- self.project_dtcs = self._get_project_dtcs()
315
-
316
- def _get_project_dtcs(self):
317
- """Return a set with DTCs in the currently included SW-Units.
318
-
319
- Returns:
320
- (set): Set of DTCs in the currently included SW-Units.
321
- """
322
- project_dtcs = set()
323
- unit_cfg = self._unit_cfgs.get_per_unit_cfg()
324
- for unit, data in unit_cfg.items():
325
- event_data = data.get('core', {}).get('Events')
326
- if event_data is None:
327
- self.critical(f'No "core" or "core.Events" key in unit config for {unit}.')
328
- continue
329
- project_dtcs |= set(event_data.keys())
330
- return project_dtcs
331
-
332
- def get_diagnostic_trouble_codes(self, event_data):
333
- """Return a set of DTCs appearing in both the project and the project yaml file.
334
-
335
- Args:
336
- event_data (dict): Diagnositc event data.
337
- Returns:
338
- (dict): Dict of DTCs, project yaml dict where the keys also appear in the project.
339
- """
340
- valid_dtcs = {}
341
-
342
- dtcs_not_in_yaml = self.project_dtcs - set(event_data.keys())
343
- for key in dtcs_not_in_yaml:
344
- self.warning(f'Ignoring DTC {key} since it does not appear in the project diagnostics yaml file.')
345
-
346
- for dtc_name, dtc_data in event_data.items():
347
- if dtc_name not in self.project_dtcs and not dtc_data.get("manual", False):
348
- self.warning(f'Ignoring DTC {dtc_name}, not defined in any model.')
349
- continue
350
- valid_dtcs[dtc_name] = {k: v for k, v in dtc_data.items() if k != "manual"}
351
- return valid_dtcs
352
-
353
- def get_header_content(self):
354
- """Get content for the DTC header file.
355
-
356
- Returns:
357
- (list(str)): List of lines to write to the DTC header file.
358
- """
359
- name = self._prj_cfg.get_composition_config("softwareComponentName")
360
- header_guard = f'{self.FILE_NAME.upper()}_H'
361
- header = [
362
- f'#ifndef {header_guard}\n',
363
- f'#define {header_guard}\n',
364
- '\n',
365
- '/* Core API Supplier Abstraction */\n',
366
- '\n',
367
- '#include "tl_basetypes.h"\n',
368
- f'#include "Rte_{name}.h"\n',
369
- '\n'
370
- ]
371
- footer = [f'\n#endif /* {header_guard} */\n']
372
-
373
- body = [
374
- '/* enum EventStatus {passed=0, failed=1, prepassed=2, prefailed=3} */\n',
375
- '#define Dem_SetEventStatus(EventName, EventStatus)',
376
- ' ',
377
- 'Rte_Call_Event_##EventName##_SetEventStatus(EventStatus)\n'
378
- ]
379
- return header + body + footer
380
-
381
- def generate_dtc_files(self):
382
- """Generate required ZC Core header files.
383
- Only use for some projects, which doesn't copy static code."""
384
- includeDiagnostics = self._prj_cfg.get_composition_config("includeDiagnostics")
385
- if includeDiagnostics in ["manual", "manual_dtcs"]:
386
- self.warning(f'includeDiagnostics is set to {includeDiagnostics}, not generating DTC files.')
387
- return
388
- file_contents = {
389
- '.h': self.get_header_content()
390
- }
391
- src_dst_dir = self._prj_cfg.get_src_code_dst_dir()
392
- for extension, content in file_contents.items():
393
- file_path = Path(src_dst_dir, self.FILE_NAME + extension)
394
- with file_path.open(mode='w', encoding='utf-8') as file_handler:
395
- file_handler.writelines(content)
1
+ # Copyright 2024 Volvo Car Corporation
2
+ # Licensed under Apache 2.0.
3
+
4
+ # -*- coding: utf-8 -*-
5
+ """This module is used to parse the core definition files.
6
+
7
+ Also provides methods to filter the definitions per project.
8
+ """
9
+
10
+ import os
11
+ import time
12
+ from collections import defaultdict
13
+ from pathlib import Path
14
+ from ruamel.yaml import YAML
15
+ from powertrain_build import build_defs
16
+ from powertrain_build.xlrd_csv import WorkBook
17
+ from powertrain_build.problem_logger import ProblemLogger
18
+
19
+
20
+ class Core(ProblemLogger):
21
+ """A class holding core configuration data."""
22
+
23
+ __wrk_sheets = {'EventIDs': {'mdl_col': 0,
24
+ 'id_col': 1,
25
+ 'desc_col': 2,
26
+ 'fid_col': 3,
27
+ 'com_col': 4,
28
+ 'data_col': 5},
29
+ 'FunctionIDs': {'mdl_col': 0,
30
+ 'id_col': 1,
31
+ 'desc_col': 2,
32
+ 'com_col': 3,
33
+ 'data_col': 4},
34
+ 'IUMPR': {'mdl_col': 0,
35
+ 'id_col': 1,
36
+ 'desc_col': 2,
37
+ 'fid_col': 3,
38
+ 'com_col': 4,
39
+ 'data_col': 5},
40
+ 'Mode$06': {'mdl_col': 0,
41
+ 'id_col': 1,
42
+ 'desc_col': 2,
43
+ 'fid_col': 3,
44
+ 'UAS_col': 4,
45
+ 'com_col': 5,
46
+ 'data_col': 6},
47
+ 'Ranking': {'mdl_col': 0,
48
+ 'id_col': 1,
49
+ 'desc_col': 2,
50
+ 'fid_col': 3,
51
+ 'com_col': 4,
52
+ 'data_col': 5}}
53
+
54
+ _NoFid = '_NoFid'
55
+
56
+ def __init__(self, project_cfg, unit_cfgs):
57
+ """Parse the config files to an internal representation.
58
+
59
+ Args:
60
+ project_cfg (BuildProjConfig): Project configuration
61
+ unit_cfgs (UnitConfigs): Unit definitions
62
+ """
63
+ super().__init__()
64
+ self._prj_cfg = project_cfg
65
+ self._unit_cfgs = unit_cfgs
66
+ self._csv_files = None
67
+ self._read_csv_files(self._prj_cfg.get_prj_cfg_dir())
68
+ self._parse_core_config()
69
+
70
+ def _read_csv_files(self, config_path):
71
+ """Metod for reading the core csv confgiuration files."""
72
+ self.info('******************************************************')
73
+ self.info('Start parsing the core configuration files')
74
+ start_time = time.time()
75
+ csv_file_names = []
76
+ for sheet in self.__wrk_sheets:
77
+ fname = os.path.join(config_path,
78
+ 'CoreIdNameDefinition_' + sheet + '.csv')
79
+ self.debug('Core csv: %s', fname)
80
+ csv_file_names.append(fname)
81
+ self._csv_files = WorkBook(csv_file_names)
82
+ self.info('Finished parsing the core configuration files (in %4.2f s)', time.time() - start_time)
83
+
84
+ def _parse_core_config(self):
85
+ """Parse core IDs for all projects."""
86
+ # Parse sheet by sheet
87
+ tmp_ids = {}
88
+ for sheet_name, cols in self.__wrk_sheets.items():
89
+ worksheet = self._csv_files.sheet_by_name(sheet_name)
90
+ prj_row = worksheet.row(1)
91
+ curr_sheet = tmp_ids[sheet_name] = {}
92
+ for prj_col in range(cols['data_col'], len(prj_row)):
93
+ prj = prj_row[prj_col].value
94
+ curr_id = curr_sheet[prj] = {}
95
+ for curr_row in range(2, worksheet.nrows):
96
+ row = worksheet.row(curr_row)
97
+ val = row[prj_col].value
98
+ if val and val.strip() in 'xX':
99
+ func_tmp = row[cols['id_col']].value.strip()
100
+ if func_tmp != '':
101
+ if sheet_name == 'Mode$06':
102
+ uas_val = row[cols['UAS_col']].value
103
+ if isinstance(uas_val, float):
104
+ uas_val = int(uas_val)
105
+ curr_id[func_tmp] = (row[cols['desc_col']].value,
106
+ str(uas_val))
107
+ else:
108
+ curr_id[func_tmp] = row[
109
+ cols['desc_col']].value
110
+ # Reformat from Sheet->Proj->Id to Proj->Sheet->Id
111
+ self._ids = defaultdict(dict)
112
+ for s_name, s_data in tmp_ids.items():
113
+ for p_name, p_data in s_data.items():
114
+ self._ids[p_name][s_name] = p_data
115
+
116
+ def get_core_ids_proj(self, project):
117
+ """Get the core IDs for a project.
118
+
119
+ Returns:
120
+ dict: Core IDs
121
+
122
+ """
123
+ core_ids = self._ids[project]
124
+ # Check for unused core symbols
125
+ for sheet_name, sheet_data in core_ids.items():
126
+ for id_ in sheet_data:
127
+ if not self._unit_cfgs.check_if_in_per_cfg_unit_cfg('core', id_):
128
+ self.debug('Core symbol not used in current project: %s/%s', sheet_name, id_)
129
+ # Check for undefined core symbols in unit configs
130
+ ucfg = self._unit_cfgs.get_per_cfg_unit_cfg()
131
+ for id_ in ucfg.get('core', {}):
132
+ for _, core_sheet in core_ids.items():
133
+ if id_ in core_sheet:
134
+ break
135
+ else:
136
+ self.warning('Core symbol not defined for current project: %s', id_)
137
+ return core_ids
138
+
139
+ def get_current_core_config(self):
140
+ """Return all the core configuration parameters for the current project.
141
+
142
+ Returns:
143
+ dict: All the core configuration parameters
144
+
145
+ """
146
+ return self.get_core_ids_proj(self._prj_cfg.get_prj_config())
147
+
148
+
149
+ class HICore(ProblemLogger):
150
+ """A class holding HI core configuration data."""
151
+
152
+ DTC_DEFINITION_FILE_NAME = 'DTCs.yaml'
153
+ FILE_NAME = 'VcCoreSupplierAbstraction'
154
+
155
+ def __init__(self, project_cfg, unit_cfgs):
156
+ """Parse the config files to an internal representation.
157
+
158
+ Args:
159
+ project_cfg (BuildProjConfig): Project configuration.
160
+ unit_cfgs (UnitConfigs): Unit definitions.
161
+ """
162
+ super().__init__()
163
+ self._prj_cfg = project_cfg
164
+ self._unit_cfgs = unit_cfgs
165
+ self.diagnostic_trouble_codes = self.get_diagnostic_trouble_codes()
166
+
167
+ def _get_project_dtcs(self):
168
+ """Return a set with DTCs in the currently included SW-Units.
169
+
170
+ Returns:
171
+ (set): Set of DTCs in the currently included SW-Units.
172
+ """
173
+ project_dtcs = set()
174
+ unit_cfg = self._unit_cfgs.get_per_unit_cfg()
175
+ for unit, data in unit_cfg.items():
176
+ event_data = data.get('core', {}).get('Events')
177
+ if event_data is None:
178
+ self.critical(f'No "core" or "core.Events" key in unit config for {unit}.')
179
+ continue
180
+ project_dtcs |= set(event_data.keys())
181
+ return project_dtcs
182
+
183
+ def _read_dtc_yaml_file(self):
184
+ """Return a set with DTCs loaded from the project DTC yaml file.
185
+
186
+ Returns:
187
+ (set): Set of DTCs loaded from the DTC yaml file.
188
+ """
189
+ diagnostic_trouble_codes = {}
190
+ dtc_definition_file_path = Path(self._prj_cfg.get_prj_cfg_dir(), self.DTC_DEFINITION_FILE_NAME)
191
+ if dtc_definition_file_path.exists():
192
+ with dtc_definition_file_path.open(mode='r', encoding='utf-8') as dtc_fh:
193
+ yaml = YAML(typ='safe', pure=True)
194
+ diagnostic_trouble_codes = yaml.load(dtc_fh)
195
+ else:
196
+ self.warning(
197
+ 'Unable to generate DTC function calls. '
198
+ f'Cannot find file: {dtc_definition_file_path.as_posix()}.'
199
+ )
200
+ return diagnostic_trouble_codes
201
+
202
+ def get_diagnostic_trouble_codes(self):
203
+ """Return a set of DTCs appearing in both the project and the project yaml file.
204
+
205
+ Returns:
206
+ (dict): Dict of DTCs, project yaml dict where the keys also appear in the project.
207
+ """
208
+ project_dtcs = self._get_project_dtcs()
209
+ yaml_dtc_dict = self._read_dtc_yaml_file()
210
+ yaml_dtcs = set(yaml_dtc_dict.keys())
211
+ dtcs_not_in_project = yaml_dtcs - project_dtcs
212
+ dtcs_not_in_yaml = project_dtcs - yaml_dtcs
213
+ for key in dtcs_not_in_project:
214
+ self.warning(f'Ignoring DTC {key} since it does not appear in any model.')
215
+ del yaml_dtc_dict[key]
216
+ for key in dtcs_not_in_yaml:
217
+ self.warning(f'Ignoring DTC {key} since it does not appear in the project DTC yaml file.')
218
+ return yaml_dtc_dict
219
+
220
+ def get_header_content(self):
221
+ """Get content for the DTC header file.
222
+
223
+ Returns:
224
+ (list(str)): List of lines to write to the DTC header file.
225
+ """
226
+ name = self._prj_cfg.get_a2l_cfg()['name']
227
+ header_guard = f'{self.FILE_NAME.upper()}_H'
228
+ header = [
229
+ f'#ifndef {header_guard}\n',
230
+ f'#define {header_guard}\n',
231
+ '\n',
232
+ '/* Core API Supplier Abstraction */\n',
233
+ '\n',
234
+ '#include "tl_basetypes.h"\n',
235
+ f'#include "Rte_{name}.h"\n',
236
+ '\n'
237
+ ]
238
+ footer = [f'\n#endif /* {header_guard} */\n']
239
+
240
+ if not self.diagnostic_trouble_codes:
241
+ return header + footer
242
+
243
+ body = [
244
+ '/* enum EventStatus {passed=0, failed=1, prepassed=2, prefailed=3} */\n',
245
+ '#define Dem_SetEventStatus(EventName, EventStatus)',
246
+ ' ',
247
+ f'{self.FILE_NAME}_##EventName##_SetEventStatus(EventStatus)\n'
248
+ ]
249
+ body.append(f'\n#include "{build_defs.PREDECL_CODE_ASIL_D_START}"\n')
250
+ for dtc_name in self.diagnostic_trouble_codes:
251
+ body.append(f'UInt8 {self.FILE_NAME}_{dtc_name}_SetEventStatus(UInt8 EventStatus);\n')
252
+ body.append(f'#include "{build_defs.PREDECL_CODE_ASIL_D_END}"\n')
253
+ return header + body + footer
254
+
255
+ def get_source_content(self):
256
+ """Get content for the DTC source file.
257
+
258
+ Returns:
259
+ (list(str)): List of lines to write to the DTC source file.
260
+ """
261
+ header = [
262
+ f'#include "{self.FILE_NAME}.h"\n',
263
+ '\n'
264
+ ]
265
+
266
+ if not self.diagnostic_trouble_codes:
267
+ return header
268
+
269
+ body = [f'#include "{build_defs.CVC_CODE_ASIL_D_START}"\n']
270
+ for dtc_name, dtc_id in self.diagnostic_trouble_codes.items():
271
+ # hex function removes leading 0, below solution zero pads to 6 digits
272
+ dtc_hex_str = f"0x{dtc_id:06X}"
273
+ body.extend([
274
+ f'UInt8 {self.FILE_NAME}_{dtc_name}_SetEventStatus(UInt8 EventStatus)\n',
275
+ '{\n',
276
+ f' Rte_Call_Event_DTC_{dtc_hex_str}_SetEventStatus(EventStatus);\n',
277
+ ' return 0;\n',
278
+ '}\n',
279
+ '\n'
280
+ ])
281
+ body.append(f'#include "{build_defs.CVC_CODE_ASIL_D_END}"\n')
282
+
283
+ return header + body
284
+
285
+ def generate_dtc_files(self):
286
+ """Generate required HI Core header files.
287
+ Only use for some projects, which doesn't copy static code."""
288
+ file_contents = {
289
+ '.h': self.get_header_content(),
290
+ '.c': self.get_source_content()
291
+ }
292
+ src_dst_dir = self._prj_cfg.get_src_code_dst_dir()
293
+ for extension, content in file_contents.items():
294
+ file_path = Path(src_dst_dir, self.FILE_NAME + extension)
295
+ with file_path.open(mode='w', encoding='utf-8') as file_handler:
296
+ file_handler.writelines(content)
297
+
298
+
299
+ class ZCCore(ProblemLogger):
300
+ """A class holding ZC core configuration data."""
301
+
302
+ FILE_NAME = 'VcCoreSupplierAbstraction'
303
+
304
+ def __init__(self, project_cfg, unit_cfgs):
305
+ """Parse the config files to an internal representation.
306
+
307
+ Args:
308
+ project_cfg (BuildProjConfig): Project configuration.
309
+ unit_cfgs (UnitConfigs): Unit definitions.
310
+ """
311
+ super().__init__()
312
+ self._prj_cfg = project_cfg
313
+ self._unit_cfgs = unit_cfgs
314
+ self.project_dtcs = self._get_project_dtcs()
315
+
316
+ def _get_project_dtcs(self):
317
+ """Return a set with DTCs in the currently included SW-Units.
318
+
319
+ Returns:
320
+ (set): Set of DTCs in the currently included SW-Units.
321
+ """
322
+ project_dtcs = set()
323
+ unit_cfg = self._unit_cfgs.get_per_unit_cfg()
324
+ for unit, data in unit_cfg.items():
325
+ event_data = data.get('core', {}).get('Events')
326
+ if event_data is None:
327
+ self.critical(f'No "core" or "core.Events" key in unit config for {unit}.')
328
+ continue
329
+ project_dtcs |= set(event_data.keys())
330
+ return project_dtcs
331
+
332
+ def get_diagnostic_trouble_codes(self, event_data):
333
+ """Return a set of DTCs appearing in both the project and the project yaml file.
334
+
335
+ Args:
336
+ event_data (dict): Diagnositc event data.
337
+ Returns:
338
+ (dict): Dict of DTCs, project yaml dict where the keys also appear in the project.
339
+ """
340
+ valid_dtcs = {}
341
+
342
+ dtcs_not_in_yaml = self.project_dtcs - set(event_data.keys())
343
+ for key in dtcs_not_in_yaml:
344
+ self.warning(f'Ignoring DTC {key} since it does not appear in the project diagnostics yaml file.')
345
+
346
+ for dtc_name, dtc_data in event_data.items():
347
+ if dtc_name not in self.project_dtcs and not dtc_data.get("manual", False):
348
+ self.warning(f'Ignoring DTC {dtc_name}, not defined in any model.')
349
+ continue
350
+ valid_dtcs[dtc_name] = {k: v for k, v in dtc_data.items() if k != "manual"}
351
+ return valid_dtcs
352
+
353
+ def get_header_content(self):
354
+ """Get content for the DTC header file.
355
+
356
+ Returns:
357
+ (list(str)): List of lines to write to the DTC header file.
358
+ """
359
+ name = self._prj_cfg.get_composition_config("softwareComponentName")
360
+ header_guard = f'{self.FILE_NAME.upper()}_H'
361
+ header = [
362
+ f'#ifndef {header_guard}\n',
363
+ f'#define {header_guard}\n',
364
+ '\n',
365
+ '/* Core API Supplier Abstraction */\n',
366
+ '\n',
367
+ '#include "tl_basetypes.h"\n',
368
+ f'#include "Rte_{name}.h"\n',
369
+ '\n'
370
+ ]
371
+ footer = [f'\n#endif /* {header_guard} */\n']
372
+
373
+ body = [
374
+ '/* enum EventStatus {passed=0, failed=1, prepassed=2, prefailed=3} */\n',
375
+ '#define Dem_SetEventStatus(EventName, EventStatus)',
376
+ ' ',
377
+ 'Rte_Call_Event_##EventName##_SetEventStatus(EventStatus)\n'
378
+ ]
379
+ return header + body + footer
380
+
381
+ def generate_dtc_files(self):
382
+ """Generate required ZC Core header files.
383
+ Only use for some projects, which doesn't copy static code."""
384
+ includeDiagnostics = self._prj_cfg.get_composition_config("includeDiagnostics")
385
+ if includeDiagnostics in ["manual", "manual_dtcs"]:
386
+ self.warning(f'includeDiagnostics is set to {includeDiagnostics}, not generating DTC files.')
387
+ return
388
+ file_contents = {
389
+ '.h': self.get_header_content()
390
+ }
391
+ src_dst_dir = self._prj_cfg.get_src_code_dst_dir()
392
+ for extension, content in file_contents.items():
393
+ file_path = Path(src_dst_dir, self.FILE_NAME + extension)
394
+ with file_path.open(mode='w', encoding='utf-8') as file_handler:
395
+ file_handler.writelines(content)