blob: f8fcb3387b91029d986d00cdd7b683afff3cf566 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef OPENTITAN_SW_DEVICE_LIB_BASE_MOCK_MMIO_TEST_UTILS_H_
#define OPENTITAN_SW_DEVICE_LIB_BASE_MOCK_MMIO_TEST_UTILS_H_
#include <initializer_list>
#include <memory>
#include <random>
#include <stdint.h>
#include <string.h>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace mock_mmio {
/**
* Represents a single bit field in an integer, useable with EXPECT_* macros
* defined in this file.
*
* An integer can be expressed as a list of BitField values, and can be more
* convenient to use than 0b or 0x literals in some cases. For example, the
* integer 0b0000'0000'1100'0101 could be expressed as
* {{0x0, 1}, {0x2, 1}, {0x4, 12}}
* This form makes it clearer to the reader that 0x0, 0x2, and 04 are indices
* to bitfields, which are set to particular values.
*
* In practice, this might use generated register constants, and look like
* {{FIELD_FOO_OFFSET, 1}, {FIELD_BAR_OFFSET, 1}, {FIELD_BAZ_OFFSET, 12}}
*
* This type does not specify the lengths of bitfields; MaskedBitField should be
* used for that, instead.
*/
struct BitField {
uintptr_t offset;
uintptr_t value;
};
/**
* Represents a single bit field in an integer, similar to BitField. It can be
* used in most places that need a BitField, as well as in `EXPECT_MASK` macros.
*
* Like with BitFields, we can express the integer 0b0000'0000'1100'0101 as a
* list of BitFieldMasks:
* {{0x0, 0x1, 1}, {0x1, 0x1, 0}, {0x2, 0x1, 1}, {0x3, 0x1, 0},
* {0x4, 0xff, 12}}
*
* In addition to showing how the integer is broken up, it also expresses
* the lengths of fields, so it is clear that 0x0 and 0x2 are one-bit fields.
* This also allows us to formally express that the fields 0x1 and 0x3 are
* *unset*.
*
* In practice, this might use generated register constants, and look like
* {{FIELD_FOO_OFFSET, FIELD_FOO_MASK, 1}, ...}
*/
struct MaskedBitField {
uintptr_t offset;
uintptr_t mask;
uintptr_t value;
};
/**
* Implicit conversion guard around `char *`. See `LeInt()`.
*/
struct LittleEndianBytes {
const char *bytes;
};
/**
* Converts the argument into an unsigned integer of type `Int`.
*
* This overload is simply the identity on integers, and allows integers to be
* converted into themselves. This enables the basic EXPECT_* macros:
* EXPECT_READ32(offset, 0xcafecafe);
*
* @param val an integer.
* @return the value `val`.
*/
template <typename Int>
Int ToInt(Int val) {
return val;
}
/**
* Converts the argument into an unsinged integer of type `Int`.
*
* This overload assumes that `str` is a valid pointer to a buffer of at least
* `sizeof(Int)` bytes, which are memcpy'd out as an `Int`. This enables
* memcpy-like EXPECT_* macros:
* EXPECT_READ32(offset, LeInt("rv32"));
* EXPECT_READ32(offset, LeInt("imc\0"));
*
* @param str a pointer to a valid buffer of length at least `sizeof(Int)`.
* @return a value of type `Int` memcpy'd out of `str`.
*/
template <typename Int>
Int ToInt(LittleEndianBytes str) {
Int val;
memcpy(&val, str.bytes, sizeof(Int));
return val;
}
/**
* Converts the argument into an unsigned integer of type `Int`.
*
* This overload performs the shifts and ors described by `fields`. See
* `BitField`'s documentation for details one what this means. This overload
* enables bitfield EXPECT_* macros:
* EXPECT_READ32(offset, {{A_OFFSET, 0x55}, {B_OFFSET, 0xaa}});
* EXPECT_READ32(offset, fields);
* where `fields` is an `std::vector<BitField>`.
*
* @param fields a list of bit field entries.
* @return a value of type `Int` built out of `fields`.
*/
template <typename Int>
Int ToInt(std::vector<BitField> fields) {
Int val = 0;
for (auto field : fields) {
// Due to the way that gtest ASSERT_* works, and the fact that this must be
// a function (since we use function overloading), these cannot be ASSERTs,
// and must be EXPECTs.
EXPECT_LE(field.offset, sizeof(Int) * 8);
val |= static_cast<Int>(field.value << field.offset);
}
return val;
}
} // namespace mock_mmio
#endif // OPENTITAN_SW_DEVICE_LIB_BASE_MOCK_MMIO_TEST_UTILS_H_