2009-05-11 19:38:43 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met: redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer;
|
|
|
|
* redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution;
|
|
|
|
* neither the name of the copyright holders nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived from
|
|
|
|
* this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2011-01-10 20:11:20 +01:00
|
|
|
#include <cassert>
|
2010-08-20 20:46:12 +02:00
|
|
|
#include <numeric>
|
|
|
|
|
2012-01-01 01:44:51 +01:00
|
|
|
#include "base/cast.hh"
|
2010-06-11 08:17:07 +02:00
|
|
|
#include "base/stl_helpers.hh"
|
2010-04-01 01:56:45 +02:00
|
|
|
#include "mem/ruby/common/NetDest.hh"
|
2014-09-01 23:55:40 +02:00
|
|
|
#include "mem/ruby/network/MessageBuffer.hh"
|
2011-04-29 02:18:14 +02:00
|
|
|
#include "mem/ruby/network/simple/SimpleLink.hh"
|
2009-05-11 19:38:45 +02:00
|
|
|
#include "mem/ruby/network/simple/SimpleNetwork.hh"
|
|
|
|
#include "mem/ruby/network/simple/Switch.hh"
|
2010-08-20 20:46:12 +02:00
|
|
|
#include "mem/ruby/network/simple/Throttle.hh"
|
2010-04-01 01:56:45 +02:00
|
|
|
#include "mem/ruby/profiler/Profiler.hh"
|
|
|
|
#include "mem/ruby/system/System.hh"
|
2009-05-11 19:38:43 +02:00
|
|
|
|
2010-04-02 20:20:32 +02:00
|
|
|
using namespace std;
|
2010-06-11 08:17:07 +02:00
|
|
|
using m5::stl_helpers::deletePointers;
|
2010-04-02 20:20:32 +02:00
|
|
|
|
2010-01-30 05:29:17 +01:00
|
|
|
SimpleNetwork::SimpleNetwork(const Params *p)
|
|
|
|
: Network(p)
|
2009-07-07 00:49:47 +02:00
|
|
|
{
|
2011-04-29 02:18:14 +02:00
|
|
|
m_buffer_size = p->buffer_size;
|
|
|
|
m_endpoint_bandwidth = p->endpoint_bandwidth;
|
|
|
|
m_adaptive_routing = p->adaptive_routing;
|
|
|
|
|
2010-04-01 01:56:45 +02:00
|
|
|
// Note: the parent Network Object constructor is called before the
|
|
|
|
// SimpleNetwork child constructor. Therefore, the member variables
|
|
|
|
// used below should already be initialized.
|
2010-06-11 08:17:07 +02:00
|
|
|
m_endpoint_switches.resize(m_nodes);
|
2010-04-01 01:56:45 +02:00
|
|
|
|
2012-10-02 21:35:45 +02:00
|
|
|
// record the routers
|
2013-03-22 21:53:22 +01:00
|
|
|
for (vector<BasicRouter*>::const_iterator i = p->routers.begin();
|
|
|
|
i != p->routers.end(); ++i) {
|
2012-10-02 21:35:45 +02:00
|
|
|
Switch* s = safe_cast<Switch*>(*i);
|
2013-09-06 23:21:29 +02:00
|
|
|
m_switches.push_back(s);
|
2012-10-02 21:35:45 +02:00
|
|
|
s->init_net_ptr(this);
|
|
|
|
}
|
2010-01-30 05:29:18 +01:00
|
|
|
}
|
|
|
|
|
2010-04-01 01:56:45 +02:00
|
|
|
void
|
|
|
|
SimpleNetwork::init()
|
2010-01-30 05:29:18 +01:00
|
|
|
{
|
2010-04-01 01:56:45 +02:00
|
|
|
Network::init();
|
|
|
|
|
|
|
|
// The topology pointer should have already been initialized in
|
|
|
|
// the parent class network constructor.
|
|
|
|
assert(m_topology_ptr != NULL);
|
2013-06-29 04:36:37 +02:00
|
|
|
m_topology_ptr->createLinks(this);
|
2009-07-07 00:49:47 +02:00
|
|
|
}
|
2009-05-11 19:38:43 +02:00
|
|
|
|
|
|
|
SimpleNetwork::~SimpleNetwork()
|
|
|
|
{
|
2013-09-06 23:21:29 +02:00
|
|
|
deletePointers(m_switches);
|
2010-06-11 08:17:07 +02:00
|
|
|
deletePointers(m_buffers_to_free);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// From a switch to an endpoint node
|
2010-04-01 01:56:45 +02:00
|
|
|
void
|
2011-04-29 02:18:14 +02:00
|
|
|
SimpleNetwork::makeOutLink(SwitchID src, NodeID dest, BasicLink* link,
|
|
|
|
LinkDirection direction,
|
2013-06-29 04:36:37 +02:00
|
|
|
const NetDest& routing_table_entry)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-04-01 01:56:45 +02:00
|
|
|
assert(dest < m_nodes);
|
2013-09-06 23:21:29 +02:00
|
|
|
assert(src < m_switches.size());
|
|
|
|
assert(m_switches[src] != NULL);
|
2010-04-01 01:56:45 +02:00
|
|
|
|
2011-04-29 02:18:14 +02:00
|
|
|
SimpleExtLink *simple_link = safe_cast<SimpleExtLink*>(link);
|
|
|
|
|
2014-09-01 23:55:47 +02:00
|
|
|
m_switches[src]->addOutPort(m_fromNetQueues[dest], routing_table_entry,
|
|
|
|
simple_link->m_latency,
|
|
|
|
simple_link->m_bw_multiplier);
|
2011-04-29 02:18:14 +02:00
|
|
|
|
2013-09-06 23:21:29 +02:00
|
|
|
m_endpoint_switches[dest] = m_switches[src];
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// From an endpoint node to a switch
|
2010-04-01 01:56:45 +02:00
|
|
|
void
|
2011-04-29 02:18:14 +02:00
|
|
|
SimpleNetwork::makeInLink(NodeID src, SwitchID dest, BasicLink* link,
|
|
|
|
LinkDirection direction,
|
2013-06-29 04:36:37 +02:00
|
|
|
const NetDest& routing_table_entry)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-04-01 01:56:45 +02:00
|
|
|
assert(src < m_nodes);
|
2013-09-06 23:21:29 +02:00
|
|
|
m_switches[dest]->addInPort(m_toNetQueues[src]);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// From a switch to a switch
|
2010-04-01 01:56:45 +02:00
|
|
|
void
|
2011-04-29 02:18:14 +02:00
|
|
|
SimpleNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
|
|
|
|
LinkDirection direction,
|
2013-06-29 04:36:37 +02:00
|
|
|
const NetDest& routing_table_entry)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
|
|
|
// Create a set of new MessageBuffers
|
2014-09-15 23:19:38 +02:00
|
|
|
std::vector<MessageBuffer*> queues(m_virtual_networks);
|
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
for (int i = 0; i < m_virtual_networks; i++) {
|
2010-04-01 01:56:45 +02:00
|
|
|
// allocate a buffer
|
|
|
|
MessageBuffer* buffer_ptr = new MessageBuffer;
|
|
|
|
buffer_ptr->setOrdering(true);
|
2014-09-01 23:55:47 +02:00
|
|
|
|
2010-04-01 01:56:45 +02:00
|
|
|
if (m_buffer_size > 0) {
|
2010-06-11 08:17:07 +02:00
|
|
|
buffer_ptr->resize(m_buffer_size);
|
2010-04-01 01:56:45 +02:00
|
|
|
}
|
2014-09-01 23:55:47 +02:00
|
|
|
|
|
|
|
queues[i] = buffer_ptr;
|
2010-04-01 01:56:45 +02:00
|
|
|
// remember to deallocate it
|
2010-06-11 08:17:07 +02:00
|
|
|
m_buffers_to_free.push_back(buffer_ptr);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
2014-09-01 23:55:47 +02:00
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
// Connect it to the two switches
|
2011-04-29 02:18:14 +02:00
|
|
|
SimpleIntLink *simple_link = safe_cast<SimpleIntLink*>(link);
|
|
|
|
|
2013-09-06 23:21:29 +02:00
|
|
|
m_switches[dest]->addInPort(queues);
|
|
|
|
m_switches[src]->addOutPort(queues, routing_table_entry,
|
2014-09-01 23:55:47 +02:00
|
|
|
simple_link->m_latency,
|
|
|
|
simple_link->m_bw_multiplier);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-04-01 01:56:45 +02:00
|
|
|
void
|
|
|
|
SimpleNetwork::checkNetworkAllocation(NodeID id, bool ordered, int network_num)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2011-01-10 20:11:20 +01:00
|
|
|
assert(id < m_nodes);
|
|
|
|
assert(network_num < m_virtual_networks);
|
2009-05-11 19:38:43 +02:00
|
|
|
|
2010-04-01 01:56:45 +02:00
|
|
|
if (ordered) {
|
|
|
|
m_ordered[network_num] = true;
|
|
|
|
}
|
|
|
|
m_in_use[network_num] = true;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2014-09-01 23:55:47 +02:00
|
|
|
void
|
|
|
|
SimpleNetwork::setToNetQueue(NodeID id, bool ordered, int network_num,
|
|
|
|
std::string vnet_type, MessageBuffer *b)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-04-01 01:56:45 +02:00
|
|
|
checkNetworkAllocation(id, ordered, network_num);
|
2014-09-15 23:19:38 +02:00
|
|
|
while (m_toNetQueues[id].size() <= network_num) {
|
|
|
|
m_toNetQueues[id].push_back(nullptr);
|
|
|
|
}
|
2014-09-01 23:55:47 +02:00
|
|
|
m_toNetQueues[id][network_num] = b;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2014-09-01 23:55:47 +02:00
|
|
|
void
|
|
|
|
SimpleNetwork::setFromNetQueue(NodeID id, bool ordered, int network_num,
|
|
|
|
std::string vnet_type, MessageBuffer *b)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-04-01 01:56:45 +02:00
|
|
|
checkNetworkAllocation(id, ordered, network_num);
|
2014-09-15 23:19:38 +02:00
|
|
|
while (m_fromNetQueues[id].size() <= network_num) {
|
|
|
|
m_fromNetQueues[id].push_back(nullptr);
|
|
|
|
}
|
2014-09-01 23:55:47 +02:00
|
|
|
m_fromNetQueues[id][network_num] = b;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-04-01 01:56:45 +02:00
|
|
|
void
|
2013-09-06 23:21:35 +02:00
|
|
|
SimpleNetwork::regStats()
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2013-09-06 23:21:35 +02:00
|
|
|
for (MessageSizeType type = MessageSizeType_FIRST;
|
|
|
|
type < MessageSizeType_NUM; ++type) {
|
|
|
|
m_msg_counts[(unsigned int) type]
|
|
|
|
.name(name() + ".msg_count." + MessageSizeType_to_string(type))
|
|
|
|
.flags(Stats::nozero)
|
|
|
|
;
|
|
|
|
m_msg_bytes[(unsigned int) type]
|
|
|
|
.name(name() + ".msg_byte." + MessageSizeType_to_string(type))
|
|
|
|
.flags(Stats::nozero)
|
|
|
|
;
|
|
|
|
|
|
|
|
// Now state what the formula is.
|
|
|
|
for (int i = 0; i < m_switches.size(); i++) {
|
|
|
|
m_msg_counts[(unsigned int) type] +=
|
|
|
|
sum(m_switches[i]->getMsgCount(type));
|
2010-08-20 20:46:12 +02:00
|
|
|
}
|
2013-09-06 23:21:35 +02:00
|
|
|
|
|
|
|
m_msg_bytes[(unsigned int) type] =
|
|
|
|
m_msg_counts[(unsigned int) type] * Stats::constant(
|
|
|
|
Network::MessageSizeType_to_int(type));
|
2010-04-01 01:56:45 +02:00
|
|
|
}
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-04-01 01:56:45 +02:00
|
|
|
void
|
2013-09-06 23:21:35 +02:00
|
|
|
SimpleNetwork::collateStats()
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2013-09-06 23:21:29 +02:00
|
|
|
for (int i = 0; i < m_switches.size(); i++) {
|
2013-09-06 23:21:35 +02:00
|
|
|
m_switches[i]->collateStats();
|
2010-04-01 01:56:45 +02:00
|
|
|
}
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-04-01 01:56:45 +02:00
|
|
|
void
|
|
|
|
SimpleNetwork::print(ostream& out) const
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-04-01 01:56:45 +02:00
|
|
|
out << "[SimpleNetwork]";
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
2010-01-30 05:29:17 +01:00
|
|
|
|
|
|
|
SimpleNetwork *
|
|
|
|
SimpleNetworkParams::create()
|
|
|
|
{
|
|
|
|
return new SimpleNetwork(this);
|
|
|
|
}
|
2012-10-16 00:51:57 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The simple network has an array of switches. These switches have buffers
|
|
|
|
* that need to be accessed for functional reads and writes. Also the links
|
|
|
|
* between different switches have buffers that need to be accessed.
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
SimpleNetwork::functionalRead(Packet *pkt)
|
|
|
|
{
|
2013-09-06 23:21:29 +02:00
|
|
|
for (unsigned int i = 0; i < m_switches.size(); i++) {
|
|
|
|
if (m_switches[i]->functionalRead(pkt)) {
|
2012-10-16 00:51:57 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) {
|
|
|
|
if (m_buffers_to_free[i]->functionalRead(pkt)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
SimpleNetwork::functionalWrite(Packet *pkt)
|
|
|
|
{
|
|
|
|
uint32_t num_functional_writes = 0;
|
|
|
|
|
2013-09-06 23:21:29 +02:00
|
|
|
for (unsigned int i = 0; i < m_switches.size(); i++) {
|
|
|
|
num_functional_writes += m_switches[i]->functionalWrite(pkt);
|
2012-10-16 00:51:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) {
|
|
|
|
num_functional_writes += m_buffers_to_free[i]->functionalWrite(pkt);
|
|
|
|
}
|
|
|
|
return num_functional_writes;
|
|
|
|
}
|