powertrain-build 1.13.1__py3-none-any.whl → 1.13.3.dev3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- powertrain_build/__init__.py +40 -40
- powertrain_build/__main__.py +6 -6
- powertrain_build/a2l.py +582 -582
- powertrain_build/a2l_merge.py +650 -650
- powertrain_build/a2l_templates.py +717 -717
- powertrain_build/build.py +985 -985
- powertrain_build/build_defs.py +309 -309
- powertrain_build/build_proj_config.py +690 -690
- powertrain_build/check_interface.py +575 -575
- powertrain_build/cli.py +141 -141
- powertrain_build/config.py +542 -542
- powertrain_build/core.py +395 -395
- powertrain_build/core_dummy.py +343 -343
- powertrain_build/create_conversion_table.py +73 -73
- powertrain_build/dids.py +916 -916
- powertrain_build/dummy.py +157 -157
- powertrain_build/dummy_spm.py +252 -252
- powertrain_build/environmentcheck.py +52 -52
- powertrain_build/ext_dbg.py +255 -255
- powertrain_build/ext_var.py +327 -327
- powertrain_build/feature_configs.py +301 -301
- powertrain_build/gen_allsysteminfo.py +227 -227
- powertrain_build/gen_label_split.py +449 -449
- powertrain_build/handcode_replacer.py +124 -124
- powertrain_build/html_report.py +133 -133
- powertrain_build/interface/__init__.py +4 -4
- powertrain_build/interface/application.py +511 -511
- powertrain_build/interface/base.py +500 -500
- powertrain_build/interface/csp_api.py +490 -490
- powertrain_build/interface/device_proxy.py +677 -677
- powertrain_build/interface/ems.py +67 -67
- powertrain_build/interface/export_global_vars.py +121 -121
- powertrain_build/interface/generate_adapters.py +132 -132
- powertrain_build/interface/generate_hi_interface.py +87 -87
- powertrain_build/interface/generate_service.py +69 -69
- powertrain_build/interface/generate_wrappers.py +147 -147
- powertrain_build/interface/generation_utils.py +142 -142
- powertrain_build/interface/hal.py +194 -194
- powertrain_build/interface/model_yaml_verification.py +348 -348
- powertrain_build/interface/service.py +296 -296
- powertrain_build/interface/simulink.py +249 -249
- powertrain_build/interface/update_call_sources.py +180 -180
- powertrain_build/interface/update_model_yaml.py +186 -186
- powertrain_build/interface/zone_controller.py +362 -362
- powertrain_build/lib/__init__.py +4 -4
- powertrain_build/lib/helper_functions.py +127 -127
- powertrain_build/lib/logger.py +55 -55
- powertrain_build/matlab_scripts/CodeGen/BuildAutomationPyBuild.m +78 -78
- powertrain_build/matlab_scripts/CodeGen/Generate_A2L.m +154 -154
- powertrain_build/matlab_scripts/CodeGen/generateTLUnit.m +239 -239
- powertrain_build/matlab_scripts/CodeGen/getAsilClassification.m +28 -28
- powertrain_build/matlab_scripts/CodeGen/modelConfiguredForTL.m +28 -28
- powertrain_build/matlab_scripts/CodeGen/moveDefOutports.m +88 -88
- powertrain_build/matlab_scripts/CodeGen/parseCalMeasData.m +410 -410
- powertrain_build/matlab_scripts/CodeGen/parseCoreIdentifiers.m +139 -139
- powertrain_build/matlab_scripts/CodeGen/parseDIDs.m +141 -141
- powertrain_build/matlab_scripts/CodeGen/parseInPorts.m +106 -106
- powertrain_build/matlab_scripts/CodeGen/parseIncludeConfigs.m +25 -25
- powertrain_build/matlab_scripts/CodeGen/parseModelInfo.m +38 -38
- powertrain_build/matlab_scripts/CodeGen/parseNVM.m +81 -81
- powertrain_build/matlab_scripts/CodeGen/parseOutPorts.m +120 -120
- powertrain_build/matlab_scripts/CodeGen/parsePreProcBlks.m +23 -23
- powertrain_build/matlab_scripts/CodeGen/struct2JSON.m +128 -128
- powertrain_build/matlab_scripts/CodeGen/updateCodeSwConfig.m +31 -31
- powertrain_build/matlab_scripts/Init_PyBuild.m +91 -91
- powertrain_build/matlab_scripts/__init__.py +2 -2
- powertrain_build/matlab_scripts/helperFunctions/Get_Full_Name.m +46 -46
- powertrain_build/matlab_scripts/helperFunctions/Get_SrcLines.m +12 -12
- powertrain_build/matlab_scripts/helperFunctions/Init_Models.m +78 -78
- powertrain_build/matlab_scripts/helperFunctions/Init_Projects.m +67 -67
- powertrain_build/matlab_scripts/helperFunctions/Read_Units.m +34 -34
- powertrain_build/matlab_scripts/helperFunctions/SetProjectTimeSamples.m +26 -26
- powertrain_build/matlab_scripts/helperFunctions/Strip_Suffix.m +16 -16
- powertrain_build/matlab_scripts/helperFunctions/followLink.m +118 -118
- powertrain_build/matlab_scripts/helperFunctions/getCodeSwitches.m +50 -50
- powertrain_build/matlab_scripts/helperFunctions/getConsumerBlocks.m +30 -30
- powertrain_build/matlab_scripts/helperFunctions/getDefBlock.m +39 -39
- powertrain_build/matlab_scripts/helperFunctions/getDefOutport.m +58 -58
- powertrain_build/matlab_scripts/helperFunctions/getDstBlocks.m +19 -19
- powertrain_build/matlab_scripts/helperFunctions/getDstLines.m +13 -13
- powertrain_build/matlab_scripts/helperFunctions/getInterfaceSignals.m +37 -37
- powertrain_build/matlab_scripts/helperFunctions/getName.m +37 -37
- powertrain_build/matlab_scripts/helperFunctions/getPath.m +6 -6
- powertrain_build/matlab_scripts/helperFunctions/getProperValue.m +21 -21
- powertrain_build/matlab_scripts/helperFunctions/getSrcBlocks.m +19 -19
- powertrain_build/matlab_scripts/helperFunctions/getSrcLines.m +13 -13
- powertrain_build/matlab_scripts/helperFunctions/loadLibraries.m +10 -10
- powertrain_build/matlab_scripts/helperFunctions/loadjson.m +6 -6
- powertrain_build/matlab_scripts/helperFunctions/modifyEnumStructField.m +21 -21
- powertrain_build/matlab_scripts/helperFunctions/removeConfigDuplicates.m +31 -31
- powertrain_build/matlab_scripts/helperFunctions/sortSystemByClass.m +26 -26
- powertrain_build/matlab_scripts/helperFunctions/tl_getfast.m +89 -89
- powertrain_build/matlab_scripts/helperFunctions/topLevelSystem.m +20 -20
- powertrain_build/matlab_scripts/helperFunctions/updateModels.m +131 -131
- powertrain_build/memory_section.py +224 -224
- powertrain_build/nvm_def.py +729 -729
- powertrain_build/problem_logger.py +86 -86
- powertrain_build/pt_matlab.py +430 -430
- powertrain_build/pt_win32.py +144 -144
- powertrain_build/replace_compu_tab_ref.py +105 -105
- powertrain_build/rte_dummy.py +254 -254
- powertrain_build/sched_funcs.py +209 -207
- powertrain_build/signal.py +7 -7
- powertrain_build/signal_if_html_rep.py +221 -221
- powertrain_build/signal_if_html_rep_all.py +302 -302
- powertrain_build/signal_incons_html_rep.py +180 -180
- powertrain_build/signal_incons_html_rep_all.py +366 -366
- powertrain_build/signal_incons_html_rep_base.py +168 -168
- powertrain_build/signal_inconsistency_check.py +641 -641
- powertrain_build/signal_interfaces.py +864 -864
- powertrain_build/templates/Index_SigCheck_All.html +22 -22
- powertrain_build/templates/Index_SigIf_All.html +19 -19
- powertrain_build/types.py +218 -218
- powertrain_build/unit_configs.py +419 -419
- powertrain_build/user_defined_types.py +660 -660
- powertrain_build/versioncheck.py +66 -66
- powertrain_build/wrapper.py +512 -512
- powertrain_build/xlrd_csv.py +87 -87
- powertrain_build/zone_controller/__init__.py +4 -4
- powertrain_build/zone_controller/calibration.py +176 -176
- powertrain_build/zone_controller/composition_yaml.py +880 -878
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/METADATA +100 -100
- powertrain_build-1.13.3.dev3.dist-info/RECORD +130 -0
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/WHEEL +1 -1
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/licenses/LICENSE +202 -202
- powertrain_build-1.13.3.dev3.dist-info/pbr.json +1 -0
- powertrain_build-1.13.1.dist-info/RECORD +0 -130
- powertrain_build-1.13.1.dist-info/pbr.json +0 -1
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/entry_points.txt +0 -0
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/licenses/AUTHORS +0 -0
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/licenses/NOTICE +0 -0
- {powertrain_build-1.13.1.dist-info → powertrain_build-1.13.3.dev3.dist-info}/top_level.txt +0 -0
powertrain_build/ext_dbg.py
CHANGED
|
@@ -1,255 +1,255 @@
|
|
|
1
|
-
# Copyright 2024 Volvo Car Corporation
|
|
2
|
-
# Licensed under Apache 2.0.
|
|
3
|
-
|
|
4
|
-
# -*- coding: utf-8 -*-
|
|
5
|
-
"""Module containing classes for VCC - Supplier debug interface.
|
|
6
|
-
|
|
7
|
-
TODO: Check if all IO parameters in SPMEMSInterfaceRequirements.xlsx defined as safety variables
|
|
8
|
-
automatically have debug switches.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
import os
|
|
12
|
-
import re
|
|
13
|
-
|
|
14
|
-
from powertrain_build import build_defs
|
|
15
|
-
from powertrain_build.types import byte_size_string, get_bitmask, a2l_range
|
|
16
|
-
from powertrain_build.a2l import A2l
|
|
17
|
-
from powertrain_build.problem_logger import ProblemLogger
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class ExtDbg(ProblemLogger):
|
|
21
|
-
"""Class for generating c-files.
|
|
22
|
-
|
|
23
|
-
These declares all debug parameters in the VCC - Supplier interface.
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
__data_type_size = {'Float32': '4', 'UInt32': '4', 'Int32': '4',
|
|
27
|
-
'UInt16': '2', 'Int16': '2',
|
|
28
|
-
'UInt8': '1', 'Int8': '1', 'Bool': '1'}
|
|
29
|
-
|
|
30
|
-
def __init__(self, variable_dict, prj_cfg, unit_cfg, integrity_level=build_defs.CVC_ASIL_QM):
|
|
31
|
-
"""Constructor.
|
|
32
|
-
|
|
33
|
-
Args:
|
|
34
|
-
variable_dict (dict): dictionary with signal information
|
|
35
|
-
|
|
36
|
-
Variable dict shall have the following format and is generated by the
|
|
37
|
-
:doc:`CsvSignalInterfaces <signal_interfaces>` class::
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
'CAN-Input': {
|
|
41
|
-
'signal1': {
|
|
42
|
-
'IOType': 'd',
|
|
43
|
-
'description': 'Some description',
|
|
44
|
-
'init': 0,
|
|
45
|
-
'max': 1,
|
|
46
|
-
'min': 0,
|
|
47
|
-
'type': 'UInt8',
|
|
48
|
-
'unit': '-'
|
|
49
|
-
},
|
|
50
|
-
'signal2': {
|
|
51
|
-
...
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
'CAN-Output': {
|
|
55
|
-
'signal3': {
|
|
56
|
-
...
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
'xxx-Input': ...,
|
|
60
|
-
'xxx-Output': ...
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
The optional keyword arguments may override which code section
|
|
64
|
-
directives to use.
|
|
65
|
-
"""
|
|
66
|
-
super().__init__()
|
|
67
|
-
self.set_integrity_level(integrity_level)
|
|
68
|
-
self._prj_cfg = prj_cfg
|
|
69
|
-
self._unit_cfg = unit_cfg
|
|
70
|
-
self._use_volatile_globals = prj_cfg.get_use_volatile_globals()
|
|
71
|
-
self.dbg_dict = self._restruct_data(variable_dict)
|
|
72
|
-
|
|
73
|
-
@staticmethod
|
|
74
|
-
def _restruct_data(variable_dict):
|
|
75
|
-
"""Restructure input variables per data-type.
|
|
76
|
-
|
|
77
|
-
This will be used for declaring the variables and generating the A2L-file.
|
|
78
|
-
"""
|
|
79
|
-
data = {'outputs': {}, 'inputs': {}}
|
|
80
|
-
for inp in variable_dict.keys():
|
|
81
|
-
if re.match(r'.*Output$', inp) is not None:
|
|
82
|
-
iotype = 'outputs'
|
|
83
|
-
else:
|
|
84
|
-
iotype = 'inputs'
|
|
85
|
-
for var, var_data in variable_dict[inp].items():
|
|
86
|
-
data_type_size = byte_size_string(var_data['type'])
|
|
87
|
-
data[iotype].setdefault(data_type_size, {})[var] = var_data
|
|
88
|
-
return data
|
|
89
|
-
|
|
90
|
-
def set_integrity_level(self, integrity_level):
|
|
91
|
-
"""Set integrity level of code generation.
|
|
92
|
-
|
|
93
|
-
Args:
|
|
94
|
-
integrity_level (str): integrity level of the unit from 'A' to 'D' or 'QM'
|
|
95
|
-
"""
|
|
96
|
-
self._disp_start = integrity_level['DISP']['START']
|
|
97
|
-
self._disp_end = integrity_level['DISP']['END']
|
|
98
|
-
self._cal_start = integrity_level['CAL']['START']
|
|
99
|
-
self._cal_end = integrity_level['CAL']['END']
|
|
100
|
-
self._code_start = integrity_level['CODE']['START']
|
|
101
|
-
self._code_end = integrity_level['CODE']['END']
|
|
102
|
-
|
|
103
|
-
def _a2l_dict(self, var_dict, function):
|
|
104
|
-
"""Generate dict defining parameters for a2l-generation."""
|
|
105
|
-
def _range(data):
|
|
106
|
-
range_a2l = a2l_range(data['type'])
|
|
107
|
-
if data['min'] == '-':
|
|
108
|
-
a2l_min = range_a2l[0]
|
|
109
|
-
else:
|
|
110
|
-
a2l_min = data['min']
|
|
111
|
-
if data['max'] == '-':
|
|
112
|
-
a2l_max = range_a2l[1]
|
|
113
|
-
else:
|
|
114
|
-
a2l_max = data['max']
|
|
115
|
-
return a2l_min, a2l_max
|
|
116
|
-
|
|
117
|
-
res = {'vars': {},
|
|
118
|
-
'function': function}
|
|
119
|
-
for var, data in self._type_order_iterator(var_dict):
|
|
120
|
-
resv = res['vars']
|
|
121
|
-
a2l_min, a2l_max = _range(data)
|
|
122
|
-
a2l_data = {
|
|
123
|
-
'bitmask': get_bitmask(data['type']),
|
|
124
|
-
'description': data['description'],
|
|
125
|
-
'lsb': '2^0',
|
|
126
|
-
'max': a2l_max,
|
|
127
|
-
'min': a2l_min,
|
|
128
|
-
'offset': '0',
|
|
129
|
-
'unit': '',
|
|
130
|
-
'x_axis': None,
|
|
131
|
-
'y_axis': None
|
|
132
|
-
}
|
|
133
|
-
var_db = f'c{var[1:]}_db'
|
|
134
|
-
var_sw = self._var_name_to_dbgsw_name(var)
|
|
135
|
-
resv.setdefault(var_db, {})['a2l_data'] = a2l_data
|
|
136
|
-
a2l_data = {
|
|
137
|
-
'bitmask': get_bitmask(data['type']),
|
|
138
|
-
'description': f'debug switch for {var_db} (1=bdsw act)',
|
|
139
|
-
'lsb': '2^0',
|
|
140
|
-
'max': '1',
|
|
141
|
-
'min': '0',
|
|
142
|
-
'offset': '0',
|
|
143
|
-
'unit': '',
|
|
144
|
-
'x_axis': None,
|
|
145
|
-
'y_axis': None
|
|
146
|
-
}
|
|
147
|
-
resv.setdefault(var_sw, {})['a2l_data'] = a2l_data
|
|
148
|
-
resv[var_db]['array'] = []
|
|
149
|
-
resv[var_sw]['array'] = []
|
|
150
|
-
resv[var_db]['function'] = [function]
|
|
151
|
-
resv[var_sw]['function'] = [function]
|
|
152
|
-
resv[var_db]['var'] = {'cvc_type': 'CVC_CAL',
|
|
153
|
-
'type': data['type'],
|
|
154
|
-
'var': var}
|
|
155
|
-
resv[var_sw]['var'] = {'cvc_type': 'CVC_CAL',
|
|
156
|
-
'type': 'Bool',
|
|
157
|
-
'var': var}
|
|
158
|
-
return res
|
|
159
|
-
|
|
160
|
-
@staticmethod
|
|
161
|
-
def _var_name_to_dbgsw_name(name):
|
|
162
|
-
"""Convert a variable name to a debug switch name."""
|
|
163
|
-
# the below conversion would generate a correct name for the
|
|
164
|
-
# debug switch, however the current build systemt generates one
|
|
165
|
-
# like the currently returned name
|
|
166
|
-
# return re.sub(r'\w(\w+?)_\w+?_(\w+)', r'c\1_B_\2_sw', name)
|
|
167
|
-
return re.sub(r'\w(\w+)', r'c\1_sw', name)
|
|
168
|
-
|
|
169
|
-
@staticmethod
|
|
170
|
-
def _type_order_iterator(var_items):
|
|
171
|
-
"""Get iterator over all variables.
|
|
172
|
-
|
|
173
|
-
In data type size order, and then in alphabetical order.
|
|
174
|
-
"""
|
|
175
|
-
for _, typ_data in var_items.items():
|
|
176
|
-
for var in sorted(typ_data.keys()):
|
|
177
|
-
yield (var, typ_data[var])
|
|
178
|
-
|
|
179
|
-
def _gen_dbg_c_file(self, data, filename):
|
|
180
|
-
"""Generate debug c-files.
|
|
181
|
-
|
|
182
|
-
These define all the debug labels for
|
|
183
|
-
the supplier input and output signals.
|
|
184
|
-
"""
|
|
185
|
-
with open(filename, 'w', encoding="utf-8") as fh_c:
|
|
186
|
-
fh_c.write(self._unit_cfg.base_types_headers)
|
|
187
|
-
fh_c.write('#define CVC_DISP\n')
|
|
188
|
-
|
|
189
|
-
# define extrern variable references
|
|
190
|
-
fh_c.write(f'#include "{self._disp_start}"\n')
|
|
191
|
-
for var, var_data in self._type_order_iterator(data):
|
|
192
|
-
fh_c.write(f"extern CVC_DISP {var_data['type']} {var};\n")
|
|
193
|
-
fh_c.write(f'#include "{self._disp_end}"\n\n')
|
|
194
|
-
|
|
195
|
-
# define debug calibration constants
|
|
196
|
-
fh_c.write(f'#include "{self._cal_start}"\n')
|
|
197
|
-
fh_c.write('\n/* Debug values */\n\n')
|
|
198
|
-
for var, var_data in self._type_order_iterator(data):
|
|
199
|
-
initial_value = var_data['min'] if var_data['min'] != "-" and float(var_data['min']) > 0 else "0"
|
|
200
|
-
if self._use_volatile_globals:
|
|
201
|
-
fh_c.write(f"volatile {var_data['type']} c{var[1:]}_db = {initial_value};\n")
|
|
202
|
-
else:
|
|
203
|
-
fh_c.write(f"{var_data['type']} c{var[1:]}_db = {initial_value};\n")
|
|
204
|
-
|
|
205
|
-
fh_c.write('\n/* Debug switches */\n\n')
|
|
206
|
-
for var, var_data in self._type_order_iterator(data):
|
|
207
|
-
sw_name = self._var_name_to_dbgsw_name(var)
|
|
208
|
-
if self._use_volatile_globals:
|
|
209
|
-
fh_c.write(f"volatile Bool {sw_name} = 0;\n")
|
|
210
|
-
else:
|
|
211
|
-
fh_c.write(f"Bool {sw_name} = 0;\n")
|
|
212
|
-
fh_c.write(f'#include "{self._cal_end}"\n\n')
|
|
213
|
-
|
|
214
|
-
# set the variable to the debug calibration constants
|
|
215
|
-
fh_c.write('/***********************/\n')
|
|
216
|
-
fh_c.write('/* debug functionality */\n')
|
|
217
|
-
fh_c.write('/***********************/\n\n')
|
|
218
|
-
_, fname_tmp = os.path.split(filename)
|
|
219
|
-
func_name = fname_tmp.split('.')[-2]
|
|
220
|
-
fh_c.write(f'#include "{self._code_start}"\n')
|
|
221
|
-
fh_c.write(f'void {func_name}(void) {{\n')
|
|
222
|
-
for var, var_data in self._type_order_iterator(data):
|
|
223
|
-
sw_name = self._var_name_to_dbgsw_name(var)
|
|
224
|
-
fh_c.write(f' if ({sw_name}) {{\n')
|
|
225
|
-
fh_c.write(f' {var} = c{var[1:]}_db;\n }}\n')
|
|
226
|
-
fh_c.write(f'}}\n#include "{self._code_end}"\n\n')
|
|
227
|
-
self.info('Generated %s', filename)
|
|
228
|
-
|
|
229
|
-
def gen_dbg_files(self, file_path_inputs, file_path_outputs):
|
|
230
|
-
"""Generate the c-files and A2L-files.
|
|
231
|
-
|
|
232
|
-
These declares all the supplier interface debug parameters and functions.
|
|
233
|
-
|
|
234
|
-
Args:
|
|
235
|
-
file_path_inputs (str): path to the debug inputs c-file.
|
|
236
|
-
file_path_outputs (str): path to the debug outputs c-file.
|
|
237
|
-
"""
|
|
238
|
-
_, file_name_inputs = os.path.split(file_path_inputs)
|
|
239
|
-
_, file_name_outputs = os.path.split(file_path_outputs)
|
|
240
|
-
|
|
241
|
-
if not self.dbg_dict['inputs']:
|
|
242
|
-
self.info(f"Skipping {file_name_inputs} as there were no corresponding vars.")
|
|
243
|
-
else:
|
|
244
|
-
self._gen_dbg_c_file(self.dbg_dict['inputs'], file_path_inputs + '.c')
|
|
245
|
-
a2l_dict_in = self._a2l_dict(self.dbg_dict['inputs'], file_name_inputs)
|
|
246
|
-
a2l = A2l(a2l_dict_in, self._prj_cfg)
|
|
247
|
-
a2l.gen_a2l(file_path_inputs + '.a2l')
|
|
248
|
-
|
|
249
|
-
if not self.dbg_dict['outputs']:
|
|
250
|
-
self.info(f"Skipping {file_name_outputs} as there were no corresponding vars.")
|
|
251
|
-
else:
|
|
252
|
-
self._gen_dbg_c_file(self.dbg_dict['outputs'], file_path_outputs + '.c')
|
|
253
|
-
a2l_dict_out = self._a2l_dict(self.dbg_dict['outputs'], file_name_outputs)
|
|
254
|
-
a2l = A2l(a2l_dict_out, self._prj_cfg)
|
|
255
|
-
a2l.gen_a2l(file_path_outputs + '.a2l')
|
|
1
|
+
# Copyright 2024 Volvo Car Corporation
|
|
2
|
+
# Licensed under Apache 2.0.
|
|
3
|
+
|
|
4
|
+
# -*- coding: utf-8 -*-
|
|
5
|
+
"""Module containing classes for VCC - Supplier debug interface.
|
|
6
|
+
|
|
7
|
+
TODO: Check if all IO parameters in SPMEMSInterfaceRequirements.xlsx defined as safety variables
|
|
8
|
+
automatically have debug switches.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import re
|
|
13
|
+
|
|
14
|
+
from powertrain_build import build_defs
|
|
15
|
+
from powertrain_build.types import byte_size_string, get_bitmask, a2l_range
|
|
16
|
+
from powertrain_build.a2l import A2l
|
|
17
|
+
from powertrain_build.problem_logger import ProblemLogger
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ExtDbg(ProblemLogger):
|
|
21
|
+
"""Class for generating c-files.
|
|
22
|
+
|
|
23
|
+
These declares all debug parameters in the VCC - Supplier interface.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
__data_type_size = {'Float32': '4', 'UInt32': '4', 'Int32': '4',
|
|
27
|
+
'UInt16': '2', 'Int16': '2',
|
|
28
|
+
'UInt8': '1', 'Int8': '1', 'Bool': '1'}
|
|
29
|
+
|
|
30
|
+
def __init__(self, variable_dict, prj_cfg, unit_cfg, integrity_level=build_defs.CVC_ASIL_QM):
|
|
31
|
+
"""Constructor.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
variable_dict (dict): dictionary with signal information
|
|
35
|
+
|
|
36
|
+
Variable dict shall have the following format and is generated by the
|
|
37
|
+
:doc:`CsvSignalInterfaces <signal_interfaces>` class::
|
|
38
|
+
|
|
39
|
+
{
|
|
40
|
+
'CAN-Input': {
|
|
41
|
+
'signal1': {
|
|
42
|
+
'IOType': 'd',
|
|
43
|
+
'description': 'Some description',
|
|
44
|
+
'init': 0,
|
|
45
|
+
'max': 1,
|
|
46
|
+
'min': 0,
|
|
47
|
+
'type': 'UInt8',
|
|
48
|
+
'unit': '-'
|
|
49
|
+
},
|
|
50
|
+
'signal2': {
|
|
51
|
+
...
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
'CAN-Output': {
|
|
55
|
+
'signal3': {
|
|
56
|
+
...
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
'xxx-Input': ...,
|
|
60
|
+
'xxx-Output': ...
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
The optional keyword arguments may override which code section
|
|
64
|
+
directives to use.
|
|
65
|
+
"""
|
|
66
|
+
super().__init__()
|
|
67
|
+
self.set_integrity_level(integrity_level)
|
|
68
|
+
self._prj_cfg = prj_cfg
|
|
69
|
+
self._unit_cfg = unit_cfg
|
|
70
|
+
self._use_volatile_globals = prj_cfg.get_use_volatile_globals()
|
|
71
|
+
self.dbg_dict = self._restruct_data(variable_dict)
|
|
72
|
+
|
|
73
|
+
@staticmethod
|
|
74
|
+
def _restruct_data(variable_dict):
|
|
75
|
+
"""Restructure input variables per data-type.
|
|
76
|
+
|
|
77
|
+
This will be used for declaring the variables and generating the A2L-file.
|
|
78
|
+
"""
|
|
79
|
+
data = {'outputs': {}, 'inputs': {}}
|
|
80
|
+
for inp in variable_dict.keys():
|
|
81
|
+
if re.match(r'.*Output$', inp) is not None:
|
|
82
|
+
iotype = 'outputs'
|
|
83
|
+
else:
|
|
84
|
+
iotype = 'inputs'
|
|
85
|
+
for var, var_data in variable_dict[inp].items():
|
|
86
|
+
data_type_size = byte_size_string(var_data['type'])
|
|
87
|
+
data[iotype].setdefault(data_type_size, {})[var] = var_data
|
|
88
|
+
return data
|
|
89
|
+
|
|
90
|
+
def set_integrity_level(self, integrity_level):
|
|
91
|
+
"""Set integrity level of code generation.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
integrity_level (str): integrity level of the unit from 'A' to 'D' or 'QM'
|
|
95
|
+
"""
|
|
96
|
+
self._disp_start = integrity_level['DISP']['START']
|
|
97
|
+
self._disp_end = integrity_level['DISP']['END']
|
|
98
|
+
self._cal_start = integrity_level['CAL']['START']
|
|
99
|
+
self._cal_end = integrity_level['CAL']['END']
|
|
100
|
+
self._code_start = integrity_level['CODE']['START']
|
|
101
|
+
self._code_end = integrity_level['CODE']['END']
|
|
102
|
+
|
|
103
|
+
def _a2l_dict(self, var_dict, function):
|
|
104
|
+
"""Generate dict defining parameters for a2l-generation."""
|
|
105
|
+
def _range(data):
|
|
106
|
+
range_a2l = a2l_range(data['type'])
|
|
107
|
+
if data['min'] == '-':
|
|
108
|
+
a2l_min = range_a2l[0]
|
|
109
|
+
else:
|
|
110
|
+
a2l_min = data['min']
|
|
111
|
+
if data['max'] == '-':
|
|
112
|
+
a2l_max = range_a2l[1]
|
|
113
|
+
else:
|
|
114
|
+
a2l_max = data['max']
|
|
115
|
+
return a2l_min, a2l_max
|
|
116
|
+
|
|
117
|
+
res = {'vars': {},
|
|
118
|
+
'function': function}
|
|
119
|
+
for var, data in self._type_order_iterator(var_dict):
|
|
120
|
+
resv = res['vars']
|
|
121
|
+
a2l_min, a2l_max = _range(data)
|
|
122
|
+
a2l_data = {
|
|
123
|
+
'bitmask': get_bitmask(data['type']),
|
|
124
|
+
'description': data['description'],
|
|
125
|
+
'lsb': '2^0',
|
|
126
|
+
'max': a2l_max,
|
|
127
|
+
'min': a2l_min,
|
|
128
|
+
'offset': '0',
|
|
129
|
+
'unit': '',
|
|
130
|
+
'x_axis': None,
|
|
131
|
+
'y_axis': None
|
|
132
|
+
}
|
|
133
|
+
var_db = f'c{var[1:]}_db'
|
|
134
|
+
var_sw = self._var_name_to_dbgsw_name(var)
|
|
135
|
+
resv.setdefault(var_db, {})['a2l_data'] = a2l_data
|
|
136
|
+
a2l_data = {
|
|
137
|
+
'bitmask': get_bitmask(data['type']),
|
|
138
|
+
'description': f'debug switch for {var_db} (1=bdsw act)',
|
|
139
|
+
'lsb': '2^0',
|
|
140
|
+
'max': '1',
|
|
141
|
+
'min': '0',
|
|
142
|
+
'offset': '0',
|
|
143
|
+
'unit': '',
|
|
144
|
+
'x_axis': None,
|
|
145
|
+
'y_axis': None
|
|
146
|
+
}
|
|
147
|
+
resv.setdefault(var_sw, {})['a2l_data'] = a2l_data
|
|
148
|
+
resv[var_db]['array'] = []
|
|
149
|
+
resv[var_sw]['array'] = []
|
|
150
|
+
resv[var_db]['function'] = [function]
|
|
151
|
+
resv[var_sw]['function'] = [function]
|
|
152
|
+
resv[var_db]['var'] = {'cvc_type': 'CVC_CAL',
|
|
153
|
+
'type': data['type'],
|
|
154
|
+
'var': var}
|
|
155
|
+
resv[var_sw]['var'] = {'cvc_type': 'CVC_CAL',
|
|
156
|
+
'type': 'Bool',
|
|
157
|
+
'var': var}
|
|
158
|
+
return res
|
|
159
|
+
|
|
160
|
+
@staticmethod
|
|
161
|
+
def _var_name_to_dbgsw_name(name):
|
|
162
|
+
"""Convert a variable name to a debug switch name."""
|
|
163
|
+
# the below conversion would generate a correct name for the
|
|
164
|
+
# debug switch, however the current build systemt generates one
|
|
165
|
+
# like the currently returned name
|
|
166
|
+
# return re.sub(r'\w(\w+?)_\w+?_(\w+)', r'c\1_B_\2_sw', name)
|
|
167
|
+
return re.sub(r'\w(\w+)', r'c\1_sw', name)
|
|
168
|
+
|
|
169
|
+
@staticmethod
|
|
170
|
+
def _type_order_iterator(var_items):
|
|
171
|
+
"""Get iterator over all variables.
|
|
172
|
+
|
|
173
|
+
In data type size order, and then in alphabetical order.
|
|
174
|
+
"""
|
|
175
|
+
for _, typ_data in var_items.items():
|
|
176
|
+
for var in sorted(typ_data.keys()):
|
|
177
|
+
yield (var, typ_data[var])
|
|
178
|
+
|
|
179
|
+
def _gen_dbg_c_file(self, data, filename):
|
|
180
|
+
"""Generate debug c-files.
|
|
181
|
+
|
|
182
|
+
These define all the debug labels for
|
|
183
|
+
the supplier input and output signals.
|
|
184
|
+
"""
|
|
185
|
+
with open(filename, 'w', encoding="utf-8") as fh_c:
|
|
186
|
+
fh_c.write(self._unit_cfg.base_types_headers)
|
|
187
|
+
fh_c.write('#define CVC_DISP\n')
|
|
188
|
+
|
|
189
|
+
# define extrern variable references
|
|
190
|
+
fh_c.write(f'#include "{self._disp_start}"\n')
|
|
191
|
+
for var, var_data in self._type_order_iterator(data):
|
|
192
|
+
fh_c.write(f"extern CVC_DISP {var_data['type']} {var};\n")
|
|
193
|
+
fh_c.write(f'#include "{self._disp_end}"\n\n')
|
|
194
|
+
|
|
195
|
+
# define debug calibration constants
|
|
196
|
+
fh_c.write(f'#include "{self._cal_start}"\n')
|
|
197
|
+
fh_c.write('\n/* Debug values */\n\n')
|
|
198
|
+
for var, var_data in self._type_order_iterator(data):
|
|
199
|
+
initial_value = var_data['min'] if var_data['min'] != "-" and float(var_data['min']) > 0 else "0"
|
|
200
|
+
if self._use_volatile_globals:
|
|
201
|
+
fh_c.write(f"volatile {var_data['type']} c{var[1:]}_db = {initial_value};\n")
|
|
202
|
+
else:
|
|
203
|
+
fh_c.write(f"{var_data['type']} c{var[1:]}_db = {initial_value};\n")
|
|
204
|
+
|
|
205
|
+
fh_c.write('\n/* Debug switches */\n\n')
|
|
206
|
+
for var, var_data in self._type_order_iterator(data):
|
|
207
|
+
sw_name = self._var_name_to_dbgsw_name(var)
|
|
208
|
+
if self._use_volatile_globals:
|
|
209
|
+
fh_c.write(f"volatile Bool {sw_name} = 0;\n")
|
|
210
|
+
else:
|
|
211
|
+
fh_c.write(f"Bool {sw_name} = 0;\n")
|
|
212
|
+
fh_c.write(f'#include "{self._cal_end}"\n\n')
|
|
213
|
+
|
|
214
|
+
# set the variable to the debug calibration constants
|
|
215
|
+
fh_c.write('/***********************/\n')
|
|
216
|
+
fh_c.write('/* debug functionality */\n')
|
|
217
|
+
fh_c.write('/***********************/\n\n')
|
|
218
|
+
_, fname_tmp = os.path.split(filename)
|
|
219
|
+
func_name = fname_tmp.split('.')[-2]
|
|
220
|
+
fh_c.write(f'#include "{self._code_start}"\n')
|
|
221
|
+
fh_c.write(f'void {func_name}(void) {{\n')
|
|
222
|
+
for var, var_data in self._type_order_iterator(data):
|
|
223
|
+
sw_name = self._var_name_to_dbgsw_name(var)
|
|
224
|
+
fh_c.write(f' if ({sw_name}) {{\n')
|
|
225
|
+
fh_c.write(f' {var} = c{var[1:]}_db;\n }}\n')
|
|
226
|
+
fh_c.write(f'}}\n#include "{self._code_end}"\n\n')
|
|
227
|
+
self.info('Generated %s', filename)
|
|
228
|
+
|
|
229
|
+
def gen_dbg_files(self, file_path_inputs, file_path_outputs):
|
|
230
|
+
"""Generate the c-files and A2L-files.
|
|
231
|
+
|
|
232
|
+
These declares all the supplier interface debug parameters and functions.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
file_path_inputs (str): path to the debug inputs c-file.
|
|
236
|
+
file_path_outputs (str): path to the debug outputs c-file.
|
|
237
|
+
"""
|
|
238
|
+
_, file_name_inputs = os.path.split(file_path_inputs)
|
|
239
|
+
_, file_name_outputs = os.path.split(file_path_outputs)
|
|
240
|
+
|
|
241
|
+
if not self.dbg_dict['inputs']:
|
|
242
|
+
self.info(f"Skipping {file_name_inputs} as there were no corresponding vars.")
|
|
243
|
+
else:
|
|
244
|
+
self._gen_dbg_c_file(self.dbg_dict['inputs'], file_path_inputs + '.c')
|
|
245
|
+
a2l_dict_in = self._a2l_dict(self.dbg_dict['inputs'], file_name_inputs)
|
|
246
|
+
a2l = A2l(a2l_dict_in, self._prj_cfg)
|
|
247
|
+
a2l.gen_a2l(file_path_inputs + '.a2l')
|
|
248
|
+
|
|
249
|
+
if not self.dbg_dict['outputs']:
|
|
250
|
+
self.info(f"Skipping {file_name_outputs} as there were no corresponding vars.")
|
|
251
|
+
else:
|
|
252
|
+
self._gen_dbg_c_file(self.dbg_dict['outputs'], file_path_outputs + '.c')
|
|
253
|
+
a2l_dict_out = self._a2l_dict(self.dbg_dict['outputs'], file_name_outputs)
|
|
254
|
+
a2l = A2l(a2l_dict_out, self._prj_cfg)
|
|
255
|
+
a2l.gen_a2l(file_path_outputs + '.a2l')
|