1. SystemC Setup 从www.systemc.org下载最新的SystemC library,这里我们统一使用已经stable的2.1.v1版。在library下载到本地以后,需要进行一次性的安装流程。这个安装流程是利用用户所使用的编译环境编译用户所需的基本SystemC library的过程。 对于Linux和Windows的安装流程是不一样的,下面分别详述。 1.1. For Linux 1、 解压缩包 a) gunzip systemc-2.1.v1.tgz b) tar –xvf systemc-2.1.v1.tar 2、 安装library a) 进入安装目录 cd systemc-2.1.v1 b) 创建临时文件夹 mkdir temp cd temp c) 设置环境 setenv CXX g++ d) 配置包 ../configure e) 编译包 gmake f) 安装包 gmake install g) 删除临时文件夹 rm –rf temp 经过以上的步骤,SystemC就安装完成了。
1.2. For Windows 要在Windows环境下使用SystemC,需要标准的C++编译器。在这里,我们统一使用VC++6.0。以下的操作都本地已经安装了VC++6.0。 1、 进入SystemC安装目录下的msvc60SystemC子目录,如: C:systemc-2.1.v1msvc60SystemC 2、 双击SystemC.dsw,VC++6.0会自动运行 3、 点击 或按ctrl+F5,开始编译SytemC.lib。编译过程的最后会询问exe文件的名字,选择Cancel。 经过以上的步骤,在systemc-2.1.v1msvc60SystemCDebug目录下,会生成SytemC.lib这个文件。安装完成。 2. SystemC Design Example 2.1. Module Design 本文以AMBA协议中AHB上的Reset Controller的设计为例子,具体说明SystemC的设计流程。 2.1.1. Introduction to Reset Controller 当外部复位指示POReset信号到来时,Reset controller产生系统的复位信号。其结构如下图: 2.1.2. Signal Descriptions 2.1.3. Function and operations POReset是个异步复位的指示信号。HRESETn对POReset打了三拍以消除亚稳态。以下是时序示意图: 在这里,我们用一个状态机来完成打三拍的操作,状态机状态转换示意图如下: 下图是Reset Controller的电路示意图: 2.1.4. SystemC Source Code /****************************************************** Filename : rst_ctrl.h Auther : Richeal.Li Date : 2006-09-08 ******************************************************/ #include "systemc.h" SC_MODULE(rst_ctrl){ sc_in <bool> HCLK ; sc_in <bool> POReset ; sc_out <bool> HRESETn ; enum state_type{ ST_POR = 0x1, ST_INI1 = 0x2, ST_INI2 = 0x3, ST_RUN = 0x4}; sc_signal <state_type> rst_state; void prc_rst_ctrl() ; SC_CTOR(rst_ctrl){ SC_METHOD(prc_rst_ctrl) ; sensitive_pos << HCLK ; sensitive_neg << POReset; } }; /****************************************************** Filename : rst_ctrl.cpp Auther : Richeal.Li Date : 2006-09-08 ******************************************************/ #include "rst_ctrl.h" void rst_ctrl::prc_rst_ctrl(){ if(!POReset.read()){ rst_state = ST_POR; HRESETn = 0 ; } else switch(rst_state){ case ST_POR : HRESETn = 0 ; rst_state = ST_INI1 ; break; case ST_INI1: HRESETn = 0 ; rst_state = ST_INI2 ; break; case ST_INI2: HRESETn = 0 ; rst_state = ST_RUN ; break; case ST_RUN : HRESETn = 1 ; rst_state = ST_RUN ; break; default: HRESETn = 1 ; rst_state = ST_RUN ; break; } }
2.2. Testbench Design 为了验证设计的正确性,我们还需要编写Testbench。因为设计非常简单,这里的Testbench只做以下两件事情: 1、 产生激励; 2、 保存波形 2.2.1. Generate POReset /****************************************************** Filename : gen_poreset.h Auther : Richeal.Li Date : 2006-09-08 ******************************************************/ #include "systemc.h" SC_MODULE(gen_poreset){ sc_out <bool> POReset ; void prc_gen_poreset() ; SC_CTOR(gen_poreset){ SC_THREAD(prc_gen_poreset); } }; /****************************************************** Filename : gen_poreset.cpp Auther : Richeal.Li Date : 2006-09-08 ******************************************************/ #include "gen_poreset.h" void gen_poreset::prc_gen_poreset(){ //1st POReset POReset.write(1); wait(45, SC_NS) ; POReset.write(0); wait(60, SC_NS) ; POReset.write(1); wait(100, SC_NS); //2nd POReset POReset.write(1); wait(45, SC_NS) ; POReset.write(0); wait(60, SC_NS) ; POReset.write(1); } 2.2.2. Generate Clock and Dump Wave 以下给出了testbench的顶层代码,要注意的是:时钟的产生必须在main顶层,不能放在子模块中产生。 /****************************************************** Filename : main.cpp Auther : Richeal.Li Date : 2006-09-08 Description : The testbench of rst_ctrl ******************************************************/ #include "rst_ctrl.h" #include "gen_poreset.h" int sc_main(int argc, char * argv[]){ sc_signal <bool> rst_n ; sc_signal <bool> prst ; sc_trace_file * tf; //建立文件指针 sc_clock clk("clk", 20, SC_NS); //产生时钟 gen_poreset u_gen_poreset("gen_poreset"); u_gen_poreset.POReset(prst) ; rst_ctrl u_rst_ctrl("u_rst_ctrl"); u_rst_ctrl.HCLK(clk) ; u_rst_ctrl.POReset(prst) ; u_rst_ctrl.HRESETn(rst_n) ; tf = sc_create_vcd_trace_file("dump"); //dump波形,波形为VCD格式 sc_trace(tf, clk, "HCLK") ; sc_trace(tf, prst, "POReset") ; sc_trace(tf, rst_n, "HRESETn") ; sc_start(500, SC_NS); //设置运行时间 sc_close_vcd_trace_file(tf); cout << "Finished at time " << sc_time_stamp() << endl; return 0; } 3. Compile design and watch wave 3.1. For Linux 3.1.1. Create Makefile 要在Linux环境下编译SystemC的工程,需要编写Makefile。假设我们已经建立了一个名叫rst_ctrl的文件夹,里面包含了以上给出的5个设计文件:main.cpp,rst_ctrl.cpp,rst_ctrl.h,gen_poreset.cpp,gen_poreset.h。 为了编译这些文件,我们需要Makefile和Makefile.defs两个文件。Makefile的内容如下图所示,请大家仅仅修改第10行和第11行。其中,MODULE的含义并不是设计的模块名,而是编译以后可执行文件的名字。在SRCS里仅指定.cpp文件即可,不用指定.h文件 Makefile.defs文件较长,在这里不再专门列出。设计者只需要修改第一行,指定SystemC的安装目录即可。图下是Makefile.defs的部分内容,只需修改蓝色部分即可,其余部分不要修改。 在编写完Makefile和Makefile.defs文件后,输入命令: make –f Makefile 编译成功后,将会产生rst_ctrl.exe。运行它,得到最后的仿真结果。 3.1.2. Watch wave 我们常用的Debussy和Virsim都可以察看VCD文件,下面以Virsim为例简述查看的过程。 输入vcs –RPP打开Virsim,在file->open中选择产生的VCD文件。 打开波形,添加想要观察的端口,就可以查看波形了。 3.2. For Windows 3.2.1. Create New Project 点击File->New,选择Win32 Console Application,输入工程的名字及路径,建立新工程。 3.2.2. Project Settings 点击Project->Settings(或者按Alt+F7),完成以下三步。 1、 选择C/C++栏中C++ language分类,选上RTTI(红线部分); 2、 选择C/C++栏中Preprocessor分类,指定路径(红线部分); 3、 选择link栏中Input分类,指定路径(红线部分),并且手动在Project Options中输入systemc.lib。 完成了以上三步,一个SystemC的工程就创建完毕了。接下来的工作仅仅是往工程中添加相应的设计文件,然后再编译即可。 3.2.3. Watch wave 在Windows环境下可以利用Modelsim来查看VCD文件。以下详述用Modelsim查看VCD文件的流程。 1、 创建Modelsim新工程,为了使用起来方便,我们有意将Modelsim的工程目录和SystemC设计目录设置成同一个。例如: 2、 将VCD文件,例如:dump.vcd添加至这个新工程里头来。 3、 输入命令:vcd2wlf dump.vcd dump.wlf,将VCD文件转换成Modelsim可以读取的wlf文件。 4、 打开dump.wlf文件,就可以查看仿真波形了。在这里,为了将来查看新仿真结果的方便,建议将dump.wlf也添加到工程中来。将来每次vcd2wlf命令操作后,就可以直接双击wlf文件来查看波形了。
5、 双击dump.wlf,察看波形。
|