pld: give devices a name for referencing in scripts

Change-Id: I05e8596ffacdb6cd8da4dd8a40bb460183f4930a
Signed-off-by: Daniel Anselmi <danselmi@gmx.ch>
Reviewed-on: https://review.openocd.org/c/openocd/+/7728
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Daniel Anselmi 2023-06-03 20:16:19 +02:00 committed by Antonio Borneo
parent 7335fbdbda
commit 5ae0264055
27 changed files with 298 additions and 251 deletions

View File

@ -8575,22 +8575,24 @@ As it does for JTAG TAPs, debug targets, and flash chips (both NOR and NAND),
OpenOCD maintains a list of PLDs available for use in various commands.
Also, each such PLD requires a driver.
They are referenced by the number shown by the @command{pld devices} command,
and new PLDs are defined by @command{pld device driver_name}.
They are referenced by the name which was given when the pld was created or
the number shown by the @command{pld devices} command.
New PLDs are defined by @command{pld create pld_name driver_name -chain-position tap_name [driver_options]}.
@deffn {Config Command} {pld device} driver_name tap_name [driver_options]
Defines a new PLD device, supported by driver @var{driver_name},
using the TAP named @var{tap_name}.
The driver may make use of any @var{driver_options} to configure its
behavior.
@deffn {Config Command} {pld create} pld_name driver_name -chain-position tap_name [driver_options]
Creates a new PLD device, supported by driver @var{driver_name},
assigning @var{pld_name} for further reference.
@code{-chain-position} @var{tap_name} names the TAP
used to access this target.
The driver may make use of any @var{driver_options} to configure its behavior.
@end deffn
@deffn {Command} {pld devices}
Lists the PLDs and their numbers.
List the known PLDs with their name.
@end deffn
@deffn {Command} {pld load} num filename
Loads the file @file{filename} into the PLD identified by @var{num}.
@deffn {Command} {pld load} pld_name filename
Loads the file @file{filename} into the PLD identified by @var{pld_name}.
The file format must be inferred by the driver.
@end deffn
@ -8600,12 +8602,12 @@ Drivers may support PLD-specific options to the @command{pld device}
definition command, and may also define commands usable only with
that particular type of PLD.
@deffn {FPGA Driver} {virtex2} [no_jstart]
@deffn {FPGA Driver} {virtex2} [@option{-no_jstart}]
Virtex-II is a family of FPGAs sold by Xilinx.
This driver can also be used to load Series3, Series6, Series7 and Zynq 7000 devices.
It supports the IEEE 1532 standard for In-System Configuration (ISC).
If @var{no_jstart} is non-zero, the JSTART instruction is not used after
If @var{-no_jstart} is given, the JSTART instruction is not used after
loading the bitstream. While required for Series2, Series3, and Series6, it
breaks bitstream loading on Series7.
@ -8615,38 +8617,38 @@ openocd -f board/digilent_zedboard.cfg -c "init" \
@end example
@deffn {Command} {virtex2 read_stat} num
@deffn {Command} {virtex2 read_stat} pld_name
Reads and displays the Virtex-II status register (STAT)
for FPGA @var{num}.
for FPGA @var{pld_name}.
@end deffn
@end deffn
@deffn {FPGA Driver} {lattice} [family]
@deffn {FPGA Driver} {lattice} [@option{-family} <name>]
The FGPA families ECP2, ECP3, ECP5, Certus and CertusPro by Lattice are supported.
This driver can be used to load the bitstream into the FPGA or read the status register and read/write the usercode register.
The option @option{family} is one of @var{ecp2 ecp3 ecp5 certus}. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices).
For the option @option{-family} @var{name} is one of @var{ecp2 ecp3 ecp5 certus}. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices).
@deffn {Command} {lattice read_status} num
@deffn {Command} {lattice read_status} pld_name
Reads and displays the status register
for FPGA @var{num}.
for FPGA @var{pld_name}.
@end deffn
@deffn {Command} {lattice read_user} num
@deffn {Command} {lattice read_user} pld_name
Reads and displays the user register
for FPGA @var{num}.
for FPGA @var{pld_name}.
@end deffn
@deffn {Command} {lattice write_user} num val
@deffn {Command} {lattice write_user} pld_name val
Writes the user register.
for FPGA @var{num} with value @var{val}.
for FPGA @var{pld_name} with value @var{val}.
@end deffn
@deffn {Command} {lattice set_preload} num length
@deffn {Command} {lattice set_preload} pld_name length
Set the length of the register for the preload. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices).
The load command for the FPGA @var{num} will use a length for the preload of @var{length}.
The load command for the FPGA @var{pld_name} will use a length for the preload of @var{length}.
@end deffn
@end deffn
@ -8657,28 +8659,28 @@ This driver can be used to load the bitstream into the FPGA.
@end deffn
@deffn {FPGA Driver} {intel} [@option{family}]
@deffn {FPGA Driver} {intel} [@option{-family} <name>]
This driver can be used to load the bitstream into Intel (former Altera) FPGAs.
The families Cyclone III, Cyclone IV, Cyclone V, Cyclone 10, Arria II are supported.
@c Arria V and Arria 10, MAX II, MAX V, MAX10)
The option @option{family} is one of @var{cycloneiii cycloneiv cyclonev cyclone10 arriaii}.
For the option @option{-family} @var{name} is one of @var{cycloneiii cycloneiv cyclonev cyclone10 arriaii}.
This is needed when the JTAG ID of the device is ambiguous (same ID is used for chips in different families).
As input file format the driver supports a '.rbf' (raw bitstream file) file. The '.rbf' file can be generated
from a '.sof' file with @verb{|quartus_cpf -c blinker.sof blinker.rbf|}
Defines a new PLD device, an FPGA of the Cyclone III family, using the TAP named @verb{|cycloneiii.tap|}:
Creates a new PLD device, an FPGA of the Cyclone III family, using the TAP named @verb{|cycloneiii.tap|}:
@example
pld device intel cycloneiii.tap cycloneiii
pld create cycloneiii.pld intel -chain-position cycloneiii.tap -family cycloneiii
@end example
@deffn {Command} {intel set_bscan} num len
Set boundary scan register length of FPGA @var{num} to @var{len}. This is needed because the
@deffn {Command} {intel set_bscan} pld_name len
Set boundary scan register length of FPGA @var{pld_name} to @var{len}. This is needed because the
length can vary between chips with the same JTAG ID.
@end deffn
@deffn {Command} {intel set_check_pos} num pos
@deffn {Command} {intel set_check_pos} pld_name pos
Selects the position @var{pos} in the boundary-scan register. The bit at this
position is checked after loading the bitstream and must be '1', which is the case when no error occurred.
With a value of -1 for @var{pos} the check will be omitted.

