diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 9aee7afd..0aee1b1f 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -5,7 +5,6 @@ add_library(libprjxray xilinx/bitstream_writer.cc xilinx/configuration_packet.cc xilinx/configuration_register.cc - xilinx/frames.cc xilinx/configuration.cc # Series-7 specific xilinx/xc7series/frame_address.cc 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/include/prjxray/xilinx/frames.h b/lib/include/prjxray/xilinx/frames.h index 43747875..c39a125c 100644 --- a/lib/include/prjxray/xilinx/frames.h +++ b/lib/include/prjxray/xilinx/frames.h @@ -1,11 +1,15 @@ #ifndef PRJXRAY_LIB_XILINX_FRAMES_H #define PRJXRAY_LIB_XILINX_FRAMES_H +#include +#include #include #include #include +#include #include +#include namespace prjxray { namespace xilinx { @@ -29,15 +33,93 @@ class Frames { const absl::optional& part); // Returns the map with frame addresses and corresponding data - Frames2Data& getFrames(); + Frames2Data& getFrames() { return frames_data_; } private: Frames2Data frames_data_; - // Updates the ECC information in the frame. + // Updates the ECC information in the frame void updateECC(FrameData& data); }; +template +void Frames::updateECC(typename Frames::FrameData& data) { + xc7series::updateECC(data); +} + +template +int Frames::readFrames(const std::string& frm_file_str) { + assert(!frm_file_str.empty()); + + std::ifstream frm_file(frm_file_str); + if (!frm_file) { + std::cerr << "Unable to open frm file: " << frm_file_str + << std::endl; + return 1; + } + std::string frm_line; + + while (std::getline(frm_file, frm_line)) { + if (frm_line[0] == '#') + continue; + + std::pair frame_delta = + absl::StrSplit(frm_line, ' '); + + uint32_t frame_address = + std::stoul(frame_delta.first, nullptr, 16); + + std::vector frame_data_strings = + absl::StrSplit(frame_delta.second, ','); + + if (frame_data_strings.size() != ArchType::words_per_frame) { + std::cerr << "Frame " << std::hex << frame_address + << ": found " << std::dec + << frame_data_strings.size() + << " words instead of " + << ArchType::words_per_frame << std::endl; + continue; + } + + FrameData frame_data(frame_data_strings.size(), 0); + std::transform(frame_data_strings.begin(), + frame_data_strings.end(), frame_data.begin(), + [](const std::string& val) -> uint32_t { + return std::stoul(val, nullptr, 16); + }); + + updateECC(frame_data); + + // Insert the frame address and corresponding frame data to the + // map + typename ArchType::FrameAddress frm_addr(frame_address); + frames_data_.insert( + std::pair( + frm_addr, frame_data)); + } + return 0; +} + +template +void Frames::addMissingFrames( + const absl::optional& part) { + auto current_frame_address = + absl::optional( + typename ArchType::FrameAddress(0)); + do { + auto iter = frames_data_.find(*current_frame_address); + if (iter == frames_data_.end()) { + FrameData frame_data(ArchType::words_per_frame, 0); + frames_data_.insert( + std::pair(*current_frame_address, + frame_data)); + } + current_frame_address = + part->GetNextFrameAddress(*current_frame_address); + } while (current_frame_address); +} + } // namespace xilinx } // namespace prjxray diff --git a/lib/include/prjxray/xilinx/xc7series/ecc.h b/lib/include/prjxray/xilinx/xc7series/ecc.h index 40e131b3..63513fd9 100644 --- a/lib/include/prjxray/xilinx/xc7series/ecc.h +++ b/lib/include/prjxray/xilinx/xc7series/ecc.h @@ -2,6 +2,7 @@ #define PRJXRAY_LIB_XILINX_XC7SERIES_ECC_H_ #include +#include namespace prjxray { namespace xilinx { @@ -9,9 +10,11 @@ namespace xc7series { // Extend the current ECC code with one data word (32 bit) at a given // word index in the configuration frame and return the new ECC code. - uint32_t icap_ecc(uint32_t idx, uint32_t data, uint32_t ecc); +// Updates the ECC information in the frame. +void updateECC(std::vector& data); + } // namespace xc7series } // 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 diff --git a/lib/xilinx/frames.cc b/lib/xilinx/frames.cc deleted file mode 100644 index 9ffd50cd..00000000 --- a/lib/xilinx/frames.cc +++ /dev/null @@ -1,113 +0,0 @@ -#include -#include - -#include - -#include -#include - -namespace prjxray { -namespace xilinx { - -template -typename Frames::Frames2Data& Frames::getFrames() { - return frames_data_; -} - -template -int Frames::readFrames(const std::string& frm_file_str) { - assert(!frm_file_str.empty()); - - std::ifstream frm_file(frm_file_str); - if (!frm_file) { - std::cerr << "Unable to open frm file: " << frm_file_str - << std::endl; - return 1; - } - std::string frm_line; - - while (std::getline(frm_file, frm_line)) { - if (frm_line[0] == '#') - continue; - - std::pair frame_delta = - absl::StrSplit(frm_line, ' '); - - uint32_t frame_address = - std::stoul(frame_delta.first, nullptr, 16); - - std::vector frame_data_strings = - absl::StrSplit(frame_delta.second, ','); - - if (frame_data_strings.size() != ArchType::words_per_frame) { - std::cerr << "Frame " << std::hex << frame_address - << ": found " << std::dec - << frame_data_strings.size() - << " words instead of " - << ArchType::words_per_frame << std::endl; - continue; - } - - FrameData frame_data(frame_data_strings.size(), 0); - std::transform(frame_data_strings.begin(), - frame_data_strings.end(), frame_data.begin(), - [](const std::string& val) -> uint32_t { - return std::stoul(val, nullptr, 16); - }); - - updateECC(frame_data); - - // Insert the frame address and corresponding frame data to the - // map - typename ArchType::FrameAddress frm_addr(frame_address); - frames_data_.insert( - std::pair( - frm_addr, frame_data)); - } - return 0; -} - -template -void Frames::addMissingFrames( - const absl::optional& part) { - auto current_frame_address = - absl::optional( - typename ArchType::FrameAddress(0)); - do { - auto iter = frames_data_.find(*current_frame_address); - if (iter == frames_data_.end()) { - FrameData frame_data(ArchType::words_per_frame, 0); - frames_data_.insert( - std::pair(*current_frame_address, - frame_data)); - } - current_frame_address = - part->GetNextFrameAddress(*current_frame_address); - } while (current_frame_address); -} - -static uint32_t calculateECC(const typename Frames::FrameData& data) { - uint32_t ecc = 0; - for (size_t ii = 0; ii < data.size(); ++ii) { - ecc = xc7series::icap_ecc(ii, data[ii], ecc); - } - return ecc; -} - -template <> -void Frames::updateECC(FrameData& data) { - assert(data.size() != 0); - // Replace the old ECC with the new. - data[0x32] &= 0xFFFFE000; - data[0x32] |= (calculateECC(data) & 0x1FFF); -} - -template Frames::Frames2Data& Frames::getFrames(); -template void Frames::addMissingFrames( - const absl::optional& part); -template int Frames::readFrames(const std::string&); -template void Frames::updateECC(Frames::FrameData&); - -} // namespace xilinx -} // namespace prjxray diff --git a/lib/xilinx/xc7series/ecc.cc b/lib/xilinx/xc7series/ecc.cc index 7c56cb8e..a3a5cb22 100644 --- a/lib/xilinx/xc7series/ecc.cc +++ b/lib/xilinx/xc7series/ecc.cc @@ -1,9 +1,13 @@ #include +#include +#include namespace prjxray { namespace xilinx { namespace xc7series { +constexpr size_t kECCFrameNumber = 0x32; + uint32_t icap_ecc(uint32_t idx, uint32_t data, uint32_t ecc) { uint32_t val = idx * 32; // bit offset @@ -36,6 +40,21 @@ uint32_t icap_ecc(uint32_t idx, uint32_t data, uint32_t ecc) { return ecc; } +static uint32_t calculateECC(const std::vector& data) { + uint32_t ecc = 0; + for (size_t ii = 0; ii < data.size(); ++ii) { + ecc = xc7series::icap_ecc(ii, data[ii], ecc); + } + return ecc; +} + +void updateECC(std::vector& data) { + assert(data.size() >= kECCFrameNumber); + // Replace the old ECC with the new. + data[kECCFrameNumber] &= 0xFFFFE000; + data[kECCFrameNumber] |= (calculateECC(data) & 0x1FFF); +} + } // namespace xc7series } // namespace xilinx } // namespace prjxray