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/jobslot.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/jobslot.cc')
-rw-r--r-- | ext/nomali/lib/jobslot.cc | 216 |
1 files changed, 216 insertions, 0 deletions
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); +} + +} |