Esempio n. 1
0
void
sc_module::end_module()
{
    if( ! m_end_module_called ) {
	/* TBD: Can check here to alert the user that end_module
                was not called for a previous module. */
	(void)sc_get_curr_simcontext()->hierarchy_pop();
	sc_get_curr_simcontext()->reset_curr_proc(); 
	sensitive.reset();
	sensitive_pos.reset();
	sensitive_neg.reset();
	m_end_module_called = true;
	m_module_name_p = 0; // make sure we are not called in ~sc_module().
    }
}
// +----------------------------------------------------------------------------
// |"sc_object_manager::create_name"
// | 
// | This method creates a hierarchical name based on the name of the active 
// | object and the supplied leaf name. If the resultant name is not unique it 
// | will be made unique and a warning message issued.
// |
// | Arguments:
// |     leaf_name = name to use for the leaf of the hierarchy.
// | Result is an std::string containing the name.
// +----------------------------------------------------------------------------
std::string sc_object_manager::create_name(const char* leaf_name) 
{ 
    bool        clash;                  // true if path name exists in obj table
    std::string leafname_string;        // string containing the leaf name.
    std::string parentname_string;      // parent path name 
    sc_object*  parent_p;               // parent for this instance or NULL.
    std::string result_orig_string;     // save for warning message.
    std::string result_string;          // name to return.
 
    // CONSTRUCT PATHNAME TO THE NAME TO BE RETURNED:
    // 
    // If there is not a leaf name generate one. 

    parent_p = sc_get_curr_simcontext()->active_object();
    parentname_string = parent_p ? parent_p->name() : ""; 
    leafname_string = leaf_name; 
    if (parent_p) {
        result_string = parentname_string;
	result_string += SC_HIERARCHY_CHAR;
	result_string += leafname_string;
    } else { 
        result_string = leafname_string;
    } 

    // SAVE the original path name 

    result_orig_string = result_string;

    // MAKE SURE THE ENTITY NAME IS UNIQUE:
    // 
    // If not use unique name generator to make it unique. 

    clash = false; 
    for (;;)
    {
	instance_table_t::iterator it = m_instance_table.find(result_string);
	if ( it == m_instance_table.end() ||
	     (it->second.m_event_p == NULL && it->second.m_object_p == NULL ) )
	{
	    break;
	}
        clash = true; 
        leafname_string = sc_gen_unique_name(leafname_string.c_str(), false); 
	if (parent_p) {
	    result_string = parentname_string;
	    result_string += SC_HIERARCHY_CHAR;
	    result_string += leafname_string;
	} else { 
	    result_string = leafname_string;
	} 
    } 
    if (clash) { 
	std::string message = result_orig_string;
	message += ". Latter declaration will be renamed to ";
	message += result_string;
        SC_REPORT_WARNING( SC_ID_INSTANCE_EXISTS_, message.c_str());
    } 

    return result_string;
}
// +----------------------------------------------------------------------------
// |"sc_object::sc_object_init"
// | 
// | This method initializes this object instance and places it in to the
// | object hierarchy if the supplied name is not NULL.
// |
// | Arguments:
// |     nm = leaf name for the object.
// +----------------------------------------------------------------------------
void 
sc_object::sc_object_init(const char* nm) 
{ 
    // SET UP POINTERS TO OBJECT MANAGER, PARENT, AND SIMULATION CONTEXT: 
    //
    // Make the current simcontext the simcontext for this object 

    m_simc = sc_get_curr_simcontext(); 
    m_attr_cltn_p = 0; 
    sc_object_manager* object_manager = m_simc->get_object_manager(); 
    m_parent = m_simc->active_object();

    // CONSTRUCT PATHNAME TO OBJECT BEING CREATED: 
    // 
    // If there is not a leaf name generate one. 

    m_name = object_manager->create_name(nm ? nm : sc_object_newname().c_str());


    // PLACE THE OBJECT INTO THE HIERARCHY IF A USER LEAF NAME WAS SUPPLIED:
    

    if ( nm != NULL && 
         strncmp(nm, SC_KERNEL_MODULE_PREFIX, strlen(SC_KERNEL_MODULE_PREFIX)) )
    { 
        object_manager->insert_object(m_name, this); 
        if ( m_parent ) 
	    m_parent->add_child_object( this );
	else
	    m_simc->add_child_object( this ); 
    } 

} 
void svf_thread_cond_sc::wait(svf_thread_mutex_sc *m)
{
	// Expect mutex to be locked on entry
	wait_ev *waiter;
	if (m_freelist) {
		waiter = m_freelist;
		m_freelist = m_freelist->m_next;
	} else {
		waiter = new wait_ev();
	}

	waiter->m_next = m_waiters;
	m_waiters = waiter;

	m->unlock();

	// Wait
	sc_core::wait(waiter->m_ev, sc_get_curr_simcontext());

	// Move the waiter to the freelist
	waiter->m_next = m_freelist;
	m_freelist = waiter;

	// Lock the mutex on the way out
	m->lock();
}
Esempio n. 5
0
double
sc_time::to_seconds() const
{
    sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
    return ( sc_dt::uint64_to_double( m_value ) *
	     time_params->time_resolution * 1e-15 );
}
Esempio n. 6
0
bool
sc_pending_activity_at_current_time()
{
    sc_simcontext* c_p = sc_get_curr_simcontext();
    return (c_p->m_delta_events.size() != 0) ||
           !c_p->m_runnable->is_empty() ||
           c_p->m_prim_channel_registry->pending_updates();
}
Esempio n. 7
0
sc_module_name::sc_module_name( const char* name_ )
: m_name( name_ ),
  m_module_p( 0 ),
  m_next( 0 ),
  m_simc( sc_get_curr_simcontext() ),
  m_pushed( true )
{
    m_simc->get_object_manager()->push_module_name( this );
}
int
sc_semaphore::wait()
{
    while( in_use() ) {
	sc_core::wait( m_free, sc_get_curr_simcontext() );
    }
    -- m_value;
    return 0;
}
int
sc_mutex::lock()
{
    if ( m_owner == sc_get_current_process_b()) return 0;
    while( in_use() ) {
	sc_core::wait( m_free, sc_get_curr_simcontext() );
    }
    m_owner = sc_get_current_process_b();
    return 0;
}
Esempio n. 10
0
sc_trace_file_base::~sc_trace_file_base()
{
    if( fp )
        fclose(fp);

#if SC_TRACING_PHASE_CALLBACKS_ == 0
    // unregister from simcontext
    sc_get_curr_simcontext()->remove_trace_file( this );
#endif
}
 void uvm_ml_run_test(const std::vector<std::string>& tops,  const char * test, const sc_time & duration) {
     int top_n = tops.size();
     const char ** local_tops = new const char*[top_n];
     for (int i = 0; i < top_n; ++i) {
         local_tops[i] = tops[i].c_str();
     }
     BP(run_test)(framework_id, top_n, const_cast<char**>(local_tops), const_cast<char*>(test));
     delete[] local_tops;
     sc_simcontext * context = sc_get_curr_simcontext();
     context->co_simulate(duration);
 }
