APP下载

基于UML&SystemC的GPU片段处理TLM建模

2020-11-14姜丽云吴晓成

计算机技术与发展 2020年9期
关键词:缓冲区进程建模

姜丽云,田 泽,2,吴晓成,张 骏,2

(1.中国航空工业集团 西安航空计算技术研究所,陕西 西安 710068;2.集成电路与微系统设计航空科技重点实验室,陕西 西安 710068)

0 引 言

随着集成电路设计和制造技术的发展,集成电路的规模及复杂程度成倍增加。图形处理器需要在RTL设计之前快速地对硬件架构和软件算法进行验证,要支持更高的仿真速度、支持时序和行为分开建模和软硬件混合建模、支持从系统到门级无缝过渡及系统性能分析。传统的设计模式中使用C、C++语言描述系统设计,使用硬件描述语言(HDL)描述寄存器传输级(RTL)设计无法满足这些要求,因此能够快速完成对硬件结构和功能验证的事务级建模(transaction-level modeling,TLM)势在必行。TLM模型既能充分地掌握各种系统需求和约束,又能基于模拟的方法或形式化方法进行系统功能的验证,从而在设计早期排除了各种错误的可能[1]。

GPU片段处理单元(ROU)位于GPU渲染管线的末尾[2],如图1所示。片段处理是片段在写入帧缓存之前所要进行的最后操作,选择要写入帧缓存中的片段以及根据条件改变帧缓存中的值。片段处理单元ROU执行OpenGL2.0所规定的片段操作,包括测试(裁剪测试、Apha测试、深度测试、模板测试)、混合、屏蔽、逻辑等操作,以及针对缓冲区的清除操作和累积操作。

图1 片段处理单元在OpenGL渲染管线中的位置

文中联合使用统一描述语言UML和SystemC语言在事务级对GPU片段处理单元进行建模研究,采用这种建模方法既可以快速地验证架构和算法设计中的不足和错误之处,节约设计时间和成本,又可以作为基础模型支持新一代产品的研发,同时,可以对模型进行量化评估,作为模型约束的参考项[3],有利于对结构快速分析,利于架构设计师对其修改和优化[4],最后通过模型仿真结果验证算法和架构的正确性。

1 基于UML的ROU单元系统分析和视图建模

UML作为一种可视化的建模语言,具有概念明确、图形结构清晰和面向对象等特点,支持各个级别的抽象综合。在描述复杂的系统结构时,它具有定义良好、易于表达并支持各个级别的有利于开发者快速的确定需求,对方案的有效性和可行性进行评估,衡量各种可选方案的利弊,对软件设计进行敏捷的思考。UML使用了9种模型图来对面向对象的软件系统进行建模[5],满足了对静态结构和动态行为进行建模的需求,弥补了传统SoC设计方法的不足。文中搭建ROU单元的UML视图模型,开发过程系统的建模行为为驱动,按照建模的不同阶段,根据颗粒度从大到小将单元的架构和算法逐层梳理。以下以用例图、类图、结构图和行为图为例,描述GPU片段处理单元UML建模的过程。

1.1 用例图

用例图用于在需求分析阶段从用户的视角来描述和建模整个系统,描述了系统中参与者、用例以及它们之间的关联、依赖、泛化等关系。ROU单元的用例图如图2所示。

图2 片段处理单元用例图

其中,ROU单元参与者有PCIE单元、输出控制单元(OCU)和参数管理单元(SGU)。与PCIE单元关联的用例有读、写ROU单元体系结构寄存器;与OCU单元关联的用例有查询ROU单元Ready服务和输入片段数据到ROU单元;与SGU单元关联的用例有下发图形功能命令到ROU单元及状态查询服务等。

1.2 类 图

类图描述了构成软件系统的类、接口、子类以及它们之间的关系,是构建其他视图的基础,在后面的模型设计中就是通过编程语言构建这些类从而实现系统功能。ROU类关联于SystemC库中的sc_module类,继承了sc_module关联的所有公共属性及操作;与ROU单元有依赖关系的模块包括OCU单元、SGU单元、PCIE单元。接口提供了一组只有名称的纯虚函数,本质是一个使用C++语法定义的抽象类。ROU单元类实现了Ocu2RouPixelIf、PCIeBackendRegIf和SguGraphFunIf接口中提供的方法,内部通过端口来实现对外的连接,端口调用接口中的方法。具体的调用关系及方法定义如图3所示。

图3 片段处理单元类图

1.3 结构图

ROU单元作为一个结构实体,是用来细化设计的基本块,内部使用进程来划分不同执行阶段。ROU单元接收来OCU单元输出的片段数据,存储在内部的fragmentFifo,经过片段处理进程Fragment_Process_Thread()处理后输出到颜色缓冲区(PCache)和深度缓冲区(ZCache)。ROU单元还实现接收来自SGU单元的功能码,由功能码处理进程Function_Code_Thread()处理来实现特定的累积、遮挡查询、清除缓冲区等功能,模块间使用端口传递数据,ROU模块的结构图及模块间互联关系如图4所示。

图4 片段处理单元静态结构图

1.4 行为图

