blob: c57cb5a3bdb9f73a50aa8537cd8d7e7945aa8e82 [file] [log] [blame]
Tanya Lattnerebac6452004-05-26 06:27:36 +00001//===-- MSSchedule.cpp Schedule ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//
11//
12//===----------------------------------------------------------------------===//
13#define DEBUG_TYPE "ModuloSched"
14
15#include "MSSchedule.h"
16#include "Support/Debug.h"
17#include "llvm/Target/TargetSchedInfo.h"
Tanya Lattnerebac6452004-05-26 06:27:36 +000018
19using namespace llvm;
20
21bool MSSchedule::insert(MSchedGraphNode *node, int cycle) {
22
23 //First, check if the cycle has a spot free to start
24 if(schedule.find(cycle) != schedule.end()) {
25 if (schedule[cycle].size() < numIssue) {
26 if(resourcesFree(node, cycle)) {
27 schedule[cycle].push_back(node);
28 DEBUG(std::cerr << "Found spot in map, and there is an issue slot\n");
29 return false;
30 }
31 }
32 }
33 //Not in the map yet so put it in
34 else {
35 if(resourcesFree(node,cycle)) {
36 std::vector<MSchedGraphNode*> nodes;
37 nodes.push_back(node);
38 schedule[cycle] = nodes;
39 DEBUG(std::cerr << "Nothing in map yet so taking an issue slot\n");
40 return false;
41 }
42 }
43
44 DEBUG(std::cerr << "All issue slots taken\n");
45 return true;
46
47}
48
49bool MSSchedule::resourcesFree(MSchedGraphNode *node, int cycle) {
50
51 //Get Resource usage for this instruction
Tanya Lattner0a88d2d2004-07-30 23:36:10 +000052 const TargetSchedInfo *msi = node->getParent()->getTarget()->getSchedInfo();
Tanya Lattnerebac6452004-05-26 06:27:36 +000053 int currentCycle = cycle;
54 bool success = true;
55
56 //Get resource usage for this instruction
Tanya Lattner0a88d2d2004-07-30 23:36:10 +000057 InstrRUsage rUsage = msi->getInstrRUsage(node->getInst()->getOpcode());
Tanya Lattnerebac6452004-05-26 06:27:36 +000058 std::vector<std::vector<resourceId_t> > resources = rUsage.resourcesByCycle;
59
60 //Loop over resources in each cycle and increments their usage count
61 for(unsigned i=0; i < resources.size(); ++i) {
62 for(unsigned j=0; j < resources[i].size(); ++j) {
63 int resourceNum = resources[i][j];
64
65 //Check if this resource is available for this cycle
66 std::map<int, std::map<int,int> >::iterator resourcesForCycle = resourceNumPerCycle.find(currentCycle);
67
68 //First check map of resources for this cycle
69 if(resourcesForCycle != resourceNumPerCycle.end()) {
70 //A map exists for this cycle, so lets check for the resource
71 std::map<int, int>::iterator resourceUse = resourcesForCycle->second.find(resourceNum);
72 if(resourceUse != resourcesForCycle->second.end()) {
73 //Check if there are enough of this resource and if so, increase count and move on
74 if(resourceUse->second < CPUResource::getCPUResource(resourceNum)->maxNumUsers)
75 ++resourceUse->second;
76 else {
77 success = false;
78 }
79 }
80 //Not in the map yet, so put it
81 else
82 resourcesForCycle->second[resourceNum] = 1;
83
84 }
85 else {
86 //Create a new map and put in our resource
87 std::map<int, int> resourceMap;
88 resourceMap[resourceNum] = 1;
89 resourceNumPerCycle[cycle] = resourceMap;
90 }
91 if(!success)
92 break;
93 }
94 if(!success)
95 break;
96 //Increase cycle
97 currentCycle++;
98 }
99
100 if(!success) {
101 int oldCycle = cycle;
102 DEBUG(std::cerr << "Backtrack\n");
103 //Get resource usage for this instruction
Tanya Lattner0a88d2d2004-07-30 23:36:10 +0000104 InstrRUsage rUsage = msi->getInstrRUsage(node->getInst()->getOpcode());
Tanya Lattnerebac6452004-05-26 06:27:36 +0000105 std::vector<std::vector<resourceId_t> > resources = rUsage.resourcesByCycle;
106
107 //Loop over resources in each cycle and increments their usage count
108 for(unsigned i=0; i < resources.size(); ++i) {
109 if(oldCycle < currentCycle) {
110
111 //Check if this resource is available for this cycle
112 std::map<int, std::map<int,int> >::iterator resourcesForCycle = resourceNumPerCycle.find(oldCycle);
113
114 for(unsigned j=0; j < resources[i].size(); ++j) {
115 int resourceNum = resources[i][j];
116 //remove from map
117 std::map<int, int>::iterator resourceUse = resourcesForCycle->second.find(resourceNum);
118 //assert if not in the map.. since it should be!
119 //assert(resourceUse != resourcesForCycle.end() && "Resource should be in map!");
120 --resourceUse->second;
121 }
122 }
123 else
124 break;
125 oldCycle++;
126 }
127 return false;
128
129 }
130
131 return true;
132
133}
134
135bool MSSchedule::constructKernel(int II) {
Reid Spencerb814e2d2004-08-07 15:19:31 +0000136 MSchedGraphNode *branchNode = 0;
Tanya Lattnerebac6452004-05-26 06:27:36 +0000137
138 int stageNum = (schedule.rbegin()->first)/ II;
139 DEBUG(std::cerr << "Number of Stages: " << stageNum << "\n");
140
141 for(int index = 0; index < II; ++index) {
142 int count = 0;
143 for(int i = index; i <= (schedule.rbegin()->first); i+=II) {
144 if(schedule.count(i)) {
145 for(std::vector<MSchedGraphNode*>::iterator I = schedule[i].begin(),
146 E = schedule[i].end(); I != E; ++I) {
147 //Check if its a branch
148 if((*I)->isBranch()) {
149 branchNode = *I;
150 assert(count == 0 && "Branch can not be from a previous iteration");
151 }
152 else
153 //FIXME: Check if the instructions in the earlier stage conflict
154 kernel.push_back(std::make_pair(*I, count));
155 }
156 }
157 ++count;
158 }
159 }
160
161 //Add Branch to the end
162 kernel.push_back(std::make_pair(branchNode, 0));
163
164 return true;
165}
166
167
168void MSSchedule::print(std::ostream &os) const {
169 os << "Schedule:\n";
170
171 for(schedule_const_iterator I = schedule.begin(), E = schedule.end(); I != E; ++I) {
172 os << "Cycle: " << I->first << "\n";
173 for(std::vector<MSchedGraphNode*>::const_iterator node = I->second.begin(), nodeEnd = I->second.end(); node != nodeEnd; ++node)
174 os << **node << "\n";
175 }
176
177 os << "Kernel:\n";
178 for(std::vector<std::pair<MSchedGraphNode*, int> >::const_iterator I = kernel.begin(),
179 E = kernel.end(); I != E; ++I)
180 os << "Node: " << *(I->first) << " Stage: " << I->second << "\n";
181}
182