timing.cc revision 2630
12650Ssaidi@eecs.umich.edu/*
22650Ssaidi@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan
32650Ssaidi@eecs.umich.edu * All rights reserved.
42650Ssaidi@eecs.umich.edu *
52650Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
62650Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are
72650Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright
82650Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
92650Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
102650Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
112650Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution;
122650Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its
132650Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from
142650Ssaidi@eecs.umich.edu * this software without specific prior written permission.
152650Ssaidi@eecs.umich.edu *
162650Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172650Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182650Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192650Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202650Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212650Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222650Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232650Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242650Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252650Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262650Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272650Ssaidi@eecs.umich.edu */
282650Ssaidi@eecs.umich.edu
294194Ssaidi@eecs.umich.edu#include "arch/utility.hh"
303817Ssaidi@eecs.umich.edu#include "cpu/exetrace.hh"
313817Ssaidi@eecs.umich.edu#include "cpu/simple/timing.hh"
323817Ssaidi@eecs.umich.edu#include "mem/packet_impl.hh"
333817Ssaidi@eecs.umich.edu#include "sim/builder.hh"
343817Ssaidi@eecs.umich.edu
354194Ssaidi@eecs.umich.eduusing namespace std;
362650Ssaidi@eecs.umich.eduusing namespace TheISA;
373817Ssaidi@eecs.umich.edu
383817Ssaidi@eecs.umich.edu
394103Ssaidi@eecs.umich.eduvoid
404103Ssaidi@eecs.umich.eduTimingSimpleCPU::init()
414103Ssaidi@eecs.umich.edu{
424103Ssaidi@eecs.umich.edu    //Create Memory Ports (conect them up)
435531Snate@binkert.org    Port *mem_dport = mem->getPort("");
445531Snate@binkert.org    dcachePort.setPeer(mem_dport);
454103Ssaidi@eecs.umich.edu    mem_dport->setPeer(&dcachePort);
464103Ssaidi@eecs.umich.edu
475531Snate@binkert.org    Port *mem_iport = mem->getPort("");
484103Ssaidi@eecs.umich.edu    icachePort.setPeer(mem_iport);
495531Snate@binkert.org    mem_iport->setPeer(&icachePort);
504103Ssaidi@eecs.umich.edu
515531Snate@binkert.org    BaseCPU::init();
524103Ssaidi@eecs.umich.edu#if FULL_SYSTEM
535531Snate@binkert.org    for (int i = 0; i < execContexts.size(); ++i) {
544103Ssaidi@eecs.umich.edu        ExecContext *xc = execContexts[i];
554103Ssaidi@eecs.umich.edu
564103Ssaidi@eecs.umich.edu        // initialize CPU, including PC
574103Ssaidi@eecs.umich.edu        TheISA::initCPU(xc, xc->readCpuId());
585531Snate@binkert.org    }
594103Ssaidi@eecs.umich.edu#endif
605531Snate@binkert.org}
614103Ssaidi@eecs.umich.edu
624103Ssaidi@eecs.umich.eduTick
634103Ssaidi@eecs.umich.eduTimingSimpleCPU::CpuPort::recvAtomic(Packet *pkt)
644103Ssaidi@eecs.umich.edu{
653817Ssaidi@eecs.umich.edu    panic("TimingSimpleCPU doesn't expect recvAtomic callback!");
664185Ssaidi@eecs.umich.edu    return curTick;
672650Ssaidi@eecs.umich.edu}
685531Snate@binkert.org
695531Snate@binkert.orgvoid
702650Ssaidi@eecs.umich.eduTimingSimpleCPU::CpuPort::recvFunctional(Packet *pkt)
712650Ssaidi@eecs.umich.edu{
722982Sstever@eecs.umich.edu    panic("TimingSimpleCPU doesn't expect recvFunctional callback!");
733919Shsul@eecs.umich.edu}
744172Ssaidi@eecs.umich.edu
754103Ssaidi@eecs.umich.eduvoid
763919Shsul@eecs.umich.eduTimingSimpleCPU::CpuPort::recvStatusChange(Status status)
773919Shsul@eecs.umich.edu{
784172Ssaidi@eecs.umich.edu    panic("TimingSimpleCPU doesn't expect recvStatusChange callback!");
793919Shsul@eecs.umich.edu}
804172Ssaidi@eecs.umich.edu
812650Ssaidi@eecs.umich.eduTimingSimpleCPU::TimingSimpleCPU(Params *p)
823919Shsul@eecs.umich.edu    : BaseSimpleCPU(p), icachePort(this), dcachePort(this)
833919Shsul@eecs.umich.edu{
843919Shsul@eecs.umich.edu    _status = Idle;
854172Ssaidi@eecs.umich.edu    ifetch_pkt = dcache_pkt = NULL;
864103Ssaidi@eecs.umich.edu}
875606Snate@binkert.org
883919Shsul@eecs.umich.edu
894103Ssaidi@eecs.umich.eduTimingSimpleCPU::~TimingSimpleCPU()
904103Ssaidi@eecs.umich.edu{
915606Snate@binkert.org}
925606Snate@binkert.org
934103Ssaidi@eecs.umich.eduvoid
943919Shsul@eecs.umich.eduTimingSimpleCPU::serialize(ostream &os)
953919Shsul@eecs.umich.edu{
962650Ssaidi@eecs.umich.edu    BaseSimpleCPU::serialize(os);
973919Shsul@eecs.umich.edu    SERIALIZE_ENUM(_status);
983919Shsul@eecs.umich.edu}
993919Shsul@eecs.umich.edu
1004172Ssaidi@eecs.umich.eduvoid
1013919Shsul@eecs.umich.eduTimingSimpleCPU::unserialize(Checkpoint *cp, const string &section)
1025606Snate@binkert.org{
1033919Shsul@eecs.umich.edu    BaseSimpleCPU::unserialize(cp, section);
1045531Snate@binkert.org    UNSERIALIZE_ENUM(_status);
1054103Ssaidi@eecs.umich.edu}
1064103Ssaidi@eecs.umich.edu
1075606Snate@binkert.orgvoid
1085606Snate@binkert.orgTimingSimpleCPU::switchOut(Sampler *s)
1094103Ssaidi@eecs.umich.edu{
1103919Shsul@eecs.umich.edu    sampler = s;
1113919Shsul@eecs.umich.edu    if (status() == Running) {
1122650Ssaidi@eecs.umich.edu        _status = SwitchedOut;
1133919Shsul@eecs.umich.edu    }
1144172Ssaidi@eecs.umich.edu    sampler->signalSwitched();
1153827Shsul@eecs.umich.edu}
1163919Shsul@eecs.umich.edu
1174172Ssaidi@eecs.umich.edu
1184103Ssaidi@eecs.umich.eduvoid
1193919Shsul@eecs.umich.eduTimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
1202650Ssaidi@eecs.umich.edu{
1213919Shsul@eecs.umich.edu    BaseCPU::takeOverFrom(oldCPU);
1223919Shsul@eecs.umich.edu
1232650Ssaidi@eecs.umich.edu    // if any of this CPU's ExecContexts are active, mark the CPU as
1243921Shsul@eecs.umich.edu    // running and schedule its tick event.
1254172Ssaidi@eecs.umich.edu    for (int i = 0; i < execContexts.size(); ++i) {
1264103Ssaidi@eecs.umich.edu        ExecContext *xc = execContexts[i];
1275531Snate@binkert.org        if (xc->status() == ExecContext::Active && _status != Running) {
1284103Ssaidi@eecs.umich.edu            _status = Running;
1295531Snate@binkert.org            break;
1304103Ssaidi@eecs.umich.edu        }
1313921Shsul@eecs.umich.edu    }
1323919Shsul@eecs.umich.edu}
1333919Shsul@eecs.umich.edu
1344172Ssaidi@eecs.umich.edu
1353919Shsul@eecs.umich.eduvoid
1362650Ssaidi@eecs.umich.eduTimingSimpleCPU::activateContext(int thread_num, int delay)
1373919Shsul@eecs.umich.edu{
1383919Shsul@eecs.umich.edu    assert(thread_num == 0);
1394172Ssaidi@eecs.umich.edu    assert(cpuXC);
1404103Ssaidi@eecs.umich.edu
1415531Snate@binkert.org    assert(_status == Idle);
1424103Ssaidi@eecs.umich.edu
1435531Snate@binkert.org    notIdleFraction++;
1444103Ssaidi@eecs.umich.edu    _status = Running;
1453919Shsul@eecs.umich.edu    // kick things off by initiating the fetch of the next instruction
1463919Shsul@eecs.umich.edu    Event *e =
1474172Ssaidi@eecs.umich.edu        new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, true);
1484103Ssaidi@eecs.umich.edu    e->schedule(curTick + cycles(delay));
1495531Snate@binkert.org}
1504103Ssaidi@eecs.umich.edu
1515531Snate@binkert.org
1524103Ssaidi@eecs.umich.eduvoid
1533919Shsul@eecs.umich.eduTimingSimpleCPU::suspendContext(int thread_num)
1543919Shsul@eecs.umich.edu{
1554172Ssaidi@eecs.umich.edu    assert(thread_num == 0);
1564103Ssaidi@eecs.umich.edu    assert(cpuXC);
1575531Snate@binkert.org
1584103Ssaidi@eecs.umich.edu    panic("TimingSimpleCPU::suspendContext not implemented");
1595531Snate@binkert.org
1604103Ssaidi@eecs.umich.edu    assert(_status == Running);
1613919Shsul@eecs.umich.edu
1623919Shsul@eecs.umich.edu    notIdleFraction--;
1634172Ssaidi@eecs.umich.edu    _status = Idle;
1644103Ssaidi@eecs.umich.edu}
1653919Shsul@eecs.umich.edu
1663828Shsul@eecs.umich.edu
1673919Shsul@eecs.umich.edutemplate <class T>
1683919Shsul@eecs.umich.eduFault
1693919Shsul@eecs.umich.eduTimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
1704172Ssaidi@eecs.umich.edu{
1713919Shsul@eecs.umich.edu    Request *data_read_req = new Request(true);
1725606Snate@binkert.org
1733919Shsul@eecs.umich.edu    data_read_req->setVaddr(addr);
1745531Snate@binkert.org    data_read_req->setSize(sizeof(T));
1754103Ssaidi@eecs.umich.edu    data_read_req->setFlags(flags);
1764103Ssaidi@eecs.umich.edu    data_read_req->setTime(curTick);
1775606Snate@binkert.org
1785606Snate@binkert.org    if (traceData) {
1794103Ssaidi@eecs.umich.edu        traceData->setAddr(data_read_req->getVaddr());
1803919Shsul@eecs.umich.edu    }
1813919Shsul@eecs.umich.edu
1823817Ssaidi@eecs.umich.edu   // translate to physical address
1833919Shsul@eecs.umich.edu    Fault fault = cpuXC->translateDataReadReq(data_read_req);
1843919Shsul@eecs.umich.edu
1854172Ssaidi@eecs.umich.edu    // Now do the access.
1864103Ssaidi@eecs.umich.edu    if (fault == NoFault) {
1874103Ssaidi@eecs.umich.edu        Packet *data_read_pkt = new Packet;
1885531Snate@binkert.org        data_read_pkt->cmd = Read;
1894103Ssaidi@eecs.umich.edu        data_read_pkt->req = data_read_req;
1905531Snate@binkert.org        data_read_pkt->dataDynamic<T>(new T);
1914103Ssaidi@eecs.umich.edu        data_read_pkt->addr = data_read_req->getPaddr();
1923919Shsul@eecs.umich.edu        data_read_pkt->size = sizeof(T);
1933919Shsul@eecs.umich.edu        data_read_pkt->dest = Packet::Broadcast;
1944194Ssaidi@eecs.umich.edu
1954194Ssaidi@eecs.umich.edu        if (!dcachePort.sendTiming(data_read_pkt)) {
1964194Ssaidi@eecs.umich.edu            _status = DcacheRetry;
1973919Shsul@eecs.umich.edu            dcache_pkt = data_read_pkt;
1984194Ssaidi@eecs.umich.edu        } else {
1994194Ssaidi@eecs.umich.edu            _status = DcacheWaitResponse;
2004194Ssaidi@eecs.umich.edu            dcache_pkt = NULL;
2014194Ssaidi@eecs.umich.edu        }
2024216Ssaidi@eecs.umich.edu    }
2034194Ssaidi@eecs.umich.edu
2044194Ssaidi@eecs.umich.edu    // This will need a new way to tell if it has a dcache attached.
2054194Ssaidi@eecs.umich.edu    if (data_read_req->getFlags() & UNCACHEABLE)
2064194Ssaidi@eecs.umich.edu        recordEvent("Uncached Read");
2075531Snate@binkert.org
2083919Shsul@eecs.umich.edu    return fault;
2093817Ssaidi@eecs.umich.edu}
2103919Shsul@eecs.umich.edu
2115531Snate@binkert.org#ifndef DOXYGEN_SHOULD_SKIP_THIS
2125531Snate@binkert.org
2132650Ssaidi@eecs.umich.edutemplate
2142650Ssaidi@eecs.umich.eduFault
2152650Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
2162650Ssaidi@eecs.umich.edu
2174185Ssaidi@eecs.umich.edutemplate
2182650Ssaidi@eecs.umich.eduFault
2194194Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);
2204194Ssaidi@eecs.umich.edu
2212650Ssaidi@eecs.umich.edutemplate
2223919Shsul@eecs.umich.eduFault
2233825Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);
2243825Ssaidi@eecs.umich.edu
2253825Ssaidi@eecs.umich.edutemplate
2263825Ssaidi@eecs.umich.eduFault
2273825Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);
2283825Ssaidi@eecs.umich.edu
2293825Ssaidi@eecs.umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
2303825Ssaidi@eecs.umich.edu
2313825Ssaidi@eecs.umich.edutemplate<>
2323825Ssaidi@eecs.umich.eduFault
2333825Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, double &data, unsigned flags)
2343825Ssaidi@eecs.umich.edu{
2353825Ssaidi@eecs.umich.edu    return read(addr, *(uint64_t*)&data, flags);
2363825Ssaidi@eecs.umich.edu}
2373825Ssaidi@eecs.umich.edu
2383825Ssaidi@eecs.umich.edutemplate<>
2394172Ssaidi@eecs.umich.eduFault
2402650Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, float &data, unsigned flags)
2413825Ssaidi@eecs.umich.edu{
2424172Ssaidi@eecs.umich.edu    return read(addr, *(uint32_t*)&data, flags);
2433825Ssaidi@eecs.umich.edu}
2444207Ssaidi@eecs.umich.edu
2454207Ssaidi@eecs.umich.edu
2464207Ssaidi@eecs.umich.edutemplate<>
2474207Ssaidi@eecs.umich.eduFault
2484207Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
2494207Ssaidi@eecs.umich.edu{
2504207Ssaidi@eecs.umich.edu    return read(addr, (uint32_t&)data, flags);
2512650Ssaidi@eecs.umich.edu}
2524194Ssaidi@eecs.umich.edu
2534194Ssaidi@eecs.umich.edu
2544194Ssaidi@eecs.umich.edutemplate <class T>
2554194Ssaidi@eecs.umich.eduFault
2564194Ssaidi@eecs.umich.eduTimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
2574194Ssaidi@eecs.umich.edu{
2585531Snate@binkert.org    Request *data_write_req = new Request(true);
2595531Snate@binkert.org    data_write_req->setVaddr(addr);
2604194Ssaidi@eecs.umich.edu    data_write_req->setTime(curTick);
2614194Ssaidi@eecs.umich.edu    data_write_req->setSize(sizeof(T));
2624194Ssaidi@eecs.umich.edu    data_write_req->setFlags(flags);
2634194Ssaidi@eecs.umich.edu
2644194Ssaidi@eecs.umich.edu    // translate to physical address
2654194Ssaidi@eecs.umich.edu    Fault fault = cpuXC->translateDataWriteReq(data_write_req);
2664194Ssaidi@eecs.umich.edu    // Now do the access.
2674194Ssaidi@eecs.umich.edu    if (fault == NoFault) {
2684194Ssaidi@eecs.umich.edu        Packet *data_write_pkt = new Packet;
2694194Ssaidi@eecs.umich.edu        data_write_pkt->cmd = Write;
2704194Ssaidi@eecs.umich.edu        data_write_pkt->req = data_write_req;
2714194Ssaidi@eecs.umich.edu        data_write_pkt->allocate();
2724194Ssaidi@eecs.umich.edu        data_write_pkt->size = sizeof(T);
2734194Ssaidi@eecs.umich.edu        data_write_pkt->set(data);
2744194Ssaidi@eecs.umich.edu        data_write_pkt->addr = data_write_req->getPaddr();
2754194Ssaidi@eecs.umich.edu        data_write_pkt->dest = Packet::Broadcast;
2764194Ssaidi@eecs.umich.edu
2774194Ssaidi@eecs.umich.edu        if (!dcachePort.sendTiming(data_write_pkt)) {
2784194Ssaidi@eecs.umich.edu            _status = DcacheRetry;
2794194Ssaidi@eecs.umich.edu            dcache_pkt = data_write_pkt;
2804194Ssaidi@eecs.umich.edu        } else {
2814194Ssaidi@eecs.umich.edu            _status = DcacheWaitResponse;
2824194Ssaidi@eecs.umich.edu            dcache_pkt = NULL;
2834194Ssaidi@eecs.umich.edu        }
2844194Ssaidi@eecs.umich.edu    }
2853825Ssaidi@eecs.umich.edu
2863825Ssaidi@eecs.umich.edu    // This will need a new way to tell if it's hooked up to a cache or not.
2872650Ssaidi@eecs.umich.edu    if (data_write_req->getFlags() & UNCACHEABLE)
2882650Ssaidi@eecs.umich.edu        recordEvent("Uncached Write");
2892650Ssaidi@eecs.umich.edu
2902651Ssaidi@eecs.umich.edu    // If the write needs to have a fault on the access, consider calling
2912680Sktlim@umich.edu    // changeStatus() and changing it to "bad addr write" or something.
2922651Ssaidi@eecs.umich.edu    return fault;
2932651Ssaidi@eecs.umich.edu}
2942651Ssaidi@eecs.umich.edu
2952651Ssaidi@eecs.umich.edu
2962651Ssaidi@eecs.umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
2972680Sktlim@umich.edutemplate
2982651Ssaidi@eecs.umich.eduFault
2995606Snate@binkert.orgTimingSimpleCPU::write(uint64_t data, Addr addr,
3005606Snate@binkert.org                       unsigned flags, uint64_t *res);
3013888Ssaidi@eecs.umich.edu
3023888Ssaidi@eecs.umich.edutemplate
3033888Ssaidi@eecs.umich.eduFault
3043888Ssaidi@eecs.umich.eduTimingSimpleCPU::write(uint32_t data, Addr addr,
3053890Ssaidi@eecs.umich.edu                       unsigned flags, uint64_t *res);
3065606Snate@binkert.org
3073888Ssaidi@eecs.umich.edutemplate
3083888Ssaidi@eecs.umich.eduFault
3094216Ssaidi@eecs.umich.eduTimingSimpleCPU::write(uint16_t data, Addr addr,
3103888Ssaidi@eecs.umich.edu                       unsigned flags, uint64_t *res);
3113888Ssaidi@eecs.umich.edu
3124172Ssaidi@eecs.umich.edutemplate
3134172Ssaidi@eecs.umich.eduFault
3143921Shsul@eecs.umich.eduTimingSimpleCPU::write(uint8_t data, Addr addr,
3153888Ssaidi@eecs.umich.edu                       unsigned flags, uint64_t *res);
3165606Snate@binkert.org
3172651Ssaidi@eecs.umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
3182651Ssaidi@eecs.umich.edu
3192651Ssaidi@eecs.umich.edutemplate<>
3202680Sktlim@umich.eduFault
3212651Ssaidi@eecs.umich.eduTimingSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
3225606Snate@binkert.org{
3235606Snate@binkert.org    return write(*(uint64_t*)&data, addr, flags, res);
3243891Ssaidi@eecs.umich.edu}
3253891Ssaidi@eecs.umich.edu
3263891Ssaidi@eecs.umich.edutemplate<>
3273891Ssaidi@eecs.umich.eduFault
3284216Ssaidi@eecs.umich.eduTimingSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
3294216Ssaidi@eecs.umich.edu{
3304216Ssaidi@eecs.umich.edu    return write(*(uint32_t*)&data, addr, flags, res);
3314216Ssaidi@eecs.umich.edu}
3323891Ssaidi@eecs.umich.edu
3335606Snate@binkert.org
3343891Ssaidi@eecs.umich.edutemplate<>
3353891Ssaidi@eecs.umich.eduFault
3364216Ssaidi@eecs.umich.eduTimingSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
3373891Ssaidi@eecs.umich.edu{
3383891Ssaidi@eecs.umich.edu    return write((uint32_t)data, addr, flags, res);
3394172Ssaidi@eecs.umich.edu}
3404172Ssaidi@eecs.umich.edu
3413921Shsul@eecs.umich.edu
3423891Ssaidi@eecs.umich.eduvoid
3433891Ssaidi@eecs.umich.eduTimingSimpleCPU::fetch()
3445606Snate@binkert.org{
3452651Ssaidi@eecs.umich.edu    Request *ifetch_req = new Request(true);
3462650Ssaidi@eecs.umich.edu    ifetch_req->setSize(sizeof(MachInst));
347
348    ifetch_pkt = new Packet;
349    ifetch_pkt->cmd = Read;
350    ifetch_pkt->dataStatic(&inst);
351    ifetch_pkt->req = ifetch_req;
352    ifetch_pkt->size = sizeof(MachInst);
353    ifetch_pkt->dest = Packet::Broadcast;
354
355    Fault fault = setupFetchPacket(ifetch_pkt);
356    if (fault == NoFault) {
357        if (!icachePort.sendTiming(ifetch_pkt)) {
358            // Need to wait for retry
359            _status = IcacheRetry;
360        } else {
361            // Need to wait for cache to respond
362            _status = IcacheWaitResponse;
363            // ownership of packet transferred to memory system
364            ifetch_pkt = NULL;
365        }
366    } else {
367        panic("TimingSimpleCPU fetch fault handling not implemented");
368    }
369}
370
371
372void
373TimingSimpleCPU::completeInst(Fault fault)
374{
375    postExecute();
376
377    if (traceData) {
378        traceData->finalize();
379    }
380
381    advancePC(fault);
382
383    fetch();
384}
385
386
387void
388TimingSimpleCPU::completeIfetch()
389{
390    // received a response from the icache: execute the received
391    // instruction
392    assert(_status == IcacheWaitResponse);
393    _status = Running;
394    preExecute();
395    if (curStaticInst->isMemRef()) {
396        // load or store: just send to dcache
397        Fault fault = curStaticInst->initiateAcc(this, traceData);
398        assert(fault == NoFault);
399        assert(_status == DcacheWaitResponse);
400    } else {
401        // non-memory instruction: execute completely now
402        Fault fault = curStaticInst->execute(this, traceData);
403        completeInst(fault);
404    }
405}
406
407
408bool
409TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt)
410{
411    cpu->completeIfetch();
412    return true;
413}
414
415Packet *
416TimingSimpleCPU::IcachePort::recvRetry()
417{
418    // we shouldn't get a retry unless we have a packet that we're
419    // waiting to transmit
420    assert(cpu->ifetch_pkt != NULL);
421    assert(cpu->_status == IcacheRetry);
422    cpu->_status = IcacheWaitResponse;
423    Packet *tmp = cpu->ifetch_pkt;
424    cpu->ifetch_pkt = NULL;
425    return tmp;
426}
427
428void
429TimingSimpleCPU::completeDataAccess(Packet *pkt)
430{
431    // received a response from the dcache: complete the load or store
432    // instruction
433    assert(pkt->result == Success);
434    assert(_status == DcacheWaitResponse);
435    _status = Running;
436
437    Fault fault = curStaticInst->completeAcc(pkt, this, traceData);
438
439    completeInst(fault);
440}
441
442
443
444bool
445TimingSimpleCPU::DcachePort::recvTiming(Packet *pkt)
446{
447    cpu->completeDataAccess(pkt);
448    return true;
449}
450
451Packet *
452TimingSimpleCPU::DcachePort::recvRetry()
453{
454    // we shouldn't get a retry unless we have a packet that we're
455    // waiting to transmit
456    assert(cpu->dcache_pkt != NULL);
457    assert(cpu->_status == DcacheRetry);
458    cpu->_status = DcacheWaitResponse;
459    Packet *tmp = cpu->dcache_pkt;
460    cpu->dcache_pkt = NULL;
461    return tmp;
462}
463
464
465////////////////////////////////////////////////////////////////////////
466//
467//  TimingSimpleCPU Simulation Object
468//
469BEGIN_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU)
470
471    Param<Counter> max_insts_any_thread;
472    Param<Counter> max_insts_all_threads;
473    Param<Counter> max_loads_any_thread;
474    Param<Counter> max_loads_all_threads;
475    SimObjectParam<MemObject *> mem;
476
477#if FULL_SYSTEM
478    SimObjectParam<AlphaITB *> itb;
479    SimObjectParam<AlphaDTB *> dtb;
480    SimObjectParam<System *> system;
481    Param<int> cpu_id;
482    Param<Tick> profile;
483#else
484    SimObjectParam<Process *> workload;
485#endif // FULL_SYSTEM
486
487    Param<int> clock;
488
489    Param<bool> defer_registration;
490    Param<int> width;
491    Param<bool> function_trace;
492    Param<Tick> function_trace_start;
493    Param<bool> simulate_stalls;
494
495END_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU)
496
497BEGIN_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU)
498
499    INIT_PARAM(max_insts_any_thread,
500               "terminate when any thread reaches this inst count"),
501    INIT_PARAM(max_insts_all_threads,
502               "terminate when all threads have reached this inst count"),
503    INIT_PARAM(max_loads_any_thread,
504               "terminate when any thread reaches this load count"),
505    INIT_PARAM(max_loads_all_threads,
506               "terminate when all threads have reached this load count"),
507    INIT_PARAM(mem, "memory"),
508
509#if FULL_SYSTEM
510    INIT_PARAM(itb, "Instruction TLB"),
511    INIT_PARAM(dtb, "Data TLB"),
512    INIT_PARAM(system, "system object"),
513    INIT_PARAM(cpu_id, "processor ID"),
514    INIT_PARAM(profile, ""),
515#else
516    INIT_PARAM(workload, "processes to run"),
517#endif // FULL_SYSTEM
518
519    INIT_PARAM(clock, "clock speed"),
520    INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
521    INIT_PARAM(width, "cpu width"),
522    INIT_PARAM(function_trace, "Enable function trace"),
523    INIT_PARAM(function_trace_start, "Cycle to start function trace"),
524    INIT_PARAM(simulate_stalls, "Simulate cache stall cycles")
525
526END_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU)
527
528
529CREATE_SIM_OBJECT(TimingSimpleCPU)
530{
531    TimingSimpleCPU::Params *params = new TimingSimpleCPU::Params();
532    params->name = getInstanceName();
533    params->numberOfThreads = 1;
534    params->max_insts_any_thread = max_insts_any_thread;
535    params->max_insts_all_threads = max_insts_all_threads;
536    params->max_loads_any_thread = max_loads_any_thread;
537    params->max_loads_all_threads = max_loads_all_threads;
538    params->deferRegistration = defer_registration;
539    params->clock = clock;
540    params->functionTrace = function_trace;
541    params->functionTraceStart = function_trace_start;
542    params->mem = mem;
543
544#if FULL_SYSTEM
545    params->itb = itb;
546    params->dtb = dtb;
547    params->system = system;
548    params->cpu_id = cpu_id;
549    params->profile = profile;
550#else
551    params->process = workload;
552#endif
553
554    TimingSimpleCPU *cpu = new TimingSimpleCPU(params);
555    return cpu;
556}
557
558REGISTER_SIM_OBJECT("TimingSimpleCPU", TimingSimpleCPU)
559
560