Cluster.py revision 9862
19100SBrad.Beckmann@amd.com# Copyright (c) 2012 Advanced Micro Devices, Inc.
29100SBrad.Beckmann@amd.com# All rights reserved.
39100SBrad.Beckmann@amd.com#
49100SBrad.Beckmann@amd.com# Redistribution and use in source and binary forms, with or without
59100SBrad.Beckmann@amd.com# modification, are permitted provided that the following conditions are
69100SBrad.Beckmann@amd.com# met: redistributions of source code must retain the above copyright
79100SBrad.Beckmann@amd.com# notice, this list of conditions and the following disclaimer;
89100SBrad.Beckmann@amd.com# redistributions in binary form must reproduce the above copyright
99100SBrad.Beckmann@amd.com# notice, this list of conditions and the following disclaimer in the
109100SBrad.Beckmann@amd.com# documentation and/or other materials provided with the distribution;
119100SBrad.Beckmann@amd.com# neither the name of the copyright holders nor the names of its
129100SBrad.Beckmann@amd.com# contributors may be used to endorse or promote products derived from
139100SBrad.Beckmann@amd.com# this software without specific prior written permission.
149100SBrad.Beckmann@amd.com#
159100SBrad.Beckmann@amd.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
169100SBrad.Beckmann@amd.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
179100SBrad.Beckmann@amd.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
189100SBrad.Beckmann@amd.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
199100SBrad.Beckmann@amd.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
209100SBrad.Beckmann@amd.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
219100SBrad.Beckmann@amd.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
229100SBrad.Beckmann@amd.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
239100SBrad.Beckmann@amd.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
249100SBrad.Beckmann@amd.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
259100SBrad.Beckmann@amd.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
269100SBrad.Beckmann@amd.com#
279100SBrad.Beckmann@amd.com# Authors: Jason Power
289100SBrad.Beckmann@amd.com
299100SBrad.Beckmann@amd.com
309100SBrad.Beckmann@amd.comfrom BaseTopology import BaseTopology
319100SBrad.Beckmann@amd.com
329100SBrad.Beckmann@amd.comclass Cluster(BaseTopology):
339100SBrad.Beckmann@amd.com    """ A cluster is a group of nodes which are all one hop from eachother
349100SBrad.Beckmann@amd.com        Clusters can also contain other clusters
359100SBrad.Beckmann@amd.com        When creating this kind of topology, return a single cluster (usually
369100SBrad.Beckmann@amd.com        the root cluster) from create_system in configs/ruby/<protocol>.py
379100SBrad.Beckmann@amd.com    """
389100SBrad.Beckmann@amd.com
399100SBrad.Beckmann@amd.com    _num_int_links = 0
409100SBrad.Beckmann@amd.com    _num_ext_links = 0
419100SBrad.Beckmann@amd.com    _num_routers = 0
429100SBrad.Beckmann@amd.com
439100SBrad.Beckmann@amd.com    # Below methods for auto counting
449100SBrad.Beckmann@amd.com    @classmethod
459100SBrad.Beckmann@amd.com    def num_int_links(cls):
469100SBrad.Beckmann@amd.com        cls._num_int_links += 1
479100SBrad.Beckmann@amd.com        return cls._num_int_links - 1
489100SBrad.Beckmann@amd.com    @classmethod
499100SBrad.Beckmann@amd.com    def num_ext_links(cls):
509100SBrad.Beckmann@amd.com        cls._num_ext_links += 1
519100SBrad.Beckmann@amd.com        return cls._num_ext_links - 1
529100SBrad.Beckmann@amd.com    @classmethod
539100SBrad.Beckmann@amd.com    def num_routers(cls):
549100SBrad.Beckmann@amd.com        cls._num_routers += 1
559100SBrad.Beckmann@amd.com        return cls._num_routers - 1
569100SBrad.Beckmann@amd.com
579100SBrad.Beckmann@amd.com    def __init__(self, intBW=0, extBW=0, intLatency=0, extLatency=0):
589100SBrad.Beckmann@amd.com        """ internalBandwidth is bandwidth of all links within the cluster
599100SBrad.Beckmann@amd.com            externalBandwidth is bandwidth from this cluster to any cluster
609100SBrad.Beckmann@amd.com                connecting to it.
619100SBrad.Beckmann@amd.com            internal/externalLatency are similar
629100SBrad.Beckmann@amd.com            **** When creating a cluster with sub-clusters, the sub-cluster
639100SBrad.Beckmann@amd.com                 external bandwidth overrides the internal bandwidth of the
649100SBrad.Beckmann@amd.com                 super cluster
659100SBrad.Beckmann@amd.com        """
669100SBrad.Beckmann@amd.com        self.nodes = []
679100SBrad.Beckmann@amd.com        self.router = None # created in makeTopology
689100SBrad.Beckmann@amd.com        self.intBW = intBW
699100SBrad.Beckmann@amd.com        self.extBW = extBW
709100SBrad.Beckmann@amd.com        self.intLatency = intLatency
719100SBrad.Beckmann@amd.com        self.extLatency = extLatency
729100SBrad.Beckmann@amd.com
739100SBrad.Beckmann@amd.com    def add(self, node):
749100SBrad.Beckmann@amd.com        self.nodes.append(node)
759100SBrad.Beckmann@amd.com
769862Snilay@cs.wisc.edu    def makeTopology(self, options, network, IntLink, ExtLink, Router):
779100SBrad.Beckmann@amd.com        """ Recursively make all of the links and routers
789100SBrad.Beckmann@amd.com        """
799100SBrad.Beckmann@amd.com
809100SBrad.Beckmann@amd.com        # make a router to connect all of the nodes
819100SBrad.Beckmann@amd.com        self.router = Router(router_id=self.num_routers())
829862Snilay@cs.wisc.edu        network.routers.append(self.router)
839862Snilay@cs.wisc.edu
849100SBrad.Beckmann@amd.com        for node in self.nodes:
859100SBrad.Beckmann@amd.com            if type(node) == Cluster:
869862Snilay@cs.wisc.edu                node.makeTopology(options, network, IntLink, ExtLink, Router)
879100SBrad.Beckmann@amd.com
889100SBrad.Beckmann@amd.com                # connect this cluster to the router
899100SBrad.Beckmann@amd.com                link = IntLink(link_id=self.num_int_links(), node_a=self.router, node_b=node.router)
909100SBrad.Beckmann@amd.com                if node.extBW:
919100SBrad.Beckmann@amd.com                    link.bandwidth_factor = node.extBW
929100SBrad.Beckmann@amd.com                elif self.intBW: # if there is an interanl b/w for this node and no ext b/w to override
939100SBrad.Beckmann@amd.com                    link.bandwidth_factor = self.intBW
949100SBrad.Beckmann@amd.com
959100SBrad.Beckmann@amd.com                if node.extLatency:
969100SBrad.Beckmann@amd.com                    link.latency = node.extLatency
979100SBrad.Beckmann@amd.com                elif self.intLatency:
989100SBrad.Beckmann@amd.com                    link.latency = self.intLatency
999100SBrad.Beckmann@amd.com
1009862Snilay@cs.wisc.edu                network.int_links.append(link)
1019100SBrad.Beckmann@amd.com            else:
1029100SBrad.Beckmann@amd.com                # node is just a controller connect it to the router via a ext_link
1039100SBrad.Beckmann@amd.com                link = ExtLink(link_id=self.num_ext_links(), ext_node=node, int_node=self.router)
1049100SBrad.Beckmann@amd.com                if self.intBW:
1059100SBrad.Beckmann@amd.com                    link.bandwidth_factor = self.intBW
1069100SBrad.Beckmann@amd.com                if self.intLatency:
1079100SBrad.Beckmann@amd.com                    link.latency = self.intLatency
1089100SBrad.Beckmann@amd.com
1099862Snilay@cs.wisc.edu                network.ext_links.append(link)
1109100SBrad.Beckmann@amd.com
1119148Spowerjg@cs.wisc.edu    def __len__(self):
1129148Spowerjg@cs.wisc.edu        return len([i for i in self.nodes if type(i) != Cluster]) + \
1139148Spowerjg@cs.wisc.edu               sum([len(i) for i in self.nodes if type(i) == Cluster])
114