APP下载

一种嵌入式硬件辅助调试机制研究与实现

2022-09-15鹏,刘杰,贾

计算机工程 2022年9期
关键词:状态机寄存器上位

刘 鹏,刘 杰,贾 讯

(江南计算技术研究所,江苏 无锡 214215)

0 概述

在高端服务器或低功耗嵌入式产品中,调试机制虽然不受关注但不可或缺。已经通过验证测试的成熟芯片产品一般提供非入侵式、入侵式这两种或其中一种调试机制[1]。入侵式调试机制主要通过软件或硬件中断陷入调试模式[2],主要以断点和单步调试为代表。用户在断点和步进调试过程中,可以控制应用程序代码运行到代码中的指定点,然后Halt 标识的处理器,此时,用户可以选择检查或更改内存以及寄存器内容,步进或重新启动应用程序。非侵入式调试机制以跟踪(Trace)模式为主,主要实现方式是将CPU 状态及指令流信息压缩导入存储器,协同软件解压缩开展现场或性能分析,能够帮助用户查证CPU 在全速运转下才出现的或偶然发生而不可预测的错误[3]。

本文针对某自主国产SoC 芯片(下文简称为GCXP),设计一个保证用户可调试观测和安全性的用户调试解决方案。调试行为通过中断及其处理程序来实现,保证在调试中断监控下开展调试行为。兼容开源上位机OpenOCD 调试软件生态,从而支持Eclipse等IDE。不同于ARM、Sivife 等需要进行CPU 设计,本文方案向CPU IP 核已经设计完备的SoC 中增加硬件辅助调试功能,不需要修改CPU 设计。

1 相关工作

目前,大多数处理器都独立设计了一套调试体系结构,以便于用户进行片上调试。例如,x86 体系结构提供了6 个调试寄存器来支持硬件断点和调试异常[1],同时Intel Processor Trace[2]也是一个备受关注的硬件辅助调试特性[3-4]。Arm 架构的处理器具有调试和非调试两种状态,并设计了一组调试寄存器来支持自主机调试和外部调试[5-6]。同时,ARM[7-9]还引入了硬件组件,如Embedded Trace Macrocell[10]和Embedded Cross Trigger[11],以完成各种硬件辅助调试目的。相应地,硬件供应商通过片上调试端口将上述调试特性暴露给外部调试器,比较常用的调试端口是IEEE 1149.1[12]定义的联合测试工作组(Joint Test Action Group,JTAG)端口,主要用来支持调试目标和外部调试工具之间的通信。使用JTAG端口和外部调试工具(如Intel System Debugger[13]、ARM DS-5[14]、OpenOCD[15]),开发人员能够有效、方便地访问目标的内存和寄存器。

ARM 的调试基础架构称为CoreSight,主要实现调试和跟踪这2 个功能:

1)调试功能,运行处理器的控制,允许启动和停止程序单步调试源码和汇编代码,在处理器运行时设置断点,即时读取/写入存储器内容和外设寄存器,读写内部和外部FLASH 存储器。

2)跟踪功能,提供程序计数器采样、数据跟踪、事件跟踪等,实现CPU 历史序列调试、软件性能分析和代码覆盖率分析。

开源SoC 硬件辅助调试解决方案主要有RISCV Debug Spec 0.11/0.13[16]、Open SoC Debug(OSD)[17],两者都描述了基于Run-Stop、Trigger、System Bus Access调试的具体规范细节,后者着重描述Trace 模式并给出了基于Rocket-Core 的参考设计实现,需要在Core 内实现Core Debug Unit 逻辑,前者有独立的Trace-Spec[18],依赖CPU 预留Core Trace IO。

在GCXP 系列中,用户通过片外维护控制模块访问I/O 和存储空间,CPU 片内状态通过扫描链硬件逻辑来观测调试[19-20]。同时,特有的HMCODE 机制也可以在核心驱动调试以承担调试功能,但一般不对用户开放。与商业SoC 调试功能相比,现阶段GCXP 系列产品的调试机制缺少安全性[21]以及交互、断点、灵活读写功能,同时缺乏上位机调试软件IDE 工具生态[22],尤其在安全性和嵌入式用户调试工具生态上,存在较大缺陷,如基于扫描链重用的调试机制,因扫描链在芯片上留下一个独立的逻辑接口,不受任何权限检查,可以在任何时刻获取芯片内部的状态信息,相当于为芯片增加了一个“后门”。同时,文献[21]中也提到了一种JTAG 扫描链攻击的逆向技术,黑客可以获取扫描链上芯片架构设计相关细节信息。在嵌入式用户调试工具方面,ARM、Sifive 都配备对应的上位机IDE 或兼容主流开源IDE,如Eclipse、Keil 等,与硬件调试辅助机制相结合,可以提供便捷丰富的寄存器以及内存观测读写、断点、程序下载、性能分析功能。

GCXP 硬件辅助调试配套软件部署要求较高(可参见文献[20]),且只提供观测功能,目前没有与商业SoC 产品类似的用户环境。此外,交互式调试设计需要CPU 设计配合,是流水线设计的重要一环,且目前没有向已有成熟CPU 设计的SoC 环境中增加交互调试的方法。

2 GCXP-1A 调试模块设计

GCXP-1A 是一款面向低功耗嵌入式领域、采用精简GCXP 指令集的国产通用处理器核心,实现了全独立自主指令集嵌入式子集,是GCXP 架构下面向嵌入式领域的处理器核心,该核心采用IP 化设计,指令、数据存储器工作模式、TLB 条目数等关键微结构参数化设计,并实现标准AXI 接口,便于通用SoC 集成。

GCXP-1A 设计主要参考RISCV Debug Spec 0.13.2 规范及Sifive U500K 开源SoC源码,兼容RISCV OpenOCD 软件调试工具及OpenOCD 的IDE生态,结合GCXP 软硬件架构开展调试模块设计,结合GCXP 特权架构开展用户调试工具的硬件设计,同时在OpenOCD 软件端开辟GCXP 分支,兼容RISCV Debug Spec 0.13.2 流程,实现完整的Run-Stop 侵入式调试机制以及OpenOCD 接口下的基本调式、程序下载功能,相较于无感知的扫描链重用调试信息获取,该方法处于调试中断语义监控环境中,安全性更高,并且对CPU 核内无设计要求,借助OpenOCD,可直接与GDB、开源IDE 产品对接,可以向前扩展CPU 产品的通用调试生态,同时开展模拟验证及FPGA 验证,从而证明功能的正确性。

RISCV Debug Spec 0.13.2 Spec 中 对CPU 设 计提出了诸多要求,例如,需要2 条调试专用指令EBREAK、DRET,Trigger 硬件断点寄存器,以及调试模式与配套的DPC、DCSR 寄存器等,同时,在流水线控制上也需要对应的设计。在GCXP 特权架构下,为了不对原有CPU 设计、操作系统核软件接口及编译工具链设计进行改动,取消调试模式(调试模式在RISCV 开源CPU 中实现,特权层级还是处于M 模式,严格上来说并不算是一种独立的特权层级),同时,EBREAK 与DRET 分别设计成GCXP 指令集中的SYSCALL,并分别约定特定的调用号,将DPC、DCSR 放入Debug Module(IO 地址空间)中。同时,因为GCXP HM 特权架构不响应中断,所以将RISCV Trigger 调试中断、单步调试、硬件调试中断都进行重新设计,并设置对应的HMCODE 处理软件程序,以实现Spec 中调试中断处理的硬件逻辑部分。

2.1 硬件逻辑设计

由于GCXP-1A 面向低功耗MCU 场景,因此调试机制设计主要考虑用户调试应用程序的Run-Stop调试以及外设I/O、Memory 内容读写功能这些需求,从而实现中断调试模式、总线访问调试。GCXP-1A的具体硬件逻辑架构如图1 所示。

图1 GCXP-1A 用户调试模块的逻辑架构Fig.1 Logical architecture of GCXP-1A user debugging module

RISCV Debug Spec 0.13.2 中主要规范了一套抽象调试命令,便于不同架构具体实现与调试工具及生态解耦,其Run-Stop 调试机制基于DM 模块接管PC 来实现,分为Trigger 中断(由硬件断点触发)、上位机调试中断、软件断点陷入调试中断这3 类,最终通过Debug ROM 程序与调试模块(Debug Module,DM)状态机协同路由,决定CPU PC 取指地址,从而执行从抽象命令解析、翻译、预装填到抽象命令相关字段所指定的不同存储空间的调试命令。

