diff --git a/vpi/Makefile.in b/vpi/Makefile.in index c76ef6705..ab500350f 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -18,7 +18,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.20 2001/01/09 03:11:28 steve Exp $" +#ident "$Id: Makefile.in,v 1.21 2001/02/16 00:26:38 steve Exp $" # # SHELL = /bin/sh @@ -54,7 +54,8 @@ all: system.vpi mv $*.d dep O = sys_table.o sys_display.o sys_finish.o sys_random.o \ -sys_readmem.o sys_readmem_lex.o sys_time.o sys_vcd.o +sys_readmem.o sys_readmem_lex.o sys_time.o sys_vcd.o \ +mt19937int.o ifeq (@CYGWIN@,yes) SYSTEM_VPI_LDFLAGS=-Wl,--enable-auto-image-base -L../vvm -lvvm -lvpip diff --git a/vpi/mt19937int.c b/vpi/mt19937int.c new file mode 100644 index 000000000..88c52e30a --- /dev/null +++ b/vpi/mt19937int.c @@ -0,0 +1,115 @@ + +/* + * NOTE: This code as been slightly modified to interface with the + * PLI implementations of $random. The copyright and license + * information are given in the comment block below. + * + * The Modifications include: + * + * Remove the "main" function, as this is being used for its functions. + * + * Change the function prototypes to use ANSI/ISO C syntax. + */ + +/* A C-program for MT19937: Integer version (1998/4/6) */ +/* genrand() generates one pseudorandom unsigned integer (32bit) */ +/* which is uniformly distributed among 0 to 2^32-1 for each */ +/* call. sgenrand(seed) set initial values to the working area */ +/* of 624 words. Before genrand(), sgenrand(seed) must be */ +/* called once. (seed is any 32-bit integer except for 0). */ +/* Coded by Takuji Nishimura, considering the suggestions by */ +/* Topher Cooper and Marc Rieffel in July-Aug. 1997. */ + +/* This library is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public */ +/* License as published by the Free Software Foundation; either */ +/* version 2 of the License, or (at your option) any later */ +/* version. */ +/* This library 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 Library General Public License for more details. */ +/* You should have received a copy of the GNU Library General */ +/* Public License along with this library; if not, write to the */ +/* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */ +/* 02111-1307 USA */ + +/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */ +/* When you use this, send an email to: matumoto@math.keio.ac.jp */ +/* with an appropriate reference to your work. */ + +/* REFERENCE */ +/* M. Matsumoto and T. Nishimura, */ +/* "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform */ +/* Pseudo-Random Number Generator", */ +/* ACM Transactions on Modeling and Computer Simulation, */ +/* Vol. 8, No. 1, January 1998, pp 3--30. */ + + +/* Period parameters */ +#define N 624 +#define M 397 +#define MATRIX_A 0x9908b0df /* constant vector a */ +#define UPPER_MASK 0x80000000 /* most significant w-r bits */ +#define LOWER_MASK 0x7fffffff /* least significant r bits */ + +/* Tempering parameters */ +#define TEMPERING_MASK_B 0x9d2c5680 +#define TEMPERING_MASK_C 0xefc60000 +#define TEMPERING_SHIFT_U(y) (y >> 11) +#define TEMPERING_SHIFT_S(y) (y << 7) +#define TEMPERING_SHIFT_T(y) (y << 15) +#define TEMPERING_SHIFT_L(y) (y >> 18) + +static unsigned long mt[N]; /* the array for the state vector */ +static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ + +/* initializing the array with a NONZERO seed */ +void +sgenrand(unsigned long seed) +{ + /* setting initial seeds to mt[N] using */ + /* the generator Line 25 of Table 1 in */ + /* [KNUTH 1981, The Art of Computer Programming */ + /* Vol. 2 (2nd Ed.), pp102] */ + mt[0]= seed & 0xffffffff; + for (mti=1; mti= N) { /* generate N words at one time */ + int kk; + + if (mti == N+1) /* if sgenrand() has not been called, */ + sgenrand(4357); /* a default initial seed is used */ + + for (kk=0;kk> 1) ^ mag01[y & 0x1]; + } + for (;kk> 1) ^ mag01[y & 0x1]; + } + y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); + mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1]; + + mti = 0; + } + + y = mt[mti++]; + y ^= TEMPERING_SHIFT_U(y); + y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B; + y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; + y ^= TEMPERING_SHIFT_L(y); + + return y; +} + diff --git a/vpi/sys_random.c b/vpi/sys_random.c index 745c87450..691458abb 100644 --- a/vpi/sys_random.c +++ b/vpi/sys_random.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: sys_random.c,v 1.2 2000/07/08 22:41:07 steve Exp $" +#ident "$Id: sys_random.c,v 1.3 2001/02/16 00:26:38 steve Exp $" #endif # include @@ -26,84 +26,10 @@ # include # include -#if 0 -double uniform(long*seed, long start, long end) -{ - union u_s { - float s; - unsigned stemp; - } u; +extern void sgenrand(unsigned long seed); +extern unsigned long genrand(void); - double d = 0.00000011920928955078125; - double a, b, c; - if ((*seed) == 0) - *seed = 259341593; - - if (start >= end) { - a = 0.0; - b = 2147483647.0; - - } else { - a = (double) start; - b = (double) end; - } - - *seed = 69069 * (*seed) + 1; - u.stemp = *seed; - - u.stemp = (u.stemp >> 9) | 0x3f800000; - - c = (double) u.s; - c = c + (c*d); - c = ((b - a) * (c - 1.0)) + a; - return c; -} -#endif - -#if 0 -static long rtl_dist_uniform(long*seed, long start, long end) -{ - double r; - long i; - - if (start >= end) - return start; - - if (end != LONG_MAX) { - end += 1; - r = uniform(seed, start, end); - if (r >= 0) - i = (long) r; - else - i = (long) (r-1); - - if (i < start) i = start; - if (i >= end) i = end - 1; - - } else if (start != LONG_MIN) { - start -= 1; - r = uniform(seed, start, end); - if (r >= 0) - i = (long) r; - else - i = (long) (r-1); - - if (i <= start) i = start; - if (i > end) i = end; - - } else { - r = (uniform(seed, start, end) + 2147483648.0) / 4294967295.0; - r = r * 4294967296.0 - 2147483648.0; - if (r >= 0) - i = (long) r; - else - i = (long) (r-1); - } - - return i; -} -#else static long rtl_dist_uniform(long*seed, long start, long end) { if (start >= end) @@ -116,7 +42,6 @@ static long rtl_dist_uniform(long*seed, long start, long end) return random(); } } -#endif static int sys_dist_uniform_calltf(char*name) @@ -174,12 +99,11 @@ static int sys_dist_uniform_sizetf(char*x) } /* - * Implement the $random system function. For now, ignore any - * parameters and only produce a random number. + * Implement the $random system function using the ``Mersenne + * Twister'' random number generator MT19937. */ static int sys_random_calltf(char*name) { - static long i_seed = 0; s_vpi_value val; vpiHandle call_handle; vpiHandle argv; @@ -188,6 +112,8 @@ static int sys_random_calltf(char*name) 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); if (argv) { seed = vpi_scan(argv); @@ -195,19 +121,21 @@ static int sys_random_calltf(char*name) val.format = vpiIntVal; vpi_get_value(seed, &val); - i_seed = val.value.integer; + sgenrand(val.value.integer); } val.format = vpiIntVal; - val.value.integer = rtl_dist_uniform(&i_seed, LONG_MIN, LONG_MAX); + val.value.integer = genrand(); vpi_put_value(call_handle, &val, 0, vpiNoDelay); +#if 0 if (seed) { val.format = vpiIntVal; val.value.integer = i_seed; vpi_put_value(seed, &val, 0, vpiNoDelay); } +#endif return 0; } @@ -240,6 +168,10 @@ void sys_random_register() /* * $Log: sys_random.c,v $ + * Revision 1.3 2001/02/16 00:26:38 steve + * Use Mersenne Twister 19937 pseudo-random number generator + * for the $random system task, and support the seed paramter. + * * Revision 1.2 2000/07/08 22:41:07 steve * Add the dist_uniform function. *