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