SystemC 38 Handle trigger while busy
Trigger Handler
When a thread is busy, it does not listen to incoming trigger. One possible design pattern is to:
- create two threads: a trigger handler, and a task processor.
- action of the trigger handler:
- a) upon receiving the trigger, check if task processor is busy. If not, dispatch the task. Else,
- b) buffer the trigger
- action of the task processor:
- a) execute the task that is dispatched by the trigger handler
- b) upon completion, check the trigger.
- i) if empty, return. Else,
- ii) pop the trigger from the buffer and execute the task
This is similar to a FIFO channel, but works without needing to modify the type of the original trigger.
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
// Learn with Examples, 2020, MIT license
#include <systemc>
#include <deque>
using namespace sc_core;
SC_MODULE(MODULE) {
sc_event trigger, dispatchTask;
std::deque<bool> bufferedEvent; // can use other types to store states needed for the task processor
SC_CTOR(MODULE) {
SC_THREAD(task_trigger);
SC_THREAD(trigger_handler);
sensitive << trigger;
dont_initialize();
SC_THREAD(task_processor);
sensitive << dispatchTask;
dont_initialize();
}
void task_trigger() {
while (sc_time_stamp() < sc_time(5, SC_SEC)) { // fire trigger even second for 5 seconds
trigger.notify();
std::cout << "Trigger task at " << sc_time_stamp().to_seconds() << std::endl;
wait(1, SC_SEC);
}
}
void trigger_handler() {
while (true) {
bufferedEvent.push_back(true); // buffer the trigger
dispatchTask.notify(); // dispatch the task
wait();
}
}
void task_processor() {
while (true) {
while (!bufferedEvent.empty()) { // continue process while there are buffered events
bufferedEvent.pop_front();
std::cout << "Process task at " << sc_time_stamp().to_seconds() << std::endl;
wait(1.3, SC_SEC); // takes 1.3 second to process each trigger
}
wait();
}
}
};
int sc_main(int, char*[]) {
MODULE module("module"); // instantiate module
sc_start(); // run simulation
return 0;
}
// Result:
Trigger task at 0
Process task at 0
Trigger task at 1
Process task at 1.3
Trigger task at 2
Process task at 2.6
Trigger task at 3
Process task at 3.9
Trigger task at 4
Process task at 5.2