aboutsummaryrefslogtreecommitdiff
path: root/spike_main
diff options
context:
space:
mode:
authorParshintsev Anatoly <anatoly.parshintsev@syntacore.com>2022-10-10 14:03:34 +0300
committerParshintsev Anatoly <anatoly.parshintsev@syntacore.com>2022-11-30 21:00:39 +0300
commit1f920f914bd7dfb343a27248cab273a14feb6925 (patch)
tree7221addcd98a98b8333ac67b02e370bbfb9ecf10 /spike_main
parent70f8aa01b803f4dbc0461fd7c986c1ca76d4b1d9 (diff)
downloadriscv-isa-sim-1f920f914bd7dfb343a27248cab273a14feb6925.zip
riscv-isa-sim-1f920f914bd7dfb343a27248cab273a14feb6925.tar.gz
riscv-isa-sim-1f920f914bd7dfb343a27248cab273a14feb6925.tar.bz2
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.
Diffstat (limited to 'spike_main')
-rw-r--r--spike_main/spike.cc63
1 files changed, 41 insertions, 22 deletions
diff --git a/spike_main/spike.cc b/spike_main/spike.cc
index cd8a6d8..5815761 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<mem_cfg_t> &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<mem_cfg_t>
+merge_overlapping_memory_regions(std::vector<mem_cfg_t> 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<mem_cfg_t> 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<mem_cfg_t> parse_mem_layout(const char* arg)
@@ -217,9 +235,10 @@ static std::vector<mem_cfg_t> 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<std::pair<reg_t, mem_t*>> make_mems(const std::vector<mem_cfg_t> &layout)