From 854c288b8b21843678a954f55c849d8a2a75573c Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sun, 2 Jun 2024 11:14:57 +0930 Subject: [PATCH] remove more unnecessary stuff #1 --- CMakeLists.txt | 10 - src/gowin.hpp | 144 -------------- src/gwu2x_jtag.cpp | 456 --------------------------------------------- src/gwu2x_jtag.hpp | 91 --------- src/pofParser.cpp | 200 -------------------- src/pofParser.hpp | 89 --------- 6 files changed, 990 deletions(-) delete mode 100644 src/gowin.hpp delete mode 100644 src/gwu2x_jtag.cpp delete mode 100644 src/gwu2x_jtag.hpp delete mode 100644 src/pofParser.cpp delete mode 100644 src/pofParser.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c63817b33..f7c2f10af3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,7 +83,6 @@ set(OPENFPGALOADER_SOURCE src/common.cpp src/ice40.cpp src/ihexParser.cpp - src/pofParser.cpp src/rawParser.cpp src/spiFlash.cpp src/spiInterface.cpp @@ -109,7 +108,6 @@ set(OPENFPGALOADER_HEADERS src/cxxopts.hpp src/ice40.hpp src/ihexParser.hpp - src/pofParser.hpp src/progressBar.hpp src/rawParser.hpp src/usbBlaster.hpp @@ -163,15 +161,7 @@ target_link_libraries(openFPGALoader ${LIBFTDI_LIBRARIES} ) -# Gowin GWU2X JTAG interface -if(ENABLE_GOWIN_GWU2X) - target_sources(openFPGALoader PRIVATE src/gwu2x_jtag.cpp) - list (APPEND OPENFPGALOADER_HEADERS src/gwu2x_jtag.hpp) - add_definitions(-DENABLE_GOWIN_GWU2X=1) - message("Gowin GWU2X support enabled") -else() message("Gowin GWU2X support disabled") -endif() if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") # winsock provides ntohs diff --git a/src/gowin.hpp b/src/gowin.hpp deleted file mode 100644 index 94649f0f41..0000000000 --- a/src/gowin.hpp +++ /dev/null @@ -1,144 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -/* - * Copyright (C) 2019 Gwenhael Goavec-Merou - */ - -#ifndef SRC_GOWIN_HPP_ -#define SRC_GOWIN_HPP_ - -#include -#include -#include -#include - -#include "configBitstreamParser.hpp" -#include "device.hpp" -#include "jtag.hpp" -#include "jtagInterface.hpp" -#include "spiInterface.hpp" - -class Gowin: public Device, SPIInterface { - public: - Gowin(Jtag *jtag, std::string filename, const std::string &file_type, - std::string mcufw, Device::prog_type_t prg_type, - bool external_flash, bool verify, int8_t verbose); - ~Gowin(); - uint32_t idCode() override; - void reset() override; - void program(unsigned int offset, bool unprotect_flash) override; - bool connectJtagToMCU() override; - - /* spi interface */ - bool protect_flash(uint32_t len) override { - (void) len; - printError("protect flash not supported"); return false;} - bool unprotect_flash() override { - if (is_gw5a) - return SPIInterface::unprotect_flash(); - printError("unprotect flash not supported"); return false;} - bool bulk_erase_flash() override { - if (is_gw5a) - return SPIInterface::bulk_erase_flash(); - printError("bulk erase flash not supported"); return false;} - bool dumpFlash(uint32_t base_addr, uint32_t len) override; - int spi_put(uint8_t cmd, const uint8_t *tx, uint8_t *rx, - uint32_t len) override; - int spi_put(const uint8_t *tx, uint8_t *rx, uint32_t len) override; - int spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond, - uint32_t timeout, bool verbose) override; - - /* ---------------- */ - /* Arora V specific */ - /* ---------------- */ - - /*! - * \brief Send cmd, followed by (optional) tx sequence and fill - * rx if not null - * \param[in] cmd: SPI command - * \param[in] rx: Byte sequence to write (may be null) - * \param[out] tx: Byte buffer when read is requested - * \param[in] len: number of Byte to read/write (0 when no read/write) - * \return 0 on success, -1 otherwise - */ - int spi_put_gw5a(const uint8_t cmd, const uint8_t *tx, uint8_t *rx, - uint32_t len); - /*! - * \brief poll on cmd register until timeout or SPI reg content match - * cond with mask - * \param[in] cmd: SPI command - * \param[in] mask: mask to apply on SPI rx - * \param[in] cond: SPI rx value value - * \param[in] timeout: number of try before fail - * \param[in] verbose: display try - * \return 0 on success, -1 otherwise - */ - int spi_wait_gw5a(uint8_t cmd, uint8_t mask, uint8_t cond, - uint32_t timeout, bool verbose); - - protected: - /*! - * \brief prepare SPI flash access - */ - bool prepare_flash_access() override; - /*! - * \brief end of SPI flash access - */ - bool post_flash_access() override; - - private: - bool detectFamily(); - bool send_command(uint8_t cmd); - void spi_gowin_write(const uint8_t *wr, uint8_t *rd, unsigned len); - uint32_t readReg32(uint8_t cmd); - void sendClkUs(unsigned us); - bool enableCfg(); - bool disableCfg(); - bool pollFlag(uint32_t mask, uint32_t value); - bool eraseSRAM(); - bool eraseFLASH(); - void programFlash(); - void programExtFlash(unsigned int offset, bool unprotect_flash); - void programSRAM(); - bool writeSRAM(const uint8_t *data, int length); - bool writeFLASH(uint32_t page, const uint8_t *data, int length); - void displayReadReg(const char *, uint32_t dev); - uint32_t readStatusReg(); - uint32_t readUserCode(); - /*! - * \brief compare usercode register with fs checksum and/or - * .fs usercode field - */ - void checkCRC(); - - /* ---------------- */ - /* Arora V specific */ - /* ---------------- */ - /*! - * \brief Send the sequence to pass GW5A to SPI mode. - * \return true on success, false otherwise - */ - bool gw5a_disable_spi(); - /*! - * \brief Send the sequence to disable SPI mode for GW5A. - * \return true on success, false otherwise - */ - bool gw5a_enable_spi(); - - ConfigBitstreamParser *_fs; - uint32_t _idcode; - bool is_gw1n1; - bool is_gw2a; - bool is_gw1n4; - bool is_gw5a; - bool skip_checksum; /**< bypass checksum verification (GW2A) */ - bool _external_flash; /**< select between int or ext flash */ - uint8_t _spi_sck; /**< clk signal offset in bscan SPI */ - uint8_t _spi_cs; /**< cs signal offset in bscan SPI */ - uint8_t _spi_di; /**< di signal (mosi) offset in bscan SPI */ - uint8_t _spi_do; /**< do signal (miso) offset in bscan SPI */ - uint8_t _spi_msk; /** default spi msk with only do out */ - ConfigBitstreamParser *_mcufw; - JtagInterface::tck_edge_t _prev_rd_edge; /**< default probe rd edge cfg */ - JtagInterface::tck_edge_t _prev_wr_edge; /**< default probe wr edge cfg */ -}; -#endif // SRC_GOWIN_HPP_ diff --git a/src/gwu2x_jtag.cpp b/src/gwu2x_jtag.cpp deleted file mode 100644 index 764abad0f4..0000000000 --- a/src/gwu2x_jtag.cpp +++ /dev/null @@ -1,456 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -/* - * Copyright (C) 2024 Gwenhael Goavec-Merou - */ - -#include - -#include -#include -#include -#include -#include - -#include "cable.hpp" -#include "display.hpp" -#include "gwu2x_jtag.hpp" -#include "libusb_ll.hpp" - -/* - * TCK -> GPIOL0 - * TMS -> GPIOL1 - * TDI -> GPIOL2 - * TDO -> GPIOL3 - */ -enum { - GWU2X_TMS_LSB_WRO = 0x5B, - GWU2X_TMS_LSB_RDWR = 0x5C, - GWU2X_TCK = 0x9b, - GWU2X_TDI_LSB_BIT_WRO = 0x6B, - GWU2X_TDI_LSB_BIT_RDWR = 0x6C, - GWU2X_TDI_LSB_BYTE_WRO = 0x7B, - GWU2X_TDI_LSB_BYTE_RDWR = 0x7C, - GWU2X_SET_FREQ_FAST = 0xAB, - GWU2X_SET_FREQ_SLOW = 0xAC, - GWU2X_READBACK_BUFFER_FORCED = 0x8B, - GWU2X_READBACK_BUFFER = 0xDB, /* 0x11: LSB, 0xff: MSB */ - GWU2X_GPIO_CONF_LOW = 0x20, /* GPIO0-7 */ - GWU2X_GPIO_CONF_HIGH = 0x21, /* GPIO8-15 */ - GWU2X_GPIO_READ_LOW = 0x22, /* GPIO0-7 */ - GWU2X_GPIO_READ_HIGH = 0x23, /* GPIO8-15 */ - GWU2X_CPOL_SETTING = 0xCB, -}; - -enum { - READBACK_LSB = 0x11, - READBACK_MSB = 0xff, -}; - -GowinGWU2x::GowinGWU2x(cable_t *cable, uint32_t clkHz, int8_t verbose): - libusb_ll(0, 0, verbose), _verbose(verbose > 1), _cable(cable), - _usb_dev(nullptr), _dev(nullptr), _xfer_buf(nullptr), _xfer_pos(0), - _buffer_len(256 + 2 + 1) -{ - const int found = get_devices_list(_cable); - if (found == 0) - throw std::runtime_error("No cable found"); - if (found > 1) - throw std::runtime_error("More than one cable found"); - std::vector dev_list = usb_dev_list(); - - /* here we have only one device present */ - _usb_dev = dev_list[0]; - - int ret = libusb_open(_usb_dev, &_dev); - if (ret < 0) - throw std::runtime_error("Failed to open device"); - - ret = libusb_claim_interface(_dev, 0); - if (ret < 0) { - char mess[256]; - snprintf(mess, 256, "Error claiming interface with error %s", libusb_error_name(ret)); - throw std::runtime_error(mess); - } - - _xfer_buf = new uint8_t[_buffer_len]; // one full TDI packet + readback cmd - - /* cable configuration */ - if (!store_seq(GWU2X_GPIO_CONF_LOW, // gpio0-7 - cable->config.bit_low_dir, // direction - cable->config.bit_low_val)) // value - throw std::runtime_error("Error: low pins configuration failed"); - if (!store_seq(GWU2X_GPIO_CONF_HIGH, // gpio8-15 - cable->config.bit_high_dir, // direction - cable->config.bit_high_val)) // value - throw std::runtime_error("Error: high pins configuration failed"); - if (!xfer(nullptr, 0)) - throw std::runtime_error("Error: pin configuration failed"); - - if (setClkFreq(clkHz) < 0) - throw std::runtime_error("Error: clock frequency configuration failed"); -} - -GowinGWU2x::~GowinGWU2x() -{ - flush(); - delete _xfer_buf; - /* nothing about interface ? */ - libusb_close(_dev); -} - -int GowinGWU2x::writeTMS(const uint8_t *tms, uint32_t len, bool flush_buffer, - const uint8_t tdi) -{ - const uint8_t tdi_bit = (tdi) ? 0x80 : 0x00; - uint8_t tms_buf = tdi_bit; - uint8_t idx = 0; // bit index in tms_buf - - /* As FTDI devices TMS instruction is 3 bytes long and can send up to - * 7bits - * 2nd byte tells number of TMS bits to send (0: 1bit, 6: 7bits) - * 3rd byte is the sequence of TMS values LSB first. Offset 7 is the TDI - * value for all TMS bits - */ - for (uint32_t pos = 0; pos < len; pos++) { - const uint8_t tms_byte = tms[pos >> 3]; - const uint8_t bit_shift = pos & 0x07; - const uint8_t tms_bit = (tms_byte >> bit_shift) & 0x01; - if (tms_bit) - tms_buf |= (1 << idx); - idx += 1; - /* if we have 7bits or if it's the last iteration - * flush the buffer, and restart for the next sequence - */ - if (idx == 7 || pos == len - 1) { - if (!store_seq(GWU2X_TMS_LSB_WRO, idx - 1, tms_buf)) - return -1; - idx = 0; - tms_buf = tdi_bit; - } - } - - if (flush_buffer) { - if (!xfer(nullptr, 0)) { - return -1; - } - } - - return static_cast(len); -} - -/* - * Write / Read data in one to three steps - * a sequence of up to 256 Bytes per packet - * a sequence of up to 8 bits - * the final bit (MSB) using TMS transition when end is true - */ -int GowinGWU2x::writeTDI(const uint8_t *tx, uint8_t *rx, uint32_t len, bool end) -{ - const uint32_t real_len = len - (end ? 1 : 0); // if end: last bit is sent with TMS - const uint32_t byte_len = real_len >> 3; // convert bit len to byte len (floor) - const uint32_t bit_len = real_len & 0x07; // extract remaining bits - uint8_t *tx_ptr = (uint8_t *)tx; - uint8_t *rx_ptr = rx; - - /* if the buffer is not empty, some tms bits are present - * flush to keep maximum size available - */ - if (_xfer_pos != 0) { - if (!xfer(nullptr, 0)) - return -1; - } - - // 1. Byte sequence with up to 256 Bytes - if (byte_len > 0) { - uint32_t xfer_len = 256; - for (uint32_t pos = 0; pos < byte_len; pos += xfer_len) { - if (pos + 256 > byte_len) - xfer_len = byte_len - pos; - _xfer_buf[_xfer_pos++] = (rx) ? GWU2X_TDI_LSB_BYTE_RDWR : GWU2X_TDI_LSB_BYTE_WRO; - _xfer_buf[_xfer_pos++] = xfer_len - 1; - memcpy(&_xfer_buf[_xfer_pos], tx_ptr, xfer_len); - _xfer_pos += xfer_len; - if (rx) - _xfer_buf[_xfer_pos++] = GWU2X_READBACK_BUFFER_FORCED; - if (!xfer((rx) ? rx_ptr : nullptr, xfer_len)) - return -1; - tx_ptr += xfer_len; - if (rx_ptr) - rx_ptr += xfer_len; - } - } - - /* when end with a sequence of bits - * don't do two usb transfers and - * postpone it to end sequence - */ - const bool postponed_read = (bit_len != 0 && end); - - // 2. Remaining bits between 1 and 7. - if (bit_len != 0) { - /* write up to 8 bits - * may be less if end, but not more - * the buffer read must be correctly aligned according to bit_len - */ - if (!store_seq(GWU2X_TDI_LSB_BIT_WRO + (rx != nullptr), - static_cast(bit_len - 1), *tx_ptr, !postponed_read && rx != nullptr)) - return -1; - // When not end, flush buffer - // NOTE: with a more clever global system why not - // postning it for the next call ? - if (!postponed_read) { - /* unlike FTDI bits are filed LSB to MSB ie - * for 2 bits: 0b000000XX - * for 7 bits: 0b0XXXXXXX - * no needs to shift here - */ - if (!xfer((rx) ? rx_ptr : nullptr, 1)) - return -1; - } - } - - // 3. End using TMS instruction and last bit. - if (end) { - uint8_t rx_byte; - /* we are in SHIFTDR or SHIFTIR -> move to next state */ - const uint8_t last_bit = (*tx_ptr >> bit_len) & 0x01; - if (!store_seq(GWU2X_TMS_LSB_WRO + (rx != nullptr), 0, - static_cast(((last_bit) ? 0x80 : 0x00) | 0x01), - rx != nullptr)) - return -1; - if (!xfer((rx)? &rx_byte : nullptr, 1)) - return -1; - if (rx) { - if (postponed_read) { - *rx_ptr = rx_byte; - } else { - const uint8_t tdo_bit = 1 << (bit_len); - if (rx_byte & 0x01) // here only one bit is read (always LSB) - *rx_ptr |= tdo_bit; - else - *rx_ptr &= ~tdo_bit; - } - } - } - return static_cast(len); -} - -int GowinGWU2x::toggleClk(uint8_t tms, uint8_t tdi, uint32_t clk_len) -{ - /* Gowin GWU2X has a specific command to produces - * a sequence sequence to up to 65536 cycles - * 0: 1 clk cycle, 0xffff: 65535 clk cycles - */ - /* No need to check/flush buffer will be done by store_seq */ - uint32_t len = 0; - if (_verbose) - printf("toggleClk : %02x %02x %u\n", tms, tdi, clk_len); - - for (uint32_t length = clk_len; length > 0; length -= len) { - len = ((length > 65536) ? 65536 : length) - 1; - if (!store_seq(GWU2X_TCK, - static_cast((len >> 0) & 0xff), - static_cast((len >> 8) & 0xff))) - return -1; - len += 1; - } - /* flush before return */ - if (_xfer_pos != 0) { - if (!xfer(nullptr, 0)) - return -1; - } - return static_cast(clk_len); -} - -enum { - EP_IN = 0x81, - EP_OUT = 0x02, -}; - -/* when readback we consider it's for the current sequence, not - * for current content - */ -bool GowinGWU2x::store_seq(const uint8_t &opcode, const uint8_t &len, - const uint8_t &data, const bool readback) -{ - if (_verbose) { - char message[256]; - snprintf(message, 256, "store seq %02x %02x %02x %d", - opcode, len, data, readback); - printInfo(message); - } - const size_t xfer_len = 3 + readback; - if (_xfer_pos + xfer_len > _buffer_len) { - if (!xfer(nullptr, 0)) - return false; - } - _xfer_buf[_xfer_pos++] = opcode; - _xfer_buf[_xfer_pos++] = len; - _xfer_buf[_xfer_pos++] = data; - if (readback) - _xfer_buf[_xfer_pos++] = GWU2X_READBACK_BUFFER_FORCED; - return true; -} - -bool GowinGWU2x::xfer(uint8_t *rx, uint16_t rx_len, const uint16_t timeout) -{ - int actual_length; - int ret; - if (_xfer_pos == 0) // nothing to do - return true; - - if (_verbose) { - printInfo("Write " + std::to_string(_xfer_pos) + " Bytes"); - printf("\t"); - for (uint32_t i = 0; i < _xfer_pos; i++) { - char message[6]; - snprintf(message, 6, "0x%02x ", _xfer_buf[i]); - printSuccess(message, false); - } - printf("\n"); - displayCmd(); - } - - ret = libusb_bulk_transfer(_dev, EP_OUT, - _xfer_buf, _xfer_pos, &actual_length, timeout); - if (ret < 0) { - printError("Write failed with error " + std::to_string(ret)); - return false; - } - _xfer_pos = 0; - if (!rx) // message sent, nothing to read -> quit - return true; - uint8_t *rx_ptr = rx; - uint32_t dummy; - ret = libusb_bulk_transfer(_dev, 0x83, (uint8_t*)&dummy, 4, &actual_length, timeout); - if (_verbose) - printf("ret: %d %u %d\n", ret, dummy, actual_length); - do { - ret = libusb_bulk_transfer(_dev, EP_IN, rx_ptr, rx_len, - &actual_length, timeout); - if (ret < 0) { - char message[256]; - snprintf(message, 256, "Failed to read: %d %s\n", ret, - libusb_strerror(static_cast(ret))); - printError(message); - return false; - } - if (_verbose) { - printf("%d %d %d\n", ret, rx_len, actual_length); - for (int ii = 0; ii < rx_len; ii++) - printf("%02x ", rx_ptr[ii]); - printf("\n"); - } - rx_ptr += actual_length; - rx_len -= actual_length; - } while (rx_len > 0); - - return true; -} - -int GowinGWU2x::setClkFreq(uint32_t freqHz) -{ - if (freqHz < 120e3 || freqHz > 30e6) { - printError("clk Frequency must be between 120kHz and 30MHz"); - return -1; - } - const uint16_t div = static_cast(60e6 / freqHz); - const int real_freq = static_cast(60e6 / div); - printInfo("User requested: " + std::to_string(freqHz) + " real frequency is " - + std::to_string(real_freq)); - _xfer_buf[_xfer_pos++] = GWU2X_SET_FREQ_FAST + ((freqHz < 240e3) ? 1 : 0); - _xfer_buf[_xfer_pos++] = static_cast(div - ((freqHz < 240e3) ? 256 : 0)); - if (!xfer(nullptr, 0, 1000)) - return -1; - _clkHZ = real_freq; - return static_cast(_clkHZ); -} - -void GowinGWU2x::displayCmd() -{ - uint32_t len = 0; - while (len < _xfer_pos) { - const uint8_t opcode = _xfer_buf[len++]; - const uint8_t b_len = _xfer_buf[len++]; - uint8_t tdi; - uint8_t tms; - char message[256]; - uint8_t bytes[256]; - switch(opcode) { - case GWU2X_TMS_LSB_WRO: - tdi = (_xfer_buf[len] >> 7) & 0x01; - tms = (_xfer_buf[len++] & 0x7f); - snprintf(message, 256, - "TMS Write Only len %d TDI: %x TMS: %02x", - b_len + 1, tdi, tms); - break; - case GWU2X_TMS_LSB_RDWR: - tdi = (_xfer_buf[len] >> 7) & 0x01; - tms = (_xfer_buf[len++] & 0x7f); - snprintf(message, 256, - "TMS Read/Write len %d TDI: %x TMS: %02x", - b_len + 1, tdi, tms); - break; - case GWU2X_TDI_LSB_BIT_WRO: - tdi = _xfer_buf[len++]; - snprintf(message, 256, - "TDI bit Write Only len %d TDI: %2x", - b_len + 1, tdi); - break; - case GWU2X_TDI_LSB_BIT_RDWR: - tdi = _xfer_buf[len++]; - snprintf(message, 256, - "TDI bit Read/Write len %d TDI: %2x", - b_len + 1, tdi); - break; - case GWU2X_TDI_LSB_BYTE_WRO: - memcpy(bytes, _xfer_buf, b_len + 1); - len += b_len + 1; - snprintf(message, 256, - "TDI Byte Write Only len %d TDI: %2x", - b_len + 1, bytes[0]); - break; - case GWU2X_TDI_LSB_BYTE_RDWR: - memcpy(bytes, _xfer_buf, b_len + 1); - len += b_len + 1; - snprintf(message, 256, - "TDI Byte Read/Write len %d TDI: %2x", - b_len + 1, bytes[0]); - break; - case GWU2X_TCK: - tdi = _xfer_buf[len++]; - snprintf(message, 256, - "toggle Clock len %d", - (b_len | (tdi << 8)) + 1); - break; - - case GWU2X_GPIO_CONF_HIGH: - tms = _xfer_buf[len++]; - snprintf(message, 256, - "GPIO conf high: direction: %x value: %02x", - b_len, tms); - break; - case GWU2X_GPIO_CONF_LOW: - tms = _xfer_buf[len++]; - snprintf(message, 256, - "GPIO conf low: direction: %x value: %02x", - b_len, tms); - break; - case GWU2X_SET_FREQ_FAST: - case GWU2X_SET_FREQ_SLOW: - snprintf(message, 256, - "Set clk freq prescaler: %02x", - b_len); - break; - case GWU2X_READBACK_BUFFER_FORCED: - len--; - snprintf(message, 256, "readback buffer"); - break; - default: - snprintf(message, 256, "Unknown"); - printError(message); - return; - } - printInfo(message); - } -} diff --git a/src/gwu2x_jtag.hpp b/src/gwu2x_jtag.hpp deleted file mode 100644 index 8e1a4834b8..0000000000 --- a/src/gwu2x_jtag.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -/* - * Copyright (C) 2024 Gwenhael Goavec-Merou - */ - -#ifndef SRC_GWU2X_JTAG_HPP__ -#define SRC_GWU2X_JTAG_HPP__ - -#include - -#include -#include - -#include "cable.hpp" -#include "jtagInterface.hpp" -#include "libusb_ll.hpp" - -class GowinGWU2x: public JtagInterface, private libusb_ll -{ - public: - GowinGWU2x(cable_t *cable, uint32_t clkHz, int8_t verbose); - ~GowinGWU2x(); - - int setClkFreq(uint32_t clkHz) override; - - /*! - * \brief flush TMS internal buffer (ie. transmit to converter) - * \param tdo: pointer for read operation. May be NULL - * \param len: number of bit to send - * \return number of bit send/received - */ - int writeTMS(const uint8_t *tms, uint32_t len, bool flush_buffer, const uint8_t tdi = 1) override; - - /*! - * \brief send TDI bits (mainly in shift DR/IR state) - * \param tdi: array of TDI values (used to write) - * \param tdo: array of TDO values (used when read) - * \param len: number of bit to send/receive - * \param end: in JTAG state machine last bit and tms are set in same time - * but only in shift[i|d]r, if end is false tms remain the same. - * \return number of bit written and/or read - */ - int writeTDI(const uint8_t *tx, uint8_t *rx, uint32_t len, bool end) override; - - /*! - * \brief toggle clk without touch of TDI/TMS - * \param tms: state of tms signal - * \param tdi: state of tdi signal - * \param clk_len: number of clock cycle - * \return number of clock cycle send - */ - int toggleClk(uint8_t tms, uint8_t tdi, uint32_t clk_len) override; - - /*! - * \brief return internal buffer size (in byte) - * \return internal buffer size - */ - int get_buffer_size() override {return static_cast(_buffer_len);} - - /*! - * \brief return status of internal buffer - * \return true when internal buffer is full - */ - bool isFull() override {return _xfer_pos == _buffer_len;} - - /*! - * \brief force internal flush buffer - * \return 1 if success, 0 if nothing to write, -1 is something wrong - */ - int flush() override { - if (_xfer_pos == 0) - return 0; - return xfer(nullptr, 0) ? 1 : -1; - } - private: - bool xfer(uint8_t *rx, uint16_t rx_len, uint16_t timeout = 1000); - bool store_seq(const uint8_t &opcode, const uint8_t &len, - const uint8_t &data, const bool readback = false); - bool init_device(); - void displayCmd(); // debug purpose: translate sequence to human - // readable sequence - bool _verbose; - cable_t *_cable; - struct libusb_device *_usb_dev; - struct libusb_device_handle *_dev; - uint8_t *_xfer_buf; /* internal buffer */ - uint32_t _xfer_pos; /* number of Bytes already stored in _xfer_buf */ - uint32_t _buffer_len; /* _xfer_buf capacity (Byte) */ -}; - -#endif // SRC_GWU2X_JTAG_HPP__ diff --git a/src/pofParser.cpp b/src/pofParser.cpp deleted file mode 100644 index 1eccf27191..0000000000 --- a/src/pofParser.cpp +++ /dev/null @@ -1,200 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -/* - * Copyright (C) 2022 Gwenhael Goavec-Merou - */ - -#include "pofParser.hpp" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "display.hpp" - -POFParser::POFParser(const std::string &filename, bool verbose): - ConfigBitstreamParser(filename, ConfigBitstreamParser::BIN_MODE, - verbose) -{} - -POFParser::~POFParser() -{} - -uint8_t *POFParser::getData(const std::string §ion_name) -{ - if (section_name == "") - return (uint8_t*)_bit_data.data(); - return mem_section[section_name].data; -} - -int POFParser::getLength(const std::string §ion_name) -{ - if (section_name == "") - return _bit_length; - return mem_section[section_name].len; -} - -void POFParser::displayHeader() -{ - ConfigBitstreamParser::displayHeader(); - for (auto it = mem_section.begin(); it != mem_section.end(); it++) { - memory_section_t v = (*it).second; - char mess[1024]; - snprintf(mess, 1024, "%02x %4s: ", v.flag, v.section.c_str()); - printInfo(mess, false); - snprintf(mess, 1024, "%08x %08x", v.offset, v.len); - printSuccess(mess); - } -} - -int POFParser::parse() -{ - uint8_t *ptr = (uint8_t *)_raw_data.data(); - uint32_t pos = 0; - - if (_verbose) - printf("[%08x:%08x] %s\n", 0, 3, ptr); - /* [0:3]: POF\0 */ - ptr += 4; - pos += 4; - /* unknown */ - if (_verbose) { - uint32_t first_section = ARRAY2INT32(ptr); - printf("first section: %08x %4u\n", first_section, first_section); - } - ptr += 4; - pos += 4; - /* number of packets */ - if (_verbose) { - uint32_t num_packets = ARRAY2INT32(ptr); - printf("number of packets: %08x %4u\n", num_packets, num_packets); - } - pos += 4; - - /* 16bit code + 32bits size + content */ - while (pos < static_cast(_file_size)) { - uint16_t flag = ARRAY2INT16((&_raw_data.data()[pos])); - pos += 2; - uint32_t size = ARRAY2INT32((&_raw_data.data()[pos])); - pos += 4; - pos += parseSection(flag, pos, size); - } - - /* update pointers to memory area */ - ptr = (uint8_t *)_bit_data.data(); - mem_section["CFM0"].data = &ptr[mem_section["CFM0"].offset + 0x0C]; - mem_section["UFM"].data = &ptr[mem_section["UFM"].offset + 0x0C]; - mem_section["ICB"].data = &ptr[mem_section["ICB"].offset + 0x0C]; - - return EXIT_SUCCESS; -} - -uint32_t POFParser::parseSection(uint16_t flag, uint32_t pos, uint32_t size) -{ - std::string content; - - if (_verbose) - printf("%d %u\n", flag, size); - - /* 0x01: software name/version */ - /* 0x02: full FPGAs model */ - /* 0x03: bitstream name ? */ - /* 0x3b: ? */ - /* 0x12: ? */ - /* 0x13: contains usercode / checksum */ - /* 0x24: ? */ - /* 0x11: ? */ - /* 0x18: ? */ - /* 0x15: ? */ - /* 0x34: ? */ - /* 0x35: ? */ - /* 0x38: ? */ - /* 0x08: ? CRC ? */ - switch (flag) { - case 0x01: // software name/version - _hdr["tool"] = _raw_data.substr(pos, size); - break; - case 0x02: // full FPGA part name - _hdr["part_name"] = _raw_data.substr(pos, size); - break; - case 0x03: // bitstream/design/xxx name - _hdr["design_name"] = _raw_data.substr(pos, size); - break; - case 0x08: // last packet: CRC ? - _hdr["maybeCRC"] = std::to_string(ARRAY2INT16((&_raw_data.data()[pos]))); - break; - case 0x11: // cfg data - // 12 Bytes unknown - // followed by UFM/CFM/DSM data - _bit_data.resize(size); - std::copy(_raw_data.begin() + pos, _raw_data.begin() + pos + size, - _bit_data.begin()); - _bit_length = size * 8; - if (_verbose) - printf("size %u %zu\n", size, _bit_data.size()); - break; - case 0x1a: // flash sections - // 12Bytes ? - // followed by flash sections separates by ';' - // 1B + name + ' ' + cfg data offset (bits) + size (bits) - content = _raw_data.substr(pos, size); - parseFlag26(flag, pos, size, content); - break; - default: - char mess[1024]; - snprintf(mess, 1024, "unknown flag 0x%02x: offset %u length %u", - flag, pos - 6, size); - printWarn(mess); - break; - } - - return size; -} - -/* section with flag 0x11A */ -/* 3 x 32bits -> unknown - * followed by flash sections separates by ';' - * 1B + name + ' ' + cfg data offset (bits) + size (bits) - */ -void POFParser::parseFlag26(uint16_t flag, uint32_t pos, - uint32_t size, const std::string &payload) -{ - if (_verbose) - printf("%04x %08x %08x\n", flag, pos, size); - - if (size != payload.size()) - printf("mismatch size\n"); - - if (_verbose) { - uint32_t val0 = ARRAY2INT32((&payload.c_str()[0])); - uint32_t val1 = ARRAY2INT32((&payload.c_str()[4])); - uint32_t val2 = ARRAY2INT32((&payload.c_str()[8])); - printf("%08x %08x %08x\n", val0, val1, val2); - } - - std::regex regex{R"([;]+)"}; // split on space - std::sregex_token_iterator it{payload.begin() + 12, payload.end(), - regex, -1}; - std::vector words{it, {}}; - - std::regex sp_reg{R"([\s]+)"}; // split on space - for (size_t i = 0; i < words.size(); i++) { - std::sregex_token_iterator it{words[i].begin(), words[i].end(), - sp_reg, -1}; - std::vector sect{it, {}}; - uint32_t start = stoul(sect[1], nullptr, 16); - uint32_t length = stoul(sect[2], nullptr, 16); - uint8_t id = static_cast(sect[0][0]); - std::string name = sect[0].substr(1); - mem_section.insert(std::pair( - name, {id, name, start, NULL, length})); - } -} diff --git a/src/pofParser.hpp b/src/pofParser.hpp deleted file mode 100644 index e1d36ff12b..0000000000 --- a/src/pofParser.hpp +++ /dev/null @@ -1,89 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -/* - * Copyright (C) 2022 Gwenhael Goavec-Merou - */ - -#ifndef SRC_POFPARSER_HPP_ -#define SRC_POFPARSER_HPP_ - -#include - -#include -#include - -#include "configBitstreamParser.hpp" - -#define ARRAY2INT16(_array_) ( \ - (static_cast(_array_[0] & 0x00ff) << 0) | \ - (static_cast(_array_[1] & 0x00ff) << 8)) - -#define ARRAY2INT32(_array_) ( \ - (static_cast(_array_[0] & 0x00ff) << 0) | \ - (static_cast(_array_[1] & 0x00ff) << 8) | \ - (static_cast(_array_[2] & 0x00ff) << 16) | \ - (static_cast(_array_[3] & 0x00ff) << 24)) - -/*! - * \file pofParser.hpp - * \class POFParser - * \brief basic implementation for intel/altera POF format - * \author Gwenhael Goavec-Merou - */ -class POFParser: public ConfigBitstreamParser { - public: - POFParser(const std::string &filename, bool verbose = false); - ~POFParser(); - - int parse() override; - - /** - * \brief return pointer to cfg data section when name is provided - * when "" -> return full cfg_data - * \return a pointer - */ - uint8_t *getData(const std::string §ion_name); - - /** - * \brief return length (bits) to a cfg data section when name is - * provided or full cfg_data length when "" - * \return size in bits - */ - int getLength(const std::string §ion_name); - - /** - * \brief display header informations - */ - void displayHeader() override; - - - private: - /* packet 0x1A content */ - typedef struct { - uint8_t flag; // 1 Byte before section name - std::string section; // UFM/CFM/ICB - uint32_t offset; // start offset in packet 17 area - uint8_t *data; // memory pointer - uint32_t len; // area length (bits) - } memory_section_t; - - std::map mem_section; - - /*! - * \brief parse a section 0x1A (list of sections) - * \param[in] flag: 16Bits flag - * \param[in] pos : 32bits _raw_data's offset - * \param[in] size: 32bits content's size - */ - void parseFlag26(uint16_t flag, uint32_t pos, - uint32_t size, const std::string &payload); - - /*! - * \brief parse a section (flag + pos + size) - * \param[in] flag: 16Bits flag - * \param[in] pos : 32bits _raw_data's offset - * \param[in] size: 32bits content's size - * \return size - */ - uint32_t parseSection(uint16_t flag, uint32_t pos, uint32_t size); -}; -#endif // SRC_POFPARSER_HPP_