View File

@ -1108,4 +1108,18 @@ proc "am335xgpio led_on_state" {state} {
}
}
lappend _telnet_autocomplete_skip "pld device"
proc "pld device" {driver tap_name {opt 0}} {
echo "DEPRECATED! use 'pld create ...', not 'pld device ...'"
if {[string is integer -strict $opt]} {
if {$opt == 0} {
eval pld create [lindex [split $tap_name .] 0].pld $driver -chain-position $tap_name
} else {
eval pld create [lindex [split $tap_name .] 0].pld $driver -chain-position $tap_name -no_jstart
}
} else {
eval pld create [lindex [split $tap_name .] 0].pld $driver -chain-position $tap_name -family $opt
}
}
# END MIGRATION AIDS

View File

@ -188,14 +188,17 @@ static int efinix_load(struct pld_device *pld_device, const char *filename)
return retval;
}
PLD_DEVICE_COMMAND_HANDLER(efinix_pld_device_command)
PLD_CREATE_COMMAND_HANDLER(efinix_pld_create_command)
{
if (CMD_ARGC != 2)
if (CMD_ARGC != 4)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
return ERROR_FAIL;
}
@ -213,6 +216,6 @@ PLD_DEVICE_COMMAND_HANDLER(efinix_pld_device_command)
struct pld_driver efinix_pld = {
.name = "efinix",
.pld_device_command = &efinix_pld_device_command,
.pld_create_command = &efinix_pld_create_command,
.load = &efinix_load,
};

View File

