预备打工人之SystemC学习(二)——一个全加器的例子

预备打工人之SystemC学习

  • 半加器
  • 全加器
  • 测试模块
    • driver模块
    • monitor负责监控
  • 顶层模块

这是一个全加器的例子。
这个全加器是由两个半加器构成,这样可以学习一下层次的连接与描述。

半加器

一位的半加器就是输入a,b,输出进位符号c和结果sum。由于和c++一样的描述,所以将module定义写在.h文件中,将具体函数写在.c中。
1、首先是.h中

#include "systemc.h"
SC_MODULE(half_add){
	sc_in<bool> a,b;
	sc_out<bool> sum,carry;
	void prc_half_add();
	SC_CTOR(half_add){
	SC_METHOD(prc_half_add);
	sensitive<<a<<b;
	}
};

SC_MODULE类似创建一个类(systemc模板)
定义了两个bool类型的输入a和b,两个输出sum和carry。
定义了主要的函数prc_half_add(),这个函数将在.c中具体定义,并且是关系到输入与输出的。
SC_CTOR是为MODULE定义了构造函数,其中SC_METHOD是将函数加载到模块,sensitive是指敏感列表。

2、下面是cpp内容,具体定义了half_add类下面的具体函数prc_half_add。函数里是输出与输入的关系。

#include "half_add.h"
void half_add::prc_half_add(){
	sum=a*b;
	carry=a&b;
}

全加器

由半加器组成全加器,主要就是调用半加器来构成。和半加器的一样,分为.h和.cpp两个文件。

1、.h文件

#include "systemc.h"
#include "half_add.h"
SC_MODULE(full_add){
    sc_in<bool> a,b,c_i;
    sc_out<bool> sum,carry;
    sc_signal<bool> c1,s1,c2;
    void prc_or();
    half_add * half1_ptr,*half2_ptr;
    SC_CTOR(full_add){
        half1_ptr= new half_add("half1");
        half1_ptr->a(a);
        half1_ptr->b(b);
        half1_ptr->sum(s1);
        half1_ptr->carry(c1);
        half2_ptr= new half_add("half2");
        half2_ptr->a(s1);
        half2_ptr->b(c_i);
        half2_ptr->sum(sum);
        half2_ptr->carry(c2);     
    	SC_METHOD(prc_or);
    	sensitive<<c1<<c2;
    }
    ~full_add(){
      	delete 	half1_ptr;
        delete 	half2_ptr;
	}
};

SC_MODULE中定义了bool的三个输入a,b,c_i 和两个输出sum和carry。
注意到设置了三个bool的信号变量,信号变量是用来链接模块的中间量。
为了调用两个半加器模块,创建了两个指针。
在SC_CTOR中呢,

 half1_ptr= new half_add("half1");

指针分指向新建的创建的半加器,括号里的是自己取的名称。

 half1_ptr->a(a);

并且使用了上述语句将半加器模块的端口与全加器端口连接,两个半加器中模块的连接使用信号。
值得注意的是,因为创建了指针,所以需要析构函数进行释放。

2、.cpp文件

#include "full_add.h"
void full_add::prc_or(){
carry=c1|c2;
}

测试模块

测试模块就是verilog中的test bench。
但是SystemC中,测试模块比较麻烦,需要两个模块,第一个模块是驱动模块产生信号,第二个模块是监视器监控输入输出信号。

driver模块

驱动将产生信号给全加器的输出
1、driver.h驱动

#include "systemc.h"
SC_MODULE(driver){
	sc_out<bool> d_a,d_b,d_cin;
	void prc_driver();
	SC_CTOR(driver){
	SC_THREAD(prc_driver);
	}
};

这里的驱动模块只有输出,这些输出将用于全加器。并且在CTOR中使用的是SC_THREAD而不是SC_METHOD

2、driver.cpp驱动

#include "driver.h"
void driver::prc_driver(){
	sc_uint<3> pattern;
	pattern=0;
	while(1){
		d_a=pattern[0];
		d_b=pattern[1];
		d_cin=pattern[2];
		wait(5,SC_NS);
		pattern++;
	} 
}

创建了3位的变量pattern,将每一位分别赋予a,b,cin,并且过5ns后pattern也会改变

monitor负责监控

1、同样是systemc.h中

#include "systemc.h"
SC_MODULE(monitor){
	sc_in<bool> m_a,m_b,m_cin,m_sum,m_cout;
	void prc_monitor();
	SC_CTOR(monitor){
		SC_METHOD(prc_monitor);
		sensitive<<m_a<<m_b<<m_cin<<m_sum<<m_cout;
	}
};

这个模块就只有输入了
2、在.c文件中具体使用cout来进行输出

#include "monitor.h"
void monitor::prc_monitor(){
	cout<<"At time"<<sc_time_stamp()<<"::";
	cout<<"(a,b,carry_in): ";
	cout<<m_a<<m_b<<m_cin;
	cout<<"(sum,carry): "<<m_sum<<m_cout<<endl;
 }

顶层模块

刚刚每个模块都已经完成,最后需要一个顶层模块全部串起来。

#include "driver.h"
#include "monitor.h"
#include "full_add.h"
int sc_main(int argc,char * argv[]){
	sc_signal<bool> t_a,t_b,t_cin,t_sum,t_cout;
	full_add f1("FULLADDerwithHalfadder");
	f1<<t_a<<t_b<<t_cin<<t_sum<<t_cout;
	driver d1("Generator");
	d1.d_a(t_a);
	d1.d_b(t_b);
	d1.d_cin(t_cin);
	monitor mo1("Monitor");
	mo1<<t_a<<t_b<<t_cin<<t_sum<<t_cout;
	sc_start(100,SC_NS);
	return 0;
}

只要有sc_main函数,程序就会从sc_main开始。
注意,端口的连接只能用信号
所以,创建了一系列的bool值用作信号。
创建了full_add的f1和driver 的d1和monitor 的mo1。
然后就调用,连接
最后 sc_start(100,SC_NS);表示开始仿真100ns。

你可能感兴趣的:(systemc,计算机体系结构,systemc)