17.9. Функции распределения вероятностей Verilog

Содержание

Имеется набор генераторов случайных чисел, которые возвращают целочисленные значения, распределенные в соответствии со стандартными функциями распределения вероятности.

17.9.1. $random

Синтаксис системной функции $random показан в Синтаксисе 17-17.

random_function ::= $random [ ( seed ) ]
Синтаксис 17-17-Синтаксис для $random

$random — это системная функция, которая предоставляет механизм для генерации случайных чисел. При каждом вызове функция возвращает новое 32-битное случайное число. Случайное число является знаковым целым числом. Оно может быть положительным или отрицательным. Более подробную информацию о вероятностных генераторах случайных чисел смотрите в разделе 17.9.2.

Аргумент seed управляет числами, которые возвращает $random, так что разные seed генерируют разные случайные потоки. Аргумент seed должен быть либо reg, либо целым числом, либо временной переменной. Значение seed должно быть присвоено этой переменной до вызова $random.

Например:

Пример 1 — Если b больше 0, то выражение ($random % b) дает число в следующем диапазоне: [(-b+1): (b-1)].

Следующий фрагмент кода показывает пример генерации случайного числа в диапазоне от -59 до 59:
reg [23:0] rand; rand = $random % 60;
Пример 2 Следующий пример показывает, как добавление оператора конкатенации к предыдущему примеру дает rand положительное значение от 0 до 59:
reg [23:0] rand; rand = {$random} % 60;

17.9.2. $dist_

Синтаксис для вероятностных функций распределения показан в Синтаксисе 17-18.

dist_functions ::= $dist_uniform ( seed , start , end ) | $dist_normal ( seed , mean , standard_deviation ) | $dist_exponential ( seed , mean ) | $dist_poisson ( seed , mean ) | $dist_chi_square ( seed , degree_of_freedom ) | $dist_t ( seed , degree_of_freedom ) | $dist_erlang ( seed , k_stage , mean )
Синтаксис 17-18 — Синтаксис для вероятностных функций распределения

Все аргументы системных функций являются целочисленными значениями. Для функций exponential, poisson, chi-square, t и erlang аргументы mean, degree_of_freedom и k_stage должны быть больше 0.

Каждая из этих функций возвращает псевдослучайное число, характеристики которого описываются именем функции. Другими словами, $dist_uniform(Непрерывное равномерное распределение) возвращает случайные числа, равномерно распределенные в интервале, заданном ее аргументами.

Для каждой системной функции аргумент seed является аргументом inout. Т.е. в функцию передается значение, а возвращается другое значение. Функции системы должны всегда возвращать одно и то же значение при одном и том же seed. Это облегчает отладку, делая работу системы повторяемой. Аргумент seed должен быть целочисленной переменной, которая инициализируется пользователем и обновляется только системной функцией. Это гарантирует достижение желаемого распределения.

В функции $dist_uniform(Непрерывное равномерное распределение) аргументы start и end являются целочисленными значениями, которые ограничивают возвращаемые значения. Начальное значение должно быть меньше конечного.

Аргумент mean, используемый $dist_normal(нормальное распределение), $dist_exponential(экспоненциальное распределение), $dist_poisson(распределение Пуассона) и $dist_erlang(распределение Ерланга), представляет собой целочисленный вход, который заставляет среднее значение, возвращаемое функцией, приближаться к указанному значению.

Аргумент standard_deviation, используемый с функцией $dist_normal, является целочисленным параметром, который помогает определить форму функции плотности. Большие числа для стандартного отклонения распределяют возвращаемые значения по более широкому диапазону.

Аргумент degree_of_freedom, используемый с функциями $dist_chi_square(распределение хи-квадрат) и $dist_t, является целочисленным значением, которое помогает определить форму функции плотности. Большие числа распределяют возвращаемые значения по более широкому диапазону.

17.9.3. Алгоритм для функций распределения вероятностей

В таблице 17-17 перечислены функции вероятностного распределения Verilog с соответствующими функциями на языке C.

Таблица 17.17 Перекрестный список функций Verilog на C

