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.

243 lines
7.5 KiB

  1. library ieee;
  2. use ieee.std_logic_1164.all;
  3. package DictP is
  4. generic (
  5. type KEY_TYPE;
  6. type VALUE_TYPE;
  7. function key_to_string(d : in KEY_TYPE) return string;
  8. function value_to_string(d : in VALUE_TYPE) return string
  9. );
  10. type t_dict_key_ptr is access KEY_TYPE;
  11. type t_dict_data_ptr is access VALUE_TYPE;
  12. type t_dict_dir is (UP, DOWN);
  13. type t_dict_iter is (TAIL, HEAD);
  14. type t_dict is protected
  15. procedure set (constant key : in KEY_TYPE; constant data : in VALUE_TYPE);
  16. procedure get (constant key : in KEY_TYPE; data : out VALUE_TYPE);
  17. procedure del (constant key : in KEY_TYPE);
  18. procedure init (constant logging : in boolean := false);
  19. procedure clear;
  20. impure function hasKey (constant key : KEY_TYPE) return boolean;
  21. impure function size return natural;
  22. procedure setIter(constant start : in t_dict_iter := TAIL);
  23. impure function iter (constant dir : t_dict_dir := UP) return KEY_TYPE;
  24. impure function get (constant key : KEY_TYPE) return VALUE_TYPE;
  25. end protected t_dict;
  26. procedure merge(d0 : inout t_dict; d1 : inout t_dict; d : inout t_dict);
  27. end package DictP;
  28. package body DictP is
  29. type t_dict is protected body
  30. type t_entry;
  31. type t_entry_ptr is access t_entry;
  32. type t_entry is record
  33. key : t_dict_key_ptr;
  34. data : t_dict_data_ptr;
  35. last_entry : t_entry_ptr;
  36. next_entry : t_entry_ptr;
  37. end record t_entry;
  38. variable v_tail : t_entry_ptr := null;
  39. variable v_head : t_entry_ptr := null;
  40. variable v_iterator : t_entry_ptr := null;
  41. variable v_size : natural := 0;
  42. variable v_logging : boolean := false;
  43. impure function find (constant key : KEY_TYPE) return t_entry_ptr;
  44. procedure set (constant key : in KEY_TYPE; constant data : in VALUE_TYPE) is
  45. variable v_entry : t_entry_ptr := find(key);
  46. begin
  47. if (v_entry = null) then
  48. if (v_head /= null) then
  49. v_entry := new t_entry;
  50. v_entry.key := new KEY_TYPE'(key);
  51. v_entry.data := new VALUE_TYPE'(data);
  52. v_entry.last_entry := v_head;
  53. v_entry.next_entry := null;
  54. v_head := v_entry;
  55. v_head.last_entry.next_entry := v_head;
  56. else
  57. v_head := new t_entry;
  58. v_head.key := new KEY_TYPE'(key);
  59. v_head.data := new VALUE_TYPE'(data);
  60. v_head.last_entry := null;
  61. v_head.next_entry := null;
  62. v_tail := v_head;
  63. end if;
  64. if (v_logging) then
  65. report t_dict'instance_name & ": Add key " & key_to_string(key) & " with value " & value_to_string(data) & " to dictionary";
  66. end if;
  67. v_size := v_size + 1;
  68. else
  69. v_entry.data.all := data;
  70. if (v_logging) then
  71. report t_dict'instance_name & ": Set value of key " & key_to_string(key) & " to 0x" & value_to_string(data);
  72. end if;
  73. end if;
  74. end procedure set;
  75. procedure get (constant key : in KEY_TYPE; data : out VALUE_TYPE) is
  76. variable v_entry : t_entry_ptr := find(key);
  77. begin
  78. assert v_entry /= null
  79. report t_dict'instance_name & ": key " & key_to_string(key) & " not found"
  80. severity failure;
  81. if(v_entry /= null) then
  82. data := v_entry.data.all;
  83. if v_logging then
  84. report t_dict'instance_name & ": Got key " & key_to_string(key) & " with value " & value_to_string(v_entry.data.all);
  85. end if;
  86. end if;
  87. end procedure get;
  88. procedure del (constant key : in KEY_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. -- remove head entry
  96. if(v_entry.next_entry = null and v_entry.last_entry /= null) then
  97. v_entry.last_entry.next_entry := null;
  98. v_head := v_entry.last_entry;
  99. -- remove start entry
  100. elsif(v_entry.next_entry /= null and v_entry.last_entry = null) then
  101. v_entry.next_entry.last_entry := null;
  102. --v_entry.next_entry.last_entry := v_entry.last_entry;
  103. v_tail := v_entry.next_entry;
  104. -- remove from between
  105. elsif(v_entry.next_entry /= null and v_entry.last_entry /= null) then
  106. v_entry.last_entry.next_entry := v_entry.next_entry;
  107. v_entry.next_entry.last_entry := v_entry.last_entry;
  108. end if;
  109. deallocate(v_entry.key);
  110. deallocate(v_entry.data);
  111. deallocate(v_entry);
  112. v_size := v_size - 1;
  113. end if;
  114. end procedure del;
  115. impure function find (constant key : KEY_TYPE) return t_entry_ptr is
  116. variable v_entry : t_entry_ptr := v_head;
  117. begin
  118. while (v_entry /= null) loop
  119. if(v_entry.key.all = key) then
  120. return v_entry;
  121. end if;
  122. v_entry := v_entry.last_entry;
  123. end loop;
  124. return null;
  125. end function find;
  126. procedure clear is
  127. variable v_entry : t_entry_ptr := v_head;
  128. variable v_entry_d : t_entry_ptr;
  129. begin
  130. while (v_entry /= null) loop
  131. v_entry_d := v_entry;
  132. del(v_entry_d.key.all);
  133. v_entry := v_entry.last_entry;
  134. end loop;
  135. end procedure clear;
  136. impure function hasKey (constant key : KEY_TYPE) return boolean is
  137. begin
  138. return find(key) /= null;
  139. end function hasKey;
  140. impure function size return natural is
  141. begin
  142. return v_size;
  143. end function size;
  144. procedure init (constant logging : in boolean := false) is
  145. begin
  146. v_logging := logging;
  147. end procedure init;
  148. procedure setIter (constant start : in t_dict_iter := TAIL) is
  149. begin
  150. if (start = TAIL) then
  151. v_iterator := v_tail;
  152. else
  153. v_iterator := v_head;
  154. end if;
  155. end procedure setIter;
  156. impure function iter (constant dir : t_dict_dir := UP) return KEY_TYPE is
  157. variable v_key : t_dict_key_ptr := null;
  158. begin
  159. v_key := new KEY_TYPE'(v_iterator.key.all);
  160. if (dir = UP) then
  161. if (v_iterator.next_entry /= null) then
  162. v_iterator := v_iterator.next_entry;
  163. end if;
  164. else
  165. if (v_iterator.last_entry /= null) then
  166. v_iterator := v_iterator.last_entry;
  167. end if;
  168. end if;
  169. return v_key.all;
  170. end function iter;
  171. impure function get(constant key : KEY_TYPE) return VALUE_TYPE is
  172. variable v_entry : t_entry_ptr := find(key);
  173. begin
  174. assert v_entry /= null
  175. report t_dict'instance_name & ": key " & key_to_string(key) & " not found"
  176. severity failure;
  177. return v_entry.data.all;
  178. end function get;
  179. end protected body t_dict;
  180. procedure merge(d0 : inout t_dict; d1 : inout t_dict; d : inout t_dict) is
  181. variable v_key : t_dict_key_ptr;
  182. variable v_data : t_dict_data_ptr;
  183. begin
  184. if (d0.size > 0) then
  185. d0.setIter(TAIL);
  186. for i in 0 to d0.size-1 loop
  187. v_key := new KEY_TYPE'(d0.iter(UP));
  188. v_data := new VALUE_TYPE'(d0.get(v_key.all));
  189. d.set(v_key.all, v_data.all);
  190. end loop;
  191. end if;
  192. if (d1.size > 0) then
  193. d1.setIter(TAIL);
  194. for i in 0 to d1.size-1 loop
  195. v_key := new KEY_TYPE'(d1.iter(UP));
  196. v_data := new VALUE_TYPE'(d1.get(v_key.all));
  197. d.set(v_key.all, v_data.all);
  198. end loop;
  199. end if;
  200. end procedure merge;
  201. end package body DictP;