library ieee; use ieee.std_logic_1164.all; package DictP is type t_dict_dir is (UP, DOWN); type t_dict_error is (NO_ERROR, KEY_INVALID, KEY_NOT_FOUND); type t_dict_key_ptr is access string; type t_dict_data_ptr is access std_logic_vector; type t_dict is protected procedure set (key : in string; data : in std_logic_vector; err : out t_dict_error); procedure get (key : in string; data : out std_logic_vector; err : out t_dict_error); procedure del (key : in string; err : out t_dict_error); procedure init (logging : in boolean := false); procedure clear (err : out t_dict_error); impure function hasKey (key : string) return boolean; impure function size return natural; procedure setFirst; procedure setLast; impure function iter (dir : t_dict_dir := UP) return string; impure function get(key : string) return std_logic_vector; end protected t_dict; procedure merge(d0 : inout t_dict; d1 : inout t_dict; d : inout t_dict); end package DictP; package body DictP is type t_dict is protected body type t_entry; type t_entry_ptr is access t_entry; type t_entry is record key : t_dict_key_ptr; data : t_dict_data_ptr; last_entry : t_entry_ptr; next_entry : t_entry_ptr; end record t_entry; variable v_tail : t_entry_ptr := null; variable v_head : t_entry_ptr := null; variable v_iterator : t_entry_ptr := null; variable v_size : natural := 0; variable v_logging : boolean := false; impure function find (key : string) return t_entry_ptr; procedure set (key : in string; data : in std_logic_vector; err : out t_dict_error) is variable v_entry : t_entry_ptr := find(key); begin if (key = "") then err := KEY_INVALID; else if (v_entry = null) then if (v_head /= null) then v_entry := new t_entry; v_entry.key := new string'(key); v_entry.data := new std_logic_vector'(data); v_entry.last_entry := v_head; v_entry.next_entry := null; v_head := v_entry; v_head.last_entry.next_entry := v_head; else v_head := new t_entry; v_head.key := new string'(key); v_head.data := new std_logic_vector'(data); v_head.last_entry := null; v_head.next_entry := null; v_tail := v_head; end if; if (v_logging) then report t_dict'instance_name & ": Add key " & key & " with data 0x" & to_hstring(data); end if; v_size := v_size + 1; else v_entry.data.all := data; if (v_logging) then report t_dict'instance_name & ": Set key " & key & " to 0x" & to_hstring(data); end if; end if; err := NO_ERROR; end if; end procedure set; procedure get (key : in string; data : out std_logic_vector; err : out t_dict_error) is variable v_entry : t_entry_ptr := find(key); begin if(v_entry /= null) then data := v_entry.data.all; if v_logging then report t_dict'instance_name & ": Got key " & key & " with data 0x" & to_hstring(v_entry.data.all); end if; err := NO_ERROR; else err := KEY_NOT_FOUND; end if; end procedure get; procedure del (key : in string; err : out t_dict_error) is variable v_entry : t_entry_ptr := find(key); begin if (v_entry /= null) then -- remove head entry if(v_entry.next_entry = null and v_entry.last_entry /= null) then v_entry.last_entry.next_entry := null; v_head := v_entry.last_entry; -- remove start entry elsif(v_entry.next_entry /= null and v_entry.last_entry = null) then v_entry.next_entry.last_entry := null; --v_entry.next_entry.last_entry := v_entry.last_entry; v_tail := v_entry.next_entry; -- remove from between elsif(v_entry.next_entry /= null and v_entry.last_entry /= null) then v_entry.last_entry.next_entry := v_entry.next_entry; v_entry.next_entry.last_entry := v_entry.last_entry; end if; deallocate(v_entry.key); deallocate(v_entry.data); deallocate(v_entry); v_size := v_size - 1; err := NO_ERROR; else err := KEY_NOT_FOUND; end if; end procedure del; impure function find (key : string) return t_entry_ptr is variable v_entry : t_entry_ptr := v_head; begin while (v_entry /= null) loop if(v_entry.key.all = key) then return v_entry; end if; v_entry := v_entry.last_entry; end loop; return null; end function find; procedure clear (err : out t_dict_error) is variable v_entry : t_entry_ptr := v_head; variable v_entry_d : t_entry_ptr; variable v_err : t_dict_error; begin while (v_entry /= null) loop v_entry_d := v_entry; del(v_entry_d.key.all, v_err); if (v_err /= NO_ERROR) then err := v_err; return; else v_entry := v_entry.last_entry; end if; end loop; err := NO_ERROR; end procedure clear; impure function hasKey (key : string) return boolean is begin return find(key) /= null; end function hasKey; impure function size return natural is begin return v_size; end function size; procedure init (logging : in boolean := false) is begin v_logging := logging; end procedure init; procedure setFirst is begin v_iterator := v_tail; end procedure setFirst; procedure setLast is begin v_iterator := v_head; end procedure setLast; impure function iter (dir : t_dict_dir := UP) return string is variable v_key : t_dict_key_ptr := null; begin if (v_iterator /= null) then v_key := new string'(v_iterator.key.all); if (dir = UP) then v_iterator := v_iterator.next_entry; else v_iterator := v_iterator.last_entry; end if; return v_key.all; else return ""; end if; end function iter; impure function get(key : string) return std_logic_vector is variable v_entry : t_entry_ptr := find(key); begin assert v_entry /= null report t_dict'instance_name & ": ERROR: key " & key & " not found" severity failure; return v_entry.data.all; end function get; end protected body t_dict; procedure merge(d0 : inout t_dict; d1 : inout t_dict; d : inout t_dict) is variable v_key : t_dict_key_ptr; variable v_data : t_dict_data_ptr; variable v_error : t_dict_error; begin if (d0.size > 0) then d0.setFirst; for i in 0 to d0.size-1 loop v_key := new string'(d0.iter(UP)); v_data := new std_logic_vector'(d0.get(v_key.all)); d.set(v_key.all, v_data.all, v_error); end loop; end if; if (d1.size > 0) then d1.setFirst; for i in 0 to d1.size-1 loop v_key := new string'(d1.iter(UP)); v_data := new std_logic_vector'(d1.get(v_key.all)); d.set(v_key.all, v_data.all, v_error); end loop; end if; end procedure merge; end package body DictP;