Функция VerilogФункция C
$dist_uniformrtl_dist_uniform
$dist_normalrtl_dist_normal
$dist_exponentialrtl_dist_exponential
$dist_poissonrtl_dist_poisson
$dist_chi_squarertl_dist_chi_square
$dist_trtl_dist_t
$dist_erlangrtl_dist_erlang
$randomrtl_dist_uniform (seed, LONG_MIN, LONG_MAX)
Алгоритм работы этих функций определяется следующим кодом на языке Си(C).
/* * Algorithm for probabilistic distribution functions. * * IEEE Std 1364-2005 Verilog Hardware Description Language (HDL) */ #include <limits.h> static double uniform( long *seed, long start, long end ); static double normal( long *seed, long mean, long deviation); static double exponential( long *seed, long mean); static long poisson( long *seed, long mean); static double chi_square( long *seed, long deg_of_free); static double t( long *seed, long deg_of_free); static double erlangian( long *seed, long k, long mean); long rtl_dist_chi_square( seed, df ) long *seed; long df; { double r; long i; if(df>0) { r=chi_square(seed,df); if(r>=0) { i=(long)(r+0.5); } else { r = -r; i=(long)(r+0.5); i = -i; } } else { print_error("WARNING: Chi_square distribution must ", "have positive degree of freedom\n"); i=0; } return (i); } long rtl_dist_erlang( seed, k, mean ) long *seed; long k, mean; { double r; long i; if(k>0) { r=erlangian(seed,k,mean); if(r>=0) { i=(long)(r+0.5); } else { r = -r; i=(long)(r+0.5); i = -i; } } else { print_error("WARNING: k-stage erlangian distribution ", "must have positive k\n"); i=0; } return (i); } long rtl_dist_exponential( seed, mean ) long *seed; long mean; { double r; long i; if(mean>0) { r=exponential(seed,mean); if(r>=0) { i=(long)(r+0.5); } else { r = -r; i=(long)(r+0.5); i = -i; } } else { print_error("WARNING: Exponential distribution must ", "have a positive mean\n"); i=0; } return (i); } long rtl_dist_normal( seed, mean, sd ) long *seed; long mean, sd; { double r; long i; r=normal(seed,mean,sd); if(r>=0) { i=(long)(r+0.5); } else { r = -r; i=(long)(r+0.5); i = -i; } return (i); } long rtl_dist_poisson( seed, mean ) long *seed; long mean; { long i; if(mean>0) { i=poisson(seed,mean); } else { print_error("WARNING: Poisson distribution must have a ", "positive mean\n"); i=0; } return (i); } long rtl_dist_t( seed, df ) long *seed; long df; { double r; long i; if(df>0) { r=t(seed,df); if(r>=0) { i=(long)(r+0.5); } else { r = -r; i=(long)(r+0.5); i = -i; } } else { print_error("WARNING: t distribution must have positive ", "degree of freedom\n"); i=0; } return (i); } long rtl_dist_uniform(seed, start, end) long *seed; long start, end; { double r; long i; if (start >= end) return(start); if (end != LONG_MAX) { end++; 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--; r = uniform( seed, start, end) + 1.0; if (r>=0) { i = (long) r; } else { i = (long) (r-1); } if (i<=start) i = start+1; 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); } static double uniform( seed, start, end ) long *seed, start, end; { union u_s { float s; unsigned stemp; } u; 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; /* * This relies on IEEE floating point format */ u.stemp = (u.stemp >> 9) | 0x3f800000; c = (double) u.s; c = c+(c*d); c = ((b - a) * (c - 1.0)) + a; return (c); } static double normal(seed,mean,deviation) long *seed,mean,deviation; { double v1,v2,s; double log(), sqrt(); s = 1.0; while ((s >= 1.0) || (s == 0.0)) { v1 = uniform(seed,-1,1); v2 = uniform(seed,-1,1); s = v1 * v1 + v2 * v2; } s = v1 * sqrt(-2.0 * log(s) / s); v1 = (double) deviation; v2 = (double) mean; return(s * v1 + v2); } static double exponential(seed,mean) long *seed,mean; { double log(),n; n = uniform(seed,0,1); if(n != 0) { n = -log(n) * mean; } return(n); } static long poisson(seed,mean) long *seed,mean; { long n; double p,q; double exp(); n = 0; q = -(double)mean; p = exp(q); q = uniform(seed,0,1); while(p < q) { n++; q = uniform(seed,0,1) * q; } return(n); } static double chi_square(seed,deg_of_free) long *seed,deg_of_free; { double x; long k; if(deg_of_free % 2) { x = normal(seed,0,1); x = x * x; } else { x = 0.0; } for(k = 2; k <= deg_of_free; k = k + 2) { x = x + 2 * exponential(seed,1); } return(x); } static double t(seed,deg_of_free) long *seed,deg_of_free; { double sqrt(),x; double chi2 = chi_square(seed,deg_of_free); double div = chi2 / (double)deg_of_free; double root = sqrt(div); x = normal(seed,0,1) / root; return(x); } static double erlangian(seed,k,mean) long *seed,k,mean; { double x,log(),a,b; long i; x=1.0; for(i=1;i<=k;i++) { x = x * uniform(seed,0,1); } a=(double)mean; b=(double)k; x= -a*log(x)/b; return(x); }