//------------------------------------------------------------------------------
//"sc_process_b::reset_changed"
//
// This method is called when there is a change in the value of the
// signal that was specified via reset_signal_is, or the value of the
// m_sticky_reset field. We get called any time m_sticky_reset changes
// or a signal value changes since, since we may need to throw an exception
// or clear one. Note that this method may be called when there is no
// active process, but rather the main simulator is executing so we must
// check for that case.
//
// Arguments:
//     async    = true if this is an asynchronous reset.
//     asserted = true if reset being asserted, false if being deasserted.
//------------------------------------------------------------------------------
void sc_process_b::reset_changed( bool async, bool asserted )
{

    // Error out on the corner case:

    if ( !sc_allow_process_control_corners && !async &&
            (m_state & ps_bit_suspended) )
    {
        report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_,
                      "synchronous reset changed on a suspended process" );
    }

    // IF THIS OBJECT IS PUSHING UP DAISIES WE ARE DONE:

    if ( m_state & ps_bit_zombie ) return;

    // Reset is being asserted:

    if ( asserted )
    {
        // if ( m_reset_event_p ) m_reset_event_p->notify();
        if ( async )
        {
            m_active_areset_n++;
            if ( sc_is_running() ) throw_reset(true);
        }
        else
        {
            m_active_reset_n++;
            if ( sc_is_running() ) throw_reset(false);
        }
    }

    // Reset is being deasserted:

    else
    {
        if ( async )
        {
            m_active_areset_n--;
        }
        else
        {
            m_active_reset_n--;
        }
    }

    // Clear the throw type if there are no active resets.

    if ( (m_throw_status == THROW_SYNC_RESET ||
            m_throw_status == THROW_ASYNC_RESET) &&
            m_active_areset_n == 0 && m_active_reset_n == 0 && !m_sticky_reset )
    {
        m_throw_status = THROW_NONE;
    }
}
//------------------------------------------------------------------------------
//"sc_method_process::sc_method_process"
//
// This is the object instance constructor for this class.
//------------------------------------------------------------------------------
sc_method_process::sc_method_process( const char* name_p,
                                      bool free_host, SC_ENTRY_FUNC method_p,
                                      sc_process_host* host_p, const sc_spawn_options* opt_p
                                    ):
        sc_process_b(
            name_p && name_p[0] ? name_p : sc_gen_unique_name("method_p"),
            free_host, method_p, host_p, opt_p)
{

    // CHECK IF THIS IS AN sc_module-BASED PROCESS AND SIMUALTION HAS STARTED:

    if ( DCAST<sc_module*>(host_p) != 0 && sc_is_running() )
    {
        SC_REPORT_ERROR( SC_ID_MODULE_METHOD_AFTER_START_, "" );
    }

    // INITIALIZE VALUES:
    //
    // If there are spawn options use them.

    m_process_kind = SC_METHOD_PROC_;
    if (opt_p)
    {
        m_dont_init = opt_p->m_dont_initialize;

        // traverse event sensitivity list
        for (unsigned int i = 0; i < opt_p->m_sensitive_events.size(); i++)
        {
            sc_sensitive::make_static_sensitivity(
                this, *opt_p->m_sensitive_events[i]);
        }

        // traverse port base sensitivity list
        for ( unsigned int i = 0; i < opt_p->m_sensitive_port_bases.size(); i++)
        {
            sc_sensitive::make_static_sensitivity(
                this, *opt_p->m_sensitive_port_bases[i]);
        }

        // traverse interface sensitivity list
        for ( unsigned int i = 0; i < opt_p->m_sensitive_interfaces.size(); i++)
        {
            sc_sensitive::make_static_sensitivity(
                this, *opt_p->m_sensitive_interfaces[i]);
        }

        // traverse event finder sensitivity list
        for ( unsigned int i = 0; i < opt_p->m_sensitive_event_finders.size();
                i++)
        {
            sc_sensitive::make_static_sensitivity(
                this, *opt_p->m_sensitive_event_finders[i]);
        }
    }

    else
    {
        m_dont_init = false;
    }
}
Exemple #3
0
void
sc_port_registry::insert( sc_port_base* port_ )
{
    if( sc_is_running() ) {
        port_->report_error( SC_ID_INSERT_PORT_, "simulation running" );
        return;
    }

    if( m_simc->elaboration_done()  ) {
       port_->report_error( SC_ID_INSERT_PORT_, "elaboration done" );
        return;
    }

#if defined(DEBUG_SYSTEMC)
    // check if port_ is already inserted
    for( int i = size() - 1; i >= 0; -- i ) {
        if( port_ == m_port_vec[i] ) {
            port_->report_error( SC_ID_INSERT_PORT_, "port already inserted" );
            return;
        }
    }
#endif

    // append the port to the current module's vector of ports
    sc_module* curr_module = m_simc->hierarchy_curr();
    if( curr_module == 0 ) {
        port_->report_error( SC_ID_PORT_OUTSIDE_MODULE_ );
        return;
    }
    curr_module->append_port( port_ );

    // insert
    m_port_vec.push_back( port_ );
}
Exemple #4
0
sc_process_handle
sc_get_current_process_handle()
{
    return ( sc_is_running() ) ?
           sc_process_handle(sc_get_current_process_b()) :
           sc_get_last_created_process_handle();
}
Exemple #5
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;
}
//------------------------------------------------------------------------------
//"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);
    }
}
Exemple #7
0
//------------------------------------------------------------------------------
//"sc_set_stop_mode"
//
// This function sets the mode of operation when sc_stop() is called.
//     mode = SC_STOP_IMMEDIATE or SC_STOP_FINISH_DELTA.
//------------------------------------------------------------------------------
void sc_set_stop_mode(sc_stop_mode mode)
{
    if ( sc_is_running() )
    {
        SC_REPORT_WARNING(SC_ID_STOP_MODE_AFTER_START_,"");
    }
    else
    {
        switch ( mode )
        {
        case SC_STOP_IMMEDIATE:
        case SC_STOP_FINISH_DELTA:
            stop_mode = mode;
            break;
        default:
            break;
        }
    }
}
Exemple #8
0
void
sc_module::set_stack_size( std::size_t size )
{
    sc_process_handle  proc_h(
    	sc_is_running() ?
	sc_get_current_process_handle() :
	sc_get_last_created_process_handle()
    );
    sc_thread_handle thread_h;  // Current process as thread.


    thread_h = (sc_thread_handle)proc_h;
    if ( thread_h ) 
    {
	thread_h->set_stack_size( size );
    }
    else
    {
	SC_REPORT_WARNING( SC_ID_SET_STACK_SIZE_, 0 );
    }
}
void
sc_module_registry::insert( sc_module& module_ )
{
    if( sc_is_running() ) {
	SC_REPORT_ERROR( SC_ID_INSERT_MODULE_, "simulation running" );
    }

    if( m_simc->elaboration_done() ) {
       SC_REPORT_ERROR( SC_ID_INSERT_MODULE_, "elaboration done" );
    }

#ifdef DEBUG_SYSTEMC
    // check if module_ is already inserted
    for( int i = size() - 1; i >= 0; -- i ) {
	if( &module_ == m_module_vec[i] ) {
	    SC_REPORT_ERROR( SC_ID_INSERT_MODULE_, "already inserted" );
	}
    }
#endif

    // insert
    m_module_vec.push_back( &module_ );
}
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