CN117422025B - 一种基于risc-v架构的随机中断调试验证系统 - Google Patents
一种基于risc-v架构的随机中断调试验证系统 Download PDFInfo
- Publication number
- CN117422025B CN117422025B CN202311733452.6A CN202311733452A CN117422025B CN 117422025 B CN117422025 B CN 117422025B CN 202311733452 A CN202311733452 A CN 202311733452A CN 117422025 B CN117422025 B CN 117422025B
- Authority
- CN
- China
- Prior art keywords
- interrupt
- irq
- test
- debugging
- task
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Active
Links
- 238000012795 verification Methods 0.000 title claims abstract description 174
- 238000012360 testing method Methods 0.000 claims abstract description 299
- 230000006870 function Effects 0.000 claims abstract description 175
- 238000000034 method Methods 0.000 claims abstract description 92
- 238000004088 simulation Methods 0.000 claims abstract description 81
- 230000007246 mechanism Effects 0.000 claims abstract description 12
- 238000013515 script Methods 0.000 claims description 62
- 230000008569 process Effects 0.000 claims description 41
- 238000012545 processing Methods 0.000 claims description 34
- 230000005284 excitation Effects 0.000 claims description 29
- 230000008859 change Effects 0.000 claims description 26
- 230000006399 behavior Effects 0.000 claims description 11
- 230000005540 biological transmission Effects 0.000 claims description 10
- 238000012544 monitoring process Methods 0.000 claims description 10
- 230000001960 triggered effect Effects 0.000 claims description 9
- 230000004044 response Effects 0.000 claims description 8
- 238000004458 analytical method Methods 0.000 claims description 7
- 238000011068 loading method Methods 0.000 claims description 7
- 238000012546 transfer Methods 0.000 claims description 7
- 238000001514 detection method Methods 0.000 claims description 6
- 238000002955 isolation Methods 0.000 claims description 6
- 238000013142 basic testing Methods 0.000 claims description 4
- 230000000630 rising effect Effects 0.000 claims description 4
- 238000010200 validation analysis Methods 0.000 claims description 4
- 238000004140 cleaning Methods 0.000 claims description 3
- 230000006386 memory function Effects 0.000 claims description 2
- 238000013461 design Methods 0.000 description 14
- 238000010276 construction Methods 0.000 description 8
- 230000004048 modification Effects 0.000 description 5
- 238000012986 modification Methods 0.000 description 5
- 230000008034 disappearance Effects 0.000 description 4
- 230000001976 improved effect Effects 0.000 description 4
- 230000003993 interaction Effects 0.000 description 4
- 238000012800 visualization Methods 0.000 description 4
- 238000010586 diagram Methods 0.000 description 3
- 230000009471 action Effects 0.000 description 2
- 230000008901 benefit Effects 0.000 description 2
- 238000006243 chemical reaction Methods 0.000 description 2
- 230000001419 dependent effect Effects 0.000 description 2
- 238000012942 design verification Methods 0.000 description 2
- 238000011990 functional testing Methods 0.000 description 2
- 230000000977 initiatory effect Effects 0.000 description 2
- 230000001360 synchronised effect Effects 0.000 description 2
- 230000009466 transformation Effects 0.000 description 2
- 238000007792 addition Methods 0.000 description 1
- 238000013459 approach Methods 0.000 description 1
- 230000009286 beneficial effect Effects 0.000 description 1
- 238000007405 data analysis Methods 0.000 description 1
- 230000007547 defect Effects 0.000 description 1
- 238000011161 development Methods 0.000 description 1
- 230000000694 effects Effects 0.000 description 1
- 239000000284 extract Substances 0.000 description 1
- 230000004927 fusion Effects 0.000 description 1
- 230000008676 import Effects 0.000 description 1
- 238000007689 inspection Methods 0.000 description 1
- 230000010354 integration Effects 0.000 description 1
- 239000000203 mixture Substances 0.000 description 1
- 230000008092 positive effect Effects 0.000 description 1
- 238000002360 preparation method Methods 0.000 description 1
- 230000003252 repetitive effect Effects 0.000 description 1
- 230000004936 stimulating effect Effects 0.000 description 1
- 230000000638 stimulation Effects 0.000 description 1
- 238000006467 substitution reaction Methods 0.000 description 1
- 230000000007 visual effect Effects 0.000 description 1
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F30/00—Computer-aided design [CAD]
- G06F30/30—Circuit design
- G06F30/32—Circuit design at the digital level
- G06F30/33—Design verification, e.g. functional simulation or model checking
- G06F30/3308—Design verification, e.g. functional simulation or model checking using simulation
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/40—Transformation of program code
- G06F8/53—Decompilation; Disassembly
-
- Y—GENERAL TAGGING OF NEW TECHNOLOGICAL DEVELOPMENTS; GENERAL TAGGING OF CROSS-SECTIONAL TECHNOLOGIES SPANNING OVER SEVERAL SECTIONS OF THE IPC; TECHNICAL SUBJECTS COVERED BY FORMER USPC CROSS-REFERENCE ART COLLECTIONS [XRACs] AND DIGESTS
- Y02—TECHNOLOGIES OR APPLICATIONS FOR MITIGATION OR ADAPTATION AGAINST CLIMATE CHANGE
- Y02D—CLIMATE CHANGE MITIGATION TECHNOLOGIES IN INFORMATION AND COMMUNICATION TECHNOLOGIES [ICT], I.E. INFORMATION AND COMMUNICATION TECHNOLOGIES AIMING AT THE REDUCTION OF THEIR OWN ENERGY USE
- Y02D10/00—Energy efficient computing, e.g. low power processors, power management or thermal management
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Computer Hardware Design (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Evolutionary Computation (AREA)
- Geometry (AREA)
- Software Systems (AREA)
- Debugging And Monitoring (AREA)
Abstract
本发明公开了一种基于RISC‑V架构的随机中断调试验证系统,属于处理器核验证技术领域,集成于一种基于RISC‑V架构的处理器验证系统中,该验证系统将指令生成模块、程序编译模块、模拟器模块、仿真验证模块、比对检查模块和回归管理模块联系起来,然后通过集成验证系统,在不同场景下模拟大量随机指令执行状态,实现全面验证处理器架构和微架构的正确性;采用UVM测试环境自我检查的方法和握手机制,实现对中断或调试功能验证的比对,从可以在独立的验证环境中进行中断或调试功能的有效验证而不依赖模拟器的支持;采用UVM_TEST来模拟各种中断调试场景,考虑不同中断验证场景和调试方式,实现对中断和调试功能的全面验证。
Description
技术领域
本发明属于处理器核验证技术领域,具体地说,是涉及一种基于RISC-V架构的随机中断调试验证系统。
背景技术
在现有技术中,虽然存在一些针对处理器中断调试验证的系统,也有一些专为RISC-V架构被测对象设计的验证系统,但目前还没有一款专门针对RISC-V架构处理器,并能完成中断调试功能验证的系统。这种缺乏专门的系统的情况导致在RISC-V架构处理器开发和调试过程中的困扰。
绝大多数针对处理器中断调试的验证系统都依赖于参考模型,如模拟器。这些系统需要使用支持RISC-V中断调试标准的模拟器才能完成整个系统的验证。然而,不同的中断和调试设计标准之间存在差异,并且即使模拟器支持中断和调试,也需要进行精确的建模来模拟中断处理程序和调试只读程序(DEBUG ROM)的行为。这种依赖于模拟器的验证方法存在一些局限性和困难。
在现有技术中,中断调试的激励信号往往是固定的,而且不同种类中断之间的仲裁和随机性较差,无法全面有效地生成各种验证场景。同样,调试激励的生成通常也是固定的,需要配置不同的调试控制寄存器来模拟不同的调试场景。这种固定的激励生成方式限制了验证的灵活性和覆盖范围。
现有技术中通常采用模块化验证方法来专门验证中断和调试功能,但无法很好地模拟在不同场景下被测对象执行大量随机指令的状态,以验证中断和调试模块的正确性。而在实际流片执行时,可能会出现一些与处理器架构和微架构相关的问题,这些问题在模块化验证阶段很难暴露出来。
发明内容
本发明提供一种基于RISC-V架构的随机中断调试验证系统,用以解决现有处理器中断调整验证中存在的依赖于模拟器的实现和建模、激励信号和调试激励生成随机化弱、难以模拟不同场景下大量随机指令执行状态等技术问题。
本发明采用以下技术方案予以实现:
提出一种基于RISC-V架构的随机中断调试验证系统,包括:
指令生成模块,为程序生成部分,生成包含随机指令流的汇编程序;其中,在中断随机指令中加入以若干条存储指令结束的握手数据,以实现基于存储指令将握手数据存储到指定的签名地址;
程序编译模块,包括汇编程序所用到的编译器、连接器和反汇编器、编译所生成的结果文件资源库、以及验证系统的编译工具调用脚本;
仿真验证模块,包括UVM测试环境、被测对象和UVM_TEST,以及用于构建、控制和管理仿真的主脚本、项目管理脚本和Makefile;所述UVM测试环境由UVM代理和虚拟序列器组成;所述UVM_TEST调用虚拟序列器动态生成用以描述中断测试场景和测试用例的随机中断激励;所述UVM代理包括内核输出代理和中断代理;所述内核输出代理包括内核输出监测器,用于监测签名地址的写入操作,将写入操作的相关信息传输到UVM测试环境,以使UVM测试环境接收到签名地址上的相关信息后,执行对应的中断测试事务或比对操作,以及,检测被测对象实时信号变化,并将关键信号的变化信息输出到被测对象信号监视输出的RTL仿真日志文件中;
所述中断代理包括事务对象、中断接口、中断序列器和中断驱动器;其中,所述事务对象用于随机生成随机中断激励;所述中断接口用于连接被测对象的各个中断信号接口和所述UVM测试环境;所述中断序列器用于生成中断序列流,管理测试序列流的执行顺序并将序列流传递给中断驱动器以进行驱动;所述中断驱动器用于向被测对象接口按照设定时序逻辑发送所述中断序列流;
所述UVM_TEST包括通过调用基础测试类和设定功能函数实施中断或调试功能验证的中断调试测试,包括:
初始化UVM测试环境并设置相关的寄存器、配置参数和变量;
通过调用发送中断调试激励信号函数调度虚拟序列中的中断序列,来发送各类中断或调试激励信号,触发中断或调试事件;
调用等待中断调试事件函数等待中断或调试事件的触发完成,确保处理器内核从正常模式正确进入了调试模式,开始执行中断调试处理程序;
调用检查中断调试事件函数检查中断或调试事件的处理状态,验证中断或调试事件是否被正确处理,并检查相关寄存器和变量的值是否正确;
在确认中断或调试事件处理完毕后,调用结束中断调试刺激信号的发送函数结束中断或调试刺激信号的发送,并等待中断或调试事件被清除;
最后,恢复UVM测试环境,并检查处理器内核返回中断或调试前的正常模式,同时检查相关的寄存器和变量是否符合预期变化,并清理测试环境,之后继续保持指令在被测对象中被执行,以准备下一轮测试。
与现有技术相比,本发明的优点和积极效果是:本发明提出的基于RISC-V架构的随机中断调试验证系统,针对现有验证系统依赖于模拟器,且模拟器实现标准不同和建模困难的问题,采用握手机制和UVM测试环境自我检查的方法,实现验证平台本身对中断和调试功能验证的比对,从而可以在独立的验证环境中进行中断调试功能的有效验证,无需依靠模拟器,解决了模拟器标准差异和建模困难带来的限制。针对激励信号和调试激励生成随机化弱,限制了验证的随机性和覆盖范围的问题,采用UVM测试环境和UVM_TEST来模拟各种中断调试场景,同时考虑到不同中断之间的仲裁以及异步中断、嵌套中断等复杂场景的验证;对于调试功能,通过诸如ebreak断点调试、ebreakm调试、单步调试等不同的调试方式,实现对中断和调试功能的全面验证。针对模块化验证方法难以模拟不同场景下的大量随机指令执行状态,从而限制了对处理器架构和微架构相关问题的发现的问题,将中断调试验证系统集成在一种基于RISC-V架构的内核验证系统中,实现内核指令功能验证的同时进行中断调试验证,通过集成验证系统,可以在不同场景下模拟大量随机指令执行状态,从而全面验证处理器架构和微架构的正确性。
结合附图阅读本发明实施方式的详细描述后,本发明的其他特点和优点将变得更加清楚。
附图说明
图1为本发明提出的基于RISC-V架构的处理器验证系统的系统架构示意;
图2为本发明提出的UVM测试环境的结构示意;
图3为本发明提出的基于RISC-V架构的随机中断调试验证方法的示意。
具体实施方式
下面结合附图对本发明的具体实施方式作进一步详细的说明。
本发明提出的基于RISC-V架构的随机中断调试验证系统,集成于一种基于RISC-V架构的处理器验证系统中,在实现内核指令功能验证同时进行中断调试验证,通过集成验证系统,可以在不同场景下模拟大量随机指令执行状态,从而全面验证处理器架构和微架构的正确性。具体的,先对基于RISC-V架构的处理器验证系统进行说明。
现有的处理器验证中,包括对非特权功能的验证和特权功能的验证,其中非特权功能的验证包括:对基本指令集执行正确性的验证、对内存访问和管理的验证和对异常处理的验证;对特权功能的验证包括:中断处理、调试功能、低功耗、复位和安全保护域测试等。
现有技术中,验证特权功能依赖于模拟器,这是因为随机指令生成器的设计初衷通常是通过生成具有一定随机性的指令序列来增加测试用例的多样性,从而提高测试的覆盖率;然而,对于验证诸如中断处理的特权功能,因为这些功能通常涉及到处理器内部状态的复杂变化,如控制寄存器的写入、特权级别的切换、中断/异常的触发、安全区域内存访问权限、处理器低功耗模式切换等,这些情况的覆盖需要更为精确和细致的控制,而随机指令生成器无法在测试中充分模拟这些场景。
鉴于上述,本发明提出一种基于RISC-V架构的处理器验证系统,在给出一种将验证环境的激励生成、编译、仿真、比对和回归等组件联系起来的完善系统同时,结合对随机激励生成器的改造和握手机制,通过状态传递由验证平台自身进行中断功能点检查,不依赖特权模拟器的支持,模拟器可以不设计中断验证部分,从而降低模拟器的设计难度。
首先,本发明充分考虑特权模拟器的有限性,通过在验证平台中引入握手机制和验证平台的自我检查,实现验证平台与非特权模拟器的协同工作,这种协同工作允许在验证平台上引入灵活的、更全面的验证方法,以弥补模拟器的不足。
第二,通过在随机指令生成过程中加入握手用的程序段,本发明实现了处理器状态的实时传递,使得验证平台能够在运行时监测和比对处理器内部状态。比如,是否进入退出中断模式,中断相关控制状态寄存器的变化是否正确等。
第三,通过动态生成随机的特权功能相关的激励,验证平台能够更灵活地驱动特权功能。这种动态激励生成方法有助于覆盖更多的特权操作场景,从而提高验证的全面性。同时,不影响随机指令的运行和比对,可以和模拟器协同工作。
第四,使用UVM监视器来进行tracer功能,但是并不是每一个周期都去记录所有寄存器的变化,而是只有当处理器有写寄存器行为时,才会检查并记录修改的寄存器的值(如果硬件去做这个功能,需要更多的逻辑,占用硬件资源和面积),这样可以减少Log的大小,并且由于使用验证平台来trace,所以trace的内容和Log的格式都是可以根据情况修改的,这样可以适配不同的模拟器,使之更灵活。
第五,通过带有时间戳的历史队列,记录不同指令写同一寄存器时的执行先后顺序和是否已经写回的状态,保证被写回的寄存器中值的变化顺序正确且写回寄存器的时间和行为按预期顺序进行比对,从而与模拟的比对顺序保持一致。之所以这样做是因为,如果几条不同的指令先后写回相同的寄存器,且有时写回的值需要跟原始寄存器中的值做比较后才能决定,那么这将依赖于指令写回寄存器的时间先后顺序,和寄存器中值的变化顺序。对于非时间精确的模拟器,这几条指令都是执行后直接出结果(先执行的指令先写回寄存器), 因此无须考虑由于执行和写回顺序不一致导致的问题。然而,处理器上执行的指令往往在执行后,需要多个周期才能出结果(这几条指令有可能后执行的指令先写回寄存器,并影响后执行指令比对的结果)。所以通过这个历史队列,可以使处理器核模拟器都按照指令写回寄存器的顺序进行对比。
基于上述,如图1和图2所示,本发明提出的处理器验证系统包括指令生成模块1、程序编译模块2、模拟器模块3、仿真验证模块4、比对检查模块5和回归管理模块6,下面对各模块进行详细说明。
指令生成模块1,通过对RISCV-DV进行扩展和改造实现,作为验证系统的程序生成部分,负责包含随机指令流的汇编程序的生成。
为了确保处理器在收到外部激励,如中断或调试请求时,能够正确更新内部状态,同时检测所处状态和相关寄存器的正确性,本发明使用握手机制,在随机指令中加入以若干条存储指令结束的握手数据,以实现基于存储指令将握手数据存储到指定的签名地址,从而通过握手协议将信息传递给验证系统的仿真环境;在UVM测试环境中,持续监控签名地址的写入操作,表明被验证的测试对象正在执行特定的握手汇编序列,并将一些信息传输到验证系统进行进一步的分析;验证系统接收到签名地址上的信息后,执行一系列的测试事务或比对操作,从而帮助验证和比对的过程。
握手机制包括:握手数据(握手代码段)使用一小段RISC-V汇编代码生成,以一条或多条存储(store)指令结束,这些指令将握手数据存储到指定的内存地址,即签名地址(signature address)。在验证系统的UVM检测环境中,持续监控签名地址的写入操作,这将表明被验证的测试对象(DUT)正在执行特定的握手汇编序列,并将一些信息传输到验证系统以进行进一步的分析。验证系统接收到签名地址上的信息后,执行一系列的测试事务或比对操作。具体签名地址上数据的格式和含义的定义参考RISCV-DV(DesignVerification)工具。
在本发明中,引入握手数据枚举类型;首先,定义signature_type_t枚举类型,用于表示握手数据中的签名类型,包括以下几种类型:CORE_STATUS,用于向UVM测试环境传递与当前状态相关的处理器信息;TEST_RESULT,用于向UVM测试环境传递UVM仿真结果的信息;WRITE_GPR,用于向UVM测试环境发送GPR(General Purpose Register)的转储指令,随后将跟随32个写入操作,用于将寄存器x0-x31的值传递给UVM测试环境;WRITE_CSR,用于向UVM测试环境发送CSR(Control and Status Register)的写入指令,数据字的位[19:8]将作为CSR地址,紧接着的第二个写入操作将写入实际的CSR数据。
另外,还定义了core_status_t枚举类型,用于表示处理器核心的不同状态。这些状态包括已初始化(INITIALIZED)、处于调试模式(IN_DEBUG_MODE)、处于机器模式(IN_MACHINE_MODE)、处于监管模式(IN_SUPERVISOR_MODE)、处于用户模式(IN_USER_MODE)、正在处理中断请求(HANDLING_IRQ)、已完成中断处理(FINISHED_IRQ)、正在处理异常(HANDLING_EXCEPTION)、指令故障异常(INSTR_FAULT_EXCEPTION)、非法指令异常(ILLEGAL_INSTR_EXCEPTION)、加载故障异常(LOAD_FAULT_EXCEPTION)、存储故障异常(STORE_FAULT_EXCEPTION)和EBREAK异常(EBREAK_EXCEPTION)等。
本发明通过上述握手机制,能够有效地将信息从被测对象(DUT)传递到UVM测试环境,并在验证过程中进行进一步的分析和比对操作。这种握手机制的使用方式能够提高验证的可靠性和全面性,确保处理器在面对外部激励时的正确行为。
在本发明申请中,指令生成模块1是对RISCV-DV进行改造得到的,用以确保生成的随机指令流覆盖各种场景和特殊情况。为了生成复杂特殊指令,对RISCV-DV随机指令生成器进行一系列约束,包括:
(1)对于64位随机指令,RISC-V处理器体系结构通常遵循跨越两个连续寄存器数据的设计,因此要求64位指令总是使用偶数编号的寄存器。在随机指令流中,RISCV-DV已经约束了一些预留寄存器,以防止一般指令使用这些寄存器。然而,对于预留寄存器中的奇数编号,由于指令字符串构造时只使用了偶数寄存器,造成原有的约束规则对于这些奇数寄存器不再适用。为了解决这个问题,本发明对RISCV-DV进行改进,引入一个新的预留寄存器列表,当64位指令中包含对奇数寄存器的约束时,将该奇数寄存器的前一个偶数寄存器存储在一个队列中,以满足特殊预留奇数寄存器的完整约束,通过这种方式,能够生成复杂特殊的64位指令,并确保对所有预留寄存器的约束都得到满足。另外,对于随机访存指令流,其存储基地址往往通过一个预留寄存器来存储,该预留寄存器不应该在这一随机访存指令流中被再次使用,此时,如果该预留寄存器为奇数编号并且该随机访存指令流包含一些64位的指令,这些64位的指令如果只被约束为不能使用上述奇数编号的预留寄存器是不足够的,还应约束其不能使用上述奇数编号的预留寄存器的前一个偶数编号寄存器,才能满足随机访存指令流基地址固定的要求。为了解决这个问题,本发明对RISCV-DV进行改进,在生成随机访存指令流时,在确定了存储基地址的奇数编号寄存器后,将奇数编号和其前一个偶数编号寄存器都加入到预留列表中,通过这种方式,能够生成含有64位特殊指令的随机访存指令流,并确保对所有预留寄存器的约束都得到满足。
(2)对于随机访存指令流,存储基地址的寄存器通常被限制为固定地址,以控制访存指令的作用范围。然而,对于一些特殊的后增访存类指令(其执行后会直接修改存储基地址的寄存器中的值),通常用于在访存操作后对基地址进行更新或调整,从而改变了原本被约束为不变的基地址。为了解决这个问题,本系统在执行后增访存指令后,在接下来的访存指令执行之前还原被修改的寄存器中的基地址值。通过这样的改造,能够确保随机访存指令流中的访存地址作用域不会受到随意的改变,保持了约束的稳定性。这样可以有效地控制特殊后增访存指令对存储基地址的影响,确保指令生成的正确性和一致性。
(3)在不同的场景下,指令生成和生成序列可能变得复杂。在RISCV-DV中,尽管可以随机生成寄存器编号和立即数的值,但无法直接随机生成指令寄存器中操作数的值,这限制了对浮点指令输入输出特殊值的能力。为了解决这个问题,本系统通过在随机指令流中插入定向指令流的方式,当即将执行浮点指令流时,随机的插入定向指令流以初始化浮点寄存器的特殊值。这样,在生成的随机指令流中,通过定向指令流可以定制浮点寄存器的特殊值,以满足特定的测试需求。除了浮点指令流,定向指令流的方法也适用于其他场景,例如,针对特定指令集扩展或特殊的处理器功能,插入定向指令流来定制寄存器或内存的特殊值,以测试功能的正确性。这可以包括输入边界条件、异常处理、数据相关性和寄存器相关性的测试等。
本发明通过改进指令生成工具,引入定向指令流的方法,可以在生成指令序列时更灵活地控制和定制各种场景下的测试需求,以实现更全面和准确的测试目标。
程序编译模块2,包含了汇编程序所用到的编译器、连接器和反汇编器,同时包含了编译所生成文件的结果文件资源库,以及该系统设计的编译工具调用脚本,该脚本使用SHELL(UNIX操作系统的命令语言)语言编写。
本发明还设计一套完善的构建系统,能够有效地将验证环境的各个组件联系起来,包括激励生成、编译、仿真、比对和回归,并实现自动化和规范化的管理,通过统一的模块接口和交互流程,提高验证环境的整体效率、自动化程度和可靠性。
首先,整个构建系统的核心是仿真验证模块中的脚本,包括主脚本、项目管理脚本和Makefile。
主脚本(Main Script):是整个验证流程的控制中心,它首先定义了一些关键的路径,用于指定各种文件的位置和目录结构。然后,通过定义宏(Define)来传递参数给仿真环境和测试平台,以配置不同的功能和选项。这些选项包含VCS编译和仿真的选项,以及一些必要的配置选项比如:批量回归测试还是单个用例、测试测试用例名、是否进行VCS编译、使用何种波形文件格式、是否使用模拟器对比、随机种子的大小、是否收集覆盖率等。接下来,主脚本会删除上次仿真留下的临时文件和目录,然后调用一个项目管理脚本(ProjectManagement Script)并传入测试用例的名称。项目管理脚本负责根据测试用例的分类执行相应的操作,比如编译和模拟器调用等。最后,主脚本会对仿真日志文件进行统计和打印,提取其中的通过和失败信息。
项目管理脚本(Project Management Script):用于配置临时参数,并根据传入的测试用例名称执行不同的任务。它可以检查编译和仿真是否成功,并根据测试用例的分类执行不同的操作。例如,如果需要使用编译器,项目管理脚本会调用编译脚本来建立临时的编译环境,并将编译生成的结果文件保存在指定目录中,以避免不同测试用例之间的资源冲突。如果需要使用模拟器,它会调用模拟器的执行脚本。最后,项目管理脚本会管理仿真产生的覆盖率文件数据,并将它们保存在固定的目录中,以方便进行覆盖率的综合分析。
Makefile:是一个用于构建和管理工程的文件,它主要用于定义 VCS 编译所需的路径,如 RTL 代码文件(Filelist 路径),以及定义 VCS 编译和仿真选项。它还定义了一系列规则,如 VCS 编译规则、VCS 仿真规则、覆盖率融合规则、查看波形规则(如 Verdi)等。通过 Makefile,可以方便地进行编译、仿真和其他相关操作。
其次,程序编译和模拟器模块也有各自的脚本:编译脚本和模拟器脚本。
编译脚本(Compile Script):主要用于配置环境变量,并根据不同的程序类型(汇编、C等)调用相应的编译命令。它会生成反汇编文件,并将编译生成的 ELF 文件转换成二进制文件,再将二进制文件转换成十六进制(HEX)文件。同时,编译脚本会保存和打印编译结果的信息,包括错误信息等。
模拟器脚本(Simulator Script):主要用于配置环境,并根据传入的测试用例名称执行模拟器命令。它会根据预先协商好的标签解析出程序的起始比对地址和结束比对地址,然后执行模拟器,并保存和打印模拟器执行结果的信息,包括错误信息等。
再者,还有RISCV-DV指令生成器的调用脚本和回归管理脚本。
RISCV-DV指令生成器的调用脚本主要用于随机指令生成的配置参数和脚本调用。
回归脚本,为一种可以利用一键定时并行回归的脚本,用来自动化多进程回归测试流程,该脚本可以完成多个测试用例的并行回归测试,并将每个测试用例的仿真结果进行分析和汇总,生成一个日志文件,然后,将日志文件转换成可视化表格的形式,用于统计回归测试的情况,包括哪些测试用例被回归了,哪些测试用例失败,失败的原因是什么,单个测试用例的随机种子和仿真命令是什么等。通过这样的表格,可以方便地还原测试用例的现场,并进行高效的调试和分析。
另外还有RTL设计和参考模型日志文件进行比对的脚本,用于比对RTL硬件电路行为和参考模型模拟器行为是否一致。
模拟器模块3,包含模拟器系统和模拟器输出日志文件的参考模型资源库,以及模拟器调用脚本,该脚本使用SHELL语言编写。
项目管理脚本在需要使用模拟器时调用模拟器的执行脚本;模拟器脚本配置环境,根据传入的测试用例名称执行模拟器命令,它会根据预先协商好的标签解析出程序的起始比对地址和结束比对地址,然后执行模拟器,并保存和打印模拟器执行结果的信息,包括错误信息等。
仿真验证模块4,基于UVM(Universal Verification Methodology,通用的验证方法学) 框架构建,其各个子模块组件的也是继承于UVM的不同组件来实现。各个组件在UVM的UVM_ENV容器中进行连接和集成。UVM_ENV容器外还有不同的UVM_TEST,用于调用虚拟序列器动态生成用以描述不同的测试场景和测试用例的随机激励。本发明中,仿真验证模块4由DUT(被测对象,也即处理器内核)和将围绕DUT的所有验证组件集合在一起的UVM测试环境组成,UVM测试环境集成了各个UVM_AGENT(代理)和VIRTUAL_SEQUENCER(虚拟序列器)等组件,在UVM测试环境外还有用于创建和驱动测试用例UVM_TEST。
UVM_AGENT(代理)包括:
内核输出代理,用于接收和检测被测对象的信号变化和覆盖率的收集。包括:
(1)内核输出监测器,用于检测被测对象实时信号变化,并将关键信号的变化信息输出到被测对象信号监视输出的RTL仿真日志文件中,用于后续与模拟器输出日志文件进行比对。
(2)覆盖率监视器,用于检测模块级 DUT 的关键功能信号变化,并通过功能覆盖率组进行各种覆盖点的统计,从而完成功能覆盖率统计;主要实现方法是通过SystemVerilog语言定义一些Covergroup,描述要收集的覆盖率类型和属性;然后,声明Coverpoint,定义要收集的信号或属性的覆盖率信息;在仿真过程中,使用Covergroup实例收集覆盖率数据,监控Coverpoint所依赖信号的取值变化。
(3)性能检测器,用于检测被测对象中指令从执行级到写回级的周期数,以及指令流水线冲突时流水线停顿的类型和周期数,并将相关周期数信息输出到RTL仿真日志中,用于性能的分析。
中断代理,负责中断激励的生成和中断序列的产生。包括:
(1)中断接口(interrupt interfance),用于连接被测对象的各个中断信号接口和UVM测试环境。
(2)事务(transaction)对象,用于随机生成中断激励,例如软件中断、定时器中断、外部中断、不可屏蔽中断、调试中断、异常中断等。
(3)中断序列器(sequencer),用于生成中断测试序列流,管理中断测试序列流的执行顺序并传递给中断驱动器以进行驱动;不同类型的中断可以有不同的序列,也可以将多种中断组成在一起生成复杂的随机中断序列。
(4)中断驱动器(driver),用于向被测对象接口按照一定时序逻辑发送实时中断序列,这些中断序列由中断序列器进行控制并送往中断驱动器。
存储器代理,用于对关键存储器访问的读写进行检测,还负责与被测对象的存储器进行交互,发送读写请求并检查响应。在内核验证中,其主要功能之一是对握手协议中的签名地址(signature address)进行检测,通过签名地址完成内核与UVM测试环境的握手(handshake)交互,从而对内核的状态信息进行监测。
还有其他不同类型的代理(AGENT),如总线 AGENT、JTAG(Joint Test ActionGroup,是一种用于测试和调试集成电路的标准接口)AGENT等。这些不同的AGENT负责连接和监控对应的接口,并生成相应的事务。在实现上,主要以继承第三方库提供的类来构建环境,具体需要参考相应的 VIP(Verification IP,是指在硬件设计验证过程中使用的模块化验证组件)库官方文档进行构建的编写。
虚拟序列器(VIRTUAL_SEQUENCER)将面向不同序列器(例如中断序列器)的序列群挂接到不同序列器上,用于控制测试序列的生成。它协调多个virtual sequence (虚拟序列)的执行顺序和时机,以确保测试序列按照预期顺序执行。因此,虚拟序列器可以根据测试计划和测试需求生成特定的测试序列,从而实现对验证环境的全面测试。
虚拟序列器预定义了一系列的虚拟序列(sequence),例如中断序列,用于承载不同目标序列器的序列群落,挂载到虚拟序列器上。每个测试用例(test case)都可以包含一个或多个虚拟序列,并调用其中的函数来启动和管理控制测试序列的发生。通过调用虚拟序列中的函数,测试用例可以精确地控制测试序列的生成和执行,从而验证被测设备的不同功能和场景。
UVM_TEST,在UVM测试环境外部,用于创建和驱动测试用例(test case),通过模拟被测对象的各种场景来验证被测对象的行为。UVM_TEST首先设置测试环境的初始状态,然后启动和控制一个或多个虚拟序列来模拟特定的场景。它调用虚拟序列器的特定测试序列,测试序列是一系列事务的集合,通过驱动器组件向DUT发送对应的事务,通过监视器组件捕获和分析从DUT接收到的信息,将信息转换为事务传递再给测试序列进行验证。这些组件在UVM_TEST的启动和管理下共同工作,确保了在不同操作序列下,DUT 的功能能够被全面验证。
在本发明的验证系统中,使用基础测试类(BASE_TEST)来构建、连接和执行基础、共性的测试用例。该类包含一个运行阶段(run_phase)函数,用于测试用例的主要执行过程。此外,还有一些特定功能的函数,如发送刺激信号(send_test_stimulus)函数用于向被测对象发送测试刺激信号,等待存储器事务(wait_for_memory_transaction )函数用于等待被测对象的存储器事务,等待CSR写操作(wait_for_csr_write_operation )函数用于等待被测对象的CSR写操作,等待核心状态(wait_core_status)函数用于等待被测对象的状态,检查下一个核心状态(check_core_next_status)函数用于检查被测对象的下一个状态是否符合预期,最终阶段(final_phase)函数用于测试结束后的清理工作等。通过使用这些函数和基础测试类,可以方便地构建和执行测试用例,并对被测对象进行全面的验证。
除此之外,还有一个测试库(TEST_LIB),它继承扩展了 BASE_TEST测试库类,根据验证计划中的功能点进行更具体的测试函数定义。每个测试用例都可以继承这个测试库类,从而实现不同测试程序与测试环境的联动。
基于上述验证系统,执行指令测试时,TEST_LIB中的“加载程序”函数初始化处理器内核指令存储器,将二进制文件加载到指定的内存地址中,其中,对于不同的内存模型,需要使用不同的加载方法进行处理,具体方法根据具体情况进行分析;然后,内核取值译码执行程序来完成指令的测试;最后,调用"等待程序执行完成"函数,通过握手(handshake)来通知验证系统全部指令执行结束。同时, UVM TEST会执行其他测试事务,两者同时进行,完成整个验证的全部过程。
UVM_TEST有很多,本发明实施例中的UVM_TEST至少包括:
1.基本指令测试;包括:
等待全面内存空间和寄存器初始化;
加载二进制文件,写入到处理器内核的指定内存地址上;
等待全部指令在被测对象中被执行;
等待过程中,每一时钟周期(每一固定单位时间)通过调用“测试完成监测事件”,来监测某一特定内存地址上是否写入了标致着仿真结束的数据信息如:0x1234567f;
如果监测到该特定内存地址上被写入了0x1234567f,则结束UVM测试环境;
2.中断调试测试,一个基本的调试中断测试函数。用于验证调试和中断处理功能的基本正确性,模拟调试事件的发生和处理过程。包括:
(1)初始化UVM测试环境并设置相关的寄存器和变量。
(2)通过调用"发送中断调试激励信号"函数发送来自虚拟序列中的中断调试激励信号,触发中断调试事件。
(3)调用"等待中断调试事件"函数等待调试事件的处理完成,确保处理器内核正确进入了中断调试模式。
(4)调用"检查中断调试事件"函数检查调试事件处理状态,验证调试事件是否被正确处理,并检查相关寄存器和变量的值是否符合预期。这里是自我检测中断事件是否正确有效的关键。
在确认调试事件处理完毕后,(5)调用"结束中断调试刺激信号的发送"函数结束调试刺激信号的发送,并等待调试事件被清除。
(6)恢复UVM测试环境,包括相关的寄存器和变量,并清理测试环境,以准备下一轮测试。
最后,(7)调用基本测试中的" check_next_core_status "函数检测处理器是否退出中断调试状态,并确保内核恢复到正常运行模式。
通过执行这些步骤,"调试中断测试"函数可以验证系统在调试事件发生时的正确响应和处理能力,以及中断调试模式的进入和退出过程是否符合预期。
3.此外,还可设计若干适应不同功能场景的库函数,例如复位、安全域、低功耗、外部存储读写等。
比对检查模块5,主要用于对处理器设计RTL(Register Transfer Level,寄存器转换级电路)仿真日志文件,与模拟器输出日志文件进行加载和比对,检查仿真验证结果的正确性。
该系统可以让模拟器执行完毕后生成固定格式的模拟器输出日志。这些日志主要记录每条指令执行后写回到 RISC-V 寄存器的情况,或者寄存器的变化序列。可以根据设计的需求选择适当的输出格式。同时,在仿真环境中也生成与模拟器一致的日志文件,最后将模拟器日志文件和处理器设计 RTL(Register Transfer Level,寄存器转换级电路) 仿真日志文件进行自动比对,以验证设计的正确性。当模拟器不支持中断调试功能的验证时,验证系统可通过在RTL仿真日志的对应位置插中断调试开始和中断调试结束的标签;在比对的过程中,如果模拟器不支持中断调试功能,在比对时忽略中断调试开始和中断调试结束标签之间的全部指令PC的比对即可,不影响非特权功能的验证比对。
基于这种RTL仿真日志与模拟器输入日志的对比方式,本发明的验证系统可以减少对参考模型(如模拟器)的依赖,无论是周期精确的模拟器,还是功能全面的模拟器,还是功能不完整(例如不支持中断调试比对)的模拟,都可以通过本发明提出的修改,并利用一套完善的日志输出和比对方案来适配本系统。
回归管理模块6,在处理器修改或添加新功能后重新运行一系列测试用例,以确保修改不会对已验证通过的功能产生负面影响。主要通过回归管理脚本进行大规模随机并行回归,并将回归结果进行可视化展示。
本系统支持回归验证,当RTL代码进行修改后,进行全面的功能验证,保证修改的正确性。支持大规模指令随机仿真解决回归时指令随机程度低的问题,支持多用例并行回归解决仿真效率低的问题,同时将仿真资源独立化保证回归结果正确性,回归过程规范化。最后,使用了第三方开源工具Jenkins和可视化工具Grafana,以及mysql数据库,实现了整个回归过程的自动化和可视化。
首先,为了提高回归测试的质量,扩大单次回归的指令条数,增加测试的随机性,以覆盖更全面的测试场景。一方面利用处理器的外部存储空间,将大规模指令放在外部,并通过处理器从外部存储中获取指令执行,以实现单次仿真执行大规模指令,这样做可以增加测试的随机性和覆盖度。与此同时,结合使用指令生成器来生成大规模程序,进一步增加测试的随机性和多样性。另一方面,用RISCV-DV批量生成多个程序,从而增加仿真次数来增加测试的随机化效果。
当每个测试用例的指令数量变得非常大,且测试程序和仿真次数增多时,会面临回归测试效率的问题。为了解决这个问题,本发明充分利用仿真环境所在系统或服务器的硬件资源,实现并行执行多个测试用例的回归测试。基本思路是通过一次编译生成simv仿真文件,并利用这个仿真文件进行多次并行的回归仿真,以最大限度地节省编译和仿真时间,并充分利用硬件资源。在进行多进程的并行仿真时,需要确保构建系统能够将单次仿真的结果文件(如程序、hex文件、比对文件、日志文件等)相互隔离开,以保证多进程仿真过程中验证的正确性。
最后,为了使回归测试过程流程化和规范化,并减少重复工作,本发明利用一键定时并行回归的脚本来自动化多进程回归测试流程。该脚本可以完成多个测试用例的并行回归测试,并将每个测试用例的仿真结果进行分析和汇总,生成一个日志文件。然后,可以将日志文件转换成可视化表格的形式,用于统计回归测试的情况,包括哪些测试用例被回归了,哪些测试用例失败,失败的原因是什么,单个测试用例的随机种子和仿真命令是什么等。通过这样的表格,可以方便地还原测试用例的现场,并进行高效的调试和分析。
此外,通过 Jenkins工具以及Pipline插件来支持回归测试管理的自动化和持续集成。Jenkins提供了自动化构建、测试和部署回归流程的功能。通过配置JenkinsPipeline,可以定义和管理回归测试的整个流程。在Pipeline中,可以包含各种阶段,如构建、测试、部署等。通过编写Pipeline脚本,可以将回归测试的各个步骤自动化执行,并与版本控制系统(如Git)集成,以便在代码提交后自动触发回归测试流程。同时,使用grafana这样的可视化工具,可以将回归测试结果以图表形式展示,使得回归测试的数据更加可视化和易于理解。grafana可以与Jenkins集成,以实时更新并展示回归测试的结果和趋势。此外,为了保存回归测试的结果和相关数据,可以使用MySQL数据库或其他适合的数据库。通过将回归测试结果存储在数据库中,可以进行历史记录和数据分析,以及与其他团队成员共享和访问。
本发明上述提出的基于RISC-V架构的处理器验证系统,按照如下步骤实施验证:
步骤1:整个系统的启动开始于指令生成模块,通过激励生成脚本或者回归管理脚本,启动指令生成模块的运作。之后,激励生成脚本或者回归管理脚本的配置参数会传递到RISCV-DV的指令生成脚本中,从而根据仿真测试用例名、指令生成测试用例名、随机种子、生成汇编程序数量、每个汇编程序中指令的条数等一系列参数来生成一个或多个汇编程序。
步骤2:汇编程序生成后放置在程序编译模块的资源库中,仿真验证模块中的主脚本、项目管理脚本解析传入的参数和测试用例名称,并开始一系列构建工作,之后调用程序编译模块中的编译脚本执行编译器,对汇编文件进行编译、链接、反汇编、转二进制文件等一系列操作,最后将结果保存在独立的编译模块结果资源库中。
步骤3:编译结果资源库中的二进制文件,被模拟器模块中的脚本和仿真验证模块中的脚本同时调用,传人各自的模块中。模拟器在模拟器脚本的作用下开始模拟器的仿真,并输出模拟器输出日志文件;同时,仿真验证模块的Makefile也开始构建,并开始执行VCS编译和仿真命令;当仿真开始后,UVM测试环境外的UVM_TEST根据不同的测试用例调用不同的测试函数;对于指令的测试,先调用二进制文件加载函数,将二进制文件写入到处理器内核的指定内存地址上,同时将没有程序存放的地址和寄存器进行初始化,防止处理器运行时读取到没有初始化的不定态数据。
步骤4:在处理器内核仿真过程中,UVM_TEST直接作用于UVM测试环境中的各个组件,从而完成不同类型的功能测试。UVM测试环境实时与处理器内核进行交互,进行仿真验证,以及实时监测内核关键寄存器的信号变化,并记录成日志导出。同时,VCS编译仿真的日志文件,也会随之输出。在此过程中,如果使用回归管理脚本,进行回归验证,会批量进行测试用例的仿真和执行,并输出对应的仿真日志。
仿真的过程和实施方案将结合图2在下面的内容中详述。
步骤5:比对模块中的比对脚本加载模拟器输出日志和处理器的RTL仿真日志,然后进行比对,最后输出报告。该报告决定了仿真验证结果的成功与否。如果是回归验证,该报告中的关键信息被保存在数据库中。
如图2所示,在UVM测试环境中,首先会根据不同的UVM_TEST执行不同的测试或生成不同的测试序列。以中断测试为例,中断测试TEST会启动UVM测试环境中虚拟序列器中的序列生成任务,使中断代理中的中断序列器生成相关的随机序列,这些随机序列会在虚拟序列器中先被虚拟任务处理,然后被送到中断代理中的中断驱动器里被相关的任务所驱动,从而将随机序列直接作用于被测对象的中断信号接口上,从而完成处理器中断的随机生成。
处理器中的相关模块收到接口上的中断请求后开始进行中断相关处理,此时,内核输出代理中的监视器开始对处理器的行为(比如中断控制寄存器)的变化进行实时监控并将变化序列保存在相关序列中,直到仿真结束,再把队列中的变化序列转换成日志格式化文件输出,用于比对模块的比对。与此同时,内核输出代理中的覆盖率监视器开始收集内核仿真的覆盖率信息。
在内核仿真过程中,UVM_TEST库中的仿真结束检测任务会一直监视用于存储仿真结束状态的签名地址。一旦监测到内核进入仿真结束状态,整个仿真验证将强制结束。此时,会输出UVM仿真的日志文件、监视器用于比对的日志文件以及含有覆盖率信息的数据库文件。
下面基于上述给出的基于RISC-V架构的处理器验证系统,针对RISC-V架构的特性进行有效的中断调试验证,能够不依靠模拟器,由验证平台自身实施中断或调试验证,降低验证系统对模拟器设计的难度,提高对特权功能验证的灵活性。
上述可知,UVM测试环境的中断代理包括事务对象、中断接口中断序列器和中断驱动器,其中:
中断接口提供了一系列接口,用于连接UVM验证环境和被测对象,包含以下输入和输出信号:输入信号clk:时钟信号;输出信号reset、irq_software、irq_timer、irq_external、irq_nmi: reset为复位信号,用于将系统复位到初始状态;irq_software为软件中断请求信号;irq_timer为定时器中断请求信号;irq_external为外部中断请求信号;irq_nmi为非可屏蔽中断请求信号。
接着,中断代理提供了事务对象和中断序列器,用于生成和管理不同类型的中断请求序列。事务对象以一个名为 `irq_sequence_item` 的类实现,用于表示中断请求的属性和约束条件。`irq_sequence_item` 类继承自 `uvm_sequence_item`,是 UVM 序列项的子类,它定义了一些成员变量,包括 `irq_software`、`irq_timer`、`irq_external`、`irq_nmi` 和 `num_of_interrupt`,用于表示中断请求的类型和数量。这些成员变量使用`rand` 关键字进行声明,以便在随机化过程中生成随机的取值。约束条件部分,`irq_sequence_item` 类定义了两个约束条件:`num_of_interrupt_c` 约束条件限制了 `num_of_interrupt` 的取值范围,并且要求 `irq_software`、`irq_timer`、`irq_external`和 `irq_nm` 这些中断类型的总数等于 `num_of_interrupt` 的值;`define_const` 约束条件用于确保在特定情况下只生成一个特定类型的中断,只有在 `num_of_interrupt`等于 1 时中断才会被有效激活,即必须至少产生一种类型的中断。这两个约束条件保证了生成的 `irq_sequence_item` 对象的属性满足特定的要求,确保了生成的中断请求的类型和数量符合预期,并能满足测试需求。
中断序列器以一个基础的中断请求序列类 `core_base_seq`实现,用于生成随机化的中断请求,并控制其优先级和类型。它基于 UVM 框架,并提供了一些成员变量、约束条件和方法,使得中断请求的生成和发送变得灵活可控。首先,`core_base_seq` 类定义了一系列成员变量,包括 `irq_interval` 和 `irq_delay`,用于表示中断请求之间的随机时间间隔和延迟时间。`num_of_iterations` 表示循环发送中断请求的次数,而 `iteration_cnt` 则用于记录已发送的中断请求数量。`irq_max_interval` 和 `irq_max_delay` 则是时间间隔和延迟时间的最大值。其次,在约束条件方面,`core_base_seq` 类定义了两个约束条件:`irq_acceptable_interval_c` 和 `acceptable_delay_c`。这些约束条件确保了 `irq_interval` 和 `irq_delay` 的取值范围在合理的范围内。接下来,`core_base_seq` 类实现了三个主要方法。(1)`body()` 方法是序列的主体任务,通过循环发送中断请求,并根据停止条件判断是否终止序列。在每次循环中,调用 `send_req()`方法发送中断请求,并根据随机化的 `irq_interval` 和 `irq_delay` 值进行等待。当达到设定的循环次数或外部设置了停止标志时,循环终止。(2)`send_req()` 方法负责发送中断请求,并需要在派生类中进行具体的实现。在派生类中,可以根据需要随机化中断请求的类型和优先级,并通过调用 `start_item()`、`randomize_item()` 和 `finish_item()` 方法完成中断请求的生成和发送。(3)`stop()` 方法用于停止序列的执行。它设置了停止标志位,并等待序列完成,以确保所有中断请求都已发送完毕。
最后,`wait_seq_stop()` 方法用于等待序列的完成。它会一直等待,直到序列的`seq_finished` 标志位被设置为 1,表示序列执行完成。
此外,还定义了一些派生类,如 `irq_raise_seq`、`irq_raise_single_seq`、`irq_raise_nmi_seq` 和 `irq_drop_seq`,它们继承自 `irq_base_seq`,并通过重写 `randomize_item()` 方法来实现特定类型的中断请求的随机化。其中,irq_base_seq为基础中断请求序列类,包含中断请求的发送任务和随机化函数;irq_raise_seq为产生多个中断请求序列类,随机化中断请求的数量和类型,支持屏蔽和非屏蔽中断;irq_raise_single_seq为产生单个中断请求序列类,随机化中断请求的类型,仅支持单个中断请求;irq_raise_nmi_seq为产生非可屏蔽中断请求序列类,仅产生非可屏蔽中断请求; irq_drop_seq为取消中断请求序列类,随机化取消中断请求的数量和类型。
然后,还设计了中断请求中断驱动器,用于驱动中断请求信号。它包含以下任务和子任务,任务:wait_clks-等待指定数量的时钟周期,wait_neg_clks-等待指定数量的下降沿时钟周期;子任务:run_phase-执行中断驱动器的运行阶段,handle_reset-处理复位信号的任务,get_and_drive-获取并驱动中断请求的任务,reset_signals-复位信号的驱动任务,drive_seq_item-驱动中断请求信号的任务;drive_reset_value-将复位信号驱动为默认值的任务
中断序列器实现了一个名为 `irq_req_driver` 的 UVM 中断驱动器,用于驱动中断请求的发送和信号的驱动。它与上面提到的 `irq_sequence_item` 类一起使用,用于定义中断请求的属性。在 `irq_req_driver` 中,有许多UMV阶段:在 `build_phase` 阶段,通过调用 `uvm_config_db` 获取并设置虚拟接口 `vif`,用于驱动和DUT接口信号。在`run_phase` 阶段,使用 `fork-join` 结构创建两个并行执行的进程分支,第一个分支 `fork_with_isolation` 用于隔离中断驱动器的运行,以便在发生中途测试重置时进行处理,第二个分支 `drive_irq` 用于不断获取irq_sequence_item中断请求,并驱动信号并将相同的请求作为响应返回给序列。在 `get_and_drive` 任务中,使用 `seq_item_port.try_next_item()` 方法获取下一个中断请求,如果获取到请求,则创建相应的响应并调用 `drive_seq_item()` 方法驱动信号,并使用 `seq_item_port.item_done()` 表示请求处理完成,如果未获取到请求,则等待一个时钟周期。在 `handle_reset` 任务中,处理中途测试重置的情况,清除所有未完成的请求并重置信号。`reset_signals` 任务用于重置信号,并在重置信号上等待上升沿。`drive_seq_item` 任务用于将中断请求的属性驱动到虚拟接口 `vif` 的相应信号上。最后,`drive_reset_value` 任务将所有中断信号重置为低电平。
中断代理的实际实施过程,依赖于上述本发明提出的一种基于RISC-V架构的处理器验证系统中提到的UVM_TEST。UVM_TEST中有一个基类base_test,是一个UVM测试类,用于测试系统中的某个功能或模块,它是TEST_LIB的基类,里面描述了一些TEST_LIB中共同拥有的任务:
(1) `send_stimulus`任务:是`sc_base_test`类中的一个任务,用于向系统发送刺激信号。任务中使用`vseq.start(env.v_sqr)`来启动一个名为`vseq`的虚拟序列,将刺激信号发送到名为`env.v_sqr`的虚拟序列器。刺激信号的具体内容和发送方式可以根据测试需求进行定义和实现。本发明中,该任务主要用于中断序列激励的启动。
(2) `wait_for_memory_transaction`任务:用于等待系统的内存事务。任务中使用一个无限循环`forever`,不断检查接收到的内存事务是否满足预期条件。在循环中,通过`transaction_port .get(memory_transaction )`从名为`transaction_port `的FIFO中获取内存事务对象`memory_transaction `。然后,检查`memory_transaction `的地址、数据类型和读写类型是否与预期的值匹配。如果匹配成功,将相应的数据存储到`signature_data`(签名数据)中,并根据不同的数据类型执行相应的操作。如果匹配失败,继续等待下一个内存事务。该任务主要用于握手协议中,对写签名地址写操作事务的不断检查和接受。
(3) `wait_for_csr_write_operation`任务:用于等待对CSR寄存器的写操作。任务中使用`fork`语句并行执行两个任务。在第一个任务中,使用一个循环不断等待内存事务,并检查其中的地址是否与指定的CSR寄存器地址匹配。如果匹配成功,将对应的CSR寄存器地址和数据存储到`csr_addr`和`signature_data`中。在第二个任务中,使用一个定时器`repeat`来等待一定的周期数,如果超过指定的超时时间,则抛出错误信息表示未在超时期限内收到对CSR寄存器的写操作。使用`join_any`来等待任意一个任务完成,如果成功等到了对CSR寄存器的写操作,则禁用`fork`语句。该任务用于对CSR寄存器写操作的检测和接受,从而检测中断过程中,中断状态的实施变化情况,方便验证平台的自我检查。
(4) `wait_core_status`任务:用于等待系统核心的状态变化。任务中使用一个循环,通过`wait_for_memory_transaction`任务来等待特定的内存事务,其中指定了等待的地址和数据类型。在循环中,获取到对应的内存事务后,将其中的数据存储到`signature_data`中。如果获取到的数据与期望的核心状态相匹配,则表示达到了目标状态,任务结束。如果未达到目标状态,则继续循环等待下一个内存事务,直到达到目标状态或超过指定的超时时间。该任务用于对处理器内核状态相关寄存器写操作的检测和接受,从而检测中断过程中,中断状态的实时变化情况,方便验证平台的自我检查。
(5)`check_core_next_status`的任务:任务首先等待接收到内存写事务,并从中获取到内核状态数据。然后,它使用`DV_CHECK_EQ_FATAL`宏将接收到的状态数据与期望的核心状态进行比较。如果它们不相等,任务会输出错误消息并停止仿真。此外,代码包含一个`fork_with_isolation`的fork块,其中包含两个并行的块。第一个块用于等待超时或接收到核心状态数据。如果成功接收到数据,则使用`DV_CHECK_EQ_FATAL`宏进行比较,并在不相等的情况下输出错误消息。第二个块用于设置超时逻辑,通过在指定的超时时间内等待时钟上升沿来判断是否超时。如果超时时间到达而未收到核心状态数据,则输出错误消息并停止仿真。最后,使用`join_any`等待任意一个块完成,即收到核心状态数据或超时。如果成功收到核心状态数据且未超时,则禁用fork块后续的执行。整个任务的目标是确保在指定的超时时间内,能够正确接收到下一个内核的状态数据,并进行相应的验证,以便在仿真过程中进行错误检测和处理。该任务用于检查下一个处理器内核的状态是否符合预期,并进行自我检查。
以上具体任务的实现需要根据测试需求和环境进行调整和修改。
UVM_TEST中还有一个测试库(TEST_LIB),它继承扩展了 BASE_TEST测试库类,根据中断相关功能点进行更具体的测试函数定义。具体将在后面的内容中详述。
针对激励信号和中断调试激励生成随机化弱,限制了验证的随机性和覆盖范围的问题,本发明采用UVM测试环境和一系列UVM TEST来模拟各种中断调试场景。同时考虑到不同中断之间的仲裁以及异步中断、嵌套中断等复杂场景的验证。对于调试功能,本发明也考虑了不同的调试方式,如ebreak断点调试、ebreakm(EBREAK when mret)调试、单步调试等,从而实现对中断和调试功能的全面验证。
本发明摆脱了对模拟器中断调试功能的依赖,采用UVM验证环境自我检查的方法和handshake(握手机制),实现对中断和调试功能验证的比对。通过该方法,可以在独立的验证环境中进行中断调试功能的有效验证,解决了模拟器标准差异和建模困难带来的限制。
具体的,本发明采用的种握手机制为在中断处理程序中插入一些特定的签名代码或数据,作为中断发生的标识;然后,在UVM测试环境中,通过读取内存函数来检测签名地址中的数据,以判断处理器进入了何种状态、进行到了中断的哪一环节,并获取相关寄存器和数据的状态。通过这种方式,可以在UVM环境中进行断言和输出,验证中断的正确性和一致性。
这种握手机制不依赖于模拟器对中断调试比对的支持,而是通过在设计中插入标识和在验证系统中进行检测来实现中断状态的确认和验证,确保中断处理程序中的签名与验证系统中的检测逻辑保持一致非常重要,以确保正确的匹配和比对。根据具体需求,需要定义更复杂的数据交互和协议,以适应中断验证的要求。
本发明还定义了一系列中断调试自我检查的函数:
(1) `wait_core_setup()` 函数:等待内核设置完成。通过调用 `wait_for_csr_write_operation()` 函数等待对 CSR_MSTATUS 寄存器的写入操作完成。将 `signature_data` 赋值给 `core_init_mstatus`(内核初始化状态)。从 `core_init_mstatus` 的位 12 和位 11 中获取初始特权模式,并将其赋值给 `init_operating_mode`(内核初始特权模式)。再次调用 `wait_for_csr_write_operation()` 函数等待对CSR_MIE 寄存器的写入操作完成。将 `signature_data` 赋值给 `core_init_mie`(初始中断使能)。调用 `check_core_next_status()` 函数检查下一个内核的状态是否为INITIALIZED(初始状态),如果不是,则输出错误信息。
(2) `determine_irq_from_transaction ()` 函数:确定中断的 ID类型。创建变量 `irq_valid`(中断有效使能) 并初始化为 0。将 `irq_txn`(irq_sequence_item的实例化对象,序列中每种中断是否有效) 中的不同部分组合成 `irq`(32位),并输出 `irq`的值(irq = {irq_txn.irq_nm, 15'b0, 4'b0, irq_txn.irq_external, 3'b0, irq_txn.irq_timer, 3'b0, irq_txn.irq_software, 3'b0})。组成的依据是根据risc-v特权文档中mstatus寄存器的描述。之后,调用 `get_valid_interrupt_id()` 函数来确定中断 ID 的有效性,并将结果赋值给 `irq_valid`。最后将 `irq_id` 赋值给 `irq_last`并返回 `irq_valid`。注意,如果 `irq_id` 等于 31(是NMI不可屏蔽中断、异步中断),需要记录保存这次中断类型,用于中断嵌套的测试。
(3)`get_valid_interrupt_id()` 函数:确定中断 ID 的有效性。首先,创建变量`irq_valid` 并初始化为 0。判断 `irq_id` 是否小于 32,如果是,则将 `irq_id` 赋值给 `irq_valid`。之后,根据mstatus寄存器32位中不同类型中断的使能位进行判断,并将使能为索引返回 `irq_valid`,从而判断出中断的类型。要注意的是,由于不同中断有优先级,所以此处会根据优先级进行比较,返回优选级最高的中断类型索引。
(4)`send_irq_stimulus_inside()` 函数:解释中断刺激信号并处理。从 `interrupt_received_port`(irq_sequence_item队列) 获取中断事务信息并存储在 `irq_txn` 中。调用 `determine_irq_from_transaction ()` 任务确定中断事务`irq_txn`的有效性以及对多个中断进行仲裁,并将仲裁有效中断类型结果赋值给 `irq_valid`。 如果中断是可屏蔽的(同步的),并且在 MIE 的相应位未设置(中断使能关闭),将跳过下面的检查,并将中断线路置为低电平以避免死锁。如果MIE 的相应位已设置(中断使能开启)则调用 `validate_irq_handle()` 函数进行中断处理的一系列检查,如:mstatus、mcause、mie等。如果中断无效`irq_valid`为0,则调用 `vseq.start_irq_drop_seq()`函数开始处理中断信号的下拉(代表中断激励信号的消失)。再次从 `interrupt_received_port` 获取中断事务信息并存储在 `irq_txn` 中。调用 `determine_irq_from_transaction ()` 函数确定结束类中断的有效性,保证中断类型是无效的。
(5) `validate_irq_handle()` 函数:用于检查中断行为和中断处理程序的正确性。调用 `check_core_next_status()` 函数检查下一次接受到的内核的状态是否为HANDLING_IRQ(处理中断),如果不是,则输出错误信息。如果 `irq_id` 不等于 31(可屏蔽中断),则执行以下操作:
这段代码定义了一个名为`validate_irq_handle`的虚拟任务(virtual task)。该任务的作用是检查中断处理程序的正确性。
任务的主要逻辑如下:
a. 调用`check_core_next_status`任务,检查核心状态是否正确跳转到向量中断处理程序(HANDLING_IRQ)。如果不是,则输出错误消息,并在超过指定个时钟周期后报告超时错误。
b. 如果中断ID(irq_id)不等于31,表示不是非屏蔽中断,执行以下操作:首先等待CSR_MSTATUS寄存器的写入,超过指定个时钟周期后报告超时错误。然后读取并保存寄存器CSR_MSTATUS的值到变量mstatus变量。检查mstatus变量的特定位字段的值是否正确,例如mstatus.mpp的值应为2'b11,否则报告mpp状态错误。检查mstatus.MPIE位是否正确设置为1'b1。根据条件判断,mstatus.MPIE在从M模式触发陷阱时必须为1,除非irq_id等于31(即非屏蔽中断),否则报告错误。然后,输出mstatus的值,检查mstatus.mie是否为1'b0,如果不是,则报告错误。调用check_mcause任务,检查mcause(中断触发源)是否与中断ID匹配,等待CSR_MIE寄存器的写入,超过指定个时钟周期后报告超时错误。然后读取并保存寄存器CSR_MIE的值到变量mie。等待CSR_MIP寄存器的写入,超过指定个时钟周期后报告超时错误。之后,读取并保存寄存器CSR_MIP的值到变量mip。然后,检查mie的特定位是否为1'b1,如果不是,则报告致命错误。输出mip的值,检查mip的特定位是否为1'b1,如果不是,则报告错误。
c、如果中断ID(irq_id)等于31(不可屏蔽中断),执行以下操作:等待CSR_MNSTATUS寄存器的写入,超过指定个时钟周期后报告超时错误。读取并保存寄存器CSR_MNSTATUS的值到变量mnstatus。检查mnstatus的特定位字段的值是否正确,例如mnstatus.mie的值应为1'b0,否则报告错误。
由此可见,`validate_irq_handle`任务的作用是检查中断处理程序的执行情况,并对相关寄存器的值进行验证,确保中断的处理过程正确无误。此处可根据处理器中断调试验证需求进行增加或删除检查点。
(6)`check_mcause`的函数, 作用是检查mcause寄存器的值是否正确匹配给定的中断类型,以验证中断的处理是否按预期执行。首先定义变量mcause来保存mcause寄存器的值。其次调用`wait_for_csr_write_operation`任务,等待CSR_MCAUSE寄存器的写入,超过设定个时钟周期后报告超时错误。然后读取并保存寄存器CSR_MCAUSE的值到变量mcaus,并输出mcause的值。
最后使用比较函数断言,检查mcause的最高位(mcause.interrupt)是否与给定的irq_or_exc(中断还是异常)、匹配。如果不匹配,则报告错误。同时使用`DV_CHECK_EQ_FATAL`宏检查mcause的低31位(mcause.exception_code)是否与给定的cause匹配。如果不匹配,则报告错误。
(7)`wait_ret_raw`函数是一个等待xRET指令(mRET、dRET、mnRET)被断言的函数。首先根据传入的`ret`参数,使用`case`语句判断指令类型。如果`ret`为"dret",则等待`i_tdu_idu_instr_dret`信号被断言(等于1)。然后如果`ret`为"mret",则等待`i_tdu_idu_instr_mret`信号被断言(等于1)。然后如果`ret`为"mnret",则等待`i_tdu_idu_instr_mnret`信号被断言(等于1)。最后如果`ret`不匹配上述情况,则报告错误,指示指令类型无效。
(8)`wait_ret`任务是在一定周期内等待xRET指令被断言的任务,超过指定的超时时间将报告错误。首先在任务开始时使用`fork_with_isolation`和`join_any`创建了一个分支。其次在分支中的第一个子任务调用`wait_ret_raw`任务,等待xRET指令被断言。然后在分支中的第二个子任务(`ret_timeout`)使用延时指令等待指定的超时时间。最后,如果超时时间到达仍未检测到xRET指令的断言,则报告错误,指示超时期间没有检测到xRET指令或权限模式切换不正确。而如果在超时时间内成功检测到xRET指令的断言,则禁用分支,任务结束。
(9)`send_debug_stimulus`函数用于发送单个调试请求并执行所有相关的检查。首先可以与中断类似调用启动单个调试序列。其次调用`check_core_next_status`任务,等待核心状态变为"IN_DEBUG_MODE",并在超时时报告错误。然后使用`wait_for_csr_write_operation`等待CSR_DCSR寄存器的写入。
再然后调用`check_dcsr_privilege `函数,检查DCSR寄存器的权限模式是否为指定的模式。再者,调用`check_dcsr_cause`函数,检查DCSR寄存器的中断原因是否为指定的原因。最后调用`wait_ret`任务,等待"dret"指令的断言,超时时间为指定数量个周期。
(10)`check_dcsr_ebreak`函数用于检查DCSR寄存器的ebreak相关位。根据DCSR寄存器的权限模式,检查相应的ebreak位是否被设置。首先根据`signature_data[1:0]`(DCSR寄存器的权限模式),使用`case`语句判断权限模式。
如果权限模式为2'b11,检查`signature_data[15]`是否为1,报告错误"ebreakm未设置"。如果权限模式为2'b01,检查`signature_data[13]`是否为1,报告错误"ebreaks未设置"。如果权限模式为2'b00,检查`signature_data[12]`是否为1,报告错误"ebreaku未设置"。如果权限模式不匹配上述情况,则报告错误,指示不支持的权限模式
(11)`check_dcsr_cause`函数用于检查DCSR寄存器的中断原因。将给定的`cause`与`signature_data[8:6]`进行比较,如果不相等则报告错误"错误地更新了dcsr.cause(dcsr原因位)"。
(12)`check_dcsr_privilege `函数用于检查DCSR寄存器的权限模式。将给定的变量`mode`与`signature_data[1:0]`进行比较,如果不相等则报告错误"不正确的dcsr.prv值(dcsr特权位)"。
(13)`send_irq_stimulus_end()`函数:结束当前中断处理。检查是否处于退出中断状态,如果是则调用 `vseq.start_irq_drop_seq()` 函数开始处理中断信号的下拉(代表中断激励信号的消失)。再次从 `interrupt_received_port` 获取中断事务信息并存储在 `irq_txn` 中。调用 `determine_irq_from_transaction ()` 函数确定结束类中断的有效性,保证中断类型是无效的。之后,等待中断处理程序执行到xRET指令。
本发明对中断调试激励生成随机化,并采用UVM测试环境和一系列UVM_TEST来模拟各种中断调试场景;同时考虑到不同中断之间的仲裁以及异步中断、嵌套中断等复杂场景的验证;对于调试功能,本发明也考虑了不同的调试方式,如ebreak断点调试、ebreakm(EBREAK when mret)调试、单步调试等,从而实现对中断和调试功能的全面验证。
其中,对中断调试激励生成随机化的技术方案,以及部分测试函数,已经在上述内容中进行了说明。除此之外,TEST_LIB还有一些功能函数,用于模拟测试中断调试的不同场景:
(1) `riscv_multiple_irq_test` 测试:用于实现多个中断的测试场景。它包含了 `send_stimulus()` 和 `send_irq_stimulus_start()` 两个任务。`send_stimulus()` 任务,首先它通过启动中断序列器来开始发送中断激励。接下来,使用了 `forever`循环来不断触发中断。`send_irq_stimulus_start()` 任务在保护点二中已经说明,此处不同之处是通过向该任务传递不同的参数,比如是否允许nmi中断、指定产生单个还是多个中断请求序列等,从而实现多个中断同时产生,需要进行仲裁的场景。
(2)`riscv_irq_instr_test` 测试:用于模拟在内核的指令译码阶段观察到每个唯一(且支持的)RISC-V指令后发送中断刺激的测试场景。该测试使用了 `forever` 循环,持续执行以下步骤:
a.等待直到在流水线的指令译码阶段看到一个有效指令或核心进入睡眠状态。
b.如果内核进入睡眠状态,则发送中断激励以唤醒内核。
c.否则,检查当前指令是否是压缩指令。如果是压缩指令,则调用 `decode_compressed_instruction` 函数进行译码,并在译码成功时发送中断刺激。
d.如果不是压缩指令,则调用 `decode_instruction` 函数进行译码,并在译码成功时发送中断刺激。
e.最后,等待一定数量的时钟周期,进入下次循环。
其中`decode_compressed_instruction`和`decode_instruction`函数是根据指令集编码规范,对不同指令进行译码和分类。
(3)`riscv_nested_interrupt_test` 测试: 用于实现嵌套中断测试场景。该测试使用了 `forever` 循环,持续执行以下步骤:
a.调用 `send_irq_stimulus_start` 任务,发送第一个中断刺激,并通过 `valid_irq` 返回中断是否有效。
b.如果收到有效中断,则执行以下操作:设置 `initial_irq_delay` 为嵌套中断的延迟。将 `irq_raise_nmi_seq_h.irq_max_delay` 设置为 0,暂时禁用嵌套中断。设置`in_nested_trap` 为 1,表示当前处于嵌套中断的处理中。发送 NMI 中断刺激,调用 `send_nmi_stimulus()`。恢复 `irq_raise_nmi_seq_h.irq_max_delay` 的初始值。设置`in_nested_trap` 为 0,表示嵌套中断处理结束。调用 `send_irq_stimulus_end()` 结束当前中断处理。
c.在每个循环迭代之间等待一段时间。
(4)`debug_ebreak_test` 测试: 用于实现 ebreak 调试测试场景。首先,调用 `start_debug_single_seq()`,启动单步调试序列。然后,调用 `check_core_next_status()` 检查内核是否正确进入调试模式。然后,等待 CSR_DCSR 的写入(通过 `wait_for_csr_write_operation(CSR_DCSR)`),并将写入的值存储在 `dcsr` 变量中。之后,调用 `check_dcsr_privilege ()` 和 `check_dcsr_cause()` 检查 `dcsr` 的权限级别和触发的原因。然后,等待 ` i_tdu_idu_instr_ebreak` (内核ebreak触发信号)为 1,表示ebreak 指令被执行。最后,延迟一定量的时钟周期后,比较第二次对 CSR_DCSR 和 CSR_DPC 的写入与之前保存的值(`dcsr` 和 `dpc`)是否一致,然后延迟一定长度时间单位,进入下一测试。
(5)`riscv_debug_ebreak_m_s_u_test`测试:用于实现具有设置 `dcsr.ebreak(m/s/u)` 的调试 ebreak 测试场景。它包含了 `send_stimulus()` 和 `check_stimulus()` 任务。
`send_stimulus()`任务使用了 `fork-join` 结构,包括两个并行的子任务: `detect_ebreak` 子任务等待 ` i_tdu_idu_instr_ebreak` 信号为 1,表示 ebreak 指令被执行,并且 ` o_tdu_csr_mstatus_wr` 信号为 0,表示没有写入 mstatus 寄存器。一旦检测到 ebreak 指令被执行,将 `seen_ebreak` 置为 1。`run_stimulus` 子任务调用`send_stimulus()` 方法,发送调试激励。
`check_stimulus()`任务使用了 `fork-join` 结构,包括两个并行的子任务:`dbg_setup` 子任务在内核初始化后发送单个调试请求以配置 `dcsr`。首先调用 `start_debug_single_seq()` 启动单步调试序列,并使用 `check_core_next_status()` 检查内核是否进入调试模式。然后等待 CSR_DCSR 的写入,并通过 `check_dcsr_privilege()` 检查 `dcsr` 的权限级别。如果不是第一次调试,则调用 `check_dcsr_ebreak()`和 `check_dcsr_cause()` 检查 `dcsr` 的 ebreak 位和触发的原因。最后,等待 `dret` 信号表示调试会话结束。`detect_ebreak` 子任务:等待 `i_tdu_idu_instr_ebreak`信号为 1,并且 `o_tdu_csr_mstatus_wr` 信号为 0。一旦检测到 ebreak 指令被执行,发出检查错误提示。
该测试场景通过发送调试请求和检查相关寄存器的设置来验证在调试模式下设置dcsr.ebreak(m/s/u)的功能。它还检测并报告ebreak指令的执行情况,以及是否成功进入和退出调试会话。
(6)`riscv_debug_single_step_test` 测试实现了一个功能测试场景,用于测试单步调试功能。
首先,创建一个名为 `event` 的事件,用于在系统停止单步调试时触发。并行执行两个子任务:第一个子任务使用 `forever` 循环,监听 `o_tdu_idu_debug_mode`(进入调试模式) 信号的下降沿。该信号表示系统是否处于调试模式。在每次循环中,通过计数器`counter` 记录系统不处于调试模式的周期数,并在计数达到指定的 `debug_mode_end_dwell_cycles` 值时,触发事件 `event`。其中,`debug_mode_end_dwell_cycles` 是一个配置参数,用于指定系统停止单步调试后等待的周期数。它的作用是为了确保系统已经稳定退出单步调试模式,避免在不稳定的状态下发送下一个单步调试请求。第二个子任务使用 `forever` 循环,间隔一定周期发送单步调试请求。在每次循环中,先等待事件 `event` 被触发,即系统停止单步调试,然后发送单步调试请求。
测试场景的目的是测试单步调试功能是否正常工作。它通过监听调试模式信号的状态,计算系统处于非调试模式的周期数,并在系统停止单步调试时触发事件。然后,在触发事件后发送单步调试请求,以验证单步调试功能是否按预期工作。
针对模块化验证方法难以模拟不同场景下的大量随机指令执行状态,从而限制了对处理器架构和微架构相关问题的发现的问题。本发明将中断调试验证系统集成在上述提出的基于RISC-V架构的内核验证系统中,实现内核指令功能验证的同时进行中断调试验证。通过集成验证系统,可以在不同场景下模拟大量随机指令执行状态,从而全面验证处理器架构和微架构的正确性。通过该集成验证系统,本发明能够发现和解决与处理器架构和微架构相关的问题。
结合上述内容,本发明将中断调试验证系统集成在上述提出的一种基于RISC-V架构的处理器验证系统中,实现内核指令功能验证的同时进行中断调试验证。通过集成验证系统,可以在不同场景下模拟大量随机指令执行状态,从而全面验证处理器架构和微架构的正确性。同时,在在指令执行的过程中可以通过在指令流中插入一系列握手指令来实现握手协议,从而满足了自我检查功能在交互上的实现。通过该集成验证系统,本发明能够发现和解决与处理器架构和微架构相关的问题。
下面以多个中断的测试场景为例,说明本验证系统的具体实施方式和流程,结合图3所示,包括:
步骤1:通过传入测试用例的参数名字,调用RISCV-DV的指令生成脚本,生成随机指令流,对RISCV-DV生成器中的配置参数进行配置,使生成的随机指令流中包含,用于不同中断的中断处理程序,这些程序中包含中断测试所需要的握手数据(握手代码段),这些握手代码段通过签名地址传递当前状态相关的处理器信息、控制状态寄存器信息、通用寄存器信息、处理器内核状态信息。通过这些握手信息,可以使处理器向验证环境传递中断测试所需要的信息,比如:是否已经进入中断、进入中断后各寄存器值变化是否正确、是否执行到了中断处理程序的结束(用于终止中断请求),是否执行到xRET指令并重新进入正常指令执行模式等。
步骤2:程序编译加载到处理器;其执行过程与上述提出的一种基于RISC-V架构的处理器验证系统的一致。
这里重点说明多个中断测试的UVM_TEST的具体实施流程:首先,`riscv_multiple_irq_test` 测试被调用,开始执行 `send_stimulus()` 任务,启动中断序列器。
步骤3:通过virtual sequence里的虚函数来启动中断序列器,虚函数初始化中断请求序列类`core_base_seq` 中的参数,比如: `irq_interval` 、 `irq_delay`,用于表示中断请求之间的随机时间间隔和延迟时间,`num_of_iterations` 表示循环发送中断请求的次数, `iteration_cnt`用于记录已发送的中断请求数量,`irq_max_interval` 和 `irq_max_delay` 表示时间间隔和延迟时间的最大值等。由于是多个中断的测试,因此随后调用`irq_raise_seq`派生类,并约束随机化中断请求的数量和类型,是否支持屏蔽和非屏蔽中断,来满足多个中断测试的场景。紧接着,执行一系列请求函数,完成中断请求的生成和发送。
步骤4: `irq_req_driver`中断请求中断驱动器开始工作,不断获取irq_sequence_item中断请求;如果获取到请求,则创建相应的响应并驱动信号,将中断请求的属性驱动到DUT接口 `vif` 的相应信号上,并持续获取下一个中断请求;如果未获取到请求,则等待一个时钟周期,从而完成中断激励的产生。由于是多个中断测试,此处会对irq_sequence_item中的`num_of_interrupt`进行约束,使他至少产生两种中断。
步骤5:使用`forever` 循环来不断触发中断。`send_irq_stimulus_start()` 任务在传递不同的参数,比如,是否允许nmi中断、指定产生单个还是多个中断请求序列等,从而实现多个中断同时产生,需要进行仲裁的场景。
步骤6:调用`send_irq_stimulus_inside()` 任务:获取中断事务信息并存储在`irq_txn` 中。调用 `determine_irq_from_transaction ()` 任务确定中断事务`irq_txn`的有效性以及对多个中断进行仲裁,并将仲裁有效中断类型结果赋值给 `irq_valid`。 如果中断是可屏蔽的(同步的),并且在 MIE 的相应位未设置(中断使能关闭),将跳过下面的检查,并将中断线路置为低电平以避免死锁。如果MIE 的相应位已设置(中断使能开启)则调用 `validate_irq_handle()` 函数进行中断处理的一系列检查,如:mstatus、mcause、mie等。如果中断无效`irq_valid`为0,则调用 `vseq.start_irq_drop_seq()`函数开始处理中断信号的下拉(代表中断激励信号的消失)。再次从 `interrupt_received_port` 获取中断事务信息并存储在 `irq_txn` 中。调用 `determine_irq_from_transaction ()` 函数确定结束类中断的有效性,保证中断类型是无效的。
步骤7:如果`irq_valid`不为0,调用 `send_irq_stimulus_end()` 结束当前中断处理。检查是否处于退出中断状态,如果是则调用 `vseq.start_irq_drop_seq()` 函数开始处理中断信号的下拉(代表中断激励信号的消失)。再次从 `interrupt_received_port` 获取中断事务信息并存储在 `irq_txn` 中。调用 `determine_irq_from_transaction ()` 函数确定结束类中断的有效性,保证中断类型是无效的。之后,等待中断处理程序执行到xRET指令。
后续相关实施方法和流程与上述提出的一种基于RISC-V架构的处理器验证系统的一致。
应该指出的是,上述说明并非是对本发明的限制,本发明也并不仅限于上述举例,本技术领域的普通技术人员在本发明的实质范围内所做出的变化、改型、添加或替换,也应属于本发明的保护范围。
Claims (10)
1.一种基于RISC-V架构的随机中断调试验证系统,其特征在于,包括:
指令生成模块,为程序生成部分,生成包含随机指令流的汇编程序;其中,在中断随机指令中加入以若干条存储指令结束的握手数据,以实现基于存储指令将握手数据存储到指定的签名地址;
程序编译模块,包括汇编程序所用到的编译器、连接器和反汇编器、编译所生成的结果文件资源库、以及验证系统的编译工具调用脚本;
仿真验证模块,包括UVM测试环境、被测对象和UVM_TEST,以及用于构建、控制和管理仿真的主脚本、项目管理脚本和Makefile;所述UVM测试环境由UVM代理和虚拟序列器组成;所述UVM_TEST调用虚拟序列器动态生成用以描述中断测试场景和测试用例的随机中断激励;所述UVM代理包括内核输出代理和中断代理;所述内核输出代理包括内核输出监测器,用于监测签名地址的写入操作,将写入操作的相关信息传输到UVM测试环境,以使UVM测试环境接收到签名地址上的相关信息后,执行对应的中断测试事务或比对操作,以及,检测被测对象实时信号变化,并将关键信号的变化信息输出到被测对象信号监视输出的RTL仿真日志文件中;
所述系统在指令生成模块中引入握手数据枚举类型,包括用于表示握手数据中的签名类型的signature_type_t枚举类型和用于表示处理器核心的不同状态的core_status_t枚举类型;所述握手数据将信息从被测对象传递到仿真验证模块的UVM测试环境中,并在验证过程中进行分析和比对操作;
所述中断代理包括事务对象、中断接口、中断序列器和中断驱动器;其中,所述事务对象用于随机生成随机中断激励;所述中断接口用于连接被测对象的各个中断信号接口和所述UVM测试环境;所述中断序列器用于生成中断序列流,管理测试序列流的执行顺序并将序列流传递给中断驱动器以进行驱动;所述中断驱动器用于向被测对象接口按照设定时序逻辑发送所述中断序列流;
所述UVM_TEST包括通过调用基础测试类和设定功能函数实施中断或调试功能验证的中断调试测试,包括:
初始化UVM测试环境并设置相关的寄存器、配置参数和变量;
通过调用发送中断调试激励信号函数调度虚拟序列中的中断序列,来发送各类中断或调试激励信号,触发中断或调试事件;
调用等待中断调试事件函数等待中断或调试事件的触发完成,确保处理器内核从正常模式正确进入了调试模式,开始执行中断调试处理程序;
调用检查中断调试事件函数检查中断或调试事件的处理状态,验证中断或调试事件是否被正确处理,并检查相关寄存器和变量的值是否正确;
在确认中断或调试事件处理完毕后,调用结束中断调试刺激信号的发送函数结束中断或调试刺激信号的发送,并等待中断或调试事件被清除;
最后,恢复UVM测试环境,并检查处理器内核返回中断或调试前的正常模式,同时检查相关的寄存器和变量是否符合预期变化,并清理测试环境,之后继续保持指令在被测对象中被执行,以准备下一轮测试。
2.根据权利要求1所述的基于RISC-V架构的随机中断调试验证系统,其特征在于,所述验证系统采用握手机制实现中断或调试功能验证,包括:
在中断处理程序中插入中断发生和中断结束退出的标识;
在UVM测试环境中,读取内存函数检测签名地址中的数据;
根据读取的数据判断处理器内核进入了何种状态,以及进入到中断的哪个环节,以及获取相关寄存器和数据的状态。
3.根据权利要求1所述的基于RISC-V架构的随机中断调试验证系统,其特征在于,所述事务对象以一个名为 irq_sequence_item的类实现,用于表示随机中断请求和属性; irq_sequence_item类继承自UVM 序列项的子类uvm_sequence_item,定义用于表示中断请求类型和数量的成员变量irq_software、irq_timer、irq_external、irq_nmi和 num_of_interrupt;所述成员变量使用 rand关键字进行声明,以便在随机化过程中生成随机的取值;为irq_sequence_item类定义两个约束条件:num_of_interrupt_c用于限制num_of_interrupt的取值范围,并且要求 irq_software、irq_timer、irq_external和 irq_nm的总数等于 num_of_interrupt的值;define_const用于确保在特定情况下只生成一个特定类型的中断,只有在 num_of_interrupt等于 1 时中断才会被有效激活,用于产生单中断激励场景。
4.根据权利要求1所述的基于RISC-V架构的随机中断调试验证系统,其特征在于,所述中断序列器以中断请求序列类core_base_seq实现,用于生成随机化的中断请求,并控制其优先级和类型;定义用于表示中断请求之间的随机时间间隔和延迟时间的成员变量irq_interval和irq_delay;为core_base_seq类定义约束条件irq_acceptable_interval_c和irq_acceptable_delay_c,确保 irq_interval和 irq_delay的取值范围;实现方法body()、send_req()、stop()和wait_seq_stop();其中,body() 方法是序列的主体任务,通过循环发送中断请求,并根据停止条件判断是否终止序列;在每次循环中,send_req()方法负责发送中断请求,并随机化的irq_interval和 irq_delay值进行等待,当达到设定的循环次数或外部设置了停止标志时,循环终止;send_req()方法在派生类中进行具体的实现,在派生类中,根据需要随机化中断请求的类型和优先级,通过调用start_item()、randomize_item()和 finish_item()方法完成中断请求的生成和发送;stop()方法用于停止序列的执行,其设置了停止标志位,并等待序列完成,以确保所有中断请求都已发送完毕;wait_seq_stop()方法用于等待序列的完成直到序列的seq_finished标志位被设置为1,表示序列执行完成。
5.根据权利要求4所述的基于RISC-V架构的随机中断调试验证系统,其特征在于,所述中断序列器通过继承irq_base_seq定义了如下派生类:irq_raise_seq、irq_raise_single_seq、irq_raise_nmi_seq和irq_drop_seq,并通过重写 randomize_item()方法来实现特定类型的中断请求的随机化;其中,irq_base_seq为基础中断请求序列类,包含中断请求的发送任务和随机化函数;irq_raise_seq用于产生多个中断请求序列类,随机化中断请求的数量和类型,支持屏蔽和非屏蔽中断;irq_raise_single_seq用于产生单个中断请求序列类,随机化中断请求的类型,仅支持单个中断请求;irq_raise_nmi_seq用于产生非可屏蔽中断请求序列类,仅产生非可屏蔽中断请求;irq_drop_seq用于取消中断请求序列类,用于取消中断请求信号的拉高,即不再发送中断请求。
6. 根据权利要求1所述的基于RISC-V架构的随机中断调试验证系统,其特征在于,所述中断驱动器包含任务wait_clks和wait_neg_clks,以及包含子任务run_phase、handle_reset、get_and_drive、reset_signals、drive_seq_item和drive_reset_value; wait_clks表示等待指定数量的时钟周期,wait_neg_clks表示等待指定数量的下降沿时钟周期;run_phase表示执行驱动器的运行阶段,handle_reset表示处理复位信号的任务,get_and_drive表示获取并驱动中断请求的任务,reset_signals表示复位信号的驱动任务,drive_seq_item表示驱动中断请求信号的任务,drive_reset_value表示将复位信号驱动为默认值的任务;
所述中断驱动器以名为irq_req_driver的类实现,用于驱动中断请求的发送和信号的驱动,与事务对象对应的类一起使用,用于定义中断请求的属性;所述irq_req_driver包括以下UVM阶段:
build_phase阶段:通过调用 uvm_config_db获取并设置虚拟接口vif,用于驱动和被测对象接口信号;
run_phase阶段,使用fork-join结构创建两个并行执行的进程分支,分支 fork_with_isolation用于隔离中断驱动器的运行,以便在发生中途测试重置时进行处理,第二个分支drive_irq用于不断获取irq_sequence_item中断请求,并驱动信号并将相同的请求作为响应返回给序列;
get_and_drive任务,使用seq_item_port.try_next_item()方法获取下一个中断请求,如果获取到请求,则创建相应的响应并调用drive_seq_item()方法驱动信号,并使用seq_item_port.item_done()表示请求处理完成;如果未获取到请求,则等待一个时钟周期;
handle_reset任务,处理中途测试重置的情况,清除所有未完成的请求并重置信号;
reset_signals任务,用于重置信号,并在重置信号上等待上升沿;
drive_seq_item任务,用于将中断请求的属性驱动到虚拟接口vif的相应信号上;
drive_reset_value任务,将所有中断信号重置为低电平。
7.根据权利要求1所述的基于RISC-V架构的随机中断调试验证系统,其特征在于,所述中断调试测试采用UVM_TEST中的基类BASE_TEST中的任务进行中断测试,包括:
采用send_stimulus任务向验证系统发送刺激信号;任务中使用vseq.start(env.v_sqr)来启动一个名为vseq的虚拟序列,将中断刺激信号发送到名为env.v_sqr的虚拟序列器;
采用wait_for_memory_transaction任务等待系统的内存事务;任务中使用一个无限循环forever不断检查接收到的内存事务是否满足预期条件;在循环中,通过transaction_port.get(memory_transaction )从名为transaction_port的FIFO中获取内存事务对象memory_transaction,然后检查memory_transaction的地址、数据类型和读写类型是否与预期的值匹配,如果匹配成功,将相应的数据存储到签名数据signature_data中,并根据不同的数据类型执行相应的操作,如果匹配失败,继续等待下一个内存事务;
采用wait_for_csr_write_operation任务等待对CSR寄存器的写操作;任务中使用fork语句并行执行两个任务;在第一个任务中,使用一个循环不断等待内存事务,并检查其中的地址是否与指定的CSR寄存器地址匹配,如果匹配成功,将对应的CSR寄存器地址和数据存储到csr_addr和signature_data中;在第二个任务中,使用一个定时器repeat来等待设定的周期数,如果超过指定的超时时间,则抛出错误信息表示未在超时期限内收到对CSR寄存器的写操作;使用join_any来等待任意一个任务完成,如果成功等到了对CSR寄存器的写操作,则禁用fork语句;
采用wait_core_status任务等待系统核心的状态变化;任务中使用一个循环,通过wait_for_memory_transaction任务来等待特定的内存事务,其中指定了等待的地址和数据类型;在循环中,获取到对应的内存事务后,将其中的数据存储到signature_data中,如果获取到的数据与期望的核心状态相匹配,则表示达到了目标状态,任务结束;如果未达到目标状态,则继续循环等待内存事务,直到达到目标状态或超过指定的超时时间;
采用check_core_next_status任务等待接收内存写事务,并从中获取到内核状态数据;然后使用比较断言将接收到的状态数据与期望的核心状态进行比较;如果不相等,任务会输出错误消息并停止仿真;以及,代码包含一个fork_with_isolation的fork块,其中包含两个并行的块,第一个块用于等待超时或接收到核心状态数据,如果成功接收到数据,则使用比较断言进行比较,并在不相等的情况下,断言错误并输出错误消息;第二个块用于设置超时逻辑,通过在指定的超时时间内等待时钟上升沿来判断是否超时,如果超时时间到达而未收到核心状态数据,则输出错误消息并停止仿真;最后,使用join_any等待任意一个块完成,即收到核心状态数据或超时,如果成功收到核心状态数据且未超时,则禁用fork块后续的执行。
8.根据权利要求7所述的基于RISC-V架构的随机中断调试验证系统,其特征在于,所述中断调试测试还根据中断调试场景和中断调试功能,采用UVM_TEST中的TEST_LIB测试库定义了以下测试函数:
riscv_multiple_irq_test测试,用于实现多个中断的测试场景,包含send_stimulus()和send_irq_stimulus_start()两个任务; send_stimulus()任务中,首先通过启动中断序列器来开始发送中断激励,接着使用forever循环来不断触发中断; send_irq_stimulus_start()用于发送中断刺激信号,通过向其传递不同的参数来实现多个中断同时产生,需要进行仲裁的场景;
riscv_irq_instr_test 测试,用于模拟在内核的指令译码阶段观察到每个唯一且支持的RISC-V指令后发送中断刺激的测试场景;其使用了forever循环,持续执行以下步骤:
等待直到在流水线的指令译码阶段看到一个有效指令或核心进入睡眠状态;
如果内核进入睡眠状态,则发送中断激励以唤醒内核;否则,检查当前指令是否是压缩指令,如果是压缩指令,则调用 decode_compressed_instruction函数进行译码,并在译码成功时发送中断刺激;
如果不是压缩指令,则调用decode_instruction函数进行译码,并在译码成功时发送中断刺激;
最后,等待一定数量的时钟周期,进入下次循环;
其中,decode_compressed_instruction和decode_instruction函数是根据指令集编码规范,对不同指令进行译码和分类,覆盖全部指令前触发中断的场景;
riscv_nested_interrupt_test测试,用于实现嵌套中断测试场景;其使用了forever循环,持续执行以下步骤:
调用send_irq_stimulus_start任务,发送第一个中断刺激,并通过valid_irq 返回中断是否有效;
如果收到有效中断,则执行以下操作:设置initial_irq_delay为嵌套中断的延迟,将irq_raise_nmi_seq_h.irq_max_delay设置为0,暂时禁用嵌套中断;设置in_nested_trap为 1,表示当前处于嵌套中断的处理中;发送 NMI 中断刺激,调用send_nmi_stimulus()恢复 irq_raise_nmi_seq_h.irq_max_delay的初始值;设置in_nested_trap为 0,表示嵌套中断处理结束;调用send_irq_stimulus_end()结束当前中断处理;
在每个循环迭代之间等待设定时间;
debug_ebreak_test测试:用于实现 ebreak 调试测试场景;首先,调用 start_debug_single_seq()启动单步调试序列;接着调用check_core_next_status()检查内核是否正确进入调试模式;然后通过wait_for_csr_write_operation等待CSR_DCSR 的写入,并将写入的值存储在dcsr变量中;之后,调用check_dcsr_privilege ()和 check_dcsr_cause()检查dcsr的权限级别和触发的原因;等待内核ebreak触发信号i_tdu_idu_instr_ebreak为1,表示 ebreak 指令被执行;最后,延迟设定量的时钟周期后,比较第二次对 CSR_DCSR 和CSR_DPC 的写入与之前保存的dcsr和dpc值是否一致,然后延迟一定长度时间单位,进入下一测试;
riscv_debug_ebreak_m_s_u_test测试:用于实现具有设置dcsr.ebreak(m/s/u)的调试 ebreak 测试场景;其包含send_stimulus()和check_stimulus()任务;send_stimulus()任务使用了 fork-join结构,包括两个并行的子任务:detect_ebreak子任务等待i_tdu_idu_instr_ebreak信号为 1,表示 ebreak 指令被执行,并且o_tdu_csr_mstatus_wr信号为 0,表示没有写入 mstatus 寄存器;一旦检测到 ebreak 指令被执行,将 seen_ebreak置为 1;run_stimulus子任务调用send_stimulus()方法,发送调试激励; check_stimulus()任务使用了fork-join结构,包括两个并行的子任务:dbg_setup子任务在内核初始化后发送单个调试请求以配置 dcsr;首先调用 start_debug_single_seq()启动单步调试序列,并使用check_core_next_status()检查内核是否进入调试模式;然后等待CSR_DCSR 的写入,并通过check_dcsr_privilege ()检查 dcsr的权限级别,如果不是第一次调试,则调用 check_dcsr_ebreak()和check_dcsr_cause()检查dcsr的 ebreak 位和触发的原因;最后,等待dret信号表示调试会话结束; detect_ebreak子任务等待i_tdu_idu_instr_ebreak信号为 1,并且o_tdu_csr_mstatus_wr信号为 0,一旦检测到 ebreak指令被执行,发出检查错误提示;所述测试场景通过发送调试请求和检查相关寄存器的设置来验证在调试模式下设置dcsr.ebreak(m/s/u)的功能,检测并报告ebreak指令的执行情况,以及是否成功进入和退出调试会话;
riscv_debug_single_step_test测试:实现了一个功能测试场景,用于测试单步调试功能;首先,创建一个名为 event的事件,用于在系统停止单步调试时触发;并行执行两个子任务:第一个子任务使用 forever循环,监听进入调试模式o_tdu_idu_debug_mode信号的下降沿,所述信号表示系统是否处于调试模式;在每次循环中,通过计数器counter记录系统不处于调试模式的周期数,并在计数达到指定的debug_mode_end_dwell_cycles值时,触发事件 event;其中,debug_mode_end_dwell_cycles是一个配置参数,用于指定系统停止单步调试后等待的周期数;第二个子任务使用forever循环,间隔一定周期发送单步调试请求,在每次循环中,先等待事件event被触发,即系统停止单步调试,然后发送单步调试请求;所述测试场景用于测试单步调试功能是否正常工作,通过监听调试模式信号的状态,计算系统处于非调试模式的周期数,并在系统停止单步调试时触发事件,然后在触发事件后发送单步调试请求,以验证单步调试功能是否按预期工作。
9.根据权利要求2所述的基于RISC-V架构的随机中断调试验证系统,其特征在于,所述UVM_TEST中定义了如下的中断调试自我检测的函数:
wait_core_setup()函数,用于等待内核设置完成;通过调用 wait_for_csr_write_operation ()函数等待对 CSR_MSTATUS 寄存器的写入操作完成;将 signature_data赋值给内核初始化状态core_init_mstatus;从core_init_mstatus的位 12 和位 11 中获取初始特权模式,并将其赋值给内核初始特权模式init_operating_mode;再次调用wait_for_csr_write_operation()函数等待对 CSR_MIE 寄存器的写入操作完成,将signature_data赋值给初始中断使能core_init_mie;调用check_core_next_status()函数检查下一个内核的状态是否为初始状态INITIALIZED,如果不是,则输出错误信息;
determine_irq_from_transaction ()函数,用于确定中断的 ID类型;创建变量中断有效使能irq_valid, 并初始化为 0,将 irq_txn中的不同部分组合成irq,并输出irq的值,其中irq_txn为irq_sequence_item的实例化对象,表示序列中每种中断是否有效;之后,调用get_valid_interrupt_id()函数来确定中断 ID 的有效性,并将结果赋值给irq_valid;最后将irq_id 赋值给irq_last并返回irq_valid;其中,若irq_id等于31表示是NMI不可屏蔽中断、异步中断的值31,记录保存这次中断类型,用于中断嵌套的测试;
get_valid_interrupt_id()函数,用于确定中断 ID 的有效性;首先,创建变量 irq_valid并初始化为 0,判断irq_id是否小于 31,如果是,则将irq_id赋值给irq_valid;之后,根据mstatus寄存器32位中不同类型中断的使能位进行判断,并将使能为索引返回irq_valid,从而判断出中断的类型;其中,基于不同中断有优先级进行比较,返回优选级最高的中断类型索引;
send_irq_stimulus_inside()函数,用于发送中断刺激信号;从 irq_sequence_item队列interrupt_received_port获取中断事务信息并存储在irq_txn中;调用 determine_irq_from_transaction ()函数确定中断的有效性,并将结果赋值给irq_valid;如果中断是可屏蔽的,并且在 MIE 的相应位为中断使能关闭,将跳过下面的检查,并将中断线路置为低电平以避免死锁;如果中断无效,则调用vseq.start_irq_drop_seq()函数开始处理中断信号的下拉;再次从interrupt_received_port获取中断事务信息并存储在 irq_txn中;调用determine_irq_from_transaction ()函数确定结束类中断的有效性;调用validate_irq_handle()函数进行中断处理的检查;
validate_irq_handle()函数,用于检查中断行为和中断处理程序的正确性;调用check_core_next_status()函数检查下一次接受到的内核的状态是否为处理中断HANDLING_IRQ,如果不是,则输出错误信息;如果irq_id表明可屏蔽中断,则执行以下操作:
定义一个名为validate_irq_handle的用于检查中断处理程序正确性的虚拟任务,逻辑如下:
调用check_core_next_status任务,检查核心状态是否正确跳转到向量中断处理程序;若否,则输出错误消息,并在超过指定个时钟周期后报告超时错误;
如果中断ID不等于31,表示不是非屏蔽中断,执行以下操作:首先等待CSR_MSTATUS寄存器的写入,超过指定个时钟周期后报告超时错误;然后读取并保存寄存器CSR_MSTATUS的值到变量mstatus变量;检查mstatus变量的特定位字段的值是否正确,否则报告mstatus.MPP状态错误;检查mstatus.MPIE位是否正确设置为1'b1;根据条件判断,mstatus.MPIE在从M模式触发陷阱时必须为1,除非irq_id表明非屏蔽中断,否则报告错误;然后,输出mstatus的值,检查mstatus.mie是否为1'b0,如果不是,则报告错误;调用check_mcause任务,检查中断触发源mcause是否与中断ID匹配,等待CSR_MIE寄存器的写入,超过指定个时钟周期后报告超时错误;然后读取并保存寄存器CSR_MIE的值到变量mie;等待CSR_MIP寄存器的写入,超过指定个时钟周期后报告超时错误;之后,读取并保存寄存器CSR_MIP的值到变量mip;然后,检查mie的特定位是否为1'b1,如果不是,则报告错误;输出mip的值,检查mip的特定位是否为1'b1,如果不是,则报告错误;
如果中断ID表明为不可屏蔽中断,执行以下操作:等待CSR_MNSTATUS寄存器的写入,超过指定个时钟周期后报告超时错误;读取并保存寄存器CSR_MNSTATUS的值到变量mnstatus;检查mnstatus的特定位字段的值是否正确,否则报告错误;
check_mcause的函数,用于检查mcause寄存器的值是否正确匹配给定的中断类型,以验证中断的处理是否按预期执行;首先定义变量mcause来保存mcause寄存器的值;其次调用wait_for_csr_write_operation任务,等待CSR_MCAUSE寄存器的写入,超过设定个时钟周期后报告超时错误;然后读取并保存寄存器CSR_MCAUSE的值到变量mcause,并输出mcause的值;最后使用比较函数进行断言,检查mcause的最高位是否与给定的irq_or_exc匹配;如果不匹配,则报告错误;同时使用比较函数进行断言,检查mcause的低31位是否与给定的cause匹配,如果不匹配,则报告错误;
wait_ret_raw函数,为一个等待xRET指令被断言的函数;首先根据传入的ret参数,使用case语句判断指令类型;如果ret为dret,则等待i_tdu_idu_instr_dret信号被断言;如果ret为mret,则等待i_tdu_idu_instr_mret信号被断言;如果ret为mnret,则等待i_tdu_idu_instr_mnret信号被断言;最后如果ret不匹配上述情况,则报告错误,指示指令类型无效;
wait_ret任务,为在设定周期内等待xRET指令被断言的任务,超过指定的超时时间将报告错误;首先在任务开始时使用fork_with_isolation和join_any创建一个分支;其次在分支中的第一个子任务调用wait_ret_raw任务,等待xRET指令被断言;然后在分支中的第二个子任务ret_timeout使用延时指令等待指定的超时时间;最后,如果超时时间到达仍未检测到xRET指令的断言,则报告错误,指示超时期间没有检测到xRET指令或权限模式切换不正确;若在超时时间内成功检测到xRET指令的断言,则禁用分支,任务结束;
send_debug_stimulus函数,用于发送单个调试请求并执行所有相关的检查;首先可以与中断类似调用启动单个调试序列;其次调用check_core_next_status任务,等待核心状态变为"IN_DEBUG_MODE",并在超时时报告错误;然后使用wait_for_csr_write_operation等待CSR_DCSR寄存器的写入;再调用check_dcsr_privilege 函数,检查DCSR寄存器的权限模式是否为指定的模式;再者,调用check_dcsr_cause函数,检查DCSR寄存器的中断原因是否为指定的原因;最后调用wait_ret任务,等待dret指令的断言,超时时间为指定数量个周期;
check_dcsr_ebreak函数,用于检查DCSR寄存器的ebreak相关位;根据DCSR寄存器的权限模式,检查相应的ebreak位是否被设置;首先根据DCSR寄存器的权限模式signature_data[1:0],使用case语句判断权限模式;如果权限模式为2'b11,检查signature_data[15]是否为1,报告ebreakm未设置;如果权限模式为2'b01,检查signature_data[13]是否为1,报告ebreaks未设置;如果权限模式为2'b00,检查signature_data[12]是否为1,报告ebreaku未设置;如果权限模式不匹配上述情况,则报告错误,指示不支持的权限模式;
check_dcsr_cause函数,用于检查DCSR寄存器的中断原因;将给定的cause与签名地址上的数据signature_data[8:6]进行比较,如果不相等则报告错误地更新了dcsr原因位dcsr.cause;
check_dcsr_privilege 函数,用于检查DCSR寄存器的权限模式;将给定的变量mode与signature_data[1:0]进行比较,如果不相等则报告不正确的dcsr特权位dcsr.prv值;
send_irq_stimulus_end()函数,用于结束当前中断处理,检查是否处于退出中断状态,如果是则调用 vseq.start_irq_drop_seq() 函数开始处理中断信号的下拉,再次从interrupt_received_port 获取中断事务信息并存储在irq_txn中,调用 determine_irq_from_transaction () 函数确定结束类中断的有效性,保证中断类型是无效的,之后,等待中断处理程序执行到xRET指令。
10.一种基于RISC-V架构的随机中断调试验证方法,应用于如权利要求1-9任一项权利要求所述的基于RISC-V架构的随机中断调试验证系统中,其特征在于,包括:
步骤1,通过传入测试用例的参数名字,调用指令生成脚本对指令生成器中的配置参数进行配置,使生成的随机指令流中包含多个中断测试所需要的握手代码段;所述握手代码段通过签名地址传递当前状态相关的处理器信息、控制状态寄存器信息、通用寄存器信息和处理器内核状态信息;
步骤2,程序编译加载到处理器;
步骤3,启动中断序列器:通过虚拟序列里的虚函数来启动,虚函数初始化中断请求序列类core_base_seq 中的参数;随后调用irq_raise_seq派生类,并约束随机化中断请求的数量和类型,是否支持屏蔽和非屏蔽中断,来满足多个中断测试的场景;最后,执行一系列请求函数,完成中断请求的生成和发送;
步骤4,中断驱动器开始工作,不断获取中断请求,在获取到中断请求后创建相应的响应并驱动信号,将中断请求的属性驱动到被测对象接口的相应信号上,并持续获取下一个中断请求;未获取到请求则等待一个时钟周期,然后重复上述过程,从而完成中断激励的不断产生;
步骤5,使用循环来不断触发中断;
步骤6,处理器中的相关模块收到接口上的中断请求后开始进行中断相关处理,内核输出代理中的监视器开始对处理器的行为进行实时监控并将变化序列保存在相关队列中,直到仿真结束,再把队列中的变化序列转换成日志格式化文件输出用于比对,同时,内核输出代理中的覆盖率监视器收集内核仿真的覆盖率信息;
步骤7,调用基本测试中的check_core_next_status函数检测处理器是否退出中断调试状态,并确保内核恢复到正常运行模。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202311733452.6A CN117422025B (zh) | 2023-12-18 | 2023-12-18 | 一种基于risc-v架构的随机中断调试验证系统 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202311733452.6A CN117422025B (zh) | 2023-12-18 | 2023-12-18 | 一种基于risc-v架构的随机中断调试验证系统 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN117422025A CN117422025A (zh) | 2024-01-19 |
CN117422025B true CN117422025B (zh) | 2024-03-29 |
Family
ID=89528709
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202311733452.6A Active CN117422025B (zh) | 2023-12-18 | 2023-12-18 | 一种基于risc-v架构的随机中断调试验证系统 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN117422025B (zh) |
Families Citing this family (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN117851268A (zh) * | 2024-03-07 | 2024-04-09 | 广东省新一代通信与网络创新研究院 | 基于fpga的原型验证平台的高频差分系统 |
Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN110058974A (zh) * | 2019-03-22 | 2019-07-26 | 威海优微科技有限公司 | 一种基于risc_v处理器的usb pd快速充电协议芯片验证法 |
CN110618929A (zh) * | 2019-08-01 | 2019-12-27 | 广东工业大学 | 一种基于uvm的对称加密算法的验证平台和验证方法 |
CN112559045A (zh) * | 2020-12-23 | 2021-03-26 | 中国电子科技集团公司第五十八研究所 | 一种基于riscv的随机指令生成平台及方法 |
CN113608769A (zh) * | 2021-08-16 | 2021-11-05 | 广东亿云智控技术有限公司 | 一种基于多单片机并行处理及自我升级的方法 |
Family Cites Families (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN110007964A (zh) * | 2019-03-15 | 2019-07-12 | 芯来科技(武汉)有限公司 | 用于risc-v架构的中断系统 |
-
2023
- 2023-12-18 CN CN202311733452.6A patent/CN117422025B/zh active Active
Patent Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN110058974A (zh) * | 2019-03-22 | 2019-07-26 | 威海优微科技有限公司 | 一种基于risc_v处理器的usb pd快速充电协议芯片验证法 |
CN110618929A (zh) * | 2019-08-01 | 2019-12-27 | 广东工业大学 | 一种基于uvm的对称加密算法的验证平台和验证方法 |
CN112559045A (zh) * | 2020-12-23 | 2021-03-26 | 中国电子科技集团公司第五十八研究所 | 一种基于riscv的随机指令生成平台及方法 |
CN113608769A (zh) * | 2021-08-16 | 2021-11-05 | 广东亿云智控技术有限公司 | 一种基于多单片机并行处理及自我升级的方法 |
Non-Patent Citations (2)
Title |
---|
ARM及RISC-V MCU的UVM验证平台;王嘉仪;《中国优秀硕士学位论文全文数据库 信息科技辑 (月刊)》;20220115;全文 * |
Formal Verfication in RISC-V CPU Design Verification Flow;Xueying Yang 等;《CONVERTER》;20210901;全文 * |
Also Published As
Publication number | Publication date |
---|---|
CN117422025A (zh) | 2024-01-19 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US8180620B2 (en) | Apparatus and method for performing hardware and software co-verification testing | |
US6757847B1 (en) | Synchronization for system analysis | |
Stott et al. | NFTAPE: a framework for assessing dependability in distributed systems with lightweight fault injectors | |
US6539522B1 (en) | Method of developing re-usable software for efficient verification of system-on-chip integrated circuit designs | |
CN117422025B (zh) | 一种基于risc-v架构的随机中断调试验证系统 | |
Schubert et al. | Functional verification of the IBM POWER7 microprocessor and POWER7 multiprocessor systems | |
Archer et al. | Interface contracts for tinyos | |
CN117422026B (zh) | 一种基于risc-v架构的处理器验证系统 | |
CN111400997B (zh) | 一种基于同步执行的处理器核验证方法、系统及介质 | |
CN103713977B (zh) | 一种微处理器ip核比较验证的实现方法 | |
Li et al. | Formalizing hardware/software interface specifications | |
Kantrowitz et al. | Functional Verification of a Multiple-issue, Pipelined, Superscalar Alpha Processor - the Alpha 21164 CPU Chip | |
US20030101040A1 (en) | Hardware simulation using a test scenario manager | |
de Oliveira et al. | Automata-based modeling of interrupts in the Linux PREEMPT RT kernel | |
US6629174B1 (en) | Synchronization using bus arbitration control for system analysis | |
Cheung et al. | A C-language binding for PSL | |
Amani et al. | Automatic verification of active device drivers | |
CN117892661A (zh) | 一种基于risc-v处理器验证的模拟器比对系统 | |
Devins | SoC Verification Software–Test Operating System | |
WO2024086965A1 (en) | Testing device driver by combining the device driver, firmware emulation layer, embedded simulator, and model of hardware subsystem within single native host application | |
Veldhuijzen | Redesign of the CSP execution engine | |
US7634396B2 (en) | Method and computer program product for generation of bus functional models | |
Sastry et al. | TESTING DISTRIBUTED EMBEDDED SYSTEMS THROUGH INSTRUCTION SET SIMULATORS | |
Amani et al. | Automatic verification of message-based device drivers | |
Lebedev et al. | Test environment for verification of multi-processor interrupt system with virtualization support |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |