112855Sgabeblack@google.com// Reset and kill a thread process, including nested kills
212855Sgabeblack@google.com
312855Sgabeblack@google.com#include <systemc>
412855Sgabeblack@google.com
512855Sgabeblack@google.comusing namespace sc_core;
612855Sgabeblack@google.comusing std::cout;
712855Sgabeblack@google.comusing std::endl;
812855Sgabeblack@google.com
912855Sgabeblack@google.comstruct M3: sc_module
1012855Sgabeblack@google.com{
1112855Sgabeblack@google.com  M3(sc_module_name _name)
1212855Sgabeblack@google.com  {
1312855Sgabeblack@google.com    SC_THREAD(ticker);
1412855Sgabeblack@google.com      k = sc_get_current_process_handle();
1512855Sgabeblack@google.com
1612855Sgabeblack@google.com    SC_THREAD(calling);
1712855Sgabeblack@google.com
1812855Sgabeblack@google.com    SC_THREAD(target);
1912855Sgabeblack@google.com      t = sc_get_current_process_handle();
2012855Sgabeblack@google.com
2112855Sgabeblack@google.com    killing_over = false;
2212855Sgabeblack@google.com  }
2312855Sgabeblack@google.com
2412855Sgabeblack@google.com  sc_process_handle t, k;
2512855Sgabeblack@google.com  sc_event ev;
2612855Sgabeblack@google.com  int count;
2712855Sgabeblack@google.com  bool killing_over;
2812855Sgabeblack@google.com
2912855Sgabeblack@google.com  void ticker()
3012855Sgabeblack@google.com  {
3112855Sgabeblack@google.com    for (;;)
3212855Sgabeblack@google.com    {
3312855Sgabeblack@google.com      try {
3412855Sgabeblack@google.com        wait(10, SC_NS);
3512855Sgabeblack@google.com        ev.notify();
3612855Sgabeblack@google.com      }
3712855Sgabeblack@google.com      catch (const sc_unwind_exception& ex) {
3812855Sgabeblack@google.com        // ticker process killed by target
3912855Sgabeblack@google.com        cout << "sc_unwind_exception caught by ticker" << endl;
4012855Sgabeblack@google.com        sc_assert( !ex.is_reset() );
4112855Sgabeblack@google.com        sc_assert( count == 1 );
4212855Sgabeblack@google.com        sc_assert( !killing_over );
4312855Sgabeblack@google.com        throw ex;
4412855Sgabeblack@google.com      }
4512855Sgabeblack@google.com    }
4612855Sgabeblack@google.com  }
4712855Sgabeblack@google.com
4812855Sgabeblack@google.com  void calling()
4912855Sgabeblack@google.com  {
5012855Sgabeblack@google.com    wait(15, SC_NS);
5112855Sgabeblack@google.com    // Target runs at time 10 NS due to notification
5212855Sgabeblack@google.com    sc_assert( count == 1 );
5312855Sgabeblack@google.com
5412855Sgabeblack@google.com    wait(10, SC_NS);
5512855Sgabeblack@google.com    // Target runs again at time 20 NS due to notification
5612855Sgabeblack@google.com    sc_assert( count == 2 );
5712855Sgabeblack@google.com
5812855Sgabeblack@google.com    t.reset();
5912855Sgabeblack@google.com    // Target reset immediately at time 25 NS
6012855Sgabeblack@google.com    sc_assert( count == 0 );
6112855Sgabeblack@google.com
6212855Sgabeblack@google.com    wait(10, SC_NS);
6312855Sgabeblack@google.com    // Target runs again at time 30 NS due to notification
6412855Sgabeblack@google.com    sc_assert( count == 1 );
6512855Sgabeblack@google.com
6612855Sgabeblack@google.com    t.kill();
6712855Sgabeblack@google.com    sc_assert( !killing_over );
6812855Sgabeblack@google.com    killing_over = true;
6912855Sgabeblack@google.com
7012855Sgabeblack@google.com    // Target killed immediately at time 35 NS
7112855Sgabeblack@google.com    sc_assert( t.terminated() ); // FAILS IN PRESENCE OF k.kill(); on line 96
7212855Sgabeblack@google.com    sc_assert( k.terminated() );
7312855Sgabeblack@google.com
7412855Sgabeblack@google.com    sc_stop();
7512855Sgabeblack@google.com  }
7612855Sgabeblack@google.com
7712855Sgabeblack@google.com  void target()
7812855Sgabeblack@google.com  {
7912855Sgabeblack@google.com    cout << "Target called/reset at " << sc_time_stamp() << endl;
8012855Sgabeblack@google.com    count = 0;
8112855Sgabeblack@google.com    for (;;)
8212855Sgabeblack@google.com    {
8312855Sgabeblack@google.com      try {
8412855Sgabeblack@google.com        wait(ev);
8512855Sgabeblack@google.com        cout << "Target awoke at " << sc_time_stamp() << endl;
8612855Sgabeblack@google.com        ++count;
8712855Sgabeblack@google.com      }
8812855Sgabeblack@google.com      catch (const sc_unwind_exception& ex) {
8912855Sgabeblack@google.com        cout << "sc_unwind_exception caught by target" << endl;
9012855Sgabeblack@google.com        if (count == 2)
9112855Sgabeblack@google.com          sc_assert( ex.is_reset() );
9212855Sgabeblack@google.com        else if (count == 1)
9312855Sgabeblack@google.com        {
9412855Sgabeblack@google.com          sc_assert( !ex.is_reset() );
9512855Sgabeblack@google.com          sc_assert( !killing_over );
9612855Sgabeblack@google.com          k.kill();
9712855Sgabeblack@google.com        }
9812855Sgabeblack@google.com        else
9912855Sgabeblack@google.com          sc_assert( false );
10012855Sgabeblack@google.com        throw ex;
10112855Sgabeblack@google.com      }
10212855Sgabeblack@google.com    }
10312855Sgabeblack@google.com  }
10412855Sgabeblack@google.com
10512855Sgabeblack@google.com  SC_HAS_PROCESS(M3);
10612855Sgabeblack@google.com};
10712855Sgabeblack@google.com
10812855Sgabeblack@google.comint sc_main(int argc, char* argv[])
10912855Sgabeblack@google.com{
11012855Sgabeblack@google.com  M3 m("m");
11112855Sgabeblack@google.com
11212855Sgabeblack@google.com  sc_start();
11312855Sgabeblack@google.com
11412855Sgabeblack@google.com  return 0;
11512855Sgabeblack@google.com}
11612855Sgabeblack@google.com
117