gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
reg_bank.test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 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  * Copyright 2020 Google, Inc.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions are
18  * met: redistributions of source code must retain the above copyright
19  * notice, this list of conditions and the following disclaimer;
20  * redistributions in binary form must reproduce the above copyright
21  * notice, this list of conditions and the following disclaimer in the
22  * documentation and/or other materials provided with the distribution;
23  * neither the name of the copyright holders nor the names of its
24  * contributors may be used to endorse or promote products derived from
25  * this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 #pragma GCC diagnostic push
41 
42 // __GNUC__ defined for both clang and gcc
43 // -Wdeprecated-copy has been added in clang10.0.0 and gcc9.0
44 #if defined(__GNUC__)
45 # if (defined(__clang__) && __GNUC__ >= 10) || \
46  (!defined(__clang__) && __GNUC__ >= 9)
47 # pragma GCC diagnostic ignored "-Wdeprecated-copy"
48 # endif
49 #endif
50 
51 #include <gmock/gmock.h>
52 #include <gtest/gtest.h>
53 
54 #pragma GCC diagnostic pop
55 
56 #include <vector>
57 
58 #include "base/gtest/logging.hh"
59 #include "dev/reg_bank.hh"
60 
61 using namespace gem5;
62 
63 // Compare the elements of an array against expected values.
64 using testing::ElementsAre;
65 // This version is needed with enough elements, empirically more than 10.
66 using testing::ElementsAreArray;
67 
68 using testing::AllOf;
69 using testing::HasSubstr;
70 
71 
72 /*
73  * The RegisterRaz (read as zero) type.
74  */
75 
76 class RegisterRazTest : public testing::Test
77 {
78  protected:
79  static constexpr size_t BufSize = 12;
80  static constexpr size_t BufOffset = 4;
81  static constexpr size_t RazSize = 4;
82 
83  std::array<uint8_t, BufSize> buf;
84  RegisterBankLE::RegisterRaz raz;
85 
86  RegisterRazTest() : raz("raz", RazSize)
87  {
88  buf.fill(0xff);
89  }
90 };
91 // Needed by C++14 and lower
92 constexpr size_t RegisterRazTest::RazSize;
93 
95 {
96  EXPECT_EQ(raz.name(), "raz");
97 }
98 
100 {
101  EXPECT_EQ(raz.size(), RazSize);
102 }
103 
104 // Accessing the entire register at once.
106 {
107  raz.write(buf.data() + BufOffset);
108  raz.read(buf.data() + BufOffset);
109  EXPECT_THAT(buf, ElementsAreArray({0xff, 0xff, 0xff, 0xff,
110  0x00, 0x00, 0x00, 0x00,
111  0xff, 0xff, 0xff, 0xff}));
112 }
113 
114 // Partial access, excluding the start of the register.
115 TEST_F(RegisterRazTest, PartialAccessHigh)
116 {
117  raz.write(buf.data() + BufOffset, 1, 3);
118  raz.read(buf.data() + BufOffset, 1, 3);
119  EXPECT_THAT(buf, ElementsAreArray({0xff, 0xff, 0xff, 0xff,
120  0x00, 0x00, 0x00, 0xff,
121  0xff, 0xff, 0xff, 0xff}));
122 }
123 
124 // Partial access, excluding the end of the register.
125 TEST_F(RegisterRazTest, PartialAccessLow)
126 {
127  raz.write(buf.data() + BufOffset, 0, 3);
128  raz.read(buf.data() + BufOffset, 0, 3);
129  EXPECT_THAT(buf, ElementsAreArray({0xff, 0xff, 0xff, 0xff,
130  0x00, 0x00, 0x00, 0xff,
131  0xff, 0xff, 0xff, 0xff}));
132 }
133 
134 // Partial access, excluding both ends of the register.
135 TEST_F(RegisterRazTest, PartialAccessMid)
136 {
137  raz.write(buf.data() + BufOffset, 1, 2);
138  raz.read(buf.data() + BufOffset, 1, 2);
139  EXPECT_THAT(buf, ElementsAreArray({0xff, 0xff, 0xff, 0xff,
140  0x00, 0x00, 0xff, 0xff,
141  0xff, 0xff, 0xff, 0xff}));
142 }
143 
145 {
146  std::ostringstream os;
147  raz.serialize(os);
148  EXPECT_EQ(os.str(), "");
149 }
150 
151 TEST_F(RegisterRazTest, Unserialize)
152 {
153  std::string s;
154  EXPECT_TRUE(raz.unserialize(s));
155 }
156 
157 
158 /*
159  * The RegisterRao (read as one) type.
160  */
161 
162 class RegisterRaoTest : public testing::Test
163 {
164  protected:
165  static constexpr size_t BufSize = 12;
166  static constexpr size_t BufOffset = 4;
167  static constexpr size_t RaoSize = 4;
168 
169  std::array<uint8_t, BufSize> buf;
170  RegisterBankLE::RegisterRao rao;
171 
172  RegisterRaoTest() : rao("rao", RaoSize)
173  {
174  buf.fill(0x00);
175  }
176 };
177 // Needed by C++14 and lower
178 constexpr size_t RegisterRaoTest::RaoSize;
179 
181 {
182  EXPECT_EQ(rao.name(), "rao");
183 }
184 
186 {
187  EXPECT_EQ(rao.size(), RaoSize);
188 }
189 
190 // Accessing the entire register at once.
192 {
193  rao.write(buf.data() + BufOffset);
194  rao.read(buf.data() + BufOffset);
195  EXPECT_THAT(buf, ElementsAreArray({0x00, 0x00, 0x00, 0x00,
196  0xff, 0xff, 0xff, 0xff,
197  0x00, 0x00, 0x00, 0x00}));
198 }
199 
200 // Partial access, excluding the start of the register.
201 TEST_F(RegisterRaoTest, PartialAccessHigh)
202 {
203  rao.write(buf.data() + BufOffset, 1, 3);
204  rao.read(buf.data() + BufOffset, 1, 3);
205  EXPECT_THAT(buf, ElementsAreArray({0x00, 0x00, 0x00, 0x00,
206  0xff, 0xff, 0xff, 0x00,
207  0x00, 0x00, 0x00, 0x00}));
208 }
209 
210 // Partial access, excluding the end of the register.
211 TEST_F(RegisterRaoTest, PartialAccessLow)
212 {
213  rao.write(buf.data() + BufOffset, 0, 3);
214  rao.read(buf.data() + BufOffset, 0, 3);
215  EXPECT_THAT(buf, ElementsAreArray({0x00, 0x00, 0x00, 0x00,
216  0xff, 0xff, 0xff, 0x00,
217  0x00, 0x00, 0x00, 0x00}));
218 }
219 
220 // Partial access, excluding both ends of the register.
221 TEST_F(RegisterRaoTest, PartialAccessMid)
222 {
223  rao.write(buf.data() + BufOffset, 1, 2);
224  rao.read(buf.data() + BufOffset, 1, 2);
225  EXPECT_THAT(buf, ElementsAreArray({0x00, 0x00, 0x00, 0x00,
226  0xff, 0xff, 0x00, 0x00,
227  0x00, 0x00, 0x00, 0x00}));
228 }
229 
231 {
232  std::ostringstream os;
233  rao.serialize(os);
234  EXPECT_EQ(os.str(), "");
235 }
236 
237 TEST_F(RegisterRaoTest, Unserialize)
238 {
239  std::string s;
240  EXPECT_TRUE(rao.unserialize(s));
241 }
242 
243 
244 /*
245  * The RegisterBuf type.
246  */
247 
248 class RegisterBufTest : public testing::Test
249 {
250  protected:
251  static constexpr size_t RegSize = 4;
252 
253  std::array<uint8_t, RegSize * 3> buf;
254  std::array<uint8_t, RegSize * 3> backing;
255 
256  RegisterBankLE::RegisterBuf reg;
257 
258  public:
260  : buf{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc},
261  backing{0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
262  0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0},
263  reg("buf_reg", backing.data() + RegSize, RegSize)
264  {}
265 };
266 // Needed by C++14 and lower
267 constexpr size_t RegisterBufTest::RegSize;
268 
270 {
271  EXPECT_EQ(reg.name(), "buf_reg");
272 }
273 
275 {
276  EXPECT_EQ(reg.size(), RegSize);
277 }
278 
279 // Read the entire register.
281 {
282  reg.read(buf.data() + RegSize);
283  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
284  0x50, 0x60, 0x70, 0x80,
285  0x9, 0xa, 0xb, 0xc}));
286  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
287  0x50, 0x60, 0x70, 0x80,
288  0x90, 0xa0, 0xb0, 0xc0}));
289 }
290 
291 // Write the entire register.
293 {
294  reg.write(buf.data() + RegSize);
295  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
296  0x5, 0x6, 0x7, 0x8,
297  0x9, 0xa, 0xb, 0xc}));
298  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
299  0x5, 0x6, 0x7, 0x8,
300  0x90, 0xa0, 0xb0, 0xc0}));
301 }
302 
303 // Partial read, excluding the start of the register.
304 TEST_F(RegisterBufTest, PartialReadHigh)
305 {
306  reg.read(buf.data() + RegSize, 1, 3);
307  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
308  0x60, 0x70, 0x80, 0x8,
309  0x9, 0xa, 0xb, 0xc}));
310  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
311  0x50, 0x60, 0x70, 0x80,
312  0x90, 0xa0, 0xb0, 0xc0}));
313 }
314 
315 // Partial write, excluding the start of the register.
316 TEST_F(RegisterBufTest, PartialWriteHigh)
317 {
318  reg.write(buf.data() + RegSize, 1, 3);
319  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
320  0x5, 0x6, 0x7, 0x8,
321  0x9, 0xa, 0xb, 0xc}));
322  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
323  0x50, 0x5, 0x6, 0x7,
324  0x90, 0xa0, 0xb0, 0xc0}));
325 }
326 
327 // Partial read, excluding the end of the register.
328 TEST_F(RegisterBufTest, PartialReadLow)
329 {
330  reg.read(buf.data() + RegSize, 0, 3);
331  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
332  0x50, 0x60, 0x70, 0x8,
333  0x9, 0xa, 0xb, 0xc}));
334  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
335  0x50, 0x60, 0x70, 0x80,
336  0x90, 0xa0, 0xb0, 0xc0}));
337 }
338 
339 // Partial write, excluding the end of the register.
340 TEST_F(RegisterBufTest, PartialWriteLow)
341 {
342  reg.write(buf.data() + RegSize, 0, 3);
343  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
344  0x5, 0x6, 0x7, 0x8,
345  0x9, 0xa, 0xb, 0xc}));
346  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
347  0x5, 0x6, 0x7, 0x80,
348  0x90, 0xa0, 0xb0, 0xc0}));
349 }
350 
351 // Partial read, excluding both ends of the register.
352 TEST_F(RegisterBufTest, PartialReadMid)
353 {
354  reg.read(buf.data() + RegSize, 1, 2);
355  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
356  0x60, 0x70, 0x7, 0x8,
357  0x9, 0xa, 0xb, 0xc}));
358  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
359  0x50, 0x60, 0x70, 0x80,
360  0x90, 0xa0, 0xb0, 0xc0}));
361 }
362 
363 // Partial write, excluding both ends of the register.
364 TEST_F(RegisterBufTest, PartialWriteMid)
365 {
366  reg.write(buf.data() + RegSize, 1, 2);
367  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
368  0x5, 0x6, 0x7, 0x8,
369  0x9, 0xa, 0xb, 0xc}));
370  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
371  0x50, 0x5, 0x6, 0x80,
372  0x90, 0xa0, 0xb0, 0xc0}));
373 }
374 
376 {
377  std::ostringstream os;
378  reg.serialize(os);
379  EXPECT_EQ(os.str(), "");
380 }
381 
382 TEST_F(RegisterBufTest, Unserialize)
383 {
384  std::string s;
385  EXPECT_TRUE(reg.unserialize(s));
386 }
387 
388 
389 /*
390  * The RegisterLBuf type. Since it's so similar to RegisterBuf, just do a
391  * basic check that it's applying it's locally managed buffer to it's parent
392  * type.
393  */
394 
395 class RegisterLBufTest : public testing::Test
396 {
397  protected:
398  static constexpr size_t RegSize = 12;
399 
400  RegisterBankLE::RegisterLBuf<12> reg;
401  std::array<uint8_t, 4> to_write;
402 
403  public:
404  RegisterLBufTest() : reg("lbuf_reg"), to_write{0x1, 0x2, 0x3, 0x4}
405  {
406  reg.buffer.fill(0xff);
407  }
408 };
409 
411 {
412  EXPECT_EQ(reg.name(), "lbuf_reg");
413 }
414 
415 TEST_F(RegisterLBufTest, PartialWrite)
416 {
417  reg.write(to_write.data(), 4, 4);
418  EXPECT_THAT(reg.buffer, ElementsAreArray({0xff, 0xff, 0xff, 0xff,
419  0x1, 0x2, 0x3, 0x4,
420  0xff, 0xff, 0xff, 0xff}));
421 }
422 
424 {
425  std::ostringstream os;
426  for (int i = 0; i < reg.buffer.size(); i++)
427  reg.buffer[i] = i;
428  reg.serialize(os);
429  EXPECT_EQ(os.str(), "0 1 2 3 4 5 6 7 8 9 10 11");
430 }
431 
432 TEST_F(RegisterLBufTest, UnserializeSucess)
433 {
434  std::string s = "0 1 2 3 4 5 6 7 8 9 10 11";
435  EXPECT_TRUE(reg.unserialize(s));
436  EXPECT_THAT(reg.buffer, ElementsAreArray({0, 1, 2, 3, 4, 5,
437  6, 7, 8, 9, 10, 11}));
438 }
439 
440 TEST_F(RegisterLBufTest, UnserializeFailure)
441 {
442  std::string s = "0 1 2 3 4 5 6 7 8 9 10";
443  EXPECT_FALSE(reg.unserialize(s));
444  EXPECT_THAT(reg.buffer, ElementsAreArray({0xff, 0xff, 0xff, 0xff,
445  0xff, 0xff, 0xff, 0xff,
446  0xff, 0xff, 0xff, 0xff}));
447 }
448 
449 
450 /*
451  * The templated Register<> type which takes a backing type and endianness
452  * as template parameters.
453  */
454 
455 class TypedRegisterTest : public testing::Test
456 {
457  protected:
458  using BackingType = uint16_t;
459  static constexpr size_t RegSize = sizeof(BackingType);
460 
461  // We'll typically test with the little endian version, since it only
462  // matters for a few methods.
463  RegisterBankLE::Register<BackingType> reg;
465 
466  std::array<uint8_t, RegSize * 3> buf;
467 
468  TypedRegisterTest() : reg("le_reg", 0x1122), regBE("be_reg", 0x1122),
469  buf{0x1, 0x2, 0x3, 0x4, 0x5, 0x6}
470  {}
471 };
472 // Needed by C++14 and lower
473 constexpr size_t TypedRegisterTest::RegSize;
474 
475 TEST_F(TypedRegisterTest, DefaultConstructor)
476 {
477  RegisterBankLE::Register<uint32_t> def("def");
478  EXPECT_EQ(def.get(), 0);
479 }
480 
482 {
483  EXPECT_EQ(reg.name(), "le_reg");
484 }
485 
487 {
488  EXPECT_EQ(reg.size(), RegSize);
489 }
490 
492 {
493  // By default, all bits of the registers are writeable.
494  EXPECT_EQ(reg.writeable(), 0xffff);
495 }
496 
497 // Verify that get returns the initial value of the reg.
499 {
500  EXPECT_EQ(reg.get(), 0x1122);
501 }
502 
504 {
505  reg.get() = 0x1020;
506  EXPECT_EQ(reg.get(), 0x1020);
507  reg.get() = 0x3040;
508  EXPECT_EQ(reg.get(), 0x3040);
509 }
510 
511 // Do a full big endian read using the default read handler.
512 TEST_F(TypedRegisterTest, BigEndianDefaultFullRead)
513 {
514  regBE.read(buf.data() + RegSize);
515  EXPECT_EQ(regBE.get(), 0x1122);
516  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x11, 0x22, 0x5, 0x6));
517 }
518 
519 // Do a full big endian write using the default write handler.
520 TEST_F(TypedRegisterTest, BigEndianDefaultFullWrite)
521 {
522  regBE.write(buf.data() + RegSize);
523  EXPECT_EQ(regBE.get(), 0x0304);
524  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
525 }
526 
527 // Do a partial big endian read of the low half of the register.
528 TEST_F(TypedRegisterTest, BigEndianDefaultPartialReadLow)
529 {
530  regBE.read(buf.data() + RegSize, 0, 1);
531  EXPECT_EQ(regBE.get(), 0x1122);
532  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x11, 0x4, 0x5, 0x6));
533 }
534 
535 // Do a partial big endian read of the high half of the register.
536 TEST_F(TypedRegisterTest, BigEndianDefaultPartialReadHigh)
537 {
538  regBE.read(buf.data() + RegSize, 1, 1);
539  EXPECT_EQ(regBE.get(), 0x1122);
540  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x22, 0x4, 0x5, 0x6));
541 }
542 
543 // Do a partial big endian write of the low half of the register.
544 TEST_F(TypedRegisterTest, BigEndianDefaultPartialWriteLow)
545 {
546  regBE.write(buf.data() + RegSize, 0, 1);
547  EXPECT_EQ(regBE.get(), 0x0322);
548  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
549 }
550 
551 // Do a partial big endian write of the High half of the register.
552 TEST_F(TypedRegisterTest, BigEndianDefaultPartialWriteHigh)
553 {
554  regBE.write(buf.data() + RegSize, 1, 1);
555  EXPECT_EQ(regBE.get(), 0x1103);
556  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
557 }
558 
559 // Do a full little endian read using the default read handler.
560 TEST_F(TypedRegisterTest, LittleEndianDefaultFullRead)
561 {
562  reg.read(buf.data() + RegSize);
563  EXPECT_EQ(reg.get(), 0x1122);
564  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x22, 0x11, 0x5, 0x6));
565 }
566 
567 // Do a full little endian write using the default write handler.
568 TEST_F(TypedRegisterTest, LittleEndianDefaultFullWrite)
569 {
570  reg.write(buf.data() + RegSize);
571  EXPECT_EQ(reg.get(), 0x0403);
572  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
573 }
574 
575 // Do a partial little endian read of the low half of the register.
576 TEST_F(TypedRegisterTest, LittleEndianDefaultPartialReadLow)
577 {
578  reg.read(buf.data() + RegSize, 0, 1);
579  EXPECT_EQ(reg.get(), 0x1122);
580  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x22, 0x4, 0x5, 0x6));
581 }
582 
583 // Do a partial little endian read of the high half of the register.
584 TEST_F(TypedRegisterTest, LittleEndianDefaultPartialReadHigh)
585 {
586  reg.read(buf.data() + RegSize, 1, 1);
587  EXPECT_EQ(reg.get(), 0x1122);
588  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x11, 0x4, 0x5, 0x6));
589 }
590 
591 // Do a partial little endian write of the low half of the register.
592 TEST_F(TypedRegisterTest, LittleEndianDefaultPartialWriteLow)
593 {
594  reg.write(buf.data() + RegSize, 0, 1);
595  EXPECT_EQ(reg.get(), 0x1103);
596  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
597 }
598 
599 // Do a partial little endian write of the High half of the register.
600 TEST_F(TypedRegisterTest, LittleEndianDefaultPartialWriteHigh)
601 {
602  reg.write(buf.data() + RegSize, 1, 1);
603  EXPECT_EQ(reg.get(), 0x0322);
604  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
605 }
606 
607 // Set a mask for use on writes.
608 TEST_F(TypedRegisterTest, SetWriteable)
609 {
610  reg.writeable(0xff00);
611  reg.write(buf.data() + RegSize);
612  EXPECT_EQ(reg.get(), 0x0422);
613 
614  regBE.writeable(0xff00);
615  regBE.write(buf.data() + RegSize);
616  EXPECT_EQ(regBE.get(), 0x0322);
617 }
618 
619 // Make a register read only.
621 {
622  reg.readonly();
623  reg.write(buf.data() + RegSize);
624  EXPECT_EQ(reg.get(), 0x1122);
625 }
626 
627 // Update a register with an explicit mask.
628 TEST_F(TypedRegisterTest, UpdateWithMask)
629 {
630  reg.update(0xeeee, 0x0ff0);
631  EXPECT_EQ(reg.get(), 0x1ee2);
632 }
633 
634 // Update a register using the register's built in mask.
635 TEST_F(TypedRegisterTest, UpdateDefaultMask)
636 {
637  reg.writeable(0xf00f);
638  reg.update(0xeeee);
639  EXPECT_EQ(reg.get(), 0xe12e);
640 }
641 
642 // Set a custom read handler for a register.
644 {
645  RegisterBankLE::Register<BackingType> *reg_ptr = nullptr;
646  BackingType ret = 0x3344;
647 
648  reg.reader([&reg_ptr, &ret](auto &r){
649  reg_ptr = &r;
650  return ret;
651  });
652 
653  reg.read(buf.data() + RegSize);
654  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x44, 0x33, 0x5, 0x6));
655  EXPECT_EQ(reg_ptr, &reg);
656 }
657 
658 // Set a custom read handler for a register which is a class method.
660 {
661  using Reg = RegisterBankLE::Register<BackingType>;
662 
663  struct ReadStruct
664  {
665  Reg *reg_ptr = nullptr;
666  BackingType ret = 0x3344;
667 
668  BackingType
669  reader(Reg &r)
670  {
671  reg_ptr = &r;
672  return ret;
673  }
674  } read_struct;
675 
676  reg.reader(&read_struct, &ReadStruct::reader);
677 
678  reg.read(buf.data() + RegSize);
679  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x44, 0x33, 0x5, 0x6));
680  EXPECT_EQ(read_struct.reg_ptr, &reg);
681 }
682 
683 // Set a custom write handler for a register.
685 {
686  RegisterBankLE::Register<BackingType> *reg_ptr = nullptr;
687  BackingType value = 0;
688 
689  reg.writer([&reg_ptr, &value](auto &r, const BackingType &v) {
690  reg_ptr = &r;
691  value = v;
692  });
693 
694  reg.write(buf.data() + RegSize);
695  EXPECT_EQ(reg_ptr, &reg);
696  EXPECT_EQ(value, 0x0403);
697 }
698 
699 // Set a custom write handler for a register which is a class method.
701 {
702  using Reg = RegisterBankLE::Register<BackingType>;
703 
704  struct WriteStruct
705  {
706  Reg *reg_ptr = nullptr;
707  BackingType value = 0;
708 
709  void
710  writer(Reg &r, const BackingType &v)
711  {
712  reg_ptr = &r;
713  value = v;
714  }
715  } write_struct;
716 
717  reg.writer(&write_struct, &WriteStruct::writer);
718 
719  reg.write(buf.data() + RegSize);
720  EXPECT_EQ(write_struct.reg_ptr, &reg);
721  EXPECT_THAT(write_struct.value, 0x0403);
722 }
723 
724 // Set a custom partial read handler for a register.
725 TEST_F(TypedRegisterTest, PartialReader)
726 {
727  RegisterBankLE::Register<BackingType> *reg_ptr = nullptr;
728  int first = 0;
729  int last = 0;
730  BackingType ret = 0x3344;
731 
732  reg.partialReader([&reg_ptr, &first, &last, ret](auto &r, int f, int l) {
733  reg_ptr = &r;
734  first = f;
735  last = l;
736  return ret;
737  });
738 
739  reg.read(buf.data() + RegSize, 1, 1);
740  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x33, 0x4, 0x5, 0x6));
741  EXPECT_EQ(reg_ptr, &reg);
742  EXPECT_EQ(first, 15);
743  EXPECT_EQ(last, 8);
744 }
745 
746 // Set a custom partial read handler for a register which is a class method.
747 TEST_F(TypedRegisterTest, PartialReaderMF)
748 {
749  using Reg = RegisterBankLE::Register<BackingType>;
750 
751  struct ReadStruct
752  {
753  Reg *reg_ptr = nullptr;
754  int first = 0;
755  int last = 0;
756  BackingType ret = 0x3344;
757 
758  BackingType
759  reader(Reg &r, int f, int l)
760  {
761  reg_ptr = &r;
762  first = f;
763  last = l;
764  return ret;
765  }
766  } read_struct;
767 
768  reg.partialReader(&read_struct, &ReadStruct::reader);
769 
770  reg.read(buf.data() + RegSize, 1, 1);
771  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x33, 0x4, 0x5, 0x6));
772  EXPECT_EQ(read_struct.reg_ptr, &reg);
773  EXPECT_EQ(read_struct.first, 15);
774  EXPECT_EQ(read_struct.last, 8);
775 }
776 
777 // Set a custom partial write handler for a register.
778 TEST_F(TypedRegisterTest, PartialWriter)
779 {
780  RegisterBankLE::Register<BackingType> *reg_ptr = nullptr;
781  BackingType value = 0;
782  int first = 0;
783  int last = 0;
784 
785  reg.partialWriter([&reg_ptr, &value, &first, &last](
786  auto &r, const BackingType &v, int f, int l) {
787  reg_ptr = &r;
788  value = v;
789  first = f;
790  last = l;
791  });
792 
793  reg.write(buf.data() + RegSize, 1, 1);
794  EXPECT_EQ(reg_ptr, &reg);
795  EXPECT_EQ(value, 0x300);
796  EXPECT_EQ(first, 15);
797  EXPECT_EQ(last, 8);
798 }
799 
800 // Set a custom partial write handler for a register which is a class method.
801 TEST_F(TypedRegisterTest, PartialWriterMF)
802 {
803  using Reg = RegisterBankLE::Register<BackingType>;
804 
805  struct WriteStruct
806  {
807  Reg *reg_ptr = nullptr;
808  BackingType value = 0;
809  int first = 0;
810  int last = 0;
811 
812  void
813  writer(Reg &r, const BackingType &v, int f, int l)
814  {
815  reg_ptr = &r;
816  value = v;
817  first = f;
818  last = l;
819  }
820  } write_struct;
821 
822  reg.partialWriter(&write_struct, &WriteStruct::writer);
823 
824  reg.write(buf.data() + RegSize, 1, 1);
825  EXPECT_EQ(write_struct.reg_ptr, &reg);
826  EXPECT_EQ(write_struct.value, 0x300);
827  EXPECT_EQ(write_struct.first, 15);
828  EXPECT_EQ(write_struct.last, 8);
829 }
830 
831 // Default partial reader with a custom read handler.
832 TEST_F(TypedRegisterTest, PartialReaderReader)
833 {
834  RegisterBankLE::Register<BackingType> *reg_ptr = nullptr;
835  BackingType ret = 0x3344;
836 
837  reg.reader([&reg_ptr, &ret](auto &r){
838  reg_ptr = &r;
839  return ret;
840  });
841 
842  reg.read(buf.data() + RegSize, 1, 1);
843  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x33, 0x4, 0x5, 0x6));
844  EXPECT_EQ(reg_ptr, &reg);
845 }
846 
847 // Default partial writer with custome read and write handlers.
848 TEST_F(TypedRegisterTest, PartialWriterReaderWriter)
849 {
850  RegisterBankLE::Register<BackingType> *read_reg_ptr = nullptr;
851  BackingType read_ret = 0x3344;
852 
853  RegisterBankLE::Register<BackingType> *write_reg_ptr = nullptr;
854  BackingType write_value = 0;
855 
856  reg.reader([&read_reg_ptr, read_ret](auto &r){
857  read_reg_ptr = &r;
858  return read_ret;
859  }).writer([&write_reg_ptr, &write_value](auto &r, const BackingType &v) {
860  write_reg_ptr = &r;
861  write_value = v;
862  });
863 
864  reg.write(buf.data() + RegSize, 1, 1);
865  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
866  EXPECT_EQ(read_reg_ptr, &reg);
867  EXPECT_EQ(write_reg_ptr, &reg);
868  EXPECT_EQ(write_value, 0x0344);
869 }
870 
871 // Use the default resetter for a register.
872 TEST_F(TypedRegisterTest, DefaultResetter)
873 {
874  BackingType initial_value = reg.get();
875 
876  reg.get() = initial_value + 1;
877  EXPECT_EQ(reg.get(), initial_value + 1);
878 
879  reg.reset();
880 
881  EXPECT_EQ(reg.get(), initial_value);
882 }
883 
884 // Set initial value later than constructor
885 TEST_F(TypedRegisterTest, LateInitialValueAssignment)
886 {
887  BackingType initial_value = reg.get();
888  BackingType new_initial_value = initial_value + 1;
889 
890  reg.get() = new_initial_value;
891  reg.resetInitialValue();
892 
893  EXPECT_EQ(reg.get(), new_initial_value);
894  EXPECT_EQ(reg.initialValue(), new_initial_value);
895 
896  reg.get() = new_initial_value + 1;
897  EXPECT_EQ(reg.get(), new_initial_value + 1);
898  EXPECT_EQ(reg.initialValue(), new_initial_value);
899 
900  reg.reset();
901 
902  EXPECT_EQ(reg.get(), new_initial_value);
903  EXPECT_EQ(reg.initialValue(), new_initial_value);
904 }
905 
906 // Set a custom resetter for a register.
908 {
909  RegisterBankLE::Register<BackingType> *reg_ptr = nullptr;
910 
911  reg.resetter([&reg_ptr](auto &r) {
912  reg_ptr = &r;
913  });
914 
915  reg.reset();
916 
917  EXPECT_EQ(reg_ptr, &reg);
918 }
919 
920 // Set a custom resetter for a register which is a class method.
922 {
923  using Reg = RegisterBankLE::Register<BackingType>;
924 
925  struct ResetStruct
926  {
927  Reg *reg_ptr = nullptr;
928 
929  void
930  resetter(Reg &r)
931  {
932  reg_ptr = &r;
933  }
934  } reset_struct;
935 
936  reg.resetter(&reset_struct, &ResetStruct::resetter);
937 
938  reg.reset();
939 
940  EXPECT_EQ(reset_struct.reg_ptr, &reg);
941 }
942 
944 {
945  std::ostringstream os;
946  reg.serialize(os);
947  EXPECT_EQ(os.str(), "4386");
948 }
949 
950 TEST_F(TypedRegisterTest, UnserializeSucess)
951 {
952  std::string s = "1234";
953  EXPECT_TRUE(reg.unserialize(s));
954  EXPECT_EQ(reg.get(), 1234);
955 }
956 
957 TEST_F(TypedRegisterTest, UnserializeFailure)
958 {
959  std::string s = "not_a_number";
960  EXPECT_FALSE(reg.unserialize(s));
961 }
962 
963 /*
964  * The RegisterBank itself.
965  */
966 
967 class RegisterBankTest : public testing::Test
968 {
969  protected:
971  {
972  public:
973  TestRegBank(const std::string &new_name, Addr new_base) :
974  RegisterBankLE(new_name, new_base)
975  {}
976  };
977 
979  {
983  PartialWrite
984  };
985 
986  struct Access
987  {
989  uint32_t value = 0;
990  int first = 0;
991  int last = 0;
992  uint32_t ret = 0;
993 
994  Access(AccessType _type) : type(_type) {}
995  Access(AccessType _type, uint32_t _value,
996  int _first, int _last, uint32_t _ret) :
997  type(_type), value(_value),
998  first(_first), last(_last), ret(_ret)
999  {}
1000 
1001  bool
1002  operator == (const Access &other) const
1003  {
1004  return type == other.type && value == other.value &&
1005  first == other.first && last == other.last &&
1006  ret == other.ret;
1007  }
1008  };
1009 
1010  // A 32 bit register which keeps track of what happens to it.
1012  {
1013  public:
1015 
1016  TestReg(const std::string &new_name, uint32_t initial) :
1017  TestRegBank::Register32(new_name, initial)
1018  {
1019  reader([this](auto &r) {
1020  Access access(Read);
1021  access.ret = defaultReader(r);
1022  accesses.push_back(access);
1023  return access.ret;
1024  });
1025  writer([this](auto &r, const uint32_t &v) {
1026  Access access(Write);
1027  access.value = v;
1028  defaultWriter(r, v);
1029  accesses.push_back(access);
1030  });
1031  partialReader([this](auto &r, int f, int l) {
1032  Access access(PartialRead);
1033  access.first = f;
1034  access.last = l;
1035  access.ret = defaultPartialReader(r, f, l);
1036  accesses.push_back(access);
1037  return access.ret;
1038  });
1039  partialWriter([this](auto &r, const uint32_t &v, int f, int l) {
1040  Access access(PartialWrite);
1041  access.value = v;
1042  access.first = f;
1043  access.last = l;
1044  defaultPartialWriter(r, v, f, l);
1045  accesses.push_back(access);
1046  });
1047  }
1048  };
1049 
1050  TestReg reg0, reg1, reg2;
1051  TestRegBank emptyBank, fullBank;
1052 
1053  std::array<uint8_t, 12> buf;
1054 
1056  reg0("reg0", 0xd3d2d1d0), reg1("reg1", 0xe3e2e1e0),
1057  reg2("reg2", 0xf3f2f1f0),
1058  emptyBank("empty", 0x12345), fullBank("full", 0x1000),
1059  buf{0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
1060  0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc}
1061  {
1062  fullBank.addRegisters({reg0, reg1, reg2});
1063  }
1064 };
1065 
1066 // Some basic accessors.
1067 
1069 {
1070  EXPECT_EQ(emptyBank.name(), "empty");
1071  EXPECT_EQ(fullBank.name(), "full");
1072 }
1073 
1075 {
1076  EXPECT_EQ(emptyBank.base(), 0x12345);
1077  EXPECT_EQ(fullBank.base(), 0x1000);
1078 }
1079 
1080 // Adding registers, and the size accessor. With registers, size is boring.
1081 TEST_F(RegisterBankTest, AddRegistersSize)
1082 {
1083  EXPECT_EQ(emptyBank.size(), 0);
1084  emptyBank.addRegister(reg0);
1085  EXPECT_EQ(emptyBank.size(), 4);
1086  emptyBank.addRegisters({reg1, reg2});
1087  EXPECT_EQ(emptyBank.size(), 12);
1088 }
1089 
1090 TEST_F(RegisterBankTest, AddRegistersWithOffsetChecks)
1091 {
1092  emptyBank.addRegister({0x12345});
1093  EXPECT_EQ(emptyBank.size(), 0);
1094  emptyBank.addRegister({0x12345, reg0});
1095  EXPECT_EQ(emptyBank.size(), 4);
1096  emptyBank.addRegister({0x12349});
1097  EXPECT_EQ(emptyBank.size(), 4);
1098 
1099  emptyBank.addRegisters({{0x12349, reg1}, {0x1234d}, {0x1234d, reg2}});
1100  EXPECT_EQ(emptyBank.size(), 12);
1101 }
1102 
1103 TEST_F(RegisterBankTest, BadRegisterOffsetDeath)
1104 {
1105  gtestLogOutput.str("");
1106  EXPECT_ANY_THROW(emptyBank.addRegisters({{0xabcd, reg0}, reg1}));
1107 
1108  std::string actual = gtestLogOutput.str();
1109  EXPECT_THAT(actual, HasSubstr("empty.reg0"));
1110  EXPECT_THAT(actual, HasSubstr("to be 0xabcd"));
1111  EXPECT_THAT(actual, HasSubstr("is 0x12345"));
1112 }
1113 
1114 TEST_F(RegisterBankTest, BadBankOffsetDeath)
1115 {
1116  gtestLogOutput.str("");
1117  EXPECT_ANY_THROW(emptyBank.addRegisters({{0xabcd}, reg0}));
1118 
1119  std::string actual = gtestLogOutput.str();
1120  EXPECT_THAT(actual, HasSubstr("empty "));
1121  EXPECT_THAT(actual, HasSubstr("to be 0xabcd"));
1122  EXPECT_THAT(actual, HasSubstr("is 0x12345"));
1123 }
1124 
1125 // Reads.
1126 
1127 TEST_F(RegisterBankTest, ReadOneAlignedFirst)
1128 {
1129  fullBank.read(0x1000, buf.data() + 4, 4);
1130  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1131  0xd0, 0xd1, 0xd2, 0xd3,
1132  0x99, 0xaa, 0xbb, 0xcc}));
1133  EXPECT_THAT(reg0.accesses, ElementsAre(
1134  Access(Read, 0, 0, 0, 0xd3d2d1d0)
1135  ));
1136  EXPECT_TRUE(reg1.accesses.empty());
1137  EXPECT_TRUE(reg2.accesses.empty());
1138 }
1139 
1140 TEST_F(RegisterBankTest, ReadOneAlignedMid)
1141 {
1142  fullBank.read(0x1004, buf.data() + 4, 4);
1143  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1144  0xe0, 0xe1, 0xe2, 0xe3,
1145  0x99, 0xaa, 0xbb, 0xcc}));
1146  EXPECT_TRUE(reg0.accesses.empty());
1147  EXPECT_THAT(reg1.accesses, ElementsAre(
1148  Access(Read, 0, 0, 0, 0xe3e2e1e0)
1149  ));
1150  EXPECT_TRUE(reg2.accesses.empty());
1151 }
1152 
1153 TEST_F(RegisterBankTest, ReadOneAlignedLast)
1154 {
1155  fullBank.read(0x1008, buf.data() + 4, 4);
1156  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1157  0xf0, 0xf1, 0xf2, 0xf3,
1158  0x99, 0xaa, 0xbb, 0xcc}));
1159  EXPECT_TRUE(reg0.accesses.empty());
1160  EXPECT_TRUE(reg1.accesses.empty());
1161  EXPECT_THAT(reg2.accesses, ElementsAre(
1162  Access(Read, 0, 0, 0, 0xf3f2f1f0)
1163  ));
1164 }
1165 
1166 TEST_F(RegisterBankTest, ReadTwoAligned)
1167 {
1168  fullBank.read(0x1004, buf.data() + 2, 8);
1169  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0xe0, 0xe1,
1170  0xe2, 0xe3, 0xf0, 0xf1,
1171  0xf2, 0xf3, 0xbb, 0xcc}));
1172  EXPECT_TRUE(reg0.accesses.empty());
1173  EXPECT_THAT(reg1.accesses, ElementsAre(
1174  Access(Read, 0, 0, 0, 0xe3e2e1e0)
1175  ));
1176  EXPECT_THAT(reg2.accesses, ElementsAre(
1177  Access(Read, 0, 0, 0, 0xf3f2f1f0)
1178  ));
1179 }
1180 
1181 TEST_F(RegisterBankTest, ReadContained)
1182 {
1183  fullBank.read(0x1001, buf.data() + 4, 2);
1184  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1185  0xd1, 0xd2, 0x77, 0x88,
1186  0x99, 0xaa, 0xbb, 0xcc}));
1187  EXPECT_THAT(reg0.accesses, ElementsAre(
1188  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1189  Access(PartialRead, 0, 23, 8, 0x00d2d100)
1190  ));
1191  EXPECT_TRUE(reg1.accesses.empty());
1192  EXPECT_TRUE(reg2.accesses.empty());
1193 }
1194 
1195 TEST_F(RegisterBankTest, ReadOneSpanning)
1196 {
1197  fullBank.read(0x1002, buf.data() + 4, 4);
1198  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1199  0xd2, 0xd3, 0xe0, 0xe1,
1200  0x99, 0xaa, 0xbb, 0xcc}));
1201  EXPECT_THAT(reg0.accesses, ElementsAre(
1202  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1203  Access(PartialRead, 0, 31, 16, 0xd3d20000)
1204  ));
1205  EXPECT_THAT(reg1.accesses, ElementsAre(
1206  Access(Read, 0, 0, 0, 0xe3e2e1e0),
1207  Access(PartialRead, 0, 15, 0, 0x0000e1e0)
1208  ));
1209  EXPECT_TRUE(reg2.accesses.empty());
1210 }
1211 
1212 TEST_F(RegisterBankTest, ReadTwoSpanning)
1213 {
1214  fullBank.read(0x1002, buf.data() + 2, 8);
1215  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0xd2, 0xd3,
1216  0xe0, 0xe1, 0xe2, 0xe3,
1217  0xf0, 0xf1, 0xbb, 0xcc}));
1218  EXPECT_THAT(reg0.accesses, ElementsAre(
1219  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1220  Access(PartialRead, 0, 31, 16, 0xd3d20000)
1221  ));
1222  EXPECT_THAT(reg1.accesses, ElementsAre(
1223  Access(Read, 0, 0, 0, 0xe3e2e1e0)
1224  ));
1225  EXPECT_THAT(reg2.accesses, ElementsAre(
1226  Access(Read, 0, 0, 0, 0xf3f2f1f0),
1227  Access(PartialRead, 0, 15, 0, 0x0000f1f0)
1228  ));
1229 }
1230 
1231 TEST_F(RegisterBankTest, ReadPartialFull)
1232 {
1233  fullBank.read(0x1002, buf.data() + 4, 6);
1234  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1235  0xd2, 0xd3, 0xe0, 0xe1,
1236  0xe2, 0xe3, 0xbb, 0xcc}));
1237  EXPECT_THAT(reg0.accesses, ElementsAre(
1238  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1239  Access(PartialRead, 0, 31, 16, 0xd3d20000)
1240  ));
1241  EXPECT_THAT(reg1.accesses, ElementsAre(
1242  Access(Read, 0, 0, 0, 0xe3e2e1e0)
1243  ));
1244  EXPECT_TRUE(reg2.accesses.empty());
1245 }
1246 
1247 TEST_F(RegisterBankTest, ReadFullPartial)
1248 {
1249  fullBank.read(0x1004, buf.data() + 4, 6);
1250  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1251  0xe0, 0xe1, 0xe2, 0xe3,
1252  0xf0, 0xf1, 0xbb, 0xcc}));
1253  EXPECT_TRUE(reg0.accesses.empty());
1254  EXPECT_THAT(reg1.accesses, ElementsAre(
1255  Access(Read, 0, 0, 0, 0xe3e2e1e0)
1256  ));
1257  EXPECT_THAT(reg2.accesses, ElementsAre(
1258  Access(Read, 0, 0, 0, 0xf3f2f1f0),
1259  Access(PartialRead, 0, 15, 0, 0x0000f1f0)
1260  ));
1261 }
1262 
1263 TEST_F(RegisterBankTest, ReadLastPartial)
1264 {
1265  fullBank.read(0x100a, buf.data() + 4, 2);
1266  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1267  0xf2, 0xf3, 0x77, 0x88,
1268  0x99, 0xaa, 0xbb, 0xcc}));
1269  EXPECT_TRUE(reg0.accesses.empty());
1270  EXPECT_TRUE(reg1.accesses.empty());
1271  EXPECT_THAT(reg2.accesses, ElementsAre(
1272  Access(Read, 0, 0, 0, 0xf3f2f1f0),
1273  Access(PartialRead, 0, 31, 16, 0xf3f20000)
1274  ));
1275 }
1276 
1277 // Write.
1278 
1279 TEST_F(RegisterBankTest, WriteOneAlignedFirst)
1280 {
1281  fullBank.write(0x1000, buf.data() + 4, 4);
1282  EXPECT_EQ(reg0.get(), 0x88776655);
1283  EXPECT_EQ(reg1.get(), 0xe3e2e1e0);
1284  EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1285  EXPECT_THAT(reg0.accesses, ElementsAre(
1286  Access(Write, 0x88776655, 0, 0, 0)
1287  ));
1288  EXPECT_TRUE(reg1.accesses.empty());
1289  EXPECT_TRUE(reg2.accesses.empty());
1290 }
1291 
1292 TEST_F(RegisterBankTest, WriteOneAlignedMid)
1293 {
1294  fullBank.write(0x1004, buf.data() + 4, 4);
1295  EXPECT_EQ(reg0.get(), 0xd3d2d1d0);
1296  EXPECT_EQ(reg1.get(), 0x88776655);
1297  EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1298  EXPECT_TRUE(reg0.accesses.empty());
1299  EXPECT_THAT(reg1.accesses, ElementsAre(
1300  Access(Write, 0x88776655, 0, 0, 0)
1301  ));
1302  EXPECT_TRUE(reg2.accesses.empty());
1303 }
1304 
1305 TEST_F(RegisterBankTest, WriteOneAlignedLast)
1306 {
1307  fullBank.write(0x1008, buf.data() + 4, 4);
1308  EXPECT_EQ(reg0.get(), 0xd3d2d1d0);
1309  EXPECT_EQ(reg1.get(), 0xe3e2e1e0);
1310  EXPECT_EQ(reg2.get(), 0x88776655);
1311  EXPECT_TRUE(reg0.accesses.empty());
1312  EXPECT_TRUE(reg1.accesses.empty());
1313  EXPECT_THAT(reg2.accesses, ElementsAre(
1314  Access(Write, 0x88776655, 0, 0, 0)
1315  ));
1316 }
1317 
1318 TEST_F(RegisterBankTest, WriteTwoAligned)
1319 {
1320  fullBank.write(0x1004, buf.data() + 2, 8);
1321  EXPECT_EQ(reg0.get(), 0xd3d2d1d0);
1322  EXPECT_EQ(reg1.get(), 0x66554433);
1323  EXPECT_EQ(reg2.get(), 0xaa998877);
1324  EXPECT_TRUE(reg0.accesses.empty());
1325  EXPECT_THAT(reg1.accesses, ElementsAre(
1326  Access(Write, 0x66554433, 0, 0, 0)
1327  ));
1328  EXPECT_THAT(reg2.accesses, ElementsAre(
1329  Access(Write, 0xaa998877, 0, 0, 0)
1330  ));
1331 }
1332 
1333 TEST_F(RegisterBankTest, WriteContained)
1334 {
1335  fullBank.write(0x1001, buf.data() + 4, 2);
1336  EXPECT_EQ(reg0.get(), 0xd36655d0);
1337  EXPECT_EQ(reg1.get(), 0xe3e2e1e0);
1338  EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1339  EXPECT_THAT(reg0.accesses, ElementsAre(
1340  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1341  Access(Write, 0xd36655d0, 0, 0, 0),
1342  Access(PartialWrite, 0x00665500, 23, 8, 0)
1343  ));
1344  EXPECT_TRUE(reg1.accesses.empty());
1345  EXPECT_TRUE(reg2.accesses.empty());
1346 }
1347 
1348 TEST_F(RegisterBankTest, WriteOneSpanning)
1349 {
1350  fullBank.write(0x1002, buf.data() + 4, 4);
1351  EXPECT_EQ(reg0.get(), 0x6655d1d0);
1352  EXPECT_EQ(reg1.get(), 0xe3e28877);
1353  EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1354  EXPECT_THAT(reg0.accesses, ElementsAre(
1355  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1356  Access(Write, 0x6655d1d0, 0, 0, 0),
1357  Access(PartialWrite, 0x66550000, 31, 16, 0)
1358  ));
1359  EXPECT_THAT(reg1.accesses, ElementsAre(
1360  Access(Read, 0, 0, 0, 0xe3e2e1e0),
1361  Access(Write, 0xe3e28877, 0, 0, 0),
1362  Access(PartialWrite, 0x00008877, 15, 0, 0)
1363  ));
1364  EXPECT_TRUE(reg2.accesses.empty());
1365 }
1366 
1367 TEST_F(RegisterBankTest, WriteTwoSpanning)
1368 {
1369  fullBank.write(0x1002, buf.data() + 2, 8);
1370  EXPECT_EQ(reg0.get(), 0x4433d1d0);
1371  EXPECT_EQ(reg1.get(), 0x88776655);
1372  EXPECT_EQ(reg2.get(), 0xf3f2aa99);
1373  EXPECT_THAT(reg0.accesses, ElementsAre(
1374  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1375  Access(Write, 0x4433d1d0, 0, 0, 0),
1376  Access(PartialWrite, 0x44330000, 31, 16, 0)
1377  ));
1378  EXPECT_THAT(reg1.accesses, ElementsAre(
1379  Access(Write, 0x88776655, 0, 0, 0)
1380  ));
1381  EXPECT_THAT(reg2.accesses, ElementsAre(
1382  Access(Read, 0, 0, 0, 0xf3f2f1f0),
1383  Access(Write, 0xf3f2aa99, 0, 0, 0),
1384  Access(PartialWrite, 0x0000aa99, 15, 0, 0)
1385  ));
1386 }
1387 
1388 TEST_F(RegisterBankTest, WritePartialFull)
1389 {
1390  fullBank.write(0x1002, buf.data() + 4, 6);
1391  EXPECT_EQ(reg0.get(), 0x6655d1d0);
1392  EXPECT_EQ(reg1.get(), 0xaa998877);
1393  EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1394  EXPECT_THAT(reg0.accesses, ElementsAre(
1395  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1396  Access(Write, 0x6655d1d0, 0, 0, 0),
1397  Access(PartialWrite, 0x66550000, 31, 16, 0)
1398  ));
1399  EXPECT_THAT(reg1.accesses, ElementsAre(
1400  Access(Write, 0xaa998877, 0, 0, 0)
1401  ));
1402  EXPECT_TRUE(reg2.accesses.empty());
1403 }
1404 
1405 TEST_F(RegisterBankTest, WriteFullPartial)
1406 {
1407  fullBank.write(0x1004, buf.data() + 4, 6);
1408  EXPECT_EQ(reg0.get(), 0xd3d2d1d0);
1409  EXPECT_EQ(reg1.get(), 0x88776655);
1410  EXPECT_EQ(reg2.get(), 0xf3f2aa99);
1411  EXPECT_TRUE(reg0.accesses.empty());
1412  EXPECT_THAT(reg1.accesses, ElementsAre(
1413  Access(Write, 0x88776655, 0, 0, 0)
1414  ));
1415  EXPECT_THAT(reg2.accesses, ElementsAre(
1416  Access(Read, 0, 0, 0, 0xf3f2f1f0),
1417  Access(Write, 0xf3f2aa99, 0, 0, 0),
1418  Access(PartialWrite, 0x0000aa99, 15, 0, 0)
1419  ));
1420 }
RegisterBankTest::RegisterBankTest
RegisterBankTest()
Definition: reg_bank.test.cc:1055
RegisterBankTest::TestRegBank::TestRegBank
TestRegBank(const std::string &new_name, Addr new_base)
Definition: reg_bank.test.cc:973
RegisterRaoTest::buf
std::array< uint8_t, BufSize > buf
Definition: reg_bank.test.cc:169
gem5::VegaISA::s
Bitfield< 1 > s
Definition: pagetable.hh:64
gem5::VegaISA::f
Bitfield< 56 > f
Definition: pagetable.hh:53
gem5::RegisterBank::addRegister
void addRegister(RegisterAdder reg)
Definition: reg_bank.hh:938
RegisterBankTest::AccessType
AccessType
Definition: reg_bank.test.cc:978
RegisterRazTest::raz
RegisterBankLE::RegisterRaz raz
Definition: reg_bank.test.cc:84
RegisterBankTest
Definition: reg_bank.test.cc:967
logging.hh
RegisterBankTest::Access::Access
Access(AccessType _type, uint32_t _value, int _first, int _last, uint32_t _ret)
Definition: reg_bank.test.cc:995
RegisterBankTest::TestReg::accesses
std::vector< Access > accesses
Definition: reg_bank.test.cc:1014
RegisterBankTest::buf
std::array< uint8_t, 12 > buf
Definition: reg_bank.test.cc:1053
RegisterRaoTest::rao
RegisterBankLE::RegisterRao rao
Definition: reg_bank.test.cc:170
TEST_F
TEST_F(RegisterRazTest, Name)
Definition: reg_bank.test.cc:94
RegisterBankTest::PartialRead
@ PartialRead
Definition: reg_bank.test.cc:982
RegisterBankTest::reg2
TestReg reg2
Definition: reg_bank.test.cc:1050
RegisterBufTest::RegisterBufTest
RegisterBufTest()
Definition: reg_bank.test.cc:259
std::vector< Access >
gem5::VegaISA::r
Bitfield< 5 > r
Definition: pagetable.hh:60
RegisterBufTest::reg
RegisterBankLE::RegisterBuf reg
Definition: reg_bank.test.cc:256
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
gem5::RegisterBank::addRegisters
void addRegisters(std::initializer_list< RegisterAdder > adders)
Definition: reg_bank.hh:913
RegisterBankTest::Access::Access
Access(AccessType _type)
Definition: reg_bank.test.cc:994
gem5::RegisterBank::size
Addr size() const
Definition: reg_bank.hh:941
gem5::copy_engine_reg::Reg
Definition: copy_engine_defs.hh:99
RegisterLBufTest
Definition: reg_bank.test.cc:395
Access
Definition: proxy_ptr.test.cc:36
gem5::RegisterBank::base
Addr base() const
Definition: reg_bank.hh:940
RegisterBufTest::backing
std::array< uint8_t, RegSize *3 > backing
Definition: reg_bank.test.cc:254
gem5::auxv::Base
@ Base
Definition: aux_vector.hh:74
RegisterBankTest::Access::ret
uint32_t ret
Definition: reg_bank.test.cc:992
RegisterRaoTest
Definition: reg_bank.test.cc:162
gem5::ArmISA::raz
Bitfield< 31, 28 > raz
Definition: misc_types.hh:541
RegisterLBufTest::RegisterLBufTest
RegisterLBufTest()
Definition: reg_bank.test.cc:404
writer
Definition: test.h:47
RegisterBankTest::TestReg::TestReg
TestReg(const std::string &new_name, uint32_t initial)
Definition: reg_bank.test.cc:1016
TypedRegisterTest::regBE
RegisterBankBE::Register< BackingType > regBE
Definition: reg_bank.test.cc:464
gem5::X86ISA::type
type
Definition: misc.hh:734
RegisterBufTest
Definition: reg_bank.test.cc:248
RegisterBufTest::buf
std::array< uint8_t, RegSize *3 > buf
Definition: reg_bank.test.cc:253
RegisterBankTest::Access::type
AccessType type
Definition: reg_bank.test.cc:988
RegisterLBufTest::to_write
std::array< uint8_t, 4 > to_write
Definition: reg_bank.test.cc:401
RegisterRaoTest::RegisterRaoTest
RegisterRaoTest()
Definition: reg_bank.test.cc:172
RegisterBankTest::Access::value
uint32_t value
Definition: reg_bank.test.cc:989
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
RegisterRaoTest::RaoSize
static constexpr size_t RaoSize
Definition: reg_bank.test.cc:167
TypedRegisterTest::RegSize
static constexpr size_t RegSize
Definition: reg_bank.test.cc:459
RegisterBankTest::Access::last
int last
Definition: reg_bank.test.cc:991
RegisterRazTest::RazSize
static constexpr size_t RazSize
Definition: reg_bank.test.cc:81
TypedRegisterTest
Definition: reg_bank.test.cc:455
gem5::X86ISA::reg
Bitfield< 5, 3 > reg
Definition: types.hh:92
RegisterRazTest
Definition: reg_bank.test.cc:76
RegisterBankTest::fullBank
TestRegBank fullBank
Definition: reg_bank.test.cc:1051
gem5::VegaISA::v
Bitfield< 0 > v
Definition: pagetable.hh:65
TypedRegisterTest::reg
RegisterBankLE::Register< BackingType > reg
Definition: reg_bank.test.cc:463
gem5::RegisterBank::name
const std::string & name() const
Definition: reg_bank.hh:942
gem5::X86ISA::os
Bitfield< 17 > os
Definition: misc.hh:810
gem5::operator==
static bool operator==(const PCStateBase &a, const PCStateBase &b)
Definition: pcstate.hh:155
RegisterBankTest::Read
@ Read
Definition: reg_bank.test.cc:980
gem5::RegisterBank< ByteOrder::little >
gem5::RegisterBank::Register< BackingType >
RegisterBankTest::TestRegBank
Definition: reg_bank.test.cc:970
RegisterLBufTest::reg
RegisterBankLE::RegisterLBuf< 12 > reg
Definition: reg_bank.test.cc:400
gem5::VegaISA::l
Bitfield< 55 > l
Definition: pagetable.hh:54
gem5::gtestLogOutput
thread_local GTestLogOutput gtestLogOutput
Definition: logging.cc:33
TypedRegisterTest::TypedRegisterTest
TypedRegisterTest()
Definition: reg_bank.test.cc:468
RegisterRazTest::RegisterRazTest
RegisterRazTest()
Definition: reg_bank.test.cc:86
RegisterBankTest::Write
@ Write
Definition: reg_bank.test.cc:981
gem5::RegisterBank< ByteOrder::little >::Register32
Register< uint32_t > Register32
Definition: reg_bank.hh:879
TypedRegisterTest::buf
std::array< uint8_t, RegSize *3 > buf
Definition: reg_bank.test.cc:466
RegisterRazTest::buf
std::array< uint8_t, BufSize > buf
Definition: reg_bank.test.cc:83
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
RegisterBankTest::Access
Definition: reg_bank.test.cc:986
RegisterBankTest::TestReg
Definition: reg_bank.test.cc:1011
reg_bank.hh
TypedRegisterTest::BackingType
uint16_t BackingType
Definition: reg_bank.test.cc:458
RegisterBufTest::RegSize
static constexpr size_t RegSize
Definition: reg_bank.test.cc:251
RegisterBankTest::Access::first
int first
Definition: reg_bank.test.cc:990

Generated on Sun Jul 30 2023 01:56:56 for gem5 by doxygen 1.8.17