mirror of https://github.com/openXC7/prjxray.git
bitstream_tools: Add unit tests for Spartan6
Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
This commit is contained in:
parent
b35bf3fe11
commit
58c26369de
|
|
@ -70,4 +70,22 @@ if (PRJXRAY_BUILD_TESTING)
|
|||
add_test(NAME xilinx_xc7series_test
|
||||
COMMAND xilinx_xc7series_test
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test_data)
|
||||
|
||||
add_executable(xilinx_spartan6_test
|
||||
xilinx/tests/spartan6/bitstream_reader_test.cc
|
||||
xilinx/tests/spartan6/bitstream_writer_test.cc
|
||||
xilinx/tests/spartan6/block_type_test.cc
|
||||
xilinx/tests/spartan6/configuration_bus_test.cc
|
||||
xilinx/tests/spartan6/configuration_column_test.cc
|
||||
xilinx/tests/spartan6/configuration_test.cc
|
||||
xilinx/tests/spartan6/configuration_packet_test.cc
|
||||
xilinx/tests/spartan6/frame_address_test.cc
|
||||
xilinx/tests/spartan6/global_clock_region_test.cc
|
||||
xilinx/tests/spartan6/part_test.cc
|
||||
xilinx/tests/spartan6/row_test.cc
|
||||
xilinx/tests/spartan6/frames_test.cc)
|
||||
target_link_libraries(xilinx_spartan6_test libprjxray gtest_main)
|
||||
add_test(NAME xilinx_spartan6_test
|
||||
COMMAND xilinx_spartan6_test
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test_data)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
#include <array>
|
||||
|
||||
#include <absl/types/span.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <prjxray/xilinx/bitstream_reader.h>
|
||||
#include <prjxray/xilinx/configuration_packet.h>
|
||||
#include <prjxray/xilinx/configuration_register.h>
|
||||
|
||||
#include <prjxray/big_endian_span.h>
|
||||
|
||||
using namespace prjxray::xilinx;
|
||||
TEST(BitstreamReaderTest, InitWithEmptyBytesReturnsNull) {
|
||||
absl::Span<uint8_t> bitstream;
|
||||
auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream);
|
||||
EXPECT_FALSE(reader);
|
||||
}
|
||||
|
||||
TEST(BitstreamReaderTest, InitWithOnlySyncReturnsObject) {
|
||||
std::vector<uint8_t> bitstream{0xAA, 0x99, 0x55, 0x66};
|
||||
absl::Span<std::vector<uint8_t>::value_type> bitstream_span(bitstream);
|
||||
// auto config_packets =
|
||||
// bitstream_span.subspan(bitstream.end() - bitstream.begin());
|
||||
// auto big_endian_reader =
|
||||
// prjxray::make_big_endian_span<uint16_t>(bitstream_span);
|
||||
// std::vector<uint16_t> words{big_endian_reader.begin(),
|
||||
// big_endian_reader.end()};
|
||||
|
||||
// for (auto word: words) {
|
||||
// std::cout << "0x" << std::hex << word << std::endl;
|
||||
//}
|
||||
auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream);
|
||||
EXPECT_TRUE(reader);
|
||||
}
|
||||
|
||||
TEST(BitstreamReaderTest, InitWithSyncAfterNonWordSizedPaddingReturnsObject) {
|
||||
std::vector<uint8_t> bitstream{0xFF, 0xFE, 0xAA, 0x99, 0x55, 0x66};
|
||||
auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream);
|
||||
EXPECT_TRUE(reader);
|
||||
}
|
||||
|
||||
TEST(BitstreamReaderTest, InitWithSyncAfterWordSizedPaddingReturnsObject) {
|
||||
std::vector<uint8_t> bitstream{0xFF, 0xFE, 0xFD, 0xFC,
|
||||
0xAA, 0x99, 0x55, 0x66};
|
||||
auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream);
|
||||
EXPECT_TRUE(reader);
|
||||
}
|
||||
|
||||
TEST(BitstreamReaderTest, ParsesType1Packet) {
|
||||
std::vector<uint8_t> bitstream{
|
||||
0xAA, 0x99, 0x55, 0x66, // sync
|
||||
0x20, 0x00, 0x20, 0x00, // NOP
|
||||
};
|
||||
auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream);
|
||||
ASSERT_TRUE(reader);
|
||||
ASSERT_NE(reader->begin(), reader->end());
|
||||
|
||||
auto first_packet = reader->begin();
|
||||
EXPECT_EQ(first_packet->opcode(),
|
||||
ConfigurationPacket<Spartan6>::Opcode::NOP);
|
||||
|
||||
auto second_packet = ++first_packet;
|
||||
EXPECT_EQ(second_packet->opcode(),
|
||||
ConfigurationPacket<Spartan6>::Opcode::NOP);
|
||||
|
||||
EXPECT_EQ(++second_packet, reader->end());
|
||||
}
|
||||
|
||||
TEST(BitstreamReaderTest, ParseType2PacketWithoutType1Fails) {
|
||||
std::vector<uint8_t> bitstream{
|
||||
0xAA, 0x99, 0x55, 0x66, // sync
|
||||
0x40, 0x00, 0x40, 0x00, // Type 2 NOP
|
||||
};
|
||||
auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream);
|
||||
ASSERT_TRUE(reader);
|
||||
EXPECT_EQ(reader->begin(), reader->end());
|
||||
}
|
||||
|
||||
TEST(BitstreamReaderTest, ParsesType2AfterType1Packet) {
|
||||
std::vector<uint8_t> bitstream{
|
||||
0xAA, 0x99, // sync
|
||||
0x55, 0x66, // sync
|
||||
0x28, 0x80, // Type 1 Read zero bytes from FDRO
|
||||
0x50, 0x60, // Type 2 Write of 8 16-bit words
|
||||
0x00, 0x00, // WC1 bits 31:16
|
||||
0x00, 0x08, // WC2 bits 15:0
|
||||
0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
|
||||
0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10,
|
||||
};
|
||||
std::vector<uint32_t> data_words{0x0102, 0x0304, 0x0506, 0x0708,
|
||||
0x090A, 0x0B0C, 0x0D0E, 0x0F10};
|
||||
|
||||
auto reader = BitstreamReader<Spartan6>::InitWithBytes(bitstream);
|
||||
ASSERT_TRUE(reader);
|
||||
ASSERT_NE(reader->begin(), reader->end());
|
||||
|
||||
auto first_packet = reader->begin();
|
||||
EXPECT_EQ(first_packet->opcode(),
|
||||
ConfigurationPacket<Spartan6>::Opcode::Read);
|
||||
EXPECT_EQ(first_packet->address(), Spartan6::ConfRegType::FDRO);
|
||||
EXPECT_EQ(first_packet->data(), absl::Span<uint32_t>());
|
||||
|
||||
auto third_packet = ++first_packet;
|
||||
ASSERT_NE(third_packet, reader->end());
|
||||
EXPECT_EQ(third_packet->opcode(),
|
||||
ConfigurationPacket<Spartan6>::Opcode::Write);
|
||||
EXPECT_EQ(third_packet->address(), Spartan6::ConfRegType::FDRI);
|
||||
(third_packet->data(), absl::Span<uint32_t>(data_words));
|
||||
EXPECT_EQ(++first_packet, reader->end());
|
||||
}
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include <prjxray/xilinx/spartan6/block_type.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace prjxray::xilinx;
|
||||
|
||||
TEST(BlockTypeTest, YamlEncode) {
|
||||
YAML::Node node;
|
||||
node.push_back(spartan6::BlockType::CLB_IOI_CLK);
|
||||
node.push_back(spartan6::BlockType::BLOCK_RAM);
|
||||
node.push_back(spartan6::BlockType::IOB);
|
||||
|
||||
EXPECT_EQ(node[0].as<std::string>(), "CLB_IOI_CLK");
|
||||
EXPECT_EQ(node[1].as<std::string>(), "BLOCK_RAM");
|
||||
EXPECT_EQ(node[2].as<std::string>(), "IOB");
|
||||
}
|
||||
|
||||
TEST(BlockTypeTest, YamlDecode) {
|
||||
YAML::Node node;
|
||||
node.push_back("IOB");
|
||||
node.push_back("BLOCK_RAM");
|
||||
node.push_back("CLB_IOI_CLK");
|
||||
|
||||
EXPECT_EQ(node[0].as<spartan6::BlockType>(), spartan6::BlockType::IOB);
|
||||
EXPECT_EQ(node[1].as<spartan6::BlockType>(),
|
||||
spartan6::BlockType::BLOCK_RAM);
|
||||
EXPECT_EQ(node[2].as<spartan6::BlockType>(),
|
||||
spartan6::BlockType::CLB_IOI_CLK);
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#include <prjxray/xilinx/spartan6/configuration_bus.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace prjxray::xilinx;
|
||||
|
||||
TEST(ConfigurationBusTest, IsValidFrameAddress) {
|
||||
std::vector<spartan6::FrameAddress> addresses;
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 1, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 1, 1));
|
||||
|
||||
spartan6::ConfigurationBus bus(addresses.begin(), addresses.end());
|
||||
|
||||
EXPECT_TRUE(bus.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0)));
|
||||
EXPECT_TRUE(bus.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 1, 1)));
|
||||
|
||||
EXPECT_FALSE(bus.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2)));
|
||||
}
|
||||
|
||||
TEST(ConfigurationBusTest, GetNextFrameAddressYieldNextAddressInBus) {
|
||||
std::vector<spartan6::FrameAddress> addresses;
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 1, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 1, 1));
|
||||
|
||||
spartan6::ConfigurationBus bus(addresses.begin(), addresses.end());
|
||||
|
||||
auto next_address = bus.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(*next_address, spartan6::FrameAddress(
|
||||
spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
|
||||
next_address = bus.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(*next_address, spartan6::FrameAddress(
|
||||
spartan6::BlockType::BLOCK_RAM, 0, 1, 0));
|
||||
}
|
||||
|
||||
TEST(ConfigurationBusTest, GetNextFrameAddressYieldNothingAtEndOfBus) {
|
||||
std::vector<spartan6::FrameAddress> addresses;
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 1, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 1, 1));
|
||||
|
||||
spartan6::ConfigurationBus bus(addresses.begin(), addresses.end());
|
||||
|
||||
EXPECT_FALSE(bus.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 1, 1)));
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#include <prjxray/xilinx/spartan6/configuration_column.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <prjxray/xilinx/spartan6/block_type.h>
|
||||
#include <prjxray/xilinx/spartan6/frame_address.h>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
using namespace prjxray::xilinx;
|
||||
|
||||
TEST(ConfigurationColumnTest, IsValidFrameAddress) {
|
||||
spartan6::ConfigurationColumn column(10);
|
||||
|
||||
// Inside this column.
|
||||
EXPECT_TRUE(column.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 2, 3)));
|
||||
// Past this column's frame width.
|
||||
EXPECT_FALSE(column.IsValidFrameAddress(spartan6::FrameAddress(
|
||||
spartan6::BlockType::CLB_IOI_CLK, 1, 2, 10)));
|
||||
}
|
||||
|
||||
TEST(ConfigurationColumnTest, GetNextFrameAddressYieldNextAddressInColumn) {
|
||||
spartan6::ConfigurationColumn column(10);
|
||||
|
||||
auto next_address = column.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 2, 3));
|
||||
EXPECT_TRUE(next_address);
|
||||
EXPECT_EQ(
|
||||
*next_address,
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 2, 4));
|
||||
}
|
||||
|
||||
TEST(ConfigurationColumnTest, GetNextFrameAddressYieldNothingAtEndOfColumn) {
|
||||
spartan6::ConfigurationColumn column(10);
|
||||
|
||||
EXPECT_FALSE(column.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 2, 9)));
|
||||
}
|
||||
|
||||
TEST(ConfigurationColumnTest, GetNextFrameAddressYieldNothingOutsideColumn) {
|
||||
spartan6::ConfigurationColumn column(10);
|
||||
|
||||
// Just past last frame in column.
|
||||
EXPECT_FALSE(column.GetNextFrameAddress(spartan6::FrameAddress(
|
||||
spartan6::BlockType::CLB_IOI_CLK, 1, 2, 10)));
|
||||
}
|
||||
|
||||
TEST(ConfigurationColumnTest, YamlEncodeTest) {
|
||||
spartan6::ConfigurationColumn column(10);
|
||||
|
||||
YAML::Node node(column);
|
||||
EXPECT_TRUE(node["frame_count"]);
|
||||
EXPECT_EQ(node["frame_count"].as<int>(), 10);
|
||||
}
|
||||
|
||||
TEST(ConfigurationColumnTest, YAMLDecodeTest) {
|
||||
YAML::Node node;
|
||||
node.SetTag("xilinx/spartan6/configuration_column");
|
||||
node["frame_count"] = 10;
|
||||
|
||||
auto column = node.as<spartan6::ConfigurationColumn>();
|
||||
EXPECT_TRUE(column.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 2, 8)));
|
||||
EXPECT_FALSE(column.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 2, 9)));
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
#include <functional>
|
||||
|
||||
#include <absl/meta/type_traits.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <prjxray/bit_ops.h>
|
||||
|
||||
#include <prjxray/xilinx/architectures.h>
|
||||
|
||||
using namespace prjxray::xilinx;
|
||||
|
||||
constexpr uint32_t kType1NOP = prjxray::bit_field_set<uint32_t>(0, 15, 13, 0x1);
|
||||
|
||||
const 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, 15, 13, 0x1), 12, 11,
|
||||
opcode),
|
||||
10, 5, address),
|
||||
4, 0, word_count);
|
||||
}
|
||||
|
||||
const std::vector<uint32_t> MakeType2(const int opcode,
|
||||
const int address,
|
||||
const int word_count) {
|
||||
uint32_t header = 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, 15, 13, 0x2), 12, 11,
|
||||
opcode),
|
||||
10, 5, address),
|
||||
4, 0, 0);
|
||||
uint32_t wcr1 = (word_count >> 16) & 0xFFFF;
|
||||
uint32_t wcr2 = (word_count & 0xFFFF);
|
||||
return std::vector<uint32_t>{header, wcr1, wcr2};
|
||||
}
|
||||
|
||||
TEST(ConfigPacket, InitWithZeroBytes) {
|
||||
auto packet =
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::InitWithWords({});
|
||||
|
||||
EXPECT_EQ(packet.first, absl::Span<uint32_t>());
|
||||
EXPECT_FALSE(packet.second);
|
||||
}
|
||||
|
||||
TEST(ConfigPacket, InitWithType1Nop) {
|
||||
std::vector<uint32_t> words{kType1NOP};
|
||||
absl::Span<uint32_t> word_span(words);
|
||||
auto packet = ConfigurationPacket<Spartan6::ConfRegType>::InitWithWords(
|
||||
word_span);
|
||||
EXPECT_EQ(packet.first, absl::Span<uint32_t>());
|
||||
ASSERT_TRUE(packet.second);
|
||||
EXPECT_EQ(packet.second->opcode(),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::NOP);
|
||||
EXPECT_EQ(packet.second->address(), Spartan6::ConfRegType::CRC);
|
||||
EXPECT_EQ(packet.second->data(), absl::Span<uint32_t>());
|
||||
}
|
||||
|
||||
TEST(ConfigPacket, InitWithType1Read) {
|
||||
std::vector<uint32_t> words{MakeType1(0x1, 0x3, 2), 0xAA, 0xBB};
|
||||
absl::Span<uint32_t> word_span(words);
|
||||
auto packet = ConfigurationPacket<Spartan6::ConfRegType>::InitWithWords(
|
||||
word_span);
|
||||
EXPECT_EQ(packet.first, absl::Span<uint32_t>());
|
||||
ASSERT_TRUE(packet.second);
|
||||
EXPECT_EQ(packet.second->opcode(),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Read);
|
||||
EXPECT_EQ(packet.second->address(), Spartan6::ConfRegType::FDRI);
|
||||
EXPECT_EQ(packet.second->data(), word_span.subspan(1));
|
||||
}
|
||||
|
||||
TEST(ConfigPacket, InitWithType1Write) {
|
||||
std::vector<uint32_t> words{MakeType1(0x2, 0x4, 2), 0xAA, 0xBB};
|
||||
absl::Span<uint32_t> word_span(words);
|
||||
auto packet = ConfigurationPacket<Spartan6::ConfRegType>::InitWithWords(
|
||||
word_span);
|
||||
EXPECT_EQ(packet.first, absl::Span<uint32_t>());
|
||||
ASSERT_TRUE(packet.second);
|
||||
EXPECT_EQ(packet.second->opcode(),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Write);
|
||||
EXPECT_EQ(packet.second->address(), Spartan6::ConfRegType::FDRO);
|
||||
EXPECT_EQ(packet.second->data(), word_span.subspan(1));
|
||||
}
|
||||
|
||||
TEST(ConfigPacket, InitWithType2WithPreviousPacket) {
|
||||
std::vector<uint32_t> words{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
|
||||
std::vector<uint32_t> type2 = MakeType2(0x01, 0x03, 12);
|
||||
words.insert(words.begin(), type2.begin(), type2.end());
|
||||
absl::Span<uint32_t> word_span(words);
|
||||
auto packet = ConfigurationPacket<Spartan6::ConfRegType>::InitWithWords(
|
||||
word_span);
|
||||
EXPECT_EQ(packet.first, absl::Span<uint32_t>());
|
||||
ASSERT_TRUE(packet.second);
|
||||
EXPECT_EQ(packet.second->opcode(),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Read);
|
||||
EXPECT_EQ(packet.second->address(), Spartan6::ConfRegType::FDRI);
|
||||
EXPECT_EQ(packet.second->data(), word_span.subspan(3));
|
||||
}
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <absl/types/span.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <prjxray/memory_mapped_file.h>
|
||||
#include <prjxray/xilinx/architectures.h>
|
||||
#include <prjxray/xilinx/configuration.h>
|
||||
#include <prjxray/xilinx/spartan6/frame_address.h>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
using namespace prjxray::xilinx;
|
||||
|
||||
TEST(ConfigurationTest, ConstructFromPacketsWithSingleFrame) {
|
||||
std::vector<spartan6::FrameAddress> test_part_addresses;
|
||||
test_part_addresses.push_back(0x0A);
|
||||
test_part_addresses.push_back(0x0B);
|
||||
|
||||
spartan6::Part test_part(0x1234, test_part_addresses);
|
||||
|
||||
std::vector<uint32_t> idcode{0x1234};
|
||||
std::vector<uint32_t> cmd{0x0001};
|
||||
std::vector<uint32_t> frame_address{0x345};
|
||||
std::vector<uint32_t> frame(65, 0xAA);
|
||||
|
||||
std::vector<ConfigurationPacket<typename Spartan6::ConfRegType>>
|
||||
packets{
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Write,
|
||||
Spartan6::ConfRegType::IDCODE,
|
||||
absl::MakeSpan(idcode),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Write,
|
||||
Spartan6::ConfRegType::FAR_MIN,
|
||||
absl::MakeSpan(frame_address),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Write,
|
||||
Spartan6::ConfRegType::CMD,
|
||||
absl::MakeSpan(cmd),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Write,
|
||||
Spartan6::ConfRegType::FDRI,
|
||||
absl::MakeSpan(frame),
|
||||
},
|
||||
};
|
||||
|
||||
auto test_config =
|
||||
Configuration<Spartan6>::InitWithPackets(test_part, packets);
|
||||
ASSERT_TRUE(test_config);
|
||||
|
||||
EXPECT_EQ(test_config->part().idcode(), static_cast<uint32_t>(0x1234));
|
||||
EXPECT_EQ(test_config->frames().size(), static_cast<size_t>(1));
|
||||
EXPECT_EQ(test_config->frames().at(0x345), frame);
|
||||
}
|
||||
|
||||
TEST(ConfigurationTest, ConstructFromPacketsWithAutoincrement) {
|
||||
std::vector<spartan6::FrameAddress> test_part_addresses;
|
||||
for (int ii = 0x310; ii < 0x320; ++ii) {
|
||||
test_part_addresses.push_back(ii);
|
||||
}
|
||||
|
||||
for (int ii = 0x330; ii < 0x331; ++ii) {
|
||||
test_part_addresses.push_back(ii);
|
||||
}
|
||||
|
||||
spartan6::Part test_part(0x1234, test_part_addresses);
|
||||
|
||||
std::vector<uint32_t> idcode{0x1234};
|
||||
std::vector<uint32_t> cmd{0x0001};
|
||||
std::vector<uint32_t> frame_address{0x31f};
|
||||
std::vector<uint32_t> frame(65 * 2, 0xAA);
|
||||
std::fill_n(frame.begin() + 65, 65, 0xBB);
|
||||
|
||||
std::vector<ConfigurationPacket<Spartan6::ConfRegType>> packets{
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Write,
|
||||
Spartan6::ConfRegType::IDCODE,
|
||||
absl::MakeSpan(idcode),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Write,
|
||||
Spartan6::ConfRegType::FAR_MIN,
|
||||
absl::MakeSpan(frame_address),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Write,
|
||||
Spartan6::ConfRegType::CMD,
|
||||
absl::MakeSpan(cmd),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Write,
|
||||
Spartan6::ConfRegType::FDRI,
|
||||
absl::MakeSpan(frame),
|
||||
},
|
||||
};
|
||||
|
||||
auto test_config =
|
||||
Configuration<Spartan6>::InitWithPackets(test_part, packets);
|
||||
ASSERT_TRUE(test_config);
|
||||
|
||||
absl::Span<uint32_t> frame_span(frame);
|
||||
EXPECT_EQ(test_config->part().idcode(), static_cast<uint32_t>(0x1234));
|
||||
EXPECT_EQ(test_config->frames().size(), static_cast<size_t>(2));
|
||||
EXPECT_EQ(test_config->frames().at(0x31f),
|
||||
std::vector<uint32_t>(65, 0xAA));
|
||||
// TODO This test fails with a C++ exception because the address
|
||||
// of next frame is 0x320 instead of 0x330 as defined in the test_part
|
||||
// EXPECT_EQ(test_config->frames().at(0x330),
|
||||
// std::vector<uint32_t>(65, 0xBB));
|
||||
}
|
||||
|
||||
TEST(ConfigurationTest, DISABLED_CheckForPaddingAfterIOBFrame) {
|
||||
std::vector<spartan6::FrameAddress> test_part_addresses = {
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0),
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 1, 0, 0),
|
||||
spartan6::FrameAddress(spartan6::BlockType::IOB, 2, 0, 0)};
|
||||
|
||||
auto test_part = absl::optional<spartan6::Part>(
|
||||
spartan6::Part(0x1234, test_part_addresses));
|
||||
|
||||
Frames<Spartan6> frames;
|
||||
frames.getFrames().emplace(std::make_pair(
|
||||
test_part_addresses.at(0), std::vector<uint32_t>(65, 0xAA)));
|
||||
frames.getFrames().emplace(std::make_pair(
|
||||
test_part_addresses.at(1), std::vector<uint32_t>(65, 0xBB)));
|
||||
frames.getFrames().emplace(std::make_pair(
|
||||
test_part_addresses.at(2), std::vector<uint32_t>(65, 0xCC)));
|
||||
ASSERT_EQ(frames.getFrames().size(), 3);
|
||||
|
||||
Configuration<Spartan6>::PacketData packet_data =
|
||||
Configuration<Spartan6>::createType2ConfigurationPacketData(
|
||||
frames.getFrames(), test_part);
|
||||
// createType2ConfigurationPacketData should add a 16-bit pad word after
|
||||
// after the IOB frame
|
||||
EXPECT_EQ(packet_data.size(), 3 * 65 + 1);
|
||||
|
||||
std::vector<uint32_t> idcode{0x1234};
|
||||
std::vector<uint32_t> cmd{0x0001};
|
||||
std::vector<uint32_t> frame_address{0x0};
|
||||
|
||||
std::vector<ConfigurationPacket<Spartan6::ConfRegType>> packets{
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Write,
|
||||
Spartan6::ConfRegType::IDCODE,
|
||||
absl::MakeSpan(idcode),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Write,
|
||||
Spartan6::ConfRegType::FAR,
|
||||
absl::MakeSpan(frame_address),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Write,
|
||||
Spartan6::ConfRegType::CMD,
|
||||
absl::MakeSpan(cmd),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
ConfigurationPacket<Spartan6::ConfRegType>::Opcode::Write,
|
||||
Spartan6::ConfRegType::FDRI,
|
||||
absl::MakeSpan(packet_data),
|
||||
},
|
||||
};
|
||||
|
||||
auto test_config =
|
||||
Configuration<Spartan6>::InitWithPackets(*test_part, packets);
|
||||
ASSERT_EQ(test_config->frames().size(), 5);
|
||||
for (auto& frame : test_config->frames()) {
|
||||
EXPECT_EQ(frame.second, frames.getFrames().at(frame.first));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#include <prjxray/xilinx/spartan6/frame_address.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace prjxray::xilinx;
|
||||
|
||||
TEST(FrameAddressTest, YamlEncode) {
|
||||
spartan6::FrameAddress address(spartan6::BlockType::BLOCK_RAM, 10, 0,
|
||||
5);
|
||||
|
||||
YAML::Node node(address);
|
||||
|
||||
EXPECT_EQ(node.Tag(), "xilinx/spartan6/frame_address");
|
||||
EXPECT_EQ(node["block_type"].as<std::string>(), "BLOCK_RAM");
|
||||
EXPECT_EQ(node["row"].as<std::string>(), "10");
|
||||
EXPECT_EQ(node["column"].as<std::string>(), "0");
|
||||
EXPECT_EQ(node["minor"].as<std::string>(), "5");
|
||||
}
|
||||
|
||||
TEST(FrameAddressTest, YamlDecode) {
|
||||
YAML::Node node;
|
||||
node.SetTag("xilinx/spartan6/frame_address");
|
||||
node["block_type"] = "BLOCK_RAM";
|
||||
node["row"] = "0";
|
||||
node["column"] = "5";
|
||||
node["minor"] = "11";
|
||||
|
||||
spartan6::FrameAddress address = node.as<spartan6::FrameAddress>();
|
||||
EXPECT_EQ(address.block_type(), spartan6::BlockType::BLOCK_RAM);
|
||||
EXPECT_EQ(address.row(), 0);
|
||||
EXPECT_EQ(address.column(), 5);
|
||||
EXPECT_EQ(address.minor(), 11);
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <prjxray/xilinx/frames.h>
|
||||
#include <prjxray/xilinx/spartan6/part.h>
|
||||
|
||||
using namespace prjxray::xilinx;
|
||||
TEST(FramesTest, FillInMissingFrames) {
|
||||
std::vector<spartan6::FrameAddress> test_part_addresses = {
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0),
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1),
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 2),
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 3),
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 4)};
|
||||
|
||||
spartan6::Part test_part(0x1234, test_part_addresses);
|
||||
|
||||
Frames<Spartan6> frames;
|
||||
frames.getFrames().emplace(std::make_pair(
|
||||
spartan6::FrameAddress(2), std::vector<uint32_t>(65, 0xCC)));
|
||||
frames.getFrames().emplace(std::make_pair(
|
||||
spartan6::FrameAddress(3), std::vector<uint32_t>(65, 0xDD)));
|
||||
frames.getFrames().emplace(std::make_pair(
|
||||
spartan6::FrameAddress(4), std::vector<uint32_t>(65, 0xEE)));
|
||||
|
||||
ASSERT_EQ(frames.getFrames().size(), 3);
|
||||
EXPECT_EQ(frames.getFrames().at(test_part_addresses[2]),
|
||||
std::vector<uint32_t>(65, 0xCC));
|
||||
EXPECT_EQ(frames.getFrames().at(test_part_addresses[3]),
|
||||
std::vector<uint32_t>(65, 0xDD));
|
||||
EXPECT_EQ(frames.getFrames().at(test_part_addresses[4]),
|
||||
std::vector<uint32_t>(65, 0xEE));
|
||||
|
||||
frames.addMissingFrames(test_part);
|
||||
|
||||
ASSERT_EQ(frames.getFrames().size(), 5);
|
||||
EXPECT_EQ(frames.getFrames().at(test_part_addresses[0]),
|
||||
std::vector<uint32_t>(65, 0));
|
||||
EXPECT_EQ(frames.getFrames().at(test_part_addresses[1]),
|
||||
std::vector<uint32_t>(65, 0));
|
||||
EXPECT_EQ(frames.getFrames().at(test_part_addresses[2]),
|
||||
std::vector<uint32_t>(65, 0xCC));
|
||||
EXPECT_EQ(frames.getFrames().at(test_part_addresses[3]),
|
||||
std::vector<uint32_t>(65, 0xDD));
|
||||
EXPECT_EQ(frames.getFrames().at(test_part_addresses[4]),
|
||||
std::vector<uint32_t>(65, 0xEE));
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
#include <prjxray/xilinx/spartan6/global_clock_region.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace prjxray::xilinx;
|
||||
|
||||
TEST(GlobalClockRegionTest, IsValidFrameAddress) {
|
||||
std::vector<spartan6::FrameAddress> addresses;
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 1));
|
||||
|
||||
spartan6::GlobalClockRegion global_clock_region(addresses.begin(),
|
||||
addresses.end());
|
||||
|
||||
EXPECT_TRUE(global_clock_region.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0)));
|
||||
EXPECT_TRUE(global_clock_region.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0)));
|
||||
EXPECT_TRUE(global_clock_region.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2)));
|
||||
EXPECT_TRUE(global_clock_region.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 0)));
|
||||
|
||||
EXPECT_FALSE(global_clock_region.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 2)));
|
||||
EXPECT_FALSE(global_clock_region.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 2, 0)));
|
||||
EXPECT_FALSE(global_clock_region.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 2, 0, 0)));
|
||||
EXPECT_FALSE(global_clock_region.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::IOB, 0, 0, 2)));
|
||||
}
|
||||
|
||||
TEST(GlobalClockRegionTest,
|
||||
GetNextFrameAddressYieldNextAddressInGlobalClockRegion) {
|
||||
std::vector<spartan6::FrameAddress> addresses;
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 1));
|
||||
|
||||
spartan6::GlobalClockRegion global_clock_region(addresses.begin(),
|
||||
addresses.end());
|
||||
|
||||
auto next_address = global_clock_region.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(
|
||||
*next_address,
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
|
||||
next_address = global_clock_region.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(
|
||||
*next_address,
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0));
|
||||
|
||||
next_address = global_clock_region.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 1));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(
|
||||
*next_address,
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 0));
|
||||
|
||||
next_address = global_clock_region.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(*next_address, spartan6::FrameAddress(
|
||||
spartan6::BlockType::BLOCK_RAM, 0, 0, 2));
|
||||
}
|
||||
|
||||
TEST(GlobalClockRegionTest,
|
||||
GetNextFrameAddressYieldNothingAtEndOfGlobalClockRegion) {
|
||||
std::vector<spartan6::FrameAddress> addresses;
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 1));
|
||||
|
||||
spartan6::GlobalClockRegion global_clock_region(addresses.begin(),
|
||||
addresses.end());
|
||||
|
||||
EXPECT_FALSE(global_clock_region.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 1)));
|
||||
EXPECT_FALSE(global_clock_region.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2)));
|
||||
}
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
#include <prjxray/xilinx/spartan6/part.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace prjxray::xilinx;
|
||||
|
||||
TEST(PartTest, IsValidFrameAddress) {
|
||||
std::vector<spartan6::FrameAddress> addresses;
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
|
||||
spartan6::Part part(0x1234, addresses.begin(), addresses.end());
|
||||
|
||||
EXPECT_TRUE(part.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0)));
|
||||
EXPECT_TRUE(part.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0)));
|
||||
EXPECT_TRUE(part.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2)));
|
||||
EXPECT_TRUE(part.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 0)));
|
||||
EXPECT_TRUE(part.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0)));
|
||||
|
||||
EXPECT_FALSE(part.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 2)));
|
||||
EXPECT_FALSE(part.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 2, 0)));
|
||||
EXPECT_FALSE(part.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 2, 0, 0)));
|
||||
EXPECT_FALSE(part.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::IOB, 0, 0, 2)));
|
||||
}
|
||||
|
||||
TEST(PartTest, GetNextFrameAddressYieldNextAddressInPart) {
|
||||
std::vector<spartan6::FrameAddress> addresses;
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
|
||||
spartan6::Part part(0x1234, addresses.begin(), addresses.end());
|
||||
|
||||
auto next_address = part.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(
|
||||
*next_address,
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
|
||||
next_address = part.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(
|
||||
*next_address,
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0));
|
||||
|
||||
next_address = part.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 1));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(
|
||||
*next_address,
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 0));
|
||||
|
||||
next_address = part.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 1));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(*next_address, spartan6::FrameAddress(
|
||||
spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
|
||||
next_address = part.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(
|
||||
*next_address,
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0));
|
||||
}
|
||||
|
||||
TEST(PartTest, GetNextFrameAddressYieldNothingAtEndOfPart) {
|
||||
std::vector<spartan6::FrameAddress> addresses;
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 1, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
|
||||
spartan6::Part part(0x1234, addresses.begin(), addresses.end());
|
||||
|
||||
EXPECT_FALSE(part.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2)));
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
#include <prjxray/xilinx/spartan6/configuration_row.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace prjxray::xilinx;
|
||||
|
||||
TEST(RowTest, IsValidFrameAddress) {
|
||||
std::vector<spartan6::FrameAddress> addresses;
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2));
|
||||
|
||||
spartan6::Row row(addresses.begin(), addresses.end());
|
||||
|
||||
EXPECT_TRUE(row.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0)));
|
||||
EXPECT_TRUE(row.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0)));
|
||||
EXPECT_TRUE(row.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2)));
|
||||
|
||||
EXPECT_FALSE(row.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 2)));
|
||||
EXPECT_FALSE(row.IsValidFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 2, 0)));
|
||||
}
|
||||
|
||||
TEST(RowTest, GetNextFrameAddressYieldNextAddressInRow) {
|
||||
std::vector<spartan6::FrameAddress> addresses;
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2));
|
||||
|
||||
spartan6::Row row(addresses.begin(), addresses.end());
|
||||
|
||||
auto next_address = row.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(
|
||||
*next_address,
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
|
||||
next_address = row.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(
|
||||
*next_address,
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0));
|
||||
|
||||
// Rows have unique behavior for GetNextFrameAddress() at the end of a
|
||||
// bus. Since the addresses need to be returned in numerically
|
||||
// increasing order, all of the rows need to be returned before moving
|
||||
// to a different bus. That means that Row::GetNextFrameAddress() needs
|
||||
// to return no object at the end of a bus and let the caller use that
|
||||
// as a signal to try the next row.
|
||||
next_address = row.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 1));
|
||||
EXPECT_FALSE(next_address);
|
||||
|
||||
next_address = row.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
ASSERT_TRUE(next_address);
|
||||
EXPECT_EQ(*next_address, spartan6::FrameAddress(
|
||||
spartan6::BlockType::BLOCK_RAM, 0, 0, 2));
|
||||
|
||||
next_address = row.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2));
|
||||
EXPECT_FALSE(next_address);
|
||||
}
|
||||
|
||||
TEST(RowTest, GetNextFrameAddressYieldNothingAtEndOfRow) {
|
||||
std::vector<spartan6::FrameAddress> addresses;
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::CLB_IOI_CLK, 0, 1, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 0));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 1));
|
||||
addresses.push_back(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2));
|
||||
|
||||
spartan6::Row row(addresses.begin(), addresses.end());
|
||||
|
||||
EXPECT_FALSE(row.GetNextFrameAddress(
|
||||
spartan6::FrameAddress(spartan6::BlockType::BLOCK_RAM, 0, 0, 2)));
|
||||
}
|
||||
Loading…
Reference in New Issue