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.
This commit is contained in:
Andreas Sandberg 2015-07-07 10:03:13 +01:00
parent a0cbf55411
commit c274057840
39 changed files with 6484 additions and 0 deletions

View file

@ -1202,6 +1202,10 @@ main.SConscript('ext/dramsim2/SConscript',
main.SConscript('ext/drampower/SConscript',
variant_dir = joinpath(build_root, 'drampower'))
# nomali build is shared across all configs in the build root.
main.SConscript('ext/nomali/SConscript',
variant_dir = joinpath(build_root, 'nomali'))
###################################################
#
# This function is used to set up a directory with switching headers

8
ext/nomali/.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
/docs
/tests/nomali_test0
/tests/nomali_test_ints
*~
*.o
*.d
*.so
*.a

1785
ext/nomali/Doxyfile Normal file

File diff suppressed because it is too large Load diff

202
ext/nomali/LICENSE Normal file
View file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

81
ext/nomali/Makefile Normal file
View file

@ -0,0 +1,81 @@
#
# 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
DOXYGEN = doxygen
GCC_VERSION := $(shell $(CC) -dumpversion | sed -e 's/\.//g')
ifeq "$(shell expr $(GCC_VERSION) \< 47)" "1"
$(error Default GCC version is too old. Please use gcc 4.7 or newer.)
endif
CPPFLAGS = -Iinclude/
CFLAGS = -fvisibility=hidden -O1 -g -Wall
CXXFLAGS = -std=c++0x $(CFLAGS)
LDFLAGS=
LIB_CPPFLAGS = $(CPPFLAGS)
LIB_CFLAGS = $(CFLAGS) -fPIC
LIB_CXXFLAGS = $(CXXFLAGS) -fPIC
LIB_LDFLAGS= $(LDFLAGS) -shared
# Default targets
ALL :=
# Test targets
ALL_TESTS :=
# Dependency includes
DEPS :=
# Files/directories to remove in the clean target
CLEAN :=
all: _all
dir:=lib
include $(dir)/Rules.mk
dir:=tests
include $(dir)/Rules.mk
_all: $(ALL)
test: $(ALL_TESTS)
@set -e; \
for T in $^ ; do \
echo "Running $${T}"; \
./$${T}; \
done
docs:
$(DOXYGEN) Doxyfile
depclean:
$(RM) $(DEPS)
clean:
$(RM) -r $(CLEAN)
$(RM) -r docs/html
.PHONY: all _all test depclean clean docs
# Include dependencies
-include $(MODEL_OBJS:.o=.d)
-include $(LIBMIDGARDMODEL_OBJS:.o=.d)
-include $(LIBNOMALI_OBJS:.o=.d)

31
ext/nomali/Rules.app.mk Normal file
View file

@ -0,0 +1,31 @@
#
# 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
# Makefile fragment for executables
$(d)/%.o: $(d)/%.c
$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
$(d)/%.o: $(d)/%.cc
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $<
$(d)/%.d: $(d)/%.c
$(CC) -MM -MT $(<:.c=.o) $(CPPFLAGS) $(CFLAGS) -o $@ $<
$(d)/%.d: $(d)/%.c
$(CXX) -MM -MT $(<:.cc=.o) $(CPPFLAGS) $(CXXFLAGS) -o $@ $<

31
ext/nomali/Rules.lib.mk Normal file
View file

@ -0,0 +1,31 @@
#
# 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
# Makefile fragment for libraries
$(d)/%.o: $(d)/%.c
$(CC) -c $(LIB_CPPFLAGS) $(LIB_CFLAGS) -o $@ $<
$(d)/%.o: $(d)/%.cc
$(CXX) -c $(LIB_CPPFLAGS) $(LIB_CXXFLAGS) -o $@ $<
$(d)/%.d: $(d)/%.c
$(CC) -MM -MT $(<:.c=.o) $(LIB_CPPFLAGS) $(LIB_CFLAGS) -o $@ $<
$(d)/%.d: $(d)/%.c
$(CXX) -MM -MT $(<:.cc=.o) $(LIB_CPPFLAGS) $(LIB_CXXFLAGS) -o $@ $<

63
ext/nomali/SConscript Normal file
View file

@ -0,0 +1,63 @@
# -*- mode:python -*-
# Copyright (c) 2015 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Andreas Sandberg
Import('main')
main.Prepend(CPPPATH=Dir('./include'))
nomali = main.Clone()
nomali_sources = [
"lib/gpu.cc",
"lib/gpublock.cc",
"lib/gpucontrol.cc",
"lib/jobcontrol.cc",
"lib/jobslot.cc",
"lib/mali_midgard.cc",
"lib/mali_t6xx.cc",
"lib/mali_t7xx.cc",
"lib/mmu.cc",
"lib/nomali_api.cc",
]
nomali.Library('nomali', [ nomali.SharedObject(f) for f in nomali_sources ])
main.Append(LIBS=['nomali'])
main.Prepend(LIBPATH=[Dir('.')])

46
ext/nomali/doxygen.sed Executable file
View file

@ -0,0 +1,46 @@
#!/bin/sed -f
#
# 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
# READ BEFORE EDITING:
#
# * Avoid adding or removing newlines (e.g., deleting matched lines). It's
# much easier to understand the Doxygen logs if they point to the right
# line in the source files.
#
# * SED can be hard to read, so please document what your replacement rules
# are supposed to do and why.
#
# Handle TODO/FIXME/BUG comments
/\/\/ \(TODO\|FIXME\|BUG\):/ {
# Transform the first line of the comment block into a Doxygen C++ comment.
s/\([^\]\)\/\/ /\1\/\/\/ /;
: todo_comment_cont
# Replace any TODO/FIXME/BUG commands with Doxygen equivalents
s/\(TODO\|FIXME\):/@todo /;
s/\(BUG\):/@bug /;
# Get the next line
n;
# If this line is only contains whitespace and a comment, it is a
# conntinuation of the previous line. If so, make it a Doxygen comment.
s/\([:space:]*\)\/\/\([^\/]\)/\1\/\/\/\2/ ;
# Try to match another line if the previous s command matched a line.
t todo_comment_cont;
}

View file

@ -0,0 +1,333 @@
/*
* 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
*/
#ifndef _LIBNOMALI_NOMALI_HH
#define _LIBNOMALI_NOMALI_HH
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file libnomali/nomali.h
* @short This header defines the NoMali stub GPU model interface.
*
*/
/** Opaque NoMali model handle. */
typedef void* nomali_handle_t;
/**
* NoMali error codes.
*/
enum {
/** No error */
NOMALI_E_OK = 0,
/** Unknown error */
NOMALI_E_UNKNOWN,
/** Memory allocation failed */
NOMALI_E_MEMORY,
/** Invalid model handle */
NOMALI_E_HANDLE,
/** Invalid parameter */
NOMALI_E_INVALID,
/**
* Number of errors defined
*
* @note This error, and higher error numbers, can be issued if
* the library is newer than the header file. Software should
* tread this condition as an unknown error.
*/
NOMALI_E_NUM_ERRORS
};
typedef int nomali_error_t;
enum {
NOMALI_GPU_T60X = 0,
NOMALI_GPU_T62X,
NOMALI_GPU_T76X,
NOMALI_GPU_T760 = NOMALI_GPU_T76X,
};
typedef int nomali_gpu_type_t;
typedef struct {
nomali_gpu_type_t type;
unsigned ver_maj;
unsigned ver_min;
unsigned ver_status;
} nomali_config_t;
enum {
/** Model is signalling an interrupt */
NOMALI_CALLBACK_INT = 0,
/** Model read physical memory callback */
NOMALI_CALLBACK_MEMREAD,
/** Model write physical memory callback */
NOMALI_CALLBACK_MEMWRITE,
/** Number of defined callbacks */
NOMALI_CALLBACK_NUM_CALLBACKS
};
typedef int nomali_callback_type_t;
enum {
NOMALI_INT_GPU = 0,
NOMALI_INT_JOB,
NOMALI_INT_MMU,
};
typedef int nomali_int_t;
typedef uint64_t nomali_addr_t;
typedef uint64_t nomali_size_t;
/**
* Callback information structure.
*/
typedef struct {
/** Callback type */
nomali_callback_type_t type;
/** Pointer to user-defined data associated with callback */
void *usr;
/** Pointer to callback function */
union {
/**
* Interrupt state change
*
* @param h Model instance handle.
* @param usr User-defined data associated with callback.
* @param intno Interrupt number.
* @param set Non-zero if raising an interrupt, zero if clearing.
*/
void (*interrupt)(nomali_handle_t h, void *usr,
nomali_int_t intno, int set);
void (*memwrite)(nomali_handle_t h, void *usr,
nomali_addr_t addr, uint32_t value);
uint32_t (*memread)(nomali_handle_t h, void *usr,
nomali_addr_t addr);
} func;
} nomali_callback_t;
/**
* GPU information struct. See nomali_get_info().
*/
typedef struct {
/** Size (in bytes) of the register window used by the GPU */
nomali_size_t reg_size;
} nomali_info_t;
typedef uint32_t nomali_api_version_t;
/**
* Current version of the NoMali API
*
* This version number will increase whenever the API changes.
*
* @see nomali_api_version()
*/
#define NOMALI_API_VERSION 0
/**
* Get the version of the API implemented by the library.
*
* Before instantiating a NoMali model, the driving application need
* to ensure that the library implements a compatible version of the
* NoMali API. This is done by calling this function and matching the
* return value with the NOMALI_API_VERSION define. The result of any
* call to the NoMali library is undefined if there is a miss-match
* between the two.
*/
nomali_api_version_t nomali_api_version();
/**
* Create an instance of the NoMali model.
*
* @param[out] h Handle of the new NoMali model instance, undefined on
* error.
*
* @param[in] cfg NoMali GPU configuration.
*
* @errors
* @error NOMALI_E_OK on success.
* @error NOMALI_E_MEMORY if a memory allocation failed.
* @error NOMALI_E_INVALID if a pointer to an output parameter is
* invalid.
*/
nomali_error_t nomali_create(nomali_handle_t *h, const nomali_config_t *cfg);
/**
* Destroy and free resources used by an existing NoMali instance.
*
* @param[in] h Model instance handle.
*
* @errors
* @error NOMALI_E_OK on success.
* @error NOMALI_E_HANDLE if the handle was invalid.
*/
nomali_error_t nomali_destroy(nomali_handle_t h);
/**
* Get a textual description of an error number.
*
* @param[in] error Error number to resolve.
*
* @return Pointer to a constant, null-terminated, string describing
* an error number.
*/
const char *nomali_errstr(nomali_error_t error);
/**
* Setup callbacks from the model.
*
* @param[in] h Model instance handle.
* @param[in] callback Structure describing the new callback to be
* installed.
*
* @errors
* @error NOMALI_E_OK on success.
* @error NOMALI_E_HANDLE if the handle was invalid.
* @error NOMALI_E_INVALID if the callback type was invalid.
*
* @see nomali_callback_t
*/
nomali_error_t nomali_set_callback(nomali_handle_t h,
const nomali_callback_t *callback);
/**
* Get information about the hardware simulated by the model.
*
* @param[in] h Model instance handle.
* @param[out] info Structure describing the model.
*
* @errors
* @error NOMALI_E_OK on success.
* @error NOMALI_E_HANDLE if the handle was invalid.
* @error NOMALI_E_INVALID if info is not pointing to a valid
* location.
*
* @see nomali_info_t
*/
nomali_error_t nomali_get_info(nomali_handle_t h,
nomali_info_t *info);
/**
* Perform a reset of the device.
*
* @param[in] h Model instance handle.
*
* @errors
* @error NOMALI_E_OK on success.
* @error NOMALI_E_HANDLE if the handle was invalid.
*/
nomali_error_t nomali_reset(nomali_handle_t h);
/**
* Read a register within the device.
*
* @param[in] h Model instance handle.
* @param[out] value Pointer to output.
* @param[in] addr Address to read.
*
* @errors
* @error NOMALI_E_OK on success.
* @error NOMALI_E_HANDLE if the handle was invalid.
* @error NOMALI_E_INVALID if an invalid register was specified or if the
* pointer to the output location was invalid.
*/
nomali_error_t nomali_reg_read(nomali_handle_t h, uint32_t *value,
nomali_addr_t addr);
/**
* Write to a register within the device.
*
* @param[in] h Model instance handle.
* @param[in] addr Address to read.
* @param[in] value Value to write to the register.
*
* @errors
* @error NOMALI_E_OK on success.
* @error NOMALI_E_HANDLE if the handle was invalid.
* @error NOMALI_E_INVALID if an invalid register was specified.
*/
nomali_error_t nomali_reg_write(nomali_handle_t h,
nomali_addr_t addr, uint32_t value);
/**
* Read a register without side effects.
*
* @param[in] h Model instance handle.
* @param[out] value Pointer to output.
* @param[in] addr Address to read.
*
* @errors
* @error NOMALI_E_OK on success.
* @error NOMALI_E_HANDLE if the handle was invalid.
* @error NOMALI_E_INVALID if an invalid register was specified or if the
* pointer to the output location was invalid.
*/
nomali_error_t nomali_reg_read_raw(nomali_handle_t h, uint32_t *value,
nomali_addr_t addr);
/**
* Write to a register without side effects.
*
* @param[in] h Model instance handle.
* @param[in] addr Address to read.
* @param[in] value Value to write to the register.
*
* @errors
* @error NOMALI_E_OK on success.
* @error NOMALI_E_HANDLE if the handle was invalid.
* @error NOMALI_E_INVALID if an invalid register was specified.
*/
nomali_error_t nomali_reg_write_raw(nomali_handle_t h,
nomali_addr_t addr, uint32_t value);
/**
* Get the state of an interrupt line
*
* This function queries the state of one of the GPU's interrupt
* lines. The state of the interrupt line is returned in 'state',
* which is 1 if the interrupt is being asserted and 0 otherwise. The
* value of the state variable is undefined if the function call
* fails.
*
* @param[in] h Model instance handle.
* @param[out] state Pointer to output, 1 if the interrupt is
* asserted, 0 otherwise.
* @param[in] intno Interrupt to query.
*
* @errors
* @error NOMALI_E_OK on success.
* @error NOMALI_E_HANDLE if the handle was invalid.
* @error NOMALI_E_INVALID if an invalid interrupt was specified or if
* pointer to the output location was invalid.
*/
nomali_error_t nomali_int_state(nomali_handle_t h, int *state,
nomali_int_t intno);
#ifdef __cplusplus
};
#endif
#endif /* _LIBNOMALI_NOMALI_HH */

