| /* |
| * 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 <gtest/gtest.h> |
| #include <prjxray/xilinx/architectures.h> |
| #include <prjxray/xilinx/bitstream_reader.h> |
| #include <prjxray/xilinx/bitstream_writer.h> |
| |
| #include <prjxray/bit_ops.h> |
| |
| using namespace prjxray::xilinx; |
| |
| constexpr uint32_t kType1NOP = prjxray::bit_field_set<uint32_t>(0, 15, 13, 0x1); |
| |
| extern const uint32_t MakeType1(const int opcode, |
| const int address, |
| const int word_count); |
| |
| extern const std::vector<uint32_t> MakeType2(const int opcode, |
| const int address, |
| const int word_count); |
| |
| void dump_packets(BitstreamWriter<Spartan6> writer, bool nl = true) { |
| int i = 0; |
| // for (uint32_t x : itr) { |
| for (auto itr = writer.begin(); itr != writer.end(); ++itr) { |
| if (nl) { |
| printf("% 3d: 0x0%08X\n", i, *itr); |
| } else { |
| printf("0x0%08X, ", *itr); |
| } |
| fflush(stdout); |
| ++i; |
| } |
| if (!nl) { |
| printf("\n"); |
| } |
| } |
| |
| // Special all 0's |
| void AddType0( |
| std::vector<std::unique_ptr<ConfigurationPacket<Spartan6::ConfRegType>>>& |
| packets) { |
| // InitWithWords doesn't like type 0 |
| /* |
| static std::vector<uint32_t> words{0x00000000}; |
| absl::Span<uint32_t> word_span(words); |
| auto packet = |
| ConfigurationPacket<Spartan6::ConfRegType>::InitWithWords(word_span); |
| packets.push_back(*(packet.second)); |
| */ |
| static std::vector<uint32_t> words{}; |
| absl::Span<uint32_t> word_span(words); |
| // CRC is config value 0 |
| packets.emplace_back(new ConfigurationPacket<Spartan6::ConfRegType>( |
| 0, ConfigurationPacket<Spartan6::ConfRegType>::NOP, |
| Spartan6::ConfRegType::CRC, word_span)); |
| } |
| |
| void AddType1( |
| std::vector<std::unique_ptr<ConfigurationPacket<Spartan6::ConfRegType>>>& |
| packets) { |
| static std::vector<uint32_t> words{MakeType1(0x2, 0x3, 2), 0xAA, 0xBB}; |
| absl::Span<uint32_t> word_span(words); |
| auto packet = ConfigurationPacket<Spartan6::ConfRegType>::InitWithWords( |
| word_span); |
| packets.emplace_back( |
| new ConfigurationPacket<Spartan6::ConfRegType>(*(packet.second))); |
| } |
| |
| // Empty |
| void AddType1E( |
| std::vector<std::unique_ptr<ConfigurationPacket<Spartan6::ConfRegType>>>& |
| packets) { |
| static std::vector<uint32_t> words{MakeType1(0x2, 0x3, 0)}; |
| absl::Span<uint32_t> word_span(words); |
| auto packet = ConfigurationPacket<Spartan6::ConfRegType>::InitWithWords( |
| word_span); |
| packets.emplace_back( |
| new ConfigurationPacket<Spartan6::ConfRegType>(*(packet.second))); |
| } |
| |
| void AddType2(Spartan6::ConfigurationPackage& packets) { |
| // Type 2 packet with data |
| { |
| static std::vector<uint32_t> words; |
| words = MakeType2(0x02, 0x3, 12); |
| std::vector<uint32_t> payload{1, 2, 3, 4, 5, 6, |
| 7, 8, 9, 10, 11, 12}; |
| words.insert(words.end(), payload.begin(), payload.end()); |
| std::cout << words.size(); |
| absl::Span<uint32_t> word_span(words); |
| auto packet = |
| ConfigurationPacket<Spartan6::ConfRegType>::InitWithWords( |
| word_span); |
| packets.emplace_back( |
| new ConfigurationPacket<Spartan6::ConfRegType>( |
| *(packet.second))); |
| } |
| } |
| |
| // Empty packets should produce just the header |
| TEST(BitstreamWriterTest, WriteHeader) { |
| std::vector<std::unique_ptr<ConfigurationPacket<Spartan6::ConfRegType>>> |
| packets; |
| |
| BitstreamWriter<Spartan6> writer(packets); |
| std::vector<uint32_t> words(writer.begin(), writer.end()); |
| |
| // Per UG380 pg 78: Bus Width Auto Detection |
| std::vector<uint32_t> ref_header{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
| 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
| 0xAA99, 0x5566}; |
| EXPECT_EQ(words, ref_header); |
| |
| // dump_packets(writer); |
| } |
| |
| TEST(BitstreamWriterTest, WriteType0) { |
| std::vector<std::unique_ptr<ConfigurationPacket<Spartan6::ConfRegType>>> |
| packets; |
| AddType0(packets); |
| BitstreamWriter<Spartan6> writer(packets); |
| // dump_packets(writer, false); |
| std::vector<uint32_t> words(writer.begin(), writer.end()); |
| std::vector<uint32_t> ref{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
| 0xFFFF, 0xFFFF, 0xFFFF, 0xAA99, 0x5566, |
| // Type 0 |
| 0x0000}; |
| EXPECT_EQ(words, ref); |
| } |
| |
| TEST(BitstreamWriterTest, WriteType1) { |
| Spartan6::ConfigurationPackage packets; |
| AddType1(packets); |
| BitstreamWriter<Spartan6> writer(packets); |
| // dump_packets(writer, false); |
| std::vector<uint32_t> words(writer.begin(), writer.end()); |
| std::vector<uint32_t> ref{// Bus width + sync |
| 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
| 0xFFFF, 0xFFFF, 0xFFFF, 0xAA99, 0x5566, |
| // Type 1 |
| 0x3062, 0x00AA, 0x00BB}; |
| EXPECT_EQ(words, ref); |
| } |
| |
| TEST(BitstreamWriterTest, WriteType2) { |
| Spartan6::ConfigurationPackage packets; |
| AddType2(packets); |
| BitstreamWriter<Spartan6> writer(packets); |
| // dump_packets(writer, false); |
| std::vector<uint32_t> words(writer.begin(), writer.end()); |
| std::vector<uint32_t> ref{ |
| // Bus width + sync |
| 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
| 0xAA99, 0x5566, 0x5060, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, |
| 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C}; |
| EXPECT_EQ(words, ref); |
| } |
| |
| TEST(BitstreamWriterTest, WriteMulti) { |
| Spartan6::ConfigurationPackage packets; |
| AddType1(packets); |
| AddType1E(packets); |
| AddType2(packets); |
| AddType1E(packets); |
| BitstreamWriter<Spartan6> writer(packets); |
| // dump_packets(writer, false); |
| std::vector<uint32_t> words(writer.begin(), writer.end()); |
| std::vector<uint32_t> ref{// Bus width + sync |
| 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
| 0xFFFF, 0xFFFF, 0xFFFF, 0xAA99, 0x5566, |
| // Type1 |
| 0x3062, 0x00AA, 0x00BB, |
| // Type1 |
| 0x3060, |
| // Type 1 + type 2 header |
| 0x5060, 0x0001, 0x0002, 0x0003, 0x0004, |
| 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, |
| 0x000A, 0x000B, 0x000C, |
| // Type 1 |
| 0x3060}; |
| EXPECT_EQ(words, ref); |
| } |