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/build.py CHANGED
@@ -1,985 +1,985 @@
1
- # Copyright 2024 Volvo Car Corporation
2
- # Licensed under Apache 2.0.
3
-
4
- # -*- coding: utf-8 -*-
5
- """Python module used for building a Vcc SPM SW release.
6
-
7
- This is the entry point to powertrain-build which includes all other needed modules.
8
- Loads configuration files and sequences the code generation steps.
9
- """
10
-
11
- import glob
12
- import logging
13
- import os
14
- import shutil
15
- import sys
16
- import time
17
- from os.path import join as pjoin
18
- from pathlib import Path
19
-
20
- from powertrain_build import __config_version__, __version__, build_defs
21
- from powertrain_build.a2l_merge import A2lMerge
22
- from powertrain_build.build_proj_config import BuildProjConfig
23
- from powertrain_build.core import Core, HICore, ZCCore
24
- from powertrain_build.core_dummy import CoreDummy
25
- from powertrain_build.create_conversion_table import create_conversion_table
26
- from powertrain_build.dids import DIDs, HIDIDs, ZCDIDs
27
- from powertrain_build.dummy import DummyVar
28
- from powertrain_build.dummy_spm import DummySpm
29
- from powertrain_build.ext_dbg import ExtDbg
30
- from powertrain_build.ext_var import ExtVarCsv, ExtVarYaml
31
- from powertrain_build.feature_configs import FeatureConfigs
32
- from powertrain_build.lib.helper_functions import create_dir, get_repo_root, merge_dicts
33
- from powertrain_build.memory_section import MemorySection
34
- from powertrain_build.nvm_def import NVMDef, ZCNVMDef
35
- from powertrain_build.problem_logger import ProblemLogger
36
- from powertrain_build.replace_compu_tab_ref import replace_tab_verb
37
- from powertrain_build.rte_dummy import RteDummy
38
- from powertrain_build.sched_funcs import SchedFuncs
39
- from powertrain_build.signal_if_html_rep import SigIfHtmlReport
40
- from powertrain_build.signal_incons_html_rep import SigConsHtmlReport
41
- from powertrain_build.signal_interfaces import CsvSignalInterfaces, YamlSignalInterfaces
42
- from powertrain_build.unit_configs import CodeGenerators, UnitConfigs
43
- from powertrain_build.user_defined_types import UserDefinedTypes
44
- from powertrain_build.zone_controller.calibration import ZoneControllerCalibration
45
- from powertrain_build.zone_controller.composition_yaml import CompositionYaml
46
-
47
- LOG = logging.getLogger()
48
- REPO_ROOT = get_repo_root()
49
-
50
-
51
- def setup_logging(log_dst_dir, problem_logger, debug=True, quiet=False):
52
- """Set up the python logger for the build environment.
53
-
54
- Three logger streams are set up. One that log to stdout (info level),
55
- and one to a build.log file (info level), and finally, on stream that
56
- logs to build_dbg.log (debug level log). The log files are put in the
57
- directory configured in the config file.
58
-
59
- Args:
60
- log_dst_dir (str): the path to where the log file should be stored
61
- problem_logger (obj): the ProblemLogger object to initialise
62
- debug (bool): True - if debug log shall be generated
63
- quiet (bool): False - disable logging to stdout
64
-
65
- """
66
- LOG.setLevel(logging.DEBUG)
67
- LOG.handlers = [] # Remove all previous loggers
68
- logging.captureWarnings(True)
69
- # Setup debug build logger
70
- log_file = pjoin(log_dst_dir, "build_dbg.log")
71
- if debug:
72
- dbg = logging.FileHandler(log_file)
73
- dbg.setLevel(logging.DEBUG)
74
- dbg_formatter = logging.Formatter(
75
- "%(asctime)s - %(module)s."
76
- "%(funcName)s [%(lineno)d]"
77
- " - %(levelname)s - %(message)s"
78
- )
79
- dbg.setFormatter(dbg_formatter)
80
- LOG.addHandler(dbg)
81
- # Setup normal build logger
82
- log_file = pjoin(log_dst_dir, "build.log")
83
- nrm = logging.FileHandler(log_file)
84
- nrm.setLevel(logging.INFO)
85
- build_log_frmt = logging.Formatter("%(asctime)s - %(levelname)s" " - %(message)s")
86
- nrm.setFormatter(build_log_frmt)
87
- LOG.addHandler(nrm)
88
-
89
- if not quiet:
90
- nrm_strm = logging.StreamHandler(sys.stdout)
91
- nrm_strm.setLevel(logging.INFO)
92
- nrm_strm.setFormatter(build_log_frmt)
93
- LOG.addHandler(nrm_strm)
94
-
95
- error_strm = logging.StreamHandler(sys.stderr)
96
- error_strm.setLevel(logging.CRITICAL)
97
- error_strm.setFormatter(build_log_frmt)
98
- LOG.addHandler(error_strm)
99
-
100
- problem_logger.init_logger(LOG)
101
-
102
-
103
- def check_interfaces(build_cfg, signal_if):
104
- """Check the interfaces.
105
-
106
- Checks interfaces in all configurations, and generates a html
107
- report with the result of the checks.
108
-
109
- Args:
110
- build_cfg (BuildProjConfig): Build project class holding where
111
- files should be stored
112
- signal_if (SignalInterfaces): class holding signal interface information
113
-
114
- """
115
- LOG.info("******************************************************")
116
- LOG.info("Start check interface inconsistencies")
117
- start_time = time.time()
118
- report_dst_dir = build_cfg.get_reports_dst_dir()
119
- signal_inconsistency_result = signal_if.check_config()
120
- sig_report = SigConsHtmlReport(signal_inconsistency_result)
121
- LOG.info(
122
- "Finished check interface inconsistencies (in %4.2f s)",
123
- time.time() - start_time,
124
- )
125
-
126
- start_time = time.time()
127
- LOG.info("******************************************************")
128
- LOG.info("Start generating interface inconsistencies html-report")
129
- sig_report.generate_report_file(pjoin(report_dst_dir, "SigCheck.html"))
130
- LOG.info(
131
- "Finished - generating interface inconsistencies html-report (in %4.2f s)",
132
- time.time() - start_time,
133
- )
134
-
135
-
136
- def interface_report(build_cfg, unit_cfg, signal_if):
137
- """Create report of signal interfaces.
138
-
139
- Creates a report of interfaces in all configurations, and generates
140
- a html-report with the result of the checks.
141
-
142
- Args:
143
- build_cfg (BuildProjConfig): Build project class holding where
144
- files should be stored.
145
- unit_cfg (UnitConfigs): Class holding all unit interfaces.
146
- signal_if (SignalInterfaces): class holding signal interface information.
147
-
148
- """
149
- LOG.info("******************************************************")
150
- LOG.info("Start creating interface report")
151
- start_time = time.time()
152
- report_dst_dir = build_cfg.get_reports_dst_dir()
153
-
154
- sig_if = SigIfHtmlReport(build_cfg, unit_cfg, signal_if)
155
- sig_if.generate_report_file(pjoin(report_dst_dir, "SigIf.html"))
156
- LOG.info(
157
- "Finished - create interface report (in %4.2f s)", time.time() - start_time
158
- )
159
-
160
-
161
- def generate_dummy_spm(build_cfg, unit_cfg, feature_cfg, signal_if, udt):
162
- """Generate c-files that define unit output signals.
163
-
164
- Args:
165
- build_cfg (BuildProjConfig): Build project class holding where files should be stored.
166
- unit_cfg (UnitConfigs): Aggregated unit configs class.
167
- feature_cfg (FeatureConfigs): Used as a library to generate C-macros.
168
- signal_if (SignalInterfaces): Class holding signal interface information.
169
- udt (UserDefinedTypes): Class holding user defined data types.
170
- """
171
-
172
- def _add_undefined_signals_from_unit(data):
173
- """Add undefined signals from unit.
174
-
175
- Includes included configs.
176
- Arguments:
177
- data (dict): Data for the unit
178
- """
179
- for signal_name, inport_attributes in data.get("inports", {}).items():
180
- if signal_name in defined_ports:
181
- continue
182
- if (
183
- feature_cfg.check_if_active_in_config(inport_attributes["configs"])
184
- or not build_cfg.allow_undefined_unused
185
- ):
186
- defined_ports.append(signal_name)
187
- undefined_outports.append(inport_attributes)
188
- for include_unit in data.get("includes", []):
189
- include_data = unit_cfg.get_unit_config(include_unit)
190
- _add_undefined_signals_from_unit(include_data)
191
-
192
- LOG.info("******************************************************")
193
- LOG.info("Start generating output vars")
194
- start_time = time.time()
195
- dst_dir = build_cfg.get_src_code_dst_dir()
196
- # Get out ports for all units in project regardless of code switches
197
- unit_vars = unit_cfg.get_per_unit_cfg_total()
198
- undefined_outports = []
199
- defined_ports = []
200
-
201
- for data in unit_vars.values():
202
- for outport_name, outport_data in data.get("outports", {}).items():
203
- if not feature_cfg.check_if_active_in_config(outport_data["configs"]):
204
- LOG.debug("Outport %s not active in current project", outport_name)
205
- elif outport_name not in defined_ports:
206
- if not outport_data.get("class").startswith("CVC_EXT"):
207
- defined_ports.append(outport_name)
208
- defined_ports.extend(signal_if.get_externally_defined_ports())
209
-
210
- for data in unit_vars.values():
211
- _add_undefined_signals_from_unit(data)
212
-
213
- dummy_spm = DummySpm(
214
- undefined_outports, build_cfg, feature_cfg, unit_cfg, udt, "VcDummy_spm"
215
- )
216
- dummy_spm.generate_files(dst_dir)
217
- LOG.info("Finished generating output vars (in %4.2f s)", time.time() - start_time)
218
-
219
-
220
- def generate_did_files(build_cfg, unit_cfg):
221
- """Generate DIDAPI definition files.
222
-
223
- Args:
224
- build_cfg (BuildProjConfig): Build project class holding where
225
- files should be stored
226
- unit_cfg (UnitConfigs): class holding units definitions,
227
- and which units to include
228
-
229
- """
230
- start_time = time.time()
231
- did_defs_files = pjoin(build_cfg.get_src_code_dst_dir(), "VcDIDDefinition")
232
- car_com_file = build_cfg.get_car_com_dst()
233
- LOG.info("******************************************************")
234
- LOG.info("Start generating %s.c&h", did_defs_files)
235
- dids = DIDs(build_cfg, unit_cfg)
236
- dids.gen_did_def_files(did_defs_files)
237
- LOG.info(
238
- "Finished generating %s.c&h (in %4.2f s)",
239
- did_defs_files,
240
- time.time() - start_time,
241
- )
242
- LOG.info("******************************************************")
243
- LOG.info("Start generating %s", car_com_file)
244
- start_time = time.time()
245
- dids.gen_did_carcom_extract(car_com_file)
246
- LOG.info(
247
- "Finished generating %s (in %4.2f s)", car_com_file, time.time() - start_time
248
- )
249
- LOG.info("******************************************************")
250
-
251
-
252
- def generate_core_dummy(build_cfg, core, unit_cfg):
253
- """Generate the Core dummy files.
254
-
255
- The core dummy creates RTE dummy functions,
256
- and Id variables for enabling testing of VCC Software. If this dummy is not
257
- included, it is not possible to build the project until the supplier deliver
258
- an updated diagnostic core SW.
259
-
260
- Note:
261
- These dummy files shall not be delivered to the supplier!
262
-
263
- Args:
264
- build_cfg (BuildProjConfig): Build project class holding where
265
- files should be stored
266
- core (Core): class holding core configuration information
267
-
268
- """
269
- core_dummy_fname = build_cfg.get_core_dummy_name()
270
- LOG.info("******************************************************")
271
- LOG.info("Start generating Core Dummy - %s", core_dummy_fname)
272
- start_time = time.time()
273
- core_dummy = CoreDummy(core.get_current_core_config(), unit_cfg)
274
- ecu_supplier = build_cfg.get_ecu_info()[0]
275
- if ecu_supplier in ["Denso", "CSP"]:
276
- core_dummy.generate_dg2_core_dummy_files(core_dummy_fname)
277
- elif ecu_supplier == "RB":
278
- core_dummy.generate_rb_core_dummy_files(core_dummy_fname)
279
- else:
280
- msg = f"Could not generate VcCoreDummy, cannot identify the supplier {ecu_supplier}."
281
- LOG.critical(msg)
282
- raise ValueError(msg)
283
- LOG.info("Finished generating Core Dummy (in %4.2f s)", time.time() - start_time)
284
-
285
-
286
- def generate_external_var(build_cfg, unit_cfg, udt, asil_level_dep, nrm_dict, dep_dict, sec_dict):
287
- """Generate two c-files that define the signal interface to the supplier.
288
-
289
- The VcExtVar function assigns all variables to the CVC_DISP memory area,
290
- while the ExtVarSafe.c are allocated to the CVC_DISP_ASIL_B memory area.
291
- Note that this function only declares the variables
292
- in the supplier interface, which the supplier writes to. All other
293
- variables shall be declared by the function which writes to the variable.
294
- Note that dummy functionality/variables should be created in the function
295
- to keep the signalling interface consistent!
296
-
297
- Args:
298
- build_cfg (BuildProjConfig): Build project class holding where files should be stored.
299
- unit_cfg (UnitConfigs) : Aggregated unit configs class.
300
- udt (UserDefinedTypes): Class holding user defined data types.
301
- asil_level_dep (str): ASIL level for the dependability variables.
302
- nrm_dict (dict): Dictionary with normal variables.
303
- dep_dict (dict): Dictionary with dependability variables.
304
- sec_dict (dict): Dictionary with secure variables.
305
- """
306
- if build_cfg.has_yaml_interface:
307
- ext_var_nrm = ExtVarYaml(nrm_dict, build_cfg, unit_cfg, udt)
308
- ext_var_dep = ExtVarYaml(dep_dict, build_cfg, unit_cfg, udt, asil_level_dep)
309
- else:
310
- ext_var_nrm = ExtVarCsv(nrm_dict, build_cfg, unit_cfg, udt)
311
- ext_var_dep = ExtVarCsv(dep_dict, build_cfg, unit_cfg, udt, asil_level_dep)
312
- ext_var_sec = ExtVarCsv(sec_dict, build_cfg, unit_cfg, udt, build_defs.SECURE)
313
-
314
- ext_var_instances = {
315
- ext_var_nrm: "VcExtVar",
316
- ext_var_dep: "VcExtVarSafe",
317
- }
318
-
319
- if not build_cfg.has_yaml_interface:
320
- ext_var_instances[ext_var_sec] = "VcExtVarSecure"
321
-
322
- for instance, dir_name in ext_var_instances.items():
323
- ext_var_path = Path(build_cfg.get_src_code_dst_dir(), dir_name)
324
- instance.generate_files(ext_var_path)
325
-
326
-
327
- def generate_dummy_var(build_cfg, unit_cfg, signal_if, udt):
328
- """Generate c-file that define the missing signals.
329
-
330
- Args:
331
- build_cfg (BuildProjConfig): Build project class holding where files should be stored.
332
- unit_cfg (UnitConfigs) : Aggregated unit configs class.
333
- signal_if (SignalInterfaces): class holding signal interface information.
334
- udt (UserDefinedTypes): Class holding user defined data types.
335
- """
336
- LOG.info("******************************************************")
337
- LOG.info("Start generating VcDummy")
338
- start_time = time.time()
339
- dst_dir = build_cfg.get_src_code_dst_dir()
340
- nrm_dict, dep_dict, sec_dict, _ = signal_if.get_external_io()
341
- nrm_dict = merge_dicts(nrm_dict, dep_dict, merge_recursively=True)
342
- nrm_dict = merge_dicts(nrm_dict, sec_dict, merge_recursively=True)
343
- res_dict = signal_if.check_config()
344
- dummy = DummyVar(unit_cfg, nrm_dict, res_dict, build_cfg, udt)
345
- dummy.generate_file(pjoin(dst_dir, "VcDummy"))
346
- LOG.info("Finished generating VcDummy (in %4.2f s)", time.time() - start_time)
347
-
348
-
349
- def generate_nvm_def(build_cfg, unit_cfg, no_nvm_a2l):
350
- """Generate the c&h-files which declares the NVM-ram.
351
-
352
- The NVM-ram is declared in a struct per datatype length, in order
353
- to provide a defined order in RAM/FLASH/EEPROM for the tester
354
- communication service. Furthermore, # defines with the variables are
355
- created to minimize the needed model changes for access to the memory.
356
-
357
- Args:
358
- build_cfg (BuildProjConfig): Build project class holding where files should be stored.
359
- unit_cfg (UnitConfigs): class holding units definitions, and which units to include.
360
- no_nvm_a2l (bool): Do not generate A2L for NVM structs.
361
- """
362
- LOG.info("******************************************************")
363
- LOG.info("Start generating NVMDefinitions")
364
- start_time = time.time()
365
- tot_vars_nvm = unit_cfg.get_per_cfg_unit_cfg().get("nvm", {})
366
- nvm_def = NVMDef(build_cfg, unit_cfg, tot_vars_nvm)
367
- nvm_def.generate_nvm_config_files(no_nvm_a2l)
368
- LOG.info(
369
- "Finished generating NVMDefinitions (in %4.2f s)", time.time() - start_time
370
- )
371
-
372
-
373
- def copy_unit_src_to_src_out(build_cfg):
374
- """Copy unit source code to delivery folder.
375
-
376
- Function to copy all relevant .c, .h and .a2l files to the src
377
- delivery folder (defined in the config file for the project),
378
- from the units that are included in the project.
379
-
380
- Args:
381
- build_cfg (BuildProjConfig): Build project class holding where
382
- files should be stored
383
- """
384
- LOG.info("******************************************************")
385
- LOG.info("Start copying unit source files")
386
- start_time = time.time()
387
- src_dirs = build_cfg.get_unit_src_dirs()
388
- src_dst_dir = build_cfg.get_src_code_dst_dir()
389
- files = []
390
- for src_dir in src_dirs.values():
391
- files.extend(glob.glob(pjoin(src_dir, "*.c")))
392
- files.extend(glob.glob(pjoin(src_dir, "*.cpp")))
393
- files.extend(glob.glob(pjoin(src_dir, "*.h")))
394
- for file_ in files:
395
- shutil.copy2(file_, src_dst_dir)
396
- LOG.debug("copied %s to %s", file_, src_dst_dir)
397
- LOG.info(
398
- "Finished copying unit source files (in %4.2f s)", time.time() - start_time
399
- )
400
-
401
-
402
- def copy_common_src_to_src_out(build_cfg):
403
- """Copy source code to delivery folder.
404
-
405
- Function to copy all relevant .c and .h files to the src
406
- delivery folder (defined in the config file for the project),
407
- from the units that are included in the project.
408
-
409
- Optionally, also patch the defined functions with the "schedulerPrefix".
410
-
411
- Args:
412
- build_cfg (BuildProjConfig): Build project class holding where files should be stored.
413
- """
414
- LOG.info("******************************************************")
415
- prefix = build_cfg.get_scheduler_prefix()
416
- if prefix:
417
- LOG.info("Start copying and patching common source files")
418
- else:
419
- LOG.info("Start copying common source files")
420
-
421
- start_time = time.time()
422
- src_dir = build_cfg.get_common_src_dir()
423
- src_dst_dir = build_cfg.get_src_code_dst_dir()
424
- included_common_files = build_cfg.get_included_common_files()
425
-
426
- files = [
427
- pjoin(src_dir, common_file + ".c") for common_file in included_common_files
428
- ]
429
- files.extend(
430
- [pjoin(src_dir, common_file + ".h") for common_file in included_common_files]
431
- )
432
-
433
- files_to_copy = filter(os.path.isfile, files)
434
- for file_ in files_to_copy:
435
- if prefix:
436
- patch_and_copy_common_src_to_src_out(prefix, Path(file_), Path(src_dst_dir))
437
- else:
438
- shutil.copy2(file_, src_dst_dir)
439
- LOG.debug("copied %s to %s", file_, src_dst_dir)
440
-
441
- LOG.info(
442
- "Finished copying common source files (in %4.2f s)", time.time() - start_time
443
- )
444
-
445
-
446
- def patch_and_copy_common_src_to_src_out(prefix, file_path, dest_dir):
447
- """Copy common source code to delivery folder, patched with "schedulerPrefix" as prefix.
448
-
449
- Args:
450
- prefix (str): Prefix.
451
- file_path (Path): Path to file to patch and copy.
452
- dest_dir (Path): Destination directory for the patched file.
453
- """
454
- with file_path.open(mode="r", encoding="utf-8") as file_handle:
455
- content = file_handle.read()
456
-
457
- new_function = f"{prefix}{file_path.stem}"
458
- new_content = content.replace(f"{file_path.stem}(", f"{new_function}(")
459
- new_content_lines = new_content.splitlines()
460
-
461
- if file_path.suffix == ".h":
462
- defines_index = next(
463
- (idx for idx, line in enumerate(new_content_lines) if "DEFINES" in line and "(OPT)" not in line),
464
- None
465
- )
466
- if defines_index is not None:
467
- # Insert at defines_index + 2, +1 to get to the next line and +1 to get after multiline comment
468
- new_content_lines.insert(defines_index + 2, f"#define {file_path.stem} {new_function}")
469
-
470
- with Path(dest_dir, file_path.name).open(mode="w", encoding="utf-8") as file_handle:
471
- file_handle.write("\n".join(new_content_lines))
472
-
473
-
474
- def copy_files_to_include(build_cfg):
475
- """Copy source code to delivery folder.
476
-
477
- Function to copy all extra include files to the src delivery folder
478
- (defined in the config file for the project),
479
- from the units that are included in the project.
480
-
481
- Args:
482
- build_cfg (BuildProjConfig): Build project class holding where
483
- files should be stored
484
- """
485
- LOG.info("******************************************************")
486
- LOG.info("Start copying extra included source files")
487
- start_time = time.time()
488
- src_dst_dir = build_cfg.get_src_code_dst_dir()
489
-
490
- # Copy some files flat to the destination directory
491
- include_paths = build_cfg.get_includes_paths_flat()
492
- files = []
493
- for include_path in include_paths:
494
- if os.path.isdir(include_path):
495
- files.extend(
496
- [
497
- Path(include_path, file_name)
498
- for file_name in Path(include_path).iterdir()
499
- if not file_name.is_dir()
500
- ]
501
- )
502
- elif os.path.isfile(include_path):
503
- files.append(include_path)
504
- else:
505
- LOG.critical("File or directory %s not found", include_path)
506
- for file_ in files:
507
- shutil.copy2(file_, src_dst_dir)
508
- LOG.debug("copied %s to %s", file_, src_dst_dir)
509
-
510
- # Copy some directories as is to the destination directory
511
- include_tree_paths = [Path(p) for p in build_cfg.get_includes_paths_tree()]
512
- existing_tree_paths = [p for p in include_tree_paths if p.exists()]
513
- missing_tree_paths = [p for p in include_tree_paths if not p.exists()]
514
- if missing_tree_paths:
515
- LOG.warning(f"Missing include paths: {missing_tree_paths}")
516
- for path in existing_tree_paths:
517
- for file_ in path.rglob("*"):
518
- if file_.is_file():
519
- new_path = Path(src_dst_dir, file_.relative_to(path))
520
- create_dir(new_path.parent)
521
- shutil.copy2(file_, new_path)
522
- LOG.debug("copied %s to %s", file_, new_path)
523
- LOG.info(
524
- "Finished copying extra included files (in %4.2f s)", time.time() - start_time
525
- )
526
-
527
-
528
- def copy_unit_cfgs_to_output(build_cfg):
529
- """Copy all relevant unit configuration files to delivery folder.
530
-
531
- Function to copy all relevant unit config .json files to the UnitCfg
532
- delivery folder (defined in the config file for the project),
533
- from the units that are included in the project.
534
-
535
- Args:
536
- build_cfg (BuildProjConfig): Build project class holding where
537
- files should be stored
538
- """
539
- cfg_dst_dir = build_cfg.get_unit_cfg_deliv_dir()
540
- if cfg_dst_dir is not None:
541
- LOG.info("******************************************************")
542
- LOG.info("Start copying the unit config files")
543
- start_time = time.time()
544
- cfg_dirs = build_cfg.get_unit_cfg_dirs()
545
- files = []
546
- for cfg_dir in cfg_dirs.values():
547
- files.extend(glob.glob(pjoin(cfg_dir, "*.json")))
548
- for file_ in files:
549
- shutil.copy2(file_, cfg_dst_dir)
550
- LOG.debug("copied %s to %s", file_, cfg_dst_dir)
551
- LOG.info(
552
- "Finished copying the unit config files (in %4.2f s)",
553
- time.time() - start_time,
554
- )
555
-
556
-
557
- def merge_a2l_files(build_cfg, unit_cfg, complete_a2l=False, silver_a2l=False):
558
- """Merge a2l-files.
559
-
560
- Args:
561
- build_cfg (BuildProjConfig): Build project class holding where
562
- files should be stored
563
- unit_cfg (UnitConfigs): class holding units definitions,
564
- and which units to include
565
- Returns:
566
- a2l (A2lMerge): A2lMerge class holding the merged a2l data.
567
- """
568
- LOG.info("******************************************************")
569
- LOG.info("Start merging A2L-files")
570
- start_time = time.time()
571
- src_dirs = build_cfg.get_unit_src_dirs()
572
- src_dst_dir = build_cfg.get_src_code_dst_dir()
573
- a2l_files_unit = []
574
- for src_dir in src_dirs.values():
575
- a2l_files_unit.extend(glob.glob(pjoin(src_dir, "*.a2l")))
576
- a2l_files_gen = glob.glob(pjoin(src_dst_dir, "*.a2l"))
577
- a2l = A2lMerge(build_cfg, unit_cfg, a2l_files_unit, a2l_files_gen)
578
- new_a2l_file = os.path.join(src_dst_dir, build_cfg.get_a2l_name())
579
- # LOG.debug(new_a2l_file)
580
- a2l.merge(new_a2l_file, complete_a2l, silver_a2l)
581
- LOG.info("Finished merging A2L-files (in %4.2f s)", time.time() - start_time)
582
- return a2l
583
-
584
-
585
- def find_all_project_configs(prj_cfg_file):
586
- """Find all Project config files."""
587
- prj_root_dir, _ = os.path.split(prj_cfg_file)
588
- prj_root_dir = os.path.abspath(prj_root_dir)
589
- all_cfg_path = os.path.join(prj_root_dir, "..", "*", "ProjectCfg.json")
590
- return glob.glob(all_cfg_path, recursive=True)
591
-
592
-
593
- def propagate_tag_name(build_cfg, tag_name, problem_logger):
594
- """Set tag name in relevant files, for release builds.
595
-
596
- Args:
597
- build_cfg (BuildProjConfig): Build project class holding where files should be stored.
598
- tag_name (str): git tag name.
599
- problem_logger (object): logger for powertrain_build.
600
- """
601
- LOG.info("******************************************************")
602
- LOG.info("Propagating tag name: %s", tag_name)
603
- start_time = time.time()
604
-
605
- src_dst_dir = build_cfg.get_src_code_dst_dir()
606
- h_file_path = os.path.join(src_dst_dir, "vcc_sp_version.h")
607
-
608
- if not os.path.isfile(h_file_path):
609
- problem_logger.critical("Missing %s", h_file_path)
610
- return
611
-
612
- with open(h_file_path, "r+", encoding="utf-8") as file_handle:
613
- contents = file_handle.read()
614
- file_handle.seek(0)
615
- new_contents = contents.replace(
616
- '#define VCC_SOFTWARE_NAME "tagname"',
617
- f'#define VCC_SOFTWARE_NAME "{tag_name}"',
618
- )
619
- file_handle.write(new_contents)
620
-
621
- LOG.info("Finished propagating tag name (in %4.2f s)", time.time() - start_time)
622
-
623
-
624
- def add_args(parser):
625
- """Add command line arguments for powertrain_build.
626
-
627
- This is useful when powertrain-build should be run through a command line wrapper function.
628
-
629
- Args:
630
- parser (argparse.ArgumentParser): Parser instance to add arguments to.
631
- """
632
- powertrain_build_parser = parser.add_argument_group("powertrain-build arguments")
633
- powertrain_build_parser.add_argument(
634
- "--project-config", required=True, help="Project root configuration file"
635
- )
636
- powertrain_build_parser.add_argument(
637
- "--generate-system-info", action="store_true", help="Generate AllSystemInfo.mat"
638
- )
639
- powertrain_build_parser.add_argument(
640
- "--generate-custom-conv-tab",
641
- default=None,
642
- help="Path to conversion table file. Useful for TargetLink enums in A2L file.",
643
- )
644
- powertrain_build_parser.add_argument(
645
- "--core-dummy",
646
- action="store_true",
647
- help="Generate core dummy code to enable integration with old supplier code",
648
- )
649
- powertrain_build_parser.add_argument(
650
- "--rte-dummy",
651
- action="store_true",
652
- help="Generate RTE dummy code to enable e.g. Silver testing",
653
- )
654
- powertrain_build_parser.add_argument(
655
- "--debug", action="store_true", help="Activate the debug log"
656
- )
657
- powertrain_build_parser.add_argument(
658
- "--no-abort", action="store_true", help="Do not abort due to errors"
659
- )
660
- powertrain_build_parser.add_argument(
661
- "--no-nvm-a2l",
662
- action="store_true",
663
- help="Do not generate a2l file for NVM structs",
664
- )
665
- powertrain_build_parser.add_argument(
666
- "--complete-a2l", action="store_true", help="Generate A2L with project info"
667
- )
668
- powertrain_build_parser.add_argument(
669
- "--silver-a2l",
670
- action="store_true",
671
- help="Generate A2L file with Silver patching. Complete A2L argument takes precedence.",
672
- )
673
- powertrain_build_parser.add_argument(
674
- "--interface", action="store_true", help="Generate interface report"
675
- )
676
- powertrain_build_parser.add_argument(
677
- "--generate-rte-checkpoint-calls",
678
- action="store_true",
679
- help="Generate RTE function checkpoint calls",
680
- )
681
- powertrain_build_parser.add_argument(
682
- "--version",
683
- action="version",
684
- version=f"%(prog)s {__version__}",
685
- help="Display program version",
686
- )
687
-
688
-
689
- def build(
690
- project_config,
691
- interface=False,
692
- core_dummy=False,
693
- rte_dummy=False,
694
- no_abort=False,
695
- no_nvm_a2l=False,
696
- debug=False,
697
- quiet=False,
698
- generate_system_info=False,
699
- generate_custom_conversion_table=None,
700
- complete_a2l=False,
701
- silver_a2l=False,
702
- generate_rte_checkpoint_calls=False,
703
- ):
704
- """Execute the build.
705
-
706
- Args:
707
- project_config (str): Project configuration file.
708
- interface (bool): Generate interface report. Default=False.
709
- core_dummy (bool): Generate core dummy code. Default=False.
710
- rte_dummy (bool): Generate RTE dummy code. Default=False.
711
- no_abort (bool): Do not abort due to errors. Default=False.
712
- no_nvm_a2l (bool): Do not generate A2L for NVM structs. Default=False.
713
- debug (bool): Activate the debug log. Default=False.
714
- quiet (bool): Disable logging to stdout. Default=False.
715
- generate_system_info (bool): Generate AllSystemInfo.mat for DocGen compatibility. Default=False.
716
- generate_custom_conversion_table (str): Path to conversion table file.
717
- Useful for TargetLink enums in A2L file. Default=None.
718
- complete_a2l (bool): Add an a2l header plus additional content such as XCP data.
719
- silver_a2l (bool): Add an a2l header plus additional patching required for Silver.
720
- generate_rte_checkpoint_calls (bool): Generate RTE function checkpoint calls.
721
- """
722
- try:
723
- problem_logger = ProblemLogger()
724
- tot_start_time = time.time()
725
- project_config_files = find_all_project_configs(project_config)
726
- prj_cfgs = {}
727
-
728
- for project_config_file in project_config_files:
729
- conf = BuildProjConfig(os.path.normpath(project_config_file))
730
- prj_cfgs.update({conf.name: conf})
731
-
732
- prj_cfgs = {}
733
- build_cfg = BuildProjConfig(os.path.normpath(project_config))
734
- prj_cfgs.update({build_cfg.name: build_cfg})
735
-
736
- build_cfg.create_build_dirs()
737
- src_dst_dir = build_cfg.get_src_code_dst_dir()
738
-
739
- setup_logging(build_cfg.get_log_dst_dir(), problem_logger, debug, quiet)
740
- LOG.info("Starting build")
741
- LOG.info("powertrain_build version is: %s", __version__)
742
- LOG.info("Project/Model config file version is: %s", __config_version__)
743
- LOG.info("Read SPM code switches")
744
- start_time = time.time()
745
- feature_cfg = FeatureConfigs(build_cfg)
746
- LOG.info(
747
- "Finished reading SPM code switches (in %4.2f s)", time.time() - start_time
748
- )
749
-
750
- LOG.info("******************************************************")
751
- LOG.info("Start generating per project unit config data")
752
- start_time = time.time()
753
- unit_cfg = UnitConfigs(build_cfg, feature_cfg)
754
- LOG.info(
755
- "Finished generating per project unit config data (in %4.2f s)",
756
- time.time() - start_time,
757
- )
758
-
759
- code_generation_config = build_cfg.get_code_generation_config()
760
-
761
- udt = UserDefinedTypes(build_cfg, unit_cfg)
762
- udt.generate_common_header_files()
763
-
764
- start_time = time.time()
765
- cnf_header = pjoin(src_dst_dir, build_cfg.get_feature_conf_header_name())
766
- LOG.info("******************************************************")
767
- LOG.info("Generate compiler switches header file %s", cnf_header)
768
- feature_cfg.gen_unit_cfg_header_file(cnf_header)
769
- LOG.info(
770
- "Finished generating compiler switches header file (in %4.2f s)",
771
- time.time() - start_time,
772
- )
773
- if build_cfg.has_yaml_interface:
774
- signal_if = YamlSignalInterfaces(build_cfg, unit_cfg, feature_cfg, udt)
775
- else:
776
- signal_if = CsvSignalInterfaces(build_cfg, unit_cfg)
777
- check_interfaces(build_cfg, signal_if)
778
- if interface:
779
- interface_report(build_cfg, unit_cfg, signal_if)
780
-
781
- LOG.info("******************************************************")
782
- LOG.info("Start generating VcExtVar and VcDebug")
783
- start_time = time.time()
784
- asil_level_db = build_defs.CVC_ASIL_LEVEL_MAP[code_generation_config["generalAsilLevelDebug"]]
785
- asil_level_dep = build_defs.ASIL_LEVEL_MAP[code_generation_config["generalAsilLevelDependability"]]
786
- nrm_dict, dep_dict, sec_dict, dbg_dict = signal_if.get_external_io()
787
-
788
- generate_external_var(build_cfg, unit_cfg, udt, asil_level_dep, nrm_dict, dep_dict, sec_dict)
789
-
790
- restructured_dbg_dict = {}
791
- dbg_instances = {
792
- ExtDbg(dbg_dict, build_cfg, unit_cfg): ("VcDebug", "VcDebugOutput"),
793
- ExtDbg(dep_dict, build_cfg, unit_cfg, asil_level_db): ("VcDebugSafe", "VcDebugOutputSafe")
794
- }
795
- for instance, dir_names in dbg_instances.items():
796
- restructured_dbg_dict.update({
797
- dir_names[0]: instance.dbg_dict["inputs"],
798
- dir_names[1]: instance.dbg_dict["outputs"]
799
- })
800
- instance.gen_dbg_files(
801
- pjoin(build_cfg.get_src_code_dst_dir(), dir_names[0]),
802
- pjoin(build_cfg.get_src_code_dst_dir(), dir_names[1])
803
- )
804
- LOG.info("Finished generating VcExtVar and VcDebug (in %4.2f s)", time.time() - start_time)
805
-
806
- if not code_generation_config["generateDummyVar"]:
807
- LOG.info("******************************************************")
808
- LOG.info("Skip generating VcDummy file")
809
- else:
810
- generate_dummy_var(build_cfg, unit_cfg, signal_if, udt)
811
-
812
- custom_dummy_spm = build_cfg.get_use_custom_dummy_spm()
813
- if custom_dummy_spm is not None:
814
- LOG.info("******************************************************")
815
- if os.path.isfile(custom_dummy_spm):
816
- LOG.info("Copying custom dummy spm file (%s)", custom_dummy_spm)
817
- shutil.copy2(custom_dummy_spm, build_cfg.get_src_code_dst_dir())
818
- else:
819
- LOG.warning(
820
- "Cannot find desired custom dummy spm file: %s", custom_dummy_spm
821
- )
822
- generate_dummy_spm(build_cfg, unit_cfg, feature_cfg, signal_if, udt)
823
- else:
824
- generate_dummy_spm(build_cfg, unit_cfg, feature_cfg, signal_if, udt)
825
-
826
- custom_sources = build_cfg.get_use_custom_sources()
827
- if custom_sources is not None:
828
- LOG.info("******************************************************")
829
- for custom_src in custom_sources:
830
- if os.path.isfile(custom_src):
831
- LOG.info("Copying custom sourcefile (%s)", custom_src)
832
- shutil.copy2(custom_src, build_cfg.get_src_code_dst_dir())
833
- else:
834
- LOG.warning("Cannot find desired custom sourcefile: %s", custom_src)
835
-
836
- LOG.info("******************************************************")
837
- LOG.info("Start generating the scheduling functions")
838
- start_time = time.time()
839
- gen_schd = SchedFuncs(build_cfg, unit_cfg, restructured_dbg_dict)
840
- gen_schd.generate_sched_c_fncs(generate_rte_checkpoint_calls)
841
- LOG.info("Finished generating the scheduling functions (in %4.2f s)", time.time() - start_time)
842
-
843
- LOG.info("******************************************************")
844
- LOG.info("Start generating the ts header file")
845
- start_time = time.time()
846
- gen_schd.generate_ts_defines(pjoin(src_dst_dir, build_cfg.get_ts_header_name()))
847
- LOG.info("Finished generating ts header file (in %4.2f s)", time.time() - start_time)
848
-
849
- # Generate AllSystemInfo.mat for DocGen compatibility
850
- if generate_system_info:
851
- from powertrain_build.gen_allsysteminfo import GenAllSystemInfo
852
-
853
- gen_all_system_info = GenAllSystemInfo(signal_if, unit_cfg)
854
- gen_all_system_info.build()
855
-
856
- # Check if errors
857
- if not no_abort:
858
- if problem_logger.errors():
859
- nbr_err = problem_logger.get_nbr_problems()
860
- problem_logger.info(
861
- "Aborting build due to errors (# critical:%s, # warnings:%s"
862
- " after %4.2f s.",
863
- nbr_err["critical"],
864
- nbr_err["warning"],
865
- time.time() - tot_start_time,
866
- )
867
- return 1
868
-
869
- # Copy files to output folder
870
- copy_unit_src_to_src_out(build_cfg)
871
- copy_common_src_to_src_out(build_cfg)
872
- copy_unit_cfgs_to_output(build_cfg)
873
- copy_files_to_include(build_cfg)
874
- if code_generation_config["generateInterfaceHeaders"]:
875
- memory_section = MemorySection(build_cfg, unit_cfg)
876
- memory_section.generate_required_header_files()
877
-
878
- # Propagate tag name for release builds, TAG_NAME must be set in environment
879
- tag_name = os.environ.get("TAG_NAME", "")
880
- if tag_name and code_generation_config["propagateTagName"]:
881
- propagate_tag_name(build_cfg, tag_name, problem_logger)
882
-
883
- # Copy header files (subversion is using an external that points to
884
- # the correct set of pragma section header_files
885
-
886
- # Make A2L-file
887
- if generate_custom_conversion_table is not None:
888
- ctable_json = Path(generate_custom_conversion_table).resolve()
889
- ctable_a2l = Path(build_cfg.get_src_code_dst_dir(), "custom_tabs.a2l")
890
- create_conversion_table(ctable_json, ctable_a2l)
891
- merged_a2l = merge_a2l_files(build_cfg, unit_cfg, complete_a2l, silver_a2l)
892
- a2l_file_path = Path(build_cfg.get_src_code_dst_dir(), build_cfg.get_a2l_name())
893
- replace_tab_verb(a2l_file_path)
894
-
895
- # Generate interface files
896
- if code_generation_config["generateYamlInterfaceFile"]:
897
- zc_core = ZCCore(build_cfg, unit_cfg)
898
- zc_dids = ZCDIDs(build_cfg, unit_cfg)
899
- LOG.info("******************************************************")
900
- LOG.info("Start generating NVMDefinitions")
901
- start_time = time.time()
902
- project_nvm_defintions = unit_cfg.get_per_cfg_unit_cfg().get("nvm", {})
903
- zc_nvm = ZCNVMDef(build_cfg, unit_cfg, project_nvm_defintions)
904
- LOG.info(
905
- "Finished generating NVMDefinitions (in %4.2f s)", time.time() - start_time
906
- )
907
- LOG.info("******************************************************")
908
- axis_data = merged_a2l.get_characteristic_axis_data()
909
- composition_yaml = CompositionYaml(
910
- build_cfg,
911
- signal_if,
912
- unit_cfg,
913
- zc_core,
914
- zc_dids,
915
- zc_nvm,
916
- axis_data,
917
- udt.get_enumerations()
918
- )
919
- composition_yaml.generate_yaml()
920
- LOG.info("******************************************************")
921
- LOG.info("Generating Core header")
922
- zc_core.generate_dtc_files()
923
- LOG.info("******************************************************")
924
- LOG.info("Generating DID files")
925
- zc_dids.generate_did_files()
926
- LOG.info("******************************************************")
927
- LOG.info("Generating NVM definitions")
928
- zc_nvm.generate_nvm_rte_files()
929
-
930
- if rte_dummy:
931
- LOG.info("******************************************************")
932
- LOG.info("Generating RTE dummy files")
933
- zc_rte = RteDummy(build_cfg, zc_nvm, composition_yaml.cal_class_info["tl"])
934
- zc_rte.generate_rte_dummy()
935
-
936
- if code_generation_config["generateCalibrationInterfaceFiles"]:
937
- LOG.info("******************************************************")
938
- if code_generation_config["useCalibrationRteMacroExpansion"]:
939
- LOG.warning(
940
- "Skip generating calibration interface files as useCalibrationRteMacroExpansion is set to true"
941
- )
942
- else:
943
- LOG.info("Generating calibration interface files")
944
- zc_calibration = ZoneControllerCalibration(
945
- build_cfg, composition_yaml.cal_class_info["tl"]
946
- )
947
- zc_calibration.generate_calibration_interface_files()
948
- elif build_cfg.get_ecu_info()[0] == "HI":
949
- generate_nvm_def(build_cfg, unit_cfg, no_nvm_a2l)
950
- LOG.info("******************************************************")
951
- LOG.info("Generating Core header")
952
- hi_core = HICore(build_cfg, unit_cfg)
953
- hi_core.generate_dtc_files()
954
- LOG.info("******************************************************")
955
- LOG.info("Generating DID files")
956
- dids = HIDIDs(build_cfg, unit_cfg)
957
- dids.generate_did_files()
958
- else:
959
- generate_nvm_def(build_cfg, unit_cfg, no_nvm_a2l)
960
- generate_did_files(build_cfg, unit_cfg)
961
- # generate core dummy files if requested
962
- if core_dummy:
963
- core_dummy_fname = os.path.basename(build_cfg.get_core_dummy_name())
964
- if CodeGenerators.embedded_coder in unit_cfg.code_generators:
965
- LOG.info("******************************************************")
966
- LOG.info("Skip generating %s for EC projects", core_dummy_fname)
967
- elif code_generation_config["generateCoreDummy"]:
968
- LOG.info("******************************************************")
969
- LOG.info("Skip generating %s for SPA2+ projects", core_dummy_fname)
970
- else:
971
- core = Core(build_cfg, unit_cfg)
972
- generate_core_dummy(build_cfg, core, unit_cfg)
973
-
974
- if problem_logger.errors():
975
- problem_logger.info(
976
- "Critical errors were detected, aborting" " after %4.2f s.",
977
- time.time() - tot_start_time,
978
- )
979
- return 1
980
-
981
- LOG.info("Finished build in %4.2f s", time.time() - tot_start_time)
982
- return 0
983
-
984
- finally:
985
- logging.shutdown()
1
+ # Copyright 2024 Volvo Car Corporation
2
+ # Licensed under Apache 2.0.
3
+
4
+ # -*- coding: utf-8 -*-
5
+ """Python module used for building a Vcc SPM SW release.
6
+
7
+ This is the entry point to powertrain-build which includes all other needed modules.
8
+ Loads configuration files and sequences the code generation steps.
9
+ """
10
+
11
+ import glob
12
+ import logging
13
+ import os
14
+ import shutil
15
+ import sys
16
+ import time
17
+ from os.path import join as pjoin
18
+ from pathlib import Path
19
+
20
+ from powertrain_build import __config_version__, __version__, build_defs
21
+ from powertrain_build.a2l_merge import A2lMerge
22
+ from powertrain_build.build_proj_config import BuildProjConfig
23
+ from powertrain_build.core import Core, HICore, ZCCore
24
+ from powertrain_build.core_dummy import CoreDummy
25
+ from powertrain_build.create_conversion_table import create_conversion_table
26
+ from powertrain_build.dids import DIDs, HIDIDs, ZCDIDs
27
+ from powertrain_build.dummy import DummyVar
28
+ from powertrain_build.dummy_spm import DummySpm
29
+ from powertrain_build.ext_dbg import ExtDbg
30
+ from powertrain_build.ext_var import ExtVarCsv, ExtVarYaml
31
+ from powertrain_build.feature_configs import FeatureConfigs
32
+ from powertrain_build.lib.helper_functions import create_dir, get_repo_root, merge_dicts
33
+ from powertrain_build.memory_section import MemorySection
34
+ from powertrain_build.nvm_def import NVMDef, ZCNVMDef
35
+ from powertrain_build.problem_logger import ProblemLogger
36
+ from powertrain_build.replace_compu_tab_ref import replace_tab_verb
37
+ from powertrain_build.rte_dummy import RteDummy
38
+ from powertrain_build.sched_funcs import SchedFuncs
39
+ from powertrain_build.signal_if_html_rep import SigIfHtmlReport
40
+ from powertrain_build.signal_incons_html_rep import SigConsHtmlReport
41
+ from powertrain_build.signal_interfaces import CsvSignalInterfaces, YamlSignalInterfaces
42
+ from powertrain_build.unit_configs import CodeGenerators, UnitConfigs
43
+ from powertrain_build.user_defined_types import UserDefinedTypes
44
+ from powertrain_build.zone_controller.calibration import ZoneControllerCalibration
45
+ from powertrain_build.zone_controller.composition_yaml import CompositionYaml
46
+
47
+ LOG = logging.getLogger()
48
+ REPO_ROOT = get_repo_root()
49
+
50
+
51
+ def setup_logging(log_dst_dir, problem_logger, debug=True, quiet=False):
52
+ """Set up the python logger for the build environment.
53
+
54
+ Three logger streams are set up. One that log to stdout (info level),
55
+ and one to a build.log file (info level), and finally, on stream that
56
+ logs to build_dbg.log (debug level log). The log files are put in the
57
+ directory configured in the config file.
58
+
59
+ Args:
60
+ log_dst_dir (str): the path to where the log file should be stored
61
+ problem_logger (obj): the ProblemLogger object to initialise
62
+ debug (bool): True - if debug log shall be generated
63
+ quiet (bool): False - disable logging to stdout
64
+
65
+ """
66
+ LOG.setLevel(logging.DEBUG)
67
+ LOG.handlers = [] # Remove all previous loggers
68
+ logging.captureWarnings(True)
69
+ # Setup debug build logger
70
+ log_file = pjoin(log_dst_dir, "build_dbg.log")
71
+ if debug:
72
+ dbg = logging.FileHandler(log_file)
73
+ dbg.setLevel(logging.DEBUG)
74
+ dbg_formatter = logging.Formatter(
75
+ "%(asctime)s - %(module)s."
76
+ "%(funcName)s [%(lineno)d]"
77
+ " - %(levelname)s - %(message)s"
78
+ )
79
+ dbg.setFormatter(dbg_formatter)
80
+ LOG.addHandler(dbg)
81
+ # Setup normal build logger
82
+ log_file = pjoin(log_dst_dir, "build.log")
83
+ nrm = logging.FileHandler(log_file)
84
+ nrm.setLevel(logging.INFO)
85
+ build_log_frmt = logging.Formatter("%(asctime)s - %(levelname)s" " - %(message)s")
86
+ nrm.setFormatter(build_log_frmt)
87
+ LOG.addHandler(nrm)
88
+
89
+ if not quiet:
90
+ nrm_strm = logging.StreamHandler(sys.stdout)
91
+ nrm_strm.setLevel(logging.INFO)
92
+ nrm_strm.setFormatter(build_log_frmt)
93
+ LOG.addHandler(nrm_strm)
94
+
95
+ error_strm = logging.StreamHandler(sys.stderr)
96
+ error_strm.setLevel(logging.CRITICAL)
97
+ error_strm.setFormatter(build_log_frmt)
98
+ LOG.addHandler(error_strm)
99
+
100
+ problem_logger.init_logger(LOG)
101
+
102
+
103
+ def check_interfaces(build_cfg, signal_if):
104
+ """Check the interfaces.
105
+
106
+ Checks interfaces in all configurations, and generates a html
107
+ report with the result of the checks.
108
+
109
+ Args:
110
+ build_cfg (BuildProjConfig): Build project class holding where
111
+ files should be stored
112
+ signal_if (SignalInterfaces): class holding signal interface information
113
+
114
+ """
115
+ LOG.info("******************************************************")
116
+ LOG.info("Start check interface inconsistencies")
117
+ start_time = time.time()
118
+ report_dst_dir = build_cfg.get_reports_dst_dir()
119
+ signal_inconsistency_result = signal_if.check_config()
120
+ sig_report = SigConsHtmlReport(signal_inconsistency_result)
121
+ LOG.info(
122
+ "Finished check interface inconsistencies (in %4.2f s)",
123
+ time.time() - start_time,
124
+ )
125
+
126
+ start_time = time.time()
127
+ LOG.info("******************************************************")
128
+ LOG.info("Start generating interface inconsistencies html-report")
129
+ sig_report.generate_report_file(pjoin(report_dst_dir, "SigCheck.html"))
130
+ LOG.info(
131
+ "Finished - generating interface inconsistencies html-report (in %4.2f s)",
132
+ time.time() - start_time,
133
+ )
134
+
135
+
136
+ def interface_report(build_cfg, unit_cfg, signal_if):
137
+ """Create report of signal interfaces.
138
+
139
+ Creates a report of interfaces in all configurations, and generates
140
+ a html-report with the result of the checks.
141
+
142
+ Args:
143
+ build_cfg (BuildProjConfig): Build project class holding where
144
+ files should be stored.
145
+ unit_cfg (UnitConfigs): Class holding all unit interfaces.
146
+ signal_if (SignalInterfaces): class holding signal interface information.
147
+
148
+ """
149
+ LOG.info("******************************************************")
150
+ LOG.info("Start creating interface report")
151
+ start_time = time.time()
152
+ report_dst_dir = build_cfg.get_reports_dst_dir()
153
+
154
+ sig_if = SigIfHtmlReport(build_cfg, unit_cfg, signal_if)
155
+ sig_if.generate_report_file(pjoin(report_dst_dir, "SigIf.html"))
156
+ LOG.info(
157
+ "Finished - create interface report (in %4.2f s)", time.time() - start_time
158
+ )
159
+
160
+
161
+ def generate_dummy_spm(build_cfg, unit_cfg, feature_cfg, signal_if, udt):
162
+ """Generate c-files that define unit output signals.
163
+
164
+ Args:
165
+ build_cfg (BuildProjConfig): Build project class holding where files should be stored.
166
+ unit_cfg (UnitConfigs): Aggregated unit configs class.
167
+ feature_cfg (FeatureConfigs): Used as a library to generate C-macros.
168
+ signal_if (SignalInterfaces): Class holding signal interface information.
169
+ udt (UserDefinedTypes): Class holding user defined data types.
170
+ """
171
+
172
+ def _add_undefined_signals_from_unit(data):
173
+ """Add undefined signals from unit.
174
+
175
+ Includes included configs.
176
+ Arguments:
177
+ data (dict): Data for the unit
178
+ """
179
+ for signal_name, inport_attributes in data.get("inports", {}).items():
180
+ if signal_name in defined_ports:
181
+ continue
182
+ if (
183
+ feature_cfg.check_if_active_in_config(inport_attributes["configs"])
184
+ or not build_cfg.allow_undefined_unused
185
+ ):
186
+ defined_ports.append(signal_name)
187
+ undefined_outports.append(inport_attributes)
188
+ for include_unit in data.get("includes", []):
189
+ include_data = unit_cfg.get_unit_config(include_unit)
190
+ _add_undefined_signals_from_unit(include_data)
191
+
192
+ LOG.info("******************************************************")
193
+ LOG.info("Start generating output vars")
194
+ start_time = time.time()
195
+ dst_dir = build_cfg.get_src_code_dst_dir()
196
+ # Get out ports for all units in project regardless of code switches
197
+ unit_vars = unit_cfg.get_per_unit_cfg_total()
198
+ undefined_outports = []
199
+ defined_ports = []
200
+
201
+ for data in unit_vars.values():
202
+ for outport_name, outport_data in data.get("outports", {}).items():
203
+ if not feature_cfg.check_if_active_in_config(outport_data["configs"]):
204
+ LOG.debug("Outport %s not active in current project", outport_name)
205
+ elif outport_name not in defined_ports:
206
+ if not outport_data.get("class").startswith("CVC_EXT"):
207
+ defined_ports.append(outport_name)
208
+ defined_ports.extend(signal_if.get_externally_defined_ports())
209
+
210
+ for data in unit_vars.values():
211
+ _add_undefined_signals_from_unit(data)
212
+
213
+ dummy_spm = DummySpm(
214
+ undefined_outports, build_cfg, feature_cfg, unit_cfg, udt, "VcDummy_spm"
215
+ )
216
+ dummy_spm.generate_files(dst_dir)
217
+ LOG.info("Finished generating output vars (in %4.2f s)", time.time() - start_time)
218
+
219
+
220
+ def generate_did_files(build_cfg, unit_cfg):
221
+ """Generate DIDAPI definition files.
222
+
223
+ Args:
224
+ build_cfg (BuildProjConfig): Build project class holding where
225
+ files should be stored
226
+ unit_cfg (UnitConfigs): class holding units definitions,
227
+ and which units to include
228
+
229
+ """
230
+ start_time = time.time()
231
+ did_defs_files = pjoin(build_cfg.get_src_code_dst_dir(), "VcDIDDefinition")
232
+ car_com_file = build_cfg.get_car_com_dst()
233
+ LOG.info("******************************************************")
234
+ LOG.info("Start generating %s.c&h", did_defs_files)
235
+ dids = DIDs(build_cfg, unit_cfg)
236
+ dids.gen_did_def_files(did_defs_files)
237
+ LOG.info(
238
+ "Finished generating %s.c&h (in %4.2f s)",
239
+ did_defs_files,
240
+ time.time() - start_time,
241
+ )
242
+ LOG.info("******************************************************")
243
+ LOG.info("Start generating %s", car_com_file)
244
+ start_time = time.time()
245
+ dids.gen_did_carcom_extract(car_com_file)
246
+ LOG.info(
247
+ "Finished generating %s (in %4.2f s)", car_com_file, time.time() - start_time
248
+ )
249
+ LOG.info("******************************************************")
250
+
251
+
252
+ def generate_core_dummy(build_cfg, core, unit_cfg):
253
+ """Generate the Core dummy files.
254
+
255
+ The core dummy creates RTE dummy functions,
256
+ and Id variables for enabling testing of VCC Software. If this dummy is not
257
+ included, it is not possible to build the project until the supplier deliver
258
+ an updated diagnostic core SW.
259
+
260
+ Note:
261
+ These dummy files shall not be delivered to the supplier!
262
+
263
+ Args:
264
+ build_cfg (BuildProjConfig): Build project class holding where
265
+ files should be stored
266
+ core (Core): class holding core configuration information
267
+
268
+ """
269
+ core_dummy_fname = build_cfg.get_core_dummy_name()
270
+ LOG.info("******************************************************")
271
+ LOG.info("Start generating Core Dummy - %s", core_dummy_fname)
272
+ start_time = time.time()
273
+ core_dummy = CoreDummy(core.get_current_core_config(), unit_cfg)
274
+ ecu_supplier = build_cfg.get_ecu_info()[0]
275
+ if ecu_supplier in ["Denso", "CSP"]:
276
+ core_dummy.generate_dg2_core_dummy_files(core_dummy_fname)
277
+ elif ecu_supplier == "RB":
278
+ core_dummy.generate_rb_core_dummy_files(core_dummy_fname)
279
+ else:
280
+ msg = f"Could not generate VcCoreDummy, cannot identify the supplier {ecu_supplier}."
281
+ LOG.critical(msg)
282
+ raise ValueError(msg)
283
+ LOG.info("Finished generating Core Dummy (in %4.2f s)", time.time() - start_time)
284
+
285
+
286
+ def generate_external_var(build_cfg, unit_cfg, udt, asil_level_dep, nrm_dict, dep_dict, sec_dict):
287
+ """Generate two c-files that define the signal interface to the supplier.
288
+
289
+ The VcExtVar function assigns all variables to the CVC_DISP memory area,
290
+ while the ExtVarSafe.c are allocated to the CVC_DISP_ASIL_B memory area.
291
+ Note that this function only declares the variables
292
+ in the supplier interface, which the supplier writes to. All other
293
+ variables shall be declared by the function which writes to the variable.
294
+ Note that dummy functionality/variables should be created in the function
295
+ to keep the signalling interface consistent!
296
+
297
+ Args:
298
+ build_cfg (BuildProjConfig): Build project class holding where files should be stored.
299
+ unit_cfg (UnitConfigs) : Aggregated unit configs class.
300
+ udt (UserDefinedTypes): Class holding user defined data types.
301
+ asil_level_dep (str): ASIL level for the dependability variables.
302
+ nrm_dict (dict): Dictionary with normal variables.
303
+ dep_dict (dict): Dictionary with dependability variables.
304
+ sec_dict (dict): Dictionary with secure variables.
305
+ """
306
+ if build_cfg.has_yaml_interface:
307
+ ext_var_nrm = ExtVarYaml(nrm_dict, build_cfg, unit_cfg, udt)
308
+ ext_var_dep = ExtVarYaml(dep_dict, build_cfg, unit_cfg, udt, asil_level_dep)
309
+ else:
310
+ ext_var_nrm = ExtVarCsv(nrm_dict, build_cfg, unit_cfg, udt)
311
+ ext_var_dep = ExtVarCsv(dep_dict, build_cfg, unit_cfg, udt, asil_level_dep)
312
+ ext_var_sec = ExtVarCsv(sec_dict, build_cfg, unit_cfg, udt, build_defs.SECURE)
313
+
314
+ ext_var_instances = {
315
+ ext_var_nrm: "VcExtVar",
316
+ ext_var_dep: "VcExtVarSafe",
317
+ }
318
+
319
+ if not build_cfg.has_yaml_interface:
320
+ ext_var_instances[ext_var_sec] = "VcExtVarSecure"
321
+
322
+ for instance, dir_name in ext_var_instances.items():
323
+ ext_var_path = Path(build_cfg.get_src_code_dst_dir(), dir_name)
324
+ instance.generate_files(ext_var_path)
325
+
326
+
327
+ def generate_dummy_var(build_cfg, unit_cfg, signal_if, udt):
328
+ """Generate c-file that define the missing signals.
329
+
330
+ Args:
331
+ build_cfg (BuildProjConfig): Build project class holding where files should be stored.
332
+ unit_cfg (UnitConfigs) : Aggregated unit configs class.
333
+ signal_if (SignalInterfaces): class holding signal interface information.
334
+ udt (UserDefinedTypes): Class holding user defined data types.
335
+ """
336
+ LOG.info("******************************************************")
337
+ LOG.info("Start generating VcDummy")
338
+ start_time = time.time()
339
+ dst_dir = build_cfg.get_src_code_dst_dir()
340
+ nrm_dict, dep_dict, sec_dict, _ = signal_if.get_external_io()
341
+ nrm_dict = merge_dicts(nrm_dict, dep_dict, merge_recursively=True)
342
+ nrm_dict = merge_dicts(nrm_dict, sec_dict, merge_recursively=True)
343
+ res_dict = signal_if.check_config()
344
+ dummy = DummyVar(unit_cfg, nrm_dict, res_dict, build_cfg, udt)
345
+ dummy.generate_file(pjoin(dst_dir, "VcDummy"))
346
+ LOG.info("Finished generating VcDummy (in %4.2f s)", time.time() - start_time)
347
+
348
+
349
+ def generate_nvm_def(build_cfg, unit_cfg, no_nvm_a2l):
350
+ """Generate the c&h-files which declares the NVM-ram.
351
+
352
+ The NVM-ram is declared in a struct per datatype length, in order
353
+ to provide a defined order in RAM/FLASH/EEPROM for the tester
354
+ communication service. Furthermore, # defines with the variables are
355
+ created to minimize the needed model changes for access to the memory.
356
+
357
+ Args:
358
+ build_cfg (BuildProjConfig): Build project class holding where files should be stored.
359
+ unit_cfg (UnitConfigs): class holding units definitions, and which units to include.
360
+ no_nvm_a2l (bool): Do not generate A2L for NVM structs.
361
+ """
362
+ LOG.info("******************************************************")
363
+ LOG.info("Start generating NVMDefinitions")
364
+ start_time = time.time()
365
+ tot_vars_nvm = unit_cfg.get_per_cfg_unit_cfg().get("nvm", {})
366
+ nvm_def = NVMDef(build_cfg, unit_cfg, tot_vars_nvm)
367
+ nvm_def.generate_nvm_config_files(no_nvm_a2l)
368
+ LOG.info(
369
+ "Finished generating NVMDefinitions (in %4.2f s)", time.time() - start_time
370
+ )
371
+
372
+
373
+ def copy_unit_src_to_src_out(build_cfg):
374
+ """Copy unit source code to delivery folder.
375
+
376
+ Function to copy all relevant .c, .h and .a2l files to the src
377
+ delivery folder (defined in the config file for the project),
378
+ from the units that are included in the project.
379
+
380
+ Args:
381
+ build_cfg (BuildProjConfig): Build project class holding where
382
+ files should be stored
383
+ """
384
+ LOG.info("******************************************************")
385
+ LOG.info("Start copying unit source files")
386
+ start_time = time.time()
387
+ src_dirs = build_cfg.get_unit_src_dirs()
388
+ src_dst_dir = build_cfg.get_src_code_dst_dir()
389
+ files = []
390
+ for src_dir in src_dirs.values():
391
+ files.extend(glob.glob(pjoin(src_dir, "*.c")))
392
+ files.extend(glob.glob(pjoin(src_dir, "*.cpp")))
393
+ files.extend(glob.glob(pjoin(src_dir, "*.h")))
394
+ for file_ in files:
395
+ shutil.copy2(file_, src_dst_dir)
396
+ LOG.debug("copied %s to %s", file_, src_dst_dir)
397
+ LOG.info(
398
+ "Finished copying unit source files (in %4.2f s)", time.time() - start_time
399
+ )
400
+
401
+
402
+ def copy_common_src_to_src_out(build_cfg):
403
+ """Copy source code to delivery folder.
404
+
405
+ Function to copy all relevant .c and .h files to the src
406
+ delivery folder (defined in the config file for the project),
407
+ from the units that are included in the project.
408
+
409
+ Optionally, also patch the defined functions with the "schedulerPrefix".
410
+
411
+ Args:
412
+ build_cfg (BuildProjConfig): Build project class holding where files should be stored.
413
+ """
414
+ LOG.info("******************************************************")
415
+ prefix = build_cfg.get_scheduler_prefix()
416
+ if prefix:
417
+ LOG.info("Start copying and patching common source files")
418
+ else:
419
+ LOG.info("Start copying common source files")
420
+
421
+ start_time = time.time()
422
+ src_dir = build_cfg.get_common_src_dir()
423
+ src_dst_dir = build_cfg.get_src_code_dst_dir()
424
+ included_common_files = build_cfg.get_included_common_files()
425
+
426
+ files = [
427
+ pjoin(src_dir, common_file + ".c") for common_file in included_common_files
428
+ ]
429
+ files.extend(
430
+ [pjoin(src_dir, common_file + ".h") for common_file in included_common_files]
431
+ )
432
+
433
+ files_to_copy = filter(os.path.isfile, files)
434
+ for file_ in files_to_copy:
435
+ if prefix:
436
+ patch_and_copy_common_src_to_src_out(prefix, Path(file_), Path(src_dst_dir))
437
+ else:
438
+ shutil.copy2(file_, src_dst_dir)
439
+ LOG.debug("copied %s to %s", file_, src_dst_dir)
440
+
441
+ LOG.info(
442
+ "Finished copying common source files (in %4.2f s)", time.time() - start_time
443
+ )
444
+
445
+
446
+ def patch_and_copy_common_src_to_src_out(prefix, file_path, dest_dir):
447
+ """Copy common source code to delivery folder, patched with "schedulerPrefix" as prefix.
448
+
449
+ Args:
450
+ prefix (str): Prefix.
451
+ file_path (Path): Path to file to patch and copy.
452
+ dest_dir (Path): Destination directory for the patched file.
453
+ """
454
+ with file_path.open(mode="r", encoding="utf-8") as file_handle:
455
+ content = file_handle.read()
456
+
457
+ new_function = f"{prefix}{file_path.stem}"
458
+ new_content = content.replace(f"{file_path.stem}(", f"{new_function}(")
459
+ new_content_lines = new_content.splitlines()
460
+
461
+ if file_path.suffix == ".h":
462
+ defines_index = next(
463
+ (idx for idx, line in enumerate(new_content_lines) if "DEFINES" in line and "(OPT)" not in line),
464
+ None
465
+ )
466
+ if defines_index is not None:
467
+ # Insert at defines_index + 2, +1 to get to the next line and +1 to get after multiline comment
468
+ new_content_lines.insert(defines_index + 2, f"#define {file_path.stem} {new_function}")
469
+
470
+ with Path(dest_dir, file_path.name).open(mode="w", encoding="utf-8") as file_handle:
471
+ file_handle.write("\n".join(new_content_lines))
472
+
473
+
474
+ def copy_files_to_include(build_cfg):
475
+ """Copy source code to delivery folder.
476
+
477
+ Function to copy all extra include files to the src delivery folder
478
+ (defined in the config file for the project),
479
+ from the units that are included in the project.
480
+
481
+ Args:
482
+ build_cfg (BuildProjConfig): Build project class holding where
483
+ files should be stored
484
+ """
485
+ LOG.info("******************************************************")
486
+ LOG.info("Start copying extra included source files")
487
+ start_time = time.time()
488
+ src_dst_dir = build_cfg.get_src_code_dst_dir()
489
+
490
+ # Copy some files flat to the destination directory
491
+ include_paths = build_cfg.get_includes_paths_flat()
492
+ files = []
493
+ for include_path in include_paths:
494
+ if os.path.isdir(include_path):
495
+ files.extend(
496
+ [
497
+ Path(include_path, file_name)
498
+ for file_name in Path(include_path).iterdir()
499
+ if not file_name.is_dir()
500
+ ]
501
+ )
502
+ elif os.path.isfile(include_path):
503
+ files.append(include_path)
504
+ else:
505
+ LOG.critical("File or directory %s not found", include_path)
506
+ for file_ in files:
507
+ shutil.copy2(file_, src_dst_dir)
508
+ LOG.debug("copied %s to %s", file_, src_dst_dir)
509
+
510
+ # Copy some directories as is to the destination directory
511
+ include_tree_paths = [Path(p) for p in build_cfg.get_includes_paths_tree()]
512
+ existing_tree_paths = [p for p in include_tree_paths if p.exists()]
513
+ missing_tree_paths = [p for p in include_tree_paths if not p.exists()]
514
+ if missing_tree_paths:
515
+ LOG.warning(f"Missing include paths: {missing_tree_paths}")
516
+ for path in existing_tree_paths:
517
+ for file_ in path.rglob("*"):
518
+ if file_.is_file():
519
+ new_path = Path(src_dst_dir, file_.relative_to(path))
520
+ create_dir(new_path.parent)
521
+ shutil.copy2(file_, new_path)
522
+ LOG.debug("copied %s to %s", file_, new_path)
523
+ LOG.info(
524
+ "Finished copying extra included files (in %4.2f s)", time.time() - start_time
525
+ )
526
+
527
+
528
+ def copy_unit_cfgs_to_output(build_cfg):
529
+ """Copy all relevant unit configuration files to delivery folder.
530
+
531
+ Function to copy all relevant unit config .json files to the UnitCfg
532
+ delivery folder (defined in the config file for the project),
533
+ from the units that are included in the project.
534
+
535
+ Args:
536
+ build_cfg (BuildProjConfig): Build project class holding where
537
+ files should be stored
538
+ """
539
+ cfg_dst_dir = build_cfg.get_unit_cfg_deliv_dir()
540
+ if cfg_dst_dir is not None:
541
+ LOG.info("******************************************************")
542
+ LOG.info("Start copying the unit config files")
543
+ start_time = time.time()
544
+ cfg_dirs = build_cfg.get_unit_cfg_dirs()
545
+ files = []
546
+ for cfg_dir in cfg_dirs.values():
547
+ files.extend(glob.glob(pjoin(cfg_dir, "*.json")))
548
+ for file_ in files:
549
+ shutil.copy2(file_, cfg_dst_dir)
550
+ LOG.debug("copied %s to %s", file_, cfg_dst_dir)
551
+ LOG.info(
552
+ "Finished copying the unit config files (in %4.2f s)",
553
+ time.time() - start_time,
554
+ )
555
+
556
+
557
+ def merge_a2l_files(build_cfg, unit_cfg, complete_a2l=False, silver_a2l=False):
558
+ """Merge a2l-files.
559
+
560
+ Args:
561
+ build_cfg (BuildProjConfig): Build project class holding where
562
+ files should be stored
563
+ unit_cfg (UnitConfigs): class holding units definitions,
564
+ and which units to include
565
+ Returns:
566
+ a2l (A2lMerge): A2lMerge class holding the merged a2l data.
567
+ """
568
+ LOG.info("******************************************************")
569
+ LOG.info("Start merging A2L-files")
570
+ start_time = time.time()
571
+ src_dirs = build_cfg.get_unit_src_dirs()
572
+ src_dst_dir = build_cfg.get_src_code_dst_dir()
573
+ a2l_files_unit = []
574
+ for src_dir in src_dirs.values():
575
+ a2l_files_unit.extend(glob.glob(pjoin(src_dir, "*.a2l")))
576
+ a2l_files_gen = glob.glob(pjoin(src_dst_dir, "*.a2l"))
577
+ a2l = A2lMerge(build_cfg, unit_cfg, a2l_files_unit, a2l_files_gen)
578
+ new_a2l_file = os.path.join(src_dst_dir, build_cfg.get_a2l_name())
579
+ # LOG.debug(new_a2l_file)
580
+ a2l.merge(new_a2l_file, complete_a2l, silver_a2l)
581
+ LOG.info("Finished merging A2L-files (in %4.2f s)", time.time() - start_time)
582
+ return a2l
583
+
584
+
585
+ def find_all_project_configs(prj_cfg_file):
586
+ """Find all Project config files."""
587
+ prj_root_dir, _ = os.path.split(prj_cfg_file)
588
+ prj_root_dir = os.path.abspath(prj_root_dir)
589
+ all_cfg_path = os.path.join(prj_root_dir, "..", "*", "ProjectCfg.json")
590
+ return glob.glob(all_cfg_path, recursive=True)
591
+
592
+
593
+ def propagate_tag_name(build_cfg, tag_name, problem_logger):
594
+ """Set tag name in relevant files, for release builds.
595
+
596
+ Args:
597
+ build_cfg (BuildProjConfig): Build project class holding where files should be stored.
598
+ tag_name (str): git tag name.
599
+ problem_logger (object): logger for powertrain_build.
600
+ """
601
+ LOG.info("******************************************************")
602
+ LOG.info("Propagating tag name: %s", tag_name)
603
+ start_time = time.time()
604
+
605
+ src_dst_dir = build_cfg.get_src_code_dst_dir()
606
+ h_file_path = os.path.join(src_dst_dir, "vcc_sp_version.h")
607
+
608
+ if not os.path.isfile(h_file_path):
609
+ problem_logger.critical("Missing %s", h_file_path)
610
+ return
611
+
612
+ with open(h_file_path, "r+", encoding="utf-8") as file_handle:
613
+ contents = file_handle.read()
614
+ file_handle.seek(0)
615
+ new_contents = contents.replace(
616
+ '#define VCC_SOFTWARE_NAME "tagname"',
617
+ f'#define VCC_SOFTWARE_NAME "{tag_name}"',
618
+ )
619
+ file_handle.write(new_contents)
620
+
621
+ LOG.info("Finished propagating tag name (in %4.2f s)", time.time() - start_time)
622
+
623
+
624
+ def add_args(parser):
625
+ """Add command line arguments for powertrain_build.
626
+
627
+ This is useful when powertrain-build should be run through a command line wrapper function.
628
+
629
+ Args:
630
+ parser (argparse.ArgumentParser): Parser instance to add arguments to.
631
+ """
632
+ powertrain_build_parser = parser.add_argument_group("powertrain-build arguments")
633
+ powertrain_build_parser.add_argument(
634
+ "--project-config", required=True, help="Project root configuration file"
635
+ )
636
+ powertrain_build_parser.add_argument(
637
+ "--generate-system-info", action="store_true", help="Generate AllSystemInfo.mat"
638
+ )
639
+ powertrain_build_parser.add_argument(
640
+ "--generate-custom-conv-tab",
641
+ default=None,
642
+ help="Path to conversion table file. Useful for TargetLink enums in A2L file.",
643
+ )
644
+ powertrain_build_parser.add_argument(
645
+ "--core-dummy",
646
+ action="store_true",
647
+ help="Generate core dummy code to enable integration with old supplier code",
648
+ )
649
+ powertrain_build_parser.add_argument(
650
+ "--rte-dummy",
651
+ action="store_true",
652
+ help="Generate RTE dummy code to enable e.g. Silver testing",
653
+ )
654
+ powertrain_build_parser.add_argument(
655
+ "--debug", action="store_true", help="Activate the debug log"
656
+ )
657
+ powertrain_build_parser.add_argument(
658
+ "--no-abort", action="store_true", help="Do not abort due to errors"
659
+ )
660
+ powertrain_build_parser.add_argument(
661
+ "--no-nvm-a2l",
662
+ action="store_true",
663
+ help="Do not generate a2l file for NVM structs",
664
+ )
665
+ powertrain_build_parser.add_argument(
666
+ "--complete-a2l", action="store_true", help="Generate A2L with project info"
667
+ )
668
+ powertrain_build_parser.add_argument(
669
+ "--silver-a2l",
670
+ action="store_true",
671
+ help="Generate A2L file with Silver patching. Complete A2L argument takes precedence.",
672
+ )
673
+ powertrain_build_parser.add_argument(
674
+ "--interface", action="store_true", help="Generate interface report"
675
+ )
676
+ powertrain_build_parser.add_argument(
677
+ "--generate-rte-checkpoint-calls",
678
+ action="store_true",
679
+ help="Generate RTE function checkpoint calls",
680
+ )
681
+ powertrain_build_parser.add_argument(
682
+ "--version",
683
+ action="version",
684
+ version=f"%(prog)s {__version__}",
685
+ help="Display program version",
686
+ )
687
+
688
+
689
+ def build(
690
+ project_config,
691
+ interface=False,
692
+ core_dummy=False,
693
+ rte_dummy=False,
694
+ no_abort=False,
695
+ no_nvm_a2l=False,
696
+ debug=False,
697
+ quiet=False,
698
+ generate_system_info=False,
699
+ generate_custom_conversion_table=None,
700
+ complete_a2l=False,
701
+ silver_a2l=False,
702
+ generate_rte_checkpoint_calls=False,
703
+ ):
704
+ """Execute the build.
705
+
706
+ Args:
707
+ project_config (str): Project configuration file.
708
+ interface (bool): Generate interface report. Default=False.
709
+ core_dummy (bool): Generate core dummy code. Default=False.
710
+ rte_dummy (bool): Generate RTE dummy code. Default=False.
711
+ no_abort (bool): Do not abort due to errors. Default=False.
712
+ no_nvm_a2l (bool): Do not generate A2L for NVM structs. Default=False.
713
+ debug (bool): Activate the debug log. Default=False.
714
+ quiet (bool): Disable logging to stdout. Default=False.
715
+ generate_system_info (bool): Generate AllSystemInfo.mat for DocGen compatibility. Default=False.
716
+ generate_custom_conversion_table (str): Path to conversion table file.
717
+ Useful for TargetLink enums in A2L file. Default=None.
718
+ complete_a2l (bool): Add an a2l header plus additional content such as XCP data.
719
+ silver_a2l (bool): Add an a2l header plus additional patching required for Silver.
720
+ generate_rte_checkpoint_calls (bool): Generate RTE function checkpoint calls.
721
+ """
722
+ try:
723
+ problem_logger = ProblemLogger()
724
+ tot_start_time = time.time()
725
+ project_config_files = find_all_project_configs(project_config)
726
+ prj_cfgs = {}
727
+
728
+ for project_config_file in project_config_files:
729
+ conf = BuildProjConfig(os.path.normpath(project_config_file))
730
+ prj_cfgs.update({conf.name: conf})
731
+
732
+ prj_cfgs = {}
733
+ build_cfg = BuildProjConfig(os.path.normpath(project_config))
734
+ prj_cfgs.update({build_cfg.name: build_cfg})
735
+
736
+ build_cfg.create_build_dirs()
737
+ src_dst_dir = build_cfg.get_src_code_dst_dir()
738
+
739
+ setup_logging(build_cfg.get_log_dst_dir(), problem_logger, debug, quiet)
740
+ LOG.info("Starting build")
741
+ LOG.info("powertrain_build version is: %s", __version__)
742
+ LOG.info("Project/Model config file version is: %s", __config_version__)
743
+ LOG.info("Read SPM code switches")
744
+ start_time = time.time()
745
+ feature_cfg = FeatureConfigs(build_cfg)
746
+ LOG.info(
747
+ "Finished reading SPM code switches (in %4.2f s)", time.time() - start_time
748
+ )
749
+
750
+ LOG.info("******************************************************")
751
+ LOG.info("Start generating per project unit config data")
752
+ start_time = time.time()
753
+ unit_cfg = UnitConfigs(build_cfg, feature_cfg)
754
+ LOG.info(
755
+ "Finished generating per project unit config data (in %4.2f s)",
756
+ time.time() - start_time,
757
+ )
758
+
759
+ code_generation_config = build_cfg.get_code_generation_config()
760
+
761
+ udt = UserDefinedTypes(build_cfg, unit_cfg)
762
+ udt.generate_common_header_files()
763
+
764
+ start_time = time.time()
765
+ cnf_header = pjoin(src_dst_dir, build_cfg.get_feature_conf_header_name())
766
+ LOG.info("******************************************************")
767
+ LOG.info("Generate compiler switches header file %s", cnf_header)
768
+ feature_cfg.gen_unit_cfg_header_file(cnf_header)
769
+ LOG.info(
770
+ "Finished generating compiler switches header file (in %4.2f s)",
771
+ time.time() - start_time,
772
+ )
773
+ if build_cfg.has_yaml_interface:
774
+ signal_if = YamlSignalInterfaces(build_cfg, unit_cfg, feature_cfg, udt)
775
+ else:
776
+ signal_if = CsvSignalInterfaces(build_cfg, unit_cfg)
777
+ check_interfaces(build_cfg, signal_if)
778
+ if interface:
779
+ interface_report(build_cfg, unit_cfg, signal_if)
780
+
781
+ LOG.info("******************************************************")
782
+ LOG.info("Start generating VcExtVar and VcDebug")
783
+ start_time = time.time()
784
+ asil_level_db = build_defs.CVC_ASIL_LEVEL_MAP[code_generation_config["generalAsilLevelDebug"]]
785
+ asil_level_dep = build_defs.ASIL_LEVEL_MAP[code_generation_config["generalAsilLevelDependability"]]
786
+ nrm_dict, dep_dict, sec_dict, dbg_dict = signal_if.get_external_io()
787
+
788
+ generate_external_var(build_cfg, unit_cfg, udt, asil_level_dep, nrm_dict, dep_dict, sec_dict)
789
+
790
+ restructured_dbg_dict = {}
791
+ dbg_instances = {
792
+ ExtDbg(dbg_dict, build_cfg, unit_cfg): ("VcDebug", "VcDebugOutput"),
793
+ ExtDbg(dep_dict, build_cfg, unit_cfg, asil_level_db): ("VcDebugSafe", "VcDebugOutputSafe")
794
+ }
795
+ for instance, dir_names in dbg_instances.items():
796
+ restructured_dbg_dict.update({
797
+ dir_names[0]: instance.dbg_dict["inputs"],
798
+ dir_names[1]: instance.dbg_dict["outputs"]
799
+ })
800
+ instance.gen_dbg_files(
801
+ pjoin(build_cfg.get_src_code_dst_dir(), dir_names[0]),
802
+ pjoin(build_cfg.get_src_code_dst_dir(), dir_names[1])
803
+ )
804
+ LOG.info("Finished generating VcExtVar and VcDebug (in %4.2f s)", time.time() - start_time)
805
+
806
+ if not code_generation_config["generateDummyVar"]:
807
+ LOG.info("******************************************************")
808
+ LOG.info("Skip generating VcDummy file")
809
+ else:
810
+ generate_dummy_var(build_cfg, unit_cfg, signal_if, udt)
811
+
812
+ custom_dummy_spm = build_cfg.get_use_custom_dummy_spm()
813
+ if custom_dummy_spm is not None:
814
+ LOG.info("******************************************************")
815
+ if os.path.isfile(custom_dummy_spm):
816
+ LOG.info("Copying custom dummy spm file (%s)", custom_dummy_spm)
817
+ shutil.copy2(custom_dummy_spm, build_cfg.get_src_code_dst_dir())
818
+ else:
819
+ LOG.warning(
820
+ "Cannot find desired custom dummy spm file: %s", custom_dummy_spm
821
+ )
822
+ generate_dummy_spm(build_cfg, unit_cfg, feature_cfg, signal_if, udt)
823
+ else:
824
+ generate_dummy_spm(build_cfg, unit_cfg, feature_cfg, signal_if, udt)
825
+
826
+ custom_sources = build_cfg.get_use_custom_sources()
827
+ if custom_sources is not None:
828
+ LOG.info("******************************************************")
829
+ for custom_src in custom_sources:
830
+ if os.path.isfile(custom_src):
831
+ LOG.info("Copying custom sourcefile (%s)", custom_src)
832
+ shutil.copy2(custom_src, build_cfg.get_src_code_dst_dir())
833
+ else:
834
+ LOG.warning("Cannot find desired custom sourcefile: %s", custom_src)
835
+
836
+ LOG.info("******************************************************")
837
+ LOG.info("Start generating the scheduling functions")
838
+ start_time = time.time()
839
+ gen_schd = SchedFuncs(build_cfg, unit_cfg, restructured_dbg_dict)
840
+ gen_schd.generate_sched_c_fncs(generate_rte_checkpoint_calls)
841
+ LOG.info("Finished generating the scheduling functions (in %4.2f s)", time.time() - start_time)
842
+
843
+ LOG.info("******************************************************")
844
+ LOG.info("Start generating the ts header file")
845
+ start_time = time.time()
846
+ gen_schd.generate_ts_defines(pjoin(src_dst_dir, build_cfg.get_ts_header_name()))
847
+ LOG.info("Finished generating ts header file (in %4.2f s)", time.time() - start_time)
848
+
849
+ # Generate AllSystemInfo.mat for DocGen compatibility
850
+ if generate_system_info:
851
+ from powertrain_build.gen_allsysteminfo import GenAllSystemInfo
852
+
853
+ gen_all_system_info = GenAllSystemInfo(signal_if, unit_cfg)
854
+ gen_all_system_info.build()
855
+
856
+ # Check if errors
857
+ if not no_abort:
858
+ if problem_logger.errors():
859
+ nbr_err = problem_logger.get_nbr_problems()
860
+ problem_logger.info(
861
+ "Aborting build due to errors (# critical:%s, # warnings:%s"
862
+ " after %4.2f s.",
863
+ nbr_err["critical"],
864
+ nbr_err["warning"],
865
+ time.time() - tot_start_time,
866
+ )
867
+ return 1
868
+
869
+ # Copy files to output folder
870
+ copy_unit_src_to_src_out(build_cfg)
871
+ copy_common_src_to_src_out(build_cfg)
872
+ copy_unit_cfgs_to_output(build_cfg)
873
+ copy_files_to_include(build_cfg)
874
+ if code_generation_config["generateInterfaceHeaders"]:
875
+ memory_section = MemorySection(build_cfg, unit_cfg)
876
+ memory_section.generate_required_header_files()
877
+
878
+ # Propagate tag name for release builds, TAG_NAME must be set in environment
879
+ tag_name = os.environ.get("TAG_NAME", "")
880
+ if tag_name and code_generation_config["propagateTagName"]:
881
+ propagate_tag_name(build_cfg, tag_name, problem_logger)
882
+
883
+ # Copy header files (subversion is using an external that points to
884
+ # the correct set of pragma section header_files
885
+
886
+ # Make A2L-file
887
+ if generate_custom_conversion_table is not None:
888
+ ctable_json = Path(generate_custom_conversion_table).resolve()
889
+ ctable_a2l = Path(build_cfg.get_src_code_dst_dir(), "custom_tabs.a2l")
890
+ create_conversion_table(ctable_json, ctable_a2l)
891
+ merged_a2l = merge_a2l_files(build_cfg, unit_cfg, complete_a2l, silver_a2l)
892
+ a2l_file_path = Path(build_cfg.get_src_code_dst_dir(), build_cfg.get_a2l_name())
893
+ replace_tab_verb(a2l_file_path)
894
+
895
+ # Generate interface files
896
+ if code_generation_config["generateYamlInterfaceFile"]:
897
+ zc_core = ZCCore(build_cfg, unit_cfg)
898
+ zc_dids = ZCDIDs(build_cfg, unit_cfg)
899
+ LOG.info("******************************************************")
900
+ LOG.info("Start generating NVMDefinitions")
901
+ start_time = time.time()
902
+ project_nvm_defintions = unit_cfg.get_per_cfg_unit_cfg().get("nvm", {})
903
+ zc_nvm = ZCNVMDef(build_cfg, unit_cfg, project_nvm_defintions)
904
+ LOG.info(
905
+ "Finished generating NVMDefinitions (in %4.2f s)", time.time() - start_time
906
+ )
907
+ LOG.info("******************************************************")
908
+ axis_data = merged_a2l.get_characteristic_axis_data()
909
+ composition_yaml = CompositionYaml(
910
+ build_cfg,
911
+ signal_if,
912
+ unit_cfg,
913
+ zc_core,
914
+ zc_dids,
915
+ zc_nvm,
916
+ axis_data,
917
+ udt.get_enumerations()
918
+ )
919
+ composition_yaml.generate_yaml()
920
+ LOG.info("******************************************************")
921
+ LOG.info("Generating Core header")
922
+ zc_core.generate_dtc_files()
923
+ LOG.info("******************************************************")
924
+ LOG.info("Generating DID files")
925
+ zc_dids.generate_did_files()
926
+ LOG.info("******************************************************")
927
+ LOG.info("Generating NVM definitions")
928
+ zc_nvm.generate_nvm_rte_files()
929
+
930
+ if rte_dummy:
931
+ LOG.info("******************************************************")
932
+ LOG.info("Generating RTE dummy files")
933
+ zc_rte = RteDummy(build_cfg, zc_nvm, composition_yaml.cal_class_info["tl"])
934
+ zc_rte.generate_rte_dummy()
935
+
936
+ if code_generation_config["generateCalibrationInterfaceFiles"]:
937
+ LOG.info("******************************************************")
938
+ if code_generation_config["useCalibrationRteMacroExpansion"]:
939
+ LOG.warning(
940
+ "Skip generating calibration interface files as useCalibrationRteMacroExpansion is set to true"
941
+ )
942
+ else:
943
+ LOG.info("Generating calibration interface files")
944
+ zc_calibration = ZoneControllerCalibration(
945
+ build_cfg, composition_yaml.cal_class_info["tl"]
946
+ )
947
+ zc_calibration.generate_calibration_interface_files()
948
+ elif build_cfg.get_ecu_info()[0] == "HI":
949
+ generate_nvm_def(build_cfg, unit_cfg, no_nvm_a2l)
950
+ LOG.info("******************************************************")
951
+ LOG.info("Generating Core header")
952
+ hi_core = HICore(build_cfg, unit_cfg)
953
+ hi_core.generate_dtc_files()
954
+ LOG.info("******************************************************")
955
+ LOG.info("Generating DID files")
956
+ dids = HIDIDs(build_cfg, unit_cfg)
957
+ dids.generate_did_files()
958
+ else:
959
+ generate_nvm_def(build_cfg, unit_cfg, no_nvm_a2l)
960
+ generate_did_files(build_cfg, unit_cfg)
961
+ # generate core dummy files if requested
962
+ if core_dummy:
963
+ core_dummy_fname = os.path.basename(build_cfg.get_core_dummy_name())
964
+ if CodeGenerators.embedded_coder in unit_cfg.code_generators:
965
+ LOG.info("******************************************************")
966
+ LOG.info("Skip generating %s for EC projects", core_dummy_fname)
967
+ elif not code_generation_config["generateCoreDummy"]:
968
+ LOG.info("******************************************************")
969
+ LOG.info("Skip generating %s since generateCoreDummy is set to False", core_dummy_fname)
970
+ else:
971
+ core = Core(build_cfg, unit_cfg)
972
+ generate_core_dummy(build_cfg, core, unit_cfg)
973
+
974
+ if problem_logger.errors():
975
+ problem_logger.info(
976
+ "Critical errors were detected, aborting" " after %4.2f s.",
977
+ time.time() - tot_start_time,
978
+ )
979
+ return 1
980
+
981
+ LOG.info("Finished build in %4.2f s", time.time() - tot_start_time)
982
+ return 0
983
+
984
+ finally:
985
+ logging.shutdown()