Thanks,

// Naderan *Mahmood;

From: Picorel Javier <[email protected]>
To: "[email protected]" <[email protected]>
Cc: "[email protected]" <[email protected]>
Sent: Monday, May 23, 2011 12:38 AM
Subject: RE: doCycle()



Just a quick correction. Not all the components need to include a drive() 
function. You might find some components that do not have (need) a drive 
function. FYI.

Javier


From: Picorel Javier [[email protected]]
Sent: 22 May 2011 17:36
To: [email protected]
Cc: [email protected]
Subject: RE: doCycle()


Dear Mahmood,


All the components in Flexus need to have a drive() function no matter what 
type of simulation you run. In trace
simulations, this function is called every 1000 cycles (1000 instructions 
because in trace IPC is 1.0 and there are no stalls) and most of the time it 
just updates the counters for statistics. In timing simulations each drive 
function in a timing component
is called every cycle. In timing besides statistical reasons we use them to 
model the component itself. At the end of each wiring.cpp file we need to 
specify the drive function of each component in a particular order. In trace 
simulations the order does not
matter but in some cases you will need to define a precise order for 
cycle-accurate simulations. In the simulator wiring file you may have something 
like this:  

#include FLEXUS_BEGIN_DRIVE_ORDER_SECTION()

DRIVE( theMagicBreak, TickDrive )
, DRIVE( theL1D, UpdateStatsDrive )
, DRIVE( theL1I, UpdateStatsDrive )
, DRIVE( theL2, UpdateStatsDrive )

#include FLEXUS_END_DRIVE_ORDER_SECTION()

In FLEXUS/core/simulator_layout.hpp you will find what 
FLEXUS_BEGIN_DRIVE_ORDER_SECTION() and FLEXUS_END_DRIVE_ORDER_SECTION() do...

#define FLEXUS_BEGIN_DRIVE_ORDER_SECTION()                        
<core/aux_/layout/begin_drive_section.hpp>
#define FLEXUS_END_DRIVE_ORDER_SECTION()                          
<core/aux_/layout/end_drive_section.hpp>

In begin_drive_section.hpp file you will find...

#define DRIVE( Handle, Drive )  \
 Flexus::Core::DriveHandle< Handle, Handle::iface::Drive >

In FLEXUS/core/component.hpp you will see what DriveHandle does but basically 
it saves component information and the drive function of the component. In 
end_drive_section.hpp it creates a list of all the drive
functions and components in the same order that the drive functions were 
defined in the wiring.cpp simulation file.    
        Drive< drive_list > drive;

        The class Drive appears in FLEXUS/core/drive.hpp...

        template < class OrderedDriveHandleList >

class Drive : public DriveBase {
  virtual void doCycle() {
    //Through the magic of template expansion and static dispatch, this calls 
every Drive's
    //do_cycle() method in the order specified in OrderedDriveHandleList.
    FLEXUS_PROFILE_N("Drive::doCycle");
    aux_::do_cycle<OrderedDriveHandleList>::doCycle();
  }

};

FLEXUS will call Drive.doCycle() function every cycle. As it was instantiated 
with the drive list it will execute  
aux_::do_cycle<OrderedDriveHandleList>::doCycle() with the list we want. Now we 
are in the part
that you want:

template <int32_t N, class DriveHandleIter>
struct do_cycle_step {
  static void doCycle() {
    {
      FLEXUS_PROFILE_N( mpl::deref<DriveHandleIter>::type::drive::name() );
      for (index_t i = 0; i < mpl::deref<DriveHandleIter>::type::width(); i++) {
        mpl::deref<DriveHandleIter>::type::getReference(i).drive( typename 
mpl::deref<DriveHandleIter>::type::drive () );
      }
    }
    do_cycle_step < N - 1, typename mpl::next<DriveHandleIter>::type 
>::doCycle();
  }
};

template <class DriveHandles>
struct do_cycle {
  static void doCycle() {
    do_cycle_step< mpl::size<DriveHandles>::value, typename 
mpl::begin<DriveHandles>::type>::doCycle();
  }
};
}

Basically it will do this:

1) The bottom doCycle() will be executed and it will call the top doCycle(). It 
will use some boost library to access to the information of each element of the 
list. As some components are not a single unit and they scale to system wide 
(Check the wiring.cpp
file of the simulator. L1D caches and L1I are usually something instantiated 
like that FLEXUS_INSTANTIATE_COMPONENT_ARRAY( ...): ) your width is larger than 
one so you want to iterate and call the drive function among all the 
replications of the same component. Basically, the part I have just explained 
to you is done by the following code:

  for (i=0; component_X.width(); i++){
    component_X[i].drive();
  }


2) Recursively you execute the same function (do_cycle) by the following code 
but this time with the next component in the drive list:

          do_cycle(){  
           for ...  

  do_cycle(component_X -> NextComponent);
}

3) Same behavior continues until all the components and their replications 
execute their drive function.

I hope my response is helpful . You can grep the code and see the code path in 
more details.

Regards,
Javier          

Reply via email to