[PATCH] Implement System Verilog $urandom and $urandom_range functions.
This patch implements the System Verilog $urandom() and $urandom_range() functions. There are no check to verify that $urandom_range is only given unsigned arguments. If you give it a negative value the bit pattern will be interpreted as a unsigned number.
This commit is contained in:
parent
d5fe5689e1
commit
38a88014cb
162
vpi/sys_random.c
162
vpi/sys_random.c
|
|
@ -527,6 +527,124 @@ static PLI_INT32 sys_random_calltf(PLI_BYTE8 *name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* From System Verilog 3.1a. */
|
||||
static PLI_INT32 sys_urandom_range_compiletf(PLI_BYTE8 *name)
|
||||
{
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||
vpiHandle arg;
|
||||
|
||||
/* Check that there are arguments. */
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: %s requires two arguments.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check that there are at least two arguments. */
|
||||
arg = vpi_scan(argv); /* This should never be zero. */
|
||||
arg = vpi_scan(argv);
|
||||
if (arg == 0) {
|
||||
vpi_printf("ERROR: %s requires two arguments.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* These functions takes at most two argument. */
|
||||
arg = vpi_scan(argv);
|
||||
if (arg != 0) {
|
||||
vpi_printf("ERROR: %s takes at most two argument.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vpi_scan returning 0 (NULL) has already freed argv. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* From System Verilog 3.1a. */
|
||||
static unsigned long urandom(long *seed, unsigned long max, unsigned long min)
|
||||
{
|
||||
static long i_seed = 0;
|
||||
unsigned long result;
|
||||
long max_i, min_i;
|
||||
|
||||
max_i = max + INT_MIN;
|
||||
min_i = min + INT_MIN;
|
||||
if (seed != 0) i_seed = *seed;
|
||||
result = rtl_dist_uniform(&i_seed, min_i, max_i) - INT_MIN;
|
||||
if (seed != 0) *seed = i_seed;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* From System Verilog 3.1a. */
|
||||
static PLI_INT32 sys_urandom_calltf(PLI_BYTE8 *name)
|
||||
{
|
||||
vpiHandle callh, argv, seed = 0;
|
||||
s_vpi_value val;
|
||||
long i_seed;
|
||||
|
||||
/* Get the argument list and look for a seed. If it is there,
|
||||
get the value and reseed the random number generator. */
|
||||
callh = vpi_handle(vpiSysTfCall, 0);
|
||||
argv = vpi_iterate(vpiArgument, callh);
|
||||
val.format = vpiIntVal;
|
||||
if (argv) {
|
||||
seed = vpi_scan(argv);
|
||||
vpi_free_object(argv);
|
||||
vpi_get_value(seed, &val);
|
||||
i_seed = val.value.integer;
|
||||
}
|
||||
|
||||
/* Calculate and return the result. */
|
||||
if (seed) {
|
||||
val.value.integer = urandom(&i_seed, UINT_MAX, 0);
|
||||
} else {
|
||||
val.value.integer = urandom(0, UINT_MAX, 0);
|
||||
}
|
||||
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||
|
||||
/* If it exists send the updated seed back to seed parameter. */
|
||||
if (seed) {
|
||||
val.value.integer = i_seed;
|
||||
vpi_put_value(seed, &val, 0, vpiNoDelay);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* From System Verilog 3.1a. */
|
||||
static PLI_INT32 sys_urandom_range_calltf(PLI_BYTE8 *name)
|
||||
{
|
||||
vpiHandle callh, argv, maxval, minval;
|
||||
s_vpi_value val;
|
||||
unsigned long i_maxval, i_minval, tmp;
|
||||
|
||||
/* Get the argument handles and convert them. */
|
||||
callh = vpi_handle(vpiSysTfCall, 0);
|
||||
argv = vpi_iterate(vpiArgument, callh);
|
||||
maxval = vpi_scan(argv);
|
||||
minval = vpi_scan(argv);
|
||||
|
||||
val.format = vpiIntVal;
|
||||
vpi_get_value(maxval, &val);
|
||||
i_maxval = val.value.integer;
|
||||
|
||||
vpi_get_value(minval, &val);
|
||||
i_minval = val.value.integer;
|
||||
|
||||
/* Swap the two arguments if they are out of order. */
|
||||
if (i_minval > i_maxval) {
|
||||
tmp = i_minval;
|
||||
i_minval = i_maxval;
|
||||
i_maxval = tmp;
|
||||
}
|
||||
|
||||
/* Calculate and return the result. */
|
||||
val.value.integer = urandom(0, i_maxval, i_minval);
|
||||
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||
}
|
||||
|
||||
static PLI_INT32 sys_dist_uniform_calltf(PLI_BYTE8 *name)
|
||||
{
|
||||
vpiHandle callh, argv, seed, start, end;
|
||||
|
|
@ -769,12 +887,31 @@ void sys_random_register()
|
|||
tf_data.sysfunctype = vpiSysFuncInt;
|
||||
tf_data.tfname = "$random";
|
||||
tf_data.calltf = sys_random_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_random_compiletf;
|
||||
tf_data.sizetf = sys_rand_func_sizetf;
|
||||
tf_data.user_data = "$random";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
/* From System Verilog 3.1a. */
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.sysfunctype = vpiSysFuncSized;
|
||||
tf_data.tfname = "$urandom";
|
||||
tf_data.calltf = sys_urandom_calltf;
|
||||
tf_data.compiletf = sys_random_compiletf;
|
||||
tf_data.sizetf = sys_rand_func_sizetf;
|
||||
tf_data.user_data = "$urandom";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
/* From System Verilog 3.1a. */
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.sysfunctype = vpiSysFuncSized;
|
||||
tf_data.tfname = "$urandom_range";
|
||||
tf_data.calltf = sys_urandom_range_calltf;
|
||||
tf_data.compiletf = sys_urandom_range_compiletf;
|
||||
tf_data.sizetf = sys_rand_func_sizetf;
|
||||
tf_data.user_data = "$urandom_range";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.sysfunctype = vpiSysFuncInt;
|
||||
tf_data.tfname = "$dist_uniform";
|
||||
|
|
@ -839,26 +976,3 @@ void sys_random_register()
|
|||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: sys_random.c,v $
|
||||
* Revision 1.16 2007/03/14 04:05:51 steve
|
||||
* VPI tasks take PLI_BYTE* by the standard.
|
||||
*
|
||||
* Revision 1.15 2006/10/30 22:45:37 steve
|
||||
* Updates for Cygwin portability (pr1585922)
|
||||
*
|
||||
* Revision 1.14 2004/10/04 01:10:58 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.13 2004/06/17 14:44:01 steve
|
||||
* Save seed in static variable, in case user doesnt pass it.
|
||||
*
|
||||
* Revision 1.12 2004/06/10 02:14:42 steve
|
||||
* Fix transcription error scaling c in uniform range.
|
||||
*
|
||||
* Revision 1.11 2004/06/09 22:14:10 steve
|
||||
* Move Mersenne Twister to $mti_random, and make
|
||||
* the standard $random standard. Also, add $dist_poisson.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#
|
||||
|
||||
$random vpiSysFuncInt
|
||||
$urandom vpiSysFuncSized 32 unsigned
|
||||
$urandom_range vpiSysFuncSized 32 unsigned
|
||||
$dist_uniform vpiSysFuncInt
|
||||
$dist_normal vpiSysFuncInt
|
||||
$dist_exponential vpiSysFuncInt
|
||||
|
|
|
|||
Loading…
Reference in New Issue