b72fdca4a3f150b3e0cb80ef3d0e1b8ac58e6f52
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) 2011 Advanced Micro Devices, Inc.
15 * Copyright (c) 2003-2006 The Regents of The University of Michigan
16 * All rights reserved.
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 * Authors: Nathan Binkert
51 #include "arch/kernel_stats.hh"
52 #include "arch/vtophys.hh"
53 #include "base/debug.hh"
54 #include "config/the_isa.hh"
55 #include "cpu/base.hh"
56 #include "cpu/quiesce_event.hh"
57 #include "cpu/thread_context.hh"
58 #include "debug/Loader.hh"
59 #include "debug/Quiesce.hh"
60 #include "debug/WorkItems.hh"
61 #include "params/BaseCPU.hh"
62 #include "sim/full_system.hh"
63 #include "sim/pseudo_inst.hh"
64 #include "sim/serialize.hh"
65 #include "sim/sim_events.hh"
66 #include "sim/sim_exit.hh"
67 #include "sim/stat_control.hh"
68 #include "sim/stats.hh"
69 #include "sim/system.hh"
70 #include "sim/vptr.hh"
74 using namespace Stats
;
75 using namespace TheISA
;
77 namespace PseudoInst
{
80 panicFsOnlyPseudoInst(const char *name
)
82 panic("Pseudo inst \"%s\" is only available in Full System mode.");
86 arm(ThreadContext
*tc
)
89 panicFsOnlyPseudoInst("arm");
91 if (tc
->getKernelStats())
92 tc
->getKernelStats()->arm();
96 quiesce(ThreadContext
*tc
)
99 panicFsOnlyPseudoInst("quiesce");
101 if (!tc
->getCpuPtr()->params()->do_quiesce
)
104 DPRINTF(Quiesce
, "%s: quiesce()\n", tc
->getCpuPtr()->name());
107 if (tc
->getKernelStats())
108 tc
->getKernelStats()->quiesce();
112 quiesceSkip(ThreadContext
*tc
)
115 panicFsOnlyPseudoInst("quiesceSkip");
117 BaseCPU
*cpu
= tc
->getCpuPtr();
119 if (!cpu
->params()->do_quiesce
)
122 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
124 Tick resume
= curTick() + 1;
126 cpu
->reschedule(quiesceEvent
, resume
, true);
128 DPRINTF(Quiesce
, "%s: quiesceSkip() until %d\n",
129 cpu
->name(), resume
);
132 if (tc
->getKernelStats())
133 tc
->getKernelStats()->quiesce();
137 quiesceNs(ThreadContext
*tc
, uint64_t ns
)
140 panicFsOnlyPseudoInst("quiesceNs");
142 BaseCPU
*cpu
= tc
->getCpuPtr();
144 if (!cpu
->params()->do_quiesce
|| ns
== 0)
147 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
149 Tick resume
= curTick() + SimClock::Int::ns
* ns
;
151 cpu
->reschedule(quiesceEvent
, resume
, true);
153 DPRINTF(Quiesce
, "%s: quiesceNs(%d) until %d\n",
154 cpu
->name(), ns
, resume
);
157 if (tc
->getKernelStats())
158 tc
->getKernelStats()->quiesce();
162 quiesceCycles(ThreadContext
*tc
, uint64_t cycles
)
165 panicFsOnlyPseudoInst("quiesceCycles");
167 BaseCPU
*cpu
= tc
->getCpuPtr();
169 if (!cpu
->params()->do_quiesce
|| cycles
== 0)
172 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
174 Tick resume
= curTick() + cpu
->ticks(cycles
);
176 cpu
->reschedule(quiesceEvent
, resume
, true);
178 DPRINTF(Quiesce
, "%s: quiesceCycles(%d) until %d\n",
179 cpu
->name(), cycles
, resume
);
182 if (tc
->getKernelStats())
183 tc
->getKernelStats()->quiesce();
187 quiesceTime(ThreadContext
*tc
)
190 panicFsOnlyPseudoInst("quiesceTime");
194 return (tc
->readLastActivate() - tc
->readLastSuspend()) /
199 rpns(ThreadContext
*tc
)
201 return curTick() / SimClock::Int::ns
;
205 wakeCPU(ThreadContext
*tc
, uint64_t cpuid
)
207 System
*sys
= tc
->getSystemPtr();
208 ThreadContext
*other_tc
= sys
->threadContexts
[cpuid
];
209 if (other_tc
->status() == ThreadContext::Suspended
)
210 other_tc
->activate();
214 m5exit(ThreadContext
*tc
, Tick delay
)
216 Tick when
= curTick() + delay
* SimClock::Int::ns
;
217 exitSimLoop("m5_exit instruction encountered", 0, when
);
221 loadsymbol(ThreadContext
*tc
)
224 panicFsOnlyPseudoInst("loadsymbol");
226 const string
&filename
= tc
->getCpuPtr()->system
->params()->symbolfile
;
227 if (filename
.empty()) {
232 ifstream
file(filename
.c_str());
235 fatal("file error: Can't open symbol table file %s\n", filename
);
237 while (!file
.eof()) {
238 getline(file
, buffer
);
243 string::size_type idx
= buffer
.find(' ');
244 if (idx
== string::npos
)
247 string address
= "0x" + buffer
.substr(0, idx
);
252 // Skip over letter and space
253 string symbol
= buffer
.substr(idx
+ 3);
259 if (!to_number(address
, addr
))
262 if (!tc
->getSystemPtr()->kernelSymtab
->insert(addr
, symbol
))
266 DPRINTF(Loader
, "Loaded symbol: %s @ %#llx\n", symbol
, addr
);
272 addsymbol(ThreadContext
*tc
, Addr addr
, Addr symbolAddr
)
275 panicFsOnlyPseudoInst("addSymbol");
278 CopyStringOut(tc
, symb
, symbolAddr
, 100);
279 std::string
symbol(symb
);
281 DPRINTF(Loader
, "Loaded symbol: %s @ %#llx\n", symbol
, addr
);
283 tc
->getSystemPtr()->kernelSymtab
->insert(addr
,symbol
);
284 debugSymbolTable
->insert(addr
,symbol
);
288 initParam(ThreadContext
*tc
)
291 panicFsOnlyPseudoInst("initParam");
295 return tc
->getCpuPtr()->system
->init_param
;
300 resetstats(ThreadContext
*tc
, Tick delay
, Tick period
)
302 if (!tc
->getCpuPtr()->params()->do_statistics_insts
)
306 Tick when
= curTick() + delay
* SimClock::Int::ns
;
307 Tick repeat
= period
* SimClock::Int::ns
;
309 Stats::schedStatEvent(false, true, when
, repeat
);
313 dumpstats(ThreadContext
*tc
, Tick delay
, Tick period
)
315 if (!tc
->getCpuPtr()->params()->do_statistics_insts
)
319 Tick when
= curTick() + delay
* SimClock::Int::ns
;
320 Tick repeat
= period
* SimClock::Int::ns
;
322 Stats::schedStatEvent(true, false, when
, repeat
);
326 dumpresetstats(ThreadContext
*tc
, Tick delay
, Tick period
)
328 if (!tc
->getCpuPtr()->params()->do_statistics_insts
)
332 Tick when
= curTick() + delay
* SimClock::Int::ns
;
333 Tick repeat
= period
* SimClock::Int::ns
;
335 Stats::schedStatEvent(true, true, when
, repeat
);
339 m5checkpoint(ThreadContext
*tc
, Tick delay
, Tick period
)
341 if (!tc
->getCpuPtr()->params()->do_checkpoint_insts
)
344 Tick when
= curTick() + delay
* SimClock::Int::ns
;
345 Tick repeat
= period
* SimClock::Int::ns
;
347 exitSimLoop("checkpoint", 0, when
, repeat
);
351 readfile(ThreadContext
*tc
, Addr vaddr
, uint64_t len
, uint64_t offset
)
354 panicFsOnlyPseudoInst("readfile");
358 const string
&file
= tc
->getSystemPtr()->params()->readfile
;
365 int fd
= ::open(file
.c_str(), O_RDONLY
, 0);
367 panic("could not open file %s\n", file
);
369 if (::lseek(fd
, offset
, SEEK_SET
) < 0)
370 panic("could not seek: %s", strerror(errno
));
372 char *buf
= new char[len
];
375 int bytes
= ::read(fd
, p
, len
);
385 CopyIn(tc
, vaddr
, buf
, result
);
391 debugbreak(ThreadContext
*tc
)
397 switchcpu(ThreadContext
*tc
)
399 exitSimLoop("switchcpu");
403 // This function is executed when annotated work items begin. Depending on
404 // what the user specified at the command line, the simulation may exit and/or
405 // take a checkpoint when a certain work item begins.
408 workbegin(ThreadContext
*tc
, uint64_t workid
, uint64_t threadid
)
410 tc
->getCpuPtr()->workItemBegin();
411 System
*sys
= tc
->getSystemPtr();
412 const System::Params
*params
= sys
->params();
413 sys
->workItemBegin(threadid
, workid
);
415 DPRINTF(WorkItems
, "Work Begin workid: %d, threadid %d\n", workid
,
419 // If specified, determine if this is the specific work item the user
422 if (params
->work_item_id
== -1 || params
->work_item_id
== workid
) {
424 uint64_t systemWorkBeginCount
= sys
->incWorkItemsBegin();
425 int cpuId
= tc
->getCpuPtr()->cpuId();
427 if (params
->work_cpus_ckpt_count
!= 0 &&
428 sys
->markWorkItem(cpuId
) >= params
->work_cpus_ckpt_count
) {
430 // If active cpus equals checkpoint count, create checkpoint
432 exitSimLoop("checkpoint");
435 if (systemWorkBeginCount
== params
->work_begin_ckpt_count
) {
437 // Note: the string specified as the cause of the exit event must
438 // exactly equal "checkpoint" inorder to create a checkpoint
440 exitSimLoop("checkpoint");
443 if (systemWorkBeginCount
== params
->work_begin_exit_count
) {
445 // If a certain number of work items started, exit simulation
447 exitSimLoop("work started count reach");
450 if (cpuId
== params
->work_begin_cpu_id_exit
) {
452 // If work started on the cpu id specified, exit simulation
454 exitSimLoop("work started on specific cpu");
460 // This function is executed when annotated work items end. Depending on
461 // what the user specified at the command line, the simulation may exit and/or
462 // take a checkpoint when a certain work item ends.
465 workend(ThreadContext
*tc
, uint64_t workid
, uint64_t threadid
)
467 tc
->getCpuPtr()->workItemEnd();
468 System
*sys
= tc
->getSystemPtr();
469 const System::Params
*params
= sys
->params();
470 sys
->workItemEnd(threadid
, workid
);
472 DPRINTF(WorkItems
, "Work End workid: %d, threadid %d\n", workid
, threadid
);
475 // If specified, determine if this is the specific work item the user
478 if (params
->work_item_id
== -1 || params
->work_item_id
== workid
) {
480 uint64_t systemWorkEndCount
= sys
->incWorkItemsEnd();
481 int cpuId
= tc
->getCpuPtr()->cpuId();
483 if (params
->work_cpus_ckpt_count
!= 0 &&
484 sys
->markWorkItem(cpuId
) >= params
->work_cpus_ckpt_count
) {
486 // If active cpus equals checkpoint count, create checkpoint
488 exitSimLoop("checkpoint");
491 if (params
->work_end_ckpt_count
!= 0 &&
492 systemWorkEndCount
== params
->work_end_ckpt_count
) {
494 // If total work items completed equals checkpoint count, create
497 exitSimLoop("checkpoint");
500 if (params
->work_end_exit_count
!= 0 &&
501 systemWorkEndCount
== params
->work_end_exit_count
) {
503 // If total work items completed equals exit count, exit simulation
505 exitSimLoop("work items exit count reached");
510 } // namespace PseudoInst