summaryrefslogtreecommitdiff
path: root/ext/nomali/lib/gpublock.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ext/nomali/lib/gpublock.cc')
-rw-r--r--ext/nomali/lib/gpublock.cc156
1 files changed, 156 insertions, 0 deletions
diff --git a/ext/nomali/lib/gpublock.cc b/ext/nomali/lib/gpublock.cc
new file mode 100644
index 000000000..7bc88de7e
--- /dev/null
+++ b/ext/nomali/lib/gpublock.cc
@@ -0,0 +1,156 @@
+/*
+ * 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];
+}
+
+
+}