base.cc revision 2519
111723Sar4jc@virginia.edu/*
211723Sar4jc@virginia.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan
311723Sar4jc@virginia.edu * All rights reserved.
411723Sar4jc@virginia.edu *
511723Sar4jc@virginia.edu * Redistribution and use in source and binary forms, with or without
611723Sar4jc@virginia.edu * modification, are permitted provided that the following conditions are
711723Sar4jc@virginia.edu * met: redistributions of source code must retain the above copyright
811723Sar4jc@virginia.edu * notice, this list of conditions and the following disclaimer;
911723Sar4jc@virginia.edu * redistributions in binary form must reproduce the above copyright
1011723Sar4jc@virginia.edu * notice, this list of conditions and the following disclaimer in the
1111723Sar4jc@virginia.edu * documentation and/or other materials provided with the distribution;
1211723Sar4jc@virginia.edu * neither the name of the copyright holders nor the names of its
1311723Sar4jc@virginia.edu * contributors may be used to endorse or promote products derived from
1411723Sar4jc@virginia.edu * this software without specific prior written permission.
1511723Sar4jc@virginia.edu *
1611723Sar4jc@virginia.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1711723Sar4jc@virginia.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1811723Sar4jc@virginia.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1911723Sar4jc@virginia.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2011723Sar4jc@virginia.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2111723Sar4jc@virginia.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2211723Sar4jc@virginia.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311723Sar4jc@virginia.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2411723Sar4jc@virginia.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511723Sar4jc@virginia.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2611723Sar4jc@virginia.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2711723Sar4jc@virginia.edu */
2811723Sar4jc@virginia.edu
2911723Sar4jc@virginia.edu#include <cmath>
3011723Sar4jc@virginia.edu#include <cstdio>
3111723Sar4jc@virginia.edu#include <cstdlib>
3211723Sar4jc@virginia.edu#include <iostream>
3311723Sar4jc@virginia.edu#include <iomanip>
3411723Sar4jc@virginia.edu#include <list>
3511723Sar4jc@virginia.edu#include <sstream>
3611723Sar4jc@virginia.edu#include <string>
3711723Sar4jc@virginia.edu
3811723Sar4jc@virginia.edu#include "arch/utility.hh"
3911723Sar4jc@virginia.edu#include "base/cprintf.hh"
4011723Sar4jc@virginia.edu#include "base/inifile.hh"
4111723Sar4jc@virginia.edu#include "base/loader/symtab.hh"
4211723Sar4jc@virginia.edu#include "base/misc.hh"
4311723Sar4jc@virginia.edu#include "base/pollevent.hh"
4411723Sar4jc@virginia.edu#include "base/range.hh"
4511723Sar4jc@virginia.edu#include "base/stats/events.hh"
4611723Sar4jc@virginia.edu#include "base/trace.hh"
4711723Sar4jc@virginia.edu#include "cpu/base.hh"
4811723Sar4jc@virginia.edu#include "cpu/cpu_exec_context.hh"
4911723Sar4jc@virginia.edu#include "cpu/exec_context.hh"
5011723Sar4jc@virginia.edu#include "cpu/exetrace.hh"
5111723Sar4jc@virginia.edu#include "cpu/profile.hh"
5212119Sar4jc@virginia.edu#include "cpu/sampler/sampler.hh"
5311723Sar4jc@virginia.edu#include "cpu/simple/cpu.hh"
5412104Snathanael.premillieu@arm.com#include "cpu/smt.hh"
5513610Sgiacomo.gabrielli@arm.com#include "cpu/static_inst.hh"
5612109SRekai.GonzalezAlberquilla@arm.com#include "kern/kernel_stats.hh"
5711911SBrandon.Potter@amd.com#include "sim/byteswap.hh"
5811723Sar4jc@virginia.edu#include "sim/builder.hh"
5911723Sar4jc@virginia.edu#include "sim/debug.hh"
6011723Sar4jc@virginia.edu#include "sim/host.hh"
6111723Sar4jc@virginia.edu#include "sim/sim_events.hh"
6211723Sar4jc@virginia.edu#include "sim/sim_object.hh"
6311723Sar4jc@virginia.edu#include "sim/stats.hh"
6411723Sar4jc@virginia.edu
6511723Sar4jc@virginia.edu#if FULL_SYSTEM
6611723Sar4jc@virginia.edu#include "base/remote_gdb.hh"
6713610Sgiacomo.gabrielli@arm.com//#include "mem/functional/memory_control.hh"
6813610Sgiacomo.gabrielli@arm.com//#include "mem/functional/physical.hh"
6913610Sgiacomo.gabrielli@arm.com#include "sim/system.hh"
7013610Sgiacomo.gabrielli@arm.com#include "arch/tlb.hh"
7113610Sgiacomo.gabrielli@arm.com#include "arch/stacktrace.hh"
7213610Sgiacomo.gabrielli@arm.com#include "arch/vtophys.hh"
7313610Sgiacomo.gabrielli@arm.com#else // !FULL_SYSTEM
7413610Sgiacomo.gabrielli@arm.com#include "mem/mem_object.hh"
7513610Sgiacomo.gabrielli@arm.com#endif // FULL_SYSTEM
7613610Sgiacomo.gabrielli@arm.com
7713610Sgiacomo.gabrielli@arm.comusing namespace std;
7813610Sgiacomo.gabrielli@arm.comusing namespace TheISA;
7913610Sgiacomo.gabrielli@arm.com
8013610Sgiacomo.gabrielli@arm.comSimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w)
8112109SRekai.GonzalezAlberquilla@arm.com    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), width(w)
8211723Sar4jc@virginia.edu{
8311726Sar4jc@virginia.edu}
8411726Sar4jc@virginia.edu
8511725Sar4jc@virginia.edu
8613610Sgiacomo.gabrielli@arm.comvoid
8713610Sgiacomo.gabrielli@arm.comSimpleCPU::init()
8813610Sgiacomo.gabrielli@arm.com{
8913610Sgiacomo.gabrielli@arm.com    //Create Memory Ports (conect them up)
9013610Sgiacomo.gabrielli@arm.com    Port *mem_dport = mem->getPort("");
9113610Sgiacomo.gabrielli@arm.com    dcachePort.setPeer(mem_dport);
9211723Sar4jc@virginia.edu    mem_dport->setPeer(&dcachePort);
9311723Sar4jc@virginia.edu
9411723Sar4jc@virginia.edu    Port *mem_iport = mem->getPort("");
9511723Sar4jc@virginia.edu    icachePort.setPeer(mem_iport);
9611723Sar4jc@virginia.edu    mem_iport->setPeer(&icachePort);
9711723Sar4jc@virginia.edu
9811723Sar4jc@virginia.edu    BaseCPU::init();
9911723Sar4jc@virginia.edu#if FULL_SYSTEM
10011723Sar4jc@virginia.edu    for (int i = 0; i < execContexts.size(); ++i) {
10112139Sar4jc@virginia.edu        ExecContext *xc = execContexts[i];
10212119Sar4jc@virginia.edu
10312119Sar4jc@virginia.edu        // initialize CPU, including PC
10411726Sar4jc@virginia.edu        TheISA::initCPU(xc, xc->readCpuId());
10511723Sar4jc@virginia.edu    }
10612413Sar4jc@virginia.edu#endif
10712413Sar4jc@virginia.edu}
10812413Sar4jc@virginia.edu
10912413Sar4jc@virginia.eduvoid
11012119Sar4jc@virginia.eduSimpleCPU::TickEvent::process()
11112119Sar4jc@virginia.edu{
11211723Sar4jc@virginia.edu    int count = width;
11311723Sar4jc@virginia.edu    do {
11411723Sar4jc@virginia.edu        cpu->tick();
11511723Sar4jc@virginia.edu    } while (--count > 0 && cpu->status() == Running);
11611723Sar4jc@virginia.edu}
11711723Sar4jc@virginia.edu
11812119Sar4jc@virginia.educonst char *
11912119Sar4jc@virginia.eduSimpleCPU::TickEvent::description()
12012119Sar4jc@virginia.edu{
12112119Sar4jc@virginia.edu    return "SimpleCPU tick event";
12212119Sar4jc@virginia.edu}
12312119Sar4jc@virginia.edu
12412119Sar4jc@virginia.edu
12512119Sar4jc@virginia.edubool
12612119Sar4jc@virginia.eduSimpleCPU::CpuPort::recvTiming(Packet &pkt)
12712119Sar4jc@virginia.edu{
12812119Sar4jc@virginia.edu    cpu->processResponse(pkt);
12912119Sar4jc@virginia.edu    return true;
13011723Sar4jc@virginia.edu}
13111723Sar4jc@virginia.edu
13212695Sar4jc@virginia.eduTick
13312695Sar4jc@virginia.eduSimpleCPU::CpuPort::recvAtomic(Packet &pkt)
13412695Sar4jc@virginia.edu{
13512695Sar4jc@virginia.edu    panic("CPU doesn't expect callback!");
13612695Sar4jc@virginia.edu    return curTick;
13712695Sar4jc@virginia.edu}
13812695Sar4jc@virginia.edu
13912695Sar4jc@virginia.eduvoid
14012695Sar4jc@virginia.eduSimpleCPU::CpuPort::recvFunctional(Packet &pkt)
14112695Sar4jc@virginia.edu{
14212695Sar4jc@virginia.edu    panic("CPU doesn't expect callback!");
14312695Sar4jc@virginia.edu}
14412695Sar4jc@virginia.edu
14512695Sar4jc@virginia.eduvoid
14612695Sar4jc@virginia.eduSimpleCPU::CpuPort::recvStatusChange(Status status)
14712695Sar4jc@virginia.edu{
14812695Sar4jc@virginia.edu    cpu->recvStatusChange(status);
14912695Sar4jc@virginia.edu}
15012695Sar4jc@virginia.edu
15112695Sar4jc@virginia.eduPacket *
15212695Sar4jc@virginia.eduSimpleCPU::CpuPort::recvRetry()
15312695Sar4jc@virginia.edu{
15412695Sar4jc@virginia.edu    return cpu->processRetry();
15512695Sar4jc@virginia.edu}
15612695Sar4jc@virginia.edu
15712695Sar4jc@virginia.eduSimpleCPU::SimpleCPU(Params *p)
15812695Sar4jc@virginia.edu#if !FULL_SYSTEM
15912695Sar4jc@virginia.edu    : BaseCPU(p), mem(p->mem), icachePort(this),
16012695Sar4jc@virginia.edu      dcachePort(this), tickEvent(this, p->width), cpuXC(NULL)
16112695Sar4jc@virginia.edu#else
16212695Sar4jc@virginia.edu    : BaseCPU(p), icachePort(this), dcachePort(this),
16312695Sar4jc@virginia.edu      tickEvent(this, p->width), cpuXC(NULL)
16412695Sar4jc@virginia.edu#endif
16512695Sar4jc@virginia.edu{
16612695Sar4jc@virginia.edu    _status = Idle;
16712695Sar4jc@virginia.edu
16812695Sar4jc@virginia.edu#if FULL_SYSTEM
16912695Sar4jc@virginia.edu    cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb);
17012695Sar4jc@virginia.edu#else
17112695Sar4jc@virginia.edu    cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process,
17212695Sar4jc@virginia.edu            /* asid */ 0);
17312695Sar4jc@virginia.edu#endif // !FULL_SYSTEM
17412695Sar4jc@virginia.edu
17512695Sar4jc@virginia.edu    xcProxy = cpuXC->getProxy();
17612695Sar4jc@virginia.edu
17712695Sar4jc@virginia.edu#if SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE
17812695Sar4jc@virginia.edu    ifetch_req = new CpuRequest;
17912695Sar4jc@virginia.edu    ifetch_req->asid = 0;
18012695Sar4jc@virginia.edu    ifetch_req->size = sizeof(MachInst);
18112695Sar4jc@virginia.edu    ifetch_pkt = new Packet;
18212695Sar4jc@virginia.edu    ifetch_pkt->cmd = Read;
18312695Sar4jc@virginia.edu    ifetch_pkt->data = (uint8_t *)&inst;
18412695Sar4jc@virginia.edu    ifetch_pkt->req = ifetch_req;
18512695Sar4jc@virginia.edu    ifetch_pkt->size = sizeof(MachInst);
18612695Sar4jc@virginia.edu
18712695Sar4jc@virginia.edu    data_read_req = new CpuRequest;
18812695Sar4jc@virginia.edu    data_read_req->asid = 0;
18912695Sar4jc@virginia.edu    data_read_pkt = new Packet;
19012695Sar4jc@virginia.edu    data_read_pkt->cmd = Read;
19112695Sar4jc@virginia.edu    data_read_pkt->data = new uint8_t[8];
19212695Sar4jc@virginia.edu    data_read_pkt->req = data_read_req;
19312695Sar4jc@virginia.edu
19412695Sar4jc@virginia.edu    data_write_req = new CpuRequest;
19512695Sar4jc@virginia.edu    data_write_req->asid = 0;
19612695Sar4jc@virginia.edu    data_write_pkt = new Packet;
19712695Sar4jc@virginia.edu    data_write_pkt->cmd = Write;
19812695Sar4jc@virginia.edu    data_write_pkt->req = data_write_req;
19912695Sar4jc@virginia.edu#endif
20012695Sar4jc@virginia.edu
20112695Sar4jc@virginia.edu    numInst = 0;
20212695Sar4jc@virginia.edu    startNumInst = 0;
20312695Sar4jc@virginia.edu    numLoad = 0;
20412695Sar4jc@virginia.edu    startNumLoad = 0;
20512695Sar4jc@virginia.edu    lastIcacheStall = 0;
20612695Sar4jc@virginia.edu    lastDcacheStall = 0;
20712695Sar4jc@virginia.edu
20812695Sar4jc@virginia.edu    execContexts.push_back(xcProxy);
20911723Sar4jc@virginia.edu}
21012695Sar4jc@virginia.edu
21112695Sar4jc@virginia.eduSimpleCPU::~SimpleCPU()
21212695Sar4jc@virginia.edu{
21312695Sar4jc@virginia.edu}
21412695Sar4jc@virginia.edu
21512695Sar4jc@virginia.eduvoid
21612695Sar4jc@virginia.eduSimpleCPU::switchOut(Sampler *s)
21712695Sar4jc@virginia.edu{
21812695Sar4jc@virginia.edu    sampler = s;
21912695Sar4jc@virginia.edu    if (status() == DcacheWaitResponse) {
22012695Sar4jc@virginia.edu        DPRINTF(Sampler,"Outstanding dcache access, waiting for completion\n");
22112695Sar4jc@virginia.edu        _status = DcacheWaitSwitch;
22212695Sar4jc@virginia.edu    }
22312695Sar4jc@virginia.edu    else {
22412695Sar4jc@virginia.edu        _status = SwitchedOut;
22512695Sar4jc@virginia.edu
22612695Sar4jc@virginia.edu        if (tickEvent.scheduled())
22712695Sar4jc@virginia.edu            tickEvent.squash();
22812695Sar4jc@virginia.edu
22912695Sar4jc@virginia.edu        sampler->signalSwitched();
23012695Sar4jc@virginia.edu    }
23112695Sar4jc@virginia.edu}
23212695Sar4jc@virginia.edu
23312695Sar4jc@virginia.edu
23412695Sar4jc@virginia.eduvoid
23512695Sar4jc@virginia.eduSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
23612695Sar4jc@virginia.edu{
23712695Sar4jc@virginia.edu    BaseCPU::takeOverFrom(oldCPU);
23811723Sar4jc@virginia.edu
23912695Sar4jc@virginia.edu    assert(!tickEvent.scheduled());
24012695Sar4jc@virginia.edu
24112695Sar4jc@virginia.edu    // if any of this CPU's ExecContexts are active, mark the CPU as
24212695Sar4jc@virginia.edu    // running and schedule its tick event.
24312695Sar4jc@virginia.edu    for (int i = 0; i < execContexts.size(); ++i) {
24412695Sar4jc@virginia.edu        ExecContext *xc = execContexts[i];
24512695Sar4jc@virginia.edu        if (xc->status() == ExecContext::Active && _status != Running) {
24612695Sar4jc@virginia.edu            _status = Running;
24712695Sar4jc@virginia.edu            tickEvent.schedule(curTick);
24811723Sar4jc@virginia.edu        }
24912695Sar4jc@virginia.edu    }
25012695Sar4jc@virginia.edu}
25112695Sar4jc@virginia.edu
25212695Sar4jc@virginia.edu
25312695Sar4jc@virginia.eduvoid
25412695Sar4jc@virginia.eduSimpleCPU::activateContext(int thread_num, int delay)
25512695Sar4jc@virginia.edu{
25611963Sar4jc@virginia.edu    assert(thread_num == 0);
25712695Sar4jc@virginia.edu    assert(cpuXC);
25812695Sar4jc@virginia.edu
25912695Sar4jc@virginia.edu    assert(_status == Idle);
26012695Sar4jc@virginia.edu    notIdleFraction++;
26112695Sar4jc@virginia.edu    scheduleTickEvent(delay);
26212695Sar4jc@virginia.edu    _status = Running;
26312695Sar4jc@virginia.edu}
26412695Sar4jc@virginia.edu
26512695Sar4jc@virginia.edu
26612695Sar4jc@virginia.eduvoid
26712695Sar4jc@virginia.eduSimpleCPU::suspendContext(int thread_num)
26812695Sar4jc@virginia.edu{
26912695Sar4jc@virginia.edu    assert(thread_num == 0);
27012695Sar4jc@virginia.edu    assert(cpuXC);
27112695Sar4jc@virginia.edu
27212695Sar4jc@virginia.edu    assert(_status == Running);
27312695Sar4jc@virginia.edu    notIdleFraction--;
27412695Sar4jc@virginia.edu    unscheduleTickEvent();
27512695Sar4jc@virginia.edu    _status = Idle;
27612695Sar4jc@virginia.edu}
27712695Sar4jc@virginia.edu
27812695Sar4jc@virginia.edu
27912695Sar4jc@virginia.eduvoid
28012695Sar4jc@virginia.eduSimpleCPU::deallocateContext(int thread_num)
28112695Sar4jc@virginia.edu{
28212695Sar4jc@virginia.edu    // for now, these are equivalent
28312695Sar4jc@virginia.edu    suspendContext(thread_num);
28412695Sar4jc@virginia.edu}
28512695Sar4jc@virginia.edu
28612695Sar4jc@virginia.edu
28712695Sar4jc@virginia.eduvoid
28812695Sar4jc@virginia.eduSimpleCPU::haltContext(int thread_num)
28912695Sar4jc@virginia.edu{
29012695Sar4jc@virginia.edu    // for now, these are equivalent
29112695Sar4jc@virginia.edu    suspendContext(thread_num);
29212695Sar4jc@virginia.edu}
29312695Sar4jc@virginia.edu
29412695Sar4jc@virginia.edu
29512695Sar4jc@virginia.eduvoid
29612695Sar4jc@virginia.eduSimpleCPU::regStats()
29712695Sar4jc@virginia.edu{
29812695Sar4jc@virginia.edu    using namespace Stats;
29912695Sar4jc@virginia.edu
30012695Sar4jc@virginia.edu    BaseCPU::regStats();
30112695Sar4jc@virginia.edu
30212695Sar4jc@virginia.edu    numInsts
30312695Sar4jc@virginia.edu        .name(name() + ".num_insts")
30412695Sar4jc@virginia.edu        .desc("Number of instructions executed")
30512695Sar4jc@virginia.edu        ;
30612695Sar4jc@virginia.edu
30712695Sar4jc@virginia.edu    numMemRefs
30812695Sar4jc@virginia.edu        .name(name() + ".num_refs")
30912695Sar4jc@virginia.edu        .desc("Number of memory references")
31012695Sar4jc@virginia.edu        ;
31112695Sar4jc@virginia.edu
31212695Sar4jc@virginia.edu    notIdleFraction
31312695Sar4jc@virginia.edu        .name(name() + ".not_idle_fraction")
31412695Sar4jc@virginia.edu        .desc("Percentage of non-idle cycles")
31512695Sar4jc@virginia.edu        ;
31612695Sar4jc@virginia.edu
31712695Sar4jc@virginia.edu    idleFraction
31812695Sar4jc@virginia.edu        .name(name() + ".idle_fraction")
31912695Sar4jc@virginia.edu        .desc("Percentage of idle cycles")
32012695Sar4jc@virginia.edu        ;
32112695Sar4jc@virginia.edu
32212695Sar4jc@virginia.edu    icacheStallCycles
32312695Sar4jc@virginia.edu        .name(name() + ".icache_stall_cycles")
32412695Sar4jc@virginia.edu        .desc("ICache total stall cycles")
32512695Sar4jc@virginia.edu        .prereq(icacheStallCycles)
32612695Sar4jc@virginia.edu        ;
32712695Sar4jc@virginia.edu
32812695Sar4jc@virginia.edu    dcacheStallCycles
32912695Sar4jc@virginia.edu        .name(name() + ".dcache_stall_cycles")
33012695Sar4jc@virginia.edu        .desc("DCache total stall cycles")
33112695Sar4jc@virginia.edu        .prereq(dcacheStallCycles)
33212695Sar4jc@virginia.edu        ;
33312695Sar4jc@virginia.edu
33412695Sar4jc@virginia.edu    icacheRetryCycles
33512695Sar4jc@virginia.edu        .name(name() + ".icache_retry_cycles")
33612695Sar4jc@virginia.edu        .desc("ICache total retry cycles")
33712695Sar4jc@virginia.edu        .prereq(icacheRetryCycles)
33812695Sar4jc@virginia.edu        ;
33912695Sar4jc@virginia.edu
34012695Sar4jc@virginia.edu    dcacheRetryCycles
34112695Sar4jc@virginia.edu        .name(name() + ".dcache_retry_cycles")
34212695Sar4jc@virginia.edu        .desc("DCache total retry cycles")
34312695Sar4jc@virginia.edu        .prereq(dcacheRetryCycles)
34412695Sar4jc@virginia.edu        ;
34512695Sar4jc@virginia.edu
34612695Sar4jc@virginia.edu    idleFraction = constant(1.0) - notIdleFraction;
34712695Sar4jc@virginia.edu}
34812695Sar4jc@virginia.edu
34912695Sar4jc@virginia.eduvoid
35012695Sar4jc@virginia.eduSimpleCPU::resetStats()
35112695Sar4jc@virginia.edu{
35212695Sar4jc@virginia.edu    startNumInst = numInst;
35312695Sar4jc@virginia.edu    notIdleFraction = (_status != Idle);
35412695Sar4jc@virginia.edu}
35512695Sar4jc@virginia.edu
35612695Sar4jc@virginia.eduvoid
35712695Sar4jc@virginia.eduSimpleCPU::serialize(ostream &os)
35812695Sar4jc@virginia.edu{
35912695Sar4jc@virginia.edu    BaseCPU::serialize(os);
36012695Sar4jc@virginia.edu    SERIALIZE_ENUM(_status);
36112695Sar4jc@virginia.edu    SERIALIZE_SCALAR(inst);
36212695Sar4jc@virginia.edu    nameOut(os, csprintf("%s.xc", name()));
36312695Sar4jc@virginia.edu    cpuXC->serialize(os);
36412695Sar4jc@virginia.edu    nameOut(os, csprintf("%s.tickEvent", name()));
36512695Sar4jc@virginia.edu    tickEvent.serialize(os);
36612695Sar4jc@virginia.edu    nameOut(os, csprintf("%s.cacheCompletionEvent", name()));
36712695Sar4jc@virginia.edu}
36812695Sar4jc@virginia.edu
36912695Sar4jc@virginia.eduvoid
37012695Sar4jc@virginia.eduSimpleCPU::unserialize(Checkpoint *cp, const string &section)
37112695Sar4jc@virginia.edu{
37212695Sar4jc@virginia.edu    BaseCPU::unserialize(cp, section);
37312695Sar4jc@virginia.edu    UNSERIALIZE_ENUM(_status);
37412695Sar4jc@virginia.edu    UNSERIALIZE_SCALAR(inst);
37512695Sar4jc@virginia.edu    cpuXC->unserialize(cp, csprintf("%s.xc", section));
37612695Sar4jc@virginia.edu    tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
37712695Sar4jc@virginia.edu}
37812695Sar4jc@virginia.edu
37912695Sar4jc@virginia.eduvoid
38012695Sar4jc@virginia.educhange_thread_state(int thread_number, int activate, int priority)
38112695Sar4jc@virginia.edu{
38212695Sar4jc@virginia.edu}
38312695Sar4jc@virginia.edu
38412695Sar4jc@virginia.eduFault
38512695Sar4jc@virginia.eduSimpleCPU::copySrcTranslate(Addr src)
38612695Sar4jc@virginia.edu{
38712695Sar4jc@virginia.edu#if 0
38812695Sar4jc@virginia.edu    static bool no_warn = true;
38912695Sar4jc@virginia.edu    int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
39012695Sar4jc@virginia.edu    // Only support block sizes of 64 atm.
39112695Sar4jc@virginia.edu    assert(blk_size == 64);
39212695Sar4jc@virginia.edu    int offset = src & (blk_size - 1);
39312695Sar4jc@virginia.edu
39412695Sar4jc@virginia.edu    // Make sure block doesn't span page
39512695Sar4jc@virginia.edu    if (no_warn &&
39612695Sar4jc@virginia.edu        (src & PageMask) != ((src + blk_size) & PageMask) &&
39712695Sar4jc@virginia.edu        (src >> 40) != 0xfffffc) {
39812695Sar4jc@virginia.edu        warn("Copied block source spans pages %x.", src);
39912695Sar4jc@virginia.edu        no_warn = false;
40012695Sar4jc@virginia.edu    }
40112695Sar4jc@virginia.edu
40212695Sar4jc@virginia.edu    memReq->reset(src & ~(blk_size - 1), blk_size);
40312695Sar4jc@virginia.edu
40412695Sar4jc@virginia.edu    // translate to physical address    Fault fault = cpuXC->translateDataReadReq(req);
40512695Sar4jc@virginia.edu
40612695Sar4jc@virginia.edu    if (fault == NoFault) {
40712695Sar4jc@virginia.edu        cpuXC->copySrcAddr = src;
40812695Sar4jc@virginia.edu        cpuXC->copySrcPhysAddr = memReq->paddr + offset;
40912695Sar4jc@virginia.edu    } else {
41012695Sar4jc@virginia.edu        assert(!fault->isAlignmentFault());
41112695Sar4jc@virginia.edu
41212695Sar4jc@virginia.edu        cpuXC->copySrcAddr = 0;
41312695Sar4jc@virginia.edu        cpuXC->copySrcPhysAddr = 0;
41412695Sar4jc@virginia.edu    }
41512695Sar4jc@virginia.edu    return fault;
41612695Sar4jc@virginia.edu#else
41712695Sar4jc@virginia.edu    return NoFault;
41812695Sar4jc@virginia.edu#endif
41912695Sar4jc@virginia.edu}
42012695Sar4jc@virginia.edu
42112695Sar4jc@virginia.eduFault
42212695Sar4jc@virginia.eduSimpleCPU::copy(Addr dest)
42311723Sar4jc@virginia.edu{
42411723Sar4jc@virginia.edu#if 0
42512695Sar4jc@virginia.edu    static bool no_warn = true;
42612695Sar4jc@virginia.edu    int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
42712695Sar4jc@virginia.edu    // Only support block sizes of 64 atm.
42812695Sar4jc@virginia.edu    assert(blk_size == 64);
42912695Sar4jc@virginia.edu    uint8_t data[blk_size];
43012119Sar4jc@virginia.edu    //assert(cpuXC->copySrcAddr);
43112695Sar4jc@virginia.edu    int offset = dest & (blk_size - 1);
43212695Sar4jc@virginia.edu
43312695Sar4jc@virginia.edu    // Make sure block doesn't span page
43412695Sar4jc@virginia.edu    if (no_warn &&
43512695Sar4jc@virginia.edu        (dest & PageMask) != ((dest + blk_size) & PageMask) &&
43612695Sar4jc@virginia.edu        (dest >> 40) != 0xfffffc) {
43712695Sar4jc@virginia.edu        no_warn = false;
43812695Sar4jc@virginia.edu        warn("Copied block destination spans pages %x. ", dest);
43912695Sar4jc@virginia.edu    }
44012695Sar4jc@virginia.edu
44112695Sar4jc@virginia.edu    memReq->reset(dest & ~(blk_size -1), blk_size);
44212695Sar4jc@virginia.edu    // translate to physical address
44312695Sar4jc@virginia.edu    Fault fault = cpuXC->translateDataWriteReq(req);
44412695Sar4jc@virginia.edu
44512695Sar4jc@virginia.edu    if (fault == NoFault) {
44612695Sar4jc@virginia.edu        Addr dest_addr = memReq->paddr + offset;
44712695Sar4jc@virginia.edu        // Need to read straight from memory since we have more than 8 bytes.
44812695Sar4jc@virginia.edu        memReq->paddr = cpuXC->copySrcPhysAddr;
44912695Sar4jc@virginia.edu        cpuXC->mem->read(memReq, data);
45012695Sar4jc@virginia.edu        memReq->paddr = dest_addr;
45112695Sar4jc@virginia.edu        cpuXC->mem->write(memReq, data);
45212695Sar4jc@virginia.edu        if (dcacheInterface) {
45312695Sar4jc@virginia.edu            memReq->cmd = Copy;
45412695Sar4jc@virginia.edu            memReq->completionEvent = NULL;
45512695Sar4jc@virginia.edu            memReq->paddr = cpuXC->copySrcPhysAddr;
45612695Sar4jc@virginia.edu            memReq->dest = dest_addr;
45712695Sar4jc@virginia.edu            memReq->size = 64;
45812695Sar4jc@virginia.edu            memReq->time = curTick;
45912695Sar4jc@virginia.edu            memReq->flags &= ~INST_READ;
46012695Sar4jc@virginia.edu            dcacheInterface->access(memReq);
46112695Sar4jc@virginia.edu        }
46212695Sar4jc@virginia.edu    }
46312695Sar4jc@virginia.edu    else
46412695Sar4jc@virginia.edu        assert(!fault->isAlignmentFault());
46512695Sar4jc@virginia.edu
46612695Sar4jc@virginia.edu    return fault;
46712695Sar4jc@virginia.edu#else
46812695Sar4jc@virginia.edu    panic("copy not implemented");
46912695Sar4jc@virginia.edu    return NoFault;
47012695Sar4jc@virginia.edu#endif
47112695Sar4jc@virginia.edu}
47212695Sar4jc@virginia.edu
47312695Sar4jc@virginia.edu// precise architected memory state accessor macros
47412695Sar4jc@virginia.edutemplate <class T>
47512119Sar4jc@virginia.eduFault
47612695Sar4jc@virginia.eduSimpleCPU::read(Addr addr, T &data, unsigned flags)
47712695Sar4jc@virginia.edu{
47812695Sar4jc@virginia.edu    if (status() == DcacheWaitResponse || status() == DcacheWaitSwitch) {
47912695Sar4jc@virginia.edu//	Fault fault = xc->read(memReq,data);
48012695Sar4jc@virginia.edu        // Not sure what to check for no fault...
48112695Sar4jc@virginia.edu        if (data_read_pkt->result == Success) {
48212695Sar4jc@virginia.edu            memcpy(&data, data_read_pkt->data, sizeof(T));
48312695Sar4jc@virginia.edu        }
48412695Sar4jc@virginia.edu
48512695Sar4jc@virginia.edu        if (traceData) {
48612695Sar4jc@virginia.edu            traceData->setAddr(addr);
48712119Sar4jc@virginia.edu        }
48812695Sar4jc@virginia.edu
48912695Sar4jc@virginia.edu        // @todo: Figure out a way to create a Fault from the packet result.
49012695Sar4jc@virginia.edu        return NoFault;
49112695Sar4jc@virginia.edu    }
49212695Sar4jc@virginia.edu
49312695Sar4jc@virginia.edu//    memReq->reset(addr, sizeof(T), flags);
49412695Sar4jc@virginia.edu
49512695Sar4jc@virginia.edu#if SIMPLE_CPU_MEM_TIMING
49612695Sar4jc@virginia.edu    CpuRequest *data_read_req = new CpuRequest;
49712695Sar4jc@virginia.edu#endif
49812695Sar4jc@virginia.edu
49912695Sar4jc@virginia.edu    data_read_req->vaddr = addr;
50012695Sar4jc@virginia.edu    data_read_req->size = sizeof(T);
50112695Sar4jc@virginia.edu    data_read_req->flags = flags;
50212695Sar4jc@virginia.edu    data_read_req->time = curTick;
50312695Sar4jc@virginia.edu
50412695Sar4jc@virginia.edu    // translate to physical address
50512695Sar4jc@virginia.edu    Fault fault = cpuXC->translateDataReadReq(data_read_req);
50612695Sar4jc@virginia.edu
50712695Sar4jc@virginia.edu    // Now do the access.
50812695Sar4jc@virginia.edu    if (fault == NoFault) {
50912695Sar4jc@virginia.edu#if SIMPLE_CPU_MEM_TIMING
51012695Sar4jc@virginia.edu        data_read_pkt = new Packet;
51112695Sar4jc@virginia.edu        data_read_pkt->cmd = Read;
51212695Sar4jc@virginia.edu        data_read_pkt->req = data_read_req;
51312695Sar4jc@virginia.edu        data_read_pkt->data = new uint8_t[8];
51412695Sar4jc@virginia.edu#endif
51512695Sar4jc@virginia.edu        data_read_pkt->addr = data_read_req->paddr;
51612695Sar4jc@virginia.edu        data_read_pkt->size = sizeof(T);
51712695Sar4jc@virginia.edu
51812695Sar4jc@virginia.edu        sendDcacheRequest(data_read_pkt);
51912695Sar4jc@virginia.edu
52012695Sar4jc@virginia.edu#if SIMPLE_CPU_MEM_IMMEDIATE
52112695Sar4jc@virginia.edu        // Need to find a way to not duplicate code above.
52212695Sar4jc@virginia.edu
52312695Sar4jc@virginia.edu        if (data_read_pkt->result == Success) {
52412695Sar4jc@virginia.edu            memcpy(&data, data_read_pkt->data, sizeof(T));
52512695Sar4jc@virginia.edu        }
52612695Sar4jc@virginia.edu
52712695Sar4jc@virginia.edu        if (traceData) {
52812695Sar4jc@virginia.edu            traceData->setAddr(addr);
52912695Sar4jc@virginia.edu        }
53012695Sar4jc@virginia.edu
53112695Sar4jc@virginia.edu        // @todo: Figure out a way to create a Fault from the packet result.
53212695Sar4jc@virginia.edu        return NoFault;
53312695Sar4jc@virginia.edu#endif
53412695Sar4jc@virginia.edu    }
53512695Sar4jc@virginia.edu/*
53612695Sar4jc@virginia.edu        memReq->cmd = Read;
53712695Sar4jc@virginia.edu        memReq->completionEvent = NULL;
53812695Sar4jc@virginia.edu        memReq->time = curTick;
53912695Sar4jc@virginia.edu        memReq->flags &= ~INST_READ;
54012695Sar4jc@virginia.edu        MemAccessResult result = dcacheInterface->access(memReq);
54112695Sar4jc@virginia.edu
54212695Sar4jc@virginia.edu        // Ugly hack to get an event scheduled *only* if the access is
54312695Sar4jc@virginia.edu        // a miss.  We really should add first-class support for this
54412695Sar4jc@virginia.edu        // at some point.
54512695Sar4jc@virginia.edu        if (result != MA_HIT && dcacheInterface->doEvents()) {
54612695Sar4jc@virginia.edu            memReq->completionEvent = &cacheCompletionEvent;
54712695Sar4jc@virginia.edu            lastDcacheStall = curTick;
54812695Sar4jc@virginia.edu            unscheduleTickEvent();
54912695Sar4jc@virginia.edu            _status = DcacheMissStall;
55012695Sar4jc@virginia.edu        } else {
55112695Sar4jc@virginia.edu            // do functional access
55212695Sar4jc@virginia.edu            fault = cpuXC->read(memReq, data);
55312695Sar4jc@virginia.edu
55412695Sar4jc@virginia.edu        }
55512695Sar4jc@virginia.edu    } else if(fault == NoFault) {
55612695Sar4jc@virginia.edu        // do functional access
55712695Sar4jc@virginia.edu        fault = cpuXC->read(memReq, data);
55812695Sar4jc@virginia.edu
55912695Sar4jc@virginia.edu    }
56012695Sar4jc@virginia.edu*/
56112695Sar4jc@virginia.edu    // This will need a new way to tell if it has a dcache attached.
56212695Sar4jc@virginia.edu    if (data_read_req->flags & UNCACHEABLE)
56312695Sar4jc@virginia.edu        recordEvent("Uncached Read");
56412695Sar4jc@virginia.edu
56512695Sar4jc@virginia.edu    return fault;
56612695Sar4jc@virginia.edu}
56712695Sar4jc@virginia.edu
56812695Sar4jc@virginia.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
56912695Sar4jc@virginia.edu
57012695Sar4jc@virginia.edutemplate
57112695Sar4jc@virginia.eduFault
57212695Sar4jc@virginia.eduSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
57312695Sar4jc@virginia.edu
57412695Sar4jc@virginia.edutemplate
57512695Sar4jc@virginia.eduFault
57612695Sar4jc@virginia.eduSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);
57712695Sar4jc@virginia.edu
57812695Sar4jc@virginia.edutemplate
57912695Sar4jc@virginia.eduFault
58012695Sar4jc@virginia.eduSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);
58112695Sar4jc@virginia.edu
58212695Sar4jc@virginia.edutemplate
58312119Sar4jc@virginia.eduFault
58412695Sar4jc@virginia.eduSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);
58512695Sar4jc@virginia.edu
58612695Sar4jc@virginia.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
58712695Sar4jc@virginia.edu
58812695Sar4jc@virginia.edutemplate<>
58912695Sar4jc@virginia.eduFault
59012695Sar4jc@virginia.eduSimpleCPU::read(Addr addr, double &data, unsigned flags)
59112695Sar4jc@virginia.edu{
59212695Sar4jc@virginia.edu    return read(addr, *(uint64_t*)&data, flags);
59312850Salec.roelke@gmail.com}
59412850Salec.roelke@gmail.com
59512850Salec.roelke@gmail.comtemplate<>
59612850Salec.roelke@gmail.comFault
59712850Salec.roelke@gmail.comSimpleCPU::read(Addr addr, float &data, unsigned flags)
59812850Salec.roelke@gmail.com{
59912850Salec.roelke@gmail.com    return read(addr, *(uint32_t*)&data, flags);
60012850Salec.roelke@gmail.com}
60112850Salec.roelke@gmail.com
60212850Salec.roelke@gmail.com
60312850Salec.roelke@gmail.comtemplate<>
60412850Salec.roelke@gmail.comFault
60512850Salec.roelke@gmail.comSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
60612850Salec.roelke@gmail.com{
60712850Salec.roelke@gmail.com    return read(addr, (uint32_t&)data, flags);
60812850Salec.roelke@gmail.com}
60912850Salec.roelke@gmail.com
61012850Salec.roelke@gmail.com
61112850Salec.roelke@gmail.comtemplate <class T>
61212850Salec.roelke@gmail.comFault
61312850Salec.roelke@gmail.comSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
61412850Salec.roelke@gmail.com{
61512850Salec.roelke@gmail.com    data_write_req->vaddr = addr;
61612850Salec.roelke@gmail.com    data_write_req->time = curTick;
61712850Salec.roelke@gmail.com    data_write_req->size = sizeof(T);
61812850Salec.roelke@gmail.com    data_write_req->flags = flags;
61912850Salec.roelke@gmail.com
62012850Salec.roelke@gmail.com    // translate to physical address
62112850Salec.roelke@gmail.com    Fault fault = cpuXC->translateDataWriteReq(data_write_req);
62212850Salec.roelke@gmail.com    // Now do the access.
62312850Salec.roelke@gmail.com    if (fault == NoFault) {
62412850Salec.roelke@gmail.com#if SIMPLE_CPU_MEM_TIMING
62512850Salec.roelke@gmail.com        data_write_pkt = new Packet;
62612850Salec.roelke@gmail.com        data_write_pkt->cmd = Write;
62712850Salec.roelke@gmail.com        data_write_pkt->req = data_write_req;
62812850Salec.roelke@gmail.com        data_write_pkt->data = new uint8_t[64];
62912850Salec.roelke@gmail.com        memcpy(data_write_pkt->data, &data, sizeof(T));
63012850Salec.roelke@gmail.com#else
63112850Salec.roelke@gmail.com        data_write_pkt->data = (uint8_t *)&data;
63212850Salec.roelke@gmail.com#endif
63312850Salec.roelke@gmail.com        data_write_pkt->addr = data_write_req->paddr;
63412850Salec.roelke@gmail.com        data_write_pkt->size = sizeof(T);
63512850Salec.roelke@gmail.com
63612850Salec.roelke@gmail.com        sendDcacheRequest(data_write_pkt);
63712850Salec.roelke@gmail.com    }
63812850Salec.roelke@gmail.com
63912850Salec.roelke@gmail.com/*
64013612Sgabeblack@google.com    // do functional access
64112695Sar4jc@virginia.edu    if (fault == NoFault)
64212695Sar4jc@virginia.edu        fault = cpuXC->write(memReq, data);
64312695Sar4jc@virginia.edu
64412695Sar4jc@virginia.edu    if (fault == NoFault && dcacheInterface) {
64512695Sar4jc@virginia.edu        memReq->cmd = Write;
64613612Sgabeblack@google.com        memcpy(memReq->data,(uint8_t *)&data,memReq->size);
64713612Sgabeblack@google.com        memReq->completionEvent = NULL;
64813612Sgabeblack@google.com        memReq->time = curTick;
64912695Sar4jc@virginia.edu        memReq->flags &= ~INST_READ;
65013612Sgabeblack@google.com        MemAccessResult result = dcacheInterface->access(memReq);
65113612Sgabeblack@google.com
65213612Sgabeblack@google.com        // Ugly hack to get an event scheduled *only* if the access is
65313612Sgabeblack@google.com        // a miss.  We really should add first-class support for this
65413612Sgabeblack@google.com        // at some point.
65513612Sgabeblack@google.com        if (result != MA_HIT && dcacheInterface->doEvents()) {
65613612Sgabeblack@google.com            memReq->completionEvent = &cacheCompletionEvent;
65713612Sgabeblack@google.com            lastDcacheStall = curTick;
65813612Sgabeblack@google.com            unscheduleTickEvent();
65913612Sgabeblack@google.com            _status = DcacheMissStall;
66013612Sgabeblack@google.com        }
66113612Sgabeblack@google.com    }
66213612Sgabeblack@google.com*/
66313612Sgabeblack@google.com    if (res && (fault == NoFault))
66413612Sgabeblack@google.com        *res = data_write_pkt->result;
66513612Sgabeblack@google.com
66613612Sgabeblack@google.com    // This will need a new way to tell if it's hooked up to a cache or not.
66713612Sgabeblack@google.com    if (data_write_req->flags & UNCACHEABLE)
66813612Sgabeblack@google.com        recordEvent("Uncached Write");
66913612Sgabeblack@google.com
67013612Sgabeblack@google.com    // If the write needs to have a fault on the access, consider calling
67113612Sgabeblack@google.com    // changeStatus() and changing it to "bad addr write" or something.
67213612Sgabeblack@google.com    return fault;
67313612Sgabeblack@google.com}
67413612Sgabeblack@google.com
67513612Sgabeblack@google.com
67613612Sgabeblack@google.com#ifndef DOXYGEN_SHOULD_SKIP_THIS
67713612Sgabeblack@google.comtemplate
67813612Sgabeblack@google.comFault
67913612Sgabeblack@google.comSimpleCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
68013612Sgabeblack@google.com
68113612Sgabeblack@google.comtemplate
68213612Sgabeblack@google.comFault
68313612Sgabeblack@google.comSimpleCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
68413612Sgabeblack@google.com
68513612Sgabeblack@google.comtemplate
68613612Sgabeblack@google.comFault
68713612Sgabeblack@google.comSimpleCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
68813612Sgabeblack@google.com
68912695Sar4jc@virginia.edutemplate
69013612Sgabeblack@google.comFault
69113612Sgabeblack@google.comSimpleCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
69213612Sgabeblack@google.com
69313612Sgabeblack@google.com#endif //DOXYGEN_SHOULD_SKIP_THIS
69413612Sgabeblack@google.com
69513612Sgabeblack@google.comtemplate<>
69613612Sgabeblack@google.comFault
69713612Sgabeblack@google.comSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
69813612Sgabeblack@google.com{
69913612Sgabeblack@google.com    return write(*(uint64_t*)&data, addr, flags, res);
70013612Sgabeblack@google.com}
70113612Sgabeblack@google.com
70213612Sgabeblack@google.comtemplate<>
70313612Sgabeblack@google.comFault
70413612Sgabeblack@google.comSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
70513612Sgabeblack@google.com{
70613612Sgabeblack@google.com    return write(*(uint32_t*)&data, addr, flags, res);
70713612Sgabeblack@google.com}
70812695Sar4jc@virginia.edu
70913612Sgabeblack@google.com
71012695Sar4jc@virginia.edutemplate<>
71112695Sar4jc@virginia.eduFault
71212695Sar4jc@virginia.eduSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
71312695Sar4jc@virginia.edu{
71412695Sar4jc@virginia.edu    return write((uint32_t)data, addr, flags, res);
71512695Sar4jc@virginia.edu}
71612695Sar4jc@virginia.edu
71712695Sar4jc@virginia.edu
71812695Sar4jc@virginia.edu#if FULL_SYSTEM
71912695Sar4jc@virginia.eduAddr
72012695Sar4jc@virginia.eduSimpleCPU::dbg_vtophys(Addr addr)
72112695Sar4jc@virginia.edu{
72212695Sar4jc@virginia.edu    return vtophys(xcProxy, addr);
72312119Sar4jc@virginia.edu}
72412119Sar4jc@virginia.edu#endif // FULL_SYSTEM
72511723Sar4jc@virginia.edu
72611723Sar4jc@virginia.eduvoid
72711723Sar4jc@virginia.eduSimpleCPU::sendIcacheRequest(Packet *pkt)
728{
729    assert(!tickEvent.scheduled());
730#if SIMPLE_CPU_MEM_TIMING
731    retry_pkt = pkt;
732    bool success = icachePort.sendTiming(*pkt);
733
734    unscheduleTickEvent();
735
736    lastIcacheStall = curTick;
737
738    if (!success) {
739        // Need to wait for retry
740        _status = IcacheRetry;
741    } else {
742        // Need to wait for cache to respond
743        _status = IcacheWaitResponse;
744    }
745#elif SIMPLE_CPU_MEM_ATOMIC
746    Tick latency = icachePort.sendAtomic(*pkt);
747
748    unscheduleTickEvent();
749    scheduleTickEvent(latency);
750
751    // Note that Icache miss cycles will be incorrect.  Unless
752    // we check the status of the packet sent (is this valid?),
753    // we won't know if the latency is a hit or a miss.
754    icacheStallCycles += latency;
755
756    _status = IcacheAccessComplete;
757#elif SIMPLE_CPU_MEM_IMMEDIATE
758    icachePort.sendAtomic(*pkt);
759#else
760#error "SimpleCPU has no mem model set"
761#endif
762}
763
764void
765SimpleCPU::sendDcacheRequest(Packet *pkt)
766{
767    assert(!tickEvent.scheduled());
768#if SIMPLE_CPU_MEM_TIMING
769    unscheduleTickEvent();
770
771    retry_pkt = pkt;
772    bool success = dcachePort.sendTiming(*pkt);
773
774    lastDcacheStall = curTick;
775
776    if (!success) {
777        _status = DcacheRetry;
778    } else {
779        _status = DcacheWaitResponse;
780    }
781#elif SIMPLE_CPU_MEM_ATOMIC
782    unscheduleTickEvent();
783
784    Tick latency = dcachePort.sendAtomic(*pkt);
785
786    scheduleTickEvent(latency);
787
788    // Note that Dcache miss cycles will be incorrect.  Unless
789    // we check the status of the packet sent (is this valid?),
790    // we won't know if the latency is a hit or a miss.
791    dcacheStallCycles += latency;
792#elif SIMPLE_CPU_MEM_IMMEDIATE
793    dcachePort.sendAtomic(*pkt);
794#else
795#error "SimpleCPU has no mem model set"
796#endif
797}
798
799void
800SimpleCPU::processResponse(Packet &response)
801{
802    assert(SIMPLE_CPU_MEM_TIMING);
803
804    // For what things is the CPU the consumer of the packet it sent
805    // out?  This may create a memory leak if that's the case and it's
806    // expected of the SimpleCPU to delete its own packet.
807    Packet *pkt = &response;
808
809    switch (status()) {
810      case IcacheWaitResponse:
811        icacheStallCycles += curTick - lastIcacheStall;
812
813        _status = IcacheAccessComplete;
814        scheduleTickEvent(1);
815
816        // Copy the icache data into the instruction itself.
817        memcpy(&inst, pkt->data, sizeof(inst));
818
819        delete pkt;
820        break;
821      case DcacheWaitResponse:
822        if (pkt->cmd == Read) {
823            curStaticInst->execute(this,traceData);
824            if (traceData)
825                traceData->finalize();
826        }
827
828        delete pkt;
829
830        dcacheStallCycles += curTick - lastDcacheStall;
831        _status = Running;
832        scheduleTickEvent(1);
833        break;
834      case DcacheWaitSwitch:
835        if (pkt->cmd == Read) {
836            curStaticInst->execute(this,traceData);
837            if (traceData)
838                traceData->finalize();
839        }
840
841        delete pkt;
842
843        _status = SwitchedOut;
844        sampler->signalSwitched();
845      case SwitchedOut:
846        // If this CPU has been switched out due to sampling/warm-up,
847        // ignore any further status changes (e.g., due to cache
848        // misses outstanding at the time of the switch).
849        delete pkt;
850
851        return;
852      default:
853        panic("SimpleCPU::processCacheCompletion: bad state");
854        break;
855    }
856}
857
858Packet *
859SimpleCPU::processRetry()
860{
861#if SIMPLE_CPU_MEM_TIMING
862    switch(status()) {
863      case IcacheRetry:
864        icacheRetryCycles += curTick - lastIcacheStall;
865        return retry_pkt;
866        break;
867      case DcacheRetry:
868        dcacheRetryCycles += curTick - lastDcacheStall;
869        return retry_pkt;
870        break;
871      default:
872        panic("SimpleCPU::processRetry: bad state");
873        break;
874    }
875#else
876    panic("shouldn't be here");
877#endif
878}
879
880#if FULL_SYSTEM
881void
882SimpleCPU::post_interrupt(int int_num, int index)
883{
884    BaseCPU::post_interrupt(int_num, index);
885
886    if (cpuXC->status() == ExecContext::Suspended) {
887                DPRINTF(IPI,"Suspended Processor awoke\n");
888        cpuXC->activate();
889    }
890}
891#endif // FULL_SYSTEM
892
893/* start simulation, program loaded, processor precise state initialized */
894void
895SimpleCPU::tick()
896{
897    DPRINTF(SimpleCPU,"\n\n");
898
899    numCycles++;
900
901    traceData = NULL;
902
903    Fault fault = NoFault;
904
905#if FULL_SYSTEM
906    if (checkInterrupts && check_interrupts() && !cpuXC->inPalMode() &&
907        status() != IcacheAccessComplete) {
908        int ipl = 0;
909        int summary = 0;
910        checkInterrupts = false;
911
912        if (cpuXC->readMiscReg(IPR_SIRR)) {
913            for (int i = INTLEVEL_SOFTWARE_MIN;
914                 i < INTLEVEL_SOFTWARE_MAX; i++) {
915                if (cpuXC->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
916                    // See table 4-19 of 21164 hardware reference
917                    ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
918                    summary |= (ULL(1) << i);
919                }
920            }
921        }
922
923        uint64_t interrupts = cpuXC->cpu->intr_status();
924        for (int i = INTLEVEL_EXTERNAL_MIN;
925            i < INTLEVEL_EXTERNAL_MAX; i++) {
926            if (interrupts & (ULL(1) << i)) {
927                // See table 4-19 of 21164 hardware reference
928                ipl = i;
929                summary |= (ULL(1) << i);
930            }
931        }
932
933        if (cpuXC->readMiscReg(IPR_ASTRR))
934            panic("asynchronous traps not implemented\n");
935
936        if (ipl && ipl > cpuXC->readMiscReg(IPR_IPLR)) {
937            cpuXC->setMiscReg(IPR_ISR, summary);
938            cpuXC->setMiscReg(IPR_INTID, ipl);
939
940            Fault(new InterruptFault)->invoke(xcProxy);
941
942            DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
943                    cpuXC->readMiscReg(IPR_IPLR), ipl, summary);
944        }
945    }
946#endif
947
948    // maintain $r0 semantics
949    cpuXC->setIntReg(ZeroReg, 0);
950#if THE_ISA == ALPHA_ISA
951    cpuXC->setFloatReg(ZeroReg, 0.0);
952#endif // ALPHA_ISA
953
954    if (status() == IcacheAccessComplete) {
955        // We've already fetched an instruction and were stalled on an
956        // I-cache miss.  No need to fetch it again.
957
958        // Set status to running; tick event will get rescheduled if
959        // necessary at end of tick() function.
960        _status = Running;
961    } else {
962        // Try to fetch an instruction
963
964        // set up memory request for instruction fetch
965#if FULL_SYSTEM
966#define IFETCH_FLAGS(pc)	((pc) & 1) ? PHYSICAL : 0
967#else
968#define IFETCH_FLAGS(pc)	0
969#endif
970
971        DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",cpuXC->readPC(),
972                cpuXC->readNextPC(),cpuXC->readNextNPC());
973
974#if SIMPLE_CPU_MEM_TIMING
975        CpuRequest *ifetch_req = new CpuRequest();
976        ifetch_req->size = sizeof(MachInst);
977#endif
978
979        ifetch_req->vaddr = cpuXC->readPC() & ~3;
980        ifetch_req->time = curTick;
981
982/*	memReq->reset(xc->regs.pc & ~3, sizeof(uint32_t),
983                     IFETCH_FLAGS(xc->regs.pc));
984*/
985
986        fault = cpuXC->translateInstReq(ifetch_req);
987
988        if (fault == NoFault) {
989#if SIMPLE_CPU_MEM_TIMING
990            Packet *ifetch_pkt = new Packet;
991            ifetch_pkt->cmd = Read;
992            ifetch_pkt->data = (uint8_t *)&inst;
993            ifetch_pkt->req = ifetch_req;
994            ifetch_pkt->size = sizeof(MachInst);
995#endif
996            ifetch_pkt->addr = ifetch_req->paddr;
997
998            sendIcacheRequest(ifetch_pkt);
999#if SIMPLE_CPU_MEM_TIMING || SIMPLE_CPU_MEM_ATOMIC
1000            return;
1001#endif
1002/*
1003        if (icacheInterface && fault == NoFault) {
1004            memReq->completionEvent = NULL;
1005
1006            memReq->time = curTick;
1007            memReq->flags |= INST_READ;
1008            MemAccessResult result = icacheInterface->access(memReq);
1009
1010            // Ugly hack to get an event scheduled *only* if the access is
1011            // a miss.  We really should add first-class support for this
1012            // at some point.
1013                if (result != MA_HIT && icacheInterface->doEvents()) {
1014                memReq->completionEvent = &cacheCompletionEvent;
1015                lastIcacheStall = curTick;
1016                unscheduleTickEvent();
1017                _status = IcacheMissStall;
1018                return;
1019            }
1020        }
1021*/
1022        }
1023    }
1024
1025    // If we've got a valid instruction (i.e., no fault on instruction
1026    // fetch), then execute it.
1027    if (fault == NoFault) {
1028
1029        // keep an instruction count
1030        numInst++;
1031        numInsts++;
1032
1033        // check for instruction-count-based events
1034        comInstEventQueue[0]->serviceEvents(numInst);
1035
1036        // decode the instruction
1037        inst = gtoh(inst);
1038        curStaticInst = StaticInst::decode(makeExtMI(inst, cpuXC->readPC()));
1039
1040        traceData = Trace::getInstRecord(curTick, xcProxy, this, curStaticInst,
1041                                         cpuXC->readPC());
1042
1043        DPRINTF(Decode,"Decode: Decoded %s instruction (opcode: 0x%x): 0x%x\n",
1044                curStaticInst->getName(),curStaticInst->getOpcode(), curStaticInst->machInst);
1045
1046#if FULL_SYSTEM
1047        cpuXC->setInst(inst);
1048#endif // FULL_SYSTEM
1049
1050        cpuXC->func_exe_inst++;
1051
1052        fault = curStaticInst->execute(this, traceData);
1053
1054#if FULL_SYSTEM
1055        if (system->kernelBinning->fnbin) {
1056            assert(kernelStats);
1057            system->kernelBinning->execute(xcProxy, inst);
1058        }
1059
1060        if (cpuXC->profile) {
1061            bool usermode =
1062                (cpuXC->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
1063            cpuXC->profilePC = usermode ? 1 : cpuXC->readPC();
1064            ProfileNode *node = cpuXC->profile->consume(xcProxy, inst);
1065            if (node)
1066                cpuXC->profileNode = node;
1067        }
1068#endif
1069
1070        if (curStaticInst->isMemRef()) {
1071            numMemRefs++;
1072        }
1073
1074        if (curStaticInst->isLoad()) {
1075            ++numLoad;
1076            comLoadEventQueue[0]->serviceEvents(numLoad);
1077        }
1078
1079        // If we have a dcache miss, then we can't finialize the instruction
1080        // trace yet because we want to populate it with the data later
1081        if (traceData && (status() != DcacheWaitResponse)) {
1082            traceData->finalize();
1083        }
1084
1085        traceFunctions(cpuXC->readPC());
1086
1087    }	// if (fault == NoFault)
1088
1089    if (fault != NoFault) {
1090#if FULL_SYSTEM
1091        fault->invoke(xcProxy);
1092#else // !FULL_SYSTEM
1093        fatal("fault (%s) detected @ PC %08p", fault->name(), cpuXC->readPC());
1094#endif // FULL_SYSTEM
1095    }
1096    else {
1097#if THE_ISA != MIPS_ISA
1098        // go to the next instruction
1099        cpuXC->setPC(cpuXC->readNextPC());
1100        cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
1101#else
1102        // go to the next instruction
1103        cpuXC->setPC(cpuXC->readNextPC());
1104        cpuXC->setNextPC(cpuXC->readNextNPC());
1105        cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst));
1106#endif
1107
1108    }
1109
1110#if FULL_SYSTEM
1111    Addr oldpc;
1112    do {
1113        oldpc = cpuXC->readPC();
1114        system->pcEventQueue.service(xcProxy);
1115    } while (oldpc != cpuXC->readPC());
1116#endif
1117
1118    assert(status() == Running ||
1119           status() == Idle ||
1120           status() == DcacheWaitResponse);
1121
1122    if (status() == Running && !tickEvent.scheduled())
1123        tickEvent.schedule(curTick + cycles(1));
1124}
1125
1126////////////////////////////////////////////////////////////////////////
1127//
1128//  SimpleCPU Simulation Object
1129//
1130BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
1131
1132    Param<Counter> max_insts_any_thread;
1133    Param<Counter> max_insts_all_threads;
1134    Param<Counter> max_loads_any_thread;
1135    Param<Counter> max_loads_all_threads;
1136
1137#if FULL_SYSTEM
1138    SimObjectParam<AlphaITB *> itb;
1139    SimObjectParam<AlphaDTB *> dtb;
1140    SimObjectParam<System *> system;
1141    Param<int> cpu_id;
1142    Param<Tick> profile;
1143#else
1144    SimObjectParam<MemObject *> mem;
1145    SimObjectParam<Process *> workload;
1146#endif // FULL_SYSTEM
1147
1148    Param<int> clock;
1149
1150    Param<bool> defer_registration;
1151    Param<int> width;
1152    Param<bool> function_trace;
1153    Param<Tick> function_trace_start;
1154
1155END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
1156
1157BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
1158
1159    INIT_PARAM(max_insts_any_thread,
1160               "terminate when any thread reaches this inst count"),
1161    INIT_PARAM(max_insts_all_threads,
1162               "terminate when all threads have reached this inst count"),
1163    INIT_PARAM(max_loads_any_thread,
1164               "terminate when any thread reaches this load count"),
1165    INIT_PARAM(max_loads_all_threads,
1166               "terminate when all threads have reached this load count"),
1167
1168#if FULL_SYSTEM
1169    INIT_PARAM(itb, "Instruction TLB"),
1170    INIT_PARAM(dtb, "Data TLB"),
1171    INIT_PARAM(system, "system object"),
1172    INIT_PARAM(cpu_id, "processor ID"),
1173    INIT_PARAM(profile, ""),
1174#else
1175    INIT_PARAM(mem, "memory"),
1176    INIT_PARAM(workload, "processes to run"),
1177#endif // FULL_SYSTEM
1178
1179    INIT_PARAM(clock, "clock speed"),
1180    INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
1181    INIT_PARAM(width, "cpu width"),
1182    INIT_PARAM(function_trace, "Enable function trace"),
1183    INIT_PARAM(function_trace_start, "Cycle to start function trace")
1184
1185END_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
1186
1187
1188CREATE_SIM_OBJECT(SimpleCPU)
1189{
1190    SimpleCPU::Params *params = new SimpleCPU::Params();
1191    params->name = getInstanceName();
1192    params->numberOfThreads = 1;
1193    params->max_insts_any_thread = max_insts_any_thread;
1194    params->max_insts_all_threads = max_insts_all_threads;
1195    params->max_loads_any_thread = max_loads_any_thread;
1196    params->max_loads_all_threads = max_loads_all_threads;
1197    params->deferRegistration = defer_registration;
1198    params->clock = clock;
1199    params->functionTrace = function_trace;
1200    params->functionTraceStart = function_trace_start;
1201    params->width = width;
1202
1203#if FULL_SYSTEM
1204    params->itb = itb;
1205    params->dtb = dtb;
1206    params->system = system;
1207    params->cpu_id = cpu_id;
1208    params->profile = profile;
1209#else
1210    params->mem = mem;
1211    params->process = workload;
1212#endif
1213
1214    SimpleCPU *cpu = new SimpleCPU(params);
1215    return cpu;
1216}
1217
1218REGISTER_SIM_OBJECT("SimpleCPU", SimpleCPU)
1219
1220