More compiletf cleanup and refactoring.

This patch adds compiletf routines for the mti random functions
and adds a common routine to check for extra arguments. It also
adds file and line information to the rest of the compiletf
routines that were missing them.
This commit is contained in:
Cary R 2009-02-26 15:22:21 -08:00 committed by Stephen Williams
parent fa1160c4ab
commit ddea64445c
12 changed files with 209 additions and 351 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2008 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2008-2009 Cary R. (cygcary@yahoo.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -48,7 +48,7 @@ static unsigned is_numeric_obj(vpiHandle obj)
case vpiRealVar:
case vpiReg:
case vpiTimeVar:
rtn = 1;;
rtn = 1;
break;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Michael Ruff (mruff at chiaro.com)
* Copyright (c) 2003-2009 Michael Ruff (mruff at chiaro.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
@ -19,6 +19,7 @@
# include "vpi_config.h"
# include "vpi_user.h"
# include "sys_priv.h"
# include <stdio.h>
# include <string.h>
# include <math.h>
@ -119,13 +120,8 @@ static PLI_INT32 sys_convert_compiletf(PLI_BYTE8*name)
vpi_put_userdata(callh, (void *) arg);
/* These functions only take one argument. */
arg = vpi_scan(argv);
if (arg != 0) {
error_message(callh, "%s takes only one argument.\n");
return 0;
}
check_for_extra_args(argv, callh, name, "one argument", 0);
/* vpi_scan() returning 0 (NULL) had already freed argv. */
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000 Stephan Boettcher <stephan@nevis.columbia.edu>
*
* This source code is free software; you can redistribute it
@ -18,10 +18,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "vpi_config.h"
# include "vpi_config.h"
# include "vpi_user.h"
# include "sys_priv.h"
# include <assert.h>
# include <string.h>
static PLI_INT32 sys_deposit_compiletf(PLI_BYTE8 *name)
{
@ -31,18 +32,22 @@ static PLI_INT32 sys_deposit_compiletf(PLI_BYTE8 *name)
/* Check that there are arguments. */
if (argv == 0) {
vpi_printf("ERROR: %s requires two arguments.\n", name);
vpi_control(vpiFinish, 1);
return 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;
}
/* Check that there are at least two arguments. */
target = vpi_scan(argv); /* This should never be zero. */
value = vpi_scan(argv);
if (value == 0) {
vpi_printf("ERROR: %s requires two arguments.\n", name);
vpi_control(vpiFinish, 1);
return 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;
}
assert(target);
@ -53,18 +58,15 @@ static PLI_INT32 sys_deposit_compiletf(PLI_BYTE8 *name)
case vpiReg:
break;
default:
vpi_printf("ERROR: invalid target type for %s.\n", name);
vpi_control(vpiFinish, 1);
return 0;
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("invalid target type (%s) for %s.\n",
vpi_get_str(vpiType, target), name);
vpi_control(vpiFinish, 1);
}
/* Check that there is at most two arguments. */
target = vpi_scan(argv);
if (target != 0) {
vpi_printf("ERROR: %s takes at most two arguments.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
check_for_extra_args(argv, callh, name, "two arguments", 0);
return 0;
}

View File

@ -1685,24 +1685,7 @@ static PLI_INT32 sys_timeformat_compiletf(PLI_BYTE8*name)
}
/* 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 a single numeric argument.\n", msg,
name);
vpi_printf("%*s Found %u extra argument%s.\n",
(int) strlen(msg), " ", argc,
argc == 1 ? "" : "s");
vpi_control(vpiFinish, 1);
}
check_for_extra_args(argv, callh, name, "four arguments", 0);
}
return 0;
@ -1807,24 +1790,7 @@ static PLI_INT32 sys_printtimescale_compiletf(PLI_BYTE8*name)
}
/* 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 a single argument with a module.\n",
msg, name);
vpi_printf("%*s Found %u extra argument%s.\n",
(int) strlen(msg), " ", argc,
argc == 1 ? "" : "s");
vpi_control(vpiFinish, 1);
}
check_for_extra_args(argv, callh, name, "one argument", 1);
}
return 0;

View File

@ -67,23 +67,7 @@ static PLI_INT32 sys_fopen_compiletf(PLI_BYTE8 *name)
}
/* 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 two string arguments.\n",
msg, name);
vpi_printf("%*s Found %u extra argument%s.\n",
(int) strlen(msg), " ", argc, argc == 1 ? "" : "s");
vpi_control(vpiFinish, 1);
}
check_for_extra_args(argv, callh, name, "two string arguments", 1);
return 0;
}
@ -377,22 +361,7 @@ static PLI_INT32 sys_fgets_compiletf(PLI_BYTE8*name)
}
/* 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 two arguments.\n", msg, name);
vpi_printf("%*s Found %u extra argument%s.\n",
(int) strlen(msg), " ", argc, argc == 1 ? "" : "s");
vpi_control(vpiFinish, 1);
}
check_for_extra_args(argv, callh, name, "two arguments", 0);
return 0;
}
@ -563,22 +532,7 @@ static PLI_INT32 sys_fseek_compiletf(PLI_BYTE8*name)
}
/* 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 three arguments.\n", msg, name);
vpi_printf("%*s Found %u extra argument%s.\n",
(int) strlen(msg), " ", argc, argc == 1 ? "" : "s");
vpi_control(vpiFinish, 1);
}
check_for_extra_args(argv, callh, name, "three arguments", 0);
return 0;
}

View File

@ -124,22 +124,7 @@ static PLI_INT32 sys_value_plusargs_compiletf(PLI_BYTE8*name)
}
/* 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 two arguments.\n", msg, name);
vpi_printf("%*s Found %u extra argument%s.\n",
(int)strlen(msg), " ", argc, argc == 1 ? "" : "s");
vpi_control(vpiFinish, 1);
}
check_for_extra_args(argv, callh, name, "two arguments", 0);
return 0;
}

View File

@ -34,7 +34,7 @@ PLI_UINT64 timerec_to_time64(const struct t_vpi_time*time)
return tmp;
}
char * as_escaped(char *arg)
char *as_escaped(char *arg)
{
unsigned idx, cur, cnt, len = strlen(arg);
char *res = (char *) malloc(sizeof(char *) * len);
@ -60,7 +60,7 @@ char * as_escaped(char *arg)
* 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)
char *get_filename(vpiHandle callh, char *name, vpiHandle file)
{
s_vpi_value val;
unsigned len, idx;
@ -101,6 +101,29 @@ char * get_filename(vpiHandle callh, char *name, vpiHandle file)
return strdup(val.value.str);
}
void check_for_extra_args(vpiHandle argv, vpiHandle callh, char *name,
char *arg_str, unsigned opt)
{
/* Check that 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 %s%s.\n", msg, name,
opt ? "at most ": "", arg_str);
vpi_printf("%*s Found %u extra argument%s.\n",
(int) strlen(msg), " ", argc, argc == 1 ? "" : "s");
vpi_control(vpiFinish, 1);
}
}
/*
* This routine returns 1 if the argument is a constant value,
* otherwise it returns 0.
@ -260,22 +283,7 @@ PLI_INT32 sys_one_numeric_arg_compiletf(PLI_BYTE8 *name)
}
/* 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 a single numeric argument.\n", msg, name);
vpi_printf("%*s Found %u extra argument%s.\n",
(int) strlen(msg), " ", argc, argc == 1 ? "" : "s");
vpi_control(vpiFinish, 1);
}
check_for_extra_args(argv, callh, name, "a single numeric argument", 0);
return 0;
}
@ -297,23 +305,7 @@ PLI_INT32 sys_one_opt_numeric_arg_compiletf(PLI_BYTE8 *name)
}
/* 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 one numeric argument.\n",
msg, name);
vpi_printf("%*s Found %u extra argument%s.\n",
(int) strlen(msg), " ", argc, argc == 1 ? "" : "s");
vpi_control(vpiFinish, 1);
}
check_for_extra_args(argv, callh, name, "one numeric argument", 1);
return 0;
}
@ -358,22 +350,7 @@ PLI_INT32 sys_two_numeric_args_compiletf(PLI_BYTE8 *name)
}
/* 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 two numeric arguments.\n", msg, name);
vpi_printf("%*s Found %u extra argument%s.\n",
(int) strlen(msg), " ", argc, argc == 1 ? "" : "s");
vpi_control(vpiFinish, 1);
}
check_for_extra_args(argv, callh, name, "two numeric arguments", 0);
return 0;
}
@ -400,22 +377,7 @@ PLI_INT32 sys_one_string_arg_compiletf(PLI_BYTE8 *name)
}
/* 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 a single string argument.\n", msg, name);
vpi_printf("%*s Found %u extra argument%s.\n",
(int) strlen(msg), " ", argc, argc == 1 ? "" : "s");
vpi_control(vpiFinish, 1);
}
check_for_extra_args(argv, callh, name, "a single string argument", 0);
return 0;
}

View File

@ -35,8 +35,11 @@ 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);
extern char *as_escaped(char *arg);
extern char *get_filename(vpiHandle callh, char *name, vpiHandle file);
extern void check_for_extra_args(vpiHandle argv, vpiHandle callh,
char *name, char *arg_str, unsigned opt);
struct timeformat_info_s {
int units;

View File

@ -18,6 +18,7 @@
*/
# include "sys_priv.h"
# include "sys_random.h"
# include <vpi_user.h>
# include <assert.h>
@ -364,6 +365,30 @@ static double erlangian(long *seed, long k, long mean)
return x;
}
/* A seed can only be an integer/time variable or a register. */
static unsigned is_seed_obj(vpiHandle obj, vpiHandle callh, char *name)
{
unsigned rtn = 0;
assert(obj);
switch (vpi_get(vpiType, obj)) {
case vpiTimeVar:
case vpiIntegerVar:
case vpiReg:
rtn = 1;
break;
default:
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s's seed must be an integer/time"
" variable or a register.\n", name);
vpi_control(vpiFinish, 1);
}
return rtn;
}
static PLI_INT32 sys_rand_two_args_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
@ -372,46 +397,43 @@ static PLI_INT32 sys_rand_two_args_compiletf(PLI_BYTE8 *name)
/* Check that there are arguments. */
if (argv == 0) {
vpi_printf("ERROR: %s requires two arguments.\n", name);
vpi_control(vpiFinish, 1);
return 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;
}
/* Check that there are at least two arguments. */
seed = vpi_scan(argv); /* This should never be zero. */
arg2 = vpi_scan(argv);
if (arg2 == 0) {
vpi_printf("ERROR: %s requires two arguments.\n", name);
vpi_control(vpiFinish, 1);
return 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;
}
/* The seed must be a time/integer variable or a register. */
switch (vpi_get(vpiType, seed)) {
case vpiTimeVar:
case vpiIntegerVar:
case vpiReg:
break;
default:
vpi_printf("ERROR: %s's seed must be an integer/time"
" variable or a register.\n", name);
vpi_control(vpiFinish, 1);
return 0;
if (! is_seed_obj(seed, callh, name)) return 0;
/* The second argument must be numeric. */
if (! is_numeric_obj(arg2)) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s second argument must be numeric.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
/* These functions takes at most two argument. */
seed = vpi_scan(argv);
if (seed != 0) {
vpi_printf("ERROR: %s takes at most two argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
/* Check that there is at most two arguments. */
check_for_extra_args(argv, callh, name, "two arguments", 0);
/* vpi_scan returning 0 (NULL) has already freed argv. */
return 0;
}
static PLI_INT32 sys_rand_three_args_compiletf(PLI_BYTE8 *name)
PLI_INT32 sys_rand_three_args_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
@ -419,9 +441,11 @@ static PLI_INT32 sys_rand_three_args_compiletf(PLI_BYTE8 *name)
/* Check that there are arguments. */
if (argv == 0) {
vpi_printf("ERROR: %s requires three arguments.\n", name);
vpi_control(vpiFinish, 1);
return 0;
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s requires three arguments.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
/* Check that there are at least three arguments. */
@ -433,68 +457,54 @@ static PLI_INT32 sys_rand_three_args_compiletf(PLI_BYTE8 *name)
arg3 = 0;
}
if (arg2 == 0 || arg3 == 0) {
vpi_printf("ERROR: %s requires three arguments.\n", name);
vpi_control(vpiFinish, 1);
return 0;
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s requires three arguments.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
/* The seed must be a time/integer variable or a register. */
switch (vpi_get(vpiType, seed)) {
case vpiTimeVar:
case vpiIntegerVar:
case vpiReg:
break;
default:
vpi_printf("ERROR: %s's seed must be an integer/time"
" variable or a register.\n", name);
vpi_control(vpiFinish, 1);
return 0;
if (! is_seed_obj(seed, callh, name)) return 0;
/* The second argument must be numeric. */
if (! is_numeric_obj(arg2)) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s second argument must be numeric.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
/* These functions takes at most three argument. */
seed = vpi_scan(argv);
if (seed != 0) {
vpi_printf("ERROR: %s takes at most three argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
/* The third argument must be numeric. */
if (! is_numeric_obj(arg3)) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
vpi_printf("%s third argument must be numeric.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
/* vpi_scan returning 0 (NULL) has already freed argv. */
/* Check that there is at most three arguments. */
check_for_extra_args(argv, callh, name, "three arguments", 0);
return 0;
}
static PLI_INT32 sys_random_compiletf(PLI_BYTE8 *name)
PLI_INT32 sys_random_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle seed;
/* The seed is optional. */
if (argv == 0) return 0;
seed = vpi_scan(argv);
/* The seed must be a time/integer variable or a register. */
switch (vpi_get(vpiType, seed)) {
case vpiTimeVar:
case vpiIntegerVar:
case vpiReg:
break;
default:
vpi_printf("ERROR: %s's seed must be an integer/time"
" variable or a register.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
if (! is_seed_obj(vpi_scan(argv), callh, name)) return 0;
/* random takes at most one argument (the seed). */
seed = vpi_scan(argv);
if (seed != 0) {
vpi_printf("ERROR: %s takes at most one argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
/* Check that there no extra arguments. */
check_for_extra_args(argv, callh, name, "one argument", 1);
/* vpi_scan returning 0 (NULL) has already freed argv. */
return 0;
}

30
vpi/sys_random.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef __vpi_sys_rand_H
#define __vpi_sys_rand_H
/*
* Copyright (c) 2000-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
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include <vpi_user.h>
/*
* Common compiletf routines for the different random implementations.
*/
extern PLI_INT32 sys_rand_three_args_compiletf(PLI_BYTE8 *name);
extern PLI_INT32 sys_random_compiletf(PLI_BYTE8 *name);
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-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,7 @@
*/
# include "sys_priv.h"
# include "sys_random.h"
# include <vpi_user.h>
# include <assert.h>
@ -46,8 +47,7 @@ static struct context_s global_context = {
static long mti_dist_uniform(long*seed, long start, long end)
{
if (start >= end)
return start;
if (start >= end) return start;
if ((start > LONG_MIN) || (end < LONG_MAX)) {
long range = end - start;
@ -57,34 +57,18 @@ static long mti_dist_uniform(long*seed, long start, long end)
}
}
static PLI_INT32 sys_mti_dist_uniform_calltf(PLI_BYTE8*name)
{
vpiHandle callh, argv, seed, start, end;
s_vpi_value val;
vpiHandle call_handle;
vpiHandle argv;
vpiHandle seed = 0, start, end;
long i_seed, i_start, i_end;
call_handle = vpi_handle(vpiSysTfCall, 0);
assert(call_handle);
argv = vpi_iterate(vpiArgument, call_handle);
if (argv == 0) {
vpi_printf("ERROR: %s requires parameters "
"(seed, start, end)\n", name);
return 0;
}
/* Get the argument handles and convert them. */
callh = vpi_handle(vpiSysTfCall, 0);
argv = vpi_iterate(vpiArgument, callh);
seed = vpi_scan(argv);
assert(seed);
start = vpi_scan(argv);
assert(start);
end = vpi_scan(argv);
assert(end);
vpi_free_object(argv);
val.format = vpiIntVal;
vpi_get_value(seed, &val);
@ -96,74 +80,61 @@ static PLI_INT32 sys_mti_dist_uniform_calltf(PLI_BYTE8*name)
vpi_get_value(end, &val);
i_end = val.value.integer;
val.format = vpiIntVal;
/* Calculate and return the result. */
val.value.integer = mti_dist_uniform(&i_seed, i_start, i_end);
vpi_put_value(call_handle, &val, 0, vpiNoDelay);
vpi_put_value(callh, &val, 0, vpiNoDelay);
val.format = vpiIntVal;
/* Return the seed. */
val.value.integer = i_seed;
vpi_put_value(seed, &val, 0, vpiNoDelay);
vpi_free_object(argv);
return 0;
}
static PLI_INT32 sys_mti_dist_uniform_sizetf(PLI_BYTE8*x)
{
return 32;
}
static PLI_INT32 sys_mti_random_calltf(PLI_BYTE8*name)
{
vpiHandle callh, argv, seed = 0;
s_vpi_value val;
vpiHandle call_handle;
vpiHandle argv;
vpiHandle seed = 0;
int i_seed = 0;
int i_seed = COOKIE;
struct context_s *context;
call_handle = vpi_handle(vpiSysTfCall, 0);
assert(call_handle);
/* Get the argument list and look for a seed. If it is there,
get the value and reseed the random number generator. */
argv = vpi_iterate(vpiArgument, call_handle);
callh = vpi_handle(vpiSysTfCall, 0);
argv = vpi_iterate(vpiArgument, callh);
val.format = vpiIntVal;
if (argv) {
seed = vpi_scan(argv);
vpi_free_object(argv);
val.format = vpiIntVal;
vpi_get_value(seed, &val);
i_seed = val.value.integer;
/* Since there is a seed use the current
context or create a new one */
context = (struct context_s *)vpi_get_userdata(call_handle);
context = (struct context_s *)vpi_get_userdata(callh);
if (!context) {
context = (struct context_s *)calloc(1, sizeof(*context));
context->mti = NP1;
assert(context);
/* squirrel away context */
vpi_put_userdata(call_handle, (void *)context);
vpi_put_userdata(callh, (void *)context);
}
/* If the argument is not the Icarus cookie, then
reseed context */
if (i_seed != COOKIE)
sgenrand(context, i_seed);
if (i_seed != COOKIE) sgenrand(context, i_seed);
} else {
/* use global context */
context = &global_context;
}
val.format = vpiIntVal;
/* Calculate and return the result */
val.value.integer = genrand(context);
vpi_put_value(call_handle, &val, 0, vpiNoDelay);
vpi_put_value(callh, &val, 0, vpiNoDelay);
/* mark seed with cookie */
if (seed && i_seed != COOKIE) {
val.format = vpiIntVal;
val.value.integer = COOKIE;
vpi_put_value(seed, &val, 0, vpiNoDelay);
}
@ -171,29 +142,24 @@ static PLI_INT32 sys_mti_random_calltf(PLI_BYTE8*name)
return 0;
}
static PLI_INT32 sys_mti_random_sizetf(PLI_BYTE8*x)
{
return 32;
}
void sys_random_mti_register()
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysFunc;
tf_data.tfname = "$mti_random";
tf_data.calltf = sys_mti_random_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = sys_mti_random_sizetf;
tf_data.user_data = "$mti_random";
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiSysFuncInt;
tf_data.tfname = "$mti_random";
tf_data.calltf = sys_mti_random_calltf;
tf_data.compiletf = sys_random_compiletf;
tf_data.user_data = "$mti_random";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysFunc;
tf_data.tfname = "$mti_dist_uniform";
tf_data.calltf = sys_mti_dist_uniform_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = sys_mti_dist_uniform_sizetf;
tf_data.user_data = "$mti_dist_uniform";
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiSysFuncInt;
tf_data.tfname = "$mti_dist_uniform";
tf_data.calltf = sys_mti_dist_uniform_calltf;
tf_data.compiletf = sys_rand_three_args_compiletf;
tf_data.user_data = "$mti_dist_uniform";
vpi_register_systf(&tf_data);
}

View File

@ -249,23 +249,7 @@ static PLI_INT32 sys_mem_compiletf(PLI_BYTE8*name)
}
/* 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);
}
check_for_extra_args(argv, callh, name, "four arguments", 1);
return 0;
}