mirror of https://github.com/openXC7/prjxray.git
106 lines
3.1 KiB
C++
106 lines
3.1 KiB
C++
|
|
#include "header.h"
|
||
|
|
#include <algorithm>
|
||
|
|
#include <ctime>
|
||
|
|
#include <sstream>
|
||
|
|
|
||
|
|
Header::Header(const std::string& line,
|
||
|
|
std::vector<uint32_t>& fpga_config_packets) {
|
||
|
|
absl::string_view header_str(line);
|
||
|
|
// Go to tag 'a' of the TLV formatted header
|
||
|
|
header_str.remove_prefix(header_str.find("61"));
|
||
|
|
bool tlv_header_end = false;
|
||
|
|
while (!tlv_header_end) {
|
||
|
|
char tag = char(GetByteAndAdvance(header_str));
|
||
|
|
switch (tag) {
|
||
|
|
case 'a':
|
||
|
|
design_name_ = GetTLVHeaderValue(header_str);
|
||
|
|
break;
|
||
|
|
case 'b':
|
||
|
|
part_ = GetTLVHeaderValue(header_str);
|
||
|
|
break;
|
||
|
|
case 'c':
|
||
|
|
date_ = GetTLVHeaderValue(header_str);
|
||
|
|
break;
|
||
|
|
case 'd':
|
||
|
|
date_ += " " + GetTLVHeaderValue(header_str);
|
||
|
|
break;
|
||
|
|
case 'e':
|
||
|
|
// Get number of bytes in bitstream and multiply
|
||
|
|
// by 8 to obtain number of bits
|
||
|
|
no_bits_ = GetWord(header_str) * 8;
|
||
|
|
tlv_header_end = true;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
assert(false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
while (!header_str.empty()) {
|
||
|
|
fpga_config_packets.emplace_back(GetWord(header_str));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string Header::GetDate() {
|
||
|
|
int year, month, day, hour, min, sec;
|
||
|
|
std::replace_if(date_.begin(), date_.end(),
|
||
|
|
[](char c) { return c == '/' or c == ':'; }, ' ');
|
||
|
|
std::istringstream(date_) >> year >> month >> day >> hour >> min >> sec;
|
||
|
|
std::tm time_raw = {sec, min, hour, day, month - 1, year - 1900};
|
||
|
|
time_t time = mktime(&time_raw);
|
||
|
|
const std::tm* time_out = std::localtime(&time);
|
||
|
|
return std::string(std::asctime(time_out));
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string Header::GetArchitecture() {
|
||
|
|
if (part_.find("xczu") != std::string::npos) {
|
||
|
|
return "zynquplus";
|
||
|
|
}
|
||
|
|
if (part_.find("7a") != std::string::npos) {
|
||
|
|
return "artix7";
|
||
|
|
}
|
||
|
|
if (part_.find("xcku") != std::string::npos) {
|
||
|
|
return "kintexu";
|
||
|
|
}
|
||
|
|
return "Unknown architecture";
|
||
|
|
}
|
||
|
|
|
||
|
|
void Header::Write(std::ostream& out) {
|
||
|
|
out << "Xilinx ASCII Bitstream" << std::endl;
|
||
|
|
out << "Created by" << std::endl;
|
||
|
|
out << "Design name: " << design_name_ << std::endl;
|
||
|
|
out << "Architecture: " << GetArchitecture() << std::endl;
|
||
|
|
out << "Part: " << part_ << std::endl;
|
||
|
|
out << "Date: " << GetDate();
|
||
|
|
out << "Bits: " << no_bits_ << std::endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
size_t Header::GetByteAndAdvance(absl::string_view& str_view) {
|
||
|
|
size_t space_pos(str_view.find(" "));
|
||
|
|
size_t byte =
|
||
|
|
std::stoul(std::string(str_view.substr(0, space_pos)), nullptr, 16);
|
||
|
|
str_view.remove_prefix((space_pos != absl::string_view::npos)
|
||
|
|
? space_pos + 1
|
||
|
|
: str_view.size());
|
||
|
|
return byte;
|
||
|
|
}
|
||
|
|
|
||
|
|
size_t Header::GetTLVHeaderLength(absl::string_view& str_view) {
|
||
|
|
return (GetByteAndAdvance(str_view) << 8) | GetByteAndAdvance(str_view);
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string Header::GetTLVHeaderValue(absl::string_view& str_view) {
|
||
|
|
size_t length(GetTLVHeaderLength(str_view));
|
||
|
|
std::string value;
|
||
|
|
for (size_t i = 0; i < length; i++) {
|
||
|
|
value += char(GetByteAndAdvance(str_view));
|
||
|
|
}
|
||
|
|
// Lose trailing 0x00
|
||
|
|
value.pop_back();
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint32_t Header::GetWord(absl::string_view& str_view) {
|
||
|
|
return (GetByteAndAdvance(str_view) << 24) |
|
||
|
|
(GetByteAndAdvance(str_view) << 16) |
|
||
|
|
(GetByteAndAdvance(str_view) << 8) | GetByteAndAdvance(str_view);
|
||
|
|
}
|