// General tests combining features of SystemC 2.1 and 1666 #define SC_INCLUDE_DYNAMIC_PROCESSES #include using sc_core::sc_interface; using sc_core::sc_object; using sc_core::sc_port; using sc_core::sc_export; using sc_core::sc_module; using sc_core::sc_module_name; using sc_core::sc_in; using sc_core::sc_in_clk; using sc_core::sc_signal; using sc_core::sc_prim_channel; using sc_core::sc_event; using sc_core::sc_delta_count; using sc_core::sc_is_running; using sc_core::sc_get_top_level_objects; using sc_core::sc_find_object; using sc_core::sc_report; using sc_core::sc_report_handler; using sc_core::sc_actions; using sc_core::SC_INFO; using sc_core::SC_UNSPECIFIED; using sc_core::SC_THROW; using sc_core::sc_spawn; using sc_core::sc_process_handle; using sc_core::sc_get_current_process_handle; using sc_core::sc_time; using sc_core::sc_time_stamp; using sc_core::SC_ZERO_TIME; using sc_core::SC_PS; using sc_core::SC_NS; using sc_core::SC_US; using sc_core::sc_start_of_simulation_invoked; using sc_core::sc_end_of_simulation_invoked; using sc_core::sc_start; using sc_core::sc_stop; using sc_core::sc_copyright; using sc_core::sc_version; using sc_core::sc_release; using sc_dt::sc_abs; using sc_dt::sc_max; using sc_dt::sc_min; using sc_dt::sc_int; using sc_dt::sc_bigint; using std::cout; using std::endl; #if defined(IEEE_1666_CPLUSPLUS) && IEEE_1666_CPLUSPLUS >= 201103L // dynamic process macros have been moved to functions on C++11 using sc_core::sc_bind; using sc_core::sc_ref; using sc_core::sc_cref; #endif // IEEE_1666_CPLUSPLUS struct i_f: virtual sc_interface { virtual void write() = 0; }; void check_form_of_suffix(std::string s) { std::string charset = "0123456789"; while (!s.empty()) { sc_assert(s[0] == '_'); s = s.substr(1); sc_assert(!s.empty()); do { sc_assert(charset.find(s[0]) < charset.size()); s = s.substr(1); } while (!s.empty() && (s[0] != '_')); } } struct Chan: i_f, sc_object { virtual void write() { sc_assert(std::string(name()).substr(0,17) == "top.m_dest.object"); check_form_of_suffix(std::string(name()).substr(17)); } }; struct M_src: sc_core::sc_behavior { sc_port* p; SC_HAS_PROCESS(M_src); M_src(sc_module_name _name) { p = new sc_port; SC_THREAD(T); } void T() { (*p)->write(); } }; struct M_dest: sc_core::sc_channel { sc_export* xp; SC_HAS_PROCESS(M_dest); M_dest(sc_module_name _name) { xp = new sc_export; Chan* ch = new Chan; xp->bind(*ch); } }; void f() { ::sc_core::wait(33, SC_PS); } struct Prim: sc_prim_channel { Prim() : cref_arg(1) {} void write() { request_update(); } void update() { sc_spawn(sc_bind(&Prim::proc, this)); } void proc() { ev.notify(SC_ZERO_TIME); wait(ev); cout << "Prim::Proc spawned and resumed" << endl; SC_FORK sc_spawn(sc_bind(&Prim::Th, this, 1)), sc_spawn(sc_bind(&Prim::Th, this, 2)) SC_JOIN sc_spawn(sc_bind(&Prim::Th_ref, this, sc_ref(ref_arg))); sc_spawn(sc_bind(&Prim::Th_cref, this, sc_cref(cref_arg))); wait(1, SC_NS); sc_assert(ref_arg == 99); } sc_event ev; void Th(int i) { cout << "Th::i=" << i << endl; } void Th_ref(int& arg) { arg = 99; sc_time t(sc_time_stamp()); sc_process_handle h = sc_spawn(&f); wait(h.terminated_event()); sc_assert(sc_time_stamp() == t + sc_time(33, SC_PS)); } void Th_cref(const int& arg) { } int ref_arg; const int cref_arg; }; SC_MODULE(M) { Prim prim; SC_CTOR(M) { SC_THREAD(T); } void T() { wait(10, SC_NS); try { sc_report_handler::set_actions("msg_type", SC_INFO, SC_THROW); SC_REPORT_INFO("msg_type", "msg"); } catch (sc_report& rpt) { cout << "Caught rpt " << rpt.what() << endl; sc_assert(rpt.get_severity() == SC_INFO); sc_assert(std::string(rpt.get_msg_type()) == "msg_type"); sc_assert(std::string(rpt.get_msg()) == "msg"); sc_assert(rpt.get_time() == sc_time(10, SC_NS)); sc_assert(std::string(rpt.get_process_name()) == "top.m.T"); sc_assert(sc_report_handler::get_count(SC_INFO) == 1); sc_report rpt2 = rpt; // Copy constructor prim.write(); sc_spawn(sc_bind(&M::proc, this, &rpt2)); wait(100, SC_NS); } } void proc(sc_report* rpt) { sc_assert(rpt->get_severity() == SC_INFO); sc_assert(std::string(rpt->get_msg_type()) == "msg_type"); sc_assert(std::string(rpt->get_msg()) == "msg"); sc_assert(rpt->get_time() == sc_time(10, SC_NS)); sc_assert(std::string(rpt->get_process_name()) == "top.m.T"); rpt->get_file_name(); rpt->get_line_number(); } }; struct CM: sc_module { sc_in_clk clk; sc_in reset; SC_HAS_PROCESS(CM); CM(sc_module_name _name) : first(true) { SC_CTHREAD(CT, clk.pos()); reset_signal_is(reset, true); sc_assert(sc_start_of_simulation_invoked() == false); sc_assert(sc_end_of_simulation_invoked() == false); sc_assert(sc_is_running() == false); } bool first; void CT() { if (first) sc_assert(sc_time_stamp() == sc_time(5, SC_US)); else sc_assert(sc_time_stamp() == sc_time(30, SC_US)); first = false; sc_assert(sc_start_of_simulation_invoked() == true); sc_assert(sc_end_of_simulation_invoked() == false); sc_assert(sc_is_running() == true); while(1) { wait(); sc_assert(sc_time_stamp() == sc_time(15, SC_US)); wait(); sc_assert(sc_time_stamp() == sc_time(25, SC_US)); wait(); sc_assert(false); } } void start_of_simulation() { sc_assert(sc_start_of_simulation_invoked() == false); sc_assert(sc_end_of_simulation_invoked() == false); sc_assert(sc_is_running() == false); } void end_of_simulation() { sc_assert(sc_start_of_simulation_invoked() == true); sc_assert(sc_end_of_simulation_invoked() == false); sc_assert(sc_is_running() == false); } }; SC_MODULE(Top) { M *m; CM *cm; M_src m_src; M_dest m_dest; sc_signal clk, reset; SC_CTOR(Top) : m_src("m_src"), m_dest("m_dest") { m = new M("m"); cm = new CM("cm"); cm->clk(clk); cm->reset(reset); m_src.p->bind( *(m_dest.xp) ); // Port-export binding SC_THREAD(T); SC_THREAD(T2); } void T() { clk = false; reset = true; wait(5, SC_US); clk = true; wait(5, SC_US); clk = false; reset = false; wait(5, SC_US); clk = true; wait(5, SC_US); clk = false; wait(5, SC_US); clk = true; wait(5, SC_US); clk = false; reset = true; wait(10, SC_US); } void T2() { sc_assert(sc_min(-1,1) == -1); sc_assert(sc_max(-1,1) == 1); sc_assert(sc_abs(-1) == 1); sc_assert(sc_min(sc_int<8>(-1),sc_int<8>(1)) == sc_int<8>(-1)); sc_assert(sc_max(sc_int<8>(-1),sc_int<8>(1)) == sc_int<8>(1)); sc_assert(sc_abs(sc_int<8>(-1)) == sc_int<8>(1)); sc_assert(sc_min(sc_bigint<256>(-1),sc_bigint<256>(1)) == sc_bigint<256>(-1)); sc_assert(sc_max(sc_bigint<256>(-1),sc_bigint<256>(1)) == sc_bigint<256>(1)); sc_assert(sc_abs(sc_bigint<256>(-1)) == sc_bigint<256>(1)); } }; int sc_main(int argc, char* argv[]) { sc_assert(sc_delta_count() == 0); sc_assert(sc_is_running() == 0); sc_assert(sc_time_stamp() == sc_time(SC_ZERO_TIME)); sc_assert(sc_report_handler::get_count(SC_INFO) == 0); sc_assert(sc_report_handler::get_count("foo") == 0); sc_actions act1 = sc_report_handler::get_new_action_id(); sc_actions act2 = sc_report_handler::get_new_action_id(); while (act2 != SC_UNSPECIFIED) { sc_assert(act2 != act1); act2 = sc_report_handler::get_new_action_id(); } sc_assert(sc_report_handler::get_log_file_name() == 0); sc_assert(sc_get_top_level_objects().size() == 0); sc_assert(sc_find_object("foo") == 0); sc_assert(!sc_get_current_process_handle().valid()); sc_copyright(); sc_version(); std::string release = sc_release(); int n = release.find('.'); std::string major = release.substr(0,n); release = release.substr(n+1,release.size()-1); n = release.find('.'); std::string minor = release.substr(0,n); release = release.substr(n+1,release.size()-1); n = release.find('-'); std::string patch = release.substr(0,n); std::string originator = release.substr(n+1,release.size()); std::string charset = "abcdefghijklmnopqrstuvwxyzABSCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"; for (unsigned int i = 0; i < major.size(); i++) sc_assert(charset.find(major[i]) < charset.size()); for (unsigned int i = 0; i < minor.size(); i++) sc_assert(charset.find(minor[i]) < charset.size()); for (unsigned int i = 0; i < patch.size(); i++) sc_assert(charset.find(patch[i]) < charset.size()); for (unsigned int i = 0; i < originator.size(); i++) sc_assert(charset.find(originator[i]) < charset.size()); Top top("top"); sc_start(); sc_stop(); sc_assert(sc_end_of_simulation_invoked() == true); cout << endl << "Success" << endl; return 0; }