jobcontrol.cc revision 10915:71ace17ccb3d
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#include "jobcontrol.hh"
21
22#include "gpu.hh"
23#include "regutils.hh"
24
25namespace NoMali {
26
27JobControl::JobControl(GPU &_gpu)
28    : GPUBlockInt(_gpu,
29                  RegAddr(JOB_IRQ_RAWSTAT),
30                  RegAddr(JOB_IRQ_CLEAR),
31                  RegAddr(JOB_IRQ_MASK),
32                  RegAddr(JOB_IRQ_STATUS))
33{
34    slots.reserve(16);
35    for (int i = 0; i < 16; ++i)
36        slots.emplace_back(_gpu, *this, i);
37
38}
39
40JobControl::~JobControl()
41{
42}
43
44uint32_t
45JobControl::readReg(RegAddr addr)
46{
47    if (addr >= RegAddr(JOB_SLOT0)) {
48        return slots[getJobSlotNo(addr)].readReg(getJobSlotAddr(addr));
49    } else {
50        return GPUBlockInt::readReg(addr);
51    }
52}
53
54void
55JobControl::writeReg(RegAddr addr, uint32_t value)
56{
57    switch(addr.value) {
58      case JOB_IRQ_CLEAR:
59        // Update JS state for all jobs that were affected by the IRQ
60        // clear
61        updateJsState((value & 0xFFFF) | ((value & 0xFFFF0000) >> 16));
62
63        // FALLTHROUGH - IRQ handling in base class
64      case JOB_IRQ_RAWSTAT:
65      case JOB_IRQ_MASK:
66      case JOB_IRQ_STATUS:
67        GPUBlockInt::writeReg(addr, value);
68        break;
69
70      default:
71        if (addr >= RegAddr(JOB_SLOT0))
72            slots[getJobSlotNo(addr)].writeReg(getJobSlotAddr(addr), value);
73        break;
74    }
75}
76
77uint32_t
78JobControl::readRegRaw(RegAddr addr)
79{
80    if (addr >= RegAddr(JOB_SLOT0)) {
81        return slots[getJobSlotNo(addr)].readRegRaw(getJobSlotAddr(addr));
82    } else {
83        return GPUBlockInt::readRegRaw(addr);
84    }
85}
86
87
88void
89JobControl::writeRegRaw(RegAddr addr, uint32_t value)
90{
91    if (addr >= RegAddr(JOB_SLOT0)) {
92        slots[getJobSlotNo(addr)].writeRegRaw(getJobSlotAddr(addr), value);
93    } else {
94        GPUBlockInt::writeRegRaw(addr, value);
95    }
96}
97
98void
99JobControl::jobDone(uint8_t slot)
100{
101    assert(slot <= 15);
102    raiseInterrupt(1 << slot);
103}
104
105void
106JobControl::jobFailed(uint8_t slot)
107{
108    assert(slot <= 15);
109    raiseInterrupt(0x10000 << slot);
110}
111
112void
113JobControl::updateJsState(uint16_t jobs)
114{
115    // The JS_STATE register contains two bits per job slot; one bit
116    // representing an active job and one bit representing the queued
117    // job. We need to mask out bits of the jobs affected by this update.
118    const uint32_t job_mask(jobs | (jobs << 16));
119    uint16_t js_state(regs[RegAddr(JOB_IRQ_JS_STATE)] & ~job_mask);
120
121    // Find if there is an active or active next job for all jobs in
122    // the job mask.
123    for (int i = 0; i < 16; ++i) {
124        const JobSlot &slot(slots[i]);
125        if (jobs & (1 << i)) {
126            js_state |= slot.active() ? (1 << i) : 0 |
127                slot.activeNext() ? (0x10000 << i) : 0;
128        }
129    }
130    regs[RegAddr(JOB_IRQ_JS_STATE)] = js_state;
131}
132
133void
134JobControl::onInterrupt(int set)
135{
136    gpu.intJob(set);
137}
138
139}
140