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.

1645 lines
64 KiB

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