inorder: resource scheduling backend
authorKorey Sewell <ksewell@umich.edu>
Fri, 25 Jun 2010 21:42:34 +0000 (17:42 -0400)
committerKorey Sewell <ksewell@umich.edu>
Fri, 25 Jun 2010 21:42:34 +0000 (17:42 -0400)
replace priority queue with vector of lists(1 list per stage) and place inside a class
so that we have more control of when an instruction uses a particular schedule entry
...
also, this is the 1st step toward making the InOrderCPU fully parameterizable. See the
wiki for details on this process

src/cpu/inorder/SConscript
src/cpu/inorder/cpu.cc
src/cpu/inorder/inorder_dyn_inst.hh
src/cpu/inorder/pipeline_traits.cc
src/cpu/inorder/pipeline_traits.hh
src/cpu/inorder/resource_sked.cc [new file with mode: 0644]
src/cpu/inorder/resource_sked.hh [new file with mode: 0644]

index 3717c2f57e536c0e1b850e3fe3f9c3b400978388..90cb285f561e8ccac1abac90989b36c4eaba0615 100644 (file)
@@ -82,6 +82,7 @@ if 'InOrderCPU' in env['CPU_MODELS']:
        Source('resources/fetch_seq_unit.cc')
        Source('resources/mult_div_unit.cc')
        Source('resource_pool.cc')
+       Source('resource_sked.cc')      
        Source('reg_dep_map.cc')
        Source('thread_state.cc')
        Source('thread_context.cc')
index d36867439f4d830f83ae518d3f9d99c0168e62f0..a895fdb0ed08f5417496f90be38b42d78b096993 100644 (file)
@@ -1354,7 +1354,7 @@ InOrderCPU::cleanUpRemovedInsts()
         // Make Sure Resource Schedule Is Emptied Out
         ThePipeline::ResSchedule *inst_sched = &inst->resSched;
         while (!inst_sched->empty()) {
-            ThePipeline::ScheduleEntry* sch_entry = inst_sched->top();
+            ScheduleEntry* sch_entry = inst_sched->top();
             inst_sched->pop();
             delete sch_entry;
         }
index 1a349676ffa869429c6f6778eae15ef1fc159cf0..ffb795e1e4a7e85a9425702e1709fb0a96b58633 100644 (file)
@@ -50,6 +50,7 @@
 #include "cpu/inorder/inorder_trace.hh"
 #include "cpu/inorder/pipeline_traits.hh"
 #include "cpu/inorder/resource.hh"
+#include "cpu/inorder/resource_sked.hh"
 #include "cpu/inorder/thread_state.hh"
 #include "cpu/inst_seq.hh"
 #include "cpu/op_class.hh"
@@ -436,7 +437,7 @@ class InOrderDynInst : public FastAlloc, public RefCounted
     void deleteStages();
 
     /** Add A Entry To Reource Schedule */
-    void addToSched(ThePipeline::ScheduleEntry* sched_entry)
+    void addToSched(ScheduleEntry* sched_entry)
     { resSched.push(sched_entry); }
 
 
@@ -481,7 +482,7 @@ class InOrderDynInst : public FastAlloc, public RefCounted
     void popSchedEntry()
     {
         if (!resSched.empty()) {
-            ThePipeline::ScheduleEntry* sked = resSched.top();
+            ScheduleEntry* sked = resSched.top();
             resSched.pop();
             if (sked != 0) {
                 delete sked;
index 3971701638a7d3d14f719c56bec0c6ab5a58a5e8..fe400471a211495b231b7aea77940e2d79af37cd 100644 (file)
@@ -77,6 +77,8 @@ void createFrontEndSchedule(DynInstPtr &inst)
     D->needs(Decode, DecodeUnit::DecodeInst);
     D->needs(BPred, BranchPredictor::PredictBranch);
     D->needs(FetchSeq, FetchSeqUnit::UpdateTargetPC);
+
+    inst->resSched.init();
 }
 
 bool createBackEndSchedule(DynInstPtr &inst)
@@ -152,4 +154,18 @@ InstStage::InstStage(DynInstPtr inst, int stage_num)
     instSched = &inst->resSched;
 }
 
+void
+InstStage::needs(int unit, int request) {
+    instSched->push( new ScheduleEntry(
+                         stageNum, nextTaskPriority++, unit, request
+                         ));
+}
+
+void
+InstStage::needs(int unit, int request, int param) {
+    instSched->push( new ScheduleEntry(
+                         stageNum, nextTaskPriority++, unit, request, param
+                         ));
+}
+
 };
