sc_spawn / sc_pawn_options / sc_process_handle

一般情况下,我们都是在module的构造函数中添加SC_THREAD/ SC_METHOD函数(此module需要添加SC_HAS_PROCESS(module_class_name); ),但有些时候,我们需要在simulation过程中添加,这就是sc_spawn的作用,用于在simulation过程中添加 SC_THREAD/ SC_METHOD到systemc kernel。

sc_spawn还有一个作用:现在 有多个 并行的处理逻辑,需要 使用多个不同的 SC_THREAD来分别处理,但这些 SC_THREAD 函数中,大部分逻辑是一样的,只有少部分的 index不同,此时为了代码的简洁性,我们可以写一个 带 index 参数的 函数,然后使用 sc_spawn注册多个 SC_THREAD函数,函数主体为 上述带参函数,注册时,传递不同的index给此函数。如下文示例代码中的 sc_core::sc_spawn (sc_bind(&TestFunction::DyanmicThread,  &m_function,  i, i+3),  

sc_core::sc_gen_unique_name("my_thread")); 这种用法时,一般可将 sc_spawn的逻辑写在module的 构造函数中。

总之,sc_sapwn可以在 systemc的任意阶段使用,比如 构造函数中(elaboration 阶段),在 SC_THREAD 函数中 (simulation阶段)。

sc_spawn需要与sc_spawn_options配合使用,sc_spawn_options中标记此process是thread还是method,默认是thread;如果想配置为method,需要调用一次成员函数spawn_method()。sc_spawn_options的成员函数void set_sensitivity(const sc_event* event)用于标记敏感事件列表,void dont_initialize()用于标识是否需要dont_initialize()。

sc_spawn函数的第一个参数为thread或method函数指针,一般通过sc_bind来实现。sc_bind的第一个参数是 函数名,需要注意的是函数名必须加class name的前缀,故函数可以是本class内的函数,也可以是其他class的函数;如果是本class内的函数,则sc_bind的第二个参数就写 this,如果不是本class的函数,则需要写对应class的指针(需保证此指针是本class的成员变量,保证指针非空)(实际代码中发现,指针 或 实例 都可以work)。如果 thread 或method 函数 含有参数,则直接在sc_bind 的第三个参数处开始添加。

sc_spawn的返回值类型为sc_process_handle,其表示刚刚创建的这个process的句柄,可用于后续对这个process进行控制。

sc_process_handle sc_spawn( 
    T object, 
    const char* name_p = 0,
    const sc_spawn_options* opt_p = 0)

如下为一个示例代码,实现的需求为:2ns时,创建一个method,敏感列表为clk上升沿,method中进行打印操作;5ns时 disable 这个method;10ns时再重新enable 这个method。

其中需要注意,#define SC_INCLUDE_DYNAMIC_PROCESSES是必不可少的,或者显式地include sc_spawn的.h文件;否则编译是过不了的。

#ifdef SC_INCLUDE_DYNAMIC_PROCESSES
#    include "sysc/kernel/sc_dynamic_processes.h"
#endif // SC_INCLUDE_DYNAMIC_PROCESSES

SystemC:SC_THREAD和SC_METHOD_123axj的博客-CSDN博客 中有提到,sc_process_handle sc_get_current_process_handle()可以获取到离它最近的上一个注册函数的句柄,然后就可以在Simulation阶段disable / enable这个processes。示例代码中中的m_method_handle获取的就是TestMethod 这个process的句柄。

cout 颜色输出 参考C/C++改变终端(cout )(printf)输出不同颜色的字体(Linux) - 代码先锋网 ,注意 字符串中的 \033[ m是固定写法,[ 和m中间的数字是 可选择的,对应 参考文章中 颜色和其他属性。

代码中发现,sc_bind(&TestFunction::DyanmicThread, &m_function, i, i+3)  和 sc_bind(&TestFunction::DyanmicThread, m_function, i, i+3)  都可以work。

// 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

#define SC_INCLUDE_DYNAMIC_PROCESSES // must add this define
#include <systemc>

class TestFunction{
public :
  void DyanmicThread(int para1, int para2)
  {
    std::cout << "\033[35m [" << sc_core::sc_time_stamp() << "]"
              << " DyanmicThread " << para1 <<" "<< para2 << " execute.\033[0m" << std::endl;
  }
};

class MySCModule : public sc_core::sc_module
{
public:
  SC_HAS_PROCESS(MySCModule); // must have this line
  explicit MySCModule(sc_core::sc_module_name name)
      : sc_core::sc_module(name),
        m_clk("m_Clock", sc_core::sc_time(1, sc_core::SC_NS)),
        m_in_clk("in_clk") {
    m_in_clk(m_clk);
    SC_THREAD(MainThread);

    SC_METHOD(TestMethod);
    sensitive << m_in_clk.posedge_event(); // sc_event
    dont_initialize();
    m_method_handle = sc_core::sc_get_current_process_handle();

    for(int i = 0 ; i < 5 ; ++i){
      // must add MySCModule:: prefix
      sc_core::sc_spawn(sc_bind(&TestFunction::DyanmicThread, &m_function, i, i+3),
                        sc_core::sc_gen_unique_name("my_thread"));
    }
  }

  void TestMethod() {
    std::cout << "\033[31m [" << sc_core::sc_time_stamp() << "]"
              << " TestMethod execute.\033[0m" << std::endl;
  }

  void DynamicMethod() {
    std::cout << "\033[33m [" << sc_core::sc_time_stamp() << "]"
              << " DynamicMethod execute.\033[0m" << std::endl;
  }

  void MainThread() {
    wait(2, sc_core::SC_NS);
    std::cout << " [" << sc_core::sc_time_stamp() << "] launch DynamicMethod "
              << std::endl;
    sc_core::sc_spawn_options t_opts;
    t_opts.spawn_method(); // if you want to create a SC_THREAD, need del this
                           // line
    t_opts.set_sensitivity(&m_in_clk.posedge_event());
    t_opts.dont_initialize();
    sc_core::sc_process_handle t_handle =
        sc_core::sc_spawn(sc_bind(&MySCModule::DynamicMethod,
                                  this), // must add MySCModule:: prefix
                          sc_core::sc_gen_unique_name("my_mthod"),
                          &t_opts);

    sc_core::wait(3, sc_core::SC_NS);
    std::cout << " [" << sc_core::sc_time_stamp() << "] disable DynamicMethod "
              << std::endl;
    t_handle.disable();
    sc_core::wait(5, sc_core::SC_NS);
    std::cout << " [" << sc_core::sc_time_stamp() << "] enable DynamicMethod "
              << std::endl;
    t_handle.enable();
    m_method_handle.disable();
  }

  sc_core::sc_clock m_clk;
  sc_core::sc_in_clk m_in_clk;
  sc_core::sc_process_handle m_method_handle;
  TestFunction m_function;
};

int sc_main(int argc, char **argv) {
  MySCModule m_top_module("my_top_module");
  sc_core::sc_start(20, sc_core::SC_NS);
  return 0;
}


打印结果如下:

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

123axj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值