2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
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.
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.
32 #include "base/cast.hh"
33 #include "base/stl_helpers.hh"
34 #include "mem/ruby/buffers/MessageBuffer.hh"
35 #include "mem/ruby/common/NetDest.hh"
36 #include "mem/ruby/network/BasicLink.hh"
37 #include "mem/ruby/network/simple/SimpleLink.hh"
38 #include "mem/ruby/network/simple/SimpleNetwork.hh"
39 #include "mem/ruby/network/simple/Switch.hh"
40 #include "mem/ruby/network/simple/Throttle.hh"
41 #include "mem/ruby/network/Topology.hh"
42 #include "mem/ruby/profiler/Profiler.hh"
43 #include "mem/ruby/system/System.hh"
46 using m5::stl_helpers::deletePointers
;
48 SimpleNetwork::SimpleNetwork(const Params
*p
)
51 m_buffer_size
= p
->buffer_size
;
52 m_endpoint_bandwidth
= p
->endpoint_bandwidth
;
53 m_adaptive_routing
= p
->adaptive_routing
;
55 // Note: the parent Network Object constructor is called before the
56 // SimpleNetwork child constructor. Therefore, the member variables
57 // used below should already be initialized.
59 m_endpoint_switches
.resize(m_nodes
);
61 m_in_use
.resize(m_virtual_networks
);
62 m_ordered
.resize(m_virtual_networks
);
63 for (int i
= 0; i
< m_virtual_networks
; i
++) {
68 // Allocate to and from queues
69 m_toNetQueues
.resize(m_nodes
);
70 m_fromNetQueues
.resize(m_nodes
);
71 for (int node
= 0; node
< m_nodes
; node
++) {
72 m_toNetQueues
[node
].resize(m_virtual_networks
);
73 m_fromNetQueues
[node
].resize(m_virtual_networks
);
74 for (int j
= 0; j
< m_virtual_networks
; j
++) {
75 m_toNetQueues
[node
][j
] =
76 new MessageBuffer(csprintf("toNet node %d j %d", node
, j
));
77 m_fromNetQueues
[node
][j
] =
78 new MessageBuffer(csprintf("fromNet node %d j %d", node
, j
));
83 for (vector
<BasicRouter
*>::const_iterator i
=
84 m_topology_ptr
->params()->routers
.begin();
85 i
!= m_topology_ptr
->params()->routers
.end(); ++i
) {
86 Switch
* s
= safe_cast
<Switch
*>(*i
);
87 m_switch_ptr_vector
.push_back(s
);
88 s
->init_net_ptr(this);
97 // The topology pointer should have already been initialized in
98 // the parent class network constructor.
99 assert(m_topology_ptr
!= NULL
);
100 // false because this isn't a reconfiguration
101 m_topology_ptr
->createLinks(this, false);
105 SimpleNetwork::reset()
107 for (int node
= 0; node
< m_nodes
; node
++) {
108 for (int j
= 0; j
< m_virtual_networks
; j
++) {
109 m_toNetQueues
[node
][j
]->clear();
110 m_fromNetQueues
[node
][j
]->clear();
114 for(int i
= 0; i
< m_switch_ptr_vector
.size(); i
++){
115 m_switch_ptr_vector
[i
]->clearBuffers();
119 SimpleNetwork::~SimpleNetwork()
121 for (int i
= 0; i
< m_nodes
; i
++) {
122 deletePointers(m_toNetQueues
[i
]);
123 deletePointers(m_fromNetQueues
[i
]);
125 deletePointers(m_switch_ptr_vector
);
126 deletePointers(m_buffers_to_free
);
127 // delete m_topology_ptr;
130 // From a switch to an endpoint node
132 SimpleNetwork::makeOutLink(SwitchID src
, NodeID dest
, BasicLink
* link
,
133 LinkDirection direction
,
134 const NetDest
& routing_table_entry
,
135 bool isReconfiguration
)
137 assert(dest
< m_nodes
);
138 assert(src
< m_switch_ptr_vector
.size());
139 assert(m_switch_ptr_vector
[src
] != NULL
);
141 if (isReconfiguration
) {
142 m_switch_ptr_vector
[src
]->reconfigureOutPort(routing_table_entry
);
146 SimpleExtLink
*simple_link
= safe_cast
<SimpleExtLink
*>(link
);
148 m_switch_ptr_vector
[src
]->addOutPort(m_fromNetQueues
[dest
],
150 simple_link
->m_latency
,
151 simple_link
->m_bw_multiplier
);
153 m_endpoint_switches
[dest
] = m_switch_ptr_vector
[src
];
156 // From an endpoint node to a switch
158 SimpleNetwork::makeInLink(NodeID src
, SwitchID dest
, BasicLink
* link
,
159 LinkDirection direction
,
160 const NetDest
& routing_table_entry
,
161 bool isReconfiguration
)
163 assert(src
< m_nodes
);
164 if (isReconfiguration
) {
169 m_switch_ptr_vector
[dest
]->addInPort(m_toNetQueues
[src
]);
172 // From a switch to a switch
174 SimpleNetwork::makeInternalLink(SwitchID src
, SwitchID dest
, BasicLink
* link
,
175 LinkDirection direction
,
176 const NetDest
& routing_table_entry
,
177 bool isReconfiguration
)
179 if (isReconfiguration
) {
180 m_switch_ptr_vector
[src
]->reconfigureOutPort(routing_table_entry
);
184 // Create a set of new MessageBuffers
185 std::vector
<MessageBuffer
*> queues
;
186 for (int i
= 0; i
< m_virtual_networks
; i
++) {
188 MessageBuffer
* buffer_ptr
= new MessageBuffer
;
189 buffer_ptr
->setOrdering(true);
190 if (m_buffer_size
> 0) {
191 buffer_ptr
->resize(m_buffer_size
);
193 queues
.push_back(buffer_ptr
);
194 // remember to deallocate it
195 m_buffers_to_free
.push_back(buffer_ptr
);
197 // Connect it to the two switches
198 SimpleIntLink
*simple_link
= safe_cast
<SimpleIntLink
*>(link
);
200 m_switch_ptr_vector
[dest
]->addInPort(queues
);
201 m_switch_ptr_vector
[src
]->addOutPort(queues
, routing_table_entry
,
202 simple_link
->m_latency
,
203 simple_link
->m_bw_multiplier
);
207 SimpleNetwork::checkNetworkAllocation(NodeID id
, bool ordered
, int network_num
)
209 assert(id
< m_nodes
);
210 assert(network_num
< m_virtual_networks
);
213 m_ordered
[network_num
] = true;
215 m_in_use
[network_num
] = true;
219 SimpleNetwork::getToNetQueue(NodeID id
, bool ordered
, int network_num
,
220 std::string vnet_type
)
222 checkNetworkAllocation(id
, ordered
, network_num
);
223 return m_toNetQueues
[id
][network_num
];
227 SimpleNetwork::getFromNetQueue(NodeID id
, bool ordered
, int network_num
,
228 std::string vnet_type
)
230 checkNetworkAllocation(id
, ordered
, network_num
);
231 return m_fromNetQueues
[id
][network_num
];
234 const std::vector
<Throttle
*>*
235 SimpleNetwork::getThrottles(NodeID id
) const
238 assert(id
< m_nodes
);
239 assert(m_endpoint_switches
[id
] != NULL
);
240 return m_endpoint_switches
[id
]->getThrottles();
244 SimpleNetwork::printStats(ostream
& out
) const
247 out
<< "Network Stats" << endl
;
248 out
<< "-------------" << endl
;
252 // Determine total counts before printing out each switch's stats
254 std::vector
<uint64
> total_msg_counts
;
255 total_msg_counts
.resize(MessageSizeType_NUM
);
256 for (MessageSizeType type
= MessageSizeType_FIRST
;
257 type
< MessageSizeType_NUM
;
259 total_msg_counts
[type
] = 0;
262 for (int i
= 0; i
< m_switch_ptr_vector
.size(); i
++) {
263 const std::vector
<Throttle
*>* throttles
=
264 m_switch_ptr_vector
[i
]->getThrottles();
266 for (int p
= 0; p
< throttles
->size(); p
++) {
268 const std::vector
<std::vector
<int> >& message_counts
=
269 ((*throttles
)[p
])->getCounters();
271 for (MessageSizeType type
= MessageSizeType_FIRST
;
272 type
< MessageSizeType_NUM
;
275 const std::vector
<int> &mct
= message_counts
[type
];
276 int sum
= accumulate(mct
.begin(), mct
.end(), 0);
277 total_msg_counts
[type
] += uint64(sum
);
281 uint64 total_msgs
= 0;
282 uint64 total_bytes
= 0;
283 for (MessageSizeType type
= MessageSizeType_FIRST
;
284 type
< MessageSizeType_NUM
;
287 if (total_msg_counts
[type
] > 0) {
288 out
<< "total_msg_count_" << type
<< ": " << total_msg_counts
[type
]
289 << " " << total_msg_counts
[type
] *
290 uint64(MessageSizeType_to_int(type
))
293 total_msgs
+= total_msg_counts
[type
];
295 total_bytes
+= total_msg_counts
[type
] *
296 uint64(MessageSizeType_to_int(type
));
300 out
<< "total_msgs: " << total_msgs
301 << " total_bytes: " << total_bytes
<< endl
;
304 for (int i
= 0; i
< m_switch_ptr_vector
.size(); i
++) {
305 m_switch_ptr_vector
[i
]->printStats(out
);
310 SimpleNetwork::clearStats()
312 for (int i
= 0; i
< m_switch_ptr_vector
.size(); i
++) {
313 m_switch_ptr_vector
[i
]->clearStats();
318 SimpleNetwork::print(ostream
& out
) const
320 out
<< "[SimpleNetwork]";
324 SimpleNetworkParams::create()
326 return new SimpleNetwork(this);
330 * The simple network has an array of switches. These switches have buffers
331 * that need to be accessed for functional reads and writes. Also the links
332 * between different switches have buffers that need to be accessed.
335 SimpleNetwork::functionalRead(Packet
*pkt
)
337 for (unsigned int i
= 0; i
< m_switch_ptr_vector
.size(); i
++) {
338 if (m_switch_ptr_vector
[i
]->functionalRead(pkt
)) {
343 for (unsigned int i
= 0; i
< m_buffers_to_free
.size(); ++i
) {
344 if (m_buffers_to_free
[i
]->functionalRead(pkt
)) {
353 SimpleNetwork::functionalWrite(Packet
*pkt
)
355 uint32_t num_functional_writes
= 0;
357 for (unsigned int i
= 0; i
< m_switch_ptr_vector
.size(); i
++) {
358 num_functional_writes
+= m_switch_ptr_vector
[i
]->functionalWrite(pkt
);
361 for (unsigned int i
= 0; i
< m_buffers_to_free
.size(); ++i
) {
362 num_functional_writes
+= m_buffers_to_free
[i
]->functionalWrite(pkt
);
364 return num_functional_writes
;