Services and Modeling for Embedded Software Development
Embecosm divider strip
Prev  Next

9.4.3.  Or1ksimDecoupSC Module Class Implementation

The constructor passes its arguments to the base class, Or1ksimSyncSC. The quantum keeper for the ISS thread is then initialized with the system global quantum and the local quantum calculated and local time offset zeroed with a call to reset.

  tgq = &(tlm::tlm_global_quantum::instance());

  issQk.set_global_quantum( refTgq.get() );
  issQk.reset();
	  
[Note]Note

The global quantum accessor function, instance returns a reference to the global quantum. We convert it to a pointer, since C++ does not allow initialization of a reference instance variable in the constructor.

The main thread function, run is reimplemented to ensure that the ISS simulation does not run past the end of the current quantum. Instead of running for ever (or1ksim_run( -1.0 );), the ISS is run for the local time quantum, less the local time offset. This means the ISS will return exactly at the point when it should need to synchronize again.

The body of the program is a perpetual loop, which calculates the time left until the next global quantum then calls the ISS for that period.

  while( true ) {
    sc_core::sc_time  timeLeft =
      tgq->compute_local_quantum() - issQk.get_local_time();
	  

On return, or1ksim_get_time_period is used to find out how much computation has actually been carried out and advance local time accordingly. This may be different to the duration requested, since an upcall may set a new time point and adjusted the duration. A new time point is immediately set ready for the next loop.

    (void)or1ksim_run( timeLeft.to_seconds());

    issQk.inc( sc_core::sc_time( or1ksim_get_time_period(), sc_core::SC_SEC ));
    or1ksim_set_time_point();
	  

If the local time offset has reached the end of the global quantum, the thread synchronizes. This replaces the call to wait in the synchronized version of the model (Chapter 8).

    if( issQk.need_sync() ) {
      issQk.sync();
	  

The transport function, doTrans has the same structure as the synchronous version in the base class. However instead of calling wait to delay calculation, it updates the local time offset. The time offset is advanced for the ISS simulation since the last time point and a new time point is set.

  issQk.inc( sc_core::sc_time( or1ksim_get_time_period(), sc_core::SC_SEC ));
  or1ksim_set_time_point();
	  

The delay argument to the blocking transport is the local time offset. This may be increased by the target (to model read/write delay), and the new value becomes the local time offset on return.

  sc_core::sc_time  delay = issQk.get_local_time();
  dataBus->b_transport( trans, delay );
  issQk.set( delay );
	  

At this point synchronization could be required—the read/write delay could have pushed the local time offset past the global quantum.

  if( issQk.need_sync() ) {
    issQk.sync();
  }
	  

The duration remaining for the ISS simulation is reset in the same way as in the main thread to be the local quantum less the local time offset. On return the ISS will continue for that period.

  sc_core::sc_time  timeLeft      =
    tgq->compute_local_quantum() - issQk.get_local_time();

  or1ksim_reset_duration ( timeLeft.to_seconds() );
	  

The implementation of the Or1ksim ISS wrapper module class with decoupled timing, Or1ksimDecoupSC may be found in sys-models/decoup-soc/Or1ksimDecoupSC.cpp in the distribution.

Embecosm divider strip