| //===-- 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 "llvm/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 = 0; |
| |
| 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"; |
| } |
| |