mirror of https://github.com/openXC7/prjxray.git
xc7series: Dynamically allocate config packets when writing bitstreams
ConfigurationPacket assumes that the payload data is owned by someone else. For frame data, that is generally true. For initialization and finalization sequences, those payloads need to be created and managed. Instead, dynamically allocate packets which allows for using subclasses of ConfigurationPacket that store the payload with the packet. Signed-off-by: Rick Altherr <kc8apf@kc8apf.net>
This commit is contained in:
parent
f5099113e6
commit
43b70caf03
|
|
@ -23,7 +23,7 @@ namespace xc7series {
|
||||||
class BitstreamWriter {
|
class BitstreamWriter {
|
||||||
public:
|
public:
|
||||||
typedef std::array<uint32_t, 6> header_t;
|
typedef std::array<uint32_t, 6> header_t;
|
||||||
typedef std::vector<ConfigurationPacket> packets_t;
|
typedef std::vector<std::unique_ptr<ConfigurationPacket>> packets_t;
|
||||||
// Only defined if a packet exists
|
// Only defined if a packet exists
|
||||||
typedef absl::optional<absl::Span<const uint32_t>> op_data_t;
|
typedef absl::optional<absl::Span<const uint32_t>> op_data_t;
|
||||||
typedef absl::Span<const uint32_t>::iterator data_iterator_t;
|
typedef absl::Span<const uint32_t>::iterator data_iterator_t;
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ BitstreamWriter::BitstreamWriter(const packets_t& packets)
|
||||||
|
|
||||||
BitstreamWriter::packet_iterator BitstreamWriter::iterator::packet_begin() {
|
BitstreamWriter::packet_iterator BitstreamWriter::iterator::packet_begin() {
|
||||||
// itr_packets = packets.begin();
|
// itr_packets = packets.begin();
|
||||||
const ConfigurationPacket& packet = *itr_packets_;
|
const ConfigurationPacket& packet = **itr_packets_;
|
||||||
|
|
||||||
return BitstreamWriter::packet_iterator(
|
return BitstreamWriter::packet_iterator(
|
||||||
&packet, BitstreamWriter::packet_iterator::STATE_HEADER,
|
&packet, BitstreamWriter::packet_iterator::STATE_HEADER,
|
||||||
|
|
@ -36,7 +36,7 @@ BitstreamWriter::packet_iterator BitstreamWriter::iterator::packet_begin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
BitstreamWriter::packet_iterator BitstreamWriter::iterator::packet_end() {
|
BitstreamWriter::packet_iterator BitstreamWriter::iterator::packet_end() {
|
||||||
const ConfigurationPacket& packet = *itr_packets_;
|
const ConfigurationPacket& packet = **itr_packets_;
|
||||||
|
|
||||||
return BitstreamWriter::packet_iterator(
|
return BitstreamWriter::packet_iterator(
|
||||||
&packet, BitstreamWriter::packet_iterator::STATE_END,
|
&packet, BitstreamWriter::packet_iterator::STATE_END,
|
||||||
|
|
@ -138,7 +138,7 @@ BitstreamWriter::iterator BitstreamWriter::begin() {
|
||||||
if (itr_packets != packets_.end()) {
|
if (itr_packets != packets_.end()) {
|
||||||
// op_packet_itr = packet_begin();
|
// op_packet_itr = packet_begin();
|
||||||
// FIXME: de-duplicate this
|
// FIXME: de-duplicate this
|
||||||
const ConfigurationPacket& packet = *itr_packets;
|
const ConfigurationPacket& packet = **itr_packets;
|
||||||
packet_iterator packet_itr =
|
packet_iterator packet_itr =
|
||||||
packet_iterator(&packet, packet_iterator::STATE_HEADER,
|
packet_iterator(&packet, packet_iterator::STATE_HEADER,
|
||||||
packet.data().begin());
|
packet.data().begin());
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,8 @@ void dump_packets(xc7series::BitstreamWriter writer, bool nl = true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special all 0's
|
// Special all 0's
|
||||||
void AddType0(std::vector<xc7series::ConfigurationPacket>& packets) {
|
void AddType0(
|
||||||
|
std::vector<std::unique_ptr<xc7series::ConfigurationPacket>>& packets) {
|
||||||
// InitWithWords doesn't like type 0
|
// InitWithWords doesn't like type 0
|
||||||
/*
|
/*
|
||||||
static std::vector<uint32_t> words{0x00000000};
|
static std::vector<uint32_t> words{0x00000000};
|
||||||
|
|
@ -61,27 +62,32 @@ void AddType0(std::vector<xc7series::ConfigurationPacket>& packets) {
|
||||||
static std::vector<uint32_t> words{};
|
static std::vector<uint32_t> words{};
|
||||||
absl::Span<uint32_t> word_span(words);
|
absl::Span<uint32_t> word_span(words);
|
||||||
// CRC is config value 0
|
// CRC is config value 0
|
||||||
packets.push_back(xc7series::ConfigurationPacket(
|
packets.emplace_back(new xc7series::ConfigurationPacket(
|
||||||
0, xc7series::ConfigurationPacket::NOP,
|
0, xc7series::ConfigurationPacket::NOP,
|
||||||
xc7series::ConfigurationRegister::CRC, word_span));
|
xc7series::ConfigurationRegister::CRC, word_span));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddType1(std::vector<xc7series::ConfigurationPacket>& packets) {
|
void AddType1(
|
||||||
|
std::vector<std::unique_ptr<xc7series::ConfigurationPacket>>& packets) {
|
||||||
static std::vector<uint32_t> words{MakeType1(0x2, 0x3, 2), 0xAA, 0xBB};
|
static std::vector<uint32_t> words{MakeType1(0x2, 0x3, 2), 0xAA, 0xBB};
|
||||||
absl::Span<uint32_t> word_span(words);
|
absl::Span<uint32_t> word_span(words);
|
||||||
auto packet = xc7series::ConfigurationPacket::InitWithWords(word_span);
|
auto packet = xc7series::ConfigurationPacket::InitWithWords(word_span);
|
||||||
packets.push_back(*(packet.second));
|
packets.emplace_back(
|
||||||
|
new xc7series::ConfigurationPacket(*(packet.second)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty
|
// Empty
|
||||||
void AddType1E(std::vector<xc7series::ConfigurationPacket>& packets) {
|
void AddType1E(
|
||||||
|
std::vector<std::unique_ptr<xc7series::ConfigurationPacket>>& packets) {
|
||||||
static std::vector<uint32_t> words{MakeType1(0x2, 0x3, 0)};
|
static std::vector<uint32_t> words{MakeType1(0x2, 0x3, 0)};
|
||||||
absl::Span<uint32_t> word_span(words);
|
absl::Span<uint32_t> word_span(words);
|
||||||
auto packet = xc7series::ConfigurationPacket::InitWithWords(word_span);
|
auto packet = xc7series::ConfigurationPacket::InitWithWords(word_span);
|
||||||
packets.push_back(*(packet.second));
|
packets.emplace_back(
|
||||||
|
new xc7series::ConfigurationPacket(*(packet.second)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddType2(std::vector<xc7series::ConfigurationPacket>& packets) {
|
void AddType2(
|
||||||
|
std::vector<std::unique_ptr<xc7series::ConfigurationPacket>>& packets) {
|
||||||
// Type 1 packet with address
|
// Type 1 packet with address
|
||||||
// Without this InitWithWords will fail on type 2
|
// Without this InitWithWords will fail on type 2
|
||||||
xc7series::ConfigurationPacket* packet1;
|
xc7series::ConfigurationPacket* packet1;
|
||||||
|
|
@ -90,8 +96,9 @@ void AddType2(std::vector<xc7series::ConfigurationPacket>& packets) {
|
||||||
absl::Span<uint32_t> word_span(words);
|
absl::Span<uint32_t> word_span(words);
|
||||||
auto packet1_pair =
|
auto packet1_pair =
|
||||||
xc7series::ConfigurationPacket::InitWithWords(word_span);
|
xc7series::ConfigurationPacket::InitWithWords(word_span);
|
||||||
packets.push_back(*(packet1_pair.second));
|
packets.emplace_back(
|
||||||
packet1 = &packets[0];
|
new xc7series::ConfigurationPacket(*(packet1_pair.second)));
|
||||||
|
packet1 = packets[0].get();
|
||||||
}
|
}
|
||||||
// Type 2 packet with data
|
// Type 2 packet with data
|
||||||
{
|
{
|
||||||
|
|
@ -100,13 +107,14 @@ void AddType2(std::vector<xc7series::ConfigurationPacket>& packets) {
|
||||||
absl::Span<uint32_t> word_span(words);
|
absl::Span<uint32_t> word_span(words);
|
||||||
auto packet = xc7series::ConfigurationPacket::InitWithWords(
|
auto packet = xc7series::ConfigurationPacket::InitWithWords(
|
||||||
word_span, packet1);
|
word_span, packet1);
|
||||||
packets.push_back(*(packet.second));
|
packets.emplace_back(
|
||||||
|
new xc7series::ConfigurationPacket(*(packet.second)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty packets should produce just the header
|
// Empty packets should produce just the header
|
||||||
TEST(BitstreamWriterTest, WriteHeader) {
|
TEST(BitstreamWriterTest, WriteHeader) {
|
||||||
std::vector<xc7series::ConfigurationPacket> packets;
|
std::vector<std::unique_ptr<xc7series::ConfigurationPacket>> packets;
|
||||||
|
|
||||||
xc7series::BitstreamWriter writer(packets);
|
xc7series::BitstreamWriter writer(packets);
|
||||||
std::vector<uint32_t> words(writer.begin(), writer.end());
|
std::vector<uint32_t> words(writer.begin(), writer.end());
|
||||||
|
|
@ -120,7 +128,7 @@ TEST(BitstreamWriterTest, WriteHeader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BitstreamWriterTest, WriteType0) {
|
TEST(BitstreamWriterTest, WriteType0) {
|
||||||
std::vector<xc7series::ConfigurationPacket> packets;
|
std::vector<std::unique_ptr<xc7series::ConfigurationPacket>> packets;
|
||||||
AddType0(packets);
|
AddType0(packets);
|
||||||
xc7series::BitstreamWriter writer(packets);
|
xc7series::BitstreamWriter writer(packets);
|
||||||
// dump_packets(writer, false);
|
// dump_packets(writer, false);
|
||||||
|
|
@ -133,7 +141,7 @@ TEST(BitstreamWriterTest, WriteType0) {
|
||||||
EXPECT_EQ(words, ref);
|
EXPECT_EQ(words, ref);
|
||||||
}
|
}
|
||||||
TEST(BitstreamWriterTest, WriteType1) {
|
TEST(BitstreamWriterTest, WriteType1) {
|
||||||
std::vector<xc7series::ConfigurationPacket> packets;
|
std::vector<std::unique_ptr<xc7series::ConfigurationPacket>> packets;
|
||||||
AddType1(packets);
|
AddType1(packets);
|
||||||
xc7series::BitstreamWriter writer(packets);
|
xc7series::BitstreamWriter writer(packets);
|
||||||
// dump_packets(writer, false);
|
// dump_packets(writer, false);
|
||||||
|
|
@ -147,7 +155,7 @@ TEST(BitstreamWriterTest, WriteType1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BitstreamWriterTest, WriteType2) {
|
TEST(BitstreamWriterTest, WriteType2) {
|
||||||
std::vector<xc7series::ConfigurationPacket> packets;
|
std::vector<std::unique_ptr<xc7series::ConfigurationPacket>> packets;
|
||||||
AddType2(packets);
|
AddType2(packets);
|
||||||
xc7series::BitstreamWriter writer(packets);
|
xc7series::BitstreamWriter writer(packets);
|
||||||
// dump_packets(writer, false);
|
// dump_packets(writer, false);
|
||||||
|
|
@ -164,7 +172,7 @@ TEST(BitstreamWriterTest, WriteType2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BitstreamWriterTest, WriteMulti) {
|
TEST(BitstreamWriterTest, WriteMulti) {
|
||||||
std::vector<xc7series::ConfigurationPacket> packets;
|
std::vector<std::unique_ptr<xc7series::ConfigurationPacket>> packets;
|
||||||
AddType1(packets);
|
AddType1(packets);
|
||||||
AddType1E(packets);
|
AddType1E(packets);
|
||||||
AddType2(packets);
|
AddType2(packets);
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,8 @@ int main(int argc, char* argv[]) {
|
||||||
frame_data[0x32] |= (ecc & 0x1FFF);
|
frame_data[0x32] |= (ecc & 0x1FFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<xc7series::ConfigurationPacket> out_packets;
|
std::vector<std::unique_ptr<xc7series::ConfigurationPacket>>
|
||||||
|
out_packets;
|
||||||
|
|
||||||
// Generate a single type 2 packet that writes everything at once.
|
// Generate a single type 2 packet that writes everything at once.
|
||||||
std::vector<uint32_t> packet_data;
|
std::vector<uint32_t> packet_data;
|
||||||
|
|
@ -139,10 +140,11 @@ int main(int argc, char* argv[]) {
|
||||||
}
|
}
|
||||||
packet_data.insert(packet_data.end(), 202, 0);
|
packet_data.insert(packet_data.end(), 202, 0);
|
||||||
|
|
||||||
out_packets.push_back(xc7series::ConfigurationPacket(
|
// Frame data write
|
||||||
|
out_packets.emplace_back(new xc7series::ConfigurationPacket(
|
||||||
1, xc7series::ConfigurationPacket::Opcode::Write,
|
1, xc7series::ConfigurationPacket::Opcode::Write,
|
||||||
xc7series::ConfigurationRegister::FDRI, {}));
|
xc7series::ConfigurationRegister::FDRI, {}));
|
||||||
out_packets.push_back(xc7series::ConfigurationPacket(
|
out_packets.emplace_back(new xc7series::ConfigurationPacket(
|
||||||
2, xc7series::ConfigurationPacket::Opcode::Write,
|
2, xc7series::ConfigurationPacket::Opcode::Write,
|
||||||
xc7series::ConfigurationRegister::FDRI, packet_data));
|
xc7series::ConfigurationRegister::FDRI, packet_data));
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue