#include #include #include #include #include #include #include namespace xc7series = prjxray::xilinx::xc7series; constexpr uint32_t kType1NOP = prjxray::bit_field_set(0, 31, 29, 0x1); constexpr uint32_t MakeType1(const int opcode, const int address, const int word_count) { return prjxray::bit_field_set( prjxray::bit_field_set( prjxray::bit_field_set( prjxray::bit_field_set(0x0, 31, 29, 0x1), 28, 27, opcode), 26, 13, address), 10, 0, word_count); } constexpr uint32_t MakeType2(const int opcode, const int word_count) { return prjxray::bit_field_set( prjxray::bit_field_set( prjxray::bit_field_set(0x0, 31, 29, 0x2), 28, 27, opcode), 26, 0, word_count); } void dump_packets(xc7series::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 = xc7series::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 xc7series::ConfigurationPacket( 0, xc7series::ConfigurationPacket::NOP, xc7series::ConfigurationRegister::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 = xc7series::ConfigurationPacket::InitWithWords(word_span); packets.emplace_back( new xc7series::ConfigurationPacket(*(packet.second))); } // Empty void AddType1E( std::vector>& packets) { static std::vector words{MakeType1(0x2, 0x3, 0)}; absl::Span word_span(words); auto packet = xc7series::ConfigurationPacket::InitWithWords(word_span); packets.emplace_back( new xc7series::ConfigurationPacket(*(packet.second))); } void AddType2( std::vector>& packets) { // Type 1 packet with address // Without this InitWithWords will fail on type 2 xc7series::ConfigurationPacket* packet1; { static std::vector words{MakeType1(0x2, 0x3, 0)}; absl::Span word_span(words); auto packet1_pair = xc7series::ConfigurationPacket::InitWithWords(word_span); packets.emplace_back( new xc7series::ConfigurationPacket(*(packet1_pair.second))); packet1 = packets[0].get(); } // Type 2 packet with data { static std::vector words{ MakeType2(0x01, 12), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; absl::Span word_span(words); auto packet = xc7series::ConfigurationPacket::InitWithWords( word_span, packet1); packets.emplace_back( new xc7series::ConfigurationPacket(*(packet.second))); } } // Empty packets should produce just the header TEST(BitstreamWriterTest, WriteHeader) { std::vector> packets; xc7series::BitstreamWriter writer(packets); std::vector words(writer.begin(), writer.end()); // Per UG470 pg 80: Bus Width Auto Detection std::vector ref_header{0xFFFFFFFF, 0x000000BB, 0x11220044, 0xFFFFFFFF, 0xFFFFFFFF, 0xAA995566}; EXPECT_EQ(words, ref_header); // dump_packets(writer); } TEST(BitstreamWriterTest, WriteType0) { std::vector> packets; AddType0(packets); xc7series::BitstreamWriter writer(packets); // dump_packets(writer, false); std::vector words(writer.begin(), writer.end()); std::vector ref{// Bus width + sync 0x0FFFFFFFF, 0x0000000BB, 0x011220044, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0AA995566, // Type 0 0x00000000}; EXPECT_EQ(words, ref); } TEST(BitstreamWriterTest, WriteType1) { std::vector> packets; AddType1(packets); xc7series::BitstreamWriter writer(packets); // dump_packets(writer, false); std::vector words(writer.begin(), writer.end()); std::vector ref{// Bus width + sync 0x0FFFFFFFF, 0x0000000BB, 0x011220044, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0AA995566, // Type 1 0x030006002, 0x0000000AA, 0x0000000BB}; EXPECT_EQ(words, ref); } TEST(BitstreamWriterTest, WriteType2) { std::vector> packets; AddType2(packets); xc7series::BitstreamWriter writer(packets); // dump_packets(writer, false); std::vector words(writer.begin(), writer.end()); std::vector ref{ // Bus width + sync 0x0FFFFFFFF, 0x0000000BB, 0x011220044, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0AA995566, // Type 1 + type 2 header 0x030006000, 0x04800000C, 0x000000001, 0x000000002, 0x000000003, 0x000000004, 0x000000005, 0x000000006, 0x000000007, 0x000000008, 0x000000009, 0x00000000A, 0x00000000B, 0x00000000C}; EXPECT_EQ(words, ref); } TEST(BitstreamWriterTest, WriteMulti) { std::vector> packets; AddType1(packets); AddType1E(packets); AddType2(packets); AddType1E(packets); xc7series::BitstreamWriter writer(packets); // dump_packets(writer, false); std::vector words(writer.begin(), writer.end()); std::vector ref{ // Bus width + sync 0x0FFFFFFFF, 0x0000000BB, 0x011220044, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0AA995566, // Type1 0x030006002, 0x0000000AA, 0x0000000BB, // Type1 0x030006000, // Type 1 + type 2 header 0x030006000, 0x04800000C, 0x000000001, 0x000000002, 0x000000003, 0x000000004, 0x000000005, 0x000000006, 0x000000007, 0x000000008, 0x000000009, 0x00000000A, 0x00000000B, 0x00000000C, // Type 1 0x030006000}; EXPECT_EQ(words, ref); }