cpu.cc revision 9954:72a72649a156
15409Sgblack@eecs.umich.edu/* 24519Sgblack@eecs.umich.edu * Copyright (c) 2011-2012 ARM Limited 34519Sgblack@eecs.umich.edu * Copyright (c) 2013 Advanced Micro Devices, Inc. 44519Sgblack@eecs.umich.edu * All rights reserved 54519Sgblack@eecs.umich.edu * 64519Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 74519Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 84519Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 94519Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 104519Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 114519Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 124519Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 134519Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 144519Sgblack@eecs.umich.edu * 154519Sgblack@eecs.umich.edu * Copyright (c) 2004-2006 The Regents of The University of Michigan 164519Sgblack@eecs.umich.edu * Copyright (c) 2011 Regents of the University of California 174519Sgblack@eecs.umich.edu * All rights reserved. 184519Sgblack@eecs.umich.edu * 194519Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 204519Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 214519Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 224519Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 234519Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 244519Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 254519Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 264519Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 274519Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 284519Sgblack@eecs.umich.edu * this software without specific prior written permission. 294519Sgblack@eecs.umich.edu * 304519Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 314519Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 324519Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 334519Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 344519Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 354519Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 364519Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 374519Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 384519Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 394519Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 404519Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 414519Sgblack@eecs.umich.edu * 424519Sgblack@eecs.umich.edu * Authors: Kevin Lim 434519Sgblack@eecs.umich.edu * Korey Sewell 444519Sgblack@eecs.umich.edu * Rick Strong 454519Sgblack@eecs.umich.edu */ 464519Sgblack@eecs.umich.edu 474519Sgblack@eecs.umich.edu#include "arch/kernel_stats.hh" 484519Sgblack@eecs.umich.edu#include "config/the_isa.hh" 494519Sgblack@eecs.umich.edu#include "cpu/checker/cpu.hh" 504519Sgblack@eecs.umich.edu#include "cpu/checker/thread_context.hh" 514519Sgblack@eecs.umich.edu#include "cpu/o3/cpu.hh" 524519Sgblack@eecs.umich.edu#include "cpu/o3/isa_specific.hh" 534519Sgblack@eecs.umich.edu#include "cpu/o3/thread_context.hh" 544519Sgblack@eecs.umich.edu#include "cpu/activity.hh" 554519Sgblack@eecs.umich.edu#include "cpu/quiesce_event.hh" 564519Sgblack@eecs.umich.edu#include "cpu/simple_thread.hh" 574519Sgblack@eecs.umich.edu#include "cpu/thread_context.hh" 584519Sgblack@eecs.umich.edu#include "debug/Activity.hh" 594519Sgblack@eecs.umich.edu#include "debug/Drain.hh" 604519Sgblack@eecs.umich.edu#include "debug/O3CPU.hh" 614519Sgblack@eecs.umich.edu#include "debug/Quiesce.hh" 624519Sgblack@eecs.umich.edu#include "enums/MemoryMode.hh" 634519Sgblack@eecs.umich.edu#include "sim/core.hh" 644519Sgblack@eecs.umich.edu#include "sim/full_system.hh" 654519Sgblack@eecs.umich.edu#include "sim/process.hh" 664519Sgblack@eecs.umich.edu#include "sim/stat_control.hh" 674519Sgblack@eecs.umich.edu#include "sim/system.hh" 684809Sgblack@eecs.umich.edu 694519Sgblack@eecs.umich.edu#if THE_ISA == ALPHA_ISA 704519Sgblack@eecs.umich.edu#include "arch/alpha/osfpal.hh" 714688Sgblack@eecs.umich.edu#include "debug/Activity.hh" 724688Sgblack@eecs.umich.edu#endif 734688Sgblack@eecs.umich.edu 744688Sgblack@eecs.umich.edustruct BaseCPUParams; 754688Sgblack@eecs.umich.edu 764688Sgblack@eecs.umich.eduusing namespace TheISA; 774708Sgblack@eecs.umich.eduusing namespace std; 784708Sgblack@eecs.umich.edu 794708Sgblack@eecs.umich.eduBaseO3CPU::BaseO3CPU(BaseCPUParams *params) 804708Sgblack@eecs.umich.edu : BaseCPU(params) 814519Sgblack@eecs.umich.edu{ 824519Sgblack@eecs.umich.edu} 834519Sgblack@eecs.umich.edu 844519Sgblack@eecs.umich.eduvoid 854519Sgblack@eecs.umich.eduBaseO3CPU::regStats() 864519Sgblack@eecs.umich.edu{ 874519Sgblack@eecs.umich.edu BaseCPU::regStats(); 884519Sgblack@eecs.umich.edu} 894519Sgblack@eecs.umich.edu 904519Sgblack@eecs.umich.edutemplate<class Impl> 914519Sgblack@eecs.umich.edubool 924951Sgblack@eecs.umich.eduFullO3CPU<Impl>::IcachePort::recvTimingResp(PacketPtr pkt) 934519Sgblack@eecs.umich.edu{ 944519Sgblack@eecs.umich.edu DPRINTF(O3CPU, "Fetch unit received timing\n"); 954519Sgblack@eecs.umich.edu // We shouldn't ever get a block in ownership state 964519Sgblack@eecs.umich.edu assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted())); 974519Sgblack@eecs.umich.edu fetch->processCacheCompletion(pkt); 984519Sgblack@eecs.umich.edu 994688Sgblack@eecs.umich.edu return true; 1004688Sgblack@eecs.umich.edu} 1014688Sgblack@eecs.umich.edu 1024688Sgblack@eecs.umich.edutemplate<class Impl> 1034688Sgblack@eecs.umich.eduvoid 1044688Sgblack@eecs.umich.eduFullO3CPU<Impl>::IcachePort::recvRetry() 1054708Sgblack@eecs.umich.edu{ 1064708Sgblack@eecs.umich.edu fetch->recvRetry(); 1074708Sgblack@eecs.umich.edu} 1084708Sgblack@eecs.umich.edu 1094519Sgblack@eecs.umich.edutemplate <class Impl> 1104519Sgblack@eecs.umich.edubool 1114519Sgblack@eecs.umich.eduFullO3CPU<Impl>::DcachePort::recvTimingResp(PacketPtr pkt) 1124519Sgblack@eecs.umich.edu{ 1134519Sgblack@eecs.umich.edu return lsq->recvTimingResp(pkt); 1144519Sgblack@eecs.umich.edu} 1154519Sgblack@eecs.umich.edu 1164519Sgblack@eecs.umich.edutemplate <class Impl> 1174519Sgblack@eecs.umich.eduvoid 1184519Sgblack@eecs.umich.eduFullO3CPU<Impl>::DcachePort::recvTimingSnoopReq(PacketPtr pkt) 1194519Sgblack@eecs.umich.edu{ 1204519Sgblack@eecs.umich.edu lsq->recvTimingSnoopReq(pkt); 1214519Sgblack@eecs.umich.edu} 1224519Sgblack@eecs.umich.edu 1234519Sgblack@eecs.umich.edutemplate <class Impl> 1244519Sgblack@eecs.umich.eduvoid 1254519Sgblack@eecs.umich.eduFullO3CPU<Impl>::DcachePort::recvRetry() 1264519Sgblack@eecs.umich.edu{ 1274519Sgblack@eecs.umich.edu lsq->recvRetry(); 1284519Sgblack@eecs.umich.edu} 1294519Sgblack@eecs.umich.edu 1304712Sgblack@eecs.umich.edutemplate <class Impl> 1314519Sgblack@eecs.umich.eduFullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 1324519Sgblack@eecs.umich.edu : Event(CPU_Tick_Pri), cpu(c) 1334519Sgblack@eecs.umich.edu{ 1344519Sgblack@eecs.umich.edu} 1354712Sgblack@eecs.umich.edu 1364519Sgblack@eecs.umich.edutemplate <class Impl> 1374519Sgblack@eecs.umich.eduvoid 1384519Sgblack@eecs.umich.eduFullO3CPU<Impl>::TickEvent::process() 1394519Sgblack@eecs.umich.edu{ 1404519Sgblack@eecs.umich.edu cpu->tick(); 1414519Sgblack@eecs.umich.edu} 1424519Sgblack@eecs.umich.edu 1434951Sgblack@eecs.umich.edutemplate <class Impl> 1444519Sgblack@eecs.umich.educonst char * 1454519Sgblack@eecs.umich.eduFullO3CPU<Impl>::TickEvent::description() const 1464519Sgblack@eecs.umich.edu{ 1474519Sgblack@eecs.umich.edu return "FullO3CPU tick"; 1484519Sgblack@eecs.umich.edu} 1494951Sgblack@eecs.umich.edu 1504519Sgblack@eecs.umich.edutemplate <class Impl> 1514519Sgblack@eecs.umich.eduFullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent() 1524951Sgblack@eecs.umich.edu : Event(CPU_Switch_Pri) 1534712Sgblack@eecs.umich.edu{ 1544519Sgblack@eecs.umich.edu} 1554951Sgblack@eecs.umich.edu 1564519Sgblack@eecs.umich.edutemplate <class Impl> 1574951Sgblack@eecs.umich.eduvoid 1584712Sgblack@eecs.umich.eduFullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num, 1594519Sgblack@eecs.umich.edu FullO3CPU<Impl> *thread_cpu) 1604519Sgblack@eecs.umich.edu{ 1614519Sgblack@eecs.umich.edu tid = thread_num; 1624519Sgblack@eecs.umich.edu cpu = thread_cpu; 1634519Sgblack@eecs.umich.edu} 1644519Sgblack@eecs.umich.edu 1654519Sgblack@eecs.umich.edutemplate <class Impl> 1664519Sgblack@eecs.umich.eduvoid 1674519Sgblack@eecs.umich.eduFullO3CPU<Impl>::ActivateThreadEvent::process() 1684519Sgblack@eecs.umich.edu{ 1694519Sgblack@eecs.umich.edu cpu->activateThread(tid); 1704519Sgblack@eecs.umich.edu} 1714519Sgblack@eecs.umich.edu 1724519Sgblack@eecs.umich.edutemplate <class Impl> 1734519Sgblack@eecs.umich.educonst char * 1744712Sgblack@eecs.umich.eduFullO3CPU<Impl>::ActivateThreadEvent::description() const 1754519Sgblack@eecs.umich.edu{ 1764581Sgblack@eecs.umich.edu return "FullO3CPU \"Activate Thread\""; 1774688Sgblack@eecs.umich.edu} 1784581Sgblack@eecs.umich.edu 1794519Sgblack@eecs.umich.edutemplate <class Impl> 1804519Sgblack@eecs.umich.eduFullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent() 1814519Sgblack@eecs.umich.edu : Event(CPU_Tick_Pri), tid(0), remove(false), cpu(NULL) 1824519Sgblack@eecs.umich.edu{ 1834519Sgblack@eecs.umich.edu} 1844519Sgblack@eecs.umich.edu 1854519Sgblack@eecs.umich.edutemplate <class Impl> 1864519Sgblack@eecs.umich.eduvoid 1874712Sgblack@eecs.umich.eduFullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num, 1884519Sgblack@eecs.umich.edu FullO3CPU<Impl> *thread_cpu) 1894581Sgblack@eecs.umich.edu{ 1904688Sgblack@eecs.umich.edu tid = thread_num; 1914581Sgblack@eecs.umich.edu cpu = thread_cpu; 1924519Sgblack@eecs.umich.edu remove = false; 1934519Sgblack@eecs.umich.edu} 1944519Sgblack@eecs.umich.edu 1954519Sgblack@eecs.umich.edutemplate <class Impl> 1964519Sgblack@eecs.umich.eduvoid 1974519Sgblack@eecs.umich.eduFullO3CPU<Impl>::DeallocateContextEvent::process() 1984519Sgblack@eecs.umich.edu{ 1994951Sgblack@eecs.umich.edu cpu->deactivateThread(tid); 2004519Sgblack@eecs.umich.edu if (remove) 2014519Sgblack@eecs.umich.edu cpu->removeThread(tid); 2024519Sgblack@eecs.umich.edu} 2034519Sgblack@eecs.umich.edu 2044951Sgblack@eecs.umich.edutemplate <class Impl> 2054519Sgblack@eecs.umich.educonst char * 2064951Sgblack@eecs.umich.eduFullO3CPU<Impl>::DeallocateContextEvent::description() const 2074712Sgblack@eecs.umich.edu{ 2084519Sgblack@eecs.umich.edu return "FullO3CPU \"Deallocate Context\""; 2094581Sgblack@eecs.umich.edu} 2104688Sgblack@eecs.umich.edu 2114581Sgblack@eecs.umich.edutemplate <class Impl> 2124519Sgblack@eecs.umich.eduFullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) 2134519Sgblack@eecs.umich.edu : BaseO3CPU(params), 2144519Sgblack@eecs.umich.edu itb(params->itb), 2154519Sgblack@eecs.umich.edu dtb(params->dtb), 2164951Sgblack@eecs.umich.edu tickEvent(this), 2174519Sgblack@eecs.umich.edu#ifndef NDEBUG 2184519Sgblack@eecs.umich.edu instcount(0), 2194951Sgblack@eecs.umich.edu#endif 2204712Sgblack@eecs.umich.edu removeInstsThisCycle(false), 2214519Sgblack@eecs.umich.edu fetch(this, params), 2224581Sgblack@eecs.umich.edu decode(this, params), 2234688Sgblack@eecs.umich.edu rename(this, params), 2244581Sgblack@eecs.umich.edu iew(this, params), 2254519Sgblack@eecs.umich.edu commit(this, params), 2264519Sgblack@eecs.umich.edu 2274519Sgblack@eecs.umich.edu regFile(params->numPhysIntRegs, 2284519Sgblack@eecs.umich.edu params->numPhysFloatRegs, 2294519Sgblack@eecs.umich.edu params->numPhysCCRegs), 2305075Sgblack@eecs.umich.edu 2315075Sgblack@eecs.umich.edu freeList(name() + ".freelist", ®File), 2325075Sgblack@eecs.umich.edu 2335075Sgblack@eecs.umich.edu rob(this, params), 2345428Sgblack@eecs.umich.edu 2355428Sgblack@eecs.umich.edu scoreboard(name() + ".scoreboard", 2365674Sgblack@eecs.umich.edu regFile.totalNumPhysRegs(), TheISA::NumMiscRegs, 2375899Sgblack@eecs.umich.edu TheISA::ZeroReg, TheISA::ZeroReg), 2385899Sgblack@eecs.umich.edu 2395428Sgblack@eecs.umich.edu isa(numThreads, NULL), 2405678Sgblack@eecs.umich.edu 2415678Sgblack@eecs.umich.edu icachePort(&fetch, this), 2425678Sgblack@eecs.umich.edu dcachePort(&iew.ldstQueue, this), 2435678Sgblack@eecs.umich.edu 2445678Sgblack@eecs.umich.edu timeBuffer(params->backComSize, params->forwardComSize), 2455678Sgblack@eecs.umich.edu fetchQueue(params->backComSize, params->forwardComSize), 2465678Sgblack@eecs.umich.edu decodeQueue(params->backComSize, params->forwardComSize), 2475678Sgblack@eecs.umich.edu renameQueue(params->backComSize, params->forwardComSize), 2485678Sgblack@eecs.umich.edu iewQueue(params->backComSize, params->forwardComSize), 2495075Sgblack@eecs.umich.edu activityRec(name(), NumStages, 2505075Sgblack@eecs.umich.edu params->backComSize + params->forwardComSize, 2515075Sgblack@eecs.umich.edu params->activity), 2525075Sgblack@eecs.umich.edu 2535075Sgblack@eecs.umich.edu globalSeqNum(1), 2545075Sgblack@eecs.umich.edu system(params->system), 2555075Sgblack@eecs.umich.edu drainManager(NULL), 2565075Sgblack@eecs.umich.edu lastRunningCycle(curCycle()) 2575075Sgblack@eecs.umich.edu{ 2585075Sgblack@eecs.umich.edu if (!params->switched_out) { 2595075Sgblack@eecs.umich.edu _status = Running; 2605075Sgblack@eecs.umich.edu } else { 2615075Sgblack@eecs.umich.edu _status = SwitchedOut; 2625075Sgblack@eecs.umich.edu } 2635075Sgblack@eecs.umich.edu 2645075Sgblack@eecs.umich.edu if (params->checker) { 2655075Sgblack@eecs.umich.edu BaseCPU *temp_checker = params->checker; 2665075Sgblack@eecs.umich.edu checker = dynamic_cast<Checker<Impl> *>(temp_checker); 2675075Sgblack@eecs.umich.edu checker->setIcachePort(&icachePort); 2685075Sgblack@eecs.umich.edu checker->setSystem(params->system); 2695075Sgblack@eecs.umich.edu } else { 2705075Sgblack@eecs.umich.edu checker = NULL; 2715075Sgblack@eecs.umich.edu } 2725075Sgblack@eecs.umich.edu 2735075Sgblack@eecs.umich.edu if (!FullSystem) { 2745075Sgblack@eecs.umich.edu thread.resize(numThreads); 2755075Sgblack@eecs.umich.edu tids.resize(numThreads); 2765075Sgblack@eecs.umich.edu } 2775075Sgblack@eecs.umich.edu 2785075Sgblack@eecs.umich.edu // The stages also need their CPU pointer setup. However this 2795075Sgblack@eecs.umich.edu // must be done at the upper level CPU because they have pointers 2805075Sgblack@eecs.umich.edu // to the upper level CPU, and not this FullO3CPU. 2815075Sgblack@eecs.umich.edu 2825075Sgblack@eecs.umich.edu // Set up Pointers to the activeThreads list for each stage 2835075Sgblack@eecs.umich.edu fetch.setActiveThreads(&activeThreads); 2844519Sgblack@eecs.umich.edu decode.setActiveThreads(&activeThreads); 2855040Sgblack@eecs.umich.edu rename.setActiveThreads(&activeThreads); 2865040Sgblack@eecs.umich.edu iew.setActiveThreads(&activeThreads); 2875040Sgblack@eecs.umich.edu commit.setActiveThreads(&activeThreads); 2885040Sgblack@eecs.umich.edu 2895040Sgblack@eecs.umich.edu // Give each of the stages the time buffer they will use. 2905040Sgblack@eecs.umich.edu fetch.setTimeBuffer(&timeBuffer); 2915040Sgblack@eecs.umich.edu decode.setTimeBuffer(&timeBuffer); 2925040Sgblack@eecs.umich.edu rename.setTimeBuffer(&timeBuffer); 2935040Sgblack@eecs.umich.edu iew.setTimeBuffer(&timeBuffer); 2945040Sgblack@eecs.umich.edu commit.setTimeBuffer(&timeBuffer); 2955040Sgblack@eecs.umich.edu 2965040Sgblack@eecs.umich.edu // Also setup each of the stages' queues. 2975040Sgblack@eecs.umich.edu fetch.setFetchQueue(&fetchQueue); 2985040Sgblack@eecs.umich.edu decode.setFetchQueue(&fetchQueue); 2995040Sgblack@eecs.umich.edu commit.setFetchQueue(&fetchQueue); 3005040Sgblack@eecs.umich.edu decode.setDecodeQueue(&decodeQueue); 3015040Sgblack@eecs.umich.edu rename.setDecodeQueue(&decodeQueue); 3025040Sgblack@eecs.umich.edu rename.setRenameQueue(&renameQueue); 3035040Sgblack@eecs.umich.edu iew.setRenameQueue(&renameQueue); 3045040Sgblack@eecs.umich.edu iew.setIEWQueue(&iewQueue); 3055040Sgblack@eecs.umich.edu commit.setIEWQueue(&iewQueue); 3065040Sgblack@eecs.umich.edu commit.setRenameQueue(&renameQueue); 3075040Sgblack@eecs.umich.edu 3085040Sgblack@eecs.umich.edu commit.setIEWStage(&iew); 3095040Sgblack@eecs.umich.edu rename.setIEWStage(&iew); 3105040Sgblack@eecs.umich.edu rename.setCommitStage(&commit); 3115040Sgblack@eecs.umich.edu 3125040Sgblack@eecs.umich.edu ThreadID active_threads; 3135040Sgblack@eecs.umich.edu if (FullSystem) { 3145040Sgblack@eecs.umich.edu active_threads = 1; 3155062Sgblack@eecs.umich.edu } else { 3165062Sgblack@eecs.umich.edu active_threads = params->workload.size(); 3175062Sgblack@eecs.umich.edu 3185062Sgblack@eecs.umich.edu if (active_threads > Impl::MaxThreads) { 3195062Sgblack@eecs.umich.edu panic("Workload Size too large. Increase the 'MaxThreads' " 3205062Sgblack@eecs.umich.edu "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) " 3215062Sgblack@eecs.umich.edu "or edit your workload size."); 3225040Sgblack@eecs.umich.edu } 3235062Sgblack@eecs.umich.edu } 3245062Sgblack@eecs.umich.edu 3255062Sgblack@eecs.umich.edu //Make Sure That this a Valid Architeture 3265062Sgblack@eecs.umich.edu assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 3275040Sgblack@eecs.umich.edu assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 3285040Sgblack@eecs.umich.edu assert(params->numPhysCCRegs >= numThreads * TheISA::NumCCRegs); 3295040Sgblack@eecs.umich.edu 3305040Sgblack@eecs.umich.edu rename.setScoreboard(&scoreboard); 3315040Sgblack@eecs.umich.edu iew.setScoreboard(&scoreboard); 3325040Sgblack@eecs.umich.edu 3335040Sgblack@eecs.umich.edu // Setup the rename map for whichever stages need it. 3345040Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 3355040Sgblack@eecs.umich.edu isa[tid] = params->isa[tid]; 3365239Sgblack@eecs.umich.edu 3375040Sgblack@eecs.umich.edu // Only Alpha has an FP zero register, so for other ISAs we 3385040Sgblack@eecs.umich.edu // use an invalid FP register index to avoid special treatment 3395040Sgblack@eecs.umich.edu // of any valid FP reg. 3405040Sgblack@eecs.umich.edu RegIndex invalidFPReg = TheISA::NumFloatRegs + 1; 3415040Sgblack@eecs.umich.edu RegIndex fpZeroReg = 3425040Sgblack@eecs.umich.edu (THE_ISA == ALPHA_ISA) ? TheISA::ZeroReg : invalidFPReg; 3435040Sgblack@eecs.umich.edu 3445040Sgblack@eecs.umich.edu commitRenameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, 3455061Sgblack@eecs.umich.edu &freeList); 3465040Sgblack@eecs.umich.edu 3475040Sgblack@eecs.umich.edu renameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, 3485061Sgblack@eecs.umich.edu &freeList); 3495061Sgblack@eecs.umich.edu 3505061Sgblack@eecs.umich.edu activateThreadEvent[tid].init(tid, this); 3515061Sgblack@eecs.umich.edu deallocateContextEvent[tid].init(tid, this); 3525061Sgblack@eecs.umich.edu } 3535061Sgblack@eecs.umich.edu 3545061Sgblack@eecs.umich.edu // Initialize rename map to assign physical registers to the 3555061Sgblack@eecs.umich.edu // architectural registers for active threads only. 3565040Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < active_threads; tid++) { 3575040Sgblack@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumIntRegs; ++ridx) { 3585040Sgblack@eecs.umich.edu // Note that we can't use the rename() method because we don't 3595040Sgblack@eecs.umich.edu // want special treatment for the zero register at this point 3605040Sgblack@eecs.umich.edu PhysRegIndex phys_reg = freeList.getIntReg(); 3615040Sgblack@eecs.umich.edu renameMap[tid].setIntEntry(ridx, phys_reg); 3625040Sgblack@eecs.umich.edu commitRenameMap[tid].setIntEntry(ridx, phys_reg); 3635040Sgblack@eecs.umich.edu } 3645040Sgblack@eecs.umich.edu 3655040Sgblack@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) { 3665040Sgblack@eecs.umich.edu PhysRegIndex phys_reg = freeList.getFloatReg(); 3675040Sgblack@eecs.umich.edu renameMap[tid].setFloatEntry(ridx, phys_reg); 3685040Sgblack@eecs.umich.edu commitRenameMap[tid].setFloatEntry(ridx, phys_reg); 3695040Sgblack@eecs.umich.edu } 3705040Sgblack@eecs.umich.edu 3715040Sgblack@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) { 3725040Sgblack@eecs.umich.edu PhysRegIndex phys_reg = freeList.getCCReg(); 3735040Sgblack@eecs.umich.edu renameMap[tid].setCCEntry(ridx, phys_reg); 3745040Sgblack@eecs.umich.edu commitRenameMap[tid].setCCEntry(ridx, phys_reg); 3755040Sgblack@eecs.umich.edu } 3765040Sgblack@eecs.umich.edu } 3775040Sgblack@eecs.umich.edu 3785040Sgblack@eecs.umich.edu rename.setRenameMap(renameMap); 3795040Sgblack@eecs.umich.edu commit.setRenameMap(commitRenameMap); 3805040Sgblack@eecs.umich.edu rename.setFreeList(&freeList); 3814688Sgblack@eecs.umich.edu 3825040Sgblack@eecs.umich.edu // Setup the ROB for whichever stages need it. 3834688Sgblack@eecs.umich.edu commit.setROB(&rob); 3844688Sgblack@eecs.umich.edu 3854688Sgblack@eecs.umich.edu lastActivatedCycle = 0; 3864688Sgblack@eecs.umich.edu#if 0 3875040Sgblack@eecs.umich.edu // Give renameMap & rename stage access to the freeList; 3884688Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) 3895040Sgblack@eecs.umich.edu globalSeqNum[tid] = 1; 3905040Sgblack@eecs.umich.edu#endif 3915040Sgblack@eecs.umich.edu 3925040Sgblack@eecs.umich.edu contextSwitch = false; 3935040Sgblack@eecs.umich.edu DPRINTF(O3CPU, "Creating O3CPU object.\n"); 3945040Sgblack@eecs.umich.edu 3955040Sgblack@eecs.umich.edu // Setup any thread state. 3965040Sgblack@eecs.umich.edu this->thread.resize(this->numThreads); 3975040Sgblack@eecs.umich.edu 3985040Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < this->numThreads; ++tid) { 3995040Sgblack@eecs.umich.edu if (FullSystem) { 4005040Sgblack@eecs.umich.edu // SMT is not supported in FS mode yet. 4015040Sgblack@eecs.umich.edu assert(this->numThreads == 1); 4025040Sgblack@eecs.umich.edu this->thread[tid] = new Thread(this, 0, NULL); 4035040Sgblack@eecs.umich.edu } else { 4045040Sgblack@eecs.umich.edu if (tid < params->workload.size()) { 4055040Sgblack@eecs.umich.edu DPRINTF(O3CPU, "Workload[%i] process is %#x", 4065040Sgblack@eecs.umich.edu tid, this->thread[tid]); 4075040Sgblack@eecs.umich.edu this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 4085040Sgblack@eecs.umich.edu (typename Impl::O3CPU *)(this), 4095040Sgblack@eecs.umich.edu tid, params->workload[tid]); 4105040Sgblack@eecs.umich.edu 4114688Sgblack@eecs.umich.edu //usedTids[tid] = true; 4124688Sgblack@eecs.umich.edu //threadMap[tid] = tid; 4135040Sgblack@eecs.umich.edu } else { 4145040Sgblack@eecs.umich.edu //Allocate Empty thread so M5 can use later 4155040Sgblack@eecs.umich.edu //when scheduling threads to CPU 4165040Sgblack@eecs.umich.edu Process* dummy_proc = NULL; 4174688Sgblack@eecs.umich.edu 4184688Sgblack@eecs.umich.edu this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 4195040Sgblack@eecs.umich.edu (typename Impl::O3CPU *)(this), 4205040Sgblack@eecs.umich.edu tid, dummy_proc); 4215040Sgblack@eecs.umich.edu //usedTids[tid] = false; 4225040Sgblack@eecs.umich.edu } 4235040Sgblack@eecs.umich.edu } 4245040Sgblack@eecs.umich.edu 4254519Sgblack@eecs.umich.edu ThreadContext *tc; 4264519Sgblack@eecs.umich.edu 4275040Sgblack@eecs.umich.edu // Setup the TC that will serve as the interface to the threads/CPU. 4284688Sgblack@eecs.umich.edu O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>; 4294701Sgblack@eecs.umich.edu 4304688Sgblack@eecs.umich.edu tc = o3_tc; 4314688Sgblack@eecs.umich.edu 4324688Sgblack@eecs.umich.edu // If we're using a checker, then the TC should be the 4334688Sgblack@eecs.umich.edu // CheckerThreadContext. 4344688Sgblack@eecs.umich.edu if (params->checker) { 4354688Sgblack@eecs.umich.edu tc = new CheckerThreadContext<O3ThreadContext<Impl> >( 4364688Sgblack@eecs.umich.edu o3_tc, this->checker); 4374519Sgblack@eecs.umich.edu } 4384519Sgblack@eecs.umich.edu 4395040Sgblack@eecs.umich.edu o3_tc->cpu = (typename Impl::O3CPU *)(this); 4405040Sgblack@eecs.umich.edu assert(o3_tc->cpu); 4415040Sgblack@eecs.umich.edu o3_tc->thread = this->thread[tid]; 4425788Sgblack@eecs.umich.edu 4435040Sgblack@eecs.umich.edu if (FullSystem) { 4444688Sgblack@eecs.umich.edu // Setup quiesce event. 4455040Sgblack@eecs.umich.edu this->thread[tid]->quiesceEvent = new EndQuiesceEvent(tc); 4464519Sgblack@eecs.umich.edu } 4475040Sgblack@eecs.umich.edu // Give the thread the TC. 4484519Sgblack@eecs.umich.edu this->thread[tid]->tc = tc; 4494519Sgblack@eecs.umich.edu 4504519Sgblack@eecs.umich.edu // Add the TC to the CPU's list of TC's. 4514539Sgblack@eecs.umich.edu this->threadContexts.push_back(tc); 4524519Sgblack@eecs.umich.edu } 4535040Sgblack@eecs.umich.edu 4544688Sgblack@eecs.umich.edu // FullO3CPU always requires an interrupt controller. 4555040Sgblack@eecs.umich.edu if (!params->switched_out && !interrupts) { 4565040Sgblack@eecs.umich.edu fatal("FullO3CPU %s has no interrupt controller.\n" 4575115Sgblack@eecs.umich.edu "Ensure createInterruptController() is called.\n", name()); 4585040Sgblack@eecs.umich.edu } 4595040Sgblack@eecs.umich.edu 4605040Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < this->numThreads; tid++) 4615115Sgblack@eecs.umich.edu this->thread[tid]->setFuncExeInst(0); 4625040Sgblack@eecs.umich.edu} 4635040Sgblack@eecs.umich.edu 4644519Sgblack@eecs.umich.edutemplate <class Impl> 4655040Sgblack@eecs.umich.eduFullO3CPU<Impl>::~FullO3CPU() 4665040Sgblack@eecs.umich.edu{ 4675040Sgblack@eecs.umich.edu} 4685040Sgblack@eecs.umich.edu 4694519Sgblack@eecs.umich.edutemplate <class Impl> 4705040Sgblack@eecs.umich.eduvoid 4715040Sgblack@eecs.umich.eduFullO3CPU<Impl>::regStats() 4725040Sgblack@eecs.umich.edu{ 4735040Sgblack@eecs.umich.edu BaseO3CPU::regStats(); 4744519Sgblack@eecs.umich.edu 4755040Sgblack@eecs.umich.edu // Register any of the O3CPU's stats here. 4765040Sgblack@eecs.umich.edu timesIdled 4775083Sgblack@eecs.umich.edu .name(name() + ".timesIdled") 4784519Sgblack@eecs.umich.edu .desc("Number of times that the entire CPU went into an idle state and" 4795063Sgblack@eecs.umich.edu " unscheduled itself") 4805063Sgblack@eecs.umich.edu .prereq(timesIdled); 4815063Sgblack@eecs.umich.edu 4825063Sgblack@eecs.umich.edu idleCycles 4835063Sgblack@eecs.umich.edu .name(name() + ".idleCycles") 4845063Sgblack@eecs.umich.edu .desc("Total number of cycles that the CPU has spent unscheduled due " 4855063Sgblack@eecs.umich.edu "to idling") 4865063Sgblack@eecs.umich.edu .prereq(idleCycles); 4875063Sgblack@eecs.umich.edu 4885063Sgblack@eecs.umich.edu quiesceCycles 4895063Sgblack@eecs.umich.edu .name(name() + ".quiesceCycles") 4905063Sgblack@eecs.umich.edu .desc("Total number of cycles that CPU has spent quiesced or waiting " 4915040Sgblack@eecs.umich.edu "for an interrupt") 4925040Sgblack@eecs.umich.edu .prereq(quiesceCycles); 4934595Sgblack@eecs.umich.edu 4945040Sgblack@eecs.umich.edu // Number of Instructions simulated 4955040Sgblack@eecs.umich.edu // -------------------------------- 4964595Sgblack@eecs.umich.edu // Should probably be in Base CPU but need templated 4975040Sgblack@eecs.umich.edu // MaxThreads so put in here instead 4985040Sgblack@eecs.umich.edu committedInsts 4994732Sgblack@eecs.umich.edu .init(numThreads) 5005138Sgblack@eecs.umich.edu .name(name() + ".committedInsts") 5015040Sgblack@eecs.umich.edu .desc("Number of Instructions Simulated"); 5025040Sgblack@eecs.umich.edu 5035040Sgblack@eecs.umich.edu committedOps 5045040Sgblack@eecs.umich.edu .init(numThreads) 5054732Sgblack@eecs.umich.edu .name(name() + ".committedOps") 5065138Sgblack@eecs.umich.edu .desc("Number of Ops (including micro ops) Simulated"); 5075040Sgblack@eecs.umich.edu 5085040Sgblack@eecs.umich.edu totalCommittedInsts 5095040Sgblack@eecs.umich.edu .name(name() + ".committedInsts_total") 5105040Sgblack@eecs.umich.edu .desc("Number of Instructions Simulated"); 5115040Sgblack@eecs.umich.edu 5125040Sgblack@eecs.umich.edu cpi 5135040Sgblack@eecs.umich.edu .name(name() + ".cpi") 5145040Sgblack@eecs.umich.edu .desc("CPI: Cycles Per Instruction") 5155040Sgblack@eecs.umich.edu .precision(6); 5165040Sgblack@eecs.umich.edu cpi = numCycles / committedInsts; 5175040Sgblack@eecs.umich.edu 5185065Sgblack@eecs.umich.edu totalCpi 5195065Sgblack@eecs.umich.edu .name(name() + ".cpi_total") 5205065Sgblack@eecs.umich.edu .desc("CPI: Total CPI of All Threads") 5215065Sgblack@eecs.umich.edu .precision(6); 5225065Sgblack@eecs.umich.edu totalCpi = numCycles / totalCommittedInsts; 5235063Sgblack@eecs.umich.edu 5245040Sgblack@eecs.umich.edu ipc 5255063Sgblack@eecs.umich.edu .name(name() + ".ipc") 5265063Sgblack@eecs.umich.edu .desc("IPC: Instructions Per Cycle") 5275063Sgblack@eecs.umich.edu .precision(6); 5285063Sgblack@eecs.umich.edu ipc = committedInsts / numCycles; 5295063Sgblack@eecs.umich.edu 5305063Sgblack@eecs.umich.edu totalIpc 5315063Sgblack@eecs.umich.edu .name(name() + ".ipc_total") 5325063Sgblack@eecs.umich.edu .desc("IPC: Total IPC of All Threads") 5335063Sgblack@eecs.umich.edu .precision(6); 5345040Sgblack@eecs.umich.edu totalIpc = totalCommittedInsts / numCycles; 5355040Sgblack@eecs.umich.edu 5365063Sgblack@eecs.umich.edu this->fetch.regStats(); 5375040Sgblack@eecs.umich.edu this->decode.regStats(); 5385063Sgblack@eecs.umich.edu this->rename.regStats(); 5394809Sgblack@eecs.umich.edu this->iew.regStats(); 5405063Sgblack@eecs.umich.edu this->commit.regStats(); 5415063Sgblack@eecs.umich.edu this->rob.regStats(); 5425063Sgblack@eecs.umich.edu 5435063Sgblack@eecs.umich.edu intRegfileReads 5445063Sgblack@eecs.umich.edu .name(name() + ".int_regfile_reads") 5455063Sgblack@eecs.umich.edu .desc("number of integer regfile reads") 5465063Sgblack@eecs.umich.edu .prereq(intRegfileReads); 5475040Sgblack@eecs.umich.edu 5485040Sgblack@eecs.umich.edu intRegfileWrites 5495063Sgblack@eecs.umich.edu .name(name() + ".int_regfile_writes") 5505063Sgblack@eecs.umich.edu .desc("number of integer regfile writes") 5515040Sgblack@eecs.umich.edu .prereq(intRegfileWrites); 5525063Sgblack@eecs.umich.edu 5535063Sgblack@eecs.umich.edu fpRegfileReads 5545063Sgblack@eecs.umich.edu .name(name() + ".fp_regfile_reads") 5555063Sgblack@eecs.umich.edu .desc("number of floating regfile reads") 5565063Sgblack@eecs.umich.edu .prereq(fpRegfileReads); 5575063Sgblack@eecs.umich.edu 5585063Sgblack@eecs.umich.edu fpRegfileWrites 5595063Sgblack@eecs.umich.edu .name(name() + ".fp_regfile_writes") 5605063Sgblack@eecs.umich.edu .desc("number of floating regfile writes") 5615063Sgblack@eecs.umich.edu .prereq(fpRegfileWrites); 5625063Sgblack@eecs.umich.edu 5635063Sgblack@eecs.umich.edu ccRegfileReads 5645062Sgblack@eecs.umich.edu .name(name() + ".cc_regfile_reads") 5655075Sgblack@eecs.umich.edu .desc("number of cc regfile reads") 5665075Sgblack@eecs.umich.edu .prereq(ccRegfileReads); 5675040Sgblack@eecs.umich.edu 5685075Sgblack@eecs.umich.edu ccRegfileWrites 5695075Sgblack@eecs.umich.edu .name(name() + ".cc_regfile_writes") 5705075Sgblack@eecs.umich.edu .desc("number of cc regfile writes") 5715075Sgblack@eecs.umich.edu .prereq(ccRegfileWrites); 5725075Sgblack@eecs.umich.edu 5735075Sgblack@eecs.umich.edu miscRegfileReads 5745075Sgblack@eecs.umich.edu .name(name() + ".misc_regfile_reads") 5755075Sgblack@eecs.umich.edu .desc("number of misc regfile reads") 5765075Sgblack@eecs.umich.edu .prereq(miscRegfileReads); 5775075Sgblack@eecs.umich.edu 5785075Sgblack@eecs.umich.edu miscRegfileWrites 5795075Sgblack@eecs.umich.edu .name(name() + ".misc_regfile_writes") 5805075Sgblack@eecs.umich.edu .desc("number of misc regfile writes") 5815075Sgblack@eecs.umich.edu .prereq(miscRegfileWrites); 5825075Sgblack@eecs.umich.edu} 5835040Sgblack@eecs.umich.edu 5844823Sgblack@eecs.umich.edutemplate <class Impl> 5855075Sgblack@eecs.umich.eduvoid 5865075Sgblack@eecs.umich.eduFullO3CPU<Impl>::tick() 5875075Sgblack@eecs.umich.edu{ 5885075Sgblack@eecs.umich.edu DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 5895075Sgblack@eecs.umich.edu assert(!switchedOut()); 5905075Sgblack@eecs.umich.edu assert(getDrainState() != Drainable::Drained); 5915075Sgblack@eecs.umich.edu 5925075Sgblack@eecs.umich.edu ++numCycles; 5935075Sgblack@eecs.umich.edu 5945075Sgblack@eecs.umich.edu// activity = false; 5955075Sgblack@eecs.umich.edu 5965075Sgblack@eecs.umich.edu //Tick each of the stages 5975075Sgblack@eecs.umich.edu fetch.tick(); 5985075Sgblack@eecs.umich.edu 5995075Sgblack@eecs.umich.edu decode.tick(); 6005075Sgblack@eecs.umich.edu 6015075Sgblack@eecs.umich.edu rename.tick(); 6025075Sgblack@eecs.umich.edu 6035075Sgblack@eecs.umich.edu iew.tick(); 6045075Sgblack@eecs.umich.edu 6055075Sgblack@eecs.umich.edu commit.tick(); 6065075Sgblack@eecs.umich.edu 6075075Sgblack@eecs.umich.edu if (!FullSystem) 6085075Sgblack@eecs.umich.edu doContextSwitch(); 6095075Sgblack@eecs.umich.edu 6105075Sgblack@eecs.umich.edu // Now advance the time buffers 6115075Sgblack@eecs.umich.edu timeBuffer.advance(); 6125075Sgblack@eecs.umich.edu 6135075Sgblack@eecs.umich.edu fetchQueue.advance(); 6145075Sgblack@eecs.umich.edu decodeQueue.advance(); 6155075Sgblack@eecs.umich.edu renameQueue.advance(); 6165075Sgblack@eecs.umich.edu iewQueue.advance(); 6175075Sgblack@eecs.umich.edu 6184732Sgblack@eecs.umich.edu activityRec.advance(); 6195075Sgblack@eecs.umich.edu 6205075Sgblack@eecs.umich.edu if (removeInstsThisCycle) { 6215075Sgblack@eecs.umich.edu cleanUpRemovedInsts(); 6225075Sgblack@eecs.umich.edu } 6235075Sgblack@eecs.umich.edu 6245040Sgblack@eecs.umich.edu if (!tickEvent.scheduled()) { 6255040Sgblack@eecs.umich.edu if (_status == SwitchedOut) { 6265040Sgblack@eecs.umich.edu DPRINTF(O3CPU, "Switched out!\n"); 6275040Sgblack@eecs.umich.edu // increment stat 6285040Sgblack@eecs.umich.edu lastRunningCycle = curCycle(); 6294732Sgblack@eecs.umich.edu } else if (!activityRec.active() || _status == Idle) { 6305040Sgblack@eecs.umich.edu DPRINTF(O3CPU, "Idle!\n"); 6315076Sgblack@eecs.umich.edu lastRunningCycle = curCycle(); 6325040Sgblack@eecs.umich.edu timesIdled++; 6334756Sgblack@eecs.umich.edu } else { 6344823Sgblack@eecs.umich.edu schedule(tickEvent, clockEdge(Cycles(1))); 6355040Sgblack@eecs.umich.edu DPRINTF(O3CPU, "Scheduling next tick!\n"); 6365076Sgblack@eecs.umich.edu } 6375076Sgblack@eecs.umich.edu } 6385076Sgblack@eecs.umich.edu 6395076Sgblack@eecs.umich.edu if (!FullSystem) 6405076Sgblack@eecs.umich.edu updateThreadPriority(); 6415076Sgblack@eecs.umich.edu 6425076Sgblack@eecs.umich.edu tryDrain(); 6435076Sgblack@eecs.umich.edu} 6445076Sgblack@eecs.umich.edu 6455076Sgblack@eecs.umich.edutemplate <class Impl> 6465076Sgblack@eecs.umich.eduvoid 6475076Sgblack@eecs.umich.eduFullO3CPU<Impl>::init() 6485076Sgblack@eecs.umich.edu{ 6495076Sgblack@eecs.umich.edu BaseCPU::init(); 6505076Sgblack@eecs.umich.edu 6515076Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; ++tid) { 6525076Sgblack@eecs.umich.edu // Set noSquashFromTC so that the CPU doesn't squash when initially 6535076Sgblack@eecs.umich.edu // setting up registers. 6545076Sgblack@eecs.umich.edu thread[tid]->noSquashFromTC = true; 6555076Sgblack@eecs.umich.edu // Initialise the ThreadContext's memory proxies 6565076Sgblack@eecs.umich.edu thread[tid]->initMemProxies(thread[tid]->getTC()); 6575040Sgblack@eecs.umich.edu } 6585076Sgblack@eecs.umich.edu 6595040Sgblack@eecs.umich.edu if (FullSystem && !params()->switched_out) { 6604756Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 6614732Sgblack@eecs.umich.edu ThreadContext *src_tc = threadContexts[tid]; 6624732Sgblack@eecs.umich.edu TheISA::initCPU(src_tc, src_tc->contextId()); 6634732Sgblack@eecs.umich.edu } 6644732Sgblack@eecs.umich.edu } 6654823Sgblack@eecs.umich.edu 6665040Sgblack@eecs.umich.edu // Clear noSquashFromTC. 6675076Sgblack@eecs.umich.edu for (int tid = 0; tid < numThreads; ++tid) 6685076Sgblack@eecs.umich.edu thread[tid]->noSquashFromTC = false; 6695076Sgblack@eecs.umich.edu 6705076Sgblack@eecs.umich.edu commit.setThreads(thread); 6715076Sgblack@eecs.umich.edu} 6725076Sgblack@eecs.umich.edu 6735076Sgblack@eecs.umich.edutemplate <class Impl> 6745076Sgblack@eecs.umich.eduvoid 6755076Sgblack@eecs.umich.eduFullO3CPU<Impl>::startup() 6765076Sgblack@eecs.umich.edu{ 6775076Sgblack@eecs.umich.edu for (int tid = 0; tid < numThreads; ++tid) 6785076Sgblack@eecs.umich.edu isa[tid]->startup(threadContexts[tid]); 6795076Sgblack@eecs.umich.edu 6805076Sgblack@eecs.umich.edu fetch.startupStage(); 6815076Sgblack@eecs.umich.edu decode.startupStage(); 6825076Sgblack@eecs.umich.edu iew.startupStage(); 6835076Sgblack@eecs.umich.edu rename.startupStage(); 6845040Sgblack@eecs.umich.edu commit.startupStage(); 6855076Sgblack@eecs.umich.edu} 6865040Sgblack@eecs.umich.edu 6874756Sgblack@eecs.umich.edutemplate <class Impl> 6884732Sgblack@eecs.umich.eduvoid 6894732Sgblack@eecs.umich.eduFullO3CPU<Impl>::activateThread(ThreadID tid) 6904732Sgblack@eecs.umich.edu{ 6914732Sgblack@eecs.umich.edu list<ThreadID>::iterator isActive = 6925032Sgblack@eecs.umich.edu std::find(activeThreads.begin(), activeThreads.end(), tid); 6934823Sgblack@eecs.umich.edu 6945040Sgblack@eecs.umich.edu DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid); 6955076Sgblack@eecs.umich.edu assert(!switchedOut()); 6965076Sgblack@eecs.umich.edu 6975076Sgblack@eecs.umich.edu if (isActive == activeThreads.end()) { 6985076Sgblack@eecs.umich.edu DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 6995076Sgblack@eecs.umich.edu tid); 7005076Sgblack@eecs.umich.edu 7015076Sgblack@eecs.umich.edu activeThreads.push_back(tid); 7025076Sgblack@eecs.umich.edu } 7035076Sgblack@eecs.umich.edu} 7045076Sgblack@eecs.umich.edu 7055076Sgblack@eecs.umich.edutemplate <class Impl> 7065076Sgblack@eecs.umich.eduvoid 7075076Sgblack@eecs.umich.eduFullO3CPU<Impl>::deactivateThread(ThreadID tid) 7085076Sgblack@eecs.umich.edu{ 7095040Sgblack@eecs.umich.edu //Remove From Active List, if Active 7105076Sgblack@eecs.umich.edu list<ThreadID>::iterator thread_it = 7115040Sgblack@eecs.umich.edu std::find(activeThreads.begin(), activeThreads.end(), tid); 7124732Sgblack@eecs.umich.edu 7134756Sgblack@eecs.umich.edu DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid); 7144732Sgblack@eecs.umich.edu assert(!switchedOut()); 7154732Sgblack@eecs.umich.edu 7164823Sgblack@eecs.umich.edu if (thread_it != activeThreads.end()) { 7174823Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 7184732Sgblack@eecs.umich.edu tid); 7194732Sgblack@eecs.umich.edu activeThreads.erase(thread_it); 7204732Sgblack@eecs.umich.edu } 7214732Sgblack@eecs.umich.edu} 7225040Sgblack@eecs.umich.edu 7235076Sgblack@eecs.umich.edutemplate <class Impl> 7245076Sgblack@eecs.umich.eduCounter 7255076Sgblack@eecs.umich.eduFullO3CPU<Impl>::totalInsts() const 7265076Sgblack@eecs.umich.edu{ 7275076Sgblack@eecs.umich.edu Counter total(0); 7285076Sgblack@eecs.umich.edu 7295076Sgblack@eecs.umich.edu ThreadID size = thread.size(); 7305076Sgblack@eecs.umich.edu for (ThreadID i = 0; i < size; i++) 7315076Sgblack@eecs.umich.edu total += thread[i]->numInst; 7325076Sgblack@eecs.umich.edu 7335076Sgblack@eecs.umich.edu return total; 7345076Sgblack@eecs.umich.edu} 7355076Sgblack@eecs.umich.edu 7365076Sgblack@eecs.umich.edutemplate <class Impl> 7375076Sgblack@eecs.umich.eduCounter 7385076Sgblack@eecs.umich.eduFullO3CPU<Impl>::totalOps() const 7395076Sgblack@eecs.umich.edu{ 7405076Sgblack@eecs.umich.edu Counter total(0); 7415076Sgblack@eecs.umich.edu 7425076Sgblack@eecs.umich.edu ThreadID size = thread.size(); 7435040Sgblack@eecs.umich.edu for (ThreadID i = 0; i < size; i++) 7445076Sgblack@eecs.umich.edu total += thread[i]->numOp; 7455040Sgblack@eecs.umich.edu 7464733Sgblack@eecs.umich.edu return total; 7474756Sgblack@eecs.umich.edu} 7484733Sgblack@eecs.umich.edu 7494733Sgblack@eecs.umich.edutemplate <class Impl> 7504733Sgblack@eecs.umich.eduvoid 7515138Sgblack@eecs.umich.eduFullO3CPU<Impl>::activateContext(ThreadID tid, Cycles delay) 7524733Sgblack@eecs.umich.edu{ 7534823Sgblack@eecs.umich.edu assert(!switchedOut()); 7544823Sgblack@eecs.umich.edu 7554733Sgblack@eecs.umich.edu // Needs to set each stage to running as well. 7564733Sgblack@eecs.umich.edu if (delay){ 7574733Sgblack@eecs.umich.edu DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " 7584733Sgblack@eecs.umich.edu "on cycle %d\n", tid, clockEdge(delay)); 7595040Sgblack@eecs.umich.edu scheduleActivateThreadEvent(tid, delay); 7605076Sgblack@eecs.umich.edu } else { 7615076Sgblack@eecs.umich.edu activateThread(tid); 7625076Sgblack@eecs.umich.edu } 7635076Sgblack@eecs.umich.edu 7645076Sgblack@eecs.umich.edu // We don't want to wake the CPU if it is drained. In that case, 7655076Sgblack@eecs.umich.edu // we just want to flag the thread as active and schedule the tick 7665076Sgblack@eecs.umich.edu // event from drainResume() instead. 7675076Sgblack@eecs.umich.edu if (getDrainState() == Drainable::Drained) 7685076Sgblack@eecs.umich.edu return; 7695076Sgblack@eecs.umich.edu 7705076Sgblack@eecs.umich.edu // If we are time 0 or if the last activation time is in the past, 7715076Sgblack@eecs.umich.edu // schedule the next tick and wake up the fetch unit 7725076Sgblack@eecs.umich.edu if (lastActivatedCycle == 0 || lastActivatedCycle < curTick()) { 7735076Sgblack@eecs.umich.edu scheduleTickEvent(delay); 7745076Sgblack@eecs.umich.edu 7755076Sgblack@eecs.umich.edu // Be sure to signal that there's some activity so the CPU doesn't 7765076Sgblack@eecs.umich.edu // deschedule itself. 7775076Sgblack@eecs.umich.edu activityRec.activity(); 7785040Sgblack@eecs.umich.edu fetch.wakeFromQuiesce(); 7795076Sgblack@eecs.umich.edu 7805040Sgblack@eecs.umich.edu Cycles cycles(curCycle() - lastRunningCycle); 7814732Sgblack@eecs.umich.edu // @todo: This is an oddity that is only here to match the stats 7824756Sgblack@eecs.umich.edu if (cycles != 0) 7834732Sgblack@eecs.umich.edu --cycles; 7844732Sgblack@eecs.umich.edu quiesceCycles += cycles; 7854823Sgblack@eecs.umich.edu 7864732Sgblack@eecs.umich.edu lastActivatedCycle = curTick(); 7874823Sgblack@eecs.umich.edu 7884732Sgblack@eecs.umich.edu _status = Running; 7894732Sgblack@eecs.umich.edu } 7904732Sgblack@eecs.umich.edu} 7914732Sgblack@eecs.umich.edu 7925040Sgblack@eecs.umich.edutemplate <class Impl> 7935076Sgblack@eecs.umich.edubool 7945076Sgblack@eecs.umich.eduFullO3CPU<Impl>::scheduleDeallocateContext(ThreadID tid, bool remove, 7955076Sgblack@eecs.umich.edu Cycles delay) 7965076Sgblack@eecs.umich.edu{ 7975076Sgblack@eecs.umich.edu // Schedule removal of thread data from CPU 7985076Sgblack@eecs.umich.edu if (delay){ 7995076Sgblack@eecs.umich.edu DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate " 8005076Sgblack@eecs.umich.edu "on tick %d\n", tid, clockEdge(delay)); 8015076Sgblack@eecs.umich.edu scheduleDeallocateContextEvent(tid, remove, delay); 8025076Sgblack@eecs.umich.edu return false; 8035076Sgblack@eecs.umich.edu } else { 8045076Sgblack@eecs.umich.edu deactivateThread(tid); 8055076Sgblack@eecs.umich.edu if (remove) 8065076Sgblack@eecs.umich.edu removeThread(tid); 8075076Sgblack@eecs.umich.edu return true; 8085076Sgblack@eecs.umich.edu } 8095076Sgblack@eecs.umich.edu} 8105076Sgblack@eecs.umich.edu 8115076Sgblack@eecs.umich.edutemplate <class Impl> 8125076Sgblack@eecs.umich.eduvoid 8135040Sgblack@eecs.umich.eduFullO3CPU<Impl>::suspendContext(ThreadID tid) 8145076Sgblack@eecs.umich.edu{ 8155040Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); 8164733Sgblack@eecs.umich.edu assert(!switchedOut()); 8174756Sgblack@eecs.umich.edu bool deallocated = scheduleDeallocateContext(tid, false, Cycles(1)); 8184733Sgblack@eecs.umich.edu // If this was the last thread then unschedule the tick event. 8194733Sgblack@eecs.umich.edu if ((activeThreads.size() == 1 && !deallocated) || 8204733Sgblack@eecs.umich.edu activeThreads.size() == 0) 8214823Sgblack@eecs.umich.edu unscheduleTickEvent(); 8225138Sgblack@eecs.umich.edu 8234733Sgblack@eecs.umich.edu DPRINTF(Quiesce, "Suspending Context\n"); 8244733Sgblack@eecs.umich.edu lastRunningCycle = curCycle(); 8254823Sgblack@eecs.umich.edu _status = Idle; 8264809Sgblack@eecs.umich.edu} 8274733Sgblack@eecs.umich.edu 8284733Sgblack@eecs.umich.edutemplate <class Impl> 8294733Sgblack@eecs.umich.eduvoid 8304733Sgblack@eecs.umich.eduFullO3CPU<Impl>::haltContext(ThreadID tid) 8315040Sgblack@eecs.umich.edu{ 8325076Sgblack@eecs.umich.edu //For now, this is the same as deallocate 8335076Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid); 8345076Sgblack@eecs.umich.edu assert(!switchedOut()); 8355076Sgblack@eecs.umich.edu scheduleDeallocateContext(tid, true, Cycles(1)); 8365076Sgblack@eecs.umich.edu} 8375076Sgblack@eecs.umich.edu 8385076Sgblack@eecs.umich.edutemplate <class Impl> 8395076Sgblack@eecs.umich.eduvoid 8405076Sgblack@eecs.umich.eduFullO3CPU<Impl>::insertThread(ThreadID tid) 8415076Sgblack@eecs.umich.edu{ 8425076Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); 8435076Sgblack@eecs.umich.edu // Will change now that the PC and thread state is internal to the CPU 8445076Sgblack@eecs.umich.edu // and not in the ThreadContext. 8455076Sgblack@eecs.umich.edu ThreadContext *src_tc; 8465076Sgblack@eecs.umich.edu if (FullSystem) 8475076Sgblack@eecs.umich.edu src_tc = system->threadContexts[tid]; 8485076Sgblack@eecs.umich.edu else 8495076Sgblack@eecs.umich.edu src_tc = tcBase(tid); 8505076Sgblack@eecs.umich.edu 8514732Sgblack@eecs.umich.edu //Bind Int Regs to Rename Map 8525040Sgblack@eecs.umich.edu for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 8535246Sgblack@eecs.umich.edu PhysRegIndex phys_reg = freeList.getIntReg(); 8545040Sgblack@eecs.umich.edu 8555040Sgblack@eecs.umich.edu renameMap[tid].setEntry(ireg,phys_reg); 8565040Sgblack@eecs.umich.edu scoreboard.setReg(phys_reg); 8575040Sgblack@eecs.umich.edu } 8585040Sgblack@eecs.umich.edu 8595426Sgblack@eecs.umich.edu //Bind Float Regs to Rename Map 8605426Sgblack@eecs.umich.edu int max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs; 8615426Sgblack@eecs.umich.edu for (int freg = TheISA::NumIntRegs; freg < max_reg; freg++) { 8625426Sgblack@eecs.umich.edu PhysRegIndex phys_reg = freeList.getFloatReg(); 8635426Sgblack@eecs.umich.edu 8645426Sgblack@eecs.umich.edu renameMap[tid].setEntry(freg,phys_reg); 8655426Sgblack@eecs.umich.edu scoreboard.setReg(phys_reg); 8665426Sgblack@eecs.umich.edu } 8675426Sgblack@eecs.umich.edu 8685426Sgblack@eecs.umich.edu //Bind condition-code Regs to Rename Map 8695040Sgblack@eecs.umich.edu max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs + TheISA::NumCCRegs; 8705246Sgblack@eecs.umich.edu for (int creg = TheISA::NumIntRegs + TheISA::NumFloatRegs; 8715040Sgblack@eecs.umich.edu creg < max_reg; creg++) { 8725040Sgblack@eecs.umich.edu PhysRegIndex phys_reg = freeList.getCCReg(); 8735040Sgblack@eecs.umich.edu 8745040Sgblack@eecs.umich.edu renameMap[tid].setEntry(creg,phys_reg); 8755426Sgblack@eecs.umich.edu scoreboard.setReg(phys_reg); 8765426Sgblack@eecs.umich.edu } 8775426Sgblack@eecs.umich.edu 8785040Sgblack@eecs.umich.edu //Copy Thread Data Into RegFile 8795040Sgblack@eecs.umich.edu //this->copyFromTC(tid); 8805116Sgblack@eecs.umich.edu 8814951Sgblack@eecs.umich.edu //Set PC/NPC/NNPC 8825011Sgblack@eecs.umich.edu pcState(src_tc->pcState(), tid); 8835011Sgblack@eecs.umich.edu 8845040Sgblack@eecs.umich.edu src_tc->setStatus(ThreadContext::Active); 8855040Sgblack@eecs.umich.edu 8865040Sgblack@eecs.umich.edu activateContext(tid, Cycles(1)); 8875040Sgblack@eecs.umich.edu 8885040Sgblack@eecs.umich.edu //Reset ROB/IQ/LSQ Entries 8894732Sgblack@eecs.umich.edu commit.rob->resetEntries(); 8905426Sgblack@eecs.umich.edu iew.resetEntries(); 8915426Sgblack@eecs.umich.edu} 8925426Sgblack@eecs.umich.edu 8935426Sgblack@eecs.umich.edutemplate <class Impl> 8945426Sgblack@eecs.umich.eduvoid 8955426Sgblack@eecs.umich.eduFullO3CPU<Impl>::removeThread(ThreadID tid) 8965426Sgblack@eecs.umich.edu{ 8975426Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid); 8985426Sgblack@eecs.umich.edu 8995426Sgblack@eecs.umich.edu // Copy Thread Data From RegFile 9005426Sgblack@eecs.umich.edu // If thread is suspended, it might be re-allocated 9015426Sgblack@eecs.umich.edu // this->copyToTC(tid); 9025426Sgblack@eecs.umich.edu 9035426Sgblack@eecs.umich.edu 9045040Sgblack@eecs.umich.edu // @todo: 2-27-2008: Fix how we free up rename mappings 9055040Sgblack@eecs.umich.edu // here to alleviate the case for double-freeing registers 9064823Sgblack@eecs.umich.edu // in SMT workloads. 9075239Sgblack@eecs.umich.edu 9085239Sgblack@eecs.umich.edu // Unbind Int Regs from Rename Map 9095239Sgblack@eecs.umich.edu for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 9105239Sgblack@eecs.umich.edu PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 9115007Sgblack@eecs.umich.edu 9125007Sgblack@eecs.umich.edu scoreboard.unsetReg(phys_reg); 9135040Sgblack@eecs.umich.edu freeList.addReg(phys_reg); 9145239Sgblack@eecs.umich.edu } 9155239Sgblack@eecs.umich.edu 9165239Sgblack@eecs.umich.edu // Unbind Float Regs from Rename Map 9175239Sgblack@eecs.umich.edu int max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs; 9185239Sgblack@eecs.umich.edu for (int freg = TheISA::NumIntRegs; freg < max_reg; freg++) { 9195239Sgblack@eecs.umich.edu PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 9205239Sgblack@eecs.umich.edu 9215239Sgblack@eecs.umich.edu scoreboard.unsetReg(phys_reg); 9224714Sgblack@eecs.umich.edu freeList.addReg(phys_reg); 9235040Sgblack@eecs.umich.edu } 9245239Sgblack@eecs.umich.edu 9255241Sgblack@eecs.umich.edu // Unbind condition-code Regs from Rename Map 9265296Sgblack@eecs.umich.edu max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs + TheISA::NumCCRegs; 9275296Sgblack@eecs.umich.edu for (int creg = TheISA::NumIntRegs + TheISA::NumFloatRegs; 9285296Sgblack@eecs.umich.edu creg < max_reg; creg++) { 9295296Sgblack@eecs.umich.edu PhysRegIndex phys_reg = renameMap[tid].lookup(creg); 9305296Sgblack@eecs.umich.edu 9315296Sgblack@eecs.umich.edu scoreboard.unsetReg(phys_reg); 9325296Sgblack@eecs.umich.edu freeList.addReg(phys_reg); 9335296Sgblack@eecs.umich.edu } 9345296Sgblack@eecs.umich.edu 9355296Sgblack@eecs.umich.edu // Squash Throughout Pipeline 9365296Sgblack@eecs.umich.edu DynInstPtr inst = commit.rob->readHeadInst(tid); 9375296Sgblack@eecs.umich.edu InstSeqNum squash_seq_num = inst->seqNum; 9385241Sgblack@eecs.umich.edu fetch.squash(0, squash_seq_num, inst, tid); 9395241Sgblack@eecs.umich.edu decode.squash(tid); 9405241Sgblack@eecs.umich.edu rename.squash(squash_seq_num, tid); 9415241Sgblack@eecs.umich.edu iew.squash(tid); 9425241Sgblack@eecs.umich.edu iew.ldstQueue.squash(squash_seq_num, tid); 9435241Sgblack@eecs.umich.edu commit.rob->squash(squash_seq_num, tid); 9445241Sgblack@eecs.umich.edu 9455241Sgblack@eecs.umich.edu 9465241Sgblack@eecs.umich.edu assert(iew.instQueue.getCount(tid) == 0); 9475241Sgblack@eecs.umich.edu assert(iew.ldstQueue.getCount(tid) == 0); 9485241Sgblack@eecs.umich.edu 9495241Sgblack@eecs.umich.edu // Reset ROB/IQ/LSQ Entries 9505241Sgblack@eecs.umich.edu 9515241Sgblack@eecs.umich.edu // Commented out for now. This should be possible to do by 9525241Sgblack@eecs.umich.edu // telling all the pipeline stages to drain first, and then 9535241Sgblack@eecs.umich.edu // checking until the drain completes. Once the pipeline is 9545241Sgblack@eecs.umich.edu // drained, call resetEntries(). - 10-09-06 ktlim 9555241Sgblack@eecs.umich.edu/* 9565241Sgblack@eecs.umich.edu if (activeThreads.size() >= 1) { 9575241Sgblack@eecs.umich.edu commit.rob->resetEntries(); 9585241Sgblack@eecs.umich.edu iew.resetEntries(); 9595241Sgblack@eecs.umich.edu } 9605241Sgblack@eecs.umich.edu*/ 9615241Sgblack@eecs.umich.edu} 9625241Sgblack@eecs.umich.edu 9635241Sgblack@eecs.umich.edu 9645241Sgblack@eecs.umich.edutemplate <class Impl> 9655241Sgblack@eecs.umich.eduvoid 9665241Sgblack@eecs.umich.eduFullO3CPU<Impl>::activateWhenReady(ThreadID tid) 9675241Sgblack@eecs.umich.edu{ 9685241Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming" 9695241Sgblack@eecs.umich.edu "(e.g. PhysRegs/ROB/IQ/LSQ) \n", 9705241Sgblack@eecs.umich.edu tid); 9715241Sgblack@eecs.umich.edu 9725241Sgblack@eecs.umich.edu bool ready = true; 9735241Sgblack@eecs.umich.edu 9745241Sgblack@eecs.umich.edu // Should these all be '<' not '>='? This seems backwards... 9755241Sgblack@eecs.umich.edu if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { 9765241Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 9775241Sgblack@eecs.umich.edu "Phys. Int. Regs.\n", 9785241Sgblack@eecs.umich.edu tid); 9795241Sgblack@eecs.umich.edu ready = false; 9805241Sgblack@eecs.umich.edu } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) { 9815241Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 9825241Sgblack@eecs.umich.edu "Phys. Float. Regs.\n", 9835241Sgblack@eecs.umich.edu tid); 9845241Sgblack@eecs.umich.edu ready = false; 9855241Sgblack@eecs.umich.edu } else if (freeList.numFreeCCRegs() >= TheISA::NumCCRegs) { 9865241Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 9875241Sgblack@eecs.umich.edu "Phys. CC. Regs.\n", 9885241Sgblack@eecs.umich.edu tid); 9895290Sgblack@eecs.umich.edu ready = false; 9905294Sgblack@eecs.umich.edu } else if (commit.rob->numFreeEntries() >= 9915672Sgblack@eecs.umich.edu commit.rob->entryAmount(activeThreads.size() + 1)) { 9925294Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 9935290Sgblack@eecs.umich.edu "ROB entries.\n", 9945294Sgblack@eecs.umich.edu tid); 9955290Sgblack@eecs.umich.edu ready = false; 9965294Sgblack@eecs.umich.edu } else if (iew.instQueue.numFreeEntries() >= 9975294Sgblack@eecs.umich.edu iew.instQueue.entryAmount(activeThreads.size() + 1)) { 9985290Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 9995294Sgblack@eecs.umich.edu "IQ entries.\n", 10005290Sgblack@eecs.umich.edu tid); 10015290Sgblack@eecs.umich.edu ready = false; 10025294Sgblack@eecs.umich.edu } else if (iew.ldstQueue.numFreeEntries() >= 10035290Sgblack@eecs.umich.edu iew.ldstQueue.entryAmount(activeThreads.size() + 1)) { 10045294Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 10055294Sgblack@eecs.umich.edu "LSQ entries.\n", 10065294Sgblack@eecs.umich.edu tid); 10075294Sgblack@eecs.umich.edu ready = false; 10085294Sgblack@eecs.umich.edu } 10095294Sgblack@eecs.umich.edu 10105294Sgblack@eecs.umich.edu if (ready) { 10115294Sgblack@eecs.umich.edu insertThread(tid); 10125294Sgblack@eecs.umich.edu 10135294Sgblack@eecs.umich.edu contextSwitch = false; 10145670Sgblack@eecs.umich.edu 10155294Sgblack@eecs.umich.edu cpuWaitList.remove(tid); 10165294Sgblack@eecs.umich.edu } else { 10175294Sgblack@eecs.umich.edu suspendContext(tid); 10185294Sgblack@eecs.umich.edu 10195294Sgblack@eecs.umich.edu //blocks fetch 10205294Sgblack@eecs.umich.edu contextSwitch = true; 10215294Sgblack@eecs.umich.edu 10225427Sgblack@eecs.umich.edu //@todo: dont always add to waitlist 10235427Sgblack@eecs.umich.edu //do waitlist 10245427Sgblack@eecs.umich.edu cpuWaitList.push_back(tid); 10255427Sgblack@eecs.umich.edu } 10265427Sgblack@eecs.umich.edu} 10275294Sgblack@eecs.umich.edu 10285294Sgblack@eecs.umich.edutemplate <class Impl> 10295294Sgblack@eecs.umich.eduFault 10305294Sgblack@eecs.umich.eduFullO3CPU<Impl>::hwrei(ThreadID tid) 10315294Sgblack@eecs.umich.edu{ 10325682Sgblack@eecs.umich.edu#if THE_ISA == ALPHA_ISA 10335682Sgblack@eecs.umich.edu // Need to clear the lock flag upon returning from an interrupt. 10345682Sgblack@eecs.umich.edu this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); 10355682Sgblack@eecs.umich.edu 10365682Sgblack@eecs.umich.edu this->thread[tid]->kernelStats->hwrei(); 10375682Sgblack@eecs.umich.edu 10385682Sgblack@eecs.umich.edu // FIXME: XXX check for interrupts? XXX 10395682Sgblack@eecs.umich.edu#endif 10405682Sgblack@eecs.umich.edu return NoFault; 10415682Sgblack@eecs.umich.edu} 10425682Sgblack@eecs.umich.edu 10435682Sgblack@eecs.umich.edutemplate <class Impl> 10445682Sgblack@eecs.umich.edubool 10455682Sgblack@eecs.umich.eduFullO3CPU<Impl>::simPalCheck(int palFunc, ThreadID tid) 10465682Sgblack@eecs.umich.edu{ 10475682Sgblack@eecs.umich.edu#if THE_ISA == ALPHA_ISA 10485428Sgblack@eecs.umich.edu if (this->thread[tid]->kernelStats) 10495428Sgblack@eecs.umich.edu this->thread[tid]->kernelStats->callpal(palFunc, 10505428Sgblack@eecs.umich.edu this->threadContexts[tid]); 10515428Sgblack@eecs.umich.edu 10525428Sgblack@eecs.umich.edu switch (palFunc) { 10535294Sgblack@eecs.umich.edu case PAL::halt: 10545424Sgblack@eecs.umich.edu halt(); 10555433Sgblack@eecs.umich.edu if (--System::numSystemsRunning == 0) 10565433Sgblack@eecs.umich.edu exitSimLoop("all cpus halted"); 10575433Sgblack@eecs.umich.edu break; 10585294Sgblack@eecs.umich.edu 10595428Sgblack@eecs.umich.edu case PAL::bpt: 10605428Sgblack@eecs.umich.edu case PAL::bugchk: 10615428Sgblack@eecs.umich.edu if (this->system->breakpoint()) 10625428Sgblack@eecs.umich.edu return false; 10635428Sgblack@eecs.umich.edu break; 10645428Sgblack@eecs.umich.edu } 10655428Sgblack@eecs.umich.edu#endif 10665428Sgblack@eecs.umich.edu return true; 10675428Sgblack@eecs.umich.edu} 10685428Sgblack@eecs.umich.edu 10695428Sgblack@eecs.umich.edutemplate <class Impl> 10705855Sgblack@eecs.umich.eduFault 10715853Sgblack@eecs.umich.eduFullO3CPU<Impl>::getInterrupts() 10725674Sgblack@eecs.umich.edu{ 10735857Sgblack@eecs.umich.edu // Check if there are any outstanding interrupts 10745674Sgblack@eecs.umich.edu return this->interrupts->getInterrupt(this->threadContexts[0]); 10755855Sgblack@eecs.umich.edu} 10765855Sgblack@eecs.umich.edu 10775853Sgblack@eecs.umich.edutemplate <class Impl> 10785861Snate@binkert.orgvoid 10795853Sgblack@eecs.umich.eduFullO3CPU<Impl>::processInterrupts(Fault interrupt) 10805853Sgblack@eecs.umich.edu{ 10815853Sgblack@eecs.umich.edu // Check for interrupts here. For now can copy the code that 10825674Sgblack@eecs.umich.edu // exists within isa_fullsys_traits.hh. Also assume that thread 0 10835428Sgblack@eecs.umich.edu // is the one that handles the interrupts. 10845433Sgblack@eecs.umich.edu // @todo: Possibly consolidate the interrupt checking code. 10855433Sgblack@eecs.umich.edu // @todo: Allow other threads to handle interrupts. 10865857Sgblack@eecs.umich.edu 10875433Sgblack@eecs.umich.edu assert(interrupt != NoFault); 10885433Sgblack@eecs.umich.edu this->interrupts->updateIntrInfo(this->threadContexts[0]); 10895673Sgblack@eecs.umich.edu 10905673Sgblack@eecs.umich.edu DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); 10915433Sgblack@eecs.umich.edu this->trap(interrupt, 0, NULL); 10925433Sgblack@eecs.umich.edu} 10935433Sgblack@eecs.umich.edu 10945433Sgblack@eecs.umich.edutemplate <class Impl> 10955857Sgblack@eecs.umich.eduvoid 10965433Sgblack@eecs.umich.eduFullO3CPU<Impl>::trap(Fault fault, ThreadID tid, StaticInstPtr inst) 10975433Sgblack@eecs.umich.edu{ 10985428Sgblack@eecs.umich.edu // Pass the thread's TC into the invoke method. 10995428Sgblack@eecs.umich.edu fault->invoke(this->threadContexts[tid], inst); 11005428Sgblack@eecs.umich.edu} 11015433Sgblack@eecs.umich.edu 11025433Sgblack@eecs.umich.edutemplate <class Impl> 11035433Sgblack@eecs.umich.eduvoid 11045433Sgblack@eecs.umich.eduFullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid) 11055679Sgblack@eecs.umich.edu{ 11065857Sgblack@eecs.umich.edu DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); 11075679Sgblack@eecs.umich.edu 11085857Sgblack@eecs.umich.edu DPRINTF(Activity,"Activity: syscall() called.\n"); 11095679Sgblack@eecs.umich.edu 11105428Sgblack@eecs.umich.edu // Temporarily increase this by one to account for the syscall 11115428Sgblack@eecs.umich.edu // instruction. 11125428Sgblack@eecs.umich.edu ++(this->thread[tid]->funcExeInst); 11135675Sgblack@eecs.umich.edu 11145675Sgblack@eecs.umich.edu // Execute the actual syscall. 11155679Sgblack@eecs.umich.edu this->thread[tid]->syscall(callnum); 11165675Sgblack@eecs.umich.edu 11175675Sgblack@eecs.umich.edu // Decrease funcExeInst by one as the normal commit will handle 11185675Sgblack@eecs.umich.edu // incrementing it. 11195675Sgblack@eecs.umich.edu --(this->thread[tid]->funcExeInst); 11205675Sgblack@eecs.umich.edu} 11215428Sgblack@eecs.umich.edu 11225899Sgblack@eecs.umich.edutemplate <class Impl> 11235899Sgblack@eecs.umich.eduvoid 11245899Sgblack@eecs.umich.eduFullO3CPU<Impl>::serializeThread(std::ostream &os, ThreadID tid) 11255899Sgblack@eecs.umich.edu{ 11265899Sgblack@eecs.umich.edu thread[tid]->serialize(os); 11275428Sgblack@eecs.umich.edu} 11285428Sgblack@eecs.umich.edu 11295428Sgblack@eecs.umich.edutemplate <class Impl> 11305294Sgblack@eecs.umich.eduvoid 11315294Sgblack@eecs.umich.eduFullO3CPU<Impl>::unserializeThread(Checkpoint *cp, const std::string §ion, 11325294Sgblack@eecs.umich.edu ThreadID tid) 11335294Sgblack@eecs.umich.edu{ 11345424Sgblack@eecs.umich.edu thread[tid]->unserialize(cp, section); 11355294Sgblack@eecs.umich.edu} 11365294Sgblack@eecs.umich.edu 11375294Sgblack@eecs.umich.edutemplate <class Impl> 11385294Sgblack@eecs.umich.eduunsigned int 11395294Sgblack@eecs.umich.eduFullO3CPU<Impl>::drain(DrainManager *drain_manager) 11405678Sgblack@eecs.umich.edu{ 11415294Sgblack@eecs.umich.edu // If the CPU isn't doing anything, then return immediately. 11425678Sgblack@eecs.umich.edu if (switchedOut()) { 11435678Sgblack@eecs.umich.edu setDrainState(Drainable::Drained); 11445678Sgblack@eecs.umich.edu return 0; 11455678Sgblack@eecs.umich.edu } 11465678Sgblack@eecs.umich.edu 11475678Sgblack@eecs.umich.edu DPRINTF(Drain, "Draining...\n"); 11485678Sgblack@eecs.umich.edu setDrainState(Drainable::Draining); 11495678Sgblack@eecs.umich.edu 11505678Sgblack@eecs.umich.edu // We only need to signal a drain to the commit stage as this 11515678Sgblack@eecs.umich.edu // initiates squashing controls the draining. Once the commit 11525678Sgblack@eecs.umich.edu // stage commits an instruction where it is safe to stop, it'll 11535678Sgblack@eecs.umich.edu // squash the rest of the instructions in the pipeline and force 11545678Sgblack@eecs.umich.edu // the fetch stage to stall. The pipeline will be drained once all 11555678Sgblack@eecs.umich.edu // in-flight instructions have retired. 11565678Sgblack@eecs.umich.edu commit.drain(); 11575678Sgblack@eecs.umich.edu 11585678Sgblack@eecs.umich.edu // Wake the CPU and record activity so everything can drain out if 11595678Sgblack@eecs.umich.edu // the CPU was not able to immediately drain. 11605294Sgblack@eecs.umich.edu if (!isDrained()) { 11615294Sgblack@eecs.umich.edu drainManager = drain_manager; 11625409Sgblack@eecs.umich.edu 11635409Sgblack@eecs.umich.edu wakeCPU(); 11645409Sgblack@eecs.umich.edu activityRec.activity(); 11655409Sgblack@eecs.umich.edu 11665409Sgblack@eecs.umich.edu DPRINTF(Drain, "CPU not drained\n"); 11675409Sgblack@eecs.umich.edu 11685409Sgblack@eecs.umich.edu return 1; 11695409Sgblack@eecs.umich.edu } else { 11705409Sgblack@eecs.umich.edu setDrainState(Drainable::Drained); 11715409Sgblack@eecs.umich.edu DPRINTF(Drain, "CPU is already drained\n"); 11725429Sgblack@eecs.umich.edu if (tickEvent.scheduled()) 11735429Sgblack@eecs.umich.edu deschedule(tickEvent); 11745429Sgblack@eecs.umich.edu 11755429Sgblack@eecs.umich.edu // Flush out any old data from the time buffers. In 11765429Sgblack@eecs.umich.edu // particular, there might be some data in flight from the 11775294Sgblack@eecs.umich.edu // fetch stage that isn't visible in any of the CPU buffers we 11785294Sgblack@eecs.umich.edu // test in isDrained(). 11795294Sgblack@eecs.umich.edu for (int i = 0; i < timeBuffer.getSize(); ++i) { 11805433Sgblack@eecs.umich.edu timeBuffer.advance(); 11815433Sgblack@eecs.umich.edu fetchQueue.advance(); 11825433Sgblack@eecs.umich.edu decodeQueue.advance(); 11835433Sgblack@eecs.umich.edu renameQueue.advance(); 11845433Sgblack@eecs.umich.edu iewQueue.advance(); 11855433Sgblack@eecs.umich.edu } 11865433Sgblack@eecs.umich.edu 11875433Sgblack@eecs.umich.edu drainSanityCheck(); 11885433Sgblack@eecs.umich.edu return 0; 11895433Sgblack@eecs.umich.edu } 11905433Sgblack@eecs.umich.edu} 11915433Sgblack@eecs.umich.edu 11925433Sgblack@eecs.umich.edutemplate <class Impl> 11935433Sgblack@eecs.umich.edubool 11945433Sgblack@eecs.umich.eduFullO3CPU<Impl>::tryDrain() 11955433Sgblack@eecs.umich.edu{ 11965433Sgblack@eecs.umich.edu if (!drainManager || !isDrained()) 11975433Sgblack@eecs.umich.edu return false; 11985433Sgblack@eecs.umich.edu 11995433Sgblack@eecs.umich.edu if (tickEvent.scheduled()) 12005433Sgblack@eecs.umich.edu deschedule(tickEvent); 12015433Sgblack@eecs.umich.edu 12025433Sgblack@eecs.umich.edu DPRINTF(Drain, "CPU done draining, processing drain event\n"); 12035433Sgblack@eecs.umich.edu drainManager->signalDrainDone(); 12045433Sgblack@eecs.umich.edu drainManager = NULL; 12055433Sgblack@eecs.umich.edu 12065433Sgblack@eecs.umich.edu return true; 12075433Sgblack@eecs.umich.edu} 12085433Sgblack@eecs.umich.edu 12095433Sgblack@eecs.umich.edutemplate <class Impl> 12105295Sgblack@eecs.umich.eduvoid 12115295Sgblack@eecs.umich.eduFullO3CPU<Impl>::drainSanityCheck() const 12125295Sgblack@eecs.umich.edu{ 12135294Sgblack@eecs.umich.edu assert(isDrained()); 12145290Sgblack@eecs.umich.edu fetch.drainSanityCheck(); 12154519Sgblack@eecs.umich.edu decode.drainSanityCheck(); 1216 rename.drainSanityCheck(); 1217 iew.drainSanityCheck(); 1218 commit.drainSanityCheck(); 1219} 1220 1221template <class Impl> 1222bool 1223FullO3CPU<Impl>::isDrained() const 1224{ 1225 bool drained(true); 1226 1227 for (ThreadID i = 0; i < thread.size(); ++i) { 1228 if (activateThreadEvent[i].scheduled()) { 1229 DPRINTF(Drain, "CPU not drained, tread %i has a " 1230 "pending activate event\n", i); 1231 drained = false; 1232 } 1233 if (deallocateContextEvent[i].scheduled()) { 1234 DPRINTF(Drain, "CPU not drained, tread %i has a " 1235 "pending deallocate context event\n", i); 1236 drained = false; 1237 } 1238 } 1239 1240 if (!instList.empty() || !removeList.empty()) { 1241 DPRINTF(Drain, "Main CPU structures not drained.\n"); 1242 drained = false; 1243 } 1244 1245 if (!fetch.isDrained()) { 1246 DPRINTF(Drain, "Fetch not drained.\n"); 1247 drained = false; 1248 } 1249 1250 if (!decode.isDrained()) { 1251 DPRINTF(Drain, "Decode not drained.\n"); 1252 drained = false; 1253 } 1254 1255 if (!rename.isDrained()) { 1256 DPRINTF(Drain, "Rename not drained.\n"); 1257 drained = false; 1258 } 1259 1260 if (!iew.isDrained()) { 1261 DPRINTF(Drain, "IEW not drained.\n"); 1262 drained = false; 1263 } 1264 1265 if (!commit.isDrained()) { 1266 DPRINTF(Drain, "Commit not drained.\n"); 1267 drained = false; 1268 } 1269 1270 return drained; 1271} 1272 1273template <class Impl> 1274void 1275FullO3CPU<Impl>::commitDrained(ThreadID tid) 1276{ 1277 fetch.drainStall(tid); 1278} 1279 1280template <class Impl> 1281void 1282FullO3CPU<Impl>::drainResume() 1283{ 1284 setDrainState(Drainable::Running); 1285 if (switchedOut()) 1286 return; 1287 1288 DPRINTF(Drain, "Resuming...\n"); 1289 verifyMemoryMode(); 1290 1291 fetch.drainResume(); 1292 commit.drainResume(); 1293 1294 _status = Idle; 1295 for (ThreadID i = 0; i < thread.size(); i++) { 1296 if (thread[i]->status() == ThreadContext::Active) { 1297 DPRINTF(Drain, "Activating thread: %i\n", i); 1298 activateThread(i); 1299 _status = Running; 1300 } 1301 } 1302 1303 assert(!tickEvent.scheduled()); 1304 if (_status == Running) 1305 schedule(tickEvent, nextCycle()); 1306} 1307 1308template <class Impl> 1309void 1310FullO3CPU<Impl>::switchOut() 1311{ 1312 DPRINTF(O3CPU, "Switching out\n"); 1313 BaseCPU::switchOut(); 1314 1315 activityRec.reset(); 1316 1317 _status = SwitchedOut; 1318 1319 if (checker) 1320 checker->switchOut(); 1321} 1322 1323template <class Impl> 1324void 1325FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 1326{ 1327 BaseCPU::takeOverFrom(oldCPU); 1328 1329 fetch.takeOverFrom(); 1330 decode.takeOverFrom(); 1331 rename.takeOverFrom(); 1332 iew.takeOverFrom(); 1333 commit.takeOverFrom(); 1334 1335 assert(!tickEvent.scheduled()); 1336 1337 FullO3CPU<Impl> *oldO3CPU = dynamic_cast<FullO3CPU<Impl>*>(oldCPU); 1338 if (oldO3CPU) 1339 globalSeqNum = oldO3CPU->globalSeqNum; 1340 1341 lastRunningCycle = curCycle(); 1342 _status = Idle; 1343} 1344 1345template <class Impl> 1346void 1347FullO3CPU<Impl>::verifyMemoryMode() const 1348{ 1349 if (!system->isTimingMode()) { 1350 fatal("The O3 CPU requires the memory system to be in " 1351 "'timing' mode.\n"); 1352 } 1353} 1354 1355template <class Impl> 1356TheISA::MiscReg 1357FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid) 1358{ 1359 return this->isa[tid]->readMiscRegNoEffect(misc_reg); 1360} 1361 1362template <class Impl> 1363TheISA::MiscReg 1364FullO3CPU<Impl>::readMiscReg(int misc_reg, ThreadID tid) 1365{ 1366 miscRegfileReads++; 1367 return this->isa[tid]->readMiscReg(misc_reg, tcBase(tid)); 1368} 1369 1370template <class Impl> 1371void 1372FullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, 1373 const TheISA::MiscReg &val, ThreadID tid) 1374{ 1375 this->isa[tid]->setMiscRegNoEffect(misc_reg, val); 1376} 1377 1378template <class Impl> 1379void 1380FullO3CPU<Impl>::setMiscReg(int misc_reg, 1381 const TheISA::MiscReg &val, ThreadID tid) 1382{ 1383 miscRegfileWrites++; 1384 this->isa[tid]->setMiscReg(misc_reg, val, tcBase(tid)); 1385} 1386 1387template <class Impl> 1388uint64_t 1389FullO3CPU<Impl>::readIntReg(int reg_idx) 1390{ 1391 intRegfileReads++; 1392 return regFile.readIntReg(reg_idx); 1393} 1394 1395template <class Impl> 1396FloatReg 1397FullO3CPU<Impl>::readFloatReg(int reg_idx) 1398{ 1399 fpRegfileReads++; 1400 return regFile.readFloatReg(reg_idx); 1401} 1402 1403template <class Impl> 1404FloatRegBits 1405FullO3CPU<Impl>::readFloatRegBits(int reg_idx) 1406{ 1407 fpRegfileReads++; 1408 return regFile.readFloatRegBits(reg_idx); 1409} 1410 1411template <class Impl> 1412CCReg 1413FullO3CPU<Impl>::readCCReg(int reg_idx) 1414{ 1415 ccRegfileReads++; 1416 return regFile.readCCReg(reg_idx); 1417} 1418 1419template <class Impl> 1420void 1421FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 1422{ 1423 intRegfileWrites++; 1424 regFile.setIntReg(reg_idx, val); 1425} 1426 1427template <class Impl> 1428void 1429FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 1430{ 1431 fpRegfileWrites++; 1432 regFile.setFloatReg(reg_idx, val); 1433} 1434 1435template <class Impl> 1436void 1437FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 1438{ 1439 fpRegfileWrites++; 1440 regFile.setFloatRegBits(reg_idx, val); 1441} 1442 1443template <class Impl> 1444void 1445FullO3CPU<Impl>::setCCReg(int reg_idx, CCReg val) 1446{ 1447 ccRegfileWrites++; 1448 regFile.setCCReg(reg_idx, val); 1449} 1450 1451template <class Impl> 1452uint64_t 1453FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid) 1454{ 1455 intRegfileReads++; 1456 PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx); 1457 1458 return regFile.readIntReg(phys_reg); 1459} 1460 1461template <class Impl> 1462float 1463FullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid) 1464{ 1465 fpRegfileReads++; 1466 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 1467 1468 return regFile.readFloatReg(phys_reg); 1469} 1470 1471template <class Impl> 1472uint64_t 1473FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid) 1474{ 1475 fpRegfileReads++; 1476 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 1477 1478 return regFile.readFloatRegBits(phys_reg); 1479} 1480 1481template <class Impl> 1482CCReg 1483FullO3CPU<Impl>::readArchCCReg(int reg_idx, ThreadID tid) 1484{ 1485 ccRegfileReads++; 1486 PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); 1487 1488 return regFile.readCCReg(phys_reg); 1489} 1490 1491template <class Impl> 1492void 1493FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid) 1494{ 1495 intRegfileWrites++; 1496 PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx); 1497 1498 regFile.setIntReg(phys_reg, val); 1499} 1500 1501template <class Impl> 1502void 1503FullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid) 1504{ 1505 fpRegfileWrites++; 1506 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 1507 1508 regFile.setFloatReg(phys_reg, val); 1509} 1510 1511template <class Impl> 1512void 1513FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid) 1514{ 1515 fpRegfileWrites++; 1516 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 1517 1518 regFile.setFloatRegBits(phys_reg, val); 1519} 1520 1521template <class Impl> 1522void 1523FullO3CPU<Impl>::setArchCCReg(int reg_idx, CCReg val, ThreadID tid) 1524{ 1525 ccRegfileWrites++; 1526 PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); 1527 1528 regFile.setCCReg(phys_reg, val); 1529} 1530 1531template <class Impl> 1532TheISA::PCState 1533FullO3CPU<Impl>::pcState(ThreadID tid) 1534{ 1535 return commit.pcState(tid); 1536} 1537 1538template <class Impl> 1539void 1540FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid) 1541{ 1542 commit.pcState(val, tid); 1543} 1544 1545template <class Impl> 1546Addr 1547FullO3CPU<Impl>::instAddr(ThreadID tid) 1548{ 1549 return commit.instAddr(tid); 1550} 1551 1552template <class Impl> 1553Addr 1554FullO3CPU<Impl>::nextInstAddr(ThreadID tid) 1555{ 1556 return commit.nextInstAddr(tid); 1557} 1558 1559template <class Impl> 1560MicroPC 1561FullO3CPU<Impl>::microPC(ThreadID tid) 1562{ 1563 return commit.microPC(tid); 1564} 1565 1566template <class Impl> 1567void 1568FullO3CPU<Impl>::squashFromTC(ThreadID tid) 1569{ 1570 this->thread[tid]->noSquashFromTC = true; 1571 this->commit.generateTCEvent(tid); 1572} 1573 1574template <class Impl> 1575typename FullO3CPU<Impl>::ListIt 1576FullO3CPU<Impl>::addInst(DynInstPtr &inst) 1577{ 1578 instList.push_back(inst); 1579 1580 return --(instList.end()); 1581} 1582 1583template <class Impl> 1584void 1585FullO3CPU<Impl>::instDone(ThreadID tid, DynInstPtr &inst) 1586{ 1587 // Keep an instruction count. 1588 if (!inst->isMicroop() || inst->isLastMicroop()) { 1589 thread[tid]->numInst++; 1590 thread[tid]->numInsts++; 1591 committedInsts[tid]++; 1592 totalCommittedInsts++; 1593 } 1594 thread[tid]->numOp++; 1595 thread[tid]->numOps++; 1596 committedOps[tid]++; 1597 1598 system->totalNumInsts++; 1599 // Check for instruction-count-based events. 1600 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1601 system->instEventQueue.serviceEvents(system->totalNumInsts); 1602} 1603 1604template <class Impl> 1605void 1606FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1607{ 1608 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s " 1609 "[sn:%lli]\n", 1610 inst->threadNumber, inst->pcState(), inst->seqNum); 1611 1612 removeInstsThisCycle = true; 1613 1614 // Remove the front instruction. 1615 removeList.push(inst->getInstListIt()); 1616} 1617 1618template <class Impl> 1619void 1620FullO3CPU<Impl>::removeInstsNotInROB(ThreadID tid) 1621{ 1622 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1623 " list.\n", tid); 1624 1625 ListIt end_it; 1626 1627 bool rob_empty = false; 1628 1629 if (instList.empty()) { 1630 return; 1631 } else if (rob.isEmpty(/*tid*/)) { 1632 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1633 end_it = instList.begin(); 1634 rob_empty = true; 1635 } else { 1636 end_it = (rob.readTailInst(tid))->getInstListIt(); 1637 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1638 } 1639 1640 removeInstsThisCycle = true; 1641 1642 ListIt inst_it = instList.end(); 1643 1644 inst_it--; 1645 1646 // Walk through the instruction list, removing any instructions 1647 // that were inserted after the given instruction iterator, end_it. 1648 while (inst_it != end_it) { 1649 assert(!instList.empty()); 1650 1651 squashInstIt(inst_it, tid); 1652 1653 inst_it--; 1654 } 1655 1656 // If the ROB was empty, then we actually need to remove the first 1657 // instruction as well. 1658 if (rob_empty) { 1659 squashInstIt(inst_it, tid); 1660 } 1661} 1662 1663template <class Impl> 1664void 1665FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid) 1666{ 1667 assert(!instList.empty()); 1668 1669 removeInstsThisCycle = true; 1670 1671 ListIt inst_iter = instList.end(); 1672 1673 inst_iter--; 1674 1675 DPRINTF(O3CPU, "Deleting instructions from instruction " 1676 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1677 tid, seq_num, (*inst_iter)->seqNum); 1678 1679 while ((*inst_iter)->seqNum > seq_num) { 1680 1681 bool break_loop = (inst_iter == instList.begin()); 1682 1683 squashInstIt(inst_iter, tid); 1684 1685 inst_iter--; 1686 1687 if (break_loop) 1688 break; 1689 } 1690} 1691 1692template <class Impl> 1693inline void 1694FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid) 1695{ 1696 if ((*instIt)->threadNumber == tid) { 1697 DPRINTF(O3CPU, "Squashing instruction, " 1698 "[tid:%i] [sn:%lli] PC %s\n", 1699 (*instIt)->threadNumber, 1700 (*instIt)->seqNum, 1701 (*instIt)->pcState()); 1702 1703 // Mark it as squashed. 1704 (*instIt)->setSquashed(); 1705 1706 // @todo: Formulate a consistent method for deleting 1707 // instructions from the instruction list 1708 // Remove the instruction from the list. 1709 removeList.push(instIt); 1710 } 1711} 1712 1713template <class Impl> 1714void 1715FullO3CPU<Impl>::cleanUpRemovedInsts() 1716{ 1717 while (!removeList.empty()) { 1718 DPRINTF(O3CPU, "Removing instruction, " 1719 "[tid:%i] [sn:%lli] PC %s\n", 1720 (*removeList.front())->threadNumber, 1721 (*removeList.front())->seqNum, 1722 (*removeList.front())->pcState()); 1723 1724 instList.erase(removeList.front()); 1725 1726 removeList.pop(); 1727 } 1728 1729 removeInstsThisCycle = false; 1730} 1731/* 1732template <class Impl> 1733void 1734FullO3CPU<Impl>::removeAllInsts() 1735{ 1736 instList.clear(); 1737} 1738*/ 1739template <class Impl> 1740void 1741FullO3CPU<Impl>::dumpInsts() 1742{ 1743 int num = 0; 1744 1745 ListIt inst_list_it = instList.begin(); 1746 1747 cprintf("Dumping Instruction List\n"); 1748 1749 while (inst_list_it != instList.end()) { 1750 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1751 "Squashed:%i\n\n", 1752 num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber, 1753 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1754 (*inst_list_it)->isSquashed()); 1755 inst_list_it++; 1756 ++num; 1757 } 1758} 1759/* 1760template <class Impl> 1761void 1762FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1763{ 1764 iew.wakeDependents(inst); 1765} 1766*/ 1767template <class Impl> 1768void 1769FullO3CPU<Impl>::wakeCPU() 1770{ 1771 if (activityRec.active() || tickEvent.scheduled()) { 1772 DPRINTF(Activity, "CPU already running.\n"); 1773 return; 1774 } 1775 1776 DPRINTF(Activity, "Waking up CPU\n"); 1777 1778 Cycles cycles(curCycle() - lastRunningCycle); 1779 // @todo: This is an oddity that is only here to match the stats 1780 if (cycles != 0) 1781 --cycles; 1782 idleCycles += cycles; 1783 numCycles += cycles; 1784 1785 schedule(tickEvent, clockEdge()); 1786} 1787 1788template <class Impl> 1789void 1790FullO3CPU<Impl>::wakeup() 1791{ 1792 if (this->thread[0]->status() != ThreadContext::Suspended) 1793 return; 1794 1795 this->wakeCPU(); 1796 1797 DPRINTF(Quiesce, "Suspended Processor woken\n"); 1798 this->threadContexts[0]->activate(); 1799} 1800 1801template <class Impl> 1802ThreadID 1803FullO3CPU<Impl>::getFreeTid() 1804{ 1805 for (ThreadID tid = 0; tid < numThreads; tid++) { 1806 if (!tids[tid]) { 1807 tids[tid] = true; 1808 return tid; 1809 } 1810 } 1811 1812 return InvalidThreadID; 1813} 1814 1815template <class Impl> 1816void 1817FullO3CPU<Impl>::doContextSwitch() 1818{ 1819 if (contextSwitch) { 1820 1821 //ADD CODE TO DEACTIVE THREAD HERE (???) 1822 1823 ThreadID size = cpuWaitList.size(); 1824 for (ThreadID tid = 0; tid < size; tid++) { 1825 activateWhenReady(tid); 1826 } 1827 1828 if (cpuWaitList.size() == 0) 1829 contextSwitch = true; 1830 } 1831} 1832 1833template <class Impl> 1834void 1835FullO3CPU<Impl>::updateThreadPriority() 1836{ 1837 if (activeThreads.size() > 1) { 1838 //DEFAULT TO ROUND ROBIN SCHEME 1839 //e.g. Move highest priority to end of thread list 1840 list<ThreadID>::iterator list_begin = activeThreads.begin(); 1841 1842 unsigned high_thread = *list_begin; 1843 1844 activeThreads.erase(list_begin); 1845 1846 activeThreads.push_back(high_thread); 1847 } 1848} 1849 1850// Forward declaration of FullO3CPU. 1851template class FullO3CPU<O3CPUImpl>; 1852