python: Add Components Library [Alpha Release]

The purpose of the gem5 components library is to provide gem5 users a
standard set of common and useful gem5 components pre-built to add to
their experiments. The gem5 components library adopts a modular
architecture design with the goal of components being easy to add and
remove from designs, and extendable as needed. E.g., any Memory system
should be interchangable with any other, and if not a helpful error
messages should be raised.

Examples of using the gem5 components library can be found in
`configs/example/components-library`.

Important Disclaimer:

This is a pre-alpha release of the gem5 components library. The purpose
of this release is to get some community feedback on this new component
of gem5. Though some testing has been done, we expect regular fixes and
improvements until this is in a stable state.

The components library has been formatted with Python Black; typing has
been checked with MyPy; and the library has been tested with the scripts
in `configs/example/components-libary`. More rigorous tests are to be
added in future revisions.

More detailed documentation will appear in future revisions.

Jira Ticket outlining TODOs and known bugs can be found here:
https://gem5.atlassian.net/browse/GEM5-648

Change-Id: I3492ec4a6d8c59ffbae899ce8e87ab4ffb92b976
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/47466
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Bobby R. Bruce
2021-07-01 17:49:58 -07:00
parent 264ee10991
commit 0b54ad277f
64 changed files with 6951 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
# The gem5 Components Library
**IMPORTANT NOTE:** This is a Work-In-Process Documentation. This will be expanded and completed in later revisions of the components library.
This is a high-level overview of what this library is.
## Philosophy
Like the [Zen of Python](https://www.python.org/dev/peps/pep-0020/), the gem5 Components Library has a set of guiding principles.
Note, these are note rules, and they are meant to be *bent* if needed (but maybe not broken).
### Components are extensible, not configurable
We prefer *extensibility* instead of *configurability*.
Instead of each component taking many different parameters, we have decided to make many different components.
For instance, instead of having one core component which takes a parameter of the type (e.g., in-order or out-of-order), we specify multiple different components, an `InOrderCPU` and an `OutOfOrder` CPU.
### Components use easy to remember names
We prefer longer and easier to remember names than shorter or jargon names.
## Structure of the components library
### Boards
### Processors
### Memories
### Cache hierarchies
## Contributing to the components library
### Code style
- Use [Black](https://black.readthedocs.io/en/stable/) to format your code.
- Docstring should follow the [ReST style and Sphinx](https://www.sphinx-doc.org/)

View File

View File

@@ -0,0 +1,181 @@
# Copyright (c) 2021 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 abc import ABCMeta, abstractmethod
from .mem_mode import MemMode
from m5.objects import System, Port, IOXBar, ClockDomain
from ..isas import ISA
from ..coherence_protocol import CoherenceProtocol
from typing import List
class AbstractBoard(System):
"""The abstract board interface.
Boards are used as the object which can connect together all other
components. This abstract class defines the external interface that other
boards must provide. Boards can be specialized for different ISAs or system
designs (e.g., core counts, cache types, memory channels, I/O devices, etc)
In addition to providing the place that system components are connected,
the board also exposes an interface for the caches, processor, and memory
to interact.
The board also exposes an interface to set up I/O devices which needs to be
specialized for each ISA and/or platform.
Board inherits from System and can therefore be used as a System simobject
when required.
"""
__metaclass__ = ABCMeta
def __init__(
self,
processor: "AbstractProcessor",
memory: "AbstractMemory",
cache_hierarchy: "AbstractCacheHierarchy",
) -> None:
super(AbstractBoard, self).__init__()
"""
:param processor: The processor for this board.
:param memory: The memory for this board.
:param cache_hierarchy: The Cachie Hierarchy for this board.
"""
self.processor = processor
self.memory = memory
self.cache_hierarchy = cache_hierarchy
def get_processor(self) -> "AbstractProcessor":
"""Get the processor connected to the board.
:returns: The processor.
"""
return self.processor
def get_memory(self) -> "AbstractMemory":
"""Get the memory (RAM) connected to the board.
:returns: The memory system.
"""
return self.memory
def get_cache_hierarchy(self) -> "AbstractCacheHierarchy":
"""Get the cache hierarchy connected to the board.
:returns: The cache hierarchy.
"""
return self.cache_hierarchy
def get_cache_line_size(self) -> int:
"""Get the size of the cache line.
:returns: The size of the cache line size.
"""
return self.cache_line_size
# Technically `get_dma_ports` returns a list. This list could be empty to
# indicate the presense of dma ports. Though I quite like having this
# boolean to quickly check a board.
@abstractmethod
def has_dma_ports(self) -> bool:
"""Determine whether the board has DMA ports or not.
:returns: True if the board has DMA ports, otherwise False.
"""
raise NotImplementedError
@abstractmethod
def get_dma_ports(self) -> List[Port]:
"""Get the board's Direct Memory Access ports.
This abstract method must be implemented within the subclasses if they
support DMA and/or full system simulation.
:returns: A List of the Direct Memory Access ports.
"""
raise NotImplementedError
@abstractmethod
def has_io_bus(self) -> bool:
"""Determine whether the board has an IO bus or not.
:returns: True if the board has an IO bus, otherwise False.
"""
raise NotImplementedError
@abstractmethod
def get_io_bus(self) -> IOXBar:
"""Get the board's IO Bus.
This abstract method must be implemented within the subclasses if they
support DMA and/or full system simulation.
The I/O bus is a non-coherent bus (in the classic caches). On the CPU
side, it accepts requests meant for I/O devices. On the memory side, it
forwards these requests to the devices (e.g., the interrupt
controllers on each core).
:returns: The I/O Bus.
"""
raise NotImplementedError
@abstractmethod
def get_clock_domain(self) -> ClockDomain:
"""Get the clock domain.
:returns: The clock domain.
"""
raise NotImplementedError
@abstractmethod
def connect_system_port(self, port: Port) -> None:
raise NotImplementedError
@abstractmethod
def set_mem_mode(self, mem_mode: MemMode) -> None:
"""
Set the memory mode of the board.
:param mem_mode: The memory mode the board is to be set to.
"""
raise NotImplementedError
@abstractmethod
def connect_things(self) -> None:
"""Connects all the components to the board.
This should be called after the constructor.
When implementing this function, derived boards should use this to
hook up the memory, process, and cache hierarchy as a *second* stage.
You should use this function to connect things together when you need
to know that everything has already been constructed.
"""
raise NotImplementedError

View File

@@ -0,0 +1,53 @@
# Copyright (c) 2021 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.
"""Specifies the MemMode enum
"""
from enum import Enum
class MemMode(Enum):
TIMING = 1
ATOMIC = 2
ATOMIC_NONCACHING = 3
def mem_mode_to_string(mem_mode: MemMode) -> str:
"""
Returns the string form of the mem_mode, compatible with the gem5
simulator.
:returns: The string form of the mem_mode
"""
if mem_mode == MemMode.TIMING:
return "timing"
elif mem_mode == MemMode.ATOMIC:
return "atomic"
elif mem_mode == MemMode.ATOMIC_NONCACHING:
return "atomic_noncaching"
else:
return NotImplementedError

View File

@@ -0,0 +1,141 @@
# Copyright (c) 2021 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 (
SrcClockDomain,
VoltageDomain,
Process,
SEWorkload,
IOXBar,
Port,
ClockDomain,
)
from .abstract_board import AbstractBoard
from .mem_mode import MemMode, mem_mode_to_string
from ..processors.abstract_processor import AbstractProcessor
from ..memory.abstract_memory_system import AbstractMemorySystem
from ..cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy
from ..utils.override import overrides
from typing import List
class SimpleBoard(AbstractBoard):
"""
This is an incredibly simple system. It contains no I/O, and will work only
with a classic cache hierarchy setup.
**Limitations**
* Only supports SE mode
You can run a binary executable via the `set_workload` function.
"""
def __init__(
self,
clk_freq: str,
processor: AbstractProcessor,
memory: AbstractMemorySystem,
cache_hierarchy: AbstractCacheHierarchy,
exit_on_work_items: bool = False,
) -> None:
super(SimpleBoard, self).__init__(
processor=processor,
memory=memory,
cache_hierarchy=cache_hierarchy,
)
# Set up the clock domain and the voltage domain.
self.clk_domain = SrcClockDomain()
self.clk_domain.clock = clk_freq
self.clk_domain.voltage_domain = VoltageDomain()
self.mem_ranges = memory.get_memory_ranges()
self.exit_on_work_items = exit_on_work_items
@overrides(AbstractBoard)
def get_clock_domain(self) -> ClockDomain:
return self.clk_domain
@overrides(AbstractBoard)
def connect_system_port(self, port: Port) -> None:
self.system_port = port
@overrides(AbstractBoard)
def set_mem_mode(self, mem_mode: MemMode) -> None:
self.mem_mode = mem_mode_to_string(mem_mode=mem_mode)
@overrides(AbstractBoard)
def connect_things(self) -> None:
# Incorporate the cache hierarchy for the motherboard.
self.get_cache_hierarchy().incorporate_cache(self)
# Incorporate the processor into the motherboard.
self.get_processor().incorporate_processor(self)
# Incorporate the memory into the motherboard.
self.get_memory().incorporate_memory(self)
@overrides(AbstractBoard)
def has_io_bus(self) -> bool:
return False
@overrides(AbstractBoard)
def get_io_bus(self) -> IOXBar:
raise NotImplementedError(
"SimpleBoard does not have an IO Bus. "
"Use `has_io_bus()` to check this."
)
@overrides(AbstractBoard)
def has_dma_ports(self) -> bool:
return False
@overrides(AbstractBoard)
def get_dma_ports(self) -> List[Port]:
raise NotImplementedError(
"SimpleBoard does not have DMA Ports. "
"Use `has_dma_ports()` to check this."
)
def set_workload(self, binary: str) -> None:
"""Set up the system to run a specific binary.
**Limitations**
* Only supports single threaded applications
* Dynamically linked executables are partially supported when the host
ISA and the simulated ISA are the same.
:param binary: The path on the *host* to the binary to run in gem5.
"""
self.workload = SEWorkload.init_compatible(binary)
process = Process()
process.cmd = [binary]
self.get_processor().get_cores()[0].set_workload(process)

View File

@@ -0,0 +1,103 @@
# Copyright (c) 2021 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 SrcClockDomain, ClockDomain, VoltageDomain, Port, IOXBar
from .mem_mode import MemMode, mem_mode_to_string
from ..utils.override import overrides
from .abstract_board import AbstractBoard
from ..processors.abstract_processor import AbstractProcessor
from ..memory.abstract_memory_system import AbstractMemorySystem
from ..cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy
from typing import List
class TestBoard(AbstractBoard):
"""This is a Testing Board used to run traffic generators on a simple
architecture.
To work as a traffic generator board, pass a generator as a processor.
"""
def __init__(
self,
clk_freq: str,
processor: AbstractProcessor,
memory: AbstractMemorySystem,
cache_hierarchy: AbstractCacheHierarchy,
):
super(TestBoard, self).__init__(
processor=processor,
memory=memory,
cache_hierarchy=cache_hierarchy,
)
self.clk_domain = SrcClockDomain(
clock=clk_freq, voltage_domain=VoltageDomain()
)
self.mem_ranges = memory.get_memory_ranges()
def connect_system_port(self, port: Port) -> None:
self.system_port = port
def connect_things(self) -> None:
self.get_cache_hierarchy().incorporate_cache(self)
self.get_processor().incorporate_processor(self)
self.get_memory().incorporate_memory(self)
def get_clock_domain(self) -> ClockDomain:
return self.clk_domain
@overrides(AbstractBoard)
def has_io_bus(self) -> bool:
return False
@overrides(AbstractBoard)
def get_io_bus(self) -> IOXBar:
raise NotImplementedError(
"The TestBoard does not have an IO Bus. "
"Use `has_io_bus()` to check this."
)
@overrides(AbstractBoard)
def get_dma_ports(self) -> List[Port]:
return False
@overrides(AbstractBoard)
def get_dma_ports(self) -> List[Port]:
raise NotImplementedError(
"The TestBoard does not have DMA Ports. "
"Use `has_dma_ports()` to check this."
)
@overrides(AbstractBoard)
def set_mem_mode(self, mem_mode: MemMode) -> None:
self.mem_mode = mem_mode_to_string(mem_mode=mem_mode)

View File

@@ -0,0 +1,342 @@
# Copyright (c) 2021 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 components_library.utils.override import overrides
from components_library.boards.abstract_board import AbstractBoard
from components_library.isas import ISA
import m5
from m5.objects import (
Cache,
Pc,
AddrRange,
X86FsLinux,
Addr,
X86SMBiosBiosInformation,
X86IntelMPProcessor,
X86IntelMPIOAPIC,
X86IntelMPBus,
X86IntelMPBusHierarchy,
X86IntelMPIOIntAssignment,
X86E820Entry,
Bridge,
IOXBar,
IdeDisk,
CowDiskImage,
RawDiskImage,
BaseXBar,
)
from m5.params import Port
from .simple_board import SimpleBoard
from ..processors.abstract_processor import AbstractProcessor
from ..memory.abstract_memory_system import AbstractMemorySystem
from ..cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy
from ..runtime import get_runtime_isa
import os
from typing import Optional, Sequence
class X86Board(SimpleBoard):
"""
A board capable of full system simulation for X86.
**Limitations**
* Currently, this board's memory is hardcoded to 3GB
* Much of the I/O subsystem is hard coded
"""
def __init__(
self,
clk_freq: str,
processor: AbstractProcessor,
memory: AbstractMemorySystem,
cache_hierarchy: AbstractCacheHierarchy,
exit_on_work_items: bool = False,
) -> None:
super(X86Board, self).__init__(
clk_freq=clk_freq,
processor=processor,
memory=memory,
cache_hierarchy=cache_hierarchy,
exit_on_work_items=exit_on_work_items,
)
if get_runtime_isa() != ISA.X86:
raise EnvironmentError(
"X86Motherboard will only work with the X86 ISA."
)
# Add the address range for the IO
# TODO: This should definitely NOT be hardcoded to 3GB
self.mem_ranges = [
AddrRange(Addr("3GB")), # All data
AddrRange(0xC0000000, size=0x100000), # For I/0
]
self.pc = Pc()
self.workload = X86FsLinux()
# Constants similar to x86_traits.hh
IO_address_space_base = 0x8000000000000000
pci_config_address_space_base = 0xC000000000000000
interrupts_address_space_base = 0xA000000000000000
APIC_range_size = 1 << 12
# North Bridge
self.iobus = IOXBar()
# Setup memory system specific settings.
if self.get_cache_hierarchy().is_ruby():
self.pc.attachIO(self.get_io_bus(), [self.pc.south_bridge.ide.dma])
else:
self.bridge = Bridge(delay="50ns")
self.bridge.mem_side_port = self.get_io_bus().cpu_side_ports
self.bridge.cpu_side_port = (
self.get_cache_hierarchy().get_mem_side_port()
)
# # Constants similar to x86_traits.hh
IO_address_space_base = 0x8000000000000000
pci_config_address_space_base = 0xC000000000000000
interrupts_address_space_base = 0xA000000000000000
APIC_range_size = 1 << 12
self.bridge.ranges = [
AddrRange(0xC0000000, 0xFFFF0000),
AddrRange(
IO_address_space_base, interrupts_address_space_base - 1
),
AddrRange(pci_config_address_space_base, Addr.max),
]
self.apicbridge = Bridge(delay="50ns")
self.apicbridge.cpu_side_port = self.get_io_bus().mem_side_ports
self.apicbridge.mem_side_port = (
self.get_cache_hierarchy().get_cpu_side_port()
)
self.apicbridge.ranges = [
AddrRange(
interrupts_address_space_base,
interrupts_address_space_base
+ self.get_processor().get_num_cores() * APIC_range_size
- 1,
)
]
self.pc.attachIO(self.get_io_bus())
self.iocache = Cache(
assoc=8,
tag_latency=50,
data_latency=50,
response_latency=50,
mshrs=20,
size="1kB",
tgts_per_mshr=12,
addr_ranges=self.mem_ranges,
)
self.iocache.cpu_side = self.get_io_bus().mem_side_ports
self.iocache.mem_side = (
self.get_cache_hierarchy().get_cpu_side_port()
)
# Add in a Bios information structure.
self.workload.smbios_table.structures = [X86SMBiosBiosInformation()]
# Set up the Intel MP table
base_entries = []
ext_entries = []
for i in range(self.get_processor().get_num_cores()):
bp = X86IntelMPProcessor(
local_apic_id=i,
local_apic_version=0x14,
enable=True,
bootstrap=(i == 0),
)
base_entries.append(bp)
io_apic = X86IntelMPIOAPIC(
id=self.get_processor().get_num_cores(),
version=0x11,
enable=True,
address=0xFEC00000,
)
self.pc.south_bridge.io_apic.apic_id = io_apic.id
base_entries.append(io_apic)
pci_bus = X86IntelMPBus(bus_id=0, bus_type="PCI ")
base_entries.append(pci_bus)
isa_bus = X86IntelMPBus(bus_id=1, bus_type="ISA ")
base_entries.append(isa_bus)
connect_busses = X86IntelMPBusHierarchy(
bus_id=1, subtractive_decode=True, parent_bus=0
)
ext_entries.append(connect_busses)
pci_dev4_inta = X86IntelMPIOIntAssignment(
interrupt_type="INT",
polarity="ConformPolarity",
trigger="ConformTrigger",
source_bus_id=0,
source_bus_irq=0 + (4 << 2),
dest_io_apic_id=io_apic.id,
dest_io_apic_intin=16,
)
base_entries.append(pci_dev4_inta)
def assignISAInt(irq, apicPin):
assign_8259_to_apic = X86IntelMPIOIntAssignment(
interrupt_type="ExtInt",
polarity="ConformPolarity",
trigger="ConformTrigger",
source_bus_id=1,
source_bus_irq=irq,
dest_io_apic_id=io_apic.id,
dest_io_apic_intin=0,
)
base_entries.append(assign_8259_to_apic)
assign_to_apic = X86IntelMPIOIntAssignment(
interrupt_type="INT",
polarity="ConformPolarity",
trigger="ConformTrigger",
source_bus_id=1,
source_bus_irq=irq,
dest_io_apic_id=io_apic.id,
dest_io_apic_intin=apicPin,
)
base_entries.append(assign_to_apic)
assignISAInt(0, 2)
assignISAInt(1, 1)
for i in range(3, 15):
assignISAInt(i, i)
self.workload.intel_mp_table.base_entries = base_entries
self.workload.intel_mp_table.ext_entries = ext_entries
entries = [
# Mark the first megabyte of memory as reserved
X86E820Entry(addr=0, size="639kB", range_type=1),
X86E820Entry(addr=0x9FC00, size="385kB", range_type=2),
# Mark the rest of physical memory as available
X86E820Entry(
addr=0x100000,
size=f"{self.mem_ranges[0].size() - 0x100000:d}B",
range_type=1,
),
]
# Reserve the last 16kB of the 32-bit address space for m5ops
entries.append(
X86E820Entry(addr=0xFFFF0000, size="64kB", range_type=2)
)
self.workload.e820_table.entries = entries
def connect_things(self) -> None:
super().connect_things()
def set_workload(
self, kernel: str, disk_image: str, command: Optional[str] = None
):
"""Setup the full system files
See <url> for the currently tested kernels and OSes.
The command is an optional string to execute once the OS is fully
booted, assuming the disk image is setup to run `m5 readfile` after
booting.
**Limitations**
* Only supports a Linux kernel
* Disk must be configured correctly to use the command option
:param kernel: The compiled kernel binary
:param disk_image: A disk image containing the OS data. The first
partition should be the root partition.
:param command: The command(s) to run with bash once the OS is booted
"""
# Set the Linux kernel to use.
self.workload.object_file = kernel
# Options specified on the kernel command line.
self.workload.command_line = " ".join(
[
"earlyprintk=ttyS0",
"console=ttyS0",
"lpj=7999923",
"root=/dev/hda1",
]
)
# Create the Disk image SimObject.
ide_disk = IdeDisk()
ide_disk.driveID = "device0"
ide_disk.image = CowDiskImage(
child=RawDiskImage(read_only=True), read_only=False
)
ide_disk.image.child.image_file = disk_image
# Attach the SimObject to the system.
self.pc.south_bridge.ide.disks = [ide_disk]
# Set the script to be passed to the simulated system to execute after
# boot.
if command:
file_name = os.path.join(m5.options.outdir, "run")
bench_file = open(file_name, "w+")
bench_file.write(command)
bench_file.close()
# Set to the system readfile
self.readfile = file_name
@overrides(AbstractBoard)
def has_io_bus(self) -> bool:
return True
@overrides(AbstractBoard)
def get_io_bus(self) -> BaseXBar:
return self.iobus
@overrides(AbstractBoard)
def has_dma_ports(self) -> bool:
return True
@overrides(AbstractBoard)
def get_dma_ports(self) -> Sequence[Port]:
return [self.pc.south_bridge.ide.dma, self.iobus.mem_side_ports]

View File

@@ -0,0 +1,72 @@
# Copyright (c) 2021 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 abc import ABCMeta, abstractmethod
from ..boards.abstract_board import AbstractBoard
from m5.objects import SubSystem
class AbstractCacheHierarchy(SubSystem):
__metaclass__ = ABCMeta
def __init__(self):
super(AbstractCacheHierarchy, self).__init__()
"""
A Cache Hierarchy incorporates any system components which manages
communicaton between the processor and memory. E.g., Caches, the MemBus,
MMU, and the MMU Cache.
All Cache Hierarchies must have this as a base class.
"""
@abstractmethod
def incorporate_cache(self, board: AbstractBoard) -> None:
"""
Incorporates the caches into a board.
Each specific hierarchy needs to implement this function and will be
unique for each setup.
:param board: The board in which the cache heirarchy is to be
incorporated.
:type board: AbstractBoard
"""
raise NotImplementedError
@abstractmethod
def is_ruby(self) -> bool:
"""
Specifies whether this cache hierarchy is using the Ruby memory system
or not.
:returns: True if the cache hierarchy is ruby. Otherwise False.
"""
raise NotImplementedError

View File

@@ -0,0 +1,75 @@
# Copyright (c) 2021 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 .abstract_cache_hierarchy import AbstractCacheHierarchy
class AbstractTwoLevelCacheHierarchy:
"""
An abstract two-level hierarchy with a configurable L1 and L2 size and
associativity.
"""
def __init__(
self,
l1i_size: str,
l1i_assoc: int,
l1d_size: str,
l1d_assoc: int,
l2_size: str,
l2_assoc: int,
):
"""
:param l1i_size: The size of the L1 Instruction cache (e.g. "32kB").
:type l1i_size: str
:param l1i_assoc:
:type l1i_assoc: int
:param l1dsize: The size of the LL1 Data cache (e.g. "32kB").
:type l1dsize: str
:param l1d_assoc:
:type l1d_assoc: int
:param l2_size: The size of the L2 cache (e.g., "256kB").
:type l2_size: str
:param l2_assoc:
:type l2_assoc: int
"""
self._l1i_size = l1i_size
self._l1i_assoc = l1i_assoc
self._l1d_size = l1d_size
self._l1d_assoc = l1d_assoc
self._l2_size = l2_size
self._l2_assoc = l2_assoc

View File

@@ -0,0 +1,54 @@
# Copyright (c) 2021 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 abc import abstractmethod
from ...utils.override import overrides
from ..abstract_cache_hierarchy import AbstractCacheHierarchy
from m5.objects import Port
class AbstractClassicCacheHierarchy(AbstractCacheHierarchy):
"""
All classic cache hierarchies inherit from this class. This class
provides the shared infrastructure that all classic memory system
implementations need.
"""
def __init__(self):
super(AbstractClassicCacheHierarchy, self).__init__()
@overrides(AbstractCacheHierarchy)
def is_ruby(self) -> bool:
return False
@abstractmethod
def get_mem_side_port(self) -> Port:
raise NotImplementedError
@abstractmethod
def get_cpu_side_port(self) -> Port:
raise NotImplementedError

View File

@@ -0,0 +1,60 @@
# Copyright (c) 2021 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 ....utils.override import *
from m5.objects import Cache, BasePrefetcher, StridePrefetcher
from typing import Optional
class L1DCache(Cache):
"""
A simple L1 data cache with default values.
"""
def __init__(
self,
size: str,
assoc: Optional[int] = 8,
tag_latency: Optional[int] = 1,
data_latency: Optional[int] = 1,
response_latency: Optional[int] = 1,
mshrs: Optional[int] = 16,
tgts_per_mshr: Optional[int] = 20,
writeback_clean: Optional[bool] = True,
prefetcher: BasePrefetcher = StridePrefetcher(),
):
super(L1DCache, self).__init__()
self.size = size
self.assoc = assoc
self.tag_latency = tag_latency
self.data_latency = data_latency
self.response_latency = response_latency
self.mshrs = mshrs
self.tgts_per_mshr = tgts_per_mshr
self.writeback_clean = writeback_clean
self.prefetcher = prefetcher

View File

@@ -0,0 +1,60 @@
# Copyright (c) 2021 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 typing import Optional
from m5.objects import Cache, BasePrefetcher, StridePrefetcher
from ....utils.override import *
class L1ICache(Cache):
"""
A simple L1 instruction cache with default values.
"""
def __init__(
self,
size: str,
assoc: Optional[int] = 8,
tag_latency: Optional[int] = 1,
data_latency: Optional[int] = 1,
response_latency: Optional[int] = 1,
mshrs: Optional[int] = 16,
tgts_per_mshr: Optional[int] = 20,
writeback_clean: Optional[bool] = True,
prefetcher: BasePrefetcher = StridePrefetcher(),
):
super(L1ICache, self).__init__()
self.size = size
self.assoc = assoc
self.tag_latency = tag_latency
self.data_latency = data_latency
self.response_latency = response_latency
self.mshrs = mshrs
self.tgts_per_mshr = tgts_per_mshr
self.writeback_clean = writeback_clean
self.prefetcher = prefetcher

View File

@@ -0,0 +1,60 @@
# Copyright (c) 2021 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 ....utils.override import *
from m5.objects import Cache, BasePrefetcher, StridePrefetcher
from typing import Optional
class L2Cache(Cache):
"""
A simple L2 Cache with default values.
"""
def __init__(
self,
size: str,
assoc: Optional[int] = 16,
tag_latency: Optional[int] = 10,
data_latency: Optional[int] = 10,
response_latency: Optional[int] = 1,
mshrs: Optional[int] = 20,
tgts_per_mshr: Optional[int] = 12,
writeback_clean: Optional[bool] = True,
prefetcher: BasePrefetcher = StridePrefetcher(),
):
super(L2Cache, self).__init__()
self.size = size
self.assoc = assoc
self.tag_latency = tag_latency
self.data_latency = data_latency
self.response_latency = response_latency
self.mshrs = mshrs
self.tgts_per_mshr = tgts_per_mshr
self.writeback_clean = writeback_clean
self.prefetcher = prefetcher

View File

@@ -0,0 +1,60 @@
# Copyright (c) 2021 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 ....utils.override import *
from m5.objects import Cache, BasePrefetcher, StridePrefetcher
from typing import Optional
class MMUCache(Cache):
"""
A simple Memory Management Unit (MMU) cache with default values.
"""
def __init__(
self,
size: str,
assoc: Optional[int] = 4,
tag_latency: Optional[int] = 1,
data_latency: Optional[int] = 1,
response_latency: Optional[int] = 1,
mshrs: Optional[int] = 20,
tgts_per_mshr: Optional[int] = 12,
writeback_clean: Optional[bool] = True,
prefetcher: BasePrefetcher = StridePrefetcher(),
):
super(MMUCache, self).__init__()
self.size = size
self.assoc = assoc
self.tag_latency = tag_latency
self.data_latency = data_latency
self.response_latency = response_latency
self.mshrs = mshrs
self.tgts_per_mshr = tgts_per_mshr
self.writeback_clean = writeback_clean
self.prefetcher = prefetcher

View File

@@ -0,0 +1,121 @@
# Copyright (c) 2021 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 components_library.cachehierarchies.classic.\
abstract_classic_cache_hierarchy import (
AbstractClassicCacheHierarchy,
)
from ..abstract_cache_hierarchy import AbstractCacheHierarchy
from ...boards.abstract_board import AbstractBoard
from ...isas import ISA
from ...runtime import get_runtime_isa
from m5.objects import BaseXBar, SystemXBar, BadAddr, Port
from typing import Optional
from ...utils.override import *
class NoCache(AbstractClassicCacheHierarchy):
"""
No cache hierarchy. The CPUs are connected straight to the memory bus.
By default a SystemXBar of width 64bit is used, though this can be
configured via the constructor.
NOTE: At present this does not work with FS. The following error is
received:
```
...
build/X86/mem/snoop_filter.cc:277: panic: panic condition
(sf_item.requested & req_mask).none() occurred: SF value
0000000000000000000000000000000000000000000000000000000000000000 ...
missing the original request
Memory Usage: 3554472 KBytes
Program aborted at tick 1668400099164
--- BEGIN LIBC BACKTRACE ---
...
```
"""
@staticmethod
def _get_default_membus() -> SystemXBar:
"""
A method used to obtain the default memory bus of 64 bit in width for
the NoCache CacheHierarchy.
:returns: The default memory bus for the NoCache CacheHierarchy.
:rtype: SystemXBar
"""
membus = SystemXBar(width=64)
membus.badaddr_responder = BadAddr()
membus.default = membus.badaddr_responder.pio
return membus
def __init__(
self, membus: Optional[BaseXBar] = _get_default_membus.__func__()
) -> None:
"""
:param membus: The memory bus for this setup. This parameter is
optional and will default toa 64 bit width SystemXBar is not specified.
:type membus: Optional[BaseXBar]
"""
super(NoCache, self).__init__()
self.membus = membus
@overrides(AbstractClassicCacheHierarchy)
def get_mem_side_port(self) -> Port:
return self.membus.mem_side_ports
@overrides(AbstractClassicCacheHierarchy)
def get_cpu_side_port(self) -> Port:
return self.membus.cpu_side_ports
@overrides(AbstractCacheHierarchy)
def incorporate_cache(self, board: AbstractBoard) -> None:
for core in board.get_processor().get_cores():
core.connect_icache(self.membus.cpu_side_ports)
core.connect_dcache(self.membus.cpu_side_ports)
core.connect_walker_ports(
self.membus.cpu_side_ports, self.membus.cpu_side_ports
)
if get_runtime_isa() == ISA.X86:
int_req_port = self.membus.mem_side_ports
int_resp_port = self.membus.cpu_side_ports
core.connect_interrupt(int_req_port, int_resp_port)
# Set up the system port for functional access from the simulator.
board.connect_system_port(self.membus.cpu_side_ports)
for cntr in board.get_memory().get_memory_controllers():
cntr.port = self.membus.mem_side_ports

View File

@@ -0,0 +1,159 @@
# Copyright (c) 2021 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 ..abstract_cache_hierarchy import AbstractCacheHierarchy
from .abstract_classic_cache_hierarchy import AbstractClassicCacheHierarchy
from ..abstract_two_level_cache_hierarchy import AbstractTwoLevelCacheHierarchy
from .caches.l1dcache import L1DCache
from .caches.l1icache import L1ICache
from .caches.l2cache import L2Cache
from ...boards.abstract_board import AbstractBoard
from ...isas import ISA
from ...runtime import get_runtime_isa
from m5.objects import L2XBar, BaseXBar, SystemXBar, BadAddr, Port
from ...utils.override import *
from typing import Optional
class PrivateL1PrivateL2CacheHierarchy(
AbstractClassicCacheHierarchy, AbstractTwoLevelCacheHierarchy
):
"""
A cache setup where each core has a private L1 Data and Instruction Cache,
and a private L2 cache.
"""
@staticmethod
def _get_default_membus() -> SystemXBar:
"""
A method used to obtain the default memory bus of 64 bit in width for
the PrivateL1PrivateL2 CacheHierarchy.
:returns: The default memory bus for the PrivateL1PrivateL2
CacheHierarchy.
:rtype: SystemXBar
"""
membus = SystemXBar(width=64)
membus.badaddr_responder = BadAddr()
membus.default = membus.badaddr_responder.pio
return membus
def __init__(
self,
l1d_size: str,
l1i_size: str,
l2_size: str,
membus: Optional[BaseXBar] = _get_default_membus.__func__(),
) -> None:
"""
:param l1d_size: The size of the L1 Data Cache (e.g., "32kB").
:type l1d_size: str
:param l1i_size: The size of the L1 Instruction Cache (e.g., "32kB").
:type l1i_size: str
:param l2_size: The size of the L2 Cache (e.g., "256kB").
:type l2_size: str
:param membus: The memory bus. This parameter is optional parameter and
will default to a 64 bit width SystemXBar is not specified.
:type membus: Optional[BaseXBar]
"""
AbstractClassicCacheHierarchy.__init__(self=self)
AbstractTwoLevelCacheHierarchy.__init__(
self,
l1i_size=l1i_size,
l1i_assoc=8,
l1d_size=l1d_size,
l1d_assoc=8,
l2_size=l2_size,
l2_assoc=4,
)
self.membus = membus
@overrides(AbstractClassicCacheHierarchy)
def get_mem_side_port(self) -> Port:
return self.membus.mem_side_ports
@overrides(AbstractClassicCacheHierarchy)
def get_cpu_side_port(self) -> Port:
return self.membus.cpu_side_ports
@overrides(AbstractCacheHierarchy)
def incorporate_cache(self, board: AbstractBoard) -> None:
# Set up the system port for functional access from the simulator.
board.connect_system_port(self.membus.cpu_side_ports)
for cntr in board.get_memory().get_memory_controllers():
cntr.port = self.membus.mem_side_ports
self.l1icaches = [
L1ICache(size=self._l1i_size)
for i in range(board.get_processor().get_num_cores())
]
self.l1dcaches = [
L1DCache(size=self._l1i_size)
for i in range(board.get_processor().get_num_cores())
]
self.l2buses = [
L2XBar() for i in range(board.get_processor().get_num_cores())
]
self.l2caches = [
L2Cache(size=self._l2_size)
for i in range(board.get_processor().get_num_cores())
]
for i, cpu in enumerate(board.get_processor().get_cores()):
cpu.connect_icache(self.l1icaches[i].cpu_side)
cpu.connect_dcache(self.l1dcaches[i].cpu_side)
self.l1icaches[i].mem_side = self.l2buses[i].cpu_side_ports
self.l1dcaches[i].mem_side = self.l2buses[i].cpu_side_ports
self.l2buses[i].mem_side_ports = self.l2caches[i].cpu_side
self.membus.cpu_side_ports = self.l2caches[i].mem_side
cpu.connect_walker_ports(
self.membus.cpu_side_ports, self.membus.cpu_side_ports
)
if get_runtime_isa() == ISA.X86:
int_req_port = self.membus.mem_side_ports
int_resp_port = self.membus.cpu_side_ports
cpu.connect_interrupt(int_req_port, int_resp_port)

View File

@@ -0,0 +1,42 @@
# Copyright (c) 2021 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 components_library.utils.override import overrides
from ..abstract_cache_hierarchy import AbstractCacheHierarchy
class AbstractRubyCacheHierarchy(AbstractCacheHierarchy):
"""
All Ruby-based cache hierarchies inherit from this class. This class
provides the shared infrastructure that all Ruby protocols need.
"""
def __init__(self):
super(AbstractRubyCacheHierarchy, self).__init__()
@overrides(AbstractCacheHierarchy)
def is_ruby(self) -> bool:
return True

View File

@@ -0,0 +1,51 @@
# Copyright (c) 2021 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 abc import abstractmethod
from m5.objects import Directory_Controller
class AbstractDirectory(Directory_Controller):
_version = 0
@classmethod
def versionCount(cls):
cls._version += 1 # Use count for this particular type
return cls._version - 1
def __init__(self, network, cache_line_size):
""" """
super(AbstractDirectory, self).__init__()
self.version = self.versionCount()
self._cache_line_size = cache_line_size
self.connectQueues(network)
@abstractmethod
def connectQueues(self, network):
"""Connect all of the queues for this controller."""
raise NotImplementedError

View File

@@ -0,0 +1,50 @@
# Copyright (c) 2021 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 abc import abstractmethod
from m5.objects import DMA_Controller
class AbstractDMAController(DMA_Controller):
_version = 0
@classmethod
def versionCount(cls):
cls._version += 1 # Use count for this particular type
return cls._version - 1
def __init__(self, network, cache_line_size):
super(AbstractDMAController, self).__init__()
self.version = self.versionCount()
self._cache_line_size = cache_line_size
self.connectQueues(network)
@abstractmethod
def connectQueues(self, network):
"""Connect all of the queues for this controller."""
raise NotImplementedError

View File

@@ -0,0 +1,76 @@
# Copyright (c) 2021 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 abc import abstractmethod
from components_library.isas import ISA
from components_library.processors.cpu_types import CPUTypes
from components_library.processors.abstract_core import AbstractCore
from m5.objects import L1Cache_Controller
import math
class AbstractL1Cache(L1Cache_Controller):
_version = 0
@classmethod
def versionCount(cls):
cls._version += 1 # Use count for this particular type
return cls._version - 1
# TODO: I don't love that we have to pass in the cache line size.
# However, we need some way to set the index bits
def __init__(self, network, cache_line_size):
""" """
super(AbstractL1Cache, self).__init__()
self.version = self.versionCount()
self._cache_line_size = cache_line_size
self.connectQueues(network)
def getBlockSizeBits(self):
bits = int(math.log(self._cache_line_size, 2))
if 2 ** bits != self._cache_line_size.value:
raise Exception("Cache line size not a power of 2!")
return bits
def sendEvicts(self, core: AbstractCore, target_isa: ISA):
"""True if the CPU model or ISA requires sending evictions from caches
to the CPU. Two scenarios warrant forwarding evictions to the CPU:
1. The O3 model must keep the LSQ coherent with the caches
2. The x86 mwait instruction is built on top of coherence
3. The local exclusive monitor in ARM systems
"""
if core.get_type() is CPUTypes.O3 or target_isa in (ISA.X86, ISA.ARM):
return True
return False
@abstractmethod
def connectQueues(self, network):
"""Connect all of the queues for this controller."""
raise NotImplementedError

View File

@@ -0,0 +1,51 @@
# Copyright (c) 2021 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 abc import abstractmethod
from m5.objects import L2Cache_Controller
class AbstractL2Cache(L2Cache_Controller):
_version = 0
@classmethod
def versionCount(cls):
cls._version += 1 # Use count for this particular type
return cls._version - 1
def __init__(self, network, cache_line_size):
super(AbstractL2Cache, self).__init__()
self.version = self.versionCount()
self._cache_line_size = cache_line_size
self.connectQueues(network)
@abstractmethod
def connectQueues(self, network):
"""Connect all of the queues for this controller."""
raise NotImplementedError

View File

@@ -0,0 +1,54 @@
# Copyright (c) 2021 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 components_library.utils.override import overrides
from ..abstract_directory import AbstractDirectory
from m5.objects import (
MessageBuffer,
RubyDirectoryMemory,
)
class Directory(AbstractDirectory):
def __init__(self, network, cache_line_size, mem_range, port):
super(Directory, self).__init__(network, cache_line_size)
self.addr_ranges = [mem_range]
self.directory = RubyDirectoryMemory()
# Connect this directory to the memory side.
self.memory_out_port = port
@overrides(AbstractDirectory)
def connectQueues(self, network):
self.requestToDir = MessageBuffer()
self.requestToDir.in_port = network.out_port
self.responseToDir = MessageBuffer()
self.responseToDir.in_port = network.out_port
self.responseFromDir = MessageBuffer()
self.responseFromDir.out_port = network.in_port
self.requestToMemory = MessageBuffer()
self.responseFromMemory = MessageBuffer()

View File

@@ -0,0 +1,43 @@
# Copyright (c) 2021 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 components_library.utils.override import overrides
from ..abstract_dma_controller import AbstractDMAController
from m5.objects import MessageBuffer
class DMAController(AbstractDMAController):
def __init__(self, network, cache_line_size):
super(DMAController, self).__init__(network, cache_line_size)
@overrides(AbstractDMAController)
def connectQueues(self, network):
self.mandatoryQueue = MessageBuffer()
self.responseFromDir = MessageBuffer(ordered=True)
self.responseFromDir.in_port = network.out_port
self.requestToDir = MessageBuffer()
self.requestToDir.out_port = network.in_port

View File

@@ -0,0 +1,96 @@
# Copyright (c) 2021 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 components_library.processors.abstract_core import AbstractCore
from components_library.isas import ISA
from ..abstract_l1_cache import AbstractL1Cache
from components_library.utils.override import *
from m5.objects import (
MessageBuffer,
RubyPrefetcher,
RubyCache,
ClockDomain,
)
import math
class L1Cache(AbstractL1Cache):
def __init__(
self,
l1i_size,
l1i_assoc,
l1d_size,
l1d_assoc,
network,
core: AbstractCore,
num_l2Caches,
cache_line_size,
target_isa: ISA,
clk_domain: ClockDomain,
):
"""Creating L1 cache controller. Consist of both instruction
and data cache.
"""
super(L1Cache, self).__init__(network, cache_line_size)
# This is the cache memory object that stores the cache data and tags
self.L1Icache = RubyCache(
size=l1i_size,
assoc=l1i_assoc,
start_index_bit=self.getBlockSizeBits(),
is_icache=True,
)
self.L1Dcache = RubyCache(
size=l1d_size,
assoc=l1d_assoc,
start_index_bit=self.getBlockSizeBits(),
is_icache=False,
)
self.l2_select_num_bits = int(math.log(num_l2Caches, 2))
self.clk_domain = clk_domain
self.prefetcher = RubyPrefetcher()
self.send_evictions = self.sendEvicts(core=core, target_isa=target_isa)
self.transitions_per_cycle = 4
self.enable_prefetch = False
@overrides(AbstractL1Cache)
def connectQueues(self, network):
self.mandatoryQueue = MessageBuffer()
self.requestFromL1Cache = MessageBuffer()
self.requestFromL1Cache.out_port = network.in_port
self.responseFromL1Cache = MessageBuffer()
self.responseFromL1Cache.out_port = network.in_port
self.unblockFromL1Cache = MessageBuffer()
self.unblockFromL1Cache.out_port = network.in_port
self.optionalQueue = MessageBuffer()
self.requestToL1Cache = MessageBuffer()
self.requestToL1Cache.in_port = network.out_port
self.responseToL1Cache = MessageBuffer()
self.responseToL1Cache.in_port = network.out_port

View File

@@ -0,0 +1,68 @@
# Copyright (c) 2021 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 ..abstract_l2_cache import AbstractL2Cache
from components_library.utils.override import *
from m5.objects import MessageBuffer, RubyCache
import math
class L2Cache(AbstractL2Cache):
def __init__(
self, l2_size, l2_assoc, network, num_l2Caches, cache_line_size
):
super(L2Cache, self).__init__(network, cache_line_size)
# This is the cache memory object that stores the cache data and tags
self.L2cache = RubyCache(
size=l2_size,
assoc=l2_assoc,
start_index_bit=self.getIndexBit(num_l2Caches),
)
self.transitions_per_cycle = "4"
def getIndexBit(self, num_l2caches):
l2_bits = int(math.log(num_l2caches, 2))
bits = int(math.log(self._cache_line_size, 2)) + l2_bits
return bits
@overrides(AbstractL2Cache)
def connectQueues(self, network):
self.DirRequestFromL2Cache = MessageBuffer()
self.DirRequestFromL2Cache.out_port = network.in_port
self.L1RequestFromL2Cache = MessageBuffer()
self.L1RequestFromL2Cache.out_port = network.in_port
self.responseFromL2Cache = MessageBuffer()
self.responseFromL2Cache.out_port = network.in_port
self.unblockToL2Cache = MessageBuffer()
self.unblockToL2Cache.in_port = network.out_port
self.L1RequestToL2Cache = MessageBuffer()
self.L1RequestToL2Cache.in_port = network.out_port
self.responseToL2Cache = MessageBuffer()
self.responseToL2Cache.in_port = network.out_port

View File

@@ -0,0 +1,205 @@
# Copyright (c) 2021 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 .abstract_ruby_cache_hierarhcy import AbstractRubyCacheHierarchy
from ..abstract_two_level_cache_hierarchy import AbstractTwoLevelCacheHierarchy
from ...coherence_protocol import CoherenceProtocol
from ...isas import ISA
from ...boards.abstract_board import AbstractBoard
from ...runtime import get_runtime_coherence_protocol, get_runtime_isa
from .topologies.simple_pt2pt import SimplePt2Pt
from .caches.mesi_two_level.l1_cache import L1Cache
from .caches.mesi_two_level.l2_cache import L2Cache
from .caches.mesi_two_level.directory import Directory
from .caches.mesi_two_level.dma_controller import DMAController
from m5.objects import (
RubySystem,
RubySequencer,
DMASequencer,
RubyPortProxy,
)
class MESITwoLevelCacheHierarchy(
AbstractRubyCacheHierarchy, AbstractTwoLevelCacheHierarchy
):
"""A two level private L1 shared L2 MESI hierarchy.
In addition to the normal two level parameters, you can also change the
number of L2 banks in this protocol.
The on-chip network is a point-to-point all-to-all simple network.
"""
def __init__(
self,
l1i_size: str,
l1i_assoc: str,
l1d_size: str,
l1d_assoc: str,
l2_size: str,
l2_assoc: str,
num_l2_banks: int,
):
AbstractRubyCacheHierarchy.__init__(self=self)
AbstractTwoLevelCacheHierarchy.__init__(
self,
l1i_size=l1i_size,
l1i_assoc=l1i_assoc,
l1d_size=l1d_size,
l1d_assoc=l1d_assoc,
l2_size=l2_size,
l2_assoc=l2_assoc,
)
self._num_l2_banks = num_l2_banks
def incorporate_cache(self, board: AbstractBoard) -> None:
if (
get_runtime_coherence_protocol()
!= CoherenceProtocol.MESI_TWO_LEVEL
):
raise EnvironmentError(
"The MESITwoLevelCacheHierarchy must be used with with the "
"MESI_Two_Level coherence protocol."
)
cache_line_size = board.get_cache_line_size()
self.ruby_system = RubySystem()
# MESI_Two_Level needs 5 virtual networks
self.ruby_system.number_of_virtual_networks = 5
self.ruby_system.network = SimplePt2Pt(self.ruby_system)
self.ruby_system.network.number_of_virtual_networks = 5
self._l1_controllers = []
for i, core in enumerate(board.get_processor().get_cores()):
cache = L1Cache(
self._l1i_size,
self._l1i_assoc,
self._l1d_size,
self._l1d_assoc,
self.ruby_system.network,
core,
self._num_l2_banks,
cache_line_size,
get_runtime_isa(),
board.get_clock_domain(),
)
if board.has_io_bus():
cache.sequencer = RubySequencer(
version=i,
dcache=cache.L1Dcache,
clk_domain=cache.clk_domain,
pio_request_port=board.get_io_bus().cpu_side_ports,
mem_request_port=board.get_io_bus().cpu_side_ports,
pio_response_port=board.get_io_bus().mem_side_ports,
)
else:
cache.sequencer = RubySequencer(
version=i,
dcache=cache.L1Dcache,
clk_domain=cache.clk_domain,
)
cache.ruby_system = self.ruby_system
core.connect_icache(cache.sequencer.in_ports)
core.connect_dcache(cache.sequencer.in_ports)
core.connect_walker_ports(
cache.sequencer.in_ports, cache.sequencer.in_ports
)
# Connect the interrupt ports
if get_runtime_isa() == ISA.X86:
int_req_port = cache.sequencer.interrupt_out_port
int_resp_port = cache.sequencer.in_ports
core.connect_interrupt(int_req_port, int_resp_port)
self._l1_controllers.append(cache)
self._l2_controllers = [
L2Cache(
self._l2_size,
self._l2_assoc,
self.ruby_system.network,
self._num_l2_banks,
cache_line_size,
)
for _ in range(self._num_l2_banks)
]
# TODO: Make this prettier: The problem is not being able to proxy
# the ruby system correctly
for cache in self._l2_controllers:
cache.ruby_system = self.ruby_system
self._directory_controllers = [
Directory(self.ruby_system.network, cache_line_size, range, port)
for range, port in board.get_memory().get_mem_ports()
]
# TODO: Make this prettier: The problem is not being able to proxy
# the ruby system correctly
for dir in self._directory_controllers:
dir.ruby_system = self.ruby_system
dma_ports = board.get_dma_ports()
self._dma_controllers = []
for i, port in enumerate(dma_ports):
ctrl = DMAController(self.ruby_system.network, cache_line_size)
ctrl.dma_sequencer = DMASequencer(version=i, in_ports=port)
self._dma_controllers.append(ctrl)
ctrl.ruby_system = self.ruby_system
self.ruby_system.num_of_sequencers = len(self._l1_controllers) + len(
self._dma_controllers
)
self.ruby_system.l1_controllers = self._l1_controllers
self.ruby_system.l2_controllers = self._l2_controllers
self.ruby_system.directory_controllers = self._directory_controllers
if len(self._dma_controllers) != 0:
self.ruby_system.dma_controllers = self._dma_controllers
# Create the network and connect the controllers.
self.ruby_system.network.connectControllers(
self._l1_controllers
+ self._l2_controllers
+ self._directory_controllers
+ self._dma_controllers
)
self.ruby_system.network.setup_buffers()
# Set up a proxy port for the system_port. Used for load binaries and
# other functional-only things.
self.ruby_system.sys_port_proxy = RubyPortProxy()
board.connect_system_port(self.ruby_system.sys_port_proxy.in_ports)

View File

@@ -0,0 +1,67 @@
# Copyright (c) 2021 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 SimpleNetwork, Switch, SimpleExtLink, SimpleIntLink
class SimplePt2Pt(SimpleNetwork):
"""A simple point-to-point network. This doesn't not use garnet."""
def __init__(self, ruby_system):
super(SimplePt2Pt, self).__init__()
self.netifs = []
# TODO: These should be in a base class
# https://gem5.atlassian.net/browse/GEM5-1039
self.ruby_system = ruby_system
def connectControllers(self, controllers):
"""Connect all of the controllers to routers and connec the routers
together in a point-to-point network.
"""
# Create one router/switch per controller in the system
self.routers = [Switch(router_id=i) for i in range(len(controllers))]
# Make a link from each controller to the router. The link goes
# externally to the network.
self.ext_links = [
SimpleExtLink(link_id=i, ext_node=c, int_node=self.routers[i])
for i, c in enumerate(controllers)
]
# Make an "internal" link (internal to the network) between every pair
# of routers.
link_count = 0
int_links = []
for ri in self.routers:
for rj in self.routers:
if ri == rj:
continue # Don't connect a router to itself!
link_count += 1
int_links.append(
SimpleIntLink(link_id=link_count, src_node=ri, dst_node=rj)
)
self.int_links = int_links

View File

@@ -0,0 +1,65 @@
# Copyright (c) 2021 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.
"""
Specifies the coherence protocol enum
"""
from enum import Enum
class CoherenceProtocol(Enum):
MESI_THREE_LEVEL = 1
MESI_THREE_LEVEL_HTM = 2
ARM_MOESI_HAMMER = 3
GARNET_STANDALONE = 4
MESI_TWO_LEVEL = 5
MOESI_CMP_DIRECTORY = 6
MOESI_CMP_TOKEN = 7
MOESI_AMD_BASE = 8
MI_EXAMPLE = 9
GPU_VIPER = 10
CHI = 11
def is_ruby(protocol: CoherenceProtocol) -> bool:
"""Specifies if a given protocol is Ruby or not
:returns: True if the given protocol is Ruby, otherwise false
"""
ruby = (
CoherenceProtocol.MESI_THREE_LEVEL,
CoherenceProtocol.MESI_THREE_LEVEL_HTM,
CoherenceProtocol.ARM_MOESI_HAMMER,
CoherenceProtocol.GARNET_STANDALONE,
CoherenceProtocol.MESI_TWO_LEVEL,
CoherenceProtocol.MOESI_CMP_DIRECTORY,
CoherenceProtocol.MOESI_CMP_TOKEN,
CoherenceProtocol.MOESI_AMD_BASE,
CoherenceProtocol.GPU_VIPER,
)
return protocol in ruby

View File

@@ -0,0 +1,41 @@
# Copyright (c) 2021 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.
"""
Specifies the ISA enum
"""
from enum import Enum
class ISA(Enum):
X86 = 1
RISCV = 2
ARM = 3
MIPS = 4
POWER = 5
SPARC = 6
NULL = 7

View File

@@ -0,0 +1,57 @@
# Copyright (c) 2021 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 abc import ABCMeta, abstractmethod
from typing import Tuple, Sequence, List
from ..boards.abstract_board import AbstractBoard
from m5.objects import AddrRange, Port, SubSystem, MemCtrl
class AbstractMemorySystem(SubSystem):
__metaclass__ = ABCMeta
def __init__(self) -> None:
super(AbstractMemorySystem, self).__init__()
@abstractmethod
def incorporate_memory(self, board: AbstractBoard) -> None:
raise NotImplementedError
@abstractmethod
def get_mem_ports(self) -> Sequence[Tuple[AddrRange, Port]]:
raise NotImplementedError
@abstractmethod
def get_memory_controllers(self) -> List[MemCtrl]:
raise NotImplementedError
@abstractmethod
def get_memory_ranges(self) -> List[AddrRange]:
"""All of the memory ranges that this memory system responds to."""
raise NotImplementedError

View File

@@ -0,0 +1,66 @@
# Copyright (c) 2021 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 abc import abstractmethod
from typing import Optional
from m5.objects import DDR3_1600_8x8 as DIMM
from m5.objects import MemCtrl
from m5.params import Port, AddrRange
from .abstract_memory_system import AbstractMemorySystem
from ..boards.abstract_board import AbstractBoard
from ..utils.override import *
from typing import Tuple, Sequence, List
class DDR3_1600_8x8(AbstractMemorySystem):
def __init__(self, size: Optional[str] = "512MiB") -> None:
super(DDR3_1600_8x8, self).__init__()
# The DDR3_1600_8x8 has a lot of variables with sensible defaults that
# make sense for a DDR3_1600_8x8 device. Only the size has been
# exposed.
self._dram = DIMM(range=size)
self.mem_cntrls = [MemCtrl(dram=self._dram)]
@overrides(AbstractMemorySystem)
def incorporate_memory(self, board: AbstractBoard) -> None:
pass
@overrides(AbstractMemorySystem)
def get_mem_ports(self) -> Tuple[Sequence[AddrRange], Port]:
return [(self._dram.range, ctrl.port) for ctrl in self.mem_cntrls]
@overrides(AbstractMemorySystem)
def get_memory_controllers(self) -> List[MemCtrl]:
return self.mem_cntrls
@overrides(AbstractMemorySystem)
def get_memory_ranges(self):
return [self._dram.range]

View File

@@ -0,0 +1,166 @@
# Copyright (c) 2012-2021 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2013 Amin Farmahini-Farahani
# Copyright (c) 2015 University of Kaiserslautern
# Copyright (c) 2015 The University of Bologna
# 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.
"""Interfaces for DDR3 memories
These memory "interfaces" contain the timing, energy, etc. parameters for each
memory type and are usually based on datasheets for the memory devices.
You can use these interfaces in the MemCtrl object as the `dram` timing
interface.
"""
from m5.objects import DRAMInterface
class DDR3_1600_8x8(DRAMInterface):
"""
A single DDR3-1600 x64 channel (one command and address bus), with
timings based on a DDR3-1600 4 Gbit datasheet (Micron MT41J512M8) in
an 8x8 configuration.
"""
# size of device in bytes
device_size = "512MiB"
# 8x8 configuration, 8 devices each with an 8-bit interface
device_bus_width = 8
# DDR3 is a BL8 device
burst_length = 8
# Each device has a page (row buffer) size of 1 Kbyte (1K columns x8)
device_rowbuffer_size = "1KiB"
# 8x8 configuration, so 8 devices
devices_per_rank = 8
# Use two ranks
ranks_per_channel = 2
# DDR3 has 8 banks in all configurations
banks_per_rank = 8
# 800 MHz
tCK = "1.25ns"
# 8 beats across an x64 interface translates to 4 clocks @ 800 MHz
tBURST = "5ns"
# DDR3-1600 11-11-11
tRCD = "13.75ns"
tCL = "13.75ns"
tRP = "13.75ns"
tRAS = "35ns"
tRRD = "6ns"
tXAW = "30ns"
activation_limit = 4
tRFC = "260ns"
tWR = "15ns"
# Greater of 4 CK or 7.5 ns
tWTR = "7.5ns"
# Greater of 4 CK or 7.5 ns
tRTP = "7.5ns"
# Default same rank rd-to-wr bus turnaround to 2 CK, @800 MHz = 2.5 ns
tRTW = "2.5ns"
# Default different rank bus delay to 2 CK, @800 MHz = 2.5 ns
tCS = "2.5ns"
# <=85C, half for >85C
tREFI = "7.8us"
# active powerdown and precharge powerdown exit time
tXP = "6ns"
# self refresh exit time
tXS = "270ns"
# Current values from datasheet Die Rev E,J
IDD0 = "55mA"
IDD2N = "32mA"
IDD3N = "38mA"
IDD4W = "125mA"
IDD4R = "157mA"
IDD5 = "235mA"
IDD3P1 = "38mA"
IDD2P1 = "32mA"
IDD6 = "20mA"
VDD = "1.5V"
class DDR3_2133_8x8(DDR3_1600_8x8):
"""
A single DDR3-2133 x64 channel refining a selected subset of the
options for the DDR-1600 configuration, based on the same DDR3-1600
4 Gbit datasheet (Micron MT41J512M8). Most parameters are kept
consistent across the two configurations.
"""
# 1066 MHz
tCK = "0.938ns"
# 8 beats across an x64 interface translates to 4 clocks @ 1066 MHz
tBURST = "3.752ns"
# DDR3-2133 14-14-14
tRCD = "13.09ns"
tCL = "13.09ns"
tRP = "13.09ns"
tRAS = "33ns"
tRRD = "5ns"
tXAW = "25ns"
# Current values from datasheet
IDD0 = "70mA"
IDD2N = "37mA"
IDD3N = "44mA"
IDD4W = "157mA"
IDD4R = "191mA"
IDD5 = "250mA"
IDD3P1 = "44mA"
IDD2P1 = "43mA"
IDD6 = "20mA"
VDD = "1.5V"

View File

@@ -0,0 +1,245 @@
# Copyright (c) 2012-2021 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2013 Amin Farmahini-Farahani
# Copyright (c) 2015 University of Kaiserslautern
# Copyright (c) 2015 The University of Bologna
# 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.
"""Interfaces for DDR4 memories
These memory "interfaces" contain the timing,energy,etc parameters for each
memory type and are usually based on datasheets for the memory devices.
You can use these interfaces in the MemCtrl object as the `dram` timing
interface.
"""
from m5.objects import DRAMInterface
class DDR4_2400_16x4(DRAMInterface):
"""
A single DDR4-2400 x64 channel (one command and address bus), with
timings based on a DDR4-2400 8 Gbit datasheet (Micron MT40A2G4)
in an 16x4 configuration.
Total channel capacity is 32GiB
16 devices/rank * 2 ranks/channel * 1GiB/device = 32GiB/channel
"""
# size of device
device_size = "1GiB"
# 16x4 configuration, 16 devices each with a 4-bit interface
device_bus_width = 4
# DDR4 is a BL8 device
burst_length = 8
# Each device has a page (row buffer) size of 512 byte (1K columns x4)
device_rowbuffer_size = "512B"
# 16x4 configuration, so 16 devices
devices_per_rank = 16
# Match our DDR3 configurations which is dual rank
ranks_per_channel = 2
# DDR4 has 2 (x16) or 4 (x4 and x8) bank groups
# Set to 4 for x4 case
bank_groups_per_rank = 4
# DDR4 has 16 banks(x4,x8) and 8 banks(x16) (4 bank groups in all
# configurations). Currently we do not capture the additional
# constraints incurred by the bank groups
banks_per_rank = 16
# override the default buffer sizes and go for something larger to
# accommodate the larger bank count
write_buffer_size = 128
read_buffer_size = 64
# 1200 MHz
tCK = "0.833ns"
# 8 beats across an x64 interface translates to 4 clocks @ 1200 MHz
# tBURST is equivalent to the CAS-to-CAS delay (tCCD)
# With bank group architectures, tBURST represents the CAS-to-CAS
# delay for bursts to different bank groups (tCCD_S)
tBURST = "3.332ns"
# @2400 data rate, tCCD_L is 6 CK
# CAS-to-CAS delay for bursts to the same bank group
# tBURST is equivalent to tCCD_S; no explicit parameter required
# for CAS-to-CAS delay for bursts to different bank groups
tCCD_L = "5ns"
# DDR4-2400 17-17-17
tRCD = "14.16ns"
tCL = "14.16ns"
tRP = "14.16ns"
tRAS = "32ns"
# RRD_S (different bank group) for 512B page is MAX(4 CK, 3.3ns)
tRRD = "3.332ns"
# RRD_L (same bank group) for 512B page is MAX(4 CK, 4.9ns)
tRRD_L = "4.9ns"
# tFAW for 512B page is MAX(16 CK, 13ns)
tXAW = "13.328ns"
activation_limit = 4
# tRFC is 350ns
tRFC = "350ns"
tWR = "15ns"
# Here using the average of WTR_S and WTR_L
tWTR = "5ns"
# Greater of 4 CK or 7.5 ns
tRTP = "7.5ns"
# Default same rank rd-to-wr bus turnaround to 2 CK, @1200 MHz = 1.666 ns
tRTW = "1.666ns"
# Default different rank bus delay to 2 CK, @1200 MHz = 1.666 ns
tCS = "1.666ns"
# <=85C, half for >85C
tREFI = "7.8us"
# active powerdown and precharge powerdown exit time
tXP = "6ns"
# self refresh exit time
# exit delay to ACT, PRE, PREALL, REF, SREF Enter, and PD Enter is:
# tRFC + 10ns = 340ns
tXS = "340ns"
# Current values from datasheet
IDD0 = "43mA"
IDD02 = "3mA"
IDD2N = "34mA"
IDD3N = "38mA"
IDD3N2 = "3mA"
IDD4W = "103mA"
IDD4R = "110mA"
IDD5 = "250mA"
IDD3P1 = "32mA"
IDD2P1 = "25mA"
IDD6 = "30mA"
VDD = "1.2V"
VDD2 = "2.5V"
class DDR4_2400_8x8(DDR4_2400_16x4):
"""
A single DDR4-2400 x64 channel (one command and address bus), with
timings based on a DDR4-2400 8 Gbit datasheet (Micron MT40A1G8)
in an 8x8 configuration.
Total channel capacity is 16GiB
8 devices/rank * 2 ranks/channel * 1GiB/device = 16GiB/channel
"""
# 8x8 configuration, 8 devices each with an 8-bit interface
device_bus_width = 8
# Each device has a page (row buffer) size of 1 Kbyte (1K columns x8)
device_rowbuffer_size = "1KiB"
# 8x8 configuration, so 8 devices
devices_per_rank = 8
# RRD_L (same bank group) for 1K page is MAX(4 CK, 4.9ns)
tRRD_L = "4.9ns"
tXAW = "21ns"
# Current values from datasheet
IDD0 = "48mA"
IDD3N = "43mA"
IDD4W = "123mA"
IDD4R = "135mA"
IDD3P1 = "37mA"
class DDR4_2400_4x16(DDR4_2400_16x4):
"""
A single DDR4-2400 x64 channel (one command and address bus), with
timings based on a DDR4-2400 8 Gbit datasheet (Micron MT40A512M16)
in an 4x16 configuration.
Total channel capacity is 4GiB
4 devices/rank * 1 ranks/channel * 1GiB/device = 4GiB/channel
"""
# 4x16 configuration, 4 devices each with an 16-bit interface
device_bus_width = 16
# Each device has a page (row buffer) size of 2 Kbyte (1K columns x16)
device_rowbuffer_size = "2KiB"
# 4x16 configuration, so 4 devices
devices_per_rank = 4
# Single rank for x16
ranks_per_channel = 1
# DDR4 has 2 (x16) or 4 (x4 and x8) bank groups
# Set to 2 for x16 case
bank_groups_per_rank = 2
# DDR4 has 16 banks(x4,x8) and 8 banks(x16) (4 bank groups in all
# configurations). Currently we do not capture the additional
# constraints incurred by the bank groups
banks_per_rank = 8
# RRD_S (different bank group) for 2K page is MAX(4 CK, 5.3ns)
tRRD = "5.3ns"
# RRD_L (same bank group) for 2K page is MAX(4 CK, 6.4ns)
tRRD_L = "6.4ns"
tXAW = "30ns"
# Current values from datasheet
IDD0 = "80mA"
IDD02 = "4mA"
IDD2N = "34mA"
IDD3N = "47mA"
IDD4W = "228mA"
IDD4R = "243mA"
IDD5 = "280mA"
IDD3P1 = "41mA"

View File

@@ -0,0 +1,134 @@
# Copyright (c) 2012-2021 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2013 Amin Farmahini-Farahani
# Copyright (c) 2015 University of Kaiserslautern
# Copyright (c) 2015 The University of Bologna
# 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.
"""Interfaces for GDDR memory devices
These memory "interfaces" contain the timing,energy,etc parameters for each
memory type and are usually based on datasheets for the memory devices.
You can use these interfaces in the MemCtrl object as the `dram` timing
interface.
"""
from m5.objects import DRAMInterface
class GDDR5_4000_2x32(DRAMInterface):
"""
A single GDDR5 x64 interface, with default timings based on a GDDR5-4000
1 Gbit part (SK Hynix H5GQ1H24AFR) in a 2x32 configuration.
"""
# size of device
device_size = "128MiB"
# 2x32 configuration, 1 device with a 32-bit interface
device_bus_width = 32
# GDDR5 is a BL8 device
burst_length = 8
# Each device has a page (row buffer) size of 2Kbits (256Bytes)
device_rowbuffer_size = "256B"
# 2x32 configuration, so 2 devices
devices_per_rank = 2
# assume single rank
ranks_per_channel = 1
# GDDR5 has 4 bank groups
bank_groups_per_rank = 4
# GDDR5 has 16 banks with 4 bank groups
banks_per_rank = 16
# 1000 MHz
tCK = "1ns"
# 8 beats across an x64 interface translates to 2 clocks @ 1000 MHz
# Data bus runs @2000 Mhz => DDR ( data runs at 4000 MHz )
# 8 beats at 4000 MHz = 2 beats at 1000 MHz
# tBURST is equivalent to the CAS-to-CAS delay (tCCD)
# With bank group architectures, tBURST represents the CAS-to-CAS
# delay for bursts to different bank groups (tCCD_S)
tBURST = "2ns"
# @1000MHz data rate, tCCD_L is 3 CK
# CAS-to-CAS delay for bursts to the same bank group
# tBURST is equivalent to tCCD_S; no explicit parameter required
# for CAS-to-CAS delay for bursts to different bank groups
tCCD_L = "3ns"
tRCD = "12ns"
# tCL is not directly found in datasheet and assumed equal tRCD
tCL = "12ns"
tRP = "12ns"
tRAS = "28ns"
# RRD_S (different bank group)
# RRD_S is 5.5 ns in datasheet.
# rounded to the next multiple of tCK
tRRD = "6ns"
# RRD_L (same bank group)
# RRD_L is 5.5 ns in datasheet.
# rounded to the next multiple of tCK
tRRD_L = "6ns"
tXAW = "23ns"
# tXAW < 4 x tRRD.
# Therefore, activation limit is set to 0
activation_limit = 0
tRFC = "65ns"
tWR = "12ns"
# Here using the average of WTR_S and WTR_L
tWTR = "5ns"
# Read-to-Precharge 2 CK
tRTP = "2ns"
# Assume 2 cycles
tRTW = "2ns"

View File

@@ -0,0 +1,196 @@
# Copyright (c) 2012-2021 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2013 Amin Farmahini-Farahani
# Copyright (c) 2015 University of Kaiserslautern
# Copyright (c) 2015 The University of Bologna
# 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.
"""Interfaces for LPDDR5 memory devices
These memory "interfaces" contain the timing,energy,etc parameters for each
memory type and are usually based on datasheets for the memory devices.
You can use these interfaces in the MemCtrl object as the `dram` timing
interface.
"""
from m5.objects import DRAMInterface
class HBM_1000_4H_1x128(DRAMInterface):
"""
A single HBM x128 interface (one command and address bus), with
default timings based on data publically released
("HBM: Memory Solution for High Performance Processors", MemCon, 2014),
IDD measurement values, and by extrapolating data from other classes.
Architecture values based on published HBM spec
A 4H stack is defined, 2Gb per die for a total of 1GiB of memory.
**IMPORTANT**
HBM gen1 supports up to 8 128-bit physical channels
Configuration defines a single channel, with the capacity
set to (full_ stack_capacity / 8) based on 2Gb dies
To use all 8 channels, set 'channels' parameter to 8 in
system configuration
"""
# 128-bit interface legacy mode
device_bus_width = 128
# HBM supports BL4 and BL2 (legacy mode only)
burst_length = 4
# size of channel in bytes, 4H stack of 2Gb dies is 1GiB per stack;
# with 8 channels, 128MiB per channel
device_size = "128MiB"
device_rowbuffer_size = "2KiB"
# 1x128 configuration
devices_per_rank = 1
# HBM does not have a CS pin; set rank to 1
ranks_per_channel = 1
# HBM has 8 or 16 banks depending on capacity
# 2Gb dies have 8 banks
banks_per_rank = 8
# depending on frequency, bank groups may be required
# will always have 4 bank groups when enabled
# current specifications do not define the minimum frequency for
# bank group architecture
# setting bank_groups_per_rank to 0 to disable until range is defined
bank_groups_per_rank = 0
# 500 MHz for 1Gbps DDR data rate
tCK = "2ns"
# use values from IDD measurement in JEDEC spec
# use tRP value for tRCD and tCL similar to other classes
tRP = "15ns"
tRCD = "15ns"
tCL = "15ns"
tRAS = "33ns"
# BL2 and BL4 supported, default to BL4
# DDR @ 500 MHz means 4 * 2ns / 2 = 4ns
tBURST = "4ns"
# value for 2Gb device from JEDEC spec
tRFC = "160ns"
# value for 2Gb device from JEDEC spec
tREFI = "3.9us"
# extrapolate the following from LPDDR configs, using ns values
# to minimize burst length, prefetch differences
tWR = "18ns"
tRTP = "7.5ns"
tWTR = "10ns"
# start with 2 cycles turnaround, similar to other memory classes
# could be more with variations across the stack
tRTW = "4ns"
# single rank device, set to 0
tCS = "0ns"
# from MemCon example, tRRD is 4ns with 2ns tCK
tRRD = "4ns"
# from MemCon example, tFAW is 30ns with 2ns tCK
tXAW = "30ns"
activation_limit = 4
# 4tCK
tXP = "8ns"
# start with tRFC + tXP -> 160ns + 8ns = 168ns
tXS = "168ns"
class HBM_1000_4H_1x64(HBM_1000_4H_1x128):
"""
A single HBM x64 interface (one command and address bus), with
default timings based on HBM gen1 and data publically released
A 4H stack is defined, 8Gb per die for a total of 4GiB of memory.
Note: This defines a pseudo-channel with a unique controller
instantiated per pseudo-channel
Stay at same IO rate (1Gbps) to maintain timing relationship with
HBM gen1 class (HBM_1000_4H_x128) where possible
**IMPORTANT**
For HBM gen2 with pseudo-channel mode, configure 2X channels.
Configuration defines a single pseudo channel, with the capacity
set to (full_ stack_capacity / 16) based on 8Gb dies
To use all 16 pseudo channels, set 'channels' parameter to 16 in
system configuration
"""
# 64-bit pseudo-channel interface
device_bus_width = 64
# HBM pseudo-channel only supports BL4
burst_length = 4
# size of channel in bytes, 4H stack of 8Gb dies is 4GiB per stack;
# with 16 channels, 256MiB per channel
device_size = "256MiB"
# page size is halved with pseudo-channel; maintaining the same same number
# of rows per pseudo-channel with 2X banks across 2 channels
device_rowbuffer_size = "1KiB"
# HBM has 8 or 16 banks depending on capacity
# Starting with 4Gb dies, 16 banks are defined
banks_per_rank = 16
# reset tRFC for larger, 8Gb device
# use HBM1 4Gb value as a starting point
tRFC = "260ns"
# start with tRFC + tXP -> 160ns + 8ns = 168ns
tXS = "268ns"
# Default different rank bus delay to 2 CK, @1000 MHz = 2 ns
tCS = "2ns"
tREFI = "3.9us"
# active powerdown and precharge powerdown exit time
tXP = "10ns"
# self refresh exit time
tXS = "65ns"

View File

@@ -0,0 +1,161 @@
# Copyright (c) 2012-2021 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2013 Amin Farmahini-Farahani
# Copyright (c) 2015 University of Kaiserslautern
# Copyright (c) 2015 The University of Bologna
# 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.
"""Interfaces for HMC memory devices
These memory "interfaces" contain the timing,energy,etc parameters for each
memory type and are usually based on datasheets for the memory devices.
You can use these interfaces in the MemCtrl object as the `dram` timing
interface.
Note that HMC is configured differently than some other DRAM interfaces.
"""
class HMC_2500_1x32(DDR3_1600_8x8):
"""
A single HMC-2500 x32 model based on:
[1] DRAMSpec: a high-level DRAM bank modelling tool
developed at the University of Kaiserslautern. This high level tool
uses RC (resistance-capacitance) and CV (capacitance-voltage) models to
estimate the DRAM bank latency and power numbers.
[2] High performance AXI-4.0 based interconnect for extensible smart memory
cubes (E. Azarkhish et. al)
Assumed for the HMC model is a 30 nm technology node.
The modelled HMC consists of 4 Gbit layers which sum up to 2GiB of memory
(4 layers).
Each layer has 16 vaults and each vault consists of 2 banks per layer.
In order to be able to use the same controller used for 2D DRAM generations
for HMC, the following analogy is done:
Channel (DDR) => Vault (HMC)
device_size (DDR) => size of a single layer in a vault
ranks per channel (DDR) => number of layers
banks per rank (DDR) => banks per layer
devices per rank (DDR) => devices per layer ( 1 for HMC).
The parameters for which no input is available are inherited from the DDR3
configuration.
This configuration includes the latencies from the DRAM to the logic layer
of the HMC
"""
# size of device
# two banks per device with each bank 4MiB [2]
device_size = "8MiB"
# 1x32 configuration, 1 device with 32 TSVs [2]
device_bus_width = 32
# HMC is a BL8 device [2]
burst_length = 8
# Each device has a page (row buffer) size of 256 bytes [2]
device_rowbuffer_size = "256B"
# 1x32 configuration, so 1 device [2]
devices_per_rank = 1
# 4 layers so 4 ranks [2]
ranks_per_channel = 4
# HMC has 2 banks per layer [2]
# Each layer represents a rank. With 4 layers and 8 banks in total, each
# layer has 2 banks; thus 2 banks per rank.
banks_per_rank = 2
# 1250 MHz [2]
tCK = "0.8ns"
# 8 beats across an x32 interface translates to 4 clocks @ 1250 MHz
tBURST = "3.2ns"
# Values using DRAMSpec HMC model [1]
tRCD = "10.2ns"
tCL = "9.9ns"
tRP = "7.7ns"
tRAS = "21.6ns"
# tRRD depends on the power supply network for each vendor.
# We assume a tRRD of a double bank approach to be equal to 4 clock
# cycles (Assumption)
tRRD = "3.2ns"
# activation limit is set to 0 since there are only 2 banks per vault
# layer.
activation_limit = 0
# Values using DRAMSpec HMC model [1]
tRFC = "59ns"
tWR = "8ns"
tRTP = "4.9ns"
# Default different rank bus delay assumed to 1 CK for TSVs, @1250 MHz =
# 0.8 ns (Assumption)
tCS = "0.8ns"
# Value using DRAMSpec HMC model [1]
tREFI = "3.9us"
# The default page policy in the vault controllers is simple closed page
# [2] nevertheless 'close' policy opens and closes the row multiple times
# for bursts largers than 32Bytes. For this reason we use 'close_adaptive'
page_policy = "close_adaptive"
# RoCoRaBaCh resembles the default address mapping in HMC
addr_mapping = "RoCoRaBaCh"
# These parameters do not directly correlate with buffer_size in real
# hardware. Nevertheless, their value has been tuned to achieve a
# bandwidth similar to the cycle-accurate model in [2]
write_buffer_size = 32
read_buffer_size = 32
def controller(self):
"""
Instantiate the memory controller and bind it to
the current interface.
"""
controller = MemCtrl(
min_writes_per_switch=8,
static_backend_latency="4ns",
static_frontend_latency="4ns",
)
controller.dram = self
return controller

View File

@@ -0,0 +1,154 @@
# Copyright (c) 2012-2021 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2013 Amin Farmahini-Farahani
# Copyright (c) 2015 University of Kaiserslautern
# Copyright (c) 2015 The University of Bologna
# 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.
"""Interfaces for LPDDR2 memory devices
These memory "interfaces" contain the timing,energy,etc parameters for each
memory type and are usually based on datasheets for the memory devices.
You can use these interfaces in the MemCtrl object as the `dram` timing
interface.
"""
from m5.objects import DRAMInterface
class LPDDR2_S4_1066_1x32(DRAMInterface):
"""
A single LPDDR2-S4 x32 interface (one command/address bus), with
default timings based on a LPDDR2-1066 4 Gbit part (Micron MT42L128M32D1)
in a 1x32 configuration.
"""
# No DLL in LPDDR2
dll = False
# size of device
device_size = "512MiB"
# 1x32 configuration, 1 device with a 32-bit interface
device_bus_width = 32
# LPDDR2_S4 is a BL4 and BL8 device
burst_length = 8
# Each device has a page (row buffer) size of 1KB
# (this depends on the memory density)
device_rowbuffer_size = "1KiB"
# 1x32 configuration, so 1 device
devices_per_rank = 1
# Use a single rank
ranks_per_channel = 1
# LPDDR2-S4 has 8 banks in all configurations
banks_per_rank = 8
# 533 MHz
tCK = "1.876ns"
# Fixed at 15 ns
tRCD = "15ns"
# 8 CK read latency, 4 CK write latency @ 533 MHz, 1.876 ns cycle time
tCL = "15ns"
# Pre-charge one bank 15 ns (all banks 18 ns)
tRP = "15ns"
tRAS = "42ns"
tWR = "15ns"
tRTP = "7.5ns"
# 8 beats across an x32 DDR interface translates to 4 clocks @ 533 MHz.
# Note this is a BL8 DDR device.
# Requests larger than 32 bytes are broken down into multiple requests
# in the controller
tBURST = "7.5ns"
# LPDDR2-S4, 4 Gbit
tRFC = "130ns"
tREFI = "3.9us"
# active powerdown and precharge powerdown exit time
tXP = "7.5ns"
# self refresh exit time
tXS = "140ns"
# Irrespective of speed grade, tWTR is 7.5 ns
tWTR = "7.5ns"
# Default same rank rd-to-wr bus turnaround to 2 CK, @533 MHz = 3.75 ns
tRTW = "3.75ns"
# Default different rank bus delay to 2 CK, @533 MHz = 3.75 ns
tCS = "3.75ns"
# Activate to activate irrespective of density and speed grade
tRRD = "10.0ns"
# Irrespective of density, tFAW is 50 ns
tXAW = "50ns"
activation_limit = 4
# Current values from datasheet
IDD0 = "15mA"
IDD02 = "70mA"
IDD2N = "2mA"
IDD2N2 = "30mA"
IDD3N = "2.5mA"
IDD3N2 = "30mA"
IDD4W = "10mA"
IDD4W2 = "190mA"
IDD4R = "3mA"
IDD4R2 = "220mA"
IDD5 = "40mA"
IDD52 = "150mA"
IDD3P1 = "1.2mA"
IDD3P12 = "8mA"
IDD2P1 = "0.6mA"
IDD2P12 = "0.8mA"
IDD6 = "1mA"
IDD62 = "3.2mA"
VDD = "1.8V"
VDD2 = "1.2V"

View File

@@ -0,0 +1,154 @@
# Copyright (c) 2012-2021 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2013 Amin Farmahini-Farahani
# Copyright (c) 2015 University of Kaiserslautern
# Copyright (c) 2015 The University of Bologna
# 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.
"""Interfaces for LPDDR3 memory devices
These memory "interfaces" contain the timing,energy,etc parameters for each
memory type and are usually based on datasheets for the memory devices.
You can use these interfaces in the MemCtrl object as the `dram` timing
interface.
"""
from m5.objects import DRAMInterface
class LPDDR3_1600_1x32(DRAMInterface):
"""
A single LPDDR3 x32 interface (one command/address bus), with default
timings based on a LPDDR3-1600 4 Gbit part (Micron EDF8132A1MC) in a 1x32
configuration.
"""
# No DLL for LPDDR3
dll = False
# size of device
device_size = "512MiB"
# 1x32 configuration, 1 device with a 32-bit interface
device_bus_width = 32
# LPDDR3 is a BL8 device
burst_length = 8
# Each device has a page (row buffer) size of 4KB
device_rowbuffer_size = "4KiB"
# 1x32 configuration, so 1 device
devices_per_rank = 1
# Technically the datasheet is a dual-rank package, but for
# comparison with the LPDDR2 config we stick to a single rank
ranks_per_channel = 1
# LPDDR3 has 8 banks in all configurations
banks_per_rank = 8
# 800 MHz
tCK = "1.25ns"
tRCD = "18ns"
# 12 CK read latency, 6 CK write latency @ 800 MHz, 1.25 ns cycle time
tCL = "15ns"
tRAS = "42ns"
tWR = "15ns"
# Greater of 4 CK or 7.5 ns, 4 CK @ 800 MHz = 5 ns
tRTP = "7.5ns"
# Pre-charge one bank 18 ns (all banks 21 ns)
tRP = "18ns"
# 8 beats across a x32 DDR interface translates to 4 clocks @ 800 MHz.
# Note this is a BL8 DDR device.
# Requests larger than 32 bytes are broken down into multiple requests
# in the controller
tBURST = "5ns"
# LPDDR3, 4 Gb
tRFC = "130ns"
tREFI = "3.9us"
# active powerdown and precharge powerdown exit time
tXP = "7.5ns"
# self refresh exit time
tXS = "140ns"
# Irrespective of speed grade, tWTR is 7.5 ns
tWTR = "7.5ns"
# Default same rank rd-to-wr bus turnaround to 2 CK, @800 MHz = 2.5 ns
tRTW = "2.5ns"
# Default different rank bus delay to 2 CK, @800 MHz = 2.5 ns
tCS = "2.5ns"
# Activate to activate irrespective of density and speed grade
tRRD = "10.0ns"
# Irrespective of size, tFAW is 50 ns
tXAW = "50ns"
activation_limit = 4
# Current values from datasheet
IDD0 = "8mA"
IDD02 = "60mA"
IDD2N = "0.8mA"
IDD2N2 = "26mA"
IDD3N = "2mA"
IDD3N2 = "34mA"
IDD4W = "2mA"
IDD4W2 = "190mA"
IDD4R = "2mA"
IDD4R2 = "230mA"
IDD5 = "28mA"
IDD52 = "150mA"
IDD3P1 = "1.4mA"
IDD3P12 = "11mA"
IDD2P1 = "0.8mA"
IDD2P12 = "1.8mA"
IDD6 = "0.5mA"
IDD62 = "1.8mA"
VDD = "1.8V"
VDD2 = "1.2V"

View File

@@ -0,0 +1,358 @@
# Copyright (c) 2012-2021 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2013 Amin Farmahini-Farahani
# Copyright (c) 2015 University of Kaiserslautern
# Copyright (c) 2015 The University of Bologna
# 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.
"""Interfaces for LPDDR5 memory devices
These memory "interfaces" contain the timing,energy,etc parameters for each
memory type and are usually based on datasheets for the memory devices.
You can use these interfaces in the MemCtrl object as the `dram` timing
interface.
"""
from m5.objects import DRAMInterface
class LPDDR5_5500_1x16_BG_BL32(DRAMInterface):
"""
A single LPDDR5 x16 interface (one command/address bus)
for a single x16 channel with default timings based on
initial JEDEC specification
Starting with 5.5Gbps data rates and 8Gbit die
Configuring for 16-bank mode with bank-group architecture
burst of 32, which means bursts can be interleaved
"""
# Increase buffer size to account for more bank resources
read_buffer_size = 64
# Set page policy to better suit DMC Huxley
page_policy = "close_adaptive"
# 16-bit channel interface
device_bus_width = 16
# LPDDR5 is a BL16 or BL32 device
# With BG mode, BL16 and BL32 are supported
# Use BL32 for higher command bandwidth
burst_length = 32
# size of device in bytes
device_size = "1GiB"
# 2KiB page with BG mode
device_rowbuffer_size = "2KiB"
# Use a 1x16 configuration
devices_per_rank = 1
# Use a single rank
ranks_per_channel = 1
# LPDDR5 supports configurable bank options
# 8B : BL32, all frequencies
# 16B : BL32 or BL16, <=3.2Gbps
# 16B with Bank Group Arch (4B/BG): BL32 or BL16, >3.2Gbps
# Initial configuration will have 16 banks with Bank Group Arch
# to maximim resources and enable higher data rates
banks_per_rank = 16
bank_groups_per_rank = 4
# 5.5Gb/s DDR with 4:1 WCK:CK ratio for 687.5 MHz CK
tCK = "1.455ns"
# Greater of 2 CK or 18ns
tRCD = "18ns"
# Base RL is 16 CK @ 687.5 MHz = 23.28ns
tCL = "23.280ns"
# Greater of 2 CK or 18ns
tRP = "18ns"
# Greater of 3 CK or 42ns
tRAS = "42ns"
# Greater of 3 CK or 34ns
tWR = "34ns"
# active powerdown and precharge powerdown exit time
# Greater of 3 CK or 7ns
tXP = "7ns"
# self refresh exit time (tRFCab + 7.5ns)
tXS = "217.5ns"
# Greater of 2 CK or 7.5 ns minus 2 CK
tRTP = "4.59ns"
# With BG architecture, burst of 32 transferred in two 16-beat
# sub-bursts, with a 16-beat gap in between.
# Each 16-beat sub-burst is 8 WCK @2.75 GHz or 2 CK @ 687.5 MHz
# tBURST is the delay to transfer the Bstof32 = 6 CK @ 687.5 MHz
tBURST = "8.73ns"
# can interleave a Bstof32 from another bank group at tBURST_MIN
# 16-beats is 8 WCK @2.75 GHz or 2 CK @ 687.5 MHz
tBURST_MIN = "2.91ns"
# tBURST_MAX is the maximum burst delay for same bank group timing
# this is 8 CK @ 687.5 MHz
tBURST_MAX = "11.64ns"
# 8 CK @ 687.5 MHz
tCCD_L = "11.64ns"
# LPDDR5, 8 Gbit/channel for 280ns tRFCab
tRFC = "210ns"
tREFI = "3.9us"
# Greater of 4 CK or 6.25 ns
tWTR = "6.25ns"
# Greater of 4 CK or 12 ns
tWTR_L = "12ns"
# Required RD-to-WR timing is RL+ BL/n + tWCKDQ0/tCK - WL
# tWCKDQ0/tCK will be 1 CK for most cases
# For gem5 RL = WL and BL/n is already accounted for with tBURST
# Result is and additional 1 CK is required
tRTW = "1.455ns"
# Default different rank bus delay to 2 CK, @687.5 MHz = 2.91 ns
tCS = "2.91ns"
# 2 CK
tPPD = "2.91ns"
# Greater of 2 CK or 5 ns
tRRD = "5ns"
tRRD_L = "5ns"
# With Bank Group Arch mode tFAW is 20 ns
tXAW = "20ns"
activation_limit = 4
# at 5Gbps, 4:1 WCK to CK ratio required
# 2 data beats per WCK (DDR) -> 8 per CK
beats_per_clock = 8
# 2 cycles required to send activate command
# 2 command phases can be sent back-to-back or
# with a gap up to tAAD = 8 CK
two_cycle_activate = True
tAAD = "11.640ns"
data_clock_sync = True
class LPDDR5_5500_1x16_BG_BL16(LPDDR5_5500_1x16_BG_BL32):
"""
A single LPDDR5 x16 interface (one command/address bus)
for a single x16 channel with default timings based on
initial JEDEC specification
Starting with 5.5Gbps data rates and 8Gbit die
Configuring for 16-bank mode with bank-group architecture, burst of 16
"""
# LPDDR5 is a BL16 or BL32 device
# With BG mode, BL16 and BL32 are supported
# Use BL16 for smaller access granularity
burst_length = 16
# For Bstof16 with BG arch, 2 CK @ 687.5 MHz with 4:1 clock ratio
tBURST = "2.91ns"
tBURST_MIN = "2.91ns"
# For Bstof16 with BG arch, 4 CK @ 687.5 MHz with 4:1 clock ratio
tBURST_MAX = "5.82ns"
# 4 CK @ 687.5 MHz
tCCD_L = "5.82ns"
class LPDDR5_5500_1x16_8B_BL32(LPDDR5_5500_1x16_BG_BL32):
"""
A single LPDDR5 x16 interface (one command/address bus)
for a single x16 channel with default timings based on
initial JEDEC specification
Starting with 5.5Gbps data rates and 8Gbit die
Configuring for 8-bank mode, burst of 32
"""
# 4KiB page with 8B mode
device_rowbuffer_size = "4KiB"
# LPDDR5 supports configurable bank options
# 8B : BL32, all frequencies
# 16B : BL32 or BL16, <=3.2Gbps
# 16B with Bank Group Arch (4B/BG): BL32 or BL16, >3.2Gbps
# Select 8B
banks_per_rank = 8
bank_groups_per_rank = 0
# For Bstof32 with 8B mode, 4 CK @ 687.5 MHz with 4:1 clock ratio
tBURST = "5.82ns"
tBURST_MIN = "5.82ns"
tBURST_MAX = "5.82ns"
# Greater of 4 CK or 12 ns
tWTR = "12ns"
# Greater of 2 CK or 10 ns
tRRD = "10ns"
# With 8B mode tFAW is 40 ns
tXAW = "40ns"
activation_limit = 4
# Reset BG arch timing for 8B mode
tCCD_L = "0ns"
tRRD_L = "0ns"
tWTR_L = "0ns"
class LPDDR5_6400_1x16_BG_BL32(LPDDR5_5500_1x16_BG_BL32):
"""
A single LPDDR5 x16 interface (one command/address bus)
for a single x16 channel with default timings based on
initial JEDEC specification
6.4Gbps data rates and 8Gbit die
Configuring for 16-bank mode with bank-group architecture
burst of 32, which means bursts can be interleaved
"""
# 5.5Gb/s DDR with 4:1 WCK:CK ratio for 687.5 MHz CK
tCK = "1.25ns"
# Base RL is 17 CK @ 800 MHz = 21.25ns
tCL = "21.25ns"
# With BG architecture, burst of 32 transferred in two 16-beat
# sub-bursts, with a 16-beat gap in between.
# Each 16-beat sub-burst is 8 WCK @3.2 GHz or 2 CK @ 800 MHz
# tBURST is the delay to transfer the Bstof32 = 6 CK @ 800 MHz
tBURST = "7.5ns"
# can interleave a Bstof32 from another bank group at tBURST_MIN
# 16-beats is 8 WCK @2.3 GHz or 2 CK @ 800 MHz
tBURST_MIN = "2.5ns"
# tBURST_MAX is the maximum burst delay for same bank group timing
# this is 8 CK @ 800 MHz
tBURST_MAX = "10ns"
# 8 CK @ 800 MHz
tCCD_L = "10ns"
# Required RD-to-WR timing is RL+ BL/n + tWCKDQ0/tCK - WL
# tWCKDQ0/tCK will be 1 CK for most cases
# For gem5 RL = WL and BL/n is already accounted for with tBURST
# Result is and additional 1 CK is required
tRTW = "1.25ns"
# Default different rank bus delay to 2 CK, @687.5 MHz = 2.5 ns
tCS = "2.5ns"
# 2 CK
tPPD = "2.5ns"
# 2 command phases can be sent back-to-back or
# with a gap up to tAAD = 8 CK
tAAD = "10ns"
class LPDDR5_6400_1x16_BG_BL16(LPDDR5_6400_1x16_BG_BL32):
"""
A single LPDDR5 x16 interface (one command/address bus)
for a single x16 channel with default timings based on initial
JEDEC specifcation
6.4Gbps data rates and 8Gbit die
Configuring for 16-bank mode with bank-group architecture, burst of 16
"""
# LPDDR5 is a BL16 or BL32 device
# With BG mode, BL16 and BL32 are supported
# Use BL16 for smaller access granularity
burst_length = 16
# For Bstof16 with BG arch, 2 CK @ 800 MHz with 4:1 clock ratio
tBURST = "2.5ns"
tBURST_MIN = "2.5ns"
# For Bstof16 with BG arch, 4 CK @ 800 MHz with 4:1 clock ratio
tBURST_MAX = "5ns"
# 4 CK @ 800 MHz
tCCD_L = "5ns"
class LPDDR5_6400_1x16_8B_BL32(LPDDR5_6400_1x16_BG_BL32):
"""
A single LPDDR5 x16 interface (one command/address bus)
for a single x16 channel with default timings based on
initial JEDEC specification
6.4Gbps data rates and 8Gbit die
Configuring for 8-bank mode, burst of 32
"""
# 4KiB page with 8B mode
device_rowbuffer_size = "4KiB"
# LPDDR5 supports configurable bank options
# 8B : BL32, all frequencies
# 16B : BL32 or BL16, <=3.2Gbps
# 16B with Bank Group Arch (4B/BG): BL32 or BL16, >3.2Gbps
# Select 8B
banks_per_rank = 8
bank_groups_per_rank = 0
# For Bstof32 with 8B mode, 4 CK @ 800 MHz with 4:1 clock ratio
tBURST = "5ns"
tBURST_MIN = "5ns"
tBURST_MAX = "5ns"
# Greater of 4 CK or 12 ns
tWTR = "12ns"
# Greater of 2 CK or 10 ns
tRRD = "10ns"
# With 8B mode tFAW is 40 ns
tXAW = "40ns"
activation_limit = 4
# Reset BG arch timing for 8B mode
tCCD_L = "0ns"
tRRD_L = "0ns"
tWTR_L = "0ns"

View File

@@ -0,0 +1,122 @@
# Copyright (c) 2012-2021 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2013 Amin Farmahini-Farahani
# Copyright (c) 2015 University of Kaiserslautern
# Copyright (c) 2015 The University of Bologna
# 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.
"""Interfaces for WideIO memory devices
These memory "interfaces" contain the timing,energy,etc parameters for each
memory type and are usually based on datasheets for the memory devices.
You can use these interfaces in the MemCtrl object as the `dram` timing
interface.
"""
from m5.objects import DRAMInterface
class WideIO_200_1x128(DRAMInterface):
"""
A single WideIO x128 interface (one command and address bus), with
default timings based on an estimated WIO-200 8 Gbit part.
"""
# No DLL for WideIO
dll = False
# size of device
device_size = "1024MiB"
# 1x128 configuration, 1 device with a 128-bit interface
device_bus_width = 128
# This is a BL4 device
burst_length = 4
# Each device has a page (row buffer) size of 4KB
# (this depends on the memory density)
device_rowbuffer_size = "4KiB"
# 1x128 configuration, so 1 device
devices_per_rank = 1
# Use one rank for a one-high die stack
ranks_per_channel = 1
# WideIO has 4 banks in all configurations
banks_per_rank = 4
# 200 MHz
tCK = "5ns"
# WIO-200
tRCD = "18ns"
tCL = "18ns"
tRP = "18ns"
tRAS = "42ns"
tWR = "15ns"
# Read to precharge is same as the burst
tRTP = "20ns"
# 4 beats across an x128 SDR interface translates to 4 clocks @ 200 MHz.
# Note this is a BL4 SDR device.
tBURST = "20ns"
# WIO 8 Gb
tRFC = "210ns"
# WIO 8 Gb, <=85C, half for >85C
tREFI = "3.9us"
# Greater of 2 CK or 15 ns, 2 CK @ 200 MHz = 10 ns
tWTR = "15ns"
# Default same rank rd-to-wr bus turnaround to 2 CK, @200 MHz = 10 ns
tRTW = "10ns"
# Default different rank bus delay to 2 CK, @200 MHz = 10 ns
tCS = "10ns"
# Activate to activate irrespective of density and speed grade
tRRD = "10.0ns"
# Two instead of four activation window
tXAW = "50ns"
activation_limit = 2
# The WideIO specification does not provide current information

View File

@@ -0,0 +1,157 @@
import m5
import os
import configparser
from m5.objects import DRAMsim3, AddrRange, Port, MemCtrl
from ..utils.override import overrides
from ..boards.abstract_board import AbstractBoard
from .abstract_memory_system import AbstractMemorySystem
from typing import Optional, Tuple, Sequence, List
def config_ds3(mem_type: str, num_chnls: int) -> Tuple[str, str]:
"""
This function creates a config file that will be used to create a memory
controller of type DRAMSim3. It stores the config file in /tmp/ directory.
:param mem_type: The name for the type of the memory to be configured.
:param num_chnls: The number of channels to configure for the memory
:returns: A tuple containing the output file and the output directory.
"""
config = configparser.ConfigParser()
# TODO: We need a better solution to this. This hard-coding is not
# an acceptable solution.
dramsim_3_dir = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
os.pardir,
os.pardir,
os.pardir,
"ext",
"DRAMsim3",
)
dramsim_3_mem_configs = os.path.join(dramsim_3_dir, "configs")
input_file = os.path.join(dramsim_3_mem_configs, mem_type + ".ini")
# Run checks to ensure the `ext/DRAMsim3` directory is present, contains
# the configs directory, and the configuration file we require.
if not os.path.isdir(dramsim_3_dir):
raise Exception(
"The `ext/DRAMsim3` directory cannot be found.\n"
"Please navigate to `ext` and run:\n"
"git clone git@github.com:umd-memsys/DRAMsim3.git"
)
elif os.path.isdir(dramsim_3_mem_configs):
raise Exception(
"The `ext/DRAMsim3/configs` directory cannot be found."
)
elif os.path.isfile(input_file):
raise Exception(
"The configuration file '" + input_file + "' cannot " " be found."
)
output_file = "/tmp/" + mem_type + "_chnls" + str(num_chnls) + ".ini"
new_config = open(output_file, "w")
config.read(input_file)
config.set("system", "channels", str(num_chnls))
config.write(new_config)
new_config.close()
return output_file, m5.options.outdir
class DRAMSim3MemCtrl(DRAMsim3):
"""
A DRAMSim3 Memory Controller.
The class serves as a SimObject object wrapper, utiliszing the DRAMSim3
configuratons.
"""
def __init__(self, mem_name: str, num_chnls: int) -> None:
"""
:param mem_name: The name of the type of memory to be configured.
:param num_chnls: The number of channels.
"""
super(DRAMSim3MemCtrl, self).__init__()
ini_path, outdir = config_ds3(mem_name, num_chnls)
self.configFile = ini_path
self.filePath = outdir
class SingleChannel(AbstractMemorySystem):
"""
A Single Channel Memory system.
"""
def __init__(self, mem_type: str, size: Optional[str]):
"""
:param mem_name: The name of the type of memory to be configured.
:param num_chnls: The number of channels.
"""
super(SingleChannel, self).__init__()
self.mem_ctrl = DRAMSim3MemCtrl(mem_type, 1)
if size:
self.mem_ctrl.range = AddrRange(size)
else:
raise NotImplementedError(
"DRAMSim3 memory controller requires a size parameter."
)
@overrides(AbstractMemorySystem)
def incorporate_memory(self, board: AbstractBoard) -> None:
pass
@overrides(AbstractMemorySystem)
def get_mem_ports(self) -> Tuple[Sequence[AddrRange], Port]:
return [(self.mem_ctrl.range, self.mem_ctrl.port)]
@overrides(AbstractMemorySystem)
def get_memory_controllers(self) -> List[MemCtrl]:
return [self.mem_ctrl]
@overrides(AbstractMemorySystem)
def get_memory_ranges(self):
return [self.mem_ctrl.range]
def SingleChannelDDR3_1600(
size: Optional[str] = "2048MB",
) -> SingleChannel:
"""
A single channel DDR3_1600.
:param size: The size of the memory system. Default value of 2048MB.
"""
return SingleChannel("DDR3_8Gb_x8_1600", size)
def SingleChannelDDR4_2400(size: Optional[str] = "1024MB") -> SingleChannel:
"""
A single channel DDR3_2400.
:param size: The size of the memory system. Default value of 1024MB.
"""
return SingleChannel("DDR4_4Gb_x8_2400", size)
def SingleChannelLPDDR3_1600(size: Optional[str] = "256MB") -> SingleChannel:
"""
A single channel LPDDR3_1600.
:param size: The size of the memory system. Default value of 256MB.
"""
return SingleChannel("LPDDR3_8Gb_x32_1600", size)
def SingleChannelHBM(size: Optional[str] = "64MB") -> SingleChannel:
"""
A single channel HBM.
:param size: The size of the memory system. Default value of 64MB.
"""
return SingleChannel("HBM1_4Gb_x128", size)

View File

@@ -0,0 +1,125 @@
# Copyright (c) 2021 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.
"""Single channel "generic" DDR memory controllers
"""
from ..boards.abstract_board import AbstractBoard
from .abstract_memory_system import AbstractMemorySystem
from ..utils.override import overrides
from m5.objects import AddrRange, DRAMInterface, MemCtrl, Port
from typing import List, Sequence, Tuple, Type, Optional
class SingleChannelMemory(AbstractMemorySystem):
"""A simple implementation of a single channel memory system
This class can take a DRAM Interface as a parameter to model many different
DDR memory systems.
"""
def __init__(
self,
dram_interface_class: Type[DRAMInterface],
size: Optional[str] = None,
):
"""
:param dram_interface_class: The DRAM interface type to create with
this memory controller
:param size: Optionally specify the size of the DRAM controller's
address space. By default, it starts at 0 and ends at the size of
the DRAM device specified
"""
super().__init__()
self._dram = dram_interface_class()
if size:
self._dram.range = size
else:
self._dram.range = AddrRange(self.get_size(self._dram))
self.mem_ctrl = MemCtrl(dram=self._dram)
def get_size(self, dram: DRAMInterface) -> int:
return (
dram.device_size.value
* dram.devices_per_rank.value
* dram.ranks_per_channel.value
)
@overrides(AbstractMemorySystem)
def incorporate_memory(self, board: AbstractBoard) -> None:
pass
@overrides(AbstractMemorySystem)
def get_mem_ports(self) -> Tuple[Sequence[AddrRange], Port]:
return [(self._dram.range, self.mem_ctrl.port)]
@overrides(AbstractMemorySystem)
def get_memory_controllers(self) -> List[MemCtrl]:
return [self.mem_ctrl]
@overrides(AbstractMemorySystem)
def get_memory_ranges(self):
return [self._dram.range]
from .dram_interfaces.ddr3 import DDR3_1600_8x8, DDR3_2133_8x8
from .dram_interfaces.ddr4 import DDR4_2400_8x8
from .dram_interfaces.lpddr3 import LPDDR3_1600_1x32
from .dram_interfaces.hbm import HBM_1000_4H_1x128
# Enumerate all of the different DDR memory systems we support
def SingleChannelDDR3_1600(size: Optional[str] = None) -> AbstractMemorySystem:
"""
A single channel memory system using a single DDR3_1600_8x8 based DIMM
"""
return SingleChannelMemory(DDR3_1600_8x8, size)
def SingleChannelDDR3_2133(size: Optional[str] = None) -> AbstractMemorySystem:
"""
A single channel memory system using a single DDR3_2133_8x8 based DIMM
"""
return SingleChannelMemory(DDR3_2133_8x8, size)
def SingleChannelDDR4_2400(size: Optional[str] = None) -> AbstractMemorySystem:
"""
A single channel memory system using a single DDR4_2400_8x8 based DIMM
"""
return SingleChannelMemory(DDR4_2400_8x8, size)
def SingleChannelLPDDR3_1600(
size: Optional[str] = None,
) -> AbstractMemorySystem:
return SingleChannelMemory(LPDDR3_1600_1x32, size)
def SingleChannelHBM(size: Optional[str] = None) -> AbstractMemorySystem:
return SingleChannelMemory(HBM_1000_4H_1x128, size)

View File

@@ -0,0 +1,86 @@
# Copyright (c) 2021 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 abc import ABCMeta, abstractmethod
from .cpu_types import CPUTypes
from m5.objects import Port, SubSystem
class AbstractCore(SubSystem):
__metaclass__ = ABCMeta
def __init__(self, cpu_type: CPUTypes):
super(AbstractCore, self).__init__()
self._cpu_type = cpu_type
def get_type(self) -> CPUTypes:
return self._cpu_type
@abstractmethod
def connect_icache(self, port: Port) -> None:
"""
This function should connect the response port from the instruction
cache to the right request port on the core.
:param port: The response port from the icache to connect to.
"""
raise NotImplementedError
@abstractmethod
def connect_dcache(self, port: Port) -> None:
"""
This function should connect the response port from the data cache to
the right request port on the core.
:param port: The response port from the icache to connect to.
"""
raise NotImplementedError
@abstractmethod
def connect_walker_ports(self, port1: Port, port2: Port) -> None:
"""
Connect the response port from itb and dtb to their respective request
ports in the core.
:param port1: The response port from itb walker to connect to.
:param port2: The response port from dtb walker to connect to.
"""
raise NotImplementedError
@abstractmethod
def set_workload(self, process: "Process") -> None:
raise NotImplementedError
@abstractmethod
def set_switched_out(self, value: bool) -> None:
raise NotImplementedError
@abstractmethod
def connect_interrupt(
self, interrupt_requestor: Port, interrupt_responce: Port
) -> None:
raise NotImplementedError

View File

@@ -0,0 +1,91 @@
# Copyright (c) 2021 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, PyTrafficGen
from ..utils.override import overrides
from .cpu_types import CPUTypes
from .abstract_core import AbstractCore
class AbstractGeneratorCore(AbstractCore):
"""The abstract generator core
Generator cores are cores that can replace the processing cores to allow
for testing computer systems in gem5. The abstract class
AbstractGeneratorCore defines the external interface that every generator
core must implement. Certain generator cores might need to extend this
interface to fit their requirements.
"""
def __init__(self):
"""
Create an AbstractCore with the CPUType of Timing. Also, setup a
dummy generator object to connect to icache
"""
# TODO: Remove the CPU Type parameter. This not needed.
# Jira issue here: https://gem5.atlassian.net/browse/GEM5-1031
super(AbstractGeneratorCore, self).__init__(CPUTypes.TIMING)
self.dummy_generator = PyTrafficGen()
@overrides(AbstractCore)
def connect_icache(self, port: Port) -> None:
"""
Generator cores only have one request port which we will connect to
the data cache not the icache. Just connect the icache to the dummy
generator here.
"""
self.dummy_generator.port = port
@overrides(AbstractCore)
def connect_walker_ports(self, port1: Port, port2: Port) -> None:
"""
Since generator cores are not used in full system mode, no need to
connect them to walker ports. Just pass here.
"""
pass
@overrides(AbstractCore)
def set_workload(self, process: "Process") -> None:
"""
Generator cores do not need any workload assigned to them, as they
generate their own synthetic workload (synthetic traffic). Just pass
here.
:param process: The process to execute during simulation.
"""
pass
@overrides(AbstractCore)
def connect_interrupt(
self, interrupt_requestor: Port, interrupt_responce: Port
) -> None:
"""
Since generator cores are not used in full system mode, no need to
connect them to walker ports. Just pass here.
"""
pass

View File

@@ -0,0 +1,54 @@
# Copyright (c) 2021 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 abc import ABCMeta, abstractmethod
from components_library.processors.abstract_core import AbstractCore
from m5.objects import SubSystem
from ..boards.abstract_board import AbstractBoard
from typing import List
class AbstractProcessor(SubSystem):
__metaclass__ = ABCMeta
def __init__(self, cores: List[AbstractCore]) -> None:
super(AbstractProcessor, self).__init__()
assert len(cores) > 0
self.cores = cores
def get_num_cores(self) -> int:
return len(self.cores)
def get_cores(self) -> List[AbstractCore]:
return self.cores
@abstractmethod
def incorporate_processor(self, board: AbstractBoard) -> None:
raise NotImplementedError

View File

@@ -0,0 +1,137 @@
# Copyright (c) 2021 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 ..utils.override import overrides
from ..boards.mem_mode import MemMode
from .complex_generator_core import ComplexGeneratorCore
from .abstract_processor import AbstractProcessor
from ..boards.abstract_board import AbstractBoard
class ComplexGenerator(AbstractProcessor):
def __init__(self, num_cores: int = 1) -> None:
super(ComplexGenerator, self).__init__(
cores=[ComplexGeneratorCore() for i in range(num_cores)]
)
"""The complex generator
This class defines an external interface to create a list of complex
generator cores that could replace the processing cores in a board.
:param num_cores: The number of complex generator cores to create.
"""
@overrides(AbstractProcessor)
def incorporate_processor(self, board: AbstractBoard) -> None:
board.set_mem_mode(MemMode.TIMING)
def add_linear(
self,
duration: str = "1ms",
rate: str = "100GB/s",
block_size: int = 64,
min_addr: int = 0,
max_addr: int = 32768,
rd_perc: int = 100,
data_limit: int = 0,
) -> None:
"""
This function will add a linear traffic to all the cores in the
generator with the params specified.
:param duration: The number of ticks for the generator core to generate
traffic.
:param rate: The rate at which the synthetic data is read/written.
:param block_size: The number of bytes to be read/written with each
request.
:param min_addr: The lower bound of the address range the generator
will read/write from/to.
:param max_addr: The upper bound of the address range the generator
will read/write from/to.
:param rd_perc: The percentage of read requests among all the generated
requests. The write percentage would be equal to 100 - rd_perc.
:param data_limit: The amount of data in bytes to read/write by the
generator before stopping generation.
"""
for core in self.cores:
core.add_linear(
duration,
rate,
block_size,
min_addr,
max_addr,
rd_perc,
data_limit,
)
def add_random(
self,
duration: str = "1ms",
rate: str = "100GB/s",
block_size: int = 64,
min_addr: int = 0,
max_addr: int = 32768,
rd_perc: int = 100,
data_limit: int = 0,
) -> None:
"""
This function will add a random traffic to all the cores in the
generator with the params specified.
:param duration: The number of ticks for the generator core to generate
traffic.
:param rate: The rate at which the synthetic data is read/written.
:param block_size: The number of bytes to be read/written with each
request.
:param min_addr: The lower bound of the address range the generator
will read/write from/to.
:param max_addr: The upper bound of the address range the generator
will read/write from/to.
:param rd_perc: The percentage of read requests among all the generated
requests. The write percentage would be equal to 100 - rd_perc.
:param data_limit: The amount of data in bytes to read/write by the
generator before stopping generation.
"""
for core in self.cores:
core.add_random(
duration,
rate,
block_size,
min_addr,
max_addr,
rd_perc,
data_limit,
)
def start_traffic(self) -> None:
"""
This function will start the traffic at the top of the traffic list. It
will also pop the first element so that the generator will start a
new traffic everytime this is called.
"""
for core in self.cores:
core.start_traffic()

View File

@@ -0,0 +1,332 @@
# Copyright (c) 2021 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.ticks import fromSeconds
from m5.util.convert import toLatency, toMemoryBandwidth
from m5.objects import PyTrafficGen, Port
from .abstract_core import AbstractCore
from .abstract_generator_core import AbstractGeneratorCore
from ..utils.override import overrides
from enum import Enum
class TrafficModes(Enum):
"""The traffic mode class
This class is an enum to store traffic mode in a more meaningful way
"""
linear = 0
random = 1
class ComplexTrafficParams:
def __init__(
self,
mode: TrafficModes,
duration: str,
rate: str,
block_size: int,
min_addr: int,
max_addr: int,
rd_perc: int,
data_limit: int,
):
"""The complex traffic params class
This class is a container for parameters to create either a linear or
random traffic. The complex generator core stores a list of complex
traffic params for resolution after m5.instantiate is called.
"""
self._mode = mode
self._duration = duration
self._rate = rate
self._block_size = block_size
self._min_addr = min_addr
self._max_addr = max_addr
self._rd_perc = rd_perc
self._data_limit = data_limit
class ComplexGeneratorCore(AbstractGeneratorCore):
def __init__(self):
"""The complex generator core interface.
This class defines the interface for a generator core that will create
a series of different types of traffic. This core uses PyTrafficGen to
create and inject the synthetic traffic. This generator could be used
to create more complex traffics that consist of linear and random
traffic in different phases.
"""
super(ComplexGeneratorCore, self).__init__()
self.generator = PyTrafficGen()
self._traffic_params = []
self._traffic = []
self._traffic_set = False
@overrides(AbstractCore)
def connect_dcache(self, port: Port) -> None:
self.generator.port = port
def add_linear(
self,
duration: str,
rate: str,
block_size: int,
min_addr: int,
max_addr: int,
rd_perc: int,
data_limit: int,
) -> None:
"""
This function will add the params for a linear traffic to the list of
traffic params in this generator core. These params will be later
resolved by the start_traffic call. This core uses a PyTrafficGen to
create the traffic based on the specified params below.
:param duration: The number of ticks for the generator core to generate
traffic.
:param rate: The rate at which the synthetic data is read/written.
:param block_size: The number of bytes to be read/written with each
request.
:param min_addr: The lower bound of the address range the generator
will read/write from/to.
:param max_addr: The upper bound of the address range the generator
will read/write from/to.
:param rd_perc: The percentage of read requests among all the generated
requests. The write percentage would be equal to 100 - rd_perc.
:param data_limit: The amount of data in bytes to read/write by the
generator before stopping generation.
"""
param = ComplexTrafficParams(
TrafficModes.linear,
duration,
rate,
block_size,
min_addr,
max_addr,
rd_perc,
data_limit,
)
self._traffic_params = self._traffic_params + [param]
self._traffic_set = False
def add_random(
self,
duration: str,
rate: str,
block_size: int,
min_addr: int,
max_addr: int,
rd_perc: int,
data_limit: int,
) -> None:
"""
This function will add the params for a random traffic to the list of
traffic params in this generator core. These params will be later
resolved by the start_traffic call. This core uses a PyTrafficGen to
create the traffic based on the specified params below.
:param duration: The number of ticks for the generator core to generate
traffic.
:param rate: The rate at which the synthetic data is read/written.
:param block_size: The number of bytes to be read/written with each
request.
:param min_addr: The lower bound of the address range the generator
will read/write from/to.
:param max_addr: The upper bound of the address range the generator
will read/write from/to.
:param rd_perc: The percentage of read requests among all the generated
requests. The write percentage would be equal to 100 - rd_perc.
:param data_limit: The amount of data in bytes to read/write by the
generator before stopping generation.
"""
param = ComplexTrafficParams(
TrafficModes.random,
duration,
rate,
block_size,
min_addr,
max_addr,
rd_perc,
data_limit,
)
self._traffic_params = self._traffic_params + [param]
self._traffic_set = False
def start_traffic(self) -> None:
"""
This function first checks if there are any pending traffics that
require creation, if so it will create the pending traffics based on
traffic_params list and adds them to the traffic list, then it starts
generating the traffic at the top of the traffic list. It also pops the
first element in the list so that every time this function is called a
new traffic is generated, each instance of a call to this function
should happen before each instance of the call to m5.simulate(). All
the instances of calls to this function should happen after
m5.instantiate()
"""
if not self._traffic_set:
self._set_traffic()
if self._traffic:
self.generator.start(self._traffic.pop(0))
else:
print("No phases left to generate!")
def _set_traffic(self) -> None:
"""
This function will pop params from traffic params list and create their
respective traffic and adds the traffic to the core's traffic list.
"""
while self._traffic_params:
param = self._traffic_params.pop(0)
mode = param._mode
duration = param._duration
rate = param._rate
block_size = param._block_size
min_addr = param._min_addr
max_addr = param._max_addr
rd_perc = param._rd_perc
data_limit = param._data_limit
if mode == TrafficModes.linear:
traffic = self._create_linear_traffic(
duration,
rate,
block_size,
min_addr,
max_addr,
rd_perc,
data_limit,
)
self._traffic = self._traffic + [traffic]
if mode == TrafficModes.random:
traffic = self._create_random_traffic(
duration,
rate,
block_size,
min_addr,
max_addr,
rd_perc,
data_limit,
)
self._traffic = self._traffic + [traffic]
self._traffic_set = True
def _create_linear_traffic(
self,
duration: str,
rate: str,
block_size: int,
min_addr: int,
max_addr: int,
rd_perc: int,
data_limit: int,
) -> None:
"""
This function yields (creates) a linear traffic based on the input
params. Then it will yield (create) an exit traffic (exit traffic is
used to exit the simulation).
:param duration: The number of ticks for the generator core to generate
traffic.
:param rate: The rate at which the synthetic data is read/written.
:param block_size: The number of bytes to be read/written with each
request.
:param min_addr: The lower bound of the address range the generator
will read/write from/to.
:param max_addr: The upper bound of the address range the generator
will read/write from/to.
:param rd_perc: The percentage of read requests among all the generated
requests. The write percentage would be equal to 100 - rd_perc.
:param data_limit: The amount of data in bytes to read/write by the
generator before stopping generation.
"""
duration = fromSeconds(toLatency(duration))
rate = toMemoryBandwidth(rate)
period = fromSeconds(block_size / rate)
min_period = period
max_period = period
yield self.generator.createLinear(
duration,
min_addr,
max_addr,
block_size,
min_period,
max_period,
rd_perc,
data_limit,
)
yield self.generator.createExit(0)
def _create_random_traffic(
self,
duration: str,
rate: str,
block_size: int,
min_addr: int,
max_addr: int,
rd_perc: int,
data_limit: int,
) -> None:
"""
This function yields (creates) a random traffic based on the input
params. Then it will yield (create) an exit traffic (exit traffic is
used to exit the simulation).
:param duration: The number of ticks for the generator core to generate
traffic.
:param rate: The rate at which the synthetic data is read/written.
:param block_size: The number of bytes to be read/written with each
request.
:param min_addr: The lower bound of the address range the generator
will read/write from/to.
:param max_addr: The upper bound of the address range the generator
will read/write from/to.
:param rd_perc: The percentage of read requests among all the generated
requests. The write percentage would be equal to 100 - rd_perc.
:param data_limit: The amount of data in bytes to read/write by the
generator before stopping generation.
"""
duration = fromSeconds(toLatency(duration))
rate = toMemoryBandwidth(rate)
period = fromSeconds(block_size / rate)
min_period = period
max_period = period
yield self.generator.createRandom(
duration,
min_addr,
max_addr,
block_size,
min_period,
max_period,
rd_perc,
data_limit,
)
yield self.generator.createExit(0)

View File

@@ -0,0 +1,34 @@
# Copyright (c) 2021 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 enum import Enum
class CPUTypes(Enum):
ATOMIC = 1
KVM = 2
O3 = 3
TIMING = 4

View File

@@ -0,0 +1,119 @@
# Copyright (c) 2021 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 ..utils.override import overrides
from ..boards.mem_mode import MemMode
from .linear_generator_core import LinearGeneratorCore
from .abstract_processor import AbstractProcessor
from ..boards.abstract_board import AbstractBoard
from typing import List
class LinearGenerator(AbstractProcessor):
def __init__(
self,
num_cores: int = 1,
duration: str = "1ms",
rate: str = "100GB/s",
block_size: int = 64,
min_addr: int = 0,
max_addr: int = 32768,
rd_perc: int = 100,
data_limit: int = 0,
) -> None:
super(LinearGenerator, self).__init__(
cores=self._create_cores(
num_cores=num_cores,
duration=duration,
rate=rate,
block_size=block_size,
min_addr=min_addr,
max_addr=max_addr,
rd_perc=rd_perc,
data_limit=data_limit,
)
)
"""The linear generator
This class defines an external interface to create a list of linear
generator cores that could replace the processing cores in a board.
:param num_cores: The number of linear generator cores to create.
:param duration: The number of ticks for the generator to generate
traffic.
:param rate: The rate at which the synthetic data is read/written.
:param block_size: The number of bytes to be read/written with each
request.
:param min_addr: The lower bound of the address range the generator
will read/write from/to.
:param max_addr: The upper bound of the address range the generator
will read/write from/to.
:param rd_perc: The percentage of read requests among all the generated
requests. The write percentage would be equal to 100 - rd_perc.
:param data_limit: The amount of data in bytes to read/write by the
generator before stopping generation.
"""
def _create_cores(
self,
num_cores,
duration,
rate,
block_size,
min_addr,
max_addr,
rd_perc,
data_limit,
) -> List[LinearGeneratorCore]:
"""
The helper function to create the cores for the generator, it will use
the same inputs as the constructor function.
"""
return [
LinearGeneratorCore(
duration=duration,
rate=rate,
block_size=block_size,
min_addr=min_addr,
max_addr=max_addr,
rd_perc=rd_perc,
data_limit=data_limit,
)
for i in range(num_cores)
]
@overrides(AbstractProcessor)
def incorporate_processor(self, board: AbstractBoard) -> None:
board.set_mem_mode(MemMode.TIMING)
def start_traffic(self) -> None:
"""
This function will start the assigned traffic to this generator.
"""
for core in self.cores:
core.start_traffic()

View File

@@ -0,0 +1,121 @@
# Copyright (c) 2021 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.ticks import fromSeconds
from m5.util.convert import toLatency, toMemoryBandwidth
from m5.objects import PyTrafficGen, Port, BaseTrafficGen
from .abstract_core import AbstractCore
from .abstract_generator_core import AbstractGeneratorCore
from ..utils.override import overrides
from typing import Iterator
class LinearGeneratorCore(AbstractGeneratorCore):
def __init__(
self,
duration: str,
rate: str,
block_size: int,
min_addr: int,
max_addr: int,
rd_perc: int,
data_limit: int,
) -> None:
super(LinearGeneratorCore, self).__init__()
""" The linear generator core interface.
This class defines the interface for a generator core that will create
a linear (stream) traffic specific to the parameters below. This core
uses PyTrafficGen to create and inject the synthetic traffic.
:param duration: The number of ticks for the generator core to generate
traffic.
:param rate: The rate at which the synthetic data is read/written.
:param block_size: The number of bytes to be read/written with each
request.
:param min_addr: The lower bound of the address range the generator
will read/write from/to.
:param max_addr: The upper bound of the address range the generator
will read/write from/to.
:param rd_perc: The percentage of read requests among all the generated
requests. The write percentage would be equal to 100 - rd_perc.
:param data_limit: The amount of data in bytes to read/write by the
generator before stopping generation.
"""
self.generator = PyTrafficGen()
self._duration = duration
self._rate = rate
self._block_size = block_size
self._min_addr = min_addr
self._max_addr = max_addr
self._rd_perc = rd_perc
self._data_limit = data_limit
@overrides(AbstractCore)
def connect_dcache(self, port: Port) -> None:
self.generator.port = port
def _set_traffic(self) -> None:
"""
This private function will set the traffic to be generated.
"""
self._traffic = self._create_traffic()
def _create_traffic(self) -> Iterator[BaseTrafficGen]:
"""
A python generator that yields (creates) a linear traffic with the
specified params in the generator core and then yields (creates) an
exit traffic.
:rtype: Iterator[BaseTrafficGen]
"""
duration = fromSeconds(toLatency(self._duration))
rate = toMemoryBandwidth(self._rate)
period = fromSeconds(self._block_size / rate)
min_period = period
max_period = period
yield self.generator.createLinear(
duration,
self._min_addr,
self._max_addr,
self._block_size,
min_period,
max_period,
self._rd_perc,
self._data_limit,
)
yield self.generator.createExit(0)
def start_traffic(self) -> None:
"""
A call to this function will start generating the traffic, this call
should happen before m5.simulate() and after m5.instantiate()
"""
self._set_traffic()
self.generator.start(self._traffic)

View File

@@ -0,0 +1,119 @@
# Copyright (c) 2021 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 ..utils.override import overrides
from ..boards.mem_mode import MemMode
from .random_generator_core import RandomGeneratorCore
from .abstract_processor import AbstractProcessor
from ..boards.abstract_board import AbstractBoard
from typing import List
class RandomGenerator(AbstractProcessor):
def __init__(
self,
num_cores: int = 1,
duration: str = "1ms",
rate: str = "100GB/s",
block_size: int = 64,
min_addr: int = 0,
max_addr: int = 32768,
rd_perc: int = 100,
data_limit: int = 0,
) -> None:
super(RandomGenerator, self).__init__(
cores=self._create_cores(
num_cores=num_cores,
duration=duration,
rate=rate,
block_size=block_size,
min_addr=min_addr,
max_addr=max_addr,
rd_perc=rd_perc,
data_limit=data_limit,
)
)
"""The random generator
This class defines an external interface to create a list of random
generator cores that could replace the processing cores in a board.
:param num_cores: The number of linear generator cores to create.
:param duration: The number of ticks for the generator to generate
traffic.
:param rate: The rate at which the synthetic data is read/written.
:param block_size: The number of bytes to be read/written with each
request.
:param min_addr: The lower bound of the address range the generator
will read/write from/to.
:param max_addr: The upper bound of the address range the generator
will read/write from/to.
:param rd_perc: The percentage of read requests among all the generated
requests. The write percentage would be equal to 100 - rd_perc.
:param data_limit: The amount of data in bytes to read/write by the
generator before stopping generation.
"""
def _create_cores(
self,
num_cores,
duration,
rate,
block_size,
min_addr,
max_addr,
rd_perc,
data_limit,
) -> List[RandomGeneratorCore]:
"""
The helper function to create the cores for the generator, it will use
the same inputs as the constructor function.
"""
return [
RandomGeneratorCore(
duration=duration,
rate=rate,
block_size=block_size,
min_addr=min_addr,
max_addr=max_addr,
rd_perc=rd_perc,
data_limit=data_limit,
)
for i in range(num_cores)
]
@overrides(AbstractProcessor)
def incorporate_processor(self, board: AbstractBoard) -> None:
board.set_mem_mode(MemMode.TIMING)
def start_traffic(self) -> None:
"""
This function will start the assigned traffic to this generator.
"""
for core in self.cores:
core.start_traffic()

View File

@@ -0,0 +1,121 @@
# Copyright (c) 2021 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.ticks import fromSeconds
from m5.util.convert import toLatency, toMemoryBandwidth
from m5.objects import PyTrafficGen, Port, BaseTrafficGen
from .abstract_core import AbstractCore
from .abstract_generator_core import AbstractGeneratorCore
from ..utils.override import overrides
from typing import Iterator
class RandomGeneratorCore(AbstractGeneratorCore):
def __init__(
self,
duration: str,
rate: str,
block_size: int,
min_addr: int,
max_addr: int,
rd_perc: int,
data_limit: int,
) -> None:
super(RandomGeneratorCore, self).__init__()
""" The random generator core interface.
This class defines the interface for a generator core that will create
a random traffic specific to the parameters below. This core uses
PyTrafficGen to create and inject the synthetic traffic.
:param duration: The number of ticks for the generator core to generate
traffic.
:param rate: The rate at which the synthetic data is read/written.
:param block_size: The number of bytes to be read/written with each
request.
:param min_addr: The lower bound of the address range the generator
will read/write from/to.
:param max_addr: The upper bound of the address range the generator
will read/write from/to.
:param rd_perc: The percentage of read requests among all the generated
requests. The write percentage would be equal to 100 - rd_perc.
:param data_limit: The amount of data in bytes to read/write by the
generator before stopping generation.
"""
self.generator = PyTrafficGen()
self._duration = duration
self._rate = rate
self._block_size = block_size
self._min_addr = min_addr
self._max_addr = max_addr
self._rd_perc = rd_perc
self._data_limit = data_limit
@overrides(AbstractCore)
def connect_dcache(self, port: Port) -> None:
self.generator.port = port
def _set_traffic(self) -> None:
"""
This private function will set the traffic to be generated.
"""
self._traffic = self._create_traffic()
def _create_traffic(self) -> Iterator[BaseTrafficGen]:
"""
A python generator that yields (creates) a random traffic with the
specified params in the generator core and then yields (creates) an
exit traffic.
:rtype: Iterator[BaseTrafficGen]
"""
duration = fromSeconds(toLatency(self._duration))
rate = toMemoryBandwidth(self._rate)
period = fromSeconds(self._block_size / rate)
min_period = period
max_period = period
yield self.generator.createRandom(
duration,
self._min_addr,
self._max_addr,
self._block_size,
min_period,
max_period,
self._rd_perc,
self._data_limit,
)
yield self.generator.createExit(0)
def start_traffic(self) -> None:
"""
A call to this function will start generating the traffic, this call
should happen before m5.simulate() and after m5.instantiate().
"""
self._set_traffic()
self.generator.start(self._traffic)

View File

@@ -0,0 +1,97 @@
# Copyright (c) 2021 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 components_library.runtime import get_runtime_isa
from components_library.processors.abstract_core import AbstractCore
from .cpu_types import CPUTypes
from ..isas import ISA
from ..utils.override import overrides
from m5.objects import (
Port,
AtomicSimpleCPU,
DerivO3CPU,
TimingSimpleCPU,
X86KvmCPU,
BaseCPU,
Process,
)
class SimpleCore(AbstractCore):
def __init__(self, cpu_type: CPUTypes, core_id: int):
super(SimpleCore, self).__init__(cpu_type=cpu_type)
if cpu_type == CPUTypes.ATOMIC:
self.core = AtomicSimpleCPU(cpu_id=core_id)
elif cpu_type == CPUTypes.O3:
self.core = DerivO3CPU(cpu_id=core_id)
elif cpu_type == CPUTypes.TIMING:
self.core = TimingSimpleCPU(cpu_id=core_id)
elif cpu_type == CPUTypes.KVM:
self.core = X86KvmCPU(cpu_id=core_id)
else:
raise NotImplementedError
self.core.createThreads()
def get_simobject(self) -> BaseCPU:
return self.core
@overrides(AbstractCore)
def connect_icache(self, port: Port) -> None:
self.core.icache_port = port
@overrides(AbstractCore)
def connect_dcache(self, port: Port) -> None:
self.core.dcache_port = port
@overrides(AbstractCore)
def connect_walker_ports(self, port1: Port, port2: Port) -> None:
self.core.mmu.connectWalkerPorts(port1, port2)
@overrides(AbstractCore)
def set_workload(self, process: Process) -> None:
self.core.workload = process
@overrides(AbstractCore)
def set_switched_out(self, value: bool) -> None:
self.core.switched_out = value
@overrides(AbstractCore)
def connect_interrupt(
self, interrupt_requestor: Port, interrupt_responce: Port
) -> None:
# TODO: This model assumes that we will only create an interrupt
# controller as we require it. Not sure how true this is in all cases.
self.core.createInterruptController()
if get_runtime_isa() == ISA.X86:
self.core.interrupts[0].pio = interrupt_requestor
self.core.interrupts[0].int_requestor = interrupt_responce
self.core.interrupts[0].int_responder = interrupt_requestor

View File

@@ -0,0 +1,92 @@
# Copyright (c) 2021 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 components_library.utils.override import overrides
from components_library.boards.mem_mode import MemMode
from components_library.processors.simple_core import SimpleCore
from m5.objects import KvmVM
from m5.util import warn
from .abstract_processor import AbstractProcessor
from .cpu_types import CPUTypes
from ..boards.abstract_board import AbstractBoard
from ..coherence_protocol import is_ruby
from ..runtime import get_runtime_coherence_protocol
from typing import List
class SimpleProcessor(AbstractProcessor):
"""
A SimpeProcessor contains a number of cores of a a single CPUType.
"""
def __init__(self, cpu_type: CPUTypes, num_cores: int) -> None:
super(SimpleProcessor, self).__init__(
cores=self._create_cores(
cpu_type=cpu_type,
num_cores=num_cores,
)
)
self._cpu_type = cpu_type
if self._cpu_type == CPUTypes.KVM:
self.kvm_vm = KvmVM()
# To get the KVM CPUs to run on different host CPUs
# Specify a different event queue for each CPU
for i, core in enumerate(self.cores):
for obj in core.get_simobject().descendants():
obj.eventq_index = 0
core.get_simobject().eventq_index = i + 1
def _create_cores(self, cpu_type: CPUTypes, num_cores: int):
return [
SimpleCore(cpu_type=cpu_type, core_id=i) for i in range(num_cores)
]
@overrides(AbstractProcessor)
def incorporate_processor(self, board: AbstractBoard) -> None:
if self._cpu_type == CPUTypes.KVM:
board.kvm_vm = self.kvm_vm
# Set the memory mode.
if self._cpu_type == CPUTypes.TIMING or self._cpu_type == CPUTypes.O3:
board.set_mem_mode(MemMode.TIMING)
elif self._cpu_type == CPUTypes.KVM:
board.set_mem_mode(MemMode.ATOMIC_NONCACHING)
elif self._cpu_type == CPUTypes.ATOMIC:
if is_ruby(get_runtime_coherence_protocol()):
warn(
"Using an atomic core with Ruby will result in "
"'atomic_noncaching' memory mode. This will skip caching "
"completely."
)
else:
board.set_mem_mode(MemMode.ATOMIC)
else:
raise NotImplementedError

View File

@@ -0,0 +1,105 @@
# Copyright (c) 2021 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 components_library.boards.mem_mode import MemMode
from components_library.boards.abstract_board import AbstractBoard
from components_library.processors.simple_core import SimpleCore
from components_library.processors.cpu_types import CPUTypes
from .switchable_processor import SwitchableProcessor
from ..utils.override import *
from m5.objects import KvmVM
class SimpleSwitchableProcessor(SwitchableProcessor):
"""
A Simplified implementation of SwitchableProcessor where there is one
processor at the start of the simuation, and another that can be switched
to via the "switch" function later in the simulation. This is good for
fast/detailed CPU setups.
"""
def __init__(
self,
starting_core_type: CPUTypes,
switch_core_type: CPUTypes,
num_cores: int,
) -> None:
if num_cores <= 0:
raise AssertionError("Number of cores must be a positive integer!")
self._start_key = "start"
self._switch_key = "switch"
self._current_is_start = True
self._prepare_kvm = CPUTypes.KVM in (
starting_core_type,
switch_core_type,
)
if starting_core_type in (CPUTypes.TIMING, CPUTypes.O3):
self._mem_mode = MemMode.TIMING
elif starting_core_type == CPUTypes.KVM:
self._mem_mode = MemMode.ATOMIC_NONCACHING
elif starting_core_type == CPUTypes.ATOMIC:
self._mem_mode = MemMode.ATOMIC
else:
raise NotImplementedError
switchable_cores = {
self._start_key: [
SimpleCore(cpu_type=starting_core_type, core_id=i)
for i in range(num_cores)
],
self._switch_key: [
SimpleCore(cpu_type=switch_core_type, core_id=i)
for i in range(num_cores)
],
}
super(SimpleSwitchableProcessor, self).__init__(
switchable_cores=switchable_cores,
starting_cores=self._start_key,
)
@overrides(SwitchableProcessor)
def incorporate_processor(self, board: AbstractBoard) -> None:
super().incorporate_processor(board=board)
if self._prepare_kvm:
board.kvm_vm = KvmVM()
board.set_mem_mode(self._mem_mode)
def switch(self):
"""Switches to the "switched out" cores."""
if self._current_is_start:
self.switch_to_processor(self._switch_key)
else:
self.switch_to_processor(self._start_key)
self._current_is_start = not self._current_is_start

View File

@@ -0,0 +1,128 @@
# Copyright (c) 2021 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 components_library.processors.simple_core import SimpleCore
from components_library.processors.abstract_core import AbstractCore
import m5
from typing import Dict, Any, List
from .abstract_processor import AbstractProcessor
from ..boards.abstract_board import AbstractBoard
from ..utils.override import *
class SwitchableProcessor(AbstractProcessor):
"""
This class can be used to setup a switchable processor/processors on a
system.
Though this class can be used directly, it is best inherited from. See
"SimpleSwitchableCPU" for an example of this.
"""
def __init__(
self,
switchable_cores: Dict[Any, List[SimpleCore]],
starting_cores: Any,
) -> None:
if starting_cores not in switchable_cores.keys():
raise AssertionError(
f"Key {starting_cores} cannot be found in the "
"switchable_processors dictionary."
)
self._current_cores = switchable_cores[starting_cores]
self._switchable_cores = switchable_cores
all_cores = []
for core_list in self._switchable_cores.values():
for core in core_list:
core.set_switched_out(core not in self._current_cores)
all_cores.append(core)
super(SwitchableProcessor, self).__init__(cores=all_cores)
@overrides(AbstractProcessor)
def incorporate_processor(self, board: AbstractBoard) -> None:
# This is a bit of a hack. The `m5.switchCpus` function, used in the
# "switch_to_processor" function, requires the System simobject as an
# argument. We therefore need to store the board when incorporating the
# procsesor
self._board = board
@overrides(AbstractProcessor)
def get_num_cores(self) -> int:
# Note: This is a special case where the total number of cores in the
# design is not the number of cores, due to some being switched out.
return len(self._current_cores)
@overrides(AbstractProcessor)
def get_cores(self) -> List[AbstractCore]:
return self._current_cores
def switch_to_processor(self, switchable_core_key: Any):
# Run various checks.
if not hasattr(self, "_board"):
raise AssertionError("The processor has not been incorporated.")
if switchable_core_key not in self._switchable_cores.keys():
raise AssertionError(
f"Key {switchable_core_key} is not a key in the"
" switchable_processor dictionary."
)
# Select the correct processor to switch to.
to_switch = self._switchable_cores[switchable_core_key]
# Run more checks.
if to_switch == self._current_cores:
raise AssertionError(
"Cannot swap current cores with the current cores"
)
if len(to_switch) != len(self._current_cores):
raise AssertionError(
"The number of cores to swap in is not the same as the number "
"already swapped in. This is not allowed."
)
current_core_simobj = [
core.get_simobject() for core in self._current_cores
]
to_switch_simobj = [core.get_simobject() for core in to_switch]
# Switch the CPUs
m5.switchCpus(
self._board,
list(zip(current_core_simobj, to_switch_simobj)),
)
# Ensure the current processor is updated.
self._current_cores = to_switch

View File

@@ -0,0 +1,87 @@
# Copyright (c) 2021 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 file contains functions to extract gem5 runtime information.
"""
from m5.defines import buildEnv
from .isas import ISA
from .coherence_protocol import CoherenceProtocol
def get_runtime_isa() -> ISA:
"""Gets the target ISA.
This can be inferred at runtime.
:returns: The target ISA.
"""
isa_map = {
"sparc": ISA.SPARC,
"mips": ISA.MIPS,
"null": ISA.NULL,
"arm": ISA.ARM,
"x86": ISA.X86,
"power": ISA.POWER,
"riscv": ISA.RISCV,
}
isa_str = str(buildEnv["TARGET_ISA"]).lower()
if isa_str not in isa_map.keys():
raise NotImplementedError(
"ISA '" + buildEnv["TARGET_ISA"] + "' not recognized."
)
return isa_map[isa_str]
def get_runtime_coherence_protocol() -> CoherenceProtocol:
"""Gets the cache coherence protocol.
This can be inferred at runtime.
:returns: The cache coherence protocol.
"""
protocol_map = {
"mi_example": CoherenceProtocol.MI_EXAMPLE,
"moesi_hammer": CoherenceProtocol.ARM_MOESI_HAMMER,
"garnet_standalone": CoherenceProtocol.GARNET_STANDALONE,
"moesi_cmp_token": CoherenceProtocol.MOESI_CMP_TOKEN,
"mesi_two_level": CoherenceProtocol.MESI_TWO_LEVEL,
"moesi_amd_base": CoherenceProtocol.MOESI_AMD_BASE,
"mesi_three_level_htm": CoherenceProtocol.MESI_THREE_LEVEL_HTM,
"mesi_three_level": CoherenceProtocol.MESI_THREE_LEVEL,
"gpu_viper": CoherenceProtocol.GPU_VIPER,
"chi": CoherenceProtocol.CHI,
}
protocol_str = str(buildEnv["PROTOCOL"]).lower()
if protocol_str not in protocol_map.keys():
raise NotImplementedError(
"Protocol '" + buildEnv["PROTOCOL"] + "' not recognized."
)
return protocol_map[protocol_str]

View File

@@ -0,0 +1,55 @@
# Copyright (c) 2021 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.
def overrides(interface_class):
"""
Function override annotation.
Corollary to @abc.abstractmethod where the override is not of an
abstractmethod.
Modified from answer https://stackoverflow.com/a/8313042/471376
"""
def confirm_override(method):
if method.__name__ not in dir(interface_class):
raise NotImplementedError(
f"function {method.__name__} is an @override, but that"
f" function is not implemented in base class {interface_class}"
)
def func():
pass
attr = getattr(interface_class, method.__name__)
if type(attr) is not type(func):
raise NotImplementedError(
f"function {method.__name__} is an @overide, but that is"
f" implemented as type {type(attr)} in base class"
f" {interface_class}, expected implemented type {type(func)}."
)
return method
return confirm_override

View File

@@ -0,0 +1,155 @@
# Copyright (c) 2021 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 example runs a simple boot exit test.
Characteristics
---------------
* Runs exclusively on the X86 ISA with the MESI_TWO_LEVEL coherence protocol.
"""
import m5
from m5.objects import Root
import sys
import os
# This is a lame hack to get the imports working correctly.
# TODO: This needs fixed.
sys.path.append(
os.path.join(
os.path.dirname(os.path.abspath(__file__)),
os.pardir,
os.pardir,
os.pardir,
)
)
from components_library.runtime import (
get_runtime_coherence_protocol,
get_runtime_isa,
)
from components_library.boards.x86_board import X86Board
from components_library.memory.ddr3_1600_8x8 import DDR3_1600_8x8
from components_library.processors.simple_processor import SimpleProcessor
from components_library.processors.cpu_types import CPUTypes
from components_library.isas import ISA
from components_library.coherence_protocol import CoherenceProtocol
import os
import subprocess
import gzip
import shutil
# Run a check to ensure the right version of gem5 is being used.
if (
get_runtime_coherence_protocol() != CoherenceProtocol.MESI_TWO_LEVEL
or get_runtime_isa() != ISA.X86
):
raise EnvironmentError(
"The boot-exit-disk_run.py should be run with X86_MESI_Two_Level."
)
from components_library.cachehierarchies.\
ruby.mesi_two_level_cache_hierarchy import (
MESITwoLevelCacheHierarchy,
)
# Setup the cache heirarchy to be MESI_Two_Level.
cache_hierarchy = MESITwoLevelCacheHierarchy(
l1d_size="32kB",
l1d_assoc=8,
l1i_size="32kB",
l1i_assoc=8,
l2_size="256kB",
l2_assoc=16,
num_l2_banks=1,
)
# Setup the system memory.
# Warning: This must be kept at 3GB for now. X86Motherboard does not support
# anything else right now!
memory = DDR3_1600_8x8(size="3GB")
# Setup a single core Timing Processor.
processor = SimpleProcessor(cpu_type=CPUTypes.TIMING, num_cores=1)
# Setup the motherboard.
motherboard = X86Board(
clk_freq="3GHz",
processor=processor,
memory=memory,
cache_hierarchy=cache_hierarchy,
exit_on_work_items=True,
)
motherboard.connect_things()
# Download the resources as necessary.
thispath = os.path.dirname(os.path.realpath(__file__))
kernel_url = (
"http://dist.gem5.org/dist/v21-0/kernels/x86/static/vmlinux-5.4.49"
)
kernel_path = os.path.join(thispath, "vmlinux-5.4.49")
if not os.path.exists(kernel_path):
subprocess.run(["wget", "-P", thispath, kernel_url])
boot_img_url = (
"http://dist.gem5.org/dist/v21-0/images/x86/ubuntu-18-04/boot-exit.img.gz"
)
boot_img_path_gz = os.path.join(thispath, "boot-exit.img.gz")
boot_img_path = os.path.join(thispath, "boot-exit.img")
if not os.path.exists(boot_img_path):
subprocess.run(["wget", "-P", thispath, boot_img_url])
with gzip.open(boot_img_path_gz, "rb") as f:
with open(boot_img_path, "wb") as o:
shutil.copyfileobj(f, o)
# Set the Full System workload.
motherboard.set_workload(
kernel=kernel_path, disk_image=boot_img_path, command="m5 exit \n"
)
# Begin running of the simulation. This will exit once the Linux system boot
# is complete.
print("Running with ISA: " + get_runtime_isa().name)
print("Running with protocol: " + get_runtime_coherence_protocol().name)
print()
root = Root(full_system=True, system=motherboard)
m5.instantiate()
print("Beginning simulation!")
exit_event = m5.simulate()
print(
"Exiting @ tick {} because {}.".format(m5.curTick(), exit_event.getCause())
)

View File

@@ -0,0 +1,243 @@
# Copyright (c) 2021 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.
"""
A run script for running the parsec benchmark suite in gem5.
On the first run of this script it will download the disk image for parsec
and Linux kernel version 5.4.
The disk image is about 8 GB so this can take 10-15 minutes on a fast
connection.
"""
import m5
import m5.ticks
from m5.objects import Root
import sys
import os
# This is a lame hack to get the imports working correctly.
# TODO: This needs fixed.
sys.path.append(
os.path.join(
os.path.dirname(os.path.abspath(__file__)),
os.pardir,
os.pardir,
os.pardir,
)
)
from components_library.boards.x86_board import X86Board
from components_library.cachehierarchies.classic.\
private_l1_private_l2_cache_hierarchy import (
PrivateL1PrivateL2CacheHierarchy,
)
from components_library.memory.ddr3_1600_8x8 import DDR3_1600_8x8
from components_library.processors.simple_switchable_processor import (
SimpleSwitchableProcessor,
)
from components_library.processors.cpu_types import CPUTypes
from components_library.runtime import (
get_runtime_isa,
get_runtime_coherence_protocol,
)
import subprocess
import gzip
import time
import shutil
import time
# Setup the cachie hierarchy.
cache_hierarchy = PrivateL1PrivateL2CacheHierarchy(
l1d_size="32kB",
l1i_size="32kB",
l2_size="256kB",
)
# Setup the memory system.
# Warning!!! This must be kept at 3GB for now. X86Motherboard does not support
# anything else right now!
memory = DDR3_1600_8x8(size="3GB")
# The processor. In this case we use the special "SwitchableProcessor" which
# allows us to switch between different SimpleProcessors.
#
# WARNING: This is known buggy. While it works starting with Atomic and
# switching to Timing. The reverse is not true. KVM is not yet functional.
processor = SimpleSwitchableProcessor(
starting_core_type=CPUTypes.ATOMIC,
switch_core_type=CPUTypes.TIMING,
num_cores=4,
)
# Setup the board.
motherboard = X86Board(
clk_freq="3GHz",
processor=processor,
memory=memory,
cache_hierarchy=cache_hierarchy,
exit_on_work_items=True,
)
motherboard.connect_things()
# Download the linux kernel and parsec disk image needed to run the
# simuluation.
thispath = os.path.dirname(os.path.realpath(__file__))
kernel_url = (
"http://dist.gem5.org/dist/v21-0/kernels/x86/static/vmlinux-5.4.49"
)
kernel_path = os.path.join(thispath, "vmlinux-5.4.49")
if not os.path.exists(kernel_path):
subprocess.run(["wget", "-P", thispath, kernel_url])
parsec_img_url = (
"http://dist.gem5.org/dist/v21-0/images/x86/ubuntu-18-04/parsec.img.gz"
)
parsec_img_path_gz = os.path.join(thispath, "parsec.img.gz")
parsec_img_path = os.path.join(thispath, "parsec.img")
if not os.path.exists(parsec_img_path):
subprocess.run(["wget", "-P", thispath, parsec_img_url])
with gzip.open(parsec_img_path_gz, "rb") as f:
with open(parsec_img_path, "wb") as o:
shutil.copyfileobj(f, o)
# The command to run. In this case the blackscholes app with the simsmall
# workload.
command = "cd /home/gem5/parsec-benchmark\n"
command += "source env.sh\n"
command += "parsecmgmt -a run -p blackscholes "
command += "-c gcc-hooks -i simsmall -n {}\n".format(processor.get_num_cores())
command += "sleep 5 \n"
command += "m5 exit \n"
motherboard.set_workload(
kernel=kernel_path, disk_image=parsec_img_path, command=command
)
print("Running with ISA: " + get_runtime_isa().name)
print("Running with protocol: " + get_runtime_coherence_protocol().name)
print()
root = Root(full_system=True, system=motherboard)
m5.instantiate()
globalStart = time.time()
print("Beginning the simulation")
start_tick = m5.curTick()
end_tick = m5.curTick()
m5.stats.reset()
exit_event = m5.simulate()
if exit_event.getCause() == "workbegin":
print("Done booting Linux")
# Reached the start of ROI.
# The start of the ROI is marked by an m5_work_begin() call.
print("Resetting stats at the start of ROI!")
m5.stats.reset()
start_tick = m5.curTick()
# Switch to the Timing Processor.
motherboard.get_processor().switch()
else:
print("Unexpected termination of simulation!")
print()
m5.stats.dump()
end_tick = m5.curTick()
m5.stats.reset()
print("Performance statistics:")
print("Simulated time: {}s".format((end_tick - start_tick) / 1e12))
print("Ran a total of", m5.curTick() / 1e12, "simulated seconds")
print(
"Total wallclock time: {}s, {} min".format(
(time.time() - globalStart, (time.time() - globalStart) / 60)
)
)
exit()
# Simulate the ROI.
exit_event = m5.simulate()
if exit_event.getCause() == "workend":
# Reached the end of ROI
# The end of the ROI is marked by an m5_work_end() call.
print("Dumping stats at the end of the ROI!")
m5.stats.dump()
end_tick = m5.curTick()
m5.stats.reset()
# Switch back to the Atomic Processor
motherboard.get_processor().switch()
else:
print("Unexpected termination of simulation!")
print()
m5.stats.dump()
end_tick = m5.curTick()
m5.stats.reset()
print("Performance statistics:")
print("Simulated time: {}s".format((end_tick - start_tick) / 1e12))
print("Ran a total of", m5.curTick() / 1e12, "simulated seconds")
print(
"Total wallclock time: {}s, {} min".format(
time.time() - globalStart, (time.time() - globalStart) / 60
)
)
exit()
# Simulate the remaning part of the benchmark
# Run the rest of the workload until m5 exit
exit_event = m5.simulate()
print("Done running the simulation")
print()
print("Performance statistics:")
print("Simulated time in ROI: {}s".format((end_tick - start_tick) / 1e12))
print("Ran a total of {} simulated seconds".format(m5.curTick() / 1e12))
print(
"Total wallclock time: {}s, {} min".format(
time.time() - globalStart, (time.time() - globalStart) / 60
)
)

View File

@@ -0,0 +1,99 @@
# Copyright (c) 2021 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.
"""
A run script for a very simple Syscall-Execution running a hello world program.
The system has no cache heirarchy.
This is as simple a setup as gem5 will allow.
"""
import m5
from m5.objects import Root
import os
import sys
# This is a lame hack to get the imports working correctly.
# TODO: This needs fixed.
sys.path.append(
os.path.join(
os.path.dirname(os.path.abspath(__file__)),
os.pardir,
os.pardir,
os.pardir,
)
)
from components_library.boards.simple_board import SimpleBoard
from components_library.cachehierarchies.classic.no_cache import NoCache
from components_library.memory.single_channel import SingleChannelDDR3_1600
from components_library.processors.simple_processor import SimpleProcessor
from components_library.processors.cpu_types import CPUTypes
from components_library.runtime import (
get_runtime_coherence_protocol,
get_runtime_isa,
)
# Setup the system.
cache_hierarchy = NoCache()
memory = SingleChannelDDR3_1600()
processor = SimpleProcessor(cpu_type=CPUTypes.ATOMIC, num_cores=1)
motherboard = SimpleBoard(
clk_freq="3GHz",
processor=processor,
memory=memory,
cache_hierarchy=cache_hierarchy,
)
motherboard.connect_things()
# Set the workload
thispath = os.path.dirname(os.path.realpath(__file__))
binary = os.path.join(
thispath, "../../../tests/test-progs/hello/bin/x86/linux/hello"
)
motherboard.set_workload(binary)
# Run the simulation.
print("Running with ISA: {}.".format(get_runtime_isa().name))
print(
"Running with protocol: {}.".format(get_runtime_coherence_protocol().name)
)
print()
root = Root(full_system=False, system=motherboard)
m5.instantiate()
exit_event = m5.simulate()
print(
"Exiting @ tick {} because {}.".format(m5.curTick(), exit_event.getCause())
)

View File

@@ -0,0 +1,94 @@
# Copyright (c) 2021 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 creates a simple traffic generator.
The simulator starts with a linear traffic generator, and ends with a random
traffic generator.
"""
import m5
from m5.objects import Root
import sys
import os
# This is a lame hack to get the imports working correctly.
# TODO: This needs fixed.
sys.path.append(
os.path.join(
os.path.dirname(os.path.abspath(__file__)),
os.pardir,
os.pardir,
os.pardir,
)
)
from components_library.boards.test_board import TestBoard
from components_library.cachehierarchies.classic.no_cache import NoCache
from components_library.memory.single_channel import SingleChannelDDR3_1600
from components_library.processors.complex_generator import ComplexGenerator
# This setup does not require a cache heirarchy. We therefore use the `NoCache`
# setup.
cache_hierarchy = NoCache()
# We test a Single Channel DDR3_1600.
memory = SingleChannelDDR3_1600(size="512MiB")
cmxgen = ComplexGenerator(num_cores=1)
cmxgen.add_linear(rate="100GB/s")
cmxgen.add_random(block_size=32, rate="50MB/s")
# We use the Test Board. This is a special board to run traffic generation
# tasks
motherboard = TestBoard(
clk_freq="3GHz",
processor=cmxgen, # We pass the traffic generator as the processor.
memory=memory,
cache_hierarchy=cache_hierarchy,
)
motherboard.connect_things()
root = Root(full_system=False, system=motherboard)
m5.instantiate()
cmxgen.start_traffic()
print("Beginning simulation!")
exit_event = m5.simulate()
print(
"Exiting @ tick {} because {}.".format(m5.curTick(), exit_event.getCause())
)
cmxgen.start_traffic()
print("The Linear taffic has finished. Swiching to random traffic!")
exit_event = m5.simulate()
print(
"Exiting @ tick {} because {}.".format(m5.curTick(), exit_event.getCause())
)