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 §ion) 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