Skip to content

Commit f8c9afc

Browse files
vpr: Use unordered_map instead of C-style hash table for pattern_names
1 parent 3db44a2 commit f8c9afc

File tree

2 files changed

+84
-118
lines changed

2 files changed

+84
-118
lines changed

vpr/src/pack/prepack.cpp

Lines changed: 79 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -27,27 +27,21 @@ using namespace std;
2727
#include "read_xml_arch_file.h"
2828
#include "globals.h"
2929
#include "atom_netlist.h"
30-
#include "hash.h"
3130
#include "prepack.h"
3231
#include "vpr_utils.h"
3332
#include "echo_files.h"
3433

3534
/*****************************************/
3635
/*Local Function Declaration */
3736
/*****************************************/
38-
static int add_pattern_name_to_hash(t_hash **nhash,
39-
const char *pattern_name, int *ncount);
40-
4137
static void discover_pattern_names_in_pb_graph_node(
42-
t_pb_graph_node *pb_graph_node, t_hash **nhash,
43-
int *ncount);
38+
t_pb_graph_node *pb_graph_node, std::unordered_map<std::string, int>& pattern_names);
4439

4540
static void forward_infer_pattern(t_pb_graph_pin *pb_graph_pin);
4641

4742
static void backward_infer_pattern(t_pb_graph_pin *pb_graph_pin);
4843

49-
static t_pack_patterns *alloc_and_init_pattern_list_from_hash(const int ncount,
50-
t_hash **nhash);
44+
static t_pack_patterns *alloc_and_init_pattern_list_from_hash(std::unordered_map<std::string, int> pattern_names);
5145

