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