一般情况下,我们都是在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的博客-优快云博客 中有提到,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;
}
打印结果如下: