gpu_nomali.cc revision 13230:2988dc5d1d6f
12567SN/A/*
212531Sandreas.sandberg@arm.com * Copyright (c) 2014-2016 ARM Limited
37650SAli.Saidi@ARM.com * All rights reserved
47650SAli.Saidi@ARM.com *
57650SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall
67650SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual
77650SAli.Saidi@ARM.com * property including but not limited to intellectual property relating
87650SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software
97650SAli.Saidi@ARM.com * licensed hereunder.  You may use the software subject to the license
107650SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated
117650SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software,
127650SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form.
137650SAli.Saidi@ARM.com *
142567SN/A * Redistribution and use in source and binary forms, with or without
152567SN/A * modification, are permitted provided that the following conditions are
162567SN/A * met: redistributions of source code must retain the above copyright
172567SN/A * notice, this list of conditions and the following disclaimer;
182567SN/A * redistributions in binary form must reproduce the above copyright
192567SN/A * notice, this list of conditions and the following disclaimer in the
202567SN/A * documentation and/or other materials provided with the distribution;
212567SN/A * neither the name of the copyright holders nor the names of its
222567SN/A * contributors may be used to endorse or promote products derived from
232567SN/A * this software without specific prior written permission.
242567SN/A *
252567SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
262567SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
272567SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282567SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
292567SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
302567SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
312567SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
322567SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
332567SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
342567SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
352567SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
362567SN/A *
372567SN/A * Authors: Andreas Sandberg
382567SN/A */
392665SN/A
402665SN/A#include "dev/arm/gpu_nomali.hh"
412567SN/A
422567SN/A#include "debug/NoMali.hh"
436757SAli.Saidi@ARM.com#include "dev/arm/base_gic.hh"
446757SAli.Saidi@ARM.com#include "dev/arm/realview.hh"
452567SN/A#include "enums/MemoryMode.hh"
4611234Sandreas.sandberg@arm.com#include "mem/packet_access.hh"
472567SN/A#include "nomali/lib/mali_midg_regmap.h"
482567SN/A#include "params/CustomNoMaliGpu.hh"
492567SN/A#include "params/NoMaliGpu.hh"
508229Snate@binkert.org
516757SAli.Saidi@ARM.comstatic const std::map<Enums::NoMaliGpuType, nomali_gpu_type_t> gpuTypeMap{
5210810Sbr@bsdpad.com    { Enums::T60x, NOMALI_GPU_T60X },
532567SN/A    { Enums::T62x, NOMALI_GPU_T62X },
542567SN/A    { Enums::T760, NOMALI_GPU_T760 },
552567SN/A};
5610844Sandreas.sandberg@arm.com
5710037SARM gem5 DevelopersNoMaliGpu::NoMaliGpu(const NoMaliGpuParams *p)
5810037SARM gem5 Developers    : PioDevice(p),
596757SAli.Saidi@ARM.com      pioAddr(p->pio_addr),
602567SN/A      platform(p->platform),
618285SPrakash.Ramrakhyani@arm.com      interruptMap{
627650SAli.Saidi@ARM.com          { NOMALI_INT_GPU, p->int_gpu },
637650SAli.Saidi@ARM.com          { NOMALI_INT_JOB, p->int_job },
647650SAli.Saidi@ARM.com          { NOMALI_INT_MMU, p->int_mmu },
657650SAli.Saidi@ARM.com      }
667650SAli.Saidi@ARM.com{
677650SAli.Saidi@ARM.com    if (nomali_api_version() != NOMALI_API_VERSION)
6811234Sandreas.sandberg@arm.com        panic("NoMali library API mismatch!\n");
6911234Sandreas.sandberg@arm.com
7011234Sandreas.sandberg@arm.com    /* Setup the GPU configuration based on our param struct */
718286SAli.Saidi@ARM.com    nomali_config_t cfg;
728286SAli.Saidi@ARM.com    memset(&cfg, 0, sizeof(cfg));
738286SAli.Saidi@ARM.com
748286SAli.Saidi@ARM.com    const auto it_gpu(gpuTypeMap.find(p->gpu_type));
758286SAli.Saidi@ARM.com    if (it_gpu == gpuTypeMap.end()) {
7610037SARM gem5 Developers        fatal("Unrecognized GPU type: %s (%i)\n",
7710037SARM gem5 Developers              Enums::NoMaliGpuTypeStrings[p->gpu_type], p->gpu_type);
7810037SARM gem5 Developers    }
7910037SARM gem5 Developers    cfg.type = it_gpu->second;
8010037SARM gem5 Developers
8110037SARM gem5 Developers    cfg.ver_maj = p->ver_maj;
8210037SARM gem5 Developers    cfg.ver_min = p->ver_min;
8310037SARM gem5 Developers    cfg.ver_status = p->ver_status;
8410037SARM gem5 Developers
8510037SARM gem5 Developers    panicOnErr(
8610037SARM gem5 Developers        nomali_create(&nomali, &cfg),
8710037SARM gem5 Developers        "Failed to instantiate NoMali");
8810037SARM gem5 Developers
8910037SARM gem5 Developers
9010037SARM gem5 Developers    /* Setup an interrupt callback */
9110037SARM gem5 Developers    nomali_callback_t cbk_int;
9213173Sgiacomo.travaglini@arm.com    cbk_int.type = NOMALI_CALLBACK_INT;
9313173Sgiacomo.travaglini@arm.com    cbk_int.usr = (void *)this;
9413173Sgiacomo.travaglini@arm.com    cbk_int.func.interrupt = NoMaliGpu::_interrupt;
9513173Sgiacomo.travaglini@arm.com    setCallback(cbk_int);
9613173Sgiacomo.travaglini@arm.com
9710037SARM gem5 Developers    /* Setup a reset callback */
9810037SARM gem5 Developers    nomali_callback_t cbk_rst;
9910037SARM gem5 Developers    cbk_rst.type = NOMALI_CALLBACK_RESET;
10010037SARM gem5 Developers    cbk_rst.usr = (void *)this;
10110037SARM gem5 Developers    cbk_rst.func.reset = NoMaliGpu::_reset;
10213396Sgiacomo.travaglini@arm.com    setCallback(cbk_rst);
10313396Sgiacomo.travaglini@arm.com
10413396Sgiacomo.travaglini@arm.com    panicOnErr(
10513396Sgiacomo.travaglini@arm.com        nomali_get_info(nomali, &nomaliInfo),
10613396Sgiacomo.travaglini@arm.com        "Failed to get NoMali information struct");
10710037SARM gem5 Developers}
10810037SARM gem5 Developers
10910037SARM gem5 DevelopersNoMaliGpu::~NoMaliGpu()
11010037SARM gem5 Developers{
11110037SARM gem5 Developers    nomali_destroy(nomali);
11210037SARM gem5 Developers}
11310037SARM gem5 Developers
11410037SARM gem5 Developers
11510037SARM gem5 Developersvoid
11610037SARM gem5 DevelopersNoMaliGpu::init()
11710037SARM gem5 Developers{
11810037SARM gem5 Developers    PioDevice::init();
11910037SARM gem5 Developers
12010037SARM gem5 Developers    /* Reset the GPU here since the reset callback won't have been
12110037SARM gem5 Developers     * installed when the GPU was reset at instantiation time.
12210037SARM gem5 Developers     */
12312005Sandreas.sandberg@arm.com    reset();
12412005Sandreas.sandberg@arm.com}
12512005Sandreas.sandberg@arm.com
12612005Sandreas.sandberg@arm.comvoid
12712005Sandreas.sandberg@arm.comNoMaliGpu::serialize(CheckpointOut &cp) const
12812005Sandreas.sandberg@arm.com{
12912531Sandreas.sandberg@arm.com    std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2);
13012531Sandreas.sandberg@arm.com
13112531Sandreas.sandberg@arm.com    for (int i = 0; i < nomaliInfo.reg_size; i += 4)
13212531Sandreas.sandberg@arm.com        regs[i >> 2] = readRegRaw(i);
13312531Sandreas.sandberg@arm.com
13411234Sandreas.sandberg@arm.com    SERIALIZE_CONTAINER(regs);
13511234Sandreas.sandberg@arm.com}
13611234Sandreas.sandberg@arm.com
13711234Sandreas.sandberg@arm.comvoid
13811234Sandreas.sandberg@arm.comNoMaliGpu::unserialize(CheckpointIn &cp)
13911234Sandreas.sandberg@arm.com{
14011234Sandreas.sandberg@arm.com    std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2);
14111234Sandreas.sandberg@arm.com
14211234Sandreas.sandberg@arm.com    UNSERIALIZE_CONTAINER(regs);
14311234Sandreas.sandberg@arm.com
1442567SN/A    for (int i = 0; i < nomaliInfo.reg_size; i += 4)
1456757SAli.Saidi@ARM.com        writeRegRaw(i, regs[i >> 2]);
1468286SAli.Saidi@ARM.com}
1478286SAli.Saidi@ARM.com
1488286SAli.Saidi@ARM.comTick
1498286SAli.Saidi@ARM.comNoMaliGpu::read(PacketPtr pkt)
1508286SAli.Saidi@ARM.com{
1518286SAli.Saidi@ARM.com    assert(pkt->getAddr() >= pioAddr);
1526757SAli.Saidi@ARM.com    const Addr addr(pkt->getAddr() - pioAddr);
1536757SAli.Saidi@ARM.com    const unsigned size(pkt->getSize());
1548286SAli.Saidi@ARM.com
1558706Sandreas.hansson@arm.com    if (addr + size >= nomaliInfo.reg_size)
1568706Sandreas.hansson@arm.com        panic("GPU register '0x%x' out of range!\n", addr);
1578706Sandreas.hansson@arm.com
1588706Sandreas.hansson@arm.com    if (size != 4)
1598286SAli.Saidi@ARM.com        panic("Unexpected GPU register read size: %i\n", size);
1603553SN/A    else if (addr & 0x3)
1613553SN/A        panic("Unaligned GPU read: %i\n", size);
1627693SAli.Saidi@ARM.com
1637693SAli.Saidi@ARM.com    pkt->setLE<uint32_t>(readReg(addr));
1647693SAli.Saidi@ARM.com    pkt->makeResponse();
1657720Sgblack@eecs.umich.edu
1663553SN/A    return 0;
1673553SN/A}
1689050Schander.sudanthi@arm.com
1699050Schander.sudanthi@arm.comTick
1709050Schander.sudanthi@arm.comNoMaliGpu::write(PacketPtr pkt)
17110037SARM gem5 Developers{
17210037SARM gem5 Developers    assert(pkt->getAddr() >= pioAddr);
17310037SARM gem5 Developers    const Addr addr(pkt->getAddr() - pioAddr);
17410037SARM gem5 Developers    const unsigned size(pkt->getSize());
17510037SARM gem5 Developers
17610037SARM gem5 Developers    if (addr + size >= nomaliInfo.reg_size)
17710037SARM gem5 Developers        panic("GPU register '0x%x' out of range!\n", addr);
17810037SARM gem5 Developers
17910037SARM gem5 Developers    if (size != 4)
18010037SARM gem5 Developers        panic("Unexpected GPU register write size: %i\n", size);
18110037SARM gem5 Developers    else if (addr & 0x3)
18210037SARM gem5 Developers        panic("Unaligned GPU write: %i\n", size);
18310037SARM gem5 Developers
18413173Sgiacomo.travaglini@arm.com    writeReg(addr, pkt->getLE<uint32_t>());
18513173Sgiacomo.travaglini@arm.com    pkt->makeAtomicResponse();
18613173Sgiacomo.travaglini@arm.com
18713173Sgiacomo.travaglini@arm.com    return 0;
18813173Sgiacomo.travaglini@arm.com}
18910037SARM gem5 Developers
19010037SARM gem5 DevelopersAddrRangeList
19110037SARM gem5 DevelopersNoMaliGpu::getAddrRanges() const
19210037SARM gem5 Developers{
19310037SARM gem5 Developers    return AddrRangeList({ RangeSize(pioAddr, nomaliInfo.reg_size) });
19410037SARM gem5 Developers}
19510844Sandreas.sandberg@arm.com
19610844Sandreas.sandberg@arm.comvoid
19710037SARM gem5 DevelopersNoMaliGpu::reset()
19810037SARM gem5 Developers{
19910037SARM gem5 Developers    DPRINTF(NoMali, "reset()\n");
20010037SARM gem5 Developers
20110037SARM gem5 Developers    panicOnErr(
20210037SARM gem5 Developers        nomali_reset(nomali),
20310037SARM gem5 Developers        "Failed to reset GPU");
20410037SARM gem5 Developers}
20510037SARM gem5 Developers
20610037SARM gem5 Developersuint32_t
20711574SCurtis.Dunham@arm.comNoMaliGpu::readReg(nomali_addr_t reg)
20811574SCurtis.Dunham@arm.com{
20910037SARM gem5 Developers    uint32_t value;
21010037SARM gem5 Developers
21110037SARM gem5 Developers    panicOnErr(
21210037SARM gem5 Developers        nomali_reg_read(nomali, &value, reg),
21310037SARM gem5 Developers        "GPU register read failed");
21413396Sgiacomo.travaglini@arm.com
21510037SARM gem5 Developers    DPRINTF(NoMali, "readReg(0x%x): 0x%x\n",
21610037SARM gem5 Developers            reg, value);
21710037SARM gem5 Developers
21810037SARM gem5 Developers    return value;
21910037SARM gem5 Developers}
22010037SARM gem5 Developers
22110037SARM gem5 Developers
22210037SARM gem5 Developersvoid
22310037SARM gem5 DevelopersNoMaliGpu::writeReg(nomali_addr_t reg, uint32_t value)
22410037SARM gem5 Developers{
22510037SARM gem5 Developers    DPRINTF(NoMali, "writeReg(0x%x, 0x%x)\n",
22610037SARM gem5 Developers            reg, value);
22710037SARM gem5 Developers
22810037SARM gem5 Developers    panicOnErr(
22910037SARM gem5 Developers        nomali_reg_write(nomali, reg, value),
23010037SARM gem5 Developers        "GPU register write failed");
23110037SARM gem5 Developers}
23210037SARM gem5 Developers
23310037SARM gem5 Developersuint32_t
23410037SARM gem5 DevelopersNoMaliGpu::readRegRaw(nomali_addr_t reg) const
23510037SARM gem5 Developers{
23610037SARM gem5 Developers    uint32_t value;
23710037SARM gem5 Developers
23810037SARM gem5 Developers    panicOnErr(
23912005Sandreas.sandberg@arm.com        nomali_reg_read_raw(nomali, &value, reg),
24012005Sandreas.sandberg@arm.com        "GPU raw register read failed");
24112005Sandreas.sandberg@arm.com
24212005Sandreas.sandberg@arm.com    return value;
24312005Sandreas.sandberg@arm.com}
24412005Sandreas.sandberg@arm.com
24512531Sandreas.sandberg@arm.com
24612531Sandreas.sandberg@arm.comvoid
24712531Sandreas.sandberg@arm.comNoMaliGpu::writeRegRaw(nomali_addr_t reg, uint32_t value)
24812317Sgiacomo.travaglini@arm.com{
24912317Sgiacomo.travaglini@arm.com    panicOnErr(
25012317Sgiacomo.travaglini@arm.com        nomali_reg_write_raw(nomali, reg, value),
25112317Sgiacomo.travaglini@arm.com        "GPU raw register write failed");
25212317Sgiacomo.travaglini@arm.com}
25312317Sgiacomo.travaglini@arm.com
25410037SARM gem5 Developersbool
25510037SARM gem5 DevelopersNoMaliGpu::intState(nomali_int_t intno)
25610037SARM gem5 Developers{
25710037SARM gem5 Developers    int state = 0;
25810037SARM gem5 Developers    panicOnErr(
25910037SARM gem5 Developers        nomali_int_state(nomali, &state, intno),
26010037SARM gem5 Developers        "Failed to get interrupt state");
26110037SARM gem5 Developers
26210037SARM gem5 Developers    return !!state;
26310037SARM gem5 Developers}
26410037SARM gem5 Developers
26510037SARM gem5 Developersvoid
26610037SARM gem5 DevelopersNoMaliGpu::gpuPanic(nomali_error_t err, const char *msg)
26710037SARM gem5 Developers{
26810037SARM gem5 Developers    panic("%s: %s\n", msg, nomali_errstr(err));
26910037SARM gem5 Developers}
27010037SARM gem5 Developers
27110037SARM gem5 Developers
27210037SARM gem5 Developersvoid
27310037SARM gem5 DevelopersNoMaliGpu::onInterrupt(nomali_int_t intno, bool set)
27410037SARM gem5 Developers{
27510037SARM gem5 Developers    const auto it_int(interruptMap.find(intno));
27610037SARM gem5 Developers    if (it_int == interruptMap.end())
27710037SARM gem5 Developers        panic("Unhandled interrupt from NoMali: %i\n", intno);
27810037SARM gem5 Developers
27912318Sgiacomo.travaglini@arm.com    DPRINTF(NoMali, "Interrupt %i->%i: %i\n",
28012318Sgiacomo.travaglini@arm.com            intno, it_int->second, set);
28112318Sgiacomo.travaglini@arm.com
28212318Sgiacomo.travaglini@arm.com    assert(platform);
28312318Sgiacomo.travaglini@arm.com    assert(platform->gic);
28410037SARM gem5 Developers
28513396Sgiacomo.travaglini@arm.com    if (set)
28610037SARM gem5 Developers        platform->gic->sendInt(it_int->second);
28710037SARM gem5 Developers    else
28810037SARM gem5 Developers        platform->gic->clearInt(it_int->second);
28910037SARM gem5 Developers}
29010037SARM gem5 Developers
29110037SARM gem5 Developersvoid
29210037SARM gem5 DevelopersNoMaliGpu::onReset()
29310037SARM gem5 Developers{
29410037SARM gem5 Developers    DPRINTF(NoMali, "Reset\n");
29510037SARM gem5 Developers}
29610037SARM gem5 Developers
29710037SARM gem5 Developersvoid
29810037SARM gem5 DevelopersNoMaliGpu::setCallback(const nomali_callback_t &callback)
29910037SARM gem5 Developers{
30012531Sandreas.sandberg@arm.com    DPRINTF(NoMali, "Registering callback %i\n",
30112531Sandreas.sandberg@arm.com            callback.type);
30212531Sandreas.sandberg@arm.com
30312531Sandreas.sandberg@arm.com    panicOnErr(
30412531Sandreas.sandberg@arm.com        nomali_set_callback(nomali, &callback),
30512531Sandreas.sandberg@arm.com        "Failed to register callback");
30612531Sandreas.sandberg@arm.com}
30712531Sandreas.sandberg@arm.com
30812531Sandreas.sandberg@arm.comvoid
30912531Sandreas.sandberg@arm.comNoMaliGpu::_interrupt(nomali_handle_t h, void *usr,
31012531Sandreas.sandberg@arm.com                      nomali_int_t intno, int set)
31110810Sbr@bsdpad.com{
31210037SARM gem5 Developers    NoMaliGpu *_this(static_cast<NoMaliGpu *>(usr));
31310810Sbr@bsdpad.com
31410810Sbr@bsdpad.com    _this->onInterrupt(intno, !!set);
31510810Sbr@bsdpad.com}
31610810Sbr@bsdpad.com
31710810Sbr@bsdpad.comvoid
31810810Sbr@bsdpad.comNoMaliGpu::_reset(nomali_handle_t h, void *usr)
31910810Sbr@bsdpad.com{
32010810Sbr@bsdpad.com    NoMaliGpu *_this(static_cast<NoMaliGpu *>(usr));
32110810Sbr@bsdpad.com
32210810Sbr@bsdpad.com    _this->onReset();
32310810Sbr@bsdpad.com}
32410810Sbr@bsdpad.com
32510810Sbr@bsdpad.com
32610810Sbr@bsdpad.comCustomNoMaliGpu::CustomNoMaliGpu(const CustomNoMaliGpuParams *p)
32710810Sbr@bsdpad.com    : NoMaliGpu(p),
32810810Sbr@bsdpad.com      idRegs{
32910810Sbr@bsdpad.com        { GPU_CONTROL_REG(GPU_ID), p->gpu_id },
3302567SN/A        { GPU_CONTROL_REG(L2_FEATURES), p->l2_features },
3312567SN/A        { GPU_CONTROL_REG(TILER_FEATURES), p->tiler_features },
3322567SN/A        { GPU_CONTROL_REG(MEM_FEATURES), p->mem_features },
333        { GPU_CONTROL_REG(MMU_FEATURES), p->mmu_features },
334        { GPU_CONTROL_REG(AS_PRESENT), p->as_present },
335        { GPU_CONTROL_REG(JS_PRESENT), p->js_present },
336
337        { GPU_CONTROL_REG(THREAD_MAX_THREADS), p->thread_max_threads },
338        { GPU_CONTROL_REG(THREAD_MAX_WORKGROUP_SIZE),
339          p->thread_max_workgroup_size },
340        { GPU_CONTROL_REG(THREAD_MAX_BARRIER_SIZE),
341          p->thread_max_barrier_size },
342        { GPU_CONTROL_REG(THREAD_FEATURES), p->thread_features },
343
344        { GPU_CONTROL_REG(SHADER_PRESENT_LO), bits(p->shader_present, 31, 0) },
345        { GPU_CONTROL_REG(SHADER_PRESENT_HI), bits(p->shader_present, 63, 32) },
346        { GPU_CONTROL_REG(TILER_PRESENT_LO), bits(p->tiler_present, 31, 0) },
347        { GPU_CONTROL_REG(TILER_PRESENT_HI), bits(p->tiler_present, 63, 32) },
348        { GPU_CONTROL_REG(L2_PRESENT_LO), bits(p->l2_present, 31, 0) },
349        { GPU_CONTROL_REG(L2_PRESENT_HI), bits(p->l2_present, 63, 32) },
350      }
351{
352    fatal_if(p->texture_features.size() > 3,
353             "Too many texture feature registers specified (%i)\n",
354             p->texture_features.size());
355
356    fatal_if(p->js_features.size() > 16,
357             "Too many job slot feature registers specified (%i)\n",
358             p->js_features.size());
359
360    for (int i = 0; i < p->texture_features.size(); i++)
361        idRegs[TEXTURE_FEATURES_REG(i)] = p->texture_features[i];
362
363    for (int i = 0; i < p->js_features.size(); i++)
364        idRegs[JS_FEATURES_REG(i)] = p->js_features[i];
365}
366
367CustomNoMaliGpu::~CustomNoMaliGpu()
368{
369}
370
371void
372CustomNoMaliGpu::onReset()
373{
374    NoMaliGpu::onReset();
375
376    for (const auto &reg : idRegs)
377        writeRegRaw(reg.first, reg.second);
378}
379
380
381
382NoMaliGpu *
383NoMaliGpuParams::create()
384{
385    return new NoMaliGpu(this);
386}
387
388CustomNoMaliGpu *
389CustomNoMaliGpuParams::create()
390{
391    return new CustomNoMaliGpu(this);
392}
393