111308Santhony.gutierrez@amd.com/*
212697Santhony.gutierrez@amd.com * Copyright (c) 2011-2015,2018 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: Brad Beckmann,
3412697Santhony.gutierrez@amd.com *          Marc Orr,
3512697Santhony.gutierrez@amd.com *          Anthony Gutierrez
3611308Santhony.gutierrez@amd.com */
3711308Santhony.gutierrez@amd.com
3811308Santhony.gutierrez@amd.com
3911308Santhony.gutierrez@amd.com#include "gpu-compute/dispatcher.hh"
4011308Santhony.gutierrez@amd.com
4111308Santhony.gutierrez@amd.com#include "cpu/base.hh"
4211308Santhony.gutierrez@amd.com#include "debug/GPUDisp.hh"
4311308Santhony.gutierrez@amd.com#include "gpu-compute/cl_driver.hh"
4411308Santhony.gutierrez@amd.com#include "gpu-compute/cl_event.hh"
4511308Santhony.gutierrez@amd.com#include "gpu-compute/shader.hh"
4611308Santhony.gutierrez@amd.com#include "gpu-compute/wavefront.hh"
4711308Santhony.gutierrez@amd.com#include "mem/packet_access.hh"
4811308Santhony.gutierrez@amd.com
4911308Santhony.gutierrez@amd.comGpuDispatcher *GpuDispatcher::instance = nullptr;
5011308Santhony.gutierrez@amd.com
5111308Santhony.gutierrez@amd.comGpuDispatcher::GpuDispatcher(const Params *p)
5212680Sgiacomo.travaglini@arm.com    : DmaDevice(p), _masterId(p->system->getMasterId(this, "disp")),
5311308Santhony.gutierrez@amd.com      pioAddr(p->pio_addr), pioSize(4096), pioDelay(p->pio_latency),
5411308Santhony.gutierrez@amd.com      dispatchCount(0), dispatchActive(false), cpu(p->cpu),
5512126Sspwilson2@wisc.edu      shader(p->shader_pointer), driver(p->cl_driver),
5612126Sspwilson2@wisc.edu      tickEvent([this]{ exec(); }, "GPU Dispatcher tick",
5712126Sspwilson2@wisc.edu                false, Event::CPU_Tick_Pri)
5811308Santhony.gutierrez@amd.com{
5911308Santhony.gutierrez@amd.com    shader->handshake(this);
6011308Santhony.gutierrez@amd.com    driver->handshake(this);
6111308Santhony.gutierrez@amd.com
6211308Santhony.gutierrez@amd.com    ndRange.wg_disp_rem = false;
6311308Santhony.gutierrez@amd.com    ndRange.globalWgId = 0;
6411308Santhony.gutierrez@amd.com
6511308Santhony.gutierrez@amd.com    schedule(&tickEvent, 0);
6611308Santhony.gutierrez@amd.com
6711308Santhony.gutierrez@amd.com    // translation port for the dispatcher
6811308Santhony.gutierrez@amd.com    tlbPort = new TLBPort(csprintf("%s-port%d", name()), this);
6911308Santhony.gutierrez@amd.com
7011308Santhony.gutierrez@amd.com    num_kernelLaunched
7111308Santhony.gutierrez@amd.com    .name(name() + ".num_kernel_launched")
7211308Santhony.gutierrez@amd.com    .desc("number of kernel launched")
7311308Santhony.gutierrez@amd.com    ;
7411308Santhony.gutierrez@amd.com}
7511308Santhony.gutierrez@amd.com
7611308Santhony.gutierrez@amd.comGpuDispatcher *GpuDispatcherParams::create()
7711308Santhony.gutierrez@amd.com{
7811308Santhony.gutierrez@amd.com    GpuDispatcher *dispatcher = new GpuDispatcher(this);
7911308Santhony.gutierrez@amd.com    GpuDispatcher::setInstance(dispatcher);
8011308Santhony.gutierrez@amd.com
8111308Santhony.gutierrez@amd.com    return GpuDispatcher::getInstance();
8211308Santhony.gutierrez@amd.com}
8311308Santhony.gutierrez@amd.com
8411308Santhony.gutierrez@amd.comvoid
8511308Santhony.gutierrez@amd.comGpuDispatcher::serialize(CheckpointOut &cp) const
8611308Santhony.gutierrez@amd.com{
8711308Santhony.gutierrez@amd.com    Tick event_tick = 0;
8811308Santhony.gutierrez@amd.com
8911308Santhony.gutierrez@amd.com    if (ndRange.wg_disp_rem)
9011308Santhony.gutierrez@amd.com        fatal("Checkpointing not supported during active workgroup execution");
9111308Santhony.gutierrez@amd.com
9211308Santhony.gutierrez@amd.com    if (tickEvent.scheduled())
9311308Santhony.gutierrez@amd.com        event_tick = tickEvent.when();
9411308Santhony.gutierrez@amd.com
9511308Santhony.gutierrez@amd.com    SERIALIZE_SCALAR(event_tick);
9611308Santhony.gutierrez@amd.com
9711308Santhony.gutierrez@amd.com}
9811308Santhony.gutierrez@amd.com
9911308Santhony.gutierrez@amd.comvoid
10011308Santhony.gutierrez@amd.comGpuDispatcher::unserialize(CheckpointIn &cp)
10111308Santhony.gutierrez@amd.com{
10211308Santhony.gutierrez@amd.com    Tick event_tick;
10311308Santhony.gutierrez@amd.com
10411308Santhony.gutierrez@amd.com    if (tickEvent.scheduled())
10511308Santhony.gutierrez@amd.com        deschedule(&tickEvent);
10611308Santhony.gutierrez@amd.com
10711308Santhony.gutierrez@amd.com    UNSERIALIZE_SCALAR(event_tick);
10811308Santhony.gutierrez@amd.com
10911308Santhony.gutierrez@amd.com    if (event_tick)
11011308Santhony.gutierrez@amd.com        schedule(&tickEvent, event_tick);
11111308Santhony.gutierrez@amd.com}
11211308Santhony.gutierrez@amd.com
11311308Santhony.gutierrez@amd.comAddrRangeList
11411308Santhony.gutierrez@amd.comGpuDispatcher::getAddrRanges() const
11511308Santhony.gutierrez@amd.com{
11611308Santhony.gutierrez@amd.com    AddrRangeList ranges;
11711308Santhony.gutierrez@amd.com
11811308Santhony.gutierrez@amd.com    DPRINTF(GPUDisp, "dispatcher registering addr range at %#x size %#x\n",
11911308Santhony.gutierrez@amd.com            pioAddr, pioSize);
12011308Santhony.gutierrez@amd.com
12111308Santhony.gutierrez@amd.com    ranges.push_back(RangeSize(pioAddr, pioSize));
12211308Santhony.gutierrez@amd.com
12311308Santhony.gutierrez@amd.com    return ranges;
12411308Santhony.gutierrez@amd.com}
12511308Santhony.gutierrez@amd.com
12611308Santhony.gutierrez@amd.comTick
12711308Santhony.gutierrez@amd.comGpuDispatcher::read(PacketPtr pkt)
12811308Santhony.gutierrez@amd.com{
12911308Santhony.gutierrez@amd.com    assert(pkt->getAddr() >= pioAddr);
13011308Santhony.gutierrez@amd.com    assert(pkt->getAddr() < pioAddr + pioSize);
13111308Santhony.gutierrez@amd.com
13211308Santhony.gutierrez@amd.com    int offset = pkt->getAddr() - pioAddr;
13311308Santhony.gutierrez@amd.com    pkt->allocate();
13411308Santhony.gutierrez@amd.com
13511308Santhony.gutierrez@amd.com    DPRINTF(GPUDisp, " read register %#x size=%d\n", offset, pkt->getSize());
13611308Santhony.gutierrez@amd.com
13711308Santhony.gutierrez@amd.com    if (offset < 8) {
13811308Santhony.gutierrez@amd.com        assert(!offset);
13911308Santhony.gutierrez@amd.com        assert(pkt->getSize() == 8);
14011308Santhony.gutierrez@amd.com
14111308Santhony.gutierrez@amd.com        uint64_t retval = dispatchActive;
14213345Sgabeblack@google.com        pkt->setLE(retval);
14311308Santhony.gutierrez@amd.com    } else {
14411308Santhony.gutierrez@amd.com        offset -= 8;
14511308Santhony.gutierrez@amd.com        assert(offset + pkt->getSize() < sizeof(HsaQueueEntry));
14611308Santhony.gutierrez@amd.com        char *curTaskPtr = (char*)&curTask;
14711308Santhony.gutierrez@amd.com
14811308Santhony.gutierrez@amd.com        memcpy(pkt->getPtr<const void*>(), curTaskPtr + offset, pkt->getSize());
14911308Santhony.gutierrez@amd.com    }
15011308Santhony.gutierrez@amd.com
15111308Santhony.gutierrez@amd.com    pkt->makeAtomicResponse();
15211308Santhony.gutierrez@amd.com
15311308Santhony.gutierrez@amd.com    return pioDelay;
15411308Santhony.gutierrez@amd.com}
15511308Santhony.gutierrez@amd.com
15611308Santhony.gutierrez@amd.comTick
15711308Santhony.gutierrez@amd.comGpuDispatcher::write(PacketPtr pkt)
15811308Santhony.gutierrez@amd.com{
15911308Santhony.gutierrez@amd.com    assert(pkt->getAddr() >= pioAddr);
16011308Santhony.gutierrez@amd.com    assert(pkt->getAddr() < pioAddr + pioSize);
16111308Santhony.gutierrez@amd.com
16211308Santhony.gutierrez@amd.com    int offset = pkt->getAddr() - pioAddr;
16311308Santhony.gutierrez@amd.com
16411308Santhony.gutierrez@amd.com#if TRACING_ON
16511308Santhony.gutierrez@amd.com    uint64_t data_val = 0;
16611308Santhony.gutierrez@amd.com
16711308Santhony.gutierrez@amd.com    switch (pkt->getSize()) {
16811308Santhony.gutierrez@amd.com      case 1:
16913345Sgabeblack@google.com        data_val = pkt->getLE<uint8_t>();
17011308Santhony.gutierrez@amd.com        break;
17111308Santhony.gutierrez@amd.com      case 2:
17213345Sgabeblack@google.com        data_val = pkt->getLE<uint16_t>();
17311308Santhony.gutierrez@amd.com        break;
17411308Santhony.gutierrez@amd.com      case 4:
17513345Sgabeblack@google.com        data_val = pkt->getLE<uint32_t>();
17611308Santhony.gutierrez@amd.com        break;
17711308Santhony.gutierrez@amd.com      case 8:
17813345Sgabeblack@google.com        data_val = pkt->getLE<uint64_t>();
17911308Santhony.gutierrez@amd.com        break;
18011308Santhony.gutierrez@amd.com      default:
18111308Santhony.gutierrez@amd.com        DPRINTF(GPUDisp, "bad size %d\n", pkt->getSize());
18211308Santhony.gutierrez@amd.com    }
18311308Santhony.gutierrez@amd.com
18411308Santhony.gutierrez@amd.com    DPRINTF(GPUDisp, "write register %#x value %#x size=%d\n", offset, data_val,
18511308Santhony.gutierrez@amd.com            pkt->getSize());
18611308Santhony.gutierrez@amd.com#endif
18711308Santhony.gutierrez@amd.com    if (!offset) {
18811308Santhony.gutierrez@amd.com        static int nextId = 0;
18911308Santhony.gutierrez@amd.com
19011308Santhony.gutierrez@amd.com        // The depends field of the qstruct, which was previously unused, is
19111308Santhony.gutierrez@amd.com        // used to communicate with simulated application.
19211308Santhony.gutierrez@amd.com        if (curTask.depends) {
19311308Santhony.gutierrez@amd.com            HostState hs;
19411308Santhony.gutierrez@amd.com            shader->ReadMem((uint64_t)(curTask.depends), &hs,
19511308Santhony.gutierrez@amd.com                            sizeof(HostState), 0);
19611308Santhony.gutierrez@amd.com
19711308Santhony.gutierrez@amd.com            // update event start time (in nano-seconds)
19811308Santhony.gutierrez@amd.com            uint64_t start = curTick() / 1000;
19911308Santhony.gutierrez@amd.com
20011308Santhony.gutierrez@amd.com            shader->WriteMem((uint64_t)(&((_cl_event*)hs.event)->start),
20111308Santhony.gutierrez@amd.com                             &start, sizeof(uint64_t), 0);
20211308Santhony.gutierrez@amd.com        }
20311308Santhony.gutierrez@amd.com
20411308Santhony.gutierrez@amd.com        // launch kernel
20511308Santhony.gutierrez@amd.com        ++num_kernelLaunched;
20611308Santhony.gutierrez@amd.com
20711308Santhony.gutierrez@amd.com        NDRange *ndr = &(ndRangeMap[nextId]);
20811308Santhony.gutierrez@amd.com        // copy dispatch info
20911308Santhony.gutierrez@amd.com        ndr->q = curTask;
21011308Santhony.gutierrez@amd.com
21111308Santhony.gutierrez@amd.com        // update the numDispTask polled by the runtime
21211308Santhony.gutierrez@amd.com        accessUserVar(cpu, (uint64_t)(curTask.numDispLeft), 0, 1);
21311308Santhony.gutierrez@amd.com
21411308Santhony.gutierrez@amd.com        ndr->numWgTotal = 1;
21511308Santhony.gutierrez@amd.com
21611308Santhony.gutierrez@amd.com        for (int i = 0; i < 3; ++i) {
21711308Santhony.gutierrez@amd.com            ndr->wgId[i] = 0;
21811308Santhony.gutierrez@amd.com            ndr->numWg[i] = divCeil(curTask.gdSize[i], curTask.wgSize[i]);
21911308Santhony.gutierrez@amd.com            ndr->numWgTotal *= ndr->numWg[i];
22011308Santhony.gutierrez@amd.com        }
22111308Santhony.gutierrez@amd.com
22211308Santhony.gutierrez@amd.com        ndr->numWgCompleted = 0;
22311308Santhony.gutierrez@amd.com        ndr->globalWgId = 0;
22411308Santhony.gutierrez@amd.com        ndr->wg_disp_rem = true;
22511308Santhony.gutierrez@amd.com        ndr->execDone = false;
22611308Santhony.gutierrez@amd.com        ndr->addrToNotify = (volatile bool*)curTask.addrToNotify;
22711308Santhony.gutierrez@amd.com        ndr->numDispLeft = (volatile uint32_t*)curTask.numDispLeft;
22811308Santhony.gutierrez@amd.com        ndr->dispatchId = nextId;
22911435Smitch.hayenga@arm.com        ndr->curCid = pkt->req->contextId();
23011308Santhony.gutierrez@amd.com        DPRINTF(GPUDisp, "launching kernel %d\n",nextId);
23111308Santhony.gutierrez@amd.com        execIds.push(nextId);
23211308Santhony.gutierrez@amd.com        ++nextId;
23311308Santhony.gutierrez@amd.com
23411308Santhony.gutierrez@amd.com        dispatchActive = true;
23511308Santhony.gutierrez@amd.com
23611308Santhony.gutierrez@amd.com        if (!tickEvent.scheduled()) {
23711308Santhony.gutierrez@amd.com            schedule(&tickEvent, curTick() + shader->ticks(1));
23811308Santhony.gutierrez@amd.com        }
23911308Santhony.gutierrez@amd.com    } else {
24011308Santhony.gutierrez@amd.com        // populate current task struct
24111308Santhony.gutierrez@amd.com        // first 64 bits are launch reg
24211308Santhony.gutierrez@amd.com        offset -= 8;
24311308Santhony.gutierrez@amd.com        assert(offset < sizeof(HsaQueueEntry));
24411308Santhony.gutierrez@amd.com        char *curTaskPtr = (char*)&curTask;
24511308Santhony.gutierrez@amd.com        memcpy(curTaskPtr + offset, pkt->getPtr<const void*>(), pkt->getSize());
24611308Santhony.gutierrez@amd.com    }
24711308Santhony.gutierrez@amd.com
24811308Santhony.gutierrez@amd.com    pkt->makeAtomicResponse();
24911308Santhony.gutierrez@amd.com
25011308Santhony.gutierrez@amd.com    return pioDelay;
25111308Santhony.gutierrez@amd.com}
25211308Santhony.gutierrez@amd.com
25311308Santhony.gutierrez@amd.com
25413784Sgabeblack@google.comPort &
25513784Sgabeblack@google.comGpuDispatcher::getPort(const std::string &if_name, PortID idx)
25611308Santhony.gutierrez@amd.com{
25711308Santhony.gutierrez@amd.com    if (if_name == "translation_port") {
25811308Santhony.gutierrez@amd.com        return *tlbPort;
25911308Santhony.gutierrez@amd.com    }
26011308Santhony.gutierrez@amd.com
26113784Sgabeblack@google.com    return DmaDevice::getPort(if_name, idx);
26211308Santhony.gutierrez@amd.com}
26311308Santhony.gutierrez@amd.com
26411308Santhony.gutierrez@amd.comvoid
26511308Santhony.gutierrez@amd.comGpuDispatcher::exec()
26611308Santhony.gutierrez@amd.com{
26711308Santhony.gutierrez@amd.com    int fail_count = 0;
26811308Santhony.gutierrez@amd.com
26911308Santhony.gutierrez@amd.com    // There are potentially multiple outstanding kernel launches.
27011308Santhony.gutierrez@amd.com    // It is possible that the workgroups in a different kernel
27111308Santhony.gutierrez@amd.com    // can fit on the GPU even if another kernel's workgroups cannot
27211308Santhony.gutierrez@amd.com    DPRINTF(GPUDisp, "Launching %d Kernels\n", execIds.size());
27311308Santhony.gutierrez@amd.com
27411308Santhony.gutierrez@amd.com    while (execIds.size() > fail_count) {
27511308Santhony.gutierrez@amd.com        int execId = execIds.front();
27611308Santhony.gutierrez@amd.com
27711308Santhony.gutierrez@amd.com        while (ndRangeMap[execId].wg_disp_rem) {
27811308Santhony.gutierrez@amd.com            //update the thread context
27911435Smitch.hayenga@arm.com            shader->updateContext(ndRangeMap[execId].curCid);
28011308Santhony.gutierrez@amd.com
28111308Santhony.gutierrez@amd.com            // attempt to dispatch_workgroup
28211308Santhony.gutierrez@amd.com            if (!shader->dispatch_workgroups(&ndRangeMap[execId])) {
28311308Santhony.gutierrez@amd.com                // if we failed try the next kernel,
28411308Santhony.gutierrez@amd.com                // it may have smaller workgroups.
28511308Santhony.gutierrez@amd.com                // put it on the queue to rety latter
28611308Santhony.gutierrez@amd.com                DPRINTF(GPUDisp, "kernel %d failed to launch\n", execId);
28711308Santhony.gutierrez@amd.com                execIds.push(execId);
28811308Santhony.gutierrez@amd.com                ++fail_count;
28911308Santhony.gutierrez@amd.com                break;
29011308Santhony.gutierrez@amd.com            }
29111308Santhony.gutierrez@amd.com        }
29211308Santhony.gutierrez@amd.com        // let's try the next kernel_id
29311308Santhony.gutierrez@amd.com        execIds.pop();
29411308Santhony.gutierrez@amd.com    }
29511308Santhony.gutierrez@amd.com
29611308Santhony.gutierrez@amd.com    DPRINTF(GPUDisp, "Returning %d Kernels\n", doneIds.size());
29711308Santhony.gutierrez@amd.com
29811308Santhony.gutierrez@amd.com    if (doneIds.size() && cpu) {
29911308Santhony.gutierrez@amd.com        shader->hostWakeUp(cpu);
30011308Santhony.gutierrez@amd.com    }
30111308Santhony.gutierrez@amd.com
30211308Santhony.gutierrez@amd.com    while (doneIds.size()) {
30311308Santhony.gutierrez@amd.com        // wakeup the CPU if any Kernels completed this cycle
30411308Santhony.gutierrez@amd.com        DPRINTF(GPUDisp, "WorkGroup %d completed\n", doneIds.front());
30511308Santhony.gutierrez@amd.com        doneIds.pop();
30611308Santhony.gutierrez@amd.com    }
30711308Santhony.gutierrez@amd.com}
30811308Santhony.gutierrez@amd.com
30911308Santhony.gutierrez@amd.comvoid
31011308Santhony.gutierrez@amd.comGpuDispatcher::notifyWgCompl(Wavefront *w)
31111308Santhony.gutierrez@amd.com{
31211639Salexandru.dutu@amd.com    int kern_id = w->kernId;
31311308Santhony.gutierrez@amd.com    DPRINTF(GPUDisp, "notify WgCompl %d\n",kern_id);
31411308Santhony.gutierrez@amd.com    assert(ndRangeMap[kern_id].dispatchId == kern_id);
31511308Santhony.gutierrez@amd.com    ndRangeMap[kern_id].numWgCompleted++;
31611308Santhony.gutierrez@amd.com
31711308Santhony.gutierrez@amd.com    if (ndRangeMap[kern_id].numWgCompleted == ndRangeMap[kern_id].numWgTotal) {
31811308Santhony.gutierrez@amd.com        ndRangeMap[kern_id].execDone = true;
31911308Santhony.gutierrez@amd.com        doneIds.push(kern_id);
32011308Santhony.gutierrez@amd.com
32111308Santhony.gutierrez@amd.com        if (ndRangeMap[kern_id].addrToNotify) {
32211308Santhony.gutierrez@amd.com            accessUserVar(cpu, (uint64_t)(ndRangeMap[kern_id].addrToNotify), 1,
32311308Santhony.gutierrez@amd.com                          0);
32411308Santhony.gutierrez@amd.com        }
32511308Santhony.gutierrez@amd.com
32611308Santhony.gutierrez@amd.com        accessUserVar(cpu, (uint64_t)(ndRangeMap[kern_id].numDispLeft), 0, -1);
32711308Santhony.gutierrez@amd.com
32811308Santhony.gutierrez@amd.com        // update event end time (in nano-seconds)
32911308Santhony.gutierrez@amd.com        if (ndRangeMap[kern_id].q.depends) {
33011308Santhony.gutierrez@amd.com            HostState *host_state = (HostState*)ndRangeMap[kern_id].q.depends;
33111308Santhony.gutierrez@amd.com            uint64_t event;
33211308Santhony.gutierrez@amd.com            shader->ReadMem((uint64_t)(&host_state->event), &event,
33311308Santhony.gutierrez@amd.com                            sizeof(uint64_t), 0);
33411308Santhony.gutierrez@amd.com
33511308Santhony.gutierrez@amd.com            uint64_t end = curTick() / 1000;
33611308Santhony.gutierrez@amd.com
33711308Santhony.gutierrez@amd.com            shader->WriteMem((uint64_t)(&((_cl_event*)event)->end), &end,
33811308Santhony.gutierrez@amd.com                             sizeof(uint64_t), 0);
33911308Santhony.gutierrez@amd.com        }
34011308Santhony.gutierrez@amd.com    }
34111308Santhony.gutierrez@amd.com
34211308Santhony.gutierrez@amd.com    if (!tickEvent.scheduled()) {
34311308Santhony.gutierrez@amd.com        schedule(&tickEvent, curTick() + shader->ticks(1));
34411308Santhony.gutierrez@amd.com    }
34511308Santhony.gutierrez@amd.com}
34611308Santhony.gutierrez@amd.com
34711308Santhony.gutierrez@amd.comvoid
34811308Santhony.gutierrez@amd.comGpuDispatcher::scheduleDispatch()
34911308Santhony.gutierrez@amd.com{
35011308Santhony.gutierrez@amd.com    if (!tickEvent.scheduled())
35111308Santhony.gutierrez@amd.com        schedule(&tickEvent, curTick() + shader->ticks(1));
35211308Santhony.gutierrez@amd.com}
35311308Santhony.gutierrez@amd.com
35411308Santhony.gutierrez@amd.comvoid
35511308Santhony.gutierrez@amd.comGpuDispatcher::accessUserVar(BaseCPU *cpu, uint64_t addr, int val, int off)
35611308Santhony.gutierrez@amd.com{
35711308Santhony.gutierrez@amd.com    if (cpu) {
35811308Santhony.gutierrez@amd.com        if (off) {
35911308Santhony.gutierrez@amd.com            shader->AccessMem(addr, &val, sizeof(int), 0, MemCmd::ReadReq,
36011308Santhony.gutierrez@amd.com                              true);
36111308Santhony.gutierrez@amd.com            val += off;
36211308Santhony.gutierrez@amd.com        }
36311308Santhony.gutierrez@amd.com
36411308Santhony.gutierrez@amd.com        shader->AccessMem(addr, &val, sizeof(int), 0, MemCmd::WriteReq, true);
36511308Santhony.gutierrez@amd.com    } else {
36611308Santhony.gutierrez@amd.com        panic("Cannot find host");
36711308Santhony.gutierrez@amd.com    }
36811308Santhony.gutierrez@amd.com}
36911308Santhony.gutierrez@amd.com
37011308Santhony.gutierrez@amd.com// helper functions for driver to retrieve GPU attributes
37111308Santhony.gutierrez@amd.comint
37211308Santhony.gutierrez@amd.comGpuDispatcher::getNumCUs()
37311308Santhony.gutierrez@amd.com{
37411308Santhony.gutierrez@amd.com    return shader->cuList.size();
37511308Santhony.gutierrez@amd.com}
37611308Santhony.gutierrez@amd.com
37711534Sjohn.kalamatianos@amd.comint
37811534Sjohn.kalamatianos@amd.comGpuDispatcher::wfSize() const
37911534Sjohn.kalamatianos@amd.com{
38011534Sjohn.kalamatianos@amd.com    return shader->cuList[0]->wfSize();
38111534Sjohn.kalamatianos@amd.com}
38211534Sjohn.kalamatianos@amd.com
38311308Santhony.gutierrez@amd.comvoid
38411308Santhony.gutierrez@amd.comGpuDispatcher::setFuncargsSize(int funcargs_size)
38511308Santhony.gutierrez@amd.com{
38611308Santhony.gutierrez@amd.com    shader->funcargs_size = funcargs_size;
38711308Santhony.gutierrez@amd.com}
38811640Salexandru.dutu@amd.com
38911640Salexandru.dutu@amd.comuint32_t
39011646Santhony.gutierrez@amd.comGpuDispatcher::getStaticContextSize() const
39111640Salexandru.dutu@amd.com{
39211640Salexandru.dutu@amd.com    return shader->cuList[0]->wfList[0][0]->getStaticContextSize();
39311640Salexandru.dutu@amd.com}
394