timing.cc revision 8948
1955SN/A/*
2955SN/A * Copyright (c) 2010-2012 ARM Limited
312230Sgiacomo.travaglini@arm.com * All rights reserved
49812Sandreas.hansson@arm.com *
59812Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
69812Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
79812Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
89812Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
99812Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
109812Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
119812Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
129812Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
139812Sandreas.hansson@arm.com *
149812Sandreas.hansson@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
157816Ssteve.reinhardt@amd.com * All rights reserved.
165871Snate@binkert.org *
171762SN/A * Redistribution and use in source and binary forms, with or without
18955SN/A * modification, are permitted provided that the following conditions are
19955SN/A * met: redistributions of source code must retain the above copyright
20955SN/A * notice, this list of conditions and the following disclaimer;
21955SN/A * redistributions in binary form must reproduce the above copyright
22955SN/A * notice, this list of conditions and the following disclaimer in the
23955SN/A * documentation and/or other materials provided with the distribution;
24955SN/A * neither the name of the copyright holders nor the names of its
25955SN/A * contributors may be used to endorse or promote products derived from
26955SN/A * this software without specific prior written permission.
27955SN/A *
28955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39955SN/A *
40955SN/A * Authors: Steve Reinhardt
41955SN/A */
422665Ssaidi@eecs.umich.edu
432665Ssaidi@eecs.umich.edu#include "arch/locked_mem.hh"
445863Snate@binkert.org#include "arch/mmapped_ipr.hh"
45955SN/A#include "arch/utility.hh"
46955SN/A#include "base/bigint.hh"
47955SN/A#include "config/the_isa.hh"
48955SN/A#include "cpu/simple/timing.hh"
49955SN/A#include "cpu/exetrace.hh"
508878Ssteve.reinhardt@amd.com#include "debug/Config.hh"
512632Sstever@eecs.umich.edu#include "debug/ExecFaulting.hh"
528878Ssteve.reinhardt@amd.com#include "debug/SimpleCPU.hh"
532632Sstever@eecs.umich.edu#include "mem/packet.hh"
54955SN/A#include "mem/packet_access.hh"
558878Ssteve.reinhardt@amd.com#include "params/TimingSimpleCPU.hh"
562632Sstever@eecs.umich.edu#include "sim/faults.hh"
572761Sstever@eecs.umich.edu#include "sim/full_system.hh"
582632Sstever@eecs.umich.edu#include "sim/system.hh"
592632Sstever@eecs.umich.edu
602632Sstever@eecs.umich.eduusing namespace std;
612761Sstever@eecs.umich.eduusing namespace TheISA;
622761Sstever@eecs.umich.edu
632761Sstever@eecs.umich.eduvoid
648878Ssteve.reinhardt@amd.comTimingSimpleCPU::init()
658878Ssteve.reinhardt@amd.com{
662761Sstever@eecs.umich.edu    BaseCPU::init();
672761Sstever@eecs.umich.edu
682761Sstever@eecs.umich.edu    // Initialise the ThreadContext's memory proxies
692761Sstever@eecs.umich.edu    tcBase()->initMemProxies(tcBase());
702761Sstever@eecs.umich.edu
718878Ssteve.reinhardt@amd.com    if (FullSystem) {
728878Ssteve.reinhardt@amd.com        for (int i = 0; i < threadContexts.size(); ++i) {
732632Sstever@eecs.umich.edu            ThreadContext *tc = threadContexts[i];
742632Sstever@eecs.umich.edu            // initialize CPU, including PC
758878Ssteve.reinhardt@amd.com            TheISA::initCPU(tc, _cpuId);
768878Ssteve.reinhardt@amd.com        }
772632Sstever@eecs.umich.edu    }
78955SN/A}
79955SN/A
80955SN/Avoid
8112563Sgabeblack@google.comTimingSimpleCPU::TimingCPUPort::TickEvent::schedule(PacketPtr _pkt, Tick t)
8212563Sgabeblack@google.com{
836654Snate@binkert.org    pkt = _pkt;
8410196SCurtis.Dunham@arm.com    cpu->schedule(this, t);
85955SN/A}
865396Ssaidi@eecs.umich.edu
8711401Sandreas.sandberg@arm.comTimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p)
885863Snate@binkert.org    : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this),
895863Snate@binkert.org    dcachePort(this), fetchEvent(this)
904202Sbinkertn@umich.edu{
915863Snate@binkert.org    _status = Idle;
925863Snate@binkert.org
935863Snate@binkert.org    ifetch_pkt = dcache_pkt = NULL;
945863Snate@binkert.org    drainEvent = NULL;
9513541Sandrea.mondelli@ucf.edu    previousTick = 0;
96955SN/A    changeState(SimObject::Running);
976654Snate@binkert.org    system->totalNumInsts = 0;
985273Sstever@gmail.com}
995871Snate@binkert.org
1005273Sstever@gmail.com
1016654Snate@binkert.orgTimingSimpleCPU::~TimingSimpleCPU()
1025396Ssaidi@eecs.umich.edu{
1038120Sgblack@eecs.umich.edu}
1048120Sgblack@eecs.umich.edu
1058120Sgblack@eecs.umich.eduvoid
1068120Sgblack@eecs.umich.eduTimingSimpleCPU::serialize(ostream &os)
1078120Sgblack@eecs.umich.edu{
1088120Sgblack@eecs.umich.edu    SimObject::State so_state = SimObject::getState();
1098120Sgblack@eecs.umich.edu    SERIALIZE_ENUM(so_state);
1108120Sgblack@eecs.umich.edu    BaseSimpleCPU::serialize(os);
1118879Ssteve.reinhardt@amd.com}
1128879Ssteve.reinhardt@amd.com
1138879Ssteve.reinhardt@amd.comvoid
1148879Ssteve.reinhardt@amd.comTimingSimpleCPU::unserialize(Checkpoint *cp, const string &section)
1158879Ssteve.reinhardt@amd.com{
1168879Ssteve.reinhardt@amd.com    SimObject::State so_state;
1178879Ssteve.reinhardt@amd.com    UNSERIALIZE_ENUM(so_state);
1188879Ssteve.reinhardt@amd.com    BaseSimpleCPU::unserialize(cp, section);
1198879Ssteve.reinhardt@amd.com}
1208879Ssteve.reinhardt@amd.com
1218879Ssteve.reinhardt@amd.comunsigned int
1228879Ssteve.reinhardt@amd.comTimingSimpleCPU::drain(Event *drain_event)
1238879Ssteve.reinhardt@amd.com{
1248120Sgblack@eecs.umich.edu    // TimingSimpleCPU is ready to drain if it's not waiting for
1258120Sgblack@eecs.umich.edu    // an access to complete.
1268120Sgblack@eecs.umich.edu    if (_status == Idle || _status == Running || _status == SwitchedOut) {
1278120Sgblack@eecs.umich.edu        changeState(SimObject::Drained);
1288120Sgblack@eecs.umich.edu        return 0;
1298120Sgblack@eecs.umich.edu    } else {
1308120Sgblack@eecs.umich.edu        changeState(SimObject::Draining);
1318120Sgblack@eecs.umich.edu        drainEvent = drain_event;
1328120Sgblack@eecs.umich.edu        return 1;
1338120Sgblack@eecs.umich.edu    }
1348120Sgblack@eecs.umich.edu}
1358120Sgblack@eecs.umich.edu
1368120Sgblack@eecs.umich.eduvoid
1378120Sgblack@eecs.umich.eduTimingSimpleCPU::resume()
1388879Ssteve.reinhardt@amd.com{
1398879Ssteve.reinhardt@amd.com    DPRINTF(SimpleCPU, "Resume\n");
1408879Ssteve.reinhardt@amd.com    if (_status != SwitchedOut && _status != Idle) {
1418879Ssteve.reinhardt@amd.com        assert(system->getMemoryMode() == Enums::timing);
14210458Sandreas.hansson@arm.com
14310458Sandreas.hansson@arm.com        if (fetchEvent.scheduled())
14410458Sandreas.hansson@arm.com           deschedule(fetchEvent);
1458879Ssteve.reinhardt@amd.com
1468879Ssteve.reinhardt@amd.com        schedule(fetchEvent, nextCycle());
1478879Ssteve.reinhardt@amd.com    }
1488879Ssteve.reinhardt@amd.com
14913421Sciro.santilli@arm.com    changeState(SimObject::Running);
15013421Sciro.santilli@arm.com}
1519227Sandreas.hansson@arm.com
1529227Sandreas.hansson@arm.comvoid
15312063Sgabeblack@google.comTimingSimpleCPU::switchOut()
15412063Sgabeblack@google.com{
15512063Sgabeblack@google.com    assert(_status == Running || _status == Idle);
1568879Ssteve.reinhardt@amd.com    _status = SwitchedOut;
1578879Ssteve.reinhardt@amd.com    numCycles += tickToCycles(curTick() - previousTick);
1588879Ssteve.reinhardt@amd.com
1598879Ssteve.reinhardt@amd.com    // If we've been scheduled to resume but are then told to switch out,
16010453SAndrew.Bardsley@arm.com    // we'll need to cancel it.
16110453SAndrew.Bardsley@arm.com    if (fetchEvent.scheduled())
16210453SAndrew.Bardsley@arm.com        deschedule(fetchEvent);
16310456SCurtis.Dunham@arm.com}
16410456SCurtis.Dunham@arm.com
16510456SCurtis.Dunham@arm.com
16610457Sandreas.hansson@arm.comvoid
16710457Sandreas.hansson@arm.comTimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
16811342Sandreas.hansson@arm.com{
16911342Sandreas.hansson@arm.com    BaseCPU::takeOverFrom(oldCPU);
1708120Sgblack@eecs.umich.edu
17112063Sgabeblack@google.com    // if any of this CPU's ThreadContexts are active, mark the CPU as
17212563Sgabeblack@google.com    // running and schedule its tick event.
17312063Sgabeblack@google.com    for (int i = 0; i < threadContexts.size(); ++i) {
17412063Sgabeblack@google.com        ThreadContext *tc = threadContexts[i];
1755871Snate@binkert.org        if (tc->status() == ThreadContext::Active && _status != Running) {
1765871Snate@binkert.org            _status = Running;
1776121Snate@binkert.org            break;
1785871Snate@binkert.org        }
1795871Snate@binkert.org    }
1809926Sstan.czerniawski@arm.com
18112243Sgabeblack@google.com    if (_status != Running) {
1821533SN/A        _status = Idle;
18312246Sgabeblack@google.com    }
18412246Sgabeblack@google.com    assert(threadContexts.size() == 1);
18512246Sgabeblack@google.com    previousTick = curTick();
18612246Sgabeblack@google.com}
1879239Sandreas.hansson@arm.com
1889239Sandreas.hansson@arm.com
1899239Sandreas.hansson@arm.comvoid
1909239Sandreas.hansson@arm.comTimingSimpleCPU::activateContext(ThreadID thread_num, int delay)
19112563Sgabeblack@google.com{
1929239Sandreas.hansson@arm.com    DPRINTF(SimpleCPU, "ActivateContext %d (%d cycles)\n", thread_num, delay);
1939239Sandreas.hansson@arm.com
194955SN/A    assert(thread_num == 0);
195955SN/A    assert(thread);
1962632Sstever@eecs.umich.edu
1972632Sstever@eecs.umich.edu    assert(_status == Idle);
198955SN/A
199955SN/A    notIdleFraction++;
200955SN/A    _status = Running;
201955SN/A
2028878Ssteve.reinhardt@amd.com    // kick things off by initiating the fetch of the next instruction
203955SN/A    schedule(fetchEvent, nextCycle(curTick() + ticks(delay)));
2042632Sstever@eecs.umich.edu}
2052632Sstever@eecs.umich.edu
2062632Sstever@eecs.umich.edu
2072632Sstever@eecs.umich.eduvoid
2082632Sstever@eecs.umich.eduTimingSimpleCPU::suspendContext(ThreadID thread_num)
2092632Sstever@eecs.umich.edu{
2102632Sstever@eecs.umich.edu    DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
2118268Ssteve.reinhardt@amd.com
2128268Ssteve.reinhardt@amd.com    assert(thread_num == 0);
2138268Ssteve.reinhardt@amd.com    assert(thread);
2148268Ssteve.reinhardt@amd.com
2158268Ssteve.reinhardt@amd.com    if (_status == Idle)
2168268Ssteve.reinhardt@amd.com        return;
2178268Ssteve.reinhardt@amd.com
21813715Sandreas.sandberg@arm.com    assert(_status == Running);
21913715Sandreas.sandberg@arm.com
22013715Sandreas.sandberg@arm.com    // just change status to Idle... if status != Running,
22113715Sandreas.sandberg@arm.com    // completeInst() will not initiate fetch of next instruction.
22213715Sandreas.sandberg@arm.com
22313715Sandreas.sandberg@arm.com    notIdleFraction--;
22413715Sandreas.sandberg@arm.com    _status = Idle;
22513715Sandreas.sandberg@arm.com}
22613715Sandreas.sandberg@arm.com
22713715Sandreas.sandberg@arm.combool
22813715Sandreas.sandberg@arm.comTimingSimpleCPU::handleReadPacket(PacketPtr pkt)
22913715Sandreas.sandberg@arm.com{
23013715Sandreas.sandberg@arm.com    RequestPtr req = pkt->req;
2312632Sstever@eecs.umich.edu    if (req->isMmappedIpr()) {
2322632Sstever@eecs.umich.edu        Tick delay;
2332632Sstever@eecs.umich.edu        delay = TheISA::handleIprRead(thread->getTC(), pkt);
2342632Sstever@eecs.umich.edu        new IprEvent(pkt, this, nextCycle(curTick() + delay));
2358268Ssteve.reinhardt@amd.com        _status = DcacheWaitResponse;
2362632Sstever@eecs.umich.edu        dcache_pkt = NULL;
2378268Ssteve.reinhardt@amd.com    } else if (!dcachePort.sendTiming(pkt)) {
2388268Ssteve.reinhardt@amd.com        _status = DcacheRetry;
2398268Ssteve.reinhardt@amd.com        dcache_pkt = pkt;
2408268Ssteve.reinhardt@amd.com    } else {
2413718Sstever@eecs.umich.edu        _status = DcacheWaitResponse;
2422634Sstever@eecs.umich.edu        // memory system takes ownership of packet
2432634Sstever@eecs.umich.edu        dcache_pkt = NULL;
2445863Snate@binkert.org    }
2452638Sstever@eecs.umich.edu    return dcache_pkt == NULL;
2468268Ssteve.reinhardt@amd.com}
2472632Sstever@eecs.umich.edu
2482632Sstever@eecs.umich.eduvoid
2492632Sstever@eecs.umich.eduTimingSimpleCPU::sendData(RequestPtr req, uint8_t *data, uint64_t *res,
2502632Sstever@eecs.umich.edu                          bool read)
25112563Sgabeblack@google.com{
2521858SN/A    PacketPtr pkt;
2533716Sstever@eecs.umich.edu    buildPacket(pkt, req, read);
2542638Sstever@eecs.umich.edu    pkt->dataDynamicArray<uint8_t>(data);
2552638Sstever@eecs.umich.edu    if (req->getFlags().isSet(Request::NO_ACCESS)) {
2562638Sstever@eecs.umich.edu        assert(!dcache_pkt);
2572638Sstever@eecs.umich.edu        pkt->makeResponse();
25812563Sgabeblack@google.com        completeDataAccess(pkt);
25912563Sgabeblack@google.com    } else if (read) {
2602638Sstever@eecs.umich.edu        handleReadPacket(pkt);
2615863Snate@binkert.org    } else {
2625863Snate@binkert.org        bool do_access = true;  // flag to suppress cache access
2635863Snate@binkert.org
264955SN/A        if (req->isLLSC()) {
2655341Sstever@gmail.com            do_access = TheISA::handleLockedWrite(thread, req);
2665341Sstever@gmail.com        } else if (req->isCondSwap()) {
2675863Snate@binkert.org            assert(res);
2687756SAli.Saidi@ARM.com            req->setExtraData(*res);
2695341Sstever@gmail.com        }
2706121Snate@binkert.org
2714494Ssaidi@eecs.umich.edu        if (do_access) {
2726121Snate@binkert.org            dcache_pkt = pkt;
2731105SN/A            handleWritePacket();
2742667Sstever@eecs.umich.edu        } else {
2752667Sstever@eecs.umich.edu            _status = DcacheWaitResponse;
2762667Sstever@eecs.umich.edu            completeDataAccess(pkt);
2772667Sstever@eecs.umich.edu        }
2786121Snate@binkert.org    }
2792667Sstever@eecs.umich.edu}
2805341Sstever@gmail.com
2815863Snate@binkert.orgvoid
2825341Sstever@gmail.comTimingSimpleCPU::sendSplitData(RequestPtr req1, RequestPtr req2,
2835341Sstever@gmail.com                               RequestPtr req, uint8_t *data, bool read)
2845341Sstever@gmail.com{
2858120Sgblack@eecs.umich.edu    PacketPtr pkt1, pkt2;
2865341Sstever@gmail.com    buildSplitPacket(pkt1, pkt2, req1, req2, req, data, read);
2878120Sgblack@eecs.umich.edu    if (req->getFlags().isSet(Request::NO_ACCESS)) {
2885341Sstever@gmail.com        assert(!dcache_pkt);
2898120Sgblack@eecs.umich.edu        pkt1->makeResponse();
2906121Snate@binkert.org        completeDataAccess(pkt1);
2916121Snate@binkert.org    } else if (read) {
29213715Sandreas.sandberg@arm.com        SplitFragmentSenderState * send_state =
29313715Sandreas.sandberg@arm.com            dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState);
2949396Sandreas.hansson@arm.com        if (handleReadPacket(pkt1)) {
2955397Ssaidi@eecs.umich.edu            send_state->clearFromParent();
2965397Ssaidi@eecs.umich.edu            send_state = dynamic_cast<SplitFragmentSenderState *>(
2977727SAli.Saidi@ARM.com                    pkt2->senderState);
2988268Ssteve.reinhardt@amd.com            if (handleReadPacket(pkt2)) {
2996168Snate@binkert.org                send_state->clearFromParent();
3005341Sstever@gmail.com            }
3018120Sgblack@eecs.umich.edu        }
3028120Sgblack@eecs.umich.edu    } else {
3038120Sgblack@eecs.umich.edu        dcache_pkt = pkt1;
3046814Sgblack@eecs.umich.edu        SplitFragmentSenderState * send_state =
3055863Snate@binkert.org            dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState);
3068120Sgblack@eecs.umich.edu        if (handleWritePacket()) {
3075341Sstever@gmail.com            send_state->clearFromParent();
3085863Snate@binkert.org            dcache_pkt = pkt2;
3098268Ssteve.reinhardt@amd.com            send_state = dynamic_cast<SplitFragmentSenderState *>(
3106121Snate@binkert.org                    pkt2->senderState);
3116121Snate@binkert.org            if (handleWritePacket()) {
3128268Ssteve.reinhardt@amd.com                send_state->clearFromParent();
3135742Snate@binkert.org            }
3145742Snate@binkert.org        }
3155341Sstever@gmail.com    }
3165742Snate@binkert.org}
3175742Snate@binkert.org
3185341Sstever@gmail.comvoid
3196017Snate@binkert.orgTimingSimpleCPU::translationFault(Fault fault)
3206121Snate@binkert.org{
3216017Snate@binkert.org    // fault may be NoFault in cases where a fault is suppressed,
32212158Sandreas.sandberg@arm.com    // for instance prefetches.
32312158Sandreas.sandberg@arm.com    numCycles += tickToCycles(curTick() - previousTick);
32412158Sandreas.sandberg@arm.com    previousTick = curTick();
3258120Sgblack@eecs.umich.edu
3267756SAli.Saidi@ARM.com    if (traceData) {
3277756SAli.Saidi@ARM.com        // Since there was a fault, we shouldn't trace this instruction.
3287756SAli.Saidi@ARM.com        delete traceData;
3297756SAli.Saidi@ARM.com        traceData = NULL;
3307816Ssteve.reinhardt@amd.com    }
3317816Ssteve.reinhardt@amd.com
3327816Ssteve.reinhardt@amd.com    postExecute();
3337816Ssteve.reinhardt@amd.com
3347816Ssteve.reinhardt@amd.com    if (getState() == SimObject::Draining) {
33511979Sgabeblack@google.com        advancePC(fault);
3367816Ssteve.reinhardt@amd.com        completeDrain();
3377816Ssteve.reinhardt@amd.com    } else {
3387816Ssteve.reinhardt@amd.com        advanceInst(fault);
3397816Ssteve.reinhardt@amd.com    }
3407756SAli.Saidi@ARM.com}
3417756SAli.Saidi@ARM.com
3429227Sandreas.hansson@arm.comvoid
3439227Sandreas.hansson@arm.comTimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr req, bool read)
3449227Sandreas.hansson@arm.com{
3459227Sandreas.hansson@arm.com    MemCmd cmd;
3469590Sandreas@sandberg.pp.se    if (read) {
3479590Sandreas@sandberg.pp.se        cmd = MemCmd::ReadReq;
3489590Sandreas@sandberg.pp.se        if (req->isLLSC())
3499590Sandreas@sandberg.pp.se            cmd = MemCmd::LoadLockedReq;
3509590Sandreas@sandberg.pp.se    } else {
3519590Sandreas@sandberg.pp.se        cmd = MemCmd::WriteReq;
3526654Snate@binkert.org        if (req->isLLSC()) {
3536654Snate@binkert.org            cmd = MemCmd::StoreCondReq;
3545871Snate@binkert.org        } else if (req->isSwap()) {
3556121Snate@binkert.org            cmd = MemCmd::SwapReq;
3568946Sandreas.hansson@arm.com        }
3579419Sandreas.hansson@arm.com    }
35812563Sgabeblack@google.com    pkt = new Packet(req, cmd, Packet::Broadcast);
3593918Ssaidi@eecs.umich.edu}
3603918Ssaidi@eecs.umich.edu
3611858SN/Avoid
3629556Sandreas.hansson@arm.comTimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
3639556Sandreas.hansson@arm.com        RequestPtr req1, RequestPtr req2, RequestPtr req,
3649556Sandreas.hansson@arm.com        uint8_t *data, bool read)
3659556Sandreas.hansson@arm.com{
36611294Sandreas.hansson@arm.com    pkt1 = pkt2 = NULL;
36711294Sandreas.hansson@arm.com
36811294Sandreas.hansson@arm.com    assert(!req1->isMmappedIpr() && !req2->isMmappedIpr());
36911294Sandreas.hansson@arm.com
37010878Sandreas.hansson@arm.com    if (req->getFlags().isSet(Request::NO_ACCESS)) {
37110878Sandreas.hansson@arm.com        buildPacket(pkt1, req, read);
37211811Sbaz21@cam.ac.uk        return;
37311811Sbaz21@cam.ac.uk    }
37411811Sbaz21@cam.ac.uk
37511982Sgabeblack@google.com    buildPacket(pkt1, req1, read);
37611982Sgabeblack@google.com    buildPacket(pkt2, req2, read);
37711982Sgabeblack@google.com
37813421Sciro.santilli@arm.com    req->setPhys(req1->getPaddr(), req->getSize(), req1->getFlags(), dataMasterId());
37913421Sciro.santilli@arm.com    PacketPtr pkt = new Packet(req, pkt1->cmd.responseCommand(),
38011982Sgabeblack@google.com                               Packet::Broadcast);
38111992Sgabeblack@google.com
38211982Sgabeblack@google.com    pkt->dataDynamicArray<uint8_t>(data);
38311982Sgabeblack@google.com    pkt1->dataStatic<uint8_t>(data);
38412305Sgabeblack@google.com    pkt2->dataStatic<uint8_t>(data + req1->getSize());
38512305Sgabeblack@google.com
38612305Sgabeblack@google.com    SplitMainSenderState * main_send_state = new SplitMainSenderState;
38712305Sgabeblack@google.com    pkt->senderState = main_send_state;
38812305Sgabeblack@google.com    main_send_state->fragments[0] = pkt1;
38912305Sgabeblack@google.com    main_send_state->fragments[1] = pkt2;
39012305Sgabeblack@google.com    main_send_state->outstanding = 2;
3919556Sandreas.hansson@arm.com    pkt1->senderState = new SplitFragmentSenderState(pkt, 0);
39212563Sgabeblack@google.com    pkt2->senderState = new SplitFragmentSenderState(pkt, 1);
39312563Sgabeblack@google.com}
39412563Sgabeblack@google.com
39512563Sgabeblack@google.comFault
3969556Sandreas.hansson@arm.comTimingSimpleCPU::readMem(Addr addr, uint8_t *data,
39712563Sgabeblack@google.com                         unsigned size, unsigned flags)
39812563Sgabeblack@google.com{
3999556Sandreas.hansson@arm.com    Fault fault;
40012563Sgabeblack@google.com    const int asid = 0;
40112563Sgabeblack@google.com    const ThreadID tid = 0;
40212563Sgabeblack@google.com    const Addr pc = thread->instAddr();
40312563Sgabeblack@google.com    unsigned block_size = dcachePort.peerBlockSize();
40412563Sgabeblack@google.com    BaseTLB::Mode mode = BaseTLB::Read;
40512563Sgabeblack@google.com
40612563Sgabeblack@google.com    if (traceData) {
40712563Sgabeblack@google.com        traceData->setAddr(addr);
4089556Sandreas.hansson@arm.com    }
4099556Sandreas.hansson@arm.com
4106121Snate@binkert.org    RequestPtr req  = new Request(asid, addr, size,
41111500Sandreas.hansson@arm.com                                  flags, dataMasterId(), pc, _cpuId, tid);
41210238Sandreas.hansson@arm.com
41310878Sandreas.hansson@arm.com    Addr split_addr = roundDown(addr + size - 1, block_size);
4149420Sandreas.hansson@arm.com    assert(split_addr <= addr || split_addr - addr < block_size);
41511500Sandreas.hansson@arm.com
41612563Sgabeblack@google.com    _status = DTBWaitResponse;
41712563Sgabeblack@google.com    if (split_addr > addr) {
4189420Sandreas.hansson@arm.com        RequestPtr req1, req2;
4199420Sandreas.hansson@arm.com        assert(!req->isLLSC() && !req->isSwap());
4209420Sandreas.hansson@arm.com        req->splitOnVaddr(split_addr, req1, req2);
4219420Sandreas.hansson@arm.com
42212063Sgabeblack@google.com        WholeTranslationState *state =
42312063Sgabeblack@google.com            new WholeTranslationState(req, req1, req2, new uint8_t[size],
42412063Sgabeblack@google.com                                      NULL, mode);
42512063Sgabeblack@google.com        DataTranslation<TimingSimpleCPU *> *trans1 =
42612063Sgabeblack@google.com            new DataTranslation<TimingSimpleCPU *>(this, state, 0);
42712063Sgabeblack@google.com        DataTranslation<TimingSimpleCPU *> *trans2 =
42812063Sgabeblack@google.com            new DataTranslation<TimingSimpleCPU *>(this, state, 1);
42912063Sgabeblack@google.com
43012063Sgabeblack@google.com        thread->dtb->translateTiming(req1, tc, trans1, mode);
43112063Sgabeblack@google.com        thread->dtb->translateTiming(req2, tc, trans2, mode);
43212063Sgabeblack@google.com    } else {
43312063Sgabeblack@google.com        WholeTranslationState *state =
43412063Sgabeblack@google.com            new WholeTranslationState(req, new uint8_t[size], NULL, mode);
43512063Sgabeblack@google.com        DataTranslation<TimingSimpleCPU *> *translation
43612063Sgabeblack@google.com            = new DataTranslation<TimingSimpleCPU *>(this, state);
43712063Sgabeblack@google.com        thread->dtb->translateTiming(req, tc, translation, mode);
43812063Sgabeblack@google.com    }
43912063Sgabeblack@google.com
44012063Sgabeblack@google.com    return NoFault;
44112063Sgabeblack@google.com}
44212063Sgabeblack@google.com
44312063Sgabeblack@google.combool
44410457Sandreas.hansson@arm.comTimingSimpleCPU::handleWritePacket()
44510457Sandreas.hansson@arm.com{
44610457Sandreas.hansson@arm.com    RequestPtr req = dcache_pkt->req;
44710457Sandreas.hansson@arm.com    if (req->isMmappedIpr()) {
44810457Sandreas.hansson@arm.com        Tick delay;
44912563Sgabeblack@google.com        delay = TheISA::handleIprWrite(thread->getTC(), dcache_pkt);
45012563Sgabeblack@google.com        new IprEvent(dcache_pkt, this, nextCycle(curTick() + delay));
45112563Sgabeblack@google.com        _status = DcacheWaitResponse;
45210457Sandreas.hansson@arm.com        dcache_pkt = NULL;
45312063Sgabeblack@google.com    } else if (!dcachePort.sendTiming(dcache_pkt)) {
45412063Sgabeblack@google.com        _status = DcacheRetry;
45512063Sgabeblack@google.com    } else {
45612563Sgabeblack@google.com        _status = DcacheWaitResponse;
45712563Sgabeblack@google.com        // memory system takes ownership of packet
45812563Sgabeblack@google.com        dcache_pkt = NULL;
45912563Sgabeblack@google.com    }
46012563Sgabeblack@google.com    return dcache_pkt == NULL;
46112563Sgabeblack@google.com}
46212063Sgabeblack@google.com
46312063Sgabeblack@google.comFault
46410238Sandreas.hansson@arm.comTimingSimpleCPU::writeMem(uint8_t *data, unsigned size,
46510238Sandreas.hansson@arm.com                          Addr addr, unsigned flags, uint64_t *res)
46610238Sandreas.hansson@arm.com{
46712063Sgabeblack@google.com    uint8_t *newData = new uint8_t[size];
46810238Sandreas.hansson@arm.com    memcpy(newData, data, size);
46910238Sandreas.hansson@arm.com
47010416Sandreas.hansson@arm.com    const int asid = 0;
47110238Sandreas.hansson@arm.com    const ThreadID tid = 0;
4729227Sandreas.hansson@arm.com    const Addr pc = thread->instAddr();
47310238Sandreas.hansson@arm.com    unsigned block_size = dcachePort.peerBlockSize();
47410416Sandreas.hansson@arm.com    BaseTLB::Mode mode = BaseTLB::Write;
47510416Sandreas.hansson@arm.com
4769227Sandreas.hansson@arm.com    if (traceData) {
4779590Sandreas@sandberg.pp.se        traceData->setAddr(addr);
4789590Sandreas@sandberg.pp.se    }
4799590Sandreas@sandberg.pp.se
48012304Sgabeblack@google.com    RequestPtr req = new Request(asid, addr, size,
48112304Sgabeblack@google.com                                 flags, dataMasterId(), pc, _cpuId, tid);
48212304Sgabeblack@google.com
48312688Sgiacomo.travaglini@arm.com    Addr split_addr = roundDown(addr + size - 1, block_size);
48412688Sgiacomo.travaglini@arm.com    assert(split_addr <= addr || split_addr - addr < block_size);
48512688Sgiacomo.travaglini@arm.com
48613020Sshunhsingou@google.com    _status = DTBWaitResponse;
48712304Sgabeblack@google.com    if (split_addr > addr) {
48812688Sgiacomo.travaglini@arm.com        RequestPtr req1, req2;
48912688Sgiacomo.travaglini@arm.com        assert(!req->isLLSC() && !req->isSwap());
49013020Sshunhsingou@google.com        req->splitOnVaddr(split_addr, req1, req2);
49112304Sgabeblack@google.com
49212304Sgabeblack@google.com        WholeTranslationState *state =
49312304Sgabeblack@google.com            new WholeTranslationState(req, req1, req2, newData, res, mode);
49412304Sgabeblack@google.com        DataTranslation<TimingSimpleCPU *> *trans1 =
49512688Sgiacomo.travaglini@arm.com            new DataTranslation<TimingSimpleCPU *>(this, state, 0);
49612688Sgiacomo.travaglini@arm.com        DataTranslation<TimingSimpleCPU *> *trans2 =
49712688Sgiacomo.travaglini@arm.com            new DataTranslation<TimingSimpleCPU *>(this, state, 1);
49812304Sgabeblack@google.com
4998737Skoansin.tan@gmail.com        thread->dtb->translateTiming(req1, tc, trans1, mode);
50010878Sandreas.hansson@arm.com        thread->dtb->translateTiming(req2, tc, trans2, mode);
50111500Sandreas.hansson@arm.com    } else {
5029420Sandreas.hansson@arm.com        WholeTranslationState *state =
5038737Skoansin.tan@gmail.com            new WholeTranslationState(req, newData, res, mode);
50410106SMitch.Hayenga@arm.com        DataTranslation<TimingSimpleCPU *> *translation =
5058737Skoansin.tan@gmail.com            new DataTranslation<TimingSimpleCPU *>(this, state);
5068737Skoansin.tan@gmail.com        thread->dtb->translateTiming(req, tc, translation, mode);
50710878Sandreas.hansson@arm.com    }
50812563Sgabeblack@google.com
50912563Sgabeblack@google.com    // Translation faults will be returned via finishTranslation()
5108737Skoansin.tan@gmail.com    return NoFault;
5118737Skoansin.tan@gmail.com}
51212563Sgabeblack@google.com
5138737Skoansin.tan@gmail.com
5148737Skoansin.tan@gmail.comvoid
51511294Sandreas.hansson@arm.comTimingSimpleCPU::finishTranslation(WholeTranslationState *state)
5169556Sandreas.hansson@arm.com{
5179556Sandreas.hansson@arm.com    _status = Running;
5189556Sandreas.hansson@arm.com
51911294Sandreas.hansson@arm.com    if (state->getFault() != NoFault) {
52010278SAndreas.Sandberg@ARM.com        if (state->isPrefetch()) {
52110278SAndreas.Sandberg@ARM.com            state->setNoFault();
52210278SAndreas.Sandberg@ARM.com        }
52310278SAndreas.Sandberg@ARM.com        delete [] state->data;
52410278SAndreas.Sandberg@ARM.com        state->deleteReqs();
52510278SAndreas.Sandberg@ARM.com        translationFault(state->getFault());
5269556Sandreas.hansson@arm.com    } else {
5279590Sandreas@sandberg.pp.se        if (!state->isSplit) {
5289590Sandreas@sandberg.pp.se            sendData(state->mainReq, state->data, state->res,
5299420Sandreas.hansson@arm.com                     state->mode == BaseTLB::Read);
5309846Sandreas.hansson@arm.com        } else {
5319846Sandreas.hansson@arm.com            sendSplitData(state->sreqLow, state->sreqHigh, state->mainReq,
5329846Sandreas.hansson@arm.com                          state->data, state->mode == BaseTLB::Read);
5339846Sandreas.hansson@arm.com        }
5348946Sandreas.hansson@arm.com    }
53511811Sbaz21@cam.ac.uk
53611811Sbaz21@cam.ac.uk    delete state;
53711811Sbaz21@cam.ac.uk}
53811811Sbaz21@cam.ac.uk
53912304Sgabeblack@google.com
54012304Sgabeblack@google.comvoid
54112304Sgabeblack@google.comTimingSimpleCPU::fetch()
54212304Sgabeblack@google.com{
54313020Sshunhsingou@google.com    DPRINTF(SimpleCPU, "Fetch\n");
54413020Sshunhsingou@google.com
54512304Sgabeblack@google.com    if (!curStaticInst || !curStaticInst->isDelayedCommit())
54612304Sgabeblack@google.com        checkForInterrupts();
54713020Sshunhsingou@google.com
54813020Sshunhsingou@google.com    checkPcEventQueue();
54912304Sgabeblack@google.com
55012304Sgabeblack@google.com    // We must have just got suspended by a PC event
55113020Sshunhsingou@google.com    if (_status == Idle)
55213020Sshunhsingou@google.com        return;
55312304Sgabeblack@google.com
55412304Sgabeblack@google.com    TheISA::PCState pcState = thread->pcState();
5553918Ssaidi@eecs.umich.edu    bool needToFetch = !isRomMicroPC(pcState.microPC()) && !curMacroStaticInst;
55612563Sgabeblack@google.com
55712563Sgabeblack@google.com    if (needToFetch) {
55812563Sgabeblack@google.com        _status = Running;
55912563Sgabeblack@google.com        Request *ifetch_req = new Request();
5609068SAli.Saidi@ARM.com        ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0);
56112563Sgabeblack@google.com        setupFetchRequest(ifetch_req);
56212563Sgabeblack@google.com        DPRINTF(SimpleCPU, "Translating address %#x\n", ifetch_req->getVaddr());
5639068SAli.Saidi@ARM.com        thread->itb->translateTiming(ifetch_req, tc, &fetchTranslation,
56412563Sgabeblack@google.com                BaseTLB::Execute);
56512563Sgabeblack@google.com    } else {
56612563Sgabeblack@google.com        _status = IcacheWaitResponse;
56712563Sgabeblack@google.com        completeIfetch(NULL);
56812563Sgabeblack@google.com
56912563Sgabeblack@google.com        numCycles += tickToCycles(curTick() - previousTick);
57012563Sgabeblack@google.com        previousTick = curTick();
57112563Sgabeblack@google.com    }
5723918Ssaidi@eecs.umich.edu}
5733918Ssaidi@eecs.umich.edu
5746157Snate@binkert.org
5756157Snate@binkert.orgvoid
5766157Snate@binkert.orgTimingSimpleCPU::sendFetch(Fault fault, RequestPtr req, ThreadContext *tc)
5776157Snate@binkert.org{
5785397Ssaidi@eecs.umich.edu    if (fault == NoFault) {
5795397Ssaidi@eecs.umich.edu        DPRINTF(SimpleCPU, "Sending fetch for addr %#x(pa: %#x)\n",
5806121Snate@binkert.org                req->getVaddr(), req->getPaddr());
5816121Snate@binkert.org        ifetch_pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
5826121Snate@binkert.org        ifetch_pkt->dataStatic(&inst);
5836121Snate@binkert.org        DPRINTF(SimpleCPU, " -- pkt addr: %#x\n", ifetch_pkt->getAddr());
5846121Snate@binkert.org
5856121Snate@binkert.org        if (!icachePort.sendTiming(ifetch_pkt)) {
5865397Ssaidi@eecs.umich.edu            // Need to wait for retry
5871851SN/A            _status = IcacheRetry;
5881851SN/A        } else {
5897739Sgblack@eecs.umich.edu            // Need to wait for cache to respond
590955SN/A            _status = IcacheWaitResponse;
5919396Sandreas.hansson@arm.com            // ownership of packet transferred to memory system
5929396Sandreas.hansson@arm.com            ifetch_pkt = NULL;
5939396Sandreas.hansson@arm.com        }
5949396Sandreas.hansson@arm.com    } else {
5959396Sandreas.hansson@arm.com        DPRINTF(SimpleCPU, "Translation of addr %#x faulted\n", req->getVaddr());
5969396Sandreas.hansson@arm.com        delete req;
59712563Sgabeblack@google.com        // fetch fault: advance directly to next instruction (fault handler)
59812563Sgabeblack@google.com        _status = Running;
59912563Sgabeblack@google.com        advanceInst(fault);
60012563Sgabeblack@google.com    }
6019396Sandreas.hansson@arm.com
6029396Sandreas.hansson@arm.com    numCycles += tickToCycles(curTick() - previousTick);
6039396Sandreas.hansson@arm.com    previousTick = curTick();
6049396Sandreas.hansson@arm.com}
6059396Sandreas.hansson@arm.com
6069396Sandreas.hansson@arm.com
60712563Sgabeblack@google.comvoid
60812563Sgabeblack@google.comTimingSimpleCPU::advanceInst(Fault fault)
60912563Sgabeblack@google.com{
61012563Sgabeblack@google.com
61112563Sgabeblack@google.com    if (_status == Faulting)
6129477Sandreas.hansson@arm.com        return;
6139477Sandreas.hansson@arm.com
6149477Sandreas.hansson@arm.com    if (fault != NoFault) {
6159477Sandreas.hansson@arm.com        advancePC(fault);
6169477Sandreas.hansson@arm.com        DPRINTF(SimpleCPU, "Fault occured, scheduling fetch event\n");
6179477Sandreas.hansson@arm.com        reschedule(fetchEvent, nextCycle(), true);
6189477Sandreas.hansson@arm.com        _status = Faulting;
6199477Sandreas.hansson@arm.com        return;
6209477Sandreas.hansson@arm.com    }
6219477Sandreas.hansson@arm.com
6229477Sandreas.hansson@arm.com
6239477Sandreas.hansson@arm.com    if (!stayAtPC)
6249477Sandreas.hansson@arm.com        advancePC(fault);
6259477Sandreas.hansson@arm.com
62612563Sgabeblack@google.com    if (_status == Running) {
62712563Sgabeblack@google.com        // kick off fetch of next instruction... callback from icache
62812563Sgabeblack@google.com        // response will cause that instruction to be executed,
6299396Sandreas.hansson@arm.com        // keeping the CPU running.
6302667Sstever@eecs.umich.edu        fetch();
63110710Sandreas.hansson@arm.com    }
63210710Sandreas.hansson@arm.com}
63310710Sandreas.hansson@arm.com
63411811Sbaz21@cam.ac.uk
63511811Sbaz21@cam.ac.ukvoid
63611811Sbaz21@cam.ac.ukTimingSimpleCPU::completeIfetch(PacketPtr pkt)
63711811Sbaz21@cam.ac.uk{
63811811Sbaz21@cam.ac.uk    DPRINTF(SimpleCPU, "Complete ICache Fetch for addr %#x\n", pkt ?
63911811Sbaz21@cam.ac.uk            pkt->getAddr() : 0);
64010710Sandreas.hansson@arm.com
64110710Sandreas.hansson@arm.com    // received a response from the icache: execute the received
64210710Sandreas.hansson@arm.com    // instruction
64310710Sandreas.hansson@arm.com
64410384SCurtis.Dunham@arm.com    assert(!pkt || !pkt->isError());
6459986Sandreas@sandberg.pp.se    assert(_status == IcacheWaitResponse);
6469986Sandreas@sandberg.pp.se
6479986Sandreas@sandberg.pp.se    _status = Running;
6489986Sandreas@sandberg.pp.se
6499986Sandreas@sandberg.pp.se    numCycles += tickToCycles(curTick() - previousTick);
6509986Sandreas@sandberg.pp.se    previousTick = curTick();
6519986Sandreas@sandberg.pp.se
6529986Sandreas@sandberg.pp.se    if (getState() == SimObject::Draining) {
6539986Sandreas@sandberg.pp.se        if (pkt) {
6549986Sandreas@sandberg.pp.se            delete pkt->req;
6559986Sandreas@sandberg.pp.se            delete pkt;
6569986Sandreas@sandberg.pp.se        }
6579986Sandreas@sandberg.pp.se
6589986Sandreas@sandberg.pp.se        completeDrain();
6599986Sandreas@sandberg.pp.se        return;
6609986Sandreas@sandberg.pp.se    }
6619986Sandreas@sandberg.pp.se
6629986Sandreas@sandberg.pp.se    preExecute();
6639986Sandreas@sandberg.pp.se    if (curStaticInst && curStaticInst->isMemRef()) {
6649986Sandreas@sandberg.pp.se        // load or store: just send to dcache
6652638Sstever@eecs.umich.edu        Fault fault = curStaticInst->initiateAcc(this, traceData);
6662638Sstever@eecs.umich.edu
6676121Snate@binkert.org        // If we're not running now the instruction will complete in a dcache
6683716Sstever@eecs.umich.edu        // response callback or the instruction faulted and has started an
6695522Snate@binkert.org        // ifetch
6709986Sandreas@sandberg.pp.se        if (_status == Running) {
6719986Sandreas@sandberg.pp.se            if (fault != NoFault && traceData) {
6729986Sandreas@sandberg.pp.se                // If there was a fault, we shouldn't trace this instruction.
6735522Snate@binkert.org                delete traceData;
6745227Ssaidi@eecs.umich.edu                traceData = NULL;
6755227Ssaidi@eecs.umich.edu            }
6765227Ssaidi@eecs.umich.edu
6775227Ssaidi@eecs.umich.edu            postExecute();
6786654Snate@binkert.org            // @todo remove me after debugging with legion done
6796654Snate@binkert.org            if (curStaticInst && (!curStaticInst->isMicroop() ||
6807769SAli.Saidi@ARM.com                        curStaticInst->isFirstMicroop()))
6817769SAli.Saidi@ARM.com                instCnt++;
6827769SAli.Saidi@ARM.com            advanceInst(fault);
6837769SAli.Saidi@ARM.com        }
6845227Ssaidi@eecs.umich.edu    } else if (curStaticInst) {
6855227Ssaidi@eecs.umich.edu        // non-memory instruction: execute completely now
6865227Ssaidi@eecs.umich.edu        Fault fault = curStaticInst->execute(this, traceData);
6875204Sstever@gmail.com
6885204Sstever@gmail.com        // keep an instruction count
6895204Sstever@gmail.com        if (fault == NoFault)
6905204Sstever@gmail.com            countInst();
6915204Sstever@gmail.com        else if (traceData && !DTRACE(ExecFaulting)) {
6925204Sstever@gmail.com            delete traceData;
6935204Sstever@gmail.com            traceData = NULL;
6945204Sstever@gmail.com        }
6955204Sstever@gmail.com
6965204Sstever@gmail.com        postExecute();
6975204Sstever@gmail.com        // @todo remove me after debugging with legion done
6985204Sstever@gmail.com        if (curStaticInst && (!curStaticInst->isMicroop() ||
6995204Sstever@gmail.com                    curStaticInst->isFirstMicroop()))
7005204Sstever@gmail.com            instCnt++;
7015204Sstever@gmail.com        advanceInst(fault);
7025204Sstever@gmail.com    } else {
7035204Sstever@gmail.com        advanceInst(NoFault);
7046121Snate@binkert.org    }
7055204Sstever@gmail.com
7067727SAli.Saidi@ARM.com    if (pkt) {
7077727SAli.Saidi@ARM.com        delete pkt->req;
70812563Sgabeblack@google.com        delete pkt;
7097727SAli.Saidi@ARM.com    }
7107727SAli.Saidi@ARM.com}
71111988Sandreas.sandberg@arm.com
71211988Sandreas.sandberg@arm.comvoid
71310453SAndrew.Bardsley@arm.comTimingSimpleCPU::IcachePort::ITickEvent::process()
71410453SAndrew.Bardsley@arm.com{
71510453SAndrew.Bardsley@arm.com    cpu->completeIfetch(pkt);
71610453SAndrew.Bardsley@arm.com}
71710453SAndrew.Bardsley@arm.com
71810453SAndrew.Bardsley@arm.combool
71910453SAndrew.Bardsley@arm.comTimingSimpleCPU::IcachePort::recvTiming(PacketPtr pkt)
72013715Sandreas.sandberg@arm.com{
72113715Sandreas.sandberg@arm.com    assert(pkt->isResponse());
72213715Sandreas.sandberg@arm.com    if (!pkt->wasNacked()) {
72313715Sandreas.sandberg@arm.com        DPRINTF(SimpleCPU, "Received timing response %#x\n", pkt->getAddr());
72413715Sandreas.sandberg@arm.com        // delay processing of returned data until next CPU clock edge
72513715Sandreas.sandberg@arm.com        Tick next_tick = cpu->nextCycle(curTick());
72613715Sandreas.sandberg@arm.com
72713715Sandreas.sandberg@arm.com        if (next_tick == curTick())
72810453SAndrew.Bardsley@arm.com            cpu->completeIfetch(pkt);
72910453SAndrew.Bardsley@arm.com        else
73013541Sandrea.mondelli@ucf.edu            tickEvent.schedule(pkt, next_tick);
73110453SAndrew.Bardsley@arm.com
73210453SAndrew.Bardsley@arm.com        return true;
73313541Sandrea.mondelli@ucf.edu    } else {
73413541Sandrea.mondelli@ucf.edu        assert(cpu->_status == IcacheWaitResponse);
7359812Sandreas.hansson@arm.com        pkt->reinitNacked();
73610453SAndrew.Bardsley@arm.com        if (!sendTiming(pkt)) {
73710453SAndrew.Bardsley@arm.com            cpu->_status = IcacheRetry;
73810453SAndrew.Bardsley@arm.com            cpu->ifetch_pkt = pkt;
73910453SAndrew.Bardsley@arm.com        }
74010453SAndrew.Bardsley@arm.com    }
74110453SAndrew.Bardsley@arm.com
74210453SAndrew.Bardsley@arm.com    return true;
74310453SAndrew.Bardsley@arm.com}
74410453SAndrew.Bardsley@arm.com
74510453SAndrew.Bardsley@arm.comvoid
74610453SAndrew.Bardsley@arm.comTimingSimpleCPU::IcachePort::recvRetry()
74710453SAndrew.Bardsley@arm.com{
7487727SAli.Saidi@ARM.com    // we shouldn't get a retry unless we have a packet that we're
74910453SAndrew.Bardsley@arm.com    // waiting to transmit
75010453SAndrew.Bardsley@arm.com    assert(cpu->ifetch_pkt != NULL);
75112790Smatteo.fusi@bsc.es    assert(cpu->_status == IcacheRetry);
75212790Smatteo.fusi@bsc.es    PacketPtr tmp = cpu->ifetch_pkt;
75312790Smatteo.fusi@bsc.es    if (sendTiming(tmp)) {
75412790Smatteo.fusi@bsc.es        cpu->_status = IcacheWaitResponse;
75512790Smatteo.fusi@bsc.es        cpu->ifetch_pkt = NULL;
75612790Smatteo.fusi@bsc.es    }
75712790Smatteo.fusi@bsc.es}
75810453SAndrew.Bardsley@arm.com
7593118Sstever@eecs.umich.eduvoid
76010453SAndrew.Bardsley@arm.comTimingSimpleCPU::completeDataAccess(PacketPtr pkt)
76110453SAndrew.Bardsley@arm.com{
76212563Sgabeblack@google.com    // received a response from the dcache: complete the load or store
76310453SAndrew.Bardsley@arm.com    // instruction
7643118Sstever@eecs.umich.edu    assert(!pkt->isError());
7653483Ssaidi@eecs.umich.edu    assert(_status == DcacheWaitResponse || _status == DTBWaitResponse ||
7663494Ssaidi@eecs.umich.edu           pkt->req->getFlags().isSet(Request::NO_ACCESS));
7673494Ssaidi@eecs.umich.edu
76812563Sgabeblack@google.com    numCycles += tickToCycles(curTick() - previousTick);
7693483Ssaidi@eecs.umich.edu    previousTick = curTick();
7703483Ssaidi@eecs.umich.edu
7713053Sstever@eecs.umich.edu    if (pkt->senderState) {
7723053Sstever@eecs.umich.edu        SplitFragmentSenderState * send_state =
7733918Ssaidi@eecs.umich.edu            dynamic_cast<SplitFragmentSenderState *>(pkt->senderState);
77412563Sgabeblack@google.com        assert(send_state);
77512563Sgabeblack@google.com        delete pkt->req;
77612563Sgabeblack@google.com        delete pkt;
7773053Sstever@eecs.umich.edu        PacketPtr big_pkt = send_state->bigPkt;
7783053Sstever@eecs.umich.edu        delete send_state;
7799396Sandreas.hansson@arm.com
7809396Sandreas.hansson@arm.com        SplitMainSenderState * main_send_state =
7819396Sandreas.hansson@arm.com            dynamic_cast<SplitMainSenderState *>(big_pkt->senderState);
7829396Sandreas.hansson@arm.com        assert(main_send_state);
7839396Sandreas.hansson@arm.com        // Record the fact that this packet is no longer outstanding.
7849396Sandreas.hansson@arm.com        assert(main_send_state->outstanding != 0);
7859396Sandreas.hansson@arm.com        main_send_state->outstanding--;
7869396Sandreas.hansson@arm.com
7879396Sandreas.hansson@arm.com        if (main_send_state->outstanding) {
78812920Sgabeblack@google.com            return;
78912920Sgabeblack@google.com        } else {
79012920Sgabeblack@google.com            delete main_send_state;
79112920Sgabeblack@google.com            big_pkt->senderState = NULL;
7929477Sandreas.hansson@arm.com            pkt = big_pkt;
7939396Sandreas.hansson@arm.com        }
79412563Sgabeblack@google.com    }
79512563Sgabeblack@google.com
79612563Sgabeblack@google.com    _status = Running;
79712563Sgabeblack@google.com
7989396Sandreas.hansson@arm.com    Fault fault = curStaticInst->completeAcc(pkt, this, traceData);
7997840Snate@binkert.org
8007865Sgblack@eecs.umich.edu    // keep an instruction count
8017865Sgblack@eecs.umich.edu    if (fault == NoFault)
8027865Sgblack@eecs.umich.edu        countInst();
8037865Sgblack@eecs.umich.edu    else if (traceData) {
8047865Sgblack@eecs.umich.edu        // If there was a fault, we shouldn't trace this instruction.
8057840Snate@binkert.org        delete traceData;
8069900Sandreas@sandberg.pp.se        traceData = NULL;
8079900Sandreas@sandberg.pp.se    }
8089900Sandreas@sandberg.pp.se
8099900Sandreas@sandberg.pp.se    // the locked flag may be cleared on the response packet, so check
81010456SCurtis.Dunham@arm.com    // pkt->req and not pkt to see if it was a load-locked
81110456SCurtis.Dunham@arm.com    if (pkt->isRead() && pkt->req->isLLSC()) {
81210456SCurtis.Dunham@arm.com        TheISA::handleLockedRead(thread, pkt->req);
81310456SCurtis.Dunham@arm.com    }
81410456SCurtis.Dunham@arm.com
81510456SCurtis.Dunham@arm.com    delete pkt->req;
81612563Sgabeblack@google.com    delete pkt;
81712563Sgabeblack@google.com
81812563Sgabeblack@google.com    postExecute();
81912563Sgabeblack@google.com
8209045SAli.Saidi@ARM.com    if (getState() == SimObject::Draining) {
82111235Sandreas.sandberg@arm.com        advancePC(fault);
82211235Sandreas.sandberg@arm.com        completeDrain();
82311235Sandreas.sandberg@arm.com
82411235Sandreas.sandberg@arm.com        return;
82511235Sandreas.sandberg@arm.com    }
82612485Sjang.hanhwi@gmail.com
82712485Sjang.hanhwi@gmail.com    advanceInst(fault);
82812485Sjang.hanhwi@gmail.com}
82911235Sandreas.sandberg@arm.com
83011811Sbaz21@cam.ac.uk
83112485Sjang.hanhwi@gmail.comvoid
83211811Sbaz21@cam.ac.ukTimingSimpleCPU::completeDrain()
83311811Sbaz21@cam.ac.uk{
83411811Sbaz21@cam.ac.uk    DPRINTF(Config, "Done draining\n");
83511235Sandreas.sandberg@arm.com    changeState(SimObject::Drained);
83611235Sandreas.sandberg@arm.com    drainEvent->process();
83711235Sandreas.sandberg@arm.com}
83812563Sgabeblack@google.com
83912563Sgabeblack@google.combool
84012563Sgabeblack@google.comTimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt)
84111235Sandreas.sandberg@arm.com{
8427840Snate@binkert.org    assert(pkt->isResponse());
84312563Sgabeblack@google.com    if (!pkt->wasNacked()) {
8447840Snate@binkert.org        // delay processing of returned data until next CPU clock edge
8451858SN/A        Tick next_tick = cpu->nextCycle(curTick());
8461858SN/A
8471858SN/A        if (next_tick == curTick()) {
84812563Sgabeblack@google.com            cpu->completeDataAccess(pkt);
84912563Sgabeblack@google.com        } else {
8501858SN/A            if (!tickEvent.scheduled()) {
85112230Sgiacomo.travaglini@arm.com                tickEvent.schedule(pkt, next_tick);
85212230Sgiacomo.travaglini@arm.com            } else {
85312230Sgiacomo.travaglini@arm.com                // In the case of a split transaction and a cache that is
85412230Sgiacomo.travaglini@arm.com                // faster than a CPU we could get two responses before
85512563Sgabeblack@google.com                // next_tick expires
85612563Sgabeblack@google.com                if (!retryEvent.scheduled())
85712563Sgabeblack@google.com                    cpu->schedule(retryEvent, next_tick);
85812230Sgiacomo.travaglini@arm.com                return false;
8599903Sandreas.hansson@arm.com            }
8609903Sandreas.hansson@arm.com        }
8619903Sandreas.hansson@arm.com
8629903Sandreas.hansson@arm.com        return true;
86310841Sandreas.sandberg@arm.com    } else  {
8649651SAndreas.Sandberg@ARM.com        assert(cpu->_status == DcacheWaitResponse);
86512563Sgabeblack@google.com        pkt->reinitNacked();
86612563Sgabeblack@google.com        if (!sendTiming(pkt)) {
8679651SAndreas.Sandberg@ARM.com            cpu->_status = DcacheRetry;
86812056Sgabeblack@google.com            cpu->dcache_pkt = pkt;
86912056Sgabeblack@google.com        }
87012056Sgabeblack@google.com    }
87112563Sgabeblack@google.com
87212056Sgabeblack@google.com    return true;
87310841Sandreas.sandberg@arm.com}
87410841Sandreas.sandberg@arm.com
87510841Sandreas.sandberg@arm.comvoid
87610841Sandreas.sandberg@arm.comTimingSimpleCPU::DcachePort::DTickEvent::process()
87710841Sandreas.sandberg@arm.com{
87810841Sandreas.sandberg@arm.com    cpu->completeDataAccess(pkt);
8799651SAndreas.Sandberg@ARM.com}
8809651SAndreas.Sandberg@ARM.com
8819651SAndreas.Sandberg@ARM.comvoid
8829651SAndreas.Sandberg@ARM.comTimingSimpleCPU::DcachePort::recvRetry()
8839651SAndreas.Sandberg@ARM.com{
8849651SAndreas.Sandberg@ARM.com    // we shouldn't get a retry unless we have a packet that we're
88512563Sgabeblack@google.com    // waiting to transmit
8869651SAndreas.Sandberg@ARM.com    assert(cpu->dcache_pkt != NULL);
8879651SAndreas.Sandberg@ARM.com    assert(cpu->_status == DcacheRetry);
88810841Sandreas.sandberg@arm.com    PacketPtr tmp = cpu->dcache_pkt;
88912563Sgabeblack@google.com    if (tmp->senderState) {
89012563Sgabeblack@google.com        // This is a packet from a split access.
89110841Sandreas.sandberg@arm.com        SplitFragmentSenderState * send_state =
89210841Sandreas.sandberg@arm.com            dynamic_cast<SplitFragmentSenderState *>(tmp->senderState);
89310841Sandreas.sandberg@arm.com        assert(send_state);
89410860Sandreas.sandberg@arm.com        PacketPtr big_pkt = send_state->bigPkt;
89510841Sandreas.sandberg@arm.com
89610841Sandreas.sandberg@arm.com        SplitMainSenderState * main_send_state =
89710841Sandreas.sandberg@arm.com            dynamic_cast<SplitMainSenderState *>(big_pkt->senderState);
89810841Sandreas.sandberg@arm.com        assert(main_send_state);
89910841Sandreas.sandberg@arm.com
90012563Sgabeblack@google.com        if (sendTiming(tmp)) {
90110841Sandreas.sandberg@arm.com            // If we were able to send without retrying, record that fact
90210841Sandreas.sandberg@arm.com            // and try sending the other fragment.
90310841Sandreas.sandberg@arm.com            send_state->clearFromParent();
90410841Sandreas.sandberg@arm.com            int other_index = main_send_state->getPendingFragment();
90510841Sandreas.sandberg@arm.com            if (other_index > 0) {
9069651SAndreas.Sandberg@ARM.com                tmp = main_send_state->fragments[other_index];
9079651SAndreas.Sandberg@ARM.com                cpu->dcache_pkt = tmp;
9089986Sandreas@sandberg.pp.se                if ((big_pkt->isRead() && cpu->handleReadPacket(tmp)) ||
9099986Sandreas@sandberg.pp.se                        (big_pkt->isWrite() && cpu->handleWritePacket())) {
9109986Sandreas@sandberg.pp.se                    main_send_state->fragments[other_index] = NULL;
9119986Sandreas@sandberg.pp.se                }
9129986Sandreas@sandberg.pp.se            } else {
9139986Sandreas@sandberg.pp.se                cpu->_status = DcacheWaitResponse;
9145863Snate@binkert.org                // memory system takes ownership of packet
9155863Snate@binkert.org                cpu->dcache_pkt = NULL;
9165863Snate@binkert.org            }
9175863Snate@binkert.org        }
9186121Snate@binkert.org    } else if (sendTiming(tmp)) {
9191858SN/A        cpu->_status = DcacheWaitResponse;
9205863Snate@binkert.org        // memory system takes ownership of packet
9215863Snate@binkert.org        cpu->dcache_pkt = NULL;
9225863Snate@binkert.org    }
9235863Snate@binkert.org}
9245863Snate@binkert.org
9252139SN/ATimingSimpleCPU::IprEvent::IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu,
9264202Sbinkertn@umich.edu    Tick t)
92711308Santhony.gutierrez@amd.com    : pkt(_pkt), cpu(_cpu)
9284202Sbinkertn@umich.edu{
92911308Santhony.gutierrez@amd.com    cpu->schedule(this, t);
9302139SN/A}
9316994Snate@binkert.org
9326994Snate@binkert.orgvoid
9336994Snate@binkert.orgTimingSimpleCPU::IprEvent::process()
9346994Snate@binkert.org{
9356994Snate@binkert.org    cpu->completeDataAccess(pkt);
9366994Snate@binkert.org}
9376994Snate@binkert.org
9386994Snate@binkert.orgconst char *
93910319SAndreas.Sandberg@ARM.comTimingSimpleCPU::IprEvent::description() const
9406994Snate@binkert.org{
9416994Snate@binkert.org    return "Timing Simple CPU Delay IPR event";
9426994Snate@binkert.org}
9436994Snate@binkert.org
9446994Snate@binkert.org
9456994Snate@binkert.orgvoid
9466994Snate@binkert.orgTimingSimpleCPU::printAddr(Addr a)
9476994Snate@binkert.org{
9486994Snate@binkert.org    dcachePort.printAddr(a);
9496994Snate@binkert.org}
9506994Snate@binkert.org
9512155SN/A
9525863Snate@binkert.org////////////////////////////////////////////////////////////////////////
9531869SN/A//
9541869SN/A//  TimingSimpleCPU Simulation Object
9555863Snate@binkert.org//
9565863Snate@binkert.orgTimingSimpleCPU *
9574202Sbinkertn@umich.eduTimingSimpleCPUParams::create()
9586108Snate@binkert.org{
9596108Snate@binkert.org    numThreads = 1;
9606108Snate@binkert.org    if (!FullSystem && workload.size() != 1)
9616108Snate@binkert.org        panic("only one workload allowed");
9629219Spower.jg@gmail.com    return new TimingSimpleCPU(this);
9639219Spower.jg@gmail.com}
9649219Spower.jg@gmail.com