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:
Gabe Black
2020-03-29 03:14:50 -07:00
parent 3ec5c71875
commit 0172089203
3 changed files with 41 additions and 0 deletions

View File

@@ -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")

View File

@@ -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)
{

View File

@@ -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.