55
ext/nomali/lib/Rules.mk Normal file
View file

@ -0,0 +1,55 @@
#
# 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
sp := $(sp).x
dirstack_$(sp) := $(d)
d := $(dir)
NOMALI_OBJS := $(addprefix $(d)/, \
gpu.o \
gpublock.o \
gpucontrol.o \
jobcontrol.o \
jobslot.o \
mmu.o \
\
mali_midgard.o \
mali_t6xx.o \
mali_t7xx.o \
)
LIBNOMALI_OBJS := $(addprefix $(d)/, \
nomali_api.o \
)
OBJS := $(NOMALI_OBJS) \
$(LIBMIDGARDMODEL_OBJS)
LIBS := libnomali.so
ALL := $(ALL) $(LIBS)
DEPS := $(DEPS) $(OBJS:.o=.d)
CLEAN := $(CLEAN) $(OBJS) $(LIBS)
include Rules.lib.mk
libnomali.so: $(NOMALI_OBJS) $(LIBNOMALI_OBJS)
$(CXX) $(LIB_LDFLAGS) -o $@ $^
d := $(dirstack_$(sp))
sp := $(basename $(sp))

112
ext/nomali/lib/gpu.cc Normal file
View file

@ -0,0 +1,112 @@
/*
* 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.
*/
#include "gpu.hh"
#include "gpucontrol.hh"
#include "jobcontrol.hh"
#include "mmu.hh"
#include "regutils.hh"
namespace NoMali {
GPU::GPU(GPUControl &gc, JobControl &jc, MMU &_mmu)
: gpuControl(gc), jobControl(jc), mmu(_mmu),
blocks({&gpuControl, // REG_BLOCK_GPU
&jobControl, // REG_BLOCK_JOB
&mmu}) // REG_BLOCK_MMU
{
}
GPU::~GPU()
{
}
void
GPU::reset()
{
for (auto *block : blocks)
block->reset();
}
uint32_t
GPU::readReg(RegAddr addr)
{
GPUBlock * const block(getGPUBlock(addr));
return block ? block->readReg(getBlockReg(addr)) : 0;
}
void
GPU::writeReg(RegAddr addr, uint32_t value)
{
GPUBlock * const block(getGPUBlock(addr));
if (block)
block->writeReg(getBlockReg(addr), value);
}
uint32_t
GPU::readRegRaw(RegAddr addr)
{
GPUBlock * const block(getGPUBlock(addr));
return block ? block->readRegRaw(getBlockReg(addr)) : 0;
}
void
GPU::writeRegRaw(RegAddr addr, uint32_t value)
{
GPUBlock * const block(getGPUBlock(addr));
if (block)
block->writeRegRaw(getBlockReg(addr), value);
}
bool
GPU::intGPUAsserted() const
{
return gpuControl.intAsserted();
}
bool
GPU::intJobAsserted() const
{
return jobControl.intAsserted();
}
bool
GPU::intMMUAsserted() const
{
return mmu.intAsserted();
}
GPUBlock *
GPU::getGPUBlock(RegAddr addr)
{
const RegBlock block(getRegBlock(addr));
const uint16_t block_no(static_cast<uint16_t>(block));
if (block_no < blocks.size())
return blocks[block_no];
else
return nullptr;
}
}

205
ext/nomali/lib/gpu.hh Normal file
View file

@ -0,0 +1,205 @@
/*
* 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
*/
#ifndef _LIBNOMALIMODEL_GPU_HH
#define _LIBNOMALIMODEL_GPU_HH
#include <vector>
#include "types.hh"
namespace NoMali {
class GPUBlock;
class GPUControl;
class JobControl;
class MMU;
/**
* Top-level GPU component (abstract).
*/
class GPU
{
public:
/**
* Instantiate a GPU from a set of functional blocks.
*
* @param gpuControl GPU control implementation.
* @param jobControl Job control implementation.
* @param mmu MMU implementation.
*/
GPU(GPUControl &gpuControl, JobControl &jobControl, MMU &mmu);
virtual ~GPU() = 0;
/**
* Reset the whole GPU
*
* The default implementation of this method calls the reset() on
* all the function blocks. Function blocks in turn typically sets
* all registers to zero.
*/
virtual void reset();
/**
* @{
* @name Register Interface
*/
/**
* Read a register value from the GPU.
*
* This method decodes the address to find the function block an
* access is intended for and forward the register access to that
* block. The access that reaches the block does not include the
* block base address.
*
* @param addr Register address to read.
* @return Value of the register.
*/
virtual uint32_t readReg(RegAddr addr);
/**
* Write a register value to the GPU.
*
* This method decodes the address to find the function block an
* access is intended for and forward the register access to that
* block. The access that reaches the block does not include the
* block base address.
*
* @param addr Target address for the write operation.
* @param value Value to write.
*/
virtual void writeReg(RegAddr addr, uint32_t value);
/**
* Read a register value from the GPU without side effects.
*
* This method decodes the address to find the function block an
* access is intended for and forward the register access to that
* block. The access that reaches the block does not include the
* block base address.
*
* Unlike a normal read (readReg()), this method does not include
* any side effects and reads straight from the register file. It
* is primarily intended for things checkpointing.
*
* @param addr Register address to read.
* @return Value of the register.
*/
virtual uint32_t readRegRaw(RegAddr addr);
/**
* Write a register value to the GPU without side effects.
*
* This method decodes the address to find the function block an
* access is intended for and forward the register access to that
* block. The access that reaches the block does not include the
* block base address.
*
* Unlike a normal write (writeReg()), this method does not
* include any side effects and writes straight into the register
* file. It is primarily intended for things checkpointing.
*
* @param addr Target address for the write operation.
* @param value Value to write.
*/
virtual void writeRegRaw(RegAddr addr, uint32_t value);
/** @} */
/**
* @{
* @name Callbacks
*/
/**
* Job interrupt state change
*
* @param set Non-zero if raising interrupt, zero if clearing.
*/
virtual void intJob(int set) {};
/**
* MMU interrupt state change
*
* @param set Non-zero if raising interrupt, zero if clearing.
*/
virtual void intMMU(int set) {};
/**
* GPU interrupt state change
*
* @param set Non-zero if raising interrupt, zero if clearing.
*/
virtual void intGPU(int set) {};
/** @} */
/**
* Check if the GPU interrupt has been asserted.
*
* @see GPUControl::intAsserted()
*
* @return true if the GPU control block reports that an interrupt
* has been asserted.
*/
bool intGPUAsserted() const;
/**
* Check if the job interrupt has been asserted.
*
* @see JobControl::intAsserted()
*
* @return true if the job control block reports that an interrupt
* has been asserted.
*/
bool intJobAsserted() const;
/**
* Check if the MMU interrupt has been asserted.
*
* @see JobControl::intAsserted()
*
* @return true if the GPU control block reports that an interrupt
* has been asserted.
*/
bool intMMUAsserted() const;
private:
/**
* Resolve an address into a functional block within the GPU.
*
* @return Valid pointer or NULL if address is out of range.
*/
GPUBlock *getGPUBlock(RegAddr addr);
GPUControl &gpuControl;
JobControl &jobControl;
MMU &mmu;
/**
* Vector of control blocks.
*
* @note The order <i>MUST</i> have the same correspond to the
* values in the RegBlock enum.
*/
const std::vector<GPUBlock *> blocks;
};
}
#endif // _LIBNOMALIMODEL_GPU_HH

156
ext/nomali/lib/gpublock.cc Normal file
View file

@ -0,0 +1,156 @@
/*
* 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 "gpublock.hh"
#include "gpu.hh"
#include "regutils.hh"
namespace NoMali {
GPUBlock::GPUBlock(GPU &_gpu)
: gpu(_gpu), regs(BLOCK_NUM_REGS)
{
}
GPUBlock::GPUBlock(GPU &_gpu, RegVector::size_type no_regs)
: gpu(_gpu), regs(no_regs)
{
}
GPUBlock::GPUBlock(GPUBlock &&rhs)
: gpu(rhs.gpu),
regs(std::move(rhs.regs))
{
}
GPUBlock::~GPUBlock()
{
}
void
GPUBlock::reset()
{
for (auto &r : regs)
r = 0;
}
uint32_t
GPUBlock::readReg(RegAddr addr)
{
return readRegRaw(addr);
}
void
GPUBlock::writeReg(RegAddr addr, uint32_t value)
{
writeRegRaw(addr, value);
}
uint32_t
GPUBlock::readRegRaw(RegAddr addr)
{
return regs[addr];
}
void
GPUBlock::writeRegRaw(RegAddr addr, uint32_t value)
{
regs[addr] = value;
}
GPUBlockInt::GPUBlockInt(GPU &_gpu,
const RegAddr &irq_raw_stat,
const RegAddr &irq_clear,
const RegAddr &irq_mask,
const RegAddr &irq_stat)
: GPUBlock(_gpu),
addrIrqRawStat(irq_raw_stat), addrIrqClear(irq_clear),
addrIrqMask(irq_mask), addrIrqStat(irq_stat)
{
}
GPUBlockInt::~GPUBlockInt()
{
}
uint32_t
GPUBlockInt::readReg(RegAddr addr)
{
if (addr == addrIrqStat) {
return irqStatus();
} else {
return GPUBlock::readReg(addr);
}
}
void
GPUBlockInt::writeReg(RegAddr addr, uint32_t value)
{
if (addr == addrIrqRawStat) {
raiseInterrupt(value);
} else if (addr == addrIrqClear) {
clearInterrupt(value);
} else if (addr == addrIrqMask ) {
const bool old_int(intAsserted());
GPUBlock::writeReg(addr, value);
if (old_int != intAsserted())
onInterrupt(intAsserted());
} else if (addr == addrIrqStat ) {
// Ignore writes to the IRQ status register
} else {
// Handle addrIrqMask & defaults
GPUBlock::writeReg(addr, value);
}
}
void
GPUBlockInt::raiseInterrupt(uint32_t ints)
{
const bool old_int(intAsserted());
regs[addrIrqRawStat] |= ints;
// Is the interrupt line going high?
if (!old_int && intAsserted())
onInterrupt(1);
}
void
GPUBlockInt::clearInterrupt(uint32_t ints)
{
const bool old_int(intAsserted());
regs[addrIrqRawStat] &= ~ints;
// Is the interrupt line going low?
if (old_int && !intAsserted())
onInterrupt(0);
}
uint32_t
GPUBlockInt::irqStatus() const
{
return regs[addrIrqRawStat] & regs[addrIrqMask];
}
}

221
ext/nomali/lib/gpublock.hh Normal file
View file

@ -0,0 +1,221 @@
/*
* 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
*/
#ifndef _LIBNOMALIMODEL_GPUBLOCK_HH
#define _LIBNOMALIMODEL_GPUBLOCK_HH
#include "types.hh"
namespace NoMali {
class GPU;
/**
* Base class for GPU function blocks providing common access
* functions.
*/
class GPUBlock
{
public:
GPUBlock(GPU &_gpu);
GPUBlock(GPU &_gpu, RegVector::size_type no_regs);
GPUBlock(GPUBlock &&rhs);
virtual ~GPUBlock() = 0;
/**
* Reset the function block.
*
* This method is called to simulated a hard reset of the GPU. It
* resets all registers to their default state and resets any
* block-specific state. The default implementation resets all
* registers to 0.
*/
virtual void reset();
/**
* @{
* @name Register Interface
*/
/**
* Read a register within a function block.
*
* @param addr Function-block relative address.
* @return Register value (32-bits)
*/
virtual uint32_t readReg(RegAddr addr);
/**
* Write to a register within a function block.
*
* @param addr Function-block relative address.
* @param value New value (32-bits)
*/
virtual void writeReg(RegAddr addr, uint32_t value);
/**
* Read a register within a function block without side effects.
*
* Unlike a normal read (readReg()), this method does not include
* any side effects and reads straight from the register file. It
* is primarily intended for things checkpointing.
*
* @param addr Function-block relative address.
* @return Register value (32-bits)
*/
virtual uint32_t readRegRaw(RegAddr addr);
/**
* Write to a register within a function block without side
* effects.
*
* Unlike a normal write (writeReg()), this method does not
* include any side effects and writes straight into the register
* file. It is primarily intended for things checkpointing.
*
* @param addr Function-block relative address.
* @param value New value (32-bits)
*/
virtual void writeRegRaw(RegAddr addr, uint32_t value);
/** @} */
protected:
/** Reference to the top-level GPU component */
GPU &gpu;
/** GPU block register file */
RegVector regs;
private:
/** Disable the default constructor */
GPUBlock();
/** Disable the copy constructor */
GPUBlock(GPUBlock &_rhs);
/** Disable the assignment operator */
GPUBlock &operator=(GPUBlock &_rhs);
};
/**
* Base class for interrupt enabled GPU function blocks.
*
* Function blocks with interrupt functionality implement four
* different registers controlling interrupts:
* <ul>
* <li>XX_IRQ_RAWSTAT -- Raw interrupt state bit mask. (RW)
* <li>XX_IRQ_CLEAR -- Interrupt clear register. (WO)
* <li>XX_IRQ_MASK -- Bitmaks of enabled interrupts. (RW)
* <li>XX_IRQ_STATUS -- Currently pending unmasked interrupts. (RO)
* </ul>
*
* This class provides implements the handling of the registers above
* and utility functions to raise interrupts from the function block
* models.
*/
class GPUBlockInt
: public GPUBlock
{
public:
GPUBlockInt(GPU &_gpu,
const RegAddr &irq_raw_stat,
const RegAddr &irq_clear,
const RegAddr &irq_mask,
const RegAddr &irq_stat);
virtual ~GPUBlockInt() = 0;
uint32_t readReg(RegAddr addr) override;
void writeReg(RegAddr addr, uint32_t value) override;
/**
* Raise an interrupt from this function block.
*
* Calling this method flags the interrupts in ints as pending in
* the raw interrupt status register. If this operation asserts a
* new unmasked interrupt (i.e., the state of the interrupt status
* register changes), the onInterrupt() callback is called to
* signal an interrupt state change.
*
* @param ints Bitfield representing interrupts to raise.
*/
void raiseInterrupt(uint32_t ints);
/**
* Clear an interrupt from this function block.
*
* Calling this method clears the interrupts in ints in the raw
* interrupt status register. If this operation clears a an
* existing interrupt (i.e., the state of the interrupt status
* register changes), the onInterrupt() callback is called to
* signal an interrupt state change.
*
* @param ints Bitfield representing interrupts to raise.
*/
void clearInterrupt(uint32_t ints);
/**
* Current interrupt status
*
* @return The value of the raw interrupt status register
* logically anded with the interrupt mask register.
*/
uint32_t irqStatus() const;
/**
* Are there unmasked interrupts pending?
*
* @return true if the interrupt status register is non-zero,
* false otherwise.
*/
bool intAsserted() const { return !!irqStatus(); }
protected:
/**
* Callback method for interrupt status change.
*
* This method is called whenever the interrupt signal going out
* of this GPU block changes. The new state of the signal can be
* determined from the 'set' parameter which is non-zero if the
* inerrupt is raised and zero if it is cleared. The state of the
* interrupt signal can also be queried using the irqStatus()
* method.
*
* @see raiseInterrupt()
* @see clearInterrupt()
* @see irqStatus()
*
* @param set Non-zero to raise interrupt, zero to clear
* interrupt.
*/
virtual void onInterrupt(int set) = 0;
private:
const RegAddr addrIrqRawStat;
const RegAddr addrIrqClear;
const RegAddr addrIrqMask;
const RegAddr addrIrqStat;
};
}
#endif // _LIBNOMALIMODEL_GPUBLOCK_HH

View file

@ -0,0 +1,177 @@
/*
* 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 "gpucontrol.hh"
#include "gpu.hh"
#include "regutils.hh"
namespace NoMali {
typedef void (GPUControl::*GpuCmdHandler)(uint32_t);
const std::vector<GpuCmdHandler> GPUControl::cmds {
&GPUControl::cmdNop, // GPU_COMMAND_NOP
&GPUControl::cmdSoftReset, // GPU_COMMAND_SOFT_RESET
&GPUControl::cmdHardReset, // GPU_COMMAND_HARD_RESET
&GPUControl::cmdPerfCntClear, // GPU_COMMAND_PRFCNT_CLEAR
&GPUControl::cmdPerfCntSample, // GPU_COMMAND_PRFCNT_SAMPLE
&GPUControl::cmdCycleCountStart, // GPU_COMMAND_CYCLE_COUNT_START
&GPUControl::cmdCycleCountStop, // GPU_COMMAND_COUNT_STOP
&GPUControl::cmdCleanCaches, // GPU_COMMAND_CLEAN_CACHES
&GPUControl::cmdCleanInvCaches, // GPU_COMMAND_CLEAN_INV_CACHES
};
GPUControl::GPUControl(GPU &_gpu)
: GPUBlockInt(_gpu,
RegAddr(GPU_IRQ_RAWSTAT),
RegAddr(GPU_IRQ_CLEAR),
RegAddr(GPU_IRQ_MASK),
RegAddr(GPU_IRQ_STATUS))
{
}
GPUControl::~GPUControl()
{
}
void
GPUControl::reset()
{
GPUBlock::reset();
}
void
GPUControl::writeReg(RegAddr addr, uint32_t value)
{
switch (addr.value) {
case GPU_IRQ_RAWSTAT:
case GPU_IRQ_CLEAR:
case GPU_IRQ_MASK:
case GPU_IRQ_STATUS:
GPUBlockInt::writeReg(addr, value);
break;
case GPU_COMMAND:
gpuCommand(value);
break;
case SHADER_PWRON_LO:
case SHADER_PWRON_HI:
case TILER_PWRON_LO:
case TILER_PWRON_HI:
case L2_PWRON_LO:
case L2_PWRON_HI:
case L3_PWRON_LO:
case L3_PWRON_HI: {
const RegAddr ready_reg(SHADER_READY_LO +
(addr.value - SHADER_PWRON_LO));
const RegAddr present_reg(SHADER_PRESENT_LO +
(addr.value - SHADER_PWRON_LO));
regs[ready_reg] |= value & regs[present_reg];
raiseInterrupt(POWER_CHANGED_SINGLE | POWER_CHANGED_ALL);
} break;
case SHADER_PWROFF_LO:
case SHADER_PWROFF_HI:
case TILER_PWROFF_LO:
case TILER_PWROFF_HI:
case L2_PWROFF_LO:
case L2_PWROFF_HI:
case L3_PWROFF_LO:
case L3_PWROFF_HI: {
const RegAddr ready_reg(SHADER_READY_LO +
(addr.value - SHADER_PWROFF_LO));
regs[ready_reg] &= ~value;
raiseInterrupt(POWER_CHANGED_SINGLE | POWER_CHANGED_ALL);
} break;
default:
// Ignore writes by default
break;
};
}
void
GPUControl::onInterrupt(int set)
{
gpu.intGPU(set);
}
void
GPUControl::gpuCommand(uint32_t cmd)
{
if (cmd < cmds.size())
(this->*cmds[cmd])(cmd);
}
void
GPUControl::cmdNop(uint32_t cmd)
{
}
void
GPUControl::cmdHardReset(uint32_t cmd)
{
gpu.reset();
raiseInterrupt(RESET_COMPLETED);
}
void
GPUControl::cmdSoftReset(uint32_t cmd)
{
gpu.reset();
raiseInterrupt(RESET_COMPLETED);
}
void
GPUControl::cmdPerfCntClear(uint32_t cmd)
{
}
void
GPUControl::cmdPerfCntSample(uint32_t cmd)
{
raiseInterrupt(PRFCNT_SAMPLE_COMPLETED);
}
void
GPUControl::cmdCycleCountStart(uint32_t cmd)
{
}
void
GPUControl::cmdCycleCountStop(uint32_t cmd)
{
}
void
GPUControl::cmdCleanCaches(uint32_t cmd)
{
raiseInterrupt(CLEAN_CACHES_COMPLETED);
}
void
GPUControl::cmdCleanInvCaches(uint32_t cmd)
{
raiseInterrupt(CLEAN_CACHES_COMPLETED);
}
}

View file

@ -0,0 +1,159 @@
/*
* 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
*/
#ifndef _LIBNOMALIMODEL_GPUCONTROL_HH
#define _LIBNOMALIMODEL_GPUCONTROL_HH
#include <vector>
#include "types.hh"
#include "gpublock.hh"
namespace NoMali {
class GPU;
/**
* Limited GPU control block implementation.
*
* This is a minimal implementation of the Midgard GPU control
* block. It contains the stuff necessary to do command decoding and
* dispatch, interrupt handling, and GPU block ready handling.
*
* An actual GPU implementation should specialize this class to setup
* the following registers from the reset() method:
* <ul>
* <li>GPU_ID
* <li>Feature registers (XX_FEATURES)
* <li>Present registers (XX_PRESENT)
* <li>Thread discovery (THREAD_XX)
* <li>Present registers (XX_PRESENT)
* </ul>
*/
class GPUControl
: public GPUBlockInt
{
public:
GPUControl(GPU &_gpu);
virtual ~GPUControl();
virtual void reset() override = 0;
void writeReg(RegAddr idx, uint32_t value) override;
protected:
void onInterrupt(int set) override;
/**
* @{
* @name GPU control block commands
*/
/**
* Control command dispatcher.
*
* This method is called whenever there is a write to the
* GPU_COMMAND register. The method uses a lookup table to call
* the right command handling method.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
virtual void gpuCommand(uint32_t cmd);
/**
* Command handler for No-ops.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
virtual void cmdNop(uint32_t cmd);
/**
* Command handler for GPU-wide hard resets
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
virtual void cmdHardReset(uint32_t cmd);
/**
* Command handler for GPU-wide soft resets
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
virtual void cmdSoftReset(uint32_t cmd);
/**
* Command handler for performance counter clear operations.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
virtual void cmdPerfCntClear(uint32_t cmd);
/**
* Command handler for performance counter sample operations.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
virtual void cmdPerfCntSample(uint32_t cmd);
/**
* Command handler for cycle counter start operations.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
virtual void cmdCycleCountStart(uint32_t cmd);
/**
* Command handler for cycle counter stop operations.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
virtual void cmdCycleCountStop(uint32_t cmd);
/**
* Command handler for cache cleaning operations.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
virtual void cmdCleanCaches(uint32_t cmd);
/**
* Command handler for cache clean and invalidate operations.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
virtual void cmdCleanInvCaches(uint32_t cmd);
/** @} */
protected:
typedef void (GPUControl::*cmd_t)(uint32_t);
/**
* Mapping between command IDs and command handling methods.
*
* @note The order of this vector <i>MUST</i> correspond to the
* GPU control command IDs in the Midgard architecture
* specification.
*/
static const std::vector<cmd_t> cmds;
};
}
#endif // _LIBNOMALIMODEL_GPUCONTROL_HH

View file

@ -0,0 +1,139 @@
/*
* 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 "jobcontrol.hh"
#include "gpu.hh"
#include "regutils.hh"
namespace NoMali {
JobControl::JobControl(GPU &_gpu)
: GPUBlockInt(_gpu,
RegAddr(JOB_IRQ_RAWSTAT),
RegAddr(JOB_IRQ_CLEAR),
RegAddr(JOB_IRQ_MASK),
RegAddr(JOB_IRQ_STATUS))
{
slots.reserve(16);
for (int i = 0; i < 16; ++i)
slots.emplace_back(_gpu, *this, i);
}
JobControl::~JobControl()
{
}
uint32_t
JobControl::readReg(RegAddr addr)
{
if (addr >= RegAddr(JOB_SLOT0)) {
return slots[getJobSlotNo(addr)].readReg(getJobSlotAddr(addr));
} else {
return GPUBlockInt::readReg(addr);
}
}
void
JobControl::writeReg(RegAddr addr, uint32_t value)
{
switch(addr.value) {
case JOB_IRQ_CLEAR:
// Update JS state for all jobs that were affected by the IRQ
// clear
updateJsState((value & 0xFFFF) | ((value & 0xFFFF0000) >> 16));
// FALLTHROUGH - IRQ handling in base class
case JOB_IRQ_RAWSTAT:
case JOB_IRQ_MASK:
case JOB_IRQ_STATUS:
GPUBlockInt::writeReg(addr, value);
break;
default:
if (addr >= RegAddr(JOB_SLOT0))
slots[getJobSlotNo(addr)].writeReg(getJobSlotAddr(addr), value);
break;
}
}
uint32_t
JobControl::readRegRaw(RegAddr addr)
{
if (addr >= RegAddr(JOB_SLOT0)) {
return slots[getJobSlotNo(addr)].readRegRaw(getJobSlotAddr(addr));
} else {
return GPUBlockInt::readRegRaw(addr);
}
}
void
JobControl::writeRegRaw(RegAddr addr, uint32_t value)
{
if (addr >= RegAddr(JOB_SLOT0)) {
slots[getJobSlotNo(addr)].writeRegRaw(getJobSlotAddr(addr), value);
} else {
GPUBlockInt::writeRegRaw(addr, value);
}
}
void
JobControl::jobDone(uint8_t slot)
{
assert(slot <= 15);
raiseInterrupt(1 << slot);
}
void
JobControl::jobFailed(uint8_t slot)
{
assert(slot <= 15);
raiseInterrupt(0x10000 << slot);
}
void
JobControl::updateJsState(uint16_t jobs)
{
// The JS_STATE register contains two bits per job slot; one bit
// representing an active job and one bit representing the queued
// job. We need to mask out bits of the jobs affected by this update.
const uint32_t job_mask(jobs | (jobs << 16));
uint16_t js_state(regs[RegAddr(JOB_IRQ_JS_STATE)] & ~job_mask);
// Find if there is an active or active next job for all jobs in
// the job mask.
for (int i = 0; i < 16; ++i) {
const JobSlot &slot(slots[i]);
if (jobs & (1 << i)) {
js_state |= slot.active() ? (1 << i) : 0 |
slot.activeNext() ? (0x10000 << i) : 0;
}
}
regs[RegAddr(JOB_IRQ_JS_STATE)] = js_state;
}
void
JobControl::onInterrupt(int set)
{
gpu.intJob(set);
}
}

View file

@ -0,0 +1,93 @@
/*
* 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
*/
#ifndef _LIBNOMALIMODEL_JOBCONTROL_HH
#define _LIBNOMALIMODEL_JOBCONTROL_HH
#include <vector>
#include "gpublock.hh"
#include "jobslot.hh"
#include "types.hh"
namespace NoMali {
class GPU;
/**
* Minimal GPU job control implementation.
*
* This class implements the job control block of a Midgard style
* GPU. The job control block mainly coordinates interrupt delivery
* and register mappings for the different job slots within the
* block. The actual job slots are implemented by the JobSlot class.
*
* @see JobSlot
*/
class JobControl
: public GPUBlockInt
{
public:
JobControl(GPU &_gpu);
virtual ~JobControl();
uint32_t readReg(RegAddr idx) override;
void writeReg(RegAddr idx, uint32_t value) override;
uint32_t readRegRaw(RegAddr idx) override;
void writeRegRaw(RegAddr idx, uint32_t value) override;
/**
* Signal job done.
*
* Calling this method raises the job done interrupt for a
* specific job slot. This is typically called from the job slot
* running the job chain.
*
* @param slot Job slot number.
*/
void jobDone(uint8_t slot);
/**
* Signal job failed.
*
* Calling this method raises the job failed interrupt for a
* specific job slot. This is typically called from the job slot
* running the job chain.
*
* @param slot Job slot number.
*/
void jobFailed(uint8_t slot);
protected:
/**
* Update the state of the job slot state snapshot register.
*
* @param jobs Bit mask representing which job slots to update.
*/
void updateJsState(uint16_t jobs);
void onInterrupt(int set) override;
/** Job slots belonging to this job control block */
std::vector<JobSlot> slots;
};
}
#endif // _LIBNOMALIMODEL_JOBCONTROL_HH

