| #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); | 
 | } |