基于SystemC的GPU软硬件协同虚拟平台构建方法
2021-08-27何嘉文
何嘉文,杜 斐,聂 瞾,田 泽
(航空工业西安航空计算技术研究所,陕西 西安 710068)
0 引 言
当前进行的芯片设计中,一般需要搭建虚拟仿真平台以验证待测设计的正确性。虚拟仿真平台包括三个部分,即待测设计、主设备模型、测试激励。传统的验证平台,一般使用硬件语言开发主设备模型和测试激励,模拟主设备行为以检测待测设计正确性。但随着芯片复杂度的增加,使用硬件语言开发主设备模型和测试激励的难度也越来越大,尤其对于GPU芯片而言,由于其功能复杂,为兼顾设计效率和开发难度,其功能被拆分到软件驱动和硬件逻辑中。因此,如果按照传统方法搭建GPU的虚拟验证平台,则面临着两个难题,一是使用硬件语言构造的主设备模型和激励开发难度大,且难以保证其功能与软件驱动的一致性,二是未能验证软件驱动的正确性[1-2]。
针对上述问题,该文提供了一种GPU芯片的软硬件协同仿真平台构建方法。以SystemC语言作为桥梁,在虚拟仿真平台中兼容C语言开发的软件驱动、测试激励,以及硬件语言开发的待测设计,不仅能够加快虚拟仿真平台的开发进度,还能保证虚拟仿真和真实芯片测试的一致性,对当前的GPU芯片虚拟验证工作很有帮助。
1 GPU芯片虚拟仿真面临的仿真问题
GPU芯片待测设计包括两个部分,即软件驱动和硬件逻辑,芯片的激励输入为标准OPENGL函数,软件驱动部分将OPENGL函数处理后,通过PCIe总线接口与GPU芯片进行数据交互,而硬件逻辑部分,则负责接收软件驱动部分发送的数据,将此数据处理后转换为视频格式(如DVI、LVDS等)输出。
如果按照传统的芯片虚拟仿真平台搭建方法,使用硬件语言构建主机模型和测试激励,模拟主机行为,则会出现以下三个问题:第一,GPU芯片的软件驱动功能复杂,难以迅速开发出主机模型,且不能保证软件驱动和主机模型功能一致;第二,未能验证软件驱动功能;第三,测试激励需要存储大量数据,至少256 MB的存储空间,如果使用硬件语言构建主机模型和验证平台,势必在验证平台中增加容量为256 MB的存储器模型,导致仿真速度大大减慢。因此,有必要引入一种新的仿真平台构建方法,能够在仿真平台中同时容纳软件驱动和硬件逻辑。该文以SystemC语言作为桥梁,构建了一种基于SystemC语言的GPU芯片软硬件协同虚拟仿真平台,实现了软件驱动和硬件逻辑的联合仿真。
2 SystemC语言简介
SystemC语言是一种系统级建模语言,是在C++语言的基础上扩展了一系列的硬件类,并且提供了一个基于事件驱动的模拟核。SystemC语言既能按照硬件设计的要求进行时钟精确的并行设计,输入输出接口可以按照硬件的要求设计为input和output管脚模式,也可以按照软件设计人员的要求进行抽象层级较高的串行设计,还能兼容C语言、C++语言,且有专门的标准接口处理SystemC语言与硬件语言的连接问题,因此很适合作为桥梁连接软件设计和硬件设计[3-5]。
图1为一个使用SystemC语言作为桥梁的兼容软件语言设计和硬件语言设计的验证平台示例。图中,硬件语言设计通过硬件语言-SystemC语言标准接口嵌入SystemC语言设计中,软件语言设计则可以直接嵌入SystemC语言设计中,再将两个SystemC语言设计直接连接,即可完成兼容软件语言设计和硬件语言设计的验证平台。
图1 兼容软件语言设计和硬件语言设计的验证平台
3 虚拟仿真平台构建方法
GPU芯片的待测设计分为两部分,即软件驱动部分和硬件设计部分。软件驱动分为两部分,第一部分功能为对激励输入的OPENGL语言进行解码(下文均简称为上层驱动),此部分的输出为经解码后的命令和数据,第二部分功能为控制PCIe主设备(在虚拟仿真中为PCIe主设备模型)经PCIe总线发送经解码后的命令和数据到GPU(下文均简称为底层驱动)[6-8]。GPU芯片的硬件设计部分则在收到解码后的命令和驱动后进行处理,转换为视频格式(DVI格式、LVDS格式等)输出。因此,在构建仿真平台时,对于硬件方面,需要引入PCIe主设备模型,并将硬件设计和PCIe主设备模型共同构建在一个顶层下;对于软件方面,上层驱动部分不需要修改,需要构建能够替代底层驱动功能的测试部件,用于驱动PCIe主设备模型向硬件设计部分发送数据,并将软件驱动和硬件设计通过使用SystemC语言开发的转接口相连接,其功能框图如图2所示。
图2 GPU芯片验证平台
如图2所示,此仿真平台包括硬件部分、软件部分、硬件语言-SystemC语言标准接口和底层驱动模型,其中硬件部分包括硬件设计、PCIe主设备模型,例化在硬件描述语言-SystemC语言标准接口的内部;软件部分包括测试激励、上层驱动、调用服务器内存;底层驱动模型,一侧连接软件部分,一侧连接硬件描述语言-SystemC语言转接口。
3.1 硬件描述语言-SystemC语言标准接口的构造
验证平台硬件部分的代码如果需要例化在此仿真平台上,首先需要添加硬件描述语言-SystemC语言标准接口[9],将硬件描述语言代码转换为SystemC语言代码。首先必须统计硬件部分代码的外接口,之后按照SystemC语言中规定的带接口的顶层代码的写法构造转接口。以此验证平台硬件部分顶层代码GPU_PCIe_Top.v为例,首先构造同名SystemC语言代码GPU_PCIe_Top.cpp和GPU_PCIe_Top.h,其中GPU_PCIe_Top.cpp中仅引用GPU_PCIe_Top.h。在GPU_PCIe_Top.h中,首先引用SystemC语言库文件systemc.h,之后按照GPU_PCIe_Top.v的输入输出在GPU_PCIe_Top.h构建同名的输入输出,之后使用SystemC语言专用类ncsc_foreign_module将GPU_PCIe_Top.v例化在GPU_PCIe_Top.h中,如图3所示。GPU_PCIe_Top.h即可例化在此仿真平台上。
图3 硬件描述语言-SystemC语言标准接口的构造
3.2 底层驱动模型的构造
底层驱动模型用于替代原软件底层驱动的功能,即控制PCIe主设备模型,将上层软件需要发送的数据和命令通过PCIe总线发送至GPU芯片,因此,底层驱动模型存在两类接口,即由上层软件调用的函数接口和连接硬件描述语言-SystemC语言标准接口的信号接口,此底层驱动模型的主要功能,即将上层软件的函数接口功能转换为PCIe主设备模型需要的信号时序,之后再将此信号按照SystemC语言的接口形式输出。
因此,构造底层驱动模型时,需要按照以下步骤进行工作:第一,统计上层软件需要的task,并在底层驱动模型定义此task,并通过C语言语法extern将此task调用到软件部分供上层软件调用;第二,在C语言-SystemC语言转接口实现task功能,即将C语言输入的数据转换为硬件描述语言需要的信号时序,并将涉及的信号例化为输入输出接口。
3.2.1 统计上层软件需要的task
按照GPU上层软件部分的要求,需要底层驱动模型实现的task包括两类,第一类是由上层软件调用的,通过此类task控制PCIe主设备向GPU发送数据;第二类是由PCIe主设备模型控制的,通过此类task向验证平台软件部分的服务器内存进行读写操作。对于第一类task,上层软件需要Pcie内部寄存器配置读写task Pcie_Config()和Pcie存储器读写task Pcie_Mem_write();对于第二类task,需要在软件内部通过C语言语法malloc向服务器申请256 MB空间,之后在C语言实现对服务器空间的配置函数Config_Mem(),之后通过语法extern到底层驱动模型中。
3.2.2 在底层驱动模型实现task功能
当在底层驱动模型中定义task后,下一步为实现task功能,首先需要在底层驱动模型中内部实现时钟,之后使用此时钟来作为时序电路的时钟端,对上文涉及的两类task,即选择第一类task介绍其实现方法,第二类task实现方法类似,限于篇幅不做专门介绍。
为在底层驱动模型内部实现时钟,在确认了时钟频率后,首先使用SystemC语法sc_clock定义时钟clock,之后使用SystemC时钟配置专用函数clock[10-13](“信号名”,路径,周期,延迟,初始值)设置时钟频率,保证其频率与PCIe主设备模型的时钟一致。
完成时钟配置后,使用SystemC语法实现软件调用的task到硬件需要的时序的转换[14-16],下文将以软件需要的Pcie存储器读写task Pcie_Mem_Access()转换为验证平台硬件部分PCIe主设备模型的Pcie存储器读写时序为例,详细介绍转换方法。图4为验证平台硬件部分PCIe主设备模型的Pcie存储器读写时序,若软件需要启动对GPU的读操作,应将信号rden和addr设置为有效,信号rden应一直有效直到PCIe主设备模型返回rdack为1一周期,此时软件可从信号data_from_pcie_to_host取值;若软件需要启动对GPU的写操作,应将信号wren、addr和data_from_host_to_pcie设置为有效,信号wren应一直有效直到PCIe主设备模型返回wrack为1一周期;上层软件task输入输出的参数包括rdwr(读写指示,高读低写)、addr(读写地址)、data_in(写操作输入数据)、data_out(读操作输出数据),底层驱动模型的输出信号包括c_addr_out,c_wren,c_rden,c_data_out,输入信号包括c_wrack,c_rdack,c_data_in。为实现上层软件需要的时序,在task开始时,首先判断task输入的参数rdwr的值,若rdwr为1则为读操作,使用SystemC语言语法.write给底层驱动模型的输出信号c_addr_out赋值为task的输入addr,给底层驱动模型的输出信号c_rden赋值为1,之后使用SystemC语言语法do while循环检测c_rdack直到此信号为1,将c_data_in的值赋给上层软件task输出data_out,给底层驱动模型的输出信号c_rden赋值为0;若rdwr为0则为写操作,使用SystemC语言语法.write给底层驱动模型的输出信号c_addr_out赋值为task的输入addr,给底层驱动模型的输出信号c_data_out赋值为task的输入data_in,给底层驱动模型的输出信号c_wren赋值为1,之后使用SystemC语言语法do while循环检测c_wrack直到此信号为1,给底层驱动模型的输出信号c_wren赋值为0,其示例逻辑如图5所示。
图4 Pcie存储器读写时序
图5 底层驱动模型数据转换示例
3.3 信号连接和软件激励添加
在实现了硬件描述语言-SystemC语言标准接口和底层驱动模型后,首先需要连接硬件描述语言-SystemC语言转接口和底层驱动模型,连接时,需要使用SystemC语言的信号连接标准类SC_CTOR[17-18]。首先定义硬件描述语言-SystemC语言转接口和底层驱动模型及其相关信号名,之后在此类的定义中分别将两接口的相应输出相连接即可。
连接完成后,需要在仿真平台中添加激励。软件提供的激励为函数sim,需要在仿真开始时运行。为达到此效果,可以使用SystemC语言类SC_THREAD,此类的功能为在其敏感列表条件达成后开始运行此类中设置的函数。在实际使用中,如图6所示,设置函数HOST_TEST_THREAD,在其中调用测试激励函数sim和退出仿真函数exit(1),之后在SystemC语言类SC_THREAD中调用函数HOST_TEST_THREAD,SC_THREAD类的敏感列表为时钟上升沿。
图6 底层驱动模型数据转换示例
4 仿真验证结果
验证平台搭建完成后,经运行,能够将软件激励经验证平台软件部分送至硬件部分的PCIe主设备模型,能够最大限度保证测试激励和实际芯片仿真环境的一致性,且软件部分调用存储资源是向服务器申请的,可以根据仿真项使用的Mem大小灵活调用和释放,不需在仿真平台上添加Mem模型,其仿真速度大大加快[19-20]。经比较,如表1所示,此仿真平台的仿真速度比同类的纯硬件仿真平台高5倍以上。因此,无论从功能实现,还是仿真速度,此虚拟仿真平台均能达到设计要求。
表1 软硬件协同仿真平台和传统仿真平台速度比较
5 结束语
该文介绍了一种基于SystemC语言的GPU芯片软硬件协同虚拟仿真平台构建方法,能够同时在验证平台中兼容C语言开发的测试激励和软件驱动,以及硬件语言开发的待测设计和PCIe主设备模型。此仿真平台不仅能同时测试软件驱动和硬件设计,其仿真速度也优于传统仿真平台,对GPU芯片的虚拟验证工作很有帮助。但由于GPU芯片规模大,设计复杂,且需要的存储器也较多,导致虚拟仿真速度仍较慢。下一步,将在此基础上研究加快GPU虚拟仿真平台仿真速度的办法,以更好地推进GPU芯片的虚拟验证工作。