216
ext/nomali/lib/jobslot.cc Normal file
View file

@ -0,0 +1,216 @@
/*
* 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 "jobslot.hh"
#include <cassert>
#include <cstdlib>
#include "jobcontrol.hh"
#include "gpu.hh"
#include "regutils.hh"
namespace NoMali {
const std::vector<JobSlot::cmd_t> JobSlot::cmds {
&JobSlot::cmdNop, // JSn_COMMAND_NOP
&JobSlot::cmdStart, // JSn_COMMAND_START
&JobSlot::cmdSoftStop, // JSn_COMMAND_SOFT_STOP
&JobSlot::cmdHardStop, // JSn_COMMAND_HARD_STOP
&JobSlot::cmdSoftStop0, // JSn_COMMAND_SOFT_STOP_0
&JobSlot::cmdHardStop0, // JSn_COMMAND_HARD_STOP_0
&JobSlot::cmdSoftStop1, // JSn_COMMAND_SOFT_STOP_1
&JobSlot::cmdHardStop1, // JSn_COMMAND_HARD_STOP_1
};
JobSlot::JobSlot(GPU &_gpu, JobControl &_jc, uint8_t _id)
: GPUBlock(_gpu, JSn_NO_REGS),
id(_id),
jc(_jc)
{
}
JobSlot::JobSlot(JobSlot &&rhs)
: GPUBlock(std::move(rhs)),
id(std::move(rhs.id)),
jc(rhs.jc)
{
}
JobSlot::~JobSlot()
{
}
void
JobSlot::writeReg(RegAddr addr, uint32_t value)
{
switch (addr.value) {
case JSn_COMMAND:
jobCommand(value);
break;
case JSn_COMMAND_NEXT:
regs[addr] = value;
tryStart();
break;
case JSn_HEAD_NEXT_LO:
case JSn_HEAD_NEXT_HI:
case JSn_AFFINITY_NEXT_LO:
case JSn_AFFINITY_NEXT_HI:
case JSn_CONFIG_NEXT:
GPUBlock::writeReg(addr, value);
break;
default:
// Ignore writes by default
break;
};
}
bool
JobSlot::active() const
{
return false;
}
bool
JobSlot::activeNext() const
{
return regs[RegAddr(JSn_COMMAND_NEXT)] == JSn_COMMAND_START;
}
void
JobSlot::tryStart()
{
// Only actually start something if the next command is start
if (regs[RegAddr(JSn_COMMAND_NEXT)] != JSn_COMMAND_START )
return;
// Reset the status register
regs[RegAddr(JSn_STATUS)] = 0;
// Transfer the next job configuration to the active job
// configuration
regs.set64(RegAddr(JSn_HEAD_LO), regs.get64(RegAddr(JSn_HEAD_NEXT_LO)));
regs.set64(RegAddr(JSn_TAIL_LO), regs.get64(RegAddr(JSn_HEAD_NEXT_LO)));
regs.set64(RegAddr(JSn_AFFINITY_LO),
regs.get64(RegAddr(JSn_AFFINITY_NEXT_LO)));
regs[RegAddr(JSn_CONFIG)] = regs[RegAddr(JSn_CONFIG_NEXT)];
regs[RegAddr(JSn_COMMAND)] = regs[RegAddr(JSn_COMMAND_NEXT)];
// Reset the next job configuration
regs.set64(RegAddr(JSn_HEAD_NEXT_LO), 0);
regs.set64(RegAddr(JSn_AFFINITY_NEXT_LO), 0);
regs[RegAddr(JSn_CONFIG_NEXT)] = 0;
regs[RegAddr(JSn_COMMAND_NEXT)] = 0;
runJob();
}
void
JobSlot::runJob()
{
exitJob(Status(Status::CLASS_NOFAULT, 0, 1), // JSn_STATUS_DONE
0); // Time stamp counter value
}
void
JobSlot::exitJob(Status status, uint64_t fault_address)
{
assert(status.statusClass() == Status::CLASS_NOFAULT ||
status.statusClass() == Status::CLASS_JOB);
regs[RegAddr(JSn_STATUS)] = status.value;
if (status.statusClass() == Status::CLASS_NOFAULT) {
jc.jobDone(id);
} else {
jc.jobFailed(id);
}
}
void
JobSlot::jobCommand(uint32_t cmd)
{
if (cmd < cmds.size())
(this->*cmds[cmd])(cmd);
}
void
JobSlot::cmdNop(uint32_t cmd)
{
assert(cmd == JSn_COMMAND_NOP);
}
void
JobSlot::cmdStart(uint32_t cmd)
{
assert(cmd == JSn_COMMAND_START);
// The JSn_COMMAND_START should never be issued through the
// JSn_COMMAND register. It should use the JSn_COMMAND_NEXT
// register instead.
abort();
}
void
JobSlot::cmdSoftStop(uint32_t cmd)
{
assert(cmd == JSn_COMMAND_SOFT_STOP ||
cmd == JSn_COMMAND_SOFT_STOP_0 ||
cmd == JSn_COMMAND_SOFT_STOP_1);
}
void
JobSlot::cmdHardStop(uint32_t cmd)
{
assert(cmd == JSn_COMMAND_HARD_STOP ||
cmd == JSn_COMMAND_HARD_STOP_0 ||
cmd == JSn_COMMAND_HARD_STOP_1);
}
void
JobSlot::cmdSoftStop0(uint32_t cmd)
{
if (!(regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG))
cmdSoftStop(cmd);
}
void
JobSlot::cmdHardStop0(uint32_t cmd)
{
if (!(regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG))
cmdHardStop(cmd);
}
void
JobSlot::cmdSoftStop1(uint32_t cmd)
{
if (regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG)
cmdSoftStop(cmd);
}
void
JobSlot::cmdHardStop1(uint32_t cmd)
{
if (regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG)
cmdHardStop(cmd);
}
}

208
ext/nomali/lib/jobslot.hh Normal file
View file

@ -0,0 +1,208 @@
/*
* 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
*/
#ifndef _LIBNOMALIMODEL_JOBSLOT_HH
#define _LIBNOMALIMODEL_JOBSLOT_HH
#include <vector>
#include "gpublock.hh"
#include "types.hh"
namespace NoMali {
class GPU;
class JobControl;
/**
* Midgard job slot implementation.
*
* A job slot is a part of a JobControl block that controls the state
* of one out of 16 active jobs. Each slot can contain one running job
* and a pending job.
*/
class JobSlot
: public GPUBlock
{
public:
JobSlot(GPU &_gpu, JobControl &_jc, uint8_t slot_id);
JobSlot(JobSlot &&rhs);
virtual ~JobSlot();
void writeReg(RegAddr idx, uint32_t value) override;
/** Is there an active job in this job slot? */
bool active() const;
/** Is there a pending next job in this job slot? */
bool activeNext() const;
protected:
/**
* @{
* @name Job Control
*/
/**
* Try to start the next job in the slot.
*
* Start the next job if the following conditions are true:
* <ul>
* <li>There is no currently running job.
* <li>The pending command in the JSn_COMMAND_NEXT register is
* JSn_COMMAND_START.
* </ul>
*
* When the job is started, the registers describing the next job
* chain are moved (resetting them to zero) into the register
* block describing the currently running job. The job is then run
* by a call to runJob().
*/
void tryStart();
/**
* Execute the job in described by the current job registers.
*/
void runJob();
/**
* Report the exit status of an exiting job.
*
* @note The exit status must be of the class
* Status::CLASS_NOFAULT or Status::CLASS_JOB.
*
* @note The fault address isn't always a fault address, it is
* sometimes used to represent a TSC value. See the Midgard
* architecture specification for details.
*
* @param status Job exit status.
* @param fault_address Fault address to write into descriptor.
*/
void exitJob(Status status, uint64_t fault_address);
/** @} */
/**
* @{
* @name Job slot commands
*/
/**
* Control command dispatcher.
*
* This method is called whenever there is a write to the
* JSn_COMMAND register. The method uses a lookup table to call
* the right command handling method.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
void jobCommand(uint32_t cmd);
/**
* Command handler for No-ops.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
void cmdNop(uint32_t cmd);
/**
* Command handler for job start commands.
*
* @note This should <i>NEVER</i> be called as the start command
* should never be written to the JSn_COMMAND register. Jobs are
* normally started by tryStart() whenever the state of the
* currently running job changes or JSn_COMMAND_START is written
* to the JSn_COMMAND_NEXT register.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
void cmdStart(uint32_t cmd);
/**
* Gently stop the currently running job chain.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
void cmdSoftStop(uint32_t cmd);
/**
* Force a stop of the currently running job chain.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
void cmdHardStop(uint32_t cmd);
/**
* Soft stop the current job chain if the JOB_CHAIN_FLAG <i>IS
* NOT</i> set.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
void cmdSoftStop0(uint32_t cmd);
/**
* Hard stop the current job chain if the JOB_CHAIN_FLAG <i>IS
* NOT</i> set.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
void cmdHardStop0(uint32_t cmd);
/**
* Soft stop the current job chain if the JOB_CHAIN_FLAG <i>IS</i>
* set.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
void cmdSoftStop1(uint32_t cmd);
/**
* Hard stop the current job chain if the JOB_CHAIN_FLAG <i>IS</i>
* set.
*
* @param cmd Command number (see the Midgard architecture
* specification)
*/
void cmdHardStop1(uint32_t cmd);
/** @} */
/** Job slot ID */
const uint8_t id;
/** Parent JobControl block */
JobControl &jc;
private:
typedef void (JobSlot::*cmd_t)(uint32_t);
/**
* Mapping between command IDs and command handling methods.
*
* @note The order of this vector <i>MUST</i> correspond to the
* job control command IDs in the Midgard architecture
* specification.
*/
static const std::vector<cmd_t> cmds;
};
}
#endif // _LIBNOMALIMODEL_JOBSLOT_HH

View file

