| # Copyright (c) 2021-2023 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 abc import ABCMeta |
| import os |
| from pathlib import Path |
| from m5.util import warn, fatal |
| from _m5 import core |
| |
| from .downloader import get_resource |
| |
| from .looppoint import LooppointCsvLoader, LooppointJsonLoader |
| from ..isas import ISA, get_isa_from_str |
| |
| from typing import Optional, Dict, Union, Type, Tuple, List |
| |
| from .client import get_resource_json_obj |
| |
| """ |
| Resources are items needed to run a simulation, such as a disk image, kernel, |
| or binary. The gem5 project provides pre-built resources, with sources, at |
| <resources.gem5.org>. Here we provide the `AbstractResource` class and its |
| various implementations which are designed to encapsulate a resource for use |
| in the gem5 Standard Library. |
| |
| These classes may be contructed directly. E.g.: |
| |
| ```python |
| binary = BinaryResource(local_path="/path/to/binary") |
| ``` |
| |
| or obtained via the gem5-resources infrastructure with the `obtain_resource` |
| function: |
| |
| ```python |
| binary = obtain_resource("resource name here") |
| ``` |
| """ |
| |
| |
| class AbstractResource: |
| """ |
| An abstract class which all Resource classes inherit from. |
| """ |
| |
| __metaclass__ = ABCMeta |
| |
| def __init__( |
| self, |
| resource_version: Optional[str] = None, |
| local_path: Optional[str] = None, |
| description: Optional[str] = None, |
| source: Optional[str] = None, |
| ): |
| """ |
| :param local_path: The path on the host system where this resource is |
| located. |
| :param description: Description describing this resource. Not a |
| required parameter. By default is None. |
| :param source: The source (as in "source code") for this resource. This |
| string should navigate users to where the source for this resource |
| may be found. Not a required parameter. By default is None. |
| :param resource_version: Version of the resource itself. |
| """ |
| |
| if local_path and not os.path.exists(local_path): |
| raise Exception( |
| f"Local path specified for resource, '{local_path}', does not " |
| "exist." |
| ) |
| |
| self._local_path = local_path |
| self._description = description |
| self._source = source |
| self._version = resource_version |
| |
| def get_resource_version(self) -> str: |
| """Returns the version of the resource.""" |
| return self._version |
| |
| def get_local_path(self) -> Optional[str]: |
| """Returns the local path of the resource.""" |
| return self._local_path |
| |
| def get_description(self) -> Optional[str]: |
| """Returns description associated with this resource.""" |
| return self._description |
| |
| def get_source(self) -> Optional[str]: |
| """Returns information as to where the source for this resource may be |
| found. |
| """ |
| return self._source |
| |
| |
| class FileResource(AbstractResource): |
| """A resource consisting of a single file.""" |
| |
| def __init__( |
| self, |
| local_path: str, |
| resource_version: Optional[str] = None, |
| description: Optional[str] = None, |
| source: Optional[str] = None, |
| **kwargs, |
| ): |
| if not os.path.isfile(local_path): |
| raise Exception( |
| f"FileResource path specified, '{local_path}', is not a file." |
| ) |
| |
| super().__init__( |
| local_path=local_path, |
| description=description, |
| source=source, |
| resource_version=resource_version, |
| ) |
| |
| |
| class DirectoryResource(AbstractResource): |
| """A resource consisting of a directory.""" |
| |
| def __init__( |
| self, |
| local_path: str, |
| resource_version: Optional[str] = None, |
| description: Optional[str] = None, |
| source: Optional[str] = None, |
| **kwargs, |
| ): |
| if not os.path.isdir(local_path): |
| raise Exception( |
| f"DirectoryResource path specified, {local_path}, is not a " |
| "directory." |
| ) |
| |
| super().__init__( |
| local_path=local_path, |
| description=description, |
| source=source, |
| resource_version=resource_version, |
| ) |
| |
| |
| class DiskImageResource(FileResource): |
| """A Disk Image resource.""" |
| |
| def __init__( |
| self, |
| local_path: str, |
| resource_version: Optional[str] = None, |
| description: Optional[str] = None, |
| source: Optional[str] = None, |
| root_partition: Optional[str] = None, |
| **kwargs, |
| ): |
| super().__init__( |
| local_path=local_path, |
| description=description, |
| source=source, |
| resource_version=resource_version, |
| ) |
| self._root_partition = root_partition |
| |
| def get_root_partition(self) -> Optional[str]: |
| """Returns, if applicable, the Root Partition of the disk image.""" |
| return self._root_partition |
| |
| |
| class BinaryResource(FileResource): |
| """A binary resource.""" |
| |
| def __init__( |
| self, |
| local_path: str, |
| resource_version: Optional[str] = None, |
| description: Optional[str] = None, |
| source: Optional[str] = None, |
| architecture: Optional[Union[ISA, str]] = None, |
| **kwargs, |
| ): |
| super().__init__( |
| local_path=local_path, |
| description=description, |
| source=source, |
| resource_version=resource_version, |
| ) |
| |
| self._architecture = None |
| if architecture: |
| if isinstance(architecture, str): |
| self._architecture = get_isa_from_str(architecture) |
| elif isinstance(architecture, ISA): |
| self._architecture = architecture |
| |
| def get_architecture(self) -> Optional[ISA]: |
| """Returns the ISA this binary is compiled to.""" |
| return self._architecture |
| |
| |
| class BootloaderResource(BinaryResource): |
| """A bootloader resource.""" |
| |
| def __init__( |
| self, |
| local_path: str, |
| resource_version: Optional[str] = None, |
| description: Optional[str] = None, |
| source: Optional[str] = None, |
| architecture: Optional[Union[ISA, str]] = None, |
| **kwargs, |
| ): |
| super().__init__( |
| local_path=local_path, |
| description=description, |
| architecture=architecture, |
| source=source, |
| resource_version=resource_version, |
| ) |
| |
| |
| class GitResource(DirectoryResource): |
| """A git resource.""" |
| |
| def __init__( |
| self, |
| local_path: str, |
| resource_version: Optional[str] = None, |
| description: Optional[str] = None, |
| source: Optional[str] = None, |
| **kwargs, |
| ): |
| super().__init__( |
| local_path=local_path, |
| description=description, |
| source=source, |
| resource_version=resource_version, |
| ) |
| |
| |
| class KernelResource(BinaryResource): |
| """A kernel resource.""" |
| |
| def __init__( |
| self, |
| local_path: str, |
| resource_version: Optional[str] = None, |
| description: Optional[str] = None, |
| source: Optional[str] = None, |
| architecture: Optional[Union[ISA, str]] = None, |
| **kwargs, |
| ): |
| super().__init__( |
| local_path=local_path, |
| description=description, |
| source=source, |
| architecture=architecture, |
| resource_version=resource_version, |
| ) |
| |
| |
| class CheckpointResource(DirectoryResource): |
| """A checkpoint resource. The following directory structure is expected: |
| |
| <local_path>: |
| - board.physmem.store0.pmem |
| - m5.cpt |
| """ |
| |
| def __init__( |
| self, |
| local_path: str, |
| resource_version: Optional[str] = None, |
| description: Optional[str] = None, |
| source: Optional[str] = None, |
| **kwargs, |
| ): |
| super().__init__( |
| local_path=local_path, |
| description=description, |
| source=source, |
| resource_version=resource_version, |
| ) |
| |
| |
| class SimpointResource(AbstractResource): |
| """A simpoint resource. This resource stores all information required to |
| perform a Simpoint creation and restore. It contains the Simpoint, the |
| Simpoint interval, the weight for each Simpoint, the full warmup length, |
| and the warmup length for each Simpoint. |
| """ |
| |
| def __init__( |
| self, |
| resource_version: Optional[str] = None, |
| simpoint_interval: int = None, |
| simpoint_list: List[int] = None, |
| weight_list: List[float] = None, |
| warmup_interval: int = 0, |
| workload_name: Optional[str] = None, |
| description: Optional[str] = None, |
| source: Optional[str] = None, |
| local_path: Optional[str] = None, |
| **kwargs, |
| ): |
| """ |
| :param simpoint_interval: The simpoint interval. |
| :param simpoint_list: The simpoint list. |
| :param weight_list: The weight list. |
| :param warmup_interval: The warmup interval. Default to zero (a value |
| of zero means effectively not set). |
| :param workload_name: Simpoints are typically associated with a |
| particular workload due to their dependency on chosen input parameters. |
| This field helps backtrack to that resource if required. This should |
| relate to a workload "name" field in the resource.json file. |
| """ |
| |
| super().__init__( |
| local_path=local_path, |
| description=description, |
| source=source, |
| resource_version=resource_version, |
| ) |
| |
| self._weight_list = weight_list |
| self._simpoint_list = simpoint_list |
| self._simpoint_interval = simpoint_interval |
| self._warmup_interval = warmup_interval |
| self._workload_name = workload_name |
| |
| self._simpoint_start_insts = list( |
| inst * simpoint_interval for inst in self.get_simpoint_list() |
| ) |
| |
| if self._warmup_interval != 0: |
| self._warmup_list = self._set_warmup_list() |
| else: |
| self._warmup_list = [0] * len(self.get_simpoint_start_insts) |
| |
| def get_simpoint_list(self) -> List[int]: |
| """Returns the a list containing all the Simpoints for the workload.""" |
| return self._simpoint_list |
| |
| def get_simpoint_start_insts(self) -> List[int]: |
| """Returns a lst containing all the Simpoint starting instrunction |
| points for the workload. This was calculated by multiplying the |
| Simpoint with the Simpoint interval when it was generated.""" |
| return self._simpoint_start_insts |
| |
| def get_warmup_interval(self) -> int: |
| """Returns the instruction length of the warmup interval.""" |
| return self._warmup_interval |
| |
| def get_weight_list(self) -> List[float]: |
| """Returns the list that contains the weight for each Simpoint. The |
| order of the weights matches that of the list returned by |
| `get_simpoint_list(). I.e. `get_weight_list()[3]` is the weight for |
| simpoint `get_simpoint_list()[3]`.""" |
| return self._weight_list |
| |
| def get_simpoint_interval(self) -> int: |
| """Returns the Simpoint interval value.""" |
| return self._simpoint_interval |
| |
| def get_warmup_list(self) -> List[int]: |
| """Returns the a list containing the warmup length for each Simpoint. |
| Each warmup length in this list corresponds to the Simpoint at the same |
| index in `get_simpoint_list()`. I.e., `get_warmup_list()[4]` is the |
| warmup length for Simpoint `get_simpoint_list()[4]`.""" |
| return self._warmup_list |
| |
| def get_workload_name(self) -> Optional[str]: |
| """Return the workload name this Simpoint is associated with.""" |
| return self._workload_name |
| |
| def _set_warmup_list(self) -> List[int]: |
| """ |
| This function uses the warmup_interval, fits it into the |
| simpoint_start_insts, and outputs a list of warmup instruction lengths |
| for each SimPoint. |
| |
| The warmup instruction length is calculated using the starting |
| instruction of a SimPoint to minus the warmup_interval and the ending |
| instruction of the last SimPoint. If it is less than 0, then the warmup |
| instruction length is the gap between the starting instruction of a |
| SimPoint and the ending instruction of the last SimPoint. |
| """ |
| warmup_list = [] |
| for index, start_inst in enumerate(self.get_simpoint_start_insts()): |
| warmup_inst = start_inst - self.get_warmup_interval() |
| if warmup_inst < 0: |
| warmup_inst = start_inst |
| else: |
| warmup_inst = self.get_warmup_interval() |
| warmup_list.append(warmup_inst) |
| # change the starting instruction of a SimPoint to include the |
| # warmup instruction length |
| self._simpoint_start_insts[index] = start_inst - warmup_inst |
| return warmup_list |
| |
| |
| class LooppointCsvResource(FileResource, LooppointCsvLoader): |
| """This Looppoint resource used to create a Looppoint resource from a |
| pinpoints CSV file""" |
| |
| def __init__( |
| self, |
| local_path: str, |
| resource_version: Optional[str] = None, |
| description: Optional[str] = None, |
| source: Optional[str] = None, |
| **kwargs, |
| ): |
| FileResource.__init__( |
| self, |
| local_path=local_path, |
| description=description, |
| source=source, |
| resource_version=resource_version, |
| ) |
| LooppointCsvLoader.__init__(self, pinpoints_file=Path(local_path)) |
| |
| |
| class LooppointJsonResource(FileResource, LooppointJsonLoader): |
| def __init__( |
| self, |
| local_path: str, |
| resource_version: Optional[str] = None, |
| region_id: Optional[Union[str, int]] = None, |
| description: Optional[str] = None, |
| source: Optional[str] = None, |
| **kwargs, |
| ): |
| FileResource.__init__( |
| self, |
| local_path=local_path, |
| description=description, |
| source=source, |
| resource_version=resource_version, |
| ) |
| LooppointJsonLoader.__init__( |
| self, looppoint_file=local_path, region_id=region_id |
| ) |
| |
| |
| class SimpointDirectoryResource(SimpointResource): |
| """A Simpoint diretory resource. This Simpoint Resource assumes the |
| existance of a directory containing a simpoint file and a weight file.""" |
| |
| def __init__( |
| self, |
| local_path: str, |
| simpoint_file: str, |
| weight_file: str, |
| simpoint_interval: int, |
| warmup_interval: int, |
| resource_version: Optional[str] = None, |
| workload_name: Optional[str] = None, |
| description: Optional[str] = None, |
| source: Optional[str] = None, |
| **kwargs, |
| ): |
| """ |
| :param simpoint_file: The Simpoint file. This file is a list of |
| Simpoints, each on its own line. It should map 1-to-1 to the weights |
| file. |
| :param weight_file: The Simpoint weights file. This file is a list of |
| weights, each on its own line. |
| """ |
| self._simpoint_file = simpoint_file |
| self._weight_file = weight_file |
| |
| # This is a little hack. The functions `get_simpoint_file` and |
| # `get_weight_file` use the local path, so we set it here despite it |
| # also being set in the `AbstractResource` constructor. This isn't |
| # elegant but does not harm. |
| self._local_path = local_path |
| ( |
| simpoint_list, |
| weight_list, |
| ) = self._get_weights_and_simpoints_from_file() |
| |
| super().__init__( |
| simpoint_interval=simpoint_interval, |
| simpoint_list=simpoint_list, |
| weight_list=weight_list, |
| warmup_interval=warmup_interval, |
| workload_name=workload_name, |
| local_path=local_path, |
| description=description, |
| source=source, |
| resource_version=resource_version, |
| ) |
| |
| def get_simpoint_file(self) -> Path: |
| """Return the Simpoint File path.""" |
| return Path(Path(self._local_path) / self._simpoint_file) |
| |
| def get_weight_file(self) -> Path: |
| """Returns the Weight File path.""" |
| return Path(Path(self._local_path) / self._weight_file) |
| |
| def _get_weights_and_simpoints_from_file( |
| self, |
| ) -> Tuple[List[int], List[int]]: |
| """This is a helper function to extract the weights and simpoints from |
| the files. |
| """ |
| simpoint_weight_pair = [] |
| with open(self.get_simpoint_file()) as simpoint_file, open( |
| self.get_weight_file() |
| ) as weight_file: |
| while True: |
| line = simpoint_file.readline() |
| if not line: |
| break |
| interval = int(line.split(" ", 1)[0]) |
| line = weight_file.readline() |
| if not line: |
| fatal("not engough weights") |
| weight = float(line.split(" ", 1)[0]) |
| simpoint_weight_pair.append((interval, weight)) |
| simpoint_weight_pair.sort(key=lambda obj: obj[0]) |
| # use simpoint to sort |
| |
| weight_list = [] |
| simpoint_list = [] |
| for simpoint, weight in simpoint_weight_pair: |
| simpoint_list.append(simpoint) |
| weight_list.append(weight) |
| return simpoint_list, weight_list |
| |
| |
| def obtain_resource( |
| resource_id: str, |
| resource_directory: Optional[str] = None, |
| download_md5_mismatch: bool = True, |
| resource_version: Optional[str] = None, |
| clients: Optional[List] = None, |
| gem5_version=core.gem5Version, |
| ) -> AbstractResource: |
| """ |
| This function primarily serves as a factory for resources. It will return |
| the correct `AbstractResource` implementation based on the resource |
| requested. |
| |
| :param resource_name: The name of the gem5 resource as it appears under the |
| "id" field in the `resource.json` file. |
| :param resource_directory: The location of the directory in which the |
| resource is to be stored. If this parameter is not set, it will set to |
| the environment variable `GEM5_RESOURCE_DIR`. If the environment is not |
| set it will default to `~/.cache/gem5` if available, otherwise the CWD. |
| :param download_md5_mismatch: If the resource is present, but does not |
| have the correct md5 value, the resoruce will be deleted and |
| re-downloaded if this value is True. Otherwise an exception will be |
| thrown. True by default. |
| :param resource_version: Version of the resource itself. |
| Not a required parameter. None by default. |
| :param clients: A list of clients to search for the resource. If this |
| parameter is not set, it will default search all clients. |
| :param gem5_version: The gem5 version to use to filter incompatible |
| resource versions. By default set to the current gem5 version. If None, |
| this filtering is not performed. |
| """ |
| |
| # Obtain the resource object entry for this resource |
| resource_json = get_resource_json_obj( |
| resource_id, |
| resource_version=resource_version, |
| clients=clients, |
| gem5_version=gem5_version, |
| ) |
| |
| to_path = None |
| # If the "url" field is specified, the resoruce must be downloaded. |
| if "url" in resource_json and resource_json["url"]: |
| |
| # If the `resource_directory` parameter is not set via this function, we |
| # check the "GEM5_RESOURCE_DIR" environment variable. If this too is not |
| # set we call `_get_default_resource_dir()` to determine where the |
| # resource directory is, or should be, located. |
| if resource_directory == None: |
| resource_directory = os.getenv( |
| "GEM5_RESOURCE_DIR", _get_default_resource_dir() |
| ) |
| |
| # Small checks here to ensure the resource directory is valid. |
| if os.path.exists(resource_directory): |
| if not os.path.isdir(resource_directory): |
| raise Exception( |
| "gem5 resource directory, " |
| "'{}', exists but is not a directory".format( |
| resource_directory |
| ) |
| ) |
| else: |
| # `exist_ok=True` here as, occasionally, if multiple instance of |
| # gem5 are started simultaneously, a race condition can exist to |
| # create the resource directory. Without `exit_ok=True`, threads |
| # which lose this race will thrown a `FileExistsError` exception. |
| # `exit_ok=True` ensures no exception is thrown. |
| os.makedirs(resource_directory, exist_ok=True) |
| |
| # This is the path to which the resource is to be stored. |
| to_path = os.path.join(resource_directory, resource_id) |
| |
| # Download the resource if it does not already exist. |
| get_resource( |
| resource_name=resource_id, |
| to_path=os.path.join(resource_directory, resource_id), |
| download_md5_mismatch=download_md5_mismatch, |
| resource_version=resource_version, |
| clients=clients, |
| gem5_version=gem5_version, |
| ) |
| |
| # Obtain the type from the JSON. From this we will determine what subclass |
| # of `AbstractResource` we are to create and return. |
| resources_category = resource_json["category"] |
| |
| if resources_category == "resource": |
| # This is a stop-gap measure to ensure to work with older versions of |
| # the "resource.json" file. These should be replaced with their |
| # respective specializations ASAP and this case removed. |
| if "root_partition" in resource_json: |
| # In this case we should return a DiskImageResource. |
| root_partition = resource_json["root_partition"] |
| return DiskImageResource( |
| local_path=to_path, |
| root_partition=root_partition, |
| **resource_json, |
| ) |
| return CustomResource(local_path=to_path) |
| |
| assert resources_category in _get_resource_json_type_map |
| resource_class = _get_resource_json_type_map[resources_category] |
| |
| # Once we know what AbstractResource subclass we are using, we create it. |
| # The fields in the JSON object are assumed to map like-for-like to the |
| # subclass contructor, so we can pass the resource_json map directly. |
| return resource_class(local_path=to_path, **resource_json) |
| |
| |
| def _get_default_resource_dir() -> str: |
| """ |
| Obtain the default gem5 resources directory on the host system. This |
| function will iterate through sensible targets until it finds one that |
| works on the host system. |
| |
| :returns: The default gem5 resources directory. |
| """ |
| test_list = [ |
| # First try `~/.cache/gem5`. |
| os.path.join(Path.home(), ".cache", "gem5"), |
| # Last resort, just put things in the cwd. |
| os.path.join(Path.cwd(), "resources"), |
| ] |
| |
| for path in test_list: |
| if os.path.exists(path): # If the path already exists... |
| if os.path.isdir(path): # Check to see the path is a directory. |
| return path # If so, the path is valid and can be used. |
| else: # If the path does not exist, try to create it. |
| try: |
| os.makedirs(path, exist_ok=False) |
| return path |
| except OSError: |
| continue # If the path cannot be created, then try another. |
| |
| raise Exception("Cannot find a valid location to download resources") |
| |
| |
| # The following classes exist to preserve backwards functionality between the |
| # API for obtaining resources in v21.1.0 and prior. |
| |
| |
| class CustomResource(AbstractResource): |
| """ |
| A custom gem5 resource. This can be used to encapsulate a resource provided |
| by a gem5 user as opposed to one available within the gem5 resources |
| repository. |
| |
| **Warning**: This class is deprecated and will be removed in future |
| releases of gem5. Please use the correct `AbstractResource` subclass |
| instead. |
| """ |
| |
| def __init__(self, local_path: str, metadata: Dict = {}): |
| """ |
| :param local_path: The path of the resource on the host system. |
| :param metadata: Add metadata for the custom resource. **Warning:** |
| As of v22.1.1, this parameter is not used. |
| """ |
| warn( |
| "The `CustomResource` class is deprecated. Please use an " |
| "`AbstractResource` subclass instead." |
| ) |
| if bool(metadata): # Empty dicts cast to False |
| warn( |
| "the `metadata` parameter was set via the `CustomResource` " |
| "constructor. This parameter is not used." |
| ) |
| super().__init__(local_path=local_path) |
| |
| |
| class CustomDiskImageResource(DiskImageResource): |
| """ |
| A custom disk image gem5 resource. It can be used to specify a custom, |
| local disk image. |
| |
| **Warning**: This class is deprecated and will be removed in future |
| releases of gem5. Please use the `DiskImageResource` class instead. This |
| class is merely a wrapper for it. |
| """ |
| |
| def __init__( |
| self, |
| local_path: str, |
| resource_version: Optional[str] = None, |
| root_partition: Optional[str] = None, |
| metadata: Dict = {}, |
| ): |
| """ |
| :param local_path: The path of the disk image on the host system. |
| :param root_partition: The root disk partition to use. |
| :param metadata: Metadata for the resource. **Warning:** As of " |
| "v22.1.1, this parameter is not used. |
| :param resource_version: Version of the resource itself. |
| """ |
| warn( |
| "The `CustomDiskImageResource` class is deprecated. Please use " |
| "`DiskImageResource` instead." |
| ) |
| if bool(metadata): # Empty dicts cast to False |
| warn( |
| "the `metadata` parameter was set via the " |
| "`CustomDiskImageResource` constructor. This parameter is not " |
| "used." |
| ) |
| super().__init__( |
| local_path=local_path, |
| root_partition=root_partition, |
| resource_version=resource_version, |
| ) |
| |
| |
| def Resource( |
| resource_id: str, |
| resource_directory: Optional[str] = None, |
| download_md5_mismatch: bool = True, |
| resource_version: Optional[str] = None, |
| clients: Optional[List[str]] = None, |
| ) -> AbstractResource: |
| """ |
| This function was created to maintain backwards compability for v21.1.0 |
| and prior releases of gem5 where `Resource` was a class. |
| |
| In the interests of gem5-resource specialization, the `Resource` class |
| has been dropped. Instead users are advized to use the `obtain_resource` |
| function which will return the correct `AbstractResource` implementation. |
| This function (disguised as a class) wraps this function. |
| """ |
| |
| warn( |
| "`Resource` has been deprecated. Please use the `obtain_resource` " |
| "function instead." |
| ) |
| |
| return obtain_resource( |
| resource_id=resource_id, |
| resource_directory=resource_directory, |
| download_md5_mismatch=download_md5_mismatch, |
| resource_version=resource_version, |
| clients=clients, |
| ) |
| |
| |
| _get_resource_json_type_map = { |
| "disk-image": DiskImageResource, |
| "binary": BinaryResource, |
| "kernel": KernelResource, |
| "checkpoint": CheckpointResource, |
| "git": GitResource, |
| "bootloader": BootloaderResource, |
| "file": FileResource, |
| "directory": DirectoryResource, |
| "simpoint": SimpointResource, |
| "simpoint-directory": SimpointDirectoryResource, |
| "resource": Resource, |
| "looppoint-pinpoint-csv": LooppointCsvResource, |
| "looppoint-json": LooppointJsonResource, |
| } |