Henrik Wahlqvist fda739bc13 Refactor usage of ecu_supplier
Removed most of the decisions based on ecu_supplier and made it more
granular using individual configuration.
Current project types will keep their config by adding templates in the
BaseConfig.json file.
Some usecases were kept for legacy reasons.

Change-Id: I3d6199713006489baff0bf73751596770fd1f968
2024-09-17 08:25:46 +00:00

185 lines
8.1 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 powertrain_build import build_defs
from powertrain_build.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'
]
def __init__(self, build_cfg):
super().__init__()
self.build_cfg = build_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'
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.mem_map_config['projectDefines'][self._get_mem_map_section(section)][section_type] + '\n'
]
if self.mem_map_config['includeMemMapForCalibration'] 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.mem_map_config['projectDefines'][self._get_mem_map_section(section)]['disp'] + '\n',
self.mem_map_include
]
return cvc_undefines, cvc_defines, memory_section_handling
def _get_code(self, section):
cvc_undefines = []
cvc_defines = []
memory_section_handling = [
self.mem_map_config['projectDefines'][self._get_mem_map_section(section)]['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.mem_map_config['projectDefines'][self._get_mem_map_section(section)]['const'] + '\n',
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)