jobslot.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 "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} 217