8857e9a6662d610ef6d4919f4360aa4bcde4c2db
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/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
{
82 arm(ThreadContext
*tc
)
84 if (tc
->getKernelStats())
85 tc
->getKernelStats()->arm();
89 quiesce(ThreadContext
*tc
)
91 if (!tc
->getCpuPtr()->params()->do_quiesce
)
94 DPRINTF(Quiesce
, "%s: quiesce()\n", tc
->getCpuPtr()->name());
97 if (tc
->getKernelStats())
98 tc
->getKernelStats()->quiesce();
102 quiesceSkip(ThreadContext
*tc
)
104 BaseCPU
*cpu
= tc
->getCpuPtr();
106 if (!cpu
->params()->do_quiesce
)
109 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
111 Tick resume
= curTick() + 1;
113 cpu
->reschedule(quiesceEvent
, resume
, true);
115 DPRINTF(Quiesce
, "%s: quiesceSkip() until %d\n",
116 cpu
->name(), resume
);
119 if (tc
->getKernelStats())
120 tc
->getKernelStats()->quiesce();
124 quiesceNs(ThreadContext
*tc
, uint64_t ns
)
126 BaseCPU
*cpu
= tc
->getCpuPtr();
128 if (!cpu
->params()->do_quiesce
|| ns
== 0)
131 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
133 Tick resume
= curTick() + SimClock::Int::ns
* ns
;
135 cpu
->reschedule(quiesceEvent
, resume
, true);
137 DPRINTF(Quiesce
, "%s: quiesceNs(%d) until %d\n",
138 cpu
->name(), ns
, resume
);
141 if (tc
->getKernelStats())
142 tc
->getKernelStats()->quiesce();
146 quiesceCycles(ThreadContext
*tc
, uint64_t cycles
)
148 BaseCPU
*cpu
= tc
->getCpuPtr();
150 if (!cpu
->params()->do_quiesce
|| cycles
== 0)
153 EndQuiesceEvent
*quiesceEvent
= tc
->getQuiesceEvent();
155 Tick resume
= curTick() + cpu
->ticks(cycles
);
157 cpu
->reschedule(quiesceEvent
, resume
, true);
159 DPRINTF(Quiesce
, "%s: quiesceCycles(%d) until %d\n",
160 cpu
->name(), cycles
, resume
);
163 if (tc
->getKernelStats())
164 tc
->getKernelStats()->quiesce();
168 quiesceTime(ThreadContext
*tc
)
170 return (tc
->readLastActivate() - tc
->readLastSuspend()) /
177 rpns(ThreadContext
*tc
)
179 return curTick() / SimClock::Int::ns
;
183 wakeCPU(ThreadContext
*tc
, uint64_t cpuid
)
185 System
*sys
= tc
->getSystemPtr();
186 ThreadContext
*other_tc
= sys
->threadContexts
[cpuid
];
187 if (other_tc
->status() == ThreadContext::Suspended
)
188 other_tc
->activate();
192 m5exit(ThreadContext
*tc
, Tick delay
)
194 Tick when
= curTick() + delay
* SimClock::Int::ns
;
195 exitSimLoop("m5_exit instruction encountered", 0, when
);
201 loadsymbol(ThreadContext
*tc
)
203 const string
&filename
= tc
->getCpuPtr()->system
->params()->symbolfile
;
204 if (filename
.empty()) {
209 ifstream
file(filename
.c_str());
212 fatal("file error: Can't open symbol table file %s\n", filename
);
214 while (!file
.eof()) {
215 getline(file
, buffer
);
220 string::size_type idx
= buffer
.find(' ');
221 if (idx
== string::npos
)
224 string address
= "0x" + buffer
.substr(0, idx
);
229 // Skip over letter and space
230 string symbol
= buffer
.substr(idx
+ 3);
236 if (!to_number(address
, addr
))
239 if (!tc
->getSystemPtr()->kernelSymtab
->insert(addr
, symbol
))
243 DPRINTF(Loader
, "Loaded symbol: %s @ %#llx\n", symbol
, addr
);
249 addsymbol(ThreadContext
*tc
, Addr addr
, Addr symbolAddr
)
252 CopyStringOut(tc
, symb
, symbolAddr
, 100);
253 std::string
symbol(symb
);
255 DPRINTF(Loader
, "Loaded symbol: %s @ %#llx\n", symbol
, addr
);
257 tc
->getSystemPtr()->kernelSymtab
->insert(addr
,symbol
);
258 debugSymbolTable
->insert(addr
,symbol
);
262 initParam(ThreadContext
*tc
)
264 return tc
->getCpuPtr()->system
->init_param
;
271 resetstats(ThreadContext
*tc
, Tick delay
, Tick period
)
273 if (!tc
->getCpuPtr()->params()->do_statistics_insts
)
277 Tick when
= curTick() + delay
* SimClock::Int::ns
;
278 Tick repeat
= period
* SimClock::Int::ns
;
280 Stats::schedStatEvent(false, true, when
, repeat
);
284 dumpstats(ThreadContext
*tc
, Tick delay
, Tick period
)
286 if (!tc
->getCpuPtr()->params()->do_statistics_insts
)
290 Tick when
= curTick() + delay
* SimClock::Int::ns
;
291 Tick repeat
= period
* SimClock::Int::ns
;
293 Stats::schedStatEvent(true, false, when
, repeat
);
297 dumpresetstats(ThreadContext
*tc
, Tick delay
, Tick period
)
299 if (!tc
->getCpuPtr()->params()->do_statistics_insts
)
303 Tick when
= curTick() + delay
* SimClock::Int::ns
;
304 Tick repeat
= period
* SimClock::Int::ns
;
306 Stats::schedStatEvent(true, true, when
, repeat
);
310 m5checkpoint(ThreadContext
*tc
, Tick delay
, Tick period
)
312 if (!tc
->getCpuPtr()->params()->do_checkpoint_insts
)
315 Tick when
= curTick() + delay
* SimClock::Int::ns
;
316 Tick repeat
= period
* SimClock::Int::ns
;
318 exitSimLoop("checkpoint", 0, when
, repeat
);
324 readfile(ThreadContext
*tc
, Addr vaddr
, uint64_t len
, uint64_t offset
)
326 const string
&file
= tc
->getSystemPtr()->params()->readfile
;
333 int fd
= ::open(file
.c_str(), O_RDONLY
, 0);
335 panic("could not open file %s\n", file
);
337 if (::lseek(fd
, offset
, SEEK_SET
) < 0)
338 panic("could not seek: %s", strerror(errno
));
340 char *buf
= new char[len
];
343 int bytes
= ::read(fd
, p
, len
);
353 CopyIn(tc
, vaddr
, buf
, result
);
361 debugbreak(ThreadContext
*tc
)
367 switchcpu(ThreadContext
*tc
)
369 exitSimLoop("switchcpu");
373 // This function is executed when annotated work items begin. Depending on
374 // what the user specified at the command line, the simulation may exit and/or
375 // take a checkpoint when a certain work item begins.
378 workbegin(ThreadContext
*tc
, uint64_t workid
, uint64_t threadid
)
380 tc
->getCpuPtr()->workItemBegin();
381 System
*sys
= tc
->getSystemPtr();
382 const System::Params
*params
= sys
->params();
384 DPRINTF(WorkItems
, "Work Begin workid: %d, threadid %d\n", workid
,
388 // If specified, determine if this is the specific work item the user
391 if (params
->work_item_id
== -1 || params
->work_item_id
== workid
) {
393 uint64_t systemWorkBeginCount
= sys
->incWorkItemsBegin();
394 int cpuId
= tc
->getCpuPtr()->cpuId();
396 if (params
->work_cpus_ckpt_count
!= 0 &&
397 sys
->markWorkItem(cpuId
) >= params
->work_cpus_ckpt_count
) {
399 // If active cpus equals checkpoint count, create checkpoint
401 exitSimLoop("checkpoint");
404 if (systemWorkBeginCount
== params
->work_begin_ckpt_count
) {
406 // Note: the string specified as the cause of the exit event must
407 // exactly equal "checkpoint" inorder to create a checkpoint
409 exitSimLoop("checkpoint");
412 if (systemWorkBeginCount
== params
->work_begin_exit_count
) {
414 // If a certain number of work items started, exit simulation
416 exitSimLoop("work started count reach");
419 if (cpuId
== params
->work_begin_cpu_id_exit
) {
421 // If work started on the cpu id specified, exit simulation
423 exitSimLoop("work started on specific cpu");
429 // This function is executed when annotated work items end. Depending on
430 // what the user specified at the command line, the simulation may exit and/or
431 // take a checkpoint when a certain work item ends.
434 workend(ThreadContext
*tc
, uint64_t workid
, uint64_t threadid
)
436 tc
->getCpuPtr()->workItemEnd();
437 System
*sys
= tc
->getSystemPtr();
438 const System::Params
*params
= sys
->params();
440 DPRINTF(WorkItems
, "Work End workid: %d, threadid %d\n", workid
, threadid
);
443 // If specified, determine if this is the specific work item the user
446 if (params
->work_item_id
== -1 || params
->work_item_id
== workid
) {
448 uint64_t systemWorkEndCount
= sys
->incWorkItemsEnd();
449 int cpuId
= tc
->getCpuPtr()->cpuId();
451 if (params
->work_cpus_ckpt_count
!= 0 &&
452 sys
->markWorkItem(cpuId
) >= params
->work_cpus_ckpt_count
) {
454 // If active cpus equals checkpoint count, create checkpoint
456 exitSimLoop("checkpoint");
459 if (params
->work_end_ckpt_count
!= 0 &&
460 systemWorkEndCount
== params
->work_end_ckpt_count
) {
462 // If total work items completed equals checkpoint count, create
465 exitSimLoop("checkpoint");
468 if (params
->work_end_exit_count
!= 0 &&
469 systemWorkEndCount
== params
->work_end_exit_count
) {
471 // If total work items completed equals exit count, exit simulation
473 exitSimLoop("work items exit count reached");
478 } // namespace PseudoInst