From 7d7c3d6e4095037fefb4897988ca2035c747e09a Mon Sep 17 00:00:00 2001 From: Kolja Waschk Date: Tue, 6 Nov 2007 18:58:07 +0000 Subject: [PATCH] [ 1074347 ] SVF Player (4 patches: jtag-svf, -inc1, -goto_state, -vec-hexa) git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@691 b68d4a1b-bc3d-0410-92ed-d4ac073336b7 --- jtag/src/Makefile.am | 7 +- jtag/src/cmd/Makefile.am | 3 +- jtag/src/cmd/cmd.c | 2 + jtag/src/cmd/svf.c | 91 +++ jtag/src/svf/Makefile.am | 38 ++ jtag/src/svf/svf.c | 1154 ++++++++++++++++++++++++++++++++++++++ jtag/src/svf/svf.h | 73 +++ jtag/src/svf/svf_bison.y | 442 +++++++++++++++ jtag/src/svf/svf_flex.l | 260 +++++++++ jtag/src/tap/chain.c | 27 +- jtag/src/tap/tap.c | 4 +- 11 files changed, 2090 insertions(+), 11 deletions(-) create mode 100644 jtag/src/cmd/svf.c create mode 100644 jtag/src/svf/Makefile.am create mode 100644 jtag/src/svf/svf.c create mode 100644 jtag/src/svf/svf.h create mode 100644 jtag/src/svf/svf_bison.y create mode 100644 jtag/src/svf/svf_flex.l diff --git a/jtag/src/Makefile.am b/jtag/src/Makefile.am index 436303b6..66691cf0 100644 --- a/jtag/src/Makefile.am +++ b/jtag/src/Makefile.am @@ -28,7 +28,8 @@ SUBDIRS = \ tap \ part \ bus \ - cmd + cmd \ + svf bin_PROGRAMS = \ jtag \ @@ -50,7 +51,8 @@ jtag_DEPENDENCIES = \ tap/libtap.a \ part/libpart.a \ bus/libbus.a \ - cmd/libcmd.a + cmd/libcmd.a \ + svf/libsvf.a jtag_LDADD = \ -Ltap -ltap \ @@ -60,6 +62,7 @@ jtag_LDADD = \ -Lcmd -lcmd \ -L../libbrux -lbrux \ -Lbus -lbus \ + -Lsvf -lsvf \ @LIBINTL@ localedir = $(datadir)/locale diff --git a/jtag/src/cmd/Makefile.am b/jtag/src/cmd/Makefile.am index a26c733b..05ec267b 100644 --- a/jtag/src/cmd/Makefile.am +++ b/jtag/src/cmd/Makefile.am @@ -51,6 +51,7 @@ libcmd_a_SOURCES = \ eraseflash.c \ script.c \ include.c \ - cmd.c + cmd.c \ + svf.c INCLUDES = -DJTAG_DATA_DIR=\"$(pkgdatadir)\" diff --git a/jtag/src/cmd/cmd.c b/jtag/src/cmd/cmd.c index dae8660f..61f36b70 100644 --- a/jtag/src/cmd/cmd.c +++ b/jtag/src/cmd/cmd.c @@ -60,6 +60,7 @@ extern cmd_t cmd_flashmem; extern cmd_t cmd_eraseflash; extern cmd_t cmd_script; extern cmd_t cmd_include; +extern cmd_t cmd_svf; const cmd_t *cmds[] = { &cmd_quit, @@ -91,6 +92,7 @@ const cmd_t *cmds[] = { &cmd_eraseflash, &cmd_script, &cmd_include, + &cmd_svf, NULL /* last must be NULL */ }; diff --git a/jtag/src/cmd/svf.c b/jtag/src/cmd/svf.c new file mode 100644 index 00000000..a058303b --- /dev/null +++ b/jtag/src/cmd/svf.c @@ -0,0 +1,91 @@ +/* + * $Id$ + * + * Copyright (C) 2004, Arnim Laeuger + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by Arnim Laeuger , 2004. + * + */ + + +#include "sysdep.h" + +#include +#include + +#include +#include + +static int +cmd_svf_run( char *params[] ) +{ + FILE *SVF_FILE; + int num_params, result = -1; + + num_params = cmd_params( params ); + if (num_params == 2 || num_params == 3) { + if ((SVF_FILE = fopen(params[1], "r")) != NULL) { + + if (num_params == 3) { + if (strcmp(params[2], "stop") == 0) { + svf_run(SVF_FILE, 1); + result = 1; + } + } else { + svf_run(SVF_FILE, 0); + result = 1; + } + + fclose(SVF_FILE); + } else { + printf( _("%s: cannot open file '%s' for reading\n"), "svf", params[1] ); + } + + } + + return result; +} + + +static void +cmd_svf_help( void ) +{ + printf( _( + "Usage: %s FILE\n" + "Usage: %s FILE stop\n" + "Execute svf commands from FILE.\n" + "Command execution stops upon TDO mismatch when 'stop' is specified.\n" + "\n" + "FILE file containing SVF commans\n" + ), "svf", "svf" ); +} + +cmd_t cmd_svf = { + "svf", + N_("execute svf commands from file"), + cmd_svf_help, + cmd_svf_run +}; + + +/* Emacs specific variables +;;; Local Variables: *** +;;; indent-tabs-mode:t *** +;;; tab-width:2 *** +;;; End: *** +*/ diff --git a/jtag/src/svf/Makefile.am b/jtag/src/svf/Makefile.am new file mode 100644 index 00000000..9d0ddc5f --- /dev/null +++ b/jtag/src/svf/Makefile.am @@ -0,0 +1,38 @@ +# +# $Id: Makefile.am,v 1.16 2003/09/14 20:04:24 telka Exp $ +# +# Copyright (C) 2002 ETC s.r.o. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# +# Written by Marcel Telka , 2002. +# + +include $(top_srcdir)/Makefile.rules + +noinst_LIBRARIES = libsvf.a + +libsvf_a_SOURCES = \ + svf_bison.y \ + svf_flex.l \ + svf.c + +AM_YFLAGS = -d + +CLEANFILES = \ + svf_bison.c \ + svf_bison.h \ + svf_flex.c diff --git a/jtag/src/svf/svf.c b/jtag/src/svf/svf.c new file mode 100644 index 00000000..4005e1d7 --- /dev/null +++ b/jtag/src/svf/svf.c @@ -0,0 +1,1154 @@ +/* + * $Id$ + * + * Copyright (C) 2004, Arnim Laeuger + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by Arnim Laeuger , 2004. + * + * See "Serial Vector Format Specification", Revision E, 1999 + * ASSET InterTech, Inc. + * http://www.asset-intertech.com/support/svf.pdf + * + */ + + +#include +#include +#include +#include +#include + +#include "sysdep.h" + +#include +#include +#include + +#include + +#include "svf.h" +#include "svf_bison.h" + +int yyparse(void); + + +struct sxr { + struct ths_params params; + int no_tdi; + int no_tdo; +}; + + +FILE *yyin, *yyout; + +int svf_stop_on_mismatch; + +static part_t *part; +static instruction *ir; +static data_register *dr; + + +static struct sxr sir_params, + sdr_params; + +static int endir, + enddr; + +static int runtest_run_state, + runtest_end_state; + +static int svf_trst_absent; +static int svf_state_executed; + +/* protocol issued warnings */ +static int issued_sir_tdo; +static int issued_runtest_maxtime; + + +/* + * svf_force_reset_state() + * + * Puts TAP controller into reset state by clocking 5 times with TMS = 1. + */ +static void +svf_force_reset_state(void) +{ + int i; + for (i = 1; i <= 5; i++) + chain_clock(chain, 1, 0); + tap_state_reset(chain); +} + + +/* + * svf_goto_state(state) + * + * Moves from any TAP state to the specified state. + * The state traversal is done according to the SVF specification. + * See STATE of the Serial Vector Format Specification + * + * Encoding of state is according to the jtag suite's defines. + * + * Parameter: + * state : new TAP controller state + */ +static void +svf_goto_state(int new_state) +{ + int current_state; + + current_state = tap_state(chain); + + /* handle unknown state */ + if (new_state == Unknown_State) + new_state = Test_Logic_Reset; + + /* abort if new_state already reached */ + if (current_state == new_state) + return; + + switch (current_state) { + case Test_Logic_Reset: + chain_clock(chain, 0, 0); + break; + + case Run_Test_Idle: + chain_clock(chain, 1, 0); + break; + + case Select_DR_Scan: + case Select_IR_Scan: + if (new_state == Test_Logic_Reset || + new_state == Run_Test_Idle || + (current_state & TAPSTAT_DR && new_state & TAPSTAT_IR) || + (current_state & TAPSTAT_IR && new_state & TAPSTAT_DR)) + /* progress in select-idle/reset loop */ + chain_clock(chain, 1, 0); + else + /* enter DR/IR branch */ + chain_clock(chain, 0, 0); + break; + + case Capture_DR: + if (new_state == Shift_DR) + /* enter Shift_DR state */ + chain_clock(chain, 0, 0); + else + /* bypass Shift_DR */ + chain_clock(chain, 1, 0); + break; + + case Capture_IR: + if (new_state == Shift_IR) + /* enter Shift_IR state */ + chain_clock(chain, 0, 0); + else + /* bypass Shift_IR */ + chain_clock(chain, 1, 0); + break; + + case Shift_DR: + case Shift_IR: + /* progress to Exit1_DR/IR */ + chain_clock(chain, 1, 0); + break; + + case Exit1_DR: + if (new_state == Pause_DR) + /* enter Pause_DR state */ + chain_clock(chain, 0, 0); + else + /* bypass Pause_DR */ + chain_clock(chain, 1, 0); + break; + + case Exit1_IR: + if (new_state == Pause_IR) + /* enter Pause_IR state */ + chain_clock(chain, 0, 0); + else + /* bypass Pause_IR */ + chain_clock(chain, 1, 0); + break; + + case Pause_DR: + case Pause_IR: + /* progress to Exit2_DR/IR */ + chain_clock(chain, 1, 0); + break; + + case Exit2_DR: + if (new_state == Shift_DR) + /* enter Shift_DR state */ + chain_clock(chain, 0, 0); + else + /* progress to Update_DR */ + chain_clock(chain, 1, 0); + break; + + case Exit2_IR: + if (new_state == Shift_IR) + /* enter Shift_IR state */ + chain_clock(chain, 0, 0); + else + /* progress to Update_IR */ + chain_clock(chain, 1, 0); + break; + + case Update_DR: + case Update_IR: + if (new_state == Run_Test_Idle) + /* enter Run_Test_Idle */ + chain_clock(chain, 0, 0); + else + /* progress to Select_DR/IR */ + chain_clock(chain, 1, 0); + break; + + default: + svf_force_reset_state(); + break; + } + + /* continue state changes */ + svf_goto_state(new_state); +} + + +/* + * svf_map_state(state) + * + * Maps the state encoding of the SVF parser to the + * state encoding of the jtag suite. + * + * Parameter: + * state : state encoded by/for SVF parser + * + * Return value: + * state encoded for jtag tools + */ +static int +svf_map_state(int state) +{ + int jtag_state; + + switch (state) { + case RESET: + jtag_state = Test_Logic_Reset; + break; + case IDLE: + jtag_state = Run_Test_Idle; + break; + case DRSELECT: + jtag_state = Select_DR_Scan; + break; + case DRCAPTURE: + jtag_state = Capture_DR; + break; + case DRSHIFT: + jtag_state = Shift_DR; + break; + case DREXIT1: + jtag_state = Exit1_DR; + break; + case DRPAUSE: + jtag_state = Pause_DR; + break; + case DREXIT2: + jtag_state = Exit2_DR; + break; + case DRUPDATE: + jtag_state = Update_DR; + break; + + case IRSELECT: + jtag_state = Select_IR_Scan; + break; + case IRCAPTURE: + jtag_state = Capture_IR; + break; + case IRSHIFT: + jtag_state = Shift_IR; + break; + case IREXIT1: + jtag_state = Exit1_IR; + break; + case IRPAUSE: + jtag_state = Pause_IR; + break; + case IREXIT2: + jtag_state = Exit2_IR; + break; + case IRUPDATE: + jtag_state = Update_IR; + break; + + default: + jtag_state = Unknown_State; + break; + } + + return(jtag_state); +} + + +/* + * svf_hex2dec(nibble) + * + * Converts a hexadecimal nibble (4 bits) to its decimal value. + * + * Parameter: + * nibble : hexadecimal character + * + * Return value: + * decimal value of nibble or 0 if nibble is not a hexadecimal character + */ +static int +svf_hex2dec(char nibble) +{ + int lower; + + if (nibble >= '0' && nibble <= '9') + return((int)(nibble - '0')); + + lower = tolower((int)nibble); + if (lower >= 'a' && lower <= 'f') + return(lower - (int)'a' + 10); + + return(0); +} + + +/* + * svf_build_bit_string(hex_string, len) + * + * Converts the hexadecimal string hex_string into a string of single bits + * with len elements (bits). + * If hex_string contains less nibbles than fit into len bits, the resulting + * bit string is padded with 0 bits. + * + * Note: + * The memory for the resulting bit string is calloc'ed and must be + * free'd when the bit string is not used anymore. + * + * Example: + * hex string : 1a + * len : 16 + * bit string : 0000000000011010 + * + * Parameter: + * hex_string : hex string to be converted + * len : number of bits in resulting bit string + * + * Return value: + * pointer to new bit string + * NULL upon error + */ +static char * +svf_build_bit_string(char *hex_string, int len) +{ + char *bit_string, *bit_string_pos; + int nibble; + char *hex_string_pos; + int hex_string_idx; + + if (!(bit_string = (char *)calloc(len + 1, sizeof(char)))) { + printf( _("out of memory") ); + return(NULL); + } + + /* copy reduced hexadecimal string to full bit string */ + hex_string_idx = strlen(hex_string); + hex_string_pos = &(hex_string[hex_string_idx]); + nibble = 3; + bit_string_pos = &(bit_string[len]); + do { + bit_string_pos--; + if (nibble == 3) { + nibble = 0; + hex_string_pos--; + hex_string_idx--; + } else + nibble++; + + *bit_string_pos = svf_hex2dec(hex_string_idx >= 0 ? *hex_string_pos : '0') & (1 << nibble) ? '1' : '0'; + } while (bit_string_pos != bit_string); + + bit_string[len] = '\0'; + + return(bit_string); +} + + +/* + * svf_copy_hex_to_register(hex_string, reg, len) + * + * Copies the contents of the hexadecimal string hex_string into the given + * tap register. + * + * Parameter: + * hex_string : hex string to be entered in reg + * reg : tap register to hold the converted hex string + * + * Return value: + * 1 : all ok + * 0 : error occured + */ +static int +svf_copy_hex_to_register(char *hex_string, tap_register *reg) +{ + char *bit_string; + + if (!(bit_string = svf_build_bit_string(hex_string, reg->len))) + return(0); + + register_init(reg, bit_string); + + /* free memory as we do not need the intermediate bit_string anymore */ + free(bit_string); + + return(1); +} + + +/* + * svf_compare_tdo(tdo, mask, reg) + * + * Compares the captured device output in tap register reg with the expected + * hex_string tdo (specified in SVF command SDR/SDI. + * + * Comparison honours the "care" bits in mask ('1') while matching the contents + * of reg with tdo. + * + * Parameter: + * tdo : reference hex string + * mask : hex string for masking tdo + * reg : hex string to be compared vs. tdo + * + * Return value: + * 1 : tdo matches reg at all positions where mask is '1' + * 0 : tdo and reg do not match or error occured + */ +static int +svf_compare_tdo(char *tdo, char *mask, tap_register *reg) +{ + char *tdo_bit, *mask_bit; + int pos, mismatch, result = 1; + + if (!(tdo_bit = svf_build_bit_string(tdo, reg->len))) + return(0); + if (!(mask_bit = svf_build_bit_string(mask, reg->len))) { + free(tdo_bit); + return(0); + } + + /* retrieve string representation */ + register_get_string(reg); + + mismatch = -1; + for (pos = 0; pos < reg->len; pos++) + if ((svf_hex2dec(tdo_bit[pos]) ^ reg->string[pos]) & svf_hex2dec(mask_bit[pos])) + mismatch = pos; + + if (mismatch >= 0) { + printf( _("Error %s: mismatch for TDO\n"), "svf"); + printf( " TDO: %s\n", tdo_bit); + printf( " MASK: %s\n", mask_bit); + printf( " Read: %s\n", reg->string); + if (svf_stop_on_mismatch) + result = 0; + } + + free(mask_bit); + free(tdo_bit); + + return(result); +} + + +/* + * svf_remember_param(rem, new) + * + * Assigns the contents of the string new to the string rem. + * By doing so, the responsability to free the memory occupied by new + * is transferred to the code that handles *rem. + * Nothing happens when new is NULL. In this case the current value of + * rem has to be "remembered". + * + * Parameter: + * rem : hex string pointer pointing to the "remembered" string + * new : hex string that has to be rememberd + * memory of the string is free'd + */ +static void +svf_remember_param(char **rem, char *new) +{ + if (new) { + if (*rem) + free(*rem); + + *rem = new; + } +} + + +/* + * svf_all_care(string, number) + * + * Allocates a hex string of given length (number gives number of bits) + * and sets it to all 'F'. + * The allocated memory of the string has to be free'd by the caller. + * + * Parameter: + * string : is updated with the pointer to the allocated hex string + * number : number of required bits + * + * Return value: + * 1 : all ok + * 0 : error occured + */ +static int +svf_all_care(char **string, double number) +{ + char *ptr; + int num, result; + + result = 1; + + num = (int)number; + num = num % 4 == 0 ? num / 4 : num / 4 + 1; + + /* build string with all cares */ + if (!(ptr = (char *)calloc(num + 1, sizeof(char)))) { + printf( _("out of memory") ); + return(0); + } + memset(ptr, 'F', num); + ptr[num] = '\0'; + + svf_remember_param(string, ptr); + /* responsability for free'ing ptr is now at the code that + operates on *string */ + + return(result); +} + + +/* + * svf_add_time(start_time, add_secs, result_time) + * + * Adds the given number of seconds to start_time. The reslt is returned + * in result_time. + * start_time and result_time are of type timeval which makes it necessary + * to have a dedicated function for adding a time period to start_time. + * Fractions of add_sec are converted to microseconds and are added to + * start_time accordingly. + * + * Parameter: + * start_time : base time + * add_secs : time to be added to start_time + * floating point value with 1.0 = 1 sec + */ +static void +svf_add_time(struct timeval *start_time, double add_secs, + struct timeval *result_time) +{ + result_time->tv_sec = start_time->tv_sec + (long)floor(add_secs); + result_time->tv_usec = start_time->tv_usec + + (long)((add_secs - floor(add_secs)) * 1000000.0); + + if (result_time->tv_usec > 1000000) { + result_time->tv_usec -= 1000000; + result_time->tv_sec += 1; + } +} + + +/* + * svf_is_later(check, ref) + * + * Compares time check against ref. + * + * Return value: + * 1 : check is later in time than ref + * 0 : otherwise + */ +static int +svf_is_later(struct timeval *check, struct timeval *ref) +{ + int later = 0; + + if (check->tv_sec <= ref->tv_sec) { + if (check->tv_sec == ref->tv_sec) + if (check->tv_usec > ref->tv_usec) + later = 1; + } else + later = 1; + + return(later); +} + + +/* + * svf_is_later_than_now(check) + * + * Compares time check against the current time (aka now). + * + * Return value: + * 1 : check is later than now + * 0 : otherwise + */ +static int +svf_is_later_than_now(struct timeval *check) +{ + struct timeval now; + struct timezone tz = {0, 0}; + + gettimeofday(&now, &tz); + + return(svf_is_later(check, &now)); +} + + +/* *************************************************************************** + * svf_endxr(ir_dr, state) + * + * Register end states for shifting IR and DR. + * + * Parameter: + * ir_dr : selects ENDIR or ENDDR + * state : required end state (SVF parser encoding) + * ***************************************************************************/ +void +svf_endxr(enum generic_irdr_coding ir_dr, int state) +{ + switch (ir_dr) { + case generic_ir: + endir = svf_map_state(state); + break; + case generic_dr: + enddr = svf_map_state(state); + break; + } +} + + +/* *************************************************************************** + * svf_frequency(freq) + * + * Implements the FREQUENCY command. + * + * Parameter: + * freq : frequency in HZ + * ***************************************************************************/ +void +svf_frequency(double freq) +{ + frequency = (uint32_t)freq; +} + + +/* *************************************************************************** + * svf_hxr(ir_dr, params) + * + * Handles HIR, HDR. + * + * Note: + * Functionality not implemented. + * + * Parameter: + * ir_dr : selects HIR or HDR + * params : paramter set for TXR, HXR and SXR + * + * Return value: + * 1 : all ok + * 0 : error occured + * ***************************************************************************/ +int +svf_hxr(enum generic_irdr_coding ir_dr, struct ths_params *params) +{ + if (params->number != 0.0) + printf( _("Warning %s: command %s not implemented\n"), "svf", + ir_dr == generic_ir ? "HIR" : "HDR"); + + return(1); +} + + +/* *************************************************************************** + * svf_runtest(params) + * + * Implements the RUNTEST command. + * + * Parameter: + * params : paramter set for RUNTEST + * + * Return value: + * 1 : all ok + * 0 : error occured + * ***************************************************************************/ +int +svf_runtest(struct runtest *params) +{ + int run_count; + struct timeval start_time, min_endtime, max_endtime; + struct timezone tz = {0, 0}; + + /* check for restrictions */ + if (params->run_count > 0 && params->run_clk != TCK) { + printf( _("Error %s: only TCK is supported for RUNTEST.\n"), "svf"); + return(0); + } + if (params->max_time > 0.0 && params->max_time < params->min_time) { + printf( _("Error %s: maximum time must be larger or equal to minimum time.\n"), + "svf"); + return(0); + } + + + /* update default values for run_state and end_state */ + if (params->run_state != 0) { + runtest_run_state = svf_map_state(params->run_state); + + if (params->end_state == 0) + runtest_end_state = svf_map_state(params->run_state); + } + if (params->end_state != 0) + runtest_end_state = svf_map_state(params->end_state); + + run_count = (int)(params->run_count); + + svf_goto_state(runtest_run_state); + + /* init timing */ + if (params->max_time > 0.0) + if (!issued_runtest_maxtime) { + printf( _("Warning %s: maximum time for RUNTEST not guaranteed.\n"), "svf"); + printf( _(" This message is only displayed once.\n")); + issued_runtest_maxtime = 1; + } + gettimeofday(&start_time, &tz); + svf_add_time(&start_time, params->min_time, &min_endtime); + svf_add_time(&start_time, params->max_time, &max_endtime); + + while (run_count > 0 || svf_is_later_than_now(&min_endtime)) { + chain_clock(chain, 0, 0); + run_count--; + + if (svf_is_later(&max_endtime, &start_time)) + if (!svf_is_later_than_now(&max_endtime)) + break; + } + + svf_goto_state(runtest_end_state); + + return(1); +} + + +/* *************************************************************************** + * svf_state(path_states, stable_state) + * + * Implements the STATE command. + * + * Parameter: + * path_states : states to traverse before reaching stable_state + * (SVF parser encoding) + * stable_state : final stable state + * (SVF parser encoding) + * + * Return value: + * 1 : all ok + * 0 : error occured + * ***************************************************************************/ +int +svf_state(struct path_states *path_states, int stable_state) +{ + int i; + + svf_state_executed = 1; + + for (i = 0; i < path_states->num_states; i++) + svf_goto_state(svf_map_state(path_states->states[i])); + + if (stable_state) + svf_goto_state(svf_map_state(stable_state)); + + return(1); +} + + +/* *************************************************************************** + * svf_sxr(ir_dr, params) + * + * Implements the SIR and SDR commands. + * + * Parameter: + * ir_dr : selects SIR or SDR + * params : paramter set for TXR, HXR and SXR + * + * Return value: + * 1 : all ok + * 0 : error occured + * ***************************************************************************/ +int +svf_sxr(enum generic_irdr_coding ir_dr, struct ths_params *params) +{ + struct sxr *sxr_params; + int len, result = 1; + + sxr_params = ir_dr == generic_ir ? &sir_params : &sdr_params; + + /* remember parameters */ + svf_remember_param(&sxr_params->params.tdi, params->tdi); + + sxr_params->params.tdo = params->tdo; /* tdo is not "remembered" */ + + svf_remember_param(&sxr_params->params.mask, params->mask); + + svf_remember_param(&sxr_params->params.smask, params->smask); + + + /* handle length change for MASK and SMASK */ + if (sxr_params->params.number != params->number) { + sxr_params->no_tdi = 1; + sxr_params->no_tdo = 1; + + if (!params->mask) + if (!svf_all_care(&sxr_params->params.mask, params->number)) + result = 0; + if (!params->smask) + if (!svf_all_care(&sxr_params->params.smask, params->number)) + result = 0; + } + + sxr_params->params.number = params->number; + + /* check consistency */ + if (sxr_params->no_tdi) { + if (!params->tdi) { + printf( _("Error %s: first %s command after length change must have a TDI value.\n"), "svf", + ir_dr == generic_ir ? "SIR" : "SDR"); + result = 0; + } + sxr_params->no_tdi = 0; + } + + /* result of consistency check */ + if (!result) + return(0); + + /* take over responsability for free'ing parameter strings */ + params->tdi = NULL; + params->mask = NULL; + params->smask = NULL; + + + /* + * handle tap registers + */ + len = (int)sxr_params->params.number; + switch (ir_dr) { + case generic_ir: + /* is SIR large enough? */ + if (ir->value->len != len) { + printf( _("Error %s: SIR command length inconsistent.\n"), + "svf"); + return(0); + } + break; + + case generic_dr: + /* check data register SDR */ + if (dr->in->len != len) { + /* length does not match, so install proper registers */ + register_free(dr->in); + dr->in = NULL; + register_free(dr->out); + dr->out = NULL; + + if (!(dr->in = register_alloc(len))) { + printf( _("out of memory") ); + return(0); + } + if (!(dr->out = register_alloc(len))) { + printf( _("out of memory") ); + return(0); + } + } + break; + + } + + /* fill register with value of TDI parameter */ + if (!svf_copy_hex_to_register(sxr_params->params.tdi, + ir_dr == generic_ir ? ir->value : + dr->in)) + return(0); + + + /* shift selected instruction/register */ + switch (ir_dr) { + case generic_ir: + svf_goto_state(Shift_IR); + chain_shift_instructions_mode(chain, 0, EXITMODE_EXIT1); + svf_goto_state(endir); + + if (sxr_params->params.tdo) + if (!issued_sir_tdo) { + printf( _("Warning %s: checking of TDO not supported for SIR.\n"), "svf"); + printf( _(" This message is only displayed once.\n")); + issued_sir_tdo = 1; + } + break; + + case generic_dr: + svf_goto_state(Shift_DR); + chain_shift_data_registers_mode(chain, 1, 0, EXITMODE_EXIT1); + svf_goto_state(enddr); + + if (sxr_params->params.tdo) + result = svf_compare_tdo(sxr_params->params.tdo, sxr_params->params.mask, dr->out); + break; + } + + return(result); +} + + + +/* *************************************************************************** + * svf_trst(int trst_mode) + * + * Sets TRST pin according to trst_mode. + * TRST modes are encoded via defines in svf.h. + * + * Note: + * The modes Z and ABSENT are not supported. + * + * Parameter: + * trst_mode : selected mode for TRST + * + * Return value: + * 1 : all ok + * 0 : error occured + * ***************************************************************************/ +int +svf_trst(int trst_mode) +{ + int trst_cable = -1; + char *unimplemented_mode; + + if (svf_trst_absent) { + printf( _("Error %s: no further TRST command allowed after mode ABSENT\n"), + "svf"); + return(0); + } + + switch (trst_mode) { + case ON: + trst_cable = 0; + break; + case OFF: + trst_cable = 1; + break; + case Z: + unimplemented_mode = "Z"; + break; + case ABSENT: + unimplemented_mode = "ABSENT"; + svf_trst_absent = 1; + + if (svf_state_executed) { + printf( _("Error %s: TRST ABSENT must not be issued after a STATE command\n"), + "svf"); + return(0); + } + if (sir_params.params.number > 0.0 || + sdr_params.params.number > 0.0) { + printf( _("Error %s: TRST ABSENT must not be issued after an SIR or SDR command\n"), + "svf"); + } + break; + default: + unimplemented_mode = "UNKNOWN"; + break; + } + + if (trst_cable < 0) + printf( _("Warning %s: unimplemented mode '%s' for TRST\n"), "svf", + unimplemented_mode); + else + cable_set_trst(chain->cable, trst_cable); + + return(1); +} + + +/* *************************************************************************** + * svf_txr(ir_dr, params) + * + * Handles TIR, TDR. + * + * Note: + * Functionality not implemented. + * + * Parameter: + * ir_dr : selects TIR or TDR + * params : paramter set for TXR, HXR and SXR + * + * Return value: + * 1 : all ok + * 0 : error occured + * ***************************************************************************/ +int +svf_txr(enum generic_irdr_coding ir_dr, struct ths_params *params) +{ + if (params->number != 0.0) + printf( _("Warning %s: command %s not implemented\n"), "svf", + ir_dr == generic_ir ? "TIR" : "TDR"); + + return(1); +} + + +/* *************************************************************************** + * svf_run(SVF_FILE, stop_on_mismatch) + * + * Main entry point for the 'svf' command. Calls the svf parser. + * + * Checks the jtag-environment (availability of SIR instruction and SDR + * register). Initializes all svf-global variables and performs clean-up + * afterwards. + * + * Parameter: + * SVF_FILE : file handle of SVF file + * stop_on_mismatch : 1 = stop upon tdo mismatch + * 0 = continue upon mismatch + * + * Return value: + * 1 : all ok + * 0 : error occured + * ***************************************************************************/ +void +svf_run(FILE *SVF_FILE, int stop_on_mismatch) +{ + const struct sxr sxr_default = { {0.0, NULL, NULL, NULL, NULL}, + 1, 1}; + + /* initialize + - part + - instruction register + - data register */ + if (chain == NULL) { + printf( _("Error %s: no JTAG chain available\n"), "svf"); + return; + } + if (chain->parts == NULL) { + printf( _("Error %s: chain without any parts\n"), "svf"); + return; + } + part = chain->parts->parts[chain->active_part]; + + /* setup register SDR if not already existing */ + if (!(dr = part_find_data_register(part, "SDR"))) { + char *register_cmd[] = {"register", + "SDR", + "32", + NULL}; + + if (cmd_run(register_cmd) < 1) + return; + + if (!(dr = part_find_data_register(part, "SDR"))) { + printf( _("Error %s: could not establish SDR register\n"), "svf"); + return; + } + } + + /* setup instruction SIR if not already existing */ + if (!(ir = part_find_instruction(part, "SIR"))) { + char *instruction_cmd[] = {"instruction", + "SIR", + "", + "SDR", + NULL}; + char *instruction_string; + int len, result; + + len = part->instruction_length; + if (len > 0) { + if ((instruction_string = (char *)calloc(len+1, sizeof(char))) != NULL) { + memset(instruction_string, '1', len); + instruction_string[len] = '\0'; + instruction_cmd[2] = instruction_string; + + result = cmd_run(instruction_cmd); + + free(instruction_string); + + if (result < 1) + return; + } + } + + if (!(ir = part_find_instruction(part, "SIR"))) { + printf( _("Error %s: could not establish SIR instruction\n"), "svf"); + return; + } + } + + /* initialize variables for new parser run */ + svf_stop_on_mismatch = stop_on_mismatch; + + sir_params = sdr_params = sxr_default; + + endir = enddr = Run_Test_Idle; + + runtest_run_state = runtest_end_state = Run_Test_Idle; + + svf_trst_absent = 0; + svf_state_executed = 0; + + /* set back flags for issued warnings */ + issued_sir_tdo = 0; + issued_runtest_maxtime = 0; + + + /* select SIR instruction */ + part_set_instruction(part, "SIR"); + + yyin = SVF_FILE; + yyparse(); + + /* clean up */ + /* SIR */ + if (sir_params.params.tdi) + free(sir_params.params.tdi); + if (sir_params.params.mask) + free(sir_params.params.mask); + if (sir_params.params.smask) + free(sir_params.params.smask); + /* SDR */ + if (sdr_params.params.tdi) + free(sdr_params.params.tdi); + if (sdr_params.params.mask) + free(sdr_params.params.mask); + if (sdr_params.params.smask) + free(sdr_params.params.smask); +} diff --git a/jtag/src/svf/svf.h b/jtag/src/svf/svf.h new file mode 100644 index 00000000..de2b5216 --- /dev/null +++ b/jtag/src/svf/svf.h @@ -0,0 +1,73 @@ +/* + * $Id$ + * + * Copyright (C) 2004, Arnim Laeuger + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by Arnim Laeuger , 2004. + * + */ + + +#define MAX_PATH_STATES 64 + +/* Coding for commands referring either to IR or DR */ +enum generic_irdr_coding { generic_ir, generic_dr }; + + +struct tdval { + int token; + double dvalue; +}; +struct tcval { + int token; + char *cvalue; + struct tcval *next; +}; + + +struct ths_params { + double number; + char *tdi; + char *tdo; + char *mask; + char *smask; +}; + +struct path_states { + int states[MAX_PATH_STATES]; + int num_states; +}; + +struct runtest { + int run_state; + double run_count; + int run_clk; + double min_time; + double max_time; + int end_state; +}; + + +void svf_endxr(enum generic_irdr_coding, int); +void svf_frequency(double); +int svf_hxr(enum generic_irdr_coding, struct ths_params *); +int svf_runtest(struct runtest *); +int svf_state(struct path_states *, int); +int svf_sxr(enum generic_irdr_coding, struct ths_params *); +int svf_trst(int); +int svf_txr(enum generic_irdr_coding, struct ths_params *); diff --git a/jtag/src/svf/svf_bison.y b/jtag/src/svf/svf_bison.y new file mode 100644 index 00000000..7e268f1d --- /dev/null +++ b/jtag/src/svf/svf_bison.y @@ -0,0 +1,442 @@ +/* + * $Id$ + * + * Copyright (C) 2002 by CSD at http://www-csd.ijs.si + * Copyright (C) 2004, Arnim Laeuger + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by Arnim Laeuger , 2004. + * Original parser skeleton by Robert Sedevici , 2002. + * + */ + + +%{ +#include +#include + +#include "svf.h" + +#define YYERROR_VERBOSE + +struct svf_parser_params { + struct ths_params ths_params; + struct path_states path_states; + struct runtest runtest; +}; + + +static struct svf_parser_params parser_params = { + {0.0, NULL, NULL, NULL, NULL}, + {{}, 0}, + {0, 0.0, 0, 0, 0, 0} +}; + +void yyerror(const char *); +int yylex(void); + +static void svf_free_ths_params(struct ths_params *); +%} + +%union { + int token; + double dvalue; + char *cvalue; + int ivalue; + struct tdval tdval; + struct tcval *tcval; +} + + +%token IDENTIFIER NUMBER HEXA_NUM VECTOR_STRING + +%token EMPTY +%token ENDDR ENDIR +%token FREQUENCY HZ +%token STATE RESET IDLE +%token TDI TDO MASK SMASK +%token TRST ON OFF Z ABSENT +%token HDR HIR SDR SIR TDR TIR +%token PIO PIOMAP IN OUT INOUT H L U D X +%token RUNTEST MAXIMUM SEC TCK SCK ENDSTATE +%token IRPAUSE IRSHIFT IRUPDATE IRSELECT IREXIT1 IREXIT2 IRCAPTURE +%token DRPAUSE DRSHIFT DRUPDATE DRSELECT DREXIT1 DREXIT2 DRCAPTURE +%token SVF_EOF 0 /* SVF_EOF must match bison's token YYEOF */ + +%type NUMBER +%type runtest_clk_count +%type runtest_run_state +%type runtest_end_state + +%% + +line + : /* empty */ + | line svf_statement + | error SVF_EOF + /* Eat whole file in case of error. + * This is necessary because the lexer will remember parts of the file + * inside its input buffer. + * In case errors do not driver the lexer to EOF then the next start + * of yyparse() will read from this buffer, executing commands after the + * previous error! + */ +; + + +svf_statement + : ENDIR stable_state ';' + { + svf_endxr(generic_ir, $2); + } + + | ENDDR stable_state ';' + { + svf_endxr(generic_dr, $2); + } + + | FREQUENCY ';' + { + svf_frequency(0.0); + } + + | FREQUENCY NUMBER HZ ';' + { + svf_frequency($2); + } + + | HDR NUMBER ths_param_list ';' + { + struct ths_params *p = &parser_params.ths_params; + + p->number = $2; + svf_hxr(generic_dr, p); + svf_free_ths_params(p); + } + + | HIR NUMBER ths_param_list ';' + { + struct ths_params *p = &parser_params.ths_params; + + p->number = $2; + svf_hxr(generic_ir, p); + svf_free_ths_params(p); + } + + | PIOMAP '(' direction IDENTIFIER piomap_rec ')' ';' + { + printf("PIOMAP not implemented\n"); + yyerror("PIOMAP"); + YYERROR; + } + + | PIO VECTOR_STRING ';' + { + free($2); + printf("PIO not implemented\n"); + yyerror("PIO"); + YYERROR; + } + + | RUNTEST runtest_run_state runtest_clk_count runtest_min_time1 runtest_end_state ';' + { + struct runtest *rt = &parser_params.runtest; + + rt->run_state = $2; + rt->run_count = $3.dvalue; + rt->run_clk = $3.token; + rt->end_state = $5; + + if (!svf_runtest(rt)) { + yyerror("RUNTEST"); + YYERROR; + } + } + + | RUNTEST runtest_run_state runtest_min_time2 runtest_max_time runtest_end_state ';' + { + struct runtest *rt = &parser_params.runtest; + + rt->run_state = $2; + rt->run_count = 0; + rt->run_clk = 0; + rt->end_state = $5; + + if (!svf_runtest(rt)) { + yyerror("RUNTEST"); + YYERROR; + } + } + + | SDR NUMBER ths_param_list ';' + { + struct ths_params *p = &parser_params.ths_params; + int result; + + p->number = $2; + result = svf_sxr(generic_dr, p); + svf_free_ths_params(p); + + if (!result) { + yyerror("SDR"); + YYERROR; + } + } + + | SIR NUMBER ths_param_list ';' + { + struct ths_params *p = &parser_params.ths_params; + int result; + + p->number = $2; + result = svf_sxr(generic_ir, p); + svf_free_ths_params(p); + + if (!result) { + yyerror("SIR"); + YYERROR; + } + } + + | STATE path_states stable_state ';' + { + if (!svf_state(&parser_params.path_states, $3)) { + yyerror("STATE"); + YYERROR; + } + } + + | TDR NUMBER ths_param_list ';' + { + struct ths_params *p = &parser_params.ths_params; + int result; + + p->number = $2; + result = svf_txr(generic_dr, p); + svf_free_ths_params(p); + + if (!result) { + yyerror("TDR"); + YYERROR; + } + } + + | TIR NUMBER ths_param_list ';' + { + struct ths_params *p = &parser_params.ths_params; + int result; + + p->number = $2; + result = svf_txr(generic_ir, p); + svf_free_ths_params(p); + + if (!result) { + yyerror("TIR"); + YYERROR; + } + } + + | TRST trst_mode ';' + { + if (!svf_trst($2)) { + yyerror("TRST"); + YYERROR; + } + } +; + + +ths_param_list + : /* empty element */ + | ths_param_list ths_opt_param +; + +ths_opt_param + : TDI HEXA_NUM + { + parser_params.ths_params.tdi = $2; + } + + | TDO HEXA_NUM + { + parser_params.ths_params.tdo = $2; + } + + | MASK HEXA_NUM + { + parser_params.ths_params.mask = $2; + } + + | SMASK HEXA_NUM + { + parser_params.ths_params.smask = $2; + } +; + +stable_state + : RESET + | IDLE + | DRPAUSE + | IRPAUSE +; + +runtest_run_state + : { $$ = 0; } /* specify value for 'not existing' */ + | stable_state + { + $$ = $1; + } +; + +runtest_clk_count + : NUMBER TCK + { + $$.token = $2; + $$.dvalue = $1; + } + + | NUMBER SCK + { + $$.token = $2; + $$.dvalue = $1; + } +; + +runtest_min_time1 + : + { + parser_params.runtest.min_time = 0.0; + parser_params.runtest.max_time = 0.0; + } + + | NUMBER SEC runtest_max_time + { + parser_params.runtest.min_time = $1; + } +; + +runtest_min_time2 + : NUMBER SEC + { + parser_params.runtest.min_time = $1; + } +; + +runtest_max_time + : + | MAXIMUM NUMBER SEC + { + parser_params.runtest.max_time = $2; + } +; + +runtest_end_state + : { $$ = 0; } /* specify value for 'not existing' */ + | ENDSTATE stable_state + { + $$ = $2; + } +; + +all_states + : DRSELECT + | DRCAPTURE + | DRSHIFT + | DREXIT1 + | DREXIT2 + | DRUPDATE + | IRSELECT + | IRCAPTURE + | IRSHIFT + | IREXIT1 + | IREXIT2 + | IRUPDATE + | IRPAUSE + | DRPAUSE + | RESET + | IDLE +; + +path_states + : /* empty element, returns index 0 */ + { + parser_params.path_states.num_states = 0; + } + + | path_states all_states + { + struct path_states *ps = &parser_params.path_states; + + if (ps->num_states < MAX_PATH_STATES) { + ps->states[ps->num_states] = $2; + ps->num_states++; + } else + printf("Error %s: maximum number of %d path states reached.\n", + "svf", MAX_PATH_STATES); + } +; + +piomap_rec + : + | piomap_rec direction IDENTIFIER +; + +trst_mode + : ON + | OFF + | Z + | ABSENT +; + +direction + : IN + | OUT + | INOUT +; + +%% + + +void +yyerror(const char *error_string) +{ + printf("Error occured for SVF command %s.\n", error_string); +} + + +static void +svf_free_ths_params(struct ths_params *params) +{ + params->number = 0.0; + + if (params->tdi) { + free(params->tdi); + params->tdi = NULL; + } + if (params->tdo) { + free(params->tdo); + params->tdo = NULL; + } + if (params->mask) { + free(params->mask); + params->mask = NULL; + } + if (params->smask) { + free(params->smask); + params->smask = NULL; + } +} diff --git a/jtag/src/svf/svf_flex.l b/jtag/src/svf/svf_flex.l new file mode 100644 index 00000000..2672bf91 --- /dev/null +++ b/jtag/src/svf/svf_flex.l @@ -0,0 +1,260 @@ +/* $Id$ + * + * Copyright (C) 2002 by CSD at http://www-csd.ijs.si + * Copyright (C) 2004, Arnim Laeuger + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Original lexer by Robert Sedevici , 2002. + * Modified by Arnim Laeuger , 2004. + * + */ + + +%{ +#include +#include + +#include "svf.h" +#include "svf_bison.h" + +static int map_keyw_ident(void); +static void align_string(char *); + +int yywrap(void) +{ + return(1); +} + +%} + +%pointer + +LETTER [A-Za-z] +DIGIT [0-9] +HEX_DIGIT {DIGIT}|[a-fA-F] +WSPACE [ \t\r] +COMMENT (!.*)|("//".*)[^\n] + +%s expect_vector + +%% + + +{LETTER}+[0-9A-Za-z_]* { + /* token is a keyword or identifier */ + int keyw; + + keyw = map_keyw_ident(); + + /* enable detection of VECTOR_STRING when this is a PIO command */ + if (keyw == PIO) { + BEGIN(expect_vector); + } + + return(keyw); +} /* end of keyword or identifier */ + + +{DIGIT}+(\.{DIGIT}+)?([eE][-+]?{DIGIT}+)? { + /* token is a real number */ + + yylval.dvalue = strtod(yytext, (char **) NULL); + return(NUMBER); +} /* end of real number */ + + +"("{WSPACE}*[\n\rHhLlZzUuDdXx \t\r]+{WSPACE}*")" { + /* There is a overlap of VECTOR_STRING and HEXA_NUM when the string + contains only 'd' or 'D'. To prevent complicated parsing rules, + the lexer is instructed to detect VECTOR_STRING only when a PIO + command has been scanned previously. + This is enabled with . */ + /* token is a vector string */ + char *cstring; + + align_string(yytext); + + cstring = calloc(strlen(yytext) + 1, sizeof(char)); + strcpy(cstring, yytext); + yylval.cvalue = cstring; + return(VECTOR_STRING); +} /* end of vector string */ + + +"("{WSPACE}*[\n\rA-Fa-f0-9 \t\r]+{WSPACE}*")" { + /* token is a hexadecimal value (2) */ + char *cstring; + + align_string(yytext); + + cstring = calloc(strlen(yytext) + 1, sizeof(char)); + strcpy(cstring, yytext); + yylval.cvalue = cstring; + return(HEXA_NUM); +} /* end of hexadecimal value */ + + +{WSPACE}+ { + /* token is a white space character */ + +} /* end of white space */ + + +{COMMENT} { + /* token is a comment */ + +} /* end of comment */ + + +[()] { + /* left or right parenthes */ + + return(yytext[0]); +} /* end of left or right parenthesis */ + + +\n { + /* token is a new line character */ + +} /* end of new line */ + + +; { + /* token is end of statement character */ + + /* release expect_vector */ + BEGIN(INITIAL); + + return(yytext[0]); +} /* end of statement character */ + + +<> { + + return(EOF); +} /* end of file token */ + + +. { + /* print token if interactive parsing enabled and yyin != stdin */ + + fprintf(stderr, "Error: \"%s\" is not a legal SVF language token\n", yytext); + +} /* end of any other character */ + +%% + + +/*============================================================================= + * rwtable - reserve word table + *===========================================================================*/ +static struct rwtable +{ + char *rw_name; + int rw_yylex; +} rwtable[] = { + {"ABSENT", ABSENT}, + {"D", D}, + {"DRCAPTURE", DRCAPTURE}, + {"DREXIT1", DREXIT1}, + {"DREXIT2", DREXIT2}, + {"DRPAUSE", DRPAUSE}, + {"DRSELECT", DRSELECT}, + {"DRSHIFT", DRSHIFT}, + {"DRUPDATE", DRUPDATE}, + {"EMPTY", EMPTY}, + {"ENDDR", ENDDR}, + {"ENDIR", ENDIR}, + {"ENDSTATE", ENDSTATE}, + {"FREQUENCY", FREQUENCY}, + {"H", H}, + {"HDR", HDR}, + {"HIR", HIR}, + {"HZ", HZ}, + {"IDLE", IDLE}, + {"IN", IN}, + {"INOUT", INOUT}, + {"IRCAPTURE", IRCAPTURE}, + {"IREXIT1", IREXIT1}, + {"IREXIT2", IREXIT2}, + {"IRPAUSE", IRPAUSE}, + {"IRSELECT", IRSELECT}, + {"IRSHIFT", IRSHIFT}, + {"IRUPDATE", IRUPDATE}, + {"L", L}, + {"MASK", MASK}, + {"MAXIMUM", MAXIMUM}, + {"OFF", OFF}, + {"ON", ON}, + {"OUT", OUT}, + {"PIO", PIO}, + {"PIOMAP", PIOMAP}, + {"RESET", RESET}, + {"RUNTEST", RUNTEST}, + {"SCK", SCK}, + {"SDR", SDR}, + {"SEC", SEC}, + {"SIR", SIR}, + {"SMASK", SMASK}, + {"STATE", STATE}, + {"TCK", TCK}, + {"TDI", TDI}, + {"TDO", TDO}, + {"TDR", TDR}, + {"TIR", TIR}, + {"TRST", TRST}, + {"U", U}, + {"X", X}, + {"Z", Z} +};//end of rwtable struct + +#define END(v) (sizeof(v) / sizeof(v[0]) - 1) + +static int +map_keyw_ident(void) +{ + int idx; + int rw = IDENTIFIER; + + yylval.cvalue = yytext; + + for (idx = 0; idx <= END(rwtable); idx++) { + if (strcasecmp(rwtable[idx].rw_name, yytext) == 0) { + /* always return terminal value as semantic value */ + rw = rwtable[idx].rw_yylex; + yylval.token = rw; + } + } + + return(rw); +} + + +static void +align_string(char *str) +{ + int src, dst, len; + + dst = 0; + len = strlen(str); + + for (src = 0; src < len; src++) { + if (isxdigit(str[src])) + str[dst++] = str[src]; + } + str[dst] = '\0'; +} diff --git a/jtag/src/tap/chain.c b/jtag/src/tap/chain.c index d1ba49cd..74391d7d 100644 --- a/jtag/src/tap/chain.c +++ b/jtag/src/tap/chain.c @@ -95,7 +95,7 @@ chain_get_trst( chain_t *chain ) } void -chain_shift_instructions( chain_t *chain ) +chain_shift_instructions_mode( chain_t *chain, int capture, int exit ) { int i; parts_t *ps; @@ -112,13 +112,21 @@ chain_shift_instructions( chain_t *chain ) } } - tap_capture_ir( chain ); + if (capture) + tap_capture_ir( chain ); for (i = 0; i < ps->len; i++) - tap_shift_register( chain, ps->parts[i]->active_instruction->value, NULL, (i + 1) == ps->len ); + tap_shift_register( chain, ps->parts[i]->active_instruction->value, NULL, + (i + 1) == ps->len ? exit : EXITMODE_SHIFT ); } void -chain_shift_data_registers( chain_t *chain, int capture_output ) +chain_shift_instructions( chain_t *chain ) +{ + chain_shift_instructions_mode( chain, 1, EXITMODE_IDLE ); +} + +void +chain_shift_data_registers_mode( chain_t *chain, int capture_output, int capture, int exit ) { int i; parts_t *ps; @@ -139,9 +147,16 @@ chain_shift_data_registers( chain_t *chain, int capture_output ) } } - tap_capture_dr( chain ); + if (capture) + tap_capture_dr( chain ); for (i = 0; i < ps->len; i++) tap_shift_register( chain, ps->parts[i]->active_instruction->data_register->in, capture_output ? ps->parts[i]->active_instruction->data_register->out : NULL, - (i + 1) == ps->len ); + (i + 1) == ps->len ? exit : EXITMODE_SHIFT ); +} + +void +chain_shift_data_registers( chain_t *chain, int capture_output ) +{ + chain_shift_data_registers_mode( chain, capture_output, 1, EXITMODE_IDLE ); } diff --git a/jtag/src/tap/tap.c b/jtag/src/tap/tap.c index e8eb29fa..e0b6de0c 100644 --- a/jtag/src/tap/tap.c +++ b/jtag/src/tap/tap.c @@ -59,10 +59,10 @@ tap_shift_register( chain_t *chain, const tap_register *in, tap_register *out, i for (i = 0; i < in->len; i++) { if (out && (i < out->len)) out->data[i] = cable_get_tdo( chain->cable ); - chain_clock( chain, (exit && ((i + 1) == in->len)) ? 1 : 0, in->data[i] ); /* Shift (& Exit1) */ + chain_clock( chain, (exit != EXITMODE_SHIFT && ((i + 1) == in->len)) ? 1 : 0, in->data[i] ); /* Shift (& Exit1) */ } /* Shift-DR, Shift-IR, Exit1-DR or Exit1-IR state */ - if (exit) { + if (exit == EXITMODE_IDLE) { chain_clock( chain, 1, 0 ); /* Update-DR or Update-IR */ chain_clock( chain, 0, 0 ); /* Run-Test/Idle */ }