stdlib: Add Workload to the stdlib
This commit adds the concept of a "Workload" to the stdlib. Workloads specify the details needed to run a particular gem5 workload on an stdlib board. These are specified as part of gem5-resources and loaded via the `Workload` class though can be specified locally via the `CustomWorkload` class. Tests are included in this commit to verify the functionality of these Workloads. Change-Id: I8840d281eb01ee4138f01ee499cae96bf7e0579d Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/62532 Maintainer: Jason Lowe-Power <power.jg@gmail.com> Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Bobby Bruce
parent
eb1242d96a
commit
329a917c71
@@ -218,6 +218,7 @@ PySource('gem5.resources', 'gem5/resources/__init__.py')
|
||||
PySource('gem5.resources', 'gem5/resources/downloader.py')
|
||||
PySource('gem5.resources', 'gem5/resources/md5_utils.py')
|
||||
PySource('gem5.resources', 'gem5/resources/resource.py')
|
||||
PySource('gem5.resources', 'gem5/resources/workload.py')
|
||||
PySource('gem5.utils', 'gem5/utils/__init__.py')
|
||||
PySource('gem5.utils', 'gem5/utils/filelock.py')
|
||||
PySource('gem5.utils', 'gem5/utils/override.py')
|
||||
|
||||
@@ -25,8 +25,10 @@
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import inspect
|
||||
|
||||
from .mem_mode import MemMode, mem_mode_to_string
|
||||
from ...resources.workload import AbstractWorkload
|
||||
|
||||
from m5.objects import (
|
||||
System,
|
||||
@@ -177,6 +179,37 @@ class AbstractBoard:
|
||||
)
|
||||
return self._is_fs
|
||||
|
||||
def set_workload(self, workload: AbstractWorkload) -> None:
|
||||
"""
|
||||
Set the workload for this board to run.
|
||||
|
||||
This function will take the workload specified and run the correct
|
||||
workload function (e.g., `set_kernel_disk_workload`) with the correct
|
||||
parameters
|
||||
|
||||
:params workload: The workload to be set to this board.
|
||||
"""
|
||||
|
||||
try:
|
||||
func = getattr(self, workload.get_function_str())
|
||||
except AttributeError:
|
||||
raise Exception(
|
||||
"This board does not support this workload type. "
|
||||
f"This board does not contain the necessary "
|
||||
f"`{workload.get_function_str()}` function"
|
||||
)
|
||||
|
||||
func_signature = inspect.signature(func)
|
||||
for param_name in workload.get_parameters().keys():
|
||||
if param_name not in func_signature.parameters.keys():
|
||||
raise Exception(
|
||||
"Workload specifies non-existent parameter "
|
||||
f"`{param_name}` for function "
|
||||
f"`{workload.get_function_str()}` "
|
||||
)
|
||||
|
||||
func(**workload.get_parameters())
|
||||
|
||||
@abstractmethod
|
||||
def _setup_board(self) -> None:
|
||||
"""
|
||||
|
||||
@@ -39,7 +39,7 @@ from pathlib import Path
|
||||
import tarfile
|
||||
from tempfile import gettempdir
|
||||
from urllib.error import HTTPError
|
||||
from typing import List, Dict
|
||||
from typing import List, Dict, Set, Optional
|
||||
|
||||
from .md5_utils import md5_file, md5_dir
|
||||
|
||||
@@ -182,17 +182,27 @@ def _get_url_base() -> str:
|
||||
return ""
|
||||
|
||||
|
||||
def _get_resources(resources_group: Dict) -> Dict[str, Dict]:
|
||||
def _get_resources(
|
||||
valid_types: Set[str], resources_group: Optional[Dict] = None
|
||||
) -> Dict[str, Dict]:
|
||||
"""
|
||||
A recursive function to get all the resources.
|
||||
A recursive function to get all the workload/resource of the specified type
|
||||
in the resources.json file.
|
||||
|
||||
:returns: A dictionary of resource names to the resource JSON objects.
|
||||
:param valid_types: The type to return (i.e., "resource" or "workload).
|
||||
:param resource_group: Used for recursion: The current resource group being
|
||||
iterated through.
|
||||
|
||||
:returns: A dictionary of artifact names to the resource JSON objects.
|
||||
"""
|
||||
|
||||
if resources_group is None:
|
||||
resources_group = _get_resources_json()["resources"]
|
||||
|
||||
to_return = {}
|
||||
for resource in resources_group:
|
||||
if resource["type"] == "resource":
|
||||
# If the type is "resource" then we add it directly to the map
|
||||
if resource["type"] in valid_types:
|
||||
# If the type is valid then we add it directly to the map
|
||||
# after a check that the name is unique.
|
||||
if resource["name"] in to_return.keys():
|
||||
raise Exception(
|
||||
@@ -204,7 +214,9 @@ def _get_resources(resources_group: Dict) -> Dict[str, Dict]:
|
||||
elif resource["type"] == "group":
|
||||
# If it's a group we get recursive. We then check to see if there
|
||||
# are any duplication of keys.
|
||||
new_map = _get_resources(resource["contents"])
|
||||
new_map = _get_resources(
|
||||
valid_types=valid_types, resources_group=resource["contents"]
|
||||
)
|
||||
intersection = set(new_map.keys()).intersection(to_return.keys())
|
||||
if len(intersection) > 0:
|
||||
# Note: if this error is received it's likely an error with
|
||||
@@ -216,10 +228,6 @@ def _get_resources(resources_group: Dict) -> Dict[str, Dict]:
|
||||
)
|
||||
)
|
||||
to_return.update(new_map)
|
||||
else:
|
||||
raise Exception(
|
||||
"Error: Unknown type '{}'.".format(resource["type"])
|
||||
)
|
||||
|
||||
return to_return
|
||||
|
||||
@@ -315,7 +323,26 @@ def list_resources() -> List[str]:
|
||||
|
||||
:returns: A list of resources by name.
|
||||
"""
|
||||
return _get_resources(_get_resources_json()["resources"]).keys()
|
||||
return _get_resources(valid_types={"resource"}).keys()
|
||||
|
||||
|
||||
def get_workload_json_obj(workload_name: str) -> Dict:
|
||||
"""
|
||||
Get a JSON object of a specified workload.
|
||||
|
||||
:param workload_name: The name of the workload.
|
||||
|
||||
:raises Exception: An exception is raised if the specified workload does
|
||||
not exit.
|
||||
"""
|
||||
workload_map = _get_resources(valid_types={"workload"})
|
||||
|
||||
if workload_name not in workload_map:
|
||||
raise Exception(
|
||||
f"Error: Workload with name {workload_name} does not exist"
|
||||
)
|
||||
|
||||
return workload_map[workload_name]
|
||||
|
||||
|
||||
def get_resources_json_obj(resource_name: str) -> Dict:
|
||||
@@ -329,7 +356,7 @@ def get_resources_json_obj(resource_name: str) -> Dict:
|
||||
:raises Exception: An exception is raised if the specified resources does
|
||||
not exist.
|
||||
"""
|
||||
resource_map = _get_resources(_get_resources_json()["resources"])
|
||||
resource_map = _get_resources(valid_types={"resource"})
|
||||
|
||||
if resource_name not in resource_map:
|
||||
raise Exception(
|
||||
|
||||
221
src/python/gem5/resources/workload.py
Normal file
221
src/python/gem5/resources/workload.py
Normal file
@@ -0,0 +1,221 @@
|
||||
# Copyright (c) 2022 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 .downloader import get_workload_json_obj
|
||||
from .resource import Resource
|
||||
|
||||
from typing import Dict, Any, Optional
|
||||
|
||||
|
||||
class AbstractWorkload:
|
||||
"""
|
||||
Workloads contain information needed to build a workload.
|
||||
|
||||
A workload specifies a function and its parameters to run on a board to
|
||||
set a workload. Workload's are passed to board via the `AbstractBoard`'s
|
||||
`set_workload` function.
|
||||
|
||||
The `AbstractBoard` has a `set_workload` function which accepts an
|
||||
AbstractWorkload. The `set_workload` function uses the `get_function_str`
|
||||
to determine which function should be called on the board and the
|
||||
`get_parameters` function specifies the parameters to be passed.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```py
|
||||
workload = CustomWorkload(
|
||||
function = "set_se_binary_workload",
|
||||
parameters = {
|
||||
"binary" : Resource("x86-print-this"),
|
||||
"arguments" : ["hello", 6]
|
||||
},
|
||||
)
|
||||
|
||||
board.set_workload(workload)
|
||||
```
|
||||
|
||||
The above is the equivalent of:
|
||||
|
||||
```py
|
||||
board.set_se_binary_workload(
|
||||
binary = Resource("x86-print-this"),
|
||||
arguments = ["hello", 6],
|
||||
)
|
||||
```
|
||||
|
||||
Notes
|
||||
-----
|
||||
This class should not be used directly. Please use `Workload` or
|
||||
`CustomWorkload`.
|
||||
"""
|
||||
|
||||
def __init__(self, function: str, parameters: Dict[str, Any]) -> None:
|
||||
self._func = function
|
||||
self._params = parameters
|
||||
|
||||
def get_function_str(self) -> str:
|
||||
"""
|
||||
Returns the name of the workload function to be run.
|
||||
|
||||
This function is called via the AbstractBoard's `set_workload`
|
||||
function. The parameters from the `get_parameters` function are passed
|
||||
to this function.
|
||||
"""
|
||||
return self._func
|
||||
|
||||
def get_parameters(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Returns a dictionary mapping the workload parameters to their values.
|
||||
|
||||
These parameters are passed to the function specified by
|
||||
`get_function_str` via the AbstractBoard's `set_workload` function.
|
||||
"""
|
||||
return self._params
|
||||
|
||||
def set_parameter(self, parameter: str, value: Any) -> None:
|
||||
"""
|
||||
Used to set or override a workload parameter
|
||||
|
||||
:param parameter: The parameter of the function to set.
|
||||
:param value: The value to set to the parameter.
|
||||
"""
|
||||
self._params[parameter] = value
|
||||
|
||||
|
||||
class CustomWorkload(AbstractWorkload):
|
||||
"""
|
||||
A workload specified locally (i.e., not via gem5-resources as with the
|
||||
`Workload` class). Here the user specifies the function and the parameters
|
||||
to be passed.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
```py
|
||||
workload = CustomWorkload(
|
||||
function = "set_se_binary_workload",
|
||||
parameters = {
|
||||
"binary" : Resource("x86-print-this"),
|
||||
"arguments" : ["hello", 6]
|
||||
},
|
||||
)
|
||||
|
||||
board.set_workload(workload)
|
||||
```
|
||||
"""
|
||||
|
||||
def __init__(self, function: str, parameters: Dict[str, Any]) -> None:
|
||||
super().__init__(function=function, parameters=parameters)
|
||||
|
||||
|
||||
class Workload(AbstractWorkload):
|
||||
"""
|
||||
The `Workload` class loads a workload's information from gem5-resources
|
||||
based on a name/id passed via the constructor.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
```py
|
||||
# Determine what workload we want to run.
|
||||
workload = Workload("example-workload-id")
|
||||
|
||||
# Optionally we can override a parameter in the workload. In this example
|
||||
# we are going to run this workload with a difference kernel.
|
||||
workload.set_parameter("kernel", Resource("arm64-linux-kernel-4.14.134"))
|
||||
|
||||
# We then set this workload to the board.
|
||||
board.set_workload(workload)
|
||||
```
|
||||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, workload_name: str, resource_directory: Optional[str] = None
|
||||
) -> None:
|
||||
"""
|
||||
This constructor will load the workload details from the workload with
|
||||
the given name/id.
|
||||
|
||||
This function assumes the dictionary returned by the downloader's
|
||||
`get_workload_json_obj` is a dictionary. An example of the schema is
|
||||
shown below:
|
||||
|
||||
```json
|
||||
{
|
||||
"type" : "workload",
|
||||
"name" : "x86-ubuntu-18.04-echo-hello",
|
||||
"documentation" : "Description of workload here",
|
||||
"function" : "set_kernel_disk_workload",
|
||||
"resources" : {
|
||||
"kernel" : "x86-linux-kernel-5.4.49",
|
||||
"disk_image" : "x86-ubuntu-18.04-img"
|
||||
},
|
||||
"additional_params" : {
|
||||
"readfile_contents" : "m5_exit; echo 'hello'; m5_exit"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This resource will result in the equivalent of the following action
|
||||
being taken:
|
||||
|
||||
```python
|
||||
board.set_kernel_disk_workload(
|
||||
kernel = Resource("x86-linux-kernel-5.4.49"),
|
||||
disk_image = Resource("x86-ubuntu-18.04-img"),
|
||||
readfile_contents = "m5_exit; echo 'hello'; m5_exit",
|
||||
)
|
||||
```
|
||||
|
||||
:param workload_name: The name of the workload in the resources.json
|
||||
file to be loaded.
|
||||
:param resource_directory: An optional parameter that specifies where
|
||||
any resources should be download and accessed from. If None, a default
|
||||
location will be used. None by default.
|
||||
"""
|
||||
workload_json = get_workload_json_obj(workload_name=workload_name)
|
||||
|
||||
func = workload_json["function"]
|
||||
assert isinstance(func, str)
|
||||
|
||||
params = {}
|
||||
if "resources" in workload_json:
|
||||
for key in workload_json["resources"].keys():
|
||||
assert isinstance(key, str)
|
||||
value = workload_json["resources"][key]
|
||||
assert isinstance(value, str)
|
||||
params[key] = Resource(
|
||||
value, resource_directory=resource_directory
|
||||
)
|
||||
|
||||
if "additional_params" in workload_json:
|
||||
for key in workload_json["additional_params"]:
|
||||
assert isinstance(key, str)
|
||||
params[key] = workload_json["additional_params"][key]
|
||||
|
||||
super().__init__(function=func, parameters=params)
|
||||
264
tests/pyunit/stdlib/resources/pyunit_workload_checks.py
Normal file
264
tests/pyunit/stdlib/resources/pyunit_workload_checks.py
Normal file
@@ -0,0 +1,264 @@
|
||||
# Copyright (c) 2022 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.
|
||||
|
||||
import unittest
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
from gem5.resources.workload import Workload, CustomWorkload
|
||||
from gem5.resources.resource import Resource
|
||||
from gem5.resources.downloader import _resources_json_version_required
|
||||
|
||||
from typing import Dict
|
||||
|
||||
|
||||
class CustomWorkloadTestSuite(unittest.TestCase):
|
||||
"""
|
||||
Tests the `gem5.resources.workload.CustomWorkload` class.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None:
|
||||
file_contents = (
|
||||
"{"
|
||||
+ f'"version" : "{_resources_json_version_required()}",'
|
||||
+ """
|
||||
"url_base" : "http://dist.gem5.org/dist/v22-0",
|
||||
"previous-versions" : {},
|
||||
"resources": [
|
||||
{
|
||||
"type" : "resource",
|
||||
"name" : "x86-hello64-static",
|
||||
"documentation" : "A 'Hello World!' binary.",
|
||||
"architecture" : "X86",
|
||||
"is_zipped" : false,
|
||||
"md5sum" : "dbf120338b37153e3334603970cebd8c",
|
||||
"url" : "{url_base}/test-progs/hello/bin/x86/linux/hello64-static",
|
||||
"source" : "src/simple"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
)
|
||||
file = tempfile.NamedTemporaryFile(mode="w", delete=False)
|
||||
file.write(file_contents)
|
||||
file.close()
|
||||
|
||||
cls.test_json = file.name
|
||||
os.environ["GEM5_RESOURCE_JSON"] = cls.test_json
|
||||
|
||||
cls.custom_workload = CustomWorkload(
|
||||
function="set_se_binary_workload",
|
||||
parameters={
|
||||
"binary": Resource("x86-hello64-static"),
|
||||
"arguments": ["hello", 6],
|
||||
},
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
# Remove the test json file and unset the environment variable so this
|
||||
# test does not interfere with others.
|
||||
os.remove(cls.test_json)
|
||||
os.environ["GEM5_RESOURCE_JSON"]
|
||||
|
||||
def test_get_function_str(self) -> None:
|
||||
# Tests `CustomResource.get_function_str`
|
||||
|
||||
self.assertEqual(
|
||||
"set_se_binary_workload", self.custom_workload.get_function_str()
|
||||
)
|
||||
|
||||
def test_get_parameters(self) -> None:
|
||||
# Tests `CustomResource.get_parameter`
|
||||
|
||||
parameters = self.custom_workload.get_parameters()
|
||||
self.assertTrue(isinstance(parameters, Dict))
|
||||
self.assertEquals(2, len(parameters))
|
||||
|
||||
self.assertTrue("binary" in parameters)
|
||||
self.assertTrue(isinstance(parameters["binary"], Resource))
|
||||
|
||||
self.assertTrue("arguments" in parameters)
|
||||
self.assertTrue(isinstance(parameters["arguments"], list))
|
||||
self.assertEquals(2, len(parameters["arguments"]))
|
||||
self.assertEquals("hello", parameters["arguments"][0])
|
||||
self.assertEquals(6, parameters["arguments"][1])
|
||||
|
||||
def test_add_parameters(self) -> None:
|
||||
# Tests `CustomResource.set_parameter` for the case where we add a new
|
||||
# parameter value.
|
||||
|
||||
self.custom_workload.set_parameter("test_param", 10)
|
||||
|
||||
self.assertTrue("test_param" in self.custom_workload.get_parameters())
|
||||
self.assertEquals(
|
||||
10, self.custom_workload.get_parameters()["test_param"]
|
||||
)
|
||||
|
||||
# Cleanup
|
||||
del self.custom_workload.get_parameters()["test_param"]
|
||||
|
||||
def test_override_parameter(self) -> None:
|
||||
# Tests `CustomResource.set_parameter` for the case where we override
|
||||
# a parameter's value.
|
||||
|
||||
old_value = self.custom_workload.get_parameters()["binary"]
|
||||
|
||||
self.custom_workload.set_parameter("binary", "test")
|
||||
self.assertTrue("binary" in self.custom_workload.get_parameters())
|
||||
self.assertEquals(
|
||||
"test", self.custom_workload.get_parameters()["binary"]
|
||||
)
|
||||
|
||||
# We set the overridden parameter back to it's old value.
|
||||
self.custom_workload.set_parameter("binary", old_value)
|
||||
|
||||
|
||||
class WorkloadTestSuite(unittest.TestCase):
|
||||
"""
|
||||
Tests the `gem5.resources.workload.Workload` class.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# In this constructor we create a json file to load then create a test
|
||||
# workload.
|
||||
|
||||
file_contents = (
|
||||
"{"
|
||||
+ f'"version" : "{_resources_json_version_required()}",'
|
||||
+ """
|
||||
"url_base" : "http://dist.gem5.org/dist/v22-0",
|
||||
"previous-versions" : {},
|
||||
"resources": [
|
||||
{
|
||||
"type" : "resource",
|
||||
"name" : "x86-linux-kernel-5.2.3",
|
||||
"documentation" : "The linux kernel (v5.2.3), compiled to X86.",
|
||||
"architecture" : "X86",
|
||||
"is_zipped" : false,
|
||||
"md5sum" : "4838c99b77d33c8307b939c16624e4ac",
|
||||
"url" : "{url_base}/kernels/x86/static/vmlinux-5.2.3",
|
||||
"source" : "src/linux-kernel"
|
||||
},
|
||||
{
|
||||
"type" : "resource",
|
||||
"name" : "x86-ubuntu-18.04-img",
|
||||
"documentation" : "A disk image containing Ubuntu 18.04 for x86..",
|
||||
"architecture" : "X86",
|
||||
"is_zipped" : true,
|
||||
"md5sum" : "90e363abf0ddf22eefa2c7c5c9391c49",
|
||||
"url" : "{url_base}/images/x86/ubuntu-18-04/x86-ubuntu.img.gz",
|
||||
"source" : "src/x86-ubuntu",
|
||||
"additional_metadata" : {
|
||||
"root_partition": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type" : "workload",
|
||||
"name" : "simple-boot",
|
||||
"documentation" : "Description of workload here",
|
||||
"function" : "set_kernel_disk_workload",
|
||||
"resources" : {
|
||||
"kernel" : "x86-linux-kernel-5.2.3",
|
||||
"disk_image" : "x86-ubuntu-18.04-img"
|
||||
},
|
||||
"additional_params" : {
|
||||
"readfile_contents" : "echo 'Boot successful'; m5 exit"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
)
|
||||
file = tempfile.NamedTemporaryFile(mode="w", delete=False)
|
||||
file.write(file_contents)
|
||||
file.close()
|
||||
|
||||
cls.test_json = file.name
|
||||
os.environ["GEM5_RESOURCE_JSON"] = cls.test_json
|
||||
cls.workload = Workload("simple-boot")
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
# Remove the test json file and unset the environment variable so this
|
||||
# test does not interfere with others.
|
||||
os.remove(cls.test_json)
|
||||
os.environ["GEM5_RESOURCE_JSON"]
|
||||
|
||||
def test_get_function_str(self) -> None:
|
||||
# Tests `Resource.get_function_str`
|
||||
|
||||
self.assertEquals(
|
||||
"set_kernel_disk_workload", self.workload.get_function_str()
|
||||
)
|
||||
|
||||
def test_get_parameters(self) -> None:
|
||||
# Tests `Resource.get_parameters`
|
||||
|
||||
parameters = self.workload.get_parameters()
|
||||
|
||||
self.assertTrue(isinstance(parameters, Dict))
|
||||
self.assertEqual(3, len(parameters))
|
||||
|
||||
self.assertTrue("kernel" in parameters)
|
||||
self.assertTrue(isinstance(parameters["kernel"], Resource))
|
||||
|
||||
self.assertTrue("disk_image" in parameters)
|
||||
self.assertTrue(isinstance(parameters["disk_image"], Resource))
|
||||
|
||||
self.assertTrue("readfile_contents" in parameters)
|
||||
self.assertTrue(
|
||||
"echo 'Boot successful'; m5 exit", parameters["readfile_contents"]
|
||||
)
|
||||
|
||||
def test_add_parameters(self) -> None:
|
||||
# Tests `Resource.set_parameter` for the case where we add a new
|
||||
# parameter value.
|
||||
|
||||
self.workload.set_parameter("test_param", 10)
|
||||
|
||||
self.assertTrue("test_param" in self.workload.get_parameters())
|
||||
self.assertEquals(10, self.workload.get_parameters()["test_param"])
|
||||
|
||||
# Cleanup
|
||||
del self.workload.get_parameters()["test_param"]
|
||||
|
||||
def test_override_parameter(self) -> None:
|
||||
# Tests `Resource.set_parameter` for the case where we override
|
||||
# a parameter's value.
|
||||
|
||||
old_value = self.workload.get_parameters()["readfile_contents"]
|
||||
|
||||
self.workload.set_parameter("readfile_contents", "test")
|
||||
self.assertTrue("readfile_contents" in self.workload.get_parameters())
|
||||
self.assertEquals(
|
||||
"test", self.workload.get_parameters()["readfile_contents"]
|
||||
)
|
||||
|
||||
# We set the overridden parameter back to it's old value.
|
||||
self.workload.set_parameter("readfile_contents", old_value)
|
||||
Reference in New Issue
Block a user