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/common/NetDest.hh"
35 #include "mem/ruby/network/MessageBuffer.hh"
36 #include "mem/ruby/network/simple/SimpleLink.hh"
37 #include "mem/ruby/network/simple/SimpleNetwork.hh"
38 #include "mem/ruby/network/simple/Switch.hh"
39 #include "mem/ruby/network/simple/Throttle.hh"
40 #include "mem/ruby/profiler/Profiler.hh"
41 #include "mem/ruby/system/System.hh"
44 using m5::stl_helpers::deletePointers
;
46 SimpleNetwork::SimpleNetwork(const Params
*p
)
49 m_buffer_size
= p
->buffer_size
;
50 m_endpoint_bandwidth
= p
->endpoint_bandwidth
;
51 m_adaptive_routing
= p
->adaptive_routing
;
53 // Note: the parent Network Object constructor is called before the
54 // SimpleNetwork child constructor. Therefore, the member variables
55 // used below should already be initialized.
56 m_endpoint_switches
.resize(m_nodes
);
59 for (vector
<BasicRouter
*>::const_iterator i
= p
->routers
.begin();
60 i
!= p
->routers
.end(); ++i
) {
61 Switch
* s
= safe_cast
<Switch
*>(*i
);
62 m_switches
.push_back(s
);
63 s
->init_net_ptr(this);
66 m_int_link_buffers
= p
->int_link_buffers
;
67 m_num_connected_buffers
= 0;
75 // The topology pointer should have already been initialized in
76 // the parent class network constructor.
77 assert(m_topology_ptr
!= NULL
);
78 m_topology_ptr
->createLinks(this);
81 SimpleNetwork::~SimpleNetwork()
83 deletePointers(m_switches
);
84 deletePointers(m_int_link_buffers
);
87 // From a switch to an endpoint node
89 SimpleNetwork::makeOutLink(SwitchID src
, NodeID dest
, BasicLink
* link
,
90 LinkDirection direction
,
91 const NetDest
& routing_table_entry
)
93 assert(dest
< m_nodes
);
94 assert(src
< m_switches
.size());
95 assert(m_switches
[src
] != NULL
);
97 SimpleExtLink
*simple_link
= safe_cast
<SimpleExtLink
*>(link
);
99 m_switches
[src
]->addOutPort(m_fromNetQueues
[dest
], routing_table_entry
,
100 simple_link
->m_latency
,
101 simple_link
->m_bw_multiplier
);
103 m_endpoint_switches
[dest
] = m_switches
[src
];
106 // From an endpoint node to a switch
108 SimpleNetwork::makeInLink(NodeID src
, SwitchID dest
, BasicLink
* link
,
109 LinkDirection direction
,
110 const NetDest
& routing_table_entry
)
112 assert(src
< m_nodes
);
113 m_switches
[dest
]->addInPort(m_toNetQueues
[src
]);
116 // From a switch to a switch
118 SimpleNetwork::makeInternalLink(SwitchID src
, SwitchID dest
, BasicLink
* link
,
119 LinkDirection direction
,
120 const NetDest
& routing_table_entry
)
122 // Create a set of new MessageBuffers
123 std::vector
<MessageBuffer
*> queues(m_virtual_networks
);
125 for (int i
= 0; i
< m_virtual_networks
; i
++) {
127 assert(m_num_connected_buffers
< m_int_link_buffers
.size());
128 MessageBuffer
* buffer_ptr
= m_int_link_buffers
[m_num_connected_buffers
];
129 m_num_connected_buffers
++;
130 queues
[i
] = buffer_ptr
;
133 // Connect it to the two switches
134 SimpleIntLink
*simple_link
= safe_cast
<SimpleIntLink
*>(link
);
136 m_switches
[dest
]->addInPort(queues
);
137 m_switches
[src
]->addOutPort(queues
, routing_table_entry
,
138 simple_link
->m_latency
,
139 simple_link
->m_bw_multiplier
);
143 SimpleNetwork::checkNetworkAllocation(NodeID id
, bool ordered
, int network_num
)
145 assert(id
< m_nodes
);
146 assert(network_num
< m_virtual_networks
);
149 m_ordered
[network_num
] = true;
151 m_in_use
[network_num
] = true;
155 SimpleNetwork::setToNetQueue(NodeID id
, bool ordered
, int network_num
,
156 std::string vnet_type
, MessageBuffer
*b
)
158 checkNetworkAllocation(id
, ordered
, network_num
);
159 while (m_toNetQueues
[id
].size() <= network_num
) {
160 m_toNetQueues
[id
].push_back(nullptr);
162 m_toNetQueues
[id
][network_num
] = b
;
166 SimpleNetwork::setFromNetQueue(NodeID id
, bool ordered
, int network_num
,
167 std::string vnet_type
, MessageBuffer
*b
)
169 checkNetworkAllocation(id
, ordered
, network_num
);
170 while (m_fromNetQueues
[id
].size() <= network_num
) {
171 m_fromNetQueues
[id
].push_back(nullptr);
173 m_fromNetQueues
[id
][network_num
] = b
;
177 SimpleNetwork::regStats()
179 for (MessageSizeType type
= MessageSizeType_FIRST
;
180 type
< MessageSizeType_NUM
; ++type
) {
181 m_msg_counts
[(unsigned int) type
]
182 .name(name() + ".msg_count." + MessageSizeType_to_string(type
))
183 .flags(Stats::nozero
)
185 m_msg_bytes
[(unsigned int) type
]
186 .name(name() + ".msg_byte." + MessageSizeType_to_string(type
))
187 .flags(Stats::nozero
)
190 // Now state what the formula is.
191 for (int i
= 0; i
< m_switches
.size(); i
++) {
192 m_msg_counts
[(unsigned int) type
] +=
193 sum(m_switches
[i
]->getMsgCount(type
));
196 m_msg_bytes
[(unsigned int) type
] =
197 m_msg_counts
[(unsigned int) type
] * Stats::constant(
198 Network::MessageSizeType_to_int(type
));
203 SimpleNetwork::collateStats()
205 for (int i
= 0; i
< m_switches
.size(); i
++) {
206 m_switches
[i
]->collateStats();
211 SimpleNetwork::print(ostream
& out
) const
213 out
<< "[SimpleNetwork]";
217 SimpleNetworkParams::create()
219 return new SimpleNetwork(this);
223 * The simple network has an array of switches. These switches have buffers
224 * that need to be accessed for functional reads and writes. Also the links
225 * between different switches have buffers that need to be accessed.
228 SimpleNetwork::functionalRead(Packet
*pkt
)
230 for (unsigned int i
= 0; i
< m_switches
.size(); i
++) {
231 if (m_switches
[i
]->functionalRead(pkt
)) {
236 for (unsigned int i
= 0; i
< m_int_link_buffers
.size(); ++i
) {
237 if (m_int_link_buffers
[i
]->functionalRead(pkt
)) {
246 SimpleNetwork::functionalWrite(Packet
*pkt
)
248 uint32_t num_functional_writes
= 0;
250 for (unsigned int i
= 0; i
< m_switches
.size(); i
++) {
251 num_functional_writes
+= m_switches
[i
]->functionalWrite(pkt
);
254 for (unsigned int i
= 0; i
< m_int_link_buffers
.size(); ++i
) {
255 num_functional_writes
+= m_int_link_buffers
[i
]->functionalWrite(pkt
);
257 return num_functional_writes
;