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.

256 lines
7.7 KiB

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