1/*
2 * Copyright (c) 2014-2015 ARM Limited
3 * All rights reserved
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * Authors: Andreas Sandberg
18 */
19
20#ifndef _LIBNOMALIMODEL_TYPES_HH
21#define _LIBNOMALIMODEL_TYPES_HH
22
23#include <cassert>
24#include <cstdint>
25
26#include <utility>
27#include <vector>
28
29namespace NoMali{
30
31/**
32 * @{
33 * @name Register handling utilities
34 */
35
36/**
37 * Register address wrapper
38 *
39 * This class wraps a register address. Unlike a simple typedef, this
40 * provides safety from automatic type conversions from other integer
41 * types since the constructor must be called explicitly.
42 */
43struct RegAddr {
44    explicit RegAddr(uint32_t v)
45        : value(v) {}
46
47    const uint32_t value;
48};
49
50inline bool
51operator<(const RegAddr &lhs, const RegAddr &rhs) {
52    return lhs.value < rhs.value;
53}
54
55inline bool
56operator>(const RegAddr &lhs, const RegAddr &rhs) {
57    return lhs.value > rhs.value;
58}
59
60inline bool
61operator<=(const RegAddr &lhs, const RegAddr &rhs) {
62    return lhs.value <= rhs.value;
63}
64
65inline bool
66operator>=(const RegAddr &lhs, const RegAddr &rhs) {
67    return lhs.value >= rhs.value;
68}
69
70inline bool
71operator==(const RegAddr &lhs, const RegAddr &rhs) {
72    return lhs.value == rhs.value;
73}
74
75inline bool
76operator!=(const RegAddr &lhs, const RegAddr &rhs) {
77    return lhs.value != rhs.value;
78}
79
80inline RegAddr
81operator+(const RegAddr &lhs, const RegAddr &rhs) {
82    return RegAddr(lhs.value + rhs.value);
83}
84
85inline RegAddr
86operator-(const RegAddr &lhs, const RegAddr &rhs) {
87    assert(lhs >= rhs);
88    return RegAddr(lhs.value - rhs.value);
89}
90
91/**
92 * Class for register storage
93 *
94 * This class wraps a std::vector and implements a subset of its
95 * functionality. Specifically, it is constant size and prevents
96 * indexing with anything other than RegAddr instances.
97 */
98class RegVector
99{
100  private:
101    typedef std::vector<uint32_t> vector_t;
102
103  public:
104    typedef vector_t::iterator iterator;
105    typedef vector_t::const_iterator const_iterator;
106    typedef vector_t::size_type size_type;
107
108  public:
109    RegVector(size_type size)
110        : vector(size, 0) {}
111
112    /** @{ */
113    /**
114     * Helper function to get a 64-bit register.
115     *
116     * @param addr Address to the low part of the register.
117     * @return 64-bit value representing the concatenation of the HI
118     * and LO parts of the register.
119     */
120    const uint32_t get64(const RegAddr &addr) const {
121        const unsigned idx_lo = index(addr);
122        const unsigned idx_hi = idx_lo + 1;
123        return (((uint64_t)vector[idx_hi]) << 32) | vector[idx_lo];
124    }
125
126    /**
127     * Helper function to set a 64-bit register.
128     *
129     * @param addr Address to the low part of the register.
130     * @param value Value to write into the 64-bit register.
131     */
132    void set64(const RegAddr &addr, uint64_t value) {
133        const unsigned idx_lo = index(addr);
134        const unsigned idx_hi = idx_lo + 1;
135        vector[idx_lo] = value & 0xFFFFFFFF;
136        vector[idx_hi] = (value >> 32) & 0xFFFFFFFF;
137    }
138
139    const uint32_t &operator[](const RegAddr &addr) const {
140        return vector[index(addr)];
141    }
142
143    uint32_t &operator[](const RegAddr &addr) {
144        return vector[index(addr)];
145    }
146
147
148    iterator begin() noexcept { return vector.begin(); }
149    const_iterator begin() const noexcept { return vector.begin(); }
150    const_iterator cbegin() const noexcept { return vector.cbegin(); }
151
152    iterator end() noexcept { return vector.end(); }
153    const_iterator end() const noexcept { return vector.end(); }
154    const_iterator cend() const noexcept { return vector.cend(); }
155
156    const size_type size() const noexcept { return vector.size(); }
157
158  private:
159    // Disable default constructor
160    RegVector();
161
162    static uint32_t index(const RegAddr &addr) {
163        assert((addr.value & 0x3) == 0);
164        return addr.value >> 2;
165    }
166
167
168    vector_t vector;
169};
170/** @} */
171
172/**
173 * Class representing the status codes in the Midgard architecture.
174 */
175struct Status {
176    /**
177     * Class representing the subsystem a status code originates from.
178     */
179    enum StatusClass {
180        CLASS_NOFAULT = 0,
181        CLASS_JOB = 1,
182        CLASS_GPU = 2,
183        CLASS_MMU = 3,
184    };
185
186    typedef uint8_t Code;
187    typedef uint8_t SubCode;
188
189    Status(StatusClass cls, Code code, SubCode subcode)
190        : value((cls << 6) | (code << 3) | subcode) {
191        assert((cls & ~0x3) == 0);
192        assert((code & ~0x7) == 0);
193        assert((subcode & ~0x7) == 0);
194    }
195
196    explicit Status(uint8_t v)
197        : value(v) {}
198
199    StatusClass statusClass() const {
200        return (StatusClass)((value >> 6) & 0x3);
201    }
202
203    Code code() const {
204        return (value >> 3) & 0x7;
205    }
206
207    SubCode subCode() const {
208        return value & 0x7;
209    }
210
211    const uint8_t value;
212};
213
214
215}
216
217#endif
218
219