@ -0,0 +1,510 @@
/*
* 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.
*/
#ifndef _MIDGARD_REGMAP_H_
#define _MIDGARD_REGMAP_H_
/*
* Begin Register Offsets
*/
#define GPU_CONTROL_BASE 0x0000
#define GPU_CONTROL_REG(r) (GPU_CONTROL_BASE + (r))
#define GPU_ID 0x000 /* (RO) GPU and revision identifier */
#define L2_FEATURES 0x004 /* (RO) Level 2 cache features */
#define L3_FEATURES 0x008 /* (RO) Level 3 cache features */
#define TILER_FEATURES 0x00C /* (RO) Tiler Features */
#define MEM_FEATURES 0x010 /* (RO) Memory system features */
#define MMU_FEATURES 0x014 /* (RO) MMU features */
#define AS_PRESENT 0x018 /* (RO) Address space slots present */
#define JS_PRESENT 0x01C /* (RO) Job slots present */
#define GPU_IRQ_RAWSTAT 0x020 /* (RW) */
#define GPU_IRQ_CLEAR 0x024 /* (WO) */
#define GPU_IRQ_MASK 0x028 /* (RW) */
#define GPU_IRQ_STATUS 0x02C /* (RO) */
/* IRQ flags */
#define GPU_FAULT (1 << 0) /* A GPU Fault has occurred */
#define MULTIPLE_GPU_FAULTS (1 << 7) /* More than one GPU Fault occurred. */
#define RESET_COMPLETED (1 << 8) /* Set when a reset has completed. Intended to use with SOFT_RESET
commands which may take time. */
#define POWER_CHANGED_SINGLE (1 << 9) /* Set when a single core has finished powering up or down. */
#define POWER_CHANGED_ALL (1 << 10) /* Set when all cores have finished powering up or down
and the power manager is idle. */
#define PRFCNT_SAMPLE_COMPLETED (1 << 16) /* Set when a performance count sample has completed. */
#define CLEAN_CACHES_COMPLETED (1 << 17) /* Set when a cache clean operation has completed. */
#define GPU_IRQ_REG_ALL (GPU_FAULT | MULTIPLE_GPU_FAULTS | RESET_COMPLETED \
| POWER_CHANGED_ALL | PRFCNT_SAMPLE_COMPLETED)
#define GPU_COMMAND 0x030 /* (WO) */
#define GPU_STATUS 0x034 /* (RO) */
#define GROUPS_L2_COHERENT (1 << 0) /* Cores groups are l2 coherent */
#define GROUPS_L3_COHERENT (1 << 1) /* Cores groups are l3 coherent */
#define GPU_FAULTSTATUS 0x03C /* (RO) GPU exception type and fault status */
#define GPU_FAULTADDRESS_LO 0x040 /* (RO) GPU exception fault address, low word */
#define GPU_FAULTADDRESS_HI 0x044 /* (RO) GPU exception fault address, high word */
#define PWR_KEY 0x050 /* (WO) Power manager key register */
#define PWR_OVERRIDE0 0x054 /* (RW) Power manager override settings */
#define PWR_OVERRIDE1 0x058 /* (RW) Power manager override settings */
#define PRFCNT_BASE_LO 0x060 /* (RW) Performance counter memory region base address, low word */
#define PRFCNT_BASE_HI 0x064 /* (RW) Performance counter memory region base address, high word */
#define PRFCNT_CONFIG 0x068 /* (RW) Performance counter configuration */
#define PRFCNT_JM_EN 0x06C /* (RW) Performance counter enable flags for Job Manager */
#define PRFCNT_SHADER_EN 0x070 /* (RW) Performance counter enable flags for shader cores */
#define PRFCNT_TILER_EN 0x074 /* (RW) Performance counter enable flags for tiler */
#define PRFCNT_L3_CACHE_EN 0x078 /* (RW) Performance counter enable flags for L3 cache */
#define PRFCNT_MMU_L2_EN 0x07C /* (RW) Performance counter enable flags for MMU/L2 cache */
#define CYCLE_COUNT_LO 0x090 /* (RO) Cycle counter, low word */
#define CYCLE_COUNT_HI 0x094 /* (RO) Cycle counter, high word */
#define TIMESTAMP_LO 0x098 /* (RO) Global time stamp counter, low word */
#define TIMESTAMP_HI 0x09C /* (RO) Global time stamp counter, high word */
#define THREAD_MAX_THREADS 0x0A0 /* (RO) Maximum number of threads per core */
#define THREAD_MAX_WORKGROUP_SIZE 0x0A4 /* (RO) Maximum workgroup size */
#define THREAD_MAX_BARRIER_SIZE 0x0A8 /* (RO) Maximum threads waiting at a barrier */
#define THREAD_FEATURES 0x0AC /* (RO) Thread features */
#define TEXTURE_FEATURES_0 0x0B0 /* (RO) Support flags for indexed texture formats 0..31 */
#define TEXTURE_FEATURES_1 0x0B4 /* (RO) Support flags for indexed texture formats 32..63 */
#define TEXTURE_FEATURES_2 0x0B8 /* (RO) Support flags for indexed texture formats 64..95 */
#define TEXTURE_FEATURES_REG(n) GPU_CONTROL_REG(TEXTURE_FEATURES_0 + ((n) << 2))
#define JS0_FEATURES 0x0C0 /* (RO) Features of job slot 0 */
#define JS1_FEATURES 0x0C4 /* (RO) Features of job slot 1 */
#define JS2_FEATURES 0x0C8 /* (RO) Features of job slot 2 */
#define JS3_FEATURES 0x0CC /* (RO) Features of job slot 3 */
#define JS4_FEATURES 0x0D0 /* (RO) Features of job slot 4 */
#define JS5_FEATURES 0x0D4 /* (RO) Features of job slot 5 */
#define JS6_FEATURES 0x0D8 /* (RO) Features of job slot 6 */
#define JS7_FEATURES 0x0DC /* (RO) Features of job slot 7 */
#define JS8_FEATURES 0x0E0 /* (RO) Features of job slot 8 */
#define JS9_FEATURES 0x0E4 /* (RO) Features of job slot 9 */
#define JS10_FEATURES 0x0E8 /* (RO) Features of job slot 10 */
#define JS11_FEATURES 0x0EC /* (RO) Features of job slot 11 */
#define JS12_FEATURES 0x0F0 /* (RO) Features of job slot 12 */
#define JS13_FEATURES 0x0F4 /* (RO) Features of job slot 13 */
#define JS14_FEATURES 0x0F8 /* (RO) Features of job slot 14 */
#define JS15_FEATURES 0x0FC /* (RO) Features of job slot 15 */
#define JS_FEATURES_REG(n) GPU_CONTROL_REG(JS0_FEATURES + ((n) << 2))
#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */
#define SHADER_PRESENT_HI 0x104 /* (RO) Shader core present bitmap, high word */
#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */
#define TILER_PRESENT_HI 0x114 /* (RO) Tiler core present bitmap, high word */
#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */
#define L2_PRESENT_HI 0x124 /* (RO) Level 2 cache present bitmap, high word */
#define L3_PRESENT_LO 0x130 /* (RO) Level 3 cache present bitmap, low word */
#define L3_PRESENT_HI 0x134 /* (RO) Level 3 cache present bitmap, high word */
#define SHADER_READY_LO 0x140 /* (RO) Shader core ready bitmap, low word */
#define SHADER_READY_HI 0x144 /* (RO) Shader core ready bitmap, high word */
#define TILER_READY_LO 0x150 /* (RO) Tiler core ready bitmap, low word */
#define TILER_READY_HI 0x154 /* (RO) Tiler core ready bitmap, high word */
#define L2_READY_LO 0x160 /* (RO) Level 2 cache ready bitmap, low word */
#define L2_READY_HI 0x164 /* (RO) Level 2 cache ready bitmap, high word */
#define L3_READY_LO 0x170 /* (RO) Level 3 cache ready bitmap, low word */
#define L3_READY_HI 0x174 /* (RO) Level 3 cache ready bitmap, high word */
#define SHADER_PWRON_LO 0x180 /* (WO) Shader core power on bitmap, low word */
#define SHADER_PWRON_HI 0x184 /* (WO) Shader core power on bitmap, high word */
#define TILER_PWRON_LO 0x190 /* (WO) Tiler core power on bitmap, low word */
#define TILER_PWRON_HI 0x194 /* (WO) Tiler core power on bitmap, high word */
#define L2_PWRON_LO 0x1A0 /* (WO) Level 2 cache power on bitmap, low word */
#define L2_PWRON_HI 0x1A4 /* (WO) Level 2 cache power on bitmap, high word */
#define L3_PWRON_LO 0x1B0 /* (WO) Level 3 cache power on bitmap, low word */
#define L3_PWRON_HI 0x1B4 /* (WO) Level 3 cache power on bitmap, high word */
#define SHADER_PWROFF_LO 0x1C0 /* (WO) Shader core power off bitmap, low word */
#define SHADER_PWROFF_HI 0x1C4 /* (WO) Shader core power off bitmap, high word */
#define TILER_PWROFF_LO 0x1D0 /* (WO) Tiler core power off bitmap, low word */
#define TILER_PWROFF_HI 0x1D4 /* (WO) Tiler core power off bitmap, high word */
#define L2_PWROFF_LO 0x1E0 /* (WO) Level 2 cache power off bitmap, low word */
#define L2_PWROFF_HI 0x1E4 /* (WO) Level 2 cache power off bitmap, high word */
#define L3_PWROFF_LO 0x1F0 /* (WO) Level 3 cache power off bitmap, low word */
#define L3_PWROFF_HI 0x1F4 /* (WO) Level 3 cache power off bitmap, high word */
#define SHADER_PWRTRANS_LO 0x200 /* (RO) Shader core power transition bitmap, low word */
#define SHADER_PWRTRANS_HI 0x204 /* (RO) Shader core power transition bitmap, high word */
#define TILER_PWRTRANS_LO 0x210 /* (RO) Tiler core power transition bitmap, low word */
#define TILER_PWRTRANS_HI 0x214 /* (RO) Tiler core power transition bitmap, high word */
#define L2_PWRTRANS_LO 0x220 /* (RO) Level 2 cache power transition bitmap, low word */
#define L2_PWRTRANS_HI 0x224 /* (RO) Level 2 cache power transition bitmap, high word */
#define L3_PWRTRANS_LO 0x230 /* (RO) Level 3 cache power transition bitmap, low word */
#define L3_PWRTRANS_HI 0x234 /* (RO) Level 3 cache power transition bitmap, high word */
#define SHADER_PWRACTIVE_LO 0x240 /* (RO) Shader core active bitmap, low word */
#define SHADER_PWRACTIVE_HI 0x244 /* (RO) Shader core active bitmap, high word */
#define TILER_PWRACTIVE_LO 0x250 /* (RO) Tiler core active bitmap, low word */
#define TILER_PWRACTIVE_HI 0x254 /* (RO) Tiler core active bitmap, high word */
#define L2_PWRACTIVE_LO 0x260 /* (RO) Level 2 cache active bitmap, low word */
#define L2_PWRACTIVE_HI 0x264 /* (RO) Level 2 cache active bitmap, high word */
#define L3_PWRACTIVE_LO 0x270 /* (RO) Level 3 cache active bitmap, low word */
#define L3_PWRACTIVE_HI 0x274 /* (RO) Level 3 cache active bitmap, high word */
#define SHADER_CONFIG 0xF04 /* (RW) Shader core configuration settings (Mali-T60x additional register) */
#define L2_MMU_CONFIG 0xF0C /* (RW) Configuration of the L2 cache and MMU (Mali-T60x additional register) */
#define JOB_CONTROL_BASE 0x1000
#define JOB_CONTROL_REG(r) (JOB_CONTROL_BASE + (r))
#define JOB_IRQ_RAWSTAT 0x000 /* Raw interrupt status register */
#define JOB_IRQ_CLEAR 0x004 /* Interrupt clear register */
#define JOB_IRQ_MASK 0x008 /* Interrupt mask register */
#define JOB_IRQ_STATUS 0x00C /* Interrupt status register */
#define JOB_IRQ_JS_STATE 0x010 /* status==active and _next == busy snapshot from last JOB_IRQ_CLEAR */
#define JOB_IRQ_THROTTLE 0x014 /* cycles to delay delivering an interrupt externally. The JOB_IRQ_STATUS is NOT affected by this, just the delivery of the interrupt. */
#define JOB_SLOT0 0x800 /* Configuration registers for job slot 0 */
#define JOB_SLOT1 0x880 /* Configuration registers for job slot 1 */
#define JOB_SLOT2 0x900 /* Configuration registers for job slot 2 */
#define JOB_SLOT3 0x980 /* Configuration registers for job slot 3 */
#define JOB_SLOT4 0xA00 /* Configuration registers for job slot 4 */
#define JOB_SLOT5 0xA80 /* Configuration registers for job slot 5 */
#define JOB_SLOT6 0xB00 /* Configuration registers for job slot 6 */
#define JOB_SLOT7 0xB80 /* Configuration registers for job slot 7 */
#define JOB_SLOT8 0xC00 /* Configuration registers for job slot 8 */
#define JOB_SLOT9 0xC80 /* Configuration registers for job slot 9 */
#define JOB_SLOT10 0xD00 /* Configuration registers for job slot 10 */
#define JOB_SLOT11 0xD80 /* Configuration registers for job slot 11 */
#define JOB_SLOT12 0xE00 /* Configuration registers for job slot 12 */
#define JOB_SLOT13 0xE80 /* Configuration registers for job slot 13 */
#define JOB_SLOT14 0xF00 /* Configuration registers for job slot 14 */
#define JOB_SLOT15 0xF80 /* Configuration registers for job slot 15 */
#define JOB_SLOT_REG(n, r) (JOB_CONTROL_REG(JOB_SLOT0 + ((n) << 7)) + (r))
#define JSn_HEAD_LO 0x00 /* (RO) Job queue head pointer for job slot n, low word */
#define JSn_HEAD_HI 0x04 /* (RO) Job queue head pointer for job slot n, high word */
#define JSn_TAIL_LO 0x08 /* (RO) Job queue tail pointer for job slot n, low word */
#define JSn_TAIL_HI 0x0C /* (RO) Job queue tail pointer for job slot n, high word */
#define JSn_AFFINITY_LO 0x10 /* (RO) Core affinity mask for job slot n, low word */
#define JSn_AFFINITY_HI 0x14 /* (RO) Core affinity mask for job slot n, high word */
#define JSn_CONFIG 0x18 /* (RO) Configuration settings for job slot n */
#define JSn_COMMAND 0x20 /* (WO) Command register for job slot n */
#define JSn_STATUS 0x24 /* (RO) Status register for job slot n */
#define JSn_HEAD_NEXT_LO 0x40 /* (RW) Next job queue head pointer for job slot n, low word */
#define JSn_HEAD_NEXT_HI 0x44 /* (RW) Next job queue head pointer for job slot n, high word */
#define JSn_AFFINITY_NEXT_LO 0x50 /* (RW) Next core affinity mask for job slot n, low word */
#define JSn_AFFINITY_NEXT_HI 0x54 /* (RW) Next core affinity mask for job slot n, high word */
#define JSn_CONFIG_NEXT 0x58 /* (RW) Next configuration settings for job slot n */
#define JSn_COMMAND_NEXT 0x60 /* (RW) Next command register for job slot n */
#define MEMORY_MANAGEMENT_BASE 0x2000
#define MMU_REG(r) (MEMORY_MANAGEMENT_BASE + (r))
#define MMU_IRQ_RAWSTAT 0x000 /* (RW) Raw interrupt status register */
#define MMU_IRQ_CLEAR 0x004 /* (WO) Interrupt clear register */
#define MMU_IRQ_MASK 0x008 /* (RW) Interrupt mask register */
#define MMU_IRQ_STATUS 0x00C /* (RO) Interrupt status register */
#define MMU_AS0 0x400 /* Configuration registers for address space 0 */
#define MMU_AS1 0x440 /* Configuration registers for address space 1 */
#define MMU_AS2 0x480 /* Configuration registers for address space 2 */
#define MMU_AS3 0x4C0 /* Configuration registers for address space 3 */
#define MMU_AS4 0x500 /* Configuration registers for address space 4 */
#define MMU_AS5 0x540 /* Configuration registers for address space 5 */
#define MMU_AS6 0x580 /* Configuration registers for address space 6 */
#define MMU_AS7 0x5C0 /* Configuration registers for address space 7 */
#define MMU_AS8 0x600 /* Configuration registers for address space 8 */
#define MMU_AS9 0x640 /* Configuration registers for address space 9 */
#define MMU_AS10 0x680 /* Configuration registers for address space 10 */
#define MMU_AS11 0x6C0 /* Configuration registers for address space 11 */
#define MMU_AS12 0x700 /* Configuration registers for address space 12 */
#define MMU_AS13 0x740 /* Configuration registers for address space 13 */
#define MMU_AS14 0x780 /* Configuration registers for address space 14 */
#define MMU_AS15 0x7C0 /* Configuration registers for address space 15 */
#define MMU_AS_REG(n, r) (MMU_REG(MMU_AS0 + ((n) << 6)) + (r))
#define ASn_TRANSTAB_LO 0x00 /* (RW) Translation Table Base Address for address space n, low word */
#define ASn_TRANSTAB_HI 0x04 /* (RW) Translation Table Base Address for address space n, high word */
#define ASn_MEMATTR_LO 0x08 /* (RW) Memory attributes for address space n, low word. */
#define ASn_MEMATTR_HI 0x0C /* (RW) Memory attributes for address space n, high word. */
#define ASn_LOCKADDR_LO 0x10 /* (RW) Lock region address for address space n, low word */
#define ASn_LOCKADDR_HI 0x14 /* (RW) Lock region address for address space n, high word */
#define ASn_COMMAND 0x18 /* (WO) MMU command register for address space n */
#define ASn_FAULTSTATUS 0x1C /* (RO) MMU fault status register for address space n */
#define ASn_FAULTADDRESS_LO 0x20 /* (RO) Fault Address for address space n, low word */
#define ASn_FAULTADDRESS_HI 0x24 /* (RO) Fault Address for address space n, high word */
#define ASn_STATUS 0x28 /* (RO) Status flags for address space n */
/* End Register Offsets */
/*
* MMU_IRQ_RAWSTAT register values. Values are valid also for
MMU_IRQ_CLEAR, MMU_IRQ_MASK, MMU_IRQ_STATUS registers.
*/
#define MMU_REGS_PAGE_FAULT_FLAGS 16
/* Macros return bit number to retrvie page fault or bus eror flag from MMU registers */
#define MMU_REGS_PAGE_FAULT_FLAG(n) (n)
#define MMU_REGS_BUS_ERROR_FLAG(n) (n + MMU_REGS_PAGE_FAULT_FLAGS)
/*
* Begin MMU TRANSTAB register values
*/
#define ASn_TRANSTAB_ADDR_SPACE_MASK 0xfffff000
#define ASn_TRANSTAB_ADRMODE_UNMAPPED (0u << 0)
#define ASn_TRANSTAB_ADRMODE_IDENTITY (1u << 1)
#define ASn_TRANSTAB_ADRMODE_TABLE (3u << 0)
#define ASn_TRANSTAB_READ_INNER (1u << 2)
#define ASn_TRANSTAB_SHARE_OUTER (1u << 4)
#define MMU_TRANSTAB_ADRMODE_MASK 0x00000003
/*
* Begin MMU STATUS register values
*/
#define ASn_STATUS_FLUSH_ACTIVE 0x01
#define ASn_FAULTSTATUS_ACCESS_TYPE_MASK (0x3<<8)
#define ASn_FAULTSTATUS_ACCESS_TYPE_EX (0x1<<8)
#define ASn_FAULTSTATUS_ACCESS_TYPE_READ (0x2<<8)
#define ASn_FAULTSTATUS_ACCESS_TYPE_WRITE (0x3<<8)
/*
* Begin Command Values
*/
/* JSn_COMMAND register commands */
#define JSn_COMMAND_NOP 0x00 /* NOP Operation. Writing this value is ignored */
#define JSn_COMMAND_START 0x01 /* Start processing a job chain. Writing this value is ignored */
#define JSn_COMMAND_SOFT_STOP 0x02 /* Gently stop processing a job chain */
#define JSn_COMMAND_HARD_STOP 0x03 /* Rudely stop processing a job chain */
#define JSn_COMMAND_SOFT_STOP_0 0x04 /* Execute SOFT_STOP if JOB_CHAIN_FLAG is 0 */
#define JSn_COMMAND_HARD_STOP_0 0x05 /* Execute HARD_STOP if JOB_CHAIN_FLAG is 0 */
#define JSn_COMMAND_SOFT_STOP_1 0x06 /* Execute SOFT_STOP if JOB_CHAIN_FLAG is 1 */
#define JSn_COMMAND_HARD_STOP_1 0x07 /* Execute HARD_STOP if JOB_CHAIN_FLAG is 1 */
/* ASn_COMMAND register commands */
#define ASn_COMMAND_NOP 0x00 /* NOP Operation */
#define ASn_COMMAND_UPDATE 0x01 /* Broadcasts the values in ASn_TRANSTAB and ASn_MEMATTR to all MMUs */
#define ASn_COMMAND_LOCK 0x02 /* Issue a lock region command to all MMUs */
#define ASn_COMMAND_UNLOCK 0x03 /* Issue a flush region command to all MMUs */
#define ASn_COMMAND_FLUSH 0x04 /* Flush all L2 caches then issue a flush region command to all MMUs
(deprecated - only for use with T60x) */
#define ASn_COMMAND_FLUSH_PT 0x04 /* Flush all L2 caches then issue a flush region command to all MMUs */
#define ASn_COMMAND_FLUSH_MEM 0x05 /* Wait for memory accesses to complete, flush all the L1s cache then
flush all L2 caches then issue a flush region command to all MMUs */
/* Possible values of JSn_CONFIG and JSn_CONFIG_NEXT registers */
#define JSn_CONFIG_START_FLUSH_NO_ACTION (0u << 0)
#define JSn_CONFIG_START_FLUSH_CLEAN (1u << 8)
#define JSn_CONFIG_START_FLUSH_CLEAN_INVALIDATE (3u << 8)
#define JSn_CONFIG_START_MMU (1u << 10)
#define JSn_CONFIG_JOB_CHAIN_FLAG (1u << 11)
#define JSn_CONFIG_END_FLUSH_NO_ACTION JSn_CONFIG_START_FLUSH_NO_ACTION
#define JSn_CONFIG_END_FLUSH_CLEAN (1u << 12)
#define JSn_CONFIG_END_FLUSH_CLEAN_INVALIDATE (3u << 12)
#define JSn_CONFIG_THREAD_PRI(n) ((n) << 16)
/* JSn_STATUS register values */
/* NOTE: Please keep this values in sync with enum base_jd_event_code in mali_base_kernel.h.
* The values are separated to avoid dependency of userspace and kernel code.
*/
/* Group of values representing the job status insead a particular fault */
#define JSn_STATUS_NO_EXCEPTION_BASE 0x00
#define JSn_STATUS_INTERRUPTED (JSn_STATUS_NO_EXCEPTION_BASE + 0x02) /* 0x02 means INTERRUPTED */
#define JSn_STATUS_STOPPED (JSn_STATUS_NO_EXCEPTION_BASE + 0x03) /* 0x03 means STOPPED */
#define JSn_STATUS_TERMINATED (JSn_STATUS_NO_EXCEPTION_BASE + 0x04) /* 0x04 means TERMINATED */
/* General fault values */
#define JSn_STATUS_FAULT_BASE 0x40
#define JSn_STATUS_CONFIG_FAULT (JSn_STATUS_FAULT_BASE) /* 0x40 means CONFIG FAULT */
#define JSn_STATUS_POWER_FAULT (JSn_STATUS_FAULT_BASE + 0x01) /* 0x41 means POWER FAULT */
#define JSn_STATUS_READ_FAULT (JSn_STATUS_FAULT_BASE + 0x02) /* 0x42 means READ FAULT */
#define JSn_STATUS_WRITE_FAULT (JSn_STATUS_FAULT_BASE + 0x03) /* 0x43 means WRITE FAULT */
#define JSn_STATUS_AFFINITY_FAULT (JSn_STATUS_FAULT_BASE + 0x04) /* 0x44 means AFFINITY FAULT */
#define JSn_STATUS_BUS_FAULT (JSn_STATUS_FAULT_BASE + 0x08) /* 0x48 means BUS FAULT */
/* Instruction or data faults */
#define JSn_STATUS_INSTRUCTION_FAULT_BASE 0x50
#define JSn_STATUS_INSTR_INVALID_PC (JSn_STATUS_INSTRUCTION_FAULT_BASE) /* 0x50 means INSTR INVALID PC */
#define JSn_STATUS_INSTR_INVALID_ENC (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x01) /* 0x51 means INSTR INVALID ENC */
#define JSn_STATUS_INSTR_TYPE_MISMATCH (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x02) /* 0x52 means INSTR TYPE MISMATCH */
#define JSn_STATUS_INSTR_OPERAND_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x03) /* 0x53 means INSTR OPERAND FAULT */
#define JSn_STATUS_INSTR_TLS_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x04) /* 0x54 means INSTR TLS FAULT */
#define JSn_STATUS_INSTR_BARRIER_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x05) /* 0x55 means INSTR BARRIER FAULT */
#define JSn_STATUS_INSTR_ALIGN_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x06) /* 0x56 means INSTR ALIGN FAULT */
/* NOTE: No fault with 0x57 code defined in spec. */
#define JSn_STATUS_DATA_INVALID_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x08) /* 0x58 means DATA INVALID FAULT */
#define JSn_STATUS_TILE_RANGE_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x09) /* 0x59 means TILE RANGE FAULT */
#define JSn_STATUS_ADDRESS_RANGE_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x0A) /* 0x5A means ADDRESS RANGE FAULT */
/* Other faults */
#define JSn_STATUS_MEMORY_FAULT_BASE 0x60
#define JSn_STATUS_OUT_OF_MEMORY (JSn_STATUS_MEMORY_FAULT_BASE) /* 0x60 means OUT OF MEMORY */
#define JSn_STATUS_UNKNOWN 0x7F /* 0x7F means UNKNOWN */
/* GPU_COMMAND values */
#define GPU_COMMAND_NOP 0x00 /* No operation, nothing happens */
#define GPU_COMMAND_SOFT_RESET 0x01 /* Stop all external bus interfaces, and then reset the entire GPU. */
#define GPU_COMMAND_HARD_RESET 0x02 /* Immediately reset the entire GPU. */
#define GPU_COMMAND_PRFCNT_CLEAR 0x03 /* Clear all performance counters, setting them all to zero. */
#define GPU_COMMAND_PRFCNT_SAMPLE 0x04 /* Sample all performance counters, writing them out to memory */
#define GPU_COMMAND_CYCLE_COUNT_START 0x05 /* Starts the cycle counter, and system timestamp propagation */
#define GPU_COMMAND_CYCLE_COUNT_STOP 0x06 /* Stops the cycle counter, and system timestamp propagation */
#define GPU_COMMAND_CLEAN_CACHES 0x07 /* Clean all caches */
#define GPU_COMMAND_CLEAN_INV_CACHES 0x08 /* Clean and invalidate all caches */
/* End Command Values */
/* GPU_STATUS values */
#define GPU_STATUS_PRFCNT_ACTIVE (1 << 2) /* Set if the performance counters are active. */
/* PRFCNT_CONFIG register values */
#define PRFCNT_CONFIG_AS_SHIFT 4 /* address space bitmap starts from bit 4 of the register */
#define PRFCNT_CONFIG_MODE_OFF 0 /* The performance counters are disabled. */
#define PRFCNT_CONFIG_MODE_MANUAL 1 /* The performance counters are enabled, but are only written out when a PRFCNT_SAMPLE command is issued using the GPU_COMMAND register. */
#define PRFCNT_CONFIG_MODE_TILE 2 /* The performance counters are enabled, and are written out each time a tile finishes rendering. */
/* AS<n>_MEMATTR values: */
/* Use GPU implementation-defined caching policy. */
#define ASn_MEMATTR_IMPL_DEF_CACHE_POLICY 0x48
/* The attribute set to force all resources to be cached. */
#define ASn_MEMATTR_FORCE_TO_CACHE_ALL 0x4F
/* Inner write-alloc cache setup, no outer caching */
#define ASn_MEMATTR_WRITE_ALLOC 0x4D
/* symbol for default MEMATTR to use */
#define ASn_MEMATTR_INDEX_DEFAULT 0
/* HW implementation defined caching */
#define ASn_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY 0
/* Force cache on */
#define ASn_MEMATTR_INDEX_FORCE_TO_CACHE_ALL 1
/* Write-alloc inner */
#define ASn_MEMATTR_INDEX_WRITE_ALLOC 2
/* GPU_ID register */
#define GPU_ID_VERSION_STATUS_SHIFT 0
#define GPU_ID_VERSION_MINOR_SHIFT 4
#define GPU_ID_VERSION_MAJOR_SHIFT 12
#define GPU_ID_VERSION_PRODUCT_ID_SHIFT 16
#define GPU_ID_VERSION_STATUS (0xF << GPU_ID_VERSION_STATUS_SHIFT)
#define GPU_ID_VERSION_MINOR (0xFF << GPU_ID_VERSION_MINOR_SHIFT)
#define GPU_ID_VERSION_MAJOR (0xF << GPU_ID_VERSION_MAJOR_SHIFT)
#define GPU_ID_VERSION_PRODUCT_ID (0xFFFF << GPU_ID_VERSION_PRODUCT_ID_SHIFT)
/* Values for GPU_ID_VERSION_PRODUCT_ID bitfield */
#define GPU_ID_PI_T60X 0x6956
#define GPU_ID_PI_T62X 0x0620
#define GPU_ID_PI_T76X 0x0750
#define GPU_ID_PI_T72X 0x0720
/* Values for GPU_ID_VERSION_STATUS field for PRODUCT_ID GPU_ID_PI_T60X */
#define GPU_ID_S_15DEV0 0x1
#define GPU_ID_S_EAC 0x2
/* Helper macro to create a GPU_ID assuming valid values for id, major, minor, status */
#define GPU_ID_MAKE(id, major, minor, status) \
(((id) << GPU_ID_VERSION_PRODUCT_ID_SHIFT) | \
((major) << GPU_ID_VERSION_MAJOR_SHIFT) | \
((minor) << GPU_ID_VERSION_MINOR_SHIFT) | \
((status) << GPU_ID_VERSION_STATUS_SHIFT))
/* End GPU_ID register */
/* JS<n>_FEATURES register */
#define JSn_FEATURE_NULL_JOB (1u << 1)
#define JSn_FEATURE_SET_VALUE_JOB (1u << 2)
#define JSn_FEATURE_CACHE_FLUSH_JOB (1u << 3)
#define JSn_FEATURE_COMPUTE_JOB (1u << 4)
#define JSn_FEATURE_VERTEX_JOB (1u << 5)
#define JSn_FEATURE_GEOMETRY_JOB (1u << 6)
#define JSn_FEATURE_TILER_JOB (1u << 7)
#define JSn_FEATURE_FUSED_JOB (1u << 8)
#define JSn_FEATURE_FRAGMENT_JOB (1u << 9)
/* End JS<n>_FEATURES register */
/* L2_MMU_CONFIG register */
#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT (24)
#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT)
#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_OCTANT (0x1 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT)
#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_QUARTER (0x2 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT)
#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_HALF (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT)
#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT (26)
#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT)
#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_OCTANT (0x1 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT)
#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_QUARTER (0x2 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT)
#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_HALF (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT)
/* End L2_MMU_CONFIG register */
/* THREAD_* registers */
/* THREAD_FEATURES IMPLEMENTATION_TECHNOLOGY values */
#define IMPLEMENTATION_UNSPECIFIED 0
#define IMPLEMENTATION_SILICON 1
#define IMPLEMENTATION_FPGA 2
#define IMPLEMENTATION_MODEL 3
/* Default values when registers are not supported by the implemented hardware */
#define THREAD_MT_DEFAULT 256
#define THREAD_MWS_DEFAULT 256
#define THREAD_MBS_DEFAULT 256
#define THREAD_MR_DEFAULT 1024
#define THREAD_MTQ_DEFAULT 4
#define THREAD_MTGS_DEFAULT 10
/* End THREAD_* registers */
/* SHADER_CONFIG register */
#define SC_ALT_COUNTERS (1ul << 3)
#define SC_OVERRIDE_FWD_PIXEL_KILL (1ul << 4)
#define SC_SDC_DISABLE_OQ_DISCARD (1ul << 6)
#define SC_LS_PAUSEBUFFER_DISABLE (1ul << 16)
#define SC_ENABLE_TEXGRD_FLAGS (1ul << 25)
/* End SHADER_CONFIG register */
#endif /* _MIDGARD_REGMAP_H_ */

