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