cpu.cc revision 10949
12124SN/A/* 22124SN/A * Copyright (c) 2012-2014 ARM Limited 35222Sksewell@umich.edu * All rights reserved 45222Sksewell@umich.edu * 55222Sksewell@umich.edu * The license below extends only to copyright in the software and shall 65222Sksewell@umich.edu * not be construed as granting a license to any other intellectual 75222Sksewell@umich.edu * property including but not limited to intellectual property relating 85222Sksewell@umich.edu * to a hardware implementation of the functionality of the software 95222Sksewell@umich.edu * licensed hereunder. You may use the software subject to the license 105222Sksewell@umich.edu * terms below provided that you ensure that this notice is replicated 115222Sksewell@umich.edu * unmodified and in its entirety in all distributions of the software, 125222Sksewell@umich.edu * modified or unmodified, in source code or in binary form. 135222Sksewell@umich.edu * 145222Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without 155222Sksewell@umich.edu * modification, are permitted provided that the following conditions are 165222Sksewell@umich.edu * met: redistributions of source code must retain the above copyright 175222Sksewell@umich.edu * notice, this list of conditions and the following disclaimer; 185222Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright 195222Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the 205222Sksewell@umich.edu * documentation and/or other materials provided with the distribution; 215222Sksewell@umich.edu * neither the name of the copyright holders nor the names of its 225222Sksewell@umich.edu * contributors may be used to endorse or promote products derived from 235222Sksewell@umich.edu * this software without specific prior written permission. 245222Sksewell@umich.edu * 255222Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 265222Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 275222Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 285222Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 295222Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 305222Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 315222Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 325222Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 335222Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 345222Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 355222Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 365222Sksewell@umich.edu * 372022SN/A * Authors: Andrew Bardsley 382649Ssaidi@eecs.umich.edu */ 392649Ssaidi@eecs.umich.edu 402706Sksewell@umich.edu#include "arch/utility.hh" 412649Ssaidi@eecs.umich.edu#include "cpu/minor/cpu.hh" 422649Ssaidi@eecs.umich.edu#include "cpu/minor/dyn_inst.hh" 432022SN/A#include "cpu/minor/fetch1.hh" 442124SN/A#include "cpu/minor/pipeline.hh" 452124SN/A#include "debug/Drain.hh" 462124SN/A#include "debug/MinorCPU.hh" 472124SN/A#include "debug/Quiesce.hh" 482124SN/A 492124SN/AMinorCPU::MinorCPU(MinorCPUParams *params) : 502124SN/A BaseCPU(params) 512124SN/A{ 522124SN/A /* This is only written for one thread at the moment */ 532124SN/A Minor::MinorThread *thread; 542124SN/A 552124SN/A if (FullSystem) { 562124SN/A thread = new Minor::MinorThread(this, 0, params->system, params->itb, 572239SN/A params->dtb, params->isa[0]); 582124SN/A } else { 592124SN/A /* thread_id 0 */ 602124SN/A thread = new Minor::MinorThread(this, 0, params->system, 612124SN/A params->workload[0], params->itb, params->dtb, params->isa[0]); 622124SN/A } 632124SN/A 642124SN/A threads.push_back(thread); 652124SN/A 662124SN/A thread->setStatus(ThreadContext::Halted); 672742Sksewell@umich.edu 682022SN/A ThreadContext *tc = thread->getTC(); 692124SN/A 702022SN/A if (params->checker) { 712124SN/A fatal("The Minor model doesn't support checking (yet)\n"); 722124SN/A } 732022SN/A 742124SN/A threadContexts.push_back(tc); 752124SN/A 762124SN/A Minor::MinorDynInst::init(); 772124SN/A 784661Sksewell@umich.edu pipeline = new Minor::Pipeline(*this, *params); 794661Sksewell@umich.edu activityRecorder = pipeline->getActivityRecorder(); 802124SN/A} 812124SN/A 822742Sksewell@umich.eduMinorCPU::~MinorCPU() 832742Sksewell@umich.edu{ 842742Sksewell@umich.edu delete pipeline; 852742Sksewell@umich.edu 862742Sksewell@umich.edu for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) { 872742Sksewell@umich.edu delete threads[thread_id]; 882742Sksewell@umich.edu } 892742Sksewell@umich.edu} 902742Sksewell@umich.edu 912742Sksewell@umich.eduvoid 922742Sksewell@umich.eduMinorCPU::init() 932742Sksewell@umich.edu{ 942742Sksewell@umich.edu BaseCPU::init(); 952742Sksewell@umich.edu 962742Sksewell@umich.edu if (!params()->switched_out && 972742Sksewell@umich.edu system->getMemoryMode() != Enums::timing) 982742Sksewell@umich.edu { 992742Sksewell@umich.edu fatal("The Minor CPU requires the memory system to be in " 1002022SN/A "'timing' mode.\n"); 1012022SN/A } 1022124SN/A 1032022SN/A /* Initialise the ThreadContext's memory proxies */ 1042124SN/A for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) { 1052124SN/A ThreadContext *tc = getContext(thread_id); 1062124SN/A 1072742Sksewell@umich.edu tc->initMemProxies(tc); 1082239SN/A } 1092124SN/A 1102124SN/A /* Initialise CPUs (== threads in the ISA) */ 1112742Sksewell@umich.edu if (FullSystem && !params()->switched_out) { 1122742Sksewell@umich.edu for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) 1132742Sksewell@umich.edu { 1142742Sksewell@umich.edu ThreadContext *tc = getContext(thread_id); 1152742Sksewell@umich.edu 1162742Sksewell@umich.edu /* Initialize CPU, including PC */ 1172742Sksewell@umich.edu TheISA::initCPU(tc, cpuId()); 1182742Sksewell@umich.edu } 1194661Sksewell@umich.edu } 1204661Sksewell@umich.edu} 1214661Sksewell@umich.edu 1224661Sksewell@umich.edu/** Stats interface from SimObject (by way of BaseCPU) */ 1234661Sksewell@umich.eduvoid 1244661Sksewell@umich.eduMinorCPU::regStats() 1254661Sksewell@umich.edu{ 1265222Sksewell@umich.edu BaseCPU::regStats(); 1274661Sksewell@umich.edu stats.regStats(name(), *this); 1284661Sksewell@umich.edu pipeline->regStats(); 1295222Sksewell@umich.edu} 1304661Sksewell@umich.edu 1314661Sksewell@umich.eduvoid 1325222Sksewell@umich.eduMinorCPU::serializeThread(CheckpointOut &cp, ThreadID thread_id) const 1334661Sksewell@umich.edu{ 1344661Sksewell@umich.edu threads[thread_id]->serialize(cp); 1355222Sksewell@umich.edu} 1364661Sksewell@umich.edu 1374661Sksewell@umich.eduvoid 1385222Sksewell@umich.eduMinorCPU::unserializeThread(CheckpointIn &cp, ThreadID thread_id) 1394661Sksewell@umich.edu{ 1404661Sksewell@umich.edu if (thread_id != 0) 1414661Sksewell@umich.edu fatal("Trying to load more than one thread into a MinorCPU\n"); 1424661Sksewell@umich.edu 1434661Sksewell@umich.edu threads[thread_id]->unserialize(cp); 1444661Sksewell@umich.edu} 1454661Sksewell@umich.edu 1464661Sksewell@umich.eduvoid 1474661Sksewell@umich.eduMinorCPU::serialize(CheckpointOut &cp) const 1484661Sksewell@umich.edu{ 1494661Sksewell@umich.edu pipeline->serialize(cp); 1502022SN/A BaseCPU::serialize(cp); 1512022SN/A} 1522124SN/A 1532124SN/Avoid 1542124SN/AMinorCPU::unserialize(CheckpointIn &cp) 1552124SN/A{ 1562124SN/A pipeline->unserialize(cp); 1572124SN/A BaseCPU::unserialize(cp); 1582124SN/A} 1592124SN/A 1602124SN/AAddr 1612124SN/AMinorCPU::dbg_vtophys(Addr addr) 1622124SN/A{ 1632124SN/A /* Note that this gives you the translation for thread 0 */ 1642124SN/A panic("No implementation for vtophy\n"); 1652124SN/A 1662124SN/A return 0; 1674661Sksewell@umich.edu} 1682124SN/A 1692124SN/Avoid 1702124SN/AMinorCPU::wakeup() 1712124SN/A{ 1722124SN/A DPRINTF(Drain, "MinorCPU wakeup\n"); 1732124SN/A 1742124SN/A for (auto i = threads.begin(); i != threads.end(); i ++) { 1752124SN/A if ((*i)->status() == ThreadContext::Suspended) 1762124SN/A (*i)->activate(); 1772124SN/A } 1782124SN/A 1794661Sksewell@umich.edu DPRINTF(Drain,"Suspended Processor awoke\n"); 1802124SN/A} 1812124SN/A 1822124SN/Avoid 1832124SN/AMinorCPU::startup() 1842124SN/A{ 1852124SN/A DPRINTF(MinorCPU, "MinorCPU startup\n"); 1862124SN/A 1874661Sksewell@umich.edu BaseCPU::startup(); 1882124SN/A 1892124SN/A for (auto i = threads.begin(); i != threads.end(); i ++) 1902124SN/A (*i)->startup(); 1912124SN/A 1922124SN/A /* Workaround cases in SE mode where a thread is activated with an 1932124SN/A * incorrect PC that is updated after the call to activate. This 1944661Sksewell@umich.edu * causes problems for Minor since it instantiates a virtual 1954661Sksewell@umich.edu * branch instruction when activateContext() is called which ends 1962124SN/A * up pointing to an illegal address. */ 1972022SN/A if (threads[0]->status() == ThreadContext::Active) 1982022SN/A activateContext(0); 1992124SN/A} 2002124SN/A 2012132SN/ADrainState 2022022SN/AMinorCPU::drain() 2032124SN/A{ 2042124SN/A if (switchedOut()) { 2052124SN/A DPRINTF(Drain, "Minor CPU switched out, draining not needed.\n"); 2064661Sksewell@umich.edu return DrainState::Drained; 2072124SN/A } 2082124SN/A 2094661Sksewell@umich.edu DPRINTF(Drain, "MinorCPU drain\n"); 2104661Sksewell@umich.edu 2114661Sksewell@umich.edu /* Need to suspend all threads and wait for Execute to idle. 2122124SN/A * Tell Fetch1 not to fetch */ 2135222Sksewell@umich.edu if (pipeline->drain()) { 2145222Sksewell@umich.edu DPRINTF(Drain, "MinorCPU drained\n"); 2155222Sksewell@umich.edu return DrainState::Drained; 2165222Sksewell@umich.edu } else { 2175222Sksewell@umich.edu DPRINTF(Drain, "MinorCPU not finished draining\n"); 2185222Sksewell@umich.edu return DrainState::Draining; 2195222Sksewell@umich.edu } 2205222Sksewell@umich.edu} 2215222Sksewell@umich.edu 2223953Sstever@eecs.umich.eduvoid 2232124SN/AMinorCPU::signalDrainDone() 2242124SN/A{ 2252124SN/A DPRINTF(Drain, "MinorCPU drain done\n"); 2264661Sksewell@umich.edu Drainable::signalDrainDone(); 2272124SN/A} 2282124SN/A 2293953Sstever@eecs.umich.eduvoid 2302124SN/AMinorCPU::drainResume() 2313953Sstever@eecs.umich.edu{ 2322124SN/A if (switchedOut()) { 2333953Sstever@eecs.umich.edu DPRINTF(Drain, "drainResume while switched out. Ignoring\n"); 2343953Sstever@eecs.umich.edu return; 2354661Sksewell@umich.edu } 2362124SN/A 2372124SN/A DPRINTF(Drain, "MinorCPU drainResume\n"); 2383953Sstever@eecs.umich.edu 2392124SN/A if (!system->isTimingMode()) { 2403953Sstever@eecs.umich.edu fatal("The Minor CPU requires the memory system to be in " 2412124SN/A "'timing' mode.\n"); 2423953Sstever@eecs.umich.edu } 2433953Sstever@eecs.umich.edu 2444661Sksewell@umich.edu wakeup(); 2452124SN/A pipeline->drainResume(); 2462124SN/A} 2472124SN/A 2482124SN/Avoid 2492124SN/AMinorCPU::memWriteback() 2502124SN/A{ 2512124SN/A DPRINTF(Drain, "MinorCPU memWriteback\n"); 2522124SN/A} 2532124SN/A 2542132SN/Avoid 2552124SN/AMinorCPU::switchOut() 2562124SN/A{ 2572124SN/A DPRINTF(MinorCPU, "MinorCPU switchOut\n"); 2582124SN/A 2592132SN/A assert(!switchedOut()); 2602124SN/A BaseCPU::switchOut(); 2615222Sksewell@umich.edu 2625222Sksewell@umich.edu /* Check that the CPU is drained? */ 2635222Sksewell@umich.edu activityRecorder->reset(); 2645222Sksewell@umich.edu} 2655222Sksewell@umich.edu 2665222Sksewell@umich.eduvoid 2675222Sksewell@umich.eduMinorCPU::takeOverFrom(BaseCPU *old_cpu) 2682124SN/A{ 2692124SN/A DPRINTF(MinorCPU, "MinorCPU takeOverFrom\n"); 2703953Sstever@eecs.umich.edu 2712124SN/A BaseCPU::takeOverFrom(old_cpu); 2724661Sksewell@umich.edu 2732124SN/A /* Don't think I need to do anything here */ 2742124SN/A} 2752124SN/A 2762124SN/Avoid 2772124SN/AMinorCPU::activateContext(ThreadID thread_id) 2782124SN/A{ 2792124SN/A DPRINTF(MinorCPU, "ActivateContext thread: %d", thread_id); 2802124SN/A 2815222Sksewell@umich.edu /* Do some cycle accounting. lastStopped is reset to stop the 2825222Sksewell@umich.edu * wakeup call on the pipeline from adding the quiesce period 2835222Sksewell@umich.edu * to BaseCPU::numCycles */ 2845222Sksewell@umich.edu stats.quiesceCycles += pipeline->cyclesSinceLastStopped(); 2855222Sksewell@umich.edu pipeline->resetLastStopped(); 2865222Sksewell@umich.edu 2875222Sksewell@umich.edu /* Wake up the thread, wakeup the pipeline tick */ 2885222Sksewell@umich.edu threads[thread_id]->activate(); 2895222Sksewell@umich.edu wakeupOnEvent(Minor::Pipeline::CPUStageId); 2905222Sksewell@umich.edu pipeline->wakeupFetch(); 2915222Sksewell@umich.edu} 2925222Sksewell@umich.edu 2935222Sksewell@umich.eduvoid 2945222Sksewell@umich.eduMinorCPU::suspendContext(ThreadID thread_id) 2955222Sksewell@umich.edu{ 2965222Sksewell@umich.edu DPRINTF(MinorCPU, "SuspendContext %d\n", thread_id); 2975222Sksewell@umich.edu 2985222Sksewell@umich.edu threads[thread_id]->suspend(); 2995222Sksewell@umich.edu} 3005222Sksewell@umich.edu 3015222Sksewell@umich.eduvoid 3025222Sksewell@umich.eduMinorCPU::wakeupOnEvent(unsigned int stage_id) 3035222Sksewell@umich.edu{ 3045222Sksewell@umich.edu DPRINTF(Quiesce, "Event wakeup from stage %d\n", stage_id); 3055222Sksewell@umich.edu 3062124SN/A /* Mark that some activity has taken place and start the pipeline */ 3072132SN/A activityRecorder->activateStage(stage_id); 3082124SN/A pipeline->start(); 3092124SN/A} 3102124SN/A 3112239SN/AMinorCPU * 3125222Sksewell@umich.eduMinorCPUParams::create() 3132132SN/A{ 3142239SN/A numThreads = 1; 3155222Sksewell@umich.edu if (!FullSystem && workload.size() != 1) 3165222Sksewell@umich.edu panic("only one workload allowed"); 3175222Sksewell@umich.edu return new MinorCPU(this); 3185222Sksewell@umich.edu} 3195222Sksewell@umich.edu 3205222Sksewell@umich.eduMasterPort &MinorCPU::getInstPort() 3215222Sksewell@umich.edu{ 3222239SN/A return pipeline->getInstPort(); 3232239SN/A} 3244661Sksewell@umich.edu 3252239SN/AMasterPort &MinorCPU::getDataPort() 3262239SN/A{ 3274661Sksewell@umich.edu return pipeline->getDataPort(); 3282239SN/A} 3294661Sksewell@umich.edu 3304661Sksewell@umich.eduCounter 3314661Sksewell@umich.eduMinorCPU::totalInsts() const 3322239SN/A{ 3332124SN/A Counter ret = 0; 3342124SN/A 3352124SN/A for (auto i = threads.begin(); i != threads.end(); i ++) 3362124SN/A ret += (*i)->numInst; 3372124SN/A 3382124SN/A return ret; 3392132SN/A} 3402124SN/A 3412124SN/ACounter 3422124SN/AMinorCPU::totalOps() const 3432132SN/A{ 3442124SN/A Counter ret = 0; 3455222Sksewell@umich.edu 3465222Sksewell@umich.edu for (auto i = threads.begin(); i != threads.end(); i ++) 3475222Sksewell@umich.edu ret += (*i)->numOp; 3485222Sksewell@umich.edu 3495222Sksewell@umich.edu return ret; 3505222Sksewell@umich.edu} 3515222Sksewell@umich.edu