| /* |
| * Copyright (C) 2017-2020 The Project X-Ray Authors. |
| * |
| * Use of this source code is governed by a ISC-style |
| * license that can be found in the LICENSE file or at |
| * https://opensource.org/licenses/ISC |
| * |
| * SPDX-License-Identifier: ISC |
| */ |
| #include <array> |
| |
| #include <absl/types/span.h> |
| #include <gtest/gtest.h> |
| #include <prjxray/xilinx/bitstream_reader.h> |
| #include <prjxray/xilinx/configuration_packet.h> |
| #include <prjxray/xilinx/configuration_register.h> |
| |
| #include <prjxray/big_endian_span.h> |
| |
| using namespace prjxray::xilinx; |
| TEST(BitstreamReaderTest, InitWithEmptyBytesReturnsNull) { |
| absl::Span<uint8_t> bitstream; |
| auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream); |
| EXPECT_FALSE(reader); |
| } |
| |
| TEST(BitstreamReaderTest, InitWithOnlySyncReturnsObject) { |
| std::vector<uint8_t> bitstream{0xAA, 0x99, 0x55, 0x66}; |
| absl::Span<std::vector<uint8_t>::value_type> bitstream_span(bitstream); |
| // auto config_packets = |
| // bitstream_span.subspan(bitstream.end() - bitstream.begin()); |
| // auto big_endian_reader = |
| // prjxray::make_big_endian_span<uint16_t>(bitstream_span); |
| // std::vector<uint16_t> words{big_endian_reader.begin(), |
| // big_endian_reader.end()}; |
| |
| // for (auto word: words) { |
| // std::cout << "0x" << std::hex << word << std::endl; |
| //} |
| auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream); |
| EXPECT_TRUE(reader); |
| } |
| |
| TEST(BitstreamReaderTest, InitWithSyncAfterNonWordSizedPaddingReturnsObject) { |
| std::vector<uint8_t> bitstream{0xFF, 0xFE, 0xAA, 0x99, 0x55, 0x66}; |
| auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream); |
| EXPECT_TRUE(reader); |
| } |
| |
| TEST(BitstreamReaderTest, InitWithSyncAfterWordSizedPaddingReturnsObject) { |
| std::vector<uint8_t> bitstream{0xFF, 0xFE, 0xFD, 0xFC, |
| 0xAA, 0x99, 0x55, 0x66}; |
| auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream); |
| EXPECT_TRUE(reader); |
| } |
| |
| TEST(BitstreamReaderTest, ParsesType1Packet) { |
| std::vector<uint8_t> bitstream{ |
| 0xAA, 0x99, 0x55, 0x66, // sync |
| 0x20, 0x00, 0x20, 0x00, // NOP |
| }; |
| auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream); |
| ASSERT_TRUE(reader); |
| ASSERT_NE(reader->begin(), reader->end()); |
| |
| auto first_packet = reader->begin(); |
| EXPECT_EQ(first_packet->opcode(), |
| ConfigurationPacket<Spartan6>::Opcode::NOP); |
| |
| auto second_packet = ++first_packet; |
| EXPECT_EQ(second_packet->opcode(), |
| ConfigurationPacket<Spartan6>::Opcode::NOP); |
| |
| EXPECT_EQ(++second_packet, reader->end()); |
| } |
| |
| TEST(BitstreamReaderTest, ParseType2PacketWithoutType1Fails) { |
| std::vector<uint8_t> bitstream{ |
| 0xAA, 0x99, 0x55, 0x66, // sync |
| 0x40, 0x00, 0x40, 0x00, // Type 2 NOP |
| }; |
| auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream); |
| ASSERT_TRUE(reader); |
| EXPECT_EQ(reader->begin(), reader->end()); |
| } |
| |
| TEST(BitstreamReaderTest, ParsesType2AfterType1Packet) { |
| std::vector<uint8_t> bitstream{ |
| 0xAA, 0x99, // sync |
| 0x55, 0x66, // sync |
| 0x28, 0x80, // Type 1 Read zero bytes from FDRO |
| 0x50, 0x60, // Type 2 Write of 8 16-bit words |
| 0x00, 0x00, // WC1 bits 31:16 |
| 0x00, 0x08, // WC2 bits 15:0 |
| 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, |
| 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, |
| }; |
| std::vector<uint32_t> data_words{0x0102, 0x0304, 0x0506, 0x0708, |
| 0x090A, 0x0B0C, 0x0D0E, 0x0F10}; |
| |
| auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream); |
| ASSERT_TRUE(reader); |
| ASSERT_NE(reader->begin(), reader->end()); |
| |
| auto first_packet = reader->begin(); |
| EXPECT_EQ(first_packet->opcode(), |
| ConfigurationPacket<Spartan6>::Opcode::Read); |
| EXPECT_EQ(first_packet->address(), Spartan6::ConfRegType::FDRO); |
| EXPECT_EQ(first_packet->data(), absl::Span<uint32_t>()); |
| |
| auto third_packet = ++first_packet; |
| ASSERT_NE(third_packet, reader->end()); |
| EXPECT_EQ(third_packet->opcode(), |
| ConfigurationPacket<Spartan6>::Opcode::Write); |
| EXPECT_EQ(third_packet->address(), Spartan6::ConfRegType::FDRI); |
| (third_packet->data(), absl::Span<uint32_t>(data_words)); |
| EXPECT_EQ(++first_packet, reader->end()); |
| } |