summaryrefslogtreecommitdiff
path: root/ext/nomali/lib/gpublock.hh
blob: 330ffcb7cea2f0a5d488fb1daeaf401c9a34295e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
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