SystemC 等待异步事件解决方案

本文为实现 SystemC 响应异步事件 解决方案。

应用场景:

SystemC是一个支持系统事务级、行为级建模的开源的C++ library;

我们将SystemC仿真的模拟叫做模拟器。在很多场景下,模拟器要保持alive,等待异步async事件,做出对应的处理。例如设计一个SystemC消费者模拟器,而生产者程序不属于SystemC仿真范畴,消费者模拟器需要一直保持等待,并在出现数据后进行处理。

         世界上没有东西是完美的啊,倒不如说,同时拥有光明和阴影才是完美的,这样的你才是真正的你。。

                                                                                       ------ 大家好啊 我是 暮冬Z羡慕

以上应用场景应当很常见,但是无论中文网站搜索、SystemC社区、谷歌搜索、Stack Overflow等,都没有合适的解决方案。笔者在综合了解相关问题及做了不少尝试后,给出了较为合适的解决方案。感兴趣的伙伴可以查看以下相关帖子:

Example of main thread controlling sub_thread(systemc module) to complete instructions - SystemC Language - Accellera Systems Initiative Forums

How to make a "single-only" sc_thread wait for a notify() from external host thread - SystemC Language - Accellera Systems Initiative Forums

https://workspace.accellera.org/document/dl/10932

async_request_update example - SystemC Language - Accellera Systems Initiative Forums

c++ - async_request_update() example in SystemC - Stack Overflow

这里是解决方案:

#include <systemc.h>
#include <pthread.h>
#include <unistd.h>

using namespace std;
class ThreadSafeEventIf : public sc_interface {
        virtual void notify(sc_time delay = SC_ZERO_TIME) = 0;
        virtual const sc_event &default_event(void) const = 0;
    protected:
        virtual void update(void) = 0;
};

class ThreadSafeEvent : public sc_prim_channel, public ThreadSafeEventIf {
    public:
        ThreadSafeEvent(const char *name = ""): event(name) {}

        void notify(sc_time delay = SC_ZERO_TIME) {
            this->delay = delay;
            async_request_update();
        }

        const sc_event &default_event(void) const {
            return event;
        }
    protected:
        virtual void update(void) {
            event.notify(delay);
        }
        sc_event event;
        sc_time delay;
};

sc_event GenScEvent;
sc_event workingFinishEvent;  // finish event
int workingFlag = 0;  // maybe dnot need a lock

SC_MODULE(Foo) {
    public:
        SC_CTOR(Foo) {
            SC_THREAD(main);

            SC_METHOD(eventTriggered);
            sensitive << threadSafeEvent;
            dont_initialize();
            SC_METHOD(stopTriggered);
            sensitive << threadStopEvent;
            dont_initialize();
        }
    private:
        void main() {   //extra forever thread to avoid simulation exit
            while (true) {
                usleep(0.05*1000*1000);  // check if there is any instruction every one sec.
                wait(SC_ZERO_TIME);
                if(workingFlag){    // check working
                    wait(workingFinishEvent);  // wait the working finish 
                }
                usleep(0.05*1000*1000);
            }
        }
        void eventTriggered() {
            GenScEvent.notify();
        }
        void stopTriggered(){
            sc_stop();
        }
    public:
        ThreadSafeEvent threadSafeEvent;
        ThreadSafeEvent threadStopEvent;
};

void* PollingThread(void* arg) {
    int cnt = 0;
    Foo *foo = (Foo*)(arg);
    while (cnt<3) {
        cnt++;
        printf("[POLL]: %d: Before generating event from PollingThread \n", cnt);
        usleep(3*1000*1000);
        foo->threadSafeEvent.notify();
        printf("[POLL]: %d: Event notified from PollingThread \n", cnt);
    }
    usleep(5*1000*1000);
    foo->threadStopEvent.notify();
};

class sc_top : public sc_module {
    private:
        SC_HAS_PROCESS(sc_top);
    public:
        sc_top(sc_module_name name="SCTOP"): sc_module(name) {
            SC_THREAD(processing_thread);
        }
        void processing_thread(){
            int cnt =0;
            while (true) {
                printf("[PROC]: processing_thread called \n");
                cout << "[PROC]: Wait GenScEvent  time: " << sc_time_stamp();
                wait(GenScEvent);
                workingFlag = 1;
                cnt++;
                wait(10, SC_SEC);  // advance simulation time
                cout << "[PROC]: Process and Finish "<<cnt << " GenScEvent   time: " << sc_time_stamp();
                workingFinishEvent.notify();
                workingFlag = 0;
            }
        }
};

