part: remove/convert fpga_list and misc_device, adapts code

This commit is contained in:
Gwenhael Goavec-Merou 2023-08-08 07:06:40 +02:00
parent d9805dd1cf
commit 82b4f24a36
9 changed files with 58 additions and 283 deletions

View File

@ -55,8 +55,8 @@ Efinix::Efinix(Jtag* jtag, const std::string &filename,
/* detect FPGA type (Trion or Titanium) */ /* detect FPGA type (Trion or Titanium) */
const uint32_t idcode = _jtag->get_target_device_id(); const Jtag::found_device* tgt_dev = _jtag->get_target();
const std::string family = fpga_list[idcode].family; const std::string family = tgt_dev->model->family;
if (family == "Titanium") { if (family == "Titanium") {
if (_file_extension == "hex" && prg_type == Device::WR_SRAM) { if (_file_extension == "hex" && prg_type == Device::WR_SRAM) {
throw std::runtime_error("Error: loading (RAM) hex file is not " throw std::runtime_error("Error: loading (RAM) hex file is not "
@ -72,7 +72,7 @@ Efinix::Efinix(Jtag* jtag, const std::string &filename,
throw std::runtime_error("Error: unknown family " + family); throw std::runtime_error("Error: unknown family " + family);
} }
/* get irlen value from model */ /* get irlen value from model */
_irlen = fpga_list[idcode].irlength; _irlen = tgt_dev->irlength;
/* WA: before using JTAG, device must restart with cs low /* WA: before using JTAG, device must restart with cs low
* but cs and rst for xyloni are connected to interfaceA (ie SPI) * but cs and rst for xyloni are connected to interfaceA (ie SPI)

View File

@ -167,7 +167,6 @@ int Jtag::detectChain(int max_dev)
/* cleanup */ /* cleanup */
_f_device_list.clear(); _f_device_list.clear();
_irlength_list.clear();
go_test_logic_reset(); go_test_logic_reset();
set_state(SHIFT_DR); set_state(SHIFT_DR);
@ -233,15 +232,15 @@ bool Jtag::search_and_insert_device_with_idcode(uint32_t idcode)
} }
/* search entry at vendor level */ /* search entry at vendor level */
vnd_list = fpga_vnd_list.find(manufacturer); vnd_list = fpga_list.find(manufacturer);
if (vnd_list != fpga_vnd_list.end()) { if (vnd_list != fpga_list.end()) {
/* try to find direct idcode (no mask) */ /* try to find direct idcode (no mask) */
fpga2 = vnd_list->second.find(idcode); fpga2 = vnd_list->second.find(idcode);
/* direct not found -> search for idcode with mask */ /* direct not found -> search for idcode with mask */
if (fpga2 == fpga_vnd_list[manufacturer].end()) { if (fpga2 == fpga_list[manufacturer].end()) {
idcode = idcode & 0x0FFFFFFF; idcode = idcode & 0x0FFFFFFF;
fpga2 = vnd_list->second.find(idcode); fpga2 = vnd_list->second.find(idcode);
if (fpga2 != fpga_vnd_list[manufacturer].end()) if (fpga2 != fpga_list[manufacturer].end())
found = true; found = true;
} else { } else {
found = true; found = true;
@ -269,18 +268,16 @@ bool Jtag::insert_first(uint32_t device_id, bool is_misc, uint16_t irlength, dev
{ {
found_device dev = {device_id, irlength, is_misc, device}; found_device dev = {device_id, irlength, is_misc, device};
_f_device_list.insert(_f_device_list.begin(), dev); _f_device_list.insert(_f_device_list.begin(), dev);
//_devices_list.insert(_devices_list.begin(), device_id);
_irlength_list.insert(_irlength_list.begin(), irlength);
return true; return true;
} }
uint16_t Jtag::device_select(uint16_t index) bool Jtag::device_select(uint16_t index)
{ {
if (index > (uint16_t) _f_device_list.size()) if (index > (uint16_t) _f_device_list.size())
return -1; return false;
device_index = index; device_index = index;
return device_index; return true;
} }
void Jtag::setTMS(unsigned char tms) void Jtag::setTMS(unsigned char tms)
@ -418,7 +415,7 @@ int Jtag::shiftIR(unsigned char *tdi, unsigned char *tdo, int irlen, int end_sta
* send to complete send ir sequence * send to complete send ir sequence
*/ */
for (int i = 0; i < device_index; i++) for (int i = 0; i < device_index; i++)
bypass_after += _irlength_list[i]; bypass_after += _f_device_list[i].irlength;
} }
/* if not in SHIFT IR move to this state */ /* if not in SHIFT IR move to this state */
@ -433,7 +430,7 @@ int Jtag::shiftIR(unsigned char *tdi, unsigned char *tdo, int irlen, int end_sta
*/ */
int bypass_before = 0; int bypass_before = 0;
for (unsigned int i = device_index + 1; i < _f_device_list.size(); i++) for (unsigned int i = device_index + 1; i < _f_device_list.size(); i++)
bypass_before += _irlength_list[i]; bypass_before += _f_device_list[i].irlength;
/* if > 0 send bits */ /* if > 0 send bits */
if (bypass_before > 0) { if (bypass_before > 0) {

View File

@ -48,7 +48,6 @@ class Jtag {
* \brief return list of devices in the chain * \brief return list of devices in the chain
* \return list of devices * \return list of devices
*/ */
//std::vector<int> get_devices_list() {return _devices_list;}
std::vector<found_device> get_devices_list() {return _f_device_list;} std::vector<found_device> get_devices_list() {return _f_device_list;}
/*! /*!
@ -57,19 +56,24 @@ class Jtag {
*/ */
uint32_t get_target_device_id() {return _f_device_list[device_index].idcode;} uint32_t get_target_device_id() {return _f_device_list[device_index].idcode;}
/*!
* \brief return current selected target
* \return device information
*/
found_device *get_target() {return &_f_device_list[device_index];}
/*! /*!
* \brief set index for targeted FPGA * \brief set index for targeted FPGA
* \param[in] index: index in the chain * \param[in] index: index in the chain
* \return -1 if index is out of bound, index otherwise * \return false if index is out of bound, true otherwise
*/ */
uint16_t device_select(uint16_t index); bool device_select(uint16_t index);
/*! /*!
* \brief inject a device into list at the begin * \brief inject a device into list at the begin
* \param[in] device_id: idcode * \param[in] device_id: idcode
* \param[in] irlength: device irlength * \param[in] irlength: device irlength
* \return false if fails * \return false if fails
*/ */
//bool insert_first(uint32_t device_id, uint16_t irlength);
bool insert_first(uint32_t idcode, bool is_misc, uint16_t irlength, device_model *device); bool insert_first(uint32_t idcode, bool is_misc, uint16_t irlength, device_model *device);
/*! /*!
@ -141,8 +145,8 @@ class Jtag {
private: private:
/*! /*!
* \brief search in fpga_list and misc_dev_list for a device with idcode * \brief search in fpga_list and misc_dev_list for a device with idcode
* if found insert idcode and irlength in _devices_list and * if found insert idcode, irlength and a pointer to entry part
* _irlength_list * in _f_devices_list
* \param[in] idcode: device idcode * \param[in] idcode: device idcode
* \return false if not found, true otherwise * \return false if not found, true otherwise
*/ */
@ -155,8 +159,6 @@ class Jtag {
std::string _board_name; std::string _board_name;
int device_index; /*!< index for targeted FPGA */ int device_index; /*!< index for targeted FPGA */
//std::vector<int32_t> _devices_list; /*!< ordered list of devices idcode */ std::vector<found_device> _f_device_list; /*!< ordered list of devices present */
std::vector<int16_t> _irlength_list; /*!< ordered list of irlength */
std::vector<found_device> _f_device_list;
}; };
#endif #endif

View File

@ -161,8 +161,7 @@ Lattice::Lattice(Jtag *jtag, const string filename, const string &file_type,
} }
} }
/* check device family */ /* check device family */
uint32_t idcode = _jtag->get_target_device_id(); string family = _jtag->get_target()->model->family;
string family = fpga_list[idcode].family;
if (family == "MachXO2") { if (family == "MachXO2") {
_fpga_family = MACHXO2_FAMILY; _fpga_family = MACHXO2_FAMILY;
} else if (family == "MachXO3LF") { } else if (family == "MachXO3LF") {

View File

@ -116,9 +116,7 @@ int LatticeBitParser::parse()
} }
string part = getHeaderVal("Part"); string part = getHeaderVal("Part");
string subpart = part.substr(0, part.find_last_of("-")); string subpart = part.substr(0, part.find_last_of("-"));
for (auto && fpga : fpga_list) { for (auto && fpga : fpga_list["lattice"]) {
if (fpga.second.manufacturer != "lattice")
continue;
string model = fpga.second.model; string model = fpga.second.model;
if (subpart.compare(0, model.size(), model) == 0) { if (subpart.compare(0, model.size(), model) == 0) {
_hdr["idcode"] = string(8, ' '); _hdr["idcode"] = string(8, ' ');

View File

@ -454,7 +454,7 @@ int main(int argc, char **argv)
/* chain detection */ /* chain detection */
int found = jtag->get_chain_length(); int found = jtag->get_chain_length();
int idcode = -1, index = 0; int index = 0;
if (args.verbose > 0) if (args.verbose > 0)
cout << "found " << std::to_string(found) << " devices" << endl; cout << "found " << std::to_string(found) << " devices" << endl;
@ -496,7 +496,6 @@ int main(int argc, char **argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
idcode = jtag->get_target_device_id();
} else { } else {
printError("Error: no device found"); printError("Error: no device found");
delete(jtag); delete(jtag);
@ -504,6 +503,7 @@ int main(int argc, char **argv)
} }
jtag->device_select(index); jtag->device_select(index);
Jtag::found_device *tgt_dev = jtag->get_target();
/* detect svf file and program the device */ /* detect svf file and program the device */
if (!args.file_type.compare("svf") || if (!args.file_type.compare("svf") ||
@ -520,13 +520,14 @@ int main(int argc, char **argv)
/* check if selected device is supported /* check if selected device is supported
* mainly used in conjunction with --index-chain * mainly used in conjunction with --index-chain
*/ */
if (fpga_list.find(idcode) == fpga_list.end()) { if (tgt_dev->is_misc || !tgt_dev->model) {
cerr << "Error: device " << hex << idcode << " not supported" << endl; cerr << "Error: device " << hex << tgt_dev->idcode
<< " not supported" << endl;
delete(jtag); delete(jtag);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
string fab = fpga_list[idcode].manufacturer; string fab = tgt_dev->model->manufacturer;
Device *fpga; Device *fpga;
@ -1005,7 +1006,7 @@ void displaySupported(const struct arguments &args)
} }
if (args.list_fpga) { if (args.list_fpga) {
for (auto &&vendor: fpga_vnd_list) { for (auto &&vendor: fpga_list) {
stringstream t; stringstream t;
t << setw(12) << left << "IDCode" << setw(14) << "manufacturer"; t << setw(12) << left << "IDCode" << setw(14) << "manufacturer";
t << setw(16) << "family" << setw(20) << "model"; t << setw(16) << "family" << setw(20) << "model";

View File

@ -18,225 +18,7 @@ typedef struct {
} device_model; } device_model;
/* Highest nibble (version) must always be set to 0 */ /* Highest nibble (version) must always be set to 0 */
static std::map <uint32_t, device_model> fpga_list = { static std::map <std::string, std::map <uint32_t, device_model>> fpga_list = {
/**************************************************************************/
/* Anlogic */
/**************************************************************************/
/* Anlogic Eagle */
{0x0a014c35, {"anlogic", "eagle s20", "EG4S20BG256", 8}},
/* Anlogic Elf2 */
{0x00004c37, {"anlogic", "elf2", "EF2M45", 8}},
/**************************************************************************/
/* Xilinx */
/**************************************************************************/
/* Xilinx XCF */
{0x05044093, {"xilinx", "xcf", "xcf01s", 8}},
{0x05045093, {"xilinx", "xcf", "xcf02s", 8}},
{0x05046093, {"xilinx", "xcf", "xcf04s", 8}},
/* Xilinx XC2 */
{0x06e5d093, {"xilinx", "xc2c", "xc2c64a", 8}},
{0x06e1c093, {"xilinx", "xc2c", "xc2c32a", 8}},
/* Xilinx XC9 */
{0x09602093, {"xilinx", "xc9500xl", "xc9536xl", 8}},
{0x09604093, {"xilinx", "xc9500xl", "xc9572xl", 8}},
{0x09608093, {"xilinx", "xc9500xl", "xc95144xl", 8}},
{0x09616093, {"xilinx", "xc9500xl", "xc95288xl", 8}},
/* Xilinx Spartan3 */
{0x01414093, {"xilinx", "spartan3", "xc3s200", 6}},
{0x11c1a093, {"xilinx", "spartan3e", "xc3s250e", 6}},
{0x01c22093, {"xilinx", "spartan3e", "xc3s500e", 6}},
/* Xilinx Spartan6 */
{0x04001093, {"xilinx", "spartan6", "xc6slx9", 6}},
{0x04002093, {"xilinx", "spartan6", "xc6slx16", 6}},
{0x04004093, {"xilinx", "spartan6", "xc6slx25", 6}},
{0x04008093, {"xilinx", "spartan6", "xc6slx45", 6}},
{0x04011093, {"xilinx", "spartan6", "xc6slx100", 6}},
{0x4403d093, {"xilinx", "spartan6", "xc6slx150T", 6}},
{0x03620093, {"xilinx", "spartan7", "xc7s15ftgb196-1", 6}},
{0x037c4093, {"xilinx", "spartan7", "xc7s25", 6}},
{0x0362f093, {"xilinx", "spartan7", "xc7s50", 6}},
/* Xilinx 7-Series / Artix7 */
{0x037c2093, {"xilinx", "artix a7 25t", "xc7a25", 6}},
{0x0362D093, {"xilinx", "artix a7 35t", "xc7a35", 6}},
{0x0362c093, {"xilinx", "artix a7 50t", "xc7a50t", 6}},
{0x03632093, {"xilinx", "artix a7 75t", "xc7a75t", 6}},
{0x03631093, {"xilinx", "artix a7 100t", "xc7a100", 6}},
{0x03636093, {"xilinx", "artix a7 200t", "xc7a200", 6}},
/* Xilinx 7-Series / Kintex7 */
{0x0364c093, {"xilinx", "kintex7", "xc7k160t", 6}},
{0x03651093, {"xilinx", "kintex7", "xc7k325t", 6}},
{0x03656093, {"xilinx", "kintex7", "xc7k410t", 6}},
{0x23752093, {"xilinx", "kintex7", "xc7k420t", 6}},
/* Xilinx 7-Series / Zynq */
{0x03722093, {"xilinx", "zynq", "xc7z010", 6}},
{0x03727093, {"xilinx", "zynq", "xc7z020", 6}},
{0x23731093, {"xilinx", "zynq", "xc7z045", 6}},
/* Xilinx Ultrascale / Kintex */
{0x13822093, {"xilinx", "kintexus", "xcku040", 6}},
{0x13823093, {"xilinx", "kintexus", "xcku035", 6}},
/* Xilinx Ultrascale+ / Artix */
{0x04A64093, {"xilinx", "artixusp", "xcau25p", 6}},
/* Xilinx Ultrascale+ / Kintex */
{0x04a63093, {"xilinx", "kintexusp", "xcku3p", 6}},
{0x04a62093, {"xilinx", "kintexusp", "xcku5p", 6}},
/* Xilinx Ultrascale+ / Virtex */
{0x04b31093, {"xilinx", "virtexusp", "xcvu9p", 18}},
{0x14b79093, {"xilinx", "virtexusp", "xcvu37p", 18}},
/* Xilinx Ultrascale+ / ZynqMP */
/* When powering a zynq ultrascale+ MPSoC, PL Tap and ARM dap
* are disabled and only PS tap with a specific IDCODE is seen.
* 0x03 must be written into JTAG_CTRL followed by RTI and
* a new scan to discover PL TAP and ARM DAP
*/
{0x08e22126, {"xilinx", "zynqmp_cfgn", "xczu2cg", 4}},
{0x08e70126, {"xilinx", "zynqmp_cfgn", "xczu9eg", 4}},
{0x08e80126, {"xilinx", "zynqmp_cfgn","xczu11eg", 4}},
{0x08e60126, {"xilinx", "zynqmp_cfgn", "xczu7ev", 4}},
{0x04711093, {"xilinx", "zynqmp", "xczu2cg", 6}},
{0x04738093, {"xilinx", "zynqmp", "xczu9eg", 6}},
{0x04740093, {"xilinx", "zynqmp", "xczu11eg", 6}},
{0x04730093, {"xilinx", "zynqmp", "xczu7ev", 6}},
/**************************************************************************/
/* Altera */
/**************************************************************************/
/* Altera Cyclone III/IV */
{0x020f20dd, {"altera", "cyclone III/IV", "EP3C16/EP4CE15", 10}},
{0x020f70dd, {"altera", "cyclone IV", "EP4CE115", 10}},
/* Altera Cyclone V */
{0x02b010dd, {"altera", "cyclone V", "5CGX*3", 10}},
{0x02b020dd, {"altera", "cyclone V", "5CGT*5/5CGX*5", 10}},
{0x02b030dd, {"altera", "cyclone V", "5CGT*7/5CGX*7", 10}},
{0x02b040dd, {"altera", "cyclone V", "5CGT*9/5CGX*9", 10}},
{0x02b050dd, {"altera", "cyclone V", "5CE*A4", 10}},
{0x02b120dd, {"altera", "cyclone V", "5CGX*4", 10}},
{0x02b130dd, {"altera", "cyclone V", "5CE*A7", 10}},
{0x02b140dd, {"altera", "cyclone V", "5CE*A9", 10}},
{0x02b150dd, {"altera", "cyclone V", "5CE*A2", 10}},
{0x02b220dd, {"altera", "cyclone V", "5CE*A5", 10}},
{0x02d010dd, {"altera", "cyclone V Soc", "5CSE*A4/5CSX*4", 10}},
{0x02d020dd, {"altera", "cyclone V Soc", "5CSE*A6/5CSX*6", 10}},
{0x02d110dd, {"altera", "cyclone V Soc", "5CSE*A2/5CSX*2", 10}},
{0x02d120dd, {"altera", "cyclone V Soc", "5CSE*A5/5CST*5/5CSX*5", 10}},
/* Altera Max 10 */
{0x031820dd, {"altera", "MAX 10", "10M08SAU169C8G", 10}},
{0x031050dd, {"altera", "MAX 10", "10M50DAF484", 10}},
/* Altera Cyclone 10 */
{0x020f30dd, {"altera", "cyclone 10 LP", "10CL025", 10}},
{0x020f50dd, {"altera", "cyclone 10 LP", "10CL055", 10}},
/**************************************************************************/
/* Efinix */
/**************************************************************************/
/* Efinix Trion */
{0x00000001, {"efinix", "Trion", "T4/T8", 4}},
{0x00210a79, {"efinix", "Trion", "T8QFP144/T13/T20", 4}},
{0x00220a79, {"efinix", "Trion", "T55/T85/T120", 4}},
{0x00240a79, {"efinix", "Trion", "T20BGA324/T35", 4}},
/* Efinix Titanium */
{0x00660a79, {"efinix", "Titanium", "Ti60", 5}},
{0x00360a79, {"efinix", "Titanium", "Ti60ES", 5}},
{0x00661a79, {"efinix", "Titanium", "Ti35", 5}},
/**************************************************************************/
/* Lattice */
/**************************************************************************/
/* Lattice XP2 */
{0x0129a043, {"lattice", "XP2", "LFXP2-8E", 8}},
/* Lattice MachXO2 */
{0x012b8043, {"lattice", "MachXO2", "LCMXO2-256HC", 8}},
{0x012b9043, {"lattice", "MachXO2", "LCMXO2-640HC", 8}},
{0x012ba043, {"lattice", "MachXO2", "LCMXO2-1200HC", 8}},
{0x012bd043, {"lattice", "MachXO2", "LCMXO2-7000HC", 8}},
{0x012b5043, {"lattice", "MachXO2", "LCMXO2-7000HE", 8}},
/* Lattice MachXO3 */
{0x012BB043, {"lattice", "MachXO3LF", "LCMX03LF-1300C", 8}},
{0x012B2043, {"lattice", "MachXO3LF", "LCMX03LF-1300E", 8}},
{0x012BB043, {"lattice", "MachXO3LF", "LCMX03LF-2100C", 8}},
{0x012B3043, {"lattice", "MachXO3LF", "LCMX03LF-2100E", 8}},
{0x012BC043, {"lattice", "MachXO3LF", "LCMX03LF-4300C", 8}},
{0x012B4043, {"lattice", "MachXO3LF", "LCMX03LF-4300E", 8}},
{0x012BD043, {"lattice", "MachXO3LF", "LCMX03LF-6900C", 8}},
{0x012B5043, {"lattice", "MachXO3LF", "LCMX03LF-6900E", 8}},
{0x012BE043, {"lattice", "MachXO3LF", "LCMX03LF-9400C", 8}},
{0x012B6043, {"lattice", "MachXO3LF", "LCMX03LF-9400E", 8}},
{0x012e3043, {"lattice", "MachXO3D", "LCMX03D-9400HC", 8}},
/* Lattice ECP5 */
{0x21111043, {"lattice", "ECP5", "LFE5U-12", 8}},
{0x41111043, {"lattice", "ECP5", "LFE5U-25", 8}},
{0x41112043, {"lattice", "ECP5", "LFE5U-45", 8}},
{0x41113043, {"lattice", "ECP5", "LFE5U-85", 8}},
{0x01111043, {"lattice", "ECP5", "LFE5UM-25", 8}},
{0x01112043, {"lattice", "ECP5", "LFE5UM-45", 8}},
{0x01113043, {"lattice", "ECP5", "LFE5UM-85", 8}},
{0x81111043, {"lattice", "ECP5", "LFE5UM5G-25", 8}},
{0x81112043, {"lattice", "ECP5", "LFE5UM5G-45", 8}},
{0x81113043, {"lattice", "ECP5", "LFE5UM5G-85", 8}},
/* Lattice Crosslink-NX */
{0x010F0043, {"lattice", "CrosslinkNX", "LIFCL-17", 8}},
{0x010F1043, {"lattice", "CrosslinkNX", "LIFCL-40", 8}},
/* Lattice Certus-NX */
{0x010F0043, {"lattice", "CertusNX", "LFD2NX-17", 8}},
{0x010F1043, {"lattice", "CertusNX", "LFD2NX-40", 8}},
/**************************************************************************/
/* Gowin */
/**************************************************************************/
/* Gowin GW1 */
{0x0100481b, {"Gowin", "GW1N", "GW1N(R)-9C", 8}},
{0x0100581b, {"Gowin", "GW1N", "GW1NR-9", 8}},
{0x0900281B, {"Gowin", "GW1N", "GW1N-1", 8}},
{0x0120681b, {"Gowin", "GW1N", "GW1N-2", 8}},
{0x0100381B, {"Gowin", "GW1N", "GW1N-4", 8}},
{0x0100681b, {"Gowin", "GW1NZ", "GW1NZ-1", 8}},
{0x0300181b, {"Gowin", "GW1NS", "GW1NS-2C", 8}},
{0x0100981b, {"Gowin", "GW1NSR", "GW1NSR-4C", 8}},
/* Gowin GW2 */
{0x0000081b, {"Gowin", "GW2A", "GW2A(R)-18(C)", 8}},
/**************************************************************************/
/* CologneChip */
/**************************************************************************/
/* CologneChip GateMate*/
/* keep highest nibble to prevent confusion with Efinix T4/T8 IDCODE */
{0x20000001, {"colognechip", "GateMate Series", "GM1Ax", 6}},
};
/* Highest nibble (version) must always be set to 0 */
static std::map <std::string, std::map <uint32_t, device_model>> fpga_vnd_list = {
/**************************************************************************/ /**************************************************************************/
/* Altera */ /* Altera */
/**************************************************************************/ /**************************************************************************/
@ -468,11 +250,6 @@ static std::map <std::string, std::map <uint32_t, device_model>> fpga_vnd_list =
}; };
/* device potentially in JTAG chain but not handled */ /* device potentially in JTAG chain but not handled */
typedef struct {
std::string name;
int irlength;
} misc_device;
static std::map <uint32_t, device_model> misc_dev_list = { static std::map <uint32_t, device_model> misc_dev_list = {
{0x4ba00477, {"ARM", "cortex", "A9", 4}}, {0x4ba00477, {"ARM", "cortex", "A9", 4}},
{0x5ba00477, {"ARM", "cortex", "A53", 4}}, {0x5ba00477, {"ARM", "cortex", "A53", 4}},

View File

@ -176,17 +176,18 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
} }
} }
uint32_t idcode = _jtag->get_target_device_id(); Jtag::found_device *tgt_dev = _jtag->get_target();
std::string family = fpga_list[idcode].family; uint32_t idcode = tgt_dev->idcode;
std::string model = fpga_list[idcode].model; _family = tgt_dev->model->family;
_irlen = fpga_list[idcode].irlength; _model = tgt_dev->model->model;
_irlen = tgt_dev->irlength;
_ircode_map = ircode_mapping.at("default"); _ircode_map = ircode_mapping.at("default");
if (family.substr(0, 5) == "artix") { if (_family.substr(0, 5) == "artix") {
_fpga_family = ARTIX_FAMILY; _fpga_family = ARTIX_FAMILY;
} else if (family == "spartan7") { } else if (_family == "spartan7") {
_fpga_family = SPARTAN7_FAMILY; _fpga_family = SPARTAN7_FAMILY;
} else if (family == "zynq") { } else if (_family == "zynq") {
_fpga_family = ZYNQ_FAMILY; _fpga_family = ZYNQ_FAMILY;
if (_mode != Device::MEM_MODE) { if (_mode != Device::MEM_MODE) {
char mess[256]; char mess[256];
@ -195,7 +196,7 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
"\tSPI Flash access is only available from PS side\n"); "\tSPI Flash access is only available from PS side\n");
throw std::runtime_error(mess); throw std::runtime_error(mess);
} }
} else if (family.substr(0, 6) == "zynqmp") { } else if (_family.substr(0, 6) == "zynqmp") {
if (_mode != Device::MEM_MODE) { if (_mode != Device::MEM_MODE) {
char mess[256]; char mess[256];
snprintf(mess, 256, "Error: can't flash non-volatile memory for " snprintf(mess, 256, "Error: can't flash non-volatile memory for "
@ -203,35 +204,35 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
"\tSPI Flash access is only available from PSU side\n"); "\tSPI Flash access is only available from PSU side\n");
throw std::runtime_error(mess); throw std::runtime_error(mess);
} }
if (!zynqmp_init(family)) if (!zynqmp_init(_family))
throw std::runtime_error("Error with ZynqMP init"); throw std::runtime_error("Error with ZynqMP init");
_fpga_family = ZYNQMP_FAMILY; _fpga_family = ZYNQMP_FAMILY;
} else if (family == "kintex7") { } else if (_family == "kintex7") {
_fpga_family = KINTEX_FAMILY; _fpga_family = KINTEX_FAMILY;
} else if (family == "kintexus") { } else if (_family == "kintexus") {
_fpga_family = KINTEXUS_FAMILY; _fpga_family = KINTEXUS_FAMILY;
} else if (family == "kintexusp") { } else if (_family == "kintexusp") {
_fpga_family = KINTEXUSP_FAMILY; _fpga_family = KINTEXUSP_FAMILY;
} else if (family == "artixusp") { } else if (_family == "artixusp") {
_fpga_family = ARTIXUSP_FAMILY; _fpga_family = ARTIXUSP_FAMILY;
} else if (family == "virtexusp") { } else if (_family == "virtexusp") {
_fpga_family = VIRTEXUSP_FAMILY; _fpga_family = VIRTEXUSP_FAMILY;
_ircode_map = ircode_mapping.at("virtexusp"); _ircode_map = ircode_mapping.at("virtexusp");
} else if (family.substr(0, 8) == "spartan3") { } else if (_family.substr(0, 8) == "spartan3") {
_fpga_family = SPARTAN3_FAMILY; _fpga_family = SPARTAN3_FAMILY;
if (_mode != Device::MEM_MODE) { if (_mode != Device::MEM_MODE) {
throw std::runtime_error("Error: Only load to mem is supported"); throw std::runtime_error("Error: Only load to mem is supported");
} }
} else if (family == "xcf") { } else if (_family == "xcf") {
_fpga_family = XCF_FAMILY; _fpga_family = XCF_FAMILY;
if (_mode == Device::MEM_MODE) { if (_mode == Device::MEM_MODE) {
throw std::runtime_error("Error: Only write or read is supported"); throw std::runtime_error("Error: Only write or read is supported");
} }
} else if (family == "spartan6") { } else if (_family == "spartan6") {
_fpga_family = SPARTAN6_FAMILY; _fpga_family = SPARTAN6_FAMILY;
} else if (family == "xc2c") { } else if (_family == "xc2c") {
xc2c_init(idcode); xc2c_init(idcode);
} else if (family == "xc9500xl") { } else if (_family == "xc9500xl") {
_fpga_family = XC95_FAMILY; _fpga_family = XC95_FAMILY;
switch (idcode) { switch (idcode) {
case 0x09602093: case 0x09602093:
@ -776,8 +777,7 @@ bool Xilinx::xc3s_flow_program(ConfigBitstreamParser *bit)
flow_disable(); flow_disable();
uint8_t mask = 0x20; // Done bit uint8_t mask = 0x20; // Done bit
uint32_t idcode = _jtag->get_target_device_id(); if (_family == "spartan3e") {
if (fpga_list[idcode].family == "spartan3e") {
mask = 0x10; // ISC done dit mask = 0x10; // ISC done dit
} }
int retry = 100; int retry = 100;
@ -1290,10 +1290,9 @@ static constexpr uint8_t _gray_code[256] = {
void Xilinx::xc2c_init(uint32_t idcode) void Xilinx::xc2c_init(uint32_t idcode)
{ {
_fpga_family = XC2C_FAMILY; _fpga_family = XC2C_FAMILY;
std::string model = fpga_list[idcode].model; int underscore_pos = _model.find_first_of('_', 0);
int underscore_pos = model.find_first_of('_', 0);
snprintf(_cpld_base_name, underscore_pos, snprintf(_cpld_base_name, underscore_pos,
"%s", model.substr(0, underscore_pos).c_str()); "%s", _model.substr(0, underscore_pos).c_str());
switch ((idcode >> 16) & 0x3f) { switch ((idcode >> 16) & 0x3f) {
case 0x01: /* xc2c32 */ case 0x01: /* xc2c32 */
case 0x11: /* xc2c32a PC44 */ case 0x11: /* xc2c32a PC44 */

View File

@ -212,6 +212,8 @@ class Xilinx: public Device, SPIInterface {
std::string _secondary_file_extension; /* file type for the secondary flash file */ std::string _secondary_file_extension; /* file type for the secondary flash file */
int _flash_chips; /* bitfield to select the target in boards with two flash chips */ int _flash_chips; /* bitfield to select the target in boards with two flash chips */
std::string _user_instruction; /* which USER bscan instruction to interface with SPI */ std::string _user_instruction; /* which USER bscan instruction to interface with SPI */
std::string _model; /* device model */
std::string _family; /* device family */
}; };
#endif #endif