From 61b6a9dfe7803e438583dfec22e2d953f7b76758 Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Thu, 1 Feb 2018 12:19:00 -0800 Subject: [PATCH 01/13] xc7patch: use ECC calculation from lib Signed-off-by: Rick Altherr --- tools/xc7patch.cc | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/tools/xc7patch.cc b/tools/xc7patch.cc index 3e0c549f..4237315e 100644 --- a/tools/xc7patch.cc +++ b/tools/xc7patch.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include DEFINE_string(part_file, "", "Definition file for target 7-series part"); @@ -111,36 +112,9 @@ int main(int argc, char* argv[]) { 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); From f5099113e666bb98f326c09384108b97b3c24aa2 Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Thu, 1 Feb 2018 12:29:01 -0800 Subject: [PATCH 02/13] xc7patch: remove disabled debug code Signed-off-by: Rick Altherr --- tools/xc7patch.cc | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/tools/xc7patch.cc b/tools/xc7patch.cc index 4237315e..fc4bc6ad 100644 --- a/tools/xc7patch.cc +++ b/tools/xc7patch.cc @@ -120,18 +120,6 @@ int main(int argc, char* argv[]) { frame_data[0x32] |= (ecc & 0x1FFF); } -#if 0 - for (auto& frame : frames) { - std::cout << "0x" << std::hex - << static_cast(frame.first) << " "; - - for (auto& word : frame.second) { - std::cout << "0x" << std::hex << word << ","; - } - - std::cout << std::endl; - } -#endif std::vector out_packets; // Generate a single type 2 packet that writes everything at once. @@ -158,12 +146,6 @@ int main(int argc, char* argv[]) { 2, xc7series::ConfigurationPacket::Opcode::Write, xc7series::ConfigurationRegister::FDRI, packet_data)); -#if 0 - for (auto& packet : out_packets) { - std::cout << packet << std::endl; - } -#endif - // Write bitstream. xc7series::BitstreamWriter out_bitstream_writer(out_packets); std::ofstream out_file(FLAGS_output_file); From 43b70caf03aae086a96fda2f8465ec478ac77fcd Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Thu, 1 Feb 2018 12:11:25 -0800 Subject: [PATCH 03/13] 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 --- .../xilinx/xc7series/bitstream_writer.h | 2 +- lib/xilinx/xc7series/bitstream_writer.cc | 6 +-- lib/xilinx/xc7series/bitstream_writer_test.cc | 38 +++++++++++-------- tools/xc7patch.cc | 8 ++-- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/lib/include/prjxray/xilinx/xc7series/bitstream_writer.h b/lib/include/prjxray/xilinx/xc7series/bitstream_writer.h index ae0634d7..806cc9a2 100644 --- a/lib/include/prjxray/xilinx/xc7series/bitstream_writer.h +++ b/lib/include/prjxray/xilinx/xc7series/bitstream_writer.h @@ -23,7 +23,7 @@ namespace xc7series { class BitstreamWriter { public: typedef std::array header_t; - typedef std::vector packets_t; + typedef std::vector> packets_t; // Only defined if a packet exists typedef absl::optional> op_data_t; typedef absl::Span::iterator data_iterator_t; diff --git a/lib/xilinx/xc7series/bitstream_writer.cc b/lib/xilinx/xc7series/bitstream_writer.cc index 3a7da30d..eb388ca5 100644 --- a/lib/xilinx/xc7series/bitstream_writer.cc +++ b/lib/xilinx/xc7series/bitstream_writer.cc @@ -28,7 +28,7 @@ BitstreamWriter::BitstreamWriter(const packets_t& packets) 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_begin() { } 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 @@ BitstreamWriter::iterator BitstreamWriter::begin() { 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 752fa4c9..be2d41ec 100644 --- a/lib/xilinx/xc7series/bitstream_writer_test.cc +++ b/lib/xilinx/xc7series/bitstream_writer_test.cc @@ -50,7 +50,8 @@ void dump_packets(xc7series::BitstreamWriter writer, bool nl = true) { } // Special all 0's -void AddType0(std::vector& packets) { +void AddType0( + std::vector>& packets) { // InitWithWords doesn't like type 0 /* static std::vector words{0x00000000}; @@ -61,27 +62,32 @@ void AddType0(std::vector& packets) { static std::vector words{}; absl::Span 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& packets) { +void AddType1( + std::vector>& packets) { static std::vector words{MakeType1(0x2, 0x3, 2), 0xAA, 0xBB}; absl::Span 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& packets) { +void AddType1E( + std::vector>& packets) { static std::vector words{MakeType1(0x2, 0x3, 0)}; absl::Span 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& packets) { +void AddType2( + std::vector>& packets) { // Type 1 packet with address // Without this InitWithWords will fail on type 2 xc7series::ConfigurationPacket* packet1; @@ -90,8 +96,9 @@ void AddType2(std::vector& packets) { absl::Span 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 @@ void AddType2(std::vector& packets) { absl::Span 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 packets; + std::vector> packets; xc7series::BitstreamWriter writer(packets); std::vector words(writer.begin(), writer.end()); @@ -120,7 +128,7 @@ TEST(BitstreamWriterTest, WriteHeader) { } TEST(BitstreamWriterTest, WriteType0) { - std::vector packets; + std::vector> packets; AddType0(packets); xc7series::BitstreamWriter writer(packets); // dump_packets(writer, false); @@ -133,7 +141,7 @@ TEST(BitstreamWriterTest, WriteType0) { EXPECT_EQ(words, ref); } TEST(BitstreamWriterTest, WriteType1) { - std::vector packets; + std::vector> packets; AddType1(packets); xc7series::BitstreamWriter writer(packets); // dump_packets(writer, false); @@ -147,7 +155,7 @@ TEST(BitstreamWriterTest, WriteType1) { } TEST(BitstreamWriterTest, WriteType2) { - std::vector packets; + std::vector> packets; AddType2(packets); xc7series::BitstreamWriter writer(packets); // dump_packets(writer, false); @@ -164,7 +172,7 @@ TEST(BitstreamWriterTest, WriteType2) { } TEST(BitstreamWriterTest, WriteMulti) { - std::vector packets; + std::vector> packets; AddType1(packets); AddType1E(packets); AddType2(packets); diff --git a/tools/xc7patch.cc b/tools/xc7patch.cc index fc4bc6ad..b3ebf6ff 100644 --- a/tools/xc7patch.cc +++ b/tools/xc7patch.cc @@ -120,7 +120,8 @@ int main(int argc, char* argv[]) { frame_data[0x32] |= (ecc & 0x1FFF); } - std::vector out_packets; + std::vector> + out_packets; // Generate a single type 2 packet that writes everything at once. std::vector packet_data; @@ -139,10 +140,11 @@ int main(int argc, char* argv[]) { } 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, 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)); From 2a1154ec169f48ba23a04f01199c2d674f2cecf4 Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Thu, 1 Feb 2018 12:20:02 -0800 Subject: [PATCH 04/13] lib: xc7series: config packet subclass that owns the payload Signed-off-by: Rick Altherr --- .../configuration_packet_with_payload.h | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 lib/include/prjxray/xilinx/xc7series/configuration_packet_with_payload.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 00000000..bdcdc3c3 --- /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 + +#include +#include +#include +#include + +namespace prjxray { +namespace xilinx { +namespace xc7series { + +template +class ConfigurationPacketWithPayload : public ConfigurationPacket { + public: + ConfigurationPacketWithPayload( + Opcode op, + ConfigurationRegister reg, + const std::array& payload) + : ConfigurationPacket(1, op, reg, absl::Span(payload_)), + payload_(std::move(payload)) {} + + private: + std::array payload_; +}; // namespace xc7series + +} // namespace xc7series +} // namespace xilinx +} // namespace prjxray + +#endif // PRJXRAY_LIB_XILINX_XC7SERIES_g_CONFIGURATION_PACKET_WITH_PAYLOAD_H From ab1e60c037629751ab28ffa07dd4f554ff8a49bc Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Thu, 1 Feb 2018 12:20:48 -0800 Subject: [PATCH 05/13] lib: xc7series: add undocumented register used in init sequence Signed-off-by: Rick Altherr --- lib/include/prjxray/xilinx/xc7series/configuration_register.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/include/prjxray/xilinx/xc7series/configuration_register.h b/lib/include/prjxray/xilinx/xc7series/configuration_register.h index 9f75a090..4fbc5d4c 100644 --- a/lib/include/prjxray/xilinx/xc7series/configuration_register.h +++ b/lib/include/prjxray/xilinx/xc7series/configuration_register.h @@ -25,6 +25,7 @@ enum class ConfigurationRegister : unsigned int { COR1 = 0x0e, WBSTAR = 0x10, TIMER = 0x11, + UNKNOWN = 0x13, BOOTSTS = 0x16, CTL1 = 0x18, BSPI = 0x1F, From 80004a373708f261ba73cc985de17e4f67fbf3b9 Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Thu, 1 Feb 2018 12:21:22 -0800 Subject: [PATCH 06/13] lib: xc7series: config packet subclass for NOPs Signed-off-by: Rick Altherr --- .../prjxray/xilinx/xc7series/nop_packet.h | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 lib/include/prjxray/xilinx/xc7series/nop_packet.h 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 00000000..65339883 --- /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 +#include + +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 From a4fb9ff7d8369ab7472c290bbc00cd6416f56a8e Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Thu, 1 Feb 2018 12:25:45 -0800 Subject: [PATCH 07/13] lib: xc7series: define known CMD register values Signed-off-by: Rick Altherr --- .../prjxray/xilinx/xc7series/command.h | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 lib/include/prjxray/xilinx/xc7series/command.h diff --git a/lib/include/prjxray/xilinx/xc7series/command.h b/lib/include/prjxray/xilinx/xc7series/command.h new file mode 100644 index 00000000..2ff16e86 --- /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_ From 0fc3ba04009fd0de4accdfd9338f29e15bece321 Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Thu, 1 Feb 2018 12:27:39 -0800 Subject: [PATCH 08/13] lib: xc7series: implement builder pattern for generating COR0 values Signed-off-by: Rick Altherr --- .../xc7series/configuration_options_0_value.h | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 lib/include/prjxray/xilinx/xc7series/configuration_options_0_value.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 00000000..1b7c1c13 --- /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 +#include +#include + +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(source)); + return *this; + } + + ConfigurationOptions0Value& SetReleaseDonePinAtStartupCycle( + SignalReleaseCycle cycle) { + value_ = + bit_field_set(value_, 14, 12, static_cast(cycle)); + return *this; + } + + ConfigurationOptions0Value& SetStallAtStartupCycleUntilDciMatch( + StallCycle cycle) { + value_ = + bit_field_set(value_, 11, 9, static_cast(cycle)); + return *this; + }; + + ConfigurationOptions0Value& SetStallAtStartupCycleUntilMmcmLock( + StallCycle cycle) { + value_ = + bit_field_set(value_, 8, 6, static_cast(cycle)); + return *this; + }; + + ConfigurationOptions0Value& SetReleaseGtsSignalAtStartupCycle( + SignalReleaseCycle cycle) { + value_ = + bit_field_set(value_, 5, 3, static_cast(cycle)); + return *this; + } + + ConfigurationOptions0Value& SetReleaseGweSignalAtStartupCycle( + SignalReleaseCycle cycle) { + value_ = + bit_field_set(value_, 2, 0, static_cast(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 From b7d01aa9f607a7a503626546b33591fb463078d8 Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Thu, 1 Feb 2018 12:30:33 -0800 Subject: [PATCH 09/13] xc7patch: generate init and final sequences in output bitstream Bitstreams generated by xc7patch can now be directly loaded into parts via Vivado's Hardware Manager (bitstream must have .bin suffix) or by flashing into a boot FLASH. Signed-off-by: Rick Altherr --- tools/xc7patch.cc | 158 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/tools/xc7patch.cc b/tools/xc7patch.cc index b3ebf6ff..245d6e65 100644 --- a/tools/xc7patch.cc +++ b/tools/xc7patch.cc @@ -10,8 +10,12 @@ #include #include #include +#include #include +#include +#include #include +#include #include DEFINE_string(part_file, "", "Definition file for target 7-series part"); @@ -140,6 +144,104 @@ int main(int argc, char* argv[]) { } packet_data.insert(packet_data.end(), 202, 0); + // 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(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(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(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(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, @@ -148,6 +250,62 @@ int main(int argc, char* argv[]) { 2, xc7series::ConfigurationPacket::Opcode::Write, xc7series::ConfigurationRegister::FDRI, packet_data)); + // Finalization sequence + out_packets.emplace_back( + new xc7series::ConfigurationPacketWithPayload<1>( + xc7series::ConfigurationPacket::Opcode::Write, + xc7series::ConfigurationRegister::CMD, + {static_cast(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(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(xc7series::Command::LFRM)})); + for (int ii = 0; ii < 100; ++ii) { + out_packets.emplace_back(new xc7series::NopPacket()); + } + out_packets.emplace_back( + new xc7series::ConfigurationPacketWithPayload<1>( + xc7series::ConfigurationPacket::Opcode::Write, + xc7series::ConfigurationRegister::CMD, + {static_cast(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(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(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); std::ofstream out_file(FLAGS_output_file); From 3d33f101bc850a17a2b8540fc70d5ed772d9be83 Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Thu, 1 Feb 2018 12:32:19 -0800 Subject: [PATCH 10/13] xc7patch: Generate Xilinx BIT header in output bitstream Xilinx tools generate and expect an additional header to be added to the bitstream. This header is the only difference between .bit and .bin files and is not required by the part in any way. OpenOCD only supports reading .bit files so the easiest path to a using FOSS tools from FASM down is to generate a .bit header in xc7patch's output. To distinguish xc7patch-generated files from Xilinx-generated files, the source file field includes a Generator tag indicating that the bitstream was produced by xc7patch. Vivado uses the same technique to record the Vivado version in a Version tag. Signed-off-by: Rick Altherr --- tools/CMakeLists.txt | 1 + tools/xc7patch.cc | 67 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 06dc18c0..85023a91 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -21,6 +21,7 @@ target_link_libraries(gen_part_base_yaml 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 245d6e65..9ea3962d 100644 --- a/tools/xc7patch.cc +++ b/tools/xc7patch.cc @@ -5,7 +5,10 @@ #include #include +#include #include +#include +#include #include #include #include @@ -18,6 +21,7 @@ #include #include +DEFINE_string(part_name, "", ""); DEFINE_string(part_file, "", "Definition file for target 7-series part"); DEFINE_string(bitstream_file, "", @@ -315,6 +319,61 @@ int main(int argc, char* argv[]) { return 1; } + // Xilinx BIT header. + // Sync header + std::vector 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((build_source.size() + 1) >> 8)); + bit_header.push_back(static_cast(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((FLAGS_part_name.size() + 1) >> 8)); + bit_header.push_back(static_cast(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((build_date_string.size() + 1) >> 8)); + bit_header.push_back( + static_cast(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((build_time_string.size() + 1) >> 8)); + bit_header.push_back( + static_cast(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(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(4); + for (uint32_t word : out_bitstream_writer) { out_file.put((word >> 24) & 0xFF); out_file.put((word >> 16) & 0xFF); @@ -322,5 +381,13 @@ int main(int argc, char* argv[]) { 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; } From 6b7af3b1686b82773c9b09e0f2692196896b4dc1 Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Thu, 1 Feb 2018 12:38:02 -0800 Subject: [PATCH 11/13] minitests: partial_reconfig_flow: always save ROI bitstreams Signed-off-by: Rick Altherr --- minitests/partial_reconfig_flow/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minitests/partial_reconfig_flow/Makefile b/minitests/partial_reconfig_flow/Makefile index f451f815..58df3cfc 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 From ad150af4dfafadeab2b2ec29ca0e2aead91f411f Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Thu, 1 Feb 2018 10:16:36 -0800 Subject: [PATCH 12/13] minitests: partial_reconfig_flow: Remove init/final sequence hacks Now that xc7series generates proper .bit files, the hacks need to be removed. Signed-off-by: Rick Altherr --- minitests/partial_reconfig_flow/Makefile | 41 ++---------------------- 1 file changed, 3 insertions(+), 38 deletions(-) diff --git a/minitests/partial_reconfig_flow/Makefile b/minitests/partial_reconfig_flow/Makefile index 58df3cfc..239cac4f 100644 --- a/minitests/partial_reconfig_flow/Makefile +++ b/minitests/partial_reconfig_flow/Makefile @@ -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. From d5a6726e3019fa60e368dbf2275aee3a472d4be6 Mon Sep 17 00:00:00 2001 From: Rick Altherr Date: Thu, 1 Feb 2018 12:03:32 -0800 Subject: [PATCH 13/13] minitests: roi_harness: Remove init/final sequence hacks Signed-off-by: Rick Altherr --- minitests/roi_harness/fasm2bit.sh | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/minitests/roi_harness/fasm2bit.sh b/minitests/roi_harness/fasm2bit.sh index 3e7798c9..5beb90f5 100755 --- a/minitests/roi_harness/fasm2bit.sh +++ b/minitests/roi_harness/fasm2bit.sh @@ -30,28 +30,11 @@ echo "Out .bit: $bit_out" ${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"