簡介
近年來Synopsys 公司, CoWare 公司和Frontier Design公司合作開發了SystemC。在1999 年9 月27 日四十多家世界上著名的EDA 公司, IP 公司,半導體公司和嵌入式軟體公司宣布成立”開放式SystemC 創始社” (Open SystemC Initiative) 這些公司包括ARM, CoWare, Cygnus Solution, Ericsson, Frontier Design, Fujitsu, Infineon, Lucent Technologies,Sony, STMicroelectronics, Synopsys, Taxas Instruments 等
這些公司認為SystemC 是一種很好的硬體軟體聯合設計語言。Ericsson 公司微電子部主任Jan-Olof Kismalm 說:“通信系統的複雜性在不斷地增加而新的系統卻要求以更短的時間推向市場為了以最短的時間開發出複雜的產品,需要我們採用單一的語言描述複雜的行為和 IP,我們相信SystemC 可以幫助我們以更好的方法描述我們的系統並在設計過程的初始階段進行有效的硬體軟體聯合設計這可以大大縮短我們開發產品的時間Kismalm 先生的話表達了世界上眾多公司歡迎SystemC 的原因。”
研究表明,具有較高的抽象能力,同時能體現出硬體設計中的信號同步、時間延遲、狀態轉換等物理信息的語言,才能給工程師提供一個系統級設計的公共基礎平台。在我們常用的設計語言中,C、C++ 和Java等高級程式語言有較高的抽象能力,但由於不能體現硬體設計的物理特性,硬體模組部分需重新用硬體描述語言設計,使得後續設計缺乏連貫性;而VHDL,Verilog最初目的並不是進行電路設計,前者是用來描述電路的,而後者起源於板級系統仿真,因此它們並不適合進行系統級的軟體和算法設計,特別是現在系統中的功能越來越多的由軟體來完成時。
SystemC是在C++的基礎上擴展了硬體類和仿真核形成的,由於結合了面向對象編程和硬體建模機制原理兩方面的優點,這可以使SystemC在抽象層次的不同級進行系統設計。系統硬體部分可以用SystemC類來描述,其基本單元是模組(modul)模組內可包含子模組、連線埠和過程,模組之間通過連線埠和信號進行連線和通訊。
隨著通訊系統複雜性的不斷增加,工程師將更多的面對使用單一的語言來描述複雜的IP和系統,而SystemC,語言良好的軟硬體協同設計能力這一最大特點,將會使其套用更加廣泛。
基本語法
C++和SystemC任務的執行
C++:任務的執行是串列的;SystemC:可以做到並行。
SystemC的基本進程
進程是程式在並發環境中的執行過程, SystemC的基本進程包括:
SC_METHOD, SC_THREAD, SC_CTHREAD
①SC_METHOD:當敏感列表上有事件發生時,才被調用,(用法很像verilog中描述組合邏輯)調用後迅速返回;
②SC_THREAD:能夠被掛起和重新激活,當敏感表上有事件發生,執行緒被重新激活運行到新的wait()語句再重新掛起,(主要用於對程式的驗證);
③SC_CTHREAD:繼承於執行緒進程,只能在時鐘的上升沿或者下降沿被觸發或者激活,(用於時鐘精確的建模)。
Systemc的時鐘模型
在Systemc程式設計中, 時鐘( sc_clock)被作為一個特殊的對象處理。
sc_clock共有六個重載的構造函式。
sc_clock(“clk1”,20,0.5,5,ture)?
模組
模組是SystemC的 最基本單元,模組內部可以包括 連線埠, 內部信號, 內部數據, 進程等
模組本質上是 類,使用 SC_MODULE聲明:
SC_MODULE(mmu)
{…..//details of the design}
等價於:
Class mmu :public sc_module
{…..//details of the design}
實例
SC_METHOD??實例
?
#ifndef_FULLADDER_H
#define_FULLADDER_H
#include<systemc.h>
SC_MODULE(FullAdder)
{
sc_in<sc_bit>A,B,Ci;
sc_out<sc_bit>S,Co;
void do_add()
{
S=(A.read())^ (B.read())^(Ci.read());
Co= (A.read())&(B.read())|
(B.read())&(Ci.read())|
(A.read())&(Ci.read());
};
SC_CTOR(FullAdder) //systemc的構造函式
{
SC_METHOD(do_add); //表示do_add對A,B,Ci敏感
sensitive<<A<<B<<Ci;
}
};
#endif
SC_THREAD實例
#ifndef_MONITOR_H
#define_MONITOR_H
#include<systemc.h>
SC_MODULE(Monitor)
{
sc_in<sc_bit>m_a,m_b,m_cin,m_sum,m_cout;
void pre_monitor()
{
while⑴{
cout<<m_a.read()<<m_b.read()<<m_cin.read();
wait(); //當執行到時程式被掛起,當敏感列表被觸發時程式繼續執行
cout<<m_sum.read()<<m_cout.read();
}
};
SC_CTOR(Monitor)
{
SC_ THREAD(pre_monitor); //表示當變數發生變化時, pre_monitor被激活或者重新激活;
sensitive<<m_a,m_b,m_cin,m_sum,m_cout ;}
};
#endif
SC_CTHREAD實例
#ifndef_DRⅣER_H
#define_DRⅣER_H
#include”systemc.h”
SC_MODULE(Drive){
sc_in_clk clk;
sc_out<sc_bit> d_a,d_b,d_cin;
void prc_drive();
SC_CTOR(Drive){ //表示prc_drive對時鐘上升沿敏感
SC_CTHREAD(prc_drive,clk.pos());
}
} ;
#endif
接口
接口: 集合一組固定的通信方法
存儲器寫接口:
Class mem_read_if: public sc_interface
{public:
virtual transfer_status read(…)=0;//讀虛函式(沒有數據)
}
存儲器讀接口:
Class mem_write_if: public sc_interface
{public:
virtual transfer_status write(…)=0;//寫虛函式(沒有數據)
}
存儲器接口(將讀接口與寫接口封裝):
Class ram_if: public mem_read_if,mem_write_if{
…
}
通道
通道實現了接口的內容,即它是一個實現通信功能的“模組”,只不過它僅完成通信功能。
例子:Ram通道:
Class ram :public sc_module,ram_if{
…
Transfer_status read(…)//定義讀函式(需要用戶自己定義具體功能)
{
…
}
Transfer_status write(…)//定義寫函式(需要用戶自己定義)
{
…
}
}
連線埠
連線埠: 模組通過連線埠與通道連線
模組的連線埠的定義要與接口同一類才能連線
SC_MASTER(Master){
sc_in_clk clk;
sc_port<ram_if>ram_port; //實例化連線埠
Int data;
Unsigned int address;
…
void main_action{ //需要用戶自己定義
…
Transfer_statusstatus=ram_port->write(address,data);//在功能函式中通過連線埠
… ;調用通道函式
Transfer_statusstatus=ram_port->read(address,data);//通過連線埠調用功能函式
…
}
…
}
行為建模
接口(interface):是c++抽象類,它以純虛數的方式定義了一組抽象的方法?
通道(channel):通道實現一個或者多個接口(接口中定義的虛函式必須在通道中實現)
連線埠(port ):連線埠定義在模組中,通過連線埠,模組中的進程就能夠連線到一定的接口
通信庫
Systemc支持業界很多設計方法學,OSCI的思路是定義一個小的語言子集以完成最基本的語言構架,具體的設計方法學有一些專用庫來實現,如可以使用Master-Slave庫來實現IP復用;
Master-Slave庫使得通信與模組的行為在一定程度上分離,從而可以方便的向SoC中集成IP模組。
Void generate_data(int &out){
for(int i=0;i<10;i++){
accumlate(out);
}
}
Void accumlate(int ∈1){
sum +=in1;
cout<<;“sum =”<<sum<<endl;
}
SC_MODULE(producer){
Sc_outmaster<int>out1; //systemc中master-slave通信庫內
表示作為主機輸出out1
Sc_in<bool>start;//啟動進程
Void generate_data(){
For(int i+0;i<10;i++){
Out1=i;
}
}
SC_CTOR(producer){
SC_METHOD(generate_data);
sensitive<<start;
}
}
SC_MODULE(consumer){
Sc_inslave<int>in1; //systemc中master-slave通信庫內表示作為從機輸入in1
Int sum;
Void accumulate(){
Sum+=int1;
Cout<<;“sum=”<<sum<<endl;
}
SC_CTOR(consumer){
sc_slave(accumulate,in1); // systemc中master-slave通信庫內表示從機中accumulate函式對in1敏感
sum=0;
}
}
SC_MODULE(top){
Producer *A1;
Consumer *B1;
Sc_link_mp<int>link1; //systemc中master-slave通信庫內中間通信
SC_CTOR(top){
A1=new producer(“A1”);
A1->out1(link1);
B1=new consumer(“B1”);
B1->in1(link1);
}
}