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