simulation_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  simulation_callbacks.cpp -- Test of simulation phase 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#ifdef BENCHMARK
44#  include "rusage_timer.h"
45#  define  ROUNDS 20
46#  define  NUM_TIMED_TRIGGERS 2000000
47#  define  NUM_DELTA_TRIGGERS 50
48#  define  VERBOSE 0
49#else
50#  define  ROUNDS 2
51#  define  NUM_TIMED_TRIGGERS 10
52#  define  NUM_DELTA_TRIGGERS 1
53#  define  VERBOSE 1
54#endif
55
56#ifndef REGISTER_CALLBACKS
57#  define REGISTER_CALLBACKS 1
58#endif
59#ifndef EXTRA_METHOD
60#  define EXTRA_METHOD 0
61#endif
62
63#define TIMED_THREAD 1
64
65#if TIMED_THREAD
66#  define TIMED_WAIT    wait
67#  define TIMED_PROCESS SC_THREAD
68#else
69#  define TIMED_WAIT    next_trigger
70#  define TIMED_PROCESS SC_METHOD
71#endif
72
73#if REGISTER_CALLBACKS
74//#  define CALLBACK_MASK ( SC_END_OF_EVALUATION )
75//#  define CALLBACK_MASK ( SC_END_OF_UPDATE )
76//#  define CALLBACK_MASK ( SC_BEFORE_TIMESTEP )
77#  define CALLBACK_MASK ( SC_END_OF_UPDATE | SC_BEFORE_TIMESTEP )
78#else
79// SC_RUNNING (for EXTRA_METHOD)
80#  define CALLBACK_MASK ( SC_RUNNING )
81#endif
82
83static const sc_dt::uint64 max_rounds         = ROUNDS;
84static const sc_dt::uint64 max_timed_triggers = NUM_TIMED_TRIGGERS;
85static const sc_dt::uint64 max_delta_triggers = NUM_DELTA_TRIGGERS;
86static const sc_time  delay(1, SC_NS);
87
88SC_MODULE(phase_tracer)
89{
90  SC_HAS_PROCESS(phase_tracer);
91  phase_tracer( sc_module_name = sc_core::sc_gen_unique_name("phase_tracer") )
92    : cb_mask(CALLBACK_MASK), cb_count(0)
93  {
94#if REGISTER_CALLBACKS
95    cb_mask = register_simulation_phase_callback( CALLBACK_MASK );
96#endif
97  }
98
99  virtual void simulation_phase_callback()
100  {
101    cb_count++;
102
103#   if VERBOSE
104    {
105      std::string ttp;
106      if( !sc_pending_activity() ) {
107        ttp = "MAX";
108      } else {
109        ttp = sc_time_to_pending_activity().to_string();
110      }
111      std::cout << name()
112                << ": phase callback "
113                << sc_get_status()
114                << ": " << sc_time_stamp()
115                << " -> pending activity: " << ttp
116                << std::endl;
117    }
118#   endif
119    sc_assert( cb_mask & sc_get_status() );
120  }
121
122  ~phase_tracer()
123      { print_static_phase_stats( "[destructor]" ); }
124
125  void print_static_phase_stats( const char* phase )
126  {
127#if VERBOSE
128      std::cout << name()
129                << ": " << phase << ": "
130                << cb_count << " callbacks called."
131                << std::endl;
132#endif
133  }
134
135private:
136  unsigned      cb_mask;
137  sc_dt::uint64 cb_count;
138};
139
140SC_MODULE(activities)
141{
142  SC_CTOR(activities)
143    : timed_count(), delta_count()
144  {
145    TIMED_PROCESS(timed);
146      sensitive << timed_ev;
147      dont_initialize();
148    SC_METHOD(delta);
149      sensitive << delta_ev;
150      dont_initialize();
151#if EXTRA_METHOD
152    SC_METHOD(extra);
153      sensitive << timed_ev;
154      dont_initialize();
155#endif
156  }
157
158  void notify_round()
159    { timed_ev.notify(SC_ZERO_TIME); }
160
161private:
162  void timed()
163  {
164#   if TIMED_THREAD
165    while(1)
166#   endif
167    {
168      if( timed_count >= max_timed_triggers ) {
169        timed_count = 0;
170        TIMED_WAIT();
171      } else {
172        verbose();
173        ++timed_count;
174        if( max_delta_triggers )
175          delta_ev.notify(SC_ZERO_TIME);
176        timed_ev.notify(delay);
177        TIMED_WAIT();
178      }
179    }
180  }
181
182  void delta()
183  {
184    ++delta_count;
185    verbose();
186    if( delta_count >= max_delta_triggers ) {
187      delta_count = 0;
188    } else {
189      delta_ev.notify(SC_ZERO_TIME);
190    }
191  }
192
193  void extra()
194  {
195    if( sc_pending_activity_at_current_time() ) {
196      pt.simulation_phase_callback();
197      next_trigger(SC_ZERO_TIME);
198    } else if (sc_time_to_pending_activity()== sc_max_time()-sc_time_stamp() ) {
199      next_trigger();
200    } else {
201      pt.simulation_phase_callback();
202      next_trigger(sc_time_to_pending_activity());
203    }
204  }
205
206  void verbose()
207  {
208#if VERBOSE
209    std::cout
210      << sc_get_current_process_handle().name()
211      << ": " << sc_time_stamp()
212      << ": " << timed_count << "/" << delta_count
213      << std::endl;
214#endif
215  }
216
217private:
218  phase_tracer pt;
219  sc_dt::uint64 timed_count, delta_count;
220  sc_event timed_ev, delta_ev;
221};
222
223
224int sc_main(int, char*[])
225{
226  activities   top("top");
227
228  sc_start(SC_ZERO_TIME);
229  for(unsigned i=0; i<max_rounds; ++i)
230  {
231#ifdef BENCHMARK
232    rusage_timer timer;
233#endif
234    top.notify_round();
235    sc_start();
236#ifdef BENCHMARK
237    std::cout << timer.to_seconds() << std::endl;
238#endif
239  }
240  sc_stop();
241  return 0;
242}
243