# HelloDSP

HelloDSP 是一个简单的MindSpore Signal+平台开发示例，展示如何开发一个矩阵乘程序。主要流程分为两部分操作，分别为{ref}`MindSpore Python端 <python>`和{ref}`MindSpore Lite端 <c++>`。MindSpore Python端在本地运行，用于生成模型；MindSpore Lite端在本地交叉编译，编译产物拷贝到MT7004板卡上运行。以下是HelloDSP矩阵乘例子介绍：

(python)=
## 1.MindSpore Python端

### 1.1 新建Python文件
打开`YHFT-IDE`，新建`test_matmul.py`文件

### 1.2 编写Python代码
```python
import mindspore as ms
import numpy as np
from mindspore import nn, ops


class Matmul(nn.Cell):
    def __init__(self):
        super(Matmul, self).__init__()
        self.matmul = ops.MatMul()

    def construct(self, x1, x2):
        out = self.matmul(x1, x2)
        return out


x1 = np.ones((2, 2), dtype=np.float32)
x2 = np.ones((2, 2), dtype=np.float32)
x1_tensor = ms.Tensor(x1)
x2_tensor = ms.Tensor(x2)

model = Matmul()
out = model(x1_tensor, x2_tensor)
print(out)

ms.export(model, x1_tensor, x2_tensor, file_name="matmul", file_format="MINDIR")
```

以上代码的作用说明如下：

- **导入库**：`mindspore` 用于构建与导出模型；`numpy` 用于生成示例数据；从 `mindspore` 引入 `nn` 与 `ops` 以定义网络与调用算子。
- **定义网络 `Matmul`**：继承 `nn.Cell`，在 `__init__` 中实例化矩阵乘算子 `ops.MatMul()`；在 `construct` 中实现前向计算，将输入 `x1`、`x2` 进行矩阵乘法并返回结果。
- **准备数据**：使用 `numpy.ones` 生成两个形状为 `(2, 2)`、类型为 `float32` 的数组，全为 1。
- **张量转换**：用 `ms.Tensor` 将 `numpy` 数组转换为 MindSpore 张量，作为模型输入。
- **构建与执行模型**：实例化 `Matmul` 模型，传入张量执行前向推理，打印结果。对于两个全 1 的 `2x2` 矩阵，输出为一个元素均为 2 的 `2x2` 张量。
- **导出模型**：调用 `ms.export` 将模型导出为 `MINDIR` 格式：
  - **`file_name`**: 保存的基础文件名为 `matmul`；
  - **`file_format`**: 指定为 `MINDIR`（MindSpore IR 格式），用于后续在 MindSpore Lite 端加载与推理；
  - 传入的输入张量 `x1_tensor` 与 `x2_tensor` 用于固化输入`shape`和`dtype`，确保在部署端可正确构建模型输入。

### 1.3 运行Python代码
在`YHFT-IDE`中运行`test_matmul.py`文件，会生成一个`matmul.mindir`模型文件，要在MindSpore Lite端运行则需要转成 `ms` 模型文件。mindir转ms的converter工具也已经集成到vscode，使用converter工具方式：

选择模型文件直接右键，找到模型转换选项，点击即可。
<img src="../_static/converter_lite.png" alt="create_project" width="auto"/>

(c++)=
## MindSpore Lite端
### 1. 新建工程
打开`YHFT-IDE`，新建工程。输入工程名、路径，工程类型选择`Heterogeneous`，输入交叉编译工具路径，参照{ref}`配置交叉编译工具链 <toolchain>`，然后点确定。会生成一个异构模板工程。

<img src="../_static/create_project.png" alt="create_project" width="auto"/>

### 2. 工程目录结构

生成的异构模板工程具有以下目录结构：

```bash
test_matmul/
├── model/
│   └── matmul.ms
├── arm_toolchain.cmake
├── build.bat
├── CMakeLists.txt
├── data_handler.cc
├── data_handler.h
└── main.cc
```

**文件说明：**

| 文件名 | 类型 | 作用 |
|--------|------|------|
| `model/matmul.ms` | 模型文件 | MindSpore 导出的模型权重和结构文件 |
| `arm_toolchain.cmake` | 配置文件 | 指定 ARM 交叉编译工具链路径和参数 |
| `build.bat` | 脚本文件 | Windows 环境下的编译构建脚本 |
| `CMakeLists.txt` | 构建文件 | CMake 构建系统的主配置文件 |
| `data_handler.h/.cc` | 源码文件 | 数据预处理和结果处理的实现 |
| `main.cc` | 源码文件 | 程序主入口，包含模型加载和推理逻辑 |

