mem: Support initializing a memory with an image file.
This is particularly useful for ROMs. It avoids forcing other components of the simulation (the System object, the Workload object) from having to know what ROMs exist, where they are, and what goes on them, and leaves that to the config script. Change-Id: Ibbcffffcb82e0d289f0b3942728c30b8f69d28ba Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/27267 Reviewed-by: Gabe Black <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com> Tested-by: Gem5 Cloud Project GCB service account <345032938727@cloudbuild.gserviceaccount.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -64,3 +64,8 @@ class AbstractMemory(ClockedObject):
|
||||
# configuration information about the physical memory layout to
|
||||
# the kernel, e.g. using ATAG or ACPI
|
||||
conf_table_reported = Param.Bool(True, "Report to configuration table")
|
||||
|
||||
# Image file to load into this memory as its initial contents. This is
|
||||
# particularly useful for ROMs.
|
||||
image_file = Param.String('',
|
||||
"Image to load into memory as its initial contents")
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
#include <vector>
|
||||
|
||||
#include "arch/locked_mem.hh"
|
||||
#include "base/loader/memory_image.hh"
|
||||
#include "base/loader/object_file.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "debug/LLSC.hh"
|
||||
@@ -66,6 +68,38 @@ AbstractMemory::AbstractMemory(const Params *p) :
|
||||
range.to_string());
|
||||
}
|
||||
|
||||
void
|
||||
AbstractMemory::initState()
|
||||
{
|
||||
ClockedObject::initState();
|
||||
|
||||
const auto &file = params()->image_file;
|
||||
if (file == "")
|
||||
return;
|
||||
|
||||
auto *object = createObjectFile(file, true);
|
||||
fatal_if(!object, "%s: Could not load %s.", name(), file);
|
||||
|
||||
panic_if(!object->loadGlobalSymbols(debugSymbolTable),
|
||||
"%s: Could not load symbols from %s.", name(), file);
|
||||
|
||||
MemoryImage image = object->buildImage();
|
||||
|
||||
AddrRange image_range(image.minAddr(), image.maxAddr());
|
||||
if (!range.contains(image_range.start())) {
|
||||
warn("%s: Moving image from %s to memory address range %s.",
|
||||
name(), image_range.to_string(), range.to_string());
|
||||
image = image.offset(range.start());
|
||||
image_range = AddrRange(image.minAddr(), image.maxAddr());
|
||||
}
|
||||
panic_if(!image_range.isSubset(range), "%s: memory image %s doesn't fit.",
|
||||
name(), file);
|
||||
|
||||
PortProxy proxy([this](PacketPtr pkt) { functionalAccess(pkt); }, size());
|
||||
|
||||
panic_if(!image.write(proxy), "%s: Unable to write image.");
|
||||
}
|
||||
|
||||
void
|
||||
AbstractMemory::setBackingStore(uint8_t* pmem_addr)
|
||||
{
|
||||
|
||||
@@ -209,6 +209,8 @@ class AbstractMemory : public ClockedObject
|
||||
AbstractMemory(const Params* p);
|
||||
virtual ~AbstractMemory() {}
|
||||
|
||||
void initState() override;
|
||||
|
||||
/**
|
||||
* See if this is a null memory that should never store data and
|
||||
* always return zero.
|
||||
|
||||
Reference in New Issue
Block a user