| /***************************************************************************** |
| |
| 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. |
| |
| *****************************************************************************/ |
| |
| /***************************************************************************** |
| |
| register_phase_callbacks.cpp -- Test for (un)registering dynamic callbacks |
| |
| Note: requires simulation phase callback support enabled in the kernel |
| SC_ENABLE_SIMULATION_PHASE_CALLBACKS / --enable-phase-callbacks |
| |
| Original Author: Philipp A. Hartmann, OFFIS, 2013-05-17 |
| |
| *****************************************************************************/ |
| |
| /***************************************************************************** |
| |
| MODIFICATION LOG - modifiers, enter your name, affiliation, date and |
| changes you are making here. |
| |
| Name, Affiliation, Date: |
| Description of Modification: |
| |
| *****************************************************************************/ |
| |
| #include <systemc.h> |
| |
| #define VERBOSE 1 |
| |
| SC_MODULE(phase_tracer) |
| { |
| SC_HAS_PROCESS(phase_tracer); |
| phase_tracer( sc_module_name nm |
| = sc_core::sc_gen_unique_name("phase_tracer") ) |
| : cb_count(0), timed_count(), delta_count() |
| { |
| SC_METHOD(timed); |
| SC_METHOD(delta); |
| sensitive << ev; |
| |
| old_mask = SC_STATUS_ANY; |
| cb_mask = register_simulation_phase_callback( SC_STATUS_ANY ); |
| sc_assert( cb_mask == (old_mask & ~SC_ELABORATION & ~SC_RUNNING) ); |
| old_mask = cb_mask; |
| |
| cb_mask = unregister_simulation_phase_callback(SC_STOPPED); |
| sc_assert( cb_mask == (old_mask & ~SC_STOPPED) ); |
| old_mask = cb_mask; |
| |
| cb_mask = register_simulation_phase_callback( SC_UNITIALIZED ); |
| sc_assert( cb_mask == old_mask ); |
| |
| cb_mask = unregister_simulation_phase_callback(SC_UNITIALIZED); |
| sc_assert( cb_mask == old_mask ); |
| |
| cb_mask = unregister_simulation_phase_callback(SC_RUNNING); |
| sc_assert( cb_mask == (old_mask & ~SC_END_OF_INITIALIZATION |
| // & ~SC_END_OF_EVALUATION |
| & ~SC_END_OF_UPDATE |
| & ~SC_BEFORE_TIMESTEP) ); |
| old_mask = cb_mask; |
| |
| cb_mask = unregister_simulation_phase_callback(SC_ELABORATION); |
| sc_assert( cb_mask == (old_mask & ~SC_BEFORE_END_OF_ELABORATION |
| & ~SC_END_OF_ELABORATION ) ); |
| old_mask = cb_mask; |
| |
| cb_mask = unregister_simulation_phase_callback( SC_STATUS_ANY ); |
| sc_assert( cb_mask == SC_UNITIALIZED ); |
| old_mask = cb_mask; |
| |
| cb_mask = register_simulation_phase_callback( SC_RUNNING ); |
| sc_assert( cb_mask == ( SC_END_OF_INITIALIZATION |
| // | SC_END_OF_EVALUATION |
| | SC_END_OF_UPDATE | SC_BEFORE_TIMESTEP ) ); |
| |
| cb_mask = register_simulation_phase_callback( SC_STATUS_ANY ); |
| sc_assert( cb_mask == (SC_STATUS_ANY & ~SC_ELABORATION & ~SC_RUNNING) ); |
| } |
| |
| void timed() |
| { |
| std::cout |
| << sc_get_current_process_handle().name() |
| << ": " << sc_time_stamp() |
| << ": " << timed_count |
| << std::endl; |
| if( timed_count++ < 5 ) { |
| next_trigger( 100, SC_NS ); |
| } |
| if( delta_count < 5 ) |
| ev.notify( SC_ZERO_TIME ); |
| |
| if( timed_count>=6 ) |
| sc_stop(); |
| } |
| void delta() |
| { |
| std::cout |
| << sc_get_current_process_handle().name() |
| << ": " << sc_time_stamp() |
| << ": " << delta_count |
| << std::endl; |
| delta_count++; |
| } |
| |
| virtual void simulation_phase_callback() |
| { |
| cb_count++; |
| |
| # if VERBOSE |
| { |
| std::string ttp; |
| if( !sc_pending_activity() ) { |
| ttp = "MAX"; |
| } else { |
| ttp = sc_time_to_pending_activity().to_string(); |
| } |
| std::cout << name() |
| << ": phase callback " |
| << sc_get_status() |
| << ": " << sc_time_stamp() |
| << " -> pending activity: " << ttp |
| << std::endl; |
| } |
| # endif |
| sc_assert( cb_mask & sc_get_status() ); |
| |
| switch( sc_get_status() ) |
| { |
| case SC_END_OF_UPDATE: |
| case SC_BEFORE_TIMESTEP: |
| if( timed_count == 3 ) |
| ev.cancel(); |
| if( delta_count == 2 ) |
| ev.notify(SC_ZERO_TIME); |
| if( timed_count == 2 ) |
| ev.notify( 1, SC_NS ); |
| break; |
| default: |
| // do nothing |
| break; |
| } |
| } |
| |
| ~phase_tracer() |
| { print_static_phase_stats( "[destructor]" ); } |
| |
| void print_static_phase_stats( const char* phase ) |
| { |
| #if VERBOSE |
| std::cout << name() |
| << ": " << phase << ": " |
| << cb_count << " callbacks called." |
| << std::endl; |
| #endif |
| } |
| |
| private: |
| |
| virtual void before_end_of_elaboration() |
| { |
| sc_assert( sc_get_status() == SC_BEFORE_END_OF_ELABORATION ); |
| print_static_phase_stats( "before_end_of_elaboration" ); |
| } |
| |
| virtual void end_of_elaboration() |
| { |
| sc_assert( sc_get_status() == SC_END_OF_ELABORATION ); |
| print_static_phase_stats( "end_of_elaboration" ); |
| } |
| |
| virtual void start_of_simulation() |
| { |
| sc_assert( sc_get_status() == SC_START_OF_SIMULATION ); |
| print_static_phase_stats( "start_of_simulation" ); |
| |
| // ignored - issues warning |
| register_simulation_phase_callback( SC_ELABORATION ); |
| } |
| |
| virtual void end_of_simulation() |
| { |
| sc_assert( sc_get_status() == SC_END_OF_SIMULATION ); |
| print_static_phase_stats( "end_of_simulation" ); |
| } |
| |
| |
| |
| private: |
| phase_cb_mask cb_mask, old_mask; |
| sc_dt::uint64 cb_count, timed_count, delta_count; |
| sc_event ev; |
| }; |
| |
| |
| int sc_main(int, char*[]) |
| { |
| // don't run without callbacks enabled |
| sc_report_handler::set_actions( SC_ID_PHASE_CALLBACKS_UNSUPPORTED_ |
| , SC_DEFAULT_ERROR_ACTIONS ); |
| |
| phase_tracer pt; |
| sc_start(); |
| return 0; |
| } |