Skip to content
Merged
1 change: 1 addition & 0 deletions vunit/builtins.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def _add_data_types(self):
"""
Add data types packages
"""
self._add_files(join(VHDL_PATH, "data_types", "src", "types", "*.vhd"))
self._add_files(join(VHDL_PATH, "data_types", "src", "*.vhd"))

def _add_array_util(self):
Expand Down
2 changes: 1 addition & 1 deletion vunit/vhdl/com/src/com_string.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ package body com_string_pkg is
constant data : integer_vector_ptr_t)
return string is
begin
return create_group(1, to_string(data.index));
return create_group(1, to_string(data.ref));
end;

function to_string (
Expand Down
147 changes: 96 additions & 51 deletions vunit/vhdl/data_types/src/dict_pkg.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,54 @@ use work.integer_vector_ptr_pool_pkg.all;

package dict_pkg is
type dict_t is record
p_meta : integer_vector_ptr_t;
p_meta : integer_vector_ptr_t;
p_bucket_lengths : integer_vector_ptr_t;
p_bucket_keys : integer_vector_ptr_t;
p_bucket_values : integer_vector_ptr_t;
p_bucket_keys : integer_vector_ptr_t;
p_bucket_values : integer_vector_ptr_t;
end record;
constant null_dict : dict_t := (others => null_ptr);

impure function new_dict return dict_t;
procedure deallocate(variable dict : inout dict_t);
impure function new_dict
return dict_t;

procedure set(dict : dict_t; key, value : string);
impure function get(dict : dict_t; key : string) return string;
impure function has_key(dict : dict_t; key : string) return boolean;
impure function num_keys(dict : dict_t) return natural;
procedure remove(dict : dict_t; key : string);
procedure deallocate (
variable dict : inout dict_t
);

procedure set (
dict : dict_t;
key, value : string
);

impure function get (
dict : dict_t;
key : string
) return string;

impure function has_key (
dict : dict_t;
key : string
) return boolean;

impure function num_keys (
dict : dict_t
) return natural;

procedure remove (
dict : dict_t;
key : string
);
end package;

package body dict_pkg is
constant int_pool : integer_vector_ptr_pool_t := new_integer_vector_ptr_pool;
constant str_pool : string_ptr_pool_t := new_string_ptr_pool;

constant meta_num_keys : natural := 0;
constant meta_length : natural := meta_num_keys+1;

constant new_bucket_size : natural := 1;

impure function new_dict return dict_t is
impure function new_dict
return dict_t is
variable dict : dict_t;
variable tmp : integer_vector_ptr_t;
constant num_buckets : natural := 1;
Expand All @@ -46,23 +67,21 @@ package body dict_pkg is
p_bucket_lengths => new_integer_vector_ptr(int_pool, num_buckets),
p_bucket_keys => new_integer_vector_ptr(int_pool, num_buckets),
p_bucket_values => new_integer_vector_ptr(int_pool, num_buckets));

set(dict.p_meta, meta_num_keys, 0);

for i in 0 to length(dict.p_bucket_lengths)-1 loop
-- Zero items in bucket
set(dict.p_bucket_lengths, i, 0);

tmp := new_integer_vector_ptr(int_pool, new_bucket_size);
set(dict.p_bucket_keys, i, to_integer(tmp));

tmp := new_integer_vector_ptr(int_pool, new_bucket_size);
set(dict.p_bucket_values, i, to_integer(tmp));
end loop;
return dict;
end function;
end;

procedure deallocate(variable dict : inout dict_t) is
procedure deallocate (
variable dict : inout dict_t
) is
constant num_buckets : natural := length(dict.p_bucket_lengths);

variable bucket_values : integer_vector_ptr_t;
Expand All @@ -78,40 +97,41 @@ package body dict_pkg is
bucket_keys := to_integer_vector_ptr(get(dict.p_bucket_keys, bucket_idx));
bucket_values := to_integer_vector_ptr(get(dict.p_bucket_values, bucket_idx));
bucket_length := get(dict.p_bucket_lengths, bucket_idx);

for idx in 0 to bucket_length-1 loop
key := to_string_ptr(get(bucket_keys, idx));
value := to_string_ptr(get(bucket_values, idx));
recycle(str_pool, key);
recycle(str_pool, value);
end loop;

recycle(int_pool, bucket_values);
recycle(int_pool, bucket_keys);
end loop;

recycle(int_pool, dict.p_meta);
recycle(int_pool, dict.p_bucket_lengths);
recycle(int_pool, dict.p_bucket_values);
recycle(int_pool, dict.p_bucket_keys);
end;

-- DJB2 hash
impure function hash(str : string) return natural is
impure function hash (
str : string
) return natural is
variable value : natural := 5381;
begin
for i in str'range loop
value := (33*value + character'pos(str(i))) mod 2**(31-6);
end loop;
return value;
end function;
end;

impure function get_value_ptr(dict : dict_t; key_hash : natural; key : string) return string_ptr_t is
impure function get_value_ptr (
dict : dict_t;
key_hash : natural;
key : string
) return string_ptr_t is
constant num_buckets : natural := length(dict.p_bucket_lengths);
constant bucket_idx : natural := key_hash mod num_buckets;

constant bucket_length : natural := get(dict.p_bucket_lengths, bucket_idx);

constant bucket_values : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_values, bucket_idx));
constant bucket_keys : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_keys, bucket_idx));
begin
Expand All @@ -123,32 +143,36 @@ package body dict_pkg is
return null_string_ptr;
end;

