| //===-- MSSchedule.cpp Schedule ---------------------------------*- C++ -*-===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file was developed by the LLVM research group and is distributed under | |
| // the University of Illinois Open Source License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #define DEBUG_TYPE "ModuloSched" | |
| #include "MSSchedule.h" | |
| #include "Support/Debug.h" | |
| #include "llvm/Target/TargetSchedInfo.h" | |
| using namespace llvm; | |
| bool MSSchedule::insert(MSchedGraphNode *node, int cycle) { | |
| //First, check if the cycle has a spot free to start | |
| if(schedule.find(cycle) != schedule.end()) { | |
| if (schedule[cycle].size() < numIssue) { | |
| if(resourcesFree(node, cycle)) { | |
| schedule[cycle].push_back(node); | |
| DEBUG(std::cerr << "Found spot in map, and there is an issue slot\n"); | |
| return false; | |
| } | |
| } | |
| } | |
| //Not in the map yet so put it in | |
| else { | |
| if(resourcesFree(node,cycle)) { | |
| std::vector<MSchedGraphNode*> nodes; | |
| nodes.push_back(node); | |
| schedule[cycle] = nodes; | |
| DEBUG(std::cerr << "Nothing in map yet so taking an issue slot\n"); | |
| return false; | |
| } | |
| } | |
| DEBUG(std::cerr << "All issue slots taken\n"); | |
| return true; | |
| } | |
| bool MSSchedule::resourcesFree(MSchedGraphNode *node, int cycle) { | |
| //Get Resource usage for this instruction | |
| const TargetSchedInfo *msi = node->getParent()->getTarget()->getSchedInfo(); | |
| int currentCycle = cycle; | |
| bool success = true; | |
| //Get resource usage for this instruction | |
| InstrRUsage rUsage = msi->getInstrRUsage(node->getInst()->getOpcode()); | |
| std::vector<std::vector<resourceId_t> > resources = rUsage.resourcesByCycle; | |
| //Loop over resources in each cycle and increments their usage count | |
| for(unsigned i=0; i < resources.size(); ++i) { | |
| for(unsigned j=0; j < resources[i].size(); ++j) { | |
| int resourceNum = resources[i][j]; | |
| //Check if this resource is available for this cycle | |
| std::map<int, std::map<int,int> >::iterator resourcesForCycle = resourceNumPerCycle.find(currentCycle); | |
| //First check map of resources for this cycle | |
| if(resourcesForCycle != resourceNumPerCycle.end()) { | |
| //A map exists for this cycle, so lets check for the resource | |
| std::map<int, int>::iterator resourceUse = resourcesForCycle->second.find(resourceNum); | |
| if(resourceUse != resourcesForCycle->second.end()) { | |
| //Check if there are enough of this resource and if so, increase count and move on | |
| if(resourceUse->second < CPUResource::getCPUResource(resourceNum)->maxNumUsers) | |
| ++resourceUse->second; | |
| else { | |
| success = false; | |
| } | |
| } | |
| //Not in the map yet, so put it | |
| else | |
| resourcesForCycle->second[resourceNum] = 1; | |
| } | |
| else { | |
| //Create a new map and put in our resource | |
| std::map<int, int> resourceMap; | |
| resourceMap[resourceNum] = 1; | |
| resourceNumPerCycle[cycle] = resourceMap; | |
| } | |
| if(!success) | |
| break; | |
| } | |
| if(!success) | |
| break; | |
| //Increase cycle | |
| currentCycle++; | |
| } | |
| if(!success) { | |
| int oldCycle = cycle; | |
| DEBUG(std::cerr << "Backtrack\n"); | |
| //Get resource usage for this instruction | |
| InstrRUsage rUsage = msi->getInstrRUsage(node->getInst()->getOpcode()); | |
| std::vector<std::vector<resourceId_t> > resources = rUsage.resourcesByCycle; | |
| //Loop over resources in each cycle and increments their usage count | |
| for(unsigned i=0; i < resources.size(); ++i) { | |
| if(oldCycle < currentCycle) { | |
| //Check if this resource is available for this cycle | |
| std::map<int, std::map<int,int> >::iterator resourcesForCycle = resourceNumPerCycle.find(oldCycle); | |
| for(unsigned j=0; j < resources[i].size(); ++j) { | |
| int resourceNum = resources[i][j]; | |
| //remove from map | |
| std::map<int, int>::iterator resourceUse = resourcesForCycle->second.find(resourceNum); | |
| //assert if not in the map.. since it should be! | |
| //assert(resourceUse != resourcesForCycle.end() && "Resource should be in map!"); | |
| --resourceUse->second; | |
| } | |
| } | |
| else | |
| break; | |
| oldCycle++; | |
| } | |
| return false; | |
| } | |
| return true; | |
| } | |
| bool MSSchedule::constructKernel(int II) { | |
| MSchedGraphNode *branchNode; | |
| int stageNum = (schedule.rbegin()->first)/ II; | |
| DEBUG(std::cerr << "Number of Stages: " << stageNum << "\n"); | |
| for(int index = 0; index < II; ++index) { | |
| int count = 0; | |
| for(int i = index; i <= (schedule.rbegin()->first); i+=II) { | |
| if(schedule.count(i)) { | |
| for(std::vector<MSchedGraphNode*>::iterator I = schedule[i].begin(), | |
| E = schedule[i].end(); I != E; ++I) { | |
| //Check if its a branch | |
| if((*I)->isBranch()) { | |
| branchNode = *I; | |
| assert(count == 0 && "Branch can not be from a previous iteration"); | |
| } | |
| else | |
| //FIXME: Check if the instructions in the earlier stage conflict | |
| kernel.push_back(std::make_pair(*I, count)); | |
| } | |
| } | |
| ++count; | |
| } | |
| } | |
| //Add Branch to the end | |
| kernel.push_back(std::make_pair(branchNode, 0)); | |
| return true; | |
| } | |
| void MSSchedule::print(std::ostream &os) const { | |
| os << "Schedule:\n"; | |
| for(schedule_const_iterator I = schedule.begin(), E = schedule.end(); I != E; ++I) { | |
| os << "Cycle: " << I->first << "\n"; | |
| for(std::vector<MSchedGraphNode*>::const_iterator node = I->second.begin(), nodeEnd = I->second.end(); node != nodeEnd; ++node) | |
| os << **node << "\n"; | |
| } | |
| os << "Kernel:\n"; | |
| for(std::vector<std::pair<MSchedGraphNode*, int> >::const_iterator I = kernel.begin(), | |
| E = kernel.end(); I != E; ++I) | |
| os << "Node: " << *(I->first) << " Stage: " << I->second << "\n"; | |
| } | |