mirror of https://github.com/openXC7/prjxray.git
77 lines
2.3 KiB
C++
77 lines
2.3 KiB
C++
#include <prjxray/xilinx_7series_configuration_packet.h>
|
|
|
|
#include <ostream>
|
|
|
|
#include <prjxray/bit_ops.h>
|
|
|
|
namespace prjxray {
|
|
|
|
std::pair<absl::Span<uint32_t>, absl::optional<Xilinx7SeriesConfigurationPacket>>
|
|
Xilinx7SeriesConfigurationPacket::InitWithWords(
|
|
absl::Span<uint32_t> words,
|
|
const Xilinx7SeriesConfigurationPacket *previous_packet) {
|
|
// Need at least one 32-bit word to have a valid packet header.
|
|
if (words.size() < 1) return {words, {}};
|
|
|
|
uint32_t header_type = bit_field_get(words[0], 31, 29);
|
|
switch (header_type) {
|
|
case 0b001: {
|
|
Opcode opcode = static_cast<Opcode>(
|
|
bit_field_get(words[0], 28, 27));
|
|
uint32_t address = bit_field_get(words[0], 26, 13);
|
|
uint32_t data_word_count = bit_field_get(words[0], 10, 0);
|
|
|
|
// If the full packet has not been received, return as though
|
|
// no valid packet was found.
|
|
if (data_word_count > words.size() - 1) {
|
|
return {words, {}};
|
|
}
|
|
|
|
return {words.subspan(data_word_count+1),
|
|
{{opcode, address, words.subspan(1, data_word_count)}}};
|
|
}
|
|
case 0b010: {
|
|
absl::optional<Xilinx7SeriesConfigurationPacket> packet;
|
|
Opcode opcode = static_cast<Opcode>(
|
|
bit_field_get(words[0], 28, 27));
|
|
uint32_t data_word_count = bit_field_get(words[0], 26, 0);
|
|
|
|
// If the full packet has not been received, return as though
|
|
// no valid packet was found.
|
|
if (data_word_count > words.size() - 1) {
|
|
return {words, {}};
|
|
}
|
|
|
|
if (previous_packet) {
|
|
packet = Xilinx7SeriesConfigurationPacket(
|
|
opcode, previous_packet->address(),
|
|
words.subspan(1, data_word_count));
|
|
}
|
|
|
|
return {words.subspan(data_word_count + 1), packet};
|
|
}
|
|
default:
|
|
return {{}, {}};
|
|
}
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& o,
|
|
const Xilinx7SeriesConfigurationPacket &packet) {
|
|
switch (packet.opcode()) {
|
|
case Xilinx7SeriesConfigurationPacket::Opcode::NOP:
|
|
return o << "[NOP]" << std::endl;
|
|
case Xilinx7SeriesConfigurationPacket::Opcode::Read:
|
|
return o << "[Read Address=" << packet.address()
|
|
<< " Length=" << packet.data().size() <<
|
|
"]" << std::endl;
|
|
case Xilinx7SeriesConfigurationPacket::Opcode::Write:
|
|
return o << "[Write Address=" << packet.address()
|
|
<< " Length=" << packet.data().size() <<
|
|
"]" << std::endl;
|
|
default:
|
|
return o << "[Invalid Opcode]" << std::endl;
|
|
}
|
|
}
|
|
|
|
} // namespace prjxray
|