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 sc_trace_file_base.cpp - Shared internal tracing implementation 23 24 Original Author: Philipp A. Hartmann, OFFIS, 2013-11-15 25 26 CHANGE LOG AT END OF FILE 27 *****************************************************************************/ 28 29/***************************************************************************** 30 31 Acknowledgement: The tracing mechanism is based on the tracing 32 mechanism developed at Infineon (formerly Siemens HL). Though this 33 code is somewhat different, and significantly enhanced, the basics 34 are identical to what was originally contributed by Infineon. The 35 contribution of Infineon in the development of this tracing 36 technology is hereby acknowledged. 37 38 *****************************************************************************/ 39 40#include <ctime> 41 42#include "sysc/tracing/sc_trace_file_base.h" 43#include "sysc/kernel/sc_simcontext.h" 44#include "sysc/kernel/sc_simcontext_int.h" 45 46#if SC_TRACING_PHASE_CALLBACKS_ 47# include "sysc/kernel/sc_object_int.h" 48#endif 49 50namespace sc_core { 51 52bool sc_trace_file_base::tracing_initialized_ = false; 53 54 55sc_trace_file_base::sc_trace_file_base( const char* name, const char* extension ) 56 : sc_trace_file() 57#if SC_TRACING_PHASE_CALLBACKS_ 58 , sc_object( sc_gen_unique_name("$$$$kernel_tracefile$$$$") ) 59#endif 60 , fp(0) 61 , timescale_unit() 62 , timescale_set_by_user(false) 63 , filename_() 64 , initialized_(false) 65 , trace_delta_cycles_(false) 66{ 67 if( !name || !*name ) { 68 SC_REPORT_ERROR( SC_ID_TRACING_FOPEN_FAILED_, "no name given" ); 69 return; 70 } else { 71 std::stringstream ss; 72 ss << name << "." << extension; 73 ss.str().swap( filename_ ); 74 } 75 76#if SC_TRACING_PHASE_CALLBACKS_ == 1 77 // remove from hierarchy 78 sc_object::detach(); 79 // register regular (non-delta) callbacks 80 sc_object::register_simulation_phase_callback( 81 // Note: Usually, one would expect to dump the initial values 82 // of the traced variables at the end of the initialization 83 // phase. The "non-callback" implementation dumps those 84 // values only after the first delta cycle, though. 85 // SC_END_OF_INITIALIZATION | 86 SC_BEFORE_TIMESTEP | 87 SC_PAUSED | SC_STOPPED 88 ); 89#else // explicitly register with simcontext 90 sc_get_curr_simcontext()->add_trace_file( this ); 91#endif 92} 93 94sc_trace_file_base::~sc_trace_file_base() 95{ 96 if( fp ) 97 fclose(fp); 98 99#if SC_TRACING_PHASE_CALLBACKS_ == 0 100 // unregister from simcontext 101 sc_get_curr_simcontext()->remove_trace_file( this ); 102#endif 103} 104 105/*****************************************************************************/ 106// simulation phase callback based trigger 107// 108// The tracing updates are triggered 109// (- at the end of the initialization phase [disabled for now]) 110// - before an update of the simulation time 111// - before returning to sc_start (via sc_pause() or sc_stop()) 112// - after an update phase (if delta cycles need to be traced) 113// 114#if SC_TRACING_PHASE_CALLBACKS_ 115void 116sc_trace_file_base::simulation_phase_callback() 117{ 118 // delta cycle is traced at the end of an update phase 119 cycle( simcontext()->get_status() == SC_END_OF_UPDATE ); 120} 121#endif // SC_TRACING_PHASE_CALLBACKS_ 122 123/*****************************************************************************/ 124 125bool 126sc_trace_file_base::initialize() 127{ 128 if( initialized_ ) 129 return false; 130 131 initialized_ = true; 132 133 if( !tracing_initialized_ ) { 134 tracing_initialized_ = true; 135 bool running_regression = ( getenv( "SYSTEMC_REGRESSION" ) != NULL ); 136 137 // hide some messages during regression 138 if( running_regression ) { 139 sc_report_handler::set_actions( SC_ID_TRACING_TIMESCALE_DEFAULT_ 140 , SC_INFO, SC_DO_NOTHING ); 141 sc_report_handler::set_actions( SC_ID_TRACING_VCD_DUPLICATE_TIME_ 142 , SC_WARNING, SC_DO_NOTHING ); 143 } 144 } 145 146 // open trace file 147 if(!fp) open_fp(); 148 149 // setup timescale 150 if( !timescale_set_by_user ) 151 { 152 timescale_unit = sc_get_time_resolution().to_seconds(); 153 154 std::stringstream ss; 155 ss << sc_get_time_resolution() << " (" << filename_ << ")"; 156 SC_REPORT_INFO( SC_ID_TRACING_TIMESCALE_DEFAULT_ 157 , ss.str().c_str() ); 158 } 159 160 // initialize derived tracing implementation class (VCD/WIF) 161 do_initialize(); 162 163 return initialized_; 164} 165 166void 167sc_trace_file_base::open_fp() 168{ 169 sc_assert( !fp ); 170 fp = fopen( filename(), "w" ); 171 if( !fp ) { 172 SC_REPORT_ERROR( SC_ID_TRACING_FOPEN_FAILED_, filename() ); 173 std::terminate(); // can't recover from here 174 } 175} 176 177void 178sc_trace_file_base::delta_cycles( bool flag ) 179{ 180 trace_delta_cycles_ = flag; 181#if SC_TRACING_PHASE_CALLBACKS_ 182 if( trace_delta_cycles_ ) { 183 sc_object::register_simulation_phase_callback( SC_END_OF_UPDATE ); 184 } else { 185 sc_object::unregister_simulation_phase_callback( SC_END_OF_UPDATE ); 186 } 187#endif 188} 189 190void 191sc_trace_file_base::set_time_unit( double v, sc_time_unit tu ) 192{ 193 if( initialized_ ) 194 { 195 std::stringstream ss; 196 ss << filename_ << "\n" 197 "\tTimescale unit cannot be changed once tracing has begun.\n" 198 "\tTo change the scale, create a new trace file."; 199 SC_REPORT_ERROR( SC_ID_TRACING_ALREADY_INITIALIZED_ 200 , ss.str().c_str() ); 201 return; 202 } 203 204 switch ( tu ) 205 { 206 case SC_FS: v = v * 1e-15; break; 207 case SC_PS: v = v * 1e-12; break; 208 case SC_NS: v = v * 1e-9; break; 209 case SC_US: v = v * 1e-6; break; 210 case SC_MS: v = v * 1e-3; break; 211 case SC_SEC: break; 212 default: { 213 std::stringstream ss; 214 ss << "unknown time unit:" << tu 215 << " (" << filename_ << ")"; 216 SC_REPORT_WARNING( SC_ID_TRACING_TIMESCALE_UNIT_ 217 , ss.str().c_str() ); 218 } 219 } 220 221 timescale_set_by_user = true; 222 timescale_unit = v; 223 224 // EMIT ADVISORY MESSAGE ABOUT CHANGE IN TIME SCALE: 225 { 226 std::stringstream ss; 227 ss << sc_time( timescale_unit, SC_SEC ) 228 << " (" << filename_ << ")"; 229 SC_REPORT_INFO( SC_ID_TRACING_TIMESCALE_UNIT_, ss.str().c_str() ); 230 } 231} 232 233bool 234sc_trace_file_base::add_trace_check( const std::string & name ) const 235{ 236 if( !initialized_ ) return true; 237 238 std::stringstream ss; 239 ss << "sc_trace() failed:\n" 240 "\tNo traces can be added to " 241 "'" << filename_ << "'" 242 " once trace recording has started.\n" 243 "\tTo add tracing of '" << name << "', create a new trace file."; 244 245 SC_REPORT_ERROR( SC_ID_TRACING_ALREADY_INITIALIZED_ 246 , ss.str().c_str() ); 247 return false; 248} 249 250// obtain formatted time string 251std::string localtime_string() 252{ 253 char buf[200]; 254 time_t long_time; 255 time(&long_time); 256 struct tm* p_tm = localtime(&long_time); 257 strftime(buf, 199, "%b %d, %Y %H:%M:%S", p_tm); 258 return buf; 259} 260 261 262} // namespace sc_core 263 264/***************************************************************************** 265 266 MODIFICATION LOG - modifiers, enter your name, affiliation, date and 267 changes you are making here. 268 269 Name, Affiliation, Date: 270 Description of Modification: 271 272 *****************************************************************************/ 273// Taf! 274