prjxray/lib/xilinx_7series_configuratio...

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