# QoS调试指南

## 概述
X5芯片采用 NOC（Network on chip） 架构下的 QoS（Quality of Service，服务质量），主要有以下几方面原因：

**SoC发展需求**

随着 SoC 不断发展，片上互联架构逐渐从总线结构演变为复杂的网络拓扑，片上网络（NoC）的概念应运而生。不同的片上核和模块之间需要高效的通信和资源分配，因此需要引入 QoS 机制来保障系统的性能和稳定性。

**解决带宽和延迟分配问题**

在X5芯片内部，众多的模块（如 CPU、VIN、BPU、CODEC、GPU 等）都需要通过NOC进行数据交互，每个模块对带宽和延迟的要求各不相同。例如，视频模块对带宽和实时性要求较高，如果没有 QoS机制来合理分配和管理资源，很可能出现带宽竞争导致数据传输延迟、丢包等问题，影响系统整体性能。采用 QoS 机制能够根据各模块的实际需求，优化带宽和延迟的分配，确保各个模块能够获得与其需求匹配的资源。

**应对数据流量不均衡问题**

不同应用场景下，芯片内各模块的数据流量分布可能极不均衡。例如在高清视频处理场景中，涉及图像采集、编解码、显示等多个模块的数据流量较大，但在一些简单任务场景下，上述模块的流量又相对较小。QoS 机制可以根据实际的数据流量情况进行动态调整，灵活分配资源。在流量高峰时优先保障关键模块的资源需求，在流量低谷时合理地重新分配剩余资源，提高资源利用率，使得整个芯片系统在不同工作场景下都能保持高效和稳定运行。

综上，X5 芯片采用 NOC 架构下的 QoS，是为了适应片上系统的发展、满足多元化服务需求、优化资源的分配利用以及应对复杂多变的数据流量情况，从而提升芯片整体的性能和稳定性，更好地支持各种应用和功能。

## 特点
在 X5 芯片 NOC 中，QoS 呈现出一系列新特性，显著提升了片上网络的服务质量，具体如下：

- 实现了流量的差异化管理，以适应多样化的应用场景需求。
- 支持丰富的模式支持，包括 Fixed 模式、Limiter 模式、Regulator 模式、Bypass 模式。
- 涵盖众多模块，包括 CPU、VIN、BPU、CODEC、GPU、HSIO、HIFI5 等，且每个模块都有对应的 IP，例如 SIF2、SIF3、SIIF_DISP、BPU、VIDEO_CODEC等，都可单独进行 QoS 配置，方便用户针对不同场景进行精细化调整。
- 支持通过 sysfs 下的节点来配置 QoS

**X5 QoS 支持模块及其 IP 如下**

| 模块 | IP |
| :---------- | :------- |
| CPU | cpu_ace / cpu_perif |
| VIN | bt1120 / dc8000 / dw230_gdc / dw230_scalar2 / dw230_scalar3 / isp_axi5_hdr /</br> isp_axi4_mcm / isp_axi3_sp2 / isp_axi1_mp / sif0 / sif1 / sif2 / sif3 / sif_disp |
| BPU | bpu |
| CODEC | video / jpeg |
| GPU | gpu2d / gpu3d |
| HSIO | dma0 / emmc / gmac / sd / sdio / security / usb2 / usb3 / etr |
| HIFI5 | hifi5 |



## 功能描述
### 典型应用
X5 芯片的 QoS 功能在多种场景中发挥重要作用，以下是一些典型应用场景：

- 高分辨率显示场景

例如 2路4K场景，该场景对分辨率要求高，对流程中的模块优先级要求也高，如 HDMI 显示模块，通过调整显示输出 QoS 确保了高分辨率显示所需的优先级和带宽，保证画面的稳定显示

- 多媒体处理场景

在多媒体处理中，涉及多个模块协同工作，不同模块对带宽和优先级需求不同。如视频编解码、图像信号处理（ISP）等模块，通过 QoS 功能合理分配带宽和设置优先级，可保障多媒体处理流畅性，避免出现掉帧、画面闪烁等问题。

