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:
Rick Altherr 2018-02-01 12:11:25 -08:00
parent f5099113e6
commit 43b70caf03
4 changed files with 32 additions and 22 deletions

View File

@ -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;

View File

@ -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());

View File

@ -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);

View File

@ -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));