#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+
#include <urjtag/log.h>
#include "svf.h"
double dvalue;
char *cvalue;
int ivalue;
+ struct hexa_frag hexa_frag;
struct tdval tdval;
struct tcval *tcval;
}
-%token IDENTIFIER NUMBER HEXA_NUM VECTOR_STRING
+%token IDENTIFIER NUMBER HEXA_NUM_FRAGMENT VECTOR_STRING
%token EMPTY
%token ENDDR ENDIR
%token SVF_EOF 0 /* SVF_EOF must match bison's token YYEOF */
%type <dvalue> NUMBER
+%type <cvalue> HEXA_NUM_FRAGMENT
%type <tdval> runtest_clk_count
%type <token> runtest_run_state_opt
%type <token> runtest_end_state_opt
+%type <hexa_frag> hexa_num_sequence
%%
;
ths_opt_param
- : TDI HEXA_NUM
+ : TDI '(' hexa_num_sequence ')'
{
- priv_data->parser_params.ths_params.tdi = $<cvalue>2;
+ priv_data->parser_params.ths_params.tdi = $3.buf;
}
- | TDO HEXA_NUM
+ | TDO '(' hexa_num_sequence ')'
{
- priv_data->parser_params.ths_params.tdo = $<cvalue>2;
+ priv_data->parser_params.ths_params.tdo = $3.buf;
}
- | MASK HEXA_NUM
+ | MASK '(' hexa_num_sequence ')'
{
- priv_data->parser_params.ths_params.mask = $<cvalue>2;
+ priv_data->parser_params.ths_params.mask = $3.buf;
}
- | SMASK HEXA_NUM
+ | SMASK '(' hexa_num_sequence ')'
{
- priv_data->parser_params.ths_params.smask = $<cvalue>2;
+ priv_data->parser_params.ths_params.smask = $3.buf;
}
;
+hexa_num_sequence
+ : HEXA_NUM_FRAGMENT
+ {
+ $$.buf = $1;
+ $$.strlen = strlen ($1);
+ $$.buflen = $$.strlen + 1;
+ }
+ | hexa_num_sequence HEXA_NUM_FRAGMENT
+ {
+#define REALLOC_STEP (1 << 16)
+ size_t req_len = $1.strlen + strlen ($2);
+ if ($1.buflen <= req_len) {
+ size_t newlen = req_len - $1.buflen < REALLOC_STEP ?
+ $1.buflen + REALLOC_STEP : req_len + 1;
+ $1.buf = (char *)realloc ($1.buf, newlen);
+ $1.buflen = newlen;
+ }
+ if ($1.buf != NULL) {
+ strcat ($1.buf, $2);
+ $1.strlen += strlen ($2);
+ }
+ free ($2);
+ $$ = $1;
+ }
+;
+
stable_state
: RESET
| IDLE
yyerror (YYLTYPE *locp, urj_svf_parser_priv_t *priv_data, urj_chain_t *chain,
const char *error_string)
{
- urj_log (URJ_LOG_LEVEL_ERROR, "Error occurred for SVF command %s.\n",
- error_string);
+ urj_log (URJ_LOG_LEVEL_ERROR, "Error occurred for SVF command, line %d, column %d-%d:\n %s.\n",
+ locp->first_line, locp->first_column, locp->last_column, error_string);
}
#define YY_USER_INIT \
do { \
- yylloc->first_line = yylloc->last_line = yylloc->first_column = yylloc->last_column = 0; \
+ yylloc->first_line = yylloc->last_line = yylloc->first_column = yylloc->last_column = 1; \
} while (0)
%}
COMMENT (!.*)|("//".*)[^\n]
%s expect_vector
+%s expect_hexa_num_paren
+%s expect_hexa_num
%%
-{LETTER}+[0-9A-Za-z_]* {
+<INITIAL>{LETTER}+[0-9A-Za-z_]* {
/* token is a keyword or identifier */
int keyw;
keyw = map_keyw_ident(yylval, yytext);
/* enable detection of VECTOR_STRING when this is a PIO command */
- if (keyw == PIO) {
- BEGIN(expect_vector);
+ switch (keyw) {
+ case PIO:
+ BEGIN(expect_vector);
+ break;
+ case TDI:
+ case TDO:
+ case MASK:
+ case SMASK:
+ BEGIN(expect_hexa_num_paren);
+ break;
}
return(keyw);
} /* end of keyword or identifier */
-{DIGIT}+(\.{DIGIT}+)?([eE][-+]?{DIGIT}+)? {
+<INITIAL>{DIGIT}+(\.{DIGIT}+)?([eE][-+]?{DIGIT}+)? {
/* token is a real number */
char *real_string = strdup(yytext);
} /* end of real number */
-<expect_vector>"("{WSPACE}*[\n\rHhLlZzUuDdXx \t\r]+{WSPACE}*")" {
+<expect_vector>"("{WSPACE}*[\n\rHhLlZzUuDdXx \t]+{WSPACE}*")" {
/* There is an overlap of VECTOR_STRING and HEXA_NUM when the string
contains only 'd' or 'D'. To prevent complicated parsing rules,
the lexer is instructed to detect VECTOR_STRING only when a PIO
fix_yylloc_nl(yylloc, yytext, yyget_extra(yyscanner));
align_string(yytext);
- cstring = calloc(strlen(yytext) + 1, sizeof(char));
+ cstring = malloc(strlen(yytext) + 1);
strcpy(cstring, yytext);
yylval->cvalue = cstring;
return(VECTOR_STRING);
} /* end of vector string */
-"("{WSPACE}*[\n\rA-Fa-f0-9 \t\r]+{WSPACE}*")" {
- /* token is a hexadecimal value (2) */
+<expect_hexa_num>[A-Fa-f0-9 \n]{1,1024} {
+ /* HEXA_NUM_FRAGMENT is restricted in size to avoid excessive token length.
+ Utilizing the {n,m} regex operator is probably not the right way
+ to do this.
+ 1024 is chosen arbitrarily, increasing to e.g. 4096 enhances scanner
+ performance, trading off against huge table sizes.
+ This whole strategy needs to be revisited with support of flex experts.
+ */
char *cstring;
fix_yylloc_nl(yylloc, yytext, yyget_extra(yyscanner));
align_string(yytext);
- cstring = calloc(strlen(yytext) + 1, sizeof(char));
+ cstring = (char *)malloc(strlen(yytext) + 1);
strcpy(cstring, yytext);
yylval->cvalue = cstring;
- return(HEXA_NUM);
+ return(HEXA_NUM_FRAGMENT);
} /* end of hexadecimal value */
} /* end of comment */
-[()] {
- /* left or right parenthes */
+<INITIAL>"(" {
fix_yylloc(yylloc, yytext);
return(yytext[0]);
} /* end of left or right parenthesis */
+<expect_hexa_num_paren>"(" {
+ /* scanning until a left parenthesis under this start condition implicitly
+ skips whitespace that would have been attributed to HEXA_NUM_FRAGMENT
+ otherwise */
+ fix_yylloc(yylloc, yytext);
+ /* now hand over to HEXA_NUM_FRAGMENT */
+ BEGIN(expect_hexa_num);
+ return(yytext[0]);
+} /* end of left or right parenthesis */
+")" {
+ fix_yylloc(yylloc, yytext);
+ BEGIN(INITIAL);
+ return(yytext[0]);
+} /* end of left or right parenthesis */
+
\n {
/* token is a new line character */
; {
/* token is end of statement character */
- /* release expect_vector */
+ /* release start condition */
BEGIN(INITIAL);
fix_yylloc(yylloc, yytext);