// SPDX-License-Identifier: Apache-2.0 /* * Copyright (C) 2021 Martin Beynon */ #include #include #include #include #include #include #include #include #include #include #include #include #include "display.hpp" #include "feaparser.hpp" using namespace std; FeaParser::FeaParser(string filename, bool verbose): ConfigBitstreamParser(filename, ConfigBitstreamParser::BIN_MODE, verbose), _feabits(0), _has_feabits(false) { for (int i=0; i < 3; i++) _featuresRow[i] = 0; } /* fill a vector with consecutive lines, begining with 0 or 1, until EOF * \brief read a line with '\r''\n' or '\n' termination * check if last char is '\r' * \return a vector of lines without [\r]\n */ vector FeaParser::readFeaFile() { vector lines; while (true) { string buffer; std::getline(_ss, buffer, '\n'); if (buffer.empty()) break; /* if '\r' is present -> drop */ if (buffer.back() == '\r') buffer.pop_back(); if (buffer.front() == '0' || buffer.front() == '1') lines.push_back(buffer); } return lines; } void FeaParser::displayHeader() { if (_has_feabits) { printf("\nFeature Row: [0x"); for(int i = 2; i >= 0; i--) { printf("%08x", _featuresRow[i]); } printf("]\n"); printf("\tCore Clock Select : 0x%x\n", (_featuresRow[2] >> 30) & 0x03); printf("\tCPU : %d\n", ((_featuresRow[2] & FEATURE_CPU)? 1 : 0)); printf("\tSSPI Auto : %s\n", ((_featuresRow[2] & FEATURE_SSPI_AUTO)?"Enabled":"Disabled")); printf("\tReserved Zero (1) : 0x%x\n", (_featuresRow[2] >> 27) & 0x01); printf("\tEBR Enable : %s\n", ((_featuresRow[2] & FEATURE_EBR_ENABLE)?"Yes":"No")); printf("\tHSE Clock Select : 0x%x\n", (_featuresRow[2] >> 24) & 0x03); printf("\tCPHA : %s\n", ((_featuresRow[2] & FEATURE_CPHA)?"Enabled":"Disabled")); printf("\tCPOL : %s\n", ((_featuresRow[2] & FEATURE_CPOL)?"Enabled":"Disabled")); printf("\tTx Edge : %s\n", ((_featuresRow[2] & FEATURE_TX_EDGE)?"Enabled":"Disabled")); printf("\tRx Edge : %s\n", ((_featuresRow[2] & FEATURE_RX_EDGE)?"Enabled":"Disabled")); printf("\tLSBF : %s\n", ((_featuresRow[2] & FEATURE_LSBF)?"Enabled":"Disabled")); printf("\tMClock Bypass : %s\n", ((_featuresRow[2] & FEATURE_MCLK_BYPASS)?"Enabled":"Disabled")); printf("\t32-bit SPIM : %s\n", ((_featuresRow[2] & FEATURE_32BIT_SPIM)?"Enabled":"Disabled")); printf("\tBulk Erase Disable : %s\n", ((_featuresRow[2] & FEATURE_BULK_ERASE_DISABLE)?"Yes":"No")); printf("\tSFDP Enable : %s\n", ((_featuresRow[2] & FEATURE_SFDP_EN)?"Yes":"No")); printf("\tSFDP Continue on Fail : %s\n", ((_featuresRow[2] & FEATURE_SFDP_CONT_FAIL)?"Yes":"No")); printf("\tReserved Zero (2) : 0x%x\n", (_featuresRow[2] >> 12) & 0x03); printf("\tSlave Idle Timer Count: %d\n", (_featuresRow[2] >> 8) & 0x0f); printf("\tMaster Timer Count : %d\n", (_featuresRow[2] >> 4) & 0x0f); printf("\tMaster Retry Count : %d\n", (_featuresRow[2] >> 2) & 0x03); printf("\tReserved Zero (2) : 0x%x\n", _featuresRow[2] & 0x03); printf("\tDual Boot Address : 0x%x\n", (_featuresRow[1] >> 16) & 0xffff); printf("\tI2C Slave Address : 0x%x\n", (_featuresRow[1] >> 8) & 0xff); printf("\tCustom Trace ID : 0x%x\n", _featuresRow[1] & 0xff); printf("\tCustom ID Code : 0x%x\n", _featuresRow[0]); printf("\nFEAbits: [0x%08x]\n", _feabits); printf("\tReserved Zero (16) : 0x%x\n", (_feabits >> 17) & 0xffff); printf("\tRollback Protection : %s\n", ((_feabits & FEA_VERSION_RB_PROT)?"Enabled":"Disabled")); printf("\tI2C Deglitch Range : %s\n", ((_feabits & FEA_I2C_DG_RANGE_SEL)?"(1) 16 to 50 ns":"(0) 8 to 25 ns")); int boot_mode = (_feabits >> 12) & 0x07; printf("\tBoot Mode : "); if ((_feabits & FEA_MSPI_PERSIST) == 0) { if (boot_mode == 0) printf("Dual Boot, CFG0 - CFG1\n"); else if (boot_mode == 1) printf("Dual Boot, CFG1 - CFG0\n"); else if (boot_mode == 3) printf("Single Boot, CFG0\n"); else if (boot_mode == 4) printf("Single Boot, CFG1\n"); else if (boot_mode == 5) printf("Dual Boot, Boot from former bitstream first\n"); else if (boot_mode == 7) printf("Dual Boot, Boot from latter bitstream first\n"); else if ((boot_mode & 0x03) == 2) printf("Dual Boot, No Boot\n"); else printf("Unknown boot sequence selection"); } else { if (boot_mode == 0) printf("Dual Boot, CFG0 - Ext\n"); else if ((boot_mode & 0x03) == 1) printf("Single Boot, Ext\n"); else if (boot_mode == 2) printf("Dual Boot, Ext - CFG0\n"); else if ((boot_mode & 0x03) == 3) printf("Dual Boot, Ext - Ext\n"); else if (boot_mode == 4) printf("Dual Boot, CFG1 - Ext\n"); else if (boot_mode == 6) printf("Dual Boot, Ext - CFG1\n"); else printf("Unknown boot sequence selection"); } printf("\tMSPI Enable : %s\n", ((_feabits & FEA_MSPI_PERSIST)?"Yes":"No")); printf("\tI2C Disable : %s\n", ((_feabits & FEA_I2C_PERSIST)?"Yes":"No")); printf("\tSSPI Disable : %s\n", ((_feabits & FEA_SSPI_PERSIST)?"Yes":"No")); printf("\tJTAG Disable : %s\n", ((_feabits & FEA_JTAG_PERSIST)?"Yes":"No")); printf("\tDONE Enable : %s\n", ((_feabits & FEA_DONE_PERSIST)?"Yes":"No")); printf("\tINIT Enable : %s\n", ((_feabits & FEA_INITN_PERSIST)?"Yes":"No")); printf("\tPROGRAM Disable : %s\n", ((_feabits & FEA_PROG_PERSIST)?"Yes":"No")); printf("\tCustom ID Enable : %s\n", ((_feabits & FEA_MY_ASSP_EN)?"Yes":"No")); int flash_prot = (_feabits >> 1) & 0x07; printf("\tFlash Protection : "); if (flash_prot == 0) { printf("None\n"); } else { if (flash_prot & 0x04) printf("CFG0 & CFG1 "); if (flash_prot & 0x02) printf("Feature, Security Keys "); if (flash_prot & 0x01) printf("All UFMs"); printf("\n"); } printf("\tI2C Deglitch Filter : %s\n", ((_feabits & FEA_I2C_DG_FIL_EN)?"Enabled":"Disabled")); } } /* Features Row & Feabits - this data is in a separate .fea file (MachXO3D) * DATA: * 1: xxxx\n : feature Row (96 bits) * 2: yyyy*\n : feabits (32 bits) */ void FeaParser::parseFeatureRowAndFeabits(const vector &content) { printf("Parsing Feature Row & FEAbits...\n"); string featuresRow = content[0]; //printf("Features: [%s]\n", featuresRow.c_str()); for (size_t i = 0; i < featuresRow.size(); i++) _featuresRow[3 - (i/32) - 1] |= ((featuresRow[i] - '0') << (32 - (i%32) - 1)); string feabits = content[1]; //printf("Feabits: [%s]\n", feabits.c_str()); _feabits = 0; for (size_t i = 0; i < feabits.size(); i++) { _feabits |= ((feabits[i] - '0') << (feabits.size() - i - 1)); } } int FeaParser::parse() { _ss.str(_raw_data); std::vectorlines; int first_pos; char instr; lines = readFeaFile(); /* empty or end of file */ if (lines.size() > 0) { parseFeatureRowAndFeabits(lines); _has_feabits = true; } return EXIT_SUCCESS; }