stdlib: Introduce an ARM Board
This changes adds a new board to the gem5 stdlib, which is capable of simulating an ARM based full system. It also adds an example config script to perform a boot-test using an Ubuntu 18.04 disk image. A test has been added in the gem5-library-example for the same. Change-Id: Ic95ee56084a444c7f1cf21cdcbf40585dcf5274a Signed-off-by: Kaustav Goswami <kggoswami@ucdavis.edu> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/58910 Reviewed-by: Bobby Bruce <bbruce@ucdavis.edu> Tested-by: kokoro <noreply+kokoro@google.com> Maintainer: Bobby Bruce <bbruce@ucdavis.edu>
This commit is contained in:
committed by
Kaustav Goswami
parent
1d93e72f2b
commit
53500ac611
149
configs/example/gem5_library/arm-ubuntu-boot-exit.py
Normal file
149
configs/example/gem5_library/arm-ubuntu-boot-exit.py
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
# Copyright (c) 2022 The Regents of the University of California
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met: redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer;
|
||||||
|
# redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution;
|
||||||
|
# neither the name of the copyright holders nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
"""
|
||||||
|
This script shows an example of booting an ARM based full system Ubuntu
|
||||||
|
disk image using the gem5's standard library. This simulation boots the disk
|
||||||
|
image using 2 TIMING CPU cores. The simulation ends when the startup is
|
||||||
|
completed successfully (i.e. when an `m5_exit instruction is reached on
|
||||||
|
successful boot).
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
```
|
||||||
|
scons build/ARM/gem5.opt -j<NUM_CPUS>
|
||||||
|
./build/ARM/gem5.opt configs/example/gem5_library/arm-ubuntu-boot-exit.py
|
||||||
|
```
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from gem5.isas import ISA
|
||||||
|
from m5.objects import ArmDefaultRelease
|
||||||
|
from gem5.utils.requires import requires
|
||||||
|
from gem5.resources.resource import Resource
|
||||||
|
from gem5.simulate.simulator import Simulator
|
||||||
|
from m5.objects import VExpress_GEM5_Foundation
|
||||||
|
from gem5.components.boards.arm_board import ArmBoard
|
||||||
|
from gem5.components.memory import DualChannelDDR4_2400
|
||||||
|
from gem5.components.processors.cpu_types import CPUTypes
|
||||||
|
from gem5.resources.resource import CustomDiskImageResource
|
||||||
|
from gem5.components.processors.simple_processor import SimpleProcessor
|
||||||
|
|
||||||
|
# This runs a check to ensure the gem5 binary is compiled for ARM.
|
||||||
|
|
||||||
|
requires(
|
||||||
|
isa_required=ISA.ARM,
|
||||||
|
)
|
||||||
|
|
||||||
|
# With ARM, we use simple caches.
|
||||||
|
|
||||||
|
from gem5.components.cachehierarchies.classic\
|
||||||
|
.private_l1_private_l2_cache_hierarchy import (
|
||||||
|
PrivateL1PrivateL2CacheHierarchy,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Here we setup the parameters of the l1 and l2 caches.
|
||||||
|
|
||||||
|
cache_hierarchy = PrivateL1PrivateL2CacheHierarchy(
|
||||||
|
l1d_size="16kB",
|
||||||
|
l1i_size="16kB",
|
||||||
|
l2_size="256kB",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Memory: Dual Channel DDR4 2400 DRAM device.
|
||||||
|
|
||||||
|
memory = DualChannelDDR4_2400(size = "2GB")
|
||||||
|
|
||||||
|
# Here we setup the processor. We use a simple TIMING processor. The config
|
||||||
|
# script was also tested with ATOMIC processor.
|
||||||
|
|
||||||
|
processor = SimpleProcessor(
|
||||||
|
cpu_type=CPUTypes.TIMING,
|
||||||
|
num_cores=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
# The ArmBoard requires a `release` to be specified. This adds all the
|
||||||
|
# extensions or features to the system. We are setting this to Armv8
|
||||||
|
# (ArmDefaultRelease) in this example config script.
|
||||||
|
|
||||||
|
release = ArmDefaultRelease()
|
||||||
|
|
||||||
|
# The platform sets up the memory ranges of all the on-chip and off-chip
|
||||||
|
# devices present on the ARM system.
|
||||||
|
|
||||||
|
platform = VExpress_GEM5_Foundation()
|
||||||
|
|
||||||
|
# Here we setup the board. The ArmBoard allows for Full-System ARM simulations.
|
||||||
|
|
||||||
|
board = ArmBoard(
|
||||||
|
clk_freq = "3GHz",
|
||||||
|
processor = processor,
|
||||||
|
memory = memory,
|
||||||
|
cache_hierarchy = cache_hierarchy,
|
||||||
|
release = release,
|
||||||
|
platform = platform
|
||||||
|
)
|
||||||
|
|
||||||
|
# Here we set the Full System workload.
|
||||||
|
|
||||||
|
# The `set_kernel_disk_workload` function on the ArmBoard accepts an ARM
|
||||||
|
# kernel, a disk image, and, path to the bootloader.
|
||||||
|
|
||||||
|
board.set_kernel_disk_workload(
|
||||||
|
|
||||||
|
# The ARM kernel will be automatically downloaded to the `~/.cache/gem5`
|
||||||
|
# directory if not already present. The arm-ubuntu-boot-exit was tested
|
||||||
|
# with `vmlinux.arm64`
|
||||||
|
|
||||||
|
kernel = Resource("arm64-linux-kernel-5.4.49"),
|
||||||
|
|
||||||
|
# The ARM ubuntu image will be automatically downloaded to the
|
||||||
|
# `~/.cache/gem5` directory if not already present.
|
||||||
|
|
||||||
|
disk_image = Resource("arm64-ubuntu-18.04-img"),
|
||||||
|
|
||||||
|
# We need to specify the path for the bootloader file `boot.arm64`.
|
||||||
|
|
||||||
|
bootloader = Resource("arm64-bootloader"),
|
||||||
|
|
||||||
|
# For the arm64-ubuntu-18.04.img, we need to specify the readfile content
|
||||||
|
|
||||||
|
readfile_contents = "m5 exit"
|
||||||
|
)
|
||||||
|
|
||||||
|
# We define the system with the aforementioned system defined.
|
||||||
|
|
||||||
|
simulator = Simulator(board = board)
|
||||||
|
|
||||||
|
# Once the system successfully boots, it encounters an
|
||||||
|
# `m5_exit instruction encountered`. We stop the simulation then. When the
|
||||||
|
# simulation has ended you may inspect `m5out/board.terminal` to see
|
||||||
|
# the stdout.
|
||||||
|
|
||||||
|
simulator.run()
|
||||||
@@ -50,6 +50,7 @@ PySource('gem5.components.boards.experimental',
|
|||||||
PySource('gem5.components.boards', 'gem5/components/boards/simple_board.py')
|
PySource('gem5.components.boards', 'gem5/components/boards/simple_board.py')
|
||||||
PySource('gem5.components.boards', 'gem5/components/boards/test_board.py')
|
PySource('gem5.components.boards', 'gem5/components/boards/test_board.py')
|
||||||
PySource('gem5.components.boards', 'gem5/components/boards/x86_board.py')
|
PySource('gem5.components.boards', 'gem5/components/boards/x86_board.py')
|
||||||
|
PySource('gem5.components.boards', 'gem5/components/boards/arm_board.py')
|
||||||
PySource('gem5.components.boards',
|
PySource('gem5.components.boards',
|
||||||
"gem5/components/boards/kernel_disk_workload.py")
|
"gem5/components/boards/kernel_disk_workload.py")
|
||||||
PySource('gem5.components.boards',
|
PySource('gem5.components.boards',
|
||||||
|
|||||||
377
src/python/gem5/components/boards/arm_board.py
Normal file
377
src/python/gem5/components/boards/arm_board.py
Normal file
@@ -0,0 +1,377 @@
|
|||||||
|
# Copyright (c) 2022 The Regents of the University of California
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met: redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer;
|
||||||
|
# redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution;
|
||||||
|
# neither the name of the copyright holders nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
from m5.objects import (
|
||||||
|
Port,
|
||||||
|
IOXBar,
|
||||||
|
Bridge,
|
||||||
|
BadAddr,
|
||||||
|
Terminal,
|
||||||
|
PciVirtIO,
|
||||||
|
VncServer,
|
||||||
|
AddrRange,
|
||||||
|
ArmSystem,
|
||||||
|
ArmRelease,
|
||||||
|
ArmFsLinux,
|
||||||
|
VirtIOBlock,
|
||||||
|
CowDiskImage,
|
||||||
|
RawDiskImage,
|
||||||
|
VoltageDomain,
|
||||||
|
SrcClockDomain,
|
||||||
|
ArmDefaultRelease,
|
||||||
|
VExpress_GEM5_Base,
|
||||||
|
VExpress_GEM5_Foundation,
|
||||||
|
)
|
||||||
|
|
||||||
|
import os
|
||||||
|
import m5
|
||||||
|
from abc import ABCMeta
|
||||||
|
from ...isas import ISA
|
||||||
|
from typing import List
|
||||||
|
from m5.util import fatal
|
||||||
|
from ...utils.requires import requires
|
||||||
|
from ...utils.override import overrides
|
||||||
|
from .abstract_board import AbstractBoard
|
||||||
|
from ...resources.resource import AbstractResource
|
||||||
|
from .kernel_disk_workload import KernelDiskWorkload
|
||||||
|
from ..cachehierarchies.classic.no_cache import NoCache
|
||||||
|
from ..processors.abstract_processor import AbstractProcessor
|
||||||
|
from ..memory.abstract_memory_system import AbstractMemorySystem
|
||||||
|
from ..cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy
|
||||||
|
|
||||||
|
class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload):
|
||||||
|
"""
|
||||||
|
A board capable of full system simulation for ARM instructions. It is based
|
||||||
|
ARMv8.
|
||||||
|
|
||||||
|
The board is based on Arm Motherboard Express uATX (V2M-P1), Arm
|
||||||
|
CoreTile Express A15x2 (V2P-CA15) and on Armv8-A FVP Foundation platform
|
||||||
|
v11.8, depending on the simulated platform. These boards are parts of ARM's
|
||||||
|
Versatile(TM) Express family of boards.
|
||||||
|
|
||||||
|
**Limitations**
|
||||||
|
* The board currently does not support ruby caches.
|
||||||
|
* stage2 walker ports are ignored.
|
||||||
|
"""
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
clk_freq: str,
|
||||||
|
processor: AbstractProcessor,
|
||||||
|
memory: AbstractMemorySystem,
|
||||||
|
cache_hierarchy: AbstractCacheHierarchy,
|
||||||
|
platform: VExpress_GEM5_Base = VExpress_GEM5_Foundation(),
|
||||||
|
release: ArmRelease = ArmDefaultRelease()
|
||||||
|
) -> None:
|
||||||
|
super().__init__()
|
||||||
|
AbstractBoard.__init__(
|
||||||
|
self,
|
||||||
|
clk_freq = clk_freq,
|
||||||
|
processor = processor,
|
||||||
|
memory = memory,
|
||||||
|
cache_hierarchy = cache_hierarchy,
|
||||||
|
)
|
||||||
|
|
||||||
|
# This board requires ARM ISA to work.
|
||||||
|
|
||||||
|
requires(isa_required = ISA.ARM)
|
||||||
|
|
||||||
|
# Setting the voltage domain here.
|
||||||
|
|
||||||
|
self.voltage_domain = self.clk_domain.voltage_domain
|
||||||
|
|
||||||
|
# Setting up ARM release here. We use the ARM default release, which
|
||||||
|
# corresponds to an ARMv8 system.
|
||||||
|
|
||||||
|
self.release = release
|
||||||
|
|
||||||
|
# RealView sets up most of the on-chip and off-chip devices and GIC
|
||||||
|
# for the ARM board. These devices' iformation is also used to
|
||||||
|
# generate the dtb file.
|
||||||
|
|
||||||
|
self._setup_realview(platform)
|
||||||
|
|
||||||
|
# ArmBoard's memory can only be setup once realview is initialized.
|
||||||
|
|
||||||
|
self._setup_arm_memory_ranges()
|
||||||
|
|
||||||
|
# Setting multi_proc of ArmSystem by counting the number of processors.
|
||||||
|
|
||||||
|
if processor.get_num_cores() != 1:
|
||||||
|
self.multi_proc = False
|
||||||
|
else:
|
||||||
|
self.multi_proc = True
|
||||||
|
|
||||||
|
@overrides(AbstractBoard)
|
||||||
|
def _setup_board(self) -> None:
|
||||||
|
|
||||||
|
# This board is expected to run full-system simulation.
|
||||||
|
# Loading ArmFsLinux() from `src/arch/arm/ArmFsWorkload.py`
|
||||||
|
|
||||||
|
self.workload = ArmFsLinux()
|
||||||
|
|
||||||
|
# We are fixing the following variable for the ArmSystem to work. The
|
||||||
|
# security extension is checked while generating the dtb file in
|
||||||
|
# realview. This board does not have security extention enabled.
|
||||||
|
|
||||||
|
self._have_psci = False
|
||||||
|
|
||||||
|
# highest_el_is_64 is set to True. True if the register width of the
|
||||||
|
# highest implemented exception level is 64 bits.
|
||||||
|
|
||||||
|
self.highest_el_is_64 = True
|
||||||
|
|
||||||
|
# Setting up the voltage and the clock domain here for the ARM board.
|
||||||
|
# The ArmSystem/RealView expects voltage_domain to be a parameter.
|
||||||
|
# The voltage and the clock frequency are taken from the devices.py
|
||||||
|
# file from configs/example/arm
|
||||||
|
|
||||||
|
self.voltage_domain = VoltageDomain(voltage="1.0V")
|
||||||
|
self.clk_domain = SrcClockDomain(
|
||||||
|
clock="1GHz", voltage_domain=self.voltage_domain
|
||||||
|
)
|
||||||
|
|
||||||
|
# The ARM board supports both Terminal and VncServer.
|
||||||
|
|
||||||
|
self.terminal = Terminal()
|
||||||
|
self.vncserver = VncServer()
|
||||||
|
|
||||||
|
# Incoherent I/O Bus
|
||||||
|
|
||||||
|
self.iobus = IOXBar()
|
||||||
|
self.iobus.badaddr_responder = BadAddr()
|
||||||
|
self.iobus.default = self.iobus.badaddr_responder.pio
|
||||||
|
|
||||||
|
def _setup_io_devices(self) -> None:
|
||||||
|
"""
|
||||||
|
This method connects the I/O devices to the I/O bus.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# We setup the iobridge for the ARM Board. The default
|
||||||
|
# cache_hierarchy's NoCache class has an iobridge has a latency of
|
||||||
|
# 10. We are using an iobridge with latency = 50ns, taken from the
|
||||||
|
# configs/example/arm/devices.py
|
||||||
|
|
||||||
|
self.iobridge = Bridge(delay="50ns")
|
||||||
|
self.iobridge.mem_side_port = self.iobus.cpu_side_ports
|
||||||
|
self.iobridge.cpu_side_port = (
|
||||||
|
self.cache_hierarchy.get_mem_side_port()
|
||||||
|
)
|
||||||
|
|
||||||
|
# We either have iocache or dmabridge depending upon the
|
||||||
|
# cache_hierarchy. If we have "NoCache", then we use the dmabridge.
|
||||||
|
# Otherwise, we use the iocache on the board.
|
||||||
|
|
||||||
|
if isinstance(self.cache_hierarchy, NoCache) is False:
|
||||||
|
|
||||||
|
# The ArmBoard does not support ruby caches.
|
||||||
|
|
||||||
|
if self.get_cache_hierarchy().is_ruby():
|
||||||
|
fatal("Ruby caches are not supported by the ArmBoard.")
|
||||||
|
|
||||||
|
# The classic caches are setup in the _setup_io_cache() method,
|
||||||
|
# defined under the cachehierarchy class. Verified it with both
|
||||||
|
# PrivateL1PrivateL2CacheHierarchy and PrivateL1CacheHierarchy
|
||||||
|
# classes.
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
# This corresponds to a machine without caches. We have a DMA
|
||||||
|
# beidge in this case. Parameters of this bridge are also taken
|
||||||
|
# from the common/example/arm/devices.py file.
|
||||||
|
|
||||||
|
self.dmabridge = Bridge(
|
||||||
|
delay="50ns", ranges=self.mem_ranges
|
||||||
|
)
|
||||||
|
|
||||||
|
self.dmabridge.mem_side_port = self.get_dma_ports()[0]
|
||||||
|
self.dmabridge.cpu_side_port = self.get_dma_ports()[1]
|
||||||
|
|
||||||
|
self.realview.attachOnChipIO(
|
||||||
|
self.cache_hierarchy.membus, self.iobridge
|
||||||
|
)
|
||||||
|
self.realview.attachIO(self.iobus)
|
||||||
|
|
||||||
|
def _setup_realview(self, platform) -> None:
|
||||||
|
"""
|
||||||
|
Notes:
|
||||||
|
The ARM Board has realview platform. Most of the on-chip and
|
||||||
|
off-chip devices are setup by the RealView platform. Currently, there
|
||||||
|
are 5 different types of realview platforms supported by the ArmBoard.
|
||||||
|
|
||||||
|
:param platform: the user can specify the platform while instantiating
|
||||||
|
an ArmBoard object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Currently, the ArmBoard supports VExpress_GEM5_V1,
|
||||||
|
# VExpress_GEM5_V1_HDLcd and VExpress_GEM5_Foundation.
|
||||||
|
# VExpress_GEM5_V2 and VExpress_GEM5_V2_HDLcd are not supported by the
|
||||||
|
# ArmBoard.
|
||||||
|
|
||||||
|
self.realview = platform
|
||||||
|
|
||||||
|
# We need to setup the global interrupt controller (GIC) addr for the
|
||||||
|
# realview system.
|
||||||
|
|
||||||
|
if hasattr(self.realview.gic, "cpu_addr"):
|
||||||
|
self.gic_cpu_addr = self.realview.gic.cpu_addr
|
||||||
|
|
||||||
|
def _setup_io_cache(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@overrides(AbstractBoard)
|
||||||
|
def has_io_bus(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
@overrides(AbstractBoard)
|
||||||
|
def get_io_bus(self) -> IOXBar:
|
||||||
|
return [self.iobus.cpu_side_ports, self.iobus.mem_side_ports]
|
||||||
|
|
||||||
|
@overrides(AbstractBoard)
|
||||||
|
def has_coherent_io(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
@overrides(AbstractBoard)
|
||||||
|
def get_mem_side_coherent_io_port(self) -> Port:
|
||||||
|
return self.iobus.mem_side_ports
|
||||||
|
|
||||||
|
@overrides(AbstractBoard)
|
||||||
|
def has_dma_ports(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _setup_coherent_io_bridge(self, board: AbstractBoard) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@overrides(AbstractBoard)
|
||||||
|
def get_dma_ports(self) -> List[Port]:
|
||||||
|
return [
|
||||||
|
self.cache_hierarchy.get_cpu_side_port(),
|
||||||
|
self.iobus.mem_side_ports
|
||||||
|
]
|
||||||
|
|
||||||
|
@overrides(AbstractBoard)
|
||||||
|
def connect_system_port(self, port: Port) -> None:
|
||||||
|
self.system_port = port
|
||||||
|
|
||||||
|
@overrides(KernelDiskWorkload)
|
||||||
|
def get_disk_device(self):
|
||||||
|
return "/dev/vda"
|
||||||
|
|
||||||
|
@overrides(KernelDiskWorkload)
|
||||||
|
def _add_disk_to_board(self, disk_image: AbstractResource):
|
||||||
|
|
||||||
|
# We define the image.
|
||||||
|
|
||||||
|
image = CowDiskImage(
|
||||||
|
child=RawDiskImage(read_only=True), read_only=False
|
||||||
|
)
|
||||||
|
|
||||||
|
self.pci_devices = [PciVirtIO(vio=VirtIOBlock(image=image))]
|
||||||
|
self.realview.attachPciDevice(
|
||||||
|
self.pci_devices[0], self.iobus
|
||||||
|
)
|
||||||
|
|
||||||
|
# Now that the disk and workload are set, we can generate the device
|
||||||
|
# tree file. We will generate the dtb file everytime the board is
|
||||||
|
# boot-up.
|
||||||
|
|
||||||
|
image.child.image_file = disk_image.get_local_path()
|
||||||
|
|
||||||
|
# _setup_io_devices needs to be implemented.
|
||||||
|
|
||||||
|
self._setup_io_devices()
|
||||||
|
|
||||||
|
# Specifying the dtb file location to the workload.
|
||||||
|
|
||||||
|
self.workload.dtb_filename = os.path.join(
|
||||||
|
m5.options.outdir, "device.dtb"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Calling generateDtb from class ArmSystem to add memory information to
|
||||||
|
# the dtb file.
|
||||||
|
|
||||||
|
self.generateDtb(self.workload.dtb_filename)
|
||||||
|
|
||||||
|
# Finally we need to setup the bootloader for the ArmBoard. An ARM
|
||||||
|
# system requires three inputs to simulate a full system: a disk image,
|
||||||
|
# the kernel file and the bootloader file(s).
|
||||||
|
|
||||||
|
self.realview.setupBootLoader(
|
||||||
|
self, self.workload.dtb_filename, self._bootloader)
|
||||||
|
|
||||||
|
def _get_memory_ranges(self, mem_size) -> list:
|
||||||
|
"""
|
||||||
|
This method is taken from configs/example/arm/devices.py. It sets up
|
||||||
|
all the memory ranges for the board.
|
||||||
|
"""
|
||||||
|
mem_ranges = []
|
||||||
|
|
||||||
|
for mem_range in self.realview._mem_regions:
|
||||||
|
size_in_range = min(mem_size, mem_range.size())
|
||||||
|
mem_ranges.append(
|
||||||
|
AddrRange(start = mem_range.start, size = size_in_range)
|
||||||
|
)
|
||||||
|
|
||||||
|
mem_size -= size_in_range
|
||||||
|
if mem_size == 0:
|
||||||
|
return mem_ranges
|
||||||
|
|
||||||
|
raise ValueError("Memory size too big for platform capabilities")
|
||||||
|
|
||||||
|
@overrides(AbstractBoard)
|
||||||
|
def _setup_memory_ranges(self) -> None:
|
||||||
|
"""
|
||||||
|
The ArmBoard's memory can only be setup after realview is setup. Once
|
||||||
|
realview is initialized, we call _setup_arm_memory_ranges() to
|
||||||
|
correctly setup the memory ranges.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _setup_arm_memory_ranges(self) -> None:
|
||||||
|
|
||||||
|
# We setup the memory here. The memory size is specified in the run
|
||||||
|
# script that the user uses.
|
||||||
|
|
||||||
|
memory = self.get_memory()
|
||||||
|
mem_size = memory.get_size()
|
||||||
|
|
||||||
|
self.mem_ranges = self._get_memory_ranges(mem_size)
|
||||||
|
memory.set_memory_range(self.mem_ranges)
|
||||||
|
|
||||||
|
@overrides(KernelDiskWorkload)
|
||||||
|
def get_default_kernel_args(self) -> List[str]:
|
||||||
|
|
||||||
|
# The default kernel string is taken from the devices.py file.
|
||||||
|
|
||||||
|
return [
|
||||||
|
"console=ttyAMA0",
|
||||||
|
"lpj=19988480",
|
||||||
|
"norandmaps",
|
||||||
|
"root={root_value}",
|
||||||
|
"rw",
|
||||||
|
"mem=%s" % self.get_memory().get_size(),
|
||||||
|
]
|
||||||
@@ -134,6 +134,7 @@ class KernelDiskWorkload:
|
|||||||
self,
|
self,
|
||||||
kernel: AbstractResource,
|
kernel: AbstractResource,
|
||||||
disk_image: AbstractResource,
|
disk_image: AbstractResource,
|
||||||
|
bootloader: Optional[AbstractResource] = None,
|
||||||
readfile: Optional[str] = None,
|
readfile: Optional[str] = None,
|
||||||
readfile_contents: Optional[str] = None,
|
readfile_contents: Optional[str] = None,
|
||||||
kernel_args: Optional[List[str]] = None,
|
kernel_args: Optional[List[str]] = None,
|
||||||
@@ -145,6 +146,8 @@ class KernelDiskWorkload:
|
|||||||
|
|
||||||
:param kernel: The kernel to boot.
|
:param kernel: The kernel to boot.
|
||||||
:param disk_image: The disk image to mount.
|
:param disk_image: The disk image to mount.
|
||||||
|
:param bootloader: The current implementation of the ARM board requires
|
||||||
|
three resources to operate -- kernel, disk image, and, a bootloader.
|
||||||
:param readfile: An optional parameter stating the file to be read by
|
:param readfile: An optional parameter stating the file to be read by
|
||||||
by `m5 readfile`.
|
by `m5 readfile`.
|
||||||
:param readfile_contents: An optional parameter stating the contents of
|
:param readfile_contents: An optional parameter stating the contents of
|
||||||
@@ -175,6 +178,13 @@ class KernelDiskWorkload:
|
|||||||
root_value=self.get_default_kernel_root_val(disk_image=disk_image)
|
root_value=self.get_default_kernel_root_val(disk_image=disk_image)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Setting the bootloader information for ARM board. The current
|
||||||
|
# implementation of the ArmBoard class expects a boot loader file to be
|
||||||
|
# provided along with the kernel and the disk image.
|
||||||
|
|
||||||
|
if bootloader is not None:
|
||||||
|
self._bootloader = [bootloader.get_local_path()]
|
||||||
|
|
||||||
# Set the readfile.
|
# Set the readfile.
|
||||||
if readfile:
|
if readfile:
|
||||||
self.readfile = readfile
|
self.readfile = readfile
|
||||||
@@ -190,4 +200,4 @@ class KernelDiskWorkload:
|
|||||||
self._add_disk_to_board(disk_image=disk_image)
|
self._add_disk_to_board(disk_image=disk_image)
|
||||||
|
|
||||||
# Set whether to exit on work items.
|
# Set whether to exit on work items.
|
||||||
self.exit_on_work_items = exit_on_work_items
|
self.exit_on_work_items = exit_on_work_items
|
||||||
|
|||||||
@@ -79,7 +79,18 @@ class SimpleCore(AbstractCore):
|
|||||||
|
|
||||||
@overrides(AbstractCore)
|
@overrides(AbstractCore)
|
||||||
def connect_walker_ports(self, port1: Port, port2: Port) -> None:
|
def connect_walker_ports(self, port1: Port, port2: Port) -> None:
|
||||||
self.core.mmu.connectWalkerPorts(port1, port2)
|
if self.get_isa() == ISA.ARM:
|
||||||
|
|
||||||
|
# Unlike X86 and RISCV MMU, the ARM MMU has two L1 TLB walker ports
|
||||||
|
# named `walker` and `stage2_walker` for both data and instruction.
|
||||||
|
# The gem5 standard library currently supports one TLB walker port
|
||||||
|
# per cache level. Therefore, we are explicitly setting the walker
|
||||||
|
# ports and not setting the stage2_walker ports for ARM systems.
|
||||||
|
|
||||||
|
self.core.mmu.itb_walker.port = port1
|
||||||
|
self.core.mmu.dtb_walker.port = port2
|
||||||
|
else:
|
||||||
|
self.core.mmu.connectWalkerPorts(port1, port2)
|
||||||
|
|
||||||
@overrides(AbstractCore)
|
@overrides(AbstractCore)
|
||||||
def set_workload(self, process: Process) -> None:
|
def set_workload(self, process: Process) -> None:
|
||||||
|
|||||||
@@ -195,3 +195,20 @@ gem5_verify_config(
|
|||||||
valid_hosts=constants.supported_hosts,
|
valid_hosts=constants.supported_hosts,
|
||||||
length=constants.long_tag,
|
length=constants.long_tag,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
gem5_verify_config(
|
||||||
|
name="test-gem5-library-example-arm-ubuntu-boot-test",
|
||||||
|
fixtures=(),
|
||||||
|
verifiers=(),
|
||||||
|
config=joinpath(
|
||||||
|
config.base_dir,
|
||||||
|
"configs",
|
||||||
|
"example",
|
||||||
|
"gem5_library",
|
||||||
|
"arm-ubuntu-boot-exit.py",
|
||||||
|
),
|
||||||
|
config_args=[],
|
||||||
|
valid_isas=(constants.arm_tag,),
|
||||||
|
valid_hosts=constants.supported_hosts,
|
||||||
|
length=constants.long_tag,
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user