pseudo_inst.cc revision 8666
111308Santhony.gutierrez@amd.com/*
211308Santhony.gutierrez@amd.com * Copyright (c) 2010 ARM Limited
311308Santhony.gutierrez@amd.com * All rights reserved
411308Santhony.gutierrez@amd.com *
511308Santhony.gutierrez@amd.com * The license below extends only to copyright in the software and shall
611308Santhony.gutierrez@amd.com * not be construed as granting a license to any other intellectual
711308Santhony.gutierrez@amd.com * property including but not limited to intellectual property relating
811308Santhony.gutierrez@amd.com * to a hardware implementation of the functionality of the software
911308Santhony.gutierrez@amd.com * licensed hereunder.  You may use the software subject to the license
1011308Santhony.gutierrez@amd.com * terms below provided that you ensure that this notice is replicated
1111308Santhony.gutierrez@amd.com * unmodified and in its entirety in all distributions of the software,
1211308Santhony.gutierrez@amd.com * modified or unmodified, in source code or in binary form.
1311308Santhony.gutierrez@amd.com *
1411308Santhony.gutierrez@amd.com * Copyright (c) 2011 Advanced Micro Devices, Inc.
1511308Santhony.gutierrez@amd.com * Copyright (c) 2003-2006 The Regents of The University of Michigan
1611308Santhony.gutierrez@amd.com * All rights reserved.
1711308Santhony.gutierrez@amd.com *
1811308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without
1911308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are
2011308Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright
2111308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer;
2211308Santhony.gutierrez@amd.com * redistributions in binary form must reproduce the above copyright
2311308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer in the
2411308Santhony.gutierrez@amd.com * documentation and/or other materials provided with the distribution;
2511308Santhony.gutierrez@amd.com * neither the name of the copyright holders nor the names of its
2611308Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from
2711308Santhony.gutierrez@amd.com * this software without specific prior written permission.
2811308Santhony.gutierrez@amd.com *
2911308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3011308Santhony.gutierrez@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3111308Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3211308Santhony.gutierrez@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3311308Santhony.gutierrez@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3411308Santhony.gutierrez@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3511308Santhony.gutierrez@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3611308Santhony.gutierrez@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3711308Santhony.gutierrez@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3811308Santhony.gutierrez@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3911308Santhony.gutierrez@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4011308Santhony.gutierrez@amd.com *
4111308Santhony.gutierrez@amd.com * Authors: Nathan Binkert
4211308Santhony.gutierrez@amd.com */
4311308Santhony.gutierrez@amd.com
4411308Santhony.gutierrez@amd.com#include <fcntl.h>
4511308Santhony.gutierrez@amd.com#include <unistd.h>
4611308Santhony.gutierrez@amd.com
4711308Santhony.gutierrez@amd.com#include <cerrno>
4811308Santhony.gutierrez@amd.com#include <fstream>
4911308Santhony.gutierrez@amd.com#include <string>
5011308Santhony.gutierrez@amd.com
5111308Santhony.gutierrez@amd.com#include "arch/vtophys.hh"
5211308Santhony.gutierrez@amd.com#include "base/debug.hh"
5311308Santhony.gutierrez@amd.com#include "config/full_system.hh"
5411308Santhony.gutierrez@amd.com#include "config/the_isa.hh"
5511308Santhony.gutierrez@amd.com#include "cpu/base.hh"
5611308Santhony.gutierrez@amd.com#include "cpu/quiesce_event.hh"
5711308Santhony.gutierrez@amd.com#include "cpu/thread_context.hh"
5811308Santhony.gutierrez@amd.com#include "debug/Loader.hh"
5911308Santhony.gutierrez@amd.com#include "debug/Quiesce.hh"
6011308Santhony.gutierrez@amd.com#include "debug/WorkItems.hh"
6111308Santhony.gutierrez@amd.com#include "params/BaseCPU.hh"
6211308Santhony.gutierrez@amd.com#include "sim/pseudo_inst.hh"
6311308Santhony.gutierrez@amd.com#include "sim/serialize.hh"
6411308Santhony.gutierrez@amd.com#include "sim/sim_events.hh"
6511308Santhony.gutierrez@amd.com#include "sim/sim_exit.hh"
6611308Santhony.gutierrez@amd.com#include "sim/stat_control.hh"
6711308Santhony.gutierrez@amd.com#include "sim/stats.hh"
6811308Santhony.gutierrez@amd.com#include "sim/system.hh"
6911308Santhony.gutierrez@amd.com
7011308Santhony.gutierrez@amd.com#if FULL_SYSTEM
7111308Santhony.gutierrez@amd.com#include "arch/kernel_stats.hh"
7211308Santhony.gutierrez@amd.com#include "sim/vptr.hh"
7311308Santhony.gutierrez@amd.com#endif
7411308Santhony.gutierrez@amd.com
7511308Santhony.gutierrez@amd.comusing namespace std;
7611308Santhony.gutierrez@amd.com
7711308Santhony.gutierrez@amd.comusing namespace Stats;
7811308Santhony.gutierrez@amd.comusing namespace TheISA;
7911308Santhony.gutierrez@amd.com
8011308Santhony.gutierrez@amd.comnamespace PseudoInst {
8111308Santhony.gutierrez@amd.com
8211308Santhony.gutierrez@amd.com#if FULL_SYSTEM
8311308Santhony.gutierrez@amd.com
8411308Santhony.gutierrez@amd.comvoid
8511308Santhony.gutierrez@amd.comarm(ThreadContext *tc)
8611308Santhony.gutierrez@amd.com{
8711308Santhony.gutierrez@amd.com    if (tc->getKernelStats())
8811308Santhony.gutierrez@amd.com        tc->getKernelStats()->arm();
8911308Santhony.gutierrez@amd.com}
9011308Santhony.gutierrez@amd.com
9111308Santhony.gutierrez@amd.comvoid
9211308Santhony.gutierrez@amd.comquiesce(ThreadContext *tc)
9311308Santhony.gutierrez@amd.com{
9411308Santhony.gutierrez@amd.com    if (!tc->getCpuPtr()->params()->do_quiesce)
9511308Santhony.gutierrez@amd.com        return;
9611308Santhony.gutierrez@amd.com
9711308Santhony.gutierrez@amd.com    DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name());
9811308Santhony.gutierrez@amd.com
9911308Santhony.gutierrez@amd.com    tc->suspend();
10011308Santhony.gutierrez@amd.com    if (tc->getKernelStats())
10111308Santhony.gutierrez@amd.com        tc->getKernelStats()->quiesce();
10211308Santhony.gutierrez@amd.com}
10311308Santhony.gutierrez@amd.com
10411308Santhony.gutierrez@amd.comvoid
10511308Santhony.gutierrez@amd.comquiesceSkip(ThreadContext *tc)
10611308Santhony.gutierrez@amd.com{
10711308Santhony.gutierrez@amd.com    BaseCPU *cpu = tc->getCpuPtr();
10811308Santhony.gutierrez@amd.com
10911308Santhony.gutierrez@amd.com    if (!cpu->params()->do_quiesce)
11011308Santhony.gutierrez@amd.com        return;
11111308Santhony.gutierrez@amd.com
11211308Santhony.gutierrez@amd.com    EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
11311308Santhony.gutierrez@amd.com
11411308Santhony.gutierrez@amd.com    Tick resume = curTick() + 1;
11511308Santhony.gutierrez@amd.com
11611308Santhony.gutierrez@amd.com    cpu->reschedule(quiesceEvent, resume, true);
11711308Santhony.gutierrez@amd.com
11811308Santhony.gutierrez@amd.com    DPRINTF(Quiesce, "%s: quiesceSkip() until %d\n",
11911308Santhony.gutierrez@amd.com            cpu->name(), resume);
12011308Santhony.gutierrez@amd.com
12111308Santhony.gutierrez@amd.com    tc->suspend();
12211308Santhony.gutierrez@amd.com    if (tc->getKernelStats())
12311308Santhony.gutierrez@amd.com        tc->getKernelStats()->quiesce();
12411308Santhony.gutierrez@amd.com}
12511308Santhony.gutierrez@amd.com
12611308Santhony.gutierrez@amd.comvoid
12711308Santhony.gutierrez@amd.comquiesceNs(ThreadContext *tc, uint64_t ns)
12811308Santhony.gutierrez@amd.com{
12911308Santhony.gutierrez@amd.com    BaseCPU *cpu = tc->getCpuPtr();
13011308Santhony.gutierrez@amd.com
13111308Santhony.gutierrez@amd.com    if (!cpu->params()->do_quiesce || ns == 0)
13211308Santhony.gutierrez@amd.com        return;
13311308Santhony.gutierrez@amd.com
13411308Santhony.gutierrez@amd.com    EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
13511308Santhony.gutierrez@amd.com
13611308Santhony.gutierrez@amd.com    Tick resume = curTick() + SimClock::Int::ns * ns;
13711308Santhony.gutierrez@amd.com
13811308Santhony.gutierrez@amd.com    cpu->reschedule(quiesceEvent, resume, true);
13911308Santhony.gutierrez@amd.com
14011308Santhony.gutierrez@amd.com    DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n",
14111308Santhony.gutierrez@amd.com            cpu->name(), ns, resume);
14211308Santhony.gutierrez@amd.com
14311308Santhony.gutierrez@amd.com    tc->suspend();
14411308Santhony.gutierrez@amd.com    if (tc->getKernelStats())
14511308Santhony.gutierrez@amd.com        tc->getKernelStats()->quiesce();
14611308Santhony.gutierrez@amd.com}
14711308Santhony.gutierrez@amd.com
14811308Santhony.gutierrez@amd.comvoid
14911308Santhony.gutierrez@amd.comquiesceCycles(ThreadContext *tc, uint64_t cycles)
15011308Santhony.gutierrez@amd.com{
15111308Santhony.gutierrez@amd.com    BaseCPU *cpu = tc->getCpuPtr();
15211308Santhony.gutierrez@amd.com
15311308Santhony.gutierrez@amd.com    if (!cpu->params()->do_quiesce || cycles == 0)
15411308Santhony.gutierrez@amd.com        return;
15511308Santhony.gutierrez@amd.com
15611308Santhony.gutierrez@amd.com    EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
15711308Santhony.gutierrez@amd.com
15811308Santhony.gutierrez@amd.com    Tick resume = curTick() + cpu->ticks(cycles);
15911308Santhony.gutierrez@amd.com
16011308Santhony.gutierrez@amd.com    cpu->reschedule(quiesceEvent, resume, true);
16111308Santhony.gutierrez@amd.com
16211308Santhony.gutierrez@amd.com    DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n",
16311308Santhony.gutierrez@amd.com            cpu->name(), cycles, resume);
16411308Santhony.gutierrez@amd.com
16511308Santhony.gutierrez@amd.com    tc->suspend();
16611308Santhony.gutierrez@amd.com    if (tc->getKernelStats())
16711308Santhony.gutierrez@amd.com        tc->getKernelStats()->quiesce();
16811308Santhony.gutierrez@amd.com}
16911308Santhony.gutierrez@amd.com
17011308Santhony.gutierrez@amd.comuint64_t
17111308Santhony.gutierrez@amd.comquiesceTime(ThreadContext *tc)
17211308Santhony.gutierrez@amd.com{
17311308Santhony.gutierrez@amd.com    return (tc->readLastActivate() - tc->readLastSuspend()) /
17411308Santhony.gutierrez@amd.com        SimClock::Int::ns;
17511308Santhony.gutierrez@amd.com}
17611308Santhony.gutierrez@amd.com
17711308Santhony.gutierrez@amd.com#endif
17811308Santhony.gutierrez@amd.com
17911308Santhony.gutierrez@amd.comuint64_t
18011308Santhony.gutierrez@amd.comrpns(ThreadContext *tc)
18111308Santhony.gutierrez@amd.com{
18211308Santhony.gutierrez@amd.com    return curTick() / SimClock::Int::ns;
18311308Santhony.gutierrez@amd.com}
18411308Santhony.gutierrez@amd.com
18511308Santhony.gutierrez@amd.comvoid
18611308Santhony.gutierrez@amd.comwakeCPU(ThreadContext *tc, uint64_t cpuid)
18711308Santhony.gutierrez@amd.com{
18811308Santhony.gutierrez@amd.com    System *sys = tc->getSystemPtr();
18911308Santhony.gutierrez@amd.com    ThreadContext *other_tc = sys->threadContexts[cpuid];
19011308Santhony.gutierrez@amd.com    if (other_tc->status() == ThreadContext::Suspended)
19111308Santhony.gutierrez@amd.com        other_tc->activate();
19211308Santhony.gutierrez@amd.com}
19311308Santhony.gutierrez@amd.com
19411308Santhony.gutierrez@amd.comvoid
19511308Santhony.gutierrez@amd.comm5exit(ThreadContext *tc, Tick delay)
19611308Santhony.gutierrez@amd.com{
19711308Santhony.gutierrez@amd.com    Tick when = curTick() + delay * SimClock::Int::ns;
19811308Santhony.gutierrez@amd.com    exitSimLoop("m5_exit instruction encountered", 0, when);
19911308Santhony.gutierrez@amd.com}
20011308Santhony.gutierrez@amd.com
20111308Santhony.gutierrez@amd.com#if FULL_SYSTEM
20211308Santhony.gutierrez@amd.com
20311308Santhony.gutierrez@amd.comvoid
20411308Santhony.gutierrez@amd.comloadsymbol(ThreadContext *tc)
20511308Santhony.gutierrez@amd.com{
20611308Santhony.gutierrez@amd.com    const string &filename = tc->getCpuPtr()->system->params()->symbolfile;
20711308Santhony.gutierrez@amd.com    if (filename.empty()) {
20811308Santhony.gutierrez@amd.com        return;
20911308Santhony.gutierrez@amd.com    }
21011308Santhony.gutierrez@amd.com
21111308Santhony.gutierrez@amd.com    std::string buffer;
21211308Santhony.gutierrez@amd.com    ifstream file(filename.c_str());
21311308Santhony.gutierrez@amd.com
21411308Santhony.gutierrez@amd.com    if (!file)
21511308Santhony.gutierrez@amd.com        fatal("file error: Can't open symbol table file %s\n", filename);
21611308Santhony.gutierrez@amd.com
21711308Santhony.gutierrez@amd.com    while (!file.eof()) {
21811308Santhony.gutierrez@amd.com        getline(file, buffer);
21911308Santhony.gutierrez@amd.com
22011308Santhony.gutierrez@amd.com        if (buffer.empty())
22111308Santhony.gutierrez@amd.com            continue;
22211308Santhony.gutierrez@amd.com
22311308Santhony.gutierrez@amd.com        string::size_type idx = buffer.find(' ');
22411308Santhony.gutierrez@amd.com        if (idx == string::npos)
22511308Santhony.gutierrez@amd.com            continue;
22611308Santhony.gutierrez@amd.com
22711308Santhony.gutierrez@amd.com        string address = "0x" + buffer.substr(0, idx);
22811308Santhony.gutierrez@amd.com        eat_white(address);
22911308Santhony.gutierrez@amd.com        if (address.empty())
23011308Santhony.gutierrez@amd.com            continue;
23111308Santhony.gutierrez@amd.com
23211308Santhony.gutierrez@amd.com        // Skip over letter and space
23311308Santhony.gutierrez@amd.com        string symbol = buffer.substr(idx + 3);
23411308Santhony.gutierrez@amd.com        eat_white(symbol);
23511308Santhony.gutierrez@amd.com        if (symbol.empty())
23611308Santhony.gutierrez@amd.com            continue;
23711308Santhony.gutierrez@amd.com
23811308Santhony.gutierrez@amd.com        Addr addr;
23911308Santhony.gutierrez@amd.com        if (!to_number(address, addr))
24011308Santhony.gutierrez@amd.com            continue;
24111308Santhony.gutierrez@amd.com
24211308Santhony.gutierrez@amd.com        if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
24311308Santhony.gutierrez@amd.com            continue;
24411308Santhony.gutierrez@amd.com
24511308Santhony.gutierrez@amd.com
24611308Santhony.gutierrez@amd.com        DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
24711308Santhony.gutierrez@amd.com    }
24811308Santhony.gutierrez@amd.com    file.close();
24911308Santhony.gutierrez@amd.com}
25011308Santhony.gutierrez@amd.com
25111308Santhony.gutierrez@amd.comvoid
25211308Santhony.gutierrez@amd.comaddsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
25311308Santhony.gutierrez@amd.com{
25411308Santhony.gutierrez@amd.com    char symb[100];
25511308Santhony.gutierrez@amd.com    CopyStringOut(tc, symb, symbolAddr, 100);
25611308Santhony.gutierrez@amd.com    std::string symbol(symb);
25711308Santhony.gutierrez@amd.com
25811308Santhony.gutierrez@amd.com    DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
25911308Santhony.gutierrez@amd.com
26011308Santhony.gutierrez@amd.com    tc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
26111308Santhony.gutierrez@amd.com    debugSymbolTable->insert(addr,symbol);
26211308Santhony.gutierrez@amd.com}
26311308Santhony.gutierrez@amd.com
26411308Santhony.gutierrez@amd.comuint64_t
26511308Santhony.gutierrez@amd.cominitParam(ThreadContext *tc)
26611308Santhony.gutierrez@amd.com{
26711308Santhony.gutierrez@amd.com    return tc->getCpuPtr()->system->init_param;
26811308Santhony.gutierrez@amd.com}
26911308Santhony.gutierrez@amd.com
27011308Santhony.gutierrez@amd.com#endif
27111308Santhony.gutierrez@amd.com
27211308Santhony.gutierrez@amd.com
27311308Santhony.gutierrez@amd.comvoid
27411308Santhony.gutierrez@amd.comresetstats(ThreadContext *tc, Tick delay, Tick period)
27511308Santhony.gutierrez@amd.com{
27611308Santhony.gutierrez@amd.com    if (!tc->getCpuPtr()->params()->do_statistics_insts)
27711308Santhony.gutierrez@amd.com        return;
27811308Santhony.gutierrez@amd.com
27911308Santhony.gutierrez@amd.com
28011308Santhony.gutierrez@amd.com    Tick when = curTick() + delay * SimClock::Int::ns;
28111308Santhony.gutierrez@amd.com    Tick repeat = period * SimClock::Int::ns;
28211308Santhony.gutierrez@amd.com
28311308Santhony.gutierrez@amd.com    Stats::schedStatEvent(false, true, when, repeat);
28411308Santhony.gutierrez@amd.com}
28511308Santhony.gutierrez@amd.com
28611308Santhony.gutierrez@amd.comvoid
28711308Santhony.gutierrez@amd.comdumpstats(ThreadContext *tc, Tick delay, Tick period)
28811308Santhony.gutierrez@amd.com{
28911308Santhony.gutierrez@amd.com    if (!tc->getCpuPtr()->params()->do_statistics_insts)
29011308Santhony.gutierrez@amd.com        return;
29111308Santhony.gutierrez@amd.com
29211308Santhony.gutierrez@amd.com
29311308Santhony.gutierrez@amd.com    Tick when = curTick() + delay * SimClock::Int::ns;
294    Tick repeat = period * SimClock::Int::ns;
295
296    Stats::schedStatEvent(true, false, when, repeat);
297}
298
299void
300dumpresetstats(ThreadContext *tc, Tick delay, Tick period)
301{
302    if (!tc->getCpuPtr()->params()->do_statistics_insts)
303        return;
304
305
306    Tick when = curTick() + delay * SimClock::Int::ns;
307    Tick repeat = period * SimClock::Int::ns;
308
309    Stats::schedStatEvent(true, true, when, repeat);
310}
311
312void
313m5checkpoint(ThreadContext *tc, Tick delay, Tick period)
314{
315    if (!tc->getCpuPtr()->params()->do_checkpoint_insts)
316        return;
317
318    Tick when = curTick() + delay * SimClock::Int::ns;
319    Tick repeat = period * SimClock::Int::ns;
320
321    exitSimLoop("checkpoint", 0, when, repeat);
322}
323
324#if FULL_SYSTEM
325
326uint64_t
327readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
328{
329    const string &file = tc->getSystemPtr()->params()->readfile;
330    if (file.empty()) {
331        return ULL(0);
332    }
333
334    uint64_t result = 0;
335
336    int fd = ::open(file.c_str(), O_RDONLY, 0);
337    if (fd < 0)
338        panic("could not open file %s\n", file);
339
340    if (::lseek(fd, offset, SEEK_SET) < 0)
341        panic("could not seek: %s", strerror(errno));
342
343    char *buf = new char[len];
344    char *p = buf;
345    while (len > 0) {
346        int bytes = ::read(fd, p, len);
347        if (bytes <= 0)
348            break;
349
350        p += bytes;
351        result += bytes;
352        len -= bytes;
353    }
354
355    close(fd);
356    CopyIn(tc, vaddr, buf, result);
357    delete [] buf;
358    return result;
359}
360
361#endif
362
363void
364debugbreak(ThreadContext *tc)
365{
366    Debug::breakpoint();
367}
368
369void
370switchcpu(ThreadContext *tc)
371{
372    exitSimLoop("switchcpu");
373}
374
375//
376// This function is executed when annotated work items begin.  Depending on
377// what the user specified at the command line, the simulation may exit and/or
378// take a checkpoint when a certain work item begins.
379//
380void
381workbegin(ThreadContext *tc, uint64_t workid, uint64_t threadid)
382{
383    tc->getCpuPtr()->workItemBegin();
384    System *sys = tc->getSystemPtr();
385    const System::Params *params = sys->params();
386    sys->workItemBegin(threadid, workid);
387
388    DPRINTF(WorkItems, "Work Begin workid: %d, threadid %d\n", workid,
389            threadid);
390
391    //
392    // If specified, determine if this is the specific work item the user
393    // identified
394    //
395    if (params->work_item_id == -1 || params->work_item_id == workid) {
396
397        uint64_t systemWorkBeginCount = sys->incWorkItemsBegin();
398        int cpuId = tc->getCpuPtr()->cpuId();
399
400        if (params->work_cpus_ckpt_count != 0 &&
401            sys->markWorkItem(cpuId) >= params->work_cpus_ckpt_count) {
402            //
403            // If active cpus equals checkpoint count, create checkpoint
404            //
405            exitSimLoop("checkpoint");
406        }
407
408        if (systemWorkBeginCount == params->work_begin_ckpt_count) {
409            //
410            // Note: the string specified as the cause of the exit event must
411            // exactly equal "checkpoint" inorder to create a checkpoint
412            //
413            exitSimLoop("checkpoint");
414        }
415
416        if (systemWorkBeginCount == params->work_begin_exit_count) {
417            //
418            // If a certain number of work items started, exit simulation
419            //
420            exitSimLoop("work started count reach");
421        }
422
423        if (cpuId == params->work_begin_cpu_id_exit) {
424            //
425            // If work started on the cpu id specified, exit simulation
426            //
427            exitSimLoop("work started on specific cpu");
428        }
429    }
430}
431
432//
433// This function is executed when annotated work items end.  Depending on
434// what the user specified at the command line, the simulation may exit and/or
435// take a checkpoint when a certain work item ends.
436//
437void
438workend(ThreadContext *tc, uint64_t workid, uint64_t threadid)
439{
440    tc->getCpuPtr()->workItemEnd();
441    System *sys = tc->getSystemPtr();
442    const System::Params *params = sys->params();
443    sys->workItemEnd(threadid, workid);
444
445    DPRINTF(WorkItems, "Work End workid: %d, threadid %d\n", workid, threadid);
446
447    //
448    // If specified, determine if this is the specific work item the user
449    // identified
450    //
451    if (params->work_item_id == -1 || params->work_item_id == workid) {
452
453        uint64_t systemWorkEndCount = sys->incWorkItemsEnd();
454        int cpuId = tc->getCpuPtr()->cpuId();
455
456        if (params->work_cpus_ckpt_count != 0 &&
457            sys->markWorkItem(cpuId) >= params->work_cpus_ckpt_count) {
458            //
459            // If active cpus equals checkpoint count, create checkpoint
460            //
461            exitSimLoop("checkpoint");
462        }
463
464        if (params->work_end_ckpt_count != 0 &&
465            systemWorkEndCount == params->work_end_ckpt_count) {
466            //
467            // If total work items completed equals checkpoint count, create
468            // checkpoint
469            //
470            exitSimLoop("checkpoint");
471        }
472
473        if (params->work_end_exit_count != 0 &&
474            systemWorkEndCount == params->work_end_exit_count) {
475            //
476            // If total work items completed equals exit count, exit simulation
477            //
478            exitSimLoop("work items exit count reached");
479        }
480    }
481}
482
483} // namespace PseudoInst
484