pseudo_inst.cc revision 7914
1298SN/A/*
22188SN/A * Copyright (c) 2003-2006 The Regents of The University of Michigan
3298SN/A * All rights reserved.
4298SN/A *
5298SN/A * Redistribution and use in source and binary forms, with or without
6298SN/A * modification, are permitted provided that the following conditions are
7298SN/A * met: redistributions of source code must retain the above copyright
8298SN/A * notice, this list of conditions and the following disclaimer;
9298SN/A * redistributions in binary form must reproduce the above copyright
10298SN/A * notice, this list of conditions and the following disclaimer in the
11298SN/A * documentation and/or other materials provided with the distribution;
12298SN/A * neither the name of the copyright holders nor the names of its
13298SN/A * contributors may be used to endorse or promote products derived from
14298SN/A * this software without specific prior written permission.
15298SN/A *
16298SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17298SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18298SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19298SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20298SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21298SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22298SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23298SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24298SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25298SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26298SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
29298SN/A */
30298SN/A
311642SN/A#include <errno.h>
32954SN/A#include <fcntl.h>
33956SN/A#include <unistd.h>
34956SN/A
354078Sbinkertn@umich.edu#include <fstream>
36299SN/A#include <string>
37299SN/A
382170SN/A#include "arch/vtophys.hh"
395882Snate@binkert.org#include "base/debug.hh"
406658Snate@binkert.org#include "config/full_system.hh"
416658Snate@binkert.org#include "config/the_isa.hh"
421717SN/A#include "cpu/base.hh"
432680Sktlim@umich.edu#include "cpu/thread_context.hh"
442313SN/A#include "cpu/quiesce_event.hh"
455529Snate@binkert.org#include "params/BaseCPU.hh"
463565Sgblack@eecs.umich.edu#include "sim/pseudo_inst.hh"
47298SN/A#include "sim/serialize.hh"
485606Snate@binkert.org#include "sim/sim_events.hh"
49298SN/A#include "sim/sim_exit.hh"
50695SN/A#include "sim/stat_control.hh"
51695SN/A#include "sim/stats.hh"
52954SN/A#include "sim/system.hh"
536118Snate@binkert.org
545780Ssteve.reinhardt@amd.com#if FULL_SYSTEM
556118Snate@binkert.org#include "arch/kernel_stats.hh"
562080SN/A#include "sim/vptr.hh"
575780Ssteve.reinhardt@amd.com#endif
58298SN/A
59299SN/Ausing namespace std;
601052SN/A
61729SN/Ausing namespace Stats;
622107SN/Ausing namespace TheISA;
63298SN/A
645504Snate@binkert.orgnamespace PseudoInst {
655504Snate@binkert.org
665780Ssteve.reinhardt@amd.com#if FULL_SYSTEM
675780Ssteve.reinhardt@amd.com
685504Snate@binkert.orgvoid
695504Snate@binkert.orgarm(ThreadContext *tc)
70298SN/A{
715504Snate@binkert.org    if (tc->getKernelStats())
725504Snate@binkert.org        tc->getKernelStats()->arm();
735504Snate@binkert.org}
745504Snate@binkert.org
755504Snate@binkert.orgvoid
765504Snate@binkert.orgquiesce(ThreadContext *tc)
775504Snate@binkert.org{
785529Snate@binkert.org    if (!tc->getCpuPtr()->params()->do_quiesce)
795504Snate@binkert.org        return;
805504Snate@binkert.org
815504Snate@binkert.org    DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name());
825504Snate@binkert.org
835504Snate@binkert.org    tc->suspend();
845504Snate@binkert.org    if (tc->getKernelStats())
855504Snate@binkert.org        tc->getKernelStats()->quiesce();
865504Snate@binkert.org}
875504Snate@binkert.org
885504Snate@binkert.orgvoid
895504Snate@binkert.orgquiesceNs(ThreadContext *tc, uint64_t ns)
905504Snate@binkert.org{
917819Ssteve.reinhardt@amd.com    BaseCPU *cpu = tc->getCpuPtr();
927819Ssteve.reinhardt@amd.com
937819Ssteve.reinhardt@amd.com    if (!cpu->params()->do_quiesce || ns == 0)
945504Snate@binkert.org        return;
955504Snate@binkert.org
965504Snate@binkert.org    EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
975504Snate@binkert.org
987823Ssteve.reinhardt@amd.com    Tick resume = curTick() + SimClock::Int::ns * ns;
995504Snate@binkert.org
1007819Ssteve.reinhardt@amd.com    cpu->reschedule(quiesceEvent, resume, true);
1015504Snate@binkert.org
1025504Snate@binkert.org    DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n",
1037819Ssteve.reinhardt@amd.com            cpu->name(), ns, resume);
1045504Snate@binkert.org
1055504Snate@binkert.org    tc->suspend();
1065504Snate@binkert.org    if (tc->getKernelStats())
1075504Snate@binkert.org        tc->getKernelStats()->quiesce();
1085504Snate@binkert.org}
1095504Snate@binkert.org
1105504Snate@binkert.orgvoid
1115504Snate@binkert.orgquiesceCycles(ThreadContext *tc, uint64_t cycles)
1125504Snate@binkert.org{
1137819Ssteve.reinhardt@amd.com    BaseCPU *cpu = tc->getCpuPtr();
1147819Ssteve.reinhardt@amd.com
1157819Ssteve.reinhardt@amd.com    if (!cpu->params()->do_quiesce || cycles == 0)
1165504Snate@binkert.org        return;
1175504Snate@binkert.org
1185504Snate@binkert.org    EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
1195504Snate@binkert.org
1207823Ssteve.reinhardt@amd.com    Tick resume = curTick() + cpu->ticks(cycles);
1215504Snate@binkert.org
1227819Ssteve.reinhardt@amd.com    cpu->reschedule(quiesceEvent, resume, true);
1235504Snate@binkert.org
1245504Snate@binkert.org    DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n",
1257819Ssteve.reinhardt@amd.com            cpu->name(), cycles, resume);
1265504Snate@binkert.org
1275504Snate@binkert.org    tc->suspend();
1285504Snate@binkert.org    if (tc->getKernelStats())
1295504Snate@binkert.org        tc->getKernelStats()->quiesce();
1305504Snate@binkert.org}
1315504Snate@binkert.org
1325504Snate@binkert.orguint64_t
1335504Snate@binkert.orgquiesceTime(ThreadContext *tc)
1345504Snate@binkert.org{
1357064Snate@binkert.org    return (tc->readLastActivate() - tc->readLastSuspend()) /
1367064Snate@binkert.org        SimClock::Int::ns;
1375504Snate@binkert.org}
1385504Snate@binkert.org
1395780Ssteve.reinhardt@amd.com#endif
1405780Ssteve.reinhardt@amd.com
1415741Snate@binkert.orguint64_t
1425741Snate@binkert.orgrpns(ThreadContext *tc)
1435741Snate@binkert.org{
1447823Ssteve.reinhardt@amd.com    return curTick() / SimClock::Int::ns;
1455741Snate@binkert.org}
1465741Snate@binkert.org
1475504Snate@binkert.orgvoid
1485808Snate@binkert.orgwakeCPU(ThreadContext *tc, uint64_t cpuid)
1495808Snate@binkert.org{
1505808Snate@binkert.org    System *sys = tc->getSystemPtr();
1515808Snate@binkert.org    ThreadContext *other_tc = sys->threadContexts[cpuid];
1525808Snate@binkert.org    if (other_tc->status() == ThreadContext::Suspended)
1535808Snate@binkert.org        other_tc->activate();
1545808Snate@binkert.org}
1555808Snate@binkert.org
1565808Snate@binkert.orgvoid
1575504Snate@binkert.orgm5exit(ThreadContext *tc, Tick delay)
1585504Snate@binkert.org{
1597823Ssteve.reinhardt@amd.com    Tick when = curTick() + delay * SimClock::Int::ns;
1607819Ssteve.reinhardt@amd.com    exitSimLoop("m5_exit instruction encountered", 0, when);
1615504Snate@binkert.org}
1625504Snate@binkert.org
1635780Ssteve.reinhardt@amd.com#if FULL_SYSTEM
1645780Ssteve.reinhardt@amd.com
1655504Snate@binkert.orgvoid
1665504Snate@binkert.orgloadsymbol(ThreadContext *tc)
1675504Snate@binkert.org{
1685504Snate@binkert.org    const string &filename = tc->getCpuPtr()->system->params()->symbolfile;
1695504Snate@binkert.org    if (filename.empty()) {
1705504Snate@binkert.org        return;
171711SN/A    }
172711SN/A
1735504Snate@binkert.org    std::string buffer;
1745504Snate@binkert.org    ifstream file(filename.c_str());
175310SN/A
1765504Snate@binkert.org    if (!file)
1775504Snate@binkert.org        fatal("file error: Can't open symbol table file %s\n", filename);
1783373Sstever@eecs.umich.edu
1795504Snate@binkert.org    while (!file.eof()) {
1805504Snate@binkert.org        getline(file, buffer);
1815504Snate@binkert.org
1825504Snate@binkert.org        if (buffer.empty())
1835504Snate@binkert.org            continue;
1845504Snate@binkert.org
1856227Snate@binkert.org        string::size_type idx = buffer.find(' ');
1865504Snate@binkert.org        if (idx == string::npos)
1875504Snate@binkert.org            continue;
1885504Snate@binkert.org
1895504Snate@binkert.org        string address = "0x" + buffer.substr(0, idx);
1905504Snate@binkert.org        eat_white(address);
1915504Snate@binkert.org        if (address.empty())
1925504Snate@binkert.org            continue;
1935504Snate@binkert.org
1945504Snate@binkert.org        // Skip over letter and space
1955504Snate@binkert.org        string symbol = buffer.substr(idx + 3);
1965504Snate@binkert.org        eat_white(symbol);
1975504Snate@binkert.org        if (symbol.empty())
1985504Snate@binkert.org            continue;
1995504Snate@binkert.org
2005504Snate@binkert.org        Addr addr;
2015504Snate@binkert.org        if (!to_number(address, addr))
2025504Snate@binkert.org            continue;
2035504Snate@binkert.org
2045504Snate@binkert.org        if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
2055504Snate@binkert.org            continue;
2065504Snate@binkert.org
2075504Snate@binkert.org
2085504Snate@binkert.org        DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
2095504Snate@binkert.org    }
2105504Snate@binkert.org    file.close();
2115504Snate@binkert.org}
2125504Snate@binkert.org
2135504Snate@binkert.orgvoid
2145780Ssteve.reinhardt@amd.comaddsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
2155780Ssteve.reinhardt@amd.com{
2165780Ssteve.reinhardt@amd.com    char symb[100];
2175780Ssteve.reinhardt@amd.com    CopyStringOut(tc, symb, symbolAddr, 100);
2185780Ssteve.reinhardt@amd.com    std::string symbol(symb);
2195780Ssteve.reinhardt@amd.com
2205780Ssteve.reinhardt@amd.com    DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
2215780Ssteve.reinhardt@amd.com
2225780Ssteve.reinhardt@amd.com    tc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
2235952Ssaidi@eecs.umich.edu    debugSymbolTable->insert(addr,symbol);
2245780Ssteve.reinhardt@amd.com}
2255780Ssteve.reinhardt@amd.com
2265780Ssteve.reinhardt@amd.com#endif
2275780Ssteve.reinhardt@amd.com
2285780Ssteve.reinhardt@amd.com
2295780Ssteve.reinhardt@amd.comvoid
2305504Snate@binkert.orgresetstats(ThreadContext *tc, Tick delay, Tick period)
2315504Snate@binkert.org{
2325529Snate@binkert.org    if (!tc->getCpuPtr()->params()->do_statistics_insts)
2335504Snate@binkert.org        return;
2345504Snate@binkert.org
2355504Snate@binkert.org
2367823Ssteve.reinhardt@amd.com    Tick when = curTick() + delay * SimClock::Int::ns;
2377064Snate@binkert.org    Tick repeat = period * SimClock::Int::ns;
2385504Snate@binkert.org
2397822Ssteve.reinhardt@amd.com    Stats::schedStatEvent(false, true, when, repeat);
2405504Snate@binkert.org}
2415504Snate@binkert.org
2425504Snate@binkert.orgvoid
2435504Snate@binkert.orgdumpstats(ThreadContext *tc, Tick delay, Tick period)
2445504Snate@binkert.org{
2455529Snate@binkert.org    if (!tc->getCpuPtr()->params()->do_statistics_insts)
2465504Snate@binkert.org        return;
2475504Snate@binkert.org
2485504Snate@binkert.org
2497823Ssteve.reinhardt@amd.com    Tick when = curTick() + delay * SimClock::Int::ns;
2507064Snate@binkert.org    Tick repeat = period * SimClock::Int::ns;
2515504Snate@binkert.org
2527822Ssteve.reinhardt@amd.com    Stats::schedStatEvent(true, false, when, repeat);
2535504Snate@binkert.org}
2545504Snate@binkert.org
2555504Snate@binkert.orgvoid
2565504Snate@binkert.orgdumpresetstats(ThreadContext *tc, Tick delay, Tick period)
2575504Snate@binkert.org{
2585529Snate@binkert.org    if (!tc->getCpuPtr()->params()->do_statistics_insts)
2595504Snate@binkert.org        return;
2605504Snate@binkert.org
2615504Snate@binkert.org
2627823Ssteve.reinhardt@amd.com    Tick when = curTick() + delay * SimClock::Int::ns;
2637064Snate@binkert.org    Tick repeat = period * SimClock::Int::ns;
2645504Snate@binkert.org
2657822Ssteve.reinhardt@amd.com    Stats::schedStatEvent(true, true, when, repeat);
2665504Snate@binkert.org}
2675504Snate@binkert.org
2685504Snate@binkert.orgvoid
2695504Snate@binkert.orgm5checkpoint(ThreadContext *tc, Tick delay, Tick period)
2705504Snate@binkert.org{
2715529Snate@binkert.org    if (!tc->getCpuPtr()->params()->do_checkpoint_insts)
2725504Snate@binkert.org        return;
2735504Snate@binkert.org
2747823Ssteve.reinhardt@amd.com    Tick when = curTick() + delay * SimClock::Int::ns;
2757064Snate@binkert.org    Tick repeat = period * SimClock::Int::ns;
2765504Snate@binkert.org
2777819Ssteve.reinhardt@amd.com    exitSimLoop("checkpoint", 0, when, repeat);
2785504Snate@binkert.org}
2795504Snate@binkert.org
2805780Ssteve.reinhardt@amd.com#if FULL_SYSTEM
2815780Ssteve.reinhardt@amd.com
2825504Snate@binkert.orguint64_t
2835504Snate@binkert.orgreadfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
2845504Snate@binkert.org{
2855504Snate@binkert.org    const string &file = tc->getSystemPtr()->params()->readfile;
2865504Snate@binkert.org    if (file.empty()) {
2875504Snate@binkert.org        return ULL(0);
288310SN/A    }
289299SN/A
2905504Snate@binkert.org    uint64_t result = 0;
2912188SN/A
2925504Snate@binkert.org    int fd = ::open(file.c_str(), O_RDONLY, 0);
2935504Snate@binkert.org    if (fd < 0)
2945504Snate@binkert.org        panic("could not open file %s\n", file);
2952235SN/A
2965504Snate@binkert.org    if (::lseek(fd, offset, SEEK_SET) < 0)
2975504Snate@binkert.org        panic("could not seek: %s", strerror(errno));
2983368Sstever@eecs.umich.edu
2995504Snate@binkert.org    char *buf = new char[len];
3005504Snate@binkert.org    char *p = buf;
3015504Snate@binkert.org    while (len > 0) {
3025504Snate@binkert.org        int bytes = ::read(fd, p, len);
3035504Snate@binkert.org        if (bytes <= 0)
3045504Snate@binkert.org            break;
3053368Sstever@eecs.umich.edu
3065504Snate@binkert.org        p += bytes;
3075504Snate@binkert.org        result += bytes;
3085504Snate@binkert.org        len -= bytes;
3092188SN/A    }
3102188SN/A
3115504Snate@binkert.org    close(fd);
3125504Snate@binkert.org    CopyIn(tc, vaddr, buf, result);
3135504Snate@binkert.org    delete [] buf;
3145504Snate@binkert.org    return result;
3155504Snate@binkert.org}
3162188SN/A
3175780Ssteve.reinhardt@amd.com#endif
3185780Ssteve.reinhardt@amd.com
3195504Snate@binkert.orgvoid
3205504Snate@binkert.orgdebugbreak(ThreadContext *tc)
3215504Snate@binkert.org{
3225504Snate@binkert.org    debug_break();
3235504Snate@binkert.org}
3242235SN/A
3255504Snate@binkert.orgvoid
3265504Snate@binkert.orgswitchcpu(ThreadContext *tc)
3275504Snate@binkert.org{
3285504Snate@binkert.org    exitSimLoop("switchcpu");
3295504Snate@binkert.org}
3303368Sstever@eecs.umich.edu
3317914SBrad.Beckmann@amd.com//
3327914SBrad.Beckmann@amd.com// This function is executed when annotated work items begin.  Depending on
3337914SBrad.Beckmann@amd.com// what the user specified at the command line, the simulation may exit and/or
3347914SBrad.Beckmann@amd.com// take a checkpoint when a certain work item begins.
3357914SBrad.Beckmann@amd.com//
3367914SBrad.Beckmann@amd.comvoid
3377914SBrad.Beckmann@amd.comworkbegin(ThreadContext *tc, uint64_t workid, uint64_t threadid)
3387914SBrad.Beckmann@amd.com{
3397914SBrad.Beckmann@amd.com    tc->getCpuPtr()->workItemBegin();
3407914SBrad.Beckmann@amd.com    System *sys = tc->getSystemPtr();
3417914SBrad.Beckmann@amd.com
3427914SBrad.Beckmann@amd.com    DPRINTF(WorkItems, "Work Begin workid: %d, threadid %d\n", workid,
3437914SBrad.Beckmann@amd.com            threadid);
3447914SBrad.Beckmann@amd.com
3457914SBrad.Beckmann@amd.com    //
3467914SBrad.Beckmann@amd.com    // If specified, determine if this is the specific work item the user
3477914SBrad.Beckmann@amd.com    // identified
3487914SBrad.Beckmann@amd.com    //
3497914SBrad.Beckmann@amd.com    if (sys->params()->work_item_id == -1 ||
3507914SBrad.Beckmann@amd.com        sys->params()->work_item_id == workid) {
3517914SBrad.Beckmann@amd.com
3527914SBrad.Beckmann@amd.com        uint64_t systemWorkBeginCount = sys->incWorkItemsBegin();
3537914SBrad.Beckmann@amd.com        int cpuId = tc->getCpuPtr()->cpuId();
3547914SBrad.Beckmann@amd.com
3557914SBrad.Beckmann@amd.com        if (sys->params()->work_cpus_ckpt_count != 0 &&
3567914SBrad.Beckmann@amd.com            sys->markWorkItem(cpuId) >= sys->params()->work_cpus_ckpt_count) {
3577914SBrad.Beckmann@amd.com            //
3587914SBrad.Beckmann@amd.com            // If active cpus equals checkpoint count, create checkpoint
3597914SBrad.Beckmann@amd.com            //
3607914SBrad.Beckmann@amd.com            Event *event = new SimLoopExitEvent("checkpoint", 0);
3617914SBrad.Beckmann@amd.com            mainEventQueue.schedule(event, curTick());
3627914SBrad.Beckmann@amd.com        }
3637914SBrad.Beckmann@amd.com
3647914SBrad.Beckmann@amd.com        if (systemWorkBeginCount == sys->params()->work_begin_ckpt_count) {
3657914SBrad.Beckmann@amd.com            //
3667914SBrad.Beckmann@amd.com            // Note: the string specified as the cause of the exit event must
3677914SBrad.Beckmann@amd.com            // exactly equal "checkpoint" inorder to create a checkpoint
3687914SBrad.Beckmann@amd.com            //
3697914SBrad.Beckmann@amd.com            Event *event = new SimLoopExitEvent("checkpoint", 0);
3707914SBrad.Beckmann@amd.com            mainEventQueue.schedule(event, curTick());
3717914SBrad.Beckmann@amd.com        }
3727914SBrad.Beckmann@amd.com
3737914SBrad.Beckmann@amd.com        if (systemWorkBeginCount == sys->params()->work_begin_exit_count) {
3747914SBrad.Beckmann@amd.com            //
3757914SBrad.Beckmann@amd.com            // If a certain number of work items started, exit simulation
3767914SBrad.Beckmann@amd.com            //
3777914SBrad.Beckmann@amd.com            Event *event = new SimLoopExitEvent("work started count reach", 0);
3787914SBrad.Beckmann@amd.com            mainEventQueue.schedule(event, curTick());
3797914SBrad.Beckmann@amd.com        }
3807914SBrad.Beckmann@amd.com
3817914SBrad.Beckmann@amd.com        if (tc->getCpuPtr()->cpuId() == sys->params()->work_begin_cpu_id_exit) {
3827914SBrad.Beckmann@amd.com            //
3837914SBrad.Beckmann@amd.com            // If work started on the specific cpu id specified, exit simulation
3847914SBrad.Beckmann@amd.com            //
3857914SBrad.Beckmann@amd.com            Event *event = new SimLoopExitEvent("work started on specific cpu",
3867914SBrad.Beckmann@amd.com                                                0);
3877914SBrad.Beckmann@amd.com
3887914SBrad.Beckmann@amd.com            mainEventQueue.schedule(event, curTick() + 1);
3897914SBrad.Beckmann@amd.com        }
3907914SBrad.Beckmann@amd.com    }
3917914SBrad.Beckmann@amd.com}
3927914SBrad.Beckmann@amd.com
3937914SBrad.Beckmann@amd.com//
3947914SBrad.Beckmann@amd.com// This function is executed when annotated work items end.  Depending on
3957914SBrad.Beckmann@amd.com// what the user specified at the command line, the simulation may exit and/or
3967914SBrad.Beckmann@amd.com// take a checkpoint when a certain work item ends.
3977914SBrad.Beckmann@amd.com//
3987914SBrad.Beckmann@amd.comvoid
3997914SBrad.Beckmann@amd.comworkend(ThreadContext *tc, uint64_t workid, uint64_t threadid)
4007914SBrad.Beckmann@amd.com{
4017914SBrad.Beckmann@amd.com    tc->getCpuPtr()->workItemEnd();
4027914SBrad.Beckmann@amd.com    System *sys = tc->getSystemPtr();
4037914SBrad.Beckmann@amd.com
4047914SBrad.Beckmann@amd.com    DPRINTF(WorkItems, "Work End workid: %d, threadid %d\n", workid, threadid);
4057914SBrad.Beckmann@amd.com
4067914SBrad.Beckmann@amd.com    //
4077914SBrad.Beckmann@amd.com    // If specified, determine if this is the specific work item the user
4087914SBrad.Beckmann@amd.com    // identified
4097914SBrad.Beckmann@amd.com    //
4107914SBrad.Beckmann@amd.com    if (sys->params()->work_item_id == -1 ||
4117914SBrad.Beckmann@amd.com        sys->params()->work_item_id == workid) {
4127914SBrad.Beckmann@amd.com
4137914SBrad.Beckmann@amd.com        uint64_t systemWorkEndCount = sys->incWorkItemsEnd();
4147914SBrad.Beckmann@amd.com        int cpuId = tc->getCpuPtr()->cpuId();
4157914SBrad.Beckmann@amd.com
4167914SBrad.Beckmann@amd.com        if (sys->params()->work_cpus_ckpt_count != 0 &&
4177914SBrad.Beckmann@amd.com            sys->markWorkItem(cpuId) >= sys->params()->work_cpus_ckpt_count) {
4187914SBrad.Beckmann@amd.com            //
4197914SBrad.Beckmann@amd.com            // If active cpus equals checkpoint count, create checkpoint
4207914SBrad.Beckmann@amd.com            //
4217914SBrad.Beckmann@amd.com            Event *event = new SimLoopExitEvent("checkpoint", 0);
4227914SBrad.Beckmann@amd.com            mainEventQueue.schedule(event, curTick());
4237914SBrad.Beckmann@amd.com        }
4247914SBrad.Beckmann@amd.com
4257914SBrad.Beckmann@amd.com        if (sys->params()->work_end_ckpt_count != 0 &&
4267914SBrad.Beckmann@amd.com            systemWorkEndCount == sys->params()->work_end_ckpt_count) {
4277914SBrad.Beckmann@amd.com            //
4287914SBrad.Beckmann@amd.com            // If total work items completed equals checkpoint count, create
4297914SBrad.Beckmann@amd.com            // checkpoint
4307914SBrad.Beckmann@amd.com            //
4317914SBrad.Beckmann@amd.com            Event *event = new SimLoopExitEvent("checkpoint", 0);
4327914SBrad.Beckmann@amd.com            mainEventQueue.schedule(event, curTick());
4337914SBrad.Beckmann@amd.com        }
4347914SBrad.Beckmann@amd.com
4357914SBrad.Beckmann@amd.com        if (sys->params()->work_end_exit_count != 0 &&
4367914SBrad.Beckmann@amd.com            systemWorkEndCount == sys->params()->work_end_exit_count) {
4377914SBrad.Beckmann@amd.com            //
4387914SBrad.Beckmann@amd.com            // If total work items completed equals exit count, exit simulation
4397914SBrad.Beckmann@amd.com            //
4407914SBrad.Beckmann@amd.com            Event *event = new SimLoopExitEvent("work items exit count reached",
4417914SBrad.Beckmann@amd.com                                                0);
4427914SBrad.Beckmann@amd.com
4437914SBrad.Beckmann@amd.com            mainEventQueue.schedule(event, curTick());
4447914SBrad.Beckmann@amd.com        }
4457914SBrad.Beckmann@amd.com    }
4467914SBrad.Beckmann@amd.com}
4477914SBrad.Beckmann@amd.com
4487811Ssteve.reinhardt@amd.com} // namespace PseudoInst
449