Check the random function seed type and a fix to handle time variables.

The standard states that the seed for the random functions should be
an integer/time variable or a register. This patch fixes the compiletf
routines to check for this. There is also a small patch to
vvp/vpi_signal.cc that removes an assert that was failing and replaces
it with appropriate code. The assert was verifying that the source was
not bigger than an integer. The problem with this is that a time
variable or register may be bigger than an integer. I altered the code
to remove the assert and copy only the lower (8 * sizeof integer) bits.
The potential overflow/loss of precision is not checked. This passes
the regression tests.
This commit is contained in:
Cary R 2007-07-24 09:01:56 -07:00 committed by Stephen Williams
parent 8dc23dad59
commit 1aa4394d75
2 changed files with 50 additions and 38 deletions

View File

@ -366,7 +366,7 @@ static PLI_INT32 sys_rand_two_args_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle arg1, arg2;
vpiHandle seed, arg2;
/* Check that there are arguments. */
if (argv == 0) {
@ -376,7 +376,7 @@ static PLI_INT32 sys_rand_two_args_compiletf(PLI_BYTE8 *name)
}
/* Check that there are at least two arguments. */
arg1 = vpi_scan(argv); /* This should never be zero. */
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);
@ -384,19 +384,22 @@ static PLI_INT32 sys_rand_two_args_compiletf(PLI_BYTE8 *name)
return 0;
}
/* These functions can't do anything with strings. */
if (vpi_get(vpiType, arg1) == vpiConstant &&
vpi_get(vpiConstType, arg1) == vpiStringConst ||
vpi_get(vpiType, arg2) == vpiConstant &&
vpi_get(vpiConstType, arg2) == vpiStringConst) {
vpi_printf("ERROR: %s does not take a string argument.\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"
" varible or a register.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
/* These functions takes at most two argument. */
arg1 = vpi_scan(argv);
if (arg1 != 0) {
seed = vpi_scan(argv);
if (seed != 0) {
vpi_printf("ERROR: %s takes at most two argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
@ -410,7 +413,7 @@ static PLI_INT32 sys_rand_three_args_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle arg1, arg2, arg3;
vpiHandle seed, arg2, arg3;
/* Check that there are arguments. */
if (argv == 0) {
@ -420,7 +423,7 @@ static PLI_INT32 sys_rand_three_args_compiletf(PLI_BYTE8 *name)
}
/* Check that there are at least three arguments. */
arg1 = vpi_scan(argv); /* This should never be zero. */
seed = vpi_scan(argv); /* This should never be zero. */
arg2 = vpi_scan(argv);
if (arg2) {
arg3 = vpi_scan(argv);
@ -433,21 +436,22 @@ static PLI_INT32 sys_rand_three_args_compiletf(PLI_BYTE8 *name)
return 0;
}
/* These functions can't do anything with strings. */
if (vpi_get(vpiType, arg1) == vpiConstant &&
vpi_get(vpiConstType, arg1) == vpiStringConst ||
vpi_get(vpiType, arg2) == vpiConstant &&
vpi_get(vpiConstType, arg2) == vpiStringConst ||
vpi_get(vpiType, arg3) == vpiConstant &&
vpi_get(vpiConstType, arg3) == vpiStringConst) {
vpi_printf("ERROR: %s does not take a string argument.\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"
" varible or a register.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
/* These functions takes at most two argument. */
arg1 = vpi_scan(argv);
if (arg1 != 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;
@ -461,23 +465,28 @@ static PLI_INT32 sys_random_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle arg;
vpiHandle seed;
/* The seed is optional. */
if (argv == 0) return 0;
arg = vpi_scan(argv);
seed = vpi_scan(argv);
/* random can't do anything with strings. */
if (vpi_get(vpiType, arg) == vpiConstant &&
vpi_get(vpiConstType, arg) == vpiStringConst) {
vpi_printf("ERROR: %s does not take a string argument.\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"
" varible or a register.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
/* random takes at most one argument (the seed). */
arg = vpi_scan(argv);
if (arg != 0) {
seed = vpi_scan(argv);
if (seed != 0) {
vpi_printf("ERROR: %s takes at most one argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;

View File

@ -262,9 +262,12 @@ static unsigned signal_width(const struct __vpiSignal*rfp)
static void signal_get_IntVal(struct __vpiSignal*rfp, s_vpi_value*vp)
{
unsigned wid = signal_width(rfp);
unsigned iwid = 8 * sizeof vp->value.integer;
vvp_fun_signal_vec*vsig = dynamic_cast<vvp_fun_signal_vec*>(rfp->node->fun);
assert(wid <= 8 * sizeof vp->value.integer);
if (wid > iwid) {
wid = iwid;
}
vp->value.integer = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {