mirror of https://github.com/openXC7/prjxray.git
Merge pull request #1103 from antmicro/ultrascaleplus_support
Bitstream Tools: Add UltraScalePlus support
This commit is contained in:
commit
2a3f6aecfe
|
|
@ -6,6 +6,7 @@ add_library(libprjxray
|
||||||
xilinx/configuration_packet.cc
|
xilinx/configuration_packet.cc
|
||||||
xilinx/configuration_register.cc
|
xilinx/configuration_register.cc
|
||||||
xilinx/configuration.cc
|
xilinx/configuration.cc
|
||||||
|
xilinx/frames.cc
|
||||||
# Series-7 specific
|
# Series-7 specific
|
||||||
xilinx/xc7series/frame_address.cc
|
xilinx/xc7series/frame_address.cc
|
||||||
xilinx/xc7series/global_clock_region.cc
|
xilinx/xc7series/global_clock_region.cc
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,11 @@ namespace prjxray {
|
||||||
namespace xilinx {
|
namespace xilinx {
|
||||||
|
|
||||||
class Series7;
|
class Series7;
|
||||||
|
class UltraScalePlus;
|
||||||
|
|
||||||
class Architecture {
|
class Architecture {
|
||||||
public:
|
public:
|
||||||
using Container = absl::variant<Series7>;
|
using Container = absl::variant<Series7, UltraScalePlus>;
|
||||||
virtual const std::string& name() const = 0;
|
virtual const std::string& name() const = 0;
|
||||||
virtual ~Architecture() {}
|
virtual ~Architecture() {}
|
||||||
};
|
};
|
||||||
|
|
@ -38,12 +39,24 @@ class Series7 : public Architecture {
|
||||||
std::string name_;
|
std::string name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class UltraScalePlus : public Series7 {
|
||||||
|
public:
|
||||||
|
UltraScalePlus() : name_("UltraScalePlus") {}
|
||||||
|
const std::string& name() const override { return name_; }
|
||||||
|
static constexpr int words_per_frame = 93;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name_;
|
||||||
|
};
|
||||||
|
|
||||||
class ArchitectureFactory {
|
class ArchitectureFactory {
|
||||||
public:
|
public:
|
||||||
static Architecture::Container create_architecture(
|
static Architecture::Container create_architecture(
|
||||||
const std::string& arch) {
|
const std::string& arch) {
|
||||||
if (arch == "Series7") {
|
if (arch == "Series7") {
|
||||||
return Series7();
|
return Series7();
|
||||||
|
} else if (arch == "UltraScalePlus") {
|
||||||
|
return UltraScalePlus();
|
||||||
} else {
|
} else {
|
||||||
return Architecture::Container();
|
return Architecture::Container();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,32 @@ BitstreamReader<Series7>::InitWithBytes(T bitstream) {
|
||||||
return BitstreamReader<Series7>(std::move(words));
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
// Sync word as specified in UG470 page 81
|
// Sync word as specified in UG470 page 81
|
||||||
template <typename ArchType>
|
template <typename ArchType>
|
||||||
std::array<uint8_t, 4> BitstreamReader<ArchType>::kSyncWord{0xAA, 0x99, 0x55,
|
std::array<uint8_t, 4> BitstreamReader<ArchType>::kSyncWord{0xAA, 0x99, 0x55,
|
||||||
|
|
|
||||||
|
|
@ -196,6 +196,138 @@ absl::optional<Configuration<Series7>> Configuration<Series7>::InitWithPackets(
|
||||||
return Configuration(part, frames);
|
return Configuration(part, frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
template <typename Collection>
|
||||||
|
absl::optional<Configuration<UltraScalePlus>>
|
||||||
|
Configuration<UltraScalePlus>::InitWithPackets(
|
||||||
|
const typename UltraScalePlus::Part& part,
|
||||||
|
Collection& packets) {
|
||||||
|
using ArchType = UltraScalePlus;
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UltraScale frames are 93-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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Configuration(part, frames);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace xilinx
|
} // namespace xilinx
|
||||||
} // namespace prjxray
|
} // namespace prjxray
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,6 @@ class Frames {
|
||||||
void updateECC(FrameData& data);
|
void updateECC(FrameData& data);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ArchType>
|
|
||||||
void Frames<ArchType>::updateECC(typename Frames<ArchType>::FrameData& data) {
|
|
||||||
xc7series::updateECC(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ArchType>
|
template <typename ArchType>
|
||||||
int Frames<ArchType>::readFrames(const std::string& frm_file_str) {
|
int Frames<ArchType>::readFrames(const std::string& frm_file_str) {
|
||||||
assert(!frm_file_str.empty());
|
assert(!frm_file_str.empty());
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,11 @@ template <>
|
||||||
typename BitstreamWriter<Series7>::header_t BitstreamWriter<Series7>::header_{
|
typename BitstreamWriter<Series7>::header_t BitstreamWriter<Series7>::header_{
|
||||||
0xFFFFFFFF, 0x000000BB, 0x11220044, 0xFFFFFFFF, 0xFFFFFFFF, 0xAA995566};
|
0xFFFFFFFF, 0x000000BB, 0x11220044, 0xFFFFFFFF, 0xFFFFFFFF, 0xAA995566};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
typename BitstreamWriter<UltraScalePlus>::header_t
|
||||||
|
BitstreamWriter<UltraScalePlus>::header_{
|
||||||
|
0xFFFFFFFF, 0x000000BB, 0x11220044, 0xFFFFFFFF, 0xFFFFFFFF, 0xAA995566};
|
||||||
|
|
||||||
uint32_t packet2header(
|
uint32_t packet2header(
|
||||||
const ConfigurationPacket<Series7ConfigurationRegister>& packet) {
|
const ConfigurationPacket<Series7ConfigurationRegister>& packet) {
|
||||||
uint32_t ret = 0;
|
uint32_t ret = 0;
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,32 @@ Configuration<Series7>::createType2ConfigurationPacketData(
|
||||||
return packet_data;
|
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 <>
|
template <>
|
||||||
void Configuration<Series7>::createConfigurationPackage(
|
void Configuration<Series7>::createConfigurationPackage(
|
||||||
Series7::ConfigurationPackage& out_packets,
|
Series7::ConfigurationPackage& out_packets,
|
||||||
|
|
@ -213,5 +239,166 @@ void Configuration<Series7>::createConfigurationPackage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void Configuration<UltraScalePlus>::createConfigurationPackage(
|
||||||
|
UltraScalePlus::ConfigurationPackage& out_packets,
|
||||||
|
const PacketData& packet_data,
|
||||||
|
absl::optional<UltraScalePlus::Part>& part) {
|
||||||
|
using ArchType = UltraScalePlus;
|
||||||
|
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>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace xilinx
|
} // namespace xilinx
|
||||||
} // namespace prjxray
|
} // namespace prjxray
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
#include <prjxray/xilinx/frames.h>
|
||||||
|
#include <prjxray/xilinx/xc7series/ecc.h>
|
||||||
|
|
||||||
|
namespace prjxray {
|
||||||
|
namespace xilinx {
|
||||||
|
template <>
|
||||||
|
void Frames<Series7>::updateECC(typename Frames<Series7>::FrameData& data) {
|
||||||
|
xc7series::updateECC(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void Frames<UltraScalePlus>::updateECC(
|
||||||
|
typename Frames<UltraScalePlus>::FrameData& data) {
|
||||||
|
xc7series::updateECC(data);
|
||||||
|
}
|
||||||
|
} // namespace xilinx
|
||||||
|
} // namespace prjxray
|
||||||
|
|
@ -39,7 +39,8 @@ struct Frames2BitWriter {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::is_same<ArchType, xilinx::Series7>::value) {
|
if (std::is_same<ArchType, xilinx::Series7>::value ||
|
||||||
|
std::is_same<ArchType, xilinx::UltraScalePlus>::value) {
|
||||||
// In case the frames input file is missing some frames
|
// In case the frames input file is missing some frames
|
||||||
// that are in the tilegrid
|
// that are in the tilegrid
|
||||||
frames.addMissingFrames(part);
|
frames.addMissingFrames(part);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue