mirror of https://github.com/openXC7/prjxray.git
Refactor Configuration::InitWithPackets template method
Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
This commit is contained in:
parent
7bc54d0c56
commit
d91b0a5006
|
|
@ -65,12 +65,11 @@ class Configuration {
|
|||
FrameMap frames_;
|
||||
};
|
||||
|
||||
template <>
|
||||
template <typename ArchType>
|
||||
template <typename Collection>
|
||||
absl::optional<Configuration<Series7>> Configuration<Series7>::InitWithPackets(
|
||||
const typename Series7::Part& part,
|
||||
Collection& packets) {
|
||||
using ArchType = Series7;
|
||||
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;
|
||||
|
|
@ -154,8 +153,9 @@ absl::optional<Configuration<Series7>> Configuration<Series7>::InitWithPackets(
|
|||
start_new_write = false;
|
||||
}
|
||||
|
||||
// 7-series frames are 101-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) {
|
||||
|
|
@ -196,269 +196,6 @@ absl::optional<Configuration<Series7>> Configuration<Series7>::InitWithPackets(
|
|||
return Configuration(part, frames);
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename Collection>
|
||||
absl::optional<Configuration<UltraScale>>
|
||||
Configuration<UltraScale>::InitWithPackets(
|
||||
const typename UltraScale::Part& part,
|
||||
Collection& packets) {
|
||||
using ArchType = UltraScale;
|
||||
// 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 123-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);
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename Collection>
|
||||
absl::optional<Configuration<UltraScalePlus>>
|
||||
Configuration<UltraScalePlus>::InitWithPackets(
|
||||
const typename UltraScale::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 prjxray
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue