gem5 v23.0.0.1
Loading...
Searching...
No Matches
translation_gen.test.cc
Go to the documentation of this file.
1/*
2 * Copyright 2021 Google, Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met: redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer;
8 * redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution;
11 * neither the name of the copyright holders nor the names of its
12 * contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <gmock/gmock.h>
29#include <gtest/gtest.h>
30
31#include <initializer_list>
32#include <list>
33#include <memory>
34#include <ostream>
35#include <vector>
36
37#include "base/cprintf.hh"
38#include "base/gtest/logging.hh"
40
41using testing::HasSubstr;
42using testing::Pointwise;
43using namespace gem5;
44
45namespace gem5
46{
47
48// A dummy fault class so we have something to return from failed translations.
49class FaultBase {};
50
51Fault dummyFault1 = std::make_shared<gem5::FaultBase>();
52Fault dummyFault2 = std::make_shared<gem5::FaultBase>();
53
54std::ostream &
55operator<<(std::ostream &os, const TranslationGen::Range &range)
56{
57 if (range.fault == dummyFault1)
58 ccprintf(os, "%#x=>fault1", range.vaddr);
59 else if (range.fault == dummyFault2)
60 ccprintf(os, "%#x=>fault2", range.vaddr);
61 else
62 ccprintf(os, "%#x=>%#x [%#x]", range.vaddr, range.paddr, range.size);
63 return os;
64}
65
66} // namespace gem5
67
69
70// Compare ranges which are returned by the generator.
71MATCHER(GenRangeEq, "")
72{
73 const auto &[actual, expected] = arg;
74 // vaddr and fault should match no matter what.
75 if (actual.vaddr != expected.vaddr || actual.fault != expected.fault)
76 return false;
77 if (expected.fault) {
78 // If there was a fault, paddr and size don't matter.
79 return true;
80 } else {
81 // If there was no fault, check paddr and size.
82 return actual.paddr == expected.paddr && actual.size == expected.size;
83 }
84}
85
86// Compare ranges which are sent to the translate function.
87MATCHER(TransRangeEq, "")
88{
89 const auto &[actual, expected] = arg;
90 // Only the vaddr and size fields are inputs to the translate function.
91 return actual.vaddr == expected.vaddr && actual.size == expected.size;
92}
93
95{
96 public:
97 // Results to return from the translate function, one by one.
99 // All the Ranges which were passed into translate from the generator.
101
102 private:
103 // Where we are in the results vector.
105
106 public:
107 TestTranslationGen(Addr new_start, Addr new_size,
108 std::initializer_list<Range> ranges={}) :
109 TranslationGen(new_start, new_size), results(ranges),
111 {}
112
113 void
114 translate(Range &range) const override
115 {
116 // First, record what range we were asked to translate.
117 args.emplace_back(range);
118 // Then, if we're not out of results to return...
119 if (resultPos != results.end()) {
120 // Record the fault we're supposed to return, if any.
121 range.fault = resultPos->fault;
122 if (!range.fault) {
123 // If there wasn't a fault, size and paddr are meaningful.
124 range.size = resultPos->size;
125 range.paddr = resultPos->paddr;
126 }
127 // Advance to the next result.
128 resultPos++;
129 }
130 }
131};
132
134{
135 TestTranslationGen gen1(0x10000, 0x20000);
136
137 EXPECT_EQ(gen1.start(), 0x10000);
138 EXPECT_EQ(gen1.size(), 0x20000);
139
140 TestTranslationGen gen2(0x3456, 0x6543);
141
142 EXPECT_EQ(gen2.start(), 0x3456);
143 EXPECT_EQ(gen2.size(), 0x6543);
144}
145
146TEST(TranslationGen, BeginAndEnd)
147{
148 TestTranslationGen gen1(0x10000, 0x20000);
149
150 EXPECT_NE(gen1.begin(), gen1.end());
151 EXPECT_EQ(gen1.begin(), gen1.begin());
152 EXPECT_EQ(gen1.end(), gen1.end());
153
154 TestTranslationGen gen2(0x30000, 0x40000);
155
156 EXPECT_NE(gen1.begin(), gen2.begin());
157 EXPECT_EQ(gen1.end(), gen2.end());
158}
159
160TEST(TranslationGen, SuccessfulTwoStep)
161{
162 TestTranslationGen gen(0x10000, 0x10000, {
163 // Results for translate.
164 {0x0, 0x8000, 0x30000, NoFault},
165 {0x0, 0x8000, 0x40000, NoFault}
166 });
167
168 RangeList range_list;
169 for (const auto &range: gen)
170 range_list.emplace_back(range);
171
172 // What the generator should return.
173 const RangeList expected_gen{
174 {0x10000, 0x8000, 0x30000, NoFault},
175 {0x18000, 0x8000, 0x40000, NoFault}
176 };
177 EXPECT_THAT(range_list, Pointwise(GenRangeEq(), expected_gen));
178
179 // What the generator should have been asked to translate.
180 const RangeList expected_trans{
181 {0x10000, 0x10000, 0x0, NoFault},
182 {0x18000, 0x8000, 0x0, NoFault}
183 };
184 EXPECT_THAT(gen.args, Pointwise(TransRangeEq(), expected_trans));
185}
186
187TEST(TranslationGen, RetryOnFault)
188{
189 TestTranslationGen gen(0x10000, 0x10000, {
190 // Results for translate.
191 {0x0, 0x8000, 0x30000, NoFault},
192 {0x0, 0x0, 0x0, dummyFault1},
193 {0x0, 0x8000, 0x40000, NoFault}
194 });
195
196 RangeList range_list;
197 for (const auto &range: gen)
198 range_list.emplace_back(range);
199
200 // What the generator should return.
201 const RangeList expected_gen{
202 {0x10000, 0x8000, 0x30000, NoFault},
203 {0x18000, 0x0, 0x0, dummyFault1},
204 {0x18000, 0x8000, 0x40000, NoFault}
205 };
206 EXPECT_THAT(range_list, Pointwise(GenRangeEq(), expected_gen));
207
208 // What the generator should have been asked to translate.
209 const RangeList expected_trans{
210 {0x10000, 0x10000, 0x0, NoFault},
211 {0x18000, 0x8000, 0x0, NoFault},
212 {0x18000, 0x8000, 0x0, NoFault}
213 };
214 EXPECT_THAT(gen.args, Pointwise(TransRangeEq(), expected_trans));
215}
216
217TEST(TranslationGen, RetryTwiceOnFault)
218{
219 TestTranslationGen gen(0x10000, 0x10000, {
220 // Results for translate.
221 {0x0, 0x8000, 0x30000, NoFault},
222 {0x0, 0x0, 0x0, dummyFault1},
223 {0x0, 0x0, 0x0, dummyFault2},
224 {0x0, 0x8000, 0x40000, NoFault}
225 });
226
227 RangeList range_list;
228 for (const auto &range: gen)
229 range_list.emplace_back(range);
230
231 // What the generator should return.
232 const RangeList expected_gen{
233 {0x10000, 0x8000, 0x30000, NoFault},
234 {0x18000, 0x0, 0x0, dummyFault1},
235 {0x18000, 0x0, 0x0, dummyFault2},
236 {0x18000, 0x8000, 0x40000, NoFault}
237 };
238 EXPECT_THAT(range_list, Pointwise(GenRangeEq(), expected_gen));
239
240 // What the generator should have been asked to translate.
241 const RangeList expected_trans{
242 {0x10000, 0x10000, 0x0, NoFault},
243 {0x18000, 0x8000, 0x0, NoFault},
244 {0x18000, 0x8000, 0x0, NoFault},
245 {0x18000, 0x8000, 0x0, NoFault}
246 };
247 EXPECT_THAT(gen.args, Pointwise(TransRangeEq(), expected_trans));
248}
249
250TEST(TranslationGen, FaultAtStart)
251{
252 TestTranslationGen gen(0x10000, 0x10000, {
253 // Results for translate.
254 {0x0, 0x0, 0x0, dummyFault1},
255 {0x0, 0x8000, 0x30000, NoFault},
256 {0x0, 0x8000, 0x40000, NoFault}
257 });
258
259 RangeList range_list;
260 for (const auto &range: gen)
261 range_list.emplace_back(range);
262
263 // What the generator should return.
264 const RangeList expected_gen{
265 {0x10000, 0x0, 0x0, dummyFault1},
266 {0x10000, 0x8000, 0x30000, NoFault},
267 {0x18000, 0x8000, 0x40000, NoFault}
268 };
269 EXPECT_THAT(range_list, Pointwise(GenRangeEq(), expected_gen));
270
271 // What the generator should have been asked to translate.
272 const RangeList expected_trans{
273 {0x10000, 0x10000, 0x0, NoFault},
274 {0x10000, 0x10000, 0x0, NoFault},
275 {0x18000, 0x8000, 0x0, NoFault}
276 };
277 EXPECT_THAT(gen.args, Pointwise(TransRangeEq(), expected_trans));
278}
279
280TEST(TranslationGen, FaultInMiddle)
281{
282 TestTranslationGen gen(0x10000, 0x18000, {
283 // Results for translate.
284 {0x0, 0x8000, 0x30000, NoFault},
285 {0x0, 0x0, 0x0, dummyFault1},
286 {0x0, 0x8000, 0x40000, NoFault},
287 {0x0, 0x8000, 0x50000, NoFault}
288 });
289
290 RangeList range_list;
291 for (const auto &range: gen)
292 range_list.emplace_back(range);
293
294 // What the generator should return.
295 const RangeList expected_gen{
296 {0x10000, 0x8000, 0x30000, NoFault},
297 {0x18000, 0x0, 0x0, dummyFault1},
298 {0x18000, 0x8000, 0x40000, NoFault},
299 {0x20000, 0x8000, 0x50000, NoFault}
300 };
301 EXPECT_THAT(range_list, Pointwise(GenRangeEq(), expected_gen));
302
303 // What the generator should have been asked to translate.
304 const RangeList expected_trans{
305 {0x10000, 0x18000, 0x0, NoFault},
306 {0x18000, 0x10000, 0x0, NoFault},
307 {0x18000, 0x10000, 0x0, NoFault},
308 {0x20000, 0x8000, 0x0, NoFault}
309 };
310 EXPECT_THAT(gen.args, Pointwise(TransRangeEq(), expected_trans));
311}
312
313TEST(TranslationGen, VariablePageSize)
314{
315 TestTranslationGen gen(0x10000, 0x20000, {
316 // Results for translate.
317 {0x0, 0x8000, 0x30000, NoFault},
318 {0x0, 0x10000, 0x40000, NoFault},
319 {0x0, 0x8000, 0x50000, NoFault}
320 });
321
322 RangeList range_list;
323 for (const auto &range: gen)
324 range_list.emplace_back(range);
325
326 // What the generator should return.
327 const RangeList expected_gen{
328 {0x10000, 0x8000, 0x30000, NoFault},
329 {0x18000, 0x10000, 0x40000, NoFault},
330 {0x28000, 0x8000, 0x50000, NoFault}
331 };
332 EXPECT_THAT(range_list, Pointwise(GenRangeEq(), expected_gen));
333
334 // What the generator should have been asked to translate.
335 const RangeList expected_trans{
336 {0x10000, 0x20000, 0x0, NoFault},
337 {0x18000, 0x18000, 0x0, NoFault},
338 {0x28000, 0x8000, 0x0, NoFault}
339 };
340 EXPECT_THAT(gen.args, Pointwise(TransRangeEq(), expected_trans));
341}
342
343TEST(TranslationGenDeathTest, IncrementEndIterator)
344{
345 TestTranslationGen gen(0x10000, 0x20000);
346 gtestLogOutput.str("");
347 ASSERT_ANY_THROW(gen.end()++);
348 EXPECT_THAT(gtestLogOutput.str(),
349 HasSubstr("Can't increment end iterator."));
350}
const std::vector< Range > results
TestTranslationGen(Addr new_start, Addr new_size, std::initializer_list< Range > ranges={})
void translate(Range &range) const override
Subclasses implement this function to complete TranslationGen.
std::vector< Range >::const_iterator resultPos
TranslationGen is a base class for a generator object which returns information about address transla...
const_iterator begin() const
const_iterator end() const
STL vector class.
Definition stl.hh:37
std::vector< SwitchingFiber * > expected({ &a, &b, &a, &a, &a, &b, &c, &a, &c, &c, &c })
Bitfield< 17 > os
Definition misc.hh:810
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::shared_ptr< FaultBase > Fault
Definition types.hh:249
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
std::ostream & operator<<(std::ostream &os, const ArmSemihosting::InPlaceArg &ipa)
thread_local GTestLogOutput gtestLogOutput
Definition logging.cc:33
constexpr decltype(nullptr) NoFault
Definition types.hh:253
void ccprintf(cp::Print &print)
Definition cprintf.hh:130
This structure represents a single, contiguous translation, or carries information about whatever fau...
TEST(TranslationGen, Accessors)
MATCHER(GenRangeEq, "")

Generated on Mon Jul 10 2023 15:32:05 for gem5 by doxygen 1.9.7