//------------------------------------------------------------------------------
//"sc_object::detach"
//
// This method detaches this object instance from the object hierarchy.
// It is called in two places: ~sc_object() and sc_process_b::kill_process().
//------------------------------------------------------------------------------
void sc_object::detach()
{
    if (m_simc) {

        // REMOVE OBJECT FROM THE OBJECT MANAGER:

        sc_object_manager* object_manager = m_simc->get_object_manager();
        object_manager->remove_object(m_name);

		// REMOVE OBJECT FROM PARENT'S LIST OF OBJECTS:

        if ( m_parent )
	    m_parent->remove_child_object( this );
	else
	    m_simc->remove_child_object( this );

        // ORPHAN THIS OBJECT'S CHILDREN:

#if 0 // ####
	    ::std::<sc_object*> children_p = &get_child_objects();
		int                 child_n = children_p->size();
		sc_object*          parent_p;

		for ( int child_i = 0; child_i < child_n; child_i++ )
		{
			(*children_p)[child_i]->m_parent = 0;
		}
#endif

    }
}
Esempio n. 2
0
//------------------------------------------------------------------------------
//"sc_method_process::enable_process"
//
// This method enables the execution of this process, and if requested, its
// descendants. If the process was suspended and has a resumption pending it 
// will be dispatched in the next delta cycle. Otherwise the state will be
// adjusted to indicate it is no longer suspended, but no immediate execution
// will occur.
//------------------------------------------------------------------------------
void sc_method_process::enable_process(
    sc_descendant_inclusion_info descendants )
{

    // IF NEEDED PROPOGATE THE RESUME 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->enable_process(descendants);
        }
    }

    // ENABLE THIS OBJECT INSTANCE:
    //
    // If it was disabled and ready to run then put it on the run queue.

    m_state = m_state & ~ps_bit_disabled;
    if ( m_state == ps_bit_ready_to_run )
    {
        m_state = ps_normal;
	if ( next_runnable() == 0 )
	    simcontext()->push_runnable_method(this);
    }
}
//------------------------------------------------------------------------------
//"sc_process_b::reset_process"
//
// This inline method changes the reset state of this object instance and
// conditionally its descendants.
//
// Notes:
//   (1) It is called for sync_reset_on() and sync_reset_off(). It is not used
//       for signal sensitive resets, though all reset flow ends up in
//       reset_changed().
//
// Arguments:
//     rt = source of the reset:
//            * reset_asynchronous     - sc_process_handle::reset()
//            * reset_synchronous_off  - sc_process_handle::sync_reset_off()
//            * reset_synchronous_on   - sc_process_handle::sync_reset_on()
//     descendants = indication of how to process descendants.
//------------------------------------------------------------------------------
void sc_process_b::reset_process( reset_type rt,
                                  sc_descendant_inclusion_info descendants )
{

    // PROCESS THIS OBJECT INSTANCE'S DESCENDANTS IF REQUESTED TO:

    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->reset_process(rt, descendants);
        }
    }

    // PROCESS THIS OBJECT INSTANCE:

    switch (rt)
    {
    // One-shot asynchronous reset: remove dynamic sensitivity and throw:
    //
    // If this is an sc_method only throw if it is active.

    case reset_asynchronous:
        if ( sc_get_status() != SC_RUNNING )
        {
            report_error(SC_ID_RESET_PROCESS_WHILE_NOT_RUNNING_);
        }
        else
        {
            remove_dynamic_events();
            throw_reset(true);
        }
        break;

    // Turn on sticky synchronous reset: use standard reset mechanism.

    case reset_synchronous_on:
        if ( m_sticky_reset == false )
        {
            m_sticky_reset = true;
            reset_changed( false, true );
        }
        break;

    // Turn off sticky synchronous reset: use standard reset mechanism.

    default:
        if ( m_sticky_reset == true )
        {
            m_sticky_reset = false;
            reset_changed( false, false );
        }
        break;
    }
}
Esempio n. 4
0
//------------------------------------------------------------------------------
//"sc_method_process::kill_process"
//
// This method removes throws a kill for this object instance. It calls the
// sc_process_b::kill_process() method to perform low level clean up. 
//------------------------------------------------------------------------------
void sc_method_process::kill_process(sc_descendant_inclusion_info descendants)
{

    // IF THE SIMULATION HAS NOT BEEN INITIALIZED YET THAT IS AN ERROR:

    if ( sc_get_status() == SC_ELABORATION )
    {
        report_error( SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_ );
    }

    // IF NEEDED, PROPOGATE THE KILL 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->kill_process(descendants);
        }
    }

    // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE
    // IGNORE THE KILL:

    if ( m_unwinding )
    {
        SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() );
        return;
    }

    if ( m_state & ps_bit_zombie )
        return;


    // REMOVE OUR PROCESS FROM EVENTS, ETC., AND IF ITS THE ACTIVE PROCESS
    // THROW ITS KILL. 
    // 
    // Note we set the throw status to kill regardless if we throw or not.
    // That lets check_for_throws stumble across it if we were in the call
    // chain when the kill call occurred.

    if ( next_runnable() != 0 )
        simcontext()->remove_runnable_method( this );
    disconnect_process();

    m_throw_status = THROW_KILL; 
    if ( sc_get_current_process_b() == this )
    {
        throw sc_unwind_exception( this, false );
    }
}
// +----------------------------------------------------------------------------
// |"sc_object::orphan_child_objects"
// | 
// | This method moves the children of this object instance to be children
// | of the simulator.
// +----------------------------------------------------------------------------
void sc_object::orphan_child_objects()
{
    std::vector< sc_object* > const & children = get_child_objects();

    std::vector< sc_object* >::const_iterator
            it  = children.begin(), end = children.end();

    for( ; it != end; ++it  )
    {
        (*it)->m_parent = NULL;
        simcontext()->add_child_object(*it);
    }
}
Esempio n. 6
0
//------------------------------------------------------------------------------
//"sc_method_process::throw_user"
//
// This virtual method is invoked when a user exception is to be thrown.
// If requested it will also throw the exception to the children of this 
// object instance. Since this is a method no throw will occur for this
// object instance. The children will be awakened from youngest child to
// eldest.
//     helper_p    -> object to use to throw the exception.
//     descendants =  indicator of whether this process' children should also
//                    be suspended
//------------------------------------------------------------------------------
void sc_method_process::throw_user( const sc_throw_it_helper& helper,
    sc_descendant_inclusion_info descendants )
{     

    // IF THE SIMULATION IS NOT ACTUALLY RUNNING THIS IS AN ERROR:

    if (  sc_get_status() != SC_RUNNING )
    {
        report_error( SC_ID_THROW_IT_WHILE_NOT_RUNNING_ );
    }

    // IF NEEDED PROPOGATE THE THROW 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 ) 
	    {
	        DEBUG_MSG(DEBUG_NAME,child_p,"about to throw user on");
	        child_p->throw_user(helper, descendants);
	    }
        }
    }

