First PIM modifications
This commit is contained in:
52
configs/example/gem5_library/arm-baremetal.py
Normal file
52
configs/example/gem5_library/arm-baremetal.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from gem5.isas import ISA
|
||||
from m5.objects import (
|
||||
ArmDefaultRelease,
|
||||
)
|
||||
from gem5.utils.requires import requires
|
||||
from gem5.resources.workload import CustomWorkload
|
||||
from gem5.resources.resource import BinaryResource
|
||||
from gem5.simulate.simulator import Simulator
|
||||
from m5.objects import VExpress_GEM5_Foundation
|
||||
from gem5.components.boards.arm_baremetal_board import ArmBareMetalBoard
|
||||
from gem5.components.memory import DRAMSysDDR3_1600
|
||||
from gem5.components.processors.cpu_types import CPUTypes
|
||||
from gem5.components.processors.simple_processor import SimpleProcessor
|
||||
|
||||
requires(isa_required=ISA.ARM)
|
||||
|
||||
from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import (
|
||||
PrivateL1PrivateL2CacheHierarchy,
|
||||
)
|
||||
from gem5.components.cachehierarchies.classic.no_cache import NoCache
|
||||
|
||||
cache_hierarchy = PrivateL1PrivateL2CacheHierarchy(
|
||||
l1d_size="16kB", l1i_size="16kB", l2_size="256kB"
|
||||
)
|
||||
# cache_hierarchy = NoCache()
|
||||
|
||||
memory = DRAMSysDDR3_1600(recordable=True)
|
||||
processor = SimpleProcessor(cpu_type=CPUTypes.O3, num_cores=1, isa=ISA.ARM)
|
||||
release = ArmDefaultRelease()
|
||||
platform = VExpress_GEM5_Foundation()
|
||||
|
||||
board = ArmBareMetalBoard(
|
||||
clk_freq="3GHz",
|
||||
processor=processor,
|
||||
memory=memory,
|
||||
cache_hierarchy=cache_hierarchy,
|
||||
release=release,
|
||||
platform=platform,
|
||||
)
|
||||
|
||||
board.m5ops_base = 0x10010000
|
||||
|
||||
workload = CustomWorkload(
|
||||
"set_baremetal_workload",
|
||||
{
|
||||
"kernel": BinaryResource("aarch64"),
|
||||
},
|
||||
)
|
||||
board.set_workload(workload)
|
||||
|
||||
simulator = Simulator(board=board)
|
||||
simulator.run()
|
||||
@@ -41,7 +41,10 @@ DRAMSys::DRAMSys(Params const& params) :
|
||||
params.resource_directory)),
|
||||
dramSysWrapper(
|
||||
params.name.c_str(), config, params.recordable, params.range)
|
||||
// checker("checker")
|
||||
{
|
||||
// checker.initiator_socket.bind(dramSysWrapper.tSocket);
|
||||
|
||||
dramSysWrapper.dramsys->registerIdleCallback(
|
||||
[this]
|
||||
{
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "mem/abstract_mem.hh"
|
||||
#include "mem/dramsys_wrapper.hh"
|
||||
#include "params/DRAMSys.hh"
|
||||
// #include "tlm2_base_protocol_checker.h"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
@@ -58,6 +59,7 @@ class DRAMSys : public AbstractMemory
|
||||
private:
|
||||
::DRAMSys::Config::Configuration config;
|
||||
DRAMSysWrapper dramSysWrapper;
|
||||
// tlm_utils::tlm2_base_protocol_checker<> checker;
|
||||
};
|
||||
|
||||
} // namespace memory
|
||||
|
||||
@@ -89,6 +89,24 @@ tlm::tlm_sync_enum DRAMSysWrapper::nb_transport_fw(
|
||||
// Subtract base address offset
|
||||
payload.set_address(payload.get_address() - range.start());
|
||||
|
||||
if (payload.get_address() < 0x4000 && payload.is_write() && phase == tlm::BEGIN_REQ)
|
||||
{
|
||||
char *msg = reinterpret_cast<char*>(payload.get_data_ptr());
|
||||
for (std::size_t i = 0; i < payload.get_data_length(); i++)
|
||||
{
|
||||
if (msg[i] != '\0')
|
||||
{
|
||||
message.push_back(msg[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << message << std::endl;
|
||||
message.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return iSocket->nb_transport_fw(payload, phase, fwDelay);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ class DRAMSysWrapper : public sc_core::sc_module
|
||||
tlm_utils::simple_target_socket<DRAMSysWrapper> tSocket;
|
||||
|
||||
std::shared_ptr<::DRAMSys::DRAMSys> dramsys;
|
||||
std::string message;
|
||||
|
||||
AddrRange range;
|
||||
};
|
||||
|
||||
1049
src/mem/tlm2_base_protocol_checker.h
Normal file
1049
src/mem/tlm2_base_protocol_checker.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -51,6 +51,7 @@ 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/x86_board.py')
|
||||
PySource('gem5.components.boards', 'gem5/components/boards/arm_board.py')
|
||||
PySource('gem5.components.boards', 'gem5/components/boards/arm_baremetal_board.py')
|
||||
PySource('gem5.components.boards',
|
||||
"gem5/components/boards/kernel_disk_workload.py")
|
||||
PySource('gem5.components.boards',
|
||||
|
||||
298
src/python/gem5/components/boards/arm_baremetal_board.py
Normal file
298
src/python/gem5/components/boards/arm_baremetal_board.py
Normal file
@@ -0,0 +1,298 @@
|
||||
# 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,
|
||||
AddrRange,
|
||||
ArmSystem,
|
||||
ArmRelease,
|
||||
ArmFsWorkload,
|
||||
VoltageDomain,
|
||||
SrcClockDomain,
|
||||
ArmDefaultRelease,
|
||||
VExpress_GEM5_Base,
|
||||
VExpress_GEM5_Foundation,
|
||||
SimObject,
|
||||
VncServer,
|
||||
)
|
||||
|
||||
from abc import ABCMeta
|
||||
from ...isas import ISA
|
||||
from ...utils.requires import requires
|
||||
from ...utils.override import overrides
|
||||
from typing import List, Sequence, Tuple
|
||||
from .abstract_board import AbstractBoard
|
||||
from ...resources.resource import AbstractResource, BinaryResource
|
||||
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 ArmBareMetalBoard(ArmSystem, AbstractBoard):
|
||||
__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:
|
||||
# The platform and the clk has to be set before calling the super class
|
||||
self._platform = platform
|
||||
self._clk_freq = clk_freq
|
||||
|
||||
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 up ARM release here. We use the ARM default release, which
|
||||
# corresponds to an ARMv8 system.
|
||||
self.release = release
|
||||
|
||||
# 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 ArmFsWorkload() from `src/arch/arm/ArmFsWorkload.py`
|
||||
self.workload = ArmFsWorkload()
|
||||
|
||||
# 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 extension 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. We set the clock to the same frequency
|
||||
# as the user specified in the config script.
|
||||
self.voltage_domain = VoltageDomain(voltage="1.0V")
|
||||
self.clk_domain = SrcClockDomain(
|
||||
clock=self._clk_freq, 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
|
||||
|
||||
# We now need to setup the dma_ports.
|
||||
self._dma_ports = None
|
||||
|
||||
# RealView sets up most of the on-chip and off-chip devices and GIC
|
||||
# for the ARM board. These devices' information is also used to
|
||||
# generate the dtb file. We then connect the I/O devices to the
|
||||
# I/O bus.
|
||||
self._setup_io_devices()
|
||||
|
||||
# Once the realview is setup, we can continue setting up the memory
|
||||
# ranges. ArmBoard's memory can only be setup once realview is
|
||||
# initialized.
|
||||
memory = self.get_memory()
|
||||
mem_size = memory.get_size()
|
||||
|
||||
# The following code is taken from configs/example/arm/devices.py. It
|
||||
# sets up all the memory ranges for the board.
|
||||
self.mem_ranges = []
|
||||
success = False
|
||||
for mem_range in self.realview._mem_regions:
|
||||
size_in_range = min(mem_size, mem_range.size())
|
||||
self.mem_ranges.append(
|
||||
AddrRange(start=mem_range.start, size=size_in_range)
|
||||
)
|
||||
|
||||
mem_size -= size_in_range
|
||||
if mem_size == 0:
|
||||
success = True
|
||||
break
|
||||
|
||||
if success:
|
||||
memory.set_memory_range(self.mem_ranges)
|
||||
else:
|
||||
raise ValueError("Memory size too big for platform capabilities")
|
||||
|
||||
def _setup_io_devices(self) -> None:
|
||||
"""
|
||||
This method first sets up the platform. ARM uses `realview` platform.
|
||||
Most of the on-chip and off-chip devices are setup by the realview
|
||||
platform. Once realview is setup, we connect the I/O devices to the
|
||||
I/O bus.
|
||||
"""
|
||||
|
||||
# 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 = self._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
|
||||
|
||||
# IO devices has to setup before incorporating the caches in the case
|
||||
# of ruby caches. Otherwise the DMA controllers are incorrectly
|
||||
# created. The IO device has to be attached first. This is done in the
|
||||
# realview class.
|
||||
if self.get_cache_hierarchy().is_ruby():
|
||||
# All the on-chip devices are attached in this method.
|
||||
self.realview.attachOnChipIO(
|
||||
self.iobus,
|
||||
dma_ports=self.get_dma_ports(),
|
||||
mem_ports=self.get_memory().get_mem_ports(),
|
||||
)
|
||||
self.realview.attachIO(self.iobus, dma_ports=self.get_dma_ports())
|
||||
|
||||
else:
|
||||
# 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.
|
||||
|
||||
# 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()
|
||||
)
|
||||
|
||||
if isinstance(self.cache_hierarchy, NoCache) is True:
|
||||
# This corresponds to a machine without caches. We have a DMA
|
||||
# bridge 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.cache_hierarchy.get_cpu_side_port()
|
||||
)
|
||||
self.dmabridge.cpu_side_port = self.iobus.mem_side_ports
|
||||
|
||||
# The classic caches are setup in the _setup_io_cache() method
|
||||
# defined under the cachehierarchy class. Verified it with both
|
||||
# PrivateL1PrivateL2CacheHierarchy and PrivateL1CacheHierarchy
|
||||
# classes.
|
||||
self.realview.attachOnChipIO(
|
||||
self.cache_hierarchy.membus, self.iobridge
|
||||
)
|
||||
self.realview.attachIO(self.iobus)
|
||||
|
||||
@overrides(AbstractBoard)
|
||||
def has_io_bus(self) -> bool:
|
||||
return True
|
||||
|
||||
@overrides(AbstractBoard)
|
||||
def get_io_bus(self) -> IOXBar:
|
||||
return self.iobus
|
||||
|
||||
@overrides(AbstractBoard)
|
||||
def has_coherent_io(self) -> bool:
|
||||
# The setup of the caches gets a little tricky here. We need to
|
||||
# override the default cache_hierarchy.iobridge due to different delay
|
||||
# values (see method _setup_io_devices()). One way to do it would be to
|
||||
# prevent creating cache_hierarchy.iobridge altogether. We trick
|
||||
# NoCache() to assume that this board has no coherent_io and we we
|
||||
# simply setup our own iobridge in the _setup_io_devices() method.
|
||||
if isinstance(self.cache_hierarchy, NoCache):
|
||||
return False
|
||||
# In all other cases, we use the default values setup in the
|
||||
# respective cache hierarchy class.
|
||||
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
|
||||
|
||||
@overrides(AbstractBoard)
|
||||
def get_dma_ports(self) -> List[Port]:
|
||||
# The DMA ports differ depending upon the cache hierarchy. The method
|
||||
# self.set_dma_ports takes care of that. In the case of ruby caches,
|
||||
# this method should initially return an empty list.
|
||||
if self.cache_hierarchy.is_ruby():
|
||||
if self._dma_ports is None:
|
||||
self._dma_ports = []
|
||||
|
||||
# _dma_ports should always be empty for classic caches.
|
||||
return self._dma_ports
|
||||
|
||||
@overrides(AbstractBoard)
|
||||
def connect_system_port(self, port: Port) -> None:
|
||||
self.system_port = port
|
||||
|
||||
@overrides(AbstractBoard)
|
||||
def _setup_memory_ranges(self) -> None:
|
||||
"""
|
||||
The ArmBoard's memory can only be setup after realview is setup. We set
|
||||
this up in the `_setup_board` function.
|
||||
"""
|
||||
pass
|
||||
|
||||
def set_baremetal_workload(self, kernel: BinaryResource) -> None:
|
||||
self._set_fullsystem(True)
|
||||
self.workload.object_file = kernel.get_local_path()
|
||||
|
||||
@overrides(SimObject)
|
||||
def createCCObject(self):
|
||||
"""We override this function as it is called in `m5.instantiate`. This
|
||||
means we can insert a check to ensure the `_connect_things` function
|
||||
has been run.
|
||||
"""
|
||||
super()._connect_things_check()
|
||||
super().createCCObject()
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "params/Gem5ToTlmBridge512.hh"
|
||||
#include "sim/eventq.hh"
|
||||
#include "sim/system.hh"
|
||||
#include "systemc/ext/tlm_core/2/generic_payload/gp.hh"
|
||||
#include "systemc/tlm_bridge/sc_ext.hh"
|
||||
#include "systemc/tlm_bridge/sc_mm.hh"
|
||||
|
||||
@@ -479,7 +480,6 @@ Gem5ToTlmBridge<BITWIDTH>::recvRespRetry()
|
||||
|
||||
tlm::tlm_generic_payload *trans = blockingResponse;
|
||||
blockingResponse = nullptr;
|
||||
|
||||
PacketPtr packet = packetMap[trans];
|
||||
sc_assert(packet);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user