int sc_main(int argc, char *argv[]) {
    Foo foo("foo");
    sc_top u_sc_top("u_sc_top");
    pthread_t thread;
    pthread_create(&thread, NULL, PollingThread, &foo); 
    sc_start();
    return 0;
}

CMakeLists.txt

cmake_minimum_required (VERSION 3.5)
project (demo)
include_directories (${PROJECT_SOURCE_DIR}/include)

find_library(SystemC_LIB systemc HINTS ${PROJECT_SOURCE_DIR}/lib)
set (syc_LIST ${PROJECT_SOURCE_DIR}/src/syc.cpp)
add_executable (syc ${syc_LIST})
find_package(Threads REQUIRED)
target_link_libraries (syc ${SystemC_LIB} Threads::Threads)

以上代码实现了 :

1.主线程中运行 SystemC仿真模型,子线程中运行异步触发程序 (也可以根据自己的需要反过来,子线程中运行SystemC仿真模型,主线程运行触发程序。)

2.子线程每隔3秒触发一次SystemC仿真模型,主线程中的SystemC进行响应。

3.子线程主动触发三次之后,睡眠5秒,告知SystemC仿真结束。

结果:

   SystemC 2.3.3-Accellera --- Mar 12 2024 15:33:04
        Copyright (c) 1996-2018 by all Contributors,
        ALL RIGHTS RESERVED
[POLL]: 1: Before generating event from PollingThread 
[PROC]: processing_thread called 
[PROC]: Wait GenScEvent  time: 0 s[POLL]: 1: Event notified from PollingThread 
[POLL]: 2: Before generating event from PollingThread 
[PROC]: Process and Finish 1 GenScEvent   time: 10 s[PROC]: processing_thread called 
[PROC]: Wait GenScEvent  time: 10 s[POLL]: 2: Event notified from PollingThread 
[POLL]: 3: Before generating event from PollingThread 
[PROC]: Process and Finish 2 GenScEvent   time: 20 s[PROC]: processing_thread called 
[PROC]: Wait GenScEvent  time: 20 s[POLL]: 3: Event notified from PollingThread 
[PROC]: Process and Finish 3 GenScEvent   time: 30 s[PROC]: processing_thread called 
[PROC]: Wait GenScEvent  time: 30 s
Info: /OSCI/SystemC: Simulation stopped by user.

相关推荐

  1. SystemC 等待异步事件解决方案

    2024-04-22 12:40:04       19 阅读
  2. Vue中等待两个异步请求完成解决方式记录

    2024-04-22 12:40:04       36 阅读
  3. Android事件冲突原理及解决方法

    2024-04-22 12:40:04       37 阅读

最近更新

  1. Mongodb地理信息数据查询

    2024-04-22 12:40:04       0 阅读
  2. uniapp实现图片懒加载 封装组件

    2024-04-22 12:40:04       0 阅读
  3. 有关区块链的一些数学知识储备

    2024-04-22 12:40:04       0 阅读
  4. MICCAI 2023 List of Papers

    2024-04-22 12:40:04       0 阅读
  5. uniapp如何发送websocket请求

    2024-04-22 12:40:04       1 阅读
  6. react

    react

    2024-04-22 12:40:04      1 阅读
  7. 光通信领域常见的会议和期刊总结

    2024-04-22 12:40:04       1 阅读
  8. uniapp上传文件并获取上传进度

    2024-04-22 12:40:04       1 阅读

热门阅读

  1. 常见DNS故障和问题解决过程

    2024-04-22 12:40:04       15 阅读
  2. Linux命令学习—Apache 服务器(下)

    2024-04-22 12:40:04       14 阅读
  3. 星期一(蓝桥杯)

    2024-04-22 12:40:04       16 阅读
  4. Remove the specified nodes in the linked list with dummy header

    2024-04-22 12:40:04       17 阅读
  5. python开发应该具备哪些能力

    2024-04-22 12:40:04       17 阅读
  6. Linux技术问答系列-NO7

    2024-04-22 12:40:04       12 阅读
  7. 【Qt之·Qt插件开发·导出插件类的步骤】

    2024-04-22 12:40:04       15 阅读
  8. C++20实践入门之类模板学习笔记

    2024-04-22 12:40:04       12 阅读
  9. Linux 远程联机服务(二)- Rsh服务器

    2024-04-22 12:40:04       14 阅读
  10. 数据结构-并查集

    2024-04-22 12:40:04       13 阅读
  11. Mac下 allure的下载与配置

    2024-04-22 12:40:04       15 阅读
  12. C - Perfect String

    2024-04-22 12:40:04       17 阅读