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.

233 lines
8.7 KiB

  1. --
  2. -- File Name: RandomBasePkg.vhd
  3. -- Design Unit Name: RandomBasePkg
  4. -- Revision: STANDARD VERSION
  5. --
  6. -- Maintainer: Jim Lewis email: jim@synthworks.com
  7. -- Contributor(s):
  8. -- Jim Lewis jim@synthworks.com
  9. --
  10. --
  11. -- Description:
  12. -- Defines Base randomization, seed definition, seed generation,
  13. -- and seed IO functionality for RandomPkg.vhd
  14. -- Defines:
  15. -- Procedure Uniform - baseline randomization
  16. -- Type RandomSeedType - the seed as a single object
  17. -- function GenRandSeed from integer_vector, integer, or string
  18. -- IO function to_string, & procedures write, read
  19. --
  20. -- In revision 2.0 these types and functions are included by package reference.
  21. -- Long term these will be passed as generics to RandomGenericPkg
  22. --
  23. --
  24. -- Developed for:
  25. -- SynthWorks Design Inc.
  26. -- VHDL Training Classes
  27. -- 11898 SW 128th Ave. Tigard, Or 97223
  28. -- http://www.SynthWorks.com
  29. --
  30. -- Revision History:
  31. -- Date Version Description
  32. -- 01/2008: 0.1 Initial revision
  33. -- Numerous revisions for VHDL Testbenches and Verification
  34. -- 02/2009: 1.0 First Public Released Version
  35. -- 02/25/2009 1.1 Replaced reference to std_2008 with a reference
  36. -- to ieee_proposed.standard_additions.all ;
  37. -- 03/01/2011 2.0 STANDARD VERSION
  38. -- Fixed abstraction by moving RandomParmType to RandomPkg.vhd
  39. -- 4/2013 2013.04 No Changes
  40. -- 5/2013 2013.05 No Changes
  41. -- 1/2015 2015.01 Changed Assert/Report to Alert
  42. -- 6/2015 2015.06 Changed GenRandSeed to impure
  43. --
  44. --
  45. -- Copyright (c) 2008 - 2015 by SynthWorks Design Inc. All rights reserved.
  46. --
  47. -- Verbatim copies of this source file may be used and
  48. -- distributed without restriction.
  49. --
  50. -- This source file is free software; you can redistribute it
  51. -- and/or modify it under the terms of the ARTISTIC License
  52. -- as published by The Perl Foundation; either version 2.0 of
  53. -- the License, or (at your option) any later version.
  54. --
  55. -- This source is distributed in the hope that it will be
  56. -- useful, but WITHOUT ANY WARRANTY; without even the implied
  57. -- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  58. -- PURPOSE. See the Artistic License for details.
  59. --
  60. -- You should have received a copy of the license with this source.
  61. -- If not download it from,
  62. -- http://www.perlfoundation.org/artistic_license_2_0
  63. --
  64. library ieee ;
  65. use ieee.math_real.all ;
  66. use std.textio.all ;
  67. use work.OsvvmGlobalPkg.all ;
  68. use work.AlertLogPkg.all ;
  69. -- comment out following 2 lines with VHDL-2008. Leave in for VHDL-2002
  70. -- library ieee_proposed ; -- remove with VHDL-2008
  71. -- use ieee_proposed.standard_additions.all ; -- remove with VHDL-2008
  72. package RandomBasePkg is
  73. -- RandomSeedType and Uniform can be replaced by any procedure that
  74. -- produces a uniform distribution with 0 <= Value < 1 or 0 < Value < 1
  75. -- and maintains the same call interface
  76. type RandomSeedType is array (1 to 2) of integer ;
  77. procedure Uniform (Result : out real ; Seed : inout RandomSeedType) ;
  78. -- Translate from integer_vector, integer, or string to RandomSeedType
  79. -- Required by RandomPkg.InitSeed
  80. -- GenRandSeed makes sure all values are in a valid range
  81. impure function GenRandSeed(IV : integer_vector) return RandomSeedType ;
  82. impure function GenRandSeed(I : integer) return RandomSeedType ;
  83. impure function GenRandSeed(S : string) return RandomSeedType ;
  84. -- IO for RandomSeedType. If use subtype, then create aliases here
  85. -- in a similar fashion VHDL-2008 std_logic_textio.
  86. -- Not required by RandomPkg
  87. function to_string(A : RandomSeedType) return string ;
  88. procedure write(variable L: inout line ; A : RandomSeedType ) ;
  89. procedure read (variable L: inout line ; A : out RandomSeedType ; good : out boolean ) ;
  90. procedure read (variable L: inout line ; A : out RandomSeedType ) ;
  91. end RandomBasePkg ;
  92. --- ///////////////////////////////////////////////////////////////////////////
  93. --- ///////////////////////////////////////////////////////////////////////////
  94. --- ///////////////////////////////////////////////////////////////////////////
  95. package body RandomBasePkg is
  96. -----------------------------------------------------------------
  97. -- Uniform
  98. -- Generate a random number with a Uniform distribution
  99. -- Required by RandomPkg. All randomization is derived from here.
  100. -- Value produced must be either:
  101. -- 0 <= Value < 1 or 0 < Value < 1
  102. --
  103. -- Current version uses ieee.math_real.Uniform
  104. -- This abstraction allows higher precision version
  105. -- of a uniform distribution to be used provided
  106. --
  107. procedure Uniform (
  108. Result : out real ;
  109. Seed : inout RandomSeedType
  110. ) is
  111. begin
  112. ieee.math_real.Uniform (Seed(Seed'left), Seed(Seed'right), Result) ;
  113. end procedure Uniform ;
  114. -----------------------------------------------------------------
  115. -- GenRandSeed
  116. -- Convert integer_vector to RandomSeedType
  117. -- Uniform requires two seed values of the form:
  118. -- 1 <= SEED1 <= 2147483562; 1 <= SEED2 <= 2147483398
  119. --
  120. -- if 2 seed values are passed to GenRandSeed and they are
  121. -- in the above range, then they must remain unmodified.
  122. --
  123. impure function GenRandSeed(IV : integer_vector) return RandomSeedType is
  124. alias iIV : integer_vector(1 to IV'length) is IV ;
  125. variable Seed1 : integer ;
  126. variable Seed2 : integer ;
  127. constant SEED1_MAX : integer := 2147483562 ;
  128. constant SEED2_MAX : integer := 2147483398 ;
  129. begin
  130. if iIV'Length <= 0 then -- no seed
  131. Alert(OSVVM_ALERTLOG_ID, "RandomBasePkg.GenRandSeed received NULL integer_vector", FAILURE) ;
  132. return (3, 17) ; -- if continue seed = (3, 17)
  133. elsif iIV'Length = 1 then -- one seed value
  134. -- inefficient handling, but condition is unlikely
  135. return GenRandSeed(iIV(1)) ; -- generate a seed
  136. else -- only use the left two values
  137. -- 1 <= SEED1 <= 2147483562
  138. -- mod returns 0 to MAX-1, the -1 adjusts legal values, +1 adjusts them back
  139. Seed1 := ((iIV(1)-1) mod SEED1_MAX) + 1 ;
  140. -- 1 <= SEED2 <= 2147483398
  141. Seed2 := ((iIV(2)-1) mod SEED2_MAX) + 1 ;
  142. return (Seed1, Seed2) ;
  143. end if ;
  144. end function GenRandSeed ;
  145. -----------------------------------------------------------------
  146. -- GenRandSeed
  147. -- transform a single integer into the internal seed
  148. --
  149. impure function GenRandSeed(I : integer) return RandomSeedType is
  150. variable result : integer_vector(1 to 2) ;
  151. begin
  152. result(1) := I ;
  153. result(2) := I/3 + 1 ;
  154. return GenRandSeed(result) ; -- make value ranges legal
  155. end function GenRandSeed ;
  156. -----------------------------------------------------------------
  157. -- GenRandSeed
  158. -- transform a string value into the internal seed
  159. -- usage: RV.GenRandSeed(RV'instance_path));
  160. --
  161. impure function GenRandSeed(S : string) return RandomSeedType is
  162. constant LEN : integer := S'length ;
  163. constant HALF_LEN : integer := LEN/2 ;
  164. alias revS : string(LEN downto 1) is S ;
  165. variable result : integer_vector(1 to 2) ;
  166. variable temp : integer := 0 ;
  167. begin
  168. for i in 1 to HALF_LEN loop
  169. temp := (temp + character'pos(revS(i))) mod (integer'right - 2**8) ;
  170. end loop ;
  171. result(1) := temp ;
  172. for i in HALF_LEN + 1 to LEN loop
  173. temp := (temp + character'pos(revS(i))) mod (integer'right - 2**8) ;
  174. end loop ;
  175. result(2) := temp ;
  176. return GenRandSeed(result) ; -- make value ranges legal
  177. end function GenRandSeed ;
  178. -----------------------------------------------------------------
  179. function to_string(A : RandomSeedType) return string is
  180. begin
  181. return to_string(A(A'left)) & " " & to_string(A(A'right)) ;
  182. end function to_string ;
  183. -----------------------------------------------------------------
  184. procedure write(variable L: inout line ; A : RandomSeedType ) is
  185. begin
  186. write(L, to_string(A)) ;
  187. end procedure ;
  188. -----------------------------------------------------------------
  189. procedure read(variable L: inout line ; A : out RandomSeedType ; good : out boolean ) is
  190. variable iReadValid : boolean ;
  191. begin
  192. for i in A'range loop
  193. read(L, A(i), iReadValid) ;
  194. exit when not iReadValid ;
  195. end loop ;
  196. good := iReadValid ;
  197. end procedure read ;
  198. -----------------------------------------------------------------
  199. procedure read(variable L: inout line ; A : out RandomSeedType ) is
  200. variable ReadValid : boolean ;
  201. begin
  202. read(L, A, ReadValid) ;
  203. AlertIfNot(ReadValid, OSVVM_ALERTLOG_ID, "RandomBasePkg.read[line, RandomSeedType] failed", FAILURE) ;
  204. end procedure read ;
  205. end RandomBasePkg ;