register_phase_callbacks.cpp revision 12855:588919e0e4aa
1/*****************************************************************************
2
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements.  See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License.  You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied.  See the License for the specific language governing
16  permissions and limitations under the License.
17
18 *****************************************************************************/
19
20/*****************************************************************************
21
22  register_phase_callbacks.cpp -- Test for (un)registering dynamic callbacks
23
24  Note: requires simulation phase callback support enabled in the kernel
25        SC_ENABLE_SIMULATION_PHASE_CALLBACKS / --enable-phase-callbacks
26
27  Original Author: Philipp A. Hartmann, OFFIS, 2013-05-17
28
29 *****************************************************************************/
30
31/*****************************************************************************
32
33  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
34  changes you are making here.
35
36      Name, Affiliation, Date:
37  Description of Modification:
38
39 *****************************************************************************/
40
41#include <systemc.h>
42
43#define VERBOSE 1
44
45SC_MODULE(phase_tracer)
46{
47  SC_HAS_PROCESS(phase_tracer);
48  phase_tracer( sc_module_name nm
49                  = sc_core::sc_gen_unique_name("phase_tracer") )
50    : cb_count(0), timed_count(), delta_count()
51  {
52    SC_METHOD(timed);
53    SC_METHOD(delta);
54      sensitive << ev;
55
56    old_mask = SC_STATUS_ANY;
57    cb_mask = register_simulation_phase_callback( SC_STATUS_ANY );
58    sc_assert( cb_mask == (old_mask & ~SC_ELABORATION & ~SC_RUNNING) );
59    old_mask = cb_mask;
60
61    cb_mask = unregister_simulation_phase_callback(SC_STOPPED);
62    sc_assert( cb_mask == (old_mask & ~SC_STOPPED) );
63    old_mask = cb_mask;
64
65    cb_mask = register_simulation_phase_callback( SC_UNITIALIZED );
66    sc_assert( cb_mask == old_mask );
67
68    cb_mask = unregister_simulation_phase_callback(SC_UNITIALIZED);
69    sc_assert( cb_mask == old_mask );
70
71    cb_mask = unregister_simulation_phase_callback(SC_RUNNING);
72    sc_assert( cb_mask == (old_mask & ~SC_END_OF_INITIALIZATION
73//                                  & ~SC_END_OF_EVALUATION
74                                    & ~SC_END_OF_UPDATE
75                                    & ~SC_BEFORE_TIMESTEP) );
76    old_mask = cb_mask;
77
78    cb_mask = unregister_simulation_phase_callback(SC_ELABORATION);
79    sc_assert( cb_mask == (old_mask & ~SC_BEFORE_END_OF_ELABORATION
80                                    & ~SC_END_OF_ELABORATION ) );
81    old_mask = cb_mask;
82
83    cb_mask = unregister_simulation_phase_callback( SC_STATUS_ANY );
84    sc_assert( cb_mask == SC_UNITIALIZED );
85    old_mask = cb_mask;
86
87    cb_mask = register_simulation_phase_callback( SC_RUNNING );
88    sc_assert( cb_mask == ( SC_END_OF_INITIALIZATION
89//                            | SC_END_OF_EVALUATION
90                            | SC_END_OF_UPDATE | SC_BEFORE_TIMESTEP ) );
91
92    cb_mask = register_simulation_phase_callback( SC_STATUS_ANY );
93    sc_assert( cb_mask == (SC_STATUS_ANY & ~SC_ELABORATION & ~SC_RUNNING) );
94  }
95
96  void timed()
97  {
98    std::cout
99      << sc_get_current_process_handle().name()
100      << ": " << sc_time_stamp()
101      << ": " << timed_count
102      << std::endl;
103    if( timed_count++ < 5 ) {
104      next_trigger( 100, SC_NS );
105    }
106    if( delta_count < 5 )
107      ev.notify( SC_ZERO_TIME );
108
109    if( timed_count>=6 )
110      sc_stop();
111  }
112  void delta()
113  {
114    std::cout
115      << sc_get_current_process_handle().name()
116      << ": " << sc_time_stamp()
117      << ": " << delta_count
118      << std::endl;
119    delta_count++;
120  }
121
122  virtual void simulation_phase_callback()
123  {
124    cb_count++;
125
126#   if VERBOSE
127    {
128      std::string ttp;
129      if( !sc_pending_activity() ) {
130        ttp = "MAX";
131      } else {
132        ttp = sc_time_to_pending_activity().to_string();
133      }
134      std::cout << name()
135                << ": phase callback "
136                << sc_get_status()
137                << ": " << sc_time_stamp()
138                << " -> pending activity: " << ttp
139                << std::endl;
140    }
141#   endif
142    sc_assert( cb_mask & sc_get_status() );
143
144    switch( sc_get_status() )
145    {
146    case SC_END_OF_UPDATE:
147    case SC_BEFORE_TIMESTEP:
148      if( timed_count == 3 )
149        ev.cancel();
150      if( delta_count == 2 )
151        ev.notify(SC_ZERO_TIME);
152      if( timed_count == 2 )
153        ev.notify( 1, SC_NS );
154      break;
155    default:
156      // do nothing
157      break;
158    }
159  }
160
161  ~phase_tracer()
162      { print_static_phase_stats( "[destructor]" ); }
163
164  void print_static_phase_stats( const char* phase )
165  {
166#if VERBOSE
167      std::cout << name()
168                << ": " << phase << ": "
169                << cb_count << " callbacks called."
170                << std::endl;
171#endif
172  }
173
174private:
175
176  virtual void before_end_of_elaboration()
177  {
178    sc_assert( sc_get_status() == SC_BEFORE_END_OF_ELABORATION );
179    print_static_phase_stats( "before_end_of_elaboration" );
180  }
181
182  virtual void end_of_elaboration()
183  {
184    sc_assert( sc_get_status() == SC_END_OF_ELABORATION );
185    print_static_phase_stats( "end_of_elaboration" );
186  }
187
188  virtual void start_of_simulation()
189  {
190    sc_assert( sc_get_status() == SC_START_OF_SIMULATION );
191    print_static_phase_stats( "start_of_simulation" );
192
193    // ignored - issues warning
194    register_simulation_phase_callback( SC_ELABORATION );
195  }
196
197  virtual void end_of_simulation()
198  {
199    sc_assert( sc_get_status() == SC_END_OF_SIMULATION );
200    print_static_phase_stats( "end_of_simulation" );
201  }
202
203
204
205private:
206  phase_cb_mask cb_mask, old_mask;
207  sc_dt::uint64 cb_count, timed_count, delta_count;
208  sc_event ev;
209};
210
211
212int sc_main(int, char*[])
213{
214  // don't run without callbacks enabled
215  sc_report_handler::set_actions( SC_ID_PHASE_CALLBACKS_UNSUPPORTED_
216                                , SC_DEFAULT_ERROR_ACTIONS );
217
218  phase_tracer pt;
219  sc_start();
220  return 0;
221}
222