diff --git a/urjtag/include/urjtag/data_register.h b/urjtag/include/urjtag/data_register.h index c69e696e..a148439d 100644 --- a/urjtag/include/urjtag/data_register.h +++ b/urjtag/include/urjtag/data_register.h @@ -40,4 +40,11 @@ struct urj_data_register urj_data_register_t *urj_part_data_register_alloc (const char *name, int len); void urj_part_data_register_free (urj_data_register_t *dr); +/** + * allocate a data register and initialize the relevant part parts + * + * @return URJ_STATUS_OK on success; URJ_STATUS_FAIL on error + */ +int urj_part_data_register_define (urj_part_t *part, const char *name, int len); + #endif /* URJ_DATA_REGISTER_H */ diff --git a/urjtag/include/urjtag/error.h b/urjtag/include/urjtag/error.h index 265b3a28..c954a6bd 100644 --- a/urjtag/include/urjtag/error.h +++ b/urjtag/include/urjtag/error.h @@ -25,6 +25,8 @@ #include +#include "log.h" + /** * Error types */ @@ -36,6 +38,8 @@ typedef enum urj_error { URJ_ERROR_INVALID, URJ_ERROR_NOTFOUND, URJ_ERROR_IO, /**< I/O error from OS */ + URJ_ERROR_NO_BUS_DRIVER, + URJ_ERROR_BUFFER_EXHAUSTED, } urj_error_t; /** Max length of message string that can be recorded. */ @@ -55,9 +59,12 @@ typedef struct urj_error_state { extern urj_error_state_t urj_error_state; /** - * Set error state. The macro interface allows for a stack of errors, where - * this macro would push an error. The implementation is free to maintain - * a stack of depth one. + * Descriptive string for error type + */ +extern const char *urj_error_string(urj_error_t error); + +/** + * Set error state. If the logging level is not SILENT, also logs the error. * * @param e urj_error_t value * @param ... consists of a printf argument set. It needs to start with a @@ -71,19 +78,21 @@ extern urj_error_state_t urj_error_state; urj_error_state.line = __LINE__; \ snprintf (urj_error_state.msg, sizeof urj_error_state.msg, \ __VA_ARGS__); \ + if (urj_log_state.level < URJ_LOG_LEVEL_SILENT) \ + { \ + urj_log(URJ_LOG_LEVEL_ERRORS, "%s:%d %s() %s: ", __FILE__, \ + __LINE__, __func__, urj_error_string(e)); \ + urj_log(URJ_LOG_LEVEL_ERRORS, __VA_ARGS__); \ + urj_log(URJ_LOG_LEVEL_ERRORS, "\n"); \ + } \ } while (0) /** - * The top of the error stack. The caller must not modify the returned struct. - */ -const urj_error_state_t *urj_error_get (void); -/** - * Pop the top off the error stack. - * @return #URJ_ERROR_OK if the bottom of the error stack is reached + * Reset the error state. */ -urj_error_t urj_error_get_reset (void); +void urj_error_reset (void); /** - * The top of the error state in human-readable form. + * The error state in human-readable form. * * This function is not reentrant. * diff --git a/urjtag/include/urjtag/log.h b/urjtag/include/urjtag/log.h new file mode 100644 index 00000000..e31b078c --- /dev/null +++ b/urjtag/include/urjtag/log.h @@ -0,0 +1,61 @@ +/* + * $Id: log.h 1519 2009-04-22 23:12:44Z rfhh $ + * + * Copyright (C) 2009, Rutger Hofman, VU Amsterdam + * + * 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. + * + */ + +#ifndef URJ_LOG_H +#define URJ_LOG_H + +#include "sysdep.h" + +#include + +/** + * Log levels + */ +typedef enum urj_log_level { + URJ_LOG_LEVEL_ALL, /**< every single bit as it is transmitted */ + URJ_LOG_LEVEL_COMM, /**< low level communication details */ + URJ_LOG_LEVEL_DEBUG, /**< more details of interest for developers */ + URJ_LOG_LEVEL_DETAIL, /**< verbose output */ + URJ_LOG_LEVEL_NORMAL, /**< just noteworthy info */ + URJ_LOG_LEVEL_WARNINGS, /**< unmissable warnings */ + URJ_LOG_LEVEL_ERRORS, /**< only fatal errors */ + URJ_LOG_LEVEL_SILENT, /**< suppress logging output */ +} urj_log_level_t; + +/** + * Log state. + */ +typedef struct urj_log_state { + urj_log_level_t level; /**< logging level */ + int (*out_vprintf) (const char *fmt, va_list ap); + int (*err_vprintf) (const char *fmt, va_list ap); +} urj_log_state_t; + +extern urj_log_state_t urj_log_state; + +int urj_log (urj_log_level_t level, const char *fmt, ...) +#ifdef __GNUC__ + __attribute__ ((format (printf, 2, 3))) +#endif + ; + +#endif /* URJ_LOG_H */ diff --git a/urjtag/src/bsdl/bsdl_sem.c b/urjtag/src/bsdl/bsdl_sem.c index 54095cb1..a67e8ebc 100644 --- a/urjtag/src/bsdl/bsdl_sem.c +++ b/urjtag/src/bsdl/bsdl_sem.c @@ -31,6 +31,9 @@ #include #include +#include +#include +#include #include "bsdl_sysdep.h" @@ -44,31 +47,6 @@ #include "dmalloc.h" #endif -/***************************************************************************** - * 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%s", idx > 0 ? " " : "", elem); - idx++; - } - printf ("\n"); -} - /***************************************************************************** * int urj_bsdl_set_instruction_length( urj_bsdl_jtag_ctrl_t *jc ) @@ -86,20 +64,11 @@ print_cmd (char **cmd) static int urj_bsdl_set_instruction_length (urj_bsdl_jtag_ctrl_t *jc) { - char lenstring[6]; - char *cmd[] = { "instruction", - "length", - lenstring, - NULL - }; - - snprintf (lenstring, 6, "%i", jc->instr_len); - lenstring[5] = '\0'; - if (jc->proc_mode & URJ_BSDL_MODE_INSTR_EXEC) - urj_cmd_run (jc->chain, cmd); + // @@@@ RFHH check result + (void) urj_part_instruction_length_set (jc->part, jc->instr_len); if (jc->proc_mode & URJ_BSDL_MODE_INSTR_PRINT) - print_cmd (cmd); + printf ("instruction %i\n", jc->instr_len); return 1; } @@ -132,10 +101,6 @@ urj_bsdl_emit_ports (urj_bsdl_jtag_ctrl_t *jc) char *port_string; int idx; int result = 0; - char *cmd[] = { "signal", - NULL, - NULL - }; while (pd) { @@ -152,8 +117,6 @@ urj_bsdl_emit_ports (urj_bsdl_jtag_ctrl_t *jc) str_len = name_len + 1 + 10 + 1 + 1; if ((port_string = malloc (str_len)) != NULL) { - cmd[1] = port_string; - for (idx = pd->low_idx; idx <= pd->high_idx; idx++) { if (pd->is_vector) @@ -164,9 +127,10 @@ urj_bsdl_emit_ports (urj_bsdl_jtag_ctrl_t *jc) port_string[str_len - 1] = '\0'; if (jc->proc_mode & URJ_BSDL_MODE_INSTR_EXEC) - urj_cmd_run (jc->chain, cmd); + // @@@@ RFHH check result + (void) urj_part_signal_define (jc->chain, port_string); if (jc->proc_mode & URJ_BSDL_MODE_INSTR_PRINT) - print_cmd (cmd); + printf ("signal %s\n", port_string); } free (port_string); @@ -206,24 +170,14 @@ urj_bsdl_emit_ports (urj_bsdl_jtag_ctrl_t *jc) static int create_register (urj_bsdl_jtag_ctrl_t *jc, char *reg_name, size_t len) { - const size_t str_len = 10; - char len_str[str_len + 1]; - char *cmd[] = { "register", - reg_name, - len_str, - NULL - }; if (urj_part_find_data_register (jc->part, reg_name)) return 1; - /* convert length information to string */ - snprintf (len_str, str_len, "%zu", len); - if (jc->proc_mode & URJ_BSDL_MODE_INSTR_EXEC) - urj_cmd_run (jc->chain, cmd); + urj_part_data_register_define (jc->part, reg_name, len); if (jc->proc_mode & URJ_BSDL_MODE_INSTR_PRINT) - print_cmd (cmd); + printf ("register %s %zd\n", reg_name, len); return 1; } @@ -300,6 +254,27 @@ urj_bsdl_set_bsr_length (urj_bsdl_jtag_ctrl_t *jc) } +static char +bsbit_type_char (int type) +{ + switch (type) + { + case URJ_BSBIT_INPUT: + return 'I'; + case URJ_BSBIT_OUTPUT: + return 'O'; + case URJ_BSBIT_CONTROL: + return 'C'; + case URJ_BSBIT_INTERNAL: + return 'X'; + case URJ_BSBIT_BIDIR: + return 'B'; + default: + return '?'; + } +} + + /***************************************************************************** * int urj_bsdl_process_cell_info( urj_bsdl_jtag_ctrl_t *jc ) * Cell Info management function @@ -318,26 +293,11 @@ static int urj_bsdl_process_cell_info (urj_bsdl_jtag_ctrl_t *jc) { urj_bsdl_cell_info_t *ci = jc->cell_info_first; - 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, - NULL, - disable_safe_value_str, - "Z", - NULL - }; + int type; + int safe; while (ci) { - /* 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) { @@ -346,55 +306,57 @@ urj_bsdl_process_cell_info (urj_bsdl_jtag_ctrl_t *jc) case OUTPUT2: /* fall through */ case OUTPUT3: - cmd[2] = "O"; + type = URJ_BSBIT_OUTPUT; break; case OBSERVE_ONLY: /* fall through */ case INPUT: /* fall through */ case CLOCK: - cmd[2] = "I"; + type = URJ_BSBIT_INPUT; break; case CONTROL: /* fall through */ case CONTROLR: - cmd[2] = "C"; + type = URJ_BSBIT_CONTROL; break; case BIDIR: - cmd[2] = "B"; + type = URJ_BSBIT_BIDIR; break; default: /* spoil command */ - cmd[2] = "?"; + type = -1; 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; + safe = strcasecmp (ci->basic_safe_value, "x") == 0 ? URJ_BSBIT_DONTCARE + : (ci->basic_safe_value[0] - '0'); - /* 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'; - cmd[5] = ctrl_bit_num_str; + if (jc->proc_mode & URJ_BSDL_MODE_INSTR_EXEC) + // @@@@ RFHH check result + (void)urj_part_bsbit_alloc_control (jc->chain, ci->bit_num, + ci->port_name, type, safe, + ci->ctrl_bit_num, + ci->disable_safe_value, + URJ_BSBIT_STATE_Z); + if (jc->proc_mode & URJ_BSDL_MODE_INSTR_PRINT) + printf ("bit %d %s %c %d %d %d %c\n", ci->bit_num, + ci->port_name, bsbit_type_char (type), safe, + ci->ctrl_bit_num, ci->disable_safe_value, + 'Z'); } else - /* stop command procssing here */ - cmd[5] = NULL; - - if (jc->proc_mode & URJ_BSDL_MODE_INSTR_EXEC) - urj_cmd_run (jc->chain, cmd); - if (jc->proc_mode & URJ_BSDL_MODE_INSTR_PRINT) - print_cmd (cmd); + { + if (jc->proc_mode & URJ_BSDL_MODE_INSTR_EXEC) + // @@@@ RFHH check result + (void)urj_part_bsbit_alloc (jc->chain, ci->bit_num, + ci->port_name, type, safe); + if (jc->proc_mode & URJ_BSDL_MODE_INSTR_PRINT) + printf ("bit %d %s %c %d\n", ci->bit_num, ci->port_name, + bsbit_type_char (type), safe); + } ci = ci->next; } @@ -531,17 +493,14 @@ urj_bsdl_process_register_access (urj_bsdl_jtag_ctrl_t *jc) if (reg_name) { - char *cmd[] = { "instruction", - instr_name, - cinst->opcode, - reg_name, - NULL - }; - if (jc->proc_mode & URJ_BSDL_MODE_INSTR_EXEC) - urj_cmd_run (jc->chain, cmd); + // @@@@ RFHH check result + // @@@@ RFHH check if jc->part equals chain_active_part + (void) urj_part_instruction_define (jc->part, instr_name, + cinst->opcode, reg_name); if (jc->proc_mode & URJ_BSDL_MODE_INSTR_PRINT) - print_cmd (cmd); + printf ("instruction %s %s %s\n", instr_name, cinst->opcode, + reg_name); } cinst = cinst->next; diff --git a/urjtag/src/cmd/cmd_instruction.c b/urjtag/src/cmd/cmd_instruction.c index d15750b1..8c1b82d1 100644 --- a/urjtag/src/cmd/cmd_instruction.c +++ b/urjtag/src/cmd/cmd_instruction.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -68,8 +69,7 @@ cmd_instruction_run (urj_chain_t *chain, char *params[]) if (urj_part_instruction_length_set (part, len) != URJ_STATUS_OK) { - printf ("%s\n", urj_error_describe()); - urj_error_get_reset(); + urj_error_reset(); } return 1; } @@ -81,8 +81,7 @@ cmd_instruction_run (urj_chain_t *chain, char *params[]) i = urj_part_instruction_define (part, params[1], params[2], params[3]); if (!i) { - printf ("%s\n", urj_error_describe()); - urj_error_get_reset(); + urj_error_reset(); return 1; } diff --git a/urjtag/src/cmd/cmd_register.c b/urjtag/src/cmd/cmd_register.c index fb502c98..5fb7bf43 100644 --- a/urjtag/src/cmd/cmd_register.c +++ b/urjtag/src/cmd/cmd_register.c @@ -57,42 +57,7 @@ cmd_register_run (urj_chain_t *chain, char *params[]) if (urj_cmd_get_number (params[2], &len)) return -1; - if (urj_part_find_data_register (part, params[1]) != NULL) - { - printf (_("Data register '%s' already defined\n"), params[1]); - return 1; - } - - dr = urj_part_data_register_alloc (params[1], len); - if (!dr) - { - printf (_("out of memory\n")); - return 1; - } - - dr->next = part->data_registers; - part->data_registers = dr; - - /* Boundary Scan Register */ - if (strcasecmp (dr->name, "BSR") == 0) - { - int i; - - part->boundary_length = len; - part->bsbits = malloc (part->boundary_length * sizeof *part->bsbits); - if (!part->bsbits) - { - printf (_("out of memory\n")); - return 1; - } - for (i = 0; i < part->boundary_length; i++) - part->bsbits[i] = NULL; - } - - /* Device Identification Register */ - if (strcasecmp (dr->name, "DIR") == 0) - urj_tap_register_init (dr->out, - urj_tap_register_get_string (part->id)); + (void) urj_part_data_register_define (part, params[1], len); return 1; } diff --git a/urjtag/src/flash/detectflash.c b/urjtag/src/flash/detectflash.c index 977b3c36..917e157d 100644 --- a/urjtag/src/flash/detectflash.c +++ b/urjtag/src/flash/detectflash.c @@ -32,6 +32,7 @@ #include #include +#include #include #include diff --git a/urjtag/src/global/urjtag.c b/urjtag/src/global/urjtag.c index 9b498a1c..f19a67eb 100644 --- a/urjtag/src/global/urjtag.c +++ b/urjtag/src/global/urjtag.c @@ -23,6 +23,9 @@ #include +#include + +#include #include #include @@ -30,20 +33,44 @@ urj_error_state_t urj_error_state; int urj_debug_mode = 0; int urj_big_endian = 0; -const urj_error_state_t * -urj_error_get (void) +static int stderr_vprintf (const char *fmt, va_list ap); + +urj_log_state_t urj_log_state = + { + .level = URJ_LOG_LEVEL_NORMAL, + .out_vprintf = vprintf, + .err_vprintf = stderr_vprintf, + }; + +static int +stderr_vprintf(const char *fmt, va_list ap) { - return &urj_error_state; + return vfprintf (stderr, fmt, ap); } -urj_error_t -urj_error_get_reset (void) +int +urj_log (urj_log_level_t level, const char *fmt, ...) { - urj_error_t e = urj_error_state.errnum; + va_list ap; + int r; - urj_error_state.errnum = URJ_ERROR_OK; + if (level < urj_log_state.level) + return 0; - return e; + va_start (ap, fmt); + if (level < URJ_LOG_LEVEL_WARNINGS) + r = urj_log_state.out_vprintf (fmt, ap); + else + r = urj_log_state.err_vprintf (fmt, ap); + va_end (ap); + + return r; +} + +void +urj_error_reset (void) +{ + urj_error_state.errnum = URJ_ERROR_OK; } const char * @@ -58,4 +85,19 @@ urj_error_describe (void) return msg; } - +const char * +urj_error_string (urj_error_t err) +{ + switch (err) + { + case URJ_ERROR_OK: return "no error"; + case URJ_ERROR_ALREADY: return "already defined"; + case URJ_ERROR_OUT_OF_MEMORY: return "out of memory"; + case URJ_ERROR_NO_ACTIVE_PART: return "no active part"; + case URJ_ERROR_INVALID: return "invalid parameter"; + case URJ_ERROR_NOTFOUND: return "not found"; + case URJ_ERROR_IO: return "I/O error from OS"; + case URJ_ERROR_NO_BUS_DRIVER: return "no bus driver"; + case URJ_ERROR_BUFFER_EXHAUSTED: return "buffer exhausted"; + } +} diff --git a/urjtag/src/part/data_register.c b/urjtag/src/part/data_register.c index 68266908..dd6fb39b 100644 --- a/urjtag/src/part/data_register.c +++ b/urjtag/src/part/data_register.c @@ -28,8 +28,10 @@ #include #include +#include #include #include +#include urj_data_register_t * urj_part_data_register_alloc (const char *name, int len) @@ -41,10 +43,15 @@ urj_part_data_register_alloc (const char *name, int len) dr = malloc (sizeof *dr); if (!dr) + { + urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "malloc(%zd) fails", + sizeof *dr); return NULL; + } if (strlen (name) > URJ_DATA_REGISTER_MAXLEN) - printf (_("Warning: Data register name too long\n")); + urj_log (URJ_LOG_LEVEL_WARNINGS, + _("Warning: Data register name too long\n")); strncpy (dr->name, name, URJ_DATA_REGISTER_MAXLEN); dr->name[URJ_DATA_REGISTER_MAXLEN] = '\0'; @@ -60,6 +67,7 @@ urj_part_data_register_alloc (const char *name, int len) } if (!dr->in || !dr->out) { + // retain error state free (dr->in); free (dr->out); free (dr->name); @@ -82,3 +90,47 @@ urj_part_data_register_free (urj_data_register_t *dr) urj_tap_register_free (dr->out); free (dr); } + +int +urj_part_data_register_define (urj_part_t *part, const char *name, int len) +{ + urj_data_register_t *dr; + + if (urj_part_find_data_register (part, name) != NULL) + { + urj_error_set (URJ_ERROR_ALREADY, + _("Data register '%s' already defined"), name); + return URJ_STATUS_FAIL; + } + + dr = urj_part_data_register_alloc (name, len); + if (!dr) + // retain error state + return URJ_STATUS_FAIL; + + dr->next = part->data_registers; + part->data_registers = dr; + + /* Boundary Scan Register */ + if (strcasecmp (dr->name, "BSR") == 0) + { + int i; + + part->boundary_length = len; + part->bsbits = malloc (part->boundary_length * sizeof *part->bsbits); + if (!part->bsbits) + { + urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "malloc(%zd) fails", + part->boundary_length * sizeof *part->bsbits); + return URJ_STATUS_FAIL; + } + for (i = 0; i < part->boundary_length; i++) + part->bsbits[i] = NULL; + } + + /* Device Identification Register */ + else if (strcasecmp (dr->name, "DIR") == 0) + urj_tap_register_init (dr->out, urj_tap_register_get_string (part->id)); + + return URJ_STATUS_OK; +} diff --git a/urjtag/src/svf/svf.c b/urjtag/src/svf/svf.c index db288fea..b5531d72 100644 --- a/urjtag/src/svf/svf.c +++ b/urjtag/src/svf/svf.c @@ -1165,13 +1165,7 @@ urj_svf_run (urj_chain_t *chain, FILE *SVF_FILE, int stop_on_mismatch, /* setup register SDR if not already existing */ if (!(priv.dr = urj_part_find_data_register (priv.part, "SDR"))) { - char *register_cmd[] = { "register", - "SDR", - "32", - NULL - }; - - if (urj_cmd_run (chain, register_cmd) < 1) + if (urj_part_data_register_define(priv.part, "SDR", 32) != URJ_STATUS_OK) return; if (!(priv.dr = urj_part_find_data_register (priv.part, "SDR"))) diff --git a/urjtag/src/svf/svf_flex.l b/urjtag/src/svf/svf_flex.l index c2acc100..228bd8f2 100644 --- a/urjtag/src/svf/svf_flex.l +++ b/urjtag/src/svf/svf_flex.l @@ -32,6 +32,7 @@ %{ #include +#include #include #include diff --git a/urjtag/src/tap/detect.c b/urjtag/src/tap/detect.c index 59990ca1..eb557b81 100644 --- a/urjtag/src/tap/detect.c +++ b/urjtag/src/tap/detect.c @@ -41,6 +41,7 @@ #include #include #include +#include #include struct id_record @@ -463,11 +464,7 @@ urj_tap_manual_add (urj_chain_t *chain, int instr_len) chain->active_part = chain->parts->len - 1; /* make the BR register available */ - cmd[0] = "register"; - cmd[1] = "BR"; - cmd[2] = "1"; - cmd[3] = NULL; - if (urj_cmd_run (chain, cmd) < 1) + if (urj_part_data_register_define (part, "BR", 1) != URJ_STATUS_OK) { printf (_("Error: could not set BR register")); return 0;