diff options
Diffstat (limited to 'ext/nomali/lib')
-rw-r--r-- | ext/nomali/lib/Rules.mk | 55 | ||||
-rw-r--r-- | ext/nomali/lib/gpu.cc | 112 | ||||
-rw-r--r-- | ext/nomali/lib/gpu.hh | 205 | ||||
-rw-r--r-- | ext/nomali/lib/gpublock.cc | 156 | ||||
-rw-r--r-- | ext/nomali/lib/gpublock.hh | 221 | ||||
-rw-r--r-- | ext/nomali/lib/gpucontrol.cc | 177 | ||||
-rw-r--r-- | ext/nomali/lib/gpucontrol.hh | 159 | ||||
-rw-r--r-- | ext/nomali/lib/jobcontrol.cc | 139 | ||||
-rw-r--r-- | ext/nomali/lib/jobcontrol.hh | 93 | ||||
-rw-r--r-- | ext/nomali/lib/jobslot.cc | 216 | ||||
-rw-r--r-- | ext/nomali/lib/jobslot.hh | 208 | ||||
-rw-r--r-- | ext/nomali/lib/mali_midg_regmap.h | 510 | ||||
-rw-r--r-- | ext/nomali/lib/mali_midgard.cc | 92 | ||||
-rw-r--r-- | ext/nomali/lib/mali_midgard.hh | 70 | ||||
-rw-r--r-- | ext/nomali/lib/mali_t6xx.cc | 55 | ||||
-rw-r--r-- | ext/nomali/lib/mali_t6xx.hh | 61 | ||||
-rw-r--r-- | ext/nomali/lib/mali_t7xx.cc | 50 | ||||
-rw-r--r-- | ext/nomali/lib/mali_t7xx.hh | 50 | ||||
-rw-r--r-- | ext/nomali/lib/mmu.cc | 64 | ||||
-rw-r--r-- | ext/nomali/lib/mmu.hh | 57 | ||||
-rw-r--r-- | ext/nomali/lib/nomali_api.cc | 355 | ||||
-rw-r--r-- | ext/nomali/lib/regutils.hh | 103 | ||||
-rw-r--r-- | ext/nomali/lib/types.hh | 218 |
23 files changed, 3426 insertions, 0 deletions
diff --git a/ext/nomali/lib/Rules.mk b/ext/nomali/lib/Rules.mk new file mode 100644 index 000000000..34fb6e32e --- /dev/null +++ b/ext/nomali/lib/Rules.mk @@ -0,0 +1,55 @@ +# +# 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 + +sp := $(sp).x +dirstack_$(sp) := $(d) +d := $(dir) + +NOMALI_OBJS := $(addprefix $(d)/, \ + gpu.o \ + gpublock.o \ + gpucontrol.o \ + jobcontrol.o \ + jobslot.o \ + mmu.o \ + \ + mali_midgard.o \ + mali_t6xx.o \ + mali_t7xx.o \ + ) + +LIBNOMALI_OBJS := $(addprefix $(d)/, \ + nomali_api.o \ + ) + +OBJS := $(NOMALI_OBJS) \ + $(LIBMIDGARDMODEL_OBJS) + +LIBS := libnomali.so + +ALL := $(ALL) $(LIBS) +DEPS := $(DEPS) $(OBJS:.o=.d) +CLEAN := $(CLEAN) $(OBJS) $(LIBS) + +include Rules.lib.mk + +libnomali.so: $(NOMALI_OBJS) $(LIBNOMALI_OBJS) + $(CXX) $(LIB_LDFLAGS) -o $@ $^ + +d := $(dirstack_$(sp)) +sp := $(basename $(sp)) diff --git a/ext/nomali/lib/gpu.cc b/ext/nomali/lib/gpu.cc new file mode 100644 index 000000000..88646ab36 --- /dev/null +++ b/ext/nomali/lib/gpu.cc @@ -0,0 +1,112 @@ +/* + * 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. + */ + +#include "gpu.hh" + +#include "gpucontrol.hh" +#include "jobcontrol.hh" +#include "mmu.hh" +#include "regutils.hh" + +namespace NoMali { + +GPU::GPU(GPUControl &gc, JobControl &jc, MMU &_mmu) + : gpuControl(gc), jobControl(jc), mmu(_mmu), + blocks({&gpuControl, // REG_BLOCK_GPU + &jobControl, // REG_BLOCK_JOB + &mmu}) // REG_BLOCK_MMU +{ +} + +GPU::~GPU() +{ +} + +void +GPU::reset() +{ + for (auto *block : blocks) + block->reset(); +} + +uint32_t +GPU::readReg(RegAddr addr) +{ + GPUBlock * const block(getGPUBlock(addr)); + + return block ? block->readReg(getBlockReg(addr)) : 0; +} + +void +GPU::writeReg(RegAddr addr, uint32_t value) +{ + GPUBlock * const block(getGPUBlock(addr)); + + if (block) + block->writeReg(getBlockReg(addr), value); +} + +uint32_t +GPU::readRegRaw(RegAddr addr) +{ + GPUBlock * const block(getGPUBlock(addr)); + + return block ? block->readRegRaw(getBlockReg(addr)) : 0; +} + +void +GPU::writeRegRaw(RegAddr addr, uint32_t value) +{ + GPUBlock * const block(getGPUBlock(addr)); + + if (block) + block->writeRegRaw(getBlockReg(addr), value); +} + + +bool +GPU::intGPUAsserted() const +{ + return gpuControl.intAsserted(); +} + +bool +GPU::intJobAsserted() const +{ + return jobControl.intAsserted(); +} + +bool +GPU::intMMUAsserted() const +{ + return mmu.intAsserted(); +} + + +GPUBlock * +GPU::getGPUBlock(RegAddr addr) +{ + const RegBlock block(getRegBlock(addr)); + const uint16_t block_no(static_cast<uint16_t>(block)); + + if (block_no < blocks.size()) + return blocks[block_no]; + else + return nullptr; +} + +} diff --git a/ext/nomali/lib/gpu.hh b/ext/nomali/lib/gpu.hh new file mode 100644 index 000000000..f167f1012 --- /dev/null +++ b/ext/nomali/lib/gpu.hh @@ -0,0 +1,205 @@ +/* + * 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 + */ + +#ifndef _LIBNOMALIMODEL_GPU_HH +#define _LIBNOMALIMODEL_GPU_HH + +#include <vector> + +#include "types.hh" + +namespace NoMali { + +class GPUBlock; +class GPUControl; +class JobControl; +class MMU; + +/** + * Top-level GPU component (abstract). + */ +class GPU +{ + public: + /** + * Instantiate a GPU from a set of functional blocks. + * + * @param gpuControl GPU control implementation. + * @param jobControl Job control implementation. + * @param mmu MMU implementation. + */ + GPU(GPUControl &gpuControl, JobControl &jobControl, MMU &mmu); + virtual ~GPU() = 0; + + /** + * Reset the whole GPU + * + * The default implementation of this method calls the reset() on + * all the function blocks. Function blocks in turn typically sets + * all registers to zero. + */ + virtual void reset(); + + + /** + * @{ + * @name Register Interface + */ + + /** + * Read a register value from the GPU. + * + * This method decodes the address to find the function block an + * access is intended for and forward the register access to that + * block. The access that reaches the block does not include the + * block base address. + * + * @param addr Register address to read. + * @return Value of the register. + */ + virtual uint32_t readReg(RegAddr addr); + + /** + * Write a register value to the GPU. + * + * This method decodes the address to find the function block an + * access is intended for and forward the register access to that + * block. The access that reaches the block does not include the + * block base address. + * + * @param addr Target address for the write operation. + * @param value Value to write. + */ + virtual void writeReg(RegAddr addr, uint32_t value); + + /** + * Read a register value from the GPU without side effects. + * + * This method decodes the address to find the function block an + * access is intended for and forward the register access to that + * block. The access that reaches the block does not include the + * block base address. + * + * Unlike a normal read (readReg()), this method does not include + * any side effects and reads straight from the register file. It + * is primarily intended for things checkpointing. + * + * @param addr Register address to read. + * @return Value of the register. + */ + virtual uint32_t readRegRaw(RegAddr addr); + + /** + * Write a register value to the GPU without side effects. + * + * This method decodes the address to find the function block an + * access is intended for and forward the register access to that + * block. The access that reaches the block does not include the + * block base address. + * + * Unlike a normal write (writeReg()), this method does not + * include any side effects and writes straight into the register + * file. It is primarily intended for things checkpointing. + * + * @param addr Target address for the write operation. + * @param value Value to write. + */ + virtual void writeRegRaw(RegAddr addr, uint32_t value); + + /** @} */ + + /** + * @{ + * @name Callbacks + */ + + /** + * Job interrupt state change + * + * @param set Non-zero if raising interrupt, zero if clearing. + */ + virtual void intJob(int set) {}; + /** + * MMU interrupt state change + * + * @param set Non-zero if raising interrupt, zero if clearing. + */ + virtual void intMMU(int set) {}; + /** + * GPU interrupt state change + * + * @param set Non-zero if raising interrupt, zero if clearing. + */ + virtual void intGPU(int set) {}; + + /** @} */ + + + /** + * Check if the GPU interrupt has been asserted. + * + * @see GPUControl::intAsserted() + * + * @return true if the GPU control block reports that an interrupt + * has been asserted. + */ + bool intGPUAsserted() const; + /** + * Check if the job interrupt has been asserted. + * + * @see JobControl::intAsserted() + * + * @return true if the job control block reports that an interrupt + * has been asserted. + */ + bool intJobAsserted() const; + /** + * Check if the MMU interrupt has been asserted. + * + * @see JobControl::intAsserted() + * + * @return true if the GPU control block reports that an interrupt + * has been asserted. + */ + bool intMMUAsserted() const; + + private: + /** + * Resolve an address into a functional block within the GPU. + * + * @return Valid pointer or NULL if address is out of range. + */ + GPUBlock *getGPUBlock(RegAddr addr); + + GPUControl &gpuControl; + JobControl &jobControl; + MMU &mmu; + + /** + * Vector of control blocks. + * + * @note The order <i>MUST</i> have the same correspond to the + * values in the RegBlock enum. + */ + const std::vector<GPUBlock *> blocks; +}; + +} + +#endif // _LIBNOMALIMODEL_GPU_HH 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]; +} + + +} diff --git a/ext/nomali/lib/gpublock.hh b/ext/nomali/lib/gpublock.hh new file mode 100644 index 000000000..330ffcb7c --- /dev/null +++ b/ext/nomali/lib/gpublock.hh @@ -0,0 +1,221 @@ +/* + * 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 + */ + +#ifndef _LIBNOMALIMODEL_GPUBLOCK_HH +#define _LIBNOMALIMODEL_GPUBLOCK_HH + +#include "types.hh" + +namespace NoMali { + +class GPU; + +/** + * Base class for GPU function blocks providing common access + * functions. + */ +class GPUBlock +{ + public: + GPUBlock(GPU &_gpu); + GPUBlock(GPU &_gpu, RegVector::size_type no_regs); + GPUBlock(GPUBlock &&rhs); + virtual ~GPUBlock() = 0; + + /** + * Reset the function block. + * + * This method is called to simulated a hard reset of the GPU. It + * resets all registers to their default state and resets any + * block-specific state. The default implementation resets all + * registers to 0. + */ + virtual void reset(); + + + /** + * @{ + * @name Register Interface + */ + + /** + * Read a register within a function block. + * + * @param addr Function-block relative address. + * @return Register value (32-bits) + */ + virtual uint32_t readReg(RegAddr addr); + + /** + * Write to a register within a function block. + * + * @param addr Function-block relative address. + * @param value New value (32-bits) + */ + virtual void writeReg(RegAddr addr, uint32_t value); + + + /** + * Read a register within a function block without side effects. + * + * Unlike a normal read (readReg()), this method does not include + * any side effects and reads straight from the register file. It + * is primarily intended for things checkpointing. + * + * @param addr Function-block relative address. + * @return Register value (32-bits) + */ + virtual uint32_t readRegRaw(RegAddr addr); + + /** + * Write to a register within a function block without side + * effects. + * + * Unlike a normal write (writeReg()), this method does not + * include any side effects and writes straight into the register + * file. It is primarily intended for things checkpointing. + * + * @param addr Function-block relative address. + * @param value New value (32-bits) + */ + virtual void writeRegRaw(RegAddr addr, uint32_t value); + + /** @} */ + + protected: + /** Reference to the top-level GPU component */ + GPU &gpu; + + /** GPU block register file */ + RegVector regs; + + + private: + /** Disable the default constructor */ + GPUBlock(); + + /** Disable the copy constructor */ + GPUBlock(GPUBlock &_rhs); + + /** Disable the assignment operator */ + GPUBlock &operator=(GPUBlock &_rhs); +}; + +/** + * Base class for interrupt enabled GPU function blocks. + * + * Function blocks with interrupt functionality implement four + * different registers controlling interrupts: + * <ul> + * <li>XX_IRQ_RAWSTAT -- Raw interrupt state bit mask. (RW) + * <li>XX_IRQ_CLEAR -- Interrupt clear register. (WO) + * <li>XX_IRQ_MASK -- Bitmaks of enabled interrupts. (RW) + * <li>XX_IRQ_STATUS -- Currently pending unmasked interrupts. (RO) + * </ul> + * + * This class provides implements the handling of the registers above + * and utility functions to raise interrupts from the function block + * models. + */ +class GPUBlockInt + : public GPUBlock +{ + public: + GPUBlockInt(GPU &_gpu, + const RegAddr &irq_raw_stat, + const RegAddr &irq_clear, + const RegAddr &irq_mask, + const RegAddr &irq_stat); + virtual ~GPUBlockInt() = 0; + + uint32_t readReg(RegAddr addr) override; + void writeReg(RegAddr addr, uint32_t value) override; + + /** + * Raise an interrupt from this function block. + * + * Calling this method flags the interrupts in ints as pending in + * the raw interrupt status register. If this operation asserts a + * new unmasked interrupt (i.e., the state of the interrupt status + * register changes), the onInterrupt() callback is called to + * signal an interrupt state change. + * + * @param ints Bitfield representing interrupts to raise. + */ + void raiseInterrupt(uint32_t ints); + + /** + * Clear an interrupt from this function block. + * + * Calling this method clears the interrupts in ints in the raw + * interrupt status register. If this operation clears a an + * existing interrupt (i.e., the state of the interrupt status + * register changes), the onInterrupt() callback is called to + * signal an interrupt state change. + * + * @param ints Bitfield representing interrupts to raise. + */ + void clearInterrupt(uint32_t ints); + + /** + * Current interrupt status + * + * @return The value of the raw interrupt status register + * logically anded with the interrupt mask register. + */ + uint32_t irqStatus() const; + + /** + * Are there unmasked interrupts pending? + * + * @return true if the interrupt status register is non-zero, + * false otherwise. + */ + bool intAsserted() const { return !!irqStatus(); } + + protected: + /** + * Callback method for interrupt status change. + * + * This method is called whenever the interrupt signal going out + * of this GPU block changes. The new state of the signal can be + * determined from the 'set' parameter which is non-zero if the + * inerrupt is raised and zero if it is cleared. The state of the + * interrupt signal can also be queried using the irqStatus() + * method. + * + * @see raiseInterrupt() + * @see clearInterrupt() + * @see irqStatus() + * + * @param set Non-zero to raise interrupt, zero to clear + * interrupt. + */ + virtual void onInterrupt(int set) = 0; + + private: + const RegAddr addrIrqRawStat; + const RegAddr addrIrqClear; + const RegAddr addrIrqMask; + const RegAddr addrIrqStat; +}; + +} + +#endif // _LIBNOMALIMODEL_GPUBLOCK_HH diff --git a/ext/nomali/lib/gpucontrol.cc b/ext/nomali/lib/gpucontrol.cc new file mode 100644 index 000000000..688f5867e --- /dev/null +++ b/ext/nomali/lib/gpucontrol.cc @@ -0,0 +1,177 @@ +/* + * 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 "gpucontrol.hh" +#include "gpu.hh" +#include "regutils.hh" + +namespace NoMali { + +typedef void (GPUControl::*GpuCmdHandler)(uint32_t); + +const std::vector<GpuCmdHandler> GPUControl::cmds { + &GPUControl::cmdNop, // GPU_COMMAND_NOP + &GPUControl::cmdSoftReset, // GPU_COMMAND_SOFT_RESET + &GPUControl::cmdHardReset, // GPU_COMMAND_HARD_RESET + &GPUControl::cmdPerfCntClear, // GPU_COMMAND_PRFCNT_CLEAR + &GPUControl::cmdPerfCntSample, // GPU_COMMAND_PRFCNT_SAMPLE + &GPUControl::cmdCycleCountStart, // GPU_COMMAND_CYCLE_COUNT_START + &GPUControl::cmdCycleCountStop, // GPU_COMMAND_COUNT_STOP + &GPUControl::cmdCleanCaches, // GPU_COMMAND_CLEAN_CACHES + &GPUControl::cmdCleanInvCaches, // GPU_COMMAND_CLEAN_INV_CACHES +}; + +GPUControl::GPUControl(GPU &_gpu) + : GPUBlockInt(_gpu, + RegAddr(GPU_IRQ_RAWSTAT), + RegAddr(GPU_IRQ_CLEAR), + RegAddr(GPU_IRQ_MASK), + RegAddr(GPU_IRQ_STATUS)) +{ +} + +GPUControl::~GPUControl() +{ +} + +void +GPUControl::reset() +{ + GPUBlock::reset(); +} + +void +GPUControl::writeReg(RegAddr addr, uint32_t value) +{ + switch (addr.value) { + case GPU_IRQ_RAWSTAT: + case GPU_IRQ_CLEAR: + case GPU_IRQ_MASK: + case GPU_IRQ_STATUS: + GPUBlockInt::writeReg(addr, value); + break; + + case GPU_COMMAND: + gpuCommand(value); + break; + + case SHADER_PWRON_LO: + case SHADER_PWRON_HI: + case TILER_PWRON_LO: + case TILER_PWRON_HI: + case L2_PWRON_LO: + case L2_PWRON_HI: + case L3_PWRON_LO: + case L3_PWRON_HI: { + const RegAddr ready_reg(SHADER_READY_LO + + (addr.value - SHADER_PWRON_LO)); + const RegAddr present_reg(SHADER_PRESENT_LO + + (addr.value - SHADER_PWRON_LO)); + + regs[ready_reg] |= value & regs[present_reg]; + raiseInterrupt(POWER_CHANGED_SINGLE | POWER_CHANGED_ALL); + } break; + + case SHADER_PWROFF_LO: + case SHADER_PWROFF_HI: + case TILER_PWROFF_LO: + case TILER_PWROFF_HI: + case L2_PWROFF_LO: + case L2_PWROFF_HI: + case L3_PWROFF_LO: + case L3_PWROFF_HI: { + const RegAddr ready_reg(SHADER_READY_LO + + (addr.value - SHADER_PWROFF_LO)); + + regs[ready_reg] &= ~value; + raiseInterrupt(POWER_CHANGED_SINGLE | POWER_CHANGED_ALL); + } break; + + default: + // Ignore writes by default + break; + }; +} + +void +GPUControl::onInterrupt(int set) +{ + gpu.intGPU(set); +} + +void +GPUControl::gpuCommand(uint32_t cmd) +{ + if (cmd < cmds.size()) + (this->*cmds[cmd])(cmd); +} + +void +GPUControl::cmdNop(uint32_t cmd) +{ +} + +void +GPUControl::cmdHardReset(uint32_t cmd) +{ + gpu.reset(); + raiseInterrupt(RESET_COMPLETED); +} + +void +GPUControl::cmdSoftReset(uint32_t cmd) +{ + gpu.reset(); + raiseInterrupt(RESET_COMPLETED); +} + +void +GPUControl::cmdPerfCntClear(uint32_t cmd) +{ +} + +void +GPUControl::cmdPerfCntSample(uint32_t cmd) +{ + raiseInterrupt(PRFCNT_SAMPLE_COMPLETED); +} + +void +GPUControl::cmdCycleCountStart(uint32_t cmd) +{ +} + +void +GPUControl::cmdCycleCountStop(uint32_t cmd) +{ +} + +void +GPUControl::cmdCleanCaches(uint32_t cmd) +{ + raiseInterrupt(CLEAN_CACHES_COMPLETED); +} + +void +GPUControl::cmdCleanInvCaches(uint32_t cmd) +{ + raiseInterrupt(CLEAN_CACHES_COMPLETED); +} + +} diff --git a/ext/nomali/lib/gpucontrol.hh b/ext/nomali/lib/gpucontrol.hh new file mode 100644 index 000000000..b5bac4eb6 --- /dev/null +++ b/ext/nomali/lib/gpucontrol.hh @@ -0,0 +1,159 @@ +/* + * 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 + */ + +#ifndef _LIBNOMALIMODEL_GPUCONTROL_HH +#define _LIBNOMALIMODEL_GPUCONTROL_HH + +#include <vector> + +#include "types.hh" +#include "gpublock.hh" + +namespace NoMali { + +class GPU; + +/** + * Limited GPU control block implementation. + * + * This is a minimal implementation of the Midgard GPU control + * block. It contains the stuff necessary to do command decoding and + * dispatch, interrupt handling, and GPU block ready handling. + * + * An actual GPU implementation should specialize this class to setup + * the following registers from the reset() method: + * <ul> + * <li>GPU_ID + * <li>Feature registers (XX_FEATURES) + * <li>Present registers (XX_PRESENT) + * <li>Thread discovery (THREAD_XX) + * <li>Present registers (XX_PRESENT) + * </ul> + */ +class GPUControl + : public GPUBlockInt +{ + public: + GPUControl(GPU &_gpu); + virtual ~GPUControl(); + + virtual void reset() override = 0; + + void writeReg(RegAddr idx, uint32_t value) override; + + protected: + void onInterrupt(int set) override; + + /** + * @{ + * @name GPU control block commands + */ + + /** + * Control command dispatcher. + * + * This method is called whenever there is a write to the + * GPU_COMMAND register. The method uses a lookup table to call + * the right command handling method. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + virtual void gpuCommand(uint32_t cmd); + /** + * Command handler for No-ops. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + virtual void cmdNop(uint32_t cmd); + /** + * Command handler for GPU-wide hard resets + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + virtual void cmdHardReset(uint32_t cmd); + /** + * Command handler for GPU-wide soft resets + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + virtual void cmdSoftReset(uint32_t cmd); + /** + * Command handler for performance counter clear operations. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + virtual void cmdPerfCntClear(uint32_t cmd); + /** + * Command handler for performance counter sample operations. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + virtual void cmdPerfCntSample(uint32_t cmd); + /** + * Command handler for cycle counter start operations. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + virtual void cmdCycleCountStart(uint32_t cmd); + /** + * Command handler for cycle counter stop operations. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + virtual void cmdCycleCountStop(uint32_t cmd); + /** + * Command handler for cache cleaning operations. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + virtual void cmdCleanCaches(uint32_t cmd); + /** + * Command handler for cache clean and invalidate operations. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + virtual void cmdCleanInvCaches(uint32_t cmd); + + /** @} */ + + protected: + typedef void (GPUControl::*cmd_t)(uint32_t); + /** + * Mapping between command IDs and command handling methods. + * + * @note The order of this vector <i>MUST</i> correspond to the + * GPU control command IDs in the Midgard architecture + * specification. + */ + static const std::vector<cmd_t> cmds; +}; + +} + +#endif // _LIBNOMALIMODEL_GPUCONTROL_HH diff --git a/ext/nomali/lib/jobcontrol.cc b/ext/nomali/lib/jobcontrol.cc new file mode 100644 index 000000000..ca4518c09 --- /dev/null +++ b/ext/nomali/lib/jobcontrol.cc @@ -0,0 +1,139 @@ +/* + * 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() +{ +} + +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); +} + +} diff --git a/ext/nomali/lib/jobcontrol.hh b/ext/nomali/lib/jobcontrol.hh new file mode 100644 index 000000000..e0efc04c9 --- /dev/null +++ b/ext/nomali/lib/jobcontrol.hh @@ -0,0 +1,93 @@ +/* + * 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 + */ + +#ifndef _LIBNOMALIMODEL_JOBCONTROL_HH +#define _LIBNOMALIMODEL_JOBCONTROL_HH + +#include <vector> + +#include "gpublock.hh" +#include "jobslot.hh" +#include "types.hh" + +namespace NoMali { + +class GPU; + +/** + * Minimal GPU job control implementation. + * + * This class implements the job control block of a Midgard style + * GPU. The job control block mainly coordinates interrupt delivery + * and register mappings for the different job slots within the + * block. The actual job slots are implemented by the JobSlot class. + * + * @see JobSlot + */ +class JobControl + : public GPUBlockInt +{ + public: + JobControl(GPU &_gpu); + virtual ~JobControl(); + + uint32_t readReg(RegAddr idx) override; + void writeReg(RegAddr idx, uint32_t value) override; + + uint32_t readRegRaw(RegAddr idx) override; + void writeRegRaw(RegAddr idx, uint32_t value) override; + + /** + * Signal job done. + * + * Calling this method raises the job done interrupt for a + * specific job slot. This is typically called from the job slot + * running the job chain. + * + * @param slot Job slot number. + */ + void jobDone(uint8_t slot); + /** + * Signal job failed. + * + * Calling this method raises the job failed interrupt for a + * specific job slot. This is typically called from the job slot + * running the job chain. + * + * @param slot Job slot number. + */ + void jobFailed(uint8_t slot); + + protected: + /** + * Update the state of the job slot state snapshot register. + * + * @param jobs Bit mask representing which job slots to update. + */ + void updateJsState(uint16_t jobs); + + void onInterrupt(int set) override; + + /** Job slots belonging to this job control block */ + std::vector<JobSlot> slots; +}; + +} + +#endif // _LIBNOMALIMODEL_JOBCONTROL_HH diff --git a/ext/nomali/lib/jobslot.cc b/ext/nomali/lib/jobslot.cc new file mode 100644 index 000000000..8ad4fa1ec --- /dev/null +++ b/ext/nomali/lib/jobslot.cc @@ -0,0 +1,216 @@ +/* + * 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 "jobslot.hh" + +#include <cassert> +#include <cstdlib> + +#include "jobcontrol.hh" +#include "gpu.hh" +#include "regutils.hh" + +namespace NoMali { + +const std::vector<JobSlot::cmd_t> JobSlot::cmds { + &JobSlot::cmdNop, // JSn_COMMAND_NOP + &JobSlot::cmdStart, // JSn_COMMAND_START + &JobSlot::cmdSoftStop, // JSn_COMMAND_SOFT_STOP + &JobSlot::cmdHardStop, // JSn_COMMAND_HARD_STOP + &JobSlot::cmdSoftStop0, // JSn_COMMAND_SOFT_STOP_0 + &JobSlot::cmdHardStop0, // JSn_COMMAND_HARD_STOP_0 + &JobSlot::cmdSoftStop1, // JSn_COMMAND_SOFT_STOP_1 + &JobSlot::cmdHardStop1, // JSn_COMMAND_HARD_STOP_1 +}; + +JobSlot::JobSlot(GPU &_gpu, JobControl &_jc, uint8_t _id) + : GPUBlock(_gpu, JSn_NO_REGS), + id(_id), + jc(_jc) +{ +} + +JobSlot::JobSlot(JobSlot &&rhs) + : GPUBlock(std::move(rhs)), + id(std::move(rhs.id)), + jc(rhs.jc) +{ +} + +JobSlot::~JobSlot() +{ +} + +void +JobSlot::writeReg(RegAddr addr, uint32_t value) +{ + switch (addr.value) { + case JSn_COMMAND: + jobCommand(value); + break; + + case JSn_COMMAND_NEXT: + regs[addr] = value; + tryStart(); + break; + + case JSn_HEAD_NEXT_LO: + case JSn_HEAD_NEXT_HI: + case JSn_AFFINITY_NEXT_LO: + case JSn_AFFINITY_NEXT_HI: + case JSn_CONFIG_NEXT: + GPUBlock::writeReg(addr, value); + break; + + default: + // Ignore writes by default + break; + }; +} + +bool +JobSlot::active() const +{ + return false; +} + +bool +JobSlot::activeNext() const +{ + return regs[RegAddr(JSn_COMMAND_NEXT)] == JSn_COMMAND_START; +} + +void +JobSlot::tryStart() +{ + // Only actually start something if the next command is start + if (regs[RegAddr(JSn_COMMAND_NEXT)] != JSn_COMMAND_START ) + return; + + // Reset the status register + regs[RegAddr(JSn_STATUS)] = 0; + + // Transfer the next job configuration to the active job + // configuration + regs.set64(RegAddr(JSn_HEAD_LO), regs.get64(RegAddr(JSn_HEAD_NEXT_LO))); + regs.set64(RegAddr(JSn_TAIL_LO), regs.get64(RegAddr(JSn_HEAD_NEXT_LO))); + regs.set64(RegAddr(JSn_AFFINITY_LO), + regs.get64(RegAddr(JSn_AFFINITY_NEXT_LO))); + regs[RegAddr(JSn_CONFIG)] = regs[RegAddr(JSn_CONFIG_NEXT)]; + regs[RegAddr(JSn_COMMAND)] = regs[RegAddr(JSn_COMMAND_NEXT)]; + + // Reset the next job configuration + regs.set64(RegAddr(JSn_HEAD_NEXT_LO), 0); + regs.set64(RegAddr(JSn_AFFINITY_NEXT_LO), 0); + regs[RegAddr(JSn_CONFIG_NEXT)] = 0; + regs[RegAddr(JSn_COMMAND_NEXT)] = 0; + + runJob(); +} + +void +JobSlot::runJob() +{ + exitJob(Status(Status::CLASS_NOFAULT, 0, 1), // JSn_STATUS_DONE + 0); // Time stamp counter value +} + +void +JobSlot::exitJob(Status status, uint64_t fault_address) +{ + assert(status.statusClass() == Status::CLASS_NOFAULT || + status.statusClass() == Status::CLASS_JOB); + + regs[RegAddr(JSn_STATUS)] = status.value; + + if (status.statusClass() == Status::CLASS_NOFAULT) { + jc.jobDone(id); + } else { + jc.jobFailed(id); + } +} + +void +JobSlot::jobCommand(uint32_t cmd) +{ + if (cmd < cmds.size()) + (this->*cmds[cmd])(cmd); +} + +void +JobSlot::cmdNop(uint32_t cmd) +{ + assert(cmd == JSn_COMMAND_NOP); +} + +void +JobSlot::cmdStart(uint32_t cmd) +{ + assert(cmd == JSn_COMMAND_START); + // The JSn_COMMAND_START should never be issued through the + // JSn_COMMAND register. It should use the JSn_COMMAND_NEXT + // register instead. + abort(); +} + +void +JobSlot::cmdSoftStop(uint32_t cmd) +{ + assert(cmd == JSn_COMMAND_SOFT_STOP || + cmd == JSn_COMMAND_SOFT_STOP_0 || + cmd == JSn_COMMAND_SOFT_STOP_1); +} + +void +JobSlot::cmdHardStop(uint32_t cmd) +{ + assert(cmd == JSn_COMMAND_HARD_STOP || + cmd == JSn_COMMAND_HARD_STOP_0 || + cmd == JSn_COMMAND_HARD_STOP_1); +} + +void +JobSlot::cmdSoftStop0(uint32_t cmd) +{ + if (!(regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG)) + cmdSoftStop(cmd); +} + +void +JobSlot::cmdHardStop0(uint32_t cmd) +{ + if (!(regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG)) + cmdHardStop(cmd); +} + +void +JobSlot::cmdSoftStop1(uint32_t cmd) +{ + if (regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG) + cmdSoftStop(cmd); +} + +void +JobSlot::cmdHardStop1(uint32_t cmd) +{ + if (regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG) + cmdHardStop(cmd); +} + +} diff --git a/ext/nomali/lib/jobslot.hh b/ext/nomali/lib/jobslot.hh new file mode 100644 index 000000000..31b178db2 --- /dev/null +++ b/ext/nomali/lib/jobslot.hh @@ -0,0 +1,208 @@ +/* + * 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 + */ + +#ifndef _LIBNOMALIMODEL_JOBSLOT_HH +#define _LIBNOMALIMODEL_JOBSLOT_HH + +#include <vector> + +#include "gpublock.hh" +#include "types.hh" + +namespace NoMali { + +class GPU; + +class JobControl; + +/** + * Midgard job slot implementation. + * + * A job slot is a part of a JobControl block that controls the state + * of one out of 16 active jobs. Each slot can contain one running job + * and a pending job. + */ +class JobSlot + : public GPUBlock +{ + public: + JobSlot(GPU &_gpu, JobControl &_jc, uint8_t slot_id); + JobSlot(JobSlot &&rhs); + virtual ~JobSlot(); + + void writeReg(RegAddr idx, uint32_t value) override; + + /** Is there an active job in this job slot? */ + bool active() const; + /** Is there a pending next job in this job slot? */ + bool activeNext() const; + + protected: + /** + * @{ + * @name Job Control + */ + + /** + * Try to start the next job in the slot. + * + * Start the next job if the following conditions are true: + * <ul> + * <li>There is no currently running job. + * <li>The pending command in the JSn_COMMAND_NEXT register is + * JSn_COMMAND_START. + * </ul> + * + * When the job is started, the registers describing the next job + * chain are moved (resetting them to zero) into the register + * block describing the currently running job. The job is then run + * by a call to runJob(). + */ + void tryStart(); + + /** + * Execute the job in described by the current job registers. + */ + void runJob(); + + /** + * Report the exit status of an exiting job. + * + * @note The exit status must be of the class + * Status::CLASS_NOFAULT or Status::CLASS_JOB. + * + * @note The fault address isn't always a fault address, it is + * sometimes used to represent a TSC value. See the Midgard + * architecture specification for details. + * + * @param status Job exit status. + * @param fault_address Fault address to write into descriptor. + */ + void exitJob(Status status, uint64_t fault_address); + + /** @} */ + + /** + * @{ + * @name Job slot commands + */ + + /** + * Control command dispatcher. + * + * This method is called whenever there is a write to the + * JSn_COMMAND register. The method uses a lookup table to call + * the right command handling method. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + void jobCommand(uint32_t cmd); + + /** + * Command handler for No-ops. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + void cmdNop(uint32_t cmd); + /** + * Command handler for job start commands. + * + * @note This should <i>NEVER</i> be called as the start command + * should never be written to the JSn_COMMAND register. Jobs are + * normally started by tryStart() whenever the state of the + * currently running job changes or JSn_COMMAND_START is written + * to the JSn_COMMAND_NEXT register. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + void cmdStart(uint32_t cmd); + /** + * Gently stop the currently running job chain. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + void cmdSoftStop(uint32_t cmd); + /** + * Force a stop of the currently running job chain. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + void cmdHardStop(uint32_t cmd); + /** + * Soft stop the current job chain if the JOB_CHAIN_FLAG <i>IS + * NOT</i> set. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + void cmdSoftStop0(uint32_t cmd); + /** + * Hard stop the current job chain if the JOB_CHAIN_FLAG <i>IS + * NOT</i> set. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + void cmdHardStop0(uint32_t cmd); + /** + * Soft stop the current job chain if the JOB_CHAIN_FLAG <i>IS</i> + * set. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + void cmdSoftStop1(uint32_t cmd); + /** + * Hard stop the current job chain if the JOB_CHAIN_FLAG <i>IS</i> + * set. + * + * @param cmd Command number (see the Midgard architecture + * specification) + */ + void cmdHardStop1(uint32_t cmd); + + /** @} */ + + /** Job slot ID */ + const uint8_t id; + + /** Parent JobControl block */ + JobControl &jc; + + private: + typedef void (JobSlot::*cmd_t)(uint32_t); + + /** + * Mapping between command IDs and command handling methods. + * + * @note The order of this vector <i>MUST</i> correspond to the + * job control command IDs in the Midgard architecture + * specification. + */ + static const std::vector<cmd_t> cmds; +}; + +} + +#endif // _LIBNOMALIMODEL_JOBSLOT_HH diff --git a/ext/nomali/lib/mali_midg_regmap.h b/ext/nomali/lib/mali_midg_regmap.h new file mode 100644 index 000000000..90eca9c18 --- /dev/null +++ b/ext/nomali/lib/mali_midg_regmap.h @@ -0,0 +1,510 @@ +/* + * 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. + */ + +#ifndef _MIDGARD_REGMAP_H_ +#define _MIDGARD_REGMAP_H_ + +/* + * Begin Register Offsets + */ + +#define GPU_CONTROL_BASE 0x0000 +#define GPU_CONTROL_REG(r) (GPU_CONTROL_BASE + (r)) +#define GPU_ID 0x000 /* (RO) GPU and revision identifier */ +#define L2_FEATURES 0x004 /* (RO) Level 2 cache features */ +#define L3_FEATURES 0x008 /* (RO) Level 3 cache features */ +#define TILER_FEATURES 0x00C /* (RO) Tiler Features */ +#define MEM_FEATURES 0x010 /* (RO) Memory system features */ +#define MMU_FEATURES 0x014 /* (RO) MMU features */ +#define AS_PRESENT 0x018 /* (RO) Address space slots present */ +#define JS_PRESENT 0x01C /* (RO) Job slots present */ +#define GPU_IRQ_RAWSTAT 0x020 /* (RW) */ +#define GPU_IRQ_CLEAR 0x024 /* (WO) */ +#define GPU_IRQ_MASK 0x028 /* (RW) */ +#define GPU_IRQ_STATUS 0x02C /* (RO) */ + +/* IRQ flags */ +#define GPU_FAULT (1 << 0) /* A GPU Fault has occurred */ +#define MULTIPLE_GPU_FAULTS (1 << 7) /* More than one GPU Fault occurred. */ +#define RESET_COMPLETED (1 << 8) /* Set when a reset has completed. Intended to use with SOFT_RESET + commands which may take time. */ +#define POWER_CHANGED_SINGLE (1 << 9) /* Set when a single core has finished powering up or down. */ +#define POWER_CHANGED_ALL (1 << 10) /* Set when all cores have finished powering up or down + and the power manager is idle. */ + +#define PRFCNT_SAMPLE_COMPLETED (1 << 16) /* Set when a performance count sample has completed. */ +#define CLEAN_CACHES_COMPLETED (1 << 17) /* Set when a cache clean operation has completed. */ + +#define GPU_IRQ_REG_ALL (GPU_FAULT | MULTIPLE_GPU_FAULTS | RESET_COMPLETED \ + | POWER_CHANGED_ALL | PRFCNT_SAMPLE_COMPLETED) + +#define GPU_COMMAND 0x030 /* (WO) */ +#define GPU_STATUS 0x034 /* (RO) */ + +#define GROUPS_L2_COHERENT (1 << 0) /* Cores groups are l2 coherent */ +#define GROUPS_L3_COHERENT (1 << 1) /* Cores groups are l3 coherent */ + +#define GPU_FAULTSTATUS 0x03C /* (RO) GPU exception type and fault status */ +#define GPU_FAULTADDRESS_LO 0x040 /* (RO) GPU exception fault address, low word */ +#define GPU_FAULTADDRESS_HI 0x044 /* (RO) GPU exception fault address, high word */ + +#define PWR_KEY 0x050 /* (WO) Power manager key register */ +#define PWR_OVERRIDE0 0x054 /* (RW) Power manager override settings */ +#define PWR_OVERRIDE1 0x058 /* (RW) Power manager override settings */ + +#define PRFCNT_BASE_LO 0x060 /* (RW) Performance counter memory region base address, low word */ +#define PRFCNT_BASE_HI 0x064 /* (RW) Performance counter memory region base address, high word */ +#define PRFCNT_CONFIG 0x068 /* (RW) Performance counter configuration */ +#define PRFCNT_JM_EN 0x06C /* (RW) Performance counter enable flags for Job Manager */ +#define PRFCNT_SHADER_EN 0x070 /* (RW) Performance counter enable flags for shader cores */ +#define PRFCNT_TILER_EN 0x074 /* (RW) Performance counter enable flags for tiler */ +#define PRFCNT_L3_CACHE_EN 0x078 /* (RW) Performance counter enable flags for L3 cache */ +#define PRFCNT_MMU_L2_EN 0x07C /* (RW) Performance counter enable flags for MMU/L2 cache */ + +#define CYCLE_COUNT_LO 0x090 /* (RO) Cycle counter, low word */ +#define CYCLE_COUNT_HI 0x094 /* (RO) Cycle counter, high word */ +#define TIMESTAMP_LO 0x098 /* (RO) Global time stamp counter, low word */ +#define TIMESTAMP_HI 0x09C /* (RO) Global time stamp counter, high word */ + +#define THREAD_MAX_THREADS 0x0A0 /* (RO) Maximum number of threads per core */ +#define THREAD_MAX_WORKGROUP_SIZE 0x0A4 /* (RO) Maximum workgroup size */ +#define THREAD_MAX_BARRIER_SIZE 0x0A8 /* (RO) Maximum threads waiting at a barrier */ +#define THREAD_FEATURES 0x0AC /* (RO) Thread features */ + +#define TEXTURE_FEATURES_0 0x0B0 /* (RO) Support flags for indexed texture formats 0..31 */ +#define TEXTURE_FEATURES_1 0x0B4 /* (RO) Support flags for indexed texture formats 32..63 */ +#define TEXTURE_FEATURES_2 0x0B8 /* (RO) Support flags for indexed texture formats 64..95 */ + +#define TEXTURE_FEATURES_REG(n) GPU_CONTROL_REG(TEXTURE_FEATURES_0 + ((n) << 2)) + +#define JS0_FEATURES 0x0C0 /* (RO) Features of job slot 0 */ +#define JS1_FEATURES 0x0C4 /* (RO) Features of job slot 1 */ +#define JS2_FEATURES 0x0C8 /* (RO) Features of job slot 2 */ +#define JS3_FEATURES 0x0CC /* (RO) Features of job slot 3 */ +#define JS4_FEATURES 0x0D0 /* (RO) Features of job slot 4 */ +#define JS5_FEATURES 0x0D4 /* (RO) Features of job slot 5 */ +#define JS6_FEATURES 0x0D8 /* (RO) Features of job slot 6 */ +#define JS7_FEATURES 0x0DC /* (RO) Features of job slot 7 */ +#define JS8_FEATURES 0x0E0 /* (RO) Features of job slot 8 */ +#define JS9_FEATURES 0x0E4 /* (RO) Features of job slot 9 */ +#define JS10_FEATURES 0x0E8 /* (RO) Features of job slot 10 */ +#define JS11_FEATURES 0x0EC /* (RO) Features of job slot 11 */ +#define JS12_FEATURES 0x0F0 /* (RO) Features of job slot 12 */ +#define JS13_FEATURES 0x0F4 /* (RO) Features of job slot 13 */ +#define JS14_FEATURES 0x0F8 /* (RO) Features of job slot 14 */ +#define JS15_FEATURES 0x0FC /* (RO) Features of job slot 15 */ + +#define JS_FEATURES_REG(n) GPU_CONTROL_REG(JS0_FEATURES + ((n) << 2)) + +#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */ +#define SHADER_PRESENT_HI 0x104 /* (RO) Shader core present bitmap, high word */ + +#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */ +#define TILER_PRESENT_HI 0x114 /* (RO) Tiler core present bitmap, high word */ + +#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */ +#define L2_PRESENT_HI 0x124 /* (RO) Level 2 cache present bitmap, high word */ + +#define L3_PRESENT_LO 0x130 /* (RO) Level 3 cache present bitmap, low word */ +#define L3_PRESENT_HI 0x134 /* (RO) Level 3 cache present bitmap, high word */ + +#define SHADER_READY_LO 0x140 /* (RO) Shader core ready bitmap, low word */ +#define SHADER_READY_HI 0x144 /* (RO) Shader core ready bitmap, high word */ + +#define TILER_READY_LO 0x150 /* (RO) Tiler core ready bitmap, low word */ +#define TILER_READY_HI 0x154 /* (RO) Tiler core ready bitmap, high word */ + +#define L2_READY_LO 0x160 /* (RO) Level 2 cache ready bitmap, low word */ +#define L2_READY_HI 0x164 /* (RO) Level 2 cache ready bitmap, high word */ + +#define L3_READY_LO 0x170 /* (RO) Level 3 cache ready bitmap, low word */ +#define L3_READY_HI 0x174 /* (RO) Level 3 cache ready bitmap, high word */ + +#define SHADER_PWRON_LO 0x180 /* (WO) Shader core power on bitmap, low word */ +#define SHADER_PWRON_HI 0x184 /* (WO) Shader core power on bitmap, high word */ + +#define TILER_PWRON_LO 0x190 /* (WO) Tiler core power on bitmap, low word */ +#define TILER_PWRON_HI 0x194 /* (WO) Tiler core power on bitmap, high word */ + +#define L2_PWRON_LO 0x1A0 /* (WO) Level 2 cache power on bitmap, low word */ +#define L2_PWRON_HI 0x1A4 /* (WO) Level 2 cache power on bitmap, high word */ + +#define L3_PWRON_LO 0x1B0 /* (WO) Level 3 cache power on bitmap, low word */ +#define L3_PWRON_HI 0x1B4 /* (WO) Level 3 cache power on bitmap, high word */ + +#define SHADER_PWROFF_LO 0x1C0 /* (WO) Shader core power off bitmap, low word */ +#define SHADER_PWROFF_HI 0x1C4 /* (WO) Shader core power off bitmap, high word */ + +#define TILER_PWROFF_LO 0x1D0 /* (WO) Tiler core power off bitmap, low word */ +#define TILER_PWROFF_HI 0x1D4 /* (WO) Tiler core power off bitmap, high word */ + +#define L2_PWROFF_LO 0x1E0 /* (WO) Level 2 cache power off bitmap, low word */ +#define L2_PWROFF_HI 0x1E4 /* (WO) Level 2 cache power off bitmap, high word */ + +#define L3_PWROFF_LO 0x1F0 /* (WO) Level 3 cache power off bitmap, low word */ +#define L3_PWROFF_HI 0x1F4 /* (WO) Level 3 cache power off bitmap, high word */ + +#define SHADER_PWRTRANS_LO 0x200 /* (RO) Shader core power transition bitmap, low word */ +#define SHADER_PWRTRANS_HI 0x204 /* (RO) Shader core power transition bitmap, high word */ + +#define TILER_PWRTRANS_LO 0x210 /* (RO) Tiler core power transition bitmap, low word */ +#define TILER_PWRTRANS_HI 0x214 /* (RO) Tiler core power transition bitmap, high word */ + +#define L2_PWRTRANS_LO 0x220 /* (RO) Level 2 cache power transition bitmap, low word */ +#define L2_PWRTRANS_HI 0x224 /* (RO) Level 2 cache power transition bitmap, high word */ + +#define L3_PWRTRANS_LO 0x230 /* (RO) Level 3 cache power transition bitmap, low word */ +#define L3_PWRTRANS_HI 0x234 /* (RO) Level 3 cache power transition bitmap, high word */ + +#define SHADER_PWRACTIVE_LO 0x240 /* (RO) Shader core active bitmap, low word */ +#define SHADER_PWRACTIVE_HI 0x244 /* (RO) Shader core active bitmap, high word */ + +#define TILER_PWRACTIVE_LO 0x250 /* (RO) Tiler core active bitmap, low word */ +#define TILER_PWRACTIVE_HI 0x254 /* (RO) Tiler core active bitmap, high word */ + +#define L2_PWRACTIVE_LO 0x260 /* (RO) Level 2 cache active bitmap, low word */ +#define L2_PWRACTIVE_HI 0x264 /* (RO) Level 2 cache active bitmap, high word */ + +#define L3_PWRACTIVE_LO 0x270 /* (RO) Level 3 cache active bitmap, low word */ +#define L3_PWRACTIVE_HI 0x274 /* (RO) Level 3 cache active bitmap, high word */ + +#define SHADER_CONFIG 0xF04 /* (RW) Shader core configuration settings (Mali-T60x additional register) */ +#define L2_MMU_CONFIG 0xF0C /* (RW) Configuration of the L2 cache and MMU (Mali-T60x additional register) */ + +#define JOB_CONTROL_BASE 0x1000 + +#define JOB_CONTROL_REG(r) (JOB_CONTROL_BASE + (r)) + +#define JOB_IRQ_RAWSTAT 0x000 /* Raw interrupt status register */ +#define JOB_IRQ_CLEAR 0x004 /* Interrupt clear register */ +#define JOB_IRQ_MASK 0x008 /* Interrupt mask register */ +#define JOB_IRQ_STATUS 0x00C /* Interrupt status register */ +#define JOB_IRQ_JS_STATE 0x010 /* status==active and _next == busy snapshot from last JOB_IRQ_CLEAR */ +#define JOB_IRQ_THROTTLE 0x014 /* cycles to delay delivering an interrupt externally. The JOB_IRQ_STATUS is NOT affected by this, just the delivery of the interrupt. */ + +#define JOB_SLOT0 0x800 /* Configuration registers for job slot 0 */ +#define JOB_SLOT1 0x880 /* Configuration registers for job slot 1 */ +#define JOB_SLOT2 0x900 /* Configuration registers for job slot 2 */ +#define JOB_SLOT3 0x980 /* Configuration registers for job slot 3 */ +#define JOB_SLOT4 0xA00 /* Configuration registers for job slot 4 */ +#define JOB_SLOT5 0xA80 /* Configuration registers for job slot 5 */ +#define JOB_SLOT6 0xB00 /* Configuration registers for job slot 6 */ +#define JOB_SLOT7 0xB80 /* Configuration registers for job slot 7 */ +#define JOB_SLOT8 0xC00 /* Configuration registers for job slot 8 */ +#define JOB_SLOT9 0xC80 /* Configuration registers for job slot 9 */ +#define JOB_SLOT10 0xD00 /* Configuration registers for job slot 10 */ +#define JOB_SLOT11 0xD80 /* Configuration registers for job slot 11 */ +#define JOB_SLOT12 0xE00 /* Configuration registers for job slot 12 */ +#define JOB_SLOT13 0xE80 /* Configuration registers for job slot 13 */ +#define JOB_SLOT14 0xF00 /* Configuration registers for job slot 14 */ +#define JOB_SLOT15 0xF80 /* Configuration registers for job slot 15 */ + +#define JOB_SLOT_REG(n, r) (JOB_CONTROL_REG(JOB_SLOT0 + ((n) << 7)) + (r)) + +#define JSn_HEAD_LO 0x00 /* (RO) Job queue head pointer for job slot n, low word */ +#define JSn_HEAD_HI 0x04 /* (RO) Job queue head pointer for job slot n, high word */ +#define JSn_TAIL_LO 0x08 /* (RO) Job queue tail pointer for job slot n, low word */ +#define JSn_TAIL_HI 0x0C /* (RO) Job queue tail pointer for job slot n, high word */ +#define JSn_AFFINITY_LO 0x10 /* (RO) Core affinity mask for job slot n, low word */ +#define JSn_AFFINITY_HI 0x14 /* (RO) Core affinity mask for job slot n, high word */ +#define JSn_CONFIG 0x18 /* (RO) Configuration settings for job slot n */ + +#define JSn_COMMAND 0x20 /* (WO) Command register for job slot n */ +#define JSn_STATUS 0x24 /* (RO) Status register for job slot n */ + +#define JSn_HEAD_NEXT_LO 0x40 /* (RW) Next job queue head pointer for job slot n, low word */ +#define JSn_HEAD_NEXT_HI 0x44 /* (RW) Next job queue head pointer for job slot n, high word */ + +#define JSn_AFFINITY_NEXT_LO 0x50 /* (RW) Next core affinity mask for job slot n, low word */ +#define JSn_AFFINITY_NEXT_HI 0x54 /* (RW) Next core affinity mask for job slot n, high word */ +#define JSn_CONFIG_NEXT 0x58 /* (RW) Next configuration settings for job slot n */ + +#define JSn_COMMAND_NEXT 0x60 /* (RW) Next command register for job slot n */ + +#define MEMORY_MANAGEMENT_BASE 0x2000 +#define MMU_REG(r) (MEMORY_MANAGEMENT_BASE + (r)) + +#define MMU_IRQ_RAWSTAT 0x000 /* (RW) Raw interrupt status register */ +#define MMU_IRQ_CLEAR 0x004 /* (WO) Interrupt clear register */ +#define MMU_IRQ_MASK 0x008 /* (RW) Interrupt mask register */ +#define MMU_IRQ_STATUS 0x00C /* (RO) Interrupt status register */ + +#define MMU_AS0 0x400 /* Configuration registers for address space 0 */ +#define MMU_AS1 0x440 /* Configuration registers for address space 1 */ +#define MMU_AS2 0x480 /* Configuration registers for address space 2 */ +#define MMU_AS3 0x4C0 /* Configuration registers for address space 3 */ +#define MMU_AS4 0x500 /* Configuration registers for address space 4 */ +#define MMU_AS5 0x540 /* Configuration registers for address space 5 */ +#define MMU_AS6 0x580 /* Configuration registers for address space 6 */ +#define MMU_AS7 0x5C0 /* Configuration registers for address space 7 */ +#define MMU_AS8 0x600 /* Configuration registers for address space 8 */ +#define MMU_AS9 0x640 /* Configuration registers for address space 9 */ +#define MMU_AS10 0x680 /* Configuration registers for address space 10 */ +#define MMU_AS11 0x6C0 /* Configuration registers for address space 11 */ +#define MMU_AS12 0x700 /* Configuration registers for address space 12 */ +#define MMU_AS13 0x740 /* Configuration registers for address space 13 */ +#define MMU_AS14 0x780 /* Configuration registers for address space 14 */ +#define MMU_AS15 0x7C0 /* Configuration registers for address space 15 */ + +#define MMU_AS_REG(n, r) (MMU_REG(MMU_AS0 + ((n) << 6)) + (r)) + +#define ASn_TRANSTAB_LO 0x00 /* (RW) Translation Table Base Address for address space n, low word */ +#define ASn_TRANSTAB_HI 0x04 /* (RW) Translation Table Base Address for address space n, high word */ +#define ASn_MEMATTR_LO 0x08 /* (RW) Memory attributes for address space n, low word. */ +#define ASn_MEMATTR_HI 0x0C /* (RW) Memory attributes for address space n, high word. */ +#define ASn_LOCKADDR_LO 0x10 /* (RW) Lock region address for address space n, low word */ +#define ASn_LOCKADDR_HI 0x14 /* (RW) Lock region address for address space n, high word */ +#define ASn_COMMAND 0x18 /* (WO) MMU command register for address space n */ +#define ASn_FAULTSTATUS 0x1C /* (RO) MMU fault status register for address space n */ +#define ASn_FAULTADDRESS_LO 0x20 /* (RO) Fault Address for address space n, low word */ +#define ASn_FAULTADDRESS_HI 0x24 /* (RO) Fault Address for address space n, high word */ +#define ASn_STATUS 0x28 /* (RO) Status flags for address space n */ + +/* End Register Offsets */ + +/* + * MMU_IRQ_RAWSTAT register values. Values are valid also for + MMU_IRQ_CLEAR, MMU_IRQ_MASK, MMU_IRQ_STATUS registers. + */ + +#define MMU_REGS_PAGE_FAULT_FLAGS 16 + +/* Macros return bit number to retrvie page fault or bus eror flag from MMU registers */ +#define MMU_REGS_PAGE_FAULT_FLAG(n) (n) +#define MMU_REGS_BUS_ERROR_FLAG(n) (n + MMU_REGS_PAGE_FAULT_FLAGS) + +/* + * Begin MMU TRANSTAB register values + */ +#define ASn_TRANSTAB_ADDR_SPACE_MASK 0xfffff000 +#define ASn_TRANSTAB_ADRMODE_UNMAPPED (0u << 0) +#define ASn_TRANSTAB_ADRMODE_IDENTITY (1u << 1) +#define ASn_TRANSTAB_ADRMODE_TABLE (3u << 0) +#define ASn_TRANSTAB_READ_INNER (1u << 2) +#define ASn_TRANSTAB_SHARE_OUTER (1u << 4) + +#define MMU_TRANSTAB_ADRMODE_MASK 0x00000003 + +/* + * Begin MMU STATUS register values + */ +#define ASn_STATUS_FLUSH_ACTIVE 0x01 + +#define ASn_FAULTSTATUS_ACCESS_TYPE_MASK (0x3<<8) +#define ASn_FAULTSTATUS_ACCESS_TYPE_EX (0x1<<8) +#define ASn_FAULTSTATUS_ACCESS_TYPE_READ (0x2<<8) +#define ASn_FAULTSTATUS_ACCESS_TYPE_WRITE (0x3<<8) + +/* + * Begin Command Values + */ + +/* JSn_COMMAND register commands */ +#define JSn_COMMAND_NOP 0x00 /* NOP Operation. Writing this value is ignored */ +#define JSn_COMMAND_START 0x01 /* Start processing a job chain. Writing this value is ignored */ +#define JSn_COMMAND_SOFT_STOP 0x02 /* Gently stop processing a job chain */ +#define JSn_COMMAND_HARD_STOP 0x03 /* Rudely stop processing a job chain */ +#define JSn_COMMAND_SOFT_STOP_0 0x04 /* Execute SOFT_STOP if JOB_CHAIN_FLAG is 0 */ +#define JSn_COMMAND_HARD_STOP_0 0x05 /* Execute HARD_STOP if JOB_CHAIN_FLAG is 0 */ +#define JSn_COMMAND_SOFT_STOP_1 0x06 /* Execute SOFT_STOP if JOB_CHAIN_FLAG is 1 */ +#define JSn_COMMAND_HARD_STOP_1 0x07 /* Execute HARD_STOP if JOB_CHAIN_FLAG is 1 */ + +/* ASn_COMMAND register commands */ +#define ASn_COMMAND_NOP 0x00 /* NOP Operation */ +#define ASn_COMMAND_UPDATE 0x01 /* Broadcasts the values in ASn_TRANSTAB and ASn_MEMATTR to all MMUs */ +#define ASn_COMMAND_LOCK 0x02 /* Issue a lock region command to all MMUs */ +#define ASn_COMMAND_UNLOCK 0x03 /* Issue a flush region command to all MMUs */ +#define ASn_COMMAND_FLUSH 0x04 /* Flush all L2 caches then issue a flush region command to all MMUs + (deprecated - only for use with T60x) */ +#define ASn_COMMAND_FLUSH_PT 0x04 /* Flush all L2 caches then issue a flush region command to all MMUs */ +#define ASn_COMMAND_FLUSH_MEM 0x05 /* Wait for memory accesses to complete, flush all the L1s cache then + flush all L2 caches then issue a flush region command to all MMUs */ + +/* Possible values of JSn_CONFIG and JSn_CONFIG_NEXT registers */ +#define JSn_CONFIG_START_FLUSH_NO_ACTION (0u << 0) +#define JSn_CONFIG_START_FLUSH_CLEAN (1u << 8) +#define JSn_CONFIG_START_FLUSH_CLEAN_INVALIDATE (3u << 8) +#define JSn_CONFIG_START_MMU (1u << 10) +#define JSn_CONFIG_JOB_CHAIN_FLAG (1u << 11) +#define JSn_CONFIG_END_FLUSH_NO_ACTION JSn_CONFIG_START_FLUSH_NO_ACTION +#define JSn_CONFIG_END_FLUSH_CLEAN (1u << 12) +#define JSn_CONFIG_END_FLUSH_CLEAN_INVALIDATE (3u << 12) +#define JSn_CONFIG_THREAD_PRI(n) ((n) << 16) + +/* JSn_STATUS register values */ + +/* NOTE: Please keep this values in sync with enum base_jd_event_code in mali_base_kernel.h. + * The values are separated to avoid dependency of userspace and kernel code. + */ + +/* Group of values representing the job status insead a particular fault */ +#define JSn_STATUS_NO_EXCEPTION_BASE 0x00 +#define JSn_STATUS_INTERRUPTED (JSn_STATUS_NO_EXCEPTION_BASE + 0x02) /* 0x02 means INTERRUPTED */ +#define JSn_STATUS_STOPPED (JSn_STATUS_NO_EXCEPTION_BASE + 0x03) /* 0x03 means STOPPED */ +#define JSn_STATUS_TERMINATED (JSn_STATUS_NO_EXCEPTION_BASE + 0x04) /* 0x04 means TERMINATED */ + +/* General fault values */ +#define JSn_STATUS_FAULT_BASE 0x40 +#define JSn_STATUS_CONFIG_FAULT (JSn_STATUS_FAULT_BASE) /* 0x40 means CONFIG FAULT */ +#define JSn_STATUS_POWER_FAULT (JSn_STATUS_FAULT_BASE + 0x01) /* 0x41 means POWER FAULT */ +#define JSn_STATUS_READ_FAULT (JSn_STATUS_FAULT_BASE + 0x02) /* 0x42 means READ FAULT */ +#define JSn_STATUS_WRITE_FAULT (JSn_STATUS_FAULT_BASE + 0x03) /* 0x43 means WRITE FAULT */ +#define JSn_STATUS_AFFINITY_FAULT (JSn_STATUS_FAULT_BASE + 0x04) /* 0x44 means AFFINITY FAULT */ +#define JSn_STATUS_BUS_FAULT (JSn_STATUS_FAULT_BASE + 0x08) /* 0x48 means BUS FAULT */ + +/* Instruction or data faults */ +#define JSn_STATUS_INSTRUCTION_FAULT_BASE 0x50 +#define JSn_STATUS_INSTR_INVALID_PC (JSn_STATUS_INSTRUCTION_FAULT_BASE) /* 0x50 means INSTR INVALID PC */ +#define JSn_STATUS_INSTR_INVALID_ENC (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x01) /* 0x51 means INSTR INVALID ENC */ +#define JSn_STATUS_INSTR_TYPE_MISMATCH (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x02) /* 0x52 means INSTR TYPE MISMATCH */ +#define JSn_STATUS_INSTR_OPERAND_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x03) /* 0x53 means INSTR OPERAND FAULT */ +#define JSn_STATUS_INSTR_TLS_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x04) /* 0x54 means INSTR TLS FAULT */ +#define JSn_STATUS_INSTR_BARRIER_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x05) /* 0x55 means INSTR BARRIER FAULT */ +#define JSn_STATUS_INSTR_ALIGN_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x06) /* 0x56 means INSTR ALIGN FAULT */ +/* NOTE: No fault with 0x57 code defined in spec. */ +#define JSn_STATUS_DATA_INVALID_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x08) /* 0x58 means DATA INVALID FAULT */ +#define JSn_STATUS_TILE_RANGE_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x09) /* 0x59 means TILE RANGE FAULT */ +#define JSn_STATUS_ADDRESS_RANGE_FAULT (JSn_STATUS_INSTRUCTION_FAULT_BASE + 0x0A) /* 0x5A means ADDRESS RANGE FAULT */ + +/* Other faults */ +#define JSn_STATUS_MEMORY_FAULT_BASE 0x60 +#define JSn_STATUS_OUT_OF_MEMORY (JSn_STATUS_MEMORY_FAULT_BASE) /* 0x60 means OUT OF MEMORY */ +#define JSn_STATUS_UNKNOWN 0x7F /* 0x7F means UNKNOWN */ + +/* GPU_COMMAND values */ +#define GPU_COMMAND_NOP 0x00 /* No operation, nothing happens */ +#define GPU_COMMAND_SOFT_RESET 0x01 /* Stop all external bus interfaces, and then reset the entire GPU. */ +#define GPU_COMMAND_HARD_RESET 0x02 /* Immediately reset the entire GPU. */ +#define GPU_COMMAND_PRFCNT_CLEAR 0x03 /* Clear all performance counters, setting them all to zero. */ +#define GPU_COMMAND_PRFCNT_SAMPLE 0x04 /* Sample all performance counters, writing them out to memory */ +#define GPU_COMMAND_CYCLE_COUNT_START 0x05 /* Starts the cycle counter, and system timestamp propagation */ +#define GPU_COMMAND_CYCLE_COUNT_STOP 0x06 /* Stops the cycle counter, and system timestamp propagation */ +#define GPU_COMMAND_CLEAN_CACHES 0x07 /* Clean all caches */ +#define GPU_COMMAND_CLEAN_INV_CACHES 0x08 /* Clean and invalidate all caches */ + +/* End Command Values */ + +/* GPU_STATUS values */ +#define GPU_STATUS_PRFCNT_ACTIVE (1 << 2) /* Set if the performance counters are active. */ + +/* PRFCNT_CONFIG register values */ +#define PRFCNT_CONFIG_AS_SHIFT 4 /* address space bitmap starts from bit 4 of the register */ +#define PRFCNT_CONFIG_MODE_OFF 0 /* The performance counters are disabled. */ +#define PRFCNT_CONFIG_MODE_MANUAL 1 /* The performance counters are enabled, but are only written out when a PRFCNT_SAMPLE command is issued using the GPU_COMMAND register. */ +#define PRFCNT_CONFIG_MODE_TILE 2 /* The performance counters are enabled, and are written out each time a tile finishes rendering. */ + +/* AS<n>_MEMATTR values: */ +/* Use GPU implementation-defined caching policy. */ +#define ASn_MEMATTR_IMPL_DEF_CACHE_POLICY 0x48 +/* The attribute set to force all resources to be cached. */ +#define ASn_MEMATTR_FORCE_TO_CACHE_ALL 0x4F +/* Inner write-alloc cache setup, no outer caching */ +#define ASn_MEMATTR_WRITE_ALLOC 0x4D +/* symbol for default MEMATTR to use */ +#define ASn_MEMATTR_INDEX_DEFAULT 0 +/* HW implementation defined caching */ +#define ASn_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY 0 +/* Force cache on */ +#define ASn_MEMATTR_INDEX_FORCE_TO_CACHE_ALL 1 +/* Write-alloc inner */ +#define ASn_MEMATTR_INDEX_WRITE_ALLOC 2 + +/* GPU_ID register */ +#define GPU_ID_VERSION_STATUS_SHIFT 0 +#define GPU_ID_VERSION_MINOR_SHIFT 4 +#define GPU_ID_VERSION_MAJOR_SHIFT 12 +#define GPU_ID_VERSION_PRODUCT_ID_SHIFT 16 +#define GPU_ID_VERSION_STATUS (0xF << GPU_ID_VERSION_STATUS_SHIFT) +#define GPU_ID_VERSION_MINOR (0xFF << GPU_ID_VERSION_MINOR_SHIFT) +#define GPU_ID_VERSION_MAJOR (0xF << GPU_ID_VERSION_MAJOR_SHIFT) +#define GPU_ID_VERSION_PRODUCT_ID (0xFFFF << GPU_ID_VERSION_PRODUCT_ID_SHIFT) + +/* Values for GPU_ID_VERSION_PRODUCT_ID bitfield */ +#define GPU_ID_PI_T60X 0x6956 +#define GPU_ID_PI_T62X 0x0620 +#define GPU_ID_PI_T76X 0x0750 +#define GPU_ID_PI_T72X 0x0720 + +/* Values for GPU_ID_VERSION_STATUS field for PRODUCT_ID GPU_ID_PI_T60X */ +#define GPU_ID_S_15DEV0 0x1 +#define GPU_ID_S_EAC 0x2 + +/* Helper macro to create a GPU_ID assuming valid values for id, major, minor, status */ +#define GPU_ID_MAKE(id, major, minor, status) \ + (((id) << GPU_ID_VERSION_PRODUCT_ID_SHIFT) | \ + ((major) << GPU_ID_VERSION_MAJOR_SHIFT) | \ + ((minor) << GPU_ID_VERSION_MINOR_SHIFT) | \ + ((status) << GPU_ID_VERSION_STATUS_SHIFT)) + +/* End GPU_ID register */ + +/* JS<n>_FEATURES register */ + +#define JSn_FEATURE_NULL_JOB (1u << 1) +#define JSn_FEATURE_SET_VALUE_JOB (1u << 2) +#define JSn_FEATURE_CACHE_FLUSH_JOB (1u << 3) +#define JSn_FEATURE_COMPUTE_JOB (1u << 4) +#define JSn_FEATURE_VERTEX_JOB (1u << 5) +#define JSn_FEATURE_GEOMETRY_JOB (1u << 6) +#define JSn_FEATURE_TILER_JOB (1u << 7) +#define JSn_FEATURE_FUSED_JOB (1u << 8) +#define JSn_FEATURE_FRAGMENT_JOB (1u << 9) + +/* End JS<n>_FEATURES register */ + +/* L2_MMU_CONFIG register */ +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT (24) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_OCTANT (0x1 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_QUARTER (0x2 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_HALF (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) + +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT (26) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_OCTANT (0x1 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_QUARTER (0x2 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_HALF (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +/* End L2_MMU_CONFIG register */ + +/* THREAD_* registers */ + +/* THREAD_FEATURES IMPLEMENTATION_TECHNOLOGY values */ +#define IMPLEMENTATION_UNSPECIFIED 0 +#define IMPLEMENTATION_SILICON 1 +#define IMPLEMENTATION_FPGA 2 +#define IMPLEMENTATION_MODEL 3 + +/* Default values when registers are not supported by the implemented hardware */ +#define THREAD_MT_DEFAULT 256 +#define THREAD_MWS_DEFAULT 256 +#define THREAD_MBS_DEFAULT 256 +#define THREAD_MR_DEFAULT 1024 +#define THREAD_MTQ_DEFAULT 4 +#define THREAD_MTGS_DEFAULT 10 + +/* End THREAD_* registers */ + +/* SHADER_CONFIG register */ + +#define SC_ALT_COUNTERS (1ul << 3) +#define SC_OVERRIDE_FWD_PIXEL_KILL (1ul << 4) +#define SC_SDC_DISABLE_OQ_DISCARD (1ul << 6) +#define SC_LS_PAUSEBUFFER_DISABLE (1ul << 16) +#define SC_ENABLE_TEXGRD_FLAGS (1ul << 25) +/* End SHADER_CONFIG register */ + +#endif /* _MIDGARD_REGMAP_H_ */ diff --git a/ext/nomali/lib/mali_midgard.cc b/ext/nomali/lib/mali_midgard.cc new file mode 100644 index 000000000..fe35f1259 --- /dev/null +++ b/ext/nomali/lib/mali_midgard.cc @@ -0,0 +1,92 @@ +/* + * 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 "mali_midgard.hh" + +#include "regutils.hh" + +namespace NoMali { + +MaliMidgard::MaliMidgard(unsigned gpuType, + unsigned major, unsigned minor, unsigned status) + : MaliMidgard(GPU_ID_MAKE(gpuType, major, minor, status)) +{ +} + +MaliMidgard::MaliMidgard(uint32_t _gpuId) + : GPU(gpuControl, jobControl, mmu), + gpuControl(*this), + jobControl(*this), + mmu(*this), + gpuId(_gpuId) +{ +} + +MaliMidgard::~MaliMidgard() +{ +} + +void +MaliMidgard::setupControlIdRegisters(RegVector ®s) +{ + regs[RegAddr(L2_FEATURES)] = + (0x07 << 24) | // lg2 ext bus width + (0x13 << 16) | // lg2 cache size + (0x02 << 8) | // lg2 associativity + (0x06); // lg2 line size + + regs[RegAddr(TILER_FEATURES)] = + (0x8 << 8) | // Maximum no active hierarchy levels + 0x09; // lg2 bin size + + /* Coherent core group, but incoherent supergroup. 1 L2 slice. */ + regs[RegAddr(MEM_FEATURES)] = 0x1; + + regs[RegAddr(MMU_FEATURES)] = 0x2830; + regs[RegAddr(AS_PRESENT)] = 0xff; + regs[RegAddr(JS_PRESENT)] = 0x7; + regs[RegAddr(JS0_FEATURES)] = 0x20e; + regs[RegAddr(JS1_FEATURES)] = 0x1fe; + regs[RegAddr(JS2_FEATURES)] = 0x7e; + + regs[RegAddr(TEXTURE_FEATURES_0)] = 0x00fe001e; + regs[RegAddr(TEXTURE_FEATURES_1)] = 0xffff; + regs[RegAddr(TEXTURE_FEATURES_2)] = 0x9f81ffff; + + regs[RegAddr(THREAD_MAX_THREADS)] = 0x100; + regs[RegAddr(THREAD_MAX_WORKGROUP_SIZE)] = 0x100; + regs[RegAddr(THREAD_MAX_BARRIER_SIZE)] = 0x100; + regs[RegAddr(THREAD_FEATURES)] = 0x0a040400; + + regs.set64(RegAddr(SHADER_PRESENT_LO), 0xf); + regs.set64(RegAddr(TILER_PRESENT_LO), 0x1); + regs.set64(RegAddr(L2_PRESENT_LO), 0x1); +} + +void +MaliMidgard::GPUControlSpec::reset() +{ + GPUControl::reset(); + + regs[RegAddr(GPU_ID)] = midgard.gpuId; + + midgard.setupControlIdRegisters(regs); +} + +}; diff --git a/ext/nomali/lib/mali_midgard.hh b/ext/nomali/lib/mali_midgard.hh new file mode 100644 index 000000000..1030b3f49 --- /dev/null +++ b/ext/nomali/lib/mali_midgard.hh @@ -0,0 +1,70 @@ +/* + * 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 + */ + +#ifndef _LIBNOMALIMODEL_MALI_MIDGARD_HH +#define _LIBNOMALIMODEL_MALI_MIDGARD_HH + +#include "gpu.hh" + +#include "gpucontrol.hh" +#include "jobcontrol.hh" +#include "mmu.hh" + +namespace NoMali { + +/** + * Base class for Midgard based GPUs + */ +class MaliMidgard + : public GPU +{ + public: + MaliMidgard(unsigned gpuType, + unsigned major, unsigned minor, unsigned status); + MaliMidgard(uint32_t gpuId); + virtual ~MaliMidgard(); + + + protected: + class GPUControlSpec + : public GPUControl + { + public: + GPUControlSpec(MaliMidgard &_gpu) + : GPUControl(_gpu), midgard(_gpu) {} + + void reset() override; + + private: + MaliMidgard &midgard; + }; + + virtual void setupControlIdRegisters(RegVector ®s); + + GPUControlSpec gpuControl; + JobControl jobControl; + MMU mmu; + + private: + const uint32_t gpuId; +}; + +} + +#endif // _LIBNOMALIMODEL_MALI_MIDGARD_HH diff --git a/ext/nomali/lib/mali_t6xx.cc b/ext/nomali/lib/mali_t6xx.cc new file mode 100644 index 000000000..4d8221346 --- /dev/null +++ b/ext/nomali/lib/mali_t6xx.cc @@ -0,0 +1,55 @@ +/* + * 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 "mali_t6xx.hh" + +#include "regutils.hh" + +namespace NoMali { + +MaliT6xxBase::MaliT6xxBase(unsigned gpuType, + unsigned major, unsigned minor, unsigned status) + : MaliMidgard(gpuType, major, minor, status) +{ +} + +void +MaliT6xxBase::setupControlIdRegisters(RegVector ®s) +{ + MaliMidgard::setupControlIdRegisters(regs); + + regs[RegAddr(L2_FEATURES)] = + (0x06 << 24) | // lg2 ext bus width + (0x10 << 16) | // lg2 cache size + (0x02 << 8) | // lg2 associativity + (0x06); // lg2 line size +} + + +MaliT60x::MaliT60x(unsigned major, unsigned minor, unsigned status) + : MaliT6xxBase(GPU_ID_PI_T60X, major, minor, status) +{ +} + +MaliT62x::MaliT62x(unsigned major, unsigned minor, unsigned status) + : MaliT6xxBase(GPU_ID_PI_T62X, major, minor, status) +{ +} + +}; diff --git a/ext/nomali/lib/mali_t6xx.hh b/ext/nomali/lib/mali_t6xx.hh new file mode 100644 index 000000000..b8e997659 --- /dev/null +++ b/ext/nomali/lib/mali_t6xx.hh @@ -0,0 +1,61 @@ +/* + * 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 + */ + +#ifndef _LIBNOMALIMODEL_MALI_T7XX_HH +#define _LIBNOMALIMODEL_MALI_T7XX_HH + +#include "mali_midgard.hh" + +namespace NoMali { + +class MaliT6xxBase + : public MaliMidgard +{ + public: + MaliT6xxBase(unsigned gpuType, + unsigned major, unsigned minor, unsigned status); + + protected: + void setupControlIdRegisters(RegVector ®s) override; +}; + + +/** + * Simple NoMali implementation of the Mali T60x + */ +class MaliT60x + : public MaliT6xxBase +{ + public: + MaliT60x(unsigned major, unsigned minor, unsigned status); +}; + +/** + * Simple NoMali implementation of the Mali T62x + */ +class MaliT62x + : public MaliT6xxBase +{ + public: + MaliT62x(unsigned major, unsigned minor, unsigned status); +}; + +} + +#endif // _LIBNOMALIMODEL_MALI_T7XX_HH diff --git a/ext/nomali/lib/mali_t7xx.cc b/ext/nomali/lib/mali_t7xx.cc new file mode 100644 index 000000000..33f3b6b24 --- /dev/null +++ b/ext/nomali/lib/mali_t7xx.cc @@ -0,0 +1,50 @@ +/* + * 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 "mali_t7xx.hh" + +#include "regutils.hh" + +namespace NoMali { + +MaliT7xxBase::MaliT7xxBase(unsigned gpuType, + unsigned major, unsigned minor, unsigned status) + : MaliMidgard(gpuType, major, minor, status) +{ +} + +void +MaliT7xxBase::setupControlIdRegisters(RegVector ®s) +{ + MaliMidgard::setupControlIdRegisters(regs); + + regs[RegAddr(L2_FEATURES)] = + (0x07 << 24) | // lg2 ext bus width + (0x13 << 16) | // lg2 cache size + (0x02 << 8) | // lg2 associativity + (0x06); // lg2 line size +} + + +MaliT76x::MaliT76x(unsigned major, unsigned minor, unsigned status) + : MaliT7xxBase(GPU_ID_PI_T76X, major, minor, status) +{ +} + +}; diff --git a/ext/nomali/lib/mali_t7xx.hh b/ext/nomali/lib/mali_t7xx.hh new file mode 100644 index 000000000..3ea5d7074 --- /dev/null +++ b/ext/nomali/lib/mali_t7xx.hh @@ -0,0 +1,50 @@ +/* + * 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 + */ + +#ifndef _LIBNOMALIMODEL_MALIT_T7XX_HH +#define _LIBNOMALIMODEL_MALIT_T7XX_HH + +#include "mali_midgard.hh" + +namespace NoMali { + +class MaliT7xxBase + : public MaliMidgard +{ + public: + MaliT7xxBase(unsigned gpuType, + unsigned major, unsigned minor, unsigned status); + + protected: + void setupControlIdRegisters(RegVector ®s) override; +}; + +/** + * Simple NoMali implementation of the Mali T76x + */ +class MaliT76x + : public MaliT7xxBase +{ + public: + MaliT76x(unsigned major, unsigned minor, unsigned status); +}; + +} + +#endif // _LIBNOMALIMODEL_MALI_T7XX_HH diff --git a/ext/nomali/lib/mmu.cc b/ext/nomali/lib/mmu.cc new file mode 100644 index 000000000..2d166b5af --- /dev/null +++ b/ext/nomali/lib/mmu.cc @@ -0,0 +1,64 @@ +/* + * 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 "mmu.hh" + +#include "gpu.hh" +#include "regutils.hh" + +namespace NoMali { + +MMU::MMU(GPU &_gpu) + : GPUBlockInt(_gpu, + RegAddr(MMU_IRQ_RAWSTAT), + RegAddr(MMU_IRQ_CLEAR), + RegAddr(MMU_IRQ_MASK), + RegAddr(MMU_IRQ_STATUS)), + regs(BLOCK_NUM_REGS) +{ +} + +MMU::~MMU() +{ +} + +void +MMU::writeReg(RegAddr addr, uint32_t value) +{ + switch (addr.value) { + case MMU_IRQ_RAWSTAT: + case MMU_IRQ_CLEAR: + case MMU_IRQ_MASK: + case MMU_IRQ_STATUS: + GPUBlockInt::writeReg(addr, value); + break; + + default: + // Ignore writes by default + break; + }; +} + +void +MMU::onInterrupt(int set) +{ + gpu.intMMU(set); +} + +} diff --git a/ext/nomali/lib/mmu.hh b/ext/nomali/lib/mmu.hh new file mode 100644 index 000000000..82864a6ff --- /dev/null +++ b/ext/nomali/lib/mmu.hh @@ -0,0 +1,57 @@ +/* + * 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 + */ + +#ifndef _LIBNOMALIMODEL_MMU_HH +#define _LIBNOMALIMODEL_MMU_HH + +#include <vector> + +#include "gpublock.hh" +#include "types.hh" + +namespace NoMali { + +class GPU; + +/** + * MMU dummy implementation. + * + * This is a dummy implementation of a Midgard GPU MMU block. The only + * features supported by the block is interrupt delivery and registers + * related to interrupt delivery. Writes to unimplemented registers + * (most registers) are discarded and their values are read as zero. + */ +class MMU + : public GPUBlockInt +{ + public: + MMU(GPU &_gpu); + virtual ~MMU(); + + void writeReg(RegAddr idx, uint32_t value) override; + + protected: + void onInterrupt(int set) override; + + RegVector regs; +}; + +} + +#endif // _LIBNOMALIMODEL_MMU_HH diff --git a/ext/nomali/lib/nomali_api.cc b/ext/nomali/lib/nomali_api.cc new file mode 100644 index 000000000..46f0e7fce --- /dev/null +++ b/ext/nomali/lib/nomali_api.cc @@ -0,0 +1,355 @@ +/* + * 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 "libnomali/nomali.h" + +#include <cstring> + +#include "mali_t6xx.hh" +#include "mali_t7xx.hh" + +#define EXPORT __attribute__ ((visibility ("default"))) + +static const char *errstrs[] = { + "No error", + "Unknown error", + "Memory allocation failed", + "Invalid model handle", + "Invalid parameter", +}; + +static_assert(sizeof(errstrs) / sizeof(*errstrs) == NOMALI_E_NUM_ERRORS, + "NoMali API error descriptions out of sync!"); + +class NoMaliApi +{ + public: + NoMaliApi(); + ~NoMaliApi(); + + void setGpu(NoMali::GPU *gpu) { _gpu = gpu; } + + public: + nomali_error_t setCallback(const nomali_callback_t *callback); + + nomali_error_t getInfo(nomali_info_t *info); + + nomali_error_t reset(); + nomali_error_t regRead(uint32_t *value, nomali_addr_t addr); + nomali_error_t regWrite(nomali_addr_t addr, uint32_t value); + nomali_error_t regReadRaw(uint32_t *value, nomali_addr_t addr); + nomali_error_t regWriteRaw(nomali_addr_t addr, uint32_t value); + nomali_error_t intState(int *state, nomali_int_t intno) const; + + public: + void callbackInt(nomali_int_t intno, int set); + + private: + nomali_callback_t callbacks[NOMALI_CALLBACK_NUM_CALLBACKS]; + + NoMali::GPU *_gpu; +}; + +template<class BaseGpu> +class NoMaliApiGpu + : public BaseGpu +{ + public: + template<typename... Args> + NoMaliApiGpu(NoMaliApi &_api, Args &&... args) + : BaseGpu(std::forward<Args>(args)...), + api(_api) + { + BaseGpu::reset(); + } + + public: + void intJob(int set) override { api.callbackInt(NOMALI_INT_JOB, set); } + void intMMU(int set) override { api.callbackInt(NOMALI_INT_MMU, set); } + void intGPU(int set) override { api.callbackInt(NOMALI_INT_GPU, set); } + + private: + NoMaliApi &api; +}; + + +NoMaliApi::NoMaliApi() + : _gpu(nullptr) +{ + memset(callbacks, 0, sizeof(callbacks)); +} + + +NoMaliApi::~NoMaliApi() +{ +} + +nomali_error_t +NoMaliApi::setCallback(const nomali_callback_t *callback) +{ + if (!callback || + callback->type >= NOMALI_CALLBACK_NUM_CALLBACKS) + return NOMALI_E_INVALID; + + callbacks[callback->type] = *callback; + + return NOMALI_E_OK; +} + +nomali_error_t +NoMaliApi::getInfo(nomali_info_t *info) +{ + if (!info) + return NOMALI_E_INVALID; + + info->reg_size = 0x4000; + + return NOMALI_E_OK; +} + +nomali_error_t +NoMaliApi::reset() +{ + _gpu->reset(); + return NOMALI_E_OK; +} + +nomali_error_t +NoMaliApi::regRead(uint32_t *value, nomali_addr_t addr) +{ + if (!value) + return NOMALI_E_INVALID; + + *value = _gpu->readReg(NoMali::RegAddr(addr)); + + return NOMALI_E_OK; +} + +nomali_error_t +NoMaliApi::regWrite(nomali_addr_t addr, uint32_t value) +{ + _gpu->writeReg(NoMali::RegAddr(addr), value); + + return NOMALI_E_OK; +} + + +nomali_error_t +NoMaliApi::regReadRaw(uint32_t *value, nomali_addr_t addr) +{ + if (!value) + return NOMALI_E_INVALID; + + *value = _gpu->readRegRaw(NoMali::RegAddr(addr)); + + return NOMALI_E_OK; +} + +nomali_error_t +NoMaliApi::regWriteRaw(nomali_addr_t addr, uint32_t value) +{ + _gpu->writeRegRaw(NoMali::RegAddr(addr), value); + + return NOMALI_E_OK; +} + +nomali_error_t +NoMaliApi::intState(int *state, nomali_int_t intno) const +{ + if (!state) + return NOMALI_E_INVALID; + + switch (intno) { + case NOMALI_INT_GPU: + *state = _gpu->intGPUAsserted(); + break; + + case NOMALI_INT_JOB: + *state = _gpu->intJobAsserted(); + break; + + case NOMALI_INT_MMU: + *state = _gpu->intMMUAsserted(); + break; + + default: + return NOMALI_E_INVALID; + } + + return NOMALI_E_OK; +} + + +void +NoMaliApi::callbackInt(nomali_int_t intno, int set) +{ + const nomali_callback_t &c(callbacks[NOMALI_CALLBACK_INT]); + + if (c.func.interrupt) + c.func.interrupt(static_cast<nomali_handle_t>(this), c.usr, intno, set); +} + + + +static NoMaliApi * +get_gpu(nomali_handle_t h) +{ + return h ? static_cast<NoMaliApi *>(h) : nullptr; +} + + +extern "C" EXPORT nomali_api_version_t +nomali_api_version() +{ + return NOMALI_API_VERSION; +} + +extern "C" EXPORT nomali_error_t +nomali_create(nomali_handle_t *h, const nomali_config_t *cfg) +{ + if (h && cfg) { + NoMaliApi *api(new NoMaliApi()); + *h = api; + if (!h) + return NOMALI_E_MEMORY; + + NoMali::GPU *gpu; + switch (cfg->type) { + case NOMALI_GPU_T60X: + gpu = new NoMaliApiGpu<NoMali::MaliT60x>( + *api, + cfg->ver_maj, cfg->ver_min, cfg->ver_status); + break; + + case NOMALI_GPU_T62X: + gpu = new NoMaliApiGpu<NoMali::MaliT62x>( + *api, + cfg->ver_maj, cfg->ver_min, cfg->ver_status); + break; + + + case NOMALI_GPU_T76X: + gpu = new NoMaliApiGpu<NoMali::MaliT76x>( + *api, + cfg->ver_maj, cfg->ver_min, cfg->ver_status); + break; + + default: + delete api; + return NOMALI_E_INVALID; + }; + + if (!gpu) { + delete api; + return NOMALI_E_MEMORY; + } + + api->setGpu(gpu); + + return NOMALI_E_OK; + } else { + return NOMALI_E_INVALID; + } +} + +extern "C" EXPORT nomali_error_t +nomali_destroy(nomali_handle_t h) +{ + NoMaliApi *gpu(get_gpu(h)); + + if (gpu) { + delete gpu; + return NOMALI_E_OK; + } else { + return NOMALI_E_HANDLE; + } +} + +extern "C" EXPORT const char * +nomali_errstr(nomali_error_t error) +{ + if (error < NOMALI_E_NUM_ERRORS) + return errstrs[error]; + else + return "Invalid error number"; +} + +extern "C" EXPORT nomali_error_t +nomali_set_callback(nomali_handle_t h, + const nomali_callback_t *callback) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->setCallback(callback) : NOMALI_E_HANDLE; +} + +extern "C" EXPORT nomali_error_t +nomali_get_info(nomali_handle_t h, nomali_info_t *info) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->getInfo(info) : NOMALI_E_HANDLE; +} + +extern "C" EXPORT nomali_error_t +nomali_reset(nomali_handle_t h) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->reset() : NOMALI_E_HANDLE; +} + +extern "C" EXPORT nomali_error_t +nomali_reg_read(nomali_handle_t h, uint32_t *value, + nomali_addr_t addr) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->regRead(value, addr) : NOMALI_E_HANDLE; +} + +extern "C" EXPORT nomali_error_t +nomali_reg_write(nomali_handle_t h, + nomali_addr_t addr, uint32_t value) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->regWrite(addr, value) : NOMALI_E_HANDLE; +} + + +extern "C" EXPORT nomali_error_t +nomali_reg_read_raw(nomali_handle_t h, uint32_t *value, + nomali_addr_t addr) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->regReadRaw(value, addr) : NOMALI_E_HANDLE; +} + +extern "C" EXPORT nomali_error_t +nomali_reg_write_raw(nomali_handle_t h, + nomali_addr_t addr, uint32_t value) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->regWriteRaw(addr, value) : NOMALI_E_HANDLE; +} + +extern "C" EXPORT nomali_error_t +nomali_int_state(nomali_handle_t h, int *state, + nomali_int_t intno) +{ + NoMaliApi *gpu(get_gpu(h)); + return gpu ? gpu->intState(state, intno) : NOMALI_E_HANDLE; +} + diff --git a/ext/nomali/lib/regutils.hh b/ext/nomali/lib/regutils.hh new file mode 100644 index 000000000..7957df2b7 --- /dev/null +++ b/ext/nomali/lib/regutils.hh @@ -0,0 +1,103 @@ +/* + * 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 + */ + +#ifndef _LIBNOMALIMODEL_REGUTILS_HH +#define _LIBNOMALIMODEL_REGUTILS_HH + +#include <cassert> + +#include "types.hh" +#include "mali_midg_regmap.h" + +namespace NoMali { + +/** Size of a function block in bytes */ +static const uint32_t BLOCK_REGS_SIZE(0x1000); +/** Number of registers in a function block */ +static const uint32_t BLOCK_NUM_REGS = BLOCK_REGS_SIZE >> 2; + +/** + * Register blocks within the GPU. + * + * The GPU splits its register space into chunks belonging to specific + * blocks. This enum lists those blocks. + */ +enum class RegBlock : uint16_t { + GPU = 0x0, + JOB = 0x1, + MMU = 0x2, + + UNKNOWN = 0xFFFF, +}; + +/** Get the register block from a GPU register address */ +static inline RegBlock +getRegBlock(RegAddr addr) +{ + return RegBlock(addr.value >> 12); +} + +/** + * Get the register address within a GPU block. + * + * This method masks away the block offset from a GPU register + * address. The resulting address is the address <i>within</i> a + * function block. + */ +static inline RegAddr +getBlockReg(RegAddr addr) +{ + static_assert((BLOCK_REGS_SIZE & (BLOCK_REGS_SIZE - 1)) == 0, + "BLOCK_REGS_SIZE is not a power of 2"); + return RegAddr(addr.value & (BLOCK_REGS_SIZE - 1)); +} + +/** + * Get the slot number owning an address within the JobControl block. + * + * @param Address relative to the JobControl block. + */ +static inline unsigned +getJobSlotNo(const RegAddr &addr) +{ + assert(addr.value >= JOB_SLOT0); + assert(addr.value <= 0xFFF); + return (addr.value - JOB_SLOT0) >> 7; +} + +/** + * Get a JobSlot-relative address from a JobControl-relative address. + * + * @param Address relative to the JobControl block. + * @return Address relative the start of the JobSlot. + */ +static inline RegAddr +getJobSlotAddr(const RegAddr &addr) +{ + const unsigned slot_no(getJobSlotNo(addr)); + const RegAddr slot_base(RegAddr(JOB_SLOT0 + slot_no * 0x80)); + return addr - slot_base; +} + +/** Number of registers per job slot */ +static const unsigned JSn_NO_REGS = 0x20; + +} + +#endif //_LIBNOMALIMODEL_REGUTILS_HH diff --git a/ext/nomali/lib/types.hh b/ext/nomali/lib/types.hh new file mode 100644 index 000000000..7d2d6e1f6 --- /dev/null +++ b/ext/nomali/lib/types.hh @@ -0,0 +1,218 @@ +/* + * 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 + */ + +#ifndef _LIBNOMALIMODEL_TYPES_HH +#define _LIBNOMALIMODEL_TYPES_HH + +#include <cassert> +#include <cstdint> + +#include <utility> +#include <vector> + +namespace NoMali{ + +/** + * @{ + * @name Register handling utilities + */ + +/** + * Register address wrapper + * + * This class wraps a register address. Unlike a simple typedef, this + * provides safety from automatic type conversions from other integer + * types since the constructor must be called explicitly. + */ +struct RegAddr { + explicit RegAddr(uint32_t v) + : value(v) {} + + const uint32_t value; +}; + +inline bool +operator<(const RegAddr &lhs, const RegAddr &rhs) { + return lhs.value < rhs.value; +} + +inline bool +operator>(const RegAddr &lhs, const RegAddr &rhs) { + return lhs.value > rhs.value; +} + +inline bool +operator<=(const RegAddr &lhs, const RegAddr &rhs) { + return lhs.value <= rhs.value; +} + +inline bool +operator>=(const RegAddr &lhs, const RegAddr &rhs) { + return lhs.value >= rhs.value; +} + +inline bool +operator==(const RegAddr &lhs, const RegAddr &rhs) { + return lhs.value == rhs.value; +} + +inline bool +operator!=(const RegAddr &lhs, const RegAddr &rhs) { + return lhs.value != rhs.value; +} + +inline RegAddr +operator+(const RegAddr &lhs, const RegAddr &rhs) { + return RegAddr(lhs.value + rhs.value); +} + +inline RegAddr +operator-(const RegAddr &lhs, const RegAddr &rhs) { + assert(lhs >= rhs); + return RegAddr(lhs.value - rhs.value); +} + +/** + * Class for register storage + * + * This class wraps a std::vector and implements a subset of its + * functionality. Specifically, it is constant size and prevents + * indexing with anything other than RegAddr instances. + */ +class RegVector +{ + private: + typedef std::vector<uint32_t> vector_t; + + public: + typedef vector_t::iterator iterator; + typedef vector_t::const_iterator const_iterator; + typedef vector_t::size_type size_type; + + public: + RegVector(size_type size) + : vector(size, 0) {} + + /** @{ */ + /** + * Helper function to get a 64-bit register. + * + * @param addr Address to the low part of the register. + * @return 64-bit value representing the concatenation of the HI + * and LO parts of the register. + */ + const uint32_t get64(const RegAddr &addr) const { + const unsigned idx_lo = index(addr); + const unsigned idx_hi = idx_lo + 1; + return (((uint64_t)vector[idx_hi]) << 32) | vector[idx_lo]; + } + + /** + * Helper function to set a 64-bit register. + * + * @param addr Address to the low part of the register. + * @param value Value to write into the 64-bit register. + */ + void set64(const RegAddr &addr, uint64_t value) { + const unsigned idx_lo = index(addr); + const unsigned idx_hi = idx_lo + 1; + vector[idx_lo] = value & 0xFFFFFFFF; + vector[idx_hi] = (value >> 32) & 0xFFFFFFFF; + } + + const uint32_t &operator[](const RegAddr &addr) const { + return vector[index(addr)]; + } + + uint32_t &operator[](const RegAddr &addr) { + return vector[index(addr)]; + } + + + iterator begin() noexcept { return vector.begin(); } + const_iterator begin() const noexcept { return vector.begin(); } + const_iterator cbegin() const noexcept { return vector.cbegin(); } + + iterator end() noexcept { return vector.end(); } + const_iterator end() const noexcept { return vector.end(); } + const_iterator cend() const noexcept { return vector.cend(); } + + const size_type size() const noexcept { return vector.size(); } + + private: + // Disable default constructor + RegVector(); + + static uint32_t index(const RegAddr &addr) { + assert((addr.value & 0x3) == 0); + return addr.value >> 2; + } + + + vector_t vector; +}; +/** @} */ + +/** + * Class representing the status codes in the Midgard architecture. + */ +struct Status { + /** + * Class representing the subsystem a status code originates from. + */ + enum StatusClass { + CLASS_NOFAULT = 0, + CLASS_JOB = 1, + CLASS_GPU = 2, + CLASS_MMU = 3, + }; + + typedef uint8_t Code; + typedef uint8_t SubCode; + + Status(StatusClass cls, Code code, SubCode subcode) + : value((cls << 6) | (code << 3) | subcode) { + assert((cls & ~0x3) == 0); + assert((code & ~0x7) == 0); + assert((subcode & ~0x7) == 0); + } + + explicit Status(uint8_t v) + : value(v) {} + + StatusClass statusClass() const { + return (StatusClass)((value >> 6) & 0x3); + } + + Code code() const { + return (value >> 3) & 0x7; + } + + SubCode subCode() const { + return value & 0x7; + } + + const uint8_t value; +}; + + +} + +#endif + |