diff options
author | Andreas Sandberg <andreas.sandberg@arm.com> | 2015-07-07 10:03:13 +0100 |
---|---|---|
committer | Andreas Sandberg <andreas.sandberg@arm.com> | 2015-07-07 10:03:13 +0100 |
commit | c2740578404b4e46d198de70af1cfd554033d99f (patch) | |
tree | bb97478f7d31251d5b1bb0013b6b06b16ca0712c /ext/nomali/lib/nomali_api.cc | |
parent | a0cbf5541133e58968919991635797babaad2a18 (diff) | |
download | gem5-c2740578404b4e46d198de70af1cfd554033d99f.tar.xz |
ext: Add the NoMali GPU no-simulation library
Add revision 9adf9d6e2d889a483a92136c96eb8a434d360561 of NoMali-model
from https://github.com/ARM-software/nomali-model. This library
implements the register interface of the Mali T6xx/T7xx series GPUs,
but doesn't do any rendering. It can be used to hide the effects of
software rendering.
Diffstat (limited to 'ext/nomali/lib/nomali_api.cc')
-rw-r--r-- | ext/nomali/lib/nomali_api.cc | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/ext/nomali/lib/nomali_api.cc b/ext/nomali/lib/nomali_api.cc new file mode 100644 index 000000000..46f0e7fce --- /dev/null +++ b/ext/nomali/lib/nomali_api.cc @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2014-2015 ARM Limited + * All rights reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Authors: Andreas Sandberg + */ + +#include "libnomali/nomali.h" + +#include <cstring> + +#include "mali_t6xx.hh" +#include "mali_t7xx.hh" + +#define EXPORT __attribute__ ((visibility ("default"))) + +static const char *errstrs[] = { + "No error", + "Unknown error", + "Memory allocation failed", + "Invalid model handle", + "Invalid parameter", +}; + +static_assert(sizeof(errstrs) / sizeof(*errstrs) == NOMALI_E_NUM_ERRORS, + "NoMali API error descriptions out of sync!"); + +class NoMaliApi +{ + public: + NoMaliApi(); + ~NoMaliApi(); + + void setGpu(NoMali::GPU *gpu) { _gpu = gpu; } + + public: + nomali_error_t setCallback(const nomali_callback_t *callback); + + nomali_error_t getInfo(nomali_info_t *info); + + nomali_error_t reset(); + nomali_error_t regRead(uint32_t *value, nomali_addr_t addr); + nomali_error_t regWrite(nomali_addr_t addr, uint32_t value); + nomali_error_t regReadRaw(uint32_t *value, nomali_addr_t addr); + nomali_error_t regWriteRaw(nomali_addr_t addr, uint32_t value); + nomali_error_t intState(int *state, nomali_int_t intno) const; + + public: + void callbackInt(nomali_int_t intno, int set); + + private: + nomali_callback_t callbacks[NOMALI_CALLBACK_NUM_CALLBACKS]; + + NoMali::GPU *_gpu; +}; + +template<class BaseGpu> +class NoMaliApiGpu + : public BaseGpu +{ + public: + template<typename... Args> + NoMaliApiGpu(NoMaliApi &_api, Args &&... args) + : BaseGpu(std::forward<Args>(args)...), + api(_api) + { + BaseGpu::reset(); + } + + public: + void intJob(int set) override { api.callbackInt(NOMALI_INT_JOB, set); } + void intMMU(int set) override { api.callbackInt(NOMALI_INT_MMU, set); } + void intGPU(int set) override { api.callbackInt(NOMALI_INT_GPU, set); } + + private: + NoMaliApi &api; +}; + + +NoMaliApi::NoMaliApi() + : _gpu(nullptr) +{ + memset(callbacks, 0, sizeof(callbacks)); +} + + +NoMaliApi::~NoMaliApi() +{ +} + +nomali_error_t +NoMaliApi::setCallback(const nomali_callback_t *callback) +{ + if (!callback || + callback->type >= NOMALI_CALLBACK_NUM_CALLBACKS) + return NOMALI_E_INVALID; + + callbacks[callback->type] = *callback; + + return NOMALI_E_OK; +} + +nomali_error_t +NoMaliApi::getInfo(nomali_info_t *info) +{ + if (!info) + return NOMALI_E_INVALID; + + info->reg_size = 0x4000; + + return NOMALI_E_OK; +} + +nomali_error_t +NoMaliApi::reset() +{ + _gpu->reset(); + return NOMALI_E_OK; +} + +nomali_error_t +NoMaliApi::regRead(uint32_t *value, nomali_addr_t addr) +{ + if (!value) + return NOMALI_E_INVALID; + + *value = _gpu->readReg(NoMali::RegAddr(addr)); + + return NOMALI_E_OK; +} + +nomali_error_t +NoMaliApi::regWrite(nomali_addr_t addr, uint32_t value) +{ + _gpu->writeReg(NoMali::RegAddr(addr), value); + + return NOMALI_E_OK; +} + + +nomali_error_t +NoMaliApi::regReadRaw(uint32_t *value, nomali_addr_t addr) +{ + if (!value) + return NOMALI_E_INVALID; + + *value = _gpu->readRegRaw(NoMali::RegAddr(addr)); + + return NOMALI_E_OK; +} + +nomali_error_t +NoMaliApi::regWriteRaw(nomali_addr_t addr, uint32_t value) +{ + _gpu->writeRegRaw(NoMali::RegAddr(addr), value); + + return NOMALI_E_OK; +} + +nomali_error_t +NoMaliApi::intState(int *state, nomali_int_t intno) const +{ + if (!state) + return NOMALI_E_INVALID; + + switch (intno) { + case NOMALI_INT_GPU: + *state = _gpu->intGPUAsserted(); + break; + + case NOMALI_INT_JOB: + *state = _gpu->intJobAsserted(); + break; + + case NOMALI_INT_MMU: + *state = _gpu->intMMUAsserted(); + break; + + default: + return NOMALI_E_INVALID; + } + + return NOMALI_E_OK; +} + + +void +NoMaliApi::callbackInt(nomali_int_t intno, int set) +{ + const nomali_callback_t &c(callbacks[NOMALI_CALLBACK_INT]); + + if (c.func.interrupt) + c.func.interrupt(static_cast<nomali_handle_t>(this), c.usr, intno, set); +} + + + +static NoMaliApi * +get_gpu(nomali_handle_t h) +{ + return h ? static_cast<NoMaliApi *>(h) : nullptr; +} + + +extern "C" EXPORT nomali_api_version_t +nomali_api_version() +{ + return NOMALI_API_VERSION; +} + +extern "C" EXPORT nomali_error_t +nomali_create(nomali_handle_t *h, const nomali_config_t *cfg) +{ + if (h && cfg) { + NoMaliApi *api(new NoMaliApi()); + *h = api; + if (!h) + return NOMALI_E_MEMORY; + + NoMali::GPU *gpu; + switch (cfg->type) { + case NOMALI_GPU_T60X: + gpu = new NoMaliApiGpu<NoMali::MaliT60x>( + *api, + cfg->ver_maj, cfg->ver_min, cfg->ver_status); + break; + + case NOMALI_GPU_T62X: + gpu = new NoMaliApiGpu<NoMali::MaliT62x>( + *api, + cfg->ver_maj, cfg->ver_min, cfg->ver_status); + break; + + + case NOMALI_GPU_T76X: + gpu = new NoMaliApiGpu<NoMali::MaliT76x>( + *api, + cfg->ver_maj, cfg->ver_min, cfg->ver_status); + break; + + default: + delete api; + return NOMALI_E_INVALID; + }; + + if (!gpu) { + delete api; + return NOMALI_E_MEMORY; + } + + api->setGpu(gpu); + + return NOMALI_E_OK; + } else { + return NOMALI_E_INVALID; + } +} + +extern "C" EXPORT nomali_error_t +nomali_destroy(nomali_handle_t h) +{ + NoMaliApi *gpu(get_gpu(h)); + + if (gpu) { + delete gpu; + return NOMALI_E_OK; + } else { + return NOMALI_E_HANDLE; + } +} + +extern "C" EXPORT const char * +nomali_errstr(nomali_error_t error) +{ + if (error < NOMALI_E_NUM_ERRORS) + return errstrs[error]; + else + return "Invalid error number"; +} + +extern "C" EXPORT nomali_error_t +nomali_set_callback(nomali_handle_t h, + const nomali_callback_t *callback) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->setCallback(callback) : NOMALI_E_HANDLE; +} + +extern "C" EXPORT nomali_error_t +nomali_get_info(nomali_handle_t h, nomali_info_t *info) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->getInfo(info) : NOMALI_E_HANDLE; +} + +extern "C" EXPORT nomali_error_t +nomali_reset(nomali_handle_t h) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->reset() : NOMALI_E_HANDLE; +} + +extern "C" EXPORT nomali_error_t +nomali_reg_read(nomali_handle_t h, uint32_t *value, + nomali_addr_t addr) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->regRead(value, addr) : NOMALI_E_HANDLE; +} + +extern "C" EXPORT nomali_error_t +nomali_reg_write(nomali_handle_t h, + nomali_addr_t addr, uint32_t value) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->regWrite(addr, value) : NOMALI_E_HANDLE; +} + + +extern "C" EXPORT nomali_error_t +nomali_reg_read_raw(nomali_handle_t h, uint32_t *value, + nomali_addr_t addr) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->regReadRaw(value, addr) : NOMALI_E_HANDLE; +} + +extern "C" EXPORT nomali_error_t +nomali_reg_write_raw(nomali_handle_t h, + nomali_addr_t addr, uint32_t value) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->regWriteRaw(addr, value) : NOMALI_E_HANDLE; +} + +extern "C" EXPORT nomali_error_t +nomali_int_state(nomali_handle_t h, int *state, + nomali_int_t intno) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->intState(state, intno) : NOMALI_E_HANDLE; +} + |