#if 0 // shouldn't we throw, if we're currently running?

    if ( sc_get_current_process_b() == (sc_process_b*)this )
    {
        remove_dynamic_events();
        m_throw_status = THROW_USER;
        if ( m_throw_helper_p != 0 ) delete m_throw_helper_p;
        m_throw_helper_p = helper.clone();
        m_throw_helper_p->throw_it();
    }

    // throw_it HAS NO EFFECT ON A METHOD, ISSUE A WARNING:

    else

#endif
   {
        SC_REPORT_WARNING( SC_ID_THROW_IT_IGNORED_, name() );
   }


}
Esempio n. 7
0
//------------------------------------------------------------------------------
//"sc_method_process::suspend_process"
//
// This virtual method suspends this process and its children if requested to.
//     descendants = indicator of whether this process' children should also
//                   be suspended
//------------------------------------------------------------------------------
void sc_method_process::suspend_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->suspend_process(descendants);
        }
    }

    // CORNER CASE CHECKS, THE FOLLOWING ARE ERRORS:
    //   (a) if this method has a reset_signal_is specification 
    //   (b) if this method is in synchronous reset

    if ( !sc_allow_process_control_corners && m_has_reset_signal )
    {
	report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_,
		     "attempt to suspend a method that has a reset signal");
    }
    else if ( !sc_allow_process_control_corners && m_sticky_reset )
    {
	report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_,
		     "attempt to suspend a method in synchronous reset");
    }

    // SUSPEND OUR OBJECT INSTANCE:
    //
    // (1) If we are on the runnable queue then set suspended and ready_to_run,
    //     and remove ourselves from the run queue.
    // (2) If this is a self-suspension then a resume should cause immediate
    //     scheduling of the process.

    m_state = m_state | ps_bit_suspended;
    if ( next_runnable() != 0 ) 
    {
	m_state = m_state | ps_bit_ready_to_run;
	simcontext()->remove_runnable_method( this );
    }
    if ( sc_get_current_process_b() == DCAST<sc_process_b*>(this)  )
    {
	m_state = m_state | ps_bit_ready_to_run;
    }
}
Esempio n. 8
0
//------------------------------------------------------------------------------
//"sc_method_process::resume_process"
//
// This method resumes the execution of this process, and if requested, its
// descendants. If the process was suspended and has a resumption pending it 
// will be dispatched in the next delta cycle. Otherwise the state will be
// adjusted to indicate it is no longer suspended, but no immediate execution
// will occur.
//------------------------------------------------------------------------------
void sc_method_process::resume_process(
    sc_descendant_inclusion_info descendants )
{

    // IF NEEDED PROPOGATE THE RESUME 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->resume_process(descendants);
        }
    }


    // BY DEFAULT THE CORNER CASE IS AN ERROR:

    if ( !sc_allow_process_control_corners && (m_state & ps_bit_disabled) &&
         (m_state & ps_bit_suspended) )
    {
	m_state = m_state & ~ps_bit_suspended;
        report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_, 
	              "call to resume() on a disabled suspended method");
    }

    // CLEAR THE SUSPENDED BIT:

    m_state = m_state & ~ps_bit_suspended;

    // RESUME OBJECT INSTANCE:
    //
    // If this is not a self-resume and the method is ready to run then
    // put it on the runnable queue.

    if ( m_state & ps_bit_ready_to_run )
    {
	m_state = m_state & ~ps_bit_ready_to_run;
	if ( next_runnable() == 0 && 
	   ( sc_get_current_process_b() != DCAST<sc_process_b*>(this) ) )
        {
	    simcontext()->push_runnable_method(this);
	    remove_dynamic_events();  
	}
    }
}
Esempio n. 9
0
//------------------------------------------------------------------------------
// Function: get_children
//  Returns vector of pointers to children
//
// Returns:
//  vec - vector of pointers to children
//------------------------------------------------------------------------------
std::vector<uvm_component*> uvm_component::get_children() {
  std::vector<sc_object*> child_vec;
  std::vector<uvm_component*> child_comp_vec;
  uvm_component* comp = NULL;
  child_vec = get_child_objects();


  for (int i = 0; i < child_vec.size(); i++)
  {
    comp = DCAST<uvm_component*>(child_vec[i]);
    if (comp != NULL)
      child_comp_vec.push_back(comp);
  }

  return child_comp_vec;
}
Esempio n. 10
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);
    }
}