Merge branch 'sdf'

This commit is contained in:
Stephen Williams 2007-11-22 19:01:20 -08:00
commit ea70ae00aa
10 changed files with 806 additions and 7 deletions

View File

@ -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

View File

@ -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)

127
vpi/sdf_lexor.lex Normal file
View File

@ -0,0 +1,127 @@
%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 <stdlib.h>
# include <strings.h>
# include <assert.h>
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;
}
/*
* Create a string witout the leading and trailing quotes.
*/
static void process_quoted_string(void)
{
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);
void sdf_process_file(FILE*fd, const char*path)
{
yyrestart(fd);
sdf_parse_path = path;
sdfparse();
sdf_parse_path = 0;
}

308
vpi/sdf_parse.y Normal file
View File

@ -0,0 +1,308 @@
%{
/*
* 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 "sdf_priv.h"
# include <stdio.h>
/* This is the hierarchy separator to use. */
static char use_hchar = '.';
%}
%union {
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
%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 <string_val> QSTRING IDENTIFIER
%token <real_val> REAL_NUMBER
%token <int_val> INTEGER
%type <string_val> celltype
%type <string_val> cell_instance
%type <string_val> hierarchical_identifier
%type <string_val> port port_instance port_spec
%type <real_val> rvalue rtriple signed_real_number
%type <real_val> delval
%type <delval_list> delval_list
%%
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 ')'
{ free($3);
}
;
design_name
: '(' K_DESIGN QSTRING ')'
{ 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 ')'
{ 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 ')'
{ 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 ')'
{ 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 ')'
{ 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 = '.'; }
| '(' K_DIVIDER '/' ')' { use_hchar = '/'; }
;
voltage
: '(' K_VOLTAGE rtriple ')'
| '(' K_VOLTAGE signed_real_number ')'
;
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 ')'
| '(' K_TEMPERATURE signed_real_number ')'
;
time_scale
: '(' K_TIMESCALE REAL_NUMBER IDENTIFIER ')'
{ 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
: cell_list cell
| cell
;
cell
: '(' 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); }
;
celltype
: '(' K_CELLTYPE QSTRING ')'
{ $$ = $3; }
;
cell_instance
: '(' K_INSTANCE hierarchical_identifier ')'
{ $$ = $3; }
| '(' K_INSTANCE '*' ')'
{ $$ = 0; }
;
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 ')'
{ sdf_iopath_delays($3, $4, &$5);
free($3);
free($4);
}
| '(' 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 { $$ = $1; }
;
port
: hierarchical_identifier
{ $$ = $1; }
/* | hierarchical_identifier '[' INTEGER ']' */
;
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
: IDENTIFIER
{ $$ = $1; }
;
rtriple
: signed_real_number ':' signed_real_number ':' signed_real_number
{ $$ = $3; /* XXXX Assume typical value. */ }
;
signed_real_number
: REAL_NUMBER { $$ = $1; }
| '+' REAL_NUMBER { $$ = $2; }
| '-' REAL_NUMBER { $$ = -$2; }
;
%%
void yyerror(const char*msg)
{
fprintf(stderr, "SDF ERROR: %s\n", msg);
}

30
vpi/sdf_parse_priv.h Normal file
View File

@ -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

48
vpi/sdf_priv.h Normal file
View File

@ -0,0 +1,48 @@
#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 <stdio.h>
/*
* 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);
extern int sdf_flag_warning;
extern int sdf_flag_inform;
/* ****
* 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,
const struct sdf_delval_list_s*delval);
#endif

219
vpi/sys_sdf.c Normal file
View File

@ -0,0 +1,219 @@
/*
* 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 <stdlib.h>
# include <string.h>
# include <assert.h>
/*
* 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. */
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,
const struct sdf_delval_list_s*delval_list)
{
assert(sdf_cur_cell);
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(iter)) ) {
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(iter);
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 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;
}
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_scope = vpi_handle(vpiScope,sys);
sdf_cur_cell = 0;
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);
}

View File

@ -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
};

View File

@ -576,19 +576,53 @@ static void modpath_src_put_delays ( vpiHandle ref, p_vpi_delay delays )
vvp_fun_modpath_src *fun = dynamic_cast<vvp_fun_modpath_src*>(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);
}

View File

@ -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