View file

@ -0,0 +1,92 @@
/*
* 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 "mali_midgard.hh"
#include "regutils.hh"
namespace NoMali {
MaliMidgard::MaliMidgard(unsigned gpuType,
unsigned major, unsigned minor, unsigned status)
: MaliMidgard(GPU_ID_MAKE(gpuType, major, minor, status))
{
}
MaliMidgard::MaliMidgard(uint32_t _gpuId)
: GPU(gpuControl, jobControl, mmu),
gpuControl(*this),
jobControl(*this),
mmu(*this),
gpuId(_gpuId)
{
}
MaliMidgard::~MaliMidgard()
{
}
void
MaliMidgard::setupControlIdRegisters(RegVector &regs)
{
regs[RegAddr(L2_FEATURES)] =
(0x07 << 24) | // lg2 ext bus width
(0x13 << 16) | // lg2 cache size
(0x02 << 8) | // lg2 associativity
(0x06); // lg2 line size
regs[RegAddr(TILER_FEATURES)] =
(0x8 << 8) | // Maximum no active hierarchy levels
0x09; // lg2 bin size
/* Coherent core group, but incoherent supergroup. 1 L2 slice. */
regs[RegAddr(MEM_FEATURES)] = 0x1;
regs[RegAddr(MMU_FEATURES)] = 0x2830;
regs[RegAddr(AS_PRESENT)] = 0xff;
regs[RegAddr(JS_PRESENT)] = 0x7;
regs[RegAddr(JS0_FEATURES)] = 0x20e;
regs[RegAddr(JS1_FEATURES)] = 0x1fe;
regs[RegAddr(JS2_FEATURES)] = 0x7e;
regs[RegAddr(TEXTURE_FEATURES_0)] = 0x00fe001e;
regs[RegAddr(TEXTURE_FEATURES_1)] = 0xffff;
regs[RegAddr(TEXTURE_FEATURES_2)] = 0x9f81ffff;
regs[RegAddr(THREAD_MAX_THREADS)] = 0x100;
regs[RegAddr(THREAD_MAX_WORKGROUP_SIZE)] = 0x100;
regs[RegAddr(THREAD_MAX_BARRIER_SIZE)] = 0x100;
regs[RegAddr(THREAD_FEATURES)] = 0x0a040400;
regs.set64(RegAddr(SHADER_PRESENT_LO), 0xf);
regs.set64(RegAddr(TILER_PRESENT_LO), 0x1);
regs.set64(RegAddr(L2_PRESENT_LO), 0x1);
}
void
MaliMidgard::GPUControlSpec::reset()
{
GPUControl::reset();
regs[RegAddr(GPU_ID)] = midgard.gpuId;
midgard.setupControlIdRegisters(regs);
}
};

