/* * 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 "gpublock.hh" #include "gpu.hh" #include "regutils.hh" namespace NoMali { GPUBlock::GPUBlock(GPU &_gpu) : gpu(_gpu), regs(BLOCK_NUM_REGS) { } GPUBlock::GPUBlock(GPU &_gpu, RegVector::size_type no_regs) : gpu(_gpu), regs(no_regs) { } GPUBlock::GPUBlock(GPUBlock &&rhs) : gpu(rhs.gpu), regs(std::move(rhs.regs)) { } GPUBlock::~GPUBlock() { } void GPUBlock::reset() { for (auto &r : regs) r = 0; } uint32_t GPUBlock::readReg(RegAddr addr) { return readRegRaw(addr); } void GPUBlock::writeReg(RegAddr addr, uint32_t value) { writeRegRaw(addr, value); } uint32_t GPUBlock::readRegRaw(RegAddr addr) { return regs[addr]; } void GPUBlock::writeRegRaw(RegAddr addr, uint32_t value) { regs[addr] = value; } GPUBlockInt::GPUBlockInt(GPU &_gpu, const RegAddr &irq_raw_stat, const RegAddr &irq_clear, const RegAddr &irq_mask, const RegAddr &irq_stat) : GPUBlock(_gpu), addrIrqRawStat(irq_raw_stat), addrIrqClear(irq_clear), addrIrqMask(irq_mask), addrIrqStat(irq_stat) { } GPUBlockInt::~GPUBlockInt() { } uint32_t GPUBlockInt::readReg(RegAddr addr) { if (addr == addrIrqStat) { return irqStatus(); } else { return GPUBlock::readReg(addr); } } void GPUBlockInt::writeReg(RegAddr addr, uint32_t value) { if (addr == addrIrqRawStat) { raiseInterrupt(value); } else if (addr == addrIrqClear) { clearInterrupt(value); } else if (addr == addrIrqMask ) { const bool old_int(intAsserted()); GPUBlock::writeReg(addr, value); if (old_int != intAsserted()) onInterrupt(intAsserted()); } else if (addr == addrIrqStat ) { // Ignore writes to the IRQ status register } else { // Handle addrIrqMask & defaults GPUBlock::writeReg(addr, value); } } void GPUBlockInt::raiseInterrupt(uint32_t ints) { const bool old_int(intAsserted()); regs[addrIrqRawStat] |= ints; // Is the interrupt line going high? if (!old_int && intAsserted()) onInterrupt(1); } void GPUBlockInt::clearInterrupt(uint32_t ints) { const bool old_int(intAsserted()); regs[addrIrqRawStat] &= ~ints; // Is the interrupt line going low? if (old_int && !intAsserted()) onInterrupt(0); } uint32_t GPUBlockInt::irqStatus() const { return regs[addrIrqRawStat] & regs[addrIrqMask]; } }