pseudo_inst.cc revision 5780
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
385529Snate@binkert.org#include "arch/kernel_stats.hh"
392170SN/A#include "arch/vtophys.hh"
403089Ssaidi@eecs.umich.edu#include "base/annotate.hh"
411717SN/A#include "cpu/base.hh"
422680Sktlim@umich.edu#include "cpu/thread_context.hh"
432313SN/A#include "cpu/quiesce_event.hh"
445529Snate@binkert.org#include "params/BaseCPU.hh"
453565Sgblack@eecs.umich.edu#include "sim/pseudo_inst.hh"
46298SN/A#include "sim/serialize.hh"
475606Snate@binkert.org#include "sim/sim_events.hh"
48298SN/A#include "sim/sim_exit.hh"
49695SN/A#include "sim/stat_control.hh"
50695SN/A#include "sim/stats.hh"
51954SN/A#include "sim/system.hh"
521052SN/A#include "sim/debug.hh"
535780Ssteve.reinhardt@amd.com#if FULL_SYSTEM
542080SN/A#include "sim/vptr.hh"
555780Ssteve.reinhardt@amd.com#endif
56298SN/A
57299SN/Ausing namespace std;
581052SN/A
59729SN/Ausing namespace Stats;
602107SN/Ausing namespace TheISA;
61298SN/A
625504Snate@binkert.orgnamespace PseudoInst {
635504Snate@binkert.org
645780Ssteve.reinhardt@amd.com#if FULL_SYSTEM
655780Ssteve.reinhardt@amd.com
665504Snate@binkert.orgvoid
675504Snate@binkert.orgarm(ThreadContext *tc)
68298SN/A{
695504Snate@binkert.org    if (tc->getKernelStats())
705504Snate@binkert.org        tc->getKernelStats()->arm();
715504Snate@binkert.org}
725504Snate@binkert.org
735504Snate@binkert.orgvoid
745504Snate@binkert.orgquiesce(ThreadContext *tc)
755504Snate@binkert.org{
765529Snate@binkert.org    if (!tc->getCpuPtr()->params()->do_quiesce)
775504Snate@binkert.org        return;
785504Snate@binkert.org
795504Snate@binkert.org    DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name());
805504Snate@binkert.org
815504Snate@binkert.org    tc->suspend();
825504Snate@binkert.org    if (tc->getKernelStats())
835504Snate@binkert.org        tc->getKernelStats()->quiesce();
845504Snate@binkert.org}
855504Snate@binkert.org
865504Snate@binkert.orgvoid
875504Snate@binkert.orgquiesceNs(ThreadContext *tc, uint64_t ns)
885504Snate@binkert.org{
895529Snate@binkert.org    if (!tc->getCpuPtr()->params()->do_quiesce || ns == 0)
905504Snate@binkert.org        return;
915504Snate@binkert.org
925504Snate@binkert.org    EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
935504Snate@binkert.org
945504Snate@binkert.org    Tick resume = curTick + Clock::Int::ns * ns;
955504Snate@binkert.org
965606Snate@binkert.org    mainEventQueue.reschedule(quiesceEvent, resume, true);
975504Snate@binkert.org
985504Snate@binkert.org    DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n",
995504Snate@binkert.org            tc->getCpuPtr()->name(), ns, resume);
1005504Snate@binkert.org
1015504Snate@binkert.org    tc->suspend();
1025504Snate@binkert.org    if (tc->getKernelStats())
1035504Snate@binkert.org        tc->getKernelStats()->quiesce();
1045504Snate@binkert.org}
1055504Snate@binkert.org
1065504Snate@binkert.orgvoid
1075504Snate@binkert.orgquiesceCycles(ThreadContext *tc, uint64_t cycles)
1085504Snate@binkert.org{
1095529Snate@binkert.org    if (!tc->getCpuPtr()->params()->do_quiesce || cycles == 0)
1105504Snate@binkert.org        return;
1115504Snate@binkert.org
1125504Snate@binkert.org    EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
1135504Snate@binkert.org
1145504Snate@binkert.org    Tick resume = curTick + tc->getCpuPtr()->ticks(cycles);
1155504Snate@binkert.org
1165606Snate@binkert.org    mainEventQueue.reschedule(quiesceEvent, resume, true);
1175504Snate@binkert.org
1185504Snate@binkert.org    DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n",
1195504Snate@binkert.org            tc->getCpuPtr()->name(), cycles, resume);
1205504Snate@binkert.org
1215504Snate@binkert.org    tc->suspend();
1225504Snate@binkert.org    if (tc->getKernelStats())
1235504Snate@binkert.org        tc->getKernelStats()->quiesce();
1245504Snate@binkert.org}
1255504Snate@binkert.org
1265504Snate@binkert.orguint64_t
1275504Snate@binkert.orgquiesceTime(ThreadContext *tc)
1285504Snate@binkert.org{
1295504Snate@binkert.org    return (tc->readLastActivate() - tc->readLastSuspend()) / Clock::Int::ns;
1305504Snate@binkert.org}
1315504Snate@binkert.org
1325780Ssteve.reinhardt@amd.com#endif
1335780Ssteve.reinhardt@amd.com
1345741Snate@binkert.orguint64_t
1355741Snate@binkert.orgrpns(ThreadContext *tc)
1365741Snate@binkert.org{
1375741Snate@binkert.org    return curTick / Clock::Int::ns;
1385741Snate@binkert.org}
1395741Snate@binkert.org
1405504Snate@binkert.orgvoid
1415504Snate@binkert.orgm5exit(ThreadContext *tc, Tick delay)
1425504Snate@binkert.org{
1435504Snate@binkert.org    Tick when = curTick + delay * Clock::Int::ns;
1445606Snate@binkert.org    Event *event = new SimLoopExitEvent("m5_exit instruction encountered", 0);
1455606Snate@binkert.org    mainEventQueue.schedule(event, when);
1465504Snate@binkert.org}
1475504Snate@binkert.org
1485780Ssteve.reinhardt@amd.com#if FULL_SYSTEM
1495780Ssteve.reinhardt@amd.com
1505504Snate@binkert.orgvoid
1515504Snate@binkert.orgloadsymbol(ThreadContext *tc)
1525504Snate@binkert.org{
1535504Snate@binkert.org    const string &filename = tc->getCpuPtr()->system->params()->symbolfile;
1545504Snate@binkert.org    if (filename.empty()) {
1555504Snate@binkert.org        return;
156711SN/A    }
157711SN/A
1585504Snate@binkert.org    std::string buffer;
1595504Snate@binkert.org    ifstream file(filename.c_str());
160310SN/A
1615504Snate@binkert.org    if (!file)
1625504Snate@binkert.org        fatal("file error: Can't open symbol table file %s\n", filename);
1633373Sstever@eecs.umich.edu
1645504Snate@binkert.org    while (!file.eof()) {
1655504Snate@binkert.org        getline(file, buffer);
1665504Snate@binkert.org
1675504Snate@binkert.org        if (buffer.empty())
1685504Snate@binkert.org            continue;
1695504Snate@binkert.org
1705504Snate@binkert.org        int idx = buffer.find(' ');
1715504Snate@binkert.org        if (idx == string::npos)
1725504Snate@binkert.org            continue;
1735504Snate@binkert.org
1745504Snate@binkert.org        string address = "0x" + buffer.substr(0, idx);
1755504Snate@binkert.org        eat_white(address);
1765504Snate@binkert.org        if (address.empty())
1775504Snate@binkert.org            continue;
1785504Snate@binkert.org
1795504Snate@binkert.org        // Skip over letter and space
1805504Snate@binkert.org        string symbol = buffer.substr(idx + 3);
1815504Snate@binkert.org        eat_white(symbol);
1825504Snate@binkert.org        if (symbol.empty())
1835504Snate@binkert.org            continue;
1845504Snate@binkert.org
1855504Snate@binkert.org        Addr addr;
1865504Snate@binkert.org        if (!to_number(address, addr))
1875504Snate@binkert.org            continue;
1885504Snate@binkert.org
1895504Snate@binkert.org        if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
1905504Snate@binkert.org            continue;
1915504Snate@binkert.org
1925504Snate@binkert.org
1935504Snate@binkert.org        DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
1945504Snate@binkert.org    }
1955504Snate@binkert.org    file.close();
1965504Snate@binkert.org}
1975504Snate@binkert.org
1985504Snate@binkert.orgvoid
1995780Ssteve.reinhardt@amd.comaddsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
2005780Ssteve.reinhardt@amd.com{
2015780Ssteve.reinhardt@amd.com    char symb[100];
2025780Ssteve.reinhardt@amd.com    CopyStringOut(tc, symb, symbolAddr, 100);
2035780Ssteve.reinhardt@amd.com    std::string symbol(symb);
2045780Ssteve.reinhardt@amd.com
2055780Ssteve.reinhardt@amd.com    DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
2065780Ssteve.reinhardt@amd.com
2075780Ssteve.reinhardt@amd.com    tc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
2085780Ssteve.reinhardt@amd.com}
2095780Ssteve.reinhardt@amd.com
2105780Ssteve.reinhardt@amd.com#endif
2115780Ssteve.reinhardt@amd.com
2125780Ssteve.reinhardt@amd.com
2135780Ssteve.reinhardt@amd.comvoid
2145504Snate@binkert.orgresetstats(ThreadContext *tc, Tick delay, Tick period)
2155504Snate@binkert.org{
2165529Snate@binkert.org    if (!tc->getCpuPtr()->params()->do_statistics_insts)
2175504Snate@binkert.org        return;
2185504Snate@binkert.org
2195504Snate@binkert.org
2205504Snate@binkert.org    Tick when = curTick + delay * Clock::Int::ns;
2215504Snate@binkert.org    Tick repeat = period * Clock::Int::ns;
2225504Snate@binkert.org
2235504Snate@binkert.org    Stats::StatEvent(false, true, when, repeat);
2245504Snate@binkert.org}
2255504Snate@binkert.org
2265504Snate@binkert.orgvoid
2275504Snate@binkert.orgdumpstats(ThreadContext *tc, Tick delay, Tick period)
2285504Snate@binkert.org{
2295529Snate@binkert.org    if (!tc->getCpuPtr()->params()->do_statistics_insts)
2305504Snate@binkert.org        return;
2315504Snate@binkert.org
2325504Snate@binkert.org
2335504Snate@binkert.org    Tick when = curTick + delay * Clock::Int::ns;
2345504Snate@binkert.org    Tick repeat = period * Clock::Int::ns;
2355504Snate@binkert.org
2365504Snate@binkert.org    Stats::StatEvent(true, false, when, repeat);
2375504Snate@binkert.org}
2385504Snate@binkert.org
2395504Snate@binkert.orgvoid
2405504Snate@binkert.orgdumpresetstats(ThreadContext *tc, Tick delay, Tick period)
2415504Snate@binkert.org{
2425529Snate@binkert.org    if (!tc->getCpuPtr()->params()->do_statistics_insts)
2435504Snate@binkert.org        return;
2445504Snate@binkert.org
2455504Snate@binkert.org
2465504Snate@binkert.org    Tick when = curTick + delay * Clock::Int::ns;
2475504Snate@binkert.org    Tick repeat = period * Clock::Int::ns;
2485504Snate@binkert.org
2495504Snate@binkert.org    Stats::StatEvent(true, true, when, repeat);
2505504Snate@binkert.org}
2515504Snate@binkert.org
2525504Snate@binkert.orgvoid
2535504Snate@binkert.orgm5checkpoint(ThreadContext *tc, Tick delay, Tick period)
2545504Snate@binkert.org{
2555529Snate@binkert.org    if (!tc->getCpuPtr()->params()->do_checkpoint_insts)
2565504Snate@binkert.org        return;
2575504Snate@binkert.org
2585504Snate@binkert.org    Tick when = curTick + delay * Clock::Int::ns;
2595504Snate@binkert.org    Tick repeat = period * Clock::Int::ns;
2605504Snate@binkert.org
2615606Snate@binkert.org    Event *event = new SimLoopExitEvent("checkpoint", 0, repeat);
2625606Snate@binkert.org    mainEventQueue.schedule(event, when);
2635504Snate@binkert.org}
2645504Snate@binkert.org
2655780Ssteve.reinhardt@amd.com#if FULL_SYSTEM
2665780Ssteve.reinhardt@amd.com
2675504Snate@binkert.orguint64_t
2685504Snate@binkert.orgreadfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
2695504Snate@binkert.org{
2705504Snate@binkert.org    const string &file = tc->getSystemPtr()->params()->readfile;
2715504Snate@binkert.org    if (file.empty()) {
2725504Snate@binkert.org        return ULL(0);
273310SN/A    }
274299SN/A
2755504Snate@binkert.org    uint64_t result = 0;
2762188SN/A
2775504Snate@binkert.org    int fd = ::open(file.c_str(), O_RDONLY, 0);
2785504Snate@binkert.org    if (fd < 0)
2795504Snate@binkert.org        panic("could not open file %s\n", file);
2802235SN/A
2815504Snate@binkert.org    if (::lseek(fd, offset, SEEK_SET) < 0)
2825504Snate@binkert.org        panic("could not seek: %s", strerror(errno));
2833368Sstever@eecs.umich.edu
2845504Snate@binkert.org    char *buf = new char[len];
2855504Snate@binkert.org    char *p = buf;
2865504Snate@binkert.org    while (len > 0) {
2875504Snate@binkert.org        int bytes = ::read(fd, p, len);
2885504Snate@binkert.org        if (bytes <= 0)
2895504Snate@binkert.org            break;
2903368Sstever@eecs.umich.edu
2915504Snate@binkert.org        p += bytes;
2925504Snate@binkert.org        result += bytes;
2935504Snate@binkert.org        len -= bytes;
2942188SN/A    }
2952188SN/A
2965504Snate@binkert.org    close(fd);
2975504Snate@binkert.org    CopyIn(tc, vaddr, buf, result);
2985504Snate@binkert.org    delete [] buf;
2995504Snate@binkert.org    return result;
3005504Snate@binkert.org}
3012188SN/A
3025780Ssteve.reinhardt@amd.com#endif
3035780Ssteve.reinhardt@amd.com
3045504Snate@binkert.orgvoid
3055504Snate@binkert.orgdebugbreak(ThreadContext *tc)
3065504Snate@binkert.org{
3075504Snate@binkert.org    debug_break();
3085504Snate@binkert.org}
3092235SN/A
3105504Snate@binkert.orgvoid
3115504Snate@binkert.orgswitchcpu(ThreadContext *tc)
3125504Snate@binkert.org{
3135504Snate@binkert.org    exitSimLoop("switchcpu");
3145504Snate@binkert.org}
3153368Sstever@eecs.umich.edu
3165504Snate@binkert.org/* namespace PseudoInst */ }
317