gem5 v24.0.0.0
Loading...
Searching...
No Matches
reg_bank.test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020, 2024 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
61using namespace gem5;
62
63// Compare the elements of an array against expected values.
64using testing::ElementsAre;
65// This version is needed with enough elements, empirically more than 10.
66using testing::ElementsAreArray;
67
68using testing::AllOf;
69using testing::HasSubstr;
70
71
72/*
73 * The RegisterRaz (read as zero) type.
74 */
75
76class 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
87 {
88 buf.fill(0xff);
89 }
90};
91// Needed by C++14 and lower
92constexpr 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.
115TEST_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.
125TEST_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.
135TEST_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
152{
153 std::string s;
154 EXPECT_TRUE(raz.unserialize(s));
155}
156
157
158/*
159 * The RegisterRao (read as one) type.
160 */
161
162class 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
173 {
174 buf.fill(0x00);
175 }
176};
177// Needed by C++14 and lower
178constexpr 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.
201TEST_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.
211TEST_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.
221TEST_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
238{
239 std::string s;
240 EXPECT_TRUE(rao.unserialize(s));
241}
242
243
244/*
245 * The RegisterBuf type.
246 */
247
248class 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
267constexpr 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.
304TEST_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.
316TEST_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.
328TEST_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.
340TEST_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.
352TEST_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.
364TEST_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
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
395class 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
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
432TEST_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
440TEST_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
455class 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
473constexpr size_t TypedRegisterTest::RegSize;
474
475TEST_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.
512TEST_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.
520TEST_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.
528TEST_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.
536TEST_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.
544TEST_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.
552TEST_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.
560TEST_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.
568TEST_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.
576TEST_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.
584TEST_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.
592TEST_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.
600TEST_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.
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.
628TEST_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.
635TEST_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.
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.
747TEST_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.
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.
801TEST_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.
832TEST_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.
848TEST_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.
872TEST_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
885TEST_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
950TEST_F(TypedRegisterTest, UnserializeSucess)
951{
952 std::string s = "1234";
953 EXPECT_TRUE(reg.unserialize(s));
954 EXPECT_EQ(reg.get(), 1234);
955}
956
957TEST_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
967class 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
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
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 {
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.
1081TEST_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
1090TEST_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
1114TEST_F(RegisterBankTest, AddRegistersAtOffsetDeath)
1115{
1116 gtestLogOutput.str("");
1117
1118 auto base = emptyBank.base();
1119 EXPECT_ANY_THROW(
1120 emptyBank.addRegistersAt<RegisterBankLE::RegisterRao>(
1121 {{base + 0x0, reg0},
1122 {base + 0x2, reg1},
1123 {base + 0x4, reg2}}));
1124
1125 std::string actual = gtestLogOutput.str();
1126 EXPECT_THAT(actual, HasSubstr("Overlapping register"));
1127 EXPECT_THAT(actual, HasSubstr("reg1"));
1128}
1129
1141TEST_F(RegisterBankTest, AddRegistersAtOffsetContiguous)
1142{
1143 auto base = emptyBank.base();
1144 EXPECT_EQ(emptyBank.size(), 0);
1145 emptyBank.addRegistersAt<RegisterBankLE::RegisterRao>(
1146 {{base + 0x0, reg0},
1147 {base + 0x4, reg1},
1148 {base + 0x8, reg2}});
1149 EXPECT_EQ(emptyBank.size(), 0xc);
1150}
1151
1164TEST_F(RegisterBankTest, AddRegistersAtOffsetSparse)
1165{
1166 auto base = emptyBank.base();
1167 EXPECT_EQ(emptyBank.size(), 0);
1168 emptyBank.addRegistersAt<RegisterBankLE::RegisterRao>(
1169 {{base + 0x0, reg0},
1170 {base + 0x8, reg1},
1171 {base + 0x10, reg2}});
1172 EXPECT_EQ(emptyBank.size(), 0x14);
1173
1174 emptyBank.read(base + 0x0, buf.data(), 4);
1175 EXPECT_EQ(reg0.get(), *reinterpret_cast<uint32_t*>(buf.data()));
1176
1177 emptyBank.read(base + 0x4, buf.data(), 4);
1178 EXPECT_EQ(0xffffffff, *reinterpret_cast<uint32_t*>(buf.data()));
1179
1180 emptyBank.read(base + 0x8, buf.data(), 4);
1181 EXPECT_EQ(reg1.get(), *reinterpret_cast<uint32_t*>(buf.data()));
1182
1183 emptyBank.read(base + 0xc, buf.data(), 4);
1184 EXPECT_EQ(0xffffffff, *reinterpret_cast<uint32_t*>(buf.data()));
1185
1186 emptyBank.read(base + 0x10, buf.data(), 4);
1187 EXPECT_EQ(reg2.get(), *reinterpret_cast<uint32_t*>(buf.data()));
1188}
1189
1190TEST_F(RegisterBankTest, BadRegisterOffsetDeath)
1191{
1192 gtestLogOutput.str("");
1193 EXPECT_ANY_THROW(emptyBank.addRegisters({{0xabcd, reg0}, reg1}));
1194
1195 std::string actual = gtestLogOutput.str();
1196 EXPECT_THAT(actual, HasSubstr("empty.reg0"));
1197 EXPECT_THAT(actual, HasSubstr("to be 0xabcd"));
1198 EXPECT_THAT(actual, HasSubstr("is 0x12345"));
1199}
1200
1201TEST_F(RegisterBankTest, BadBankOffsetDeath)
1202{
1203 gtestLogOutput.str("");
1204 EXPECT_ANY_THROW(emptyBank.addRegisters({{0xabcd}, reg0}));
1205
1206 std::string actual = gtestLogOutput.str();
1207 EXPECT_THAT(actual, HasSubstr("empty "));
1208 EXPECT_THAT(actual, HasSubstr("to be 0xabcd"));
1209 EXPECT_THAT(actual, HasSubstr("is 0x12345"));
1210}
1211
1212// Reads.
1213
1214TEST_F(RegisterBankTest, ReadOneAlignedFirst)
1215{
1216 fullBank.read(0x1000, buf.data() + 4, 4);
1217 EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1218 0xd0, 0xd1, 0xd2, 0xd3,
1219 0x99, 0xaa, 0xbb, 0xcc}));
1220 EXPECT_THAT(reg0.accesses, ElementsAre(
1221 Access(Read, 0, 0, 0, 0xd3d2d1d0)
1222 ));
1223 EXPECT_TRUE(reg1.accesses.empty());
1224 EXPECT_TRUE(reg2.accesses.empty());
1225}
1226
1227TEST_F(RegisterBankTest, ReadOneAlignedMid)
1228{
1229 fullBank.read(0x1004, buf.data() + 4, 4);
1230 EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1231 0xe0, 0xe1, 0xe2, 0xe3,
1232 0x99, 0xaa, 0xbb, 0xcc}));
1233 EXPECT_TRUE(reg0.accesses.empty());
1234 EXPECT_THAT(reg1.accesses, ElementsAre(
1235 Access(Read, 0, 0, 0, 0xe3e2e1e0)
1236 ));
1237 EXPECT_TRUE(reg2.accesses.empty());
1238}
1239
1240TEST_F(RegisterBankTest, ReadOneAlignedLast)
1241{
1242 fullBank.read(0x1008, buf.data() + 4, 4);
1243 EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1244 0xf0, 0xf1, 0xf2, 0xf3,
1245 0x99, 0xaa, 0xbb, 0xcc}));
1246 EXPECT_TRUE(reg0.accesses.empty());
1247 EXPECT_TRUE(reg1.accesses.empty());
1248 EXPECT_THAT(reg2.accesses, ElementsAre(
1249 Access(Read, 0, 0, 0, 0xf3f2f1f0)
1250 ));
1251}
1252
1253TEST_F(RegisterBankTest, ReadTwoAligned)
1254{
1255 fullBank.read(0x1004, buf.data() + 2, 8);
1256 EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0xe0, 0xe1,
1257 0xe2, 0xe3, 0xf0, 0xf1,
1258 0xf2, 0xf3, 0xbb, 0xcc}));
1259 EXPECT_TRUE(reg0.accesses.empty());
1260 EXPECT_THAT(reg1.accesses, ElementsAre(
1261 Access(Read, 0, 0, 0, 0xe3e2e1e0)
1262 ));
1263 EXPECT_THAT(reg2.accesses, ElementsAre(
1264 Access(Read, 0, 0, 0, 0xf3f2f1f0)
1265 ));
1266}
1267
1269{
1270 fullBank.read(0x1001, buf.data() + 4, 2);
1271 EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1272 0xd1, 0xd2, 0x77, 0x88,
1273 0x99, 0xaa, 0xbb, 0xcc}));
1274 EXPECT_THAT(reg0.accesses, ElementsAre(
1275 Access(Read, 0, 0, 0, 0xd3d2d1d0),
1276 Access(PartialRead, 0, 23, 8, 0x00d2d100)
1277 ));
1278 EXPECT_TRUE(reg1.accesses.empty());
1279 EXPECT_TRUE(reg2.accesses.empty());
1280}
1281
1282TEST_F(RegisterBankTest, ReadOneSpanning)
1283{
1284 fullBank.read(0x1002, buf.data() + 4, 4);
1285 EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1286 0xd2, 0xd3, 0xe0, 0xe1,
1287 0x99, 0xaa, 0xbb, 0xcc}));
1288 EXPECT_THAT(reg0.accesses, ElementsAre(
1289 Access(Read, 0, 0, 0, 0xd3d2d1d0),
1290 Access(PartialRead, 0, 31, 16, 0xd3d20000)
1291 ));
1292 EXPECT_THAT(reg1.accesses, ElementsAre(
1293 Access(Read, 0, 0, 0, 0xe3e2e1e0),
1294 Access(PartialRead, 0, 15, 0, 0x0000e1e0)
1295 ));
1296 EXPECT_TRUE(reg2.accesses.empty());
1297}
1298
1299TEST_F(RegisterBankTest, ReadTwoSpanning)
1300{
1301 fullBank.read(0x1002, buf.data() + 2, 8);
1302 EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0xd2, 0xd3,
1303 0xe0, 0xe1, 0xe2, 0xe3,
1304 0xf0, 0xf1, 0xbb, 0xcc}));
1305 EXPECT_THAT(reg0.accesses, ElementsAre(
1306 Access(Read, 0, 0, 0, 0xd3d2d1d0),
1307 Access(PartialRead, 0, 31, 16, 0xd3d20000)
1308 ));
1309 EXPECT_THAT(reg1.accesses, ElementsAre(
1310 Access(Read, 0, 0, 0, 0xe3e2e1e0)
1311 ));
1312 EXPECT_THAT(reg2.accesses, ElementsAre(
1313 Access(Read, 0, 0, 0, 0xf3f2f1f0),
1314 Access(PartialRead, 0, 15, 0, 0x0000f1f0)
1315 ));
1316}
1317
1318TEST_F(RegisterBankTest, ReadPartialFull)
1319{
1320 fullBank.read(0x1002, buf.data() + 4, 6);
1321 EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1322 0xd2, 0xd3, 0xe0, 0xe1,
1323 0xe2, 0xe3, 0xbb, 0xcc}));
1324 EXPECT_THAT(reg0.accesses, ElementsAre(
1325 Access(Read, 0, 0, 0, 0xd3d2d1d0),
1326 Access(PartialRead, 0, 31, 16, 0xd3d20000)
1327 ));
1328 EXPECT_THAT(reg1.accesses, ElementsAre(
1329 Access(Read, 0, 0, 0, 0xe3e2e1e0)
1330 ));
1331 EXPECT_TRUE(reg2.accesses.empty());
1332}
1333
1334TEST_F(RegisterBankTest, ReadFullPartial)
1335{
1336 fullBank.read(0x1004, buf.data() + 4, 6);
1337 EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1338 0xe0, 0xe1, 0xe2, 0xe3,
1339 0xf0, 0xf1, 0xbb, 0xcc}));
1340 EXPECT_TRUE(reg0.accesses.empty());
1341 EXPECT_THAT(reg1.accesses, ElementsAre(
1342 Access(Read, 0, 0, 0, 0xe3e2e1e0)
1343 ));
1344 EXPECT_THAT(reg2.accesses, ElementsAre(
1345 Access(Read, 0, 0, 0, 0xf3f2f1f0),
1346 Access(PartialRead, 0, 15, 0, 0x0000f1f0)
1347 ));
1348}
1349
1350TEST_F(RegisterBankTest, ReadLastPartial)
1351{
1352 fullBank.read(0x100a, buf.data() + 4, 2);
1353 EXPECT_THAT(buf, ElementsAreArray({0x11, 0x22, 0x33, 0x44,
1354 0xf2, 0xf3, 0x77, 0x88,
1355 0x99, 0xaa, 0xbb, 0xcc}));
1356 EXPECT_TRUE(reg0.accesses.empty());
1357 EXPECT_TRUE(reg1.accesses.empty());
1358 EXPECT_THAT(reg2.accesses, ElementsAre(
1359 Access(Read, 0, 0, 0, 0xf3f2f1f0),
1360 Access(PartialRead, 0, 31, 16, 0xf3f20000)
1361 ));
1362}
1363
1364// Write.
1365
1366TEST_F(RegisterBankTest, WriteOneAlignedFirst)
1367{
1368 fullBank.write(0x1000, buf.data() + 4, 4);
1369 EXPECT_EQ(reg0.get(), 0x88776655);
1370 EXPECT_EQ(reg1.get(), 0xe3e2e1e0);
1371 EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1372 EXPECT_THAT(reg0.accesses, ElementsAre(
1373 Access(Write, 0x88776655, 0, 0, 0)
1374 ));
1375 EXPECT_TRUE(reg1.accesses.empty());
1376 EXPECT_TRUE(reg2.accesses.empty());
1377}
1378
1379TEST_F(RegisterBankTest, WriteOneAlignedMid)
1380{
1381 fullBank.write(0x1004, buf.data() + 4, 4);
1382 EXPECT_EQ(reg0.get(), 0xd3d2d1d0);
1383 EXPECT_EQ(reg1.get(), 0x88776655);
1384 EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1385 EXPECT_TRUE(reg0.accesses.empty());
1386 EXPECT_THAT(reg1.accesses, ElementsAre(
1387 Access(Write, 0x88776655, 0, 0, 0)
1388 ));
1389 EXPECT_TRUE(reg2.accesses.empty());
1390}
1391
1392TEST_F(RegisterBankTest, WriteOneAlignedLast)
1393{
1394 fullBank.write(0x1008, buf.data() + 4, 4);
1395 EXPECT_EQ(reg0.get(), 0xd3d2d1d0);
1396 EXPECT_EQ(reg1.get(), 0xe3e2e1e0);
1397 EXPECT_EQ(reg2.get(), 0x88776655);
1398 EXPECT_TRUE(reg0.accesses.empty());
1399 EXPECT_TRUE(reg1.accesses.empty());
1400 EXPECT_THAT(reg2.accesses, ElementsAre(
1401 Access(Write, 0x88776655, 0, 0, 0)
1402 ));
1403}
1404
1405TEST_F(RegisterBankTest, WriteTwoAligned)
1406{
1407 fullBank.write(0x1004, buf.data() + 2, 8);
1408 EXPECT_EQ(reg0.get(), 0xd3d2d1d0);
1409 EXPECT_EQ(reg1.get(), 0x66554433);
1410 EXPECT_EQ(reg2.get(), 0xaa998877);
1411 EXPECT_TRUE(reg0.accesses.empty());
1412 EXPECT_THAT(reg1.accesses, ElementsAre(
1413 Access(Write, 0x66554433, 0, 0, 0)
1414 ));
1415 EXPECT_THAT(reg2.accesses, ElementsAre(
1416 Access(Write, 0xaa998877, 0, 0, 0)
1417 ));
1418}
1419
1420TEST_F(RegisterBankTest, WriteContained)
1421{
1422 fullBank.write(0x1001, buf.data() + 4, 2);
1423 EXPECT_EQ(reg0.get(), 0xd36655d0);
1424 EXPECT_EQ(reg1.get(), 0xe3e2e1e0);
1425 EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1426 EXPECT_THAT(reg0.accesses, ElementsAre(
1427 Access(Read, 0, 0, 0, 0xd3d2d1d0),
1428 Access(Write, 0xd36655d0, 0, 0, 0),
1429 Access(PartialWrite, 0x00665500, 23, 8, 0)
1430 ));
1431 EXPECT_TRUE(reg1.accesses.empty());
1432 EXPECT_TRUE(reg2.accesses.empty());
1433}
1434
1435TEST_F(RegisterBankTest, WriteOneSpanning)
1436{
1437 fullBank.write(0x1002, buf.data() + 4, 4);
1438 EXPECT_EQ(reg0.get(), 0x6655d1d0);
1439 EXPECT_EQ(reg1.get(), 0xe3e28877);
1440 EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1441 EXPECT_THAT(reg0.accesses, ElementsAre(
1442 Access(Read, 0, 0, 0, 0xd3d2d1d0),
1443 Access(Write, 0x6655d1d0, 0, 0, 0),
1444 Access(PartialWrite, 0x66550000, 31, 16, 0)
1445 ));
1446 EXPECT_THAT(reg1.accesses, ElementsAre(
1447 Access(Read, 0, 0, 0, 0xe3e2e1e0),
1448 Access(Write, 0xe3e28877, 0, 0, 0),
1449 Access(PartialWrite, 0x00008877, 15, 0, 0)
1450 ));
1451 EXPECT_TRUE(reg2.accesses.empty());
1452}
1453
1454TEST_F(RegisterBankTest, WriteTwoSpanning)
1455{
1456 fullBank.write(0x1002, buf.data() + 2, 8);
1457 EXPECT_EQ(reg0.get(), 0x4433d1d0);
1458 EXPECT_EQ(reg1.get(), 0x88776655);
1459 EXPECT_EQ(reg2.get(), 0xf3f2aa99);
1460 EXPECT_THAT(reg0.accesses, ElementsAre(
1461 Access(Read, 0, 0, 0, 0xd3d2d1d0),
1462 Access(Write, 0x4433d1d0, 0, 0, 0),
1463 Access(PartialWrite, 0x44330000, 31, 16, 0)
1464 ));
1465 EXPECT_THAT(reg1.accesses, ElementsAre(
1466 Access(Write, 0x88776655, 0, 0, 0)
1467 ));
1468 EXPECT_THAT(reg2.accesses, ElementsAre(
1469 Access(Read, 0, 0, 0, 0xf3f2f1f0),
1470 Access(Write, 0xf3f2aa99, 0, 0, 0),
1471 Access(PartialWrite, 0x0000aa99, 15, 0, 0)
1472 ));
1473}
1474
1475TEST_F(RegisterBankTest, WritePartialFull)
1476{
1477 fullBank.write(0x1002, buf.data() + 4, 6);
1478 EXPECT_EQ(reg0.get(), 0x6655d1d0);
1479 EXPECT_EQ(reg1.get(), 0xaa998877);
1480 EXPECT_EQ(reg2.get(), 0xf3f2f1f0);
1481 EXPECT_THAT(reg0.accesses, ElementsAre(
1482 Access(Read, 0, 0, 0, 0xd3d2d1d0),
1483 Access(Write, 0x6655d1d0, 0, 0, 0),
1484 Access(PartialWrite, 0x66550000, 31, 16, 0)
1485 ));
1486 EXPECT_THAT(reg1.accesses, ElementsAre(
1487 Access(Write, 0xaa998877, 0, 0, 0)
1488 ));
1489 EXPECT_TRUE(reg2.accesses.empty());
1490}
1491
1492TEST_F(RegisterBankTest, WriteFullPartial)
1493{
1494 fullBank.write(0x1004, buf.data() + 4, 6);
1495 EXPECT_EQ(reg0.get(), 0xd3d2d1d0);
1496 EXPECT_EQ(reg1.get(), 0x88776655);
1497 EXPECT_EQ(reg2.get(), 0xf3f2aa99);
1498 EXPECT_TRUE(reg0.accesses.empty());
1499 EXPECT_THAT(reg1.accesses, ElementsAre(
1500 Access(Write, 0x88776655, 0, 0, 0)
1501 ));
1502 EXPECT_THAT(reg2.accesses, ElementsAre(
1503 Access(Read, 0, 0, 0, 0xf3f2f1f0),
1504 Access(Write, 0xf3f2aa99, 0, 0, 0),
1505 Access(PartialWrite, 0x0000aa99, 15, 0, 0)
1506 ));
1507}
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
static constexpr size_t RegSize
std::array< uint8_t, 4 > to_write
RegisterBankLE::RegisterLBuf< 12 > reg
static constexpr size_t BufOffset
std::array< uint8_t, BufSize > buf
static constexpr size_t RaoSize
RegisterBankLE::RegisterRao rao
static constexpr size_t BufSize
std::array< uint8_t, BufSize > buf
static constexpr size_t BufSize
RegisterBankLE::RegisterRaz raz
static constexpr size_t RazSize
static constexpr size_t BufOffset
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< RegisterAdder > adders)
Definition reg_bank.hh:956
STL vector class.
Definition stl.hh:37
Definition test.h:49
Bitfield< 28 > v
Definition misc_types.hh:54
Bitfield< 4 > s
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 6 > f
Definition misc_types.hh:68
Bitfield< 31, 28 > raz
Bitfield< 5 > l
Bitfield< 5, 3 > reg
Definition types.hh:92
Bitfield< 51, 12 > base
Definition pagetable.hh:141
Bitfield< 17 > os
Definition misc.hh:838
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
thread_local GTestLogOutput gtestLogOutput
Definition logging.cc:33
TEST_F(RegisterRazTest, Name)
bool operator==(const Access &other) const
Access(AccessType _type)
Access(AccessType _type, uint32_t _value, int _first, int _last, uint32_t _ret)

Generated on Tue Jun 18 2024 16:24:03 for gem5 by doxygen 1.11.0