@@ -11,33 +11,54 @@ use work.integer_vector_ptr_pool_pkg.all;
11
11
12
12
package dict_pkg is
13
13
type dict_t is record
14
- p_meta : integer_vector_ptr_t;
14
+ p_meta : integer_vector_ptr_t;
15
15
p_bucket_lengths : integer_vector_ptr_t;
16
- p_bucket_keys : integer_vector_ptr_t;
17
- p_bucket_values : integer_vector_ptr_t;
16
+ p_bucket_keys : integer_vector_ptr_t;
17
+ p_bucket_values : integer_vector_ptr_t;
18
18
end record ;
19
19
constant null_dict : dict_t := (others => null_ptr);
20
20
21
- impure function new_dict return dict_t;
22
- procedure deallocate ( variable dict : inout dict_t) ;
21
+ impure function new_dict
22
+ return dict_t;
23
23
24
- procedure set (dict : dict_t; key, value : string );
25
- impure function get(dict : dict_t; key : string ) return string ;
26
- impure function has_key(dict : dict_t; key : string ) return boolean ;
27
- impure function num_keys(dict : dict_t) return natural ;
28
- procedure remove (dict : dict_t; key : string );
24
+ procedure deallocate (
25
+ variable dict : inout dict_t
26
+ );
27
+
28
+ procedure set (
29
+ dict : dict_t;
30
+ key, value : string
31
+ );
32
+
33
+ impure function get (
34
+ dict : dict_t;
35
+ key : string
36
+ ) return string ;
37
+
38
+ impure function has_key (
39
+ dict : dict_t;
40
+ key : string
41
+ ) return boolean ;
42
+
43
+ impure function num_keys (
44
+ dict : dict_t
45
+ ) return natural ;
46
+
47
+ procedure remove (
48
+ dict : dict_t;
49
+ key : string
50
+ );
29
51
end package ;
30
52
31
53
package body dict_pkg is
32
54
constant int_pool : integer_vector_ptr_pool_t := new_integer_vector_ptr_pool;
33
55
constant str_pool : string_ptr_pool_t := new_string_ptr_pool;
34
-
35
56
constant meta_num_keys : natural := 0 ;
36
57
constant meta_length : natural := meta_num_keys+ 1 ;
37
-
38
58
constant new_bucket_size : natural := 1 ;
39
59
40
- impure function new_dict return dict_t is
60
+ impure function new_dict
61
+ return dict_t is
41
62
variable dict : dict_t;
42
63
variable tmp : integer_vector_ptr_t;
43
64
constant num_buckets : natural := 1 ;
@@ -46,23 +67,21 @@ package body dict_pkg is
46
67
p_bucket_lengths => new_integer_vector_ptr(int_pool, num_buckets),
47
68
p_bucket_keys => new_integer_vector_ptr(int_pool, num_buckets),
48
69
p_bucket_values => new_integer_vector_ptr(int_pool, num_buckets));
49
-
50
70
set(dict.p_meta, meta_num_keys, 0 );
51
-
52
71
for i in 0 to length(dict.p_bucket_lengths)- 1 loop
53
72
-- Zero items in bucket
54
73
set(dict.p_bucket_lengths, i, 0 );
55
-
56
74
tmp := new_integer_vector_ptr(int_pool, new_bucket_size);
57
75
set(dict.p_bucket_keys, i, to_integer (tmp));
58
-
59
76
tmp := new_integer_vector_ptr(int_pool, new_bucket_size);
60
77
set(dict.p_bucket_values, i, to_integer (tmp));
61
78
end loop ;
62
79
return dict;
63
- end function ;
80
+ end ;
64
81
65
- procedure deallocate(variable dict : inout dict_t) is
82
+ procedure deallocate (
83
+ variable dict : inout dict_t
84
+ ) is
66
85
constant num_buckets : natural := length(dict.p_bucket_lengths);
67
86
68
87
variable bucket_values : integer_vector_ptr_t;
@@ -78,40 +97,41 @@ package body dict_pkg is
78
97
bucket_keys := to_integer_vector_ptr(get(dict.p_bucket_keys, bucket_idx));
79
98
bucket_values := to_integer_vector_ptr(get(dict.p_bucket_values, bucket_idx));
80
99
bucket_length := get(dict.p_bucket_lengths, bucket_idx);
81
-
82
100
for idx in 0 to bucket_length- 1 loop
83
101
key := to_string_ptr(get(bucket_keys, idx));
84
102
value := to_string_ptr(get(bucket_values, idx));
85
103
recycle(str_pool, key);
86
104
recycle(str_pool, value);
87
105
end loop ;
88
-
89
106
recycle(int_pool, bucket_values);
90
107
recycle(int_pool, bucket_keys);
91
108
end loop ;
92
-
93
109
recycle(int_pool, dict.p_meta);
94
110
recycle(int_pool, dict.p_bucket_lengths);
95
111
recycle(int_pool, dict.p_bucket_values);
96
112
recycle(int_pool, dict.p_bucket_keys);
97
113
end ;
98
114
99
115
-- DJB2 hash
100
- impure function hash(str : string ) return natural is
116
+ impure function hash (
117
+ str : string
118
+ ) return natural is
101
119
variable value : natural := 5381 ;
102
120
begin
103
121
for i in str'range loop
104
122
value := (33 * value + character 'pos (str(i))) mod 2 ** (31 - 6 );
105
123
end loop ;
106
124
return value;
107
- end function ;
125
+ end ;
108
126
109
- impure function get_value_ptr(dict : dict_t; key_hash : natural ; key : string ) return string_ptr_t is
127
+ impure function get_value_ptr (
128
+ dict : dict_t;
129
+ key_hash : natural ;
130
+ key : string
131
+ ) return string_ptr_t is
110
132
constant num_buckets : natural := length(dict.p_bucket_lengths);
111
133
constant bucket_idx : natural := key_hash mod num_buckets;
112
-
113
134
constant bucket_length : natural := get(dict.p_bucket_lengths, bucket_idx);
114
-
115
135
constant bucket_values : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_values, bucket_idx));
116
136
constant bucket_keys : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_keys, bucket_idx));
117
137
begin
@@ -123,32 +143,36 @@ package body dict_pkg is
123
143
return null_string_ptr;
124
144
end ;
125
145
126
- procedure remove(dict : dict_t; bucket_idx : natural ; i : natural ; deallocate_item : boolean := true ) is
146
+ procedure remove (
147
+ dict : dict_t;
148
+ bucket_idx : natural ;
149
+ i : natural ;
150
+ deallocate_item : boolean := true
151
+ ) is
127
152
constant bucket_length : natural := get(dict.p_bucket_lengths, bucket_idx);
128
153
constant bucket_values : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_values, bucket_idx));
129
154
constant bucket_keys : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_keys, bucket_idx));
130
-
131
155
variable key, value : string_ptr_t;
132
156
begin
133
-
134
157
if deallocate_item then
135
158
key := to_string_ptr(get(bucket_keys, i));
136
159
value := to_string_ptr(get(bucket_values, i));
137
160
recycle(str_pool, key);
138
161
recycle(str_pool, value);
139
162
end if ;
140
-
141
163
set(bucket_keys, i, get(bucket_keys, bucket_length- 1 ));
142
164
set(bucket_values, i, get(bucket_values, bucket_length- 1 ));
143
-
144
165
set(dict.p_bucket_lengths, bucket_idx, bucket_length- 1 );
145
166
set(dict.p_meta, meta_num_keys, num_keys(dict)- 1 );
146
167
end ;
147
168
148
- procedure remove(dict : dict_t; key_hash : natural ; key : string ) is
169
+ procedure remove (
170
+ dict : dict_t;
171
+ key_hash : natural ;
172
+ key : string
173
+ ) is
149
174
constant num_buckets : natural := length(dict.p_bucket_lengths);
150
175
constant bucket_idx : natural := key_hash mod num_buckets;
151
-
152
176
constant bucket_length : natural := get(dict.p_bucket_lengths, bucket_idx);
153
177
constant bucket_keys : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_keys, bucket_idx));
154
178
begin
@@ -160,13 +184,19 @@ package body dict_pkg is
160
184
end loop ;
161
185
end ;
162
186
163
- procedure insert_new(dict : dict_t; key_hash : natural ; key, value : string_ptr_t);
187
+ procedure insert_new (
188
+ dict : dict_t;
189
+ key_hash : natural ;
190
+ key, value : string_ptr_t
191
+ );
164
192
165
- procedure relocate_items(dict : dict_t; old_num_buckets : natural ) is
193
+ procedure relocate_items (
194
+ dict : dict_t;
195
+ old_num_buckets : natural
196
+ ) is
166
197
constant num_buckets : natural := length(dict.p_bucket_lengths);
167
198
variable bucket_values : integer_vector_ptr_t;
168
199
variable bucket_keys : integer_vector_ptr_t;
169
-
170
200
variable idx : natural ;
171
201
variable key_hash : natural ;
172
202
variable key : string_ptr_t;
@@ -199,7 +229,10 @@ package body dict_pkg is
199
229
end loop ;
200
230
end ;
201
231
202
- procedure resize (dict : dict_t; num_buckets : natural ) is
232
+ procedure resize (
233
+ dict : dict_t;
234
+ num_buckets : natural
235
+ ) is
203
236
constant old_num_buckets : natural := length(dict.p_bucket_lengths);
204
237
begin
205
238
resize (dict.p_bucket_lengths, num_buckets);
@@ -216,7 +249,10 @@ package body dict_pkg is
216
249
relocate_items(dict, old_num_buckets);
217
250
end ;
218
251
219
- procedure set(dict : dict_t; key, value : string ) is
252
+ procedure set (
253
+ dict : dict_t;
254
+ key, value : string
255
+ ) is
220
256
constant key_hash : natural := hash(key);
221
257
constant old_value_ptr : string_ptr_t := get_value_ptr(dict, key_hash, key);
222
258
begin
@@ -228,16 +264,17 @@ package body dict_pkg is
228
264
end if ;
229
265
end ;
230
266
231
- procedure insert_new(dict : dict_t; key_hash : natural ; key, value : string_ptr_t) is
267
+ procedure insert_new (
268
+ dict : dict_t;
269
+ key_hash : natural ;
270
+ key, value : string_ptr_t
271
+ ) is
232
272
constant num_buckets : natural := length(dict.p_bucket_lengths);
233
273
constant bucket_idx : natural := key_hash mod num_buckets;
234
-
235
274
constant bucket_length : natural := get(dict.p_bucket_lengths, bucket_idx);
236
-
237
275
constant bucket_values : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_values, bucket_idx));
238
276
constant bucket_keys : integer_vector_ptr_t := to_integer_vector_ptr(get(dict.p_bucket_keys, bucket_idx));
239
277
constant bucket_max_length : natural := length(bucket_values);
240
-
241
278
constant num_keys : natural := get(dict.p_meta, meta_num_keys);
242
279
begin
243
280
if num_keys > num_buckets then
@@ -246,42 +283,50 @@ package body dict_pkg is
246
283
resize (dict, 2 * num_buckets);
247
284
insert_new(dict, key_hash, key, value);
248
285
return ;
249
-
250
286
elsif bucket_length = bucket_max_length then
251
287
-- Bucket size to small, resize
252
288
resize (bucket_keys, bucket_max_length+ 1 );
253
289
resize (bucket_values, bucket_max_length+ 1 );
254
290
end if ;
255
-
256
291
set(dict.p_meta, meta_num_keys, num_keys+ 1 );
257
292
set(dict.p_bucket_lengths, bucket_idx, bucket_length+ 1 );
258
293
-- Create new value storage
259
294
set(bucket_keys, bucket_length, to_integer (key));
260
295
set(bucket_values, bucket_length, to_integer (value));
261
- end procedure ;
296
+ end ;
262
297
263
- impure function get(dict : dict_t; key : string ) return string is
298
+ impure function get (
299
+ dict : dict_t;
300
+ key : string
301
+ ) return string is
264
302
constant key_hash : natural := hash(key);
265
303
constant value_ptr : string_ptr_t := get_value_ptr(dict, key_hash, key);
266
304
begin
267
305
assert value_ptr /= null_string_ptr report " missing key '" & key & " '" ;
268
306
return to_string(value_ptr);
269
307
end ;
270
308
271
- impure function has_key(dict : dict_t; key : string ) return boolean is
309
+ impure function has_key (
310
+ dict : dict_t;
311
+ key : string
312
+ ) return boolean is
272
313
constant key_hash : natural := hash(key);
273
314
begin
274
315
return get_value_ptr(dict, key_hash, key) /= null_string_ptr;
275
316
end ;
276
317
277
- procedure remove(dict : dict_t; key : string ) is
318
+ procedure remove (
319
+ dict : dict_t;
320
+ key : string
321
+ ) is
278
322
constant key_hash : natural := hash(key);
279
323
begin
280
324
remove(dict, key_hash, key);
281
325
end ;
282
326
283
- impure function num_keys(dict : dict_t) return natural is
284
- begin
327
+ impure function num_keys (
328
+ dict : dict_t
329
+ ) return natural is begin
285
330
return get(dict.p_meta, meta_num_keys);
286
331
end ;
287
332
0 commit comments