姜麗云,田 澤,2,吳曉成,張 駿,2
(1.中國航空工業(yè)集團 西安航空計算技術研究所,陜西 西安 710068;2.集成電路與微系統(tǒng)設計航空科技重點實驗室,陜西 西安 710068)
隨著集成電路設計和制造技術的發(fā)展,集成電路的規(guī)模及復雜程度成倍增加。圖形處理器需要在RTL設計之前快速地對硬件架構和軟件算法進行驗證,要支持更高的仿真速度、支持時序和行為分開建模和軟硬件混合建模、支持從系統(tǒng)到門級無縫過渡及系統(tǒng)性能分析。傳統(tǒng)的設計模式中使用C、C++語言描述系統(tǒng)設計,使用硬件描述語言(HDL)描述寄存器傳輸級(RTL)設計無法滿足這些要求,因此能夠快速完成對硬件結(jié)構和功能驗證的事務級建模(transaction-level modeling,TLM)勢在必行。TLM模型既能充分地掌握各種系統(tǒng)需求和約束,又能基于模擬的方法或形式化方法進行系統(tǒng)功能的驗證,從而在設計早期排除了各種錯誤的可能[1]。
GPU片段處理單元(ROU)位于GPU渲染管線的末尾[2],如圖1所示。片段處理是片段在寫入幀緩存之前所要進行的最后操作,選擇要寫入幀緩存中的片段以及根據(jù)條件改變幀緩存中的值。片段處理單元ROU執(zhí)行OpenGL2.0所規(guī)定的片段操作,包括測試(裁剪測試、Apha測試、深度測試、模板測試)、混合、屏蔽、邏輯等操作,以及針對緩沖區(qū)的清除操作和累積操作。
圖1 片段處理單元在OpenGL渲染管線中的位置
文中聯(lián)合使用統(tǒng)一描述語言UML和SystemC語言在事務級對GPU片段處理單元進行建模研究,采用這種建模方法既可以快速地驗證架構和算法設計中的不足和錯誤之處,節(jié)約設計時間和成本,又可以作為基礎模型支持新一代產(chǎn)品的研發(fā),同時,可以對模型進行量化評估,作為模型約束的參考項[3],有利于對結(jié)構快速分析,利于架構設計師對其修改和優(yōu)化[4],最后通過模型仿真結(jié)果驗證算法和架構的正確性。
UML作為一種可視化的建模語言,具有概念明確、圖形結(jié)構清晰和面向?qū)ο蟮忍攸c,支持各個級別的抽象綜合。在描述復雜的系統(tǒng)結(jié)構時,它具有定義良好、易于表達并支持各個級別的有利于開發(fā)者快速的確定需求,對方案的有效性和可行性進行評估,衡量各種可選方案的利弊,對軟件設計進行敏捷的思考。UML使用了9種模型圖來對面向?qū)ο蟮能浖到y(tǒng)進行建模[5],滿足了對靜態(tài)結(jié)構和動態(tài)行為進行建模的需求,彌補了傳統(tǒng)SoC設計方法的不足。文中搭建ROU單元的UML視圖模型,開發(fā)過程系統(tǒng)的建模行為為驅(qū)動,按照建模的不同階段,根據(jù)顆粒度從大到小將單元的架構和算法逐層梳理。以下以用例圖、類圖、結(jié)構圖和行為圖為例,描述GPU片段處理單元UML建模的過程。
用例圖用于在需求分析階段從用戶的視角來描述和建模整個系統(tǒng),描述了系統(tǒng)中參與者、用例以及它們之間的關聯(lián)、依賴、泛化等關系。ROU單元的用例圖如圖2所示。
圖2 片段處理單元用例圖
其中,ROU單元參與者有PCIE單元、輸出控制單元(OCU)和參數(shù)管理單元(SGU)。與PCIE單元關聯(lián)的用例有讀、寫ROU單元體系結(jié)構寄存器;與OCU單元關聯(lián)的用例有查詢ROU單元Ready服務和輸入片段數(shù)據(jù)到ROU單元;與SGU單元關聯(lián)的用例有下發(fā)圖形功能命令到ROU單元及狀態(tài)查詢服務等。
類圖描述了構成軟件系統(tǒng)的類、接口、子類以及它們之間的關系,是構建其他視圖的基礎,在后面的模型設計中就是通過編程語言構建這些類從而實現(xiàn)系統(tǒng)功能。ROU類關聯(lián)于SystemC庫中的sc_module類,繼承了sc_module關聯(lián)的所有公共屬性及操作;與ROU單元有依賴關系的模塊包括OCU單元、SGU單元、PCIE單元。接口提供了一組只有名稱的純虛函數(shù),本質(zhì)是一個使用C++語法定義的抽象類。ROU單元類實現(xiàn)了Ocu2RouPixelIf、PCIeBackendRegIf和SguGraphFunIf接口中提供的方法,內(nèi)部通過端口來實現(xiàn)對外的連接,端口調(diào)用接口中的方法。具體的調(diào)用關系及方法定義如圖3所示。
圖3 片段處理單元類圖
ROU單元作為一個結(jié)構實體,是用來細化設計的基本塊,內(nèi)部使用進程來劃分不同執(zhí)行階段。ROU單元接收來OCU單元輸出的片段數(shù)據(jù),存儲在內(nèi)部的fragmentFifo,經(jīng)過片段處理進程Fragment_Process_Thread()處理后輸出到顏色緩沖區(qū)(PCache)和深度緩沖區(qū)(ZCache)。ROU單元還實現(xiàn)接收來自SGU單元的功能碼,由功能碼處理進程Function_Code_Thread()處理來實現(xiàn)特定的累積、遮擋查詢、清除緩沖區(qū)等功能,模塊間使用端口傳遞數(shù)據(jù),ROU模塊的結(jié)構圖及模塊間互聯(lián)關系如圖4所示。
圖4 片段處理單元靜態(tài)結(jié)構圖
行為圖用來描述系統(tǒng)的動態(tài)模型和對象之間的交互關系,描述了內(nèi)部進程的具體執(zhí)行流程。片段處理進程Fragment_Process_Thread()實現(xiàn)了在片段數(shù)據(jù)實際存儲到幀緩沖區(qū)之前進行的各種測試,包括裁剪測試、alpha測試、模板測試、深度測試;隨后,將要執(zhí)行混合操作,邏輯操作及單色擴展操作;最后執(zhí)行掩碼的屏蔽操作后將片段輸出到深度緩沖區(qū)和顏色緩沖區(qū),如圖5所示。
圖5 片段處理進程行為圖
功能碼處理進程Function_Code_Thread()處理來自SGU單元的功能碼,實現(xiàn)了清除緩沖區(qū)、累積操作、遮擋查詢[6]等指定的功能,ROU單元執(zhí)行的功能碼如表1所示。
表1 片段處理單元執(zhí)行的功能碼
TLM模型建立在SystemC標準之上,包括SystemC核心語言、結(jié)構化元素、預定義通道、數(shù)據(jù)類型等概念。SystemC的描述能力支持不同層次的抽象行為,向上可以描述系統(tǒng)級的算法模型,向下可以描述硬件電路的RTL級行為[7]。軟硬件工程師可以基于SystemC在同一個環(huán)境下同時描述軟硬件結(jié)構和接口,將通信與功能分開,解決了傳統(tǒng)片上系統(tǒng)設計方法中不同級別使用不同描述語言帶來的過渡問題,能提供更高設計效率[8]。
SystemC對標準C++進行了擴充,為系統(tǒng)結(jié)構建模提供了硬件時序、并發(fā)等概念,體現(xiàn)在核語言的描述上,包括模塊(module)、端口(port)、接口(interface)、信道(channel)、進程(process)、信號(signal)、事件(event)等;另一方面,SystemC支持8種可綜合的數(shù)據(jù)類型,包括二值信號(sc_bit)、位向量(sc_bv
圖6 TLM模型層次結(jié)構及SystemC語言結(jié)構
模塊是SystemC設計的最基本單位,實際上就是一個有構造函數(shù)和析構函數(shù)的類,類似于VHDL中的entity和verilog中的module。模塊使用C++的語法,可以方便地把復雜系統(tǒng)劃分為更小的塊,并且可以方便地隱藏內(nèi)部的數(shù)據(jù)和算法,只需要公開接口,以利于其他模塊的調(diào)用,是一個能夠包含其他的模塊與進程的層次化實體。下面使用module來描述片段處理單元的框架結(jié)構,對應于UML中的結(jié)構圖和類圖。
ROU單元module內(nèi)部包括ports(端口)、processes(進程)、internal data(內(nèi)部信號)和channels(通道)等部分[11],其中ports用于模塊之間的通信;processes描述module的功能;internal data and channels用于管理module內(nèi)部的各種狀態(tài),用于module內(nèi)部processes之間的通信。具體實現(xiàn)如下:
class G3D_ROU:public sc_module,
public Ocu2RouPixelIf,
public PcieBackendRegIf,
public SguGraphFunIf
{
public:
sc_in_clk clock; //時鐘
sc_port
sc_port
……
//例化端口
sc_export
sc_export
……
SC_HAS_PROCESS(G3D_ROU);
//片段處理進程聲明
SC_HAS_PROCESS(Fragment_Process_Thread);
//功能碼處理進程聲明
SC_HAS_PROCESS(Function_Code_Thread);
//構造函數(shù)定義
G3D_ROU(sc_module_name _name, sc_trace_file *tf);
//構造函數(shù)定義
virtual ~G3D_ROU();
……
private:
//內(nèi)部變量定義
ds_func_rou::S_Segment segment;
ds_func_rou::S_Rou_Register reg;
sc_uint<8> graphFunCode;
//內(nèi)部信號定義
sc_signal
sc_signal
……
//FIFO定義
ds_arch_fifo::Fifo< WIDTH> *fragmentFifo;
//內(nèi)部進程定義
voidFragment_Process_Thread();
voidFunction_Code_Thread();
//內(nèi)部方法定義
……}
在構造函數(shù)G3D_ROU∷G3D_ROU():sc_module(_name)內(nèi)部,初始化成員變量:Ocu2RouPixelExport(*this); rouArchRegExport(*this);……
將定義的進程注冊到仿真kernel中:
SC_THREAD(Fragment_Process_Thread);
sensitive_pos(clock);
SC_THREAD(Function_Code_Thread);
sensitive_pos(clock);
其中,敏感(sensitivity)與Verilog中的@類似,設置時鐘為敏感事件,敏感向量列表中的信號被觸發(fā)后,進程將會被重新激活[12]。
SystemC使用進程對并行行為進行建模,進程作為一個基本執(zhí)行單位來仿真目標系統(tǒng)的行為,實現(xiàn)模塊的算法細節(jié),具有動態(tài)性、并發(fā)性、獨立性、異步性和結(jié)構性五大特征。進程包括SC_METHOD、SC_THREAD和SC_CTHREAD三種,其中SC_METHOD用于描述方法進程,是唯一可綜合的寄存區(qū)傳輸級進程;SC_THREAD用于描述線程,線程能夠被掛起和重新激活;SC_CTHREAD用于描述鐘線程,時鐘線程能在時鐘的上升沿或者下降沿被觸發(fā)或者激活,能夠產(chǎn)生更好的行為綜合。
ROU單元定義了片段處理線程Fragment_Process_Thread()和功能碼處理線程Function_Code_Thread(),進程使用wait()掛起,當敏感表中有事件發(fā)生,進程被重新激活運行到遇到新的wait()語句再重新掛起。
以Fragment_Process_Thread()為例來描述建模的進程實現(xiàn)方法:
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);//單色擴展操作
}
……
//更新深度/模板緩沖區(qū)
Write_Depth_Buffer();
//更新顏色緩沖區(qū)
Write_Color_Buffer();
}}
其中,以邏輯操作為例,具體描述算法的實現(xiàn)過程:
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 :} 文中搭建的仿真平臺應用程序運行在Tight-VNC1.3.9版本軟件上,VNC是一款基于Linux和UNIX操作系統(tǒng)的開源軟件[13]。配置Linux內(nèi)核版本為64位:TARGET_ARCH=linux64。配置SystemC庫版本為SystemC2.3.1,SystemC2.3.1不僅提供了SystemC的語言結(jié)構,也提供了用于仿真的kernel[14]。編譯器采用通用的GCC編譯器。對比平臺采用Mesa,Mesa是國際官方組織發(fā)布的實現(xiàn)OpenGL應用程序接口純軟件模型,不依賴任何硬件[15]。 本節(jié)搭建基于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)使能深度測試,清除深度緩沖區(qū)的深度值為0.5,配置glDepthFunc(GL_LESS),繪制圖像。 模型繪制結(jié)果和Mesa的繪圖結(jié)果分別如圖7(a)、7(b)所示。該實驗驗證了ROU片段處理流程的正確性。 (a)模型繪制結(jié)果 (b)Mesa繪制結(jié)果 文中聯(lián)合使用UML的統(tǒng)一描述語言和基于SystemC的體系結(jié)構建模對片段處理單元進行了TLM建模,最后以邏輯操作、混合操作和深度測試為例通過模型仿真結(jié)果驗證算法和流程的正確性。采用這種建模方法實現(xiàn)了在RTL設計之前快速的對硬件架構和軟件算法進行探索和驗證,為RTL設計提供參考依據(jù)。SystemC支持更高的仿真速度、支持軟硬件混合建模和從系統(tǒng)到門的無縫過渡,在進一步的研究中,可以利用SystemC進行基于虛擬原型系統(tǒng)之上的開發(fā),加速GPU的軟硬件協(xié)同設計。2.3 仿真驗證
3 結(jié)束語