### 3. 更改输入数据

通过修改 `data_handler.cc` 文件中的函数来调整输入输出数据：

- **修改输入数据**：编辑 `GetInputData` 函数内容
- **查看输出结果**：编辑 `GetOutputData` 函数内容

**默认配置：**
- 输入数据填充为 1
- 输出结果打印输出地址

<img src="../_static/init_input_data.png" alt="init_input_data" width="auto"/>

### 4. main.cc 功能介绍

`main` 函数主要包含 6 个核心步骤，实现完整的模型推理流程：

#### 4.1 读取模型文件
通过 `ReadFile` 接口读取 `.ms` 模型文件，将数据保存到 `model_buf` 中。

<img src="../_static/read_model.png" alt="read_model" width="auto"/>

#### 4.2 设置运行后端
通过 `context` 的 `MutableDeviceInfo` 添加一个或多个后端：

- **默认后端**：`MT7004`
- **可选后端**：`CPU`、`FT78NE`

<img src="../_static/set_device.png" alt="set_device" width="auto"/>

#### 4.3 编译模型图
通过 MindSpore 的 `Model` 类的 `Build` 方法编译模型图：

**编译规则**：按设置顺序查找后端算子，都没找到则编译失败

**Build 方法参数：**

| 参数 | 类型 | 说明 |
|------|------|------|
| `model_data` | `const void *` | 模型数据 |
| `data_size` | `size_t` | 模型数据大小 |
| `model_type` | `ModeType` | 模型类型 |
| `model_context` | `const std::shared_ptr<Context> &` | 模型上下文（主要传递设备信息） |

<img src="../_static/build_model.png" alt="build_model" width="auto"/>

#### 4.4 获取模型输入
通过 `Model` 类的 `GetInputs` 方法获取所有模型输入的 `Tensor` 地址，通过修改 `GetInputData` 函数传递输入值。

<img src="../_static/get_input.png" alt="get_input" width="auto"/>

#### 4.5 执行模型推理
通过 `Model` 类的 `Predict` 方法进行模型推理：

**Predict 方法参数：**

| 参数 | 类型 | 说明 |
|------|------|------|
| `inputs` | `const std::vector<MSTensor> &` | 模型的输入 |
| `output` | `const std::vector<MSTensor> *` | 模型的输出地址 |

<img src="../_static/model_predict.png" alt="model_predict" width="auto"/>

#### 4.6 获取模型结果
通过 `Model` 类的 `GetOutputs` 方法获取所有模型输出，通过修改 `GetOutputData` 函数查看输出值。

<img src="../_static/get_output.png" alt="get_output" width="auto"/>

### 5. 编译工程

提供多种编译方式，选择其中一种即可：

**编译方式：**
- **方式一**：在 `YHFT-IDE` 集成终端运行 `build.bat` 脚本
- **方式二**：点击调试按钮 → 编译
- **方式三**：直接点击编译图标

<img src="../_static/build_project.png" alt="build_project" width="auto"/>

### 6. 运行工程

编译生成的可执行文件位于 `build` 目录下，默认文件名为 `main`。需要将可执行文件拷贝到 MT7004 板卡上运行。

#### 6.1 连接 MT7004 板卡

**步骤 1：** 打开远程窗口
- 在 `YHFT-IDE` 左下角找到远程窗口功能
- 点击打开远程窗口按钮

<img src="../_static/open_ssh.png" alt="open_ssh" width="auto"/>

**步骤 2：** 选择连接方式
- 在弹出的选项中选择第一个选项进行远程连接

<img src="../_static/connect_mt7004.png" alt="connect_mt7004" width="auto"/>

**步骤 3：** 输入连接信息
- 输入 MT7004 板卡的用户名和 IP 地址
- 按回车键后会弹出新的窗口界面

> **注意**：确保本机和 MT7004 板卡在同一网段，或使用网线直接连接并修改本机 IP 地址与板卡在同一网段

<img src="../_static/ssh.png" alt="ssh" width="auto"/>

**连接成功标志：** 新界面左下角出现 `SSH:xxx` 表示连接成功

<img src="../_static/ssh_success.png" alt="ssh_success" width="auto"/>

#### 6.2 部署和运行程序

**步骤 4：** 部署程序文件
- 在 MT7004 板卡上新建目录存放程序
- 通过拖拽方式将可执行文件和模型文件传输到板卡
- 使用 `chmod` 命令赋予可执行文件执行权限

<img src="../_static/model_run.png" alt="model_run" width="auto"/>