Browse Source

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.
pull/1/head
T. Meissner 9 years ago
parent
commit
1b9d6a14fb
2 changed files with 88 additions and 27 deletions
  1. +53
    -18
      sim/DictP.vhd
  2. +35
    -9
      test/DictT.vhd

+ 53
- 18
sim/DictP.vhd View File

@ -8,7 +8,9 @@ package DictP is
type t_dict_dir is (UP, DOWN); type t_dict_dir is (UP, DOWN);
type t_dict_error is (NO_ERROR, KEY_INVALID, KEY_NOT_FOUND); type t_dict_error is (NO_ERROR, KEY_INVALID, KEY_NOT_FOUND);
type t_dict_key_ptr is access string; type t_dict_key_ptr is access string;
type t_dict_data_ptr is access std_logic_vector;
type t_dict is protected type t_dict is protected
@ -21,11 +23,13 @@ package DictP is
impure function size return natural; impure function size return natural;
procedure setFirst; procedure setFirst;
procedure setLast; 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; end protected t_dict;
procedure merge(d0 : inout t_dict; d1 : inout t_dict; d : inout t_dict);
end package DictP; end package DictP;
@ -40,20 +44,18 @@ package body DictP is
type t_entry; type t_entry;
type t_entry_ptr is access t_entry; type t_entry_ptr is access t_entry;
type t_data_ptr is access std_logic_vector;
type t_entry is record type t_entry is record
key : t_dict_key_ptr; key : t_dict_key_ptr;
data : t_data_ptr;
data : t_dict_data_ptr;
last_entry : t_entry_ptr; last_entry : t_entry_ptr;
next_entry : t_entry_ptr; next_entry : t_entry_ptr;
end record t_entry; 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; 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.data := new std_logic_vector'(data);
v_head.last_entry := null; v_head.last_entry := null;
v_head.next_entry := null; v_head.next_entry := null;
v_begin := v_head;
v_tail := v_head;
end if; end if;
if (v_logging) then if (v_logging) then
report t_dict'instance_name & ": Add key " & key & " with data 0x" & to_hstring(data); 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 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 := null;
--v_entry.next_entry.last_entry := v_entry.last_entry; --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 -- remove from between
elsif(v_entry.next_entry /= null and v_entry.last_entry /= null) then 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.last_entry.next_entry := v_entry.next_entry;
@ -183,23 +185,23 @@ package body DictP is
procedure setFirst is procedure setFirst is
begin begin
v_current := v_begin;
v_iterator := v_tail;
end procedure setFirst; end procedure setFirst;
procedure setLast is procedure setLast is
begin begin
v_current := v_head;
v_iterator := v_head;
end procedure setLast; end procedure setLast;
impure function iter (dir : t_dict_dir := UP) return string is impure function iter (dir : t_dict_dir := UP) return string is
variable v_key : t_dict_key_ptr := null; variable v_key : t_dict_key_ptr := null;
begin 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 if (dir = UP) then
v_current := v_current.next_entry;
v_iterator := v_iterator.next_entry;
else else
v_current := v_current.last_entry;
v_iterator := v_iterator.last_entry;
end if; end if;
return v_key.all; return v_key.all;
else else
@ -207,8 +209,41 @@ package body DictP is
end if; end if;
end function iter; 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; 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; end package body DictP;

+ 35
- 9
test/DictT.vhd View File

@ -29,6 +29,8 @@ architecture sim of DictT is
type t_scoreboard is array (natural range <>) of std_logic_vector(7 downto 0); type t_scoreboard is array (natural range <>) of std_logic_vector(7 downto 0);
shared variable sv_dict : t_dict; shared variable sv_dict : t_dict;
shared variable sv_dact : t_dict;
shared variable sv_duct : t_dict;
begin begin
@ -37,16 +39,18 @@ begin
DictInitP : process is DictInitP : process is
begin begin
sv_dict.init(false); sv_dict.init(false);
sv_dact.init(false);
sv_duct.init(false);
wait; wait;
end process DictInitP; end process DictInitP;
DictTestP : process is 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; variable v_error : t_dict_error;
begin begin
v_random.InitSeed(v_random'instance_name); v_random.InitSeed(v_random'instance_name);
@ -148,8 +152,30 @@ begin
deallocate(v_key); deallocate(v_key);
report "INFO: Test successful"; 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 -- 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); sv_dict.del("255", v_error);
assert not(sv_dict.hasKey("255")) assert not(sv_dict.hasKey("255"))
report "ERROR: Key 255 shouldn't exist in dictionary" report "ERROR: Key 255 shouldn't exist in dictionary"
@ -157,7 +183,7 @@ begin
report "INFO: Test successful"; report "INFO: Test successful";
-- Remove key/value pair from head of dictionary -- 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); sv_dict.del("127", v_error);
assert not(sv_dict.hasKey("127")) assert not(sv_dict.hasKey("127"))
report "ERROR: Key 127 shouldn't exist in dictionary" report "ERROR: Key 127 shouldn't exist in dictionary"
@ -165,7 +191,7 @@ begin
report "INFO: Test successful"; report "INFO: Test successful";
-- Remove key/value pair from head of dictionary -- 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); sv_dict.del("0", v_error);
assert not(sv_dict.hasKey("0")) assert not(sv_dict.hasKey("0"))
report "ERROR: Key 0 shouldn't exist in dictionary" report "ERROR: Key 0 shouldn't exist in dictionary"
@ -173,7 +199,7 @@ begin
report "INFO: Test successful"; report "INFO: Test successful";
-- Remove key/value pair from head of dictionary -- 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); sv_dict.clear(v_error);
assert sv_dict.size = 0 assert sv_dict.size = 0
report "ERROR: Dict should be empty" report "ERROR: Dict should be empty"


Loading…
Cancel
Save