svf: initial SVF player + svf_play command

New modules/svf/ plays the single-device SVF subset over the bscan_*
primitives: SIR/SDR with masked TDO compare, RUNTEST (TCK/SEC), STATE
(RESET/IDLE), ENDIR/ENDDR (IDLE only), HIR/HDR/TIR/TDR (length 0), TRST,
FREQUENCY. Exposed as `svf_play <file>`. It warms up the FTDI link
first — the MPSSE's first data read after open returns stale FIFO
content, normally hidden because jtag_scan runs before anything.

Also adds the bscan_tap_reset prototype. Validated on the live IGLOO2
M2GL010T: a hand-written IDCODE-check SVF passes (masked compare) and a
deliberately wrong one is caught at the mismatching bit. A generic
program dispatch off the prog tag, multi-device chains and non-IDLE end
states are still TODO.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 14:36:41 +02:00
parent 37efccaf50
commit c77d86efd0
7 changed files with 541 additions and 0 deletions

View File

@@ -40,6 +40,7 @@
#include "fpga/fpga.h"
#include "probes/probes.h"
#include "bscan/bscan.h"
#include "svf/svf.h"
#include "spi_flash/spi_flash.h"
#include "env.h"
@@ -3512,6 +3513,35 @@ static int cmd_flash_verify(script_ctx *ctx, char *line)
return JTAG_CORE_NO_ERROR;
}
static void svf_log_cb(void *user, int is_error, const char *msg)
{
script_ctx *ctx = (script_ctx *)user;
ctx->script_printf(ctx, is_error ? MSG_ERROR : MSG_INFO_0, "%s\n", msg);
}
const char *cmd_svf_play_help[] = {
"<file>(str)",
"Play an SVF file over the open probe (single-device chain).",
"Runs SIR/SDR/RUNTEST/STATE with masked TDO compare — the universal",
"way to program a part from a vendor-exported SVF (Lattice, Microsemi,",
"Xilinx fabric, CPLDs). A TDO mismatch stops play and is reported.",
""
};
static int cmd_svf_play(script_ctx *ctx, char *line)
{
jtag_core *jc;
char path[MAX_PATH + 1];
jc = (jtag_core *)ctx->app_ctx;
if (get_param(ctx, line, 1, path) <= 0) {
ctx->script_printf(ctx, MSG_ERROR, "Usage: svf_play <file>\n");
return JTAG_CORE_BAD_PARAMETER;
}
if (svf_play_file(jc, path, svf_log_cb, ctx, NULL) < 0)
return JTAG_CORE_ACCESS_ERROR;
return JTAG_CORE_NO_ERROR;
}
cmd_list script_commands_list[] =
{
{"print", cmd_print, cmd_print_help},
@@ -3567,6 +3597,7 @@ cmd_list script_commands_list[] =
{"flash_erase", cmd_flash_erase, cmd_flash_erase_help},
{"flash_write", cmd_flash_write, cmd_flash_write_help},
{"flash_verify", cmd_flash_verify, cmd_flash_verify_help},
{"svf_play", cmd_svf_play, cmd_svf_play_help},
{0, 0}};
///////////////////////////////////////////////////////////////////////////////