/* * 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 #include #include #include #include #include using namespace prjxray::xilinx; constexpr uint32_t kType1NOP = prjxray::bit_field_set(0, 15, 13, 0x1); extern const uint32_t MakeType1(const int opcode, const int address, const int word_count); extern const std::vector MakeType2(const int opcode, const int address, const int word_count); void dump_packets(BitstreamWriter 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>>& packets) { // InitWithWords doesn't like type 0 /* static std::vector words{0x00000000}; absl::Span word_span(words); auto packet = ConfigurationPacket::InitWithWords(word_span); packets.push_back(*(packet.second)); */ static std::vector words{}; absl::Span word_span(words); // CRC is config value 0 packets.emplace_back(new ConfigurationPacket( 0, ConfigurationPacket::NOP, Spartan6::ConfRegType::CRC, word_span)); } void AddType1( std::vector>>& packets) { static std::vector words{MakeType1(0x2, 0x3, 2), 0xAA, 0xBB}; absl::Span word_span(words); auto packet = ConfigurationPacket::InitWithWords( word_span); packets.emplace_back( new ConfigurationPacket(*(packet.second))); } // Empty void AddType1E( std::vector>>& packets) { static std::vector words{MakeType1(0x2, 0x3, 0)}; absl::Span word_span(words); auto packet = ConfigurationPacket::InitWithWords( word_span); packets.emplace_back( new ConfigurationPacket(*(packet.second))); } void AddType2(Spartan6::ConfigurationPackage& packets) { // Type 2 packet with data { static std::vector words; words = MakeType2(0x02, 0x3, 12); std::vector 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 word_span(words); auto packet = ConfigurationPacket::InitWithWords( word_span); packets.emplace_back( new ConfigurationPacket( *(packet.second))); } } // Empty packets should produce just the header TEST(BitstreamWriterTest, WriteHeader) { std::vector>> packets; BitstreamWriter writer(packets); std::vector words(writer.begin(), writer.end()); // Per UG380 pg 78: Bus Width Auto Detection std::vector 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>> packets; AddType0(packets); BitstreamWriter writer(packets); // dump_packets(writer, false); std::vector words(writer.begin(), writer.end()); std::vector 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 writer(packets); // dump_packets(writer, false); std::vector words(writer.begin(), writer.end()); std::vector 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 writer(packets); // dump_packets(writer, false); std::vector words(writer.begin(), writer.end()); std::vector 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 writer(packets); // dump_packets(writer, false); std::vector words(writer.begin(), writer.end()); std::vector 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); }