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.

417 lines
13 KiB

  1. --
  2. -- File Name: SortListPkg_int.vhd
  3. -- Design Unit Name: SortListPkg_int
  4. -- Revision: STANDARD VERSION
  5. --
  6. -- Maintainer: Jim Lewis email: jim@synthworks.com
  7. -- Contributor(s):
  8. -- Jim Lewis jim@synthworks.com
  9. --
  10. -- Description:
  11. -- Sorting utility for array of scalars
  12. -- Uses protected type so as to shrink and expand the data structure
  13. --
  14. -- Developed for:
  15. -- SynthWorks Design Inc.
  16. -- VHDL Training Classes
  17. -- 11898 SW 128th Ave. Tigard, Or 97223
  18. -- http://www.SynthWorks.com
  19. --
  20. -- Revision History:
  21. -- Date Version Description
  22. -- 06/2008: 0.1 Initial revision
  23. -- Numerous revisions for VHDL Testbenches and Verification
  24. -- 02/2009: 1.0 First Public Released Version
  25. -- 02/25/2009 1.1 Replaced reference to std_2008 with a reference to
  26. -- ieee_proposed.standard_additions.all ;
  27. -- 06/16/2010 1.2 Added EraseList parameter to to_array
  28. -- 3/2011 2.0 added inside as non protected type
  29. -- 6/2011 2.1 added sort as non protected type
  30. -- 4/2013 2013.04 No Changes
  31. -- 5/2013 2013.05 No changes of substance.
  32. -- Deleted extra variable declaration in procedure remove
  33. -- 1/2014 2014.01 Added RevSort. Added AllowDuplicate paramter to Add procedure
  34. -- 1/2015 2015.01 Changed Assert/Report to Alert
  35. -- 11/2016 2016.11 Revised Add. When AllowDuplicate, add a matching value last.
  36. --
  37. --
  38. --
  39. -- Copyright (c) 2008 - 2016 by SynthWorks Design Inc. All rights reserved.
  40. --
  41. -- Verbatim copies of this source file may be used and
  42. -- distributed without restriction.
  43. --
  44. -- This source file is free software; you can redistribute it
  45. -- and/or modify it under the terms of the ARTISTIC License
  46. -- as published by The Perl Foundation; either version 2.0 of
  47. -- the License, or (at your option) any later version.
  48. --
  49. -- This source is distributed in the hope that it will be
  50. -- useful, but WITHOUT ANY WARRANTY; without even the implied
  51. -- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  52. -- PURPOSE. See the Artistic License for details.
  53. --
  54. -- You should have received a copy of the license with this source.
  55. -- If not download it from,
  56. -- http://www.perlfoundation.org/artistic_license_2_0
  57. --
  58. use work.OsvvmGlobalPkg.all ;
  59. use work.AlertLogPkg.all ;
  60. use std.textio.all ;
  61. library ieee ;
  62. use ieee.std_logic_1164.all ;
  63. use ieee.numeric_std.all ;
  64. use ieee.std_logic_textio.all ;
  65. -- comment out following 2 lines with VHDL-2008. Leave in for VHDL-2002
  66. -- library ieee_proposed ; -- remove with VHDL-2008
  67. -- use ieee_proposed.standard_additions.all ; -- remove with VHDL-2008
  68. package SortListPkg_int is
  69. -- with VHDL-2008, convert package to generic package
  70. -- convert subtypes ElementType and ArrayofElementType to generics
  71. -- package SortListGenericPkg is
  72. subtype ElementType is integer ;
  73. subtype ArrayofElementType is integer_vector ;
  74. impure function inside (constant E : ElementType; constant A : in ArrayofElementType) return boolean ;
  75. impure function sort (constant A : in ArrayofElementType) return ArrayofElementType ;
  76. impure function revsort (constant A : in ArrayofElementType) return ArrayofElementType ;
  77. type SortListPType is protected
  78. procedure add ( constant A : in ElementType ; constant AllowDuplicate : Boolean := FALSE ) ;
  79. procedure add ( constant A : in ArrayofElementType ) ;
  80. procedure add ( constant A : in ArrayofElementType ; Min, Max : ElementType ) ;
  81. procedure add ( variable A : inout SortListPType ) ;
  82. -- Count items in list
  83. impure function count return integer ;
  84. impure function find_index ( constant A : ElementType) return integer ;
  85. impure function inside (constant A : ElementType) return boolean ;
  86. procedure insert ( constant A : in ElementType; constant index : in integer := 1 ) ;
  87. impure function get ( constant index : in integer := 1 ) return ElementType ;
  88. procedure erase ;
  89. impure function Empty return boolean ;
  90. procedure print ;
  91. procedure remove ( constant A : in ElementType ) ;
  92. procedure remove ( constant A : in ArrayofElementType ) ;
  93. procedure remove ( variable A : inout SortListPType ) ;
  94. impure function to_array (constant EraseList : boolean := FALSE) return ArrayofElementType ;
  95. impure function to_rev_array (constant EraseList : boolean := FALSE) return ArrayofElementType ;
  96. end protected SortListPType ;
  97. end SortListPkg_int ;
  98. --- ///////////////////////////////////////////////////////////////////////////
  99. --- ///////////////////////////////////////////////////////////////////////////
  100. --- ///////////////////////////////////////////////////////////////////////////
  101. package body SortListPkg_int is
  102. impure function inside (constant E : ElementType; constant A : in ArrayofElementType) return boolean is
  103. begin
  104. for i in A'range loop
  105. if E = A(i) then
  106. return TRUE ;
  107. end if ;
  108. end loop ;
  109. return FALSE ;
  110. end function inside ;
  111. type SortListPType is protected body
  112. type ListType ;
  113. type ListPointerType is access ListType ;
  114. type ListType is record
  115. A : ElementType ;
  116. -- item_num : integer ;
  117. NextPtr : ListPointerType ;
  118. -- PrevPtr : ListPointerType ;
  119. end record ;
  120. variable HeadPointer : ListPointerType := NULL ;
  121. -- variable TailPointer : ListPointerType := NULL ;
  122. procedure add ( constant A : in ElementType ; constant AllowDuplicate : Boolean := FALSE ) is
  123. variable CurPtr, tempPtr : ListPointerType ;
  124. begin
  125. if HeadPointer = NULL then
  126. HeadPointer := new ListType'(A, NULL) ;
  127. elsif A = HeadPointer.A then -- ignore duplicates
  128. if AllowDuplicate then
  129. tempPtr := HeadPointer ;
  130. HeadPointer := new ListType'(A, tempPtr) ;
  131. end if ;
  132. elsif A < HeadPointer.A then
  133. tempPtr := HeadPointer ;
  134. HeadPointer := new ListType'(A, tempPtr) ;
  135. else
  136. CurPtr := HeadPointer ;
  137. AddLoop : loop
  138. exit AddLoop when CurPtr.NextPtr = NULL ;
  139. exit AddLoop when A < CurPtr.NextPtr.A ;
  140. if A = CurPtr.NextPtr.A then
  141. -- if AllowDuplicate then -- changed s.t. insert at after match rather than before
  142. -- exit AddLoop ; -- insert
  143. -- else
  144. if not AllowDuplicate then
  145. return ; -- return without insert
  146. end if;
  147. end if ;
  148. CurPtr := CurPtr.NextPtr ;
  149. end loop AddLoop ;
  150. tempPtr := CurPtr.NextPtr ;
  151. CurPtr.NextPtr := new ListType'(A, tempPtr) ;
  152. end if ;
  153. end procedure add ;
  154. procedure add ( constant A : in ArrayofElementType ) is
  155. begin
  156. for i in A'range loop
  157. add(A(i)) ;
  158. end loop ;
  159. end procedure add ;
  160. procedure add ( constant A : in ArrayofElementType ; Min, Max : ElementType ) is
  161. begin
  162. for i in A'range loop
  163. if A(i) >= Min and A(i) <= Max then
  164. add(A(i)) ;
  165. end if ;
  166. end loop ;
  167. end procedure add ;
  168. procedure add ( variable A : inout SortListPType ) is
  169. begin
  170. for i in 1 to A.Count loop
  171. add(A.Get(i)) ;
  172. end loop ;
  173. end procedure add ;
  174. -- Count items in list
  175. impure function count return integer is
  176. variable result : positive := 1 ;
  177. variable CurPtr : ListPointerType ;
  178. begin
  179. if HeadPointer = NULL then
  180. return 0 ;
  181. else
  182. CurPtr := HeadPointer ;
  183. loop
  184. exit when CurPtr.NextPtr = NULL ;
  185. result := result + 1 ;
  186. CurPtr := CurPtr.NextPtr ;
  187. end loop ;
  188. return result ;
  189. end if ;
  190. end function count ;
  191. impure function find_index (constant A : ElementType) return integer is
  192. variable result : positive := 2 ;
  193. variable CurPtr : ListPointerType ;
  194. begin
  195. if HeadPointer = NULL then
  196. return 0 ;
  197. elsif A <= HeadPointer.A then
  198. return 1 ;
  199. else
  200. CurPtr := HeadPointer ;
  201. loop
  202. exit when CurPtr.NextPtr = NULL ;
  203. exit when A <= CurPtr.NextPtr.A ;
  204. result := result + 1 ;
  205. CurPtr := CurPtr.NextPtr ;
  206. end loop ;
  207. return result ;
  208. end if ;
  209. end function find_index ;
  210. impure function inside (constant A : ElementType) return boolean is
  211. variable CurPtr : ListPointerType ;
  212. begin
  213. if HeadPointer = NULL then
  214. return FALSE ;
  215. end if ;
  216. if A = HeadPointer.A then
  217. return TRUE ;
  218. else
  219. CurPtr := HeadPointer ;
  220. loop
  221. exit when CurPtr.NextPtr = NULL ;
  222. exit when A < CurPtr.NextPtr.A ;
  223. if A = CurPtr.NextPtr.A then
  224. return TRUE ; -- exit
  225. end if;
  226. CurPtr := CurPtr.NextPtr ;
  227. end loop ;
  228. end if ;
  229. return FALSE ;
  230. end function inside ;
  231. procedure insert( constant A : in ElementType; constant index : in integer := 1 ) is
  232. variable CurPtr, tempPtr : ListPointerType ;
  233. begin
  234. if index <= 1 then
  235. tempPtr := HeadPointer ;
  236. HeadPointer := new ListType'(A, tempPtr) ;
  237. else
  238. CurPtr := HeadPointer ;
  239. for i in 3 to index loop
  240. exit when CurPtr.NextPtr = NULL ; -- end of list
  241. CurPtr := CurPtr.NextPtr ;
  242. end loop ;
  243. tempPtr := CurPtr.NextPtr ;
  244. CurPtr.NextPtr := new ListType'(A, tempPtr) ;
  245. end if;
  246. end procedure insert ;
  247. impure function get ( constant index : in integer := 1 ) return ElementType is
  248. variable CurPtr : ListPointerType ;
  249. begin
  250. if index > Count then
  251. Alert(OSVVM_ALERTLOG_ID, "SortLIstPkg_int.get index out of range", FAILURE) ;
  252. return ElementType'left ;
  253. elsif HeadPointer = NULL then
  254. return ElementType'left ;
  255. elsif index <= 1 then
  256. return HeadPointer.A ;
  257. else
  258. CurPtr := HeadPointer ;
  259. for i in 2 to index loop
  260. CurPtr := CurPtr.NextPtr ;
  261. end loop ;
  262. return CurPtr.A ;
  263. end if;
  264. end function get ;
  265. procedure erase (variable CurPtr : inout ListPointerType ) is
  266. begin
  267. if CurPtr.NextPtr /= NULL then
  268. erase (CurPtr.NextPtr) ;
  269. end if ;
  270. deallocate (CurPtr) ;
  271. end procedure erase ;
  272. procedure erase is
  273. begin
  274. if HeadPointer /= NULL then
  275. erase(HeadPointer) ;
  276. -- deallocate (HeadPointer) ;
  277. HeadPointer := NULL ;
  278. end if;
  279. end procedure erase ;
  280. impure function Empty return boolean is
  281. begin
  282. return HeadPointer = NULL ;
  283. end Empty ;
  284. procedure print is
  285. variable buf : line ;
  286. variable CurPtr : ListPointerType ;
  287. begin
  288. if HeadPointer = NULL then
  289. write (buf, string'("( )")) ;
  290. else
  291. CurPtr := HeadPointer ;
  292. write (buf, string'("(")) ;
  293. loop
  294. write (buf, CurPtr.A) ;
  295. exit when CurPtr.NextPtr = NULL ;
  296. write (buf, string'(", ")) ;
  297. CurPtr := CurPtr.NextPtr ;
  298. end loop ;
  299. write (buf, string'(")")) ;
  300. end if ;
  301. writeline(OUTPUT, buf) ;
  302. end procedure print ;
  303. procedure remove ( constant A : in ElementType ) is
  304. variable CurPtr, tempPtr : ListPointerType ;
  305. begin
  306. if HeadPointer = NULL then
  307. return ;
  308. elsif A = HeadPointer.A then
  309. tempPtr := HeadPointer ;
  310. HeadPointer := HeadPointer.NextPtr ;
  311. deallocate (tempPtr) ;
  312. else
  313. CurPtr := HeadPointer ;
  314. loop
  315. exit when CurPtr.NextPtr = NULL ;
  316. if A = CurPtr.NextPtr.A then
  317. tempPtr := CurPtr.NextPtr ;
  318. CurPtr.NextPtr := CurPtr.NextPtr.NextPtr ;
  319. deallocate (tempPtr) ;
  320. exit ;
  321. end if ;
  322. exit when A < CurPtr.NextPtr.A ;
  323. CurPtr := CurPtr.NextPtr ;
  324. end loop ;
  325. end if ;
  326. end procedure remove ;
  327. procedure remove ( constant A : in ArrayofElementType ) is
  328. begin
  329. for i in A'range loop
  330. remove(A(i)) ;
  331. end loop ;
  332. end procedure remove ;
  333. procedure remove ( variable A : inout SortListPType ) is
  334. begin
  335. for i in 1 to A.Count loop
  336. remove(A.Get(i)) ;
  337. end loop ;
  338. end procedure remove ;
  339. impure function to_array (constant EraseList : boolean := FALSE) return ArrayofElementType is
  340. variable result : ArrayofElementType(1 to Count) ;
  341. begin
  342. for i in 1 to Count loop
  343. result(i) := Get(i) ;
  344. end loop ;
  345. if EraseList then
  346. erase ;
  347. end if ;
  348. return result ;
  349. end function to_array ;
  350. impure function to_rev_array (constant EraseList : boolean := FALSE) return ArrayofElementType is
  351. variable result : ArrayofElementType(Count downto 1) ;
  352. begin
  353. for i in 1 to Count loop
  354. result(i) := Get(i) ;
  355. end loop ;
  356. if EraseList then
  357. erase ;
  358. end if ;
  359. return result ;
  360. end function to_rev_array ;
  361. end protected body SortListPType ;
  362. impure function sort (constant A : in ArrayofElementType) return ArrayofElementType is
  363. variable Result : SortListPType ;
  364. begin
  365. for i in A'range loop
  366. Result.Add(A(i), TRUE) ;
  367. end loop ;
  368. return Result.to_array(EraseList => TRUE) ;
  369. end function sort ;
  370. impure function revsort (constant A : in ArrayofElementType) return ArrayofElementType is
  371. variable Result : SortListPType ;
  372. begin
  373. for i in A'range loop
  374. Result.Add(A(i), TRUE) ;
  375. end loop ;
  376. return Result.to_rev_array(EraseList => TRUE) ;
  377. end function revsort ;
  378. end SortListPkg_int ;