int LatticeBitParser::parse()
{
/* until 0xFFFFBDB3 0xFFFF */
if (parseHeader() != EXIT_SUCCESS)
return EXIT_FAILURE;
/* check preamble */
if (_endHeader + 4 >= _raw_data.size()) {
printError("LatticeBitParser: truncated preamble");
return EXIT_FAILURE;
}
uint32_t preamble = (*(uint32_t *)&_raw_data[_endHeader + 1]);
//0xb3beffff is the preamble for encrypted bitstreams in Nexus fpgas
if ((preamble != 0xb3bdffff) && (preamble != 0xb3bfffff) && (preamble != 0xb3beffff)) {
printError("Error: missing preamble\n");
return EXIT_FAILURE;
}
printf("%08x\n", preamble);
if (preamble == 0xb3bdffff) {
/* 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;
}
std::map<std::string, std::string>::const_iterator part_it = _hdr.find("Part");
if (part_it == _hdr.end()) {
printError("LatticeBitParser: Missing Part in header section");
return EXIT_FAILURE;
}
std::string_view subpart(part_it->second);
const size_t pos = subpart.find_last_of('-');
if (pos == std::string_view::npos) {
printError("LatticeBitParser: invalid Part string");
return EXIT_FAILURE;
}
subpart = subpart.substr(0, pos);
for (const std::pair<const uint32_t, fpga_model> &fpga : fpga_list) {
if (fpga.second.manufacturer != "lattice")
continue;
const std::string_view model = fpga.second.model;
if (subpart.compare(0, model.size(), model) == 0) {
_hdr["idcode"] = fmtIdcode(fpga.first);
break;
}
}
}
/* read All data */
if (!_is_machXO2) {
/* According to FPGA-TN-02192-3.4
* the Lattice ECP3 must trasnmit at least 128 clock pulses before
* receiving the preamble.
* Here the header contains 3x8 Dummy bit + preamble so only
* 13bits 8x13= 112bits must be added as padding.
*/
const uint32_t offset = (_is_ecp3) ? 13 : 0;
_bit_data.resize(_raw_data.size() - _endHeader + offset);
if (_is_ecp3)
std::fill_n(_bit_data.begin(), offset, uint8_t{0xff});
std::move(_raw_data.begin() + _endHeader, _raw_data.end(), _bit_data.begin() + offset);
_bit_length = _bit_data.size() * 8;
} else {
_endHeader++;
const size_t len = _raw_data.size() - _endHeader;
const size_t array_len = (len + 15) / 16;
_bit_array.reserve(array_len);
for (size_t i = 0; i < len; i += 16) {
const size_t max_len = std::min<size_t>(16, len - i);
_bit_array.emplace_back(16, '\xff');
std::string &tmp = _bit_array.back();
for (uint32_t pos = 0; pos < max_len; pos++)
tmp[pos] = static_cast<char>(reverseByte(
static_cast<uint8_t>(_raw_data[_endHeader + i + pos])));
}
_bit_length = _bit_array.size() * 16 * 8;
}
printf("%s(%d) _bit_length=%u \n",__FUNCTION__,__LINE__,_bit_length);
return 0;
}