File size: 11,282 Bytes
747451d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | # /*---------------------------------------------------------------------------------------------
# * Copyright (c) 2022 STMicroelectronics.
# * All rights reserved.
# *
# * This software is licensed under terms that can be found in the LICENSE file in
# * the root directory of this software component.
# * If no LICENSE file comes with this software, it is provided AS-IS.
# *--------------------------------------------------------------------------------------------*/
import os
import sys
import warnings
import shutil
from hydra.core.hydra_config import HydraConfig
from omegaconf import DictConfig
from typing import Optional
warnings.filterwarnings("ignore")
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
from common.utils import get_model_name_and_its_input_shape, get_model_name
from common.deployment import stm32ai_deploy_stm32n6, stm32ai_deploy_mpu, stm32ai_deploy
from common.benchmarking import cloud_connect
from object_detection.tf.src.utils import gen_h_user_file_n6, gen_h_user_file_h7,gen_h_user_file_n6_onnx_yolod, gen_h_user_file_n6_onnx_ssd
anchors_str = "\t\t<link>\n\t\t\t<name>Application/STM32H747I-DISCO/Src/CM7/anchors.c</name>\n\t\t\t<type>1</type>\n\t\t\t<locationURI>PARENT-3-PROJECT_LOC/STM32H747I-DISCO/Src/CM7/anchors.c</locationURI>\n\t\t</link>\n"
network_str = "\t\t<link>\n\t\t\t<name>Application/Network/network.c</name>\n\t\t\t<type>1</type>\n\t\t\t<locationURI>PARENT-3-PROJECT_LOC/Network/Src/network.c</locationURI>\n\t\t</link>\n"
def _add_anchors_to_project(output_dir, c_project_path):
# Copy anchors.h
shutil.copyfile(os.path.join(output_dir, os.path.join("C_header", "anchors.h")), c_project_path + '/Application/STM32H747I-DISCO/Inc/CM7/anchors.h')
def _remove_anchors_from_project(c_project_path):
# Remove anchors.h
if os.path.exists(c_project_path + '/Application/STM32H747I-DISCO/Inc/CM7/anchors.h'):
os.remove(c_project_path + '/Application/STM32H747I-DISCO/Inc/CM7/anchors.h')
def deploy(cfg: DictConfig = None, model_path_to_deploy: Optional[str] = None) -> None:
"""
Deploy the AI model to a target device.
Args:
cfg (DictConfig): The configuration dictionary. Defaults to None.
model_path_to_deploy (str, optional): Model path to deploy. Defaults to None
Returns:
None
"""
# Build and flash Getting Started
board = cfg.deployment.hardware_setup.board
stlink_serial_number = cfg.deployment.hardware_setup.stlink_serial_number
c_project_path = cfg.deployment.c_project_path
output_dir = HydraConfig.get().runtime.output_dir
stm32ai_output = os.path.join(output_dir, "generated")
stedgeai_core_version = cfg.tools.stedgeai.version
optimization = cfg.tools.stedgeai.optimization
path_to_stm32ai = cfg.tools.stedgeai.path_to_stm32ai
path_to_cube_ide = cfg.tools.path_to_cubeIDE
verbosity = cfg.deployment.verbosity
stm32ai_ide = cfg.deployment.IDE
stm32ai_serie = cfg.deployment.hardware_setup.serie
# Get model name for STEdgeAI STATS
if model_path_to_deploy:
model_path = model_path_to_deploy
else:
model_path = cfg.model.model_path
model_name, input_shape = get_model_name_and_its_input_shape(model_path=model_path)
# Get model name
get_model_name_output = get_model_name(model_type=str(model_name),
input_shape=str(input_shape[0]),
project_name=cfg.general.project_name)
# Generate ai_model_config.h for C embedded application
print("[INFO] : Generating C header file for Getting Started...")
if stm32ai_serie.upper() == "STM32H7":
tpp, quantized_model_path = gen_h_user_file_h7(config=cfg, quantized_model_path=model_path)
else:
if cfg.model.model_type == "ssd":
tpp, quantized_model_path = gen_h_user_file_n6_onnx_ssd(config=cfg, quantized_model_path=model_path)
elif cfg.model.model_type == "st_yolod":
tpp, quantized_model_path = gen_h_user_file_n6_onnx_yolod(config=cfg, quantized_model_path=model_path)
else:
tpp, quantized_model_path = gen_h_user_file_n6(config=cfg, quantized_model_path=model_path)
if tpp:
model_path = quantized_model_path
# Anchors gestion
if os.path.isfile(os.path.join(output_dir, os.path.join("C_header", "anchors.h"))):
_add_anchors_to_project(output_dir, c_project_path)
else:
_remove_anchors_from_project(c_project_path)
# gen_h_user_file(config=cfg, quantized_model_path=model_path, board=board)
if stm32ai_serie.upper() == "STM32H7" and stm32ai_ide.lower() == "gcc":
if board == "STM32H747I-DISCO":
stmaic_conf_filename = "stmaic_STM32H747I-DISCO.conf"
else:
raise TypeError("The hardware selected in cfg.deployment.stm32ai.target is not supported yet!")
# Run the deployment
stm32ai_deploy(target=board, stlink_serial_number=stlink_serial_number, stedgeai_core_version=stedgeai_core_version, c_project_path=c_project_path,
output_dir=output_dir,
stm32ai_output=stm32ai_output, optimization=optimization, path_to_stm32ai=path_to_stm32ai,
path_to_cube_ide=path_to_cube_ide, stmaic_conf_filename=stmaic_conf_filename,
verbosity=verbosity,
debug=False, model_path=model_path, get_model_name_output=get_model_name_output,
stm32ai_ide=stm32ai_ide, stm32ai_serie=stm32ai_serie, on_cloud=cfg.tools.stedgeai.on_cloud,
check_large_model=True, cfg=cfg)
elif stm32ai_serie.upper() == "STM32N6" and stm32ai_ide.lower() == "gcc":
if board == "STM32N6570-DK":
stmaic_conf_filename = "stmaic_STM32N6570-DK.conf"
elif board == "NUCLEO-N657X0-Q":
stmaic_conf_filename = "stmaic_NUCLEO-N657X0-Q.conf"
else:
raise TypeError("The hardware selected in cfg.deployment.hardware_setup.board is not supported yet!\n"
"Please choose one of the following boards : `STM32N6570-DK` or `NUCLEO-N657X0-Q`.")
if cfg.model.model_type == 'st_ssd_mobilenet_v1' or cfg.model.model_type == 'ssd_mobilenet_v2_fpnlite':
model_output_type = ''
else:
model_output_type = 'int8'
additional_files = [
os.path.join(output_dir, "stai_network.c"),
os.path.join(output_dir, "stai_network.h"),
os.path.join(output_dir, "network_atonbuf.xSPI2.raw")
]
stm32ai_deploy_stm32n6(target=board,
stlink_serial_number=stlink_serial_number,
stedgeai_core_version=stedgeai_core_version,
c_project_path=c_project_path,
output_dir=output_dir,
stm32ai_output=stm32ai_output,
optimization=optimization,
path_to_stm32ai=path_to_stm32ai,
path_to_cube_ide=path_to_cube_ide,
stmaic_conf_filename=stmaic_conf_filename,
verbosity=verbosity,
debug=False,
model_path=model_path,
get_model_name_output=get_model_name_output,
stm32ai_ide=stm32ai_ide,
stm32ai_serie=stm32ai_serie,
on_cloud=cfg.tools.stedgeai.on_cloud,
build_conf = cfg.deployment.hardware_setup.output,
check_large_model=True,
cfg=cfg,
input_data_type='uint8',
output_data_type=model_output_type,
inputs_ch_position='chlast',
outputs_ch_position='',
additional_files=additional_files)
else:
raise TypeError("Options for cfg.deployment.hardware_setup.serie and cfg.deployment.IDE not supported yet!")
def deploy_mpu(cfg: DictConfig = None, model_path_to_deploy: Optional[str] = None,
credentials: list[str] = None) -> None:
"""
Deploy the AI model to a MPU target device.
Args:
cfg (DictConfig): The configuration dictionary. Defaults to None.
model_path_to_deploy (str, optional): Model path to deploy. Defaults to None
credentials list[str]: User credentials used before to connect.
Returns:
None
"""
# Build and flash Getting Started
board = cfg.deployment.hardware_setup.board
c_project_path = cfg.deployment.c_project_path
class_names = cfg.dataset.class_names
board_deploy_path = cfg.deployment.board_deploy_path
verbosity = cfg.deployment.verbosity
board_serie = cfg.deployment.hardware_setup.serie
board_ip = cfg.deployment.hardware_setup.ip_address
optimized_model_path = c_project_path + "Optimized_models/"
# Get model name for STEdgeAI STATS
model_path = model_path_to_deploy if model_path_to_deploy else cfg.model.model_path
model_extension = os.path.splitext(model_path)[1]
model_name, input_shape = get_model_name_and_its_input_shape(model_path=model_path)
if board_serie == "STM32MP2" and (model_extension == ".tflite" or model_extension == ".onnx") and cfg.tools.stedgeai.on_cloud:
# Connect to STEdgeAI Developer Cloud
login_success, ai, _ = cloud_connect(stedgeai_core_version=None, credentials=credentials)
if login_success:
try:
ai.upload_model(model_path)
model = model_name + model_extension
res = ai.generate_nbg(model)
ai.download_model(res, optimized_model_path + res)
model_path=os.path.join(optimized_model_path,res)
model_name = model_name + ".nb"
rename_model_path=os.path.join(optimized_model_path,model_name)
os.rename(model_path, rename_model_path)
model_path = rename_model_path
print("[INFO] : Optimized Model Name:", model_name)
print("[INFO] : Optimization done ! Model available at :",optimized_model_path)
except Exception as e:
print(f"[FAIL] : Model optimization via Cloud failed : {e}.")
print("[INFO] : Use default model instead of optimized ...")
if board in ["STM32MP257F-EV1","STM32MP157F-DK2","STM32MP135F-DK"]:
# Run the deployment
res = stm32ai_deploy_mpu(target=board, board_ip_address=board_ip, class_names=class_names, board_deploy=board_deploy_path, c_project_path=c_project_path,
verbosity=verbosity, debug=False, model_path=model_path,cfg=cfg)
if res == False:
raise TypeError("Deployment on the target failed\n")
else:
raise TypeError("Options for cfg.deployment.hardware_setup.board and not supported !\n"
"Only valid options are STM32MP257F-EV1,STM32MP157F-DK2,STM32MP135F-DK \n") |