From 4ac82c17f13106559edfd3751b1b6fa73a10eaf7 Mon Sep 17 00:00:00 2001 From: Filip Hazubski Date: Mon, 11 Aug 2025 18:09:40 +0000 Subject: [PATCH] refactor: move method to release helper Related-To: NEO-14998 Signed-off-by: Tomasz Biernacik Signed-off-by: Filip Hazubski --- manifests/manifest.yml | 2 +- .../helpers/gfx_core_helper_xe3_and_later.inl | 4 ++-- shared/source/os_interface/product_helper.h | 1 - shared/source/os_interface/product_helper.inl | 5 ----- shared/source/os_interface/product_helper_hw.h | 1 - shared/source/release_helper/release_helper.h | 2 ++ .../source/release_helper/release_helper_base.inl | 6 ++++++ shared/test/common/mocks/mock_release_helper.h | 1 + .../os_interface/product_helper_tests.cpp | 5 ----- .../release_helper/release_helper_12_55_tests.cpp | 4 ++++ .../release_helper/release_helper_12_56_tests.cpp | 4 ++++ .../release_helper/release_helper_12_57_tests.cpp | 4 ++++ .../release_helper/release_helper_12_60_tests.cpp | 4 ++++ .../release_helper/release_helper_12_61_tests.cpp | 4 ++++ .../release_helper/release_helper_12_70_tests.cpp | 4 ++++ .../release_helper/release_helper_12_71_tests.cpp | 4 ++++ .../release_helper/release_helper_12_74_tests.cpp | 6 +++++- .../release_helper/release_helper_20_01_tests.cpp | 4 ++++ .../release_helper/release_helper_20_02_tests.cpp | 4 ++++ .../release_helper/release_helper_20_04_tests.cpp | 4 ++++ .../release_helper/release_helper_30_00_tests.cpp | 4 ++++ .../release_helper/release_helper_30_01_tests.cpp | 4 ++++ .../release_helper/release_helper_30_03_tests.cpp | 4 ++++ .../release_helper/release_helper_tests_base.cpp | 14 +++++++++++++- .../release_helper/release_helper_tests_base.h | 1 + 25 files changed, 83 insertions(+), 17 deletions(-) diff --git a/manifests/manifest.yml b/manifests/manifest.yml index 711eb9c5fa..4863929d8d 100644 --- a/manifests/manifest.yml +++ b/manifests/manifest.yml @@ -41,7 +41,7 @@ components: dest_dir: kernels_bin type: git branch: kernels_bin - revision: 3551-4999 + revision: 3551-5007 kmdaf: branch: kmdaf dest_dir: kmdaf diff --git a/shared/source/helpers/gfx_core_helper_xe3_and_later.inl b/shared/source/helpers/gfx_core_helper_xe3_and_later.inl index 7ba0548854..fcf7d7c027 100644 --- a/shared/source/helpers/gfx_core_helper_xe3_and_later.inl +++ b/shared/source/helpers/gfx_core_helper_xe3_and_later.inl @@ -13,7 +13,7 @@ template <> uint32_t GfxCoreHelperHw::calculateAvailableThreadCount(const HardwareInfo &hwInfo, uint32_t grfCount, const RootDeviceEnvironment &rootDeviceEnvironment) const { auto maxThreadsPerEuCount = 1u; - const auto &productHelper = rootDeviceEnvironment.getHelper(); + const auto releaseHelper = rootDeviceEnvironment.getReleaseHelper(); if (grfCount <= 96u) { maxThreadsPerEuCount = 10; @@ -27,7 +27,7 @@ uint32_t GfxCoreHelperHw::calculateAvailableThreadCount(const HardwareIn maxThreadsPerEuCount = 4; } - maxThreadsPerEuCount = productHelper.adjustMaxThreadsPerEuCount(maxThreadsPerEuCount, grfCount); + maxThreadsPerEuCount = releaseHelper->adjustMaxThreadsPerEuCount(maxThreadsPerEuCount, grfCount); return std::min(hwInfo.gtSystemInfo.ThreadCount, maxThreadsPerEuCount * hwInfo.gtSystemInfo.EUCount); } diff --git a/shared/source/os_interface/product_helper.h b/shared/source/os_interface/product_helper.h index 84d5e32702..5ab24f81af 100644 --- a/shared/source/os_interface/product_helper.h +++ b/shared/source/os_interface/product_helper.h @@ -275,7 +275,6 @@ class ProductHelper { virtual bool isPidFdOrSocketForIpcSupported() const = 0; virtual bool checkBcsForDirectSubmissionStop() const = 0; virtual bool shouldRegisterEnqueuedWalkerWithProfiling() const = 0; - virtual uint32_t adjustMaxThreadsPerEuCount(uint32_t maxThreadsPerEuCount, uint32_t grfCount) const = 0; virtual bool getStorageInfoLocalOnlyFlag(LocalMemAllocationMode usmDeviceAllocationMode, bool defaultValue) const = 0; virtual ~ProductHelper() = default; diff --git a/shared/source/os_interface/product_helper.inl b/shared/source/os_interface/product_helper.inl index 3967fe4165..c5da909300 100644 --- a/shared/source/os_interface/product_helper.inl +++ b/shared/source/os_interface/product_helper.inl @@ -1095,9 +1095,4 @@ bool ProductHelperHw::shouldRegisterEnqueuedWalkerWithProfiling() co return false; } -template -uint32_t ProductHelperHw::adjustMaxThreadsPerEuCount(uint32_t maxThreadsPerEuCount, uint32_t grfCount) const { - return maxThreadsPerEuCount; -} - } // namespace NEO diff --git a/shared/source/os_interface/product_helper_hw.h b/shared/source/os_interface/product_helper_hw.h index df9f485e72..e012b27451 100644 --- a/shared/source/os_interface/product_helper_hw.h +++ b/shared/source/os_interface/product_helper_hw.h @@ -212,7 +212,6 @@ class ProductHelperHw : public ProductHelper { bool isPidFdOrSocketForIpcSupported() const override; bool checkBcsForDirectSubmissionStop() const override; bool shouldRegisterEnqueuedWalkerWithProfiling() const override; - uint32_t adjustMaxThreadsPerEuCount(uint32_t maxThreadsPerEuCount, uint32_t grfCount) const override; ~ProductHelperHw() override = default; diff --git a/shared/source/release_helper/release_helper.h b/shared/source/release_helper/release_helper.h index 00e6838da1..48f5a4eeb3 100644 --- a/shared/source/release_helper/release_helper.h +++ b/shared/source/release_helper/release_helper.h @@ -68,6 +68,7 @@ class ReleaseHelper { virtual uint32_t computeSlmValues(uint32_t slmSize, bool isHeapless) const = 0; virtual bool isBlitImageAllowedForDepthFormat() const = 0; virtual bool isPostImageWriteFlushRequired() const = 0; + virtual uint32_t adjustMaxThreadsPerEuCount(uint32_t maxThreadsPerEuCount, uint32_t grfCount) const = 0; protected: ReleaseHelper(HardwareIpVersion hardwareIpVersion) : hardwareIpVersion(hardwareIpVersion) {} @@ -115,6 +116,7 @@ class ReleaseHelperHw : public ReleaseHelper { uint32_t computeSlmValues(uint32_t slmSize, bool isHeapless) const override; bool isBlitImageAllowedForDepthFormat() const override; bool isPostImageWriteFlushRequired() const override; + uint32_t adjustMaxThreadsPerEuCount(uint32_t maxThreadsPerEuCount, uint32_t grfCount) const override; protected: ReleaseHelperHw(HardwareIpVersion hardwareIpVersion) : ReleaseHelper(hardwareIpVersion) {} diff --git a/shared/source/release_helper/release_helper_base.inl b/shared/source/release_helper/release_helper_base.inl index e2f07535f0..4dbcc9b341 100644 --- a/shared/source/release_helper/release_helper_base.inl +++ b/shared/source/release_helper/release_helper_base.inl @@ -188,4 +188,10 @@ template bool ReleaseHelperHw::isPostImageWriteFlushRequired() const { return false; } + +template +uint32_t ReleaseHelperHw::adjustMaxThreadsPerEuCount(uint32_t maxThreadsPerEuCount, uint32_t grfCount) const { + return maxThreadsPerEuCount; +} + } // namespace NEO diff --git a/shared/test/common/mocks/mock_release_helper.h b/shared/test/common/mocks/mock_release_helper.h index 15ce302650..79dc6329a0 100644 --- a/shared/test/common/mocks/mock_release_helper.h +++ b/shared/test/common/mocks/mock_release_helper.h @@ -45,6 +45,7 @@ class MockReleaseHelper : public ReleaseHelper { ADDMETHOD_CONST_NOBASE(computeSlmValues, uint32_t, {}, (uint32_t slmSize, bool isHeapless)); ADDMETHOD_CONST_NOBASE(programmAdditionalStallPriorToBarrierWithTimestamp, bool, false, ()); ADDMETHOD_CONST_NOBASE(isPostImageWriteFlushRequired, bool, false, ()); + ADDMETHOD_CONST_NOBASE(adjustMaxThreadsPerEuCount, uint32_t, 8u, (uint32_t maxThreadsPerEuCount, uint32_t grfCount)); ADDMETHOD_CONST_NOBASE_VOIDRETURN(adjustRTDispatchGlobals, (void *rtDispatchGlobals, uint32_t rtStacksPerDss, bool heaplessEnabled, uint32_t maxBvhLevels)); const SizeToPreferredSlmValueArray &getSizeToPreferredSlmValue(bool isHeapless) const override { diff --git a/shared/test/unit_test/os_interface/product_helper_tests.cpp b/shared/test/unit_test/os_interface/product_helper_tests.cpp index 825aa0b801..ad26f6c131 100644 --- a/shared/test/unit_test/os_interface/product_helper_tests.cpp +++ b/shared/test/unit_test/os_interface/product_helper_tests.cpp @@ -1268,8 +1268,3 @@ HWTEST2_F(ProductHelperTest, givenProductHelperWhenPidFdOrSocketForIpcIsNotSuppo HWTEST_F(ProductHelperTest, givenProductHelperWhenAskingShouldRegisterEnqueuedWalkerWithProfilingThenFalseReturned) { EXPECT_FALSE(productHelper->shouldRegisterEnqueuedWalkerWithProfiling()); } - -HWTEST_F(ProductHelperTest, givenProductHelperWhenCallingAdjustMaxThreadsPerEuCountThenDoNotChangeMaxThreadsPerEuCount) { - uint32_t maxThreadsPerEuCount = 17u; - EXPECT_EQ(maxThreadsPerEuCount, productHelper->adjustMaxThreadsPerEuCount(maxThreadsPerEuCount, 0u)); -} diff --git a/shared/test/unit_test/release_helper/release_helper_12_55_tests.cpp b/shared/test/unit_test/release_helper/release_helper_12_55_tests.cpp index 40dabca223..a8ac879d63 100644 --- a/shared/test/unit_test/release_helper/release_helper_12_55_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_12_55_tests.cpp @@ -122,3 +122,7 @@ TEST_F(ReleaseHelper1255Tests, whenGettingPreferredSlmSizeThenAllEntriesHaveCorr EXPECT_EQ(13u, preferredSlmValueArray[5].valueToProgram); } } + +TEST_F(ReleaseHelper1255Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_12_56_tests.cpp b/shared/test/unit_test/release_helper/release_helper_12_56_tests.cpp index 6e5d8f1a90..50fcda38e2 100644 --- a/shared/test/unit_test/release_helper/release_helper_12_56_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_12_56_tests.cpp @@ -122,3 +122,7 @@ TEST_F(ReleaseHelper1256Tests, whenGettingPreferredSlmSizeThenAllEntriesHaveCorr EXPECT_EQ(13u, preferredSlmValueArray[5].valueToProgram); } } + +TEST_F(ReleaseHelper1256Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_12_57_tests.cpp b/shared/test/unit_test/release_helper/release_helper_12_57_tests.cpp index e8825dc7f7..e53bd321e6 100644 --- a/shared/test/unit_test/release_helper/release_helper_12_57_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_12_57_tests.cpp @@ -121,3 +121,7 @@ TEST_F(ReleaseHelper1257Tests, whenGettingPreferredSlmSizeThenAllEntriesHaveCorr EXPECT_EQ(13u, preferredSlmValueArray[5].valueToProgram); } } + +TEST_F(ReleaseHelper1257Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_12_60_tests.cpp b/shared/test/unit_test/release_helper/release_helper_12_60_tests.cpp index 36aa532ed1..55459257c5 100644 --- a/shared/test/unit_test/release_helper/release_helper_12_60_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_12_60_tests.cpp @@ -106,3 +106,7 @@ TEST_F(ReleaseHelper1260Tests, whenGettingPreferredSlmSizeThenAllEntriesHaveCorr EXPECT_EQ(13u, preferredSlmValueArray[5].valueToProgram); } } + +TEST_F(ReleaseHelper1260Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_12_61_tests.cpp b/shared/test/unit_test/release_helper/release_helper_12_61_tests.cpp index 8a6173466c..f92915a433 100644 --- a/shared/test/unit_test/release_helper/release_helper_12_61_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_12_61_tests.cpp @@ -105,3 +105,7 @@ TEST_F(ReleaseHelper1261Tests, whenGettingPreferredSlmSizeThenAllEntriesHaveCorr EXPECT_EQ(13u, preferredSlmValueArray[5].valueToProgram); } } + +TEST_F(ReleaseHelper1261Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_12_70_tests.cpp b/shared/test/unit_test/release_helper/release_helper_12_70_tests.cpp index a60ec2411c..a992dab042 100644 --- a/shared/test/unit_test/release_helper/release_helper_12_70_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_12_70_tests.cpp @@ -115,3 +115,7 @@ TEST_F(ReleaseHelper1270Tests, whenGettingPreferredSlmSizeThenAllEntriesHaveCorr EXPECT_EQ(12u, preferredSlmValueArray[4].valueToProgram); } } + +TEST_F(ReleaseHelper1270Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_12_71_tests.cpp b/shared/test/unit_test/release_helper/release_helper_12_71_tests.cpp index 091955252f..469e1499b6 100644 --- a/shared/test/unit_test/release_helper/release_helper_12_71_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_12_71_tests.cpp @@ -116,3 +116,7 @@ TEST_F(ReleaseHelper1271Tests, whenGettingPreferredSlmSizeThenAllEntriesHaveCorr EXPECT_EQ(12u, preferredSlmValueArray[4].valueToProgram); } } + +TEST_F(ReleaseHelper1271Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_12_74_tests.cpp b/shared/test/unit_test/release_helper/release_helper_12_74_tests.cpp index a4c2a5442e..43d9addcb6 100644 --- a/shared/test/unit_test/release_helper/release_helper_12_74_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_12_74_tests.cpp @@ -121,4 +121,8 @@ TEST_F(ReleaseHelper1274Tests, whenIsBlitImageAllowedForDepthFormatCalledThenFal ASSERT_NE(nullptr, releaseHelper); EXPECT_FALSE(releaseHelper->isBlitImageAllowedForDepthFormat()); } -} \ No newline at end of file +} + +TEST_F(ReleaseHelper1274Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_20_01_tests.cpp b/shared/test/unit_test/release_helper/release_helper_20_01_tests.cpp index 68ed53fae9..60271d703a 100644 --- a/shared/test/unit_test/release_helper/release_helper_20_01_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_20_01_tests.cpp @@ -115,3 +115,7 @@ TEST_F(ReleaseHelper2001Tests, whenGettingPreferredSlmSizeThenAllEntriesHaveCorr EXPECT_EQ(6u, preferredSlmValueArray[6].valueToProgram); } } + +TEST_F(ReleaseHelper2001Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_20_02_tests.cpp b/shared/test/unit_test/release_helper/release_helper_20_02_tests.cpp index 6157fa9e8c..90eefbff35 100644 --- a/shared/test/unit_test/release_helper/release_helper_20_02_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_20_02_tests.cpp @@ -115,3 +115,7 @@ TEST_F(ReleaseHelper2002Tests, whenGettingPreferredSlmSizeThenAllEntriesHaveCorr EXPECT_EQ(6u, preferredSlmValueArray[6].valueToProgram); } } + +TEST_F(ReleaseHelper2002Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_20_04_tests.cpp b/shared/test/unit_test/release_helper/release_helper_20_04_tests.cpp index da7fa0db47..60cb43b226 100644 --- a/shared/test/unit_test/release_helper/release_helper_20_04_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_20_04_tests.cpp @@ -118,3 +118,7 @@ TEST_F(ReleaseHelper2004Tests, whenGettingPreferredSlmSizeThenAllEntriesHaveCorr EXPECT_EQ(5u, preferredSlmValueArray[5].valueToProgram); } } + +TEST_F(ReleaseHelper2004Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_30_00_tests.cpp b/shared/test/unit_test/release_helper/release_helper_30_00_tests.cpp index 54374b0a92..f886305322 100644 --- a/shared/test/unit_test/release_helper/release_helper_30_00_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_30_00_tests.cpp @@ -116,3 +116,7 @@ TEST_F(ReleaseHelper3000Tests, whenGettingPreferredSlmSizeThenAllEntriesHaveCorr EXPECT_EQ(5u, preferredSlmValueArray[5].valueToProgram); } } + +TEST_F(ReleaseHelper3000Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_30_01_tests.cpp b/shared/test/unit_test/release_helper/release_helper_30_01_tests.cpp index 06fa5db602..edb4f7f392 100644 --- a/shared/test/unit_test/release_helper/release_helper_30_01_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_30_01_tests.cpp @@ -116,3 +116,7 @@ TEST_F(ReleaseHelper3001Tests, whenGettingPreferredSlmSizeThenAllEntriesHaveCorr EXPECT_EQ(5u, preferredSlmValueArray[5].valueToProgram); } } + +TEST_F(ReleaseHelper3001Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_30_03_tests.cpp b/shared/test/unit_test/release_helper/release_helper_30_03_tests.cpp index 9c3f7b04ac..8bf9ea2056 100644 --- a/shared/test/unit_test/release_helper/release_helper_30_03_tests.cpp +++ b/shared/test/unit_test/release_helper/release_helper_30_03_tests.cpp @@ -116,3 +116,7 @@ TEST_F(ReleaseHelper3003Tests, whenGettingPreferredSlmSizeThenAllEntriesHaveCorr EXPECT_EQ(5u, preferredSlmValueArray[5].valueToProgram); } } + +TEST_F(ReleaseHelper3003Tests, whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned) { + whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); +} diff --git a/shared/test/unit_test/release_helper/release_helper_tests_base.cpp b/shared/test/unit_test/release_helper/release_helper_tests_base.cpp index 10e03958d4..55bff700d4 100644 --- a/shared/test/unit_test/release_helper/release_helper_tests_base.cpp +++ b/shared/test/unit_test/release_helper/release_helper_tests_base.cpp @@ -198,4 +198,16 @@ void ReleaseHelperTestsBase::whenIsPostImageWriteFlushRequiredCalledThenFalseRet ASSERT_NE(nullptr, releaseHelper); EXPECT_FALSE(releaseHelper->isPostImageWriteFlushRequired()); } -} \ No newline at end of file +} + +void ReleaseHelperTestsBase::whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned() { + for (auto &revision : getRevisions()) { + ipVersion.revision = revision; + releaseHelper = ReleaseHelper::create(ipVersion); + ASSERT_NE(nullptr, releaseHelper); + for (auto grfCount : releaseHelper->getSupportedNumGrfs()) { + uint32_t maxThreadsPerEuCount = 17; + EXPECT_EQ(maxThreadsPerEuCount, releaseHelper->adjustMaxThreadsPerEuCount(maxThreadsPerEuCount, grfCount)); + } + } +} diff --git a/shared/test/unit_test/release_helper/release_helper_tests_base.h b/shared/test/unit_test/release_helper/release_helper_tests_base.h index 3555096ee0..131cfc7557 100644 --- a/shared/test/unit_test/release_helper/release_helper_tests_base.h +++ b/shared/test/unit_test/release_helper/release_helper_tests_base.h @@ -37,6 +37,7 @@ struct ReleaseHelperTestsBase : public ::testing::Test { void whenIsBlitImageAllowedForDepthFormatCalledThenTrueReturned(); void whenProgrammAdditionalStallPriorToBarrierWithTimestampCalledThenFalseReturned(); void whenIsPostImageWriteFlushRequiredCalledThenFalseReturned(); + void whenCallingAdjustMaxThreadsPerEuCountThenCorrectValueIsReturned(); virtual std::vector getRevisions() = 0; std::unique_ptr releaseHelper;