Fix/enhance readmem/writemem routines, etc.

This patch adds compilef routines for the readmemb/h and
writememb/h system tasks. It also fixes some errors related
to arrays with negative range values. You can not specify a
negative address in the file, but arrays with negative range
values or negative start/finish argument to the tasks are
supported. It also generates an error when reading invalid
character from the input file.

A significant amount of the code is common between the two
styles of tasks so this has been grouped into common
routines.

It also adds a common routine for getting a string that will
be used as a file name. This routine is used by any task
that requires a file name value. If a filename has a
non-printable character it will be displayed as a \octal
constant to show what the character is.

Updates the dumping routines to match each other better,
improves some error messages and fixes a bug in the LXT2
dumper when dumping greater than 32 bit delays.
This commit is contained in:
Cary R 2009-02-24 16:47:46 -08:00 committed by Stephen Williams
parent fa02455f36
commit fa1160c4ab
10 changed files with 551 additions and 601 deletions

View File

@ -96,12 +96,12 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
int fail = 0;
char *mode_string = 0;
unsigned idx;
vpiHandle item = vpi_scan(argv);
vpiHandle fileh = vpi_scan(argv);
char *fname;
vpiHandle mode = vpi_scan(argv);
unsigned len;
/* Get the mode handle if it exists. */
if (mode) {
char *esc_md;
val.format = vpiStringVal;
vpi_get_value(mode, &val);
/* Verify that we have a string and that it is not NULL. */
@ -119,8 +119,10 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
vpi_printf("WARNING: %s:%d: ",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
esc_md = as_escaped(val.value.str);
vpi_printf("%s's mode argument (%s) is too long.\n",
name, val.value.str);
name, esc_md);
free(esc_md);
fail = 1;
} else {
unsigned bin = 0, plus = 0;
@ -150,8 +152,10 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
vpi_printf("WARNING: %s:%d: ",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
esc_md = as_escaped(val.value.str);
vpi_printf("%s's mode argument (%s) is invalid.\n",
name, val.value.str);
name, esc_md);
free(esc_md);
fail = 1;
break;
}
@ -162,49 +166,18 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
vpi_free_object(argv);
}
/* Get the string form of the file name from the file name
argument. */
val.format = vpiStringVal;
vpi_get_value(item, &val);
/* Verify that we have a string and that it is not NULL. */
if (val.format != vpiStringVal || !*(val.value.str)) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's file name argument is not a valid string.\n",
name);
fail = 1;
if (mode) free(mode_string);
}
/*
* Verify that the file name is composed of only printable
* characters.
*/
len = strlen(val.value.str);
for (idx = 0; idx < len; idx++) {
if (! isprint(val.value.str[idx])) {
char msg [64];
snprintf(msg, 64, "WARNING: %s:%d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s %s's file name argument contains non-"
"printable characters.\n", msg, name);
vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", val.value.str);
fail = 1;
if (mode) free(mode_string);
}
}
fname = get_filename(callh, name, fileh);
if (fname == 0 && mode) free(mode_string);
/* If either the mode or file name are not valid just return. */
if (fail) return 0;
if (fail || fname == 0) return 0;
val.format = vpiIntVal;
if (mode) {
val.value.integer = vpi_fopen(val.value.str, mode_string);
val.value.integer = vpi_fopen(fname, mode_string);
free(mode_string);
} else
val.value.integer = vpi_mcd_open(val.value.str);
val.value.integer = vpi_mcd_open(fname);
vpi_put_value(callh, &val, 0, vpiNoDelay);
@ -220,51 +193,23 @@ static PLI_INT32 sys_fopenrwa_calltf(PLI_BYTE8*name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle file = vpi_scan(argv);
s_vpi_value val;
char *mode;
unsigned idx, len;
char *mode, *fname;
vpi_free_object(argv);
/* Get the mode. */
mode = name + strlen(name) - 1;
/* Get the filename. */
val.format = vpiStringVal;
vpi_get_value(file, &val);
/* Verify that we have a string and that it is not NULL. */
if (val.format != vpiStringVal || !*(val.value.str)) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's file name argument is not a valid string.\n",
name);
return 0;
}
/*
* Verify that the file name is composed of only printable
* characters.
*/
len = strlen(val.value.str);
for (idx = 0; idx < len; idx++) {
if (! isprint(val.value.str[idx])) {
char msg [64];
snprintf(msg, 64, "WARNING: %s:%d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s %s's file name argument contains non-"
"printable characters.\n", msg, name);
vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", val.value.str);
return 0;
}
}
/* Get the file name. */
fname = get_filename(callh, name, vpi_scan(argv));
vpi_free_object(argv);
if (fname == 0) return 0;
/* Open the file and return the result. */
val.format = vpiIntVal;
val.value.integer = vpi_fopen(val.value.str, mode);
val.value.integer = vpi_fopen(fname, mode);
vpi_put_value(callh, &val, 0, vpiNoDelay);
free(fname);
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2009 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
@ -168,7 +168,7 @@ static void show_this_item(struct vcd_info*info)
{
s_vpi_value value;
if (vpi_get(vpiType,info->item) == vpiRealVar) {
if (vpi_get(vpiType, info->item) == vpiRealVar) {
value.format = vpiRealVal;
vpi_get_value(info->item, &value);
lt_emit_value_double(dump_file, info->sym, 0, value.value.real);
@ -177,8 +177,8 @@ static void show_this_item(struct vcd_info*info)
value.format = vpiBinStrVal;
vpi_get_value(info->item, &value);
lt_emit_value_bit_string(dump_file, info->sym,
0 /* array row */,
value.value.str);
0 /* array row */,
value.value.str);
}
}
@ -252,10 +252,10 @@ static PLI_INT32 variable_cb_1(p_cb_data cause)
struct t_cb_data cb;
struct vcd_info*info = (struct vcd_info*)cause->user_data;
if (dump_is_full) return 0;
if (dump_is_off) return 0;
if (dump_is_full) return 0;
if (dump_is_off) return 0;
if (dump_header_pending()) return 0;
if (info->scheduled) return 0;
if (info->scheduled) return 0;
if ((dump_limit > 0) && (ftell(dump_file->handle) > dump_limit)) {
dump_is_full = 1;
@ -280,8 +280,7 @@ static PLI_INT32 variable_cb_1(p_cb_data cause)
static PLI_INT32 dumpvars_cb(p_cb_data cause)
{
if (dumpvars_status != 1)
return 0;
if (dumpvars_status != 1) return 0;
dumpvars_status = 2;
@ -298,13 +297,11 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause)
static PLI_INT32 finish_cb(p_cb_data cause)
{
if (finish_status != 0)
return 0;
if (finish_status != 0) return 0;
finish_status = 1;
dumpvars_time = timerec_to_time64(cause->time);
if (!dump_is_off && !dump_is_full && dumpvars_time != vcd_cur_time) {
lt_set_time64(dump_file, dumpvars_time);
}
@ -317,8 +314,7 @@ __inline__ static int install_dumpvars_callback(void)
struct t_cb_data cb;
static struct t_vpi_time now;
if (dumpvars_status == 1)
return 0;
if (dumpvars_status == 1) return 0;
if (dumpvars_status == 2) {
vpi_printf("LXT warning: $dumpvars ignored, previously"
@ -362,8 +358,8 @@ static PLI_INT32 sys_dumpoff_calltf(PLI_BYTE8*name)
now64 = timerec_to_time64(&now);
if (now64 > vcd_cur_time) {
lt_set_time64(dump_file, now64);
vcd_cur_time = now64;
lt_set_time64(dump_file, now64);
vcd_cur_time = now64;
}
lt_set_dumpoff(dump_file);
@ -389,8 +385,8 @@ static PLI_INT32 sys_dumpon_calltf(PLI_BYTE8*name)
now64 = timerec_to_time64(&now);
if (now64 > vcd_cur_time) {
lt_set_time64(dump_file, now64);
vcd_cur_time = now64;
lt_set_time64(dump_file, now64);
vcd_cur_time = now64;
}
lt_set_dumpon(dump_file);
@ -412,9 +408,9 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
vpi_get_time(0, &now);
now64 = timerec_to_time64(&now);
if (now64> vcd_cur_time) {
lt_set_time64(dump_file, now64);
vcd_cur_time = now64;
if (now64 > vcd_cur_time) {
lt_set_time64(dump_file, now64);
vcd_cur_time = now64;
}
vcd_checkpoint();
@ -450,7 +446,7 @@ static void open_dumpfile(vpiHandle callh)
lt_set_timescale(dump_file, prec);
lt_set_initial_value(dump_file, 'x');
lt_set_clock_compress(dump_file);
lt_set_clock_compress(dump_file);
atexit((void(*)(void))close_dumpfile);
}
@ -460,31 +456,33 @@ static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
s_vpi_value value;
char*path;
char *path;
/* $dumpfile must be called before $dumpvars starts! */
if (dumpvars_status != 0) {
vpi_printf("LXT warning: %s called after $dumpvars started,\n"
" using existing file (%s).\n",
name, dump_path);
char msg [64];
snprintf(msg, 64, "LXT warning: %s:%d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s %s called after $dumpvars started,\n", msg, name);
vpi_printf("%*s using existing file (%s).\n",
(int) strlen(msg), " ", dump_path);
vpi_free_object(argv);
return 0;
}
assert(argv);
value.format = vpiStringVal;
vpi_get_value(vpi_scan(argv), &value);
path = strdup(value.value.str);
path = get_filename(callh, name, vpi_scan(argv));
vpi_free_object(argv);
if (! path) return 0;
if (dump_path) {
vpi_printf("LXT warning: Overriding dump file %s with %s\n",
dump_path, path);
vpi_printf("LXT warning: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("Overriding dump file %s with %s.\n", dump_path, path);
free(dump_path);
}
dump_path = path;
vpi_free_object(argv);
return 0;
}
@ -500,12 +498,11 @@ static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle limit = vpi_scan(argv);
s_vpi_value val;
/* Get the value and set the dump limit. */
val.format = vpiIntVal;
vpi_get_value(limit, &val);
vpi_get_value(vpi_scan(argv), &val);
dump_limit = val.value.integer;
vpi_free_object(argv);
@ -566,8 +563,12 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
info = malloc(sizeof(*info));
info->time.type = vpiSimTime;
info->item = item;
info->sym = lt_symbol_add(dump_file, ident, 0 /* array rows */, vpi_get(vpiLeftRange, item), vpi_get(vpiRightRange, item), LT_SYM_F_BITS);
info->item = item;
info->sym = lt_symbol_add(dump_file, ident,
0 /* array rows */,
vpi_get(vpiLeftRange, item),
vpi_get(vpiRightRange, item),
LT_SYM_F_BITS);
info->scheduled = 0;
cb.time = &info->time;
@ -603,8 +604,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
info = malloc(sizeof(*info));
info->time.type = vpiSimTime;
info->item = item;
info->sym = lt_symbol_add(dump_file, ident, 0 /* array rows */, vpi_get(vpiSize, item)-1, 0, LT_SYM_F_DOUBLE);
info->item = item;
info->sym = lt_symbol_add(dump_file, ident,
0 /* array rows */,
vpi_get(vpiSize, item)-1,
0, LT_SYM_F_DOUBLE);
info->scheduled = 0;
cb.time = &info->time;
@ -675,8 +679,7 @@ static int draw_scope(vpiHandle item)
const char *name;
vpiHandle scope = vpi_handle(vpiScope, item);
if (!scope)
return 0;
if (!scope) return 0;
depth = 1 + draw_scope(scope);
name = vpi_get_str(vpiName, scope);
@ -696,10 +699,16 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name)
if (dump_file == 0) {
open_dumpfile(callh);
if (dump_file == 0) return 0;
if (dump_file == 0) {
vpi_free_object(argv);
return 0;
}
}
if (install_dumpvars_callback()) return 0;
if (install_dumpvars_callback()) {
vpi_free_object(argv);
return 0;
}
/* Get the depth if it exists. */
if (argv) {
@ -727,7 +736,9 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name)
}
/* Most effective compression. */
if (lxm_optimum_mode == LXM_SPACE) lt_set_no_interlace(dump_file);
if (lxm_optimum_mode == LXM_SPACE) {
lt_set_no_interlace(dump_file);
}
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2009 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
@ -142,7 +142,7 @@ static char *create_full_name(const char *name)
}
static char *dump_path;
static char *dump_path = 0;
static struct lxt2_wr_trace *dump_file = 0;
struct vcd_info {
@ -169,7 +169,7 @@ static void show_this_item(struct vcd_info*info)
{
s_vpi_value value;
if (vpi_get(vpiType,info->item) == vpiRealVar) {
if (vpi_get(vpiType, info->item) == vpiRealVar) {
value.format = vpiRealVal;
vpi_get_value(info->item, &value);
lxt2_wr_emit_value_double(dump_file, info->sym, 0,
@ -179,8 +179,8 @@ static void show_this_item(struct vcd_info*info)
value.format = vpiBinStrVal;
vpi_get_value(info->item, &value);
lxt2_wr_emit_value_bit_string(dump_file, info->sym,
0 /* array row */,
value.value.str);
0 /* array row */,
value.value.str);
}
}
@ -360,8 +360,8 @@ static PLI_INT32 sys_dumpoff_calltf(PLI_BYTE8*name)
now64 = timerec_to_time64(&now);
if (now64 > vcd_cur_time) {
lxt2_wr_set_time(dump_file, now64);
vcd_cur_time = now.low;
lxt2_wr_set_time(dump_file, now64);
vcd_cur_time = now64;
}
lxt2_wr_set_dumpoff(dump_file);
@ -387,8 +387,8 @@ static PLI_INT32 sys_dumpon_calltf(PLI_BYTE8*name)
now64 = timerec_to_time64(&now);
if (now64 > vcd_cur_time) {
lxt2_wr_set_time64(dump_file, now64);
vcd_cur_time = now64;
lxt2_wr_set_time64(dump_file, now64);
vcd_cur_time = now64;
}
lxt2_wr_set_dumpon(dump_file);
@ -410,9 +410,10 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
vpi_get_time(0, &now);
now64 = timerec_to_time64(&now);
if (now64 > vcd_cur_time)
lxt2_wr_set_time64(dump_file, now64);
vcd_cur_time = now64;
if (now64 > vcd_cur_time) {
lxt2_wr_set_time64(dump_file, now64);
vcd_cur_time = now64;
}
vcd_checkpoint();
@ -458,33 +459,35 @@ static void open_dumpfile(vpiHandle callh)
static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
s_vpi_value value;
char*path;
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
char *path;
/* $dumpfile must be called before $dumpvars starts! */
if (dumpvars_status != 0) {
vpi_printf("LXT2 warning: %s called after $dumpvars started,\n"
" using existing file (%s).\n",
name, dump_path);
char msg [64];
snprintf(msg, 64, "LXT2 warning: %s:%d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s %s called after $dumpvars started,\n", msg, name);
vpi_printf("%*s using existing file (%s).\n",
(int) strlen(msg), " ", dump_path);
vpi_free_object(argv);
return 0;
}
assert(argv);
value.format = vpiStringVal;
vpi_get_value(vpi_scan(argv), &value);
path = strdup(value.value.str);
path = get_filename(callh, name, vpi_scan(argv));
vpi_free_object(argv);
if (! path) return 0;
if (dump_path) {
vpi_printf("LXT2 warning: Overriding dump file %s with %s.\n",
dump_path, path);
vpi_printf("LXT2 warning: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("Overriding dump file %s with %s.\n", dump_path, path);
free(dump_path);
}
dump_path = path;
vpi_free_object(argv);
return 0;
}
@ -572,12 +575,12 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
info = malloc(sizeof(*info));
info->time.type = vpiSimTime;
info->item = item;
info->sym = lxt2_wr_symbol_add(dump_file, ident,
0 /* array rows */,
vpi_get(vpiLeftRange, item),
vpi_get(vpiRightRange, item),
LXT2_WR_SYM_F_BITS);
info->item = item;
info->sym = lxt2_wr_symbol_add(dump_file, ident,
0 /* array rows */,
vpi_get(vpiLeftRange, item),
vpi_get(vpiRightRange, item),
LXT2_WR_SYM_F_BITS);
info->scheduled = 0;
cb.time = &info->time;
@ -613,11 +616,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
info = malloc(sizeof(*info));
info->time.type = vpiSimTime;
info->item = item;
info->sym = lxt2_wr_symbol_add(dump_file, ident,
0 /* array rows */,
vpi_get(vpiSize, item)-1,
0, LXT2_WR_SYM_F_DOUBLE);
info->item = item;
info->sym = lxt2_wr_symbol_add(dump_file, ident,
0 /* array rows */,
vpi_get(vpiSize, item)-1,
0, LXT2_WR_SYM_F_DOUBLE);
info->scheduled = 0;
cb.time = &info->time;
@ -708,10 +711,16 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name)
if (dump_file == 0) {
open_dumpfile(callh);
if (dump_file == 0) return 0;
if (dump_file == 0) {
vpi_free_object(argv);
return 0;
}
}
if (install_dumpvars_callback()) return 0;
if (install_dumpvars_callback()) {
vpi_free_object(argv);
return 0;
}
/* Get the depth if it exists. */
if (argv) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2009 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
@ -18,6 +18,8 @@
*/
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "sys_priv.h"
@ -32,6 +34,73 @@ PLI_UINT64 timerec_to_time64(const struct t_vpi_time*time)
return tmp;
}
char * as_escaped(char *arg)
{
unsigned idx, cur, cnt, len = strlen(arg);
char *res = (char *) malloc(sizeof(char *) * len);
cur = 0;
cnt = len;
for (idx = 0; idx < cnt; idx++) {
if (isprint(arg[idx])) {
res[cur] = arg[idx];
cur += 1;
} else {
len += 3;
res = (char *) realloc(res, sizeof(char *) * len);
sprintf(&(res[cur]), "\\%03o", arg[idx]);
cur += 4;
}
}
res[cur] = 0;
return res;
}
/*
* Generic routine to get the filename from the given handle.
* The result is duplicated so call free when the name is no
* longer needed. Returns 0 (NULL) for an error.
*/
char * get_filename(vpiHandle callh, char *name, vpiHandle file)
{
s_vpi_value val;
unsigned len, idx;
/* Get the filename. */
val.format = vpiStringVal;
vpi_get_value(file, &val);
/* Verify that we have a string and that it is not NULL. */
if (val.format != vpiStringVal || !*(val.value.str)) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's file name argument (%s) is not a valid string.\n",
name, vpi_get_str(vpiType, file));
return 0;
}
/*
* Verify that the file name is composed of only printable
* characters.
*/
len = strlen(val.value.str);
for (idx = 0; idx < len; idx++) {
if (! isprint(val.value.str[idx])) {
char msg [64];
char *esc_fname = as_escaped(val.value.str);
snprintf(msg, 64, "WARNING: %s:%d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s %s's file name argument contains non-"
"printable characters.\n", msg, name);
vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", esc_fname);
free(esc_fname);
return 0;
}
}
return strdup(val.value.str);
}
/*
* This routine returns 1 if the argument is a constant value,
* otherwise it returns 0.

View File

@ -1,7 +1,7 @@
#ifndef __vpi_sys_priv_H
#define __vpi_sys_priv_H
/*
* Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2009 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
@ -35,6 +35,9 @@ extern unsigned long genrand(struct context_s *context);
extern PLI_UINT64 timerec_to_time64(const struct t_vpi_time*time);
extern char * as_escaped(char *arg);
extern char * get_filename(vpiHandle callh, char *name, vpiHandle file);
struct timeformat_info_s {
int units;
unsigned prec;

View File

@ -20,105 +20,267 @@
# include "vpi_config.h"
# include "vpi_user.h"
# include "sys_priv.h"
# include <ctype.h>
# include <string.h>
# include <stdlib.h>
# include <stdio.h>
# include <assert.h>
# include "sys_readmem_lex.h"
static int check_integer_constant(char*name, vpiHandle handle)
static void get_mem_params(vpiHandle argv, vpiHandle callh, char *name,
char **fname, vpiHandle *mitem,
vpiHandle *start_item, vpiHandle *stop_item)
{
if (vpi_get(vpiType, handle) != vpiConstant){
vpi_printf("ERROR: %s parameter must be a constant (vpiType=%d)\n",
name, vpi_get(vpiType, handle));
return 0;
}
/* Get the first parameter (file name). */
*fname = get_filename(callh, name, vpi_scan(argv));
switch(vpi_get(vpiConstType, handle)){
case vpiDecConst:
case vpiBinaryConst:
case vpiOctConst:
case vpiHexConst:
return 1;
break;
/* Get the second parameter (memory). */
*mitem = vpi_scan(argv);
/* We rely on vpi_get_value for reals and strings to return a correct */
/* integer value when this is requested. So only a warning is generated. */
case vpiRealConst:
vpi_printf("Warning: real supplied to %s instead of integer.\n", name);
return 1;
break;
/* Get optional third parameter (start address). */
*start_item = vpi_scan(argv);
if (*start_item) {
/* Warn the user if they gave a real value for the start
* address. */
switch (vpi_get(vpiType, *start_item)) {
case vpiConstant:
case vpiParameter:
if (vpi_get(vpiConstType, *start_item) != vpiRealConst) break;
case vpiRealVar:
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's third argument (start address) is a real "
"value.\n", name);
}
case vpiStringConst:
vpi_printf("Warning: string supplied to %s instead of integer.\n", name);
return 1;
break;
}
/* switch statement covers all possibilities. Code should never come here... */
assert(0);
return 0;
/* Get optional forth parameter (finish address). */
*stop_item = vpi_scan(argv);
if (*stop_item) {
/* Warn the user if they gave a real value for the finish
* address. */
switch (vpi_get(vpiType, *stop_item)) {
case vpiConstant:
case vpiParameter:
if (vpi_get(vpiConstType, *stop_item) != vpiRealConst) {
break;
}
case vpiRealVar:
vpi_printf("WARNING: %s:%d: ",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's fourth argument (finish address) is a "
"real value.\n", name);
}
vpi_free_object(argv);
}
} else {
*stop_item = 0;
}
}
/*
* This function makes sure the handle is of an object that can get a
* string value for a file name.
*/
static int check_file_name(const char*name, vpiHandle item)
static int process_params(vpiHandle mitem,
vpiHandle start_item, vpiHandle stop_item,
vpiHandle callh, char *name,
int *start_addr, int *stop_addr, int *addr_incr,
int *min_addr, int *max_addr)
{
switch (vpi_get(vpiType, item)) {
s_vpi_value val;
int left_addr, right_addr;
case vpiConstant:
if (vpi_get(vpiConstType, item) != vpiStringConst) {
vpi_printf("ERROR: %s argument 1: file name argument "
"must be a string.\n", name);
return 0;
}
break;
/* Get left addr of memory */
val.format = vpiIntVal;
vpi_get_value(vpi_handle(vpiLeftRange, mitem), &val);
left_addr = val.value.integer;
case vpiParameter:
if (vpi_get(vpiConstType,item) != vpiStringConst) {
vpi_printf("ERROR: %s argument 1: Parameter %s is "
"not a string in this context.\n",
name, vpi_get_str(vpiName,item));
return 0;
}
break;
/* Get right addr of memory */
val.format = vpiIntVal;
vpi_get_value(vpi_handle(vpiRightRange, mitem), &val);
right_addr = val.value.integer;
case vpiReg:
break;
/* Get start_addr, stop_addr and addr_incr */
if (! start_item) {
*start_addr = left_addr<right_addr ? left_addr : right_addr;
*stop_addr = left_addr<right_addr ? right_addr : left_addr;
*addr_incr = 1;
} else {
val.format = vpiIntVal;
vpi_get_value(start_item, &val);
*start_addr = val.value.integer;
default:
vpi_printf("ERROR: %s argument 1: must be a string\n", name);
if (! stop_item) {
*stop_addr = left_addr<right_addr ? right_addr : left_addr;
*addr_incr = 1;
} else {
val.format = vpiIntVal;
vpi_get_value(stop_item, &val);
*stop_addr = val.value.integer;
*addr_incr = *start_addr<*stop_addr ? 1 : -1;
}
}
/* Find the minimum and maximum address. */
*min_addr = *start_addr<*stop_addr ? *start_addr : *stop_addr ;
*max_addr = *start_addr<*stop_addr ? *stop_addr : *start_addr;
/* If the range is not fully specified and the left address is
* greater than the right address. Print a warning that this
* code follows 1364-2005.
*
* If we passed a generation flag we could do the correct thing
* for 1364-1995 and 1364-2001 instead of this general warning
* or we could only show the warning when using 2001/1995.
*/
if (!stop_item && (left_addr > right_addr)) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s: Standard inconsistency, following 1364-2005.\n",
name);
}
/* Check that start_addr and stop_addr are within the memory
range */
if (left_addr < right_addr) {
if (*start_addr < left_addr || *start_addr > right_addr) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s: Start address %d is out of bounds for memory "
"\'%s[%d:%d]\'!\n", name, *start_addr,
vpi_get_str(vpiFullName, mitem),
left_addr, right_addr);
return 1;
}
if (*stop_addr < left_addr || *stop_addr > right_addr) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s: Finish address %d is out of bounds for memory "
"\'%s[%d:%d]\'!\n", name, *stop_addr,
vpi_get_str(vpiFullName, mitem),
left_addr, right_addr);
return 1;
}
} else {
if (*start_addr < right_addr || *start_addr > left_addr) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s: Start address %d is out of bounds for memory "
"\'%s[%d:%d]\'!\n", name, *start_addr,
vpi_get_str(vpiFullName, mitem),
left_addr, right_addr);
return 1;
}
if (*stop_addr < right_addr || *stop_addr > left_addr) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s: Finish address %d is out of bounds for memory "
"\'%s[%d:%d]\'!\n", name, *stop_addr,
vpi_get_str(vpiFullName, mitem),
left_addr, right_addr);
return 1;
}
}
return 0;
}
static PLI_INT32 sys_mem_compiletf(PLI_BYTE8*name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle arg;
/* Check that there is a file name argument. */
if (argv == 0) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s requires two arguments.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
if (! is_string_obj(vpi_scan(argv))) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's first argument must be a file name (string).\n",
name);
vpi_control(vpiFinish, 1);
}
/* Check that there is a memory argument. */
arg = vpi_scan(argv);
if (! arg) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s requires a second (memory) argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
return 1;
}
if (vpi_get(vpiType, arg) != vpiMemory) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's second argument must be a memory.\n", name);
vpi_control(vpiFinish, 1);
}
/* Check if there is a starting address argument. */
arg = vpi_scan(argv);
if (! arg) return 0;
if (! is_numeric_obj(arg)) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's third argument must be a start address "
"(numeric).\n", name);
vpi_control(vpiFinish, 1);
}
/* Check if there is a finish address argument. */
arg = vpi_scan(argv);
if (! arg) return 0;
if (! is_numeric_obj(arg)) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's fourth argument must be a finish address "
"(numeric).\n", name);
vpi_control(vpiFinish, 1);
}
/* Make sure there are no extra arguments. */
if (vpi_scan(argv) != 0) {
char msg [64];
unsigned argc;
snprintf(msg, 64, "ERROR: %s:%d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
argc = 1;
while (vpi_scan(argv)) argc += 1;
vpi_printf("%s %s takes at most four arguments.\n",
msg, name);
vpi_printf("%*s Found %u extra argument%s.\n",
(int) strlen(msg), " ", argc, argc == 1 ? "" : "s");
vpi_control(vpiFinish, 1);
}
return 0;
}
static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name)
{
int code;
int wwid;
char*path;
char*mem_name;
int code, wwid, addr;
FILE*file;
unsigned addr;
char *fname = 0;
s_vpi_value value;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle item = vpi_scan(argv);
vpiHandle mitem;
vpiHandle start_item;
vpiHandle stop_item;
vpiHandle left_range;
vpiHandle right_range;
vpiHandle word_index;
/* These are left and right hand side parameters in the
declaration of the memory. */
int left_addr, right_addr;
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle mitem = 0;
vpiHandle start_item = 0;
vpiHandle stop_item = 0;
/* start_addr and stop_addr are the parameters given to $readmem in the
Verilog code. When not specified, start_addr is equal to the lower of
@ -128,159 +290,37 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name)
/* min_addr and max_addr are equal to start_addr and stop_addr if
start_addr<stop_addr or vice versa if not... */
unsigned min_addr, max_addr;
int min_addr, max_addr;
/* This is the number of words that we need from the memory. */
/* This is the number of words that we need from the memory. */
unsigned word_count;
/*======================================== Get parameters */
if (item == 0) {
vpi_printf("%s: file name parameter missing.\n", name);
return 0;
}
/* Check then get the first argument, the file name. It is
possible that Verilog would right-justify a name to fit a
reg value to fit the reg width, so chop off leading white
space in the process. */
if (check_file_name(name, item) == 0) {
vpi_free_object(argv);
return 0;
}
value.format = vpiStringVal;
vpi_get_value(item, &value);
path = strdup(value.value.str + strspn(value.value.str, " "));
/* Get and check the second parameter. It must be a memory. */
mitem = vpi_scan(argv);
if (mitem == 0) {
vpi_printf("%s: Missing memory parameter\n", name);
free(path);
return 0;
}
if (vpi_get(vpiType, mitem) != vpiMemory) {
vpi_printf("%s: Second parameter must be a memory.\n", name);
free(path);
vpi_free_object(argv);
return 0;
}
mem_name = vpi_get_str(vpiFullName, mitem);
/* Get optional third parameter. It must be a constant. */
start_item = vpi_scan(argv);
if (start_item!=0){
if (check_integer_constant(name, start_item) == 0){
vpi_free_object(argv);
return 0;
}
/* Get optional forth parameter. It must be a constant. */
stop_item = vpi_scan(argv);
if (stop_item!=0){
if (check_integer_constant(name, stop_item) == 0){
vpi_free_object(argv);
return 0;
}
/* Check that there is no 5th parameter */
if (vpi_scan(argv) != 0){
vpi_printf("ERROR: %s accepts maximum 4 parameters!\n", name );
vpi_free_object(argv);
return 0;
}
}
}
else{
stop_item = 0;
}
get_mem_params(argv, callh, name,
&fname, &mitem, &start_item, &stop_item);
if (fname == 0) return 0;
/*======================================== Process parameters */
if (process_params(mitem, start_item, stop_item, callh, name,
&start_addr, &stop_addr, &addr_incr,
&min_addr, &max_addr)) return 0;
/* Open the data file. */
file = fopen(path, "r");
file = fopen(fname, "r");
if (file == 0) {
vpi_printf("%s: Unable to open %s for reading.\n", name, path);
free(path);
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s: Unable to open %s for reading.\n", name, fname);
free(fname);
return 0;
}
/* Get left addr of memory */
left_range = vpi_handle(vpiLeftRange, mitem);
value.format = vpiIntVal;
vpi_get_value(left_range, &value);
left_addr = value.value.integer;
/* Get right addr of memory */
right_range = vpi_handle(vpiRightRange, mitem);
value.format = vpiIntVal;
vpi_get_value(right_range, &value);
right_addr = value.value.integer;
/* Get start_addr, stop_addr and addr_incr */
if (start_item==0){
start_addr = left_addr<right_addr ? left_addr : right_addr;
stop_addr = left_addr<right_addr ? right_addr : left_addr;
addr_incr = 1;
}
else{
s_vpi_value value2;
value2.format = vpiIntVal;
vpi_get_value(start_item, &value2);
start_addr = value2.value.integer;
if (stop_item==0){
stop_addr = left_addr<right_addr ? right_addr : left_addr;
addr_incr = 1;
}
else{
s_vpi_value value3;
value3.format = vpiIntVal;
vpi_get_value(stop_item, &value3);
stop_addr = value3.value.integer;
addr_incr = start_addr<stop_addr ? 1 : -1;
}
}
min_addr = start_addr<stop_addr ? start_addr : stop_addr ;
max_addr = start_addr<stop_addr ? stop_addr : start_addr;
/* We need this many words from the file. */
word_count = max_addr-min_addr+1;
/* Check that start_addr and stop_addr are within the memory
range */
if (left_addr<right_addr){
if (start_addr<left_addr || start_addr > right_addr) {
vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name);
return 0;
}
if (stop_addr<left_addr || stop_addr > right_addr) {
vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name);
return 0;
}
}
else{
if (start_addr<right_addr || start_addr > left_addr) {
vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name);
return 0;
}
if (stop_addr<right_addr || stop_addr > left_addr) {
vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name);
return 0;
}
}
item = vpi_handle_by_index(mitem,min_addr);
wwid = vpi_get(vpiSize, item);
wwid = vpi_get(vpiSize, vpi_handle_by_index(mitem, min_addr));
/* variable that will be uses by the lexer to pass values
back to this code */
@ -293,7 +333,6 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name)
else
sys_readmem_start_file(file, 0, wwid, value.value.vector);
/*======================================== Read memory file */
/* Run through the input file and store the new contents in the memory */
@ -302,44 +341,67 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name)
switch (code) {
case MEM_ADDRESS:
addr = value.value.vector->aval;
if (addr < min_addr || addr > max_addr) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s(%s): address (0x%x) is out of range "
"[0x%x:0x%x]\n",
name, fname, addr, start_addr, stop_addr);
goto bailout;
}
/* if there is an address in the memory file, then
turn off any possible warnings about not having
enough words to load the memory. This is standard
behavior. */
behavior from 1364-2005. */
word_count = 0;
break;
case MEM_WORD:
if (addr >= min_addr && addr <= max_addr){
if (addr >= min_addr && addr <= max_addr) {
vpiHandle word_index;
word_index = vpi_handle_by_index(mitem, addr);
assert(word_index);
vpi_put_value(word_index, &value, 0, vpiNoDelay);
if (word_count > 0)
word_count -= 1;
}
else{
vpi_printf("%s(%s): address (0x%x) out of range (0x%x:0x%x)\n",
name, path, addr, start_addr, stop_addr);
if (word_count > 0) word_count -= 1;
} else {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s(%s): Too many words in the file for the "
"requested range [%d:%d].\n",
name, fname, start_addr, stop_addr);
goto bailout;
}
addr += addr_incr;
break;
case MEM_ERROR:
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s(%s): Invalid input character: %s\n", name,
fname, readmem_error_token);
goto bailout;
break;
default:
vpi_printf("Huh?! (%d)\n", code);
assert(0);
break;
}
}
if (word_count > 0)
vpi_printf("%s(%s): Not enough words in the read file "
"for requested range.\n", name, path);
/* Print a warning if there are not enough words in the data file. */
if (word_count > 0) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s(%s): Not enough words in the file for the "
"requested range [%d:%d].\n", name, fname,
start_addr, stop_addr);
}
bailout:
free(value.value.vector);
free(path);
free(fname);
fclose(file);
destroy_readmem_lexor(file);
return 0;
@ -347,197 +409,53 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name)
static PLI_INT32 sys_writemem_calltf(PLI_BYTE8*name)
{
int wwid;
char*path;
char*mem_name;
int addr;
FILE*file;
unsigned addr = 0;
unsigned cnt = 0;
char*fname = 0;
unsigned cnt;
s_vpi_value value;
vpiHandle words;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle item = vpi_scan(argv);
vpiHandle mitem;
vpiHandle start_item;
vpiHandle stop_item;
vpiHandle word_index;
vpiHandle left_range;
vpiHandle right_range;
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle mitem = 0;
vpiHandle start_item = 0;
vpiHandle stop_item = 0;
int left_addr, right_addr;
int start_addr, stop_addr, addr_incr;
int min_addr, max_addr;
int min_addr, max_addr; // Not used in this routine.
/*======================================== Get parameters */
if (item == 0) {
vpi_printf("%s: file name parameter missing.\n", name);
return 0;
}
get_mem_params(argv, callh, name,
&fname, &mitem, &start_item, &stop_item);
if (vpi_get(vpiType, item) != vpiConstant) {
vpi_printf("ERROR: %s parameter must be a constant\n", name);
vpi_free_object(argv);
return 0;
}
if (vpi_get(vpiConstType, item) != vpiStringConst) {
vpi_printf("ERROR: %s parameter must be a string\n", name);
vpi_free_object(argv);
return 0;
}
value.format = vpiStringVal;
vpi_get_value(item, &value);
path = strdup(value.value.str);
/* Get and check the second parameter. It must be a memory. */
mitem = vpi_scan(argv);
if (mitem == 0) {
vpi_printf("%s: Missing memory parameter\n", name);
free(path);
return 0;
}
if (vpi_get(vpiType, mitem) != vpiMemory) {
vpi_printf("%s: Second parameter must be a memory.\n", name);
free(path);
vpi_free_object(argv);
return 0;
}
mem_name = vpi_get_str(vpiFullName, mitem);
/* Get optional third parameter. It must be a constant. */
start_item = vpi_scan(argv);
if (start_item!=0){
if (check_integer_constant(name, start_item) == 0){
free(path);
vpi_free_object(argv);
return 0;
}
/* Get optional forth parameter. It must be a constant. */
stop_item = vpi_scan(argv);
if (stop_item!=0){
if (check_integer_constant(name, stop_item) == 0){
free(path);
vpi_free_object(argv);
return 0;
}
/* Check that there is no 5th parameter */
if (vpi_scan(argv) != 0){
vpi_printf("ERROR: %s accepts maximum 4 parameters!\n", name );
free(path);
vpi_free_object(argv);
return 0;
}
}
}
else{
stop_item = 0;
}
if (fname == 0) return 0;
/*======================================== Process parameters */
if (process_params(mitem, start_item, stop_item, callh, name,
&start_addr, &stop_addr, &addr_incr,
&min_addr, &max_addr)) return 0;
/* Open the data file. */
file = fopen(path, "w");
file = fopen(fname, "w");
if (file == 0) {
vpi_printf("%s: Unable to open %s for writing.\n", name, path);
free(path);
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s: Unable to open %s for writing.\n", name, fname);
free(fname);
return 0;
}
/* Get left addr of memory */
left_range = vpi_handle(vpiLeftRange, mitem);
value.format = vpiIntVal;
vpi_get_value(left_range, &value);
left_addr = value.value.integer;
/* Get right addr of memory */
right_range = vpi_handle(vpiRightRange, mitem);
value.format = vpiIntVal;
vpi_get_value(right_range, &value);
right_addr = value.value.integer;
/* Get start_addr, stop_addr and addr_incr */
if (start_item==0){
start_addr = left_addr<right_addr ? left_addr : right_addr;
stop_addr = left_addr<right_addr ? right_addr : left_addr;
addr_incr = 1;
}
else{
s_vpi_value value2;
value2.format = vpiIntVal;
vpi_get_value(start_item, &value2);
start_addr = value2.value.integer;
if (stop_item==0){
stop_addr = left_addr<right_addr ? right_addr : left_addr;
addr_incr = 1;
}
else{
s_vpi_value value3;
value3.format = vpiIntVal;
vpi_get_value(stop_item, &value3);
stop_addr = value3.value.integer;
addr_incr = start_addr<stop_addr ? 1 : -1;
}
}
min_addr = start_addr<stop_addr ? start_addr : stop_addr ;
max_addr = start_addr<stop_addr ? stop_addr : start_addr;
/* Check that start_addr and stop_addr are within the memory
range */
if (left_addr<right_addr){
if (start_addr<left_addr || start_addr > right_addr) {
vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name);
return 0;
}
if (stop_addr<left_addr || stop_addr > right_addr) {
vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name);
return 0;
}
}
else{
if (start_addr<right_addr || start_addr > left_addr) {
vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name);
return 0;
}
if (stop_addr<right_addr || stop_addr > left_addr) {
vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name);
return 0;
}
}
words = vpi_iterate(vpiMemoryWord, mitem);
assert(words);
item = vpi_scan(words);
wwid = vpi_get(vpiSize, item);
vpi_free_object(words);
if (strcmp(name,"$writememb")==0){
value.format = vpiBinStrVal;
}
else{
value.format = vpiHexStrVal;
}
if (strcmp(name,"$writememb")==0) value.format = vpiBinStrVal;
else value.format = vpiHexStrVal;
/*======================================== Write memory file */
cnt=0;
for(addr=start_addr; addr!=stop_addr+addr_incr; addr+=addr_incr, ++cnt){
if (cnt%16 == 0)
fprintf(file, "// 0x%08x\n", cnt);
cnt = 0;
for(addr=start_addr; addr!=stop_addr+addr_incr; addr+=addr_incr, ++cnt) {
vpiHandle word_index;
if (cnt%16 == 0) fprintf(file, "// 0x%08x\n", cnt);
word_index = vpi_handle_by_index(mitem, addr);
assert(word_index);
@ -546,7 +464,7 @@ static PLI_INT32 sys_writemem_calltf(PLI_BYTE8*name)
}
fclose(file);
free(path);
free(fname);
return 0;
}
@ -557,7 +475,7 @@ void sys_readmem_register()
tf_data.type = vpiSysTask;
tf_data.tfname = "$readmemh";
tf_data.calltf = sys_readmem_calltf;
tf_data.compiletf = 0;
tf_data.compiletf = sys_mem_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$readmemh";
vpi_register_systf(&tf_data);
@ -565,7 +483,7 @@ void sys_readmem_register()
tf_data.type = vpiSysTask;
tf_data.tfname = "$readmemb";
tf_data.calltf = sys_readmem_calltf;
tf_data.compiletf = 0;
tf_data.compiletf = sys_mem_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$readmemb";
vpi_register_systf(&tf_data);
@ -573,7 +491,7 @@ void sys_readmem_register()
tf_data.type = vpiSysTask;
tf_data.tfname = "$writememh";
tf_data.calltf = sys_writemem_calltf;
tf_data.compiletf = 0;
tf_data.compiletf = sys_mem_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$writememh";
vpi_register_systf(&tf_data);
@ -581,7 +499,7 @@ void sys_readmem_register()
tf_data.type = vpiSysTask;
tf_data.tfname = "$writememb";
tf_data.calltf = sys_writemem_calltf;
tf_data.compiletf = 0;
tf_data.compiletf = sys_mem_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$writememb";
vpi_register_systf(&tf_data);

