diff options
author | Andreas Sandberg <andreas.sandberg@arm.com> | 2015-07-07 10:03:13 +0100 |
---|---|---|
committer | Andreas Sandberg <andreas.sandberg@arm.com> | 2015-07-07 10:03:13 +0100 |
commit | c2740578404b4e46d198de70af1cfd554033d99f (patch) | |
tree | bb97478f7d31251d5b1bb0013b6b06b16ca0712c /ext/nomali/lib/jobcontrol.cc | |
parent | a0cbf5541133e58968919991635797babaad2a18 (diff) | |
download | gem5-c2740578404b4e46d198de70af1cfd554033d99f.tar.xz |
ext: Add the NoMali GPU no-simulation library
Add revision 9adf9d6e2d889a483a92136c96eb8a434d360561 of NoMali-model
from https://github.com/ARM-software/nomali-model. This library
implements the register interface of the Mali T6xx/T7xx series GPUs,
but doesn't do any rendering. It can be used to hide the effects of
software rendering.
Diffstat (limited to 'ext/nomali/lib/jobcontrol.cc')
-rw-r--r-- | ext/nomali/lib/jobcontrol.cc | 139 |
1 files changed, 139 insertions, 0 deletions
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); +} + +} |