diff --git a/jtag/ChangeLog b/jtag/ChangeLog index 582d3f24..7a790b9e 100644 --- a/jtag/ChangeLog +++ b/jtag/ChangeLog @@ -1,5 +1,6 @@ 2007-12-30 Arnim Laeuger + * many files: integration of BSDL parser * data/xilinx/PARTS: added xc2v80-fg256,xc2v250-fg256,xc2v1000-fg256 '[ 1859678 ] jtag support for xilinx xc2v80-fg256, xc2v250, xc2v1000 FPGA' (Alexander Didebulidze) * data/altera/ep1c12/ep1c12: CLAMP and HIGHZ instructions activated diff --git a/jtag/NEWS b/jtag/NEWS index f72dc56a..f520345e 100644 --- a/jtag/NEWS +++ b/jtag/NEWS @@ -4,6 +4,7 @@ Also see libbrux/NEWS for more news, especially regarding the flash support. urjtag-n/a + * Integration of BSDL parser (Arnim Laeuger) * New and updated cable drivers - Vision EP9307 GPIO (Hartley Sweeten) * Added new JTAG declarations for diff --git a/jtag/configure.ac b/jtag/configure.ac index 9c887f7c..95659582 100644 --- a/jtag/configure.ac +++ b/jtag/configure.ac @@ -68,6 +68,7 @@ AC_CONFIG_FILES( src/bus/Makefile src/cmd/Makefile src/svf/Makefile + src/bsdl/Makefile po/Makefile.in ) diff --git a/jtag/data/Makefile.am b/jtag/data/Makefile.am index bbf8745e..f0bf28b1 100644 --- a/jtag/data/Makefile.am +++ b/jtag/data/Makefile.am @@ -59,6 +59,7 @@ nobase_dist_pkgdata_DATA = \ analog/bf533/bf533 \ analog/PARTS \ analog/sharc21065l/STEPPINGS \ + analog/sharc21065l/sharc21065l analog/sharc21065l/sharc21065l \ brecis/PARTS \ brecis/msp2006/STEPPINGS \ @@ -72,6 +73,8 @@ nobase_dist_pkgdata_DATA = \ broadcom/bcm4712/bcm4712 \ broadcom/bcm5421s/STEPPINGS \ broadcom/bcm5421s/bcm5421s \ + bsdl/STD_1149_1_1990 \ + bsdl/STD_1149_1_1994 \ dec/PARTS \ dec/sa1100/STEPPINGS \ dec/sa1100/sa1100 \ diff --git a/jtag/data/bsdl/STD_1149_1_1990 b/jtag/data/bsdl/STD_1149_1_1990 new file mode 100644 index 00000000..9e9409ce --- /dev/null +++ b/jtag/data/bsdl/STD_1149_1_1990 @@ -0,0 +1,149 @@ +package STD_1149_1_1990 is + +-- Give pin mapping declarations + +attribute PIN_MAP : string; + +subtype PIN_MAP_STRING is string; + +-- Give TAP control declarations + +type CLOCK_LEVEL is (LOW, BOTH); +type CLOCK_INFO is record + FREQ : real; + LEVEL: CLOCK_LEVEL; +end record; + +attribute TAP_SCAN_IN : boolean; +attribute TAP_SCAN_OUT : boolean; +attribute TAP_SCAN_CLOCK: CLOCK_INFO; +attribute TAP_SCAN_MODE : boolean; +attribute TAP_SCAN_RESET: boolean; + +-- Give instruction register declarations + +attribute INSTRUCTION_LENGTH : integer; +attribute INSTRUCTION_OPCODE : string; +attribute INSTRUCTION_CAPTURE : string; +attribute INSTRUCTION_DISABLE : string; +attribute INSTRUCTION_GUARD : string; +attribute INSTRUCTION_PRIVATE : string; +attribute INSTRUCTION_USAGE : string; +attribute INSTRUCTION_SEQUENCE : string; + +-- Give ID and USER code declarations + +type ID_BITS is ('0', '1', 'x', 'X'); +type ID_STRING is array (31 downto 0) of ID_BITS; +attribute IDCODE_REGISTER : ID_STRING; +attribute USERCODE_REGISTER: ID_STRING; + +-- Give register declarations + +attribute REGISTER_ACCESS : string; + +-- Give boundary cell declarations + +type BSCAN_INST is (EXTEST, SAMPLE, INTEST, RUNBIST); +type CELL_TYPE is (INPUT, INTERNAL, CLOCK, + CONTROL, CONTROLR, OUTPUT2, + OUTPUT3, BIDIR_IN, BIDIR_OUT); +type CAP_DATA is (PI, PO, UPD, CAP, X, ZERO, ONE); +type CELL_DATA is record + CT : CELL_TYPE; + I : BSCAN_INST; + CD : CAP_DATA; +end record; +type CELL_INFO is array (positive range <>) of CELL_DATA; + +-- Boundary cell deferred constants (see package body) + +constant BC_1 : CELL_INFO; +constant BC_2 : CELL_INFO; +constant BC_3 : CELL_INFO; +constant BC_4 : CELL_INFO; +constant BC_5 : CELL_INFO; +constant BC_6 : CELL_INFO; + +-- Boundary register declarations + +attribute BOUNDARY_CELLS : string; +attribute BOUNDARY_LENGTH : integer; +attribute BOUNDARY_REGISTER : string; + +-- Miscellaneous + +attribute DESIGN_WARNING : string; + +end STD_1149_1_1990; -- End of IEEE Std 1149.1-1990 Package + + +package body STD_1149_1_1990 is -- Standard boundary cells + +-- Description for f10-12, f10-16, f10-18c, f10-18d, f10-21c + +constant BC_1 : CELL_INFO := + ((INPUT, EXTEST, PI), (OUTPUT2, EXTEST, PI), + (INPUT, SAMPLE, PI), (OUTPUT2, SAMPLE, PI), + (INPUT, INTEST, PI), (OUTPUT2, INTEST, PI), + (INPUT, RUNBIST, PI), (OUTPUT2, RUNBIST, PI), + (OUTPUT3, EXTEST, PI), (INTERNAL, EXTEST, PI), + (OUTPUT3, SAMPLE, PI), (INTERNAL, SAMPLE, PI), + (OUTPUT3, INTEST, PI), (INTERNAL, INTEST, PI), + (OUTPUT3, RUNBIST, PI), (INTERNAL, RUNBIST, PI), + (CONTROL, EXTEST, PI), (CONTROLR, EXTEST, PI), + (CONTROL, SAMPLE, PI), (CONTROLR, SAMPLE, PI), + (CONTROL, INTEST, PI), (CONTROLR, INTEST, PI), + (CONTROL, RUNBIST, PI), (CONTROLR, RUNBIST, PI) ); + +-- Description for f10-8, f10-17, f10-19c, f10-19d, f10-22c + +constant BC_2 : CELL_INFO := + ((INPUT, EXTEST, PI), (OUTPUT2, EXTEST, UPD), + (INPUT, SAMPLE, PI), (OUTPUT2, SAMPLE, PI), + (INPUT, INTEST, UPD), -- Intest on output2 not supported + (INPUT, RUNBIST, UPD), (OUTPUT2, RUNBIST, UPD), + (OUTPUT3, EXTEST, UPD), (INTERNAL, EXTEST, PI), + (OUTPUT3, SAMPLE, PI), (INTERNAL, SAMPLE, PI), + (OUTPUT3, INTEST, PI), (INTERNAL, INTEST, UPD), + (OUTPUT3, RUNBIST, PI), (INTERNAL, RUNBIST, UPD), + (CONTROL, EXTEST, UPD), (CONTROLR, EXTEST, UPD), + (CONTROL, SAMPLE, PI), (CONTROLR, SAMPLE, PI), + (CONTROL, INTEST, PI), (CONTROLR, INTEST, PI), + (CONTROL, RUNBIST, PI), (CONTROLR, RUNBIST, PI) ); + +-- Description for f10-9 + +constant BC_3 : CELL_INFO := + ((INPUT, EXTEST, PI), (INTERNAL, EXTEST, PI), + (INPUT, SAMPLE, PI), (INTERNAL, SAMPLE, PI), + (INPUT, INTEST, PI), (INTERNAL, INTEST, PI), + (INPUT, RUNBIST, PI), (INTERNAL, RUNBIST, PI) ); + +-- Description for f10-10, f10-11 + +constant BC_4 : CELL_INFO := + ((INPUT, EXTEST, PI), -- Intest on input not supported + (INPUT, SAMPLE, PI), -- Runbist on input not supported + (CLOCK, EXTEST, PI), (INTERNAL, EXTEST, PI), + (CLOCK, SAMPLE, PI), (INTERNAL, SAMPLE, PI), + (CLOCK, INTEST, PI), (INTERNAL, INTEST, PI), + (CLOCK, RUNBIST, PI), (INTERNAL, RUNBIST, PI) ); + +-- Description for f10-20c, a combined input/control + +constant BC_5 : CELL_INFO := + ((INPUT, EXTEST, PI), (CONTROL, EXTEST, PI), + (INPUT, SAMPLE, PI), (CONTROL, SAMPLE, PI), + (INPUT, INTEST, UPD), (CONTROL, INTEST, UPD), + (INPUT, RUNBIST, PI), (CONTROL, RUNBIST, PI) ); + +-- Description for f10-22d, a reversible cell + +constant BC_6 : CELL_INFO := + ((BIDIR_IN, EXTEST, PI), (BIDIR_OUT, EXTEST, UPD), + (BIDIR_IN, SAMPLE, PI), (BIDIR_OUT, SAMPLE, PI), + (BIDIR_IN, INTEST, UPD), (BIDIR_OUT, INTEST, PI), + (BIDIR_IN, RUNBIST, UPD), (BIDIR_OUT, RUNBIST, PI) ); + +end STD_1149_1_1990; -- End of 1990 Package Body diff --git a/jtag/data/bsdl/STD_1149_1_1994 b/jtag/data/bsdl/STD_1149_1_1994 new file mode 100644 index 00000000..5968b9da --- /dev/null +++ b/jtag/data/bsdl/STD_1149_1_1994 @@ -0,0 +1,170 @@ +package STD_1149_1_1994 is + +-- Give component conformance declaration + +attribute COMPONENT_CONFORMANCE : string; +-- Give pin mapping declarations + +attribute PIN_MAP : string; +subtype PIN_MAP_STRING is string; + +-- Give TAP control declarations + +type CLOCK_LEVEL is (LOW, BOTH); +type CLOCK_INFO is record + FREQ : real; + LEVEL: CLOCK_LEVEL; +end record; + +attribute TAP_SCAN_IN : boolean; +attribute TAP_SCAN_OUT : boolean; +attribute TAP_SCAN_CLOCK: CLOCK_INFO; +attribute TAP_SCAN_MODE : boolean; +attribute TAP_SCAN_RESET: boolean; + +-- Give instruction register declarations + +attribute INSTRUCTION_LENGTH : integer; +attribute INSTRUCTION_OPCODE : string; +attribute INSTRUCTION_CAPTURE : string; +attribute INSTRUCTION_PRIVATE : string; + +-- Give ID and USER code declarations + +type ID_BITS is ('0', '1', 'x', 'X'); +type ID_STRING is array (31 downto 0) of ID_BITS; +attribute IDCODE_REGISTER : ID_STRING; +attribute USERCODE_REGISTER: ID_STRING; + +-- Give register declarations + +attribute REGISTER_ACCESS : string; + +-- Give boundary cell declarations + +type BSCAN_INST is (EXTEST, SAMPLE, INTEST); +type CELL_TYPE is (INPUT, INTERNAL, CLOCK, OBSERVE_ONLY, + CONTROL, CONTROLR, OUTPUT2, + OUTPUT3, BIDIR_IN, BIDIR_OUT); +type CAP_DATA is (PI, PO, UPD, CAP, X, ZERO, ONE); +type CELL_DATA is record + CT : CELL_TYPE; + I : BSCAN_INST; + CD : CAP_DATA; +end record; +type CELL_INFO is array (positive range <>) of CELL_DATA; + +-- Boundary cell deferred constants (see package body) + +constant BC_0 : CELL_INFO; +constant BC_1 : CELL_INFO; +constant BC_2 : CELL_INFO; +constant BC_3 : CELL_INFO; +constant BC_4 : CELL_INFO; +constant BC_5 : CELL_INFO; +constant BC_6 : CELL_INFO; +constant BC_7 : CELL_INFO; + +-- Boundary register declarations + +attribute BOUNDARY_LENGTH : integer; +attribute BOUNDARY_REGISTER : string; + +-- Miscellaneous + +attribute PORT_GROUPING : string; +attribute RUNBIST_EXECUTION : string; +attribute INTEST_EXECUTION : string; +subtype BSDL_EXTENSION is string; +attribute COMPLIANCE_PATTERNS : string; +attribute DESIGN_WARNING : string; + +end STD_1149_1_1994; -- End of 1149.1-1994 Package + +package body STD_1149_1_1994 is -- Standard boundary cells + +-- Generic cell capturing minimum allowed data + +constant BC_0 : CELL_INFO := + ((INPUT, EXTEST, PI), (OUTPUT2, EXTEST, X), + (INPUT, SAMPLE, PI), (OUTPUT2, SAMPLE, PI), + (INPUT, INTEST, X), (OUTPUT2, INTEST, PI), + (OUTPUT3, EXTEST, X), (INTERNAL, EXTEST, X), + (OUTPUT3, SAMPLE, PI), (INTERNAL, SAMPLE, X), + (OUTPUT3, INTEST, PI), (INTERNAL, INTEST, X), + (CONTROL, EXTEST, X), (CONTROLR, EXTEST, X), + (CONTROL, SAMPLE, PI), (CONTROLR, SAMPLE, PI), + (CONTROL, INTEST, PI), (CONTROLR, INTEST, PI), + (BIDIR_IN,EXTEST, PI), (BIDIR_OUT, EXTEST, X ), + (BIDIR_IN,SAMPLE, PI), (BIDIR_OUT, SAMPLE, PI), + (BIDIR_IN,INTEST, X ), (BIDIR_OUT, INTEST, PI), + (OBSERVE_ONLY, SAMPLE, PI), (OBSERVE_ONLY, EXTEST, PI) ); + +-- Description for f10-18, f10-29, f10-31c, f10-31d, f10-33c, f10-41d + +constant BC_1 : CELL_INFO := + ((INPUT, EXTEST, PI), (OUTPUT2, EXTEST, PI), + (INPUT, SAMPLE, PI), (OUTPUT2, SAMPLE, PI), + (INPUT, INTEST, PI), (OUTPUT2, INTEST, PI), + (OUTPUT3, EXTEST, PI), (INTERNAL, EXTEST, PI), + (OUTPUT3, SAMPLE, PI), (INTERNAL, SAMPLE, PI), + (OUTPUT3, INTEST, PI), (INTERNAL, INTEST, PI), + (CONTROL, EXTEST, PI), (CONTROLR, EXTEST, PI), + (CONTROL, SAMPLE, PI), (CONTROLR, SAMPLE, PI), + (CONTROL, INTEST, PI), (CONTROLR, INTEST, PI) ); + +-- Description for f10-14, f10-30, f10-32c, f10-32d, f10-35c + +constant BC_2 : CELL_INFO := + ((INPUT, EXTEST, PI), (OUTPUT2, EXTEST, UPD), + (INPUT, SAMPLE, PI), (OUTPUT2, SAMPLE, PI), + (INPUT, INTEST, UPD), -- Intest on output2 not supported + (OUTPUT3, EXTEST, UPD), (INTERNAL, EXTEST, PI), + (OUTPUT3, SAMPLE, PI), (INTERNAL, SAMPLE, PI), + (OUTPUT3, INTEST, PI), (INTERNAL, INTEST, UPD), + (CONTROL, EXTEST, UPD), (CONTROLR, EXTEST, UPD), + (CONTROL, SAMPLE, PI), (CONTROLR, SAMPLE, PI), + (CONTROL, INTEST, PI), (CONTROLR, INTEST, PI) ); + +-- Description for f10-15 + +constant BC_3 : CELL_INFO := + ((INPUT, EXTEST, PI), (INTERNAL, EXTEST, PI), + (INPUT, SAMPLE, PI), (INTERNAL, SAMPLE, PI), + (INPUT, INTEST, PI), (INTERNAL, INTEST, PI) ); + +-- Description for f10-16, f10-17 + +constant BC_4 : CELL_INFO := + ((INPUT, EXTEST, PI), -- Intest on input not supported + (INPUT, SAMPLE, PI), + (OBSERVE_ONLY, EXTEST, PI), + (OBSERVE_ONLY, SAMPLE, PI), -- Intest on observe_only not supported + (CLOCK, EXTEST, PI), (INTERNAL, EXTEST, PI), + (CLOCK, SAMPLE, PI), (INTERNAL, SAMPLE, PI), + (CLOCK, INTEST, PI), (INTERNAL, INTEST, PI) ); + +-- Description for f10-41c, a combined input/control + +constant BC_5 : CELL_INFO := + ((INPUT, EXTEST, PI), (CONTROL, EXTEST, PI), + (INPUT, SAMPLE, PI), (CONTROL, SAMPLE, PI), + (INPUT, INTEST, UPD), (CONTROL, INTEST, UPD) ); + +-- Description for f10-35d, a reversible cell +-- !! Not recommended; replaced by BC_7 below !! + +constant BC_6 : CELL_INFO := + ((BIDIR_IN, EXTEST, PI), (BIDIR_OUT, EXTEST, UPD), + (BIDIR_IN, SAMPLE, PI), (BIDIR_OUT, SAMPLE, PI), + (BIDIR_IN, INTEST, UPD), (BIDIR_OUT, INTEST, PI) ); + +-- Description for f10-34d, self monitor reversible +-- !! Recommended over cell BC_6 !! + +constant BC_7 : CELL_INFO := + ((BIDIR_IN, EXTEST, PI), (BIDIR_OUT, EXTEST, PO), + (BIDIR_IN, SAMPLE, PI), (BIDIR_OUT, SAMPLE, PI), + (BIDIR_IN, INTEST, UPD), (BIDIR_OUT, INTEST, PI) ); + +end STD_1149_1_1994; -- End of IEEE Std 1149.1-1994 Package Body diff --git a/jtag/include/bsdl.h b/jtag/include/bsdl.h new file mode 100644 index 00000000..86ed407e --- /dev/null +++ b/jtag/include/bsdl.h @@ -0,0 +1,34 @@ +/* + * $Id$ + * + * Copyright (C) 2007, 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 , 2007. + * + */ + +#ifndef BSDL_H +#define BSDL_H + +extern int bsdl_debug; + +int bsdl_read_file(const char *, int, char *); +void bsdl_set_path(const char *); +int bsdl_scan_files(const char *, int); + +#endif /* BSDL_H */ diff --git a/jtag/src/Makefile.am b/jtag/src/Makefile.am index 3edb0a22..03cb937f 100644 --- a/jtag/src/Makefile.am +++ b/jtag/src/Makefile.am @@ -29,7 +29,8 @@ SUBDIRS = \ part \ bus \ cmd \ - svf + svf \ + bsdl bin_PROGRAMS = \ jtag \ @@ -53,7 +54,8 @@ jtag_DEPENDENCIES = \ part/libpart.a \ bus/libbus.a \ cmd/libcmd.a \ - svf/libsvf.a + svf/libsvf.a \ + bsdl/libbsdl.a jtag_LDADD = \ -Ltap -ltap \ @@ -64,6 +66,7 @@ jtag_LDADD = \ -L../libbrux -lbrux \ -Lbus -lbus \ -Lsvf -lsvf \ + -Lbsdl -lbsdl \ -lm \ @FTD2XXLIB@ \ @LIBINTL@ diff --git a/jtag/src/bsdl/Makefile.am b/jtag/src/bsdl/Makefile.am new file mode 100644 index 00000000..bb0a0c6b --- /dev/null +++ b/jtag/src/bsdl/Makefile.am @@ -0,0 +1,39 @@ +# +# $Id$ +# +# Copyright (C) 2007, 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. +# + +include $(top_srcdir)/Makefile.rules + +noinst_LIBRARIES = libbsdl.a + +libbsdl_a_SOURCES = \ + bsdl.c \ + bsdl_bison.y \ + bsdl_flex.l \ + bsdl_sem.c + +AM_LFLAGS = -i + +MAINTAINERCLEANFILES = \ + bsdl_bison.c \ + bsdl_bison.h \ + bsdl_flex.c + +INCLUDES = -DJTAG_DATA_DIR=\"$(pkgdatadir)\" diff --git a/jtag/src/bsdl/bsdl.c b/jtag/src/bsdl/bsdl.c new file mode 100644 index 00000000..0c57e97c --- /dev/null +++ b/jtag/src/bsdl/bsdl.c @@ -0,0 +1,304 @@ +/* + * $Id$ + * + * Copyright (C) 2007, 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 , 2007. + * + */ + +#include +#include +#include +#define __USE_GNU +#include + +#include +#include + +#include "sysdep.h" + +#include +#include + +#include "bsdl.h" + + +static char **bsdl_path_list = NULL; + +int bsdl_debug = 0; + + +void bsdl_msg(int type, char *format, ...) +{ + va_list lst; + + va_start(lst, format); + switch (type) { + case BSDL_MSG_NOTE: + printf("-N- "); + break; + case BSDL_MSG_WARN: + printf("-W- "); + break; + case BSDL_MSG_ERR: + printf("-E- "); + break; + default: + printf("-?- "); + break; + } + vprintf(format, lst); + va_end(lst); +} + + +/***************************************************************************** + * bsdl_read_file(BSDL_File_Name, mode, idcode) + * + * mode: -1 -> read file + * no further action based on components + * 0 -> read file and extract all components + * dump commands to stdout, do not execute commands + * 1 -> read file and extract all components + * execute commands + * + * Return value: + * < 0 : Error occured, parse/syntax problems or out of memory + * = 0 : No errors, idcode not checked or mismatching + * > 0 : No errors, idcode checked and matched + * + ****************************************************************************/ +int bsdl_read_file(const char *BSDL_File_Name, int mode, const char *idcode) +{ + FILE *BSDL_File; + parser_priv_t *parser_priv; + int Compile_Errors = 1; + int idcode_match = 0; + + BSDL_File = fopen(BSDL_File_Name, "r"); + + if (bsdl_debug || (mode == 0)) + bsdl_msg(BSDL_MSG_NOTE, "Reading file '%s'\n", BSDL_File_Name); + + if (BSDL_File == NULL) { + bsdl_msg(BSDL_MSG_ERR, "Unable to open BSDL_file '%s'\n", BSDL_File_Name); + return -1; + } + + if ((parser_priv = bsdl_parser_init(BSDL_File))) { + if (mode >= 0) { + if (mode >= 1) { + if (chain == NULL) { + bsdl_msg(BSDL_MSG_ERR, _("No JTAG chain available\n")); + bsdl_parser_deinit(parser_priv); + fclose(BSDL_File); + return -1; + } + if (chain->parts == NULL) { + bsdl_msg(BSDL_MSG_ERR, _("Shain without any parts\n")); + bsdl_parser_deinit(parser_priv); + fclose(BSDL_File); + return -1; + } + if (!(chain && chain->parts)) { + bsdl_parser_deinit(parser_priv); + fclose(BSDL_File); + return -1; + } + parser_priv->jtag_ctrl.part = chain->parts->parts[chain->active_part]; + } else + parser_priv->jtag_ctrl.part = NULL; + } else + parser_priv->jtag_ctrl.part = NULL; + + parser_priv->jtag_ctrl.mode = mode; + parser_priv->jtag_ctrl.idcode = NULL; + + bsdlparse(parser_priv); + + Compile_Errors = bsdl_flex_get_compile_errors(parser_priv->scanner); + if (Compile_Errors == 0) { + if (bsdl_debug) + bsdl_msg(BSDL_MSG_NOTE, "BSDL file '%s' compiled correctly\n", BSDL_File_Name); + } else { + bsdl_msg(BSDL_MSG_ERR, "BSDL file '%s' contains errors, stopping\n", BSDL_File_Name); + } + + if (Compile_Errors == 0) + bsdl_ac_finalize(parser_priv); + + if ((Compile_Errors == 0) && parser_priv->jtag_ctrl.idcode) { + if (bsdl_debug) + bsdl_msg(BSDL_MSG_NOTE, "Got IDCODE: %s\n", parser_priv->jtag_ctrl.idcode); + + /* should be compare the idcodes? */ + if (idcode) { + if (strlen(idcode) == strlen(parser_priv->jtag_ctrl.idcode)) { + int idx; + + /* compare given idcode with idcode from BSDL file + including the end of string character */ + idcode_match = 1; + for (idx = 0; idx <= strlen(idcode); idx++) + if (parser_priv->jtag_ctrl.idcode[idx] != 'X') + if (idcode[idx] != parser_priv->jtag_ctrl.idcode[idx]) + idcode_match = 0; + + if (bsdl_debug) { + if (idcode_match) + bsdl_msg(BSDL_MSG_NOTE, _("IDCODE matched\n") ); + else + bsdl_msg(BSDL_MSG_NOTE, _("IDCODE mismatch\n") ); + } + } + } + + free(parser_priv->jtag_ctrl.idcode); + parser_priv->jtag_ctrl.idcode = NULL; + } + bsdl_parser_deinit(parser_priv); + } + + return Compile_Errors == 0 ? idcode_match : -1; +} + + +/***************************************************************************** + * void bsdl_set_path(const char *pathlist) + * + * Dissects pathlist and enters its elements to the global variable + * bsdl_path_list. + * + * Return value: + * void + ****************************************************************************/ +void bsdl_set_path(const char *pathlist) +{ + char *delim; + char *elem; + int num; + + /* free memory of current path list */ + if (bsdl_path_list) { + for (num = 0; bsdl_path_list[num]; num++) + if (bsdl_path_list[num]) + free(bsdl_path_list[num]); + free(bsdl_path_list); + bsdl_path_list = NULL; + } + + /* run through path list and determine number of elements */ + for (num = 0, elem = (char *)pathlist; strlen(elem) > 0; ) { + delim = strchr(elem, ';'); + if ((delim - elem > 0) || (delim == NULL)) { + num++; + /* extend path list array */ + bsdl_path_list = (char **)realloc(bsdl_path_list, (num+1) * sizeof(char *)); + /* enter path element up to the delimeter */ + bsdl_path_list[num-1] = strndup(elem, (size_t)(delim - elem)); + bsdl_path_list[num] = NULL; + } + elem = delim ? delim + 1 : elem + strlen(elem); + } + + if (bsdl_debug) + for (num = 0; bsdl_path_list[num] != NULL; num++) { + bsdl_msg(BSDL_MSG_NOTE, "%s\n", bsdl_path_list[num]); + } +} + + +/***************************************************************************** + * int bsdl_scan_files(const char *idcode, int mode) + * + * Scans through all files found via the elements in bsdl_path_list + * and does a test read on each of them. + * If mode >= 1 is requested, it will read the first BSDL file with matching + * idcode in "execute" mode. I.e. all extracted statements are applied to + * the current part. + * + * mode: -1 -> read file + * no further action based on components + * 0 -> read file and extract all components + * dump commands to stdout, do not execute commands + * 1 -> read file and extract all components + * execute commands + * + * Return value: + * < 0 : Error occured, parse/syntax problems or out of memory + * = 0 : No errors, idcode not checked or mismatching + * > 0 : No errors, idcode checked and matched + * + ****************************************************************************/ +int bsdl_scan_files(const char *idcode, int mode) +{ + int idx = 0; + int result = 0; + + /* abort if no path list was specified */ + if (bsdl_path_list == NULL) + return 0; + + while (bsdl_path_list[idx] && (result <= 0)) { + DIR *dir; + + if ((dir = opendir(bsdl_path_list[idx]))) { + struct dirent *elem; + + /* run through all elements in the current directory */ + while ((elem = readdir(dir)) && (result <= 0)) { + char *name; + + name = (char *)malloc(strlen(bsdl_path_list[idx]) + strlen(elem->d_name) + 1 + 1); + if (name) { + struct stat buf; + + strcpy(name, bsdl_path_list[idx]); + strcat(name, "/"); + strcat(name, elem->d_name); + + if (stat(name, &buf) == 0) { + if (buf.st_mode & S_IFREG) { + if (mode >= 1) { + /* now we know we can finally read the file */ + /* do a test read first */ + result = bsdl_read_file(name, -1, idcode); + if (result > 0) { + /* read in BSDL file if IDCODE matched */ + printf( _(" Filename: %s\n"), name ); + result = bsdl_read_file(name, 1, idcode); + } + } else + result = bsdl_read_file(name, mode, idcode); + } + } + + free(name); + } + } + + closedir(dir); + } else + bsdl_msg(BSDL_MSG_WARN, "Warning: Cannot open directory %s\n", bsdl_path_list[idx]); + + idx++; + } + + return result; +} diff --git a/jtag/src/bsdl/bsdl.h b/jtag/src/bsdl/bsdl.h new file mode 100644 index 00000000..3bfa9e67 --- /dev/null +++ b/jtag/src/bsdl/bsdl.h @@ -0,0 +1,151 @@ +/* + * $Id$ + * + * Copyright (C) 2007, 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 , 2007. + * + */ + +#include + + +/* message types for bsdl_msg() */ +#define BSDL_MSG_NOTE 0 +#define BSDL_MSG_WARN 1 +#define BSDL_MSG_ERR 2 + + +/* private data of the flex scanner + handled internally in bsdl_flex.l as yyextra */ +struct scan_extra { + int Compile_Errors; + int Base; +}; +typedef struct scan_extra scan_extra_t; + + +/* list of instructions + the instruction name and its opcode (optional) is stored here */ +struct instr_elem { + struct instr_elem *next; + char *instr; + char *opcode; +}; + +/* register access information + * derived from the entries of the REGISTER_ACCESS attribute + * ainfo_elem describes a register and its accosiated instructions + * - register name + * - register length (optional) + * - list of associated instructions + */ +struct ainfo_elem { + struct ainfo_elem *next; + char *reg; + int reg_len; + struct instr_elem *instr_list; +}; + +/* the access_data structure is the entry point into the register access + management data + it contains the pointer to the main list of REGISTER_ACCESS entries plus + components that store temporary data while an entry is parser/built */ +struct access_data { + struct ainfo_elem *ainfo_list; + /* temporary private data for building the "current" access info entry */ + char *reg; + int reg_len; + struct instr_elem *instr_list; +}; + +/* structure cell_info collects bit/cell information from the + BOUNDARY_REGISTER attribute + each Cell_Entry fills in the structure and the contents is used for the + respective 'bit' command */ +struct cell_info { + /* basic cell spec entries */ + int bit_num; + char *port_name; + int cell_function; + char *basic_safe_value; + /* the disable spec entries */ + int ctrl_bit_num; + int disable_safe_value; +}; + +/* structure jtag_ctrl collects all elements that are required to interface + with jtag internals */ +struct jtag_ctrl { + int mode; + char *idcode; /* IDCODE string */ + part_t *part; + struct cell_info cell_info; + struct instr_elem *instr_list; + struct access_data access_data; +}; + +/* private data of the bison parser + used to store variables the would end up as globals otherwise */ +struct parser_priv { + char String_Val[150]; + char Package_File_Name[100]; + int Reading_Package; + char *buffer_for_switch; + size_t len_buffer_for_switch; + int idx_to_buffer; + void *scanner; + struct jtag_ctrl jtag_ctrl; +}; +typedef struct parser_priv parser_priv_t; + + +void bsdl_msg(int, char *, ...); + +/* BSDL lexer declarations */ +void *bsdl_flex_init(FILE *); +void bsdl_flex_deinit(void *); +void bsdl_flex_switch_file(void *, const char *); +void bsdl_flex_switch_buffer(void *, const char *); +int bsdl_flex_get_compile_errors(void *); +int bsdl_flex_postinc_compile_errors(void *); +int bsdl_flex_get_lineno(void *); + +/* BSDL parser declarations */ +parser_priv_t *bsdl_parser_init(FILE *); +void bsdl_parser_deinit(parser_priv_t *); +int bsdlparse(parser_priv_t *); + +/* BSDL / JTAG semantic action interface */ +void bsdl_sem_init(parser_priv_t *); +void bsdl_sem_deinit(parser_priv_t *); +void bsdl_set_entity(parser_priv_t *, char *); +void bsdl_set_instruction_length(parser_priv_t *, int); +void bsdl_add_pin(parser_priv_t *, char *); +void bsdl_set_idcode(parser_priv_t *, char *); +void bsdl_set_usercode(parser_priv_t *, char *); +void bsdl_add_instruction(parser_priv_t *, char *, char *); +void bsdl_set_bsr_length(parser_priv_t *, int); +void bsdl_ci_no_disable(parser_priv_t *); +void bsdl_ci_set_cell_spec(parser_priv_t *, char *, int, char *); +void bsdl_ci_set_cell_spec_disable(parser_priv_t *, int, int, int); +void bsdl_ci_apply_cell_info(parser_priv_t *, int); +void bsdl_ac_set_register(parser_priv_t *, char *, int); +void bsdl_ac_add_instruction(parser_priv_t *, char *); +void bsdl_ac_apply_assoc(parser_priv_t *); +void bsdl_ac_finalize(parser_priv_t *); diff --git a/jtag/src/bsdl/bsdl_bison.y b/jtag/src/bsdl/bsdl_bison.y new file mode 100644 index 00000000..23243ea5 --- /dev/null +++ b/jtag/src/bsdl/bsdl_bison.y @@ -0,0 +1,970 @@ +/* + * $Id$ + * + * Original Yacc code by Ken Parker, 1990 + * Extensions and adaptions for UrJTAG by Arnim Laeuger, 2007 + * + */ + +/* ----------------------------------------------------------------------- */ +/* */ +/* Yacc code for BSDL */ +/* */ +/* ----------------------------------------------------------------------- */ +/* Date: 901003 */ + +/* + +Email header accompanying the original Yacc code: + +-----------------------------------8<-------------------------------------- + +Hello All, + +This is this first mailing of the BSDL* Version 0.0 parser specifications +we are sending to people who request it from our publicized E-Mail address; + + bsdl%hpmtlx@hplabs.HP.com + +You are free to redistribute this at will, but we feel that it would be +better if respondents asked for it directly so that their addresses can +be entered into our list for future mailings and updates. + +It would be helpful if you could confirm receipt of this transmission. +We also would be very interested to hear about your experiences with this +information and what you are planning to do with BSDL. + +Regards, + +Ken Parker +Hewlett-Packard Company + + +*Boundary-Scan Description Language - as documented in: + +"A Language for Describing Boundary-Scan Devices", K.P. Parker +and S. Oresjo, Proceedings 1990 International Test Conference, +Washington DC, pp 222-234 + + +- -----------------cut here--------------------------------------------------- + + +901004.0721 Hewlett-Packard Company +901016.1049 Manufacturing Test Division + P.O. Box 301 + Loveland, Colorado 80537 + USA + + October 1990 +Hello BSDL Parser Requestor, + + This Electronic Mail reply contains the computer specifications for +Hewlett-Packard's Version 0.0 BSDL parser. This section of the reply +explains the contents of the rest of this file. + +This file is composed of seven (7) parts: + + 1) How to use this file + + 2) UNIX* Lex source (lexicographical tokenizing rules) + + 3) UNIX* Yacc source (BNF-like syntax description) + + 4) A sample main program to recognize BSDL. + + 5) A BSDL description of the Texas Instruments 74bct8374 that is + recognized by the parser, for testing purposes. + + 6) The VHDL package STD_1149_1_1990 needed by this parser. + + 7) [added 901016] Porting experiences to other systems. + + +RECOMMENDATION: Save a copy of this file in archival storage before + processing it via the instructions below. This will + allow you to recover from errors, and allow you to + compare subsequently released data for changes. + +DISCLAIMERS: + +1. The IEEE 1149.1 Working Group has not endorsed BSDL Version 0.0 and + therefore no person may represent it as an IEEE standard or imply that + a resulting IEEE standard will be identical to it. + +2. The IEEE 1149.1 Working Group recognizes that BSDL Version 0.0 is a + well-conceived initiative that is likely to excelerate the creation + of tools that support the 1149.1 standard. As such, changes and + enhancements will be carefully considered so as not to needlessly + disrupt these development efforts. The overriding goal is the + ultimate success of the 1149.1 standard. + +LEGAL NOTICES: + + Hewlett-Packard Company makes no warranty of any kind with regard to + this information, including, but not limited to, the implied + waranties of merchantability and fitness for a particular purpose. + + Hewlett-Packard Company shall not be liable for errors contained + herein or direct, indirect, special, incidental, or consequential + damages in connection with the furnishing, performance, or use of + this material. + + +*UNIX is a trademark of AT&T in the USA and other countries. + +*/ + + +%pure-parser +%parse-param {parser_priv_t *priv_data} +%defines +%name-prefix="bsdl" + +%{ +#include +#include +#include +#include + +/* interface to flex */ +#include "bsdl_bison.h" +#include "bsdl.h" + +#define YYLEX_PARAM priv_data->scanner +int yylex (YYSTYPE *, void *); + +#if 1 +#define ERROR_LIMIT 15 +#define BUMP_ERROR if (bsdl_flex_postinc_compile_errors(priv_data->scanner)>ERROR_LIMIT) \ + {Give_Up_And_Quit(priv_data);YYABORT;} +#else +#define BUMP_ERROR {Give_Up_And_Quit(priv_data);YYABORT;} +#endif + +static void Init_Text(parser_priv_t *); +static void Store_Text(parser_priv_t *, char *); +static void Make_String(char *, char *); +static void Print_Error(parser_priv_t *, char *); +static void Print_Warning(parser_priv_t *, char *); +static void Give_Up_And_Quit(parser_priv_t *); + +void yyerror(parser_priv_t *, const char *); +%} + +%union { + int integer; + char *str; +} + + +%token ENTITY PORT GENERIC USE ATTRIBUTE IS +%token OF CONSTANT STRING END ALL PIN_MAP +%token PHYSICAL_PIN_MAP PIN_MAP_STRING TRUE FALSE SIGNAL +%token TAP_SCAN_IN TAP_SCAN_OUT TAP_SCAN_MODE TAP_SCAN_RESET +%token TAP_SCAN_CLOCK LOW BOTH IN OUT INOUT +%token BUFFER LINKAGE BIT BIT_VECTOR TO DOWNTO +%token PACKAGE BODY TYPE SUBTYPE RECORD ARRAY +%token POSITIVE RANGE CELL_INFO INSTRUCTION_LENGTH +%token INSTRUCTION_OPCODE INSTRUCTION_CAPTURE INSTRUCTION_DISABLE +%token INSTRUCTION_GUARD INSTRUCTION_PRIVATE INSTRUCTION_USAGE +%token INSTRUCTION_SEQUENCE REGISTER_ACCESS BOUNDARY_CELLS +%token BOUNDARY_LENGTH BOUNDARY_REGISTER IDCODE_REGISTER +%token USERCODE_REGISTER DESIGN_WARNING BOUNDARY BYPASS HIGHZ IDCODE DEVICE_ID +%token USERCODE INPUT OUTPUT2 OUTPUT3 CONTROL CONTROLR INTERNAL +%token CLOCK BIDIR BIDIR_IN BIDIR_OUT EXTEST SAMPLE +%token INTEST RUNBIST PI PO UPD CAP X +%token ZERO ONE Z WEAK0 WEAK1 IDENTIFIER +%token PULL0 PULL1 KEEPER +%token SINGLE_QUOTE QUOTED_STRING DECIMAL_NUMBER BINARY_PATTERN +%token BIN_X_PATTERN REAL_NUMBER CONCATENATE SEMICOLON COMMA +%token LPAREN RPAREN LBRACKET RBRACKET COLON ASTERISK +%token BOX COLON_EQUAL PERIOD ILLEGAL +%token COMPONENT_CONFORMANCE PORT_GROUPING RUNBIST_EXECUTION +%token INTEST_EXECUTION BSDL_EXTENSION COMPLIANCE_PATTERNS +%token OBSERVE_ONLY + +%type BIN_X_PATTERN +%type IDENTIFIER +%type QUOTED_STRING +%type BINARY_PATTERN +%type Binary_Pattern +%type Pattern_List +%type DECIMAL_NUMBER +%type REAL_NUMBER +%type Port_Name +%type Cell_Function +%type Safe_Value +%type Disable_Value +%type Standard_Reg +%type Standard_Inst + +%start BSDL_Program + +%% /* End declarations, begin rules */ + +BSDL_Program : Begin_BSDL Part_1 Part_2 End_BSDL + ; +Begin_BSDL : ENTITY IDENTIFIER IS + { bsdl_set_entity(priv_data, $2); } + | error + {Print_Error(priv_data, "Improper Entity declaration"); + Print_Error(priv_data, "Check if source file is BSDL"); + YYABORT; /* Probably not a BSDL source file */ + } + ; +Part_1 : VHDL_Generic /* 1994 and later */ + VHDL_Port + VHDL_Use_Part + VHDL_Component_Conformance + VHDL_Pin_Map + VHDL_Constant_List + | VHDL_Generic /* 1990 */ + VHDL_Port + VHDL_Use_Part + VHDL_Pin_Map + VHDL_Constant_List + | error + {Print_Error(priv_data, "Syntax Error"); + BUMP_ERROR; YYABORT; } + ; +Part_2 : VHDL_Tap_Signals + VHDL_Compliance_Patterns + VHDL_Inst_Length + VHDL_Inst_Opcode + VHDL_Inst_Details + VHDL_Boundary_Details + VHDL_Boundary_Register + | VHDL_Tap_Signals + VHDL_Inst_Length + VHDL_Inst_Opcode + VHDL_Inst_Details + VHDL_Boundary_Details + VHDL_Boundary_Register + | error + {Print_Error(priv_data, "Syntax Error"); + BUMP_ERROR; YYABORT; } + ; +End_BSDL : VHDL_Design_Warning END IDENTIFIER SEMICOLON + { free($3); } + | error + {Print_Error(priv_data, "Syntax Error"); + BUMP_ERROR; YYABORT; } + ; +VHDL_Generic : GENERIC LPAREN PHYSICAL_PIN_MAP COLON STRING COLON_EQUAL + Quoted_String RPAREN SEMICOLON + { + bsdl_flex_switch_buffer(priv_data->scanner, + priv_data->buffer_for_switch); + } + IDENTIFIER + { free($11); } + ; +VHDL_Port : PORT LPAREN Port_Specifier_List RPAREN SEMICOLON + | error + {Print_Error(priv_data, "Improper Port declaration"); + BUMP_ERROR; YYABORT; } + ; +Port_Specifier_List : Port_Specifier + | Port_Specifier_List SEMICOLON Port_Specifier + ; +Port_Specifier : Port_List COLON Function Scaler_Or_Vector + ; +Port_List : IDENTIFIER + { free($1); } + | Port_List COMMA IDENTIFIER + { free($3); } + ; +Function : IN | OUT | INOUT | BUFFER | LINKAGE + ; +Scaler_Or_Vector : BIT + | BIT_VECTOR LPAREN Vector_Range RPAREN + ; +Vector_Range : DECIMAL_NUMBER TO DECIMAL_NUMBER + | DECIMAL_NUMBER DOWNTO DECIMAL_NUMBER + ; +VHDL_Use_Part : Standard_Use + | Standard_Use VHDL_Use_List + | error + {Print_Error(priv_data, "Error in Package declaration(s)"); + BUMP_ERROR; YYABORT; } + ; +Standard_Use : USE IDENTIFIER + {/* Parse Standard 1149.1 Package */ + strcpy(priv_data->Package_File_Name, $2); + free($2); + } + PERIOD ALL SEMICOLON + { + priv_data->Reading_Package = 1; + bsdl_flex_switch_file(priv_data->scanner, + priv_data->Package_File_Name); + } + Standard_Package + { + priv_data->Reading_Package = 0; + } + ; +Standard_Package : PACKAGE IDENTIFIER IS Standard_Decls Defered_Constants + Standard_Decls END IDENTIFIER SEMICOLON Package_Body + { free($2); free($8); } + | error + {Print_Error(priv_data, "Error in Standard Package"); + BUMP_ERROR; YYABORT; } + ; +Standard_Decls : Standard_Decl + | Standard_Decls Standard_Decl + ; +Standard_Decl : ATTRIBUTE Standard_Attributes COLON Attribute_Type SEMICOLON + | TYPE IDENTIFIER IS Type_Body SEMICOLON + { free($2); } + | TYPE CELL_INFO IS ARRAY LPAREN POSITIVE RANGE BOX RPAREN + OF IDENTIFIER SEMICOLON + { free($11); } + | SUBTYPE PIN_MAP_STRING IS STRING SEMICOLON + | SUBTYPE BSDL_EXTENSION IS STRING SEMICOLON + | error + {Print_Error(priv_data, "Error in Standard Declarations"); + BUMP_ERROR; YYABORT; } + ; +Standard_Attributes : PIN_MAP | TAP_SCAN_IN | TAP_SCAN_OUT + | TAP_SCAN_CLOCK | TAP_SCAN_MODE | TAP_SCAN_RESET + | COMPONENT_CONFORMANCE | PORT_GROUPING | RUNBIST_EXECUTION + | INTEST_EXECUTION | COMPLIANCE_PATTERNS + | INSTRUCTION_LENGTH | INSTRUCTION_OPCODE + | INSTRUCTION_CAPTURE | INSTRUCTION_DISABLE + | INSTRUCTION_GUARD | INSTRUCTION_PRIVATE + | INSTRUCTION_USAGE | INSTRUCTION_SEQUENCE + | IDCODE_REGISTER | USERCODE_REGISTER + | REGISTER_ACCESS | BOUNDARY_CELLS + | BOUNDARY_LENGTH | BOUNDARY_REGISTER + | DESIGN_WARNING + | error + {Print_Error(priv_data, "Error in Attribute identifier"); + BUMP_ERROR; YYABORT; } + ; +Attribute_Type : IDENTIFIER + { free($1); } + | STRING + | DECIMAL_NUMBER + | error + {Print_Error(priv_data, "Error in Attribute type identification"); + BUMP_ERROR; YYABORT; } + ; +Type_Body : LPAREN ID_Bits RPAREN + | LPAREN ID_List RPAREN + | LPAREN LOW COMMA BOTH RPAREN + | ARRAY LPAREN DECIMAL_NUMBER TO DECIMAL_NUMBER RPAREN + OF IDENTIFIER + { free($8); } + | ARRAY LPAREN DECIMAL_NUMBER DOWNTO DECIMAL_NUMBER RPAREN + OF IDENTIFIER + { free($8); } + | RECORD Record_Body END RECORD + | error + {Print_Error(priv_data, "Error in Type definition"); + BUMP_ERROR; YYABORT; } + ; +ID_Bits : ID_Bit + | ID_Bits COMMA ID_Bit + ; +ID_List : IDENTIFIER + { free($1); } + | ID_List COMMA IDENTIFIER + { free($3); } + ; +ID_Bit : SINGLE_QUOTE BIN_X_PATTERN SINGLE_QUOTE + { free($2); } + | error + {Print_Error(priv_data, "Error in Bit definition"); + BUMP_ERROR; YYABORT; } + ; +Record_Body : Record_Element + | Record_Body Record_Element + ; +Record_Element : IDENTIFIER COLON IDENTIFIER SEMICOLON + { free($1); free($3); } + | error + {Print_Error(priv_data, "Error in Record Definition"); + BUMP_ERROR; YYABORT; } + ; +Defered_Constants: Defered_Constant + | Defered_Constants Defered_Constant + ; +Defered_Constant : CONSTANT Constant_Body + ; +Constant_Body : IDENTIFIER COLON CELL_INFO SEMICOLON + { free($1); } + | error + {Print_Error(priv_data, "Error in defered constant"); + BUMP_ERROR; YYABORT; } + ; +VHDL_Use_List : VHDL_Use + | VHDL_Use_List VHDL_Use + ; +Package_Body : PACKAGE BODY IDENTIFIER IS Constant_List END IDENTIFIER + { free($3); free($7); } + SEMICOLON + | error + {Print_Error(priv_data, "Error in Package Body definition"); + BUMP_ERROR; YYABORT; } + ; +Constant_List : Cell_Constant + | Constant_List Cell_Constant + ; +Cell_Constant : CONSTANT IDENTIFIER COLON CELL_INFO COLON_EQUAL + LPAREN Triples_List RPAREN SEMICOLON + { free($2); } + | error + {Print_Error(priv_data, "Error in Cell Constant definition"); + BUMP_ERROR; YYABORT; } + ; +Triples_List : Triple + | Triples_List COMMA Triple + ; +Triple : LPAREN Triple_Function COMMA Triple_Inst COMMA CAP_Data + RPAREN + | error + {Print_Error(priv_data, "Error in Cell Data Record"); + BUMP_ERROR; YYABORT; } + ; +Triple_Function : INPUT | OUTPUT2 | OUTPUT3 | INTERNAL | CONTROL + | CONTROLR | CLOCK | BIDIR_IN | BIDIR_OUT + | OBSERVE_ONLY + | error + {Print_Error(priv_data, "Error in Cell_Type Function field"); + BUMP_ERROR; YYABORT; } + ; +Triple_Inst : EXTEST | SAMPLE | INTEST | RUNBIST + | error + {Print_Error(priv_data, "Error in BScan_Inst Instruction field"); + BUMP_ERROR; YYABORT; } + ; +CAP_Data : PI | PO | UPD | CAP | X | ZERO | ONE + | error + {Print_Error(priv_data, "Error in Constant CAP data source field"); + BUMP_ERROR; YYABORT; } + ; +VHDL_Use : USE IDENTIFIER + {/* Parse Standard 1149.1 Package */ + strcpy(priv_data->Package_File_Name, $2); + free($2); + } + PERIOD ALL SEMICOLON + { + priv_data->Reading_Package = 1; + bsdl_flex_switch_file(priv_data->scanner, + priv_data->Package_File_Name); + } + User_Package + { + priv_data->Reading_Package = 0; + } + ; +User_Package : PACKAGE IDENTIFIER + IS Defered_Constants END IDENTIFIER SEMICOLON Package_Body + { free($2); free($6); } + | error + {Print_Error(priv_data, "Error in User-Defined Package declarations"); + BUMP_ERROR; YYABORT; } + ; +VHDL_Pin_Map : ATTRIBUTE PIN_MAP OF IDENTIFIER + COLON ENTITY IS PHYSICAL_PIN_MAP SEMICOLON + { free($4); } + | error + {Print_Error(priv_data, "Error in Pin_Map Attribute"); + BUMP_ERROR; YYABORT; } + ; +VHDL_Constant_List : VHDL_Constant + | VHDL_Constant_List VHDL_Constant + ; +VHDL_Constant : CONSTANT VHDL_Constant_Part + ; +VHDL_Constant_Part : IDENTIFIER COLON PIN_MAP_STRING COLON_EQUAL + Quoted_String SEMICOLON + { + bsdl_flex_switch_buffer(priv_data->scanner, + priv_data->buffer_for_switch); + } + BSDL_Map_String + { free($1); } + | error + {Print_Error(priv_data, "Error in Pin_Map_String constant declaration"); + BUMP_ERROR; YYABORT; } + ; +BSDL_Map_String : Pin_Mapping + | BSDL_Map_String COMMA Pin_Mapping + ; +Pin_Mapping : IDENTIFIER COLON Physical_Pin_Desc + { + bsdl_add_pin(priv_data, $1); + } + ; +Physical_Pin_Desc: Physical_Pin + | LPAREN Physical_Pin_List RPAREN + ; +Physical_Pin_List: Physical_Pin + | Physical_Pin_List COMMA Physical_Pin + ; +Physical_Pin : IDENTIFIER + { free($1); } + | DECIMAL_NUMBER + ; +VHDL_Tap_Signals : VHDL_Tap_Signal + | VHDL_Tap_Signals VHDL_Tap_Signal + ; +VHDL_Tap_Signal : VHDL_Tap_Scan_In + | VHDL_Tap_Scan_Out + | VHDL_Tap_Scan_Clock + | VHDL_Tap_Scan_Mode + | VHDL_Tap_Scan_Reset + ; +VHDL_Tap_Scan_In : ATTRIBUTE TAP_SCAN_IN OF IDENTIFIER + COLON SIGNAL IS Boolean SEMICOLON + { free($4); } + ; +VHDL_Tap_Scan_Out : ATTRIBUTE TAP_SCAN_OUT OF IDENTIFIER + COLON SIGNAL IS Boolean SEMICOLON + { free($4); } + ; +VHDL_Tap_Scan_Mode : ATTRIBUTE TAP_SCAN_MODE OF IDENTIFIER + COLON SIGNAL IS Boolean SEMICOLON + { free($4); } + ; +VHDL_Tap_Scan_Reset : ATTRIBUTE TAP_SCAN_RESET OF IDENTIFIER + COLON SIGNAL IS Boolean SEMICOLON + { free($4); } + ; +VHDL_Tap_Scan_Clock : ATTRIBUTE TAP_SCAN_CLOCK OF IDENTIFIER COLON SIGNAL + IS LPAREN REAL_NUMBER COMMA Stop RPAREN SEMICOLON + { free($4); free($9); } + ; +Stop : LOW | BOTH + ; +Boolean : TRUE | FALSE + ; +VHDL_Inst_Length : ATTRIBUTE INSTRUCTION_LENGTH OF IDENTIFIER + COLON ENTITY IS DECIMAL_NUMBER SEMICOLON + { + bsdl_set_instruction_length(priv_data, $8); + free($4); + } + ; +VHDL_Inst_Opcode : ATTRIBUTE INSTRUCTION_OPCODE OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + { + bsdl_flex_switch_buffer(priv_data->scanner, + priv_data->buffer_for_switch); + } + BSDL_Opcode_Table + { free($4); } + ; +BSDL_Opcode_Table: Opcode_Desc + | BSDL_Opcode_Table COMMA Opcode_Desc + | error + {Print_Error(priv_data, + "Error in Instruction_Opcode attribute statement"); + BUMP_ERROR; + YYABORT; } + ; +Opcode_Desc : IDENTIFIER LPAREN Pattern_List RPAREN + { bsdl_add_instruction(priv_data, $1, $3); } + ; +Pattern_List : Binary_Pattern + { $$ = $1; } + | Pattern_List COMMA Binary_Pattern + { + Print_Warning(priv_data, + "Multiple opcode patterns are not supported, first pattern will be used"); + $$ = $1; + free($3); + } + ; +Binary_Pattern : BINARY_PATTERN + { $$ = $1; } + ; +VHDL_Inst_Details: VHDL_Inst_Detail + | VHDL_Inst_Details VHDL_Inst_Detail + ; +VHDL_Inst_Detail : VHDL_Inst_Capture + | VHDL_Inst_Disable + | VHDL_Inst_Guard + | VHDL_Inst_Private + | VHDL_Register_Access + | VHDL_Inst_Usage + | VHDL_Inst_Sequence + | VHDL_Idcode_Register + | VHDL_Usercode_Register + ; +VHDL_Inst_Capture: ATTRIBUTE INSTRUCTION_CAPTURE OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + { + bsdl_flex_switch_buffer(priv_data->scanner, + priv_data->buffer_for_switch); + } + BIN_X_PATTERN + { free($4); free($11); } + ; +VHDL_Inst_Disable: ATTRIBUTE INSTRUCTION_DISABLE OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + { + bsdl_flex_switch_buffer(priv_data->scanner, + priv_data->buffer_for_switch); + } + IDENTIFIER + { free($4); free($11); } + ; +VHDL_Inst_Guard : ATTRIBUTE INSTRUCTION_GUARD OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + { + bsdl_flex_switch_buffer(priv_data->scanner, + priv_data->buffer_for_switch); + } + IDENTIFIER + { free($4); free($11); } + ; +VHDL_Inst_Private: ATTRIBUTE INSTRUCTION_PRIVATE OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + { + bsdl_flex_switch_buffer(priv_data->scanner, + priv_data->buffer_for_switch); + } + Private_Opcode_List + { free($4); } + ; +Private_Opcode_List : Private_Opcode + | Private_Opcode_List COMMA Private_Opcode + | error + {Print_Error(priv_data, "Error in Opcode List"); + BUMP_ERROR; + YYABORT; } + ; +Private_Opcode : IDENTIFIER + { free($1); } + ; +VHDL_Inst_Usage : ATTRIBUTE INSTRUCTION_USAGE OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + {/* Syntax of string content to be changed in future */ + free($4); } + ; +VHDL_Inst_Sequence : ATTRIBUTE INSTRUCTION_SEQUENCE OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + {/* Syntax of string content to be determined in future */ + free($4); } + ; +VHDL_Idcode_Register: ATTRIBUTE IDCODE_REGISTER OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + { + bsdl_flex_switch_buffer(priv_data->scanner, + priv_data->buffer_for_switch); + } + BIN_X_PATTERN + { + bsdl_set_idcode(priv_data, $11); + free($4); + } + ; +VHDL_Usercode_Register: ATTRIBUTE USERCODE_REGISTER OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + { + bsdl_flex_switch_buffer(priv_data->scanner, + priv_data->buffer_for_switch); + } + BIN_X_PATTERN + { + bsdl_set_usercode(priv_data, $11); + free($4); + } + ; +VHDL_Register_Access: ATTRIBUTE REGISTER_ACCESS OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + { + bsdl_flex_switch_buffer(priv_data->scanner, + priv_data->buffer_for_switch); + } + Register_String + { free($4); } + ; +Register_String : Register_Assoc + | Register_String COMMA Register_Assoc + ; +Register_Assoc : Register_Decl LPAREN Reg_Opcode_List RPAREN + { bsdl_ac_apply_assoc(priv_data); } + ; +Register_Decl : Standard_Reg + { bsdl_ac_set_register(priv_data, $1, 0); } + | IDENTIFIER LBRACKET DECIMAL_NUMBER RBRACKET + { bsdl_ac_set_register(priv_data, $1, $3); } + ; +Standard_Reg : BOUNDARY + { $$ = strdup("BOUNDARY"); } + | BYPASS + { $$ = strdup("BYPASS"); } + | IDCODE + { $$ = strdup("IDCODE"); } + | USERCODE + { $$ = strdup("USERCODE"); } + | DEVICE_ID + { $$ = strdup("DEVICE_ID"); } + ; +Reg_Opcode_List : Reg_Opcode + | Reg_Opcode_List COMMA Reg_Opcode + ; +Standard_Inst : BOUNDARY + { $$ = strdup("BOUNDARY"); } + | BYPASS + { $$ = strdup("BYPASS"); } + | HIGHZ + { $$ = strdup("HIGHZ"); } + | IDCODE + { $$ = strdup("IDCODE"); } + | USERCODE + { $$ = strdup("USERCODE"); } + ; +Reg_Opcode : IDENTIFIER + { bsdl_ac_add_instruction(priv_data, $1); } + | Standard_Inst + { bsdl_ac_add_instruction(priv_data, $1); } + ; +VHDL_Boundary_Details: VHDL_Boundary_Detail + | VHDL_Boundary_Details VHDL_Boundary_Detail + ; +VHDL_Boundary_Detail: VHDL_Boundary_Cells + | VHDL_Boundary_Length + ; +VHDL_Boundary_Cells: ATTRIBUTE BOUNDARY_CELLS OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + { + bsdl_flex_switch_buffer(priv_data->scanner, + priv_data->buffer_for_switch); + } + BSDL_Cell_List + { free($4); } + ; +BSDL_Cell_List : BCell_Identifier + | BSDL_Cell_List COMMA BCell_Identifier + ; +BCell_Identifier : IDENTIFIER + { free($1); } + ; +VHDL_Boundary_Length: ATTRIBUTE BOUNDARY_LENGTH OF IDENTIFIER + COLON ENTITY IS DECIMAL_NUMBER SEMICOLON + { + bsdl_set_bsr_length(priv_data, $8); + free($4); + } + ; +VHDL_Boundary_Register: ATTRIBUTE BOUNDARY_REGISTER OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + { + bsdl_flex_switch_buffer(priv_data->scanner, + priv_data->buffer_for_switch); + } + BSDL_Cell_Table + { free($4); } + ; +BSDL_Cell_Table : Cell_Entry + | BSDL_Cell_Table COMMA Cell_Entry + | error + {Print_Error(priv_data, "Error in Boundary Cell description"); + BUMP_ERROR; YYABORT; } + ; +Cell_Entry : DECIMAL_NUMBER LPAREN Cell_Info RPAREN + { bsdl_ci_apply_cell_info(priv_data, $1); } + ; +Cell_Info : Cell_Spec + { bsdl_ci_no_disable(priv_data); } + | Cell_Spec COMMA Disable_Spec + ; +Cell_Spec : IDENTIFIER COMMA Port_Name COMMA Cell_Function + COMMA Safe_Value + { + free($1); + bsdl_ci_set_cell_spec(priv_data, $3, $5, $7); + } + ; +Port_Name : IDENTIFIER + { $$ = $1; } + | IDENTIFIER LPAREN DECIMAL_NUMBER RPAREN + { + Print_Warning(priv_data, "Port name index not supported in Boundary Cell description"); + $$ = NULL; + free($1); + } + | ASTERISK + { $$ = strdup("*"); } + ; +Cell_Function : INPUT + { $$ = INPUT; } + | OUTPUT2 + { $$ = OUTPUT2; } + | OUTPUT3 + { $$ = OUTPUT3; } + | CONTROL + { $$ = CONTROL; } + | CONTROLR + { $$ = CONTROLR; } + | INTERNAL + { $$ = INTERNAL; } + | CLOCK + { $$ = CLOCK; } + | BIDIR + { $$ = BIDIR; } + ; +Safe_Value : IDENTIFIER + { $$ = $1; } + | DECIMAL_NUMBER + { + char *tmp; + tmp = (char *)malloc(2); + snprintf(tmp, 2, "%i", $1); + tmp[1] = '\0'; + $$ = tmp; + } + ; +Disable_Spec : DECIMAL_NUMBER COMMA DECIMAL_NUMBER COMMA Disable_Value + { bsdl_ci_set_cell_spec_disable(priv_data, $1, $3, $5); } + ; +Disable_Value : Z + { $$ = Z; } + | WEAK0 + { $$ = WEAK0; } + | WEAK1 + { $$ = WEAK1; } + | PULL0 + { $$ = PULL0; } + | PULL1 + { $$ = PULL1; } + | KEEPER + { $$ = KEEPER; } + ; +VHDL_Design_Warning: /* Null Statement */ + | ATTRIBUTE DESIGN_WARNING OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + { free($4); } + ; +VHDL_Component_Conformance: ATTRIBUTE COMPONENT_CONFORMANCE OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + { free($4); } + ; +VHDL_Compliance_Patterns: ATTRIBUTE COMPLIANCE_PATTERNS OF IDENTIFIER + COLON ENTITY IS Quoted_String SEMICOLON + { + bsdl_flex_switch_buffer(priv_data->scanner, + priv_data->buffer_for_switch); + } + BSDL_Compliance_Pattern + { free($4); } + ; +BSDL_Compliance_Pattern: LPAREN Physical_Pin_List RPAREN + LPAREN BIN_X_PATTERN RPAREN + { free($5); } + ; +Quoted_String : QUOTED_STRING + {Make_String($1, priv_data->String_Val); + Init_Text(priv_data); + Store_Text(priv_data, priv_data->String_Val); + free($1); } + | Quoted_String CONCATENATE QUOTED_STRING + {Make_String($3, priv_data->String_Val); + Store_Text(priv_data, priv_data->String_Val); + free($3); } + ; +%% /* End rules, begin programs */ +/*----------------------------------------------------------------------*/ +static void Init_Text(parser_priv_t *priv_data) +{ + if (priv_data->len_buffer_for_switch == 0) { + priv_data->buffer_for_switch = (char *)malloc(160); + priv_data->len_buffer_for_switch = 160; + } + priv_data->buffer_for_switch[0] = '\0'; + priv_data->idx_to_buffer = 0; +} +/*----------------------------------------------------------------------*/ +static void Store_Text(parser_priv_t *priv_data, char *String) +{ /* Save characters from VHDL string in local string buffer. */ + size_t req_len; + + req_len = strlen(priv_data->buffer_for_switch) + strlen(String) + 1; + if (req_len > priv_data->len_buffer_for_switch) { + priv_data->buffer_for_switch = (char *)realloc(priv_data->buffer_for_switch, + req_len); + priv_data->len_buffer_for_switch = req_len; + } + strcpy(&(priv_data->buffer_for_switch[priv_data->idx_to_buffer]), String); + priv_data->idx_to_buffer += strlen(String); +} +/*----------------------------------------------------------------------*/ +static void Make_String(char *Source, char *Dest) +{ + char Ch; + for (Source++; Ch = *Source, (Ch != '"') && (Ch != '\n'); Source++, Dest++) + *Dest = *Source; + *Dest = '\0'; +} +/*----------------------------------------------------------------------*/ +static void Print_Error(parser_priv_t *priv_data, char *Errmess) +{ + if (priv_data->Reading_Package) + bsdl_msg(BSDL_MSG_ERR, "Error in Package %s, Line %d, %s.\n", + priv_data->Package_File_Name, + bsdl_flex_get_lineno(priv_data->scanner), + Errmess); + else + bsdl_msg(BSDL_MSG_ERR, "Error, Line %d, %s.\n", + bsdl_flex_get_lineno(priv_data->scanner), + Errmess); +} +/*----------------------------------------------------------------------*/ +static void Print_Warning(parser_priv_t *priv_data, char *Warnmess) +{ + if (priv_data->Reading_Package) + bsdl_msg(BSDL_MSG_WARN, "Warning in Package %s, Line %d, %s.\n", + priv_data->Package_File_Name, + bsdl_flex_get_lineno(priv_data->scanner), + Warnmess); + else + bsdl_msg(BSDL_MSG_WARN, "Warning, Line %d, %s.\n", + bsdl_flex_get_lineno(priv_data->scanner), + Warnmess); +} +/*----------------------------------------------------------------------*/ +static void Give_Up_And_Quit(parser_priv_t *priv_data) +{ + Print_Error(priv_data, "Too many errors"); +} +/*----------------------------------------------------------------------*/ +void yyerror(parser_priv_t *priv_data, const char *error_string) +{ +} +/*----------------------------------------------------------------------*/ +parser_priv_t *bsdl_parser_init(FILE *f) +{ + parser_priv_t *new_priv; + + if (!(new_priv = (parser_priv_t *)malloc(sizeof(parser_priv_t)))) { + bsdl_msg(BSDL_MSG_ERR, "Out of memory, %s line %i\n", __FILE__, __LINE__); + return NULL; + } + + new_priv->Reading_Package = 0; + new_priv->buffer_for_switch = NULL; + new_priv->len_buffer_for_switch = 0; + + if (!(new_priv->scanner = bsdl_flex_init(f))) { + free(new_priv); + new_priv = NULL; + } + + bsdl_sem_init(new_priv); + + return new_priv; +} +/*----------------------------------------------------------------------*/ +void bsdl_parser_deinit(parser_priv_t *priv_data) +{ + bsdl_sem_deinit(priv_data); + bsdl_flex_deinit(priv_data->scanner); + free(priv_data); +} diff --git a/jtag/src/bsdl/bsdl_flex.l b/jtag/src/bsdl/bsdl_flex.l new file mode 100644 index 00000000..c77077ac --- /dev/null +++ b/jtag/src/bsdl/bsdl_flex.l @@ -0,0 +1,557 @@ +/* + * $Id$ + * + * Original Lex source by Ken Parker, 1990 + * Extensions and adaptions for UrJTAG by Arnim Laeuger, 2007 + * + */ + +/*---------------------------------------------------------- + * + * Lex source for BSDL + * + *----------------------------------------------------------*/ +/* Date: 901003 */ + +/* + +Email header accompanying the original Yacc code: + +-----------------------------------8<-------------------------------------- + +Hello All, + +This is this first mailing of the BSDL* Version 0.0 parser specifications +we are sending to people who request it from our publicized E-Mail address; + + bsdl%hpmtlx@hplabs.HP.com + +You are free to redistribute this at will, but we feel that it would be +better if respondents asked for it directly so that their addresses can +be entered into our list for future mailings and updates. + +It would be helpful if you could confirm receipt of this transmission. +We also would be very interested to hear about your experiences with this +information and what you are planning to do with BSDL. + +Regards, + +Ken Parker +Hewlett-Packard Company + + +*Boundary-Scan Description Language - as documented in: + +"A Language for Describing Boundary-Scan Devices", K.P. Parker +and S. Oresjo, Proceedings 1990 International Test Conference, +Washington DC, pp 222-234 + + +- -----------------cut here--------------------------------------------------- + + +901004.0721 Hewlett-Packard Company +901016.1049 Manufacturing Test Division + P.O. Box 301 + Loveland, Colorado 80537 + USA + + October 1990 +Hello BSDL Parser Requestor, + + This Electronic Mail reply contains the computer specifications for +Hewlett-Packard's Version 0.0 BSDL parser. This section of the reply +explains the contents of the rest of this file. + +This file is composed of seven (7) parts: + + 1) How to use this file + + 2) UNIX* Lex source (lexicographical tokenizing rules) + + 3) UNIX* Yacc source (BNF-like syntax description) + + 4) A sample main program to recognize BSDL. + + 5) A BSDL description of the Texas Instruments 74bct8374 that is + recognized by the parser, for testing purposes. + + 6) The VHDL package STD_1149_1_1990 needed by this parser. + + 7) [added 901016] Porting experiences to other systems. + + +RECOMMENDATION: Save a copy of this file in archival storage before + processing it via the instructions below. This will + allow you to recover from errors, and allow you to + compare subsequently released data for changes. + +DISCLAIMERS: + +1. The IEEE 1149.1 Working Group has not endorsed BSDL Version 0.0 and + therefore no person may represent it as an IEEE standard or imply that + a resulting IEEE standard will be identical to it. + +2. The IEEE 1149.1 Working Group recognizes that BSDL Version 0.0 is a + well-conceived initiative that is likely to excelerate the creation + of tools that support the 1149.1 standard. As such, changes and + enhancements will be carefully considered so as not to needlessly + disrupt these development efforts. The overriding goal is the + ultimate success of the 1149.1 standard. + +LEGAL NOTICES: + + Hewlett-Packard Company makes no warranty of any kind with regard to + this information, including, but not limited to, the implied + waranties of merchantability and fitness for a particular purpose. + + Hewlett-Packard Company shall not be liable for errors contained + herein or direct, indirect, special, incidental, or consequential + damages in connection with the furnishing, performance, or use of + this material. + + +*UNIX is a trademark of AT&T in the USA and other countries. + +*/ + +%option bison-bridge +%option reentrant +%option prefix="bsdl" +%option outfile="lex.yy.c" + +%{ +/* Begin lex input specifications */ + +#include +#include + +#include "bsdl_bison.h" + +#include "bsdl.h" + +#define YY_EXTRA_TYPE scan_extra_t * + +static char *new_string(const char *); + +#define BINARY 0 +#define DECIMAL 1 +#define BIN_X 2 + +%} +%a 2800 +%e 1200 +%p 4700 +%n 520 +%k 140 +%o 3000 +%START RES BOU REG PAC +White [ \t\b\r]* +VHDL_Comment \-\-[^\n]* +Binary_Pattern [0-1]+ +Bin_X_Pattern [0-1X]+ +Digit [0-9] +Exponent [E][+-]?{Digit}+ +Real_Number {Digit}+[\.]{Digit}+{Exponent} +Decimal_Number {Digit}+ +Identifier [A-Z][A-Z0-9_]* +Quoted_String \"[^\"\n]*\" +Concatenate & +Single_Quote [\'] +Semicolon ; +Eol [\n] +Comma [,] +Lparen [\(] +Rparen [\)] +Lbracket [\[] +Rbracket [\]] +Colon_Equal \:\= +Colon [\:] +Period [\.] +Asterisk [\*] +Box [\<][\>] +Illegal [^A-Z0-9 \t\b\n\r\"\&\'\*\(\)\[\]\_\:\.\,\;\<\>] +Entity ENTITY +Port PORT +Generic GENERIC +Use USE +Attribute ATTRIBUTE +Is IS +Of OF +Constant CONSTANT +String STRING +End END +All ALL +Physical_Pin_Map PHYSICAL_PIN_MAP +Pin_Map PIN_MAP +Pin_Map_String PIN_MAP_STRING +True TRUE +False FALSE +Signal SIGNAL +Tap_Scan_In TAP_SCAN_IN +Tap_Scan_Out TAP_SCAN_OUT +Tap_Scan_Clock TAP_SCAN_CLOCK +Tap_Scan_Mode TAP_SCAN_MODE +Tap_Scan_Reset TAP_SCAN_RESET +Low LOW +Both BOTH +Out OUT +Inout INOUT +In IN +Buffer BUFFER +Linkage LINKAGE +Bit_Vector BIT_VECTOR +Bit BIT +To TO +Downto DOWNTO +Package PACKAGE +Body BODY +Type TYPE +Subtype SUBTYPE +Record RECORD +Array ARRAY +Positive POSITIVE +Range RANGE +Cell_Info CELL_INFO +Instruction_Length INSTRUCTION_LENGTH +Instruction_Opcode INSTRUCTION_OPCODE +Instruction_Capture INSTRUCTION_CAPTURE +Instruction_Disable INSTRUCTION_DISABLE +Instruction_Guard INSTRUCTION_GUARD +Instruction_Private INSTRUCTION_PRIVATE +Instruction_Usage INSTRUCTION_USAGE +Instruction_Sequence INSTRUCTION_SEQUENCE +Register_Access REGISTER_ACCESS +Boundary_Cells BOUNDARY_CELLS +Boundary_Length BOUNDARY_LENGTH +Boundary_Register BOUNDARY_REGISTER +Idcode_Register IDCODE_REGISTER +Usercode_Register USERCODE_REGISTER +Design_Warning DESIGN_WARNING +Boundary BOUNDARY +Bypass BYPASS +Highz HIGHZ +Idcode IDCODE +Device_Id DEVICE_ID +Usercode USERCODE +Input INPUT +Output2 OUTPUT2 +Output3 OUTPUT3 +Control CONTROL +Controlr CONTROLR +Internal INTERNAL +Clock CLOCK +Bidir BIDIR +Bidir_In BIDIR_IN +Bidir_Out BIDIR_OUT +Z Z +Weak0 WEAK0 +Weak1 WEAK1 +Pull0 PULL0 +Pull1 PULL1 +Keeper KEEPER +Extest EXTEST +Sample SAMPLE +Intest INTEST +Runbist RUNBIST +Pi PI +Po PO +Upd UPD +Cap CAP +X X +Zero ZERO +One ONE +Component_Conformance COMPONENT_CONFORMANCE +Port_Grouping PORT_GROUPING +Runbist_Execution RUNBIST_EXECUTION +Intest_Execution INTEST_EXECUTION +Bsdl_Extension BSDL_EXTENSION +Compliance_Patterns COMPLIANCE_PATTERNS +Observe_Only OBSERVE_ONLY +%% +{Entity} {return(ENTITY); } +{Port} {yyextra->Base = DECIMAL; /* Default number base */ + return(PORT); } +{Generic} {yyextra->Base = DECIMAL; return(GENERIC); } +{Use} {yyextra->Base = DECIMAL; return(USE); } +{Attribute} {yyextra->Base = DECIMAL; return(ATTRIBUTE); } +{Is} {return(IS); } +{Constant} {yyextra->Base = DECIMAL; return(CONSTANT); } +{String} {return(STRING); } +{End} {yyextra->Base = DECIMAL; + BEGIN INITIAL; /* Turn off start conditions */ + return(END); } +{All} {return(ALL); } +{Of} {return(OF); } +{Pin_Map} {return(PIN_MAP); } +{Physical_Pin_Map} {return(PHYSICAL_PIN_MAP); } +{Pin_Map_String} {return(PIN_MAP_STRING); } +{True} {return(TRUE); } +{False} {return(FALSE); } +{Signal} {return(SIGNAL); } +{Tap_Scan_In} {return(TAP_SCAN_IN); } +{Tap_Scan_Out} {return(TAP_SCAN_OUT); } +{Tap_Scan_Clock} {return(TAP_SCAN_CLOCK); } +{Tap_Scan_Mode} {return(TAP_SCAN_MODE); } +{Tap_Scan_Reset} {return(TAP_SCAN_RESET); } +{Low} {return(LOW); } +{Both} {return(BOTH); } +{In} {return(IN); } +{Out} {return(OUT); } +{Inout} {return(INOUT); } +{Buffer} {return(BUFFER); } +{Linkage} {return(LINKAGE); } +{Bit} {return(BIT); } +{Bit_Vector} {return(BIT_VECTOR); } +{To} {return(TO); } +{Downto} {return(DOWNTO); } +{Package} {return(PACKAGE); } +{Body} {return(BODY); } +{Type} {return(TYPE); } +{Subtype} {return(SUBTYPE); } +{Record} {return(RECORD); } +{Array} {yyextra->Base = DECIMAL; return(ARRAY); } +{Positive} {return(POSITIVE); } +{Range} {return(RANGE); } +{Cell_Info} {BEGIN PAC; return(CELL_INFO); } +{Instruction_Length} {return(INSTRUCTION_LENGTH); } +{Instruction_Opcode} {yyextra->Base = BINARY; /* Enable Binary Patterns */ + return(INSTRUCTION_OPCODE); } +{Instruction_Capture} {yyextra->Base = BIN_X; /* Enable Bin_X Patterns */ + return(INSTRUCTION_CAPTURE); } +{Instruction_Disable} {return(INSTRUCTION_DISABLE); } +{Instruction_Guard} {return(INSTRUCTION_GUARD); } +{Instruction_Private} {return(INSTRUCTION_PRIVATE); } +{Instruction_Usage} {return(INSTRUCTION_USAGE); } +{Instruction_Sequence} {return(INSTRUCTION_SEQUENCE); } +{Register_Access} {BEGIN REG; return(REGISTER_ACCESS); } +{Boundary_Cells} {return(BOUNDARY_CELLS); } +{Boundary_Length} {return(BOUNDARY_LENGTH); } +{Boundary_Register} {BEGIN BOU; return(BOUNDARY_REGISTER); } +{Idcode_Register} {yyextra->Base = BIN_X; return(IDCODE_REGISTER); } +{Usercode_Register} {yyextra->Base = BIN_X; return(USERCODE_REGISTER); } +{Design_Warning} {return(DESIGN_WARNING); } +{Component_Conformance} {return(COMPONENT_CONFORMANCE); } +{Port_Grouping} {return(PORT_GROUPING); } +{Runbist_Execution} {return(RUNBIST_EXECUTION); } +{Intest_Execution} {return(INTEST_EXECUTION); } +{Bsdl_Extension} {return(BSDL_EXTENSION); } +{Compliance_Patterns} {yyextra->Base = BIN_X; return(COMPLIANCE_PATTERNS); } +{Boundary} {return(BOUNDARY); } +{Bypass} {return(BYPASS); } +{Highz} {return(HIGHZ); } +{Idcode} {return(IDCODE); } +{Usercode} {return(USERCODE); } +{Device_Id} {return(DEVICE_ID); } +{Input} {return(INPUT); } +{Output2} {return(OUTPUT2); } +{Output3} {return(OUTPUT3); } +{Controlr} {return(CONTROLR); } +{Control} {return(CONTROL); } +{Internal} {return(INTERNAL); } +{Clock} {return(CLOCK); } +{Bidir} {return(BIDIR); } +{Bidir_In} {return(BIDIR_IN); } +{Bidir_Out} {return(BIDIR_OUT); } +{Extest} {return(EXTEST); } +{Sample} {return(SAMPLE); } +{Intest} {return(INTEST); } +{Runbist} {return(RUNBIST); } +{Observe_Only} {return(OBSERVE_ONLY); } +{Pi} {return(PI); } +{Po} {return(PO); } +{Upd} {return(UPD); } +{Cap} {return(CAP); } +{X} {return(X); } +{Zero} {return(ZERO); } +{One} {return(ONE); } +{Z} {return(Z); } +{Weak0} {return(WEAK0); } +{Weak1} {return(WEAK1); } +{Pull0} {return(PULL0); } +{Pull1} {return(PULL1); } +{Keeper} {return(KEEPER); } +{Eol} {yylineno++; /* Count lines */} +{Comma} {return(COMMA); } +{Lparen} {return(LPAREN);} +{Rparen} {return(RPAREN);} +{Period} {return(PERIOD); } +{Lbracket} {return(LBRACKET); } +{Rbracket} {return(RBRACKET); } +{Colon} {return(COLON); } +{Asterisk} {return(ASTERISK); } +{Box} {return(BOX); } +{Single_Quote} {yyextra->Base = BIN_X; return(SINGLE_QUOTE); } +{Colon_Equal} {return(COLON_EQUAL); } +{White} { /* Do Nothing on White Space */ } +{VHDL_Comment} { /* Do Nothing on Comments */ } +{Bin_X_Pattern} {if (yyextra->Base != BIN_X) REJECT; + yylval->str = new_string(yytext); + return(BIN_X_PATTERN);} +{Identifier} {yylval->str = new_string(yytext); + return(IDENTIFIER); } +{Quoted_String} {yylval->str = new_string(yytext); + return(QUOTED_STRING); } +{Binary_Pattern} {if (yyextra->Base != BINARY) REJECT; + yylval->str = new_string(yytext); + return(BINARY_PATTERN);} +{Decimal_Number} {if (yyextra->Base != DECIMAL) REJECT; + yylval->integer = atoi((char *)yytext); + return(DECIMAL_NUMBER);} +{Real_Number} {yylval->str = new_string(yytext); + return(REAL_NUMBER);} +{Concatenate} {return(CONCATENATE);} +{Semicolon} {return(SEMICOLON);} +{Illegal} {fprintf(stderr, + "Error: Illegal character %c (/%03o) at line %d:\n", + (char)yytext[yyleng-1], (int)yytext[yyleng-1], + yylineno); + yyextra->Compile_Errors++; + return(ILLEGAL); /* Will cause syntax error */} +<> { + yypop_buffer_state(yyscanner); + if ( !YY_CURRENT_BUFFER ) + yyterminate(); +} +%% +void *bsdl_flex_init(FILE *f) /* Change input file from STDIN to BSDL file */ +{ + scan_extra_t *extra; + yyscan_t scanner; + + /* get our scanner structure */ + if (yylex_init(&scanner) != 0) { + printf("%s: Scanner could not be initialized\n", "BSDL"); + return NULL; + } + yyset_in(f, scanner); + + if (!(extra = (scan_extra_t *)malloc(sizeof(scan_extra_t)))) { + printf("%s: Out of memory\n", "BSDL"); + yylex_destroy(scanner); + return NULL; + } + + extra->Compile_Errors = 0; + extra->Base = DECIMAL; + + yyset_extra(extra, scanner); + + return scanner; +} + +void bsdl_flex_deinit(void *scanner) +{ + free(yyget_extra(scanner)); + yylex_destroy(scanner); +} + + +int yywrap(yyscan_t scanner) +{ + if (yyget_in(scanner)) { + fclose(yyget_in(scanner)); + yyset_in(NULL, scanner); + } + return(1); +} + + +static char *new_string(const char *str) +{ + char *n_str; + size_t n_str_size; + + n_str_size = strlen(str) + 1; + if ((n_str = (char *)malloc(n_str_size))) { + strncpy(n_str, str, n_str_size-1); + n_str[n_str_size-1] = '\0'; /* set very last element to EOS */ + } else + printf("%s: Out of memory\n", "BSDL"); + + return(n_str); +} + + +void bsdl_flex_switch_file(yyscan_t scanner, const char *filename) +{ + scan_extra_t *extra; + FILE *f; + + /* file in current directory has precedence */ + f = fopen(filename, "r"); + if (!f) { + char db_path[] = JTAG_DATA_DIR; + char *db_file; + + if ((db_file = (char *)malloc(strlen(db_path) + + 1 + /* "/" */ + 4 + /* "bsdl" */ + 1 + /* "/" */ + strlen(filename) + + 1))) { + strcpy(db_file, db_path); + strcat(db_file, "/"); + strcat(db_file, "bsdl"); + strcat(db_file, "/"); + strcat(db_file, filename); + f = fopen(db_file, "r"); + + if (!f) + printf("%s: Cannot open file %s or %s.\n", "BSDL", filename, db_file); + free(db_file); + if (!f) + return; + } + } + + yypush_buffer_state(yy_create_buffer(f, YY_BUF_SIZE, scanner), scanner); + extra = yyget_extra(scanner); + yyset_lineno(1, scanner); +} + +void bsdl_flex_switch_buffer(yyscan_t scanner, const char *buffer) +{ + /* ugly, ulgy, ugly + prepare yyg for later use of YY_CURRENT_BUFFER */ + struct yyguts_t * yyg = (struct yyguts_t*)scanner; + int lineno; + +/* printf("bsdl_flex_switch_buffer(%s)\n", buffer);*/ + + lineno = yyget_lineno(scanner); + /* yy_scan_string() switches to the string buffer internally, + so we must save the current buffer state explicitly by pushing the stack + and setting top of stack to the current buffer state again. + yy_scan_string() can then savely switch YY_CURRENT_BUFFER to the string buffer. + yypop_buffer_state() will delete the string buffer afterwards and pop the saved + current buffer state. */ + yypush_buffer_state(YY_CURRENT_BUFFER, scanner); + yy_scan_string(buffer, scanner); + yyset_lineno(lineno, scanner); +} + +int bsdl_flex_get_compile_errors(yyscan_t scanner) +{ + scan_extra_t *extra = yyget_extra(scanner); + return extra->Compile_Errors; +} + +static void bsdl_flex_set_compile_errors(int n, yyscan_t scanner) +{ + scan_extra_t *extra = yyget_extra(scanner); + extra->Compile_Errors = n; +} + +int bsdl_flex_postinc_compile_errors(yyscan_t scanner) +{ + int errors = bsdl_flex_get_compile_errors(scanner); + + bsdl_flex_set_compile_errors(errors+1, scanner); + return errors; +} + +int bsdl_flex_get_lineno(yyscan_t scanner) +{ + return yyget_lineno(scanner); +} diff --git a/jtag/src/bsdl/bsdl_sem.c b/jtag/src/bsdl/bsdl_sem.c new file mode 100644 index 00000000..51c71e0b --- /dev/null +++ b/jtag/src/bsdl/bsdl_sem.c @@ -0,0 +1,770 @@ +/* + * $Id$ + * + * Copyright (C) 2007, 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 , 2007. + * + * This file contains semantic actions that are called by the bison + * parser. They interface between the parser and the jtag application. + * + */ + +#include +#include +#include + +#include +#include + +#include "bsdl_bison.h" + +#include "bsdl.h" + + +/***************************************************************************** + * void print_cmd(char **cmd) + * + * Prints the strings in array cmd until NULL is encountered. + * + * Parameters + * cmd : array of strings to print, terminated by NULL + * + * Returns + * void + ****************************************************************************/ +static void print_cmd(char **cmd) +{ + int idx = 0; + char *elem; + + while ((elem = cmd[idx])) { + printf(" %s", elem); + idx++; + } + printf("\n"); +} + + +/***************************************************************************** + * void bsdl_sem_init(parser_priv_t *priv) + * + * Performs initialization of data structures for the semantic action + * routines. + * + * Parameters + * priv : private data container for parser related tasks + * + * Returns + * void + ****************************************************************************/ +void bsdl_sem_init(parser_priv_t *priv) +{ + struct access_data *ad = &(priv->jtag_ctrl.access_data); + + ad->ainfo_list = NULL; + ad->instr_list = NULL; + + priv->jtag_ctrl.instr_list = NULL; +} + + +/***************************************************************************** + * void free_instr_list(struct instr_elem *il) + * + * Deallocates the given list of instr_elem. + * + * Parameters + * il : first instr_elem to deallocate + * + * Returns + * void + ****************************************************************************/ +static void free_instr_list(struct instr_elem *il) +{ + if (il) { + if (il->instr) + free(il->instr); + if (il->opcode) + free(il->opcode); + free_instr_list(il->next); + free(il); + } +} + + +/***************************************************************************** + * void free_ainfo_list(struct ainfo_elem *ai) + * + * Deallocates the given list of ainfo_elem. + * + * Parameters + * ai : first ainfo_elem to deallocate + * + * Returns + * void + ****************************************************************************/ +static void free_ainfo_list(struct ainfo_elem *ai) +{ + if (ai) { + if (ai->reg) + free(ai->reg); + free_instr_list(ai->instr_list); + free_ainfo_list(ai->next); + free(ai); + } +} + + +/***************************************************************************** + * void bsdl_sem_deinit(parser_priv_t *priv) + * + * Performs deinitialization of data structures for the semantic action + * routines. + * + * Parameters + * priv : private data container for parser related tasks + * + * Returns + * void + ****************************************************************************/ +void bsdl_sem_deinit(parser_priv_t *priv) +{ + struct access_data *ad = &(priv->jtag_ctrl.access_data); + + free_ainfo_list(ad->ainfo_list); + + free_instr_list(priv->jtag_ctrl.instr_list); +} + + +/***************************************************************************** + * void bsdl_set_entity(parser_priv_t *priv, char *entityname) + * + * Applies the entity name from BSDL as the part name. + * + * Parameters + * priv : private data container for parser related tasks + * entityname : entity name string, memory gets free'd + * + * Returns + * void + ****************************************************************************/ +void bsdl_set_entity(parser_priv_t *priv, char *entityname) +{ + if (priv->jtag_ctrl.mode >= 1) { + strncpy(priv->jtag_ctrl.part->part, entityname, MAXLEN_PART); + priv->jtag_ctrl.part->part[MAXLEN_PART] = '\0'; + } + + free(entityname); +} + + +/***************************************************************************** + * void bsdl_set_instruction_length(parser_priv_t *priv, int len) + * + * Sets the specified length of the instruction register via shell command + * instruction length + * + * Parameters + * priv : private data container for parser related tasks + * len : number of bits (= length) of instruction register + ****************************************************************************/ +void bsdl_set_instruction_length(parser_priv_t *priv, int len) +{ + if (priv->jtag_ctrl.mode >= 0) { + char lenstring[6]; + char *cmd[] = {"instruction", + "length", + lenstring, + NULL}; + + snprintf(lenstring, 6, "%i", len); + lenstring[5] = '\0'; + + if (priv->jtag_ctrl.mode >= 1) + cmd_run(cmd); + else + print_cmd(cmd); + } +} + + +/***************************************************************************** + * void bsdl_add_pin(parser_priv_t *priv, char *pin) + * + * Adds the specified pin name as a signal via shell command + * signal + * + * Parameters + * priv : private data container for parser related tasks + * pin : name of the new pin, memory gets free'd + * + * Returns + * void + ****************************************************************************/ +void bsdl_add_pin(parser_priv_t *priv, char *pin) +{ + if (priv->jtag_ctrl.mode >= 0) { + char *cmd[] = {"signal", + pin, + NULL}; + + if (priv->jtag_ctrl.mode >= 1) + cmd_run(cmd); + else + print_cmd(cmd); + } + + free(pin); +} + + +/***************************************************************************** + * void create_register(parser_priv_t *priv, char *reg_name, size_t len) + * + * Generic function to create a jtag register via shell command + * register + * + * Parameters + * priv : private data container for parser related tasks + * reg_name : name of the new register + * len : number of bits (= length) of new register + * + * Returns + * void + ****************************************************************************/ +static void create_register(parser_priv_t *priv, char *reg_name, size_t len) +{ + if (priv->jtag_ctrl.mode >= 0) { + const size_t str_len = 10; + char len_str[str_len+1]; + char *cmd[] = {"register", + reg_name, + len_str, + NULL}; + + /* convert length information to string */ + snprintf(len_str, str_len, "%i", len); + + if (priv->jtag_ctrl.mode >= 1) + cmd_run(cmd); + else + print_cmd(cmd); + } +} + + +/***************************************************************************** + * void bsdl_set_idcode(parser_priv_t *priv, char *idcode) + * + * Stores the specified IDCODE of the device for later use and creates + * the DIR register. + * + * Parameters + * priv : private data container for parser related tasks + * idcode : string containing the device's IDCODE + * + * Returns + * void + ****************************************************************************/ +void bsdl_set_idcode(parser_priv_t *priv, char *idcode) +{ + priv->jtag_ctrl.idcode = idcode; + + create_register(priv, "DIR", strlen(idcode)); +} + + +/***************************************************************************** + * void bsdl_set_usercode(parser_priv_t *priv, char *usercode) + * + * Creates the USERCODE register, the contents of the usercode string is + * ignored. + * + * Parameters + * priv : private data container for parser related tasks + * usercode : string containing the device's USERCODE, memory gets free'd + * + * Returns + * void + ****************************************************************************/ +void bsdl_set_usercode(parser_priv_t *priv, char *usercode) +{ + create_register(priv, "USERCODE", strlen(usercode)); + + /* we're not interested in the usercode value at all */ + free(usercode); +} + + +/***************************************************************************** + * void bsdl_add_instruction(parser_priv_t *priv, char *instr, char *opcode) + * + * Converts the instruction specification into a member of the main + * list of instructions at priv->jtag_ctrl.instr_list. + * + * Parameters + * priv : private data container for parser related tasks + * instr : instruction name + * opcode : instruction opcode + * + * Returns + * void + ****************************************************************************/ +void bsdl_add_instruction(parser_priv_t *priv, char *instr, char *opcode) +{ + struct instr_elem *new_instr; + + new_instr = (struct instr_elem *)malloc(sizeof(struct instr_elem)); + if (new_instr) { + new_instr->next = NULL; + new_instr->instr = instr; + new_instr->opcode = opcode; + + if (priv->jtag_ctrl.instr_list) { + struct instr_elem *il = priv->jtag_ctrl.instr_list; + + while (il->next) + il = il->next; + + il->next = new_instr; + } else + priv->jtag_ctrl.instr_list = new_instr; + } else + bsdl_msg(BSDL_MSG_ERR, "Out of memory, %s line %i\n", __FILE__, __LINE__); +} + + +/***************************************************************************** + * void bsdl_set_bsr_length(parser_priv_t *priv, int len) + * + * Creates the BSR register based on the specified length. + * + * Parameters + * priv : private data container for parser related tasks + * len : number of bits (= length) of BSR register + * + * Returns + * void + ****************************************************************************/ +void bsdl_set_bsr_length(parser_priv_t *priv, int len) +{ + create_register(priv, "BSR", len); +} + + +/***************************************************************************** + * Cell Info management function + * void bsdl_ci_no_disable(parser_priv_t *priv) + * + * Tracks that there is no disable term for the current cell info. + * + * Parameters + * priv : private data container for parser related tasks + * + * Returns + * void + ****************************************************************************/ +void bsdl_ci_no_disable(parser_priv_t *priv) +{ + priv->jtag_ctrl.cell_info.ctrl_bit_num = -1; +} + + +/***************************************************************************** + * Cell Info management function + * void bsdl_ci_set_cell_spec(parser_priv_t *priv, + * char *port_name, int function, char *safe_value) + * + * Sets the specified values of the current cell_spec (without disable term) + * to the variables for temporary storage of these information elements. + * + * Parameters + * priv : private data container for parser related tasks + * port_name : port name this spec applies to + * function : cell function indentificator + * safe_value : safe value for initialization of this cell + * + * Returns + * void + ****************************************************************************/ +void bsdl_ci_set_cell_spec(parser_priv_t *priv, + char *port_name, int function, char *safe_value) +{ + struct cell_info *ci = &(priv->jtag_ctrl.cell_info); + + ci->port_name = port_name; + ci->cell_function = function; + ci->basic_safe_value = safe_value; +} + + +/***************************************************************************** + * Cell Info management function + * void bsdl_ci_set_cell_spec_disable(parser_priv_t *priv, + * int ctrl_bit_num, int safe_value, int disable_value) + * + * Applies the disable specification of the current cell spec to the variables + * for temporary storage of these information elements. + * + * Parameters + * priv : private data container for parser related tasks + * ctrl_bit_num : bit number of related control cell + * safe_value : safe value for initialization of this cell + * disable_value : currently ignored + * + * Returns + * void + ****************************************************************************/ +void bsdl_ci_set_cell_spec_disable(parser_priv_t *priv, + int ctrl_bit_num, int safe_value, int disable_value) +{ + struct cell_info *ci = &(priv->jtag_ctrl.cell_info); + + ci->ctrl_bit_num = ctrl_bit_num; + ci->disable_safe_value = safe_value; + /* disable value is ignored at the moment */ +} + + +/***************************************************************************** + * Cell Info management function + * void bsdl_ci_apply_cell_info(parser_priv_t *priv, int bit_num) + * + * Creates a BSR cell from the temporary storage variables via shell command + * bit [ Z] + * + * Parameters + * priv : private data container for parser related tasks + * bit_num : bit number of current cell + * + * Returns + * void + ****************************************************************************/ +void bsdl_ci_apply_cell_info(parser_priv_t *priv, int bit_num) +{ + struct cell_info *ci = &(priv->jtag_ctrl.cell_info); + + ci->bit_num = bit_num; + + if (priv->jtag_ctrl.mode >= 0) { + const size_t str_len = 10; + char bit_num_str[str_len+1]; + char ctrl_bit_num_str[str_len+1]; + char disable_safe_value_str[str_len+1]; + char *cmd[] = {"bit", + bit_num_str, + NULL, + NULL, + NULL, + ctrl_bit_num_str, + disable_safe_value_str, + "Z", + NULL}; + + /* convert bit number to string */ + snprintf(bit_num_str, str_len, "%i", ci->bit_num); + bit_num_str[str_len] = '\0'; + /* convert cell function from BSDL token to jtag syntax */ + switch (ci->cell_function) { + case INTERNAL: + /* fall through */ + case OUTPUT2: + /* fall through */ + case OUTPUT3: + cmd[2] = "O"; + break; + case INPUT: + /* fall through */ + case CLOCK: + cmd[2] = "I"; + break; + case CONTROL: + /* fall through */ + case CONTROLR: + cmd[2] = "C"; + break; + case BIDIR: + cmd[2] = "B"; + break; + default: + /* spoil command */ + cmd[2] = "?"; + break; + } + /* convert basic safe value */ + cmd[3] = strcasecmp(ci->basic_safe_value, "x") == 0 ? "?" : ci->basic_safe_value; + /* apply port name */ + cmd[4] = ci->port_name; + + /* add disable spec if present */ + if (ci->ctrl_bit_num >= 0) { + /* convert bit number to string */ + snprintf(ctrl_bit_num_str, str_len, "%i", ci->ctrl_bit_num); + ctrl_bit_num_str[str_len] = '\0'; + /* convert disable safe value to string */ + snprintf(disable_safe_value_str, str_len, "%i", ci->disable_safe_value); + disable_safe_value_str[str_len] = '\0'; + } else + /* stop command procssing here */ + cmd[5] = NULL; + + if (priv->jtag_ctrl.mode >= 1) + cmd_run(cmd); + else + print_cmd(cmd); + } + + /* free malloc'ed memory */ + if (ci->port_name) + free(ci->port_name); + if (ci->basic_safe_value) + free(ci->basic_safe_value); +} + + +/***************************************************************************** + * Register Access management function + * void bsdl_ac_set_register(parser_priv_t *priv, char *reg, int reg_len) + * + * Stores the register specification values for the current register access + * specification in the temporary storage region for later usage. + * + * Parameters + * priv : private data container for parser related tasks + * reg : register name + * reg_len : optional register length + * + * Returns + * void + ****************************************************************************/ +void bsdl_ac_set_register(parser_priv_t *priv, char *reg, int reg_len) +{ + struct access_data *ad = &(priv->jtag_ctrl.access_data); + + ad->reg = reg; + ad->reg_len = reg_len; +} + + +/***************************************************************************** + * Register Access management function + * void bsdl_ac_add_instruction(parser_priv_t *priv, char *instr) + * + * Appends the specified instruction to the list of instructions for the + * current register access specification in the temporary storage region + * for later usage. + * + * Parameters + * priv : private data container for parser related tasks + * instr : instruction name + * + * Returns + * void + ****************************************************************************/ +void bsdl_ac_add_instruction(parser_priv_t *priv, char *instr) +{ + struct access_data *ad = &(priv->jtag_ctrl.access_data); + struct instr_elem *new_instr; + + new_instr = (struct instr_elem *)malloc(sizeof(struct instr_elem)); + if (new_instr) { + new_instr->next = NULL; + new_instr->instr = instr; + new_instr->opcode = NULL; + + if (ad->instr_list) { + struct instr_elem *il = ad->instr_list; + + while (il->next) + il = il->next; + + il->next = new_instr; + } else + ad->instr_list = new_instr; + } else + bsdl_msg(BSDL_MSG_ERR, "Out of memory, %s line %i\n", __FILE__, __LINE__); +} + + +/***************************************************************************** + * Register Access management function + * void bsdl_ac_apply_assoc(parser_priv_t *priv) + * + * Appends the collected register access specification from the temporary + * storage region to the main ainfo list. + * + * Parameters + * priv : private data container for parser related tasks + * + * Returns + * void + ****************************************************************************/ +void bsdl_ac_apply_assoc(parser_priv_t *priv) +{ + struct access_data *ad = &(priv->jtag_ctrl.access_data); + struct ainfo_elem *new_ainfo; + + new_ainfo = (struct ainfo_elem *)malloc(sizeof(struct ainfo_elem)); + if (new_ainfo) { + new_ainfo->next = NULL; + new_ainfo->reg = ad->reg; + new_ainfo->reg_len = ad->reg_len; + new_ainfo->instr_list = ad->instr_list; + + if (ad->ainfo_list) { + struct ainfo_elem *ai = ad->ainfo_list; + + while (ai->next) + ai = ai->next; + + ai->next = new_ainfo; + } else + ad->ainfo_list = new_ainfo; + } else + bsdl_msg(BSDL_MSG_ERR, "Out of memory, %s line %i\n", __FILE__, __LINE__); + + /* clean up obsolete temporary entries */ + ad->reg = NULL; + ad->reg_len = 0; + ad->instr_list = NULL; +} + + +/***************************************************************************** + * Register Access management function + * void bsdl_ac_finalize(parser_priv_t *priv) + * + * Runs through the main instruction list and builds the instruction/register + * association for each instruction from the register access specifications + * via shell command + * instruction + * + * Additional register are created on the fly: + * - standard registers that haven't been created so far + * - non-standard registers encountered in register access specs + * + * Mandatory instruction/register associations are generated also in + * absence of a related register access specification (such specs are + * optional in the BSDL standard). + * + * Parameters + * priv : private data container for parser related tasks + * + * Returns + * void + ****************************************************************************/ +void bsdl_ac_finalize(parser_priv_t *priv) +{ + /* ensure that all mandatory registers are created prior to + handling the instruction/register associations + + BOUNDARY/BSR has been generated during the parsing process + + DEVICE_ID/DIR has been generated during the parsing process + */ + /* we need a BYPASS register */ + create_register(priv, "BYPASS", 1); + + if (priv->jtag_ctrl.mode >= 0) { + struct ainfo_elem *ai; + struct instr_elem *cinst; + + /* next scan through all register_access definitions and create + the non-standard registers */ + ai = priv->jtag_ctrl.access_data.ainfo_list; + while (ai) { + int is_std = 0; + + if (strcasecmp(ai->reg, "BOUNDARY" ) == 0) is_std = 1; + if (strcasecmp(ai->reg, "BYPASS" ) == 0) is_std = 1; + if (strcasecmp(ai->reg, "DEVICE_ID") == 0) is_std = 1; + if (strcasecmp(ai->reg, "USERCODE" ) == 0) is_std = 1; + + if (!is_std) + create_register(priv, ai->reg, ai->reg_len); + + ai = ai->next; + } + + + /* next scan through all instruction/opcode definitions and resolve + the instruction/register associations for these */ + cinst = priv->jtag_ctrl.instr_list; + while (cinst) { + char *reg_name = NULL; + char *instr_name = NULL; + + /* now see which of the register_access elements matches this instruction */ + ai = priv->jtag_ctrl.access_data.ainfo_list; + while (ai && (reg_name == NULL)) { + struct instr_elem *tinst = ai->instr_list; + + while (tinst && (reg_name == NULL)) { + if (strcasecmp(tinst->instr, cinst->instr) == 0) { + /* found the instruction inside the current access info, + now set the register name + map some standard register names to different internal names*/ + if (strcasecmp(ai->reg, "BOUNDARY") == 0) reg_name = "BSR"; + else if (strcasecmp(ai->reg, "DEVICE_ID") == 0) reg_name = "DIR"; + else reg_name = ai->reg; + } + + tinst = tinst->next; + } + + ai = ai->next; + } + + if (reg_name == NULL) { + /* BSDL file didn't specify an explicit register_access definition + if we're looking at a standard mandatory instruction, we should + build the association ourselves */ + if (strcasecmp(cinst->instr, "BYPASS" ) == 0) reg_name = "BYPASS"; + else if (strcasecmp(cinst->instr, "CLAMP" ) == 0) reg_name = "BYPASS"; + else if (strcasecmp(cinst->instr, "EXTEST" ) == 0) reg_name = "BSR"; + else if (strcasecmp(cinst->instr, "HIGHZ" ) == 0) reg_name = "BYPASS"; + else if (strcasecmp(cinst->instr, "IDCODE" ) == 0) reg_name = "DIR"; + else if (strcasecmp(cinst->instr, "INTEST" ) == 0) reg_name = "BSR"; + else if (strcasecmp(cinst->instr, "PRELOAD" ) == 0) reg_name = "BSR"; + else if (strcasecmp(cinst->instr, "SAMPLE" ) == 0) reg_name = "BSR"; + else if (strcasecmp(cinst->instr, "USERCODE") == 0) reg_name = "USERCODE"; + } + + if (strcasecmp(cinst->instr, "SAMPLE" ) == 0) + instr_name = "SAMPLE/PRELOAD"; + else + instr_name = cinst->instr; + + if (reg_name) { + char *cmd[] = {"instruction", + instr_name, + cinst->opcode, + reg_name, + NULL}; + + if (priv->jtag_ctrl.mode >= 1) + cmd_run(cmd); + else + print_cmd(cmd); + } + + cinst = cinst->next; + } + } +} diff --git a/jtag/src/cmd/Makefile.am b/jtag/src/cmd/Makefile.am index cc9996d7..1891beb7 100644 --- a/jtag/src/cmd/Makefile.am +++ b/jtag/src/cmd/Makefile.am @@ -56,6 +56,7 @@ libcmd_a_SOURCES = \ script.c \ include.c \ cmd.c \ - svf.c + svf.c \ + bsdl.c INCLUDES = -DJTAG_DATA_DIR=\"$(pkgdatadir)\" diff --git a/jtag/src/cmd/bsdl.c b/jtag/src/cmd/bsdl.c new file mode 100644 index 00000000..6349d906 --- /dev/null +++ b/jtag/src/cmd/bsdl.c @@ -0,0 +1,115 @@ +/* + * $Id$ + * + * Copyright (C) 2007, 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 , 2007. + * + */ + + +#include "sysdep.h" + +#include +#include + +#include +#include + +static int +cmd_bsdl_run( char *params[] ) +{ + int num_params, result = -1; + + num_params = cmd_params(params); + if (num_params >= 2) { + if (strcmp(params[1], "test") == 0) { + int debug_save; + + debug_save = bsdl_debug; + bsdl_debug = 1; + if (num_params == 3) { + result = bsdl_read_file(params[2], -1, NULL) >= 0 ? 1 : -1; + } else if (num_params == 2) { + bsdl_scan_files(NULL, -1); + result = 1; + } + bsdl_debug = debug_save; + } + + if (strcmp(params[1], "dump") == 0) { + if (num_params == 3) { + result = bsdl_read_file(params[2], 0, NULL) >= 0 ? 1 : -1; + } else if (num_params == 2) { + bsdl_scan_files(NULL, 0); + result = 1; + } + } + + if (num_params == 3) { + if (strcmp(params[1], "path") == 0) { + bsdl_set_path(params[2]); + result = 1; + } + + if (strcmp(params[1], "debug") == 0) { + if (strcmp(params[2], "on") == 0) { + bsdl_debug = 1; + result = 1; + } + if (strcmp(params[2], "off") == 0) { + bsdl_debug = 0; + result = 1; + } + } + } + } + + return result; +} + + +static void +cmd_bsdl_help( void ) +{ + printf( _( + "Usage: %s path PATHLIST\n" + "Usage: %s test [FILE]\n" + "Usage: %s dump [FILE]\n" + "Usage: %s debug on|off\n" + "Manage BSDL files\n" + "\n" + "PATHLIST semicolon separated list of directory paths to search for BSDL files\n" + "FILE file containing part description in BSDL format\n" + ), "bsdl", "bsdl", "bsdl", "bsdl" ); +} + +cmd_t cmd_bsdl = { + "bsdl", + N_("manage BSDL files"), + cmd_bsdl_help, + cmd_bsdl_run +}; + + +/* Emacs specific variables +;;; Local Variables: *** +;;; indent-tabs-mode:t *** +;;; tab-width:2 *** +;;; End: *** +*/ diff --git a/jtag/src/cmd/cmd.c b/jtag/src/cmd/cmd.c index 83b6a907..5a0f688a 100644 --- a/jtag/src/cmd/cmd.c +++ b/jtag/src/cmd/cmd.c @@ -64,6 +64,7 @@ extern cmd_t cmd_eraseflash; extern cmd_t cmd_script; extern cmd_t cmd_include; extern cmd_t cmd_svf; +extern cmd_t cmd_bsdl; extern cmd_t cmd_debug; const cmd_t *cmds[] = { @@ -100,6 +101,7 @@ const cmd_t *cmds[] = { &cmd_script, &cmd_include, &cmd_svf, + &cmd_bsdl, &cmd_debug, NULL /* last must be NULL */ }; diff --git a/jtag/src/detect.c b/jtag/src/detect.c index e24dc749..3cbae74e 100644 --- a/jtag/src/detect.c +++ b/jtag/src/detect.c @@ -31,6 +31,8 @@ #include +#include + #include "register.h" #include "tap.h" #include "cable.h" @@ -272,6 +274,10 @@ detect_parts( chain_t *chain, char *db_path ) if (did == br) continue; + chain->active_part = ps->len - 1; + + if (bsdl_scan_files(register_get_string( did ), 1) <= 0) { + /* find JTAG declarations for a part with id */ strcpy( data_path, db_path ); /* FIXME: Buffer overrun */ @@ -353,11 +359,12 @@ detect_parts( chain_t *chain, char *db_path ) printf( _(" Filename: %s\n"), data_path ); /* run JTAG declarations */ - chain->active_part = ps->len - 1; strcpy( part->manufacturer, manufacturer ); strcpy( part->part, partname ); strcpy( part->stepping, stepping ); cmd_run( cmd ); + } + if (part->active_instruction == NULL) part->active_instruction = part_find_instruction( part, "IDCODE" ); }