CPU验证环境关键机制

B站影视 港台电影 2025-06-21 09:11 1

摘要:本文记录CPU验证环境中一些基本但重要的机制,包括验证环境中的编译、CPU启动配置、Tube机制和Testcase结束机制。

1. 前言

本文记录CPU验证环境中一些基本但重要的机制,包括验证环境中的编译、CPU启动配置、Tube机制和Testcase结束机制。

2. 编译

CPU验证环境编译分为软件编译和硬件编译。因为CPU的Core会去memory中取指令去执行,而这些指令需要我们提前生成好,并后门放在memory中取,这些指令的集合通常使用hex格式的文件存储,软件编译就是将C语言或汇编语言转换为二进制指令码,并存储在hex格式文件中。硬件编译是将RTL和UVM验证环境一同编译起来,形成一个验证环境的骨架,软件编译的hex文件依托于硬件编译产生的平台。编译环境如图1所示。

图1 编译环境

2.1 软件编译

软件编译通常使用makefile来管理的。makefile调用各CPU的子makefile去生成各个CPU的hex文件。步骤如图2所示。

图2 软件编译流程

确定软件编译环境(编译器、编译选项、编译文件和目录)

将文件编译成.o格式的文件

确定link方式(link器、link选项、规则、文件)

将.o文件link成elf文件

将elf文件转成hex文件

2.2 硬件编译

硬件编译就是使用Xcelium/Questasim/VCS对SystemVerilog代码进行编译、细分和开启仿真的过程。在如今普遍使用UVM的环境中,会形成一个UVM树,使用uvm_test来启动仿真。

在仿真开始时,验证环境会使用后门加载软件编译的hex文件到对应的DDR/SRAM/ROM里。根据加载到memory类型的不同,通常还有不同的方式:

如果memory是真实RTL,可以使用SystemVerilog语法的$readmemh将hex数据从后门填充到真实DDR/RAM/ROM里。

如果memory是虚拟RAM,通常用虚拟RAM提供的函数将hex数据从后门填充进去。

3. CPU启动配置

3.1 确定PC初始值

CPU启动最关键的要确定PC值,PC值决定了CPU从哪里开始取值并执行。

对于ARM Cortex-A来说,初始PC是放在RVBAR(Reset Vector Base Address Register

)寄存器中,RVBAR寄存器是RO类型的,也就是实现就定义好的了。在IP验证中,通常force这个寄存器的值来控制CPU启动PC值。在SoC验证中,如果RVBAR为0,那么会提前在0地址处放置跳转指令(BL),将Cortex-A CPU的PC跳转到真正的启动地址去执行。

对于ARM Cortex-M来说,没有RVBAR寄存器,在复位后会查询中断向量表并进入reset中断函数执行,因此在reset中断函数里可以控制PC跳转到真正的启动地址。中断向量表一般存放在ROM中,Cortex-M CPU在boot的过程中可以读取它的内容。

3.2 Cortex-A启动流程

Cortex-A启动流程通常按以下步骤进行:

把通用寄存器值、堆栈指针、link指针和状态寄存器全部初始化为0;

关掉Trap功能;

设置VBAR(Vector Base Address Register),使它指向中断向量表;

初始化堆栈指针,内容来自scatter file指定的;

使能NEON和初始化相关寄存器为0;(包括使能其它想要打开的特性)

创建页表,配置TTBR/TCR/MAIR等;

使能cache和MMU;

使能中断;

进入main主程序,完成主要操作;

进入WFI;

通常步骤1~8以及步骤10在CPU验证中是固定的流程,不需要反复写,大部分验证人员只需要在步骤9的main函数中完成想要验证的功能。

3.3 Cortex-M启动流程

Cortex-M启动流程通常按以下步骤进行:

复位后,进入reset_handler,初始化通用寄存器为0;

调用系统初始化函数去配置UART、配置MPU等等;

进入C库的启动函数__main,完成一些初始化工作,像设置栈指针、初始化全局变量等,之后调用用户编写的main函数;

进入main主程序,完成主要操作;

进入WFI;

类似Cortex-A,步骤1~4以及步骤5在CPU验证中是固定的流程,不需要反复写,大部分验证人员只需要在步骤4的main函数中完成想要验证的功能。

4. Tube机制

SystemVerilog代码可以使用$display等内置的系统函数很方便的将信息打印到log上,但是C语言就不好弄。

常用的方法是Tube机制,把将要打印的字符串写到UART口上,UART上对接的组件会一直监控出现在UART口上的二进制数据,并把它们转成ASIIC码,然后调用SystemVerilog的$display函数打印到log上。

总得来说,还是借用了SystemVerilog的系统函数来打印的。

5. Testcase结束机制

对于只使用SystemVerilog和UVM环境的验证同学可能有疑问,Testcase结束不就很简单吗,直接调用$stop或drop_objection就ok了。但对于包含CPU运行的环境来说就不一样了,CPU执行的是C语言,从Memory中取值执行,验证环境不好监控它是否执行完毕,这就需要CPU发出一些可以被验证环境捕捉到的信号,用于表示CPU执行的状态。

一种常用的方法是CPU在执行完之后,往UART口写某些特定字符。UART口连接的监控组件如果解析到这些字符,将字符含义传达给验证环境。

同理,如果有多个CPU,那么需要UART监控多个CPU都往UART写完某些字符后,再使用event或全局变量等触发一个事件,UVM等到这个事件,再执行相应动作。

IC工程师技术盛会研讨会报名通知

从功率到 AI 的全面芯片测试论坛

来源:小玉科技频道

相关推荐