Merge pull request #72 from kc8apf/xc7patch_emit_init_final_seq

Replace init/final sequence hacks with less hacky solution
This commit is contained in:
Rick Altherr 2018-02-07 14:51:52 -08:00 committed by GitHub
commit d287de935a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 478 additions and 124 deletions

View File

@ -23,7 +23,7 @@ namespace xc7series {
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;

View File

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

View File

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

View File

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

View File

@ -25,6 +25,7 @@ enum class ConfigurationRegister : unsigned int {
COR1 = 0x0e,
WBSTAR = 0x10,
TIMER = 0x11,
UNKNOWN = 0x13,
BOOTSTS = 0x16,
CTL1 = 0x18,
BSPI = 0x1F,

View File

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

View File

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

View File

@ -50,7 +50,8 @@ void dump_packets(xc7series::BitstreamWriter writer, bool nl = true) {
}
// 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 @@ void AddType0(std::vector<xc7series::ConfigurationPacket>& packets) {
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 @@ void AddType2(std::vector<xc7series::ConfigurationPacket>& packets) {
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 @@ void AddType2(std::vector<xc7series::ConfigurationPacket>& packets) {
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, WriteHeader) {
}
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 @@ TEST(BitstreamWriterTest, WriteType0) {
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, WriteType1) {
}
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, WriteType2) {
}
TEST(BitstreamWriterTest, WriteMulti) {
std::vector<xc7series::ConfigurationPacket> packets;
std::vector<std::unique_ptr<xc7series::ConfigurationPacket>> packets;
AddType1(packets);
AddType1E(packets);
AddType2(packets);

View File

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

View File

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

View File

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

View File

@ -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 @@ 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);
}
#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 @@ int main(int argc, char* argv[]) {
}
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());
}
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());
}
#endif
// Write bitstream.
xc7series::BitstreamWriter out_bitstream_writer(out_packets);
@ -199,6 +319,61 @@ int main(int argc, char* argv[]) {
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 @@ 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;
}