This change updates the API in the component library for setting the size of memory. Now, you can set the size of the memory system as an argument to the memory object. Then, the board is responsible for figuring out what the overall memory ranges should be which it communicates back to the memory system. This should make multi-channel memories easier to implement and it fixes some confusion around things like the HiFive platform starting at 0x8000000. Change-Id: Ibef5aafbbb1177a992950cdc2bd2634dcfb81eec Signed-off-by: Jason Lowe-Power <jason@lowepower.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/49348 Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
167 lines
5.2 KiB
Python
167 lines
5.2 KiB
Python
import m5
|
|
import os
|
|
import configparser
|
|
|
|
from m5.objects import DRAMsim3, AddrRange, Port, MemCtrl
|
|
from m5.util.convert import toMemorySize
|
|
|
|
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)
|
|
self._size = toMemorySize(size)
|
|
if not size:
|
|
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_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:
|
|
raise Exception(
|
|
"Single channel DRAMSim memory controller requires a single "
|
|
"range which matches the memory's size."
|
|
)
|
|
self.mem_ctrl.range = ranges[0]
|
|
|
|
|
|
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)
|