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.

1646 lines
64 KiB

  1. --
  2. -- File Name : RandomPkg.vhd
  3. -- Design Unit Name : RandomPkg
  4. -- Revision : STANDARD VERSION
  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 SynthWorks' Advanced 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 Major clean-up. Moved RandomParmType and control to here
  37. -- 07/2011 2.1 Bug fix to convenience functions for slv, unsigned, and signed.
  38. -- 06/2012 2.2 Removed '_' in the name of subprograms FavorBig and FavorSmall
  39. -- 04/2013 2013.04 Changed DistInt. Return array indices now match input
  40. -- Better Min, Max error handling in Uniform, FavorBig, FavorSmall, Normal, Poisson
  41. -- 5/2013 - Removed extra variable declaration in functions RandInt and RandReal
  42. -- 5/2013 2013.05 Big vector randomization added overloading RandUnsigned, RandSlv, and RandSigned
  43. -- Added NULL_RANGE_TYPE to minimize null range warnings
  44. -- 1/2014 2014.01 Added RandTime, RandReal(set), RandIntV, RandRealV, RandTimeV
  45. -- Made sort, revsort from SortListPkg_int visible via aliases
  46. -- 1/2015 2015.01 Changed Assert/Report to Alert
  47. -- 5/2015 2015.06 Revised Alerts to Alert(OSVVM_ALERTLOG_ID, ...) ;
  48. -- 11/2016 2016.11 No changes. Updated release numbers to make documentation and
  49. -- package have consistent release identifiers.
  50. --
  51. -- Copyright (c) 2006 - 2016 by SynthWorks Design Inc. All rights reserved.
  52. --
  53. -- Verbatim copies of this source file may be used and
  54. -- distributed without restriction.
  55. --
  56. -- This source file is free software ; you can redistribute it
  57. -- and/or modify it under the terms of the ARTISTIC License
  58. -- as published by The Perl Foundation ; either version 2.0 of
  59. -- the License, or (at your option) any later version.
  60. --
  61. -- This source is distributed in the hope that it will be
  62. -- useful, but WITHOUT ANY WARRANTY ; without even the implied
  63. -- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  64. -- PURPOSE. See the Artistic License for details.
  65. --
  66. -- You should have received a copy of the license with this source.
  67. -- If not download it from,
  68. -- http ://www.perlfoundation.org/artistic_license_2_0
  69. --
  70. use work.OsvvmGlobalPkg.all ;
  71. use work.AlertLogPkg.all ;
  72. use work.RandomBasePkg.all ;
  73. use work.SortListPkg_int.all ;
  74. use std.textio.all ;
  75. library ieee ;
  76. use ieee.std_logic_1164.all ;
  77. use ieee.numeric_std.all ;
  78. use ieee.numeric_std_unsigned.all ;
  79. use ieee.math_real.all ;
  80. -- comment out following 3 lines with VHDL-2008. Leave in for VHDL-2002
  81. -- library ieee_proposed ; -- remove with VHDL-2008
  82. -- use ieee_proposed.standard_additions.all ; -- remove with VHDL-2008
  83. -- use ieee_proposed.standard_textio_additions.all ; -- remove with VHDL-2008
  84. package RandomPkg is
  85. -- Uncomment the following with VHDL-2008 package generics.
  86. -- For now they are defined in the package RandomBasePkg.vhd
  87. -- package RandomGenericPkg is
  88. -- generic (
  89. -- type RandomSeedType ; -- base type for randomization
  90. -- procedure Uniform (Result : out real ; Seed : inout RandomSeedType) ;
  91. -- function GenRandSeed(IV : integer_vector) return RandomSeedType ;
  92. -- function GenRandSeed(I : integer) return RandomSeedType ;
  93. -- function GenRandSeed(S : string) return RandomSeedType ;
  94. -- ) ;
  95. -- make things from SortListPkg_int visible
  96. alias sort is work.SortListPkg_int.sort[integer_vector return integer_vector] ;
  97. alias revsort is work.SortListPkg_int.revsort[integer_vector return integer_vector] ;
  98. -- note NULL_RANGE_TYPE should probably be in std.standard
  99. subtype NULL_RANGE_TYPE is integer range 0 downto 1 ;
  100. constant NULL_INTV : integer_vector (NULL_RANGE_TYPE) := (others => 0) ;
  101. -- Supports DistValInt functionality
  102. type DistRecType is record
  103. Value : integer ;
  104. Weight : integer ;
  105. end record ;
  106. type DistType is array (natural range <>) of DistRecType ;
  107. -- Parameters for randomization
  108. -- RandomDistType specifies the distribution to use for randomize
  109. type RandomDistType is (NONE, UNIFORM, FAVOR_SMALL, FAVOR_BIG, NORMAL, POISSON) ;
  110. type RandomParmType is record
  111. Distribution : RandomDistType ;
  112. Mean : Real ; -- also used as probability of success
  113. StdDeviation : Real ; -- also used as number of trials for binomial
  114. end record ;
  115. -- RandomParm IO
  116. function to_string(A : RandomDistType) return string ;
  117. procedure write(variable L : inout line ; A : RandomDistType ) ;
  118. procedure read(variable L : inout line ; A : out RandomDistType ; good : out boolean ) ;
  119. procedure read(variable L : inout line ; A : out RandomDistType ) ;
  120. function to_string(A : RandomParmType) return string ;
  121. procedure write(variable L : inout line ; A : RandomParmType ) ;
  122. procedure read(variable L : inout line ; A : out RandomParmType ; good : out boolean ) ;
  123. procedure read(variable L : inout line ; A : out RandomParmType ) ;
  124. type RandomPType is protected
  125. -- Seed Manipulation
  126. -- Known ambiguity between InitSeed with string and integer_vector
  127. -- Recommendation, use : RV.InitSeed(RV'instance_path) ;
  128. -- For integer_vector use either : RV.InitSeed(IV => (1,5)) ;
  129. -- or : RV.InitSeed(integer_vector'(1,5)) ;
  130. procedure InitSeed (S : string ) ;
  131. procedure InitSeed (I : integer ) ;
  132. procedure InitSeed (IV : integer_vector ) ;
  133. -- SetSeed & GetSeed : Used to save and restore seed values
  134. procedure SetSeed (RandomSeedIn : RandomSeedType ) ;
  135. impure function GetSeed return RandomSeedType ;
  136. -- SeedRandom = SetSeed & GetSeed for SV compatibility
  137. -- replace with aliases when they work in popular simulators
  138. procedure SeedRandom (RandomSeedIn : RandomSeedType ) ;
  139. impure function SeedRandom return RandomSeedType ;
  140. -- alias SeedRandom is SetSeed [RandomSeedType] ;
  141. -- alias SeedRandom is GetSeed [return RandomSeedType] ;
  142. -- Setting Randomization Parameters
  143. -- Allows RandInt to have distributions other than uniform
  144. procedure SetRandomParm (RandomParmIn : RandomParmType) ;
  145. procedure SetRandomParm (
  146. Distribution : RandomDistType ;
  147. Mean : Real := 0.0 ;
  148. Deviation : Real := 0.0
  149. ) ;
  150. impure function GetRandomParm return RandomParmType ;
  151. impure function GetRandomParm return RandomDistType ;
  152. -- For compatibility with previous version - replace with alias
  153. procedure SetRandomMode (RandomDistIn : RandomDistType) ;
  154. -- alias SetRandomMode is SetRandomParm [RandomDistType, Real, Real] ;
  155. -- Base Randomization Distributions
  156. -- Uniform : Generate a random number with a Uniform distribution
  157. impure function Uniform (Min, Max : in real) return real ;
  158. impure function Uniform (Min, Max : integer) return integer ;
  159. impure function Uniform (Min, Max : integer ; Exclude : integer_vector) return integer ;
  160. -- FavorSmall
  161. -- Generate random numbers with a greater number of small
  162. -- values than large values
  163. impure function FavorSmall (Min, Max : real) return real ;
  164. impure function FavorSmall (Min, Max : integer) return integer ;
  165. impure function FavorSmall (Min, Max : integer ; Exclude : integer_vector) return integer ;
  166. -- FavorBig
  167. -- Generate random numbers with a greater number of large
  168. -- values than small values
  169. impure function FavorBig (Min, Max : real) return real ;
  170. impure function FavorBig (Min, Max : integer) return integer ;
  171. impure function FavorBig (Min, Max : integer ; Exclude : integer_vector) return integer ;
  172. -- Normal : Generate a random number with a normal distribution
  173. impure function Normal (Mean, StdDeviation : real) return real ;
  174. -- Normal + RandomVal >= Min and RandomVal < Max
  175. impure function Normal (Mean, StdDeviation, Min, Max : real) return real ;
  176. impure function Normal (
  177. Mean : real ;
  178. StdDeviation : real ;
  179. Min : integer ;
  180. Max : integer ;
  181. Exclude : integer_vector := NULL_INTV
  182. ) return integer ;
  183. -- Poisson : Generate a random number with a poisson distribution
  184. -- Discrete distribution = only generates integral values
  185. impure function Poisson (Mean : real) return real ;
  186. -- Poisson + RandomVal >= Min and RandomVal < Max
  187. impure function Poisson (Mean, Min, Max : real) return real ;
  188. impure function Poisson (
  189. Mean : real ;
  190. Min : integer ;
  191. Max : integer ;
  192. Exclude : integer_vector := NULL_INTV
  193. ) return integer ;
  194. -- randomization with a range
  195. impure function RandInt (Min, Max : integer) return integer ;
  196. impure function RandReal(Min, Max : Real) return real ;
  197. impure function RandTime (Min, Max : time ; Unit : time := ns) return time ;
  198. impure function RandSlv (Min, Max, Size : natural) return std_logic_vector ;
  199. impure function RandUnsigned (Min, Max, Size : natural) return Unsigned ;
  200. impure function RandSigned (Min, Max : integer ; Size : natural ) return Signed ;
  201. impure function RandIntV (Min, Max : integer ; Size : natural) return integer_vector ;
  202. impure function RandIntV (Min, Max : integer ; Unique : natural ; Size : natural) return integer_vector ;
  203. impure function RandRealV (Min, Max : real ; Size : natural) return real_vector ;
  204. impure function RandTimeV (Min, Max : time ; Size : natural ; Unit : time := ns) return time_vector ;
  205. impure function RandTimeV (Min, Max : time ; Unique : natural ; Size : natural ; Unit : time := ns) return time_vector ;
  206. -- randomization with a range and exclude vector
  207. impure function RandInt (Min, Max : integer ; Exclude : integer_vector ) return integer ;
  208. impure function RandTime (Min, Max : time ; Exclude : time_vector ; Unit : time := ns) return time ;
  209. impure function RandSlv (Min, Max : natural ; Exclude : integer_vector ; Size : natural ) return std_logic_vector ;
  210. impure function RandUnsigned (Min, Max : natural ; Exclude : integer_vector ; Size : natural ) return Unsigned ;
  211. impure function RandSigned (Min, Max : integer ; Exclude : integer_vector ; Size : natural ) return Signed ;
  212. impure function RandIntV (Min, Max : integer ; Exclude : integer_vector ; Size : natural) return integer_vector ;
  213. impure function RandIntV (Min, Max : integer ; Exclude : integer_vector ; Unique : natural ; Size : natural) return integer_vector ;
  214. impure function RandTimeV (Min, Max : time ; Exclude : time_vector ; Size : natural ; Unit : in time := ns) return time_vector ;
  215. impure function RandTimeV (Min, Max : time ; Exclude : time_vector ; Unique : natural ; Size : natural ; Unit : in time := ns) return time_vector ;
  216. -- Randomly select a value within a set of values
  217. impure function RandInt ( A : integer_vector ) return integer ;
  218. impure function RandReal ( A : real_vector ) return real ;
  219. impure function RandTime (A : time_vector) return time ;
  220. impure function RandSlv (A : integer_vector ; Size : natural) return std_logic_vector ;
  221. impure function RandUnsigned (A : integer_vector ; Size : natural) return Unsigned ;
  222. impure function RandSigned (A : integer_vector ; Size : natural ) return Signed ;
  223. impure function RandIntV (A : integer_vector ; Size : natural) return integer_vector ;
  224. impure function RandIntV (A : integer_vector ; Unique : natural ; Size : natural) return integer_vector ;
  225. impure function RandRealV (A : real_vector ; Size : natural) return real_vector ;
  226. impure function RandRealV (A : real_vector ; Unique : natural ; Size : natural) return real_vector ;
  227. impure function RandTimeV (A : time_vector ; Size : natural) return time_vector ;
  228. impure function RandTimeV (A : time_vector ; Unique : natural ; Size : natural) return time_vector ;
  229. -- Randomly select a value within a set of values with exclude values (so can skip last or last n)
  230. impure function RandInt ( A, Exclude : integer_vector ) return integer ;
  231. impure function RandReal ( A, Exclude : real_vector ) return real ;
  232. impure function RandTime (A, Exclude : time_vector) return time ;
  233. impure function RandSlv (A, Exclude : integer_vector ; Size : natural) return std_logic_vector ;
  234. impure function RandUnsigned (A, Exclude : integer_vector ; Size : natural) return Unsigned ;
  235. impure function RandSigned (A, Exclude : integer_vector ; Size : natural ) return Signed ;
  236. impure function RandIntV (A, Exclude : integer_vector ; Size : natural) return integer_vector ;
  237. impure function RandIntV (A, Exclude : integer_vector ; Unique : natural ; Size : natural) return integer_vector ;
  238. impure function RandRealV (A, Exclude : real_vector ; Size : natural) return real_vector ;
  239. impure function RandRealV (A, Exclude : real_vector ; Unique : natural ; Size : natural) return real_vector ;
  240. impure function RandTimeV (A, Exclude : time_vector ; Size : natural) return time_vector ;
  241. impure function RandTimeV (A, Exclude : time_vector ; Unique : natural ; Size : natural) return time_vector ;
  242. -- Randomly select between 0 and N-1 based on the specified weight.
  243. -- where N = number values in weight array
  244. impure function DistInt ( Weight : integer_vector ) return integer ;
  245. impure function DistSlv ( Weight : integer_vector ; Size : natural ) return std_logic_vector ;
  246. impure function DistUnsigned ( Weight : integer_vector ; Size : natural ) return unsigned ;
  247. impure function DistSigned ( Weight : integer_vector ; Size : natural ) return signed ;
  248. -- Distribution with just weights and with exclude values
  249. impure function DistInt ( Weight : integer_vector ; Exclude : integer_vector ) return integer ;
  250. impure function DistSlv ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return std_logic_vector ;
  251. impure function DistUnsigned ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return unsigned ;
  252. impure function DistSigned ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return signed ;
  253. -- Distribution with weight and value
  254. impure function DistValInt ( A : DistType ) return integer ;
  255. impure function DistValSlv ( A : DistType ; Size : natural) return std_logic_vector ;
  256. impure function DistValUnsigned ( A : DistType ; Size : natural) return unsigned ;
  257. impure function DistValSigned ( A : DistType ; Size : natural) return signed ;
  258. -- Distribution with weight and value and with exclude values
  259. impure function DistValInt ( A : DistType ; Exclude : integer_vector ) return integer ;
  260. impure function DistValSlv ( A : DistType ; Exclude : integer_vector ; Size : natural) return std_logic_vector ;
  261. impure function DistValUnsigned ( A : DistType ; Exclude : integer_vector ; Size : natural) return unsigned ;
  262. impure function DistValSigned ( A : DistType ; Exclude : integer_vector ; Size : natural) return signed ;
  263. -- Large vector handling.
  264. impure function RandUnsigned (Size : natural) return unsigned ;
  265. impure function RandSlv (Size : natural) return std_logic_vector ;
  266. impure function RandSigned (Size : natural) return signed ;
  267. impure function RandUnsigned (Max : Unsigned) return unsigned ;
  268. impure function RandSlv (Max : std_logic_vector) return std_logic_vector ;
  269. impure function RandSigned (Max : signed) return signed ;
  270. impure function RandUnsigned (Min, Max : unsigned) return unsigned ;
  271. impure function RandSlv (Min, Max : std_logic_vector) return std_logic_vector ;
  272. impure function RandSigned (Min, Max : signed) return signed ;
  273. -- Convenience Functions
  274. impure function RandReal return real ; -- 0.0 to 1.0
  275. impure function RandReal(Max : Real) return real ; -- 0.0 to Max
  276. impure function RandInt (Max : integer) return integer ;
  277. impure function RandSlv (Max, Size : natural) return std_logic_vector ;
  278. impure function RandUnsigned (Max, Size : natural) return Unsigned ;
  279. impure function RandSigned (Max : integer ; Size : natural ) return Signed ;
  280. end protected RandomPType ;
  281. end RandomPkg ;
  282. --- ///////////////////////////////////////////////////////////////////////////
  283. --- ///////////////////////////////////////////////////////////////////////////
  284. --- ///////////////////////////////////////////////////////////////////////////
  285. package body RandomPkg is
  286. -----------------------------------------------------------------
  287. -- Local Randomization Support
  288. -----------------------------------------------------------------
  289. constant NULL_SLV : std_logic_vector (NULL_RANGE_TYPE) := (others => '0') ;
  290. constant NULL_UV : unsigned (NULL_RANGE_TYPE) := (others => '0') ;
  291. constant NULL_SV : signed (NULL_RANGE_TYPE) := (others => '0') ;
  292. -----------------------------------------------------------------
  293. -- Scale -- Scale a value to be within a given range
  294. --
  295. function Scale (A, Min, Max : real) return real is
  296. variable ValRange : Real ;
  297. begin
  298. if Max >= Min then
  299. ValRange := Max - Min ;
  300. return A * ValRange + Min ;
  301. else
  302. return real'left ;
  303. end if ;
  304. end function Scale ;
  305. function Scale (A : real ; Min, Max : integer) return integer is
  306. variable ValRange : real ;
  307. variable rMin, rMax : real ;
  308. begin
  309. if Max >= Min then
  310. rMin := real(Min) - 0.5 ;
  311. rMax := real(Max) + 0.5 ;
  312. ValRange := rMax - rMin ;
  313. return integer(round(A * ValRange + rMin)) ;
  314. else
  315. return integer'left ;
  316. end if ;
  317. end function Scale ;
  318. -- create more smaller values
  319. function FavorSmall (A : real) return real is
  320. begin
  321. return 1.0 - sqrt(A) ;
  322. end FavorSmall ;
  323. -- create more larger values
  324. -- alias FavorBig is sqrt[real return real] ;
  325. function FavorBig (A : real) return real is
  326. begin
  327. return sqrt(A) ;
  328. end FavorBig ;
  329. -- local.
  330. function to_time_vector (A : integer_vector ; Unit : time) return time_vector is
  331. variable result : time_vector(A'range) ;
  332. begin
  333. for i in A'range loop
  334. result(i) := A(i) * Unit ;
  335. end loop ;
  336. return result ;
  337. end function to_time_vector ;
  338. -- local
  339. function to_integer_vector (A : time_vector ; Unit : time) return integer_vector is
  340. variable result : integer_vector(A'range) ;
  341. begin
  342. for i in A'range loop
  343. result(i) := A(i) / Unit ;
  344. end loop ;
  345. return result ;
  346. end function to_integer_vector ;
  347. -- Local. Remove the exclude list from the list - integer_vector
  348. procedure RemoveExclude(A, Exclude : integer_vector ; variable NewA : out integer_vector ; variable NewALength : inout natural ) is
  349. alias norm_NewA : integer_vector(1 to NewA'length) is NewA ;
  350. begin
  351. NewALength := 0 ;
  352. for i in A'range loop
  353. if not inside(A(i), Exclude) then
  354. NewALength := NewALength + 1 ;
  355. norm_NewA(NewALength) := A(i) ;
  356. end if ;
  357. end loop ;
  358. end procedure RemoveExclude ;
  359. -- Local. Inside - real_vector
  360. function inside(A : real ; Exclude : real_vector) return boolean is
  361. begin
  362. for i in Exclude'range loop
  363. if A = Exclude(i) then
  364. return TRUE ;
  365. end if ;
  366. end loop ;
  367. return FALSE ;
  368. end function inside ;
  369. -- Local. Remove the exclude list from the list - real_vector
  370. procedure RemoveExclude(A, Exclude : real_vector ; variable NewA : out real_vector ; variable NewALength : inout natural ) is
  371. alias norm_NewA : real_vector(1 to NewA'length) is NewA ;
  372. begin
  373. NewALength := 0 ;
  374. for i in A'range loop
  375. if not inside(A(i), Exclude) then
  376. NewALength := NewALength + 1 ;
  377. norm_NewA(NewALength) := A(i) ;
  378. end if ;
  379. end loop ;
  380. end procedure RemoveExclude ;
  381. -- Local. Inside - time_vector
  382. function inside(A : time ; Exclude : time_vector) return boolean is
  383. begin
  384. for i in Exclude'range loop
  385. if A = Exclude(i) then
  386. return TRUE ;
  387. end if ;
  388. end loop ;
  389. return FALSE ;
  390. end function inside ;
  391. -- Local. Remove the exclude list from the list - time_vector
  392. procedure RemoveExclude(A, Exclude : time_vector ; variable NewA : out time_vector ; variable NewALength : inout natural ) is
  393. alias norm_NewA : time_vector(1 to NewA'length) is NewA ;
  394. begin
  395. NewALength := 0 ;
  396. for i in A'range loop
  397. if not inside(A(i), Exclude) then
  398. NewALength := NewALength + 1 ;
  399. norm_NewA(NewALength) := A(i) ;
  400. end if ;
  401. end loop ;
  402. end procedure RemoveExclude ;
  403. -----------------------------------------------------------------
  404. -- RandomParmType IO
  405. -----------------------------------------------------------------
  406. -----------------------------------------------------------------
  407. function to_string(A : RandomDistType) return string is
  408. begin
  409. return RandomDistType'image(A) ;
  410. end function to_string ;
  411. -----------------------------------------------------------------
  412. procedure write(variable L : inout line ; A : RandomDistType ) is
  413. begin
  414. write(L, to_string(A)) ;
  415. end procedure write ;
  416. -----------------------------------------------------------------
  417. procedure read(variable L : inout line ; A : out RandomDistType ; good : out boolean ) is
  418. variable strval : string(1 to 40) ;
  419. variable len : natural ;
  420. begin
  421. -- procedure SREAD (L : inout LINE ; VALUE : out STRING ; STRLEN : out NATURAL) ;
  422. sread(L, strval, len) ;
  423. A := RandomDistType'value(strval(1 to len)) ;
  424. good := len > 0 ;
  425. end procedure read ;
  426. -----------------------------------------------------------------
  427. procedure read(variable L : inout line ; A : out RandomDistType ) is
  428. variable ReadValid : boolean ;
  429. begin
  430. read(L, A, ReadValid) ;
  431. AlertIfNot( OSVVM_ALERTLOG_ID, ReadValid, "RandomPkg.read[line, RandomDistType] failed", FAILURE) ;
  432. end procedure read ;
  433. -----------------------------------------------------------------
  434. function to_string(A : RandomParmType) return string is
  435. begin
  436. return RandomDistType'image(A.Distribution) & " " &
  437. to_string(A.Mean, 2) & " " & to_string(A.StdDeviation, 2) ;
  438. end function to_string ;
  439. -----------------------------------------------------------------
  440. procedure write(variable L : inout line ; A : RandomParmType ) is
  441. begin
  442. write(L, to_string(A)) ;
  443. end procedure write ;
  444. -----------------------------------------------------------------
  445. procedure read(variable L : inout line ; A : out RandomParmType ; good : out boolean ) is
  446. variable strval : string(1 to 40) ;
  447. variable len : natural ;
  448. variable igood : boolean ;
  449. begin
  450. loop
  451. -- procedure SREAD (L : inout LINE ; VALUE : out STRING ; STRLEN : out NATURAL) ;
  452. sread(L, strval, len) ;
  453. A.Distribution := RandomDistType'value(strval(1 to len)) ;
  454. igood := len > 0 ;
  455. exit when not igood ;
  456. read(L, A.Mean, igood) ;
  457. exit when not igood ;
  458. read(L, A.StdDeviation, igood) ;
  459. exit ;
  460. end loop ;
  461. good := igood ;
  462. end procedure read ;
  463. -----------------------------------------------------------------
  464. procedure read(variable L : inout line ; A : out RandomParmType ) is
  465. variable ReadValid : boolean ;
  466. begin
  467. read(L, A, ReadValid) ;
  468. AlertIfNot( OSVVM_ALERTLOG_ID, ReadValid, "RandomPkg.read[line, RandomParmType] failed", FAILURE) ;
  469. end procedure read ;
  470. -----------------------------------------------------------------
  471. -----------------------------------------------------------------
  472. type RandomPType is protected body
  473. --
  474. -- RandomSeed manipulation
  475. --
  476. variable RandomSeed : RandomSeedType := GenRandSeed(integer_vector'(1,7)) ;
  477. procedure InitSeed (S : string ) is
  478. begin
  479. RandomSeed := GenRandSeed(S) ;
  480. end procedure InitSeed ;
  481. procedure InitSeed (I : integer ) is
  482. begin
  483. RandomSeed := GenRandSeed(I) ;
  484. end procedure InitSeed ;
  485. procedure InitSeed (IV : integer_vector ) is
  486. begin
  487. RandomSeed := GenRandSeed(IV) ;
  488. end procedure InitSeed ;
  489. procedure SetSeed (RandomSeedIn : RandomSeedType ) is
  490. begin
  491. RandomSeed := RandomSeedIn ;
  492. end procedure SetSeed ;
  493. procedure SeedRandom (RandomSeedIn : RandomSeedType ) is
  494. begin
  495. RandomSeed := RandomSeedIn ;
  496. end procedure SeedRandom ;
  497. impure function GetSeed return RandomSeedType is
  498. begin
  499. return RandomSeed ;
  500. end function GetSeed ;
  501. impure function SeedRandom return RandomSeedType is
  502. begin
  503. return RandomSeed ;
  504. end function SeedRandom ;
  505. --
  506. -- randomization mode
  507. --
  508. variable RandomParm : RandomParmType ; -- left most values ok for init
  509. procedure SetRandomParm (RandomParmIn : RandomParmType) is
  510. begin
  511. RandomParm := RandomParmIn ;
  512. end procedure SetRandomParm ;
  513. procedure SetRandomParm (
  514. Distribution : RandomDistType ;
  515. Mean : Real := 0.0 ;
  516. Deviation : Real := 0.0
  517. ) is
  518. begin
  519. RandomParm := RandomParmType'(Distribution, Mean, Deviation) ;
  520. end procedure SetRandomParm ;
  521. impure function GetRandomParm return RandomParmType is
  522. begin
  523. return RandomParm ;
  524. end function GetRandomParm ;
  525. impure function GetRandomParm return RandomDistType is
  526. begin
  527. return RandomParm.Distribution ;
  528. end function GetRandomParm ;
  529. -- For compatibility with previous version
  530. procedure SetRandomMode (RandomDistIn : RandomDistType) is
  531. begin
  532. SetRandomParm(RandomDistIn) ;
  533. end procedure SetRandomMode ;
  534. --
  535. -- Base Randomization Distributions
  536. --
  537. --
  538. -- Uniform : Generate a random number with a Uniform distribution
  539. --
  540. impure function Uniform (Min, Max : in real) return real is
  541. variable rRandomVal : real ;
  542. begin
  543. AlertIf (OSVVM_ALERTLOG_ID, Max < Min, "RandomPkg.Uniform: Max < Min", FAILURE) ;
  544. Uniform(rRandomVal, RandomSeed) ;
  545. return scale(rRandomVal, Min, Max) ;
  546. end function Uniform ;
  547. impure function Uniform (Min, Max : integer) return integer is
  548. variable rRandomVal : real ;
  549. begin
  550. AlertIf (OSVVM_ALERTLOG_ID, Max < Min, "RandomPkg.Uniform: Max < Min", FAILURE) ;
  551. Uniform(rRandomVal, RandomSeed) ;
  552. return scale(rRandomVal, Min, Max) ;
  553. end function Uniform ;
  554. impure function Uniform (Min, Max : integer ; Exclude : integer_vector) return integer is
  555. variable iRandomVal : integer ;
  556. variable ExcludeList : SortListPType ;
  557. variable count : integer ;
  558. begin
  559. ExcludeList.add(Exclude, Min, Max) ;
  560. count := ExcludeList.count ;
  561. iRandomVal := Uniform(Min, Max - count) ;
  562. -- adjust count, note iRandomVal changes while checking.
  563. for i in 1 to count loop
  564. exit when iRandomVal < ExcludeList.Get(i) ;
  565. iRandomVal := iRandomVal + 1 ;
  566. end loop ;
  567. ExcludeList.erase ;
  568. return iRandomVal ;
  569. end function Uniform ;
  570. --
  571. -- FavorSmall
  572. -- Generate random numbers with a greater number of small
  573. -- values than large values
  574. --
  575. impure function FavorSmall (Min, Max : real) return real is
  576. variable rRandomVal : real ;
  577. begin
  578. AlertIf (OSVVM_ALERTLOG_ID, Max < Min, "RandomPkg.FavorSmall: Max < Min", FAILURE) ;
  579. Uniform(rRandomVal, RandomSeed) ;
  580. return scale(FavorSmall(rRandomVal), Min, Max) ; -- real
  581. end function FavorSmall ;
  582. impure function FavorSmall (Min, Max : integer) return integer is
  583. variable rRandomVal : real ;
  584. begin
  585. AlertIf (OSVVM_ALERTLOG_ID, Max < Min, "RandomPkg.FavorSmall: Max < Min", FAILURE) ;
  586. Uniform(rRandomVal, RandomSeed) ;
  587. return scale(FavorSmall(rRandomVal), Min, Max) ; -- integer
  588. end function FavorSmall ;
  589. impure function FavorSmall (Min, Max : integer ; Exclude : integer_vector) return integer is
  590. variable iRandomVal : integer ;
  591. variable ExcludeList : SortListPType ;
  592. variable count : integer ;
  593. begin
  594. ExcludeList.add(Exclude, Min, Max) ;
  595. count := ExcludeList.count ;
  596. iRandomVal := FavorSmall(Min, Max - count) ;
  597. -- adjust count, note iRandomVal changes while checking.
  598. for i in 1 to count loop
  599. exit when iRandomVal < ExcludeList.Get(i) ;
  600. iRandomVal := iRandomVal + 1 ;
  601. end loop ;
  602. ExcludeList.erase ;
  603. return iRandomVal ;
  604. end function FavorSmall ;
  605. --
  606. -- FavorBig
  607. -- Generate random numbers with a greater number of large
  608. -- values than small values
  609. --
  610. impure function FavorBig (Min, Max : real) return real is
  611. variable rRandomVal : real ;
  612. begin
  613. AlertIf (OSVVM_ALERTLOG_ID, Max < Min, "RandomPkg.FavorBig: Max < Min", FAILURE) ;
  614. Uniform(rRandomVal, RandomSeed) ;
  615. return scale(FavorBig(rRandomVal), Min, Max) ; -- real
  616. end function FavorBig ;
  617. impure function FavorBig (Min, Max : integer) return integer is
  618. variable rRandomVal : real ;
  619. begin
  620. AlertIf (OSVVM_ALERTLOG_ID, Max < Min, "RandomPkg.FavorBig: Max < Min", FAILURE) ;
  621. Uniform(rRandomVal, RandomSeed) ;
  622. return scale(FavorBig(rRandomVal), Min, Max) ; -- integer
  623. end function FavorBig ;
  624. impure function FavorBig (Min, Max : integer ; Exclude : integer_vector) return integer is
  625. variable iRandomVal : integer ;
  626. variable ExcludeList : SortListPType ;
  627. variable count : integer ;
  628. begin
  629. ExcludeList.add(Exclude, Min, Max) ;
  630. count := ExcludeList.count ;
  631. iRandomVal := FavorBig(Min, Max - count) ;
  632. -- adjust count, note iRandomVal changes while checking.
  633. for i in 1 to count loop
  634. exit when iRandomVal < ExcludeList.Get(i) ;
  635. iRandomVal := iRandomVal + 1 ;
  636. end loop ;
  637. ExcludeList.erase ;
  638. return iRandomVal ;
  639. end function FavorBig ;
  640. -----------------------------------------------------------------
  641. -- Normal
  642. -- Generate a random number with a normal distribution
  643. --
  644. -- Use Box Muller, per Wikipedia :
  645. -- http ://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
  646. --
  647. -- Use polar method, per Wikipedia :
  648. -- http ://en.wikipedia.org/wiki/Marsaglia_polar_method
  649. --
  650. impure function Normal (Mean, StdDeviation : real) return real is
  651. variable x01, y01 : real ;
  652. variable StdNormalDist : real ; -- mean 0, variance 1
  653. begin
  654. -- add this check to set parameters?
  655. if StdDeviation < 0.0 then
  656. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.Normal: Standard deviation must be >= 0.0", FAILURE) ;
  657. return -1.0 ;
  658. end if ;
  659. -- Box Muller
  660. Uniform (x01, RandomSeed) ;
  661. Uniform (y01, RandomSeed) ;
  662. StdNormalDist := sqrt(-2.0 * log(x01)) * cos(math_2_pi*y01) ;
  663. -- Polar form rejected due to mean 50.0, std deviation = 5 resulted
  664. -- in a median of 49
  665. -- -- find two Uniform distributed values with range -1 to 1
  666. -- -- that satisify S = X **2 + Y**2 < 1.0
  667. -- loop
  668. -- Uniform (x01, RandomSeed) ;
  669. -- Uniform (y01, RandomSeed) ;
  670. -- x := 2.0 * x01 - 1.0 ; -- scale to -1 to 1
  671. -- y := 2.0 * y01 - 1.0 ;
  672. -- s := x*x + y*y ;
  673. -- exit when s < 1.0 and s > 0.0 ;
  674. -- end loop ;
  675. -- -- Calculate Standard Normal Distribution
  676. -- StdNormalDist := x * sqrt((-2.0 * log(s)) / s) ;
  677. -- Convert to have Mean and StdDeviation
  678. return StdDeviation * StdNormalDist + Mean ;
  679. end function Normal ;
  680. -- Normal + RandomVal >= Min and RandomVal <= Max
  681. impure function Normal (Mean, StdDeviation, Min, Max : real) return real is
  682. variable rRandomVal : real ;
  683. begin
  684. if Max < Min then
  685. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.Normal: Max < Min", FAILURE) ;
  686. return Mean ;
  687. else
  688. loop
  689. rRandomVal := Normal (Mean, StdDeviation) ;
  690. exit when rRandomVal >= Min and rRandomVal <= Max ;
  691. end loop ;
  692. end if ;
  693. return rRandomVal ;
  694. end function Normal ;
  695. -- Normal + RandomVal >= Min and RandomVal <= Max
  696. impure function Normal (
  697. Mean : real ;
  698. StdDeviation : real ;
  699. Min : integer ;
  700. Max : integer ;
  701. Exclude : integer_vector := NULL_INTV
  702. ) return integer is
  703. variable iRandomVal : integer ;
  704. begin
  705. if Max < Min then
  706. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.Normal: Max < Min", FAILURE) ;
  707. return integer(round(Mean)) ;
  708. else
  709. loop
  710. iRandomVal := integer(round( Normal(Mean, StdDeviation) )) ;
  711. exit when iRandomVal >= Min and iRandomVal <= Max and
  712. not inside(iRandomVal, Exclude) ;
  713. end loop ;
  714. end if ;
  715. return iRandomVal ;
  716. end function Normal ;
  717. -----------------------------------------------------------------
  718. -- Poisson
  719. -- Generate a random number with a poisson distribution
  720. -- Discrete distribution = only generates integral values
  721. --
  722. -- Use knuth method, per Wikipedia :
  723. -- http ://en.wikipedia.org/wiki/Poisson_distribution
  724. --
  725. impure function Poisson (Mean : real) return real is
  726. variable Product : Real := 1.0 ;
  727. variable Bound : Real := 0.0 ;
  728. variable UniformRand : Real := 0.0 ;
  729. variable PoissonRand : Real := 0.0 ;
  730. begin
  731. Bound := exp(-1.0 * Mean) ;
  732. Product := 1.0 ;
  733. -- add this check to set parameters?
  734. if Mean <= 0.0 or Bound <= 0.0 then
  735. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.Poisson: Mean < 0 or too large. Mean = " & real'image(Mean), FAILURE) ;
  736. return Mean ;
  737. end if ;
  738. while (Product >= Bound) loop
  739. PoissonRand := PoissonRand + 1.0 ;
  740. Uniform(UniformRand, RandomSeed) ;
  741. Product := Product * UniformRand ;
  742. end loop ;
  743. return PoissonRand ;
  744. end function Poisson ; -- no range
  745. -- Poisson + RandomVal >= Min and RandomVal < Max
  746. impure function Poisson (Mean, Min, Max : real) return real is
  747. variable rRandomVal : real ;
  748. begin
  749. if Max < Min then
  750. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.Poisson: Max < Min", FAILURE) ;
  751. return Mean ;
  752. else
  753. loop
  754. rRandomVal := Poisson (Mean) ;
  755. exit when rRandomVal >= Min and rRandomVal <= Max ;
  756. end loop ;
  757. end if ;
  758. return rRandomVal ;
  759. end function Poisson ;
  760. impure function Poisson (
  761. Mean : real ;
  762. Min : integer ;
  763. Max : integer ;
  764. Exclude : integer_vector := NULL_INTV
  765. ) return integer is
  766. variable iRandomVal : integer ;
  767. begin
  768. if Max < Min then
  769. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.Poisson: Max < Min", FAILURE) ;
  770. return integer(round(Mean)) ;
  771. else
  772. loop
  773. iRandomVal := integer(round( Poisson (Mean) )) ;
  774. exit when iRandomVal >= Min and iRandomVal <= Max and
  775. not inside(iRandomVal, Exclude) ;
  776. end loop ;
  777. end if ;
  778. return iRandomVal ;
  779. end function Poisson ;
  780. --
  781. -- integer randomization with a range
  782. -- Distribution determined by RandomParm
  783. --
  784. impure function RandInt (Min, Max : integer) return integer is
  785. begin
  786. case RandomParm.Distribution is
  787. when NONE | UNIFORM => return Uniform(Min, Max) ;
  788. when FAVOR_SMALL => return FavorSmall(Min, Max) ;
  789. when FAVOR_BIG => return FavorBig (Min, Max) ;
  790. when NORMAL => return Normal(RandomParm.Mean, RandomParm.StdDeviation, Min, Max) ;
  791. when POISSON => return Poisson(RandomParm.Mean, Min, Max) ;
  792. when others =>
  793. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandInt: RandomParm.Distribution not implemented", FAILURE) ;
  794. return integer'low ;
  795. end case ;
  796. end function RandInt ;
  797. --
  798. -- real randomization with a range
  799. -- Distribution determined by RandomParm
  800. --
  801. impure function RandReal(Min, Max : Real) return real is
  802. begin
  803. case RandomParm.Distribution is
  804. when NONE | UNIFORM => return Uniform(Min, Max) ;
  805. when FAVOR_SMALL => return FavorSmall(Min, Max) ;
  806. when FAVOR_BIG => return FavorBig (Min, Max) ;
  807. when NORMAL => return Normal(RandomParm.Mean, RandomParm.StdDeviation, Min, Max) ;
  808. when POISSON => return Poisson(RandomParm.Mean, Min, Max) ;
  809. when others =>
  810. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandReal: Specified RandomParm.Distribution not implemented", FAILURE) ;
  811. return real(integer'low) ;
  812. end case ;
  813. end function RandReal ;
  814. impure function RandTime (Min, Max : time ; Unit :time := ns) return time is
  815. variable IntVal : integer ;
  816. begin
  817. -- if Max - Min > 2**31 result will be out of range
  818. IntVal := RandInt(0, (Max - Min)/Unit) ;
  819. Return Min + Unit*IntVal ;
  820. end function RandTime ;
  821. impure function RandSlv (Min, Max, Size : natural) return std_logic_vector is
  822. begin
  823. return std_logic_vector(to_unsigned(RandInt(Min, Max), Size)) ;
  824. end function RandSlv ;
  825. impure function RandUnsigned (Min, Max, Size : natural) return Unsigned is
  826. begin
  827. return to_unsigned(RandInt(Min, Max), Size) ;
  828. end function RandUnsigned ;
  829. impure function RandSigned (Min, Max : integer ; Size : natural ) return Signed is
  830. begin
  831. return to_signed(RandInt(Min, Max), Size) ;
  832. end function RandSigned ;
  833. impure function RandIntV (Min, Max : integer ; Size : natural) return integer_vector is
  834. variable result : integer_vector(1 to Size) ;
  835. begin
  836. for i in result'range loop
  837. result(i) := RandInt(Min, Max) ;
  838. end loop ;
  839. return result ;
  840. end function RandIntV ;
  841. impure function RandIntV (Min, Max : integer ; Unique : natural ; Size : natural) return integer_vector is
  842. variable result : integer_vector(1 to Size) ;
  843. variable iUnique : natural ;
  844. begin
  845. -- if Unique = 0, it is more efficient to call RandIntV(Min, Max, Size)
  846. iUnique := Unique ;
  847. if Max-Min+1 < Unique then
  848. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.(RandIntV | RandRealV | RandTimeV): Unique > number of values available", FAILURE) ;
  849. iUnique := Max-Min+1 ;
  850. end if ;
  851. for i in result'range loop
  852. result(i) := RandInt(Min, Max, result(maximum(1, 1 + i - iUnique) to Size)) ;
  853. end loop ;
  854. return result ;
  855. end function RandIntV ;
  856. impure function RandRealV (Min, Max : real ; Size : natural) return real_vector is
  857. variable result : real_vector(1 to Size) ;
  858. begin
  859. for i in result'range loop
  860. result(i) := RandReal(Min, Max) ;
  861. end loop ;
  862. return result ;
  863. end function RandRealV ;
  864. impure function RandTimeV (Min, Max : time ; Size : natural ; Unit : time := ns) return time_vector is
  865. variable result : time_vector(1 to Size) ;
  866. begin
  867. for i in result'range loop
  868. result(i) := RandTime(Min, Max, Unit) ;
  869. end loop ;
  870. return result ;
  871. end function RandTimeV ;
  872. impure function RandTimeV (Min, Max : time ; Unique : natural ; Size : natural ; Unit : time := ns) return time_vector is
  873. begin
  874. -- if Unique = 0, it is more efficient to call RandTimeV(Min, Max, Size)
  875. return to_time_vector(RandIntV(Min/Unit, Max/Unit, Unique, Size), Unit) ;
  876. end function RandTimeV ;
  877. --
  878. -- integer randomization with a range and exclude vector
  879. -- Distribution determined by RandomParm
  880. --
  881. impure function RandInt (Min, Max : integer ; Exclude : integer_vector ) return integer is
  882. begin
  883. case RandomParm.Distribution is
  884. when NONE | UNIFORM => return Uniform(Min, Max, Exclude) ;
  885. when FAVOR_SMALL => return FavorSmall(Min, Max, Exclude) ;
  886. when FAVOR_BIG => return FavorBig (Min, Max, Exclude) ;
  887. when NORMAL => return Normal(RandomParm.Mean, RandomParm.StdDeviation, Min, Max, Exclude) ;
  888. when POISSON => return Poisson(RandomParm.Mean, Min, Max, Exclude) ;
  889. when others =>
  890. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandInt: Specified RandomParm.Distribution not implemented", FAILURE) ;
  891. return integer'low ;
  892. end case ;
  893. end function RandInt ;
  894. impure function RandTime (Min, Max : time ; Exclude : time_vector ; Unit : time := ns) return time is
  895. variable IntVal : integer ;
  896. begin
  897. -- if Min or Max > 2**31 value will be out of range
  898. return RandInt(Min/Unit, Max/Unit, to_integer_vector(Exclude, Unit)) * Unit ;
  899. end function RandTime ;
  900. impure function RandSlv (Min, Max : natural ; Exclude : integer_vector ; Size : natural ) return std_logic_vector is
  901. begin
  902. return std_logic_vector(to_unsigned(RandInt(Min, Max, Exclude), Size)) ;
  903. end function RandSlv ;
  904. impure function RandUnsigned (Min, Max : natural ; Exclude : integer_vector ; Size : natural ) return Unsigned is
  905. begin
  906. return to_unsigned(RandInt(Min, Max, Exclude), Size) ;
  907. end function RandUnsigned ;
  908. impure function RandSigned (Min, Max : integer ; Exclude : integer_vector ; Size : natural ) return Signed is
  909. begin
  910. return to_signed(RandInt(Min, Max, Exclude), Size) ;
  911. end function RandSigned ;
  912. impure function RandIntV (Min, Max : integer ; Exclude : integer_vector ; Size : natural) return integer_vector is
  913. variable result : integer_vector(1 to Size) ;
  914. begin
  915. for i in result'range loop
  916. result(i) := RandInt(Min, Max, Exclude) ;
  917. end loop ;
  918. return result ;
  919. end function RandIntV ;
  920. impure function RandIntV (Min, Max : integer ; Exclude : integer_vector ; Unique : natural ; Size : natural) return integer_vector is
  921. variable ResultPlus : integer_vector(1 to Size + Exclude'length) ;
  922. begin
  923. -- if Unique = 0, it is more efficient to call RandIntV(Min, Max, Size)
  924. ResultPlus(Size+1 to ResultPlus'right) := Exclude ;
  925. for i in 1 to Size loop
  926. ResultPlus(i) := RandInt(Min, Max, ResultPlus(maximum(1, 1 + i - Unique) to ResultPlus'right)) ;
  927. end loop ;
  928. return ResultPlus(1 to Size) ;
  929. end function RandIntV ;
  930. impure function RandTimeV (Min, Max : time ; Exclude : time_vector ; Size : natural ; Unit : in time := ns) return time_vector is
  931. begin
  932. return to_time_vector( RandIntV(Min/Unit, Max/Unit, to_integer_vector(Exclude, Unit), Size), Unit ) ;
  933. end function RandTimeV ;
  934. impure function RandTimeV (Min, Max : time ; Exclude : time_vector ; Unique : natural ; Size : natural ; Unit : in time := ns) return time_vector is
  935. begin
  936. -- if Unique = 0, it is more efficient to call RandIntV(Min, Max, Size)
  937. return to_time_vector( RandIntV(Min/Unit, Max/Unit, to_integer_vector(Exclude, Unit), Unique, Size), Unit ) ;
  938. end function RandTimeV ;
  939. --
  940. -- Randomly select a value within a set of values
  941. -- Distribution determined by RandomParm
  942. --
  943. impure function RandInt ( A : integer_vector ) return integer is
  944. alias A_norm : integer_vector(1 to A'length) is A ;
  945. begin
  946. return A_norm( RandInt(1, A'length) ) ;
  947. end function RandInt ;
  948. impure function RandReal ( A : real_vector ) return real is
  949. alias A_norm : real_vector(1 to A'length) is A ;
  950. begin
  951. return A_norm( RandInt(1, A'length) ) ;
  952. end function RandReal ;
  953. impure function RandTime ( A : time_vector ) return time is
  954. alias A_norm : time_vector(1 to A'length) is A ;
  955. begin
  956. return A_norm( RandInt(1, A'length) ) ;
  957. end function RandTime ;
  958. impure function RandSlv (A : integer_vector ; Size : natural) return std_logic_vector is
  959. begin
  960. return std_logic_vector(to_unsigned(RandInt(A), Size)) ;
  961. end function RandSlv ;
  962. impure function RandUnsigned (A : integer_vector ; Size : natural) return Unsigned is
  963. begin
  964. return to_unsigned(RandInt(A), Size) ;
  965. end function RandUnsigned ;
  966. impure function RandSigned (A : integer_vector ; Size : natural ) return Signed is
  967. begin
  968. return to_signed(RandInt(A), Size) ;
  969. end function RandSigned ;
  970. impure function RandIntV (A : integer_vector ; Size : natural) return integer_vector is
  971. variable result : integer_vector(1 to Size) ;
  972. begin
  973. for i in result'range loop
  974. result(i) := RandInt(A) ;
  975. end loop ;
  976. return result ;
  977. end function RandIntV ;
  978. impure function RandIntV (A : integer_vector ; Unique : natural ; Size : natural) return integer_vector is
  979. variable result : integer_vector(1 to Size) ;
  980. variable iUnique : natural ;
  981. begin
  982. -- if Unique = 0, it is more efficient to call RandIntV(A, Size)
  983. -- require A'length >= Unique
  984. iUnique := Unique ;
  985. if A'length < Unique then
  986. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandIntV: Unique > length of set of values", FAILURE) ;
  987. iUnique := A'length ;
  988. end if ;
  989. for i in result'range loop
  990. result(i) := RandInt(A, result(maximum(1, 1 + i - iUnique) to Size)) ;
  991. end loop ;
  992. return result ;
  993. end function RandIntV ;
  994. impure function RandRealV (A : real_vector ; Size : natural) return real_vector is
  995. variable result : real_vector(1 to Size) ;
  996. begin
  997. for i in result'range loop
  998. result(i) := RandReal(A) ;
  999. end loop ;
  1000. return result ;
  1001. end function RandRealV ;
  1002. impure function RandRealV (A : real_vector ; Unique : natural ; Size : natural) return real_vector is
  1003. alias A_norm : real_vector(1 to A'length) is A ;
  1004. variable result : real_vector(1 to Size) ;
  1005. variable IntResult : integer_vector(result'range) ;
  1006. begin
  1007. -- randomly generate indices
  1008. IntResult := RandIntV(1, A'length, Unique, Size) ;
  1009. -- translate indicies into result values
  1010. for i in result'range loop
  1011. result(i) := A_norm(IntResult(i)) ;
  1012. end loop ;
  1013. return result ;
  1014. end function RandRealV ;
  1015. impure function RandTimeV (A : time_vector ; Size : natural) return time_vector is
  1016. variable result : time_vector(1 to Size) ;
  1017. begin
  1018. for i in result'range loop
  1019. result(i) := RandTime(A) ;
  1020. end loop ;
  1021. return result ;
  1022. end function RandTimeV ;
  1023. impure function RandTimeV (A : time_vector ; Unique : natural ; Size : natural) return time_vector is
  1024. alias A_norm : time_vector(1 to A'length) is A ;
  1025. variable result : time_vector(1 to Size) ;
  1026. variable IntResult : integer_vector(result'range) ;
  1027. begin
  1028. -- randomly generate indices
  1029. IntResult := RandIntV(1, A'length, Unique, Size) ;
  1030. -- translate indicies into result values
  1031. for i in result'range loop
  1032. result(i) := A_norm(IntResult(i)) ;
  1033. end loop ;
  1034. return result ;
  1035. end function RandTimeV ;
  1036. --
  1037. -- Randomly select a value within a set of values with exclude values (so can skip last or last n)
  1038. -- Distribution determined by RandomParm
  1039. --
  1040. impure function RandInt ( A, Exclude : integer_vector ) return integer is
  1041. variable NewA : integer_vector(1 to A'length) ;
  1042. variable NewALength : natural ;
  1043. begin
  1044. -- Remove Exclude from A
  1045. RemoveExclude(A, Exclude, NewA, NewALength) ;
  1046. -- Randomize Index
  1047. return NewA(RandInt(1, NewALength)) ;
  1048. end function RandInt ;
  1049. impure function RandReal ( A, Exclude : real_vector ) return real is
  1050. variable NewA : real_vector(1 to A'length) ;
  1051. variable NewALength : natural ;
  1052. begin
  1053. -- Remove Exclude from A
  1054. RemoveExclude(A, Exclude, NewA, NewALength) ;
  1055. -- Randomize Index
  1056. return NewA(RandInt(1, NewALength)) ;
  1057. end function RandReal ;
  1058. impure function RandTime ( A, Exclude : time_vector ) return time is
  1059. variable NewA : time_vector(1 to A'length) ;
  1060. variable NewALength : natural ;
  1061. begin
  1062. -- Remove Exclude from A
  1063. RemoveExclude(A, Exclude, NewA, NewALength) ;
  1064. -- Randomize Index
  1065. return NewA(RandInt(1, NewALength)) ;
  1066. end function RandTime ;
  1067. impure function RandSlv (A, Exclude : integer_vector ; Size : natural) return std_logic_vector is
  1068. begin
  1069. return std_logic_vector(to_unsigned(RandInt(A, Exclude), Size)) ;
  1070. end function RandSlv ;
  1071. impure function RandUnsigned (A, Exclude : integer_vector ; Size : natural) return Unsigned is
  1072. begin
  1073. return to_unsigned(RandInt(A, Exclude), Size) ;
  1074. end function RandUnsigned ;
  1075. impure function RandSigned (A, Exclude : integer_vector ; Size : natural ) return Signed is
  1076. begin
  1077. return to_signed(RandInt(A, Exclude), Size) ;
  1078. end function RandSigned ;
  1079. impure function RandIntV (A, Exclude : integer_vector ; Size : natural) return integer_vector is
  1080. variable result : integer_vector(1 to Size) ;
  1081. variable NewA : integer_vector(1 to A'length) ;
  1082. variable NewALength : natural ;
  1083. begin
  1084. -- Remove Exclude from A
  1085. RemoveExclude(A, Exclude, NewA, NewALength) ;
  1086. -- Randomize Index
  1087. for i in result'range loop
  1088. result(i) := NewA(RandInt(1, NewALength)) ;
  1089. end loop ;
  1090. return result ;
  1091. end function RandIntV ;
  1092. impure function RandIntV (A, Exclude : integer_vector ; Unique : natural ; Size : natural) return integer_vector is
  1093. variable result : integer_vector(1 to Size) ;
  1094. variable NewA : integer_vector(1 to A'length) ;
  1095. variable NewALength, iUnique : natural ;
  1096. begin
  1097. -- if Unique = 0, it is more efficient to call RandIntV(Min, Max, Size)
  1098. -- Remove Exclude from A
  1099. RemoveExclude(A, Exclude, NewA, NewALength) ;
  1100. -- Require NewALength >= Unique
  1101. iUnique := Unique ;
  1102. if NewALength < Unique then
  1103. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandIntV: Unique > Length of Set A - Exclude", FAILURE) ;
  1104. iUnique := NewALength ;
  1105. end if ;
  1106. -- Randomize using exclude list of Unique # of newly generated values
  1107. for i in result'range loop
  1108. result(i) := RandInt(NewA(1 to NewALength), result(maximum(1, 1 + i - iUnique) to Size)) ;
  1109. end loop ;
  1110. return result ;
  1111. end function RandIntV ;
  1112. impure function RandRealV (A, Exclude : real_vector ; Size : natural) return real_vector is
  1113. variable result : real_vector(1 to Size) ;
  1114. variable NewA : real_vector(1 to A'length) ;
  1115. variable NewALength : natural ;
  1116. begin
  1117. -- Remove Exclude from A
  1118. RemoveExclude(A, Exclude, NewA, NewALength) ;
  1119. -- Randomize Index
  1120. for i in result'range loop
  1121. result(i) := NewA(RandInt(1, NewALength)) ;
  1122. end loop ;
  1123. return result ;
  1124. end function RandRealV ;
  1125. impure function RandRealV (A, Exclude : real_vector ; Unique : natural ; Size : natural) return real_vector is
  1126. variable result : real_vector(1 to Size) ;
  1127. variable NewA : real_vector(1 to A'length) ;
  1128. variable NewALength, iUnique : natural ;
  1129. begin
  1130. -- if Unique = 0, it is more efficient to call RandRealV(Min, Max, Size)
  1131. -- Remove Exclude from A
  1132. RemoveExclude(A, Exclude, NewA, NewALength) ;
  1133. -- Require NewALength >= Unique
  1134. iUnique := Unique ;
  1135. if NewALength < Unique then
  1136. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandRealV: Unique > Length of Set A - Exclude", FAILURE) ;
  1137. iUnique := NewALength ;
  1138. end if ;
  1139. -- Randomize using exclude list of Unique # of newly generated values
  1140. for i in result'range loop
  1141. result(i) := RandReal(NewA(1 to NewALength), result(maximum(1, 1 + i - iUnique) to Size)) ;
  1142. end loop ;
  1143. return result ;
  1144. end function RandRealV ;
  1145. impure function RandTimeV (A, Exclude : time_vector ; Size : natural) return time_vector is
  1146. variable result : time_vector(1 to Size) ;
  1147. variable NewA : time_vector(1 to A'length) ;
  1148. variable NewALength : natural ;
  1149. begin
  1150. -- Remove Exclude from A
  1151. RemoveExclude(A, Exclude, NewA, NewALength) ;
  1152. -- Randomize Index
  1153. for i in result'range loop
  1154. result(i) := NewA(RandInt(1, NewALength)) ;
  1155. end loop ;
  1156. return result ;
  1157. end function RandTimeV ;
  1158. impure function RandTimeV (A, Exclude : time_vector ; Unique : natural ; Size : natural) return time_vector is
  1159. variable result : time_vector(1 to Size) ;
  1160. variable NewA : time_vector(1 to A'length) ;
  1161. variable NewALength, iUnique : natural ;
  1162. begin
  1163. -- if Unique = 0, it is more efficient to call RandRealV(Min, Max, Size)
  1164. -- Remove Exclude from A
  1165. RemoveExclude(A, Exclude, NewA, NewALength) ;
  1166. -- Require NewALength >= Unique
  1167. iUnique := Unique ;
  1168. if NewALength < Unique then
  1169. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandTimeV: Unique > Length of Set A - Exclude", FAILURE) ;
  1170. iUnique := NewALength ;
  1171. end if ;
  1172. -- Randomize using exclude list of Unique # of newly generated values
  1173. for i in result'range loop
  1174. result(i) := RandTime(NewA(1 to NewALength), result(maximum(1, 1 + i - iUnique) to Size)) ;
  1175. end loop ;
  1176. return result ;
  1177. end function RandTimeV ;
  1178. --
  1179. -- Basic Discrete Distributions
  1180. -- Always uses Uniform
  1181. --
  1182. impure function DistInt ( Weight : integer_vector ) return integer is
  1183. variable DistArray : integer_vector(weight'range) ;
  1184. variable sum : integer ;
  1185. variable iRandomVal : integer ;
  1186. begin
  1187. DistArray := Weight ;
  1188. sum := 0 ;
  1189. for i in DistArray'range loop
  1190. DistArray(i) := DistArray(i) + sum ;
  1191. if DistArray(i) < sum then
  1192. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.DistInt: negative weight or sum > 31 bits", FAILURE) ;
  1193. return DistArray'low ; -- allows debugging vs integer'left, out of range
  1194. end if ;
  1195. sum := DistArray(i) ;
  1196. end loop ;
  1197. if sum >= 1 then
  1198. iRandomVal := Uniform(1, sum) ;
  1199. for i in DistArray'range loop
  1200. if iRandomVal <= DistArray(i) then
  1201. return i ;
  1202. end if ;
  1203. end loop ;
  1204. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.DistInt: randomization failed", FAILURE) ;
  1205. else
  1206. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.DistInt: No randomization weights", FAILURE) ;
  1207. end if ;
  1208. return DistArray'low ; -- allows debugging vs integer'left, out of range
  1209. end function DistInt ;
  1210. impure function DistSlv ( Weight : integer_vector ; Size : natural ) return std_logic_vector is
  1211. begin
  1212. return std_logic_vector(to_unsigned(DistInt(Weight), Size)) ;
  1213. end function DistSlv ;
  1214. impure function DistUnsigned ( Weight : integer_vector ; Size : natural ) return unsigned is
  1215. begin
  1216. return to_unsigned(DistInt(Weight), Size) ;
  1217. end function DistUnsigned ;
  1218. impure function DistSigned ( Weight : integer_vector ; Size : natural ) return signed is
  1219. begin
  1220. return to_signed(DistInt(Weight), Size) ;
  1221. end function DistSigned ;
  1222. --
  1223. -- Basic Distributions with exclude values (so can skip last or last n)
  1224. -- Always uses Uniform via DistInt
  1225. --
  1226. impure function DistInt ( Weight : integer_vector ; Exclude : integer_vector ) return integer is
  1227. variable DistArray : integer_vector(weight'range) ;
  1228. variable ExcludeTemp : integer ;
  1229. begin
  1230. DistArray := Weight ;
  1231. for i in Exclude'range loop
  1232. ExcludeTemp := Exclude(i) ;
  1233. if ExcludeTemp >= DistArray'low and ExcludeTemp <= DistArray'high then
  1234. DistArray(ExcludeTemp) := 0 ;
  1235. end if ;
  1236. end loop ;
  1237. return DistInt(DistArray) ;
  1238. end function DistInt ;
  1239. impure function DistSlv ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return std_logic_vector is
  1240. begin
  1241. return std_logic_vector(to_unsigned(DistInt(Weight, Exclude), Size)) ;
  1242. end function DistSlv ;
  1243. impure function DistUnsigned ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return unsigned is
  1244. begin
  1245. return to_unsigned(DistInt(Weight, Exclude), Size) ;
  1246. end function DistUnsigned ;
  1247. impure function DistSigned ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return signed is
  1248. begin
  1249. return to_signed(DistInt(Weight, Exclude), Size) ;
  1250. end function DistSigned ;
  1251. --
  1252. -- Distribution for sparse values
  1253. -- Always uses Uniform via DistInt
  1254. --
  1255. impure function DistValInt ( A : DistType ) return integer is
  1256. variable DistArray : integer_vector(0 to A'length -1) ;
  1257. alias DistRecArray : DistType(DistArray'range) is A ;
  1258. begin
  1259. for i in DistArray'range loop
  1260. DistArray(i) := DistRecArray(i).Weight ;
  1261. end loop ;
  1262. return DistRecArray(DistInt(DistArray)).Value ;
  1263. end function DistValInt ;
  1264. impure function DistValSlv ( A : DistType ; Size : natural ) return std_logic_vector is
  1265. begin
  1266. return std_logic_vector(to_unsigned(DistValInt(A), Size)) ;
  1267. end function DistValSlv ;
  1268. impure function DistValUnsigned ( A : DistType ; Size : natural ) return unsigned is
  1269. begin
  1270. return to_unsigned(DistValInt(A), Size) ;
  1271. end function DistValUnsigned ;
  1272. impure function DistValSigned ( A : DistType ; Size : natural ) return signed is
  1273. begin
  1274. return to_signed(DistValInt(A), Size) ;
  1275. end function DistValSigned ;
  1276. --
  1277. -- Distribution for sparse values with exclude values (so can skip last or last n)
  1278. -- Always uses Uniform via DistInt
  1279. --
  1280. impure function DistValInt ( A : DistType ; Exclude : integer_vector ) return integer is
  1281. variable DistArray : integer_vector(0 to A'length -1) ;
  1282. alias DistRecArray : DistType(DistArray'range) is A ;
  1283. begin
  1284. for i in DistRecArray'range loop
  1285. if inside(DistRecArray(i).Value, exclude) then
  1286. DistArray(i) := 0 ; -- exclude
  1287. else
  1288. DistArray(i) := DistRecArray(i).Weight ;
  1289. end if ;
  1290. end loop ;
  1291. return DistRecArray(DistInt(DistArray)).Value ;
  1292. end function DistValInt ;
  1293. impure function DistValSlv ( A : DistType ; Exclude : integer_vector ; Size : natural ) return std_logic_vector is
  1294. begin
  1295. return std_logic_vector(to_unsigned(DistValInt(A, Exclude), Size)) ;
  1296. end function DistValSlv ;
  1297. impure function DistValUnsigned ( A : DistType ; Exclude : integer_vector ; Size : natural ) return unsigned is
  1298. begin
  1299. return to_unsigned(DistValInt(A, Exclude), Size) ;
  1300. end function DistValUnsigned ;
  1301. impure function DistValSigned ( A : DistType ; Exclude : integer_vector ; Size : natural ) return signed is
  1302. begin
  1303. return to_signed(DistValInt(A, Exclude), Size) ;
  1304. end function DistValSigned ;
  1305. --
  1306. -- Large vector handling.
  1307. --
  1308. impure function RandUnsigned (Size : natural) return unsigned is
  1309. constant NumLoops : integer := integer(ceil(real(Size)/30.0)) ;
  1310. constant Remain : integer := (Size - 1) mod 30 + 1 ; -- range 1 to 30
  1311. variable RandVal : unsigned(1 to Size) ;
  1312. begin
  1313. if size = 0 then
  1314. return NULL_UV ; -- Null array
  1315. end if ;
  1316. for i in 0 to NumLoops-2 loop
  1317. RandVal(1 + 30*i to 30 + 30*i) := to_unsigned(RandInt(0, 2**30-1), 30) ;
  1318. end loop ;
  1319. RandVal(1+30*(NumLoops-1) to Remain + 30*(NumLoops-1)) := to_unsigned(RandInt(0, 2**Remain-1), Remain) ;
  1320. return RandVal ;
  1321. end function RandUnsigned ;
  1322. impure function RandSlv (Size : natural) return std_logic_vector is
  1323. begin
  1324. return std_logic_vector(RandUnsigned(Size)) ;
  1325. end function RandSlv ;
  1326. impure function RandSigned (Size : natural) return signed is
  1327. begin
  1328. return signed(RandUnsigned(Size)) ;
  1329. end function RandSigned ;
  1330. impure function RandUnsigned (Max : unsigned) return unsigned is
  1331. alias normMax : unsigned (Max'length downto 1) is Max ;
  1332. variable Result : unsigned(Max'range) := (others => '0') ;
  1333. alias normResult : unsigned(normMax'range) is Result ;
  1334. variable Size : integer ;
  1335. begin
  1336. -- Size = -1 if not found or Max'length = 0
  1337. Size := find_leftmost(normMax, '1') ;
  1338. if Size > 0 then
  1339. loop
  1340. normResult(Size downto 1) := RandUnsigned(Size) ;
  1341. exit when normResult <= Max ;
  1342. end loop ;
  1343. return Result ; -- = normResult with range same as Max
  1344. else
  1345. return resize("0", Max'length) ;
  1346. end if ;
  1347. end function RandUnsigned ;
  1348. -- Working version that scales the value
  1349. -- impure function RandUnsigned (Max : unsigned) return unsigned is
  1350. -- constant MaxVal : unsigned(Max'length+3 downto 1) := (others => '1') ;
  1351. -- begin
  1352. -- if max'length > 0 then
  1353. -- -- "Max'length+3" creates 3 guard bits
  1354. -- return resize( RandUnsigned(Max'length+3) * ('0'&Max+1) / ('0'&MaxVal+1), Max'length) ;
  1355. -- else
  1356. -- return NULL_UV ; -- Null Array
  1357. -- end if ;
  1358. -- end function RandUnsigned ;
  1359. impure function RandSlv (Max : std_logic_vector) return std_logic_vector is
  1360. begin
  1361. return std_logic_vector(RandUnsigned( unsigned(Max))) ;
  1362. end function RandSlv ;
  1363. impure function RandSigned (Max : signed) return signed is
  1364. begin
  1365. if max'length > 0 then
  1366. AlertIf (OSVVM_ALERTLOG_ID, Max < 0, "RandomPkg.RandSigned: Max < 0", FAILURE) ;
  1367. return signed(RandUnsigned( unsigned(Max))) ;
  1368. else
  1369. return NULL_SV ; -- Null Array
  1370. end if ;
  1371. end function RandSigned ;
  1372. impure function RandUnsigned (Min, Max : unsigned) return unsigned is
  1373. constant LEN : integer := maximum(Max'length, Min'length) ;
  1374. begin
  1375. if LEN > 0 and Min <= Max then
  1376. return RandUnsigned(Max-Min) + Min ;
  1377. else
  1378. if Len > 0 then
  1379. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandUnsigned: Max < Min", FAILURE) ;
  1380. end if ;
  1381. return NULL_UV ;
  1382. end if ;
  1383. end function RandUnsigned ;
  1384. impure function RandSlv (Min, Max : std_logic_vector) return std_logic_vector is
  1385. constant LEN : integer := maximum(Max'length, Min'length) ;
  1386. begin
  1387. if LEN > 0 and Min <= Max then
  1388. return RandSlv(Max-Min) + Min ;
  1389. else
  1390. if Len > 0 then
  1391. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandSlv: Max < Min", FAILURE) ;
  1392. end if ;
  1393. return NULL_SlV ;
  1394. end if ;
  1395. end function RandSlv ;
  1396. impure function RandSigned (Min, Max : signed) return signed is
  1397. constant LEN : integer := maximum(Max'length, Min'length) ;
  1398. begin
  1399. if LEN > 0 and Min <= Max then
  1400. return resize(RandSigned(resize(Max,LEN+1) - resize(Min,LEN+1)) + Min, LEN) ;
  1401. else
  1402. if Len > 0 then
  1403. Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandSigned: Max < Min", FAILURE) ;
  1404. end if ;
  1405. return NULL_SV ;
  1406. end if ;
  1407. end function RandSigned ;
  1408. --
  1409. -- Convenience Functions. Resolve into calls into the other functions
  1410. --
  1411. impure function RandReal return real is
  1412. begin
  1413. return RandReal(0.0, 1.0) ;
  1414. end function RandReal ;
  1415. impure function RandReal(Max : Real) return real is -- 0.0 to Max
  1416. begin
  1417. return RandReal(0.0, Max) ;
  1418. end function RandReal ;
  1419. impure function RandInt (Max : integer) return integer is
  1420. begin
  1421. return RandInt(0, Max) ;
  1422. end function RandInt ;
  1423. impure function RandSlv (Max, Size : natural) return std_logic_vector is
  1424. begin
  1425. return std_logic_vector(to_unsigned(RandInt(0, Max), Size)) ;
  1426. end function RandSlv ;
  1427. impure function RandUnsigned (Max, Size : natural) return Unsigned is
  1428. begin
  1429. return to_unsigned(RandInt(0, Max), Size) ;
  1430. end function RandUnsigned ;
  1431. impure function RandSigned (Max : integer ; Size : natural ) return Signed is
  1432. begin
  1433. -- chose 0 to Max rather than -Max to +Max to be same as RandUnsigned, either seems logical
  1434. return to_signed(RandInt(0, Max), Size) ;
  1435. end function RandSigned ;
  1436. end protected body RandomPType ;
  1437. end RandomPkg ;