Jason Lowe-Power has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/49348 )
Change subject: configs: Update component API for memory size
......................................................................
configs: Update component API for memory size
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 <[email protected]>
---
M components_library/boards/abstract_board.py
M components_library/boards/simple_board.py
M components_library/boards/test_board.py
M components_library/boards/x86_board.py
M components_library/memory/abstract_memory_system.py
M components_library/memory/dramsim_3.py
M components_library/memory/single_channel.py
7 files changed, 143 insertions(+), 26 deletions(-)
diff --git a/components_library/boards/abstract_board.py
b/components_library/boards/abstract_board.py
index 4bece04..3eae0e0 100644
--- a/components_library/boards/abstract_board.py
+++ b/components_library/boards/abstract_board.py
@@ -25,6 +25,7 @@
# 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
@@ -165,6 +166,22 @@
raise NotImplementedError
@abstractmethod
+ def setup_memory_ranges(self) -> None:
+ """
+ Set the memory ranges for this board.
+
+ This is called by `connect_things`. It can query the board's memory
+ to determine the size and the set the memory ranges on the memory
if
+ it needs to move the memory devices.
+
+ The simplest implementation just sets the board's memory range to
be
+ the size of memory and memory's memory range to be the same as the
+ board. Full system implementations will likely need something more
+ complicated.
+ """
+ raise NotImplementedError
+
+ @abstractmethod
def connect_things(self) -> None:
"""Connects all the components to the board.
diff --git a/components_library/boards/simple_board.py
b/components_library/boards/simple_board.py
index 7d67e08..fdba342 100644
--- a/components_library/boards/simple_board.py
+++ b/components_library/boards/simple_board.py
@@ -25,6 +25,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from m5.objects import (
+ AddrRange,
SrcClockDomain,
VoltageDomain,
Process,
@@ -74,8 +75,6 @@
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)
@@ -92,6 +91,9 @@
@overrides(AbstractBoard)
def connect_things(self) -> None:
+ # Before incorporating the memory, set up the memory ranges
+ self.setup_memory_ranges()
+
# Incorporate the cache hierarchy for the motherboard.
self.get_cache_hierarchy().incorporate_cache(self)
@@ -123,6 +125,15 @@
"Use `has_dma_ports()` to check this."
)
+ @overrides(AbstractBoard)
+ def setup_memory_ranges(self) -> None:
+ memory = self.get_memory()
+
+ # The simple board just has one memory range that is the size of
the
+ # memory.
+ self.mem_ranges = [AddrRange(memory.get_size())]
+ memory.set_memory_range(self.mem_ranges)
+
def set_workload(self, binary: str) -> None:
"""Set up the system to run a specific binary.
diff --git a/components_library/boards/test_board.py
b/components_library/boards/test_board.py
index 74bd91a..567a4ad 100644
--- a/components_library/boards/test_board.py
+++ b/components_library/boards/test_board.py
@@ -24,7 +24,14 @@
# (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 m5.objects import (
+ SrcClockDomain,
+ ClockDomain,
+ VoltageDomain,
+ Port,
+ IOXBar,
+ AddrRange,
+)
from .mem_mode import MemMode, mem_mode_to_string
from ..utils.override import overrides
@@ -61,12 +68,12 @@
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.set_memory_ranges()
+
self.get_cache_hierarchy().incorporate_cache(self)
self.get_processor().incorporate_processor(self)
@@ -101,3 +108,12 @@
@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 setup_memory_ranges(self) -> None:
+ memory = self.get_memory()
+
+ # The simple board just has one memory range that is the size of
the
+ # memory.
+ self.mem_ranges = [AddrRange(memory.get_size())]
+ memory.set_memory_range(self.mem_ranges)
diff --git a/components_library/boards/x86_board.py
b/components_library/boards/x86_board.py
index a2de653..11a223f 100644
--- a/components_library/boards/x86_board.py
+++ b/components_library/boards/x86_board.py
@@ -49,9 +49,10 @@
CowDiskImage,
RawDiskImage,
BaseXBar,
+ Port,
)
-from m5.params import Port
+from m5.util.convert import toMemorySize
from .simple_board import SimpleBoard
@@ -94,17 +95,17 @@
"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()
+ def _setup_io_devices(self):
+ """ Sets up the x86 IO devices.
+
+ Note: This is mostly copy-paste from prior X86 FS setups. Some of
it
+ may not be documented and there may be bugs.
+ """
+
# Constants similar to x86_traits.hh
IO_address_space_base = 0x8000000000000000
pci_config_address_space_base = 0xC000000000000000
@@ -267,7 +268,25 @@
self.workload.e820_table.entries = entries
def connect_things(self) -> None:
- super().connect_things()
+ # This board is a bit particular about the order that things are
+ # connected together.
+
+ # Before incorporating the memory or creating the I/O devices
figure
+ # out the memory ranges.
+ self.setup_memory_ranges()
+
+ # Set up all of the I/O before we incorporate anything else.
+ self._setup_io_devices()
+
+ # 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)
+
def set_workload(
self, kernel: str, disk_image: str, command: Optional[str] = None
@@ -340,3 +359,21 @@
@overrides(AbstractBoard)
def get_dma_ports(self) -> Sequence[Port]:
return [self.pc.south_bridge.ide.dma, self.iobus.mem_side_ports]
+
+ @overrides(AbstractBoard)
+ def setup_memory_ranges(self):
+ memory = self.get_memory()
+
+ if memory.get_size() > toMemorySize("3GB"):
+ raise Exception(
+ "X86Board currently only supports memory sizes up "
+ "to 3GB because of the I/O hole."
+ )
+ data_range = AddrRange(memory.get_size())
+ memory.set_memory_range([data_range])
+
+ # Add the address range for the IO
+ self.mem_ranges = [
+ data_range, # All data
+ AddrRange(0xC0000000, size=0x100000), # For I/0
+ ]
diff --git a/components_library/memory/abstract_memory_system.py
b/components_library/memory/abstract_memory_system.py
index f579f05..22a8c51 100644
--- a/components_library/memory/abstract_memory_system.py
+++ b/components_library/memory/abstract_memory_system.py
@@ -41,17 +41,33 @@
@abstractmethod
def incorporate_memory(self, board: AbstractBoard) -> None:
+ """This function completes all of the necessary steps to add this
+ memory system to the board."""
raise NotImplementedError
@abstractmethod
def get_mem_ports(self) -> Sequence[Tuple[AddrRange, Port]]:
+ """Get the ports to connect this memory system to the cache"""
raise NotImplementedError
@abstractmethod
def get_memory_controllers(self) -> List[MemCtrl]:
+ """Get all of the memory controllers in this memory system"""
raise NotImplementedError
@abstractmethod
- def get_memory_ranges(self) -> List[AddrRange]:
- """All of the memory ranges that this memory system responds to."""
+ def get_size(self) -> int:
+ """Returns the total size of the memory system"""
+ raise NotImplementedError
+
+ @abstractmethod
+ def set_memory_range(self, ranges: List[AddrRange]) -> None:
+ """Set the total range for this memory system
+
+ May pass multiple non-overlapping ranges. The total size of the
ranges
+ should match the size of the memory.
+
+ If this memory system is incompatible with the ranges, an exception
+ will be raised.
+ """
raise NotImplementedError
diff --git a/components_library/memory/dramsim_3.py
b/components_library/memory/dramsim_3.py
index ba71397..b41935b 100644
--- a/components_library/memory/dramsim_3.py
+++ b/components_library/memory/dramsim_3.py
@@ -3,6 +3,7 @@
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
@@ -95,9 +96,8 @@
"""
super(SingleChannel, self).__init__()
self.mem_ctrl = DRAMSim3MemCtrl(mem_type, 1)
- if size:
- self.mem_ctrl.range = AddrRange(size)
- else:
+ self._size = toMemorySize(size)
+ if not size:
raise NotImplementedError(
"DRAMSim3 memory controller requires a size parameter."
)
@@ -115,8 +115,17 @@
return [self.mem_ctrl]
@overrides(AbstractMemorySystem)
- def get_memory_ranges(self):
- return [self.mem_ctrl.range]
+ 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(
diff --git a/components_library/memory/single_channel.py
b/components_library/memory/single_channel.py
index c733d2c..fcaab40 100644
--- a/components_library/memory/single_channel.py
+++ b/components_library/memory/single_channel.py
@@ -32,6 +32,7 @@
from ..utils.override import overrides
from m5.objects import AddrRange, DRAMInterface, MemCtrl, Port
+from m5.util.convert import toMemorySize
from typing import List, Sequence, Tuple, Type, Optional
@@ -59,12 +60,12 @@
self._dram = dram_interface_class()
if size:
- self._dram.range = size
+ self._size = toMemorySize(size)
else:
- self._dram.range = AddrRange(self.get_size(self._dram))
+ self._size = self._get_dram_size(self._dram)
self.mem_ctrl = MemCtrl(dram=self._dram)
- def get_size(self, dram: DRAMInterface) -> int:
+ def _get_dram_size(self, dram: DRAMInterface) -> int:
return (
dram.device_size.value
* dram.devices_per_rank.value
@@ -84,8 +85,18 @@
return [self.mem_ctrl]
@overrides(AbstractMemorySystem)
- def get_memory_ranges(self):
- return [self._dram.range]
+ 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
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/49348
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Ibef5aafbbb1177a992950cdc2bd2634dcfb81eec
Gerrit-Change-Number: 49348
Gerrit-PatchSet: 1
Gerrit-Owner: Jason Lowe-Power <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s