110915Sandreas.sandberg@arm.com/* 210915Sandreas.sandberg@arm.com * Copyright (c) 2014-2015 ARM Limited 310915Sandreas.sandberg@arm.com * All rights reserved 410915Sandreas.sandberg@arm.com * 510915Sandreas.sandberg@arm.com * Licensed under the Apache License, Version 2.0 (the "License"); 610915Sandreas.sandberg@arm.com * you may not use this file except in compliance with the License. 710915Sandreas.sandberg@arm.com * You may obtain a copy of the License at 810915Sandreas.sandberg@arm.com * 910915Sandreas.sandberg@arm.com * http://www.apache.org/licenses/LICENSE-2.0 1010915Sandreas.sandberg@arm.com * 1110915Sandreas.sandberg@arm.com * Unless required by applicable law or agreed to in writing, software 1210915Sandreas.sandberg@arm.com * distributed under the License is distributed on an "AS IS" BASIS, 1310915Sandreas.sandberg@arm.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1410915Sandreas.sandberg@arm.com * See the License for the specific language governing permissions and 1510915Sandreas.sandberg@arm.com * limitations under the License. 1610915Sandreas.sandberg@arm.com * 1710915Sandreas.sandberg@arm.com * Authors: Andreas Sandberg 1810915Sandreas.sandberg@arm.com */ 1910915Sandreas.sandberg@arm.com 2010915Sandreas.sandberg@arm.com#include "jobcontrol.hh" 2110915Sandreas.sandberg@arm.com 2210915Sandreas.sandberg@arm.com#include "gpu.hh" 2310915Sandreas.sandberg@arm.com#include "regutils.hh" 2410915Sandreas.sandberg@arm.com 2510915Sandreas.sandberg@arm.comnamespace NoMali { 2610915Sandreas.sandberg@arm.com 2710915Sandreas.sandberg@arm.comJobControl::JobControl(GPU &_gpu) 2810915Sandreas.sandberg@arm.com : GPUBlockInt(_gpu, 2910915Sandreas.sandberg@arm.com RegAddr(JOB_IRQ_RAWSTAT), 3010915Sandreas.sandberg@arm.com RegAddr(JOB_IRQ_CLEAR), 3110915Sandreas.sandberg@arm.com RegAddr(JOB_IRQ_MASK), 3210915Sandreas.sandberg@arm.com RegAddr(JOB_IRQ_STATUS)) 3310915Sandreas.sandberg@arm.com{ 3410915Sandreas.sandberg@arm.com slots.reserve(16); 3510915Sandreas.sandberg@arm.com for (int i = 0; i < 16; ++i) 3610915Sandreas.sandberg@arm.com slots.emplace_back(_gpu, *this, i); 3710915Sandreas.sandberg@arm.com 3810915Sandreas.sandberg@arm.com} 3910915Sandreas.sandberg@arm.com 4010915Sandreas.sandberg@arm.comJobControl::~JobControl() 4110915Sandreas.sandberg@arm.com{ 4210915Sandreas.sandberg@arm.com} 4310915Sandreas.sandberg@arm.com 4411313Sandreas.sandberg@arm.comvoid 4511313Sandreas.sandberg@arm.comJobControl::reset() 4611313Sandreas.sandberg@arm.com{ 4711313Sandreas.sandberg@arm.com GPUBlockInt::reset(); 4811313Sandreas.sandberg@arm.com 4911313Sandreas.sandberg@arm.com for (auto &js : slots) 5011313Sandreas.sandberg@arm.com js.reset(); 5111313Sandreas.sandberg@arm.com} 5211313Sandreas.sandberg@arm.com 5310915Sandreas.sandberg@arm.comuint32_t 5410915Sandreas.sandberg@arm.comJobControl::readReg(RegAddr addr) 5510915Sandreas.sandberg@arm.com{ 5610915Sandreas.sandberg@arm.com if (addr >= RegAddr(JOB_SLOT0)) { 5710915Sandreas.sandberg@arm.com return slots[getJobSlotNo(addr)].readReg(getJobSlotAddr(addr)); 5810915Sandreas.sandberg@arm.com } else { 5910915Sandreas.sandberg@arm.com return GPUBlockInt::readReg(addr); 6010915Sandreas.sandberg@arm.com } 6110915Sandreas.sandberg@arm.com} 6210915Sandreas.sandberg@arm.com 6310915Sandreas.sandberg@arm.comvoid 6410915Sandreas.sandberg@arm.comJobControl::writeReg(RegAddr addr, uint32_t value) 6510915Sandreas.sandberg@arm.com{ 6610915Sandreas.sandberg@arm.com switch(addr.value) { 6710915Sandreas.sandberg@arm.com case JOB_IRQ_CLEAR: 6810915Sandreas.sandberg@arm.com // Update JS state for all jobs that were affected by the IRQ 6910915Sandreas.sandberg@arm.com // clear 7010915Sandreas.sandberg@arm.com updateJsState((value & 0xFFFF) | ((value & 0xFFFF0000) >> 16)); 7110915Sandreas.sandberg@arm.com 7210915Sandreas.sandberg@arm.com // FALLTHROUGH - IRQ handling in base class 7310915Sandreas.sandberg@arm.com case JOB_IRQ_RAWSTAT: 7410915Sandreas.sandberg@arm.com case JOB_IRQ_MASK: 7510915Sandreas.sandberg@arm.com case JOB_IRQ_STATUS: 7610915Sandreas.sandberg@arm.com GPUBlockInt::writeReg(addr, value); 7710915Sandreas.sandberg@arm.com break; 7810915Sandreas.sandberg@arm.com 7910915Sandreas.sandberg@arm.com default: 8010915Sandreas.sandberg@arm.com if (addr >= RegAddr(JOB_SLOT0)) 8110915Sandreas.sandberg@arm.com slots[getJobSlotNo(addr)].writeReg(getJobSlotAddr(addr), value); 8210915Sandreas.sandberg@arm.com break; 8310915Sandreas.sandberg@arm.com } 8410915Sandreas.sandberg@arm.com} 8510915Sandreas.sandberg@arm.com 8610915Sandreas.sandberg@arm.comuint32_t 8710915Sandreas.sandberg@arm.comJobControl::readRegRaw(RegAddr addr) 8810915Sandreas.sandberg@arm.com{ 8910915Sandreas.sandberg@arm.com if (addr >= RegAddr(JOB_SLOT0)) { 9010915Sandreas.sandberg@arm.com return slots[getJobSlotNo(addr)].readRegRaw(getJobSlotAddr(addr)); 9110915Sandreas.sandberg@arm.com } else { 9210915Sandreas.sandberg@arm.com return GPUBlockInt::readRegRaw(addr); 9310915Sandreas.sandberg@arm.com } 9410915Sandreas.sandberg@arm.com} 9510915Sandreas.sandberg@arm.com 9610915Sandreas.sandberg@arm.com 9710915Sandreas.sandberg@arm.comvoid 9810915Sandreas.sandberg@arm.comJobControl::writeRegRaw(RegAddr addr, uint32_t value) 9910915Sandreas.sandberg@arm.com{ 10010915Sandreas.sandberg@arm.com if (addr >= RegAddr(JOB_SLOT0)) { 10110915Sandreas.sandberg@arm.com slots[getJobSlotNo(addr)].writeRegRaw(getJobSlotAddr(addr), value); 10210915Sandreas.sandberg@arm.com } else { 10310915Sandreas.sandberg@arm.com GPUBlockInt::writeRegRaw(addr, value); 10410915Sandreas.sandberg@arm.com } 10510915Sandreas.sandberg@arm.com} 10610915Sandreas.sandberg@arm.com 10710915Sandreas.sandberg@arm.comvoid 10810915Sandreas.sandberg@arm.comJobControl::jobDone(uint8_t slot) 10910915Sandreas.sandberg@arm.com{ 11010915Sandreas.sandberg@arm.com assert(slot <= 15); 11110915Sandreas.sandberg@arm.com raiseInterrupt(1 << slot); 11210915Sandreas.sandberg@arm.com} 11310915Sandreas.sandberg@arm.com 11410915Sandreas.sandberg@arm.comvoid 11510915Sandreas.sandberg@arm.comJobControl::jobFailed(uint8_t slot) 11610915Sandreas.sandberg@arm.com{ 11710915Sandreas.sandberg@arm.com assert(slot <= 15); 11810915Sandreas.sandberg@arm.com raiseInterrupt(0x10000 << slot); 11910915Sandreas.sandberg@arm.com} 12010915Sandreas.sandberg@arm.com 12110915Sandreas.sandberg@arm.comvoid 12210915Sandreas.sandberg@arm.comJobControl::updateJsState(uint16_t jobs) 12310915Sandreas.sandberg@arm.com{ 12410915Sandreas.sandberg@arm.com // The JS_STATE register contains two bits per job slot; one bit 12510915Sandreas.sandberg@arm.com // representing an active job and one bit representing the queued 12610915Sandreas.sandberg@arm.com // job. We need to mask out bits of the jobs affected by this update. 12710915Sandreas.sandberg@arm.com const uint32_t job_mask(jobs | (jobs << 16)); 12810915Sandreas.sandberg@arm.com uint16_t js_state(regs[RegAddr(JOB_IRQ_JS_STATE)] & ~job_mask); 12910915Sandreas.sandberg@arm.com 13010915Sandreas.sandberg@arm.com // Find if there is an active or active next job for all jobs in 13110915Sandreas.sandberg@arm.com // the job mask. 13210915Sandreas.sandberg@arm.com for (int i = 0; i < 16; ++i) { 13310915Sandreas.sandberg@arm.com const JobSlot &slot(slots[i]); 13410915Sandreas.sandberg@arm.com if (jobs & (1 << i)) { 13510915Sandreas.sandberg@arm.com js_state |= slot.active() ? (1 << i) : 0 | 13610915Sandreas.sandberg@arm.com slot.activeNext() ? (0x10000 << i) : 0; 13710915Sandreas.sandberg@arm.com } 13810915Sandreas.sandberg@arm.com } 13910915Sandreas.sandberg@arm.com regs[RegAddr(JOB_IRQ_JS_STATE)] = js_state; 14010915Sandreas.sandberg@arm.com} 14110915Sandreas.sandberg@arm.com 14210915Sandreas.sandberg@arm.comvoid 14310915Sandreas.sandberg@arm.comJobControl::onInterrupt(int set) 14410915Sandreas.sandberg@arm.com{ 14510915Sandreas.sandberg@arm.com gpu.intJob(set); 14610915Sandreas.sandberg@arm.com} 14710915Sandreas.sandberg@arm.com 14810915Sandreas.sandberg@arm.com} 149