You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
757 lines
28 KiB
757 lines
28 KiB
/*
|
|
* Copyright 2002-2019 Intel Corporation.
|
|
*
|
|
* This software is provided to you as Sample Source Code as defined in the accompanying
|
|
* End User License Agreement for the Intel(R) Software Development Products ("Agreement")
|
|
* section 1.L.
|
|
*
|
|
* This software and the related documents are provided as is, with no express or implied
|
|
* warranties, other than those that are expressly stated in the License.
|
|
*/
|
|
|
|
#ifndef REGIONS_CONTROL_H
|
|
#define REGIONS_CONTROL_H
|
|
|
|
/*! @defgroup CONTROLLER_REGIONS
|
|
@ingroup CONTROLLER
|
|
Controller for "regions" that are specified using instruction counts.
|
|
Use -regions:in regions.csv
|
|
|
|
regions.csv files will be an alternative to PinPoints files.
|
|
The main goal is to separate warm-up specification from region description.
|
|
Another major goal is the simplicity of implementation.
|
|
|
|
Regions are specified using a text file with the records of the form:
|
|
comment,thread-id,region-id,simulation-region-start-icount,
|
|
simulation-region-end-icount,region-weight
|
|
|
|
[ fields after the first six are ignored, so are lines beginning with '#' ]
|
|
|
|
Knobs:
|
|
------
|
|
-regions:in foo.csv : input file
|
|
-regions:warmup N : use N instructions for warmup
|
|
-regions:prolog N : use N instructions for prolog
|
|
-regions:epilog N : use N instructions for epilog
|
|
-regions:verbose : for getting informed about regions/events
|
|
-regions:overlap-ok : allow overlap among multiple regions.
|
|
-regions:out : Output file for regions skipped due to overlap
|
|
(if overlap is not ok)
|
|
The idea is to feed this file with "-regions:in" to the next
|
|
invocation of the tool to process skipped regions.
|
|
* If this knob is specified but no regions are skipped, the output
|
|
file will be empty.
|
|
|
|
Region working with the controller:
|
|
-----------------
|
|
1. IREGION class reads region data from file.
|
|
2. Region events are sorted according to icount and type.
|
|
3. Each region event is translated into controller event string like: start:icount:100:tid0
|
|
4. The events will be triggered by the controller ICOUNT alarms mechanism.
|
|
5. The controller will notify IREGION class of the events.
|
|
6. Modify driver not to allow IREGION events and controller events.
|
|
|
|
Region processing:
|
|
-----------------
|
|
* The overall regions picture looks as follows:
|
|
WARMUP--PROLOG--(SIM)REGION--EPILOG
|
|
|
|
each sub-region has a start and end event. So there are eight
|
|
events possible (some coinciding e.g. warmup-end and prolog-start)
|
|
EVENT_WARMUP_START : Beginning of warmup region
|
|
EVENT_WARMUP_STOP : End of warmup region
|
|
EVENT_PROLOG_START : Beginning of prolog region
|
|
EVENT_PROLOG_STOP : End of prolog region
|
|
EVENT_START : Beginning of interval
|
|
EVENT_STOP : End of interval
|
|
EVENT_EPILOG_START : Beginning of epilog region
|
|
EVENT_EPILOG_STOP : End of epilog region
|
|
|
|
* Using the warmup/prolog/epilog knobs provided to the controller,
|
|
the region boundaries for the four sub-regions above are computed for
|
|
each record in the regions.csv file.
|
|
|
|
* If overlap is not allowed (-regions:overlap-ok is zero), any record
|
|
that has any of its 4 sub-regions overapping with any sub-region of
|
|
previously processed records will be ignored. If -regions:out knob
|
|
is specified, the skipped records will be output to a file. The
|
|
idea is to feed the skipped region records to another invocation of the
|
|
tool involved iteratively till all the records are processed.
|
|
|
|
* As regions are processed, an event list containing tuples of the form
|
|
(icount, event-type, region-pointer) is created per thread. There is
|
|
one tuple for each of the possible 8 events for four sub-regions.
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include <sstream>
|
|
#include <string.h>
|
|
#include <cctype>
|
|
#include "region_utils.H"
|
|
|
|
using namespace std;
|
|
namespace CONTROLLER{
|
|
class IREGION
|
|
{
|
|
private:
|
|
friend class CONTROL_IREGIONS; // allow it to set private fields
|
|
UINT64 _icountStart; // read in
|
|
UINT64 _icountEnd; // read in
|
|
double _weight; // read in
|
|
string _comment; // read in
|
|
UINT32 _rid; // read in
|
|
UINT32 _tid; // read in
|
|
size_t _rno; // assigned
|
|
UINT64 _warmup_length; // computed + assigned
|
|
UINT64 _prolog_length; // computed + assigned
|
|
UINT64 _epilog_length; // computed + assigned
|
|
UINT32 _weightTimesHundredThousand; // computed + assigned
|
|
// Convert input weight ('double' 0--1) to UINT32 to avoid
|
|
// floating point code in the pintools.
|
|
public:
|
|
IREGION()
|
|
{
|
|
_icountStart = 0;
|
|
_icountEnd = 0;
|
|
_weight = 0;
|
|
_rid = 0;
|
|
_tid = 0 ;
|
|
_rno = 0;
|
|
_warmup_length = 0;
|
|
_prolog_length = 0;
|
|
_epilog_length = 0;
|
|
_weightTimesHundredThousand = 0;
|
|
}
|
|
string GetComment() const { return _comment;}
|
|
UINT32 GetRegionId() const { return _rid;}
|
|
UINT64 GetRegionStartICount() const { return _icountStart; }
|
|
UINT64 GetRegionEndICount() const { return _icountEnd; }
|
|
UINT64 GetWarmupLength() const { return _warmup_length; }
|
|
UINT64 GetPrologLength() const { return _prolog_length; }
|
|
UINT64 GetRegionLength() const { return _icountEnd - _icountStart; }
|
|
UINT64 GetEpilogLength() const { return _epilog_length;}
|
|
UINT32 GetWeightTimesHundredThousand() const {
|
|
return _weightTimesHundredThousand;}
|
|
VOID SetICountEnd(UINT64 icountEnd) {_icountEnd = icountEnd;}
|
|
VOID SetEpilogLength(UINT64 epilog_length) {_epilog_length = epilog_length;}
|
|
};
|
|
|
|
class IEVENT
|
|
{
|
|
public:
|
|
IEVENT()
|
|
{
|
|
icount = 0;
|
|
type = EVENT_INVALID;
|
|
iregion = (class IREGION *) NULL;
|
|
}
|
|
static BOOL EventLessThan (const IEVENT & a, const IEVENT & b)
|
|
{
|
|
BOOL retval = false;
|
|
if(a.icount == b.icount)
|
|
{
|
|
if (b.type == EVENT_WARMUP_START)
|
|
{
|
|
if ((a.type == EVENT_WARMUP_START))
|
|
{
|
|
retval = true;
|
|
}
|
|
}
|
|
else if (b.type == EVENT_WARMUP_STOP)
|
|
{
|
|
if ((a.type == EVENT_WARMUP_START) ||
|
|
(a.type == EVENT_WARMUP_STOP))
|
|
{
|
|
retval = true;
|
|
}
|
|
}
|
|
else if (b.type == EVENT_PROLOG_START)
|
|
{
|
|
if ((a.type == EVENT_WARMUP_START) ||
|
|
(a.type == EVENT_WARMUP_STOP) ||
|
|
(a.type == EVENT_PROLOG_START))
|
|
{
|
|
retval = true;
|
|
}
|
|
}
|
|
else if (b.type == EVENT_PROLOG_STOP)
|
|
{
|
|
if ((a.type == EVENT_WARMUP_START) ||
|
|
(a.type == EVENT_WARMUP_STOP) ||
|
|
(a.type == EVENT_PROLOG_START) ||
|
|
(a.type == EVENT_PROLOG_STOP))
|
|
{
|
|
retval = true;
|
|
}
|
|
}
|
|
else if (b.type == EVENT_START)
|
|
{
|
|
retval = true;
|
|
if ((a.type == EVENT_STOP) ||
|
|
(a.type == EVENT_EPILOG_START) ||
|
|
(a.type == EVENT_EPILOG_STOP))
|
|
{
|
|
retval = false;
|
|
}
|
|
}
|
|
else if (b.type == EVENT_STOP)
|
|
{
|
|
retval = true;
|
|
if ((a.type == EVENT_EPILOG_START) ||
|
|
(a.type == EVENT_EPILOG_STOP))
|
|
{
|
|
retval = false;
|
|
}
|
|
}
|
|
else if (b.type == EVENT_EPILOG_START)
|
|
{
|
|
retval = true;
|
|
if ((a.type == EVENT_EPILOG_STOP))
|
|
{
|
|
retval = false;
|
|
}
|
|
}
|
|
else if (b.type == EVENT_EPILOG_STOP)
|
|
{
|
|
retval = true;
|
|
}
|
|
else{
|
|
retval = true;
|
|
}
|
|
return retval;
|
|
}
|
|
return a.icount < b.icount;
|
|
}
|
|
|
|
static const CHAR * EventToString(EVENT_TYPE type)
|
|
{
|
|
switch(type)
|
|
{
|
|
case EVENT_THREADID : return "control-threadid";
|
|
case EVENT_START : return "region-start";
|
|
case EVENT_STOP : return "region-end";
|
|
case EVENT_WARMUP_START : return "warmup-start";
|
|
case EVENT_WARMUP_STOP : return "warmup-end";
|
|
case EVENT_PROLOG_START : return "prolog-start";
|
|
case EVENT_PROLOG_STOP : return "prolog-end";
|
|
case EVENT_EPILOG_START : return "epilog-start";
|
|
case EVENT_EPILOG_STOP : return "epilog-end";
|
|
default: return "invalid";
|
|
}
|
|
}
|
|
|
|
private:
|
|
friend class CONTROL_IREGIONS; // allow it to set private fields
|
|
UINT64 icount;
|
|
EVENT_TYPE type;
|
|
class IREGION * iregion;
|
|
};
|
|
|
|
typedef vector<IREGION> IREGION_VECTOR;
|
|
typedef vector<IEVENT> IEVENT_VECTOR;
|
|
|
|
/*! @ingroup CONTROLLER_IREGIONS
|
|
*/
|
|
|
|
class CONTROL_IREGIONS
|
|
{
|
|
private:
|
|
static const UINT32 BUFSIZE=2000;
|
|
|
|
public:
|
|
CONTROL_IREGIONS(CONTROL_ARGS & control_args,
|
|
CONTROL_MANAGER* cm)
|
|
: _control_args(control_args),
|
|
_rFileKnob(KNOB_MODE_WRITEONCE,
|
|
control_args.get_knob_family(),
|
|
"regions:in",
|
|
"",
|
|
"Regions file",
|
|
control_args.get_prefix()),
|
|
_rWarmupKnob(KNOB_MODE_WRITEONCE,
|
|
control_args.get_knob_family(),
|
|
"regions:warmup",
|
|
"0",
|
|
"# of instructions in the warm-up region",
|
|
control_args.get_prefix()),
|
|
_rPrologKnob(KNOB_MODE_WRITEONCE,
|
|
control_args.get_knob_family(),
|
|
"regions:prolog",
|
|
"0",
|
|
"# of instructions in the prolog region",
|
|
control_args.get_prefix()),
|
|
_rEpilogKnob(KNOB_MODE_WRITEONCE,
|
|
control_args.get_knob_family(),
|
|
"regions:epilog",
|
|
"0",
|
|
"# of instructions in the epilog region",
|
|
control_args.get_prefix()),
|
|
_rVerboseKnob(KNOB_MODE_WRITEONCE,
|
|
control_args.get_knob_family(),
|
|
"regions:verbose",
|
|
"0",
|
|
"Print information about regions/events ",
|
|
control_args.get_prefix()),
|
|
_rOverlapOkKnob(KNOB_MODE_WRITEONCE,
|
|
control_args.get_knob_family(),
|
|
"regions:overlap-ok",
|
|
"0",
|
|
"Allow overlap in regions.",
|
|
control_args.get_prefix()),
|
|
_rOutFileKnob(KNOB_MODE_WRITEONCE,
|
|
control_args.get_knob_family(),
|
|
"regions:out",
|
|
"",
|
|
"Output file containing regions skipped due to overlap",
|
|
control_args.get_prefix())
|
|
{
|
|
_cm = cm;
|
|
_valid = true;
|
|
_maxThreads = PIN_MAX_THREADS;
|
|
_regions = new IREGION_VECTOR[_maxThreads];
|
|
_events = new IEVENT_VECTOR[_maxThreads];
|
|
_xcount = 0;
|
|
_last_triggered_region = new IREGION * [_maxThreads];
|
|
memset(_last_triggered_region , 0,
|
|
sizeof(_last_triggered_region[0]) * _maxThreads);
|
|
_passContext = FALSE;
|
|
_active = false;
|
|
}
|
|
|
|
/*! @ingroup CONTROLLER_IREGIONS
|
|
Activate the controller if the -regions knob is provided
|
|
@return 1 if controller can start an interval, otherwise 0
|
|
*/
|
|
INT32 Activate(BOOL passContext, CHAIN_EVENT_VECTOR ** regionControlChains)
|
|
{
|
|
if (strcmp(_rFileKnob.Value().c_str(),"") == 0)
|
|
{
|
|
*regionControlChains = NULL;
|
|
return 0;
|
|
}
|
|
_passContext = passContext;
|
|
_active = true;
|
|
|
|
if (strcmp(_rOutFileKnob.Value().c_str(),"") != 0)
|
|
{
|
|
xfile.open(_rOutFileKnob.Value().c_str());
|
|
if (!xfile.is_open())
|
|
{
|
|
cerr << "Could not open output file " <<
|
|
_rOutFileKnob.Value().c_str() << endl;
|
|
PIN_ExitApplication(-1);
|
|
}
|
|
}
|
|
|
|
ReadRegionsFile();
|
|
|
|
ProcessRegions();
|
|
|
|
if(_rVerboseKnob) PrintRegions();
|
|
|
|
ProcessEvents();
|
|
|
|
if(_rVerboseKnob) PrintEvents();
|
|
|
|
// Copy region controller events
|
|
*regionControlChains = &_regionControlChains;
|
|
|
|
// Set Region name callback
|
|
_cm->SetRegionInfoCallback(CONTROL_IREGIONS::RegionInfoCallback, this);
|
|
|
|
return 1;
|
|
}
|
|
bool IsActive() const { return _active; };
|
|
IREGION * LastTriggeredRegion(THREADID tid) const {
|
|
return _last_triggered_region[tid];}
|
|
|
|
// Region name callback
|
|
static CONTROL_REGION_INFO RegionInfoCallback(THREADID tid, VOID * region_info_param) {
|
|
CONTROL_REGION_INFO region_info;
|
|
CONTROL_IREGIONS * ci = (CONTROL_IREGIONS *)region_info_param;
|
|
IREGION * curr_region = ci->LastTriggeredRegion(tid);
|
|
|
|
// Build the region name
|
|
string weight_string = REGION_UTILS::WeightToString(curr_region->GetWeightTimesHundredThousand());
|
|
region_info.regionName = "_t" + decstr(tid) +
|
|
"r" + decstr(curr_region->GetRegionId()) +
|
|
"_warmup" + decstr(curr_region->GetWarmupLength()) +
|
|
"_prolog" + decstr(curr_region->GetPrologLength()) +
|
|
"_region" + decstr(curr_region->GetRegionLength()) +
|
|
"_epilog" + decstr(curr_region->GetEpilogLength()) +
|
|
"_" + StringDecSigned(curr_region->GetRegionId(), 3, '0') +
|
|
"_" + weight_string;
|
|
region_info.regionId = curr_region->GetRegionId();
|
|
|
|
return region_info;
|
|
}
|
|
|
|
// Get the next region event
|
|
VOID SetTriggeredRegion(THREADID tid, VOID* event_handler) {
|
|
|
|
ASSERT(event_handler, "Event Handler is NULL.");
|
|
IEVENT * event = (IEVENT *)event_handler;
|
|
_last_triggered_region[tid] = event->iregion;
|
|
return;
|
|
}
|
|
|
|
private:
|
|
CONTROL_ARGS _control_args;
|
|
bool _valid;
|
|
CONTROLLER::CONTROL_MANAGER* _cm;
|
|
|
|
VOID ReadRegionsFile()
|
|
{
|
|
string filename = _rFileKnob.Value().c_str();
|
|
|
|
ifstream rfile(filename.c_str());
|
|
|
|
if (!rfile.is_open())
|
|
{
|
|
cerr << "Could not open regions file " <<
|
|
_rFileKnob.Value().c_str() << endl;
|
|
PIN_ExitApplication(-1);
|
|
}
|
|
|
|
UINT32 lineNum = 0;
|
|
UINT32 recordNum = 0;
|
|
IREGION * region = 0;
|
|
while(true)
|
|
{
|
|
if( rfile.eof() )
|
|
{
|
|
break;
|
|
}
|
|
|
|
UINT32 recordLen = 0;
|
|
CHAR record[BUFSIZE+1];
|
|
CHAR urecord[BUFSIZE+1];
|
|
string field;
|
|
|
|
double t_weight;
|
|
string t_comment;
|
|
INT32 t_rid;
|
|
INT32 t_tid;
|
|
UINT64 t_icountStart;
|
|
UINT64 t_icountEnd;
|
|
|
|
rfile.getline(record, BUFSIZE);
|
|
lineNum++;
|
|
|
|
recordLen = strnlen_s(record, BUFSIZE+1);
|
|
if (recordLen == 0) continue;
|
|
|
|
// Create a temporary record with lower case letters
|
|
for (UINT32 i = 0; i <= recordLen; i++)
|
|
urecord[i] = tolower(record[i]);
|
|
|
|
// first word "comment" : this is the header
|
|
if(strncmp(urecord,"comment",7)==0) continue;
|
|
|
|
// first letter '#' : this is a comment
|
|
if(urecord[0]=='#') continue;
|
|
|
|
istringstream s(record);
|
|
recordNum++;
|
|
|
|
|
|
// cerr << "Record # " << recordNum << endl;
|
|
field.clear();
|
|
getline(s, field, ',');
|
|
ASSERT(!field.empty(), "Empty comment field.");
|
|
t_comment = field;
|
|
// cerr << "Comment " << t_comment << endl;
|
|
|
|
field.clear();
|
|
getline(s, field, ',');
|
|
ASSERT(!field.empty(), "Empty thread-id field.");
|
|
t_tid = REGION_UTILS::StringToUINT32(field, "thread-id");
|
|
// cerr << "thread-id " << t_tid << endl;
|
|
|
|
field.clear();
|
|
getline(s, field, ',');
|
|
ASSERT(!field.empty(), "Empty region-id field.");
|
|
t_rid = REGION_UTILS::StringToUINT32(field, "region-id");
|
|
//cerr << "region-id " << t_rid << endl;
|
|
|
|
field.clear();
|
|
getline(s, field, ',');
|
|
ASSERT(!field.empty(), "Empty start-icount field.");
|
|
istringstream sistart(field);
|
|
t_icountStart = REGION_UTILS::StringToUINT64(field,
|
|
"simulation-region-start-icount");
|
|
//cerr << "start-icount " << t_icountStart << endl;
|
|
|
|
field.clear();
|
|
getline(s, field, ',');
|
|
ASSERT(!field.empty(), "Empty end-icount field.");
|
|
t_icountEnd = REGION_UTILS::StringToUINT64(field,
|
|
"simulation-region-end-icount");
|
|
//cerr << "end-icount " << siend << endl;
|
|
|
|
ASSERT(t_icountEnd > t_icountStart ,
|
|
"simulation-region-start-icount:" +
|
|
decstr(t_icountStart) +
|
|
" is not smaller than simulation-region-end-icount:"
|
|
+ decstr(t_icountEnd) );
|
|
|
|
field.clear();
|
|
getline(s, field, ',');
|
|
ASSERT(!field.empty(), "Empty region-weight field.");
|
|
t_weight = REGION_UTILS::StringToDouble(field, "region-weight");
|
|
ASSERT((t_weight >= 0),
|
|
"region-weight (" + field + ") must be positive" );
|
|
ASSERT((t_weight <= 1),
|
|
"region-weight (" + field + ") must be between 0 and 1" );
|
|
//cerr << "region-weight" << t_weight << endl;
|
|
|
|
string tail;
|
|
|
|
s >> tail;
|
|
|
|
if(!tail.empty())
|
|
cerr << "WARNING: regions:in file '" << filename <<
|
|
"' line number " << dec << lineNum <<
|
|
": ignoring fields : " << tail << endl;
|
|
|
|
ASSERTX(t_tid>=0 && (UINT32)t_tid<_maxThreads);
|
|
_regions[t_tid].push_back(IREGION());
|
|
region = & _regions[t_tid].back();
|
|
region->_comment = t_comment;
|
|
region->_rno = _regions[t_tid].size();
|
|
region->_rid = t_rid;
|
|
region->_tid = t_tid;
|
|
region->_weight = t_weight;
|
|
region->_weightTimesHundredThousand = (UINT32)(t_weight*100000);
|
|
region->_icountStart = t_icountStart;
|
|
region->_icountEnd = t_icountEnd;
|
|
}
|
|
rfile.close();
|
|
}
|
|
|
|
VOID PrintRegions()
|
|
{
|
|
for(UINT32 tid=0; tid < _maxThreads; tid++)
|
|
{
|
|
for ( UINT32 i = 0; i < _regions[tid].size(); i++ )
|
|
{
|
|
IREGION * region = & _regions[tid][i];
|
|
cerr << "rno: " << region->_rno
|
|
<< " comment " << region->_comment
|
|
<< " rid " << region->_rid
|
|
<< " tid " << region->_tid
|
|
<< " weight " << region->_weight
|
|
<< " weightTimesHundredThousand "
|
|
<< region->_weightTimesHundredThousand
|
|
<< " icountStart " << region->_icountStart
|
|
<< " icountEnd " << region->_icountEnd
|
|
<< " warmup_length " << region->_warmup_length
|
|
<< " prolog_length " << region->_prolog_length
|
|
<< " region_length " << region->GetRegionLength()
|
|
<< " epilog_length " << region->_epilog_length
|
|
<< endl;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
BOOL RegionHasOverlap(UINT32 tid, UINT64 span_begin, UINT64 span_end)
|
|
{
|
|
if(_rOverlapOkKnob) return false;
|
|
for ( UINT32 i = 0; i < _events[tid].size(); i++ )
|
|
{
|
|
IEVENT * event = & _events[tid][i];
|
|
if((span_begin <= event->icount) && (span_end >= event->icount))
|
|
{
|
|
if (xfile.is_open())
|
|
{
|
|
if(_xcount==0)
|
|
xfile << "comment,thread-id,region-id,"
|
|
<< "simulation-region-start-icount,"
|
|
<< "simulation-region-end-icount,region-weight"
|
|
<< endl;
|
|
xfile << "#expanded region " << dec << span_begin
|
|
<< ":" << dec << span_end
|
|
<< " overlapped with event "
|
|
<< IEVENT::EventToString(event->type) << " at "
|
|
<< dec << event->icount << endl;
|
|
_xcount++;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
VOID PrintEvents()
|
|
{
|
|
cerr << "Events:" << endl;
|
|
for(UINT32 tid=0; tid < _maxThreads; tid++)
|
|
{
|
|
for ( UINT32 i = 0; i < _events[tid].size(); i++ )
|
|
{
|
|
IEVENT * event = & _events[tid][i];
|
|
cerr << "tid " << dec << tid << " event "
|
|
<< IEVENT::EventToString(event->type) << " at "
|
|
<< dec << event->icount << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sort the events according to their type and icount
|
|
// Prepare controller events strings
|
|
VOID ProcessEvents()
|
|
{
|
|
for(UINT32 tid=0; tid < _maxThreads; tid++)
|
|
{
|
|
sort(_events[tid].begin(), _events[tid].end(),
|
|
IEVENT::EventLessThan);
|
|
|
|
// Add to controller strings
|
|
for ( UINT32 i = 0; i < _events[tid].size(); i++ )
|
|
{
|
|
IEVENT * event = & _events[tid][i];
|
|
CHAIN_EVENT chain_event;
|
|
chain_event.event_handler = event;
|
|
chain_event.chain_str = _cm->EventToString(event->type)+":icount:"+decstr(event->icount)+":tid"+decstr(tid);
|
|
chain_event.tid = tid;
|
|
_regionControlChains.push_back(chain_event);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add an event to the events vector
|
|
VOID InsertOneEvent(UINT32 tid, UINT64 icount,
|
|
EVENT_TYPE type, IREGION * region)
|
|
{
|
|
IEVENT * event = 0;
|
|
_events[tid].push_back(IEVENT());
|
|
event = & _events[tid].back();
|
|
|
|
event->icount = icount;
|
|
event->type = type;
|
|
event->iregion = region;
|
|
}
|
|
|
|
VOID ProcessRegions()
|
|
{
|
|
for(UINT32 tid=0; tid < _maxThreads; tid++)
|
|
{
|
|
for ( UINT32 i = 0; i < _regions[tid].size(); i++ )
|
|
{
|
|
IREGION * region = & _regions[tid][i];
|
|
UINT64 span_begin = 0;
|
|
UINT64 span_end = 0;
|
|
|
|
// cerr << "rno: " << region->_rno
|
|
// << " comment " << region->_comment
|
|
// << " icountStart " << region->_icountStart
|
|
// << " icountEnd " << region->_icountEnd
|
|
// << endl;
|
|
|
|
INT64 wstart = region->_icountStart-_rPrologKnob-_rWarmupKnob;
|
|
INT64 wend = region->_icountStart - _rPrologKnob;
|
|
INT64 pstart = wend;
|
|
INT64 pend = region->_icountStart;
|
|
INT64 rstart = pend;
|
|
INT64 estart = region->_icountEnd;
|
|
INT64 rend = estart;
|
|
INT64 eend = region->_icountEnd + _rEpilogKnob;
|
|
|
|
if(_rWarmupKnob && (wstart > 0))
|
|
{
|
|
// cerr << "WarmupStart " << dec << wstart << endl;
|
|
// cerr << "WarmupEnd " << dec << wend << endl;
|
|
span_begin = wstart;
|
|
}
|
|
|
|
if(_rPrologKnob && (pstart > 0))
|
|
{
|
|
// cerr << "PrologStart " << dec << pstart << endl;
|
|
// cerr << "PrologEnd " << dec << pend << endl;
|
|
if(!span_begin) span_begin = pstart;
|
|
}
|
|
|
|
if(!span_begin) span_begin = rstart;
|
|
// cerr << "RegionStart " << dec << rstart << endl;
|
|
// cerr << "RegionEnd " << dec << rend << endl;
|
|
span_end = rend;
|
|
|
|
if(_rEpilogKnob && (eend > estart))
|
|
{
|
|
// cerr << "EpilogStart " << dec << estart << endl;
|
|
// cerr << "EpilogEnd " << dec << eend << endl;
|
|
span_end = eend;
|
|
}
|
|
|
|
// cerr << "span_begin " << dec << span_begin << endl;
|
|
// cerr << "span_end " << dec << span_end << endl;
|
|
|
|
if(RegionHasOverlap(tid, span_begin, span_end))
|
|
{
|
|
// cerr << "Region has overlap" << endl;
|
|
if (xfile.is_open())
|
|
{
|
|
xfile << region->_comment
|
|
<< "," << region->_tid
|
|
<< "," << region->_rid
|
|
<< "," << region->_icountStart
|
|
<< "," << region->_icountEnd
|
|
<< "," << region->_weight
|
|
<< endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(_rWarmupKnob && (wstart > 0))
|
|
{
|
|
InsertOneEvent(tid, wstart, EVENT_WARMUP_START, region);
|
|
InsertOneEvent(tid, wend, EVENT_WARMUP_STOP, region);
|
|
region->_warmup_length = wend - wstart;
|
|
}
|
|
if(_rPrologKnob && (pstart > 0))
|
|
{
|
|
InsertOneEvent(tid, pstart, EVENT_PROLOG_START, region);
|
|
InsertOneEvent(tid, pend, EVENT_PROLOG_STOP, region);
|
|
region->_prolog_length = pend - pstart;
|
|
}
|
|
InsertOneEvent(tid, rstart, EVENT_START, region);
|
|
InsertOneEvent(tid, rend, EVENT_STOP, region);
|
|
if(_rEpilogKnob && (eend > estart))
|
|
{
|
|
InsertOneEvent(tid, estart, EVENT_EPILOG_START, region);
|
|
InsertOneEvent(tid, eend, EVENT_EPILOG_STOP, region);
|
|
region->_epilog_length = eend - estart;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (xfile.is_open())
|
|
{
|
|
if(_xcount) xfile << "#eof" << endl;
|
|
xfile.close();
|
|
}
|
|
}
|
|
|
|
KNOB<string> _rFileKnob;
|
|
KNOB<UINT64> _rWarmupKnob;
|
|
KNOB<UINT64> _rPrologKnob;
|
|
KNOB<UINT64> _rEpilogKnob;
|
|
KNOB<BOOL> _rVerboseKnob;
|
|
KNOB<BOOL> _rOverlapOkKnob;
|
|
KNOB<string> _rOutFileKnob;
|
|
IREGION_VECTOR *_regions; // per thread vector containing region info
|
|
IEVENT_VECTOR *_events; // per thread list (sorted by icount) of events
|
|
bool _active;
|
|
THREADID _maxThreads;
|
|
ofstream xfile; // for writing out regions excluded due to overlap
|
|
UINT32 _xcount; // number of regions excluded
|
|
IREGION ** _last_triggered_region;
|
|
BOOL _passContext;
|
|
CHAIN_EVENT_VECTOR _regionControlChains;
|
|
};
|
|
}
|
|
#endif
|