timing.cc revision 5894
12623SN/A/*
210596Sgabeblack@google.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
312276Sanouk.vanlaer@arm.com * All rights reserved.
47725SAli.Saidi@ARM.com *
57725SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
67725SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
77725SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
87725SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
97725SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
107725SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
117725SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
127725SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
137725SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
147725SAli.Saidi@ARM.com * this software without specific prior written permission.
152623SN/A *
162623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272623SN/A *
282623SN/A * Authors: Steve Reinhardt
292623SN/A */
302623SN/A
312623SN/A#include "arch/locked_mem.hh"
322623SN/A#include "arch/mmaped_ipr.hh"
332623SN/A#include "arch/utility.hh"
342623SN/A#include "base/bigint.hh"
352623SN/A#include "cpu/exetrace.hh"
362623SN/A#include "cpu/simple/timing.hh"
372623SN/A#include "mem/packet.hh"
382623SN/A#include "mem/packet_access.hh"
392623SN/A#include "params/TimingSimpleCPU.hh"
402665Ssaidi@eecs.umich.edu#include "sim/system.hh"
412665Ssaidi@eecs.umich.edu
422623SN/Ausing namespace std;
432623SN/Ausing namespace TheISA;
4411793Sbrandon.potter@amd.com
4511793Sbrandon.potter@amd.comPort *
463170Sstever@eecs.umich.eduTimingSimpleCPU::getPort(const std::string &if_name, int idx)
478105Sgblack@eecs.umich.edu{
482623SN/A    if (if_name == "dcache_port")
496658Snate@binkert.org        return &dcachePort;
502623SN/A    else if (if_name == "icache_port")
518232Snate@binkert.org        return &icachePort;
529152Satgutier@umich.edu    else
538232Snate@binkert.org        panic("No Such Port\n");
5411793Sbrandon.potter@amd.com}
558232Snate@binkert.org
563348Sbinkertn@umich.eduvoid
573348Sbinkertn@umich.eduTimingSimpleCPU::init()
584762Snate@binkert.org{
597678Sgblack@eecs.umich.edu    BaseCPU::init();
608779Sgblack@eecs.umich.edu#if FULL_SYSTEM
612901Ssaidi@eecs.umich.edu    for (int i = 0; i < threadContexts.size(); ++i) {
622623SN/A        ThreadContext *tc = threadContexts[i];
632623SN/A
642623SN/A        // initialize CPU, including PC
652623SN/A        TheISA::initCPU(tc, _cpuId);
662623SN/A    }
672623SN/A#endif
682623SN/A}
6911147Smitch.hayenga@arm.com
702623SN/ATick
712623SN/ATimingSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt)
722623SN/A{
738707Sandreas.hansson@arm.com    panic("TimingSimpleCPU doesn't expect recvAtomic callback!");
742948Ssaidi@eecs.umich.edu    return curTick;
752948Ssaidi@eecs.umich.edu}
765606Snate@binkert.org
772948Ssaidi@eecs.umich.eduvoid
782948Ssaidi@eecs.umich.eduTimingSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt)
795529Snate@binkert.org{
808707Sandreas.hansson@arm.com    //No internal storage to update, jusst return
819179Sandreas.hansson@arm.com    return;
8212085Sspwilson2@wisc.edu}
832623SN/A
842623SN/Avoid
852623SN/ATimingSimpleCPU::CpuPort::recvStatusChange(Status status)
862623SN/A{
872623SN/A    if (status == RangeChange) {
8810030SAli.Saidi@ARM.com        if (!snoopRangeSent) {
892623SN/A            snoopRangeSent = true;
902623SN/A            sendStatusChange(Port::RangeChange);
912623SN/A        }
922623SN/A        return;
9310913Sandreas.sandberg@arm.com    }
9410913Sandreas.sandberg@arm.com
952798Sktlim@umich.edu    panic("TimingSimpleCPU doesn't expect recvStatusChange callback!");
9612276Sanouk.vanlaer@arm.com}
9712276Sanouk.vanlaer@arm.com
9812276Sanouk.vanlaer@arm.com
999448SAndreas.Sandberg@ARM.comvoid
10010913Sandreas.sandberg@arm.comTimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t)
1019448SAndreas.Sandberg@ARM.com{
1029342SAndreas.Sandberg@arm.com    pkt = _pkt;
1039448SAndreas.Sandberg@ARM.com    cpu->schedule(this, t);
1049442SAndreas.Sandberg@ARM.com}
10511147Smitch.hayenga@arm.com
10610913Sandreas.sandberg@arm.comTimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p)
1072798Sktlim@umich.edu    : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this, p->clock),
10811147Smitch.hayenga@arm.com    dcachePort(this, p->clock), fetchEvent(this)
1099442SAndreas.Sandberg@ARM.com{
1109442SAndreas.Sandberg@ARM.com    _status = Idle;
1119442SAndreas.Sandberg@ARM.com
1129442SAndreas.Sandberg@ARM.com    icachePort.snoopRangeSent = false;
1139448SAndreas.Sandberg@ARM.com    dcachePort.snoopRangeSent = false;
1149648Sdam.sunwoo@arm.com
1159442SAndreas.Sandberg@ARM.com    ifetch_pkt = dcache_pkt = NULL;
11610913Sandreas.sandberg@arm.com    drainEvent = NULL;
1172798Sktlim@umich.edu    previousTick = 0;
1182623SN/A    changeState(SimObject::Running);
1192623SN/A}
1202623SN/A
1219342SAndreas.Sandberg@arm.com
1222623SN/ATimingSimpleCPU::~TimingSimpleCPU()
1239442SAndreas.Sandberg@ARM.com{
1249448SAndreas.Sandberg@ARM.com}
1259448SAndreas.Sandberg@ARM.com
1269442SAndreas.Sandberg@ARM.comvoid
1275221Ssaidi@eecs.umich.eduTimingSimpleCPU::serialize(ostream &os)
1289523SAndreas.Sandberg@ARM.com{
1293201Shsul@eecs.umich.edu    SimObject::State so_state = SimObject::getState();
1309448SAndreas.Sandberg@ARM.com    SERIALIZE_ENUM(so_state);
1319448SAndreas.Sandberg@ARM.com    BaseSimpleCPU::serialize(os);
13211147Smitch.hayenga@arm.com}
13311147Smitch.hayenga@arm.com
13411147Smitch.hayenga@arm.comvoid
13511147Smitch.hayenga@arm.comTimingSimpleCPU::unserialize(Checkpoint *cp, const string &section)
13611147Smitch.hayenga@arm.com{
13711147Smitch.hayenga@arm.com    SimObject::State so_state;
13811147Smitch.hayenga@arm.com    UNSERIALIZE_ENUM(so_state);
13911147Smitch.hayenga@arm.com    BaseSimpleCPU::unserialize(cp, section);
14011147Smitch.hayenga@arm.com}
14111147Smitch.hayenga@arm.com
14211147Smitch.hayenga@arm.comunsigned int
14311147Smitch.hayenga@arm.comTimingSimpleCPU::drain(Event *drain_event)
14411147Smitch.hayenga@arm.com{
14511147Smitch.hayenga@arm.com    // TimingSimpleCPU is ready to drain if it's not waiting for
14611147Smitch.hayenga@arm.com    // an access to complete.
14711147Smitch.hayenga@arm.com    if (_status == Idle || _status == Running || _status == SwitchedOut) {
14811147Smitch.hayenga@arm.com        changeState(SimObject::Drained);
1492623SN/A        return 0;
15011147Smitch.hayenga@arm.com    } else {
15112276Sanouk.vanlaer@arm.com        changeState(SimObject::Draining);
15212276Sanouk.vanlaer@arm.com        drainEvent = drain_event;
15312276Sanouk.vanlaer@arm.com        return 1;
15411147Smitch.hayenga@arm.com    }
1559442SAndreas.Sandberg@ARM.com}
1562798Sktlim@umich.edu
1579442SAndreas.Sandberg@ARM.comvoid
1589442SAndreas.Sandberg@ARM.comTimingSimpleCPU::resume()
1599442SAndreas.Sandberg@ARM.com{
16010913Sandreas.sandberg@arm.com    DPRINTF(SimpleCPU, "Resume\n");
1619442SAndreas.Sandberg@ARM.com    if (_status != SwitchedOut && _status != Idle) {
1629442SAndreas.Sandberg@ARM.com        assert(system->getMemoryMode() == Enums::timing);
16311147Smitch.hayenga@arm.com
1649442SAndreas.Sandberg@ARM.com        if (fetchEvent.scheduled())
1659442SAndreas.Sandberg@ARM.com           deschedule(fetchEvent);
1669442SAndreas.Sandberg@ARM.com
1679442SAndreas.Sandberg@ARM.com        schedule(fetchEvent, nextCycle());
16810913Sandreas.sandberg@arm.com    }
1699442SAndreas.Sandberg@ARM.com
1709442SAndreas.Sandberg@ARM.com    changeState(SimObject::Running);
1712798Sktlim@umich.edu}
1722798Sktlim@umich.edu
1732798Sktlim@umich.eduvoid
1742798Sktlim@umich.eduTimingSimpleCPU::switchOut()
1752798Sktlim@umich.edu{
17611147Smitch.hayenga@arm.com    assert(_status == Running || _status == Idle);
17711147Smitch.hayenga@arm.com    _status = SwitchedOut;
17811147Smitch.hayenga@arm.com    numCycles += tickToCycles(curTick - previousTick);
1799429SAndreas.Sandberg@ARM.com
1809429SAndreas.Sandberg@ARM.com    // If we've been scheduled to resume but are then told to switch out,
1819442SAndreas.Sandberg@ARM.com    // we'll need to cancel it.
1829342SAndreas.Sandberg@arm.com    if (fetchEvent.scheduled())
18311147Smitch.hayenga@arm.com        deschedule(fetchEvent);
18411147Smitch.hayenga@arm.com}
1859442SAndreas.Sandberg@ARM.com
18610464SAndreas.Sandberg@ARM.com
18712284Sjose.marinho@arm.comvoid
1882623SN/ATimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
1892623SN/A{
1902623SN/A    BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort);
1912623SN/A
1922623SN/A    // if any of this CPU's ThreadContexts are active, mark the CPU as
1932623SN/A    // running and schedule its tick event.
1949429SAndreas.Sandberg@ARM.com    for (int i = 0; i < threadContexts.size(); ++i) {
1952623SN/A        ThreadContext *tc = threadContexts[i];
1969179Sandreas.hansson@arm.com        if (tc->status() == ThreadContext::Active && _status != Running) {
1972623SN/A            _status = Running;
1982623SN/A            break;
1999523SAndreas.Sandberg@ARM.com        }
2009523SAndreas.Sandberg@ARM.com    }
2019523SAndreas.Sandberg@ARM.com
2029524SAndreas.Sandberg@ARM.com    if (_status != Running) {
2039523SAndreas.Sandberg@ARM.com        _status = Idle;
2049523SAndreas.Sandberg@ARM.com    }
2059523SAndreas.Sandberg@ARM.com    assert(threadContexts.size() == 1);
2069523SAndreas.Sandberg@ARM.com    previousTick = curTick;
2072623SN/A}
2082623SN/A
20910407Smitch.hayenga@arm.com
2102623SN/Avoid
21110407Smitch.hayenga@arm.comTimingSimpleCPU::activateContext(int thread_num, int delay)
2125221Ssaidi@eecs.umich.edu{
21311147Smitch.hayenga@arm.com    DPRINTF(SimpleCPU, "ActivateContext %d (%d cycles)\n", thread_num, delay);
2142623SN/A
21511147Smitch.hayenga@arm.com    assert(thread_num == 0);
21611147Smitch.hayenga@arm.com    assert(thread);
21711147Smitch.hayenga@arm.com
2183686Sktlim@umich.edu    assert(_status == Idle);
2192623SN/A
22011147Smitch.hayenga@arm.com    notIdleFraction++;
22111147Smitch.hayenga@arm.com    _status = Running;
22211147Smitch.hayenga@arm.com
22311147Smitch.hayenga@arm.com    // kick things off by initiating the fetch of the next instruction
22411147Smitch.hayenga@arm.com    schedule(fetchEvent, nextCycle(curTick + ticks(delay)));
22511147Smitch.hayenga@arm.com}
22611147Smitch.hayenga@arm.com
22711526Sdavid.guillen@arm.com
22811526Sdavid.guillen@arm.comvoid
2292623SN/ATimingSimpleCPU::suspendContext(int thread_num)
2302623SN/A{
2312623SN/A    DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
2322623SN/A
2338737Skoansin.tan@gmail.com    assert(thread_num == 0);
2342623SN/A    assert(thread);
2355221Ssaidi@eecs.umich.edu
2365221Ssaidi@eecs.umich.edu    assert(_status == Running);
23711147Smitch.hayenga@arm.com
23811147Smitch.hayenga@arm.com    // just change status to Idle... if status != Running,
2392623SN/A    // completeInst() will not initiate fetch of next instruction.
2406043Sgblack@eecs.umich.edu
2416043Sgblack@eecs.umich.edu    notIdleFraction--;
2426043Sgblack@eecs.umich.edu    _status = Idle;
2439342SAndreas.Sandberg@arm.com}
2442623SN/A
24511147Smitch.hayenga@arm.combool
2462623SN/ATimingSimpleCPU::handleReadPacket(PacketPtr pkt)
24711147Smitch.hayenga@arm.com{
24811147Smitch.hayenga@arm.com    RequestPtr req = pkt->req;
24911147Smitch.hayenga@arm.com    if (req->isMmapedIpr()) {
25011147Smitch.hayenga@arm.com        Tick delay;
25111147Smitch.hayenga@arm.com        delay = TheISA::handleIprRead(thread->getTC(), pkt);
25211147Smitch.hayenga@arm.com        new IprEvent(pkt, this, nextCycle(curTick + delay));
25311147Smitch.hayenga@arm.com        _status = DcacheWaitResponse;
25411526Sdavid.guillen@arm.com        dcache_pkt = NULL;
25511526Sdavid.guillen@arm.com    } else if (!dcachePort.sendTiming(pkt)) {
2562623SN/A        _status = DcacheRetry;
2572623SN/A        dcache_pkt = pkt;
2585728Sgblack@eecs.umich.edu    } else {
2595728Sgblack@eecs.umich.edu        _status = DcacheWaitResponse;
2605728Sgblack@eecs.umich.edu        // memory system takes ownership of packet
26111147Smitch.hayenga@arm.com        dcache_pkt = NULL;
26211147Smitch.hayenga@arm.com    }
26311147Smitch.hayenga@arm.com    return dcache_pkt == NULL;
26412749Sgiacomo.travaglini@arm.com}
26510533Sali.saidi@arm.com
26610533Sali.saidi@arm.comvoid
26710533Sali.saidi@arm.comTimingSimpleCPU::sendData(Fault fault, RequestPtr req,
26810533Sali.saidi@arm.com        uint8_t *data, uint64_t *res, bool read)
26910533Sali.saidi@arm.com{
27010533Sali.saidi@arm.com    _status = Running;
2718105Sgblack@eecs.umich.edu    if (fault != NoFault) {
2729180Sandreas.hansson@arm.com        delete data;
2739179Sandreas.hansson@arm.com        delete req;
2745728Sgblack@eecs.umich.edu
2755728Sgblack@eecs.umich.edu        translationFault(fault);
2768975Sandreas.hansson@arm.com        return;
2775728Sgblack@eecs.umich.edu    }
2785728Sgblack@eecs.umich.edu    PacketPtr pkt;
2795728Sgblack@eecs.umich.edu    buildPacket(pkt, req, read);
2805728Sgblack@eecs.umich.edu    pkt->dataDynamic<uint8_t>(data);
2815728Sgblack@eecs.umich.edu    if (req->getFlags().isSet(Request::NO_ACCESS)) {
2825728Sgblack@eecs.umich.edu        assert(!dcache_pkt);
2835728Sgblack@eecs.umich.edu        pkt->makeResponse();
2845728Sgblack@eecs.umich.edu        completeDataAccess(pkt);
2855728Sgblack@eecs.umich.edu    } else if (read) {
2862623SN/A        handleReadPacket(pkt);
2875894Sgblack@eecs.umich.edu    } else {
28812749Sgiacomo.travaglini@arm.com        bool do_access = true;  // flag to suppress cache access
2896973Stjones1@inf.ed.ac.uk
2905744Sgblack@eecs.umich.edu        if (req->isLocked()) {
29111147Smitch.hayenga@arm.com            do_access = TheISA::handleLockedWrite(thread, req);
29211147Smitch.hayenga@arm.com        } else if (req->isCondSwap()) {
29311147Smitch.hayenga@arm.com            assert(res);
29410653Sandreas.hansson@arm.com            req->setExtraData(*res);
29510566Sandreas.hansson@arm.com        }
2965894Sgblack@eecs.umich.edu
2975894Sgblack@eecs.umich.edu        if (do_access) {
2985894Sgblack@eecs.umich.edu            dcache_pkt = pkt;
2995894Sgblack@eecs.umich.edu            handleWritePacket();
3005894Sgblack@eecs.umich.edu        } else {
3015894Sgblack@eecs.umich.edu            _status = DcacheWaitResponse;
3025894Sgblack@eecs.umich.edu            completeDataAccess(pkt);
3035894Sgblack@eecs.umich.edu        }
3045894Sgblack@eecs.umich.edu    }
3056102Sgblack@eecs.umich.edu}
30610030SAli.Saidi@ARM.com
3075894Sgblack@eecs.umich.eduvoid
3085894Sgblack@eecs.umich.eduTimingSimpleCPU::sendSplitData(Fault fault1, Fault fault2,
3095894Sgblack@eecs.umich.edu        RequestPtr req1, RequestPtr req2, RequestPtr req,
3105894Sgblack@eecs.umich.edu        uint8_t *data, bool read)
3115894Sgblack@eecs.umich.edu{
3125894Sgblack@eecs.umich.edu    _status = Running;
3135894Sgblack@eecs.umich.edu    if (fault1 != NoFault || fault2 != NoFault) {
3145894Sgblack@eecs.umich.edu        delete data;
31511148Smitch.hayenga@arm.com        delete req1;
3165894Sgblack@eecs.umich.edu        delete req2;
3175894Sgblack@eecs.umich.edu        if (fault1 != NoFault)
3185894Sgblack@eecs.umich.edu            translationFault(fault1);
3195894Sgblack@eecs.umich.edu        else if (fault2 != NoFault)
3205894Sgblack@eecs.umich.edu            translationFault(fault2);
3215894Sgblack@eecs.umich.edu        return;
3225894Sgblack@eecs.umich.edu    }
3235894Sgblack@eecs.umich.edu    PacketPtr pkt1, pkt2;
32412749Sgiacomo.travaglini@arm.com    buildSplitPacket(pkt1, pkt2, req1, req2, req, data, read);
32512749Sgiacomo.travaglini@arm.com    if (req->getFlags().isSet(Request::NO_ACCESS)) {
3265894Sgblack@eecs.umich.edu        assert(!dcache_pkt);
3275894Sgblack@eecs.umich.edu        pkt1->makeResponse();
3285894Sgblack@eecs.umich.edu        completeDataAccess(pkt1);
3295894Sgblack@eecs.umich.edu    } else if (read) {
3305894Sgblack@eecs.umich.edu        if (handleReadPacket(pkt1)) {
3315894Sgblack@eecs.umich.edu            SplitFragmentSenderState * send_state =
3325894Sgblack@eecs.umich.edu                dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState);
3335894Sgblack@eecs.umich.edu            send_state->clearFromParent();
3347911Shestness@cs.utexas.edu            if (handleReadPacket(pkt2)) {
3357911Shestness@cs.utexas.edu                send_state = dynamic_cast<SplitFragmentSenderState *>(
3365894Sgblack@eecs.umich.edu                        pkt1->senderState);
3375894Sgblack@eecs.umich.edu                send_state->clearFromParent();
3387911Shestness@cs.utexas.edu            }
3397911Shestness@cs.utexas.edu        }
3405894Sgblack@eecs.umich.edu    } else {
3415894Sgblack@eecs.umich.edu        dcache_pkt = pkt1;
3425894Sgblack@eecs.umich.edu        if (handleWritePacket()) {
3435894Sgblack@eecs.umich.edu            SplitFragmentSenderState * send_state =
3445894Sgblack@eecs.umich.edu                dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState);
3455894Sgblack@eecs.umich.edu            send_state->clearFromParent();
3467911Shestness@cs.utexas.edu            dcache_pkt = pkt2;
3477911Shestness@cs.utexas.edu            if (handleWritePacket()) {
3485894Sgblack@eecs.umich.edu                send_state = dynamic_cast<SplitFragmentSenderState *>(
3495894Sgblack@eecs.umich.edu                        pkt1->senderState);
3505894Sgblack@eecs.umich.edu                send_state->clearFromParent();
3517911Shestness@cs.utexas.edu            }
3527911Shestness@cs.utexas.edu        }
3535894Sgblack@eecs.umich.edu    }
3545894Sgblack@eecs.umich.edu}
3555894Sgblack@eecs.umich.edu
3565894Sgblack@eecs.umich.eduvoid
3575894Sgblack@eecs.umich.eduTimingSimpleCPU::translationFault(Fault fault)
3585894Sgblack@eecs.umich.edu{
3595894Sgblack@eecs.umich.edu    numCycles += tickToCycles(curTick - previousTick);
3605894Sgblack@eecs.umich.edu    previousTick = curTick;
36110379Sandreas.hansson@arm.com
3625894Sgblack@eecs.umich.edu    if (traceData) {
3636739Sgblack@eecs.umich.edu        // Since there was a fault, we shouldn't trace this instruction.
3646739Sgblack@eecs.umich.edu        delete traceData;
36510464SAndreas.Sandberg@ARM.com        traceData = NULL;
36612284Sjose.marinho@arm.com    }
3675894Sgblack@eecs.umich.edu
3685894Sgblack@eecs.umich.edu    postExecute();
3695894Sgblack@eecs.umich.edu
3705894Sgblack@eecs.umich.edu    if (getState() == SimObject::Draining) {
3715894Sgblack@eecs.umich.edu        advancePC(fault);
3725744Sgblack@eecs.umich.edu        completeDrain();
3735744Sgblack@eecs.umich.edu    } else {
3745894Sgblack@eecs.umich.edu        advanceInst(fault);
3755894Sgblack@eecs.umich.edu    }
3769442SAndreas.Sandberg@ARM.com}
3775894Sgblack@eecs.umich.edu
3785894Sgblack@eecs.umich.eduvoid
37910653Sandreas.hansson@arm.comTimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr req, bool read)
38012749Sgiacomo.travaglini@arm.com{
3815894Sgblack@eecs.umich.edu    MemCmd cmd;
38210653Sandreas.hansson@arm.com    if (read) {
3835894Sgblack@eecs.umich.edu        cmd = MemCmd::ReadReq;
3845894Sgblack@eecs.umich.edu        if (req->isLocked())
3855894Sgblack@eecs.umich.edu            cmd = MemCmd::LoadLockedReq;
3865894Sgblack@eecs.umich.edu    } else {
38712749Sgiacomo.travaglini@arm.com        cmd = MemCmd::WriteReq;
3885894Sgblack@eecs.umich.edu        if (req->isLocked()) {
3895894Sgblack@eecs.umich.edu            cmd = MemCmd::StoreCondReq;
3905894Sgblack@eecs.umich.edu        } else if (req->isSwap()) {
3915894Sgblack@eecs.umich.edu            cmd = MemCmd::SwapReq;
3928105Sgblack@eecs.umich.edu        }
3935744Sgblack@eecs.umich.edu    }
3945894Sgblack@eecs.umich.edu    pkt = new Packet(req, cmd, Packet::Broadcast);
39510653Sandreas.hansson@arm.com}
3965894Sgblack@eecs.umich.edu
3975894Sgblack@eecs.umich.eduvoid
3985894Sgblack@eecs.umich.eduTimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
39910653Sandreas.hansson@arm.com        RequestPtr req1, RequestPtr req2, RequestPtr req,
40010653Sandreas.hansson@arm.com        uint8_t *data, bool read)
4015894Sgblack@eecs.umich.edu{
4028949Sandreas.hansson@arm.com    pkt1 = pkt2 = NULL;
4035744Sgblack@eecs.umich.edu
40410566Sandreas.hansson@arm.com    assert(!req1->isMmapedIpr() && !req2->isMmapedIpr());
4055744Sgblack@eecs.umich.edu
4065744Sgblack@eecs.umich.edu    if (req->getFlags().isSet(Request::NO_ACCESS)) {
4075744Sgblack@eecs.umich.edu        buildPacket(pkt1, req, read);
4085744Sgblack@eecs.umich.edu        return;
4095744Sgblack@eecs.umich.edu    }
4105744Sgblack@eecs.umich.edu
4115744Sgblack@eecs.umich.edu    buildPacket(pkt1, req1, read);
4125744Sgblack@eecs.umich.edu    buildPacket(pkt2, req2, read);
4135744Sgblack@eecs.umich.edu
4145744Sgblack@eecs.umich.edu    req->setPhys(req1->getPaddr(), req->getSize(), req1->getFlags());
4155744Sgblack@eecs.umich.edu    PacketPtr pkt = new Packet(req, pkt1->cmd.responseCommand(),
4165744Sgblack@eecs.umich.edu                               Packet::Broadcast);
4172623SN/A
4188444Sgblack@eecs.umich.edu    pkt->dataDynamic<uint8_t>(data);
41911608Snikos.nikoleris@arm.com    pkt1->dataStatic<uint8_t>(data);
4202623SN/A    pkt2->dataStatic<uint8_t>(data + req1->getSize());
42111303Ssteve.reinhardt@amd.com
42211303Ssteve.reinhardt@amd.com    SplitMainSenderState * main_send_state = new SplitMainSenderState;
42311303Ssteve.reinhardt@amd.com    pkt->senderState = main_send_state;
42411303Ssteve.reinhardt@amd.com    main_send_state->fragments[0] = pkt1;
42511303Ssteve.reinhardt@amd.com    main_send_state->fragments[1] = pkt2;
42611608Snikos.nikoleris@arm.com    main_send_state->outstanding = 2;
42711608Snikos.nikoleris@arm.com    pkt1->senderState = new SplitFragmentSenderState(pkt, 0);
42811303Ssteve.reinhardt@amd.com    pkt2->senderState = new SplitFragmentSenderState(pkt, 1);
42911147Smitch.hayenga@arm.com}
43011147Smitch.hayenga@arm.com
43111147Smitch.hayenga@arm.comtemplate <class T>
4325728Sgblack@eecs.umich.eduFault
4335728Sgblack@eecs.umich.eduTimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
4347720Sgblack@eecs.umich.edu{
4359814Sandreas.hansson@arm.com    Fault fault;
4366973Stjones1@inf.ed.ac.uk    const int asid = 0;
4372623SN/A    const int thread_id = 0;
43810665SAli.Saidi@ARM.com    const Addr pc = thread->readPC();
43910665SAli.Saidi@ARM.com    int block_size = dcachePort.peerBlockSize();
4407045Ssteve.reinhardt@amd.com    int data_size = sizeof(T);
44112749Sgiacomo.travaglini@arm.com
44212749Sgiacomo.travaglini@arm.com    RequestPtr req  = new Request(asid, addr, data_size,
44312749Sgiacomo.travaglini@arm.com                                  flags, pc, _cpuId, thread_id);
4445728Sgblack@eecs.umich.edu
44510024Sdam.sunwoo@arm.com    Addr split_addr = roundDown(addr + data_size - 1, block_size);
44610024Sdam.sunwoo@arm.com    assert(split_addr <= addr || split_addr - addr < block_size);
4477520Sgblack@eecs.umich.edu
4485744Sgblack@eecs.umich.edu
4495728Sgblack@eecs.umich.edu    _status = DTBWaitResponse;
4505894Sgblack@eecs.umich.edu    if (split_addr > addr) {
4515744Sgblack@eecs.umich.edu        RequestPtr req1, req2;
4525894Sgblack@eecs.umich.edu        assert(!req->isLocked() && !req->isSwap());
4536102Sgblack@eecs.umich.edu        req->splitOnVaddr(split_addr, req1, req2);
4545894Sgblack@eecs.umich.edu
4555894Sgblack@eecs.umich.edu        typedef SplitDataTranslation::WholeTranslationState WholeState;
4566973Stjones1@inf.ed.ac.uk        WholeState *state = new WholeState(req1, req2, req,
4577520Sgblack@eecs.umich.edu                (uint8_t *)(new T), true);
4586973Stjones1@inf.ed.ac.uk        thread->dtb->translateTiming(req1, tc,
4598486Sgblack@eecs.umich.edu                new SplitDataTranslation(this, 0, state), false);
4608486Sgblack@eecs.umich.edu        thread->dtb->translateTiming(req2, tc,
4618486Sgblack@eecs.umich.edu                new SplitDataTranslation(this, 1, state), false);
4628486Sgblack@eecs.umich.edu    } else {
4636973Stjones1@inf.ed.ac.uk        thread->dtb->translateTiming(req, tc,
46411147Smitch.hayenga@arm.com                new DataTranslation(this, (uint8_t *)(new T), NULL, true),
46511147Smitch.hayenga@arm.com                false);
4665744Sgblack@eecs.umich.edu    }
4676973Stjones1@inf.ed.ac.uk
4687520Sgblack@eecs.umich.edu    if (traceData) {
4698486Sgblack@eecs.umich.edu        traceData->setData(data);
4708486Sgblack@eecs.umich.edu        traceData->setAddr(addr);
47111147Smitch.hayenga@arm.com    }
4722623SN/A
4732623SN/A    // This will need a new way to tell if it has a dcache attached.
4745728Sgblack@eecs.umich.edu    if (req->isUncacheable())
4752623SN/A        recordEvent("Uncached Read");
4762623SN/A
4775728Sgblack@eecs.umich.edu    return NoFault;
4785728Sgblack@eecs.umich.edu}
4795728Sgblack@eecs.umich.edu
48011147Smitch.hayenga@arm.com#ifndef DOXYGEN_SHOULD_SKIP_THIS
48111147Smitch.hayenga@arm.com
48211147Smitch.hayenga@arm.comtemplate
48312749Sgiacomo.travaglini@arm.comFault
4848105Sgblack@eecs.umich.eduTimingSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags);
4859180Sandreas.hansson@arm.com
4869179Sandreas.hansson@arm.comtemplate
4875728Sgblack@eecs.umich.eduFault
4885728Sgblack@eecs.umich.eduTimingSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags);
4898975Sandreas.hansson@arm.com
4905728Sgblack@eecs.umich.edutemplate
4915728Sgblack@eecs.umich.eduFault
4925728Sgblack@eecs.umich.eduTimingSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
4935728Sgblack@eecs.umich.edu
4945728Sgblack@eecs.umich.edutemplate
4955728Sgblack@eecs.umich.eduFault
4965728Sgblack@eecs.umich.eduTimingSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);
4975728Sgblack@eecs.umich.edu
4982623SN/Atemplate
4992623SN/AFault
5008444Sgblack@eecs.umich.eduTimingSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);
50111608Snikos.nikoleris@arm.com
5022623SN/Atemplate
50311147Smitch.hayenga@arm.comFault
50411147Smitch.hayenga@arm.comTimingSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);
50511147Smitch.hayenga@arm.com
5068443Sgblack@eecs.umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
5075728Sgblack@eecs.umich.edu
5087720Sgblack@eecs.umich.edutemplate<>
5099814Sandreas.hansson@arm.comFault
5106973Stjones1@inf.ed.ac.ukTimingSimpleCPU::read(Addr addr, double &data, unsigned flags)
5113169Sstever@eecs.umich.edu{
51210031SAli.Saidi@ARM.com    return read(addr, *(uint64_t*)&data, flags);
51312355Snikos.nikoleris@arm.com}
51410031SAli.Saidi@ARM.com
51510031SAli.Saidi@ARM.comtemplate<>
51610031SAli.Saidi@ARM.comFault
51710031SAli.Saidi@ARM.comTimingSimpleCPU::read(Addr addr, float &data, unsigned flags)
51810031SAli.Saidi@ARM.com{
51910031SAli.Saidi@ARM.com    return read(addr, *(uint32_t*)&data, flags);
52010665SAli.Saidi@ARM.com}
52110665SAli.Saidi@ARM.com
5227045Ssteve.reinhardt@amd.com
52312749Sgiacomo.travaglini@arm.comtemplate<>
52412749Sgiacomo.travaglini@arm.comFault
52512749Sgiacomo.travaglini@arm.comTimingSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
5265728Sgblack@eecs.umich.edu{
52710024Sdam.sunwoo@arm.com    return read(addr, (uint32_t&)data, flags);
52810024Sdam.sunwoo@arm.com}
5297520Sgblack@eecs.umich.edu
5305744Sgblack@eecs.umich.edubool
5315728Sgblack@eecs.umich.eduTimingSimpleCPU::handleWritePacket()
5325894Sgblack@eecs.umich.edu{
5335744Sgblack@eecs.umich.edu    RequestPtr req = dcache_pkt->req;
5345894Sgblack@eecs.umich.edu    if (req->isMmapedIpr()) {
5356102Sgblack@eecs.umich.edu        Tick delay;
5365894Sgblack@eecs.umich.edu        delay = TheISA::handleIprWrite(thread->getTC(), dcache_pkt);
5375894Sgblack@eecs.umich.edu        new IprEvent(dcache_pkt, this, nextCycle(curTick + delay));
5386973Stjones1@inf.ed.ac.uk        _status = DcacheWaitResponse;
5398443Sgblack@eecs.umich.edu        dcache_pkt = NULL;
5408486Sgblack@eecs.umich.edu    } else if (!dcachePort.sendTiming(dcache_pkt)) {
5418486Sgblack@eecs.umich.edu        _status = DcacheRetry;
5428486Sgblack@eecs.umich.edu    } else {
5438486Sgblack@eecs.umich.edu        _status = DcacheWaitResponse;
5446973Stjones1@inf.ed.ac.uk        // memory system takes ownership of packet
54511147Smitch.hayenga@arm.com        dcache_pkt = NULL;
54611147Smitch.hayenga@arm.com    }
5475744Sgblack@eecs.umich.edu    return dcache_pkt == NULL;
5486973Stjones1@inf.ed.ac.uk}
5498443Sgblack@eecs.umich.edu
5508486Sgblack@eecs.umich.edutemplate <class T>
5518486Sgblack@eecs.umich.eduFault
55211147Smitch.hayenga@arm.comTimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
5532623SN/A{
5542623SN/A    const int asid = 0;
5557045Ssteve.reinhardt@amd.com    const int thread_id = 0;
5565728Sgblack@eecs.umich.edu    const Addr pc = thread->readPC();
5572623SN/A    int block_size = dcachePort.peerBlockSize();
5582623SN/A    int data_size = sizeof(T);
55911148Smitch.hayenga@arm.com
56011148Smitch.hayenga@arm.com    RequestPtr req = new Request(asid, addr, data_size,
56111148Smitch.hayenga@arm.com                                 flags, pc, _cpuId, thread_id);
56211148Smitch.hayenga@arm.com
56311148Smitch.hayenga@arm.com    Addr split_addr = roundDown(addr + data_size - 1, block_size);
56411321Ssteve.reinhardt@amd.com    assert(split_addr <= addr || split_addr - addr < block_size);
56511151Smitch.hayenga@arm.com
56611148Smitch.hayenga@arm.com    T *dataP = new T;
56711148Smitch.hayenga@arm.com    *dataP = TheISA::gtoh(data);
56811148Smitch.hayenga@arm.com    _status = DTBWaitResponse;
56911148Smitch.hayenga@arm.com    if (split_addr > addr) {
57011148Smitch.hayenga@arm.com        RequestPtr req1, req2;
57111148Smitch.hayenga@arm.com        assert(!req->isLocked() && !req->isSwap());
5722623SN/A        req->splitOnVaddr(split_addr, req1, req2);
5732623SN/A
5746973Stjones1@inf.ed.ac.uk        typedef SplitDataTranslation::WholeTranslationState WholeState;
5756973Stjones1@inf.ed.ac.uk        WholeState *state = new WholeState(req1, req2, req,
5769342SAndreas.Sandberg@arm.com                (uint8_t *)dataP, false);
5776973Stjones1@inf.ed.ac.uk        thread->dtb->translateTiming(req1, tc,
5786973Stjones1@inf.ed.ac.uk                new SplitDataTranslation(this, 0, state), true);
5796973Stjones1@inf.ed.ac.uk        thread->dtb->translateTiming(req2, tc,
5806973Stjones1@inf.ed.ac.uk                new SplitDataTranslation(this, 1, state), true);
5816973Stjones1@inf.ed.ac.uk    } else {
5827691SAli.Saidi@ARM.com        thread->dtb->translateTiming(req, tc,
5836973Stjones1@inf.ed.ac.uk                new DataTranslation(this, (uint8_t *)dataP, res, false),
5846973Stjones1@inf.ed.ac.uk                true);
5856973Stjones1@inf.ed.ac.uk    }
5866973Stjones1@inf.ed.ac.uk
5876973Stjones1@inf.ed.ac.uk    if (traceData) {
5886973Stjones1@inf.ed.ac.uk        traceData->setAddr(req->getVaddr());
5896973Stjones1@inf.ed.ac.uk        traceData->setData(data);
5906973Stjones1@inf.ed.ac.uk    }
5916973Stjones1@inf.ed.ac.uk
5926973Stjones1@inf.ed.ac.uk    // This will need a new way to tell if it's hooked up to a cache or not.
5936973Stjones1@inf.ed.ac.uk    if (req->isUncacheable())
5946973Stjones1@inf.ed.ac.uk        recordEvent("Uncached Write");
5956973Stjones1@inf.ed.ac.uk
5966973Stjones1@inf.ed.ac.uk    // If the write needs to have a fault on the access, consider calling
5976973Stjones1@inf.ed.ac.uk    // changeStatus() and changing it to "bad addr write" or something.
5986973Stjones1@inf.ed.ac.uk    return NoFault;
5996973Stjones1@inf.ed.ac.uk}
6002623SN/A
6012623SN/A
60211147Smitch.hayenga@arm.com#ifndef DOXYGEN_SHOULD_SKIP_THIS
60311147Smitch.hayenga@arm.comtemplate
60411147Smitch.hayenga@arm.comFault
60511147Smitch.hayenga@arm.comTimingSimpleCPU::write(Twin32_t data, Addr addr,
60611147Smitch.hayenga@arm.com                       unsigned flags, uint64_t *res);
60711147Smitch.hayenga@arm.com
6085221Ssaidi@eecs.umich.edutemplate
6095221Ssaidi@eecs.umich.eduFault
61010596Sgabeblack@google.comTimingSimpleCPU::write(Twin64_t data, Addr addr,
6113387Sgblack@eecs.umich.edu                       unsigned flags, uint64_t *res);
61210596Sgabeblack@google.com
61310596Sgabeblack@google.comtemplate
6145348Ssaidi@eecs.umich.eduFault
6158143SAli.Saidi@ARM.comTimingSimpleCPU::write(uint64_t data, Addr addr,
6168143SAli.Saidi@ARM.com                       unsigned flags, uint64_t *res);
6178143SAli.Saidi@ARM.com
6188143SAli.Saidi@ARM.comtemplate
6197720Sgblack@eecs.umich.eduFault
62011147Smitch.hayenga@arm.comTimingSimpleCPU::write(uint32_t data, Addr addr,
62111147Smitch.hayenga@arm.com                       unsigned flags, uint64_t *res);
6222623SN/A
6237720Sgblack@eecs.umich.edutemplate
6249342SAndreas.Sandberg@arm.comFault
62512749Sgiacomo.travaglini@arm.comTimingSimpleCPU::write(uint16_t data, Addr addr,
62610024Sdam.sunwoo@arm.com                       unsigned flags, uint64_t *res);
62711435Smitch.hayenga@arm.com
6285894Sgblack@eecs.umich.edutemplate
6298277SAli.Saidi@ARM.comFault
63011147Smitch.hayenga@arm.comTimingSimpleCPU::write(uint8_t data, Addr addr,
63111147Smitch.hayenga@arm.com                       unsigned flags, uint64_t *res);
6322623SN/A
6335669Sgblack@eecs.umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
6345669Sgblack@eecs.umich.edu
6355894Sgblack@eecs.umich.edutemplate<>
63610464SAndreas.Sandberg@ARM.comFault
63712284Sjose.marinho@arm.comTimingSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
6385894Sgblack@eecs.umich.edu{
6395894Sgblack@eecs.umich.edu    return write(*(uint64_t*)&data, addr, flags, res);
6405894Sgblack@eecs.umich.edu}
6415894Sgblack@eecs.umich.edu
6425894Sgblack@eecs.umich.edutemplate<>
64312749Sgiacomo.travaglini@arm.comFault
64410379Sandreas.hansson@arm.comTimingSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
6455894Sgblack@eecs.umich.edu{
6465894Sgblack@eecs.umich.edu    return write(*(uint32_t*)&data, addr, flags, res);
6478277SAli.Saidi@ARM.com}
6488277SAli.Saidi@ARM.com
6498949Sandreas.hansson@arm.com
6505894Sgblack@eecs.umich.edutemplate<>
6518277SAli.Saidi@ARM.comFault
6525894Sgblack@eecs.umich.eduTimingSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
6538975Sandreas.hansson@arm.com{
6545894Sgblack@eecs.umich.edu    return write((uint32_t)data, addr, flags, res);
6555894Sgblack@eecs.umich.edu}
6565894Sgblack@eecs.umich.edu
6575894Sgblack@eecs.umich.edu
6585894Sgblack@eecs.umich.eduvoid
6595894Sgblack@eecs.umich.eduTimingSimpleCPU::fetch()
6605894Sgblack@eecs.umich.edu{
6615894Sgblack@eecs.umich.edu    DPRINTF(SimpleCPU, "Fetch\n");
6625894Sgblack@eecs.umich.edu
6638277SAli.Saidi@ARM.com    if (!curStaticInst || !curStaticInst->isDelayedCommit())
6645894Sgblack@eecs.umich.edu        checkForInterrupts();
6659342SAndreas.Sandberg@arm.com
6665894Sgblack@eecs.umich.edu    checkPcEventQueue();
6672623SN/A
6683222Sktlim@umich.edu    bool fromRom = isRomMicroPC(thread->readMicroPC());
66910464SAndreas.Sandberg@ARM.com
67012284Sjose.marinho@arm.com    if (!fromRom) {
6712623SN/A        Request *ifetch_req = new Request();
6722623SN/A        ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0);
6732623SN/A        setupFetchRequest(ifetch_req);
6742623SN/A        thread->itb->translateTiming(ifetch_req, tc,
67510379Sandreas.hansson@arm.com                &fetchTranslation);
6762623SN/A    } else {
67711147Smitch.hayenga@arm.com        _status = IcacheWaitResponse;
67811147Smitch.hayenga@arm.com        completeIfetch(NULL);
6798276SAli.Saidi@ARM.com
6808276SAli.Saidi@ARM.com        numCycles += tickToCycles(curTick - previousTick);
6818276SAli.Saidi@ARM.com        previousTick = curTick;
6828276SAli.Saidi@ARM.com    }
68312769Sqtt2@cornell.edu}
68411877Sbrandon.potter@amd.com
6858276SAli.Saidi@ARM.com
68611877Sbrandon.potter@amd.comvoid
68712769Sqtt2@cornell.eduTimingSimpleCPU::sendFetch(Fault fault, RequestPtr req, ThreadContext *tc)
68812769Sqtt2@cornell.edu{
68912769Sqtt2@cornell.edu    if (fault == NoFault) {
69012769Sqtt2@cornell.edu        ifetch_pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
69112769Sqtt2@cornell.edu        ifetch_pkt->dataStatic(&inst);
69212769Sqtt2@cornell.edu
69312769Sqtt2@cornell.edu        if (!icachePort.sendTiming(ifetch_pkt)) {
69411877Sbrandon.potter@amd.com            // Need to wait for retry
69512769Sqtt2@cornell.edu            _status = IcacheRetry;
69612769Sqtt2@cornell.edu        } else {
69712769Sqtt2@cornell.edu            // Need to wait for cache to respond
69812769Sqtt2@cornell.edu            _status = IcacheWaitResponse;
69912769Sqtt2@cornell.edu            // ownership of packet transferred to memory system
70011877Sbrandon.potter@amd.com            ifetch_pkt = NULL;
7018276SAli.Saidi@ARM.com        }
7028276SAli.Saidi@ARM.com    } else {
7038276SAli.Saidi@ARM.com        delete req;
70411147Smitch.hayenga@arm.com        // fetch fault: advance directly to next instruction (fault handler)
7055726Sgblack@eecs.umich.edu        advanceInst(fault);
7062623SN/A    }
7079442SAndreas.Sandberg@ARM.com
70812769Sqtt2@cornell.edu    numCycles += tickToCycles(curTick - previousTick);
7099442SAndreas.Sandberg@ARM.com    previousTick = curTick;
7109342SAndreas.Sandberg@arm.com}
7112631SN/A
7122631SN/A
7132631SN/Avoid
7142631SN/ATimingSimpleCPU::advanceInst(Fault fault)
7152631SN/A{
7162623SN/A    if (fault != NoFault || !stayAtPC)
7172623SN/A        advancePC(fault);
7182623SN/A
7192623SN/A    if (_status == Running) {
7203349Sbinkertn@umich.edu        // kick off fetch of next instruction... callback from icache
7212623SN/A        // response will cause that instruction to be executed,
72211147Smitch.hayenga@arm.com        // keeping the CPU running.
72311147Smitch.hayenga@arm.com        fetch();
7248277SAli.Saidi@ARM.com    }
7258277SAli.Saidi@ARM.com}
7268277SAli.Saidi@ARM.com
7272623SN/A
7282623SN/Avoid
7295669Sgblack@eecs.umich.eduTimingSimpleCPU::completeIfetch(PacketPtr pkt)
7302623SN/A{
7312798Sktlim@umich.edu    DPRINTF(SimpleCPU, "Complete ICache Fetch\n");
7329342SAndreas.Sandberg@arm.com
7332644Sstever@eecs.umich.edu    // received a response from the icache: execute the received
73410464SAndreas.Sandberg@ARM.com    // instruction
73512284Sjose.marinho@arm.com
7363222Sktlim@umich.edu    assert(!pkt || !pkt->isError());
73710020Smatt.horsnell@ARM.com    assert(_status == IcacheWaitResponse);
73810020Smatt.horsnell@ARM.com
73910020Smatt.horsnell@ARM.com    _status = Running;
74010020Smatt.horsnell@ARM.com
7412623SN/A    numCycles += tickToCycles(curTick - previousTick);
7427725SAli.Saidi@ARM.com    previousTick = curTick;
7432623SN/A
74411147Smitch.hayenga@arm.com    if (getState() == SimObject::Draining) {
7457945SAli.Saidi@ARM.com        if (pkt) {
7467945SAli.Saidi@ARM.com            delete pkt->req;
7477945SAli.Saidi@ARM.com            delete pkt;
7487945SAli.Saidi@ARM.com        }
7499342SAndreas.Sandberg@arm.com
7505894Sgblack@eecs.umich.edu        completeDrain();
7515001Sgblack@eecs.umich.edu        return;
7525001Sgblack@eecs.umich.edu    }
7535001Sgblack@eecs.umich.edu
7543170Sstever@eecs.umich.edu    preExecute();
7554998Sgblack@eecs.umich.edu    if (curStaticInst &&
7562644Sstever@eecs.umich.edu            curStaticInst->isMemRef() && !curStaticInst->isDataPrefetch()) {
7575103Ssaidi@eecs.umich.edu        // load or store: just send to dcache
7585103Ssaidi@eecs.umich.edu        Fault fault = curStaticInst->initiateAcc(this, traceData);
7595103Ssaidi@eecs.umich.edu        if (_status != Running) {
7605103Ssaidi@eecs.umich.edu            // instruction will complete in dcache response callback
7612644Sstever@eecs.umich.edu            assert(_status == DcacheWaitResponse ||
7622644Sstever@eecs.umich.edu                    _status == DcacheRetry || DTBWaitResponse);
7635726Sgblack@eecs.umich.edu            assert(fault == NoFault);
7642623SN/A        } else {
76511147Smitch.hayenga@arm.com            if (fault != NoFault && traceData) {
7664998Sgblack@eecs.umich.edu                // If there was a fault, we shouldn't trace this instruction.
7674998Sgblack@eecs.umich.edu                delete traceData;
7684998Sgblack@eecs.umich.edu                traceData = NULL;
7694998Sgblack@eecs.umich.edu            }
7707655Sali.saidi@arm.com
7715001Sgblack@eecs.umich.edu            postExecute();
7725001Sgblack@eecs.umich.edu            // @todo remove me after debugging with legion done
7735001Sgblack@eecs.umich.edu            if (curStaticInst && (!curStaticInst->isMicroop() ||
7744998Sgblack@eecs.umich.edu                        curStaticInst->isFirstMicroop()))
7752644Sstever@eecs.umich.edu                instCnt++;
7765103Ssaidi@eecs.umich.edu            advanceInst(fault);
7775103Ssaidi@eecs.umich.edu        }
77811147Smitch.hayenga@arm.com    } else if (curStaticInst) {
7795103Ssaidi@eecs.umich.edu        // non-memory instruction: execute completely now
7802644Sstever@eecs.umich.edu        Fault fault = curStaticInst->execute(this, traceData);
7815726Sgblack@eecs.umich.edu
7825726Sgblack@eecs.umich.edu        // keep an instruction count
7832623SN/A        if (fault == NoFault)
7843658Sktlim@umich.edu            countInst();
7855669Sgblack@eecs.umich.edu        else if (traceData) {
7865669Sgblack@eecs.umich.edu            // If there was a fault, we shouldn't trace this instruction.
7875669Sgblack@eecs.umich.edu            delete traceData;
7882623SN/A            traceData = NULL;
7892623SN/A        }
7902948Ssaidi@eecs.umich.edu
7912948Ssaidi@eecs.umich.edu        postExecute();
7922948Ssaidi@eecs.umich.edu        // @todo remove me after debugging with legion done
7932948Ssaidi@eecs.umich.edu        if (curStaticInst && (!curStaticInst->isMicroop() ||
7942948Ssaidi@eecs.umich.edu                    curStaticInst->isFirstMicroop()))
7952623SN/A            instCnt++;
7962623SN/A        advanceInst(fault);
7978975Sandreas.hansson@arm.com    } else {
7982623SN/A        advanceInst(NoFault);
79910669Sandreas.hansson@arm.com    }
80010669Sandreas.hansson@arm.com
80110669Sandreas.hansson@arm.com    if (pkt) {
80210669Sandreas.hansson@arm.com        delete pkt->req;
8039165Sandreas.hansson@arm.com        delete pkt;
80410669Sandreas.hansson@arm.com    }
8058948Sandreas.hansson@arm.com}
8064433Ssaidi@eecs.umich.edu
8072623SN/Avoid
8082623SN/ATimingSimpleCPU::IcachePort::ITickEvent::process()
8092657Ssaidi@eecs.umich.edu{
81010713Sandreas.hansson@arm.com    cpu->completeIfetch(pkt);
8112623SN/A}
8122623SN/A
8132623SN/Abool
8142623SN/ATimingSimpleCPU::IcachePort::recvTiming(PacketPtr pkt)
8152623SN/A{
8163349Sbinkertn@umich.edu    if (pkt->isResponse() && !pkt->wasNacked()) {
8178975Sandreas.hansson@arm.com        // delay processing of returned data until next CPU clock edge
8182657Ssaidi@eecs.umich.edu        Tick next_tick = cpu->nextCycle(curTick);
8192657Ssaidi@eecs.umich.edu
8202657Ssaidi@eecs.umich.edu        if (next_tick == curTick)
8212623SN/A            cpu->completeIfetch(pkt);
8222623SN/A        else
8232623SN/A            tickEvent.schedule(pkt, next_tick);
8243349Sbinkertn@umich.edu
8252623SN/A        return true;
8262623SN/A    }
8272623SN/A    else if (pkt->wasNacked()) {
8284870Sstever@eecs.umich.edu        assert(cpu->_status == IcacheWaitResponse);
8297516Shestness@cs.utexas.edu        pkt->reinitNacked();
8307516Shestness@cs.utexas.edu        if (!sendTiming(pkt)) {
8312623SN/A            cpu->_status = IcacheRetry;
83210020Smatt.horsnell@ARM.com            cpu->ifetch_pkt = pkt;
83310464SAndreas.Sandberg@ARM.com        }
83410464SAndreas.Sandberg@ARM.com    }
83512284Sjose.marinho@arm.com    //Snooping a Coherence Request, do nothing
8363184Srdreslin@umich.edu    return true;
8375728Sgblack@eecs.umich.edu}
8385728Sgblack@eecs.umich.edu
8395728Sgblack@eecs.umich.eduvoid
8405728Sgblack@eecs.umich.eduTimingSimpleCPU::IcachePort::recvRetry()
8415728Sgblack@eecs.umich.edu{
8425728Sgblack@eecs.umich.edu    // we shouldn't get a retry unless we have a packet that we're
8435728Sgblack@eecs.umich.edu    // waiting to transmit
84411320Ssteve.reinhardt@amd.com    assert(cpu->ifetch_pkt != NULL);
8455728Sgblack@eecs.umich.edu    assert(cpu->_status == IcacheRetry);
8465728Sgblack@eecs.umich.edu    PacketPtr tmp = cpu->ifetch_pkt;
8475728Sgblack@eecs.umich.edu    if (sendTiming(tmp)) {
8485728Sgblack@eecs.umich.edu        cpu->_status = IcacheWaitResponse;
8495728Sgblack@eecs.umich.edu        cpu->ifetch_pkt = NULL;
8505728Sgblack@eecs.umich.edu    }
8515728Sgblack@eecs.umich.edu}
8525728Sgblack@eecs.umich.edu
8535728Sgblack@eecs.umich.eduvoid
8545728Sgblack@eecs.umich.eduTimingSimpleCPU::completeDataAccess(PacketPtr pkt)
8555728Sgblack@eecs.umich.edu{
8565728Sgblack@eecs.umich.edu    // received a response from the dcache: complete the load or store
8575728Sgblack@eecs.umich.edu    // instruction
8585728Sgblack@eecs.umich.edu    assert(!pkt->isError());
8595728Sgblack@eecs.umich.edu
8605728Sgblack@eecs.umich.edu    numCycles += tickToCycles(curTick - previousTick);
8619342SAndreas.Sandberg@arm.com    previousTick = curTick;
8625728Sgblack@eecs.umich.edu
86311147Smitch.hayenga@arm.com    if (pkt->senderState) {
86411147Smitch.hayenga@arm.com        SplitFragmentSenderState * send_state =
8652623SN/A            dynamic_cast<SplitFragmentSenderState *>(pkt->senderState);
8664998Sgblack@eecs.umich.edu        assert(send_state);
8674998Sgblack@eecs.umich.edu        delete pkt->req;
8684998Sgblack@eecs.umich.edu        delete pkt;
8695001Sgblack@eecs.umich.edu        PacketPtr big_pkt = send_state->bigPkt;
8705001Sgblack@eecs.umich.edu        delete send_state;
8715001Sgblack@eecs.umich.edu
8725001Sgblack@eecs.umich.edu        SplitMainSenderState * main_send_state =
8735001Sgblack@eecs.umich.edu            dynamic_cast<SplitMainSenderState *>(big_pkt->senderState);
8744998Sgblack@eecs.umich.edu        assert(main_send_state);
8752644Sstever@eecs.umich.edu        // Record the fact that this packet is no longer outstanding.
8762644Sstever@eecs.umich.edu        assert(main_send_state->outstanding != 0);
8773184Srdreslin@umich.edu        main_send_state->outstanding--;
8783227Sktlim@umich.edu
8792644Sstever@eecs.umich.edu        if (main_send_state->outstanding) {
8802623SN/A            return;
8812623SN/A        } else {
88210030SAli.Saidi@ARM.com            delete main_send_state;
88310464SAndreas.Sandberg@ARM.com            big_pkt->senderState = NULL;
88410464SAndreas.Sandberg@ARM.com            pkt = big_pkt;
88510464SAndreas.Sandberg@ARM.com        }
88610464SAndreas.Sandberg@ARM.com    }
88710464SAndreas.Sandberg@ARM.com
88810464SAndreas.Sandberg@ARM.com    assert(_status == DcacheWaitResponse || _status == DTBWaitResponse);
88910464SAndreas.Sandberg@ARM.com    _status = Running;
89010464SAndreas.Sandberg@ARM.com
89110464SAndreas.Sandberg@ARM.com    Fault fault = curStaticInst->completeAcc(pkt, this, traceData);
89210464SAndreas.Sandberg@ARM.com
89310030SAli.Saidi@ARM.com    // keep an instruction count
89410030SAli.Saidi@ARM.com    if (fault == NoFault)
89511148Smitch.hayenga@arm.com        countInst();
89611148Smitch.hayenga@arm.com    else if (traceData) {
89711151Smitch.hayenga@arm.com        // If there was a fault, we shouldn't trace this instruction.
89811148Smitch.hayenga@arm.com        delete traceData;
89910529Smorr@cs.wisc.edu        traceData = NULL;
90011147Smitch.hayenga@arm.com    }
90111356Skrinat01@arm.com
90211356Skrinat01@arm.com    // the locked flag may be cleared on the response packet, so check
90311356Skrinat01@arm.com    // pkt->req and not pkt to see if it was a load-locked
90411356Skrinat01@arm.com    if (pkt->isRead() && pkt->req->isLocked()) {
90511356Skrinat01@arm.com        TheISA::handleLockedRead(thread, pkt->req);
90611356Skrinat01@arm.com    }
90711356Skrinat01@arm.com
90811356Skrinat01@arm.com    delete pkt->req;
90911147Smitch.hayenga@arm.com    delete pkt;
91010030SAli.Saidi@ARM.com
91110030SAli.Saidi@ARM.com    postExecute();
91210529Smorr@cs.wisc.edu
91310529Smorr@cs.wisc.edu    if (getState() == SimObject::Draining) {
91410529Smorr@cs.wisc.edu        advancePC(fault);
91511148Smitch.hayenga@arm.com        completeDrain();
91611321Ssteve.reinhardt@amd.com
91711151Smitch.hayenga@arm.com        return;
91811148Smitch.hayenga@arm.com    }
91910529Smorr@cs.wisc.edu
92010529Smorr@cs.wisc.edu    advanceInst(fault);
92110030SAli.Saidi@ARM.com}
9222623SN/A
9238975Sandreas.hansson@arm.com
9242623SN/Avoid
92510669Sandreas.hansson@arm.comTimingSimpleCPU::completeDrain()
9262948Ssaidi@eecs.umich.edu{
92710669Sandreas.hansson@arm.com    DPRINTF(Config, "Done draining\n");
92810669Sandreas.hansson@arm.com    changeState(SimObject::Drained);
92910669Sandreas.hansson@arm.com    drainEvent->process();
93010669Sandreas.hansson@arm.com}
93110669Sandreas.hansson@arm.com
93210669Sandreas.hansson@arm.comvoid
9339165Sandreas.hansson@arm.comTimingSimpleCPU::DcachePort::setPeer(Port *port)
93410669Sandreas.hansson@arm.com{
93510669Sandreas.hansson@arm.com    Port::setPeer(port);
93610669Sandreas.hansson@arm.com
93710713Sandreas.hansson@arm.com#if FULL_SYSTEM
93810713Sandreas.hansson@arm.com    // Update the ThreadContext's memory ports (Functional/Virtual
93910669Sandreas.hansson@arm.com    // Ports)
9403310Srdreslin@umich.edu    cpu->tcBase()->connectMemPorts(cpu->tcBase());
9412948Ssaidi@eecs.umich.edu#endif
9422948Ssaidi@eecs.umich.edu}
9432948Ssaidi@eecs.umich.edu
9442948Ssaidi@eecs.umich.edubool
9452948Ssaidi@eecs.umich.eduTimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt)
9462630SN/A{
9472623SN/A    if (pkt->isResponse() && !pkt->wasNacked()) {
9482623SN/A        // delay processing of returned data until next CPU clock edge
9492657Ssaidi@eecs.umich.edu        Tick next_tick = cpu->nextCycle(curTick);
95010713Sandreas.hansson@arm.com
9512623SN/A        if (next_tick == curTick) {
9522623SN/A            cpu->completeDataAccess(pkt);
9532623SN/A        } else {
9542623SN/A            tickEvent.schedule(pkt, next_tick);
9552623SN/A        }
9563349Sbinkertn@umich.edu
9575728Sgblack@eecs.umich.edu        return true;
9585728Sgblack@eecs.umich.edu    }
9595728Sgblack@eecs.umich.edu    else if (pkt->wasNacked()) {
9605728Sgblack@eecs.umich.edu        assert(cpu->_status == DcacheWaitResponse);
9615728Sgblack@eecs.umich.edu        pkt->reinitNacked();
9625728Sgblack@eecs.umich.edu        if (!sendTiming(pkt)) {
96311320Ssteve.reinhardt@amd.com            cpu->_status = DcacheRetry;
9645728Sgblack@eecs.umich.edu            cpu->dcache_pkt = pkt;
9655728Sgblack@eecs.umich.edu        }
9665728Sgblack@eecs.umich.edu    }
9675728Sgblack@eecs.umich.edu    //Snooping a Coherence Request, do nothing
9688975Sandreas.hansson@arm.com    return true;
9695728Sgblack@eecs.umich.edu}
9705728Sgblack@eecs.umich.edu
9715728Sgblack@eecs.umich.eduvoid
9725728Sgblack@eecs.umich.eduTimingSimpleCPU::DcachePort::DTickEvent::process()
9735728Sgblack@eecs.umich.edu{
9745728Sgblack@eecs.umich.edu    cpu->completeDataAccess(pkt);
9755728Sgblack@eecs.umich.edu}
9765728Sgblack@eecs.umich.edu
9775728Sgblack@eecs.umich.eduvoid
9785728Sgblack@eecs.umich.eduTimingSimpleCPU::DcachePort::recvRetry()
9795728Sgblack@eecs.umich.edu{
9805728Sgblack@eecs.umich.edu    // we shouldn't get a retry unless we have a packet that we're
9815728Sgblack@eecs.umich.edu    // waiting to transmit
9825728Sgblack@eecs.umich.edu    assert(cpu->dcache_pkt != NULL);
9835728Sgblack@eecs.umich.edu    assert(cpu->_status == DcacheRetry);
9845728Sgblack@eecs.umich.edu    PacketPtr tmp = cpu->dcache_pkt;
9855728Sgblack@eecs.umich.edu    if (tmp->senderState) {
9868975Sandreas.hansson@arm.com        // This is a packet from a split access.
9872657Ssaidi@eecs.umich.edu        SplitFragmentSenderState * send_state =
9883170Sstever@eecs.umich.edu            dynamic_cast<SplitFragmentSenderState *>(tmp->senderState);
9892657Ssaidi@eecs.umich.edu        assert(send_state);
9902657Ssaidi@eecs.umich.edu        PacketPtr big_pkt = send_state->bigPkt;
9912623SN/A
9922623SN/A        SplitMainSenderState * main_send_state =
9935606Snate@binkert.org            dynamic_cast<SplitMainSenderState *>(big_pkt->senderState);
9945606Snate@binkert.org        assert(main_send_state);
9955606Snate@binkert.org
9965103Ssaidi@eecs.umich.edu        if (sendTiming(tmp)) {
9975606Snate@binkert.org            // If we were able to send without retrying, record that fact
9985103Ssaidi@eecs.umich.edu            // and try sending the other fragment.
9995103Ssaidi@eecs.umich.edu            send_state->clearFromParent();
10005103Ssaidi@eecs.umich.edu            int other_index = main_send_state->getPendingFragment();
10015103Ssaidi@eecs.umich.edu            if (other_index > 0) {
10025103Ssaidi@eecs.umich.edu                tmp = main_send_state->fragments[other_index];
10035103Ssaidi@eecs.umich.edu                cpu->dcache_pkt = tmp;
10045103Ssaidi@eecs.umich.edu                if ((big_pkt->isRead() && cpu->handleReadPacket(tmp)) ||
10055103Ssaidi@eecs.umich.edu                        (big_pkt->isWrite() && cpu->handleWritePacket())) {
10065103Ssaidi@eecs.umich.edu                    main_send_state->fragments[other_index] = NULL;
10075336Shines@cs.fsu.edu                }
10085103Ssaidi@eecs.umich.edu            } else {
10095103Ssaidi@eecs.umich.edu                cpu->_status = DcacheWaitResponse;
10105103Ssaidi@eecs.umich.edu                // memory system takes ownership of packet
10115103Ssaidi@eecs.umich.edu                cpu->dcache_pkt = NULL;
10122623SN/A            }
10135315Sstever@gmail.com        }
10145315Sstever@gmail.com    } else if (sendTiming(tmp)) {
10155315Sstever@gmail.com        cpu->_status = DcacheWaitResponse;
10165315Sstever@gmail.com        // memory system takes ownership of packet
10175315Sstever@gmail.com        cpu->dcache_pkt = NULL;
10185315Sstever@gmail.com    }
10195315Sstever@gmail.com}
10202623SN/A
10212623SN/ATimingSimpleCPU::IprEvent::IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu,
10222623SN/A    Tick t)
10232623SN/A    : pkt(_pkt), cpu(_cpu)
10244762Snate@binkert.org{
10254762Snate@binkert.org    cpu->schedule(this, t);
10262623SN/A}
10275529Snate@binkert.org
10282623SN/Avoid
1029TimingSimpleCPU::IprEvent::process()
1030{
1031    cpu->completeDataAccess(pkt);
1032}
1033
1034const char *
1035TimingSimpleCPU::IprEvent::description() const
1036{
1037    return "Timing Simple CPU Delay IPR event";
1038}
1039
1040
1041void
1042TimingSimpleCPU::printAddr(Addr a)
1043{
1044    dcachePort.printAddr(a);
1045}
1046
1047
1048////////////////////////////////////////////////////////////////////////
1049//
1050//  TimingSimpleCPU Simulation Object
1051//
1052TimingSimpleCPU *
1053TimingSimpleCPUParams::create()
1054{
1055    numThreads = 1;
1056#if !FULL_SYSTEM
1057    if (workload.size() != 1)
1058        panic("only one workload allowed");
1059#endif
1060    return new TimingSimpleCPU(this);
1061}
1062