112e714ceSopenharmony_ci# Neural Network Runtime设备接入指导
212e714ceSopenharmony_ci
312e714ceSopenharmony_ci## 概述
412e714ceSopenharmony_ci
512e714ceSopenharmony_ci### 功能简介
612e714ceSopenharmony_ci
712e714ceSopenharmony_ciNNRt(Neural Network Runtime,神经网络运行时)是面向AI领域的跨芯片推理计算运行时,作为中间桥梁连通上层AI推理框架和底层加速芯片,实现AI模型的跨芯片推理计算。
812e714ceSopenharmony_ci
912e714ceSopenharmony_ciNNRt开放了设备接口,芯片厂商通过设备接口将专有加速芯片接入NNRt,从而实现与OpenHarmony社区生态的对接。以下内容将介绍芯片如何接入NNRt。
1012e714ceSopenharmony_ci
1112e714ceSopenharmony_ci### 基本概念
1212e714ceSopenharmony_ci在开发前,开发者需要先了解以下概念,以便更好地理解全文内容:
1312e714ceSopenharmony_ci
1412e714ceSopenharmony_ci- HDI(Hardware Device Interface):OpenHarmony硬件设备接口,定义系统中跨进程通信的接口,实现服务间的跨进程通信。
1512e714ceSopenharmony_ci- IDL(Interface Description Language):接口描述语言,是HDI接口的语言格式。
1612e714ceSopenharmony_ci
1712e714ceSopenharmony_ci### 约束与限制
1812e714ceSopenharmony_ci- 系统版本:OpenHarmony主干版本。
1912e714ceSopenharmony_ci- 开发环境:Ubuntu 18.04及以上。
2012e714ceSopenharmony_ci- 接入设备:具备AI计算能力的芯片。
2112e714ceSopenharmony_ci
2212e714ceSopenharmony_ci### 运作机制
2312e714ceSopenharmony_ciNNRt通过HDI接口实现与设备芯片的对接,由HDI接口实现跨进程通信。
2412e714ceSopenharmony_ci
2512e714ceSopenharmony_ci**图1** NNRt架构图
2612e714ceSopenharmony_ci
2712e714ceSopenharmony_ci![架构图](../../figures/arch_diagram.png)
2812e714ceSopenharmony_ci
2912e714ceSopenharmony_ci整个架构主要分为三层,AI应用在应用层,AI推理框架和NNRt在系统层,设备服务在芯片层。AI应用如果要使用AI专用加速芯片进行模型推理,需要经过AI推理框架和NNRt才能调用到底层AI专用加速芯片,NNRt就是负责适配底层各种AI专用加速芯片的中间层。NNRt开放了标准统一的HDI设备接口,众多AI专用加速芯片都可以通过HDI接口接入OpenHarmony。此外NNRt也开放了标准统一的接口对接上层各种AI推理框架。
3012e714ceSopenharmony_ci
3112e714ceSopenharmony_ci程序运行时,AI应用、AI推理框架、NNRt都运行在用户进程中,底层AI芯片设备服务运行在HDI服务进程中。NNRt根据HDI接口实现了HDI Client,服务端也需要根据HDI接口实现HDI Service,两者通过OpenHarmony标准的HDF子系统实现跨进程通信。
3212e714ceSopenharmony_ci
3312e714ceSopenharmony_ci## 开发指导
3412e714ceSopenharmony_ci
3512e714ceSopenharmony_ci### 场景介绍
3612e714ceSopenharmony_ci当需要将一款AI加速芯片接入NNRt的时候,可以参考下文。下文以RK3568芯片为例,展示RK3568 CPU如何通过NNRt的V2.0版本HDI接口接入NNRt,并完成AI模型推理。V1.0版本HDI接口接入NNRt的流程与此类似。
3712e714ceSopenharmony_ci> 依赖说明:该教程展示的RK3568 CPU接入NNRt并没有真正实现CPU的驱动,而是借用了MindSpore Lite的runtime和CPU算子,因此会依赖MindSpore Lite的动态库以及头文件。实际开发时并不需要依赖MindSpore Lite的任何库或者头文件。
3812e714ceSopenharmony_ci
3912e714ceSopenharmony_ci### 开发流程
4012e714ceSopenharmony_ciAI专用加速芯片接入NNRt的整体流程如下:
4112e714ceSopenharmony_ci
4212e714ceSopenharmony_ci**图2** AI专用加速芯片接入NNRt流程
4312e714ceSopenharmony_ci
4412e714ceSopenharmony_ci![开发流程](../../figures/dev_flow.png)
4512e714ceSopenharmony_ci
4612e714ceSopenharmony_ci### 开发步骤
4712e714ceSopenharmony_ciAI芯片设备HDI服务开发者具体可通过以下步骤实现AI专用加速芯片对接NNRt:
4812e714ceSopenharmony_ci#### 生成HDI头文件
4912e714ceSopenharmony_ci开源社区下载OpenHarmony的代码,编译drivers_interface部件,生成HDI接口的头文件。
5012e714ceSopenharmony_ci
5112e714ceSopenharmony_ci1. [下载源码](../get-code/sourcecode-acquire.md)。
5212e714ceSopenharmony_ci
5312e714ceSopenharmony_ci2. 进入OpenHarmony源码根目录,编译NNRt的IDL接口文件(以RK3568产品为例):
5412e714ceSopenharmony_ci    ```shell
5512e714ceSopenharmony_ci    ./build.sh --product-name rk3568 –ccache --build-target drivers_interface_nnrt
5612e714ceSopenharmony_ci    ```
5712e714ceSopenharmony_ci
5812e714ceSopenharmony_ci    编译完成后,会在```out/rk3568/gen/drivers/interface/nnrt/v2_0```目录下生成C++类型的HDI头文件。若需要生成C类型的头文件,请在编译之前使用如下命令对```drivers/interface/nnrt/v2_0/BUILD.gn```文件中的```language```配置项进行设置。
5912e714ceSopenharmony_ci
6012e714ceSopenharmony_ci    ```shell
6112e714ceSopenharmony_ci    language = "c"
6212e714ceSopenharmony_ci    ```
6312e714ceSopenharmony_ci
6412e714ceSopenharmony_ci    生成头文件目录如下所示:
6512e714ceSopenharmony_ci    ```text
6612e714ceSopenharmony_ci    out/rk3568/gen/drivers/interface/nnrt
6712e714ceSopenharmony_ci    └── v2_0
6812e714ceSopenharmony_ci        ├── drivers_interface_nnrt__libnnrt_proxy_2.0_external_deps_temp.json
6912e714ceSopenharmony_ci        ├── drivers_interface_nnrt__libnnrt_stub_2.0_external_deps_temp.json
7012e714ceSopenharmony_ci        ├── innrt_device.h                        # 设备接口头文件
7112e714ceSopenharmony_ci        ├── iprepared_model.h                     # 编译AI模型对象头文件
7212e714ceSopenharmony_ci        ├── libnnrt_proxy_2.0__notice.d
7312e714ceSopenharmony_ci        ├── libnnrt_stub_2.0__notice.d
7412e714ceSopenharmony_ci        ├── model_types.cpp                       # AI模型结构定义实现文件
7512e714ceSopenharmony_ci        ├── model_types.h                         # AI模型结构定义头文件
7612e714ceSopenharmony_ci        ├── nnrt_device_driver.cpp                # 设备驱动实现参考样例
7712e714ceSopenharmony_ci        ├── nnrt_device_proxy.cpp
7812e714ceSopenharmony_ci        ├── nnrt_device_proxy.h
7912e714ceSopenharmony_ci        ├── nnrt_device_service.cpp               # 设备服务端实现参考样例
8012e714ceSopenharmony_ci        ├── nnrt_device_service.h                 # 设备服务端头文件
8112e714ceSopenharmony_ci        ├── nnrt_device_stub.cpp
8212e714ceSopenharmony_ci        ├── nnrt_device_stub.h
8312e714ceSopenharmony_ci        ├── nnrt_types.cpp                        # 数据类型定义实现文件
8412e714ceSopenharmony_ci        ├── nnrt_types.h                          # 数据类型定义头文件
8512e714ceSopenharmony_ci        ├── node_attr_types.cpp                   # AI模型算子属性定义实现文件
8612e714ceSopenharmony_ci        ├── node_attr_types.h                     # AI模型算子属性定义
8712e714ceSopenharmony_ci        ├── prepared_model_proxy.cpp
8812e714ceSopenharmony_ci        ├── prepared_model_proxy.h
8912e714ceSopenharmony_ci        ├── prepared_model_service.cpp            # 编译AI模型对象服务端实现参考样例
9012e714ceSopenharmony_ci        ├── prepared_model_service.h              # 编译AI模型对象服务端头文件
9112e714ceSopenharmony_ci        ├── prepared_model_stub.cpp
9212e714ceSopenharmony_ci        └── prepared_model_stub.h
9312e714ceSopenharmony_ci    ```
9412e714ceSopenharmony_ci
9512e714ceSopenharmony_ci#### 实现HDI服务
9612e714ceSopenharmony_ci
9712e714ceSopenharmony_ci1. 进入OpenHarmony源码根目录,在```drivers/peripheral```目录下新建开发目录```nnrt```,用于HDI服务开发。开发目录结构如下所示:
9812e714ceSopenharmony_ci    ```text
9912e714ceSopenharmony_ci    drivers/peripheral/nnrt
10012e714ceSopenharmony_ci    ├── bundle.json
10112e714ceSopenharmony_ci    ├── v2_0
10212e714ceSopenharmony_ci        ├── BUILD.gn                                  # 代码编译脚本文件
10312e714ceSopenharmony_ci        └── hdi_cpu_service                           # 自定义目录
10412e714ceSopenharmony_ci            ├── BUILD.gn                              # 代码编译脚本文件
10512e714ceSopenharmony_ci            ├── include
10612e714ceSopenharmony_ci            │   ├── nnrt_device_service.h             # 设备服务端头文件
10712e714ceSopenharmony_ci            │   ├── node_functions.h                  # 非必须,由具体实现决定
10812e714ceSopenharmony_ci            │   ├── node_registry.h                   # 非必须,由具体实现决定
10912e714ceSopenharmony_ci            │   └── prepared_model_service.h          # 编译AI模型对象服务端头文件
11012e714ceSopenharmony_ci            └── src
11112e714ceSopenharmony_ci                ├── nnrt_device_driver.cpp            # 设备驱动实现文件
11212e714ceSopenharmony_ci                ├── nnrt_device_service.cpp           # 设备服务端实现文件
11312e714ceSopenharmony_ci                ├── nnrt_device_stub.cpp              # 非必须,由具体实现决定
11412e714ceSopenharmony_ci                ├── node_attr_types.cpp               # 非必须,由具体实现决定
11512e714ceSopenharmony_ci                ├── node_functions.cpp                # 非必须,由具体实现决定
11612e714ceSopenharmony_ci                ├── node_registry.cpp                 # 非必须,由具体实现决定
11712e714ceSopenharmony_ci                └── prepared_model_service.cpp        # 编译AI模型对象服务端实现文件
11812e714ceSopenharmony_ci    ```
11912e714ceSopenharmony_ci
12012e714ceSopenharmony_ci2. 实现设备驱动,无特殊需求可直接使用IDL文件编译生成的```nnrt_device_driver.cpp```文件,否则根据具体驱动开发。
12112e714ceSopenharmony_ci
12212e714ceSopenharmony_ci3. 实现服务接口,可参考```nnrt_device_service.cpp```和```prepared_model_service.cpp```实现文件,接口定义可以参考[NNRt的HDI接口定义](https://gitee.com/openharmony/drivers_interface/tree/master/nnrt)。
12312e714ceSopenharmony_ci
12412e714ceSopenharmony_ci4. 编译驱动和服务的实现文件为共享库。
12512e714ceSopenharmony_ci
12612e714ceSopenharmony_ci    在```drivers/peripheral/nnrt/v2_0/hdi_cpu_service/```下新建```BUILD.gn```文件,文件内容如下所示,相关参数配置内容可参考[Build教程](https://gitee.com/openharmony/build)。
12712e714ceSopenharmony_ci
12812e714ceSopenharmony_ci    ```shell
12912e714ceSopenharmony_ci    import("//build/ohos.gni")
13012e714ceSopenharmony_ci    import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni")
13112e714ceSopenharmony_ci
13212e714ceSopenharmony_ci    ohos_shared_library("libnnrt_service_2.0") {
13312e714ceSopenharmony_ci      include_dirs = []
13412e714ceSopenharmony_ci      sources = [
13512e714ceSopenharmony_ci        "src/nnrt_device_service.cpp",
13612e714ceSopenharmony_ci        "src/node_functions.cpp",
13712e714ceSopenharmony_ci        "src/node_registry.cpp",
13812e714ceSopenharmony_ci        "src/prepared_model_service.cpp",
13912e714ceSopenharmony_ci        "src/shared_buffer_parser.cpp",
14012e714ceSopenharmony_ci        "src/validation.cpp",
14112e714ceSopenharmony_ci      ]
14212e714ceSopenharmony_ci
14312e714ceSopenharmony_ci      external_deps = [
14412e714ceSopenharmony_ci        "c_utils:utils",
14512e714ceSopenharmony_ci        "drivers_interface_nnrt:libnnrt_stub_2.0",
14612e714ceSopenharmony_ci        "hdf_core:libhdf_utils",
14712e714ceSopenharmony_ci        "hilog_native:libhilog",
14812e714ceSopenharmony_ci        "ipc:ipc_core",
14912e714ceSopenharmony_ci      ]
15012e714ceSopenharmony_ci
15112e714ceSopenharmony_ci      install_images = [ chipset_base_dir ]
15212e714ceSopenharmony_ci      subsystem_name = "hdf"
15312e714ceSopenharmony_ci      part_name = "drivers_peripheral_nnrt"
15412e714ceSopenharmony_ci    }
15512e714ceSopenharmony_ci
15612e714ceSopenharmony_ci    ohos_shared_library("libnnrt_driver") {
15712e714ceSopenharmony_ci      include_dirs = []
15812e714ceSopenharmony_ci      sources = [ "src/nnr_device_driver.cpp" ]
15912e714ceSopenharmony_ci      deps = [ ":libnnrt_service_2.0" ]
16012e714ceSopenharmony_ci
16112e714ceSopenharmony_ci      external_deps = [
16212e714ceSopenharmony_ci        "c_utils:utils",
16312e714ceSopenharmony_ci        "drivers_interface_nnrt:libnnrt_stub_2.0",
16412e714ceSopenharmony_ci        "hdf_core:libhdf_host",
16512e714ceSopenharmony_ci        "hdf_core:libhdf_ipc_adapter",
16612e714ceSopenharmony_ci        "hdf_core:libhdf_utils",
16712e714ceSopenharmony_ci        "hdf_core:libhdi",
16812e714ceSopenharmony_ci        "hilog_native:libhilog",
16912e714ceSopenharmony_ci        "ipc:ipc_core",
17012e714ceSopenharmony_ci      ]
17112e714ceSopenharmony_ci
17212e714ceSopenharmony_ci      install_images = [ chipset_base_dir ]
17312e714ceSopenharmony_ci      subsystem_name = "hdf"
17412e714ceSopenharmony_ci      part_name = "drivers_peripheral_nnrt"
17512e714ceSopenharmony_ci    }
17612e714ceSopenharmony_ci
17712e714ceSopenharmony_ci    group("hdf_nnrt_service") {
17812e714ceSopenharmony_ci      deps = [
17912e714ceSopenharmony_ci        ":libnnrt_driver",
18012e714ceSopenharmony_ci        ":libnnrt_service_2.0",
18112e714ceSopenharmony_ci      ]
18212e714ceSopenharmony_ci    }
18312e714ceSopenharmony_ci    ```
18412e714ceSopenharmony_ci
18512e714ceSopenharmony_ci    将```group("hdf_nnrt_service")```添加到```drivers/peripheral/nnrt/v2_0/BUILD.gn```文件中,以便在更上目录层级就能引用。
18612e714ceSopenharmony_ci    ```shell
18712e714ceSopenharmony_ci    if (defined(ohos_lite)) {
18812e714ceSopenharmony_ci      group("nnrt_entry") {
18912e714ceSopenharmony_ci        deps = []
19012e714ceSopenharmony_ci      }
19112e714ceSopenharmony_ci    } else {
19212e714ceSopenharmony_ci      group("nnrt_entry") {
19312e714ceSopenharmony_ci        deps = [ "./hdi_cpu_service:hdf_nnrt_service" ]
19412e714ceSopenharmony_ci      }
19512e714ceSopenharmony_ci    }
19612e714ceSopenharmony_ci    ```
19712e714ceSopenharmony_ci
19812e714ceSopenharmony_ci    新建```drivers/peripheral/nnrt/bundle.json```用于定义新增的```drivers_peripheral_nnrt```部件。
19912e714ceSopenharmony_ci    ```json
20012e714ceSopenharmony_ci    {
20112e714ceSopenharmony_ci      "name": "drivers_peripheral_nnrt",
20212e714ceSopenharmony_ci      "description": "Neural network runtime device driver",
20312e714ceSopenharmony_ci      "version": "4.0",
20412e714ceSopenharmony_ci      "license": "Apache License 2.0",
20512e714ceSopenharmony_ci      "component": {
20612e714ceSopenharmony_ci        "name": "drivers_peripheral_nnrt",
20712e714ceSopenharmony_ci        "subsystem": "hdf",
20812e714ceSopenharmony_ci        "syscap": [""],
20912e714ceSopenharmony_ci        "adapter_system_type": ["standard"],
21012e714ceSopenharmony_ci        "rom": "1024KB",
21112e714ceSopenharmony_ci        "ram": "2048KB",
21212e714ceSopenharmony_ci        "deps": {
21312e714ceSopenharmony_ci          "components": [
21412e714ceSopenharmony_ci            "c_utils",
21512e714ceSopenharmony_ci            "hdf_core",
21612e714ceSopenharmony_ci            "hilog",
21712e714ceSopenharmony_ci            "ipc",
21812e714ceSopenharmony_ci            "drivers_interface_nnrt"
21912e714ceSopenharmony_ci          ],
22012e714ceSopenharmony_ci          "third_part": [
22112e714ceSopenharmony_ci            "bounds_checking_function"
22212e714ceSopenharmony_ci          ]
22312e714ceSopenharmony_ci        },
22412e714ceSopenharmony_ci        "build": {
22512e714ceSopenharmony_ci          "sub_component": [
22612e714ceSopenharmony_ci            "//drivers/peripheral/nnrt/v2_0:nnrt_entry"
22712e714ceSopenharmony_ci          ],
22812e714ceSopenharmony_ci          "test": [
22912e714ceSopenharmony_ci          ],
23012e714ceSopenharmony_ci          "inner_kits": [
23112e714ceSopenharmony_ci          ]
23212e714ceSopenharmony_ci        }
23312e714ceSopenharmony_ci      }
23412e714ceSopenharmony_ci    }
23512e714ceSopenharmony_ci    ```
23612e714ceSopenharmony_ci
23712e714ceSopenharmony_ci#### 声明HDI服务
23812e714ceSopenharmony_ci
23912e714ceSopenharmony_ci  在对应产品的uhdf hcs配置文件中声明NNRt的用户态驱动与服务。例如针对RK3568,服务需要在```vendor/hihope/rk3568/hdf_config/uhdf/device_info.hcs```文件中新增如下配置:
24012e714ceSopenharmony_ci  ```text
24112e714ceSopenharmony_ci  nnrt :: host {
24212e714ceSopenharmony_ci      hostName = "nnrt_host";
24312e714ceSopenharmony_ci      priority = 50;
24412e714ceSopenharmony_ci      uid = "";
24512e714ceSopenharmony_ci      gid = "";
24612e714ceSopenharmony_ci      caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"];
24712e714ceSopenharmony_ci      nnrt_device :: device {
24812e714ceSopenharmony_ci          device0 :: deviceNode {
24912e714ceSopenharmony_ci              policy = 2;
25012e714ceSopenharmony_ci              priority = 100;
25112e714ceSopenharmony_ci              moduleName = "libnnrt_driver.z.so";
25212e714ceSopenharmony_ci              serviceName = "nnrt_device_service";
25312e714ceSopenharmony_ci          }
25412e714ceSopenharmony_ci      }
25512e714ceSopenharmony_ci  }
25612e714ceSopenharmony_ci  ```
25712e714ceSopenharmony_ci> 注意:修改hcs文件需要删除out目录重新编译,才能生效。
25812e714ceSopenharmony_ci
25912e714ceSopenharmony_ci#### 配置host进程用户ID和组ID
26012e714ceSopenharmony_ci  对于新增的nnrt_host进程的场景,需要配置对应进程的用户ID和组ID。 进程的用户ID在文件```base/startup/init/services/etc/passwd```中配置,进程的组ID在文件```base/startup/init/services/etc/group```中配置。 
26112e714ceSopenharmony_ci  ```text
26212e714ceSopenharmony_ci  # 在base/startup/init/services/etc/passwd新增
26312e714ceSopenharmony_ci  nnrt_host:x:3311:3311:::/bin/false
26412e714ceSopenharmony_ci
26512e714ceSopenharmony_ci  # 在base/startup/init/services/etc/group新增
26612e714ceSopenharmony_ci  nnrt_host:x:3311:
26712e714ceSopenharmony_ci  ```
26812e714ceSopenharmony_ci
26912e714ceSopenharmony_ci#### 配置SELinux
27012e714ceSopenharmony_ci
27112e714ceSopenharmony_ciOpenHarmony已经开启SELinux特性,需要对新增的进程和服务配置相应的SELinux规则,用于运行host进程访问某些资源、发布HDI服务等。
27212e714ceSopenharmony_ci
27312e714ceSopenharmony_ci1. 在```base/security/selinux/sepolicy/ohos_policy/drivers/adapter/public/hdf_service_contexts```文件中新增配置:
27412e714ceSopenharmony_ci    ```text
27512e714ceSopenharmony_ci    # 新增配置
27612e714ceSopenharmony_ci    nnrt_device_service        u:object_r:hdf_nnrt_device_service:s0 
27712e714ceSopenharmony_ci    ```
27812e714ceSopenharmony_ci    > ```nnrt_host```为[声明HDI服务](#声明hdi服务)步骤中配置的进程名称,下同。
27912e714ceSopenharmony_ci
28012e714ceSopenharmony_ci2. 在```base/security/selinux/sepolicy/ohos_policy/drivers/adapter/public/hdf_service.te```文件中新增配置:
28112e714ceSopenharmony_ci    ```text
28212e714ceSopenharmony_ci    # 新增配置
28312e714ceSopenharmony_ci    type hdf_nnrt_device_service, hdf_service_attr; 
28412e714ceSopenharmony_ci    ```
28512e714ceSopenharmony_ci
28612e714ceSopenharmony_ci3. 在```base/security/selinux/sepolicy/ohos_policy/drivers/adapter/public/hdfdomain.te```文件中新增配置:
28712e714ceSopenharmony_ci    ```text
28812e714ceSopenharmony_ci    # 新增配置
28912e714ceSopenharmony_ci    neverallow { domain -hdfdomain -sadomain } { hdfdomain -nnrt_host -allocator_host -hdf_public_domain }:binder call; 
29012e714ceSopenharmony_ci    ```
29112e714ceSopenharmony_ci
29212e714ceSopenharmony_ci4. 在```base/security/selinux/sepolicy/ohos_policy/drivers/adapter/public/type.te```文件中新增配置:
29312e714ceSopenharmony_ci    ```text
29412e714ceSopenharmony_ci    # 新增配置
29512e714ceSopenharmony_ci    type nnrt_host, hdfdomain, domain;
29612e714ceSopenharmony_ci    ```
29712e714ceSopenharmony_ci
29812e714ceSopenharmony_ci5. 在```base/security/selinux/sepolicy/ohos_policy/drivers/adapter/vendor/hdf_devmgr.te```文件中新增配置:
29912e714ceSopenharmony_ci    ```text
30012e714ceSopenharmony_ci    # 新增配置
30112e714ceSopenharmony_ci    allow hdf_devmgr nnrt_host:binder { call transfer };
30212e714ceSopenharmony_ci    allow hdf_devmgr nnrt_host:dir { search };
30312e714ceSopenharmony_ci    allow hdf_devmgr nnrt_host:file { open read write };
30412e714ceSopenharmony_ci    allow hdf_devmgr nnrt_host:process { getattr };
30512e714ceSopenharmony_ci    ```
30612e714ceSopenharmony_ci
30712e714ceSopenharmony_ci6. 在```base/security/selinux/sepolicy/ohos_policy/drivers/adapter/vendor/init.te```文件中新增配置:
30812e714ceSopenharmony_ci    ```text
30912e714ceSopenharmony_ci    # 新增配置
31012e714ceSopenharmony_ci    allow init nnrt_host:process { rlimitinh siginh transition };
31112e714ceSopenharmony_ci    ```
31212e714ceSopenharmony_ci
31312e714ceSopenharmony_ci7. 在```base/security/selinux/sepolicy/ohos_policy/startup/init/public/chipset_init.te```文件中作如下修改:
31412e714ceSopenharmony_ci
31512e714ceSopenharmony_ci    找到chipset_init这一行:
31612e714ceSopenharmony_ci    ```text
31712e714ceSopenharmony_ci    allow chipset_init { light_host input_user_host wifi_host camera_host power_host audio_host }:process { rlimitinh siginh transition };
31812e714ceSopenharmony_ci    ```
31912e714ceSopenharmony_ci    在host列表中增加nnrt_host:
32012e714ceSopenharmony_ci    ```text
32112e714ceSopenharmony_ci    allow chipset_init { light_host input_user_host wifi_host camera_host power_host audio_host nnrt_host }:process { rlimitinh siginh transition };
32212e714ceSopenharmony_ci    ```
32312e714ceSopenharmony_ci
32412e714ceSopenharmony_ci8. 新建```nnrt_host.te```配置文件:
32512e714ceSopenharmony_ci    ```shell
32612e714ceSopenharmony_ci    # 创建nnrt文件夹
32712e714ceSopenharmony_ci    mkdir base/security/selinux/sepolicy/ohos_policy/drivers/peripheral/nnrt
32812e714ceSopenharmony_ci
32912e714ceSopenharmony_ci    # 创建vendor文件夹
33012e714ceSopenharmony_ci    mkdir base/security/selinux/sepolicy/ohos_policy/drivers/peripheral/nnrt/vendor
33112e714ceSopenharmony_ci
33212e714ceSopenharmony_ci    # 创建nnrt_host.te文件
33312e714ceSopenharmony_ci    touch base/security/selinux/sepolicy/ohos_policy/drivers/peripheral/nnrt/vendor/nnrt_host.te
33412e714ceSopenharmony_ci    ```
33512e714ceSopenharmony_ci
33612e714ceSopenharmony_ci9. 将所需的权限写入```nnrt_host.te```文件中:
33712e714ceSopenharmony_ci    ```text
33812e714ceSopenharmony_ci    allow nnrt_host dev_hdf_kevent:chr_file { ioctl };
33912e714ceSopenharmony_ci    allow nnrt_host hilog_param:file { read open map };
34012e714ceSopenharmony_ci    allow nnrt_host sh:binder { transfer };
34112e714ceSopenharmony_ci    allow nnrt_host samgr:binder { call };
34212e714ceSopenharmony_ci    allow nnrt_host dev_ashmem_file:chr_file { open };
34312e714ceSopenharmony_ci    allow nnrt_host dev_unix_socket:dir { search };
34412e714ceSopenharmony_ci    allow nnrt_host hdf_device_manager:hdf_devmgr_class { get };
34512e714ceSopenharmony_ci    allow nnrt_host hdf_nnrt_device_service:hdf_devmgr_class { add get };
34612e714ceSopenharmony_ci    allow nnrt_host dev_console_file:chr_file { read write };
34712e714ceSopenharmony_ci    allow nnrt_host debug_param:file { read open map };
34812e714ceSopenharmony_ci    allow nnrt_host sa_device_service_manager:samgr_class { get };
34912e714ceSopenharmony_ci    allow nnrt_host hdf_devmgr:binder { call transfer };
35012e714ceSopenharmony_ci    allow nnrt_host hdf_nnrt_device_service:binder { call };
35112e714ceSopenharmony_ci    allow nnrt_host sysfs_devices_system_cpu:file { read open getattr };
35212e714ceSopenharmony_ci    allow sh hdf_nnrt_device_service:hdf_devmgr_class { add get };
35312e714ceSopenharmony_ci    allow sh hdf_hci_interface_service:hdf_devmgr_class { get };
35412e714ceSopenharmony_ci    allow sh nnrt_host:dir { getattr search };
35512e714ceSopenharmony_ci    allow sh nnrt_host:file { open read };
35612e714ceSopenharmony_ci    allow sh nnrt_host:process { getattr };
35712e714ceSopenharmony_ci    allow sh nnrt_host:binder { call };
35812e714ceSopenharmony_ci    allow sh nnrt_host:fd { use };
35912e714ceSopenharmony_ci    ```
36012e714ceSopenharmony_ci
36112e714ceSopenharmony_ci10. 由于SELinux是白名单访问的权限机制,需要根据实际权限需求配置。将服务启动之后,可通过以下dmesg命令查看avc告警,
36212e714ceSopenharmony_ciavc告警会给出缺少的权限。SELinux的配置也可以参考[OpenHarmony SELinux子系统的说明](https://gitee.com/openharmony/security_selinux/blob/master/README.md)。
36312e714ceSopenharmony_ci    ```shell
36412e714ceSopenharmony_ci    hdc_std shell
36512e714ceSopenharmony_ci    dmesg | grep nnrt
36612e714ceSopenharmony_ci    ```
36712e714ceSopenharmony_ci
36812e714ceSopenharmony_ci#### 配置部件编译入口
36912e714ceSopenharmony_ci以RK3568产品为例:
37012e714ceSopenharmony_ci```shell
37112e714ceSopenharmony_civim //productdefine/common/inherit/chipset_common.json
37212e714ceSopenharmony_ci```
37312e714ceSopenharmony_ci在```"subsystems"```, ```"subsystem":"hdf"```, ```"components"```中添加:
37412e714ceSopenharmony_ci```shell
37512e714ceSopenharmony_ci{
37612e714ceSopenharmony_ci  "component": "drivers_peripheral_nnrt",
37712e714ceSopenharmony_ci  "features": []
37812e714ceSopenharmony_ci}
37912e714ceSopenharmony_ci```
38012e714ceSopenharmony_ci
38112e714ceSopenharmony_ci#### 删除out目录并编译整个系统
38212e714ceSopenharmony_ci```shell
38312e714ceSopenharmony_ci# 删除out目录
38412e714ceSopenharmony_cirm -rf ./out
38512e714ceSopenharmony_ci
38612e714ceSopenharmony_ci# 编译
38712e714ceSopenharmony_ci./build.sh --product-name rk3568 –ccache --jobs=4
38812e714ceSopenharmony_ci```
38912e714ceSopenharmony_ci
39012e714ceSopenharmony_ci
39112e714ceSopenharmony_ci### 调测验证
39212e714ceSopenharmony_ci服务开发完成后,可以使用XTS用例验证基本功能和兼容性。开发者可通过以下步骤进行验证:
39312e714ceSopenharmony_ci
39412e714ceSopenharmony_ci1. 编译NNRt的hats用例,用例在```test/xts/hats/ai/nnrt/hdi```目录下。
39512e714ceSopenharmony_ci    ```shell
39612e714ceSopenharmony_ci    # 进入hats目录
39712e714ceSopenharmony_ci    cd test/xts/hats
39812e714ceSopenharmony_ci
39912e714ceSopenharmony_ci    # 编译hats测试用例
40012e714ceSopenharmony_ci    ./build.sh suite=hats system_size=standard product_name=rk3568
40112e714ceSopenharmony_ci
40212e714ceSopenharmony_ci    # 回到代码根目录
40312e714ceSopenharmony_ci    cd -
40412e714ceSopenharmony_ci    ```
40512e714ceSopenharmony_ci    编译好的测试用例可执行文件```HatsHdfNnrtFunctionTest```会输出到```out/rk3568/suites/hats/testcases/```下。
40612e714ceSopenharmony_ci
40712e714ceSopenharmony_ci2. 将测试用例push到RK3568设备的```/data/local/tmp/```目录下。
40812e714ceSopenharmony_ci    ```shell
40912e714ceSopenharmony_ci    # 将测试用例可执行文件推送到设备上,HatsHdfNnrtFunctionTest是测试用例可执行文件。
41012e714ceSopenharmony_ci    hdc_std file send out/rk3568/suites/hats/testcases/HartsHdfNnrtFunctionTest /data/local/tmp/
41112e714ceSopenharmony_ci
41212e714ceSopenharmony_ci    # 给测试用例可执行文件加上权限。
41312e714ceSopenharmony_ci    hdc_std shell "chmod +x /data/local/tmp/HatsHdfNnrtFunctionTest"
41412e714ceSopenharmony_ci    ```
41512e714ceSopenharmony_ci
41612e714ceSopenharmony_ci3. 执行用例并查看结果。
41712e714ceSopenharmony_ci    ```shell
41812e714ceSopenharmony_ci    # 执行测试用例
41912e714ceSopenharmony_ci    hdc_std shell "/data/local/tmp/HatsHdfNnrtFunctionTest"
42012e714ceSopenharmony_ci    ```
42112e714ceSopenharmony_ci
42212e714ceSopenharmony_ci    测试报告显示已通过47个用例,说明所有hats用例已执行成功,服务已通过兼容性测试。
42312e714ceSopenharmony_ci    ```text
42412e714ceSopenharmony_ci    ...
42512e714ceSopenharmony_ci    [----------] Global test environment tear-down
42612e714ceSopenharmony_ci    Gtest xml output finished
42712e714ceSopenharmony_ci    [==========] 47 tests from 3 test suites ran. (515 ms total)
42812e714ceSopenharmony_ci    [  PASSED  ] 47 tests.
42912e714ceSopenharmony_ci    ```
43012e714ceSopenharmony_ci
43112e714ceSopenharmony_ci### 开发实例
43212e714ceSopenharmony_ci完整Demo代码可以参考[社区实现](https://gitee.com/openharmony/ai_neural_network_runtime/tree/master/example/drivers)。
43312e714ceSopenharmony_ci
43412e714ceSopenharmony_ci1. 进入OpenHarmony源码根目录,在```drivers/peripheral```路径下创建```nnrt```目录,拷贝NNRt源码路径```foundation/ai/neural_network_runtime```下的```example/driver/nnrt/v2_0```目录到```drivers/peripheral/nnrt```路径下。
43512e714ceSopenharmony_ci    ```shell
43612e714ceSopenharmony_ci    cp -r example/drivers/nnrt/v2_0 drivers/peripheral/nnrt
43712e714ceSopenharmony_ci    ```
43812e714ceSopenharmony_ci
43912e714ceSopenharmony_ci2. 在```drivers/peripheral/nnrt```下补充```bundle.json```文件,```bundle.json```的写法参考本教程上面[开发步骤](#开发步骤)中的[实现HDI服务](#实现hdi服务)章节。
44012e714ceSopenharmony_ci
44112e714ceSopenharmony_ci3. 由于Demo依赖MindSpore Lite CPU算子,因此需要添加MindSpore Lite依赖文件:
44212e714ceSopenharmony_ci    - 在```drivers/peripheral/nnrt/v2_0```下创建```mindspore```目录,用于存放mindspore动态库和头文件。
44312e714ceSopenharmony_ci      ```shell
44412e714ceSopenharmony_ci      mkdir drivers/peripheral/nnrt/v2_0/mindspore
44512e714ceSopenharmony_ci      ```
44612e714ceSopenharmony_ci    - 将所需的头文件拷贝到```drivers/peripheral/nnrt/v2_0/mindspore```目录下。
44712e714ceSopenharmony_ci      ```shell
44812e714ceSopenharmony_ci      cp -r third_party/mindspore/mindspore-src/source/include drivers/peripheral/nnrt/v2_0/mindspore
44912e714ceSopenharmony_ci      cp -r third_party/mindspore/mindspore-src/source/mindspore/core/mindapi drivers/peripheral/nnrt/v2_0/mindspore/include/
45012e714ceSopenharmony_ci      ```
45112e714ceSopenharmony_ci    - Demo还依赖mindspore的```schema```文件:
45212e714ceSopenharmony_ci      ```shell
45312e714ceSopenharmony_ci      # 创建mindspore_schema目录
45412e714ceSopenharmony_ci      mkdir drivers/peripheral/nnrt/v2_0/hdi_cpu_service/include/mindspore_schema
45512e714ceSopenharmony_ci
45612e714ceSopenharmony_ci      # 从third_party目录拷贝mindspore schema文件
45712e714ceSopenharmony_ci      cp third_party/mindspore/mindspore/lite/schema/* drivers/peripheral/nnrt/v2_0/hdi_cpu_service/include/mindspore_schema/
45812e714ceSopenharmony_ci      ```
45912e714ceSopenharmony_ci    - 编译OpenHarmony的MindSpore Lite动态库,并将动态库拷贝到```mindspore```目录下。
46012e714ceSopenharmony_ci      ```shell
46112e714ceSopenharmony_ci      # 编译mindspore动态库
46212e714ceSopenharmony_ci      ./build.sh --product-name rk3568 -ccaache --jobs 4 --build-target mindspore_lib
46312e714ceSopenharmony_ci
46412e714ceSopenharmony_ci      # 在drivers/peripheral/nnrt/v2_0/mindspore下创建mindspore目录
46512e714ceSopenharmony_ci      mkdir drivers/peripheral/nnrt/v2_0/mindspore/mindspore
46612e714ceSopenharmony_ci
46712e714ceSopenharmony_ci      # 从out目录将mindspore动态库拷贝到drivers/peripheral/nnrt/v2_0/mindspore/mindspore46812e714ceSopenharmony_ci      cp out/rk3568/package/phone/system/lib/libmindspore-lite.so drivers/peripheral/nnrt/v2_0/mindspore/mindspore/
46912e714ceSopenharmony_ci      ```
47012e714ceSopenharmony_ci4. 其他配置请参考本教程上面的[开发步骤](#开发步骤)章节。