1999-08-15 03:23:56 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 1999 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
|
|
|
|
|
*/
|
2002-08-12 03:34:58 +02:00
|
|
|
#ifdef HAVE_CVS_IDENT
|
2002-08-24 04:02:44 +02:00
|
|
|
#ident "$Id: sys_display.c,v 1.44 2002/08/24 02:02:44 steve Exp $"
|
1999-08-15 03:23:56 +02:00
|
|
|
#endif
|
|
|
|
|
|
2001-07-25 05:10:48 +02:00
|
|
|
# include "config.h"
|
|
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
# include "vpi_user.h"
|
|
|
|
|
# include <assert.h>
|
|
|
|
|
# include <string.h>
|
|
|
|
|
# include <ctype.h>
|
|
|
|
|
# include <stdlib.h>
|
|
|
|
|
|
2002-05-31 06:26:54 +02:00
|
|
|
struct timeformat_info_s {
|
|
|
|
|
int units;
|
|
|
|
|
unsigned prec;
|
|
|
|
|
char*suff;
|
|
|
|
|
unsigned width;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct timeformat_info_s timeformat_info = { 0, 0, 0, 20 };
|
|
|
|
|
|
1999-11-07 00:32:14 +01:00
|
|
|
struct strobe_cb_info {
|
|
|
|
|
char*name;
|
2002-01-15 04:23:34 +01:00
|
|
|
int default_format;
|
2000-11-04 02:52:57 +01:00
|
|
|
vpiHandle scope;
|
1999-11-07 00:32:14 +01:00
|
|
|
vpiHandle*items;
|
|
|
|
|
unsigned nitems;
|
|
|
|
|
};
|
1999-08-15 03:23:56 +02:00
|
|
|
|
2002-01-22 01:18:10 +01:00
|
|
|
// The number of decimal digits needed to represent a
|
|
|
|
|
// nr_bits binary number is floor(nr_bits*log_10(2))+1,
|
|
|
|
|
// where log_10(2) = 0.30102999566398.... and I approximate
|
|
|
|
|
// this transcendental number as 146/485, to avoid the vagaries
|
|
|
|
|
// of floating-point. The smallest nr_bits for which this
|
|
|
|
|
// approximation fails is 2621,
|
|
|
|
|
// 2621*log_10(2)=789.9996, but (2621*146+484)/485=790 (exactly).
|
|
|
|
|
// In cases like this, all that happens is we allocate one
|
|
|
|
|
// unneeded char for the output. I add a "L" suffix to 146
|
|
|
|
|
// to make sure the computation is done as long ints, otherwise
|
|
|
|
|
// on a 16-bit int machine (allowed by ISO C) we would mangle
|
|
|
|
|
// this computation for bit-length of 224. I'd like to put
|
|
|
|
|
// in a test for nr_bits < LONG_MAX/146, but don't know how
|
|
|
|
|
// to fail, other than crashing.
|
|
|
|
|
//
|
|
|
|
|
// In an April 2000 thread in comp.unix.programmer, with subject
|
|
|
|
|
// "integer -> string", I <LRDoolittle@lbl.gov> give the 28/93
|
|
|
|
|
// approximation, but overstate its accuracy: that version first
|
|
|
|
|
// fails when the number of bits is 289, not 671.
|
|
|
|
|
//
|
|
|
|
|
// This result does not include space for a trailing '\0', if any.
|
|
|
|
|
//
|
|
|
|
|
inline static int calc_dec_size(int nr_bits, int is_signed)
|
2002-01-15 04:23:34 +01:00
|
|
|
{
|
2002-01-22 01:18:10 +01:00
|
|
|
int r;
|
|
|
|
|
if (is_signed) --nr_bits;
|
|
|
|
|
r = (nr_bits * 146L + 484) / 485;
|
|
|
|
|
if (is_signed) ++r;
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int vpi_get_dec_size(vpiHandle item)
|
|
|
|
|
{
|
|
|
|
|
return calc_dec_size(
|
|
|
|
|
vpi_get(vpiSize, item),
|
|
|
|
|
vpi_get(vpiSigned, item)==1
|
|
|
|
|
);
|
2002-01-15 04:23:34 +01:00
|
|
|
}
|
|
|
|
|
|
1999-11-07 00:32:14 +01:00
|
|
|
static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv)
|
1999-08-15 03:23:56 +02:00
|
|
|
{
|
2001-03-18 01:31:32 +01:00
|
|
|
if (argv) {
|
|
|
|
|
vpiHandle item;
|
|
|
|
|
unsigned nitems = 1;
|
|
|
|
|
vpiHandle*items = malloc(sizeof(vpiHandle));
|
|
|
|
|
items[0] = vpi_scan(argv);
|
2002-07-23 04:41:15 +02:00
|
|
|
if (items[0] == 0) {
|
|
|
|
|
free(items);
|
|
|
|
|
info->nitems = 0;
|
|
|
|
|
info->items = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-18 01:31:32 +01:00
|
|
|
for (item = vpi_scan(argv) ; item ; item = vpi_scan(argv)) {
|
|
|
|
|
items = realloc(items, (nitems+1)*sizeof(vpiHandle));
|
|
|
|
|
items[nitems] = item;
|
|
|
|
|
nitems += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info->nitems = nitems;
|
|
|
|
|
info->items = items;
|
1999-08-15 03:23:56 +02:00
|
|
|
|
2001-03-18 01:31:32 +01:00
|
|
|
} else {
|
|
|
|
|
info->nitems = 0;
|
|
|
|
|
info->items = 0;
|
|
|
|
|
}
|
1999-08-15 03:23:56 +02:00
|
|
|
}
|
|
|
|
|
|
2002-05-31 06:26:54 +02:00
|
|
|
static void format_time(unsigned mcd, int fsize, const char*value)
|
|
|
|
|
{
|
|
|
|
|
char buf[256];
|
|
|
|
|
const char*cp;
|
|
|
|
|
char*bp;
|
|
|
|
|
unsigned len;
|
2002-08-24 04:02:44 +02:00
|
|
|
|
|
|
|
|
int idx, idx_point, idx_start, idx_value;
|
2002-05-31 06:26:54 +02:00
|
|
|
|
|
|
|
|
/* This is the time precision for the simulation. */
|
|
|
|
|
int prec = vpi_get(vpiTimePrecision, 0);
|
|
|
|
|
|
|
|
|
|
if (fsize < 0)
|
|
|
|
|
fsize = timeformat_info.width;
|
|
|
|
|
|
2002-08-24 04:02:44 +02:00
|
|
|
/* bp starts at the end of the buffer, and works forward as we
|
|
|
|
|
build up the output value. */
|
2002-05-31 06:26:54 +02:00
|
|
|
bp = buf + sizeof buf;
|
|
|
|
|
|
2002-08-24 04:02:44 +02:00
|
|
|
/* cp points to digits of the value, starting with the least
|
|
|
|
|
significant. If the value is only '0', then short circuit
|
|
|
|
|
the value by setting cp = value. */
|
|
|
|
|
if (value[0] != '0')
|
|
|
|
|
cp = value + strlen(value);
|
|
|
|
|
else
|
|
|
|
|
cp = value;
|
|
|
|
|
|
2002-05-31 06:26:54 +02:00
|
|
|
|
|
|
|
|
/* Draw the suffix into the buffer. */
|
2002-08-24 04:02:44 +02:00
|
|
|
*--bp = 0;
|
2002-05-31 06:26:54 +02:00
|
|
|
bp -= strlen(timeformat_info.suff);
|
|
|
|
|
strcpy(bp, timeformat_info.suff);
|
|
|
|
|
|
2002-08-24 04:02:44 +02:00
|
|
|
/* This is the precision index where the decimal point goes. */
|
|
|
|
|
idx_point = timeformat_info.units;
|
2002-08-23 01:34:52 +02:00
|
|
|
|
2002-08-24 04:02:44 +02:00
|
|
|
/* This is the precision index where we start drawing digits. */
|
|
|
|
|
idx_start = idx_point - (int)timeformat_info.prec;
|
2002-08-23 01:34:52 +02:00
|
|
|
|
2002-08-24 04:02:44 +02:00
|
|
|
/* This is the precision index where the integer time value
|
|
|
|
|
digits start. */
|
|
|
|
|
idx_value = prec;
|
2002-05-31 06:26:54 +02:00
|
|
|
|
2002-08-24 04:02:44 +02:00
|
|
|
idx = idx_start;
|
|
|
|
|
if (idx > idx_value)
|
|
|
|
|
idx = idx_value;
|
2002-08-23 01:34:52 +02:00
|
|
|
|
2002-08-24 04:02:44 +02:00
|
|
|
/* If we want no precision, then set idx_point to a high value
|
|
|
|
|
so that the '.' is never printed. */
|
|
|
|
|
if (timeformat_info.prec == 0)
|
|
|
|
|
idx_point = idx - 1;
|
2002-05-31 06:26:54 +02:00
|
|
|
|
2002-08-24 04:02:44 +02:00
|
|
|
/* Now build up the time string, from the least significant
|
|
|
|
|
digit up to the last. */
|
|
|
|
|
while ((cp > value) || (idx <= idx_point)) {
|
2002-08-23 01:34:52 +02:00
|
|
|
|
2002-08-24 04:02:44 +02:00
|
|
|
if (idx == idx_point) {
|
|
|
|
|
*--bp = '.';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (idx >= idx_start) {
|
2002-08-23 01:34:52 +02:00
|
|
|
|
2002-08-24 04:02:44 +02:00
|
|
|
if (idx < idx_value) {
|
|
|
|
|
*--bp = '0';
|
|
|
|
|
} else if (cp > value) {
|
|
|
|
|
*--bp = cp[-1];
|
|
|
|
|
} else {
|
|
|
|
|
*--bp = '0';
|
|
|
|
|
}
|
2002-05-31 06:26:54 +02:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-24 04:02:44 +02:00
|
|
|
if ((idx >= idx_value) && (cp > value))
|
|
|
|
|
cp -= 1;
|
2002-05-31 06:26:54 +02:00
|
|
|
|
2002-08-24 04:02:44 +02:00
|
|
|
idx += 1;
|
2002-05-31 06:26:54 +02:00
|
|
|
}
|
|
|
|
|
|
2002-08-24 04:02:44 +02:00
|
|
|
/* Patch up cases that need a leading 0. */
|
|
|
|
|
if ((*bp == '.') || (idx == idx_start))
|
2002-05-31 06:26:54 +02:00
|
|
|
*--bp = '0';
|
|
|
|
|
|
|
|
|
|
/* Pad the string on the left to the requested minimum
|
|
|
|
|
width. Pad with spaces. */
|
|
|
|
|
len = strlen(bp);
|
|
|
|
|
while (len < fsize) {
|
|
|
|
|
*--bp = ' ';
|
|
|
|
|
len += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vpi_mcd_printf(mcd, "%s", bp);
|
|
|
|
|
}
|
1999-10-08 19:47:49 +02:00
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
/*
|
|
|
|
|
* If $display discovers a string as a parameter, this function is
|
|
|
|
|
* called to process it as a format string. I need the argv handle as
|
|
|
|
|
* well so that I can look for arguments as I move forward through the
|
|
|
|
|
* string.
|
|
|
|
|
*/
|
2000-10-28 02:51:41 +02:00
|
|
|
static int format_str(vpiHandle scope, unsigned int mcd,
|
|
|
|
|
char*fmt, int argc, vpiHandle*argv)
|
1999-11-06 23:16:50 +01:00
|
|
|
{
|
|
|
|
|
s_vpi_value value;
|
|
|
|
|
char buf[256];
|
|
|
|
|
char*cp = fmt;
|
2002-01-11 05:48:01 +01:00
|
|
|
char format_char = ' ';
|
1999-11-06 23:16:50 +01:00
|
|
|
int idx;
|
|
|
|
|
|
|
|
|
|
assert(fmt);
|
|
|
|
|
|
|
|
|
|
idx = 0;
|
|
|
|
|
|
|
|
|
|
while (*cp) {
|
|
|
|
|
size_t cnt = strcspn(cp, "%\\");
|
|
|
|
|
if (cnt > 0) {
|
|
|
|
|
if (cnt >= sizeof buf)
|
|
|
|
|
cnt = sizeof buf - 1;
|
|
|
|
|
strncpy(buf, cp, cnt);
|
|
|
|
|
buf[cnt] = 0;
|
2000-05-07 20:20:07 +02:00
|
|
|
vpi_mcd_printf(mcd, "%s", buf);
|
1999-11-06 23:16:50 +01:00
|
|
|
cp += cnt;
|
|
|
|
|
|
|
|
|
|
} else if (*cp == '%') {
|
2002-01-15 04:23:34 +01:00
|
|
|
int leading_zero = -1, fsize = -1, ffsize = -1;
|
2002-01-11 05:48:01 +01:00
|
|
|
int do_arg = 0;
|
1999-11-06 23:16:50 +01:00
|
|
|
|
|
|
|
|
cp += 1;
|
2002-01-15 04:23:34 +01:00
|
|
|
if (*cp == '0')
|
|
|
|
|
leading_zero=1;
|
|
|
|
|
if (isdigit((int)*cp))
|
1999-11-06 23:16:50 +01:00
|
|
|
fsize = strtoul(cp, &cp, 10);
|
2001-11-02 06:56:47 +01:00
|
|
|
if (*cp == '.') {
|
|
|
|
|
cp += 1;
|
|
|
|
|
ffsize = strtoul(cp, &cp, 10);
|
|
|
|
|
}
|
1999-11-06 23:16:50 +01:00
|
|
|
switch (*cp) {
|
|
|
|
|
case 0:
|
|
|
|
|
break;
|
2002-01-11 05:48:01 +01:00
|
|
|
|
1999-11-06 23:16:50 +01:00
|
|
|
case 'b':
|
|
|
|
|
case 'B':
|
2002-01-15 04:23:34 +01:00
|
|
|
if (ffsize != -1) {
|
|
|
|
|
vpi_printf("\nERROR: Illegal format \"%s\"\n", fmt);
|
|
|
|
|
fsize = -1;
|
|
|
|
|
}
|
2002-01-11 05:48:01 +01:00
|
|
|
format_char = 'b';
|
|
|
|
|
do_arg = 1;
|
1999-11-06 23:16:50 +01:00
|
|
|
value.format = vpiBinStrVal;
|
|
|
|
|
cp += 1;
|
|
|
|
|
break;
|
2002-01-11 05:48:01 +01:00
|
|
|
|
1999-11-06 23:16:50 +01:00
|
|
|
case 'd':
|
|
|
|
|
case 'D':
|
2002-01-15 04:23:34 +01:00
|
|
|
if (ffsize != -1) {
|
|
|
|
|
vpi_printf("\nERROR: Illegal format \"%s\"\n", fmt);
|
|
|
|
|
fsize = -1;
|
|
|
|
|
}
|
2002-01-11 05:48:01 +01:00
|
|
|
format_char = 'd';
|
|
|
|
|
do_arg = 1;
|
1999-11-06 23:16:50 +01:00
|
|
|
value.format = vpiDecStrVal;
|
|
|
|
|
cp += 1;
|
|
|
|
|
break;
|
2002-01-11 05:48:01 +01:00
|
|
|
|
1999-11-06 23:16:50 +01:00
|
|
|
case 'h':
|
|
|
|
|
case 'H':
|
|
|
|
|
case 'x':
|
|
|
|
|
case 'X':
|
2002-01-15 04:23:34 +01:00
|
|
|
if (ffsize != -1) {
|
|
|
|
|
vpi_printf("\nERROR: Illegal format \"%s\"\n", fmt);
|
|
|
|
|
fsize = -1;
|
|
|
|
|
}
|
2002-01-11 05:48:01 +01:00
|
|
|
format_char = 'h';
|
|
|
|
|
do_arg = 1;
|
1999-11-06 23:16:50 +01:00
|
|
|
value.format = vpiHexStrVal;
|
|
|
|
|
cp += 1;
|
|
|
|
|
break;
|
2002-01-11 05:48:01 +01:00
|
|
|
|
|
|
|
|
case 'c':
|
|
|
|
|
case 'C':
|
2002-01-15 04:23:34 +01:00
|
|
|
if (fsize != -1 && ffsize != -1) {
|
|
|
|
|
vpi_printf("\nERROR: Illegal format \"%s\"\n", fmt);
|
|
|
|
|
fsize = -1;
|
|
|
|
|
ffsize = -1;
|
|
|
|
|
}
|
2002-01-11 05:48:01 +01:00
|
|
|
format_char = 'c';
|
|
|
|
|
do_arg = 1;
|
|
|
|
|
value.format = vpiStringVal;
|
|
|
|
|
cp += 1;
|
|
|
|
|
break;
|
|
|
|
|
|
1999-11-06 23:16:50 +01:00
|
|
|
case 'm':
|
2002-01-11 05:48:01 +01:00
|
|
|
case 'M':
|
2002-01-15 04:23:34 +01:00
|
|
|
if (ffsize != -1) {
|
|
|
|
|
vpi_printf("\nERROR: Illegal format \"%s\"\n", fmt);
|
|
|
|
|
fsize = -1;
|
|
|
|
|
}
|
|
|
|
|
if (fsize == -1)
|
|
|
|
|
fsize = 0;
|
2000-10-28 02:51:41 +02:00
|
|
|
assert(scope);
|
2002-01-15 04:23:34 +01:00
|
|
|
vpi_mcd_printf(mcd, "%*s",
|
|
|
|
|
fsize,
|
2002-01-11 05:48:01 +01:00
|
|
|
vpi_get_str(vpiFullName, scope));
|
1999-11-06 23:16:50 +01:00
|
|
|
cp += 1;
|
|
|
|
|
break;
|
2002-01-11 05:48:01 +01:00
|
|
|
|
1999-11-06 23:16:50 +01:00
|
|
|
case 'o':
|
|
|
|
|
case 'O':
|
2002-01-15 04:23:34 +01:00
|
|
|
if (ffsize != -1) {
|
|
|
|
|
vpi_printf("\nERROR: Illegal format \"%s\"\n", fmt);
|
|
|
|
|
fsize = -1;
|
|
|
|
|
}
|
2002-01-11 05:48:01 +01:00
|
|
|
format_char = 'o';
|
|
|
|
|
do_arg = 1;
|
1999-11-06 23:16:50 +01:00
|
|
|
value.format = vpiOctStrVal;
|
|
|
|
|
cp += 1;
|
|
|
|
|
break;
|
2002-01-11 05:48:01 +01:00
|
|
|
|
2000-12-02 03:40:56 +01:00
|
|
|
case 's':
|
|
|
|
|
case 'S':
|
2002-01-15 04:23:34 +01:00
|
|
|
if (ffsize != -1) {
|
|
|
|
|
vpi_printf("\nERROR: Illegal format \"%s\"\n", fmt);
|
|
|
|
|
fsize = -1;
|
|
|
|
|
}
|
2002-01-11 05:48:01 +01:00
|
|
|
format_char = 's';
|
|
|
|
|
do_arg = 1;
|
2000-12-02 03:40:56 +01:00
|
|
|
value.format = vpiStringVal;
|
|
|
|
|
cp += 1;
|
|
|
|
|
break;
|
2002-01-11 05:48:01 +01:00
|
|
|
|
1999-11-06 23:16:50 +01:00
|
|
|
case 't':
|
|
|
|
|
case 'T':
|
2002-01-15 04:23:34 +01:00
|
|
|
if (ffsize != -1) {
|
|
|
|
|
vpi_printf("\nERROR: Illegal format \"%s\"\n", fmt);
|
|
|
|
|
fsize = -1;
|
|
|
|
|
}
|
2002-01-11 05:48:01 +01:00
|
|
|
format_char = 't';
|
|
|
|
|
do_arg = 1;
|
1999-11-06 23:16:50 +01:00
|
|
|
value.format = vpiDecStrVal;
|
|
|
|
|
cp += 1;
|
|
|
|
|
break;
|
2002-01-11 05:48:01 +01:00
|
|
|
|
1999-11-06 23:16:50 +01:00
|
|
|
case '%':
|
2002-01-11 05:48:01 +01:00
|
|
|
if (fsize != -1 && ffsize != -1) {
|
|
|
|
|
vpi_printf("\nERROR: Illegal format \"%s\"\n", fmt);
|
|
|
|
|
fsize = -1;
|
|
|
|
|
ffsize = -1;
|
|
|
|
|
}
|
2000-05-07 20:20:07 +02:00
|
|
|
vpi_mcd_printf(mcd, "%%");
|
1999-11-06 23:16:50 +01:00
|
|
|
cp += 1;
|
|
|
|
|
break;
|
2002-01-11 05:48:01 +01:00
|
|
|
|
|
|
|
|
case 'v':
|
|
|
|
|
case 'V':
|
|
|
|
|
case 'e':
|
|
|
|
|
case 'f':
|
|
|
|
|
case 'g':
|
2002-01-15 04:23:34 +01:00
|
|
|
// new Verilog 2001 format specifiers...
|
|
|
|
|
case 'l':
|
|
|
|
|
case 'L':
|
|
|
|
|
case 'u':
|
|
|
|
|
case 'U':
|
|
|
|
|
case 'z':
|
|
|
|
|
case 'Z':
|
2002-01-11 05:48:01 +01:00
|
|
|
vpi_printf("\nERROR: Unsupported format \"%s\"\n", fmt);
|
|
|
|
|
vpi_mcd_printf(mcd, "%c", *cp);
|
|
|
|
|
cp += 1;
|
|
|
|
|
break;
|
|
|
|
|
|
1999-11-06 23:16:50 +01:00
|
|
|
default:
|
2002-01-11 05:48:01 +01:00
|
|
|
vpi_printf("\nERROR: Illegal format \"%s\"\n", fmt);
|
2000-05-07 20:20:07 +02:00
|
|
|
vpi_mcd_printf(mcd, "%c", *cp);
|
1999-11-06 23:16:50 +01:00
|
|
|
cp += 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2000-11-04 06:49:22 +01:00
|
|
|
/* If we encountered a numeric format string, then
|
|
|
|
|
grab the number value from the next parameter
|
|
|
|
|
and display it in the requested format. */
|
2002-01-11 05:48:01 +01:00
|
|
|
if (do_arg) {
|
2000-11-04 06:49:22 +01:00
|
|
|
if (idx >= argc) {
|
|
|
|
|
vpi_printf("\ntoo few arguments for format %s\n",
|
|
|
|
|
fmt);
|
|
|
|
|
} else {
|
2002-01-15 04:23:34 +01:00
|
|
|
vpi_get_value(argv[idx], &value);
|
2002-02-06 05:50:04 +01:00
|
|
|
if (value.format == vpiSuppressVal){
|
2002-05-24 21:05:30 +02:00
|
|
|
vpi_printf("\nERROR: parameter does not have a printable value!\n");
|
2002-02-06 05:50:04 +01:00
|
|
|
goto bail_out;
|
|
|
|
|
}
|
2002-01-11 05:48:01 +01:00
|
|
|
|
|
|
|
|
switch(format_char){
|
2002-01-15 04:23:34 +01:00
|
|
|
case 'c':
|
|
|
|
|
vpi_mcd_printf(mcd, "%c", value.value.str[strlen(value.value.str)-1]);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 't':
|
2002-05-31 06:26:54 +02:00
|
|
|
format_time(mcd, fsize, value.value.str);
|
|
|
|
|
break;
|
|
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
case 'd':
|
|
|
|
|
if (fsize==-1){
|
|
|
|
|
// simple %d parameter.
|
|
|
|
|
// Size is now determined by the width
|
|
|
|
|
// of the vector or integer
|
2002-01-22 01:18:10 +01:00
|
|
|
fsize = vpi_get_dec_size(argv[idx]);
|
2002-01-15 04:23:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vpi_mcd_printf(mcd, "%*s", fsize,
|
|
|
|
|
value.value.str);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'b':
|
|
|
|
|
case 'h':
|
|
|
|
|
case 'x':
|
|
|
|
|
case 'o':
|
|
|
|
|
if (fsize==-1){
|
|
|
|
|
// For hex, oct and binary values, the string is already
|
|
|
|
|
// prefixed with the correct number of zeros...
|
|
|
|
|
vpi_mcd_printf(mcd, "%s", value.value.str);
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
char* value_str = value.value.str;
|
|
|
|
|
|
|
|
|
|
if (leading_zero==1){
|
|
|
|
|
// Strip away all leading zeros from string
|
|
|
|
|
int i=0;
|
|
|
|
|
while(i< (strlen(value_str)-1) && value_str[i]=='0')
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
|
|
value_str += i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vpi_mcd_printf(mcd, "%*s", fsize, value_str);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
|
if (fsize==-1){
|
|
|
|
|
vpi_mcd_printf(mcd, "%s", value.value.str);
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
char* value_str = value.value.str;
|
|
|
|
|
|
|
|
|
|
if (leading_zero==1){
|
|
|
|
|
// Remove leading spaces from the value
|
|
|
|
|
// string *except* if the argument is a
|
|
|
|
|
// constant string... (hey, that's how
|
|
|
|
|
// the commerical guys behave...)
|
|
|
|
|
|
|
|
|
|
if (!(vpi_get(vpiType, argv[idx]) == vpiConstant
|
|
|
|
|
&& vpi_get(vpiConstType, argv[idx]) == vpiStringConst)) {
|
|
|
|
|
int i=0;
|
|
|
|
|
// Strip away all leading zeros from string
|
|
|
|
|
while(i< (strlen(value_str)-1) && value_str[i]==' ')
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
|
|
value_str += i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vpi_mcd_printf(mcd, "%*s", fsize, value_str);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2002-01-11 05:48:01 +01:00
|
|
|
if (fsize > 0)
|
|
|
|
|
vpi_mcd_printf(mcd, "%*s", fsize,
|
|
|
|
|
value.value.str);
|
|
|
|
|
else
|
|
|
|
|
vpi_mcd_printf(mcd, "%s",
|
|
|
|
|
value.value.str);
|
|
|
|
|
}
|
2002-02-06 05:50:04 +01:00
|
|
|
|
|
|
|
|
bail_out:
|
2002-01-15 04:23:34 +01:00
|
|
|
idx++;
|
2000-11-04 06:49:22 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-06 23:16:50 +01:00
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
cp += 1;
|
|
|
|
|
switch (*cp) {
|
|
|
|
|
case 0:
|
|
|
|
|
break;
|
|
|
|
|
case 'n':
|
2000-05-07 20:20:07 +02:00
|
|
|
vpi_mcd_printf(mcd, "\n");
|
1999-11-06 23:16:50 +01:00
|
|
|
cp += 1;
|
|
|
|
|
break;
|
2001-08-16 05:26:04 +02:00
|
|
|
case 't':
|
|
|
|
|
vpi_mcd_printf(mcd, "\t");
|
|
|
|
|
cp += 1;
|
|
|
|
|
break;
|
|
|
|
|
case '\\':
|
|
|
|
|
vpi_mcd_printf(mcd, "\\");
|
|
|
|
|
cp += 1;
|
|
|
|
|
break;
|
|
|
|
|
case '"':
|
|
|
|
|
vpi_mcd_printf(mcd, "\"");
|
|
|
|
|
cp += 1;
|
|
|
|
|
break;
|
|
|
|
|
|
1999-11-06 23:16:50 +01:00
|
|
|
default:
|
2000-05-07 20:20:07 +02:00
|
|
|
vpi_mcd_printf(mcd, "%c", *cp);
|
1999-11-06 23:16:50 +01:00
|
|
|
cp += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return idx;
|
|
|
|
|
}
|
|
|
|
|
|
2000-11-04 02:52:57 +01:00
|
|
|
static void do_display(unsigned int mcd, struct strobe_cb_info*info)
|
1999-10-28 02:47:24 +02:00
|
|
|
{
|
1999-11-06 23:16:50 +01:00
|
|
|
s_vpi_value value;
|
1999-11-07 00:32:14 +01:00
|
|
|
int idx;
|
2002-01-15 04:23:34 +01:00
|
|
|
int size;
|
1999-11-06 23:16:50 +01:00
|
|
|
|
|
|
|
|
for (idx = 0 ; idx < info->nitems ; idx += 1) {
|
|
|
|
|
vpiHandle item = info->items[idx];
|
|
|
|
|
|
|
|
|
|
switch (vpi_get(vpiType, item)) {
|
|
|
|
|
|
|
|
|
|
case 0:
|
2000-05-07 20:20:07 +02:00
|
|
|
vpi_mcd_printf(mcd, " ");
|
1999-11-06 23:16:50 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case vpiConstant:
|
|
|
|
|
if (vpi_get(vpiConstType, item) == vpiStringConst) {
|
|
|
|
|
value.format = vpiStringVal;
|
|
|
|
|
vpi_get_value(item, &value);
|
2000-11-04 02:52:57 +01:00
|
|
|
idx += format_str(info->scope, mcd, value.value.str,
|
1999-11-06 23:16:50 +01:00
|
|
|
info->nitems-idx-1,
|
1999-11-07 03:25:07 +01:00
|
|
|
info->items+idx+1);
|
1999-11-06 23:16:50 +01:00
|
|
|
} else {
|
|
|
|
|
value.format = vpiBinStrVal;
|
|
|
|
|
vpi_get_value(item, &value);
|
2000-05-07 20:20:07 +02:00
|
|
|
vpi_mcd_printf(mcd, "%s", value.value.str);
|
1999-11-06 23:16:50 +01:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case vpiNet:
|
|
|
|
|
case vpiReg:
|
2002-06-21 06:59:35 +02:00
|
|
|
case vpiIntegerVar:
|
2000-02-13 20:18:27 +01:00
|
|
|
case vpiMemoryWord:
|
2002-01-15 04:23:34 +01:00
|
|
|
value.format = info->default_format;
|
1999-11-06 23:16:50 +01:00
|
|
|
vpi_get_value(item, &value);
|
2002-01-15 04:23:34 +01:00
|
|
|
|
|
|
|
|
switch(info->default_format){
|
|
|
|
|
case vpiDecStrVal:
|
2002-01-22 01:18:10 +01:00
|
|
|
size = vpi_get_dec_size(item);
|
2002-01-15 04:23:34 +01:00
|
|
|
vpi_mcd_printf(mcd, "%*s", size, value.value.str);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
vpi_mcd_printf(mcd, "%s", value.value.str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1999-11-06 23:16:50 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case vpiTimeVar:
|
|
|
|
|
value.format = vpiTimeVal;
|
|
|
|
|
vpi_get_value(item, &value);
|
2002-01-15 04:23:34 +01:00
|
|
|
vpi_mcd_printf(mcd, "%20u", value.value.time->low);
|
1999-11-06 23:16:50 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2000-05-07 20:20:07 +02:00
|
|
|
vpi_mcd_printf(mcd, "?");
|
1999-11-06 23:16:50 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-11-07 00:32:14 +01:00
|
|
|
}
|
|
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
static int get_default_format(char *name)
|
|
|
|
|
{
|
|
|
|
|
int default_format;
|
|
|
|
|
|
|
|
|
|
switch(name[ strlen(name)-1 ]){
|
|
|
|
|
// writE/strobE or monitoR or displaY/fdisplaY
|
|
|
|
|
case 'e':
|
|
|
|
|
case 'r':
|
|
|
|
|
case 'y': default_format = vpiDecStrVal; break;
|
|
|
|
|
case 'h': default_format = vpiHexStrVal; break;
|
|
|
|
|
case 'o': default_format = vpiOctStrVal; break;
|
|
|
|
|
case 'b': default_format = vpiBinStrVal; break;
|
|
|
|
|
default:
|
|
|
|
|
assert(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return default_format;
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-07 00:32:14 +01:00
|
|
|
static int sys_display_calltf(char *name)
|
|
|
|
|
{
|
|
|
|
|
struct strobe_cb_info info;
|
|
|
|
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
2000-10-28 02:51:41 +02:00
|
|
|
vpiHandle scope = vpi_handle(vpiScope, sys);
|
1999-11-07 00:32:14 +01:00
|
|
|
|
|
|
|
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
|
|
|
|
|
2000-10-28 02:51:41 +02:00
|
|
|
assert(scope);
|
2002-01-15 04:23:34 +01:00
|
|
|
info.default_format = get_default_format(name);
|
2000-11-04 02:52:57 +01:00
|
|
|
info.scope = scope;
|
1999-11-07 00:32:14 +01:00
|
|
|
array_from_iterator(&info, argv);
|
|
|
|
|
|
2001-07-16 20:40:19 +02:00
|
|
|
do_display(5, &info);
|
1999-11-07 00:32:14 +01:00
|
|
|
free(info.items);
|
|
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
if (strncmp(name,"$display",8) == 0)
|
2001-07-16 20:40:19 +02:00
|
|
|
vpi_mcd_printf(5, "\n");
|
1999-11-07 00:32:14 +01:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The strobe implementation takes the parameter handles that are
|
|
|
|
|
* passed to the calltf and puts them in to an array for safe
|
|
|
|
|
* keeping. That array (and other bookkeeping) is passed, via the
|
|
|
|
|
* struct_cb_info object, to the REadOnlySych function strobe_cb,
|
|
|
|
|
* where it is use to perform the actual formatting and printing.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static int strobe_cb(p_cb_data cb)
|
|
|
|
|
{
|
|
|
|
|
struct strobe_cb_info*info = (struct strobe_cb_info*)cb->user_data;
|
|
|
|
|
|
2000-11-04 02:52:57 +01:00
|
|
|
do_display(1, info);
|
1999-11-06 23:16:50 +01:00
|
|
|
|
|
|
|
|
vpi_printf("\n");
|
|
|
|
|
|
|
|
|
|
free(info->name);
|
|
|
|
|
free(info->items);
|
|
|
|
|
free(info);
|
|
|
|
|
|
1999-10-28 02:47:24 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int sys_strobe_calltf(char*name)
|
|
|
|
|
{
|
|
|
|
|
struct t_cb_data cb;
|
|
|
|
|
struct t_vpi_time time;
|
1999-11-06 23:16:50 +01:00
|
|
|
|
|
|
|
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
2000-11-04 02:52:57 +01:00
|
|
|
vpiHandle scope = vpi_handle(vpiScope, sys);
|
1999-11-06 23:16:50 +01:00
|
|
|
|
|
|
|
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
|
|
|
|
|
1999-11-07 00:32:14 +01:00
|
|
|
struct strobe_cb_info*info = calloc(1, sizeof(struct strobe_cb_info));
|
1999-11-06 23:16:50 +01:00
|
|
|
|
1999-11-07 00:32:14 +01:00
|
|
|
array_from_iterator(info, argv);
|
1999-11-06 23:16:50 +01:00
|
|
|
info->name = strdup(name);
|
2002-01-15 04:23:34 +01:00
|
|
|
info->default_format = get_default_format(name);
|
2000-11-04 02:52:57 +01:00
|
|
|
info->scope= scope;
|
1999-10-28 02:47:24 +02:00
|
|
|
|
|
|
|
|
time.type = vpiSimTime;
|
|
|
|
|
time.low = 0;
|
|
|
|
|
time.high = 0;
|
|
|
|
|
|
|
|
|
|
cb.reason = cbReadOnlySynch;
|
|
|
|
|
cb.cb_rtn = strobe_cb;
|
|
|
|
|
cb.time = &time;
|
|
|
|
|
cb.obj = 0;
|
2001-10-25 06:19:53 +02:00
|
|
|
cb.value = 0;
|
1999-11-06 23:16:50 +01:00
|
|
|
cb.user_data = (char*)info;
|
1999-10-28 02:47:24 +02:00
|
|
|
vpi_register_cb(&cb);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-07 03:25:07 +01:00
|
|
|
/*
|
|
|
|
|
* The $monitor system task works by managing these static variables,
|
|
|
|
|
* and the cbValueChange callbacks associated with registers and
|
|
|
|
|
* nets. Note that it is proper to keep the state in static variables
|
|
|
|
|
* because there can only be one monitor at a time pending (even
|
|
|
|
|
* though that monitor may be watching many variables).
|
|
|
|
|
*/
|
|
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
static struct strobe_cb_info monitor_info = { 0, 0, 0, 0, 0 };
|
1999-11-07 03:25:07 +01:00
|
|
|
static vpiHandle *monitor_callbacks = 0;
|
2002-07-25 05:35:51 +02:00
|
|
|
static int monitor_scheduled = 0;
|
|
|
|
|
static int monitor_enabled = 1;
|
1999-11-07 03:25:07 +01:00
|
|
|
|
|
|
|
|
static int monitor_cb_2(p_cb_data cb)
|
|
|
|
|
{
|
2000-11-04 02:52:57 +01:00
|
|
|
do_display(1, &monitor_info);
|
1999-11-07 03:25:07 +01:00
|
|
|
vpi_printf("\n");
|
|
|
|
|
monitor_scheduled = 0;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-25 05:35:51 +02:00
|
|
|
/*
|
|
|
|
|
* The monitor_cb_1 callback is called when an even occurs somewhere
|
|
|
|
|
* in the simulation. All this function does is schedule the actual
|
|
|
|
|
* display to occur in a ReadOnlySync callback. The monitor_scheduled
|
|
|
|
|
* flag is used to allow only one monitor strobe to be scheduled.
|
|
|
|
|
*/
|
1999-11-07 03:25:07 +01:00
|
|
|
static int monitor_cb_1(p_cb_data cause)
|
|
|
|
|
{
|
|
|
|
|
struct t_cb_data cb;
|
|
|
|
|
struct t_vpi_time time;
|
|
|
|
|
|
2002-07-25 05:35:51 +02:00
|
|
|
if (monitor_enabled == 0) return 0;
|
1999-11-07 03:25:07 +01:00
|
|
|
if (monitor_scheduled) return 0;
|
|
|
|
|
|
|
|
|
|
/* This this action caused the first trigger, then schedule
|
|
|
|
|
the monitor to happen at the end of the time slice and mark
|
|
|
|
|
it as scheduled. */
|
|
|
|
|
monitor_scheduled += 1;
|
|
|
|
|
time.type = vpiSimTime;
|
|
|
|
|
time.low = 0;
|
|
|
|
|
time.high = 0;
|
|
|
|
|
|
|
|
|
|
cb.reason = cbReadOnlySynch;
|
|
|
|
|
cb.cb_rtn = monitor_cb_2;
|
|
|
|
|
cb.time = &time;
|
|
|
|
|
cb.obj = 0;
|
2001-10-25 06:19:53 +02:00
|
|
|
cb.value = 0;
|
1999-11-07 03:25:07 +01:00
|
|
|
vpi_register_cb(&cb);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1999-10-29 05:37:22 +02:00
|
|
|
static int sys_monitor_calltf(char*name)
|
|
|
|
|
{
|
1999-11-07 03:25:07 +01:00
|
|
|
unsigned idx;
|
1999-10-29 05:37:22 +02:00
|
|
|
struct t_cb_data cb;
|
|
|
|
|
struct t_vpi_time time;
|
|
|
|
|
|
|
|
|
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
2000-11-04 02:52:57 +01:00
|
|
|
vpiHandle scope = vpi_handle(vpiScope, sys);
|
1999-10-29 05:37:22 +02:00
|
|
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
1999-11-07 03:25:07 +01:00
|
|
|
|
2002-07-25 05:35:51 +02:00
|
|
|
/* If there was a previous $monitor, then remove the calbacks
|
|
|
|
|
related to it. */
|
1999-11-07 03:25:07 +01:00
|
|
|
if (monitor_callbacks) {
|
|
|
|
|
for (idx = 0 ; idx < monitor_info.nitems ; idx += 1)
|
|
|
|
|
if (monitor_callbacks[idx])
|
|
|
|
|
vpi_remove_cb(monitor_callbacks[idx]);
|
|
|
|
|
|
|
|
|
|
free(monitor_callbacks);
|
|
|
|
|
monitor_callbacks = 0;
|
|
|
|
|
|
|
|
|
|
free(monitor_info.items);
|
|
|
|
|
free(monitor_info.name);
|
|
|
|
|
monitor_info.items = 0;
|
|
|
|
|
monitor_info.nitems = 0;
|
|
|
|
|
monitor_info.name = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-25 05:35:51 +02:00
|
|
|
/* Make an array of handles from the argument list. */
|
1999-11-07 03:25:07 +01:00
|
|
|
array_from_iterator(&monitor_info, argv);
|
|
|
|
|
monitor_info.name = strdup(name);
|
2002-01-15 04:23:34 +01:00
|
|
|
monitor_info.default_format = get_default_format(name);
|
2000-11-04 02:52:57 +01:00
|
|
|
monitor_info.scope = scope;
|
1999-11-07 03:25:07 +01:00
|
|
|
|
2002-07-25 05:35:51 +02:00
|
|
|
/* Attach callbacks to all the parameters that might change. */
|
1999-11-07 03:25:07 +01:00
|
|
|
monitor_callbacks = calloc(monitor_info.nitems, sizeof(vpiHandle));
|
1999-10-29 05:37:22 +02:00
|
|
|
|
|
|
|
|
time.type = vpiSuppressTime;
|
1999-11-07 03:25:07 +01:00
|
|
|
cb.reason = cbValueChange;
|
|
|
|
|
cb.cb_rtn = monitor_cb_1;
|
|
|
|
|
cb.time = &time;
|
2001-10-25 06:19:53 +02:00
|
|
|
cb.value = NULL;
|
1999-11-07 03:25:07 +01:00
|
|
|
for (idx = 0 ; idx < monitor_info.nitems ; idx += 1) {
|
|
|
|
|
|
|
|
|
|
switch (vpi_get(vpiType, monitor_info.items[idx])) {
|
|
|
|
|
case vpiNet:
|
|
|
|
|
case vpiReg:
|
2002-06-21 06:59:35 +02:00
|
|
|
case vpiIntegerVar:
|
2000-03-31 09:08:39 +02:00
|
|
|
/* Monitoring reg and net values involves setting
|
2002-06-21 06:59:35 +02:00
|
|
|
a callback for value changes. pass the storage
|
2000-03-31 09:08:39 +02:00
|
|
|
pointer for the callback itself as user_data so
|
|
|
|
|
that the callback can refresh itself. */
|
|
|
|
|
cb.user_data = (char*)(monitor_callbacks+idx);
|
1999-11-07 03:25:07 +01:00
|
|
|
cb.obj = monitor_info.items[idx];
|
|
|
|
|
monitor_callbacks[idx] = vpi_register_cb(&cb);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-10-29 05:37:22 +02:00
|
|
|
|
2002-07-25 05:35:51 +02:00
|
|
|
/* When the $monitor is called, it schedules a first display
|
|
|
|
|
for the end of the current time, like a $strobe. */
|
|
|
|
|
monitor_cb_1(0);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int sys_monitoron_calltf(char*name)
|
|
|
|
|
{
|
|
|
|
|
monitor_enabled = 1;
|
|
|
|
|
monitor_cb_1(0);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int sys_monitoroff_calltf(char*name)
|
|
|
|
|
{
|
|
|
|
|
monitor_enabled = 0;
|
1999-10-29 05:37:22 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-07 20:20:07 +02:00
|
|
|
/*
|
|
|
|
|
* Implement the $fopen system function.
|
|
|
|
|
*/
|
|
|
|
|
static int sys_fopen_calltf(char *name)
|
|
|
|
|
{
|
2001-03-22 03:23:17 +01:00
|
|
|
s_vpi_value val, value, modevalue;
|
|
|
|
|
unsigned char *mode_string;
|
2000-05-07 20:20:07 +02:00
|
|
|
|
|
|
|
|
vpiHandle call_handle = vpi_handle(vpiSysTfCall, 0);
|
|
|
|
|
vpiHandle argv = vpi_iterate(vpiArgument, call_handle);
|
2001-06-25 05:11:41 +02:00
|
|
|
vpiHandle item = argv ? vpi_scan(argv) : 0;
|
|
|
|
|
vpiHandle mode = item ? vpi_scan(argv) : 0;
|
2000-05-07 20:20:07 +02:00
|
|
|
|
|
|
|
|
if (item == 0) {
|
|
|
|
|
vpi_printf("%s: file name parameter missing.\n", name);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-25 05:11:41 +02:00
|
|
|
if (mode == 0) {
|
|
|
|
|
argv = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-07 20:20:07 +02:00
|
|
|
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) {
|
2001-02-10 20:50:33 +01:00
|
|
|
vpi_printf("ERROR: %s parameter must be a string.\n", name);
|
2000-05-07 20:20:07 +02:00
|
|
|
vpi_free_object(argv);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-22 03:23:17 +01:00
|
|
|
if (mode == 0) {
|
|
|
|
|
mode_string = "w";
|
|
|
|
|
} else {
|
|
|
|
|
if (vpi_get(vpiType, mode) != vpiConstant) {
|
|
|
|
|
vpi_printf("ERROR: %s parameter must be a constant\n", name);
|
|
|
|
|
vpi_free_object(argv);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (vpi_get(vpiConstType, mode) != vpiStringConst) {
|
|
|
|
|
vpi_printf("ERROR: %s parameter must be a string.\n", name);
|
|
|
|
|
vpi_free_object(argv);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
modevalue.format = vpiStringVal;
|
|
|
|
|
vpi_get_value(mode, &modevalue);
|
|
|
|
|
mode_string = modevalue.value.str;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-07 20:20:07 +02:00
|
|
|
value.format = vpiStringVal;
|
|
|
|
|
vpi_get_value(item, &value);
|
|
|
|
|
|
|
|
|
|
val.format = vpiIntVal;
|
2001-03-22 03:23:17 +01:00
|
|
|
val.value.integer = vpi_mcd_open_x( value.value.str, mode_string );
|
2000-05-07 20:20:07 +02:00
|
|
|
|
|
|
|
|
vpi_put_value(call_handle, &val, 0, vpiNoDelay);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int sys_fopen_sizetf(char*x)
|
|
|
|
|
{
|
|
|
|
|
return 32;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Implement $fdisplay and $fwrite.
|
|
|
|
|
* Perhaps this could be merged into sys_display_calltf.
|
|
|
|
|
*/
|
|
|
|
|
static int sys_fdisplay_calltf(char *name)
|
|
|
|
|
{
|
|
|
|
|
struct strobe_cb_info info;
|
|
|
|
|
unsigned int mcd;
|
|
|
|
|
int type;
|
|
|
|
|
s_vpi_value value;
|
|
|
|
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
2001-11-02 06:56:47 +01:00
|
|
|
vpiHandle scope = vpi_handle(vpiScope, sys);
|
2000-05-07 20:20:07 +02:00
|
|
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
|
|
|
|
vpiHandle item = vpi_scan(argv);
|
|
|
|
|
|
|
|
|
|
if (item == 0) {
|
|
|
|
|
vpi_printf("%s: mcd parameter missing.\n", name);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type = vpi_get(vpiType, item);
|
2002-06-21 06:59:35 +02:00
|
|
|
switch (type) {
|
|
|
|
|
case vpiReg:
|
|
|
|
|
case vpiRealVal:
|
|
|
|
|
case vpiIntegerVar:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
vpi_printf("ERROR: %s mcd parameter must be of integral", name);
|
|
|
|
|
vpi_printf(", got vpiType=%d\n", type);
|
|
|
|
|
vpi_free_object(argv);
|
|
|
|
|
return 0;
|
2000-05-07 20:20:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
value.format = vpiIntVal;
|
|
|
|
|
vpi_get_value(item, &value);
|
|
|
|
|
mcd = value.value.integer;
|
|
|
|
|
|
2001-11-02 06:56:47 +01:00
|
|
|
assert(scope);
|
2002-01-15 04:23:34 +01:00
|
|
|
info.default_format = get_default_format(name);
|
2001-11-02 06:56:47 +01:00
|
|
|
info.scope = scope;
|
2000-05-07 20:20:07 +02:00
|
|
|
array_from_iterator(&info, argv);
|
2000-11-04 02:52:57 +01:00
|
|
|
do_display(mcd, &info);
|
2000-05-07 20:20:07 +02:00
|
|
|
free(info.items);
|
|
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
if (strncmp(name,"$fdisplay",9) == 0)
|
2000-05-07 20:20:07 +02:00
|
|
|
vpi_mcd_printf(mcd, "\n");
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Implement $fclose system function
|
|
|
|
|
*/
|
|
|
|
|
static int sys_fclose_calltf(char *name)
|
|
|
|
|
{
|
|
|
|
|
unsigned int mcd;
|
|
|
|
|
int type;
|
|
|
|
|
s_vpi_value value;
|
|
|
|
|
|
|
|
|
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
|
|
|
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
|
|
|
|
vpiHandle item = vpi_scan(argv);
|
|
|
|
|
|
|
|
|
|
if (item == 0) {
|
|
|
|
|
vpi_printf("%s: mcd parameter missing.\n", name);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
type = vpi_get(vpiType, item);
|
2002-06-21 06:59:35 +02:00
|
|
|
switch (type) {
|
|
|
|
|
case vpiReg:
|
|
|
|
|
case vpiRealVal:
|
|
|
|
|
case vpiIntegerVar:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
vpi_printf("ERROR: %s mcd parameter must be of integral type",
|
|
|
|
|
name);
|
|
|
|
|
vpi_printf(", got vpiType=%d\n", type);
|
|
|
|
|
vpi_free_object(argv);
|
|
|
|
|
return 0;
|
2000-05-07 20:20:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
value.format = vpiIntVal;
|
|
|
|
|
vpi_get_value(item, &value);
|
|
|
|
|
mcd = value.value.integer;
|
|
|
|
|
|
|
|
|
|
vpi_mcd_close(mcd);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-22 03:23:17 +01:00
|
|
|
static int sys_fputc_calltf(char *name)
|
|
|
|
|
{
|
|
|
|
|
unsigned int mcd;
|
|
|
|
|
int type;
|
|
|
|
|
unsigned char x;
|
|
|
|
|
s_vpi_value value, xvalue;
|
|
|
|
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
|
|
|
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
|
|
|
|
vpiHandle item = vpi_scan(argv);
|
|
|
|
|
|
|
|
|
|
if (item == 0) {
|
|
|
|
|
vpi_printf("%s: mcd parameter missing.\n", name);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type = vpi_get(vpiType, item);
|
2002-06-21 06:59:35 +02:00
|
|
|
switch (type) {
|
|
|
|
|
case vpiReg:
|
|
|
|
|
case vpiRealVal:
|
|
|
|
|
case vpiIntegerVar:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
vpi_printf("ERROR: %s mcd parameter must be of integral", name);
|
|
|
|
|
vpi_printf(", got vpiType=%d\n", type);
|
|
|
|
|
vpi_free_object(argv);
|
|
|
|
|
return 0;
|
2001-03-22 03:23:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
value.format = vpiIntVal;
|
|
|
|
|
vpi_get_value(item, &value);
|
|
|
|
|
mcd = value.value.integer;
|
|
|
|
|
|
|
|
|
|
item = vpi_scan(argv);
|
|
|
|
|
|
|
|
|
|
xvalue.format = vpiIntVal;
|
|
|
|
|
vpi_get_value(item, &xvalue);
|
|
|
|
|
x = xvalue.value.integer;
|
|
|
|
|
|
|
|
|
|
return vpi_mcd_fputc( mcd, x );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int sys_fgetc_calltf(char *name)
|
|
|
|
|
{
|
|
|
|
|
unsigned int mcd;
|
|
|
|
|
int type;
|
|
|
|
|
s_vpi_value value, rval;
|
|
|
|
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
|
|
|
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
|
|
|
|
vpiHandle item = vpi_scan(argv);
|
|
|
|
|
|
|
|
|
|
if (item == 0) {
|
|
|
|
|
vpi_printf("%s: mcd parameter missing.\n", name);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type = vpi_get(vpiType, item);
|
2002-06-21 06:59:35 +02:00
|
|
|
switch (type) {
|
|
|
|
|
case vpiReg:
|
|
|
|
|
case vpiRealVal:
|
|
|
|
|
case vpiIntegerVar:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
vpi_printf("ERROR: %s mcd parameter must be of integral", name);
|
|
|
|
|
vpi_printf(", got vpiType=%d\n", type);
|
|
|
|
|
vpi_free_object(argv);
|
|
|
|
|
return 0;
|
2001-03-22 03:23:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
value.format = vpiIntVal;
|
|
|
|
|
vpi_get_value(item, &value);
|
|
|
|
|
mcd = value.value.integer;
|
|
|
|
|
|
|
|
|
|
rval.format = vpiIntVal;
|
|
|
|
|
rval.value.integer = vpi_mcd_fgetc( mcd );
|
|
|
|
|
|
|
|
|
|
vpi_put_value(sys, &rval, 0, vpiNoDelay);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int sys_fgetc_sizetf(char*x)
|
|
|
|
|
{
|
|
|
|
|
return 32;
|
|
|
|
|
}
|
2000-05-07 20:20:07 +02:00
|
|
|
|
2002-05-31 06:26:54 +02:00
|
|
|
static int sys_timeformat_compiletf(char *xx)
|
|
|
|
|
{
|
|
|
|
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
|
|
|
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
|
|
|
|
vpiHandle tmp;
|
|
|
|
|
|
|
|
|
|
assert(argv);
|
|
|
|
|
tmp = vpi_scan(argv);
|
|
|
|
|
assert(tmp);
|
|
|
|
|
assert(vpi_get(vpiType, tmp) == vpiConstant);
|
|
|
|
|
|
|
|
|
|
tmp = vpi_scan(argv);
|
|
|
|
|
assert(tmp);
|
|
|
|
|
assert(vpi_get(vpiType, tmp) == vpiConstant);
|
|
|
|
|
|
|
|
|
|
tmp = vpi_scan(argv);
|
|
|
|
|
assert(tmp);
|
|
|
|
|
assert(vpi_get(vpiType, tmp) == vpiConstant);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int sys_timeformat_calltf(char *xx)
|
|
|
|
|
{
|
|
|
|
|
s_vpi_value value;
|
|
|
|
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
|
|
|
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
|
|
|
|
vpiHandle units = vpi_scan(argv);
|
|
|
|
|
vpiHandle prec = vpi_scan(argv);
|
|
|
|
|
vpiHandle suff = vpi_scan(argv);
|
|
|
|
|
vpiHandle wid = vpi_scan(argv);
|
|
|
|
|
|
|
|
|
|
vpi_free_object(argv);
|
|
|
|
|
|
|
|
|
|
value.format = vpiIntVal;
|
|
|
|
|
vpi_get_value(units, &value);
|
|
|
|
|
timeformat_info.units = value.value.integer;
|
|
|
|
|
|
|
|
|
|
value.format = vpiIntVal;
|
|
|
|
|
vpi_get_value(prec, &value);
|
|
|
|
|
timeformat_info.prec = value.value.integer;
|
|
|
|
|
|
|
|
|
|
value.format = vpiStringVal;
|
|
|
|
|
vpi_get_value(suff, &value);
|
|
|
|
|
timeformat_info.suff = strdup(value.value.str);
|
|
|
|
|
|
|
|
|
|
value.format = vpiIntVal;
|
|
|
|
|
vpi_get_value(wid, &value);
|
|
|
|
|
timeformat_info.width = value.value.integer;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int sys_end_of_compile(p_cb_data cb_data)
|
|
|
|
|
{
|
|
|
|
|
timeformat_info.suff = strdup("");
|
|
|
|
|
timeformat_info.units = vpi_get(vpiTimePrecision, 0);
|
2002-08-24 04:02:44 +02:00
|
|
|
timeformat_info.prec = 0;
|
2002-05-31 06:26:54 +02:00
|
|
|
timeformat_info.width = 20;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
void sys_display_register()
|
|
|
|
|
{
|
2002-05-31 06:26:54 +02:00
|
|
|
s_cb_data cb_data;
|
1999-08-15 03:23:56 +02:00
|
|
|
s_vpi_systf_data tf_data;
|
|
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
//============================== display
|
1999-08-15 03:23:56 +02:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$display";
|
|
|
|
|
tf_data.calltf = sys_display_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
1999-09-29 03:41:18 +02:00
|
|
|
tf_data.user_data = "$display";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$displayh";
|
|
|
|
|
tf_data.calltf = sys_display_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$displayh";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$displayo";
|
|
|
|
|
tf_data.calltf = sys_display_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$displayo";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$displayb";
|
|
|
|
|
tf_data.calltf = sys_display_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$displayb";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
//============================== write
|
1999-09-29 03:41:18 +02:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$write";
|
|
|
|
|
tf_data.calltf = sys_display_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$write";
|
1999-08-15 03:23:56 +02:00
|
|
|
vpi_register_systf(&tf_data);
|
1999-10-28 02:47:24 +02:00
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$writeh";
|
|
|
|
|
tf_data.calltf = sys_display_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$writeh";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$writeo";
|
|
|
|
|
tf_data.calltf = sys_display_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$writeo";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$writeb";
|
|
|
|
|
tf_data.calltf = sys_display_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$writeb";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
//============================== strobe
|
1999-10-28 02:47:24 +02:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$strobe";
|
|
|
|
|
tf_data.calltf = sys_strobe_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$strobe";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
1999-10-29 05:37:22 +02:00
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$strobeh";
|
|
|
|
|
tf_data.calltf = sys_strobe_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$strobeh";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$strobeo";
|
|
|
|
|
tf_data.calltf = sys_strobe_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$strobeo";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$strobeb";
|
|
|
|
|
tf_data.calltf = sys_strobe_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$strobeb";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
//============================== monitor
|
1999-10-29 05:37:22 +02:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$monitor";
|
|
|
|
|
tf_data.calltf = sys_monitor_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$monitor";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
2000-05-07 20:20:07 +02:00
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$monitorh";
|
|
|
|
|
tf_data.calltf = sys_monitor_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$monitorh";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$monitoro";
|
|
|
|
|
tf_data.calltf = sys_monitor_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$monitoro";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$monitorb";
|
|
|
|
|
tf_data.calltf = sys_monitor_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$monitorb";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
2002-07-25 05:35:51 +02:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$monitoron";
|
|
|
|
|
tf_data.calltf = sys_monitoron_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$monitoron";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$monitoroff";
|
|
|
|
|
tf_data.calltf = sys_monitoroff_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$monitoroff";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
//============================== fopen
|
2000-05-07 20:20:07 +02:00
|
|
|
tf_data.type = vpiSysFunc;
|
|
|
|
|
tf_data.tfname = "$fopen";
|
|
|
|
|
tf_data.calltf = sys_fopen_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = sys_fopen_sizetf;
|
|
|
|
|
tf_data.user_data = "$fopen";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
//============================== fclose
|
2000-05-07 20:20:07 +02:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$fclose";
|
|
|
|
|
tf_data.calltf = sys_fclose_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$fclose";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
//============================== fdisplay
|
2000-05-07 20:20:07 +02:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$fdisplay";
|
|
|
|
|
tf_data.calltf = sys_fdisplay_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$fdisplay";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$fdisplayh";
|
|
|
|
|
tf_data.calltf = sys_fdisplay_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$fdisplayh";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$fdisplayo";
|
|
|
|
|
tf_data.calltf = sys_fdisplay_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$fdisplayo";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$fdisplayb";
|
|
|
|
|
tf_data.calltf = sys_fdisplay_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$fdisplayb";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
//============================== fwrite
|
2000-05-07 20:20:07 +02:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$fwrite";
|
|
|
|
|
tf_data.calltf = sys_fdisplay_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$fwrite";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
2001-03-22 03:23:17 +01:00
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
//============================== fputc
|
2001-03-22 03:23:17 +01:00
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$fputc";
|
|
|
|
|
tf_data.calltf = sys_fputc_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
tf_data.user_data = "$fputc";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
2002-01-15 04:23:34 +01:00
|
|
|
//============================== fgetc
|
2001-03-22 03:23:17 +01:00
|
|
|
tf_data.type = vpiSysFunc;
|
|
|
|
|
tf_data.tfname = "$fgetc";
|
|
|
|
|
tf_data.calltf = sys_fgetc_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = sys_fgetc_sizetf;
|
|
|
|
|
tf_data.user_data = "$fgetc";
|
|
|
|
|
vpi_register_systf(&tf_data);
|
2002-05-31 06:26:54 +02:00
|
|
|
|
|
|
|
|
//============================ timeformat
|
|
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$timeformat";
|
|
|
|
|
tf_data.calltf = sys_timeformat_calltf;
|
|
|
|
|
tf_data.compiletf = sys_timeformat_compiletf;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
|
|
|
|
|
cb_data.reason = cbEndOfCompile;
|
|
|
|
|
cb_data.cb_rtn = sys_end_of_compile;
|
|
|
|
|
cb_data.user_data = "system";
|
|
|
|
|
vpi_register_cb(&cb_data);
|
1999-08-15 03:23:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* $Log: sys_display.c,v $
|
2002-08-24 04:02:44 +02:00
|
|
|
* Revision 1.44 2002/08/24 02:02:44 steve
|
|
|
|
|
* Rewire time formatting to handle all cases.
|
|
|
|
|
*
|
2002-08-23 01:34:52 +02:00
|
|
|
* Revision 1.43 2002/08/22 23:34:52 steve
|
|
|
|
|
* Watch signed comparisons, that lead to infinite loops.
|
|
|
|
|
*
|
2002-08-12 03:34:58 +02:00
|
|
|
* Revision 1.42 2002/08/12 01:35:04 steve
|
|
|
|
|
* conditional ident string using autoconfig.
|
|
|
|
|
*
|
2002-07-25 05:35:51 +02:00
|
|
|
* Revision 1.41 2002/07/25 03:35:51 steve
|
|
|
|
|
* Add monitoron and monitoroff system tasks.
|
|
|
|
|
*
|
2002-07-23 04:41:15 +02:00
|
|
|
* Revision 1.40 2002/07/23 02:41:15 steve
|
|
|
|
|
* Fix display of no arguments.
|
|
|
|
|
*
|
2002-06-21 06:59:35 +02:00
|
|
|
* Revision 1.39 2002/06/21 04:59:36 steve
|
|
|
|
|
* Carry integerness throughout the compilation.
|
|
|
|
|
*
|
2002-05-31 06:26:54 +02:00
|
|
|
* Revision 1.38 2002/05/31 04:26:54 steve
|
|
|
|
|
* Add support for $timeformat.
|
|
|
|
|
*
|
2002-05-24 21:05:30 +02:00
|
|
|
* Revision 1.37 2002/05/24 19:05:30 steve
|
|
|
|
|
* support GCC __attributes__ for printf formats.
|
|
|
|
|
*
|
2002-04-06 22:25:45 +02:00
|
|
|
* Revision 1.36 2002/04/06 20:25:45 steve
|
|
|
|
|
* cbValueChange automatically replays.
|
|
|
|
|
*
|
2002-02-06 05:50:04 +01:00
|
|
|
* Revision 1.35 2002/02/06 04:50:04 steve
|
|
|
|
|
* Detect and skip suppressed values in display
|
|
|
|
|
*
|
2002-01-22 01:18:10 +01:00
|
|
|
* Revision 1.34 2002/01/22 00:18:10 steve
|
|
|
|
|
* Better calcuation of dec string width (Larry Doolittle)
|
|
|
|
|
*
|
2002-01-15 04:23:34 +01:00
|
|
|
* Revision 1.33 2002/01/15 03:23:34 steve
|
|
|
|
|
* Default widths pad out as per the standard,
|
|
|
|
|
* add $displayb/o/h et al., and some better
|
|
|
|
|
* error messages for incorrect formats.
|
|
|
|
|
*
|
2002-01-11 05:48:01 +01:00
|
|
|
* Revision 1.32 2002/01/11 04:48:01 steve
|
|
|
|
|
* Add the %c format, and some warning messages.
|
|
|
|
|
*
|
2001-11-02 06:56:47 +01:00
|
|
|
* Revision 1.31 2001/11/02 05:56:47 steve
|
|
|
|
|
* initialize scope for %m in $fdisplay.
|
|
|
|
|
*
|
2001-10-25 06:19:53 +02:00
|
|
|
* Revision 1.30 2001/10/25 04:19:53 steve
|
|
|
|
|
* VPI support for callback to return values.
|
1999-08-15 03:23:56 +02:00
|
|
|
*/
|
|
|
|
|
|