SystemC 40 Interrupt a thread while busy


In order for a thread to be interrupted, the following needs to be done:

  1. monitor interrupt while the thread is running
  2. handle the interrupt:
    • a) abort. Or,
    • b) pause, and resume later

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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Learn with Examples, 2020, MIT license
#include <systemc>
using namespace sc_core;

SC_MODULE(MODULE) { // option: action upon interruption. 0: abort; 1: pause and resume
  sc_event trigger, dispatchTask, interrupt, taskDone;
  SC_HAS_PROCESS(MODULE);
  int option;
  sc_time taskDoneTime = SC_ZERO_TIME, taskRemainningTime = SC_ZERO_TIME;
  MODULE(sc_module_name name, int option = 0) : sc_module(name), option(option) {
    SC_THREAD(task_trigger);
    SC_THREAD(interrupt_generator);
    SC_THREAD(trigger_handler); // receive trigger, dispatch task
    sensitive << trigger;
    dont_initialize();
    
    SC_THREAD(task_processor); // process task
    sensitive << dispatchTask;
    dont_initialize();

    SC_THREAD(interrupt_handler); // receive interrupt
    sensitive << interrupt;
    dont_initialize();

    SC_THREAD(task_done);
    sensitive << taskDone;
    dont_initialize();
  }
  void task_trigger() {
    while (sc_time_stamp() < sc_time(2, SC_SEC)) { // fire trigger every second for 2 seconds
      trigger.notify();
      std::cout << name() << ": Trigger task at " << sc_time_stamp().to_seconds() << std::endl;
      wait(1, SC_SEC);
    }
  }
  void interrupt_generator() {
    wait(0.2, SC_SEC); // interrupt fired 0.2 sec after task is triggered
    while (sc_time_stamp() < sc_time(2, SC_SEC)) { // fire interrupt every second for 2 seconds
      interrupt.notify();
      std::cout << name() << ": Interrupt task at " << sc_time_stamp().to_seconds() << std::endl;
      wait(1, SC_SEC);
    }
  }
  void trigger_handler() {
    while (true) {
      dispatchTask.notify(); // dispatch the task
      wait();
    }
  }
  void task_processor() {
    while (true) {
      std::cout << name() << ": Process task at " << sc_time_stamp().to_seconds() << std::endl;
      taskRemainningTime = sc_time(0.5, SC_SEC); // process takes 0.5 sec to finish
      taskDone.notify(taskRemainningTime); // process takes 0.5 second to finish
      taskDoneTime = sc_time_stamp() + taskRemainningTime; // if not interrupted, proc will be done at this time
      wait();
    }
  }
  void interrupt_handler() {
    while (true) {
      taskDone.cancel(); // stop current process
      if (taskRemainningTime > SC_ZERO_TIME) {
        if (option == 0) {
          std::cout << name() << ": Process task aborted at " << sc_time_stamp().to_seconds() << std::endl;
        } else if (option == 1) { // pause and resume
          taskRemainningTime = (taskDoneTime - sc_time_stamp()); // process takes 0.5 sec to finish
          wait(0.3, SC_SEC); // wait 0.3 second, to handle interrupt
          std::cout << name() << ": Process task resumed at " << sc_time_stamp().to_seconds() << std::endl;
          taskDone.notify(taskRemainningTime); // process takes 0.5 second to finish
          taskDoneTime = sc_time_stamp() + sc_time(taskRemainningTime); // if not interrupted, proc will be done at this time
        }
      }
      wait();
    }
  }
  void task_done() {
    while (true) {
      taskRemainningTime = SC_ZERO_TIME;
      std::cout << name() << ": Task completes at " << sc_time_stamp().to_seconds() << std::endl;
      wait();
    }
  }
};

int sc_main(int, char*[]) {
  MODULE module0("module0", 0); // task will be aborted upon interruption
  MODULE module1("module1", 1); // task will pause, and resume after interruption
  sc_start(); // run simulation
  return 0;
}

// Result:
module0: Trigger task at 0
module1: Trigger task at 0
module0: Process task at 0
module1: Process task at 0
module0: Interrupt task at 0.2
module1: Interrupt task at 0.2
module0: Process task aborted at 0.2
module1: Process task resumed at 0.5
module1: Task completes at 0.8
module0: Trigger task at 1
module1: Trigger task at 1
module0: Process task at 1
module1: Process task at 1
module1: Interrupt task at 1.2
module0: Interrupt task at 1.2
module0: Process task aborted at 1.2
module1: Process task resumed at 1.5
module1: Task completes at 1.8

Reference

Notes Mentioning This Note

Table of Contents


Share on: