blob: 7bc88de7ee8f58e351ffeb2aafd7ec710a2098a2 [file] [log] [blame]
/*
* 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];
}
}