stdlib: Removing SingleChannelMemory
This change removes the code base for SingleChannelMemory and replaces it with MultiChannelMemory. muli_channel defines all the classes that were defined by single_channel. Basically any SingleChannelMemory could be thought of as a MultiChannelMemory with 1 channel. Change-Id: If96079d5f77be5a3ba26d2c2ddb98f5c60375cd8 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/53304 Reviewed-by: Bobby Bruce <bbruce@ucdavis.edu> Maintainer: Bobby Bruce <bbruce@ucdavis.edu> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -133,8 +133,9 @@ PySource('gem5.components.cachehierarchies.ruby.topologies',
|
||||
PySource('gem5.components.memory', 'gem5/components/memory/__init__.py')
|
||||
PySource('gem5.components.memory', 'gem5/components/memory/abstract_memory_system.py')
|
||||
PySource('gem5.components.memory', 'gem5/components/memory/dramsim_3.py')
|
||||
PySource('gem5.components.memory', 'gem5/components/memory/single_channel.py')
|
||||
PySource('gem5.components.memory', 'gem5/components/memory/simple.py')
|
||||
PySource('gem5.components.memory', 'gem5/components/memory/memory.py')
|
||||
PySource('gem5.components.memory', 'gem5/components/memory/single_channel.py')
|
||||
PySource('gem5.components.memory', 'gem5/components/memory/multi_channel.py')
|
||||
PySource('gem5.components.memory.dram_interfaces',
|
||||
'gem5/components/memory/dram_interfaces/__init__.py')
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# 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 .single_channel import SingleChannelDDR3_1600
|
||||
from .single_channel import SingleChannelDDR3_2133
|
||||
from .single_channel import SingleChannelDDR4_2400
|
||||
from .single_channel import SingleChannelHBM
|
||||
from .single_channel import SingleChannelLPDDR3_1600
|
||||
from .multi_channel import DualChannelDDR3_1600
|
||||
from .multi_channel import DualChannelDDR3_2133
|
||||
from .multi_channel import DualChannelDDR4_2400
|
||||
from .multi_channel import HBM2Stack
|
||||
from .multi_channel import DualChannelLPDDR3_1600
|
||||
|
||||
185
src/python/gem5/components/memory/memory.py
Normal file
185
src/python/gem5/components/memory/memory.py
Normal file
@@ -0,0 +1,185 @@
|
||||
# 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.
|
||||
|
||||
""" Channeled "generic" DDR memory controllers
|
||||
"""
|
||||
|
||||
from math import log
|
||||
from ...utils.override import overrides
|
||||
from m5.util.convert import toMemorySize
|
||||
from ..boards.abstract_board import AbstractBoard
|
||||
from .abstract_memory_system import AbstractMemorySystem
|
||||
from m5.objects import AddrRange, DRAMInterface, MemCtrl, Port
|
||||
from typing import Type, Sequence, Tuple, List, Optional, Union
|
||||
|
||||
|
||||
def _try_convert(val, cls):
|
||||
try:
|
||||
return cls(val)
|
||||
except:
|
||||
raise Exception(f"Could not convert {val} to {cls}")
|
||||
|
||||
def _isPow2(num):
|
||||
log_num = int(log(num, 2))
|
||||
if 2 ** log_num != num:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
class ChanneledMemory(AbstractMemorySystem):
|
||||
"""A class to implement multi-channel memory system
|
||||
|
||||
This class can take a DRAM Interface as a parameter to model a multi
|
||||
channel DDR DRAM memory system.
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
dram_interface_class: Type[DRAMInterface],
|
||||
num_channels: Union[int, str],
|
||||
interleaving_size: Union[int, str],
|
||||
size: Optional[str] = None,
|
||||
addr_mapping: Optional[str] = None,
|
||||
) -> None:
|
||||
"""
|
||||
:param dram_interface_class: The DRAM interface type to create with
|
||||
this memory controller
|
||||
:param num_channels: The number of channels that needs to be
|
||||
simulated
|
||||
: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
|
||||
:param addr_mapping: Defines the address mapping scheme to be used.
|
||||
If None, it is defaulted to addr_mapping from dram_interface_class.
|
||||
:param interleaving_size: Defines the interleaving size of the multi-
|
||||
channel memory system. By default, it is equivalent to the atom
|
||||
size, i.e., 64.
|
||||
"""
|
||||
num_channels = _try_convert(num_channels, int)
|
||||
interleaving_size = _try_convert(interleaving_size, int)
|
||||
|
||||
if size:
|
||||
size = _try_convert(size, str)
|
||||
|
||||
if addr_mapping:
|
||||
addr_mapping = _try_convert(addr_mapping, str)
|
||||
|
||||
super().__init__()
|
||||
self._dram_class = dram_interface_class
|
||||
self._num_channels = num_channels
|
||||
|
||||
if not _isPow2(interleaving_size):
|
||||
raise ValueError("Memory interleaving size should be a power of 2")
|
||||
self._intlv_size = interleaving_size
|
||||
|
||||
if addr_mapping:
|
||||
self._addr_mapping = addr_mapping
|
||||
else:
|
||||
self._addr_mapping = self._dram_class.addr_mapping.value
|
||||
|
||||
if size:
|
||||
self._size = toMemorySize(size)
|
||||
else:
|
||||
self._size = self._get_dram_size(num_channels, self._dram_class)
|
||||
|
||||
self._dram = [
|
||||
self._dram_class(addr_mapping=self._addr_mapping)
|
||||
for _ in range(num_channels)
|
||||
]
|
||||
self.mem_ctrl = [
|
||||
MemCtrl(dram=self._dram[i]) for i in range(num_channels)
|
||||
]
|
||||
|
||||
def _get_dram_size(self, num_channels: int, dram: DRAMInterface) -> int:
|
||||
return num_channels * (
|
||||
dram.device_size.value
|
||||
* dram.devices_per_rank.value
|
||||
* dram.ranks_per_channel.value
|
||||
)
|
||||
|
||||
def _interleave_addresses(self):
|
||||
if self._addr_mapping == "RoRaBaChCo":
|
||||
rowbuffer_size = (
|
||||
self._dram_class.device_rowbuffer_size.value
|
||||
* self._dram_class.devices_per_rank.value
|
||||
)
|
||||
intlv_low_bit = log(rowbuffer_size, 2)
|
||||
elif self._addr_mapping in ["RoRaBaCoCh", "RoCoRaBaCh"]:
|
||||
intlv_low_bit = log(self._intlv_size, 2)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Only these address mappings are supported: "
|
||||
"RoRaBaChCo, RoRaBaCoCh, RoCoRaBaCh"
|
||||
)
|
||||
|
||||
intlv_bits = log(self._num_channels, 2)
|
||||
for i, ctrl in enumerate(self.mem_ctrl):
|
||||
ctrl.dram.range = AddrRange(
|
||||
start=self._mem_range.start,
|
||||
size=self._mem_range.size(),
|
||||
intlvHighBit=intlv_low_bit + intlv_bits - 1,
|
||||
xorHighBit=0,
|
||||
intlvBits=intlv_bits,
|
||||
intlvMatch=i,
|
||||
)
|
||||
|
||||
@overrides(AbstractMemorySystem)
|
||||
def incorporate_memory(self, board: AbstractBoard) -> None:
|
||||
if self._intlv_size < int(board.get_cache_line_size()):
|
||||
raise ValueError(
|
||||
"Memory interleaving size can not be smaller than"
|
||||
" board's cache line size.\nBoard's cache line size: "
|
||||
f"{board.get_cache_line_size()}\n, This memory's interleaving "
|
||||
f"size: {self._intlv_size}"
|
||||
)
|
||||
|
||||
@overrides(AbstractMemorySystem)
|
||||
def get_mem_ports(self) -> Sequence[Tuple[AddrRange, Port]]:
|
||||
return [(ctrl.dram.range, ctrl.port) for ctrl in self.mem_ctrl]
|
||||
|
||||
@overrides(AbstractMemorySystem)
|
||||
def get_memory_controllers(self) -> List[MemCtrl]:
|
||||
return [ctrl for ctrl in self.mem_ctrl]
|
||||
|
||||
@overrides(AbstractMemorySystem)
|
||||
def get_size(self) -> int:
|
||||
return self._size
|
||||
|
||||
@overrides(AbstractMemorySystem)
|
||||
def set_memory_range(self, ranges: List[AddrRange]) -> None:
|
||||
"""Need to add support for non-contiguous non overlapping ranges in
|
||||
the future.
|
||||
"""
|
||||
if len(ranges) != 1 or ranges[0].size() != self._size:
|
||||
raise Exception(
|
||||
"Multi channel memory controller requires a single range "
|
||||
"which matches the memory's size.\n"
|
||||
f"The range size: {range[0].size()}\n"
|
||||
f"This memory's size: {self._size}"
|
||||
)
|
||||
self._mem_range = ranges[0]
|
||||
self._interleave_addresses()
|
||||
|
||||
|
||||
@@ -24,182 +24,15 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""Multi channel "generic" DDR memory controllers
|
||||
"""
|
||||
|
||||
from math import log
|
||||
from ...utils.override import overrides
|
||||
from m5.util.convert import toMemorySize
|
||||
from ..boards.abstract_board import AbstractBoard
|
||||
from .memory import ChanneledMemory
|
||||
from .abstract_memory_system import AbstractMemorySystem
|
||||
from m5.objects import AddrRange, DRAMInterface, MemCtrl, Port
|
||||
from typing import Type, Sequence, Tuple, List, Optional, Union
|
||||
|
||||
|
||||
def _try_convert(val, cls):
|
||||
try:
|
||||
return cls(val)
|
||||
except:
|
||||
raise Exception(f"Could not convert {val} to {cls}")
|
||||
|
||||
def _isPow2(num):
|
||||
log_num = int(log(num, 2))
|
||||
if 2 ** log_num != num:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
class MultiChannelMemory(AbstractMemorySystem):
|
||||
"""A class to implement multi-channel memory system
|
||||
|
||||
This class can take a DRAM Interface as a parameter to model a multi
|
||||
channel DDR DRAM memory system.
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
dram_interface_class: Type[DRAMInterface],
|
||||
num_channels: Union[int, str],
|
||||
interleaving_size: Union[int, str],
|
||||
size: Optional[str] = None,
|
||||
addr_mapping: Optional[str] = None,
|
||||
) -> None:
|
||||
"""
|
||||
:param dram_interface_class: The DRAM interface type to create with
|
||||
this memory controller
|
||||
:param num_channels: The number of channels that needs to be
|
||||
simulated
|
||||
: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
|
||||
:param addr_mapping: Defines the address mapping scheme to be used.
|
||||
If None, it is defaulted to addr_mapping from dram_interface_class.
|
||||
:param interleaving_size: Defines the interleaving size of the multi-
|
||||
channel memory system. By default, it is equivalent to the atom
|
||||
size, i.e., 64.
|
||||
"""
|
||||
num_channels = _try_convert(num_channels, int)
|
||||
interleaving_size = _try_convert(interleaving_size, int)
|
||||
|
||||
if size:
|
||||
size = _try_convert(size, str)
|
||||
|
||||
if addr_mapping:
|
||||
addr_mapping = _try_convert(addr_mapping, str)
|
||||
|
||||
super().__init__()
|
||||
self._dram_class = dram_interface_class
|
||||
self._num_channels = num_channels
|
||||
|
||||
if not _isPow2(interleaving_size):
|
||||
raise ValueError("Memory interleaving size should be a power of 2")
|
||||
self._intlv_size = interleaving_size
|
||||
|
||||
if addr_mapping:
|
||||
self._addr_mapping = addr_mapping
|
||||
else:
|
||||
self._addr_mapping = self._dram_class.addr_mapping.value
|
||||
|
||||
if size:
|
||||
self._size = toMemorySize(size)
|
||||
else:
|
||||
self._size = self._get_dram_size(num_channels, self._dram_class)
|
||||
|
||||
self._dram = [
|
||||
self._dram_class(addr_mapping=self._addr_mapping)
|
||||
for _ in range(num_channels)
|
||||
]
|
||||
self.mem_ctrl = [
|
||||
MemCtrl(dram=self._dram[i]) for i in range(num_channels)
|
||||
]
|
||||
|
||||
def _get_dram_size(self, num_channels: int, dram: DRAMInterface) -> int:
|
||||
return num_channels * (
|
||||
dram.device_size.value
|
||||
* dram.devices_per_rank.value
|
||||
* dram.ranks_per_channel.value
|
||||
)
|
||||
|
||||
def _interleave_addresses(self):
|
||||
if self._addr_mapping == "RoRaBaChCo":
|
||||
rowbuffer_size = (
|
||||
self._dram_class.device_rowbuffer_size.value
|
||||
* self._dram_class.devices_per_rank.value
|
||||
)
|
||||
intlv_low_bit = log(rowbuffer_size, 2)
|
||||
elif self._addr_mapping in ["RoRaBaCoCh", "RoCoRaBaCh"]:
|
||||
intlv_low_bit = log(self._intlv_size, 2)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Only these address mappings are supported: "
|
||||
"RoRaBaChCo, RoRaBaCoCh, RoCoRaBaCh"
|
||||
)
|
||||
|
||||
intlv_bits = log(self._num_channels, 2)
|
||||
for i, ctrl in enumerate(self.mem_ctrl):
|
||||
ctrl.dram.range = AddrRange(
|
||||
start=self._mem_range.start,
|
||||
size=self._mem_range.size(),
|
||||
intlvHighBit=intlv_low_bit + intlv_bits - 1,
|
||||
xorHighBit=0,
|
||||
intlvBits=intlv_bits,
|
||||
intlvMatch=i,
|
||||
)
|
||||
|
||||
@overrides(AbstractMemorySystem)
|
||||
def incorporate_memory(self, board: AbstractBoard) -> None:
|
||||
if self._intlv_size < int(board.get_cache_line_size()):
|
||||
raise ValueError(
|
||||
"Memory interleaving size can not be smaller than"
|
||||
" board's cache line size.\nBoard's cache line size: "
|
||||
f"{board.get_cache_line_size()}\n, This memory's interleaving "
|
||||
f"size: {self._intlv_size}"
|
||||
)
|
||||
|
||||
@overrides(AbstractMemorySystem)
|
||||
def get_mem_ports(self) -> Sequence[Tuple[AddrRange, Port]]:
|
||||
return [(ctrl.dram.range, ctrl.port) for ctrl in self.mem_ctrl]
|
||||
|
||||
@overrides(AbstractMemorySystem)
|
||||
def get_memory_controllers(self) -> List[MemCtrl]:
|
||||
return [ctrl for ctrl in self.mem_ctrl]
|
||||
|
||||
@overrides(AbstractMemorySystem)
|
||||
def get_size(self) -> int:
|
||||
return self._size
|
||||
|
||||
@overrides(AbstractMemorySystem)
|
||||
def set_memory_range(self, ranges: List[AddrRange]) -> None:
|
||||
"""Need to add support for non-contiguous non overlapping ranges in
|
||||
the future.
|
||||
"""
|
||||
if len(ranges) != 1 or ranges[0].size() != self._size:
|
||||
raise Exception(
|
||||
"Multi channel memory controller requires a single range "
|
||||
"which matches the memory's size.\n"
|
||||
f"The range size: {range[0].size()}\n"
|
||||
f"This memory's size: {self._size}"
|
||||
)
|
||||
self._mem_range = ranges[0]
|
||||
self._interleave_addresses()
|
||||
|
||||
|
||||
from typing import Optional
|
||||
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_1x64, HBM_1000_4H_1x128
|
||||
from .dram_interfaces.hbm import HBM_1000_4H_1x64
|
||||
|
||||
def SingleChannelDDR3_1600(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
"""
|
||||
A single channel memory system using DDR3_1600_8x8 based DIMM
|
||||
"""
|
||||
return MultiChannelMemory(
|
||||
DDR3_1600_8x8,
|
||||
1,
|
||||
64,
|
||||
size=size,
|
||||
)
|
||||
|
||||
def DualChannelDDR3_1600(
|
||||
size: Optional[str] = None,
|
||||
@@ -207,103 +40,55 @@ def DualChannelDDR3_1600(
|
||||
"""
|
||||
A dual channel memory system using DDR3_1600_8x8 based DIMM
|
||||
"""
|
||||
return MultiChannelMemory(
|
||||
return ChanneledMemory(
|
||||
DDR3_1600_8x8,
|
||||
2,
|
||||
64,
|
||||
size=size,
|
||||
)
|
||||
|
||||
def SingleChannelDDR3_2133(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
"""
|
||||
A single channel memory system using DDR3_2133_8x8 based DIMM
|
||||
"""
|
||||
return MultiChannelMemory(
|
||||
DDR3_2133_8x8,
|
||||
1,
|
||||
64,
|
||||
size=size,
|
||||
)
|
||||
|
||||
def DualChannelDDR3_2133(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
"""
|
||||
A dual channel memory system using DDR3_2133_8x8 based DIMM
|
||||
"""
|
||||
return MultiChannelMemory(
|
||||
return ChanneledMemory(
|
||||
DDR3_2133_8x8,
|
||||
2,
|
||||
64,
|
||||
size=size,
|
||||
)
|
||||
|
||||
def SingleChannelDDR4_2400(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
"""
|
||||
A single channel memory system using DDR4_2400_8x8 based DIMM
|
||||
"""
|
||||
return MultiChannelMemory(
|
||||
DDR4_2400_8x8,
|
||||
1,
|
||||
64,
|
||||
size=size,
|
||||
)
|
||||
|
||||
def DualChannelDDR4_2400(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
"""
|
||||
A dual channel memory system using DDR4_2400_8x8 based DIMM
|
||||
"""
|
||||
return MultiChannelMemory(
|
||||
return ChanneledMemory(
|
||||
DDR4_2400_8x8,
|
||||
2,
|
||||
64,
|
||||
size=size,
|
||||
)
|
||||
|
||||
def SingleChannelLPDDR3_1600(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
return MultiChannelMemory(
|
||||
LPDDR3_1600_1x32,
|
||||
1,
|
||||
64,
|
||||
size=size,
|
||||
)
|
||||
|
||||
def DualChannelLPDDR3_1600(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
return MultiChannelMemory(
|
||||
return ChanneledMemory(
|
||||
LPDDR3_1600_1x32,
|
||||
2,
|
||||
64,
|
||||
size=size,
|
||||
)
|
||||
|
||||
def SingleChannelHBM(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
if not size:
|
||||
size = "256MiB"
|
||||
return MultiChannelMemory(
|
||||
HBM_1000_4H_1x128,
|
||||
1,
|
||||
64,
|
||||
size=size
|
||||
)
|
||||
|
||||
def HBM2Stack(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
if not size:
|
||||
size = "4GiB"
|
||||
return MultiChannelMemory(
|
||||
return ChanneledMemory(
|
||||
HBM_1000_4H_1x64,
|
||||
16,
|
||||
64,
|
||||
|
||||
@@ -24,113 +24,74 @@
|
||||
# (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 .memory import ChanneledMemory
|
||||
from .abstract_memory_system import AbstractMemorySystem
|
||||
from ...utils.override import overrides
|
||||
|
||||
from m5.objects import AddrRange, DRAMInterface, MemCtrl, Port
|
||||
from m5.util.convert import toMemorySize
|
||||
from typing import Optional
|
||||
|
||||
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._size = toMemorySize(size)
|
||||
else:
|
||||
self._size = self._get_dram_size(self._dram)
|
||||
self.mem_ctrl = MemCtrl(dram=self._dram)
|
||||
|
||||
def _get_dram_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_size(self) -> int:
|
||||
return self._size
|
||||
|
||||
@overrides(AbstractMemorySystem)
|
||||
def set_memory_range(self, ranges: List[AddrRange]) -> None:
|
||||
if len(ranges) != 1 or ranges[0].size() != self._size:
|
||||
print(ranges[0].size())
|
||||
raise Exception(
|
||||
"Single channel memory controller requires a single range "
|
||||
"which matches the memory's size."
|
||||
)
|
||||
self.mem_ctrl.dram.range = ranges[0]
|
||||
|
||||
|
||||
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)
|
||||
from .dram_interfaces.lpddr3 import LPDDR3_1600_1x32
|
||||
from .dram_interfaces.ddr3 import DDR3_1600_8x8, DDR3_2133_8x8
|
||||
|
||||
|
||||
def SingleChannelDDR3_2133(size: Optional[str] = None) -> AbstractMemorySystem:
|
||||
def SingleChannelDDR3_1600(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
"""
|
||||
A single channel memory system using a single DDR3_2133_8x8 based DIMM
|
||||
A single channel memory system using DDR3_1600_8x8 based DIMM
|
||||
"""
|
||||
return SingleChannelMemory(DDR3_2133_8x8, size)
|
||||
return ChanneledMemory(
|
||||
DDR3_1600_8x8,
|
||||
1,
|
||||
64,
|
||||
size=size,
|
||||
)
|
||||
|
||||
|
||||
def SingleChannelDDR4_2400(size: Optional[str] = None) -> AbstractMemorySystem:
|
||||
def SingleChannelDDR3_2133(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
"""
|
||||
A single channel memory system using a single DDR4_2400_8x8 based DIMM
|
||||
A single channel memory system using DDR3_2133_8x8 based DIMM
|
||||
"""
|
||||
return SingleChannelMemory(DDR4_2400_8x8, size)
|
||||
return ChanneledMemory(
|
||||
DDR3_2133_8x8,
|
||||
1,
|
||||
64,
|
||||
size=size,
|
||||
)
|
||||
|
||||
def SingleChannelDDR4_2400(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
"""
|
||||
A single channel memory system using DDR4_2400_8x8 based DIMM
|
||||
"""
|
||||
return ChanneledMemory(
|
||||
DDR4_2400_8x8,
|
||||
1,
|
||||
64,
|
||||
size=size,
|
||||
)
|
||||
|
||||
def SingleChannelLPDDR3_1600(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
return SingleChannelMemory(LPDDR3_1600_1x32, size)
|
||||
return ChanneledMemory(
|
||||
LPDDR3_1600_1x32,
|
||||
1,
|
||||
64,
|
||||
size=size,
|
||||
)
|
||||
|
||||
|
||||
def SingleChannelHBM(size: Optional[str] = None) -> AbstractMemorySystem:
|
||||
return SingleChannelMemory(HBM_1000_4H_1x128, size)
|
||||
def SingleChannelHBM(
|
||||
size: Optional[str] = None,
|
||||
) -> AbstractMemorySystem:
|
||||
if not size:
|
||||
size = "256MiB"
|
||||
return ChanneledMemory(
|
||||
HBM_1000_4H_1x128,
|
||||
1,
|
||||
64,
|
||||
size=size
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user