powertrain-build/pybuild/memory_section.py
Henrik Wahlqvist 65c1d746a7 Copy from Volvo Cars local project
We don't transfer git history since it may contain proprietary data that
we cannot have in an open sources version.

Change-Id: I9586124c1720db69a76b9390e208e9f0ba3b86d4
2024-05-29 08:03:54 +02:00

225 lines
9.8 KiB
Python

# Copyright 2024 Volvo Car Corporation
# Licensed under Apache 2.0.
# -*- coding: utf-8 -*-
"""Module containing cvc classes for VCC - defines and includes for memory sections."""
import time
from pathlib import Path
from pybuild import build_defs
from pybuild.problem_logger import ProblemLogger
class MemorySection(ProblemLogger):
"""Handle headers for CVC_* definitions."""
calibration_definitions = [
'CVC_CAL',
'CVC_CAL_ASIL_A',
'CVC_CAL_ASIL_B',
'CVC_CAL_ASIL_C',
'CVC_CAL_ASIL_D',
'CVC_CAL_MERGEABLE_ASIL_A',
'CVC_CAL_MERGEABLE_ASIL_B',
'CVC_CAL_MERGEABLE_ASIL_C',
'CVC_CAL_MERGEABLE_ASIL_D'
]
measurable_definitions = [
'CVC_DISP',
'CVC_DISP_ASIL_A',
'CVC_DISP_ASIL_B',
'CVC_DISP_ASIL_C',
'CVC_DISP_ASIL_D'
]
project_defines = {
'HI': {
'START': {
'const': '#define {software_component_name}_START_SEC_CONST_UNSPECIFIED\n',
'disp': '#define {software_component_name}_START_SEC_VAR_INIT_UNSPECIFIED\n',
'cal': '#pragma section ".XcpCalibrationSection"\n'
},
'STOP': {
'const': '#define {software_component_name}_STOP_SEC_CONST_UNSPECIFIED\n',
'disp': '#define {software_component_name}_STOP_SEC_VAR_INIT_UNSPECIFIED\n',
'cal': '#pragma section\n'
}
},
'ZC': {
'START': {
'const': '#define {software_component_name}_START_SEC_VCC_CONST\n',
'disp': '#define {software_component_name}_START_SEC_VCC_DISP\n',
'cal': '#define {software_component_name}_START_SEC_VCC_CAL\n'
},
'STOP': {
'const': '#define {software_component_name}_STOP_SEC_VCC_CONST\n',
'disp': '#define {software_component_name}_STOP_SEC_VCC_DISP\n',
'cal': '#define {software_component_name}_STOP_SEC_VCC_CAL\n'
},
}
}
def __init__(self, build_cfg):
super().__init__()
self.build_cfg = build_cfg
self.a2l_cfg_name = self.build_cfg.get_a2l_cfg()['name']
self.ecu_supplier = self.build_cfg.get_ecu_info()[0]
if self.ecu_supplier == 'HI':
self.include_header_guards = True
self.software_component_name = self.a2l_cfg_name
self.mem_map_include = f'#include "{self.a2l_cfg_name}_MemMap.h"\n'
else:
self.include_header_guards = False
self.software_component_name = self.build_cfg.get_swc_name()
self.mem_map_include = f'#include "{self.software_component_name}_MemMap.h"\n'
self.xcp_enabled = self.build_cfg.get_xcp_enabled()
self.use_volatile_globals = self.build_cfg.get_use_volatile_globals()
@staticmethod
def _get_mem_map_section(section):
return 'STOP' if section == 'END' else section
@staticmethod
def _get_header(section_file):
section_file_header_guard = section_file.split('.')[0].upper()
return [
f'#ifndef {section_file_header_guard}_H\n',
f'#define {section_file_header_guard}_H\n\n'
]
@staticmethod
def _get_footer(section_file):
section_file_header_guard = section_file.split('.')[0].upper()
return [f'\n#endif /* {section_file_header_guard}_H */\n']
def _get_cal(self, section):
cvc_undefines = [f'#undef {definition}\n' for definition in self.calibration_definitions]
if section == 'START':
volatile_string = 'volatile' if self.use_volatile_globals else ''
cvc_defines = [f'#define {definition} {volatile_string}\n' for definition in self.calibration_definitions]
else:
cvc_defines = []
section_type = 'cal' if self.xcp_enabled else 'disp'
memory_section_handling = [
self.project_defines[self.ecu_supplier][self._get_mem_map_section(section)][section_type].format(
software_component_name=self.software_component_name
)
]
if self.ecu_supplier != 'HI' or not self.xcp_enabled:
memory_section_handling.append(self.mem_map_include)
return cvc_undefines, cvc_defines, memory_section_handling
def _get_disp(self, section):
cvc_undefines = [f'#undef {definition}\n' for definition in self.measurable_definitions]
if section == 'START':
volatile_string = 'volatile' if self.use_volatile_globals else ''
cvc_defines = [f'#define {definition} {volatile_string}\n' for definition in self.measurable_definitions]
else:
cvc_defines = []
memory_section_handling = [
self.project_defines[self.ecu_supplier][self._get_mem_map_section(section)]['disp'].format(
software_component_name=self.software_component_name
),
self.mem_map_include
]
return cvc_undefines, cvc_defines, memory_section_handling
def _get_code(self, section):
mem_map_section = self._get_mem_map_section(section)
cvc_undefines = []
cvc_defines = []
memory_section_handling = [
f'#define {self.software_component_name}_{mem_map_section}_SEC_CODE\n',
self.mem_map_include
]
return cvc_undefines, cvc_defines, memory_section_handling
def _get_const(self, section):
cvc_undefines = []
cvc_defines = []
memory_section_handling = [
self.project_defines[self.ecu_supplier][self._get_mem_map_section(section)]['const'].format(
software_component_name=self.software_component_name
),
self.mem_map_include
]
return cvc_undefines, cvc_defines, memory_section_handling
def _get_rest(self):
cvc_undefines = []
cvc_defines = []
memory_section_handling = [
self.mem_map_include
]
return cvc_undefines, cvc_defines, memory_section_handling
def _get_predecl(self):
cvc_undefines = []
cvc_defines = []
memory_section_handling = [
self.mem_map_include
]
return cvc_undefines, cvc_defines, memory_section_handling
def generate_cvc_header(self, section, section_file):
"""Generate CVC headers.
Args:
section (str): Name of the CVC section
section_file (str): Name of the header file
Returns:
lines_to_write (list(str)): Lines to write to given section file.
"""
header = self._get_header(section_file) if self.include_header_guards else []
footer = self._get_footer(section_file) if self.include_header_guards else []
if '_CAL_' in section_file:
cvc_undefines, cvc_defines, memory_section_handling = self._get_cal(section)
elif '_DISP_' in section_file:
cvc_undefines, cvc_defines, memory_section_handling = self._get_disp(section)
elif not section_file.startswith('PREDECL_'):
if section_file.startswith('CVC_CAL') or section_file.startswith('CVC_DISP'):
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)
elif section_file.startswith('CVC_CONST'):
cvc_undefines, cvc_defines, memory_section_handling = self._get_const(section)
else:
cvc_undefines, cvc_defines, memory_section_handling = self._get_rest()
else:
cvc_undefines, cvc_defines, memory_section_handling = self._get_predecl()
return header + cvc_undefines + cvc_defines + memory_section_handling + footer
def generate_required_header_files(self):
"""Generate required header files to delivery folder.
Generate required header files such as memory protection files.
NOTE: Currently, only one ASIL level can be selected for an SWC.
"""
self.info('******************************************************')
self.info('Start generating required header files')
start_time = time.time()
src_dst_dir = self.build_cfg.get_src_code_dst_dir()
for section_dict in build_defs.PREDECL_EXTRA.values():
for section_file in section_dict.values():
header = self._get_header(section_file) if self.include_header_guards else []
footer = self._get_footer(section_file) if self.include_header_guards else []
with Path(src_dst_dir, section_file).open('w', encoding="utf-8") as header_file_handler:
header_file_handler.writelines(header + footer)
for asil_dict in build_defs.ASIL_LEVEL_MAP.values():
for type_dict in asil_dict.values():
for section_dict in type_dict.values():
for section, section_file in section_dict.items():
lines_to_write = self.generate_cvc_header(section, section_file)
with Path(src_dst_dir, section_file).open('w', encoding="utf-8") as header_file_handler:
header_file_handler.writelines(lines_to_write)
for nvm_dict in build_defs.NVM_LEVEL_MAP.values():
for section_dict in nvm_dict.values():
for section_file in section_dict.values():
header = self._get_header(section_file) if self.include_header_guards else []
footer = self._get_footer(section_file) if self.include_header_guards else []
with Path(src_dst_dir, section_file).open('w', encoding="utf-8") as header_file_handler:
header_file_handler.writelines(header + footer)
self.info('Finished generating required header files (in %4.2f s)', time.time() - start_time)