atomic.cc revision 4762
111784Sarthur.perais@inria.fr/* 211784Sarthur.perais@inria.fr * Copyright (c) 2002-2005 The Regents of The University of Michigan 311784Sarthur.perais@inria.fr * All rights reserved. 411784Sarthur.perais@inria.fr * 511784Sarthur.perais@inria.fr * Redistribution and use in source and binary forms, with or without 611784Sarthur.perais@inria.fr * modification, are permitted provided that the following conditions are 711784Sarthur.perais@inria.fr * met: redistributions of source code must retain the above copyright 811784Sarthur.perais@inria.fr * notice, this list of conditions and the following disclaimer; 911784Sarthur.perais@inria.fr * redistributions in binary form must reproduce the above copyright 1011784Sarthur.perais@inria.fr * notice, this list of conditions and the following disclaimer in the 1111784Sarthur.perais@inria.fr * documentation and/or other materials provided with the distribution; 1211784Sarthur.perais@inria.fr * neither the name of the copyright holders nor the names of its 1311784Sarthur.perais@inria.fr * contributors may be used to endorse or promote products derived from 1411784Sarthur.perais@inria.fr * this software without specific prior written permission. 1511784Sarthur.perais@inria.fr * 1611784Sarthur.perais@inria.fr * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1711784Sarthur.perais@inria.fr * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1811784Sarthur.perais@inria.fr * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1911784Sarthur.perais@inria.fr * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2011784Sarthur.perais@inria.fr * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2111784Sarthur.perais@inria.fr * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2211784Sarthur.perais@inria.fr * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2311784Sarthur.perais@inria.fr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2411784Sarthur.perais@inria.fr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2511784Sarthur.perais@inria.fr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2611784Sarthur.perais@inria.fr * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2711784Sarthur.perais@inria.fr * 2811784Sarthur.perais@inria.fr * Authors: Steve Reinhardt 2911784Sarthur.perais@inria.fr */ 3011784Sarthur.perais@inria.fr 3111784Sarthur.perais@inria.fr#include "arch/locked_mem.hh" 3211784Sarthur.perais@inria.fr#include "arch/mmaped_ipr.hh" 3311784Sarthur.perais@inria.fr#include "arch/utility.hh" 3411784Sarthur.perais@inria.fr#include "base/bigint.hh" 3511784Sarthur.perais@inria.fr#include "cpu/exetrace.hh" 3611784Sarthur.perais@inria.fr#include "cpu/simple/atomic.hh" 3711784Sarthur.perais@inria.fr#include "mem/packet.hh" 3811784Sarthur.perais@inria.fr#include "mem/packet_access.hh" 3911784Sarthur.perais@inria.fr#include "params/AtomicSimpleCPU.hh" 4011784Sarthur.perais@inria.fr#include "sim/system.hh" 4111784Sarthur.perais@inria.fr 4211784Sarthur.perais@inria.frusing namespace std; 4311784Sarthur.perais@inria.frusing namespace TheISA; 4411784Sarthur.perais@inria.fr 4511784Sarthur.perais@inria.frAtomicSimpleCPU::TickEvent::TickEvent(AtomicSimpleCPU *c) 4611784Sarthur.perais@inria.fr : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) 4711784Sarthur.perais@inria.fr{ 4811784Sarthur.perais@inria.fr} 4911784Sarthur.perais@inria.fr 5011784Sarthur.perais@inria.fr 5111784Sarthur.perais@inria.frvoid 5211784Sarthur.perais@inria.frAtomicSimpleCPU::TickEvent::process() 5311784Sarthur.perais@inria.fr{ 5411784Sarthur.perais@inria.fr cpu->tick(); 5511784Sarthur.perais@inria.fr} 5611784Sarthur.perais@inria.fr 5711784Sarthur.perais@inria.frconst char * 5811784Sarthur.perais@inria.frAtomicSimpleCPU::TickEvent::description() 5911784Sarthur.perais@inria.fr{ 6011784Sarthur.perais@inria.fr return "AtomicSimpleCPU tick event"; 6111784Sarthur.perais@inria.fr} 6211784Sarthur.perais@inria.fr 6311784Sarthur.perais@inria.frPort * 6411784Sarthur.perais@inria.frAtomicSimpleCPU::getPort(const std::string &if_name, int idx) 6511784Sarthur.perais@inria.fr{ 6611784Sarthur.perais@inria.fr if (if_name == "dcache_port") 6711784Sarthur.perais@inria.fr return &dcachePort; 6811784Sarthur.perais@inria.fr else if (if_name == "icache_port") 6911784Sarthur.perais@inria.fr return &icachePort; 7011784Sarthur.perais@inria.fr else 7111784Sarthur.perais@inria.fr panic("No Such Port\n"); 7211784Sarthur.perais@inria.fr} 7311784Sarthur.perais@inria.fr 7411784Sarthur.perais@inria.frvoid 7511784Sarthur.perais@inria.frAtomicSimpleCPU::init() 7611784Sarthur.perais@inria.fr{ 7711784Sarthur.perais@inria.fr BaseCPU::init(); 7811784Sarthur.perais@inria.fr#if FULL_SYSTEM 7911784Sarthur.perais@inria.fr for (int i = 0; i < threadContexts.size(); ++i) { 8011784Sarthur.perais@inria.fr ThreadContext *tc = threadContexts[i]; 8111784Sarthur.perais@inria.fr 8211784Sarthur.perais@inria.fr // initialize CPU, including PC 8311784Sarthur.perais@inria.fr TheISA::initCPU(tc, tc->readCpuId()); 8411784Sarthur.perais@inria.fr } 8511784Sarthur.perais@inria.fr#endif 8611784Sarthur.perais@inria.fr} 8711784Sarthur.perais@inria.fr 8811784Sarthur.perais@inria.frbool 8911784Sarthur.perais@inria.frAtomicSimpleCPU::CpuPort::recvTiming(PacketPtr pkt) 9011784Sarthur.perais@inria.fr{ 9111784Sarthur.perais@inria.fr panic("AtomicSimpleCPU doesn't expect recvTiming callback!"); 9211784Sarthur.perais@inria.fr return true; 9311784Sarthur.perais@inria.fr} 9411784Sarthur.perais@inria.fr 9511784Sarthur.perais@inria.frTick 9611784Sarthur.perais@inria.frAtomicSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt) 9711784Sarthur.perais@inria.fr{ 9811784Sarthur.perais@inria.fr //Snooping a coherence request, just return 9911784Sarthur.perais@inria.fr return 0; 10011784Sarthur.perais@inria.fr} 10111784Sarthur.perais@inria.fr 10211784Sarthur.perais@inria.frvoid 10311784Sarthur.perais@inria.frAtomicSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt) 10411784Sarthur.perais@inria.fr{ 10511784Sarthur.perais@inria.fr //No internal storage to update, just return 10611784Sarthur.perais@inria.fr return; 10711784Sarthur.perais@inria.fr} 10811784Sarthur.perais@inria.fr 10911784Sarthur.perais@inria.frvoid 11011784Sarthur.perais@inria.frAtomicSimpleCPU::CpuPort::recvStatusChange(Status status) 11111784Sarthur.perais@inria.fr{ 11211784Sarthur.perais@inria.fr if (status == RangeChange) { 11311784Sarthur.perais@inria.fr if (!snoopRangeSent) { 11411784Sarthur.perais@inria.fr snoopRangeSent = true; 11511784Sarthur.perais@inria.fr sendStatusChange(Port::RangeChange); 11611784Sarthur.perais@inria.fr } 11711784Sarthur.perais@inria.fr return; 11811784Sarthur.perais@inria.fr } 11911784Sarthur.perais@inria.fr 12011784Sarthur.perais@inria.fr panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!"); 12111784Sarthur.perais@inria.fr} 12211784Sarthur.perais@inria.fr 12311784Sarthur.perais@inria.frvoid 12411784Sarthur.perais@inria.frAtomicSimpleCPU::CpuPort::recvRetry() 12511784Sarthur.perais@inria.fr{ 12611784Sarthur.perais@inria.fr panic("AtomicSimpleCPU doesn't expect recvRetry callback!"); 12711784Sarthur.perais@inria.fr} 12811784Sarthur.perais@inria.fr 12911784Sarthur.perais@inria.frvoid 13011784Sarthur.perais@inria.frAtomicSimpleCPU::DcachePort::setPeer(Port *port) 13111784Sarthur.perais@inria.fr{ 13211784Sarthur.perais@inria.fr Port::setPeer(port); 13311784Sarthur.perais@inria.fr 13411784Sarthur.perais@inria.fr#if FULL_SYSTEM 13511784Sarthur.perais@inria.fr // Update the ThreadContext's memory ports (Functional/Virtual 13611784Sarthur.perais@inria.fr // Ports) 13711784Sarthur.perais@inria.fr cpu->tcBase()->connectMemPorts(); 13811784Sarthur.perais@inria.fr#endif 13911784Sarthur.perais@inria.fr} 14011784Sarthur.perais@inria.fr 14111784Sarthur.perais@inria.frAtomicSimpleCPU::AtomicSimpleCPU(Params *p) 14211784Sarthur.perais@inria.fr : BaseSimpleCPU(p), tickEvent(this), 14311784Sarthur.perais@inria.fr width(p->width), simulate_stalls(p->simulate_stalls), 14411784Sarthur.perais@inria.fr icachePort(name() + "-iport", this), dcachePort(name() + "-iport", this) 14511784Sarthur.perais@inria.fr{ 14611784Sarthur.perais@inria.fr _status = Idle; 14711784Sarthur.perais@inria.fr 14811784Sarthur.perais@inria.fr icachePort.snoopRangeSent = false; 14911784Sarthur.perais@inria.fr dcachePort.snoopRangeSent = false; 15011784Sarthur.perais@inria.fr 15111784Sarthur.perais@inria.fr ifetch_req = new Request(); 15211784Sarthur.perais@inria.fr ifetch_req->setThreadContext(p->cpu_id, 0); // Add thread ID if we add MT 15311784Sarthur.perais@inria.fr ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); 15411784Sarthur.perais@inria.fr ifetch_pkt->dataStatic(&inst); 15511784Sarthur.perais@inria.fr 15611784Sarthur.perais@inria.fr data_read_req = new Request(); 15711784Sarthur.perais@inria.fr data_read_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too 15811784Sarthur.perais@inria.fr data_read_pkt = new Packet(data_read_req, MemCmd::ReadReq, 15911784Sarthur.perais@inria.fr Packet::Broadcast); 16011784Sarthur.perais@inria.fr data_read_pkt->dataStatic(&dataReg); 16111784Sarthur.perais@inria.fr 16211784Sarthur.perais@inria.fr data_write_req = new Request(); 16311784Sarthur.perais@inria.fr data_write_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too 16411784Sarthur.perais@inria.fr data_write_pkt = new Packet(data_write_req, MemCmd::WriteReq, 16511784Sarthur.perais@inria.fr Packet::Broadcast); 16611784Sarthur.perais@inria.fr data_swap_pkt = new Packet(data_write_req, MemCmd::SwapReq, 16711784Sarthur.perais@inria.fr Packet::Broadcast); 16811784Sarthur.perais@inria.fr} 16911784Sarthur.perais@inria.fr 17011784Sarthur.perais@inria.fr 17111784Sarthur.perais@inria.frAtomicSimpleCPU::~AtomicSimpleCPU() 17211784Sarthur.perais@inria.fr{ 17311784Sarthur.perais@inria.fr} 17411784Sarthur.perais@inria.fr 17511784Sarthur.perais@inria.frvoid 17611784Sarthur.perais@inria.frAtomicSimpleCPU::serialize(ostream &os) 17711784Sarthur.perais@inria.fr{ 17811784Sarthur.perais@inria.fr SimObject::State so_state = SimObject::getState(); 17911784Sarthur.perais@inria.fr SERIALIZE_ENUM(so_state); 18011784Sarthur.perais@inria.fr Status _status = status(); 18111784Sarthur.perais@inria.fr SERIALIZE_ENUM(_status); 18211784Sarthur.perais@inria.fr BaseSimpleCPU::serialize(os); 18311784Sarthur.perais@inria.fr nameOut(os, csprintf("%s.tickEvent", name())); 18411784Sarthur.perais@inria.fr tickEvent.serialize(os); 18511784Sarthur.perais@inria.fr} 18611784Sarthur.perais@inria.fr 18711784Sarthur.perais@inria.frvoid 18811784Sarthur.perais@inria.frAtomicSimpleCPU::unserialize(Checkpoint *cp, const string §ion) 18911784Sarthur.perais@inria.fr{ 19011784Sarthur.perais@inria.fr SimObject::State so_state; 19111784Sarthur.perais@inria.fr UNSERIALIZE_ENUM(so_state); 19211784Sarthur.perais@inria.fr UNSERIALIZE_ENUM(_status); 19311784Sarthur.perais@inria.fr BaseSimpleCPU::unserialize(cp, section); 19411784Sarthur.perais@inria.fr tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); 19511784Sarthur.perais@inria.fr} 19611784Sarthur.perais@inria.fr 19711784Sarthur.perais@inria.frvoid 19811784Sarthur.perais@inria.frAtomicSimpleCPU::resume() 19911784Sarthur.perais@inria.fr{ 20011784Sarthur.perais@inria.fr if (_status != SwitchedOut && _status != Idle) { 20111784Sarthur.perais@inria.fr assert(system->getMemoryMode() == Enums::atomic); 20211784Sarthur.perais@inria.fr 20311784Sarthur.perais@inria.fr changeState(SimObject::Running); 20411784Sarthur.perais@inria.fr if (thread->status() == ThreadContext::Active) { 20511784Sarthur.perais@inria.fr if (!tickEvent.scheduled()) { 20611784Sarthur.perais@inria.fr tickEvent.schedule(nextCycle()); 20711784Sarthur.perais@inria.fr } 20811784Sarthur.perais@inria.fr } 20911784Sarthur.perais@inria.fr } 21011784Sarthur.perais@inria.fr} 21111784Sarthur.perais@inria.fr 21211784Sarthur.perais@inria.frvoid 21311784Sarthur.perais@inria.frAtomicSimpleCPU::switchOut() 21411784Sarthur.perais@inria.fr{ 21511784Sarthur.perais@inria.fr assert(status() == Running || status() == Idle); 21611784Sarthur.perais@inria.fr _status = SwitchedOut; 21711784Sarthur.perais@inria.fr 21811784Sarthur.perais@inria.fr tickEvent.squash(); 21911784Sarthur.perais@inria.fr} 22011784Sarthur.perais@inria.fr 22111784Sarthur.perais@inria.fr 22211784Sarthur.perais@inria.frvoid 22311784Sarthur.perais@inria.frAtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) 22411784Sarthur.perais@inria.fr{ 22511784Sarthur.perais@inria.fr BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); 22611784Sarthur.perais@inria.fr 22711784Sarthur.perais@inria.fr assert(!tickEvent.scheduled()); 22811784Sarthur.perais@inria.fr 22911784Sarthur.perais@inria.fr // if any of this CPU's ThreadContexts are active, mark the CPU as 23011784Sarthur.perais@inria.fr // running and schedule its tick event. 23111784Sarthur.perais@inria.fr for (int i = 0; i < threadContexts.size(); ++i) { 23211784Sarthur.perais@inria.fr ThreadContext *tc = threadContexts[i]; 23311784Sarthur.perais@inria.fr if (tc->status() == ThreadContext::Active && _status != Running) { 23411784Sarthur.perais@inria.fr _status = Running; 23511784Sarthur.perais@inria.fr tickEvent.schedule(nextCycle()); 23611784Sarthur.perais@inria.fr break; 23711784Sarthur.perais@inria.fr } 23811784Sarthur.perais@inria.fr } 23911784Sarthur.perais@inria.fr if (_status != Running) { 24011784Sarthur.perais@inria.fr _status = Idle; 24111784Sarthur.perais@inria.fr } 24211784Sarthur.perais@inria.fr} 24311784Sarthur.perais@inria.fr 24411784Sarthur.perais@inria.fr 24511784Sarthur.perais@inria.frvoid 24611784Sarthur.perais@inria.frAtomicSimpleCPU::activateContext(int thread_num, int delay) 24711784Sarthur.perais@inria.fr{ 24811784Sarthur.perais@inria.fr assert(thread_num == 0); 24911784Sarthur.perais@inria.fr assert(thread); 25011784Sarthur.perais@inria.fr 25111784Sarthur.perais@inria.fr assert(_status == Idle); 25211784Sarthur.perais@inria.fr assert(!tickEvent.scheduled()); 25311784Sarthur.perais@inria.fr 25411784Sarthur.perais@inria.fr notIdleFraction++; 25511784Sarthur.perais@inria.fr 25611784Sarthur.perais@inria.fr //Make sure ticks are still on multiples of cycles 25711784Sarthur.perais@inria.fr tickEvent.schedule(nextCycle(curTick + cycles(delay))); 25811784Sarthur.perais@inria.fr _status = Running; 25911784Sarthur.perais@inria.fr} 26011784Sarthur.perais@inria.fr 26111784Sarthur.perais@inria.fr 26211784Sarthur.perais@inria.frvoid 26311784Sarthur.perais@inria.frAtomicSimpleCPU::suspendContext(int thread_num) 26411784Sarthur.perais@inria.fr{ 26511784Sarthur.perais@inria.fr assert(thread_num == 0); 26611784Sarthur.perais@inria.fr assert(thread); 26711784Sarthur.perais@inria.fr 26811784Sarthur.perais@inria.fr assert(_status == Running); 26911784Sarthur.perais@inria.fr 27011784Sarthur.perais@inria.fr // tick event may not be scheduled if this gets called from inside 27111784Sarthur.perais@inria.fr // an instruction's execution, e.g. "quiesce" 27211784Sarthur.perais@inria.fr if (tickEvent.scheduled()) 27311784Sarthur.perais@inria.fr tickEvent.deschedule(); 27411784Sarthur.perais@inria.fr 27511784Sarthur.perais@inria.fr notIdleFraction--; 27611784Sarthur.perais@inria.fr _status = Idle; 27711784Sarthur.perais@inria.fr} 27811784Sarthur.perais@inria.fr 27911784Sarthur.perais@inria.fr 28011784Sarthur.perais@inria.frtemplate <class T> 28111784Sarthur.perais@inria.frFault 28211784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) 28311784Sarthur.perais@inria.fr{ 28411784Sarthur.perais@inria.fr // use the CPU's statically allocated read request and packet objects 28511784Sarthur.perais@inria.fr Request *req = data_read_req; 28611784Sarthur.perais@inria.fr PacketPtr pkt = data_read_pkt; 28711784Sarthur.perais@inria.fr 28811784Sarthur.perais@inria.fr req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 28911784Sarthur.perais@inria.fr 29011784Sarthur.perais@inria.fr if (traceData) { 29111784Sarthur.perais@inria.fr traceData->setAddr(addr); 29211784Sarthur.perais@inria.fr } 29311784Sarthur.perais@inria.fr 29411784Sarthur.perais@inria.fr // translate to physical address 29511784Sarthur.perais@inria.fr Fault fault = thread->translateDataReadReq(req); 29611784Sarthur.perais@inria.fr 29711784Sarthur.perais@inria.fr // Now do the access. 29811784Sarthur.perais@inria.fr if (fault == NoFault) { 29911784Sarthur.perais@inria.fr pkt->reinitFromRequest(); 30011784Sarthur.perais@inria.fr 30111784Sarthur.perais@inria.fr if (req->isMmapedIpr()) 30211784Sarthur.perais@inria.fr dcache_latency = TheISA::handleIprRead(thread->getTC(),pkt); 30311784Sarthur.perais@inria.fr else 30411784Sarthur.perais@inria.fr dcache_latency = dcachePort.sendAtomic(pkt); 30511784Sarthur.perais@inria.fr dcache_access = true; 30611784Sarthur.perais@inria.fr#if !defined(NDEBUG) 30711784Sarthur.perais@inria.fr if (pkt->result != Packet::Success) 30811784Sarthur.perais@inria.fr panic("Unable to find responder for address pa = %#X va = %#X\n", 30911784Sarthur.perais@inria.fr pkt->req->getPaddr(), pkt->req->getVaddr()); 31011784Sarthur.perais@inria.fr#endif 31111784Sarthur.perais@inria.fr data = pkt->get<T>(); 31211784Sarthur.perais@inria.fr 31311784Sarthur.perais@inria.fr if (req->isLocked()) { 31411784Sarthur.perais@inria.fr TheISA::handleLockedRead(thread, req); 31511784Sarthur.perais@inria.fr } 31611784Sarthur.perais@inria.fr } 31711784Sarthur.perais@inria.fr 31811784Sarthur.perais@inria.fr // This will need a new way to tell if it has a dcache attached. 31911784Sarthur.perais@inria.fr if (req->isUncacheable()) 32011784Sarthur.perais@inria.fr recordEvent("Uncached Read"); 32111784Sarthur.perais@inria.fr 32211784Sarthur.perais@inria.fr return fault; 32311784Sarthur.perais@inria.fr} 32411784Sarthur.perais@inria.fr 32511784Sarthur.perais@inria.fr#ifndef DOXYGEN_SHOULD_SKIP_THIS 32611784Sarthur.perais@inria.fr 32711784Sarthur.perais@inria.frtemplate 32811784Sarthur.perais@inria.frFault 32911784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags); 33011784Sarthur.perais@inria.fr 33111784Sarthur.perais@inria.frtemplate 33211784Sarthur.perais@inria.frFault 33311784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags); 33411784Sarthur.perais@inria.fr 33511784Sarthur.perais@inria.frtemplate 33611784Sarthur.perais@inria.frFault 33711784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags); 33811784Sarthur.perais@inria.fr 33911784Sarthur.perais@inria.frtemplate 34011784Sarthur.perais@inria.frFault 34111784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags); 34211784Sarthur.perais@inria.fr 34311784Sarthur.perais@inria.frtemplate 34411784Sarthur.perais@inria.frFault 34511784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags); 34611784Sarthur.perais@inria.fr 34711784Sarthur.perais@inria.frtemplate 34811784Sarthur.perais@inria.frFault 34911784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags); 35011784Sarthur.perais@inria.fr 35111784Sarthur.perais@inria.fr#endif //DOXYGEN_SHOULD_SKIP_THIS 35211784Sarthur.perais@inria.fr 35311784Sarthur.perais@inria.frtemplate<> 35411784Sarthur.perais@inria.frFault 35511784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, double &data, unsigned flags) 35611784Sarthur.perais@inria.fr{ 35711784Sarthur.perais@inria.fr return read(addr, *(uint64_t*)&data, flags); 35811784Sarthur.perais@inria.fr} 35911784Sarthur.perais@inria.fr 36011784Sarthur.perais@inria.frtemplate<> 36111784Sarthur.perais@inria.frFault 36211784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, float &data, unsigned flags) 36311784Sarthur.perais@inria.fr{ 36411784Sarthur.perais@inria.fr return read(addr, *(uint32_t*)&data, flags); 36511784Sarthur.perais@inria.fr} 36611784Sarthur.perais@inria.fr 36711784Sarthur.perais@inria.fr 36811784Sarthur.perais@inria.frtemplate<> 36911784Sarthur.perais@inria.frFault 37011784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags) 37111784Sarthur.perais@inria.fr{ 37211784Sarthur.perais@inria.fr return read(addr, (uint32_t&)data, flags); 37311784Sarthur.perais@inria.fr} 37411784Sarthur.perais@inria.fr 37511784Sarthur.perais@inria.fr 37611784Sarthur.perais@inria.frtemplate <class T> 37711784Sarthur.perais@inria.frFault 37811784Sarthur.perais@inria.frAtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 37911784Sarthur.perais@inria.fr{ 38011784Sarthur.perais@inria.fr // use the CPU's statically allocated write request and packet objects 38111784Sarthur.perais@inria.fr Request *req = data_write_req; 38211784Sarthur.perais@inria.fr PacketPtr pkt; 38311784Sarthur.perais@inria.fr 38411784Sarthur.perais@inria.fr req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 38511784Sarthur.perais@inria.fr 38611784Sarthur.perais@inria.fr if (req->isSwap()) 38711784Sarthur.perais@inria.fr pkt = data_swap_pkt; 38811784Sarthur.perais@inria.fr else 38911784Sarthur.perais@inria.fr pkt = data_write_pkt; 39011784Sarthur.perais@inria.fr 39111784Sarthur.perais@inria.fr if (traceData) { 39211784Sarthur.perais@inria.fr traceData->setAddr(addr); 39311784Sarthur.perais@inria.fr } 39411784Sarthur.perais@inria.fr 39511784Sarthur.perais@inria.fr // translate to physical address 39611784Sarthur.perais@inria.fr Fault fault = thread->translateDataWriteReq(req); 39711784Sarthur.perais@inria.fr 39811784Sarthur.perais@inria.fr // Now do the access. 39911784Sarthur.perais@inria.fr if (fault == NoFault) { 40011784Sarthur.perais@inria.fr bool do_access = true; // flag to suppress cache access 40111784Sarthur.perais@inria.fr 40211784Sarthur.perais@inria.fr if (req->isLocked()) { 40311784Sarthur.perais@inria.fr do_access = TheISA::handleLockedWrite(thread, req); 40411784Sarthur.perais@inria.fr } 40511784Sarthur.perais@inria.fr if (req->isCondSwap()) { 40611784Sarthur.perais@inria.fr assert(res); 40711784Sarthur.perais@inria.fr req->setExtraData(*res); 40811784Sarthur.perais@inria.fr } 40911784Sarthur.perais@inria.fr 41011784Sarthur.perais@inria.fr 41111784Sarthur.perais@inria.fr if (do_access) { 41211784Sarthur.perais@inria.fr pkt->reinitFromRequest(); 41311784Sarthur.perais@inria.fr pkt->dataStatic(&data); 41411784Sarthur.perais@inria.fr 41511784Sarthur.perais@inria.fr if (req->isMmapedIpr()) { 41611784Sarthur.perais@inria.fr dcache_latency = TheISA::handleIprWrite(thread->getTC(), pkt); 41711784Sarthur.perais@inria.fr } else { 41811784Sarthur.perais@inria.fr data = htog(data); 41911784Sarthur.perais@inria.fr dcache_latency = dcachePort.sendAtomic(pkt); 42011784Sarthur.perais@inria.fr } 42111784Sarthur.perais@inria.fr dcache_access = true; 42211784Sarthur.perais@inria.fr 42311784Sarthur.perais@inria.fr#if !defined(NDEBUG) 42411784Sarthur.perais@inria.fr if (pkt->result != Packet::Success) 42511784Sarthur.perais@inria.fr panic("Unable to find responder for address pa = %#X va = %#X\n", 42611784Sarthur.perais@inria.fr pkt->req->getPaddr(), pkt->req->getVaddr()); 42711784Sarthur.perais@inria.fr#endif 42811784Sarthur.perais@inria.fr } 42911784Sarthur.perais@inria.fr 43011784Sarthur.perais@inria.fr if (req->isSwap()) { 43111784Sarthur.perais@inria.fr assert(res); 43211784Sarthur.perais@inria.fr *res = pkt->get<T>(); 43311784Sarthur.perais@inria.fr } else if (res) { 43411784Sarthur.perais@inria.fr *res = req->getExtraData(); 43511784Sarthur.perais@inria.fr } 43611784Sarthur.perais@inria.fr } 43711784Sarthur.perais@inria.fr 43811784Sarthur.perais@inria.fr // This will need a new way to tell if it's hooked up to a cache or not. 43911784Sarthur.perais@inria.fr if (req->isUncacheable()) 44011784Sarthur.perais@inria.fr recordEvent("Uncached Write"); 44111784Sarthur.perais@inria.fr 44211784Sarthur.perais@inria.fr // If the write needs to have a fault on the access, consider calling 44311784Sarthur.perais@inria.fr // changeStatus() and changing it to "bad addr write" or something. 44411784Sarthur.perais@inria.fr return fault; 44511784Sarthur.perais@inria.fr} 44611784Sarthur.perais@inria.fr 44711784Sarthur.perais@inria.fr 44811784Sarthur.perais@inria.fr#ifndef DOXYGEN_SHOULD_SKIP_THIS 44911784Sarthur.perais@inria.fr 45011784Sarthur.perais@inria.frtemplate 45111784Sarthur.perais@inria.frFault 45211784Sarthur.perais@inria.frAtomicSimpleCPU::write(Twin32_t data, Addr addr, 45311784Sarthur.perais@inria.fr unsigned flags, uint64_t *res); 45411784Sarthur.perais@inria.fr 45511784Sarthur.perais@inria.frtemplate 45611784Sarthur.perais@inria.frFault 45711784Sarthur.perais@inria.frAtomicSimpleCPU::write(Twin64_t data, Addr addr, 45811784Sarthur.perais@inria.fr unsigned flags, uint64_t *res); 45911784Sarthur.perais@inria.fr 46011784Sarthur.perais@inria.frtemplate 46111784Sarthur.perais@inria.frFault 46211784Sarthur.perais@inria.frAtomicSimpleCPU::write(uint64_t data, Addr addr, 46311784Sarthur.perais@inria.fr unsigned flags, uint64_t *res); 46411784Sarthur.perais@inria.fr 46511784Sarthur.perais@inria.frtemplate 46611784Sarthur.perais@inria.frFault 46711784Sarthur.perais@inria.frAtomicSimpleCPU::write(uint32_t data, Addr addr, 46811784Sarthur.perais@inria.fr unsigned flags, uint64_t *res); 46911784Sarthur.perais@inria.fr 47011784Sarthur.perais@inria.frtemplate 47111784Sarthur.perais@inria.frFault 47211784Sarthur.perais@inria.frAtomicSimpleCPU::write(uint16_t data, Addr addr, 47311784Sarthur.perais@inria.fr unsigned flags, uint64_t *res); 47411784Sarthur.perais@inria.fr 47511784Sarthur.perais@inria.frtemplate 47611784Sarthur.perais@inria.frFault 47711784Sarthur.perais@inria.frAtomicSimpleCPU::write(uint8_t data, Addr addr, 47811784Sarthur.perais@inria.fr unsigned flags, uint64_t *res); 47911784Sarthur.perais@inria.fr 48011784Sarthur.perais@inria.fr#endif //DOXYGEN_SHOULD_SKIP_THIS 48111784Sarthur.perais@inria.fr 48211784Sarthur.perais@inria.frtemplate<> 48311784Sarthur.perais@inria.frFault 48411784Sarthur.perais@inria.frAtomicSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 48511784Sarthur.perais@inria.fr{ 48611784Sarthur.perais@inria.fr return write(*(uint64_t*)&data, addr, flags, res); 48711784Sarthur.perais@inria.fr} 48811784Sarthur.perais@inria.fr 48911784Sarthur.perais@inria.frtemplate<> 49011784Sarthur.perais@inria.frFault 49111784Sarthur.perais@inria.frAtomicSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 49211784Sarthur.perais@inria.fr{ 49311784Sarthur.perais@inria.fr return write(*(uint32_t*)&data, addr, flags, res); 49411784Sarthur.perais@inria.fr} 49511784Sarthur.perais@inria.fr 49611784Sarthur.perais@inria.fr 49711784Sarthur.perais@inria.frtemplate<> 49811784Sarthur.perais@inria.frFault 49911784Sarthur.perais@inria.frAtomicSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 50011784Sarthur.perais@inria.fr{ 50111784Sarthur.perais@inria.fr return write((uint32_t)data, addr, flags, res); 50211784Sarthur.perais@inria.fr} 50311784Sarthur.perais@inria.fr 50411784Sarthur.perais@inria.fr 50511784Sarthur.perais@inria.frvoid 50611784Sarthur.perais@inria.frAtomicSimpleCPU::tick() 50711784Sarthur.perais@inria.fr{ 50811784Sarthur.perais@inria.fr Tick latency = cycles(1); // instruction takes one cycle by default 50911784Sarthur.perais@inria.fr 51011784Sarthur.perais@inria.fr for (int i = 0; i < width; ++i) { 51111784Sarthur.perais@inria.fr numCycles++; 51211784Sarthur.perais@inria.fr 51311784Sarthur.perais@inria.fr if (!curStaticInst || !curStaticInst->isDelayedCommit()) 51411784Sarthur.perais@inria.fr checkForInterrupts(); 51511784Sarthur.perais@inria.fr 51611784Sarthur.perais@inria.fr Fault fault = setupFetchRequest(ifetch_req); 51711784Sarthur.perais@inria.fr 51811784Sarthur.perais@inria.fr if (fault == NoFault) { 51911784Sarthur.perais@inria.fr Tick icache_latency = 0; 52011784Sarthur.perais@inria.fr bool icache_access = false; 52111784Sarthur.perais@inria.fr dcache_access = false; // assume no dcache access 52211784Sarthur.perais@inria.fr 52311784Sarthur.perais@inria.fr //Fetch more instruction memory if necessary 52411784Sarthur.perais@inria.fr //if(predecoder.needMoreBytes()) 52511784Sarthur.perais@inria.fr //{ 52611784Sarthur.perais@inria.fr icache_access = true; 52711784Sarthur.perais@inria.fr ifetch_pkt->reinitFromRequest(); 52811784Sarthur.perais@inria.fr 52911784Sarthur.perais@inria.fr icache_latency = icachePort.sendAtomic(ifetch_pkt); 53011784Sarthur.perais@inria.fr // ifetch_req is initialized to read the instruction directly 53111784Sarthur.perais@inria.fr // into the CPU object's inst field. 53211784Sarthur.perais@inria.fr //} 53311784Sarthur.perais@inria.fr 53411784Sarthur.perais@inria.fr preExecute(); 53511784Sarthur.perais@inria.fr 53611784Sarthur.perais@inria.fr if(curStaticInst) 53711784Sarthur.perais@inria.fr { 53811784Sarthur.perais@inria.fr fault = curStaticInst->execute(this, traceData); 53911784Sarthur.perais@inria.fr postExecute(); 54011784Sarthur.perais@inria.fr } 54111784Sarthur.perais@inria.fr 54211784Sarthur.perais@inria.fr // @todo remove me after debugging with legion done 54311784Sarthur.perais@inria.fr if (curStaticInst && (!curStaticInst->isMicroop() || 54411784Sarthur.perais@inria.fr curStaticInst->isFirstMicroop())) 54511784Sarthur.perais@inria.fr instCnt++; 54611784Sarthur.perais@inria.fr 54711784Sarthur.perais@inria.fr if (simulate_stalls) { 54811784Sarthur.perais@inria.fr Tick icache_stall = 54911784Sarthur.perais@inria.fr icache_access ? icache_latency - cycles(1) : 0; 55011784Sarthur.perais@inria.fr Tick dcache_stall = 55111784Sarthur.perais@inria.fr dcache_access ? dcache_latency - cycles(1) : 0; 55211784Sarthur.perais@inria.fr Tick stall_cycles = (icache_stall + dcache_stall) / cycles(1); 55311784Sarthur.perais@inria.fr if (cycles(stall_cycles) < (icache_stall + dcache_stall)) 55411784Sarthur.perais@inria.fr latency += cycles(stall_cycles+1); 55511784Sarthur.perais@inria.fr else 55611784Sarthur.perais@inria.fr latency += cycles(stall_cycles); 55711784Sarthur.perais@inria.fr } 55811784Sarthur.perais@inria.fr 55911784Sarthur.perais@inria.fr } 56011784Sarthur.perais@inria.fr if(fault != NoFault || !stayAtPC) 56111784Sarthur.perais@inria.fr advancePC(fault); 56211784Sarthur.perais@inria.fr } 56311784Sarthur.perais@inria.fr 56411784Sarthur.perais@inria.fr if (_status != Idle) 56511784Sarthur.perais@inria.fr tickEvent.schedule(curTick + latency); 56611784Sarthur.perais@inria.fr} 56711784Sarthur.perais@inria.fr 56811784Sarthur.perais@inria.fr 56911784Sarthur.perais@inria.fr//////////////////////////////////////////////////////////////////////// 57011784Sarthur.perais@inria.fr// 57111784Sarthur.perais@inria.fr// AtomicSimpleCPU Simulation Object 57211784Sarthur.perais@inria.fr// 57311784Sarthur.perais@inria.frAtomicSimpleCPU * 57411784Sarthur.perais@inria.frAtomicSimpleCPUParams::create() 57511784Sarthur.perais@inria.fr{ 57611784Sarthur.perais@inria.fr AtomicSimpleCPU::Params *params = new AtomicSimpleCPU::Params(); 57711784Sarthur.perais@inria.fr params->name = name; 57811784Sarthur.perais@inria.fr params->numberOfThreads = 1; 57911784Sarthur.perais@inria.fr params->max_insts_any_thread = max_insts_any_thread; 58011784Sarthur.perais@inria.fr params->max_insts_all_threads = max_insts_all_threads; 58111784Sarthur.perais@inria.fr params->max_loads_any_thread = max_loads_any_thread; 58211784Sarthur.perais@inria.fr params->max_loads_all_threads = max_loads_all_threads; 58311784Sarthur.perais@inria.fr params->progress_interval = progress_interval; 58411784Sarthur.perais@inria.fr params->deferRegistration = defer_registration; 58511784Sarthur.perais@inria.fr params->phase = phase; 58611784Sarthur.perais@inria.fr params->clock = clock; 58711784Sarthur.perais@inria.fr params->functionTrace = function_trace; 58811784Sarthur.perais@inria.fr params->functionTraceStart = function_trace_start; 58911784Sarthur.perais@inria.fr params->width = width; 59011784Sarthur.perais@inria.fr params->simulate_stalls = simulate_stalls; 59111784Sarthur.perais@inria.fr params->system = system; 59211784Sarthur.perais@inria.fr params->cpu_id = cpu_id; 59311784Sarthur.perais@inria.fr 59411784Sarthur.perais@inria.fr#if FULL_SYSTEM 59511784Sarthur.perais@inria.fr params->itb = itb; 59611784Sarthur.perais@inria.fr params->dtb = dtb; 59711784Sarthur.perais@inria.fr params->profile = profile; 59811784Sarthur.perais@inria.fr params->do_quiesce = do_quiesce; 59911784Sarthur.perais@inria.fr params->do_checkpoint_insts = do_checkpoint_insts; 60011784Sarthur.perais@inria.fr params->do_statistics_insts = do_statistics_insts; 60111784Sarthur.perais@inria.fr#else 60211784Sarthur.perais@inria.fr if (workload.size() != 1) 60311784Sarthur.perais@inria.fr panic("only one workload allowed"); 60411784Sarthur.perais@inria.fr params->process = workload[0]; 60511784Sarthur.perais@inria.fr#endif 60611784Sarthur.perais@inria.fr 60711784Sarthur.perais@inria.fr AtomicSimpleCPU *cpu = new AtomicSimpleCPU(params); 60811784Sarthur.perais@inria.fr return cpu; 60911784Sarthur.perais@inria.fr} 61011784Sarthur.perais@inria.fr