Esempio n. 12
0
double
sc_simulation_time()
{
    static bool warn_simulation_time=true;
    if ( warn_simulation_time )
    {
        warn_simulation_time=false;
        SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
                       "sc_simulation_time() is deprecated use sc_time_stamp()" );
    }
    return sc_get_curr_simcontext()->time_stamp().to_default_time_units();
}
Esempio n. 13
0
void
sc_cycle( const sc_time& duration )
{
    static bool warning_cycle = true;

    if ( warning_cycle )
    {
        warning_cycle = false;
        SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
                       "sc_cycle is deprecated: use sc_start(sc_time)" );
    }
    sc_get_curr_simcontext()->cycle( duration );
}
Esempio n. 14
0
void
sc_initialize()
{
    static bool warning_initialize = true;

    if ( warning_initialize )
    {
        warning_initialize = false;
        SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
                       "sc_initialize() is deprecated: use sc_start(SC_ZERO_TIME)" );
    }
    sc_get_curr_simcontext()->initialize();
}
Esempio n. 15
0
// not documented, but available
const std::string sc_report_compose_message(const sc_report& rep)
{
    static const char * severity_names[] =
    {
        "Info", "Warning", "Error", "Fatal"
    };
    std::string str;

    str += severity_names[rep.get_severity()];
    str += ": ";

    if ( rep.get_id() >= 0 ) // backward compatibility with 2.0+
    {
        char idstr[64];
        std::sprintf(idstr, "(%c%d) ",
                     "IWEF"[rep.get_severity()], rep.get_id());
        str += idstr;
    }
    str += rep.get_msg_type();

    if ( *rep.get_msg() )
    {
        str += ": ";
        str += rep.get_msg();
    }
    if ( rep.get_severity() > SC_INFO )
    {
        char line_number_str[16];
        str += "\nIn file: ";
        str += rep.get_file_name();
        str += ":";
        std::sprintf(line_number_str, "%d", rep.get_line_number());
        str += line_number_str;
        sc_simcontext* simc = sc_get_curr_simcontext();

        if ( simc && sc_is_running() )
        {
            const char* proc_name = rep.get_process_name();

            if ( proc_name )
            {
                str += "\nIn process: ";
                str += proc_name;
                str += " @ ";
                str += rep.get_time().to_string();
            }
        }
    }

    return str;
}
Esempio n. 16
0
// THE FOLLOWING FUNCTION IS DEPRECATED IN 2.1
sc_process_b*
sc_get_curr_process_handle()
{
    static bool warn=true;
    if ( warn )
    {
        warn = false;
        SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
                       "sc_get_curr_process_handle deprecated use sc_get_current_process_handle"
                      );
    }

    return sc_get_curr_simcontext()->get_curr_proc_info()->process_handle;
}
Esempio n. 17
0
bool
sc_writer_policy_check_port::
  check_port( sc_object* target, sc_port_base * port_, bool is_output )
{
    if ( is_output && sc_get_curr_simcontext()->write_check() )
    {
        // an out or inout port; only one can be connected
        if( m_output != 0) {
            sc_signal_invalid_writer( target, m_output, port_, false );
            return false;
        } else {
            m_output = port_;
        }
    }
    return true;
}
Esempio n. 18
0
//------------------------------------------------------------------------------
//"sc_method_process::disable_process"
//
// This virtual method disables this process and its children if requested to.
//     descendants = indicator of whether this process' children should also
//                   be suspended
//------------------------------------------------------------------------------
void sc_method_process::disable_process(
    sc_descendant_inclusion_info descendants )
{     

    // IF NEEDED PROPOGATE THE SUSPEND REQUEST THROUGH OUR DESCENDANTS:

    if ( descendants == SC_INCLUDE_DESCENDANTS )
    {
        const std::vector<sc_object*>& children = get_child_objects();
        int                            child_n  = children.size();

        for ( int child_i = 0; child_i < child_n; child_i++ )
        {
            sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]);
            if ( child_p ) child_p->disable_process(descendants);
        }
    }

    // DON'T ALLOW CORNER CASE BY DEFAULT:

    if ( !sc_allow_process_control_corners )
    {
	switch( m_trigger_type )
	{ 
	  case AND_LIST_TIMEOUT:
	  case EVENT_TIMEOUT: 
	  case OR_LIST_TIMEOUT:
	  case TIMEOUT:
	    report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_,
	                  "attempt to disable a method with timeout wait" );
	    break;
	  default:
	    break;
	}
    }

    // DISABLE OUR OBJECT INSTANCE:

    m_state = m_state | ps_bit_disabled;

    // IF THIS CALL IS BEFORE THE SIMULATION DON'T RUN THE METHOD:

    if ( !sc_is_running() )
    {
        sc_get_curr_simcontext()->remove_runnable_method(this);
    }
}
Esempio n. 19
0
void
REGFILE::
regfile_read_thread(void)
{
	sc_uint<AWORDREG>	a_wreg;
	sc_uint<AWORDREG>	a_reg1;
	sc_uint<AWORDREG>	a_reg2;
	sc_uint<DWORD>		d_wreg;
	sc_uint<1>		w_t;

	while (true) {

		#ifdef VERBOSE
		cerr 	<< "REGFILE" 
			<< " Time is:" 
			<< sc_get_curr_simcontext()->time_stamp() << endl;
		#endif

		w_t = w.read();
		if (w_t == 1) {
			a_wreg = w_addr_reg.read();
			d_wreg = w_data_reg.read();

			#ifdef VERBOSE
			cerr	<< "...writing $" << a_wreg << " = " 
				<< d_wreg << endl;
			#endif
			if (a_wreg < REGSIZE && a_wreg != 0) {
				rfile[a_wreg] = d_wreg;
			}
		}
		else{
		a_reg1 = r_addr_reg1.read();
		a_reg2 = r_addr_reg2.read();
			r_data_reg1.write(rfile[a_reg1]);
			r_data_reg2.write(rfile[a_reg2]);
			#ifdef VERBOSE
			cerr	<< "...reading $" << a_reg1 << " = " 
				<< rfile[a_reg1] << " $" << a_reg2 << " = " 
				<< rfile[a_reg2] << endl;
			#endif
		}
		wait();
	}
}
Esempio n. 20
0
void
sc_start( const sc_time& duration )
{
    sc_simcontext* context;
    int status;

    context = sc_get_curr_simcontext();
    status = context->sim_status();
    if ( status != SC_SIM_OK )
    {
        if ( status == SC_SIM_USER_STOP )
        {
            SC_REPORT_ERROR(SC_ID_SIMULATION_START_AFTER_STOP_, "");
        }
        return;
    }
    context->simulate( duration );
}
Esempio n. 21
0
const char*
sc_gen_unique_name( const char* basename_, bool preserve_first )
{
    sc_simcontext* simc = sc_get_curr_simcontext();
    sc_module* curr_module = simc->hierarchy_curr();
    if( curr_module != 0 ) {
	return curr_module->gen_unique_name( basename_, preserve_first );
    } else {
        sc_process_b* curr_proc_p = sc_get_current_process_b();
	if ( curr_proc_p )
	{
	    return curr_proc_p->gen_unique_name( basename_, preserve_first );
	}
	else
	{
	    return simc->gen_unique_name( basename_, preserve_first );
	}
    }
}
Esempio n. 22
0
bool
sc_vector_base::check_init( size_type n ) const
{
  if ( !n )
    return false;

  if( size() ) // already filled
  {
    std::stringstream str;
    str << name()
        << ", size=" << size()
        << ", requested size=" << n;
    SC_REPORT_ERROR( SC_ID_VECTOR_INIT_CALLED_TWICE_
                   , str.str().c_str() );
    return false;
  }

  sc_simcontext* simc = simcontext();
  sc_assert( simc == sc_get_curr_simcontext() );

  sc_object* parent_p = simc->get_object_manager()->hierarchy_curr();
  if ( !parent_p )
        parent_p = static_cast<sc_object*>( sc_get_current_process_b() );

  if( parent_p != get_parent_object() )
  {
    std::stringstream str;
    str << name() << ": expected "
        << ( get_parent_object()
              ? get_parent_object()->name() : "<top-level>" )
        << ", got "
        << ( parent_p ? parent_p->name() : "<top-level>" );

    SC_REPORT_ERROR( SC_ID_VECTOR_INIT_INVALID_CONTEXT_
                   , str.str().c_str() );
    return false;
  }

  return true;
}
Esempio n. 23
0
const std::string
sc_time::to_string() const
{
    sc_dt::uint64 val = m_value;
    if( val == 0 ) {
	return std::string( "0 s" );
    }
    sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params;
    sc_dt::uint64 tr = SCAST<sc_dt::int64>( time_params->time_resolution );
    int n = 0;
    while( ( tr % 10 ) == 0 ) {
	tr /= 10;
	n ++;
    }
    assert( tr == 1 );
    while( ( val % 10 ) == 0 ) {
	val /= 10;
	n ++;
    }
    char buf[BUFSIZ];
#if !defined( _MSC_VER )
    std::sprintf( buf, "%llu", val );
#else
    std::sprintf( buf, "%I64u", val );
#endif
    std::string result( buf );
    if( n >= 15 ) {
	for( int i = n - 15; i > 0; -- i ) {
	    result += "0";
	}
	result += " s";
    } else {
	for( int i = n % 3; i > 0; -- i ) {
	    result += "0";
	}
	result += " ";
	result += time_units[n / 3];
    }
    return result;
}
Esempio n. 24
0
sc_trace_file_base::sc_trace_file_base( const char* name, const char* extension )
  : sc_trace_file()
