| # Copyright (c) 2021 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 components_library.processors.simple_core import SimpleCore |
| from components_library.processors.abstract_core import AbstractCore |
| import m5 |
| |
| from typing import Dict, Any, List |
| |
| from .abstract_processor import AbstractProcessor |
| from ..boards.abstract_board import AbstractBoard |
| from ..utils.override import * |
| |
| |
| class SwitchableProcessor(AbstractProcessor): |
| """ |
| This class can be used to setup a switchable processor/processors on a |
| system. |
| |
| Though this class can be used directly, it is best inherited from. See |
| "SimpleSwitchableCPU" for an example of this. |
| """ |
| |
| def __init__( |
| self, |
| switchable_cores: Dict[Any, List[SimpleCore]], |
| starting_cores: Any, |
| ) -> None: |
| |
| if starting_cores not in switchable_cores.keys(): |
| raise AssertionError( |
| f"Key {starting_cores} cannot be found in the " |
| "switchable_processors dictionary." |
| ) |
| |
| self._current_cores = switchable_cores[starting_cores] |
| self._switchable_cores = switchable_cores |
| |
| all_cores = [] |
| for core_list in self._switchable_cores.values(): |
| for core in core_list: |
| core.set_switched_out(core not in self._current_cores) |
| all_cores.append(core) |
| |
| super(SwitchableProcessor, self).__init__(cores=all_cores) |
| |
| @overrides(AbstractProcessor) |
| def incorporate_processor(self, board: AbstractBoard) -> None: |
| |
| # This is a bit of a hack. The `m5.switchCpus` function, used in the |
| # "switch_to_processor" function, requires the System simobject as an |
| # argument. We therefore need to store the board when incorporating the |
| # procsesor |
| self._board = board |
| |
| @overrides(AbstractProcessor) |
| def get_num_cores(self) -> int: |
| # Note: This is a special case where the total number of cores in the |
| # design is not the number of cores, due to some being switched out. |
| return len(self._current_cores) |
| |
| @overrides(AbstractProcessor) |
| def get_cores(self) -> List[AbstractCore]: |
| return self._current_cores |
| |
| def switch_to_processor(self, switchable_core_key: Any): |
| |
| # Run various checks. |
| if not hasattr(self, "_board"): |
| raise AssertionError("The processor has not been incorporated.") |
| |
| if switchable_core_key not in self._switchable_cores.keys(): |
| raise AssertionError( |
| f"Key {switchable_core_key} is not a key in the" |
| " switchable_processor dictionary." |
| ) |
| |
| # Select the correct processor to switch to. |
| to_switch = self._switchable_cores[switchable_core_key] |
| |
| # Run more checks. |
| if to_switch == self._current_cores: |
| raise AssertionError( |
| "Cannot swap current cores with the current cores" |
| ) |
| |
| if len(to_switch) != len(self._current_cores): |
| raise AssertionError( |
| "The number of cores to swap in is not the same as the number " |
| "already swapped in. This is not allowed." |
| ) |
| |
| current_core_simobj = [ |
| core.get_simobject() for core in self._current_cores |
| ] |
| to_switch_simobj = [core.get_simobject() for core in to_switch] |
| |
| # Switch the CPUs |
| m5.switchCpus( |
| self._board, |
| list(zip(current_core_simobj, to_switch_simobj)), |
| ) |
| |
| # Ensure the current processor is updated. |
| self._current_cores = to_switch |