types: clean up types, especially signed vs unsigned
[gem5.git] / src / cpu / inorder / resources / inst_buffer.cc
1 /*
2 * Copyright (c) 2007 MIPS Technologies, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Korey Sewell
29 *
30 */
31
32 #include <vector>
33 #include <list>
34 #include "arch/isa_traits.hh"
35 #include "cpu/inorder/pipeline_traits.hh"
36 #include "cpu/inorder/resources/inst_buffer.hh"
37 #include "cpu/inorder/cpu.hh"
38
39 using namespace std;
40 using namespace TheISA;
41 using namespace ThePipeline;
42
43 InstBuffer::InstBuffer(string res_name, int res_id, int res_width,
44 int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params)
45 : Resource(res_name, res_id, res_width, res_latency, _cpu)
46 { }
47
48 void
49 InstBuffer::regStats()
50 {
51 instsBypassed
52 .name(name() + ".instsBypassed")
53 .desc("Number of Instructions Bypassed.");
54
55 Resource::regStats();
56 }
57
58 void
59 InstBuffer::execute(int slot_idx)
60 {
61 ResReqPtr ib_req = reqMap[slot_idx];
62 DynInstPtr inst = ib_req->inst;
63 ThreadID tid = inst->readTid();
64 int stage_num = ib_req->getStageNum();
65
66 ib_req->fault = NoFault;
67
68 switch (ib_req->cmd)
69 {
70 case ScheduleOrBypass:
71 {
72 int next_stage = stage_num + 1;
73 int bypass_stage = stage_num + 2;
74 bool do_bypass = true;
75
76 if (!instList.empty()) {
77 DPRINTF(InOrderInstBuffer, "[sn:%i] cannot bypass stage %i because buffer isn't empty.\n",
78 inst->seqNum, next_stage);
79 do_bypass = false;
80 } else if(cpu->pipelineStage[bypass_stage]->isBlocked(tid)) {
81 DPRINTF(InOrderInstBuffer, "[sn:%i] cannot bypass stage %i because stage %i is blocking.\n",
82 inst->seqNum, next_stage);
83 do_bypass = false;
84 } else if(cpu->pipelineStage[bypass_stage]->stageBufferAvail() <= 0) {
85 DPRINTF(InOrderInstBuffer, "[sn:%i] cannot bypass stage %i because there is no room in "
86 "stage %i incoming stage buffer.\n", inst->seqNum, next_stage);
87 do_bypass = false;
88 }
89
90 if (!do_bypass) { // SCHEDULE USAGE OF BUFFER
91 DPRINTF(InOrderInstBuffer, "Scheduling [sn:%i] for buffer insertion in stage %i\n",
92 inst->seqNum, next_stage);
93
94 // Add to schedule: Insert into buffer in next stage
95 int stage_pri = ThePipeline::getNextPriority(inst, next_stage);
96
97 inst->resSched.push(new ScheduleEntry(next_stage, stage_pri, id,
98 InstBuffer::InsertInst));
99
100 // Add to schedule: Remove from buffer in next next (bypass) stage
101 stage_pri = ThePipeline::getNextPriority(inst, bypass_stage);
102
103 inst->resSched.push(new ScheduleEntry(bypass_stage, stage_pri, id,
104 InstBuffer::RemoveInst));
105 } else { // BYPASS BUFFER & NEXT STAGE
106 DPRINTF(InOrderInstBuffer, "Setting [sn:%i] to bypass stage %i and enter stage %i.\n",
107 inst->seqNum, next_stage, bypass_stage);
108 inst->setNextStage(bypass_stage);
109 instsBypassed++;
110 }
111
112 ib_req->done();
113 }
114 break;
115
116 case InsertInst:
117 {
118 bool inserted = false;
119
120 if (instList.size() < width) {
121 DPRINTF(InOrderInstBuffer, "[tid:%i]: Inserting [sn:%i] into buffer.\n",
122 tid, inst->seqNum);
123 insert(inst);
124 inserted = true;
125 } else {
126 DPRINTF(InOrderInstBuffer, "[tid:%i]: Denying [sn:%i] request because "
127 "buffer is full.\n", tid, inst->seqNum);
128
129
130 std::list<DynInstPtr>::iterator list_it = instList.begin();
131 std::list<DynInstPtr>::iterator list_end = instList.end();
132
133 while (list_it != list_end) {
134 DPRINTF(Resource,"Serving [tid:%i] [sn:%i].\n", (*list_it)->readTid(), (*list_it)->seqNum);
135 list_it++;
136 }
137 }
138
139 ib_req->done(inserted);
140 }
141 break;
142
143 case RemoveInst:
144 {
145 DPRINTF(InOrderInstBuffer, "[tid:%i]: Removing [sn:%i] from buffer.\n",
146 tid, inst->seqNum);
147 remove(inst);
148 ib_req->done();
149 }
150 break;
151
152 default:
153 fatal("Unrecognized command to %s", resName);
154 }
155
156 DPRINTF(InOrderInstBuffer, "Buffer now contains %i insts.\n", instList.size());
157 }
158
159 void
160 InstBuffer::insert(DynInstPtr inst)
161 {
162 instList.push_back(inst);
163 }
164
165 void
166 InstBuffer::remove(DynInstPtr inst)
167 {
168 std::list<DynInstPtr>::iterator list_it = instList.begin();
169 std::list<DynInstPtr>::iterator list_end = instList.end();
170
171 while (list_it != list_end) {
172 if((*list_it) == inst) {
173 instList.erase(list_it);
174 break;
175 }
176 list_it++;
177 }
178 }
179
180 void
181 InstBuffer::pop(ThreadID tid)
182 {
183 instList.pop_front();
184 }
185
186 ThePipeline::DynInstPtr
187 InstBuffer::top(ThreadID tid)
188 {
189 return instList.front();
190 }
191
192 void
193 InstBuffer::squash(DynInstPtr inst, int stage_num,
194 InstSeqNum squash_seq_num, ThreadID tid)
195 {
196 queue<list<DynInstPtr>::iterator> remove_list;
197 list<DynInstPtr>::iterator list_it = instList.begin();
198 list<DynInstPtr>::iterator list_end = instList.end();
199
200 // Collect All Instructions to be Removed in Remove List
201 while (list_it != list_end) {
202 if((*list_it)->readTid() == tid &&
203 (*list_it)->seqNum > squash_seq_num) {
204 (*list_it)->setSquashed();
205 remove_list.push(list_it);
206 }
207
208 list_it++;
209 }
210
211 // Removed Instructions from InstList & Clear Remove List
212 while (!remove_list.empty()) {
213 DPRINTF(InOrderInstBuffer, "[tid:%i]: Removing squashed [sn:%i] from buffer.\n",
214 tid, (*remove_list.front())->seqNum);
215 instList.erase(remove_list.front());
216 remove_list.pop();
217 }
218
219 Resource::squash(inst, stage_num, squash_seq_num, tid);
220 }