procedure remove(dict : dict_t; bucket_idx : natural; i : natural; deallocate_item : boolean := true) is
procedure remove (
dict : dict_t;
bucket_idx : natural;
i : natural;
deallocate_item : boolean := true
) is
constant bucket_length : natural := get(dict.p_bucket_lengths, bucket_idx);
constant bucket_values : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_values, bucket_idx));
constant bucket_keys : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_keys, bucket_idx));

variable key, value : string_ptr_t;
begin

if deallocate_item then
key := to_string_ptr(get(bucket_keys, i));
value := to_string_ptr(get(bucket_values, i));
recycle(str_pool, key);
recycle(str_pool, value);
end if;

set(bucket_keys, i, get(bucket_keys, bucket_length-1));
set(bucket_values, i, get(bucket_values, bucket_length-1));

set(dict.p_bucket_lengths, bucket_idx, bucket_length-1);
set(dict.p_meta, meta_num_keys, num_keys(dict)-1);
end;

procedure remove(dict : dict_t; key_hash : natural; key : string) is
procedure remove (
dict : dict_t;
key_hash : natural;
key : string
) is
constant num_buckets : natural := length(dict.p_bucket_lengths);
constant bucket_idx : natural := key_hash mod num_buckets;

constant bucket_length : natural := get(dict.p_bucket_lengths, bucket_idx);
constant bucket_keys : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_keys, bucket_idx));
begin
Expand All @@ -160,13 +184,19 @@ package body dict_pkg is
end loop;
end;

procedure insert_new(dict : dict_t; key_hash : natural; key, value : string_ptr_t);
procedure insert_new (
dict : dict_t;
key_hash : natural;
key, value : string_ptr_t
);

procedure relocate_items(dict : dict_t; old_num_buckets : natural) is
procedure relocate_items (
dict : dict_t;
old_num_buckets : natural
) is
constant num_buckets : natural := length(dict.p_bucket_lengths);
variable bucket_values : integer_vector_ptr_t;
variable bucket_keys : integer_vector_ptr_t;

variable idx : natural;
variable key_hash : natural;
variable key : string_ptr_t;
Expand Down Expand Up @@ -199,7 +229,10 @@ package body dict_pkg is
end loop;
end;

procedure resize(dict : dict_t; num_buckets : natural) is
procedure resize (
dict : dict_t;
num_buckets : natural
) is
constant old_num_buckets : natural := length(dict.p_bucket_lengths);
begin
resize(dict.p_bucket_lengths, num_buckets);
Expand All @@ -216,7 +249,10 @@ package body dict_pkg is
relocate_items(dict, old_num_buckets);
end;

procedure set(dict : dict_t; key, value : string) is
procedure set (
dict : dict_t;
key, value : string
) is
constant key_hash : natural := hash(key);
constant old_value_ptr : string_ptr_t := get_value_ptr(dict, key_hash, key);
begin
Expand All @@ -228,16 +264,17 @@ package body dict_pkg is
end if;
end;

procedure insert_new(dict : dict_t; key_hash : natural; key, value : string_ptr_t) is
procedure insert_new (
dict : dict_t;
key_hash : natural;
key, value : string_ptr_t
) is
constant num_buckets : natural := length(dict.p_bucket_lengths);
constant bucket_idx : natural := key_hash mod num_buckets;

constant bucket_length : natural := get(dict.p_bucket_lengths, bucket_idx);

constant bucket_values : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_values, bucket_idx));
constant bucket_keys : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_keys, bucket_idx));
constant bucket_max_length : natural := length(bucket_values);

constant num_keys : natural := get(dict.p_meta, meta_num_keys);
begin
if num_keys > num_buckets then
Expand All @@ -246,42 +283,50 @@ package body dict_pkg is
resize(dict, 2*num_buckets);
insert_new(dict, key_hash, key, value);
return;

elsif bucket_length = bucket_max_length then
-- Bucket size to small, resize
resize(bucket_keys, bucket_max_length+1);
resize(bucket_values, bucket_max_length+1);
end if;

set(dict.p_meta, meta_num_keys, num_keys+1);
set(dict.p_bucket_lengths, bucket_idx, bucket_length+1);
-- Create new value storage
set(bucket_keys, bucket_length, to_integer(key));
set(bucket_values, bucket_length, to_integer(value));
end procedure;
end;

impure function get(dict : dict_t; key : string) return string is
impure function get (
dict : dict_t;
key : string
) return string is
constant key_hash : natural := hash(key);
constant value_ptr : string_ptr_t := get_value_ptr(dict, key_hash, key);
begin
assert value_ptr /= null_string_ptr report "missing key '" & key & "'";
return to_string(value_ptr);
end;

impure function has_key(dict : dict_t; key : string) return boolean is
impure function has_key (
dict : dict_t;
key : string
) return boolean is
constant key_hash : natural := hash(key);
begin
return get_value_ptr(dict, key_hash, key) /= null_string_ptr;
end;

procedure remove(dict : dict_t; key : string) is
procedure remove (
dict : dict_t;
key : string
) is
constant key_hash : natural := hash(key);
begin
remove(dict, key_hash, key);
end;

impure function num_keys(dict : dict_t) return natural is
begin
impure function num_keys (
dict : dict_t
) return natural is begin
return get(dict.p_meta, meta_num_keys);
end;

Expand Down
Loading