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

Generated on Wed Dec 21 2022 10:22:34 for gem5 by doxygen 1.9.1