From 1f920f914bd7dfb343a27248cab273a14feb6925 Mon Sep 17 00:00:00 2001 From: Parshintsev Anatoly Date: Mon, 10 Oct 2022 14:03:34 +0300 Subject: [PATCH] Reimplement memory merging routines This commit simplifies the codebase by factoring out memory merging and intersection checking routines into separate functions. This allows us to check for corner cases more easily. --- spike_main/spike.cc | 63 +++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/spike_main/spike.cc b/spike_main/spike.cc index cd8a6d89..5815761c 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -123,31 +123,49 @@ bool sort_mem_region(const mem_cfg_t &a, const mem_cfg_t &b) return (a.base < b.base); } -void merge_overlapping_memory_regions(std::vector &mems) +static bool check_mem_overlap(const mem_cfg_t& L, const mem_cfg_t& R) { - // check the user specified memory regions and merge the overlapping or - // eliminate the containing parts - assert(!mems.empty()); + const reg_t L_end = L.base + L.size - 1; + const reg_t R_end = R.base + R.size - 1; + + return std::max(L.base, R.base) <= std::min(L_end, R_end); +} + +static mem_cfg_t merge_mem_regions(const mem_cfg_t& L, const mem_cfg_t& R) +{ + // one can merge only intersecting regions + assert(check_mem_overlap(L, R)); + + const reg_t merged_base = std::min(L.base, R.base); + const reg_t merged_end_incl = std::max(L.base + L.size - 1, R.base + R.size - 1); + const reg_t merged_size = merged_end_incl - merged_base + 1; + + return mem_cfg_t(merged_base, merged_size); +} + +// check the user specified memory regions and merge the overlapping or +// eliminate the containing parts +static std::vector +merge_overlapping_memory_regions(std::vector mems) +{ + if (mems.empty()) + return {}; std::sort(mems.begin(), mems.end(), sort_mem_region); - for (auto it = mems.begin() + 1; it != mems.end(); ) { - reg_t start = prev(it)->base; - reg_t end = prev(it)->base + prev(it)->size; - reg_t start2 = it->base; - reg_t end2 = it->base + it->size; - - //contains -> remove - if (start2 >= start && end2 <= end) { - it = mems.erase(it); - //partial overlapped -> extend - } else if (start2 >= start && start2 < end) { - prev(it)->size = std::max(end, end2) - start; - it = mems.erase(it); - // no overlapping -> keep it - } else { - it++; + + std::vector merged_mem; + merged_mem.push_back(mems.front()); + + for (auto mem_it = std::next(mems.begin()); mem_it != mems.end(); ++mem_it) { + const auto& mem_int = *mem_it; + if (!check_mem_overlap(merged_mem.back(), mem_int)) { + merged_mem.push_back(mem_int); + continue; } + merged_mem.back() = merge_mem_regions(merged_mem.back(), mem_int); } + + return merged_mem; } static std::vector parse_mem_layout(const char* arg) @@ -217,9 +235,10 @@ static std::vector parse_mem_layout(const char* arg) arg = p + 1; } - merge_overlapping_memory_regions(res); + auto merged_mem = merge_overlapping_memory_regions(res); - return res; + assert(!merged_mem.empty()); + return merged_mem; } static std::vector> make_mems(const std::vector &layout)