行为图用来描述系统的动态模型和对象之间的交互关系,描述了内部进程的具体执行流程。片段处理进程Fragment_Process_Thread()实现了在片段数据实际存储到帧缓冲区之前进行的各种测试,包括裁剪测试、alpha测试、模板测试、深度测试;随后,将要执行混合操作,逻辑操作及单色扩展操作;最后执行掩码的屏蔽操作后将片段输出到深度缓冲区和颜色缓冲区,如图5所示。

图5 片段处理进程行为图

功能码处理进程Function_Code_Thread()处理来自SGU单元的功能码,实现了清除缓冲区、累积操作、遮挡查询[6]等指定的功能,ROU单元执行的功能码如表1所示。

表1 片段处理单元执行的功能码

2 基于SystemC的ROU单元模型开发、仿真和验证

TLM模型建立在SystemC标准之上,包括SystemC核心语言、结构化元素、预定义通道、数据类型等概念。SystemC的描述能力支持不同层次的抽象行为,向上可以描述系统级的算法模型,向下可以描述硬件电路的RTL级行为[7]。软硬件工程师可以基于SystemC在同一个环境下同时描述软硬件结构和接口,将通信与功能分开,解决了传统片上系统设计方法中不同级别使用不同描述语言带来的过渡问题,能提供更高设计效率[8]。

SystemC对标准C++进行了扩充,为系统结构建模提供了硬件时序、并发等概念,体现在核语言的描述上,包括模块(module)、端口(port)、接口(interface)、信道(channel)、进程(process)、信号(signal)、事件(event)等;另一方面,SystemC支持8种可综合的数据类型,包括二值信号(sc_bit)、位向量(sc_bv)、四值信号(sc_logic)、逻辑向量(sc_lv)、最多可达64位的有(无)符号整型数(sc_int,sc_uint)和任意位宽的有(无)符号整型数(sc_bigint,sc_biguint),以及支持通用bool、int、unsigned int、long、short、enum和struct等C++数据类型。此外,SystemC还拥有许多更高层次上的建模特性,提供了用于软硬件模块连接的信息传输通道,用来对系统的抽象通信机制和同步机制建模,还拥有各种类库,以支持特定设计领域的需要[9-10]。TLM模型层次结构及SystemC语言结构如图6所示。

图6 TLM模型层次结构及SystemC语言结构

2.1 模块设计

模块是SystemC设计的最基本单位,实际上就是一个有构造函数和析构函数的类,类似于VHDL中的entity和verilog中的module。模块使用C++的语法,可以方便地把复杂系统划分为更小的块,并且可以方便地隐藏内部的数据和算法,只需要公开接口,以利于其他模块的调用,是一个能够包含其他的模块与进程的层次化实体。下面使用module来描述片段处理单元的框架结构,对应于UML中的结构图和类图。

ROU单元module内部包括ports(端口)、processes(进程)、internal data(内部信号)和channels(通道)等部分[11],其中ports用于模块之间的通信;processes描述module的功能;internal data and channels用于管理module内部的各种状态,用于module内部processes之间的通信。具体实现如下:

class G3D_ROU:public sc_module,

public Ocu2RouPixelIf,

public PcieBackendRegIf,

public SguGraphFunIf

{

public:

sc_in_clk clock; //时钟

sc_port rou2SpmuPort;

sc_port rou2PCachePort;

……

//例化端口

sc_export rouArchRegExport;

sc_export sgu2RouGraphFunExport;

……

SC_HAS_PROCESS(G3D_ROU);

//片段处理进程声明

SC_HAS_PROCESS(Fragment_Process_Thread);

//功能码处理进程声明

SC_HAS_PROCESS(Function_Code_Thread);

//构造函数定义

G3D_ROU(sc_module_name _name, sc_trace_file *tf);

//构造函数定义

virtual ~G3D_ROU();

……

private:

//内部变量定义

ds_func_rou::S_Segment segment;

ds_func_rou::S_Rou_Register reg;

sc_uint<8> graphFunCode;

//内部信号定义

sc_signalgraphFunCodeEn;

sc_signalfunCodeDone;

……

//FIFO定义

ds_arch_fifo::Fifo< WIDTH> *fragmentFifo;

//内部进程定义

voidFragment_Process_Thread();

voidFunction_Code_Thread();

//内部方法定义

……}

在构造函数G3D_ROU∷G3D_ROU():sc_module(_name)内部,初始化成员变量:Ocu2RouPixelExport(*this); rouArchRegExport(*this);……

将定义的进程注册到仿真kernel中:

SC_THREAD(Fragment_Process_Thread);

sensitive_pos(clock);

SC_THREAD(Function_Code_Thread);

sensitive_pos(clock);

其中,敏感(sensitivity)与Verilog中的@类似,设置时钟为敏感事件,敏感向量列表中的信号被触发后,进程将会被重新激活[12]。

2.2 进程设计及算法实现

