eba7273c3cebae0f212304bc3bd303e807dcfb6a
2 * Copyright (c) 2010 ARM Limited
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.
14 * Copyright (c) 2003-2006 The Regents of The University of Michigan
15 * All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 * Authors: Nathan Binkert
50 #include "arch/vtophys.hh"
51 #include "base/debug.hh"
52 #include "config/full_system.hh"
53 #include "config/the_isa.hh"
54 #include "cpu/base.hh"
55 #include "cpu/quiesce_event.hh"
56 #include "cpu/thread_context.hh"
57 #include "debug/Loader.hh"
58 #include "debug/Quiesce.hh"
59 #include "debug/WorkItems.hh"
60 #include "params/BaseCPU.hh"
61 #include "sim/pseudo_inst.hh"
62 #include "sim/serialize.hh"
63 #include "sim/sim_events.hh"
64 #include "sim/sim_exit.hh"
65 #include "sim/stat_control.hh"
66 #include "sim/stats.hh"
67 #include "sim/system.hh"
70 #include "arch/kernel_stats.hh"
71 #include "sim/vptr.hh"
76 using namespace Stats
;
77 using namespace TheISA
;
79 namespace PseudoInst
{
84 arm(ThreadContext
*tc
)
86 if (tc
->getKernelStats())
87 tc
->getKernelStats()->arm();
91 quiesce(ThreadContext
*tc
)
93 if (!tc
->getCpuPtr()->params()->do_quiesce
)
96 DPRINTF(Quiesce
, "%s: quiesce()\n", tc
->getCpuPtr()->name());
99 if (tc
->getKernelStats())
100 tc
->getKernelStats()->quiesce();
104 quiesceSkip(ThreadContext
*tc
)
106 BaseCPU
*cpu
= tc
->getCpuPtr();
108 if (!cpu
->params()->do_quiesce
)
111 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
113 Tick resume
= curTick() + 1;
115 cpu
->reschedule(quiesceEvent
, resume
, true);
117 DPRINTF(Quiesce
, "%s: quiesceSkip() until %d\n",
118 cpu
->name(), resume
);
121 if (tc
->getKernelStats())
122 tc
->getKernelStats()->quiesce();
126 quiesceNs(ThreadContext
*tc
, uint64_t ns
)
128 BaseCPU
*cpu
= tc
->getCpuPtr();
130 if (!cpu
->params()->do_quiesce
|| ns
== 0)
133 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
135 Tick resume
= curTick() + SimClock::Int::ns
* ns
;
137 cpu
->reschedule(quiesceEvent
, resume
, true);
139 DPRINTF(Quiesce
, "%s: quiesceNs(%d) until %d\n",
140 cpu
->name(), ns
, resume
);
143 if (tc
->getKernelStats())
144 tc
->getKernelStats()->quiesce();
148 quiesceCycles(ThreadContext
*tc
, uint64_t cycles
)
150 BaseCPU
*cpu
= tc
->getCpuPtr();
152 if (!cpu
->params()->do_quiesce
|| cycles
== 0)
155 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
157 Tick resume
= curTick() + cpu
->ticks(cycles
);
159 cpu
->reschedule(quiesceEvent
, resume
, true);
161 DPRINTF(Quiesce
, "%s: quiesceCycles(%d) until %d\n",
162 cpu
->name(), cycles
, resume
);
165 if (tc
->getKernelStats())
166 tc
->getKernelStats()->quiesce();
170 quiesceTime(ThreadContext
*tc
)
172 return (tc
->readLastActivate() - tc
->readLastSuspend()) /
179 rpns(ThreadContext
*tc
)
181 return curTick() / SimClock::Int::ns
;
185 wakeCPU(ThreadContext
*tc
, uint64_t cpuid
)
187 System
*sys
= tc
->getSystemPtr();
188 ThreadContext
*other_tc
= sys
->threadContexts
[cpuid
];
189 if (other_tc
->status() == ThreadContext::Suspended
)
190 other_tc
->activate();
194 m5exit(ThreadContext
*tc
, Tick delay
)
196 Tick when
= curTick() + delay
* SimClock::Int::ns
;
197 exitSimLoop("m5_exit instruction encountered", 0, when
);
203 loadsymbol(ThreadContext
*tc
)
205 const string
&filename
= tc
->getCpuPtr()->system
->params()->symbolfile
;
206 if (filename
.empty()) {
211 ifstream
file(filename
.c_str());
214 fatal("file error: Can't open symbol table file %s\n", filename
);
216 while (!file
.eof()) {
217 getline(file
, buffer
);
222 string::size_type idx
= buffer
.find(' ');
223 if (idx
== string::npos
)
226 string address
= "0x" + buffer
.substr(0, idx
);
231 // Skip over letter and space
232 string symbol
= buffer
.substr(idx
+ 3);
238 if (!to_number(address
, addr
))
241 if (!tc
->getSystemPtr()->kernelSymtab
->insert(addr
, symbol
))
245 DPRINTF(Loader
, "Loaded symbol: %s @ %#llx\n", symbol
, addr
);
251 addsymbol(ThreadContext
*tc
, Addr addr
, Addr symbolAddr
)
254 CopyStringOut(tc
, symb
, symbolAddr
, 100);
255 std::string
symbol(symb
);
257 DPRINTF(Loader
, "Loaded symbol: %s @ %#llx\n", symbol
, addr
);
259 tc
->getSystemPtr()->kernelSymtab
->insert(addr
,symbol
);
260 debugSymbolTable
->insert(addr
,symbol
);
267 resetstats(ThreadContext
*tc
, Tick delay
, Tick period
)
269 if (!tc
->getCpuPtr()->params()->do_statistics_insts
)
273 Tick when
= curTick() + delay
* SimClock::Int::ns
;
274 Tick repeat
= period
* SimClock::Int::ns
;
276 Stats::schedStatEvent(false, true, when
, repeat
);
280 dumpstats(ThreadContext
*tc
, Tick delay
, Tick period
)
282 if (!tc
->getCpuPtr()->params()->do_statistics_insts
)
286 Tick when
= curTick() + delay
* SimClock::Int::ns
;
287 Tick repeat
= period
* SimClock::Int::ns
;
289 Stats::schedStatEvent(true, false, when
, repeat
);
293 dumpresetstats(ThreadContext
*tc
, Tick delay
, Tick period
)
295 if (!tc
->getCpuPtr()->params()->do_statistics_insts
)
299 Tick when
= curTick() + delay
* SimClock::Int::ns
;
300 Tick repeat
= period
* SimClock::Int::ns
;
302 Stats::schedStatEvent(true, true, when
, repeat
);
306 m5checkpoint(ThreadContext
*tc
, Tick delay
, Tick period
)
308 if (!tc
->getCpuPtr()->params()->do_checkpoint_insts
)
311 Tick when
= curTick() + delay
* SimClock::Int::ns
;
312 Tick repeat
= period
* SimClock::Int::ns
;
314 exitSimLoop("checkpoint", 0, when
, repeat
);
320 readfile(ThreadContext
*tc
, Addr vaddr
, uint64_t len
, uint64_t offset
)
322 const string
&file
= tc
->getSystemPtr()->params()->readfile
;
329 int fd
= ::open(file
.c_str(), O_RDONLY
, 0);
331 panic("could not open file %s\n", file
);
333 if (::lseek(fd
, offset
, SEEK_SET
) < 0)
334 panic("could not seek: %s", strerror(errno
));
336 char *buf
= new char[len
];
339 int bytes
= ::read(fd
, p
, len
);
349 CopyIn(tc
, vaddr
, buf
, result
);
357 debugbreak(ThreadContext
*tc
)
363 switchcpu(ThreadContext
*tc
)
365 exitSimLoop("switchcpu");
369 // This function is executed when annotated work items begin. Depending on
370 // what the user specified at the command line, the simulation may exit and/or
371 // take a checkpoint when a certain work item begins.
374 workbegin(ThreadContext
*tc
, uint64_t workid
, uint64_t threadid
)
376 tc
->getCpuPtr()->workItemBegin();
377 System
*sys
= tc
->getSystemPtr();
379 DPRINTF(WorkItems
, "Work Begin workid: %d, threadid %d\n", workid
,
383 // If specified, determine if this is the specific work item the user
386 if (sys
->params()->work_item_id
== -1 ||
387 sys
->params()->work_item_id
== workid
) {
389 uint64_t systemWorkBeginCount
= sys
->incWorkItemsBegin();
390 int cpuId
= tc
->getCpuPtr()->cpuId();
392 if (sys
->params()->work_cpus_ckpt_count
!= 0 &&
393 sys
->markWorkItem(cpuId
) >= sys
->params()->work_cpus_ckpt_count
) {
395 // If active cpus equals checkpoint count, create checkpoint
397 Event
*event
= new SimLoopExitEvent("checkpoint", 0);
398 mainEventQueue
.schedule(event
, curTick());
401 if (systemWorkBeginCount
== sys
->params()->work_begin_ckpt_count
) {
403 // Note: the string specified as the cause of the exit event must
404 // exactly equal "checkpoint" inorder to create a checkpoint
406 Event
*event
= new SimLoopExitEvent("checkpoint", 0);
407 mainEventQueue
.schedule(event
, curTick());
410 if (systemWorkBeginCount
== sys
->params()->work_begin_exit_count
) {
412 // If a certain number of work items started, exit simulation
414 Event
*event
= new SimLoopExitEvent("work started count reach", 0);
415 mainEventQueue
.schedule(event
, curTick());
418 if (tc
->getCpuPtr()->cpuId() == sys
->params()->work_begin_cpu_id_exit
) {
420 // If work started on the specific cpu id specified, exit simulation
422 Event
*event
= new SimLoopExitEvent("work started on specific cpu",
425 mainEventQueue
.schedule(event
, curTick() + 1);
431 // This function is executed when annotated work items end. Depending on
432 // what the user specified at the command line, the simulation may exit and/or
433 // take a checkpoint when a certain work item ends.
436 workend(ThreadContext
*tc
, uint64_t workid
, uint64_t threadid
)
438 tc
->getCpuPtr()->workItemEnd();
439 System
*sys
= tc
->getSystemPtr();
441 DPRINTF(WorkItems
, "Work End workid: %d, threadid %d\n", workid
, threadid
);
444 // If specified, determine if this is the specific work item the user
447 if (sys
->params()->work_item_id
== -1 ||
448 sys
->params()->work_item_id
== workid
) {
450 uint64_t systemWorkEndCount
= sys
->incWorkItemsEnd();
451 int cpuId
= tc
->getCpuPtr()->cpuId();
453 if (sys
->params()->work_cpus_ckpt_count
!= 0 &&
454 sys
->markWorkItem(cpuId
) >= sys
->params()->work_cpus_ckpt_count
) {
456 // If active cpus equals checkpoint count, create checkpoint
458 Event
*event
= new SimLoopExitEvent("checkpoint", 0);
459 mainEventQueue
.schedule(event
, curTick());
462 if (sys
->params()->work_end_ckpt_count
!= 0 &&
463 systemWorkEndCount
== sys
->params()->work_end_ckpt_count
) {
465 // If total work items completed equals checkpoint count, create
468 Event
*event
= new SimLoopExitEvent("checkpoint", 0);
469 mainEventQueue
.schedule(event
, curTick());
472 if (sys
->params()->work_end_exit_count
!= 0 &&
473 systemWorkEndCount
== sys
->params()->work_end_exit_count
) {
475 // If total work items completed equals exit count, exit simulation
477 Event
*event
= new SimLoopExitEvent("work items exit count reached",
480 mainEventQueue
.schedule(event
, curTick());
485 } // namespace PseudoInst