Merge pull request #84 from kc8apf/arch_docs
docs: low-level configuration details
diff --git a/lib/include/prjxray/xilinx/xc7series/bitstream_writer.h b/lib/include/prjxray/xilinx/xc7series/bitstream_writer.h
index ae0634d..806cc9a 100644
--- a/lib/include/prjxray/xilinx/xc7series/bitstream_writer.h
+++ b/lib/include/prjxray/xilinx/xc7series/bitstream_writer.h
@@ -23,7 +23,7 @@
class BitstreamWriter {
public:
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
typedef absl::optional<absl::Span<const uint32_t>> op_data_t;
typedef absl::Span<const uint32_t>::iterator data_iterator_t;
diff --git a/lib/include/prjxray/xilinx/xc7series/command.h b/lib/include/prjxray/xilinx/xc7series/command.h
new file mode 100644
index 0000000..2ff16e8
--- /dev/null
+++ b/lib/include/prjxray/xilinx/xc7series/command.h
@@ -0,0 +1,34 @@
+#ifndef PRJXRAY_LIB_XILINX_XC7SERIES_COMMAND_H_
+#define PRJXRAY_LIB_XILINX_XC7SERIES_COMMAND_H_
+
+namespace prjxray {
+namespace xilinx {
+namespace xc7series {
+
+enum class Command : uint32_t {
+ NOP = 0x0,
+ WCFG = 0x1,
+ MFW = 0x2,
+ LFRM = 0x3,
+ RCFG = 0x4,
+ START = 0x5,
+ RCAP = 0x6,
+ RCRC = 0x7,
+ AGHIGH = 0x8,
+ SWITCH = 0x9,
+ GRESTORE = 0xA,
+ SHUTDOWN = 0xB,
+ GCAPTURE = 0xC,
+ DESYNC = 0xD,
+ IPROG = 0xF,
+ CRCC = 0x10,
+ LTIMER = 0x11,
+ BSPI_READ = 0x12,
+ FALL_EDGE = 0x13,
+};
+
+} // namespace xc7series
+} // namespace xilinx
+} // namespace prjxray
+
+#endif // PRJXRAY_LIB_XILINX_XC7SERIES_COMMAND_H_
diff --git a/lib/include/prjxray/xilinx/xc7series/configuration_options_0_value.h b/lib/include/prjxray/xilinx/xc7series/configuration_options_0_value.h
new file mode 100644
index 0000000..1b7c1c1
--- /dev/null
+++ b/lib/include/prjxray/xilinx/xc7series/configuration_options_0_value.h
@@ -0,0 +1,122 @@
+#ifndef PRJXRAY_LIB_XILINX_XC7SERIES_CONFIGURATION_OPTIONS_0_VALUE_H
+#define PRJXRAY_LIB_XILINX_XC7SERIES_CONFIGURATION_OPTIONS_0_VALUE_H
+
+#include <prjxray/bit_ops.h>
+#include <prjxray/xilinx/xc7series/configuration_packet.h>
+#include <prjxray/xilinx/xc7series/configuration_register.h>
+
+namespace prjxray {
+namespace xilinx {
+namespace xc7series {
+
+class ConfigurationOptions0Value {
+ public:
+ enum class StartupClockSource : uint32_t {
+ CCLK = 0x0,
+ User = 0x1,
+ JTAG = 0x2,
+ };
+
+ enum class SignalReleaseCycle : uint32_t {
+ Phase1 = 0x0,
+ Phase2 = 0x1,
+ Phase3 = 0x2,
+ Phase4 = 0x3,
+ Phase5 = 0x4,
+ Phase6 = 0x5,
+ TrackDone = 0x6,
+ Keep = 0x7,
+ };
+
+ enum class StallCycle : uint32_t {
+ Phase0 = 0x0,
+ Phase1 = 0x1,
+ Phase2 = 0x2,
+ Phase3 = 0x3,
+ Phase4 = 0x4,
+ Phase5 = 0x5,
+ Phase6 = 0x6,
+ NoWait = 0x7,
+ };
+
+ ConfigurationOptions0Value() : value_(0) {}
+
+ operator uint32_t() const { return value_; }
+
+ ConfigurationOptions0Value& SetUseDonePinAsPowerdownStatus(
+ bool enabled) {
+ value_ = bit_field_set(value_, 27, 27, enabled ? 1 : 0);
+ return *this;
+ }
+
+ ConfigurationOptions0Value& SetAddPipelineStageForDoneIn(bool enabled) {
+ value_ = bit_field_set(value_, 25, 25, enabled ? 1 : 0);
+ return *this;
+ }
+
+ ConfigurationOptions0Value& SetDriveDoneHigh(bool enabled) {
+ value_ = bit_field_set(value_, 24, 24, enabled);
+ return *this;
+ }
+
+ ConfigurationOptions0Value& SetReadbackIsSingleShot(bool enabled) {
+ value_ = bit_field_set(value_, 23, 23, enabled);
+ return *this;
+ }
+
+ ConfigurationOptions0Value& SetCclkFrequency(uint32_t mhz) {
+ value_ = bit_field_set(value_, 22, 17, mhz);
+ return *this;
+ }
+
+ ConfigurationOptions0Value& SetStartupClockSource(
+ StartupClockSource source) {
+ value_ = bit_field_set(value_, 16, 15,
+ static_cast<uint32_t>(source));
+ return *this;
+ }
+
+ ConfigurationOptions0Value& SetReleaseDonePinAtStartupCycle(
+ SignalReleaseCycle cycle) {
+ value_ =
+ bit_field_set(value_, 14, 12, static_cast<uint32_t>(cycle));
+ return *this;
+ }
+
+ ConfigurationOptions0Value& SetStallAtStartupCycleUntilDciMatch(
+ StallCycle cycle) {
+ value_ =
+ bit_field_set(value_, 11, 9, static_cast<uint32_t>(cycle));
+ return *this;
+ };
+
+ ConfigurationOptions0Value& SetStallAtStartupCycleUntilMmcmLock(
+ StallCycle cycle) {
+ value_ =
+ bit_field_set(value_, 8, 6, static_cast<uint32_t>(cycle));
+ return *this;
+ };
+
+ ConfigurationOptions0Value& SetReleaseGtsSignalAtStartupCycle(
+ SignalReleaseCycle cycle) {
+ value_ =
+ bit_field_set(value_, 5, 3, static_cast<uint32_t>(cycle));
+ return *this;
+ }
+
+ ConfigurationOptions0Value& SetReleaseGweSignalAtStartupCycle(
+ SignalReleaseCycle cycle) {
+ value_ =
+ bit_field_set(value_, 2, 0, static_cast<uint32_t>(cycle));
+ return *this;
+ }
+
+ private:
+ uint32_t value_;
+}; // namespace xc7series
+
+} // namespace xc7series
+} // namespace xilinx
+} // namespace prjxray
+
+#endif // PRJXRAY_LIB_XILINX_XC7SERIES_CONFIGURATION_OPTIONS_0_VALUE_H
diff --git a/lib/include/prjxray/xilinx/xc7series/configuration_packet_with_payload.h b/lib/include/prjxray/xilinx/xc7series/configuration_packet_with_payload.h
new file mode 100644
index 0000000..bdcdc3c
--- /dev/null
+++ b/lib/include/prjxray/xilinx/xc7series/configuration_packet_with_payload.h
@@ -0,0 +1,33 @@
+#ifndef PRJXRAY_LIB_XILINX_XC7SERIES_g_CONFIGURATION_PACKET_WITH_PAYLOAD_H
+#define PRJXRAY_LIB_XILINX_XC7SERIES_g_CONFIGURATION_PACKET_WITH_PAYLOAD_H
+
+#include <memory>
+
+#include <absl/types/span.h>
+#include <prjxray/bit_ops.h>
+#include <prjxray/xilinx/xc7series/configuration_packet.h>
+#include <prjxray/xilinx/xc7series/configuration_register.h>
+
+namespace prjxray {
+namespace xilinx {
+namespace xc7series {
+
+template <int Words>
+class ConfigurationPacketWithPayload : public ConfigurationPacket {
+ public:
+ ConfigurationPacketWithPayload(
+ Opcode op,
+ ConfigurationRegister reg,
+ const std::array<uint32_t, Words>& payload)
+ : ConfigurationPacket(1, op, reg, absl::Span<uint32_t>(payload_)),
+ payload_(std::move(payload)) {}
+
+ private:
+ std::array<uint32_t, Words> payload_;
+}; // namespace xc7series
+
+} // namespace xc7series
+} // namespace xilinx
+} // namespace prjxray
+
+#endif // PRJXRAY_LIB_XILINX_XC7SERIES_g_CONFIGURATION_PACKET_WITH_PAYLOAD_H
diff --git a/lib/include/prjxray/xilinx/xc7series/configuration_register.h b/lib/include/prjxray/xilinx/xc7series/configuration_register.h
index 9f75a09..4fbc5d4 100644
--- a/lib/include/prjxray/xilinx/xc7series/configuration_register.h
+++ b/lib/include/prjxray/xilinx/xc7series/configuration_register.h
@@ -25,6 +25,7 @@
COR1 = 0x0e,
WBSTAR = 0x10,
TIMER = 0x11,
+ UNKNOWN = 0x13,
BOOTSTS = 0x16,
CTL1 = 0x18,
BSPI = 0x1F,
diff --git a/lib/include/prjxray/xilinx/xc7series/nop_packet.h b/lib/include/prjxray/xilinx/xc7series/nop_packet.h
new file mode 100644
index 0000000..6533988
--- /dev/null
+++ b/lib/include/prjxray/xilinx/xc7series/nop_packet.h
@@ -0,0 +1,24 @@
+#ifndef PRJXRAY_LIB_XILINX_XC7SERIES_NOP_PACKET_H
+#define PRJXRAY_LIB_XILINX_XC7SERIES_NOP_PACKET_H
+
+#include <prjxray/xilinx/xc7series/configuration_packet.h>
+#include <prjxray/xilinx/xc7series/configuration_register.h>
+
+namespace prjxray {
+namespace xilinx {
+namespace xc7series {
+
+class NopPacket : public ConfigurationPacket {
+ public:
+ NopPacket()
+ : ConfigurationPacket(1,
+ Opcode::NOP,
+ ConfigurationRegister::CRC,
+ {}) {}
+};
+
+} // namespace xc7series
+} // namespace xilinx
+} // namespace prjxray
+
+#endif // PRJXRAY_LIB_XILINX_XC7SERIES_NOP_PACKET_H
diff --git a/lib/xilinx/xc7series/bitstream_writer.cc b/lib/xilinx/xc7series/bitstream_writer.cc
index 3a7da30..eb388ca 100644
--- a/lib/xilinx/xc7series/bitstream_writer.cc
+++ b/lib/xilinx/xc7series/bitstream_writer.cc
@@ -28,7 +28,7 @@
BitstreamWriter::packet_iterator BitstreamWriter::iterator::packet_begin() {
// itr_packets = packets.begin();
- const ConfigurationPacket& packet = *itr_packets_;
+ const ConfigurationPacket& packet = **itr_packets_;
return BitstreamWriter::packet_iterator(
&packet, BitstreamWriter::packet_iterator::STATE_HEADER,
@@ -36,7 +36,7 @@
}
BitstreamWriter::packet_iterator BitstreamWriter::iterator::packet_end() {
- const ConfigurationPacket& packet = *itr_packets_;
+ const ConfigurationPacket& packet = **itr_packets_;
return BitstreamWriter::packet_iterator(
&packet, BitstreamWriter::packet_iterator::STATE_END,
@@ -138,7 +138,7 @@
if (itr_packets != packets_.end()) {
// op_packet_itr = packet_begin();
// FIXME: de-duplicate this
- const ConfigurationPacket& packet = *itr_packets;
+ const ConfigurationPacket& packet = **itr_packets;
packet_iterator packet_itr =
packet_iterator(&packet, packet_iterator::STATE_HEADER,
packet.data().begin());
diff --git a/lib/xilinx/xc7series/bitstream_writer_test.cc b/lib/xilinx/xc7series/bitstream_writer_test.cc
index 752fa4c..be2d41e 100644
--- a/lib/xilinx/xc7series/bitstream_writer_test.cc
+++ b/lib/xilinx/xc7series/bitstream_writer_test.cc
@@ -50,7 +50,8 @@
}
// 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
/*
static std::vector<uint32_t> words{0x00000000};
@@ -61,27 +62,32 @@
static std::vector<uint32_t> words{};
absl::Span<uint32_t> word_span(words);
// CRC is config value 0
- packets.push_back(xc7series::ConfigurationPacket(
+ packets.emplace_back(new xc7series::ConfigurationPacket(
0, xc7series::ConfigurationPacket::NOP,
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};
absl::Span<uint32_t> word_span(words);
auto packet = xc7series::ConfigurationPacket::InitWithWords(word_span);
- packets.push_back(*(packet.second));
+ packets.emplace_back(
+ new xc7series::ConfigurationPacket(*(packet.second)));
}
// 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)};
absl::Span<uint32_t> word_span(words);
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
// Without this InitWithWords will fail on type 2
xc7series::ConfigurationPacket* packet1;
@@ -90,8 +96,9 @@
absl::Span<uint32_t> word_span(words);
auto packet1_pair =
xc7series::ConfigurationPacket::InitWithWords(word_span);
- packets.push_back(*(packet1_pair.second));
- packet1 = &packets[0];
+ packets.emplace_back(
+ new xc7series::ConfigurationPacket(*(packet1_pair.second)));
+ packet1 = packets[0].get();
}
// Type 2 packet with data
{
@@ -100,13 +107,14 @@
absl::Span<uint32_t> word_span(words);
auto packet = xc7series::ConfigurationPacket::InitWithWords(
word_span, packet1);
- packets.push_back(*(packet.second));
+ packets.emplace_back(
+ new xc7series::ConfigurationPacket(*(packet.second)));
}
}
// Empty packets should produce just the header
TEST(BitstreamWriterTest, WriteHeader) {
- std::vector<xc7series::ConfigurationPacket> packets;
+ std::vector<std::unique_ptr<xc7series::ConfigurationPacket>> packets;
xc7series::BitstreamWriter writer(packets);
std::vector<uint32_t> words(writer.begin(), writer.end());
@@ -120,7 +128,7 @@
}
TEST(BitstreamWriterTest, WriteType0) {
- std::vector<xc7series::ConfigurationPacket> packets;
+ std::vector<std::unique_ptr<xc7series::ConfigurationPacket>> packets;
AddType0(packets);
xc7series::BitstreamWriter writer(packets);
// dump_packets(writer, false);
@@ -133,7 +141,7 @@
EXPECT_EQ(words, ref);
}
TEST(BitstreamWriterTest, WriteType1) {
- std::vector<xc7series::ConfigurationPacket> packets;
+ std::vector<std::unique_ptr<xc7series::ConfigurationPacket>> packets;
AddType1(packets);
xc7series::BitstreamWriter writer(packets);
// dump_packets(writer, false);
@@ -147,7 +155,7 @@
}
TEST(BitstreamWriterTest, WriteType2) {
- std::vector<xc7series::ConfigurationPacket> packets;
+ std::vector<std::unique_ptr<xc7series::ConfigurationPacket>> packets;
AddType2(packets);
xc7series::BitstreamWriter writer(packets);
// dump_packets(writer, false);
@@ -164,7 +172,7 @@
}
TEST(BitstreamWriterTest, WriteMulti) {
- std::vector<xc7series::ConfigurationPacket> packets;
+ std::vector<std::unique_ptr<xc7series::ConfigurationPacket>> packets;
AddType1(packets);
AddType1E(packets);
AddType2(packets);
diff --git a/minitests/partial_reconfig_flow/Makefile b/minitests/partial_reconfig_flow/Makefile
index f451f81..239cac4 100644
--- a/minitests/partial_reconfig_flow/Makefile
+++ b/minitests/partial_reconfig_flow/Makefile
@@ -1,4 +1,4 @@
-.PRECIOUS: harness_impl.dcp %_impl.dcp %.bit
+.PRECIOUS: harness_impl.dcp %_impl.dcp %.bit %_roi_partial.bit
# Top-level target for generating a programmable bitstream. Given a .fasm
# file, calling make with the .fasm extension replaced with _hand_crafted.bit
@@ -6,49 +6,14 @@
# ready for programming to a board. For example,
# 'make inv_hand_crafted.bit' will generate a bitstream that includes the
# design from roi_noninv.fasm.
-%_hand_crafted.bit: init_sequence.bit %_no_headers.bin final_sequence.bin
- cat $^ > $@
-
-%_no_headers.bin: %_patched.bin
- # WARNING: these values need to be tweaked if anything about the
- # Vivado-generated design changes.
- xxd -p -s 0x18 $< | xxd -r -p - $@
-
-%_patched.bin: %_roi_partial.frm harness.bit
+%_hand_crafted.bit: %_roi_partial.frm harness.bit
${XRAY_TOOLS_DIR}/xc7patch \
- --part_file ${XRAY_PART_YAML} \
+ --part_name "${XRAY_PART}" \
+ --part_file "${XRAY_PART_YAML}" \
--bitstream_file harness.bit \
--frm_file $< \
--output_file $@
-# xc7patch currently only generates the actual frame writes which is
-# insufficient to program a device. Grab the initialization and finalization
-# sequences from the harness bitstream so they can be tacked on to the
-# xc7patch-generated bitstream to create a programmable bitstream.
-#
-# The offsets used below were determined by manually inspecting
-# harness.bit with a hex editor. init_sequence.bit is the beginning of
-# the file until just before the actual frame data is sent via a write to FDRI.
-# final_sequence.bin is from just after the frame data write to the end of the
-# file. Note that final_sequence.bin normally includes at least one CRC check.
-# The sed command replaces any CRC checks with a Reset CRC command which is the
-# same behavior as setting BITSTREAM.GENERAL.CRC to Disabled. These offset
-# should not change unless you alter the bitstream format used (i.e. setting
-# BITSTREAM.GENERAL.DEBUGBITSTREAM or BITSTREAM.GENERAL.PERFRAMECRC to YES).
-init_sequence.bit: harness.bit
- # WARNING: these values need to be tweaked if anything about the
- # Vivado-generated design changes.
- xxd -p -l 0x147 $< | xxd -r -p - $@
-
-final_sequence.bin: harness.bit
- # WARNING: these values need to be tweaked if anything about the
- # Vivado-generated design changes.
- xxd -p -s 0x216abf $< | \
- tr -d '\n' | \
- sed -e 's/30000001.\{8\}/3000800100000007/g' | \
- fold -w 40 | \
- xxd -r -p - $@
-
# Generate a suitable harness by using Vivado's partial reconfiguration
# feature. inv.v is used as a sample reconfiguration design as one is
# required to generate a partial reconfiguration design.
diff --git a/minitests/roi_harness/fasm2bit.sh b/minitests/roi_harness/fasm2bit.sh
index 3e7798c..5beb90f 100755
--- a/minitests/roi_harness/fasm2bit.sh
+++ b/minitests/roi_harness/fasm2bit.sh
@@ -30,28 +30,11 @@
${XRAY_DIR}/tools/fasm2frame.py $fasm_in roi_partial.frm
${XRAY_TOOLS_DIR}/xc7patch \
+ --part_name ${XRAY_PART} \
--part_file ${XRAY_PART_YAML} \
--bitstream_file $bit_in \
--frm_file roi_partial.frm \
- --output_file patched.bin
-
-# WARNING: these values need to be tweaked if anything about the
-# Vivado-generated design changes.
-xxd -p -l 0x147 $bit_in | xxd -r -p - init_sequence.bit
-
-# WARNING: these values need to be tweaked if anything about the
-# Vivado-generated design changes.
-xxd -p -s 0x18 patched.bin | xxd -r -p - no_headers.bin
-
-# WARNING: these values need to be tweaked if anything about the
-# Vivado-generated design changes.
-xxd -p -s 0x216abf $bit_in | \
- tr -d '\n' | \
- sed -e 's/30000001.\{8\}/3000800100000007/g' | \
- fold -w 40 | \
- xxd -r -p - final_sequence.bin
-
-cat init_sequence.bit no_headers.bin final_sequence.bin >$bit_out
+ --output_file $bit_out
#openocd -f $XRAY_DIR/utils/openocd/board-digilent-basys3.cfg -c "init; pld load 0 $bit_out; exit"
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 06dc18c..85023a9 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -21,6 +21,7 @@
add_executable(xc7patch xc7patch.cc)
target_link_libraries(xc7patch
absl::strings
+ absl::time
gflags
libprjxray
)
diff --git a/tools/xc7patch.cc b/tools/xc7patch.cc
index 3e0c549..9ea3962 100644
--- a/tools/xc7patch.cc
+++ b/tools/xc7patch.cc
@@ -5,14 +5,23 @@
#include <string>
#include <vector>
+#include <absl/strings/str_cat.h>
#include <absl/strings/str_split.h>
+#include <absl/time/clock.h>
+#include <absl/time/time.h>
#include <gflags/gflags.h>
#include <prjxray/memory_mapped_file.h>
#include <prjxray/xilinx/xc7series/bitstream_reader.h>
#include <prjxray/xilinx/xc7series/bitstream_writer.h>
+#include <prjxray/xilinx/xc7series/command.h>
#include <prjxray/xilinx/xc7series/configuration.h>
+#include <prjxray/xilinx/xc7series/configuration_options_0_value.h>
+#include <prjxray/xilinx/xc7series/configuration_packet_with_payload.h>
+#include <prjxray/xilinx/xc7series/ecc.h>
+#include <prjxray/xilinx/xc7series/nop_packet.h>
#include <prjxray/xilinx/xc7series/part.h>
+DEFINE_string(part_name, "", "");
DEFINE_string(part_file, "", "Definition file for target 7-series part");
DEFINE_string(bitstream_file,
"",
@@ -111,54 +120,16 @@
uint32_t ecc = 0;
for (size_t ii = 0; ii < frame_data.size(); ++ii) {
- uint32_t word = frame_data[ii];
- uint32_t offset = ii * 32;
- if (ii > 0x25) {
- offset += 0x1360;
- } else if (ii > 0x6) {
- offset += 0x1340;
- } else {
- offset += 0x1320;
- }
-
- // Mask out where the ECC should be.
- if (ii == 0x32) {
- word &= 0xFFFFE000;
- }
-
- for (int jj = 0; jj < 32; ++jj) {
- if ((word & 1) == 1) {
- ecc ^= offset + jj;
- }
- word >>= 1;
- }
+ ecc = xc7series::icap_ecc(ii, frame_data[ii], ecc);
}
- uint32_t v = ecc & 0xFFF;
- v ^= v >> 8;
- v ^= v >> 4;
- v ^= v >> 2;
- v ^= v >> 1;
- ecc ^= (v & 1) << 12;
-
// Replace the old ECC with the new.
frame_data[0x32] &= 0xFFFFE000;
frame_data[0x32] |= (ecc & 0x1FFF);
}
-#if 0
- for (auto& frame : frames) {
- std::cout << "0x" << std::hex
- << static_cast<uint32_t>(frame.first) << " ";
-
- for (auto& word : frame.second) {
- std::cout << "0x" << std::hex << word << ",";
- }
-
- std::cout << std::endl;
- }
-#endif
- 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.
std::vector<uint32_t> packet_data;
@@ -177,18 +148,167 @@
}
packet_data.insert(packet_data.end(), 202, 0);
- out_packets.push_back(xc7series::ConfigurationPacket(
+ // Initialization sequence
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::TIMER, {0x0}));
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::WBSTAR, {0x0}));
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::CMD,
+ {static_cast<uint32_t>(xc7series::Command::NOP)}));
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::CMD,
+ {static_cast<uint32_t>(xc7series::Command::RCRC)}));
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::UNKNOWN, {0x0}));
+
+ // Configuration Options 0
+ out_packets.emplace_back(new xc7series::ConfigurationPacketWithPayload<
+ 1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::COR0,
+ {xc7series::ConfigurationOptions0Value()
+ .SetAddPipelineStageForDoneIn(true)
+ .SetReleaseDonePinAtStartupCycle(
+ xc7series::ConfigurationOptions0Value::SignalReleaseCycle::
+ Phase4)
+ .SetStallAtStartupCycleUntilDciMatch(
+ xc7series::ConfigurationOptions0Value::StallCycle::NoWait)
+ .SetStallAtStartupCycleUntilMmcmLock(
+ xc7series::ConfigurationOptions0Value::StallCycle::NoWait)
+ .SetReleaseGtsSignalAtStartupCycle(
+ xc7series::ConfigurationOptions0Value::SignalReleaseCycle::
+ Phase5)
+ .SetReleaseGweSignalAtStartupCycle(
+ xc7series::ConfigurationOptions0Value::SignalReleaseCycle::
+ Phase6)}));
+
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::COR1, {0x0}));
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::IDCODE, {part->idcode()}));
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::CMD,
+ {static_cast<uint32_t>(xc7series::Command::SWITCH)}));
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::MASK, {0x401}));
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::CTL0, {0x501}));
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::MASK, {0x0}));
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::CTL1, {0x0}));
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::FAR, {0x0}));
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::CMD,
+ {static_cast<uint32_t>(xc7series::Command::WCFG)}));
+ out_packets.emplace_back(new xc7series::NopPacket());
+
+ // Frame data write
+ out_packets.emplace_back(new xc7series::ConfigurationPacket(
1, xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::FDRI, {}));
- out_packets.push_back(xc7series::ConfigurationPacket(
+ out_packets.emplace_back(new xc7series::ConfigurationPacket(
2, xc7series::ConfigurationPacket::Opcode::Write,
xc7series::ConfigurationRegister::FDRI, packet_data));
-#if 0
- for (auto& packet : out_packets) {
- std::cout << packet << std::endl;
+ // Finalization sequence
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::CMD,
+ {static_cast<uint32_t>(xc7series::Command::RCRC)}));
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::CMD,
+ {static_cast<uint32_t>(xc7series::Command::GRESTORE)}));
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::CMD,
+ {static_cast<uint32_t>(xc7series::Command::LFRM)}));
+ for (int ii = 0; ii < 100; ++ii) {
+ out_packets.emplace_back(new xc7series::NopPacket());
}
-#endif
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::CMD,
+ {static_cast<uint32_t>(xc7series::Command::START)}));
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::FAR, {0x3be0000}));
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::MASK, {0x501}));
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::CTL0, {0x501}));
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::CMD,
+ {static_cast<uint32_t>(xc7series::Command::RCRC)}));
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(new xc7series::NopPacket());
+ out_packets.emplace_back(
+ new xc7series::ConfigurationPacketWithPayload<1>(
+ xc7series::ConfigurationPacket::Opcode::Write,
+ xc7series::ConfigurationRegister::CMD,
+ {static_cast<uint32_t>(xc7series::Command::DESYNC)}));
+ for (int ii = 0; ii < 400; ++ii) {
+ out_packets.emplace_back(new xc7series::NopPacket());
+ }
// Write bitstream.
xc7series::BitstreamWriter out_bitstream_writer(out_packets);
@@ -199,6 +319,61 @@
return 1;
}
+ // Xilinx BIT header.
+ // Sync header
+ std::vector<uint8_t> bit_header{0x0, 0x9, 0x0f, 0xf0, 0x0f,
+ 0xf0, 0x0f, 0xf0, 0x0f, 0xf0,
+ 0x00, 0x00, 0x01, 'a'};
+ auto build_source = absl::StrCat(FLAGS_frm_file, ";Generator=xc7patch");
+ bit_header.push_back(
+ static_cast<uint8_t>((build_source.size() + 1) >> 8));
+ bit_header.push_back(static_cast<uint8_t>(build_source.size() + 1));
+ bit_header.insert(bit_header.end(), build_source.begin(),
+ build_source.end());
+ bit_header.push_back(0x0);
+
+ // Source file.
+ bit_header.push_back('b');
+ bit_header.push_back(
+ static_cast<uint8_t>((FLAGS_part_name.size() + 1) >> 8));
+ bit_header.push_back(static_cast<uint8_t>(FLAGS_part_name.size() + 1));
+ bit_header.insert(bit_header.end(), FLAGS_part_name.begin(),
+ FLAGS_part_name.end());
+ bit_header.push_back(0x0);
+
+ // Build timestamp.
+ auto build_time = absl::Now();
+ auto build_date_string =
+ absl::FormatTime("%E4Y/%m/%d", build_time, absl::UTCTimeZone());
+ auto build_time_string =
+ absl::FormatTime("%H:%M:%S", build_time, absl::UTCTimeZone());
+
+ bit_header.push_back('c');
+ bit_header.push_back(
+ static_cast<uint8_t>((build_date_string.size() + 1) >> 8));
+ bit_header.push_back(
+ static_cast<uint8_t>(build_date_string.size() + 1));
+ bit_header.insert(bit_header.end(), build_date_string.begin(),
+ build_date_string.end());
+ bit_header.push_back(0x0);
+
+ bit_header.push_back('d');
+ bit_header.push_back(
+ static_cast<uint8_t>((build_time_string.size() + 1) >> 8));
+ bit_header.push_back(
+ static_cast<uint8_t>(build_time_string.size() + 1));
+ bit_header.insert(bit_header.end(), build_time_string.begin(),
+ build_time_string.end());
+ bit_header.push_back(0x0);
+
+ bit_header.insert(bit_header.end(), {'e', 0x0, 0x0, 0x0, 0x0});
+ out_file.write(reinterpret_cast<const char*>(bit_header.data()),
+ bit_header.size());
+
+ auto end_of_header_pos = out_file.tellp();
+ auto header_data_length_pos =
+ end_of_header_pos - static_cast<std::ofstream::off_type>(4);
+
for (uint32_t word : out_bitstream_writer) {
out_file.put((word >> 24) & 0xFF);
out_file.put((word >> 16) & 0xFF);
@@ -206,5 +381,13 @@
out_file.put((word)&0xFF);
}
+ uint32_t length_of_data = out_file.tellp() - end_of_header_pos;
+
+ out_file.seekp(header_data_length_pos);
+ out_file.put((length_of_data >> 24) & 0xFF);
+ out_file.put((length_of_data >> 16) & 0xFF);
+ out_file.put((length_of_data >> 8) & 0xFF);
+ out_file.put((length_of_data)&0xFF);
+
return 0;
}