劉 靜,史彥芳,孔 黎
(西北工業大學 電子信息學院,陜西 西安 710072)
在構建一個新系統時,為了有效地測試和驗證新系統的行為和正確性,通常需要對此新系統進行仿真。系統仿真包括軟硬件結合仿真和軟件仿真,其中,軟件仿真由于其具有脫離具體的硬件,便于調試的優點,而得到廣泛的應用。
所謂軟件仿真是指通過軟件的執行來模擬硬件行為的一種方法。軟件仿真器是在宿主機上運行并能模擬目標機器行為的一種軟件系統。
利用軟件仿真器,硬件生產廠商可以在構建系統之前就對其正確性及性能進行驗證,從而使得軟件開發商可以在硬件生產出來之前進行軟件開發使得軟硬件可以同時面世,從而大大降低了開發時間。
與此同時,軟件仿真器具有執行速度低的缺點,因此如何提高指令集仿真器的執行速度成為指令集仿真器的一個研究課題。文中首先介紹了指令集仿真的實現策略,并對基于ZWFcore的DSP指令集仿真器具體設計與實現做了闡述。
指令集仿真器是最基本的軟件仿真器。目前最流行的指令集仿真器實現策略[1]有3種:基于解釋的指令集仿真策略、基于編譯的指令集仿真策略和混合指令集仿真策略。
解釋型指令集仿真器是基于解釋的指令集仿真策略來實現的仿真器。它通過在內存中建立一個數據結構來模擬目標處理器的狀態,然后進入一個循環,循環體包括取值、譯碼、路由、執行4個基本的步驟。如圖1所示。

圖1 解釋型指令集仿真Fig.1 Interpreted instruction set simulator
其中取值是從內存中將一條指令字取出,譯碼是通過相應的掩碼取出指令字中的操作數和操作碼,然后通過路由根據操作碼選擇到相應的執行函數,再有對應的執行函數完成對操作數的操作。從而完成對一條指令的的仿真。其優點是,設計簡單且靈活性好,但完成一個周期的時間較長。
編譯型指令集仿真器[2-4]是基于編譯型指令集仿真策略來實現的仿真器。它在程序執行之前,首先對程序進行編譯處理,把每一條目標機指令轉譯成一組宿主機指令,在實際運行時直接使用那一組宿主機的指令代替那條目標機的指令來完成處理器狀態的修改,如圖2所示。編譯型指令集仿真器具有較高的模擬速度,但它對宿主機過分依賴使得其通常只用于宿主機和目標機體系結構相近的模擬器中。

圖2 編譯型指令集仿真Fig.2 Compiled instruction set simulator
解釋型指令集仿真器能夠精確地模擬指令執行過程中各個部件的狀態,具有良好的擴展性,因此可以方便地在模擬器外部擴充調試其和程序分析器。另外,由于指令解釋部分采用高級語言的函數來實現,使得模擬器便于向其他宿主機移植,故本文采用解釋型指令仿真策略來模擬指令的讀取、譯碼和執行過程。
ZWFcore是一款高性能通用DSP核,支持多種片上系統(SOC)。其主要應用于通信、圖像處理及視頻處理領域。DSP指令集仿真器(ZWISS)是運行在ZWFcore平臺之上,基于解釋型指令集仿真策略對ZWFcore指令集進行仿真的仿真器。其首先在內存中建立一個數據結構來代表目標處理器的狀態,并將可執行的指令加載到內存開辟的存儲結構中,然后進入一個處理循環。它有效地對ZWFcore的存儲器、及存儲器的訪問、指令集流水線及中央處理單元進行了模擬,并通過設計server模塊,在server上完成了對ZWFcore上的開發程序的調試。
為實現上述功能,基于ZWFcore的DSP指令集仿真器[5](ZWISS)主要可以分為7個模塊,分別為:初始化模塊、加載模塊、譯碼模塊、路由模塊、中央處理單元模塊、多級存儲器模塊、MMU模塊、MPS模塊、PMA模塊和調試代理rsp_server模塊。其中MMU模塊、MPS模塊和PMA模塊是可選的模塊。根據硬件的設計需求來決定是否啟用相應的模塊。
2.2.1 初始化模塊
在啟動zwiss時,需要對多級存儲單元模塊的類中生成對象按照硬件啟動時應該具有的狀態進行初始化設置,并且對其他各模塊進行初始化,因此需要初始化模塊完成這個功能。
具體地,初始化模塊主要完成以下幾項任務:
1)對多級存儲單元的初始化:多級存儲單元的初始化包括對寄存器的初始化和內存的初始化,其可以通過通過加載模塊對elf頭文件中的信息進行解析,獲得相應的系統初始化的參數后,對多級存儲單元中的特殊寄存器和內存的值分別進行相應的初始化,其他寄存器可以賦為0。
2)對譯碼模塊的初始化:主要是將配置文件中的信息存儲到向量表中,這樣可以使代碼的重用性大大提高。
3)對路由模塊的初始化就是對函數指針數組的初始化,由函數functionmap()來完成。
2.2.2 加載模塊
加載模塊[6]是在ZWFcore指令集仿真器初始化模塊運行后,在譯碼模塊運行之前運行的模塊。加載模塊用于解析elf文件,提取相關信息包括其頭信息和此文件涉及的指令,將提取的信息存儲到多級存儲單元中。加載模塊是中微一號指令集仿真器運行的基礎,是后面譯碼、路由、執行函數的先決條件,只有加載了信息后,中微一號指令集仿真器的運行才有意義,才能夠驗證指令仿真的正確性。
設計加載模塊前,首先要區分文件是否為ELF文件,根據文件的格式,提取指令信息。從ELF文件信息中分析出需要將指令信息加載到代碼區或者數據區的具體問題,然后將提取出的信息加載到代碼區或者數據區中。
2.2.3 譯碼模塊
譯碼模塊實現對指令中操作碼和操作數的提取。從多級存儲單元中提取指令,然后經過譯碼模塊的解釋,將操作數和操作碼提取出來,根據操作碼定位到對應的指令序號,將操作數和指令序號存入到操作數結構體中,為后面的指令的運行提供了保證。
譯碼模塊主要完成以下工作:
1)將指令和指令掩碼按照順序依次進行掩碼操作,判斷出指令的類別,然后根據指令的類別,和特征碼進行匹配,如果特征碼相同,即完成了操作碼的定位,將其定位到特定的指令序號。
2)由于前面初始化的過程中已經建立了操作數的初始化列表,并且定位了指令中具體的比特位的是第幾個操作數的比特位,所以可以根據這些定位從指令中提取出操作數,并將操作數按照順序存放到定義的vector中。
譯碼模塊將操作數存在vector中,故定義如下的結構體:
struct operand_struct
{
int instruction_index;//指令序號
vector
};
該結構體包括指令序號和操作數列表信息。其中操作數列表中包含了從指令中提取的操作數的信息。
同時譯碼模塊定義了opcoder類,其流程圖如圖3所示。

