| /* |
| * 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 <cstdio> |
| #include <list> |
| #include <vector> |
| |
| #include "cpu/inorder/pipeline_traits.hh" |
| #include "cpu/inorder/resource_sked.hh" |
| #include "debug/SkedCache.hh" |
| |
| using namespace std; |
| using namespace ThePipeline; |
| |
| ResourceSked::ResourceSked() |
| { |
| stages.resize(NumStages); |
| } |
| |
| void |
| ResourceSked::init() |
| { |
| assert(!stages[0].empty()); |
| |
| curSkedEntry = stages[0].begin(); |
| } |
| |
| int |
| ResourceSked::size() |
| { |
| int total = 0; |
| for (int i = 0; i < stages.size(); i++) { |
| total += stages[i].size(); |
| } |
| |
| return total; |
| } |
| |
| bool |
| ResourceSked::empty() |
| { |
| return size() == 0; |
| } |
| |
| |
| ResourceSked::SkedIt |
| ResourceSked::begin() |
| { |
| int num_stages = stages.size(); |
| for (int i = 0; i < num_stages; i++) { |
| if (stages[i].size() > 0) |
| return stages[i].begin(); |
| } |
| |
| return stages[num_stages - 1].end(); |
| } |
| |
| ResourceSked::SkedIt |
| ResourceSked::end() |
| { |
| int num_stages = stages.size(); |
| return stages[num_stages - 1].end(); |
| } |
| |
| ResourceSked::SkedIt |
| ResourceSked::end(int stage_num) |
| { |
| return stages[stage_num].end(); |
| } |
| |
| ResourceSked::SkedIt |
| ResourceSked::find(int stage_num, int cmd) |
| { |
| SkedIt stage_it = stages[stage_num].begin(); |
| SkedIt stage_end = stages[stage_num].end(); |
| |
| while (stage_it != stage_end) { |
| if ((*stage_it)->cmd == cmd) |
| return stage_it; |
| stage_it++; |
| } |
| |
| return stages[stage_num].end(); |
| } |
| |
| ScheduleEntry* |
| ResourceSked::top() |
| { |
| assert(size() > 0); |
| |
| return *curSkedEntry; |
| } |
| |
| void |
| ResourceSked::pop() |
| { |
| int stage_num = (*curSkedEntry)->stageNum; |
| |
| stages[stage_num].erase(curSkedEntry); |
| |
| if (!stages[stage_num].empty()) { |
| curSkedEntry = stages[stage_num].begin(); |
| } else { |
| int next_stage = stage_num + 1; |
| |
| while (next_stage < NumStages) { |
| if (stages[next_stage].empty()) { |
| next_stage++; |
| } else { |
| curSkedEntry = stages[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); |
| |
| stages[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 != stages[stage_num].end() && |
| "Could not find command to insert in front of."); |
| |
| stages[stage_num].insert(pri_iter, sked_entry); |
| } |
| |
| ResourceSked::SkedIt |
| ResourceSked::findIterByPriority(ScheduleEntry* sked_entry, int stage_num) |
| { |
| if (stages[stage_num].empty()) { |
| return stages[stage_num].end(); |
| } |
| |
| int priority = sked_entry->priority; |
| |
| SkedIt sked_it = stages[stage_num].begin(); |
| SkedIt sked_end = stages[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 (stages[stage_num].empty()) { |
| return stages[stage_num].end(); |
| } |
| |
| SkedIt sked_it = stages[stage_num].begin(); |
| SkedIt sked_end = stages[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 < stages.size(); i++) { |
| //ccprintf(cerr, "Stage %i\n====\n", i); |
| SkedIt sked_it = stages[i].begin(); |
| SkedIt sked_end = stages[i].end(); |
| while (sked_it != sked_end) { |
| DPRINTF(SkedCache, "\t stage:%i res:%i cmd:%i idx:%i\n", |
| (*sked_it)->stageNum, |
| (*sked_it)->resNum, |
| (*sked_it)->cmd, |
| (*sked_it)->idx); |
| sked_it++; |
| } |
| } |
| } |