1/*
2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "mem/ruby/common/NetDest.hh"
30
31#include <algorithm>
32
33NetDest::NetDest()
34{
35  resize();
36}
37
38void
39NetDest::add(MachineID newElement)
40{
41    assert(bitIndex(newElement.num) < m_bits[vecIndex(newElement)].getSize());
42    m_bits[vecIndex(newElement)].add(bitIndex(newElement.num));
43}
44
45void
46NetDest::addNetDest(const NetDest& netDest)
47{
48    assert(m_bits.size() == netDest.getSize());
49    for (int i = 0; i < m_bits.size(); i++) {
50        m_bits[i].addSet(netDest.m_bits[i]);
51    }
52}
53
54void
55NetDest::setNetDest(MachineType machine, const Set& set)
56{
57    // assure that there is only one set of destinations for this machine
58    assert(MachineType_base_level((MachineType)(machine + 1)) -
59           MachineType_base_level(machine) == 1);
60    m_bits[MachineType_base_level(machine)] = set;
61}
62
63void
64NetDest::remove(MachineID oldElement)
65{
66    m_bits[vecIndex(oldElement)].remove(bitIndex(oldElement.num));
67}
68
69void
70NetDest::removeNetDest(const NetDest& netDest)
71{
72    assert(m_bits.size() == netDest.getSize());
73    for (int i = 0; i < m_bits.size(); i++) {
74        m_bits[i].removeSet(netDest.m_bits[i]);
75    }
76}
77
78void
79NetDest::clear()
80{
81    for (int i = 0; i < m_bits.size(); i++) {
82        m_bits[i].clear();
83    }
84}
85
86void
87NetDest::broadcast()
88{
89    for (MachineType machine = MachineType_FIRST;
90         machine < MachineType_NUM; ++machine) {
91        broadcast(machine);
92    }
93}
94
95void
96NetDest::broadcast(MachineType machineType)
97{
98    for (NodeID i = 0; i < MachineType_base_count(machineType); i++) {
99        MachineID mach = {machineType, i};
100        add(mach);
101    }
102}
103
104//For Princeton Network
105std::vector<NodeID>
106NetDest::getAllDest()
107{
108    std::vector<NodeID> dest;
109    dest.clear();
110    for (int i = 0; i < m_bits.size(); i++) {
111        for (int j = 0; j < m_bits[i].getSize(); j++) {
112            if (m_bits[i].isElement(j)) {
113                int id = MachineType_base_number((MachineType)i) + j;
114                dest.push_back((NodeID)id);
115            }
116        }
117    }
118    return dest;
119}
120
121int
122NetDest::count() const
123{
124    int counter = 0;
125    for (int i = 0; i < m_bits.size(); i++) {
126        counter += m_bits[i].count();
127    }
128    return counter;
129}
130
131NodeID
132NetDest::elementAt(MachineID index)
133{
134    return m_bits[vecIndex(index)].elementAt(bitIndex(index.num));
135}
136
137MachineID
138NetDest::smallestElement() const
139{
140    assert(count() > 0);
141    for (int i = 0; i < m_bits.size(); i++) {
142        for (NodeID j = 0; j < m_bits[i].getSize(); j++) {
143            if (m_bits[i].isElement(j)) {
144                MachineID mach = {MachineType_from_base_level(i), j};
145                return mach;
146            }
147        }
148    }
149    panic("No smallest element of an empty set.");
150}
151
152MachineID
153NetDest::smallestElement(MachineType machine) const
154{
155    int size = m_bits[MachineType_base_level(machine)].getSize();
156    for (NodeID j = 0; j < size; j++) {
157        if (m_bits[MachineType_base_level(machine)].isElement(j)) {
158            MachineID mach = {machine, j};
159            return mach;
160        }
161    }
162
163    panic("No smallest element of given MachineType.");
164}
165
166// Returns true iff all bits are set
167bool
168NetDest::isBroadcast() const
169{
170    for (int i = 0; i < m_bits.size(); i++) {
171        if (!m_bits[i].isBroadcast()) {
172            return false;
173        }
174    }
175    return true;
176}
177
178// Returns true iff no bits are set
179bool
180NetDest::isEmpty() const
181{
182    for (int i = 0; i < m_bits.size(); i++) {
183        if (!m_bits[i].isEmpty()) {
184            return false;
185        }
186    }
187    return true;
188}
189
190// returns the logical OR of "this" set and orNetDest
191NetDest
192NetDest::OR(const NetDest& orNetDest) const
193{
194    assert(m_bits.size() == orNetDest.getSize());
195    NetDest result;
196    for (int i = 0; i < m_bits.size(); i++) {
197        result.m_bits[i] = m_bits[i].OR(orNetDest.m_bits[i]);
198    }
199    return result;
200}
201
202// returns the logical AND of "this" set and andNetDest
203NetDest
204NetDest::AND(const NetDest& andNetDest) const
205{
206    assert(m_bits.size() == andNetDest.getSize());
207    NetDest result;
208    for (int i = 0; i < m_bits.size(); i++) {
209        result.m_bits[i] = m_bits[i].AND(andNetDest.m_bits[i]);
210    }
211    return result;
212}
213
214// Returns true if the intersection of the two sets is non-empty
215bool
216NetDest::intersectionIsNotEmpty(const NetDest& other_netDest) const
217{
218    assert(m_bits.size() == other_netDest.getSize());
219    for (int i = 0; i < m_bits.size(); i++) {
220        if (!m_bits[i].intersectionIsEmpty(other_netDest.m_bits[i])) {
221            return true;
222        }
223    }
224    return false;
225}
226
227bool
228NetDest::isSuperset(const NetDest& test) const
229{
230    assert(m_bits.size() == test.getSize());
231
232    for (int i = 0; i < m_bits.size(); i++) {
233        if (!m_bits[i].isSuperset(test.m_bits[i])) {
234            return false;
235        }
236    }
237    return true;
238}
239
240bool
241NetDest::isElement(MachineID element) const
242{
243    return ((m_bits[vecIndex(element)])).isElement(bitIndex(element.num));
244}
245
246void
247NetDest::resize()
248{
249    m_bits.resize(MachineType_base_level(MachineType_NUM));
250    assert(m_bits.size() == MachineType_NUM);
251
252    for (int i = 0; i < m_bits.size(); i++) {
253        m_bits[i].setSize(MachineType_base_count((MachineType)i));
254    }
255}
256
257void
258NetDest::print(std::ostream& out) const
259{
260    out << "[NetDest (" << m_bits.size() << ") ";
261
262    for (int i = 0; i < m_bits.size(); i++) {
263        for (int j = 0; j < m_bits[i].getSize(); j++) {
264            out << (bool) m_bits[i].isElement(j) << " ";
265        }
266        out << " - ";
267    }
268    out << "]";
269}
270
271bool
272NetDest::isEqual(const NetDest& n) const
273{
274    assert(m_bits.size() == n.m_bits.size());
275    for (unsigned int i = 0; i < m_bits.size(); ++i) {
276        if (!m_bits[i].isEqual(n.m_bits[i]))
277            return false;
278    }
279    return true;
280}
281