SystemC 04 SC_HAS_PROCESS
SC_CTOR vs SC_HAS_PROCESS
SC_HAS_PROCESS
is introduced since systemC v2.0. It takes only one argument which is the name of the module class. It is often compared with SC_CTOR. Let’s see how these two macros are defined:
-
SC_SCOR
:#define SC_CTOR(user_module_name) typedef user_module_name SC_CURRENT_USER_MODULE; user_module_name( ::sc_core::sc_module_name )
-
SC_HAS_PROCESS
:#define SC_HAS_PROCESS(user_module_name) typedef user_module_name SC_CURRENT_USER_MODULE
When providing e.g. “module” as input argument to SC_CTOR
and SC_HAS_PROCESS
, they expand to:
-
SC_CTOR(module)
:typedef module SC_CURRENT_USER_MODULE; module( ::sc_core::sc_module_name )
-
SC_HAS_PROCESS(module)
:typedef module SC_CURRENT_USER_MODULE;
From this you can see:
- both defines the “
module
” as “SC_CURRENT_USER_MODULE
”, which is used when registering member functions to simulation kernel viaSC_METHOD/SC_THREAD/SC_CTHREAD.
-
SC_CTOR
also declares a default constructor with module name as the only input argument. The impact is: a)SC_CTOR
saves one line of code to write a constructor file, whereas if usingSC_HAS_PROCESS
, one has to declare a constructor function:module_class_name(sc_module_name name, additional argument ...);
b) sinceSC_CTOR
has a constructor function declaration, it can only be placed inside class header.
When to use SC_HAS_PROCESS
My recommendation:
- Don’t use
SC_CTOR
orSC_HAS_PROCESS
if a module has no simulation process (member functions registered to simulation kernel viaSC_METHOD/SC_THREAD/SC_CTHREAD
) - Use
SC_CTOR
if the module need no additional parameter (other than module name) to instantiate - Use
SC_HAS_PROCESS
when additional parameters are needed during instantiation
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Learn with Examples, 2020, MIT license
#include <systemc>
using namespace sc_core;
SC_MODULE(MODULE_A) { // module without simulation processes doesn't need SC_CTOR or SC_HAS_PROCESS
MODULE_A(sc_module_name name) { // c++ style constructor, the base class is implicitly instantiated with module name.
std::cout << this->name() << ", no SC_CTOR or SC_HAS_PROCESS" << std::endl;
}
};
SC_MODULE(MODULE_B1) { // constructor with module name as the only input argument
SC_CTOR(MODULE_B1) { // implicitly declares a constructor of MODULE_B1(sc_module_name)
SC_METHOD(func_b); // register member function to simulation kernel
}
void func_b() { // define function
std::cout << name() << ", SC_CTOR" << std::endl;
}
};
SC_MODULE(MODULE_B2) { // constructor with module name as the only input argument
SC_HAS_PROCESS(MODULE_B2); // no implicit constructor declarition
MODULE_B2(sc_module_name name) { // explicit constructor declaration, also instantiate base class by default via sc_module(name)
SC_METHOD(func_b); // register member function
}
void func_b() { // define function
std::cout << name() << ", SC_HAS_PROCESS" << std::endl;
}
};
SC_MODULE(MODULE_C) { // pass additional input argument(s)
const int i;
SC_HAS_PROCESS(MODULE_C); // OK to use SC_CTOR, which will also define an un-used constructor: MODULE_A(sc_module_name);
MODULE_C(sc_module_name name, int i) : i(i) { // define the constructor function
SC_METHOD(func_c); // register member function
}
void func_c() { // define function
std::cout << name() << ", additional input argument" << std::endl;
}
};
SC_MODULE(MODULE_D1) { // SC_CTOR inside header, constructor defined outside header
SC_CTOR(MODULE_D1);
void func_d() {
std::cout << this->name() << ", SC_CTOR inside header, constructor defined outside header" << std::endl;
}
};
MODULE_D1::MODULE_D1(sc_module_name name) : sc_module(name) { // defines constructor. Fine with/without "sc_module(name)"
SC_METHOD(func_d);
}
SC_MODULE(MODULE_D2) { // SC_HAS_PROCESS inside header, constructor defined outside header
SC_HAS_PROCESS(MODULE_D2);
MODULE_D2(sc_module_name); // declares constructor
void func_d() {
std::cout << this->name() << ", SC_CTOR inside header, constructor defined outside header" << std::endl;
}
};
MODULE_D2::MODULE_D2(sc_module_name name) : sc_module(name) { // defines constructor. Fine with/without "sc_module(name)"
SC_METHOD(func_d);
}
SC_MODULE(MODULE_E) { // SC_CURRENT_USER_MODULE and constructor defined outside header
MODULE_E(sc_module_name name); // c++ style constructor declaration
void func_e() {
std::cout << this->name() << ", SC_HAS_PROCESS outside header, CANNOT use SC_CTOR" << std::endl;
}
};
MODULE_E::MODULE_E(sc_module_name name) { // constructor definition
SC_HAS_PROCESS(MODULE_E); // NOT OK to use SC_CTOR
SC_METHOD(func_e);
}
int sc_main(int, char*[]) {
MODULE_A module_a("module_a");
MODULE_B1 module_b1("module_b1");
MODULE_B2 module_b2("module_b2");
MODULE_C module_c("module_c", 1);
MODULE_D1 module_d1("module_d1");
MODULE_D2 module_d2("module_d2");
MODULE_E module_e("module_e");
sc_start();
return 0;
}
// Result
module_a, no SC_CTOR or SC_HAS_PROCESS
module_b1, SC_CTOR
module_b2, SC_HAS_PROCESS
module_c, additional input argument
module_d1, SC_CTOR inside header, constructor defined outside header
module_d2, SC_CTOR inside header, constructor defined outside header
module_e, SC_HAS_PROCESS outside header, CANNOT use SC_CTOR