atomic.cc revision 7046:d21d575a6f99
16019Shines@cs.fsu.edu/* 211496Sandreas.sandberg@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 37093Sgblack@eecs.umich.edu * All rights reserved. 47093Sgblack@eecs.umich.edu * 57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146019Shines@cs.fsu.edu * this software without specific prior written permission. 156019Shines@cs.fsu.edu * 166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu * 286019Shines@cs.fsu.edu * Authors: Steve Reinhardt 296019Shines@cs.fsu.edu */ 306019Shines@cs.fsu.edu 316019Shines@cs.fsu.edu#include "arch/locked_mem.hh" 326019Shines@cs.fsu.edu#include "arch/mmaped_ipr.hh" 336019Shines@cs.fsu.edu#include "arch/utility.hh" 346019Shines@cs.fsu.edu#include "base/bigint.hh" 356019Shines@cs.fsu.edu#include "config/the_isa.hh" 366019Shines@cs.fsu.edu#include "cpu/exetrace.hh" 376019Shines@cs.fsu.edu#include "cpu/simple/atomic.hh" 386019Shines@cs.fsu.edu#include "mem/packet.hh" 396019Shines@cs.fsu.edu#include "mem/packet_access.hh" 406019Shines@cs.fsu.edu#include "params/AtomicSimpleCPU.hh" 416735Sgblack@eecs.umich.edu#include "sim/system.hh" 426735Sgblack@eecs.umich.edu 4310037SARM gem5 Developersusing namespace std; 4410037SARM gem5 Developersusing namespace TheISA; 456019Shines@cs.fsu.edu 466019Shines@cs.fsu.eduAtomicSimpleCPU::TickEvent::TickEvent(AtomicSimpleCPU *c) 476019Shines@cs.fsu.edu : Event(CPU_Tick_Pri), cpu(c) 4811793Sbrandon.potter@amd.com{ 4911793Sbrandon.potter@amd.com} 5010037SARM gem5 Developers 5110037SARM gem5 Developers 5210037SARM gem5 Developersvoid 538229Snate@binkert.orgAtomicSimpleCPU::TickEvent::process() 548229Snate@binkert.org{ 556019Shines@cs.fsu.edu cpu->tick(); 568232Snate@binkert.org} 578782Sgblack@eecs.umich.edu 586019Shines@cs.fsu.educonst char * 596019Shines@cs.fsu.eduAtomicSimpleCPU::TickEvent::description() const 606019Shines@cs.fsu.edu{ 616019Shines@cs.fsu.edu return "AtomicSimpleCPU tick"; 6210037SARM gem5 Developers} 6310037SARM gem5 Developers 6410037SARM gem5 DevelopersPort * 6510037SARM gem5 DevelopersAtomicSimpleCPU::getPort(const string &if_name, int idx) 6610037SARM gem5 Developers{ 6710037SARM gem5 Developers if (if_name == "dcache_port") 6810037SARM gem5 Developers return &dcachePort; 6910037SARM gem5 Developers else if (if_name == "icache_port") 7010037SARM gem5 Developers return &icachePort; 7110037SARM gem5 Developers else if (if_name == "physmem_port") { 7210037SARM gem5 Developers hasPhysMemPort = true; 7310037SARM gem5 Developers return &physmemPort; 7410037SARM gem5 Developers } 7510037SARM gem5 Developers else 7610037SARM gem5 Developers panic("No Such Port\n"); 7710037SARM gem5 Developers} 7810037SARM gem5 Developers 7910037SARM gem5 Developersvoid 8010037SARM gem5 DevelopersAtomicSimpleCPU::init() 8110037SARM gem5 Developers{ 8210037SARM gem5 Developers BaseCPU::init(); 8310037SARM gem5 Developers#if FULL_SYSTEM 8410037SARM gem5 Developers ThreadID size = threadContexts.size(); 8510037SARM gem5 Developers for (ThreadID i = 0; i < size; ++i) { 8610037SARM gem5 Developers ThreadContext *tc = threadContexts[i]; 8710037SARM gem5 Developers 8810037SARM gem5 Developers // initialize CPU, including PC 8910037SARM gem5 Developers TheISA::initCPU(tc, tc->contextId()); 9010037SARM gem5 Developers } 9110037SARM gem5 Developers#endif 9210037SARM gem5 Developers if (hasPhysMemPort) { 9310037SARM gem5 Developers bool snoop = false; 9410037SARM gem5 Developers AddrRangeList pmAddrList; 9510037SARM gem5 Developers physmemPort.getPeerAddressRanges(pmAddrList, snoop); 9610037SARM gem5 Developers physMemAddr = *pmAddrList.begin(); 9710037SARM gem5 Developers } 9810037SARM gem5 Developers // Atomic doesn't do MT right now, so contextId == threadId 9910037SARM gem5 Developers ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT 10010037SARM gem5 Developers data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too 10110037SARM gem5 Developers data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too 1026019Shines@cs.fsu.edu} 10310037SARM gem5 Developers 10410037SARM gem5 Developersbool 10510037SARM gem5 DevelopersAtomicSimpleCPU::CpuPort::recvTiming(PacketPtr pkt) 1066019Shines@cs.fsu.edu{ 10710037SARM gem5 Developers panic("AtomicSimpleCPU doesn't expect recvTiming callback!"); 10810037SARM gem5 Developers return true; 10910037SARM gem5 Developers} 11010037SARM gem5 Developers 11110037SARM gem5 DevelopersTick 11210037SARM gem5 DevelopersAtomicSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt) 11310037SARM gem5 Developers{ 11410037SARM gem5 Developers //Snooping a coherence request, just return 11510037SARM gem5 Developers return 0; 11610037SARM gem5 Developers} 11710037SARM gem5 Developers 11810037SARM gem5 Developersvoid 11910037SARM gem5 DevelopersAtomicSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt) 12010037SARM gem5 Developers{ 12110037SARM gem5 Developers //No internal storage to update, just return 12210037SARM gem5 Developers return; 12310037SARM gem5 Developers} 12410037SARM gem5 Developers 12510037SARM gem5 Developersvoid 12610037SARM gem5 DevelopersAtomicSimpleCPU::CpuPort::recvStatusChange(Status status) 12710037SARM gem5 Developers{ 12810037SARM gem5 Developers if (status == RangeChange) { 12910037SARM gem5 Developers if (!snoopRangeSent) { 13010037SARM gem5 Developers snoopRangeSent = true; 13110037SARM gem5 Developers sendStatusChange(Port::RangeChange); 13210037SARM gem5 Developers } 13310037SARM gem5 Developers return; 13410037SARM gem5 Developers } 13510037SARM gem5 Developers 13610037SARM gem5 Developers panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!"); 13710037SARM gem5 Developers} 13810037SARM gem5 Developers 13910037SARM gem5 Developersvoid 14010037SARM gem5 DevelopersAtomicSimpleCPU::CpuPort::recvRetry() 14110037SARM gem5 Developers{ 14210037SARM gem5 Developers panic("AtomicSimpleCPU doesn't expect recvRetry callback!"); 14310037SARM gem5 Developers} 14410037SARM gem5 Developers 14510037SARM gem5 Developersvoid 14610037SARM gem5 DevelopersAtomicSimpleCPU::DcachePort::setPeer(Port *port) 1476019Shines@cs.fsu.edu{ 14810037SARM gem5 Developers Port::setPeer(port); 14910037SARM gem5 Developers 15010037SARM gem5 Developers#if FULL_SYSTEM 1516019Shines@cs.fsu.edu // Update the ThreadContext's memory ports (Functional/Virtual 15210037SARM gem5 Developers // Ports) 15310037SARM gem5 Developers cpu->tcBase()->connectMemPorts(cpu->tcBase()); 15410037SARM gem5 Developers#endif 15510037SARM gem5 Developers} 15610037SARM gem5 Developers 15710037SARM gem5 DevelopersAtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p) 15810037SARM gem5 Developers : BaseSimpleCPU(p), tickEvent(this), width(p->width), locked(false), 15910037SARM gem5 Developers simulate_data_stalls(p->simulate_data_stalls), 16010037SARM gem5 Developers simulate_inst_stalls(p->simulate_inst_stalls), 16110037SARM gem5 Developers icachePort(name() + "-iport", this), dcachePort(name() + "-iport", this), 16210037SARM gem5 Developers physmemPort(name() + "-iport", this), hasPhysMemPort(false) 16310037SARM gem5 Developers{ 16410037SARM gem5 Developers _status = Idle; 16510037SARM gem5 Developers 16610037SARM gem5 Developers icachePort.snoopRangeSent = false; 16710037SARM gem5 Developers dcachePort.snoopRangeSent = false; 16810037SARM gem5 Developers 16910037SARM gem5 Developers} 17010037SARM gem5 Developers 17110037SARM gem5 Developers 17210037SARM gem5 DevelopersAtomicSimpleCPU::~AtomicSimpleCPU() 17310037SARM gem5 Developers{ 17410037SARM gem5 Developers if (tickEvent.scheduled()) { 17510037SARM gem5 Developers deschedule(tickEvent); 17610037SARM gem5 Developers } 17710037SARM gem5 Developers} 17810037SARM gem5 Developers 17910037SARM gem5 Developersvoid 18010037SARM gem5 DevelopersAtomicSimpleCPU::serialize(ostream &os) 18110037SARM gem5 Developers{ 18210037SARM gem5 Developers SimObject::State so_state = SimObject::getState(); 18310037SARM gem5 Developers SERIALIZE_ENUM(so_state); 18410037SARM gem5 Developers SERIALIZE_SCALAR(locked); 18510037SARM gem5 Developers BaseSimpleCPU::serialize(os); 18610037SARM gem5 Developers nameOut(os, csprintf("%s.tickEvent", name())); 18710037SARM gem5 Developers tickEvent.serialize(os); 18810037SARM gem5 Developers} 18910037SARM gem5 Developers 19010037SARM gem5 Developersvoid 19110037SARM gem5 DevelopersAtomicSimpleCPU::unserialize(Checkpoint *cp, const string §ion) 19210037SARM gem5 Developers{ 1936019Shines@cs.fsu.edu SimObject::State so_state; 19410037SARM gem5 Developers UNSERIALIZE_ENUM(so_state); 19510037SARM gem5 Developers UNSERIALIZE_SCALAR(locked); 19610037SARM gem5 Developers BaseSimpleCPU::unserialize(cp, section); 1976019Shines@cs.fsu.edu tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); 19810037SARM gem5 Developers} 19910037SARM gem5 Developers 20010037SARM gem5 Developersvoid 20110037SARM gem5 DevelopersAtomicSimpleCPU::resume() 20210037SARM gem5 Developers{ 20310037SARM gem5 Developers if (_status == Idle || _status == SwitchedOut) 20410037SARM gem5 Developers return; 20510037SARM gem5 Developers 20610037SARM gem5 Developers DPRINTF(SimpleCPU, "Resume\n"); 20710037SARM gem5 Developers assert(system->getMemoryMode() == Enums::atomic); 20810037SARM gem5 Developers 20910037SARM gem5 Developers changeState(SimObject::Running); 21010037SARM gem5 Developers if (thread->status() == ThreadContext::Active) { 21110037SARM gem5 Developers if (!tickEvent.scheduled()) 21210037SARM gem5 Developers schedule(tickEvent, nextCycle()); 21310037SARM gem5 Developers } 21410037SARM gem5 Developers} 21510037SARM gem5 Developers 21610037SARM gem5 Developersvoid 21710037SARM gem5 DevelopersAtomicSimpleCPU::switchOut() 21810037SARM gem5 Developers{ 21910037SARM gem5 Developers assert(_status == Running || _status == Idle); 22010037SARM gem5 Developers _status = SwitchedOut; 22110037SARM gem5 Developers 22210037SARM gem5 Developers tickEvent.squash(); 22310037SARM gem5 Developers} 22410037SARM gem5 Developers 22510037SARM gem5 Developers 22610037SARM gem5 Developersvoid 22710037SARM gem5 DevelopersAtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) 22810037SARM gem5 Developers{ 22910037SARM gem5 Developers BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); 23010037SARM gem5 Developers 23110037SARM gem5 Developers assert(!tickEvent.scheduled()); 23210037SARM gem5 Developers 23310037SARM gem5 Developers // if any of this CPU's ThreadContexts are active, mark the CPU as 23410037SARM gem5 Developers // running and schedule its tick event. 23510037SARM gem5 Developers ThreadID size = threadContexts.size(); 23610037SARM gem5 Developers for (ThreadID i = 0; i < size; ++i) { 23710037SARM gem5 Developers ThreadContext *tc = threadContexts[i]; 23810037SARM gem5 Developers if (tc->status() == ThreadContext::Active && _status != Running) { 23910037SARM gem5 Developers _status = Running; 24010037SARM gem5 Developers schedule(tickEvent, nextCycle()); 24110037SARM gem5 Developers break; 24210037SARM gem5 Developers } 24310037SARM gem5 Developers } 24410037SARM gem5 Developers if (_status != Running) { 24510037SARM gem5 Developers _status = Idle; 24610037SARM gem5 Developers } 24710037SARM gem5 Developers assert(threadContexts.size() == 1); 24810037SARM gem5 Developers ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT 24910037SARM gem5 Developers data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too 25010037SARM gem5 Developers data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too 25110037SARM gem5 Developers} 25210037SARM gem5 Developers 25310037SARM gem5 Developers 25410037SARM gem5 Developersvoid 25510037SARM gem5 DevelopersAtomicSimpleCPU::activateContext(int thread_num, int delay) 25610037SARM gem5 Developers{ 25710037SARM gem5 Developers DPRINTF(SimpleCPU, "ActivateContext %d (%d cycles)\n", thread_num, delay); 25810037SARM gem5 Developers 25910037SARM gem5 Developers assert(thread_num == 0); 26010037SARM gem5 Developers assert(thread); 26110037SARM gem5 Developers 26210037SARM gem5 Developers assert(_status == Idle); 26310037SARM gem5 Developers assert(!tickEvent.scheduled()); 26410037SARM gem5 Developers 26510037SARM gem5 Developers notIdleFraction++; 26610037SARM gem5 Developers numCycles += tickToCycles(thread->lastActivate - thread->lastSuspend); 26710037SARM gem5 Developers 26810037SARM gem5 Developers //Make sure ticks are still on multiples of cycles 26910037SARM gem5 Developers schedule(tickEvent, nextCycle(curTick + ticks(delay))); 27010037SARM gem5 Developers _status = Running; 27110037SARM gem5 Developers} 27210037SARM gem5 Developers 27310037SARM gem5 Developers 27410037SARM gem5 Developersvoid 27510037SARM gem5 DevelopersAtomicSimpleCPU::suspendContext(int thread_num) 27610037SARM gem5 Developers{ 27710037SARM gem5 Developers DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num); 27810037SARM gem5 Developers 27910037SARM gem5 Developers assert(thread_num == 0); 28010037SARM gem5 Developers assert(thread); 28110037SARM gem5 Developers 28210037SARM gem5 Developers if (_status == Idle) 28310037SARM gem5 Developers return; 28410037SARM gem5 Developers 28510037SARM gem5 Developers assert(_status == Running); 28610037SARM gem5 Developers 28710037SARM gem5 Developers // tick event may not be scheduled if this gets called from inside 28810037SARM gem5 Developers // an instruction's execution, e.g. "quiesce" 28910037SARM gem5 Developers if (tickEvent.scheduled()) 29010037SARM gem5 Developers deschedule(tickEvent); 29110037SARM gem5 Developers 29210037SARM gem5 Developers notIdleFraction--; 29310037SARM gem5 Developers _status = Idle; 29410037SARM gem5 Developers} 29510037SARM gem5 Developers 2966019Shines@cs.fsu.edu 29710037SARM gem5 Developerstemplate <class T> 2987362Sgblack@eecs.umich.eduFault 2996735Sgblack@eecs.umich.eduAtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) 30010037SARM gem5 Developers{ 3016019Shines@cs.fsu.edu // use the CPU's statically allocated read request and packet objects 30210037SARM gem5 Developers Request *req = &data_read_req; 30310037SARM gem5 Developers 3047400SAli.Saidi@ARM.com if (traceData) { 3056735Sgblack@eecs.umich.edu traceData->setAddr(addr); 3066735Sgblack@eecs.umich.edu } 30710037SARM gem5 Developers 3086735Sgblack@eecs.umich.edu //The block size of our peer. 30910037SARM gem5 Developers unsigned blockSize = dcachePort.peerBlockSize(); 31010037SARM gem5 Developers //The size of the data we're trying to read. 31110037SARM gem5 Developers int dataSize = sizeof(T); 31210037SARM gem5 Developers 3137400SAli.Saidi@ARM.com uint8_t * dataPtr = (uint8_t *)&data; 31410037SARM gem5 Developers 31510037SARM gem5 Developers //The address of the second part of this access if it needs to be split 31610037SARM gem5 Developers //across a cache line boundary. 31710037SARM gem5 Developers Addr secondAddr = roundDown(addr + dataSize - 1, blockSize); 31810037SARM gem5 Developers 31910037SARM gem5 Developers if(secondAddr > addr) 32010037SARM gem5 Developers dataSize = secondAddr - addr; 32110037SARM gem5 Developers 32210037SARM gem5 Developers dcache_latency = 0; 32310037SARM gem5 Developers 32410037SARM gem5 Developers while(1) { 32510037SARM gem5 Developers req->setVirt(0, addr, dataSize, flags, thread->readPC()); 32610037SARM gem5 Developers 32710037SARM gem5 Developers // translate to physical address 32810037SARM gem5 Developers Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read); 32910037SARM gem5 Developers 33010037SARM gem5 Developers // Now do the access. 3316019Shines@cs.fsu.edu if (fault == NoFault && !req->getFlags().isSet(Request::NO_ACCESS)) { 3326019Shines@cs.fsu.edu Packet pkt = Packet(req, 33310037SARM gem5 Developers req->isLLSC() ? MemCmd::LoadLockedReq : MemCmd::ReadReq, 33410037SARM gem5 Developers Packet::Broadcast); 33510037SARM gem5 Developers pkt.dataStatic(dataPtr); 33610037SARM gem5 Developers 33710037SARM gem5 Developers if (req->isMmapedIpr()) 33810037SARM gem5 Developers dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt); 33910037SARM gem5 Developers else { 34010037SARM gem5 Developers if (hasPhysMemPort && pkt.getAddr() == physMemAddr) 34110037SARM gem5 Developers dcache_latency += physmemPort.sendAtomic(&pkt); 34211574SCurtis.Dunham@arm.com else 34311574SCurtis.Dunham@arm.com dcache_latency += dcachePort.sendAtomic(&pkt); 34411574SCurtis.Dunham@arm.com } 34511574SCurtis.Dunham@arm.com dcache_access = true; 34610037SARM gem5 Developers 34710037SARM gem5 Developers assert(!pkt.isError()); 34810037SARM gem5 Developers 34910037SARM gem5 Developers if (req->isLLSC()) { 35010037SARM gem5 Developers TheISA::handleLockedRead(thread, req); 35110037SARM gem5 Developers } 35210037SARM gem5 Developers } 35310037SARM gem5 Developers 35410037SARM gem5 Developers //If there's a fault, return it 35510037SARM gem5 Developers if (fault != NoFault) { 35610037SARM gem5 Developers if (req->isPrefetch()) { 35710037SARM gem5 Developers return NoFault; 35810037SARM gem5 Developers } else { 35910037SARM gem5 Developers return fault; 36010037SARM gem5 Developers } 36110037SARM gem5 Developers } 36210037SARM gem5 Developers 36310037SARM gem5 Developers //If we don't need to access a second cache line, stop now. 36410037SARM gem5 Developers if (secondAddr <= addr) 36510037SARM gem5 Developers { 36610037SARM gem5 Developers data = gtoh(data); 36710037SARM gem5 Developers if (traceData) { 36810037SARM gem5 Developers traceData->setData(data); 36910037SARM gem5 Developers } 37010037SARM gem5 Developers if (req->isLocked() && fault == NoFault) { 37110037SARM gem5 Developers assert(!locked); 37210037SARM gem5 Developers locked = true; 37310037SARM gem5 Developers } 37410037SARM gem5 Developers return fault; 37510037SARM gem5 Developers } 37610037SARM gem5 Developers 37710037SARM gem5 Developers /* 37810037SARM gem5 Developers * Set up for accessing the second cache line. 37910037SARM gem5 Developers */ 38010037SARM gem5 Developers 38110037SARM gem5 Developers //Move the pointer we're reading into to the correct location. 38210037SARM gem5 Developers dataPtr += dataSize; 38310037SARM gem5 Developers //Adjust the size to get the remaining bytes. 38410037SARM gem5 Developers dataSize = addr + sizeof(T) - secondAddr; 38510037SARM gem5 Developers //And access the right address. 38610037SARM gem5 Developers addr = secondAddr; 38710037SARM gem5 Developers } 38810037SARM gem5 Developers} 38910037SARM gem5 Developers 39010037SARM gem5 Developers#ifndef DOXYGEN_SHOULD_SKIP_THIS 39110037SARM gem5 Developers 39210037SARM gem5 Developerstemplate 39310037SARM gem5 DevelopersFault 39410037SARM gem5 DevelopersAtomicSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags); 39510037SARM gem5 Developers 39610037SARM gem5 Developerstemplate 39710037SARM gem5 DevelopersFault 39810037SARM gem5 DevelopersAtomicSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags); 39910037SARM gem5 Developers 40010037SARM gem5 Developerstemplate 40110037SARM gem5 DevelopersFault 40210037SARM gem5 DevelopersAtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags); 40310037SARM gem5 Developers 40410037SARM gem5 Developerstemplate 40510037SARM gem5 DevelopersFault 40610037SARM gem5 DevelopersAtomicSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags); 40710037SARM gem5 Developers 40810037SARM gem5 Developerstemplate 40910037SARM gem5 DevelopersFault 41010037SARM gem5 DevelopersAtomicSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags); 41110037SARM gem5 Developers 41210037SARM gem5 Developerstemplate 41310037SARM gem5 DevelopersFault 41410037SARM gem5 DevelopersAtomicSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags); 41510037SARM gem5 Developers 41610037SARM gem5 Developers#endif //DOXYGEN_SHOULD_SKIP_THIS 41710037SARM gem5 Developers 41810037SARM gem5 Developerstemplate<> 41910037SARM gem5 DevelopersFault 42010037SARM gem5 DevelopersAtomicSimpleCPU::read(Addr addr, double &data, unsigned flags) 42110037SARM gem5 Developers{ 42210037SARM gem5 Developers return read(addr, *(uint64_t*)&data, flags); 42310037SARM gem5 Developers} 42410037SARM gem5 Developers 42510037SARM gem5 Developerstemplate<> 42610037SARM gem5 DevelopersFault 42710037SARM gem5 DevelopersAtomicSimpleCPU::read(Addr addr, float &data, unsigned flags) 42810037SARM gem5 Developers{ 42910417Sandreas.hansson@arm.com return read(addr, *(uint32_t*)&data, flags); 4306019Shines@cs.fsu.edu} 43110037SARM gem5 Developers 43210037SARM gem5 Developers 43310037SARM gem5 Developerstemplate<> 43410037SARM gem5 DevelopersFault 43510037SARM gem5 DevelopersAtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags) 43610037SARM gem5 Developers{ 43710037SARM gem5 Developers return read(addr, (uint32_t&)data, flags); 43810037SARM gem5 Developers} 43910037SARM gem5 Developers 44010037SARM gem5 Developers 44110037SARM gem5 Developerstemplate <class T> 44210037SARM gem5 DevelopersFault 44311578SDylan.Johnson@ARM.comAtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 44411578SDylan.Johnson@ARM.com{ 44510037SARM gem5 Developers // use the CPU's statically allocated write request and packet objects 44610037SARM gem5 Developers Request *req = &data_write_req; 44710037SARM gem5 Developers 44810037SARM gem5 Developers if (traceData) { 44910037SARM gem5 Developers traceData->setAddr(addr); 45010037SARM gem5 Developers traceData->setData(data); 45110037SARM gem5 Developers } 45210037SARM gem5 Developers 45310037SARM gem5 Developers //The block size of our peer. 45410037SARM gem5 Developers unsigned blockSize = dcachePort.peerBlockSize(); 45510037SARM gem5 Developers //The size of the data we're trying to read. 45610037SARM gem5 Developers int dataSize = sizeof(T); 45710037SARM gem5 Developers 45810037SARM gem5 Developers uint8_t * dataPtr = (uint8_t *)&data; 45910037SARM gem5 Developers 46010037SARM gem5 Developers //The address of the second part of this access if it needs to be split 46110037SARM gem5 Developers //across a cache line boundary. 46210037SARM gem5 Developers Addr secondAddr = roundDown(addr + dataSize - 1, blockSize); 4636735Sgblack@eecs.umich.edu 4648782Sgblack@eecs.umich.edu if(secondAddr > addr) 4658782Sgblack@eecs.umich.edu dataSize = secondAddr - addr; 4666735Sgblack@eecs.umich.edu 4676019Shines@cs.fsu.edu dcache_latency = 0; 4686735Sgblack@eecs.umich.edu 46910037SARM gem5 Developers while(1) { 4708303SAli.Saidi@ARM.com req->setVirt(0, addr, dataSize, flags, thread->readPC()); 47110338SCurtis.Dunham@arm.com 47210338SCurtis.Dunham@arm.com // translate to physical address 47310338SCurtis.Dunham@arm.com Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write); 47410338SCurtis.Dunham@arm.com 4758303SAli.Saidi@ARM.com // Now do the access. 4767720Sgblack@eecs.umich.edu if (fault == NoFault) { 4778205SAli.Saidi@ARM.com MemCmd cmd = MemCmd::WriteReq; // default 4788205SAli.Saidi@ARM.com bool do_access = true; // flag to suppress cache access 4798205SAli.Saidi@ARM.com 4806735Sgblack@eecs.umich.edu if (req->isLLSC()) { 48110037SARM gem5 Developers cmd = MemCmd::StoreCondReq; 48210037SARM gem5 Developers do_access = TheISA::handleLockedWrite(thread, req); 48310037SARM gem5 Developers } else if (req->isSwap()) { 48410037SARM gem5 Developers cmd = MemCmd::SwapReq; 48510037SARM gem5 Developers if (req->isCondSwap()) { 48610037SARM gem5 Developers assert(res); 48710037SARM gem5 Developers req->setExtraData(*res); 48810037SARM gem5 Developers } 48910037SARM gem5 Developers } 49010037SARM gem5 Developers 49110037SARM gem5 Developers if (do_access && !req->getFlags().isSet(Request::NO_ACCESS)) { 49210037SARM gem5 Developers Packet pkt = Packet(req, cmd, Packet::Broadcast); 49310037SARM gem5 Developers pkt.dataStatic(dataPtr); 49410037SARM gem5 Developers 49510037SARM gem5 Developers if (req->isMmapedIpr()) { 49610037SARM gem5 Developers dcache_latency += 49710037SARM gem5 Developers TheISA::handleIprWrite(thread->getTC(), &pkt); 49810037SARM gem5 Developers } else { 49910037SARM gem5 Developers //XXX This needs to be outside of the loop in order to 50010037SARM gem5 Developers //work properly for cache line boundary crossing 50110037SARM gem5 Developers //accesses in transendian simulations. 50210037SARM gem5 Developers data = htog(data); 50310037SARM gem5 Developers if (hasPhysMemPort && pkt.getAddr() == physMemAddr) 50410037SARM gem5 Developers dcache_latency += physmemPort.sendAtomic(&pkt); 50510037SARM gem5 Developers else 50610037SARM gem5 Developers dcache_latency += dcachePort.sendAtomic(&pkt); 50710037SARM gem5 Developers } 50810037SARM gem5 Developers dcache_access = true; 50910037SARM gem5 Developers assert(!pkt.isError()); 51010037SARM gem5 Developers 51110037SARM gem5 Developers if (req->isSwap()) { 51210037SARM gem5 Developers assert(res); 51310037SARM gem5 Developers *res = pkt.get<T>(); 51410037SARM gem5 Developers } 51510037SARM gem5 Developers } 51610037SARM gem5 Developers 51710037SARM gem5 Developers if (res && !req->isSwap()) { 51810037SARM gem5 Developers *res = req->getExtraData(); 51910037SARM gem5 Developers } 52010037SARM gem5 Developers } 52110037SARM gem5 Developers 52210037SARM gem5 Developers //If there's a fault or we don't need to access a second cache line, 52310037SARM gem5 Developers //stop now. 52410037SARM gem5 Developers if (fault != NoFault || secondAddr <= addr) 52510037SARM gem5 Developers { 52610037SARM gem5 Developers if (req->isLocked() && fault == NoFault) { 52710037SARM gem5 Developers assert(locked); 52810037SARM gem5 Developers locked = false; 5296735Sgblack@eecs.umich.edu } 5306735Sgblack@eecs.umich.edu if (fault != NoFault && req->isPrefetch()) { 5316735Sgblack@eecs.umich.edu return NoFault; 53210037SARM gem5 Developers } else { 5338518Sgeoffrey.blake@arm.com return fault; 5348518Sgeoffrey.blake@arm.com } 5356735Sgblack@eecs.umich.edu } 53610037SARM gem5 Developers 53710037SARM gem5 Developers /* 53810037SARM gem5 Developers * Set up for accessing the second cache line. 53910037SARM gem5 Developers */ 54010037SARM gem5 Developers 54110037SARM gem5 Developers //Move the pointer we're reading into to the correct location. 54210037SARM gem5 Developers dataPtr += dataSize; 54310037SARM gem5 Developers //Adjust the size to get the remaining bytes. 54410037SARM gem5 Developers dataSize = addr + sizeof(T) - secondAddr; 54510037SARM gem5 Developers //And access the right address. 54610037SARM gem5 Developers addr = secondAddr; 54710037SARM gem5 Developers } 5486735Sgblack@eecs.umich.edu} 5496735Sgblack@eecs.umich.edu 5506735Sgblack@eecs.umich.edu 5516735Sgblack@eecs.umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS 5526735Sgblack@eecs.umich.edu 5536735Sgblack@eecs.umich.edutemplate 5546735Sgblack@eecs.umich.eduFault 5556735Sgblack@eecs.umich.eduAtomicSimpleCPU::write(Twin32_t data, Addr addr, 5566735Sgblack@eecs.umich.edu unsigned flags, uint64_t *res); 55710037SARM gem5 Developers 55810037SARM gem5 Developerstemplate 55910037SARM gem5 DevelopersFault 5606735Sgblack@eecs.umich.eduAtomicSimpleCPU::write(Twin64_t data, Addr addr, 5616735Sgblack@eecs.umich.edu unsigned flags, uint64_t *res); 5626735Sgblack@eecs.umich.edu 5636735Sgblack@eecs.umich.edutemplate 56410037SARM gem5 DevelopersFault 56510037SARM gem5 DevelopersAtomicSimpleCPU::write(uint64_t data, Addr addr, 56610037SARM gem5 Developers unsigned flags, uint64_t *res); 56710037SARM gem5 Developers 56810037SARM gem5 Developerstemplate 56910037SARM gem5 DevelopersFault 57010037SARM gem5 DevelopersAtomicSimpleCPU::write(uint32_t data, Addr addr, 57110037SARM gem5 Developers unsigned flags, uint64_t *res); 57210037SARM gem5 Developers 57310037SARM gem5 Developerstemplate 5746735Sgblack@eecs.umich.eduFault 5756735Sgblack@eecs.umich.eduAtomicSimpleCPU::write(uint16_t data, Addr addr, 5767093Sgblack@eecs.umich.edu unsigned flags, uint64_t *res); 5777093Sgblack@eecs.umich.edu 5787720Sgblack@eecs.umich.edutemplate 5797585SAli.Saidi@arm.comFault 5807720Sgblack@eecs.umich.eduAtomicSimpleCPU::write(uint8_t data, Addr addr, 5817720Sgblack@eecs.umich.edu unsigned flags, uint64_t *res); 5827720Sgblack@eecs.umich.edu 5837720Sgblack@eecs.umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS 5847720Sgblack@eecs.umich.edu 5857720Sgblack@eecs.umich.edutemplate<> 58610037SARM gem5 DevelopersFault 58710037SARM gem5 DevelopersAtomicSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 5887720Sgblack@eecs.umich.edu{ 5896019Shines@cs.fsu.edu return write(*(uint64_t*)&data, addr, flags, res); 5907189Sgblack@eecs.umich.edu} 5917400SAli.Saidi@ARM.com 59210417Sandreas.hansson@arm.comtemplate<> 59310037SARM gem5 DevelopersFault 59410037SARM gem5 DevelopersAtomicSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 59510037SARM gem5 Developers{ 59610037SARM gem5 Developers return write(*(uint32_t*)&data, addr, flags, res); 59710037SARM gem5 Developers} 59810037SARM gem5 Developers 59910037SARM gem5 Developers 60010037SARM gem5 Developerstemplate<> 60111574SCurtis.Dunham@arm.comFault 60211574SCurtis.Dunham@arm.comAtomicSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 60311574SCurtis.Dunham@arm.com{ 60411574SCurtis.Dunham@arm.com return write((uint32_t)data, addr, flags, res); 60511574SCurtis.Dunham@arm.com} 60610037SARM gem5 Developers 60710037SARM gem5 Developers 60810037SARM gem5 Developersvoid 60910037SARM gem5 DevelopersAtomicSimpleCPU::tick() 61010037SARM gem5 Developers{ 61110037SARM gem5 Developers DPRINTF(SimpleCPU, "Tick\n"); 61210037SARM gem5 Developers 61310037SARM gem5 Developers Tick latency = 0; 61410037SARM gem5 Developers 61510037SARM gem5 Developers for (int i = 0; i < width || locked; ++i) { 61610037SARM gem5 Developers numCycles++; 61710037SARM gem5 Developers 61810037SARM gem5 Developers if (!curStaticInst || !curStaticInst->isDelayedCommit()) 61910338SCurtis.Dunham@arm.com checkForInterrupts(); 62010338SCurtis.Dunham@arm.com 62110338SCurtis.Dunham@arm.com checkPcEventQueue(); 62210037SARM gem5 Developers 62310037SARM gem5 Developers Fault fault = NoFault; 62410037SARM gem5 Developers 62510037SARM gem5 Developers bool fromRom = isRomMicroPC(thread->readMicroPC()); 62610037SARM gem5 Developers if (!fromRom && !curMacroStaticInst) { 62710037SARM gem5 Developers setupFetchRequest(&ifetch_req); 62810037SARM gem5 Developers fault = thread->itb->translateAtomic(&ifetch_req, tc, 62910037SARM gem5 Developers BaseTLB::Execute); 63010037SARM gem5 Developers } 63110037SARM gem5 Developers 63210338SCurtis.Dunham@arm.com if (fault == NoFault) { 63310037SARM gem5 Developers Tick icache_latency = 0; 63410037SARM gem5 Developers bool icache_access = false; 63510037SARM gem5 Developers dcache_access = false; // assume no dcache access 63610037SARM gem5 Developers 63710037SARM gem5 Developers if (!fromRom && !curMacroStaticInst) { 63810037SARM gem5 Developers // This is commented out because the predecoder would act like 63910037SARM gem5 Developers // a tiny cache otherwise. It wouldn't be flushed when needed 64010037SARM gem5 Developers // like the I cache. It should be flushed, and when that works 64110037SARM gem5 Developers // this code should be uncommented. 64210037SARM gem5 Developers //Fetch more instruction memory if necessary 64310037SARM gem5 Developers //if(predecoder.needMoreBytes()) 64410037SARM gem5 Developers //{ 64510037SARM gem5 Developers icache_access = true; 64610037SARM gem5 Developers Packet ifetch_pkt = Packet(&ifetch_req, MemCmd::ReadReq, 64710037SARM gem5 Developers Packet::Broadcast); 64810037SARM gem5 Developers ifetch_pkt.dataStatic(&inst); 64910037SARM gem5 Developers 65010037SARM gem5 Developers if (hasPhysMemPort && ifetch_pkt.getAddr() == physMemAddr) 65110037SARM gem5 Developers icache_latency = physmemPort.sendAtomic(&ifetch_pkt); 65210037SARM gem5 Developers else 65310037SARM gem5 Developers icache_latency = icachePort.sendAtomic(&ifetch_pkt); 65410037SARM gem5 Developers 65510037SARM gem5 Developers assert(!ifetch_pkt.isError()); 65610037SARM gem5 Developers 65710037SARM gem5 Developers // ifetch_req is initialized to read the instruction directly 65810037SARM gem5 Developers // into the CPU object's inst field. 65910037SARM gem5 Developers //} 66010037SARM gem5 Developers } 66110037SARM gem5 Developers 66210037SARM gem5 Developers preExecute(); 66310037SARM gem5 Developers 66410037SARM gem5 Developers if (curStaticInst) { 66510037SARM gem5 Developers fault = curStaticInst->execute(this, traceData); 66610037SARM gem5 Developers 66710037SARM gem5 Developers // keep an instruction count 66810037SARM gem5 Developers if (fault == NoFault) 66910037SARM gem5 Developers countInst(); 67010037SARM gem5 Developers else if (traceData) { 67110037SARM gem5 Developers // If there was a fault, we should trace this instruction. 67210037SARM gem5 Developers delete traceData; 67310037SARM gem5 Developers traceData = NULL; 67410037SARM gem5 Developers } 67510037SARM gem5 Developers 67610037SARM gem5 Developers postExecute(); 67710037SARM gem5 Developers } 67810037SARM gem5 Developers 67910037SARM gem5 Developers // @todo remove me after debugging with legion done 68010037SARM gem5 Developers if (curStaticInst && (!curStaticInst->isMicroop() || 68110037SARM gem5 Developers curStaticInst->isFirstMicroop())) 68210417Sandreas.hansson@arm.com instCnt++; 6837400SAli.Saidi@ARM.com 6848782Sgblack@eecs.umich.edu Tick stall_ticks = 0; 68511150Smitch.hayenga@arm.com if (simulate_inst_stalls && icache_access) 6868782Sgblack@eecs.umich.edu stall_ticks += icache_latency; 6878782Sgblack@eecs.umich.edu 68810037SARM gem5 Developers if (simulate_data_stalls && dcache_access) 68910037SARM gem5 Developers stall_ticks += dcache_latency; 69010037SARM gem5 Developers 69110037SARM gem5 Developers if (stall_ticks) { 69210037SARM gem5 Developers Tick stall_cycles = stall_ticks / ticks(1); 69310037SARM gem5 Developers Tick aligned_stall_ticks = ticks(stall_cycles); 69410037SARM gem5 Developers 69510037SARM gem5 Developers if (aligned_stall_ticks < stall_ticks) 69610037SARM gem5 Developers aligned_stall_ticks += 1; 69710037SARM gem5 Developers 69810037SARM gem5 Developers latency += aligned_stall_ticks; 69910037SARM gem5 Developers } 70010037SARM gem5 Developers 70110037SARM gem5 Developers } 70210037SARM gem5 Developers if(fault != NoFault || !stayAtPC) 70310037SARM gem5 Developers advancePC(fault); 70410037SARM gem5 Developers } 70510037SARM gem5 Developers 70610037SARM gem5 Developers // instruction takes at least one cycle 7077400SAli.Saidi@ARM.com if (latency < ticks(1)) 7087400SAli.Saidi@ARM.com latency = ticks(1); 7097189Sgblack@eecs.umich.edu 71010417Sandreas.hansson@arm.com if (_status != Idle) 7117189Sgblack@eecs.umich.edu schedule(tickEvent, curTick + latency); 7128782Sgblack@eecs.umich.edu} 7138782Sgblack@eecs.umich.edu 7148806Sgblack@eecs.umich.edu 7158806Sgblack@eecs.umich.eduvoid 7168806Sgblack@eecs.umich.eduAtomicSimpleCPU::printAddr(Addr a) 7178806Sgblack@eecs.umich.edu{ 7188806Sgblack@eecs.umich.edu dcachePort.printAddr(a); 7198806Sgblack@eecs.umich.edu} 7208806Sgblack@eecs.umich.edu 7218806Sgblack@eecs.umich.edu 7228806Sgblack@eecs.umich.edu//////////////////////////////////////////////////////////////////////// 7238806Sgblack@eecs.umich.edu// 7248806Sgblack@eecs.umich.edu// AtomicSimpleCPU Simulation Object 7257189Sgblack@eecs.umich.edu// 7268806Sgblack@eecs.umich.eduAtomicSimpleCPU * 7278806Sgblack@eecs.umich.eduAtomicSimpleCPUParams::create() 7287189Sgblack@eecs.umich.edu{ 7297189Sgblack@eecs.umich.edu numThreads = 1; 7307189Sgblack@eecs.umich.edu#if !FULL_SYSTEM 73110037SARM gem5 Developers if (workload.size() != 1) 73210037SARM gem5 Developers panic("only one workload allowed"); 73310037SARM gem5 Developers#endif 73410037SARM gem5 Developers return new AtomicSimpleCPU(this); 73510037SARM gem5 Developers} 73610037SARM gem5 Developers