add parser for jed file (lattice)
This commit is contained in:
parent
da93384d6a
commit
89d874d156
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "jedParser.hpp"
|
||||
|
||||
/* GGM: TODO
|
||||
* - use NOTE for Lxxx
|
||||
* - be less lattice compliant
|
||||
*/
|
||||
|
||||
using namespace std;
|
||||
|
||||
JedParser::JedParser(string filename):
|
||||
ConfigBitstreamParser(filename, ConfigBitstreamParser::BIN_MODE),
|
||||
_fuse_count(0), _pin_count(0), _featuresRow(0), _feabits(0), _checksum(0)
|
||||
{
|
||||
}
|
||||
|
||||
/* fill a vector with consecutive lines until '*'
|
||||
*/
|
||||
vector<string> JedParser::readJEDLine()
|
||||
{
|
||||
string buffer;
|
||||
vector<string> lines;
|
||||
bool inLine = true;
|
||||
|
||||
do {
|
||||
std::getline(_fd, buffer, '\n');
|
||||
if (buffer.size() == 0)
|
||||
break;
|
||||
|
||||
if (buffer[buffer.size()-1] == '*') {
|
||||
inLine = false;
|
||||
buffer.pop_back();
|
||||
}
|
||||
lines.push_back(buffer);
|
||||
} while (inLine);
|
||||
return lines;
|
||||
}
|
||||
|
||||
/* convert one serie ASCII 1/0 to a vector of
|
||||
* unsigned char
|
||||
*/
|
||||
void JedParser::buildDataArray(const string &content, struct jed_data &jed)
|
||||
{
|
||||
size_t data_len = content.size();
|
||||
string tmp_buff;
|
||||
uint8_t data = 0;
|
||||
for (size_t i = 0; i < content.size(); i+=8) {
|
||||
data = 0;
|
||||
for (int ii = 0; ii < 8; ii++) {
|
||||
uint8_t val = (content[i+ii] == '1'?1:0);
|
||||
data |= val << ii;
|
||||
}
|
||||
tmp_buff += data;
|
||||
}
|
||||
jed.data.push_back(std::move(tmp_buff));
|
||||
jed.len += data_len;
|
||||
}
|
||||
|
||||
void JedParser::display()
|
||||
{
|
||||
printf("feabits :\n");
|
||||
printf("%04x <-> %d\n", _feabits, _feabits);
|
||||
/* 15-14: always 0 */
|
||||
printf("\tBoot Mode : ");
|
||||
switch ((_feabits>>11)&0x07) {
|
||||
case 0:
|
||||
printf("Single Boot from Configuration Flash\n");
|
||||
break;
|
||||
case 1:
|
||||
printf("Dual Boot from Configuration Flash then External if there is a failure\n");
|
||||
break;
|
||||
case 3:
|
||||
printf("Single Boot from External Flash\n");
|
||||
break;
|
||||
default:
|
||||
printf("Error\n");
|
||||
}
|
||||
|
||||
printf("\tMaster Mode SPI : %s\n",
|
||||
(((_feabits>>11)&0x01)?"enable":"disable"));
|
||||
printf("\tI2c port : %s\n",
|
||||
(((_feabits>>10)&0x01)?"disable":"enable"));
|
||||
printf("\tSlave SPI port : %s\n",
|
||||
(((_feabits>>9)&0x01)?"disable":"enable"));
|
||||
printf("\tJTAG port : %s\n",
|
||||
(((_feabits>>8)&0x01)?"disable":"enable"));
|
||||
printf("\tDONE : %s\n",
|
||||
(((_feabits>>7)&0x01)?"enable":"disable"));
|
||||
printf("\tINITN : %s\n",
|
||||
(((_feabits>>6)&0x01)?"enable":"disable"));
|
||||
printf("\tPROGRAMN : %s\n",
|
||||
(((_feabits>>5)&0x01)?"disable":"enable"));
|
||||
printf("\tMy_ASSP : %s\n",
|
||||
(((_feabits>>4)&0x01)?"enable":"disable"));
|
||||
/* 3-0: always 0 */
|
||||
|
||||
printf("Pin Count : %d\n", _pin_count);
|
||||
printf("Fuse Count : %d\n", _fuse_count);
|
||||
}
|
||||
|
||||
/* E field, for latice contains two sub-field
|
||||
* 1: Exxxx\n : feature Row
|
||||
* 2: yyyy*\n : feabits
|
||||
*/
|
||||
void JedParser::parseEField(vector<string> content)
|
||||
{
|
||||
_featuresRow = 0;
|
||||
string featuresRow = content[0].substr(1);
|
||||
for (size_t i = 0; i < featuresRow.size(); i++)
|
||||
_featuresRow |= ((featuresRow[i] - '0') << i);
|
||||
string feabits = content[1];
|
||||
_feabits = 0;
|
||||
for (size_t i = 0; i < feabits.size(); i++) {
|
||||
_feabits |= ((feabits[i] - '0') << i);
|
||||
}
|
||||
}
|
||||
|
||||
void JedParser::parseLField(vector<string> content)
|
||||
{
|
||||
int start_offset;
|
||||
sscanf(content[0].substr(1).c_str(), "%d", &start_offset);
|
||||
/* two possibilities
|
||||
* current line finish with '*' : Lxxxx YYYYY*<EOF>
|
||||
* or current line is only offset and next(s) line(s) are data :
|
||||
* Lxxxx<EOF>
|
||||
*/
|
||||
struct jed_data d;
|
||||
string buffer;
|
||||
d.offset = start_offset;
|
||||
d.len = 0;
|
||||
if (content.size() > 1) {
|
||||
for (size_t i = 1; i < content.size(); i++) {
|
||||
if (content[i].size() != 0)
|
||||
buildDataArray((content[i]), d);
|
||||
}
|
||||
} else {
|
||||
// search space
|
||||
std::istringstream iss(content[0]);
|
||||
vector<string> myList((std::istream_iterator<string>(iss)),
|
||||
std::istream_iterator<string>());
|
||||
myList[1].pop_back();
|
||||
buildDataArray(myList[1], d);
|
||||
}
|
||||
_data_list.push_back(std::move(d));
|
||||
}
|
||||
|
||||
int JedParser::parse()
|
||||
{
|
||||
if (!_fd.is_open()) {
|
||||
_fd.open(_filename);
|
||||
if (!_fd.is_open()) {
|
||||
cerr << "error to opening jed file " << _filename << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
string content;
|
||||
|
||||
_fd.seekg(0, _fd.beg);
|
||||
|
||||
/* First line must STX (0x02) */
|
||||
std::getline(_fd, content, '\n');
|
||||
if (content[0] != 0x02) {
|
||||
printf("wrong file\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read full content
|
||||
* JED file end fix ETX (0x03) + file checksum + \n
|
||||
*/
|
||||
std::vector<string>lines;
|
||||
do {
|
||||
lines = readJEDLine();
|
||||
if (lines.size() == 0) {
|
||||
printf("a un problem\n");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (lines[0][0]) {
|
||||
case 'N': // note
|
||||
break;
|
||||
case 'Q':
|
||||
int count;
|
||||
sscanf(lines[0].c_str()+2, "%d", &count);
|
||||
switch (lines[0][1]) {
|
||||
case 'F': // fuse count
|
||||
_fuse_count = count;
|
||||
break;
|
||||
case 'P': // pin count
|
||||
_pin_count = count;
|
||||
break;
|
||||
default:
|
||||
cerr << "Error for 'Q' unknown qualifier " << lines[1] << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
case 'G':
|
||||
cout << lines[0] << endl;
|
||||
break;
|
||||
case 'F':
|
||||
cout << lines[0] << endl;
|
||||
break;
|
||||
case 'C':
|
||||
sscanf(lines[0].c_str() + 1, "%hx", &_checksum);
|
||||
cout << "fuse checksum " << lines[0];
|
||||
printf(" AA %x\n", _checksum);
|
||||
break;
|
||||
case 0x03:
|
||||
cout << "end" << endl;
|
||||
break;
|
||||
case 'E':
|
||||
parseEField(lines);
|
||||
break;
|
||||
case 'L': // fuse offset
|
||||
parseLField(lines);
|
||||
break;
|
||||
default:
|
||||
printf("inconnu\n");
|
||||
cout << lines[0]<< endl;
|
||||
}
|
||||
} while (lines[0][0] != 0x03);
|
||||
|
||||
int size = 0;
|
||||
for (size_t i = 0; i < _data_list.size(); i++) {
|
||||
printf("area[%ld] %d %d\n", i, _data_list[i].offset, _data_list[i].len);
|
||||
size += _data_list[i].len;
|
||||
}
|
||||
|
||||
uint16_t checksum = 0;
|
||||
for (size_t line = 0; line < _data_list[0].data.size(); line++) {
|
||||
for (size_t col = 0; col < _data_list[0].data[line].size(); col++)
|
||||
checksum += (uint8_t)_data_list[0].data[line][col];
|
||||
}
|
||||
|
||||
printf("theorical checksum %x -> %x\n", _checksum, checksum);
|
||||
|
||||
FILE *fd = fopen("toto.txt", "w+");
|
||||
for (size_t line = 0; line < _data_list[0].data.size(); line++) {
|
||||
for (size_t col = 0; col < _data_list[0].data[line].size(); col++)
|
||||
fprintf(fd, "%02x ", (unsigned char)_data_list[0].data[line][col]);
|
||||
fprintf(fd, "\n");
|
||||
}
|
||||
fclose(fd);
|
||||
printf("array size %ld\n", _data_list[0].data.size());
|
||||
|
||||
if (_fuse_count != size)
|
||||
cerr << "Not all fuses are programmed" << endl;
|
||||
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef JEDPARSER_HPP_
|
||||
#define JEDPARSER_HPP_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "configBitstreamParser.hpp"
|
||||
|
||||
class JedParser: public ConfigBitstreamParser {
|
||||
private:
|
||||
struct jed_data {
|
||||
int offset;
|
||||
std::vector<std::string> data;
|
||||
int len;
|
||||
};
|
||||
|
||||
public:
|
||||
JedParser(std::string filename);
|
||||
int parse();
|
||||
void display();
|
||||
|
||||
size_t nb_section() { return _data_list.size();}
|
||||
size_t offset_for_section(int id) {return _data_list[id].offset;}
|
||||
std::vector<std::string> data_for_section(int id) {
|
||||
return _data_list[id].data;
|
||||
}
|
||||
uint32_t feabits() {return _feabits;}
|
||||
uint64_t featuresRow() {return _featuresRow;}
|
||||
|
||||
private:
|
||||
std::vector<std::string>readJEDLine();
|
||||
void buildDataArray(const std::string &content, struct jed_data &jed);
|
||||
void parseEField(const std::vector<std::string> content);
|
||||
void parseLField(const std::vector<std::string> content);
|
||||
|
||||
std::vector<struct jed_data> _data_list;
|
||||
int _fuse_count;
|
||||
int _pin_count;
|
||||
uint64_t _featuresRow;
|
||||
uint16_t _feabits;
|
||||
uint16_t _checksum;
|
||||
};
|
||||
|
||||
#endif // JEDPARSER_HPP_
|
||||
Loading…
Reference in New Issue