Zhantong Qiu has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/64893?usp=email )

Change subject: stdlib: Added stdlib LoopPoint classes
......................................................................

stdlib: Added stdlib LoopPoint classes

The stdlib LoopPoint classes have to work with the LoopPoint probes and
the LoopPointManger. They are all added for running the LoopPoint
sampling method.
The stdlib LoopPoint has three classes, an abstract class and two
subclasses.
The LoopPointRestore is responsible for profiling restoring points.
The LoopPointCheckpoint is responsible for profiling checkpoints.
The BaseLoopPoint stores the general information and setup the
LoopPointManager and the LoopPoint probes to the cores.

Change-Id: I37b101efab6e801ec66eef8e0a93a508d4e5bc62
---
M src/python/SConscript
M src/python/gem5/components/processors/abstract_core.py
M src/python/gem5/components/processors/base_cpu_core.py
A src/python/gem5/utils/looppoint.py
4 files changed, 325 insertions(+), 0 deletions(-)



diff --git a/src/python/SConscript b/src/python/SConscript
index cbf88c9..bc1887a 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -217,6 +217,7 @@
 PySource('gem5.components.processors',
     'gem5/components/processors/switchable_processor.py')
 PySource('gem5.utils', 'gem5/utils/simpoint.py')
+PySource('gem5.utils', 'gem5/utils/looppoint.py')
 PySource('gem5.components.processors',
     'gem5/components/processors/traffic_generator_core.py')
 PySource('gem5.components.processors',
diff --git a/src/python/gem5/components/processors/abstract_core.py b/src/python/gem5/components/processors/abstract_core.py
index 70335c3..5db4c03 100644
--- a/src/python/gem5/components/processors/abstract_core.py
+++ b/src/python/gem5/components/processors/abstract_core.py
@@ -27,9 +27,12 @@
 from abc import ABCMeta, abstractmethod
 from typing import Optional, List

+from m5.params import UInt64
+
 from ...isas import ISA

 from m5.objects import BaseMMU, Port, SubSystem
+from m5.objects.LoopPointManager import LoopPointManager


 class AbstractCore(SubSystem):
@@ -148,3 +151,11 @@
         simulation
         """
raise NotImplementedError("This core type does not support MAX_INSTS")
+
+    @abstractmethod
+ def addLoopPointProbe(self, targetpc, manager: LoopPointManager) -> None:
+        """Add a LoopPoint to the core
+        :param targetpc: a list of target PC for the LoopPoint
+        :param manager: the LoopPointManager object
+        """
+        raise NotImplementedError
diff --git a/src/python/gem5/components/processors/base_cpu_core.py b/src/python/gem5/components/processors/base_cpu_core.py
index 7f77ad5..9551952 100644
--- a/src/python/gem5/components/processors/base_cpu_core.py
+++ b/src/python/gem5/components/processors/base_cpu_core.py
@@ -25,6 +25,8 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 from typing import Optional, List
+
+from m5.params import UInt64
 from ...utils.requires import requires
 from .abstract_core import AbstractCore

@@ -35,6 +37,9 @@

 from m5.objects import BaseMMU, Port, BaseCPU, Process

+from m5.objects.LoopPointManager import LoopPointManager
+from m5.objects.LoopPoint import LoopPoint
+

 class BaseCPUCore(AbstractCore):
     """
@@ -165,3 +170,13 @@
             self.core.max_insts_any_thread = inst
         else:
             self.core.scheduleInstStopAnyThread(inst)
+
+    @overrides(AbstractCore)
+    def addLoopPointProbe(
+        self, targetpc: List[AbstractCore], manager: LoopPointManager
+    ) -> None:
+        looppoint = LoopPoint()
+        looppoint.target_pc = targetpc
+        looppoint.core = self.core
+        looppoint.lpmanager = manager
+        self.core.probeListener = looppoint
diff --git a/src/python/gem5/utils/looppoint.py b/src/python/gem5/utils/looppoint.py
new file mode 100644
index 0000000..c74b9ee
--- /dev/null
+++ b/src/python/gem5/utils/looppoint.py
@@ -0,0 +1,279 @@
+# 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
+from gem5.components.processors.abstract_core import AbstractCore
+from m5.objects.LoopPointManager import LoopPointManager
+import csv
+import re
+from abc import ABCMeta
+
+
+class BaseLoopPoint:
+    """
+    A stdlib LoopPoint object that contains the information gather from the
+    input files and use a LoopPointManager to connect them with the cores.
+    """
+
+    __metaclass__ = ABCMeta
+
+    def __init__(
+        self,
+        checkpointPC: List[int],
+        checkpointCount: List[int],
+        relativePC: List[int],
+        relativeCount: List[int],
+        regionID: List[int],
+    ) -> None:
+        """Stores the LoopPoint related information
+
+        :param checkpointPC: A list of PC numbers that will raise an exit
+        event at.
+ :param checkpointCount: A list of targeting counts that will raise an
+        exit event at.
+        :param relativePC: A list of PC numbers that are related to the
+        checkpoint PC and needed for outputting relative PC counts for
+        restoring the LoopPoint checkpoints.
+ :param relativeCount: A list of targeting counts for the relativePC. It + is needed for outputing relative PC counts for restoring the LoopPoint
+        checkpoints.
+        :param reginID: The ID of the targeting region.
+        """
+
+        self._checkpointPC = checkpointPC
+        self._checkpointCount = checkpointCount
+        self._relativePC = relativePC
+        self._relativeCount = relativeCount
+        self._regionID = regionID
+
+        self._looppointManager = LoopPointManager()
+
+    def setup_cpu(
+        self,
+        cpuList: List[AbstractCore],
+    ) -> None:
+ """Setup LoopPointManager and connect LoopPoint probes with the cores
+        :param cpuList: A list of cores that will be used in the simulation
+        """
+        self._looppointManager.target_count = self._checkpointCount
+        self._looppointManager.target_pc = self._checkpointPC
+        self._looppointManager.region_id = self._regionID
+        self._looppointManager.relative_pc = self._relativePC
+        self._looppointManager.relative_count = self._relativeCount
+        self._looppointManager.setup(cpuList)
+
+    def get_checkpointPC(self):
+        return self._checkpointPC
+
+    def get_checkpointCount(self):
+        return self._checkpointCount
+
+    def get_relativePC(self):
+        return self._relativePC
+
+    def get_relativeCount(self):
+        return self._relativeCount
+
+
+class LoopPointsCheckpoint(BaseLoopPoint):
+    def __init__(self, LoopPointFilePath: Path) -> None:
+        """A subclass of BaseLoopPoint for profiling LoopPoint checkpoints
+ :param LoopPointFilePath: The path to the LoopPoint file that contains
+        all the LoopPoint region information
+        """
+
+        _checkpointPC = []
+        _checkpointCount = []
+        _relativePC = []
+        _relativeCount = []
+        _regionID = []
+        self.simulationRegion = dict()
+        self.warmupRegion = dict()
+        self.max_regionid = 0
+        self.profile_checkpoints(
+            LoopPointFilePath,
+            checkpointPC=_checkpointPC,
+            checkpointCount=_checkpointCount,
+            relativePC=_relativePC,
+            relativeCount=_relativeCount,
+            regionID=_regionID,
+        )
+        super().__init__(
+            checkpointPC=_checkpointPC,
+            checkpointCount=_checkpointCount,
+            relativePC=_relativePC,
+            relativeCount=_relativeCount,
+            regionID=_regionID,
+        )
+
+    def profile_checkpoints(
+        self,
+        looppoint_file_path: Path,
+        checkpointPC: List[int],
+        checkpointCount: List[int],
+        relativePC: List[int],
+        relativeCount: List[int],
+        regionID: List[int],
+    ) -> None:
+        """
+        Profile LoopPoint checkpoint information from the input file
+        """
+
+        # read information from the file
+        with open(looppoint_file_path, newline="") as csvfile:
+            spamreader = csv.reader(csvfile, delimiter=" ", quotechar="|")
+            for row in spamreader:
+                if len(row) > 1:
+                    if row[0] == "cluster":
+                        line = row[4].split(",")
+                        self.simulationRegion[line[2]] = [
+                            (line[3], line[6]),
+                            (line[7], line[10]),
+                        ]
+                        if self.max_regionid < int(line[2]):
+                            self.max_regionid = int(line[2])
+                    elif row[0] == "Warmup":
+                        line = row[3].split(",")
+                        self.warmupRegion[line[0]] = [
+                            (line[3], line[6]),
+                            (line[7], line[10]),
+                        ]
+
+        # Assign PC and its targeting counts to the corresponding lists
+        for id in range(1, self.max_regionid + 1):
+ # The LoopPoint region id might not be continuous, so it needs to + # check if the region id was recorded in the simulationRegion or
+            # not. If it was not, it means this region id is not valid.
+            if str(id) in self.simulationRegion:
+                regionID.append(id)
+                if str(id) in self.warmupRegion:
+                    # Check if this simulation region has a warmup region.
+ # If it does, use the PC and the starting count of the warm
+                    # up region as the checkpoint. The PC, starting
+ # count, and ending count of the simulation region will be
+                    # the relatives to the checkpoint.
+                    checkpointPC.append(self.warmupRegion[str(id)][0][0])
+ checkpointCount.append(self.warmupRegion[str(id)][0][1])
+                    relativePC.append(self.simulationRegion[str(id)][0][0])
+ relativeCount.append(self.simulationRegion[str(id)][0][1])
+                    relativePC.append(self.simulationRegion[str(id)][1][0])
+ relativeCount.append(self.simulationRegion[str(id)][1][1])
+                else:
+ # If the simulation region doesn't have a warmup region, + # then the PC and starting count of the simulation region + # will be the checkpoint. The PC and the ending count of
+                    # this simulation region will be the relatives of the
+                    # checkpoint.
+ checkpointPC.append(self.simulationRegion[str(id)][0][0])
+                    checkpointCount.append(
+                        self.simulationRegion[str(id)][0][1]
+                    )
+                    relativePC.append(self.simulationRegion[str(id)][1][0])
+ relativeCount.append(self.simulationRegion[str(id)][1][1])
+                    relativePC.append(0)
+                    relativeCount.append(-1)
+
+    def get_simulationRegion_dict(self):
+        return self.simulationRegion
+
+    def get_warmupRegion_dict(self):
+        return self.warmupRegion
+
+    def get_max_regionid(self):
+        return self.max_regionid
+
+
+class LoopPointsRestore(BaseLoopPoint):
+    def __init__(
+        self, LoopPointOutputFilePath: Path, CheckPointDir: Path
+    ) -> None:
+ """A subclass of BaseLoopPoint for profiling LoopPoint restoring point
+        :param LoopPointOutputFilePath: The path to the LoopPoint file
+        outputted from the checkpoint simulation that contains all the
+        information needed to restore a LoopPoint checkpoint.
+        :param CheckPointDir: The path to the checkpoint directory.
+        """
+
+        _checkpointPC = []
+        _checkpointCount = []
+        _regionID = []
+        self.profile_restore(
+            LoopPointOutputFilePath,
+            CheckPointDir,
+            checkpointPC=_checkpointPC,
+            checkpointCount=_checkpointCount,
+            regionID=_regionID,
+        )
+        super().__init__(
+            checkpointPC=_checkpointPC,
+            checkpointCount=_checkpointCount,
+            relativePC=[],
+            relativeCount=[],
+            regionID=_regionID,
+        )
+
+    def profile_restore(
+        self,
+        checkpoint_file_path: Path,
+        checkpoint_dir: Path,
+        checkpointPC: List[int],
+        checkpointCount: List[int],
+        regionID: List[int],
+    ) -> None:
+        """
+        Profile LoopPoint checkpoint information from the input file
+        """
+        regex = re.compile(r"cpt.([0-9]+)")
+ # The checkpoint directory is named by the simulation Tick it was at + # when the checkpoint was taken, so we can get the Tick number from the
+        # checkpoint directory name.
+        tick = regex.findall(checkpoint_dir.as_posix())[0]
+        with open(checkpoint_file_path) as file:
+            while True:
+                line = file.readline()
+                if not line:
+ # If the Tick number can't find a match in the output file + # it means the checkpoint and the output file doesn't match
+                    fatal("checkpoint tick not found in checkpoint file")
+                line = line.split(":")
+                print(f"split:{line}\n")
+                if line[0] == tick:
+ # If the Tick number is found, we can read the information
+                    # needed to setup the restoring point and ending point
+                    regionID.append(line[1])
+ # Because the simulation region might or might not have a + # warmup region, there might only be one targeting point.
+                    if len(line) > 6:
+                        checkpointPC.append(line[4])
+                        checkpointCount.append(line[5])
+                    if len(line) > 8:
+                        checkpointPC.append(line[6])
+                        checkpointCount.append(line[7])
+                    print(f"get target PC {checkpointPC}\n")
+                    print(f"get target PC count {checkpointCount}\n")
+                    break

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/64893?usp=email 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: I37b101efab6e801ec66eef8e0a93a508d4e5bc62
Gerrit-Change-Number: 64893
Gerrit-PatchSet: 1
Gerrit-Owner: Zhantong Qiu <zt...@ucdavis.edu>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org

Reply via email to