diff --git a/pacman/data/pacman_data_view.py b/pacman/data/pacman_data_view.py index 588cc0a25..fa2a5138f 100644 --- a/pacman/data/pacman_data_view.py +++ b/pacman/data/pacman_data_view.py @@ -562,7 +562,7 @@ def get_all_monitor_sdram(cls) -> AbstractSDRAM: """ # Note the sdram can not be calculated in advance as some Vertices # require the hardware time step not available until simulator run - sdram = ConstantSDRAM(0) + sdram: AbstractSDRAM = ConstantSDRAM(0) for vertex in cls.__pacman_data._all_monitor_vertices: sdram += vertex.sdram_required return sdram @@ -580,7 +580,7 @@ def get_ethernet_monitor_sdram(cls) -> AbstractSDRAM: :rtype: AbstractSDRAM """ - sdram = ConstantSDRAM(0) + sdram: AbstractSDRAM = ConstantSDRAM(0) for vertex in cls.__pacman_data._ethernet_monitor_vertices: sdram += vertex.sdram_required return sdram diff --git a/pacman/model/resources/__init__.py b/pacman/model/resources/__init__.py index c761aae5d..43d0a6796 100644 --- a/pacman/model/resources/__init__.py +++ b/pacman/model/resources/__init__.py @@ -17,8 +17,9 @@ from .iptag_resource import IPtagResource from .multi_region_sdram import MultiRegionSDRAM from .reverse_iptag_resource import ReverseIPtagResource +from .shared_sdram import SharedSDRAM from .variable_sdram import VariableSDRAM __all__ = ["AbstractSDRAM", "ConstantSDRAM", "IPtagResource", "MultiRegionSDRAM", - "ReverseIPtagResource", "VariableSDRAM"] + "ReverseIPtagResource", "SharedSDRAM", "VariableSDRAM"] diff --git a/pacman/model/resources/abstract_sdram.py b/pacman/model/resources/abstract_sdram.py index d605acda5..06db3ad3c 100644 --- a/pacman/model/resources/abstract_sdram.py +++ b/pacman/model/resources/abstract_sdram.py @@ -43,28 +43,6 @@ def __add__(self, other: AbstractSDRAM) -> AbstractSDRAM: """ raise NotImplementedError - @abstractmethod - def __sub__(self, other: AbstractSDRAM) -> AbstractSDRAM: - """ - Creates a new SDRAM which is this one less the other. - - :param AbstractSDRAM other: another SDRAM resource - :return: a New AbstractSDRAM - :rtype: AbstractSDRAM - """ - raise NotImplementedError - - @abstractmethod - def sub_from(self, other: AbstractSDRAM) -> AbstractSDRAM: - """ - Creates a new SDRAM which is the other less this one. - - :param AbstractSDRAM other: another SDRAM resource - :return: a New AbstractSDRAM - :rtype: AbstractSDRAM - """ - raise NotImplementedError - @property @abstractmethod def fixed(self) -> int: @@ -84,12 +62,9 @@ def per_timestep(self) -> float: """ raise NotImplementedError + @abstractmethod def __eq__(self, other: Any) -> bool: - if not isinstance(other, AbstractSDRAM): - return False - if other.fixed != self.fixed: - return False - return other.per_timestep == self.per_timestep + raise NotImplementedError @abstractmethod def report(self, timesteps: Optional[int], indent: str = "", @@ -105,3 +80,16 @@ def report(self, timesteps: Optional[int], indent: str = "", ``None`` is standard print """ raise NotImplementedError + + @property + @abstractmethod + def short_str(self) -> str: + """ + A short string representation of this SDRAM. + + To be used within main str methods + """ + raise NotImplementedError + + def __str__(self): + return f"SDRAM:{self.short_str}" diff --git a/pacman/model/resources/constant_sdram.py b/pacman/model/resources/constant_sdram.py index b89cbaea2..b05006f6f 100644 --- a/pacman/model/resources/constant_sdram.py +++ b/pacman/model/resources/constant_sdram.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, TextIO +from typing import Any, Optional, TextIO from spinn_utilities.overrides import overrides from .abstract_sdram import AbstractSDRAM @@ -49,7 +49,12 @@ def fixed(self) -> int: def per_timestep(self) -> float: return 0 - def __add__(self, other): + def __eq__(self, other: Any) -> bool: + if not isinstance(other, ConstantSDRAM): + return False + return other.fixed == self.fixed + + def __add__(self, other: AbstractSDRAM) -> AbstractSDRAM: if isinstance(other, ConstantSDRAM): return ConstantSDRAM( self._sdram + other.fixed) @@ -57,24 +62,12 @@ def __add__(self, other): # The other is more complex so delegate to it return other.__add__(self) - def __sub__(self, other): - if isinstance(other, ConstantSDRAM): - return ConstantSDRAM( - self._sdram - other.fixed) - else: - # The other is more complex so delegate to it - return other.sub_from(self) - - @overrides(AbstractSDRAM.sub_from) - def sub_from(self, other: AbstractSDRAM) -> AbstractSDRAM: - if isinstance(other, ConstantSDRAM): - return ConstantSDRAM( - other.fixed - self._sdram) - else: - # The other is more complex so delegate to it - return other - self - @overrides(AbstractSDRAM.report) def report(self, timesteps: Optional[int], indent: str = "", preamble: str = "", target: Optional[TextIO] = None): print(indent, preamble, f"Constant {self._sdram} bytes", file=target) + + @property + @overrides(AbstractSDRAM.short_str) + def short_str(self) -> str: + return f"fixed: {self._sdram}" diff --git a/pacman/model/resources/multi_region_sdram.py b/pacman/model/resources/multi_region_sdram.py index 4c546fcc7..89a022412 100644 --- a/pacman/model/resources/multi_region_sdram.py +++ b/pacman/model/resources/multi_region_sdram.py @@ -14,7 +14,7 @@ from __future__ import annotations from enum import Enum import math -from typing import Dict, Optional, TextIO, Union +from typing import Any, Dict, Optional, TextIO, Union import numpy from typing_extensions import TypeAlias @@ -33,7 +33,7 @@ def _ceil(value: _Value) -> int: return math.ceil(value) -class MultiRegionSDRAM(VariableSDRAM): +class MultiRegionSDRAM(AbstractSDRAM): """ A resource for SDRAM that comes in regions. @@ -48,16 +48,18 @@ class MultiRegionSDRAM(VariableSDRAM): __slots__ = ( # The regions of SDRAM, each of which is an AbstractSDRAM - "__regions", ) + "__regions", + # The total cost of all the regions + "_total") def __init__(self) -> None: - super().__init__(0, 0) self.__regions: Dict[_RegionKey, AbstractSDRAM] = {} + self._total: AbstractSDRAM = ConstantSDRAM(0) @property def regions(self): """ - The map from region identifiers to the to the amount of SDRAM required. + The map from region identifiers to the amount of SDRAM required. :rtype: dict(int or str or enum, AbstractSDRAM) """ @@ -75,18 +77,11 @@ def add_cost(self, region: _RegionKey, fixed_sdram: _Value, :param per_timestep_sdram: The variable cost for this region is any :type per_timestep_sdram: int or numpy.integer """ - self._fixed_sdram += _ceil(fixed_sdram) - self._per_timestep_sdram += _ceil(per_timestep_sdram) - sdram: AbstractSDRAM if per_timestep_sdram: - sdram = VariableSDRAM( - _ceil(fixed_sdram), _ceil(per_timestep_sdram)) + self.nest(region, VariableSDRAM( + _ceil(fixed_sdram), _ceil(per_timestep_sdram))) else: - sdram = ConstantSDRAM(_ceil(fixed_sdram)) - if region in self.__regions: - self.__regions[region] += sdram - else: - self.__regions[region] = sdram + self.nest(region, ConstantSDRAM(_ceil(fixed_sdram))) def nest(self, region: _RegionKey, other: AbstractSDRAM): """ @@ -102,15 +97,14 @@ def nest(self, region: _RegionKey, other: AbstractSDRAM): :param AbstractSDRAM other: Another SDRAM model to make combine by nesting """ - self._fixed_sdram += other.fixed - self._per_timestep_sdram += other.per_timestep + self._total += other if region in self.__regions: if isinstance(other, MultiRegionSDRAM): r = self.__regions[region] if isinstance(r, MultiRegionSDRAM): r.merge(other) else: - other.add_cost(region, r.fixed, r.per_timestep) + other.nest(region, r) self.__regions[region] = other else: self.__regions[region] += other @@ -127,8 +121,7 @@ def merge(self, other: MultiRegionSDRAM): :param MultiRegionSDRAM other: Another mapping of costs by region """ - self._fixed_sdram += other.fixed - self._per_timestep_sdram += other.per_timestep + self._total += other for region in other.regions: if region in self.regions: self.__regions[region] += other.regions[region] @@ -138,7 +131,52 @@ def merge(self, other: MultiRegionSDRAM): @overrides(AbstractSDRAM.report) def report(self, timesteps: Optional[int], indent: str = "", preamble: str = "", target: Optional[TextIO] = None): - super().report(timesteps, indent, preamble, target) + self._total.report(timesteps, indent, preamble, target) for region in self.__regions: self.__regions[region].report( timesteps, indent+" ", str(region)+":", target) + + def get_total_sdram(self, n_timesteps: Optional[int]) -> int: + """ + The total SDRAM. + + :param int n_timesteps: number of timesteps to cost for + :return: + """ + return self._total.get_total_sdram(n_timesteps) + + def __eq__(self, other: Any) -> bool: + if isinstance(other, MultiRegionSDRAM): + return self._total == other._total + return self._total == other + + def __add__(self, other: AbstractSDRAM) -> AbstractSDRAM: + """ + Combines this SDRAM resource with the other one and creates a new one. + + :param other: another SDRAM resource + :return: a New AbstractSDRAM + """ + return self._total + other + + @property + def fixed(self) -> int: + """ + The fixed SDRAM cost. + """ + return self._total.fixed + + @property + def per_timestep(self) -> float: + """ + The extra SDRAM cost for each additional timestep. + + .. warning:: + May well be zero. + """ + return self._total.per_timestep + + @property + @overrides(AbstractSDRAM.short_str) + def short_str(self) -> str: + return f"Multi:{self._total.short_str}" diff --git a/pacman/model/resources/shared_sdram.py b/pacman/model/resources/shared_sdram.py new file mode 100644 index 000000000..23966c5c7 --- /dev/null +++ b/pacman/model/resources/shared_sdram.py @@ -0,0 +1,136 @@ +# Copyright (c) 2017 The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math +from typing import Any, Dict, Optional, TextIO, Union + +import numpy + +from spinn_utilities.overrides import overrides +from pacman.exceptions import PacmanConfigurationException +from .abstract_sdram import AbstractSDRAM +from .constant_sdram import ConstantSDRAM +from .variable_sdram import VariableSDRAM + + +def _ceil(value: Union[int, float, numpy.integer, numpy.floating]) -> int: + return math.ceil(value) + + +class SharedSDRAM(AbstractSDRAM): + """ + Represents an amount of SDRAM used on a chip in the machine. + + This is split into cost for each core and ones for each chip + """ + + __slots__ = ( + # The amount of SDRAM per core + "_per_core", + # Map of extra shared SDRAM per Chip + "_shared" + ) + + def __init__(self, shared: Dict[str, AbstractSDRAM], + per_core: Optional[AbstractSDRAM] = None) -> None: + """ + Creates an SDRAM of both per_core and shared requirements. + + .. note:: + Each key must map GLOBALLY to the same SDRAM (or an equal one) + It is recommended that a vertex use its label at the start the key + + :param shared: + The sdram that will be allocated ONCE per Chip + This is a dict of keys to sdram + :param per_core: + The amount of SDRAM that will be needed on every core. + """ + # create a shallow copy + self._shared = shared.copy() + if per_core is None: + self._per_core: AbstractSDRAM = ConstantSDRAM(0) + else: + self._per_core = per_core + + @overrides(AbstractSDRAM.get_total_sdram) + def get_total_sdram(self, n_timesteps: Optional[int]) -> int: + running = self._per_core.get_total_sdram(n_timesteps) + for sdram in self._shared.values(): + running += sdram.get_total_sdram(n_timesteps) + return running + + @property + @overrides(AbstractSDRAM.fixed) + def fixed(self) -> int: + running = self._per_core.fixed + for sdram in self._shared.values(): + running += sdram.fixed + return running + + @property + @overrides(AbstractSDRAM.per_timestep) + def per_timestep(self) -> float: + running = self._per_core.per_timestep + for sdram in self._shared.values(): + running += sdram.per_timestep + return running + + @overrides(AbstractSDRAM.__eq__) + def __eq__(self, other: Any) -> bool: + if not isinstance(other, SharedSDRAM): + return False + if self._per_core != other._per_core: + return False + return self._shared == other._shared + + @overrides(AbstractSDRAM.__add__) + def __add__(self, other: AbstractSDRAM) -> AbstractSDRAM: + if isinstance(other, (ConstantSDRAM, VariableSDRAM)): + return SharedSDRAM(self._shared, self._per_core + other) + elif isinstance(other, SharedSDRAM): + shared = self._shared.copy() + for key, value in other._shared.items(): + if key in shared: + if value != shared[key]: + raise PacmanConfigurationException( + f"Shared {key} has different values") + else: + shared[key] = value + return SharedSDRAM(shared, self._per_core) + else: + # MultiRegionSDRAM + return other + self + + @overrides(AbstractSDRAM.report) + def report(self, timesteps: Optional[int], indent: str = "", + preamble: str = "", target: Optional[TextIO] = None): + self._per_core.report(timesteps, indent, preamble, target) + for key, sdram in self._shared.items(): + sdram.report(timesteps, indent+" ", key+":", target) + + @property + @overrides(AbstractSDRAM.short_str) + def short_str(self) -> str: + if self._per_core.fixed > 0 or self._per_core.per_timestep > 0: + per_core = f"per-core: {self._per_core.short_str} " + else: + per_core = "" + shared = "" + for key, sdram in self._shared.items(): + if shared == "": + shared = f"shared:{key}: {sdram.short_str}" + else: + shared = f" {key}: {sdram.short_str}" + return per_core + shared diff --git a/pacman/model/resources/variable_sdram.py b/pacman/model/resources/variable_sdram.py index 0dc1419b3..ed874e3da 100644 --- a/pacman/model/resources/variable_sdram.py +++ b/pacman/model/resources/variable_sdram.py @@ -13,13 +13,14 @@ # limitations under the License. import math -from typing import Optional, TextIO, Union +from typing import Any, Optional, TextIO, Union import numpy from spinn_utilities.overrides import overrides from pacman.exceptions import PacmanConfigurationException from .abstract_sdram import AbstractSDRAM +from .constant_sdram import ConstantSDRAM def _ceil(value: Union[int, float, numpy.integer, numpy.floating]) -> int: @@ -72,21 +73,31 @@ def fixed(self) -> int: def per_timestep(self) -> float: return self._per_timestep_sdram - def __add__(self, other: AbstractSDRAM) -> 'VariableSDRAM': - return VariableSDRAM( - self._fixed_sdram + other.fixed, - self._per_timestep_sdram + other.per_timestep) - - def __sub__(self, other: AbstractSDRAM) -> 'VariableSDRAM': - return VariableSDRAM( - self._fixed_sdram - other.fixed, - self._per_timestep_sdram - other.per_timestep) - - @overrides(AbstractSDRAM.sub_from) - def sub_from(self, other: AbstractSDRAM) -> 'VariableSDRAM': - return VariableSDRAM( - other.fixed - self._fixed_sdram, - other.per_timestep - self._per_timestep_sdram) + def __eq__(self, other: Any) -> bool: + if isinstance(other, VariableSDRAM): + if other.fixed != self.fixed: + return False + else: + return other.per_timestep == self.per_timestep + elif isinstance(other, ConstantSDRAM): + if self._per_timestep_sdram != 0: + return False + else: + return other.fixed == self.fixed + else: + return False + + def __add__(self, other: AbstractSDRAM) -> AbstractSDRAM: + if isinstance(other, ConstantSDRAM): + return VariableSDRAM( + self._fixed_sdram + other.fixed, self._per_timestep_sdram) + elif isinstance(other, VariableSDRAM): + return VariableSDRAM( + self._fixed_sdram + other.fixed, + self._per_timestep_sdram + other.per_timestep) + else: + # SharedSDRAM, MultiRegionSDRAM + return other + self @overrides(AbstractSDRAM.report) def report(self, timesteps: Optional[int], indent: str = "", @@ -95,3 +106,9 @@ def report(self, timesteps: Optional[int], indent: str = "", f"Fixed {self._fixed_sdram} bytes " f"Per_timestep {self._per_timestep_sdram} bytes " f"for a total of {self.get_total_sdram(timesteps)}", file=target) + + @property + @overrides(AbstractSDRAM.short_str) + def short_str(self) -> str: + return (f"fixed:{self._fixed_sdram} " + f"per_timestep:{self._per_timestep_sdram}") diff --git a/pacman/utilities/json_utils.py b/pacman/utilities/json_utils.py index c69794c90..e59f1a186 100644 --- a/pacman/utilities/json_utils.py +++ b/pacman/utilities/json_utils.py @@ -22,10 +22,10 @@ from spinn_utilities.typing.json import JsonArray, JsonObject from pacman.data import PacmanDataView -from pacman.model.graphs.machine import MachineVertex, SimpleMachineVertex +from pacman.model.graphs.machine import SimpleMachineVertex from pacman.model.placements.placement import Placement from pacman.model.resources import ( - IPtagResource, ReverseIPtagResource, VariableSDRAM) + IPtagResource, ReverseIPtagResource) from pacman.model.routing_info import BaseKeyAndMask @@ -185,47 +185,6 @@ def reverse_iptags_from_json( return iptags -def vertex_to_json(vertex: MachineVertex) -> JsonObject: - """ - Converts a Machine Vertex to json. - - :param MachineVertex vertex: - :rtype: dict(str, object) - """ - json_dict: JsonObject = dict() - try: - json_dict["class"] = vertex.__class__.__name__ - json_dict["label"] = vertex.label - json_dict["fixed_sdram"] = int(vertex.sdram_required.fixed) - json_dict["per_timestep_sdram"] = int( - vertex.sdram_required.per_timestep) - json_dict["iptags"] = iptag_resources_to_json(vertex.iptags) - json_dict["reverse_iptags"] = reverse_iptags_to_json( - vertex.reverse_iptags) - except Exception as ex: # pylint: disable=broad-except - json_dict["exception"] = str(ex) - return json_dict - - -def vertex_from_json(json_dict: JsonObject) -> SimpleMachineVertex: - """ - Creates a simple Vertex based on the json - - :param dict(str, object) json_dict: - :rtype: SimpleMachineVertex - """ - sdram = VariableSDRAM( - cast(int, json_dict["fixed_sdram"]), - cast(float, json_dict["per_timestep_sdram"])) - iptags = iptag_resources_from_json( - cast(List[JsonObject], json_dict["iptags"])) - reverse_iptags = reverse_iptags_from_json( - cast(List[JsonObject], json_dict["reverse_iptags"])) - return SimpleMachineVertex( - sdram=sdram, label=json_dict["label"], iptags=iptags, - reverse_iptags=reverse_iptags) - - def placement_to_json(placement: Placement) -> JsonObject: """ Converts a Placement to json diff --git a/unittests/model_tests/resources_tests/test_resources_model.py b/unittests/model_tests/resources_tests/test_resources_model.py index 825b5fd56..22f511969 100644 --- a/unittests/model_tests/resources_tests/test_resources_model.py +++ b/unittests/model_tests/resources_tests/test_resources_model.py @@ -22,7 +22,7 @@ from pacman.exceptions import PacmanConfigurationException from pacman.model.resources import ( ConstantSDRAM, IPtagResource, MultiRegionSDRAM, ReverseIPtagResource, - VariableSDRAM) + SharedSDRAM, VariableSDRAM) class MockEnum(Enum): @@ -48,28 +48,18 @@ def test_sdram(self): const2 = ConstantSDRAM(256) combo = const1 + const2 self.assertEqual(combo.get_total_sdram(None), 128+256) - combo = const1 - const2 - self.assertEqual(combo.get_total_sdram(None), 128-256) combo = const2 + const1 self.assertEqual(combo.get_total_sdram(None), 256+128) - combo = const2 - const1 - self.assertEqual(combo.get_total_sdram(None), 256-128) var1 = VariableSDRAM(124, 8) self.assertEqual(var1.get_total_sdram(100), 124 + 8 * 100) combo = var1 + const1 self.assertEqual(combo.get_total_sdram(100), 124 + 8 * 100 + 128) - combo = var1 - const1 - self.assertEqual(combo.get_total_sdram(100), 124 + 8 * 100 - 128) combo = const1 + var1 self.assertEqual(combo.get_total_sdram(100), 128 + 124 + 8 * 100) - combo = const1 - var1 - self.assertEqual(combo.get_total_sdram(100), 128 - (124 + 8 * 100)) var2 = VariableSDRAM(234, 6) combo = var2 + var1 self.assertEqual(combo.get_total_sdram(150), 234 + 124 + (6 + 8) * 150) - combo = var2 - var1 - self.assertEqual(combo.get_total_sdram(150), 234 - 124 + (6 - 8) * 150) multi1 = MultiRegionSDRAM() multi1.add_cost(1, 100, 4) @@ -154,16 +144,6 @@ def test_tags_resources(self): self.assertEqual(riptr, riptr2) self.assertEqual(hash(riptr), hash(riptr2)) - def test_sub(self): - const1 = ConstantSDRAM(128) - const2 = ConstantSDRAM(28) - self.assertEqual(ConstantSDRAM(100), const1 - const2) - self.assertEqual(ConstantSDRAM(100), const2.sub_from(const1)) - var1 = VariableSDRAM(100, 5) - self.assertEqual(VariableSDRAM(28, -5), const1 - var1) - self.assertEqual(VariableSDRAM(-28, 5), var1 - const1) - self.assertEqual(VariableSDRAM(-28, 5), const1.sub_from(var1)) - def test_total(self): var0 = VariableSDRAM(28, 0) self.assertEqual(28, var0.get_total_sdram(None)) @@ -171,6 +151,81 @@ def test_total(self): with self.assertRaises(PacmanConfigurationException): var4.get_total_sdram(None) + def test_shared(self): + var1 = VariableSDRAM(20, 1) + sh1 = SharedSDRAM({"foo": var1}) + sh1.report(10) + str(sh1) + self.assertEqual(sh1.get_total_sdram(5), 25) + combo1 = sh1 + sh1 + self.assertEqual(combo1.get_total_sdram(5), 25) + self.assertEqual(combo1, sh1) + combo2 = var1 + var1 + self.assertEqual(combo2.get_total_sdram(5), 50) + con1 = ConstantSDRAM(12) + combo3 = sh1 + con1 + self.assertEqual(combo3.get_total_sdram(5), 37) + combo4 = con1 + sh1 + self.assertEqual(combo4.get_total_sdram(5), 37) + self.assertEqual(combo3, combo4) + + def test_sdram_multi(self): + multi1 = MultiRegionSDRAM() + multi1.add_cost(1, 100, 4) + sh1 = SharedSDRAM({"foo": multi1}) + self.assertEqual(sh1.get_total_sdram(10), 100 + 4 * 10) + + multi2 = MultiRegionSDRAM() + var2 = VariableSDRAM(20, 1) + sh2 = SharedSDRAM({"bar": var2}) + multi2.nest(2, sh2) + self.assertEqual(multi2.get_total_sdram(10), 20 + 10) + + combo = sh1 + sh2 + self.assertEqual(combo.get_total_sdram(10), 100 + 4 * 10 + 20 + 10) + + def test_nested_shared(self): + # nested sdram do not make sense but do work + # all but the outer sdram acts like a non shared sdram + c1 = ConstantSDRAM(45) + sh1 = SharedSDRAM({"foo": c1}) + sh2 = SharedSDRAM({"bar": sh1}) + self.assertEqual(sh2.get_total_sdram(None), 45) + + def test_reused_key(self): + var1 = VariableSDRAM(20, 1) + sh1 = SharedSDRAM({"foo": var1}) + var2 = VariableSDRAM(20, 1) + sh2 = SharedSDRAM({"foo": var2}) + + v_sum = var1 + var2 + self.assertEqual(v_sum.get_total_sdram(10), 2 * (20 + 10)) + + # same shared entered more than once is the same as entered once + combo = sh1 + sh2 + self.assertEqual(combo.get_total_sdram(10), 20 + 10) + + # Same share inside a multiple is NOT summed! + multi = MultiRegionSDRAM() + multi.nest(1, sh1) + multi.nest(2, sh1) + self.assertEqual(combo.get_total_sdram(10), 20 + 10) + + var3 = VariableSDRAM(30, 2) + # reusing key with different values is HIGHLy discouraged + sh3 = SharedSDRAM({"foo": var3}) + + # But will go boom it the shared are combined. + # Remember this will happen is placed on same Chip + with self.assertRaises(PacmanConfigurationException): + sh1 + sh3 + + sh4 = SharedSDRAM({"bar": var3}) + multi4 = MultiRegionSDRAM() + multi4.nest(1, sh1) + multi4.nest(2, sh4) + self.assertEqual(multi4.get_total_sdram(10), 20 + 10 + 30 + 2 * 10) + if __name__ == '__main__': unittest.main() diff --git a/unittests/utilities_tests/test_json_utils.py b/unittests/utilities_tests/test_json_utils.py index 95bfc4543..0711555f4 100644 --- a/unittests/utilities_tests/test_json_utils.py +++ b/unittests/utilities_tests/test_json_utils.py @@ -18,7 +18,7 @@ from pacman.model.resources import ( ConstantSDRAM, IPtagResource, ReverseIPtagResource) from pacman.utilities.json_utils import ( - placement_from_json, placement_to_json, vertex_to_json, vertex_from_json) + placement_from_json, placement_to_json) from pacman.model.graphs.machine import SimpleMachineVertex @@ -59,13 +59,6 @@ def _compare_placement(self, p1, p2, seen=None): # Composite JSON round-trip testing schemes # ------------------------------------------------------------------ - def vertex_there_and_back(self, there): - j_object = vertex_to_json(there) - j_str = json.dumps(j_object) - j_object2 = json.loads(j_str) - back = vertex_from_json(j_object2) - self._compare_vertex(there, back) - def placement_there_and_back(self, there): j_object = placement_to_json(there) j_str = json.dumps(j_object) @@ -77,14 +70,6 @@ def placement_there_and_back(self, there): # Test cases # ------------------------------------------------------------------ - def test_vertex(self): - s1 = SimpleMachineVertex( - sdram=ConstantSDRAM(0), - iptags=[IPtagResource("127.0.0.1", port=None, strip_sdp=True)], - reverse_iptags=[ReverseIPtagResource(port=25, sdp_port=2, tag=5)], - label="Vertex") - self.vertex_there_and_back(s1) - def test_placement(self): s1 = SimpleMachineVertex( sdram=ConstantSDRAM(0),