| 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) |