- 复杂传感器接入场景

当X5芯片应用于扫地机、割草机、家庭陪伴机器人等设备，需要接入多路复杂传感器时，QoS 功能可对不同传感器数据传输进行优先级和带宽分配。如重要传感器数据可能设置较高优先级，保证数据实时性和准确性；对带宽需求大的传感器，也可分配足够带宽，确保系统稳定运行，使机器人能更好感知环境、进行决策和行动。


### 功能原理
QoS 是发起者和目标之间传输事务关于带宽和延迟的吞吐量和延迟的统计分配，QoS 类似银行 VIP 用户服务，对网络流量分类并赋予不同服务质量，高优先级流量优先转发，低优先级流量尽力服务。

X5 QoS 驱动源码位于 `drivers/soc/hobot/ddr_monitor/horizon_noc_qos.c`，本章节主要介绍 QoS 基本原理以及使用方法，不对驱动代码做赘述。

QoS 支持 Fixed、Limiter、Regulator、Bypass 四种模式，下面分别介绍四种模式及其原理

#### Fixed 模式
**Fixed 模式特性**
- 用于固定分配一个预定义的优先级级别
- 可以分别设置读和写事务的优先级

Fixed 模式下寄存器定义如下:

![image-qos3](_static/_images/40-QOS_Driver_Debug_Guide/fixed_mode.jpg)

#### Limiter 模式
**Limiter 模式特性**
- 在达到预定义的带宽阈值时进行流量控制
- 可以分别设置读和写事务的优先级
- 可设置的寄存器包括: `Bandwidth` `Saturation` 以及 `ExtControl`寄存器
- 当端口的带宽超过 `BW` 时并且超出 `threshold` 字节，该端口会被限流（反压）。其中 `Bandwidth寄存器值 = 256 * BW/F`，`Threshold = Saturation寄存器 ×16`

