blob: f17ad62f605a6fe23bc463957cb8848be5dabb82 [file] [log] [blame]
/*
* 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/bitstream_reader.h>
#include <prjxray/xilinx/bitstream_writer.h>
#include <prjxray/xilinx/configuration_packet.h>
#include <prjxray/xilinx/configuration_register.h>
#include <prjxray/bit_ops.h>
using namespace prjxray::xilinx;
constexpr uint32_t kType1NOP = prjxray::bit_field_set<uint32_t>(0, 31, 29, 0x1);
constexpr uint32_t MakeType1(const int opcode,
const int address,
const int word_count) {
return prjxray::bit_field_set<uint32_t>(
prjxray::bit_field_set<uint32_t>(
prjxray::bit_field_set<uint32_t>(
prjxray::bit_field_set<uint32_t>(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<uint32_t>(
prjxray::bit_field_set<uint32_t>(
prjxray::bit_field_set<uint32_t>(0x0, 31, 29, 0x2), 28, 27,
opcode),
26, 0, word_count);
}
void dump_packets(BitstreamWriter<Series7> 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<Series7::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<Series7::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<Series7::ConfRegType>(
0, ConfigurationPacket<Series7::ConfRegType>::NOP,
Series7::ConfRegType::CRC, word_span));
}
void AddType1(
std::vector<std::unique_ptr<ConfigurationPacket<Series7::ConfRegType>>>&
packets) {
static std::vector<uint32_t> words{MakeType1(0x2, 0x3, 2), 0xAA, 0xBB};
absl::Span<uint32_t> word_span(words);
auto packet =
ConfigurationPacket<Series7::ConfRegType>::InitWithWords(word_span);
packets.emplace_back(
new ConfigurationPacket<Series7::ConfRegType>(*(packet.second)));
}
// Empty
void AddType1E(
std::vector<std::unique_ptr<ConfigurationPacket<Series7::ConfRegType>>>&
packets) {
static std::vector<uint32_t> words{MakeType1(0x2, 0x3, 0)};
absl::Span<uint32_t> word_span(words);
auto packet =
ConfigurationPacket<Series7::ConfRegType>::InitWithWords(word_span);
packets.emplace_back(
new ConfigurationPacket<Series7::ConfRegType>(*(packet.second)));
}
void AddType2(
std::vector<std::unique_ptr<ConfigurationPacket<Series7::ConfRegType>>>&
packets) {
// Type 1 packet with address
// Without this InitWithWords will fail on type 2
ConfigurationPacket<Series7::ConfRegType>* packet1;
{
static std::vector<uint32_t> words{MakeType1(0x2, 0x3, 0)};
absl::Span<uint32_t> word_span(words);
auto packet1_pair =
ConfigurationPacket<Series7::ConfRegType>::InitWithWords(
word_span);
packets.emplace_back(
new ConfigurationPacket<Series7::ConfRegType>(
*(packet1_pair.second)));
packet1 = packets[0].get();
}
// Type 2 packet with data
{
static std::vector<uint32_t> words{
MakeType2(0x01, 12), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
absl::Span<uint32_t> word_span(words);
auto packet =
ConfigurationPacket<Series7::ConfRegType>::InitWithWords(
word_span, packet1);
packets.emplace_back(
new ConfigurationPacket<Series7::ConfRegType>(
*(packet.second)));
}
}
// Empty packets should produce just the header
TEST(BitstreamWriterTest, WriteHeader) {
std::vector<std::unique_ptr<ConfigurationPacket<Series7::ConfRegType>>>
packets;
BitstreamWriter<Series7> writer(packets);
std::vector<uint32_t> words(writer.begin(), writer.end());
// Per UG470 pg 80: Bus Width Auto Detection
std::vector<uint32_t> ref_header{
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000000BB, 0x11220044,
0xFFFFFFFF, 0xFFFFFFFF, 0xAA995566};
EXPECT_EQ(words, ref_header);
// dump_packets(writer);
}
TEST(BitstreamWriterTest, WriteType0) {
std::vector<std::unique_ptr<ConfigurationPacket<Series7::ConfRegType>>>
packets;
AddType0(packets);
BitstreamWriter<Series7> writer(packets);
// dump_packets(writer, false);
std::vector<uint32_t> words(writer.begin(), writer.end());
std::vector<uint32_t> ref{
// Bus width + sync
0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF,
0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0000000BB, 0x011220044,
0x0FFFFFFFF, 0x0FFFFFFFF, 0x0AA995566,
// Type 0
0x00000000};
EXPECT_EQ(words, ref);
}
TEST(BitstreamWriterTest, WriteType1) {
std::vector<std::unique_ptr<ConfigurationPacket<Series7::ConfRegType>>>
packets;
AddType1(packets);
BitstreamWriter<Series7> writer(packets);
// dump_packets(writer, false);
std::vector<uint32_t> words(writer.begin(), writer.end());
std::vector<uint32_t> ref{
// Bus width + sync
0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF,
0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0000000BB, 0x011220044,
0x0FFFFFFFF, 0x0FFFFFFFF, 0x0AA995566,
// Type 1
0x030006002, 0x0000000AA, 0x0000000BB};
EXPECT_EQ(words, ref);
}
TEST(BitstreamWriterTest, WriteType2) {
std::vector<std::unique_ptr<ConfigurationPacket<Series7::ConfRegType>>>
packets;
AddType2(packets);
BitstreamWriter<Series7> writer(packets);
// dump_packets(writer, false);
std::vector<uint32_t> words(writer.begin(), writer.end());
std::vector<uint32_t> ref{
// Bus width + sync
0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF,
0x0FFFFFFFF, 0x0FFFFFFFF, 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<std::unique_ptr<ConfigurationPacket<Series7::ConfRegType>>>
packets;
AddType1(packets);
AddType1E(packets);
AddType2(packets);
AddType1E(packets);
BitstreamWriter<Series7> writer(packets);
// dump_packets(writer, false);
std::vector<uint32_t> words(writer.begin(), writer.end());
std::vector<uint32_t> ref{
// Bus width + sync
0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF, 0x0FFFFFFFF,
0x0FFFFFFFF, 0x0FFFFFFFF, 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);
}