SystemC/TLM:SC_METHOD 和敏感列表的关系

SC_THREAD和SC_METHOD是在systemC/TLM编程中实现 模拟RTL并行执行的关键所在。
SC_METHOD的实现主体中不能有wait,所以它必须配合sensitive敏感列表一起使用,当敏感列表中的event被notify时,SC_METHOD的函数主体 被执行一次。并且,Method同一拍只能被执行一次。
在SC_METHOD的使用过程中,经常会犯一个错误,就是敏感事件被多次触发时,很有可能会把某些次的触发给隐藏掉。以下给出一个实例。
假设我们要建模这样一个场景:一个pipeline为10T,A 以每隔3T的频率往pipeline入口push,经pipeline的10T后,预期让SC_METHOD执行一次。假设A是从0T开始push,那么我们预期的结果是:在10T,13T,16T…的时候分别执行一次SC_METHOD的内容。
但假设我们在写代码时这样来实现:

/*
Original 2020-03-16
README:
    This is a example of the interrelation between SC_METHOD and sc_event in systemC/TLM

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

*/

#include <iostream>
#include <fstream>
#include "systemc.h"

using namespace std;

class TestPlatform
: public sc_module
{
    public:
        SC_HAS_PROCESS(TestPlatform);

        TestPlatform(const sc_module_name&    name)
        : sc_module(name)
        ,m_period (sc_time(1000,SC_PS))
        ,m_pipeline_delay(m_period * 20)
        {
            SC_METHOD(TestMethod);
            sensitive << m_event <<m_event_2 ;
            dont_initialize();

            SC_THREAD(NotifyEvtThread);
            // SC_THREAD(NotifyEvtThread_2);// this line can enable m_event_2 notify
        };

    public:
        void TestMethod();
        void NotifyEvtThread();
        void NotifyEvtThread_2();

        ~TestPlatform()
        {;}
        
    public:
        sc_time     m_period;
        sc_time     m_pipeline_delay;
        sc_event    m_event;
        sc_event    m_event_2;
};

void TestPlatform::TestMethod()
{
    cout<<" ["<<sc_time_stamp()<<" ]"
        << "ethod execute one time, notify time is "
        << sc_time_stamp() - m_pipeline_delay
        <<endl;
}
void TestPlatform::NotifyEvtThread()
{
    while(1)
    {
        m_event.notify( m_pipeline_delay);
        cout<<" ["<<sc_time_stamp()<<" ]"<< "notify event "<<endl;  
        wait(3 *m_period);  
    }
}

void TestPlatform::NotifyEvtThread_2()
{
    while(1)
    {
        m_event_2.notify( m_pipeline_delay);
        cout<<" ["<<sc_time_stamp()<<" ]"<< "notify event 2222 "<<endl; 
        wait(5 *m_period);
        // wait(3 *m_period);       
    }
}

int main(int argc, char** argv)
{
    TestPlatform *     m_platform;
    m_platform = new  TestPlatform("TestPlatform");
    sc_start(50,SC_NS);
    return 0;
}

那么最终的仿真结果如下,奇怪了,怎么跟预想的不一致呢。
在这里插入图片描述
接着让我们来分析一下原因。实际上,method中只能记录最早的一笔event,之后再有event notify没有用,不会覆盖掉之前的。0T 第1次notify,第一次执行method是20ns,执行method的时候 同时将记录的event删除掉,21ns的时候被notify,然后这个event被记录下来,然后41ns的时候 执行method。
所以说,由于我们将pipeline的10T直接用m_event.notify( m_pipeline_delay);来实现,导致了多次的m_event 触发 被隐藏掉了。
注意:程序中的dont_initialize是为了让0T的时候,SC_METHOD不要强制初始化执行一次。

进一步分析。
如果是sensitive << m_event <<m_event_2 ;则相当于是这个method对应两个坑位,两个event分别进行计时。两个event之间互不影响,应该 也可以查看本次是哪个event导致的method执行,但此功能暂时还不太会用。
假设NotifyEvtThread_2()中每隔5拍m_event_2.notify( m_pipeline_delay),那么仿真结果如下。可以发现SC_METHOD在40ns和41ns的时候分别被执行了一次;分别对应event2和event的notify结果。
在这里插入图片描述

同时,需要注意一点:Method同一拍只能执行一次。如果两个event的notify时间点完全相同,但method依然是只能在同一拍执行一次。可以修改NotifyEvtThread_2()中也是每隔3拍m_event_2.notify( m_pipeline_delay).仿真结果如下。
在这里插入图片描述

综上,我们在使用SC_METHOD的时候一定要特别注意,为了避免不必要的debug,尽量在功能简单的时候使用SC_METHOD,尽量不要出现敏感列表为两个event,尽量不要在多个thread函数中notify event。复杂场景请使用SC_THREAD,以后我们再重点分析。
那怎么才能正确地实现 最初的那个建模场景呢?且看下次分析。

发布了8 篇原创文章 · 获赞 0 · 访问量 190

猜你喜欢

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