Загрузка данных


#include <fstream> // Обязательно добавьте этот инклуд в начало файла, если его там нет

bool Lattice::program_mem()
{
	bool err;

	LatticeBitParser _bit(_filename, false, false, _verbose);

	printInfo("Open file: ", false);
	printSuccess("DONE");

	err = _bit.parse();

	printInfo("Parse file: ", false);
	if (err == EXIT_FAILURE) {
		printError("FAIL");
		return false;
	} else {
		printSuccess("DONE");
	}

	if (_verbose)
		_bit.displayHeader();

#ifndef MY_CODE
readStatusReg();
#endif
	/* read ID Code 0xE0 and compare to bitstream */
	uint32_t bit_idcode = std::stoul(_bit.getHeaderVal("idcode").c_str(), NULL, 16);
	uint32_t idcode = idCode();
#if 1//def MY_CODE
	if (idcode != bit_idcode) {
		char mess[256];
		snprintf(mess, 256, "mismatch between target's idcode and bitstream idcode\n"
			"\tbitstream has 0x%08X hardware requires 0x%08x", bit_idcode, idcode);
		printError(mess);
		return false;
	}
#endif
	if (_verbose) {
		printf("IDCode : %x\n", idcode);
		displayReadReg(readStatusReg());
	}

	/* The command code 0x1C is not listed in the manual?
	 * PRELOAD/SAMPLE 0x1C
	 * For NEXUS family fpgas, the Bscan register is 362 bits long or
	 * 45.25 bytes => 46 bytes
	 * For ECP3 family fpgas, the Bscan register is 1077 bits long or
	 * 134.62 bytes => 135 bytes
	 */
	preload();

	/* LSC_REFRESH 0x79 -- "Equivalent to toggle PROGRAMN pin"
	 * We REFRESH only if the fpga is in a status of error due to
	 * the previous bitstream. For example, this happens if
	 * no bitstream is present on the SPI FLASH
	 */
	/*flag to understand if we refreshed or not*/
	bool was_refreshed;
	switch (_fpga_family) {
		case NEXUS_FAMILY:
			break;
		case ECP3_FAMILY:
			wr_rd(ECP3_LSCC_REFRESH, NULL, 0, NULL, 0);
			_jtag->set_state(Jtag::RUN_TEST_IDLE);
			_jtag->toggleClk(5, 1);
			usleep_ecp3(500000);  // 0.5s
			was_refreshed = false;
			break;
		default:
			was_refreshed = false;
	}

	/* ISC Enable 0xC6 */
	printInfo("Enable configuration: ", false);
	if (!EnableISC(0x00)) {
		printError("FAIL");
		displayReadReg(readStatusReg());
		return false;
	} else {
		printSuccess("DONE");
	}

	if (_fpga_family == NEXUS_FAMILY) {
		wr_rd(REFRESH, NULL, 0, NULL, 0);
		_jtag->set_state(Jtag::RUN_TEST_IDLE);
		_jtag->toggleClk(2);

		/* LSC_DEVICE_CONTROL 0x7D -- configuration reset */
		printInfo("Configuration Logic Reset: ", false);
		uint8_t tx_tmp[1] = {0x08};
		wr_rd(LSC_DEVICE_CONTROL, tx_tmp, 1, NULL, 0);
		_jtag->set_state(Jtag::RUN_TEST_IDLE);
		_jtag->toggleClk(1000);
		if(!pollBusyFlag()) {
			printError("FAIL");
			return false;
		}

		tx_tmp[0] = 0x00;
		wr_rd(LSC_DEVICE_CONTROL, tx_tmp, 1, NULL, 0);
		_jtag->set_state(Jtag::RUN_TEST_IDLE);
		_jtag->toggleClk(1000);
		if(!pollBusyFlag()) {
			printError("FAIL");
			return false;
		}
		printSuccess("DONE");
	}

	if (_fpga_family == ECP3_FAMILY) {
		if (!write_userCode(0xffffffff))
			return false;
	}

	/* ISC ERASE
	 * For Nexus family (from svf file): 1 byte to tx 0x00
	 */
	printInfo("SRAM erase: ", false);
	uint32_t mask_erase[1] = {FLASH_ERASE_SRAM};
	if (_fpga_family == NEXUS_FAMILY){
		mask_erase[0] = 0x00;
	}
	if (flashErase(mask_erase[0]) == false) {
		printError("FAIL");
		displayReadReg(readStatusReg());
		return false;
	} else {
		printSuccess("DONE");
	}

	if (_fpga_family == NEXUS_FAMILY) {
		printInfo("SRAM erase check: ", false);
		uint64_t status = readStatusReg();
		if ((status & 0x000000000002100) != 0) {
			printError("FAIL");
			return false;
		} else {
			printSuccess("DONE");
		}
	}

	/* LSC_INIT_ADDRESS */
	if (_fpga_family == ECP3_FAMILY) {
		wr_rd(ECP3_RESET_ADDRESS, NULL, 0, NULL, 0);
		_jtag->set_state(Jtag::RUN_TEST_IDLE);
		_jtag->toggleClk(5);
		usleep_ecp3(2000); // 2ms

		/* read user code (User Code register must have all bit set cleared) */
		const uint32_t dummy = 0xffffffff;
		uint32_t rx = 0;
		wr_rd(ECP3_READ_USERCODE, (uint8_t *)&dummy, 4, (uint8_t *)&rx, 4);
		if (rx != 0x00000000) {
			char message[256];
			snprintf(message, 256, "failed: 0x%08x instead of 0xffffffff", rx);
			printError(message);
			return false;
		}
	} else {
		wr_rd(RESET_CFG_ADDR, NULL, 0, NULL, 0); // LSC_INIT_ADDRESS
		_jtag->set_state(Jtag::RUN_TEST_IDLE);
		_jtag->toggleClk(1000);
	}

	const uint8_t *data = _bit.getData();
	int length = _bit.getLength()/8;
	printf("%s(%d) length=%u\n",__FUNCTION__,__LINE__,length);
	if (_fpga_family == ECP3_FAMILY) {
		/* Reset Address */
		wr_rd(ECP3_RESET_ADDRESS, NULL, 0, NULL, 0);
		_jtag->set_state(Jtag::RUN_TEST_IDLE);
		_jtag->toggleClk(5, 1);
		usleep_ecp3(2000); // 2ms

		wr_rd(ECP3_LSCC_BITSTREAM_BURST, NULL, 0, NULL, 0);
	} else {
		wr_rd(LSC_BITSTREAM_BURST, NULL, 0, NULL, 0);
		_jtag->set_state(Jtag::RUN_TEST_IDLE);
		_jtag->toggleClk(2);
	}

	uint8_t tmp[1024];
	int size = 1024;
	Jtag::tapState_t next_state = Jtag::SHIFT_DR;

	ProgressBar progress("Loading", length, 50, _quiet);

	// ==================== НАЧАЛО ИЗМЕНЕНИЙ СТРИМ-ДАМПА ====================
	std::ofstream dump_file("jtag_stream_dump.bin", std::ios::out | std::ios::binary);
	if (!dump_file.is_open()) {
		printError("Failed to open jtag_stream_dump.bin for writing!");
	}
	// ======================================================================

	for (int i = 0; i < length; i += size) {
		progress.display(i);

		if (length < i + size) {
			size = length-i;
			next_state = Jtag::RUN_TEST_IDLE;
		}
		printf("%d)\n",i);
		for (int ii = 0; ii < size; ii++) {
			tmp[ii] = ConfigBitstreamParser::reverseByte(data[i+ii]);
#ifndef MY_CODE
			printf("0x%X ",tmp[ii]);
#endif
		}

		// ==================== ЗАПИСЬ ДАННЫХ В ФАЙЛ ====================
		if (dump_file.is_open()) {
			dump_file.write(reinterpret_cast<const char*>(tmp), size);
		}
		// ==============================================================

		_jtag->shiftDR(tmp, NULL, size * 8, next_state);
	}

	// ==================== КОРРЕКТНОЕ ЗАКРЫТИЕ ФАЙЛА ====================
	if (dump_file.is_open()) {
		dump_file.close();
		printInfo("JTAG stream dump saved to jtag_stream_dump.bin successfully.", true);
	}
	// ===================================================================

	_jtag->set_state(Jtag::RUN_TEST_IDLE);

	if (_fpga_family == ECP3_FAMILY) {
		_jtag->toggleClk(256, 1);
		usleep_ecp3(2000);

		/* Verifiy User Code register */
		uint32_t rx = userCode();
		if (rx != 0x00000000) {
			progress.fail();
			char message[256];
			snprintf(message, 256, "failed: 0x%08x instead of 0x00000000", rx);
			printError(message);
			return false;
		}
		progress.done();
	} else {
		_jtag->toggleClk(1000);

		uint32_t status_mask;
		uint32_t status_val = 0;
		if (_fpga_family == MACHXO3D_FAMILY)
			status_mask = REG_STATUS_MACHXO3D_CNF_CHK_MASK;
		else if (_fpga_family == NEXUS_FAMILY) {
			status_val = REG_STATUS_DONE;
			status_mask = REG_STATUS_DONE | REG_STATUS_BUSY | REG_STATUS_FAIL
				| REG_NEXUS_STATUS_BSE_ERR_MASK;
		}
		else
			status_mask = REG_STATUS_CNF_CHK_MASK;

		if (checkStatus(status_val, status_mask)) {
			progress.done();
		} else {
			progress.fail();
			displayReadReg(readStatusReg());
			return false;
		}

		/* bypass */
		wr_rd(0xff, NULL, 0, NULL, 0);
	}

	if (_verbose)
		printf("userCode: %08x\n", userCode());

	/* bypass */
	wr_rd(0xff, NULL, 0, NULL, 0);
	/* disable configuration mode */
	printInfo("Disable configuration: ", false);
	if (!DisableISC()) {
		printError("FAIL");
		displayReadReg(readStatusReg());
		return false;
	} else {
		printSuccess("DONE");
	}

	if (_fpga_family == ECP3_FAMILY) {
		/* Bypass */
		wr_rd(0xff, NULL, 0, NULL, 0);
		_jtag->set_state(Jtag::RUN_TEST_IDLE);
		_jtag->toggleClk(100, 1);
		usleep_ecp3(1000);

		// Verify STATUS Register
		uint64_t status = readStatusReg();
		_jtag->toggleClk(5, 1);
		if ((status & 0x60007) != 0x20000) {
			char message[256];
			snprintf(message, 256, "Programming failed: status 0x%" PRIx64 "instead of 0x20000", status);
			printError(message);
			displayReadReg(status);
			return false;
		}
	}

	if (_verbose)
		displayReadReg(readStatusReg());

	/* bypass */
	wr_rd(0xff, NULL, 0, NULL, 0);
	if (_fpga_family == NEXUS_FAMILY) {
		_jtag->set_state(Jtag::RUN_TEST_IDLE);
		_jtag->toggleClk(100);
		usleep_ecp3(1000000);
	}
	_jtag->go_test_logic_reset();
	return true;
}