GCXP-1A 用户调试模块的逻辑架构主要实现用户程序异常中断调试、提供断点环境通用寄存器及CSR 寄存器的访问、提供SoC 总线上外设I/O 寄存器或存储器的访问。具体如下:

1)DM_TRANSPORT 模块负责JTAG TAP 状态机的实现,以及上位机指令操作向DM_ROUTER模块内部总线的转写,主要分为DM_TRASNPORT寄存器访问和DM 内部总线访问,前者主要是标识调试协议实现版本,后者用于交互具体的调试任务。

当TAP 状态机进入Update-DR 状态,IR 寄存器的值为DMI_ACCESS(5’h11),且当前调试系统总线(Debug Message Interface,DMI)接口没有错误信息时,开始执行dmi.op 指定的操作。

如图2 所示,当dmi.op=0x1,dmi 状态机进入Read 状态。在Read 状态中,先将dmi_req_valid 信号拉高,再等待dmi_req_ready 信号为高时进入WaitReadValid 状态。在WaitReadValid 状态中等待dmi_resp_valid 信号为高,当该信号为高时,dmi 读取DM 模块回应的数据(dmi_resp.data),并返回Idle 状态。当dmi.op=0x2,dmi 状态机进入Write 状态。在Write 状态中,先将dmi_req_valid 信号拉高,再等待dmi_req_valid 信号为高时返回Idle 状态。

图2 JTAG 转DMI 内部总线状态机Fig.2 JTAG to DMI internal bus state machine

2)DM_ROUTER 模块负责上位机通过JTAG DMI_ACCESS 访问填充的抽象调试寄存器内容,图3 为其功能逻辑图,将调试任务依据抽象命令对应标志位,通过内部总线发送到具体部件执行。

图3 DM_ROUTER 功能流程Fig.3 Procedure of DM_ROUTER function

3)DM_EXE 模块接收并处理处理器内部信息的调试指令,图4 为其功能逻辑图,根据用户Halt 指令、软件配置的硬件断点是否等于CPU Trace 信号中PC 值、单步调试指令标志情况,向外发出调试中断信号,同时完成调试目的寄存器访问路由,分别组织指令架构下通用寄存器访问、CSR 寄存器访问的指令编码,并依据调试任务中标识的执行空间进行指令填充(结果目的地址为内部DATA 寄存器),等待PC 正确跳入取指执行,执行完毕标记完成位,上位机将DATA 寄存器中的结果扫回。DM_EXE 模块中的关键点是CPU、上位机、DM 模块的三方协同状态机,从而保证作业正常流转。

图4 DM_EXE 解析ABSTRACT_CMD 以及填充指令槽位逻辑Fig.4 DM_EXE parsing ABSTRACT_CMD and filling instruction slot logic

三方协同状态机设计如图5 所示,其中,左图主要描述DM_EXE 硬件状态机,右图主要描述Debug Rom 软件中断处理程序。中断可以由软件陷入或上位机调制命令通过DM 发出,任何一种调试中断发起,即触发调试中断,PC 跳入调试中断入口程序(Debug Rom),首先挪用一个通用寄存器,再将标定调试的Core_Id 写入DM Halted 寄存器,硬件状态机确认选中的CPU 已经被停住,此时,若上位机发送了调试命令,则DM 将CMD_BUSY 拉高,进入下一状态,否则停留在IDLE,在Debug Rom 程序go 与resume 都等于0 的情况下会在Debug Rom 程序空间死循环,等待调试指令到来。

图5 DM_EXE 软硬协同状态机Fig.5 DM_EXE software and hardware collaborative state machine

当上位机调试指令到来,CMD_BUSY 信号随即拉高,DM_EXE状态机进入GO状态,此时等待Debug Rom程序填写DM 寄存器going 为1,此处设计是因为调试指令一般由1~2 条组成,并且为硬件寄存器装填,1 个CLK 周期就能完成,在GCXP-1A 5 级流水线设计下,一条指令执行周期即可保证指令硬件装填完毕,Debug Rom执行DM go寄存器判断这条指令周期就足以满足,因此,这里不再做DM 指令槽位填充完毕握手机制。状态机检测到Going 地址有写操作后,随即PC 获取一条跳转指令,跳入DM_EXE 取指入口(where to go),根据上位机指令标记获取跳入不同DM 内部指令槽入口的跳转指令,从而执行调试任务,指令槽位最后一条指令必然为跳回Debug Rom 首地址,通过再次写Halted地址进入Idle 状态。复位三方握手流程类似,不再详细描述。

