No public description

PiperOrigin-RevId: 797844866
Change-Id: If7867865eca03b12866ae45055a78cbe8a947b12
diff --git a/mpact/sim/util/program_loader/BUILD b/mpact/sim/util/program_loader/BUILD
index 421ffdf..3a3f113 100644
--- a/mpact/sim/util/program_loader/BUILD
+++ b/mpact/sim/util/program_loader/BUILD
@@ -47,6 +47,7 @@
         "//mpact/sim/util/memory",
         "@com_github_serge1_elfio//:elfio",
         "@com_google_absl//absl/container:flat_hash_map",
+        "@com_google_absl//absl/functional:any_invocable",
         "@com_google_absl//absl/status",
         "@com_google_absl//absl/status:statusor",
         "@com_google_absl//absl/strings",
diff --git a/mpact/sim/util/program_loader/elf_program_loader.cc b/mpact/sim/util/program_loader/elf_program_loader.cc
index 4c7e5a6..ec4beea 100644
--- a/mpact/sim/util/program_loader/elf_program_loader.cc
+++ b/mpact/sim/util/program_loader/elf_program_loader.cc
@@ -20,6 +20,7 @@
 #include <cstring>
 #include <string>
 #include <utility>
+#include <vector>
 
 #include "absl/status/status.h"
 #include "absl/status/statusor.h"
@@ -41,6 +42,10 @@
                                    util::MemoryInterface* data_memory)
     : code_memory_(code_memory), data_memory_(data_memory) {}
 
+ElfProgramLoader::ElfProgramLoader(
+    const std::vector<MemoryDescriptor>& memories)
+    : memories_(&memories) {}
+
 ElfProgramLoader::ElfProgramLoader(util::MemoryInterface* memory)
     : code_memory_(memory), data_memory_(memory) {}
 
@@ -95,7 +100,7 @@
       if (type == STT_FUNC) {
         fcn_symbol_map_.emplace(value, name);
         function_range_map_.insert(
-            std::make_pair(AddressRange(value, size), name));
+            std::make_pair(AddressRange(value, size / text_size_scale_), name));
       }
     }
   }
@@ -123,14 +128,30 @@
     if (segment->get_file_size() == 0) continue;
     // Read the data from the elf file.
     if (dbg_if_ == nullptr) {  // Use memory interfaces.
-      auto* db = db_factory.Allocate(segment->get_file_size());
-      std::memcpy(db->raw_ptr(), segment->get_data(), segment->get_file_size());
-
-      if (segment->get_flags() &
-          PF_X) {  // Executable, so write to code memory.
-        code_memory_->Store(segment->get_virtual_address(), db);
-      } else {  // Write to data memory.
-        data_memory_->Store(segment->get_virtual_address(), db);
+      auto size = segment->get_file_size();
+      auto* db = db_factory.Allocate(size);
+      std::memcpy(db->raw_ptr(), segment->get_data(), size);
+      if (memories_ == nullptr) {
+        if (segment->get_flags() &
+            PF_X) {  // Executable, so write to code memory.
+          code_memory_->Store(segment->get_virtual_address(), db);
+        } else {  // Write to data memory.
+          data_memory_->Store(segment->get_virtual_address(), db);
+        }
+      } else {
+        int i = 0;
+        for (auto& memory : *memories_) {
+          if (memory.predicate_fcn(*segment)) {
+            if (memory.address_fcn) {
+              memory.memory->Store(
+                  memory.address_fcn(segment->get_virtual_address()), db);
+            } else {
+              memory.memory->Store(segment->get_virtual_address(), db);
+            }
+            break;
+          }
+          i++;
+        }
       }
       db->DecRef();
       continue;
diff --git a/mpact/sim/util/program_loader/elf_program_loader.h b/mpact/sim/util/program_loader/elf_program_loader.h
index 760f11b..a1ae625 100644
--- a/mpact/sim/util/program_loader/elf_program_loader.h
+++ b/mpact/sim/util/program_loader/elf_program_loader.h
@@ -22,8 +22,10 @@
 #include <vector>
 
 #include "absl/container/flat_hash_map.h"
+#include "absl/functional/any_invocable.h"
 #include "absl/status/statusor.h"
 #include "elfio/elfio.hpp"
+#include "elfio/elfio_segment.hpp"
 #include "elfio/elfio_symbols.hpp"
 #include "mpact/sim/generic/core_debug_interface.h"
 #include "mpact/sim/util/memory/memory_interface.h"
@@ -51,6 +53,20 @@
   }
 };
 
+// This struct is used to describe a memory to be used by the elf program loader
+// when there is more than one or two memories that have to be loaded.
+struct MemoryDescriptor {
+  // Pointer to the memory interface.
+  util::MemoryInterface* memory;
+  // Predicate function that takes a segment and return true if it should be
+  // loaded into this memory.
+  absl::AnyInvocable<bool(const ELFIO::segment&) const> predicate_fcn;
+  // Function that takes a segment load address and returns the address it
+  // should be loaded at in the memory. If not specified, the load address is
+  // used unmodified.
+  absl::AnyInvocable<uint64_t(uint64_t) const> address_fcn;
+};
+
 // This class wraps the elfio class to provide an easy interface to load the
 // segments of an elf executable file into memory. If both code and data
 // memories are given, then executable segments are loaded into code memory and
@@ -63,6 +79,7 @@
  public:
   ElfProgramLoader(util::MemoryInterface* code_memory,
                    util::MemoryInterface* data_memory);
+  ElfProgramLoader(const std::vector<MemoryDescriptor>& memories);
   explicit ElfProgramLoader(util::MemoryInterface* memory);
   explicit ElfProgramLoader(generic::CoreDebugInterface* dbg_if);
   ElfProgramLoader() = delete;
@@ -82,9 +99,13 @@
   // If the GNU stack size program header exists, return the memory size.
   absl::StatusOr<uint64_t> GetStackSize() const;
 
+  void set_text_size_scale(uint64_t scale) { text_size_scale_ = scale; }
+  void set_data_size_scale(uint64_t scale) { data_size_scale_ = scale; }
+
   const ELFIO::elfio* elf_reader() const { return &elf_reader_; }
 
  private:
+  const std::vector<MemoryDescriptor>* memories_ = nullptr;
   bool loaded_ = false;
   ELFIO::elfio elf_reader_;
   util::MemoryInterface* code_memory_ = nullptr;
@@ -95,6 +116,8 @@
   std::map<AddressRange, std::string, AddressRangeComp> function_range_map_;
   uint64_t has_stack_size_ = false;
   uint64_t stack_size_ = 0;
+  uint64_t text_size_scale_ = 1;
+  uint64_t data_size_scale_ = 1;
 };
 
 }  // namespace util