gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
trie.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012 Google
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * Authors: Gabe Black
29  */
30 
31 #ifndef __BASE_TRIE_HH__
32 #define __BASE_TRIE_HH__
33 
34 #include <cassert>
35 
36 #include "base/cprintf.hh"
37 #include "base/misc.hh"
38 #include "base/types.hh"
39 
40 // Key has to be an integral type.
41 template <class Key, class Value>
42 class Trie
43 {
44  protected:
45  struct Node
46  {
47  Key key;
48  Key mask;
49 
50  bool
51  matches(Key test)
52  {
53  return (test & mask) == key;
54  }
55 
56  Value *value;
57 
59  Node *kids[2];
60 
61  Node(Key _key, Key _mask, Value *_val) :
62  key(_key & _mask), mask(_mask), value(_val),
63  parent(NULL)
64  {
65  kids[0] = NULL;
66  kids[1] = NULL;
67  }
68 
69  void
71  {
72  if (kids[1]) {
73  kids[1]->clear();
74  delete kids[1];
75  kids[1] = NULL;
76  }
77  if (kids[0]) {
78  kids[0]->clear();
79  delete kids[0];
80  kids[0] = NULL;
81  }
82  }
83 
84  void
85  dump(int level)
86  {
87  for (int i = 1; i < level; i++) {
88  cprintf("|");
89  }
90  if (level == 0)
91  cprintf("Root ");
92  else
93  cprintf("+ ");
94  cprintf("(%p, %p, %#X, %#X, %p)\n", parent, this, key, mask, value);
95  if (kids[0])
96  kids[0]->dump(level + 1);
97  if (kids[1])
98  kids[1]->dump(level + 1);
99  }
100  };
101 
102  protected:
103  Node head;
104 
105  public:
106  typedef Node *Handle;
107 
108  Trie() : head(0, 0, NULL)
109  {}
110 
111  static const unsigned MaxBits = sizeof(Key) * 8;
112 
113  private:
124  bool
125  goesAfter(Node **parent, Node *kid, Key key, Key new_mask)
126  {
127  if (kid && kid->matches(key) && (kid->mask & new_mask) == kid->mask) {
128  *parent = kid;
129  return true;
130  } else {
131  return false;
132  }
133  }
134 
143  Key
144  extendMask(Key orig)
145  {
146  // Just in case orig was 0.
147  const Key msb = ULL(1) << (MaxBits - 1);
148  return orig | (orig >> 1) | msb;
149  }
150 
158  Handle
159  lookupHandle(Key key)
160  {
161  Node *node = &head;
162  while (node) {
163  if (node->value)
164  return node;
165 
166  if (node->kids[0] && node->kids[0]->matches(key))
167  node = node->kids[0];
168  else if (node->kids[1] && node->kids[1]->matches(key))
169  node = node->kids[1];
170  else
171  node = NULL;
172  }
173 
174  return NULL;
175  }
176 
177  public:
185  Handle
186  insert(Key key, unsigned width, Value *val)
187  {
188  // Build a mask which masks off all the bits we don't care about.
189  Key new_mask = ~(Key)0;
190  if (width < MaxBits)
191  new_mask <<= (MaxBits - width);
192  // Use it to tidy up the key.
193  key &= new_mask;
194 
195  // Walk past all the nodes this new node will be inserted after. They
196  // can be ignored for the purposes of this function.
197  Node *node = &head;
198  while (goesAfter(&node, node->kids[0], key, new_mask) ||
199  goesAfter(&node, node->kids[1], key, new_mask))
200  {}
201  assert(node);
202 
203  Key cur_mask = node->mask;
204  // If we're already where the value needs to be...
205  if (cur_mask == new_mask) {
206  assert(!node->value);
207  node->value = val;
208  return node;
209  }
210 
211  for (unsigned int i = 0; i < 2; i++) {
212  Node *&kid = node->kids[i];
213  Node *new_node;
214  if (!kid) {
215  // No kid. Add a new one.
216  new_node = new Node(key, new_mask, val);
217  new_node->parent = node;
218  kid = new_node;
219  return new_node;
220  }
221 
222  // Walk down the leg until something doesn't match or we run out
223  // of bits.
224  Key last_mask;
225  bool done;
226  do {
227  last_mask = cur_mask;
228  cur_mask = extendMask(cur_mask);
229  done = ((key & cur_mask) != (kid->key & cur_mask)) ||
230  last_mask == new_mask;
231  } while (!done);
232  cur_mask = last_mask;
233 
234  // If this isn't the right leg to go down at all, skip it.
235  if (cur_mask == node->mask)
236  continue;
237 
238  // At the point we walked to above, add a new node.
239  new_node = new Node(key, cur_mask, NULL);
240  new_node->parent = node;
241  kid->parent = new_node;
242  new_node->kids[0] = kid;
243  kid = new_node;
244 
245  // If we ran out of bits, the value goes right here.
246  if (cur_mask == new_mask) {
247  new_node->value = val;
248  return new_node;
249  }
250 
251  // Still more bits to deal with, so add a new node for that path.
252  new_node = new Node(key, new_mask, val);
253  new_node->parent = kid;
254  kid->kids[1] = new_node;
255  return new_node;
256  }
257 
258  panic("Reached the end of the Trie insert function!\n");
259  return NULL;
260  }
261 
267  Value *
268  lookup(Key key)
269  {
270  Node *node = lookupHandle(key);
271  if (node)
272  return node->value;
273  else
274  return NULL;
275  }
276 
282  Value *
283  remove(Handle handle)
284  {
285  Node *node = handle;
286  Value *val = node->value;
287  if (node->kids[1]) {
288  assert(node->value);
289  node->value = NULL;
290  return val;
291  }
292  if (!node->parent)
293  panic("Trie: Can't remove root node.\n");
294 
295  Node *parent = node->parent;
296 
297  // If there's a kid, fix up it's parent pointer.
298  if (node->kids[0])
299  node->kids[0]->parent = parent;
300  // Figure out which kid we are, and update our parent's pointers.
301  if (parent->kids[0] == node)
302  parent->kids[0] = node->kids[0];
303  else if (parent->kids[1] == node)
304  parent->kids[1] = node->kids[0];
305  else
306  panic("Trie: Inconsistent parent/kid relationship.\n");
307  // Make sure if the parent only has one kid, it's kid[0].
308  if (parent->kids[1] && !parent->kids[0]) {
309  parent->kids[0] = parent->kids[1];
310  parent->kids[1] = NULL;
311  }
312 
313  // If the parent has less than two kids and no cargo and isn't the
314  // root, delete it too.
315  if (!parent->kids[1] && !parent->value && parent->parent)
316  remove(parent);
317  delete node;
318  return val;
319  }
320 
326  Value *
327  remove(Key key)
328  {
329  Handle handle = lookupHandle(key);
330  if (!handle)
331  return NULL;
332  return remove(handle);
333  }
334 
339  void
341  {
342  head.clear();
343  }
344 
349  void
350  dump(const char *title)
351  {
352  cprintf("**************************************************\n");
353  cprintf("*** Start of Trie: %s\n", title);
354  cprintf("*** (parent, me, key, mask, value pointer)\n");
355  cprintf("**************************************************\n");
356  head.dump(0);
357  }
358 };
359 
360 #endif
Handle insert(Key key, unsigned width, Value *val)
Method which inserts a key/value pair into the trie.
Definition: trie.hh:186
bool goesAfter(Node **parent, Node *kid, Key key, Key new_mask)
A utility method which checks whether the key being looked up lies beyond the Node being examined...
Definition: trie.hh:125
Trie()
Definition: trie.hh:108
Bitfield< 7 > i
Definition: miscregs.hh:1378
#define panic(...)
Definition: misc.hh:153
bool matches(Key test)
Definition: trie.hh:51
static const unsigned MaxBits
Definition: trie.hh:111
Value * value
Definition: trie.hh:56
Node(Key _key, Key _mask, Value *_val)
Definition: trie.hh:61
Key mask
Definition: trie.hh:48
void clear()
A method which removes all key/value pairs from the trie.
Definition: trie.hh:340
Handle lookupHandle(Key key)
Method which looks up the Handle corresponding to a particular key.
Definition: trie.hh:159
Node * kids[2]
Definition: trie.hh:59
Bitfield< 63 > val
Definition: misc.hh:770
Key extendMask(Key orig)
A utility method which extends a mask value one more bit towards the lsb.
Definition: trie.hh:144
void clear()
Definition: trie.hh:70
void dump(int level)
Definition: trie.hh:85
Value * lookup(Key key)
Method which looks up the Value corresponding to a particular key.
Definition: trie.hh:268
Node head
Definition: trie.hh:103
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
#define ULL(N)
uint64_t constant
Definition: types.hh:50
void dump(const char *title)
A debugging method which prints the contents of this trie.
Definition: trie.hh:350
Bitfield< 20 > level
Definition: intmessage.hh:48
Node * Handle
Definition: trie.hh:106
Definition: trie.hh:42
Bitfield< 4 > width
Definition: miscregs.hh:1383
Key key
Definition: trie.hh:47
Node * parent
Definition: trie.hh:58
if(it_gpu==gpuTypeMap.end())
Definition: gpu_nomali.cc:75
void cprintf(const char *format, const Args &...args)
Definition: cprintf.hh:155

Generated on Fri Jun 9 2017 13:03:41 for gem5 by doxygen 1.8.6