index 0f996023b7925570c746134bb507853c9122e485..7abfc9a818dfb732397db370052a7c27f40572ca 100644 (file)
@@ -42,6 +42,8 @@
 #include "params/InOrderCPU.hh"
 
 class InOrderDynInst;
+class ScheduleEntry;
+class ResourceSked;
 
 /* This Namespace contains constants, typedefs, functions and
  * objects specific to the Pipeline Implementation.
@@ -88,51 +90,7 @@ namespace ThePipeline {
     //////////////////////////
     // RESOURCE SCHEDULING
     //////////////////////////
-    struct ScheduleEntry {
-        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)
-        { }
-
-        // Stage number to perform this service.
-        int stageNum;
-
-        // Resource ID to access
-        int resNum;
-
-        // See specific resource for meaning
-        unsigned cmd;
-
-        // See specific resource for meaning
-        unsigned idx;
-
-        // Some Resources May Need Priority?
-        int priority;
-    };
-
-    struct entryCompare {
-        bool operator()(const ScheduleEntry* lhs, const ScheduleEntry* rhs) 
-            const
-        {
-            // Prioritize first by stage number that the resource is needed
-            if (lhs->stageNum > rhs->stageNum) {
-                return true;
-            } else if (lhs->stageNum == rhs->stageNum) {
-                if (lhs->priority > rhs->priority) {
-                  return true;
-                } else {
-                  return false;
-                }
-            } else {
-                return false;
-            }
-        }
-    };
-
-
-    typedef std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>,
-                                         entryCompare> ResSchedule;
+    typedef ResourceSked ResSchedule;
 
     void createFrontEndSchedule(DynInstPtr &inst);
     bool createBackEndSchedule(DynInstPtr &inst);
@@ -147,17 +105,8 @@ namespace ThePipeline {
       public:
         InstStage(DynInstPtr inst, int stage_num);
 
-        void needs(int unit, int request) {
-            instSched->push( new ScheduleEntry(
-                stageNum, nextTaskPriority++, unit, request
-            ));
-        }
-
-        void needs(int unit, int request, int param) {
-            instSched->push( new ScheduleEntry(
-                stageNum, nextTaskPriority++, unit, request, param
-            ));
-        }
+        void needs(int unit, int request);
+        void needs(int unit, int request, int param);
     };
 };
 
diff --git a/src/cpu/inorder/resource_sked.cc b/src/cpu/inorder/resource_sked.cc
new file mode 100644 (file)
index 0000000..4104e69
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2010 The Regents of The University of Michigan
+ * 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
+ *
+ */
+
+#include "cpu/inorder/resource_sked.hh"
+#include "cpu/inorder/pipeline_traits.hh"
+
+#include <vector>
+#include <list>
+#include <stdio.h>
+
+using namespace std;
+using namespace ThePipeline;
+
+ResourceSked::ResourceSked()
+{
+    sked.resize(NumStages);
+}
+
+void
+ResourceSked::init()
+{
+    assert(!sked[0].empty());
+
+    curSkedEntry = sked[0].begin();
+}
+
+int
+ResourceSked::size()
+{
+    int total = 0;
+    for (int i = 0; i < sked.size(); i++) {
+        total += sked[i].size();
+    }
+
+    return total;
+}
+
+bool
+ResourceSked::empty()
+{
+    return size() == 0;
+}
+
+ScheduleEntry*
+ResourceSked::top()
+{
+    assert(size() > 0);
+
+    return *curSkedEntry;
+}
+
+void
+ResourceSked::pop()
+{
+    int stage_num = (*curSkedEntry)->stageNum;
+
+    sked[stage_num].erase(curSkedEntry);
+
+    if (!sked[stage_num].empty()) {
+        curSkedEntry = sked[stage_num].begin();
+    } else {
+        int next_stage = stage_num + 1;
+
+        while (next_stage < NumStages) {
+            if (sked[next_stage].empty()) {
+                next_stage++;
+            } else {
+                curSkedEntry = sked[next_stage].begin();
+                break;
+            }
+        }
+    }
+}
+
+void
+ResourceSked::push(ScheduleEntry* sked_entry)
+{
+    int stage_num = sked_entry->stageNum;
+    assert(stage_num < NumStages);
+
+    SkedIt pri_iter = findIterByPriority(sked_entry, stage_num);
+
+    sked[stage_num].insert(pri_iter, sked_entry);
+}
+
+void
+ResourceSked::pushBefore(ScheduleEntry* sked_entry, int sked_cmd,
+                         int sked_cmd_idx)
+{
+
+    int stage_num = sked_entry->stageNum;
+    assert(stage_num < NumStages);
+
+    SkedIt pri_iter = findIterByCommand(sked_entry, stage_num,
+                                        sked_cmd, sked_cmd_idx);
+
+    assert(pri_iter != sked[stage_num].end() &&
+           "Could not find command to insert in front of.");
+
+    sked[stage_num].insert(pri_iter, sked_entry);
+}
+
+ResourceSked::SkedIt
+ResourceSked::findIterByPriority(ScheduleEntry* sked_entry, int stage_num)
+{
+    if (sked[stage_num].empty()) {
+        return sked[stage_num].end();
+    }
+
+    int priority = sked_entry->priority;
+
+    SkedIt sked_it = sked[stage_num].begin();
+    SkedIt sked_end = sked[stage_num].end();
+
+    while (sked_it != sked_end) {
+        if ((*sked_it)->priority > priority)
+            break;
+
+        sked_it++;
+    }
+
+    return sked_it;
+}
+
+ResourceSked::SkedIt
+ResourceSked::findIterByCommand(ScheduleEntry* sked_entry, int stage_num,
+                                int sked_cmd, int sked_cmd_idx)
+{
+    if (sked[stage_num].empty()) {
+        return sked[stage_num].end();
+    }
+
+    SkedIt sked_it = sked[stage_num].begin();
+    SkedIt sked_end = sked[stage_num].end();
+
+    while (sked_it != sked_end) {
+        if ((*sked_it)->cmd == sked_cmd &&
+            (sked_cmd_idx != -1) ? (*sked_it)->idx == sked_cmd_idx : true)
+            break;
+
+        sked_it++;
+    }
+
+    return sked_it;
+}
+
+void
+ResourceSked::print()
+{
+    for (int i = 0; i < sked.size(); i++) {
+        cprintf("Stage %i\n====\n", i);
+        SkedIt sked_it = sked[i].begin();
+        SkedIt sked_end = sked[i].end();
+        while (sked_it != sked_end) {
+            cprintf("\t res:%i cmd:%i idx:%i\n", (*sked_it)->resNum, (*sked_it)->cmd, (*sked_it)->idx);
+            sked_it++;
+        }
+    }
+}
diff --git a/src/cpu/inorder/resource_sked.hh b/src/cpu/inorder/resource_sked.hh
new file mode 100644 (file)
index 0000000..22e29d7
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010 The Regents of The University of Michigan
+ * 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>
+
+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)
+    { }
+
+    // Stage number to perform this service.
+    int stageNum;
+
+    // Resource ID to access
+    int resNum;
+
+    // See specific resource for meaning
+    unsigned cmd;
+
+    // See specific resource for meaning
+    unsigned idx;
+
+    // Some Resources May Need Priority
+    int priority;
+};
+
+class ResourceSked {
+  public:
+    typedef std::list<ScheduleEntry*>::iterator SkedIt;
+
+    ResourceSked();
+
+    void init();
+
+    int size();
+    bool empty();
+    ScheduleEntry* top();
+    void pop();
+    void push(ScheduleEntry* sked_entry);
+    void pushBefore(ScheduleEntry* sked_entry, int sked_cmd, int sked_cmd_idx);
+    void print();
+
+  private:
+    SkedIt curSkedEntry;
+    std::vector<std::list<ScheduleEntry*> > sked;
+
+    SkedIt findIterByPriority(ScheduleEntry *sked_entry, int stage_num);
+    SkedIt findIterByCommand(ScheduleEntry *sked_entry, int stage_num,
+                             int sked_cmd, int sked_cmd_idx = -1);
+};
+
+#endif //__CPU_INORDER_RESOURCE_SKED_HH__