111308Santhony.gutierrez@amd.com/*
211308Santhony.gutierrez@amd.com * Copyright (c) 2014-2015 Advanced Micro Devices, Inc.
311308Santhony.gutierrez@amd.com * All rights reserved.
411308Santhony.gutierrez@amd.com *
511308Santhony.gutierrez@amd.com * For use for simulation and test purposes only
611308Santhony.gutierrez@amd.com *
711308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without
811308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are met:
911308Santhony.gutierrez@amd.com *
1011308Santhony.gutierrez@amd.com * 1. Redistributions of source code must retain the above copyright notice,
1111308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer.
1211308Santhony.gutierrez@amd.com *
1311308Santhony.gutierrez@amd.com * 2. Redistributions in binary form must reproduce the above copyright notice,
1411308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer in the documentation
1511308Santhony.gutierrez@amd.com * and/or other materials provided with the distribution.
1611308Santhony.gutierrez@amd.com *
1712697Santhony.gutierrez@amd.com * 3. Neither the name of the copyright holder nor the names of its
1812697Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from this
1912697Santhony.gutierrez@amd.com * software without specific prior written permission.
2011308Santhony.gutierrez@amd.com *
2111308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2211308Santhony.gutierrez@amd.com * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2311308Santhony.gutierrez@amd.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2411308Santhony.gutierrez@amd.com * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2511308Santhony.gutierrez@amd.com * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2611308Santhony.gutierrez@amd.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2711308Santhony.gutierrez@amd.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2811308Santhony.gutierrez@amd.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2911308Santhony.gutierrez@amd.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3011308Santhony.gutierrez@amd.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3111308Santhony.gutierrez@amd.com * POSSIBILITY OF SUCH DAMAGE.
3211308Santhony.gutierrez@amd.com *
3312697Santhony.gutierrez@amd.com * Authors: John Kalamatianos,
3412697Santhony.gutierrez@amd.com *          Sooraj Puthoor
3511308Santhony.gutierrez@amd.com */
3611308Santhony.gutierrez@amd.com
3711308Santhony.gutierrez@amd.com#include "gpu-compute/exec_stage.hh"
3811308Santhony.gutierrez@amd.com
3911308Santhony.gutierrez@amd.com#include "gpu-compute/compute_unit.hh"
4011308Santhony.gutierrez@amd.com#include "gpu-compute/wavefront.hh"
4111308Santhony.gutierrez@amd.com
4211308Santhony.gutierrez@amd.comExecStage::ExecStage(const ComputeUnitParams *p) : numSIMDs(p->num_SIMDs),
4311308Santhony.gutierrez@amd.com    numMemUnits(p->num_global_mem_pipes + p->num_shared_mem_pipes),
4411308Santhony.gutierrez@amd.com    vectorAluInstAvail(nullptr), glbMemInstAvail(nullptr),
4511308Santhony.gutierrez@amd.com    shrMemInstAvail(nullptr), lastTimeInstExecuted(false),
4611308Santhony.gutierrez@amd.com    thisTimeInstExecuted(false), instrExecuted (false),
4711308Santhony.gutierrez@amd.com    executionResourcesUsed(0)
4811308Santhony.gutierrez@amd.com{
4911308Santhony.gutierrez@amd.com    numTransActiveIdle = 0;
5011308Santhony.gutierrez@amd.com    idle_dur = 0;
5111308Santhony.gutierrez@amd.com}
5211308Santhony.gutierrez@amd.com
5311308Santhony.gutierrez@amd.comvoid
5411308Santhony.gutierrez@amd.comExecStage::init(ComputeUnit *cu)
5511308Santhony.gutierrez@amd.com{
5611308Santhony.gutierrez@amd.com    computeUnit = cu;
5711308Santhony.gutierrez@amd.com    _name = computeUnit->name() + ".ExecStage";
5811308Santhony.gutierrez@amd.com    dispatchList = &computeUnit->dispatchList;
5911308Santhony.gutierrez@amd.com    vectorAluInstAvail = &(computeUnit->vectorAluInstAvail);
6011308Santhony.gutierrez@amd.com    glbMemInstAvail= &(computeUnit->glbMemInstAvail);
6111308Santhony.gutierrez@amd.com    shrMemInstAvail= &(computeUnit->shrMemInstAvail);
6211308Santhony.gutierrez@amd.com    idle_dur = 0;
6311308Santhony.gutierrez@amd.com}
6411308Santhony.gutierrez@amd.com
6511308Santhony.gutierrez@amd.comvoid
6611308Santhony.gutierrez@amd.comExecStage::collectStatistics(enum STAT_STATUS stage, int unitId) {
6711308Santhony.gutierrez@amd.com    if (stage == IdleExec) {
6811308Santhony.gutierrez@amd.com        // count cycles of no vector ALU instruction executed
6911308Santhony.gutierrez@amd.com        // even if one was the oldest in a WV of that vector SIMD unit
7011308Santhony.gutierrez@amd.com        if (computeUnit->isVecAlu(unitId) && vectorAluInstAvail->at(unitId)) {
7111308Santhony.gutierrez@amd.com            numCyclesWithNoInstrTypeIssued[unitId]++;
7211308Santhony.gutierrez@amd.com        }
7311308Santhony.gutierrez@amd.com
7411308Santhony.gutierrez@amd.com        // count cycles of no global memory (vector) instruction executed
7511308Santhony.gutierrez@amd.com        // even if one was the oldest in a WV of that vector SIMD unit
7611308Santhony.gutierrez@amd.com        if (computeUnit->isGlbMem(unitId) && *glbMemInstAvail > 0) {
7711308Santhony.gutierrez@amd.com            numCyclesWithNoInstrTypeIssued[unitId]++;
7811308Santhony.gutierrez@amd.com            (*glbMemInstAvail)--;
7911308Santhony.gutierrez@amd.com        }
8011308Santhony.gutierrez@amd.com
8111308Santhony.gutierrez@amd.com        // count cycles of no shared memory (vector) instruction executed
8211308Santhony.gutierrez@amd.com        // even if one was the oldest in a WV of that vector SIMD unit
8311308Santhony.gutierrez@amd.com        if (computeUnit->isShrMem(unitId) && *shrMemInstAvail > 0) {
8411308Santhony.gutierrez@amd.com            numCyclesWithNoInstrTypeIssued[unitId]++;
8511308Santhony.gutierrez@amd.com            (*shrMemInstAvail)--;
8611308Santhony.gutierrez@amd.com        }
8711308Santhony.gutierrez@amd.com    } else if (stage == BusyExec) {
8811308Santhony.gutierrez@amd.com        // count the number of cycles an instruction to a specific unit
8911308Santhony.gutierrez@amd.com        // was issued
9011308Santhony.gutierrez@amd.com        numCyclesWithInstrTypeIssued[unitId]++;
9111308Santhony.gutierrez@amd.com        thisTimeInstExecuted = true;
9211308Santhony.gutierrez@amd.com        instrExecuted = true;
9311308Santhony.gutierrez@amd.com        ++executionResourcesUsed;
9411308Santhony.gutierrez@amd.com    } else if (stage == PostExec) {
9511308Santhony.gutierrez@amd.com        // count the number of transitions from active to idle
9611308Santhony.gutierrez@amd.com        if (lastTimeInstExecuted && !thisTimeInstExecuted) {
9711308Santhony.gutierrez@amd.com            ++numTransActiveIdle;
9811308Santhony.gutierrez@amd.com        }
9911308Santhony.gutierrez@amd.com
10011308Santhony.gutierrez@amd.com        if (!lastTimeInstExecuted && thisTimeInstExecuted) {
10111308Santhony.gutierrez@amd.com            idleDur.sample(idle_dur);
10211308Santhony.gutierrez@amd.com            idle_dur = 0;
10311308Santhony.gutierrez@amd.com        } else if (!thisTimeInstExecuted) {
10411308Santhony.gutierrez@amd.com            idle_dur++;
10511308Santhony.gutierrez@amd.com        }
10611308Santhony.gutierrez@amd.com
10711308Santhony.gutierrez@amd.com        lastTimeInstExecuted = thisTimeInstExecuted;
10811308Santhony.gutierrez@amd.com        // track the number of cycles we either issued one vector instruction
10911308Santhony.gutierrez@amd.com        // or issued no instructions at all
11011308Santhony.gutierrez@amd.com        if (instrExecuted) {
11111308Santhony.gutierrez@amd.com            numCyclesWithInstrIssued++;
11211308Santhony.gutierrez@amd.com        } else {
11311308Santhony.gutierrez@amd.com            numCyclesWithNoIssue++;
11411308Santhony.gutierrez@amd.com        }
11511308Santhony.gutierrez@amd.com
11611308Santhony.gutierrez@amd.com        spc.sample(executionResourcesUsed);
11711308Santhony.gutierrez@amd.com    }
11811308Santhony.gutierrez@amd.com}
11911308Santhony.gutierrez@amd.com
12011308Santhony.gutierrez@amd.comvoid
12111308Santhony.gutierrez@amd.comExecStage::initStatistics()
12211308Santhony.gutierrez@amd.com{
12311308Santhony.gutierrez@amd.com    instrExecuted = false;
12411308Santhony.gutierrez@amd.com    executionResourcesUsed = 0;
12511308Santhony.gutierrez@amd.com    thisTimeInstExecuted = false;
12611308Santhony.gutierrez@amd.com}
12711308Santhony.gutierrez@amd.com
12811308Santhony.gutierrez@amd.comvoid
12911308Santhony.gutierrez@amd.comExecStage::exec()
13011308Santhony.gutierrez@amd.com{
13111308Santhony.gutierrez@amd.com    initStatistics();
13211308Santhony.gutierrez@amd.com
13311308Santhony.gutierrez@amd.com    for (int unitId = 0; unitId < (numSIMDs + numMemUnits); ++unitId) {
13411308Santhony.gutierrez@amd.com         // if dispatch list for this execution resource is empty,
13511308Santhony.gutierrez@amd.com         // skip this execution resource this cycle
13611308Santhony.gutierrez@amd.com         if (dispatchList->at(unitId).second == EMPTY) {
13711308Santhony.gutierrez@amd.com             collectStatistics(IdleExec, unitId);
13811308Santhony.gutierrez@amd.com             continue;
13911308Santhony.gutierrez@amd.com         }
14011308Santhony.gutierrez@amd.com
14111308Santhony.gutierrez@amd.com         collectStatistics(BusyExec, unitId);
14211308Santhony.gutierrez@amd.com         // execute an instruction for the WF
14311308Santhony.gutierrez@amd.com         dispatchList->at(unitId).first->exec();
14411308Santhony.gutierrez@amd.com         // clear the dispatch list entry
14511308Santhony.gutierrez@amd.com         dispatchList->at(unitId).second = EMPTY;
14611308Santhony.gutierrez@amd.com         dispatchList->at(unitId).first = (Wavefront*)nullptr;
14711308Santhony.gutierrez@amd.com    }
14811308Santhony.gutierrez@amd.com
14911308Santhony.gutierrez@amd.com    collectStatistics(PostExec, 0);
15011308Santhony.gutierrez@amd.com}
15111308Santhony.gutierrez@amd.com
15211308Santhony.gutierrez@amd.comvoid
15311308Santhony.gutierrez@amd.comExecStage::regStats()
15411308Santhony.gutierrez@amd.com{
15511308Santhony.gutierrez@amd.com    numTransActiveIdle
15611308Santhony.gutierrez@amd.com       .name(name() + ".num_transitions_active_to_idle")
15711308Santhony.gutierrez@amd.com       .desc("number of CU transitions from active to idle")
15811308Santhony.gutierrez@amd.com        ;
15911308Santhony.gutierrez@amd.com
16011308Santhony.gutierrez@amd.com    numCyclesWithNoIssue
16111308Santhony.gutierrez@amd.com        .name(name() + ".num_cycles_with_no_issue")
16211308Santhony.gutierrez@amd.com        .desc("number of cycles the CU issues nothing")
16311308Santhony.gutierrez@amd.com        ;
16411308Santhony.gutierrez@amd.com
16511308Santhony.gutierrez@amd.com    numCyclesWithInstrIssued
16611308Santhony.gutierrez@amd.com        .name(name() + ".num_cycles_with_instr_issued")
16711308Santhony.gutierrez@amd.com        .desc("number of cycles the CU issued at least one instruction")
16811308Santhony.gutierrez@amd.com        ;
16911308Santhony.gutierrez@amd.com
17011308Santhony.gutierrez@amd.com    spc
17111308Santhony.gutierrez@amd.com        .init(0, numSIMDs + numMemUnits, 1)
17211308Santhony.gutierrez@amd.com        .name(name() + ".spc")
17311308Santhony.gutierrez@amd.com        .desc("Execution units active per cycle (Exec unit=SIMD,MemPipe)")
17411308Santhony.gutierrez@amd.com        ;
17511308Santhony.gutierrez@amd.com
17611308Santhony.gutierrez@amd.com    idleDur
17711308Santhony.gutierrez@amd.com        .init(0,75,5)
17811308Santhony.gutierrez@amd.com        .name(name() + ".idle_duration_in_cycles")
17911308Santhony.gutierrez@amd.com        .desc("duration of idle periods in cycles")
18011308Santhony.gutierrez@amd.com        ;
18111308Santhony.gutierrez@amd.com
18211308Santhony.gutierrez@amd.com    numCyclesWithInstrTypeIssued
18311308Santhony.gutierrez@amd.com        .init(numSIMDs + numMemUnits)
18411308Santhony.gutierrez@amd.com        .name(name() + ".num_cycles_with_instrtype_issue")
18511308Santhony.gutierrez@amd.com        .desc("Number of cycles at least one instruction of specific type "
18611308Santhony.gutierrez@amd.com              "issued")
18711308Santhony.gutierrez@amd.com        ;
18811308Santhony.gutierrez@amd.com
18911308Santhony.gutierrez@amd.com    numCyclesWithNoInstrTypeIssued
19011308Santhony.gutierrez@amd.com        .init(numSIMDs + numMemUnits)
19111308Santhony.gutierrez@amd.com       .name(name() + ".num_cycles_with_instr_type_no_issue")
19211308Santhony.gutierrez@amd.com       .desc("Number of cycles no instruction of specific type issued")
19311308Santhony.gutierrez@amd.com       ;
19411308Santhony.gutierrez@amd.com
19511308Santhony.gutierrez@amd.com    for (int i = 0; i < numSIMDs; ++i) {
19611308Santhony.gutierrez@amd.com        numCyclesWithInstrTypeIssued.subname(i, csprintf("ALU%d",i));
19711308Santhony.gutierrez@amd.com        numCyclesWithNoInstrTypeIssued.subname(i, csprintf("ALU%d",i));
19811308Santhony.gutierrez@amd.com    }
19911308Santhony.gutierrez@amd.com
20011308Santhony.gutierrez@amd.com    numCyclesWithInstrTypeIssued.subname(numSIMDs, csprintf("GM"));
20111308Santhony.gutierrez@amd.com    numCyclesWithNoInstrTypeIssued.subname(numSIMDs, csprintf("GM"));
20211308Santhony.gutierrez@amd.com    numCyclesWithInstrTypeIssued.subname(numSIMDs + 1, csprintf("LM"));
20311308Santhony.gutierrez@amd.com    numCyclesWithNoInstrTypeIssued.subname(numSIMDs + 1, csprintf("LM"));
20411308Santhony.gutierrez@amd.com}
205