From 1b9d6a14fb73a5bb22f630f029542a6ad412f382 Mon Sep 17 00:00:00 2001 From: tmeissner Date: Thu, 3 Sep 2015 23:48:08 +0200 Subject: [PATCH] Add new procedure to merge 2 dicts There is a new procedure merge() to merge the content of 2 diicts into a third one. This procedure is defined outside of the t_dict protected type. Also a new get() function returning the data as std_logic_vector. is added. It is needed to save the data in a unconstrained access type which is used inside the merge() procedure. This get() function is public. It can be used when no error return value is needed as you get with the get() procedure. Instead an assertion is triggered when the given key isn't found. --- sim/DictP.vhd | 71 +++++++++++++++++++++++++++++++++++++------------- test/DictT.vhd | 44 ++++++++++++++++++++++++------- 2 files changed, 88 insertions(+), 27 deletions(-) diff --git a/sim/DictP.vhd b/sim/DictP.vhd index 82a47c2..c337bd8 100644 --- a/sim/DictP.vhd +++ b/sim/DictP.vhd @@ -8,7 +8,9 @@ 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 @@ -21,11 +23,13 @@ package DictP is impure function size return natural; procedure setFirst; procedure setLast; - impure function iter (dir : t_dict_dir := UP) return string; - + 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; @@ -40,20 +44,18 @@ package body DictP is type t_entry; type t_entry_ptr is access t_entry; - type t_data_ptr is access std_logic_vector; - type t_entry is record key : t_dict_key_ptr; - data : t_data_ptr; + data : t_dict_data_ptr; last_entry : t_entry_ptr; next_entry : t_entry_ptr; end record t_entry; - variable v_begin : t_entry_ptr := null; - variable v_head : t_entry_ptr := null; - variable v_current : t_entry_ptr := null; - variable v_size : natural := 0; - variable v_logging : boolean := false; + 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; @@ -78,7 +80,7 @@ package body DictP is v_head.data := new std_logic_vector'(data); v_head.last_entry := null; v_head.next_entry := null; - v_begin := v_head; + v_tail := v_head; end if; if (v_logging) then report t_dict'instance_name & ": Add key " & key & " with data 0x" & to_hstring(data); @@ -120,7 +122,7 @@ package body DictP is 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_begin := v_entry.next_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; @@ -183,23 +185,23 @@ package body DictP is procedure setFirst is begin - v_current := v_begin; + v_iterator := v_tail; end procedure setFirst; procedure setLast is begin - v_current := v_head; + 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_current /= null) then - v_key := new string'(v_current.key.all); + if (v_iterator /= null) then + v_key := new string'(v_iterator.key.all); if (dir = UP) then - v_current := v_current.next_entry; + v_iterator := v_iterator.next_entry; else - v_current := v_current.last_entry; + v_iterator := v_iterator.last_entry; end if; return v_key.all; else @@ -207,8 +209,41 @@ package body DictP is 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; diff --git a/test/DictT.vhd b/test/DictT.vhd index c9b4cd4..c3c2055 100644 --- a/test/DictT.vhd +++ b/test/DictT.vhd @@ -29,6 +29,8 @@ architecture sim of DictT is type t_scoreboard is array (natural range <>) of std_logic_vector(7 downto 0); shared variable sv_dict : t_dict; + shared variable sv_dact : t_dict; + shared variable sv_duct : t_dict; begin @@ -37,16 +39,18 @@ begin DictInitP : process is begin sv_dict.init(false); + sv_dact.init(false); + sv_duct.init(false); wait; end process DictInitP; DictTestP : process is - variable v_key : t_dict_key_ptr; - variable v_random : RandomPType; - variable v_input : std_logic_vector(7 downto 0); - variable v_output : std_logic_vector(7 downto 0); - variable v_scoreboard : t_scoreboard(0 to 256); + variable v_key : t_dict_key_ptr; + variable v_random : RandomPType; + variable v_input : std_logic_vector(7 downto 0); + variable v_output : std_logic_vector(7 downto 0); + variable v_scoreboard : t_scoreboard(0 to 511); variable v_error : t_dict_error; begin v_random.InitSeed(v_random'instance_name); @@ -148,8 +152,30 @@ begin deallocate(v_key); report "INFO: Test successful"; + -- merge 2 dictionaries + -- fill dictionary and check count + report "INFO: Test 7: Merge dictionaries"; + for i in 256 to 511 loop + v_input := v_random.RandSlv(8); + sv_dact.set(integer'image(i), v_input, v_error); + v_scoreboard(i) := v_input; + assert sv_dact.size = i-255 + report "ERROR: Dict should have " & to_string(i-255) & " entries" + severity failure; + end loop; + -- merge dictionaries + merge(sv_dict, sv_dact, sv_duct); + -- read all entries and check for correct data + for i in 0 to 511 loop + sv_duct.get(integer'image(i), v_output, v_error); + assert v_output = v_scoreboard(i) + report "ERROR: Got 0x" & to_hstring(v_output) & ", expected 0x" & to_hstring(v_scoreboard(i)) + severity failure; + end loop; + report "INFO: Test successful"; + -- Remove key/value pair from head of dictionary - report "INFO: Test 7: Removing entry from head of dictionary"; + report "INFO: Test 8: Removing entry from head of dictionary"; sv_dict.del("255", v_error); assert not(sv_dict.hasKey("255")) report "ERROR: Key 255 shouldn't exist in dictionary" @@ -157,7 +183,7 @@ begin report "INFO: Test successful"; -- Remove key/value pair from head of dictionary - report "INFO: Test 8: Removing entry from middle of dictionary"; + report "INFO: Test 9: Removing entry from middle of dictionary"; sv_dict.del("127", v_error); assert not(sv_dict.hasKey("127")) report "ERROR: Key 127 shouldn't exist in dictionary" @@ -165,7 +191,7 @@ begin report "INFO: Test successful"; -- Remove key/value pair from head of dictionary - report "INFO: Test 9: Removing entry from beginning of dictionary"; + report "INFO: Test 10: Removing entry from beginning of dictionary"; sv_dict.del("0", v_error); assert not(sv_dict.hasKey("0")) report "ERROR: Key 0 shouldn't exist in dictionary" @@ -173,7 +199,7 @@ begin report "INFO: Test successful"; -- Remove key/value pair from head of dictionary - report "INFO: Test 10: Clear all entries from dictionary"; + report "INFO: Test 11: Clear all entries from dictionary"; sv_dict.clear(v_error); assert sv_dict.size = 0 report "ERROR: Dict should be empty"