gem5  v21.2.1.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 <vector>
35 
36 #include "base/cprintf.hh"
37 #include "base/gtest/logging.hh"
38 #include "mem/translation_gen.hh"
39 
40 using testing::HasSubstr;
41 using testing::Pointwise;
42 using namespace gem5;
43 
44 namespace gem5
45 {
46 
47 // A dummy fault class so we have something to return from failed translations.
48 class FaultBase {};
49 
50 } // namespace gem5
51 
52 Fault dummyFault1 = std::make_shared<gem5::FaultBase>();
53 Fault dummyFault2 = std::make_shared<gem5::FaultBase>();
54 
55 std::ostream &
56 operator<<(std::ostream &os, const TranslationGen::Range &range)
57 {
58  if (range.fault == dummyFault1)
59  ccprintf(os, "%#x=>fault1", range.vaddr);
60  else if (range.fault == dummyFault2)
61  ccprintf(os, "%#x=>fault2", range.vaddr);
62  else
63  ccprintf(os, "%#x=>%#x [%#x]", range.vaddr, range.paddr, range.size);
64  return os;
65 }
66 
68 
69 // Compare ranges which are returned by the generator.
70 MATCHER(GenRangeEq, "")
71 {
72  const auto &[actual, expected] = arg;
73  // vaddr and fault should match no matter what.
74  if (actual.vaddr != expected.vaddr || actual.fault != expected.fault)
75  return false;
76  if (expected.fault) {
77  // If there was a fault, paddr and size don't matter.
78  return true;
79  } else {
80  // If there was no fault, check paddr and size.
81  return actual.paddr == expected.paddr && actual.size == expected.size;
82  }
83 }
84 
85 // Compare ranges which are sent to the translate function.
86 MATCHER(TransRangeEq, "")
87 {
88  const auto &[actual, expected] = arg;
89  // Only the vaddr and size fields are inputs to the translate function.
90  return actual.vaddr == expected.vaddr && actual.size == expected.size;
91 }
92 
94 {
95  public:
96  // Results to return from the translate function, one by one.
98  // All the Ranges which were passed into translate from the generator.
99  mutable RangeList args;
100 
101  private:
102  // Where we are in the results vector.
104 
105  public:
106  TestTranslationGen(Addr new_start, Addr new_size,
107  std::initializer_list<Range> ranges={}) :
108  TranslationGen(new_start, new_size), results(ranges),
109  resultPos(results.begin())
110  {}
111 
112  void
113  translate(Range &range) const override
114  {
115  // First, record what range we were asked to translate.
116  args.emplace_back(range);
117  // Then, if we're not out of results to return...
118  if (resultPos != results.end()) {
119  // Record the fault we're supposed to return, if any.
120  range.fault = resultPos->fault;
121  if (!range.fault) {
122  // If there wasn't a fault, size and paddr are meaningful.
123  range.size = resultPos->size;
124  range.paddr = resultPos->paddr;
125  }
126  // Advance to the next result.
127  resultPos++;
128  }
129  }
130 };
131 
132 TEST(TranslationGen, Accessors)
133 {
134  TestTranslationGen gen1(0x10000, 0x20000);
135 
136  EXPECT_EQ(gen1.start(), 0x10000);
137  EXPECT_EQ(gen1.size(), 0x20000);
138 
139  TestTranslationGen gen2(0x3456, 0x6543);
140 
141  EXPECT_EQ(gen2.start(), 0x3456);
142  EXPECT_EQ(gen2.size(), 0x6543);
143 }
144 
145 TEST(TranslationGen, BeginAndEnd)
146 {
147  TestTranslationGen gen1(0x10000, 0x20000);
148 
149  EXPECT_NE(gen1.begin(), gen1.end());
150  EXPECT_EQ(gen1.begin(), gen1.begin());
151  EXPECT_EQ(gen1.end(), gen1.end());
152 
153  TestTranslationGen gen2(0x30000, 0x40000);
154 
155  EXPECT_NE(gen1.begin(), gen2.begin());
156  EXPECT_EQ(gen1.end(), gen2.end());
157 }
158 
159 TEST(TranslationGen, SuccessfulTwoStep)
160 {
161  TestTranslationGen gen(0x10000, 0x10000, {
162  // Results for translate.
163  {0x0, 0x8000, 0x30000, NoFault},
164  {0x0, 0x8000, 0x40000, NoFault}
165  });
166 
167  RangeList range_list;
168  for (const auto &range: gen)
169  range_list.emplace_back(range);
170 
171  // What the generator should return.
172  const RangeList expected_gen{
173  {0x10000, 0x8000, 0x30000, NoFault},
174  {0x18000, 0x8000, 0x40000, NoFault}
175  };
176  EXPECT_THAT(range_list, Pointwise(GenRangeEq(), expected_gen));
177 
178  // What the generator should have been asked to translate.
179  const RangeList expected_trans{
180  {0x10000, 0x10000, 0x0, NoFault},
181  {0x18000, 0x8000, 0x0, NoFault}
182  };
183  EXPECT_THAT(gen.args, Pointwise(TransRangeEq(), expected_trans));
184 }
185 
186 TEST(TranslationGen, RetryOnFault)
187 {
188  TestTranslationGen gen(0x10000, 0x10000, {
189  // Results for translate.
190  {0x0, 0x8000, 0x30000, NoFault},
191  {0x0, 0x0, 0x0, dummyFault1},
192  {0x0, 0x8000, 0x40000, NoFault}
193  });
194 
195  RangeList range_list;
196  for (const auto &range: gen)
197  range_list.emplace_back(range);
198 
199  // What the generator should return.
200  const RangeList expected_gen{
201  {0x10000, 0x8000, 0x30000, NoFault},
202  {0x18000, 0x0, 0x0, dummyFault1},
203  {0x18000, 0x8000, 0x40000, NoFault}
204  };
205  EXPECT_THAT(range_list, Pointwise(GenRangeEq(), expected_gen));
206 
207  // What the generator should have been asked to translate.
208  const RangeList expected_trans{
209  {0x10000, 0x10000, 0x0, NoFault},
210  {0x18000, 0x8000, 0x0, NoFault},
211  {0x18000, 0x8000, 0x0, NoFault}
212  };
213  EXPECT_THAT(gen.args, Pointwise(TransRangeEq(), expected_trans));
214 }
215 
216 TEST(TranslationGen, RetryTwiceOnFault)
217 {
218  TestTranslationGen gen(0x10000, 0x10000, {
219  // Results for translate.
220  {0x0, 0x8000, 0x30000, NoFault},
221  {0x0, 0x0, 0x0, dummyFault1},
222  {0x0, 0x0, 0x0, dummyFault2},
223  {0x0, 0x8000, 0x40000, NoFault}
224  });
225 
226  RangeList range_list;
227  for (const auto &range: gen)
228  range_list.emplace_back(range);
229 
230  // What the generator should return.
231  const RangeList expected_gen{
232  {0x10000, 0x8000, 0x30000, NoFault},
233  {0x18000, 0x0, 0x0, dummyFault1},
234  {0x18000, 0x0, 0x0, dummyFault2},
235  {0x18000, 0x8000, 0x40000, NoFault}
236  };
237  EXPECT_THAT(range_list, Pointwise(GenRangeEq(), expected_gen));
238 
239  // What the generator should have been asked to translate.
240  const RangeList expected_trans{
241  {0x10000, 0x10000, 0x0, NoFault},
242  {0x18000, 0x8000, 0x0, NoFault},
243  {0x18000, 0x8000, 0x0, NoFault},
244  {0x18000, 0x8000, 0x0, NoFault}
245  };
246  EXPECT_THAT(gen.args, Pointwise(TransRangeEq(), expected_trans));
247 }
248 
249 TEST(TranslationGen, FaultAtStart)
250 {
251  TestTranslationGen gen(0x10000, 0x10000, {
252  // Results for translate.
253  {0x0, 0x0, 0x0, dummyFault1},
254  {0x0, 0x8000, 0x30000, NoFault},
255  {0x0, 0x8000, 0x40000, NoFault}
256  });
257 
258  RangeList range_list;
259  for (const auto &range: gen)
260  range_list.emplace_back(range);
261 
262  // What the generator should return.
263  const RangeList expected_gen{
264  {0x10000, 0x0, 0x0, dummyFault1},
265  {0x10000, 0x8000, 0x30000, NoFault},
266  {0x18000, 0x8000, 0x40000, NoFault}
267  };
268  EXPECT_THAT(range_list, Pointwise(GenRangeEq(), expected_gen));
269 
270  // What the generator should have been asked to translate.
271  const RangeList expected_trans{
272  {0x10000, 0x10000, 0x0, NoFault},
273  {0x10000, 0x10000, 0x0, NoFault},
274  {0x18000, 0x8000, 0x0, NoFault}
275  };
276  EXPECT_THAT(gen.args, Pointwise(TransRangeEq(), expected_trans));
277 }
278 
279 TEST(TranslationGen, FaultInMiddle)
280 {
281  TestTranslationGen gen(0x10000, 0x18000, {
282  // Results for translate.
283  {0x0, 0x8000, 0x30000, NoFault},
284  {0x0, 0x0, 0x0, dummyFault1},
285  {0x0, 0x8000, 0x40000, NoFault},
286  {0x0, 0x8000, 0x50000, NoFault}
287  });
288 
289  RangeList range_list;
290  for (const auto &range: gen)
291  range_list.emplace_back(range);
292 
293  // What the generator should return.
294  const RangeList expected_gen{
295  {0x10000, 0x8000, 0x30000, NoFault},
296  {0x18000, 0x0, 0x0, dummyFault1},
297  {0x18000, 0x8000, 0x40000, NoFault},
298  {0x20000, 0x8000, 0x50000, NoFault}
299  };
300  EXPECT_THAT(range_list, Pointwise(GenRangeEq(), expected_gen));
301 
302  // What the generator should have been asked to translate.
303  const RangeList expected_trans{
304  {0x10000, 0x18000, 0x0, NoFault},
305  {0x18000, 0x10000, 0x0, NoFault},
306  {0x18000, 0x10000, 0x0, NoFault},
307  {0x20000, 0x8000, 0x0, NoFault}
308  };
309  EXPECT_THAT(gen.args, Pointwise(TransRangeEq(), expected_trans));
310 }
311 
312 TEST(TranslationGen, VariablePageSize)
313 {
314  TestTranslationGen gen(0x10000, 0x20000, {
315  // Results for translate.
316  {0x0, 0x8000, 0x30000, NoFault},
317  {0x0, 0x10000, 0x40000, NoFault},
318  {0x0, 0x8000, 0x50000, NoFault}
319  });
320 
321  RangeList range_list;
322  for (const auto &range: gen)
323  range_list.emplace_back(range);
324 
325  // What the generator should return.
326  const RangeList expected_gen{
327  {0x10000, 0x8000, 0x30000, NoFault},
328  {0x18000, 0x10000, 0x40000, NoFault},
329  {0x28000, 0x8000, 0x50000, NoFault}
330  };
331  EXPECT_THAT(range_list, Pointwise(GenRangeEq(), expected_gen));
332 
333  // What the generator should have been asked to translate.
334  const RangeList expected_trans{
335  {0x10000, 0x20000, 0x0, NoFault},
336  {0x18000, 0x18000, 0x0, NoFault},
337  {0x28000, 0x8000, 0x0, NoFault}
338  };
339  EXPECT_THAT(gen.args, Pointwise(TransRangeEq(), expected_trans));
340 }
341 
342 TEST(TranslationGenDeathTest, IncrementEndIterator)
343 {
344  TestTranslationGen gen(0x10000, 0x20000);
345  gtestLogOutput.str("");
346  ASSERT_ANY_THROW(gen.end()++);
347  EXPECT_THAT(gtestLogOutput.str(),
348  HasSubstr("Can't increment end iterator."));
349 }
gem5::operator<<
std::ostream & operator<<(std::ostream &os, const ArmSemihosting::InPlaceArg &ipa)
Definition: semihosting.cc:1054
gem5::TranslationGen::size
Addr size() const
Definition: translation_gen.hh:112
gem5::TranslationGen::Range::size
Addr size
Definition: translation_gen.hh:71
gem5::NoFault
constexpr decltype(nullptr) NoFault
Definition: types.hh:260
gem5::TranslationGen::start
Addr start() const
Definition: translation_gen.hh:111
gem5::TranslationGen::Range::vaddr
Addr vaddr
Definition: translation_gen.hh:70
logging.hh
gem5::TranslationGen::Range::paddr
Addr paddr
Definition: translation_gen.hh:73
TEST
TEST(TranslationGen, Accessors)
Definition: translation_gen.test.cc:132
std::vector< Range >
TestTranslationGen::TestTranslationGen
TestTranslationGen(Addr new_start, Addr new_size, std::initializer_list< Range > ranges={})
Definition: translation_gen.test.cc:106
dummyFault2
Fault dummyFault2
Definition: translation_gen.test.cc:53
gem5::ccprintf
void ccprintf(cp::Print &print)
Definition: cprintf.hh:130
gem5::TranslationGen::Range
This structure represents a single, contiguous translation, or carries information about whatever fau...
Definition: translation_gen.hh:68
dummyFault1
Fault dummyFault1
Definition: translation_gen.test.cc:52
MATCHER
MATCHER(GenRangeEq, "")
Definition: translation_gen.test.cc:70
gem5::Fault
std::shared_ptr< FaultBase > Fault
Definition: types.hh:255
gem5::TranslationGen::Range::fault
Fault fault
Definition: translation_gen.hh:74
TestTranslationGen::args
RangeList args
Definition: translation_gen.test.cc:99
translation_gen.hh
gem5::TranslationGen::end
const_iterator end() const
Definition: translation_gen.hh:259
TestTranslationGen::translate
void translate(Range &range) const override
Subclasses implement this function to complete TranslationGen.
Definition: translation_gen.test.cc:113
cprintf.hh
TestTranslationGen::results
const std::vector< Range > results
Definition: translation_gen.test.cc:97
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::TranslationGen
TranslationGen is a base class for a generator object which returns information about address transla...
Definition: translation_gen.hh:60
TestTranslationGen::resultPos
std::vector< Range >::const_iterator resultPos
Definition: translation_gen.test.cc:103
gem5::FaultBase
Definition: translation_gen.test.cc:48
gem5::X86ISA::os
Bitfield< 17 > os
Definition: misc.hh:809
TestTranslationGen
Definition: translation_gen.test.cc:93
gem5::gtestLogOutput
thread_local GTestLogOutput gtestLogOutput
Definition: logging.cc:33
std::list< TranslationGen::Range >
gem5::TranslationGen::begin
const_iterator begin() const
Definition: translation_gen.hh:253
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: tlb.cc:60
expected
std::vector< SwitchingFiber * > expected({ &a, &b, &a, &a, &a, &b, &c, &a, &c, &c, &c })

Generated on Tue Feb 8 2022 11:47:12 for gem5 by doxygen 1.8.17