2 * Copyright (c) 2010-2011 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 "base/output.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 panicFsOnlyPseudoInst("arm");
92 if (tc
->getKernelStats())
93 tc
->getKernelStats()->arm();
97 quiesce(ThreadContext
*tc
)
100 panicFsOnlyPseudoInst("quiesce");
102 if (!tc
->getCpuPtr()->params()->do_quiesce
)
105 DPRINTF(Quiesce
, "%s: quiesce()\n", tc
->getCpuPtr()->name());
108 if (tc
->getKernelStats())
109 tc
->getKernelStats()->quiesce();
113 quiesceSkip(ThreadContext
*tc
)
116 panicFsOnlyPseudoInst("quiesceSkip");
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();
138 quiesceNs(ThreadContext
*tc
, uint64_t ns
)
141 panicFsOnlyPseudoInst("quiesceNs");
143 BaseCPU
*cpu
= tc
->getCpuPtr();
145 if (!cpu
->params()->do_quiesce
|| ns
== 0)
148 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
150 Tick resume
= curTick() + SimClock::Int::ns
* ns
;
152 cpu
->reschedule(quiesceEvent
, resume
, true);
154 DPRINTF(Quiesce
, "%s: quiesceNs(%d) until %d\n",
155 cpu
->name(), ns
, resume
);
158 if (tc
->getKernelStats())
159 tc
->getKernelStats()->quiesce();
163 quiesceCycles(ThreadContext
*tc
, uint64_t cycles
)
166 panicFsOnlyPseudoInst("quiesceCycles");
168 BaseCPU
*cpu
= tc
->getCpuPtr();
170 if (!cpu
->params()->do_quiesce
|| cycles
== 0)
173 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
175 Tick resume
= cpu
->clockEdge(Cycles(cycles
));
177 cpu
->reschedule(quiesceEvent
, resume
, true);
179 DPRINTF(Quiesce
, "%s: quiesceCycles(%d) until %d\n",
180 cpu
->name(), cycles
, resume
);
183 if (tc
->getKernelStats())
184 tc
->getKernelStats()->quiesce();
188 quiesceTime(ThreadContext
*tc
)
191 panicFsOnlyPseudoInst("quiesceTime");
195 return (tc
->readLastActivate() - tc
->readLastSuspend()) /
200 rpns(ThreadContext
*tc
)
202 return curTick() / SimClock::Int::ns
;
206 wakeCPU(ThreadContext
*tc
, uint64_t cpuid
)
208 System
*sys
= tc
->getSystemPtr();
209 ThreadContext
*other_tc
= sys
->threadContexts
[cpuid
];
210 if (other_tc
->status() == ThreadContext::Suspended
)
211 other_tc
->activate();
215 m5exit(ThreadContext
*tc
, Tick delay
)
217 Tick when
= curTick() + delay
* SimClock::Int::ns
;
218 exitSimLoop("m5_exit instruction encountered", 0, when
);
222 m5fail(ThreadContext
*tc
, Tick delay
, uint64_t code
)
224 Tick when
= curTick() + delay
* SimClock::Int::ns
;
225 exitSimLoop("m5_fail instruction encountered", code
, when
);
229 loadsymbol(ThreadContext
*tc
)
232 panicFsOnlyPseudoInst("loadsymbol");
234 const string
&filename
= tc
->getCpuPtr()->system
->params()->symbolfile
;
235 if (filename
.empty()) {
240 ifstream
file(filename
.c_str());
243 fatal("file error: Can't open symbol table file %s\n", filename
);
245 while (!file
.eof()) {
246 getline(file
, buffer
);
251 string::size_type idx
= buffer
.find(' ');
252 if (idx
== string::npos
)
255 string address
= "0x" + buffer
.substr(0, idx
);
260 // Skip over letter and space
261 string symbol
= buffer
.substr(idx
+ 3);
267 if (!to_number(address
, addr
))
270 if (!tc
->getSystemPtr()->kernelSymtab
->insert(addr
, symbol
))
274 DPRINTF(Loader
, "Loaded symbol: %s @ %#llx\n", symbol
, addr
);
280 addsymbol(ThreadContext
*tc
, Addr addr
, Addr symbolAddr
)
283 panicFsOnlyPseudoInst("addSymbol");
286 CopyStringOut(tc
, symb
, symbolAddr
, 100);
287 std::string
symbol(symb
);
289 DPRINTF(Loader
, "Loaded symbol: %s @ %#llx\n", symbol
, addr
);
291 tc
->getSystemPtr()->kernelSymtab
->insert(addr
,symbol
);
292 debugSymbolTable
->insert(addr
,symbol
);
296 initParam(ThreadContext
*tc
)
299 panicFsOnlyPseudoInst("initParam");
303 return tc
->getCpuPtr()->system
->init_param
;
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 panicFsOnlyPseudoInst("readfile");
366 const string
&file
= tc
->getSystemPtr()->params()->readfile
;
373 int fd
= ::open(file
.c_str(), O_RDONLY
, 0);
375 panic("could not open file %s\n", file
);
377 if (::lseek(fd
, offset
, SEEK_SET
) < 0)
378 panic("could not seek: %s", strerror(errno
));
380 char *buf
= new char[len
];
383 int bytes
= ::read(fd
, p
, len
);
393 CopyIn(tc
, vaddr
, buf
, result
);
399 writefile(ThreadContext
*tc
, Addr vaddr
, uint64_t len
, uint64_t offset
,
404 // copy out target filename
406 std::string filename
;
407 CopyStringOut(tc
, fn
, filename_addr
, 100);
408 filename
= std::string(fn
);
411 // create a new file (truncate)
412 os
= simout
.create(filename
, true);
414 // do not truncate file if offset is non-zero
415 // (ios::in flag is required as well to keep the existing data
416 // intact, otherwise existing data will be zeroed out.)
417 os
= simout
.openFile(simout
.directory() + filename
,
418 ios::in
| ios::out
| ios::binary
);
421 panic("could not open file %s\n", filename
);
426 // copy out data and write to file
427 char *buf
= new char[len
];
428 CopyOut(tc
, buf
, vaddr
, len
);
430 if (os
->fail() || os
->bad())
431 panic("Error while doing writefile!\n");
441 debugbreak(ThreadContext
*tc
)
447 switchcpu(ThreadContext
*tc
)
449 exitSimLoop("switchcpu");
453 // This function is executed when annotated work items begin. Depending on
454 // what the user specified at the command line, the simulation may exit and/or
455 // take a checkpoint when a certain work item begins.
458 workbegin(ThreadContext
*tc
, uint64_t workid
, uint64_t threadid
)
460 tc
->getCpuPtr()->workItemBegin();
461 System
*sys
= tc
->getSystemPtr();
462 const System::Params
*params
= sys
->params();
463 sys
->workItemBegin(threadid
, workid
);
465 DPRINTF(WorkItems
, "Work Begin workid: %d, threadid %d\n", workid
,
469 // If specified, determine if this is the specific work item the user
472 if (params
->work_item_id
== -1 || params
->work_item_id
== workid
) {
474 uint64_t systemWorkBeginCount
= sys
->incWorkItemsBegin();
475 int cpuId
= tc
->getCpuPtr()->cpuId();
477 if (params
->work_cpus_ckpt_count
!= 0 &&
478 sys
->markWorkItem(cpuId
) >= params
->work_cpus_ckpt_count
) {
480 // If active cpus equals checkpoint count, create checkpoint
482 exitSimLoop("checkpoint");
485 if (systemWorkBeginCount
== params
->work_begin_ckpt_count
) {
487 // Note: the string specified as the cause of the exit event must
488 // exactly equal "checkpoint" inorder to create a checkpoint
490 exitSimLoop("checkpoint");
493 if (systemWorkBeginCount
== params
->work_begin_exit_count
) {
495 // If a certain number of work items started, exit simulation
497 exitSimLoop("work started count reach");
500 if (cpuId
== params
->work_begin_cpu_id_exit
) {
502 // If work started on the cpu id specified, exit simulation
504 exitSimLoop("work started on specific cpu");
510 // This function is executed when annotated work items end. Depending on
511 // what the user specified at the command line, the simulation may exit and/or
512 // take a checkpoint when a certain work item ends.
515 workend(ThreadContext
*tc
, uint64_t workid
, uint64_t threadid
)
517 tc
->getCpuPtr()->workItemEnd();
518 System
*sys
= tc
->getSystemPtr();
519 const System::Params
*params
= sys
->params();
520 sys
->workItemEnd(threadid
, workid
);
522 DPRINTF(WorkItems
, "Work End workid: %d, threadid %d\n", workid
, threadid
);
525 // If specified, determine if this is the specific work item the user
528 if (params
->work_item_id
== -1 || params
->work_item_id
== workid
) {
530 uint64_t systemWorkEndCount
= sys
->incWorkItemsEnd();
531 int cpuId
= tc
->getCpuPtr()->cpuId();
533 if (params
->work_cpus_ckpt_count
!= 0 &&
534 sys
->markWorkItem(cpuId
) >= params
->work_cpus_ckpt_count
) {
536 // If active cpus equals checkpoint count, create checkpoint
538 exitSimLoop("checkpoint");
541 if (params
->work_end_ckpt_count
!= 0 &&
542 systemWorkEndCount
== params
->work_end_ckpt_count
) {
544 // If total work items completed equals checkpoint count, create
547 exitSimLoop("checkpoint");
550 if (params
->work_end_exit_count
!= 0 &&
551 systemWorkEndCount
== params
->work_end_exit_count
) {
553 // If total work items completed equals exit count, exit simulation
555 exitSimLoop("work items exit count reached");
560 } // namespace PseudoInst