Some more $table_model() changes.
The code should be able to correctly parse any command string and assign the appropriate values from the file to a structure that will be used to add the information to the table structure.
This commit is contained in:
parent
0597b56ba2
commit
b13c899b89
108
vpi/table_mod.c
108
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?
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,78 @@
|
|||
#include <stdio.h>
|
||||
#include <vpi_user.h>
|
||||
|
||||
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();
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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> 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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue