Пример #1
0
void
sc_simcontext::initial_crunch( bool no_crunch )
{
    if ( no_crunch || m_runnable->is_empty() )
    {
        return;
    }
    m_runnable->toggle();

    // run the delta cycle loop

    crunch();
    if ( m_error )
    {
        return;
    }
    if ( m_something_to_trace )
    {
        trace_cycle( false );
    }
    // check for call(s) to sc_stop
    if ( m_forced_stop )
    {
        do_sc_stop_action();
    }
}
Пример #2
0
inline
void
sc_simcontext::cycle( const sc_time& t)
{
    sc_time next_event_time;

    m_in_simulator_control = true;
    m_runnable->toggle();
    crunch(); 
    trace_cycle( /* delta cycle? */ false );
    m_curr_time += t;
    next_event_time = next_time();
    if ( next_event_time != SC_ZERO_TIME && next_event_time <= m_curr_time) {
        SC_REPORT_WARNING(SC_ID_CYCLE_MISSES_EVENTS_, "");
    }
    m_in_simulator_control = false;
}
Пример #3
0
void
sc_simcontext::simulate( const sc_time& duration )
{
    initialize( true );

    if (sim_status() != SC_SIM_OK)
    {
        return;
    }

    sc_time non_overflow_time =
        sc_time(~sc_dt::UINT64_ZERO, false) - m_curr_time;
    if ( duration > non_overflow_time )
    {
        SC_REPORT_ERROR(SC_ID_SIMULATION_TIME_OVERFLOW_, "");
        return;
    }
    else if ( duration < SC_ZERO_TIME )
    {
        SC_REPORT_ERROR(SC_ID_NEGATIVE_SIMULATION_TIME_,"");
    }
    m_in_simulator_control = true;

    sc_time until_t = m_curr_time + duration;

    m_until_event->cancel();  // to be on the safe side
    m_until_event->notify_internal( duration );

    sc_time t;

    // IF DURATION WAS ZERO WE ONLY CRUNCH:
    //
    // We duplicate the code so that we don't add the overhead of the
    // check to each loop in the do below.
    if ( duration == SC_ZERO_TIME )
    {
        m_runnable->toggle();
        crunch( true );
        if ( m_error ) return;
        if ( m_something_to_trace ) trace_cycle( /* delta cycle? */ false );
        if ( m_forced_stop )
            do_sc_stop_action();
        return;
    }


    // NON-ZERO DURATION: EXECUTE UP TO THAT TIME:
    do
    {
        m_runnable->toggle();

        crunch();
        if ( m_error )
        {
            m_in_simulator_control = false;
            return;
        }
        if ( m_something_to_trace )
        {
            trace_cycle( false );
        }
        // check for call(s) to sc_stop
        if ( m_forced_stop )
        {
            do_sc_stop_action();
            return;
        }

        do
        {
            t = next_time();

            // PROCESS TIMED NOTIFICATIONS

            do
            {
                sc_event_timed* et = m_timed_events->extract_top();
                sc_event* e = et->event();
                delete et;
                if ( e != 0 )
                {
                    e->trigger();
                }
            }
            while ( m_timed_events->size() &&
                    m_timed_events->top()->notify_time() == t );

        }
        while ( m_runnable->is_empty() && t != until_t );
        if ( t > m_curr_time ) m_curr_time = t;

    }
    while ( t != until_t );
    m_in_simulator_control = false;
}
Пример #4
0
inline void
sc_simcontext::crunch( bool once )
{
#ifdef DEBUG_SYSTEMC
    int num_deltas = 0;  // number of delta cycles
#endif

    while ( true )
    {

        // EVALUATE PHASE

        m_execution_phase = phase_evaluate;
        while ( true )
        {


            // execute method processes

            sc_method_handle method_h = pop_runnable_method();
            while ( method_h != 0 )
            {
                try
                {
                    method_h->semantics();
                }
                catch ( const sc_report& ex )
                {
                    ::std::cout << "\n" << ex.what() << ::std::endl;
                    m_error = true;
                    return;
                }
                method_h = pop_runnable_method();
            }

            // execute (c)thread processes

            sc_thread_handle thread_h = pop_runnable_thread();
            while ( thread_h != 0 )
            {
                if ( thread_h->ready_to_run() ) break;
                thread_h = pop_runnable_thread();
            }
            if ( thread_h != 0 )
            {
                m_cor_pkg->yield( thread_h->m_cor_p );
            }
            if ( m_error )
            {
                return;
            }

            // check for call(s) to sc_stop
            if ( m_forced_stop )
            {
                if ( stop_mode == SC_STOP_IMMEDIATE ) return;
            }

            if ( m_runnable->is_empty() )
            {
                // no more runnable processes
                break;
            }
            m_runnable->toggle();
        }

        // UPDATE PHASE
        //
        // The delta count must be updated first so that event_occurred()
        // will work.

        m_execution_phase = phase_update;
        m_delta_count ++;
        m_prim_channel_registry->perform_update();
        m_execution_phase = phase_notify;

        if ( m_something_to_trace )
        {
            trace_cycle( /* delta cycle? */ true );
        }

        // m_delta_count ++;

        // check for call(s) to sc_stop
        if ( m_forced_stop )
        {
            break;
        }

#ifdef DEBUG_SYSTEMC
        // check for possible infinite loops
        if ( ++ num_deltas > SC_MAX_NUM_DELTA_CYCLES )
        {
            ::std::cerr << "SystemC warning: "
                        << "the number of delta cycles exceeds the limit of "
                        << SC_MAX_NUM_DELTA_CYCLES
                        << ", defined in sc_constants.h.\n"
                        << "This is a possible sign of an infinite loop.\n"
                        << "Increase the limit if this warning is invalid.\n";
            break;
        }
#endif

        // PROCESS DELTA NOTIFICATIONS:

        int size = m_delta_events.size();
        if ( size != 0 )
        {
            sc_event** l_events = &m_delta_events[0];
            int i = size - 1;
            do
            {
                l_events[i]->trigger();
            }
            while ( -- i >= 0 );
            m_delta_events.resize(0);
        }

        if ( m_runnable->is_empty() )
        {
            // no more runnable processes
            break;
        }

        // IF ONLY DOING ONE CYCLE, WE ARE DONE. OTHERWISE GET NEW CALLBACKS

        if ( once ) break;

        m_runnable->toggle();
    }
}