Deleted Added
sdiff udiff text old ( 10915:71ace17ccb3d ) new ( 11313:89fd4a775287 )
full compact
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 "jobslot.hh"
21
22#include <cassert>
23#include <cstdlib>
24
25#include "jobcontrol.hh"
26#include "gpu.hh"
27#include "regutils.hh"
28
29namespace NoMali {
30
31const std::vector<JobSlot::cmd_t> JobSlot::cmds {
32 &JobSlot::cmdNop, // JSn_COMMAND_NOP
33 &JobSlot::cmdStart, // JSn_COMMAND_START
34 &JobSlot::cmdSoftStop, // JSn_COMMAND_SOFT_STOP
35 &JobSlot::cmdHardStop, // JSn_COMMAND_HARD_STOP
36 &JobSlot::cmdSoftStop0, // JSn_COMMAND_SOFT_STOP_0
37 &JobSlot::cmdHardStop0, // JSn_COMMAND_HARD_STOP_0
38 &JobSlot::cmdSoftStop1, // JSn_COMMAND_SOFT_STOP_1
39 &JobSlot::cmdHardStop1, // JSn_COMMAND_HARD_STOP_1
40};
41
42JobSlot::JobSlot(GPU &_gpu, JobControl &_jc, uint8_t _id)
43 : GPUBlock(_gpu, JSn_NO_REGS),
44 id(_id),
45 jc(_jc)
46{
47}
48
49JobSlot::JobSlot(JobSlot &&rhs)
50 : GPUBlock(std::move(rhs)),
51 id(std::move(rhs.id)),
52 jc(rhs.jc)
53{
54}
55
56JobSlot::~JobSlot()
57{
58}
59
60void
61JobSlot::writeReg(RegAddr addr, uint32_t value)
62{
63 switch (addr.value) {
64 case JSn_COMMAND:
65 jobCommand(value);
66 break;
67
68 case JSn_COMMAND_NEXT:
69 regs[addr] = value;
70 tryStart();
71 break;
72
73 case JSn_HEAD_NEXT_LO:
74 case JSn_HEAD_NEXT_HI:
75 case JSn_AFFINITY_NEXT_LO:
76 case JSn_AFFINITY_NEXT_HI:
77 case JSn_CONFIG_NEXT:
78 GPUBlock::writeReg(addr, value);
79 break;
80
81 default:
82 // Ignore writes by default
83 break;
84 };
85}
86
87bool
88JobSlot::active() const
89{
90 return false;
91}
92
93bool
94JobSlot::activeNext() const
95{
96 return regs[RegAddr(JSn_COMMAND_NEXT)] == JSn_COMMAND_START;
97}
98
99void
100JobSlot::tryStart()
101{
102 // Only actually start something if the next command is start
103 if (regs[RegAddr(JSn_COMMAND_NEXT)] != JSn_COMMAND_START )
104 return;
105
106 // Reset the status register
107 regs[RegAddr(JSn_STATUS)] = 0;
108
109 // Transfer the next job configuration to the active job
110 // configuration
111 regs.set64(RegAddr(JSn_HEAD_LO), regs.get64(RegAddr(JSn_HEAD_NEXT_LO)));
112 regs.set64(RegAddr(JSn_TAIL_LO), regs.get64(RegAddr(JSn_HEAD_NEXT_LO)));
113 regs.set64(RegAddr(JSn_AFFINITY_LO),
114 regs.get64(RegAddr(JSn_AFFINITY_NEXT_LO)));
115 regs[RegAddr(JSn_CONFIG)] = regs[RegAddr(JSn_CONFIG_NEXT)];
116 regs[RegAddr(JSn_COMMAND)] = regs[RegAddr(JSn_COMMAND_NEXT)];
117
118 // Reset the next job configuration
119 regs.set64(RegAddr(JSn_HEAD_NEXT_LO), 0);
120 regs.set64(RegAddr(JSn_AFFINITY_NEXT_LO), 0);
121 regs[RegAddr(JSn_CONFIG_NEXT)] = 0;
122 regs[RegAddr(JSn_COMMAND_NEXT)] = 0;
123
124 runJob();
125}
126
127void
128JobSlot::runJob()
129{
130 exitJob(Status(Status::CLASS_NOFAULT, 0, 1), // JSn_STATUS_DONE
131 0); // Time stamp counter value
132}
133
134void
135JobSlot::exitJob(Status status, uint64_t fault_address)
136{
137 assert(status.statusClass() == Status::CLASS_NOFAULT ||
138 status.statusClass() == Status::CLASS_JOB);
139
140 regs[RegAddr(JSn_STATUS)] = status.value;
141
142 if (status.statusClass() == Status::CLASS_NOFAULT) {
143 jc.jobDone(id);
144 } else {
145 jc.jobFailed(id);
146 }
147}
148
149void
150JobSlot::jobCommand(uint32_t cmd)
151{
152 if (cmd < cmds.size())
153 (this->*cmds[cmd])(cmd);
154}
155
156void
157JobSlot::cmdNop(uint32_t cmd)
158{
159 assert(cmd == JSn_COMMAND_NOP);
160}
161
162void
163JobSlot::cmdStart(uint32_t cmd)
164{
165 assert(cmd == JSn_COMMAND_START);
166 // The JSn_COMMAND_START should never be issued through the
167 // JSn_COMMAND register. It should use the JSn_COMMAND_NEXT
168 // register instead.
169 abort();
170}
171
172void
173JobSlot::cmdSoftStop(uint32_t cmd)
174{
175 assert(cmd == JSn_COMMAND_SOFT_STOP ||
176 cmd == JSn_COMMAND_SOFT_STOP_0 ||
177 cmd == JSn_COMMAND_SOFT_STOP_1);
178}
179
180void
181JobSlot::cmdHardStop(uint32_t cmd)
182{
183 assert(cmd == JSn_COMMAND_HARD_STOP ||
184 cmd == JSn_COMMAND_HARD_STOP_0 ||
185 cmd == JSn_COMMAND_HARD_STOP_1);
186}
187
188void
189JobSlot::cmdSoftStop0(uint32_t cmd)
190{
191 if (!(regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG))
192 cmdSoftStop(cmd);
193}
194
195void
196JobSlot::cmdHardStop0(uint32_t cmd)
197{
198 if (!(regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG))
199 cmdHardStop(cmd);
200}
201
202void
203JobSlot::cmdSoftStop1(uint32_t cmd)
204{
205 if (regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG)
206 cmdSoftStop(cmd);
207}
208
209void
210JobSlot::cmdHardStop1(uint32_t cmd)
211{
212 if (regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG)
213 cmdHardStop(cmd);
214}
215
216}