SC_THREAD 和SC_METHOD如果需要对同一个信号( sc_signal /sc_in/ sc_out)进行操作,比如在thread中进行write,在method中读,可能会打破SC_METHOD的clock触发机制,使得当拍write的值在当拍就能被read到。
如文章最后源码中,TestThread在2ns 对m_sig赋值为1,按照正常逻辑,2ns 的read值依然是0,3ns才能read到值为1。从仿真结果来看,2ns时,TestThread中read值为0,正确;但TestMethod读到的值却是1,显然TestMethod提前读到了write的新值。这就出现了SC_THREAD 和SC_METHOD之间的交互问题。
解决方法:在TestThread中,write新值之前,wait SC_ZERO_TIME (delta time)或者wait 1 FS。FS (femto second) 飞秒,1PS = 1000 FS,FS是systemC支持的时间最小颗粒度。Write之前增加wait 1FS,可以保证其他thread或method在同一拍的read执行在前,那read的值自然就是上一拍的值了。
源代码对应的仿真结果如下。可以看到增加wait SC_ZERO_TIME后,4ns thread write值为2,5ns method才读到。增加wait 1 FS后,6ns thread write值为3,7ns method才读到。
/*
Original 2020-04-05
README:
This is a example can teach you how to fix the error
when SC_METHOD and SC_THREAD operate a same sc_signal
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 :
*/
#include <iostream>
#include "systemc.h"
using namespace std;
class MyTest
: public sc_module
{
public:
SC_HAS_PROCESS(MyTest);
MyTest(const sc_module_name& name)
: sc_module(name)
,m_period (sc_time(1000,SC_PS))
,m_sig("test_sig")
,m_in_clk("in_clk")
{
SC_METHOD(TestMethod);
sensitive << m_in_clk.pos() ; // static sensitive event
dont_initialize();
SC_THREAD(TestThread);
m_sig.write(0);
};
public:
void TestMethod();
void TestThread();
~MyTest(){
;}
public:
sc_time m_period;
sc_signal<sc_uint<5> > m_sig; // must have a blank in <sc_uint<5> >
sc_in_clk m_in_clk;
};
void MyTest::TestMethod()
{
cout<<" ["<<sc_time_stamp()<<"]"<< " Method read is "<< m_sig.read() <<endl;
}
void MyTest::TestThread()
{
wait(2 *m_period);
m_sig.write(1);
cout<<" ["<<sc_time_stamp()<<"]"<< " Thread write 1, read is "<< m_sig.read() <<endl;
wait(2 *m_period);
wait(SC_ZERO_TIME);
m_sig.write(2);
cout<<" ["<<sc_time_stamp()<<"]"<< " Thread write 2, read is "<< m_sig.read() <<endl;
wait(2 *m_period);
wait(1,SC_FS);
m_sig.write(3);
cout<<" ["<<sc_time_stamp()<<"]"<< " Thread write 3, read is "<< m_sig.read() <<endl;
}
int sc_main(int argc, char** argv)
{
MyTest * m_test;
m_test = new MyTest("MyTest");
sc_clock m_clk ("Clock",m_test->m_period);
m_test->m_in_clk( m_clk );
sc_start(10,SC_NS);
return 0;
}
}