/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ // sc_pause.cpp -- test for // // Original Author: John Aynsley, Doulos, Inc. // // MODIFICATION LOG - modifiers, enter your name, affiliation, date and // // $Log: sc_pause.cpp,v $ // Revision 1.2 2011/05/08 19:18:46 acg // Andy Goodrich: remove extraneous + prefixes from git diff. // // sc_pause, sc_get_status, sc_is_running #define SC_INCLUDE_DYNAMIC_PROCESSES #include using namespace sc_core; using std::cout; using std::endl; using std::hex; struct my_interface: virtual sc_interface { virtual void schedule_events_while_paused() = 0; }; struct M: sc_module, private my_interface { sc_export xport; SC_CTOR(M) { cout << "sc_get_status() == " << hex << sc_get_status() << " CTOR in " << name() << endl; sc_assert( sc_get_status() == SC_BEFORE_END_OF_ELABORATION ); sc_assert( sc_is_running() == false ); xport.bind(*this); sc_spawn(sc_bind(&M::T, this)); SC_THREAD(on_immed_event); SC_THREAD(on_delta_event); SC_THREAD(on_timed_event); } sc_signal sig1, sig2, sig3, sig4; sc_event immed_event; sc_event delta_event; sc_event timed_event; void before_end_of_elaboration() { cout << "sc_get_status() == " << hex << sc_get_status() << " before_end_of_elaboration in " << name() << endl; sc_assert( sc_get_status() == SC_BEFORE_END_OF_ELABORATION ); sc_assert( sc_is_running() == false ); sig1.write(1); timed_event.notify(1234, SC_NS); sc_pause(); // Should be ignored } void end_of_elaboration() { cout << "sc_get_status() == " << hex << sc_get_status() << " end_of_elaboration in " << name() << endl; sc_assert( sc_get_status() == SC_END_OF_ELABORATION ); sc_assert( sc_is_running() == false ); sig2.write(2); sc_pause(); // Should be ignored } void start_of_simulation() { cout << "sc_get_status() == " << hex << sc_get_status() << " start_of_simulation in " << name() << endl; sc_assert( sc_get_status() == SC_START_OF_SIMULATION ); sc_assert( sc_is_running() == false ); sig3.write(3); sig4.write(0); sc_pause(); // Should be ignored } void end_of_simulation() { cout << "sc_get_status() == " << hex << sc_get_status() << " end_of_simulation in " << name() << endl;; sc_assert( sc_get_status() == SC_END_OF_SIMULATION ); sc_assert( sc_is_running() == false ); } void T() { sc_assert( sig1.read() == 1 ); sc_assert( sig2.read() == 2 ); sc_assert( sig3.read() == 3 ); } void on_immed_event() { wait(immed_event); cout << "on_immed_event() awoke\n"; // Should run in 1st eval phase after pause sc_assert( sig4.read() == 0 ); } void on_delta_event() { wait(delta_event); cout << "on_delta_event() awoke\n"; // Should run in 2nd eval phase after pause sc_assert( sig4.read() == 4 ); } void on_timed_event() { wait(timed_event); cout << "on_timed_event() awoke\n"; sc_assert( sig1.read() == 1 ); sc_assert( sig2.read() == 2 ); sc_assert( sig3.read() == 3 ); sc_assert( sig4.read() == 0 ); sc_assert( sc_time_stamp() == sc_time(1234, SC_NS) ); } private: void schedule_events_while_paused() { sig4.write(4); immed_event.notify(); delta_event.notify(SC_ZERO_TIME); // Should be able to instantiate an sc_object while paused mut = new sc_mutex("mut"); sem = new sc_semaphore("sem", 1); } sc_mutex* mut; sc_semaphore* sem; }; SC_MODULE(Top) { SC_CTOR(Top) { cout << "sc_get_status() == " << hex << sc_get_status() << " CTOR in " << name() << endl; sc_assert( sc_get_status() == SC_ELABORATION ); sc_assert( sc_is_running() == false ); SC_THREAD(T); sc_spawn_options opt; opt.spawn_method(); opt.set_sensitivity( &timed_ev ); opt.set_sensitivity( &delta_ev ); opt.dont_initialize(); sc_spawn(sc_bind(&Top::ev_handler, this), "ev_handler", &opt); SC_METHOD(immed_ev_handler); sensitive << immed_ev; dont_initialize(); immed_ev_delta = 0; sc_assert( sc_delta_count() == 0 ); } ~Top() { sc_assert( sc_get_status() == SC_STOPPED ); sc_assert( sc_is_running() == false ); } M* m; sc_event timed_ev; sc_event delta_ev; sc_event immed_ev; unsigned immed_ev_delta; sc_signal sig; void before_end_of_elaboration() { cout << "sc_get_status() == " << hex << sc_get_status() << " before_end_of_elaboration in " << name() << endl; sc_assert( sc_get_status() == SC_BEFORE_END_OF_ELABORATION ); sc_assert( sc_is_running() == false ); m = new M("m"); } void end_of_elaboration() { cout << "sc_get_status() == " << hex << sc_get_status() << " end_of_elaboration in " << name() << endl; sc_assert( sc_get_status() == SC_END_OF_ELABORATION ); sc_assert( sc_is_running() == false ); } void start_of_simulation() { cout << "sc_get_status() == " << hex << sc_get_status() << " start_of_simulation in " << name() << endl; sc_assert( sc_get_status() == SC_START_OF_SIMULATION ); sc_assert( sc_is_running() == false ); } void end_of_simulation() { cout << "sc_get_status() == " << hex << sc_get_status() << " end_of_simulation in " << name() << endl; sc_assert( sc_get_status() == SC_END_OF_SIMULATION ); sc_assert( sc_is_running() == false ); sc_assert( immed_ev_delta == 999 ); } void T() { cout << "sc_get_status() == " << hex << sc_get_status() << " PROCESS in " << name() << endl; sc_assert( sc_delta_count() == 0 ); sc_assert( sig.read() == 42 ); sc_assert( sc_get_status() == SC_RUNNING ); sc_assert( sc_is_running() == true ); wait(timed_ev); sc_assert( sc_time_stamp() == sc_time(42, SC_US) ); sc_assert( sc_get_status() == SC_RUNNING ); sc_assert( sc_is_running() == true ); sc_pause(); cout << "sc_get_status() == " << hex << sc_get_status() << " PROCESS after sc_pause in " << name() << endl; sc_assert( sc_time_stamp() == sc_time(42, SC_US) ); sc_assert( sc_get_status() == SC_RUNNING ); sc_assert( sc_is_running() == true ); wait(SC_ZERO_TIME); sc_assert( sc_get_status() == SC_RUNNING ); sc_assert( sc_is_running() == true ); sc_pause(); cout << "sc_get_status() == " << hex << sc_get_status() << " PROCESS after sc_pause in " << name() << endl; sc_assert( sc_time_stamp() == sc_time(42, SC_US) ); sc_assert( sc_get_status() == SC_RUNNING ); sc_assert( sc_is_running() == true ); wait(2, SC_US); sc_assert( sc_time_stamp() == sc_time(44, SC_US) ); sc_assert( sc_get_status() == SC_RUNNING ); sc_assert( sc_is_running() == true ); sc_stop(); cout << "sc_get_status() == " << hex << sc_get_status() << " PROCESS after sc_stop() in " << name() << endl;; sc_assert( sc_time_stamp() == sc_time(44, SC_US) ); sc_assert( sc_get_status() == SC_RUNNING ); sc_assert( sc_is_running() == true ); sc_pause(); sc_assert( sc_get_status() == SC_RUNNING ); } void ev_handler() { cout << "sc_get_status() == " << hex << sc_get_status() << " METHOD in " << name() << endl; sc_assert( sc_get_status() == SC_RUNNING ); sc_assert( sig.read() == 42 ); static bool first = true; if (first) { sc_assert( sc_time_stamp() == SC_ZERO_TIME ); first = false; } else sc_assert( sc_time_stamp() == sc_time(42, SC_US) ); } void immed_ev_handler() { sc_assert( sc_time_stamp() == sc_time(42, SC_US) ); sc_assert( sc_delta_count() == immed_ev_delta ); immed_ev_delta = 999; } }; void spawned_while_paused() { cout << "spawned_while_paused() awoke" << endl; sc_assert( sc_time_stamp() == sc_time(42, SC_US) ); sc_assert( sc_get_status() == SC_RUNNING ); sc_assert( sc_pending_activity() == true ); } int sc_main(int argc, char* argv[]) { sc_assert( sc_delta_count() == 0 ); cout << "sc_get_status() == " << hex << sc_get_status() << " ELAB" << endl; sc_assert( sc_get_status() == SC_ELABORATION ); sc_assert( sc_is_running() == false ); Top top("top"); sc_pause(); // Should be ignored // Schedule some update requests and events top.sig.write(42); top.timed_ev.notify(42, SC_US); top.delta_ev.notify(SC_ZERO_TIME); sc_assert( sc_get_status() == SC_ELABORATION ); sc_assert( sc_delta_count() == 0 ); sc_start(); cout << "sc_get_status() == " << hex << sc_get_status() << " PAUSED" << endl; sc_assert( sc_get_status() == SC_PAUSED ); sc_assert( sc_is_running() == true ); sc_assert( sc_time_stamp() == sc_time(42, SC_US) ); sc_start(1, SC_US); cout << "sc_get_status() == " << hex << sc_get_status() << " PAUSED" << endl; sc_assert( sc_get_status() == SC_PAUSED ); sc_assert( sc_is_running() == true ); sc_assert( sc_time_stamp() == sc_time(42, SC_US) ); // Schedule an immediate notification top.immed_ev.notify(); top.immed_ev_delta = sc_delta_count(); // IMC while paused top.m->xport->schedule_events_while_paused(); sc_process_handle h = sc_spawn(&spawned_while_paused); sc_assert( h.valid() ); sc_start(); cout << "sc_get_status() == " << hex << sc_get_status() << " STOPPED" << endl; sc_assert( sc_get_status() == SC_STOPPED ); sc_assert( sc_is_running() == false ); sc_assert( sc_time_stamp() == sc_time(44, SC_US) ); cout << endl << "Success" << endl; return 0; }