View file

@ -0,0 +1,70 @@
/*
* 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
*/
#ifndef _LIBNOMALIMODEL_MALI_MIDGARD_HH
#define _LIBNOMALIMODEL_MALI_MIDGARD_HH
#include "gpu.hh"
#include "gpucontrol.hh"
#include "jobcontrol.hh"
#include "mmu.hh"
namespace NoMali {
/**
* Base class for Midgard based GPUs
*/
class MaliMidgard
: public GPU
{
public:
MaliMidgard(unsigned gpuType,
unsigned major, unsigned minor, unsigned status);
MaliMidgard(uint32_t gpuId);
virtual ~MaliMidgard();
protected:
class GPUControlSpec
: public GPUControl
{
public:
GPUControlSpec(MaliMidgard &_gpu)
: GPUControl(_gpu), midgard(_gpu) {}
void reset() override;
private:
MaliMidgard &midgard;
};
virtual void setupControlIdRegisters(RegVector &regs);
GPUControlSpec gpuControl;
JobControl jobControl;
MMU mmu;
private:
const uint32_t gpuId;
};
}
#endif // _LIBNOMALIMODEL_MALI_MIDGARD_HH

View file

@ -0,0 +1,55 @@
/*
* 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 "mali_t6xx.hh"
#include "regutils.hh"
namespace NoMali {
MaliT6xxBase::MaliT6xxBase(unsigned gpuType,
unsigned major, unsigned minor, unsigned status)
: MaliMidgard(gpuType, major, minor, status)
{
}
void
MaliT6xxBase::setupControlIdRegisters(RegVector &regs)
{
MaliMidgard::setupControlIdRegisters(regs);
regs[RegAddr(L2_FEATURES)] =
(0x06 << 24) | // lg2 ext bus width
(0x10 << 16) | // lg2 cache size
(0x02 << 8) | // lg2 associativity
(0x06); // lg2 line size
}
MaliT60x::MaliT60x(unsigned major, unsigned minor, unsigned status)
: MaliT6xxBase(GPU_ID_PI_T60X, major, minor, status)
{
}
MaliT62x::MaliT62x(unsigned major, unsigned minor, unsigned status)
: MaliT6xxBase(GPU_ID_PI_T62X, major, minor, status)
{
}
};

View file

@ -0,0 +1,61 @@
/*
* 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
*/
#ifndef _LIBNOMALIMODEL_MALI_T7XX_HH
#define _LIBNOMALIMODEL_MALI_T7XX_HH
#include "mali_midgard.hh"
namespace NoMali {
class MaliT6xxBase
: public MaliMidgard
{
public:
MaliT6xxBase(unsigned gpuType,
unsigned major, unsigned minor, unsigned status);
protected:
void setupControlIdRegisters(RegVector &regs) override;
};
/**
* Simple NoMali implementation of the Mali T60x
*/
class MaliT60x
: public MaliT6xxBase
{
public:
MaliT60x(unsigned major, unsigned minor, unsigned status);
};
/**
* Simple NoMali implementation of the Mali T62x
*/
class MaliT62x
: public MaliT6xxBase
{
public:
MaliT62x(unsigned major, unsigned minor, unsigned status);
};
}
#endif // _LIBNOMALIMODEL_MALI_T7XX_HH

View file

@ -0,0 +1,50 @@
/*
* 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 "mali_t7xx.hh"
#include "regutils.hh"
namespace NoMali {
MaliT7xxBase::MaliT7xxBase(unsigned gpuType,
unsigned major, unsigned minor, unsigned status)
: MaliMidgard(gpuType, major, minor, status)
{
}
void
MaliT7xxBase::setupControlIdRegisters(RegVector &regs)
{
MaliMidgard::setupControlIdRegisters(regs);
regs[RegAddr(L2_FEATURES)] =
(0x07 << 24) | // lg2 ext bus width
(0x13 << 16) | // lg2 cache size
(0x02 << 8) | // lg2 associativity
(0x06); // lg2 line size
}
MaliT76x::MaliT76x(unsigned major, unsigned minor, unsigned status)
: MaliT7xxBase(GPU_ID_PI_T76X, major, minor, status)
{
}
};

View file

@ -0,0 +1,50 @@
/*
* 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
*/
#ifndef _LIBNOMALIMODEL_MALIT_T7XX_HH
#define _LIBNOMALIMODEL_MALIT_T7XX_HH
#include "mali_midgard.hh"
namespace NoMali {
class MaliT7xxBase
: public MaliMidgard
{
public:
MaliT7xxBase(unsigned gpuType,
unsigned major, unsigned minor, unsigned status);
protected:
void setupControlIdRegisters(RegVector &regs) override;
};
/**
* Simple NoMali implementation of the Mali T76x
*/
class MaliT76x
: public MaliT7xxBase
{
public:
MaliT76x(unsigned major, unsigned minor, unsigned status);
};
}
#endif // _LIBNOMALIMODEL_MALI_T7XX_HH

64
ext/nomali/lib/mmu.cc Normal file
View file

@ -0,0 +1,64 @@
/*
* 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 "mmu.hh"
#include "gpu.hh"
#include "regutils.hh"
namespace NoMali {
MMU::MMU(GPU &_gpu)
: GPUBlockInt(_gpu,
RegAddr(MMU_IRQ_RAWSTAT),
RegAddr(MMU_IRQ_CLEAR),
RegAddr(MMU_IRQ_MASK),
RegAddr(MMU_IRQ_STATUS)),
regs(BLOCK_NUM_REGS)
{
}
MMU::~MMU()
{
}
void
MMU::writeReg(RegAddr addr, uint32_t value)
{
switch (addr.value) {
case MMU_IRQ_RAWSTAT:
case MMU_IRQ_CLEAR:
case MMU_IRQ_MASK:
case MMU_IRQ_STATUS:
GPUBlockInt::writeReg(addr, value);
break;
default:
// Ignore writes by default
break;
};
}
void
MMU::onInterrupt(int set)
{
gpu.intMMU(set);
}
}

57
ext/nomali/lib/mmu.hh Normal file
View file

@ -0,0 +1,57 @@
/*
* 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
*/
#ifndef _LIBNOMALIMODEL_MMU_HH
#define _LIBNOMALIMODEL_MMU_HH
#include <vector>
#include "gpublock.hh"
#include "types.hh"
namespace NoMali {
class GPU;
/**
* MMU dummy implementation.
*
* This is a dummy implementation of a Midgard GPU MMU block. The only
* features supported by the block is interrupt delivery and registers
* related to interrupt delivery. Writes to unimplemented registers
* (most registers) are discarded and their values are read as zero.
*/
class MMU
: public GPUBlockInt
{
public:
MMU(GPU &_gpu);
virtual ~MMU();
void writeReg(RegAddr idx, uint32_t value) override;
protected:
void onInterrupt(int set) override;
RegVector regs;
};
}
#endif // _LIBNOMALIMODEL_MMU_HH

View file

@ -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;
}

103
ext/nomali/lib/regutils.hh Normal file
View file

@ -0,0 +1,103 @@
/*
* 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
*/
#ifndef _LIBNOMALIMODEL_REGUTILS_HH
#define _LIBNOMALIMODEL_REGUTILS_HH
#include <cassert>
#include "types.hh"
#include "mali_midg_regmap.h"
namespace NoMali {
/** Size of a function block in bytes */
static const uint32_t BLOCK_REGS_SIZE(0x1000);
/** Number of registers in a function block */
static const uint32_t BLOCK_NUM_REGS = BLOCK_REGS_SIZE >> 2;
/**
* Register blocks within the GPU.
*
* The GPU splits its register space into chunks belonging to specific
* blocks. This enum lists those blocks.
*/
enum class RegBlock : uint16_t {
GPU = 0x0,
JOB = 0x1,
MMU = 0x2,
UNKNOWN = 0xFFFF,
};
/** Get the register block from a GPU register address */
static inline RegBlock
getRegBlock(RegAddr addr)
{
return RegBlock(addr.value >> 12);
}
/**
* Get the register address within a GPU block.
*
* This method masks away the block offset from a GPU register
* address. The resulting address is the address <i>within</i> a
* function block.
*/
static inline RegAddr
getBlockReg(RegAddr addr)
{
static_assert((BLOCK_REGS_SIZE & (BLOCK_REGS_SIZE - 1)) == 0,
"BLOCK_REGS_SIZE is not a power of 2");
return RegAddr(addr.value & (BLOCK_REGS_SIZE - 1));
}
/**
* Get the slot number owning an address within the JobControl block.
*
* @param Address relative to the JobControl block.
*/
static inline unsigned
getJobSlotNo(const RegAddr &addr)
{
assert(addr.value >= JOB_SLOT0);
assert(addr.value <= 0xFFF);
return (addr.value - JOB_SLOT0) >> 7;
}
/**
* Get a JobSlot-relative address from a JobControl-relative address.
*
* @param Address relative to the JobControl block.
* @return Address relative the start of the JobSlot.
*/
static inline RegAddr
getJobSlotAddr(const RegAddr &addr)
{
const unsigned slot_no(getJobSlotNo(addr));
const RegAddr slot_base(RegAddr(JOB_SLOT0 + slot_no * 0x80));
return addr - slot_base;
}
/** Number of registers per job slot */
static const unsigned JSn_NO_REGS = 0x20;
}
#endif //_LIBNOMALIMODEL_REGUTILS_HH

