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