atomic.cc revision 5714
17375Sgblack@eecs.umich.edu/* 27375Sgblack@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 37375Sgblack@eecs.umich.edu * All rights reserved. 47375Sgblack@eecs.umich.edu * 57375Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67375Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77375Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87375Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97375Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107375Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117375Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127375Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137375Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147375Sgblack@eecs.umich.edu * this software without specific prior written permission. 157375Sgblack@eecs.umich.edu * 167375Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177375Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187375Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197375Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207375Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217375Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227375Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237375Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247375Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257375Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267375Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277375Sgblack@eecs.umich.edu * 287375Sgblack@eecs.umich.edu * Authors: Steve Reinhardt 297375Sgblack@eecs.umich.edu */ 307375Sgblack@eecs.umich.edu 317375Sgblack@eecs.umich.edu#include "arch/locked_mem.hh" 327375Sgblack@eecs.umich.edu#include "arch/mmaped_ipr.hh" 337375Sgblack@eecs.umich.edu#include "arch/utility.hh" 347375Sgblack@eecs.umich.edu#include "base/bigint.hh" 357375Sgblack@eecs.umich.edu#include "cpu/exetrace.hh" 367375Sgblack@eecs.umich.edu#include "cpu/simple/atomic.hh" 377375Sgblack@eecs.umich.edu#include "mem/packet.hh" 387375Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 397375Sgblack@eecs.umich.edu#include "params/AtomicSimpleCPU.hh" 407375Sgblack@eecs.umich.edu#include "sim/system.hh" 417375Sgblack@eecs.umich.edu 427375Sgblack@eecs.umich.eduusing namespace std; 437375Sgblack@eecs.umich.eduusing namespace TheISA; 447378Sgblack@eecs.umich.edu 457378Sgblack@eecs.umich.eduAtomicSimpleCPU::TickEvent::TickEvent(AtomicSimpleCPU *c) 467382Sgblack@eecs.umich.edu : Event(CPU_Tick_Pri), cpu(c) 477375Sgblack@eecs.umich.edu{ 487384Sgblack@eecs.umich.edu} 497384Sgblack@eecs.umich.edu 507384Sgblack@eecs.umich.edu 517375Sgblack@eecs.umich.eduvoid 527375Sgblack@eecs.umich.eduAtomicSimpleCPU::TickEvent::process() 537375Sgblack@eecs.umich.edu{ 547375Sgblack@eecs.umich.edu cpu->tick(); 557375Sgblack@eecs.umich.edu} 567375Sgblack@eecs.umich.edu 577375Sgblack@eecs.umich.educonst char * 587375Sgblack@eecs.umich.eduAtomicSimpleCPU::TickEvent::description() const 597375Sgblack@eecs.umich.edu{ 607375Sgblack@eecs.umich.edu return "AtomicSimpleCPU tick"; 617375Sgblack@eecs.umich.edu} 627375Sgblack@eecs.umich.edu 637375Sgblack@eecs.umich.eduPort * 647375Sgblack@eecs.umich.eduAtomicSimpleCPU::getPort(const std::string &if_name, int idx) 657375Sgblack@eecs.umich.edu{ 667375Sgblack@eecs.umich.edu if (if_name == "dcache_port") 677375Sgblack@eecs.umich.edu return &dcachePort; 687375Sgblack@eecs.umich.edu else if (if_name == "icache_port") 697375Sgblack@eecs.umich.edu return &icachePort; 707375Sgblack@eecs.umich.edu else if (if_name == "physmem_port") { 717375Sgblack@eecs.umich.edu hasPhysMemPort = true; 727375Sgblack@eecs.umich.edu return &physmemPort; 737375Sgblack@eecs.umich.edu } 747375Sgblack@eecs.umich.edu else 757375Sgblack@eecs.umich.edu panic("No Such Port\n"); 767375Sgblack@eecs.umich.edu} 777376Sgblack@eecs.umich.edu 787376Sgblack@eecs.umich.eduvoid 797376Sgblack@eecs.umich.eduAtomicSimpleCPU::init() 807375Sgblack@eecs.umich.edu{ 817375Sgblack@eecs.umich.edu BaseCPU::init(); 827378Sgblack@eecs.umich.edu#if FULL_SYSTEM 837378Sgblack@eecs.umich.edu for (int i = 0; i < threadContexts.size(); ++i) { 847378Sgblack@eecs.umich.edu ThreadContext *tc = threadContexts[i]; 857378Sgblack@eecs.umich.edu 867378Sgblack@eecs.umich.edu // initialize CPU, including PC 877378Sgblack@eecs.umich.edu TheISA::initCPU(tc, tc->contextId()); 887378Sgblack@eecs.umich.edu } 897378Sgblack@eecs.umich.edu#endif 907378Sgblack@eecs.umich.edu if (hasPhysMemPort) { 917378Sgblack@eecs.umich.edu bool snoop = false; 927378Sgblack@eecs.umich.edu AddrRangeList pmAddrList; 937378Sgblack@eecs.umich.edu physmemPort.getPeerAddressRanges(pmAddrList, snoop); 947378Sgblack@eecs.umich.edu physMemAddr = *pmAddrList.begin(); 957378Sgblack@eecs.umich.edu } 967378Sgblack@eecs.umich.edu // Atomic doesn't do MT right now, so contextId == threadId 977378Sgblack@eecs.umich.edu ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT 987378Sgblack@eecs.umich.edu data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too 997378Sgblack@eecs.umich.edu data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too 1007378Sgblack@eecs.umich.edu} 1017378Sgblack@eecs.umich.edu 1027378Sgblack@eecs.umich.edubool 1037378Sgblack@eecs.umich.eduAtomicSimpleCPU::CpuPort::recvTiming(PacketPtr pkt) 1047378Sgblack@eecs.umich.edu{ 1057378Sgblack@eecs.umich.edu panic("AtomicSimpleCPU doesn't expect recvTiming callback!"); 1067378Sgblack@eecs.umich.edu return true; 1077378Sgblack@eecs.umich.edu} 1087382Sgblack@eecs.umich.edu 1097382Sgblack@eecs.umich.eduTick 1107382Sgblack@eecs.umich.eduAtomicSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt) 1117382Sgblack@eecs.umich.edu{ 1127382Sgblack@eecs.umich.edu //Snooping a coherence request, just return 1137382Sgblack@eecs.umich.edu return 0; 1147382Sgblack@eecs.umich.edu} 1157382Sgblack@eecs.umich.edu 1167382Sgblack@eecs.umich.eduvoid 1177382Sgblack@eecs.umich.eduAtomicSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt) 1187382Sgblack@eecs.umich.edu{ 1197382Sgblack@eecs.umich.edu //No internal storage to update, just return 1207382Sgblack@eecs.umich.edu return; 1217382Sgblack@eecs.umich.edu} 1227382Sgblack@eecs.umich.edu 1237382Sgblack@eecs.umich.eduvoid 1247382Sgblack@eecs.umich.eduAtomicSimpleCPU::CpuPort::recvStatusChange(Status status) 1257382Sgblack@eecs.umich.edu{ 1267382Sgblack@eecs.umich.edu if (status == RangeChange) { 1277382Sgblack@eecs.umich.edu if (!snoopRangeSent) { 1287384Sgblack@eecs.umich.edu snoopRangeSent = true; 1297384Sgblack@eecs.umich.edu sendStatusChange(Port::RangeChange); 1307384Sgblack@eecs.umich.edu } 1317384Sgblack@eecs.umich.edu return; 1327384Sgblack@eecs.umich.edu } 1337384Sgblack@eecs.umich.edu 1347384Sgblack@eecs.umich.edu panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!"); 1357384Sgblack@eecs.umich.edu} 1367384Sgblack@eecs.umich.edu 1377384Sgblack@eecs.umich.eduvoid 1387384Sgblack@eecs.umich.eduAtomicSimpleCPU::CpuPort::recvRetry() 1397384Sgblack@eecs.umich.edu{ 1407384Sgblack@eecs.umich.edu panic("AtomicSimpleCPU doesn't expect recvRetry callback!"); 1417384Sgblack@eecs.umich.edu} 1427384Sgblack@eecs.umich.edu 1437384Sgblack@eecs.umich.eduvoid 1447384Sgblack@eecs.umich.eduAtomicSimpleCPU::DcachePort::setPeer(Port *port) 1457384Sgblack@eecs.umich.edu{ 1467384Sgblack@eecs.umich.edu Port::setPeer(port); 1477384Sgblack@eecs.umich.edu 1487384Sgblack@eecs.umich.edu#if FULL_SYSTEM 1497384Sgblack@eecs.umich.edu // Update the ThreadContext's memory ports (Functional/Virtual 1507384Sgblack@eecs.umich.edu // Ports) 1517384Sgblack@eecs.umich.edu cpu->tcBase()->connectMemPorts(cpu->tcBase()); 1527384Sgblack@eecs.umich.edu#endif 1537384Sgblack@eecs.umich.edu} 1547384Sgblack@eecs.umich.edu 1557384Sgblack@eecs.umich.eduAtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p) 1567384Sgblack@eecs.umich.edu : BaseSimpleCPU(p), tickEvent(this), width(p->width), 1577384Sgblack@eecs.umich.edu simulate_data_stalls(p->simulate_data_stalls), 1587384Sgblack@eecs.umich.edu simulate_inst_stalls(p->simulate_inst_stalls), 1597384Sgblack@eecs.umich.edu icachePort(name() + "-iport", this), dcachePort(name() + "-iport", this), 1607384Sgblack@eecs.umich.edu physmemPort(name() + "-iport", this), hasPhysMemPort(false) 1617384Sgblack@eecs.umich.edu{ 1627384Sgblack@eecs.umich.edu _status = Idle; 1637384Sgblack@eecs.umich.edu 1647384Sgblack@eecs.umich.edu icachePort.snoopRangeSent = false; 1657384Sgblack@eecs.umich.edu dcachePort.snoopRangeSent = false; 1667384Sgblack@eecs.umich.edu 1677384Sgblack@eecs.umich.edu} 1687384Sgblack@eecs.umich.edu 1697384Sgblack@eecs.umich.edu 1707384Sgblack@eecs.umich.eduAtomicSimpleCPU::~AtomicSimpleCPU() 1717384Sgblack@eecs.umich.edu{ 1727384Sgblack@eecs.umich.edu} 1737384Sgblack@eecs.umich.edu 1747384Sgblack@eecs.umich.eduvoid 1757384Sgblack@eecs.umich.eduAtomicSimpleCPU::serialize(ostream &os) 1767384Sgblack@eecs.umich.edu{ 1777384Sgblack@eecs.umich.edu SimObject::State so_state = SimObject::getState(); 1787386Sgblack@eecs.umich.edu SERIALIZE_ENUM(so_state); 1797386Sgblack@eecs.umich.edu BaseSimpleCPU::serialize(os); 1807386Sgblack@eecs.umich.edu nameOut(os, csprintf("%s.tickEvent", name())); 1817386Sgblack@eecs.umich.edu tickEvent.serialize(os); 1827386Sgblack@eecs.umich.edu} 1837386Sgblack@eecs.umich.edu 1847386Sgblack@eecs.umich.eduvoid 1857386Sgblack@eecs.umich.eduAtomicSimpleCPU::unserialize(Checkpoint *cp, const string §ion) 1867386Sgblack@eecs.umich.edu{ 1877386Sgblack@eecs.umich.edu SimObject::State so_state; 1887386Sgblack@eecs.umich.edu UNSERIALIZE_ENUM(so_state); 1897386Sgblack@eecs.umich.edu BaseSimpleCPU::unserialize(cp, section); 1907386Sgblack@eecs.umich.edu tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); 1917386Sgblack@eecs.umich.edu} 1927386Sgblack@eecs.umich.edu 1937386Sgblack@eecs.umich.eduvoid 1947386Sgblack@eecs.umich.eduAtomicSimpleCPU::resume() 1957386Sgblack@eecs.umich.edu{ 1967386Sgblack@eecs.umich.edu if (_status == Idle || _status == SwitchedOut) 1977386Sgblack@eecs.umich.edu return; 1987386Sgblack@eecs.umich.edu 1997386Sgblack@eecs.umich.edu DPRINTF(SimpleCPU, "Resume\n"); 2007386Sgblack@eecs.umich.edu assert(system->getMemoryMode() == Enums::atomic); 2017386Sgblack@eecs.umich.edu 2027385Sgblack@eecs.umich.edu changeState(SimObject::Running); 2037384Sgblack@eecs.umich.edu if (thread->status() == ThreadContext::Active) { 2047385Sgblack@eecs.umich.edu if (!tickEvent.scheduled()) 2057385Sgblack@eecs.umich.edu schedule(tickEvent, nextCycle()); 2067385Sgblack@eecs.umich.edu } 2077384Sgblack@eecs.umich.edu} 2087384Sgblack@eecs.umich.edu 2097384Sgblack@eecs.umich.eduvoid 2107384Sgblack@eecs.umich.eduAtomicSimpleCPU::switchOut() 2117384Sgblack@eecs.umich.edu{ 2127384Sgblack@eecs.umich.edu assert(_status == Running || _status == Idle); 2137384Sgblack@eecs.umich.edu _status = SwitchedOut; 2147384Sgblack@eecs.umich.edu 2157384Sgblack@eecs.umich.edu tickEvent.squash(); 2167384Sgblack@eecs.umich.edu} 2177384Sgblack@eecs.umich.edu 2187384Sgblack@eecs.umich.edu 2197384Sgblack@eecs.umich.eduvoid 2207384Sgblack@eecs.umich.eduAtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) 2217384Sgblack@eecs.umich.edu{ 2227384Sgblack@eecs.umich.edu BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); 2237384Sgblack@eecs.umich.edu 2247385Sgblack@eecs.umich.edu assert(!tickEvent.scheduled()); 2257385Sgblack@eecs.umich.edu 2267385Sgblack@eecs.umich.edu // if any of this CPU's ThreadContexts are active, mark the CPU as 2277385Sgblack@eecs.umich.edu // running and schedule its tick event. 2287385Sgblack@eecs.umich.edu for (int i = 0; i < threadContexts.size(); ++i) { 2297384Sgblack@eecs.umich.edu ThreadContext *tc = threadContexts[i]; 2307384Sgblack@eecs.umich.edu if (tc->status() == ThreadContext::Active && _status != Running) { 2317384Sgblack@eecs.umich.edu _status = Running; 2327384Sgblack@eecs.umich.edu schedule(tickEvent, nextCycle()); 2337386Sgblack@eecs.umich.edu break; 2347386Sgblack@eecs.umich.edu } 2357386Sgblack@eecs.umich.edu } 2367386Sgblack@eecs.umich.edu if (_status != Running) { 2377386Sgblack@eecs.umich.edu _status = Idle; 2387386Sgblack@eecs.umich.edu } 2397386Sgblack@eecs.umich.edu assert(threadContexts.size() == 1); 2407386Sgblack@eecs.umich.edu ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT 2417386Sgblack@eecs.umich.edu data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too 2427386Sgblack@eecs.umich.edu data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too 2437386Sgblack@eecs.umich.edu} 2447386Sgblack@eecs.umich.edu 2457386Sgblack@eecs.umich.edu 2467386Sgblack@eecs.umich.eduvoid 2477386Sgblack@eecs.umich.eduAtomicSimpleCPU::activateContext(int thread_num, int delay) 2487386Sgblack@eecs.umich.edu{ 2497386Sgblack@eecs.umich.edu DPRINTF(SimpleCPU, "ActivateContext %d (%d cycles)\n", thread_num, delay); 2507386Sgblack@eecs.umich.edu 2517386Sgblack@eecs.umich.edu assert(thread_num == 0); 2527386Sgblack@eecs.umich.edu assert(thread); 2537386Sgblack@eecs.umich.edu 2547386Sgblack@eecs.umich.edu assert(_status == Idle); 2557386Sgblack@eecs.umich.edu assert(!tickEvent.scheduled()); 2567386Sgblack@eecs.umich.edu 2577386Sgblack@eecs.umich.edu notIdleFraction++; 2587386Sgblack@eecs.umich.edu numCycles += tickToCycles(thread->lastActivate - thread->lastSuspend); 2597386Sgblack@eecs.umich.edu 2607386Sgblack@eecs.umich.edu //Make sure ticks are still on multiples of cycles 2617386Sgblack@eecs.umich.edu schedule(tickEvent, nextCycle(curTick + ticks(delay))); 2627386Sgblack@eecs.umich.edu _status = Running; 2637386Sgblack@eecs.umich.edu} 2647386Sgblack@eecs.umich.edu 2657386Sgblack@eecs.umich.edu 2667386Sgblack@eecs.umich.eduvoid 2677386Sgblack@eecs.umich.eduAtomicSimpleCPU::suspendContext(int thread_num) 2687386Sgblack@eecs.umich.edu{ 2697386Sgblack@eecs.umich.edu DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num); 2707386Sgblack@eecs.umich.edu 2717386Sgblack@eecs.umich.edu assert(thread_num == 0); 2727386Sgblack@eecs.umich.edu assert(thread); 2737386Sgblack@eecs.umich.edu 2747386Sgblack@eecs.umich.edu assert(_status == Running); 2757386Sgblack@eecs.umich.edu 2767386Sgblack@eecs.umich.edu // tick event may not be scheduled if this gets called from inside 2777386Sgblack@eecs.umich.edu // an instruction's execution, e.g. "quiesce" 2787386Sgblack@eecs.umich.edu if (tickEvent.scheduled()) 2797386Sgblack@eecs.umich.edu deschedule(tickEvent); 2807386Sgblack@eecs.umich.edu 2817386Sgblack@eecs.umich.edu notIdleFraction--; 2827386Sgblack@eecs.umich.edu _status = Idle; 2837386Sgblack@eecs.umich.edu} 2847386Sgblack@eecs.umich.edu 2857386Sgblack@eecs.umich.edu 2867386Sgblack@eecs.umich.edutemplate <class T> 2877386Sgblack@eecs.umich.eduFault 2887386Sgblack@eecs.umich.eduAtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) 2897386Sgblack@eecs.umich.edu{ 2907386Sgblack@eecs.umich.edu // use the CPU's statically allocated read request and packet objects 2917386Sgblack@eecs.umich.edu Request *req = &data_read_req; 2927386Sgblack@eecs.umich.edu 2937386Sgblack@eecs.umich.edu if (traceData) { 2947386Sgblack@eecs.umich.edu traceData->setAddr(addr); 2957386Sgblack@eecs.umich.edu } 2967386Sgblack@eecs.umich.edu 2977386Sgblack@eecs.umich.edu //The block size of our peer. 2987386Sgblack@eecs.umich.edu int blockSize = dcachePort.peerBlockSize(); 2997386Sgblack@eecs.umich.edu //The size of the data we're trying to read. 3007386Sgblack@eecs.umich.edu int dataSize = sizeof(T); 3017386Sgblack@eecs.umich.edu 3027386Sgblack@eecs.umich.edu uint8_t * dataPtr = (uint8_t *)&data; 3037386Sgblack@eecs.umich.edu 3047386Sgblack@eecs.umich.edu //The address of the second part of this access if it needs to be split 3057386Sgblack@eecs.umich.edu //across a cache line boundary. 3067386Sgblack@eecs.umich.edu Addr secondAddr = roundDown(addr + dataSize - 1, blockSize); 3077386Sgblack@eecs.umich.edu 3087386Sgblack@eecs.umich.edu if(secondAddr > addr) 3097386Sgblack@eecs.umich.edu dataSize = secondAddr - addr; 3107386Sgblack@eecs.umich.edu 3117379Sgblack@eecs.umich.edu dcache_latency = 0; 3127388Sgblack@eecs.umich.edu 3137388Sgblack@eecs.umich.edu while(1) { 3147379Sgblack@eecs.umich.edu req->setVirt(0, addr, dataSize, flags, thread->readPC()); 3157388Sgblack@eecs.umich.edu 3167388Sgblack@eecs.umich.edu // translate to physical address 3177379Sgblack@eecs.umich.edu Fault fault = thread->translateDataReadReq(req); 3187379Sgblack@eecs.umich.edu 3197388Sgblack@eecs.umich.edu // Now do the access. 3207388Sgblack@eecs.umich.edu if (fault == NoFault) { 3217388Sgblack@eecs.umich.edu Packet pkt = Packet(req, 3227388Sgblack@eecs.umich.edu req->isLocked() ? MemCmd::LoadLockedReq : MemCmd::ReadReq, 3237379Sgblack@eecs.umich.edu Packet::Broadcast); 3247382Sgblack@eecs.umich.edu pkt.dataStatic(dataPtr); 3257382Sgblack@eecs.umich.edu 3267382Sgblack@eecs.umich.edu if (req->isMmapedIpr()) 3277382Sgblack@eecs.umich.edu dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt); 3287382Sgblack@eecs.umich.edu else { 3297382Sgblack@eecs.umich.edu if (hasPhysMemPort && pkt.getAddr() == physMemAddr) 3307382Sgblack@eecs.umich.edu dcache_latency += physmemPort.sendAtomic(&pkt); 3317382Sgblack@eecs.umich.edu else 3327382Sgblack@eecs.umich.edu dcache_latency += dcachePort.sendAtomic(&pkt); 3337382Sgblack@eecs.umich.edu } 3347382Sgblack@eecs.umich.edu dcache_access = true; 3357382Sgblack@eecs.umich.edu 3367382Sgblack@eecs.umich.edu assert(!pkt.isError()); 3377379Sgblack@eecs.umich.edu 3387379Sgblack@eecs.umich.edu if (req->isLocked()) { 3397381Sgblack@eecs.umich.edu TheISA::handleLockedRead(thread, req); 3407379Sgblack@eecs.umich.edu } 3417382Sgblack@eecs.umich.edu } 3427379Sgblack@eecs.umich.edu 3437379Sgblack@eecs.umich.edu // This will need a new way to tell if it has a dcache attached. 3447381Sgblack@eecs.umich.edu if (req->isUncacheable()) 3457379Sgblack@eecs.umich.edu recordEvent("Uncached Read"); 3467382Sgblack@eecs.umich.edu 3477379Sgblack@eecs.umich.edu //If there's a fault, return it 3487379Sgblack@eecs.umich.edu if (fault != NoFault) 3497379Sgblack@eecs.umich.edu return fault; 3507379Sgblack@eecs.umich.edu //If we don't need to access a second cache line, stop now. 3517381Sgblack@eecs.umich.edu if (secondAddr <= addr) 3527379Sgblack@eecs.umich.edu { 3537382Sgblack@eecs.umich.edu data = gtoh(data); 3547379Sgblack@eecs.umich.edu if (traceData) { 3557379Sgblack@eecs.umich.edu traceData->setData(data); 3567381Sgblack@eecs.umich.edu } 3577379Sgblack@eecs.umich.edu return fault; 3587382Sgblack@eecs.umich.edu } 3597379Sgblack@eecs.umich.edu 3607379Sgblack@eecs.umich.edu /* 3617379Sgblack@eecs.umich.edu * Set up for accessing the second cache line. 3627379Sgblack@eecs.umich.edu */ 3637379Sgblack@eecs.umich.edu 3647379Sgblack@eecs.umich.edu //Move the pointer we're reading into to the correct location. 3657381Sgblack@eecs.umich.edu dataPtr += dataSize; 3667379Sgblack@eecs.umich.edu //Adjust the size to get the remaining bytes. 3677382Sgblack@eecs.umich.edu dataSize = addr + sizeof(T) - secondAddr; 3687379Sgblack@eecs.umich.edu //And access the right address. 3697379Sgblack@eecs.umich.edu addr = secondAddr; 3707381Sgblack@eecs.umich.edu } 3717379Sgblack@eecs.umich.edu} 3727382Sgblack@eecs.umich.edu 3737379Sgblack@eecs.umich.eduFault 3747379Sgblack@eecs.umich.eduAtomicSimpleCPU::translateDataReadAddr(Addr vaddr, Addr & paddr, 3757379Sgblack@eecs.umich.edu int size, unsigned flags) 3767379Sgblack@eecs.umich.edu{ 3777381Sgblack@eecs.umich.edu // use the CPU's statically allocated read request and packet objects 3787379Sgblack@eecs.umich.edu Request *req = &data_read_req; 3797382Sgblack@eecs.umich.edu 3807379Sgblack@eecs.umich.edu if (traceData) { 3817379Sgblack@eecs.umich.edu traceData->setAddr(vaddr); 3827381Sgblack@eecs.umich.edu } 3837379Sgblack@eecs.umich.edu 3847382Sgblack@eecs.umich.edu //The block size of our peer. 3857379Sgblack@eecs.umich.edu int blockSize = dcachePort.peerBlockSize(); 3867379Sgblack@eecs.umich.edu //The size of the data we're trying to read. 3877379Sgblack@eecs.umich.edu int dataSize = size; 3887379Sgblack@eecs.umich.edu 3897379Sgblack@eecs.umich.edu bool firstTimeThrough = true; 3907379Sgblack@eecs.umich.edu 3917379Sgblack@eecs.umich.edu //The address of the second part of this access if it needs to be split 3927379Sgblack@eecs.umich.edu //across a cache line boundary. 3937386Sgblack@eecs.umich.edu Addr secondAddr = roundDown(vaddr + dataSize - 1, blockSize); 3947379Sgblack@eecs.umich.edu 3957379Sgblack@eecs.umich.edu if(secondAddr > vaddr) 3967379Sgblack@eecs.umich.edu dataSize = secondAddr - vaddr; 3977379Sgblack@eecs.umich.edu 3987382Sgblack@eecs.umich.edu while(1) { 3997382Sgblack@eecs.umich.edu req->setVirt(0, vaddr, dataSize, flags, thread->readPC()); 4007382Sgblack@eecs.umich.edu 4017382Sgblack@eecs.umich.edu // translate to physical address 4027386Sgblack@eecs.umich.edu Fault fault = thread->translateDataReadReq(req); 4037379Sgblack@eecs.umich.edu 4047379Sgblack@eecs.umich.edu //If there's a fault, return it 4057379Sgblack@eecs.umich.edu if (fault != NoFault) 4067386Sgblack@eecs.umich.edu return fault; 4077379Sgblack@eecs.umich.edu 4087379Sgblack@eecs.umich.edu if (firstTimeThrough) { 4097379Sgblack@eecs.umich.edu paddr = req->getPaddr(); 4107379Sgblack@eecs.umich.edu firstTimeThrough = false; 4117382Sgblack@eecs.umich.edu } 4127382Sgblack@eecs.umich.edu 4137382Sgblack@eecs.umich.edu //If we don't need to access a second cache line, stop now. 4147382Sgblack@eecs.umich.edu if (secondAddr <= vaddr) 4157386Sgblack@eecs.umich.edu return fault; 4167379Sgblack@eecs.umich.edu 4177379Sgblack@eecs.umich.edu /* 4187379Sgblack@eecs.umich.edu * Set up for accessing the second cache line. 4197388Sgblack@eecs.umich.edu */ 4207388Sgblack@eecs.umich.edu 4217379Sgblack@eecs.umich.edu //Adjust the size to get the remaining bytes. 4227388Sgblack@eecs.umich.edu dataSize = vaddr + size - secondAddr; 4237382Sgblack@eecs.umich.edu //And access the right address. 4247379Sgblack@eecs.umich.edu vaddr = secondAddr; 4257379Sgblack@eecs.umich.edu } 4267388Sgblack@eecs.umich.edu} 4277388Sgblack@eecs.umich.edu 4287388Sgblack@eecs.umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS 4297388Sgblack@eecs.umich.edu 4307379Sgblack@eecs.umich.edutemplate 4317382Sgblack@eecs.umich.eduFault 4327382Sgblack@eecs.umich.eduAtomicSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags); 4337382Sgblack@eecs.umich.edu 4347382Sgblack@eecs.umich.edutemplate 4357382Sgblack@eecs.umich.eduFault 4367382Sgblack@eecs.umich.eduAtomicSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags); 4377382Sgblack@eecs.umich.edu 4387382Sgblack@eecs.umich.edutemplate 4397382Sgblack@eecs.umich.eduFault 4407382Sgblack@eecs.umich.eduAtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags); 4417382Sgblack@eecs.umich.edu 4427382Sgblack@eecs.umich.edutemplate 4437379Sgblack@eecs.umich.eduFault 4447379Sgblack@eecs.umich.eduAtomicSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags); 4457379Sgblack@eecs.umich.edu 4467379Sgblack@eecs.umich.edutemplate 4477382Sgblack@eecs.umich.eduFault 4487379Sgblack@eecs.umich.eduAtomicSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags); 4497379Sgblack@eecs.umich.edu 4507379Sgblack@eecs.umich.edutemplate 4517379Sgblack@eecs.umich.eduFault 4527382Sgblack@eecs.umich.eduAtomicSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags); 4537379Sgblack@eecs.umich.edu 4547379Sgblack@eecs.umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS 4557379Sgblack@eecs.umich.edu 4567379Sgblack@eecs.umich.edutemplate<> 4577379Sgblack@eecs.umich.eduFault 4587379Sgblack@eecs.umich.eduAtomicSimpleCPU::read(Addr addr, double &data, unsigned flags) 4597382Sgblack@eecs.umich.edu{ 4607379Sgblack@eecs.umich.edu return read(addr, *(uint64_t*)&data, flags); 4617379Sgblack@eecs.umich.edu} 4627379Sgblack@eecs.umich.edu 4637379Sgblack@eecs.umich.edutemplate<> 4647382Sgblack@eecs.umich.eduFault 4657379Sgblack@eecs.umich.eduAtomicSimpleCPU::read(Addr addr, float &data, unsigned flags) 4667379Sgblack@eecs.umich.edu{ 4677379Sgblack@eecs.umich.edu return read(addr, *(uint32_t*)&data, flags); 4687379Sgblack@eecs.umich.edu} 4697379Sgblack@eecs.umich.edu 4707379Sgblack@eecs.umich.edu 4717379Sgblack@eecs.umich.edutemplate<> 4727379Sgblack@eecs.umich.eduFault 4737382Sgblack@eecs.umich.eduAtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags) 4747379Sgblack@eecs.umich.edu{ 4757379Sgblack@eecs.umich.edu return read(addr, (uint32_t&)data, flags); 4767379Sgblack@eecs.umich.edu} 4777379Sgblack@eecs.umich.edu 4787382Sgblack@eecs.umich.edu 4797379Sgblack@eecs.umich.edutemplate <class T> 4807379Sgblack@eecs.umich.eduFault 4817379Sgblack@eecs.umich.eduAtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 4827379Sgblack@eecs.umich.edu{ 4837379Sgblack@eecs.umich.edu // use the CPU's statically allocated write request and packet objects 4847379Sgblack@eecs.umich.edu Request *req = &data_write_req; 4857382Sgblack@eecs.umich.edu 4867379Sgblack@eecs.umich.edu if (traceData) { 4877379Sgblack@eecs.umich.edu traceData->setAddr(addr); 4887379Sgblack@eecs.umich.edu } 4897379Sgblack@eecs.umich.edu 4907382Sgblack@eecs.umich.edu //The block size of our peer. 4917379Sgblack@eecs.umich.edu int blockSize = dcachePort.peerBlockSize(); 4927379Sgblack@eecs.umich.edu //The size of the data we're trying to read. 4937379Sgblack@eecs.umich.edu int dataSize = sizeof(T); 4947379Sgblack@eecs.umich.edu 4957379Sgblack@eecs.umich.edu uint8_t * dataPtr = (uint8_t *)&data; 4967379Sgblack@eecs.umich.edu 4977379Sgblack@eecs.umich.edu //The address of the second part of this access if it needs to be split 4987379Sgblack@eecs.umich.edu //across a cache line boundary. 4997386Sgblack@eecs.umich.edu Addr secondAddr = roundDown(addr + dataSize - 1, blockSize); 5007379Sgblack@eecs.umich.edu 5017379Sgblack@eecs.umich.edu if(secondAddr > addr) 5027379Sgblack@eecs.umich.edu dataSize = secondAddr - addr; 5037379Sgblack@eecs.umich.edu 5047382Sgblack@eecs.umich.edu dcache_latency = 0; 5057382Sgblack@eecs.umich.edu 5067382Sgblack@eecs.umich.edu while(1) { 5077382Sgblack@eecs.umich.edu req->setVirt(0, addr, dataSize, flags, thread->readPC()); 5087386Sgblack@eecs.umich.edu 5097379Sgblack@eecs.umich.edu // translate to physical address 5107379Sgblack@eecs.umich.edu Fault fault = thread->translateDataWriteReq(req); 5117379Sgblack@eecs.umich.edu 5127386Sgblack@eecs.umich.edu // Now do the access. 5137379Sgblack@eecs.umich.edu if (fault == NoFault) { 5147379Sgblack@eecs.umich.edu MemCmd cmd = MemCmd::WriteReq; // default 5157379Sgblack@eecs.umich.edu bool do_access = true; // flag to suppress cache access 5167379Sgblack@eecs.umich.edu 5177382Sgblack@eecs.umich.edu if (req->isLocked()) { 5187382Sgblack@eecs.umich.edu cmd = MemCmd::StoreCondReq; 5197382Sgblack@eecs.umich.edu do_access = TheISA::handleLockedWrite(thread, req); 5207382Sgblack@eecs.umich.edu } else if (req->isSwap()) { 5217386Sgblack@eecs.umich.edu cmd = MemCmd::SwapReq; 5227379Sgblack@eecs.umich.edu if (req->isCondSwap()) { 5237379Sgblack@eecs.umich.edu assert(res); 5247378Sgblack@eecs.umich.edu req->setExtraData(*res); 5257378Sgblack@eecs.umich.edu } 5267378Sgblack@eecs.umich.edu } 5277378Sgblack@eecs.umich.edu 5287378Sgblack@eecs.umich.edu if (do_access) { 5297378Sgblack@eecs.umich.edu Packet pkt = Packet(req, cmd, Packet::Broadcast); 5307378Sgblack@eecs.umich.edu pkt.dataStatic(dataPtr); 5317378Sgblack@eecs.umich.edu 5327378Sgblack@eecs.umich.edu if (req->isMmapedIpr()) { 5337378Sgblack@eecs.umich.edu dcache_latency += 5347378Sgblack@eecs.umich.edu TheISA::handleIprWrite(thread->getTC(), &pkt); 5357378Sgblack@eecs.umich.edu } else { 5367378Sgblack@eecs.umich.edu //XXX This needs to be outside of the loop in order to 5377378Sgblack@eecs.umich.edu //work properly for cache line boundary crossing 5387378Sgblack@eecs.umich.edu //accesses in transendian simulations. 5397378Sgblack@eecs.umich.edu data = htog(data); 5407378Sgblack@eecs.umich.edu if (hasPhysMemPort && pkt.getAddr() == physMemAddr) 5417378Sgblack@eecs.umich.edu dcache_latency += physmemPort.sendAtomic(&pkt); 5427378Sgblack@eecs.umich.edu else 5437378Sgblack@eecs.umich.edu dcache_latency += dcachePort.sendAtomic(&pkt); 5447378Sgblack@eecs.umich.edu } 5457378Sgblack@eecs.umich.edu dcache_access = true; 5467378Sgblack@eecs.umich.edu assert(!pkt.isError()); 5477378Sgblack@eecs.umich.edu 5487378Sgblack@eecs.umich.edu if (req->isSwap()) { 5497378Sgblack@eecs.umich.edu assert(res); 5507378Sgblack@eecs.umich.edu *res = pkt.get<T>(); 5517378Sgblack@eecs.umich.edu } 5527378Sgblack@eecs.umich.edu } 5537378Sgblack@eecs.umich.edu 5547378Sgblack@eecs.umich.edu if (res && !req->isSwap()) { 5557378Sgblack@eecs.umich.edu *res = req->getExtraData(); 5567378Sgblack@eecs.umich.edu } 5577378Sgblack@eecs.umich.edu } 5587378Sgblack@eecs.umich.edu 5597378Sgblack@eecs.umich.edu // This will need a new way to tell if it's hooked up to a cache or not. 5607378Sgblack@eecs.umich.edu if (req->isUncacheable()) 5617378Sgblack@eecs.umich.edu recordEvent("Uncached Write"); 5627378Sgblack@eecs.umich.edu 5637378Sgblack@eecs.umich.edu //If there's a fault or we don't need to access a second cache line, 5647378Sgblack@eecs.umich.edu //stop now. 5657378Sgblack@eecs.umich.edu if (fault != NoFault || secondAddr <= addr) 5667378Sgblack@eecs.umich.edu { 5677378Sgblack@eecs.umich.edu // If the write needs to have a fault on the access, consider 5687378Sgblack@eecs.umich.edu // calling changeStatus() and changing it to "bad addr write" 5697378Sgblack@eecs.umich.edu // or something. 5707378Sgblack@eecs.umich.edu if (traceData) { 5717376Sgblack@eecs.umich.edu traceData->setData(data); 5727376Sgblack@eecs.umich.edu } 5737376Sgblack@eecs.umich.edu return fault; 5747376Sgblack@eecs.umich.edu } 5757376Sgblack@eecs.umich.edu 5767376Sgblack@eecs.umich.edu /* 5777376Sgblack@eecs.umich.edu * Set up for accessing the second cache line. 5787376Sgblack@eecs.umich.edu */ 5797376Sgblack@eecs.umich.edu 5807376Sgblack@eecs.umich.edu //Move the pointer we're reading into to the correct location. 5817376Sgblack@eecs.umich.edu dataPtr += dataSize; 5827376Sgblack@eecs.umich.edu //Adjust the size to get the remaining bytes. 5837376Sgblack@eecs.umich.edu dataSize = addr + sizeof(T) - secondAddr; 5847376Sgblack@eecs.umich.edu //And access the right address. 5857376Sgblack@eecs.umich.edu addr = secondAddr; 5867376Sgblack@eecs.umich.edu } 5877376Sgblack@eecs.umich.edu} 5887376Sgblack@eecs.umich.edu 5897376Sgblack@eecs.umich.eduFault 5907376Sgblack@eecs.umich.eduAtomicSimpleCPU::translateDataWriteAddr(Addr vaddr, Addr &paddr, 5917376Sgblack@eecs.umich.edu int size, unsigned flags) 5927376Sgblack@eecs.umich.edu{ 5937376Sgblack@eecs.umich.edu // use the CPU's statically allocated write request and packet objects 5947376Sgblack@eecs.umich.edu Request *req = &data_write_req; 5957376Sgblack@eecs.umich.edu 5967376Sgblack@eecs.umich.edu if (traceData) { 5977376Sgblack@eecs.umich.edu traceData->setAddr(vaddr); 5987376Sgblack@eecs.umich.edu } 5997376Sgblack@eecs.umich.edu 6007376Sgblack@eecs.umich.edu //The block size of our peer. 6017376Sgblack@eecs.umich.edu int blockSize = dcachePort.peerBlockSize(); 6027376Sgblack@eecs.umich.edu 6037376Sgblack@eecs.umich.edu //The address of the second part of this access if it needs to be split 6047376Sgblack@eecs.umich.edu //across a cache line boundary. 6057376Sgblack@eecs.umich.edu Addr secondAddr = roundDown(vaddr + size - 1, blockSize); 6067376Sgblack@eecs.umich.edu 6077376Sgblack@eecs.umich.edu //The size of the data we're trying to read. 6087376Sgblack@eecs.umich.edu int dataSize = size; 6097376Sgblack@eecs.umich.edu 6107376Sgblack@eecs.umich.edu bool firstTimeThrough = true; 6117376Sgblack@eecs.umich.edu 6127376Sgblack@eecs.umich.edu if(secondAddr > vaddr) 6137376Sgblack@eecs.umich.edu dataSize = secondAddr - vaddr; 6147376Sgblack@eecs.umich.edu 6157376Sgblack@eecs.umich.edu dcache_latency = 0; 6167376Sgblack@eecs.umich.edu 6177376Sgblack@eecs.umich.edu while(1) { 6187376Sgblack@eecs.umich.edu req->setVirt(0, vaddr, dataSize, flags, thread->readPC()); 6197376Sgblack@eecs.umich.edu 6207376Sgblack@eecs.umich.edu // translate to physical address 6217376Sgblack@eecs.umich.edu Fault fault = thread->translateDataWriteReq(req); 6227376Sgblack@eecs.umich.edu 6237376Sgblack@eecs.umich.edu //If there's a fault or we don't need to access a second cache line, 6247376Sgblack@eecs.umich.edu //stop now. 6257376Sgblack@eecs.umich.edu if (fault != NoFault) 6267376Sgblack@eecs.umich.edu return fault; 6277376Sgblack@eecs.umich.edu 6287376Sgblack@eecs.umich.edu if (firstTimeThrough) { 6297376Sgblack@eecs.umich.edu paddr = req->getPaddr(); 6307376Sgblack@eecs.umich.edu firstTimeThrough = false; 6317376Sgblack@eecs.umich.edu } 6327376Sgblack@eecs.umich.edu 6337375Sgblack@eecs.umich.edu if (secondAddr <= vaddr) 6347375Sgblack@eecs.umich.edu return fault; 6357375Sgblack@eecs.umich.edu 6367375Sgblack@eecs.umich.edu /* 6377375Sgblack@eecs.umich.edu * Set up for accessing the second cache line. 6387375Sgblack@eecs.umich.edu */ 6397375Sgblack@eecs.umich.edu 6407375Sgblack@eecs.umich.edu //Adjust the size to get the remaining bytes. 6417375Sgblack@eecs.umich.edu dataSize = vaddr + size - secondAddr; 6427375Sgblack@eecs.umich.edu //And access the right address. 6437375Sgblack@eecs.umich.edu vaddr = secondAddr; 6447375Sgblack@eecs.umich.edu } 6457375Sgblack@eecs.umich.edu} 6467375Sgblack@eecs.umich.edu 6477375Sgblack@eecs.umich.edu 6487375Sgblack@eecs.umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS 6497375Sgblack@eecs.umich.edu 6507375Sgblack@eecs.umich.edutemplate 6517375Sgblack@eecs.umich.eduFault 6527375Sgblack@eecs.umich.eduAtomicSimpleCPU::write(Twin32_t data, Addr addr, 6537375Sgblack@eecs.umich.edu unsigned flags, uint64_t *res); 6547375Sgblack@eecs.umich.edu 6557375Sgblack@eecs.umich.edutemplate 6567375Sgblack@eecs.umich.eduFault 6577375Sgblack@eecs.umich.eduAtomicSimpleCPU::write(Twin64_t data, Addr addr, 6587375Sgblack@eecs.umich.edu unsigned flags, uint64_t *res); 6597375Sgblack@eecs.umich.edu 6607375Sgblack@eecs.umich.edutemplate 6617375Sgblack@eecs.umich.eduFault 6627375Sgblack@eecs.umich.eduAtomicSimpleCPU::write(uint64_t data, Addr addr, 6637375Sgblack@eecs.umich.edu unsigned flags, uint64_t *res); 6647375Sgblack@eecs.umich.edu 6657375Sgblack@eecs.umich.edutemplate 6667375Sgblack@eecs.umich.eduFault 6677375Sgblack@eecs.umich.eduAtomicSimpleCPU::write(uint32_t data, Addr addr, 6687375Sgblack@eecs.umich.edu unsigned flags, uint64_t *res); 6697375Sgblack@eecs.umich.edu 6707375Sgblack@eecs.umich.edutemplate 6717375Sgblack@eecs.umich.eduFault 6727375Sgblack@eecs.umich.eduAtomicSimpleCPU::write(uint16_t data, Addr addr, 6737375Sgblack@eecs.umich.edu unsigned flags, uint64_t *res); 6747375Sgblack@eecs.umich.edu 6757375Sgblack@eecs.umich.edutemplate 6767375Sgblack@eecs.umich.eduFault 6777375Sgblack@eecs.umich.eduAtomicSimpleCPU::write(uint8_t data, Addr addr, 6787375Sgblack@eecs.umich.edu unsigned flags, uint64_t *res); 6797375Sgblack@eecs.umich.edu 6807375Sgblack@eecs.umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS 6817384Sgblack@eecs.umich.edu 6827384Sgblack@eecs.umich.edutemplate<> 6837375Sgblack@eecs.umich.eduFault 684AtomicSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 685{ 686 return write(*(uint64_t*)&data, addr, flags, res); 687} 688 689template<> 690Fault 691AtomicSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 692{ 693 return write(*(uint32_t*)&data, addr, flags, res); 694} 695 696 697template<> 698Fault 699AtomicSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 700{ 701 return write((uint32_t)data, addr, flags, res); 702} 703 704 705void 706AtomicSimpleCPU::tick() 707{ 708 DPRINTF(SimpleCPU, "Tick\n"); 709 710 Tick latency = 0; 711 712 for (int i = 0; i < width; ++i) { 713 numCycles++; 714 715 if (!curStaticInst || !curStaticInst->isDelayedCommit()) 716 checkForInterrupts(); 717 718 checkPcEventQueue(); 719 720 Fault fault = NoFault; 721 722 bool fromRom = isRomMicroPC(thread->readMicroPC()); 723 if (!fromRom) 724 fault = setupFetchRequest(&ifetch_req); 725 726 if (fault == NoFault) { 727 Tick icache_latency = 0; 728 bool icache_access = false; 729 dcache_access = false; // assume no dcache access 730 731 if (!fromRom) { 732 // This is commented out because the predecoder would act like 733 // a tiny cache otherwise. It wouldn't be flushed when needed 734 // like the I cache. It should be flushed, and when that works 735 // this code should be uncommented. 736 //Fetch more instruction memory if necessary 737 //if(predecoder.needMoreBytes()) 738 //{ 739 icache_access = true; 740 Packet ifetch_pkt = Packet(&ifetch_req, MemCmd::ReadReq, 741 Packet::Broadcast); 742 ifetch_pkt.dataStatic(&inst); 743 744 if (hasPhysMemPort && ifetch_pkt.getAddr() == physMemAddr) 745 icache_latency = physmemPort.sendAtomic(&ifetch_pkt); 746 else 747 icache_latency = icachePort.sendAtomic(&ifetch_pkt); 748 749 assert(!ifetch_pkt.isError()); 750 751 // ifetch_req is initialized to read the instruction directly 752 // into the CPU object's inst field. 753 //} 754 } 755 756 preExecute(); 757 758 if (curStaticInst) { 759 fault = curStaticInst->execute(this, traceData); 760 761 // keep an instruction count 762 if (fault == NoFault) 763 countInst(); 764 else if (traceData) { 765 // If there was a fault, we should trace this instruction. 766 delete traceData; 767 traceData = NULL; 768 } 769 770 postExecute(); 771 } 772 773 // @todo remove me after debugging with legion done 774 if (curStaticInst && (!curStaticInst->isMicroop() || 775 curStaticInst->isFirstMicroop())) 776 instCnt++; 777 778 Tick stall_ticks = 0; 779 if (simulate_inst_stalls && icache_access) 780 stall_ticks += icache_latency; 781 782 if (simulate_data_stalls && dcache_access) 783 stall_ticks += dcache_latency; 784 785 if (stall_ticks) { 786 Tick stall_cycles = stall_ticks / ticks(1); 787 Tick aligned_stall_ticks = ticks(stall_cycles); 788 789 if (aligned_stall_ticks < stall_ticks) 790 aligned_stall_ticks += 1; 791 792 latency += aligned_stall_ticks; 793 } 794 795 } 796 if(fault != NoFault || !stayAtPC) 797 advancePC(fault); 798 } 799 800 // instruction takes at least one cycle 801 if (latency < ticks(1)) 802 latency = ticks(1); 803 804 if (_status != Idle) 805 schedule(tickEvent, curTick + latency); 806} 807 808 809void 810AtomicSimpleCPU::printAddr(Addr a) 811{ 812 dcachePort.printAddr(a); 813} 814 815 816//////////////////////////////////////////////////////////////////////// 817// 818// AtomicSimpleCPU Simulation Object 819// 820AtomicSimpleCPU * 821AtomicSimpleCPUParams::create() 822{ 823 numThreads = 1; 824#if !FULL_SYSTEM 825 if (workload.size() != 1) 826 panic("only one workload allowed"); 827#endif 828 return new AtomicSimpleCPU(this); 829} 830