f8a46cead4c3e7078831a18d05bd4b601354582e
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/full_system.hh"
55 #include "config/the_isa.hh"
56 #include "cpu/base.hh"
57 #include "cpu/quiesce_event.hh"
58 #include "cpu/thread_context.hh"
59 #include "debug/Loader.hh"
60 #include "debug/Quiesce.hh"
61 #include "debug/WorkItems.hh"
62 #include "params/BaseCPU.hh"
63 #include "sim/full_system.hh"
64 #include "sim/pseudo_inst.hh"
65 #include "sim/serialize.hh"
66 #include "sim/sim_events.hh"
67 #include "sim/sim_exit.hh"
68 #include "sim/stat_control.hh"
69 #include "sim/stats.hh"
70 #include "sim/system.hh"
71 #include "sim/vptr.hh"
75 using namespace Stats
;
76 using namespace TheISA
;
78 namespace PseudoInst
{
81 panicFsOnlyPseudoInst(const char *name
)
83 panic("Pseudo inst \"%s\" is only available in Full System mode.");
87 arm(ThreadContext
*tc
)
90 if (tc
->getKernelStats())
91 tc
->getKernelStats()->arm();
93 panicFsOnlyPseudoInst("arm");
98 quiesce(ThreadContext
*tc
)
101 if (!tc
->getCpuPtr()->params()->do_quiesce
)
104 DPRINTF(Quiesce
, "%s: quiesce()\n", tc
->getCpuPtr()->name());
107 if (tc
->getKernelStats())
108 tc
->getKernelStats()->quiesce();
110 panicFsOnlyPseudoInst("quiesce");
115 quiesceSkip(ThreadContext
*tc
)
118 BaseCPU
*cpu
= tc
->getCpuPtr();
120 if (!cpu
->params()->do_quiesce
)
123 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
125 Tick resume
= curTick() + 1;
127 cpu
->reschedule(quiesceEvent
, resume
, true);
129 DPRINTF(Quiesce
, "%s: quiesceSkip() until %d\n",
130 cpu
->name(), resume
);
133 if (tc
->getKernelStats())
134 tc
->getKernelStats()->quiesce();
136 panicFsOnlyPseudoInst("quiesceSkip");
141 quiesceNs(ThreadContext
*tc
, uint64_t ns
)
144 BaseCPU
*cpu
= tc
->getCpuPtr();
146 if (!cpu
->params()->do_quiesce
|| ns
== 0)
149 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
151 Tick resume
= curTick() + SimClock::Int::ns
* ns
;
153 cpu
->reschedule(quiesceEvent
, resume
, true);
155 DPRINTF(Quiesce
, "%s: quiesceNs(%d) until %d\n",
156 cpu
->name(), ns
, resume
);
159 if (tc
->getKernelStats())
160 tc
->getKernelStats()->quiesce();
162 panicFsOnlyPseudoInst("quiesceNs");
167 quiesceCycles(ThreadContext
*tc
, uint64_t cycles
)
170 BaseCPU
*cpu
= tc
->getCpuPtr();
172 if (!cpu
->params()->do_quiesce
|| cycles
== 0)
175 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
177 Tick resume
= curTick() + cpu
->ticks(cycles
);
179 cpu
->reschedule(quiesceEvent
, resume
, true);
181 DPRINTF(Quiesce
, "%s: quiesceCycles(%d) until %d\n",
182 cpu
->name(), cycles
, resume
);
185 if (tc
->getKernelStats())
186 tc
->getKernelStats()->quiesce();
188 panicFsOnlyPseudoInst("quiesceCycles");
193 quiesceTime(ThreadContext
*tc
)
196 return (tc
->readLastActivate() - tc
->readLastSuspend()) /
199 panicFsOnlyPseudoInst("quiesceTime");
205 rpns(ThreadContext
*tc
)
207 return curTick() / SimClock::Int::ns
;
211 wakeCPU(ThreadContext
*tc
, uint64_t cpuid
)
213 System
*sys
= tc
->getSystemPtr();
214 ThreadContext
*other_tc
= sys
->threadContexts
[cpuid
];
215 if (other_tc
->status() == ThreadContext::Suspended
)
216 other_tc
->activate();
220 m5exit(ThreadContext
*tc
, Tick delay
)
222 Tick when
= curTick() + delay
* SimClock::Int::ns
;
223 exitSimLoop("m5_exit instruction encountered", 0, when
);
227 loadsymbol(ThreadContext
*tc
)
230 const string
&filename
= tc
->getCpuPtr()->system
->params()->symbolfile
;
231 if (filename
.empty()) {
236 ifstream
file(filename
.c_str());
239 fatal("file error: Can't open symbol table file %s\n", filename
);
241 while (!file
.eof()) {
242 getline(file
, buffer
);
247 string::size_type idx
= buffer
.find(' ');
248 if (idx
== string::npos
)
251 string address
= "0x" + buffer
.substr(0, idx
);
256 // Skip over letter and space
257 string symbol
= buffer
.substr(idx
+ 3);
263 if (!to_number(address
, addr
))
266 if (!tc
->getSystemPtr()->kernelSymtab
->insert(addr
, symbol
))
270 DPRINTF(Loader
, "Loaded symbol: %s @ %#llx\n", symbol
, addr
);
274 panicFsOnlyPseudoInst("loadsymbol");
279 addsymbol(ThreadContext
*tc
, Addr addr
, Addr symbolAddr
)
283 CopyStringOut(tc
, symb
, symbolAddr
, 100);
284 std::string
symbol(symb
);
286 DPRINTF(Loader
, "Loaded symbol: %s @ %#llx\n", symbol
, addr
);
288 tc
->getSystemPtr()->kernelSymtab
->insert(addr
,symbol
);
289 debugSymbolTable
->insert(addr
,symbol
);
291 panicFsOnlyPseudoInst("addSymbol");
296 initParam(ThreadContext
*tc
)
299 return tc
->getCpuPtr()->system
->init_param
;
301 panicFsOnlyPseudoInst("initParam");
308 resetstats(ThreadContext
*tc
, Tick delay
, Tick period
)
310 if (!tc
->getCpuPtr()->params()->do_statistics_insts
)
314 Tick when
= curTick() + delay
* SimClock::Int::ns
;
315 Tick repeat
= period
* SimClock::Int::ns
;
317 Stats::schedStatEvent(false, true, when
, repeat
);
321 dumpstats(ThreadContext
*tc
, Tick delay
, Tick period
)
323 if (!tc
->getCpuPtr()->params()->do_statistics_insts
)
327 Tick when
= curTick() + delay
* SimClock::Int::ns
;
328 Tick repeat
= period
* SimClock::Int::ns
;
330 Stats::schedStatEvent(true, false, when
, repeat
);
334 dumpresetstats(ThreadContext
*tc
, Tick delay
, Tick period
)
336 if (!tc
->getCpuPtr()->params()->do_statistics_insts
)
340 Tick when
= curTick() + delay
* SimClock::Int::ns
;
341 Tick repeat
= period
* SimClock::Int::ns
;
343 Stats::schedStatEvent(true, true, when
, repeat
);
347 m5checkpoint(ThreadContext
*tc
, Tick delay
, Tick period
)
349 if (!tc
->getCpuPtr()->params()->do_checkpoint_insts
)
352 Tick when
= curTick() + delay
* SimClock::Int::ns
;
353 Tick repeat
= period
* SimClock::Int::ns
;
355 exitSimLoop("checkpoint", 0, when
, repeat
);
359 readfile(ThreadContext
*tc
, Addr vaddr
, uint64_t len
, uint64_t offset
)
362 const string
&file
= tc
->getSystemPtr()->params()->readfile
;
369 int fd
= ::open(file
.c_str(), O_RDONLY
, 0);
371 panic("could not open file %s\n", file
);
373 if (::lseek(fd
, offset
, SEEK_SET
) < 0)
374 panic("could not seek: %s", strerror(errno
));
376 char *buf
= new char[len
];
379 int bytes
= ::read(fd
, p
, len
);
389 CopyIn(tc
, vaddr
, buf
, result
);
393 panicFsOnlyPseudoInst("readfile");
399 debugbreak(ThreadContext
*tc
)
405 switchcpu(ThreadContext
*tc
)
407 exitSimLoop("switchcpu");
411 // This function is executed when annotated work items begin. Depending on
412 // what the user specified at the command line, the simulation may exit and/or
413 // take a checkpoint when a certain work item begins.
416 workbegin(ThreadContext
*tc
, uint64_t workid
, uint64_t threadid
)
418 tc
->getCpuPtr()->workItemBegin();
419 System
*sys
= tc
->getSystemPtr();
420 const System::Params
*params
= sys
->params();
422 DPRINTF(WorkItems
, "Work Begin workid: %d, threadid %d\n", workid
,
426 // If specified, determine if this is the specific work item the user
429 if (params
->work_item_id
== -1 || params
->work_item_id
== workid
) {
431 uint64_t systemWorkBeginCount
= sys
->incWorkItemsBegin();
432 int cpuId
= tc
->getCpuPtr()->cpuId();
434 if (params
->work_cpus_ckpt_count
!= 0 &&
435 sys
->markWorkItem(cpuId
) >= params
->work_cpus_ckpt_count
) {
437 // If active cpus equals checkpoint count, create checkpoint
439 exitSimLoop("checkpoint");
442 if (systemWorkBeginCount
== params
->work_begin_ckpt_count
) {
444 // Note: the string specified as the cause of the exit event must
445 // exactly equal "checkpoint" inorder to create a checkpoint
447 exitSimLoop("checkpoint");
450 if (systemWorkBeginCount
== params
->work_begin_exit_count
) {
452 // If a certain number of work items started, exit simulation
454 exitSimLoop("work started count reach");
457 if (cpuId
== params
->work_begin_cpu_id_exit
) {
459 // If work started on the cpu id specified, exit simulation
461 exitSimLoop("work started on specific cpu");
467 // This function is executed when annotated work items end. Depending on
468 // what the user specified at the command line, the simulation may exit and/or
469 // take a checkpoint when a certain work item ends.
472 workend(ThreadContext
*tc
, uint64_t workid
, uint64_t threadid
)
474 tc
->getCpuPtr()->workItemEnd();
475 System
*sys
= tc
->getSystemPtr();
476 const System::Params
*params
= sys
->params();
478 DPRINTF(WorkItems
, "Work End workid: %d, threadid %d\n", workid
, threadid
);
481 // If specified, determine if this is the specific work item the user
484 if (params
->work_item_id
== -1 || params
->work_item_id
== workid
) {
486 uint64_t systemWorkEndCount
= sys
->incWorkItemsEnd();
487 int cpuId
= tc
->getCpuPtr()->cpuId();
489 if (params
->work_cpus_ckpt_count
!= 0 &&
490 sys
->markWorkItem(cpuId
) >= params
->work_cpus_ckpt_count
) {
492 // If active cpus equals checkpoint count, create checkpoint
494 exitSimLoop("checkpoint");
497 if (params
->work_end_ckpt_count
!= 0 &&
498 systemWorkEndCount
== params
->work_end_ckpt_count
) {
500 // If total work items completed equals checkpoint count, create
503 exitSimLoop("checkpoint");
506 if (params
->work_end_exit_count
!= 0 &&
507 systemWorkEndCount
== params
->work_end_exit_count
) {
509 // If total work items completed equals exit count, exit simulation
511 exitSimLoop("work items exit count reached");
516 } // namespace PseudoInst