atomic.cc revision 4593
14120Sgblack@eecs.umich.edu/* 28839Sandreas.hansson@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 38839Sandreas.hansson@arm.com * All rights reserved. 48839Sandreas.hansson@arm.com * 58839Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68839Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78839Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88839Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98839Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108839Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118839Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128839Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138839Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 144120Sgblack@eecs.umich.edu * this software without specific prior written permission. 154120Sgblack@eecs.umich.edu * 164120Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227087Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237087Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247087Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254120Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267087Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277087Snate@binkert.org * 287087Snate@binkert.org * Authors: Steve Reinhardt 297087Snate@binkert.org */ 307087Snate@binkert.org 317087Snate@binkert.org#include "arch/locked_mem.hh" 327087Snate@binkert.org#include "arch/mmaped_ipr.hh" 337087Snate@binkert.org#include "arch/utility.hh" 344120Sgblack@eecs.umich.edu#include "base/bigint.hh" 357087Snate@binkert.org#include "cpu/exetrace.hh" 364120Sgblack@eecs.umich.edu#include "cpu/simple/atomic.hh" 374120Sgblack@eecs.umich.edu#include "mem/packet.hh" 384120Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 394120Sgblack@eecs.umich.edu#include "sim/builder.hh" 404120Sgblack@eecs.umich.edu#include "sim/system.hh" 414120Sgblack@eecs.umich.edu 424120Sgblack@eecs.umich.eduusing namespace std; 434120Sgblack@eecs.umich.eduusing namespace TheISA; 444120Sgblack@eecs.umich.edu 454120Sgblack@eecs.umich.eduAtomicSimpleCPU::TickEvent::TickEvent(AtomicSimpleCPU *c) 464120Sgblack@eecs.umich.edu : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) 474120Sgblack@eecs.umich.edu{ 484120Sgblack@eecs.umich.edu} 494120Sgblack@eecs.umich.edu 508839Sandreas.hansson@arm.com 514120Sgblack@eecs.umich.eduvoid 524120Sgblack@eecs.umich.eduAtomicSimpleCPU::TickEvent::process() 534120Sgblack@eecs.umich.edu{ 544120Sgblack@eecs.umich.edu cpu->tick(); 554120Sgblack@eecs.umich.edu} 568229Snate@binkert.org 575086Sgblack@eecs.umich.educonst char * 585655Sgblack@eecs.umich.eduAtomicSimpleCPU::TickEvent::description() 595654Sgblack@eecs.umich.edu{ 605086Sgblack@eecs.umich.edu return "AtomicSimpleCPU tick event"; 618229Snate@binkert.org} 625648Sgblack@eecs.umich.edu 635647Sgblack@eecs.umich.eduPort * 645647Sgblack@eecs.umich.eduAtomicSimpleCPU::getPort(const std::string &if_name, int idx) 655647Sgblack@eecs.umich.edu{ 665647Sgblack@eecs.umich.edu if (if_name == "dcache_port") 675810Sgblack@eecs.umich.edu return &dcachePort; 684120Sgblack@eecs.umich.edu else if (if_name == "icache_port") 699554Sandreas.hansson@arm.com return &icachePort; 709554Sandreas.hansson@arm.com else 715704Snate@binkert.org panic("No Such Port\n"); 725086Sgblack@eecs.umich.edu} 739554Sandreas.hansson@arm.com 749554Sandreas.hansson@arm.comvoid 759807Sstever@gmail.comAtomicSimpleCPU::init() 765086Sgblack@eecs.umich.edu{ 775647Sgblack@eecs.umich.edu BaseCPU::init(); 785654Sgblack@eecs.umich.edu#if FULL_SYSTEM 795647Sgblack@eecs.umich.edu for (int i = 0; i < threadContexts.size(); ++i) { 805654Sgblack@eecs.umich.edu ThreadContext *tc = threadContexts[i]; 815691Sgblack@eecs.umich.edu 825691Sgblack@eecs.umich.edu // initialize CPU, including PC 835691Sgblack@eecs.umich.edu TheISA::initCPU(tc, tc->readCpuId()); 845691Sgblack@eecs.umich.edu } 855691Sgblack@eecs.umich.edu#endif 865691Sgblack@eecs.umich.edu} 875691Sgblack@eecs.umich.edu 885691Sgblack@eecs.umich.edubool 895691Sgblack@eecs.umich.eduAtomicSimpleCPU::CpuPort::recvTiming(PacketPtr pkt) 905691Sgblack@eecs.umich.edu{ 915691Sgblack@eecs.umich.edu panic("AtomicSimpleCPU doesn't expect recvTiming callback!"); 925654Sgblack@eecs.umich.edu return true; 935654Sgblack@eecs.umich.edu} 945654Sgblack@eecs.umich.edu 955647Sgblack@eecs.umich.eduTick 965647Sgblack@eecs.umich.eduAtomicSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt) 975691Sgblack@eecs.umich.edu{ 985691Sgblack@eecs.umich.edu //Snooping a coherence request, just return 995647Sgblack@eecs.umich.edu return 0; 1005691Sgblack@eecs.umich.edu} 1015691Sgblack@eecs.umich.edu 1025647Sgblack@eecs.umich.eduvoid 1035647Sgblack@eecs.umich.eduAtomicSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt) 1045647Sgblack@eecs.umich.edu{ 1055647Sgblack@eecs.umich.edu //No internal storage to update, just return 1065691Sgblack@eecs.umich.edu return; 1075691Sgblack@eecs.umich.edu} 1085691Sgblack@eecs.umich.edu 1095691Sgblack@eecs.umich.eduvoid 1105691Sgblack@eecs.umich.eduAtomicSimpleCPU::CpuPort::recvStatusChange(Status status) 1115647Sgblack@eecs.umich.edu{ 1125647Sgblack@eecs.umich.edu if (status == RangeChange) { 1135647Sgblack@eecs.umich.edu if (!snoopRangeSent) { 1145647Sgblack@eecs.umich.edu snoopRangeSent = true; 1155647Sgblack@eecs.umich.edu sendStatusChange(Port::RangeChange); 1165654Sgblack@eecs.umich.edu } 1175655Sgblack@eecs.umich.edu return; 1185655Sgblack@eecs.umich.edu } 1195655Sgblack@eecs.umich.edu 1205655Sgblack@eecs.umich.edu panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!"); 1215691Sgblack@eecs.umich.edu} 1225655Sgblack@eecs.umich.edu 1235691Sgblack@eecs.umich.eduvoid 1245655Sgblack@eecs.umich.eduAtomicSimpleCPU::CpuPort::recvRetry() 1255691Sgblack@eecs.umich.edu{ 1265655Sgblack@eecs.umich.edu panic("AtomicSimpleCPU doesn't expect recvRetry callback!"); 1275691Sgblack@eecs.umich.edu} 1286050Sgblack@eecs.umich.edu 1296050Sgblack@eecs.umich.eduvoid 1306066Sgblack@eecs.umich.eduAtomicSimpleCPU::DcachePort::setPeer(Port *port) 1315655Sgblack@eecs.umich.edu{ 1325655Sgblack@eecs.umich.edu Port::setPeer(port); 1335655Sgblack@eecs.umich.edu 1345655Sgblack@eecs.umich.edu#if FULL_SYSTEM 1356069Sgblack@eecs.umich.edu // Update the ThreadContext's memory ports (Functional/Virtual 1366069Sgblack@eecs.umich.edu // Ports) 1376069Sgblack@eecs.umich.edu cpu->tcBase()->connectMemPorts(); 1385655Sgblack@eecs.umich.edu#endif 1395654Sgblack@eecs.umich.edu} 1405654Sgblack@eecs.umich.edu 1415654Sgblack@eecs.umich.eduAtomicSimpleCPU::AtomicSimpleCPU(Params *p) 1425654Sgblack@eecs.umich.edu : BaseSimpleCPU(p), tickEvent(this), 1435654Sgblack@eecs.umich.edu width(p->width), simulate_stalls(p->simulate_stalls), 1445654Sgblack@eecs.umich.edu icachePort(name() + "-iport", this), dcachePort(name() + "-iport", this) 1455654Sgblack@eecs.umich.edu{ 1465654Sgblack@eecs.umich.edu _status = Idle; 1475654Sgblack@eecs.umich.edu 1485654Sgblack@eecs.umich.edu icachePort.snoopRangeSent = false; 1495654Sgblack@eecs.umich.edu dcachePort.snoopRangeSent = false; 1505654Sgblack@eecs.umich.edu 1515654Sgblack@eecs.umich.edu ifetch_req = new Request(); 1525654Sgblack@eecs.umich.edu ifetch_req->setThreadContext(p->cpu_id, 0); // Add thread ID if we add MT 1535654Sgblack@eecs.umich.edu ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); 1545654Sgblack@eecs.umich.edu ifetch_pkt->dataStatic(&inst); 1555654Sgblack@eecs.umich.edu 1565654Sgblack@eecs.umich.edu data_read_req = new Request(); 1575654Sgblack@eecs.umich.edu data_read_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too 1585654Sgblack@eecs.umich.edu data_read_pkt = new Packet(data_read_req, MemCmd::ReadReq, 1595654Sgblack@eecs.umich.edu Packet::Broadcast); 1605654Sgblack@eecs.umich.edu data_read_pkt->dataStatic(&dataReg); 1615654Sgblack@eecs.umich.edu 1625654Sgblack@eecs.umich.edu data_write_req = new Request(); 1635654Sgblack@eecs.umich.edu data_write_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too 1645654Sgblack@eecs.umich.edu data_write_pkt = new Packet(data_write_req, MemCmd::WriteReq, 1655654Sgblack@eecs.umich.edu Packet::Broadcast); 1665654Sgblack@eecs.umich.edu data_swap_pkt = new Packet(data_write_req, MemCmd::SwapReq, 1675654Sgblack@eecs.umich.edu Packet::Broadcast); 1685654Sgblack@eecs.umich.edu} 1695654Sgblack@eecs.umich.edu 1705654Sgblack@eecs.umich.edu 1716101Sgblack@eecs.umich.eduAtomicSimpleCPU::~AtomicSimpleCPU() 1725654Sgblack@eecs.umich.edu{ 1735654Sgblack@eecs.umich.edu} 1745654Sgblack@eecs.umich.edu 1755654Sgblack@eecs.umich.eduvoid 1765654Sgblack@eecs.umich.eduAtomicSimpleCPU::serialize(ostream &os) 1776101Sgblack@eecs.umich.edu{ 1785654Sgblack@eecs.umich.edu SimObject::State so_state = SimObject::getState(); 1795654Sgblack@eecs.umich.edu SERIALIZE_ENUM(so_state); 1805654Sgblack@eecs.umich.edu Status _status = status(); 1815654Sgblack@eecs.umich.edu SERIALIZE_ENUM(_status); 1825654Sgblack@eecs.umich.edu BaseSimpleCPU::serialize(os); 18310541Sgabeblack@google.com nameOut(os, csprintf("%s.tickEvent", name())); 1845654Sgblack@eecs.umich.edu tickEvent.serialize(os); 1855654Sgblack@eecs.umich.edu} 1865691Sgblack@eecs.umich.edu 1875691Sgblack@eecs.umich.eduvoid 1885810Sgblack@eecs.umich.eduAtomicSimpleCPU::unserialize(Checkpoint *cp, const string §ion) 1895810Sgblack@eecs.umich.edu{ 1906136Sgblack@eecs.umich.edu SimObject::State so_state; 1916136Sgblack@eecs.umich.edu UNSERIALIZE_ENUM(so_state); 1928851Sandreas.hansson@arm.com UNSERIALIZE_ENUM(_status); 1938922Swilliam.wang@arm.com BaseSimpleCPU::unserialize(cp, section); 1948851Sandreas.hansson@arm.com tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); 1955086Sgblack@eecs.umich.edu} 1968742Sgblack@eecs.umich.edu 1978746Sgblack@eecs.umich.eduvoid 1988746Sgblack@eecs.umich.eduAtomicSimpleCPU::resume() 1995654Sgblack@eecs.umich.edu{ 2005654Sgblack@eecs.umich.edu if (_status != SwitchedOut && _status != Idle) { 2015654Sgblack@eecs.umich.edu assert(system->getMemoryMode() == System::Atomic); 2025647Sgblack@eecs.umich.edu 2035647Sgblack@eecs.umich.edu changeState(SimObject::Running); 2046041Sgblack@eecs.umich.edu if (thread->status() == ThreadContext::Active) { 2055810Sgblack@eecs.umich.edu if (!tickEvent.scheduled()) { 2065647Sgblack@eecs.umich.edu tickEvent.schedule(nextCycle()); 2075647Sgblack@eecs.umich.edu } 2085086Sgblack@eecs.umich.edu } 2095647Sgblack@eecs.umich.edu } 2105647Sgblack@eecs.umich.edu} 2115647Sgblack@eecs.umich.edu 2125654Sgblack@eecs.umich.eduvoid 2136137Sgblack@eecs.umich.eduAtomicSimpleCPU::switchOut() 2146137Sgblack@eecs.umich.edu{ 21511175Sandreas.hansson@arm.com assert(status() == Running || status() == Idle); 2166137Sgblack@eecs.umich.edu _status = SwitchedOut; 2176137Sgblack@eecs.umich.edu 2189807Sstever@gmail.com tickEvent.squash(); 2195654Sgblack@eecs.umich.edu} 22011175Sandreas.hansson@arm.com 22111175Sandreas.hansson@arm.com 22211175Sandreas.hansson@arm.comvoid 22311175Sandreas.hansson@arm.comAtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) 2245647Sgblack@eecs.umich.edu{ 2255691Sgblack@eecs.umich.edu BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); 2265691Sgblack@eecs.umich.edu 2275691Sgblack@eecs.umich.edu assert(!tickEvent.scheduled()); 2285691Sgblack@eecs.umich.edu 2295691Sgblack@eecs.umich.edu // if any of this CPU's ThreadContexts are active, mark the CPU as 2305691Sgblack@eecs.umich.edu // running and schedule its tick event. 2315691Sgblack@eecs.umich.edu for (int i = 0; i < threadContexts.size(); ++i) { 2325691Sgblack@eecs.umich.edu ThreadContext *tc = threadContexts[i]; 2335691Sgblack@eecs.umich.edu if (tc->status() == ThreadContext::Active && _status != Running) { 23411175Sandreas.hansson@arm.com _status = Running; 2355651Sgblack@eecs.umich.edu tickEvent.schedule(nextCycle()); 2369294Sandreas.hansson@arm.com break; 23711175Sandreas.hansson@arm.com } 2385654Sgblack@eecs.umich.edu } 2398839Sandreas.hansson@arm.com if (_status != Running) { 2408922Swilliam.wang@arm.com _status = Idle; 2418839Sandreas.hansson@arm.com } 2428922Swilliam.wang@arm.com} 2438922Swilliam.wang@arm.com 2448922Swilliam.wang@arm.com 2459294Sandreas.hansson@arm.comvoid 24611175Sandreas.hansson@arm.comAtomicSimpleCPU::activateContext(int thread_num, int delay) 2478922Swilliam.wang@arm.com{ 2488922Swilliam.wang@arm.com assert(thread_num == 0); 2498922Swilliam.wang@arm.com assert(thread); 2508922Swilliam.wang@arm.com 2518922Swilliam.wang@arm.com assert(_status == Idle); 2525654Sgblack@eecs.umich.edu assert(!tickEvent.scheduled()); 2535654Sgblack@eecs.umich.edu 2545654Sgblack@eecs.umich.edu notIdleFraction++; 2555654Sgblack@eecs.umich.edu 2565654Sgblack@eecs.umich.edu //Make sure ticks are still on multiples of cycles 2575654Sgblack@eecs.umich.edu tickEvent.schedule(nextCycle(curTick + cycles(delay))); 2585648Sgblack@eecs.umich.edu _status = Running; 2595648Sgblack@eecs.umich.edu} 2605704Snate@binkert.org 2615704Snate@binkert.org 2625647Sgblack@eecs.umich.eduvoid 2635648Sgblack@eecs.umich.eduAtomicSimpleCPU::suspendContext(int thread_num) 2645648Sgblack@eecs.umich.edu{ 2655648Sgblack@eecs.umich.edu assert(thread_num == 0); 2665654Sgblack@eecs.umich.edu assert(thread); 2675654Sgblack@eecs.umich.edu 2685654Sgblack@eecs.umich.edu assert(_status == Running); 2695654Sgblack@eecs.umich.edu 2706041Sgblack@eecs.umich.edu // tick event may not be scheduled if this gets called from inside 2715086Sgblack@eecs.umich.edu // an instruction's execution, e.g. "quiesce" 2725654Sgblack@eecs.umich.edu if (tickEvent.scheduled()) 2735654Sgblack@eecs.umich.edu tickEvent.deschedule(); 2745654Sgblack@eecs.umich.edu 2755651Sgblack@eecs.umich.edu notIdleFraction--; 2765704Snate@binkert.org _status = Idle; 2779874Sandreas@sandberg.pp.se} 2789874Sandreas@sandberg.pp.se 2799874Sandreas@sandberg.pp.se 2809874Sandreas@sandberg.pp.setemplate <class T> 2819874Sandreas@sandberg.pp.seFault 2829874Sandreas@sandberg.pp.seAtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) 2839874Sandreas@sandberg.pp.se{ 28410112Sandreas@sandberg.pp.se // use the CPU's statically allocated read request and packet objects 28510112Sandreas@sandberg.pp.se Request *req = data_read_req; 28610112Sandreas@sandberg.pp.se PacketPtr pkt = data_read_pkt; 28710112Sandreas@sandberg.pp.se 28810112Sandreas@sandberg.pp.se req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 28910112Sandreas@sandberg.pp.se 2905704Snate@binkert.org if (traceData) { 2915704Snate@binkert.org traceData->setAddr(addr); 2925086Sgblack@eecs.umich.edu } 2935654Sgblack@eecs.umich.edu 2945654Sgblack@eecs.umich.edu // translate to physical address 2955654Sgblack@eecs.umich.edu Fault fault = thread->translateDataReadReq(req); 29611168Sandreas.hansson@arm.com 29711168Sandreas.hansson@arm.com // Now do the access. 2985654Sgblack@eecs.umich.edu if (fault == NoFault) { 2995654Sgblack@eecs.umich.edu pkt->reinitFromRequest(); 3005654Sgblack@eecs.umich.edu 3015654Sgblack@eecs.umich.edu if (req->isMmapedIpr()) 3025654Sgblack@eecs.umich.edu dcache_latency = TheISA::handleIprRead(thread->getTC(),pkt); 3035704Snate@binkert.org else 3045704Snate@binkert.org dcache_latency = dcachePort.sendAtomic(pkt); 3055654Sgblack@eecs.umich.edu dcache_access = true; 3065654Sgblack@eecs.umich.edu#if !defined(NDEBUG) 3075654Sgblack@eecs.umich.edu if (pkt->result != Packet::Success) 3085654Sgblack@eecs.umich.edu panic("Unable to find responder for address pa = %#X va = %#X\n", 3095704Snate@binkert.org pkt->req->getPaddr(), pkt->req->getVaddr()); 3105704Snate@binkert.org#endif 3115654Sgblack@eecs.umich.edu data = pkt->get<T>(); 3125654Sgblack@eecs.umich.edu 3135654Sgblack@eecs.umich.edu if (req->isLocked()) { 3145654Sgblack@eecs.umich.edu TheISA::handleLockedRead(thread, req); 3155704Snate@binkert.org } 3165704Snate@binkert.org } 3175654Sgblack@eecs.umich.edu 3185704Snate@binkert.org // This will need a new way to tell if it has a dcache attached. 3195654Sgblack@eecs.umich.edu if (req->isUncacheable()) 3205086Sgblack@eecs.umich.edu recordEvent("Uncached Read"); 3215086Sgblack@eecs.umich.edu 3225704Snate@binkert.org return fault; 3234120Sgblack@eecs.umich.edu} 3244120Sgblack@eecs.umich.edu 325#ifndef DOXYGEN_SHOULD_SKIP_THIS 326 327template 328Fault 329AtomicSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags); 330 331template 332Fault 333AtomicSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags); 334 335template 336Fault 337AtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags); 338 339template 340Fault 341AtomicSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags); 342 343template 344Fault 345AtomicSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags); 346 347template 348Fault 349AtomicSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags); 350 351#endif //DOXYGEN_SHOULD_SKIP_THIS 352 353template<> 354Fault 355AtomicSimpleCPU::read(Addr addr, double &data, unsigned flags) 356{ 357 return read(addr, *(uint64_t*)&data, flags); 358} 359 360template<> 361Fault 362AtomicSimpleCPU::read(Addr addr, float &data, unsigned flags) 363{ 364 return read(addr, *(uint32_t*)&data, flags); 365} 366 367 368template<> 369Fault 370AtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags) 371{ 372 return read(addr, (uint32_t&)data, flags); 373} 374 375 376template <class T> 377Fault 378AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 379{ 380 // use the CPU's statically allocated write request and packet objects 381 Request *req = data_write_req; 382 PacketPtr pkt; 383 384 req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 385 386 if (req->isSwap()) 387 pkt = data_swap_pkt; 388 else 389 pkt = data_write_pkt; 390 391 if (traceData) { 392 traceData->setAddr(addr); 393 } 394 395 // translate to physical address 396 Fault fault = thread->translateDataWriteReq(req); 397 398 // Now do the access. 399 if (fault == NoFault) { 400 bool do_access = true; // flag to suppress cache access 401 402 if (req->isLocked()) { 403 do_access = TheISA::handleLockedWrite(thread, req); 404 } 405 if (req->isCondSwap()) { 406 assert(res); 407 req->setExtraData(*res); 408 } 409 410 411 if (do_access) { 412 pkt->reinitFromRequest(); 413 pkt->dataStatic(&data); 414 415 if (req->isMmapedIpr()) { 416 dcache_latency = TheISA::handleIprWrite(thread->getTC(), pkt); 417 } else { 418 data = htog(data); 419 dcache_latency = dcachePort.sendAtomic(pkt); 420 } 421 dcache_access = true; 422 423#if !defined(NDEBUG) 424 if (pkt->result != Packet::Success) 425 panic("Unable to find responder for address pa = %#X va = %#X\n", 426 pkt->req->getPaddr(), pkt->req->getVaddr()); 427#endif 428 } 429 430 if (req->isSwap()) { 431 assert(res); 432 *res = pkt->get<T>(); 433 } else if (res) { 434 *res = req->getExtraData(); 435 } 436 } 437 438 // This will need a new way to tell if it's hooked up to a cache or not. 439 if (req->isUncacheable()) 440 recordEvent("Uncached Write"); 441 442 // If the write needs to have a fault on the access, consider calling 443 // changeStatus() and changing it to "bad addr write" or something. 444 return fault; 445} 446 447 448#ifndef DOXYGEN_SHOULD_SKIP_THIS 449 450template 451Fault 452AtomicSimpleCPU::write(Twin32_t data, Addr addr, 453 unsigned flags, uint64_t *res); 454 455template 456Fault 457AtomicSimpleCPU::write(Twin64_t data, Addr addr, 458 unsigned flags, uint64_t *res); 459 460template 461Fault 462AtomicSimpleCPU::write(uint64_t data, Addr addr, 463 unsigned flags, uint64_t *res); 464 465template 466Fault 467AtomicSimpleCPU::write(uint32_t data, Addr addr, 468 unsigned flags, uint64_t *res); 469 470template 471Fault 472AtomicSimpleCPU::write(uint16_t data, Addr addr, 473 unsigned flags, uint64_t *res); 474 475template 476Fault 477AtomicSimpleCPU::write(uint8_t data, Addr addr, 478 unsigned flags, uint64_t *res); 479 480#endif //DOXYGEN_SHOULD_SKIP_THIS 481 482template<> 483Fault 484AtomicSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 485{ 486 return write(*(uint64_t*)&data, addr, flags, res); 487} 488 489template<> 490Fault 491AtomicSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 492{ 493 return write(*(uint32_t*)&data, addr, flags, res); 494} 495 496 497template<> 498Fault 499AtomicSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 500{ 501 return write((uint32_t)data, addr, flags, res); 502} 503 504 505void 506AtomicSimpleCPU::tick() 507{ 508 Tick latency = cycles(1); // instruction takes one cycle by default 509 510 for (int i = 0; i < width; ++i) { 511 numCycles++; 512 513 if (!curStaticInst || !curStaticInst->isDelayedCommit()) 514 checkForInterrupts(); 515 516 Fault fault = setupFetchRequest(ifetch_req); 517 518 if (fault == NoFault) { 519 Tick icache_latency = 0; 520 bool icache_access = false; 521 dcache_access = false; // assume no dcache access 522 523 //Fetch more instruction memory if necessary 524 //if(predecoder.needMoreBytes()) 525 //{ 526 icache_access = true; 527 ifetch_pkt->reinitFromRequest(); 528 529 icache_latency = icachePort.sendAtomic(ifetch_pkt); 530 // ifetch_req is initialized to read the instruction directly 531 // into the CPU object's inst field. 532 //} 533 534 preExecute(); 535 536 if(curStaticInst) 537 { 538 fault = curStaticInst->execute(this, traceData); 539 postExecute(); 540 } 541 542 // @todo remove me after debugging with legion done 543 if (curStaticInst && (!curStaticInst->isMicroop() || 544 curStaticInst->isFirstMicroop())) 545 instCnt++; 546 547 if (simulate_stalls) { 548 Tick icache_stall = 549 icache_access ? icache_latency - cycles(1) : 0; 550 Tick dcache_stall = 551 dcache_access ? dcache_latency - cycles(1) : 0; 552 Tick stall_cycles = (icache_stall + dcache_stall) / cycles(1); 553 if (cycles(stall_cycles) < (icache_stall + dcache_stall)) 554 latency += cycles(stall_cycles+1); 555 else 556 latency += cycles(stall_cycles); 557 } 558 559 } 560 if(fault != NoFault || !stayAtPC) 561 advancePC(fault); 562 } 563 564 if (_status != Idle) 565 tickEvent.schedule(curTick + latency); 566} 567 568 569//////////////////////////////////////////////////////////////////////// 570// 571// AtomicSimpleCPU Simulation Object 572// 573BEGIN_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU) 574 575 Param<Counter> max_insts_any_thread; 576 Param<Counter> max_insts_all_threads; 577 Param<Counter> max_loads_any_thread; 578 Param<Counter> max_loads_all_threads; 579 Param<Tick> progress_interval; 580 SimObjectParam<System *> system; 581 Param<int> cpu_id; 582 583#if FULL_SYSTEM 584 SimObjectParam<TheISA::ITB *> itb; 585 SimObjectParam<TheISA::DTB *> dtb; 586 Param<Tick> profile; 587 588 Param<bool> do_quiesce; 589 Param<bool> do_checkpoint_insts; 590 Param<bool> do_statistics_insts; 591#else 592 SimObjectParam<Process *> workload; 593#endif // FULL_SYSTEM 594 595 Param<int> clock; 596 Param<int> phase; 597 598 Param<bool> defer_registration; 599 Param<int> width; 600 Param<bool> function_trace; 601 Param<Tick> function_trace_start; 602 Param<bool> simulate_stalls; 603 604END_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU) 605 606BEGIN_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU) 607 608 INIT_PARAM(max_insts_any_thread, 609 "terminate when any thread reaches this inst count"), 610 INIT_PARAM(max_insts_all_threads, 611 "terminate when all threads have reached this inst count"), 612 INIT_PARAM(max_loads_any_thread, 613 "terminate when any thread reaches this load count"), 614 INIT_PARAM(max_loads_all_threads, 615 "terminate when all threads have reached this load count"), 616 INIT_PARAM(progress_interval, "Progress interval"), 617 INIT_PARAM(system, "system object"), 618 INIT_PARAM(cpu_id, "processor ID"), 619 620#if FULL_SYSTEM 621 INIT_PARAM(itb, "Instruction TLB"), 622 INIT_PARAM(dtb, "Data TLB"), 623 INIT_PARAM(profile, ""), 624 INIT_PARAM(do_quiesce, ""), 625 INIT_PARAM(do_checkpoint_insts, ""), 626 INIT_PARAM(do_statistics_insts, ""), 627#else 628 INIT_PARAM(workload, "processes to run"), 629#endif // FULL_SYSTEM 630 631 INIT_PARAM(clock, "clock speed"), 632 INIT_PARAM_DFLT(phase, "clock phase", 0), 633 INIT_PARAM(defer_registration, "defer system registration (for sampling)"), 634 INIT_PARAM(width, "cpu width"), 635 INIT_PARAM(function_trace, "Enable function trace"), 636 INIT_PARAM(function_trace_start, "Cycle to start function trace"), 637 INIT_PARAM(simulate_stalls, "Simulate cache stall cycles") 638 639END_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU) 640 641 642CREATE_SIM_OBJECT(AtomicSimpleCPU) 643{ 644 AtomicSimpleCPU::Params *params = new AtomicSimpleCPU::Params(); 645 params->name = getInstanceName(); 646 params->numberOfThreads = 1; 647 params->max_insts_any_thread = max_insts_any_thread; 648 params->max_insts_all_threads = max_insts_all_threads; 649 params->max_loads_any_thread = max_loads_any_thread; 650 params->max_loads_all_threads = max_loads_all_threads; 651 params->progress_interval = progress_interval; 652 params->deferRegistration = defer_registration; 653 params->phase = phase; 654 params->clock = clock; 655 params->functionTrace = function_trace; 656 params->functionTraceStart = function_trace_start; 657 params->width = width; 658 params->simulate_stalls = simulate_stalls; 659 params->system = system; 660 params->cpu_id = cpu_id; 661 662#if FULL_SYSTEM 663 params->itb = itb; 664 params->dtb = dtb; 665 params->profile = profile; 666 params->do_quiesce = do_quiesce; 667 params->do_checkpoint_insts = do_checkpoint_insts; 668 params->do_statistics_insts = do_statistics_insts; 669#else 670 params->process = workload; 671#endif 672 673 AtomicSimpleCPU *cpu = new AtomicSimpleCPU(params); 674 return cpu; 675} 676 677REGISTER_SIM_OBJECT("AtomicSimpleCPU", AtomicSimpleCPU) 678 679