#if SC_TRACING_PHASE_CALLBACKS_
  , sc_object( sc_gen_unique_name("$$$$kernel_tracefile$$$$") )
#endif
  , fp(0)
  , timescale_unit()
  , timescale_set_by_user(false)
  , filename_() 
  , initialized_(false)
  , trace_delta_cycles_(false)
{
    if( !name || !*name ) {
        SC_REPORT_ERROR( SC_ID_TRACING_FOPEN_FAILED_, "no name given" );
        return;
    } else {
        std::stringstream ss;
        ss << name << "." << extension;
        ss.str().swap( filename_ );
    }

#if SC_TRACING_PHASE_CALLBACKS_ == 1
    // remove from hierarchy
    sc_object::detach();
    // register regular (non-delta) callbacks
    sc_object::register_simulation_phase_callback(
        // Note: Usually, one would expect to dump the initial values
        //       of the traced variables at the end of the initialization
        //       phase.  The "non-callback" implementation dumps those
        //       values only after the first delta cycle, though.
        // SC_END_OF_INITIALIZATION |
        SC_BEFORE_TIMESTEP |
        SC_PAUSED | SC_STOPPED
    );
#else // explicitly register with simcontext
    sc_get_curr_simcontext()->add_trace_file( this );
#endif
}
Esempio n. 25
0
//------------------------------------------------------------------------------
// Function: process_state_executing_nonruntime
//
// Parameters:
//------------------------------------------------------------------------------
void uvm_common_phase::process_state_executing_nonruntime(sc_core::sc_module *pmod)
{
    std::ostringstream outmsg;

    if (get_phase_type() != UVM_POSTRUN_PHASE) { // postrun phases are not generalized yet
        int result = do_execute(pmod);

        if (result && (CHECK_STOP_AT_PHASE_END() == true)) {
            SC_REPORT_INFO(UVM_PHASE_CTRL_STOP_USER, "");
#ifdef UVM_ML_PORTABLE
            // TODO - should be be incorporated into the phase controller instead?
            sc_get_curr_simcontext()->stop();
#endif
	    //  result = 0;
        }
    }
    else {
        uvm_component* pcomp = DCAST<uvm_component*>(pmod); 
        if (pcomp != NULL) {
            if (_name.compare("final") == 0)
                pcomp->final_phase(this);
            else if (_name.compare("extract") == 0)
                pcomp->extract_phase(this);
            else if (_name.compare("check") == 0)
                pcomp->check_phase(this);
            else if (_name.compare("report") == 0)
                pcomp->report_phase(this);
            else
            {
                outmsg << _name << endl;
                SC_REPORT_FATAL(UVM_PHASE_UNKNOWN, outmsg.str().c_str());
                exit(1);        // TODO - is 'exit()' needed here after a FATAL?
            }
        }
    }
}
int uvm_ml_tlm_rec::startup() {
    uvm_ml_utils::m_quasi_static_elaboration_started = true;
    sc_get_curr_simcontext()->quasi_static_start_of_construction();
    return 1;
}
Esempio n. 27
0
const sc_time&
sc_time_stamp()
{
    return sc_get_curr_simcontext()->time_stamp();
}
Esempio n. 28
0
	void ghi()
	{
		sc_curr_proc_handle cpi = sc_get_curr_simcontext()->get_curr_proc_info();
		cout << cpi->process_handle->name() << endl;
	}
Esempio n. 29
0
void 
sc_object::sc_object_init(const char* nm) 
{ 
    bool        clash;                  // True if path name exists in obj table
    const char* leafname_p;             // Leaf name (this object) 
    char        pathname[BUFSIZ];       // Path name 
    char        pathname_orig[BUFSIZ];  // Original path name which may clash 
    const char* parentname_p;           // Parent path name 
    bool        put_in_table;           // True if should put in object table 
 
    // SET UP POINTERS TO OBJECT MANAGER, PARENT, AND SIMULATION CONTEXT: 
	//
    // Make the current simcontext the simcontext for this object 

    m_simc = sc_get_curr_simcontext(); 
    m_attr_cltn_p = 0; 
    sc_object_manager* object_manager = m_simc->get_object_manager(); 
    sc_object*         parent_p = object_manager->hierarchy_curr(); 
    if (!parent_p) { 
        sc_object* proc = (sc_object*)sc_get_current_process_b();
        parent_p = proc; 
    } 
    m_parent = parent_p; 


    // CONSTRUCT PATHNAME TO OBJECT BEING CREATED: 
    // 
    // If there is not a leaf name generate one. 

    parentname_p = parent_p ? parent_p->name() : ""; 
    if (nm && nm[0] ) 
    { 
        leafname_p = nm; 
        put_in_table = true; 
    } 
    else 
    { 
        leafname_p = sc_object_newname(pathname_orig); 
        put_in_table = false; 
    } 
    if (parent_p) { 
        std::sprintf(pathname, "%s%c%s", parentname_p, 
                SC_HIERARCHY_CHAR, leafname_p 
        ); 
    } else { 
        strcpy(pathname, leafname_p); 
    } 

    // SAVE the original path name 
    // 
    strcpy(pathname_orig, pathname); 

    // MAKE SURE THE OBJECT NAME IS UNIQUE 
    // 
    // If not use unique name generator to make it unique. 

    clash = false; 
    while (object_manager->find_object(pathname)) { 
        clash = true; 
        leafname_p = sc_gen_unique_name(leafname_p); 
        if (parent_p) { 
            std::sprintf(pathname, "%s%c%s", parentname_p, 
                    SC_HIERARCHY_CHAR, leafname_p 
            ); 
        } else { 
            strcpy(pathname, leafname_p); 
        } 
    } 
    if (clash) { 
	std::string message = pathname_orig;
	message += ". Latter declaration will be renamed to ";
	message += pathname;
        SC_REPORT_WARNING( SC_ID_OBJECT_EXISTS_, message.c_str());
    } 


    // MOVE OBJECT NAME TO PERMANENT STORAGE 
    // 
    // Note here we pull a little trick -- use the first byte to store 
    // information about whether to put the object in the object table in the 
    // object manager 

    char* ptr = new char[strlen( pathname ) + 2]; 
    ptr[0] = put_in_table; 
    m_name = ptr + 1; 
    strcpy(m_name, pathname); 

    if (put_in_table) { 
        object_manager->insert_object(m_name, this); 
        sc_module* curr_module = m_simc->hierarchy_curr(); 
        if( curr_module != 0 ) { 
            curr_module->add_child_object( this ); 
        } else { 
            sc_process_b* curr_proc = sc_get_current_process_b();
            if (curr_proc) { 
                curr_proc->add_child_object( this ); 
            } else { 
                m_simc->add_child_object( this ); 
            } 
        } 
    } 
} 
Esempio n. 30
0
void
sc_set_time_resolution( double v, sc_time_unit tu )
{
    // first perform the necessary checks

    // must be positive
    if( v < 0.0 ) {
	SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "value not positive" );
    }

    // must be a power of ten
    double dummy;
#if defined( __HP_aCC ) || defined(__ppc__)
    // aCC seems to have a bug in modf()
    if( modf( log10( v < 1.0 ? 1.0/v : v ), &dummy ) != 0.0 ) {
#else
    if( modf( log10( v ), &dummy ) != 0.0 ) {
#endif
	SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_,
			 "value not a power of ten" );
    }

    sc_simcontext* simc = sc_get_curr_simcontext();

    // can only be specified during elaboration
    if( sc_is_running() ) {
	SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "simulation running" );
    }

    sc_time_params* time_params = simc->m_time_params;

    // can be specified only once
    if( time_params->time_resolution_specified ) {
	SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "already specified" );
    }

    // can only be specified before any sc_time is constructed
    if( time_params->time_resolution_fixed ) {
	SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_,
			 "sc_time object(s) constructed" );
    }

    // must be larger than or equal to 1 fs
    volatile double resolution = v * time_values[tu];
    if( resolution < 1.0 ) {
	SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_,
			 "value smaller than 1 fs" );
    }

    // recalculate the default time unit
    volatile double time_unit = sc_dt::uint64_to_double(
	time_params->default_time_unit ) *
	( time_params->time_resolution / resolution );
    if( time_unit < 1.0 ) {
	SC_REPORT_WARNING( SC_ID_DEFAULT_TIME_UNIT_CHANGED_, 0 );
	time_params->default_time_unit = 1;
    } else {
	time_params->default_time_unit = SCAST<sc_dt::int64>( time_unit );
    }

    time_params->time_resolution = resolution;
    time_params->time_resolution_specified = true;
}

