| /* |
| * Copyright (c) 2014-2015 ARM Limited |
| * All rights reserved |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| * Authors: Andreas Sandberg |
| */ |
| |
| #include "jobcontrol.hh" |
| |
| #include "gpu.hh" |
| #include "regutils.hh" |
| |
| namespace NoMali { |
| |
| JobControl::JobControl(GPU &_gpu) |
| : GPUBlockInt(_gpu, |
| RegAddr(JOB_IRQ_RAWSTAT), |
| RegAddr(JOB_IRQ_CLEAR), |
| RegAddr(JOB_IRQ_MASK), |
| RegAddr(JOB_IRQ_STATUS)) |
| { |
| slots.reserve(16); |
| for (int i = 0; i < 16; ++i) |
| slots.emplace_back(_gpu, *this, i); |
| |
| } |
| |
| JobControl::~JobControl() |
| { |
| } |
| |
| void |
| JobControl::reset() |
| { |
| GPUBlockInt::reset(); |
| |
| for (auto &js : slots) |
| js.reset(); |
| } |
| |
| uint32_t |
| JobControl::readReg(RegAddr addr) |
| { |
| if (addr >= RegAddr(JOB_SLOT0)) { |
| return slots[getJobSlotNo(addr)].readReg(getJobSlotAddr(addr)); |
| } else { |
| return GPUBlockInt::readReg(addr); |
| } |
| } |
| |
| void |
| JobControl::writeReg(RegAddr addr, uint32_t value) |
| { |
| switch(addr.value) { |
| case JOB_IRQ_CLEAR: |
| // Update JS state for all jobs that were affected by the IRQ |
| // clear |
| updateJsState((value & 0xFFFF) | ((value & 0xFFFF0000) >> 16)); |
| |
| // FALLTHROUGH - IRQ handling in base class |
| case JOB_IRQ_RAWSTAT: |
| case JOB_IRQ_MASK: |
| case JOB_IRQ_STATUS: |
| GPUBlockInt::writeReg(addr, value); |
| break; |
| |
| default: |
| if (addr >= RegAddr(JOB_SLOT0)) |
| slots[getJobSlotNo(addr)].writeReg(getJobSlotAddr(addr), value); |
| break; |
| } |
| } |
| |
| uint32_t |
| JobControl::readRegRaw(RegAddr addr) |
| { |
| if (addr >= RegAddr(JOB_SLOT0)) { |
| return slots[getJobSlotNo(addr)].readRegRaw(getJobSlotAddr(addr)); |
| } else { |
| return GPUBlockInt::readRegRaw(addr); |
| } |
| } |
| |
| |
| void |
| JobControl::writeRegRaw(RegAddr addr, uint32_t value) |
| { |
| if (addr >= RegAddr(JOB_SLOT0)) { |
| slots[getJobSlotNo(addr)].writeRegRaw(getJobSlotAddr(addr), value); |
| } else { |
| GPUBlockInt::writeRegRaw(addr, value); |
| } |
| } |
| |
| void |
| JobControl::jobDone(uint8_t slot) |
| { |
| assert(slot <= 15); |
| raiseInterrupt(1 << slot); |
| } |
| |
| void |
| JobControl::jobFailed(uint8_t slot) |
| { |
| assert(slot <= 15); |
| raiseInterrupt(0x10000 << slot); |
| } |
| |
| void |
| JobControl::updateJsState(uint16_t jobs) |
| { |
| // The JS_STATE register contains two bits per job slot; one bit |
| // representing an active job and one bit representing the queued |
| // job. We need to mask out bits of the jobs affected by this update. |
| const uint32_t job_mask(jobs | (jobs << 16)); |
| uint16_t js_state(regs[RegAddr(JOB_IRQ_JS_STATE)] & ~job_mask); |
| |
| // Find if there is an active or active next job for all jobs in |
| // the job mask. |
| for (int i = 0; i < 16; ++i) { |
| const JobSlot &slot(slots[i]); |
| if (jobs & (1 << i)) { |
| js_state |= slot.active() ? (1 << i) : 0 | |
| slot.activeNext() ? (0x10000 << i) : 0; |
| } |
| } |
| regs[RegAddr(JOB_IRQ_JS_STATE)] = js_state; |
| } |
| |
| void |
| JobControl::onInterrupt(int set) |
| { |
| gpu.intJob(set); |
| } |
| |
| } |