|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  |  | 
|  | #include "sw/device/lib/base/mock_mmio.h" | 
|  |  | 
|  | #include "gtest/gtest.h" | 
|  | #include "sw/device/lib/base/mmio.h" | 
|  |  | 
|  | namespace { | 
|  | using ::mock_mmio::LeInt; | 
|  | using ::mock_mmio::MmioTest; | 
|  | using ::testing::Test; | 
|  |  | 
|  | /** | 
|  | * Exercises the register |dev| by reading a value at offset 0x0, | 
|  | * writing its complement to 0x4, and then writing it byte by byte | 
|  | * back over itself, from MSB to LSB. | 
|  | */ | 
|  | uint32_t WriteTwice(mmio_region_t dev) { | 
|  | auto value = mmio_region_read32(dev, 0x0); | 
|  | mmio_region_write32(dev, 0x4, ~value); | 
|  | mmio_region_write8(dev, 0x12, (value >> 24) & 0xff); | 
|  | mmio_region_write8(dev, 0x8, (value >> 16) & 0xff); | 
|  | mmio_region_write8(dev, 0x4, (value >> 8) & 0xff); | 
|  | mmio_region_write8(dev, 0x0, value & 0xff); | 
|  | return value; | 
|  | } | 
|  |  | 
|  | class MockMmioTest : public Test, public MmioTest {}; | 
|  |  | 
|  | TEST_F(MockMmioTest, WriteTwice) { | 
|  | EXPECT_READ32(0x0, 0xdeadbeef); | 
|  | EXPECT_WRITE32(0x4, 0x21524110); | 
|  | EXPECT_WRITE8(0x12, 0xde); | 
|  | EXPECT_WRITE8(0x8, 0xad); | 
|  | EXPECT_WRITE8(0x4, 0xbe); | 
|  | EXPECT_WRITE8(0x0, 0xef); | 
|  |  | 
|  | EXPECT_EQ(WriteTwice(dev().region()), 0xdeadbeef); | 
|  | } | 
|  |  | 
|  | // This test mostly exists to guard against |0x0| being interpreted as a NULL | 
|  | // pointer literal. C++ overloading is unpredictable in choosing between T* and | 
|  | // int here. | 
|  | TEST_F(MockMmioTest, ExpectReadZero) { | 
|  | EXPECT_READ8(0x0, 0x0); | 
|  | EXPECT_EQ(mmio_region_read8(dev().region(), 0x0), 0x0); | 
|  | } | 
|  |  | 
|  | TEST_F(MockMmioTest, ExpectWithString) { | 
|  | EXPECT_READ32(0xc, LeInt("*\0\0*")); | 
|  | EXPECT_EQ(mmio_region_read32(dev().region(), 0xc), 0x2a00002a); | 
|  |  | 
|  | EXPECT_WRITE32(0x12, LeInt("abcd")); | 
|  | mmio_region_write32(dev().region(), 0x12, 0x64636261); | 
|  | } | 
|  |  | 
|  | TEST_F(MockMmioTest, ExpectWithBits) { | 
|  | EXPECT_READ8(0xc, {{0x0, false}, {0x1, true}, {0x3, true}}); | 
|  | EXPECT_EQ(mmio_region_read8(dev().region(), 0xc), 0b1010); | 
|  |  | 
|  | EXPECT_WRITE32(0x12, {{0x0, 0xfe}, {0x8, 0xca}}); | 
|  | mmio_region_write32(dev().region(), 0x12, 0xcafe); | 
|  | } | 
|  |  | 
|  | TEST_F(MockMmioTest, ExpectMask) { | 
|  | EXPECT_MASK32(0x8, { | 
|  | {0x0, 0xfff, 0xabc}, | 
|  | {0x10, 0x1, 0x0}, | 
|  | }); | 
|  |  | 
|  | auto value = mmio_region_read32(dev().region(), 0x8); | 
|  | // Set the first three nybbles. | 
|  | value &= ~0xfff; | 
|  | value |= 0xabc; | 
|  | // Clear the 16th bit. | 
|  | value &= ~(1 << 0x10); | 
|  | mmio_region_write32(dev().region(), 0x8, value); | 
|  | } | 
|  | }  // namespace |