mirror of https://github.com/openXC7/prjxray.git
Merge pull request #1091 from antmicro/ultrascale_support
Bitstream Tools: Add UltraScale devices support
This commit is contained in:
commit
ee5e0f80c3
|
|
@ -14,13 +14,18 @@ namespace prjxray {
|
|||
namespace xilinx {
|
||||
|
||||
class Series7;
|
||||
class UltraScale;
|
||||
class UltraScalePlus;
|
||||
|
||||
class Architecture {
|
||||
public:
|
||||
using Container = absl::variant<Series7, UltraScalePlus>;
|
||||
virtual const std::string& name() const = 0;
|
||||
using Container = absl::variant<Series7, UltraScale, UltraScalePlus>;
|
||||
Architecture(const std::string& name) : name_(name) {}
|
||||
const std::string& name() const { return name_; }
|
||||
virtual ~Architecture() {}
|
||||
|
||||
private:
|
||||
const std::string name_;
|
||||
};
|
||||
|
||||
class Series7 : public Architecture {
|
||||
|
|
@ -31,22 +36,21 @@ class Series7 : public Architecture {
|
|||
std::vector<std::unique_ptr<ConfigurationPacket<ConfRegType>>>;
|
||||
using FrameAddress = xc7series::FrameAddress;
|
||||
using WordType = uint32_t;
|
||||
Series7() : name_("Series7") {}
|
||||
const std::string& name() const override { return name_; }
|
||||
Series7() : Architecture("Series7") {}
|
||||
Series7(const std::string& name) : Architecture(name) {}
|
||||
static constexpr int words_per_frame = 101;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
class UltraScalePlus : public Series7 {
|
||||
public:
|
||||
UltraScalePlus() : name_("UltraScalePlus") {}
|
||||
const std::string& name() const override { return name_; }
|
||||
UltraScalePlus() : Series7("UltraScalePlus") {}
|
||||
static constexpr int words_per_frame = 93;
|
||||
};
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
class UltraScale : public Series7 {
|
||||
public:
|
||||
UltraScale() : Series7("UltraScale") {}
|
||||
static constexpr int words_per_frame = 123;
|
||||
};
|
||||
|
||||
class ArchitectureFactory {
|
||||
|
|
@ -55,6 +59,8 @@ class ArchitectureFactory {
|
|||
const std::string& arch) {
|
||||
if (arch == "Series7") {
|
||||
return Series7();
|
||||
} else if (arch == "UltraScale") {
|
||||
return UltraScale();
|
||||
} else if (arch == "UltraScalePlus") {
|
||||
return UltraScalePlus();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -72,16 +72,16 @@ class BitstreamReader {
|
|||
std::vector<uint32_t> words_;
|
||||
};
|
||||
|
||||
template <>
|
||||
template <typename ArchType>
|
||||
template <typename T>
|
||||
absl::optional<BitstreamReader<Series7>>
|
||||
BitstreamReader<Series7>::InitWithBytes(T bitstream) {
|
||||
absl::optional<BitstreamReader<ArchType>>
|
||||
BitstreamReader<ArchType>::InitWithBytes(T bitstream) {
|
||||
// If this is really a Xilinx bitstream, there will be a sync
|
||||
// word somewhere toward the beginning.
|
||||
auto sync_pos = std::search(bitstream.begin(), bitstream.end(),
|
||||
kSyncWord.begin(), kSyncWord.end());
|
||||
if (sync_pos == bitstream.end()) {
|
||||
return absl::optional<BitstreamReader<Series7>>();
|
||||
return absl::optional<BitstreamReader<ArchType>>();
|
||||
}
|
||||
sync_pos += kSyncWord.size();
|
||||
|
||||
|
|
@ -91,37 +91,12 @@ BitstreamReader<Series7>::InitWithBytes(T bitstream) {
|
|||
bitstream_span.subspan(sync_pos - bitstream.begin());
|
||||
|
||||
// Convert the bytes into 32-bit, big-endian words.
|
||||
auto big_endian_reader = make_big_endian_span<uint32_t>(config_packets);
|
||||
auto big_endian_reader =
|
||||
make_big_endian_span<typename ArchType::WordType>(config_packets);
|
||||
std::vector<uint32_t> words{big_endian_reader.begin(),
|
||||
big_endian_reader.end()};
|
||||
|
||||
return BitstreamReader<Series7>(std::move(words));
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename T>
|
||||
absl::optional<BitstreamReader<UltraScalePlus>>
|
||||
BitstreamReader<UltraScalePlus>::InitWithBytes(T bitstream) {
|
||||
// If this is really a Xilinx bitstream, there will be a sync
|
||||
// word somewhere toward the beginning.
|
||||
auto sync_pos = std::search(bitstream.begin(), bitstream.end(),
|
||||
kSyncWord.begin(), kSyncWord.end());
|
||||
if (sync_pos == bitstream.end()) {
|
||||
return absl::optional<BitstreamReader<UltraScalePlus>>();
|
||||
}
|
||||
sync_pos += kSyncWord.size();
|
||||
|
||||
// Wrap the provided container in a span that strips off the preamble.
|
||||
absl::Span<typename T::value_type> bitstream_span(bitstream);
|
||||
auto config_packets =
|
||||
bitstream_span.subspan(sync_pos - bitstream.begin());
|
||||
|
||||
// Convert the bytes into 32-bit, big-endian words.
|
||||
auto big_endian_reader = make_big_endian_span<uint32_t>(config_packets);
|
||||
std::vector<uint32_t> words{big_endian_reader.begin(),
|
||||
big_endian_reader.end()};
|
||||
|
||||
return BitstreamReader<UltraScalePlus>(std::move(words));
|
||||
return BitstreamReader<ArchType>(std::move(words));
|
||||
}
|
||||
|
||||
// Sync word as specified in UG470 page 81
|
||||
|
|
|
|||
|
|
@ -65,144 +65,40 @@ class Configuration {
|
|||
FrameMap frames_;
|
||||
};
|
||||
|
||||
template <>
|
||||
template <typename Collection>
|
||||
absl::optional<Configuration<Series7>> Configuration<Series7>::InitWithPackets(
|
||||
const typename Series7::Part& part,
|
||||
Collection& packets) {
|
||||
using ArchType = Series7;
|
||||
// Registers that can be directly written to.
|
||||
uint32_t command_register = 0;
|
||||
uint32_t frame_address_register = 0;
|
||||
uint32_t mask_register = 0;
|
||||
uint32_t ctl1_register = 0;
|
||||
template <typename ArchType>
|
||||
typename Configuration<ArchType>::PacketData
|
||||
Configuration<ArchType>::createType2ConfigurationPacketData(
|
||||
const typename Frames<ArchType>::Frames2Data& frames,
|
||||
absl::optional<typename ArchType::Part>& part) {
|
||||
PacketData packet_data;
|
||||
// Certain configuration frames blocks are separated by Zero Frames,
|
||||
// i.e. frames with words with all zeroes. For Series-7, US and US+
|
||||
// there zero frames separator consists of two frames.
|
||||
static const int kZeroFramesSeparatorWords =
|
||||
ArchType::words_per_frame * 2;
|
||||
for (auto& frame : frames) {
|
||||
std::copy(frame.second.begin(), frame.second.end(),
|
||||
std::back_inserter(packet_data));
|
||||
|
||||
// Internal state machine for writes.
|
||||
bool start_new_write = false;
|
||||
typename ArchType::FrameAddress current_frame_address = 0;
|
||||
|
||||
Configuration<ArchType>::FrameMap frames;
|
||||
for (auto packet : packets) {
|
||||
if (packet.opcode() !=
|
||||
ConfigurationPacket<
|
||||
typename ArchType::ConfRegType>::Opcode::Write) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (packet.address()) {
|
||||
case ArchType::ConfRegType::MASK:
|
||||
if (packet.data().size() < 1)
|
||||
continue;
|
||||
mask_register = packet.data()[0];
|
||||
break;
|
||||
case ArchType::ConfRegType::CTL1:
|
||||
if (packet.data().size() < 1)
|
||||
continue;
|
||||
ctl1_register =
|
||||
packet.data()[0] & mask_register;
|
||||
break;
|
||||
case ArchType::ConfRegType::CMD:
|
||||
if (packet.data().size() < 1)
|
||||
continue;
|
||||
command_register = packet.data()[0];
|
||||
// Writes to CMD trigger an immediate action. In
|
||||
// the case of WCFG, that is just setting a flag
|
||||
// for the next FDIR.
|
||||
if (command_register == 0x1) {
|
||||
start_new_write = true;
|
||||
}
|
||||
break;
|
||||
case ArchType::ConfRegType::IDCODE:
|
||||
// This really should be a one-word write.
|
||||
if (packet.data().size() < 1)
|
||||
continue;
|
||||
|
||||
// If the IDCODE doesn't match our expected
|
||||
// part, consider the bitstream invalid.
|
||||
if (packet.data()[0] != part.idcode()) {
|
||||
return {};
|
||||
}
|
||||
break;
|
||||
case ArchType::ConfRegType::FAR:
|
||||
// This really should be a one-word write.
|
||||
if (packet.data().size() < 1)
|
||||
continue;
|
||||
frame_address_register = packet.data()[0];
|
||||
|
||||
// Per UG470, the command present in the CMD
|
||||
// register is executed each time the FAR
|
||||
// register is laoded with a new value. As we
|
||||
// only care about WCFG commands, just check
|
||||
// that here. CTRL1 is completely undocumented
|
||||
// but looking at generated bitstreams, bit 21
|
||||
// is used when per-frame CRC is enabled.
|
||||
// Setting this bit seems to inhibit the
|
||||
// re-execution of CMD during a FAR write. In
|
||||
// practice, this is used so FAR writes can be
|
||||
// added in the bitstream to show progress
|
||||
// markers without impacting the actual write
|
||||
// operation.
|
||||
if (bit_field_get(ctl1_register, 21, 21) == 0 &&
|
||||
command_register == 0x1) {
|
||||
start_new_write = true;
|
||||
}
|
||||
break;
|
||||
case ArchType::ConfRegType::FDRI: {
|
||||
if (start_new_write) {
|
||||
current_frame_address =
|
||||
frame_address_register;
|
||||
start_new_write = false;
|
||||
}
|
||||
|
||||
// 7-series frames are 101-words long. Writes
|
||||
// to this register can be multiples of that to
|
||||
// do auto-incrementing block writes.
|
||||
for (size_t ii = 0; ii < packet.data().size();
|
||||
ii += ArchType::words_per_frame) {
|
||||
frames[current_frame_address] =
|
||||
packet.data().subspan(
|
||||
ii, ArchType::words_per_frame);
|
||||
|
||||
auto next_address =
|
||||
part.GetNextFrameAddress(
|
||||
current_frame_address);
|
||||
if (!next_address)
|
||||
break;
|
||||
|
||||
// Bitstreams appear to have 2 frames of
|
||||
// padding between rows.
|
||||
if (next_address &&
|
||||
(next_address->block_type() !=
|
||||
current_frame_address
|
||||
.block_type() ||
|
||||
next_address
|
||||
->is_bottom_half_rows() !=
|
||||
current_frame_address
|
||||
.is_bottom_half_rows() ||
|
||||
next_address->row() !=
|
||||
current_frame_address.row())) {
|
||||
ii += 2 *
|
||||
ArchType::words_per_frame;
|
||||
}
|
||||
current_frame_address = *next_address;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
auto next_address = part->GetNextFrameAddress(frame.first);
|
||||
if (next_address &&
|
||||
(next_address->block_type() != frame.first.block_type() ||
|
||||
next_address->is_bottom_half_rows() !=
|
||||
frame.first.is_bottom_half_rows() ||
|
||||
next_address->row() != frame.first.row())) {
|
||||
packet_data.insert(packet_data.end(),
|
||||
kZeroFramesSeparatorWords, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return Configuration(part, frames);
|
||||
packet_data.insert(packet_data.end(), kZeroFramesSeparatorWords, 0);
|
||||
return packet_data;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename ArchType>
|
||||
template <typename Collection>
|
||||
absl::optional<Configuration<UltraScalePlus>>
|
||||
Configuration<UltraScalePlus>::InitWithPackets(
|
||||
const typename UltraScalePlus::Part& part,
|
||||
Collection& packets) {
|
||||
using ArchType = UltraScalePlus;
|
||||
absl::optional<Configuration<ArchType>>
|
||||
Configuration<ArchType>::InitWithPackets(const typename ArchType::Part& part,
|
||||
Collection& packets) {
|
||||
// Registers that can be directly written to.
|
||||
uint32_t command_register = 0;
|
||||
uint32_t frame_address_register = 0;
|
||||
|
|
@ -286,8 +182,9 @@ Configuration<UltraScalePlus>::InitWithPackets(
|
|||
start_new_write = false;
|
||||
}
|
||||
|
||||
// UltraScale frames are 93-words long. Writes
|
||||
// to this register can be multiples of that to
|
||||
// Number of words in configuration frames
|
||||
// depend on tje architecture. Writes to this
|
||||
// register can be multiples of that number to
|
||||
// do auto-incrementing block writes.
|
||||
for (size_t ii = 0; ii < packet.data().size();
|
||||
ii += ArchType::words_per_frame) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ template <>
|
|||
typename BitstreamWriter<Series7>::header_t BitstreamWriter<Series7>::header_{
|
||||
0xFFFFFFFF, 0x000000BB, 0x11220044, 0xFFFFFFFF, 0xFFFFFFFF, 0xAA995566};
|
||||
|
||||
template <>
|
||||
typename BitstreamWriter<UltraScale>::header_t
|
||||
BitstreamWriter<UltraScale>::header_{0xFFFFFFFF, 0x000000BB, 0x11220044,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xAA995566};
|
||||
|
||||
template <>
|
||||
typename BitstreamWriter<UltraScalePlus>::header_t
|
||||
BitstreamWriter<UltraScalePlus>::header_{
|
||||
|
|
|
|||
|
|
@ -18,55 +18,6 @@
|
|||
namespace prjxray {
|
||||
namespace xilinx {
|
||||
|
||||
template <>
|
||||
Configuration<Series7>::PacketData
|
||||
Configuration<Series7>::createType2ConfigurationPacketData(
|
||||
const Frames<Series7>::Frames2Data& frames,
|
||||
absl::optional<Series7::Part>& part) {
|
||||
PacketData packet_data;
|
||||
for (auto& frame : frames) {
|
||||
std::copy(frame.second.begin(), frame.second.end(),
|
||||
std::back_inserter(packet_data));
|
||||
|
||||
auto next_address = part->GetNextFrameAddress(frame.first);
|
||||
if (next_address &&
|
||||
(next_address->block_type() != frame.first.block_type() ||
|
||||
next_address->is_bottom_half_rows() !=
|
||||
frame.first.is_bottom_half_rows() ||
|
||||
next_address->row() != frame.first.row())) {
|
||||
packet_data.insert(packet_data.end(), 202, 0);
|
||||
}
|
||||
}
|
||||
packet_data.insert(packet_data.end(), 202, 0);
|
||||
return packet_data;
|
||||
}
|
||||
|
||||
template <>
|
||||
Configuration<UltraScalePlus>::PacketData
|
||||
Configuration<UltraScalePlus>::createType2ConfigurationPacketData(
|
||||
const Frames<UltraScalePlus>::Frames2Data& frames,
|
||||
absl::optional<UltraScalePlus::Part>& part) {
|
||||
PacketData packet_data;
|
||||
for (auto& frame : frames) {
|
||||
std::copy(frame.second.begin(), frame.second.end(),
|
||||
std::back_inserter(packet_data));
|
||||
|
||||
auto next_address = part->GetNextFrameAddress(frame.first);
|
||||
if (next_address &&
|
||||
(next_address->block_type() != frame.first.block_type() ||
|
||||
next_address->is_bottom_half_rows() !=
|
||||
frame.first.is_bottom_half_rows() ||
|
||||
next_address->row() != frame.first.row())) {
|
||||
packet_data.insert(packet_data.end(),
|
||||
UltraScalePlus::words_per_frame * 2,
|
||||
0);
|
||||
}
|
||||
}
|
||||
packet_data.insert(packet_data.end(),
|
||||
UltraScalePlus::words_per_frame * 2, 0);
|
||||
return packet_data;
|
||||
}
|
||||
|
||||
template <>
|
||||
void Configuration<Series7>::createConfigurationPackage(
|
||||
Series7::ConfigurationPackage& out_packets,
|
||||
|
|
@ -239,6 +190,167 @@ void Configuration<Series7>::createConfigurationPackage(
|
|||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void Configuration<UltraScale>::createConfigurationPackage(
|
||||
UltraScale::ConfigurationPackage& out_packets,
|
||||
const PacketData& packet_data,
|
||||
absl::optional<UltraScale::Part>& part) {
|
||||
using ArchType = UltraScale;
|
||||
using ConfigurationRegister = ArchType::ConfRegType;
|
||||
// Initialization sequence
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::TIMER, {0x0}));
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::WBSTAR, {0x0}));
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::CMD,
|
||||
{static_cast<uint32_t>(xc7series::Command::NOP)}));
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::CMD,
|
||||
{static_cast<uint32_t>(xc7series::Command::RCRC)}));
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::FAR, {0x0}));
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::UNKNOWN, {0x0}));
|
||||
|
||||
// Configuration Options 0
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::COR0, {0x38003fe5}));
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::COR1, {0x400000}));
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::IDCODE, {part->idcode()}));
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::CMD,
|
||||
{static_cast<uint32_t>(xc7series::Command::SWITCH)}));
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::MASK, {0x1}));
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::CTL0, {0x101}));
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::MASK, {0x0}));
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::CTL1, {0x0}));
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::FAR, {0x0}));
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::CMD,
|
||||
{static_cast<uint32_t>(xc7series::Command::WCFG)}));
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
|
||||
// Frame data write
|
||||
out_packets.emplace_back(new ConfigurationPacket<ConfigurationRegister>(
|
||||
TYPE1, ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::FDRI, {}));
|
||||
out_packets.emplace_back(new ConfigurationPacket<ConfigurationRegister>(
|
||||
TYPE2, ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::FDRI, packet_data));
|
||||
|
||||
// Finalization sequence
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::CMD,
|
||||
{static_cast<uint32_t>(xc7series::Command::RCRC)}));
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::CMD,
|
||||
{static_cast<uint32_t>(xc7series::Command::GRESTORE)}));
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::CMD,
|
||||
{static_cast<uint32_t>(xc7series::Command::LFRM)}));
|
||||
for (int ii = 0; ii < 100; ++ii) {
|
||||
out_packets.emplace_back(
|
||||
new NopPacket<ConfigurationRegister>());
|
||||
}
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::CMD,
|
||||
{static_cast<uint32_t>(xc7series::Command::START)}));
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::FAR, {0x3be0000}));
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::MASK, {0x101}));
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::CTL0, {0x101}));
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::CMD,
|
||||
{static_cast<uint32_t>(xc7series::Command::RCRC)}));
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(new NopPacket<ConfigurationRegister>());
|
||||
out_packets.emplace_back(
|
||||
new ConfigurationPacketWithPayload<1, ConfigurationRegister>(
|
||||
ConfigurationPacket<ConfigurationRegister>::Opcode::Write,
|
||||
ConfigurationRegister::CMD,
|
||||
{static_cast<uint32_t>(xc7series::Command::DESYNC)}));
|
||||
for (int ii = 0; ii < 400; ++ii) {
|
||||
out_packets.emplace_back(
|
||||
new NopPacket<ConfigurationRegister>());
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void Configuration<UltraScalePlus>::createConfigurationPackage(
|
||||
UltraScalePlus::ConfigurationPackage& out_packets,
|
||||
|
|
@ -399,6 +511,5 @@ void Configuration<UltraScalePlus>::createConfigurationPackage(
|
|||
new NopPacket<ConfigurationRegister>());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xilinx
|
||||
} // namespace prjxray
|
||||
|
|
|
|||
|
|
@ -8,10 +8,17 @@ void Frames<Series7>::updateECC(typename Frames<Series7>::FrameData& data) {
|
|||
xc7series::updateECC(data);
|
||||
}
|
||||
|
||||
template <>
|
||||
void Frames<UltraScale>::updateECC(
|
||||
typename Frames<UltraScale>::FrameData& data) {
|
||||
xc7series::updateECC(data);
|
||||
}
|
||||
|
||||
template <>
|
||||
void Frames<UltraScalePlus>::updateECC(
|
||||
typename Frames<UltraScalePlus>::FrameData& data) {
|
||||
xc7series::updateECC(data);
|
||||
}
|
||||
|
||||
} // namespace xilinx
|
||||
} // namespace prjxray
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ struct Frames2BitWriter {
|
|||
}
|
||||
|
||||
if (std::is_same<ArchType, xilinx::Series7>::value ||
|
||||
std::is_same<ArchType, xilinx::UltraScale>::value ||
|
||||
std::is_same<ArchType, xilinx::UltraScalePlus>::value) {
|
||||
// In case the frames input file is missing some frames
|
||||
// that are in the tilegrid
|
||||
|
|
|
|||
Loading…
Reference in New Issue