1/*
2 * Copyright (c) 2018-2019 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Nikos Nikoleris
38 */
39
40#include <gtest/gtest.h>
41
42#include "base/addr_range.hh"
43#include "base/bitfield.hh"
44
45TEST(AddrRangeComp, AddrRangeIsSubset)
46{
47    AddrRange r, r1, r2;
48
49    // Test non-interleaved ranges
50    r1 = AddrRange(0x0, 0x7f);
51    r2 = AddrRange(0x80, 0xff);
52
53    r = AddrRange(0x0, 0xf);
54    EXPECT_TRUE(r.isSubset(r1));
55    EXPECT_FALSE(r.isSubset(r2));
56
57    r = AddrRange(0x80, 0x8f);
58    EXPECT_FALSE(r.isSubset(r1));
59    EXPECT_TRUE(r.isSubset(r2));
60
61    // Test interleaved ranges
62    r1 = AddrRange(0x0, 0xff, 6, 0, 1, 0);
63    r2 = AddrRange(0x0, 0xff, 6, 0, 1, 1);
64
65    r = AddrRange(0x0, 0xf);
66    EXPECT_TRUE(r.isSubset(r1));
67    EXPECT_FALSE(r.isSubset(r2));
68
69    r = AddrRange(0x40, 0x4f);
70    EXPECT_FALSE(r.isSubset(r1));
71    EXPECT_TRUE(r.isSubset(r2));
72
73    r = AddrRange(0xbf, 0xc0);
74    EXPECT_FALSE(r.isSubset(r1));
75    EXPECT_FALSE(r.isSubset(r2));
76
77    // Test interleaved ranges with hashing
78    r1 = AddrRange(0x0, 0xff, 6, 7, 1, 0);
79    r2 = AddrRange(0x0, 0xff, 6, 7, 1, 1);
80
81    r = AddrRange(0x0, 0xf);
82    EXPECT_TRUE(r.isSubset(r1));
83    EXPECT_FALSE(r.isSubset(r2));
84
85    r = AddrRange(0x40, 0x4f);
86    EXPECT_FALSE(r.isSubset(r1));
87    EXPECT_TRUE(r.isSubset(r2));
88
89    r = AddrRange(0xbf, 0xc0);
90    EXPECT_FALSE(r.isSubset(r1));
91    EXPECT_FALSE(r.isSubset(r2));
92}
93
94class AddrRangeBase : public testing::Test {
95  protected:
96
97    virtual int getIndex(Addr addr) = 0;
98
99    void testContains()
100    {
101        for (Addr addr = start; addr <= end; addr++) {
102            int i = getIndex(addr);
103            ASSERT_TRUE(range[i].contains(addr));
104            for (int j = 1; j < intlvSize; j++) {
105                ASSERT_FALSE(range[(i + j) % intlvSize].contains(addr));
106            }
107        }
108    }
109
110    void testGetOffset()
111    {
112        Addr offsets[intlvSize] = {0, 0, 0, 0};
113        for (Addr addr = start; addr <= end; addr++) {
114            int i = getIndex(addr);
115            Addr offset = range[i].getOffset(addr);
116            ASSERT_EQ(offsets[i], offset);
117            offsets[i]++;
118        }
119        for (Addr offset: offsets) {
120            ASSERT_EQ(offset, (end - start + 1) / intlvSize);
121        }
122    }
123
124    static const Addr end = 0x1ffff;
125    static const Addr start = 0x0;
126    static const int intlvSize = 4;
127
128    AddrRange range[intlvSize];
129};
130
131
132class AddrRangeCont : public AddrRangeBase {
133  protected:
134    void SetUp() override
135    {
136        std::vector<Addr> masks = {
137            1UL << xorBits0[0] | 1UL << xorBits0[1],
138            1UL << xorBits1[0] | 1UL << xorBits1[1]
139        };
140        for (auto i = 0; i < intlvSize; i++) {
141            range[i] = AddrRange(start, end, masks, i);
142        }
143    }
144
145    int getIndex(Addr addr) override
146    {
147        return bits(addr, xorBits1[1], xorBits0[1]) ^
148            bits(addr, xorBits1[0], xorBits0[0]);
149    }
150
151    const int xorBits0[2] = {8, 14};
152    const int xorBits1[2] = {9, 15};
153};
154
155TEST_F(AddrRangeCont, AddrRangeContains)
156{
157    testContains();
158}
159
160TEST_F(AddrRangeCont, AddrRangeGetOffset)
161{
162    testGetOffset();
163}
164
165
166class AddrRangeContLegacy : public AddrRangeCont {
167  protected:
168    void SetUp() override
169    {
170        // Test interleaved ranges with hashing
171        for (auto i = 0; i < intlvSize; i++) {
172            range[i] = AddrRange(start, end, xorBits1[0], xorBits1[1],
173                                 2, i);
174        }
175    }
176};
177
178TEST_F(AddrRangeContLegacy, AddrRangeContains)
179{
180    testContains();
181}
182
183TEST_F(AddrRangeContLegacy, AddrRangeGetOffset)
184{
185    testGetOffset();
186}
187
188
189class AddrRangeArb : public AddrRangeBase {
190  protected:
191    void SetUp() override
192    {
193        std::vector<Addr> masks = {
194            1UL << xorBits0[0] | 1UL << xorBits0[1],
195            1UL << xorBits1[0] | 1UL << xorBits1[1]
196        };
197        for (auto i = 0; i < intlvSize; i++) {
198            range[i] = AddrRange(start, end, masks, i);
199        }
200    }
201
202    int getIndex(Addr addr) override
203    {
204        return (bits(addr, xorBits0[0]) ^ bits(addr, xorBits0[1])) |
205            (bits(addr, xorBits1[0]) ^ bits(addr, xorBits1[1])) << 1;
206    }
207
208    const int xorBits0[2] = {11, 12};
209    const int xorBits1[2] = {8, 15};
210};
211
212TEST_F(AddrRangeArb, AddrRangeContains)
213{
214    testContains();
215}
216
217TEST_F(AddrRangeArb, AddrRangeGetOffset)
218{
219    testGetOffset();
220}
221