View File

@ -24,6 +24,9 @@
# define MEM_ADDRESS 257
# define MEM_WORD 258
# define MEM_ERROR 259
extern char *readmem_error_token;
extern void sys_readmem_start_file(FILE*in, int bin_flag,
unsigned width, struct t_vpi_vecval*val);

View File

@ -30,6 +30,8 @@ static void make_bin_value();
static int save_state;
char *readmem_error_token = 0;
%}
%x BIN
@ -51,6 +53,9 @@ static int save_state;
<CCOMMENT>"*" { ; }
<CCOMMENT>"*"+"/" { BEGIN(save_state); }
/* Catch any invalid tokens and flagged them as an error. */
<HEX,BIN>. { readmem_error_token = yytext; return MEM_ERROR; }
%%
static unsigned word_width = 0;
static struct t_vpi_vecval*vecval = 0;

View File

@ -286,34 +286,19 @@ static PLI_INT32 sys_sdf_annotate_compiletf(PLI_BYTE8*name)
static PLI_INT32 sys_sdf_annotate_calltf(PLI_BYTE8*name)
{
s_vpi_value value;
vpiHandle callh = vpi_handle(vpiSysTfCall,0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
FILE *sdf_fd;
char *fname = get_filename(callh, name, vpi_scan(argv));
/* The first argument is the path to the SDF file. */
vpiHandle path = vpi_scan(argv);
assert(path);
if (fname == 0) return 0;
value.format = vpiStringVal;
vpi_get_value(path, &value);
if ((value.format != vpiStringVal) || !*(value.value.str)) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's file name argument (type=%s)"
" does not have a string value.\n",
name, vpi_get_str(vpiType, path));
vpi_control(vpiFinish, 1);
return 0;
}
char*path_str = strdup(value.value.str);
FILE*sdf_fd = fopen(path_str, "r");
sdf_fd = fopen(fname, "r");
if (sdf_fd == 0) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("Unable to open SDF file \"%s\"."
" Skipping this annotation.\n", path_str);
" Skipping this annotation.\n", fname);
return 0;
}
@ -324,11 +309,11 @@ static PLI_INT32 sys_sdf_annotate_calltf(PLI_BYTE8*name)
sdf_cur_cell = 0;
sdf_callh = callh;
sdf_process_file(sdf_fd, path_str);
sdf_process_file(sdf_fd, fname);
sdf_callh = 0;
fclose(sdf_fd);
free(path_str);
free(fname);
return 0;
}

