Software APIs
mock_mmio_test_utils.h
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #ifndef OPENTITAN_SW_DEVICE_LIB_BASE_MOCK_MMIO_TEST_UTILS_H_
6 #define OPENTITAN_SW_DEVICE_LIB_BASE_MOCK_MMIO_TEST_UTILS_H_
7 
8 #include <initializer_list>
9 #include <memory>
10 #include <random>
11 #include <stdint.h>
12 #include <string.h>
13 #include <vector>
14 
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
17 
18 namespace mock_mmio {
19 
20 /**
21  * Represents a single bit field in an integer, useable with EXPECT_* macros
22  * defined in this file.
23  *
24  * An integer can be expressed as a list of BitField values, and can be more
25  * convenient to use than 0b or 0x literals in some cases. For example, the
26  * integer 0b0000'0000'1100'0101 could be expressed as
27  * {{0x0, 1}, {0x2, 1}, {0x4, 12}}
28  * This form makes it clearer to the reader that 0x0, 0x2, and 04 are indices
29  * to bitfields, which are set to particular values.
30  *
31  * In practice, this might use generated register constants, and look like
32  * {{FIELD_FOO_OFFSET, 1}, {FIELD_BAR_OFFSET, 1}, {FIELD_BAZ_OFFSET, 12}}
33  *
34  * This type does not specify the lengths of bitfields; MaskedBitField should be
35  * used for that, instead.
36  */
37 struct BitField {
38  uintptr_t offset;
39  uintptr_t value;
40 };
41 
42 /**
43  * Represents a single bit field in an integer, similar to BitField. It can be
44  * used in most places that need a BitField, as well as in `EXPECT_MASK` macros.
45  *
46  * Like with BitFields, we can express the integer 0b0000'0000'1100'0101 as a
47  * list of BitFieldMasks:
48  * {{0x0, 0x1, 1}, {0x1, 0x1, 0}, {0x2, 0x1, 1}, {0x3, 0x1, 0},
49  * {0x4, 0xff, 12}}
50  *
51  * In addition to showing how the integer is broken up, it also expresses
52  * the lengths of fields, so it is clear that 0x0 and 0x2 are one-bit fields.
53  * This also allows us to formally express that the fields 0x1 and 0x3 are
54  * *unset*.
55  *
56  * In practice, this might use generated register constants, and look like
57  * {{FIELD_FOO_OFFSET, FIELD_FOO_MASK, 1}, ...}
58  */
60  uintptr_t offset;
61  uintptr_t mask;
62  uintptr_t value;
63 };
64 
65 /**
66  * Implicit conversion guard around `char *`. See `LeInt()`.
67  */
69  const char *bytes;
70 };
71 
72 /**
73  * Converts the argument into an unsigned integer of type `Int`.
74  *
75  * This overload is simply the identity on integers, and allows integers to be
76  * converted into themselves. This enables the basic EXPECT_* macros:
77  * EXPECT_READ32(offset, 0xcafecafe);
78  *
79  * @param val an integer.
80  * @return the value `val`.
81  */
82 template <typename Int>
83 Int ToInt(Int val) {
84  return val;
85 }
86 
87 /**
88  * Converts the argument into an unsinged integer of type `Int`.
89  *
90  * This overload assumes that `str` is a valid pointer to a buffer of at least
91  * `sizeof(Int)` bytes, which are memcpy'd out as an `Int`. This enables
92  * memcpy-like EXPECT_* macros:
93  * EXPECT_READ32(offset, LeInt("rv32"));
94  * EXPECT_READ32(offset, LeInt("imc\0"));
95  *
96  * @param str a pointer to a valid buffer of length at least `sizeof(Int)`.
97  * @return a value of type `Int` memcpy'd out of `str`.
98  */
99 template <typename Int>
100 Int ToInt(LittleEndianBytes str) {
101  Int val;
102  memcpy(&val, str.bytes, sizeof(Int));
103  return val;
104 }
105 
106 /**
107  * Converts the argument into an unsigned integer of type `Int`.
108  *
109  * This overload performs the shifts and ors described by `fields`. See
110  * `BitField`'s documentation for details one what this means. This overload
111  * enables bitfield EXPECT_* macros:
112  * EXPECT_READ32(offset, {{A_OFFSET, 0x55}, {B_OFFSET, 0xaa}});
113  * EXPECT_READ32(offset, fields);
114  * where `fields` is an `std::vector<BitField>`.
115  *
116  * @param fields a list of bit field entries.
117  * @return a value of type `Int` built out of `fields`.
118  */
119 template <typename Int>
120 Int ToInt(std::vector<BitField> fields) {
121  Int val = 0;
122  for (auto field : fields) {
123  // Due to the way that gtest ASSERT_* works, and the fact that this must be
124  // a function (since we use function overloading), these cannot be ASSERTs,
125  // and must be EXPECTs.
126  EXPECT_LE(field.offset, sizeof(Int) * 8);
127  val |= static_cast<Int>(field.value << field.offset);
128  }
129  return val;
130 }
131 } // namespace mock_mmio
132 
133 #endif // OPENTITAN_SW_DEVICE_LIB_BASE_MOCK_MMIO_TEST_UTILS_H_