ihexParser: new parser for (i)hex files

This commit is contained in:
Gwenhael Goavec-Merou 2021-05-13 12:14:52 +02:00
parent bbc1c4dde4
commit c09bc0662b
3 changed files with 184 additions and 1 deletions

View File

@ -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

125
src/ihexParser.cpp Normal file
View File

@ -0,0 +1,125 @@
// SPDX-License-Identifier: GPL-v3
/*
* Copyright (c) 2021 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
*/
#include <sstream>
#include <string>
#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;
}

56
src/ihexParser.hpp Normal file
View File

@ -0,0 +1,56 @@
// SPDX-License-Identifier: GPL-3.0-or-later
/*
* Copyright (c) 2021 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
*/
#ifndef SRC_IHEXPARSER_HPP_
#define SRC_IHEXPARSER_HPP_
#include <string>
#include <vector>
#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<uint8_t> line_data;
} data_line_t;
/*!
* \brief return list of sections
*/
std::vector<data_line_t> getDataArray() {return _array_content;}
private:
int _base_addr;
bool _reverseOrder;
std::vector<uint32_t> _data;
std::vector<data_line_t> _array_content; /**< list of sections */
};
#endif // SRC_IHEXPARSER_HPP_