112855Sgabeblack@google.com
212855Sgabeblack@google.com// General tests combining features of SystemC 2.1 and 1666
312855Sgabeblack@google.com
412855Sgabeblack@google.com
512855Sgabeblack@google.com#define SC_INCLUDE_DYNAMIC_PROCESSES
612855Sgabeblack@google.com
712855Sgabeblack@google.com#include <systemc>
812855Sgabeblack@google.comusing sc_core::sc_interface;
912855Sgabeblack@google.comusing sc_core::sc_object;
1012855Sgabeblack@google.comusing sc_core::sc_port;
1112855Sgabeblack@google.comusing sc_core::sc_export;
1212855Sgabeblack@google.comusing sc_core::sc_module;
1312855Sgabeblack@google.comusing sc_core::sc_module_name;
1412855Sgabeblack@google.comusing sc_core::sc_in;
1512855Sgabeblack@google.comusing sc_core::sc_in_clk;
1612855Sgabeblack@google.comusing sc_core::sc_signal;
1712855Sgabeblack@google.comusing sc_core::sc_prim_channel;
1812855Sgabeblack@google.comusing sc_core::sc_event;
1912855Sgabeblack@google.comusing sc_core::sc_delta_count;
2012855Sgabeblack@google.comusing sc_core::sc_is_running;
2112855Sgabeblack@google.comusing sc_core::sc_get_top_level_objects;
2212855Sgabeblack@google.comusing sc_core::sc_find_object;
2312855Sgabeblack@google.comusing sc_core::sc_report;
2412855Sgabeblack@google.comusing sc_core::sc_report_handler;
2512855Sgabeblack@google.comusing sc_core::sc_actions;
2612855Sgabeblack@google.comusing sc_core::SC_INFO;
2712855Sgabeblack@google.comusing sc_core::SC_UNSPECIFIED;
2812855Sgabeblack@google.comusing sc_core::SC_THROW;
2912855Sgabeblack@google.comusing sc_core::sc_spawn;
3012855Sgabeblack@google.comusing sc_core::sc_process_handle;
3112855Sgabeblack@google.comusing sc_core::sc_get_current_process_handle;
3212855Sgabeblack@google.comusing sc_core::sc_time;
3312855Sgabeblack@google.comusing sc_core::sc_time_stamp;
3412855Sgabeblack@google.comusing sc_core::SC_ZERO_TIME;
3512855Sgabeblack@google.comusing sc_core::SC_PS;
3612855Sgabeblack@google.comusing sc_core::SC_NS;
3712855Sgabeblack@google.comusing sc_core::SC_US;
3812855Sgabeblack@google.comusing sc_core::sc_start_of_simulation_invoked;
3912855Sgabeblack@google.comusing sc_core::sc_end_of_simulation_invoked;
4012855Sgabeblack@google.comusing sc_core::sc_start;
4112855Sgabeblack@google.comusing sc_core::sc_stop;
4212855Sgabeblack@google.comusing sc_core::sc_copyright;
4312855Sgabeblack@google.comusing sc_core::sc_version;
4412855Sgabeblack@google.comusing sc_core::sc_release;
4512855Sgabeblack@google.comusing sc_dt::sc_abs;
4612855Sgabeblack@google.comusing sc_dt::sc_max;
4712855Sgabeblack@google.comusing sc_dt::sc_min;
4812855Sgabeblack@google.comusing sc_dt::sc_int;
4912855Sgabeblack@google.comusing sc_dt::sc_bigint;
5012855Sgabeblack@google.comusing std::cout;
5112855Sgabeblack@google.comusing std::endl;
5212855Sgabeblack@google.com
5312855Sgabeblack@google.com#if defined(IEEE_1666_CPLUSPLUS) && IEEE_1666_CPLUSPLUS >= 201103L
5412855Sgabeblack@google.com// dynamic process macros have been moved to functions on C++11
5512855Sgabeblack@google.comusing sc_core::sc_bind;
5612855Sgabeblack@google.comusing sc_core::sc_ref;
5712855Sgabeblack@google.comusing sc_core::sc_cref;
5812855Sgabeblack@google.com#endif // IEEE_1666_CPLUSPLUS
5912855Sgabeblack@google.com
6012855Sgabeblack@google.comstruct i_f: virtual sc_interface
6112855Sgabeblack@google.com{
6212855Sgabeblack@google.com  virtual void write() = 0;
6312855Sgabeblack@google.com};
6412855Sgabeblack@google.com
6512855Sgabeblack@google.comvoid check_form_of_suffix(std::string s)
6612855Sgabeblack@google.com{
6712855Sgabeblack@google.com  std::string charset = "0123456789";
6812855Sgabeblack@google.com  while (!s.empty())
6912855Sgabeblack@google.com  {
7012855Sgabeblack@google.com    sc_assert(s[0] == '_');
7112855Sgabeblack@google.com  s = s.substr(1);
7212855Sgabeblack@google.com  sc_assert(!s.empty());
7312855Sgabeblack@google.com  do
7412855Sgabeblack@google.com  {
7512855Sgabeblack@google.com    sc_assert(charset.find(s[0]) < charset.size());
7612855Sgabeblack@google.com    s = s.substr(1);
7712855Sgabeblack@google.com  } while (!s.empty() && (s[0] != '_'));
7812855Sgabeblack@google.com  }
7912855Sgabeblack@google.com}
8012855Sgabeblack@google.com
8112855Sgabeblack@google.comstruct Chan: i_f, sc_object
8212855Sgabeblack@google.com{
8312855Sgabeblack@google.com  virtual void write()
8412855Sgabeblack@google.com  {
8512855Sgabeblack@google.com    sc_assert(std::string(name()).substr(0,17) == "top.m_dest.object");
8612855Sgabeblack@google.com    check_form_of_suffix(std::string(name()).substr(17));
8712855Sgabeblack@google.com  }
8812855Sgabeblack@google.com};
8912855Sgabeblack@google.com
9012855Sgabeblack@google.comstruct M_src: sc_core::sc_behavior
9112855Sgabeblack@google.com{
9212855Sgabeblack@google.com  sc_port<i_f>* p;
9312855Sgabeblack@google.com  SC_HAS_PROCESS(M_src);
9412855Sgabeblack@google.com
9512855Sgabeblack@google.com  M_src(sc_module_name _name)
9612855Sgabeblack@google.com  {
9712855Sgabeblack@google.com    p = new sc_port<i_f>;
9812855Sgabeblack@google.com
9912855Sgabeblack@google.com    SC_THREAD(T);
10012855Sgabeblack@google.com  }
10112855Sgabeblack@google.com  void T()
10212855Sgabeblack@google.com  {
10312855Sgabeblack@google.com    (*p)->write();
10412855Sgabeblack@google.com  }
10512855Sgabeblack@google.com};
10612855Sgabeblack@google.com
10712855Sgabeblack@google.comstruct M_dest: sc_core::sc_channel
10812855Sgabeblack@google.com{
10912855Sgabeblack@google.com  sc_export<i_f>* xp;
11012855Sgabeblack@google.com  SC_HAS_PROCESS(M_dest);
11112855Sgabeblack@google.com
11212855Sgabeblack@google.com  M_dest(sc_module_name _name)
11312855Sgabeblack@google.com  {
11412855Sgabeblack@google.com    xp = new sc_export<i_f>;
11512855Sgabeblack@google.com    Chan* ch = new Chan;
11612855Sgabeblack@google.com    xp->bind(*ch);
11712855Sgabeblack@google.com  }
11812855Sgabeblack@google.com};
11912855Sgabeblack@google.com
12012855Sgabeblack@google.comvoid f()
12112855Sgabeblack@google.com{
12212855Sgabeblack@google.com  ::sc_core::wait(33, SC_PS);
12312855Sgabeblack@google.com}
12412855Sgabeblack@google.com
12512855Sgabeblack@google.comstruct Prim: sc_prim_channel
12612855Sgabeblack@google.com{
12712855Sgabeblack@google.com  Prim() : cref_arg(1) {}
12812855Sgabeblack@google.com
12912855Sgabeblack@google.com  void write() { request_update(); }
13012855Sgabeblack@google.com
13112855Sgabeblack@google.com  void update()
13212855Sgabeblack@google.com  {
13312855Sgabeblack@google.com    sc_spawn(sc_bind(&Prim::proc, this));
13412855Sgabeblack@google.com  }
13512855Sgabeblack@google.com
13612855Sgabeblack@google.com  void proc()
13712855Sgabeblack@google.com  {
13812855Sgabeblack@google.com    ev.notify(SC_ZERO_TIME);
13912855Sgabeblack@google.com    wait(ev);
14012855Sgabeblack@google.com    cout << "Prim::Proc spawned and resumed" << endl;
14112855Sgabeblack@google.com    SC_FORK
14212855Sgabeblack@google.com      sc_spawn(sc_bind(&Prim::Th, this, 1)),
14312855Sgabeblack@google.com      sc_spawn(sc_bind(&Prim::Th, this, 2))
14412855Sgabeblack@google.com    SC_JOIN
14512855Sgabeblack@google.com    sc_spawn(sc_bind(&Prim::Th_ref, this, sc_ref(ref_arg)));
14612855Sgabeblack@google.com    sc_spawn(sc_bind(&Prim::Th_cref, this, sc_cref(cref_arg)));
14712855Sgabeblack@google.com    wait(1, SC_NS);
14812855Sgabeblack@google.com    sc_assert(ref_arg == 99);
14912855Sgabeblack@google.com  }
15012855Sgabeblack@google.com  sc_event ev;
15112855Sgabeblack@google.com  void Th(int i)
15212855Sgabeblack@google.com  {
15312855Sgabeblack@google.com    cout << "Th::i=" << i << endl;
15412855Sgabeblack@google.com  }
15512855Sgabeblack@google.com  void Th_ref(int& arg)
15612855Sgabeblack@google.com  {
15712855Sgabeblack@google.com    arg = 99;
15812855Sgabeblack@google.com    sc_time t(sc_time_stamp());
15912855Sgabeblack@google.com    sc_process_handle h = sc_spawn(&f);
16012855Sgabeblack@google.com    wait(h.terminated_event());
16112855Sgabeblack@google.com    sc_assert(sc_time_stamp() == t + sc_time(33, SC_PS));
16212855Sgabeblack@google.com  }
16312855Sgabeblack@google.com  void Th_cref(const int& arg)
16412855Sgabeblack@google.com  {
16512855Sgabeblack@google.com  }
16612855Sgabeblack@google.com  int ref_arg;
16712855Sgabeblack@google.com  const int cref_arg;
16812855Sgabeblack@google.com};
16912855Sgabeblack@google.com
17012855Sgabeblack@google.comSC_MODULE(M)
17112855Sgabeblack@google.com{
17212855Sgabeblack@google.com  Prim prim;
17312855Sgabeblack@google.com  SC_CTOR(M)
17412855Sgabeblack@google.com  {
17512855Sgabeblack@google.com    SC_THREAD(T);
17612855Sgabeblack@google.com  }
17712855Sgabeblack@google.com
17812855Sgabeblack@google.com  void T()
17912855Sgabeblack@google.com  {
18012855Sgabeblack@google.com    wait(10, SC_NS);
18112855Sgabeblack@google.com    try {
18212855Sgabeblack@google.com      sc_report_handler::set_actions("msg_type", SC_INFO, SC_THROW);
18312855Sgabeblack@google.com      SC_REPORT_INFO("msg_type", "msg");
18412855Sgabeblack@google.com    }
18512855Sgabeblack@google.com    catch (sc_report& rpt) {
18612855Sgabeblack@google.com      cout << "Caught rpt " << rpt.what() << endl;
18712855Sgabeblack@google.com      sc_assert(rpt.get_severity() == SC_INFO);
18812855Sgabeblack@google.com      sc_assert(std::string(rpt.get_msg_type()) == "msg_type");
18912855Sgabeblack@google.com      sc_assert(std::string(rpt.get_msg()) == "msg");
19012855Sgabeblack@google.com      sc_assert(rpt.get_time() == sc_time(10, SC_NS));
19112855Sgabeblack@google.com      sc_assert(std::string(rpt.get_process_name()) == "top.m.T");
19212855Sgabeblack@google.com
19312855Sgabeblack@google.com      sc_assert(sc_report_handler::get_count(SC_INFO) == 1);
19412855Sgabeblack@google.com      sc_report rpt2 = rpt; // Copy constructor
19512855Sgabeblack@google.com
19612855Sgabeblack@google.com      prim.write();
19712855Sgabeblack@google.com
19812855Sgabeblack@google.com      sc_spawn(sc_bind(&M::proc, this, &rpt2));
19912855Sgabeblack@google.com      wait(100, SC_NS);
20012855Sgabeblack@google.com    }
20112855Sgabeblack@google.com  }
20212855Sgabeblack@google.com  void proc(sc_report* rpt)
20312855Sgabeblack@google.com  {
20412855Sgabeblack@google.com    sc_assert(rpt->get_severity() == SC_INFO);
20512855Sgabeblack@google.com    sc_assert(std::string(rpt->get_msg_type()) == "msg_type");
20612855Sgabeblack@google.com    sc_assert(std::string(rpt->get_msg()) == "msg");
20712855Sgabeblack@google.com    sc_assert(rpt->get_time() == sc_time(10, SC_NS));
20812855Sgabeblack@google.com    sc_assert(std::string(rpt->get_process_name()) == "top.m.T");
20912855Sgabeblack@google.com    rpt->get_file_name();
21012855Sgabeblack@google.com    rpt->get_line_number();
21112855Sgabeblack@google.com  }
21212855Sgabeblack@google.com};
21312855Sgabeblack@google.com
21412855Sgabeblack@google.comstruct CM: sc_module
21512855Sgabeblack@google.com{
21612855Sgabeblack@google.com  sc_in_clk clk;
21712855Sgabeblack@google.com  sc_in<bool> reset;
21812855Sgabeblack@google.com
21912855Sgabeblack@google.com  SC_HAS_PROCESS(CM);
22012855Sgabeblack@google.com
22112855Sgabeblack@google.com  CM(sc_module_name _name)
22212855Sgabeblack@google.com  : first(true)
22312855Sgabeblack@google.com  {
22412855Sgabeblack@google.com    SC_CTHREAD(CT, clk.pos());
22512855Sgabeblack@google.com      reset_signal_is(reset, true);
22612855Sgabeblack@google.com
22712855Sgabeblack@google.com    sc_assert(sc_start_of_simulation_invoked() == false);
22812855Sgabeblack@google.com    sc_assert(sc_end_of_simulation_invoked() == false);
22912855Sgabeblack@google.com    sc_assert(sc_is_running() == false);
23012855Sgabeblack@google.com  }
23112855Sgabeblack@google.com
23212855Sgabeblack@google.com  bool first;
23312855Sgabeblack@google.com
23412855Sgabeblack@google.com  void CT()
23512855Sgabeblack@google.com  {
23612855Sgabeblack@google.com    if (first)
23712855Sgabeblack@google.com      sc_assert(sc_time_stamp() == sc_time(5, SC_US));
23812855Sgabeblack@google.com    else
23912855Sgabeblack@google.com      sc_assert(sc_time_stamp() == sc_time(30, SC_US));
24012855Sgabeblack@google.com    first = false;
24112855Sgabeblack@google.com
24212855Sgabeblack@google.com    sc_assert(sc_start_of_simulation_invoked() == true);
24312855Sgabeblack@google.com    sc_assert(sc_end_of_simulation_invoked() == false);
24412855Sgabeblack@google.com    sc_assert(sc_is_running() == true);
24512855Sgabeblack@google.com
24612855Sgabeblack@google.com    while(1)
24712855Sgabeblack@google.com    {
24812855Sgabeblack@google.com      wait();
24912855Sgabeblack@google.com      sc_assert(sc_time_stamp() == sc_time(15, SC_US));
25012855Sgabeblack@google.com      wait();
25112855Sgabeblack@google.com      sc_assert(sc_time_stamp() == sc_time(25, SC_US));
25212855Sgabeblack@google.com      wait();
25312855Sgabeblack@google.com      sc_assert(false);
25412855Sgabeblack@google.com    }
25512855Sgabeblack@google.com  }
25612855Sgabeblack@google.com
25712855Sgabeblack@google.com  void start_of_simulation()
25812855Sgabeblack@google.com  {
25912855Sgabeblack@google.com    sc_assert(sc_start_of_simulation_invoked() == false);
26012855Sgabeblack@google.com    sc_assert(sc_end_of_simulation_invoked() == false);
26112855Sgabeblack@google.com    sc_assert(sc_is_running() == false);
26212855Sgabeblack@google.com  }
26312855Sgabeblack@google.com
26412855Sgabeblack@google.com  void end_of_simulation()
26512855Sgabeblack@google.com  {
26612855Sgabeblack@google.com    sc_assert(sc_start_of_simulation_invoked() == true);
26712855Sgabeblack@google.com    sc_assert(sc_end_of_simulation_invoked() == false);
26812855Sgabeblack@google.com    sc_assert(sc_is_running() == false);
26912855Sgabeblack@google.com  }
27012855Sgabeblack@google.com};
27112855Sgabeblack@google.com
27212855Sgabeblack@google.comSC_MODULE(Top)
27312855Sgabeblack@google.com{
27412855Sgabeblack@google.com  M *m;
27512855Sgabeblack@google.com  CM *cm;
27612855Sgabeblack@google.com
27712855Sgabeblack@google.com  M_src m_src;
27812855Sgabeblack@google.com  M_dest m_dest;
27912855Sgabeblack@google.com
28012855Sgabeblack@google.com  sc_signal<bool> clk, reset;
28112855Sgabeblack@google.com
28212855Sgabeblack@google.com  SC_CTOR(Top)
28312855Sgabeblack@google.com  : m_src("m_src"), m_dest("m_dest")
28412855Sgabeblack@google.com  {
28512855Sgabeblack@google.com    m = new M("m");
28612855Sgabeblack@google.com    cm = new CM("cm");
28712855Sgabeblack@google.com    cm->clk(clk);
28812855Sgabeblack@google.com    cm->reset(reset);
28912855Sgabeblack@google.com
29012855Sgabeblack@google.com    m_src.p->bind( *(m_dest.xp) );  // Port-export binding
29112855Sgabeblack@google.com
29212855Sgabeblack@google.com    SC_THREAD(T);
29312855Sgabeblack@google.com    SC_THREAD(T2);
29412855Sgabeblack@google.com  }
29512855Sgabeblack@google.com  void T()
29612855Sgabeblack@google.com  {
29712855Sgabeblack@google.com    clk = false;
29812855Sgabeblack@google.com    reset = true;
29912855Sgabeblack@google.com    wait(5, SC_US);
30012855Sgabeblack@google.com    clk = true;
30112855Sgabeblack@google.com    wait(5, SC_US);
30212855Sgabeblack@google.com    clk = false;
30312855Sgabeblack@google.com    reset = false;
30412855Sgabeblack@google.com    wait(5, SC_US);
30512855Sgabeblack@google.com    clk = true;
30612855Sgabeblack@google.com    wait(5, SC_US);
30712855Sgabeblack@google.com    clk = false;
30812855Sgabeblack@google.com    wait(5, SC_US);
30912855Sgabeblack@google.com    clk = true;
31012855Sgabeblack@google.com    wait(5, SC_US);
31112855Sgabeblack@google.com    clk = false;
31212855Sgabeblack@google.com    reset = true;
31312855Sgabeblack@google.com    wait(10, SC_US);
31412855Sgabeblack@google.com  }
31512855Sgabeblack@google.com  void T2()
31612855Sgabeblack@google.com  {
31712855Sgabeblack@google.com    sc_assert(sc_min(-1,1) == -1);
31812855Sgabeblack@google.com    sc_assert(sc_max(-1,1) == 1);
31912855Sgabeblack@google.com    sc_assert(sc_abs(-1) == 1);
32012855Sgabeblack@google.com
32112855Sgabeblack@google.com    sc_assert(sc_min(sc_int<8>(-1),sc_int<8>(1)) == sc_int<8>(-1));
32212855Sgabeblack@google.com    sc_assert(sc_max(sc_int<8>(-1),sc_int<8>(1)) == sc_int<8>(1));
32312855Sgabeblack@google.com    sc_assert(sc_abs(sc_int<8>(-1)) == sc_int<8>(1));
32412855Sgabeblack@google.com
32512855Sgabeblack@google.com    sc_assert(sc_min(sc_bigint<256>(-1),sc_bigint<256>(1)) == sc_bigint<256>(-1));
32612855Sgabeblack@google.com    sc_assert(sc_max(sc_bigint<256>(-1),sc_bigint<256>(1)) == sc_bigint<256>(1));
32712855Sgabeblack@google.com    sc_assert(sc_abs(sc_bigint<256>(-1)) == sc_bigint<256>(1));
32812855Sgabeblack@google.com  }
32912855Sgabeblack@google.com};
33012855Sgabeblack@google.com
33112855Sgabeblack@google.comint sc_main(int argc, char* argv[])
33212855Sgabeblack@google.com{
33312855Sgabeblack@google.com  sc_assert(sc_delta_count() == 0);
33412855Sgabeblack@google.com  sc_assert(sc_is_running() == 0);
33512855Sgabeblack@google.com  sc_assert(sc_time_stamp() == sc_time(SC_ZERO_TIME));
33612855Sgabeblack@google.com  sc_assert(sc_report_handler::get_count(SC_INFO) == 0);
33712855Sgabeblack@google.com  sc_assert(sc_report_handler::get_count("foo") == 0);
33812855Sgabeblack@google.com
33912855Sgabeblack@google.com  sc_actions act1 = sc_report_handler::get_new_action_id();
34012855Sgabeblack@google.com  sc_actions act2 = sc_report_handler::get_new_action_id();
34112855Sgabeblack@google.com  while (act2 != SC_UNSPECIFIED)
34212855Sgabeblack@google.com  {
34312855Sgabeblack@google.com    sc_assert(act2 != act1);
34412855Sgabeblack@google.com    act2 = sc_report_handler::get_new_action_id();
34512855Sgabeblack@google.com  }
34612855Sgabeblack@google.com  sc_assert(sc_report_handler::get_log_file_name() == 0);
34712855Sgabeblack@google.com  sc_assert(sc_get_top_level_objects().size() == 0);
34812855Sgabeblack@google.com  sc_assert(sc_find_object("foo") == 0);
34912855Sgabeblack@google.com  sc_assert(!sc_get_current_process_handle().valid());
35012855Sgabeblack@google.com
35112855Sgabeblack@google.com  sc_copyright();
35212855Sgabeblack@google.com  sc_version();
35312855Sgabeblack@google.com  std::string release = sc_release();
35412855Sgabeblack@google.com  int n = release.find('.');
35512855Sgabeblack@google.com  std::string major = release.substr(0,n);
35612855Sgabeblack@google.com  release = release.substr(n+1,release.size()-1);
35712855Sgabeblack@google.com  n = release.find('.');
35812855Sgabeblack@google.com  std::string minor = release.substr(0,n);
35912855Sgabeblack@google.com  release = release.substr(n+1,release.size()-1);
36012855Sgabeblack@google.com  n = release.find('-');
36112855Sgabeblack@google.com  std::string patch = release.substr(0,n);
36212855Sgabeblack@google.com  std::string originator = release.substr(n+1,release.size());
36312855Sgabeblack@google.com
36412855Sgabeblack@google.com  std::string charset =
36512855Sgabeblack@google.com  "abcdefghijklmnopqrstuvwxyzABSCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
36612855Sgabeblack@google.com
36712855Sgabeblack@google.com  for (unsigned int i = 0; i < major.size(); i++)
36812855Sgabeblack@google.com    sc_assert(charset.find(major[i]) < charset.size());
36912855Sgabeblack@google.com  for (unsigned int i = 0; i < minor.size(); i++)
37012855Sgabeblack@google.com    sc_assert(charset.find(minor[i]) < charset.size());
37112855Sgabeblack@google.com  for (unsigned int i = 0; i < patch.size(); i++)
37212855Sgabeblack@google.com    sc_assert(charset.find(patch[i]) < charset.size());
37312855Sgabeblack@google.com  for (unsigned int i = 0; i < originator.size(); i++)
37412855Sgabeblack@google.com    sc_assert(charset.find(originator[i]) < charset.size());
37512855Sgabeblack@google.com
37612855Sgabeblack@google.com  Top top("top");
37712855Sgabeblack@google.com  sc_start();
37812855Sgabeblack@google.com
37912855Sgabeblack@google.com  sc_stop();
38012855Sgabeblack@google.com  sc_assert(sc_end_of_simulation_invoked() == true);
38112855Sgabeblack@google.com
38212855Sgabeblack@google.com  cout << endl << "Success" << endl;
38312855Sgabeblack@google.com  return 0;
38412855Sgabeblack@google.com}
385