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
2913774Sandreas.sandberg@arm.comfrom __future__ import print_function
3013774Sandreas.sandberg@arm.comfrom __future__ import absolute_import
319100SBrad.Beckmann@amd.com
3213774Sandreas.sandberg@arm.comfrom .BaseTopology import BaseTopology
339100SBrad.Beckmann@amd.com
349100SBrad.Beckmann@amd.comclass Cluster(BaseTopology):
359100SBrad.Beckmann@amd.com    """ A cluster is a group of nodes which are all one hop from eachother
369100SBrad.Beckmann@amd.com        Clusters can also contain other clusters
379100SBrad.Beckmann@amd.com        When creating this kind of topology, return a single cluster (usually
389100SBrad.Beckmann@amd.com        the root cluster) from create_system in configs/ruby/<protocol>.py
399100SBrad.Beckmann@amd.com    """
409100SBrad.Beckmann@amd.com
419100SBrad.Beckmann@amd.com    _num_int_links = 0
429100SBrad.Beckmann@amd.com    _num_ext_links = 0
439100SBrad.Beckmann@amd.com    _num_routers = 0
449100SBrad.Beckmann@amd.com
459100SBrad.Beckmann@amd.com    # Below methods for auto counting
469100SBrad.Beckmann@amd.com    @classmethod
479100SBrad.Beckmann@amd.com    def num_int_links(cls):
489100SBrad.Beckmann@amd.com        cls._num_int_links += 1
499100SBrad.Beckmann@amd.com        return cls._num_int_links - 1
509100SBrad.Beckmann@amd.com    @classmethod
519100SBrad.Beckmann@amd.com    def num_ext_links(cls):
529100SBrad.Beckmann@amd.com        cls._num_ext_links += 1
539100SBrad.Beckmann@amd.com        return cls._num_ext_links - 1
549100SBrad.Beckmann@amd.com    @classmethod
559100SBrad.Beckmann@amd.com    def num_routers(cls):
569100SBrad.Beckmann@amd.com        cls._num_routers += 1
579100SBrad.Beckmann@amd.com        return cls._num_routers - 1
589100SBrad.Beckmann@amd.com
599100SBrad.Beckmann@amd.com    def __init__(self, intBW=0, extBW=0, intLatency=0, extLatency=0):
609100SBrad.Beckmann@amd.com        """ internalBandwidth is bandwidth of all links within the cluster
619100SBrad.Beckmann@amd.com            externalBandwidth is bandwidth from this cluster to any cluster
629100SBrad.Beckmann@amd.com                connecting to it.
639100SBrad.Beckmann@amd.com            internal/externalLatency are similar
649100SBrad.Beckmann@amd.com            **** When creating a cluster with sub-clusters, the sub-cluster
659100SBrad.Beckmann@amd.com                 external bandwidth overrides the internal bandwidth of the
669100SBrad.Beckmann@amd.com                 super cluster
679100SBrad.Beckmann@amd.com        """
689100SBrad.Beckmann@amd.com        self.nodes = []
699100SBrad.Beckmann@amd.com        self.router = None # created in makeTopology
709100SBrad.Beckmann@amd.com        self.intBW = intBW
719100SBrad.Beckmann@amd.com        self.extBW = extBW
729100SBrad.Beckmann@amd.com        self.intLatency = intLatency
739100SBrad.Beckmann@amd.com        self.extLatency = extLatency
749100SBrad.Beckmann@amd.com
759100SBrad.Beckmann@amd.com    def add(self, node):
769100SBrad.Beckmann@amd.com        self.nodes.append(node)
779100SBrad.Beckmann@amd.com
789862Snilay@cs.wisc.edu    def makeTopology(self, options, network, IntLink, ExtLink, Router):
799100SBrad.Beckmann@amd.com        """ Recursively make all of the links and routers
809100SBrad.Beckmann@amd.com        """
819100SBrad.Beckmann@amd.com
829100SBrad.Beckmann@amd.com        # make a router to connect all of the nodes
839100SBrad.Beckmann@amd.com        self.router = Router(router_id=self.num_routers())
849862Snilay@cs.wisc.edu        network.routers.append(self.router)
859862Snilay@cs.wisc.edu
869100SBrad.Beckmann@amd.com        for node in self.nodes:
879100SBrad.Beckmann@amd.com            if type(node) == Cluster:
8813885Sdavid.hashe@amd.com                node.makeTopology(options, network, IntLink,
8913885Sdavid.hashe@amd.com                                  ExtLink, Router)
909100SBrad.Beckmann@amd.com
919100SBrad.Beckmann@amd.com                # connect this cluster to the router
9211663Stushar@ece.gatech.edu                link_out = IntLink(link_id=self.num_int_links(), src_node=self.router,
9311669Stushar@ece.gatech.edu                           dst_node=node.router)
9411663Stushar@ece.gatech.edu                link_in = IntLink(link_id=self.num_int_links(), src_node=node.router,
9511669Stushar@ece.gatech.edu                                  dst_node=self.router)
9610088Snilay@cs.wisc.edu
979100SBrad.Beckmann@amd.com                if node.extBW:
9811663Stushar@ece.gatech.edu                    link_out.bandwidth_factor = node.extBW
9911663Stushar@ece.gatech.edu                    link_in.bandwidth_factor = node.extBW
10010088Snilay@cs.wisc.edu
10111663Stushar@ece.gatech.edu                # if there is an internal b/w for this node
10210088Snilay@cs.wisc.edu                # and no ext b/w to override
10310088Snilay@cs.wisc.edu                elif self.intBW:
10411663Stushar@ece.gatech.edu                    link_out.bandwidth_factor = self.intBW
10511663Stushar@ece.gatech.edu                    link_in.bandwidth_factor = self.intBW
1069100SBrad.Beckmann@amd.com
1079100SBrad.Beckmann@amd.com                if node.extLatency:
10811663Stushar@ece.gatech.edu                    link_out.latency = node.extLatency
10911663Stushar@ece.gatech.edu                    link_in.latency = node.extLatency
1109100SBrad.Beckmann@amd.com                elif self.intLatency:
11111663Stushar@ece.gatech.edu                    link_out.latency = self.intLatency
11211663Stushar@ece.gatech.edu                    link_in.latency = self.intLatency
1139100SBrad.Beckmann@amd.com
11411663Stushar@ece.gatech.edu                network.int_links.append(link_out)
11511663Stushar@ece.gatech.edu                network.int_links.append(link_in)
1169100SBrad.Beckmann@amd.com            else:
11710088Snilay@cs.wisc.edu                # node is just a controller,
11810088Snilay@cs.wisc.edu                # connect it to the router via a ext_link
11910088Snilay@cs.wisc.edu                link = ExtLink(link_id=self.num_ext_links(), ext_node=node,
12010088Snilay@cs.wisc.edu                        int_node=self.router)
12110088Snilay@cs.wisc.edu
1229100SBrad.Beckmann@amd.com                if self.intBW:
1239100SBrad.Beckmann@amd.com                    link.bandwidth_factor = self.intBW
1249100SBrad.Beckmann@amd.com                if self.intLatency:
1259100SBrad.Beckmann@amd.com                    link.latency = self.intLatency
1269100SBrad.Beckmann@amd.com
1279862Snilay@cs.wisc.edu                network.ext_links.append(link)
1289100SBrad.Beckmann@amd.com
1299148Spowerjg@cs.wisc.edu    def __len__(self):
1309148Spowerjg@cs.wisc.edu        return len([i for i in self.nodes if type(i) != Cluster]) + \
1319148Spowerjg@cs.wisc.edu               sum([len(i) for i in self.nodes if type(i) == Cluster])
132