timing.cc revision 2630
12650Ssaidi@eecs.umich.edu/* 22650Ssaidi@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 32650Ssaidi@eecs.umich.edu * All rights reserved. 42650Ssaidi@eecs.umich.edu * 52650Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 62650Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are 72650Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright 82650Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 92650Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 102650Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 112650Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution; 122650Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its 132650Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from 142650Ssaidi@eecs.umich.edu * this software without specific prior written permission. 152650Ssaidi@eecs.umich.edu * 162650Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172650Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182650Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192650Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202650Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212650Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222650Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232650Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242650Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252650Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262650Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272650Ssaidi@eecs.umich.edu */ 282650Ssaidi@eecs.umich.edu 294194Ssaidi@eecs.umich.edu#include "arch/utility.hh" 303817Ssaidi@eecs.umich.edu#include "cpu/exetrace.hh" 313817Ssaidi@eecs.umich.edu#include "cpu/simple/timing.hh" 323817Ssaidi@eecs.umich.edu#include "mem/packet_impl.hh" 333817Ssaidi@eecs.umich.edu#include "sim/builder.hh" 343817Ssaidi@eecs.umich.edu 354194Ssaidi@eecs.umich.eduusing namespace std; 362650Ssaidi@eecs.umich.eduusing namespace TheISA; 373817Ssaidi@eecs.umich.edu 383817Ssaidi@eecs.umich.edu 394103Ssaidi@eecs.umich.eduvoid 404103Ssaidi@eecs.umich.eduTimingSimpleCPU::init() 414103Ssaidi@eecs.umich.edu{ 424103Ssaidi@eecs.umich.edu //Create Memory Ports (conect them up) 435531Snate@binkert.org Port *mem_dport = mem->getPort(""); 445531Snate@binkert.org dcachePort.setPeer(mem_dport); 454103Ssaidi@eecs.umich.edu mem_dport->setPeer(&dcachePort); 464103Ssaidi@eecs.umich.edu 475531Snate@binkert.org Port *mem_iport = mem->getPort(""); 484103Ssaidi@eecs.umich.edu icachePort.setPeer(mem_iport); 495531Snate@binkert.org mem_iport->setPeer(&icachePort); 504103Ssaidi@eecs.umich.edu 515531Snate@binkert.org BaseCPU::init(); 524103Ssaidi@eecs.umich.edu#if FULL_SYSTEM 535531Snate@binkert.org for (int i = 0; i < execContexts.size(); ++i) { 544103Ssaidi@eecs.umich.edu ExecContext *xc = execContexts[i]; 554103Ssaidi@eecs.umich.edu 564103Ssaidi@eecs.umich.edu // initialize CPU, including PC 574103Ssaidi@eecs.umich.edu TheISA::initCPU(xc, xc->readCpuId()); 585531Snate@binkert.org } 594103Ssaidi@eecs.umich.edu#endif 605531Snate@binkert.org} 614103Ssaidi@eecs.umich.edu 624103Ssaidi@eecs.umich.eduTick 634103Ssaidi@eecs.umich.eduTimingSimpleCPU::CpuPort::recvAtomic(Packet *pkt) 644103Ssaidi@eecs.umich.edu{ 653817Ssaidi@eecs.umich.edu panic("TimingSimpleCPU doesn't expect recvAtomic callback!"); 664185Ssaidi@eecs.umich.edu return curTick; 672650Ssaidi@eecs.umich.edu} 685531Snate@binkert.org 695531Snate@binkert.orgvoid 702650Ssaidi@eecs.umich.eduTimingSimpleCPU::CpuPort::recvFunctional(Packet *pkt) 712650Ssaidi@eecs.umich.edu{ 722982Sstever@eecs.umich.edu panic("TimingSimpleCPU doesn't expect recvFunctional callback!"); 733919Shsul@eecs.umich.edu} 744172Ssaidi@eecs.umich.edu 754103Ssaidi@eecs.umich.eduvoid 763919Shsul@eecs.umich.eduTimingSimpleCPU::CpuPort::recvStatusChange(Status status) 773919Shsul@eecs.umich.edu{ 784172Ssaidi@eecs.umich.edu panic("TimingSimpleCPU doesn't expect recvStatusChange callback!"); 793919Shsul@eecs.umich.edu} 804172Ssaidi@eecs.umich.edu 812650Ssaidi@eecs.umich.eduTimingSimpleCPU::TimingSimpleCPU(Params *p) 823919Shsul@eecs.umich.edu : BaseSimpleCPU(p), icachePort(this), dcachePort(this) 833919Shsul@eecs.umich.edu{ 843919Shsul@eecs.umich.edu _status = Idle; 854172Ssaidi@eecs.umich.edu ifetch_pkt = dcache_pkt = NULL; 864103Ssaidi@eecs.umich.edu} 875606Snate@binkert.org 883919Shsul@eecs.umich.edu 894103Ssaidi@eecs.umich.eduTimingSimpleCPU::~TimingSimpleCPU() 904103Ssaidi@eecs.umich.edu{ 915606Snate@binkert.org} 925606Snate@binkert.org 934103Ssaidi@eecs.umich.eduvoid 943919Shsul@eecs.umich.eduTimingSimpleCPU::serialize(ostream &os) 953919Shsul@eecs.umich.edu{ 962650Ssaidi@eecs.umich.edu BaseSimpleCPU::serialize(os); 973919Shsul@eecs.umich.edu SERIALIZE_ENUM(_status); 983919Shsul@eecs.umich.edu} 993919Shsul@eecs.umich.edu 1004172Ssaidi@eecs.umich.eduvoid 1013919Shsul@eecs.umich.eduTimingSimpleCPU::unserialize(Checkpoint *cp, const string §ion) 1025606Snate@binkert.org{ 1033919Shsul@eecs.umich.edu BaseSimpleCPU::unserialize(cp, section); 1045531Snate@binkert.org UNSERIALIZE_ENUM(_status); 1054103Ssaidi@eecs.umich.edu} 1064103Ssaidi@eecs.umich.edu 1075606Snate@binkert.orgvoid 1085606Snate@binkert.orgTimingSimpleCPU::switchOut(Sampler *s) 1094103Ssaidi@eecs.umich.edu{ 1103919Shsul@eecs.umich.edu sampler = s; 1113919Shsul@eecs.umich.edu if (status() == Running) { 1122650Ssaidi@eecs.umich.edu _status = SwitchedOut; 1133919Shsul@eecs.umich.edu } 1144172Ssaidi@eecs.umich.edu sampler->signalSwitched(); 1153827Shsul@eecs.umich.edu} 1163919Shsul@eecs.umich.edu 1174172Ssaidi@eecs.umich.edu 1184103Ssaidi@eecs.umich.eduvoid 1193919Shsul@eecs.umich.eduTimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) 1202650Ssaidi@eecs.umich.edu{ 1213919Shsul@eecs.umich.edu BaseCPU::takeOverFrom(oldCPU); 1223919Shsul@eecs.umich.edu 1232650Ssaidi@eecs.umich.edu // if any of this CPU's ExecContexts are active, mark the CPU as 1243921Shsul@eecs.umich.edu // running and schedule its tick event. 1254172Ssaidi@eecs.umich.edu for (int i = 0; i < execContexts.size(); ++i) { 1264103Ssaidi@eecs.umich.edu ExecContext *xc = execContexts[i]; 1275531Snate@binkert.org if (xc->status() == ExecContext::Active && _status != Running) { 1284103Ssaidi@eecs.umich.edu _status = Running; 1295531Snate@binkert.org break; 1304103Ssaidi@eecs.umich.edu } 1313921Shsul@eecs.umich.edu } 1323919Shsul@eecs.umich.edu} 1333919Shsul@eecs.umich.edu 1344172Ssaidi@eecs.umich.edu 1353919Shsul@eecs.umich.eduvoid 1362650Ssaidi@eecs.umich.eduTimingSimpleCPU::activateContext(int thread_num, int delay) 1373919Shsul@eecs.umich.edu{ 1383919Shsul@eecs.umich.edu assert(thread_num == 0); 1394172Ssaidi@eecs.umich.edu assert(cpuXC); 1404103Ssaidi@eecs.umich.edu 1415531Snate@binkert.org assert(_status == Idle); 1424103Ssaidi@eecs.umich.edu 1435531Snate@binkert.org notIdleFraction++; 1444103Ssaidi@eecs.umich.edu _status = Running; 1453919Shsul@eecs.umich.edu // kick things off by initiating the fetch of the next instruction 1463919Shsul@eecs.umich.edu Event *e = 1474172Ssaidi@eecs.umich.edu new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, true); 1484103Ssaidi@eecs.umich.edu e->schedule(curTick + cycles(delay)); 1495531Snate@binkert.org} 1504103Ssaidi@eecs.umich.edu 1515531Snate@binkert.org 1524103Ssaidi@eecs.umich.eduvoid 1533919Shsul@eecs.umich.eduTimingSimpleCPU::suspendContext(int thread_num) 1543919Shsul@eecs.umich.edu{ 1554172Ssaidi@eecs.umich.edu assert(thread_num == 0); 1564103Ssaidi@eecs.umich.edu assert(cpuXC); 1575531Snate@binkert.org 1584103Ssaidi@eecs.umich.edu panic("TimingSimpleCPU::suspendContext not implemented"); 1595531Snate@binkert.org 1604103Ssaidi@eecs.umich.edu assert(_status == Running); 1613919Shsul@eecs.umich.edu 1623919Shsul@eecs.umich.edu notIdleFraction--; 1634172Ssaidi@eecs.umich.edu _status = Idle; 1644103Ssaidi@eecs.umich.edu} 1653919Shsul@eecs.umich.edu 1663828Shsul@eecs.umich.edu 1673919Shsul@eecs.umich.edutemplate <class T> 1683919Shsul@eecs.umich.eduFault 1693919Shsul@eecs.umich.eduTimingSimpleCPU::read(Addr addr, T &data, unsigned flags) 1704172Ssaidi@eecs.umich.edu{ 1713919Shsul@eecs.umich.edu Request *data_read_req = new Request(true); 1725606Snate@binkert.org 1733919Shsul@eecs.umich.edu data_read_req->setVaddr(addr); 1745531Snate@binkert.org data_read_req->setSize(sizeof(T)); 1754103Ssaidi@eecs.umich.edu data_read_req->setFlags(flags); 1764103Ssaidi@eecs.umich.edu data_read_req->setTime(curTick); 1775606Snate@binkert.org 1785606Snate@binkert.org if (traceData) { 1794103Ssaidi@eecs.umich.edu traceData->setAddr(data_read_req->getVaddr()); 1803919Shsul@eecs.umich.edu } 1813919Shsul@eecs.umich.edu 1823817Ssaidi@eecs.umich.edu // translate to physical address 1833919Shsul@eecs.umich.edu Fault fault = cpuXC->translateDataReadReq(data_read_req); 1843919Shsul@eecs.umich.edu 1854172Ssaidi@eecs.umich.edu // Now do the access. 1864103Ssaidi@eecs.umich.edu if (fault == NoFault) { 1874103Ssaidi@eecs.umich.edu Packet *data_read_pkt = new Packet; 1885531Snate@binkert.org data_read_pkt->cmd = Read; 1894103Ssaidi@eecs.umich.edu data_read_pkt->req = data_read_req; 1905531Snate@binkert.org data_read_pkt->dataDynamic<T>(new T); 1914103Ssaidi@eecs.umich.edu data_read_pkt->addr = data_read_req->getPaddr(); 1923919Shsul@eecs.umich.edu data_read_pkt->size = sizeof(T); 1933919Shsul@eecs.umich.edu data_read_pkt->dest = Packet::Broadcast; 1944194Ssaidi@eecs.umich.edu 1954194Ssaidi@eecs.umich.edu if (!dcachePort.sendTiming(data_read_pkt)) { 1964194Ssaidi@eecs.umich.edu _status = DcacheRetry; 1973919Shsul@eecs.umich.edu dcache_pkt = data_read_pkt; 1984194Ssaidi@eecs.umich.edu } else { 1994194Ssaidi@eecs.umich.edu _status = DcacheWaitResponse; 2004194Ssaidi@eecs.umich.edu dcache_pkt = NULL; 2014194Ssaidi@eecs.umich.edu } 2024216Ssaidi@eecs.umich.edu } 2034194Ssaidi@eecs.umich.edu 2044194Ssaidi@eecs.umich.edu // This will need a new way to tell if it has a dcache attached. 2054194Ssaidi@eecs.umich.edu if (data_read_req->getFlags() & UNCACHEABLE) 2064194Ssaidi@eecs.umich.edu recordEvent("Uncached Read"); 2075531Snate@binkert.org 2083919Shsul@eecs.umich.edu return fault; 2093817Ssaidi@eecs.umich.edu} 2103919Shsul@eecs.umich.edu 2115531Snate@binkert.org#ifndef DOXYGEN_SHOULD_SKIP_THIS 2125531Snate@binkert.org 2132650Ssaidi@eecs.umich.edutemplate 2142650Ssaidi@eecs.umich.eduFault 2152650Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags); 2162650Ssaidi@eecs.umich.edu 2174185Ssaidi@eecs.umich.edutemplate 2182650Ssaidi@eecs.umich.eduFault 2194194Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags); 2204194Ssaidi@eecs.umich.edu 2212650Ssaidi@eecs.umich.edutemplate 2223919Shsul@eecs.umich.eduFault 2233825Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags); 2243825Ssaidi@eecs.umich.edu 2253825Ssaidi@eecs.umich.edutemplate 2263825Ssaidi@eecs.umich.eduFault 2273825Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags); 2283825Ssaidi@eecs.umich.edu 2293825Ssaidi@eecs.umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS 2303825Ssaidi@eecs.umich.edu 2313825Ssaidi@eecs.umich.edutemplate<> 2323825Ssaidi@eecs.umich.eduFault 2333825Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, double &data, unsigned flags) 2343825Ssaidi@eecs.umich.edu{ 2353825Ssaidi@eecs.umich.edu return read(addr, *(uint64_t*)&data, flags); 2363825Ssaidi@eecs.umich.edu} 2373825Ssaidi@eecs.umich.edu 2383825Ssaidi@eecs.umich.edutemplate<> 2394172Ssaidi@eecs.umich.eduFault 2402650Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, float &data, unsigned flags) 2413825Ssaidi@eecs.umich.edu{ 2424172Ssaidi@eecs.umich.edu return read(addr, *(uint32_t*)&data, flags); 2433825Ssaidi@eecs.umich.edu} 2444207Ssaidi@eecs.umich.edu 2454207Ssaidi@eecs.umich.edu 2464207Ssaidi@eecs.umich.edutemplate<> 2474207Ssaidi@eecs.umich.eduFault 2484207Ssaidi@eecs.umich.eduTimingSimpleCPU::read(Addr addr, int32_t &data, unsigned flags) 2494207Ssaidi@eecs.umich.edu{ 2504207Ssaidi@eecs.umich.edu return read(addr, (uint32_t&)data, flags); 2512650Ssaidi@eecs.umich.edu} 2524194Ssaidi@eecs.umich.edu 2534194Ssaidi@eecs.umich.edu 2544194Ssaidi@eecs.umich.edutemplate <class T> 2554194Ssaidi@eecs.umich.eduFault 2564194Ssaidi@eecs.umich.eduTimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 2574194Ssaidi@eecs.umich.edu{ 2585531Snate@binkert.org Request *data_write_req = new Request(true); 2595531Snate@binkert.org data_write_req->setVaddr(addr); 2604194Ssaidi@eecs.umich.edu data_write_req->setTime(curTick); 2614194Ssaidi@eecs.umich.edu data_write_req->setSize(sizeof(T)); 2624194Ssaidi@eecs.umich.edu data_write_req->setFlags(flags); 2634194Ssaidi@eecs.umich.edu 2644194Ssaidi@eecs.umich.edu // translate to physical address 2654194Ssaidi@eecs.umich.edu Fault fault = cpuXC->translateDataWriteReq(data_write_req); 2664194Ssaidi@eecs.umich.edu // Now do the access. 2674194Ssaidi@eecs.umich.edu if (fault == NoFault) { 2684194Ssaidi@eecs.umich.edu Packet *data_write_pkt = new Packet; 2694194Ssaidi@eecs.umich.edu data_write_pkt->cmd = Write; 2704194Ssaidi@eecs.umich.edu data_write_pkt->req = data_write_req; 2714194Ssaidi@eecs.umich.edu data_write_pkt->allocate(); 2724194Ssaidi@eecs.umich.edu data_write_pkt->size = sizeof(T); 2734194Ssaidi@eecs.umich.edu data_write_pkt->set(data); 2744194Ssaidi@eecs.umich.edu data_write_pkt->addr = data_write_req->getPaddr(); 2754194Ssaidi@eecs.umich.edu data_write_pkt->dest = Packet::Broadcast; 2764194Ssaidi@eecs.umich.edu 2774194Ssaidi@eecs.umich.edu if (!dcachePort.sendTiming(data_write_pkt)) { 2784194Ssaidi@eecs.umich.edu _status = DcacheRetry; 2794194Ssaidi@eecs.umich.edu dcache_pkt = data_write_pkt; 2804194Ssaidi@eecs.umich.edu } else { 2814194Ssaidi@eecs.umich.edu _status = DcacheWaitResponse; 2824194Ssaidi@eecs.umich.edu dcache_pkt = NULL; 2834194Ssaidi@eecs.umich.edu } 2844194Ssaidi@eecs.umich.edu } 2853825Ssaidi@eecs.umich.edu 2863825Ssaidi@eecs.umich.edu // This will need a new way to tell if it's hooked up to a cache or not. 2872650Ssaidi@eecs.umich.edu if (data_write_req->getFlags() & UNCACHEABLE) 2882650Ssaidi@eecs.umich.edu recordEvent("Uncached Write"); 2892650Ssaidi@eecs.umich.edu 2902651Ssaidi@eecs.umich.edu // If the write needs to have a fault on the access, consider calling 2912680Sktlim@umich.edu // changeStatus() and changing it to "bad addr write" or something. 2922651Ssaidi@eecs.umich.edu return fault; 2932651Ssaidi@eecs.umich.edu} 2942651Ssaidi@eecs.umich.edu 2952651Ssaidi@eecs.umich.edu 2962651Ssaidi@eecs.umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS 2972680Sktlim@umich.edutemplate 2982651Ssaidi@eecs.umich.eduFault 2995606Snate@binkert.orgTimingSimpleCPU::write(uint64_t data, Addr addr, 3005606Snate@binkert.org unsigned flags, uint64_t *res); 3013888Ssaidi@eecs.umich.edu 3023888Ssaidi@eecs.umich.edutemplate 3033888Ssaidi@eecs.umich.eduFault 3043888Ssaidi@eecs.umich.eduTimingSimpleCPU::write(uint32_t data, Addr addr, 3053890Ssaidi@eecs.umich.edu unsigned flags, uint64_t *res); 3065606Snate@binkert.org 3073888Ssaidi@eecs.umich.edutemplate 3083888Ssaidi@eecs.umich.eduFault 3094216Ssaidi@eecs.umich.eduTimingSimpleCPU::write(uint16_t data, Addr addr, 3103888Ssaidi@eecs.umich.edu unsigned flags, uint64_t *res); 3113888Ssaidi@eecs.umich.edu 3124172Ssaidi@eecs.umich.edutemplate 3134172Ssaidi@eecs.umich.eduFault 3143921Shsul@eecs.umich.eduTimingSimpleCPU::write(uint8_t data, Addr addr, 3153888Ssaidi@eecs.umich.edu unsigned flags, uint64_t *res); 3165606Snate@binkert.org 3172651Ssaidi@eecs.umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS 3182651Ssaidi@eecs.umich.edu 3192651Ssaidi@eecs.umich.edutemplate<> 3202680Sktlim@umich.eduFault 3212651Ssaidi@eecs.umich.eduTimingSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 3225606Snate@binkert.org{ 3235606Snate@binkert.org return write(*(uint64_t*)&data, addr, flags, res); 3243891Ssaidi@eecs.umich.edu} 3253891Ssaidi@eecs.umich.edu 3263891Ssaidi@eecs.umich.edutemplate<> 3273891Ssaidi@eecs.umich.eduFault 3284216Ssaidi@eecs.umich.eduTimingSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 3294216Ssaidi@eecs.umich.edu{ 3304216Ssaidi@eecs.umich.edu return write(*(uint32_t*)&data, addr, flags, res); 3314216Ssaidi@eecs.umich.edu} 3323891Ssaidi@eecs.umich.edu 3335606Snate@binkert.org 3343891Ssaidi@eecs.umich.edutemplate<> 3353891Ssaidi@eecs.umich.eduFault 3364216Ssaidi@eecs.umich.eduTimingSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 3373891Ssaidi@eecs.umich.edu{ 3383891Ssaidi@eecs.umich.edu return write((uint32_t)data, addr, flags, res); 3394172Ssaidi@eecs.umich.edu} 3404172Ssaidi@eecs.umich.edu 3413921Shsul@eecs.umich.edu 3423891Ssaidi@eecs.umich.eduvoid 3433891Ssaidi@eecs.umich.eduTimingSimpleCPU::fetch() 3445606Snate@binkert.org{ 3452651Ssaidi@eecs.umich.edu Request *ifetch_req = new Request(true); 3462650Ssaidi@eecs.umich.edu ifetch_req->setSize(sizeof(MachInst)); 347 348 ifetch_pkt = new Packet; 349 ifetch_pkt->cmd = Read; 350 ifetch_pkt->dataStatic(&inst); 351 ifetch_pkt->req = ifetch_req; 352 ifetch_pkt->size = sizeof(MachInst); 353 ifetch_pkt->dest = Packet::Broadcast; 354 355 Fault fault = setupFetchPacket(ifetch_pkt); 356 if (fault == NoFault) { 357 if (!icachePort.sendTiming(ifetch_pkt)) { 358 // Need to wait for retry 359 _status = IcacheRetry; 360 } else { 361 // Need to wait for cache to respond 362 _status = IcacheWaitResponse; 363 // ownership of packet transferred to memory system 364 ifetch_pkt = NULL; 365 } 366 } else { 367 panic("TimingSimpleCPU fetch fault handling not implemented"); 368 } 369} 370 371 372void 373TimingSimpleCPU::completeInst(Fault fault) 374{ 375 postExecute(); 376 377 if (traceData) { 378 traceData->finalize(); 379 } 380 381 advancePC(fault); 382 383 fetch(); 384} 385 386 387void 388TimingSimpleCPU::completeIfetch() 389{ 390 // received a response from the icache: execute the received 391 // instruction 392 assert(_status == IcacheWaitResponse); 393 _status = Running; 394 preExecute(); 395 if (curStaticInst->isMemRef()) { 396 // load or store: just send to dcache 397 Fault fault = curStaticInst->initiateAcc(this, traceData); 398 assert(fault == NoFault); 399 assert(_status == DcacheWaitResponse); 400 } else { 401 // non-memory instruction: execute completely now 402 Fault fault = curStaticInst->execute(this, traceData); 403 completeInst(fault); 404 } 405} 406 407 408bool 409TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt) 410{ 411 cpu->completeIfetch(); 412 return true; 413} 414 415Packet * 416TimingSimpleCPU::IcachePort::recvRetry() 417{ 418 // we shouldn't get a retry unless we have a packet that we're 419 // waiting to transmit 420 assert(cpu->ifetch_pkt != NULL); 421 assert(cpu->_status == IcacheRetry); 422 cpu->_status = IcacheWaitResponse; 423 Packet *tmp = cpu->ifetch_pkt; 424 cpu->ifetch_pkt = NULL; 425 return tmp; 426} 427 428void 429TimingSimpleCPU::completeDataAccess(Packet *pkt) 430{ 431 // received a response from the dcache: complete the load or store 432 // instruction 433 assert(pkt->result == Success); 434 assert(_status == DcacheWaitResponse); 435 _status = Running; 436 437 Fault fault = curStaticInst->completeAcc(pkt, this, traceData); 438 439 completeInst(fault); 440} 441 442 443 444bool 445TimingSimpleCPU::DcachePort::recvTiming(Packet *pkt) 446{ 447 cpu->completeDataAccess(pkt); 448 return true; 449} 450 451Packet * 452TimingSimpleCPU::DcachePort::recvRetry() 453{ 454 // we shouldn't get a retry unless we have a packet that we're 455 // waiting to transmit 456 assert(cpu->dcache_pkt != NULL); 457 assert(cpu->_status == DcacheRetry); 458 cpu->_status = DcacheWaitResponse; 459 Packet *tmp = cpu->dcache_pkt; 460 cpu->dcache_pkt = NULL; 461 return tmp; 462} 463 464 465//////////////////////////////////////////////////////////////////////// 466// 467// TimingSimpleCPU Simulation Object 468// 469BEGIN_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU) 470 471 Param<Counter> max_insts_any_thread; 472 Param<Counter> max_insts_all_threads; 473 Param<Counter> max_loads_any_thread; 474 Param<Counter> max_loads_all_threads; 475 SimObjectParam<MemObject *> mem; 476 477#if FULL_SYSTEM 478 SimObjectParam<AlphaITB *> itb; 479 SimObjectParam<AlphaDTB *> dtb; 480 SimObjectParam<System *> system; 481 Param<int> cpu_id; 482 Param<Tick> profile; 483#else 484 SimObjectParam<Process *> workload; 485#endif // FULL_SYSTEM 486 487 Param<int> clock; 488 489 Param<bool> defer_registration; 490 Param<int> width; 491 Param<bool> function_trace; 492 Param<Tick> function_trace_start; 493 Param<bool> simulate_stalls; 494 495END_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU) 496 497BEGIN_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU) 498 499 INIT_PARAM(max_insts_any_thread, 500 "terminate when any thread reaches this inst count"), 501 INIT_PARAM(max_insts_all_threads, 502 "terminate when all threads have reached this inst count"), 503 INIT_PARAM(max_loads_any_thread, 504 "terminate when any thread reaches this load count"), 505 INIT_PARAM(max_loads_all_threads, 506 "terminate when all threads have reached this load count"), 507 INIT_PARAM(mem, "memory"), 508 509#if FULL_SYSTEM 510 INIT_PARAM(itb, "Instruction TLB"), 511 INIT_PARAM(dtb, "Data TLB"), 512 INIT_PARAM(system, "system object"), 513 INIT_PARAM(cpu_id, "processor ID"), 514 INIT_PARAM(profile, ""), 515#else 516 INIT_PARAM(workload, "processes to run"), 517#endif // FULL_SYSTEM 518 519 INIT_PARAM(clock, "clock speed"), 520 INIT_PARAM(defer_registration, "defer system registration (for sampling)"), 521 INIT_PARAM(width, "cpu width"), 522 INIT_PARAM(function_trace, "Enable function trace"), 523 INIT_PARAM(function_trace_start, "Cycle to start function trace"), 524 INIT_PARAM(simulate_stalls, "Simulate cache stall cycles") 525 526END_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU) 527 528 529CREATE_SIM_OBJECT(TimingSimpleCPU) 530{ 531 TimingSimpleCPU::Params *params = new TimingSimpleCPU::Params(); 532 params->name = getInstanceName(); 533 params->numberOfThreads = 1; 534 params->max_insts_any_thread = max_insts_any_thread; 535 params->max_insts_all_threads = max_insts_all_threads; 536 params->max_loads_any_thread = max_loads_any_thread; 537 params->max_loads_all_threads = max_loads_all_threads; 538 params->deferRegistration = defer_registration; 539 params->clock = clock; 540 params->functionTrace = function_trace; 541 params->functionTraceStart = function_trace_start; 542 params->mem = mem; 543 544#if FULL_SYSTEM 545 params->itb = itb; 546 params->dtb = dtb; 547 params->system = system; 548 params->cpu_id = cpu_id; 549 params->profile = profile; 550#else 551 params->process = workload; 552#endif 553 554 TimingSimpleCPU *cpu = new TimingSimpleCPU(params); 555 return cpu; 556} 557 558REGISTER_SIM_OBJECT("TimingSimpleCPU", TimingSimpleCPU) 559 560