cpu.cc revision 10949
12330SN/A/*
22330SN/A * Copyright (c) 2012-2014 ARM Limited
32330SN/A * All rights reserved
42330SN/A *
52330SN/A * The license below extends only to copyright in the software and shall
62330SN/A * not be construed as granting a license to any other intellectual
72330SN/A * property including but not limited to intellectual property relating
82330SN/A * to a hardware implementation of the functionality of the software
92330SN/A * licensed hereunder.  You may use the software subject to the license
102330SN/A * terms below provided that you ensure that this notice is replicated
112330SN/A * unmodified and in its entirety in all distributions of the software,
122330SN/A * modified or unmodified, in source code or in binary form.
132330SN/A *
142330SN/A * Redistribution and use in source and binary forms, with or without
152330SN/A * modification, are permitted provided that the following conditions are
162330SN/A * met: redistributions of source code must retain the above copyright
172330SN/A * notice, this list of conditions and the following disclaimer;
182330SN/A * redistributions in binary form must reproduce the above copyright
192330SN/A * notice, this list of conditions and the following disclaimer in the
202330SN/A * documentation and/or other materials provided with the distribution;
212330SN/A * neither the name of the copyright holders nor the names of its
222330SN/A * contributors may be used to endorse or promote products derived from
232330SN/A * this software without specific prior written permission.
242330SN/A *
252330SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
262330SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
272689Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282689Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
292330SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
302292SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
312292SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
322292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
332292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
342980Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
356658Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
368229Snate@binkert.org *
372362SN/A * Authors: Andrew Bardsley
382680Sktlim@umich.edu */
392683Sktlim@umich.edu
402683Sktlim@umich.edu#include "arch/utility.hh"
412678Sktlim@umich.edu#include "cpu/minor/cpu.hh"
422292SN/A#include "cpu/minor/dyn_inst.hh"
432292SN/A#include "cpu/minor/fetch1.hh"
442292SN/A#include "cpu/minor/pipeline.hh"
453548Sgblack@eecs.umich.edu#include "debug/Drain.hh"
463548Sgblack@eecs.umich.edu#include "debug/MinorCPU.hh"
473548Sgblack@eecs.umich.edu#include "debug/Quiesce.hh"
488902Sandreas.hansson@arm.com
498902Sandreas.hansson@arm.comMinorCPU::MinorCPU(MinorCPUParams *params) :
502292SN/A    BaseCPU(params)
512862Sktlim@umich.edu{
522862Sktlim@umich.edu    /* This is only written for one thread at the moment */
532330SN/A    Minor::MinorThread *thread;
542330SN/A
552330SN/A    if (FullSystem) {
562330SN/A        thread = new Minor::MinorThread(this, 0, params->system, params->itb,
572330SN/A            params->dtb, params->isa[0]);
582330SN/A    } else {
5910905Sandreas.sandberg@arm.com        /* thread_id 0 */
602683Sktlim@umich.edu        thread = new Minor::MinorThread(this, 0, params->system,
612683Sktlim@umich.edu            params->workload[0], params->itb, params->dtb, params->isa[0]);
626331Sgblack@eecs.umich.edu    }
632683Sktlim@umich.edu
648735Sandreas.hanson@arm.com    threads.push_back(thread);
653486Sktlim@umich.edu
6611168Sandreas.hansson@arm.com    thread->setStatus(ThreadContext::Halted);
672862Sktlim@umich.edu
6811168Sandreas.hansson@arm.com    ThreadContext *tc = thread->getTC();
692862Sktlim@umich.edu
7010110Sandreas.hansson@arm.com    if (params->checker) {
712683Sktlim@umich.edu        fatal("The Minor model doesn't support checking (yet)\n");
7210190Sakash.bagdia@arm.com    }
7310190Sakash.bagdia@arm.com
7411005Sandreas.sandberg@arm.com    threadContexts.push_back(tc);
755714Shsul@eecs.umich.edu
7611005Sandreas.sandberg@arm.com    Minor::MinorDynInst::init();
775714Shsul@eecs.umich.edu
786221Snate@binkert.org    pipeline = new Minor::Pipeline(*this, *params);
792683Sktlim@umich.edu    activityRecorder = pipeline->getActivityRecorder();
8010110Sandreas.hansson@arm.com}
812683Sktlim@umich.edu
8210110Sandreas.hansson@arm.comMinorCPU::~MinorCPU()
832683Sktlim@umich.edu{
8410110Sandreas.hansson@arm.com    delete pipeline;
852683Sktlim@umich.edu
868706Sandreas.hansson@arm.com    for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) {
878706Sandreas.hansson@arm.com        delete threads[thread_id];
888706Sandreas.hansson@arm.com    }
898706Sandreas.hansson@arm.com}
908921Sandreas.hansson@arm.com
918706Sandreas.hansson@arm.comvoid
928706Sandreas.hansson@arm.comMinorCPU::init()
933675Sktlim@umich.edu{
942683Sktlim@umich.edu    BaseCPU::init();
952683Sktlim@umich.edu
962683Sktlim@umich.edu    if (!params()->switched_out &&
972683Sktlim@umich.edu        system->getMemoryMode() != Enums::timing)
982683Sktlim@umich.edu    {
992683Sktlim@umich.edu        fatal("The Minor CPU requires the memory system to be in "
1002683Sktlim@umich.edu            "'timing' mode.\n");
1012683Sktlim@umich.edu    }
1023548Sgblack@eecs.umich.edu
1032683Sktlim@umich.edu    /* Initialise the ThreadContext's memory proxies */
1049101SBrad.Beckmann@amd.com    for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) {
1052690Sktlim@umich.edu        ThreadContext *tc = getContext(thread_id);
1069101SBrad.Beckmann@amd.com
1078799Sgblack@eecs.umich.edu        tc->initMemProxies(tc);
1082683Sktlim@umich.edu    }
1092683Sktlim@umich.edu
11011886Sbrandon.potter@amd.com    /* Initialise CPUs (== threads in the ISA) */
11111886Sbrandon.potter@amd.com    if (FullSystem && !params()->switched_out) {
11211886Sbrandon.potter@amd.com        for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++)
11311886Sbrandon.potter@amd.com        {
11411886Sbrandon.potter@amd.com            ThreadContext *tc = getContext(thread_id);
11511886Sbrandon.potter@amd.com
11611886Sbrandon.potter@amd.com            /* Initialize CPU, including PC */
11711886Sbrandon.potter@amd.com            TheISA::initCPU(tc, cpuId());
11811886Sbrandon.potter@amd.com        }
11911886Sbrandon.potter@amd.com    }
12011886Sbrandon.potter@amd.com}
12111886Sbrandon.potter@amd.com
12211886Sbrandon.potter@amd.com/** Stats interface from SimObject (by way of BaseCPU) */
12311886Sbrandon.potter@amd.comvoid
12411886Sbrandon.potter@amd.comMinorCPU::regStats()
1259101SBrad.Beckmann@amd.com{
1262292SN/A    BaseCPU::regStats();
1272683Sktlim@umich.edu    stats.regStats(name(), *this);
1282683Sktlim@umich.edu    pipeline->regStats();
1292683Sktlim@umich.edu}
13013865Sgabeblack@google.com
1312683Sktlim@umich.eduvoid
1322683Sktlim@umich.eduMinorCPU::serializeThread(CheckpointOut &cp, ThreadID thread_id) const
1332683Sktlim@umich.edu{
1342683Sktlim@umich.edu    threads[thread_id]->serialize(cp);
1352683Sktlim@umich.edu}
1362683Sktlim@umich.edu
1372683Sktlim@umich.eduvoid
1382683Sktlim@umich.eduMinorCPU::unserializeThread(CheckpointIn &cp, ThreadID thread_id)
1392683Sktlim@umich.edu{
1402683Sktlim@umich.edu    if (thread_id != 0)
1412683Sktlim@umich.edu        fatal("Trying to load more than one thread into a MinorCPU\n");
1422683Sktlim@umich.edu
1433673Srdreslin@umich.edu    threads[thread_id]->unserialize(cp);
1443486Sktlim@umich.edu}
1452683Sktlim@umich.edu
1462683Sktlim@umich.eduvoid
1472683Sktlim@umich.eduMinorCPU::serialize(CheckpointOut &cp) const
1485999Snate@binkert.org{
1498834Satgutier@umich.edu    pipeline->serialize(cp);
1508834Satgutier@umich.edu    BaseCPU::serialize(cp);
1518834Satgutier@umich.edu}
1528834Satgutier@umich.edu
1532683Sktlim@umich.eduvoid
1545999Snate@binkert.orgMinorCPU::unserialize(CheckpointIn &cp)
1552683Sktlim@umich.edu{
1562683Sktlim@umich.edu    pipeline->unserialize(cp);
1572683Sktlim@umich.edu    BaseCPU::unserialize(cp);
1582683Sktlim@umich.edu}
1592683Sktlim@umich.edu
1602683Sktlim@umich.eduAddr
1612683Sktlim@umich.eduMinorCPU::dbg_vtophys(Addr addr)
1622683Sktlim@umich.edu{
1632683Sktlim@umich.edu    /* Note that this gives you the translation for thread 0 */
1642683Sktlim@umich.edu    panic("No implementation for vtophy\n");
1652683Sktlim@umich.edu
1662683Sktlim@umich.edu    return 0;
1673402Sktlim@umich.edu}
1683402Sktlim@umich.edu
1693402Sktlim@umich.eduvoid
1705714Shsul@eecs.umich.eduMinorCPU::wakeup()
17111005Sandreas.sandberg@arm.com{
1725714Shsul@eecs.umich.edu    DPRINTF(Drain, "MinorCPU wakeup\n");
1732292SN/A
1746221Snate@binkert.org    for (auto i = threads.begin(); i != threads.end(); i ++) {
1752292SN/A        if ((*i)->status() == ThreadContext::Suspended)
1762690Sktlim@umich.edu            (*i)->activate();
1772683Sktlim@umich.edu    }
1782683Sktlim@umich.edu
1792292SN/A    DPRINTF(Drain,"Suspended Processor awoke\n");
1802683Sktlim@umich.edu}
1812683Sktlim@umich.edu
1822292SN/Avoid
1832683Sktlim@umich.eduMinorCPU::startup()
1842292SN/A{
1852292SN/A    DPRINTF(MinorCPU, "MinorCPU startup\n");
1862292SN/A
1872292SN/A    BaseCPU::startup();
1882292SN/A
1893548Sgblack@eecs.umich.edu    for (auto i = threads.begin(); i != threads.end(); i ++)
1908777Sgblack@eecs.umich.edu        (*i)->startup();
1912683Sktlim@umich.edu
1928229Snate@binkert.org    /* Workaround cases in SE mode where a thread is activated with an
1938229Snate@binkert.org     * incorrect PC that is updated after the call to activate. This
1948706Sandreas.hansson@arm.com     * causes problems for Minor since it instantiates a virtual
1952683Sktlim@umich.edu     * branch instruction when activateContext() is called which ends
1968706Sandreas.hansson@arm.com     * up pointing to an illegal address.  */
1972683Sktlim@umich.edu    if (threads[0]->status() == ThreadContext::Active)
1988706Sandreas.hansson@arm.com        activateContext(0);
1998706Sandreas.hansson@arm.com}
2008852Sandreas.hansson@arm.com
2018852Sandreas.hansson@arm.comDrainState
2022678Sktlim@umich.eduMinorCPU::drain()
2032690Sktlim@umich.edu{
2042292SN/A    if (switchedOut()) {
2052292SN/A        DPRINTF(Drain, "Minor CPU switched out, draining not needed.\n");
2062292SN/A        return DrainState::Drained;
2072292SN/A    }
2082292SN/A
2092292SN/A    DPRINTF(Drain, "MinorCPU drain\n");
2102292SN/A
2112292SN/A    /* Need to suspend all threads and wait for Execute to idle.
2122292SN/A     * Tell Fetch1 not to fetch */
2132292SN/A    if (pipeline->drain()) {
2142292SN/A        DPRINTF(Drain, "MinorCPU drained\n");
2152292SN/A        return DrainState::Drained;
2162292SN/A    } else {
217        DPRINTF(Drain, "MinorCPU not finished draining\n");
218        return DrainState::Draining;
219    }
220}
221
222void
223MinorCPU::signalDrainDone()
224{
225    DPRINTF(Drain, "MinorCPU drain done\n");
226    Drainable::signalDrainDone();
227}
228
229void
230MinorCPU::drainResume()
231{
232    if (switchedOut()) {
233        DPRINTF(Drain, "drainResume while switched out.  Ignoring\n");
234        return;
235    }
236
237    DPRINTF(Drain, "MinorCPU drainResume\n");
238
239    if (!system->isTimingMode()) {
240        fatal("The Minor CPU requires the memory system to be in "
241            "'timing' mode.\n");
242    }
243
244    wakeup();
245    pipeline->drainResume();
246}
247
248void
249MinorCPU::memWriteback()
250{
251    DPRINTF(Drain, "MinorCPU memWriteback\n");
252}
253
254void
255MinorCPU::switchOut()
256{
257    DPRINTF(MinorCPU, "MinorCPU switchOut\n");
258
259    assert(!switchedOut());
260    BaseCPU::switchOut();
261
262    /* Check that the CPU is drained? */
263    activityRecorder->reset();
264}
265
266void
267MinorCPU::takeOverFrom(BaseCPU *old_cpu)
268{
269    DPRINTF(MinorCPU, "MinorCPU takeOverFrom\n");
270
271    BaseCPU::takeOverFrom(old_cpu);
272
273    /* Don't think I need to do anything here */
274}
275
276void
277MinorCPU::activateContext(ThreadID thread_id)
278{
279    DPRINTF(MinorCPU, "ActivateContext thread: %d", thread_id);
280
281    /* Do some cycle accounting.  lastStopped is reset to stop the
282     *  wakeup call on the pipeline from adding the quiesce period
283     *  to BaseCPU::numCycles */
284    stats.quiesceCycles += pipeline->cyclesSinceLastStopped();
285    pipeline->resetLastStopped();
286
287    /* Wake up the thread, wakeup the pipeline tick */
288    threads[thread_id]->activate();
289    wakeupOnEvent(Minor::Pipeline::CPUStageId);
290    pipeline->wakeupFetch();
291}
292
293void
294MinorCPU::suspendContext(ThreadID thread_id)
295{
296    DPRINTF(MinorCPU, "SuspendContext %d\n", thread_id);
297
298    threads[thread_id]->suspend();
299}
300
301void
302MinorCPU::wakeupOnEvent(unsigned int stage_id)
303{
304    DPRINTF(Quiesce, "Event wakeup from stage %d\n", stage_id);
305
306    /* Mark that some activity has taken place and start the pipeline */
307    activityRecorder->activateStage(stage_id);
308    pipeline->start();
309}
310
311MinorCPU *
312MinorCPUParams::create()
313{
314    numThreads = 1;
315    if (!FullSystem && workload.size() != 1)
316        panic("only one workload allowed");
317    return new MinorCPU(this);
318}
319
320MasterPort &MinorCPU::getInstPort()
321{
322    return pipeline->getInstPort();
323}
324
325MasterPort &MinorCPU::getDataPort()
326{
327    return pipeline->getDataPort();
328}
329
330Counter
331MinorCPU::totalInsts() const
332{
333    Counter ret = 0;
334
335    for (auto i = threads.begin(); i != threads.end(); i ++)
336        ret += (*i)->numInst;
337
338    return ret;
339}
340
341Counter
342MinorCPU::totalOps() const
343{
344    Counter ret = 0;
345
346    for (auto i = threads.begin(); i != threads.end(); i ++)
347        ret += (*i)->numOp;
348
349    return ret;
350}
351