View File

@ -404,7 +404,8 @@ static void open_dumpfile(vpiHandle callh)
unsigned udx = 0;
time_t walltime;
vpi_printf("VCD info: dumpfile %s opened for output.\n", dump_path);
vpi_printf("VCD info: dumpfile %s opened for output.\n",
dump_path);
time(&walltime);
@ -434,32 +435,33 @@ static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
s_vpi_value value;
char*path;
char *path;
/* $dumpfile must be called before $dumpvars starts! */
if (dumpvars_status != 0) {
vpi_printf("VCD warning: %s called after $dumpvars started,\n"
" using existing file (%s).\n",
name, dump_path);
char msg [64];
snprintf(msg, 64, "VCD warning: %s:%d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s %s called after $dumpvars started,\n", msg, name);
vpi_printf("%*s using existing file (%s).\n",
(int) strlen(msg), " ", dump_path);
vpi_free_object(argv);
return 0;
}
assert(argv);
value.format = vpiStringVal;
vpi_get_value(vpi_scan(argv), &value);
path = strdup(value.value.str);
path = get_filename(callh, name, vpi_scan(argv));
vpi_free_object(argv);
if (! path) return 0;
if (dump_path) {
vpi_printf("VCD warning: Overriding dump file %s with %s\n",
dump_path, path);
vpi_printf("VCD warning: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("Overriding dump file %s with %s.\n", dump_path, path);
free(dump_path);
}
dump_path = path;
vpi_free_object(argv);
return 0;
}