From: Gabe Black Date: Sun, 29 Mar 2020 10:14:50 +0000 (-0700) Subject: mem: Support initializing a memory with an image file. X-Git-Tag: v20.0.0.0~191 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0172089203592037f99fc89126285896c73e6a60;p=gem5.git 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 Maintainer: Gabe Black Tested-by: Gem5 Cloud Project GCB service account <345032938727@cloudbuild.gserviceaccount.com> Tested-by: kokoro --- diff --git a/src/mem/AbstractMemory.py b/src/mem/AbstractMemory.py index 897e9e3cd..4c21d529c 100644 --- a/src/mem/AbstractMemory.py +++ b/src/mem/AbstractMemory.py @@ -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") diff --git a/src/mem/abstract_mem.cc b/src/mem/abstract_mem.cc index b5412badf..aa800113b 100644 --- a/src/mem/abstract_mem.cc +++ b/src/mem/abstract_mem.cc @@ -43,6 +43,8 @@ #include #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) { diff --git a/src/mem/abstract_mem.hh b/src/mem/abstract_mem.hh index b1d54fdeb..616fd0e26 100644 --- a/src/mem/abstract_mem.hh +++ b/src/mem/abstract_mem.hh @@ -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.