blob: 9e861cc0a5beb7d3f51268ad501177c053130216 [file] [log] [blame]
# 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 m5.util import fatal
from pathlib import Path
from typing import List, Tuple
from gem5.resources.resource import Resource, CustomResource
class SimPoint:
"""
This SimPoint class is used to manage the information needed for SimPoints
in workload
"""
def __init__(
self,
simpoint_resource: CustomResource = None,
simpoint_interval: int = None,
simpoint_file_path: Path = None,
weight_file_path: Path = None,
simpoint_list: List[int] = None,
weight_list: List[int] = None,
warmup_interval: int = 0,
) -> None:
"""
:param simpoint_interval: the length of each SimPoints interval
:param simpoint_file_path: the path to the SimPoints result file
generated by Simpoint3.2 or gem5
:param weight_file_path: the path to the weight result file generated
by Simpoint3.2 or gem5
:param simpoint_list: a list of SimPoints starting instructions
:param weight_list: a list of SimPoints weights
:param warmup_interval: a number of instructions for warming up before
restoring a SimPoints checkpoint
usage note
-----------
Need to pass in the paths or the lists for the SimPoints and their
weights. If the paths are passed in, no actions will be done to the
list.
When passing in simpoint_list and weight_list, passing in sorted lists
(sorted by SimPoints in ascending order) is strongly suggested.
The warmup_list only works correctly with sorted simpoint_list.
"""
# initalize input if you're passing in a CustomResource
if simpoint_resource is not None:
simpoint_directory = str(simpoint_resource.get_local_path())
simpoint_file_path = Path(simpoint_directory + "/simpoint.simpt")
weight_file_path = Path(simpoint_directory + "/simpoint.weight")
simpoint_interval = (
simpoint_resource.get_metadata()
.get("additional_metadata")
.get("simpoint_interval")
)
warmup_interval = (
simpoint_resource.get_metadata()
.get("additional_metadata")
.get("warmup_interval")
)
self._simpoint_interval = simpoint_interval
if simpoint_file_path is None or weight_file_path is None:
if simpoint_list is None or weight_list is None:
fatal(
"Please pass in file paths or lists for both simpoints "
"and weights."
)
else:
self._simpoint_start_insts = list(
inst * simpoint_interval for inst in simpoint_list
)
self._weight_list = weight_list
else:
# if passing in file paths then it calls the function to generate
# simpoint_start_insts and weight list from the files
(
self._simpoint_start_insts,
self._weight_list,
) = self.get_weights_and_simpoints_from_file(
simpoint_file_path, weight_file_path
)
if warmup_interval != 0:
self._warmup_list = self.set_warmup_intervals(warmup_interval)
else:
self._warmup_list = [0] * len(self._simpoint_start_insts)
def get_weights_and_simpoints_from_file(
self,
simpoint_path: Path,
weight_path: Path,
) -> Tuple[List[int], List[int]]:
"""
This function takes in file paths and outputs a list of SimPoints
instruction starts and a list of weights
"""
simpoint = []
with open(simpoint_path) as simpoint_file, open(
weight_path
) 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.append((interval, weight))
simpoint.sort(key=lambda obj: obj[0])
# use simpoint to sort
simpoint_start_insts = []
weight_list = []
for start, weight in simpoint:
simpoint_start_insts.append(start * self._simpoint_interval)
weight_list.append(weight)
return simpoint_start_insts, weight_list
def set_warmup_intervals(self, warmup_interval: int) -> List[int]:
"""
This function takes 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._simpoint_start_insts):
warmup_inst = start_inst - warmup_interval
if warmup_inst < 0:
warmup_inst = start_inst
else:
warmup_inst = 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
def get_simpoint_start_insts(self) -> List[int]:
return self._simpoint_start_insts
def get_weight_list(self) -> List[float]:
return self._weight_list
def get_simpoint_interval(self) -> int:
return self._simpoint_interval
def get_warmup_list(self) -> List[int]:
return self._warmup_list