cpu.cc (10407:a9023811bf9e) cpu.cc (10905:a6ca6831e775)
1/*
2 * Copyright (c) 2012-2014 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 * Authors: Andrew Bardsley
38 */
39
40#include "arch/utility.hh"
41#include "cpu/minor/cpu.hh"
42#include "cpu/minor/dyn_inst.hh"
43#include "cpu/minor/fetch1.hh"
44#include "cpu/minor/pipeline.hh"
45#include "debug/Drain.hh"
46#include "debug/MinorCPU.hh"
47#include "debug/Quiesce.hh"
48
49MinorCPU::MinorCPU(MinorCPUParams *params) :
50 BaseCPU(params),
51 drainManager(NULL)
52{
53 /* This is only written for one thread at the moment */
54 Minor::MinorThread *thread;
55
56 if (FullSystem) {
57 thread = new Minor::MinorThread(this, 0, params->system, params->itb,
58 params->dtb, params->isa[0]);
59 } else {
60 /* thread_id 0 */
61 thread = new Minor::MinorThread(this, 0, params->system,
62 params->workload[0], params->itb, params->dtb, params->isa[0]);
63 }
64
65 threads.push_back(thread);
66
67 thread->setStatus(ThreadContext::Halted);
68
69 ThreadContext *tc = thread->getTC();
70
71 if (params->checker) {
72 fatal("The Minor model doesn't support checking (yet)\n");
73 }
74
75 threadContexts.push_back(tc);
76
77 Minor::MinorDynInst::init();
78
79 pipeline = new Minor::Pipeline(*this, *params);
80 activityRecorder = pipeline->getActivityRecorder();
81}
82
83MinorCPU::~MinorCPU()
84{
85 delete pipeline;
86
87 for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) {
88 delete threads[thread_id];
89 }
90}
91
92void
93MinorCPU::init()
94{
95 BaseCPU::init();
96
97 if (!params()->switched_out &&
98 system->getMemoryMode() != Enums::timing)
99 {
100 fatal("The Minor CPU requires the memory system to be in "
101 "'timing' mode.\n");
102 }
103
104 /* Initialise the ThreadContext's memory proxies */
105 for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) {
106 ThreadContext *tc = getContext(thread_id);
107
108 tc->initMemProxies(tc);
109 }
110
111 /* Initialise CPUs (== threads in the ISA) */
112 if (FullSystem && !params()->switched_out) {
113 for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++)
114 {
115 ThreadContext *tc = getContext(thread_id);
116
117 /* Initialize CPU, including PC */
118 TheISA::initCPU(tc, cpuId());
119 }
120 }
121}
122
123/** Stats interface from SimObject (by way of BaseCPU) */
124void
125MinorCPU::regStats()
126{
127 BaseCPU::regStats();
128 stats.regStats(name(), *this);
129 pipeline->regStats();
130}
131
132void
1/*
2 * Copyright (c) 2012-2014 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 * Authors: Andrew Bardsley
38 */
39
40#include "arch/utility.hh"
41#include "cpu/minor/cpu.hh"
42#include "cpu/minor/dyn_inst.hh"
43#include "cpu/minor/fetch1.hh"
44#include "cpu/minor/pipeline.hh"
45#include "debug/Drain.hh"
46#include "debug/MinorCPU.hh"
47#include "debug/Quiesce.hh"
48
49MinorCPU::MinorCPU(MinorCPUParams *params) :
50 BaseCPU(params),
51 drainManager(NULL)
52{
53 /* This is only written for one thread at the moment */
54 Minor::MinorThread *thread;
55
56 if (FullSystem) {
57 thread = new Minor::MinorThread(this, 0, params->system, params->itb,
58 params->dtb, params->isa[0]);
59 } else {
60 /* thread_id 0 */
61 thread = new Minor::MinorThread(this, 0, params->system,
62 params->workload[0], params->itb, params->dtb, params->isa[0]);
63 }
64
65 threads.push_back(thread);
66
67 thread->setStatus(ThreadContext::Halted);
68
69 ThreadContext *tc = thread->getTC();
70
71 if (params->checker) {
72 fatal("The Minor model doesn't support checking (yet)\n");
73 }
74
75 threadContexts.push_back(tc);
76
77 Minor::MinorDynInst::init();
78
79 pipeline = new Minor::Pipeline(*this, *params);
80 activityRecorder = pipeline->getActivityRecorder();
81}
82
83MinorCPU::~MinorCPU()
84{
85 delete pipeline;
86
87 for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) {
88 delete threads[thread_id];
89 }
90}
91
92void
93MinorCPU::init()
94{
95 BaseCPU::init();
96
97 if (!params()->switched_out &&
98 system->getMemoryMode() != Enums::timing)
99 {
100 fatal("The Minor CPU requires the memory system to be in "
101 "'timing' mode.\n");
102 }
103
104 /* Initialise the ThreadContext's memory proxies */
105 for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) {
106 ThreadContext *tc = getContext(thread_id);
107
108 tc->initMemProxies(tc);
109 }
110
111 /* Initialise CPUs (== threads in the ISA) */
112 if (FullSystem && !params()->switched_out) {
113 for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++)
114 {
115 ThreadContext *tc = getContext(thread_id);
116
117 /* Initialize CPU, including PC */
118 TheISA::initCPU(tc, cpuId());
119 }
120 }
121}
122
123/** Stats interface from SimObject (by way of BaseCPU) */
124void
125MinorCPU::regStats()
126{
127 BaseCPU::regStats();
128 stats.regStats(name(), *this);
129 pipeline->regStats();
130}
131
132void
133MinorCPU::serializeThread(std::ostream &os, ThreadID thread_id)
133MinorCPU::serializeThread(CheckpointOut &cp, ThreadID thread_id) const
134{
134{
135 threads[thread_id]->serialize(os);
135 threads[thread_id]->serialize(cp);
136}
137
138void
136}
137
138void
139MinorCPU::unserializeThread(Checkpoint *cp, const std::string &section,
140 ThreadID thread_id)
139MinorCPU::unserializeThread(CheckpointIn &cp, ThreadID thread_id)
141{
142 if (thread_id != 0)
143 fatal("Trying to load more than one thread into a MinorCPU\n");
144
140{
141 if (thread_id != 0)
142 fatal("Trying to load more than one thread into a MinorCPU\n");
143
145 threads[thread_id]->unserialize(cp, section);
144 threads[thread_id]->unserialize(cp);
146}
147
148void
145}
146
147void
149MinorCPU::serialize(std::ostream &os)
148MinorCPU::serialize(CheckpointOut &cp) const
150{
149{
151 pipeline->serialize(os);
152 BaseCPU::serialize(os);
150 pipeline->serialize(cp);
151 BaseCPU::serialize(cp);
153}
154
155void
152}
153
154void
156MinorCPU::unserialize(Checkpoint *cp, const std::string &section)
155MinorCPU::unserialize(CheckpointIn &cp)
157{
156{
158 pipeline->unserialize(cp, section);
159 BaseCPU::unserialize(cp, section);
157 pipeline->unserialize(cp);
158 BaseCPU::unserialize(cp);
160}
161
162Addr
163MinorCPU::dbg_vtophys(Addr addr)
164{
165 /* Note that this gives you the translation for thread 0 */
166 panic("No implementation for vtophy\n");
167
168 return 0;
169}
170
171void
172MinorCPU::wakeup()
173{
174 DPRINTF(Drain, "MinorCPU wakeup\n");
175
176 for (auto i = threads.begin(); i != threads.end(); i ++) {
177 if ((*i)->status() == ThreadContext::Suspended)
178 (*i)->activate();
179 }
180
181 DPRINTF(Drain,"Suspended Processor awoke\n");
182}
183
184void
185MinorCPU::startup()
186{
187 DPRINTF(MinorCPU, "MinorCPU startup\n");
188
189 BaseCPU::startup();
190
191 for (auto i = threads.begin(); i != threads.end(); i ++)
192 (*i)->startup();
193
194 /* CPU state setup, activate initial context */
195 activateContext(0);
196}
197
198unsigned int
199MinorCPU::drain(DrainManager *drain_manager)
200{
201 DPRINTF(Drain, "MinorCPU drain\n");
202
203 drainManager = drain_manager;
204
205 /* Need to suspend all threads and wait for Execute to idle.
206 * Tell Fetch1 not to fetch */
207 unsigned int ret = pipeline->drain(drain_manager);
208
209 if (ret == 0)
210 DPRINTF(Drain, "MinorCPU drained\n");
211 else
212 DPRINTF(Drain, "MinorCPU not finished draining\n");
213
214 return ret;
215}
216
217void
218MinorCPU::signalDrainDone()
219{
220 DPRINTF(Drain, "MinorCPU drain done\n");
221 setDrainState(Drainable::Drained);
222 drainManager->signalDrainDone();
223 drainManager = NULL;
224}
225
226void
227MinorCPU::drainResume()
228{
229 assert(getDrainState() == Drainable::Drained ||
230 getDrainState() == Drainable::Running);
231
232 if (switchedOut()) {
233 DPRINTF(Drain, "drainResume while switched out. Ignoring\n");
234 return;
235 }
236
237 DPRINTF(Drain, "MinorCPU drainResume\n");
238
239 if (!system->isTimingMode()) {
240 fatal("The Minor CPU requires the memory system to be in "
241 "'timing' mode.\n");
242 }
243
244 wakeup();
245 pipeline->drainResume();
246
247 setDrainState(Drainable::Running);
248}
249
250void
251MinorCPU::memWriteback()
252{
253 DPRINTF(Drain, "MinorCPU memWriteback\n");
254}
255
256void
257MinorCPU::switchOut()
258{
259 DPRINTF(MinorCPU, "MinorCPU switchOut\n");
260
261 assert(!switchedOut());
262 BaseCPU::switchOut();
263
264 /* Check that the CPU is drained? */
265 activityRecorder->reset();
266}
267
268void
269MinorCPU::takeOverFrom(BaseCPU *old_cpu)
270{
271 DPRINTF(MinorCPU, "MinorCPU takeOverFrom\n");
272
273 BaseCPU::takeOverFrom(old_cpu);
274
275 /* Don't think I need to do anything here */
276}
277
278void
279MinorCPU::activateContext(ThreadID thread_id)
280{
281 DPRINTF(MinorCPU, "ActivateContext thread: %d", thread_id);
282
283 /* Do some cycle accounting. lastStopped is reset to stop the
284 * wakeup call on the pipeline from adding the quiesce period
285 * to BaseCPU::numCycles */
286 stats.quiesceCycles += pipeline->cyclesSinceLastStopped();
287 pipeline->resetLastStopped();
288
289 /* Wake up the thread, wakeup the pipeline tick */
290 threads[thread_id]->activate();
291 wakeupOnEvent(Minor::Pipeline::CPUStageId);
292 pipeline->wakeupFetch();
293}
294
295void
296MinorCPU::suspendContext(ThreadID thread_id)
297{
298 DPRINTF(MinorCPU, "SuspendContext %d\n", thread_id);
299
300 threads[thread_id]->suspend();
301}
302
303void
304MinorCPU::wakeupOnEvent(unsigned int stage_id)
305{
306 DPRINTF(Quiesce, "Event wakeup from stage %d\n", stage_id);
307
308 /* Mark that some activity has taken place and start the pipeline */
309 activityRecorder->activateStage(stage_id);
310 pipeline->start();
311}
312
313MinorCPU *
314MinorCPUParams::create()
315{
316 numThreads = 1;
317 if (!FullSystem && workload.size() != 1)
318 panic("only one workload allowed");
319 return new MinorCPU(this);
320}
321
322MasterPort &MinorCPU::getInstPort()
323{
324 return pipeline->getInstPort();
325}
326
327MasterPort &MinorCPU::getDataPort()
328{
329 return pipeline->getDataPort();
330}
331
332Counter
333MinorCPU::totalInsts() const
334{
335 Counter ret = 0;
336
337 for (auto i = threads.begin(); i != threads.end(); i ++)
338 ret += (*i)->numInst;
339
340 return ret;
341}
342
343Counter
344MinorCPU::totalOps() const
345{
346 Counter ret = 0;
347
348 for (auto i = threads.begin(); i != threads.end(); i ++)
349 ret += (*i)->numOp;
350
351 return ret;
352}
159}
160
161Addr
162MinorCPU::dbg_vtophys(Addr addr)
163{
164 /* Note that this gives you the translation for thread 0 */
165 panic("No implementation for vtophy\n");
166
167 return 0;
168}
169
170void
171MinorCPU::wakeup()
172{
173 DPRINTF(Drain, "MinorCPU wakeup\n");
174
175 for (auto i = threads.begin(); i != threads.end(); i ++) {
176 if ((*i)->status() == ThreadContext::Suspended)
177 (*i)->activate();
178 }
179
180 DPRINTF(Drain,"Suspended Processor awoke\n");
181}
182
183void
184MinorCPU::startup()
185{
186 DPRINTF(MinorCPU, "MinorCPU startup\n");
187
188 BaseCPU::startup();
189
190 for (auto i = threads.begin(); i != threads.end(); i ++)
191 (*i)->startup();
192
193 /* CPU state setup, activate initial context */
194 activateContext(0);
195}
196
197unsigned int
198MinorCPU::drain(DrainManager *drain_manager)
199{
200 DPRINTF(Drain, "MinorCPU drain\n");
201
202 drainManager = drain_manager;
203
204 /* Need to suspend all threads and wait for Execute to idle.
205 * Tell Fetch1 not to fetch */
206 unsigned int ret = pipeline->drain(drain_manager);
207
208 if (ret == 0)
209 DPRINTF(Drain, "MinorCPU drained\n");
210 else
211 DPRINTF(Drain, "MinorCPU not finished draining\n");
212
213 return ret;
214}
215
216void
217MinorCPU::signalDrainDone()
218{
219 DPRINTF(Drain, "MinorCPU drain done\n");
220 setDrainState(Drainable::Drained);
221 drainManager->signalDrainDone();
222 drainManager = NULL;
223}
224
225void
226MinorCPU::drainResume()
227{
228 assert(getDrainState() == Drainable::Drained ||
229 getDrainState() == Drainable::Running);
230
231 if (switchedOut()) {
232 DPRINTF(Drain, "drainResume while switched out. Ignoring\n");
233 return;
234 }
235
236 DPRINTF(Drain, "MinorCPU drainResume\n");
237
238 if (!system->isTimingMode()) {
239 fatal("The Minor CPU requires the memory system to be in "
240 "'timing' mode.\n");
241 }
242
243 wakeup();
244 pipeline->drainResume();
245
246 setDrainState(Drainable::Running);
247}
248
249void
250MinorCPU::memWriteback()
251{
252 DPRINTF(Drain, "MinorCPU memWriteback\n");
253}
254
255void
256MinorCPU::switchOut()
257{
258 DPRINTF(MinorCPU, "MinorCPU switchOut\n");
259
260 assert(!switchedOut());
261 BaseCPU::switchOut();
262
263 /* Check that the CPU is drained? */
264 activityRecorder->reset();
265}
266
267void
268MinorCPU::takeOverFrom(BaseCPU *old_cpu)
269{
270 DPRINTF(MinorCPU, "MinorCPU takeOverFrom\n");
271
272 BaseCPU::takeOverFrom(old_cpu);
273
274 /* Don't think I need to do anything here */
275}
276
277void
278MinorCPU::activateContext(ThreadID thread_id)
279{
280 DPRINTF(MinorCPU, "ActivateContext thread: %d", thread_id);
281
282 /* Do some cycle accounting. lastStopped is reset to stop the
283 * wakeup call on the pipeline from adding the quiesce period
284 * to BaseCPU::numCycles */
285 stats.quiesceCycles += pipeline->cyclesSinceLastStopped();
286 pipeline->resetLastStopped();
287
288 /* Wake up the thread, wakeup the pipeline tick */
289 threads[thread_id]->activate();
290 wakeupOnEvent(Minor::Pipeline::CPUStageId);
291 pipeline->wakeupFetch();
292}
293
294void
295MinorCPU::suspendContext(ThreadID thread_id)
296{
297 DPRINTF(MinorCPU, "SuspendContext %d\n", thread_id);
298
299 threads[thread_id]->suspend();
300}
301
302void
303MinorCPU::wakeupOnEvent(unsigned int stage_id)
304{
305 DPRINTF(Quiesce, "Event wakeup from stage %d\n", stage_id);
306
307 /* Mark that some activity has taken place and start the pipeline */
308 activityRecorder->activateStage(stage_id);
309 pipeline->start();
310}
311
312MinorCPU *
313MinorCPUParams::create()
314{
315 numThreads = 1;
316 if (!FullSystem && workload.size() != 1)
317 panic("only one workload allowed");
318 return new MinorCPU(this);
319}
320
321MasterPort &MinorCPU::getInstPort()
322{
323 return pipeline->getInstPort();
324}
325
326MasterPort &MinorCPU::getDataPort()
327{
328 return pipeline->getDataPort();
329}
330
331Counter
332MinorCPU::totalInsts() const
333{
334 Counter ret = 0;
335
336 for (auto i = threads.begin(); i != threads.end(); i ++)
337 ret += (*i)->numInst;
338
339 return ret;
340}
341
342Counter
343MinorCPU::totalOps() const
344{
345 Counter ret = 0;
346
347 for (auto i = threads.begin(); i != threads.end(); i ++)
348 ret += (*i)->numOp;
349
350 return ret;
351}