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.

409 lines
13 KiB

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