cpu: Delete authors lists from the cpu directory.
[gem5.git] / src / cpu / minor / cpu.cc
1 /*
2 * Copyright (c) 2012-2014, 2017 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include "cpu/minor/cpu.hh"
39
40 #include "arch/utility.hh"
41 #include "cpu/minor/dyn_inst.hh"
42 #include "cpu/minor/fetch1.hh"
43 #include "cpu/minor/pipeline.hh"
44 #include "debug/Drain.hh"
45 #include "debug/MinorCPU.hh"
46 #include "debug/Quiesce.hh"
47
48 MinorCPU::MinorCPU(MinorCPUParams *params) :
49 BaseCPU(params),
50 threadPolicy(params->threadPolicy)
51 {
52 /* This is only written for one thread at the moment */
53 Minor::MinorThread *thread;
54
55 for (ThreadID i = 0; i < numThreads; i++) {
56 if (FullSystem) {
57 thread = new Minor::MinorThread(this, i, params->system,
58 params->itb, params->dtb, params->isa[i]);
59 thread->setStatus(ThreadContext::Halted);
60 } else {
61 thread = new Minor::MinorThread(this, i, params->system,
62 params->workload[i], params->itb, params->dtb,
63 params->isa[i]);
64 }
65
66 threads.push_back(thread);
67 ThreadContext *tc = thread->getTC();
68 threadContexts.push_back(tc);
69 }
70
71
72 if (params->checker) {
73 fatal("The Minor model doesn't support checking (yet)\n");
74 }
75
76 Minor::MinorDynInst::init();
77
78 pipeline = new Minor::Pipeline(*this, *params);
79 activityRecorder = pipeline->getActivityRecorder();
80 }
81
82 MinorCPU::~MinorCPU()
83 {
84 delete pipeline;
85
86 for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) {
87 delete threads[thread_id];
88 }
89 }
90
91 void
92 MinorCPU::init()
93 {
94 BaseCPU::init();
95
96 if (!params()->switched_out &&
97 system->getMemoryMode() != Enums::timing)
98 {
99 fatal("The Minor CPU requires the memory system to be in "
100 "'timing' mode.\n");
101 }
102
103 /* Initialise the ThreadContext's memory proxies */
104 for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) {
105 ThreadContext *tc = getContext(thread_id);
106
107 tc->initMemProxies(tc);
108 }
109 }
110
111 /** Stats interface from SimObject (by way of BaseCPU) */
112 void
113 MinorCPU::regStats()
114 {
115 BaseCPU::regStats();
116 stats.regStats(name(), *this);
117 pipeline->regStats();
118 }
119
120 void
121 MinorCPU::serializeThread(CheckpointOut &cp, ThreadID thread_id) const
122 {
123 threads[thread_id]->serialize(cp);
124 }
125
126 void
127 MinorCPU::unserializeThread(CheckpointIn &cp, ThreadID thread_id)
128 {
129 threads[thread_id]->unserialize(cp);
130 }
131
132 void
133 MinorCPU::serialize(CheckpointOut &cp) const
134 {
135 pipeline->serialize(cp);
136 BaseCPU::serialize(cp);
137 }
138
139 void
140 MinorCPU::unserialize(CheckpointIn &cp)
141 {
142 pipeline->unserialize(cp);
143 BaseCPU::unserialize(cp);
144 }
145
146 Addr
147 MinorCPU::dbg_vtophys(Addr addr)
148 {
149 /* Note that this gives you the translation for thread 0 */
150 panic("No implementation for vtophy\n");
151
152 return 0;
153 }
154
155 void
156 MinorCPU::wakeup(ThreadID tid)
157 {
158 DPRINTF(Drain, "[tid:%d] MinorCPU wakeup\n", tid);
159 assert(tid < numThreads);
160
161 if (threads[tid]->status() == ThreadContext::Suspended) {
162 threads[tid]->activate();
163 }
164 }
165
166 void
167 MinorCPU::startup()
168 {
169 DPRINTF(MinorCPU, "MinorCPU startup\n");
170
171 BaseCPU::startup();
172
173 for (ThreadID tid = 0; tid < numThreads; tid++) {
174 threads[tid]->startup();
175 pipeline->wakeupFetch(tid);
176 }
177 }
178
179 DrainState
180 MinorCPU::drain()
181 {
182 // Deschedule any power gating event (if any)
183 deschedulePowerGatingEvent();
184
185 if (switchedOut()) {
186 DPRINTF(Drain, "Minor CPU switched out, draining not needed.\n");
187 return DrainState::Drained;
188 }
189
190 DPRINTF(Drain, "MinorCPU drain\n");
191
192 /* Need to suspend all threads and wait for Execute to idle.
193 * Tell Fetch1 not to fetch */
194 if (pipeline->drain()) {
195 DPRINTF(Drain, "MinorCPU drained\n");
196 return DrainState::Drained;
197 } else {
198 DPRINTF(Drain, "MinorCPU not finished draining\n");
199 return DrainState::Draining;
200 }
201 }
202
203 void
204 MinorCPU::signalDrainDone()
205 {
206 DPRINTF(Drain, "MinorCPU drain done\n");
207 Drainable::signalDrainDone();
208 }
209
210 void
211 MinorCPU::drainResume()
212 {
213 /* When taking over from another cpu make sure lastStopped
214 * is reset since it might have not been defined previously
215 * and might lead to a stats corruption */
216 pipeline->resetLastStopped();
217
218 if (switchedOut()) {
219 DPRINTF(Drain, "drainResume while switched out. Ignoring\n");
220 return;
221 }
222
223 DPRINTF(Drain, "MinorCPU drainResume\n");
224
225 if (!system->isTimingMode()) {
226 fatal("The Minor CPU requires the memory system to be in "
227 "'timing' mode.\n");
228 }
229
230 for (ThreadID tid = 0; tid < numThreads; tid++){
231 wakeup(tid);
232 }
233
234 pipeline->drainResume();
235
236 // Reschedule any power gating event (if any)
237 schedulePowerGatingEvent();
238 }
239
240 void
241 MinorCPU::memWriteback()
242 {
243 DPRINTF(Drain, "MinorCPU memWriteback\n");
244 }
245
246 void
247 MinorCPU::switchOut()
248 {
249 DPRINTF(MinorCPU, "MinorCPU switchOut\n");
250
251 assert(!switchedOut());
252 BaseCPU::switchOut();
253
254 /* Check that the CPU is drained? */
255 activityRecorder->reset();
256 }
257
258 void
259 MinorCPU::takeOverFrom(BaseCPU *old_cpu)
260 {
261 DPRINTF(MinorCPU, "MinorCPU takeOverFrom\n");
262
263 BaseCPU::takeOverFrom(old_cpu);
264 }
265
266 void
267 MinorCPU::activateContext(ThreadID thread_id)
268 {
269 DPRINTF(MinorCPU, "ActivateContext thread: %d\n", thread_id);
270
271 /* Do some cycle accounting. lastStopped is reset to stop the
272 * wakeup call on the pipeline from adding the quiesce period
273 * to BaseCPU::numCycles */
274 stats.quiesceCycles += pipeline->cyclesSinceLastStopped();
275 pipeline->resetLastStopped();
276
277 /* Wake up the thread, wakeup the pipeline tick */
278 threads[thread_id]->activate();
279 wakeupOnEvent(Minor::Pipeline::CPUStageId);
280 pipeline->wakeupFetch(thread_id);
281
282 BaseCPU::activateContext(thread_id);
283 }
284
285 void
286 MinorCPU::suspendContext(ThreadID thread_id)
287 {
288 DPRINTF(MinorCPU, "SuspendContext %d\n", thread_id);
289
290 threads[thread_id]->suspend();
291
292 BaseCPU::suspendContext(thread_id);
293 }
294
295 void
296 MinorCPU::wakeupOnEvent(unsigned int stage_id)
297 {
298 DPRINTF(Quiesce, "Event wakeup from stage %d\n", stage_id);
299
300 /* Mark that some activity has taken place and start the pipeline */
301 activityRecorder->activateStage(stage_id);
302 pipeline->start();
303 }
304
305 MinorCPU *
306 MinorCPUParams::create()
307 {
308 return new MinorCPU(this);
309 }
310
311 Port &
312 MinorCPU::getInstPort()
313 {
314 return pipeline->getInstPort();
315 }
316
317 Port &
318 MinorCPU::getDataPort()
319 {
320 return pipeline->getDataPort();
321 }
322
323 Counter
324 MinorCPU::totalInsts() const
325 {
326 Counter ret = 0;
327
328 for (auto i = threads.begin(); i != threads.end(); i ++)
329 ret += (*i)->numInst;
330
331 return ret;
332 }
333
334 Counter
335 MinorCPU::totalOps() const
336 {
337 Counter ret = 0;
338
339 for (auto i = threads.begin(); i != threads.end(); i ++)
340 ret += (*i)->numOp;
341
342 return ret;
343 }