From 2f630efada757dfd8cb13e8d5b6161072d0f53ed Mon Sep 17 00:00:00 2001 From: Tomasz Michalak Date: Thu, 10 Oct 2019 13:31:15 +0200 Subject: [PATCH] bitstream_tools: Move bitstream writer template methods to header file Signed-off-by: Tomasz Michalak --- lib/include/prjxray/xilinx/bitstream_writer.h | 287 +++++++++++++++++ lib/xilinx/bitstream_writer.cc | 302 ------------------ 2 files changed, 287 insertions(+), 302 deletions(-) diff --git a/lib/include/prjxray/xilinx/bitstream_writer.h b/lib/include/prjxray/xilinx/bitstream_writer.h index f904e7cb..883e9c2a 100644 --- a/lib/include/prjxray/xilinx/bitstream_writer.h +++ b/lib/include/prjxray/xilinx/bitstream_writer.h @@ -7,9 +7,13 @@ #define PRJXRAY_LIB_XILINX_BITSTREAM_WRITER_H #include +#include #include #include +#include +#include +#include #include #include @@ -19,6 +23,8 @@ namespace prjxray { namespace xilinx { +uint32_t packet2header( + const ConfigurationPacket& packet); // Writes out the complete Xilinx bitstream including // header, sync word and configuration sequence. template @@ -129,6 +135,287 @@ class BitstreamWriter { const std::string& generator_name); }; +template +int BitstreamWriter::writeBitstream( + const typename ArchType::ConfigurationPackage& packets, + const std::string& part_name, + const std::string& frames_file, + const std::string& generator_name, + const std::string& output_file) { + std::ofstream out_file(output_file, std::ofstream::binary); + if (!out_file) { + std::cerr << "Unable to open file for writting: " << output_file + << std::endl; + return 1; + } + + BitstreamHeader bit_header( + create_header(part_name, frames_file, generator_name)); + out_file.write(reinterpret_cast(bit_header.data()), + bit_header.size()); + + auto end_of_header_pos = out_file.tellp(); + auto header_data_length_pos = + end_of_header_pos - static_cast(4); + + BitstreamWriter out_bitstream_writer(packets); + int bytes_per_word = sizeof(typename ArchType::WordType); + for (uint32_t word : out_bitstream_writer) { + for (int byte = bytes_per_word - 1; byte >= 0; byte--) { + out_file.put((word >> (byte * 8)) & 0xFF); + } + } + + uint32_t length_of_data = out_file.tellp() - end_of_header_pos; + + out_file.seekp(header_data_length_pos); + for (int byte = 3; byte >= 0; byte--) { + out_file.put((length_of_data >> (byte * 8)) & 0xFF); + } + return 0; +} + +template +typename BitstreamWriter::BitstreamHeader +BitstreamWriter::create_header(const std::string& part_name, + const std::string& frames_file_name, + const std::string& generator_name) { + // Sync header + BitstreamHeader bit_header{0x0, 0x9, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, + 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 'a'}; + auto build_source = + absl::StrCat(frames_file_name, ";Generator=" + generator_name); + bit_header.push_back( + static_cast((build_source.size() + 1) >> 8)); + bit_header.push_back(static_cast(build_source.size() + 1)); + bit_header.insert(bit_header.end(), build_source.begin(), + build_source.end()); + bit_header.push_back(0x0); + + // Source file. + bit_header.push_back('b'); + bit_header.push_back(static_cast((part_name.size() + 1) >> 8)); + bit_header.push_back(static_cast(part_name.size() + 1)); + bit_header.insert(bit_header.end(), part_name.begin(), part_name.end()); + bit_header.push_back(0x0); + + // Build timestamp. + auto build_time = absl::Now(); + auto build_date_string = + absl::FormatTime("%E4Y/%m/%d", build_time, absl::UTCTimeZone()); + auto build_time_string = + absl::FormatTime("%H:%M:%S", build_time, absl::UTCTimeZone()); + + bit_header.push_back('c'); + bit_header.push_back( + static_cast((build_date_string.size() + 1) >> 8)); + bit_header.push_back( + static_cast(build_date_string.size() + 1)); + bit_header.insert(bit_header.end(), build_date_string.begin(), + build_date_string.end()); + bit_header.push_back(0x0); + + bit_header.push_back('d'); + bit_header.push_back( + static_cast((build_time_string.size() + 1) >> 8)); + bit_header.push_back( + static_cast(build_time_string.size() + 1)); + bit_header.insert(bit_header.end(), build_time_string.begin(), + build_time_string.end()); + bit_header.push_back(0x0); + bit_header.insert(bit_header.end(), {'e', 0x0, 0x0, 0x0, 0x0}); + return bit_header; +} + +template +typename BitstreamWriter::packet_iterator +BitstreamWriter::iterator::packet_begin() { + // itr_packets = packets.begin(); + const ConfigurationPacket& packet = + **itr_packets_; + + return BitstreamWriter::packet_iterator( + &packet, BitstreamWriter::packet_iterator::STATE_HEADER, + packet.data().begin()); +} + +template +typename BitstreamWriter::packet_iterator +BitstreamWriter::iterator::packet_end() { + const ConfigurationPacket& packet = + **itr_packets_; + + return BitstreamWriter::packet_iterator( + &packet, BitstreamWriter::packet_iterator::STATE_END, + // Essentially ignored + packet.data().end()); +} + +template +BitstreamWriter::packet_iterator::packet_iterator( + const ConfigurationPacket* packet, + state_t state, + data_iterator_t itr_data) + : state_(state), itr_data_(itr_data), packet_(packet) {} + +template +typename BitstreamWriter::packet_iterator& + BitstreamWriter::packet_iterator::operator++() { + if (state_ == STATE_HEADER) { + itr_data_ = packet_->data().begin(); + if (itr_data_ == packet_->data().end()) { + state_ = STATE_END; + } else { + state_ = STATE_DATA; + } + } else if (state_ == STATE_DATA) { + /// Advance. data must be valid while not at end + itr_data_++; + // Reached this end of this packet? + if (itr_data_ == packet_->data().end()) { + state_ = STATE_END; + } + } + return *this; +} + +template +bool BitstreamWriter::packet_iterator::operator==( + const packet_iterator& other) const { + return state_ == other.state_ && itr_data_ == other.itr_data_; +} + +template +bool BitstreamWriter::packet_iterator::operator!=( + const packet_iterator& other) const { + return !(*this == other); +} + +template +const typename BitstreamWriter::itr_value_type + BitstreamWriter::packet_iterator::operator*() const { + if (state_ == STATE_HEADER) { + return packet2header(*packet_); + } else if (state_ == STATE_DATA) { + return *itr_data_; + } + return 0; // XXX: assert or something? +} + +template +const typename BitstreamWriter::itr_value_type + BitstreamWriter::packet_iterator::operator->() const { + return *(*this); +} + +/************************************************** + * BitstreamWriter::iterator + *************************************************/ + +template +typename BitstreamWriter::iterator +BitstreamWriter::begin() { + typename packets_t::const_iterator itr_packets = packets_.begin(); + absl::optional op_packet_itr; + + // May have no packets + if (itr_packets != packets_.end()) { + // op_packet_itr = packet_begin(); + // FIXME: de-duplicate this + const ConfigurationPacket& + packet = **itr_packets; + packet_iterator packet_itr = + packet_iterator(&packet, packet_iterator::STATE_HEADER, + packet.data().begin()); + op_packet_itr = packet_itr; + } + return iterator(header_.begin(), packets_, itr_packets, op_packet_itr); +} + +template +typename BitstreamWriter::iterator BitstreamWriter::end() { + return iterator(header_.end(), packets_, packets_.end(), + absl::optional()); +} + +template +BitstreamWriter::iterator::iterator( + header_t::iterator itr_header, + const typename BitstreamWriter::packets_t& packets, + typename BitstreamWriter::packets_t::const_iterator itr_packets, + absl::optional itr_packet) + : itr_header_(itr_header), + packets_(packets), + itr_packets_(itr_packets), + op_itr_packet_(itr_packet) {} + +template +typename BitstreamWriter::iterator& + BitstreamWriter::iterator::operator++() { + // Still generating header? + if (itr_header_ != header_.end()) { + itr_header_++; + // Finished header? + // Will advance to initialized itr_packets value + // XXX: maybe should just overwrite here + if (itr_header_ == header_.end()) { + itr_packets_ = packets_.begin(); + if (itr_packets_ != packets_.end()) { + op_itr_packet_ = packet_begin(); + } + } + // Then somewhere in packets + } else { + // We are either at end() in which case this operation is + // invalid Or there is a packet in progress packet in progress? + // Advance it + ++(*op_itr_packet_); + // Done with this packet? + if (*op_itr_packet_ == packet_end()) { + itr_packets_++; + if (itr_packets_ == packets_.end()) { + // we are at the very end + // invalidate data to be neat + op_itr_packet_.reset(); + } else { + op_itr_packet_ = packet_begin(); + } + } + } + return *this; +} + +template +bool BitstreamWriter::iterator::operator==( + const iterator& other) const { + return itr_header_ == other.itr_header_ && + itr_packets_ == other.itr_packets_ && + op_itr_packet_ == other.op_itr_packet_; +} + +template +bool BitstreamWriter::iterator::operator!=( + const iterator& other) const { + return !(*this == other); +} + +template +const typename BitstreamWriter::itr_value_type + BitstreamWriter::iterator::operator*() const { + if (itr_header_ != header_.end()) { + return *itr_header_; + } else { + // Iterating over packets, get data from current packet position + return *(*op_itr_packet_); + } +} + +template +const typename BitstreamWriter::itr_value_type + BitstreamWriter::iterator::operator->() const { + return *(*this); +} + } // namespace xilinx } // namespace prjxray diff --git a/lib/xilinx/bitstream_writer.cc b/lib/xilinx/bitstream_writer.cc index 72cd5d77..2426f4f0 100644 --- a/lib/xilinx/bitstream_writer.cc +++ b/lib/xilinx/bitstream_writer.cc @@ -1,11 +1,5 @@ -#include #include -#include -#include -#include -#include - #include #include #include @@ -18,162 +12,6 @@ template <> typename BitstreamWriter::header_t BitstreamWriter::header_{ 0xFFFFFFFF, 0x000000BB, 0x11220044, 0xFFFFFFFF, 0xFFFFFFFF, 0xAA995566}; -template -int BitstreamWriter::writeBitstream( - const typename ArchType::ConfigurationPackage& packets, - const std::string& part_name, - const std::string& frames_file, - const std::string& generator_name, - const std::string& output_file) { - std::ofstream out_file(output_file, std::ofstream::binary); - if (!out_file) { - std::cerr << "Unable to open file for writting: " << output_file - << std::endl; - return 1; - } - - BitstreamHeader bit_header( - create_header(part_name, frames_file, generator_name)); - out_file.write(reinterpret_cast(bit_header.data()), - bit_header.size()); - - auto end_of_header_pos = out_file.tellp(); - auto header_data_length_pos = - end_of_header_pos - static_cast(4); - - BitstreamWriter out_bitstream_writer(packets); - int bytes_per_word = sizeof(typename ArchType::WordType); - for (uint32_t word : out_bitstream_writer) { - for (int byte = bytes_per_word - 1; byte >= 0; byte--) { - out_file.put((word >> (byte * 8)) & 0xFF); - } - } - - uint32_t length_of_data = out_file.tellp() - end_of_header_pos; - - out_file.seekp(header_data_length_pos); - for (int byte = 3; byte >= 0; byte--) { - out_file.put((length_of_data >> (byte * 8)) & 0xFF); - } - return 0; -} - -template -typename BitstreamWriter::BitstreamHeader -BitstreamWriter::create_header(const std::string& part_name, - const std::string& frames_file_name, - const std::string& generator_name) { - // Sync header - BitstreamHeader bit_header{0x0, 0x9, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, - 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 'a'}; - auto build_source = - absl::StrCat(frames_file_name, ";Generator=" + generator_name); - bit_header.push_back( - static_cast((build_source.size() + 1) >> 8)); - bit_header.push_back(static_cast(build_source.size() + 1)); - bit_header.insert(bit_header.end(), build_source.begin(), - build_source.end()); - bit_header.push_back(0x0); - - // Source file. - bit_header.push_back('b'); - bit_header.push_back(static_cast((part_name.size() + 1) >> 8)); - bit_header.push_back(static_cast(part_name.size() + 1)); - bit_header.insert(bit_header.end(), part_name.begin(), part_name.end()); - bit_header.push_back(0x0); - - // Build timestamp. - auto build_time = absl::Now(); - auto build_date_string = - absl::FormatTime("%E4Y/%m/%d", build_time, absl::UTCTimeZone()); - auto build_time_string = - absl::FormatTime("%H:%M:%S", build_time, absl::UTCTimeZone()); - - bit_header.push_back('c'); - bit_header.push_back( - static_cast((build_date_string.size() + 1) >> 8)); - bit_header.push_back( - static_cast(build_date_string.size() + 1)); - bit_header.insert(bit_header.end(), build_date_string.begin(), - build_date_string.end()); - bit_header.push_back(0x0); - - bit_header.push_back('d'); - bit_header.push_back( - static_cast((build_time_string.size() + 1) >> 8)); - bit_header.push_back( - static_cast(build_time_string.size() + 1)); - bit_header.insert(bit_header.end(), build_time_string.begin(), - build_time_string.end()); - bit_header.push_back(0x0); - bit_header.insert(bit_header.end(), {'e', 0x0, 0x0, 0x0, 0x0}); - return bit_header; -} - -template -typename BitstreamWriter::packet_iterator -BitstreamWriter::iterator::packet_begin() { - // itr_packets = packets.begin(); - const ConfigurationPacket& packet = - **itr_packets_; - - return BitstreamWriter::packet_iterator( - &packet, BitstreamWriter::packet_iterator::STATE_HEADER, - packet.data().begin()); -} - -template -typename BitstreamWriter::packet_iterator -BitstreamWriter::iterator::packet_end() { - const ConfigurationPacket& packet = - **itr_packets_; - - return BitstreamWriter::packet_iterator( - &packet, BitstreamWriter::packet_iterator::STATE_END, - // Essentially ignored - packet.data().end()); -} - -template -BitstreamWriter::packet_iterator::packet_iterator( - const ConfigurationPacket* packet, - state_t state, - data_iterator_t itr_data) - : state_(state), itr_data_(itr_data), packet_(packet) {} - -template -typename BitstreamWriter::packet_iterator& - BitstreamWriter::packet_iterator::operator++() { - if (state_ == STATE_HEADER) { - itr_data_ = packet_->data().begin(); - if (itr_data_ == packet_->data().end()) { - state_ = STATE_END; - } else { - state_ = STATE_DATA; - } - } else if (state_ == STATE_DATA) { - /// Advance. data must be valid while not at end - itr_data_++; - // Reached this end of this packet? - if (itr_data_ == packet_->data().end()) { - state_ = STATE_END; - } - } - return *this; -} - -template -bool BitstreamWriter::packet_iterator::operator==( - const packet_iterator& other) const { - return state_ == other.state_ && itr_data_ == other.itr_data_; -} - -template -bool BitstreamWriter::packet_iterator::operator!=( - const packet_iterator& other) const { - return !(*this == other); -} - uint32_t packet2header( const ConfigurationPacket& packet) { uint32_t ret = 0; @@ -206,145 +44,5 @@ uint32_t packet2header( return ret; } -template -const typename BitstreamWriter::itr_value_type - BitstreamWriter::packet_iterator::operator*() const { - if (state_ == STATE_HEADER) { - return packet2header(*packet_); - } else if (state_ == STATE_DATA) { - return *itr_data_; - } - return 0; // XXX: assert or something? -} - -template -const typename BitstreamWriter::itr_value_type - BitstreamWriter::packet_iterator::operator->() const { - return *(*this); -} - -/************************************************** - * BitstreamWriter::iterator - *************************************************/ - -template -typename BitstreamWriter::iterator -BitstreamWriter::begin() { - typename packets_t::const_iterator itr_packets = packets_.begin(); - absl::optional op_packet_itr; - - // May have no packets - if (itr_packets != packets_.end()) { - // op_packet_itr = packet_begin(); - // FIXME: de-duplicate this - const ConfigurationPacket& - packet = **itr_packets; - packet_iterator packet_itr = - packet_iterator(&packet, packet_iterator::STATE_HEADER, - packet.data().begin()); - op_packet_itr = packet_itr; - } - return iterator(header_.begin(), packets_, itr_packets, op_packet_itr); -} - -template -typename BitstreamWriter::iterator BitstreamWriter::end() { - return iterator(header_.end(), packets_, packets_.end(), - absl::optional()); -} - -template -BitstreamWriter::iterator::iterator( - header_t::iterator itr_header, - const typename BitstreamWriter::packets_t& packets, - typename BitstreamWriter::packets_t::const_iterator itr_packets, - absl::optional itr_packet) - : itr_header_(itr_header), - packets_(packets), - itr_packets_(itr_packets), - op_itr_packet_(itr_packet) {} - -template -typename BitstreamWriter::iterator& - BitstreamWriter::iterator::operator++() { - // Still generating header? - if (itr_header_ != header_.end()) { - itr_header_++; - // Finished header? - // Will advance to initialized itr_packets value - // XXX: maybe should just overwrite here - if (itr_header_ == header_.end()) { - itr_packets_ = packets_.begin(); - if (itr_packets_ != packets_.end()) { - op_itr_packet_ = packet_begin(); - } - } - // Then somewhere in packets - } else { - // We are either at end() in which case this operation is - // invalid Or there is a packet in progress packet in progress? - // Advance it - ++(*op_itr_packet_); - // Done with this packet? - if (*op_itr_packet_ == packet_end()) { - itr_packets_++; - if (itr_packets_ == packets_.end()) { - // we are at the very end - // invalidate data to be neat - op_itr_packet_.reset(); - } else { - op_itr_packet_ = packet_begin(); - } - } - } - return *this; -} - -template -bool BitstreamWriter::iterator::operator==( - const iterator& other) const { - return itr_header_ == other.itr_header_ && - itr_packets_ == other.itr_packets_ && - op_itr_packet_ == other.op_itr_packet_; -} - -template -bool BitstreamWriter::iterator::operator!=( - const iterator& other) const { - return !(*this == other); -} - -template -const typename BitstreamWriter::itr_value_type - BitstreamWriter::iterator::operator*() const { - if (itr_header_ != header_.end()) { - return *itr_header_; - } else { - // Iterating over packets, get data from current packet position - return *(*op_itr_packet_); - } -} - -template -const typename BitstreamWriter::itr_value_type - BitstreamWriter::iterator::operator->() const { - return *(*this); -} - -template int BitstreamWriter::writeBitstream( - const Series7::ConfigurationPackage&, - const std::string&, - const std::string&, - const std::string&, - const std::string&); -template BitstreamWriter::iterator BitstreamWriter::begin(); -template BitstreamWriter::iterator BitstreamWriter::end(); -template const BitstreamWriter::itr_value_type - BitstreamWriter::iterator::operator*() const; -template BitstreamWriter::iterator& - BitstreamWriter::iterator::operator++(); -template bool BitstreamWriter::iterator::operator!=( - const BitstreamWriter::iterator&) const; - } // namespace xilinx } // namespace prjxray