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
@@ -1,252 +1,252 @@
1
- # Copyright 2024 Volvo Car Corporation
2
- # Licensed under Apache 2.0.
3
-
4
- # -*- coding: utf-8 -*-
5
- """Module containing classes for model out-port interfaces."""
6
- import os
7
- from operator import itemgetter
8
- import math
9
-
10
- import powertrain_build.build_defs as bd
11
- from powertrain_build import signal
12
- from powertrain_build.a2l import A2l
13
- from powertrain_build.problem_logger import ProblemLogger
14
- from powertrain_build.types import byte_size, get_bitmask
15
-
16
-
17
- class DummySpm(ProblemLogger):
18
- """Generate c-files which defines missing outport variables in the model out-port interface.
19
-
20
- The models declare all in-ports as 'external' and powertrain-build will then
21
- generate any missing outports in the correct #if/#endif guards here.
22
- One c-file per outport origin model should be generated.
23
-
24
- * Generate c-code from matlab/TL script with #if/#endif guards.
25
- - Pro: Is generated at the same time as other code and placed in model src folder.
26
- - Pro: Generic code. Will be cached together with TL-generated code.
27
- - Con: m-script
28
- * Generate c-code from python with only needed variables. No preprocessor directives.
29
- - Pro: Python
30
- - Pro: Simpler c-file with only used variables.
31
- - Con: Not generic! Not cached?
32
-
33
- """
34
-
35
- __asil_level_map = {
36
- 'A': (bd.CVC_DISP_ASIL_A_START, bd.CVC_DISP_ASIL_A_END),
37
- 'B': (bd.CVC_DISP_ASIL_B_START, bd.CVC_DISP_ASIL_B_END),
38
- 'C': (bd.CVC_DISP_ASIL_C_START, bd.CVC_DISP_ASIL_C_END),
39
- 'D': (bd.CVC_DISP_ASIL_D_START, bd.CVC_DISP_ASIL_D_END),
40
- 'QM': (bd.CVC_DISP_START, bd.CVC_DISP_END)}
41
-
42
- def __init__(self, missing_outports, prj_cfg, feature_cfg, unit_cfg, user_defined_types, basename):
43
- """Constructor.
44
-
45
- Args:
46
- missing_outports (list): undefined outports based on unit config variables.
47
- prj_cfg (BuildProjConfig): Build project class holding where files should be stored.
48
- feature_cfg (FeatureConfig): Feature configs from SPM_Codeswitch_Setup.
49
- unit_cfg (UnitConfigs): Class holding all unit interfaces.
50
- user_defined_types (UserDefinedTypes): Class holding user defined data types.
51
- basename (str): the basename of the outvar, used for .c and .a2l creation.
52
-
53
- See :doc:`Unit config <unit_config>` for information on the 'outport' dict.
54
- """
55
- super().__init__()
56
- self._prj_cfg = prj_cfg
57
- self._feature_cfg = feature_cfg
58
- self._unit_cfg = unit_cfg
59
- self._enumerations = user_defined_types.get_enumerations()
60
- self._common_header_files = user_defined_types.common_header_files
61
- self._name = basename
62
- self.use_volatile_globals = prj_cfg.get_use_volatile_globals()
63
- self._missing_outports = self._restruct_input_data(missing_outports)
64
-
65
- def _get_byte_size(self, data_type):
66
- """Get byte size of a data type.
67
- Enumeration byte sizes are derived from the underlying data type.
68
-
69
- Args:
70
- data_type (str): Data type.
71
- Returns:
72
- byte_size(powertrain_build.types.byte_size): Return result of powertrain_build.types.byte_size.
73
- """
74
- if data_type in self._enumerations:
75
- return byte_size(self._enumerations[data_type]['underlying_data_type'])
76
- return byte_size(data_type)
77
-
78
- def _restruct_input_data(self, outports):
79
- """Restructure all the input variables per data-type."""
80
- outports.sort(key=itemgetter('name'))
81
- outports.sort(key=lambda var: self._get_byte_size(var['type']), reverse=True)
82
- new_outports = {}
83
- for outport in outports:
84
- integrity_level = outport.get('integrity_level', 'QM')
85
- if integrity_level == 'QM':
86
- outport['cvc_type'] = 'CVC_DISP'
87
- else:
88
- outport['cvc_type'] = f'ASIL_{integrity_level}/CVC_DISP_ASIL_{integrity_level}'
89
- if integrity_level in new_outports:
90
- new_outports[integrity_level].append(outport)
91
- else:
92
- new_outports.update({integrity_level: [outport]})
93
- return new_outports
94
-
95
- def _a2l_dict(self, outports):
96
- """Return a dict defining all parameters for a2l-generation."""
97
- res = {
98
- 'vars': {},
99
- 'function': 'VcDummy_spm'
100
- }
101
-
102
- for outport in [port for sublist in outports.values() for port in sublist]:
103
- var = outport['name']
104
-
105
- if outport['type'] in self._enumerations:
106
- data_type = self._enumerations[outport['type']]['underlying_data_type']
107
- else:
108
- data_type = outport['type']
109
-
110
- resv = res['vars']
111
- resv.setdefault(var, {})['a2l_data'] = {
112
- 'bitmask': get_bitmask(data_type),
113
- 'description': outport.get('description', ''),
114
- 'lsb': '2^{}'.format(int(math.log2(outport.get('lsb', 1)))
115
- if outport.get('lsb') not in ['-', '']
116
- else 0),
117
- 'max': outport.get('max'),
118
- 'min': outport.get('min'),
119
- 'offset': -(outport.get('offset', 0) if outport.get('offset') not in ['-', ''] else 0),
120
- 'unit': outport['unit'],
121
- 'x_axis': None,
122
- 'y_axis': None}
123
- resv[var]['function'] = ['VcEc']
124
- resv[var]['var'] = {'cvc_type': outport['cvc_type'],
125
- 'type': data_type,
126
- 'var': var}
127
- resv[var]['array'] = outport.get('width', 1)
128
- res.update({'vars': resv})
129
- return res
130
-
131
- def generate_code_files(self, dst_dir):
132
- """Generate code and header files.
133
-
134
- Args:
135
- dst_dir (str): Path to destination directory.
136
-
137
- """
138
- h_file_path = os.path.join(dst_dir, f'{self._name}.h')
139
- self._generate_h_file(h_file_path, self._missing_outports)
140
- c_file_path = os.path.join(dst_dir, f'{self._name}.c')
141
- self._generate_c_file(c_file_path, self._missing_outports)
142
-
143
- def generate_a2l_files(self, dst_dir):
144
- """Generate A2L files.
145
-
146
- Args:
147
- dst_dir (str): Path to destination directory.
148
-
149
- """
150
- filename = f"{os.path.join(dst_dir, self._name)}.a2l"
151
- a2l_dict = self._a2l_dict(self._missing_outports)
152
- a2l = A2l(a2l_dict, self._prj_cfg)
153
- a2l.gen_a2l(filename)
154
-
155
- def _generate_h_file(self, file_path, outports):
156
- """Generate header file.
157
-
158
- Args:
159
- file_path (str): File path to generate.
160
- """
161
- file_name = os.path.basename(file_path).split('.')[0]
162
- with open(file_path, 'w', encoding="utf-8") as fh:
163
- fh.write(f'#ifndef {file_name.upper()}_H\n')
164
- fh.write(f'#define {file_name.upper()}_H\n')
165
-
166
- fh.write(self._unit_cfg.base_types_headers)
167
- fh.write('#include "VcCodeSwDefines.h"\n')
168
- for common_header_file in self._common_header_files:
169
- fh.write(f'#include "{common_header_file}"\n')
170
-
171
- for integrity_level in outports.keys():
172
- disp_start = bd.PREDECL_ASIL_LEVEL_MAP[integrity_level]['DISP']['START']
173
- disp_end = bd.PREDECL_ASIL_LEVEL_MAP[integrity_level]['DISP']['END']
174
- fh.write('\n')
175
- fh.write(f'#include "{disp_start}"\n')
176
- for outport in outports[integrity_level]:
177
- if outport['class'] not in signal.INPORT_CLASSES:
178
- self.warning(f'inport {outport["name"]} class {outport["class"]} is not an inport class')
179
-
180
- array = ''
181
- width = outport['width']
182
- if not isinstance(width, list):
183
- width = [width]
184
- if len(width) != 1 or width[0] != 1:
185
- for w in width:
186
- if w > 1:
187
- if not isinstance(w, int):
188
- self.critical(f'{outport["name"]} widths must be integers. Got "{type(w)}"')
189
- array += f'[{w}]'
190
- elif w < 0:
191
- self.critical(f'{outport["name"]} widths can not be negative. Got "{w}"')
192
- if self.use_volatile_globals:
193
- fh.write(f"extern volatile {outport['type']} {outport['name']}{array};\n")
194
- else:
195
- fh.write(f"extern {outport['type']} {outport['name']}{array};\n")
196
- fh.write(f'#include "{disp_end}"\n')
197
-
198
- fh.write(f'#endif /* {file_name.upper()}_H */\n')
199
-
200
- def _generate_c_file(self, file_path, outports):
201
- """Generate C-file for inports that are missing outports except for supplier ports."""
202
- file_name = os.path.basename(file_path).split('.')[0]
203
- base_header = f'#include "{file_name}.h"\n'
204
-
205
- with open(file_path, 'w', encoding="utf-8") as fh_c:
206
- fh_c.write(base_header)
207
- for integrity_level in outports.keys():
208
- disp_start = bd.CVC_ASIL_LEVEL_MAP[integrity_level]['DISP']['START']
209
- disp_end = bd.CVC_ASIL_LEVEL_MAP[integrity_level]['DISP']['END']
210
- fh_c.write('\n')
211
- fh_c.write(f'#include "{disp_start}"\n')
212
- for outport in outports[integrity_level]:
213
- if outport['class'] not in signal.INPORT_CLASSES:
214
- self.warning(f'inport {outport["name"]} class {outport["class"]} is not an inport class')
215
-
216
- width = outport['width']
217
- if outport['type'] in self._enumerations:
218
- if self._enumerations[outport['type']]['default_value'] is not None:
219
- init_value = self._enumerations[outport['type']]['default_value']
220
- else:
221
- self.warning('Initializing enumeration %s to "zero".', outport['type'])
222
- init_value = [
223
- k for k, v in self._enumerations[outport['type']]['members'].items() if v == 0
224
- ][0]
225
- if width != 1:
226
- self.critical(f'{outport["name"]} enumeration width must be 1. Got "{width}"')
227
- fh_c.write(f"{outport['type']} {outport['name']} = {init_value};\n")
228
- else:
229
- if not isinstance(width, list):
230
- width = [width]
231
- if len(width) == 1 and width[0] == 1:
232
- array = ' = 0'
233
- else:
234
- array = ''
235
- for w in width:
236
- if w > 1:
237
- if not isinstance(w, int):
238
- msg = f'{outport["name"]} widths must be integers. Got "{type(w)}"'
239
- self.critical(msg)
240
- array += f'[{w}]'
241
- elif w < 0:
242
- self.critical(f'{outport["name"]} widths can not be negative. Got "{w}"')
243
- if self.use_volatile_globals:
244
- fh_c.write(f'volatile {outport["type"]} {outport["name"]}{array};\n')
245
- else:
246
- fh_c.write(f'{outport["type"]} {outport["name"]}{array};\n')
247
- fh_c.write(f'#include "{disp_end}"\n')
248
-
249
- def generate_files(self, dst_dir):
250
- """Generate the files for defining all missing input variables."""
251
- self.generate_code_files(dst_dir)
252
- self.generate_a2l_files(dst_dir)
1
+ # Copyright 2024 Volvo Car Corporation
2
+ # Licensed under Apache 2.0.
3
+
4
+ # -*- coding: utf-8 -*-
5
+ """Module containing classes for model out-port interfaces."""
6
+ import os
7
+ from operator import itemgetter
8
+ import math
9
+
10
+ import powertrain_build.build_defs as bd
11
+ from powertrain_build import signal
12
+ from powertrain_build.a2l import A2l
13
+ from powertrain_build.problem_logger import ProblemLogger
14
+ from powertrain_build.types import byte_size, get_bitmask
15
+
16
+
17
+ class DummySpm(ProblemLogger):
18
+ """Generate c-files which defines missing outport variables in the model out-port interface.
19
+
20
+ The models declare all in-ports as 'external' and powertrain-build will then
21
+ generate any missing outports in the correct #if/#endif guards here.
22
+ One c-file per outport origin model should be generated.
23
+
24
+ * Generate c-code from matlab/TL script with #if/#endif guards.
25
+ - Pro: Is generated at the same time as other code and placed in model src folder.
26
+ - Pro: Generic code. Will be cached together with TL-generated code.
27
+ - Con: m-script
28
+ * Generate c-code from python with only needed variables. No preprocessor directives.
29
+ - Pro: Python
30
+ - Pro: Simpler c-file with only used variables.
31
+ - Con: Not generic! Not cached?
32
+
33
+ """
34
+
35
+ __asil_level_map = {
36
+ 'A': (bd.CVC_DISP_ASIL_A_START, bd.CVC_DISP_ASIL_A_END),
37
+ 'B': (bd.CVC_DISP_ASIL_B_START, bd.CVC_DISP_ASIL_B_END),
38
+ 'C': (bd.CVC_DISP_ASIL_C_START, bd.CVC_DISP_ASIL_C_END),
39
+ 'D': (bd.CVC_DISP_ASIL_D_START, bd.CVC_DISP_ASIL_D_END),
40
+ 'QM': (bd.CVC_DISP_START, bd.CVC_DISP_END)}
41
+
42
+ def __init__(self, missing_outports, prj_cfg, feature_cfg, unit_cfg, user_defined_types, basename):
43
+ """Constructor.
44
+
45
+ Args:
46
+ missing_outports (list): undefined outports based on unit config variables.
47
+ prj_cfg (BuildProjConfig): Build project class holding where files should be stored.
48
+ feature_cfg (FeatureConfig): Feature configs from SPM_Codeswitch_Setup.
49
+ unit_cfg (UnitConfigs): Class holding all unit interfaces.
50
+ user_defined_types (UserDefinedTypes): Class holding user defined data types.
51
+ basename (str): the basename of the outvar, used for .c and .a2l creation.
52
+
53
+ See :doc:`Unit config <unit_config>` for information on the 'outport' dict.
54
+ """
55
+ super().__init__()
56
+ self._prj_cfg = prj_cfg
57
+ self._feature_cfg = feature_cfg
58
+ self._unit_cfg = unit_cfg
59
+ self._enumerations = user_defined_types.get_enumerations()
60
+ self._common_header_files = user_defined_types.common_header_files
61
+ self._name = basename
62
+ self.use_volatile_globals = prj_cfg.get_use_volatile_globals()
63
+ self._missing_outports = self._restruct_input_data(missing_outports)
64
+
65
+ def _get_byte_size(self, data_type):
66
+ """Get byte size of a data type.
67
+ Enumeration byte sizes are derived from the underlying data type.
68
+
69
+ Args:
70
+ data_type (str): Data type.
71
+ Returns:
72
+ byte_size(powertrain_build.types.byte_size): Return result of powertrain_build.types.byte_size.
73
+ """
74
+ if data_type in self._enumerations:
75
+ return byte_size(self._enumerations[data_type]['underlying_data_type'])
76
+ return byte_size(data_type)
77
+
78
+ def _restruct_input_data(self, outports):
79
+ """Restructure all the input variables per data-type."""
80
+ outports.sort(key=itemgetter('name'))
81
+ outports.sort(key=lambda var: self._get_byte_size(var['type']), reverse=True)
82
+ new_outports = {}
83
+ for outport in outports:
84
+ integrity_level = outport.get('integrity_level', 'QM')
85
+ if integrity_level == 'QM':
86
+ outport['cvc_type'] = 'CVC_DISP'
87
+ else:
88
+ outport['cvc_type'] = f'ASIL_{integrity_level}/CVC_DISP_ASIL_{integrity_level}'
89
+ if integrity_level in new_outports:
90
+ new_outports[integrity_level].append(outport)
91
+ else:
92
+ new_outports.update({integrity_level: [outport]})
93
+ return new_outports
94
+
95
+ def _a2l_dict(self, outports):
96
+ """Return a dict defining all parameters for a2l-generation."""
97
+ res = {
98
+ 'vars': {},
99
+ 'function': 'VcDummy_spm'
100
+ }
101
+
102
+ for outport in [port for sublist in outports.values() for port in sublist]:
103
+ var = outport['name']
104
+
105
+ if outport['type'] in self._enumerations:
106
+ data_type = self._enumerations[outport['type']]['underlying_data_type']
107
+ else:
108
+ data_type = outport['type']
109
+
110
+ resv = res['vars']
111
+ resv.setdefault(var, {})['a2l_data'] = {
112
+ 'bitmask': get_bitmask(data_type),
113
+ 'description': outport.get('description', ''),
114
+ 'lsb': '2^{}'.format(int(math.log2(outport.get('lsb', 1)))
115
+ if outport.get('lsb') not in ['-', '']
116
+ else 0),
117
+ 'max': outport.get('max'),
118
+ 'min': outport.get('min'),
119
+ 'offset': -(outport.get('offset', 0) if outport.get('offset') not in ['-', ''] else 0),
120
+ 'unit': outport['unit'],
121
+ 'x_axis': None,
122
+ 'y_axis': None}
123
+ resv[var]['function'] = ['VcEc']
124
+ resv[var]['var'] = {'cvc_type': outport['cvc_type'],
125
+ 'type': data_type,
126
+ 'var': var}
127
+ resv[var]['array'] = outport.get('width', 1)
128
+ res.update({'vars': resv})
129
+ return res
130
+
131
+ def generate_code_files(self, dst_dir):
132
+ """Generate code and header files.
133
+
134
+ Args:
135
+ dst_dir (str): Path to destination directory.
136
+
137
+ """
138
+ h_file_path = os.path.join(dst_dir, f'{self._name}.h')
139
+ self._generate_h_file(h_file_path, self._missing_outports)
140
+ c_file_path = os.path.join(dst_dir, f'{self._name}.c')
141
+ self._generate_c_file(c_file_path, self._missing_outports)
142
+
143
+ def generate_a2l_files(self, dst_dir):
144
+ """Generate A2L files.
145
+
146
+ Args:
147
+ dst_dir (str): Path to destination directory.
148
+
149
+ """
150
+ filename = f"{os.path.join(dst_dir, self._name)}.a2l"
151
+ a2l_dict = self._a2l_dict(self._missing_outports)
152
+ a2l = A2l(a2l_dict, self._prj_cfg)
153
+ a2l.gen_a2l(filename)
154
+
155
+ def _generate_h_file(self, file_path, outports):
156
+ """Generate header file.
157
+
158
+ Args:
159
+ file_path (str): File path to generate.
160
+ """
161
+ file_name = os.path.basename(file_path).split('.')[0]
162
+ with open(file_path, 'w', encoding="utf-8") as fh:
163
+ fh.write(f'#ifndef {file_name.upper()}_H\n')
164
+ fh.write(f'#define {file_name.upper()}_H\n')
165
+
166
+ fh.write(self._unit_cfg.base_types_headers)
167
+ fh.write('#include "VcCodeSwDefines.h"\n')
168
+ for common_header_file in self._common_header_files:
169
+ fh.write(f'#include "{common_header_file}"\n')
170
+
171
+ for integrity_level in outports.keys():
172
+ disp_start = bd.PREDECL_ASIL_LEVEL_MAP[integrity_level]['DISP']['START']
173
+ disp_end = bd.PREDECL_ASIL_LEVEL_MAP[integrity_level]['DISP']['END']
174
+ fh.write('\n')
175
+ fh.write(f'#include "{disp_start}"\n')
176
+ for outport in outports[integrity_level]:
177
+ if outport['class'] not in signal.INPORT_CLASSES:
178
+ self.warning(f'inport {outport["name"]} class {outport["class"]} is not an inport class')
179
+
180
+ array = ''
181
+ width = outport['width']
182
+ if not isinstance(width, list):
183
+ width = [width]
184
+ if len(width) != 1 or width[0] != 1:
185
+ for w in width:
186
+ if w > 1:
187
+ if not isinstance(w, int):
188
+ self.critical(f'{outport["name"]} widths must be integers. Got "{type(w)}"')
189
+ array += f'[{w}]'
190
+ elif w < 0:
191
+ self.critical(f'{outport["name"]} widths can not be negative. Got "{w}"')
192
+ if self.use_volatile_globals:
193
+ fh.write(f"extern volatile {outport['type']} {outport['name']}{array};\n")
194
+ else:
195
+ fh.write(f"extern {outport['type']} {outport['name']}{array};\n")
196
+ fh.write(f'#include "{disp_end}"\n')
197
+
198
+ fh.write(f'#endif /* {file_name.upper()}_H */\n')
199
+
200
+ def _generate_c_file(self, file_path, outports):
201
+ """Generate C-file for inports that are missing outports except for supplier ports."""
202
+ file_name = os.path.basename(file_path).split('.')[0]
203
+ base_header = f'#include "{file_name}.h"\n'
204
+
205
+ with open(file_path, 'w', encoding="utf-8") as fh_c:
206
+ fh_c.write(base_header)
207
+ for integrity_level in outports.keys():
208
+ disp_start = bd.CVC_ASIL_LEVEL_MAP[integrity_level]['DISP']['START']
209
+ disp_end = bd.CVC_ASIL_LEVEL_MAP[integrity_level]['DISP']['END']
210
+ fh_c.write('\n')
211
+ fh_c.write(f'#include "{disp_start}"\n')
212
+ for outport in outports[integrity_level]:
213
+ if outport['class'] not in signal.INPORT_CLASSES:
214
+ self.warning(f'inport {outport["name"]} class {outport["class"]} is not an inport class')
215
+
216
+ width = outport['width']
217
+ if outport['type'] in self._enumerations:
218
+ if self._enumerations[outport['type']]['default_value'] is not None:
219
+ init_value = self._enumerations[outport['type']]['default_value']
220
+ else:
221
+ self.warning('Initializing enumeration %s to "zero".', outport['type'])
222
+ init_value = [
223
+ k for k, v in self._enumerations[outport['type']]['members'].items() if v == 0
224
+ ][0]
225
+ if width != 1:
226
+ self.critical(f'{outport["name"]} enumeration width must be 1. Got "{width}"')
227
+ fh_c.write(f"{outport['type']} {outport['name']} = {init_value};\n")
228
+ else:
229
+ if not isinstance(width, list):
230
+ width = [width]
231
+ if len(width) == 1 and width[0] == 1:
232
+ array = ' = 0'
233
+ else:
234
+ array = ''
235
+ for w in width:
236
+ if w > 1:
237
+ if not isinstance(w, int):
238
+ msg = f'{outport["name"]} widths must be integers. Got "{type(w)}"'
239
+ self.critical(msg)
240
+ array += f'[{w}]'
241
+ elif w < 0:
242
+ self.critical(f'{outport["name"]} widths can not be negative. Got "{w}"')
243
+ if self.use_volatile_globals:
244
+ fh_c.write(f'volatile {outport["type"]} {outport["name"]}{array};\n')
245
+ else:
246
+ fh_c.write(f'{outport["type"]} {outport["name"]}{array};\n')
247
+ fh_c.write(f'#include "{disp_end}"\n')
248
+
249
+ def generate_files(self, dst_dir):
250
+ """Generate the files for defining all missing input variables."""
251
+ self.generate_code_files(dst_dir)
252
+ self.generate_a2l_files(dst_dir)
@@ -1,52 +1,52 @@
1
- # Copyright 2024 Volvo Car Corporation
2
- # Licensed under Apache 2.0.
3
-
4
- """Environment compatibility check."""
5
-
6
- import sys
7
-
8
-
9
- def check_python_string(python_lower, python_upper=None):
10
- """Ensure current Python interpreter is a version between lower and upper.
11
-
12
- Arguments:
13
- python_lower (str): Required lower bound for Python version.
14
- python_upper (str): Optional upper bound for Python version.
15
- Raises:
16
- RuntimeError: If current Python executable is not compatible with powertrain_build.
17
-
18
- """
19
- versions = [_split_version(python_lower)]
20
- if python_upper:
21
- versions.append(_split_version(python_upper))
22
- check_python_tuple(*versions)
23
-
24
-
25
- def check_python_tuple(python_lower, python_upper=None):
26
- """Ensure current Python interpreter is a version between lower and upper.
27
-
28
- Arguments:
29
- python_lower (2-tuple): Required lower bound for Python version.
30
- python_upper (2-tuple): Optional upper bound for Python version.
31
- Raises:
32
- RuntimeError: If current Python executable is not compatible with powertrain_build.
33
-
34
- """
35
- cur_version = sys.version_info[:2]
36
-
37
- if cur_version[0] < python_lower[0] or cur_version[1] < python_lower[1]:
38
- raise RuntimeError(_format_error(f'must be higher than {python_lower}'))
39
-
40
- if python_upper and (cur_version[0] > python_upper[0] or cur_version[1] > python_upper[1]):
41
- raise RuntimeError(_format_error(f'must be lower than {python_upper}'))
42
-
43
-
44
- def _split_version(version_string):
45
- """Split a major.minor style string and returns a 2-tuple of integers."""
46
- parts = version_string.split('.')
47
- return (int(parts[0]), int(parts[1]))
48
-
49
-
50
- def _format_error(message):
51
- """Return a version error string including current interpreter, version and a custom message."""
52
- return f'Unsupported Python version ({sys.version_info}), {message}. Path: {sys.executable}'
1
+ # Copyright 2024 Volvo Car Corporation
2
+ # Licensed under Apache 2.0.
3
+
4
+ """Environment compatibility check."""
5
+
6
+ import sys
7
+
8
+
9
+ def check_python_string(python_lower, python_upper=None):
10
+ """Ensure current Python interpreter is a version between lower and upper.
11
+
12
+ Arguments:
13
+ python_lower (str): Required lower bound for Python version.
14
+ python_upper (str): Optional upper bound for Python version.
15
+ Raises:
16
+ RuntimeError: If current Python executable is not compatible with powertrain_build.
17
+
18
+ """
19
+ versions = [_split_version(python_lower)]
20
+ if python_upper:
21
+ versions.append(_split_version(python_upper))
22
+ check_python_tuple(*versions)
23
+
24
+
25
+ def check_python_tuple(python_lower, python_upper=None):
26
+ """Ensure current Python interpreter is a version between lower and upper.
27
+
28
+ Arguments:
29
+ python_lower (2-tuple): Required lower bound for Python version.
30
+ python_upper (2-tuple): Optional upper bound for Python version.
31
+ Raises:
32
+ RuntimeError: If current Python executable is not compatible with powertrain_build.
33
+
34
+ """
35
+ cur_version = sys.version_info[:2]
36
+
37
+ if cur_version[0] < python_lower[0] or cur_version[1] < python_lower[1]:
38
+ raise RuntimeError(_format_error(f'must be higher than {python_lower}'))
39
+
40
+ if python_upper and (cur_version[0] > python_upper[0] or cur_version[1] > python_upper[1]):
41
+ raise RuntimeError(_format_error(f'must be lower than {python_upper}'))
42
+
43
+
44
+ def _split_version(version_string):
45
+ """Split a major.minor style string and returns a 2-tuple of integers."""
46
+ parts = version_string.split('.')
47
+ return (int(parts[0]), int(parts[1]))
48
+
49
+
50
+ def _format_error(message):
51
+ """Return a version error string including current interpreter, version and a custom message."""
52
+ return f'Unsupported Python version ({sys.version_info}), {message}. Path: {sys.executable}'