**参数说明**
- `BW` : 预期的内存带宽限制值
- `threshold`: 从 `BW` 到 QoS 限流之间的门槛值
- `F` : 模块频率，各个模块对应的频率可查看 [QoS寄存器默认配置表格](#QOS_Defult_Register)

Limiter 模式下寄存器定义如下

![image-qos3](_static/_images/40-QOS_Driver_Debug_Guide/limiter_mode.jpg)

#### Regulator 模式
**Regulator 模式特性**
- 用于确保启动器从目标获得所需的带宽
- 不可以分别设置读和写事务的优先级，此时读和写事务的优先级一致
- 可设置的寄存器包括: `Bandwidth` `Saturation` 以及 `ExtControl` 寄存器。
- Regulator 模式会根据带宽调节读写优先级。
  - 当带宽大于预期带宽时，即当端口带宽高于 `BW + threshold`，QoS 将读写优先级调小至 `P0` 优先级
  - 当带宽小于预期带宽时，即当端口带宽低于 `BW - threshold`，QoS 将读写优先级调大至 `P1` 优先级
  - 其中 `Bandwidth寄存器值 = 256 * BW/F`，`Threshold = Saturation寄存器 ×16`

**参数说明**
- `P0` : 读写优先级，高优先级
- `P1` : 读写优先级，低优先级
- `BW` : 预期的内存带宽限制值
- `threshold` : 从 `BW` 到 QoS 调节之间的门槛值
- `F` : 模块频率，各个模块对应的频率可查看 [QoS寄存器默认配置表格](#QOS_Defult_Register)

Regulator 模式下寄存器定义如下

![image-qos3](_static/_images/40-QOS_Driver_Debug_Guide/regulator_mode.jpg)

#### Bypass 模式
Bypass 模式则比较复杂，主要由 `Socket qos signals` 和 `Qos box` 决定 `Priority` 寄存器的值，

- `Socket qos signals` 指的是 QoS 内部调节的值（ `AxQOS` 和 `Hurry` 两者取其最大），其中
  - `AxQos` : 为 IP 本身所调节出的值
  - `Hurry` : `Hurry` 信号只有 SIF 支持的信号，其可以提高长时间未收到响应的挂起事务的处理优先级。而 SIF Hurry 信号是由相关 FIFO 中的 almost-full 信号驱动的
- `Qos box` 指的是上文中 `priority` 寄存器值。

主要包含以下几种情况
- 当 SocketQosEn 寄存器值为 0，且当前不是 Bypass 模式，则通过 `priority` 寄存器设置优先级
- 当 SocketQosEn 寄存器值为 0，且当前是 Bypass 模式，由 `Socket qos signals` 设置优先级
- 当 SocketQosEn 寄存器值为 1，则取 `Socket qos signals` 和 `Qos box` 中的最大值作为优先级

优先级的值如下表规则所示

![image-qos3](_static/_images/40-QOS_Driver_Debug_Guide/Bypass_mode.jpg)



<span id="QOS_Defult_Register"/> </span>

## QoS寄存器默认配置
### Bandwidth、BW、F寄存器值
![image-qos9](_static/_images/40-QOS_Driver_Debug_Guide/X1.jpg)

![image-qos9](_static/_images/40-QOS_Driver_Debug_Guide/X2.jpg)

### Mode、P1、P0寄存器
![image-qos9](_static/_images/40-QOS_Driver_Debug_Guide/X3.jpg)

![image-qos9](_static/_images/40-QOS_Driver_Debug_Guide/X4.jpg)


#### 注意事项
- X5 芯片通常使用 Fixed 模式，如果想调整为Limiter、Regulator以及Bypass模式，细节见[复杂模式配置章节](#QOS_Advanced_Mode)
- 各个模式 Priority 寄存器定义不一样
  - Fixed 和 Limiter 模式:  P0 代表 write 优先级，P1 代表 read 优先级
  - Mode 和 Regulator 模式: P0 代表低优先级，P1 代表高优先级

- write\P0 优先级 和 read\P1 优先级定义如下
  - write\P0 优先级由 Priority 寄存器 bit[0:2]决定，范围[0-7]
  - read\P1 优先级由 Priority 寄存器 bit[8:10]决定，范围[0-7]
  - **数值越大，优先级越高**

![image-qos3](_static/_images/40-QOS_Driver_Debug_Guide/zongjie.jpg)





## 使用方法

X5 芯片 QoS 支持通过 sysfs 方式配置，用户无需关注复杂寄存器配置，可直接通过 sysfs 节点操作。其操作模式又分为常见模式和复杂模式，以下将分别介绍其使用方法

### 常见模式
X5 系统默认使用常见模式，即 Fixed 模式，当通过 sysfs 配置优先级时，QoS 将自动配置为 Fixed 模式。

#### 读写 Priority 寄存器
QoS 模块所在目录为 `/sys/bus/platform/drivers/noc_qos`，该目录包含 X5 系统支持配置 QoS 的所有模块，每个模块均以子目录形式存在

![image-qos8](_static/_images/40-QOS_Driver_Debug_Guide/image-qos8.png)


对于 Fixed 模式，可以配置每个模块下的 read priority 和 write priority，分别位于每个模块目录的 `read_priority_qos_ctrl/priority` 和 `write_priority_qos_ctrl/priority` 节点。

**以 sif0 qos 为例，读取和配置读写优先级**
```shell
cd /sys/bus/platform/drivers/noc_qos    # 进入 qos 目录

cd 20510500.sif0_qos                    # 进入 sif0 qos 子目录

cat read_priority_qos_ctrl/priority     # 读取 read priority
# read_priority : 7                     # 显示当前 read priority 值为 7

echo 5 > read_priority_qos_ctrl/priority     # 设置 read priority 值为 5


cat write_priority_qos_ctrl/priority     # 读取 write priority
# write_priority : 7                     # 显示当前 write priority 值为 7

echo 5 > write_priority_qos_ctrl/priority     # 设置 write priority 值为 5
```

<span id="QOS_Advanced_Mode"/> </span>

### 复杂模式

#### 配置复杂模式
X5 QoS 默认为常见模式，每次配置优先级时，驱动都会自动配置为 Fixed 模式，如果需要进入复杂模式，需要先关闭自动配置。X5 QoS 通过每个模块目录下的 `mode_qos_ctrl/advanced` 节点开启/关闭自动配置。

**以 sif0 qos 为例**

查看当前是否自动配置 Fixed 模式
```shell
cd /sys/bus/platform/drivers/noc_qos/20510500.sif0_qos

cat mode_qos_ctrl/advanced
qos_advanced : 0              # 0 表示当前自动设置 mode 为 Fixed 模式
```
关闭自动配置 Fixed 模式
```
echo 1 > mode_qos_ctrl/advanced

cat mode_qos_ctrl/advanced
qos_advanced : 1
```

#### 配置优先级
在复杂模式下，每个模块子目录，可配置的寄存器目录主要是
- `mode_qos_ctrl` 目录: 包含 `advanced`  `bandwidth`  `extcontrol`  `mode`  `saturation` 寄存器
- `read_priority_qos_ctrl` 目录: 包含 `priority`，对应 read / P1 优先级
- `write_priority_qos_ctrl` 目录: 包含 `priority`，对应 write / P0 优先级

**注意: 配置值需转换为十进制**

**以 cpu_ace_qos 为例**

设置 Limiter 模式，BW 为 1GB/s， threshold 为 2MB， 其中 F = 1.2GHZ (模块频率，各个模块对应的频率可查看 [QoS寄存器默认配置表格](#QOS_Defult_Register)
)。
Bandwidth 寄存器值为0xD5，则 Saturation 寄存器值为 0x80。

![image-qos9](_static/_images/40-QOS_Driver_Debug_Guide/complex_3.jpg)


### QoS 各模块参数展示脚本
X5 提供了脚本 `qos_show.sh` 方便用户快速查看各个模块的读写优先级。

脚本参数如下:
  - 默认不带参数: 只显示 `write priority` 和 `read priority` 参数信息
  - `-a`: 同时显示 `advanced` `mode` `bandwidth` `saturation` `extcontrol` 参数信息

**注意: 该脚本并不在板端固件集成，用户可拷贝至板端任意路径下执行**

脚本代码如下:

```shell
#!/bin/bash

# cd /sys/bus/platform/drivers/noc_qos
cd /sys/bus/platform/drivers/noc_qos || exit

for dir in */; do
    if [[ $dir == *qos* ]]; then
            cd "$dir" || continue
    fi
    echo "$dir: "

    val=$(cat write_priority_qos_ctrl/priority | awk '{print $NF}')
    printf "\t\t\t%-18s%-10s\n" "write priority:" $val

    val=$(cat read_priority_qos_ctrl/priority | awk '{print $NF}')
    printf "\t\t\t%-18s%-10s\n" "read priority:" $val

    if [ "$1" != "-a" ]; then
        cd ..
        continue
    fi

    val=$(cat mode_qos_ctrl/mode | awk '{print $NF}')
    printf "\t\t\t%-18s%-10s\n" "mode val:" $val

    val=$(cat mode_qos_ctrl/advanced | awk '{print $NF}')
    printf "\t\t\t%-18s%-10s\n" "advanced val:" $val

    val=$(cat mode_qos_ctrl/bandwidth | awk '{print $NF}')
    num=$((val))
    printf "\t\t\t%-18s%s%-10x\n" "bandwidth val:" "0x" $((val))

    val=$(cat mode_qos_ctrl/saturation | awk '{print $NF}')
    num=$((val))
    printf "\t\t\t%-18s%s%-10x\n" "saturation val:" "0x" $((val))

    val=$(cat mode_qos_ctrl/extcontrol | awk '{print $NF}')
    printf "\t\t\t%-18s%-10s\n" "extcontrol val:" $val

    cd ..

done

```
#### 默认不带参数，仅显示读写优先级
![image-qos9](_static/_images/40-QOS_Driver_Debug_Guide/shell1.jpg)

#### 带 -a 参数，显示所有寄存器值
![image-qos9](_static/_images/40-QOS_Driver_Debug_Guide/shell.jpg)