218
ext/nomali/lib/types.hh Normal file
View file

@ -0,0 +1,218 @@
/*
* 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
*/
#ifndef _LIBNOMALIMODEL_TYPES_HH
#define _LIBNOMALIMODEL_TYPES_HH
#include <cassert>
#include <cstdint>
#include <utility>
#include <vector>
namespace NoMali{
/**
* @{
* @name Register handling utilities
*/
/**
* Register address wrapper
*
* This class wraps a register address. Unlike a simple typedef, this
* provides safety from automatic type conversions from other integer
* types since the constructor must be called explicitly.
*/
struct RegAddr {
explicit RegAddr(uint32_t v)
: value(v) {}
const uint32_t value;
};
inline bool
operator<(const RegAddr &lhs, const RegAddr &rhs) {
return lhs.value < rhs.value;
}
inline bool
operator>(const RegAddr &lhs, const RegAddr &rhs) {
return lhs.value > rhs.value;
}
inline bool
operator<=(const RegAddr &lhs, const RegAddr &rhs) {
return lhs.value <= rhs.value;
}
inline bool
operator>=(const RegAddr &lhs, const RegAddr &rhs) {
return lhs.value >= rhs.value;
}
inline bool
operator==(const RegAddr &lhs, const RegAddr &rhs) {
return lhs.value == rhs.value;
}
inline bool
operator!=(const RegAddr &lhs, const RegAddr &rhs) {
return lhs.value != rhs.value;
}
inline RegAddr
operator+(const RegAddr &lhs, const RegAddr &rhs) {
return RegAddr(lhs.value + rhs.value);
}
inline RegAddr
operator-(const RegAddr &lhs, const RegAddr &rhs) {
assert(lhs >= rhs);
return RegAddr(lhs.value - rhs.value);
}
/**
* Class for register storage
*
* This class wraps a std::vector and implements a subset of its
* functionality. Specifically, it is constant size and prevents
* indexing with anything other than RegAddr instances.
*/
class RegVector
{
private:
typedef std::vector<uint32_t> vector_t;
public:
typedef vector_t::iterator iterator;
typedef vector_t::const_iterator const_iterator;
typedef vector_t::size_type size_type;
public:
RegVector(size_type size)
: vector(size, 0) {}
/** @{ */
/**
* Helper function to get a 64-bit register.
*
* @param addr Address to the low part of the register.
* @return 64-bit value representing the concatenation of the HI
* and LO parts of the register.
*/
const uint32_t get64(const RegAddr &addr) const {
const unsigned idx_lo = index(addr);
const unsigned idx_hi = idx_lo + 1;
return (((uint64_t)vector[idx_hi]) << 32) | vector[idx_lo];
}
/**
* Helper function to set a 64-bit register.
*
* @param addr Address to the low part of the register.
* @param value Value to write into the 64-bit register.
*/
void set64(const RegAddr &addr, uint64_t value) {
const unsigned idx_lo = index(addr);
const unsigned idx_hi = idx_lo + 1;
vector[idx_lo] = value & 0xFFFFFFFF;
vector[idx_hi] = (value >> 32) & 0xFFFFFFFF;
}
const uint32_t &operator[](const RegAddr &addr) const {
return vector[index(addr)];
}
uint32_t &operator[](const RegAddr &addr) {
return vector[index(addr)];
}
iterator begin() noexcept { return vector.begin(); }
const_iterator begin() const noexcept { return vector.begin(); }
const_iterator cbegin() const noexcept { return vector.cbegin(); }
iterator end() noexcept { return vector.end(); }
const_iterator end() const noexcept { return vector.end(); }
const_iterator cend() const noexcept { return vector.cend(); }
const size_type size() const noexcept { return vector.size(); }
private:
// Disable default constructor
RegVector();
static uint32_t index(const RegAddr &addr) {
assert((addr.value & 0x3) == 0);
return addr.value >> 2;
}
vector_t vector;
};
/** @} */
/**
* Class representing the status codes in the Midgard architecture.
*/
struct Status {
/**
* Class representing the subsystem a status code originates from.
*/
enum StatusClass {
CLASS_NOFAULT = 0,
CLASS_JOB = 1,
CLASS_GPU = 2,
CLASS_MMU = 3,
};
typedef uint8_t Code;
typedef uint8_t SubCode;
Status(StatusClass cls, Code code, SubCode subcode)
: value((cls << 6) | (code << 3) | subcode) {
assert((cls & ~0x3) == 0);
assert((code & ~0x7) == 0);
assert((subcode & ~0x7) == 0);
}
explicit Status(uint8_t v)
: value(v) {}
StatusClass statusClass() const {
return (StatusClass)((value >> 6) & 0x3);
}
Code code() const {
return (value >> 3) & 0x7;
}
SubCode subCode() const {
return value & 0x7;
}
const uint8_t value;
};
}
#endif

44
ext/nomali/tests/Rules.mk Normal file
View file

@ -0,0 +1,44 @@
#
# 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
sp := $(sp).x
dirstack_$(sp) := $(d)
d := $(dir)
HELPER_OBJS := $(addprefix $(d)/, \
test_helpers.o \
)
TESTS := $(addprefix $(d)/nomali_, \
test0 \
test_ints \
)
OBJS := $(HELPER_OBJS) $(addsuffix .o, $(TESTS))
ALL_TESTS := $(ALL_TESTS) $(TESTS)
DEPS := $(DEPS) $(OBJS:.o=.d)
CLEAN := $(CLEAN) $(OBJS) $(TESTS)
include Rules.app.mk
$(d)/nomali_%: $(d)/nomali_%.o $(d)/test_helpers.o libnomali.so
$(CXX) $(LDFLAGS) -Wl,-rpath -Wl,"$(CURDIR)" -o $@ $^
d := $(dirstack_$(sp))
sp := $(basename $(sp))

View file

@ -0,0 +1,53 @@
/*
* 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 <inttypes.h>
#include "nomali_test_helpers.h"
#include "../lib/mali_midg_regmap.h"
int
main(int argc, char **argv)
{
const nomali_config_t cfg = {
.type = NOMALI_GPU_T60X,
.ver_maj = 0,
.ver_min = 1,
.ver_status = 0,
};
nomali_handle_t h;
nomali_error_t error = NOMALI_E_OK;
uint32_t value;
E_NOMALI_TEST("nomali_create", nomali_create(&h, &cfg));
if (error != NOMALI_E_OK)
test_bail("Failed to create NoMail instance!");
E_NOMALI_TEST("reg_read(GPU_ID)",
nomali_reg_read(h, &value, GPU_CONTROL_REG(GPU_ID)));
if (value != ((GPU_ID_PI_T60X << 16) | 0x10)) {
test_fail("GPU_ID");
} else
test_ok("GPU_ID");
E_NOMALI_TEST("nomali_destroy", nomali_destroy(h));
return 0;
}

View file

@ -0,0 +1,46 @@
/*
* 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
*/
#ifndef _TESTS_NOMALI_TEST_HELPERS_H
#define _TESTS_NOMALI_TEST_HELPERS_H
#include <libnomali/nomali.h>
#include "test_helpers.h"
#define E_NOMALI_BAIL(c) \
do { \
if ((error = (c)) != NOMALI_E_OK) { \
test_bail(# c " failed: %s (%i)", \
nomali_errstr(error), error); \
} \
} while (0)
#define E_NOMALI_TEST(t, c) \
do { \
if ((error = (c)) != NOMALI_E_OK) { \
test_diag(# c " failed: %s (%i)", \
nomali_errstr(error), error); \
test_fail(t); \
} else { \
test_ok(t); \
} \
} while (0)
#endif /* _TESTS_NOMALI_TEST_HELPERS_H */

View file

@ -0,0 +1,127 @@
/*
* 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 <inttypes.h>
#include "nomali_test_helpers.h"
#include "../lib/mali_midg_regmap.h"
static void
on_int(nomali_handle_t h, void *usr, nomali_int_t intno, int set)
{
test_diag("on_int: intno: %i, set: %i", intno, set);
*(int*)usr = !!set;
}
static void
test_gpu_int(nomali_handle_t h)
{
nomali_error_t error = NOMALI_E_OK;
int int_triggered = 0;
nomali_callback_t int_callback = {
.type = NOMALI_CALLBACK_INT,
.usr = &int_triggered,
.func.interrupt = on_int,
};
nomali_callback_t int_null_callback = {
.type = NOMALI_CALLBACK_INT,
.usr = NULL,
.func.interrupt = NULL,
};
/*
* Raise an interrupt without callbacks
*/
E_NOMALI_BAIL(nomali_reg_write(h,
GPU_CONTROL_REG(GPU_IRQ_CLEAR),
GPU_IRQ_REG_ALL));
E_NOMALI_BAIL(nomali_reg_write(h, GPU_CONTROL_REG(GPU_IRQ_MASK),
GPU_FAULT));
E_NOMALI_BAIL(nomali_reg_write(h, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT),
GPU_FAULT));
E_NOMALI_BAIL(nomali_reg_write(h,
GPU_CONTROL_REG(GPU_IRQ_CLEAR),
GPU_IRQ_REG_ALL));
/*
* Register callbacks and raise interrupt again.
*/
E_NOMALI_BAIL(nomali_set_callback(h, &int_callback));
if (int_triggered != 0) {
test_diag("Got spurious interrupt\n");
test_fail("gpu_int");
}
E_NOMALI_BAIL(nomali_reg_write(h, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT),
GPU_FAULT));
if (int_triggered == 1) {
test_ok("gpu_int");
} else {
test_fail("gpu_int");
}
int_triggered = 0;
/*
* Register mask interrupts and raise interrupt again.
*/
E_NOMALI_BAIL(nomali_reg_write(h,
GPU_CONTROL_REG(GPU_IRQ_CLEAR),
GPU_IRQ_REG_ALL));
E_NOMALI_BAIL(nomali_reg_write(h, GPU_CONTROL_REG(GPU_IRQ_MASK),
0));
E_NOMALI_BAIL(nomali_reg_write(h, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT),
GPU_FAULT));
if (int_triggered == 0) {
test_ok("gpu_int_masked");
} else {
test_fail("gpu_int_maked");
}
E_NOMALI_BAIL(nomali_reg_write(h,
GPU_CONTROL_REG(GPU_IRQ_CLEAR),
GPU_IRQ_REG_ALL));
E_NOMALI_BAIL(nomali_set_callback(h, &int_null_callback));
}
int
main(int argc, char **argv)
{
const nomali_config_t cfg = {
.type = NOMALI_GPU_T60X,
.ver_maj = 0,
.ver_min = 1,
.ver_status = 0,
};
nomali_handle_t h;
nomali_error_t error = NOMALI_E_OK;
E_NOMALI_BAIL(nomali_create(&h, &cfg));
test_gpu_int(h);
E_NOMALI_BAIL(nomali_destroy(h));
return 0;
}

View file

@ -0,0 +1,147 @@
/*
* Copyright (c) 2013 Andreas Sandberg
* 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 "test_helpers.h"
#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
unsigned test_current = 0;
unsigned test_count = 0;
unsigned test_fail_count = 0;
void
test_init(unsigned no_tests)
{
assert(test_count == 0 && test_current == 0);
test_count = no_tests;
test_current = 1;
test_fail_count = 0;
printf("1..%u\n", no_tests);
}
void
test_exit()
{
if (test_fail_count)
exit(EXIT_FAILURE);
else
exit(EXIT_SUCCESS);
}
void
test_bail(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
printf("Bail out! ");
vprintf(fmt, ap);
printf("\n");
va_end(ap);
exit(EXIT_FAILURE);
}
void
test_diag(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
printf("# ");
vprintf(fmt, ap);
printf("\n");
va_end(ap);
}
static void
test_vstatus(const char *status, const char *test,
const char *directive,
const char *fmt_why, va_list ap)
{
printf("%s %i", status, test_current);
if (test && test[0] != '\0')
printf(" - %s", test);
if (directive && directive[0] != '\0') {
printf(" # %s ", directive);
if (fmt_why && fmt_why[0] != '\0')
vprintf(fmt_why, ap);
}
printf("\n");
++test_current;
}
static void __attribute__((format (printf, 4, 5)))
test_status(const char *status, const char *test,
const char *directive,
const char *fmt_why, ...)
{
va_list ap;
va_start(ap, fmt_why);
test_vstatus(status, test, directive, fmt_why, ap);
va_end(ap);
}
void
test_ok(const char *test)
{
test_status("ok", test, NULL, NULL);
}
void
test_fail(const char *test)
{
test_status("not ok", test, NULL, NULL);
++test_fail_count;
}
void
test_skip(const char *test, const char *fmt_why, ...)
{
va_list ap;
va_start(ap, fmt_why);
test_vstatus("ok", test, "SKIP", fmt_why, ap);
va_end(ap);
}
void
test_todo(const char *test, const char *fmt_why, ...)
{
va_list ap;
va_start(ap, fmt_why);
test_vstatus("not ok", test, "TODO", fmt_why, ap);
va_end(ap);
++test_fail_count;
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2013 Andreas Sandberg
* 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
*/
#ifndef _TEST_HELPERS
#define _TEST_HELPERS 1
#include <stdio.h>
#ifdef __cplusplus
#extern "C" {
#endif
extern unsigned test_current;
extern unsigned test_count;
extern unsigned test_fail_count;
void test_init(unsigned no_tests);
void test_exit()
__attribute__((noreturn));
void test_bail(const char *fmt, ...)
__attribute__((format (printf, 1, 2), noreturn));
void test_diag(const char *fmt, ...)
__attribute__((format (printf, 1, 2)));
void test_ok(const char *test);
void test_fail(const char *test);
void test_skip(const char *test, const char *fmt_why, ...)
__attribute__((format (printf, 2, 3)));
void test_todo(const char *test, const char *fmt_why, ...)
__attribute__((format (printf, 2, 3)));
#ifdef __cplusplus
}
#endif
#endif