Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Style: data_types #1

Merged
merged 9 commits into from
May 26, 2019
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