在Armv9架构的DynamIQ设计中,DSU-120T作为共享单元承担着关键的性能监控职能。不同于传统的核心级PMU(Performance Monitoring Unit),DSU-120T实现了集群层级的性能监控能力,这意味着它可以捕捉跨核心的协同操作指标,比如缓存一致性流量、集群总线利用率等系统级指标。
DSU-120T的性能监控寄存器组采用标准的AArch64系统寄存器访问方式,通过MRS/MSR指令进行操作。这些寄存器主要分为三类:
特别值得注意的是,DSU-120T的PMU寄存器在以下两种配置下会变为RAZ/WI(Read-As-Zero/Write-Ignored):
IMP_CLUSTERPMCR_EL1作为控制中枢,其关键字段包括:
典型初始化流程:
assembly复制// 读取当前PMCR配置
mrs x0, S3_0_C15_C5_0
// 设置FZO位(第9位)并启用全局监控(第0位)
orr x0, x0, #(1 << 9) | (1 << 0)
// 写回配置
msr S3_0_C15_C5_0, x0
重要提示:在EL1访问这些寄存器时,需确保ACTLR_EL2.CLUSTERPMUEN和ACTLR_EL3.CLUSTERPMUEN已启用,否则会触发异常。
DSU-120T提供6个32位事件计数器(P0-P5),通过以下寄存器协同管理:
事件配置示例(监控L3缓存访问):
assembly复制// 选择计数器0
mov x0, #0
msr S3_0_C15_C5_5, x0 // PMSELR_EL1
// 设置事件类型(假设0x1A为L3访问事件)
mov x0, #0x1A
msr S3_0_C15_C6_1, x0 // PMXEVTYPER_EL1
// 启用计数器0
mov x0, #(1 << 0)
msr S3_0_C15_C5_1, x0 // PMCNTENSET_EL1
DSU-120T提供完整的溢出管理方案:
高效溢出处理流程:
assembly复制// 配置计数器1溢出中断
mov x0, #(1 << 1)
msr S3_0_C15_C5_6, x0 // PMINTENSET_EL1
// 在中断处理中:
mrs x0, S3_0_C15_C5_3 // 读取PMOVSSET_EL1
tst x0, #(1 << 1)
b.eq no_overflow
// 处理计数器1溢出
mov x1, #(1 << 1)
msr S3_0_C15_C5_4, x1 // 清除溢出标志
DSU-120T支持丰富的集群级事件,部分关键事件包括:
| 事件编码 | 事件名称 | 监控意义 |
|---|---|---|
| 0x01 | BUS_ACCESS | 集群总线访问次数 |
| 0x11 | COHERENT_LINEFILL | 一致性缓存行填充 |
| 0x15 | DVM_MSG_RECEIVED | 接收到的DVM消息数 |
| 0x1A | L3_CACHE_ACCESS | L3缓存访问次数 |
| 0x1F | CLUSTER_CLK_CYCLES | 集群时钟周期数 |
当访问PMU寄存器触发异常时,按以下步骤检查:
assembly复制// 禁用所有计数器
mov x0, #0x3F // 低6位对应P0-P5
msr S3_0_C15_C5_2, x0 // PMCNTENCLR_EL1
// 清除所有溢出标志
msr S3_0_C15_C5_4, x0 // PMOVSCLR_EL1
c复制uint64_t sample_event(uint8_t counter_id) {
static uint32_t accum[6] = {0};
uint32_t current;
asm volatile("msr S3_0_C15_C5_5, %0" :: "r"(counter_id)); // Select counter
asm volatile("mrs %0, S3_0_C15_C6_2" : "=r"(current)); // Read value
if(current < accum[counter_id]) { // Overflow occurred
accum[counter_id] = current + (UINT32_MAX - accum[counter_id]);
} else {
accum[counter_id] = current - accum[counter_id];
}
return accum[counter_id];
}
通过监控DVM消息和一致性操作,评估多核通信效率:
assembly复制// 配置计数器0监控DVM消息
mov x0, #0
msr S3_0_C15_C5_5, x0 // 选择计数器0
mov x0, #0x15 // DVM_MSG_RECEIVED事件
msr S3_0_C15_C6_1, x0
// 配置计数器1监控一致性行填充
mov x0, #1
msr S3_0_C15_C5_5, x1
mov x0, #0x11 // COHERENT_LINEFILL事件
msr S3_0_C15_C6_1, x0
// 同时启用两个计数器
mov x0, #0x3
msr S3_0_C15_C5_1, x0 // PMCNTENSET_EL1
通过时钟周期与指令退休数的比率评估能效:
c复制void measure_energy_efficiency() {
uint64_t cycles, inst_retired;
// 读取集群周期计数器
asm volatile("mrs %0, S3_0_C15_C6_0" : "=r"(cycles));
// 读取核心指令退休计数器(需在每个核心执行)
asm volatile("mrs %0, PMCCNTR_EL0" : "=r"(inst_retired));
double cpi = (double)cycles / inst_retired;
printf("Cycles per instruction: %.2f\n", cpi);
}
在实际产品开发中,我们曾通过这种分析方法发现某款芯片在特定工作负载下CPI异常增高,最终定位到是L3缓存预取策略的问题。通过调整IMP_CLUSTERPMCR_EL1的FZO位,我们成功捕获了缓存失效的精确时间点,为优化提供了关键数据支撑。