From 426c93cffdefd82ca1ffbae7a5704e4bc9b3d528 Mon Sep 17 00:00:00 2001 From: Tomasz Michalak Date: Wed, 18 Nov 2020 14:39:55 +0100 Subject: [PATCH] bitread: Add AUX support Signed-off-by: Tomasz Michalak --- lib/include/prjxray/xilinx/bitstream_reader.h | 59 +++++++++++++++++++ lib/include/prjxray/xilinx/configuration.h | 14 +++++ tools/bitread.cc | 23 ++++++++ 3 files changed, 96 insertions(+) diff --git a/lib/include/prjxray/xilinx/bitstream_reader.h b/lib/include/prjxray/xilinx/bitstream_reader.h index bae16bc1..094371ad 100644 --- a/lib/include/prjxray/xilinx/bitstream_reader.h +++ b/lib/include/prjxray/xilinx/bitstream_reader.h @@ -68,6 +68,14 @@ class BitstreamReader { static absl::optional> InitWithBytes( T bitstream); + // Extract information from bitstream necessary to reconstruct RBT + // header and add it to the AUX data + template + static void ExtractHeader(T bitstream, FILE* aux_fp); + + // Extract configuration logic data and add to the AUX data + void ExtractFpgaConfigurationLogicData(FILE* aux_fp); + const std::vector& words() { return words_; }; // Returns an iterator that yields `ConfigurationPackets` @@ -77,10 +85,61 @@ class BitstreamReader { private: static std::array kSyncWord; + const std::vector kWcfgCmd = {0x30008001, 0x1}; + const std::vector kNullCmd = {0x30008001, 0x0}; std::vector words_; }; +// Extract FPGA configuration logic information +template +void BitstreamReader::ExtractFpgaConfigurationLogicData( + FILE* aux_fp) { + // Get the data before the first FDRI_WRITE command packet + const auto fpga_conf_end = std::search( + words_.cbegin(), words_.cend(), kWcfgCmd.cbegin(), kWcfgCmd.cend()); + fprintf(aux_fp, "FPGA configuration logic prefix: "); + for (auto it = words_.cbegin(); it != fpga_conf_end; ++it) { + fprintf(aux_fp, "%08X ", *it); + } + fseek(aux_fp, -1, SEEK_CUR); + fprintf(aux_fp, "\n"); + + // Get the data after the last Null Command packet + const auto last_null_cmd = std::find_end( + words_.cbegin(), words_.cend(), kNullCmd.cbegin(), kNullCmd.cend()); + fprintf(aux_fp, "FPGA configuration logic suffix: "); + for (auto it = last_null_cmd; it != words_.cend(); ++it) { + fprintf(aux_fp, "%08X ", *it); + } + fseek(aux_fp, -1, SEEK_CUR); + fprintf(aux_fp, "\n"); +} + +template +template +void BitstreamReader::ExtractHeader(T bitstream, FILE* aux_fp) { + // 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; + } + sync_pos += kSyncWord.size(); + // Wrap the provided container in a span that strips off the preamble. + absl::Span bitstream_span(bitstream); + auto header_packets = + bitstream_span.subspan(0, sync_pos - bitstream.begin()); + + fprintf(aux_fp, "Header bytes: "); + for (auto& word : header_packets) { + fprintf(aux_fp, "%02X ", word); + } + fseek(aux_fp, -1, SEEK_CUR); + fprintf(aux_fp, "\n"); +} + template template absl::optional> diff --git a/lib/include/prjxray/xilinx/configuration.h b/lib/include/prjxray/xilinx/configuration.h index 89fad613..571441e8 100644 --- a/lib/include/prjxray/xilinx/configuration.h +++ b/lib/include/prjxray/xilinx/configuration.h @@ -68,6 +68,7 @@ class Configuration { const typename ArchType::Part& part() const { return part_; } const FrameMap& frames() const { return frames_; } + void ExtractFrameAddresses(FILE* fp); private: typename ArchType::Part part_; @@ -358,6 +359,19 @@ Configuration::InitWithPackets(const typename ArchType::Part& part, return Configuration(part, frames); } +template +void Configuration::ExtractFrameAddresses(FILE* fp) { + fprintf(fp, "Frame addresses in bitstream: "); + for (auto frame = frames_.begin(); frame != frames_.end(); ++frame) { + fprintf(fp, "%08X", (int)frame->first); + if (std::next(frame) != frames_.end()) { + fprintf(fp, " "); + } else { + fprintf(fp, "\n"); + } + } +} + } // namespace xilinx } // namespace prjxray diff --git a/tools/bitread.cc b/tools/bitread.cc index f5aa7e06..ef1d0e39 100644 --- a/tools/bitread.cc +++ b/tools/bitread.cc @@ -54,6 +54,10 @@ DEFINE_string(part_file, "", "YAML file describing a Xilinx part"); DEFINE_string(architecture, "Series7", "Architecture of the provided bitstream"); +DEFINE_string( + aux, + "", + "write machine-readable output file with auxiliary bitstream data"); namespace xilinx = prjxray::xilinx; @@ -115,6 +119,25 @@ struct BitReader { fprintf(f, "\n"); } + if (!FLAGS_aux.empty()) { + FILE* aux_file = fopen(FLAGS_aux.c_str(), "w"); + if (aux_file == nullptr) { + printf( + "Can't open aux output file '%s' for " + "writing!\n", + FLAGS_aux.c_str()); + return 1; + } + // Extract and decode header information as in RBT file + xilinx::BitstreamReader::ExtractHeader( + bytes_, aux_file); + // Extract FPGA configuration logic information + reader->ExtractFpgaConfigurationLogicData(aux_file); + // Extract configuration frames' addresses + config->ExtractFrameAddresses(aux_file); + fclose(aux_file); + } + std::vector> pgmdata; std::vector pgmsep;