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.

259 lines
8.1 KiB

  1. -- Copyright (c) 2014 - 2022 by Torsten Meissner
  2. --
  3. -- Licensed under the Apache License, Version 2.0 (the "License");
  4. -- you may not use this file except in compliance with the License.
  5. -- You may obtain a copy of the License at
  6. --
  7. -- https://www.apache.org/licenses/LICENSE-2.0
  8. --
  9. -- Unless required by applicable law or agreed to in writing, software
  10. -- distributed under the License is distributed on an "AS IS" BASIS,
  11. -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. -- See the License for the specific language governing permissions and
  13. -- limitations under the License.
  14. library ieee;
  15. use ieee.std_logic_1164.all;
  16. package DictP is
  17. generic (
  18. type KEY_TYPE;
  19. type VALUE_TYPE;
  20. function key_to_string(d : in KEY_TYPE) return string;
  21. function value_to_string(d : in VALUE_TYPE) return string
  22. );
  23. type t_dict_key_ptr is access KEY_TYPE;
  24. type t_dict_data_ptr is access VALUE_TYPE;
  25. type t_dict_dir is (UP, DOWN);
  26. type t_dict_iter is (TAIL, HEAD);
  27. type t_dict is protected
  28. procedure set (constant key : in KEY_TYPE; constant data : in VALUE_TYPE);
  29. procedure get (constant key : in KEY_TYPE; data : out VALUE_TYPE);
  30. procedure del (constant key : in KEY_TYPE);
  31. procedure init (constant logging : in boolean := false);
  32. procedure clear;
  33. impure function hasKey (constant key : KEY_TYPE) return boolean;
  34. impure function size return natural;
  35. procedure setIter(constant start : in t_dict_iter := TAIL);
  36. impure function iter (constant dir : t_dict_dir := UP) return KEY_TYPE;
  37. impure function get (constant key : KEY_TYPE) return VALUE_TYPE;
  38. end protected t_dict;
  39. procedure merge(d0 : inout t_dict; d1 : inout t_dict; d : inout t_dict);
  40. end package DictP;
  41. package body DictP is
  42. type t_dict is protected body
  43. type t_entry;
  44. type t_entry_ptr is access t_entry;
  45. type t_entry is record
  46. key : t_dict_key_ptr;
  47. data : t_dict_data_ptr;
  48. last_entry : t_entry_ptr;
  49. next_entry : t_entry_ptr;
  50. end record t_entry;
  51. variable v_tail : t_entry_ptr := null;
  52. variable v_head : t_entry_ptr := null;
  53. variable v_iterator : t_entry_ptr := null;
  54. variable v_size : natural := 0;
  55. variable v_logging : boolean := false;
  56. impure function find (constant key : KEY_TYPE) return t_entry_ptr;
  57. procedure set (constant key : in KEY_TYPE; constant data : in VALUE_TYPE) is
  58. variable v_entry : t_entry_ptr := find(key);
  59. begin
  60. if (v_entry = null) then
  61. if (v_head /= null) then
  62. v_entry := new t_entry;
  63. v_entry.key := new KEY_TYPE'(key);
  64. v_entry.data := new VALUE_TYPE'(data);
  65. v_entry.last_entry := v_head;
  66. v_entry.next_entry := null;
  67. v_head := v_entry;
  68. v_head.last_entry.next_entry := v_head;
  69. else
  70. v_head := new t_entry;
  71. v_head.key := new KEY_TYPE'(key);
  72. v_head.data := new VALUE_TYPE'(data);
  73. v_head.last_entry := null;
  74. v_head.next_entry := null;
  75. v_tail := v_head;
  76. end if;
  77. if (v_logging) then
  78. report t_dict'instance_name & ": Add key " & key_to_string(key) & " with value " & value_to_string(data) & " to dictionary";
  79. end if;
  80. v_size := v_size + 1;
  81. else
  82. v_entry.data.all := data;
  83. if (v_logging) then
  84. report t_dict'instance_name & ": Set value of key " & key_to_string(key) & " to 0x" & value_to_string(data);
  85. end if;
  86. end if;
  87. end procedure set;
  88. procedure get (constant key : in KEY_TYPE; data : out VALUE_TYPE) is
  89. variable v_entry : t_entry_ptr := find(key);
  90. begin
  91. assert v_entry /= null
  92. report t_dict'instance_name & ": key " & key_to_string(key) & " not found"
  93. severity failure;
  94. if(v_entry /= null) then
  95. data := v_entry.data.all;
  96. if v_logging then
  97. report t_dict'instance_name & ": Got key " & key_to_string(key) & " with value " & value_to_string(v_entry.data.all);
  98. end if;
  99. end if;
  100. end procedure get;
  101. procedure del (constant key : in KEY_TYPE) is
  102. variable v_entry : t_entry_ptr := find(key);
  103. begin
  104. assert v_entry /= null
  105. report t_dict'instance_name & ": key " & key_to_string(key) & " not found"
  106. severity failure;
  107. if (v_entry /= null) then
  108. -- remove head entry
  109. if(v_entry.next_entry = null and v_entry.last_entry /= null) then
  110. v_entry.last_entry.next_entry := null;
  111. v_head := v_entry.last_entry;
  112. -- remove start entry
  113. elsif(v_entry.next_entry /= null and v_entry.last_entry = null) then
  114. v_entry.next_entry.last_entry := null;
  115. --v_entry.next_entry.last_entry := v_entry.last_entry;
  116. v_tail := v_entry.next_entry;
  117. -- remove from between
  118. elsif(v_entry.next_entry /= null and v_entry.last_entry /= null) then
  119. v_entry.last_entry.next_entry := v_entry.next_entry;
  120. v_entry.next_entry.last_entry := v_entry.last_entry;
  121. end if;
  122. deallocate(v_entry.key);
  123. deallocate(v_entry.data);
  124. deallocate(v_entry);
  125. v_size := v_size - 1;
  126. end if;
  127. end procedure del;
  128. impure function find (constant key : KEY_TYPE) return t_entry_ptr is
  129. variable v_entry : t_entry_ptr := v_head;
  130. begin
  131. while (v_entry /= null) loop
  132. if(v_entry.key.all = key) then
  133. return v_entry;
  134. end if;
  135. v_entry := v_entry.last_entry;
  136. end loop;
  137. return null;
  138. end function find;
  139. procedure clear is
  140. variable v_entry : t_entry_ptr := v_head;
  141. variable v_entry_d : t_entry_ptr;
  142. begin
  143. while (v_entry /= null) loop
  144. v_entry_d := v_entry;
  145. del(v_entry_d.key.all);
  146. v_entry := v_entry.last_entry;
  147. end loop;
  148. end procedure clear;
  149. impure function hasKey (constant key : KEY_TYPE) return boolean is
  150. begin
  151. return find(key) /= null;
  152. end function hasKey;
  153. impure function size return natural is
  154. begin
  155. return v_size;
  156. end function size;
  157. procedure init (constant logging : in boolean := false) is
  158. begin
  159. v_logging := logging;
  160. end procedure init;
  161. procedure setIter (constant start : in t_dict_iter := TAIL) is
  162. begin
  163. if (start = TAIL) then
  164. v_iterator := v_tail;
  165. else
  166. v_iterator := v_head;
  167. end if;
  168. end procedure setIter;
  169. impure function iter (constant dir : t_dict_dir := UP) return KEY_TYPE is
  170. variable v_key : t_dict_key_ptr := null;
  171. begin
  172. v_key := new KEY_TYPE'(v_iterator.key.all);
  173. if (dir = UP) then
  174. if (v_iterator.next_entry /= null) then
  175. v_iterator := v_iterator.next_entry;
  176. end if;
  177. else
  178. if (v_iterator.last_entry /= null) then
  179. v_iterator := v_iterator.last_entry;
  180. end if;
  181. end if;
  182. return v_key.all;
  183. end function iter;
  184. impure function get(constant key : KEY_TYPE) return VALUE_TYPE is
  185. variable v_entry : t_entry_ptr := find(key);
  186. begin
  187. assert v_entry /= null
  188. report t_dict'instance_name & ": key " & key_to_string(key) & " not found"
  189. severity failure;
  190. return v_entry.data.all;
  191. end function get;
  192. end protected body t_dict;
  193. procedure merge(d0 : inout t_dict; d1 : inout t_dict; d : inout t_dict) is
  194. variable v_key : t_dict_key_ptr;
  195. variable v_data : t_dict_data_ptr;
  196. begin
  197. if (d0.size > 0) then
  198. d0.setIter(TAIL);
  199. for i in 0 to d0.size-1 loop
  200. v_key := new KEY_TYPE'(d0.iter(UP));
  201. v_data := new VALUE_TYPE'(d0.get(v_key.all));
  202. d.set(v_key.all, v_data.all);
  203. end loop;
  204. end if;
  205. if (d1.size > 0) then
  206. d1.setIter(TAIL);
  207. for i in 0 to d1.size-1 loop
  208. v_key := new KEY_TYPE'(d1.iter(UP));
  209. v_data := new VALUE_TYPE'(d1.get(v_key.all));
  210. d.set(v_key.all, v_data.all);
  211. end loop;
  212. end if;
  213. end procedure merge;
  214. end package body DictP;