Henrik Wahlqvist e36e378e9b Updates to be able to generate NVM RTE function calls
Change-Id: If692ccdf96403b7132735b70bfd8be4a96458ff8
2024-10-30 12:49:06 +01:00

199 lines
8.7 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_nvm(self, section):
cvc_undefines = []
cvc_defines = []
memory_section_handling = [
self.mem_map_config['projectDefines'][self._get_mem_map_section(section)]['nvm'] + '\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_type, nvm_dict in build_defs.NVM_LEVEL_MAP.items():
for section_dict in nvm_dict.values():
for section, section_file in section_dict.items():
section_config = self.mem_map_config['projectDefines'][self._get_mem_map_section(section)]
if nvm_type == "NORMAL" and "nvm" in section_config:
lines_to_write = self._get_nvm(section)[2]
else:
lines_to_write = []
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 + lines_to_write + footer)
self.info('Finished generating required header files (in %4.2f s)', time.time() - start_time)