mirror of https://github.com/openXC7/prjxray.git
184 lines
6.1 KiB
C++
184 lines
6.1 KiB
C++
#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);
|
|
}
|