gem5  v21.0.0.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 "dev/reg_bank.hh"
59 
60 // Compare the elements of an array against expected values.
61 using testing::ElementsAre;
62 // This version is needed with enough elements, empirically more than 10.
63 using testing::ElementsAreArray;
64 
65 
66 /*
67  * The RegisterRaz (read as zero) type.
68  */
69 
70 class RegisterRazTest : public testing::Test
71 {
72  protected:
73  static constexpr size_t BufSize = 12;
74  static constexpr size_t BufOffset = 4;
75  static constexpr size_t RazSize = 4;
76 
77  std::array<uint8_t, BufSize> buf;
78  RegisterBankLE::RegisterRaz raz;
79 
81  {
82  buf.fill(0xff);
83  }
84 };
85 // Needed by C++14 and lower
86 constexpr size_t RegisterRazTest::RazSize;
87 
89 {
90  EXPECT_EQ(raz.name(), "raz");
91 }
92 
94 {
95  EXPECT_EQ(raz.size(), RazSize);
96 }
97 
98 // Accessing the entire register at once.
99 TEST_F(RegisterRazTest, FullAccess)
100 {
101  raz.write(buf.data() + BufOffset);
102  raz.read(buf.data() + BufOffset);
103  EXPECT_THAT(buf, ElementsAreArray({0xff, 0xff, 0xff, 0xff,
104  0x00, 0x00, 0x00, 0x00,
105  0xff, 0xff, 0xff, 0xff}));
106 }
107 
108 // Partial access, excluding the start of the register.
109 TEST_F(RegisterRazTest, PartialAccessHigh)
110 {
111  raz.write(buf.data() + BufOffset, 1, 3);
112  raz.read(buf.data() + BufOffset, 1, 3);
113  EXPECT_THAT(buf, ElementsAreArray({0xff, 0xff, 0xff, 0xff,
114  0x00, 0x00, 0x00, 0xff,
115  0xff, 0xff, 0xff, 0xff}));
116 }
117 
118 // Partial access, excluding the end of the register.
119 TEST_F(RegisterRazTest, PartialAccessLow)
120 {
121  raz.write(buf.data() + BufOffset, 0, 3);
122  raz.read(buf.data() + BufOffset, 0, 3);
123  EXPECT_THAT(buf, ElementsAreArray({0xff, 0xff, 0xff, 0xff,
124  0x00, 0x00, 0x00, 0xff,
125  0xff, 0xff, 0xff, 0xff}));
126 }
127 
128 // Partial access, excluding both ends of the register.
129 TEST_F(RegisterRazTest, PartialAccessMid)
130 {
131  raz.write(buf.data() + BufOffset, 1, 2);
132  raz.read(buf.data() + BufOffset, 1, 2);
133  EXPECT_THAT(buf, ElementsAreArray({0xff, 0xff, 0xff, 0xff,
134  0x00, 0x00, 0xff, 0xff,
135  0xff, 0xff, 0xff, 0xff}));
136 }
137 
139 {
140  std::ostringstream os;
141  raz.serialize(os);
142  EXPECT_EQ(os.str(), "");
143 }
144 
145 TEST_F(RegisterRazTest, Unserialize)
146 {
147  std::string s;
148  EXPECT_TRUE(raz.unserialize(s));
149 }
150 
151 
152 /*
153  * The RegisterRao (read as one) type.
154  */
155 
156 class RegisterRaoTest : public testing::Test
157 {
158  protected:
159  static constexpr size_t BufSize = 12;
160  static constexpr size_t BufOffset = 4;
161  static constexpr size_t RaoSize = 4;
162 
163  std::array<uint8_t, BufSize> buf;
164  RegisterBankLE::RegisterRao rao;
165 
167  {
168  buf.fill(0x00);
169  }
170 };
171 // Needed by C++14 and lower
172 constexpr size_t RegisterRaoTest::RaoSize;
173 
175 {
176  EXPECT_EQ(rao.name(), "rao");
177 }
178 
180 {
181  EXPECT_EQ(rao.size(), RaoSize);
182 }
183 
184 // Accessing the entire register at once.
186 {
187  rao.write(buf.data() + BufOffset);
188  rao.read(buf.data() + BufOffset);
189  EXPECT_THAT(buf, ElementsAreArray({0x00, 0x00, 0x00, 0x00,
190  0xff, 0xff, 0xff, 0xff,
191  0x00, 0x00, 0x00, 0x00}));
192 }
193 
194 // Partial access, excluding the start of the register.
195 TEST_F(RegisterRaoTest, PartialAccessHigh)
196 {
197  rao.write(buf.data() + BufOffset, 1, 3);
198  rao.read(buf.data() + BufOffset, 1, 3);
199  EXPECT_THAT(buf, ElementsAreArray({0x00, 0x00, 0x00, 0x00,
200  0xff, 0xff, 0xff, 0x00,
201  0x00, 0x00, 0x00, 0x00}));
202 }
203 
204 // Partial access, excluding the end of the register.
205 TEST_F(RegisterRaoTest, PartialAccessLow)
206 {
207  rao.write(buf.data() + BufOffset, 0, 3);
208  rao.read(buf.data() + BufOffset, 0, 3);
209  EXPECT_THAT(buf, ElementsAreArray({0x00, 0x00, 0x00, 0x00,
210  0xff, 0xff, 0xff, 0x00,
211  0x00, 0x00, 0x00, 0x00}));
212 }
213 
214 // Partial access, excluding both ends of the register.
215 TEST_F(RegisterRaoTest, PartialAccessMid)
216 {
217  rao.write(buf.data() + BufOffset, 1, 2);
218  rao.read(buf.data() + BufOffset, 1, 2);
219  EXPECT_THAT(buf, ElementsAreArray({0x00, 0x00, 0x00, 0x00,
220  0xff, 0xff, 0x00, 0x00,
221  0x00, 0x00, 0x00, 0x00}));
222 }
223 
225 {
226  std::ostringstream os;
227  rao.serialize(os);
228  EXPECT_EQ(os.str(), "");
229 }
230 
231 TEST_F(RegisterRaoTest, Unserialize)
232 {
233  std::string s;
234  EXPECT_TRUE(rao.unserialize(s));
235 }
236 
237 
238 /*
239  * The RegisterBuf type.
240  */
241 
242 class RegisterBufTest : public testing::Test
243 {
244  protected:
245  static constexpr size_t RegSize = 4;
246 
247  RegisterBankLE::RegisterBuf reg;
248 
249  std::array<uint8_t, RegSize * 3> buf;
250  std::array<uint8_t, RegSize * 3> backing;
251 
252  public:
254  buf{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc},
255  backing{0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
256  0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0}
257  {}
258 };
259 // Needed by C++14 and lower
260 constexpr size_t RegisterBufTest::RegSize;
261 
263 {
264  EXPECT_EQ(reg.name(), "buf_reg");
265 }
266 
268 {
269  EXPECT_EQ(reg.size(), RegSize);
270 }
271 
272 // Read the entire register.
274 {
275  reg.read(buf.data() + RegSize);
276  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
277  0x50, 0x60, 0x70, 0x80,
278  0x9, 0xa, 0xb, 0xc}));
279  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
280  0x50, 0x60, 0x70, 0x80,
281  0x90, 0xa0, 0xb0, 0xc0}));
282 }
283 
284 // Write the entire register.
286 {
287  reg.write(buf.data() + RegSize);
288  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
289  0x5, 0x6, 0x7, 0x8,
290  0x9, 0xa, 0xb, 0xc}));
291  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
292  0x5, 0x6, 0x7, 0x8,
293  0x90, 0xa0, 0xb0, 0xc0}));
294 }
295 
296 // Partial read, excluding the start of the register.
297 TEST_F(RegisterBufTest, PartialReadHigh)
298 {
299  reg.read(buf.data() + RegSize, 1, 3);
300  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
301  0x60, 0x70, 0x80, 0x8,
302  0x9, 0xa, 0xb, 0xc}));
303  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
304  0x50, 0x60, 0x70, 0x80,
305  0x90, 0xa0, 0xb0, 0xc0}));
306 }
307 
308 // Partial write, excluding the start of the register.
309 TEST_F(RegisterBufTest, PartialWriteHigh)
310 {
311  reg.write(buf.data() + RegSize, 1, 3);
312  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
313  0x5, 0x6, 0x7, 0x8,
314  0x9, 0xa, 0xb, 0xc}));
315  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
316  0x50, 0x5, 0x6, 0x7,
317  0x90, 0xa0, 0xb0, 0xc0}));
318 }
319 
320 // Partial read, excluding the end of the register.
321 TEST_F(RegisterBufTest, PartialReadLow)
322 {
323  reg.read(buf.data() + RegSize, 0, 3);
324  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
325  0x50, 0x60, 0x70, 0x8,
326  0x9, 0xa, 0xb, 0xc}));
327  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
328  0x50, 0x60, 0x70, 0x80,
329  0x90, 0xa0, 0xb0, 0xc0}));
330 }
331 
332 // Partial write, excluding the end of the register.
333 TEST_F(RegisterBufTest, PartialWriteLow)
334 {
335  reg.write(buf.data() + RegSize, 0, 3);
336  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
337  0x5, 0x6, 0x7, 0x8,
338  0x9, 0xa, 0xb, 0xc}));
339  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
340  0x5, 0x6, 0x7, 0x80,
341  0x90, 0xa0, 0xb0, 0xc0}));
342 }
343 
344 // Partial read, excluding both ends of the register.
345 TEST_F(RegisterBufTest, PartialReadMid)
346 {
347  reg.read(buf.data() + RegSize, 1, 2);
348  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
349  0x60, 0x70, 0x7, 0x8,
350  0x9, 0xa, 0xb, 0xc}));
351  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
352  0x50, 0x60, 0x70, 0x80,
353  0x90, 0xa0, 0xb0, 0xc0}));
354 }
355 
356 // Partial write, excluding both ends of the register.
357 TEST_F(RegisterBufTest, PartialWriteMid)
358 {
359  reg.write(buf.data() + RegSize, 1, 2);
360  EXPECT_THAT(buf, ElementsAreArray({0x1, 0x2, 0x3, 0x4,
361  0x5, 0x6, 0x7, 0x8,
362  0x9, 0xa, 0xb, 0xc}));
363  EXPECT_THAT(backing, ElementsAreArray({0x10, 0x20, 0x30, 0x40,
364  0x50, 0x5, 0x6, 0x80,
365  0x90, 0xa0, 0xb0, 0xc0}));
366 }
367 
369 {
370  std::ostringstream os;
371  reg.serialize(os);
372  EXPECT_EQ(os.str(), "");
373 }
374 
375 TEST_F(RegisterBufTest, Unserialize)
376 {
377  std::string s;
378  EXPECT_TRUE(reg.unserialize(s));
379 }
380 
381 
382 /*
383  * The RegisterLBuf type. Since it's so similar to RegisterBuf, just do a
384  * basic check that it's applying it's locally managed buffer to it's parent
385  * type.
386  */
387 
388 class RegisterLBufTest : public testing::Test
389 {
390  protected:
391  static constexpr size_t RegSize = 12;
392 
393  RegisterBankLE::RegisterLBuf<12> reg;
394  std::array<uint8_t, 4> to_write;
395 
396  public:
397  RegisterLBufTest() : reg("lbuf_reg"), to_write{0x1, 0x2, 0x3, 0x4}
398  {
399  reg.buffer.fill(0xff);
400  }
401 };
402 
404 {
405  EXPECT_EQ(reg.name(), "lbuf_reg");
406 }
407 
408 TEST_F(RegisterLBufTest, PartialWrite)
409 {
410  reg.write(to_write.data(), 4, 4);
411  EXPECT_THAT(reg.buffer, ElementsAreArray({0xff, 0xff, 0xff, 0xff,
412  0x1, 0x2, 0x3, 0x4,
413  0xff, 0xff, 0xff, 0xff}));
414 }
415 
417 {
418  std::ostringstream os;
419  for (int i = 0; i < reg.buffer.size(); i++)
420  reg.buffer[i] = i;
421  reg.serialize(os);
422  EXPECT_EQ(os.str(), "0 1 2 3 4 5 6 7 8 9 10 11");
423 }
424 
425 TEST_F(RegisterLBufTest, UnserializeSucess)
426 {
427  std::string s = "0 1 2 3 4 5 6 7 8 9 10 11";
428  EXPECT_TRUE(reg.unserialize(s));
429  EXPECT_THAT(reg.buffer, ElementsAreArray({0, 1, 2, 3, 4, 5,
430  6, 7, 8, 9, 10, 11}));
431 }
432 
433 TEST_F(RegisterLBufTest, UnserializeFailure)
434 {
435  std::string s = "0 1 2 3 4 5 6 7 8 9 10";
436  EXPECT_FALSE(reg.unserialize(s));
437  EXPECT_THAT(reg.buffer, ElementsAreArray({0xff, 0xff, 0xff, 0xff,
438  0xff, 0xff, 0xff, 0xff,
439  0xff, 0xff, 0xff, 0xff}));
440 }
441 
442 
443 /*
444  * The templated Register<> type which takes a backing type and endianness
445  * as template parameters.
446  */
447 
448 class TypedRegisterTest : public testing::Test
449 {
450  protected:
451  using BackingType = uint16_t;
452  static constexpr size_t RegSize = sizeof(BackingType);
453 
454  // We'll typically test with the little endian version, since it only
455  // matters for a few methods.
456  RegisterBankLE::Register<BackingType> reg;
458 
459  std::array<uint8_t, RegSize * 3> buf;
460 
461  TypedRegisterTest() : reg("le_reg", 0x1122), regBE("be_reg", 0x1122),
462  buf{0x1, 0x2, 0x3, 0x4, 0x5, 0x6}
463  {}
464 };
465 // Needed by C++14 and lower
466 constexpr size_t TypedRegisterTest::RegSize;
467 
468 TEST_F(TypedRegisterTest, DefaultConstructor)
469 {
470  RegisterBankLE::Register<uint32_t> def("def");
471  EXPECT_EQ(def.get(), 0);
472 }
473 
475 {
476  EXPECT_EQ(reg.name(), "le_reg");
477 }
478 
480 {
481  EXPECT_EQ(reg.size(), RegSize);
482 }
483 
485 {
486  // By default, all bits of the registers are writeable.
487  EXPECT_EQ(reg.writeable(), 0xffff);
488 }
489 
490 // Verify that get returns the initial value of the reg.
492 {
493  EXPECT_EQ(reg.get(), 0x1122);
494 }
495 
497 {
498  reg.get() = 0x1020;
499  EXPECT_EQ(reg.get(), 0x1020);
500  reg.get() = 0x3040;
501  EXPECT_EQ(reg.get(), 0x3040);
502 }
503 
504 // Do a full big endian read using the default read handler.
505 TEST_F(TypedRegisterTest, BigEndianDefaultFullRead)
506 {
507  regBE.read(buf.data() + RegSize);
508  EXPECT_EQ(regBE.get(), 0x1122);
509  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x11, 0x22, 0x5, 0x6));
510 }
511 
512 // Do a full big endian write using the default write handler.
513 TEST_F(TypedRegisterTest, BigEndianDefaultFullWrite)
514 {
515  regBE.write(buf.data() + RegSize);
516  EXPECT_EQ(regBE.get(), 0x0304);
517  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
518 }
519 
520 // Do a partial big endian read of the low half of the register.
521 TEST_F(TypedRegisterTest, BigEndianDefaultPartialReadLow)
522 {
523  regBE.read(buf.data() + RegSize, 0, 1);
524  EXPECT_EQ(regBE.get(), 0x1122);
525  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x11, 0x4, 0x5, 0x6));
526 }
527 
528 // Do a partial big endian read of the high half of the register.
529 TEST_F(TypedRegisterTest, BigEndianDefaultPartialReadHigh)
530 {
531  regBE.read(buf.data() + RegSize, 1, 1);
532  EXPECT_EQ(regBE.get(), 0x1122);
533  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x22, 0x4, 0x5, 0x6));
534 }
535 
536 // Do a partial big endian write of the low half of the register.
537 TEST_F(TypedRegisterTest, BigEndianDefaultPartialWriteLow)
538 {
539  regBE.write(buf.data() + RegSize, 0, 1);
540  EXPECT_EQ(regBE.get(), 0x0322);
541  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
542 }
543 
544 // Do a partial big endian write of the High half of the register.
545 TEST_F(TypedRegisterTest, BigEndianDefaultPartialWriteHigh)
546 {
547  regBE.write(buf.data() + RegSize, 1, 1);
548  EXPECT_EQ(regBE.get(), 0x1103);
549  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
550 }
551 
552 // Do a full little endian read using the default read handler.
553 TEST_F(TypedRegisterTest, LittleEndianDefaultFullRead)
554 {
555  reg.read(buf.data() + RegSize);
556  EXPECT_EQ(reg.get(), 0x1122);
557  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x22, 0x11, 0x5, 0x6));
558 }
559 
560 // Do a full little endian write using the default write handler.
561 TEST_F(TypedRegisterTest, LittleEndianDefaultFullWrite)
562 {
563  reg.write(buf.data() + RegSize);
564  EXPECT_EQ(reg.get(), 0x0403);
565  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
566 }
567 
568 // Do a partial little endian read of the low half of the register.
569 TEST_F(TypedRegisterTest, LittleEndianDefaultPartialReadLow)
570 {
571  reg.read(buf.data() + RegSize, 0, 1);
572  EXPECT_EQ(reg.get(), 0x1122);
573  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x22, 0x4, 0x5, 0x6));
574 }
575 
576 // Do a partial little endian read of the high half of the register.
577 TEST_F(TypedRegisterTest, LittleEndianDefaultPartialReadHigh)
578 {
579  reg.read(buf.data() + RegSize, 1, 1);
580  EXPECT_EQ(reg.get(), 0x1122);
581  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x11, 0x4, 0x5, 0x6));
582 }
583 
584 // Do a partial little endian write of the low half of the register.
585 TEST_F(TypedRegisterTest, LittleEndianDefaultPartialWriteLow)
586 {
587  reg.write(buf.data() + RegSize, 0, 1);
588  EXPECT_EQ(reg.get(), 0x1103);
589  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
590 }
591 
592 // Do a partial little endian write of the High half of the register.
593 TEST_F(TypedRegisterTest, LittleEndianDefaultPartialWriteHigh)
594 {
595  reg.write(buf.data() + RegSize, 1, 1);
596  EXPECT_EQ(reg.get(), 0x0322);
597  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
598 }
599 
600 // Set a mask for use on writes.
601 TEST_F(TypedRegisterTest, SetWriteable)
602 {
603  reg.writeable(0xff00);
604  reg.write(buf.data() + RegSize);
605  EXPECT_EQ(reg.get(), 0x0422);
606 
607  regBE.writeable(0xff00);
608  regBE.write(buf.data() + RegSize);
609  EXPECT_EQ(regBE.get(), 0x0322);
610 }
611 
612 // Make a register read only.
614 {
615  reg.readonly();
616  reg.write(buf.data() + RegSize);
617  EXPECT_EQ(reg.get(), 0x1122);
618 }
619 
620 // Update a register with an explicit mask.
621 TEST_F(TypedRegisterTest, UpdateWithMask)
622 {
623  reg.update(0xeeee, 0x0ff0);
624  EXPECT_EQ(reg.get(), 0x1ee2);
625 }
626 
627 // Update a register using the register's built in mask.
628 TEST_F(TypedRegisterTest, UpdateDefaultMask)
629 {
630  reg.writeable(0xf00f);
631  reg.update(0xeeee);
632  EXPECT_EQ(reg.get(), 0xe12e);
633 }
634 
635 // Set a custom read handler for a register.
637 {
638  RegisterBankLE::Register<BackingType> *reg_ptr = nullptr;
639  BackingType ret = 0x3344;
640 
641  reg.reader([&reg_ptr, &ret](auto &r){
642  reg_ptr = &r;
643  return ret;
644  });
645 
646  reg.read(buf.data() + RegSize);
647  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x44, 0x33, 0x5, 0x6));
648  EXPECT_EQ(reg_ptr, &reg);
649 }
650 
651 // Set a custom read handler for a register which is a class method.
653 {
654  using Reg = RegisterBankLE::Register<BackingType>;
655 
656  struct ReadStruct
657  {
658  Reg *reg_ptr = nullptr;
659  BackingType ret = 0x3344;
660 
661  BackingType
662  reader(Reg &r)
663  {
664  reg_ptr = &r;
665  return ret;
666  }
667  } read_struct;
668 
669  reg.reader(&read_struct, &ReadStruct::reader);
670 
671  reg.read(buf.data() + RegSize);
672  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x44, 0x33, 0x5, 0x6));
673  EXPECT_EQ(read_struct.reg_ptr, &reg);
674 }
675 
676 // Set a custom write handler for a register.
678 {
679  RegisterBankLE::Register<BackingType> *reg_ptr = nullptr;
680  BackingType value = 0;
681 
682  reg.writer([&reg_ptr, &value](auto &r, const BackingType &v) {
683  reg_ptr = &r;
684  value = v;
685  });
686 
687  reg.write(buf.data() + RegSize);
688  EXPECT_EQ(reg_ptr, &reg);
689  EXPECT_EQ(value, 0x0403);
690 }
691 
692 // Set a custom write handler for a register which is a class method.
694 {
695  using Reg = RegisterBankLE::Register<BackingType>;
696 
697  struct WriteStruct
698  {
699  Reg *reg_ptr = nullptr;
700  BackingType value = 0;
701 
702  void
703  writer(Reg &r, const BackingType &v)
704  {
705  reg_ptr = &r;
706  value = v;
707  }
708  } write_struct;
709 
710  reg.writer(&write_struct, &WriteStruct::writer);
711 
712  reg.write(buf.data() + RegSize);
713  EXPECT_EQ(write_struct.reg_ptr, &reg);
714  EXPECT_THAT(write_struct.value, 0x0403);
715 }
716 
717 // Set a custom partial read handler for a register.
718 TEST_F(TypedRegisterTest, PartialReader)
719 {
720  RegisterBankLE::Register<BackingType> *reg_ptr = nullptr;
721  int first = 0;
722  int last = 0;
723  BackingType ret = 0x3344;
724 
725  reg.partialReader([&reg_ptr, &first, &last, ret](auto &r, int f, int l) {
726  reg_ptr = &r;
727  first = f;
728  last = l;
729  return ret;
730  });
731 
732  reg.read(buf.data() + RegSize, 1, 1);
733  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x33, 0x4, 0x5, 0x6));
734  EXPECT_EQ(reg_ptr, &reg);
735  EXPECT_EQ(first, 15);
736  EXPECT_EQ(last, 8);
737 }
738 
739 // Set a custom partial read handler for a register which is a class method.
740 TEST_F(TypedRegisterTest, PartialReaderMF)
741 {
742  using Reg = RegisterBankLE::Register<BackingType>;
743 
744  struct ReadStruct
745  {
746  Reg *reg_ptr = nullptr;
747  int first = 0;
748  int last = 0;
749  BackingType ret = 0x3344;
750 
751  BackingType
752  reader(Reg &r, int f, int l)
753  {
754  reg_ptr = &r;
755  first = f;
756  last = l;
757  return ret;
758  }
759  } read_struct;
760 
761  reg.partialReader(&read_struct, &ReadStruct::reader);
762 
763  reg.read(buf.data() + RegSize, 1, 1);
764  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x33, 0x4, 0x5, 0x6));
765  EXPECT_EQ(read_struct.reg_ptr, &reg);
766  EXPECT_EQ(read_struct.first, 15);
767  EXPECT_EQ(read_struct.last, 8);
768 }
769 
770 // Set a custom partial write handler for a register.
771 TEST_F(TypedRegisterTest, PartialWriter)
772 {
773  RegisterBankLE::Register<BackingType> *reg_ptr = nullptr;
774  BackingType value = 0;
775  int first = 0;
776  int last = 0;
777 
778  reg.partialWriter([&reg_ptr, &value, &first, &last](
779  auto &r, const BackingType &v, int f, int l) {
780  reg_ptr = &r;
781  value = v;
782  first = f;
783  last = l;
784  });
785 
786  reg.write(buf.data() + RegSize, 1, 1);
787  EXPECT_EQ(reg_ptr, &reg);
788  EXPECT_EQ(value, 0x300);
789  EXPECT_EQ(first, 15);
790  EXPECT_EQ(last, 8);
791 }
792 
793 // Set a custom partial write handler for a register which is a class method.
794 TEST_F(TypedRegisterTest, PartialWriterMF)
795 {
796  using Reg = RegisterBankLE::Register<BackingType>;
797 
798  struct WriteStruct
799  {
800  Reg *reg_ptr = nullptr;
801  BackingType value = 0;
802  int first = 0;
803  int last = 0;
804 
805  void
806  writer(Reg &r, const BackingType &v, int f, int l)
807  {
808  reg_ptr = &r;
809  value = v;
810  first = f;
811  last = l;
812  }
813  } write_struct;
814 
815  reg.partialWriter(&write_struct, &WriteStruct::writer);
816 
817  reg.write(buf.data() + RegSize, 1, 1);
818  EXPECT_EQ(write_struct.reg_ptr, &reg);
819  EXPECT_EQ(write_struct.value, 0x300);
820  EXPECT_EQ(write_struct.first, 15);
821  EXPECT_EQ(write_struct.last, 8);
822 }
823 
824 // Default partial reader with a custom read handler.
825 TEST_F(TypedRegisterTest, PartialReaderReader)
826 {
827  RegisterBankLE::Register<BackingType> *reg_ptr = nullptr;
828  BackingType ret = 0x3344;
829 
830  reg.reader([&reg_ptr, &ret](auto &r){
831  reg_ptr = &r;
832  return ret;
833  });
834 
835  reg.read(buf.data() + RegSize, 1, 1);
836  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x33, 0x4, 0x5, 0x6));
837  EXPECT_EQ(reg_ptr, &reg);
838 }
839 
840 // Default partial writer with custome read and write handlers.
841 TEST_F(TypedRegisterTest, PartialWriterReaderWriter)
842 {
843  RegisterBankLE::Register<BackingType> *read_reg_ptr = nullptr;
844  BackingType read_ret = 0x3344;
845 
846  RegisterBankLE::Register<BackingType> *write_reg_ptr = nullptr;
847  BackingType write_value = 0;
848 
849  reg.reader([&read_reg_ptr, read_ret](auto &r){
850  read_reg_ptr = &r;
851  return read_ret;
852  }).writer([&write_reg_ptr, &write_value](auto &r, const BackingType &v) {
853  write_reg_ptr = &r;
854  write_value = v;
855  });
856 
857  reg.write(buf.data() + RegSize, 1, 1);
858  EXPECT_THAT(buf, ElementsAre(0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
859  EXPECT_EQ(read_reg_ptr, &reg);
860  EXPECT_EQ(write_reg_ptr, &reg);
861  EXPECT_EQ(write_value, 0x0344);
862 }
863 
865 {
866  std::ostringstream os;
867  reg.serialize(os);
868  EXPECT_EQ(os.str(), "4386");
869 }
870 
871 TEST_F(TypedRegisterTest, UnserializeSucess)
872 {
873  std::string s = "1234";
874  EXPECT_TRUE(reg.unserialize(s));
875  EXPECT_EQ(reg.get(), 1234);
876 }
877 
878 TEST_F(TypedRegisterTest, UnserializeFailure)
879 {
880  std::string s = "not_a_number";
881  EXPECT_FALSE(reg.unserialize(s));
882 }
883 
884 /*
885  * The RegisterBank itself.
886  */
887 
888 class RegisterBankTest : public testing::Test
889 {
890  protected:
892  {
893  public:
894  TestRegBank(const std::string &new_name, Addr new_base) :
895  RegisterBankLE(new_name, new_base)
896  {}
897  };
898 
899  enum AccessType {
904  };
905 
906  struct Access
907  {
909  uint32_t value = 0;
910  int first = 0;
911  int last = 0;
912  uint32_t ret = 0;
913 
914  Access(AccessType _type) : type(_type) {}
915  Access(AccessType _type, uint32_t _value,
916  int _first, int _last, uint32_t _ret) :
917  type(_type), value(_value),
918  first(_first), last(_last), ret(_ret)
919  {}
920 
921  bool
922  operator == (const Access &other) const
923  {
924  return type == other.type && value == other.value &&
925  first == other.first && last == other.last &&
926  ret == other.ret;
927  }
928  };
929 
930  // A 32 bit register which keeps track of what happens to it.
932  {
933  public:
935 
936  TestReg(const std::string &new_name, uint32_t initial) :
937  TestRegBank::Register32(new_name, initial)
938  {
939  reader([this](auto &r) {
940  Access access(Read);
941  access.ret = defaultReader(r);
942  accesses.push_back(access);
943  return access.ret;
944  });
945  writer([this](auto &r, const uint32_t &v) {
946  Access access(Write);
947  access.value = v;
948  defaultWriter(r, v);
949  accesses.push_back(access);
950  });
951  partialReader([this](auto &r, int f, int l) {
952  Access access(PartialRead);
953  access.first = f;
954  access.last = l;
955  access.ret = defaultPartialReader(r, f, l);
956  accesses.push_back(access);
957  return access.ret;
958  });
959  partialWriter([this](auto &r, const uint32_t &v, int f, int l) {
960  Access access(PartialWrite);
961  access.value = v;
962  access.first = f;
963  access.last = l;
964  defaultPartialWriter(r, v, f, l);
965  accesses.push_back(access);
966  });
967  }
968  };
969 
972 
973  std::array<uint8_t, 12> buf;
974 
976  reg0("reg0", 0xd3d2d1d0), reg1("reg1", 0xe3e2e1e0),
977  reg2("reg2", 0xf3f2f1f0),
978  emptyBank("empty", 0x12345), fullBank("full", 0x1000),
979  buf{0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
980  0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc}
981  {
983  }
984 };
985 
986 // Some basic accessors.
987 
989 {
990  EXPECT_EQ(emptyBank.name(), "empty");
991  EXPECT_EQ(fullBank.name(), "full");
992 }
993 
995 {
996  EXPECT_EQ(emptyBank.base(), 0x12345);
997  EXPECT_EQ(fullBank.base(), 0x1000);
998 }
999 
1000 // Adding registers, and the size accessor. With registers, size is boring.
1001 TEST_F(RegisterBankTest, AddRegistersSize)
1002 {
1003  EXPECT_EQ(emptyBank.size(), 0);
1004  emptyBank.addRegister(reg0);
1005  EXPECT_EQ(emptyBank.size(), 4);
1006  emptyBank.addRegisters({reg1, reg2});
1007  EXPECT_EQ(emptyBank.size(), 12);
1008 }
1009 
1010 // Reads.
1011 
1012 TEST_F(RegisterBankTest, ReadOneAlignedFirst)
1013 {
1014  fullBank.read(0x1000, buf.data() + 4, 4);
1015  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1016  0xd0, 0xd1, 0xd2, 0xd3,
1017  0x99, 0xaa, 0xbb, 0xcc}));
1018  EXPECT_THAT(reg0.accesses, ElementsAre(
1019  Access(Read, 0, 0, 0, 0xd3d2d1d0)
1020  ));
1021  EXPECT_TRUE(reg1.accesses.empty());
1022  EXPECT_TRUE(reg2.accesses.empty());
1023 }
1024 
1025 TEST_F(RegisterBankTest, ReadOneAlignedMid)
1026 {
1027  fullBank.read(0x1004, buf.data() + 4, 4);
1028  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1029  0xe0, 0xe1, 0xe2, 0xe3,
1030  0x99, 0xaa, 0xbb, 0xcc}));
1031  EXPECT_TRUE(reg0.accesses.empty());
1032  EXPECT_THAT(reg1.accesses, ElementsAre(
1033  Access(Read, 0, 0, 0, 0xe3e2e1e0)
1034  ));
1035  EXPECT_TRUE(reg2.accesses.empty());
1036 }
1037 
1038 TEST_F(RegisterBankTest, ReadOneAlignedLast)
1039 {
1040  fullBank.read(0x1008, buf.data() + 4, 4);
1041  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1042  0xf0, 0xf1, 0xf2, 0xf3,
1043  0x99, 0xaa, 0xbb, 0xcc}));
1044  EXPECT_TRUE(reg0.accesses.empty());
1045  EXPECT_TRUE(reg1.accesses.empty());
1046  EXPECT_THAT(reg2.accesses, ElementsAre(
1047  Access(Read, 0, 0, 0, 0xf3f2f1f0)
1048  ));
1049 }
1050 
1051 TEST_F(RegisterBankTest, ReadTwoAligned)
1052 {
1053  fullBank.read(0x1004, buf.data() + 2, 8);
1054  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0xe0, 0xe1,
1055  0xe2, 0xe3, 0xf0, 0xf1,
1056  0xf2, 0xf3, 0xbb, 0xcc}));
1057  EXPECT_TRUE(reg0.accesses.empty());
1058  EXPECT_THAT(reg1.accesses, ElementsAre(
1059  Access(Read, 0, 0, 0, 0xe3e2e1e0)
1060  ));
1061  EXPECT_THAT(reg2.accesses, ElementsAre(
1062  Access(Read, 0, 0, 0, 0xf3f2f1f0)
1063  ));
1064 }
1065 
1066 TEST_F(RegisterBankTest, ReadContained)
1067 {
1068  fullBank.read(0x1001, buf.data() + 4, 2);
1069  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1070  0xd1, 0xd2, 0x77, 0x88,
1071  0x99, 0xaa, 0xbb, 0xcc}));
1072  EXPECT_THAT(reg0.accesses, ElementsAre(
1073  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1074  Access(PartialRead, 0, 23, 8, 0x00d2d100)
1075  ));
1076  EXPECT_TRUE(reg1.accesses.empty());
1077  EXPECT_TRUE(reg2.accesses.empty());
1078 }
1079 
1080 TEST_F(RegisterBankTest, ReadOneSpanning)
1081 {
1082  fullBank.read(0x1002, buf.data() + 4, 4);
1083  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1084  0xd2, 0xd3, 0xe0, 0xe1,
1085  0x99, 0xaa, 0xbb, 0xcc}));
1086  EXPECT_THAT(reg0.accesses, ElementsAre(
1087  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1088  Access(PartialRead, 0, 31, 16, 0xd3d20000)
1089  ));
1090  EXPECT_THAT(reg1.accesses, ElementsAre(
1091  Access(Read, 0, 0, 0, 0xe3e2e1e0),
1092  Access(PartialRead, 0, 15, 0, 0x0000e1e0)
1093  ));
1094  EXPECT_TRUE(reg2.accesses.empty());
1095 }
1096 
1097 TEST_F(RegisterBankTest, ReadTwoSpanning)
1098 {
1099  fullBank.read(0x1002, buf.data() + 2, 8);
1100  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0xd2, 0xd3,
1101  0xe0, 0xe1, 0xe2, 0xe3,
1102  0xf0, 0xf1, 0xbb, 0xcc}));
1103  EXPECT_THAT(reg0.accesses, ElementsAre(
1104  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1105  Access(PartialRead, 0, 31, 16, 0xd3d20000)
1106  ));
1107  EXPECT_THAT(reg1.accesses, ElementsAre(
1108  Access(Read, 0, 0, 0, 0xe3e2e1e0)
1109  ));
1110  EXPECT_THAT(reg2.accesses, ElementsAre(
1111  Access(Read, 0, 0, 0, 0xf3f2f1f0),
1112  Access(PartialRead, 0, 15, 0, 0x0000f1f0)
1113  ));
1114 }
1115 
1116 TEST_F(RegisterBankTest, ReadPartialFull)
1117 {
1118  fullBank.read(0x1002, buf.data() + 4, 6);
1119  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1120  0xd2, 0xd3, 0xe0, 0xe1,
1121  0xe2, 0xe3, 0xbb, 0xcc}));
1122  EXPECT_THAT(reg0.accesses, ElementsAre(
1123  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1124  Access(PartialRead, 0, 31, 16, 0xd3d20000)
1125  ));
1126  EXPECT_THAT(reg1.accesses, ElementsAre(
1127  Access(Read, 0, 0, 0, 0xe3e2e1e0)
1128  ));
1129  EXPECT_TRUE(reg2.accesses.empty());
1130 }
1131 
1132 TEST_F(RegisterBankTest, ReadFullPartial)
1133 {
1134  fullBank.read(0x1004, buf.data() + 4, 6);
1135  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1136  0xe0, 0xe1, 0xe2, 0xe3,
1137  0xf0, 0xf1, 0xbb, 0xcc}));
1138  EXPECT_TRUE(reg0.accesses.empty());
1139  EXPECT_THAT(reg1.accesses, ElementsAre(
1140  Access(Read, 0, 0, 0, 0xe3e2e1e0)
1141  ));
1142  EXPECT_THAT(reg2.accesses, ElementsAre(
1143  Access(Read, 0, 0, 0, 0xf3f2f1f0),
1144  Access(PartialRead, 0, 15, 0, 0x0000f1f0)
1145  ));
1146 }
1147 
1148 TEST_F(RegisterBankTest, ReadLastPartial)
1149 {
1150  fullBank.read(0x100a, buf.data() + 4, 2);
1151  EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1152  0xf2, 0xf3, 0x77, 0x88,
1153  0x99, 0xaa, 0xbb, 0xcc}));
1154  EXPECT_TRUE(reg0.accesses.empty());
1155  EXPECT_TRUE(reg1.accesses.empty());
1156  EXPECT_THAT(reg2.accesses, ElementsAre(
1157  Access(Read, 0, 0, 0, 0xf3f2f1f0),
1158  Access(PartialRead, 0, 31, 16, 0xf3f20000)
1159  ));
1160 }
1161 
1162 // Write.
1163 
1164 TEST_F(RegisterBankTest, WriteOneAlignedFirst)
1165 {
1166  fullBank.write(0x1000, buf.data() + 4, 4);
1167  EXPECT_EQ(reg0.get(), 0x88776655);
1168  EXPECT_EQ(reg1.get(), 0xe3e2e1e0);
1169  EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1170  EXPECT_THAT(reg0.accesses, ElementsAre(
1171  Access(Write, 0x88776655, 0, 0, 0)
1172  ));
1173  EXPECT_TRUE(reg1.accesses.empty());
1174  EXPECT_TRUE(reg2.accesses.empty());
1175 }
1176 
1177 TEST_F(RegisterBankTest, WriteOneAlignedMid)
1178 {
1179  fullBank.write(0x1004, buf.data() + 4, 4);
1180  EXPECT_EQ(reg0.get(), 0xd3d2d1d0);
1181  EXPECT_EQ(reg1.get(), 0x88776655);
1182  EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1183  EXPECT_TRUE(reg0.accesses.empty());
1184  EXPECT_THAT(reg1.accesses, ElementsAre(
1185  Access(Write, 0x88776655, 0, 0, 0)
1186  ));
1187  EXPECT_TRUE(reg2.accesses.empty());
1188 }
1189 
1190 TEST_F(RegisterBankTest, WriteOneAlignedLast)
1191 {
1192  fullBank.write(0x1008, buf.data() + 4, 4);
1193  EXPECT_EQ(reg0.get(), 0xd3d2d1d0);
1194  EXPECT_EQ(reg1.get(), 0xe3e2e1e0);
1195  EXPECT_EQ(reg2.get(), 0x88776655);
1196  EXPECT_TRUE(reg0.accesses.empty());
1197  EXPECT_TRUE(reg1.accesses.empty());
1198  EXPECT_THAT(reg2.accesses, ElementsAre(
1199  Access(Write, 0x88776655, 0, 0, 0)
1200  ));
1201 }
1202 
1203 TEST_F(RegisterBankTest, WriteTwoAligned)
1204 {
1205  fullBank.write(0x1004, buf.data() + 2, 8);
1206  EXPECT_EQ(reg0.get(), 0xd3d2d1d0);
1207  EXPECT_EQ(reg1.get(), 0x66554433);
1208  EXPECT_EQ(reg2.get(), 0xaa998877);
1209  EXPECT_TRUE(reg0.accesses.empty());
1210  EXPECT_THAT(reg1.accesses, ElementsAre(
1211  Access(Write, 0x66554433, 0, 0, 0)
1212  ));
1213  EXPECT_THAT(reg2.accesses, ElementsAre(
1214  Access(Write, 0xaa998877, 0, 0, 0)
1215  ));
1216 }
1217 
1218 TEST_F(RegisterBankTest, WriteContained)
1219 {
1220  fullBank.write(0x1001, buf.data() + 4, 2);
1221  EXPECT_EQ(reg0.get(), 0xd36655d0);
1222  EXPECT_EQ(reg1.get(), 0xe3e2e1e0);
1223  EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1224  EXPECT_THAT(reg0.accesses, ElementsAre(
1225  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1226  Access(Write, 0xd36655d0, 0, 0, 0),
1227  Access(PartialWrite, 0x00665500, 23, 8, 0)
1228  ));
1229  EXPECT_TRUE(reg1.accesses.empty());
1230  EXPECT_TRUE(reg2.accesses.empty());
1231 }
1232 
1233 TEST_F(RegisterBankTest, WriteOneSpanning)
1234 {
1235  fullBank.write(0x1002, buf.data() + 4, 4);
1236  EXPECT_EQ(reg0.get(), 0x6655d1d0);
1237  EXPECT_EQ(reg1.get(), 0xe3e28877);
1238  EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1239  EXPECT_THAT(reg0.accesses, ElementsAre(
1240  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1241  Access(Write, 0x6655d1d0, 0, 0, 0),
1242  Access(PartialWrite, 0x66550000, 31, 16, 0)
1243  ));
1244  EXPECT_THAT(reg1.accesses, ElementsAre(
1245  Access(Read, 0, 0, 0, 0xe3e2e1e0),
1246  Access(Write, 0xe3e28877, 0, 0, 0),
1247  Access(PartialWrite, 0x00008877, 15, 0, 0)
1248  ));
1249  EXPECT_TRUE(reg2.accesses.empty());
1250 }
1251 
1252 TEST_F(RegisterBankTest, WriteTwoSpanning)
1253 {
1254  fullBank.write(0x1002, buf.data() + 2, 8);
1255  EXPECT_EQ(reg0.get(), 0x4433d1d0);
1256  EXPECT_EQ(reg1.get(), 0x88776655);
1257  EXPECT_EQ(reg2.get(), 0xf3f2aa99);
1258  EXPECT_THAT(reg0.accesses, ElementsAre(
1259  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1260  Access(Write, 0x4433d1d0, 0, 0, 0),
1261  Access(PartialWrite, 0x44330000, 31, 16, 0)
1262  ));
1263  EXPECT_THAT(reg1.accesses, ElementsAre(
1264  Access(Write, 0x88776655, 0, 0, 0)
1265  ));
1266  EXPECT_THAT(reg2.accesses, ElementsAre(
1267  Access(Read, 0, 0, 0, 0xf3f2f1f0),
1268  Access(Write, 0xf3f2aa99, 0, 0, 0),
1269  Access(PartialWrite, 0x0000aa99, 15, 0, 0)
1270  ));
1271 }
1272 
1273 TEST_F(RegisterBankTest, WritePartialFull)
1274 {
1275  fullBank.write(0x1002, buf.data() + 4, 6);
1276  EXPECT_EQ(reg0.get(), 0x6655d1d0);
1277  EXPECT_EQ(reg1.get(), 0xaa998877);
1278  EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1279  EXPECT_THAT(reg0.accesses, ElementsAre(
1280  Access(Read, 0, 0, 0, 0xd3d2d1d0),
1281  Access(Write, 0x6655d1d0, 0, 0, 0),
1282  Access(PartialWrite, 0x66550000, 31, 16, 0)
1283  ));
1284  EXPECT_THAT(reg1.accesses, ElementsAre(
1285  Access(Write, 0xaa998877, 0, 0, 0)
1286  ));
1287  EXPECT_TRUE(reg2.accesses.empty());
1288 }
1289 
1290 TEST_F(RegisterBankTest, WriteFullPartial)
1291 {
1292  fullBank.write(0x1004, buf.data() + 4, 6);
1293  EXPECT_EQ(reg0.get(), 0xd3d2d1d0);
1294  EXPECT_EQ(reg1.get(), 0x88776655);
1295  EXPECT_EQ(reg2.get(), 0xf3f2aa99);
1296  EXPECT_TRUE(reg0.accesses.empty());
1297  EXPECT_THAT(reg1.accesses, ElementsAre(
1298  Access(Write, 0x88776655, 0, 0, 0)
1299  ));
1300  EXPECT_THAT(reg2.accesses, ElementsAre(
1301  Access(Read, 0, 0, 0, 0xf3f2f1f0),
1302  Access(Write, 0xf3f2aa99, 0, 0, 0),
1303  Access(PartialWrite, 0x0000aa99, 15, 0, 0)
1304  ));
1305 }
RegisterBankTest::RegisterBankTest
RegisterBankTest()
Definition: reg_bank.test.cc:975
RegisterRazTest::BufOffset
static constexpr size_t BufOffset
Definition: reg_bank.test.cc:74
RegisterBankTest::TestRegBank::TestRegBank
TestRegBank(const std::string &new_name, Addr new_base)
Definition: reg_bank.test.cc:894
RegisterRaoTest::buf
std::array< uint8_t, BufSize > buf
Definition: reg_bank.test.cc:163
RegisterBank::addRegisters
void addRegisters(std::initializer_list< std::reference_wrapper< RegisterBase >> regs)
Definition: reg_bank.hh:787
RegisterBank::Register< BackingType >
X86ISA::os
Bitfield< 17 > os
Definition: misc.hh:803
RegisterRaoTest::BufOffset
static constexpr size_t BufOffset
Definition: reg_bank.test.cc:160
RegisterBankTest::reg0
TestReg reg0
Definition: reg_bank.test.cc:970
RegisterBankTest::AccessType
AccessType
Definition: reg_bank.test.cc:899
data
const char data[]
Definition: circlebuf.test.cc:47
RegisterRazTest::raz
RegisterBankLE::RegisterRaz raz
Definition: reg_bank.test.cc:78
RegisterBankTest
Definition: reg_bank.test.cc:888
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
RegisterRazTest::BufSize
static constexpr size_t BufSize
Definition: reg_bank.test.cc:73
RegisterBankTest::emptyBank
TestRegBank emptyBank
Definition: reg_bank.test.cc:971
RegisterBank::addRegister
void addRegister(RegisterBase &reg)
Definition: reg_bank.hh:798
RegisterBankTest::Access::Access
Access(AccessType _type, uint32_t _value, int _first, int _last, uint32_t _ret)
Definition: reg_bank.test.cc:915
RegisterBankTest::TestReg::accesses
std::vector< Access > accesses
Definition: reg_bank.test.cc:934
RegisterBankTest::buf
std::array< uint8_t, 12 > buf
Definition: reg_bank.test.cc:973
RegisterRaoTest::rao
RegisterBankLE::RegisterRao rao
Definition: reg_bank.test.cc:164
TEST_F
TEST_F(RegisterRazTest, Name)
Definition: reg_bank.test.cc:88
RegisterBankTest::PartialRead
@ PartialRead
Definition: reg_bank.test.cc:902
RegisterBankTest::reg2
TestReg reg2
Definition: reg_bank.test.cc:970
ArmISA::raz
Bitfield< 31, 28 > raz
Definition: miscregs_types.hh:478
RegisterBufTest::RegisterBufTest
RegisterBufTest()
Definition: reg_bank.test.cc:253
std::vector< Access >
RegisterBank::write
virtual void write(Addr addr, const void *buf, Addr bytes)
Definition: reg_bank.hh:862
RegisterBufTest::reg
RegisterBankLE::RegisterBuf reg
Definition: reg_bank.test.cc:247
X86ISA::reg
Bitfield< 5, 3 > reg
Definition: types.hh:88
RegisterBank::base
Addr base() const
Definition: reg_bank.hh:800
RegisterBankTest::Access::Access
Access(AccessType _type)
Definition: reg_bank.test.cc:914
RegisterLBufTest
Definition: reg_bank.test.cc:388
Access
Definition: proxy_ptr.test.cc:34
RegisterBufTest::backing
std::array< uint8_t, RegSize *3 > backing
Definition: reg_bank.test.cc:250
RegisterBank::read
virtual void read(Addr addr, void *buf, Addr bytes)
Definition: reg_bank.hh:805
RegisterBankTest::Access::ret
uint32_t ret
Definition: reg_bank.test.cc:912
RegisterRaoTest
Definition: reg_bank.test.cc:156
RegisterLBufTest::RegisterLBufTest
RegisterLBufTest()
Definition: reg_bank.test.cc:397
writer
Definition: test.h:47
RegisterBankTest::TestReg::TestReg
TestReg(const std::string &new_name, uint32_t initial)
Definition: reg_bank.test.cc:936
TypedRegisterTest::regBE
RegisterBankBE::Register< BackingType > regBE
Definition: reg_bank.test.cc:457
MipsISA::r
r
Definition: pra_constants.hh:95
RegisterBank< ByteOrder::little >::Register32
Register< uint32_t > Register32
Definition: reg_bank.hh:772
RegisterBufTest
Definition: reg_bank.test.cc:242
RegisterBufTest::buf
std::array< uint8_t, RegSize *3 > buf
Definition: reg_bank.test.cc:249
RegisterBank::size
Addr size() const
Definition: reg_bank.hh:801
RegisterBankTest::Access::type
AccessType type
Definition: reg_bank.test.cc:908
RegisterLBufTest::to_write
std::array< uint8_t, 4 > to_write
Definition: reg_bank.test.cc:394
RegisterBank< ByteOrder::little >
RegisterRaoTest::RegisterRaoTest
RegisterRaoTest()
Definition: reg_bank.test.cc:166
RegisterBankTest::Access::value
uint32_t value
Definition: reg_bank.test.cc:909
RegisterLBufTest::RegSize
static constexpr size_t RegSize
Definition: reg_bank.test.cc:391
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:148
RegisterRaoTest::RaoSize
static constexpr size_t RaoSize
Definition: reg_bank.test.cc:161
TypedRegisterTest::RegSize
static constexpr size_t RegSize
Definition: reg_bank.test.cc:452
RegisterBankTest::Access::last
int last
Definition: reg_bank.test.cc:911
RegisterRazTest::RazSize
static constexpr size_t RazSize
Definition: reg_bank.test.cc:75
TypedRegisterTest
Definition: reg_bank.test.cc:448
RegisterRazTest
Definition: reg_bank.test.cc:70
RegisterBankTest::fullBank
TestRegBank fullBank
Definition: reg_bank.test.cc:971
RegisterBankTest::PartialWrite
@ PartialWrite
Definition: reg_bank.test.cc:903
TypedRegisterTest::reg
RegisterBankLE::Register< BackingType > reg
Definition: reg_bank.test.cc:456
RegisterBankTest::reg1
TestReg reg1
Definition: reg_bank.test.cc:970
RegisterBank::name
const std::string & name() const
Definition: reg_bank.hh:802
RegisterBankTest::Read
@ Read
Definition: reg_bank.test.cc:900
RegisterBankTest::TestRegBank
Definition: reg_bank.test.cc:891
RegisterLBufTest::reg
RegisterBankLE::RegisterLBuf< 12 > reg
Definition: reg_bank.test.cc:393
TypedRegisterTest::TypedRegisterTest
TypedRegisterTest()
Definition: reg_bank.test.cc:461
RegisterRazTest::RegisterRazTest
RegisterRazTest()
Definition: reg_bank.test.cc:80
ArmISA::s
Bitfield< 4 > s
Definition: miscregs_types.hh:556
RegisterBankTest::Write
@ Write
Definition: reg_bank.test.cc:901
TypedRegisterTest::buf
std::array< uint8_t, RegSize *3 > buf
Definition: reg_bank.test.cc:459
RegisterRazTest::buf
std::array< uint8_t, BufSize > buf
Definition: reg_bank.test.cc:77
RegisterBankTest::Access
Definition: reg_bank.test.cc:906
MipsISA::l
Bitfield< 5 > l
Definition: pra_constants.hh:320
RegisterBankTest::Access::operator==
bool operator==(const Access &other) const
Definition: reg_bank.test.cc:922
RegisterBankTest::TestReg
Definition: reg_bank.test.cc:931
ArmISA::v
Bitfield< 28 > v
Definition: miscregs_types.hh:51
reg_bank.hh
TypedRegisterTest::BackingType
uint16_t BackingType
Definition: reg_bank.test.cc:451
RegisterBufTest::RegSize
static constexpr size_t RegSize
Definition: reg_bank.test.cc:245
RegisterRaoTest::BufSize
static constexpr size_t BufSize
Definition: reg_bank.test.cc:159
ArmISA::f
Bitfield< 6 > f
Definition: miscregs_types.hh:64
RegisterBankTest::Access::first
int first
Definition: reg_bank.test.cc:910

Generated on Tue Mar 23 2021 19:41:26 for gem5 by doxygen 1.8.17