Library of reusable VHDL components
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1078 lines
41 KiB

  1. --
  2. -- File Name: RandomPkg.vhd
  3. -- Design Unit Name: RandomPkg
  4. -- Revision: STANDARD VERSION, revision 2.1
  5. --
  6. -- Maintainer: Jim Lewis email: jim@synthworks.com
  7. -- Contributor(s):
  8. -- Jim Lewis email: jim@synthworks.com
  9. -- *
  10. --
  11. -- * In writing procedures normal, poisson, the following sources were referenced:
  12. -- Wikipedia
  13. -- package rnd2 written by John Breen and Ken Christensen
  14. -- package RNG written by Gnanasekaran Swaminathan
  15. --
  16. --
  17. -- Description:
  18. -- RandomPType, a protected type, defined to hold randomization RandomSeeds and
  19. -- function methods to facilitate randomization with uniform and weighted
  20. -- distributions
  21. --
  22. -- Developed for:
  23. -- SynthWorks Design Inc.
  24. -- VHDL Training Classes
  25. -- 11898 SW 128th Ave. Tigard, Or 97223
  26. -- http://www.SynthWorks.com
  27. --
  28. -- Revision History:
  29. -- Date Version Description
  30. -- 12/2006: 0.1 Initial revision
  31. -- Numerous revisions for VHDL Testbenches and Verification
  32. -- 02/2009: 1.0 First Public Released Version
  33. -- 02/25/2009 1.1 Replaced reference to std_2008 with a reference to
  34. -- ieee_proposed.standard_additions.all ;
  35. -- 06/2010 1.2 Added Normal and Poisson distributions
  36. -- 03/2011 2.0 STANDARD VERSION
  37. -- Major clean-up.
  38. -- Moved RandomParmType and control to here
  39. -- 07/2011 2.1 STANDARD VERSION
  40. -- Bug fix to convenience functions for slv, unsigned, and signed.
  41. --
  42. --
  43. -- Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011 by SynthWorks Design Inc. All rights reserved.
  44. --
  45. -- Verbatim copies of this source file may be used and
  46. -- distributed without restriction.
  47. --
  48. -- This source file is free software; you can redistribute it
  49. -- and/or modify it under the terms of the ARTISTIC License
  50. -- as published by The Perl Foundation; either version 2.0 of
  51. -- the License, or (at your option) any later version.
  52. --
  53. -- This source is distributed in the hope that it will be
  54. -- useful, but WITHOUT ANY WARRANTY; without even the implied
  55. -- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  56. -- PURPOSE. See the Artistic License for details.
  57. --
  58. -- You should have received a copy of the license with this source.
  59. -- If not download it from,
  60. -- http://www.perlfoundation.org/artistic_license_2_0
  61. --
  62. library osvvm;
  63. use osvvm.RandomBasePkg.all ;
  64. use osvvm.SortListPkg_int.all ;
  65. use std.textio.all ;
  66. library ieee ;
  67. use ieee.std_logic_1164.all ;
  68. use ieee.numeric_std.all ;
  69. use ieee.math_real.all ;
  70. -- comment out following 3 lines with VHDL-2008. Leave in for VHDL-2002
  71. library ieee_proposed ; -- remove with VHDL-2008
  72. use ieee_proposed.standard_additions.all ; -- remove with VHDL-2008
  73. use ieee_proposed.standard_textio_additions.all ; -- remove with VHDL-2008
  74. package RandomPkg is
  75. -- Uncomment the following with VHDL-2008 package generics.
  76. -- For now they are defined in the package RandomBasePkg.vhd
  77. -- package RandomGenericPkg is
  78. -- generic (
  79. -- type RandomSeedType ; -- base type for randomization
  80. -- procedure Uniform (Result : out real ; Seed : inout RandomSeedType) ;
  81. -- function GenRandSeed(IV : integer_vector) return RandomSeedType ;
  82. -- function GenRandSeed(I : integer) return RandomSeedType ;
  83. -- function GenRandSeed(S : string) return RandomSeedType ;
  84. -- ) ;
  85. constant NULL_INTV : integer_vector (0 downto 1) := (others => 0);
  86. -- Supports DistValInt functionality
  87. type DistRecType is record
  88. Value : integer ;
  89. Weight : integer ;
  90. end record ;
  91. type DistType is array (natural range <>) of DistRecType ;
  92. -- Parameters for randomization
  93. -- RandomDistType specifies the distribution to use for randomize
  94. type RandomDistType is (NONE, UNIFORM, FAVOR_SMALL, FAVOR_BIG, NORMAL, POISSON) ;
  95. type RandomParmType is record
  96. Distribution : RandomDistType ;
  97. Mean : Real ; -- also used as probability of success
  98. StdDeviation : Real ; -- also used as number of trials for binomial
  99. end record ;
  100. -- RandomParm IO
  101. function to_string(A : RandomDistType) return string ;
  102. procedure write(variable L: inout line ; A : RandomDistType ) ;
  103. procedure read(variable L: inout line ; A : out RandomDistType ; good : out boolean ) ;
  104. procedure read(variable L: inout line ; A : out RandomDistType ) ;
  105. function to_string(A : RandomParmType) return string ;
  106. procedure write(variable L: inout line ; A : RandomParmType ) ;
  107. procedure read(variable L: inout line ; A : out RandomParmType ; good : out boolean ) ;
  108. procedure read(variable L: inout line ; A : out RandomParmType ) ;
  109. type RandomPType is protected
  110. -- Seed Manipulation
  111. -- Known ambiguity between InitSeed with string and integer_vector
  112. -- Recommendation, use: RV.InitSeed(RV'instance_path) ;
  113. -- For integer_vector use either: RV.InitSeed(IV => (1,5)) ;
  114. -- or: RV.InitSeed(integer_vector'(1,5)) ;
  115. procedure InitSeed (S : string ) ;
  116. procedure InitSeed (I : integer ) ;
  117. procedure InitSeed (IV : integer_vector ) ;
  118. -- SetSeed & GetSeed: Used to save and restore seed values
  119. procedure SetSeed (RandomSeedIn : RandomSeedType ) ;
  120. impure function GetSeed return RandomSeedType ;
  121. -- SeedRandom = SetSeed & GetSeed for SV compatibility
  122. -- replace with aliases when they work in popular simulators
  123. procedure SeedRandom (RandomSeedIn : RandomSeedType ) ;
  124. impure function SeedRandom return RandomSeedType ;
  125. -- alias SeedRandom is SetSeed [RandomSeedType] ;
  126. -- alias SeedRandom is GetSeed [return RandomSeedType] ;
  127. -- Setting Randomization Parameters
  128. -- Allows RandInt to have distributions other than uniform
  129. procedure SetRandomParm (RandomParmIn : RandomParmType) ;
  130. procedure SetRandomParm (
  131. Distribution : RandomDistType ;
  132. Mean : Real := 0.0 ;
  133. Deviation : Real := 0.0
  134. ) ;
  135. impure function GetRandomParm return RandomParmType ;
  136. impure function GetRandomParm return RandomDistType ;
  137. -- For compatibility with previous version - replace with alias
  138. procedure SetRandomMode (RandomDistIn : RandomDistType) ;
  139. -- alias SetRandomMode is SetRandomParm [RandomDistType, Real, Real] ;
  140. -- Base Randomization Distributions
  141. -- Uniform: Generate a random number with a Uniform distribution
  142. impure function Uniform (Min, Max : in real) return real ;
  143. impure function Uniform (Min, Max : integer) return integer ;
  144. impure function Uniform (Min, Max : integer ; Exclude: integer_vector) return integer ;
  145. -- Favor_small
  146. -- Generate random numbers with a greater number of small
  147. -- values than large values
  148. impure function Favor_small (Min, Max : real) return real ;
  149. impure function Favor_small (Min, Max : integer) return integer ;
  150. impure function Favor_small (Min, Max : integer ; Exclude: integer_vector) return integer ;
  151. -- Favor_big
  152. -- Generate random numbers with a greater number of large
  153. -- values than small values
  154. impure function Favor_big (Min, Max : real) return real ;
  155. impure function Favor_big (Min, Max : integer) return integer ;
  156. impure function Favor_big (Min, Max : integer ; Exclude: integer_vector) return integer ;
  157. -- Normal: Generate a random number with a normal distribution
  158. impure function Normal (Mean, StdDeviation : real) return real ;
  159. -- Normal + RandomVal >= Min and RandomVal < Max
  160. impure function Normal (Mean, StdDeviation, Min, Max : real) return real ;
  161. impure function Normal (
  162. Mean : real ;
  163. StdDeviation : real ;
  164. Min : integer ;
  165. Max : integer ;
  166. Exclude : integer_vector := NULL_INTV
  167. ) return integer ;
  168. -- Poisson: Generate a random number with a poisson distribution
  169. -- Discrete distribution = only generates integral values
  170. impure function Poisson (Mean : real) return real ;
  171. -- Poisson + RandomVal >= Min and RandomVal < Max
  172. impure function Poisson (Mean, Min, Max : real) return real ;
  173. impure function Poisson (
  174. Mean : real ;
  175. Min : integer ;
  176. Max : integer ;
  177. Exclude : integer_vector := NULL_INTV
  178. ) return integer ;
  179. -- real randomization with a range
  180. impure function RandReal(Min, Max: Real) return real ;
  181. -- integer randomization with a range
  182. impure function RandInt (Min, Max : integer) return integer ;
  183. impure function RandSlv (Min, Max, Size : natural) return std_logic_vector ;
  184. impure function RandUnsigned (Min, Max, Size : natural) return Unsigned ;
  185. impure function RandSigned (Min, Max : integer; Size : natural ) return Signed ;
  186. -- integer randomization with a range and exclude vector
  187. impure function RandInt (Min, Max : integer; Exclude: integer_vector ) return integer ;
  188. impure function RandSlv (Min, Max : natural; Exclude: integer_vector; Size : natural ) return std_logic_vector ;
  189. impure function RandUnsigned (Min, Max : natural; Exclude: integer_vector ; Size : natural ) return Unsigned ;
  190. impure function RandSigned (Min, Max : integer; Exclude: integer_vector ; Size : natural ) return Signed ;
  191. -- Randomly select a value within a set of values
  192. impure function RandInt ( A : integer_vector ) return integer ;
  193. impure function RandSlv (A : integer_vector ; Size : natural) return std_logic_vector ;
  194. impure function RandUnsigned (A : integer_vector ; Size : natural) return Unsigned ;
  195. impure function RandSigned (A : integer_vector ; Size : natural ) return Signed ;
  196. -- Randomly select a value within a set of values with exclude values (so can skip last or last n)
  197. impure function RandInt ( A : integer_vector; Exclude: integer_vector ) return integer ;
  198. impure function RandSlv (A : integer_vector; Exclude: integer_vector; Size : natural) return std_logic_vector ;
  199. impure function RandUnsigned (A : integer_vector; Exclude: integer_vector ; Size : natural) return Unsigned ;
  200. impure function RandSigned (A : integer_vector; Exclude: integer_vector ; Size : natural ) return Signed ;
  201. -- Randomly select between 0 and N-1 based on the specified weight.
  202. -- where N = number values in weight array
  203. impure function DistInt ( Weight : integer_vector ) return integer ;
  204. impure function DistSlv ( Weight : integer_vector ; Size : natural ) return std_logic_vector ;
  205. impure function DistUnsigned ( Weight : integer_vector ; Size : natural ) return unsigned ;
  206. impure function DistSigned ( Weight : integer_vector ; Size : natural ) return signed ;
  207. -- Distribution with just weights and with exclude values
  208. impure function DistInt ( Weight : integer_vector; Exclude: integer_vector ) return integer ;
  209. impure function DistSlv ( Weight : integer_vector; Exclude: integer_vector; Size : natural ) return std_logic_vector ;
  210. impure function DistUnsigned ( Weight : integer_vector; Exclude: integer_vector; Size : natural ) return unsigned ;
  211. impure function DistSigned ( Weight : integer_vector; Exclude: integer_vector; Size : natural ) return signed ;
  212. -- Distribution with weight and value
  213. impure function DistValInt ( A : DistType ) return integer ;
  214. impure function DistValSlv ( A : DistType ; Size : natural) return std_logic_vector ;
  215. impure function DistValUnsigned ( A : DistType ; Size : natural) return unsigned ;
  216. impure function DistValSigned ( A : DistType ; Size : natural) return signed ;
  217. -- Distribution with weight and value and with exclude values
  218. impure function DistValInt ( A : DistType; Exclude: integer_vector ) return integer ;
  219. impure function DistValSlv ( A : DistType; Exclude: integer_vector; Size : natural) return std_logic_vector ;
  220. impure function DistValUnsigned ( A : DistType; Exclude: integer_vector; Size : natural) return unsigned ;
  221. impure function DistValSigned ( A : DistType; Exclude: integer_vector; Size : natural) return signed ;
  222. -- Convenience Functions
  223. impure function RandReal return real ; -- 0.0 to 1.0
  224. impure function RandReal(Max: Real) return real ; -- 0.0 to Max
  225. impure function RandInt (Max : integer) return integer ;
  226. impure function RandSlv (Size : natural) return std_logic_vector ;
  227. impure function RandSlv (Max, Size : natural) return std_logic_vector ;
  228. impure function RandUnsigned (Size : natural) return Unsigned ;
  229. impure function RandUnsigned (Max, Size : natural) return Unsigned ;
  230. impure function RandSigned (Size : natural) return Signed ;
  231. impure function RandSigned (Max : integer; Size : natural ) return Signed ;
  232. end protected RandomPType ;
  233. end RandomPkg ;
  234. -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  235. -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  236. package body RandomPkg is
  237. -----------------------------------------------------------------
  238. -- Local Randomization Support
  239. -----------------------------------------------------------------
  240. -----------------------------------------------------------------
  241. -- Scale -- Scale a value to be within a given range
  242. --
  243. function Scale (A, Min, Max : real) return real is
  244. variable ValRange : Real ;
  245. begin
  246. assert (Max >= Min) report "%%RandomPkg Error: Max < Min" severity FAILURE ;
  247. ValRange := Max - Min ;
  248. return A * ValRange + Min ;
  249. end function Scale ;
  250. function Scale (A : real ; Min, Max : integer) return integer is
  251. variable ValRange : real ;
  252. variable rMin, rMax : real ;
  253. begin
  254. assert (Max >= Min) report "%%RandomPkg Error: Max < Min" severity FAILURE ;
  255. rMin := real(Min) - 0.5 ;
  256. rMax := real(Max) + 0.5 ;
  257. ValRange := rMax - rMin ;
  258. return integer(round(A * ValRange + rMin)) ;
  259. end function Scale ;
  260. -- create more smaller values
  261. function favor_small (A : real) return real is
  262. begin
  263. return 1.0 - sqrt(A) ;
  264. end favor_small ;
  265. -- create more larger values
  266. -- alias favor_big is sqrt[real return real] ;
  267. function favor_big (A : real) return real is
  268. begin
  269. return sqrt(A) ;
  270. end favor_big ;
  271. -----------------------------------------------------------------
  272. -- RandomParmType IO
  273. -----------------------------------------------------------------
  274. -----------------------------------------------------------------
  275. function to_string(A : RandomDistType) return string is
  276. begin
  277. return RandomDistType'image(A) ;
  278. end function to_string ;
  279. -----------------------------------------------------------------
  280. procedure write(variable L: inout line ; A : RandomDistType ) is
  281. begin
  282. write(L, to_string(A)) ;
  283. end procedure write ;
  284. -----------------------------------------------------------------
  285. procedure read(variable L: inout line ; A : out RandomDistType ; good : out boolean ) is
  286. variable strval : string(1 to 40) ;
  287. variable len : natural ;
  288. begin
  289. -- procedure SREAD (L: inout LINE; VALUE: out STRING; STRLEN: out NATURAL);
  290. sread(L, strval, len) ;
  291. A := RandomDistType'value(strval(1 to len)) ;
  292. good := len > 0 ;
  293. end procedure read ;
  294. -----------------------------------------------------------------
  295. procedure read(variable L: inout line ; A : out RandomDistType ) is
  296. variable good : boolean ;
  297. begin
  298. read(L, A, good) ;
  299. assert good report "read[line, RandomDistType] failed" severity error ;
  300. end procedure read ;
  301. -----------------------------------------------------------------
  302. function to_string(A : RandomParmType) return string is
  303. begin
  304. return RandomDistType'image(A.Distribution) & " " &
  305. to_string(A.Mean, 2) & " " & to_string(A.StdDeviation, 2) ;
  306. end function to_string ;
  307. -----------------------------------------------------------------
  308. procedure write(variable L: inout line ; A : RandomParmType ) is
  309. begin
  310. write(L, to_string(A)) ;
  311. end procedure write ;
  312. -----------------------------------------------------------------
  313. procedure read(variable L: inout line ; A : out RandomParmType ; good : out boolean ) is
  314. variable strval : string(1 to 40) ;
  315. variable len : natural ;
  316. variable igood : boolean ;
  317. begin
  318. loop
  319. -- procedure SREAD (L: inout LINE; VALUE: out STRING; STRLEN: out NATURAL);
  320. sread(L, strval, len) ;
  321. A.Distribution := RandomDistType'value(strval(1 to len)) ;
  322. igood := len > 0 ;
  323. exit when not igood ;
  324. read(L, A.Mean, igood) ;
  325. exit when not igood ;
  326. read(L, A.StdDeviation, igood) ;
  327. exit ;
  328. end loop ;
  329. good := igood ;
  330. end procedure read ;
  331. -----------------------------------------------------------------
  332. procedure read(variable L: inout line ; A : out RandomParmType ) is
  333. variable good : boolean ;
  334. begin
  335. read(L, A, good) ;
  336. assert good report "read[line, RandomParmType] failed" severity error ;
  337. end procedure read ;
  338. -----------------------------------------------------------------
  339. -----------------------------------------------------------------
  340. type RandomPType is protected body
  341. --
  342. -- RandomSeed manipulation
  343. --
  344. variable RandomSeed : RandomSeedType := GenRandSeed(integer_vector'(1,7)) ;
  345. procedure InitSeed (S : string ) is
  346. begin
  347. RandomSeed := GenRandSeed(S) ;
  348. end procedure InitSeed ;
  349. procedure InitSeed (I : integer ) is
  350. begin
  351. RandomSeed := GenRandSeed(I) ;
  352. end procedure InitSeed ;
  353. procedure InitSeed (IV : integer_vector ) is
  354. begin
  355. RandomSeed := GenRandSeed(IV) ;
  356. end procedure InitSeed ;
  357. procedure SetSeed (RandomSeedIn : RandomSeedType ) is
  358. begin
  359. RandomSeed := RandomSeedIn ;
  360. end procedure SetSeed ;
  361. procedure SeedRandom (RandomSeedIn : RandomSeedType ) is
  362. begin
  363. RandomSeed := RandomSeedIn ;
  364. end procedure SeedRandom ;
  365. impure function GetSeed return RandomSeedType is
  366. begin
  367. return RandomSeed ;
  368. end function GetSeed ;
  369. impure function SeedRandom return RandomSeedType is
  370. begin
  371. return RandomSeed ;
  372. end function SeedRandom ;
  373. --
  374. -- randomization mode
  375. --
  376. variable RandomParm : RandomParmType ; -- left most values ok for init
  377. procedure SetRandomParm (RandomParmIn : RandomParmType) is
  378. begin
  379. RandomParm := RandomParmIn ;
  380. end procedure SetRandomParm ;
  381. procedure SetRandomParm (
  382. Distribution : RandomDistType ;
  383. Mean : Real := 0.0 ;
  384. Deviation : Real := 0.0
  385. ) is
  386. begin
  387. RandomParm := RandomParmType'(Distribution, Mean, Deviation) ;
  388. end procedure SetRandomParm ;
  389. impure function GetRandomParm return RandomParmType is
  390. begin
  391. return RandomParm ;
  392. end function GetRandomParm ;
  393. impure function GetRandomParm return RandomDistType is
  394. begin
  395. return RandomParm.Distribution ;
  396. end function GetRandomParm ;
  397. -- For compatibility with previous version
  398. procedure SetRandomMode (RandomDistIn : RandomDistType) is
  399. begin
  400. SetRandomParm(RandomDistIn);
  401. end procedure SetRandomMode ;
  402. --
  403. -- Base Randomization Distributions
  404. --
  405. --
  406. -- Uniform: Generate a random number with a Uniform distribution
  407. --
  408. impure function Uniform (Min, Max : in real) return real is
  409. variable rRandomVal : real ;
  410. begin
  411. Uniform(rRandomVal, RandomSeed) ;
  412. return scale(rRandomVal, Min, Max) ;
  413. end function Uniform ;
  414. impure function Uniform (Min, Max : integer) return integer is
  415. variable rRandomVal : real ;
  416. begin
  417. Uniform(rRandomVal, RandomSeed) ;
  418. return scale(rRandomVal, Min, Max) ;
  419. end function Uniform ;
  420. impure function Uniform (Min, Max : integer ; Exclude: integer_vector) return integer is
  421. variable iRandomVal : integer ;
  422. variable ExcludeList : SortListPType ;
  423. variable count : integer ;
  424. begin
  425. ExcludeList.add(Exclude, Min, Max) ;
  426. count := ExcludeList.count ;
  427. iRandomVal := Uniform(Min, Max - count) ;
  428. -- adjust count, note iRandomVal changes while checking.
  429. for i in 1 to count loop
  430. exit when iRandomVal < ExcludeList.Get(i) ;
  431. iRandomVal := iRandomVal + 1 ;
  432. end loop ;
  433. ExcludeList.erase ;
  434. return iRandomVal ;
  435. end function Uniform ;
  436. --
  437. -- Favor_small
  438. -- Generate random numbers with a greater number of small
  439. -- values than large values
  440. --
  441. impure function Favor_small (Min, Max : real) return real is
  442. variable rRandomVal : real ;
  443. begin
  444. Uniform(rRandomVal, RandomSeed) ;
  445. return scale(favor_small(rRandomVal), Min, Max) ; -- real
  446. end function Favor_small ;
  447. impure function Favor_small (Min, Max : integer) return integer is
  448. variable rRandomVal : real ;
  449. begin
  450. Uniform(rRandomVal, RandomSeed) ;
  451. return scale(favor_small(rRandomVal), Min, Max) ; -- integer
  452. end function Favor_small ;
  453. impure function Favor_small (Min, Max : integer ; Exclude: integer_vector) return integer is
  454. variable iRandomVal : integer ;
  455. variable ExcludeList : SortListPType ;
  456. variable count : integer ;
  457. begin
  458. ExcludeList.add(Exclude, Min, Max) ;
  459. count := ExcludeList.count ;
  460. iRandomVal := Favor_small(Min, Max - count) ;
  461. -- adjust count, note iRandomVal changes while checking.
  462. for i in 1 to count loop
  463. exit when iRandomVal < ExcludeList.Get(i) ;
  464. iRandomVal := iRandomVal + 1 ;
  465. end loop ;
  466. ExcludeList.erase ;
  467. return iRandomVal ;
  468. end function Favor_small ;
  469. --
  470. -- Favor_big
  471. -- Generate random numbers with a greater number of large
  472. -- values than small values
  473. --
  474. impure function Favor_big (Min, Max : real) return real is
  475. variable rRandomVal : real ;
  476. begin
  477. Uniform(rRandomVal, RandomSeed) ;
  478. return scale(favor_big(rRandomVal), Min, Max) ; -- real
  479. end function Favor_big ;
  480. impure function Favor_big (Min, Max : integer) return integer is
  481. variable rRandomVal : real ;
  482. begin
  483. Uniform(rRandomVal, RandomSeed) ;
  484. return scale(favor_big(rRandomVal), Min, Max) ; -- integer
  485. end function Favor_big ;
  486. impure function Favor_big (Min, Max : integer ; Exclude: integer_vector) return integer is
  487. variable iRandomVal : integer ;
  488. variable ExcludeList : SortListPType ;
  489. variable count : integer ;
  490. begin
  491. ExcludeList.add(Exclude, Min, Max) ;
  492. count := ExcludeList.count ;
  493. iRandomVal := Favor_big(Min, Max - count) ;
  494. -- adjust count, note iRandomVal changes while checking.
  495. for i in 1 to count loop
  496. exit when iRandomVal < ExcludeList.Get(i) ;
  497. iRandomVal := iRandomVal + 1 ;
  498. end loop ;
  499. ExcludeList.erase ;
  500. return iRandomVal ;
  501. end function Favor_big ;
  502. -----------------------------------------------------------------
  503. -- Normal
  504. -- Generate a random number with a normal distribution
  505. --
  506. -- Use Box Muller, per Wikipedia:
  507. -- http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
  508. --
  509. -- Use polar method, per Wikipedia:
  510. -- http://en.wikipedia.org/wiki/Marsaglia_polar_method
  511. --
  512. impure function Normal (Mean, StdDeviation : real) return real is
  513. variable x01, y01 : real ;
  514. variable StdNormalDist : real ; -- mean 0, variance 1
  515. begin
  516. -- add this check to set parameters?
  517. if StdDeviation < 0.0 then
  518. report "standard deviation must be >= 0.0" severity failure ;
  519. return -1.0 ;
  520. end if ;
  521. -- Box Muller
  522. Uniform (x01, RandomSeed) ;
  523. Uniform (y01, RandomSeed) ;
  524. StdNormalDist := sqrt(-2.0 * log(x01)) * cos(math_2_pi*y01) ;
  525. -- Polar form rejected due to mean 50.0, std deviation = 5 resulted
  526. -- in a median of 49
  527. -- -- find two Uniform distributed values with range -1 to 1
  528. -- -- that satisify S = X **2 + Y**2 < 1.0
  529. -- loop
  530. -- Uniform (x01, RandomSeed) ;
  531. -- Uniform (y01, RandomSeed) ;
  532. -- x := 2.0 * x01 - 1.0 ; -- scale to -1 to 1
  533. -- y := 2.0 * y01 - 1.0 ;
  534. -- s := x*x + y*y ;
  535. -- exit when s < 1.0 and s > 0.0 ;
  536. -- end loop ;
  537. -- -- Calculate Standard Normal Distribution
  538. -- StdNormalDist := x * sqrt((-2.0 * log(s)) / s) ;
  539. -- Convert to have Mean and StdDeviation
  540. return StdDeviation * StdNormalDist + Mean ;
  541. end function Normal ;
  542. -- Normal + RandomVal >= Min and RandomVal <= Max
  543. impure function Normal (Mean, StdDeviation, Min, Max : real) return real is
  544. variable rRandomVal : real ;
  545. begin
  546. loop
  547. rRandomVal := Normal (Mean, StdDeviation) ;
  548. exit when rRandomVal >= Min and rRandomVal <= Max ;
  549. end loop ;
  550. return rRandomVal ;
  551. end function Normal ;
  552. -- Normal + RandomVal >= Min and RandomVal <= Max
  553. impure function Normal (
  554. Mean : real ;
  555. StdDeviation : real ;
  556. Min : integer ;
  557. Max : integer ;
  558. Exclude : integer_vector := NULL_INTV
  559. ) return integer is
  560. variable iRandomVal : integer ;
  561. begin
  562. loop
  563. iRandomVal := integer(round( Normal(Mean, StdDeviation) )) ;
  564. exit when iRandomVal >= Min and iRandomVal <= Max and
  565. not inside(iRandomVal, Exclude) ;
  566. end loop ;
  567. return iRandomVal ;
  568. end function Normal ;
  569. -----------------------------------------------------------------
  570. -- Poisson
  571. -- Generate a random number with a poisson distribution
  572. -- Discrete distribution = only generates integral values
  573. --
  574. -- Use knuth method, per Wikipedia:
  575. -- http://en.wikipedia.org/wiki/Poisson_distribution
  576. --
  577. impure function Poisson (Mean : real) return real is
  578. variable Product : Real := 1.0;
  579. variable Bound : Real := 0.0;
  580. variable UniformRand : Real := 0.0 ;
  581. variable PoissonRand : Real := 0.0 ;
  582. begin
  583. Bound := exp(-1.0 * Mean);
  584. Product := 1.0 ;
  585. -- add this check to set parameters?
  586. if Mean <= 0.0 or Bound <= 0.0 then
  587. report "Poisson: Mean < 0 or too large. Mean = " & real'image(Mean) severity failure ;
  588. return -1.0 ;
  589. end if ;
  590. while (Product >= Bound) loop
  591. PoissonRand := PoissonRand + 1.0;
  592. Uniform(UniformRand, RandomSeed) ;
  593. Product := Product * UniformRand;
  594. end loop;
  595. return PoissonRand ;
  596. end function Poisson ; -- no range
  597. -- Poisson + RandomVal >= Min and RandomVal < Max
  598. impure function Poisson (Mean, Min, Max : real) return real is
  599. variable rRandomVal : real ;
  600. begin
  601. loop
  602. rRandomVal := Poisson (Mean) ;
  603. exit when rRandomVal >= Min and rRandomVal <= Max ;
  604. end loop ;
  605. return rRandomVal ;
  606. end function Poisson ;
  607. impure function Poisson (
  608. Mean : real ;
  609. Min : integer ;
  610. Max : integer ;
  611. Exclude : integer_vector := NULL_INTV
  612. ) return integer is
  613. variable iRandomVal : integer ;
  614. begin
  615. loop
  616. iRandomVal := integer(round( Poisson (Mean) )) ;
  617. exit when iRandomVal >= Min and iRandomVal <= Max and
  618. not inside(iRandomVal, Exclude) ;
  619. end loop ;
  620. return iRandomVal ;
  621. end function Poisson ;
  622. --
  623. -- real randomization with a range
  624. -- Distribution determined by RandomParm
  625. --
  626. impure function RandReal(Min, Max: Real) return real is
  627. begin
  628. assert Max >= Min report "RandReal: Range Error" severity FAILURE ;
  629. case RandomParm.Distribution is
  630. when NONE | UNIFORM => return Uniform(Min, Max) ;
  631. when FAVOR_SMALL => return Favor_small(Min, Max) ;
  632. when FAVOR_BIG => return Favor_big (Min, Max) ;
  633. when NORMAL => return Normal(RandomParm.Mean, RandomParm.StdDeviation, Min, Max) ;
  634. when POISSON => return Poisson(RandomParm.Mean, Min, Max) ;
  635. when others =>
  636. report "RandomPkg: distribution not implemented" severity failure ;
  637. return real(integer'low) ;
  638. end case ;
  639. end function RandReal ;
  640. --
  641. -- integer randomization with a range
  642. -- Distribution determined by RandomParm
  643. --
  644. impure function RandInt (Min, Max : integer) return integer is
  645. begin
  646. assert (Max >= Min) report "RandInt: Range Error" severity FAILURE ;
  647. case RandomParm.Distribution is
  648. when NONE | UNIFORM => return Uniform(Min, Max) ;
  649. when FAVOR_SMALL => return Favor_small(Min, Max) ;
  650. when FAVOR_BIG => return Favor_big (Min, Max) ;
  651. when NORMAL => return Normal(RandomParm.Mean, RandomParm.StdDeviation, Min, Max) ;
  652. when POISSON => return Poisson(RandomParm.Mean, Min, Max) ;
  653. when others =>
  654. report "RandomPkg: distribution not implemented" severity failure ;
  655. return integer'low ;
  656. end case ;
  657. end function RandInt ;
  658. impure function RandSlv (Min, Max, Size : natural) return std_logic_vector is
  659. begin
  660. return std_logic_vector(to_unsigned(RandInt(Min, Max), Size)) ;
  661. end function RandSlv ;
  662. impure function RandUnsigned (Min, Max, Size : natural) return Unsigned is
  663. begin
  664. return to_unsigned(RandInt(Min, Max), Size) ;
  665. end function RandUnsigned ;
  666. impure function RandSigned (Min, Max : integer; Size : natural ) return Signed is
  667. begin
  668. return to_signed(RandInt(Min, Max), Size) ;
  669. end function RandSigned ;
  670. --
  671. -- integer randomization with a range and exclude vector
  672. -- Distribution determined by RandomParm
  673. --
  674. impure function RandInt (Min, Max : integer; Exclude: integer_vector ) return integer is
  675. variable iRandomVal : integer ;
  676. begin
  677. assert (Max >= Min) report "RandInt: Range Error" severity FAILURE ;
  678. case RandomParm.Distribution is
  679. when NONE | UNIFORM => return Uniform(Min, Max, Exclude) ;
  680. when FAVOR_SMALL => return Favor_small(Min, Max, Exclude) ;
  681. when FAVOR_BIG => return Favor_big (Min, Max, Exclude) ;
  682. when NORMAL => return Normal(RandomParm.Mean, RandomParm.StdDeviation, Min, Max, Exclude) ;
  683. when POISSON => return Poisson(RandomParm.Mean, Min, Max, Exclude) ;
  684. when others =>
  685. report "RandomPkg: distribution not implemented" severity failure ;
  686. return integer'low ;
  687. end case ;
  688. end function RandInt ;
  689. impure function RandSlv (Min, Max : natural; Exclude: integer_vector; Size : natural ) return std_logic_vector is
  690. begin
  691. return std_logic_vector(to_unsigned(RandInt(Min, Max, Exclude), Size)) ;
  692. end function RandSlv ;
  693. impure function RandUnsigned (Min, Max : natural; Exclude: integer_vector; Size : natural ) return Unsigned is
  694. begin
  695. return to_unsigned(RandInt(Min, Max, Exclude), Size) ;
  696. end function RandUnsigned ;
  697. impure function RandSigned (Min, Max : integer; Exclude: integer_vector; Size : natural ) return Signed is
  698. begin
  699. return to_signed(RandInt(Min, Max, Exclude), Size) ;
  700. end function RandSigned ;
  701. --
  702. -- Randomly select a value within a set of values
  703. -- Distribution determined by RandomParm
  704. --
  705. impure function RandInt ( A : integer_vector ) return integer is
  706. alias A_norm : integer_vector(1 to A'length) is A ;
  707. begin
  708. return A_norm( RandInt(1, A'length) ) ;
  709. end function RandInt ;
  710. impure function RandSlv (A : integer_vector ; Size : natural) return std_logic_vector is
  711. begin
  712. return std_logic_vector(to_unsigned(RandInt(A), Size)) ;
  713. end function RandSlv ;
  714. impure function RandUnsigned (A : integer_vector ; Size : natural) return Unsigned is
  715. begin
  716. return to_unsigned(RandInt(A), Size) ;
  717. end function RandUnsigned ;
  718. impure function RandSigned (A : integer_vector ; Size : natural ) return Signed is
  719. begin
  720. return to_signed(RandInt(A), Size) ;
  721. end function RandSigned ;
  722. --
  723. -- Randomly select a value within a set of values with exclude values (so can skip last or last n)
  724. -- Distribution determined by RandomParm
  725. --
  726. impure function RandInt ( A : integer_vector; Exclude: integer_vector ) return integer is
  727. alias A_norm : integer_vector(1 to A'length) is A ;
  728. variable ExcludeIndexList : SortListPType ;
  729. variable iVal : integer ;
  730. begin
  731. -- convert exclude list into indices of A_norm to exclude
  732. -- necessary to preserve ordering of the distribution (such as NORMAL)
  733. for i in A_norm'range loop
  734. if inside(A_norm(i), Exclude) then
  735. ExcludeIndexList.add(i) ;
  736. end if ;
  737. end loop ;
  738. -- Randomize an index into A_Norm with exclude index list
  739. iVal := RandInt(1, A'length, ExcludeIndexList.to_array (EraseList => TRUE)) ;
  740. -- return the value at the randomized index
  741. return A_norm(iVal) ;
  742. end function RandInt ;
  743. impure function RandSlv (A : integer_vector; Exclude: integer_vector; Size : natural) return std_logic_vector is
  744. begin
  745. return std_logic_vector(to_unsigned(RandInt(A, Exclude), Size)) ;
  746. end function RandSlv ;
  747. impure function RandUnsigned (A : integer_vector; Exclude: integer_vector; Size : natural) return Unsigned is
  748. begin
  749. return to_unsigned(RandInt(A, Exclude), Size) ;
  750. end function RandUnsigned ;
  751. impure function RandSigned (A : integer_vector; Exclude: integer_vector; Size : natural ) return Signed is
  752. begin
  753. return to_signed(RandInt(A, Exclude), Size) ;
  754. end function RandSigned ;
  755. --
  756. -- Basic Discrete Distributions
  757. -- Always uses Uniform
  758. --
  759. impure function DistInt ( Weight : integer_vector ) return integer is
  760. variable DistArray : integer_vector(0 to Weight'length-1) ;
  761. variable sum : integer ;
  762. variable iRandomVal : integer ;
  763. begin
  764. DistArray := Weight ;
  765. for i in 1 to DistArray'right loop
  766. DistArray(i) := DistArray(i) + DistArray(i-1) ;
  767. end loop ;
  768. sum := DistArray(DistArray'right) ;
  769. assert sum >= 1 report "DistInt failed: no elements" severity failure ;
  770. iRandomVal := Uniform(1, sum) ;
  771. for i in DistArray'range loop
  772. if iRandomVal <= DistArray(i) then
  773. return i ;
  774. end if;
  775. end loop ;
  776. return integer'left ; -- can't get here
  777. end function DistInt ;
  778. impure function DistSlv ( Weight : integer_vector ; Size : natural ) return std_logic_vector is
  779. begin
  780. return std_logic_vector(to_unsigned(DistInt(Weight), Size)) ;
  781. end function DistSlv ;
  782. impure function DistUnsigned ( Weight : integer_vector ; Size : natural ) return unsigned is
  783. begin
  784. return to_unsigned(DistInt(Weight), Size) ;
  785. end function DistUnsigned ;
  786. impure function DistSigned ( Weight : integer_vector ; Size : natural ) return signed is
  787. begin
  788. return to_signed(DistInt(Weight), Size) ;
  789. end function DistSigned ;
  790. --
  791. -- Basic Distributions with exclude values (so can skip last or last n)
  792. -- Always uses Uniform via DistInt
  793. --
  794. impure function DistInt ( Weight : integer_vector; Exclude: integer_vector ) return integer is
  795. variable DistArray : integer_vector(0 to Weight'length-1) ;
  796. variable ExcludeTemp : integer ;
  797. begin
  798. DistArray := Weight ;
  799. for i in Exclude'range loop
  800. ExcludeTemp := Exclude(i) ;
  801. if ExcludeTemp >= 0 and ExcludeTemp <= Weight'length-1 then
  802. DistArray(ExcludeTemp) := 0 ;
  803. end if ;
  804. end loop ;
  805. return DistInt(DistArray) ;
  806. end function DistInt ;
  807. impure function DistSlv ( Weight : integer_vector; Exclude: integer_vector; Size : natural ) return std_logic_vector is
  808. begin
  809. return std_logic_vector(to_unsigned(DistInt(Weight, Exclude), Size)) ;
  810. end function DistSlv ;
  811. impure function DistUnsigned ( Weight : integer_vector; Exclude: integer_vector; Size : natural ) return unsigned is
  812. begin
  813. return to_unsigned(DistInt(Weight, Exclude), Size) ;
  814. end function DistUnsigned ;
  815. impure function DistSigned ( Weight : integer_vector; Exclude: integer_vector; Size : natural ) return signed is
  816. begin
  817. return to_signed(DistInt(Weight, Exclude), Size) ;
  818. end function DistSigned ;
  819. --
  820. -- Distribution for sparse values
  821. -- Always uses Uniform via DistInt
  822. --
  823. impure function DistValInt ( A : DistType ) return integer is
  824. variable DistArray : integer_vector(0 to A'length -1) ;
  825. alias DistRecArray : DistType(DistArray'range) is A;
  826. begin
  827. for i in DistArray'range loop
  828. DistArray(i) := DistRecArray(i).Weight ;
  829. end loop ;
  830. return DistRecArray(DistInt(DistArray)).Value ;
  831. end function DistValInt ;
  832. impure function DistValSlv ( A : DistType ; Size : natural ) return std_logic_vector is
  833. begin
  834. return std_logic_vector(to_unsigned(DistValInt(A), Size)) ;
  835. end function DistValSlv ;
  836. impure function DistValUnsigned ( A : DistType ; Size : natural ) return unsigned is
  837. begin
  838. return to_unsigned(DistValInt(A), Size) ;
  839. end function DistValUnsigned ;
  840. impure function DistValSigned ( A : DistType ; Size : natural ) return signed is
  841. begin
  842. return to_signed(DistValInt(A), Size) ;
  843. end function DistValSigned ;
  844. --
  845. -- Distribution for sparse values with exclude values (so can skip last or last n)
  846. -- Always uses Uniform via DistInt
  847. --
  848. impure function DistValInt ( A : DistType; Exclude: integer_vector ) return integer is
  849. variable DistArray : integer_vector(0 to A'length -1) ;
  850. alias DistRecArray : DistType(DistArray'range) is A;
  851. begin
  852. for i in DistRecArray'range loop
  853. if inside(DistRecArray(i).Value, exclude) then
  854. DistArray(i) := 0 ; -- exclude
  855. else
  856. DistArray(i) := DistRecArray(i).Weight ;
  857. end if;
  858. end loop ;
  859. return DistRecArray(DistInt(DistArray)).Value ;
  860. end function DistValInt ;
  861. impure function DistValSlv ( A : DistType; Exclude: integer_vector; Size : natural ) return std_logic_vector is
  862. begin
  863. return std_logic_vector(to_unsigned(DistValInt(A, Exclude), Size)) ;
  864. end function DistValSlv ;
  865. impure function DistValUnsigned ( A : DistType; Exclude: integer_vector; Size : natural ) return unsigned is
  866. begin
  867. return to_unsigned(DistValInt(A, Exclude), Size) ;
  868. end function DistValUnsigned ;
  869. impure function DistValSigned ( A : DistType; Exclude: integer_vector; Size : natural ) return signed is
  870. begin
  871. return to_signed(DistValInt(A, Exclude), Size) ;
  872. end function DistValSigned ;
  873. --
  874. -- Convenience Functions. Resolve into calls into the other functions
  875. --
  876. impure function RandReal return real is
  877. variable RandomValue : real ;
  878. begin
  879. return RandReal(0.0, 1.0) ;
  880. end function RandReal ;
  881. impure function RandReal(Max: Real) return real is -- 0.0 to Max
  882. begin
  883. return RandReal(0.0, Max) ;
  884. -- assert Max >= 0.0 report "RandReal: Range Error" severity FAILURE ;
  885. -- return RandReal * Max ;
  886. end function RandReal ;
  887. impure function RandInt (Max : integer) return integer is
  888. begin
  889. return RandInt(0, Max) ;
  890. end function RandInt ;
  891. impure function RandSlv (Size : natural) return std_logic_vector is
  892. begin
  893. return std_logic_vector(to_unsigned(RandInt(0, 2**Size-1), Size)) ;
  894. end function RandSlv ;
  895. impure function RandSlv (Max, Size : natural) return std_logic_vector is
  896. begin
  897. return std_logic_vector(to_unsigned(RandInt(0, Max), Size)) ;
  898. end function RandSlv ;
  899. impure function RandUnsigned (Size : natural) return Unsigned is
  900. begin
  901. return to_unsigned(RandInt(0, 2**Size-1), Size) ;
  902. end function RandUnsigned ;
  903. impure function RandUnsigned (Max, Size : natural) return Unsigned is
  904. begin
  905. return to_unsigned(RandInt(0, Max), Size) ;
  906. end function RandUnsigned ;
  907. impure function RandSigned (Size : natural) return Signed is
  908. begin
  909. return to_signed(RandInt(-2**(Size-1), 2**(Size-1)-1), Size) ;
  910. end function RandSigned ;
  911. impure function RandSigned (Max : integer; Size : natural ) return Signed is
  912. begin
  913. -- chose 0 to Max rather than -Max to +Max to be same as RandUnsigned, either seems logical
  914. return to_signed(RandInt(0, Max), Size) ;
  915. end function RandSigned ;
  916. end protected body RandomPType ;
  917. end RandomPkg ;