T: improve to_vcd tracer
Make it compatible with 'template' gtwave files as found in openair's repository. The type VCD_NAME was added to the VCD IDs in T_messages.txt. The database processing code was adapted to use it. The tracer to_vcd was adapted to use it and render the produced vcd output compatible with the 'template' gtkwave files. When running to_vcd, do not forget to pass -vcd to use this feature.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,7 @@ typedef struct {
|
|||||||
char **arg_type;
|
char **arg_type;
|
||||||
char **arg_name;
|
char **arg_name;
|
||||||
int asize;
|
int asize;
|
||||||
|
char *vcd_name;
|
||||||
int id;
|
int id;
|
||||||
} id;
|
} id;
|
||||||
|
|
||||||
@@ -138,6 +139,7 @@ id *add_id(database *r, char *idname, int i)
|
|||||||
r->i[r->isize].arg_type = NULL;
|
r->i[r->isize].arg_type = NULL;
|
||||||
r->i[r->isize].arg_name = NULL;
|
r->i[r->isize].arg_name = NULL;
|
||||||
r->i[r->isize].asize = 0;
|
r->i[r->isize].asize = 0;
|
||||||
|
r->i[r->isize].vcd_name = NULL;
|
||||||
r->i[r->isize].id = i;
|
r->i[r->isize].id = i;
|
||||||
r->isize++;
|
r->isize++;
|
||||||
qsort(r->i, r->isize, sizeof(id), id_cmp);
|
qsort(r->i, r->isize, sizeof(id), id_cmp);
|
||||||
@@ -224,6 +226,12 @@ void add_desc(id *i, char *desc)
|
|||||||
i->desc = strdup(desc); if (i->desc == NULL) abort();
|
i->desc = strdup(desc); if (i->desc == NULL) abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_vcd_name(id *i, char *vcd_name)
|
||||||
|
{
|
||||||
|
if (i == NULL) {printf("ERROR: VCD_NAME line before ID line\n");exit(1);}
|
||||||
|
i->vcd_name = strdup(vcd_name); if (i->vcd_name == NULL) abort();
|
||||||
|
}
|
||||||
|
|
||||||
char *format_get_next_token(char **cur)
|
char *format_get_next_token(char **cur)
|
||||||
{
|
{
|
||||||
char *start;
|
char *start;
|
||||||
@@ -320,6 +328,7 @@ void *parse_database(char *filename)
|
|||||||
if (!strcmp(name, "GROUP")) add_groups(r, last_id, value);
|
if (!strcmp(name, "GROUP")) add_groups(r, last_id, value);
|
||||||
if (!strcmp(name, "DESC")) add_desc(last_id, value);
|
if (!strcmp(name, "DESC")) add_desc(last_id, value);
|
||||||
if (!strcmp(name, "FORMAT")) add_format(last_id, value);
|
if (!strcmp(name, "FORMAT")) add_format(last_id, value);
|
||||||
|
if (!strcmp(name, "VCD_NAME")) add_vcd_name(last_id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(in);
|
fclose(in);
|
||||||
@@ -424,6 +433,12 @@ char *event_name_from_id(void *_database, int id)
|
|||||||
return d->i[d->id_to_pos[id]].name;
|
return d->i[d->id_to_pos[id]].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *event_vcd_name_from_id(void *_database, int id)
|
||||||
|
{
|
||||||
|
database *d = _database;
|
||||||
|
return d->i[d->id_to_pos[id]].vcd_name;
|
||||||
|
}
|
||||||
|
|
||||||
int event_id_from_name(void *_database, char *name)
|
int event_id_from_name(void *_database, char *name)
|
||||||
{
|
{
|
||||||
database *d = _database;
|
database *d = _database;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ void list_ids(void *database);
|
|||||||
void list_groups(void *database);
|
void list_groups(void *database);
|
||||||
void on_off(void *d, char *item, int *a, int onoff);
|
void on_off(void *d, char *item, int *a, int onoff);
|
||||||
char *event_name_from_id(void *database, int id);
|
char *event_name_from_id(void *database, int id);
|
||||||
|
char *event_vcd_name_from_id(void *_database, int id);
|
||||||
int event_id_from_name(void *database, char *name);
|
int event_id_from_name(void *database, char *name);
|
||||||
int number_of_ids(void *database);
|
int number_of_ids(void *database);
|
||||||
int database_get_ids(void *database, char ***ids);
|
int database_get_ids(void *database, char ***ids);
|
||||||
|
|||||||
@@ -12,7 +12,14 @@
|
|||||||
#include "logger/logger.h"
|
#include "logger/logger.h"
|
||||||
#include "view/view.h"
|
#include "view/view.h"
|
||||||
|
|
||||||
|
enum var_type {
|
||||||
|
DEFAULT,
|
||||||
|
VCD_FUNCTION,
|
||||||
|
VCD_VARIABLE
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
enum var_type type;
|
||||||
char *event;
|
char *event;
|
||||||
char *arg;
|
char *arg;
|
||||||
char *vcd_name;
|
char *vcd_name;
|
||||||
@@ -44,16 +51,39 @@ void vcd_write_header(vcd_vars *v, int n)
|
|||||||
"$version\n"
|
"$version\n"
|
||||||
" to_vcd\n"
|
" to_vcd\n"
|
||||||
"$end\n"
|
"$end\n"
|
||||||
"$timescale 1ns $end\n"
|
"$timescale 1ns $end\n") <= 0) abort();
|
||||||
|
|
||||||
|
if (fprintf(out,
|
||||||
"$scope module logic $end\n") <= 0) abort();
|
"$scope module logic $end\n") <= 0) abort();
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
if (v[i].type == DEFAULT)
|
||||||
|
if (fprintf(out, "$var wire %d %s %s $end\n",
|
||||||
|
v[i].boolean ? 1 : 64,
|
||||||
|
v[i].vcd_name, v[i].vcd_name) <= 0) abort();
|
||||||
|
if (fprintf(out,
|
||||||
|
"$upscope $end\n") <= 0) abort();
|
||||||
|
|
||||||
|
if (fprintf(out,
|
||||||
|
"$scope module functions $end\n") <= 0) abort();
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
if (v[i].type == VCD_FUNCTION)
|
||||||
|
if (fprintf(out, "$var wire %d %s %s $end\n",
|
||||||
|
v[i].boolean ? 1 : 64,
|
||||||
|
v[i].vcd_name, v[i].vcd_name) <= 0) abort();
|
||||||
|
if (fprintf(out,
|
||||||
|
"$upscope $end\n") <= 0) abort();
|
||||||
|
|
||||||
|
if (fprintf(out,
|
||||||
|
"$scope module variables $end\n") <= 0) abort();
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
if (fprintf(out, "$var wire %d %s %s $end\n",
|
if (v[i].type == VCD_VARIABLE)
|
||||||
v[i].boolean ? 1 : 64,
|
if (fprintf(out, "$var wire %d %s %s $end\n",
|
||||||
v[i].vcd_name, v[i].vcd_name) <= 0) abort();
|
v[i].boolean ? 1 : 64,
|
||||||
|
v[i].vcd_name, v[i].vcd_name) <= 0) abort();
|
||||||
|
if (fprintf(out,
|
||||||
|
"$upscope $end\n") <= 0) abort();
|
||||||
|
|
||||||
if (fprintf(out,
|
if (fprintf(out,
|
||||||
"$upscope $end\n"
|
|
||||||
"$enddefinitions $end\n"
|
"$enddefinitions $end\n"
|
||||||
"$dumpvars\n") <= 0) abort();
|
"$dumpvars\n") <= 0) abort();
|
||||||
|
|
||||||
@@ -194,12 +224,13 @@ void force_stop(int x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
vcd_vars *add_var(vcd_vars *vars, int nvars,
|
vcd_vars *add_var(vcd_vars *vars, int nvars,
|
||||||
char *event, char *arg, char *vcd_name, int is_boolean)
|
char *event, char *arg, char *vcd_name, int is_boolean, enum var_type t)
|
||||||
{
|
{
|
||||||
if (nvars % 64 == 0) {
|
if (nvars % 64 == 0) {
|
||||||
vars = realloc(vars, (nvars+64) * sizeof(vcd_vars));
|
vars = realloc(vars, (nvars+64) * sizeof(vcd_vars));
|
||||||
if (vars == NULL) abort();
|
if (vars == NULL) abort();
|
||||||
}
|
}
|
||||||
|
vars[nvars].type = t;
|
||||||
vars[nvars].event = event;
|
vars[nvars].event = event;
|
||||||
vars[nvars].arg = arg;
|
vars[nvars].arg = arg;
|
||||||
vars[nvars].vcd_name = vcd_name;
|
vars[nvars].vcd_name = vcd_name;
|
||||||
@@ -240,7 +271,7 @@ int main(int n, char **v)
|
|||||||
char *event = v[++i];
|
char *event = v[++i];
|
||||||
char *arg = v[++i];
|
char *arg = v[++i];
|
||||||
char *vcd_name = v[++i];
|
char *vcd_name = v[++i];
|
||||||
vars = add_var(vars, nvars, event, arg, vcd_name, 1);
|
vars = add_var(vars, nvars, event, arg, vcd_name, 1, DEFAULT);
|
||||||
nvars++;
|
nvars++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -248,7 +279,7 @@ int main(int n, char **v)
|
|||||||
char *event = v[++i];
|
char *event = v[++i];
|
||||||
char *arg = v[++i];
|
char *arg = v[++i];
|
||||||
char *vcd_name = v[++i];
|
char *vcd_name = v[++i];
|
||||||
vars = add_var(vars, nvars, event, arg, vcd_name, 0);
|
vars = add_var(vars, nvars, event, arg, vcd_name, 0, DEFAULT);
|
||||||
nvars++;
|
nvars++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -283,20 +314,30 @@ int main(int n, char **v)
|
|||||||
/* activate all VCD traces */
|
/* activate all VCD traces */
|
||||||
for (i = 0; i < number_of_events; i++) {
|
for (i = 0; i < number_of_events; i++) {
|
||||||
int is_boolean;
|
int is_boolean;
|
||||||
|
enum var_type type;
|
||||||
int prefix_length;
|
int prefix_length;
|
||||||
char *name = event_name_from_id(database, i);
|
char *name = event_name_from_id(database, i);
|
||||||
|
char *vcd_name;
|
||||||
char *var_prefix = "VCD_VARIABLE_";
|
char *var_prefix = "VCD_VARIABLE_";
|
||||||
char *fun_prefix = "VCD_FUNCTION_";
|
char *fun_prefix = "VCD_FUNCTION_";
|
||||||
if (!strncmp(name, var_prefix, strlen(var_prefix))) {
|
if (!strncmp(name, var_prefix, strlen(var_prefix))) {
|
||||||
prefix_length = strlen(var_prefix);
|
prefix_length = strlen(var_prefix);
|
||||||
is_boolean = 0;
|
is_boolean = 0;
|
||||||
|
type = VCD_VARIABLE;
|
||||||
} else if (!strncmp(name, fun_prefix, strlen(fun_prefix))) {
|
} else if (!strncmp(name, fun_prefix, strlen(fun_prefix))) {
|
||||||
prefix_length = strlen(fun_prefix);
|
prefix_length = strlen(fun_prefix);
|
||||||
is_boolean = 1;
|
is_boolean = 1;
|
||||||
|
type = VCD_FUNCTION;
|
||||||
} else
|
} else
|
||||||
continue;
|
continue;
|
||||||
|
vcd_name = event_vcd_name_from_id(database, i);
|
||||||
|
if (vcd_name == NULL) {
|
||||||
|
vcd_name = name+prefix_length;
|
||||||
|
printf("WARNING: ID %s does not define VCD_NAME in the file %s, using %s\n",
|
||||||
|
name, database_filename, vcd_name);
|
||||||
|
}
|
||||||
vars = add_var(vars, nvars,
|
vars = add_var(vars, nvars,
|
||||||
name, "value", name+prefix_length, is_boolean);
|
name, "value", vcd_name, is_boolean, type);
|
||||||
nvars++;
|
nvars++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user