4)DM_SBA 模块实现一个总线的Master 端,从而使得DM 模块能够访问SoC 总线下编址地址信息读写。DM_SBA 的总体功能逻辑结构如图6所示。

图6 DM_SBA 模块功能逻辑Fig.6 DM_SBA module function logic

DM_SBA 模块的读写过程用一个状态机实现,有idle、write、read、waite_write、waite_read 这5 种状态。状态机的转换示意图如图7 所示,Idle 为master接口处于空闲状态,write 为master 接口往内存写数据,read 为master 接口向内存读取数据,waite_write和waite_read 分别为master 接口的读、写等待状态。

图7 DM_SBA 工作状态机Fig.7 DM_SBA working state machine

2.2 软件设计

GCXP 软件特权架构有3 种特权级:1)硬件模式(Hadware Mode,HM),是最高权限模式,为特权程序运行环境;2)内核模式(Kernel Mode,KM),是次低级模式,为操作系统运行环境;3)用户模式(User Mode,UM),是最低级模式,为用户程序运行环境。

特权程序运行程序(SW-HMCODE)为代替硬件逻辑的软件代码,定义了平台SYS_CALL,注册了操作系统核心对应的特权异常、中断处理入口地址,在扩展处理器功能实验、规避硬件错误以及OS 调试上都有重要的地位,是一种GCXP 独有的软硬件协同机制,默认为绝对正确,保证程序不会挂死在HM 模式下,且对用户透明。

RISCV Debug Spec 中所涉及的CPU 硬件中断处理、调试模式及其配套的DPC、DCSR,在GCXP GCXP-1A 软硬件环境下都进行了重新设计,与GCXP-1A HMCODE 相结合,调试中断改为普通中断,通过HMCODE 中断处理流程,实现现场保护和复原,并在HMCODE 中设置专用SYS_CALL 入口,结合中断控制器,与普通中断跳入操作系统核心注册处理程序不同,调试中断处理程序(DM_ROM)在HMCODE 内部进行调试中断识别并完成跳转,从而实现软硬件调试陷入。

在上位机OpenOCD 中,由于兼容RISCV Debug Spec 0.13.2,因此按照RISCV Debug Spec 0.13.2 的软件流程,添加th1a-013 target 分支,注册寄存器读写、内存地址读写以及programbuf、abstract commad函数读写等,从而完善用户调试流程。

3 验证分析

3.1 GCXP-1A 调试模块模拟验证

如图8 所示,GCXP-1A 调试模块模拟验证环境由3 个部分组成,分别为:1)SimJTAG.sv 包含Jtag_tick DPI-C 接口,负责路由来自DPI-C 的JTAG引脚信号,并与GCXP-1A SOC DM JTAG 桥接;2)DPI-C 接口具体实现本机socket 注册、监听和链接接受服务,使用bitbang 协议将socket 调试请求转换成JTAG 信号;3)上位机调试软件通过DPI-C 暴露的本地端口链接,开展调试流程。

图8 调试模块模拟验证环境逻辑结构Fig.8 Debugging module simulation verification environment logical structure

如图9 所示,在模拟验证环境下,激励时钟起震、复位撤销前使用HMCODE+TEST_CODE HEX进行约定地址空间布数。软件流程具体如下:1)CPU 从HMCODE 开始取指运行,跳转到TEST_CODE 地址;2)TEST_CODE 配置CSR 寄存器打开调试中断使能;3)跳出HM 模式,运行死循环;4)HMCODE 根据CPU 捕获的中断(CPU 保证流水线硬件冲刷),将PC 跳转到Debug ROM HALT 地址执行;5)上位机执行调试作业;6)Debug 退出,执行Debug ROM resume 程序段,恢复现场,跳转PC 到保留PC。

图9 模拟验证环境软件逻辑结构Fig.9 Simulation verification environment software logical structure

基于Synopsys VCS 2018.09-SP2 开展GCXP-1A SoC 模拟验证,针对dm 开展OpenOCD test_compliance测试集验证,针对所设计的功能,波形日志如下:

1)调试中断流程。

如图10 所示,当上位机中断请求发起,dm 模块io_debug_req_o 信号拉高,由HMCODE 中断现场保护,并跳转PC 到0x100 调试处理程序首地址,执行118 地址的写hart id(0)到dm 0x400(Halted_aligned)地址,dm状态机检测到该写操作后随即拉高halted_q 信号,标识CPU 已经成功响应调试中断。

图10 模拟环境调试中断响应波形图Fig.10 Simulated environment debugging interrupt response waveform

2)CPU 内部寄存器读写。

如图11所示,state_q为上文描述的三方交互状态机状态寄存器,分别标识idle(0)、go(1)、resume(2)、excuting(3),调试指令下达后,由idle->go 状态,并等待debug rom 程序写going 地址,期间硬件完成abstract_cmd 任务指令转译和填充,在going 拉高后跳入excuting 阶段,执行完毕后(指令槽位最后一条固定位回到debug rom 首地址),等待debug rom 再次写halted_align 地址,从而回到Idle 状态。

图11 模拟环境abstract cmd CPU 内部寄存器读写Fig.11 Simulated environment abstract cmd CPU internal register read and write

3)SBA 总线地址访问。

如图12 所示,上位机通过OpenOCD 对总线上的地址进行读写访问,dm_sba 模块从dm_csr 路由信号操作axi4 master 读写时序,从而完成读写任务。

图12 模拟环境SBA 时序Fig.12 Simulation environment SBA time limit

3.2 GCXP-1A 调试模块FPGA 验 证

FPGA 验证环境为KCU105,将设计中的JTAG引脚约束到FMC XM105 扩展卡引脚,链接JLink v9,DM 模块挂在系统总线下。在Vivado 2019.2 环境下开展SoC 综合仿真实验,运行频率为100 MHz。

在仿真过程中,需要HMCODE 逻辑配合,在不依赖linux kernel 的情况下识别响应调试中断。实验环境如图13 所示。

图13 GCXP SoC DM+JLINKV9+OpenOCD 验证平台Fig.13 GCXP SoC DM+JLINKV9+OpenOCD verification platform

在图14 中,使用OpenOCD 客户端链接JLNK 开展DM 功能测试实验,图14(a)测试内容为通用寄存器或CSR 寄存器读写功能,图中示例使用OpenOCD寄存器读写命令读写寄存器,图14(b)测试内容为SoC 总线地址空间存储器读写功能,使用OpenOCD SBA 模式测试字读写。

图14 OpenOCD 命令行操作示例Fig.14 OpenOCD command line operation example

覆盖率是判断DUT 验证是否完备的重要指标,在数字集成电路设计中,覆盖率分为代码覆盖率和功能覆盖率,代码覆盖率表征每行代码的执行情况,功能覆盖率表征具备一定功能的代码组合的执行情况。从图15 可以看出,本文DM 模块的代码及功能覆盖率都能达到100%,能够满足流片要求。

图15 代码及功能覆盖率Fig.15 Code and function coverage rate

4 结束语

本文在RISCV 调试协议规范的基础上,结合GC,使用GCXP的HMCODE机制实现一套轻量级且对CPU无设计需求的调试方案,该方案可以兼容GCXP 全系列CPU IP 产品以及RISCV 的调试软件和转接器,从而丰富自主芯片的调试生态。下一步将协同CPU 设计Trace 模式,实现CPU 非入侵式调试机制,完成可控可过滤的指令流、数据流跟踪,此外,配套上位机程序开发,实现性能可分析观测、功能完备且安全的用户调试机制,也是今后的研究方向。

猜你喜欢

状态机寄存器上位
Lite寄存器模型的设计与实现
基于有限状态机的交会对接飞行任务规划方法
二进制翻译中动静结合的寄存器分配优化方法
基于Spring StateMachine的有限状态机应用研究
要攻城略地关键要有好筹码,这匹水产动保“黑马”如何能迅速上位?
特斯拉 风云之老阿姨上位
移位寄存器及算术运算应用
基于ZigBee和VC上位机的教室智能监测管理系统
Lx5280模拟器移植设计及实施
基于反熔丝FPGA的有限状态机加固设计