本文为实现 SystemC 响应异步事件 解决方案。
应用场景:
SystemC是一个支持系统事务级、行为级建模的开源的C++ library;
我们将SystemC仿真的模拟叫做模拟器。在很多场景下,模拟器要保持alive,等待异步async事件,做出对应的处理。例如设计一个SystemC消费者模拟器,而生产者程序不属于SystemC仿真范畴,消费者模拟器需要一直保持等待,并在出现数据后进行处理。
世界上没有东西是完美的啊,倒不如说,同时拥有光明和阴影才是完美的,这样的你才是真正的你。。
------ 大家好啊 我是 暮冬Z羡慕
以上应用场景应当很常见,但是无论中文网站搜索、SystemC社区、谷歌搜索、Stack Overflow等,都没有合适的解决方案。笔者在综合了解相关问题及做了不少尝试后,给出了较为合适的解决方案。感兴趣的伙伴可以查看以下相关帖子:
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
- #include
- #include
-
- 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 "<
" 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.