@ -209,22 +209,21 @@ static int gatemate_load(struct pld_device *pld_device, const char *filename)
return retval;
}
PLD_DEVICE_COMMAND_HANDLER(gatemate_pld_device_command)
PLD_CREATE_COMMAND_HANDLER(gatemate_pld_create_command)
{
struct jtag_tap *tap;
struct gatemate_pld_device *gatemate_info;
if (CMD_ARGC != 2)
if (CMD_ARGC != 4)
return ERROR_COMMAND_SYNTAX_ERROR;
tap = jtag_tap_by_string(CMD_ARGV[1]);
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
return ERROR_FAIL;
}
gatemate_info = malloc(sizeof(struct gatemate_pld_device));
struct gatemate_pld_device *gatemate_info = malloc(sizeof(struct gatemate_pld_device));
if (!gatemate_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
@ -238,6 +237,6 @@ PLD_DEVICE_COMMAND_HANDLER(gatemate_pld_device_command)
struct pld_driver gatemate_pld = {
.name = "gatemate",
.pld_device_command = &gatemate_pld_device_command,
.pld_create_command = &gatemate_pld_create_command,
.load = &gatemate_load,
};

View File

@ -451,15 +451,12 @@ static int gowin_reload_command(struct pld_device *pld_device)
COMMAND_HANDLER(gowin_read_status_command_handler)
{
int dev_id;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -474,15 +471,12 @@ COMMAND_HANDLER(gowin_read_status_command_handler)
COMMAND_HANDLER(gowin_read_user_register_command_handler)
{
int dev_id;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -497,15 +491,12 @@ COMMAND_HANDLER(gowin_read_user_register_command_handler)
COMMAND_HANDLER(gowin_reload_command_handler)
{
int dev_id;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -518,19 +509,19 @@ static const struct command_registration gowin_exec_command_handlers[] = {
.mode = COMMAND_EXEC,
.handler = gowin_read_status_command_handler,
.help = "reading status register from FPGA",
.usage = "num_pld",
.usage = "pld_name",
}, {
.name = "read_user",
.mode = COMMAND_EXEC,
.handler = gowin_read_user_register_command_handler,
.help = "reading user register from FPGA",
.usage = "num_pld",
.usage = "pld_name",
}, {
.name = "reload",
.mode = COMMAND_EXEC,
.handler = gowin_reload_command_handler,
.help = "reloading bitstream from flash to SRAM",
.usage = "num_pld",
.usage = "pld_name",
},
COMMAND_REGISTRATION_DONE
};
@ -546,22 +537,21 @@ static const struct command_registration gowin_command_handler[] = {
COMMAND_REGISTRATION_DONE
};
PLD_DEVICE_COMMAND_HANDLER(gowin_pld_device_command)
PLD_CREATE_COMMAND_HANDLER(gowin_pld_create_command)
{
struct jtag_tap *tap;
struct gowin_pld_device *gowin_info;
if (CMD_ARGC != 2)
if (CMD_ARGC != 4)
return ERROR_COMMAND_SYNTAX_ERROR;
tap = jtag_tap_by_string(CMD_ARGV[1]);
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
return ERROR_FAIL;
}
gowin_info = malloc(sizeof(struct gowin_pld_device));
struct gowin_pld_device *gowin_info = malloc(sizeof(struct gowin_pld_device));
if (!gowin_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
@ -576,6 +566,6 @@ PLD_DEVICE_COMMAND_HANDLER(gowin_pld_device_command)
struct pld_driver gowin_pld = {
.name = "gowin",
.commands = gowin_command_handler,
.pld_device_command = &gowin_pld_device_command,
.pld_create_command = &gowin_pld_create_command,
.load = &gowin_load_to_sram,
};

View File

@ -339,16 +339,14 @@ static int intel_load(struct pld_device *pld_device, const char *filename)
COMMAND_HANDLER(intel_set_bscan_command_handler)
{
int dev_id;
unsigned int boundary_scan_length;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *pld_device = get_pld_device_by_num(dev_id);
struct pld_device *pld_device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!pld_device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -366,16 +364,14 @@ COMMAND_HANDLER(intel_set_bscan_command_handler)
COMMAND_HANDLER(intel_set_check_pos_command_handler)
{
int dev_id;
int checkpos;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *pld_device = get_pld_device_by_num(dev_id);
struct pld_device *pld_device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!pld_device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -392,42 +388,47 @@ COMMAND_HANDLER(intel_set_check_pos_command_handler)
}
PLD_DEVICE_COMMAND_HANDLER(intel_pld_device_command)
PLD_CREATE_COMMAND_HANDLER(intel_pld_create_command)
{
if (CMD_ARGC < 2 || CMD_ARGC > 3)
if (CMD_ARGC != 4 && CMD_ARGC != 6)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
return ERROR_FAIL;
}
enum intel_family_e family = INTEL_UNKNOWN;
if (CMD_ARGC == 6) {
if (strcmp(CMD_ARGV[4], "-family") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (strcmp(CMD_ARGV[5], "cycloneiii") == 0) {
family = INTEL_CYCLONEIII;
} else if (strcmp(CMD_ARGV[5], "cycloneiv") == 0) {
family = INTEL_CYCLONEIV;
} else if (strcmp(CMD_ARGV[5], "cyclonev") == 0) {
family = INTEL_CYCLONEV;
} else if (strcmp(CMD_ARGV[5], "cyclone10") == 0) {
family = INTEL_CYCLONE10;
} else if (strcmp(CMD_ARGV[5], "arriaii") == 0) {
family = INTEL_ARRIAII;
} else {
command_print(CMD, "unknown family");
return ERROR_FAIL;
}
}
struct intel_pld_device *intel_info = malloc(sizeof(struct intel_pld_device));
if (!intel_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
enum intel_family_e family = INTEL_UNKNOWN;
if (CMD_ARGC == 3) {
if (strcmp(CMD_ARGV[2], "cycloneiii") == 0) {
family = INTEL_CYCLONEIII;
} else if (strcmp(CMD_ARGV[2], "cycloneiv") == 0) {
family = INTEL_CYCLONEIV;
} else if (strcmp(CMD_ARGV[2], "cyclonev") == 0) {
family = INTEL_CYCLONEV;
} else if (strcmp(CMD_ARGV[2], "cyclone10") == 0) {
family = INTEL_CYCLONE10;
} else if (strcmp(CMD_ARGV[2], "arriaii") == 0) {
family = INTEL_ARRIAII;
} else {
command_print(CMD, "unknown family");
free(intel_info);
return ERROR_FAIL;
}
}
intel_info->tap = tap;
intel_info->boundary_scan_length = 0;
intel_info->checkpos = -1;
@ -444,13 +445,13 @@ static const struct command_registration intel_exec_command_handlers[] = {
.mode = COMMAND_EXEC,
.handler = intel_set_bscan_command_handler,
.help = "set boundary scan register length of FPGA",
.usage = "num_pld len",
.usage = "pld_name len",
}, {
.name = "set_check_pos",
.mode = COMMAND_EXEC,
.handler = intel_set_check_pos_command_handler,
.help = "set check_pos of FPGA",
.usage = "num_pld pos",
.usage = "pld_name pos",
},
COMMAND_REGISTRATION_DONE
};
@ -469,6 +470,6 @@ static const struct command_registration intel_command_handler[] = {
struct pld_driver intel_pld = {
.name = "intel",
.commands = intel_command_handler,
.pld_device_command = &intel_pld_device_command,
.pld_create_command = &intel_pld_create_command,
.load = &intel_load,
};

View File

@ -316,39 +316,46 @@ static int lattice_load_command(struct pld_device *pld_device, const char *filen
return retval;
}
PLD_DEVICE_COMMAND_HANDLER(lattice_pld_device_command)
PLD_CREATE_COMMAND_HANDLER(lattice_pld_create_command)
{
if (CMD_ARGC < 2 || CMD_ARGC > 3)
if (CMD_ARGC != 4 && CMD_ARGC != 6)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
return ERROR_FAIL;
}
/* id is not known yet -> postpone lattice_check_device_family() */
enum lattice_family_e family = LATTICE_UNKNOWN;
if (CMD_ARGC == 6) {
if (strcmp(CMD_ARGV[4], "-family") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (strcasecmp(CMD_ARGV[5], "ecp2") == 0) {
family = LATTICE_ECP2;
} else if (strcasecmp(CMD_ARGV[5], "ecp3") == 0) {
family = LATTICE_ECP3;
} else if (strcasecmp(CMD_ARGV[5], "ecp5") == 0) {
family = LATTICE_ECP5;
} else if (strcasecmp(CMD_ARGV[5], "certus") == 0) {
family = LATTICE_CERTUS;
} else {
command_print(CMD, "unknown family");
return ERROR_FAIL;
}
}
struct lattice_pld_device *lattice_device = malloc(sizeof(struct lattice_pld_device));
if (!lattice_device) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
/* id is not known yet -> postpone lattice_check_device_family() */
enum lattice_family_e family = LATTICE_UNKNOWN;
if (CMD_ARGC == 3) {
if (strcasecmp(CMD_ARGV[2], "ecp2") == 0) {
family = LATTICE_ECP2;
} else if (strcasecmp(CMD_ARGV[2], "ecp3") == 0) {
family = LATTICE_ECP3;
} else if (strcasecmp(CMD_ARGV[2], "ecp5") == 0) {
family = LATTICE_ECP5;
} else if (strcasecmp(CMD_ARGV[2], "certus") == 0) {
family = LATTICE_CERTUS;
} else {
command_print(CMD, "unknown family");
free(lattice_device);
return ERROR_FAIL;
}
}
lattice_device->tap = tap;
lattice_device->family = family;
lattice_device->preload_length = 0;
@ -360,16 +367,14 @@ PLD_DEVICE_COMMAND_HANDLER(lattice_pld_device_command)
COMMAND_HANDLER(lattice_read_usercode_register_command_handler)
{
int dev_id;
uint32_t usercode;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -390,16 +395,14 @@ COMMAND_HANDLER(lattice_read_usercode_register_command_handler)
COMMAND_HANDLER(lattice_set_preload_command_handler)
{
int dev_id;
unsigned int preload_length;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -417,16 +420,14 @@ COMMAND_HANDLER(lattice_set_preload_command_handler)
COMMAND_HANDLER(lattice_write_usercode_register_command_handler)
{
int dev_id;
uint32_t usercode;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -445,15 +446,12 @@ COMMAND_HANDLER(lattice_write_usercode_register_command_handler)
COMMAND_HANDLER(lattice_read_status_command_handler)
{
int dev_id;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -487,25 +485,25 @@ static const struct command_registration lattice_exec_command_handlers[] = {
.mode = COMMAND_EXEC,
.handler = lattice_read_status_command_handler,
.help = "reading status register from FPGA",
.usage = "num_pld",
.usage = "pld_name",
}, {
.name = "read_user",
.mode = COMMAND_EXEC,
.handler = lattice_read_usercode_register_command_handler,
.help = "reading usercode register from FPGA",
.usage = "num_pld",
.usage = "pld_name",
}, {
.name = "write_user",
.mode = COMMAND_EXEC,
.handler = lattice_write_usercode_register_command_handler,
.help = "writing usercode register to FPGA",
.usage = "num_pld value",
.usage = "pld_name value",
}, {
.name = "set_preload",
.mode = COMMAND_EXEC,
.handler = lattice_set_preload_command_handler,
.help = "set length for preload (device specific)",
.usage = "num_pld value",
.usage = "pld_name value",
},
COMMAND_REGISTRATION_DONE
};
@ -524,6 +522,6 @@ static const struct command_registration lattice_command_handler[] = {
struct pld_driver lattice_pld = {
.name = "lattice",
.commands = lattice_command_handler,
.pld_device_command = &lattice_pld_device_command,
.pld_create_command = &lattice_pld_create_command,
.load = &lattice_load_command,
};

View File

@ -34,68 +34,110 @@ struct pld_device *get_pld_device_by_num(int num)
int i = 0;
for (p = pld_devices; p; p = p->next) {
if (i++ == num)
if (i++ == num) {
LOG_WARNING("DEPRECATED: use pld name \"%s\" instead of number %d", p->name, num);
return p;
}
}
return NULL;
}
struct pld_device *get_pld_device_by_name(const char *name)
{
for (struct pld_device *p = pld_devices; p; p = p->next) {
if (strcmp(p->name, name) == 0)
return p;
}
return NULL;
}
/* pld device <driver> [driver_options ...]
*/
COMMAND_HANDLER(handle_pld_device_command)
struct pld_device *get_pld_device_by_name_or_numstr(const char *str)
{
int i;
int found = 0;
struct pld_device *dev = get_pld_device_by_name(str);
if (dev)
return dev;
if (CMD_ARGC < 1)
char *end;
unsigned long dev_num = strtoul(str, &end, 0);
if (*end || dev_num > INT_MAX) {
LOG_ERROR("Invalid argument");
return NULL;
}
return get_pld_device_by_num(dev_num);
}
/* @deffn {Config Command} {pld create} pld_name driver -chain-position tap_name [options]
*/
COMMAND_HANDLER(handle_pld_create_command)
{
if (CMD_ARGC < 2)
return ERROR_COMMAND_SYNTAX_ERROR;
for (i = 0; pld_drivers[i]; i++) {
if (strcmp(CMD_ARGV[0], pld_drivers[i]->name) == 0) {
struct pld_device *p, *c;
struct pld_driver *pld_driver = NULL;
/* register pld specific commands */
int retval;
if (pld_drivers[i]->commands) {
retval = register_commands(CMD_CTX, NULL, pld_drivers[i]->commands);
if (retval != ERROR_OK) {
LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[0]);
return ERROR_FAIL;
}
}
c = malloc(sizeof(struct pld_device));
c->driver = pld_drivers[i];
c->next = NULL;
retval = CALL_COMMAND_HANDLER(
pld_drivers[i]->pld_device_command, c);
if (retval != ERROR_OK) {
LOG_ERROR("'%s' driver rejected pld device",
CMD_ARGV[0]);
free(c);
return ERROR_OK;
}
/* put pld device in linked list */
if (pld_devices) {
/* find last pld device */
for (p = pld_devices; p && p->next; p = p->next)
;
if (p)
p->next = c;
} else
pld_devices = c;
found = 1;
for (int i = 0; pld_drivers[i]; i++) {
if (strcmp(CMD_ARGV[1], pld_drivers[i]->name) == 0) {
pld_driver = pld_drivers[i];
break;
}
}
/* no matching pld driver found */
if (!found) {
LOG_ERROR("pld driver '%s' not found", CMD_ARGV[0]);
exit(-1);
if (!pld_driver) {
LOG_ERROR("pld driver '%s' not found", CMD_ARGV[1]);
return ERROR_FAIL; /* exit(-1); */
}
if (get_pld_device_by_name(CMD_ARGV[0])) {
LOG_ERROR("pld device with name '%s' already exists", CMD_ARGV[0]);
return ERROR_FAIL;
}
struct pld_device *pld_device = malloc(sizeof(struct pld_device));
if (!pld_device) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
pld_device->driver = pld_driver;
pld_device->next = NULL;
int retval = CALL_COMMAND_HANDLER(pld_driver->pld_create_command, pld_device);
if (retval != ERROR_OK) {
LOG_ERROR("'%s' driver rejected pld device",
CMD_ARGV[1]);
free(pld_device);
return ERROR_OK;
}
pld_device->name = strdup(CMD_ARGV[0]);
if (!pld_device->name) {
LOG_ERROR("Out of memory");
free(pld_device);
return ERROR_FAIL;
}
/* register pld specific commands */
if (pld_driver->commands) {
retval = register_commands(CMD_CTX, NULL, pld_driver->commands);
if (retval != ERROR_OK) {
LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[1]);
free(pld_device->name);
free(pld_device);
return ERROR_FAIL;
}
}
if (pld_devices) {
/* find last pld device */
struct pld_device *p = pld_devices;
for (; p && p->next; p = p->next)
;
if (p)
p->next = pld_device;
} else {
pld_devices = pld_device;
}
return ERROR_OK;
@ -112,7 +154,7 @@ COMMAND_HANDLER(handle_pld_devices_command)
}
for (p = pld_devices; p; p = p->next)
command_print(CMD, "#%i: %s", i++, p->driver->name);
command_print(CMD, "#%i: %s (driver: %s)", i++, p->name, p->driver->name);
return ERROR_OK;
}
@ -128,11 +170,9 @@ COMMAND_HANDLER(handle_pld_load_command)
if (CMD_ARGC < 2)
return ERROR_COMMAND_SYNTAX_ERROR;
unsigned dev_id;
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], dev_id);
p = get_pld_device_by_num(dev_id);
p = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!p) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_OK;
}
@ -154,15 +194,15 @@ COMMAND_HANDLER(handle_pld_load_command)
retval = p->driver->load(p, CMD_ARGV[1]);
if (retval != ERROR_OK) {
command_print(CMD, "failed loading file %s to pld device %u",
CMD_ARGV[1], dev_id);
command_print(CMD, "failed loading file %s to pld device %s",
CMD_ARGV[1], CMD_ARGV[0]);
return retval;
} else {
gettimeofday(&end, NULL);
timeval_subtract(&duration, &end, &start);
command_print(CMD, "loaded file %s to pld device %u in %jis %jius",
CMD_ARGV[1], dev_id,
command_print(CMD, "loaded file %s to pld device %s in %jis %jius",
CMD_ARGV[1], CMD_ARGV[0],
(intmax_t)duration.tv_sec, (intmax_t)duration.tv_usec);
}
@ -182,7 +222,7 @@ static const struct command_registration pld_exec_command_handlers[] = {
.handler = handle_pld_load_command,
.mode = COMMAND_EXEC,
.help = "load configuration file into PLD",
.usage = "pld_num filename",
.usage = "pld_name filename",
},
COMMAND_REGISTRATION_DONE
};
@ -213,11 +253,11 @@ COMMAND_HANDLER(handle_pld_init_command)
static const struct command_registration pld_config_command_handlers[] = {
{
.name = "device",
.name = "create",
.mode = COMMAND_CONFIG,
.handler = handle_pld_device_command,
.help = "configure a PLD device",
.usage = "driver_name [driver_args ... ]",
.handler = handle_pld_create_command,
.help = "create a PLD device",
.usage = "name.pld driver_name [driver_args ... ]",
},
{
.name = "init",

View File

@ -12,28 +12,31 @@
struct pld_device;
#define __PLD_DEVICE_COMMAND(name) \
#define __PLD_CREATE_COMMAND(name) \
COMMAND_HELPER(name, struct pld_device *pld)
struct pld_driver {
const char *name;
__PLD_DEVICE_COMMAND((*pld_device_command));
__PLD_CREATE_COMMAND((*pld_create_command));
const struct command_registration *commands;
int (*load)(struct pld_device *pld_device, const char *filename);
};
#define PLD_DEVICE_COMMAND_HANDLER(name) \
static __PLD_DEVICE_COMMAND(name)
#define PLD_CREATE_COMMAND_HANDLER(name) \
static __PLD_CREATE_COMMAND(name)
struct pld_device {
struct pld_driver *driver;
void *driver_priv;
struct pld_device *next;
char *name;
};
int pld_register_commands(struct command_context *cmd_ctx);
struct pld_device *get_pld_device_by_num(int num);
struct pld_device *get_pld_device_by_name(const char *name);
struct pld_device *get_pld_device_by_name_or_numstr(const char *str);
#define ERROR_PLD_DEVICE_INVALID (-1000)
#define ERROR_PLD_FILE_LOAD_FAILED (-1001)

View File

@ -233,11 +233,9 @@ COMMAND_HANDLER(virtex2_handle_read_stat_command)
if (CMD_ARGC < 1)
return ERROR_COMMAND_SYNTAX_ERROR;
unsigned dev_id;
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], dev_id);
device = get_pld_device_by_num(dev_id);
device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -252,22 +250,21 @@ COMMAND_HANDLER(virtex2_handle_read_stat_command)
return ERROR_OK;
}
PLD_DEVICE_COMMAND_HANDLER(virtex2_pld_device_command)
PLD_CREATE_COMMAND_HANDLER(virtex2_pld_create_command)
{
struct jtag_tap *tap;
struct virtex2_pld_device *virtex2_info;
if (CMD_ARGC < 2)
if (CMD_ARGC < 4)
return ERROR_COMMAND_SYNTAX_ERROR;
tap = jtag_tap_by_string(CMD_ARGV[1]);
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
return ERROR_FAIL;
}
virtex2_info = malloc(sizeof(struct virtex2_pld_device));
struct virtex2_pld_device *virtex2_info = malloc(sizeof(struct virtex2_pld_device));
if (!virtex2_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
@ -275,8 +272,8 @@ PLD_DEVICE_COMMAND_HANDLER(virtex2_pld_device_command)
virtex2_info->tap = tap;
virtex2_info->no_jstart = 0;
if (CMD_ARGC >= 3)
COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], virtex2_info->no_jstart);
if (CMD_ARGC >= 5 && strcmp(CMD_ARGV[4], "-no_jstart") == 0)
virtex2_info->no_jstart = 1;
pld->driver_priv = virtex2_info;
@ -289,7 +286,7 @@ static const struct command_registration virtex2_exec_command_handlers[] = {
.mode = COMMAND_EXEC,
.handler = virtex2_handle_read_stat_command,
.help = "read status register",
.usage = "pld_num",
.usage = "pld_name",
},
COMMAND_REGISTRATION_DONE
};
@ -307,6 +304,6 @@ static const struct command_registration virtex2_command_handler[] = {
struct pld_driver virtex2_pld = {
.name = "virtex2",
.commands = virtex2_command_handler,
.pld_device_command = &virtex2_pld_device_command,
.pld_create_command = &virtex2_pld_create_command,
.load = &virtex2_load,
};

View File

@ -25,7 +25,7 @@ jtag newtap $_CHIPNAME tap -irlen 6 -ignore-version \
-expected-id 0x0401D093 \
-expected-id 0x0403D093
pld device virtex2 $_CHIPNAME.tap
pld create $_CHIPNAME.pld virtex2 -chain-position $_CHIPNAME.tap
set XC6S_CFG_IN 0x05
set XC6S_JSHUTDOWN 0x0d

View File

@ -49,7 +49,7 @@ jtag newtap $_CHIPNAME tap -irlen 6 -ignore-version \
#jtag newtap $_CHIPNAME tap -irlen 38 -ignore-version -expected-id 0x036DB093
pld device virtex2 $_CHIPNAME.tap 1
pld create $_CHIPNAME.pld virtex2 -chain-position $_CHIPNAME.tap -no_jstart
set XC7_JSHUTDOWN 0x0d
set XC7_JPROGRAM 0x0b

View File

@ -54,7 +54,7 @@ set _IRLEN [lindex $_XCU_DATA($CHIP) 1]
# the 4 top bits (28:31) are the die stepping/revisions. ignore it.
jtag newtap $_CHIPNAME tap -irlen $_IRLEN -ignore-version -expected-id $_EXPID
pld device virtex2 $_CHIPNAME.tap 1
pld create $_CHIPNAME.pld virtex2 -chain-position $_CHIPNAME.tap -no_jstart
set XCU_JSHUTDOWN 0x0d
set XCU_JPROGRAM 0x0b

View File

@ -28,4 +28,4 @@ jtag newtap $_CHIPNAME tap -irlen 10 \
-expected-id 0x025030dd -expected-id 0x024820dd \
-expected-id 0x025140dd
pld device intel $_CHIPNAME.tap arriaii
pld create $_CHIPNAME.pld intel -chain-position $_CHIPNAME.tap -family arriaii

View File

@ -32,4 +32,4 @@ jtag newtap $_CHIPNAME tap -irlen 10 \
-expected-id 0x027000dd -expected-id 0x027030dd \
-expected-id 0x027020dd
pld device intel $_CHIPNAME.tap cycloneiii
pld create $_CHIPNAME.pld intel -chain-position $_CHIPNAME.tap -family cycloneiii

View File

@ -38,4 +38,4 @@ jtag newtap $_CHIPNAME tap -irlen 10 \
-expected-id 0x028030dd -expected-id 0x028140dd \
-expected-id 0x028040dd
pld device intel $_CHIPNAME.tap cycloneiv
pld create $_CHIPNAME.pld intel -chain-position $_CHIPNAME.tap -family cycloneiv

View File

@ -44,4 +44,4 @@ jtag newtap $_CHIPNAME tap -irlen 10 \
-expected-id 0x02d110dd -expected-id 0x02d010dd \
-expected-id 0x02d120dd -expected-id 0x02d020dd
pld device intel $_CHIPNAME.tap cyclonev
pld create $_CHIPNAME.pld intel -chain-position $_CHIPNAME.tap -family cyclonev

View File

@ -20,4 +20,4 @@ jtag newtap $_CHIPNAME tap -irlen 5 -ignore-version \
-expected-id 0x00680A79 \
-expected-id 0x00684A79
pld device efinix $_CHIPNAME.tap
pld create $_CHIPNAME.pld efinix -chain-position $_CHIPNAME.tap

View File

@ -14,4 +14,4 @@ jtag newtap $_CHIPNAME tap -irlen 4 -ignore-version \
-expected-id 0x00240A79 \
-expected-id 0x00220A79
pld device efinix $_CHIPNAME.tap
pld create $_CHIPNAME.pld efinix -chain-position $_CHIPNAME.tap

View File

@ -13,4 +13,4 @@ if { [info exists CHIPNAME] } {
jtag newtap $_CHIPNAME tap -irlen 6 -ignore-version \
-expected-id 0x20000001
pld device gatemate $_CHIPNAME.tap
pld create $_CHIPNAME.pld gatemate -chain-position $_CHIPNAME.tap

View File

@ -26,4 +26,4 @@ jtag newtap $_CHIPNAME tap -irlen 8 -ignore-version \
-expected-id 0x1100181B \
-expected-id 0x0100481B
pld device gowin $_CHIPNAME.tap
pld create $_CHIPNAME.pld gowin -chain-position $_CHIPNAME.tap

View File

@ -15,4 +15,4 @@ if { [info exists CHIPNAME] } {
jtag newtap $_CHIPNAME tap -irlen 8 -irmask 0x83 -ircapture 0x1 \
-expected-id 0x310F1043 -expected-id 0x310F0043
pld device lattice $_CHIPNAME.tap
pld create $_CHIPNAME.pld lattice -chain-position $_CHIPNAME.tap

View File

@ -15,4 +15,4 @@ jtag newtap $_CHIPNAME tap -irlen 8 -irmask 0x83 -ircapture 0x1 \
-expected-id 0x010f4043
# -expected-id 0x01112043
pld device lattice $_CHIPNAME.tap
pld create $_CHIPNAME.pld lattice -chain-position $_CHIPNAME.tap

View File

@ -28,4 +28,4 @@ jtag newtap $_CHIPNAME tap -irlen 8 \
-expected-id 0x01271043 -expected-id 0x01272043 -expected-id 0x01274043 \
-expected-id 0x01273043 -expected-id 0x01275043
pld device lattice $_CHIPNAME.tap
pld create $_CHIPNAME.pld lattice -chain-position $_CHIPNAME.tap

View File

@ -19,4 +19,4 @@ jtag newtap $_CHIPNAME tap -irlen 8 \
-expected-id 0x01010043 -expected-id 0x01012043 \
-expected-id 0x01014043 -expected-id 0x01015043
pld device lattice $_CHIPNAME.tap
pld create $_CHIPNAME.pld lattice -chain-position $_CHIPNAME.tap

View File

@ -27,4 +27,4 @@ jtag newtap $_CHIPNAME tap -irlen 8 -irmask 0x83 -ircapture 0x1 \
-expected-id 0x41113043 -expected-id 0x81111043 -expected-id 0x81112043 \
-expected-id 0x81113043
pld device lattice $_CHIPNAME.tap
pld create $_CHIPNAME.pld lattice -chain-position $_CHIPNAME.tap

View File

@ -46,7 +46,7 @@ adapter speed 1000
${_TARGETNAME}0 configure -event reset-assert-post "cortex_a dbginit"
${_TARGETNAME}1 configure -event reset-assert-post "cortex_a dbginit"
pld device virtex2 zynq_pl.bs 1
pld create zynq_pl.pld virtex2 -chain-position zynq_pl.bs -no_jstart
set XC7_JSHUTDOWN 0x0d
set XC7_JPROGRAM 0x0b