Henrik Wahlqvist b42d107422 Bug fixes to rte_dummy.py
Introduced in: 75b3991f5720dcbe78f06def9a85fa55169cab65

* Rte_CData_* functions were never declared.
* Type definitions of Maps should be structs.

Change-Id: Id8d371e6fd0dee7e7accf480a5a09e568db80af4
2025-04-10 10:51:41 +00:00

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())