1 /*
2  * Copyright (C) 2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #include "shared/source/memory_manager/memory_banks.h"
9 #include "shared/source/memory_manager/physical_address_allocator.h"
10 #include "shared/test/common/mocks/mock_physical_address_allocator.h"
11 #include "shared/test/common/test_macros/test.h"
12 
13 using namespace NEO;
14 
15 template <typename GfxFamily>
16 class MockPhysicalAddressAllocatorHw : public PhysicalAddressAllocatorHw<GfxFamily> {
17   public:
18     using PhysicalAddressAllocator::initialPageAddress;
19     using PhysicalAddressAllocator::mainAllocator;
20     using PhysicalAddressAllocatorHw<GfxFamily>::bankAllocators;
21     using PhysicalAddressAllocatorHw<GfxFamily>::memoryBankSize;
22     using PhysicalAddressAllocatorHw<GfxFamily>::numberOfBanks;
23     using PhysicalAddressAllocatorHw<GfxFamily>::PhysicalAddressAllocatorHw;
24 
MockPhysicalAddressAllocatorHw()25     MockPhysicalAddressAllocatorHw() : PhysicalAddressAllocatorHw<GfxFamily>(MemoryConstants::gigaByte, 4) {}
26 };
27 
28 using PhysicalAddressAllocatorHwTest = ::testing::Test;
29 
HWTEST_F(PhysicalAddressAllocatorHwTest,givenZeroBanksWhenPageInBankIsReservedThenMainAllocatorIsUsed)30 HWTEST_F(PhysicalAddressAllocatorHwTest, givenZeroBanksWhenPageInBankIsReservedThenMainAllocatorIsUsed) {
31     size_t bankSize = 1024 * MemoryConstants::pageSize;
32     MockPhysicalAddressAllocatorHw<FamilyType> allocator(bankSize, 0);
33 
34     auto physAddress = allocator.reserve4kPage(MemoryBanks::getBankForLocalMemory(1));
35     EXPECT_NE(0u, physAddress);
36     auto address = allocator.mainAllocator.load();
37 
38     auto physAddress1 = allocator.reserve4kPage(MemoryBanks::getBankForLocalMemory(1));
39     EXPECT_NE(0u, physAddress1);
40     EXPECT_NE(physAddress, physAddress1);
41 
42     auto address1 = allocator.mainAllocator.load();
43 
44     EXPECT_NE(address, address1);
45 }
46 
HWTEST_F(PhysicalAddressAllocatorHwTest,given4BanksWhenAllocatorIsCreatedThen4AllocatorsAreCreated)47 HWTEST_F(PhysicalAddressAllocatorHwTest, given4BanksWhenAllocatorIsCreatedThen4AllocatorsAreCreated) {
48     MockPhysicalAddressAllocatorHw<FamilyType> allocator(2 * MemoryConstants::megaByte, 4);
49     EXPECT_NE(nullptr, allocator.bankAllocators);
50     EXPECT_EQ(4u, allocator.numberOfBanks);
51     EXPECT_EQ(2 * MemoryConstants::megaByte, allocator.memoryBankSize);
52 }
53 
HWTEST_F(PhysicalAddressAllocatorHwTest,given4BanksWhenReservingFirstPageInBanksThenNonZeroAddressIsReturnedAndEachBankAddressIsDifferent)54 HWTEST_F(PhysicalAddressAllocatorHwTest, given4BanksWhenReservingFirstPageInBanksThenNonZeroAddressIsReturnedAndEachBankAddressIsDifferent) {
55     MockPhysicalAddressAllocatorHw<FamilyType> allocator(2 * MemoryConstants::megaByte, 4);
56     auto physAddress0 = allocator.reserve4kPage(MemoryBanks::getBankForLocalMemory(0));
57     EXPECT_NE(0u, physAddress0);
58     auto physAddress1 = allocator.reserve4kPage(MemoryBanks::getBankForLocalMemory(1));
59     EXPECT_NE(0u, physAddress1);
60     auto physAddress2 = allocator.reserve4kPage(MemoryBanks::getBankForLocalMemory(2));
61     EXPECT_NE(0u, physAddress2);
62     auto physAddress3 = allocator.reserve4kPage(MemoryBanks::getBankForLocalMemory(3));
63     EXPECT_NE(0u, physAddress3);
64 
65     EXPECT_NE(physAddress0, physAddress1);
66     EXPECT_NE(physAddress0, physAddress2);
67     EXPECT_NE(physAddress0, physAddress3);
68     EXPECT_NE(physAddress1, physAddress2);
69     EXPECT_NE(physAddress1, physAddress3);
70     EXPECT_NE(physAddress2, physAddress3);
71 }
72 
HWTEST_F(PhysicalAddressAllocatorHwTest,given4BanksWhenReservingFirstPageInBanksThenEveryNextBankAddressIsOffsetedByBankSize)73 HWTEST_F(PhysicalAddressAllocatorHwTest, given4BanksWhenReservingFirstPageInBanksThenEveryNextBankAddressIsOffsetedByBankSize) {
74     size_t bankSize = 4 * 1024 * MemoryConstants::pageSize;
75     MockPhysicalAddressAllocatorHw<FamilyType> allocator(bankSize, 4);
76     auto physAddress0 = allocator.reserve4kPage(MemoryBanks::getBankForLocalMemory(0));
77     EXPECT_EQ(0x1000u, physAddress0);
78 
79     auto physAddress1 = allocator.reserve4kPage(MemoryBanks::getBankForLocalMemory(1));
80     EXPECT_EQ(bankSize, physAddress1);
81 
82     auto physAddress2 = allocator.reserve4kPage(MemoryBanks::getBankForLocalMemory(2));
83     EXPECT_EQ(2 * bankSize, physAddress2);
84 
85     auto physAddress3 = allocator.reserve4kPage(MemoryBanks::getBankForLocalMemory(3));
86     EXPECT_EQ(3 * bankSize, physAddress3);
87 }
88 
HWTEST_F(PhysicalAddressAllocatorHwTest,givenSpecificBankWhenReservingConsecutivePagesThenReturnedAddressesAreDifferent)89 HWTEST_F(PhysicalAddressAllocatorHwTest, givenSpecificBankWhenReservingConsecutivePagesThenReturnedAddressesAreDifferent) {
90     auto bankSize = 4 * 1024 * MemoryConstants::pageSize;
91     MockPhysicalAddressAllocatorHw<FamilyType> allocator(bankSize, 4);
92 
93     uint32_t banks[4] = {MemoryBanks::getBankForLocalMemory(0),
94                          MemoryBanks::getBankForLocalMemory(1),
95                          MemoryBanks::getBankForLocalMemory(2),
96                          MemoryBanks::getBankForLocalMemory(3)};
97 
98     for (uint32_t bankIndex = 0; bankIndex < 4; bankIndex++) {
99         auto physAddress = allocator.reserve4kPage(banks[bankIndex]);
100         EXPECT_NE(0u, physAddress);
101         auto physAddress1 = allocator.reserve4kPage(banks[bankIndex]);
102         EXPECT_NE(physAddress, physAddress1);
103         auto physAddress2 = allocator.reserve4kPage(banks[bankIndex]);
104         EXPECT_NE(physAddress1, physAddress2);
105     }
106 }
107 
HWTEST_F(PhysicalAddressAllocatorHwTest,givenSingleBankWhen4kAnd64kPagesAreAllocatedAlternatelyThenCorrectAlignementIsSatisfied)108 HWTEST_F(PhysicalAddressAllocatorHwTest, givenSingleBankWhen4kAnd64kPagesAreAllocatedAlternatelyThenCorrectAlignementIsSatisfied) {
109     size_t bankSize = 4 * 1024 * MemoryConstants::pageSize;
110     MockPhysicalAddressAllocatorHw<FamilyType> allocator(bankSize, 4);
111     auto physAddress0 = allocator.reserve4kPage(MemoryBanks::getBankForLocalMemory(0));
112     EXPECT_NE(0u, physAddress0);
113     EXPECT_EQ(0u, physAddress0 & MemoryConstants::pageMask);
114 
115     auto physAddress1 = allocator.reserve64kPage(MemoryBanks::getBankForLocalMemory(0));
116     EXPECT_NE(0u, physAddress1);
117     EXPECT_EQ(0u, physAddress1 & MemoryConstants::page64kMask);
118 
119     auto physAddress2 = allocator.reserve4kPage(MemoryBanks::getBankForLocalMemory(0));
120     EXPECT_NE(0u, physAddress2);
121     EXPECT_EQ(0u, physAddress2 & MemoryConstants::pageMask);
122 
123     auto physAddress3 = allocator.reserve64kPage(MemoryBanks::getBankForLocalMemory(0));
124     EXPECT_NE(0u, physAddress3);
125     EXPECT_EQ(0u, physAddress3 & MemoryConstants::page64kMask);
126 }
127 
TEST(MemoryBank,givenDifferentDeviceOrdinalsWhenGettingBankThenCorrectBanksAreReturned)128 TEST(MemoryBank, givenDifferentDeviceOrdinalsWhenGettingBankThenCorrectBanksAreReturned) {
129     auto bank = MemoryBanks::getBankForLocalMemory(0);
130     EXPECT_EQ(1u, bank);
131 
132     bank = MemoryBanks::getBankForLocalMemory(1);
133     EXPECT_EQ(2u, bank);
134 
135     bank = MemoryBanks::getBankForLocalMemory(2);
136     EXPECT_EQ(3u, bank);
137 
138     bank = MemoryBanks::getBankForLocalMemory(3);
139     EXPECT_EQ(4u, bank);
140 }
141