From c09bc0662b47f5675b61908a7990d0b599c30248 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Thu, 13 May 2021 12:14:52 +0200 Subject: [PATCH] ihexParser: new parser for (i)hex files --- CMakeLists.txt | 4 +- src/ihexParser.cpp | 125 +++++++++++++++++++++++++++++++++++++++++++++ src/ihexParser.hpp | 56 ++++++++++++++++++++ 3 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 src/ihexParser.cpp create mode 100644 src/ihexParser.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7778c4c..5ad6a05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ set(OPENFPGALOADER_SOURCE src/efinix.cpp src/efinixHexParser.cpp src/ice40.cpp + src/ihexParser.cpp src/spiFlash.cpp src/rawParser.cpp src/usbBlaster.cpp @@ -85,7 +86,8 @@ set(OPENFPGALOADER_HEADERS src/dirtyJtag.hpp src/efinix.hpp src/efinixHexParser.hpp - src/ice40.cpp + src/ice40.hpp + src/ihexParser.hpp src/progressBar.hpp src/rawParser.hpp src/usbBlaster.hpp diff --git a/src/ihexParser.cpp b/src/ihexParser.cpp new file mode 100644 index 0000000..e279504 --- /dev/null +++ b/src/ihexParser.cpp @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-v3 +/* + * Copyright (c) 2021 Gwenhael Goavec-Merou +*/ + + +#include +#include + +#include "configBitstreamParser.hpp" +#include "display.hpp" +#include "ihexParser.hpp" + +using namespace std; + +/* line format + * :LLAAAATTHH...HHCC + * LL : nb octets de data dans la ligne (hexa) + * AAAA : addresse du debut de la ligne ou mettre les data + * TT : type de la ligne (cf. plus bas) + * HH : le champ de data + * CC : Checksum (cf. plus bas) + */ +/* type : 00 -> data + addr 16b + * 01 -> end of file + * 02 -> extended addr + * 03 -> start segment addr record + * 04 -> extented linear addr record + * 05 -> start linear addr record + */ + +#define LEN_BASE 1 +#define ADDR_BASE 3 +#define TYPE_BASE 7 +#define DATA_BASE 9 + +IhexParser::IhexParser(const string &filename, bool reverseOrder, bool verbose): + ConfigBitstreamParser(filename, ConfigBitstreamParser::ASCII_MODE, + verbose), + _base_addr(0), _reverseOrder(reverseOrder) +{} + +int IhexParser::parse() +{ + string str; + istringstream lineStream(_raw_data); + + uint16_t next_addr = 0; + bool is_first = true; + data_line_t cnt; + cnt.length = 0; + + while (std::getline(lineStream, str, '\n')) { + char *ptr; + uint8_t sum = 0; + uint16_t tmp, byteLen, type, checksum; + uint32_t addr, loc_addr; + + /* if '\r' is present -> drop */ + if (str.back() == '\r') + str.pop_back(); + + if (str[0] == '#') // comment + continue; + if (str[0] != ':') { + printError("Error: a line must start with ':'"); + return EXIT_FAILURE; + } + /* len */ + sscanf((char *)&str[LEN_BASE], "%2hx", &byteLen); + /* address */ + sscanf((char *)&str[ADDR_BASE], "%4x", &addr); + /* type */ + sscanf((char *)&str[TYPE_BASE], "%2hx", &type); + /* checksum */ + sscanf((char *)&str[DATA_BASE + byteLen * 2], "%2hx", &checksum); + + sum = byteLen + type + (addr & 0xff) + ((addr >> 8) & 0xff); + + switch (type) { + case 0: + loc_addr = _base_addr + addr; + /* if this is the first line + * prepare structure with base address + * if previous address + line length didn't match new addr + * -> break -> store and start a new section + */ + if (next_addr != addr || is_first) { + if (!is_first) + _array_content.push_back(cnt); + cnt.addr = loc_addr; + cnt.length = 0; + cnt.line_data.clear(); + is_first = false; + } + + ptr = (char *)&str[DATA_BASE]; + for (int i = 0; i < byteLen; i++, ptr += 2) { + sscanf(ptr, "%2hx", &tmp); + _bit_data[loc_addr + i] = (_reverseOrder)? reverseByte(tmp):tmp; + sum += tmp; + cnt.line_data.push_back(_bit_data[loc_addr+i]); + } + cnt.length += byteLen; + next_addr = addr + byteLen; + _bit_length += (byteLen * 8); + break; + case 1: + if (cnt.length != 0) + _array_content.push_back(cnt); + return EXIT_SUCCESS; + break; + default: + printError("Error: unknown type"); + return EXIT_FAILURE; + } + + if (checksum != (0xff&((~sum)+1))) { + printError("Error: wrong checksum"); + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; +} diff --git a/src/ihexParser.hpp b/src/ihexParser.hpp new file mode 100644 index 0000000..481f546 --- /dev/null +++ b/src/ihexParser.hpp @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +/* + * Copyright (c) 2021 Gwenhael Goavec-Merou +*/ + +#ifndef SRC_IHEXPARSER_HPP_ +#define SRC_IHEXPARSER_HPP_ + +#include +#include + +#include "configBitstreamParser.hpp" + +/*! + * \file ihexParser + * \brief IhexParser + * \brief class used to read a (i)hex data file + * \author Gwenhael Goavec-Merou + */ +class IhexParser: public ConfigBitstreamParser { + public: + /*! + * \brief constructor + * \param[in] filename: file path + * \param[in] reverseOrder: MSB or LSB storage + * \param[in] verbose: verbosity level + */ + IhexParser(const std::string &filename, bool reverseOrder, bool verbose); + /*! + * \brief read full content of the file, fill sections + */ + int parse() override; + + /*! + * structure to store file content by section + */ + typedef struct { + uint16_t addr; + uint16_t length; + std::vector line_data; + } data_line_t; + + /*! + * \brief return list of sections + */ + std::vector getDataArray() {return _array_content;} + + private: + int _base_addr; + bool _reverseOrder; + std::vector _data; + std::vector _array_content; /**< list of sections */ +}; + +#endif // SRC_IHEXPARSER_HPP_ +