diff --git a/vpi/table_mod.c b/vpi/table_mod.c index 1a1d68a5f..ff2e09070 100644 --- a/vpi/table_mod.c +++ b/vpi/table_mod.c @@ -31,53 +31,6 @@ */ static unsigned table_model_debug = 0; -// HERE: Should these just be defines? -/* - * Define the allowed interpolation control values. - */ -typedef enum interp_type_e { - IVL_CLOSEST_POINT = 0, /* D */ - IVL_LINEAR_INTERP = 1, /* 1 - Default */ - IVL_QUADRATIC_INTERP = 2, /* 2 */ - IVL_CUBIC_INTERP = 3, /* 3 */ - IVL_IGNORE_COLUMN = 4 /* I */ -} interp_type_t; - -/* - * Define the allowed extrapolation control values. - */ -typedef enum extrap_type_e { - IVL_CONSTANT_EXTRAP = 0, /* C */ - IVL_LINEAR_EXTRAP = 1, /* L - Default */ - IVL_ERROR_EXTRAP = 2 /* E */ -} extrap_type_t; - -/* - * This structure is saved for each table model instance. - */ -typedef struct t_table_mod { - vpiHandle *indep; /* Independent variable arguments. */ - double *indep_val; /* Current independent variable values. */ - union { /* Data file or argument to get the data file. */ - char *name; - vpiHandle arg; - } file; - union { /* Control string argument. */ - struct { - char *interp; - char *extrap_low; - char *extrap_high; - } info; - vpiHandle arg; - } control; -// HERE need a pointer to the dependent data and the final table. - unsigned dims; /* The number of independent variables. */ - unsigned fields; /* The number of control fields. */ - unsigned depend; /* Where the dependent column is located. */ - char have_fname; /* Has the file name been allocated? */ - char have_ctl; /* Has the file name been allocated? */ -} s_table_mod, *p_table_mod; - static p_table_mod *tables = 0; static unsigned table_count = 0; @@ -382,7 +335,7 @@ static unsigned parse_extrap(vpiHandle callh, p_table_mod table, unsigned idx, static unsigned initialize_control_fields(vpiHandle callh, p_table_mod table, char *control) { - unsigned width, idx; + unsigned num_fields, num_ignore, idx; char *cp; /* If we need to fail these must be defined to zero until memory @@ -413,7 +366,7 @@ static unsigned initialize_control_fields(vpiHandle callh, p_table_mod table, vpi_printf("Control string dependent selector is " "invalid: %s.\n", cp); vpi_control(vpiFinish, 1); - return 0; + return 1; } val = strtoul(cp, &end, 10); assert(*end == 0); @@ -424,39 +377,41 @@ static unsigned initialize_control_fields(vpiHandle callh, p_table_mod table, vpi_printf("Control string dependent value is " "to large: %lu.\n", val); vpi_control(vpiFinish, 1); - return 0; + return 1; } table->depend = (unsigned) val; } else table->depend = 1; /* Find the number of interpolation/extrapolation control fields. */ - width = 1; + num_fields = 1; cp = control; while ((cp = index(cp, ','))) { cp += 1; - width += 1; + num_fields += 1; } + /* We must have at least as many control fields as dimensions. */ - if (width < table->dims) { + if (num_fields < table->dims) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("Not enough control field(s) (%u) for the dimension(s) " - "(%u).", width, table->dims); + "(%u).", num_fields, table->dims); vpi_control(vpiFinish, 1); - return 0; + return 1; } /* Allocate space for the interpolation/extrapolation values. */ - table->control.info.interp = (char *) malloc(width); + table->control.info.interp = (char *) malloc(num_fields); assert(table->control.info.interp); - table->control.info.extrap_low = (char *) malloc(width); + table->control.info.extrap_low = (char *) malloc(num_fields); assert(table->control.info.extrap_low); - table->control.info.extrap_high = (char *) malloc(width); + table->control.info.extrap_high = (char *) malloc(num_fields); assert(table->control.info.extrap_high); /* Parse the individual dimension control string. */ + num_ignore = 0; cp = control; - for (idx = 0; idx < width; idx += 1) { + for (idx = 0; idx < num_fields; idx += 1) { switch (*cp) { /* Closest point interpolation. */ case 'D': @@ -485,12 +440,16 @@ static unsigned initialize_control_fields(vpiHandle callh, p_table_mod table, /* Ignore column. No extrapolation codes are allowed. */ case 'I': table->control.info.interp[idx] = IVL_IGNORE_COLUMN; + table->control.info.extrap_low[idx] = IVL_ERROR_EXTRAP; + table->control.info.extrap_high[idx] = IVL_ERROR_EXTRAP; + cp += 1; + num_ignore += 1; break; /* This field is not specified so use the default values. * Linear interpolation and extrapolation. */ case 0: - assert(idx == width-1); + assert(idx == num_fields-1); case ',': table->control.info.interp[idx] = IVL_LINEAR_INTERP; table->control.info.extrap_low[idx] = IVL_LINEAR_EXTRAP; @@ -504,7 +463,7 @@ static unsigned initialize_control_fields(vpiHandle callh, p_table_mod table, vpi_printf("Unknown interpolation code '%c' for dimension " "%u: %s\n", *cp, idx+1, control); vpi_control(vpiFinish, 1); - return 0; + return 1; } /* Verify that there is no extra junk at the end of the field. */ @@ -514,7 +473,7 @@ static unsigned initialize_control_fields(vpiHandle callh, p_table_mod table, vpi_printf("Extra control characters found for dimension " "%u: %s\n", idx+1, control); vpi_control(vpiFinish, 1); - return 0; + return 1; } /* Advance to the next field if we are not at the end of the @@ -522,9 +481,20 @@ static unsigned initialize_control_fields(vpiHandle callh, p_table_mod table, if (*cp == ',') cp += 1; } - /* Return the number of fields plus the dependent offset as the - * minimum number of fields. */ - return (width + table->depend); + /* We must have a usable control field for each dimensions. */ + if ((num_fields - num_ignore) != table->dims) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("Usable control field(s) (%u) do not match dimension(s) " + "(%u).", (num_fields - num_ignore), table->dims); + vpi_control(vpiFinish, 1); + return 1; + } + + /* Set the number of control fields. */ + table->fields = num_fields; + + return 0; } /* @@ -563,7 +533,7 @@ static void dump_diag_info(vpiHandle callh, p_table_mod table) unsigned idx; char msg[64]; - snprintf(msg, sizeof(msg), "%s:%d: DEBUG:", vpi_get_str(vpiFile, callh), + snprintf(msg, sizeof(msg), "DEBUG: %s:%d:", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); msg[sizeof(msg)-1] = 0; fprintf(stderr, "%s Building %u variable table using \"%s\" and\n", @@ -638,11 +608,7 @@ static unsigned initialize_table_model(vpiHandle callh, const char *name, /* Parse the given file and produce the basic data structure. We * need to have columns for each control string field and for the * dependent data. */ -// HERE: This is going to return a pointer to the data. - if (! parse_table_model(fp, table->file.name, callh, - table->fields, table->depend)) { - return 1; - } + if (parse_table_model(fp, callh, table)) return 1; // HERE: once we are done with the control string should we build a table // of function pointer for the interp/extrap? diff --git a/vpi/table_mod.h b/vpi/table_mod.h index 3a92f6088..35a513404 100644 --- a/vpi/table_mod.h +++ b/vpi/table_mod.h @@ -21,8 +21,78 @@ #include #include -extern int parse_table_model(FILE *fp, const char *file_name, vpiHandle callh, - unsigned indep__cols, unsigned dep_col); +/* + * Define the allowed interpolation control values. + */ +#define IVL_CLOSEST_POINT 0 /* D */ +#define IVL_LINEAR_INTERP 1 /* 1 - Default */ +#define IVL_QUADRATIC_INTERP 2 /* 2 */ +#define IVL_CUBIC_INTERP 3 /* 3 */ +#define IVL_IGNORE_COLUMN 4 /* I */ + +/* + * Define the allowed extrapolation control values. + */ +#define IVL_CONSTANT_EXTRAP 0 /* C */ +#define IVL_LINEAR_EXTRAP 1 /* L - Default */ +#define IVL_ERROR_EXTRAP 2 /* E */ + +/* + * Structure that represents an individual iso line element. + */ +typedef struct t_indep { + double value; + struct t_indep *left; /* previous element. */ + struct t_indep *right; /* next element. */ + union { + double data; + struct t_indep *child; + struct t_build *build; + } data; +} s_indep, *p_indep; + +/* + * This is used as an interface element while building the iso lines. It will + * be removed when the list is converted to a balanced threaded tree. It is + * used to make in order insertion faster. + */ +typedef struct t_build { + p_indep first; + p_indep last; + unsigned count; +} s_build, *p_build; + +/* + * This structure is saved for each table model instance. + */ +typedef struct t_table_mod { + vpiHandle *indep; /* Independent variable arguments. */ + double *indep_val; /* Current independent variable values. */ + union { /* Data file or argument to get the data file. */ + char *name; + vpiHandle arg; + } file; + union { /* Control string argument. */ + struct { + char *interp; + char *extrap_low; + char *extrap_high; + } info; + vpiHandle arg; + } control; +// HERE need a pointer to the dependent data and the final table. + unsigned dims; /* The number of independent variables. */ + unsigned fields; /* The number of control fields. */ + unsigned depend; /* Where the dependent column is located. */ + char have_fname; /* Has the file name been allocated? */ + char have_ctl; /* Has the file name been allocated? */ +} s_table_mod, *p_table_mod; + +/* + * Define the non-static table model routines. + */ + +extern unsigned parse_table_model(FILE *fp, vpiHandle callh, p_table_mod table); extern int tblmodlex(); extern void destroy_tblmod_lexor(); diff --git a/vpi/table_mod_lexor.lex b/vpi/table_mod_lexor.lex index 12958efff..196df266f 100644 --- a/vpi/table_mod_lexor.lex +++ b/vpi/table_mod_lexor.lex @@ -53,7 +53,7 @@ SCALE [afpnumkKMGT] {EOL} { tblmodlloc.first_line += 1; - return EOL; + return END_LINE; } /* Recognize a real value with a Verilog-AMS scale. */ diff --git a/vpi/table_mod_parse.y b/vpi/table_mod_parse.y index ecd5d3deb..d2c004c5a 100644 --- a/vpi/table_mod_parse.y +++ b/vpi/table_mod_parse.y @@ -24,13 +24,17 @@ #include "table_mod.h" #include "ivl_alloc.h" +static unsigned errors = 0; static unsigned minimum_columns; +static unsigned indep_values; static unsigned indep_columns; static unsigned dep_column; static unsigned number_of_columns = 0; static unsigned cur_columns; +static unsigned cur_value; static double *values; static const char *in_file_name; +static p_table_mod table_def; extern int tblmodlex(void); static void yyerror(const char *fmt, ...); @@ -43,7 +47,7 @@ static void yyerror(const char *fmt, ...); double real; }; -%token EOL +%token END_LINE %token REAL %% @@ -51,14 +55,16 @@ static void yyerror(const char *fmt, ...); table : point | table point -point : columns EOL +point : columns END_LINE { - unsigned idx; - fprintf(stderr, "%#g", values[0]); - for (idx = 1; idx < indep_columns; idx += 1) { - fprintf(stderr, ", %#g", values[idx]); - } - fprintf(stderr, " => %#g\n", values[indep_columns]); + #if 0 + unsigned idx; + fprintf(stderr, "%#g", values[0]); + for (idx = 1; idx < indep_values; idx += 1) { + fprintf(stderr, ", %#g", values[idx]); + } + fprintf(stderr, " => %#g\n", values[indep_values]); + #endif if (number_of_columns) { if (cur_columns < minimum_columns) { yyerror("Found %u columns, need at least %u.", @@ -77,43 +83,64 @@ point : columns EOL columns : REAL { - values[0] = $1; + if (table_def->control.info.interp[0] != IVL_IGNORE_COLUMN) { + values[0] = $1; + cur_value = 1; + } else cur_value = 0; cur_columns = 1; } | columns REAL { - if (cur_columns < indep_columns) values[cur_columns] = $2; - else if (cur_columns == dep_column) values[indep_columns] = $2; + if (cur_columns < indep_columns) { + if (table_def->control.info.interp[cur_columns] != + IVL_IGNORE_COLUMN) { + values[cur_value] = $2; + cur_value += 1; + } + } else if (cur_columns == dep_column) values[indep_values] = $2; cur_columns += 1; } %% -int parse_table_model(FILE *fp, const char *file_name, vpiHandle callh, - unsigned indep_cols, unsigned dep_col) +unsigned parse_table_model(FILE *fp, vpiHandle callh, p_table_mod table) { - assert(indep_cols > 1); - assert(dep_col > 0); - indep_columns = indep_cols; - minimum_columns = indep_cols + dep_col; + unsigned rtn = 0; + assert(table); + assert(table->fields > 0); + assert(table->depend > 0); + table_def = table; + indep_values = table->dims; + indep_columns = table->fields; + minimum_columns = table->fields + table->depend; dep_column = minimum_columns - 1; - values = malloc(sizeof(double)*(indep_cols+1)); + values = malloc(sizeof(double)*(indep_values+1)); assert(values); - in_file_name = file_name; + in_file_name = table->file.name; init_tblmod_lexor(fp); - yyparse(); + if (yyparse()) errors += 1; + if (errors) { + vpi_printf("ERROR: %s:%u: ", vpi_get_str(vpiFile, callh), + (int) vpi_get(vpiLineNo, callh)); + vpi_printf("Had %u error(s) while reading table file.\n", errors); + rtn = 1; + } destroy_tblmod_lexor(); free(values); -// HERE: Need to handle errors. - return 1; + return rtn; } +/* + * Because every parse error is reported after the newline subtract one from + * the line count. + */ void yyerror(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - fprintf(stderr, "%s:%u: TABLE ERROR: ", in_file_name, yylloc.first_line); + fprintf(stderr, "%s:%u: TABLE ERROR: ", in_file_name, + yylloc.first_line-1); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); - + errors += 1; }