# AXI-Monitor 调试指南
## 概述

AXI-Monitor 是基于 AMBA AXI (Advanced eXtensible Interface) 总线协议的性能检测模块，主要用于监测系统总线上各模块读写 DDR 的带宽，为系统优化提供依据。

![AXI-Monitor 框架 ](_static/_images/41-AXI-monitor_Driver_Debug_Guide/AXI_performance_monitor.png)

- NOC:(Network-on-Chip) 将多个处理单元（如 CPU、 GPU、 DDR 控制器等）通过一个高速、低延迟的网络互连，实现并行通信。
  - `DDR NOC`：分别与 `CPU NOC`、`BPU NOC`、`GPU NOC`、`VIN NOC`、`Codec NOC` 连接， 实现各个模块读写 DDR。
  - `VIN NOC`： 连接了多个模块，包括 Camera 子系统和 Display 子系统。
  - `GPU NOC`： 连接了多个模块，包括 2DGPU 和 3DGPU。
  - `Codec NOC` ： 连接了多个模块，包括 VPU 和 JPU。
- DDR 中包含如下模块：
  - `AXI-Monitor`：监听各个 NOC 端口的 DDR 读写带宽， 针对每个端口的带宽进行独立监控，不会对端口访问 DDR 的操作产生影响。
  - `MPU`：(Memory Protection Unit) 用于保护系统的内存区域，并提供不同访问权限控制。
  - `DDR Controller`：是负责与 DDR 内存进行通信的核心模块。它的主要功能是管理内存的访问、读写操作、时序控制和内存的初始化等。
  - `DDR PHY`：是 DDR 控制器与物理内存之间的接口，负责将数字信号（来自 DDR Controller）转换为适合在物理传输层（例如电气信号）上传输的信号。

### 典型应用
- 场景 1 ：系统带宽优化
  - 场景描述：在多模块并行运行时，某些模块的帧率未达预期，需确认是否因 DDR 带宽瓶颈所致。
  - 解决办法： AXI-Monitor 通过实时监控各模块以及整个系统对 DDR 的带宽占用情况，从而针对性的优化。

- 场景 2 ：系统模块运行检测
  - 场景描述：应用程序完成开发后，需要长时间监控程序是否运行正常。
  - 解决办法： 通过 AXI-Monitor 获取各个模块对 DDR 带宽的占用，推测某个模块是否出现异常带宽暴增或读写停止。

### 功能原理
AXI-Monitor 硬件模块用于监测 AXI 总线的性能，其内部集成了 时间计数器 和 事件计数器，协同工作以统计数据传输情况。
- 时间计数器 （ Time Counter）
  - 主要功能：统计测量窗口的总时长，并控制事件计数器的启停。
  - 工作机制：
  	- 通过软件启动 / 停止 时间计数器时，所有已使能的事件计数器会同步开始 / 停止工作。
  	- 时间计数器启动后会持续运行，直到发生溢出或被软件停止。
- 事件计数器 （ Event Counter）
   - 主要功能：为每个 AXI 端口 分别统计 读写传输事件，记录 读 / 写 DDR 数据量。
   - 统计粒度：
     - Read 事件计数：统计 AXI 总线的读数据传输量。
     - Write 事件计数：统计 AXI 总线的写数据传输量。

时间计数器与事件计数器协同工作，可测量一段时间内的 数据传输总量。

## 功能使用

### 参数说明
登录设备后执行 `hrut_ddr -h`:
```sh
root@buildroot:~# hrut_ddr -h
DDR MONITOR HELP INFORMATION
>>> -t/--type   sample type: cpu,bpu,vin,codec,gpu,sum,all
>>> -p/--period sample period: [1-1000] ms
>>> -r/--raw    print raw data
```

运行参数解释：
1. -t 表示指定端口， 支持 cpu、 bpu、 vin、 codec、 gpu、 sum、 all。
2. -p 表示采样周期，不设置时，取默认值 10ms，范围为 [1,1000]ms。
3. -r 表示输出原始数据。

### 日志说明
1. 运行一个可以把各个模块跑起来的程序，比如 `sunrise_camera` ，参考 [sunrise_camera](../../samples/sunrise_camera_user_guide.html)。
2. 执行 `hrut_ddr` 查看各个模块的带宽占用情况：
	```shell
	root@buildroot:~# hrut_ddr -t all -p 1000
	port_type:ALL
	DDR type is
	Set sample period:1000ms, 1 samples per seconds

	Time 6690.524s
	MB/S   P0:CPU   P1:BPU  P2:VIN  P3:CODEC  P4:GPU      SUM
	Read :   1724     1533     1482      956      165     5860
	Write:    829     1553     1712      359      116     4569

	Time 6691.524s
	MB/S   P0:CPU   P1:BPU  P2:VIN  P3:CODEC  P4:GPU      SUM
	Read :   1722     1536     1442     1005      174     5879
	Write:    833     1560     1681      377      125     4576

	Time 6692.524s
	MB/S   P0:CPU   P1:BPU  P2:VIN  P3:CODEC  P4:GPU      SUM
	Read :   1744     1548     1436      971      163     5862
	Write:    845     1568     1673      364      113     4563

	```
3. 日志解释
   程序间隔 1s 打印一次带宽占用数据，如下描述：
   - `Time 6690.524s`: 读取 DDR 带宽占用数据的时间点。
   - `MB/S`: 下面输出的带宽数据的单位。
   - `Read/Write`: 分别展示了各个模块以及所有模块的 读写 DDR 的带宽占用。
     - P0 到 P4 列：分别展示了 `CPU`、`BPU`、`VIN`、`CODEC`、`GPU` 模块的 DDR 读写带宽占用。
     - SUM 列：展示了当前所有模块的 DDR 读写带宽占用。

## 常见问题
1. 在多个模块并行运行时，由于某些模块帧率波动导致 `hrut_ddr` 工具检测到 DDR 带宽占用，忽高忽低
   - 问题分析：`hrut_ddr` 工具的原理是计算 -p 参数（采样窗口）指定的时间段内的平均内存带宽占用
   - 解决办法：可以适当调节 -p 参数（采样窗口）得到更稳定的带宽数据