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)