112027Sjungma@eit.uni-kl.de/*****************************************************************************
212027Sjungma@eit.uni-kl.de
312027Sjungma@eit.uni-kl.de  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
412027Sjungma@eit.uni-kl.de  more contributor license agreements.  See the NOTICE file distributed
512027Sjungma@eit.uni-kl.de  with this work for additional information regarding copyright ownership.
612027Sjungma@eit.uni-kl.de  Accellera licenses this file to you under the Apache License, Version 2.0
712027Sjungma@eit.uni-kl.de  (the "License"); you may not use this file except in compliance with the
812027Sjungma@eit.uni-kl.de  License.  You may obtain a copy of the License at
912027Sjungma@eit.uni-kl.de
1012027Sjungma@eit.uni-kl.de    http://www.apache.org/licenses/LICENSE-2.0
1112027Sjungma@eit.uni-kl.de
1212027Sjungma@eit.uni-kl.de  Unless required by applicable law or agreed to in writing, software
1312027Sjungma@eit.uni-kl.de  distributed under the License is distributed on an "AS IS" BASIS,
1412027Sjungma@eit.uni-kl.de  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1512027Sjungma@eit.uni-kl.de  implied.  See the License for the specific language governing
1612027Sjungma@eit.uni-kl.de  permissions and limitations under the License.
1712027Sjungma@eit.uni-kl.de
1812027Sjungma@eit.uni-kl.de *****************************************************************************/
1912027Sjungma@eit.uni-kl.de
2012027Sjungma@eit.uni-kl.de/*****************************************************************************
2112027Sjungma@eit.uni-kl.de
2212027Sjungma@eit.uni-kl.de  sc_trace_file_base.cpp - Shared internal tracing implementation
2312027Sjungma@eit.uni-kl.de
2412027Sjungma@eit.uni-kl.de  Original Author: Philipp A. Hartmann, OFFIS, 2013-11-15
2512027Sjungma@eit.uni-kl.de
2612027Sjungma@eit.uni-kl.de  CHANGE LOG AT END OF FILE
2712027Sjungma@eit.uni-kl.de *****************************************************************************/
2812027Sjungma@eit.uni-kl.de
2912027Sjungma@eit.uni-kl.de/*****************************************************************************
3012027Sjungma@eit.uni-kl.de
3112027Sjungma@eit.uni-kl.de   Acknowledgement: The tracing mechanism is based on the tracing
3212027Sjungma@eit.uni-kl.de   mechanism developed at Infineon (formerly Siemens HL). Though this
3312027Sjungma@eit.uni-kl.de   code is somewhat different, and significantly enhanced, the basics
3412027Sjungma@eit.uni-kl.de   are identical to what was originally contributed by Infineon.  The
3512027Sjungma@eit.uni-kl.de   contribution of Infineon in the development of this tracing
3612027Sjungma@eit.uni-kl.de   technology is hereby acknowledged.
3712027Sjungma@eit.uni-kl.de
3812027Sjungma@eit.uni-kl.de *****************************************************************************/
3912027Sjungma@eit.uni-kl.de
4012027Sjungma@eit.uni-kl.de#include <ctime>
4112027Sjungma@eit.uni-kl.de
4212027Sjungma@eit.uni-kl.de#include "sysc/tracing/sc_trace_file_base.h"
4312027Sjungma@eit.uni-kl.de#include "sysc/kernel/sc_simcontext.h"
4412027Sjungma@eit.uni-kl.de#include "sysc/kernel/sc_simcontext_int.h"
4512027Sjungma@eit.uni-kl.de
4612027Sjungma@eit.uni-kl.de#if SC_TRACING_PHASE_CALLBACKS_
4712027Sjungma@eit.uni-kl.de#  include "sysc/kernel/sc_object_int.h"
4812027Sjungma@eit.uni-kl.de#endif
4912027Sjungma@eit.uni-kl.de
5012027Sjungma@eit.uni-kl.denamespace sc_core {
5112027Sjungma@eit.uni-kl.de
5212027Sjungma@eit.uni-kl.debool sc_trace_file_base::tracing_initialized_ = false;
5312027Sjungma@eit.uni-kl.de
5412027Sjungma@eit.uni-kl.de
5512027Sjungma@eit.uni-kl.desc_trace_file_base::sc_trace_file_base( const char* name, const char* extension )
5612027Sjungma@eit.uni-kl.de  : sc_trace_file()
5712027Sjungma@eit.uni-kl.de#if SC_TRACING_PHASE_CALLBACKS_
5812027Sjungma@eit.uni-kl.de  , sc_object( sc_gen_unique_name("$$$$kernel_tracefile$$$$") )
5912027Sjungma@eit.uni-kl.de#endif
6012027Sjungma@eit.uni-kl.de  , fp(0)
6112027Sjungma@eit.uni-kl.de  , timescale_unit()
6212027Sjungma@eit.uni-kl.de  , timescale_set_by_user(false)
6312027Sjungma@eit.uni-kl.de  , filename_()
6412027Sjungma@eit.uni-kl.de  , initialized_(false)
6512027Sjungma@eit.uni-kl.de  , trace_delta_cycles_(false)
6612027Sjungma@eit.uni-kl.de{
6712027Sjungma@eit.uni-kl.de    if( !name || !*name ) {
6812027Sjungma@eit.uni-kl.de        SC_REPORT_ERROR( SC_ID_TRACING_FOPEN_FAILED_, "no name given" );
6912027Sjungma@eit.uni-kl.de        return;
7012027Sjungma@eit.uni-kl.de    } else {
7112027Sjungma@eit.uni-kl.de        std::stringstream ss;
7212027Sjungma@eit.uni-kl.de        ss << name << "." << extension;
7312027Sjungma@eit.uni-kl.de        ss.str().swap( filename_ );
7412027Sjungma@eit.uni-kl.de    }
7512027Sjungma@eit.uni-kl.de
7612027Sjungma@eit.uni-kl.de#if SC_TRACING_PHASE_CALLBACKS_ == 1
7712027Sjungma@eit.uni-kl.de    // remove from hierarchy
7812027Sjungma@eit.uni-kl.de    sc_object::detach();
7912027Sjungma@eit.uni-kl.de    // register regular (non-delta) callbacks
8012027Sjungma@eit.uni-kl.de    sc_object::register_simulation_phase_callback(
8112027Sjungma@eit.uni-kl.de        // Note: Usually, one would expect to dump the initial values
8212027Sjungma@eit.uni-kl.de        //       of the traced variables at the end of the initialization
8312027Sjungma@eit.uni-kl.de        //       phase.  The "non-callback" implementation dumps those
8412027Sjungma@eit.uni-kl.de        //       values only after the first delta cycle, though.
8512027Sjungma@eit.uni-kl.de        // SC_END_OF_INITIALIZATION |
8612027Sjungma@eit.uni-kl.de        SC_BEFORE_TIMESTEP |
8712027Sjungma@eit.uni-kl.de        SC_PAUSED | SC_STOPPED
8812027Sjungma@eit.uni-kl.de    );
8912027Sjungma@eit.uni-kl.de#else // explicitly register with simcontext
9012027Sjungma@eit.uni-kl.de    sc_get_curr_simcontext()->add_trace_file( this );
9112027Sjungma@eit.uni-kl.de#endif
9212027Sjungma@eit.uni-kl.de}
9312027Sjungma@eit.uni-kl.de
9412027Sjungma@eit.uni-kl.desc_trace_file_base::~sc_trace_file_base()
9512027Sjungma@eit.uni-kl.de{
9612027Sjungma@eit.uni-kl.de    if( fp )
9712027Sjungma@eit.uni-kl.de        fclose(fp);
9812027Sjungma@eit.uni-kl.de
9912027Sjungma@eit.uni-kl.de#if SC_TRACING_PHASE_CALLBACKS_ == 0
10012027Sjungma@eit.uni-kl.de    // unregister from simcontext
10112027Sjungma@eit.uni-kl.de    sc_get_curr_simcontext()->remove_trace_file( this );
10212027Sjungma@eit.uni-kl.de#endif
10312027Sjungma@eit.uni-kl.de}
10412027Sjungma@eit.uni-kl.de
10512027Sjungma@eit.uni-kl.de/*****************************************************************************/
10612027Sjungma@eit.uni-kl.de// simulation phase callback based trigger
10712027Sjungma@eit.uni-kl.de//
10812027Sjungma@eit.uni-kl.de//  The tracing updates are triggered
10912027Sjungma@eit.uni-kl.de//    (- at the end of the initialization phase [disabled for now])
11012027Sjungma@eit.uni-kl.de//    - before an update of the simulation time
11112027Sjungma@eit.uni-kl.de//    - before returning to sc_start (via sc_pause() or sc_stop())
11212027Sjungma@eit.uni-kl.de//    - after an update phase (if delta cycles need to be traced)
11312027Sjungma@eit.uni-kl.de//
11412027Sjungma@eit.uni-kl.de#if SC_TRACING_PHASE_CALLBACKS_
11512027Sjungma@eit.uni-kl.devoid
11612027Sjungma@eit.uni-kl.desc_trace_file_base::simulation_phase_callback()
11712027Sjungma@eit.uni-kl.de{
11812027Sjungma@eit.uni-kl.de    // delta cycle is traced at the end of an update phase
11912027Sjungma@eit.uni-kl.de    cycle( simcontext()->get_status() == SC_END_OF_UPDATE );
12012027Sjungma@eit.uni-kl.de}
12112027Sjungma@eit.uni-kl.de#endif // SC_TRACING_PHASE_CALLBACKS_
12212027Sjungma@eit.uni-kl.de
12312027Sjungma@eit.uni-kl.de/*****************************************************************************/
12412027Sjungma@eit.uni-kl.de
12512027Sjungma@eit.uni-kl.debool
12612027Sjungma@eit.uni-kl.desc_trace_file_base::initialize()
12712027Sjungma@eit.uni-kl.de{
12812027Sjungma@eit.uni-kl.de    if( initialized_ )
12912027Sjungma@eit.uni-kl.de      return false;
13012027Sjungma@eit.uni-kl.de
13112027Sjungma@eit.uni-kl.de    initialized_ = true;
13212027Sjungma@eit.uni-kl.de
13312027Sjungma@eit.uni-kl.de    if( !tracing_initialized_ ) {
13412027Sjungma@eit.uni-kl.de        tracing_initialized_ = true;
13512027Sjungma@eit.uni-kl.de        bool running_regression = ( getenv( "SYSTEMC_REGRESSION" ) != NULL );
13612027Sjungma@eit.uni-kl.de
13712027Sjungma@eit.uni-kl.de        // hide some messages during regression
13812027Sjungma@eit.uni-kl.de        if( running_regression ) {
13912027Sjungma@eit.uni-kl.de          sc_report_handler::set_actions( SC_ID_TRACING_TIMESCALE_DEFAULT_
14012027Sjungma@eit.uni-kl.de                                        , SC_INFO,    SC_DO_NOTHING );
14112027Sjungma@eit.uni-kl.de          sc_report_handler::set_actions( SC_ID_TRACING_VCD_DUPLICATE_TIME_
14212027Sjungma@eit.uni-kl.de                                        , SC_WARNING, SC_DO_NOTHING );
14312027Sjungma@eit.uni-kl.de        }
14412027Sjungma@eit.uni-kl.de    }
14512027Sjungma@eit.uni-kl.de
14612027Sjungma@eit.uni-kl.de    // open trace file
14712027Sjungma@eit.uni-kl.de    if(!fp) open_fp();
14812027Sjungma@eit.uni-kl.de
14912027Sjungma@eit.uni-kl.de    // setup timescale
15012027Sjungma@eit.uni-kl.de    if( !timescale_set_by_user )
15112027Sjungma@eit.uni-kl.de    {
15212027Sjungma@eit.uni-kl.de        timescale_unit = sc_get_time_resolution().to_seconds();
15312027Sjungma@eit.uni-kl.de
15412027Sjungma@eit.uni-kl.de        std::stringstream ss;
15512027Sjungma@eit.uni-kl.de        ss << sc_get_time_resolution() << " (" << filename_ << ")";
15612027Sjungma@eit.uni-kl.de        SC_REPORT_INFO( SC_ID_TRACING_TIMESCALE_DEFAULT_
15712027Sjungma@eit.uni-kl.de                      , ss.str().c_str() );
15812027Sjungma@eit.uni-kl.de    }
15912027Sjungma@eit.uni-kl.de
16012027Sjungma@eit.uni-kl.de    // initialize derived tracing implementation class (VCD/WIF)
16112027Sjungma@eit.uni-kl.de    do_initialize();
16212027Sjungma@eit.uni-kl.de
16312027Sjungma@eit.uni-kl.de    return initialized_;
16412027Sjungma@eit.uni-kl.de}
16512027Sjungma@eit.uni-kl.de
16612027Sjungma@eit.uni-kl.devoid
16712027Sjungma@eit.uni-kl.desc_trace_file_base::open_fp()
16812027Sjungma@eit.uni-kl.de{
16912027Sjungma@eit.uni-kl.de    sc_assert( !fp );
17012027Sjungma@eit.uni-kl.de    fp = fopen( filename(), "w" );
17112027Sjungma@eit.uni-kl.de    if( !fp ) {
17212027Sjungma@eit.uni-kl.de        SC_REPORT_ERROR( SC_ID_TRACING_FOPEN_FAILED_, filename() );
17312027Sjungma@eit.uni-kl.de        std::terminate(); // can't recover from here
17412027Sjungma@eit.uni-kl.de    }
17512027Sjungma@eit.uni-kl.de}
17612027Sjungma@eit.uni-kl.de
17712027Sjungma@eit.uni-kl.devoid
17812027Sjungma@eit.uni-kl.desc_trace_file_base::delta_cycles( bool flag )
17912027Sjungma@eit.uni-kl.de{
18012027Sjungma@eit.uni-kl.de    trace_delta_cycles_ = flag;
18112027Sjungma@eit.uni-kl.de#if SC_TRACING_PHASE_CALLBACKS_
18212027Sjungma@eit.uni-kl.de    if( trace_delta_cycles_ ) {
18312027Sjungma@eit.uni-kl.de        sc_object::register_simulation_phase_callback( SC_END_OF_UPDATE );
18412027Sjungma@eit.uni-kl.de    } else {
18512027Sjungma@eit.uni-kl.de        sc_object::unregister_simulation_phase_callback( SC_END_OF_UPDATE );
18612027Sjungma@eit.uni-kl.de    }
18712027Sjungma@eit.uni-kl.de#endif
18812027Sjungma@eit.uni-kl.de}
18912027Sjungma@eit.uni-kl.de
19012027Sjungma@eit.uni-kl.devoid
19112027Sjungma@eit.uni-kl.desc_trace_file_base::set_time_unit( double v, sc_time_unit tu )
19212027Sjungma@eit.uni-kl.de{
19312027Sjungma@eit.uni-kl.de    if( initialized_ )
19412027Sjungma@eit.uni-kl.de    {
19512027Sjungma@eit.uni-kl.de        std::stringstream ss;
19612027Sjungma@eit.uni-kl.de        ss << filename_ << "\n"
19712027Sjungma@eit.uni-kl.de           "\tTimescale unit cannot be changed once tracing has begun.\n"
19812027Sjungma@eit.uni-kl.de           "\tTo change the scale, create a new trace file.";
19912027Sjungma@eit.uni-kl.de        SC_REPORT_ERROR( SC_ID_TRACING_ALREADY_INITIALIZED_
20012027Sjungma@eit.uni-kl.de                       , ss.str().c_str() );
20112027Sjungma@eit.uni-kl.de        return;
20212027Sjungma@eit.uni-kl.de    }
20312027Sjungma@eit.uni-kl.de
20412027Sjungma@eit.uni-kl.de    switch ( tu )
20512027Sjungma@eit.uni-kl.de    {
20612027Sjungma@eit.uni-kl.de      case SC_FS:  v = v * 1e-15; break;
20712027Sjungma@eit.uni-kl.de      case SC_PS:  v = v * 1e-12; break;
20812027Sjungma@eit.uni-kl.de      case SC_NS:  v = v * 1e-9;  break;
20912027Sjungma@eit.uni-kl.de      case SC_US:  v = v * 1e-6;  break;
21012027Sjungma@eit.uni-kl.de      case SC_MS:  v = v * 1e-3;  break;
21112027Sjungma@eit.uni-kl.de      case SC_SEC:                break;
21212027Sjungma@eit.uni-kl.de      default: {
21312027Sjungma@eit.uni-kl.de            std::stringstream ss;
21412027Sjungma@eit.uni-kl.de            ss << "unknown time unit:" << tu
21512027Sjungma@eit.uni-kl.de               << " (" << filename_ << ")";
21612027Sjungma@eit.uni-kl.de            SC_REPORT_WARNING( SC_ID_TRACING_TIMESCALE_UNIT_
21712027Sjungma@eit.uni-kl.de                             , ss.str().c_str() );
21812027Sjungma@eit.uni-kl.de        }
21912027Sjungma@eit.uni-kl.de    }
22012027Sjungma@eit.uni-kl.de
22112027Sjungma@eit.uni-kl.de    timescale_set_by_user = true;
22212027Sjungma@eit.uni-kl.de    timescale_unit = v;
22312027Sjungma@eit.uni-kl.de
22412027Sjungma@eit.uni-kl.de    // EMIT ADVISORY MESSAGE ABOUT CHANGE IN TIME SCALE:
22512027Sjungma@eit.uni-kl.de    {
22612027Sjungma@eit.uni-kl.de      std::stringstream ss;
22712027Sjungma@eit.uni-kl.de      ss << sc_time( timescale_unit, SC_SEC )
22812027Sjungma@eit.uni-kl.de         << " (" << filename_ << ")";
22912027Sjungma@eit.uni-kl.de      SC_REPORT_INFO( SC_ID_TRACING_TIMESCALE_UNIT_, ss.str().c_str() );
23012027Sjungma@eit.uni-kl.de    }
23112027Sjungma@eit.uni-kl.de}
23212027Sjungma@eit.uni-kl.de
23312027Sjungma@eit.uni-kl.debool
23412027Sjungma@eit.uni-kl.desc_trace_file_base::add_trace_check( const std::string & name ) const
23512027Sjungma@eit.uni-kl.de{
23612027Sjungma@eit.uni-kl.de    if( !initialized_ ) return true;
23712027Sjungma@eit.uni-kl.de
23812027Sjungma@eit.uni-kl.de    std::stringstream ss;
23912027Sjungma@eit.uni-kl.de    ss << "sc_trace() failed:\n"
24012027Sjungma@eit.uni-kl.de         "\tNo traces can be added to "
24112027Sjungma@eit.uni-kl.de         "'" << filename_  << "'"
24212027Sjungma@eit.uni-kl.de         " once trace recording has started.\n"
24312027Sjungma@eit.uni-kl.de         "\tTo add tracing of '" << name << "', create a new trace file.";
24412027Sjungma@eit.uni-kl.de
24512027Sjungma@eit.uni-kl.de    SC_REPORT_ERROR( SC_ID_TRACING_ALREADY_INITIALIZED_
24612027Sjungma@eit.uni-kl.de                   , ss.str().c_str() );
24712027Sjungma@eit.uni-kl.de    return false;
24812027Sjungma@eit.uni-kl.de}
24912027Sjungma@eit.uni-kl.de
25012027Sjungma@eit.uni-kl.de// obtain formatted time string
25112027Sjungma@eit.uni-kl.destd::string localtime_string()
25212027Sjungma@eit.uni-kl.de{
25312027Sjungma@eit.uni-kl.de    char buf[200];
25412027Sjungma@eit.uni-kl.de    time_t long_time;
25512027Sjungma@eit.uni-kl.de    time(&long_time);
25612027Sjungma@eit.uni-kl.de    struct tm* p_tm = localtime(&long_time);
25712027Sjungma@eit.uni-kl.de    strftime(buf, 199, "%b %d, %Y       %H:%M:%S", p_tm);
25812027Sjungma@eit.uni-kl.de    return buf;
25912027Sjungma@eit.uni-kl.de}
26012027Sjungma@eit.uni-kl.de
26112027Sjungma@eit.uni-kl.de
26212027Sjungma@eit.uni-kl.de} // namespace sc_core
26312027Sjungma@eit.uni-kl.de
26412027Sjungma@eit.uni-kl.de/*****************************************************************************
26512027Sjungma@eit.uni-kl.de
26612027Sjungma@eit.uni-kl.de  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
26712027Sjungma@eit.uni-kl.de  changes you are making here.
26812027Sjungma@eit.uni-kl.de
26912027Sjungma@eit.uni-kl.de      Name, Affiliation, Date:
27012027Sjungma@eit.uni-kl.de  Description of Modification:
27112027Sjungma@eit.uni-kl.de
27212027Sjungma@eit.uni-kl.de *****************************************************************************/
27312027Sjungma@eit.uni-kl.de// Taf!
274