systemC
System C是一种软/硬件协同设计语言,一种新的系统级建模语言。它包含了一系列C++的类和宏,并且提供了一个事件驱动的模拟核,使得系统的设计者能够用C++的词法模拟并行的进程,特别是在SoC系统中。
简介
近年来Synopsys 公司, CoWare 公司和Frontier 设计公司合作开发了SystemC。在1999 年9 月27 日四十多家世界上著名的EDA 公司, IP 公司,半导体公司和嵌入式软件公司宣布成立”开放式SystemC 创始社” (Open SystemC Initiative) 这些公司包括ARM, CoWare, Cygnus Solution, Ericsson, Frontier Design, 富士通株式会社, Infineon, Lucent Technologies,索尼, 意法半导体, Synopsys, Taxas Instruments 等
这些公司认为SystemC 是一种很好的硬件软件联合设计语言。爱立信 公司微电子部主任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 设计}
等价于:
Class mmu :public sc_module
{…..//details of the design}
实例
SC_METHOD??实例
?
#ifndef_FULLADDER_H
#define_FULLADDER_H
#include\u003csystemc.h\u003e
SC_MODULE(FullAdder)
{
sc_in\u003csc_bit\u003eA,B,Ci;
sc_out\u003csc_bit\u003eS,Co;
void do_add()
{
S=(A.read())^ (B.read())^(Ci.read());
Co= (A.read())\u0026(B.read())|
(B.read())\u0026(Ci.read())|
(A.read())\u0026(Ci.read());
};
SC_CTOR(FullAdder) //systemc的构造函数
{
SC_METHOD(do_add); //表示do_add对A,B,Ci敏感
含羞草\u003c\u003cA\u003c\u003cB\u003c\u003cCi;
}
};
#endif
SC_THREAD实例
#ifndef_MONITOR_H
#define_MONITOR_H
#include\u003csystemc.h\u003e
SC_MODULE(Monitor)
{
sc_in\u003csc_bit\u003em_a,m_b,m_cin,m_sum,m_cout;
void pre_monitor()
{
while⑴{
cout\u003c\u003cm_a.read()\u003c\u003cm_b.read()\u003c\u003cm_cin.read();
wait(); //当执行到时程序被挂起,当敏感列表被触发时程序继续执行
cout\u003c\u003cm_sum.read()\u003c\u003cm_cout.read();
}
};
SC_CTOR(Monitor)
{
SC_ THREAD(pre_monitor); //表示当变量发生变化时, pre_monitor被激活或者重新激活;
sensitive\u003c\u003cm_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\u003csc_bit\u003e 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\u003cram_if\u003eram_port; //实例化端口
Int data;
Unsigned int address;
…
void main_action{ //需要用户自己定义
…
Transfer_statusstatus=ram_port-\u003ewrite(address,data);//在功能函数中通过端口
… ;调用通道函数
Transfer_statusstatus=ram_port-\u003eread(address,data);//通过端口调用功能函数
…
}
…
}
行为建模
接口(interface):是C++抽象类,它以纯虚数的方式定义了一组抽象的方法?
通道(channel):通道实现一个或者多个接口(接口中定义的虚函数必须在通道中实现)
端口(port):端口定义在模块中,通过端口,模块中的进程就能够连接到一定的接口
通信库
Systemc支持业界很多设计方法学,OSCI的思路是定义一个小的语言子集以完成最基本的语言构架,具体的设计方法学有一些专用库来实现,如可以使用Master-Slave库来实现IP复用;
Master-Slave库使得通信与模块的行为在一定程度上分离,从而可以方便的向SoC中集成IP模块。
Void generate_data(int \u0026out){
for(int i=0;i\u003c10;i++){
accumlate(out);
}
}
Void accumlate(int \u0026in1){
sum +=in1;
cout\u003c\u003c;“sum =”\u003c\u003csum\u003c\u003cendl;
}
SC_MODULE(producer){
Sc_outmaster\u003cint\u003eout1; //systemc中master-slave通信库内
表示作为主机输出out1
Sc_in\u003cbool\u003estart;//启动进程
Void generate_data(){
For(int i+0;i\u003c10;i++){
Out1=i;
}
}
SC_CTOR(producer){
SC_METHOD(generate_data);
sensitive\u003c\u003cstart;
}
}
SC_MODULE(consumer){
Sc_inslave\u003cint\u003ein1; //systemc中master-slave通信库内表示作为从机输入in1
Int sum;
Void accumulate(){
Sum+=int1;
Cout\u003c\u003c;“sum=”\u003c\u003csum\u003c\u003cendl;
}
SC_CTOR(consumer){
sc_slave(accumulate,in1); // systemc中master-slave通信库内表示从机中accumulate函数对in1敏感
sum=0;
}
}
SC_MODULE(top){
Producer *A1;
Consumer *B1;
Sc_link_mp\u003cint\u003elink1; //systemc中master-slave通信库内中间通信
SC_CTOR(top){
A1=new producer(“A1”);
A1-\u003eout1(link1);
B1=new consumer(“B1”);
B1-\u003ein1(link1);
}
}
参考资料
Warning: Invalid argument supplied for foreach() in /www/wwwroot/6gwu.com/id.php on line 283