text: /*
   * Copyright (C) 2020 Intel Corporation
   *
   * SPDX-License-Identifier: MIT
   *
   */
  
  #include "shared/source/gen12lp/hw_info.h"
  #include "shared/test/unit_test/cmd_parse/hw_parse.h"
  
  #include "opencl/source/command_queue/gpgpu_walker.h"
  #include "opencl/source/command_queue/hardware_interface.h"
  #include "opencl/test/unit_test/command_stream/linear_stream_fixture.h"
  #include "opencl/test/unit_test/fixtures/cl_device_fixture.h"
  #include "opencl/test/unit_test/mocks/mock_command_queue.h"
  #include "opencl/test/unit_test/mocks/mock_kernel.h"
  #include "test.h"
  
  namespace NEO {
  struct GpgpuWalkerTests : public ::testing::Test {
      void SetUp() override {
      }
  
      void TearDown() override {
      }
  };
  
  GEN12LPTEST_F(GpgpuWalkerTests, givenMiStoreRegMemWhenAdjustMiStoreRegMemModeThenMmioRemapEnableIsSet) {
      using MI_STORE_REGISTER_MEM = typename FamilyType::MI_STORE_REGISTER_MEM;
  
      MI_STORE_REGISTER_MEM cmd = FamilyType::cmdInitStoreRegisterMem;
  
      GpgpuWalkerHelper<FamilyType>::adjustMiStoreRegMemMode(&cmd);
  
      EXPECT_EQ(true, cmd.getMmioRemapEnable());
  }
  
  class MockKernelWithApplicableWa : public MockKernel {
    public:
      MockKernelWithApplicableWa(Program *program, KernelInfo &kernelInfo, ClDevice &device) : MockKernel(program, kernelInfo, device) {}
      bool requiresWaDisableRccRhwoOptimization() const override {
          return waApplicable;
      }
      bool waApplicable = false;
  };
  
  struct HardwareInterfaceTests : public ClDeviceFixture, public LinearStreamFixture, public ::testing::Test {
      void SetUp() override {
          ClDeviceFixture::SetUp();
          LinearStreamFixture::SetUp();
  
          pContext = new NEO::MockContext(pClDevice);
          pCommandQueue = new MockCommandQueue(pContext, pClDevice, nullptr);
          pProgram = new MockProgram(*pClDevice->getExecutionEnvironment(), pContext, false, &pClDevice->getDevice());
          pKernel = new MockKernelWithApplicableWa(static_cast<Program *>(pProgram), pProgram->mockKernelInfo, *pClDevice);
      }
  
      void TearDown() override {
          pKernel->release();
          pProgram->release();
          pCommandQueue->release();
          pContext->release();
  
          LinearStreamFixture::TearDown();
          ClDeviceFixture::TearDown();
      }
  
      CommandQueue *pCommandQueue = nullptr;
      Context *pContext = nullptr;
      MockProgram *pProgram = nullptr;
      MockKernelWithApplicableWa *pKernel = nullptr;
  };
  
  GEN12LPTEST_F(HardwareInterfaceTests, GivenKernelWithApplicableWaDisableRccRhwoOptimizationWhenDispatchWorkaroundsIsCalledThenWorkaroundIsApplied) {
      using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
      using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
  
      bool enableWa = true;
      pKernel->waApplicable = true;
  
      HardwareInterface<FamilyType>::dispatchWorkarounds(&linearStream, *pCommandQueue, *pKernel, enableWa);
      size_t expectedUsedForEnableWa = (sizeof(PIPE_CONTROL) + sizeof(MI_LOAD_REGISTER_IMM));
      ASSERT_EQ(expectedUsedForEnableWa, linearStream.getUsed());
  
      HardwareParse hwParse;
      hwParse.parseCommands<FamilyType>(linearStream);
      auto itorPipeCtrl = find<PIPE_CONTROL *>(hwParse.cmdList.begin(), hwParse.cmdList.end());
      ASSERT_NE(hwParse.cmdList.end(), itorPipeCtrl);
      auto pipeControl = genCmdCast<PIPE_CONTROL *>(*itorPipeCtrl);
      ASSERT_NE(nullptr, pipeControl);
      EXPECT_TRUE(pipeControl->getCommandStreamerStallEnable());
  
      auto itorLri = find<MI_LOAD_REGISTER_IMM *>(hwParse.cmdList.begin(), hwParse.cmdList.end());
      ASSERT_NE(hwParse.cmdList.end(), itorLri);
      auto lriCmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*itorLri);
      ASSERT_NE(nullptr, lriCmd);
      EXPECT_EQ(0x7010u, lriCmd->getRegisterOffset());
      EXPECT_EQ(0x40004000u, lriCmd->getDataDword());
  
      enableWa = false;
      HardwareInterface<FamilyType>::dispatchWorkarounds(&linearStream, *pCommandQueue, *pKernel, enableWa);
      size_t expectedUsedForDisableWa = 2 * (sizeof(PIPE_CONTROL) + sizeof(MI_LOAD_REGISTER_IMM));
      ASSERT_EQ(expectedUsedForDisableWa, linearStream.getUsed());
  
      hwParse.TearDown();
      hwParse.parseCommands<FamilyType>(linearStream, expectedUsedForEnableWa);
      itorPipeCtrl = find<PIPE_CONTROL *>(hwParse.cmdList.begin(), hwParse.cmdList.end());
      ASSERT_NE(hwParse.cmdList.end(), itorPipeCtrl);
      pipeControl = genCmdCast<PIPE_CONTROL *>(*itorPipeCtrl);
      ASSERT_NE(nullptr, pipeControl);
      EXPECT_TRUE(pipeControl->getCommandStreamerStallEnable());
  
      itorLri = find<MI_LOAD_REGISTER_IMM *>(hwParse.cmdList.begin(), hwParse.cmdList.end());
      ASSERT_NE(hwParse.cmdList.end(), itorLri);
      lriCmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*itorLri);
      ASSERT_NE(nullptr, lriCmd);
      EXPECT_EQ(0x7010u, lriCmd->getRegisterOffset());
      EXPECT_EQ(0x40000000u, lriCmd->getDataDword());
  }
  
  GEN12LPTEST_F(HardwareInterfaceTests, GivenKernelWithoutApplicableWaDisableRccRhwoOptimizationWhenDispatchWorkaroundsIsCalledThenWorkaroundIsApplied) {
      bool enableWa = true;
      pKernel->waApplicable = false;
  
      HardwareInterface<FamilyType>::dispatchWorkarounds(&linearStream, *pCommandQueue, *pKernel, enableWa);
      EXPECT_EQ(0u, linearStream.getUsed());
  
      enableWa = false;
      HardwareInterface<FamilyType>::dispatchWorkarounds(&linearStream, *pCommandQueue, *pKernel, enableWa);
      EXPECT_EQ(0u, linearStream.getUsed());
  }
  
  GEN12LPTEST_F(HardwareInterfaceTests, GivenKernelWithApplicableWaDisableRccRhwoOptimizationWhenCalculatingCommandsSizeThenAppropriateSizeIsReturned) {
      using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
      using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
  
      pKernel->waApplicable = true;
      auto cmdSize = GpgpuWalkerHelper<FamilyType>::getSizeForWaDisableRccRhwoOptimization(pKernel);
      size_t expectedSize = 2 * (sizeof(PIPE_CONTROL) + sizeof(MI_LOAD_REGISTER_IMM));
      EXPECT_EQ(expectedSize, cmdSize);
  }
  
  GEN12LPTEST_F(HardwareInterfaceTests, GivenKernelWithoutApplicableWaDisableRccRhwoOptimizationWhenCalculatingCommandsSizeThenZeroIsReturned) {
      pKernel->waApplicable = false;
      auto cmdSize = GpgpuWalkerHelper<FamilyType>::getSizeForWaDisableRccRhwoOptimization(pKernel);
      EXPECT_EQ(0u, cmdSize);
  }
  
  } // namespace NEO