addr_range_map.hh revision 12783:a610dc4b5778
14484Sbinkertn@umich.edu/*
24484Sbinkertn@umich.edu * Copyright (c) 2012, 2018 ARM Limited
34484Sbinkertn@umich.edu * All rights reserved
44484Sbinkertn@umich.edu *
54484Sbinkertn@umich.edu * The license below extends only to copyright in the software and shall
64484Sbinkertn@umich.edu * not be construed as granting a license to any other intellectual
74484Sbinkertn@umich.edu * property including but not limited to intellectual property relating
84484Sbinkertn@umich.edu * to a hardware implementation of the functionality of the software
94484Sbinkertn@umich.edu * licensed hereunder.  You may use the software subject to the license
104484Sbinkertn@umich.edu * terms below provided that you ensure that this notice is replicated
114484Sbinkertn@umich.edu * unmodified and in its entirety in all distributions of the software,
124484Sbinkertn@umich.edu * modified or unmodified, in source code or in binary form.
134484Sbinkertn@umich.edu *
144484Sbinkertn@umich.edu * Copyright (c) 2006 The Regents of The University of Michigan
154484Sbinkertn@umich.edu * All rights reserved.
164484Sbinkertn@umich.edu *
174484Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without
184484Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are
194484Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright
204484Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer;
214484Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright
224484Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the
234484Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution;
244484Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its
254484Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from
264484Sbinkertn@umich.edu * this software without specific prior written permission.
274484Sbinkertn@umich.edu *
284484Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
294484Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
304484Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
314484Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
324484Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
334484Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
344484Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
354484Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
364484Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
374484Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
384484Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
394484Sbinkertn@umich.edu *
404484Sbinkertn@umich.edu * Authors: Ali Saidi
414484Sbinkertn@umich.edu *          Andreas Hansson
424484Sbinkertn@umich.edu */
434484Sbinkertn@umich.edu
444484Sbinkertn@umich.edu#ifndef __BASE_ADDR_RANGE_MAP_HH__
454484Sbinkertn@umich.edu#define __BASE_ADDR_RANGE_MAP_HH__
464484Sbinkertn@umich.edu
474484Sbinkertn@umich.edu#include <cstddef>
484484Sbinkertn@umich.edu#include <functional>
494484Sbinkertn@umich.edu#include <list>
504484Sbinkertn@umich.edu#include <map>
514484Sbinkertn@umich.edu#include <utility>
524484Sbinkertn@umich.edu
534484Sbinkertn@umich.edu#include "base/addr_range.hh"
544484Sbinkertn@umich.edu#include "base/types.hh"
554484Sbinkertn@umich.edu
564484Sbinkertn@umich.edu/**
574484Sbinkertn@umich.edu * The AddrRangeMap uses an STL map to implement an interval tree for
584484Sbinkertn@umich.edu * address decoding. The value stored is a template type and can be
594484Sbinkertn@umich.edu * e.g. a port identifier, or a pointer.
604484Sbinkertn@umich.edu */
614484Sbinkertn@umich.edutemplate <typename V, int max_cache_size=0>
624484Sbinkertn@umich.educlass AddrRangeMap
634484Sbinkertn@umich.edu{
644484Sbinkertn@umich.edu  private:
654484Sbinkertn@umich.edu    typedef std::map<AddrRange, V> RangeMap;
664484Sbinkertn@umich.edu
674484Sbinkertn@umich.edu  public:
684484Sbinkertn@umich.edu    typedef typename RangeMap::iterator iterator;
694484Sbinkertn@umich.edu    typedef typename RangeMap::const_iterator const_iterator;
704484Sbinkertn@umich.edu
714484Sbinkertn@umich.edu    /**
724484Sbinkertn@umich.edu     * Find entry that contains the given address range
734484Sbinkertn@umich.edu     *
744484Sbinkertn@umich.edu     * Searches through the ranges in the address map and returns an
754484Sbinkertn@umich.edu     * iterator to the entry which range is a superset of the input
764484Sbinkertn@umich.edu     * address range. Returns end() if none found.
77     *
78     * @param r An input address range
79     * @return An iterator that contains the input address range
80     */
81    const_iterator
82    contains(const AddrRange &r) const
83    {
84        return find(r, [r](const AddrRange r1) { return r.isSubset(r1); });
85    }
86
87    /**
88     * Find entry that contains the given address
89     *
90     * Searches through the ranges in the address map and returns an
91     * iterator to the entry which range is a superset of the input
92     * address. Returns end() if none found.
93     *
94     * @param r An input address
95     * @return An iterator that contains the input address
96     */
97    const_iterator
98    contains(Addr r) const
99    {
100        return contains(RangeSize(r, 1));
101    }
102
103    /**
104     * Find entry that intersects with the given address range
105     *
106     * Searches through the ranges in the address map and returns an
107     * iterator to the first entry which range intersects with the
108     * input address.
109     *
110     * @param r An input address
111     * @return An iterator that intersects with the input address range
112     */
113    const_iterator
114    intersects(const AddrRange &r) const
115    {
116        return find(r, [r](const AddrRange r1) { return r.intersects(r1); });
117    }
118
119    const_iterator
120    insert(const AddrRange &r, const V& d)
121    {
122        if (intersects(r) != end())
123            return tree.end();
124
125        return tree.insert(std::make_pair(r, d)).first;
126    }
127
128    void
129    erase(iterator p)
130    {
131        cache.remove(p);
132        tree.erase(p);
133    }
134
135    void
136    erase(iterator p, iterator q)
137    {
138        for (auto it = p; it != q; it++) {
139            cache.remove(p);
140        }
141        tree.erase(p,q);
142    }
143
144    void
145    clear()
146    {
147        cache.erase(cache.begin(), cache.end());
148        tree.erase(tree.begin(), tree.end());
149    }
150
151    const_iterator
152    begin() const
153    {
154        return tree.begin();
155    }
156
157    iterator
158    begin()
159    {
160        return tree.begin();
161    }
162
163    const_iterator
164    end() const
165    {
166        return tree.end();
167    }
168
169    iterator
170    end()
171    {
172        return tree.end();
173    }
174
175    std::size_t
176    size() const
177    {
178        return tree.size();
179    }
180
181    bool
182    empty() const
183    {
184        return tree.empty();
185    }
186
187  private:
188    /**
189     * Add an address range map entry to the cache.
190     *
191     * @param it Iterator to the entry in the address range map
192     */
193    void
194    addNewEntryToCache(const_iterator it) const
195    {
196        if (max_cache_size != 0) {
197            // If there's a cache, add this element to it.
198            if (cache.size() >= max_cache_size) {
199                // If the cache is full, move the last element to the
200                // front and overwrite it with the new value. This
201                // avoids creating or destroying elements of the list.
202                auto last = cache.end();
203                last--;
204                *last = it;
205                if (max_cache_size > 1)
206                    cache.splice(cache.begin(), cache, last);
207            } else {
208                cache.push_front(it);
209            }
210        }
211    }
212
213    /**
214     * Find entry that satisfies a condition on an address range
215     *
216     * Searches through the ranges in the address map and returns an
217     * iterator to the entry that satisfies the input conidition on
218     * the input address range. Returns end() if none found.
219     *
220     * @param r An input address range
221     * @param f A condition on an address range
222     * @return An iterator that contains the input address range
223     */
224    const_iterator
225    find(const AddrRange &r, std::function<bool(const AddrRange)> cond) const
226    {
227        // Check the cache first
228        for (auto c = cache.begin(); c != cache.end(); c++) {
229            auto it = *c;
230            if (cond(it->first)) {
231                // If this entry matches, promote it to the front
232                // of the cache and return it.
233                cache.splice(cache.begin(), cache, c);
234                return it;
235            }
236        }
237
238        const_iterator next = tree.upper_bound(r);
239        if (next != end() && cond(next->first)) {
240            addNewEntryToCache(next);
241            return next;
242        }
243        if (next == begin())
244            return end();
245        next--;
246
247        const_iterator i;
248        do {
249            i = next;
250            if (cond(i->first)) {
251                addNewEntryToCache(i);
252                return i;
253            }
254            // Keep looking if the next range merges with the current one.
255        } while (next != begin() &&
256                 (--next)->first.mergesWith(i->first));
257
258        return end();
259    }
260
261    RangeMap tree;
262
263    /**
264     * A list of iterator that correspond to the max_cache_size most
265     * recently used entries in the address range map. This mainly
266     * used to optimize lookups. The elements in the list should
267     * always be valid iterators of the tree.
268     */
269    mutable std::list<const_iterator> cache;
270};
271
272#endif //__BASE_ADDR_RANGE_MAP_HH__
273