圖3 譯碼流程圖Fig.3 Flow chart the decoder design
文中采用了基于決策森林的二進制指令譯碼算法,其思想是先構建一決策森林,當一條待譯碼指令字進入譯碼入口后,按照決策森林中的第一棵決策樹對應的指令掩碼計算出其可能的指令決策碼,在決策樹中尋找,找到則識別完畢,譯碼成功退出,否則依次遍歷所有的決策樹,直至譯碼成功退出,若還未匹配則說明該指令字不合法,譯碼失敗退出。
2.2.4 路由模塊
路由模塊是緊跟譯碼模塊之后的模塊,主要根據譯碼所得的指令序號,路由到中央處理單元的相應處理函數來處理。
路由模塊的實現是通過定義一個函數指針數組,此數組的結構如下:
Int(*function_map[765])(struct operand_struct&);
其中*function_map為定義的指針數組,765為指令的個數,struct_operand_struct代表的是操作數結構體。
2.2.5 中央處理單元模塊
中央處理單元模塊是整個仿真器的核心部分,其本質是一個函數集,主要完成的是將ZWFcore所有的指令用C++語言的函數來實現,每條指令根據指令集中給出的定義對相應的多級存儲器進行訪問或修改。
為了方便整個系統的調用,中央處理單元針對每條向外部提供了接口,這些接口的命名如下:
int ins0(struct operand_struct operand&);
int ins1(struct operand_struct operand&);
……
由于這些函數采用了統一的參數,即由譯碼模塊提供的指令操作數,故使代碼的編寫更加規范,同時降低了出錯概率。
2.2.6 內存管理單元模塊
內存管理單元(MMU)模塊是可選的模塊,其實現的是虛擬地址與物理地址的轉換功能(詳見圖4)。從而避免不同的指令執行過程中訪問同一物理地址。
MMU的實現主要是將虛擬頁表映射到物理頁表。通過查找TLBs來實現這種轉換。而TLBs是由操作系統填充的,用戶不能隨意更改。
2.2.7 存儲保護系統模塊
通過定義一對存儲器,用來存放可以讀寫的內存的上下界的地址,從而來限定用戶訪問的內存范圍。它是一種基于地址的保護,保障了系統的安全性。

