From c5950e3aa684837afdc55e7b1c45a0eb56516a74 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 18 Nov 2007 17:36:03 -0800 Subject: [PATCH 1/4] Add stub $sdf_annotate function. Add the $sdf_annotate function infrastructure, and a stub parser that can parse miniman SDF files. Signed-off-by: Stephen Williams --- vpi/Makefile.in | 13 ++- vpi/configure.in | 8 ++ vpi/sdf_lexor.lex | 120 +++++++++++++++++++++ vpi/sdf_parse.y | 247 +++++++++++++++++++++++++++++++++++++++++++ vpi/sdf_parse_priv.h | 30 ++++++ vpi/sdf_priv.h | 31 ++++++ vpi/sys_sdf.c | 76 +++++++++++++ vpi/sys_table.c | 2 + 8 files changed, 525 insertions(+), 2 deletions(-) create mode 100644 vpi/sdf_lexor.lex create mode 100644 vpi/sdf_parse.y create mode 100644 vpi/sdf_parse_priv.h create mode 100644 vpi/sdf_priv.h create mode 100644 vpi/sys_sdf.c diff --git a/vpi/Makefile.in b/vpi/Makefile.in index 7f8c2c696..730b64fe4 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -39,6 +39,8 @@ CC = @CC@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ +LEX = @LEX@ +YACC = @YACC@ CPPFLAGS = @ident_support@ -I. -I$(srcdir)/.. -I$(srcdir) -I.. @file64_support@ @CPPFLAGS@ @DEFS@ @PICFLAG@ CFLAGS = -Wall @CFLAGS@ @@ -62,8 +64,9 @@ dep: O = sys_table.o sys_convert.o sys_deposit.o sys_display.o sys_fileio.o \ sys_finish.o sys_plusargs.o sys_random.o sys_random_mti.o \ -sys_readmem.o sys_readmem_lex.o sys_scanf.o \ -sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o priv.o stringheap.o +sys_readmem.o sys_readmem_lex.o sys_scanf.o sys_sdf.o \ +sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o \ +mt19937int.o priv.o sdf_lexor.o sdf_parse.o stringheap.o ifeq (@HAVE_LIBZ@,yes) ifeq (@HAVE_LIBBZ2@,yes) @@ -84,6 +87,12 @@ system.vpi: $O ../vvp/libvpi.a sys_readmem_lex.c: sys_readmem_lex.lex flex -t -Preadmem $(srcdir)/sys_readmem_lex.lex > sys_readmem_lex.c +sdf_lexor.c: sdf_lexor.lex + flex -t -Psdf $(srcdir)/sdf_lexor.lex > sdf_lexor.c + +sdf_parse.c sdf_parse.h: $(srcdir)/sdf_parse.y + $(YACC) --verbose -d -p sdf -o sdf_parse.c $(srcdir)/sdf_parse.y + ifeq (@enable_vvp32@,yes) all32: bin32 bin32/system.vpi diff --git a/vpi/configure.in b/vpi/configure.in index 172378351..e4e98738c 100644 --- a/vpi/configure.in +++ b/vpi/configure.in @@ -15,6 +15,14 @@ then exit 1 fi +AC_CHECK_PROGS(YACC,bison,none) +if test "$YACC" = "none" +then + echo "*** Error: No suitable bison found. ***" + echo " Please install the 'bison' package." + exit 1 +fi + AC_EXEEXT AC_SUBST(EXEEXT) diff --git a/vpi/sdf_lexor.lex b/vpi/sdf_lexor.lex new file mode 100644 index 000000000..7f75d6ef8 --- /dev/null +++ b/vpi/sdf_lexor.lex @@ -0,0 +1,120 @@ + +%option never-interactive + +%{ +/* + * Copyright (c) 2007 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form 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 + */ + +# include "sdf_priv.h" +# include "sdf_parse_priv.h" +# include "sdf_parse.h" +# include +# include + +static void process_quoted_string(void); +static int lookup_keyword(const char*text); +const char*sdf_parse_path = 0; + +static int yywrap(void) +{ + return 1; +} + + +# define yylval sdflval +%} + +%% + +[ \m\t] { /* Skip white space. */; } + + /* Count lines so that the parser can assign line numbers. */ +\n { sdflloc.first_line += 1; } + + /* Real values */ +[0-9]+(\.[0-9]+)?([Ee][+-]?[0-9]+)? { + yylval.real_val = strtod(yytext, 0); + return REAL_NUMBER; +} + +[a-zA-Z]+ { + return lookup_keyword(yytext); +} + +\"[^\"]*\" { + process_quoted_string(); + return QSTRING; +} + +. { return yytext[0]; } + +%% + +static struct { + const char*name; + int code; +} keywords[] = { + { "ABSOLUTE", K_ABSOLUTE }, + { "CELL", K_CELL }, + { "CELLTYPE", K_CELLTYPE }, + { "DATE", K_DATE }, + { "DELAY", K_DELAY }, + { "DELAYFILE", K_DELAYFILE }, + { "DESIGN", K_DESIGN }, + { "DIVIDER", K_DIVIDER }, + { "INCREMENT", K_INCREMENT }, + { "INSTANCE", K_INSTANCE }, + { "IOPATH", K_IOPATH }, + { "PROCESS", K_PROCESS }, + { "PROGRAM", K_PROGRAM }, + { "SDFVERSION", K_SDFVERSION }, + { "TEMPERATURE",K_TEMPERATURE }, + { "TIMESCALE", K_TIMESCALE }, + { "VENDOR", K_VENDOR }, + { "VERSION", K_VERSION }, + { "VOLTAGE", K_VOLTAGE }, + { 0, IDENTIFIER } +}; + +static int lookup_keyword(const char*text) +{ + int idx; + for (idx = 0 ; keywords[idx].name ; idx += 1) { + if (strcasecmp(text, keywords[idx].name) == 0) + return keywords[idx].code; + } + + yylval.string_val = strdup(yytext); + return IDENTIFIER; +} + +static void process_quoted_string(void) +{ + yylval.string_val = strdup(yytext); +} + +extern int sdfparse(void); +void sdf_process_file(FILE*fd, const char*path) +{ + yyrestart(fd); + + sdf_parse_path = path; + sdfparse(); + sdf_parse_path = 0; +} diff --git a/vpi/sdf_parse.y b/vpi/sdf_parse.y new file mode 100644 index 000000000..1e8d21d93 --- /dev/null +++ b/vpi/sdf_parse.y @@ -0,0 +1,247 @@ + +%{ +/* + * Copyright (c) 1998-2007 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form 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 + */ + +extern int sdflex(void); +static void yyerror(const char*msg); +# include "vpi_user.h" +# include "sdf_parse_priv.h" +# include +%} + +%union { + unsigned long int_val; + double real_val; + char* string_val; +}; + +%token K_ABSOLUTE K_CELL K_CELLTYPE K_DATE K_DELAYFILE K_DELAY K_DESIGN +%token K_DIVIDER K_INCREMENT K_INSTANCE K_IOPATH +%token K_PROCESS K_PROGRAM K_SDFVERSION K_TEMPERATURE K_TIMESCALE +%token K_VENDOR K_VERSION K_VOLTAGE + +%token QSTRING IDENTIFIER +%token REAL_NUMBER +%token INTEGER + +%% + +source_file + : '(' K_DELAYFILE sdf_header_list cell_list ')' + ; + +sdf_header_list + : sdf_header_list sdf_header_item + | sdf_header_item + ; + +sdf_header_item + : sdfversion + | design_name + | date + | vendor + | program_name + | program_version + | hierarchy_divider + | voltage + | process + | temperature + | time_scale + ; + +sdfversion + : '(' K_SDFVERSION QSTRING ')' + { vpi_printf("SDFVERSION: %s\n", $3); + free($3); + } + ; + +design_name + : '(' K_DESIGN QSTRING ')' + { vpi_printf("SDF Design: %s\n", $3); + free($3); + } + ; + +date + : '(' K_DATE QSTRING ')' + { vpi_printf("SDF Date: %s\n", $3); + free($3); + } + ; + +vendor : '(' K_VENDOR QSTRING ')' + { vpi_printf("SDF Vendor: %s\n", $3); + free($3); + } +; + +program_name : '(' K_PROGRAM QSTRING ')' + { vpi_printf("SDF Program: %s\n", $3); + free($3); + } +; + +program_version : '(' K_VERSION QSTRING ')' + { vpi_printf("SDF Program Version: %s\n", $3); + free($3); + } +; + +hierarchy_divider + : '(' K_DIVIDER '.' ')' { vpi_printf("SDF Use . for hierarchy\n"); } + | '(' K_DIVIDER '/' ')' { vpi_printf("SDF Use / for hierarchy\n"); } + ; + +voltage + : '(' K_VOLTAGE rtriple ')' + | '(' K_VOLTAGE signed_real_number ')' + ; + +process : '(' K_PROCESS QSTRING ')' + { vpi_printf("SDF Process: %s\n", $3); + free($3); + } +; + +temperature + : '(' K_TEMPERATURE rtriple ')' + | '(' K_TEMPERATURE signed_real_number ')' + ; + +time_scale + : '(' K_TIMESCALE REAL_NUMBER IDENTIFIER ')' + { vpi_printf("SDF TIMESCALE : %f%s\n", $3, $4); + free($4); + } + ; + +cell_list + : cell_list cell + | cell + ; + +cell + : '(' K_CELL celltype cell_instance timing_spec_list ')' + | '(' K_CELL error ')' + { vpi_printf("%s:%d: Syntax error in CELL\n", + sdf_parse_path, @2.first_line); } + ; + +celltype + : '(' K_CELLTYPE QSTRING ')' + { vpi_printf("%s:%d: SDF CELL TYPE: %s\n", sdf_parse_path, @1.first_line, $3); + free($3); + } + ; + +cell_instance + : '(' K_INSTANCE hierarchical_identifier ')' + | '(' K_INSTANCE '*' ')' + ; + +timing_spec_list + : timing_spec_list timing_spec + | timing_spec + ; + +timing_spec + : '(' K_DELAY deltype_list ')' + | '(' K_DELAY error ')' + { vpi_printf("%s:%d: Syntax error in CELL DELAY SPEC\n", + sdf_parse_path, @2.first_line); } + ; + +deltype_list + : deltype_list deltype + | deltype + ; + +deltype + : '(' K_ABSOLUTE del_def_list ')' + | '(' K_INCREMENT del_def_list ')' + | '(' error ')' + { vpi_printf("%s:%d: Invalid/malformed delay type\n", + sdf_parse_path, @1.first_line); } + ; + +del_def_list + : del_def_list del_def + | del_def + ; + +del_def + : '(' K_IOPATH port_spec port_instance delval_list ')' + | '(' K_IOPATH error ')' + { vpi_printf("%s:%d: Invalid/malformed IOPATH\n", + sdf_parse_path, @2.first_line); } + ; + +port_spec + : port_instance + /* | port_edge */ + ; + +port_instance + : port + ; + +port + : hierarchical_identifier + | hierarchical_identifier '[' INTEGER ']' + ; + +delval_list + : delval_list delval + | delval + ; + +delval + : rvalue + | '(' rvalue rvalue ')' + | '(' rvalue rvalue rvalue ')' + ; + +rvalue + : '(' signed_real_number ')' + | '(' rtriple ')' + ; + +hierarchical_identifier + : IDENTIFIER + { free($1); } + ; + +rtriple + : signed_real_number ':' signed_real_number ':' signed_real_number + ; + +signed_real_number + : REAL_NUMBER + | '+' REAL_NUMBER + | '-' REAL_NUMBER + ; + +%% + +void yyerror(const char*msg) +{ + fprintf(stderr, "SDF ERROR: %s\n", msg); +} diff --git a/vpi/sdf_parse_priv.h b/vpi/sdf_parse_priv.h new file mode 100644 index 000000000..9ecce9dad --- /dev/null +++ b/vpi/sdf_parse_priv.h @@ -0,0 +1,30 @@ +#ifndef _sdf_parse_priv_h +#define _sdf_parse_priv_h +/* + * Copyright (c) 2007 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form 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 + */ + +/* + * This file is only included by sdf_parse.y and sdf_lexor.lex. It is + * used to share declarations between the parse and the lexor. + */ + + /* Path to source for error messages. */ +extern const char*sdf_parse_path; + +#endif diff --git a/vpi/sdf_priv.h b/vpi/sdf_priv.h new file mode 100644 index 000000000..82f26fed2 --- /dev/null +++ b/vpi/sdf_priv.h @@ -0,0 +1,31 @@ +#ifndef _sdf_priv_h +#define _sdf_priv_h +/* + * Copyright (c) 2007 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form 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 + */ + +# include + +/* + * Invoke the parser to parse the opened SDF file. The fd is the SDF + * file already opened and ready for reading. The path is the path to + * the file and is only used for error messages. + */ +extern void sdf_process_file(FILE*fd, const char*path); + +#endif diff --git a/vpi/sys_sdf.c b/vpi/sys_sdf.c new file mode 100644 index 000000000..5a4b27e5e --- /dev/null +++ b/vpi/sys_sdf.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2007 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form 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 + */ + +# include "vpi_config.h" + +# include "vpi_user.h" +# include "sdf_priv.h" +# include +# include +# include + +static PLI_INT32 sys_sdf_annotate_compiletf(PLI_BYTE8*name) +{ + return 0; +} + +static PLI_INT32 sys_sdf_annotate_calltf(PLI_BYTE8*name) +{ + s_vpi_value value; + vpiHandle sys = vpi_handle(vpiSysTfCall,0); + vpiHandle argv = vpi_iterate(vpiArgument, sys); + + vpiHandle path = vpi_scan(argv); + assert(path); + + vpi_free_object(argv); + + value.format = vpiStringVal; + vpi_get_value(path, &value); + + if ((value.format != vpiStringVal) || !value.value.str) { + vpi_printf("ERROR: %s: File name argument (type=%d)" + " does not have a string value\n", + name, vpi_get(vpiType, path)); + return 0; + } + + char*path_str = strdup(value.value.str); + FILE*sdf_fd = fopen(path_str, "r"); + assert(sdf_fd); + + sdf_process_file(sdf_fd, path_str); + + fclose(sdf_fd); + free(path_str); + return 0; +} + +void sys_sdf_register() +{ + s_vpi_systf_data tf_data; + + tf_data.type = vpiSysTask; + tf_data.tfname = "$sdf_annotate"; + tf_data.calltf = sys_sdf_annotate_calltf; + tf_data.compiletf = sys_sdf_annotate_compiletf; + tf_data.sizetf = 0; + tf_data.user_data = "$sdf_annotate"; + vpi_register_systf(&tf_data); +} diff --git a/vpi/sys_table.c b/vpi/sys_table.c index ceb7e0033..be260e8bc 100644 --- a/vpi/sys_table.c +++ b/vpi/sys_table.c @@ -36,6 +36,7 @@ extern void sys_random_register(); extern void sys_random_mti_register(); extern void sys_readmem_register(); extern void sys_scanf_register(); +extern void sys_sdf_register(); extern void sys_time_register(); extern void sys_vcd_register(); extern void sys_vcdoff_register(); @@ -176,6 +177,7 @@ void (*vlog_startup_routines[])() = { sys_scanf_register, sys_time_register, sys_lxt_or_vcd_register, + sys_sdf_register, 0 }; From 73e60f4b81fd1567a97e8e5acddbac982496114d Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Tue, 20 Nov 2007 22:20:22 -0800 Subject: [PATCH 2/4] Match parsed IOPATH to cell and modpath to be annotated. --- vpi/sdf_lexor.lex | 9 ++++- vpi/sdf_parse.y | 49 ++++++++++++++++-------- vpi/sdf_priv.h | 8 ++++ vpi/sys_sdf.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 16 deletions(-) diff --git a/vpi/sdf_lexor.lex b/vpi/sdf_lexor.lex index 7f75d6ef8..44d0aa94b 100644 --- a/vpi/sdf_lexor.lex +++ b/vpi/sdf_lexor.lex @@ -26,6 +26,7 @@ # include "sdf_parse.h" # include # include +# include static void process_quoted_string(void); static int lookup_keyword(const char*text); @@ -104,9 +105,15 @@ static int lookup_keyword(const char*text) return IDENTIFIER; } +/* + * Create a string witout the leading and trailing quotes. + */ static void process_quoted_string(void) { - yylval.string_val = strdup(yytext); + yylval.string_val = strdup(yytext+1); + char*endp = yylval.string_val+strlen(yylval.string_val); + assert(endp[-1] == '"'); + endp[-1] = 0; } extern int sdfparse(void); diff --git a/vpi/sdf_parse.y b/vpi/sdf_parse.y index 1e8d21d93..3afe61c3e 100644 --- a/vpi/sdf_parse.y +++ b/vpi/sdf_parse.y @@ -23,7 +23,12 @@ extern int sdflex(void); static void yyerror(const char*msg); # include "vpi_user.h" # include "sdf_parse_priv.h" +# include "sdf_priv.h" # include + +/* This is the hierarchy separator to use. */ +static char use_hchar = '.'; + %} %union { @@ -41,6 +46,11 @@ static void yyerror(const char*msg); %token REAL_NUMBER %token INTEGER +%type celltype +%type cell_instance +%type hierarchical_identifier +%type port port_instance port_spec + %% source_file @@ -68,8 +78,7 @@ sdf_header_item sdfversion : '(' K_SDFVERSION QSTRING ')' - { vpi_printf("SDFVERSION: %s\n", $3); - free($3); + { free($3); } ; @@ -106,8 +115,8 @@ program_version : '(' K_VERSION QSTRING ')' ; hierarchy_divider - : '(' K_DIVIDER '.' ')' { vpi_printf("SDF Use . for hierarchy\n"); } - | '(' K_DIVIDER '/' ')' { vpi_printf("SDF Use / for hierarchy\n"); } + : '(' K_DIVIDER '.' ')' { use_hchar = '.'; } + | '(' K_DIVIDER '/' ')' { use_hchar = '/'; } ; voltage @@ -139,22 +148,27 @@ cell_list ; cell - : '(' K_CELL celltype cell_instance timing_spec_list ')' + : '(' K_CELL celltype cell_instance + { sdf_select_instance($3, $4); /* find the instance in the design */} + timing_spec_list + ')' + { free($3); + free($4); } | '(' K_CELL error ')' - { vpi_printf("%s:%d: Syntax error in CELL\n", - sdf_parse_path, @2.first_line); } + { vpi_printf("%s:%d: Syntax error in CELL\n", + sdf_parse_path, @2.first_line); } ; celltype : '(' K_CELLTYPE QSTRING ')' - { vpi_printf("%s:%d: SDF CELL TYPE: %s\n", sdf_parse_path, @1.first_line, $3); - free($3); - } + { $$ = $3; } ; cell_instance : '(' K_INSTANCE hierarchical_identifier ')' + { $$ = $3; } | '(' K_INSTANCE '*' ')' + { $$ = 0; } ; timing_spec_list @@ -189,9 +203,13 @@ del_def_list del_def : '(' K_IOPATH port_spec port_instance delval_list ')' + { sdf_iopath_delays($3, $4); + free($3); + free($4); + } | '(' K_IOPATH error ')' - { vpi_printf("%s:%d: Invalid/malformed IOPATH\n", - sdf_parse_path, @2.first_line); } + { vpi_printf("%s:%d: Invalid/malformed IOPATH\n", + sdf_parse_path, @2.first_line); } ; port_spec @@ -200,12 +218,13 @@ port_spec ; port_instance - : port + : port { $$ = $1; } ; port : hierarchical_identifier - | hierarchical_identifier '[' INTEGER ']' + { $$ = $1; } + /* | hierarchical_identifier '[' INTEGER ']' */ ; delval_list @@ -226,7 +245,7 @@ rvalue hierarchical_identifier : IDENTIFIER - { free($1); } + { $$ = $1; } ; rtriple diff --git a/vpi/sdf_priv.h b/vpi/sdf_priv.h index 82f26fed2..f5707c87c 100644 --- a/vpi/sdf_priv.h +++ b/vpi/sdf_priv.h @@ -28,4 +28,12 @@ */ extern void sdf_process_file(FILE*fd, const char*path); + +/* **** + * These functions are called by the parser to process the SDF file as + * it is parsed. + */ +extern void sdf_select_instance(const char*celltype, const char*inst); +extern void sdf_iopath_delays(const char*src, const char*dst); + #endif diff --git a/vpi/sys_sdf.c b/vpi/sys_sdf.c index 5a4b27e5e..75ae2bbe2 100644 --- a/vpi/sys_sdf.c +++ b/vpi/sys_sdf.c @@ -25,6 +25,99 @@ # include # include +/* + * These are static context + */ + + /* Scope of the $sdf_annotate call. Annotation starts here. */ +static vpiHandle sdf_scope; + /* The cell in process. */ +static vpiHandle sdf_cur_cell; + +/* + * These functions are called by the SDF parser during parsing to + * handling items discovered in the parse. + */ +void sdf_select_instance(const char*celltype, const char*cellinst) +{ + vpiHandle idx = vpi_iterate(vpiModule, sdf_scope); + assert(idx); + + vpiHandle cur; + while ( (cur = vpi_scan(idx)) ) { + + /* If we find the cell in this scope, then save it for + future processing. */ + if ( strcmp(cellinst, vpi_get_str(vpiName,cur)) == 0) { + sdf_cur_cell = cur; + vpi_free_object(idx); + + /* The scope that matches should be a module. */ + if (vpi_get(vpiType,sdf_cur_cell) != vpiModule) { + vpi_printf("SDF ERROR: Scope %s in %s is not a module.\n", + cellinst, vpi_get_str(vpiName,sdf_scope)); + } + /* The matching scope (a module) should have the + expected type. */ + if (strcmp(celltype,vpi_get_str(vpiDefName,sdf_cur_cell)) != 0) { + vpi_printf("SDF ERROR: Module %s in %s is not a %s; " + "it is an %s\n", cellinst, + vpi_get_str(vpiName,sdf_scope), celltype, + vpi_get_str(vpiDefName,sdf_cur_cell)); + } + + return; + } + } + + sdf_cur_cell = 0; + vpi_printf("SDF WARNING: Unable to find %s in current scope\n", cellinst); +} + +void sdf_iopath_delays(const char*src, const char*dst) +{ + assert(sdf_cur_cell); + + vpiHandle idx = vpi_iterate(vpiModPath, sdf_cur_cell); + assert(idx); + + /* Search for the modpath that matches the IOPATH by looking + for the modpath that uses the same ports as the ports that + the parser has found. */ + vpiHandle path; + while ( (path = vpi_scan(idx)) ) { + vpiHandle path_in = vpi_handle(vpiModPathIn,path); + vpiHandle path_out = vpi_handle(vpiModPathOut,path); + + path_in = vpi_handle(vpiExpr,path_in); + path_out = vpi_handle(vpiExpr,path_out); + assert(vpi_get(vpiType,path_in) == vpiNet); + assert(vpi_get(vpiType,path_out) == vpiNet); + + /* If the src name doesn't match, go on. */ + if (strcmp(src,vpi_get_str(vpiName,path_in)) != 0) + continue; + + /* If the dst name doesn't match, go on. */ + if (strcmp(dst,vpi_get_str(vpiName,path_out)) != 0) + continue; + + /* Ah, this must be a match! */ + break; + } + + if (path == 0) { + vpi_printf("SDF ERROR: Unable to find ModPath %s -> %s in %s\n", + src, dst, vpi_get_str(vpiName,sdf_cur_cell)); + return; + } + + /* No longer need the iterator. */ + vpi_free_object(idx); + + vpi_printf("XXXX Found the modpath object.\n"); +} + static PLI_INT32 sys_sdf_annotate_compiletf(PLI_BYTE8*name) { return 0; @@ -55,6 +148,9 @@ static PLI_INT32 sys_sdf_annotate_calltf(PLI_BYTE8*name) FILE*sdf_fd = fopen(path_str, "r"); assert(sdf_fd); + sdf_scope = vpi_handle(vpiScope,sys); + sdf_cur_cell = 0; + sdf_process_file(sdf_fd, path_str); fclose(sdf_fd); From 4986e550b12cbf74174b6b3cd686166c6cabdd02 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 22 Nov 2007 17:34:51 -0800 Subject: [PATCH 3/4] Pass SDF delays into simulation Pass parsed SDF delays into the vvp run time as vpiScaledRealTime variables, and handling the mapping of 2-values to 12-delays. Signed-off-by: Stephen Williams --- vpi/sdf_parse.y | 39 +++++++++++++++++++++++++++++++++++---- vpi/sdf_priv.h | 9 ++++++++- vpi/sys_sdf.c | 28 ++++++++++++++++++++++------ vvp/delay.cc | 44 +++++++++++++++++++++++++++++++++++++++----- 4 files changed, 104 insertions(+), 16 deletions(-) diff --git a/vpi/sdf_parse.y b/vpi/sdf_parse.y index 3afe61c3e..6d1551016 100644 --- a/vpi/sdf_parse.y +++ b/vpi/sdf_parse.y @@ -35,6 +35,8 @@ static char use_hchar = '.'; unsigned long int_val; double real_val; char* string_val; + + struct sdf_delval_list_s delval_list; }; %token K_ABSOLUTE K_CELL K_CELLTYPE K_DATE K_DELAYFILE K_DELAY K_DESIGN @@ -51,6 +53,11 @@ static char use_hchar = '.'; %type hierarchical_identifier %type port port_instance port_spec +%type rvalue rtriple signed_real_number +%type delval + +%type delval_list + %% source_file @@ -203,7 +210,7 @@ del_def_list del_def : '(' K_IOPATH port_spec port_instance delval_list ')' - { sdf_iopath_delays($3, $4); + { sdf_iopath_delays($3, $4, &$5); free($3); free($4); } @@ -229,18 +236,41 @@ port delval_list : delval_list delval + { int idx; + $$.count = $1.count; + for (idx = 0 ; idx < $$.count ; idx += 1) + $$.val[idx] = $1.val[idx]; + if ($$.count < 12) { + $$.val[$$.count] = $2; + $$.count += 1; + } + } | delval + { $$.count = 1; + $$.val[0] = $1; + } ; delval : rvalue + { $$ = $1; } | '(' rvalue rvalue ')' + { $$ = $2; + vpi_printf("%s:%d: SDF WARNING: Pulse rejection limits ignored\n", + sdf_parse_path, @3.first_line); + } | '(' rvalue rvalue rvalue ')' + { $$ = $2; + vpi_printf("%s:%d: SDF WARNING: Pulse rejection limits ignored\n", + sdf_parse_path, @3.first_line); + } ; rvalue : '(' signed_real_number ')' + { $$ = $2; } | '(' rtriple ')' + { $$ = $2; } ; hierarchical_identifier @@ -250,12 +280,13 @@ hierarchical_identifier rtriple : signed_real_number ':' signed_real_number ':' signed_real_number + { $$ = $3; /* XXXX Assume typical value. */ } ; signed_real_number - : REAL_NUMBER - | '+' REAL_NUMBER - | '-' REAL_NUMBER + : REAL_NUMBER { $$ = $1; } + | '+' REAL_NUMBER { $$ = $2; } + | '-' REAL_NUMBER { $$ = -$2; } ; %% diff --git a/vpi/sdf_priv.h b/vpi/sdf_priv.h index f5707c87c..5a981dd57 100644 --- a/vpi/sdf_priv.h +++ b/vpi/sdf_priv.h @@ -33,7 +33,14 @@ extern void sdf_process_file(FILE*fd, const char*path); * These functions are called by the parser to process the SDF file as * it is parsed. */ + +struct sdf_delval_list_s { + int count; + double val[12]; +}; + extern void sdf_select_instance(const char*celltype, const char*inst); -extern void sdf_iopath_delays(const char*src, const char*dst); +extern void sdf_iopath_delays(const char*src, const char*dst, + const struct sdf_delval_list_s*delval); #endif diff --git a/vpi/sys_sdf.c b/vpi/sys_sdf.c index 75ae2bbe2..d382738d3 100644 --- a/vpi/sys_sdf.c +++ b/vpi/sys_sdf.c @@ -74,18 +74,19 @@ void sdf_select_instance(const char*celltype, const char*cellinst) vpi_printf("SDF WARNING: Unable to find %s in current scope\n", cellinst); } -void sdf_iopath_delays(const char*src, const char*dst) +void sdf_iopath_delays(const char*src, const char*dst, + const struct sdf_delval_list_s*delval_list) { assert(sdf_cur_cell); - vpiHandle idx = vpi_iterate(vpiModPath, sdf_cur_cell); - assert(idx); + vpiHandle iter = vpi_iterate(vpiModPath, sdf_cur_cell); + assert(iter); /* Search for the modpath that matches the IOPATH by looking for the modpath that uses the same ports as the ports that the parser has found. */ vpiHandle path; - while ( (path = vpi_scan(idx)) ) { + while ( (path = vpi_scan(iter)) ) { vpiHandle path_in = vpi_handle(vpiModPathIn,path); vpiHandle path_out = vpi_handle(vpiModPathOut,path); @@ -113,9 +114,24 @@ void sdf_iopath_delays(const char*src, const char*dst) } /* No longer need the iterator. */ - vpi_free_object(idx); + vpi_free_object(iter); - vpi_printf("XXXX Found the modpath object.\n"); + struct t_vpi_time delay_vals[12]; + int idx; + for (idx = 0 ; idx < delval_list->count ; idx += 1) { + delay_vals[idx].type = vpiScaledRealTime; + delay_vals[idx].real = delval_list->val[idx]; + } + + s_vpi_delay delays; + delays.da = delay_vals; + delays.no_of_delays = delval_list->count; + delays.time_type = vpiScaledRealTime; + delays.mtm_flag = 0; + delays.append_flag = 0; + delays.plusere_flag = 0; + + vpi_put_delays(path, &delays); } static PLI_INT32 sys_sdf_annotate_compiletf(PLI_BYTE8*name) diff --git a/vvp/delay.cc b/vvp/delay.cc index 446795e37..4497f8901 100644 --- a/vvp/delay.cc +++ b/vvp/delay.cc @@ -576,19 +576,53 @@ static void modpath_src_put_delays ( vpiHandle ref, p_vpi_delay delays ) vvp_fun_modpath_src *fun = dynamic_cast(src->net->fun); assert( fun ); - assert(delays->no_of_delays == 12); + + typedef unsigned char map_array_t[12]; + static const map_array_t map_2 = {0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0}; + static const map_array_t map12 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + + const map_array_t*use_map = 0; + switch (delays->no_of_delays) { + case 2: + use_map = &map_2; + break; + case 12: + use_map = &map12; + break; + default: + assert(0); + break; + } if (delays->time_type == vpiSimTime) { - for (idx = 0 ; idx < delays->no_of_delays ; idx += 1) { - tmp[idx] = vpip_timestruct_to_time(delays->da+idx); + for (idx = 0 ; idx < 12 ; idx += 1) { + tmp[idx] = vpip_timestruct_to_time(delays->da+use_map[0][idx]); } } else { - for (idx = 0 ; idx < delays->no_of_delays ; idx += 1) { - tmp[idx] = vpip_scaled_real_to_time64(delays->da[idx].real, + for (idx = 0 ; idx < 12 ; idx += 1) { + tmp[idx] = vpip_scaled_real_to_time64(delays->da[use_map[0][idx]].real, src->dest->scope); } } + /* Now clean up any to-from-x delays to me the min/max based on + the rules for selecting X delays. This only needs to happen + if the X delays are not already explicitly given. */ + if (delays->no_of_delays <= 6) { + vvp_time64_t t_max = tmp[0]; + vvp_time64_t t_min = tmp[1]; + for (idx = 1 ; idx < delays->no_of_delays ; idx += 1) { + if (tmp[idx] > t_max) t_max = tmp[idx]; + if (tmp[idx] < t_min) t_min = tmp[idx]; + } + tmp[DELAY_EDGE_0x] = t_min; + tmp[DELAY_EDGE_x1] = t_max; + tmp[DELAY_EDGE_1x] = t_min; + tmp[DELAY_EDGE_x0] = t_max; + tmp[DELAY_EDGE_xz] = t_max; + tmp[DELAY_EDGE_zx] = t_min; + } + fun->put_delay12(tmp); } From 5af8fff9802b6266886e8cc4c33ea240cafe5140 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 22 Nov 2007 18:22:46 -0800 Subject: [PATCH 4/4] Command line control of warnings Implement extended vvp command line options to control the amount of detail that the sdf annotator emits while parsing the source file. Signed-off-by: Stephen Williams --- vpi/sdf_parse.y | 67 ++++++++++++++++++++++++++++--------------------- vpi/sdf_priv.h | 2 ++ vpi/sys_sdf.c | 31 +++++++++++++++++++++++ vvp/vvp.man | 14 +++++++++++ 4 files changed, 86 insertions(+), 28 deletions(-) diff --git a/vpi/sdf_parse.y b/vpi/sdf_parse.y index 6d1551016..8ac41013c 100644 --- a/vpi/sdf_parse.y +++ b/vpi/sdf_parse.y @@ -91,35 +91,43 @@ sdfversion design_name : '(' K_DESIGN QSTRING ')' - { vpi_printf("SDF Design: %s\n", $3); - free($3); - } + { if (sdf_flag_inform) vpi_printf("%s:%d:SDF INFO: Design: %s\n", + sdf_parse_path, @2.first_line, $3); + free($3); + } ; date : '(' K_DATE QSTRING ')' - { vpi_printf("SDF Date: %s\n", $3); - free($3); - } + { if (sdf_flag_inform) vpi_printf("%s:%d:SDF INFO: Date: %s\n", + sdf_parse_path, @2.first_line, $3); + free($3); + } ; -vendor : '(' K_VENDOR QSTRING ')' - { vpi_printf("SDF Vendor: %s\n", $3); - free($3); - } +vendor + : '(' K_VENDOR QSTRING ')' + { if (sdf_flag_inform) vpi_printf("%s:%d:SDF INFO: Vendor: %s\n", + sdf_parse_path, @2.first_line, $3); + free($3); + } ; -program_name : '(' K_PROGRAM QSTRING ')' - { vpi_printf("SDF Program: %s\n", $3); - free($3); - } -; +program_name + : '(' K_PROGRAM QSTRING ')' + { if (sdf_flag_inform) vpi_printf("%s:%d:SDF INFO: Program: %s\n", + sdf_parse_path, @2.first_line, $3); + free($3); + } + ; -program_version : '(' K_VERSION QSTRING ')' - { vpi_printf("SDF Program Version: %s\n", $3); - free($3); - } -; +program_version + : '(' K_VERSION QSTRING ')' + { if (sdf_flag_inform) vpi_printf("%s:%d:SDF INFO: Program Version: %s\n", + sdf_parse_path, @2.first_line, $3); + free($3); + } + ; hierarchy_divider : '(' K_DIVIDER '.' ')' { use_hchar = '.'; } @@ -131,11 +139,13 @@ voltage | '(' K_VOLTAGE signed_real_number ')' ; -process : '(' K_PROCESS QSTRING ')' - { vpi_printf("SDF Process: %s\n", $3); - free($3); - } -; +process + : '(' K_PROCESS QSTRING ')' + { if (sdf_flag_inform) vpi_printf("%s:%d:SDF INFO: Process: %s\n", + sdf_parse_path, @2.first_line, $3); + free($3); + } + ; temperature : '(' K_TEMPERATURE rtriple ')' @@ -144,9 +154,10 @@ temperature time_scale : '(' K_TIMESCALE REAL_NUMBER IDENTIFIER ')' - { vpi_printf("SDF TIMESCALE : %f%s\n", $3, $4); - free($4); - } + { if (sdf_flag_inform) vpi_printf("%s:%d:SDF INFO: TIMESCALE : %f%s\n", + sdf_parse_path, @2.first_line, $3, $4); + free($4); + } ; cell_list diff --git a/vpi/sdf_priv.h b/vpi/sdf_priv.h index 5a981dd57..d76e5626b 100644 --- a/vpi/sdf_priv.h +++ b/vpi/sdf_priv.h @@ -28,6 +28,8 @@ */ extern void sdf_process_file(FILE*fd, const char*path); +extern int sdf_flag_warning; +extern int sdf_flag_inform; /* **** * These functions are called by the parser to process the SDF file as diff --git a/vpi/sys_sdf.c b/vpi/sys_sdf.c index d382738d3..681fafde9 100644 --- a/vpi/sys_sdf.c +++ b/vpi/sys_sdf.c @@ -29,6 +29,9 @@ * These are static context */ +int sdf_flag_warnings = 0; +int sdf_flag_inform = 0; + /* Scope of the $sdf_annotate call. Annotation starts here. */ static vpiHandle sdf_scope; /* The cell in process. */ @@ -134,8 +137,36 @@ void sdf_iopath_delays(const char*src, const char*dst, vpi_put_delays(path, &delays); } +static void check_command_line_args(void) +{ + struct t_vpi_vlog_info vlog_info; + int idx; + + static int sdf_command_line_done = 0; + if (sdf_command_line_done) + return; + + vpi_get_vlog_info(&vlog_info); + + for (idx = 0 ; idx < vlog_info.argc ; idx += 1) { + if (strcmp(vlog_info.argv[idx],"-sdf-warn") == 0) { + sdf_flag_warnings = 1; + + } else if (strcmp(vlog_info.argv[idx],"-sdf-info") == 0) { + sdf_flag_inform = 1; + + } else if (strcmp(vlog_info.argv[idx],"-sdf-verbose") == 0) { + sdf_flag_warnings = 1; + sdf_flag_inform = 1; + } + } + + sdf_command_line_done = 1; +} + static PLI_INT32 sys_sdf_annotate_compiletf(PLI_BYTE8*name) { + check_command_line_args(); return 0; } diff --git a/vvp/vvp.man b/vvp/vvp.man index 3ad520cd5..a3afa4e5b 100644 --- a/vvp/vvp.man +++ b/vvp/vvp.man @@ -96,6 +96,20 @@ space, and is written out incrementally. Thus, you can view lxt2 files while a simulation is still running (or paused) or if your simulation crashes or is killed, you still have a useful dump. +.TP 8 +.B -sdf-warn +When loading an SDF annnotation file, this option causes the annotator +to print warnings for questionable but non-fatal issues. + +.TP 8 +.B -sdf-info +When loading an SDF annnotation file, this option causes the annotator +to print information about the annotation. + +.TP 8 +.B -sdf-verbose +This is shorthand for -sdf-info -sdf-warn. + .SH ENVIRONMENT .PP The vvp command also accepts some environment variables that control