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