SystemC使用进程对并行行为进行建模,进程作为一个基本执行单位来仿真目标系统的行为,实现模块的算法细节,具有动态性、并发性、独立性、异步性和结构性五大特征。进程包括SC_METHOD、SC_THREAD和SC_CTHREAD三种,其中SC_METHOD用于描述方法进程,是唯一可综合的寄存区传输级进程;SC_THREAD用于描述线程,线程能够被挂起和重新激活;SC_CTHREAD用于描述钟线程,时钟线程能在时钟的上升沿或者下降沿被触发或者激活,能够产生更好的行为综合。

ROU单元定义了片段处理线程Fragment_Process_Thread()和功能码处理线程Function_Code_Thread(),进程使用wait()挂起,当敏感表中有事件发生,进程被重新激活运行到遇到新的wait()语句再重新挂起。

以Fragment_Process_Thread()为例来描述建模的进程实现方法:

void G3D_ROU∷Fragment_Process_Thread()

{

wait();

segment=fragmentFifo->read();//读FIFO

if(0x0 !=segment.tileMask)

{

……

segmen.scissor_test(reg);//scissor测试

segment.alpha_test(reg);//alpha测试

if(need_read_depth_buffer()==true)

{

Read_Depth_Buffer();

}

segment.depth_test(reg);//depth测试

segment.stencil_test(reg);//stencil测试

if(need_read_color_buffer()==true)

{

Read_Color_Buffer();

segment.Blend_Operation(reg);//混合操作

segment.Logic_Operation(reg);//逻辑操作

segment.Single_Color_Expand_Operation(reg);//单色扩展操作

}

……

//更新深度/模板缓冲区

Write_Depth_Buffer();

//更新颜色缓冲区

Write_Color_Buffer();

}}

其中,以逻辑操作为例,具体描述算法的实现过程:

void Logic_Operation(S_Rou_Register reg)

{

if(reg.logicOpEn)//判断逻辑操作使能开关

{

for(pixelNum=0; pixelNum

//依次轮询每个像素

{

//判断逻辑操作类型

switch(reg.logicOperationFunc)

{

case ds_func_spmu::GL_CLEAR :

……

case ds_func_spmu::GL_COPY :

……

case ds_func_spmu::GL_XOR :

logic_ color_r[pixelNum]=src_r[pixelNum]^color_buf_r[pixelNum];

logic_ color_g[pixelNum]=src_g[pixelNum]^color_buf_g[pixelNum];

logic_ color_b[pixelNum]=src_b[pixelNum]^color_buf_b[pixelNum];

logic_ color_a[pixelNum]=src_a[pixelNum]^color_buf_a[pixelNum];

break;

default :}

2.3 仿真验证

文中搭建的仿真平台应用程序运行在Tight-VNC1.3.9版本软件上,VNC是一款基于Linux和UNIX操作系统的开源软件[13]。配置Linux内核版本为64位:TARGET_ARCH=linux64。配置SystemC库版本为SystemC2.3.1,SystemC2.3.1不仅提供了SystemC的语言结构,也提供了用于仿真的kernel[14]。编译器采用通用的GCC编译器。对比平台采用Mesa,Mesa是国际官方组织发布的实现OpenGL应用程序接口纯软件模型,不依赖任何硬件[15]。

本节搭建基于OpenGL2.0标准的GPU片段处理单元测试用例:定义分辨率为1 024*768,首先将屏幕划分为4个视口,在视口glViewport(0,0,W/2,H/2)绘制原始图像,绘制一组点、线、三角形和多边形;在视口glViewport(W/2,0,W/2,H/2)使能逻辑操作并配置逻辑操作类型为GL_XOR,绘制图像;在视口glViewport(0,H/2,W/2,H/2)使能混合操作,配置像素的RGBA分量的混合等式为GL_FUNC_REVERSE_SUBTRACT,配置像素RGBA源混合因子计算模式为GL_SRC_COLOR,目的混合因子计算模式为GL_DST_COLOR,绘制图像;在视口glViewport(W/2,H/2,W/2,H/2)使能深度测试,清除深度缓冲区的深度值为0.5,配置glDepthFunc(GL_LESS),绘制图像。

模型绘制结果和Mesa的绘图结果分别如图7(a)、7(b)所示。该实验验证了ROU片段处理流程的正确性。

(a)模型绘制结果

(b)Mesa绘制结果

3 结束语

文中联合使用UML的统一描述语言和基于SystemC的体系结构建模对片段处理单元进行了TLM建模,最后以逻辑操作、混合操作和深度测试为例通过模型仿真结果验证算法和流程的正确性。采用这种建模方法实现了在RTL设计之前快速的对硬件架构和软件算法进行探索和验证,为RTL设计提供参考依据。SystemC支持更高的仿真速度、支持软硬件混合建模和从系统到门的无缝过渡,在进一步的研究中,可以利用SystemC进行基于虚拟原型系统之上的开发,加速GPU的软硬件协同设计。

猜你喜欢

缓冲区进程建模
物理建模在教与学实践中的应用
在经历中发现在探究中建模
联想等效,拓展建模——以“带电小球在等效场中做圆周运动”为例
求距求值方程建模
Dalvik虚拟机进程模型研究
快速杀掉顽固进程
不留死角 全方位监控系统
缓冲区溢出漏洞攻击及其对策探析
中外民主法制进程专题复习
初涉缓冲区