2010-06-25 23:42:34 +02:00
|
|
|
/*
|
2011-02-12 16:14:43 +01:00
|
|
|
* Copyright (c) 2010-2011 The Regents of The University of Michigan
|
2010-06-25 23:42:34 +02:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met: redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer;
|
|
|
|
* redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution;
|
|
|
|
* neither the name of the copyright holders nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived from
|
|
|
|
* this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* Authors: Korey Sewell
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __CPU_INORDER_RESOURCE_SKED_HH__
|
|
|
|
#define __CPU_INORDER_RESOURCE_SKED_HH__
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
#include <list>
|
2011-02-12 16:14:43 +01:00
|
|
|
#include <cstdlib>
|
2010-06-25 23:42:34 +02:00
|
|
|
|
2011-02-12 16:14:34 +01:00
|
|
|
/** ScheduleEntry class represents a single function that an instruction
|
|
|
|
wants to do at any pipeline stage. For example, if an instruction
|
|
|
|
needs to be decoded and do a branch prediction all in one stage
|
|
|
|
then each of those tasks would need it's own ScheduleEntry.
|
|
|
|
|
|
|
|
Each schedule entry corresponds to some resource that the instruction
|
|
|
|
wants to interact with.
|
|
|
|
|
|
|
|
The file pipeline_traits.cc shows how a typical instruction schedule is
|
|
|
|
made up of these schedule entries.
|
|
|
|
*/
|
2010-06-25 23:42:34 +02:00
|
|
|
class ScheduleEntry {
|
|
|
|
public:
|
|
|
|
ScheduleEntry(int stage_num, int _priority, int res_num, int _cmd = 0,
|
|
|
|
int _idx = 0) :
|
|
|
|
stageNum(stage_num), resNum(res_num), cmd(_cmd),
|
|
|
|
idx(_idx), priority(_priority)
|
|
|
|
{ }
|
|
|
|
|
2011-02-12 16:14:34 +01:00
|
|
|
/** Stage number to perform this service. */
|
2010-06-25 23:42:34 +02:00
|
|
|
int stageNum;
|
|
|
|
|
2011-02-12 16:14:34 +01:00
|
|
|
/** Resource ID to access */
|
2010-06-25 23:42:34 +02:00
|
|
|
int resNum;
|
|
|
|
|
2011-02-12 16:14:34 +01:00
|
|
|
/** See specific resource for meaning */
|
2010-06-25 23:42:34 +02:00
|
|
|
unsigned cmd;
|
|
|
|
|
2011-02-12 16:14:34 +01:00
|
|
|
/** See specific resource for meaning */
|
2010-06-25 23:42:34 +02:00
|
|
|
unsigned idx;
|
|
|
|
|
2011-02-12 16:14:34 +01:00
|
|
|
/** Some Resources May Need Priority */
|
2010-06-25 23:42:34 +02:00
|
|
|
int priority;
|
|
|
|
};
|
|
|
|
|
2011-02-12 16:14:34 +01:00
|
|
|
/** The ResourceSked maintains the complete schedule
|
|
|
|
for an instruction. That schedule includes what
|
|
|
|
resources an instruction wants to acquire at each
|
|
|
|
pipeline stage and is represented by a collection
|
|
|
|
of ScheduleEntry objects (described above) that
|
|
|
|
must be executed in-order.
|
|
|
|
|
|
|
|
In every pipeline stage, the InOrder model will
|
|
|
|
process all entries on the resource schedule for
|
|
|
|
that stage and then send the instruction to the next
|
|
|
|
stage if and only if the instruction successfully
|
|
|
|
completed each ScheduleEntry.
|
|
|
|
*/
|
2010-06-25 23:42:34 +02:00
|
|
|
class ResourceSked {
|
|
|
|
public:
|
|
|
|
typedef std::list<ScheduleEntry*>::iterator SkedIt;
|
2011-02-12 16:14:43 +01:00
|
|
|
typedef std::vector<std::list<ScheduleEntry*> > StageList;
|
2010-06-25 23:42:34 +02:00
|
|
|
|
|
|
|
ResourceSked();
|
|
|
|
|
2011-02-12 16:14:34 +01:00
|
|
|
/** Initializee the current entry pointer to
|
|
|
|
pipeline stage 0 and the 1st schedule entry
|
|
|
|
*/
|
2010-06-25 23:42:34 +02:00
|
|
|
void init();
|
|
|
|
|
2011-02-12 16:14:34 +01:00
|
|
|
/** Goes through the remaining stages on the schedule
|
|
|
|
and sums all the remaining entries left to be
|
|
|
|
processed
|
|
|
|
*/
|
2010-06-25 23:42:34 +02:00
|
|
|
int size();
|
2011-02-12 16:14:34 +01:00
|
|
|
|
|
|
|
/** Is the schedule empty? */
|
2010-06-25 23:42:34 +02:00
|
|
|
bool empty();
|
2011-02-12 16:14:34 +01:00
|
|
|
|
2011-02-12 16:14:43 +01:00
|
|
|
/** Beginning Entry of this schedule */
|
|
|
|
SkedIt begin();
|
|
|
|
|
|
|
|
/** Ending Entry of this schedule */
|
|
|
|
SkedIt end();
|
|
|
|
|
2011-02-12 16:14:34 +01:00
|
|
|
/** What is the next task for this instruction schedule? */
|
2010-06-25 23:42:34 +02:00
|
|
|
ScheduleEntry* top();
|
2011-02-12 16:14:34 +01:00
|
|
|
|
|
|
|
/** Top() Task is completed, remove it from schedule */
|
2010-06-25 23:42:34 +02:00
|
|
|
void pop();
|
2011-02-12 16:14:34 +01:00
|
|
|
|
|
|
|
/** Add To Schedule based on stage num and priority of
|
|
|
|
Schedule Entry
|
|
|
|
*/
|
2010-06-25 23:42:34 +02:00
|
|
|
void push(ScheduleEntry* sked_entry);
|
2011-02-12 16:14:34 +01:00
|
|
|
|
|
|
|
/** Add Schedule Entry to be in front of another Entry */
|
2010-06-25 23:42:34 +02:00
|
|
|
void pushBefore(ScheduleEntry* sked_entry, int sked_cmd, int sked_cmd_idx);
|
2011-02-12 16:14:34 +01:00
|
|
|
|
|
|
|
/** Print what's left on the instruction schedule */
|
2010-06-25 23:42:34 +02:00
|
|
|
void print();
|
|
|
|
|
2011-02-12 16:14:43 +01:00
|
|
|
StageList *getStages()
|
|
|
|
{
|
|
|
|
return &stages;
|
|
|
|
}
|
|
|
|
|
2010-06-25 23:42:34 +02:00
|
|
|
private:
|
2011-02-12 16:14:34 +01:00
|
|
|
/** Current Schedule Entry Pointer */
|
2010-06-25 23:42:34 +02:00
|
|
|
SkedIt curSkedEntry;
|
2011-02-12 16:14:34 +01:00
|
|
|
|
2011-02-12 16:14:43 +01:00
|
|
|
/** The Stage-by-Stage Resource Schedule:
|
|
|
|
Resized to Number of Stages in the constructor
|
2011-02-12 16:14:34 +01:00
|
|
|
*/
|
2011-02-12 16:14:43 +01:00
|
|
|
StageList stages;
|
2010-06-25 23:42:34 +02:00
|
|
|
|
2011-02-12 16:14:34 +01:00
|
|
|
/** Find a place to insert the instruction using the
|
|
|
|
schedule entries priority
|
|
|
|
*/
|
2010-06-25 23:42:34 +02:00
|
|
|
SkedIt findIterByPriority(ScheduleEntry *sked_entry, int stage_num);
|
2011-02-12 16:14:34 +01:00
|
|
|
|
|
|
|
/** Find a place to insert the instruction using a particular command
|
|
|
|
to look for.
|
|
|
|
*/
|
2010-06-25 23:42:34 +02:00
|
|
|
SkedIt findIterByCommand(ScheduleEntry *sked_entry, int stage_num,
|
|
|
|
int sked_cmd, int sked_cmd_idx = -1);
|
|
|
|
};
|
|
|
|
|
2011-02-12 16:14:43 +01:00
|
|
|
/** Wrapper class around the SkedIt iterator in the Resource Sked so that
|
|
|
|
we can use ++ operator to automatically go to the next available
|
|
|
|
resource schedule entry but otherwise maintain same functionality
|
|
|
|
as a normal iterator.
|
|
|
|
*/
|
|
|
|
class RSkedIt
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
RSkedIt()
|
|
|
|
: curStage(0), numStages(0)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
/** init() must be called before the use of any other member
|
|
|
|
in the RSkedIt class.
|
|
|
|
*/
|
|
|
|
void init(ResourceSked* rsked)
|
|
|
|
{
|
|
|
|
stages = rsked->getStages();
|
|
|
|
numStages = stages->size();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update the encapsulated "myIt" iterator, but only
|
|
|
|
update curStage/curStage_end if the iterator is valid.
|
|
|
|
The iterator could be invalid in the case where
|
|
|
|
someone is saving the end of a list (i.e. std::list->end())
|
|
|
|
*/
|
|
|
|
RSkedIt operator=(ResourceSked::SkedIt const &rhs)
|
|
|
|
{
|
|
|
|
myIt = rhs;
|
|
|
|
if (myIt != (*stages)[numStages-1].end()) {
|
|
|
|
curStage = (*myIt)->stageNum;
|
|
|
|
curStage_end = (*stages)[curStage].end();
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Increment to the next entry in current stage.
|
|
|
|
If no more entries then find the next stage that has
|
|
|
|
resource schedule to complete.
|
|
|
|
If no more stages, then return the end() iterator from
|
|
|
|
the last stage to indicate we are done.
|
|
|
|
*/
|
|
|
|
RSkedIt &operator++(int unused)
|
|
|
|
{
|
|
|
|
if (++myIt == curStage_end) {
|
|
|
|
curStage++;
|
|
|
|
while (curStage < numStages) {
|
|
|
|
if ((*stages)[curStage].empty()) {
|
|
|
|
curStage++;
|
|
|
|
} else {
|
|
|
|
myIt = (*stages)[curStage].begin();
|
|
|
|
curStage_end = (*stages)[curStage].end();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
myIt = (*stages)[numStages - 1].end();
|
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** The "pointer" operator can be used on a RSkedIt and it
|
|
|
|
will use the encapsulated iterator
|
|
|
|
*/
|
|
|
|
ScheduleEntry* operator->()
|
|
|
|
{
|
|
|
|
return *myIt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Dereferencing a RSKedIt will access the encapsulated
|
|
|
|
iterator
|
|
|
|
*/
|
|
|
|
ScheduleEntry* operator*()
|
|
|
|
{
|
|
|
|
return *myIt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Equality for RSkedIt only compares the "myIt" iterators,
|
|
|
|
as the other members are just ancillary
|
|
|
|
*/
|
|
|
|
bool operator==(RSkedIt const &rhs)
|
|
|
|
{
|
|
|
|
return this->myIt == rhs.myIt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Inequality for RSkedIt only compares the "myIt" iterators,
|
|
|
|
as the other members are just ancillary
|
|
|
|
*/
|
|
|
|
bool operator!=(RSkedIt const &rhs)
|
|
|
|
{
|
|
|
|
return this->myIt != rhs.myIt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The == and != operator overloads should be sufficient
|
|
|
|
here if need otherwise direct access to the schedule
|
|
|
|
iterator, then this can be used */
|
|
|
|
ResourceSked::SkedIt getIt()
|
|
|
|
{
|
|
|
|
return myIt;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
/** Schedule Iterator that this class is encapsulating */
|
|
|
|
ResourceSked::SkedIt myIt;
|
|
|
|
|
|
|
|
/** Ptr to resource schedule that the 'myIt' iterator
|
|
|
|
belongs to
|
|
|
|
*/
|
|
|
|
ResourceSked::StageList *stages;
|
|
|
|
|
|
|
|
/** The last iterator in the current stage. */
|
|
|
|
ResourceSked::SkedIt curStage_end;
|
|
|
|
|
|
|
|
/** Current Stage that "myIt" refers to. */
|
|
|
|
int curStage;
|
|
|
|
|
|
|
|
/** Number of stages in the "*stages" object. */
|
|
|
|
int numStages;
|
|
|
|
};
|
|
|
|
|
2010-06-25 23:42:34 +02:00
|
|
|
#endif //__CPU_INORDER_RESOURCE_SKED_HH__
|