# 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