110915Sandreas.sandberg@arm.com/*
211313Sandreas.sandberg@arm.com * Copyright (c) 2014-2016 ARM Limited
310915Sandreas.sandberg@arm.com * All rights reserved
410915Sandreas.sandberg@arm.com *
510915Sandreas.sandberg@arm.com * Licensed under the Apache License, Version 2.0 (the "License");
610915Sandreas.sandberg@arm.com * you may not use this file except in compliance with the License.
710915Sandreas.sandberg@arm.com * You may obtain a copy of the License at
810915Sandreas.sandberg@arm.com *
910915Sandreas.sandberg@arm.com *     http://www.apache.org/licenses/LICENSE-2.0
1010915Sandreas.sandberg@arm.com *
1110915Sandreas.sandberg@arm.com * Unless required by applicable law or agreed to in writing, software
1210915Sandreas.sandberg@arm.com * distributed under the License is distributed on an "AS IS" BASIS,
1310915Sandreas.sandberg@arm.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1410915Sandreas.sandberg@arm.com * See the License for the specific language governing permissions and
1510915Sandreas.sandberg@arm.com * limitations under the License.
1610915Sandreas.sandberg@arm.com *
1710915Sandreas.sandberg@arm.com * Authors: Andreas Sandberg
1810915Sandreas.sandberg@arm.com */
1910915Sandreas.sandberg@arm.com
2010915Sandreas.sandberg@arm.com#include "jobslot.hh"
2110915Sandreas.sandberg@arm.com
2210915Sandreas.sandberg@arm.com#include <cassert>
2310915Sandreas.sandberg@arm.com#include <cstdlib>
2410915Sandreas.sandberg@arm.com
2510915Sandreas.sandberg@arm.com#include "jobcontrol.hh"
2610915Sandreas.sandberg@arm.com#include "gpu.hh"
2710915Sandreas.sandberg@arm.com#include "regutils.hh"
2810915Sandreas.sandberg@arm.com
2910915Sandreas.sandberg@arm.comnamespace NoMali {
3010915Sandreas.sandberg@arm.com
3111313Sandreas.sandberg@arm.comstatic const Status STATUS_IDLE(Status::CLASS_NOFAULT, 0, 0);
3211313Sandreas.sandberg@arm.comstatic const Status STATUS_DONE(Status::CLASS_NOFAULT, 0, 1);
3311313Sandreas.sandberg@arm.comstatic const Status STATUS_ACTIVE(Status::CLASS_NOFAULT, 1, 0);
3411313Sandreas.sandberg@arm.com
3510915Sandreas.sandberg@arm.comconst std::vector<JobSlot::cmd_t> JobSlot::cmds {
3610915Sandreas.sandberg@arm.com    &JobSlot::cmdNop,                      // JSn_COMMAND_NOP
3710915Sandreas.sandberg@arm.com    &JobSlot::cmdStart,                    // JSn_COMMAND_START
3810915Sandreas.sandberg@arm.com    &JobSlot::cmdSoftStop,                 // JSn_COMMAND_SOFT_STOP
3910915Sandreas.sandberg@arm.com    &JobSlot::cmdHardStop,                 // JSn_COMMAND_HARD_STOP
4010915Sandreas.sandberg@arm.com    &JobSlot::cmdSoftStop0,                // JSn_COMMAND_SOFT_STOP_0
4110915Sandreas.sandberg@arm.com    &JobSlot::cmdHardStop0,                // JSn_COMMAND_HARD_STOP_0
4210915Sandreas.sandberg@arm.com    &JobSlot::cmdSoftStop1,                // JSn_COMMAND_SOFT_STOP_1
4310915Sandreas.sandberg@arm.com    &JobSlot::cmdHardStop1,                // JSn_COMMAND_HARD_STOP_1
4410915Sandreas.sandberg@arm.com};
4510915Sandreas.sandberg@arm.com
4610915Sandreas.sandberg@arm.comJobSlot::JobSlot(GPU &_gpu, JobControl &_jc, uint8_t _id)
4710915Sandreas.sandberg@arm.com    : GPUBlock(_gpu, JSn_NO_REGS),
4810915Sandreas.sandberg@arm.com      id(_id),
4910915Sandreas.sandberg@arm.com      jc(_jc)
5010915Sandreas.sandberg@arm.com{
5110915Sandreas.sandberg@arm.com}
5210915Sandreas.sandberg@arm.com
5310915Sandreas.sandberg@arm.comJobSlot::JobSlot(JobSlot &&rhs)
5410915Sandreas.sandberg@arm.com    : GPUBlock(std::move(rhs)),
5510915Sandreas.sandberg@arm.com      id(std::move(rhs.id)),
5610915Sandreas.sandberg@arm.com      jc(rhs.jc)
5710915Sandreas.sandberg@arm.com{
5810915Sandreas.sandberg@arm.com}
5910915Sandreas.sandberg@arm.com
6010915Sandreas.sandberg@arm.comJobSlot::~JobSlot()
6110915Sandreas.sandberg@arm.com{
6210915Sandreas.sandberg@arm.com}
6310915Sandreas.sandberg@arm.com
6410915Sandreas.sandberg@arm.comvoid
6510915Sandreas.sandberg@arm.comJobSlot::writeReg(RegAddr addr, uint32_t value)
6610915Sandreas.sandberg@arm.com{
6710915Sandreas.sandberg@arm.com    switch (addr.value) {
6810915Sandreas.sandberg@arm.com      case JSn_COMMAND:
6910915Sandreas.sandberg@arm.com        jobCommand(value);
7010915Sandreas.sandberg@arm.com        break;
7110915Sandreas.sandberg@arm.com
7210915Sandreas.sandberg@arm.com      case JSn_COMMAND_NEXT:
7310915Sandreas.sandberg@arm.com        regs[addr] = value;
7410915Sandreas.sandberg@arm.com        tryStart();
7510915Sandreas.sandberg@arm.com        break;
7610915Sandreas.sandberg@arm.com
7710915Sandreas.sandberg@arm.com      case JSn_HEAD_NEXT_LO:
7810915Sandreas.sandberg@arm.com      case JSn_HEAD_NEXT_HI:
7910915Sandreas.sandberg@arm.com      case JSn_AFFINITY_NEXT_LO:
8010915Sandreas.sandberg@arm.com      case JSn_AFFINITY_NEXT_HI:
8110915Sandreas.sandberg@arm.com      case JSn_CONFIG_NEXT:
8210915Sandreas.sandberg@arm.com        GPUBlock::writeReg(addr, value);
8310915Sandreas.sandberg@arm.com        break;
8410915Sandreas.sandberg@arm.com
8510915Sandreas.sandberg@arm.com      default:
8610915Sandreas.sandberg@arm.com        // Ignore writes by default
8710915Sandreas.sandberg@arm.com        break;
8810915Sandreas.sandberg@arm.com    };
8910915Sandreas.sandberg@arm.com}
9010915Sandreas.sandberg@arm.com
9110915Sandreas.sandberg@arm.combool
9210915Sandreas.sandberg@arm.comJobSlot::active() const
9310915Sandreas.sandberg@arm.com{
9410915Sandreas.sandberg@arm.com    return false;
9510915Sandreas.sandberg@arm.com}
9610915Sandreas.sandberg@arm.com
9710915Sandreas.sandberg@arm.combool
9810915Sandreas.sandberg@arm.comJobSlot::activeNext() const
9910915Sandreas.sandberg@arm.com{
10010915Sandreas.sandberg@arm.com    return regs[RegAddr(JSn_COMMAND_NEXT)] == JSn_COMMAND_START;
10110915Sandreas.sandberg@arm.com}
10210915Sandreas.sandberg@arm.com
10310915Sandreas.sandberg@arm.comvoid
10410915Sandreas.sandberg@arm.comJobSlot::tryStart()
10510915Sandreas.sandberg@arm.com{
10610915Sandreas.sandberg@arm.com    // Only actually start something if the next command is start
10710915Sandreas.sandberg@arm.com    if (regs[RegAddr(JSn_COMMAND_NEXT)] != JSn_COMMAND_START )
10810915Sandreas.sandberg@arm.com        return;
10910915Sandreas.sandberg@arm.com
11010915Sandreas.sandberg@arm.com    // Reset the status register
11111313Sandreas.sandberg@arm.com    regs[RegAddr(JSn_STATUS)] = STATUS_ACTIVE.value;
11210915Sandreas.sandberg@arm.com
11310915Sandreas.sandberg@arm.com    // Transfer the next job configuration to the active job
11410915Sandreas.sandberg@arm.com    // configuration
11510915Sandreas.sandberg@arm.com    regs.set64(RegAddr(JSn_HEAD_LO), regs.get64(RegAddr(JSn_HEAD_NEXT_LO)));
11610915Sandreas.sandberg@arm.com    regs.set64(RegAddr(JSn_TAIL_LO), regs.get64(RegAddr(JSn_HEAD_NEXT_LO)));
11710915Sandreas.sandberg@arm.com    regs.set64(RegAddr(JSn_AFFINITY_LO),
11810915Sandreas.sandberg@arm.com               regs.get64(RegAddr(JSn_AFFINITY_NEXT_LO)));
11910915Sandreas.sandberg@arm.com    regs[RegAddr(JSn_CONFIG)] = regs[RegAddr(JSn_CONFIG_NEXT)];
12010915Sandreas.sandberg@arm.com
12110915Sandreas.sandberg@arm.com    // Reset the next job configuration
12210915Sandreas.sandberg@arm.com    regs.set64(RegAddr(JSn_HEAD_NEXT_LO), 0);
12310915Sandreas.sandberg@arm.com    regs[RegAddr(JSn_COMMAND_NEXT)] = 0;
12410915Sandreas.sandberg@arm.com
12510915Sandreas.sandberg@arm.com    runJob();
12610915Sandreas.sandberg@arm.com}
12710915Sandreas.sandberg@arm.com
12810915Sandreas.sandberg@arm.comvoid
12910915Sandreas.sandberg@arm.comJobSlot::runJob()
13010915Sandreas.sandberg@arm.com{
13111313Sandreas.sandberg@arm.com    exitJob(STATUS_DONE,
13210915Sandreas.sandberg@arm.com            0); // Time stamp counter value
13310915Sandreas.sandberg@arm.com}
13410915Sandreas.sandberg@arm.com
13510915Sandreas.sandberg@arm.comvoid
13610915Sandreas.sandberg@arm.comJobSlot::exitJob(Status status, uint64_t fault_address)
13710915Sandreas.sandberg@arm.com{
13810915Sandreas.sandberg@arm.com    assert(status.statusClass() == Status::CLASS_NOFAULT ||
13910915Sandreas.sandberg@arm.com           status.statusClass() == Status::CLASS_JOB);
14010915Sandreas.sandberg@arm.com
14110915Sandreas.sandberg@arm.com    regs[RegAddr(JSn_STATUS)] = status.value;
14210915Sandreas.sandberg@arm.com
14310915Sandreas.sandberg@arm.com    if (status.statusClass() == Status::CLASS_NOFAULT) {
14410915Sandreas.sandberg@arm.com        jc.jobDone(id);
14510915Sandreas.sandberg@arm.com    } else {
14610915Sandreas.sandberg@arm.com        jc.jobFailed(id);
14710915Sandreas.sandberg@arm.com    }
14810915Sandreas.sandberg@arm.com}
14910915Sandreas.sandberg@arm.com
15010915Sandreas.sandberg@arm.comvoid
15110915Sandreas.sandberg@arm.comJobSlot::jobCommand(uint32_t cmd)
15210915Sandreas.sandberg@arm.com{
15310915Sandreas.sandberg@arm.com    if (cmd < cmds.size())
15410915Sandreas.sandberg@arm.com        (this->*cmds[cmd])(cmd);
15510915Sandreas.sandberg@arm.com}
15610915Sandreas.sandberg@arm.com
15710915Sandreas.sandberg@arm.comvoid
15810915Sandreas.sandberg@arm.comJobSlot::cmdNop(uint32_t cmd)
15910915Sandreas.sandberg@arm.com{
16010915Sandreas.sandberg@arm.com    assert(cmd == JSn_COMMAND_NOP);
16110915Sandreas.sandberg@arm.com}
16210915Sandreas.sandberg@arm.com
16310915Sandreas.sandberg@arm.comvoid
16410915Sandreas.sandberg@arm.comJobSlot::cmdStart(uint32_t cmd)
16510915Sandreas.sandberg@arm.com{
16610915Sandreas.sandberg@arm.com    assert(cmd == JSn_COMMAND_START);
16710915Sandreas.sandberg@arm.com    // The JSn_COMMAND_START should never be issued through the
16810915Sandreas.sandberg@arm.com    // JSn_COMMAND register. It should use the JSn_COMMAND_NEXT
16910915Sandreas.sandberg@arm.com    // register instead.
17010915Sandreas.sandberg@arm.com    abort();
17110915Sandreas.sandberg@arm.com}
17210915Sandreas.sandberg@arm.com
17310915Sandreas.sandberg@arm.comvoid
17410915Sandreas.sandberg@arm.comJobSlot::cmdSoftStop(uint32_t cmd)
17510915Sandreas.sandberg@arm.com{
17610915Sandreas.sandberg@arm.com    assert(cmd == JSn_COMMAND_SOFT_STOP ||
17710915Sandreas.sandberg@arm.com           cmd == JSn_COMMAND_SOFT_STOP_0 ||
17810915Sandreas.sandberg@arm.com           cmd == JSn_COMMAND_SOFT_STOP_1);
17910915Sandreas.sandberg@arm.com}
18010915Sandreas.sandberg@arm.com
18110915Sandreas.sandberg@arm.comvoid
18210915Sandreas.sandberg@arm.comJobSlot::cmdHardStop(uint32_t cmd)
18310915Sandreas.sandberg@arm.com{
18410915Sandreas.sandberg@arm.com    assert(cmd == JSn_COMMAND_HARD_STOP ||
18510915Sandreas.sandberg@arm.com           cmd == JSn_COMMAND_HARD_STOP_0 ||
18610915Sandreas.sandberg@arm.com           cmd == JSn_COMMAND_HARD_STOP_1);
18710915Sandreas.sandberg@arm.com}
18810915Sandreas.sandberg@arm.com
18910915Sandreas.sandberg@arm.comvoid
19010915Sandreas.sandberg@arm.comJobSlot::cmdSoftStop0(uint32_t cmd)
19110915Sandreas.sandberg@arm.com{
19210915Sandreas.sandberg@arm.com    if (!(regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG))
19310915Sandreas.sandberg@arm.com        cmdSoftStop(cmd);
19410915Sandreas.sandberg@arm.com}
19510915Sandreas.sandberg@arm.com
19610915Sandreas.sandberg@arm.comvoid
19710915Sandreas.sandberg@arm.comJobSlot::cmdHardStop0(uint32_t cmd)
19810915Sandreas.sandberg@arm.com{
19910915Sandreas.sandberg@arm.com    if (!(regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG))
20010915Sandreas.sandberg@arm.com        cmdHardStop(cmd);
20110915Sandreas.sandberg@arm.com}
20210915Sandreas.sandberg@arm.com
20310915Sandreas.sandberg@arm.comvoid
20410915Sandreas.sandberg@arm.comJobSlot::cmdSoftStop1(uint32_t cmd)
20510915Sandreas.sandberg@arm.com{
20610915Sandreas.sandberg@arm.com    if (regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG)
20710915Sandreas.sandberg@arm.com        cmdSoftStop(cmd);
20810915Sandreas.sandberg@arm.com}
20910915Sandreas.sandberg@arm.com
21010915Sandreas.sandberg@arm.comvoid
21110915Sandreas.sandberg@arm.comJobSlot::cmdHardStop1(uint32_t cmd)
21210915Sandreas.sandberg@arm.com{
21310915Sandreas.sandberg@arm.com    if (regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG)
21410915Sandreas.sandberg@arm.com        cmdHardStop(cmd);
21510915Sandreas.sandberg@arm.com}
21610915Sandreas.sandberg@arm.com
21710915Sandreas.sandberg@arm.com}
218