Add option for redirecting calibration variables as RTE function calls
Change-Id: Iacc4ea5188c01dd1c030b1b0606658177130e322
This commit is contained in:
parent
9fc9a2f40d
commit
ed73202f9d
@ -118,6 +118,7 @@ This key is used to set individual options to match the old ECU types, see examp
|
||||
"generalAsilLevelDebug": "B",
|
||||
"generalAsilLevelDependability": "B",
|
||||
"generateCalibrationInterfaceFiles": false,
|
||||
"useCalibrationRteMacroExpansion": false,
|
||||
"generateCoreDummy": true,
|
||||
"generateDummyVar": true,
|
||||
"generateInterfaceHeaders": false,
|
||||
@ -154,6 +155,15 @@ These files can be used together with a certain type of calibration strategy in
|
||||
The files generates a certain variable called "c\<swc_name\>\_TriggerReadRteCData" which can be toggled to read the rest of the calibration variables.
|
||||
This makes the CPU not overload reading all the calibration variables from the RTE every iteration.
|
||||
|
||||
#### useCalibrationRteMacroExpansion
|
||||
|
||||
Redefine calibration variables as RTE calls.
|
||||
Takes priority over "generateCalibrationInterfaceFiles" and is only available when "generateYamlInterfaceFile" is true.
|
||||
Default is False.
|
||||
|
||||
Redefines calibration variables as RTE calls in an attempty to save memory.
|
||||
Note that this increases CPU load.
|
||||
|
||||
#### generateCoreDummy
|
||||
|
||||
Generates a file defining dummy versions of functions towards e.g. supplier interface type functions.
|
||||
|
@ -888,7 +888,7 @@ def build(
|
||||
copy_unit_cfgs_to_output(build_cfg)
|
||||
copy_files_to_include(build_cfg)
|
||||
if code_generation_config["generateInterfaceHeaders"]:
|
||||
memory_section = MemorySection(build_cfg)
|
||||
memory_section = MemorySection(build_cfg, unit_cfg)
|
||||
memory_section.generate_required_header_files()
|
||||
|
||||
# Propagate tag name for release builds, TAG_NAME must be set in environment
|
||||
@ -944,11 +944,16 @@ def build(
|
||||
|
||||
if code_generation_config["generateCalibrationInterfaceFiles"]:
|
||||
LOG.info("******************************************************")
|
||||
LOG.info("Generating calibration interface files")
|
||||
zc_calibration = ZoneControllerCalibration(
|
||||
build_cfg, composition_yaml.cal_class_info["tl"]
|
||||
)
|
||||
zc_calibration.generate_calibration_interface_files()
|
||||
if code_generation_config["useCalibrationRteMacroExpansion"]:
|
||||
LOG.warning(
|
||||
"Skip generating calibration interface files as useCalibrationRteMacroExpansion is set to true"
|
||||
)
|
||||
else:
|
||||
LOG.info("Generating calibration interface files")
|
||||
zc_calibration = ZoneControllerCalibration(
|
||||
build_cfg, composition_yaml.cal_class_info["tl"]
|
||||
)
|
||||
zc_calibration.generate_calibration_interface_files()
|
||||
elif build_cfg.get_ecu_info()[0] == "HI":
|
||||
generate_nvm_def(build_cfg, unit_cfg, no_nvm_a2l)
|
||||
LOG.info("******************************************************")
|
||||
|
@ -67,6 +67,7 @@ class BuildProjConfig:
|
||||
'generalAsilLevelDebug': 'B',
|
||||
'generalAsilLevelDependability': 'B',
|
||||
'generateCalibrationInterfaceFiles': False,
|
||||
'useCalibrationRteMacroExpansion': False,
|
||||
'generateCoreDummy': False,
|
||||
'generateDummyVar': False,
|
||||
'generateInterfaceHeaders': False,
|
||||
|
@ -32,9 +32,10 @@ class MemorySection(ProblemLogger):
|
||||
'CVC_DISP_ASIL_D'
|
||||
]
|
||||
|
||||
def __init__(self, build_cfg):
|
||||
def __init__(self, build_cfg, unit_cfg):
|
||||
super().__init__()
|
||||
self.build_cfg = build_cfg
|
||||
self.unit_cfg = unit_cfg
|
||||
self.mem_map_config = self.build_cfg.get_memory_map_config()
|
||||
self.include_header_guards = self.mem_map_config['includeHeaderGuards']
|
||||
self.mem_map_include = f'#include "{self.mem_map_config["memMapPrefix"]}_MemMap.h"\n'
|
||||
@ -58,6 +59,27 @@ class MemorySection(ProblemLogger):
|
||||
section_file_header_guard = section_file.split('.')[0].upper()
|
||||
return [f'\n#endif /* {section_file_header_guard}_H */\n']
|
||||
|
||||
def _get_calibration_rte_macro_expansion(self, section_file):
|
||||
macros = self._get_header(section_file)
|
||||
swc_name = self.build_cfg.get_composition_config("softwareComponentName")
|
||||
macros.append(f'#include "Rte_{swc_name}.h"\n')
|
||||
|
||||
config = self.unit_cfg.get_per_cfg_unit_cfg()
|
||||
valid_configs = ["outports", "local_vars", "calib_consts"]
|
||||
for valid_config in valid_configs:
|
||||
for signal_name, unit_info in config.get(valid_config, {}).items():
|
||||
define_str = f'#define {signal_name} Rte_CData_{swc_name}_{signal_name}()'
|
||||
if signal_name.startswith("m") and not signal_name.endswith("_r") and not signal_name.endswith("_c"):
|
||||
define_str += f"->dt_{signal_name}"
|
||||
define_str += "\n"
|
||||
for info in unit_info.values(): # Should be length 1 for cal
|
||||
if "CVC_CAL" in info["class"]:
|
||||
macros.append(define_str)
|
||||
|
||||
macros.extend(self._get_footer(section_file))
|
||||
|
||||
return macros
|
||||
|
||||
def _get_cal(self, section):
|
||||
cvc_undefines = [f'#undef {definition}\n' for definition in self.calibration_definitions]
|
||||
if section == 'START':
|
||||
@ -149,6 +171,12 @@ class MemorySection(ProblemLogger):
|
||||
self.critical('Should not find CVC_CAL/DISP here. Check logic. File: %s.', section_file)
|
||||
elif section_file.startswith('CVC_CODE'):
|
||||
cvc_undefines, cvc_defines, memory_section_handling = self._get_code(section)
|
||||
use_rte_macro_expansion = self.build_cfg.get_code_generation_config(item="useRteMacroExpansion")
|
||||
if section == 'START' and use_rte_macro_expansion:
|
||||
memory_section_handling.extend(self._get_calibration_rte_macro_expansion(section_file))
|
||||
# header and footer are part of the extension
|
||||
header = []
|
||||
footer = []
|
||||
elif section_file.startswith('CVC_CONST'):
|
||||
cvc_undefines, cvc_defines, memory_section_handling = self._get_const(section)
|
||||
else:
|
||||
|
@ -57,7 +57,12 @@ class CompositionYaml(ProblemLogger):
|
||||
self.calibration_init_values = self.get_init_values(calibration_variables)
|
||||
self.cal_class_info = self._get_class_info(calibration_variables)
|
||||
self.meas_class_info = self._get_class_info(measurable_variables)
|
||||
self.include_calibration_interface_files = False
|
||||
if self.build_cfg.get_code_generation_config(item="generateCalibrationInterfaceFiles"):
|
||||
self.include_calibration_interface_files = True
|
||||
if self.build_cfg.get_code_generation_config(item="useCalibrationRteMacroExpansion"):
|
||||
self.include_calibration_interface_files = False
|
||||
if self.include_calibration_interface_files:
|
||||
trigger_read_rte_cdata_signal_name = self._get_calibration_trigger_signal_name(calibration_variables)
|
||||
self.cal_class_info["autosar"]["class_info"].update(
|
||||
{
|
||||
@ -456,7 +461,7 @@ class CompositionYaml(ProblemLogger):
|
||||
calibration_variables = list(self.cal_class_info["autosar"]["class_info"].keys())
|
||||
swc_content = {init_function: {"type": "INIT", "accesses": calibration_variables}}
|
||||
|
||||
if self.build_cfg.get_code_generation_config(item="generateCalibrationInterfaceFiles"):
|
||||
if self.include_calibration_interface_files:
|
||||
cal_init_function = autosar_prefix + ZCC.calibration_function_init_template.format(swc_name=swc_name)
|
||||
cal_step_function = autosar_prefix + ZCC.calibration_function_step_template.format(swc_name=swc_name)
|
||||
swc_content[cal_init_function] = {"type": "INIT", "accesses": calibration_variables}
|
||||
|
@ -7,6 +7,7 @@ from pathlib import Path
|
||||
from unittest import mock, TestCase
|
||||
from powertrain_build.build_proj_config import BuildProjConfig
|
||||
from powertrain_build.memory_section import MemorySection
|
||||
from powertrain_build.unit_configs import UnitConfigs
|
||||
from powertrain_build.lib import helper_functions
|
||||
from .test_build import remove
|
||||
|
||||
@ -22,10 +23,12 @@ class TestMemorySection(TestCase):
|
||||
helper_functions.create_dir(self.src_code_dir)
|
||||
|
||||
cnfg_files_folder = Path(SRC_DIR, 'cnfg_files')
|
||||
build_cfg = mock.MagicMock(spec_set=BuildProjConfig(Path(cnfg_files_folder, 'ProjectCfg.json')))
|
||||
build_cfg.get_src_code_dst_dir = mock.MagicMock(return_value=self.src_code_dir)
|
||||
build_cfg.get_use_volatile_globals = mock.MagicMock(return_value=False)
|
||||
build_cfg.get_memory_map_config = mock.MagicMock(
|
||||
self.build_cfg = mock.MagicMock(spec_set=BuildProjConfig(Path(cnfg_files_folder, 'ProjectCfg.json')))
|
||||
self.build_cfg.get_composition_config = mock.MagicMock(return_value='DUMMY')
|
||||
self.build_cfg.get_code_generation_config = mock.MagicMock(return_value=False)
|
||||
self.build_cfg.get_src_code_dst_dir = mock.MagicMock(return_value=self.src_code_dir)
|
||||
self.build_cfg.get_use_volatile_globals = mock.MagicMock(return_value=False)
|
||||
self.build_cfg.get_memory_map_config = mock.MagicMock(
|
||||
return_value={
|
||||
'includeHeaderGuards': True,
|
||||
'includeMemMapForCalibration': False,
|
||||
@ -46,7 +49,8 @@ class TestMemorySection(TestCase):
|
||||
}
|
||||
}
|
||||
)
|
||||
self.memory_section = MemorySection(build_cfg)
|
||||
self.unit_cfg = mock.MagicMock(spec_set=UnitConfigs)
|
||||
self.memory_section = MemorySection(self.build_cfg, self.unit_cfg)
|
||||
|
||||
def test_generate_cvc_header_cal(self):
|
||||
"""Test MemorySection.generate_cvc_header() with CAL type file."""
|
||||
@ -240,6 +244,43 @@ class TestMemorySection(TestCase):
|
||||
self.assertListEqual(expected_start, result_start)
|
||||
self.assertListEqual(expected_stop, result_stop)
|
||||
|
||||
def test_generate_cvc_header_code_with_rte_macros(self):
|
||||
"""Test MemorySection.generate_cvc_header(),
|
||||
with CODE type file and useCalibrationRteMacroExpansion set to true."""
|
||||
self.build_cfg.get_code_generation_config = mock.MagicMock(return_value=True)
|
||||
self.unit_cfg.get_per_cfg_unit_cfg.return_value = {
|
||||
'calib_consts': {
|
||||
'mVcDummyOne': {'DummyUnit': {'class': 'CVC_CAL'}}
|
||||
},
|
||||
'outports': {
|
||||
'sVcDummyOne': {'DummyUnit': {'class': 'CVC_DISP'}},
|
||||
'sVcDummyTwo': {'DummyUnit': {'class': 'CVC_CAL'}}
|
||||
}
|
||||
}
|
||||
self.memory_section = MemorySection(self.build_cfg, self.unit_cfg)
|
||||
test_file_name = 'CVC_CODE_DUMMY.h'
|
||||
expected_start = [
|
||||
'#define MOCK_HI_START_SEC_CODE\n',
|
||||
'#include "MOCK_HI_MemMap.h"\n',
|
||||
'#ifndef CVC_CODE_DUMMY_H\n',
|
||||
'#define CVC_CODE_DUMMY_H\n\n',
|
||||
'#include "Rte_DUMMY.h"\n',
|
||||
'#define sVcDummyTwo Rte_CData_DUMMY_sVcDummyTwo()\n',
|
||||
'#define mVcDummyOne Rte_CData_DUMMY_mVcDummyOne()->dt_mVcDummyOne\n',
|
||||
'\n#endif /* CVC_CODE_DUMMY_H */\n'
|
||||
]
|
||||
expected_stop = [
|
||||
'#ifndef CVC_CODE_DUMMY_H\n',
|
||||
'#define CVC_CODE_DUMMY_H\n\n',
|
||||
'#define MOCK_HI_STOP_SEC_CODE\n',
|
||||
'#include "MOCK_HI_MemMap.h"\n',
|
||||
'\n#endif /* CVC_CODE_DUMMY_H */\n'
|
||||
]
|
||||
result_start = self.memory_section.generate_cvc_header('START', test_file_name)
|
||||
result_stop = self.memory_section.generate_cvc_header('END', test_file_name)
|
||||
self.assertListEqual(expected_start, result_start)
|
||||
self.assertListEqual(expected_stop, result_stop)
|
||||
|
||||
def test_generate_cvc_header_const(self):
|
||||
"""Test MemorySection.generate_cvc_header() with CONST type file."""
|
||||
test_file_name = 'CVC_CONST_DUMMY.h'
|
||||
|
@ -33,12 +33,52 @@ class BuildProjConfigMock(BuildProjConfig):
|
||||
name = ""
|
||||
|
||||
|
||||
def mock_get_code_generation_config_default(item):
|
||||
"""Function to mock BuildProjConfig.get_code_generation_config."""
|
||||
return {
|
||||
"generalAsilLevelDebug": "B",
|
||||
"generalAsilLevelDependability": "B",
|
||||
"generateCalibrationInterfaceFiles": False,
|
||||
"useCalibrationRteMacroExpansion": False,
|
||||
"generateCoreDummy": False,
|
||||
"generateDummyVar": False,
|
||||
"generateInterfaceHeaders": False,
|
||||
"generateRteCheckpointIds": False,
|
||||
"generateYamlInterfaceFile": False,
|
||||
"includeAllEnums": False,
|
||||
"mapToRteEnums": False,
|
||||
"propagateTagName": False,
|
||||
"useA2lSymbolLinks": False,
|
||||
"useRteNvmStructs": False,
|
||||
}[item]
|
||||
|
||||
|
||||
def mock_get_code_generation_config_calibration_interface(item):
|
||||
"""Function to mock BuildProjConfig.get_code_generation_config."""
|
||||
return {
|
||||
"generalAsilLevelDebug": "B",
|
||||
"generalAsilLevelDependability": "B",
|
||||
"generateCalibrationInterfaceFiles": True,
|
||||
"useCalibrationRteMacroExpansion": False,
|
||||
"generateCoreDummy": False,
|
||||
"generateDummyVar": False,
|
||||
"generateInterfaceHeaders": False,
|
||||
"generateRteCheckpointIds": False,
|
||||
"generateYamlInterfaceFile": False,
|
||||
"includeAllEnums": False,
|
||||
"mapToRteEnums": False,
|
||||
"propagateTagName": False,
|
||||
"useA2lSymbolLinks": False,
|
||||
"useRteNvmStructs": False,
|
||||
}[item]
|
||||
|
||||
|
||||
def mock_get_composition_config_default(key):
|
||||
"""Function to mock BuildProjConfig.get_composition_config."""
|
||||
return {
|
||||
"compositionArxml": "some_arxml.arxml",
|
||||
"compositionName": "compositionName",
|
||||
'compositionEnding': 'yml',
|
||||
"compositionEnding": "yml",
|
||||
"softwareComponentName": "testName_SC",
|
||||
"softwareComponentTemplate": "ARTCSC",
|
||||
"asil": "QM",
|
||||
@ -46,11 +86,11 @@ def mock_get_composition_config_default(key):
|
||||
"customYamlInitFunctionName": None,
|
||||
"customYamlStepFunctionName": None,
|
||||
"generateExternalImplementationType": True,
|
||||
'includeStatic': True,
|
||||
'includeShared': True,
|
||||
'includeDiagnostics': True,
|
||||
'includeNvm': True,
|
||||
'scaleMapsAndCurves': True,
|
||||
"includeStatic": True,
|
||||
"includeShared": True,
|
||||
"includeDiagnostics": True,
|
||||
"includeNvm": True,
|
||||
"scaleMapsAndCurves": True,
|
||||
}[key]
|
||||
|
||||
|
||||
@ -59,7 +99,7 @@ def mock_get_composition_config_custom_names(key):
|
||||
return {
|
||||
"compositionArxml": "some_arxml.arxml",
|
||||
"compositionName": "compositionName",
|
||||
'compositionEnding': 'yml',
|
||||
"compositionEnding": "yml",
|
||||
"softwareComponentName": "testName_SC",
|
||||
"softwareComponentTemplate": "ARTCSC",
|
||||
"asil": "QM",
|
||||
@ -67,11 +107,11 @@ def mock_get_composition_config_custom_names(key):
|
||||
"customYamlInitFunctionName": "dummy_init",
|
||||
"customYamlStepFunctionName": "dummy_step",
|
||||
"generateExternalImplementationType": True,
|
||||
'includeStatic': True,
|
||||
'includeShared': True,
|
||||
'includeDiagnostics': True,
|
||||
'includeNvm': True,
|
||||
'scaleMapsAndCurves': True,
|
||||
"includeStatic": True,
|
||||
"includeShared": True,
|
||||
"includeDiagnostics": True,
|
||||
"includeNvm": True,
|
||||
"scaleMapsAndCurves": True,
|
||||
}[key]
|
||||
|
||||
|
||||
@ -81,6 +121,7 @@ class TestCompositionYaml(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set-up common data structures for all tests in the test case."""
|
||||
self.build_cfg = MagicMock(spec_set=BuildProjConfigMock)
|
||||
self.build_cfg.get_code_generation_config.side_effect = mock_get_code_generation_config_default
|
||||
self.build_cfg.get_composition_config.side_effect = mock_get_composition_config_default
|
||||
self.build_cfg.name = "XVC"
|
||||
self.build_cfg.get_scheduler_prefix = MagicMock(return_value="prefix_")
|
||||
@ -90,7 +131,6 @@ class TestCompositionYaml(unittest.TestCase):
|
||||
self.build_cfg.get_units_raster_cfg = MagicMock(
|
||||
return_value=({"SampleTimes": {"testRunnable": 10}})
|
||||
)
|
||||
self.build_cfg.get_code_generation_config = MagicMock(return_value=False)
|
||||
|
||||
self.unit_cfg = MagicMock(spec_set=UnitConfigs)
|
||||
self.unit_cfg.get_per_cfg_unit_cfg.return_value = copy.deepcopy(
|
||||
@ -145,8 +185,8 @@ class TestCompositionYaml(unittest.TestCase):
|
||||
|
||||
def test_composition_yaml_with_calibration(self):
|
||||
"""Checking that the dict is generated correctly including calibration data,
|
||||
setting generateCalibrationInterfaceFiles to true (sort of)."""
|
||||
self.build_cfg.get_code_generation_config = MagicMock(return_value=True)
|
||||
setting generateCalibrationInterfaceFiles to true."""
|
||||
self.build_cfg.get_code_generation_config.side_effect = mock_get_code_generation_config_calibration_interface
|
||||
with patch.object(
|
||||
CompositionYaml,
|
||||
"_get_all_calibration_definitions",
|
||||
@ -158,6 +198,21 @@ class TestCompositionYaml(unittest.TestCase):
|
||||
result = self.composition_yaml.gather_yaml_info()
|
||||
self.assertDictEqual(composition_yaml.expected_cal_result, result)
|
||||
|
||||
def test_composition_yaml_with_calibration_and_rte_macro(self):
|
||||
"""Checking that the dict is generated correctly including calibration data,
|
||||
setting both generateCalibrationInterfaceFiles and useCalibrationRteMacroExpansion to true (sort of)."""
|
||||
self.build_cfg.get_code_generation_config = MagicMock(return_value=True)
|
||||
with patch.object(
|
||||
CompositionYaml,
|
||||
"_get_all_calibration_definitions",
|
||||
return_value=self.calibration_definitions
|
||||
):
|
||||
self.composition_yaml = CompositionYaml(
|
||||
self.build_cfg, self.zc_spec, self.unit_cfg, self.zc_core, self.zc_dids, self.nvm_def, {}, {}
|
||||
)
|
||||
result = self.composition_yaml.gather_yaml_info()
|
||||
self.assertDictEqual(composition_yaml.expected_result, result)
|
||||
|
||||
def test_composition_yaml_with_a2l_axis_data(self):
|
||||
"""Checking that the dict is generated correctly, including a2l axis data."""
|
||||
self.unit_cfg.get_per_cfg_unit_cfg.return_value = \
|
||||
|
Loading…
x
Reference in New Issue
Block a user