MSC8251 DPU寄存器深度解析:硬件性能监控与调试实战指南 1. 项目概述深入MSC8251 DPU寄存器世界在嵌入式系统尤其是像飞思卡尔MSC8251这类高性能多核DSP的开发中调试和性能分析从来都不是一件轻松的事。你可能会遇到程序跑飞了却不知道最后一条指令是什么或者系统性能不达标却难以定位是缓存问题、总线瓶颈还是代码执行效率低下。传统的软件打点或仿真器单步调试在复杂的实时系统中往往力不从心要么侵入性太强影响时序要么信息粒度太粗。这时候硬件级别的调试与性能监控单元DPU就成了我们手中的“手术刀”和“显微镜”。MSC8251的DPU模块绝非一个简单的“看门狗”或断点控制器。它是一个高度可配置的硬件性能监控与事件追踪系统其核心是一系列精心设计的寄存器。这些寄存器允许我们以近乎零开销的方式实时捕获处理器内核、缓存、总线乃至整个内存子系统的运行时行为。想象一下你可以精确地知道在某个关键任务执行期间指令缓存ICache发生了多少次未命中数据缓存DCache的预取效率如何或者外部总线被占用了多少周期。这些数据对于优化关键路径代码、调整内存布局、诊断偶发性故障具有不可估量的价值。本文的目的就是带你彻底吃透MSC8251 DPU的这些核心寄存器。我不会仅仅复述数据手册的寄存器位定义表——任何一位工程师都能翻手册查到。我要做的是结合我多年在嵌入式实时系统调试中的实战经验为你解读这些寄存器字段背后真正的设计意图、它们之间的联动关系以及如何将它们组合起来搭建出高效的调试与性能监控方案。我们将从全局控制逻辑入手逐步深入到计数器组、事件选择乃至跟踪缓冲区的配置并分享一些手册上不会写的配置技巧和常见陷阱。无论你是正在为MSC8251平台优化性能的软件工程师还是需要深度定制调试工具链的系统架构师这篇文章都将为你提供一套可直接落地的“寄存器级”操作指南。2. DPU寄存器架构与寻址基础在深入每个寄存器细节之前我们必须先建立起对MSC8251 DPU寄存器整体架构的认知。这就像看地图前先搞清楚东南西北一样重要。DPU的所有功能寄存器都映射到处理器统一的内存地址空间其基地址Base Address固定为0xFFF0A000。这是一个非常重要的信息所有后续对DPU寄存器的读写操作都是基于这个基地址加上各自的偏移量Offset来进行的。从功能上划分DPU的寄存器群可以大致分为四大类它们共同构成了一个完整的事件采集、记录与响应链条全局控制与状态寄存器这是DPU的“大脑”和“仪表盘”。DP_CR控制寄存器负责总开关和路由配置比如决定哪些事件可以产生调试中断DP_SR状态寄存器则实时显示各个计数器和跟踪缓冲区的当前使能状态DP_MR监控寄存器更像一个事件日志记录下是哪个具体部件如Counter A0或跟踪缓冲区触发了最近一次调试请求或中断。理解这三者的关系是灵活运用DPU的基础。任务ID比较器相关寄存器DP_RPID和DP_RDID。这是DPU实现“精准监控”的关键。在多任务或操作系统环境中你可能只关心某个特定任务由唯一的Program ID或Data ID标识的行为。这两个寄存器用于设置你关心的任务ID参考值配合DP_CR中的TIDCM任务ID比较器掩码字段可以过滤掉其他无关任务的干扰事件让计数器只统计你关注的那个任务的数据极大提升了监控的针对性和数据洁净度。计数器组控制与数值寄存器这是DPU的“核心工作单元”。MSC8251的DPU提供了两组三重计数器Triad A和 Triad B每组包含三个计数器如A0, A1, A2以及额外的扩展支持计数器。每组计数器都有对应的控制寄存器如DP_TAC, DP_TBC, DP_CA0C等和数值寄存器如DP_CA0V等。控制寄存器定义了“数什么”事件选择、“何时开始数”使能条件、“何时停止数”禁用条件以及“数到后怎么办”工作模式。数值寄存器则是一个32位的向下计数器你写入初始值它根据选定的事件递减减到0时可能触发事件。跟踪缓冲区Trace Buffer寄存器这是DPU的“黑匣子”。当使能跟踪功能后处理器在执行流满足特定条件时如遇到断点、计数器溢出等会将关键的执行上下文信息如程序计数器、数据地址等实时写入一块称为虚拟跟踪缓冲区VTB的内存区域。DP_TC, DP_TSA, DP_TEA, DP_TER, DP_TW, DP_TD这一系列寄存器就是用来配置和控制这个“黑匣子”的包括设置缓冲区在内存中的起始/结束地址、控制跟踪触发条件、读取跟踪数据等。注意手册中提到的所有寄存器偏移量都是相对于基地址0xFFF0A000的十六进制值。例如DP_CR的偏移是0x00那么它的完整物理地址就是0xFFF0A000。在编写底层驱动或调试脚本时务必使用完整地址进行访问。3. 全局控制与状态寄存器深度解析3.1 DP_CR调试逻辑的总指挥DP_CR寄存器是配置DPU行为的起点它主要管两件事中断路由和任务ID过滤。我们逐位拆解其设计逻辑。位[29:28] TIDCM (Task ID Comparator Mask)这是任务ID比较器的掩码控制位。它的存在解决了监控的“焦点”问题。在复杂软件中内核在不同任务间快速切换。如果你不加以过滤计数器统计的将是所有任务的混合事件数据毫无意义。TIDCM让你可以精确选择参与比较的任务ID类型00不比较。任何任务的事件都会被计数。这通常用于全局性的性能概览。01屏蔽数据任务IDData Task ID只比较程序任务IDProgram Task ID。当你只关心某个特定线程或进程的执行行为时使用。10屏蔽程序任务ID只比较数据任务ID。这可能用于监控特定数据区域如某个共享内存池的访问情况。11两者都参与比较。只有程序ID和数据ID都匹配的事件才会被计数。这是最严格的过滤模式用于监控某个任务对特定数据的操作。位[27:16] ISEDCA[5:0] (Interrupt Selector for EDCA Channels)这6个字段每个占2位分别对应OCEOn-Chip Event模块的6个事件检测与计数阵列EDCA通道。OCE可以检测更底层、更丰富的事件如特定地址范围访问、数据值匹配等。当OCE的某个通道检测到事件后DP_CR中的这个字段决定了该事件将触发哪种调试中断00不产生中断。事件仅用于内部触发例如用于启/停计数器。10产生Debug A中断发送给EPIC外部中断控制器。11产生Debug B中断。这里的设计非常灵活。你可以将不同重要性或不同类型的事件路由到不同的中断向量从而在中断服务程序ISR中快速区分事件来源。例如你可以将致命的错误事件如非法地址访问路由到Debug A而将性能警告事件如缓存未命中率过高路由到Debug B。位[14] EIS (OCE Interrupt Selector)这是一个全局路由开关。当OCE产生一个可屏蔽中断时注意这与上述EDCA通道事件不同此位决定该中断是去Debug A还是Debug B。这为OCE的通用中断提供了一个顶层的路由选择。位[13:12] DETB 与 [11:0] DECA[2:0]/DECB[2:0]这些字段是DPU内部事件跟踪缓冲区事件和各计数器事件的中断使能与路由控制。它们的编码一致00不产生中断。10产生Debug A中断。11产生Debug B中断。例如DECA0位控制着Counter A0溢出时是否产生中断以及产生何种中断。一个关键点这些位只是“使能”和“选路”真正触发中断还需要计数器本身被配置为在溢出时产生事件例如在计数器控制寄存器中设置为One-shot模式。这就构成了一个两级开关第一级是计数器自身的“事件生成能力”第二级是DP_CR中的“事件中断路由”。实操心得在系统初始化时我通常会先规划好中断的用途。例如将Debug A中断关联到一个高优先级的ISR用于紧急错误处理和系统状态保存将Debug B中断关联到一个低优先级的ISR用于性能数据的周期性采集和记录。然后根据这个规划统一配置DP_CR中的各个ISEDCAx、DETB和DECxx字段。避免在调试过程中临时修改导致中断逻辑混乱。3.2 DP_SR与DP_MR状态监控与事件溯源如果说DP_CR是“指挥官”那么DP_SR和DP_MR就是“侦察兵”和“记事本”。DP_SR (Status Register)是一个只读寄存器它实时反映了DPU内部几个关键部件的使能状态。位[6] TWBA (Trace Write Buffer Active)这是一个非常重要的状态位。当你试图停止跟踪通过设置DP_TC[TMPDIS]或清除DP_TC[EN]时跟踪写入缓冲区TWB可能还在忙于将数据刷入主存的VTB区域。直接关闭可能会导致跟踪数据不完整。正确的做法是先发起停止请求然后轮询此位直到TWBA从1变为0表示刷新完成再安全地关闭跟踪逻辑。忽略这个步骤是导致跟踪数据丢失的常见原因。位[5:0] ENCA[2:0] / ENCB[2:0]这6个位分别指示计数器A0/A1/A2和B0/B1/B2的当前状态1为使能0为禁用。这个状态是动态的可能因为MARK/DEBUGEV指令或EDCA事件而改变。通过读取DP_SR你可以确认你的配置是否已生效或者计数器是否已被预期的事件自动关闭。DP_MR (Monitor Register)是一个“粘性”状态寄存器用于记录上一次调试请求或中断是由谁触发的。它的位如DRCA0,DRTB等在相应事件发生时被硬件置1并且只能通过向该位写1来清除写0无效。这是一个非常关键的特性应用场景当Debug A中断发生时你的ISR需要快速知道是谁触发了它。直接读取DP_MR检查DRCA0、DRTB等位就能立即定位到是Counter A0溢出了还是跟踪缓冲区满了。处理完事件后必须向对应的位写1来清除该状态标志否则该位将一直保持为1影响后续事件的判断。位[9] TBF (Trace Buffer Finished)和位[8] DRA (Debug Request Asynchronous)提供了更高级的状态信息。TBF指示跟踪缓冲区是否已写满到最后一项这对于循环缓冲区模式下的数据读取时机判断很重要DRA则指示是否存在外部异步调试请求。避坑指南DP_MR的“写1清除”W1C特性很容易被忽略。常见的错误是在ISR中读取DP_MR判断事件源后忘记清除标志位。导致的结果是即使中断已被处理该标志位依然为1当下次读取DP_MR时你会误以为同一个事件又发生了。务必在ISR末尾根据判断结果执行类似*(volatile uint32_t *) (DPU_BASE 0x08) (1 event_bit);的操作来清除相应位。4. 计数器系统从配置到解读计数器是DPU进行性能剖析的基石。MSC8251提供了两组三重计数器Triad A/B和额外的独立计数器它们共享相似但灵活可配的控制逻辑。4.1 计数器控制寄存器通用模型无论是三重控制寄存器DP_TAC/DP_TBC还是独立计数器控制寄存器DP_CA0C等其位字段设计都遵循一个清晰的逻辑层次我们可以将其归纳为一个“事件驱动状态机”的配置模型使能条件 (Enable Condition)由TENM/CENM和TENMP/CENMP字段控制。它定义了计数器从禁用状态进入计数状态的触发事件。事件源可以是MARK指令在代码中插入MARK指令作为软件触发点。EDCAx事件由OCE模块检测到的硬件事件。直接使能 (1111)上电或配置后立即开始计数。TENMP/CENMP则进一步限定只有符合特定特权级用户/超级用户或通过任务ID比较器过滤后的事件才能触发使能。这实现了基于代码上下文的精确计数触发。禁用条件 (Disable Condition)由TDM/CDM和TDMP/CDMP字段控制。它定义了计数器停止计数并可能触发事件的条件。事件源与使能条件类似包括DEBUGEV指令和EDCAx事件。TDMP/CDMP同样提供特权级过滤。一个典型的用例是用MARK指令开始统计一段函数用DEBUGEV指令结束统计。计数事件源 (Counted Event)由CEG(Triad) 或CE(Independent) 字段选择。这是核心决定了计数器“数什么”。手册中的Table 25-17Counted Event Group是宝藏图。它定义了每个编码对应的具体事件组。例如CEG00000统计ICache行为未命中、命中、预取命中。CEG01100统计Master Bus 1的负载总线周期、指令传输、数据传输。CE00000统计非调试时钟周期。CE00001统计应用周期非等待、非停止、非调试。CEP/CEGP字段再次对事件源进行任务特权级过滤。工作模式 (Counter Mode)由CMODE字段控制。00(One-shot模式)计数器减到0时生成一个事件可能触发中断取决于DP_CR配置然后停止计数并自动禁用。这适用于测量一段特定代码的执行代价比如执行了X个时钟周期后停止。01(Trace模式)计数器减到0时生成事件但继续计数通常从初始值重新加载。同时当跟踪缓冲区需要记录时计数器的当前值会被保存到一个影子寄存器。这适用于与程序执行流跟踪相结合的性能采样。组控使能 (Triad Control Enable - TCEN)仅存在于DP_TAC/DP_TBC。当TCEN1时该三重组内的三个计数器如A0, A1, A2全部受这个三重控制寄存器的统一配置控制它们各自的独立控制寄存器失效。当TCEN0时每个计数器由自己的控制寄存器独立配置。这提供了极大的灵活性你可以将三个计数器作为一个协同的组来监控一组相关事件如同时监控Cache的未命中、命中、预取也可以让它们各自为政监控完全不相关的指标。4.2 计数器数值寄存器与初始化流程每个计数器都有一个对应的32位数值寄存器如DP_CA0V。这是一个可读写的递减计数器。你需要向其中写入一个初始值例如0x0000FFFF表示你要计数65535次事件。当计数器使能后每发生一次所选事件该值减1。当值减到0时根据CMODE模式产生相应行为。一个完整的计数器配置与使用流程如下规划与配置明确监控目标。例如想测量任务Task_X在函数Func_Y执行期间的ICache未命中次数。设置任务ID过滤如果需要将Task_X的程序ID写入DP_RPID并在DP_CR中配置TIDCM为01仅比较程序ID。配置计数器控制寄存器假设使用Counter A0。设置DP_CA0C的CENM0001由MARK指令使能CDM0001由DEBUGEV指令禁用。设置CEP为01仅统计用户任务且通过ID比较器过滤的事件。设置CE00100统计DCache因未命中导致的Thrash次数根据手册此处举例实际需查对应事件编码。设置CMODE00One-shot模式。写入初始值向DP_CA0V写入一个足够大的初始值比如0xFFFFFFFF确保在测量区间内不会溢出除非你希望它溢出触发中断。配置中断如果需要在DP_CR中将DECA0位设置为10或11使Counter A0溢出事件能触发Debug A或B中断。插入仪器化代码在Func_Y的入口处插入MARK指令在出口处插入DEBUGEV指令。执行与读取运行程序。执行完毕后读取DP_CA0V的值。初始值减去当前值即为Func_Y执行期间Task_X造成的DCache未命中Thrash次数。检查状态读取DP_SR确认计数器已禁用读取DP_MR确认事件源并清除标志位。4.3 三重计数器组的协同工作实例让我们看一个利用三重计数器组Triad A进行缓存性能全景分析的实战案例。目标是同时获取一段代码执行时ICache的未命中、命中和预取命中次数。配置DP_TACTCEN 1启用三重组控制。CEG 00000选择“ICache hit-miss”事件组。根据Table 25-17这会将Counter A0自动映射为统计“ICache misses (without prefetch hits)”Counter A1统计“ICache hits”Counter A2统计“ICache prefetch hits”。TENM 0001由MARK指令使能。TDM 0001由DEBUGEV指令禁用。CMODE 00One-shot模式。根据需要配置TENMP,TDMP,CEGP进行任务过滤。初始化计数器值分别向DP_CA0V, DP_CA1V, DP_CA2V写入初始值例如都写入0xFFFFFFF。插入MARK和DEBUGEV指令到目标代码段前后。执行代码并读取结果执行后分别读取三个计数器的值。假设初始值为N读取值为M则事件发生次数为(N - M)。由此你可以一次性得到ICache未命中次数A0ICache命中次数A1ICache预取命中次数A2 进而可以计算命中率、预取效率等关键指标。这种“组配置”方式极大地简化了多指标协同监控的编程复杂度确保了三个计数器在完全同步的起止条件下进行测量数据具有高度可比性。5. 跟踪缓冲区配置与数据采集跟踪缓冲区Trace Buffer是DPU的“飞行记录仪”它能够在程序运行时以极低的开销连续记录程序流、数据访问等关键信息对于复现偶发性bug、分析复杂执行路径至关重要。5.1 跟踪缓冲区寄存器详解跟踪功能由一组寄存器协同控制DP_TC (Trace Control Register)跟踪的总控制寄存器。它包含使能位、跟踪模式选择如循环/停止满、是否允许在调试模式下跟踪等关键控制位。这是开启跟踪功能的开关。DP_TSA (Trace Start Address Register) DP_TEA (Trace End Address Register)这两个寄存器定义了VTB在系统内存中的物理地址范围。VTB是一段由软件分配、DPU硬件负责写入的连续内存区域。DP_TSA是起始地址DP_TEA是结束地址通常是最后一个有效字节的地址。DPU会以类似循环缓冲区的方式向这个区域写入跟踪数据包。DP_TER (Trace Event Request Register)这个寄存器定义了触发跟踪记录的事件。你可以配置当特定计数器溢出、EDCA事件发生、或者遇到特定指令如分支时将当前的处理器上下文如PC值、时间戳等作为一个跟踪数据包写入VTB。这实现了“选择性跟踪”避免产生海量无用数据。DP_TW (Trace Write Pointer Register)这是一个只读寄存器指示DPU下一个要写入VTB的数据包的位置相对于TSA的偏移。软件可以通过轮询此指针来了解有多少新数据可读。DP_TD (Trace Data Register)这是一个只读寄存器用于顺序读取VTB中的数据。通常软件会维护一个自己的读指针当读指针落后于DP_TW时就通过读取DP_TD来获取跟踪数据包。每次读DP_TD硬件可能会自动递增内部索引具体行为需参考手册。5.2 跟踪缓冲区使用流程与避坑指南配置和使用跟踪缓冲区是一个相对复杂的过程以下是一个简化的流程和关键注意事项内存分配在非缓存Non-cacheable或写回Write-back且一致性得到保证的内存区域分配一块足够大的连续物理内存作为VTB。大小取决于你想跟踪的深度通常为几十KB到几MB。地址配置将VTB的起始物理地址写入DP_TSA结束地址写入DP_TEA。事件配置在DP_TER中精心选择触发跟踪的事件。例如你可以设置为当Counter A0溢出即特定事件发生指定次数时记录一条跟踪信息。过于频繁的触发事件会导致VTB迅速被填满。启动跟踪设置DP_TC的使能位启动跟踪。数据采集在程序运行期间或触发停止后软件需要读取跟踪数据。方法一轮询定期读取DP_TW与本地读指针比较。如果不等则通过循环读取DP_TD来获取新数据包直到追平DP_TW。方法二中断驱动配置跟踪缓冲区满或接近满时触发调试中断通过DP_CR的DETB位。在ISR中批量读取数据。避坑指南与实操心得内存属性至关重要VTB所在的内存必须确保DPU作为总线主设备可以正确写入并且软件可以正确读取。通常建议使用非缓存Non-cacheable的内存区域以避免缓存一致性问题导致读不到最新数据。如果使用可缓存内存则必须在读取前执行缓存无效Cache Invalidate操作。缓冲区溢出管理DP_TC可以配置为循环模式缓冲区满后覆盖旧数据或停止模式缓冲区满后停止跟踪。在循环模式下你需要处理数据被覆盖的问题。一种策略是设置一个“水印”中断当DP_TW到达某个位置时触发中断让软件及时取走数据。数据包解析从DP_TD读出的原始数据是高度编码的。你需要根据MSC8251的Nexus或处理器特定的跟踪协议来解析这些数据包才能还原出程序计数器PC、数据地址、时间戳等信息。这通常需要借助厂商提供的跟踪解码库或工具。与计数器联动跟踪功能最强大的用法是与计数器联动。例如配置Counter A0统计“分支指令误预测”次数工作在Trace模式并设置当该计数器溢出即发生N次误预测时触发跟踪记录在DP_TER中配置。这样你不仅能知道误预测发生了多少次还能在它发生时立刻捕获到当时的程序执行上下文精准定位问题代码。6. 常见问题排查与调试技巧实录即使理解了所有寄存器在实际操作中依然会遇到各种问题。下面是我在多年项目中总结的一些典型问题及其排查思路。6.1 问题一配置了计数器但数值始终不变化现象按照手册配置了控制寄存器和初始值插入了MARK/DEBUGEV指令但读取计数器值时发现毫无变化。排查步骤确认计数器使能状态首先读取DP_SR寄存器检查对应的ENCAx或ENCBx位是否为1。如果为0说明计数器从未被使能。问题可能出在MARK指令未正确执行或未到达。检查代码路径确认MARK指令确实被执行了。使能条件CENM/TENM配置错误或特权级过滤CENMP/TENMP条件不满足当前执行上下文。确认事件源如果计数器已使能DP_SR显示为1但不计数问题可能出在事件源选择或过滤上。检查CE/CEG字段确保选择的事件在监控的代码段中确实会发生。例如如果你监控的是DCache未命中但测试代码完全在Tightly Coupled Memory中运行那事件自然不会发生。检查CEP/CEGP特权级过滤和DP_CR中的TIDCM任务ID过滤是否过于严格导致当前执行的任务被排除在外。检查中断屏蔽虽然不影响计数但如果DP_CR中对应的DECAx位被错误地设置为00不产生中断而你又在等待中断发生就会产生“看似没工作”的错觉。计数和中断触发是两个独立的功能。6.2 问题二调试中断触发了但DP_MR中找不到事件源现象系统进入了Debug A/B中断服务程序但读取DP_MR寄存器发现所有事件标志位DRCA0,DRTB等都是0。排查思路中断源非DPU首先确认中断一定是DPU触发的吗EPIC可能收到来自其他外设的调试中断。检查EPIC的中断状态寄存器确认中断向量号确实对应DPU的Debug A/B。DP_MR读取时机或清除问题如果确认是DPU中断那么DP_MR的位一定是被置位过的。有可能在ISR中其他代码先清除了DP_MR标志后读取。确保你的ISR第一件事就是读取并保存DP_MR的值。共享中断线Debug A和Debug B可能各自对应多个潜在事件源。虽然DP_MR指明了具体部件但中断线本身是共享的。确保你的ISR逻辑正确处理了多个事件源同时置位的可能性尽管不常见。6.3 问题三跟踪缓冲区数据读不出来或数据混乱现象使能了跟踪程序也运行了但通过DP_TD读出的数据全是0或者是一些无意义的乱码。排查步骤检查VTB内存配置这是最常见的原因。确保DP_TSA/DP_TEA设置的地址是物理地址并且该内存区域已正确初始化并且其内存属性Cacheability, Shareability允许DPU写入和CPU读取。对于很多SoCDPU作为总线主设备访问内存可能需要特定的属性如Outer Shareable,Non-cacheable。强烈建议将VTB放在一段标记为Non-cacheable的静态内存中。检查跟踪触发条件DP_TER配置是否正确你设置的事件如特定计数器溢出是否真的发生了可以通过先验证计数器功能是否正常来确认。检查DP_TW指针在跟踪使能后程序运行一段时间读取DP_TW。如果它仍然等于0或一个很小的值说明根本没有数据写入。回到步骤1和2。检查数据读取方法DP_TD的读取可能有特定的顺序要求。是每读一次自动指向下一个数据项还是需要软件维护一个索引仔细阅读手册中关于DP_TD操作的描述。确保你的读指针管理逻辑与硬件行为匹配。缓存一致性问题如果你将VTB放在可缓存Cacheable内存中并且CPU侧在读取前没有对数据缓存D-Cache进行无效化Invalidate操作那么你读到的可能是旧的、缓存的脏数据而不是DPU新写入的数据。在读取VTB数据前务必对VTB内存范围执行缓存无效化操作。6.4 性能监控的实践技巧基线测量在优化前先进行一轮“空白”测量。即在不改变任何配置的情况下运行你的目标代码记录下各类计数器如时钟周期、缓存未命中、总线占用的基线值。这样优化后的效果才有对比的依据。聚焦热点不要试图一次性监控所有事件。这会产生大量数据难以分析。根据性能瓶颈的假设是CPU boundMemory boundIO bound有针对性地选择1-3个最关键的事件组进行监控。例如怀疑内存带宽是瓶颈就重点监控总线负载CEG01100或01101和Cache未命中率。利用任务ID过滤在多任务系统中务必使用DP_RPID/DP_RDID和TIDCM功能。这能让你得到纯净的、属于单个任务或进程的性能数据避免其他任务的干扰使分析结果直接明了。组合使用One-shot和Trace模式One-shot模式用于精确测量一段代码的绝对代价。例如测量一个算法循环的执行周期数。Trace模式结合跟踪缓冲区用于进行统计采样。例如设置一个计数器每N个时钟周期溢出一次并触发跟踪记录。通过分析一段时间内采集的大量PC样本你可以绘制出程序的“热点图”找到最耗时的函数。这就是很多性能剖析工具如gprof的硬件辅助版本的工作原理。注意测量开销虽然DPU是硬件模块开销极低但MARK和DEBUGEV是处理器指令它们的执行本身需要时间。在测量非常短小的代码片段时这个开销可能变得显著。对于纳秒级精度的测量需要考虑指令执行时间带来的误差。对于更宏观的性能分析这个开销通常可以忽略。