systemc: sc_event和sc_event_finder

在使用systemC模拟RTL的时序行为时,往往需要将clock的上升沿作为SC_METHOD的敏感事件列表。而设置敏感事件列表时,我们会遇到sensitive << sc_in_clk.pos() 和sensitive << sc_in_clk. posedge_event () 两种形式。那pos()和posedge_event ()有什么区别呢?
查阅systemc使用手册或systemc源代码,我们发现typedef sc_in sc_in_clk ,也就是说sc_in_clk 就是sc_in的一个别名,进一步查看sc_in的内置函数,发现pos()的返回值是sc_event_finder,而posedge_event ()的返回值是sc_event。

const sc_event& default_event() const;
const sc_event& value_changed_event() const;
const sc_event& posedge_event() const;
const sc_event& negedge_event() const;

sc_event_finder& value_changed() const;
sc_event_finder& pos() const;
sc_event_finder& neg() const;

查看systemc使用手册中sc_event_finder的相关章节,有这样的一段描述。
An event finder function is called when creating static sensitivity to events through a port. Because port binding may be deferred, it may not be possible for the implementation to retrieve an event to which a process is to be made sensitive at the time the process instance is created. Instead, an application should call an event finder function, in which case the implementation shall defer the adding of events to the static sensitivity of the process until port binding has been completed. These deferred actions shall be completed by the implementation before the callbacks to function end_of_elaboration.
简单翻译一下:
因为port 绑定可能会有延后,导致在创建process实例时,不能检索(此port相关的)敏感事件。这种情况下,一个process实例可以调用sc_event_finder函数, port相关的事件将会推迟添加,直到port绑定完成之后再添加到process实例的静态敏感事件列表中去。这个推迟的动作将在end_of_elaboration函数回调之前实施。
也就是说,sc_event_finder一般用在配置静态敏感事件上,在end_of_elaboration函数回调之前使用。在SC_METHOD和SC_THREAD的函数实现中,也就是在simulation阶段,不能出现sc_event_finder。而sc_event则广泛应用于SC_METHOD和SC_THREAD的函数实现中,同时也可以作为静态敏感事件添加到SC_METHOD和SC_THREAD。这就是sc_event和sc_event_finder的一个基本区别。
以下通过一个例子,给出三种实现方法,将clock的上升沿作为SC_METHOD的敏感事件列表。
如果我们在一个sc_module的构造函数中添加 SC_METHOD 函数,紧接着添加这个method的静态敏感事件sensitive << sc_in_clk.posedge_event()。这个时候就需要格外注意,如果这个 sc_in_clk还没有进行绑定,比如,绑定在sc_module例化后,在top层完成,那么编译没有问题,但在执行程序时,会发生报错,提示有port没有进行绑定。
Error: (E112) get interface failed: port is not bound: port ‘MyTest.in_clk’ (sc_in)
In file: …/…/…/…/src/sysc/communication/sc_port.cpp:231
出现报错的原因就是 sc_in_clk在还没有绑定的时候就被添加到静态敏感事件列表中了,在simulation过程中发现检索不到敏感事件,报错。 修改方法有三种:

  1. 将敏感事件修改为sc_event_finder, sensitive << sc_in_clk.pos()
  2. 在添加 SC_METHOD 函数前,将sc_in_clk进行绑定。
  3. 在end_of_elaboration()函数中添加 SC_METHOD 函数和其敏感事件列表。
    参考 : http://bbs.eetop.cn/thread-467342-1-1.html
    仿真结果为
    在这里插入图片描述
/*
Original 2020-04-11
README:
    This is a example can teach you how to set an sc_in_clk of SC_METHOD 
	here give three solutions, 
	1. use sc_event_finder (sc_in_clk.pos() ) as sensitive
	2. use sc_event (sc_in_clk.posedge_event()) as sensitive, 
		and in_clk must already bind to sc_clock before SC_METHOD
	3. solution 1 & 2 implement in constructor of a sc_module, 
		you also can move SC_METHOD & sensitive to end_of_elaboration(),
		then you can use sc_event as sensitive, and no need bind before.
execute:    
    g++ -g -Wall -lsystemc -m64 -pthread main.cpp  
		-L/$(your systemc path)/lib-linux64 
		-I/$(your systemc path)/include  -I/$(your systemc path)/src/tlm_utils -o sim
NOTE :
	1. if you add SC_METHOD in constructor of a sc_module,
		use sc_event as sensitive, and no bind to sc_clock before SC_METHOD
		no error when compile, but an error like following will occur when execute
	Error: (E112) get interface failed: port is not bound: port 'MyTest.in_clk' (sc_in)
	In file: ../../../../src/sysc/communication/sc_port.cpp:231
*/

#include <iostream>
#include "systemc.h"
using namespace std;

// this is an error example
#if 0
class MyTest: public sc_module
{
    
    
public:
	SC_HAS_PROCESS(MyTest);
	MyTest(const sc_module_name&    name)
	: sc_module(name)
	,m_in_clk("in_clk")
	{
    
    
		SC_METHOD(TestMethod);
		sensitive << m_in_clk.posedge_event(); 	// sc_event
		dont_initialize();
	}
	void TestMethod()
	{
    
    
		cout<<"test sc_event"<<endl;
	}	
	sc_in_clk   m_in_clk;
};
#endif

//this example give three solutions
class MyTest: public sc_module
{
    
    
public:
	SC_HAS_PROCESS(MyTest);
	MyTest(const sc_module_name&    name)
	: sc_module(name)
	,m_clk("m_Clock",sc_time(1000,SC_PS))
	,m_in_clk("in_clk")
	,m_in_clk_2("in_clk_2")
	{
    
    
		SC_METHOD(TestMethod1);
		sensitive << m_in_clk.pos()  ; 			// sc_event_finder
		dont_initialize();

		m_in_clk_2(m_clk);
		SC_METHOD(TestMethod2);
		sensitive << m_in_clk_2.posedge_event() ; // sc event
		dont_initialize();
	};
	void end_of_elaboration()
	{
    
    
		SC_METHOD(TestMethod3);
		sensitive << m_in_clk.posedge_event() ; // sc event
		dont_initialize();
	}
public:
	void TestMethod1();
	void TestMethod2();
	void TestMethod3();
	~MyTest(){
    
    ;}
public:
	sc_clock				m_clk;
	sc_in_clk   			m_in_clk;
	sc_in_clk				m_in_clk_2;
};

void MyTest::TestMethod1()
{
    
    
	cout<<" ["<<sc_time_stamp()<<"]"<< " Method 1" <<endl; 
}
void MyTest::TestMethod2()
{
    
    
	cout<<" ["<<sc_time_stamp()<<"]"<< " Method 2" <<endl; 
}
void MyTest::TestMethod3()
{
    
    
	cout<<" ["<<sc_time_stamp()<<"]"<< " Method 3" <<endl; 
}

int sc_main(int argc, char** argv)
{
    
    
    MyTest *   m_test = new MyTest("MyTest");
	sc_clock   g_clk ("g_Clock",sc_time(1000,SC_PS));
	m_test->m_in_clk( g_clk ); // bind sc_in_clk to sc_clock

    sc_start(3,SC_NS);
    return 0;
}



猜你喜欢

转载自blog.csdn.net/zgcjaxj/article/details/105455330
sc"
sc