
Introduced in: 75b3991f5720dcbe78f06def9a85fa55169cab65 * Rte_CData_* functions were never declared. * Type definitions of Maps should be structs. Change-Id: Id8d371e6fd0dee7e7accf480a5a09e568db80af4
239 lines
11 KiB
Python
239 lines
11 KiB
Python
# Copyright 2024 Volvo Car Corporation
|
|
# Licensed under Apache 2.0.
|
|
|
|
# -*- coding: utf-8 -*-
|
|
"""Module containing classes for generating RTE dummy code.
|
|
|
|
These files are needed for building test SW,
|
|
where the RTE is not available.
|
|
For example, when running Silver tests.
|
|
"""
|
|
|
|
from powertrain_build.problem_logger import ProblemLogger
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
class RteDummy(ProblemLogger):
|
|
"""A class for RTE dummy file generation."""
|
|
|
|
def __init__(self, build_cfg, nvm_def, calib_data):
|
|
"""Init.
|
|
|
|
Args:
|
|
build_cfg (BuildProjConfig): Object with build configuration settings.
|
|
nvm_def (ZCNVMDef): Object with NVM definition information.
|
|
calib_data (dict): Dictionary containing calibration data for a ZoneController project.
|
|
"""
|
|
super().__init__()
|
|
self.build_cfg = build_cfg
|
|
self.nvm_def = nvm_def
|
|
self.calibration_variables = calib_data.get("class_info", {})
|
|
self.swc_header_file_name = f"Rte_{self.build_cfg.get_composition_config('softwareComponentName')}"
|
|
self.type_header_file_name = "Rte_Type"
|
|
self.source_file_name = "Rte_Dummy"
|
|
|
|
def _get_common_header(self):
|
|
"""Get common header for the RTE dummy files."""
|
|
return (
|
|
"/*\n"
|
|
" * This file is generated by the Powertrain Build System.\n"
|
|
" * It defines RTE dummy types and/or functions.\n"
|
|
" * Do not modify this file manually.\n"
|
|
" */\n"
|
|
)
|
|
|
|
def _get_swc_header_content(self):
|
|
"""Get content for the SWC RTE dummy header."""
|
|
return (
|
|
f"{self._get_common_header()}"
|
|
f"#ifndef {self.swc_header_file_name.upper()}_H\n"
|
|
f"#define {self.swc_header_file_name.upper()}_H\n\n"
|
|
f'#include "{self.type_header_file_name}.h"\n'
|
|
f"#endif /* {self.swc_header_file_name.upper()}_H */\n"
|
|
)
|
|
|
|
def _get_type_header_header(self):
|
|
"""Get header for the RTE type dummy header."""
|
|
include_nvm_header = ""
|
|
if not self.build_cfg.get_code_generation_config("useRteNvmStructs"):
|
|
nvm_defs = self.build_cfg.get_nvm_defs()
|
|
nvm_file_name = nvm_defs["fileName"]
|
|
include_nvm_header = f'#include "{nvm_file_name}.h"\n'
|
|
return (
|
|
f"{self._get_common_header()}"
|
|
f"#ifndef {self.type_header_file_name.upper()}_H\n"
|
|
f"#define {self.type_header_file_name.upper()}_H\n\n"
|
|
'#include "tl_basetypes.h"\n'
|
|
f"{include_nvm_header}\n"
|
|
"#define FALSE 0U\n"
|
|
"#define TRUE 1U\n"
|
|
)
|
|
|
|
def _get_type_header_footer(self):
|
|
"""Get footer for the RTE type dummy header."""
|
|
return f"\n#endif /* {self.type_header_file_name.upper()}_H */\n"
|
|
|
|
def _get_source_header(self):
|
|
"""Get header for the RTE dummy source."""
|
|
return (
|
|
f"{self._get_common_header()}"
|
|
f'#include "{self.swc_header_file_name}.h"\n\n'
|
|
)
|
|
|
|
def _get_typedef_dummy(self):
|
|
"""Get typedef dummy code."""
|
|
typedefs = []
|
|
|
|
function_name = self.build_cfg.get_composition_config("compositionName")
|
|
if function_name is None:
|
|
function_name = self.build_cfg.get_composition_config("softwareComponentName")
|
|
if self.build_cfg.get_code_generation_config("generateRteCheckpointIds"):
|
|
typedefs.append(f"typedef UInt8 {function_name}FctList;\n")
|
|
|
|
# MAPs get typedef:ed to structs and need special data type mapping in calibration.py
|
|
for signal_name, signal_data in self.calibration_variables.items():
|
|
if isinstance(signal_data["width"], list):
|
|
if signal_name.startswith("m") and signal_name[-2:] not in ["_r", "_c"]:
|
|
typedefs.append(
|
|
f"typedef {signal_data['type']} {signal_data['autosar_type']}_e[{signal_data['width'][0]}];\n"
|
|
)
|
|
typedefs.append(
|
|
"typedef struct \n"
|
|
"{\n"
|
|
f" {signal_data['autosar_type']}_e {signal_data['autosar_type']}[{signal_data['width'][1]}];\n"
|
|
f"}} {signal_data['autosar_type']};\n\n"
|
|
)
|
|
|
|
return "".join(typedefs)
|
|
|
|
def _get_nvm_header_dummy(self):
|
|
"""Get NVM dummy header code."""
|
|
struct_defines = []
|
|
function_declarations = []
|
|
prefix = self.build_cfg.get_scheduler_prefix()
|
|
use_rte_nvm_structs = self.build_cfg.get_code_generation_config("useRteNvmStructs")
|
|
|
|
for memory_area in self.nvm_def._nvm_memory_areas:
|
|
nvm_name = f"{prefix}{memory_area}"
|
|
struct_name = f"dt_{nvm_name}" if use_rte_nvm_structs else f"struct {nvm_name}"
|
|
function_declarations.append(f"{struct_name} *Rte_Pim_{nvm_name}(void);")
|
|
function_declarations.append(f"void Rte_Read_{nvm_name.upper()}_{nvm_name.upper()}({struct_name} *block);")
|
|
function_declarations.append(f"void Rte_Write_{nvm_name.upper()}_{nvm_name.upper()}({struct_name} *block);")
|
|
|
|
if use_rte_nvm_structs:
|
|
struct_defines.append("typedef struct\n{")
|
|
memory_area_index = self.nvm_def._get_nvm_areas_index(memory_area)
|
|
nr_of_unused_signals = self.nvm_def.nvm_definitions[memory_area_index]["size"]
|
|
signals = self.nvm_def.nvm_definitions[memory_area_index]["signals"]
|
|
for signal in signals:
|
|
signal_string = ""
|
|
nr_of_unused_signals -= signal["x_size"] * signal["y_size"]
|
|
signal_string += f' {signal["type"]} {self.nvm_def.struct_member_prefix}{signal["name"]}'
|
|
size = max(signal["x_size"], 1) * max(signal["y_size"], 1)
|
|
if size > 1:
|
|
if signal["x_size"] > 1:
|
|
signal_string += f'[{signal["x_size"]}]'
|
|
if signal["y_size"] > 1:
|
|
signal_string += f'[{signal["y_size"]}]'
|
|
signal_string += ";"
|
|
struct_defines.append(signal_string)
|
|
if nr_of_unused_signals > 0:
|
|
struct_defines.append(
|
|
f' {self.nvm_def.nvm_definitions[memory_area_index]["default_datatype"]} '
|
|
f'unused[{nr_of_unused_signals}];'
|
|
)
|
|
struct_defines.append(f"}} {struct_name};\n")
|
|
|
|
return "\n".join(struct_defines + function_declarations)
|
|
|
|
def _get_nvm_source_dummy(self):
|
|
"""Generate NVM source dummy code."""
|
|
lines_to_write = []
|
|
prefix = self.build_cfg.get_scheduler_prefix()
|
|
use_rte_nvm_structs = self.build_cfg.get_code_generation_config("useRteNvmStructs")
|
|
for memory_area in self.nvm_def._nvm_memory_areas:
|
|
nvm_name = f"{prefix}{memory_area}"
|
|
struct_name = f"dt_{nvm_name}" if use_rte_nvm_structs else f"struct {nvm_name}"
|
|
return_string = f"{struct_name} dummy; {struct_name}* dummyPtr = &dummy; return dummyPtr;"
|
|
lines_to_write.append(f"{struct_name} *Rte_Pim_{nvm_name}(void) {{ {return_string} }}")
|
|
lines_to_write.append(f"void Rte_Read_{nvm_name.upper()}_{nvm_name.upper()}({struct_name} *block) {{}}")
|
|
lines_to_write.append(f"void Rte_Write_{nvm_name.upper()}_{nvm_name.upper()}({struct_name} *block) {{}}")
|
|
lines_to_write.append("")
|
|
return "\n".join(lines_to_write)
|
|
|
|
def _get_calibration_function_data(self, signal_name, signal_data):
|
|
""""Get calibration function data.
|
|
|
|
Args:
|
|
signal_name (str): Name of the signal.
|
|
signal_data (dict): Dictionary containing signal data.
|
|
Returns:
|
|
return_type, return_string (tuple): Tuple containing the return type and return string.
|
|
"""
|
|
if isinstance(signal_data["width"], list):
|
|
# MAPs get typedef:ed to structs and need special data type mapping in calibration.py
|
|
if signal_name.startswith("m") and signal_name[-2:] not in ["_r", "_c"]:
|
|
return_type = f'const {signal_data["autosar_type"]}*'
|
|
return_string = (
|
|
f"const {signal_data['autosar_type']} dummy; "
|
|
f"{return_type} dummyPtr = &dummy; "
|
|
"return dummyPtr;"
|
|
)
|
|
else:
|
|
return_type = f'const {signal_data["type"]}*'
|
|
return_string = (
|
|
f"{signal_data['type']} dummy; "
|
|
f"{return_type} dummyPtr = &dummy; "
|
|
"return dummyPtr;"
|
|
)
|
|
else:
|
|
return_type = f'{signal_data["type"]}'
|
|
return_string = f"return ({return_type})0;"
|
|
return return_type, return_string
|
|
|
|
def _get_calibration_header_dummy(self):
|
|
"""Get calibration dummy header code."""
|
|
if not self.calibration_variables:
|
|
return ""
|
|
|
|
lines_to_write = []
|
|
swc_name = self.build_cfg.get_composition_config("softwareComponentName")
|
|
for signal_name, signal_data in self.calibration_variables.items():
|
|
return_type = self._get_calibration_function_data(signal_name, signal_data)[0]
|
|
lines_to_write.append(f"{return_type} Rte_CData_{swc_name}_{signal_name}(void);")
|
|
lines_to_write.append("")
|
|
return "\n".join(lines_to_write)
|
|
|
|
def _get_calibration_source_dummy(self):
|
|
"""Get calibration source dummy code."""
|
|
if not self.calibration_variables:
|
|
return ""
|
|
|
|
lines_to_write = []
|
|
swc_name = self.build_cfg.get_composition_config("softwareComponentName")
|
|
for signal_name, signal_data in self.calibration_variables.items():
|
|
return_type, return_string = self._get_calibration_function_data(signal_name, signal_data)
|
|
lines_to_write.append(f"{return_type} Rte_CData_{swc_name}_{signal_name}(void) {{ {return_string} }}")
|
|
lines_to_write.append("")
|
|
return "\n".join(lines_to_write)
|
|
|
|
def generate_rte_dummy(self):
|
|
"""Generate RTE dummy files."""
|
|
src_code_dest_dir = self.build_cfg.get_src_code_dst_dir()
|
|
swc_header_file = Path(src_code_dest_dir, self.swc_header_file_name + ".h")
|
|
type_header_file = Path(src_code_dest_dir, self.type_header_file_name + ".h")
|
|
source_file = Path(src_code_dest_dir, self.source_file_name + ".c")
|
|
with swc_header_file.open(mode="w", encoding="utf-8") as swc_header_fh:
|
|
swc_header_fh.write(self._get_swc_header_content())
|
|
with type_header_file.open(mode="w", encoding="utf-8") as type_header_fh:
|
|
type_header_fh.write(self._get_type_header_header())
|
|
type_header_fh.write(self._get_typedef_dummy())
|
|
type_header_fh.write(self._get_nvm_header_dummy())
|
|
type_header_fh.write(self._get_calibration_header_dummy())
|
|
type_header_fh.write(self._get_type_header_footer())
|
|
with source_file.open(mode="w", encoding="utf-8") as source_fh:
|
|
source_fh.write(self._get_source_header())
|
|
source_fh.write(self._get_nvm_source_dummy())
|
|
source_fh.write(self._get_calibration_source_dummy())
|