#endif
#include "svf.h"
-
#include "jtag.h"
-#include "command.h"
-#include "log.h"
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
+#include "time_support.h"
-#include <sys/time.h>
-#include <time.h>
// SVF command
typedef enum
TRST,
}svf_command_t;
-const char *svf_command_name[14] =
+const char *svf_command_name[14] =
{
"ENDDR",
"ENDIR",
"ABSENT"
};
-char *svf_tap_state_name[16];
+typedef struct
+{
+ tap_state_t from;
+ tap_state_t to;
+ u32 num_of_moves;
+ tap_state_t paths[8];
+}svf_statemove_t;
+
+svf_statemove_t svf_statemoves[] =
+{
+ // from to num_of_moves, paths[8]
+// {TAP_RESET, TAP_RESET, 1, {TAP_RESET}},
+ {TAP_RESET, TAP_IDLE, 2, {TAP_RESET, TAP_IDLE}},
+ {TAP_RESET, TAP_DRPAUSE, 6, {TAP_RESET, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE}},
+ {TAP_RESET, TAP_IRPAUSE, 7, {TAP_RESET, TAP_IDLE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE}},
+
+// {TAP_IDLE, TAP_RESET, 4, {TAP_IDLE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}},
+ {TAP_IDLE, TAP_IDLE, 1, {TAP_IDLE}},
+ {TAP_IDLE, TAP_DRPAUSE, 5, {TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE}},
+ {TAP_IDLE, TAP_IRPAUSE, 6, {TAP_IDLE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE}},
+
+// {TAP_DRPAUSE, TAP_RESET, 6, {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}},
+ {TAP_DRPAUSE, TAP_IDLE, 4, {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE}},
+ {TAP_DRPAUSE, TAP_DRPAUSE, 7, {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE}},
+ {TAP_DRPAUSE, TAP_IRPAUSE, 8, {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE}},
+
+// {TAP_IRPAUSE, TAP_RESET, 6, {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}},
+ {TAP_IRPAUSE, TAP_IDLE, 4, {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_IDLE}},
+ {TAP_IRPAUSE, TAP_DRPAUSE, 7, {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE}},
+ {TAP_IRPAUSE, TAP_IRPAUSE, 8, {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE}}
+};
+
+char *svf_tap_state_name[TAP_NUM_STATES];
#define XXR_TDI (1 << 0)
#define XXR_TDO (1 << 1)
}svf_para_t;
svf_para_t svf_para;
-const svf_para_t svf_para_init =
+const svf_para_t svf_para_init =
{
// frequency, ir_end_state, dr_end_state, runtest_run_state, runtest_end_state, trst_mode
0, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TRST_Z,
#define SVF_MAX_BUFFER_SIZE_TO_COMMIT (4 * 1024)
static u8 *svf_tdi_buffer = NULL, *svf_tdo_buffer = NULL, *svf_mask_buffer = NULL;
static int svf_buffer_index = 0, svf_buffer_size = 0;
+static int svf_quiet = 0;
int svf_register_commands(struct command_context_s *cmd_ctx)
}
}
+unsigned svf_get_mask_u32(int bitlen)
+{
+ u32 bitmask;
+
+ if (bitlen < 0)
+ {
+ bitmask = 0;
+ }
+ else if (bitlen >= 32)
+ {
+ bitmask = 0xFFFFFFFF;
+ }
+ else
+ {
+ bitmask = (1 << bitlen) - 1;
+ }
+
+ return bitmask;
+}
+
+static const char* tap_state_svf_name(tap_state_t state)
+{
+ const char* ret;
+
+ switch( state )
+ {
+ case TAP_RESET: ret = "RESET"; break;
+ case TAP_IDLE: ret = "IDLE"; break;
+ case TAP_DRSELECT: ret = "DRSELECT"; break;
+ case TAP_DRCAPTURE: ret = "DRCAPTURE"; break;
+ case TAP_DRSHIFT: ret = "DRSHIFT"; break;
+ case TAP_DREXIT1: ret = "DREXIT1"; break;
+ case TAP_DRPAUSE: ret = "DRPAUSE"; break;
+ case TAP_DREXIT2: ret = "DREXIT2"; break;
+ case TAP_DRUPDATE: ret = "DRUPDATE"; break;
+ case TAP_IRSELECT: ret = "IRSELECT"; break;
+ case TAP_IRCAPTURE: ret = "IRCAPTURE"; break;
+ case TAP_IRSHIFT: ret = "IRSHIFT"; break;
+ case TAP_IREXIT1: ret = "IREXIT1"; break;
+ case TAP_IRPAUSE: ret = "IRPAUSE"; break;
+ case TAP_IREXIT2: ret = "IREXIT2"; break;
+ case TAP_IRUPDATE: ret = "IRUPDATE"; break;
+ default: ret = "???"; break;
+ }
+
+ return ret;
+}
+
+static int svf_add_statemove(tap_state_t state_to)
+{
+ tap_state_t state_from = cmd_queue_cur_state;
+ u8 index;
+
+ for (index = 0; index < dimof(svf_statemoves); index++)
+ {
+ if ((svf_statemoves[index].from == state_from)
+ && (svf_statemoves[index].to == state_to))
+ {
+ if (TAP_RESET == state_from)
+ {
+ jtag_add_tlr();
+ if (svf_statemoves[index].num_of_moves > 1)
+ {
+ jtag_add_pathmove(svf_statemoves[index].num_of_moves - 1, svf_statemoves[index].paths + 1);
+ }
+ }
+ else
+ {
+ if (svf_statemoves[index].num_of_moves > 0)
+ {
+ jtag_add_pathmove(svf_statemoves[index].num_of_moves, svf_statemoves[index].paths);
+ }
+ }
+ return ERROR_OK;
+ }
+ }
+ LOG_ERROR("can not move to %s", tap_state_svf_name(state_to));
+ return ERROR_FAIL;
+}
+
static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
+#define SVF_NUM_OF_OPTIONS 1
int command_num = 0, i;
int ret = ERROR_OK;
+ long long time_ago;
- if (argc < 1)
+ if ((argc < 1) || (argc > (1 + SVF_NUM_OF_OPTIONS)))
{
- command_print(cmd_ctx, "usage: svf <file>");
+ command_print(cmd_ctx, "usage: svf <file> [quiet]");
return ERROR_FAIL;
}
+ // parse variant
+ svf_quiet = 0;
+ for (i = 1; i < argc; i++)
+ {
+ if (!strcmp(args[i], "quiet"))
+ {
+ svf_quiet = 1;
+ }
+ else
+ {
+ LOG_ERROR("unknown variant for svf: %s", args[i]);
+
+ // no need to free anything now
+ return ERROR_FAIL;
+ }
+ }
+
if ((svf_fd = open(args[0], O_RDONLY)) < 0)
{
command_print(cmd_ctx, "file \"%s\" not found", args[0]);
+
+ // no need to free anything now
return ERROR_FAIL;
}
LOG_USER("svf processing file: \"%s\"", args[0]);
+ // get time
+ time_ago = timeval_ms();
+
// init
svf_line_number = 1;
svf_command_buffer_size = 0;
svf_buffer_size = 2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT;
memcpy(&svf_para, &svf_para_init, sizeof(svf_para));
- for (i = 0; i < dimof(svf_tap_state_name); i++)
+ for (i = 0; i < (int)dimof(svf_tap_state_name); i++)
{
- svf_tap_state_name[i] = (char *)jtag_state_name(i);
+ svf_tap_state_name[i] = (char *)tap_state_svf_name(i);
}
+
// TAP_RESET
jtag_add_tlr();
ret = ERROR_FAIL;
}
+ // print time
+ command_print(cmd_ctx, "%lld ms used", timeval_ms() - time_ago);
+
free_all:
close(svf_fd);
static int svf_tap_state_is_valid(tap_state_t state)
{
- return ((state >= 0) && (state < sizeof(svf_tap_state_name)));
+ return state >= 0 && state < TAP_NUM_STATES;
}
static int svf_find_string_in_array(char *str, char **strs, int num_of_element)
static int svf_check_tdo(void)
{
- int i, j, byte_len, index;
+ int i, len, index;
for (i = 0; i < svf_check_tdo_para_index; i++)
{
- if (svf_check_tdo_para[i].enabled)
+ index = svf_check_tdo_para[i].buffer_offset;
+ len = svf_check_tdo_para[i].bit_len;
+ if ((svf_check_tdo_para[i].enabled)
+ && buf_cmp_mask(&svf_tdi_buffer[index], &svf_tdo_buffer[index], &svf_mask_buffer[index], len))
{
- byte_len = (svf_check_tdo_para[i].bit_len + 7) >> 3;
- index = svf_check_tdo_para[i].buffer_offset;
- for (j = 0; j < byte_len; j++)
- {
- if ((svf_tdi_buffer[index + j] & svf_mask_buffer[index + j]) != svf_tdo_buffer[index + j])
- {
- LOG_ERROR("tdo check error at line %d, read = 0x%X, want = 0x%X, mask = 0x%X",
- svf_check_tdo_para[i].line_num,
- (*(int*)(svf_tdi_buffer + index)) & ((1 << svf_check_tdo_para[i].bit_len) - 1),
- (*(int*)(svf_tdo_buffer + index)) & ((1 << svf_check_tdo_para[i].bit_len) - 1),
- (*(int*)(svf_mask_buffer + index)) & ((1 << svf_check_tdo_para[i].bit_len) - 1));
- return ERROR_FAIL;
- }
- }
+ unsigned bitmask;
+ unsigned received, expected, tapmask;
+ bitmask = svf_get_mask_u32(svf_check_tdo_para[i].bit_len);
+
+ memcpy(&received, svf_tdi_buffer + index, sizeof(unsigned));
+ memcpy(&expected, svf_tdo_buffer + index, sizeof(unsigned));
+ memcpy(&tapmask, svf_mask_buffer + index, sizeof(unsigned));
+ LOG_ERROR("tdo check error at line %d",
+ svf_check_tdo_para[i].line_num);
+ LOG_ERROR("read = 0x%X, want = 0x%X, mask = 0x%X",
+ received & bitmask,
+ expected & bitmask,
+ tapmask & bitmask);
+ return ERROR_FAIL;
}
}
svf_check_tdo_para_index = 0;
return ERROR_OK;
}
-// not good to use this
-extern jtag_command_t** jtag_get_last_command_p(void);
-extern void* cmd_queue_alloc(size_t size);
-extern jtag_command_t **last_comand_pointer;
+static int svf_execute_tap(void)
+{
+ if (ERROR_OK != jtag_execute_queue())
+ {
+ return ERROR_FAIL;
+ }
+ else if (ERROR_OK != svf_check_tdo())
+ {
+ return ERROR_FAIL;
+ }
+
+ svf_buffer_index = 0;
+
+ return ERROR_OK;
+}
static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
{
// tmp variable
int i_tmp;
- // not good to use this
- jtag_command_t **last_cmd;
-
// for RUNTEST
int run_count;
float min_time, max_time;
// for STATE
tap_state_t *path = NULL, state;
- LOG_DEBUG("%s", cmd_str);
+ if (!svf_quiet)
+ {
+ LOG_USER("%s", svf_command_buffer);
+ }
if (ERROR_OK != svf_parse_cmd_string(cmd_str, strlen(cmd_str), argus, &num_of_argu))
{
LOG_ERROR("HZ not found in FREQUENCY command");
return ERROR_FAIL;
}
+ if (ERROR_OK != svf_execute_tap())
+ {
+ return ERROR_FAIL;
+ }
svf_para.frequency = atof(argus[1]);
// TODO: set jtag speed to
if (svf_para.frequency > 0)
xxr_para_tmp->data_mask = 0;
for (i = 2; i < num_of_argu; i += 2)
{
- if ((argus[i + 1][0] != '(') || (argus[i + 1][strlen(argus[i + 1]) - 1] != ')'))
+ if ((strlen(argus[i + 1]) < 3) || (argus[i + 1][0] != '(') || (argus[i + 1][strlen(argus[i + 1]) - 1] != ')'))
{
LOG_ERROR("data section error");
return ERROR_FAIL;
LOG_ERROR("fail to parse hex value");
return ERROR_FAIL;
}
- LOG_DEBUG("\t%s = 0x%X", argus[i], (**(int**)pbuffer_tmp) & ((1 << (xxr_para_tmp->len)) - 1));
+ LOG_DEBUG("\t%s = 0x%X", argus[i], (**(int**)pbuffer_tmp) & svf_get_mask_u32(xxr_para_tmp->len));
}
- // If a command changes the length of the last scan of the same type and the MASK parameter is absent,
+ // If a command changes the length of the last scan of the same type and the MASK parameter is absent,
// the mask pattern used is all cares
if (!(xxr_para_tmp->data_mask & XXR_MASK) && (i_tmp != xxr_para_tmp->len))
{
}
buf_set_ones(xxr_para_tmp->mask, xxr_para_tmp->len);
}
+ // If TDO is absent, no comparison is needed, set the mask to 0
+ if (!(xxr_para_tmp->data_mask & XXR_TDO))
+ {
+ if (NULL == xxr_para_tmp->tdo)
+ {
+ if (ERROR_OK != svf_adjust_array_length(&xxr_para_tmp->tdo, i_tmp, xxr_para_tmp->len))
+ {
+ LOG_ERROR("fail to adjust length of array");
+ return ERROR_FAIL;
+ }
+ }
+ if (NULL == xxr_para_tmp->mask)
+ {
+ if (ERROR_OK != svf_adjust_array_length(&xxr_para_tmp->mask, i_tmp, xxr_para_tmp->len))
+ {
+ LOG_ERROR("fail to adjust length of array");
+ return ERROR_FAIL;
+ }
+ }
+ memset(xxr_para_tmp->mask, 0, (xxr_para_tmp->len + 7) >> 3);
+ }
// do scan if necessary
if (SDR == command)
{
field.tap = tap;
field.num_bits = i;
field.out_value = &svf_tdi_buffer[svf_buffer_index];
- field.out_mask = NULL;
field.in_value = &svf_tdi_buffer[svf_buffer_index];
- field.in_check_value = NULL;
- field.in_check_mask = NULL;
- field.in_handler = NULL;
- field.in_handler_priv = NULL;
jtag_add_plain_dr_scan(1, &field, svf_para.dr_end_state);
svf_buffer_index += (i + 7) >> 3;
field.tap = tap;
field.num_bits = i;
field.out_value = &svf_tdi_buffer[svf_buffer_index];
- field.out_mask = NULL;
field.in_value = &svf_tdi_buffer[svf_buffer_index];
- field.in_check_value = NULL;
- field.in_check_mask = NULL;
- field.in_handler = NULL;
- field.in_handler_priv = NULL;
jtag_add_plain_ir_scan(1, &field, svf_para.ir_end_state);
svf_buffer_index += (i + 7) >> 3;
{
if (run_count > 0)
{
+ // run_state and end_state is checked to be stable state
// TODO: do runtest
+#if 1
+ // enter into run_state if necessary
+ if (cmd_queue_cur_state != svf_para.runtest_run_state)
+ {
+ svf_add_statemove(svf_para.runtest_run_state);
+ }
+
+ // call jtag_add_clocks
+ jtag_add_clocks(run_count);
+
+ // move to end_state if necessary
+ if (svf_para.runtest_end_state != svf_para.runtest_run_state)
+ {
+ svf_add_statemove(svf_para.runtest_end_state);
+ }
+#else
if (svf_para.runtest_run_state != TAP_IDLE)
{
// RUNTEST can only executed in TAP_IDLE
LOG_ERROR("cannot runtest in %s state", svf_tap_state_name[svf_para.runtest_run_state]);
return ERROR_FAIL;
}
+
jtag_add_runtest(run_count, svf_para.runtest_end_state);
+#endif
}
}
else
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
- for (i = 1; i < num_of_argu; i++)
+ num_of_argu--; // num of path
+ i_tmp = 1; // path is from patameter 1
+ for (i = 0; i < num_of_argu; i++)
{
- path[i - 1] = svf_find_string_in_array(argus[i], (char **)svf_tap_state_name, dimof(svf_tap_state_name));
- if (!svf_tap_state_is_valid(path[i - 1]))
+ path[i] = svf_find_string_in_array(argus[i_tmp++], (char **)svf_tap_state_name, dimof(svf_tap_state_name));
+ if (!svf_tap_state_is_valid(path[i]))
{
- LOG_ERROR("%s is not valid state", svf_tap_state_name[path[i - 1]]);
+ LOG_ERROR("%s is not valid state", svf_tap_state_name[path[i]]);
return ERROR_FAIL;
}
- if (TAP_RESET == path[i - 1])
+ if (TAP_RESET == path[i])
{
- LOG_ERROR("TAP_RESET is not allowed in pathmove");
- return ERROR_FAIL;
+ if (i > 0)
+ {
+ jtag_add_pathmove(i, path);
+ }
+ jtag_add_tlr();
+ num_of_argu -= i + 1;
+ i = -1;
}
}
- if (svf_tap_state_is_stable(path[num_of_argu - 1]))
- {
- // last state MUST be stable state
- // TODO: call path_move
- jtag_add_pathmove(num_of_argu - 1, path);
- LOG_DEBUG("\tmove to %s by path_move", svf_tap_state_name[path[num_of_argu - 1]]);
- }
- else
+ if (num_of_argu > 0)
{
- LOG_ERROR("%s is not valid state", svf_tap_state_name[path[num_of_argu - 1]]);
- return ERROR_FAIL;
+ // execute last path if necessary
+ if (svf_tap_state_is_stable(path[num_of_argu - 1]))
+ {
+ // last state MUST be stable state
+ // TODO: call path_move
+ jtag_add_pathmove(num_of_argu, path);
+ LOG_DEBUG("\tmove to %s by path_move", svf_tap_state_name[path[num_of_argu - 1]]);
+ }
+ else
+ {
+ LOG_ERROR("%s is not valid state", svf_tap_state_name[path[num_of_argu - 1]]);
+ return ERROR_FAIL;
+ }
}
+ // no need to keep this memory, in jtag_add_pathmove, path will be duplicated
if (NULL != path)
{
free(path);
if (svf_tap_state_is_stable(state))
{
// TODO: move to state
- last_cmd = jtag_get_last_command_p();
- *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
- last_comand_pointer = &((*last_cmd)->next);
- (*last_cmd)->next = NULL;
- (*last_cmd)->type = JTAG_STATEMOVE;
- (*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
- (*last_cmd)->cmd.statemove->end_state = state;
-
- LOG_DEBUG("\tmove to %s by state_move", svf_tap_state_name[state]);
+ svf_add_statemove(state);
+
+ LOG_DEBUG("\tmove to %s by svf_add_statemove", svf_tap_state_name[state]);
}
else
{
}
if (svf_para.trst_mode != TRST_ABSENT)
{
+ if (ERROR_OK != svf_execute_tap())
+ {
+ return ERROR_FAIL;
+ }
i_tmp = svf_find_string_in_array(argus[1], (char **)svf_trst_mode_name, dimof(svf_trst_mode_name));
switch (i_tmp)
{
case TRST_ON:
jtag_add_reset(1, 0);
break;
- case TRST_OFF:
- jtag_add_reset(1, 1);
- break;
case TRST_Z:
+ case TRST_OFF:
+ jtag_add_reset(0, 0);
break;
case TRST_ABSENT:
break;
(((command != STATE) && (command != RUNTEST)) || \
((command == STATE) && (num_of_argu == 2))))
{
- // there is data to be executed
- if (ERROR_OK != jtag_execute_queue())
+ if (ERROR_OK != svf_execute_tap())
{
return ERROR_FAIL;
}
+
// output debug info
if ((SIR == command) || (SDR == command))
{
- LOG_DEBUG("\tTDO read = 0x%X", (*(int*)svf_tdi_buffer) & ((1 << (svf_check_tdo_para[0].bit_len)) - 1));
- }
- if (ERROR_OK != svf_check_tdo())
- {
- return ERROR_FAIL;
+ int read_value;
+ memcpy(&read_value, svf_tdi_buffer, sizeof(int));
+ // in debug mode, data is from index 0
+ int read_mask = svf_get_mask_u32(svf_check_tdo_para[0].bit_len);
+ LOG_DEBUG("\tTDO read = 0x%X", read_value & read_mask);
}
-
- svf_buffer_index = 0;
}
}
else
(((command != STATE) && (command != RUNTEST)) || \
((command == STATE) && (num_of_argu == 2))))
{
- if (ERROR_OK != jtag_execute_queue())
- {
- return ERROR_FAIL;
- }
- else if (ERROR_OK != svf_check_tdo())
- {
- return ERROR_FAIL;
- }
-
- svf_buffer_index = 0;
+ return svf_execute_tap();
}
}