圖4 虛擬地址轉換Fig.4 Virtual addressing translation
2.2.8 物理內存屬性模塊
物理內存屬性模塊(MPS),其主要功能是對內存中的各個段進行劃分,規定其特殊的屬性,包括外設屬性(Privileged Peripheral(P)),可緩存(Cacheable (C))
投機性(Speculative (S)),代碼可讀(Code Fetch (F)),數據可訪問(Data Access(D))。這是一種基于段的保護,防止對一些地址的非法訪問。
2.2.9 多級存儲器模塊
多級存儲單元模塊主要完成的是對ZWFcore的寄存器組、主存和cache進行管理。在指令仿真執行的過程中通過調用該模塊完成對寄存器以及主存的修改與讀取。這里我們將其寄存器組合主存抽象成一個類,故對主存和寄存器的修改和讀取可以看作是對該類對象的相應的操作。
在多級存儲器模塊中,ZWISS采用了虛擬頁表來仿真ZWFcore的主存,每個頁64 kB。由于ZWFcore的地址是32位,故我們將其告16位作為其頁地址,低16位為其頁內地址。這種方式與單純使用“地址-值”的方式相比,具有查找次數少,用時短的優點。
該模塊對外提供了很多接口,主要是完成其他模塊對寄存器和內存的訪問和修改。
這些接口的設計須滿足通用性、高效性、高內聚和低耦合,并且應在實現相應功能基礎上,具有較好的擴展性。
該類的設計表示如下所示:class MLSS
{
public:
//程序狀態字寄存器
unsigned int PSW;
//程序計數器
unsigned int PC;
…
private:
//資料寄存器
union reg data_reg;
//地址寄存器
union reg addr_reg;
//代碼區
std::map
//數據區
std::map
public:
int get_reg32bit (int reg_type, int reg_ID, unsigned int&val);//讀 32 位
int set_reg32bit (unsigned int val, int reg_type, int reg_ID);//寫 32 位
……
}
其中,在讀寫內存時,根據MMU、MPS、以及PMA的存在與否,來進行對將要操作的地址進行判斷,看其是否允許被操作,在進行相應的操作。其具體的操作如圖5所示。

圖5 地址的翻譯過程Fig.5 Progress of the addressing translation
2.2.10 調試代理模塊
調試代理模塊即server模塊,相當于ZWISS仿真器與調試器GDB的接口。其用于解析調試器GDB發出的調試命令并調用仿真器進行相應的處理,同時將結果返回給調試器GDB。
Server模塊通過RSP協議與GDB進行通信,針對RSP協議中的指令,在server模塊中設計了ZWDPI(中微一號調試編程接口)。在ZWDPI中提供最精簡的調試編程方法,包括設置斷點,移除斷點,讀/寫全部寄存器,連接主機等。這些方法函數保證了server模塊通過方法的組合執行GDB發出的所有命令。
2.2.11 陷阱模塊
陷阱模塊提供了各種陷阱的接口。其實現是通過定義一個類,在程序執行過程中,當發生陷阱時可以調用此模塊中的類成員函數來實現相應的處理。
模擬器的好壞直接由各個模塊的性能決定,因此對各個模塊性能分析成為設計的一個主要部分,現對主要模塊的性能分析如下。
路由模塊主要是利用函數指針指向對應的中央處理單元的執行函數,因此其具有較高的性能,時間復雜度僅為O(1)。
中央處理單元是整個模擬器的核心單元,其性能的好壞直接影響模擬器的正確性和執行速度,故其是否能準確的解釋指令,并且用最短的時間來實現指令,成為我們關注的核心。在用C語言實現中央處理單元時,要盡可能使用執行速度高的編碼,如:盡量使用比較簡單的移位操作而避免使用與或操作。這樣大大提高此單元的執行速度和可靠性。
多級存儲單元在實現上,采用了動態申請空間的方式而不是一次性申請所需的模擬大小的內存空間,這使得多級存儲單元的空間復雜度大大降低,同時,在對寄存器和內存進行讀寫操作時,使用較少的循環操作,提高了多級存儲單元的時間復雜度。
文中實現對ZWFcore的仿真,在對其進行指令集仿真的基礎上,通過對其體系結構的升入分析,對其特殊模塊如MMU、MPS、PMA單元進行了仿真,實現了對內存的保護和更加真實的模擬了硬件的實現情況。同時,增加了調試代理模塊為仿真器的調試提供了接口,便于掛接其他的調試模塊。
[1]俞甲子,石凡,潘愛民,等.程序員的自我修養[M].北京:電子工業出版社,2009.
[2]譚華.嵌入式系統軟件仿真器的研究與實現 [D].成都:電子科技大學,2005.
[3]Reshadi M,Mishra P,Dutt N.Instruction Set Compiled Simulation:A Technique for Fast and Flexible Instruction Set Simulation [C]//Design Automation Conference,2003:758-763.
[4]A Nohl et al.A Universal Technique for fast and Flexible Instruction-Set Architecture Simulation[J].IEEE Transaction on Computer-Aided Design ofIntegrated Circuitsand Systems,2002,123(12):1625-1639.
[5]S Pees et al.Using Static Scheduling Techniques for the Retargeting ofHigh Speed, Compiled Simulators for Embedded Processors from an Abstract Machine Description[C]//The 14th International Symposium on System Synthesis,2001:57-62.
[6]陶峰峰,付宇卓.DSP指令集仿真器的設與實現[J].計算機仿真,2005,22(9):225-228.TAO Feng-feng,FU Yu-zhuo.Design and implementation of DSP instruction simulator[J].Computer Simulation,2005,22(9):225-228.