diff --git a/src/latticeBitParser.cpp b/src/latticeBitParser.cpp index 55d546c..b33a45e 100644 --- a/src/latticeBitParser.cpp +++ b/src/latticeBitParser.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 /* - * Copyright (C) 2019 Gwenhael Goavec-Merou + * Copyright (C) 2019-2022 Gwenhael Goavec-Merou */ #include #include @@ -21,9 +21,10 @@ using namespace std; -LatticeBitParser::LatticeBitParser(const string &filename, bool verbose): +LatticeBitParser::LatticeBitParser(const string &filename, bool machxo2, + bool verbose): ConfigBitstreamParser(filename, ConfigBitstreamParser::BIN_MODE, verbose), - _endHeader(0) + _endHeader(0), _is_machXO2(machxo2) {} LatticeBitParser::~LatticeBitParser() @@ -46,7 +47,8 @@ int LatticeBitParser::parseHeader() } /* bit file comment area start with 0xff00 */ - if ((uint8_t)_raw_data[currPos] != 0xff || (uint8_t)_raw_data[currPos + 1] != 0x00) { + if ((uint8_t)_raw_data[currPos] != 0xff || + (uint8_t)_raw_data[currPos + 1] != 0x00) { printf("Wrong File %02x%02x\n", (uint8_t) _raw_data[currPos], (uint8_t)_raw_data[currPos]); return EXIT_FAILURE; @@ -76,7 +78,7 @@ int LatticeBitParser::parseHeader() istringstream lineStream(_raw_data.substr(currPos, _endHeader-currPos)); string buff; while (std::getline(lineStream, buff, '\0')) { - size_t pos = buff.find_first_of(':', 0); + pos = buff.find_first_of(':', 0); if (pos != string::npos) { string key(buff.substr(0, pos)); string val(buff.substr(pos+1, buff.size())); @@ -101,26 +103,17 @@ int LatticeBitParser::parse() return EXIT_FAILURE; } - /* read All data */ - _bit_data.resize(_raw_data.size() - _endHeader); - std::move(_raw_data.begin()+_endHeader, _raw_data.end(), _bit_data.begin()); - _bit_length = _bit_data.size() * 8; - if (preamble == 0xb3bdffff) { - /* extract idcode from configuration data (area starting with 0xE2) */ - for (size_t i = 0; i < _bit_data.size();i++) { - if ((uint8_t)_bit_data[i] != 0xe2) - continue; - /* E2: verif id */ - uint32_t idcode = (((uint32_t)_bit_data[i+4]) << 24) | - (((uint32_t)_bit_data[i+5]) << 16) | - (((uint32_t)_bit_data[i+6]) << 8) | - (((uint32_t)_bit_data[i+7]) << 0); - _hdr["idcode"] = string(8, ' '); - snprintf(&_hdr["idcode"][0], 9, "%08x", idcode); - break; + /* extract idcode from configuration data (area starting with 0xE2) + * and check compression when machXO2 + */ + if (parseCfgData() == false) + return EXIT_FAILURE; + } else { // encrypted bitstream + if (_is_machXO2) { + printError("encrypted bitstream not supported for machXO2"); + return EXIT_FAILURE; } - } else { // encrypted bitstream string part = getHeaderVal("Part"); string subpart = part.substr(0, part.find_last_of("-")); for (auto && fpga : fpga_list) { @@ -134,5 +127,86 @@ int LatticeBitParser::parse() } } + /* read All data */ + if (!_is_machXO2) { + _bit_data.resize(_raw_data.size() - _endHeader); + std::move(_raw_data.begin()+_endHeader, _raw_data.end(), _bit_data.begin()); + _bit_length = _bit_data.size() * 8; + } else { + _endHeader += 1; + uint32_t len = _raw_data.size() - _endHeader; + uint32_t max_len = 16; + for (uint32_t i = 0; i < len; i+=max_len) { + std::string tmp(16, 0xff); + /* each line must have 16B */ + if (len < i + max_len) + max_len = len - i; + for (uint32_t pos = 0; pos < max_len; pos++) + tmp[pos] = reverseByte(_raw_data[i+pos+_endHeader]); + _bit_array.push_back(std::move(tmp)); + } + _bit_length = _bit_array.size() * 16 * 8; + } + return 0; } + +#define LSC_WRITE_COMP_DIC 0x02 +#define LSC_PROG_CNTRL0 0x22 +#define LSC_RESET_CRC 0x3B +#define LSC_INIT_ADDRESS 0x46 +#define LSC_PROG_INCR_CMP 0xB8 +#define LSC_PROG_INCR_RTI 0x82 +#define VERIFY_ID 0xE2 +#define BYPASS 0xFF + +bool LatticeBitParser::parseCfgData() +{ + uint8_t *ptr; + size_t pos = _endHeader + 5; // drop preamble + uint32_t idcode; + while (pos < _raw_data.size()) { + uint8_t cmd = (uint8_t) _raw_data[pos++]; + switch (cmd) { + case BYPASS: + break; + case LSC_RESET_CRC: + pos += 3; + break; + case VERIFY_ID: + ptr = (uint8_t*)&_raw_data[pos]; + idcode = (((uint32_t)ptr[3]) << 24) | + (((uint32_t)ptr[4]) << 16) | + (((uint32_t)ptr[5]) << 8) | + (((uint32_t)ptr[6]) << 0); + _hdr["idcode"] = string(8, ' '); + snprintf(&_hdr["idcode"][0], 9, "%08x", idcode); + pos += 7; + if (!_is_machXO2) + return true; + break; + case LSC_WRITE_COMP_DIC: + pos += 11; + break; + case LSC_PROG_CNTRL0: + pos += 7; + break; + case LSC_INIT_ADDRESS: + pos += 3; + break; + case LSC_PROG_INCR_CMP: + return true; + break; + case LSC_PROG_INCR_RTI: + printError("Bitstream is not compressed- not writing."); + return false; + default: + char mess[256]; + snprintf(mess, 256, "Unknown command type %02x.\n", cmd); + printError(mess); + return false; + } + } + + return false; +} diff --git a/src/latticeBitParser.hpp b/src/latticeBitParser.hpp index 29a90c0..da24b87 100644 --- a/src/latticeBitParser.hpp +++ b/src/latticeBitParser.hpp @@ -1,26 +1,38 @@ // SPDX-License-Identifier: Apache-2.0 /* - * Copyright (C) 2019 Gwenhael Goavec-Merou + * Copyright (C) 2019-2022 Gwenhael Goavec-Merou */ -#ifndef LATTICEBITPARSER_HPP_ -#define LATTICEBITPARSER_HPP_ +#ifndef SRC_LATTICEBITPARSER_HPP_ +#define SRC_LATTICEBITPARSER_HPP_ #include #include #include #include +#include #include "configBitstreamParser.hpp" class LatticeBitParser: public ConfigBitstreamParser { public: - LatticeBitParser(const std::string &filename, bool verbose = false); + LatticeBitParser(const std::string &filename, bool machxo2, + bool verbose = false); ~LatticeBitParser(); int parse() override; + /*! + * \brief return configuration data with structure similar to jedec + * \return configuration data + */ + std::vector getDataArray() {return _bit_array;} + private: int parseHeader(); + bool parseCfgData(); size_t _endHeader; + bool _is_machXO2; + /* data storage for machXO2 */ + std::vector _bit_array; }; -#endif // LATTICEBITPARSER_HPP_ +#endif // SRC_LATTICEBITPARSER_HPP_