概述
simple_perf,SystemC的性能建模示例,也是SystemC中系统级建模的一个入门简介。
SystemC自带example的系列:
SystemC自带example的pipe研习
SystemC自带example的pkt_switch研习
1 simple_perf的基本介绍
这是一个SystemC的性能建模示例,也是SystemC系统级建模的一个入门简介计。建模的系统包含一个生产者和消费者,通过fifo发送字符,fifo将需要确保生产者和消费者之间所有字符可靠地传输。
要达到这样的需求:除非fifo为空,否则消费将每100 ns正好消耗一个字符。除非fifo为满,否则生产者每1000 ns产生1到19个字符。由于字符计数使用随机线性分布,因此平均而言,生产者每100 ns产生一个字符(除非fifo满)。
如果fifo大小足够大,则每个字符的平均传输时间将接近100ns,因为生产者和消费者很少被阻塞。但是,随着fifo大小的减小,平均传输时间将增加,因为生产者有时会在写入时暂停(由于fifo已满),消费者有时会在读取时暂停(由于fifo已空)。
运行此程序时,可以通过命令行参数设置fifo大小。默认情况下,fifo大小为10。当设计被模拟时,十万个字符从生产者转移到消费者,然后显示性能统计数据。
使用此系统级模型,确定以下维持所需的fifo大小:
A) 每个字符的平均传输时间为110 ns
B) 每个字符的平均传输时间为105纳秒
2 fifo的建模
fifo涉及的有宽度、深度、空满标志和读写指针以及in与out的方法。直接分析代码吧。下面先看看新遇见的语法,而后是fifo的设计。
两个基类:写write和读read的定义,用了C++类的纯虚函数。fifo是基于3个基类(sc_channel、write_if、read_if)的派生类,因为写和读是纯虚函数,所以在派生类中重新定义该函数更好地适用于对象。
使用sc_event的wait方法:使用sc_event定义一个事件,通过event.notify来激活事件,使用event.cancel来取消事件,可以将event事件放入到wait语句中使用,来通知一个事件的发生。目的实现fifo满空时的写读反压。
fifo派生类的构造函数和析构函数:初始化和释放了定义的变量,从data的定义来看,深度size,宽度char一个字符。
in方法:fifo只要不满(num_elements == size,暂停写入),就按照(first + num_elements) % size目前fifo元素填充情况循环递增写入空的位置上去,元素个数加1.
out方法:fifo只要不空(num_elements == 0,暂停读取),就按照(first = (first + 1) % size)目前fifo元素填充情况循环递增读取满的位置上去,元素个数减1。
class write_if : virtual public sc_interface
{
public:
virtual void write(char) = 0;
virtual void reset() = 0;
};
class read_if : virtual public sc_interface
{
public:
virtual void read(char &) = 0;
virtual int num_available() = 0;
};
class fifo : public sc_channel, public write_if, public read_if
{
public:
fifo(sc_module_name name, int size_) : sc_channel(name), size(size_)
{
data = new char[size];
num_elements = first = 0;
num_read = max_used = average = 0;
last_time = SC_ZERO_TIME;
}
~fifo()
{
delete[] data;
cout << endl << "Fifo size is: " << size << endl;
cout << "Average fifo fill depth: " << double(average) / num_read << endl;
cout << "Maximum fifo fill depth: " << max_used << endl;
cout << "Average transfer time per character: " << last_time / num_read << endl;
cout << "Total characters transferred: " << num_read << endl;
cout << "Total time: " << last_time << endl;
}
void write(char c) {
if (num_elements == size)
wait(read_event);
data[(first + num_elements) % size] = c;
++ num_elements;
write_event.notify();
}
void read(char &c) {
last_time = sc_time_stamp();
if (num_elements == 0)
wait(write_event);
compute_stats();
c = data[first];
-- num_elements;
first = (first + 1) % size;
read_event.notify();
}
void reset() { num_elements = first = 0; }
int num_available() { return num_elements;}
private:
char *data;
int num_elements, first;
sc_event write_event, read_event;
int size, num_read, max_used, average;
sc_time last_time;
void compute_stats() {
average += num_elements;
if (num_elements > max_used)
max_used = num_elements;
++num_read;
}
};
3 生产者建模
生产者每1000 ns产生1到19个字符,过程基本逻辑两个while循环搞定的,这里新的语法便是SC_HAS_PROCESS,注意使用进程方法没有了SC_CTOR的构造指示,这样做的目前是因为这个类的构造函数我们要传入参数了,至于SC_THREAD进程特性是不变的。
模块间的互联之前一直使用的是sc_signal,常用的还有这个sc_port,在建模时port相较于信号与顶层互联时要简便一些。
class producer : public sc_module
{
public:
sc_port<write_if> out;
SC_HAS_PROCESS(producer);
producer(sc_module_name name) : sc_module(name)
{
SC_THREAD(main);
}
void main()
{
const char *str = "Visit www.accellera.org and see what SystemC can do for you today!n";
const char *p = str;
int total = 100000;
while (true) {
int i = 1 + int(19.0 * rand() / RAND_MAX);
//
1 <= i <= 19
while (--i >= 0) {
out->write(*p++);
if (!*p) p = str;
-- total;
}
if (total <= 0)
break;
wait(1000, SC_NS);
}
}
};
4 消费者建模
每100 ns正好消耗一个字符。
lass consumer : public sc_module
{
public:
sc_port<read_if> in;
SC_HAS_PROCESS(consumer);
consumer(sc_module_name name) : sc_module(name)
{
SC_THREAD(main);
}
void main()
{
char c;
while (true) {
in->read(c);
wait(100, SC_NS);
}
}
};
5 顶层互联
例化时的互联,这种事务级建模的方式要快速而且简便得多。
class top : public sc_module
{
public:
fifo fifo_inst;
producer prod_inst;
consumer cons_inst;
top(sc_module_name name, int size) :
sc_module(name) ,
fifo_inst("Fifo1", size) ,
prod_inst("Producer1") ,
cons_inst("Consumer1")
{
prod_inst.out(fifo_inst);
cons_inst.in(fifo_inst);
}
};
int sc_main (int argc , char *argv[])
{
int size = 10;
if (argc > 1)
size = atoi(argv[1]);
if (size < 1)
size = 1;
if (size > 100000)
size = 100000;
top top1("Top1", size);
sc_start();
return 0;
}
最后
以上就是现实橘子为你收集整理的SystemC自带example的simple_perf研习1 simple_perf的基本介绍2 fifo的建模3 生产者建模4 消费者建模5 顶层互联的全部内容,希望文章能够帮你解决SystemC自带example的simple_perf研习1 simple_perf的基本介绍2 fifo的建模3 生产者建模4 消费者建模5 顶层互联所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复