5246
static t_pb_graph_edge * find_expansion_edge_of_pattern(const int pattern_index,
5347
const t_pb_graph_node *pb_graph_node);
@@ -122,29 +116,26 @@ static AtomBlockId get_driving_block(const AtomBlockId block_id, const t_model_p
122116
* If this limitation is too constraining, code is designed so that this limitation can be removed.
123117
*/
124118
t_pack_patterns *alloc_and_load_pack_patterns(int *num_packing_patterns) {
125-
int i, j, ncount, k;
119+
126120
int L_num_blocks;
127-
t_hash **nhash;
128121
t_pack_patterns *list_of_packing_patterns;
129122
t_pb_graph_edge *expansion_edge;
130123
auto& device_ctx = g_vpr_ctx.device();
131124

132125
/* alloc and initialize array of packing patterns based on architecture complex blocks */
133-
nhash = alloc_hash_table();
134-
ncount = 0;
135-
for (i = 0; i < device_ctx.num_block_types; i++) {
136-
discover_pattern_names_in_pb_graph_node(
137-
device_ctx.block_types[i].pb_graph_head, nhash, &ncount);
126+
std::unordered_map<std::string, int> pattern_names;
127+
for (int i = 0; i < device_ctx.num_block_types; i++) {
128+
discover_pattern_names_in_pb_graph_node(device_ctx.block_types[i].pb_graph_head, pattern_names);
138129
}
139130

140-
list_of_packing_patterns = alloc_and_init_pattern_list_from_hash(ncount, nhash);
131+
list_of_packing_patterns = alloc_and_init_pattern_list_from_hash(pattern_names);
141132

142133
/* load packing patterns by traversing the edges to find edges belonging to pattern */
143-
for (i = 0; i < ncount; i++) {
144-
for (j = 0; j < device_ctx.num_block_types; j++) {
134+
for (size_t i = 0; i < pattern_names.size(); i++) {
135+
for (int j = 0; j < device_ctx.num_block_types; j++) {
145136
// find an edge that belongs to this pattern
146137
expansion_edge = find_expansion_edge_of_pattern(i, device_ctx.block_types[j].pb_graph_head);
147-
if (expansion_edge == nullptr) {
138+
if (!expansion_edge) {
148139
continue;
149140
}
150141

@@ -162,7 +153,7 @@ t_pack_patterns *alloc_and_load_pack_patterns(int *num_packing_patterns) {
162153
* of size, it is optional whether or not an atom in a netlist matches any
163154
* particular block inside the chain */
164155
list_of_packing_patterns[i].is_block_optional = (bool*) vtr::malloc(L_num_blocks * sizeof(bool));
165-
for(k = 0; k < L_num_blocks; k++) {
156+
for(int k = 0; k < L_num_blocks; k++) {
166157
list_of_packing_patterns[i].is_block_optional[k] = false;
167158
if(list_of_packing_patterns[i].is_chain && list_of_packing_patterns[i].root_block->block_id != k) {
168159
list_of_packing_patterns[i].is_block_optional[k] = true;
@@ -181,73 +172,55 @@ t_pack_patterns *alloc_and_load_pack_patterns(int *num_packing_patterns) {
181172
}
182173

183174
//Sanity check, every pattern should have a root block
184-
for(i = 0; i < ncount; ++i) {
175+
for(size_t i = 0; i < pattern_names.size(); ++i) {
185176
if(list_of_packing_patterns[i].root_block == nullptr) {
186177
VPR_THROW(VPR_ERROR_ARCH, "Failed to find root block for pack pattern %s", list_of_packing_patterns[i].name);
187178
}
188179
}
189180

190-
free_hash_table(nhash);
191-
192-
*num_packing_patterns = ncount;
181+
*num_packing_patterns = pattern_names.size();
193182

194183

195184
return list_of_packing_patterns;
196185
}
197186

198-
/**
199-
* Adds pack pattern name to hashtable of pack pattern names.
200-
*/
201-
static int add_pattern_name_to_hash(t_hash **nhash,
202-
const char *pattern_name, int *ncount) {
203-
t_hash *hash_value;
204-
205-
hash_value = insert_in_hash_table(nhash, pattern_name, *ncount);
206-
if (hash_value->count == 1) {
207-
VTR_ASSERT(*ncount == hash_value->index);
208-
(*ncount)++;
209-
}
210-
return hash_value->index;
211-
}
212187

213188
/**
214189
* Locate all pattern names
215190
* Side-effect: set all pb_graph_node temp_scratch_pad field to NULL
216191
* For cases where a pattern inference is "obvious", mark it as obvious.
217192
*/
218193
static void discover_pattern_names_in_pb_graph_node(
219-
t_pb_graph_node *pb_graph_node, t_hash **nhash,
220-
int *ncount) {
221-
int i, j, k, m;
222-
int index;
223-
bool hasPattern;
194+
t_pb_graph_node *pb_graph_node, std::unordered_map<std::string, int>& pattern_names) {
195+
224196
/* Iterate over all edges to discover if an edge in current physical block belongs to a pattern
225-
If edge does, then record the name of the pattern in a hash table
226-
*/
197+
If edge does, then record the name of the pattern in a hash table */
227198

228199
if (pb_graph_node == nullptr) {
229200
return;
230201
}
231202

232203
pb_graph_node->temp_scratch_pad = nullptr;
233204

234-
for (i = 0; i < pb_graph_node->num_input_ports; i++) {
235-
for (j = 0; j < pb_graph_node->num_input_pins[i]; j++) {
236-
hasPattern = false;
237-
for (k = 0; k < pb_graph_node->input_pins[i][j].num_output_edges; k++) {
238-
for (m = 0; m < pb_graph_node->input_pins[i][j].output_edges[k]->num_pack_patterns; m++) {
205+
for (int i = 0; i < pb_graph_node->num_input_ports; i++) {
206+
for (int j = 0; j < pb_graph_node->num_input_pins[i]; j++) {
207+
bool hasPattern = false;
208+
for (int k = 0; k < pb_graph_node->input_pins[i][j].num_output_edges; k++) {
209+
auto output_edge = pb_graph_node->input_pins[i][j].output_edges[k];
210+
for (int m = 0; m < output_edge->num_pack_patterns; m++) {
239211
hasPattern = true;
240-
index = add_pattern_name_to_hash(nhash,
241-
pb_graph_node->input_pins[i][j].output_edges[k]->pack_pattern_names[m], ncount);
242-
if (pb_graph_node->input_pins[i][j].output_edges[k]->pack_pattern_indices == nullptr) {
243-
pb_graph_node->input_pins[i][j].output_edges[k]->pack_pattern_indices =
244-
(int*) vtr::malloc(pb_graph_node->input_pins[i][j].output_edges[k]->num_pack_patterns
245-
* sizeof(int));
212+
// insert the found pattern name to the hash table. If this pattern is inserted
213+
// for the first time, then its index is the current size of the hash table
214+
// otherwise the insert function will return an iterator of the previously
215+
// inserted element with the index given to that pattern
216+
std::string pattern_name(output_edge->pack_pattern_names[m]);
217+
int index = (pattern_names.insert({pattern_name, pattern_names.size()}).first)->second;
218+
if (!output_edge->pack_pattern_indices) {
219+
output_edge->pack_pattern_indices = (int*) vtr::malloc(output_edge->num_pack_patterns * sizeof(int));
246220
}
247-
pb_graph_node->input_pins[i][j].output_edges[k]->pack_pattern_indices[m] = index;
221+
output_edge->pack_pattern_indices[m] = index;
248222
// if this output edges belongs to a pack pattern. Expand forward starting from
249223
// all its output pins to check if you need to infer pattern for direct connections
250-
auto& output_edge = pb_graph_node->input_pins[i][j].output_edges[k];
251224
for (int ipin = 0; ipin < output_edge->num_output_pins; ipin++) {
252225
forward_infer_pattern(output_edge->output_pins[ipin]);
253226
}
@@ -256,29 +229,31 @@ static void discover_pattern_names_in_pb_graph_node(
256229
// if the output edge to this pin is annotated with a pack pattern
257230
// trace the inputs to this pin and mark them to infer pattern
258231
// if they are direct connections (num_input_edges == 1)
259-
if (hasPattern == true) {
232+
if (hasPattern) {
260233
backward_infer_pattern(&pb_graph_node->input_pins[i][j]);
261234
}
262235
}
263236
}
264237

265-
for (i = 0; i < pb_graph_node->num_output_ports; i++) {
266-
for (j = 0; j < pb_graph_node->num_output_pins[i]; j++) {
267-
hasPattern = false;
268-
for (k = 0; k < pb_graph_node->output_pins[i][j].num_output_edges; k++) {
269-
for (m = 0; m < pb_graph_node->output_pins[i][j].output_edges[k]->num_pack_patterns; m++) {
238+
for (int i = 0; i < pb_graph_node->num_output_ports; i++) {
239+
for (int j = 0; j < pb_graph_node->num_output_pins[i]; j++) {
240+
bool hasPattern = false;
241+
for (int k = 0; k < pb_graph_node->output_pins[i][j].num_output_edges; k++) {
242+
auto output_edge = pb_graph_node->output_pins[i][j].output_edges[k];
243+
for (int m = 0; m < output_edge->num_pack_patterns; m++) {
270244
hasPattern = true;
271-
index = add_pattern_name_to_hash(nhash,
272-
pb_graph_node->output_pins[i][j].output_edges[k]->pack_pattern_names[m], ncount);
273-
if (pb_graph_node->output_pins[i][j].output_edges[k]->pack_pattern_indices == nullptr) {
274-
pb_graph_node->output_pins[i][j].output_edges[k]->pack_pattern_indices =
275-
(int*) vtr::malloc(pb_graph_node->output_pins[i][j].output_edges[k]->num_pack_patterns
276-
* sizeof(int));
245+
// insert the found pattern name to the hash table. If this pattern is inserted
246+
// for the first time, then its index is the current size of the hash table
247+
// otherwise the insert function will return an iterator of the previously
248+
// inserted element with the index given to that pattern
249+
std::string pattern_name(output_edge->pack_pattern_names[m]);
250+
int index = (pattern_names.insert({pattern_name, pattern_names.size()}).first)->second;
251+
if (!output_edge->pack_pattern_indices) {
252+
output_edge->pack_pattern_indices = (int*) vtr::malloc(output_edge->num_pack_patterns * sizeof(int));
277253
}
278-
pb_graph_node->output_pins[i][j].output_edges[k]->pack_pattern_indices[m] = index;
254+
output_edge->pack_pattern_indices[m] = index;
279255
// if this output edges belongs to a pack pattern. Expand forward starting from
280256
// all its output pins to check if you need to infer pattern for direct connections
281-
auto& output_edge = pb_graph_node->output_pins[i][j].output_edges[k];
282257
for (int ipin = 0; ipin < output_edge->num_output_pins; ipin++) {
283258
forward_infer_pattern(output_edge->output_pins[ipin]);
284259
}
@@ -287,29 +262,31 @@ static void discover_pattern_names_in_pb_graph_node(
287262
// if the output edge to this pin is annotated with a pack pattern
288263
// trace the inputs to this pin and mark them to infer pattern
289264
// if they are direct connections (num_input_edges == 1)
290-
if (hasPattern == true) {
265+
if (hasPattern) {
291266
backward_infer_pattern(&pb_graph_node->output_pins[i][j]);
292267
}
293268
}
294269
}
295270

296-
for (i = 0; i < pb_graph_node->num_clock_ports; i++) {
297-
for (j = 0; j < pb_graph_node->num_clock_pins[i]; j++) {
298-
hasPattern = false;
299-
for (k = 0; k < pb_graph_node->clock_pins[i][j].num_output_edges; k++) {
300-
for (m = 0; m < pb_graph_node->clock_pins[i][j].output_edges[k]->num_pack_patterns; m++) {
271+
for (int i = 0; i < pb_graph_node->num_clock_ports; i++) {
272+
for (int j = 0; j < pb_graph_node->num_clock_pins[i]; j++) {
273+
bool hasPattern = false;
274+
for (int k = 0; k < pb_graph_node->clock_pins[i][j].num_output_edges; k++) {
275+
auto& output_edge = pb_graph_node->clock_pins[i][j].output_edges[k];
276+
for (int m = 0; m < output_edge->num_pack_patterns; m++) {
301277
hasPattern = true;
302-
index = add_pattern_name_to_hash(nhash,
303-
pb_graph_node->clock_pins[i][j].output_edges[k]->pack_pattern_names[m], ncount);
304-
if (pb_graph_node->clock_pins[i][j].output_edges[k]->pack_pattern_indices == nullptr) {
305-
pb_graph_node->clock_pins[i][j].output_edges[k]->pack_pattern_indices =
306-
(int*) vtr::malloc(pb_graph_node->clock_pins[i][j].output_edges[k]->num_pack_patterns
307-
* sizeof(int));
278+
// insert the found pattern name to the hash table. If this pattern is inserted
279+
// for the first time, then its index is the current size of the hash table
280+
// otherwise the insert function will return an iterator of the previously
281+
// inserted element with the index given to that pattern
282+
std::string pattern_name(output_edge->pack_pattern_names[m]);
283+
int index = (pattern_names.insert({pattern_name, pattern_names.size()}).first)->second;
284+
if (output_edge->pack_pattern_indices == nullptr) {
285+
output_edge->pack_pattern_indices = (int*) vtr::malloc(output_edge->num_pack_patterns * sizeof(int));
308286
}
309-
pb_graph_node->clock_pins[i][j].output_edges[k]->pack_pattern_indices[m] = index;
287+
output_edge->pack_pattern_indices[m] = index;
310288
// if this output edges belongs to a pack pattern. Expand forward starting from
311289
// all its output pins to check if you need to infer pattern for direct connections
312-
auto& output_edge = pb_graph_node->clock_pins[i][j].output_edges[k];
313290
for (int ipin = 0; ipin < output_edge->num_output_pins; ipin++) {
314291
forward_infer_pattern(output_edge->output_pins[ipin]);
315292
}
@@ -318,17 +295,17 @@ static void discover_pattern_names_in_pb_graph_node(
318295
// if the output edge to this pin is annotated with a pack pattern
319296
// trace the inputs to this pin and mark them to infer pattern
320297
// if they are direct connections (num_input_edges == 1)
321-
if (hasPattern == true) {
298+
if (hasPattern) {
322299
backward_infer_pattern(&pb_graph_node->clock_pins[i][j]);
323300
}
324301
}
325302
}
326303

327-
for (i = 0; i < pb_graph_node->pb_type->num_modes; i++) {
328-
for (j = 0; j < pb_graph_node->pb_type->modes[i].num_pb_type_children; j++) {
329-
for (k = 0; k < pb_graph_node->pb_type->modes[i].pb_type_children[j].num_pb; k++) {
304+
for (int i = 0; i < pb_graph_node->pb_type->num_modes; i++) {
305+
for (int j = 0; j < pb_graph_node->pb_type->modes[i].num_pb_type_children; j++) {
306+
for (int k = 0; k < pb_graph_node->pb_type->modes[i].pb_type_children[j].num_pb; k++) {
330307
discover_pattern_names_in_pb_graph_node(
331-
&pb_graph_node->child_pb_graph_nodes[i][j][k], nhash, ncount);
308+
&pb_graph_node->child_pb_graph_nodes[i][j][k], pattern_names);
332309
}
333310
}
334311
}
@@ -358,24 +335,18 @@ static void backward_infer_pattern(t_pb_graph_pin *pb_graph_pin) {
358335
* Allocates memory for models and loads the name of the packing pattern
359336
* so that it can be identified and loaded with more complete information later
360337
*/
361-
static t_pack_patterns *alloc_and_init_pattern_list_from_hash(const int ncount,
362-
t_hash **nhash) {
363-
t_pack_patterns *nlist;
364-
t_hash_iterator hash_iter;
365-
t_hash *curr_pattern;
366-
367-
nlist = new t_pack_patterns[ncount];
368-
369-
hash_iter = start_hash_table_iterator();
370-
curr_pattern = get_next_hash(nhash, &hash_iter);
371-
while (curr_pattern != nullptr) {
372-
VTR_ASSERT(nlist[curr_pattern->index].name == nullptr);
373-
nlist[curr_pattern->index].name = vtr::strdup(curr_pattern->name);
374-
nlist[curr_pattern->index].root_block = nullptr;
375-
nlist[curr_pattern->index].is_chain = false;
376-
nlist[curr_pattern->index].index = curr_pattern->index;
377-
curr_pattern = get_next_hash(nhash, &hash_iter);
338+
static t_pack_patterns *alloc_and_init_pattern_list_from_hash(std::unordered_map<std::string, int> pattern_names) {
339+
340+
t_pack_patterns* nlist = new t_pack_patterns[pattern_names.size()];
341+
342+
for (const auto& curr_pattern : pattern_names) {
343+
VTR_ASSERT(nlist[curr_pattern.second].name == nullptr);
344+
nlist[curr_pattern.second].name = vtr::strdup(curr_pattern.first.c_str());
345+
nlist[curr_pattern.second].root_block = nullptr;
346+
nlist[curr_pattern.second].is_chain = false;
347+
nlist[curr_pattern.second].index = curr_pattern.second;
378348
}
349+
379350
return nlist;
380351
}
381352

vpr/src/util/hash.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@ using namespace std;
77

88
#include "hash.h"
99

10-
t_hash **
11-
alloc_hash_table() {
10+
t_hash ** alloc_hash_table() {
1211

1312
/* Creates a hash table with HASHSIZE different locations (hash values). */
1413

1514
t_hash **hash_table;
1615

17-
hash_table = (t_hash **) vtr::calloc(sizeof(t_hash *),
18-
HASHSIZE);
16+
hash_table = (t_hash **) vtr::calloc(sizeof(t_hash *), HASHSIZE);
1917
return (hash_table);
2018
}
2119

@@ -51,8 +49,7 @@ t_hash_iterator start_hash_table_iterator() {
5149
return (hash_iterator);
5250
}
5351

54-
t_hash *
55-
get_next_hash(t_hash **hash_table, t_hash_iterator *hash_iterator) {
52+
t_hash * get_next_hash(t_hash **hash_table, t_hash_iterator *hash_iterator) {
5653

5754
/* Returns the next occupied hash entry, and moves the iterator structure *
5855
* forward so the next call gets the next entry. */
@@ -76,8 +73,7 @@ get_next_hash(t_hash **hash_table, t_hash_iterator *hash_iterator) {
7673
return (h_ptr);
7774
}
7875

79-
t_hash *
80-
insert_in_hash_table(t_hash **hash_table, const char *name,
76+
t_hash * insert_in_hash_table(t_hash **hash_table, const char *name,
8177
int next_free_index) {
8278

8379
/* Adds the string pointed to by name to the hash table, and returns the *
@@ -119,8 +115,7 @@ insert_in_hash_table(t_hash **hash_table, const char *name,
119115
return (h_ptr);
120116
}
121117

122-
t_hash *
123-
get_hash_entry(t_hash **hash_table, const char *name) {
118+
t_hash * get_hash_entry(t_hash **hash_table, const char *name) {
124119

125120
/* Returns the hash entry with this name, or NULL if there is no *
126121
* corresponding entry. */

0 commit comments

Comments
 (0)