blob: b7e7f8309a760ce0ab2f9872be53760df6043e12 [file] [log] [blame]
// 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