sc_time 
sc_get_time_resolution()
{
    return sc_time( sc_dt::UINT64_ONE, false );
}


void
sc_set_default_time_unit( double v, sc_time_unit tu )
{
    static bool warn_default_time_unit=true;
    if ( warn_default_time_unit )
    {
        warn_default_time_unit=false;
        SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
	    "deprecated function: sc_set_default_time_unit");
    }
    
    // first perform the necessary checks

    // must be positive
    if( v < 0.0 ) {
	SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "value not positive" );
    }

    // must be a power of ten
    double dummy;
    if( modf( log10( v ), &dummy ) != 0.0 ) {
	SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_,
			 "value not a power of ten" );
    }

    sc_simcontext* simc = sc_get_curr_simcontext();

    // can only be specified during elaboration
    if( sc_is_running() ) {
	SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "simulation running" );
    }

    sc_time_params* time_params = simc->m_time_params;

    // can only be specified before any sc_time is constructed
    if( time_params->time_resolution_fixed ) {
        SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_,
                         "sc_time object(s) constructed" );
    }

    // can be specified only once
    if( time_params->default_time_unit_specified ) {
	SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "already specified" );
    }

    // must be larger than or equal to the time resolution
    volatile double time_unit = ( v * time_values[tu] ) /
	                        time_params->time_resolution;
    if( time_unit < 1.0 ) {
	SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_,
			 "value smaller than time resolution" );
    }

    time_params->default_time_unit = SCAST<sc_dt::int64>( time_unit );
    time_params->default_time_unit_specified = true;
}

sc_time
sc_get_default_time_unit()
{
    bool warn_get_default_time_unit = true;
    if ( warn_get_default_time_unit )
    {
        warn_get_default_time_unit=false;
        SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
            "deprecated function: sc_get_default_time_unit");
    }
    return sc_time( sc_get_curr_simcontext()->m_time_params->default_time_unit,
		    false );
}


// ----------------------------------------------------------------------------

const sc_time SC_ZERO_TIME;


} // namespace sc_core