cpu.cc revision 14198
12330SN/A/*
22330SN/A * Copyright (c) 2012-2014, 2017 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 "cpu/minor/cpu.hh"
412678Sktlim@umich.edu
422292SN/A#include "arch/utility.hh"
432292SN/A#include "cpu/minor/dyn_inst.hh"
442292SN/A#include "cpu/minor/fetch1.hh"
453548Sgblack@eecs.umich.edu#include "cpu/minor/pipeline.hh"
463548Sgblack@eecs.umich.edu#include "debug/Drain.hh"
473548Sgblack@eecs.umich.edu#include "debug/MinorCPU.hh"
488902Sandreas.hansson@arm.com#include "debug/Quiesce.hh"
498902Sandreas.hansson@arm.com
502292SN/AMinorCPU::MinorCPU(MinorCPUParams *params) :
512862Sktlim@umich.edu    BaseCPU(params),
522862Sktlim@umich.edu    threadPolicy(params->threadPolicy)
532330SN/A{
542330SN/A    /* This is only written for one thread at the moment */
552330SN/A    Minor::MinorThread *thread;
562330SN/A
572330SN/A    for (ThreadID i = 0; i < numThreads; i++) {
582330SN/A        if (FullSystem) {
592292SN/A            thread = new Minor::MinorThread(this, i, params->system,
602683Sktlim@umich.edu                    params->itb, params->dtb, params->isa[i]);
612683Sktlim@umich.edu            thread->setStatus(ThreadContext::Halted);
626331Sgblack@eecs.umich.edu        } else {
632683Sktlim@umich.edu            thread = new Minor::MinorThread(this, i, params->system,
648735Sandreas.hanson@arm.com                    params->workload[i], params->itb, params->dtb,
653486Sktlim@umich.edu                    params->isa[i]);
662862Sktlim@umich.edu        }
672862Sktlim@umich.edu
682862Sktlim@umich.edu        threads.push_back(thread);
692862Sktlim@umich.edu        ThreadContext *tc = thread->getTC();
705712Shsul@eecs.umich.edu        threadContexts.push_back(tc);
712683Sktlim@umich.edu    }
725714Shsul@eecs.umich.edu
735714Shsul@eecs.umich.edu
745714Shsul@eecs.umich.edu    if (params->checker) {
755714Shsul@eecs.umich.edu        fatal("The Minor model doesn't support checking (yet)\n");
766221Snate@binkert.org    }
772683Sktlim@umich.edu
786221Snate@binkert.org    Minor::MinorDynInst::init();
792683Sktlim@umich.edu
802683Sktlim@umich.edu    pipeline = new Minor::Pipeline(*this, *params);
812683Sktlim@umich.edu    activityRecorder = pipeline->getActivityRecorder();
822683Sktlim@umich.edu}
832683Sktlim@umich.edu
848706Sandreas.hansson@arm.comMinorCPU::~MinorCPU()
858706Sandreas.hansson@arm.com{
868706Sandreas.hansson@arm.com    delete pipeline;
878706Sandreas.hansson@arm.com
888921Sandreas.hansson@arm.com    for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) {
898706Sandreas.hansson@arm.com        delete threads[thread_id];
908706Sandreas.hansson@arm.com    }
913675Sktlim@umich.edu}
922683Sktlim@umich.edu
932683Sktlim@umich.eduvoid
942683Sktlim@umich.eduMinorCPU::init()
952683Sktlim@umich.edu{
962683Sktlim@umich.edu    BaseCPU::init();
972683Sktlim@umich.edu
982683Sktlim@umich.edu    if (!params()->switched_out &&
992683Sktlim@umich.edu        system->getMemoryMode() != Enums::timing)
1003548Sgblack@eecs.umich.edu    {
1012683Sktlim@umich.edu        fatal("The Minor CPU requires the memory system to be in "
1028852Sandreas.hansson@arm.com            "'timing' mode.\n");
1032690Sktlim@umich.edu    }
1048852Sandreas.hansson@arm.com
1058799Sgblack@eecs.umich.edu    /* Initialise the ThreadContext's memory proxies */
1062683Sktlim@umich.edu    for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) {
1072683Sktlim@umich.edu        ThreadContext *tc = getContext(thread_id);
1088921Sandreas.hansson@arm.com
1092292SN/A        tc->initMemProxies(tc);
1102683Sktlim@umich.edu    }
1112683Sktlim@umich.edu
1122683Sktlim@umich.edu    /* Initialise CPUs (== threads in the ISA) */
1132683Sktlim@umich.edu    if (FullSystem && !params()->switched_out) {
1142683Sktlim@umich.edu        for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++)
1152683Sktlim@umich.edu        {
1162683Sktlim@umich.edu            ThreadContext *tc = getContext(thread_id);
1172683Sktlim@umich.edu
1182683Sktlim@umich.edu            /* Initialize CPU, including PC */
1192683Sktlim@umich.edu            TheISA::initCPU(tc, cpuId());
1202683Sktlim@umich.edu        }
1212683Sktlim@umich.edu    }
1222683Sktlim@umich.edu}
1232683Sktlim@umich.edu
1242683Sktlim@umich.edu/** Stats interface from SimObject (by way of BaseCPU) */
1252683Sktlim@umich.eduvoid
1263673Srdreslin@umich.eduMinorCPU::regStats()
1273486Sktlim@umich.edu{
1282683Sktlim@umich.edu    BaseCPU::regStats();
1292683Sktlim@umich.edu    stats.regStats(name(), *this);
1302683Sktlim@umich.edu    pipeline->regStats();
1315999Snate@binkert.org}
1328834Satgutier@umich.edu
1338834Satgutier@umich.eduvoid
1348834Satgutier@umich.eduMinorCPU::serializeThread(CheckpointOut &cp, ThreadID thread_id) const
1358834Satgutier@umich.edu{
1362683Sktlim@umich.edu    threads[thread_id]->serialize(cp);
1375999Snate@binkert.org}
1382683Sktlim@umich.edu
1392683Sktlim@umich.eduvoid
1402683Sktlim@umich.eduMinorCPU::unserializeThread(CheckpointIn &cp, ThreadID thread_id)
1412683Sktlim@umich.edu{
1422683Sktlim@umich.edu    threads[thread_id]->unserialize(cp);
1432683Sktlim@umich.edu}
1442683Sktlim@umich.edu
1452683Sktlim@umich.eduvoid
1462683Sktlim@umich.eduMinorCPU::serialize(CheckpointOut &cp) const
1472683Sktlim@umich.edu{
1482683Sktlim@umich.edu    pipeline->serialize(cp);
1492683Sktlim@umich.edu    BaseCPU::serialize(cp);
1503402Sktlim@umich.edu}
1513402Sktlim@umich.edu
1523402Sktlim@umich.eduvoid
1535714Shsul@eecs.umich.eduMinorCPU::unserialize(CheckpointIn &cp)
1545714Shsul@eecs.umich.edu{
1555714Shsul@eecs.umich.edu    pipeline->unserialize(cp);
1562292SN/A    BaseCPU::unserialize(cp);
1576221Snate@binkert.org}
1582292SN/A
1592690Sktlim@umich.eduAddr
1602683Sktlim@umich.eduMinorCPU::dbg_vtophys(Addr addr)
1612683Sktlim@umich.edu{
1622292SN/A    /* Note that this gives you the translation for thread 0 */
1632683Sktlim@umich.edu    panic("No implementation for vtophy\n");
1642683Sktlim@umich.edu
1652292SN/A    return 0;
1662683Sktlim@umich.edu}
1672292SN/A
1682292SN/Avoid
1692292SN/AMinorCPU::wakeup(ThreadID tid)
1702292SN/A{
1712292SN/A    DPRINTF(Drain, "[tid:%d] MinorCPU wakeup\n", tid);
1723548Sgblack@eecs.umich.edu    assert(tid < numThreads);
1738777Sgblack@eecs.umich.edu
1742683Sktlim@umich.edu    if (threads[tid]->status() == ThreadContext::Suspended) {
1758229Snate@binkert.org        threads[tid]->activate();
1768229Snate@binkert.org    }
1778706Sandreas.hansson@arm.com}
1782683Sktlim@umich.edu
1798706Sandreas.hansson@arm.comvoid
1802683Sktlim@umich.eduMinorCPU::startup()
1818706Sandreas.hansson@arm.com{
1828706Sandreas.hansson@arm.com    DPRINTF(MinorCPU, "MinorCPU startup\n");
1838852Sandreas.hansson@arm.com
1848852Sandreas.hansson@arm.com    BaseCPU::startup();
1852678Sktlim@umich.edu
1862690Sktlim@umich.edu    for (ThreadID tid = 0; tid < numThreads; tid++) {
1872292SN/A        threads[tid]->startup();
1882292SN/A        pipeline->wakeupFetch(tid);
1892292SN/A    }
1902292SN/A}
1912292SN/A
1922292SN/ADrainState
1932292SN/AMinorCPU::drain()
1942292SN/A{
1952292SN/A    // Deschedule any power gating event (if any)
1962292SN/A    deschedulePowerGatingEvent();
1972292SN/A
1982292SN/A    if (switchedOut()) {
1992292SN/A        DPRINTF(Drain, "Minor CPU switched out, draining not needed.\n");
200        return DrainState::Drained;
201    }
202
203    DPRINTF(Drain, "MinorCPU drain\n");
204
205    /* Need to suspend all threads and wait for Execute to idle.
206     * Tell Fetch1 not to fetch */
207    if (pipeline->drain()) {
208        DPRINTF(Drain, "MinorCPU drained\n");
209        return DrainState::Drained;
210    } else {
211        DPRINTF(Drain, "MinorCPU not finished draining\n");
212        return DrainState::Draining;
213    }
214}
215
216void
217MinorCPU::signalDrainDone()
218{
219    DPRINTF(Drain, "MinorCPU drain done\n");
220    Drainable::signalDrainDone();
221}
222
223void
224MinorCPU::drainResume()
225{
226    /* When taking over from another cpu make sure lastStopped
227     * is reset since it might have not been defined previously
228     * and might lead to a stats corruption */
229    pipeline->resetLastStopped();
230
231    if (switchedOut()) {
232        DPRINTF(Drain, "drainResume while switched out.  Ignoring\n");
233        return;
234    }
235
236    DPRINTF(Drain, "MinorCPU drainResume\n");
237
238    if (!system->isTimingMode()) {
239        fatal("The Minor CPU requires the memory system to be in "
240            "'timing' mode.\n");
241    }
242
243    for (ThreadID tid = 0; tid < numThreads; tid++){
244        wakeup(tid);
245    }
246
247    pipeline->drainResume();
248
249    // Reschedule any power gating event (if any)
250    schedulePowerGatingEvent();
251}
252
253void
254MinorCPU::memWriteback()
255{
256    DPRINTF(Drain, "MinorCPU memWriteback\n");
257}
258
259void
260MinorCPU::switchOut()
261{
262    DPRINTF(MinorCPU, "MinorCPU switchOut\n");
263
264    assert(!switchedOut());
265    BaseCPU::switchOut();
266
267    /* Check that the CPU is drained? */
268    activityRecorder->reset();
269}
270
271void
272MinorCPU::takeOverFrom(BaseCPU *old_cpu)
273{
274    DPRINTF(MinorCPU, "MinorCPU takeOverFrom\n");
275
276    BaseCPU::takeOverFrom(old_cpu);
277}
278
279void
280MinorCPU::activateContext(ThreadID thread_id)
281{
282    DPRINTF(MinorCPU, "ActivateContext thread: %d\n", thread_id);
283
284    /* Do some cycle accounting.  lastStopped is reset to stop the
285     *  wakeup call on the pipeline from adding the quiesce period
286     *  to BaseCPU::numCycles */
287    stats.quiesceCycles += pipeline->cyclesSinceLastStopped();
288    pipeline->resetLastStopped();
289
290    /* Wake up the thread, wakeup the pipeline tick */
291    threads[thread_id]->activate();
292    wakeupOnEvent(Minor::Pipeline::CPUStageId);
293    pipeline->wakeupFetch(thread_id);
294
295    BaseCPU::activateContext(thread_id);
296}
297
298void
299MinorCPU::suspendContext(ThreadID thread_id)
300{
301    DPRINTF(MinorCPU, "SuspendContext %d\n", thread_id);
302
303    threads[thread_id]->suspend();
304
305    BaseCPU::suspendContext(thread_id);
306}
307
308void
309MinorCPU::wakeupOnEvent(unsigned int stage_id)
310{
311    DPRINTF(Quiesce, "Event wakeup from stage %d\n", stage_id);
312
313    /* Mark that some activity has taken place and start the pipeline */
314    activityRecorder->activateStage(stage_id);
315    pipeline->start();
316}
317
318MinorCPU *
319MinorCPUParams::create()
320{
321    return new MinorCPU(this);
322}
323
324Port &
325MinorCPU::getInstPort()
326{
327    return pipeline->getInstPort();
328}
329
330Port &
331MinorCPU::getDataPort()
332{
333    return pipeline->getDataPort();
334}
335
336Counter
337MinorCPU::totalInsts() const
338{
339    Counter ret = 0;
340
341    for (auto i = threads.begin(); i != threads.end(); i ++)
342        ret += (*i)->numInst;
343
344    return ret;
345}
346
347Counter
348MinorCPU::totalOps() const
349{
350    Counter ret = 0;
351
352    for (auto i = threads.begin(); i != threads.end(); i ++)
353        ret += (*i)->numOp;
354
355    return ret;
356}
357